summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
committerIgor Pashev <pashev.igor@gmail.com>2012-06-24 22:28:35 +0000
commit3950ffe2a485479f6561c27364d3d7df5a21d124 (patch)
tree468c6e14449d1b1e279222ec32f676b0311917d2
downloadksh-3950ffe2a485479f6561c27364d3d7df5a21d124.tar.gz
Imported Upstream version 93u+upstream
-rw-r--r--README29
-rwxr-xr-xbin/ignore24
-rwxr-xr-xbin/mamprobe248
-rwxr-xr-xbin/package7284
-rwxr-xr-xbin/silent23
-rw-r--r--lib/package/INIT.README1013
-rw-r--r--lib/package/INIT.html991
-rw-r--r--lib/package/INIT.pkg12
-rw-r--r--lib/package/INIT.req0
-rw-r--r--lib/package/INIT.ver1
-rw-r--r--lib/package/LICENSES/epl221
-rw-r--r--lib/package/ast-ksh.README5212
-rw-r--r--lib/package/ast-ksh.html5346
-rw-r--r--lib/package/ast-ksh.pkg89
-rw-r--r--lib/package/ast-ksh.req0
-rw-r--r--lib/package/ast-ksh.ver1
-rw-r--r--lib/package/ast.def47
-rw-r--r--lib/package/ast.lic5
-rw-r--r--lib/package/epl.def8
-rw-r--r--lib/package/ksh.pkg14
-rw-r--r--lib/package/ksh.req0
-rw-r--r--lib/package/ksh.ver1
-rw-r--r--lib/package/package.mk1537
-rw-r--r--src/Makefile1
-rw-r--r--src/Mamfile7
-rw-r--r--src/cmd/INIT/C+probe870
-rw-r--r--src/cmd/INIT/CONVERT.mk260
-rw-r--r--src/cmd/INIT/MAPLIB.mk45
-rw-r--r--src/cmd/INIT/MSGFUN.mk2
-rw-r--r--src/cmd/INIT/MSGKEY.mk2
-rw-r--r--src/cmd/INIT/Makefile293
-rw-r--r--src/cmd/INIT/Mamfile1332
-rw-r--r--src/cmd/INIT/PROBE.mk13
-rw-r--r--src/cmd/INIT/RELEASE918
-rw-r--r--src/cmd/INIT/TEST.mk197
-rw-r--r--src/cmd/INIT/WWW.mk450
-rwxr-xr-xsrc/cmd/INIT/ar.ibm.risc9
-rwxr-xr-xsrc/cmd/INIT/cc.darwin73
-rwxr-xr-xsrc/cmd/INIT/cc.darwin.i38673
-rwxr-xr-xsrc/cmd/INIT/cc.darwin.i386-6473
-rwxr-xr-xsrc/cmd/INIT/cc.hp.ia6413
-rwxr-xr-xsrc/cmd/INIT/cc.hp.pa13
-rwxr-xr-xsrc/cmd/INIT/cc.hp.pa6411
-rwxr-xr-xsrc/cmd/INIT/cc.ibm.risc63
-rwxr-xr-xsrc/cmd/INIT/cc.ibm.risc.gcc36
-rwxr-xr-xsrc/cmd/INIT/cc.linux.i386-64-icc22
-rwxr-xr-xsrc/cmd/INIT/cc.linux.i386-icc22
-rwxr-xr-xsrc/cmd/INIT/cc.linux.ia64-icc22
-rwxr-xr-xsrc/cmd/INIT/cc.lynxos.i38681
-rwxr-xr-xsrc/cmd/INIT/cc.lynxos.ppc85
-rwxr-xr-xsrc/cmd/INIT/cc.mvs.390279
-rwxr-xr-xsrc/cmd/INIT/cc.next.i386158
-rwxr-xr-xsrc/cmd/INIT/cc.next.m68k9
-rwxr-xr-xsrc/cmd/INIT/cc.osf.alpha9
-rwxr-xr-xsrc/cmd/INIT/cc.pentium426
-rwxr-xr-xsrc/cmd/INIT/cc.sco.i3869
-rwxr-xr-xsrc/cmd/INIT/cc.sgi.mips268
-rwxr-xr-xsrc/cmd/INIT/cc.sgi.mips3110
-rwxr-xr-xsrc/cmd/INIT/cc.sgi.mips3-o3265
-rwxr-xr-xsrc/cmd/INIT/cc.sgi.mips490
-rwxr-xr-xsrc/cmd/INIT/cc.sgi.mips4-n3265
-rwxr-xr-xsrc/cmd/INIT/cc.specialize35
-rwxr-xr-xsrc/cmd/INIT/cc.unix.mc68k76
-rw-r--r--src/cmd/INIT/crossexec.sh139
-rw-r--r--src/cmd/INIT/db.c37
-rw-r--r--src/cmd/INIT/ditto.sh460
-rw-r--r--src/cmd/INIT/dl.c33
-rw-r--r--src/cmd/INIT/execrate.sh179
-rw-r--r--src/cmd/INIT/filter.sh98
-rw-r--r--src/cmd/INIT/gdbm.c37
-rw-r--r--src/cmd/INIT/gdbm1.c37
-rw-r--r--src/cmd/INIT/gdbm2.c37
-rwxr-xr-xsrc/cmd/INIT/hello.c23
-rw-r--r--src/cmd/INIT/hosttype.tst6
-rw-r--r--src/cmd/INIT/hurl.sh207
-rw-r--r--src/cmd/INIT/iconv.c29
-rw-r--r--src/cmd/INIT/iffe.sh4639
-rw-r--r--src/cmd/INIT/iffe.tst1943
-rw-r--r--src/cmd/INIT/ignore.sh43
-rw-r--r--src/cmd/INIT/intl.c29
-rwxr-xr-xsrc/cmd/INIT/ld.hp.pa5
-rwxr-xr-xsrc/cmd/INIT/ldd.cygwin.i38622
-rwxr-xr-xsrc/cmd/INIT/ldd.darwin2
-rwxr-xr-xsrc/cmd/INIT/ldd.hp.pa21
-rwxr-xr-xsrc/cmd/INIT/ldd.ibm.risc16
-rwxr-xr-xsrc/cmd/INIT/ldd.lynxos1
-rwxr-xr-xsrc/cmd/INIT/ldd.mvs.39018
-rwxr-xr-xsrc/cmd/INIT/ldd.sgi2
-rw-r--r--src/cmd/INIT/m.c34
-rw-r--r--src/cmd/INIT/m2.c36
-rw-r--r--src/cmd/INIT/m3.c36
-rw-r--r--src/cmd/INIT/m4.c32
-rw-r--r--src/cmd/INIT/m5.c32
-rw-r--r--src/cmd/INIT/m6.c34
-rw-r--r--src/cmd/INIT/make.probe2242
-rw-r--r--src/cmd/INIT/mamake.c2375
-rw-r--r--src/cmd/INIT/mamake.rt40
-rw-r--r--src/cmd/INIT/mamake.tst63
-rw-r--r--src/cmd/INIT/mamprobe.sh267
-rw-r--r--src/cmd/INIT/mkdir.sh80
-rwxr-xr-xsrc/cmd/INIT/mktest.sh641
-rw-r--r--src/cmd/INIT/mprobe.sh30
-rw-r--r--src/cmd/INIT/nsl.c31
-rw-r--r--src/cmd/INIT/p.c24
-rw-r--r--src/cmd/INIT/package.mk1537
-rw-r--r--src/cmd/INIT/package.sh7302
-rw-r--r--src/cmd/INIT/probe.win32283
-rw-r--r--src/cmd/INIT/proto.c5283
-rw-r--r--src/cmd/INIT/ratz.c5293
-rw-r--r--src/cmd/INIT/regress.sh1463
-rw-r--r--src/cmd/INIT/release.c366
-rw-r--r--src/cmd/INIT/rt.sh479
-rw-r--r--src/cmd/INIT/silent.sh42
-rw-r--r--src/cmd/INIT/socket.c33
-rw-r--r--src/cmd/INIT/w.c30
-rw-r--r--src/cmd/INIT/w2.c27
-rw-r--r--src/cmd/Makefile1
-rw-r--r--src/cmd/Mamfile7
-rw-r--r--src/cmd/ksh93/COMPATIBILITY136
-rw-r--r--src/cmd/ksh93/DESIGN170
-rw-r--r--src/cmd/ksh93/Makefile248
-rw-r--r--src/cmd/ksh93/Mamfile1527
-rw-r--r--src/cmd/ksh93/OBSOLETE152
-rw-r--r--src/cmd/ksh93/PROMO.mm141
-rw-r--r--src/cmd/ksh93/README232
-rw-r--r--src/cmd/ksh93/RELEASE2888
-rw-r--r--src/cmd/ksh93/RELEASE88422
-rw-r--r--src/cmd/ksh93/RELEASE93455
-rw-r--r--src/cmd/ksh93/TYPES182
-rw-r--r--src/cmd/ksh93/bltins/alarm.c276
-rw-r--r--src/cmd/ksh93/bltins/cd_pwd.c250
-rw-r--r--src/cmd/ksh93/bltins/cflow.c117
-rw-r--r--src/cmd/ksh93/bltins/enum.c284
-rw-r--r--src/cmd/ksh93/bltins/getopts.c199
-rw-r--r--src/cmd/ksh93/bltins/hist.c312
-rw-r--r--src/cmd/ksh93/bltins/misc.c590
-rw-r--r--src/cmd/ksh93/bltins/mkservice.c494
-rw-r--r--src/cmd/ksh93/bltins/print.c1058
-rw-r--r--src/cmd/ksh93/bltins/read.c802
-rw-r--r--src/cmd/ksh93/bltins/regress.c343
-rw-r--r--src/cmd/ksh93/bltins/sleep.c235
-rw-r--r--src/cmd/ksh93/bltins/test.c667
-rw-r--r--src/cmd/ksh93/bltins/trap.c420
-rw-r--r--src/cmd/ksh93/bltins/typeset.c1471
-rw-r--r--src/cmd/ksh93/bltins/ulimit.c216
-rw-r--r--src/cmd/ksh93/bltins/umask.c98
-rw-r--r--src/cmd/ksh93/bltins/whence.c294
-rw-r--r--src/cmd/ksh93/builtins.mm648
-rw-r--r--src/cmd/ksh93/data/aliases.c57
-rw-r--r--src/cmd/ksh93/data/bash_pre_rc.sh255
-rw-r--r--src/cmd/ksh93/data/builtins.c1902
-rw-r--r--src/cmd/ksh93/data/keywords.c62
-rw-r--r--src/cmd/ksh93/data/lexstates.c417
-rw-r--r--src/cmd/ksh93/data/limits.c62
-rw-r--r--src/cmd/ksh93/data/math.tab75
-rw-r--r--src/cmd/ksh93/data/msg.c215
-rw-r--r--src/cmd/ksh93/data/options.c149
-rw-r--r--src/cmd/ksh93/data/signals.c244
-rw-r--r--src/cmd/ksh93/data/strdata.c104
-rw-r--r--src/cmd/ksh93/data/testops.c174
-rw-r--r--src/cmd/ksh93/data/variables.c136
-rw-r--r--src/cmd/ksh93/edit/completion.c572
-rw-r--r--src/cmd/ksh93/edit/edit.c1806
-rw-r--r--src/cmd/ksh93/edit/emacs.c1571
-rw-r--r--src/cmd/ksh93/edit/hexpand.c734
-rw-r--r--src/cmd/ksh93/edit/history.c1222
-rw-r--r--src/cmd/ksh93/edit/vi.c2753
-rw-r--r--src/cmd/ksh93/features/cmds4
-rw-r--r--src/cmd/ksh93/features/dynamic12
-rw-r--r--src/cmd/ksh93/features/externs13
-rw-r--r--src/cmd/ksh93/features/locale27
-rw-r--r--src/cmd/ksh93/features/math.sh305
-rwxr-xr-xsrc/cmd/ksh93/features/options47
-rw-r--r--src/cmd/ksh93/features/poll157
-rw-r--r--src/cmd/ksh93/features/rlimits3
-rw-r--r--src/cmd/ksh93/features/setjmp18
-rw-r--r--src/cmd/ksh93/features/sigfeatures49
-rw-r--r--src/cmd/ksh93/features/time35
-rw-r--r--src/cmd/ksh93/features/ttys3
-rwxr-xr-xsrc/cmd/ksh93/fun/dirs108
-rwxr-xr-xsrc/cmd/ksh93/fun/popd111
-rwxr-xr-xsrc/cmd/ksh93/fun/pushd111
-rw-r--r--src/cmd/ksh93/include/argnod.h145
-rw-r--r--src/cmd/ksh93/include/builtins.h202
-rw-r--r--src/cmd/ksh93/include/defs.h509
-rw-r--r--src/cmd/ksh93/include/edit.h286
-rw-r--r--src/cmd/ksh93/include/env.h50
-rw-r--r--src/cmd/ksh93/include/fault.h127
-rw-r--r--src/cmd/ksh93/include/fcin.h71
-rw-r--r--src/cmd/ksh93/include/history.h75
-rw-r--r--src/cmd/ksh93/include/io.h126
-rw-r--r--src/cmd/ksh93/include/jobs.h216
-rw-r--r--src/cmd/ksh93/include/lexstates.h157
-rw-r--r--src/cmd/ksh93/include/name.h268
-rw-r--r--src/cmd/ksh93/include/national.h37
-rw-r--r--src/cmd/ksh93/include/nval.h311
-rw-r--r--src/cmd/ksh93/include/path.h147
-rw-r--r--src/cmd/ksh93/include/regress.h66
-rw-r--r--src/cmd/ksh93/include/shell.h259
-rw-r--r--src/cmd/ksh93/include/shlex.h171
-rw-r--r--src/cmd/ksh93/include/shnodes.h221
-rw-r--r--src/cmd/ksh93/include/shtable.h65
-rw-r--r--src/cmd/ksh93/include/streval.h207
-rw-r--r--src/cmd/ksh93/include/terminal.h195
-rw-r--r--src/cmd/ksh93/include/test.h72
-rw-r--r--src/cmd/ksh93/include/timeout.h30
-rw-r--r--src/cmd/ksh93/include/ulimit.h174
-rw-r--r--src/cmd/ksh93/include/variables.h111
-rw-r--r--src/cmd/ksh93/include/version.h20
-rw-r--r--src/cmd/ksh93/ksh-regress.rt71
-rw-r--r--src/cmd/ksh93/ksh-regress.tst22544
-rwxr-xr-xsrc/cmd/ksh93/mamexec307
-rw-r--r--src/cmd/ksh93/mamstate.c73
-rw-r--r--src/cmd/ksh93/nval.3688
-rw-r--r--src/cmd/ksh93/sh.18142
-rw-r--r--src/cmd/ksh93/sh.memo3248
-rw-r--r--src/cmd/ksh93/sh/args.c892
-rw-r--r--src/cmd/ksh93/sh/arith.c549
-rw-r--r--src/cmd/ksh93/sh/array.c1843
-rw-r--r--src/cmd/ksh93/sh/bash.c423
-rw-r--r--src/cmd/ksh93/sh/defs.c48
-rw-r--r--src/cmd/ksh93/sh/deparse.c603
-rw-r--r--src/cmd/ksh93/sh/env.c255
-rw-r--r--src/cmd/ksh93/sh/expand.c468
-rw-r--r--src/cmd/ksh93/sh/fault.c672
-rw-r--r--src/cmd/ksh93/sh/fcin.c214
-rw-r--r--src/cmd/ksh93/sh/init.c2238
-rw-r--r--src/cmd/ksh93/sh/io.c2647
-rw-r--r--src/cmd/ksh93/sh/jobs.c2055
-rw-r--r--src/cmd/ksh93/sh/lex.c2516
-rw-r--r--src/cmd/ksh93/sh/macro.c2814
-rw-r--r--src/cmd/ksh93/sh/main.c787
-rw-r--r--src/cmd/ksh93/sh/name.c3684
-rw-r--r--src/cmd/ksh93/sh/nvdisc.c1468
-rw-r--r--src/cmd/ksh93/sh/nvtree.c1161
-rw-r--r--src/cmd/ksh93/sh/nvtype.c1709
-rw-r--r--src/cmd/ksh93/sh/parse.c2082
-rw-r--r--src/cmd/ksh93/sh/path.c1824
-rw-r--r--src/cmd/ksh93/sh/pmain.c46
-rw-r--r--src/cmd/ksh93/sh/shcomp.c177
-rw-r--r--src/cmd/ksh93/sh/streval.c1023
-rw-r--r--src/cmd/ksh93/sh/string.c730
-rw-r--r--src/cmd/ksh93/sh/subshell.c780
-rw-r--r--src/cmd/ksh93/sh/suid_exec.c509
-rw-r--r--src/cmd/ksh93/sh/tdump.c262
-rw-r--r--src/cmd/ksh93/sh/timers.c248
-rw-r--r--src/cmd/ksh93/sh/trestore.c353
-rw-r--r--src/cmd/ksh93/sh/waitevent.c54
-rw-r--r--src/cmd/ksh93/sh/xec.c3991
-rw-r--r--src/cmd/ksh93/shell.3414
-rwxr-xr-xsrc/cmd/ksh93/tests/alias.sh102
-rwxr-xr-xsrc/cmd/ksh93/tests/append.sh86
-rwxr-xr-xsrc/cmd/ksh93/tests/arith.sh737
-rwxr-xr-xsrc/cmd/ksh93/tests/arrays.sh588
-rwxr-xr-xsrc/cmd/ksh93/tests/arrays2.sh212
-rwxr-xr-xsrc/cmd/ksh93/tests/attributes.sh418
-rwxr-xr-xsrc/cmd/ksh93/tests/basic.sh513
-rwxr-xr-xsrc/cmd/ksh93/tests/bracket.sh340
-rwxr-xr-xsrc/cmd/ksh93/tests/builtins.sh562
-rwxr-xr-xsrc/cmd/ksh93/tests/case.sh85
-rwxr-xr-xsrc/cmd/ksh93/tests/comvar.sh689
-rw-r--r--src/cmd/ksh93/tests/comvario.sh686
-rwxr-xr-xsrc/cmd/ksh93/tests/coprocess.sh360
-rwxr-xr-xsrc/cmd/ksh93/tests/cubetype.sh213
-rwxr-xr-xsrc/cmd/ksh93/tests/enum.sh68
-rwxr-xr-xsrc/cmd/ksh93/tests/exit.sh80
-rwxr-xr-xsrc/cmd/ksh93/tests/expand.sh126
-rwxr-xr-xsrc/cmd/ksh93/tests/functions.sh1157
-rwxr-xr-xsrc/cmd/ksh93/tests/glob.sh374
-rwxr-xr-xsrc/cmd/ksh93/tests/grep.sh105
-rwxr-xr-xsrc/cmd/ksh93/tests/heredoc.sh496
-rwxr-xr-xsrc/cmd/ksh93/tests/io.sh484
-rwxr-xr-xsrc/cmd/ksh93/tests/leaks.sh68
-rwxr-xr-xsrc/cmd/ksh93/tests/locale.sh319
-rw-r--r--src/cmd/ksh93/tests/math.sh202
-rwxr-xr-xsrc/cmd/ksh93/tests/nameref.sh658
-rwxr-xr-xsrc/cmd/ksh93/tests/options.sh544
-rwxr-xr-xsrc/cmd/ksh93/tests/path.sh375
-rwxr-xr-xsrc/cmd/ksh93/tests/pointtype.sh138
-rwxr-xr-xsrc/cmd/ksh93/tests/pty.sh442
-rwxr-xr-xsrc/cmd/ksh93/tests/quoting.sh369
-rwxr-xr-xsrc/cmd/ksh93/tests/quoting2.sh215
-rw-r--r--src/cmd/ksh93/tests/readcsv.sh65
-rwxr-xr-xsrc/cmd/ksh93/tests/recttype.sh70
-rwxr-xr-xsrc/cmd/ksh93/tests/restricted.sh83
-rwxr-xr-xsrc/cmd/ksh93/tests/return.sh183
-rwxr-xr-xsrc/cmd/ksh93/tests/select.sh67
-rwxr-xr-xsrc/cmd/ksh93/tests/shtests235
-rwxr-xr-xsrc/cmd/ksh93/tests/sigchld.sh160
-rwxr-xr-xsrc/cmd/ksh93/tests/signal.sh435
-rwxr-xr-xsrc/cmd/ksh93/tests/statics.sh690
-rwxr-xr-xsrc/cmd/ksh93/tests/subshell.sh582
-rwxr-xr-xsrc/cmd/ksh93/tests/substring.sh628
-rwxr-xr-xsrc/cmd/ksh93/tests/tilde.sh101
-rwxr-xr-xsrc/cmd/ksh93/tests/timetype.sh81
-rwxr-xr-xsrc/cmd/ksh93/tests/treemove.sh163
-rwxr-xr-xsrc/cmd/ksh93/tests/types.sh632
-rwxr-xr-xsrc/cmd/ksh93/tests/variables.sh665
-rwxr-xr-xsrc/cmd/ksh93/tests/vartree1.sh215
-rwxr-xr-xsrc/cmd/ksh93/tests/vartree2.sh335
-rw-r--r--src/lib/Makefile1
-rw-r--r--src/lib/Mamfile7
-rw-r--r--src/lib/libast/Makefile442
-rw-r--r--src/lib/libast/Mamfile7356
-rw-r--r--src/lib/libast/README95
-rw-r--r--src/lib/libast/RELEASE1769
-rw-r--r--src/lib/libast/aso/aso-fcntl.c188
-rw-r--r--src/lib/libast/aso/aso-sem.c193
-rw-r--r--src/lib/libast/aso/aso.c866
-rw-r--r--src/lib/libast/aso/asohdr.h71
-rw-r--r--src/lib/libast/aso/asolock.c55
-rw-r--r--src/lib/libast/aso/asometh.c43
-rw-r--r--src/lib/libast/aso/asorelax.c56
-rw-r--r--src/lib/libast/astsa/README-astsa15
-rw-r--r--src/lib/libast/astsa/aso.c56
-rw-r--r--src/lib/libast/astsa/aso.h32
-rw-r--r--src/lib/libast/astsa/ast.c85
-rw-r--r--src/lib/libast/astsa/ast.h156
-rw-r--r--src/lib/libast/astsa/ast_common.h49
-rw-r--r--src/lib/libast/astsa/astsa.manifest50
-rw-r--r--src/lib/libast/astsa/astsa.mm33
-rw-r--r--src/lib/libast/astsa/astsa.omk82
-rw-r--r--src/lib/libast/astsa/ccode.h34
-rw-r--r--src/lib/libast/astsa/debug.h29
-rw-r--r--src/lib/libast/astsa/error.c103
-rw-r--r--src/lib/libast/astsa/error.h66
-rw-r--r--src/lib/libast/astsa/hashkey.h61
-rwxr-xr-xsrc/lib/libast/astsa/mkast_sa150
-rw-r--r--src/lib/libast/astsa/option.h106
-rw-r--r--src/lib/libast/astsa/optlib.h105
-rw-r--r--src/lib/libast/astsa/sfstr.c246
-rw-r--r--src/lib/libast/astsa/sfstr.h60
-rw-r--r--src/lib/libast/astsa/strdup.c37
-rw-r--r--src/lib/libast/astsa/strmatch.c597
-rw-r--r--src/lib/libast/astsa/times.h27
-rw-r--r--src/lib/libast/astsa/vmalloc.c102
-rw-r--r--src/lib/libast/astsa/vmalloc.h61
-rw-r--r--src/lib/libast/cdt/cdtlib.h183
-rw-r--r--src/lib/libast/cdt/dtclose.c66
-rw-r--r--src/lib/libast/cdt/dtcomp.c60
-rw-r--r--src/lib/libast/cdt/dtdisc.c91
-rw-r--r--src/lib/libast/cdt/dthash.c431
-rw-r--r--src/lib/libast/cdt/dthdr.h37
-rw-r--r--src/lib/libast/cdt/dtlist.c387
-rw-r--r--src/lib/libast/cdt/dtmethod.c107
-rw-r--r--src/lib/libast/cdt/dtnew.c81
-rw-r--r--src/lib/libast/cdt/dtopen.c177
-rw-r--r--src/lib/libast/cdt/dtstrhash.c61
-rw-r--r--src/lib/libast/cdt/dttree.c696
-rw-r--r--src/lib/libast/cdt/dtview.c157
-rw-r--r--src/lib/libast/cdt/dtwalk.c53
-rw-r--r--src/lib/libast/comp/atexit.c115
-rw-r--r--src/lib/libast/comp/basename.c55
-rw-r--r--src/lib/libast/comp/catopen.c182
-rw-r--r--src/lib/libast/comp/closelog.c51
-rw-r--r--src/lib/libast/comp/conf.sh1635
-rw-r--r--src/lib/libast/comp/conf.tab601
-rw-r--r--src/lib/libast/comp/creat64.c38
-rw-r--r--src/lib/libast/comp/dirname.c61
-rw-r--r--src/lib/libast/comp/dup2.c46
-rw-r--r--src/lib/libast/comp/eaccess.c139
-rw-r--r--src/lib/libast/comp/errno.c40
-rw-r--r--src/lib/libast/comp/execlp.c50
-rw-r--r--src/lib/libast/comp/execve.c70
-rw-r--r--src/lib/libast/comp/execvp.c50
-rw-r--r--src/lib/libast/comp/execvpe.c78
-rw-r--r--src/lib/libast/comp/fakelink.h34
-rw-r--r--src/lib/libast/comp/fcntl.c98
-rw-r--r--src/lib/libast/comp/fmtmsg.h141
-rw-r--r--src/lib/libast/comp/fmtmsglib.c335
-rw-r--r--src/lib/libast/comp/fnmatch.c79
-rw-r--r--src/lib/libast/comp/fnmatch.h61
-rw-r--r--src/lib/libast/comp/frexp.c153
-rw-r--r--src/lib/libast/comp/frexpl.c161
-rw-r--r--src/lib/libast/comp/fsync.c46
-rw-r--r--src/lib/libast/comp/ftw.c50
-rw-r--r--src/lib/libast/comp/ftw.h60
-rw-r--r--src/lib/libast/comp/getdate.c83
-rw-r--r--src/lib/libast/comp/getgroups.c78
-rw-r--r--src/lib/libast/comp/getlogin.c42
-rw-r--r--src/lib/libast/comp/getopt.c78
-rw-r--r--src/lib/libast/comp/getopt.h51
-rw-r--r--src/lib/libast/comp/getoptl.c151
-rw-r--r--src/lib/libast/comp/getpgrp.c47
-rw-r--r--src/lib/libast/comp/getsubopt.c84
-rw-r--r--src/lib/libast/comp/getwd.c37
-rw-r--r--src/lib/libast/comp/gross.c99
-rw-r--r--src/lib/libast/comp/gross_sgi.h188
-rw-r--r--src/lib/libast/comp/hsearch.c138
-rw-r--r--src/lib/libast/comp/iconv.c1599
-rw-r--r--src/lib/libast/comp/killpg.c40
-rw-r--r--src/lib/libast/comp/libgen.h52
-rw-r--r--src/lib/libast/comp/link.c47
-rw-r--r--src/lib/libast/comp/localeconv.c100
-rw-r--r--src/lib/libast/comp/lstat.c39
-rw-r--r--src/lib/libast/comp/memccpy.c51
-rw-r--r--src/lib/libast/comp/memchr.c49
-rw-r--r--src/lib/libast/comp/memcmp.c45
-rw-r--r--src/lib/libast/comp/memcpy.c60
-rw-r--r--src/lib/libast/comp/memmove.c53
-rw-r--r--src/lib/libast/comp/memset.c42
-rw-r--r--src/lib/libast/comp/mkdir.c62
-rw-r--r--src/lib/libast/comp/mkfifo.c50
-rw-r--r--src/lib/libast/comp/mknod.c50
-rw-r--r--src/lib/libast/comp/mktemp.c85
-rw-r--r--src/lib/libast/comp/mktime.c77
-rw-r--r--src/lib/libast/comp/mount.c49
-rw-r--r--src/lib/libast/comp/nftw.c61
-rw-r--r--src/lib/libast/comp/omitted.c1152
-rw-r--r--src/lib/libast/comp/open.c119
-rw-r--r--src/lib/libast/comp/openlog.c58
-rw-r--r--src/lib/libast/comp/putenv.c53
-rw-r--r--src/lib/libast/comp/re_comp.c81
-rw-r--r--src/lib/libast/comp/re_comp.h41
-rw-r--r--src/lib/libast/comp/readlink.c61
-rw-r--r--src/lib/libast/comp/realpath.c48
-rw-r--r--src/lib/libast/comp/regcmp.c224
-rw-r--r--src/lib/libast/comp/regexp.c123
-rw-r--r--src/lib/libast/comp/regexp.h129
-rw-r--r--src/lib/libast/comp/remove.c49
-rw-r--r--src/lib/libast/comp/rename.c98
-rw-r--r--src/lib/libast/comp/resolvepath.c72
-rw-r--r--src/lib/libast/comp/rmdir.c66
-rw-r--r--src/lib/libast/comp/setenv.c58
-rw-r--r--src/lib/libast/comp/setlocale.c2865
-rw-r--r--src/lib/libast/comp/setlogmask.c48
-rw-r--r--src/lib/libast/comp/setpgid.c80
-rw-r--r--src/lib/libast/comp/setsid.c90
-rw-r--r--src/lib/libast/comp/sigflag.c52
-rw-r--r--src/lib/libast/comp/sigunblock.c63
-rw-r--r--src/lib/libast/comp/spawnveg.c296
-rw-r--r--src/lib/libast/comp/statvfs.c163
-rw-r--r--src/lib/libast/comp/strcasecmp.c58
-rw-r--r--src/lib/libast/comp/strchr.c57
-rw-r--r--src/lib/libast/comp/strftime.c104
-rw-r--r--src/lib/libast/comp/strncasecmp.c62
-rw-r--r--src/lib/libast/comp/strptime.c82
-rw-r--r--src/lib/libast/comp/strrchr.c60
-rw-r--r--src/lib/libast/comp/strstr.c76
-rw-r--r--src/lib/libast/comp/strtod.c31
-rw-r--r--src/lib/libast/comp/strtol.c34
-rw-r--r--src/lib/libast/comp/strtold.c50
-rw-r--r--src/lib/libast/comp/strtoll.c44
-rw-r--r--src/lib/libast/comp/strtoul.c35
-rw-r--r--src/lib/libast/comp/strtoull.c45
-rw-r--r--src/lib/libast/comp/swab.c60
-rw-r--r--src/lib/libast/comp/symlink.c59
-rw-r--r--src/lib/libast/comp/syslog.c367
-rw-r--r--src/lib/libast/comp/syslog.h132
-rw-r--r--src/lib/libast/comp/sysloglib.h54
-rw-r--r--src/lib/libast/comp/system.c55
-rw-r--r--src/lib/libast/comp/tempnam.c58
-rw-r--r--src/lib/libast/comp/tmpnam.c51
-rw-r--r--src/lib/libast/comp/transition.c86
-rw-r--r--src/lib/libast/comp/tsearch.c240
-rw-r--r--src/lib/libast/comp/unlink.c38
-rw-r--r--src/lib/libast/comp/unsetenv.c50
-rw-r--r--src/lib/libast/comp/vfork.c55
-rw-r--r--src/lib/libast/comp/waitpid.c199
-rw-r--r--src/lib/libast/comp/wc.c139
-rw-r--r--src/lib/libast/comp/wordexp.c217
-rw-r--r--src/lib/libast/comp/wordexp.h63
-rw-r--r--src/lib/libast/dir/dirlib.h174
-rw-r--r--src/lib/libast/dir/dirstd.h63
-rw-r--r--src/lib/libast/dir/getdents.c166
-rw-r--r--src/lib/libast/dir/opendir.c95
-rw-r--r--src/lib/libast/dir/readdir.c61
-rw-r--r--src/lib/libast/dir/rewinddir.c46
-rw-r--r--src/lib/libast/dir/seekdir.c56
-rw-r--r--src/lib/libast/dir/telldir.c43
-rw-r--r--src/lib/libast/disc/memfatal.c82
-rw-r--r--src/lib/libast/disc/sfdcdio.c229
-rw-r--r--src/lib/libast/disc/sfdcdos.c416
-rw-r--r--src/lib/libast/disc/sfdcfilter.c186
-rw-r--r--src/lib/libast/disc/sfdchdr.h28
-rw-r--r--src/lib/libast/disc/sfdcmore.c369
-rw-r--r--src/lib/libast/disc/sfdcprefix.c153
-rw-r--r--src/lib/libast/disc/sfdcseekable.c227
-rw-r--r--src/lib/libast/disc/sfdcslow.c84
-rw-r--r--src/lib/libast/disc/sfdcsubstr.c217
-rw-r--r--src/lib/libast/disc/sfdctee.c102
-rw-r--r--src/lib/libast/disc/sfdcunion.c203
-rw-r--r--src/lib/libast/disc/sfkeyprintf.c392
-rw-r--r--src/lib/libast/disc/sfstrtmp.c62
-rw-r--r--src/lib/libast/features/align.c188
-rw-r--r--src/lib/libast/features/api11
-rw-r--r--src/lib/libast/features/aso671
-rw-r--r--src/lib/libast/features/botch.c72
-rw-r--r--src/lib/libast/features/ccode81
-rw-r--r--src/lib/libast/features/common624
-rw-r--r--src/lib/libast/features/dirent275
-rw-r--r--src/lib/libast/features/eaccess11
-rw-r--r--src/lib/libast/features/errno31
-rw-r--r--src/lib/libast/features/fcntl.c360
-rw-r--r--src/lib/libast/features/float1191
-rw-r--r--src/lib/libast/features/fs251
-rw-r--r--src/lib/libast/features/hack1
-rw-r--r--src/lib/libast/features/iconv116
-rw-r--r--src/lib/libast/features/isoc9913
-rw-r--r--src/lib/libast/features/lib664
-rw-r--r--src/lib/libast/features/libpath.sh73
-rw-r--r--src/lib/libast/features/limits.c339
-rw-r--r--src/lib/libast/features/locale28
-rw-r--r--src/lib/libast/features/map.c565
-rw-r--r--src/lib/libast/features/mmap342
-rw-r--r--src/lib/libast/features/mode.c218
-rw-r--r--src/lib/libast/features/ndbm29
-rw-r--r--src/lib/libast/features/nl_types64
-rw-r--r--src/lib/libast/features/omitted110
-rw-r--r--src/lib/libast/features/options1
-rw-r--r--src/lib/libast/features/param.sh47
-rw-r--r--src/lib/libast/features/preroot.sh46
-rw-r--r--src/lib/libast/features/prog12
-rw-r--r--src/lib/libast/features/sfinit.c94
-rw-r--r--src/lib/libast/features/sfio170
-rw-r--r--src/lib/libast/features/sig.sh132
-rw-r--r--src/lib/libast/features/siglist14
-rw-r--r--src/lib/libast/features/signal.c371
-rw-r--r--src/lib/libast/features/sizeof13
-rw-r--r--src/lib/libast/features/standards153
-rw-r--r--src/lib/libast/features/stdio568
-rw-r--r--src/lib/libast/features/sys272
-rw-r--r--src/lib/libast/features/syscall18
-rw-r--r--src/lib/libast/features/time46
-rw-r--r--src/lib/libast/features/tmlib45
-rw-r--r--src/lib/libast/features/tmx106
-rw-r--r--src/lib/libast/features/tty127
-rw-r--r--src/lib/libast/features/tv81
-rw-r--r--src/lib/libast/features/tvlib80
-rw-r--r--src/lib/libast/features/uwin10
-rw-r--r--src/lib/libast/features/vfork13
-rw-r--r--src/lib/libast/features/vmalloc220
-rw-r--r--src/lib/libast/features/wait9
-rw-r--r--src/lib/libast/features/wchar158
-rw-r--r--src/lib/libast/features/wctype14
-rw-r--r--src/lib/libast/hash/hashalloc.c200
-rw-r--r--src/lib/libast/hash/hashdump.c173
-rw-r--r--src/lib/libast/hash/hashfree.c144
-rw-r--r--src/lib/libast/hash/hashlast.c43
-rw-r--r--src/lib/libast/hash/hashlib.h104
-rw-r--r--src/lib/libast/hash/hashlook.c367
-rw-r--r--src/lib/libast/hash/hashscan.c139
-rw-r--r--src/lib/libast/hash/hashsize.c84
-rw-r--r--src/lib/libast/hash/hashview.c88
-rw-r--r--src/lib/libast/hash/hashwalk.c51
-rw-r--r--src/lib/libast/hash/memhash.c45
-rw-r--r--src/lib/libast/hash/memsum.c53
-rw-r--r--src/lib/libast/hash/strhash.c45
-rw-r--r--src/lib/libast/hash/strkey.c49
-rw-r--r--src/lib/libast/hash/strsum.c53
-rw-r--r--src/lib/libast/include/aso.h183
-rw-r--r--src/lib/libast/include/ast.h405
-rw-r--r--src/lib/libast/include/ast_dir.h77
-rw-r--r--src/lib/libast/include/ast_getopt.h42
-rw-r--r--src/lib/libast/include/ast_std.h362
-rw-r--r--src/lib/libast/include/ast_windows.h39
-rw-r--r--src/lib/libast/include/ccode.h90
-rw-r--r--src/lib/libast/include/cdt.h354
-rw-r--r--src/lib/libast/include/cmdarg.h92
-rw-r--r--src/lib/libast/include/debug.h109
-rw-r--r--src/lib/libast/include/dt.h41
-rw-r--r--src/lib/libast/include/error.h182
-rw-r--r--src/lib/libast/include/find.h86
-rw-r--r--src/lib/libast/include/fnv.h72
-rw-r--r--src/lib/libast/include/fs3d.h117
-rw-r--r--src/lib/libast/include/fts.h162
-rw-r--r--src/lib/libast/include/ftwalk.h124
-rw-r--r--src/lib/libast/include/glob.h146
-rw-r--r--src/lib/libast/include/hash.h202
-rw-r--r--src/lib/libast/include/hashkey.h62
-rw-r--r--src/lib/libast/include/hashpart.h51
-rw-r--r--src/lib/libast/include/ip6.h40
-rw-r--r--src/lib/libast/include/ls.h88
-rw-r--r--src/lib/libast/include/magic.h86
-rw-r--r--src/lib/libast/include/magicid.h46
-rw-r--r--src/lib/libast/include/mc.h96
-rw-r--r--src/lib/libast/include/mime.h91
-rw-r--r--src/lib/libast/include/mnt.h58
-rw-r--r--src/lib/libast/include/modecanon.h65
-rw-r--r--src/lib/libast/include/modex.h51
-rw-r--r--src/lib/libast/include/namval.h42
-rw-r--r--src/lib/libast/include/option.h106
-rw-r--r--src/lib/libast/include/proc.h108
-rw-r--r--src/lib/libast/include/recfmt.h83
-rw-r--r--src/lib/libast/include/regex.h248
-rw-r--r--src/lib/libast/include/sfdisc.h70
-rw-r--r--src/lib/libast/include/sfio.h457
-rw-r--r--src/lib/libast/include/sfio_s.h51
-rw-r--r--src/lib/libast/include/sfio_t.h126
-rw-r--r--src/lib/libast/include/shcmd.h112
-rw-r--r--src/lib/libast/include/stack.h83
-rw-r--r--src/lib/libast/include/stak.h55
-rw-r--r--src/lib/libast/include/stk.h78
-rw-r--r--src/lib/libast/include/swap.h53
-rw-r--r--src/lib/libast/include/tar.h118
-rw-r--r--src/lib/libast/include/times.h54
-rw-r--r--src/lib/libast/include/tm.h192
-rw-r--r--src/lib/libast/include/tok.h47
-rw-r--r--src/lib/libast/include/usage.h37
-rw-r--r--src/lib/libast/include/vdb.h46
-rw-r--r--src/lib/libast/include/vecargs.h45
-rw-r--r--src/lib/libast/include/vmalloc.h335
-rw-r--r--src/lib/libast/include/wait.h98
-rw-r--r--src/lib/libast/man/LIBAST.398
-rw-r--r--src/lib/libast/man/aso.3355
-rw-r--r--src/lib/libast/man/ast.3283
-rw-r--r--src/lib/libast/man/astsa.3161
-rw-r--r--src/lib/libast/man/cdt.3617
-rw-r--r--src/lib/libast/man/chr.3126
-rw-r--r--src/lib/libast/man/compat.3103
-rw-r--r--src/lib/libast/man/error.3283
-rw-r--r--src/lib/libast/man/find.389
-rw-r--r--src/lib/libast/man/fmt.3213
-rw-r--r--src/lib/libast/man/fmtls.3143
-rw-r--r--src/lib/libast/man/fs3d.392
-rw-r--r--src/lib/libast/man/ftwalk.3235
-rw-r--r--src/lib/libast/man/getcwd.367
-rw-r--r--src/lib/libast/man/hash.3644
-rw-r--r--src/lib/libast/man/iblocks.362
-rw-r--r--src/lib/libast/man/int.368
-rw-r--r--src/lib/libast/man/ip6.385
-rw-r--r--src/lib/libast/man/magic.3493
-rw-r--r--src/lib/libast/man/mem.398
-rw-r--r--src/lib/libast/man/mime.3117
-rw-r--r--src/lib/libast/man/modecanon.3104
-rw-r--r--src/lib/libast/man/optget.368
-rw-r--r--src/lib/libast/man/path.3391
-rw-r--r--src/lib/libast/man/preroot.3151
-rw-r--r--src/lib/libast/man/proc.3319
-rw-r--r--src/lib/libast/man/re.3214
-rw-r--r--src/lib/libast/man/regex.3163
-rw-r--r--src/lib/libast/man/setenviron.379
-rw-r--r--src/lib/libast/man/sfdisc.3118
-rw-r--r--src/lib/libast/man/sfio.32373
-rw-r--r--src/lib/libast/man/sig.375
-rw-r--r--src/lib/libast/man/spawnveg.397
-rw-r--r--src/lib/libast/man/stak.3169
-rw-r--r--src/lib/libast/man/stk.3165
-rw-r--r--src/lib/libast/man/strcopy.354
-rw-r--r--src/lib/libast/man/strdup.355
-rw-r--r--src/lib/libast/man/strelapsed.377
-rw-r--r--src/lib/libast/man/strerror.353
-rw-r--r--src/lib/libast/man/stresc.353
-rw-r--r--src/lib/libast/man/streval.383
-rw-r--r--src/lib/libast/man/strgid.353
-rw-r--r--src/lib/libast/man/strmatch.3101
-rw-r--r--src/lib/libast/man/stropt.3130
-rw-r--r--src/lib/libast/man/strperm.3109
-rw-r--r--src/lib/libast/man/strsignal.353
-rw-r--r--src/lib/libast/man/strsort.373
-rw-r--r--src/lib/libast/man/strtape.386
-rw-r--r--src/lib/libast/man/strton.397
-rw-r--r--src/lib/libast/man/struid.353
-rw-r--r--src/lib/libast/man/swap.3138
-rw-r--r--src/lib/libast/man/tab.374
-rw-r--r--src/lib/libast/man/tm.3775
-rw-r--r--src/lib/libast/man/tmx.3576
-rw-r--r--src/lib/libast/man/tok.3217
-rw-r--r--src/lib/libast/man/touch.368
-rw-r--r--src/lib/libast/man/tv.3173
-rw-r--r--src/lib/libast/man/vecargs.3126
-rw-r--r--src/lib/libast/man/vmalloc.3640
-rw-r--r--src/lib/libast/misc/astintercept.c53
-rw-r--r--src/lib/libast/misc/cmdarg.c382
-rw-r--r--src/lib/libast/misc/conformance.c151
-rw-r--r--src/lib/libast/misc/debug.c66
-rw-r--r--src/lib/libast/misc/error.c659
-rw-r--r--src/lib/libast/misc/errorf.c41
-rw-r--r--src/lib/libast/misc/errormsg.c41
-rw-r--r--src/lib/libast/misc/errorx.c50
-rw-r--r--src/lib/libast/misc/fastfind.c1282
-rw-r--r--src/lib/libast/misc/findlib.h123
-rw-r--r--src/lib/libast/misc/fmtrec.c102
-rw-r--r--src/lib/libast/misc/fs3d.c116
-rw-r--r--src/lib/libast/misc/fts.c1605
-rw-r--r--src/lib/libast/misc/ftwalk.c156
-rw-r--r--src/lib/libast/misc/ftwflags.c35
-rw-r--r--src/lib/libast/misc/getcwd.c334
-rw-r--r--src/lib/libast/misc/getenv.c113
-rw-r--r--src/lib/libast/misc/glob.c829
-rw-r--r--src/lib/libast/misc/intercepts.h40
-rw-r--r--src/lib/libast/misc/magic.c2497
-rw-r--r--src/lib/libast/misc/magic.tab1721
-rw-r--r--src/lib/libast/misc/mime.c839
-rw-r--r--src/lib/libast/misc/mimelib.h52
-rw-r--r--src/lib/libast/misc/mimetype.c69
-rw-r--r--src/lib/libast/misc/optctx.c70
-rw-r--r--src/lib/libast/misc/optesc.c93
-rw-r--r--src/lib/libast/misc/optget.c5751
-rw-r--r--src/lib/libast/misc/optjoin.c129
-rw-r--r--src/lib/libast/misc/optlib.h115
-rw-r--r--src/lib/libast/misc/procclose.c98
-rw-r--r--src/lib/libast/misc/procfree.c43
-rw-r--r--src/lib/libast/misc/proclib.h64
-rw-r--r--src/lib/libast/misc/procopen.c941
-rw-r--r--src/lib/libast/misc/procrun.c49
-rw-r--r--src/lib/libast/misc/recfmt.c165
-rw-r--r--src/lib/libast/misc/reclen.c71
-rw-r--r--src/lib/libast/misc/recstr.c206
-rw-r--r--src/lib/libast/misc/setenviron.c147
-rw-r--r--src/lib/libast/misc/sigcrit.c199
-rw-r--r--src/lib/libast/misc/sigdata.c40
-rw-r--r--src/lib/libast/misc/signal.c136
-rw-r--r--src/lib/libast/misc/stack.c172
-rw-r--r--src/lib/libast/misc/state.c42
-rw-r--r--src/lib/libast/misc/stk.c553
-rw-r--r--src/lib/libast/misc/systrace.c68
-rw-r--r--src/lib/libast/misc/translate.c437
-rw-r--r--src/lib/libast/misc/univdata.c58
-rw-r--r--src/lib/libast/misc/univlib.h93
-rw-r--r--src/lib/libast/obsolete/spawn.c152
-rw-r--r--src/lib/libast/path/pathaccess.c69
-rw-r--r--src/lib/libast/path/pathbin.c46
-rw-r--r--src/lib/libast/path/pathcanon.c222
-rw-r--r--src/lib/libast/path/pathcat.c98
-rw-r--r--src/lib/libast/path/pathcd.c142
-rw-r--r--src/lib/libast/path/pathcheck.c91
-rw-r--r--src/lib/libast/path/pathexists.c134
-rw-r--r--src/lib/libast/path/pathfind.c168
-rw-r--r--src/lib/libast/path/pathgetlink.c102
-rw-r--r--src/lib/libast/path/pathkey.c320
-rw-r--r--src/lib/libast/path/pathnative.c126
-rw-r--r--src/lib/libast/path/pathpath.c127
-rw-r--r--src/lib/libast/path/pathposix.c128
-rw-r--r--src/lib/libast/path/pathprobe.c316
-rw-r--r--src/lib/libast/path/pathprog.c128
-rw-r--r--src/lib/libast/path/pathrepl.c93
-rw-r--r--src/lib/libast/path/pathsetlink.c72
-rw-r--r--src/lib/libast/path/pathshell.c112
-rw-r--r--src/lib/libast/path/pathstat.c45
-rw-r--r--src/lib/libast/path/pathtemp.c337
-rw-r--r--src/lib/libast/path/pathtmp.c41
-rw-r--r--src/lib/libast/port/astconf.c1718
-rw-r--r--src/lib/libast/port/astcopy.c90
-rw-r--r--src/lib/libast/port/astdynamic.c132
-rw-r--r--src/lib/libast/port/astlicense.c1292
-rw-r--r--src/lib/libast/port/astmath.c72
-rw-r--r--src/lib/libast/port/astquery.c114
-rw-r--r--src/lib/libast/port/aststatic.c44
-rw-r--r--src/lib/libast/port/astwinsize.c143
-rw-r--r--src/lib/libast/port/atmain.C37
-rw-r--r--src/lib/libast/port/iblocks.c95
-rw-r--r--src/lib/libast/port/lc.c883
-rw-r--r--src/lib/libast/port/lc.tab275
-rw-r--r--src/lib/libast/port/lcgen.c791
-rw-r--r--src/lib/libast/port/lclang.h120
-rw-r--r--src/lib/libast/port/lclib.h71
-rw-r--r--src/lib/libast/port/mc.c675
-rw-r--r--src/lib/libast/port/mnt.c816
-rw-r--r--src/lib/libast/port/touch.c74
-rw-r--r--src/lib/libast/preroot/getpreroot.c165
-rw-r--r--src/lib/libast/preroot/ispreroot.c71
-rw-r--r--src/lib/libast/preroot/realopen.c47
-rw-r--r--src/lib/libast/preroot/setpreroot.c75
-rw-r--r--src/lib/libast/regex/regalloc.c36
-rw-r--r--src/lib/libast/regex/regcache.c198
-rw-r--r--src/lib/libast/regex/regclass.c298
-rw-r--r--src/lib/libast/regex/regcoll.c120
-rw-r--r--src/lib/libast/regex/regcomp.c3544
-rw-r--r--src/lib/libast/regex/regdecomp.c448
-rw-r--r--src/lib/libast/regex/regerror.c95
-rw-r--r--src/lib/libast/regex/regexec.c54
-rw-r--r--src/lib/libast/regex/regfatal.c49
-rw-r--r--src/lib/libast/regex/reginit.c412
-rw-r--r--src/lib/libast/regex/reglib.h582
-rw-r--r--src/lib/libast/regex/regnexec.c2045
-rw-r--r--src/lib/libast/regex/regrecord.c34
-rw-r--r--src/lib/libast/regex/regrexec.c145
-rw-r--r--src/lib/libast/regex/regstat.c53
-rw-r--r--src/lib/libast/regex/regsub.c269
-rw-r--r--src/lib/libast/regex/regsubcomp.c377
-rw-r--r--src/lib/libast/regex/regsubexec.c196
-rw-r--r--src/lib/libast/sfio/_sfclrerr.c34
-rw-r--r--src/lib/libast/sfio/_sfdlen.c34
-rw-r--r--src/lib/libast/sfio/_sfeof.c34
-rw-r--r--src/lib/libast/sfio/_sferror.c34
-rw-r--r--src/lib/libast/sfio/_sffileno.c34
-rw-r--r--src/lib/libast/sfio/_sfgetc.c34
-rw-r--r--src/lib/libast/sfio/_sfgetl.c42
-rw-r--r--src/lib/libast/sfio/_sfgetl2.c50
-rw-r--r--src/lib/libast/sfio/_sfgetu.c42
-rw-r--r--src/lib/libast/sfio/_sfgetu2.c50
-rw-r--r--src/lib/libast/sfio/_sfllen.c34
-rw-r--r--src/lib/libast/sfio/_sfopen.c219
-rw-r--r--src/lib/libast/sfio/_sfputc.c35
-rw-r--r--src/lib/libast/sfio/_sfputd.c96
-rw-r--r--src/lib/libast/sfio/_sfputl.c82
-rw-r--r--src/lib/libast/sfio/_sfputm.c78
-rw-r--r--src/lib/libast/sfio/_sfputu.c75
-rw-r--r--src/lib/libast/sfio/_sfslen.c33
-rw-r--r--src/lib/libast/sfio/_sfstacked.c34
-rw-r--r--src/lib/libast/sfio/_sfulen.c34
-rw-r--r--src/lib/libast/sfio/_sfvalue.c34
-rw-r--r--src/lib/libast/sfio/sfclose.c178
-rw-r--r--src/lib/libast/sfio/sfclrlock.c63
-rw-r--r--src/lib/libast/sfio/sfcvt.c532
-rw-r--r--src/lib/libast/sfio/sfdisc.c271
-rw-r--r--src/lib/libast/sfio/sfdlen.c58
-rw-r--r--src/lib/libast/sfio/sfecvt.c38
-rw-r--r--src/lib/libast/sfio/sfexcept.c133
-rw-r--r--src/lib/libast/sfio/sfextern.c99
-rw-r--r--src/lib/libast/sfio/sffcvt.c38
-rw-r--r--src/lib/libast/sfio/sffilbuf.c116
-rw-r--r--src/lib/libast/sfio/sfflsbuf.c126
-rw-r--r--src/lib/libast/sfio/sfgetd.c79
-rw-r--r--src/lib/libast/sfio/sfgetl.c70
-rw-r--r--src/lib/libast/sfio/sfgetm.c68
-rw-r--r--src/lib/libast/sfio/sfgetr.c169
-rw-r--r--src/lib/libast/sfio/sfgetu.c67
-rw-r--r--src/lib/libast/sfio/sfhdr.h1302
-rw-r--r--src/lib/libast/sfio/sfllen.c39
-rw-r--r--src/lib/libast/sfio/sfmode.c596
-rw-r--r--src/lib/libast/sfio/sfmove.c242
-rw-r--r--src/lib/libast/sfio/sfmutex.c69
-rw-r--r--src/lib/libast/sfio/sfnew.c129
-rw-r--r--src/lib/libast/sfio/sfnotify.c38
-rw-r--r--src/lib/libast/sfio/sfnputc.c81
-rw-r--r--src/lib/libast/sfio/sfopen.c40
-rw-r--r--src/lib/libast/sfio/sfpeek.c89
-rw-r--r--src/lib/libast/sfio/sfpkrd.c325
-rw-r--r--src/lib/libast/sfio/sfpoll.c250
-rw-r--r--src/lib/libast/sfio/sfpool.c369
-rw-r--r--src/lib/libast/sfio/sfpopen.c293
-rw-r--r--src/lib/libast/sfio/sfprintf.c114
-rw-r--r--src/lib/libast/sfio/sfprints.c125
-rw-r--r--src/lib/libast/sfio/sfpurge.c98
-rw-r--r--src/lib/libast/sfio/sfputd.c35
-rw-r--r--src/lib/libast/sfio/sfputl.c35
-rw-r--r--src/lib/libast/sfio/sfputm.c36
-rw-r--r--src/lib/libast/sfio/sfputr.c136
-rw-r--r--src/lib/libast/sfio/sfputu.c35
-rw-r--r--src/lib/libast/sfio/sfraise.c107
-rw-r--r--src/lib/libast/sfio/sfrd.c317
-rw-r--r--src/lib/libast/sfio/sfread.c140
-rw-r--r--src/lib/libast/sfio/sfreserve.c210
-rw-r--r--src/lib/libast/sfio/sfresize.c83
-rw-r--r--src/lib/libast/sfio/sfscanf.c102
-rw-r--r--src/lib/libast/sfio/sfseek.c281
-rw-r--r--src/lib/libast/sfio/sfset.c99
-rw-r--r--src/lib/libast/sfio/sfsetbuf.c426
-rw-r--r--src/lib/libast/sfio/sfsetfd.c136
-rw-r--r--src/lib/libast/sfio/sfsize.c109
-rw-r--r--src/lib/libast/sfio/sfsk.c106
-rw-r--r--src/lib/libast/sfio/sfstack.c115
-rw-r--r--src/lib/libast/sfio/sfstrtod.c157
-rw-r--r--src/lib/libast/sfio/sfstrtof.h568
-rw-r--r--src/lib/libast/sfio/sfswap.c119
-rw-r--r--src/lib/libast/sfio/sfsync.c172
-rw-r--r--src/lib/libast/sfio/sftable.c543
-rw-r--r--src/lib/libast/sfio/sftell.c59
-rw-r--r--src/lib/libast/sfio/sftmp.c402
-rw-r--r--src/lib/libast/sfio/sfungetc.c108
-rw-r--r--src/lib/libast/sfio/sfvprintf.c1445
-rw-r--r--src/lib/libast/sfio/sfvscanf.c1100
-rw-r--r--src/lib/libast/sfio/sfwalk.c67
-rw-r--r--src/lib/libast/sfio/sfwr.c252
-rw-r--r--src/lib/libast/sfio/sfwrite.c171
-rw-r--r--src/lib/libast/sfio/vthread.h219
-rw-r--r--src/lib/libast/std/bytesex.h43
-rw-r--r--src/lib/libast/std/dirent.h22
-rw-r--r--src/lib/libast/std/endian.h54
-rw-r--r--src/lib/libast/std/iconv.h22
-rw-r--r--src/lib/libast/std/nl_types.h22
-rw-r--r--src/lib/libast/std/stdio.h22
-rw-r--r--src/lib/libast/std/wchar.h22
-rw-r--r--src/lib/libast/std/wctype.h22
-rw-r--r--src/lib/libast/stdio/_doprnt.c32
-rw-r--r--src/lib/libast/stdio/_doscan.c32
-rw-r--r--src/lib/libast/stdio/_filbuf.c36
-rw-r--r--src/lib/libast/stdio/_flsbuf.c44
-rw-r--r--src/lib/libast/stdio/_stdfun.c80
-rw-r--r--src/lib/libast/stdio/_stdopen.c32
-rw-r--r--src/lib/libast/stdio/_stdprintf.c38
-rw-r--r--src/lib/libast/stdio/_stdscanf.c38
-rw-r--r--src/lib/libast/stdio/_stdsprnt.c38
-rw-r--r--src/lib/libast/stdio/_stdvbuf.c32
-rw-r--r--src/lib/libast/stdio/_stdvsnprnt.c32
-rw-r--r--src/lib/libast/stdio/_stdvsprnt.c32
-rw-r--r--src/lib/libast/stdio/_stdvsscn.c32
-rw-r--r--src/lib/libast/stdio/asprintf.c36
-rw-r--r--src/lib/libast/stdio/clearerr.c33
-rw-r--r--src/lib/libast/stdio/fclose.c32
-rw-r--r--src/lib/libast/stdio/fcloseall.c57
-rw-r--r--src/lib/libast/stdio/fdopen.c34
-rw-r--r--src/lib/libast/stdio/feof.c42
-rw-r--r--src/lib/libast/stdio/ferror.c42
-rw-r--r--src/lib/libast/stdio/fflush.c41
-rw-r--r--src/lib/libast/stdio/fgetc.c32
-rw-r--r--src/lib/libast/stdio/fgetpos.c48
-rw-r--r--src/lib/libast/stdio/fgets.c110
-rw-r--r--src/lib/libast/stdio/fgetwc.c35
-rw-r--r--src/lib/libast/stdio/fgetws.c52
-rw-r--r--src/lib/libast/stdio/fileno.c42
-rw-r--r--src/lib/libast/stdio/flockfile.c32
-rw-r--r--src/lib/libast/stdio/fmemopen.c32
-rw-r--r--src/lib/libast/stdio/fopen.c30
-rw-r--r--src/lib/libast/stdio/fprintf.c39
-rw-r--r--src/lib/libast/stdio/fpurge.c32
-rw-r--r--src/lib/libast/stdio/fputc.c42
-rw-r--r--src/lib/libast/stdio/fputs.c32
-rw-r--r--src/lib/libast/stdio/fputwc.c33
-rw-r--r--src/lib/libast/stdio/fputws.c36
-rw-r--r--src/lib/libast/stdio/fread.c34
-rw-r--r--src/lib/libast/stdio/freopen.c32
-rw-r--r--src/lib/libast/stdio/fscanf.c39
-rw-r--r--src/lib/libast/stdio/fseek.c48
-rw-r--r--src/lib/libast/stdio/fseeko.c48
-rw-r--r--src/lib/libast/stdio/fsetpos.c48
-rw-r--r--src/lib/libast/stdio/ftell.c48
-rw-r--r--src/lib/libast/stdio/ftello.c48
-rw-r--r--src/lib/libast/stdio/ftrylockfile.c32
-rw-r--r--src/lib/libast/stdio/funlockfile.c32
-rw-r--r--src/lib/libast/stdio/fwide.c51
-rw-r--r--src/lib/libast/stdio/fwprintf.c36
-rw-r--r--src/lib/libast/stdio/fwrite.c34
-rw-r--r--src/lib/libast/stdio/fwscanf.c39
-rw-r--r--src/lib/libast/stdio/getc.c42
-rw-r--r--src/lib/libast/stdio/getchar.c40
-rw-r--r--src/lib/libast/stdio/getdelim.c96
-rw-r--r--src/lib/libast/stdio/getline.c36
-rw-r--r--src/lib/libast/stdio/getw.c34
-rw-r--r--src/lib/libast/stdio/getwc.c31
-rw-r--r--src/lib/libast/stdio/getwchar.c31
-rw-r--r--src/lib/libast/stdio/pclose.c32
-rw-r--r--src/lib/libast/stdio/popen.c30
-rw-r--r--src/lib/libast/stdio/printf.c36
-rw-r--r--src/lib/libast/stdio/putc.c42
-rw-r--r--src/lib/libast/stdio/putchar.c40
-rw-r--r--src/lib/libast/stdio/puts.c30
-rw-r--r--src/lib/libast/stdio/putw.c32
-rw-r--r--src/lib/libast/stdio/putwc.c31
-rw-r--r--src/lib/libast/stdio/putwchar.c31
-rw-r--r--src/lib/libast/stdio/rewind.c33
-rw-r--r--src/lib/libast/stdio/scanf.c36
-rw-r--r--src/lib/libast/stdio/setbuf.c32
-rw-r--r--src/lib/libast/stdio/setbuffer.c32
-rw-r--r--src/lib/libast/stdio/setlinebuf.c33
-rw-r--r--src/lib/libast/stdio/setvbuf.c48
-rw-r--r--src/lib/libast/stdio/snprintf.c36
-rw-r--r--src/lib/libast/stdio/sprintf.c36
-rw-r--r--src/lib/libast/stdio/sscanf.c36
-rw-r--r--src/lib/libast/stdio/stdhdr.h115
-rw-r--r--src/lib/libast/stdio/stdio_c99.c118
-rw-r--r--src/lib/libast/stdio/swprintf.c36
-rw-r--r--src/lib/libast/stdio/swscanf.c36
-rw-r--r--src/lib/libast/stdio/tmpfile.c30
-rw-r--r--src/lib/libast/stdio/ungetc.c32
-rw-r--r--src/lib/libast/stdio/ungetwc.c39
-rw-r--r--src/lib/libast/stdio/vasprintf.c45
-rw-r--r--src/lib/libast/stdio/vfprintf.c32
-rw-r--r--src/lib/libast/stdio/vfscanf.c32
-rw-r--r--src/lib/libast/stdio/vfwprintf.c68
-rw-r--r--src/lib/libast/stdio/vfwscanf.c129
-rw-r--r--src/lib/libast/stdio/vprintf.c30
-rw-r--r--src/lib/libast/stdio/vscanf.c30
-rw-r--r--src/lib/libast/stdio/vsnprintf.c52
-rw-r--r--src/lib/libast/stdio/vsprintf.c30
-rw-r--r--src/lib/libast/stdio/vsscanf.c30
-rw-r--r--src/lib/libast/stdio/vswprintf.c55
-rw-r--r--src/lib/libast/stdio/vswscanf.c51
-rw-r--r--src/lib/libast/stdio/vwprintf.c30
-rw-r--r--src/lib/libast/stdio/vwscanf.c30
-rw-r--r--src/lib/libast/stdio/wprintf.c36
-rw-r--r--src/lib/libast/stdio/wscanf.c36
-rw-r--r--src/lib/libast/string/base64.c312
-rw-r--r--src/lib/libast/string/ccmap.c746
-rw-r--r--src/lib/libast/string/ccmapid.c173
-rw-r--r--src/lib/libast/string/ccnative.c56
-rw-r--r--src/lib/libast/string/chresc.c235
-rw-r--r--src/lib/libast/string/chrtoi.c55
-rw-r--r--src/lib/libast/string/fmtbase.c70
-rw-r--r--src/lib/libast/string/fmtbuf.c69
-rw-r--r--src/lib/libast/string/fmtclock.c63
-rw-r--r--src/lib/libast/string/fmtdev.c60
-rw-r--r--src/lib/libast/string/fmtelapsed.c61
-rw-r--r--src/lib/libast/string/fmterror.c37
-rw-r--r--src/lib/libast/string/fmtesc.c248
-rw-r--r--src/lib/libast/string/fmtfmt.c205
-rw-r--r--src/lib/libast/string/fmtfs.c100
-rw-r--r--src/lib/libast/string/fmtgid.c101
-rw-r--r--src/lib/libast/string/fmtident.c77
-rw-r--r--src/lib/libast/string/fmtint.c122
-rw-r--r--src/lib/libast/string/fmtip4.c43
-rw-r--r--src/lib/libast/string/fmtip6.c175
-rw-r--r--src/lib/libast/string/fmtls.c120
-rw-r--r--src/lib/libast/string/fmtmatch.c286
-rw-r--r--src/lib/libast/string/fmtmode.c47
-rw-r--r--src/lib/libast/string/fmtnum.c92
-rw-r--r--src/lib/libast/string/fmtperm.c91
-rw-r--r--src/lib/libast/string/fmtre.c226
-rw-r--r--src/lib/libast/string/fmtscale.c94
-rw-r--r--src/lib/libast/string/fmtsignal.c62
-rw-r--r--src/lib/libast/string/fmttime.c41
-rw-r--r--src/lib/libast/string/fmttmx.c45
-rw-r--r--src/lib/libast/string/fmttv.c44
-rw-r--r--src/lib/libast/string/fmtuid.c101
-rw-r--r--src/lib/libast/string/fmtversion.c53
-rw-r--r--src/lib/libast/string/memdup.c44
-rw-r--r--src/lib/libast/string/modedata.c69
-rw-r--r--src/lib/libast/string/modei.c55
-rw-r--r--src/lib/libast/string/modelib.h55
-rw-r--r--src/lib/libast/string/modex.c75
-rw-r--r--src/lib/libast/string/stracmp.c62
-rw-r--r--src/lib/libast/string/strcopy.c36
-rw-r--r--src/lib/libast/string/strdup.c60
-rw-r--r--src/lib/libast/string/strelapsed.c154
-rw-r--r--src/lib/libast/string/strerror.c148
-rw-r--r--src/lib/libast/string/stresc.c67
-rw-r--r--src/lib/libast/string/streval.c50
-rw-r--r--src/lib/libast/string/strexpr.c294
-rw-r--r--src/lib/libast/string/strgid.c121
-rw-r--r--src/lib/libast/string/strlcat.c83
-rw-r--r--src/lib/libast/string/strlcpy.c71
-rw-r--r--src/lib/libast/string/strlook.c50
-rw-r--r--src/lib/libast/string/strmatch.c171
-rw-r--r--src/lib/libast/string/strmode.c51
-rw-r--r--src/lib/libast/string/strnacmp.c66
-rw-r--r--src/lib/libast/string/strncopy.c46
-rw-r--r--src/lib/libast/string/strnpcmp.c51
-rw-r--r--src/lib/libast/string/strntod.c32
-rw-r--r--src/lib/libast/string/strntol.c31
-rw-r--r--src/lib/libast/string/strntold.c32
-rw-r--r--src/lib/libast/string/strntoll.c31
-rw-r--r--src/lib/libast/string/strnton.c32
-rw-r--r--src/lib/libast/string/strntonll.c32
-rw-r--r--src/lib/libast/string/strntoul.c32
-rw-r--r--src/lib/libast/string/strntoull.c32
-rw-r--r--src/lib/libast/string/strnvcmp.c86
-rw-r--r--src/lib/libast/string/stropt.c188
-rw-r--r--src/lib/libast/string/strpcmp.c44
-rw-r--r--src/lib/libast/string/strperm.c267
-rw-r--r--src/lib/libast/string/strpsearch.c125
-rw-r--r--src/lib/libast/string/strsearch.c57
-rw-r--r--src/lib/libast/string/strsort.c57
-rw-r--r--src/lib/libast/string/strtape.c148
-rw-r--r--src/lib/libast/string/strtoi.h640
-rw-r--r--src/lib/libast/string/strtoip4.c150
-rw-r--r--src/lib/libast/string/strtoip6.c204
-rw-r--r--src/lib/libast/string/strton.c31
-rw-r--r--src/lib/libast/string/strtonll.c31
-rw-r--r--src/lib/libast/string/struid.c109
-rw-r--r--src/lib/libast/string/struniq.c51
-rw-r--r--src/lib/libast/string/strvcmp.c74
-rw-r--r--src/lib/libast/string/swapget.c57
-rw-r--r--src/lib/libast/string/swapmem.c109
-rw-r--r--src/lib/libast/string/swapop.c59
-rw-r--r--src/lib/libast/string/swapput.c50
-rw-r--r--src/lib/libast/string/tok.c190
-rw-r--r--src/lib/libast/string/tokline.c193
-rw-r--r--src/lib/libast/string/tokscan.c360
-rw-r--r--src/lib/libast/string/wc2utf8.c74
-rw-r--r--src/lib/libast/tm/tmdata.c288
-rw-r--r--src/lib/libast/tm/tmdate.c41
-rw-r--r--src/lib/libast/tm/tmequiv.c57
-rw-r--r--src/lib/libast/tm/tmfix.c173
-rw-r--r--src/lib/libast/tm/tmfmt.c41
-rw-r--r--src/lib/libast/tm/tmform.c44
-rw-r--r--src/lib/libast/tm/tmgoff.c77
-rw-r--r--src/lib/libast/tm/tminit.c460
-rw-r--r--src/lib/libast/tm/tmleap.c41
-rw-r--r--src/lib/libast/tm/tmlex.c67
-rw-r--r--src/lib/libast/tm/tmlocale.c644
-rw-r--r--src/lib/libast/tm/tmmake.c41
-rw-r--r--src/lib/libast/tm/tmpoff.c62
-rw-r--r--src/lib/libast/tm/tmscan.c41
-rw-r--r--src/lib/libast/tm/tmsleep.c42
-rw-r--r--src/lib/libast/tm/tmtime.c41
-rw-r--r--src/lib/libast/tm/tmtype.c57
-rw-r--r--src/lib/libast/tm/tmweek.c87
-rw-r--r--src/lib/libast/tm/tmword.c89
-rw-r--r--src/lib/libast/tm/tmxdate.c1745
-rw-r--r--src/lib/libast/tm/tmxduration.c80
-rw-r--r--src/lib/libast/tm/tmxfmt.c703
-rw-r--r--src/lib/libast/tm/tmxgettime.c44
-rw-r--r--src/lib/libast/tm/tmxleap.c51
-rw-r--r--src/lib/libast/tm/tmxmake.c140
-rw-r--r--src/lib/libast/tm/tmxscan.c533
-rw-r--r--src/lib/libast/tm/tmxsettime.c45
-rw-r--r--src/lib/libast/tm/tmxsleep.c41
-rw-r--r--src/lib/libast/tm/tmxtime.c137
-rw-r--r--src/lib/libast/tm/tmxtouch.c81
-rw-r--r--src/lib/libast/tm/tmzone.c95
-rw-r--r--src/lib/libast/tm/tvcmp.c46
-rw-r--r--src/lib/libast/tm/tvgettime.c70
-rw-r--r--src/lib/libast/tm/tvsettime.c72
-rw-r--r--src/lib/libast/tm/tvsleep.c144
-rw-r--r--src/lib/libast/tm/tvtouch.c295
-rw-r--r--src/lib/libast/uwin/a64l.c76
-rw-r--r--src/lib/libast/uwin/acosh.c108
-rw-r--r--src/lib/libast/uwin/asinh.c107
-rw-r--r--src/lib/libast/uwin/atanh.c89
-rw-r--r--src/lib/libast/uwin/cbrt.c38
-rw-r--r--src/lib/libast/uwin/crypt.c959
-rw-r--r--src/lib/libast/uwin/erf.c403
-rw-r--r--src/lib/libast/uwin/err.c124
-rw-r--r--src/lib/libast/uwin/exp.c213
-rw-r--r--src/lib/libast/uwin/exp__E.c142
-rw-r--r--src/lib/libast/uwin/expm1.c173
-rw-r--r--src/lib/libast/uwin/gamma.c343
-rw-r--r--src/lib/libast/uwin/getpass.c79
-rw-r--r--src/lib/libast/uwin/lgamma.c316
-rw-r--r--src/lib/libast/uwin/log.c496
-rw-r--r--src/lib/libast/uwin/log1p.c176
-rw-r--r--src/lib/libast/uwin/log__L.c116
-rw-r--r--src/lib/libast/uwin/mathimpl.h103
-rw-r--r--src/lib/libast/uwin/mini.sym84
-rw-r--r--src/lib/libast/uwin/rand48.c177
-rw-r--r--src/lib/libast/uwin/random.c381
-rw-r--r--src/lib/libast/uwin/rcmd.c571
-rw-r--r--src/lib/libast/uwin/rint.c41
-rw-r--r--src/lib/libast/uwin/rlib.h80
-rw-r--r--src/lib/libast/uwin/support.c605
-rw-r--r--src/lib/libast/vec/vecargs.c76
-rw-r--r--src/lib/libast/vec/vecfile.c62
-rw-r--r--src/lib/libast/vec/vecfree.c48
-rw-r--r--src/lib/libast/vec/vecload.c96
-rw-r--r--src/lib/libast/vec/vecstring.c46
-rw-r--r--src/lib/libast/vmalloc/malloc.c1438
-rw-r--r--src/lib/libast/vmalloc/vmbest.c1390
-rw-r--r--src/lib/libast/vmalloc/vmclear.c85
-rw-r--r--src/lib/libast/vmalloc/vmclose.c91
-rw-r--r--src/lib/libast/vmalloc/vmdcheap.c63
-rw-r--r--src/lib/libast/vmalloc/vmdebug.c745
-rw-r--r--src/lib/libast/vmalloc/vmdisc.c55
-rw-r--r--src/lib/libast/vmalloc/vmexit.c100
-rw-r--r--src/lib/libast/vmalloc/vmgetmem.c51
-rw-r--r--src/lib/libast/vmalloc/vmhdr.h530
-rw-r--r--src/lib/libast/vmalloc/vmlast.c431
-rw-r--r--src/lib/libast/vmalloc/vmmopen.c518
-rw-r--r--src/lib/libast/vmalloc/vmopen.c180
-rw-r--r--src/lib/libast/vmalloc/vmpool.c316
-rw-r--r--src/lib/libast/vmalloc/vmprivate.c292
-rw-r--r--src/lib/libast/vmalloc/vmprofile.c709
-rw-r--r--src/lib/libast/vmalloc/vmregion.c61
-rw-r--r--src/lib/libast/vmalloc/vmsegment.c58
-rw-r--r--src/lib/libast/vmalloc/vmset.c62
-rw-r--r--src/lib/libast/vmalloc/vmstat.c145
-rw-r--r--src/lib/libast/vmalloc/vmstrdup.c48
-rw-r--r--src/lib/libast/vmalloc/vmtrace.c286
-rw-r--r--src/lib/libast/vmalloc/vmwalk.c69
-rw-r--r--src/lib/libcmd/Makefile90
-rw-r--r--src/lib/libcmd/Mamfile866
-rw-r--r--src/lib/libcmd/RELEASE328
-rw-r--r--src/lib/libcmd/basename.c139
-rw-r--r--src/lib/libcmd/cat.c557
-rw-r--r--src/lib/libcmd/chgrp.c501
-rw-r--r--src/lib/libcmd/chmod.c325
-rw-r--r--src/lib/libcmd/chown.c39
-rw-r--r--src/lib/libcmd/cksum.c632
-rw-r--r--src/lib/libcmd/cmd.h163
-rw-r--r--src/lib/libcmd/cmdinit.c75
-rw-r--r--src/lib/libcmd/cmp.c383
-rw-r--r--src/lib/libcmd/comm.c203
-rw-r--r--src/lib/libcmd/cp.c1009
-rw-r--r--src/lib/libcmd/cut.c702
-rw-r--r--src/lib/libcmd/date.c515
-rw-r--r--src/lib/libcmd/dirname.c139
-rw-r--r--src/lib/libcmd/expr.c535
-rw-r--r--src/lib/libcmd/fds.c360
-rw-r--r--src/lib/libcmd/features/ids9
-rw-r--r--src/lib/libcmd/features/sockets3
-rw-r--r--src/lib/libcmd/features/symlink23
-rw-r--r--src/lib/libcmd/features/utsname15
-rw-r--r--src/lib/libcmd/fmt.c635
-rw-r--r--src/lib/libcmd/fold.c240
-rw-r--r--src/lib/libcmd/fts_fix.c57
-rw-r--r--src/lib/libcmd/fts_fix.h49
-rw-r--r--src/lib/libcmd/getconf.c396
-rw-r--r--src/lib/libcmd/head.c150
-rw-r--r--src/lib/libcmd/id.c472
-rw-r--r--src/lib/libcmd/join.c984
-rw-r--r--src/lib/libcmd/lib.c25
-rw-r--r--src/lib/libcmd/ln.c35
-rw-r--r--src/lib/libcmd/logname.c78
-rw-r--r--src/lib/libcmd/md5sum.c35
-rw-r--r--src/lib/libcmd/mkdir.c189
-rw-r--r--src/lib/libcmd/mkfifo.c96
-rw-r--r--src/lib/libcmd/mktemp.c169
-rw-r--r--src/lib/libcmd/mv.c35
-rw-r--r--src/lib/libcmd/paste.c288
-rw-r--r--src/lib/libcmd/pathchk.c265
-rw-r--r--src/lib/libcmd/pids.c124
-rw-r--r--src/lib/libcmd/rev.c168
-rw-r--r--src/lib/libcmd/rev.h34
-rw-r--r--src/lib/libcmd/revlib.c112
-rw-r--r--src/lib/libcmd/rm.c417
-rw-r--r--src/lib/libcmd/rmdir.c126
-rw-r--r--src/lib/libcmd/stty.c971
-rw-r--r--src/lib/libcmd/sum.c35
-rw-r--r--src/lib/libcmd/sync.c79
-rw-r--r--src/lib/libcmd/tail.c773
-rw-r--r--src/lib/libcmd/tee.c204
-rw-r--r--src/lib/libcmd/tty.c105
-rw-r--r--src/lib/libcmd/uname.c514
-rw-r--r--src/lib/libcmd/uniq.c342
-rw-r--r--src/lib/libcmd/vmstate.c197
-rw-r--r--src/lib/libcmd/wc.c188
-rw-r--r--src/lib/libcmd/wc.h59
-rw-r--r--src/lib/libcmd/wclib.c505
-rw-r--r--src/lib/libcoshell/Makefile20
-rw-r--r--src/lib/libcoshell/Mamfile464
-rw-r--r--src/lib/libcoshell/RELEASE49
-rw-r--r--src/lib/libcoshell/coclose.c113
-rw-r--r--src/lib/libcoshell/codata.c169
-rw-r--r--src/lib/libcoshell/coexec.c449
-rw-r--r--src/lib/libcoshell/coexport.c80
-rw-r--r--src/lib/libcoshell/coinit.c431
-rw-r--r--src/lib/libcoshell/cokill.c134
-rw-r--r--src/lib/libcoshell/colib.h137
-rw-r--r--src/lib/libcoshell/coopen.c411
-rw-r--r--src/lib/libcoshell/coquote.c60
-rw-r--r--src/lib/libcoshell/coshell.3396
-rw-r--r--src/lib/libcoshell/coshell.h143
-rw-r--r--src/lib/libcoshell/costash.c40
-rw-r--r--src/lib/libcoshell/cosync.c127
-rw-r--r--src/lib/libcoshell/cowait.c411
-rw-r--r--src/lib/libcoshell/ignore.sh45
-rw-r--r--src/lib/libcoshell/procrun.c56
-rw-r--r--src/lib/libcoshell/silent.sh44
-rw-r--r--src/lib/libcoshell/system.c57
-rw-r--r--src/lib/libdll/Makefile17
-rw-r--r--src/lib/libdll/Mamfile319
-rw-r--r--src/lib/libdll/RELEASE52
-rw-r--r--src/lib/libdll/dlfcn.c536
-rw-r--r--src/lib/libdll/dll_lib.c183
-rw-r--r--src/lib/libdll/dllcheck.c85
-rw-r--r--src/lib/libdll/dllerror.c52
-rw-r--r--src/lib/libdll/dllfind.c46
-rw-r--r--src/lib/libdll/dlllib.h34
-rw-r--r--src/lib/libdll/dlllook.c46
-rw-r--r--src/lib/libdll/dllnext.c223
-rw-r--r--src/lib/libdll/dllopen.c93
-rw-r--r--src/lib/libdll/dllplug.c126
-rw-r--r--src/lib/libdll/dllscan.c525
-rw-r--r--src/lib/libdll/features/dll263
-rw-r--r--src/lib/libsum/Makefile11
-rw-r--r--src/lib/libsum/Mamfile245
-rw-r--r--src/lib/libsum/RELEASE16
-rw-r--r--src/lib/libsum/features/sum4
-rw-r--r--src/lib/libsum/sum-ast4.c120
-rw-r--r--src/lib/libsum/sum-att.c60
-rw-r--r--src/lib/libsum/sum-bsd.c48
-rw-r--r--src/lib/libsum/sum-crc.c191
-rw-r--r--src/lib/libsum/sum-lmd.c330
-rw-r--r--src/lib/libsum/sum-md5.c355
-rw-r--r--src/lib/libsum/sum-prng.c113
-rw-r--r--src/lib/libsum/sum-sha1.c323
-rw-r--r--src/lib/libsum/sum-sha2.c1229
-rw-r--r--src/lib/libsum/sum.h65
-rw-r--r--src/lib/libsum/sumlib.c376
1250 files changed, 373344 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..cf7ba4e
--- /dev/null
+++ b/README
@@ -0,0 +1,29 @@
+This is a package root directory $PACKAGEROOT. Source and binary
+packages in this directory tree are controlled by the command
+
+ bin/package
+
+Binary files may be in this directory or in the install root directory
+
+ INSTALLROOT=$PACKAGEROOT/arch/`bin/package`
+
+For more information run
+
+ bin/package help
+
+Many of the packaged commands self-document via the --man and --html
+options; those that do have no separate man page.
+
+Each package is covered by one of the license files
+
+ lib/package/LICENSES/<license>
+
+where <license> is the license type for the package. At the top
+of each license file is a URL; the license covers all software that
+refers to this URL. For details run
+
+ bin/package license [<package>]
+
+Any archives, distributions or packages made from source or
+binaries covered by license(s) must contain the corresponding
+license file(s).
diff --git a/bin/ignore b/bin/ignore
new file mode 100755
index 0000000..2e795f4
--- /dev/null
+++ b/bin/ignore
@@ -0,0 +1,24 @@
+# non-ksh script for the nmake ignore prefix
+# @(#)ignore (AT&T Research) 1992-08-11
+
+case $-:$BASH_VERSION in
+*x*:[0123456789]*) : bash set -x is broken :; set +ex ;;
+esac
+
+while :
+do case $# in
+ 0) exit 0 ;;
+ esac
+ case $1 in
+ *=*) case $RANDOM in
+ $RANDOM)`echo $1 | sed "s/\\([^=]*\\)=\\(.*\\)/eval \\1='\\2'; export \\1/"` ;;
+ *) export "$1" ;;
+ esac
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+done
+"$@"
+exit 0
diff --git a/bin/mamprobe b/bin/mamprobe
new file mode 100755
index 0000000..033c4d2
--- /dev/null
+++ b/bin/mamprobe
@@ -0,0 +1,248 @@
+### this script contains archaic constructs that work with all sh variants ###
+# mamprobe - generate MAM cc probe info
+# Glenn Fowler <gsf@research.att.com>
+
+case $-:$BASH_VERSION in
+*x*:[0123456789]*) : bash set -x is broken :; set +ex ;;
+esac
+
+command=mamprobe
+
+# check the options
+
+opt=
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) USAGE=$'
+[-?
+@(#)$Id: mamprobe (AT&T Labs Research) 2011-02-11 $
+]
+[+NAME?mamprobe - generate MAM cc probe info]
+[+DESCRIPTION?\bmamprobe\b generates MAM (make abstract machine) \bcc\b(1)
+ probe information for use by \bmamake\b(1). \acc-path\a is the
+ absolute path of the probed compiler and \ainfo-file\a is where
+ the information is placed. \ainfo-file\a is usually
+ \b$INSTALLROOT/lib/probe/C/mam/\b\ahash\a, where \ahash\a is a hash
+ of \acc-path\a. Any \ainfo-file\a directories are created if needed.
+ If \ainfo-file\a is \b-\b then the probe information is written to
+ the standard output.]
+[+?\bmamprobe\b and \bmamake\b are used in the bootstrap phase of
+ \bpackage\b(1) installation before \bnmake\b(1) is built. The
+ probed variable names are the \bnmake\b(1) names with a \bmam_\b
+ prefix, \bCC\b converted to \bcc\b, and \b.\b converted to \b_\b.
+ Additional variables are:]{
+ [+_hosttype_?the \bpackage\b(1) host type]
+ [+mam_cc_L?\b-L\b\adir\a supported]
+ [+STDCAT?command to execute for \bcat\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDCHMOD?command to execute for \bchmod\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDCMP?command to execute for \bcmp\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDCP?command to execute for \bcp\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDED?command to execute for \bed\b(1) or \bex\b(1)]
+ [+STDEDFLAGS?flags for \bSTDED\b]
+ [+STDLN?command to execute for \bln\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDMV?command to execute for \bmv\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDRM?command to execute for \brm\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+}
+[d:debug?Enable probe script debug trace.]
+
+info-file cc-path
+
+[+SEE ALSO?\bexecrate\b(1), \bpackage\b(1), \bmamake\b(1), \bnmake\b(1),
+ \bprobe\b(1)]
+'
+ while getopts -a "$command" "$USAGE" OPT
+ do case $OPT in
+ d) opt=-d ;;
+ esac
+ done
+ shift `expr $OPTIND - 1`
+ ;;
+*) while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ -) break
+ ;;
+ -d) opt=-d
+ ;;
+ -*) echo $command: $1: unknown option >&2
+ ;;
+ *) break
+ ;;
+ esac
+ set ''
+ break
+ done
+ ;;
+esac
+
+# check the args
+
+case $1 in
+-) ;;
+/*) ;;
+*) set '' ;;
+esac
+case $2 in
+/*) ;;
+*) set '' ;;
+esac
+case $# in
+0|1) echo "Usage: $command info-file cc-path" >&2; exit 2 ;;
+esac
+info=$1
+shift
+cc=$*
+
+# find the make probe script
+
+ifs=${IFS-'
+ '}
+IFS=:
+set $PATH
+IFS=$ifs
+script=lib/probe/C/make/probe
+while :
+do case $# in
+ 0) echo "$0: ../$script: probe script not found on PATH" >&2
+ exit 1
+ ;;
+ esac
+ case $1 in
+ '') continue ;;
+ esac
+ makeprobe=`echo $1 | sed 's,[^/]*$,'$script,`
+ if test -x $makeprobe
+ then break
+ fi
+ shift
+done
+
+# create the info dir if necessary
+
+case $info in
+/*) i=X$info
+ ifs=${IFS-'
+ '}
+ IFS=/
+ set $i
+ IFS=$ifs
+ while :
+ do i=$1
+ shift
+ case $i in
+ X) break ;;
+ esac
+ done
+ case $info in
+ //*) path=/ ;;
+ *) path= ;;
+ esac
+ while :
+ do case $# in
+ 0|1) break ;;
+ esac
+ comp=$1
+ shift
+ case $comp in
+ '') continue ;;
+ esac
+ path=$path/$comp
+ if test ! -d $path
+ then mkdir $path || exit
+ fi
+ done
+ ;;
+esac
+
+# generate info in a tmp file and rename when finished
+
+case $info in
+-) ;;
+*) tmp=/tmp/mam$$
+ trap "exec >/dev/null; rm -f $tmp" 0 1 2 3 15
+ exec > $tmp
+ echo "probing C language processor $cc for mam information" >&2
+ ;;
+esac
+
+echo "note generated by $0 for $cc"
+
+(
+ set '' $opt $cc
+ shift
+ . $makeprobe "$@"
+
+ case " $CC_DIALECT " in
+ *" -L "*) echo "CC.L = 1" ;;
+ esac
+
+) | sed \
+ -e '/^CC\./!d' \
+ -e 's/^CC./setv mam_cc_/' \
+ -e 's/^\([^=.]*\)\./\1_/' \
+ -e 's/^\([^=.]*\)\./\1_/' \
+ -e 's/ =//' \
+ -e 's/\$("\([^"]*\)")/\1/g' \
+ -e 's/\$(\([^)]*\))/${\1}/g' \
+ -e 's/\${CC\./${mam_cc_}/g'
+
+echo 'setv _hosttype_ ${mam_cc_HOSTTYPE}'
+
+# STD* are standard commands/flags with possible execrate(1)
+
+if (
+ed <<!
+q
+!
+) < /dev/null > /dev/null 2>&1
+then STDED=ed
+else STDED=ex
+fi
+STDEDFLAGS=-
+set STDCAT cat STDCHMOD chmod STDCMP cmp STDCP cp STDLN ln STDMV mv STDRM rm
+while :
+do case $# in
+ 0|1) break ;;
+ esac
+ p=$2
+ for d in /bin /usr/bin /usr/sbin
+ do if test -x $d/$p
+ then p=$d/$p
+ break
+ fi
+ done
+ eval $1=\$p
+ shift
+ shift
+done
+if execrate
+then for n in STDCAT STDCHMOD STDCMP STDCP STDLN STDMV STDRM
+ do eval $n=\"execrate \$$n\"
+ done
+fi
+for n in STDCAT STDCHMOD STDCMP STDCP STDED STDEDFLAGS STDLN STDMV STDRM
+do eval echo setv \$n \$$n
+done
+
+# all done
+
+case $info in
+-) ;;
+*) exec >/dev/null
+ test -f $info && rm -f $info
+ cp $tmp $info
+ chmod -w $info
+ ;;
+esac
diff --git a/bin/package b/bin/package
new file mode 100755
index 0000000..f7f4c86
--- /dev/null
+++ b/bin/package
@@ -0,0 +1,7284 @@
+USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+### this script contains archaic constructs that work with all sh variants ###
+# package - source and binary package control
+# Glenn Fowler <gsf@research.att.com>
+
+command=package
+
+case $-:$BASH_VERSION in
+*x*:[0123456789]*) : bash set -x is broken :; set +ex ;;
+esac
+
+# ksh checks -- ksh between 2007-11-05 and 2011-11-11 conflict with new -lcmd -- wea culpa
+checksh()
+{
+ egrep 'Version.*(88|1993)' $1 >/dev/null 2>&1 ||
+ $1 -c '(( .sh.version >= 20111111 ))' >/dev/null 2>&1
+}
+
+case $_AST_BIN_PACKAGE_:$SHELL:$0 in
+1:*|*:/bin/sh:*)
+ ;;
+*:*/*:*/*)
+ _AST_BIN_PACKAGE_=1 # prevent non-interactive sh .rc referencing bin/package recursion #
+ export _AST_BIN_PACKAGE_
+ if checksh $SHELL
+ then : no -lcmd conflict :
+ else case " $* " in
+ *" debug "*|*" DEBUG "*|*" show "*)
+ echo $command: $SHELL: warning: possible -lcmd conflict -- falling back to /bin/sh >&2
+ ;;
+ esac
+ SHELL=/bin/sh
+ export SHELL
+ exec $SHELL "$0" "$@"
+ fi
+ ;;
+esac
+
+LC_ALL=C
+export LC_ALL
+
+src="cmd contrib etc lib"
+use="/usr/common /exp /usr/local /usr/add-on /usr/addon /usr/tools /usr /opt"
+usr="/home"
+lib="" # nee /usr/local/lib /usr/local/shlib
+ccs="/usr/kvm /usr/ccs/bin"
+org="gnu GNU"
+makefiles="Mamfile Nmakefile nmakefile Makefile makefile"
+env="HOSTTYPE NPROC PACKAGEROOT INSTALLROOT PATH"
+checksum=md5sum
+checksum_commands="$checksum md5"
+checksum_empty="d41d8cd98f00b204e9800998ecf8427e"
+
+package_use='=$HOSTTYPE=$PACKAGEROOT=$INSTALLROOT=$EXECROOT=$CC='
+
+PACKAGE_admin_tail_timeout=${PACKAGE_admin_tail_timeout:-"1m"}
+
+CROSS=0
+
+admin_db=admin.db
+admin_env=admin.env
+admin_ditto="ditto --checksum --delete --verbose"
+admin_ditto_update=--update
+admin_ditto_skip="OFFICIAL|core|old|*.core|*.tmp|.nfs*"
+admin_list='PACKAGE.$type.lst'
+admin_ping="ping -c 1 -w 5"
+
+default_url=default.url
+MAKESKIP=${MAKESKIP:-"*[-.]*"}
+RATZ=ratz
+SED=
+TAR=tar
+TARFLAGS=xv
+TARPROBE=B
+TR=
+
+all_types='*.*|sun4' # all but sun4 match *.*
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) USAGE=$'
+[-?
+@(#)$Id: package (AT&T Research) 2012-02-29 $
+]'$USAGE_LICENSE$'
+[+NAME?package - source and binary package control]
+[+DESCRIPTION?The \bpackage\b command controls source and binary
+ packages. It is a \bsh\b(1) script coded for maximal portability. All
+ package files are in the \b$PACKAGEROOT\b directory tree.
+ \b$PACKAGEROOT\b must at minumum contain a \bbin/package\b command or a
+ \blib/package\b directory. Binary package files are in the
+ \b$INSTALLROOT\b (\b$PACKAGEROOT/arch/\b\ahosttype\a) tree, where
+ \ahosttpe\a=`\bpackage\b`. All \aactions\a but \bhost\b and \buse\b
+ require the current directory to be under \b$PACKAGEROOT\b. See
+ \bDETAILS\b for more information.]
+[+?Note that no environment variables need be set by the user;
+ \bpackage\b determines the environment based on the current working
+ directory. The \buse\b action starts a \bsh\b(1) with the environment
+ initialized. \bCC\b, \bCCFLAGS\b, \bHOSTTYPE\b and \bSHELL\b may be set
+ by explicit command argument assignments to override the defaults.]
+[+?Packages are composed of components. Each component is built and
+ installed by an \bast\b \bnmake\b(1) makefile. Each package is also
+ described by an \bnmake\b makefile that lists its components and
+ provides a content description. The package makefile and component
+ makefiles provide all the information required to read, write, build
+ and install packages.]
+[+?Package recipients only need \bsh\b(1) and \bcc\b(1) to build and
+ install source packages, and \bsh\b to install binary packages.
+ \bnmake\b and \bksh93\b are required to write new packages. An
+ \b$INSTALLROOT/bin/cc\b script may be supplied for some architectures.
+ This script supplies a reasonable set of default options for compilers
+ that accept multiple dialects or generate multiple object/executable
+ formats.]
+[+?The command arguments are composed of a sequence of words: zero or
+ more \aqualifiers\a, one \aaction\a, and zero or more action-specific
+ \aarguments\a, and zero or more \aname=value\a definitions. \apackage\a
+ names a particular package. The naming scheme is a \b-\b separated
+ hierarchy; the leftmost parts describe ownership, e.g.,
+ \bgnu-fileutils\b, \bast-base\b. If no packages are specified then all
+ packages are operated on. \boptget\b(3) documentation options are also
+ supported. The default with no arguments is \bhost type\b.]
+[+?The qualifiers are:]
+ {
+ [+authorize \aname\a?Remote authorization user name or license
+ acceptance phrase.]
+ [+debug|environment?Show environment and actions but do not
+ execute.]
+ [+flat?Collapse \b$INSTALLROOT\b { bin fun include lib } onto
+ \b$PACKAGEROOT\b.]
+ [+force?Force the action to override saved state.]
+ [+never?Run make -N and show other actions.]
+ [+only?Only operate on the specified packages.]
+ [+password \apassword\a?Remote authorization or license
+ acceptance password.]
+ [+quiet?Do not list captured action output.]
+ [+show?Run make -n and show other actions.]
+ [+verbose?Provide detailed action output.]
+ [+DEBUG?Trace the package script actions in detail.]
+ }
+[+?The actions are:]
+ {
+ [+admin\b [\ball\b]] [\bdb\b \afile\a]] [\bon\b \apattern\a]][\aaction\a ...]]?Apply
+ \aaction\a ... to the hosts listed in \afile\a. If \afile\a is
+ omitted then \badmin.db\b is assumed. The caller must have
+ \brcp\b(1) and \brsh\b(1) or \bscp\b(1) and \bssh\b(1) access
+ to the hosts. Output for \aaction\a is saved per-host in the
+ file \aaction\a\b.log/\b\ahost\a. Logs can be viewed by
+ \bpackage admin\b [\bon\b \ahost\a]] \bresults\b [\aaction\a]].
+ By default only local PACKAGEROOT hosts are selected from
+ \afile\a; \ball\b selects all hosts. \bon\b \apattern\a selects
+ only hosts matching the \b|\b separated \apattern\a. \afile\a
+ contains four types of lines. Blank lines and lines beginning
+ with \b#\b are ignored. Lines starting with \aid\a=\avalue\a
+ are variable assignments. Set admin_ping to local conventions
+ if \"'$admin_ping$'\" fails. If a package list is not specified
+ on the command line the \aaction\a applies to all packages; a
+ variable assigment \bpackage\b=\"\alist\a\" applies \aaction\a
+ to the packages in \alist\a for subsequent hosts in \afile\a.
+ The remaining line type is a host description consisting of 6
+ tab separated fields. The first 3 are mandatory; the remaining
+ 3 are updated by the \badmin\b action. \afile\a is saved in
+ \afile\a\b.old\b before update. The fields are:]
+ {
+ [+hosttype?The host type as reported by
+ \"\bpackage\b\".]
+ [+[user@]]host?The host name and optionally user name
+ for \brcp\b(1) and \brsh\b(1) access.]
+ [+[remote::[[master]]::]]]]PACKAGEROOT?The absolute remote package
+ root directory and optionally the remote protocol (rsh
+ or ssh) if the directory is on a different server than
+ the master package root directory. If
+ \blib/package/admin/'$admin_env$'\b exists under this
+ directory then it is sourced by \bsh\b(1) before
+ \aaction\a is done. If this field begins with \b-\b
+ then the host is ignored. If this field contains \b:\b
+ then \bditto\b(1) is used to sync the remote \bsrc\b
+ directory hierarchy to the local one. If [\amaster\a]]:
+ is specified then the sync is deferred to the \amaster\a
+ host. If \amaster\a is omitted (two :) then the sync is
+ disabled. These directories must exist on the remote side:
+ \blib/package\b, \bsrc/cmd\b, \bsrc/lib\b.]
+ [+date?\aYYMMDD\a of the last action.]
+ [+time?Elapsed wall time for the last action.]
+ [+M T W?The \badmin\b action \bmake\b, \btest\b and
+ \bwrite\b action error counts. A non-numeric value in
+ any of these fields disables the corresponding action.]
+ }
+ [+clean | clobber?Delete the \barch/\b\aHOSTTYPE\a hierarchy; this
+ deletes all generated files and directories for \aHOSTTYPE\a.
+ The heirarchy can be rebuilt by \bpackage make\b.]
+ [+contents\b [ \apackage\a ... ]]?List description and
+ components for \apackage\a on the standard output.]
+ [+copyright\b [ \apackage\a ... ]]?List the general copyright
+ notice(s) for \apackage\a on the standard output. Note that
+ individual components in \apackage\a may contain additional or
+ replacement notices.]
+ [+export\b [ \avariable\a ...]]?List \aname\a=\avalue\a for
+ \avariable\a, one per line. If the \bonly\b attribute is
+ specified then only the variable values are listed. If no
+ variables are specified then \b'$env$'\b are assumed.]
+ [+help\b [ \aaction\a ]]?Display help text on the standard
+ error (standard output for \aaction\a).]
+ [+host\b [ \aattribute\a ... ]]?List
+ architecture/implementation dependent host information on the
+ standard output. \btype\b is listed if no attributes are
+ specified. Information is listed on a single line in
+ \aattribute\a order. The attributes are:]
+ {
+ [+canon \aname\a?An external host type name to be
+ converted to \bpackage\b syntax.]
+ [+cpu?The number of cpus; 1 if the host is not a
+ multiprocessor.]
+ [+name?The host name.]
+ [+rating?The cpu rating in pseudo mips; the value is
+ useful useful only in comparisons with rating values of
+ other hosts. Other than a vax rating (mercifully) fixed
+ at 1, ratings can vary wildly but consistently from
+ vendor mips ratings. \bcc\b(1) may be required to
+ determine the rating.]
+ [+type?The host type, usually in the form
+ \avendor\a.\aarchitecture\a, with an optional trailing
+ -\aversion\a. The main theme is that type names within
+ a family of architectures are named in a similar,
+ predictable style. OS point release information is
+ avoided as much as possible, but vendor resistance to
+ release incompatibilities has for the most part been
+ futile.]
+ }
+ [+html\b [ \aaction\a ]]?Display html help text on the standard
+ error (standard output for \aaction\a).]
+ [+install\b [ \aarchitecture\a ... ]] \adirectory\a [ \apackage\a ... ]]?Copy
+ the package binary hierarchy to \adirectory\a. If
+ \aarchitecture\a is omitted then all architectures are
+ installed. If \bflat\b is specified then exactly one
+ \aarchitecture\a must be specified; this architecture will be
+ installed in \adirectory\a without the \barch/\b\aHOSTTYPE\a
+ directory prefixes. Otherwise each architecture will be
+ installed in a separate \barch/\b\aHOSTTYPE\a subdirectory of
+ \adirectory\a. The \aarchitecture\a \b-\b names the current
+ architecture. \adirectory\a must be an existing directory. If
+ \apackage\a is omitted then all binary packages are installed.
+ This action requires \bnmake\b.]
+ [+license\b [ \apackage\a ... ]]?List the source license(s) for
+ \apackage\a on the standard output. Note that individual
+ components in \apackage\a may contain additional or replacement
+ licenses.]
+ [+list\b [ \apackage\a ... ]]?List the name, version and
+ prerequisites for \apackage\a on the standard output.]
+ [+make\b [ \apackage\a ]] [ \aoption\a ... ]] [ \atarget\a ... ]]?Build
+ and install. The default \atarget\a is \binstall\b, which makes
+ and installs \apackage\a. If the standard output is a terminal
+ then the output is also captured in
+ \b$INSTALLROOT/lib/package/gen/make.out\b. The build is done in
+ the \b$INSTALLROOT\b directory tree viewpathed on top of the
+ \b$PACKAGEROOT\b directory tree. If \bflat\b is specified then
+ the \b$INSTALLROOT\b { bin fun include lib } directories are
+ linked to the same directories in the package root. Only one
+ architecture may be \bflat\b. Leaf directory names matching the
+ \b|\b-separated shell pattern \b$MAKESKIP\b are ignored. The
+ \bview\b action is done before making. \aoption\a operands are
+ passed to the underlying make command.]
+ [+read\b [ \apackage\a ... | \aarchive\a ... ]]?Read the named
+ package or archive(s). Must be run from the package root
+ directory. Archives are searched for in \b.\b and
+ \blib/package/tgz\b. Each package archive is read only once.
+ The file \blib/package/tgz/\b\apackage\a[.\atype\a]]\b.tim\b
+ tracks the read time. See the \bwrite\b action for archive
+ naming conventions. Text file archive member are assumed to be
+ ASCII or UTF-8 encoded.]
+ [+regress?\bdiff\b(1) the current and previous \bpackage test\b
+ results.]
+ [+release\b [ [\aCC\a]]\aYY-MM-DD\a [ [\acc\a]]\ayy-mm-dd\a ]]]] [ \apackage\a ]]?Display
+ recent changes for the date range [\aCC\a]]\aYY-MM-DD\a (up to
+ [\acc\a]]\ayy-mm-dd\a.), where \b-\b means lowest (or highest.)
+ If no dates are specified then changes for the last 4 months
+ are listed. \apackage\a may be a package or component name.]
+ [+remove\b [ \apackage\a ]]?Remove files installed for
+ \apackage\a.]
+ [+results\b [ \bfailed\b ]] [ \bpath\b ]] [ \bold\b ]] [\bmake\b | \btest\b | \bwrite\b ]]?List
+ results and interesting messages captured by the most recent
+ \bmake\b (default), \btest\b or \bwrite\b action. \bold\b
+ specifies the previous results, if any (current and previous
+ results are retained.) \b$HOME/.pkgresults\b, if it exists,
+ must contain an \begrep\b(1) expression of result lines to be
+ ignored. \bfailed\b lists failures only and \bpath\b lists the
+ results file path name only.]
+ [+setup\b [ beta ]] [ binary ]] [ source ]] [ \aarchitecture\a ... ]] [ \aurl\a ]] [ \apackage\a ... ]]?This
+ action initializes the current directory as a package root, runs the
+ \bupdate\b action to download new or out of date packages, and runs the
+ \bread\b action on those packages. If \bflat\b is specified then the
+ \b$INSTALLROOT\b { bin fun include lib } directories are linked to the
+ same directories in the package root. Only one architecture may be
+ \bflat\b. See the \bupdate\b and \bread\b action descriptions for
+ argument details.]
+ [+test\b [ \apackage\a ]]?Run the regression tests for
+ \apackage\a. If the standard output is a terminal then the
+ output is also captured in
+ \b$INSTALLROOT/lib/package/gen/test.out\b. In general a package
+ must be made before it can be tested. Components tested with
+ the \bregress\b(1) command require \bksh93\b. If \bonly\b is
+ also specified then only the listed package components are
+ tested, otherwise the closure of the components is tested.]
+ [+update\b [ beta ]] [ binary ]] [ source ]] [\aarchitecture\a ... ]] [ \aurl\a ]] [ \apackage\a ... ]]?Download
+ the latest release of the selected and required packages from \aurl\a
+ (e.g., \bhttp://www.research.att.com/sw/download\b) into the directory
+ \b$PACKAGEROOT/lib/package/tgz\b. \bbeta\b acesses beta packages;
+ download these at your own risk. If \aarchitecture\a is omitted then
+ only architectures already present in the \btgz\b directory will be
+ downloaded. If \aarchitecture\a is \b-\b then all posted architectures
+ will be downloaded. If \aurl\a matches \b*.url\b then it is interpreted
+ as a file containing shell variable assignments for \burl\b,
+ \bauthorize\b and \bpassword\b. If \aurl\a is omitted then the
+ definitions for \burl\b, \bauthorize\b and \bpassword\b in
+ \b$PACKAGEROOT/lib/package/tgz/default.url\b, if it exists, are used.
+ If \b$PACKAGEROOT/lib/package/tgz/default.url\b does not exist then it
+ is initialized with the current \burl\b, \bauthorize\b and \bpassword\b
+ values and read permission for the current user only. If \apackage\a is
+ omitted then only packages already present in the tgz directory will be
+ downloaded. If \apackage\a is \b-\b then all posted packages will be
+ downloaded. If \bsource\b and \bbinary\b are omitted then both source
+ and binary packages will be downloaded. If \bonly\b is specified then
+ only the named packages are updated; otherwise the closure of required
+ packages is updated. This action requires \bwget\b(1), \blynx\b(1),
+ \bcurl\b(1) or a shell that supports io to
+ \b/dev/tcp/\b\ahost\a/\aport\a.]
+ [+use\b [ \auid\a | \apackage\a | . [ 32 | 64 ]] | 32 | 64 | - ]] [ command ...]]?Run
+ \acommand\a, or an interactive shell if \acommand\a is omitted,
+ with the environment initialized for using the package (can you
+ say \ashared\a \alibrary\a or \adll\a without cussing?) If
+ \auid\a or \apackage\a or \a.\a is specified then it is used
+ to determine a \b$PACKAGEROOT\b, possibly different from
+ the current directory. For example, to try out bozo`s package:
+ \bpackage use bozo\b. The \buse\b action may be run from any
+ directory. If the file \b$INSTALLROOT/lib/package/profile\b is
+ readable then it is sourced to initialize the environment. 32 or 64
+ implies \b$PACKAGEROOT\b of . and specifies the target architecture
+ word size (which may be silently ignored.)]
+ [+verify\b [ \apackage\a ]]?Verify installed binary files
+ against the checksum files in
+ \b$INSTALLROOT/lib/\b\apackage\a\b/gen/*.sum\b. The checksum
+ files contain mode, user and group information. If the checksum
+ matches for a given file then the mode, user and group are
+ changed as necessary to match the checksum entry. A warning is
+ printed on the standard error for each mismatch. Requires the
+ \bast\b package \bcksum\b(1) command.]
+ [+view\b?Initialize the architecture specific viewpath
+ hierarchy. If \bflat\b is specified then the \b$INSTALLROOT\b {
+ bin fun include lib } directories are linked to the same
+ directories in the package root. Only one architecture may be
+ \bflat\b. The \bmake\b action implicitly calls this action.]
+ [+write\b [\aformat\a]] \atype\a ... [ \apackage\a ...]]?Write
+ a package archive for \apackage\a. All work is done in the
+ \b$PACKAGEROOT/lib/package\b directory. \aformat\a-specific
+ files are placed in the \aformat\a subdirectory. A
+ \apackage\a[.\atype\a]]\b.tim\b file in this directory tracks
+ the write time and prevents a package from being read in the
+ same root it was written. If more than one file is generated
+ for a particular \aformat\a then those files are placed in the
+ \aformat\a/\apackage\a subdirectory. File names in the
+ \aformat\a subdirectory will contain the package name, a
+ \ayyyy-mm-dd\a date, and for binary packages, \aHOSTTYPE\a. If
+ \apackage\a is omitted then an ordered list of previously
+ written packages is generated. If \bonly\b is specified then
+ only the named packages will be written; otherwise prerequisite
+ packages are written first. Package components must be listed
+ in \apackage\a\b.pkg\b. \aformat\a may be one of:]
+ {
+ [+cyg?Generate a \bcygwin\b package.]
+ [+exp?Generate an \bexptools\b maintainer source
+ archive and \aNPD\a file, suitable for \bexpmake\b(1)]
+ [+lcl?Generate a package archive suitable for
+ restoration into the local source tree (i.e., the
+ source is not annotated for licencing.)]
+ [+pkg?Generate a \bpkgmk\b(1) package suitable for
+ \bpkgadd\b(1).]
+ [+rpm?Generate an \brpm\b(1) package.]
+ [+tgz?Generate a \bgzip\b(1) \btar\b(1) package
+ archive. This is the default.]
+ [+tst?Generate a \btgz\b format package archive in the
+ \btst\b subdirectory. Version state files are not updated.]
+ }
+ [+?\btype\b specifies the package type which must be one of
+ \bsource\b, \bbinary\b or \bruntime\b. A source package
+ contains the source needed to build the corresponding binary
+ package. A binary package includes the libraries and headers
+ needed for compiling and linking against the public interfaces.
+ A runtime package contains the commands and required dynamic
+ libraries.]
+ [+?A package may be either a \bbase\b or \bdelta\b. A base
+ package contains a complete copy of all components. A delta
+ package contains only changes from a previous base package.
+ Delta recipients must have the \bast\b \bpax\b(1) command (in
+ the \bast-base\b package.) If neither \bbase\b nor \bdelta\b is
+ specified, then the current base is overwritten if there are no
+ deltas referring to the current base. Only the \btgz\b and
+ \blcl\b formats support \bdelta\b. If \bbase\b is specified
+ then a new base and two delta archives are generated: one delta
+ to generate the new base from the old, and one delta to
+ generate the old base from the new; the old base is then
+ removed. If \bdelta\b is specified then a new delta referring
+ to the current base is written.]
+ [+?\apackage\a\b.pkg\b may reference other packages. By default
+ a pointer to those packages is written. The recipient \bpackage
+ read\b will then check that all required packages have been
+ downloaded. If \bclosure\b is specified then the components for
+ all package references are included in the generated package.
+ This may be useful for \blcl\b and versioning.]
+ [+?All formats but \blcl\b annotate each \bsource\b file (not
+ already annotated) with a license comment as it is written to
+ the package archive using \bproto\b(1).]
+ }
+[+DETAILS?The package directory hierarchy is rooted at
+ \b$PACKAGEROOT\b. All source and binaries reside under this tree. A two
+ level viewpath is used to separate source and binaries. The top view is
+ architecture specific, the bottom view is shared source. All building
+ is done in the architecture specific view; no source view files are
+ intentionally changed. This means that many different binary
+ architectures can be made from a single copy of the source.]
+[+?Independent \b$PACKAGEROOT\b hierarchies can be combined by
+ appending \b$INSTALLROOT:$PACKAGEROOT\b pairs to \bVPATH\b. The
+ \bVPATH\b viewing order is from left to right. Each \b$PACKAGEROOT\b
+ must have a \b$PACKAGEROOT/lib/package\b directory.]
+[+?Each package contains one or more components. Component source for
+ the \afoo\a command is in \b$PACKAGEROOT/src/cmd/\b\afoo\a, and source
+ for the \abar\a library is in \b$PACKAGEROOT/src/lib/lib\b\abar\a. This
+ naming is for convenience only; the underlying makefiles handle
+ inter-component build order. The \bINIT\b component, which contains
+ generic package support files, is always made first, then the
+ components named \bINIT\b*, then the component order determined by the
+ closure of component makefile dependencies.]
+[+?\b$PACKAGEROOT/lib/package\b contains package specific files. The
+ package naming convention is \agroup\a[-\apart\a]]; e.g., \bast-base\b,
+ \bgnu-fileutils\b. The *\b.pkg\b files are ast \bnmake\b(1) makefiles
+ that contain the package name, package components, references to other
+ packages, and a short package description. *\b.pkg\b files are used by
+ \bpackage write\b to generate new source and binary packages.]
+[+?\b$PACKAGEROOT/lib/package/\b\agroup\a\b.lic\b files contain license
+ information that is used by the \bast\b \bproto\b(1) and \bnmake\b(1)
+ commands to generate source and binary license strings. \agroup\a is
+ determined by the first \b:PACKAGE:\b operator name listed in the
+ component \bnmake\b makefile. \agroup\a\b.lic\b files are part of the
+ licensing documentation. Each component may have its own \bLICENSE\b file
+ that overrides the \agroup\a\b.lic\b file. The full text of the licenses
+ are in the \b$PACKAGEROOT/lib/package/LICENSES\b and
+ \b$INSTALLROOT/lib/package/LICENSES\b directories.]
+[+?A few files are generated in \b$PACKAGEROOT/lib/package/gen\b and
+ \b$INSTALLROOT/lib/package/gen\b. \apackage\a\b.ver\b contains one line
+ consisting of \apackage version release\a \b1\b for the most recent
+ instance of \apackage\a read into \b$PACKAGEROOT\b, where \apackage\a
+ is the package name, \aversion\a is the \aYYYY-MM-DD\a base version,
+ and \arelease\a is \aversion\a for the base release or \aYYYY-MM-DD\a
+ for delta releases. \apackage\a\b.req\b contains *\b.ver\b entries for
+ the packages required by \apackage\a, except that the fourth field is
+ \b0\b instead of \b1\b. All packages except \bINIT\b require the
+ \bINIT\b package. A simple sort of \apackage\a\b.pkg\b and *\b.ver\b
+ determines if the required package have been read in. Finally,
+ \apackage\a\b.README\b and \apackage\a\a.html\b contain the README text
+ for \apackage\a and all its components. Included are all changes added
+ to the component \bRELEASE\b, \bCHANGES\b or \bChangeLog\b files dated
+ since the two most recent base releases. Component \bRELEASE\b files
+ contain tag lines of the form [\aYY\a]]\aYY-MM-DD\a [ \atext\a ]] (or
+ \bdate\b(1) format dates) followed by README text, in reverse
+ chronological order (newer entries at the top of the file.) \bpackage
+ release\b lists this information, and \bpackage contents ...\b lists
+ the descriptions and components.]
+[+?\b$HOSTYPE\b names the current binary architecture and is determined
+ by the output of \bpackage\b (no arguments.) The \b$HOSTTYPE\b naming
+ scheme is used to separate incompatible executable and object formats.
+ All architecture specific binaries are placed under \b$INSTALLROOT\b
+ (\b$PACKAGEROOT/arch/$HOSTTYPE\b.) There are a few places that match
+ against \b$HOSTTYPE\b when making binaries; these are limited to
+ makefile compiler workarounds, e.g., if \b$HOSTTYPE\b matches \bhp.*\b
+ then turn off the optimizer for these objects. All other architecture
+ dependent logic is handled either by the \bast\b \biffe\b(1) command or
+ by component specific configure scripts. Explicit \b$HOSTYPE\b
+ values matching *,*cc*[,-*,...]] optionally set the default \bCC\b and
+ \bCCFLAGS\b. This is handy for build farms that support different
+ compilers on the same architecture.]
+[+?Each component contains an \bast\b \bnmake\b(1) makefile (either
+ \bNmakefile\b or \bMakefile\b) and a \bMAM\b (make abstract machine)
+ file (\bMamfile\b.) A Mamfile contains a portable makefile description
+ that is used by \bmamake\b(1) to simulate \bnmake\b. Currently there is
+ no support for old-make/gnu-make makefiles; if the binaries are just
+ being built then \bmamake\b will suffice; if source or makefile
+ modifications are anticipated then \bnmake\b (in the \bast-base\b
+ package) should be used. Mamfiles are automatically generated by
+ \bpackage write\b.]
+[+?Most component C source is prototyped. If \b$CC\b (default value
+ \bcc\b) is not a prototyping C compiler then \bpackage make\b runs
+ \bproto\b(1) on portions of the \b$PACKAGEROOT/src\b tree and places
+ the converted output files in the \b$PACKAGEROOT/proto/src\b tree.
+ Converted files are then viewpathed over the original source.
+ \bproto\b(1) converts an ANSI C subset to code that is compatible with
+ K&R, ANSI, and C++ dialects.]
+[+?All scripts and commands under \b$PACKAGEROOT\b use \b$PATH\b
+ relative pathnames (via the \bast\b \bpathpath\b(3) function); there
+ are no imbedded absolute pathnames. This means that binaries generated
+ under \b$PACKAGEROOT\b may be copied to a different root; users need
+ only change their \b$PATH\b variable to reference the new installation
+ root \bbin\b directory. \bpackage install\b installs binary packages in
+ a new \b$INSTALLROOT\b.]
+
+[ qualifier ... ] [ action ] [ arg ... ] [ n=v ... ]
+
+[+SEE ALSO?\bautoconfig\b(1), \bcksum\b(1), \bexecrate\b(1), \bexpmake\b(1),
+ \bgzip\b(1), \bmake\b(1), \bmamake\b(1), \bnmake\b(1), \bpax\b(1),
+ \bpkgadd\b(1), \bpkgmk\b(1), \bproto\b(1), \bratz\b(1), \brpm\b(1),
+ \bsh\b(1), \btar\b(1), \boptget\b(3)]
+'
+ case $* in
+ help) set -- --man ;;
+ esac
+ while getopts -a $command "$USAGE" OPT
+ do :
+ done
+ shift $OPTIND-1
+ ;;
+esac
+
+# check the args
+
+case $AR in
+'') AR=ar ;;
+esac
+case $CC in
+'') CC=cc ;;
+esac
+case $LD in
+'') LD=ld ;;
+esac
+case $NM in
+'') NM=nm ;;
+esac
+
+action=
+admin_all=1
+admin_on=
+authorize=
+bit=
+exec=
+flat=0
+force=0
+global=
+hi=
+html=0
+ifs=${IFS-'
+ '}
+lo=
+make=
+makeflags='-k -K'
+nmakeflags=
+nmakesep=
+nl="
+"
+noexec=
+only=0
+output=
+package_src=
+password=
+quiet=0
+show=:
+tab=" "
+verbose=0
+AUTHORIZE=
+DEBUG=
+HURL=
+PROTOROOT=-
+SHELLMAGIC=-
+
+unset FIGNORE BINDIR DLLDIR ETCDIR FUNDIR INCLUDEDIR LIBDIR LOCALEDIR MANDIR SHAREDIR 2>/dev/null || true
+
+while :
+do case $# in
+ 0) set host type ;;
+ esac
+ case $1 in
+ admin|clean|clobber|contents|copyright|export|host|install|license|list|make|read|regress|release|remove|results|setup|test|update|use|verify|view|write|TEST)
+ action=$1
+ shift
+ break
+ ;;
+ authorize)
+ case $# in
+ 1) echo $command: $1: authorization user name argument expected >&2; exit 1 ;;
+ esac
+ shift
+ authorize=$1
+ shift
+ continue
+ ;;
+ debug|environment)
+ exec=echo make=echo show=echo
+ ;;
+ flat) flat=1
+ ;;
+ force) force=1
+ ;;
+ never) exec=echo noexec=-N
+ ;;
+ only) only=1
+ ;;
+ password)
+ case $# in
+ 1) echo $command: $1: authorization password argument expected >&2; exit 1 ;;
+ esac
+ shift
+ password=$1
+ shift
+ continue
+ ;;
+ quiet) quiet=1
+ ;;
+ show) exec=echo noexec=-n
+ ;;
+ verbose)verbose=1
+ ;;
+ DEBUG) DEBUG=1
+ PS4='+$LINENO:$SECONDS+ '
+ set -x
+ ;;
+ help|HELP|html|man|--[?m]*)
+ case $1 in
+ help) code=0
+ case $2 in
+ '') exec 1>&2 ;;
+ esac
+ ;;
+ html) code=0 html=1
+ ;;
+ *) code=2
+ exec 1>&2
+ ;;
+ esac
+ case $html in
+ 1) bO="<HTML>
+<HEAD>
+<TITLE>$2 package installation instructions</TITLE>
+<HEAD>
+<BODY bgcolor=white link=teal vlink=dimgray>"
+ eO='</BODY>
+</HTML>'
+ bH="<CENTER><H3><FONT face=courier color=red>"
+ eH='</FONT></H3></CENTER>'
+ bP='<P>'
+ bL='<P><TABLE cellpadding=0 cellspacing=2>'
+ bL2='<P><TABLE border=0 cellpadding=0 cellspacing=2>'
+ eL='</TABLE><P>'
+ bT='<TR><TD align=right valign=top><B>'
+ bD='</B></TD><TD align=left>' eD='</TD></TR>'
+ bB='<B>' eB='</B>'
+ bI='<I>' eI='</I>'
+ bX='<PRE>' eX='</PRE>'
+ bF='<TT>' eF='</TT>'
+ Camp='&amp;'
+ Mcurl='<A href=../../man/man1/curl.html>curl</A>(1)'
+ Mdate='<A href=../../man/man1/date.html>date</A>(1)'
+ Mfile='<A href=../../man/man1/file.html>file</A>(1)'
+ Mgunzip='<A href=../../man/man1/gzip.html>gunzip</A>(1)'
+ Mhurl='<A href=../../man/man1/hurl.html>hurl</A>(1)'
+ Mlynx='<A href=../../man/man1/lynx.html>lynx</A>(1)'
+ Mnmake='<A href=../../man/man1/nmake.html>nmake</A>(1)'
+ Mpackage='<A href=../../man/man1/package.html>package</A>(1)'
+ Mproto='<A href=../../man/man1/proto.html>proto</A>(1)'
+ Mratz='<A href=../../man/man1/ratz.html>ratz</A>'
+ Mtar='<A href=../../man/man1/tar.html>tar</A>(1)'
+ Mwget='<A href=../../man/man1/wget.html>wget</A>(1)'
+ ;;
+ *) bO='' eO=''
+ bH='' eH=':'
+ bP=''
+ bL='' eL=''
+ bL2=''
+ bT=' '
+ bD=' ' eD=''
+ bB='' eB=''
+ bI='' eI=''
+ bX='' eX=''
+ bF='"' eF='"'
+ Camp='&'
+ Mcurl='curl(1)'
+ Mdate='date(1)'
+ Mfile='file(1)'
+ Mgunzip='gunzip(1)'
+ Mhurl='hurl(1)'
+ Mlynx='lynx(1)'
+ Mnmake='nmake(1)'
+ Mpackage='package(1)'
+ Mproto='proto(1)'
+ Mratz='ratz'
+ Mtar='tar(1)'
+ Mwget='wget(1)'
+ ;;
+ esac
+ case $2 in
+ binary) echo "${bO}
+${bH}Binary Package Installation Instructions${eH}
+${bL}
+${bT}(1)${bD}Do not install packages as ${bI}root/super-user${eI}. Although some components may
+ have setuid executables, few must be owned by ${bI}root${eI}. These are best
+ changed manually when the security implications are understood.${eD}
+${bT}(2)${bD}Choose a package root directory and cd to it. This will be a local work
+ area for all packages.${eD}
+${bT}(3)${bD}These instructions bypass the ${bI}click to download${eI} package links on the
+ download site. If you already clicked, or if your system does not have
+ ${Mcurl}, ${Mhurl}, ${Mlynx} or ${Mwget} then use the alternate instructions
+ for (3),(4),(5) in plan ${bB}B${eB} below. Plan ${bB}B${eB} installs the ${Mhurl}
+ script which works with ksh and modern bash. The top level URL is:${bX}
+ URL=http://www.research.att.com/sw/download${eX}${eD}
+${bT}(4)${bD}If the ${bB}bin/package${eB} script does not exist then run:${bX}
+ test -d bin || mkdir bin
+ url=\$URL/package
+ (wget -O bin/package \$url||curl -L \$url||hurl \$url) > bin/package
+ chmod +x bin/package${eX}${eD}
+${bT}(5)${bD}Determine the list of package names you want from the download site, then
+ use the ${Mpackage} command to do the actual download:${bX}
+ bin/package authorize \"${bI}NAME${eI}\" password \"${bI}PASSWORD${eI}\" \\
+ setup binary \$URL ${bI}PACKAGE${eI} ...${eX}
+ (Refer to the ${bB}AUTHORIZATION${eB} paragraph on the main download page for
+ ${bI}NAME${eI}/${bI}PASSWORD${eI} details.) This downloads the closure of the latest
+ binary package(s); covered and up-to-date packages are not downloaded again unless
+ ${bB}package force ...${eB} is specified. Package content is verified using ${bB}${checksum}${eB}.
+ If the package root will contain only one architecture then you can install in ${bB}bin${eB} and
+ ${bB}lib${eB} instead of ${bB}arch/${eB}${bI}HOSTTYPE${eI}${bB}/bin${eB} and ${bB}arch/${eB}${bI}HOSTTYPE${eI}${bB}/lib${eB} by running this
+ instead:${bX}
+ bin/package authorize \"${bI}NAME${eI}\" password \"${bI}PASSWORD${eI}\" \\
+ flat setup binary \$URL ${bB}PACKAGE${eB} ...${eX}
+ To update the same packages from the same URL run:${bX}
+ bin/package setup binary${eX}${eD}
+${bT}(6)${bD}The packaged binaries are position independent, i.e., they do not
+ contain hard-coded paths. However, commands with related files, like
+ ${Mfile} and ${Mnmake}, require the path of the bin directory to be
+ exported in ${bB}PATH${eb}.${eD}
+${bT}(7)${bD}You can run the binaries directly from the package root, or you can
+ install them in a public root (requires the ${bI}AT${Camp}T${eI} ${Mnmake} command):${bX}
+ bin/package flat install ${bI}DIRECTORY PACKAGE${eI}${eX}
+ This will install in ${bI}DIRECTORY${eI}${bB}/bin${eB} and ${bI}DIRECTORY${eI}${bB}/lib${eB}. If you want to
+ preserve the ${bB}arch/${eB}${bI}HOSTTYPE${eI} hierarchy under ${bI}DIRECTORY${eI} then omit the
+ ${bB}flat${eB} argument. If you don't have ${Mnmake} then the following will do a
+ flat install:${bX}
+ cd \$INSTALLROOT
+ cp -p -r bin lib include ${bI}DIRECTORY${eI}${eX}${eD}
+${bT}(8)${bD}To summarize, after the first time, the download cycle for the latest
+ binary release is:${bX}
+ bin/package setup binary${eX}${eD}${eL}
+
+${bH}Binary Package Installation Instructions -- Plan B${eH}
+${bL}
+${bT}(3)${bD}Create the subdirectory ${bB}lib/package/tgz${eB} and download all package archives
+ into that directory.${eD}
+${bT}(4)${bD}If the ${bB}bin/package${eB} script does not exist then manually read the ${bB}INIT${eB}
+ binary package:${bX}
+ gunzip < lib/package/tgz/INIT.${bI}YYYY-MM-DD.HOSTTYPE${eI}.tgz |
+ ${TAR} ${TARFLAGS}f -${eX}
+ Note that some browsers automatically unzip downloaded without warning.
+ If the gunzip fails try:
+ ${TAR} ${TARFLAGS}f -${eX} lib/package/tgz/INIT.${bI}YYYY-MM-DD.HOSTTYPE${eI}.tgz
+ If your system does not have ${Mtar} or ${Mgunzip} then download the ${Mratz}
+ binary package:${bX}
+ mkdir bin
+ cp lib/package/tgz/ratz.${bI}YYYY-MM-DD.HOSTTYPE${eI}.exe bin/ratz
+ chmod +x bin/ratz
+ bin/ratz -lm < lib/package/tgz/INIT.${bI}YYYY-MM-DD/HOSTTYPE${eI}.tgz
+${bT}(5)${bD}Read all unread package archive(s):${bX}
+ bin/package read${eX}
+ Both source and binary packages will be read by this step.${eD}${eL}${eO}"
+ ;;
+ intro) echo "${bO}
+${bH}Package Hierarchy Details${eH}
+${bP}
+The package directory hierarchy is rooted at ${bB}\$PACKAGEROOT${eB}. All source and
+binaries reside under this tree. A two level viewpath is used to separate
+source and binaries. The top view is architecture specific, the bottom view
+is shared source. All building is done in the architecture specific view;
+no source view files are intentionally changed. This means that many
+different binary architectures can be made from a single copy of the source.
+${bP}
+Each package contains one or more components. Component source for the ${bI}FOO${eI}
+command is in ${bB}\$PACKAGEROOT/src/cmd/${eB}${bI}FOO${eI}, and source for the ${bI}BAR${eI} library is
+in ${bB}\$PACKAGEROOT/src/lib/lib${eB}${bI}BAR${eI}. This naming is for convenience only; the
+underlying makefiles handle inter-component build order. The ${bB}INIT${eB} component,
+which contains generic package support files, is always made first, then the
+components named ${bB}INIT${eB}*, then the order determined by the closure of component
+makefile dependencies.
+${bP}
+${bB}\$PACKAGEROOT/lib/package${eB} contains package specific files. The package naming
+convention is ${bI}GROUP${eI}[${bI}-PART${eI}]; e.g., ${bB}ast-base${eB}, ${bB}gnu-fileutils${eB}. The *${bB}.pkg${eB} files
+are ${bB}ast${eB} ${Mnmake} makefiles that contain the package name, package components,
+references to other packages, and a short package description. *${bB}.pkg${eB} files
+are used by ${bF}package write${eF} to generate new source and binary packages.
+${bP}
+${bB}\$PACKAGEROOT/lib/package/${eB}${bI}GROUP${eI}${bB}.lic${eB} files contain license information that
+is used by the ${bB}ast${eB} ${Mproto} and ${Mnmake} commands to generate source and
+binary license strings. ${bI}GROUP${eI} is determined by the first ${bB}:PACKAGE:${eB} operator
+name listed in the component ${bB}nmake${eB} makefile. ${bI}GROUP${eI}${bB}.lic${eB} files are part of the
+licensing documentation. Each component may have its own ${bB}LICENSE${eB} file that
+overrides the ${bI}GROUP${eI}${bB}.lic${eB} file. The full text of the licenses are in the
+${bB}\$PACKAGEROOT/lib/package/LICENSES${eB} and ${bB}\$INSTALLROOT/lib/package/LICENSES${eB}
+directories.
+${bP}
+A few files are generated in ${bB}\$PACKAGEROOT/lib/package/gen${eB} and
+${bB}\$INSTALLROOT/lib/package/gen${eB}. ${bI}PACKAGE${eI}${bB}.ver${eB} contains one line consisting of${bX}
+ ${bI}PACKAGE VERSION RELEASE${eI} 1${eX}
+for the most recent instance of ${bI}PACKAGE${eI} read into ${bB}\$PACKAGEROOT${eB}, where
+${bI}PACKAGE${eI} is the package name, ${bI}VERSION${eI} is the ${bI}YYYY-MM-DD${eI} base version,
+and ${bI}RELEASE${eI} is ${bI}VERSION${eI} for the base release or ${bI}YYYY-MM-DD${eI} for delta releases.
+${bI}PACKAGE${eI}${bB}.req${eB} contains *${bB}.ver${eB} entries for the packages required by
+${bI}PACKAGE${eI}, except that the fourth field is 0 instead of 1. All packages
+except ${bB}INIT${eB} and ${Mratz} require the ${bB}INIT${eB} package. A simple sort of ${bI}PACKAGE${eI}${bB}.pkg${eB}
+and *${bB}.ver${eB} determines if the required package have been read in. Finally,
+${bI}PACKAGE${eI}${bB}.README${eB} contains the ${bB}README${eB} text for ${bI}PACKAGE${eI} and all its
+components. Included are all changes added to the component ${bB}RELEASE${eB},
+${bB}CHANGES${eB} or ${bB}ChangeLog${eB} files dated since the two most recent base
+releases. Component ${bB}RELEASE${eB} files contain tag lines of the form
+[${bI}CC${eI}]${bI}YY-MM-DD${eI} [ ${bI}TEXT${eI} ] (or ${Mdate} format dates) followed by README
+text, in reverse chronological order (newer entries at the top of the
+file.) ${bF}package release${eF} generates this information, and
+${bF}package contents ...${eF} lists the descriptions and components.
+${bP}
+${bB}\$HOSTYPE${eB} names the current binary architecture and is determined by the
+output of ${bF}package${eF} (no arguments.) The ${bB}\$HOSTTYPE${eB} naming scheme is used
+to separate incompatible executable and object formats. All architecture
+specific binaries are placed under ${bB}\$INSTALLROOT${eB} (${bB}\$PACKAGEROOT/arch/\$HOSTTYPE${eB}.)
+There are a few places that match against ${bB}\$HOSTTYPE${eB} when making binaries; these
+are limited to makefile compiler workarounds, e.g., if ${bB}\$HOSTTYPE${eB} matches
+'hp.*' then turn off the optimizer for these objects. All other architecture
+dependent logic is handled either by ${bB}\$INSTALLROOT/bin/iffe${eB} or by component
+specific configure scripts. Explicit ${bB}\$HOSTYPE${eB} values matching *,*cc*[,-*,...]
+optionally set the default ${bB}CC${eB} and ${bB}CCFLAGS${eB}. This is handy for build
+farms that support different compilers on the same architecture.
+${bP}
+Each component contains an ${bB}ast${eB} ${Mnmake} makefile (either ${bB}Nmakefile${eB} or ${bB}Makefile${eB})
+and a ${bI}MAM${eI} (make abstract machine) file (${bB}Mamfile${eB}.) A Mamfile contains a portable
+makefile description that is used by ${bB}\$INSTALLROOT/bin/mamake${eB} to simulate
+${bB}nmake${eB}. Currently there is no support for old-make/gnu-make makefiles; if
+the binaries are just being built then ${bB}mamake${eB} will suffice; if source or
+makefile modifications are anticipated then ${bB}nmake${eB} (from the ${bB}ast-open${eB} or
+${bB}ast-base${eB} package) should be used. Mamfiles are automatically generated by
+${bF}package write${eF}.
+${bP}
+Most component C source is prototyped. If ${bB}\$CC${eB} (default value ${bB}cc${eB}) is not a
+prototyping C compiler then ${bF}package make${eF} runs ${Mproto} on portions of the
+${bB}\$PACKAGEROOT/src${eB} tree and places the converted output files in the
+${bB}\$PACKAGEROOT/proto/src${eB} tree. Converted files are then viewpathed over the
+original source. The ${bB}ast${eB} ${Mproto} command converts an ANSI C subset to code
+that is compatible with K&R, ANSI, and C++ dialects.
+${bP}
+All scripts and commands under ${bB}\$PACKAGEROOT${eB} use ${bB}\$PATH${eB} relative pathnames;
+there are no imbedded absolute pathnames. This means that binaries generated
+under ${bB}\$PACKAGEROOT${eB} may be copied to a different root; users need only change
+their ${bB}\$PATH${eB} variable to reference the new instalation root bin directory.
+${bF}package install${eF} installs binary packages in a new ${bB}\$INSTALLROOT${eB}.
+${eO}"
+ ;;
+ source) echo "${bO}
+${bH}Source Package Installation Instructions${eH}
+${bL}
+${bT}(1)${bD}Do not install packages as ${bI}root/super-user${eI}. Although some components may
+ have setuid executables, few must be owned by ${bI}root${eI}. These are best
+ changed manually when the security implications are understood.${eD}
+${bT}(2)${bD}Choose a package root directory and cd to it. This will be a local work
+ area for all packages.
+${bT}(3)${bD}These instructions bypass the ${bI}click to download${eI} package links on the
+ download site. If you already clicked, or if your system does not have
+ ${Mcurl}, ${Mhurl}, ${Mlynx} or ${Mwget} then use the alternate instructions
+ for (3),(4),(5) in plan ${bB}B${eB} below. Plan ${bB}B${eB} installs the ${Mhurl}
+ script which works with ksh and modern bash. The top level URL is:${bX}
+ URL=http://www.research.att.com/sw/download${eX}${eD}
+${bT}(4)${bD}If the ${bB}bin/package${eB} script does not exist then run:${bX}
+ test -d bin || mkdir bin
+ url=\$URL/package
+ (wget -O bin/package \$url||curl -L \$url||hurl \$url) > bin/package
+ chmod +x bin/package${eX}${eD}
+${bT}(5)${bD}Determine the list of package names you want from the download site, then
+ use the ${Mpackage} command to do the actual download:${bX}
+ bin/package authorize \"${bI}NAME${eI}\" password \"${bI}PASSWORD${eI}\" \\
+ setup source \$URL ${bB}PACKAGE${eB} ...${eX}
+ (Refer to the ${bB}AUTHORIZATION${eB} paragraph on the main download page for
+ ${bI}NAME${eI}/${bI}PASSWORD${eI} details.) This downloads the closure of the latest
+ source package(s); covered and up-to-date packages are not downloaded again unless
+ ${bB}package force ...${eB} is specified. Package content is verified using ${bB}${checksum}${eB}.
+ If the package root will contain only one architecture then you can install in ${bB}bin${eB} and
+ ${bB}lib${eB} instead of ${bB}arch/${eB}${bI}HOSTTYPE${eI}${bB}/bin${eB} and ${bB}arch/${eB}${bI}HOSTTYPE${eI}${bB}/lib${eB} by running this
+ instead:${bX}
+ bin/package authorize \"${bI}NAME${eI}\" password \"${bI}PASSWORD${eI}\" \\
+ flat setup source \$URL ${bB}PACKAGE${eB} ...${eX}
+ To update the same packages from the same URL run:${bX}
+ bin/package setup source${eX}${eD}
+${bT}(6)${bD}Build and install; all generated files are placed under ${bB}arch/${eB}${bI}HOSTTYPE${eI}
+ (${bB}\$INSTALLROOT${eB}), where ${bI}HOSTTYPE${eI} is the output of ${bB}bin/package${eB} (with no
+ arguments.) ${bI}name=value${eI} arguments are supported; ${bB}CC${eB} and ${bB}debug=1${eB} (compile
+ with -g instead of -O) are likely candidates. The output is written to
+ the terminal and captured in ${bB}\$INSTALLROOT/lib/package/gen/make.out${eB}:${bX}
+ bin/package make${eX}${eD}
+${bT}(7)${bD}List make results and interesting errors:${bX}
+ bin/package results${eX}
+ Run the regression tests:${bX}
+ bin/package test${eX}
+ List test results and errors:${bX}
+ bin/package results test${eX}${eD}
+${bT}(8)${bD}The generated binaries are position independent, i.e., they do not
+ contain hard-coded paths. However, commands with related files, like
+ ${Mfile} and ${Mnmake}, require the path of the bin directory to be
+ exported in ${bB}PATH${eb}.${eD}
+${bT}(9)${bD}You can run the binaries directly from the package root, or you can
+ install them in a public root after you are satisfied with the make and
+ test actions (requires the ${bI}AT${Camp}T${eI} ${Mnmake} command):${bX}
+ bin/package flat install ${bI}DIRECTORY PACKAGE${eI}${eX}
+ This will install in ${bI}DIRECTORY${eI}${bB}/bin${eB} and ${bI}DIRECTORY${eI}${bB}/lib${eB}. If you want to
+ preserve the ${bB}arch/${eB}${bI}HOSTTYPE${eI} hierarchy under ${bI}DIRECTORY${eI} then omit the
+ ${bB}flat${eB} argument. If you don't have ${Mnmake} then the following will do a
+ flat install:${bX}
+ cd \$INSTALLROOT
+ cp -p -r bin lib include ${bI}DIRECTORY${eI}${eX}${eD}
+${bT}(10)${bD}To summarize, after the first time the download, build, and test cycle
+ for the latest source release is:${bX}
+ bin/package setup source
+ bin/package make
+ bin/package test${eX}${eD}${eL}
+
+${bH}Source Package Installation Instructions -- Plan B${eH}
+${bL}
+${bT}(3)${bD}Create the subdirectory ${bB}lib/package/tgz${eB} and download all package archives
+ into that directory.${eD}
+${bT}(4)${bD}If the ${bB}bin/package${eB} script does not exist then manually read the ${bB}INIT${eB}
+ source package:${bX}
+ gunzip < lib/package/tgz/INIT.${bI}YYYY-MM-DD${eI}.tgz | ${TAR} ${TARFLAGS}f -${eX}
+ Note that some browsers automatically unzip downloaded without warning.
+ If the gunzip fails try:
+ ${TAR} ${TARFLAGS}f -${eX} lib/package/tgz/INIT.${bI}YYYY-MM-DD${eI}.tgz
+ If your system does not have ${Mtar} or ${Mgunzip} then download the ${Mratz}
+ source package, compile it, and manually read the ${bB}INIT${eB}
+ source package:${bX}
+ mkdir bin
+ cp lib/package/tgz/ratz.${bI}YYYY-MM-DD${eI}.c lib/package/tgz/ratz.c
+ cc -o bin/ratz lib/package/tgz/ratz.c
+ bin/ratz -lm < lib/package/tgz/INIT.${bI}YYYY-MM-DD${eI}.tgz
+${bT}(5)${bD}Read all unread package archive(s):${bX}
+ bin/package read${eX}
+ Both source and binary packages will be read by this step.${eD}${eL}${eO}"
+ ;;
+ *) echo "Usage: $command [ qualifier ... ] [ action ] [ arg ... ] [ n=v ... ]
+
+ The $command command controls source and binary packages. It must be run
+ within the package root directory tree. See \"$command help intro\" for
+ details. In the following, PACKAGE names either a package or a component
+ within a package; if omitted, all packages are operated on. The default
+ action is \"host type\".
+
+ qualifier:
+ authorize NAME Remote authorization name or license acceptance phrase.
+ debug|environment Show environment and actions; do not execute.
+ flat Collapse \$INSTALLROOT { bin fun include lib } onto \$PACKAGEROOT.
+ force Force the action to override saved state.
+ never Run make -N; otherwise show other actions.
+ only Only operate on the specified packages.
+ password PASSWORD Remote authorization or license acceptance password.
+ quiet Do not list captured make and test action output.
+ show Run make -n; otherwise show other actions.
+ DEBUG Trace the package script actions in detail for debugging.
+ action:
+ admin [ all ] [ db FILE ] [ on PATTERN ] [ action ... ]
+ Apply ACTION ... to the hosts listed in FILE. If FILE is
+ omitted then "admin.db" is assumed. The caller must have rcp(1)
+ and rsh(1) or scp(1) and ssh(1) access to the hosts. Output
+ for the action is saved per-host in ACTION.log/HOST. Logs
+ can be viewed by \"package admin [on HOST] results [ACTION]\".
+ By default only local PACKAGEROOT hosts are selected from FILE;
+ \"all\" selects all hosts. \"on PATTERN\" selects only
+ hosts matching the | separated PATTERN. FILE contains four
+ types of lines. Blank lines and lines beginning with # are
+ ignored. Lines starting with id=value are variable assignments.
+ Set admin_ping to local conventions if \"$admin_ping\" fails.
+ If a package list is not specified on the command line the
+ action applies to all packages; a variable assigment
+ package=list applies action to the packages in list for
+ subsequent hosts in FILE. The remaining line type is a host
+ description consisting of 6 tab separated fields. The first 3
+ are mandatory; the remaining 3 are updated by the admin action:
+ hosttype
+ The host type as reported by package.
+ [user@]host
+ The host name and optionally user name for rcp(1)
+ and rsh(1) access.
+ [remote:[[master]:]]PACKAGEROOT
+ The absolute remote package root directory and
+ optionally the remote prorocol (rsh or ssh) if
+ the directory is on a different server than the
+ master package root directory. If
+ lib/package/admin/$admin_env exists under
+ this directory then it is sourced by sh(1)
+ before ACTION is done. If this field begins with -
+ then the host is ignored. If this field contains
+ : then ditto(1) is used to sync the remote src
+ directory hierarchy to the local one. If [master]:
+ is specified then the sync is deferred to the
+ master host. If master is omitted (two :) then
+ the sync is disabled. These directories must exist
+ on the remote side: lib/package, src/cmd, src/lib.
+ date YYMMDD of the last action.
+ date Elapsed wall time of the last action.
+ M T W The admin action make, test and write action error
+ counts. A non-numeric value in any of these fields
+ disables the corresponding action.
+ clean | clobber
+ Delete the arch/HOSTTYPE hierarchy; this deletes all generated
+ files and directories for HOSTTYPE. The heirarchy can be rebuilt
+ by package make.]
+ contents [ package ... ]
+ List description and components for PACKAGE on the standard
+ output.
+ copyright [ package ... ]
+ List the general copyright notice(s) for PACKAGE on the
+ standard output. Note that individual components in PACKAGE
+ may contain additional or replacement notices.
+ export [ VARIABLE ... ]
+ List NAME=VALUE for each VARIABLE, one per line. If the
+ \"only\" attribute is specified then only the variable
+ values are listed. If no variables are specified then
+ $env are assumed.
+ help [ ACTION ]
+ Display help text on the standard error [ standard output
+ for ACTION ].
+ host [ canon cpu name rating type ... ]
+ List architecture/implementation dependent host information
+ on the standard output. type is listed if no attributes are
+ specified. Information is listed on a single line in attributes
+ order. The attributes are:
+ canon The next argument is a host type name to be
+ converted to package syntax.
+ cpu The number of cpus; 1 if the host is not a
+ multiprocessor.
+ name The host name.
+ rating The cpu rating in pseudo mips; the value is useful
+ useful only in comparisons with rating values of
+ other hosts. Other than a vax rating fixed at 1,
+ ratings can vary wildly but consistently from
+ vendor mips ratings. cc(1) may be required to
+ determine the rating.
+ type The host type, usually of the form
+ vendor.architecture, with an optional trailing
+ -version. The main theme is that type names within
+ a family of architectures are named in a similar,
+ predictable style. Os point release information is
+ avoided as much as possible, but vendor resistance
+ to release incompatibilities has for the most part
+ been futile.
+ html [ ACTION ]
+ Display html help text on the standard error [ standard output
+ for ACTION ].
+ install [ ARCHITECTURE ... ] DIR [ PACKAGE ... ]
+ Copy the package binary hierarchy to DIR. If ARCHITECTURE is
+ omitted then all architectures are installed. If the \"flat\"
+ attribute is specified then exactly one ARCHITECTURE must be
+ specified; this architecture will be installed in DIR without
+ the \"arch/HOSTTYPE\" directory prefixes. Otherwise each
+ architecture will be installed in a separate \"arch/HOSTTYPE\"
+ subdirectory of DIR. The ARCHITECTURE - names the current
+ architecture. DIR must be an existing directory. If PACKAGE
+ is omitted then all binary packages are installed. This action
+ requires nmake.
+ license [ package ... ]
+ List the source license(s) for PACKAGE on the standard output.
+ Note that individual components in PACKAGE may contain
+ additional or replacement licenses.
+ list [ PACKAGE ... ]
+ List the name, version and prerequisites for PACKAGE on the
+ standard output.
+ make [ PACKAGE ] [ OPTION ... ] [ TARGET ... ]
+ Build and install. The default TARGET is install, which
+ makes and installs all packages. If the standard output
+ is a terminal then the output is also captured in
+ \$INSTALLROOT/lib/package/gen/make.out. The build is done
+ in the \$INSTALLROOT directory tree viewpathed on top of
+ the \$PACKAGEROOT directory tree. If \"flat\" is specified then
+ the \$INSTALLROOT { bin fun include lib } directories are
+ linked to the same directories in the package root. Only
+ one architecture may be flat. Leaf directory names matching
+ the |-separated shell pattern \$MAKESKIP are ignored. The
+ view action is done before making. OPTION operands are
+ passed to the underlying make command.
+ read [ package ... | archive ... ]
+ Read the named package archive(s). Must be run from the
+ package root directory. Archives are searched for in .
+ and lib/package/tgz. Each package is read only once. The
+ file lib/package/tgz/package[.type].tim tracks the read time.
+ See the write action for archive naming conventions. Text
+ file archive member are assumed to be ASCII or UTF-8 encoded.
+ regress diff(1) the current and previous package test results.
+ release [ [CC]YY-MM-DD [ [cc]yy-mm-dd ] ] [ package ]
+ Display recent changes since [CC]YY-MM-DD (up to [cc]yy-mm-dd),
+ where - means lowest (or highest.) If no dates are specified
+ then changes for the last 4 months are listed. PACKAGE may
+ be a package or component name.
+ remove PACKAGE
+ Remove files installed for PACKAGE.
+ results [ path ] [ old ] [ make | test ]
+ List results and interesting messages captured by the most
+ recent make (default), test or write action. old specifies the
+ previous results, if any (current and previous results are
+ retained.) $HOME/.pkgresults, if it exists, must contain an
+ egrep(1) expression of result lines to be ignored. failed lists
+ failures only and path lists the results file path only.
+ setup [ beta ] [ binary ] [ source ] [ ARCHITECTURE ... ] [ URL ] [ PACKAGE ... ]
+ The action initializes the current directory as a package root,
+ runs the update action to download new or out of date packages,
+ and runs the read action on those packages. If \"flat\" is
+ specified then the \$INSTALLROOT { bin fun include lib }
+ directories are linked to the same directories in the package
+ root. Only one architecture may be flat. See the update and
+ read actions for argument details.
+ test [ PACKAGE ]
+ Run the regression tests for PACKAGE. If the standard output
+ is a terminal then the output is also captured in
+ \$INSTALLROOT/lib/package/gen/test.out. In general a package
+ must be made before it can be tested. Components tested with
+ the \bregress\b(1) command require \bksh93\b. If only is
+ also specified then only the listed package components are
+ tested, otherwise the closure of the components is tested.
+ update [ beta ] [ binary ] [ source ] [ ARCHITECTURE ... ] [ URL ] [ PACKAGE ... ]
+ Download the latest release of the selected and required
+ packages from URL (e.g.,
+ http://www.research.att.com/sw/download) into the directory
+ \$PACKAGEROOT/lib/package/tgz. beta acesses beta packages;
+ download these at your own risk. If ARCHITECTURE is omitted
+ then only architectures already present in the tgz directory
+ will be downloaded. If ARCHITECTURE is - then all posted
+ architectures will be downloaded. If URL matches *.url then
+ it is interpreted as a file containing shell variable
+ assignments for url, authorize and password. If URL is
+ omitted then the definitions for url, authorize and password
+ in \$PACKAGEROOT/lib/package/tgz/$default_url, if it exists,
+ are used. If \$PACKAGEROOT/lib/package/tgz/$default_url does
+ not exist then it is initialized with the current url,
+ authorize and password values and read permission for the
+ current user only. If PACKAGE is omitted then only
+ packages already present in the tgz directory will be
+ downloaded. If PACKAGE is - then all posted packages will be
+ downloaded. If source and binary are omitted then both source
+ and binary packages will be downloaded. If \bonly\b is
+ specified then only the named packages are updated; otherwise
+ the closure of required packages is updated. This action
+ requires wget(1), lynx(1), curl(1) or a shell that supports
+ io to /dev/tcp/HOST/PORT.
+ use [ uid | PACKAGE | . [ 32 | 64 ] | 32 | 64 | - ] [ COMMAND ... ]
+ Run COMMAND or an interactive shell if COMMAND is omitted, with
+ the environment initialized for using the package (can you say
+ shared library without cussing?) If uid or PACKAGE or . is
+ specified then it is used to determine a \$PACKAGEROOT,
+ possibly different from the current directory. For example, to
+ try out bozo's package: \"package use bozo\". In this case the
+ command may be run from any directory. If the file
+ \$INSTALLROOT/lib/package/profile is readable then it is
+ sourced to initialize the environment. 32 or 64 implies
+ \$PACKAGEROOT of . and specifies the target architecture word
+ size (which may be silently ignored.)
+ verify [ PACKAGE ]
+ Verify installed binary files against the checksum files in
+ \$INSTALLROOT/lib/package/gen/*.sum. The checksum files contain
+ mode, user and group information. If the checksum matches
+ for a given file then the mode, user and group are changed
+ as necessary to match the checksum entry. A warning is printed
+ on the standard error for each mismatch. Requires the ast
+ package cksum(1) command.
+ view
+ Initialize the architecture specific viewpath hierarchy. The
+ make action implicitly calls this action. If \"flat\" is specified
+ then the \$INSTALLROOT { bin fun include lib } directories are
+ linked to the same directories in the package root. Only one
+ architecture may be flat.
+ write [closure] [cyg|exp|lcl|pkg|rpm|tgz|tst] [base|delta]
+ [binary|runtime|source] PACKAGE
+ Write a package archive for PACKAGE. All work is done in the
+ \$PACKAGEROOT/lib/package directory. FORMAT-specific files
+ are placed in the FORMAT subdirectory. A PACKAGE[.TYPE].tim
+ file in this directory tracksthe write time and prevents a
+ package from being read in the same root it was written. If
+ more than one file is generated for a particular FORMAT then
+ those files are placed in the FORMAT/PACKAGE subdirectory.
+ File names in the FORMAT subdirectory will contain the package
+ name, a YYYY-MM-DD date, and for binary packages, HOSTTYPE.
+ If PACKAGE is omitted then an ordered list of previously
+ written packages is generated. If \"only\" is specified then
+ only the named packages will be written; otherwise
+ prerequisite packages are written first. Package components
+ must be listed in PACKAGE.pkg. FORMAT may be one of:
+ cyg generate a cygwin package
+ exp generate an exptools(1) maintainer source archive
+ and NPD file in the exp subdirectory, suitable for
+ expmake(1); support files are placed in the
+ exp/PACKAGE subdirectory
+ lcl generate a package archive or delta in the lcl
+ subdirectory, suitable for restoration into the
+ primary source tree (no source licence annotation)
+ pkg generate a pkgmk(1) package, suitable for pkgadd(1)
+ rpm generate an rpm(1) package
+ tgz generate a gzip(1) tar(1) package archive; this is
+ the default
+ tst generate tgz FORMAT package archive in the tst
+ subdirectory; version state files are not updated
+ The package type must be one of source, binary or runtime.
+ A source package contains the source needed to build the
+ corresponding binary package. A binary package includes the
+ libraries and headers needed for compiling and linking
+ against the public interfaces. A runtime package contains
+ the commands and required dynamic libraries. A package may
+ be either a base or delta. A base package contains a
+ complete copy of all components. A delta package contains
+ only changes from a previous base package. Delta recipients
+ must have the ast pax(1) command (in the ast-base package.)
+ If neither base nor delta is specified, then the current
+ base is overwritten if there are no deltas referring to the
+ current base. Only the tgz and lcl formats support delta.
+ If base is specified then a new base and two delta archives
+ are generated: one delta to generate the new base from the
+ old, and one delta to generate the old base from the new;
+ the old base is then removed. If delta is specified then a
+ new delta referring to the current base is written.
+ package.pkg may reference other packages. By default a
+ pointer to those packages is written. The recipient package
+ read will then check that all required packages have been
+ downloaded. If closure is specified then the components for
+ all package references are included in the generated
+ package. This may be useful for lcl and versioning. All
+ formats but lcl annotate each source file (not already
+ annotated) with a license comment as it is written to the
+ package archive using proto(1).
+ name=value:
+ variable definition: typically CC=cc or CCFLAGS=-g."
+ ;;
+ esac
+ exit $code
+ ;;
+ *=*) set DEFAULT host type "$@"
+ ;;
+ *) echo "Usage: $command [ options ] [ qualifier ... ] [ action ] [ arg ... ] [ n=v ... ]" >&2
+ exit 2
+ ;;
+ esac
+ global="$global $1"
+ shift
+done
+
+# gather HOSTTYPE *,* options
+# ,*cc*,-*,... set CC and CCFLAGS
+
+hostopts()
+{
+ _ifs_=$IFS
+ IFS=,
+ set '' $HOSTTYPE
+ IFS=$_ifs_
+ shift
+ while :
+ do case $# in
+ 0|1) break ;;
+ esac
+ shift
+ case $1 in
+ *cc*) CC=$1
+ while :
+ do case $# in
+ 0|1) break ;;
+ esac
+ case $2 in
+ -*) case $assign_CCFLAGS in
+ ?*) assign_CCFLAGS="$assign_CCFLAGS " ;;
+ esac
+ assign_CCFLAGS="$assign_CCFLAGS$2"
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ done
+}
+
+# collect command line targets and definitions
+
+case $_PACKAGE_HOSTTYPE_ in
+?*) HOSTTYPE=$_PACKAGE_HOSTTYPE_
+ KEEP_HOSTTYPE=1
+ ;;
+*) KEEP_HOSTTYPE=0
+ ;;
+esac
+KEEP_PACKAGEROOT=0
+KEEP_SHELL=0
+USER_VPATH=
+args=
+assign=
+assign_CCFLAGS=
+for i
+do case $i in
+ *:*=*) args="$args $i"
+ continue
+ ;;
+ *=*) eval `echo ' ' "$i" | sed 's,^[ ]*\([^=]*\)=\(.*\),n=\1 v='\''\2'\'','`
+ ;;
+ esac
+ case $i in
+ AR=*|LD=*|NM=*)
+ assign="$assign $n='$v'"
+ eval $n='$'v
+ ;;
+ CC=*) eval $n='$'v
+ ;;
+ CCFLAGS=*)
+ eval $n='$'v
+ assign_CCFLAGS="CCFLAGS=\"\$CCFLAGS\""
+ ;;
+ HOSTTYPE=*)
+ eval $n='$'v
+ case $HOSTTYPE in
+ ?*) KEEP_HOSTTYPE=1 ;;
+ esac
+ ;;
+ HURL=*) eval $n='$'v
+ ;;
+ PACKAGEROOT=*)
+ eval $n='$'v
+ case $PACKAGEROOT in
+ ?*) KEEP_PACKAGEROOT=1 ;;
+ esac
+ ;;
+ SHELL=*)eval $n='$'v
+ case $SHELL in
+ ?*) KEEP_SHELL=1 ;;
+ esac
+ ;;
+ TAR=*) eval $n='$'v
+ ;;
+ TARFLAGS=*)
+ eval $n='$'v
+ ;;
+ VPATH=*)eval USER_$n='$'v
+ ;;
+ 'debug=1')
+ makeflags="$makeflags --debug-symbols"
+ ;;
+ 'strip=1')
+ makeflags="$makeflags --strip-symbols"
+ ;;
+ *=*) assign="$assign $n='$v'"
+ ;;
+ *) args="$args $i"
+ ;;
+ esac
+done
+case $HOSTTYPE in
+*,*) hostopts $HOSTTYPE ;;
+esac
+case $assign_CCFLAGS in
+?*) assign="$assign $assign_CCFLAGS"
+esac
+case $CC in
+''|cc) ;;
+*) export CC ;;
+esac
+
+# grab action specific args
+
+case $action in
+admin) while :
+ do case $# in
+ 0) set list
+ break
+ ;;
+ esac
+ case $1 in
+ all) admin_all=1
+ ;;
+ db) case $# in
+ 1) echo $command: $action: $1: db file argument expected >&2
+ exit 1
+ ;;
+ esac
+ shift
+ admin_db=$1
+ ;;
+ on) case $# in
+ 1) echo $command: $action: $1: host pattern argument expected >&2
+ exit 1
+ ;;
+ esac
+ shift
+ admin_on=$1
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ done
+ admin_action=$1
+ admin_args=$*
+ for i
+ do case $i in
+ debug|environment|force|never|only|quiet|show|DEBUG)
+ ;;
+ *) admin_action=$i
+ break
+ ;;
+ esac
+ done
+ ;;
+setup) PACKAGEROOT=${PWD:-`pwd`}
+ export PACKAGEROOT
+ KEEP_PACKAGEROOT=1
+ ;;
+use) case $1 in
+ .|32|64)case $1 in
+ 32|64) bit=$1 ;;
+ esac
+ shift
+
+ # HOSTTYPE specific setup
+
+ case $HOSTTYPE in
+ win32.*)sys=uwin
+ wow=`uname -i`
+ case $bit in
+ 32) case $HOSTTYPE in
+ *-64) HOSTTYPE=${HOSTTYPE%-64} ;;
+ esac
+ case $wow in
+ */32) ;;
+ *) vpath / /$bit ;;
+ esac
+ ;;
+ 64) case $HOSTTYPE in
+ *-64) ;;
+ *) HOSTTYPE=$HOSTTYPE-64 ;;
+ esac
+ case $wow in
+ */32) echo $command: cannot build $bit-bit on $wow $sys >&2; exit 2 ;;
+ *) vpath / /$bit ;;
+ esac
+ ;;
+ esac
+ case $bit in
+ '') PS1="($sys) " ;;
+ *) PS1="($sys-$bit) " ;;
+ esac
+
+ $exec umask 002
+ $exec unset MAKESKIP
+
+ $exec export P=$PWD
+ $exec export A=$P/arch/$HOSTTYPE
+
+ $exec export CDPATH=:..:$A/src/cmd:$A/src/lib:$A/src/uwin:$P/lib/package
+ $exec export INSTALLROOT=$A
+ $exec export PACKAGEROOT=$P
+ $exec export PATH=$A/bin:$P/bin:$PATH
+ $exec export PS1="$PS1"
+ $exec export VPATH=$A:$P
+ $exec export nativepp=/usr/lib
+
+ if test '' != "$INSTALLROOT" -a -d $INSTALLROOT/include/ast
+ then $exec export PACKAGE_ast=$INSTALLROOT
+ elif test -d ${PWD%/*}/ast/arch/$HOSTTYPE
+ then $exec export PACKAGE_ast=${PWD%/*}/ast/arch/$HOSTTYPE
+ fi
+
+ # run the command
+
+ case $# in
+ 0) case $show in
+ ':') $exec exec $SHELL ;;
+ esac
+ ;;
+ *) $exec exec $SHELL -c "$@"
+ ;;
+ esac
+ exit
+ ;;
+ esac
+ PACKAGEROOT=${PWD:-`pwd`}
+ $show export PACKAGEROOT
+ esac
+ ;;
+esac
+
+# true if arg is a valid PACKAGEROOT
+
+packageroot() # dir
+{
+ test -d $1/lib/$command -o -x $1/bin/$command
+}
+
+# true if arg is executable
+
+executable() # [!] command
+{
+ case $1 in
+ '!') test ! -x "$2" -a ! -x "$2.exe"; return ;;
+ *) test -x "$1" -o -x "$1.exe"; return ;;
+ esac
+}
+
+# initialize SHELLMAGIC
+# tangible proof of cygwin's disdain for unix (well, this and execrate)
+
+shellmagic()
+{
+ case $SHELLMAGIC in
+ '') ;;
+ -) if test -f /emx/bin/sh.exe
+ then SHELLMAGIC='#!/emx/bin/sh.exe'$nl
+ elif test -f /bin/env.exe
+ then SHELLMAGIC='#!/bin/env sh'$nl
+ else SHELLMAGIC=
+ fi
+ ;;
+ esac
+}
+
+# true if arg is executable command on $PATH
+
+onpath() # command
+{
+ _onpath_b=$1
+ case $_onpath_b in
+ /*) if executable $_onpath_b
+ then _onpath_=$_onpath_b
+ return 0
+ fi
+ return 1
+ ;;
+ esac
+ IFS=':'
+ set '' $PATH
+ IFS=$ifs
+ shift
+ for _onpath_d
+ do case $_onpath_d in
+ '') _onpath_d=. ;;
+ esac
+ if executable "$_onpath_d/$_onpath_b"
+ then _onpath_=$_onpath_d/$_onpath_b
+ return 0
+ fi
+ done
+ return 1
+}
+
+# true if no nmake or nmake not from AT&T or nmake too old
+
+nonmake() # nmake
+{
+ _nonmake_version=`( $1 -n -f - 'print $(MAKEVERSION:@/.*AT&T.* //:/-//G:@/.* .*/19960101/)' . ) </dev/null 2>/dev/null || echo 19840919`
+ if test $_nonmake_version -lt 20001031
+ then return 0
+ fi
+ return 1
+}
+
+# determine local host attributes
+
+hostinfo() # attribute ...
+{
+ case $DEBUG in
+ 1) set -x ;;
+ esac
+ map=
+ something=
+ path=$PATH
+ for i in $ccs
+ do PATH=$PATH:$i
+ done
+ for i in $use
+ do for j in $org
+ do PATH=$PATH:$i/$j/bin
+ done
+ PATH=$PATH:$i/bin
+ done
+ # LD_LIBRARY_PATH may be out of sync with PATH here
+ case $SED in
+ '') SED=sed
+ $SED 1d < /dev/null > /dev/null 2>&1 ||
+ for dir in /bin /usr/bin
+ do if test -x $dir/$SED
+ then SED=$dir/$SED
+ break
+ fi
+ done
+ TR=tr
+ $TR < /dev/null > /dev/null 2>&1 ||
+ for dir in /bin /usr/bin
+ do if test -x $dir/$TR
+ then TR=$dir/$TR
+ break
+ fi
+ done
+ ;;
+ esac
+ case $PACKAGE_PATH in
+ ?*) for i in `echo $PACKAGE_PATH | $SED 's,:, ,g'`
+ do PATH=$PATH:$i/bin
+ done
+ ;;
+ esac
+
+ # validate the args
+
+ canon=
+ cc=$CC
+ for info
+ do case $canon in
+ -) canon=$info
+ ;;
+ *) case $info in
+ */*|*[cC][cC])
+ cc=$info
+ ;;
+ canon) canon=-
+ something=1
+ ;;
+ cpu|name|rating|type)
+ something=1
+ ;;
+ *) echo "$command: $action: $info: unknown attribute" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $canon in
+ -) echo "$command: $action: canon: host type name expected" >&2
+ exit 1
+ ;;
+ esac
+ case $something in
+ "") set "$@" type ;;
+ esac
+ case $DEBUG in
+ '') exec 9>&2
+ exec 2>/dev/null
+ ;;
+ esac
+
+ # compute the info
+
+ _hostinfo_=
+ for info
+ do
+ case $info in
+ cpu) case $NPROC in
+ [123456789]*)
+ _hostinfo_="$_hostinfo_ $NPROC"
+ continue
+ ;;
+ esac
+ cpu=`grep -ic '^processor[ ][ ]*:[ ]*[0123456789]' /proc/cpuinfo`
+ case $cpu in
+ [123456789]*)
+ _hostinfo_="$_hostinfo_ $cpu"
+ continue
+ ;;
+ esac
+ cpu=1
+ # exact match
+ set \
+ hinv '^Processor [0123456789]' \
+ psrinfo 'on-line' \
+ 'cat /reg/LOCAL_MACHINE/Hardware/Description/System/CentralProcessor' '.' \
+ 'cat /proc/registry/HKEY_LOCAL_MACHINE/Hardware/Description/System/CentralProcessor' '.' \
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ i=`$1 2>/dev/null | grep -c "$2"`
+ case $i in
+ [123456789]*)
+ cpu=$i
+ break
+ ;;
+ esac
+ shift;shift
+ done
+ case $cpu in
+ 0|1) set \
+ /bin/mpstat
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ if executable $1
+ then case `$1 | grep -ic '^cpu '` in
+ 1) cpu=`$1 | grep -ic '^ *[0123456789][0123456789]* '`
+ break
+ ;;
+ esac
+ fi
+ shift
+ done
+ ;;
+ esac
+ case $cpu in
+ 0|1) # token match
+ set \
+ /usr/kvm/mpstat 'cpu[0123456789]' \
+ /usr/etc/cpustatus 'enable' \
+ /usr/alliant/showsched 'CE' \
+ 'ls /config/hw/system/cpu' 'cpu' \
+ prtconf 'cpu-unit' \
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ i=`$1 2>/dev/null | $TR ' ' '
+
+' | grep -c "^$2"`
+ case $i in
+ [123456789]*)
+ cpu=$i
+ break
+ ;;
+ esac
+ shift;shift
+ done
+ ;;
+ esac
+ case $cpu in
+ 0|1) # special match
+ set \
+ \
+ hinv \
+ '/^[0123456789][0123456789]* .* Processors*$/' \
+ '/[ ].*//' \
+ \
+ /usr/bin/hostinfo \
+ '/^[0123456789][0123456789]* .* physically available\.*$/' \
+ '/[ ].*//' \
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ i=`$1 2>/dev/null | $SED -e "${2}!d" -e "s${3}"`
+ case $i in
+ [123456789]*)
+ cpu=$i
+ break
+ ;;
+ esac
+ shift;shift;shift
+ done
+ ;;
+ esac
+ case $cpu in
+ 0|1) cpu=`(
+ cd ${TMPDIR:-/tmp}
+ tmp=hi$$
+ trap 'rm -f $tmp.*' 0 1 2
+ cat > $tmp.c <<!
+#include <stdio.h>
+#include <pthread.h>
+int main()
+{
+ printf("%d\n", pthread_num_processors_np());
+ return 0;
+}
+!
+ for o in -lpthread ''
+ do if $CC $o -O -o $tmp.exe $tmp.c $o >/dev/null 2>&1 ||
+ gcc $o -O -o $tmp.exe $tmp.c $o >/dev/null 2>&1
+ then ./$tmp.exe
+ break
+ fi
+ done
+ )`
+ case $cpu in
+ [0123456789]*) ;;
+ *) cpu=1 ;;
+ esac
+ ;;
+ esac
+ _hostinfo_="$_hostinfo_ $cpu"
+ ;;
+ name) _name_=`hostname || uname -n || cat /etc/whoami || echo local`
+ _hostinfo_="$_hostinfo_ $_name_"
+ ;;
+ rating) for rating in `grep -i ^bogomips /proc/cpuinfo 2>/dev/null | $SED -e 's,.*:[ ]*,,' -e 's,\(...*\)\..*,\1,' -e 's,\(\..\).*,\1,'`
+ do case $rating in
+ [0123456789]*) break ;;
+ esac
+ done
+ case $rating in
+ [0123456789]*) ;;
+ *) cd ${TMPDIR:-/tmp}
+ tmp=hi$$
+ trap 'rm -f $tmp.*' 0 1 2
+ cat > $tmp.c <<!
+#include <stdio.h>
+#include <sys/types.h>
+#if TD || TZ
+#include <sys/time.h>
+#else
+extern time_t time();
+#endif
+int main()
+{
+ register unsigned long i;
+ register unsigned long j;
+ register unsigned long k;
+ unsigned long l;
+ unsigned long m;
+ unsigned long t;
+ int x;
+#if TD || TZ
+ struct timeval b;
+ struct timeval e;
+#if TZ
+ struct timezone z;
+#endif
+#endif
+ l = 500;
+ m = 890;
+ x = 0;
+ for (;;)
+ {
+#if TD || TZ
+#if TZ
+ gettimeofday(&b, &z);
+#else
+ gettimeofday(&b);
+#endif
+#else
+ t = (unsigned long)time((time_t*)0);
+#endif
+ k = 0;
+ for (i = 0; i < l; i++)
+ for (j = 0; j < 50000; j++)
+ k += j;
+#if TD || TZ
+#if TZ
+ gettimeofday(&e, &z);
+#else
+ gettimeofday(&e);
+#endif
+ t = (e.tv_sec - b.tv_sec) * 1000 + (e.tv_usec - b.tv_usec) / 1000;
+ if (!x++ && t < 1000)
+ {
+ t = 10000 / t;
+ l = (l * t) / 10;
+ continue;
+ }
+#else
+ t = ((unsigned long)time((time_t*)0) - t) * 1000;
+ if (!x++ && t < 20000)
+ {
+ t = 200000l / t;
+ l = (l * t) / 10;
+ continue;
+ }
+#endif
+#if PR
+ printf("[ k=%lu l=%lu m=%lu t=%lu ] ", k, l, m, t);
+#endif
+ if (t == 0)
+ t = 1;
+ break;
+ }
+ printf("%lu\n", ((l * m) / 10) / t);
+ return k == 0;
+}
+!
+ rating=
+ for o in -DTZ -DTD ''
+ do if $CC $o -O -o $tmp.exe $tmp.c >/dev/null 2>&1 ||
+ gcc $o -O -o $tmp.exe $tmp.c >/dev/null 2>&1
+ then rating=`./$tmp.exe`
+ break
+ fi
+ done
+ case $rating in
+ [0123456789]*) ;;
+ *) rating=1 ;;
+ esac
+ ;;
+ esac
+ _hostinfo_="$_hostinfo_ $rating"
+ ;;
+ type|canon)
+ case $CROSS:$canon in
+ 0:) case $cc in
+ cc) case $KEEP_HOSTTYPE:$HOSTTYPE in
+ 0:?*) if test -d ${PACKAGEROOT:-.}/arch/$HOSTTYPE
+ then KEEP_HOSTTYPE=1
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ case $KEEP_HOSTTYPE in
+ 1) _hostinfo_="$_hostinfo_ $HOSTTYPE"
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ case $cc in
+ /*) a=`$cc -dumpmachine $CCFLAGS 2>/dev/null`
+ case $a in
+ '') case $CCFLAGS in
+ ?*) a=`$cc -dumpmachine 2>/dev/null` ;;
+ esac
+ ;;
+ esac
+ case $a in
+ ''|*' '*|*/*:*)
+ ;;
+ *.*-*) _hostinfo_="$_hostinfo_ $a"
+ continue
+ ;;
+ *-*-*) case $canon in
+ '') canon=$a ;;
+ esac
+ ;;
+ *) _hostinfo_="$_hostinfo_ $a"
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ IFS=:
+ set /$IFS$PATH
+ IFS=$ifs
+ shift
+ f=../lib/hostinfo/typemap
+ for i
+ do case $i in
+ "") i=. ;;
+ esac
+ case $canon in
+ '') case $cc in
+ /*|cc) ;;
+ *) if executable $i/$cc
+ then a=`$i/$cc -dumpmachine $CCFLAGS 2>/dev/null`
+ case $a in
+ '') case $CCFLAGS in
+ ?*) a=`$cc -dumpmachine 2>/dev/null` ;;
+ esac
+ ;;
+ esac
+ case $a in
+ ''|*' '*|*/*:*)
+ ;;
+ *-*) canon=$a
+ ;;
+ *) _hostinfo_="$_hostinfo_ $a"
+ continue 2
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ if test -f "$i/$f"
+ then map="`grep -v '^#' $i/$f` $map"
+ fi
+ done
+
+ # inconsistent -dumpmachine filtered here
+
+ case -${canon}- in
+ --|*-powerpc-*)
+ h=`hostname || uname -n || cat /etc/whoami`
+ case $h in
+ '') h=local ;;
+ esac
+ a=`arch || uname -m || att uname -m || uname -s || att uname -s`
+ case $a in
+ *[\ \ ]*) a=`echo $a | $SED "s/[ ]/-/g"` ;;
+ esac
+ case $a in
+ '') a=unknown ;;
+ esac
+ m=`mach || machine || uname -p || att uname -p`
+ case $m in
+ *[\ \ ]*) m=`echo $m | $SED "s/[ ]/-/g"` ;;
+ esac
+ case $m in
+ '') m=unknown ;;
+ esac
+ x=`uname -a || att uname -a`
+ case $x in
+ '') x="unknown $host unknown unknown unknown unknown unknown" ;;
+ esac
+ set "" $h $a $m $x
+ expected=$1 host=$2 arch=$3 mach=$4 os=$5 sys=$6 rel=$7 ver=$8
+ ;;
+ *) case $canon in
+ *-*) IFS=-
+ set "" $canon
+ shift
+ IFS=$ifs
+ case $# in
+ 2) host= mach= arch=$1 os=$2 sys= rel= ;;
+ *) host= mach=$2 arch=$1 os=$3 sys= rel= ;;
+ esac
+ case $os in
+ [abcdefghijklmnopqrstuvwxyz]*[0123456789])
+ eval `echo $os | $SED -e 's/^\([^0123456789.]*\)\.*\(.*\)/os=\1 rel=\2/'`
+ ;;
+ esac
+ ;;
+ *) arch=$canon mach= os= sys= rel=
+ ;;
+ esac
+ ;;
+ esac
+ type=unknown
+ case $host in
+ *.*) host=`echo $host | $SED -e 's/\..*//'` ;;
+ esac
+ case $mach in
+ unknown)
+ mach=
+ ;;
+ [Rr][0123][0123456789][0123456789][0123456789])
+ mach=mips1
+ ;;
+ [Rr][4][0123456789][0123456789][0123456789])
+ mach=mips2
+ ;;
+ [Rr][56789][0123456789][0123456789][0123456789]|[Rr][123456789][0123456789][0123456789][0123456789][0123456789])
+ mach=mips4
+ ;;
+ pc) arch=i386
+ mach=
+ ;;
+ [Pp][Oo][Ww][Ee][Rr][Pp][Cc])
+ arch=ppc
+ mach=
+ ;;
+ *) case $arch in
+ 34[0123456789][0123456789])
+ os=ncr
+ arch=i386
+ ;;
+ esac
+ ;;
+ esac
+ case $canon in
+ '') set \
+ \
+ /NextDeveloper -d next - \
+ /config/hw/system/cpu -d tandem mach \
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ if test $2 $1
+ then os=$3
+ case $4 in
+ arch) mach=$arch ;;
+ mach) arch=$mach ;;
+ esac
+ break
+ fi
+ shift;shift;shift;shift
+ done
+ ;;
+ esac
+ case $os in
+ AIX*|aix*)
+ type=ibm.risc
+ ;;
+ HP-UX) case $arch in
+ 9000/[78]*)
+ type=hp.pa
+ ;;
+ */*) type=hp.`echo $arch | $SED 's,/,_,g'`
+ ;;
+ *) type=hp.$arch
+ ;;
+ esac
+ ;;
+ [Ii][Rr][Ii][Xx]*)
+ set xx `hinv | $SED -e '/^CPU:/!d' -e 's/CPU:[ ]*\([^ ]*\)[ ]*\([^ ]*\).*/\1 \2/' -e q | $TR ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ shift
+ type=$1
+ n=
+ case $2 in
+ r[0123][0123456789][0123456789][0123456789])
+ n=1
+ ;;
+ r[4][0123][0123456789][0123456789])
+ n=2
+ ;;
+ r[4][456789][0123456789][0123456789]|r[5][0123456789][0123456789][0123456789])
+ n=3
+ ;;
+ r[6789][0123456789][0123456789][0123456789]|r[123456789][0123456789][0123456789][0123456789][0123456789])
+ n=4
+ ;;
+ esac
+ case $rel in
+ [01234].*|5.[012]|5.[012].*)
+ case $n in
+ 1) ;;
+ *) n=2 ;;
+ esac
+ ;;
+ 5.*) case $n in
+ 2) n=3 ;;
+ esac
+ ;;
+ esac
+ if executable $cc
+ then a=$cc
+ else IFS=:
+ set /$IFS$PATH
+ IFS=$ifs
+ shift
+ for i
+ do a=$i/$cc
+ if executable $a
+ then break
+ fi
+ done
+ fi
+ split='
+'
+ a=`strings $a < /dev/null | $SED -e 's/[^abcdefghijklmnopqrstuvwxyz0123456789]/ /g' -e 's/[ ][ ]*/\'"$split"'/g' | $SED -e "/^${type}[0123456789]$/!d" -e "s/^${type}//" -e q`
+ case $a in
+ [0123456789]) n=$a ;;
+ esac
+ case $n in
+ 4) a=`$cc -${type}3 2>&1`
+ case $a in
+ *unknown*|*install*|*conflict*)
+ ;;
+ *) n=3
+ ;;
+ esac
+ ;;
+ esac
+ a=`$cc -show F0oB@r.c 2>&1`
+ case $n:$a in
+ [!2]:*mips2*) n=2 ;;
+ [!23]:*mips3*) n=3 ;;
+ [!234]:*mips4*) n=4 ;;
+ esac
+ case $n:$a in
+ [!2]:*[Oo]32*) abi=-o32 ;;
+ [!3]:*[Nn]32*) abi=-n32 ;;
+ esac
+ mach=${type}$n
+ type=sgi.$mach
+ ;;
+ OSx*|SMP*|pyramid)
+ type=pyr
+ ;;
+ OS/390) type=mvs.390
+ ;;
+ [Ss][Cc][Oo]*)
+ type=sco
+ ;;
+ [Ss]ol*)
+ v=`echo $rel | $SED -e 's/^[25]\.//' -e 's/\.[^.]*$//'`
+ case $v in
+ [6789]|[1-9][0-9])
+ ;;
+ *) v=
+ ;;
+ esac
+ case $arch in
+ '') case $mach in
+ '') arch=sun4 ;;
+ *) arch=$mach ;;
+ esac
+ ;;
+ esac
+ case $arch in
+ sparc) arch=sun4 ;;
+ esac
+ type=sol$v.$arch
+ ;;
+ [Ss]un*)type=`echo $arch | $SED -e 's/\(sun.\).*/\1/'`
+ case $type in
+ sparc) type=sun4 ;;
+ esac
+ case $rel in
+ [01234]*)
+ ;;
+ '') case $os in
+ *[Oo][Ss])
+ ;;
+ *) type=sol.$type
+ ;;
+ esac
+ ;;
+ *) case $type in
+ '') case $mach in
+ sparc*) type=sun4 ;;
+ *) type=$mach ;;
+ esac
+ ;;
+ esac
+ v=`echo $rel | $SED -e 's/^[25]\.//' -e 's/\.[^.]*$//'`
+ case $v in
+ [6789]|[1-9][0-9])
+ ;;
+ *) v=
+ ;;
+ esac
+ type=sol$v.$type
+ ;;
+ esac
+ case $type in
+ sun*|*.*)
+ ;;
+ *) type=sun.$type
+ ;;
+ esac
+ ;;
+ [Uu][Nn][Ii][Xx]_[Ss][Vv])
+ type=unixware
+ ;;
+ UTS*|uts*)
+ if test -x /bin/u370 -o -x /bin/u390
+ then type=uts.390
+ else case $arch in
+ '') arch=$mach ;;
+ esac
+ type=uts.$arch
+ fi
+ ;;
+ $host) type=$arch
+ case $type in
+ *.*|*[0123456789]*86|*68*)
+ ;;
+ *) case $mach in
+ *[0123456789]*86|*68*|mips)
+ type=$type.$mach
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ unknown)
+ case $arch in
+ ?*) case $arch in
+ sun*) mach= ;;
+ esac
+ type=$arch
+ case $mach in
+ ?*) type=$type.$mach ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) case $ver in
+ FTX*|ftx*)
+ case $mach in
+ *[0123456789][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]*)
+ mach=`echo $mach | $SED -e 's/[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]*$//'`
+ ;;
+ esac
+ type=stratus.$mach
+ ;;
+ *) case $arch in
+ [Oo][Ss][-/.]2)
+ type=os2
+ arch=$rel
+ ;;
+ *) type=`echo $os | $SED -e 's/[0123456789].*//' -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789.].*//'`
+ ;;
+ esac
+ case $type in
+ [Cc][Yy][Gg][Ww][Ii][Nn]_*)
+ type=cygwin
+ ;;
+ [Uu][Ww][Ii][Nn]*|[Ww]indows_[0123456789][0123456789]|[Ww]indows_[Nn][Tt])
+ type=win32
+ arch=`echo $arch | $SED -e 's/_[^_]*$//'`
+ ;;
+ esac
+ case $arch in
+ '') case $mach in
+ ?*) type=$type.$mach ;;
+ esac
+ ;;
+ *) type=$type.$arch ;;
+ esac
+ ;;
+ esac
+ esac
+ case $type in
+ [0123456789]*)
+ case $mach in
+ ?*) type=$mach ;;
+ esac
+ case $type in
+ */MC) type=ncr.$type ;;
+ esac
+ ;;
+ *.*) ;;
+ *[0123456789]*86|*68*)
+ case $rel in
+ [34].[0123456789]*)
+ type=att.$type
+ ;;
+ esac
+ ;;
+ [abcdefghijklmnopqrstuvwxyz]*[0123456789])
+ ;;
+ [abcdefghijklmnopqrstuvwxyz]*) case $mach in
+ $type) case $ver in
+ Fault*|fault*|FAULT*)
+ type=ft.$type
+ ;;
+ esac
+ ;;
+ ?*) case $arch in
+ '') type=$type.$mach ;;
+ *) type=$type.$arch ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $type in
+ *[-_]32|*[-_]64|*[-_]128)
+ bits=`echo $type | $SED 's,.*[-_],,'`
+ type=`echo $type | $SED 's,[-_][0-9]*$,,'`
+ ;;
+ *) bits=
+ ;;
+ esac
+ type=`echo $type | $SED -e 's%[-+/].*%%' | $TR ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ case $type in
+ *.*) lhs=`echo $type | $SED -e 's/\..*//'`
+ rhs=`echo $type | $SED -e 's/.*\.//'`
+ case $rhs in
+ [x0123456789]*86) rhs=i$rhs ;;
+ 68*) rhs=m$rhs ;;
+ esac
+ case $rhs in
+ i[x23456789]86|i?[x23456789]86|*86pc)
+ rhs=i386 ;;
+ powerpc) rhs=ppc ;;
+ s[0123456789]*[0123456789]x)
+ rhs=`echo $rhs | $SED -e 's/x$/-64/'` ;;
+ esac
+ case $rhs in
+ arm[abcdefghijklmnopqrstuvwxyz_][0123456789]*)
+ rhs=arm ;;
+ hppa) rhs=pa ;;
+ esac
+ case $lhs in
+ ?*coff|?*dwarf|?*elf)
+ case $lhs in
+ ?*coff) x=coff ;;
+ ?*dwarf)x=coff ;;
+ ?*elf) x=elf ;;
+ esac
+ lhs=`echo ${lhs}XXX | $SED -e "s/${x}XXX//"`
+ ;;
+ esac
+ case $lhs in
+ bsdi) lhs=bsd ;;
+ darwin) case $rel in
+ [01234567].*) lhs=${lhs}7 ;;
+ esac
+ ;;
+ freebsd) case $rel in
+ [01234].*) lhs=${lhs}4 ;;
+ [123456789]*.*) lhs=${lhs}`echo $rel | $SED -e 's/\..*//'` ;;
+ esac
+ ;;
+ hpux) lhs=hp ;;
+ mvs) rhs=390 ;;
+ esac
+ case $lhs in
+ '') type=$rhs ;;
+ $rhs) type=$lhs ;;
+ *) type=$lhs.$rhs ;;
+ esac
+ ;;
+ esac
+ case $type in
+ sgi.mips*)
+ case $mach in
+ mips2) type=sgi.$mach
+ abi=-o32
+ ;;
+ mips3) type=sgi.$mach
+ abi=-n32
+ ;;
+ mips[456789])
+ type=sgi.$mach
+ case $abi in
+ *-n32) ;;
+ *) abi=-64 ;;
+ esac
+ ;;
+ *) pwd=`pwd`
+ cd ${TMPDIR:-/tmp}
+ tmp=hi$$
+ trap 'rm -f $tmp.*' 0 1 2
+ cat > $tmp.a.c <<!
+extern int b();
+int main() { return b(); }
+!
+ cat > $tmp.b.c <<!
+int b() { return 0; }
+!
+ abi=
+ if $cc -c $tmp.a.c
+ then for i in -n32 -o32 -64
+ do if $cc $i -c $tmp.b.c &&
+ $cc -o $tmp.exe $tmp.a.o $tmp.b.o
+ then abi=$i
+ for i in 2 3 4 5 6 7 8 9
+ do case $i:$abi in
+ 2:-n32|2:-64|3:-64)
+ continue
+ ;;
+ esac
+ if $cc $abi -mips$i -c $tmp.b.c &&
+ $cc -o $tmp.exe $tmp.a.o $tmp.b.o
+ then type=`echo $type | $SED -e 's/.$//'`$i
+ break
+ fi
+ done
+ break
+ fi
+ done
+ fi </dev/null >/dev/null 2>&1
+ rm -f $tmp.*
+ trap - 0 1 2
+ cd $pwd
+ ;;
+ esac
+ case $type$abi in
+ sgi.mips2-o32)
+ ;;
+ sgi.mips3)
+ type=$type-o32
+ ;;
+ sgi.mips3-n32)
+ ;;
+ sgi.mips4)
+ type=$type-o32
+ ;;
+ sgi.mips[456789]-64)
+ ;;
+ *) type=$type$abi
+ ;;
+ esac
+ ;;
+ *) case $bits in
+ '') case `file /bin/sh 2>/dev/null` in
+ *universal*64*)
+ pwd=`pwd`
+ cd ${TMPDIR:-/tmp}
+ tmp=hi$$
+ trap 'rm -f $tmp.*' 0 1 2
+ cat > $tmp.a.c <<!
+int main() { return 0; }
+!
+ if $cc -o $tmp.a.exe $tmp.a.c
+ then case `file $tmp.a.exe` in
+ *64*) bits=64 ;;
+ esac
+ fi </dev/null >/dev/null 2>&1
+ rm -f $tmp.*
+ trap - 0 1 2
+ cd $pwd
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $bits in
+ 32) case $type in
+ *.i386) bits= ;;
+ esac
+ ;;
+ esac
+ case $bits in
+ ?*) type=$type-$bits ;;
+ esac
+
+ # last chance mapping
+
+ set "" "" $map
+ while :
+ do case $# in
+ [012]) break ;;
+ esac
+ shift;shift
+ eval " case \$type in
+ $1) type=\$2; break ;;
+ esac"
+ done
+ _hostinfo_="$_hostinfo_ $type"
+ ;;
+ esac
+ done
+ set '' $_hostinfo_
+ shift
+ _hostinfo_=$*
+
+ # restore the global state
+
+ PATH=$path
+ case $DEBUG in
+ '') exec 2>&9
+ exec 9>&-
+ ;;
+ esac
+}
+
+# info message
+
+note() # message ...
+{
+ echo $command: "$@" >&2
+}
+
+# cc checks
+#
+# CC: compiler base name name
+# cc: full path, empty if not found
+
+checkcc()
+{
+ cc=
+ if onpath $CC
+ then cc=$_onpath_
+ else case $CC in
+ cc) if onpath gcc
+ then CC=gcc
+ cc=$_onpath_
+ fi
+ ;;
+ esac
+ fi
+ case $cc in
+ '') case $action in
+ make|test) note "$CC: not found"; exit 1 ;;
+ *) note "warning: $CC: not found" ;;
+ esac
+ ;;
+ esac
+}
+
+# some actions have their own PACKAGEROOT or kick out early
+
+case $action in
+host) eval u=$package_use
+ case $u in
+ $PACKAGE_USE)
+ ;;
+ *) if onpath $0
+ then case $_onpath_ in
+ */arch/$HOSTTYPE/bin/package)
+ KEEP_HOSTTYPE=1
+ ;;
+ *) KEEP_HOSTTYPE=0
+ ;;
+ esac
+ else KEEP_HOSTTYPE=0
+ fi
+ ;;
+ esac
+ hostinfo $args
+ echo $_hostinfo_
+ exit 0
+ ;;
+export|setup|use)
+ x=
+ ;;
+*) x=
+ eval u=$package_use
+ case $u in
+ $PACKAGE_USE)
+ case :$PATH: in
+ *:$INSTALLROOT/bin:*)
+ case $LIBPATH: in
+ $INSTALLROOT/bin:$INSTALLROOT/lib:*)
+ case $SHLIB_PATH: in
+ $INSTALLROOT/lib:*)
+ x=1
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+run=-
+case $x in
+1) : accept the current package use environment
+
+ OK=ok
+ KSH=$EXECROOT/bin/ksh
+ MAKE=nmake
+ NMAKE=$EXECROOT/bin/$MAKE
+ SUM=$EXECROOT/bin/sum
+ TEE=$EXECROOT/bin/tee
+ INITROOT=$PACKAGEROOT/src/cmd/INIT
+ checkcc
+ ;;
+*) hosttype=
+ case $KEEP_PACKAGEROOT in
+ 0) case $action in
+ use) PACKAGEROOT=
+ case $show in
+ echo) exec=echo make=echo show=echo ;;
+ esac
+ set '' $args
+ shift
+ case $# in
+ 0) ;;
+ *) case $1 in
+ -|.) ;;
+ /*) PACKAGEROOT=$1
+ ;;
+ *) i=`echo ~$1`
+ if packageroot $i
+ then PACKAGEROOT=$i
+ else for i in `echo $HOME | sed -e 's,/[^/]*$,,'` $usr $use
+ do if packageroot $i/$1
+ then PACKAGEROOT=$i/$1
+ break
+ fi
+ done
+ case $PACKAGEROOT in
+ '') hosttype=$1 ;;
+ esac
+ fi
+ ;;
+ esac
+ shift
+ ;;
+ esac
+ run="$@"
+ ;;
+ esac
+ case $PACKAGEROOT in
+ '') PACKAGEROOT=${PWD:-`pwd`} ;;
+ esac
+
+ # . must be within the PACKAGEROOT tree
+
+ i=X$PACKAGEROOT
+ IFS=/
+ set $i
+ IFS=$ifs
+ while :
+ do i=$1
+ shift
+ case $i in
+ X) break ;;
+ esac
+ done
+ case $PACKAGEROOT in
+ //*) d=/ ;;
+ *) d= ;;
+ esac
+ case $1 in
+ home) k=1 ;;
+ *) k=0 ;;
+ esac
+ for i
+ do case $i in
+ '') continue ;;
+ esac
+ d=$d/$i
+ case $k in
+ 2) k=1
+ ;;
+ 1) k=0
+ ;;
+ 0) case $i in
+ arch) k=2
+ ;;
+ *) if packageroot $d
+ then PACKAGEROOT=$d
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ done
+ ;;
+ esac
+ INITROOT=$PACKAGEROOT/src/cmd/INIT
+ $show PACKAGEROOT=$PACKAGEROOT
+ $show export PACKAGEROOT
+ export PACKAGEROOT
+
+ # initialize the architecture environment
+
+ case $KEEP_HOSTTYPE in
+ 0) hostinfo type
+ HOSTTYPE=$_hostinfo_
+ ;;
+ 1) _PACKAGE_HOSTTYPE_=$HOSTTYPE
+ export _PACKAGE_HOSTTYPE_
+ ;;
+ esac
+ $show HOSTTYPE=$HOSTTYPE
+ $show export HOSTTYPE
+ export HOSTTYPE
+ INSTALLROOT=$PACKAGEROOT/arch/$HOSTTYPE
+ case $action in
+ admin|install|make|read|remove|test|verify|view|write)
+ ;;
+ *) if test ! -d $INSTALLROOT
+ then INSTALLROOT=$PACKAGEROOT
+ fi
+ ;;
+ esac
+ $show INSTALLROOT=$INSTALLROOT
+ $show export INSTALLROOT
+ export INSTALLROOT
+
+ # HOSTTYPE specific package profile
+
+ if test -r $INSTALLROOT/lib/package/profile
+ then . $INSTALLROOT/lib/package/profile
+ fi
+
+ # check the basic package hierarchy
+
+ case $action in
+ export|use)
+ packageroot $PACKAGEROOT || {
+ echo "$command: $PACKAGEROOT: invalid package root directory" >&2
+ exit 1
+ }
+ case $KEEP_HOSTTYPE:$hosttype in
+ 0:?*) if test -d ${PACKAGEROOT:-.}/arch/$hosttype
+ then KEEP_HOSTTYPE=1
+ HOSTTYPE=$hosttype
+ else echo "$command: $hosttype: package root not found" >&2
+ exit 1
+ fi
+ ;;
+ esac
+ ;;
+ *) packageroot $PACKAGEROOT || {
+ case $KEEP_PACKAGEROOT in
+ 1) ;;
+ *) echo "$command: $PACKAGEROOT: must be in the package root directory tree" >&2
+ exit 1
+ ;;
+ esac
+ }
+
+ case $action in
+ admin) ;;
+ *) for i in arch arch/$HOSTTYPE
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || exit
+ done
+ for i in lib
+ do test -d $INSTALLROOT/$i || $exec mkdir $INSTALLROOT/$i || exit
+ done
+ ;;
+ esac
+
+ # no $INITROOT means INIT already installed elsewhere
+
+ if test -d $INITROOT
+ then
+ # update the basic package commands
+
+ for i in execrate ignore mamprobe silent
+ do test -h $PACKAGEROOT/bin/$i 2>/dev/null ||
+ case `ls -t $INITROOT/$i.sh $PACKAGEROOT/bin/$i 2>/dev/null` in
+ "$INITROOT/$i.sh"*)
+ note update $PACKAGEROOT/bin/$i
+ shellmagic
+ case $SHELLMAGIC in
+ '') $exec cp $INITROOT/$i.sh $PACKAGEROOT/bin/$i || exit
+ ;;
+ *) case $exec in
+ '') {
+ echo "$SHELLMAGIC"
+ cat $INITROOT/$i.sh
+ } > $PACKAGEROOT/bin/$i || exit
+ ;;
+ *) echo "{
+echo \"$SHELLMAGIC\"
+cat $INITROOT/$i.sh
+} > $PACKAGEROOT/bin/$i"
+ ;;
+ esac
+ ;;
+ esac
+ $exec chmod +x $PACKAGEROOT/bin/$i || exit
+ ;;
+ esac
+ done
+ fi
+ ;;
+ esac
+ path=$PATH
+ PATH=$INSTALLROOT/bin:$PACKAGEROOT/bin:$PATH
+ checkcc
+ PATH=$path
+ case $cc in
+ ?*) if test -f $INITROOT/hello.c
+ then
+ # check if $CC (full path $cc) is a cross compiler
+
+ (
+ cd /tmp || exit 3
+ cp $INITROOT/hello.c pkg$$.c || exit 3
+ $cc -o pkg$$.exe pkg$$.c > pkg$$.e 2>&1 || {
+ if $cc -Dnew=old -o pkg$$.exe pkg$$.c > /dev/null 2>&1
+ then echo "$command: ${warn}$CC: must be a C compiler (not C++)" >&2
+ else cat pkg$$.e
+ echo "$command: ${warn}$CC: failed to compile and link $INITROOT/hello.c -- is it a C compiler?" >&2
+ fi
+ exit 2
+ }
+ if ./pkg$$.exe >/dev/null 2>&1
+ then code=0
+ else code=1
+ fi
+ rm -f pkg$$.*
+ exit $code
+ )
+ code=$?
+ case $code in
+ 1) CROSS=1 ;;
+ esac
+ fi
+ ;;
+ esac
+ EXECTYPE=$HOSTTYPE
+ EXECROOT=$INSTALLROOT
+ case $CROSS in
+ 0) # dll hackery -- why is this so complicated?
+
+ abi=
+ case $HOSTTYPE in
+ sgi.mips[0123456789]*)
+ x=rld
+ if executable /lib32/$x || executable /lib64/$x
+ then case $INSTALLROOT in
+ */sgi.mips[0123456789]*)
+ u=`echo $INSTALLROOT | sed -e 's,-[^-/]*$,,' -e 's,.$,,'`
+ ;;
+ *) u=
+ ;;
+ esac
+ for a in "n=2 v= l=" "n=3 v=N32 l=lib32" "n=4-n32 v=N32 l=lib32" "n=4 v=64 l=lib64"
+ do eval $a
+ case $v in
+ N32) case $n:$HOSTTYPE in
+ *-n32:*-n32) ;;
+ *-n32:*) continue ;;
+ *:*-n32) continue ;;
+ esac
+ ;;
+ esac
+ case $l in
+ ?*) if executable ! /$l/$x
+ then continue
+ fi
+ ;;
+ esac
+ case $u in
+ '') case $HOSTTYPE in
+ sgi.mips$n|sgi.mips$n-*)
+ abi="$abi 'd=$INSTALLROOT v=$v'"
+ ;;
+ *) continue
+ ;;
+ esac
+ ;;
+ *) if test -d $u$n
+ then abi="$abi 'd=$u$n v=$v'"
+ fi
+ ;;
+ esac
+ done
+ fi
+ ;;
+ esac
+ case $abi in
+ '') abi="'d=$INSTALLROOT v='" ;;
+ esac
+ p=0
+ eval "
+ for a in $abi
+ do eval \$a
+ eval \"
+ case \\\$LD_LIBRARY\${v}_PATH: in
+ \\\$d/lib:*)
+ ;;
+ *) x=\\\$LD_LIBRARY\${v}_PATH
+ case \\\$x in
+ ''|:*) ;;
+ *) x=:\\\$x ;;
+ esac
+ LD_LIBRARY\${v}_PATH=\$d/lib\\\$x
+ export LD_LIBRARY\${v}_PATH
+ p=1
+ ;;
+ esac
+ \"
+ done
+ "
+ case $LD_LIBRARY_PATH in
+ '') ;;
+ *) for d in $lib
+ do case $HOSTTYPE in
+ *64) if test -d ${d}64
+ then d=${d}64
+ fi
+ ;;
+ esac
+ case :$LD_LIBRARY_PATH: in
+ *:$d:*) ;;
+ *) if test -d $d
+ then LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$d
+ p=1
+ fi
+ ;;
+ esac
+ done
+ ;;
+ esac
+ case $p in
+ 1) $show LD_LIBRARY_PATH=$LD_LIBRARY_PATH
+ $show export LD_LIBRARY_PATH
+ export LD_LIBRARY_PATH
+ ;;
+ esac
+ case $LIBPATH: in
+ $INSTALLROOT/bin:$INSTALLROOT/lib:*)
+ ;;
+ *) case $LIBPATH in
+ '') LIBPATH=/usr/lib:/lib ;;
+ esac
+ LIBPATH=$INSTALLROOT/bin:$INSTALLROOT/lib:$LIBPATH
+ $show LIBPATH=$LIBPATH
+ $show export LIBPATH
+ export LIBPATH
+ ;;
+ esac
+ case $SHLIB_PATH: in
+ $INSTALLROOT/lib:*)
+ ;;
+ *) SHLIB_PATH=$INSTALLROOT/lib${SHLIB_PATH:+:$SHLIB_PATH}
+ $show SHLIB_PATH=$SHLIB_PATH
+ $show export SHLIB_PATH
+ export SHLIB_PATH
+ ;;
+ esac
+ case $DYLD_LIBRARY_PATH: in
+ $INSTALLROOT/lib:*)
+ ;;
+ *) DYLD_LIBRARY_PATH=$INSTALLROOT/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}
+ $show DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH
+ $show export DYLD_LIBRARY_PATH
+ export DYLD_LIBRARY_PATH
+ ;;
+ esac
+ case $_RLD_ROOT in
+ $INSTALLROOT/arch*) ;;
+ ':') _RLD_ROOT=$INSTALLROOT/arch:/ ;;
+ /|*:/) _RLD_ROOT=$INSTALLROOT/arch:$_RLD_ROOT ;;
+ *) _RLD_ROOT=$INSTALLROOT/arch:$_RLD_ROOT:/ ;;
+ esac
+ $show _RLD_ROOT=$_RLD_ROOT
+ $show export _RLD_ROOT
+ export _RLD_ROOT
+
+ # now set up PATH
+ #
+ # NOTE: PACKAGEROOT==INSTALLROOT is possible for binary installations
+
+ case $PATH: in
+ $PACKAGEROOT/bin:*)
+ ;;
+ *) PATH=$PACKAGEROOT/bin:$PATH
+ ;;
+ esac
+ case $PATH: in
+ $INSTALLROOT/bin:*)
+ ;;
+ *) PATH=$INSTALLROOT/bin:$PATH
+ ;;
+ esac
+ $show PATH=$PATH
+ $show export PATH
+ export PATH
+ ;;
+ *) for i in package proto nmake
+ do if onpath $i
+ then EXECROOT=`echo $_onpath_ | sed -e 's,//*[^/]*//*[^/]*$,,'`
+ EXECTYPE=`echo $EXECROOT | sed -e 's,.*/,,'`
+ break
+ fi
+ done
+ case $HOSTTYPE in
+ $EXECTYPE)
+ OCC=$CC
+ CC=cc
+ hostinfo type
+ EXECTYPE=$_hostinfo_
+ case $HOSTTYPE in
+ $EXECTYPE)
+ echo "$command: $CC: seems to be a cross-compiler" >&2
+ echo "$command: set HOSTTYPE to something other than the native $EXECTYPE" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ $show EXECTYPE=$EXECTYPE
+ $show export EXECTYPE
+ export EXECTYPE
+ ;;
+ esac
+ $show EXECROOT=$EXECROOT
+ $show export EXECROOT
+ export EXECROOT
+
+ # use these if possible
+
+ OK=ok
+ KSH=$EXECROOT/bin/ksh
+ MAKE=nmake
+ NMAKE=$EXECROOT/bin/$MAKE
+ SUM=$EXECROOT/bin/sum
+ TEE=$EXECROOT/bin/tee
+
+ # grab a decent default shell
+
+ case $KEEP_SHELL in
+ 0) executable "$SHELL" || SHELL=
+ case $SHELL in
+ ?*) checksh $SHELL || SHELL= ;;
+ esac
+ case $SHELL in
+ ''|/bin/*|/usr/bin/*)
+ case $SHELL in
+ '') SHELL=/bin/sh ;;
+ esac
+ for i in ksh sh bash
+ do if onpath $i && checksh $_onpath_
+ then SHELL=$_onpath_
+ break
+ fi
+ done
+ ;;
+ */*ksh) if executable $KSH
+ then SHELL=$KSH
+ fi
+ ;;
+ esac
+ ;;
+ esac
+
+ # $SHELL must be /bin/sh compatible
+
+ case $SHELL in
+ /bin/sh);;
+ '') SHELL=/bin/sh
+ ;;
+ *) $SHELL -c 'trap "exit 0" 0; exit 1' 2>/dev/null
+ case $? in
+ 1) SHELL=/bin/sh
+ ;;
+ *) # catch (our own) pipe/socket configuration mismatches
+ $SHELL -c "date | $SHELL -c 'read x'"
+ case $? in
+ 0) ;;
+ *) SHELL=/bin/sh ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ export SHELL
+ $show SHELL=$SHELL
+ $show export SHELL
+ COSHELL=$SHELL
+ export COSHELL
+ $show COSHELL=$COSHELL
+ $show export COSHELL
+
+ # tame the environment
+
+ case $action in
+ use) ;;
+ *) ENV=
+ ERROR_OPTIONS=
+ export ENV ERROR_OPTIONS
+ ;;
+ esac
+
+ # finalize the views
+
+ case $USER_VPATH in
+ '') case $VPATH in
+ ?*) IFS=':'
+ set '' $VPATH
+ shift
+ IFS=$ifs
+ USER_VPATH=
+ for i
+ do case $i in
+ */arch/$HOSTTYPE) ;;
+ */arch/*/*) ;;
+ */arch/*) continue ;;
+ esac
+ if packageroot $i
+ then case $USER_VPATH in
+ '') USER_VPATH=$i ;;
+ ?*) USER_VPATH=$USER_VPATH:$i ;;
+ esac
+ fi
+ done
+ esac
+ ;;
+ esac
+ case $USER_VPATH in
+ ?*) IFS=':'
+ set '' $USER_VPATH
+ shift
+ IFS=$ifs
+ USER_VPATH=
+ USER_VPATH_CHAIN=
+ p=$PACKAGEROOT
+ for i
+ do case $i in
+ ''|$PACKAGEROOT|$INSTALLROOT)
+ ;;
+ ?*) USER_VPATH=$USER_VPATH:$i
+ USER_VPATH_CHAIN="$USER_VPATH_CHAIN $p $i"
+ p=$i
+ case $PROTOROOT in
+ -) executable $i/bin/mamake && PROTOROOT= ;;
+ esac
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+esac
+PACKAGESRC=$PACKAGEROOT/lib/package
+PACKAGEBIN=$INSTALLROOT/lib/package
+case $action:$run in
+use:-) set '' $args
+ shift
+ case $# in
+ 0) ;;
+ *) shift ;;
+ esac
+ run="$@"
+ ;;
+esac
+
+# more cygwin hassles
+
+case $HOSTTYPE in
+cygwin.*)
+ lose=
+ case $CYGWIN in
+ *nontsec*)
+ lose=ntsec
+ ;;
+ *ntsec*);;
+ *) exe=/tmp/pkg$$.exe
+ rm -f $exe
+ : > $exe
+ if test -x $exe
+ then lose=ntsec
+ fi
+ ;;
+ esac
+ case $CYGWIN in
+ *nobinmode*)
+ case $lose in
+ '') lose=binmode ;;
+ *) lose="$lose binmode" ;;
+ esac
+ ;;
+ esac
+ case $lose in
+ ?*) echo "$command: $HOSTTYPE: export '$lose' in CYGWIN or languish in windows" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+esac
+
+# set up the view state
+
+VIEW_bin=$INSTALLROOT VIEW_src=$PACKAGEROOT VIEW_all="$INSTALLROOT $PACKAGEROOT"
+if (vpath $INSTALLROOT $PACKAGEROOT $USER_VPATH_CHAIN) >/dev/null 2>&1 &&
+ vpath $INSTALLROOT $PACKAGEROOT $USER_VPATH_CHAIN
+then $show vpath $INSTALLROOT $PACKAGEROOT $USER_VPATH_CHAIN
+else VPATH=$INSTALLROOT:$PACKAGEROOT$USER_VPATH
+ $show VPATH=$VPATH
+ $show export VPATH
+ export VPATH
+ IFS=':'
+ set '' $VPATH
+ shift
+ IFS=$ifs
+ for i
+ do case $i in
+ */arch/*/*)
+ VIEW_src="$VIEW_src $i"
+ ;;
+ */arch/*)
+ VIEW_bin="$VIEW_bin $i"
+ ;;
+ *)
+ VIEW_src="$VIEW_src $i"
+ ;;
+ esac
+ VIEW_all="$VIEW_all $i"
+ done
+fi
+
+# return 0 if arg in src|bin|all view
+
+view() # [test] [-|type] [src|bin|all] file
+{
+ case $1 in
+ -[dfsx])_view_T_=$1; shift ;;
+ *) _view_T_=-f ;;
+ esac
+ case $1 in
+ -) _view_t_= ;;
+ *) _view_t_=$1 ;;
+ esac
+ shift
+ case $1 in
+ all) shift; _view_v_=$VIEW_all ;;
+ bin) shift; _view_v_=$VIEW_bin ;;
+ src) shift; _view_v_=$VIEW_src ;;
+ *) _view_v_=$VIEW_all ;;
+ esac
+ case $1 in
+ /*) if test $_view_T_ $1
+ then _view_=$1
+ return 0
+ fi
+ ;;
+ *) for _view_d_ in $_view_v_
+ do if test $_view_T_ $_view_d_/$1
+ then _view_=$_view_d_/$1
+ return 0
+ fi
+ done
+ ;;
+ esac
+ _view_=
+ case $_view_t_ in
+ ?*) echo $command: $1: $_view_t_ not found >&2 ;;
+ esac
+ return 1
+}
+
+# determine the package and targets
+
+case $action in
+admin) case $admin_action in
+ results)action=$admin_action
+ set '' $admin_args
+ shift;shift
+ admin_args="admin $*"
+ case $admin_on in
+ '') target=$admin_args ;;
+ *) target="on $admin_on $admin_args" ;;
+ esac
+ ;;
+ esac
+ ;;
+release)set '' $args
+ target=
+ while :
+ do shift
+ case $1 in
+ -|[0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789])
+ target="$target $1"
+ ;;
+ *) break
+ ;;
+ esac
+ done
+ package=$*
+ ;;
+setup) # { update read } with optional (bin|fun|include|lib) symlinks
+ # flat option sets up { bin fun include lib } symlinks from
+ # $INSTALLROOT to $PACKAGEROOT
+
+ # . is the package root
+
+ set '' $args
+ shift
+ types=
+ url=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ flat) flat=1 # backwards compatibility -- documentation dropped
+ ;;
+ *://*|*.url)
+ url=$1
+ shift
+ break
+ ;;
+ *) types="$types $1"
+ ;;
+ esac
+ shift
+ done
+ if test ! -d $PACKAGEROOT/lib/package/tgz
+ then $exec mkdir -p $PACKAGEROOT/lib/package/tgz || exit
+ fi
+ case " $types " in
+ *" source "*)
+ case " $* " in
+ ' ') ;;
+ *" INIT "*)
+ ;;
+ *) view - all src/cmd/INIT ||
+ set INIT "$@"
+ ;;
+ esac
+ ;;
+ esac
+ packages=`$0 $global authorize "$authorize" password "$password" update setup $types $url "$@" PACKAGEROOT=$PACKAGEROOT`
+ case $packages in
+ ?*) $0 $global read $packages PACKAGEROOT=$PACKAGEROOT
+ esac
+ exit
+ ;;
+*) package=
+ target=
+ set '' $args
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ ''|-) target="$target $package"
+ package=
+ ;;
+ *) if view - src "lib/package/$1.pkg"
+ then package="$package $1"
+ else target="$target $package $1"
+ package=
+ fi
+ ;;
+ esac
+ done
+ ;;
+esac
+
+# flatten -- assumes symlink support
+
+case $flat in
+1) case $action in
+ make|read|setup|update|use|view)
+ if test ! -d $INSTALLROOT
+ then $exec mkdir -p $INSTALLROOT || exit
+ fi
+ for i in bin include lib fun man share
+ do if test ! -d $INSTALLROOT/../../$i
+ then $exec mkdir $INSTALLROOT/../../$i
+ fi
+ if test ! -d $INSTALLROOT/$i
+ then if test ! -h $INSTALLROOT/$i
+ then $exec ln -s ../../$i $INSTALLROOT/$i
+ fi
+ elif test ! -h $INSTALLROOT/$i
+ then for x in $INSTALLROOT/$i/.[a-z]* $INSTALLROOT/$i/*
+ do if test -f $x -o -d $x
+ then if test ! -d $INSTALLROOT/$i/$x || test ! -d $INSTALLROOT/../../$i/$x
+ then $exec mv $x $INSTALLROOT/../../$i
+ fi
+ fi
+ done
+ $exec rm -rf $INSTALLROOT/$i
+ $exec ln -s ../../$i $INSTALLROOT/$i
+ fi
+ done
+ ;;
+ esac
+ ;;
+esac
+
+# check that cmd args are up to date a.out's
+
+checkaout() # cmd ...
+{
+ case $PROTOROOT in
+ -) PROTOROOT=
+ case $* in
+ ratz) if test -f $INITROOT/ratz.c -a -w $PACKAGEROOT
+ then test -f $INITROOT/hello.c || {
+ cat > $INITROOT/hello.c <<'!'
+#ifndef printf
+#include <stdio.h>
+#endif
+int main() { int new = 0; printf("hello world\n"); return new;}
+!
+ }
+ test -f $INITROOT/p.c || {
+ cat > $INITROOT/p.c <<'!'
+/*
+ * small test for prototyping cc
+ */
+
+int main(int argc, char** argv) { return argc || argv; }
+!
+ }
+ fi
+ ;;
+ esac
+ test -f $INITROOT/hello.c -a -f $INITROOT/p.c -a -w $PACKAGEROOT || {
+ for i
+ do onpath $i || {
+ echo "$command: $i: command not found" >&2
+ return 1
+ }
+ done
+ return 0
+ }
+ case $cc in
+ '') _PACKAGE_cc=0
+ ;;
+ *) _PACKAGE_cc=1
+ test -f $INITROOT/hello.c -a -f $INITROOT/p.c || {
+ echo "$command: $INITROOT: INIT package source not found" >&2
+ return 1
+ }
+ executable $INSTALLROOT/bin/nmake || {
+ # check for prototyping cc
+ # NOTE: proto.c must be K&R compatible
+
+ $CC -c $INITROOT/p.c >/dev/null 2>&1
+ c=$?
+ rm -f p.*
+ test 0 != "$c" && {
+ checkaout proto || return
+ PROTOROOT=$PACKAGEROOT/proto
+ $show PROTOROOT=$PACKAGEROOT/proto
+ export PROTOROOT
+ INITPROTO=$PROTOROOT/src/cmd/INIT
+ note proto convert $PACKAGEROOT/src into $PROTOROOT/src
+ if test -d $PACKAGEROOT/src/cmd/nmake
+ then dirs="src/cmd/INIT src/lib/libast src/lib/libardir src/lib/libcoshell src/lib/libpp src/cmd/probe src/cmd/cpp src/cmd/nmake"
+ else dirs="src"
+ fi
+ (
+ if test -f $PROTOROOT/UPDATE
+ then newer="-newer $PROTOROOT/UPDATE"
+ else newer=""
+ fi
+ case $exec in
+ '') cd $PACKAGEROOT
+ find $dirs -name '*.[CcHh]' $newer -print | proto -v -L - -C proto
+ ;;
+ *) $exec cd $PACKAGEROOT
+ $exec "find $dirs -name '*.[CcHh]' $newer -print | proto -L - -C proto"
+ ;;
+ esac
+ $exec touch $PROTOROOT/UPDATE
+ )
+ if (vpath $INSTALLROOT - $INSTALLROOT $PROTOROOT $PROTOROOT $PACKAGEROOT) >/dev/null 2>&1 &&
+ vpath $INSTALLROOT - $INSTALLROOT $PROTOROOT $PROTOROOT $PACKAGEROOT
+ then $show vpath $INSTALLROOT $PROTOROOT $PROTOROOT $PACKAGEROOT $USER_VPATH_CHAIN
+ else VPATH=$INSTALLROOT:$PROTOROOT:$PACKAGEROOT$USER_VPATH
+ $show VPATH=$VPATH
+ export VPATH
+ fi
+ }
+ }
+ for i in arch arch/$HOSTTYPE arch/$HOSTTYPE/bin
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || return
+ done
+ ;;
+ esac
+ ;;
+ esac
+ case $_PACKAGE_cc in
+ '') case $cc in
+ '') _PACKAGE_cc=0 ;;
+ *) _PACKAGE_cc=1 ;;
+ esac
+ ;;
+ esac
+ for i
+ do eval j=\$_PACKAGE_AOUT_$i
+ case $j in
+ '') eval _PACKAGE_AOUT_$i=1 ;;
+ *) continue ;;
+ esac
+ k=$_PACKAGE_cc
+ if test -f $INITROOT/$i.c
+ then k=${k}1
+ else k=${k}0
+ fi
+ if executable $EXECROOT/bin/$i
+ then k=${k}1
+ else k=${k}0
+ fi
+ : $k : compiler : source : binary :
+ case $k in
+ *00) view - bin/$i && continue ;;
+ esac
+ case $k in
+ 000) echo "$command: $i: not found: download the INIT package $HOSTTYPE binary to continue" >&2
+ return 1
+ ;;
+ 010) echo "$command: $i: not found: set CC=C-compiler or download the INIT package $HOSTTYPE binary to continue" >&2
+ return 1
+ ;;
+ 100) echo "$command: $i: not found: download the INIT package source or $HOSTTYPE binary to continue" >&2
+ return 1
+ ;;
+ 110) case $CROSS in
+ 1) echo "$command: $i: not found: make the local $EXECTYPE binary package before $HOSTTYPE" >&2
+ return 1
+ ;;
+ esac
+ ;;
+ ?01) : accept binary
+ continue
+ ;;
+ 011) : accept binary
+ continue
+ ;;
+ ??1) case $CROSS in
+ 1) continue ;;
+ esac
+ ;;
+ esac
+ case `ls -t $INITROOT/$i.c $INSTALLROOT/bin/$i 2>/dev/null` in
+ "$INITROOT/$i.c"*)
+ note update $INSTALLROOT/bin/$i
+ if test proto != "$i" && executable $INSTALLROOT/bin/proto
+ then case $exec in
+ '') $INSTALLROOT/bin/proto -p $INITROOT/$i.c > $i.c || return ;;
+ *) $exec "$INSTALLROOT/bin/proto -p $INITROOT/$i.c > $i.c" ;;
+ esac
+ $exec $CC $CCFLAGS -o $INSTALLROOT/bin/$i $i.c || return
+ $exec rm -f $i.c
+ else if test ! -d $INSTALLROOT/bin
+ then for j in arch arch/$HOSTTYPE arch/$HOSTTYPE/bin
+ do test -d $PACKAGEROOT/$j || $exec mkdir $PACKAGEROOT/$j || return
+ done
+ fi
+ if test '' != "$PROTOROOT" -a -f $INITPROTO/$i.c
+ then $exec $CC $CCFLAGS -o $INSTALLROOT/bin/$i $INITPROTO/$i.c || return
+ else $exec $CC $CCFLAGS -o $INSTALLROOT/bin/$i $INITROOT/$i.c || return
+ fi
+ case $i:$exec in
+ proto:) test -d $INSTALLROOT/include || mkdir $INSTALLROOT/include
+ $INSTALLROOT/bin/proto -f /dev/null > $i.c
+ cmp -s $i.c $INSTALLROOT/include/prototyped.h 2>/dev/null || cp $i.c $INSTALLROOT/include/prototyped.h
+ rm $i.c
+ ;;
+ esac
+ fi
+ test -f $i.o && $exec rm -f $i.o
+ i=$PATH
+ PATH=/bin
+ PATH=$i
+ ;;
+ esac
+ done
+ return 0
+}
+
+# check package requirements against received packages
+
+requirements() # source|binary [ package ]
+{
+ case $1 in
+ binary) r=$VIEW_BIN ;;
+ source) r=$VIEW_SRC ;;
+ *) r=$VIEW_ALL ;;
+ esac
+ shift
+ case $1 in
+ '') x= ;;
+ *) x=$* ;;
+ esac
+ set ''
+ for d in $r
+ do set "$@" $d/gen/*.ver
+ case $x in
+ '') set "$@" $d/gen/*.req
+ ;;
+ *) for p in $x
+ do set "$@" $d/gen/$p.req
+ done
+ ;;
+ esac
+ done
+ shift
+ e=0
+ x=$*
+ y=
+ n=
+ set ''
+ for i in $x
+ do p=`echo $i | sed -e 's,.*/,,' -e 's,\....$,,'`
+ if test -f $i
+ then set "$@" $i
+ y="$y $p"
+ else case $p in
+ '*') ;;
+ *) n="$n $p" ;;
+ esac
+ fi
+ done
+ for i in $n
+ do case " $y " in
+ *" $i "*)
+ ;;
+ *) echo "$command: $i: must read or write package" >&2
+ e=1
+ ;;
+ esac
+ done
+ case $e in
+ 1) exit 1 ;;
+ esac
+ shift
+ test 0 != "$#" && release=`sort -r "$@" | {
+ q=
+ e=0
+ o=
+ while read p v r s
+ do q="$q
+$v $r"
+ case $p in
+ $o) continue ;;
+ esac
+ case $s in
+ 0) e=1
+ case $r in
+ base) echo "$command: base package $p.$v or newer required" >&2 ;;
+ *) echo "$command: delta package $p.$v.$r or newer required" >&2 ;;
+ esac
+ ;;
+ esac
+ o=$p
+ done
+ case $e in
+ 0) echo "$q" | sort | { read v r; read v r; echo $v; } ;;
+ 1) echo ERROR ;;
+ esac
+ }`
+ case $release in
+ ERROR) case $force in
+ 0) exit 1 ;;
+ esac
+ ;;
+ ?*) eval `echo $release | sed -e 's,\(.*\)-\(.*\)-\(.*\),yy=\1 mm=\2 dd=\3,'`
+ # slide back 4 months
+ case $mm in
+ 01) mm=09 dd=1 ;;
+ 02) mm=10 dd=1 ;;
+ 03) mm=11 dd=1 ;;
+ 04) mm=12 dd=1 ;;
+ 05) mm=01 dd=0 ;;
+ 06) mm=02 dd=0 ;;
+ 07) mm=03 dd=0 ;;
+ 08) mm=04 dd=0 ;;
+ 09) mm=05 dd=0 ;;
+ 10) mm=06 dd=0 ;;
+ 11) mm=07 dd=0 ;;
+ 12) mm=08 dd=0 ;;
+ esac
+ case $dd in
+ 1) yy=`expr $yy - 1` ;;
+ esac
+ release=$yy-$mm-01
+ count=1
+ lo=$release
+ release="-f $release -r $count"
+ ;;
+ esac
+}
+
+# write ordered package prerequisite list to the standard output
+
+order() # [ package ]
+{
+ _order_t_=lib/package/tgz
+ case $action in
+ binary) _order_a_=.$HOSTTYPE ;;
+ *) _order_a_= ;;
+ esac
+ _order_n_=$#
+ case $_order_n_ in
+ 0) _order_p_=
+ for _order_v_ in $VIEW_all
+ do for _order_f_ in $_order_v_/lib/package/*.pkg
+ do if test -f $_order_f_
+ then _order_p_="$_order_p_ $_order_f_"
+ fi
+ done
+ done
+ set '' $_order_p_
+ shift
+ esac
+ {
+ if test ratz != "$*"
+ then for _order_f_ in ratz INIT
+ do if view -s - src $_order_t_/$_order_f_$_order_a_.tim
+ then echo $_order_f_ $_order_f_
+ fi
+ done
+ fi
+ for _order_f_
+ do while :
+ do view - src $_order_f_ && break
+ case $_order_f_ in
+ *.pkg) ;;
+ *) _order_f_=$_order_f_.pkg; view - src $_order_f_ && break ;;
+ esac
+ case $_order_f_ in
+ */*) ;;
+ *) _order_f_=lib/package/$_order_f_; view - src $_order_f_ && break ;;
+ esac
+ echo "$command: $_order_f_: not a package" >&2
+ continue 2
+ done
+ _order_f_=$_view_
+ _order_p_=`echo $_order_f_ | sed -e 's,.*/,,' -e 's,\.pkg$,,'`
+ case $_order_n_ in
+ 0) view -s - src $_order_t_/$_order_p_$_order_a_.tim || continue ;;
+ esac
+ echo $_order_p_ $_order_p_
+ case $_order_p_ in
+ INIT|ratz)
+ ;;
+ *) echo INIT $_order_p_
+ ;;
+ esac
+ {
+ req= req_sep=
+ op=::
+ while read line
+ do IFS=' \\'
+ set '' $line
+ IFS=$ifs
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :*:) op=$1
+ ;;
+ INIT|'$('*|*')')
+ ;;
+ *) case $op in
+ :REQUIRES:)
+ req="$req$req_sep$1"
+ req_sep=" "
+ ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ for _order_i_ in $req
+ do if view - src lib/package/$_order_i_.pkg
+ then case $_order_u_ in
+ 0) view -s - src $_order_t_/$_order_i_$_order_a_.tim || continue ;;
+ esac
+ echo $_order_i_ $_order_i_; echo INIT $_order_i_; echo $_order_i_ $_order_p_
+ fi
+ done
+ } < $_order_f_
+ done
+ } | tsort
+}
+
+# generate the package component list in _components_
+
+components() # [ package ]
+{
+ _components_=
+ for p
+ do case $p in
+ '') ;;
+ INIT) case " $_components_ " in
+ *" $p "*) ;;
+ *) _components_="$_components_ $p" ;;
+ esac
+ ;;
+ *) if view - src lib/package/$p.pkg
+ then p=$_view_
+ op=::
+ exec < $p
+ while read line
+ do IFS=' \\'
+ set '' $line
+ IFS=$ifs
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :*:) op=$1
+ ;;
+ INIT|'$('*|*')')
+ ;;
+ *) case $op in
+ :PACKAGE:)
+ case " $_components_ " in
+ *" $1 "*) ;;
+ *) _components_="$_components_ $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ exec < /dev/null
+ elif test -d $PACKAGEROOT/src/cmd/$p -o -d $PACKAGEROOT/src/lib/$p
+ then _components_="$_components_ $p"
+ else echo "$command: $p: package or component not found" >&2
+ exit 1
+ fi
+ ;;
+ esac
+ done
+}
+
+# list main environment values
+
+showenv()
+{
+ case $1 in
+ ''|make)for __i__ in CC SHELL $env
+ do eval echo $__i__='$'$__i__
+ done
+ ;;
+ esac
+}
+
+# capture command output
+
+capture() # file command ...
+{
+ case $make:$noexec in
+ :) case $action in
+ install|make|view)
+ o=$action
+ ;;
+ *) case $package in
+ ''|*' '*)
+ o=$action
+ ;;
+ *) o=$package
+ ;;
+ esac
+ ;;
+ esac
+ case $action in
+ write) d=$PACKAGESRC/gen ;;
+ *) d=$PACKAGEBIN/gen ;;
+ esac
+ test -d $d || $exec mkdir $d
+ o=$d/$o
+ case $o in
+ $output)o=$o.out
+ s=
+ ;;
+ *) output=$o
+ if test -f $o.old
+ then mv $o.old $o.out.1
+ if test -f $o.out
+ then mv $o.out $o.out.2
+ fi
+ elif test -f $o.out
+ then for i in `ls -t $o.out.? 2>/dev/null`
+ do break
+ done
+ case $i in
+ *.1) i=2 ;;
+ *.2) i=3 ;;
+ *.3) i=4 ;;
+ *.4) i=5 ;;
+ *.5) i=6 ;;
+ *.6) i=7 ;;
+ *.7) i=8 ;;
+ *.8) i=9 ;;
+ *) i=1 ;;
+ esac
+ mv $o.out $o.out.$i
+ fi
+ o=$o.out
+ : > $o
+ note $action output captured in $o
+ s="$command: $action start at `date` in $INSTALLROOT"
+ case $quiet in
+ 0) trap "echo \"$command: $action done at \`date\`\" in $INSTALLROOT 2>&1 | \$TEE -a $o" 0 1 2 ;;
+ *) trap "echo \"$command: $action done at \`date\`\" in $INSTALLROOT >> $o" 0 1 2 ;;
+ esac
+ ;;
+ esac
+ case $quiet in
+ 0) if executable ! $TEE
+ then TEE=tee
+ fi
+ {
+ case $s in
+ ?*) echo "$s" ;;
+ esac
+ showenv $action
+ "$@"
+ } < /dev/null 2>&1 | $TEE -a $o
+ ;;
+ *) {
+ case $s in
+ ?*) echo "$s" ;;
+ esac
+ showenv $action
+ "$@"
+ } < /dev/null > $o 2>&1
+ ;;
+ esac
+ ;;
+ *) $make "$@"
+ ;;
+ esac
+}
+
+package_install() # dest sum
+{
+ dest=$1 sum=$2
+ ot=
+ code=0
+ sed -e '/ /!d' -e 's,[^ ]* ,,' -e 's, \(arch/[^/]*\)/, \1 ,' -e '/ arch\//!s,^[^ ]* [^ ]* [^ ]*,& .,' -e 's,/\([^ /]*\)$, \1,' $sum |
+ while read mode user group arch dir file
+ do case $flat:$arch in
+ 1:*|?:.)t=$dest/$dir ;;
+ *) t=$dest/$arch/$dir ;;
+ esac
+ case $t in
+ $ot) ;;
+ *) if test ! -d "$t"
+ then $exec mkdir -p "$t" || exit
+ fi
+ ot=$t
+ ;;
+ esac
+ case $file in
+ ?*) case $arch in
+ .) f=$dir/$file ;;
+ *) f=$arch/$dir/$file ;;
+ esac
+ if test -f "$f"
+ then t=$t/$file
+ case $quiet in
+ 0) echo "$t" ;;
+ esac
+ $exec cp -f "$f" "$t" || code=1
+ $exec chmod $mode "$t" || code=1
+ fi
+ ;;
+ esac
+ done
+ return $code
+}
+
+package_verify() # sum
+{
+ $exec $SUM -cp $1
+}
+
+make_recurse() # dir
+{
+ for _make_recurse_j in $makefiles
+ do if view - $1/$_make_recurse_j
+ then return
+ fi
+ done
+ if test -d $1
+ then case $exec in
+ '') echo :MAKE: > $1/Makefile || exit ;;
+ *) $exec "echo :MAKE: > $1/Makefile" ;;
+ esac
+ fi
+}
+
+get() # host path [ file size ]
+{
+ case $HURL in
+ '') HURL=.
+ for i in wget lynx curl
+ do if onpath $i
+ then HURL=$i
+ break;
+ fi
+ done
+ AUTHORIZE="User-Agent: package AT&T Research\\r\\n"
+ case $HURL:$authorize in
+ .:?*) AUTHORIZE="${AUTHORIZE}Authorization: Basic `print -n -r -- $authorize:$password | uuencode -h -x base64`\\r\\n" ;;
+ esac
+ ;;
+ esac
+ getfd=8
+ case $3 in
+ '') case $HURL in
+ .) host=$1
+ path=$2
+ while :
+ do eval "exec $getfd<> /dev/tcp/$host/80" || exit
+ case $path in
+ /*) ;;
+ *) path=/$path ;;
+ esac
+ print "GET $path HTTP/1.0\\r\\nHost: $host\\r\\n$AUTHORIZE\\r" >&$getfd
+ cat <&8 > get.tmp
+ got=`sed -e 1q get.tmp`
+ case $got in
+ *" "200" "*)
+ got=`sed -e '1,/^.$/d' -e '/^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]/!d' get.tmp`
+ : > get.err
+ code=0
+ break
+ ;;
+ *" "30[123]" "*)
+ got=`sed -e '/^Location: /!d' -e 's,^Location: \(.*\)://\([^/]*\)\(/.*\),prot='\''\1'\'' host='\''\2'\'' path='\''\3'\'',' get.tmp`
+ case $got in
+ '') rm get.tmp
+ echo "$command: $action: $url: redirect error" >&2
+ exit 1
+ ;;
+ esac
+ eval $got
+ ;;
+ *) rm get.tmp
+ echo "$command: $action: $url: $got" >&2
+ echo '' "$got" > get.err
+ code=1
+ break
+ ;;
+ esac
+ done
+ ;;
+ curl) case $authorize in
+ '') curl -s -L -o get.tmp http://$1/$2 2> get.err; code=$? ;;
+ *) curl -s -L -o get.tmp -u "$authorize":"$password" http://$1/$2 2> get.err; code=$? ;;
+ esac
+ got=`grep '^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]' get.tmp 2>/dev/null`
+ case $code in
+ 0) if grep '^<H1>Authorization Required</H1>' get.tmp > get.err
+ then code=1
+ fi
+ ;;
+ esac
+ ;;
+ hurl) case $authorize in
+ '') hurl http://$1/$2 > get.tmp 2> get.err; code=$? ;;
+ *) hurl -a "$authorize":"$password" http://$1/$2 > get.tmp 2> get.err; code=$? ;;
+ esac
+ got=`grep '^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]' get.tmp`
+ ;;
+ lynx) case $authorize in
+ '') lynx -source http://$1/$2 > get.tmp 2> get.err; code=$? ;;
+ *) lynx -source -auth "$authorize":"$password" http://$1/$2 > get.tmp 2> get.err; code=$? ;;
+ esac
+ got=`grep '^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]' get.tmp`
+ ;;
+ wget) wget -nv -O get.tmp ${authorize:+--http-user="$authorize"} ${password:+--http-passwd="$password"} http://$1/$2 2> get.err
+ code=$?
+ got=`grep '^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]' get.tmp 2>/dev/null`
+ ;;
+ *) echo $command: $action: $HURL: url get command not found >&2
+ exit 1
+ ;;
+ esac
+ if test 0 != "$code"
+ then case `cat get.err get.tmp 2>/dev/null` in
+ *[Aa][Uu][Tt][Hh][Oo][Rr][Ii][SsZz]*|*[Dd][Ee][Nn][Ii][Ee][Dd]*)
+ echo $command: $action: authorization required -- see $url for license acceptance authorization name and password >&2
+ ;;
+ *) cat get.err
+ ;;
+ esac
+ rm -f get.tmp get.err
+ echo $command: $action: $2: download failed >&2
+ exit 1
+ fi
+ rm -f get.tmp get.err
+ ;;
+ *) case $exec in
+ '') echo "$3 ($4 bytes):" >&2
+ case $HURL in
+ .) eval "exec $getfd<> /dev/tcp/$1/80" || exit
+ path=$2/$3
+ case $path in
+ /*) ;;
+ *) path=/$path ;;
+ esac
+ print "GET $path HTTP/1.0\\r\\nHost: $host\\r\\n$AUTHORIZE\\r" >&$getfd
+ read got <&$getfd
+ case $got in
+ *" 200 "*)
+ code=0
+ : > get.err
+ ;;
+ *) echo '' "$got" > get.err
+ code=1
+ ;;
+ esac
+ while read got <&$getfd
+ do case $got in
+ ''|?) break ;;
+ esac
+ done
+ cat <&$getfd > get.tmp
+ ;;
+ curl) case $authorize in
+ '') curl -s -L -o get.tmp http://$1/$2/$3 2> get.err; code=$? ;;
+ *) curl -s -L -o get.tmp -u "$authorize":"$password" http://$1/$2/$3 2> get.err; code=$?
+ esac
+ case $code in
+ 0) if grep '^<H1>Authorization Required</H1>' get.tmp > get.err
+ then code=1
+ fi
+ ;;
+ esac
+ ;;
+ hurl) case $authorize in
+ '') ksh -x hurl http://$1/$2/$3 > get.tmp 2> get.err; code=$? ;;
+ *) ksh -x hurl -a "$authorize":"$password" http://$1/$2/$3 > get.tmp 2> get.err; code=$? ;;
+ esac
+ ;;
+ lynx) case $authorize in
+ '') lynx -source http://$1/$2/$3 > get.tmp 2> get.err; code=$? ;;
+ *) lynx -source -auth "$authorize":"$password" http://$1/$2/$3 > get.tmp 2> get.err; code=$? ;;
+ esac
+ ;;
+ wget) wget -nv -O get.tmp ${authorize:+--http-user="$authorize"} ${password:+--http-passwd="$password"} http://$1/$2/$3 2> get.err
+ code=$?
+ ;;
+ *) echo $command: $action: $HURL: url get command not found >&2
+ exit 1
+ ;;
+ esac
+ if test 0 != "$code"
+ then case `cat get.err get.tmp` in
+ *[Aa][Uu][Tt][Hh][Oo][Rr][Ii][SsZz]*|*[Dd][Ee][Nn][Ii][Ee][Dd]*)
+ echo $command: $action: authorization required -- see $url for license acceptance authorization name and password >&2
+ ;;
+ *) cat get.err
+ ;;
+ esac
+ rm get.tmp get.err
+ echo $command: $action: $3: download failed >&2
+ exit 1
+ fi
+ rm get.err
+ case $checksum:$5 in
+ :*|*:-) z=`wc -c < get.tmp`
+ case " $z " in
+ *" $4 "*)
+ ;;
+ *) rm -f get.tmp
+ echo $command: $3: download error: expected $4 bytes, got $z >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ *) z=`$checksum < get.tmp | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'`
+ case " $z " in
+ *" $5 "*)
+ ;;
+ *) rm -f get.tmp
+ echo $command: $3: download $checksum error: expected $5, got $z >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ mv get.tmp $3 || exit
+ ;;
+ *) echo "$3 ($4 bytes)" >&2
+ ;;
+ esac
+ esac
+}
+
+# generate copyright notice
+
+copyright()
+{
+ if test -f $1.lic
+ then echo $1 package general copyright notice
+ echo
+ proto -c'#' -p -s -l $1.lic -o type=verbose,author='*' /dev/null
+ return 0
+ fi
+ case $1 in
+ *-*) eval `echo '' $1 | sed 's/\([^-]*\)-\(.*\)/__j__="\1" __i__="\2"/'`
+ if copyright $__i__ || copyright $__j__
+ then return 0
+ fi
+ ;;
+ esac
+ return 1
+}
+
+# run remote make on host
+
+remote() # host no-exec-background
+{
+ host=$1
+ background=$2
+ eval name=\$${host}_name user=\$${host}_user snarf=\$${host}_snarf type=\$${host}_type rsh=\$${host}_rsh root=\$${host}_root keep=\$${host}_keep log=\$${host}_log
+ case $keep in
+ 1*) ;;
+ *) return ;;
+ esac
+ case $host in
+ $main) ;;
+ *) case $exec in
+ '') exec > $admin_log/$log 2>&1 ;;
+ *) echo "exec > $admin_log/$log 2>&1" ;;
+ esac
+ ;;
+ esac
+ if $admin_ping $name >/dev/null 2>&1 || $admin_ping $name >/dev/null 2>&1
+ then cmd=". ./.profile"
+ case $root in
+ .) root=
+ ;;
+ *) cmd="$cmd && cd $root"
+ root=$root/
+ ;;
+ esac
+ cmd="$cmd && { test -f lib/package/admin/$admin_env && . ./lib/package/admin/$admin_env || true ;} && PATH=\${PWD:-\`pwd\`}/bin:\$PATH \${SHELL:-/bin/sh} -c 'package $admin_args PACKAGEROOT=\${PWD:-\`pwd\`} HOSTTYPE=$type VPATH='"
+ case $admin_binary in
+ '') snarf= ;;
+ esac
+ case $snarf in
+ '') $exec $rsh $user$name "$cmd" $background
+ ;;
+ *?) rcp=`echo $rsh | sed 's/\(.\).*/\1/'`cp
+ case $background in
+ ?*) $exec "{" ;;
+ esac
+ $exec $rsh $user$name "$cmd"
+ eval lst=$admin_list
+ case $admin_pkgs in
+ '') filter=cat ;;
+ *) filter="egrep lib/package/tgz/($admin_pkgs)\\." ;;
+ esac
+ if $exec $rcp $user$name:${root}lib/package/tgz/$lst $PACKAGESRC/tgz
+ then $exec $rcp `$filter $PACKAGESRC/tgz/$lst | sed "s,^,$user$name:,"` $PACKAGESRC/tgz
+ else echo "$command: $user$name:${root}lib/package/tgz/$lst: not found" >&2
+ fi
+ case $background in
+ ?*) $exec "} $background" ;;
+ esac
+ ;;
+ esac
+ else echo "$command: $name: down" >&2
+ fi
+}
+
+# update package_src
+
+checksrc()
+{
+ case $package_src in
+ '') package_src=$src
+ for _i_ in `cd $PACKAGESRC; ls *.def *.lic *.pkg 2>/dev/null | sed 's/[-.].*//'`
+ do case " $package_src " in
+ *" $_i_ "*)
+ ;;
+ *) package_src="$package_src $_i_"
+ ;;
+ esac
+ done
+ ;;
+ esac
+}
+
+# check for native ascii 0:yes 1:no
+
+__isascii__=
+
+isascii()
+{
+ case $__isascii__ in
+ '') case `echo A | od -o | sed -e 's/[ ]*$//' -e '/[ ]/!d' -e 's/.*[ ]//'` in
+ 005101|040412) __isascii__=0 ;;
+ *) __isascii__=1 ;;
+ esac
+ esac
+ return $__isascii__
+}
+
+case $action in
+
+admin) while test ! -f $admin_db
+ do case $admin_db in
+ /*) echo $command: $action: $admin_db: data file not found >&2
+ exit 1
+ ;;
+ esac
+ view file src lib/package/admin/$admin_db || exit 1
+ admin_db=$_view_
+ done
+ admin_components=
+ case $admin_action in
+ list) cat $admin_db
+ exit
+ ;;
+ test) set $admin_args
+ while :
+ do case $# in
+ 1) break ;;
+ esac
+ shift
+ case $1 in
+ *=*) ;;
+ *) admin_components=-$1
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ : all work done in $PACKAGESRC/admin
+ cd $PACKAGESRC/admin || exit
+ checksrc
+ packages=
+ admin_log=${admin_action}${admin_components}.log
+ exec < $admin_db || exit
+ test -d $admin_log || $exec mkdir $admin_log || exit
+ case $admin_on in
+ '') admin_on="*" ;;
+ esac
+ hostname=
+ hosts=
+ logs=
+ local_hosts=
+ local_types=
+ pids=
+ remote_hosts=
+ sync_hosts=
+ admin_host=_admin_host_
+ admin_out=
+ case " $admin_args " in
+ *" write binary "*|*" write "*" binary "*)
+ admin_binary=1
+ ;;
+ *) admin_binary=
+ ;;
+ esac
+ case $only in
+ 1) admin_args="only $admin_args" ;;
+ esac
+ trap 'kill $pids >/dev/null 2>&1' 1 2 3 15
+ index=0
+ while read type host root date time make test write comment
+ do case $type in
+ ''|'#'*);;
+ *=*) eval "$type $host $root $date $time $make $test $write $comment"
+ ;;
+ *) case $admin_action in
+ make|test|write)
+ eval f='$'$admin_action
+ case $f in
+ *[!0123456789]*) continue ;;
+ esac
+ ;;
+ esac
+ rsh=rsh
+ case $host in
+ *@*) IFS=@
+ set '' $host
+ IFS=$ifs
+ user=${2}@
+ host=$3
+ ;;
+ *) user=
+ ;;
+ esac
+ : type=$type host=$host root=$root date=$date time=$time make=$make test=$test write=$write :
+ name=$host
+ host=`echo $name | sed 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789],__,g'`
+ eval x='$'${host}_index
+ eval ${host}_index=1
+ case $x in
+ 1) i=0
+ while :
+ do case $i in
+ $index) h=''
+ break
+ ;;
+ esac
+ i=`expr $i + 1`
+ eval h='$'${admin_host}${i}_name
+ case $h in
+ $host) host=${admin_host}${i}
+ eval user='$'${host}_user root='$'${host}_rsh:$host:'$'${host}_root
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ case $root in
+ *:$name:*)root=`echo '' $root | sed 's,:.*,:,'` ;;
+ esac
+ case $root in
+ *:*:*) index=`expr $index + 1`
+ host=${admin_host}$index
+ ;;
+ *:*) case " $sync_hosts " in
+ *" $name ${admin_host}"*)
+ set '' '' $sync_hosts
+ while :
+ do shift
+ shift
+ case $1 in
+ $name) host=$2
+ break
+ ;;
+ esac
+ done
+ ;;
+ *) index=`expr $index + 1`
+ host=${admin_host}$index
+ sync_hosts="$sync_hosts $name $host"
+ ;;
+ esac
+ ;;
+ *) index=`expr $index + 1`
+ host=${admin_host}$index
+ ;;
+ esac
+ case $root in
+ -*) continue
+ ;;
+ *:*) case $admin_all in
+ 0) continue ;;
+ esac
+ case $root in
+ *:) root=${root}. ;;
+ esac
+ IFS=:
+ set '' $root
+ IFS=$ifs
+ sync=$host
+ case $hostname in
+ '') hostinfo name
+ hostname=$_hostinfo_
+ ;;
+ esac
+ shift
+ case $# in
+ 0) ;;
+ 1) root=$1
+ ;;
+ 2) rsh=$1 root=$2
+ ;;
+ *) rsh=$1 sync=$2 root=$3
+ case $sync in
+ ${admin_host}*)
+ ;;
+ ?*) case " $sync_hosts " in
+ *" $sync ${admin_host}"*)
+ set '' '' $sync_hosts
+ while :
+ do shift
+ shift
+ case $1 in
+ $sync) sync=$2
+ break
+ ;;
+ esac
+ done
+ ;;
+ *) index=`expr $index + 1`
+ x=${admin_host}$index
+ sync_hosts="$sync_hosts $sync $x"
+ sync=$x
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) sync=
+ ;;
+ esac
+ case $name in
+ $admin_on)
+ keep=1
+ ;;
+ *) case " $admin_on " in
+ *" $name "*) keep=1 ;;
+ *) keep=0 ;;
+ esac
+ ;;
+ esac
+ case " $admin_out " in
+ *" $name "*)
+ log=$name.$type
+ ;;
+ *) admin_out="$admin_out $name"
+ log=$name
+ ;;
+ esac
+ case $sync in
+ '') local_types="$local_types $type" ;;
+ esac
+ case $sync in
+ $host) remote_hosts="$remote_hosts $host"
+ ;;
+ ?*) eval ${sync}_share=\"\$${sync}_share $host\"
+ ;;
+ '') local_hosts="$local_hosts $host"
+ ;;
+ esac
+ eval ${host}_name='$'name ${host}_type='$'type ${host}_user='$'user ${host}_sync='$'sync ${host}_snarf='$'sync ${host}_rsh='$'rsh ${host}_root='$'root ${host}_keep='$'keep ${host}_log='$'log
+ ;;
+ esac
+ done
+ p=
+ for i in $admin_args
+ do p="$i $p"
+ done
+ admin_pkgs=
+ for i in $p
+ do if view - src "lib/package/$i.pkg"
+ then case $admin_pkgs in
+ '') admin_pkgs="$i" ;;
+ *) admin_pkgs="$admin_pkgs|$i" ;;
+ esac
+ fi
+ done
+ : "admin_binary :" $admin_binary
+ : "admin_args :" $admin_args
+ : "admin_pkgs :" $admin_pkgs
+ : "admin_on :" "$admin_on"
+ : "local_hosts :" $local_hosts
+ : "local_types :" $local_types
+ : "remote_hosts :" $remote_hosts
+ : "sync_hosts :" $sync_hosts
+ : "sync_share :" $sync_share
+ case $admin_binary in
+ 1) admin_bin_types=
+ admin_bin_main=
+ for main in $local_hosts $remote_hosts
+ do eval share=\$${main}_share keep=\$${main}_keep
+ case $keep in
+ 0*) continue ;;
+ esac
+ for host in $main $share
+ do case " $admin_bin_hosts " in
+ *" $host "*)
+ continue
+ ;;
+ esac
+ eval type=\$${host}_type
+ case " $admin_bin_types " in
+ *" $type "*)
+ continue
+ ;;
+ esac
+ case " $types " in
+ " ") ;;
+ *" $type "*)
+ ;;
+ *) continue
+ ;;
+ esac
+ admin_bin_hosts="$admin_bin_hosts $host"
+ admin_bin_types="$admin_bin_types $type"
+ case " $admin_bin_hosts " in
+ *" $main "*)
+ ;;
+ *) case " $admin_bin_main " in
+ *" $main "*)
+ ;;
+ *) admin_bin_main="$admin_bin_main $main"
+ ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ local=
+ remote=
+ for host in $admin_bin_main $admin_bin_hosts
+ do case " $local_hosts " in
+ *" $host "*)
+ local="$local $host"
+ ;;
+ *) case " $remote_hosts " in
+ *" $host "*)
+ remote="$remote $host"
+ ;;
+ esac
+ ;;
+ esac
+ done
+ local_hosts=$local
+ remote_hosts=$remote
+ ;;
+ esac
+ for host in $remote_hosts $local_hosts
+ do eval share=\$${host}_share
+ case $share in
+ ?*) while :
+ do oshare=$share
+ for s in $share
+ do eval r='$'${s}_share
+ case $r in
+ ?*) case " $share " in
+ *" $r "*) ;;
+ *) share="$share $r" ;;
+ esac
+ ;;
+ esac
+ done
+ case $share in
+ $oshare) eval ${host}_share="'$share'"
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ done
+ for host in $remote_hosts
+ do eval type=\$${host}_type
+ case " $local_types " in
+ *" $type "*)
+ eval ${host}_snarf=
+ ;;
+ esac
+ eval name=\$${host}_name keep=\$${host}_keep share=\$${host}_share
+ for share in $share
+ do eval type=\$${share}_type keep=\$keep\$${share}_keep
+ case " $local_types " in
+ *" $type "*)
+ eval ${share}_snarf=
+ ;;
+ esac
+ done
+ case $keep in
+ 0*1*) keep=2$keep ;;
+ *1*) ;;
+ *) keep=0 ;;
+ esac
+ eval ${host}_keep=$keep
+ done
+ for host in $remote_hosts $local_hosts
+ do eval name=\$${host}_name user=\$${host}_user type=\$${host}_type sync=\$${host}_sync snarf=\$${host}_snarf share=\$${host}_share rsh=\$${host}_rsh root=\$${host}_root keep=\$${host}_keep
+ case $keep in
+ 0*) continue ;;
+ esac
+ case $sync in
+ '') case $admin_action in
+ ditto) continue ;;
+ esac
+ case $admin_binary in
+ 1) case $keep in
+ 1*|?*1*);;
+ *) continue ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ eval main_log='$'${host}_log
+ main=
+ share_keep=
+ for i in $host $share
+ do eval n='$'${i}_name t='$'${i}_type q='$'${i}_sync s='$'${i}_snarf l='$'${i}_log k='$'${i}_keep
+ case $main:$k in
+ :*) ;;
+ *:0) continue ;;
+ esac
+ case $admin_binary in
+ 1) case $s:$q in
+ :?*) continue ;;
+ esac
+ case " $admin_bin_hosts " in
+ *" $i "*)
+ ;;
+ *) continue
+ ;;
+ esac
+ ;;
+ esac
+ case $main in
+ '') main=$i ;;
+ *) share_keep="$share_keep $i" ;;
+ esac
+ echo package "$admin_args" "[ $n $t ]"
+ case $exec in
+ '') : > $admin_log/$l ;;
+ *) $exec ": > $admin_log/$l" ;;
+ esac
+ done
+ host=$main
+ share=$share_keep
+ case $force in
+ 0) admin_ditto_update=--update ;;
+ *) admin_ditto_update= ;;
+ esac
+ case $exec in
+ '') {
+ case $admin_binary:$sync in
+ :?*) eval syncname='$'${sync}_name
+ test -x $PACKAGEROOT/bin/package && $admin_ditto $admin_ditto_update --remote=$rsh --expr="name=='package'" $PACKAGEROOT/bin $user$syncname:$root/bin
+ test -d $PACKAGESRC && $admin_ditto $admin_ditto_update --remote=$rsh --expr="if(level>1&&path!='LICENSES/*')status=SKIP;path=='LICENSES*|*.(pkg|lic|def)'" $PACKAGESRC $user$syncname:$root/lib/package
+ for dir in $package_src
+ do case $MAKESKIP in
+ '') expr="--expr=if(name=='$admin_ditto_skip')status=SKIP" ;;
+ *) expr="--expr=if(name=='$admin_ditto_skip'||level==1&&name=='$MAKESKIP')status=SKIP" ;;
+ esac
+ test -d $PACKAGEROOT/src/$dir && $admin_ditto $admin_ditto_update --remote=$rsh "$expr" $PACKAGEROOT/src/$dir $user$syncname:$root/src/$dir
+ done
+ ;;
+ esac
+ case $admin_action in
+ ditto) ;;
+ ?*) pids=
+ set '' $host $share
+ while :
+ do shift
+ case $# in
+ 0) break
+ ;;
+ 1) remote $1
+ ;;
+ *) remote $1 &
+ pids="$pids $!"
+ ;;
+ esac
+ done
+ case $pids in
+ ?*) wait $pids ;;
+ esac
+ ;;
+ esac
+ } < /dev/null > $admin_log/$main_log 2>&1 &
+ pids="$pids $!"
+ ;;
+ *) echo "{"
+ case $admin_binary:$sync in
+ :?*) eval syncname='$'${sync}_name
+ test -d $PACKAGESRC && echo $admin_ditto $admin_ditto_update --remote=$rsh --expr="if(level>1)status=SKIP;name=='*.(pkg|lic|def)'" $PACKAGESRC $user$syncname:$root/lib/package
+ for dir in $package_src
+ do case $MAKESKIP in
+ '') expr="--expr=if(name=='$admin_ditto_skip')status=SKIP" ;;
+ *) expr="--expr=if(name=='$admin_ditto_skip'||level==1&&name=='$MAKESKIP')status=SKIP" ;;
+ esac
+ test -d $PACKAGEROOT/src/$dir && echo $admin_ditto $admin_ditto_update --remote=$rsh "$expr" $PACKAGEROOT/src/$dir $user$syncname:$root/src/$dir
+ done
+ ;;
+ esac
+ case $admin_action in
+ ditto) ;;
+ ?*) pids=
+ set '' $host $share
+ while :
+ do shift
+ case $# in
+ 0) break
+ ;;
+ 1) remote $1
+ ;;
+ *) remote $1 "&"
+ pids=1
+ ;;
+ esac
+ done
+ case $pids in
+ 1) echo wait ;;
+ esac
+ ;;
+ esac
+ echo "} < /dev/null > $admin_log/$main_log 2>&1 &"
+ ;;
+ esac
+ eval name='$'${main}_name
+ hosts="$hosts $name"
+ logs="$logs $main_log"
+ for share in $share
+ do eval keep=\$${share}_keep
+ case $keep in
+ 1) eval name='$'${share}_name log='$'${share}_log
+ hosts="$hosts $name"
+ logs="$logs $log"
+ ;;
+ esac
+ done
+ done
+ case $exec in
+ '') # track the progress
+ case $quiet in
+ 0) cd $admin_log
+ tail -t $PACKAGE_admin_tail_timeout -f $logs
+ cd ..
+ ;;
+ esac
+ # wait for the remote actions to complete
+ wait
+ trap - 1 2 3 15
+ # update the db
+ exec < $admin_db || exit
+ exec 9>&1
+ D=`date +%y%m%d`
+ while read line
+ do set -- $line
+ case $1 in
+ ''|'#'*|*=*)
+ ;;
+ *) case " $hosts " in
+ *" $2 "*)
+ : ast date command assumed :
+ E=`eval date -E \`egrep '[ ](start|done)[ ][ ]*at[ ]' $admin_log/$2 | sed -e 's/.*[ ][ ]*at[ ][ ]*//' -e 's/[ ][ ]*in[ ].*$//' -e 's/.*/"&"/'\``
+ M=$6 T=$7 W=$8
+ case $admin_action in
+ make|view)
+ M=`egrep -c ']:.* (\*\*\*.* code|don'\''t know) | \*\*\* termination code ' $admin_log/$2` ;;
+ test) T=`grep -ci 'fail[es]' $admin_log/$2` ;;
+ *) W=`grep '^[abcdefghijklmnopqrstuvwxyz][abcdefghijklmnopqrstuvwxyz]*:.' $admin_log/$2 | egrep -cv 'start at|done at|output captured|warning:|: package not found|whence: command not found'` ;;
+ esac
+ case $1 in
+ ?|??|???|????|?????|??????|???????)
+ t1=' '
+ ;;
+ ????????|?????????|??????????|???????????|????????????|?????????????|??????????????|???????????????)
+ t1=' '
+ ;;
+ *) t1=''
+ ;;
+ esac
+ case $2 in
+ ?|??|???|????|?????|??????|???????)
+ t2=' '
+ ;;
+ *) t2=''
+ ;;
+ esac
+ case $3 in
+ ?|??|???|????|?????|??????|???????)
+ t3=' '
+ ;;
+ *) t3=''
+ ;;
+ esac
+ case $E in
+ ?????) E=" $E" ;;
+ ????) E=" $E" ;;
+ ???) E=" $E" ;;
+ ??) E=" $E" ;;
+ ?) E=" $E" ;;
+ esac
+ case $M in
+ ???) M="$M" ;;
+ ??) M=" $M" ;;
+ ?) M=" $M" ;;
+ '') M=" 0" ;;
+ esac
+ case $T in
+ ???) T="$T" ;;
+ ??) T=" $T" ;;
+ ?) T=" $T" ;;
+ '') T=" 0" ;;
+ esac
+ case $W in
+ ???) W="$W" ;;
+ ??) W=" $W" ;;
+ ?) W=" $W" ;;
+ '') W=" 0" ;;
+ esac
+ A=$1$t1
+ H=$2$t2
+ R=$3$t3
+ case $# in
+ [0-8]) C=
+ ;;
+ *) shift 8
+ C=" $*"
+ ;;
+ esac
+ echo "$A $H $R $D $E $M $T $W$C"
+ echo "$A $H $R $D $E $M $T $W$C" >&9
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ echo "$line"
+ done > $admin_db.new
+ mv $admin_db $admin_db.old
+ mv $admin_db.new $admin_db
+ ;;
+ esac
+ ;;
+
+clean|clobber)
+ cd $PACKAGEROOT
+ $exec rm -rf $INSTALLROOT
+ exit
+ ;;
+
+contents|list)
+ # all work in $PACKAGESRC
+
+ cd $PACKAGESRC
+
+ # generate the package list
+
+ set '' $target $package
+ shift
+ argc=$#
+ case $# in
+ 0) set '' *.pkg
+ case $2 in
+ '*.pkg')
+ echo $command: $action: no packages >&2
+ exit 1
+ ;;
+ esac
+ set '' `echo $* | sed 's,\.pkg,,g'`
+ shift
+ ;;
+ esac
+ sep="$nl "
+ echo packages in $PACKAGEROOT
+ case $action in
+ list) echo
+ echo "NAME${nl}VERSION${nl}RELEASE${nl}TYPE${nl}STATUS${nl}REQUIRES${nl}----${nl}-------${nl}-------${nl}----${nl}------${nl}--------" | pr -6 -a -o4 -t
+ ;;
+ esac
+ {
+ omit=:
+ for pkg
+ do if test ! -f $pkg.pkg
+ then echo $command: $action: $pkg: not a package >&2
+ else if test -f gen/$pkg.ver
+ then set '' `cat gen/$pkg.ver`
+ case $3 in
+ $2) ver=base ;;
+ *) ver=$3 ;;
+ esac
+ if test -s tgz/$pkg.tim
+ then sts=local
+ else sts=
+ fi
+ else ver=
+ sts=unwritten
+ fi
+ typ=
+ txt=
+ cmp= cmp_sep=
+ req= req_sep=
+ op=::
+ exec < $pkg.pkg
+ while read line
+ do IFS=' \\'
+ set '' $line
+ IFS=$ifs
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :*:) op=$1
+ ;;
+ INIT|'$('*|*')')
+ ;;
+ *) case $op in
+ :DESCRIPTION:)
+ txt="$txt$sep$line"
+ break
+ ;;
+ :PACKAGE:)
+ cmp="$cmp$cmp_sep$1"
+ cmp_sep=$nl
+ ;;
+ :REQUIRES:)
+ req="$req$req_sep$1"
+ req_sep=" "
+ ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ exec < /dev/null
+ case $txt in
+ ?*) txt="$nl$txt" ;;
+ esac
+ case :$ver: in
+ *::*) ;;
+ *) case $action in
+ list) case $sts in
+ '') case `ls -t "tgz/$pkg.$ver.base" "tgz/$pkg.tim" 2>/dev/null` in
+ "tgz/$pkg.tim"*)
+ sts=read
+ ;;
+ *) sts=unread
+ ;;
+ esac
+ ;;
+ esac
+ echo "$pkg${nl}$ver${nl}base${nl}$typ${nl}$sts${nl}$req"
+ case $typ in
+ '') omit=$omit$pkg.$ver.base: ;;
+ esac
+ ;;
+ *) case $req in
+ ?*) req=": $req" ;;
+ esac
+ echo
+ echo $pkg $ver $req "$txt"
+ case $cmp in
+ ?*) echo "${sep}Components in this package:$nl"
+ echo "$cmp" | pr -4 -o4 -t ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ case $argc:$action in
+ 0:list) if test -d tgz
+ then cd tgz
+ # f:file p:package v:version r:release t:type u:update
+ for f in `find . -name '*?[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]*' -print | sed 's,^\./,,' | sort -r`
+ do eval `echo "$f" | sed -e 's,\.c$,,' -e 's,\.gz$,,' -e 's,\.exe$,,' -e 's,\.tgz$,,' -e 's,\([^_.]*\)[_.]\([0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]\)[_.]\([0123456789][0123456789][0123456789][0123456789][^_.]*\)[_.]*\(.*\),p=\1 v=\2 r=\3 t=\4,' -e 's,\([^_.]*\)[_.]\([0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]\)[_.]*\(.*\),p=\1 v=\2 r=base t=\3,'`
+ case $t in
+ '') case $omit in
+ *:$p.$v.$r:*) continue ;;
+ esac
+ u=$p.tim
+ ;;
+ *) u=$p.$t.tim
+ ;;
+ esac
+ if test -s "$u"
+ then s=local
+ elif test -f "$u"
+ then case `ls -t "$f" "$u" 2>/dev/null` in
+ "$u"*) s=read ;;
+ *) s=unread ;;
+ esac
+ else s=unread
+ fi
+ echo "$p$nl$v$nl$r$nl$t$nl$s$nl"
+ done
+ fi
+ ;;
+ esac
+ } |
+ case $action in
+ list) pr -6 -a -o4 -t | sort -u ;;
+ *) cat ;;
+ esac
+ case $argc in
+ 0) if test -d $PACKAGEROOT/arch
+ then echo
+ echo architectures in $PACKAGEROOT
+ echo
+ for i in `ls $PACKAGEROOT/arch`
+ do if test -f $PACKAGEROOT/arch/$i/lib/package/gen/host
+ then h=`cat $PACKAGEROOT/arch/$i/lib/package/gen/host`
+ else h=
+ fi
+ echo $i
+ echo $h
+ echo
+ echo
+ done | pr -4 -a -o4 -t
+ fi
+ ;;
+ esac
+ ;;
+
+copyright)
+ # all work in $PACKAGESRC
+
+ cd $PACKAGESRC
+
+ # generate the package list
+
+ set '' $target $package
+ shift
+ argc=$#
+ case $# in
+ 0) set '' `echo *.lic | sed 's,\.lic,,g'`
+ shift
+ case $1 in
+ '*') echo $command: $action: no packages >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ checkaout proto || exit
+ for i
+ do copyright $i
+ done
+ ;;
+
+export) case $INSTALLROOT in
+ $PACKAGEROOT)
+ INSTALLROOT=$INSTALLROOT/arch/$HOSTTYPE
+ ;;
+ esac
+ case $only in
+ 0) v='$i=' ;;
+ *) v= ;;
+ esac
+ set '' $target $package
+ case $# in
+ 1) set '' $env ;;
+ esac
+ while :
+ do case $# in
+ 1) break ;;
+ esac
+ shift
+ i=$1
+ eval echo ${v}'$'${i}
+ done
+ ;;
+
+install)cd $PACKAGEROOT
+ set '' $package
+ shift
+ case $only in
+ 0) set '' `order "$@"`
+ shift
+ ;;
+ esac
+ case $# in
+ 0) echo "$command: at least one package name expected" >&2
+ exit 1
+ ;;
+ esac
+ package=$*
+ requirements - $package
+ set '' $target
+ shift
+ case $1 in
+ flat) flat=1 # backwards compatibility -- documentation dropped
+ shift
+ ;;
+ esac
+ case $# in
+ 0) echo "$command: $action: target directory argument expected" >&2
+ exit 1
+ ;;
+ esac
+ target=
+ while :
+ do case $# in
+ 1) directory=$1
+ break
+ ;;
+ esac
+ target="$target $1"
+ shift
+ done
+ if test ! -d $directory
+ then echo "$command: $action: $directory: target directory not found" >&2
+ exit 1
+ fi
+ case $target in
+ '') cd arch
+ set '' *
+ shift
+ target=$*
+ cd ..
+ ;;
+ esac
+ code=0
+ makecheck=1
+ for a in $target
+ do case $a in
+ -) a=$HOSTTYPE ;;
+ esac
+ case $flat:$a in
+ 1:*|?:.)dest=$directory
+ ;;
+ *) dest=$directory/arch/$a
+ if test "" = "$exec" -a ! -d $dest
+ then mkdir -p $dest || {
+ echo "$command: $dest: destination directory must exist" >&2
+ exit 1
+ }
+ fi
+ ;;
+ esac
+ for i in $package
+ do if test "ratz" = "$i"
+ then : skip
+ elif test -f arch/$a/lib/package/gen/$i.sum
+ then package_install $directory arch/$a/lib/package/gen/$i.sum || code=1
+ elif test ! -d arch/$a/bin
+ then echo "$command: $a: invalid architecture" >&2
+ elif test ! -d $dest
+ then echo "$command: $dest: destination directory must exist" >&2
+ else if test "" != "$makecheck"
+ then if onpath $MAKE
+ then MAKE=$_onpath_
+ else echo "$command: $MAKE: not found" >&2
+ exit 1
+ fi
+ makecheck=
+ fi
+ if test "" != "$exec"
+ then (
+ trap - 0 1 2 15
+ echo "=== $i installation manifest ==="
+ cd arch/$a
+ (
+ cd lib/package
+ INSTALLROOT=$PACKAGEROOT/arch/$a
+ VPATH=$INSTALLROOT:$PACKAGEROOT:$VPATH
+ export INSTALLROOT VPATH
+ $MAKE -s $makeflags -f $i.pkg $qualifier list.installed $assign
+ ) | sort -u
+ )
+ else (
+ set -
+ cd arch/$a
+ (
+ cd lib/package
+ INSTALLROOT=$PACKAGEROOT/arch/$a
+ VPATH=$INSTALLROOT:$PACKAGEROOT:$VPATH
+ export INSTALLROOT VPATH
+ echo lib/$command
+ $MAKE -s $makeflags -f $i.pkg $qualifier list.installed $assign
+ ) | sort -u | pax -drw -ps $dest
+ )
+ fi
+ fi
+ done
+ done
+ exit $code
+ ;;
+
+license)# all work in $PACKAGESRC/LICENSES
+
+ cd $PACKAGESRC/LICENSES || exit
+
+ # generate the package list
+
+ set '' $target $package
+ shift
+ argc=$#
+ case $# in
+ 0) set '' *
+ shift
+ case $1 in
+ '*') echo $command: $action: no licenses >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ *) checkaout proto || exit
+ a=
+ for i
+ do while :
+ do if test -f ../$i.lic
+ then j=`proto -df -l ../$i.lic -o query=type /dev/null 2>/dev/null`
+ case $j in
+ ?*) if test -f $j
+ then case " $a " in
+ *" $j "*) ;;
+ *) a="$a $j" ;;
+ esac
+ fi
+ break
+ ;;
+ esac
+ fi
+ case $i in
+ *-*) i=`echo $i | sed 's/-[^-]*$//'`
+ ;;
+ *) echo "$command: $i: package license not found" >&2
+ break
+ ;;
+ esac
+ done
+ done
+ set '' $a
+ shift
+ ;;
+ esac
+ for i
+ do case $exec in
+ '') echo
+ echo " --- $i source license ---"
+ echo
+ cat $i
+ ;;
+ *) echo $PACKAGESRC/LICENSES/$i
+ ;;
+ esac
+ done
+ ;;
+
+make|view)
+ cd $PACKAGEROOT
+ case $package in
+ '') lic="lib/package/*.lic"
+ ;;
+ *) for i in $package
+ do lic="$lic lib/package/$i.lic"
+ case $i in
+ *-*) lic="$lic lib/package/"`echo $i | sed 's,-.*,,'`".lic" ;;
+ esac
+ done
+ ;;
+ esac
+ checksrc
+ requirements source $package
+ components $package
+ package=$_components_
+
+ # check for some required commands
+
+ must="$AR"
+ warn="$NM yacc bison"
+ test="$must $warn"
+ have=
+ IFS=:
+ set /$IFS$PATH
+ IFS=$ifs
+ shift
+ for t in $test
+ do if executable $t
+ then have="$have $t"
+ fi
+ done
+ for d
+ do for t in $test
+ do case " $have " in
+ *" $t "*)
+ ;;
+ *) if executable $d/$t
+ then have="$have $t"
+ fi
+ ;;
+ esac
+ done
+ done
+ case " $have " in
+ *" bison "*) ;;
+ *" yacc "*) have="$have bison" ;;
+ esac
+ case " $have " in
+ *" yacc "*) ;;
+ *" bison "*) have="$have yacc" ;;
+ esac
+ for t in $test
+ do case " $have " in
+ *" $t "*)
+ ;;
+ *) case " $must " in
+ *" $t "*)
+ echo "$command: $t: not found -- must be on PATH to $action" >&2
+ exit 1
+ ;;
+ *) echo "$command: warning: $t: not found -- some $action actions may fail" >&2
+ ;;
+ esac
+ ;;
+ esac
+ done
+
+ # verify the top view
+
+ if test ! -d $PACKAGEROOT/src
+ then note no source packages to make
+ exit 0
+ elif test ! -d $INSTALLROOT/src
+ then note initialize the $INSTALLROOT view
+ fi
+ for i in arch arch/$HOSTTYPE
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || exit
+ done
+ for i in bin bin/$OK bin/$OK/lib fun include lib lib/package lib/package/gen src man man/man1 man/man3 man/man8
+ do test -d $INSTALLROOT/$i || $exec mkdir $INSTALLROOT/$i || exit
+ done
+ make_recurse src
+ o= k=
+ for i in $makefiles
+ do case $o in
+ ?*) o="$o -o" k="$k|" ;;
+ esac
+ o="$o -name $i"
+ k="$k$i"
+ done
+ o="( $o ) -print"
+ for d in $package_src
+ do i=src/$d
+ if test -d $i
+ then test -d $INSTALLROOT/$i || $exec mkdir $INSTALLROOT/$i || exit
+ make_recurse $i
+ for j in `cd $i; find . $o 2>/dev/null | sed -e 's,^\./,,' -e '/\//!d' -e 's,/[^/]*$,,' | sort -u`
+ do case $j in
+ $k|$MAKESKIP) continue ;;
+ esac
+ test -d $INSTALLROOT/$i/$j ||
+ $exec mkdir -p $INSTALLROOT/$i/$j || exit
+ done
+ fi
+ done
+ def=
+ for i in $lic
+ do test -f $i || continue
+ cmp -s $i $INSTALLROOT/$i 2>/dev/null ||
+ $exec cp $PACKAGEROOT/$i $INSTALLROOT/$i
+ for j in `grep '^. .*\.def$' $i`
+ do case $j in
+ .) ;;
+ *) case " $def " in
+ *" $i "*) ;;
+ *) def="$def $i" ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ for i in $def
+ do i=lib/package/$i
+ test -f $i || continue
+ cmp -s $i $INSTALLROOT/$i 2>/dev/null ||
+ $exec cp $PACKAGEROOT/$i $INSTALLROOT/$i
+ done
+
+ # check $CC and { ar cc ld ldd } intercepts
+
+ h="${HOSTTYPE} ${HOSTTYPE}.*"
+ case $HOSTTYPE in
+ *.*) t=`echo $HOSTTYPE | sed 's/[.][^.]*//'`
+ h="$h $t"
+ ;;
+ *) t=$HOSTTYPE
+ ;;
+ esac
+ case $t in
+ *[0123456789])
+ t=`echo $t | sed 's/[0123456789]*$//'`
+ h="$h $t"
+ ;;
+ esac
+ case $CC in
+ cc) c=cc
+ b=$INSTALLROOT/bin/$c
+ t=$INSTALLROOT/lib/package/gen/$c.tim
+ intercept=0
+ for k in $h
+ do for s in $INITROOT/$c.$k
+ do test -x "$s" || continue
+ if cmp -s "$s" "$b" >/dev/null 2>&1
+ then intercept=1
+ break 2
+ fi
+ case `ls -t "$t" "$b" "$s" 2>/dev/null` in
+ $t*) ;;
+ $b*) cc=$b
+ ;;
+ $s*) cd $INSTALLROOT/lib/package/gen
+ tmp=pkg$$
+ eval '$'exec echo "'int main(){return 0;}' > $tmp.c"
+ if $exec $s -o $tmp.exe $tmp.c >/dev/null 2>&1 &&
+ test -x $tmp.exe
+ then case $HOSTTYPE in
+ *.mips*)$s -version >/dev/null 2>&1 || s= ;;
+ esac
+ case $s in
+ ?*) $exec sed "s/^HOSTTYPE=.*/HOSTTYPE=$HOSTTYPE/" < "$s" > "$b" || exit
+ $exec chmod +x "$b" || exit
+ cc=$b
+ intercept=1
+ note update $b
+ ;;
+ esac
+ fi
+ $exec rm -f $tmp.*
+ $exec touch "$t"
+ cd $PACKAGEROOT
+ ;;
+ esac
+ break 2
+ done
+ done
+ case $intercept in
+ 1) c=ld
+ b=$INSTALLROOT/bin/$c
+ for k in $h
+ do for s in $INITROOT/$c.$k
+ do test -x "$s" || continue
+ case `ls -t "$b" "$s" 2>/dev/null` in
+ $b*) ;;
+ $s*) $exec cp "$s" "$b"
+ note update $b
+ ;;
+ esac
+ done
+ done
+ ;;
+ esac
+ ;;
+ esac
+ c=ldd
+ b=$INSTALLROOT/bin/$c
+ for t in $h
+ do s=$INITROOT/$c.$t
+ test -x "$s" || continue
+ onpath $c ||
+ case `ls -t "$b" "$s" 2>/dev/null` in
+ $b*) ;;
+ $s*) $exec cp "$s" "$b"
+ note update $b
+ ;;
+ esac
+ done
+# following code stubbed out just in case ar.ibm.risc is needed
+# c=ar
+# b=$INSTALLROOT/bin/$c
+# for t in $h
+# do s=$INITROOT/$c.$t
+# test -x "$s" || continue
+# onpath $c ||
+# case `ls -t "$b" "$s" 2>/dev/null` in
+# $b*) ;;
+# $s*) x=`$s -tv /foo/bar.a 2>&1 | egrep -i 'option|usage'`
+# case $x in
+# '') $exec cp "$s" "$b"
+# note update $b
+# ;;
+# esac
+# ;;
+# esac
+# done
+ case $cc in
+ /*) ;;
+ *) echo "$command: $CC: not found -- set CC=C-compiler" >&2
+ exit 1
+ ;;
+ esac
+ case $exec in
+ '') cd $INSTALLROOT/lib/package/gen
+ tmp=pkg$$
+ echo 'int main(){return 0;}' > $tmp.c
+ if $CC -o $tmp.exe $tmp.c > /dev/null 2> $tmp.err &&
+ test -x $tmp.exe
+ then : ok
+ else echo "$command: $CC: failed to compile this program:" >&2
+ cat $tmp.c >&2
+ if test -s $tmp.err
+ then cat $tmp.err >&2
+ else echo "$command: $CC: not a C compiler" >&2
+ fi
+ rm -f $tmp.*
+ exit 1
+ fi
+ rm -f $tmp.*
+ cd $PACKAGEROOT
+ ;;
+ esac
+
+ # remember the default $CC
+
+ case $CC in
+ cc) ;;
+ *) if test -x $INSTALLROOT/bin/cc
+ then case `sed 1q $INSTALLROOT/bin/cc` in
+ ": $CC :")
+ CC=cc
+ export CC
+ ;;
+ *) assign="$assign CC=\"\$CC\""
+ ;;
+ esac
+ else case $CROSS in
+ 1) assign="$assign CC=\"\$CC\""
+ ;;
+ *) case $exec in
+ '') {
+ echo ": $CC :"
+ echo "$CC \"\$@\""
+ } > $INSTALLROOT/bin/cc
+ chmod +x $INSTALLROOT/bin/cc
+ ;;
+ *) note generate a $INSTALLROOT/bin/cc wrapper for $CC
+ ;;
+ esac
+ CC=cc
+ export CC
+ ;;
+ esac
+ fi
+ ;;
+ esac
+
+ # no $INITROOT means INIT already installed elsewhere
+
+ if test -d $INITROOT
+ then
+ # update probe scripts
+
+ for i in lib/probe lib/probe/C lib/probe/C/make
+ do test -d $INSTALLROOT/$i || $exec mkdir $INSTALLROOT/$i || exit
+ done
+ i=$INSTALLROOT/lib/probe/C/make/probe
+ j=$INITROOT/C+probe
+ k=$INITROOT/make.probe
+ case `ls -t $i $j $k 2>/dev/null` in
+ $i*) ;;
+ *) if test -f $j -a -f $k
+ then note update $i
+ shellmagic
+ case $exec in
+ '') {
+ case $SHELLMAGIC in
+ ?*) echo "$SHELLMAGIC" ;;
+ esac
+ cat $j $k
+ } > $i || exit
+ ;;
+ *) echo "{
+echo $SHELLMAGIC
+cat $j $k
+} > $i"
+ ;;
+ esac
+ $exec chmod +x $i || exit
+ fi
+ ;;
+ esac
+ fi
+
+ # initialize a few mamake related commands
+
+ checkaout mamake proto ratz release || exit
+
+ # execrate if necessary
+
+ if (execrate) >/dev/null 2>&1
+ then execrate=execrate
+ $make cd $INSTALLROOT/bin
+ for i in chmod chgrp cmp cp ln mv rm
+ do if test ! -x $OK/$i -a -x /bin/$i.exe
+ then shellmagic
+ case $exec in
+ '') echo "$SHELLMAGIC"'execrate /bin/'$i' "$@"' > $OK/$i
+ chmod +x $OK/$i
+ ;;
+ *) $exec echo \'"$SHELLMAGIC"'execrate /bin/'$i' "$@"'\'' >' $OK/$i
+ $exec chmod +x $OK/$i
+ ;;
+ esac
+ fi
+ done
+ PATH=$INSTALLROOT/bin/$OK:$PATH
+ export PATH
+ else execrate=
+ fi
+ case $action in
+ view) exit 0 ;;
+ esac
+
+ # all work under $INSTALLROOT/src
+
+ $make cd $INSTALLROOT/src
+
+ # record the build host name
+
+ case $noexec in
+ '') hostinfo name
+ echo "$_hostinfo_" | sed 's,\..*,,' > $PACKAGEBIN/gen/host
+ ;;
+ esac
+
+ # make in parallel if possible
+
+ case $NPROC in
+ '') hostinfo cpu
+ case $_hostinfo_ in
+ 0|1) ;;
+ *) NPROC=$_hostinfo_
+ $show NPROC=$NPROC
+ $show export NPROC
+ export NPROC
+ ;;
+ esac
+ ;;
+ esac
+
+ # separate flags from target list
+
+ case $target in
+ *-*) a=
+ for t in $target
+ do case $t in
+ -[eiknFKNV]*|--*-symbols)
+ makeflags="$makeflags $t"
+ ;;
+ -*) nmakeflags="$nmakeflags $t"
+ ;;
+ *) a="$a $t"
+ ;;
+ esac
+ done
+ target=$a
+ ;;
+ esac
+
+ # generate nmake first if possible
+
+ if executable ! $NMAKE && test -d $PACKAGEROOT/src/cmd/nmake
+ then if nonmake $MAKE
+ then note make $NMAKE with mamake
+ c=$CC
+ a=$assign
+ case $HOSTTYPE in
+ win32*|cygwin*)
+ CC="$CC -D_BLD_STATIC"
+ accept="libast"
+ case $assign in
+ *' CC='*) ;;
+ *) assign="$assign CC=\"\$CC\"" ;;
+ esac
+ ;;
+ *) accept=nmake
+ ;;
+ esac
+ eval capture mamake \$makeflags \$nmakeflags \$noexec install nmake $assign
+ assign=$a
+ CC=$c
+ case $make$noexec in
+ '') if executable ! $NMAKE
+ then echo "$command: $action: errors making $NMAKE" >&2
+ exit 1
+ fi
+ ;;
+ *) make=echo
+ ;;
+ esac
+ if test '' != "$PROTOROOT"
+ then if (vpath $INSTALLROOT - $PROTOROOT - $INSTALLROOT $PACKAGEROOT) >/dev/null 2>&1 &&
+ vpath $INSTALLROOT - $PROTOROOT - $INSTALLROOT $PACKAGEROOT
+ then $show vpath $INSTALLROOT $PACKAGEROOT $USER_VPATH_CHAIN
+ else VPATH=$INSTALLROOT:$PACKAGEROOT$USER_VPATH
+ $show VPATH=$VPATH
+ export VPATH
+ fi
+ fi
+ note believe generated files for $accept
+ eval capture \$NMAKE \$makeflags \$nmakeflags \$noexec recurse believe \$nmakesep $accept $assign
+ $exec touch $INSTALLROOT/bin/.paths
+ note make the remaining targets with $NMAKE
+ else eval capture $MAKE \$makeflags \$nmakeflags \$noexec install nmake $assign
+ case $make$noexec in
+ '') if executable ! $NMAKE
+ then echo "$command: $action: errors making $NMAKE" >&2
+ exit 1
+ fi
+ ;;
+ *) make=echo
+ ;;
+ esac
+ fi
+ fi
+
+ # generate ksh next if possible
+
+ if nonmake $MAKE
+ then : no need to generate ksh next -- it could be the only package
+ elif test "$KEEP_SHELL" != 1 -a -d $PACKAGEROOT/src/cmd/ksh93 && executable ! $KSH
+ then eval capture nmake $nmakeflags \$makeflags \$noexec install ksh93 $assign
+ case $make$noexec in
+ '') if executable ! $KSH
+ then echo "$command: $action: errors making $KSH" >&2
+ exit 1
+ fi
+ ;;
+ *) make=echo
+ ;;
+ esac
+ fi
+
+ # mamprobe data should have been generated by this point
+
+ case $exec in
+ '') if test ! -f $INSTALLROOT/bin/.paths -o -w $INSTALLROOT/bin/.paths
+ then nl="
+"
+ o=`cat $INSTALLROOT/bin/.paths 2>/dev/null`
+ v=
+ n=
+ case $nl$o in
+ *${nl}FPATH=*|*#FPATH=*|*[Nn][Oo]FPATH=*)
+ ;;
+ *) case $n in
+ '') ;;
+ *) n="$n$nl" v="$v|" ;;
+ esac
+ n="${n}FPATH=../fun"
+ v="${v}FPATH"
+ ;;
+ esac
+ case $nl$o in
+ *${nl}BUILTIN_LIB=*|*#BUILTIN_LIB=*|*[Nn][Oo]BUILTIN_LIB=*)
+ ;;
+ *) case $n in
+ '') ;;
+ *) n="$n$nl" v="$v|" ;;
+ esac
+ if grep '^setv mam_cc_DIALECT .* EXPORT=[AD]LL' $INSTALLROOT/lib/probe/C/mam/* >/dev/null 2>&1
+ then x=
+ else x='no'
+ fi
+ n="${n}${x}BUILTIN_LIB=cmd"
+ v="${v}BUILTIN_LIB"
+ ;;
+ esac
+ case $n in
+ ?*) case $o in
+ ?*) o=`egrep -v "($v)=" $INSTALLROOT/bin/.paths`$nl ;;
+ esac
+ echo "# use { # no NO } prefix instead of XX to permanently disable #$nl$o$n" > $INSTALLROOT/bin/.paths
+ ;;
+ esac
+ fi
+ ;;
+ esac
+
+ # run from separate copies since nmake and ksh may be rebuilt
+
+ case $EXECROOT in
+ $INSTALLROOT)
+ $make cd $INSTALLROOT/bin
+ if executable /bin/cp
+ then cp=/bin/cp
+ else cp=cp
+ fi
+ if executable /bin/mv
+ then mv=/bin/mv
+ else mv=mv
+ fi
+ if executable /bin/rm
+ then rm=/bin/rm
+ else rm=rm
+ fi
+ for i in \
+ ksh nmake tee cp ln mv rm \
+ *ast*.dll *cmd*.dll *dll*.dll *shell*.dll
+ do executable $i && {
+ cmp -s $i $OK/$i 2>/dev/null || {
+ test -f $OK/$i &&
+ $exec $execrate $rm $OK/$i </dev/null
+ test -f $OK/$i &&
+ $exec $execrate $mv $OK/$i $OK/$i.old </dev/null
+ test -f $OK/$i &&
+ case $exec:$i in
+ :nmake|:ksh)
+ echo "$command: $OK/$i: cannot update [may be in use by a running process] remove manually and try again" >&2
+ exit 1
+ ;;
+ esac
+ $exec $execrate $cp $i $OK/$i
+ }
+ }
+ done
+ if test -f ../lib/make/makerules.mo
+ then cmp -s ../lib/make/makerules.mo $OK/lib/makerules.mo ||
+ $exec $execrate $cp -p ../lib/make/makerules.mo $OK/lib/makerules.mo ||
+ $exec $execrate $cp ../lib/make/makerules.mo $OK/lib/makerules.mo
+ fi
+ if executable $OK/nmake
+ then MAKE="$INSTALLROOT/bin/$OK/nmake LOCALRULESPATH=$INSTALLROOT/bin/$OK/lib"
+ fi
+ if executable $OK/tee
+ then TEE=$INSTALLROOT/bin/$OK/tee
+ fi
+ if test "$KEEP_SHELL" != 1 && executable $OK/ksh
+ then SHELL=$INSTALLROOT/bin/$OK/ksh
+ export SHELL
+ COSHELL=$SHELL
+ export COSHELL
+ fi
+ case :$PATH: in
+ *:$INSTALLROOT/bin/$OK:*)
+ ;;
+ *) PATH=$INSTALLROOT/bin/$OK:$PATH
+ export PATH
+ ;;
+ esac
+ $make cd $INSTALLROOT/src
+ ;;
+ esac
+
+ # fall back to mamake if nmake not found or too old
+
+ if nonmake $MAKE
+ then note make with mamake
+ case $target in
+ '') target="install" ;;
+ esac
+ eval capture mamake \$makeflags \$noexec \$target $assign
+ else case $target in
+ '') target="install cc-" ;;
+ esac
+ eval capture \$MAKE \$makeflags \$nmakeflags \$noexec recurse \$target \$nmakesep \$package $assign
+ fi
+ ;;
+
+read) case ${PWD:-`pwd`} in
+ $PACKAGEROOT)
+ ;;
+ *) echo "$command: must be in package root directory" >&2
+ exit 1
+ ;;
+ esac
+ PAX=
+ if onpath pax
+ then case `$_onpath_ -rw --?meter 2>&1` in
+ *--meter*) PAX=pax ;;
+ esac
+ fi
+ code=0
+ i=
+ x=
+ remove=
+ touch=
+ set '' $target
+ case $2 in
+ lcl|tgz)tgz=$2
+ shift 2
+ target=$*
+ ;;
+ *) tgz=tgz
+ ;;
+ esac
+ set '' $package $target
+ case $# in
+ 1) verbose=:
+ set '' `ls lib/package/$tgz/*?[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]* 2>/dev/null`
+ ;;
+ *) verbose=
+ ;;
+ esac
+ shift
+ files=
+ for f
+ do if test -f "$f"
+ then : ok
+ elif test -f "lib/package/$tgz/$f"
+ then f=lib/package/$tgz/$f
+ else set '' `ls -r ${f}[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]* 2>/dev/null`
+ if test '' != "$2" -a -f "$2"
+ then f=$2
+ else set '' `ls -r lib/package/$tgz/${f}[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]* 2>/dev/null`
+ if test '' != "$2" -a -f "$2"
+ then f=$2
+ else echo "$command: $f: package archive not found" >&2
+ continue
+ fi
+ fi
+ fi
+ files="$files $f"
+ done
+ case $files in
+ '') echo "$command: lib/package/$tgz: no package archives" >&2
+ exit 1
+ ;;
+ esac
+ set '' `ls -r $files 2>/dev/null`
+ shift
+ f1= f2= f3= f4=
+ for f
+ do case $f in
+ ratz.*|*/ratz.*)
+ f1="$f1 $f"
+ ;;
+ INIT.*|*/INIT.*)
+ f2="$f2 $f"
+ ;;
+ INIT*|*/INIT*)
+ f3="$f3 $f"
+ ;;
+ *) f4="$f4 $f"
+ ;;
+ esac
+ done
+ gen=
+ set '' $f1 $f2 $f3 $f4
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ f=$1
+ case $f in
+ *.gz) : standalone packages unbundled manually
+ continue
+ ;;
+ *.md5) : tarball checksum
+ continue
+ ;;
+ *?[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]*)
+ ;;
+ *) echo "$command: $f: not a package archive" >&2
+ code=1
+ continue
+ ;;
+ esac
+ case $f in
+ */*) eval `echo "$f" | sed -e 's,\(.*/\)\(.*\),d=\1 a=\2,'` ;;
+ *) d= a=$f ;;
+ esac
+ # f:file d:dir a:base p:package v:version r:release t:type
+ eval `echo "$a" | sed -e 's,\.c$,,' -e 's,\.gz$,,' -e 's,\.exe$,,' -e 's,\.tgz$,,' -e 's,\([^_.]*\)[_.]\([0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]\)[_.]\([0123456789][0123456789][0123456789][0123456789][^_.]*\)[_.]*\(.*\),p=\1 v=\2 r=\3 t=\4,' -e 's,\([^_.]*\)[_.]\([0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]\)[_.]*\(.*\),p=\1 v=\2 r=base t=\3,'`
+ case $r in
+ base) y=$p.base ;;
+ *) y=$p.delta ;;
+ esac
+ case " $x " in
+ *" $y "*)
+ continue
+ ;;
+ esac
+ case $t in
+ '') w=$PACKAGESRC
+ q=
+ Q=
+ m=
+ ;;
+ *) w=$PACKAGEROOT/arch/$t/lib/package
+ q=".$t"
+ Q="_$t"
+ m="[_.]$t"
+ ;;
+ esac
+ u=$d$p$q.tim
+ if test -s "$u"
+ then continue
+ else case $force in
+ 0) case `ls -t "$f" "$u" 2>/dev/null` in
+ "$u"*) case $verbose in
+ 1) note $p already read ;;
+ esac
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ case $p in
+ INIT) if test -f $PACKAGEROOT/bin/package
+ then $exec mv $PACKAGEROOT/bin/package $PACKAGEROOT/bin/package.old
+ fi
+ ;;
+ esac
+ z=
+ case $r in
+ base) # base archive
+ if test ratz = "$p"
+ then # ratz packages are not archives
+ case $t in
+ '') for i in src src/cmd src/cmd/INIT
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || exit
+ done
+ $exec cp $f $PACKAGEROOT/src/cmd/INIT/$p.c
+ ;;
+ *) for i in arch arch/$t arch/$t/bin
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || exit
+ done
+ $exec cp $f $PACKAGEROOT/arch/$t/bin/$p &&
+ $exec chmod +x $PACKAGEROOT/arch/$t/bin/$p
+ ;;
+ esac
+ elif test "" != "$PAX"
+ then $exec pax -L --from=ascii --local -m -ps -rvf "$f" || {
+ code=1
+ continue
+ }
+ else if onpath gunzip && onpath $TAR && isascii
+ then case $TARPROBE in
+ ?*) for i in $TARPROBE
+ do if $TAR ${i}f - /dev/null > /dev/null 2>&1
+ then TARFLAGS=$TARFLAGS$i
+ fi
+ done
+ TARPROBE=
+ ;;
+ esac
+ if gunzip -l < "$f" > /dev/null 2>&1
+ then case $exec in
+ '') $exec gunzip < "$f" | $TAR ${TARFLAGS}f - ;;
+ *) $exec "gunzip < $f | $TAR ${TARFLAGS}f -" ;;
+ esac || {
+ code=1
+ continue
+ }
+ else $exec $TAR ${TARFLAGS}f "$f" || {
+ code=1
+ continue
+ }
+ fi
+ else checkaout ratz && onpath ratz || {
+ code=1
+ continue
+ }
+ RATZ=$_onpath_
+ case $exec in
+ '') echo $f:
+ $exec $RATZ -lm < "$f"
+ ;;
+ *) $exec "$RATZ -lm < $f"
+ ;;
+ esac || {
+ code=1
+ continue
+ }
+ fi
+ if test -f $PACKAGEBIN/gen/$p.sum
+ then while read md5 mode usr grp file
+ do case $file in
+ -*) file=./$file ;;
+ esac
+ case $mode in
+ [01234567][01234567][01234567][01234567])
+ case $grp in
+ -) ;;
+ *) $exec chgrp $grp "$file" ;;
+ esac
+ case $usr in
+ -) ;;
+ *) $exec chown $usr "$file" ;;
+ esac
+ $exec chmod $mode "$file"
+ ;;
+ esac
+ done < $PACKAGEBIN/gen/$p.sum
+ fi
+ fi
+ ;;
+ *) # delta archive
+ test "" != "$PAX" || {
+ echo "$command: $f: pax required to read delta archive" >&2
+ code=1
+ continue
+ }
+ case `echo "$v:
+$r:" | sort` in
+ $r:*) y=$p.base
+ b=${d}${p}_${r}${Q}.tgz
+ test -f "$b" || b=${d}${p}.${r}${q}.tgz
+ test -f "$b" || {
+ case " $gen " in
+ *" $b "*)
+ ;;
+ *) case $# in
+ 1) echo "$command: $f: base archive $b required to read delta" >&2
+ code=1
+ ;;
+ *) shift
+ y=$1
+ shift
+ set '' $y $f "$@"
+ esac
+ continue
+ ;;
+ esac
+ }
+ # -m with delta bug fixed 2005-02-08
+ $exec pax -L --from=ascii --local -ps -rvf "$f" -z "$b" || {
+ code=1
+ continue
+ }
+ note $f: generate new base $d$p.$v$q.tgz
+ $exec pax -rf "$f" -z "$b" -wf $d$p.$v$q.tgz -x tgz || {
+ code=1
+ continue
+ }
+ case $exec in
+ '') echo $p $v $v 1 > $w/gen/$p.ver
+ ;;
+ *) z=$d${p}[_.]$v$q.tgz
+ $exec "echo $p $v $v 1 > $w/gen/$p.ver"
+ gen="$gen $d$p.$v$q.tgz"
+ ;;
+ esac
+ case " $remove " in
+ *" $f "*) ;;
+ *) remove="$remove $f" ;;
+ esac
+ ;;
+ *) b=${d}${p}_${v}${Q}.tgz
+ test -f "$b" || b=${d}${p}.${v}${q}.tgz
+ test -f "$b" || {
+ case " $gen " in
+ *" $b "*)
+ ;;
+ *) case $# in
+ 1) echo "$command: $f: base archive $b required to read delta" >&2
+ code=1
+ ;;
+ *) shift
+ y=$1
+ shift
+ set '' $y $f "$@"
+ esac
+ continue
+ ;;
+ esac
+ }
+ # -m with delta bug fixed 2005-02-08
+ $exec pax -L --from=ascii --local -ps -rvf "$f" -z "$b" || {
+ code=1
+ continue
+ }
+ ;;
+ esac
+ ;;
+ *) echo "$command: $f: unknown archive type" >&2
+ code=1
+ continue
+ ;;
+ esac
+
+ # check for ini files
+
+ if executable $w/$p.ini
+ then $exec $w/$p.ini read || {
+ code=1
+ continue
+ }
+ fi
+
+ # add to the obsolete list
+
+ k=
+ for i in `ls $d$p[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]????$m* $z 2>/dev/null`
+ do case $i in
+ *.md5) continue
+ ;;
+ $d${p}[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]$m*)
+ ;;
+ $d${p}[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]$m*)
+ continue
+ ;;
+ esac
+ case $k in
+ ?*) case " $remove " in
+ *" $k "*) ;;
+ *) remove="$remove $k" ;;
+ esac
+ ;;
+ esac
+ k=$i
+ done
+ x="$x $y"
+ case " $touch " in
+ *" $u "*) ;;
+ *) touch="$touch $u" ;;
+ esac
+ done
+ if test ! -f $PACKAGEROOT/bin/package -a -f $PACKAGEROOT/bin/package.old
+ then $exec cp $PACKAGEROOT/bin/package.old $PACKAGEROOT/bin/package
+ fi
+
+ # drop obsolete archives
+
+ case $remove in
+ ?*) $exec rm -f $remove ;;
+ esac
+
+ # mark the updated archives
+
+ case $touch in
+ ?*) sleep 1; $exec touch $touch ;;
+ esac
+
+ # check the requirements
+
+ case $code$exec in
+ 0) requirements - $x ;;
+ esac
+ exit $code
+ ;;
+
+regress)if test ! -d $PACKAGEBIN/gen
+ then echo "$command: 'package make' and 'package test' required for regression" >&2
+ exit 1
+ fi
+ dir=$PACKAGEBIN/gen
+ cd $dir
+ for s in out old
+ do case `ls -t regress.$s test.$s 2>/dev/null` in
+ regress*)
+ ;;
+ test*) if test -f regress.$s
+ then $exec mv regress.$s regress.old
+ fi
+ case $exec in
+ '') egrep -i '\*\*\*|FAIL|^TEST.* [123456789][0123456789]* error|core.*dump' test.$s |
+ sed -e '/\*\*\* [0123456789]/d' \
+ -e '/^TEST.\//s,/[^ ]*/,,' \
+ -e 's,[ ][ ]*$,,' \
+ -e 's/[0123456789][0123456789]*:* \([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 ]*([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 ]*[Cc][Oo][Rr][Ee][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 ]*)\)/\1/' \
+ -e 's/\.sh failed at .* with /.sh failed /' \
+ > regress.$s
+ ;;
+ *) $exec filter test failures from $dir/test.$s to $dir/regress.$s
+ ;;
+ esac
+ ;;
+ esac
+ done
+ if test -f regress.out -a -f regress.old
+ then $exec diff -b regress.out regress.old
+ else echo "$command: at least 2 test runs required for regression" >&2
+ exit 1
+ fi
+ ;;
+
+release)count= lo= hi=
+ checksrc
+ checkaout release || exit
+ requirements source $package
+ components $package
+ package=$_components_
+ set '' $target
+ shift
+ case $# in
+ 0) ;;
+ *) case $1 in
+ -|[0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789])
+ case $1 in
+ -) lo= release= ;;
+ *) lo=$1 release="-f $1" ;;
+ esac
+ shift
+ case $1 in
+ -|[0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789])
+ case $1 in
+ -) hi= ;;
+ *) hi=$1 release="$release -t $1" ;;
+ esac
+ shift
+ ;;
+ esac
+ ;;
+ [0123456789]|[0123456789][0123456789]|[0123456789][0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789][0123456789]*)
+ count=$1
+ release="-r $count"
+ shift
+ ;;
+ esac
+ ;;
+ esac
+ case $# in
+ 0) case $package in
+ '') package=* ;;
+ esac
+ ;;
+ *) case $package in
+ '') package=$*
+ ;;
+ *) echo $command: $*: lo-date hi-date arguments expected >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ echo
+ case $count:$lo:$hi in
+ ::) echo "All recorded changes follow." ;;
+ 1::) echo "Changes since the last release follow." ;;
+ ?*::) echo "Changes since the last $count releases follow." ;;
+ 1:?*:) echo "Changes since $lo or the last release follow." ;;
+ *:?*:*) echo "Changes since $lo follow." ;;
+ *::?*) echo "Changes before $hi follow." ;;
+ *) echo "Changes between $lo and $hi follow." ;;
+ esac
+ x=
+ for r in $INSTALLROOT $PACKAGEROOT
+ do for s in $package_src
+ do d=$r/src/$s
+ if test -d $d
+ then cd $d
+ for i in $package
+ do if test -h $i 2>/dev/null
+ then continue
+ fi
+ case " $x " in
+ *" $i "*) continue ;;
+ esac
+ for f in RELEASE CHANGES ChangeLog
+ do if test -f $i/$f
+ then $exec release $release $i/$f
+ x="$x $i"
+ for f in $i/*/$f
+ do if test -f $f
+ then $exec release $release $f
+ fi
+ done
+ break
+ fi
+ done
+ done
+ fi
+ done
+ done
+ ;;
+
+remove) echo "$command: $action: not implemented yet" >&2
+ exit 1
+ ;;
+
+results)set '' $target
+ shift
+ def=make
+ dir=$PACKAGEBIN/gen
+ case $verbose in
+ 0) filter=yes ;;
+ *) filter=cat ;;
+ esac
+ path=0
+ suf=out
+ on=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ admin) dir=$PACKAGESRC/admin
+ ;;
+ error*|fail*)
+ filter=errors
+ ;;
+ make|test|view|write)
+ def=$1
+ case $filter:$1:$SHELL in
+ errors:*:*) ;;
+ *:test:*/ksh*) filter=rt ;;
+ esac
+ ;;
+ old) suf=old
+ ;;
+ on) case $# in
+ 1) echo $command: $action: $1: host pattern argument expected >&2
+ exit 1
+ ;;
+ esac
+ shift
+ case $on in
+ ?*) on="$on|" ;;
+ esac
+ on="$on$1"
+ ;;
+ path) path=1
+ ;;
+ test) def=test
+ filter=rt
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ done
+ case $dir in
+ */admin)case $on in
+ '') on="*" ;;
+ *) on="@($on)" ;;
+ esac
+ def=$def.log/$on
+ ;;
+ esac
+ case $# in
+ 0) set "$def" ;;
+ esac
+ m=
+ t=
+ for i
+ do k=0
+ eval set '""' $i - $i.$suf - $dir/$i - $dir/$i.$suf -
+ shift
+ for j
+ do case $j in
+ -) case $k in
+ 1) continue 2 ;;
+ esac
+ ;;
+ *) if test -f $j
+ then k=1
+ case /$j in
+ */test.*) t="$t $j" ;;
+ *) m="$m $j" ;;
+ esac
+ fi
+ ;;
+ esac
+ done
+ echo "$command: $i action output not found" >&2
+ exit 1
+ done
+ sep=
+ case $t in
+ ?*) case $path in
+ 0) for j in $t
+ do echo "$sep==> $j <=="
+ sep=$nl
+ case $filter in
+ cat) $exec cat $j
+ ;;
+ errors) $exec egrep -i '\*\*\*|FAIL[ES]|^TEST.* [123456789][0123456789]* error|core.*dump' $j | sed -e '/^TEST.\//s,/[^ ]*/,,'
+ ;;
+ rt) $exec rt - $j
+ ;;
+ *) $exec egrep -i '^TEST|FAIL' $j
+ ;;
+ esac
+ done
+ ;;
+ 1) echo $t
+ ;;
+ esac
+ ;;
+ esac
+ case $m in
+ ?*) case $path in
+ 0) case $filter in
+ cat) cat $m
+ ;;
+ *) if test -f $HOME/.pkgresults
+ then i="`cat $HOME/.pkgresults`"
+ case $i in
+ '|'*) ;;
+ *) i="|$i" ;;
+ esac
+ else i=
+ fi
+ for j in $m
+ do echo "$sep==> $j <=="
+ sep=$nl
+ case $filter in
+ errors) $exeg egrep '^pax:|\*\*\*' $j
+ ;;
+ *) $exec egrep -iv '^($||[\+\[]|cc[^-:]|kill |make.*(file system time|has been replaced)|so|[0123456789]+ error|uncrate |[0123456789]+ block|ar: creat|iffe: test: |conf: (check|generate|test)|[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*=|gsf@research|ar:.*warning|cpio:|ld:.*(duplicate symbol|to obtain more information)|[0123456789]*$|(checking|creating|touch) [/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789])| obsolete predefined symbol | is (almost always misused|dangerous|deprecated|not implemented)| trigraph| assigned to | cast .* different size| integer overflow .*<<| optimization may be attained | passed as |::__builtin|pragma.*prototyped|^creating.*\.a$|warning.*not optimized|exceeds size thresh|ld:.*preempts|is unchanged|with value >=|(-l|lib)\*|/(ast|sys)/(dir|limits|param|stropts)\.h.*redefined|usage|base registers|`\.\.\.` obsolete'"$i" $j |
+ $exec grep :
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ 1) echo $m
+ ;;
+ esac
+ esac
+ ;;
+
+test) requirements source $package
+ components $package
+ package=$_components_
+ case $only in
+ 0) only= ;;
+ 1) only=--recurse=only ;;
+ esac
+
+ # must have nmake
+
+ if nonmake $MAKE
+ then echo $command: $action: must have $MAKE to test >&2
+ exit 1
+ fi
+
+ # all work under $INSTALLROOT/src
+
+ $make cd $INSTALLROOT/src
+
+ # disable core dumps (could be disasterous over nfs)
+
+ (ulimit -c 0) > /dev/null 2>&1 && ulimit -c 0
+
+ # do the tests
+
+ eval capture \$MAKE \$makeflags \$noexec \$only recurse test \$target \$nmakesep \$package $assign
+ ;;
+
+update) # download the latest release.version for selected packages
+
+ # all work in $PACKAGEROOT/lib/package/tgz
+
+ if test ! -d $PACKAGEROOT/lib/package/tgz
+ then $exec mkdir -p $PACKAGEROOT/lib/package/tgz || exit
+ $exec cd $PACKAGEROOT/lib/package/tgz
+ else cd $PACKAGEROOT/lib/package/tgz
+ fi
+
+ # get the architectures, update query url, and packages
+
+ set '' $args
+ op=update
+ tgz=tgz
+ source=
+ binary=
+ setup=
+ types=
+ url=
+ urlfile=$default_url
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ beta) op=beta
+ tgz=beta
+ ;;
+ binary) binary=1
+ ;;
+ setup) setup=1
+ ;;
+ source) source=1
+ ;;
+ *://*) url=$1
+ shift
+ break
+ ;;
+ *.url) urlfile=$1
+ if test ! -s $urlfile
+ then echo $command: $urlfile: not found >&2; exit 1
+ fi
+ break
+ ;;
+ $all_types)
+ binary=1
+ types="$types $1"
+ ;;
+ *) break
+ ;;
+ esac
+ done
+ case $source:$binary in
+ :) source=1 binary=1
+ ;;
+ :1) case $types in
+ '') types=$HOSTTYPE ;;
+ esac
+ ;;
+ esac
+ case $url in
+ '') case $urlfile in
+ $default_url)
+ if test ! -s $urlfile
+ then echo $command: url argument expected >&2; exit 1
+ fi
+ ;;
+ *) default_url=
+ ;;
+ esac
+ url=
+ if grep '^url=' $urlfile >/dev/null
+ then a=$authorize
+ p=$password
+ case $urlfile in
+ */*) ;;
+ *) urlfile=./$urlfile ;;
+ esac
+ . $urlfile
+ case $a:$p in
+ $authorize:$password)
+ default_url=
+ ;;
+ *) case $a in
+ ?*) authorize=$a ;;
+ esac
+ case $p in
+ ?*) password=$p ;;
+ esac
+ ;;
+ esac
+ else url=`cat $urlfile`
+ fi
+ ;;
+ esac
+ case $exec in
+ ?*) default_url= ;;
+ esac
+
+ # get the update list
+
+ eval `echo $url | sed 's,\(.*\)://\([^/]*\)/\(.*\),prot=\"\1\" host=\"\2\" dir=\"\3\",'`
+ get $host $dir/$op.html
+
+ # get/check the package names
+
+ case " $* " in
+ *" - "*)case $source in
+ 1) source_packages=$* ;;
+ *) source_packages= ;;
+ esac
+ case $binary in
+ 1) binary_packages=$* ;;
+ *) binary_packages= ;;
+ esac
+ package_hit=$*
+ ;;
+ " ") nl="
+"
+ case $source in
+ 1) p=
+ for f in `ls *.????-??-??.* 2>/dev/null`
+ do case $f in
+ *.????-??-??.????-??-??.*.*)
+ ;;
+ *.????-??-??.????-??-??.*)
+ p=$p$nl$f
+ ;;
+ *.????-??-??.*.*)
+ ;;
+ *.????-??-??.*)
+ p=$p$nl$f
+ ;;
+ esac
+ done
+ set '' `echo "$p" | sed 's,\..*,,' | sort -u`
+ shift
+ source_packages=$*
+ ;;
+ *) source_packages=
+ ;;
+ esac
+ case $binary in
+ 1) p=
+ for f in `ls *.????-??-??.* 2>/dev/null`
+ do case $f in
+ *.????-??-??.????-??-??.*.*)
+ p=$p$nl$f
+ ;;
+ *.????-??-??.????-??-??.*)
+ ;;
+ *.????-??-??.*.*)
+ p=$p$nl$f
+ ;;
+ *.????-??-??.*)
+ ;;
+ esac
+ done
+ set '' `echo "$p" | sed 's,\..*,,' | sort -u`
+ shift
+ binary_packages=$*
+ ;;
+ *) binary_packages=
+ ;;
+ esac
+ package_hit="$source_packages $binary_packages"
+ ;;
+ *) case $source in
+ 1) source_packages=$* ;;
+ *) source_packages= ;;
+ esac
+ case $binary in
+ 1) binary_packages=$* ;;
+ *) binary_packages= ;;
+ esac
+ package_hit=
+ ;;
+ esac
+
+ # get the latest updates
+
+ types_test=
+ types_local=
+ dir=$dir/$tgz
+ case $default_url in
+ ?*) echo "url='$url' authorize='$authorize' password='$password'" > $default_url
+ case $authorize in
+ ?*) chmod go-rwx $default_url ;;
+ esac
+ ;;
+ esac
+ echo "$got" > got.tmp
+ case $only in
+ 0) exec < got.tmp
+ covered=
+ while read name suffix type base base_size delta delta_size sync sync_size requires covers base_sum delta_sum sync_sum comment
+ do case $requires in
+ ''|-*) continue ;;
+ esac
+ IFS=:
+ set '' $requires
+ IFS=$ifs
+ case $type in
+ -) case " $source_packages " in
+ *" $name "*|*" - "*)
+ for name
+ do case " $source_packages " in
+ *" $name "*)
+ ;;
+ *) source_packages="$source_packages $name"
+ covered=$covered:$covers
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ *) case " $binary_packages " in
+ *" $name "*|*" - "*)
+ for name
+ do case " $binary_packages " in
+ *" $name "*)
+ ;;
+ *) binary_packages="$binary_packages $name"
+ covered=$covered:$covers
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $covered in
+ ?*) x=$source_packages
+ source_packages=
+ for name in $x
+ do case :$covered: in
+ *:$name:*) ;;
+ *) source_packages="$source_packages $name" ;;
+ esac
+ done
+ x=$binary_packages
+ binary_packages=
+ for name in $x
+ do case :$covered: in
+ *:$name:*) ;;
+ *) binary_packages="$binary_packages $name" ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ esac
+ checksum=
+ for i in $checksum_commands
+ do case `( $i ) < /dev/null 2> /dev/null` in
+ ${checksum_empty}|${checksum_empty}[\ \ ]*)
+ checksum=$i
+ break
+ ;;
+ esac
+ done
+ case $checksum in
+ '') echo $command: warning: '{' $checksum_commands '}' command not found -- only download sizes will be checked >&2 ;;
+ esac
+ exec < got.tmp
+ while read name suffix type base base_size delta delta_size sync sync_size requires covers base_sum delta_sum sync_sum comment
+ do case $verbose in
+ 1) case $type in
+ -) i= ;;
+ *) i=.$type ;;
+ esac
+ j="$name.$base$i.$suffix"
+ case $delta in
+ -) j="$j -" ;;
+ *) j="$j $name.$base.$delta$i.$suffix" ;;
+ esac
+ case $sync in
+ -) j="$j -" ;;
+ *) j="$j $name.$base.$sync$i.$suffix" ;;
+ esac
+ echo $command: $j $base_size:$base_sum $delta_size:$delta_sum $sync_size:$sync_sum $requires >&2
+ esac
+ case " $package_hit " in
+ *" $name "*|*" - "*)
+ ;;
+ *) package_hit="$package_hit $name"
+ ;;
+ esac
+ case $type in
+ -) case " $source_packages " in
+ *" $name "*|*" - "*)
+ if test -s $name.tim
+ then continue
+ fi
+ lcl=$name.$base.$suffix
+ if test -f $lcl
+ then case $checksum:$base_sum in
+ :*|*:-) size=`wc -c < $lcl | sed 's, ,,g'` sum=$base_sum ;;
+ *) size=$base_size sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'` ;;
+ esac
+ else size=X sum=X
+ fi
+ if test "0" != "$force" -a "X-" = "X$delta" -o "$base_size" != "$size" -o "$base_sum" != "$sum"
+ then rmt=
+ case $sync:$sync_size in
+ -*|*[-:])
+ ;;
+ *) lcl=$name.$base.$sync.$suffix
+ if test -f $lcl
+ then rmt=1
+ get $host $dir $lcl $sync_size $sync_sum
+ fi
+ ;;
+ esac
+ case $base:$base_size in
+ -*|*[-:])
+ ;;
+ *) case $rmt in
+ '') lcl=$name.$base.$suffix
+ get $host $dir $lcl $base_size $base_sum
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ case $delta:$delta_size in
+ -*|*[-:])
+ ;;
+ *) lcl=$name.$delta.$base.$suffix
+ if test -f $lcl
+ then case $checksum:$delta_sum in
+ :*|*:-) size=`wc -c < $lcl | sed 's, ,,g'` sum=$delta_sum ;;
+ *) size=$base_size sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'` ;;
+ esac
+ else size=X sum=X
+ fi
+ if test "0" != "$force" -o "$delta_size" != "$size" -o "$delta_sum" != "$sum"
+ then get $host $dir $lcl $delta_size $delta_sum
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) case " $binary_packages " in
+ *" $name "*|*" - "*)
+ if test -s $name.$type.tim
+ then continue
+ fi
+ case " $types " in
+ *" - "*);;
+ " ") case " $types_test " in
+ *" $type "*)
+ ;;
+ *) types_test="$types_test $type"
+ for i in *.????-??-??.$type.* *.????-??-??.????-??-??.$type.*
+ do if test -f $i
+ then types_local="$types_local $type"
+ fi
+ break
+ done
+ ;;
+ esac
+ case " $types_local " in
+ *" $type "*)
+ ;;
+ *) continue
+ ;;
+ esac
+ ;;
+ *) case " $types " in
+ *" $type "*)
+ ;;
+ *) continue
+ ;;
+ esac
+ ;;
+ esac
+ lcl=$name.$base.$type.$suffix
+ if test -f $lcl
+ then case $checksum:$base_sum in
+ :*|*:-) size=`wc -c < $lcl | sed 's, ,,g'` sum=$base_sum ;;
+ *) size=$base_size sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'` ;;
+ esac
+ else size=X sum=X
+ fi
+ if test "0" != "$force" -a "X-" = "X$delta" -o "$base_size" != "$size" -o "$base_sum" != "$sum"
+ then rmt=
+ case $sync:$sync_size in
+ -*|*[-:])
+ ;;
+ *) lcl=$name.$base.$sync.$type.$suffix
+ if test -f $lcl
+ then rmt=1
+ get $host $dir $lcl $sync_size $sync_sum
+ fi
+ ;;
+ esac
+ case $base:$base_size in
+ -*|*[-:])
+ ;;
+ *) case $rmt in
+ '') lcl=$name.$base.$type.$suffix
+ get $host $dir $lcl $base_size $base_sum
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ case $delta:$delta_size in
+ -*|*[-:])
+ ;;
+ *) lcl=$name.$delta.$base.$type.$suffix
+ if test -f $lcl
+ then sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'`
+ else sum=X
+ fi
+ if test -f $lcl
+ then case $checksum:$delta_sum in
+ :*|*:-) size=`wc -c < $lcl | sed 's, ,,g'` sum=$delta_sum ;;
+ *) size=$base_size sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'` ;;
+ esac
+ else size=X sum=X
+ fi
+ if test "0" != "$force" -o "$delta_size" != "$size" -o "$delta_sum" != "$sum"
+ then get $host $dir $lcl $delta_size $delta_sum
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ closure=
+ for name in $source_packages $binary_packages
+ do case $name in
+ -) ;;
+ *) case " $package_hit " in
+ *" $name "*)
+ case $setup in
+ 1) case " $closure " in
+ *" $name "*)
+ ;;
+ *) closure="$closure $name"
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) echo $command: $name: unknown package >&2
+ ;;
+ esac
+ ;;
+ esac
+ done
+ exec <&-
+ rm -f got.tmp
+ case $closure in
+ ?*) echo $closure ;;
+ esac
+ ;;
+
+use) # finalize the environment
+
+ x=:..
+ for d in `( cd $PACKAGEROOT; ls src/*/Makefile src/*/Nmakefile 2>/dev/null | sed 's,/[^/]*$,,' | sort -u )`
+ do x=$x:$INSTALLROOT/$d
+ done
+ x=$x:$INSTALLROOT
+ case $CDPATH: in
+ $x:*) ;;
+ *) CDPATH=$x:$CDPATH
+ $show CDPATH=$CDPATH
+ $show export CDPATH
+ export CDPATH
+ ;;
+ esac
+ P=$PACKAGEROOT
+ $show P=$P
+ $show export P
+ export P
+ A=$INSTALLROOT
+ $show A=$A
+ $show export A
+ export A
+ case $NPROC in
+ '') hostinfo cpu
+ case $_hostinfo_ in
+ 0|1) ;;
+ *) NPROC=$_hostinfo_
+ $show NPROC=$NPROC
+ $show export NPROC
+ export NPROC
+ ;;
+ esac
+ ;;
+ esac
+ eval PACKAGE_USE=$package_use
+ export PACKAGE_USE
+
+ # run the command
+
+ case $run in
+ '') case $show in
+ ':') $exec exec $SHELL ;;
+ esac
+ ;;
+ *) $exec exec $SHELL -c "$run"
+ ;;
+ esac
+ ;;
+
+verify) cd $PACKAGEROOT
+ requirements binary $package
+ if executable ! $SUM
+ then echo "$command: $action: $SUM command required" >&2
+ exit 1
+ fi
+ case $target in
+ '') cd arch
+ set '' *
+ shift
+ target=$*
+ cd ..
+ ;;
+ esac
+ code=0
+ for a in $target
+ do case $package in
+ '') set '' arch/$a/lib/package/gen/*.sum
+ shift
+ if test -f $1
+ then for i
+ do package_verify $i || code=1
+ done
+ else echo "$command: warning: $a: no binary packages" >&2
+ fi
+ ;;
+ *) for i in $package
+ do if test -f arch/$a/lib/package/gen/$i.sum
+ then package_verify arch/$a/lib/package/gen/$i.sum || code=1
+ else echo "$command: warning: $a: no binary package for $i" >&2
+ fi
+ done
+ ;;
+ esac
+ done
+ exit $code
+ ;;
+
+write) set '' $target
+ shift
+ action=
+ list=
+ qualifier=
+ while :
+ do case $1 in
+ base|closure|delta|exp|lcl|pkg|rpm|tgz)
+ qualifier="$qualifier $1"
+ ;;
+ binary) action=$1
+ type=$HOSTTYPE
+ eval list=$PACKAGESRC/tgz/$admin_list
+ ;;
+ cyg) qualifier="$qualifier $1"
+ assign="$assign closure=1"
+ only=1
+ ;;
+ runtime|source)
+ action=$1
+ ;;
+ tst) qualifier="$qualifier tgz"
+ assign="$assign copyright=0 'PACKAGEDIR=\$(PACKAGESRC)/tst'"
+ ;;
+ nocopyright)
+ assign="$assign copyright=0"
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ done
+ case $action in
+ '') echo "$command: binary or source operand expected" >&2
+ exit 1
+ ;;
+ esac
+ set '' "$@" $package
+ shift
+ case $only in
+ 0) set '' `order "$@"`
+ shift
+ ;;
+ esac
+ case $# in
+ 0) echo "$command: at least one package name expected" >&2
+ exit 1
+ ;;
+ esac
+ if nonmake $MAKE
+ then echo "$command: must have $MAKE to generate archives" >&2
+ exit 1
+ fi
+
+ # all work under $PACKAGEBIN
+
+ $make cd $PACKAGEBIN
+ case $list in
+ ?*) $exec rm -f $list ;;
+ esac
+
+ # go for it
+
+ for package
+ do if view - all $package.pkg || view - all lib/package/$package.pkg
+ then eval capture \$MAKE \$makeflags -X ignore \$noexec -f \$package.pkg \$qualifier \$action $assign
+ else echo "$command: $package: not a package" >&2
+ fi
+ done
+ ;;
+
+TEST) set '' $target $package
+ shift
+ case $1 in
+ binary|source)
+ action=$1
+ shift
+ ;;
+ esac
+ order "$@"
+ ;;
+
+*) echo "$command: $action: internal error" >&2
+ exit 1
+ ;;
+
+esac
diff --git a/bin/silent b/bin/silent
new file mode 100755
index 0000000..c05e231
--- /dev/null
+++ b/bin/silent
@@ -0,0 +1,23 @@
+# non-ksh stub for the nmake silent prefix
+# @(#)silent (AT&T Research) 1992-08-11
+
+case $-:$BASH_VERSION in
+*x*:[01234567899]*) : bash set -x is broken :; set +ex ;;
+esac
+
+while :
+do case $# in
+ 0) exit 0 ;;
+ esac
+ case $1 in
+ *=*) case $RANDOM in
+ $RANDOM)`echo $1 | sed "s/\\([^=]*\\)=\\(.*\\)/eval \\1='\\2'; export \\1/"` ;;
+ *) export "$1" ;;
+ esac
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+done
+"$@"
diff --git a/lib/package/INIT.README b/lib/package/INIT.README
new file mode 100644
index 0000000..aa6af8b
--- /dev/null
+++ b/lib/package/INIT.README
@@ -0,0 +1,1013 @@
+The INIT package is required by all but the standalone and self
+extracting archive packages. It contains the package command, support
+scripts, and utilities. The package command installs binary packages,
+makes source packages, and generates new package tarballs.
+
+Source Package Installation Instructions:
+
+ (1) Do not install packages as root/super-user. Although some components may
+ have setuid executables, few must be owned by root. These are best
+ changed manually when the security implications are understood.
+ (2) Choose a package root directory and cd to it. This will be a local work
+ area for all packages.
+ (3) These instructions bypass the click to download package links on the
+ download site. If you already clicked, or if your system does not have
+ curl(1), hurl(1), lynx(1) or wget(1) then use the alternate instructions
+ for (3),(4),(5) in plan B below. Plan B installs the hurl(1)
+ script which works with ksh and modern bash. The top level URL is:
+ URL=http://www.research.att.com/sw/download
+ (4) If the bin/package script does not exist then run:
+ test -d bin || mkdir bin
+ url=$URL/package
+ (wget -O bin/package $url||curl -L $url||hurl $url) > bin/package
+ chmod +x bin/package
+ (5) Determine the list of package names you want from the download site, then
+ use the package(1) command to do the actual download:
+ bin/package authorize "NAME" password "PASSWORD" \
+ setup source $URL PACKAGE ...
+ (Refer to the AUTHORIZATION paragraph on the main download page for
+ NAME/PASSWORD details.) This downloads the closure of the latest
+ source package(s); covered and up-to-date packages are not downloaded again unless
+ package force ... is specified. Package content is verified using md5sum.
+ If the package root will contain only one architecture then you can install in bin and
+ lib instead of arch/HOSTTYPE/bin and arch/HOSTTYPE/lib by running this
+ instead:
+ bin/package authorize "NAME" password "PASSWORD" \
+ flat setup source $URL PACKAGE ...
+ To update the same packages from the same URL run:
+ bin/package setup source
+ (6) Build and install; all generated files are placed under arch/HOSTTYPE
+ ($INSTALLROOT), where HOSTTYPE is the output of bin/package (with no
+ arguments.) name=value arguments are supported; CC and debug=1 (compile
+ with -g instead of -O) are likely candidates. The output is written to
+ the terminal and captured in $INSTALLROOT/lib/package/gen/make.out:
+ bin/package make
+ (7) List make results and interesting errors:
+ bin/package results
+ Run the regression tests:
+ bin/package test
+ List test results and errors:
+ bin/package results test
+ (8) The generated binaries are position independent, i.e., they do not
+ contain hard-coded paths. However, commands with related files, like
+ file(1) and nmake(1), require the path of the bin directory to be
+ exported in PATH.
+ (9) You can run the binaries directly from the package root, or you can
+ install them in a public root after you are satisfied with the make and
+ test actions (requires the AT&T nmake(1) command):
+ bin/package flat install DIRECTORY PACKAGE
+ This will install in DIRECTORY/bin and DIRECTORY/lib. If you want to
+ preserve the arch/HOSTTYPE hierarchy under DIRECTORY then omit the
+ flat argument. If you don't have nmake(1) then the following will do a
+ flat install:
+ cd $INSTALLROOT
+ cp -p -r bin lib include DIRECTORY
+ (10) To summarize, after the first time the download, build, and test cycle
+ for the latest source release is:
+ bin/package setup source
+ bin/package make
+ bin/package test
+
+Source Package Installation Instructions -- Plan B:
+
+ (3) Create the subdirectory lib/package/tgz and download all package archives
+ into that directory.
+ (4) If the bin/package script does not exist then manually read the INIT
+ source package:
+ gunzip < lib/package/tgz/INIT.YYYY-MM-DD.tgz | tar xvf -
+ Note that some browsers automatically unzip downloaded without warning.
+ If the gunzip fails try:
+ tar xvf - lib/package/tgz/INIT.YYYY-MM-DD.tgz
+ If your system does not have tar(1) or gunzip(1) then download the ratz
+ source package, compile it, and manually read the INIT
+ source package:
+ mkdir bin
+ cp lib/package/tgz/ratz.YYYY-MM-DD.c lib/package/tgz/ratz.c
+ cc -o bin/ratz lib/package/tgz/ratz.c
+ bin/ratz -lm < lib/package/tgz/INIT.YYYY-MM-DD.tgz
+ (5) Read all unread package archive(s):
+ bin/package read
+ Both source and binary packages will be read by this step.
+
+All recorded changes follow.
+
+:::::::: INIT ::::::::
+
+12-02-29 cc.darwin.i386*: handle default cc vs kernel bittedness
+12-02-29 C+probe: add __TIMESTAMP__ to the nopredefined list
+12-02-29 package.sh: don't assume grep -q or /usr/local/lib in LD_LIBRARY_PATH
+12-02-29 package.sh: fix ksh vs -lcmd compatibility checks
+12-02-23 iffe.sh: checkcc() before checkread() for sensible diagnostics
+12-02-14 package.mk: { --clobber --compare --link=lib*.a* } for --mam=static
+12-02-14 package.mk: export LICENSEFILEDEFAULT instead of LICENSEFILE
+12-02-14 package.sh: handle @(cc|ld).${HOSTTYPE}* intercepts
+12-02-07 package.sh: add { clean clobber } actions
+12-02-02 regress.sh: fix ulimit -c defaults for --nokeep
+12-01-18 regress.sh: add INPUT|OUTPUT|ERROR -e 'filter' to filter before comparison
+12-01-21 package.sh: fix `admin make' bug that created unused $INSTALLROOT/lib
+12-01-21 Makefile: :PACKAGE: license=ast -- oops
+12-01-20 cc.darwin,cc.mvs.390: tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+12-01-12 package.sh: add admin make share closure to handle alternate HOSTTYPEs
+11-12-13 iffe.sh: add /*<NOSTDIO>*/ test code comment to disable default #include <stdio.h>
+11-11-11 C+probe: test for .so before .sl
+11-10-26 package.sh: don't forget about *.pkg for admin update
+11-10-18 cc.*-icc: update and add more
+11-10-11 package.sh: handle package make|view when no source installed
+11-09-11 package.sh: count admin '*** termination code' errors
+11-08-31 mamake.c: add -e, ignore use recursive prereq timestamps
+11-08-29 iffe.sh: add ``set stdio try1.h - try2.h ...''
+11-08-29 iffe.sh: trap EXIT => trap 0 for ancient sh
+11-08-11 iffe.sh: handle ancient sort that doesn't have -k
+11-06-01 make.probe: add more /lib64 logic
+11-05-01 package.sh: fix admin ditto to sync LICENSES too
+11-03-25 package.sh: initialize { $SED $TR } before first use!
+11-03-21 package.sh: fix vpath probes
+11-03-17 iffe.sh: fix cleanup to rm $tmp* instead of $tmp*.*
+11-02-24 package.sh: change curl usage to "curl -L ..."
+11-02-11 package.sh,C+probe,make.probe,mamprobe.sh: add ###.*archiac.*###
+11-02-02 Makefile: add :MAPLIB: check for ancient -lw
+11-02-02 make.probe: handle -print-multi-directory => 64 => /usr/lib64 /lib64
+11-02-02 package.sh: HOSTTYPE=*,*cc*[,-*,...] sets CC [ and CCFLAGS ]
+11-02-02 make.probe: handle gcc $ORIGIN link but exec failure -- gee thanks
+11-01-25 cc.hp.ia64: bundled cc is a pile of shaving cream
+11-01-07 iffe.sh: check debug==3 for is_hdr() failure
+10-11-22 ditto.sh: fix timing problem between |& and exec &p
+10-11-10 package.sh: fix cc cross compile check to use checkcc absolute path
+10-10-10 package.sh: list main env vars at start of make action
+10-10-10 ratz.c: tweak widnows delays
+10-09-10 ratz.c: add _SEAR_ARGS for _SEAR_EXEC
+10-09-01 package.sh: fix ratz from source logic
+10-08-25 package.mk: consolidate license file search in .package.licenses.
+10-08-22 ratz.c: run sear bootstrap command detached
+10-08-20 C+probe: version_stamp only if version_flags works
+10-08-17 package.sh: unset makerules *DIR variables in env
+10-08-15 package.sh: "make" action now lists some env values
+10-08-11 mktest.sh: add "DO command ..."
+10-07-27 rt.sh: handle "rt X=Y ..."
+10-06-29 ratz.c: non-option sear args passed to sear_exec()
+10-06-25 iffe.sh: "api" op chanegd to not do "map-libc" type mappings
+10-06-25 package.sh: "force admin ditto" => no ditto --update option
+10-06-22 C+probe: handle cc that require .[ci] input for version info
+10-06-21 ditto.sh: change default remote access to ssh (about time)
+10-06-12 regress.sh: DISGNOSTICS [ 1 | 0 | pattern ] and fix EXIT for all
+10-06-09 package.sh: add AT&T to usable nmake check
+10-06-06 iffe.sh,iffe.tst: add { api ver } ops
+10-04-22 package.sh: update "html binary|source" NAME/PASSWORD info
+10-04-15 iffe.sh: don't forget candidate headers for hdr|sys!
+10-04-11 WWW.mk: disable man page metarule -- now done by admin-man(1)
+10-02-14 package.sh: $CC verification needs $INSTALLROOT/bin in PATH
+10-02-11 package.sh: fix package admin make report error count
+10-02-02 package.sh: fix write binary bug that did scp on local fs
+10-02-02 package.mk: up to date binary targets must still be in PACKAGE.*.lst
+10-01-01 package.sh: fix premature $INSTALLROOT/bin during cross compile check
+10-01-01 make.probe: handle ['"] in CC.VERSION.STRING
+09-12-04 iffe.sh: add "opt name" to check for name in $PACKAGE_OPTIONS
+09-11-30 mktest.sh: change RESET to STATE.RESET to make it global
+09-11-14 make.probe: use gcc { -print-multi-directory -print-search-dirs }
+09-11-11 package.sh: re-order and combine cc checks
+09-10-27 C+probe,make.probe,probe.win32: add CC.SUFFIX.DEBUG
+09-10-21 iffe.sh,Makefile: test -e is not in ksh88!
+09-10-06 iffe.sh: handle cc -E #error with 0 exit status (sgi)
+09-10-06 package.sh: stub in ar intercept checks -- not used yet
+09-10-06 ar.ibm.risc: add ar intercept because some aix require -Xfoo first!!
+09-09-24 regress.sh: fix UMASK logic to create test support files before umask
+09-08-28 release.c: change docs to mention stdin if no file operands
+09-08-24 package.sh: fix isascii() bug that failed on od(1) trailing space
+09-08-20 make.probe: add CC.SHARED.NAME
+09-08-20 regress.sh: add { JOB CONTINUE EXITED KILL FIFO }
+09-08-11 package.sh: filter lines containing : for package results
+09-07-31 make.probe: add CC.AR.ARFLAGS (for aix ar -xany)
+09-07-31 package.sh,cc.*: fix -dumpmachine to handle 32/64/* bit options
+09-06-24 package.sh: fix admin.db output formatting
+09-05-05 package.sh: export dll hackery environment vars
+09-05-05 package.sh: handle non-identifier hostnames
+09-05-05 mamake.c: pass undefined ${...} identifiers to the shell
+09-05-05 mamake.rt: add macro expansion regression tests
+09-05-01 iffe.sh: fix output initialization *again*
+09-04-28 package.sh: handle admin.db contact field $9
+09-04-15 iffe.sh: add implicit "ini" op to initialize io for subsequent ops
+09-03-31 regress.sh: EXPORT before test => global ENVIRON[]
+09-03-26 package.sh: test fail pattern is 'fail[es]'
+09-03-26 UNIT - ... appends (options) to command line
+09-03-19 TEST.mk: x.tst => x only if x is command target
+09-03-15 regress.sh: add ${MAIN} for base name of main unit
+09-03-10 TEST.mk: add .SOURCE:tests if tests is a dir
+09-03-03 regress.sh: allow command line unit to override UNIT
+09-03-03 mktest.sh: handle IO == $'\n'
+09-02-02 package.sh: delay $INSTALLROOT/bin/.paths generation until mamprobe runs
+09-01-30 cc.mvs.390: c89 balks at [ ()] in -Dname="..."!
+09-01-27 package.sh: add isascii() to use ratz instead of tar
+09-01-20 hurl.sh: add --size=bytes option
+09-01-08 TEST.mk: add test.* prereqs, multiple arg lists with :T=*: binding
+09-01-03 regress.sh: fix UNIT to allow command line override
+09-01-03 mktest.sh: handle TWD
+08-12-24 package.sh: fix cross-compile HOSTTYPE logic
+08-12-15 package.sh,hurl.sh: handle http codes { 301 302 303 }
+08-10-16 make.probe '-fno-stack-protector -fno-stack-protector-all' to cop out!!
+08-09-30 rt.sh: fix ksh93 regression test signal count
+08-09-26 regress.sh: ignore SIGPIPE for SET pipe-input
+08-09-24 package.sh: package only test foo => make --recurse=only recurse tests foo
+08-09-20 make.probe: handle another /usr/bin/file shared lib description
+08-09-20 regress.sh: add --pipefail for SET pipe-input ...
+08-09-17 Makefile: add gdbm1.c for <gdbm-ndbm.h>
+08-09-10 make.probe: add CC.NOPROTECT
+08-08-08 mktest.sh: add --width=width
+08-08-05 dbm.req: favor sleepycat ndbm compatibility
+08-08-04 C+probe: fix stdlib initialization logic
+08-06-24 package.sh: fix $INSTALLROOT/bin/cc intercept time stamp file typo
+08-06-20 TEST.mk: make the localyunit before *.rt => *.tst -- doh
+08-06-20 mktest.sh: prepend $PWD onto PATH for local units -- doh^2
+08-06-11 regress.sh: fix bug that skipped the last test
+08-05-20 regress.sh: add --local to put *.tmp dir in local fs
+08-05-05 regress.sh: add IF command ... ELIF command ... ELSE ... FI
+08-05-01 package.sh: package test => ulimit -c 0
+08-04-28 regress.sh: fix EXPORT quoting
+08-04-28 regress.sh: fix UNIT set check args too
+08-04-24 rt.sh: exit code > 256 => signal termination
+08-04-10 C+probe: change probe_so order to check .so last (macos ld workaround)
+08-04-01 package.sh: handle multiple admin HOSTTYPEs per HOST
+08-03-28 C+probe: add C++ #include <iostream> (no extension) dir probes
+08-03-17 regress.sh: fix trap on EXIT, add terminated note to final tally
+08-02-28 make.probe: fix probe_warn to include ld!
+08-02-02 make.probe: add CC.RUNPATH to match default -L order
+08-01-31 package.sh: check lib64 for LD_LIBRARY_PATH
+08-01-31 iffe.sh: tweak ancient /bin/sh workarounds
+08-01-28 make.probe: darwin ld export dynamic is -force_flat_namespace
+08-01-28 C+probe: handle sgi cc error message but exit 0 botch(es)
+08-01-23 package.sh: fix checksum doc typo
+08-01-09 C+probe: add __FUNCTION__ to the undef (don't check) list
+07-12-14 iffe.sh: add set nooptimize
+07-12-03 package.sh: add LC_ALL=C
+07-11-27 package.sh: fix overaggressive *.md5 cleanup
+07-11-20 iffe.sh: treat exit status >= 250 as normal error with no signal
+07-11-05 package.sh: fix write op error count pattern
+07-11-05 package.mk: fix $(~req) .ver binding
+07-08-11 probe.win32: add cl.exe setuid workaround, CC.VERSION[.STRING]
+07-08-01 package.sh: handle 'package read lcl|tgz'
+07-05-08 regress.sh: execute basename instead of absolute path for short $0
+07-04-27 cc.sgi.mips[34]: for #error to exit non-zero -- a no brainer
+07-04-20 mktest.sh: defer to systems without 'grep -q' -- sigh
+07-04-11 mamprobe.sh: handle $(CC.*) => ${mam_cc_*}, $(...) => ${...}
+07-04-11 make.probe: fix CC.PICBIG probe, default { CC.PIC CC.DLL } to BIG
+07-04-04 iffe.sh: prepend ${tst}${ext} to each .c probe
+07-03-28 package.sh: fix binary tgz architecture type duplication
+07-03-28 package.mk: add binary write PACKAGE.$HOSTTYPE.lst
+07-03-28 iffe.sh: add -F header to mac test
+07-03-23 make.probe: handle file(1) that returns 'archive' for .so
+07-03-22 mamprobe.sh: fix STDED probe for implementations that ignore EOF
+07-03-11 package.sh: add nocopyright and tst => nocopyright
+07-03-11 package.mk: add copyright=0
+07-03-08 C+probe: restore IFS after probe.ini
+07-02-26 mamake.c: expand first of ${mam_lib*} for ${AR}
+07-01-05 package.sh: fix "admin write binary" logic
+07-01-01 iffe.sh: add "cmd" --verbose trace
+07-01-01 iffe.sh: sort => LC_ALL=C sort
+07-01-01 C+probe: LC_ALL=C
+06-12-22 make.probe: lean on gcc -v for stdlib, but preserve /usr/local!
+06-11-23 package.sh: *.md5 are not tarballs -- doh
+06-11-23 iffe.sh: add -F, --features=feature-test-header
+06-11-11 make.probe: favor lib64 over lib for hosttype==*64
+06-10-31 make.probe: add "-ignore-source-dir -iquote" test
+06-10-31 iffe.sh: add status{...} code block
+06-10-11 regress.sh: fix DO to handle {...} (time for regress.tst?)
+06-10-11 package.sh: handle already gunzip'd *.tgz
+06-10-06 iffe.sh: add reference for header content tests
+06-09-27 regress.sh: fix UMASK to do DO too (duh)
+06-09-22 iffe.sh: drop -O for npt tests (for msvc intrinsics)
+06-09-14 cc.darwin: drop -O until gcc 4.* gets its act together
+06-09-11 package.sh: { cc ld ldd } intercepts check ${HOSTTYPE%.*} too
+06-09-08 regress.sh: add PIPE INPUT|OUTPUT for pipe io
+06-09-05 C+probe: add { probe_version version_stamp version_string }
+06-09-05 make.probe: add version stamp comment, CC.VERSION[.STRING]
+06-08-27 regress.sh,mktest.sh: add UMASK
+06-08-25 regress.sh: add -b,--ignore-space,IGNORESPACE
+06-08-25 mktest.sh: add IGNORESPACE
+06-08-24 mktest.sh: handle \000 in data
+06-08-24 regress.sh: handle -f* for INPUT|OUTPUT|ERROR
+06-08-16 package.sh: fix 'install flat' logic
+06-08-11 rt.sh: handle style=shell %K date format
+06-07-17 ratz.c: fix __MVS__ FAR definition
+06-07-17 iffe.sh: "header x.h" -- deprecate "include x.h" for .SCAN.iffe
+06-07-17 package.sh: differentiate urls vs. assignments
+06-06-27 rt.sh: add --failed, --heading
+06-06-27 C+probe,TEST.mk,make.probe,mktest.sh,regress.sh: 'ulimit -c 0'
+06-06-26 cc.darwin.ppc: handle -lcc_dynamic disappearance
+06-06-25 mktest.sh: implement PROG
+06-06-11 Makefile: add -ldbm :MAPLIB:, provide public MAPLIB.mk
+06-05-06 package.sh: add PACKAGE_admin_tail_timeout
+06-05-22 ratz.c: upgrade to zlib-1.2.3
+06-05-09 package.sh: fix admin.db docs
+06-03-11 package.sh: fix `package use - command ...'
+06-03-05 make.probe: work around pedantic bash 3.1 mismatched " in `.`
+06-02-14 package.sh: "results failed test" == "results test failed"
+ cc.sgi.*: add _AST_cc_OPTIONS parameterization, -OPT:Olimit=0
+ cc.linux.ia64-icc: add for intel cc
+06-02-02 package.sh: freebsd stuck with os version for all arch
+06-02-01 package.mk: fix locale logic (tw -d requires dir arg)
+06-01-31 package.sh: require $CC only for make|test
+06-01-30 package.sh,hurl.sh: use the backwards-compatible --http-passwd
+ package.sh: add more pdksh => /bin/sh checks
+06-01-26 package.sh: wget --http-pass => --http-password
+ package.sh: fix wget error logic
+ hurl.sh: wget --http-pass => --http-password
+06-01-11 package.mk: pass package.license.class to make --mam too
+ package.mk: variants=pattern => --variants=pattern
+ package.sh: darwin rel<=7 => darwin7.ppc
+ package.sh: freebsd rel<=4 => freebsd4
+ package.sh: freebsd rel<=5 => freebsd5
+05-12-07 iffe.sh: don't emit <stdio.h> if <sfio.h>|<ast.h> (XXX)
+05-12-05 make.probe: disable readonly.exe core dump via ulimit -c 0
+05-09-22 mktest.sh: add EXEC [ ++NOOUTPUT ++NOERROR ++NOEXIT ]
+05-09-21 mktest.sh: fix --style=shell compare to ignore \r
+05-09-12 TEST.mk: all --force to force %.rt regeneration
+05-09-05 TEST.mk: regenerate from %.rt only if newer, :SAVE: %.tst
+05-08-25 mktest.sh: add
+ TEST.mk: add %.rt=>%.tst for mktest
+05-08-18 package.sh: 'package host cpu' now checks $NPROC first
+05-07-17 iffe.sh: add { define extern include print } ops
+ iffe.sh: accept output{...}end output on success only -- doh
+05-07-01 package.sh: add TARPROBE for tar B flag probe
+05-06-24 package.sh: fix binary read chmod via *.sum
+05-06-06 package.sh: fix KEEP_HOSTTYPE logic to handle synthesized types
+05-06-01 make.probe: verify that cc_pic works for hosted cc
+ cc.lynxos.ppc: make -mshared the default
+ package.sh: note $INSTALLROOT/bin/@(cc|ld|ldd) installation
+05-05-25 make.probe: add CC.INCLUDE.LOCAL instead of -I- in CC.DIALECT
+05-05-24 iffe.sh: really fix grouping logic -- with tests this time
+ package.sh: pipe/socket configuration mismatches => use /bin/sh
+05-04-28 TEST.mk: add $(TESTS)
+05-04-19 package.sh: package results test uses rt if possible
+ iffe.sh: fix 'op var - ... - ...' grouping logic
+05-04-15 rt.sh: handle autom4ate style
+05-04-11 regress.sh: fix unit name when command line unit also specified
+ rt.sh: handle all ast package test output formats
+ package.sh: fix make docs for options passed to underlying make
+05-04-08 package.sh: cp -p makerules.mo to $OK to preserve mtime
+ regress.sh: add "TITLE name" to change TEST output title
+05-04-01 rt.sh: add pretty make test + regress.sh wrapper
+05-03-29 package.sh: test -e path => test -f path -o -d path
+05-03-24 make.probe: fix CC.PICBIG probe to prefer -fPIC over -fpic -- doh
+05-03-19 mamake.c: command line name=var also defines name.FORCE=var
+05-03-11 regress.sh: unset LC_ALL when LC_* EXPORT'd
+ package.sh: old make.out saved in circular make.out.[1-9]
+ mamake.c: sync with nmake :W=O:
+05-03-01 package.sh: fix flat hierarchy initialization
+ package.sh: admin action now properly resets sibling remote logs
+ package.mk: relax unknown/unwritten package messages to warnings
+ package.sh: handle space in command line name=value
+ make.probe: add mvs -Wc,dll,exportall,longname,rent to CC.DLL probe
+05-02-24 package.sh: hosttype *.powerpc => *.ppc
+ cc.lynxos.ppc,ldd.lynxos.ppc: add
+05-02-22 mamake.c: fix { -G --debug-symbols -S --strip-symbols } MAMAKEFLAGS bug
+05-02-20 probe.win32: handle /platformsdk mount
+05-02-19 package.sh,package.mk: add write tst for tgz in tst subdir
+05-02-18 package.sh: accept cc -dumpmachine with 0 or 1 -
+05-02-14 package.sh: handle mutiple architectures per host in admin.db
+ Makefile,package.sh: honor $INSTALLROOT/bin/.paths overrides
+ package.sh: normalize trailing [-_]bits in host type
+ iffe.sh: some ksh-compatible shells don't do *(pattern)
+05-02-11 iffe.sh: back out 05-01-11 child process stdin hijack
+ cc.lynxos.i386: -dynamic instead of -static default
+05-02-10 package.sh: cyg usr/doc => usr/share/doc
+05-02-08 package.sh: drop -m with pax -- delta bug fixed 2005-02-08
+ iffe.sh: work around old bash 0<... redirection bug
+05-02-06 package.mk: source.tgz: update generated files only when they change
+05-02-02 *.sh,*probe: IFS may be unset and { ash bsh } don't on startup -- wow
+05-01-11 package.sh: update setup docs to include authorize+password
+ package.mk: fix .source.cyg final directory edit
+ package.mk: notice=1 for conspicuous empty NOTICE file
+ WWW.mk: fix *-index.html installation
+ filter.sh: retain input file suffix in tmp copy
+ mamexec.c: fix non-contiguous "exec" bug that skipped lines
+ iffe.sh: fix candidate lib test to try grouping subsequent libs
+ iffe.sh: fix child process stdin hijack that skipped input lines
+ iffe.sh: --shell=osh to force read -r compatibility command
+ iffe.sh: chop iffe input leading space before # for KnR compatibility
+05-01-05 package.sh: add ${TAR} ${TARFLAGS} and tar B flag for pipes
+ mamake.c: fix makefile scan to ignore lib*.[hH]
+ iffe.sh: immunize function/symbol tests from aggressive -O
+04-12-28 WWW.mk: add :WWWPAGE: faq.*.mm index generator
+04-12-21 ratz.c: make sure tmp dir is writable -- doh
+04-12-08 iffe.sh: fix dat test for aggressive -O
+04-12-01 iffe.sh: add `include file' to pull in #define's for `exp'
+04-11-11 package.sh: default MAKESKIP is "*[-.]*"
+04-10-22 ratz.c: change docs to note zlib license
+ mamake.c: handle --debug-symbols and --strip-symbols
+ package.sh: make (debug|strip)=1 => --(debug|strip)-symbols
+ package.mk: add :LICENSE: => package.license.class
+ mamake.c: fix recursive order logic
+04-10-18 package.mk: add :LICENSE:, :OMIT: to omit package subdirs
+04-10-11 package.sh: add 'authorize name' and 'password password'
+04-10-01 iffe.sh: double check $static link with ! $static
+ Makefile: add BUILTIN_LIB to $INSTALLROOT/bin/.paths
+ make.probe: add CC.DIALECT EXPORT={ALL,REF,EXT,DLL}
+ package.sh: add BUILTIN_LIB to $INSTALLROOT/bin/.paths
+04-09-21 package.mk: $(init)$(name) is now an implicit prereq
+04-09-09 package.sh: copy makerules.mo to $INSTALLROOT/bin/ok
+04-09-01 package.mk,package.sh: rename *.txt => *.README
+ package.mk: add the runtime package type (no *.[ah])
+ iffe.sh: fix key test reports
+04-08-26 Makefile: { add m2.c m3.c } -lm tests for { frexp[l] ldexp[l] }
+04-08-11 package.mk: handle HOSTTYPE for solaris > 9
+ package.sh: add `checkaout proto' for { make view }
+ package.sh: check for { md5sum md5 }
+ iffe.sh: add {if|elif|else|endif} test ...
+ iffe.sh: add 'exp - expression' and '( expression )'
+ iffe.sh: add 'name = test ...' user defined macros
+ iffe.sh: add '! test ...' negation
+ TEST.mk: add implied { .c .sh } generated prereq
+ cc.darwin.ppc: handle 10.3 -dylib mess
+04-08-01 package.mk: let include handle nested requirements -- duh
+04-07-31 package.sh: attempt a second ping before admin assumes host down
+04-07-26 package.sh: fix hp.ia64 HOSTTYPE
+04-07-23 probe.win32: generalize #include dir order search
+04-07-17 regress.sh: add INPUT -x for chmod +x
+04-07-01 regress.sh: TMP => TWD
+04-06-29 regress.sh: put COMMAND in $TWD too
+04-06-21 regress.sh: mkdir -p INPUT and OUTPUT intermediate dirs
+ TEST.mk: add :TEST: -- to disable .c .sh search
+04-06-18 TEST.mk: add .SCAN.tst
+04-06-17 regress.sh: TEST returns true if active, false otherwise
+ regress.sh: add CD to change test pwd from $TWD
+04-06-16 regress.sh: add TWD for ./unit.tmp override
+ regress.sh: DO now flushes previous test
+ regress.sh: INPUT and OUTPUT handle -f for printf instead of print
+04-06-11 package.sh: make sure $INSTALLROOT/bin is in front of $PATH
+ package.sh: skip nmake if older than 2000-10-31
+04-05-20 package.sh: fix arg vs. package parse with - or '' to disambuguate
+04-05-11 package.sh: package verbose update lists closure for package setup
+ package.sh: add src/lib/libardir to nmake proto bootstrap
+ regress.sh: probe for rm -u vs. chmod -R u+rwx
+04-05-01 package.sh: $CC must be C, not C++; allow release command on $PATH
+04-04-15 make.probe: check probe_libdir false positives
+ package.sh: add lib/package/*.lic src package subdirs
+ package.mk: add mamfile=0 to inhibit Mamfile generation
+ iffe.sh: config name_DECLARED => HAVE_name_DECL
+ iffe.sh: fix mac to handle default value
+04-04-11 iffe.sh: normalize sed [\\\\/] quoting
+04-04-04 package.mk: only checksum generated tarballs
+ mamprobe.sh: add STDCHMOD
+04-04-01 C+probe: set export LANG=C for uniform error messages
+ make.probe: another CC.STDLIB tweak
+ package.sh: fix regress core dump pattern, expand [a-z] match ranges
+04-03-31 Makefile: add intl :MAPLIB: test
+ make.probe: fix CC.STDLIB search; drop CC.* path duplicates
+04-03-28 iffe.sh: drop unused exec $stdin<&0 dup
+04-03-25 Makefile: add iconv :MAPLIB:
+ package.sh: use ${PING:-ping -c 1 -w 4}, allowing admin.db override
+04-03-24 package.mk: add *.md5 checksum for each *.(c|exe|tgz)
+ package.sh: update base change on md5 sum instead of size
+ iffe.sh: adjust case label \ and keyword quoting for ancient /bin/sh
+04-03-22 probe.win32: ncc => nld
+04-03-19 CONVERT.mk: change the instructions and old source dir default
+ package.mk: fix recurse=list check
+ package.mk: add *.md5 checksum for each *.(c|exe|tgz)
+ package.sh: fix update base/delta/sync existence check
+04-03-18 iffe.sh: -d2 does not remove core dumps on exit
+04-03-17 package.sh: fix make recurse arg/action order
+04-02-29 package.sh: add regress action to compare current and previous tests
+ package.sh: fix sgi.mips[23] HOSTTYPE test for old irix cc
+ package.sh: add `export variable ...'
+ package.sh: admin action now handles host name with non-id chars
+ package.sh: non-numeric M T W in admin.db disables that action
+ package.sh: fix admin write binary local vs. shared clash
+ cc.hp.pa: add _AST_CC_hp_pa_DEFAULT=+DAportable
+ cc.hp.pa64: sync with cc.hp.pa
+ cc.ibm.risc: -bnolibpath => -blibpath:/usr/lib:/lib
+ probe.win32: sync with make.probe
+ make.probe: fix last chance dynamic test
+ make.probe: add hp.pa CC.EXPORT.DYNAMIC -Wl,-E
+ make.probe: add ibm.risc CC.EXPORT.DYNAMIC -bexpall
+ make.probe: move probe_dll_def to the end of probe_dll
+ package.mk: capture subcomponent mamfile recursion
+04-02-24 make.probe: strip "..." from cc/ld traces
+ iffe.sh: add ``set [no]define'' to disable macro #define/#undef
+04-02-23 make.probe: rework CC.LD search
+04-02-14 make.probe: add CC.EXPORT.DYNAMIC for main dynamic sym export
+ make.probe: resurrect CC.PIC with separate semantics from CC.DLL
+ make.probe: add CC.SHARED.LD for CC.SHARED linker
+ C+probe: clear DISPLAY to stifle interactive windows
+04-02-11 iffe.sh: handle ``siz void*'', add cross{ ... }end
+ make.probe: add { CC.AR CC.SIZE }, fix cross command search
+ cc.darwin.ppc: change $cc => $CC for old ksh + libast conf bug
+04-02-09 make.probe: drop -nostartfiles from CC.SHARED for C++
+04-02-04 package.sh: fix cross compilation bug that mixed binary formats
+04-02-02 package.sh: package admin now ditto's bin/package too
+04-01-30 cc.sgi.mips3: drop warning 3421
+04-01-11 regress.sh: output label#count for tests in loops
+04-01-05 regress.sh: fix bug that ignored the first SAME
+04-01-04 crossexec.sh: fix typo that did not recognize rcp
+03-12-19 mamake.c: add `foolib:foo:libfoo' to recurse()
+03-10-11 regress.sh: add EXPORT, export COLUMNS=80 for message consistency
+03-09-23 ratz.c: fix tar header number parse bug that skipped to next number
+ regress.sh: rm cleanup now handles files matching -*
+03-09-11 iffe.sh: add unnamed { ... } blocks
+ regress.sh: add COPY from to, like MOVE but comprison still done
+ regress.sh: rm -rfu to handle test dirs w/o u+rwx
+03-08-14 Makfile: add hello.c to the manifest
+03-08-11 package.sh: fix `html binary' generation
+03-06-21 package.sh: fix INITROOT initialization bug
+ package.sh: make sure admin logs exists before tail'ing
+03-06-11 probe.win32: fix $(BINDIR) typo that expanded in sh instead of make
+ cc.mvs.390: return code 4 yields exit code 3 but its *really* ok
+ package.sh: fix onpath function global var conflict
+ make.probe: add CC.DIALECT { GNU -dD }
+ package.mk: add Mamfile to lcl manifest
+03-06-10 package.sh: fix setup action typo that only checked the INIT package
+ package.sh: *.s390x => *.s390-64
+03-06-09 package.mk: add cyg :POSTINSTALL:
+03-06-08 make.probe: fix CC.STDLIB logic
+ hurl.sh: add User-Agent identification
+ package.sh: tweak source and binary installation instructions
+ cc.hp.pa,ld.hp.pa: +-Wl,+cdp,${INSTALLROOT}/lib/: drops abs lib paths
+ ldd.hp.pa: add
+03-06-06 package.sh: fix $INSTALLROOT/bin/ldd check
+ make.probe: add CC.STDLIB verification
+03-06-04 make.probe: add +forceread +noforceread
+03-05-11 hurl.sh: handle http://host:port/path
+03-05-06 package.sh: fix setup action PACKAGEROOT and INIT logic
+03-05-05 package.mk: fix cygwin tarball names
+03-04-30 package.sh: move (cc|ld|ldd).$HOSTTYPE updates from Makefile
+03-04-27 make.probe: fix mvs CC.PREFIX.SHARED "lib" => ""
+ make.probe: add CC.DLL.DIR = $(BINDIR) or $(LIBDIR)
+ make.probe: add { CC.LD.LAZY CC.LD.NOLAZY CC.LD.RECORD CC.LD.NORECORD }
+ probe.win32: sync with latest CC.*
+03-04-25 mamprobe.sh: add args to `. $makeprobe' for ancient sh
+03-04-23 package.mk: fix dup "covered by" licenses
+03-04-22 probe.win32: CC.DIALECT += "LIBPP -I-" for all cc's
+ package.sh: fix admin write binary tarball snarf
+03-04-21 package.mk: package covered *.@(pkg|lic) too
+03-04-15 package.mk: don't generate incremental archives for lcl
+ package.mk: add incremental=[source:1 binary:0] archive control
+ package.sh: generate $INSTALLROOT/bin/cc wrapper for CC != cc
+ package.sh: admin must ditto lib/package/*.@(pkg|lic) too
+ mamake.c: ignore time of ignore prereqs
+ mamake.c: -D2 lists propagated times
+03-04-11 package.mk: tidy up cyg tarballs
+ package.sh: fix old shell clash between get() and $get
+03-04-05 package.mk: restore *.inx generation somehow lost during cyg additions
+ package.sh: add pthread_num_processors_np() last resort for cpu count
+ package.sh: use `make believe' to accept mamake generated files
+ package.sh: handle `make [make-flags] [target ...]'
+ mamake.c: ignore -e
+03-03-21 package.mk: fix cyg old make typo
+ package.sh: switch to `package setup' instructions
+03-03-19 package.sh: add registry checks for `host cpu'
+ package.sh: `results failed' now lists core dump messages
+03-03-17 package.sh: on cygwin verify 'ntsec binmode' in $CYGWIN or die
+ Makefile: install gcc wrapper if no cc
+ package.mk: add :DETAILS: { :README: :EXPORT: :INSTALL: :TEST: } ops
+03-03-12 package.mk: add :DETAILS: for style-specific details
+03-03-11 package.sh: add beta setup/update support
+ TEST.mk: add (TESTCC) prereq for .sh tests
+03-03-07 hurl.sh: add
+03-03-06 iffe.sh: fix lib win32 test cygwin vs native incompatibility
+ iffe.sh: change internal stdio.h guard to handle C++ inline vs. macro
+03-03-03 package.sh: check for curl or wget for update
+ package.sh: add setup action == update read make
+ package.sh: fix packageroot() typo that showed up in non ~user shells
+ mamake.c: treat name+=value args like name=value
+ mamake.c: add ${var?*|value?match?no-match?}
+ mamake.c: fix archive vs. dynamic bind logic
+03-02-28 package.sh: add the "cyg" (cygwin) package type
+ package.mk: add "cyg" stubs, :CATEGORY: for category name(s)
+03-02-25 mamake.c: add -D4 system(3) debug trace
+03-02-24 package.mk: change --mismatch to --corrupt=accept
+03-02-14 ratz.c: add _WIN32 setmode([01],O_BINARY) and fopen "rb"/"wb"
+03-02-12 Makefile: handle getconf LIBPATH with host pattern
+03-01-31 package.mk: fix .lic search
+03-01-30 package.sh: handle { INIT ksh nmake } already installed elsewhere
+ package.sh: admin handles command outside of $PACKAGEROOT/bin
+ Makefile: install $(INSTALLROOT)/lib/make/package.mk
+03-01-28 package.sh: admin remote commands on one line to please syslog
+03-01-23 probe.win32: borland and mingw32 tweaks
+03-01-22 package.sh: fix $CC test to ignore set -x trace -- duh
+03-01-16 ditto.sh: tw --chop on by default
+03-01-14 package.sh: use /bin/cp to copy previous binaries to bin/ok/
+ package.sh: admin now initiates remote exec and copy from local host
+03-01-12 package.sh: handle admin "xxx:" default root
+03-01-03 probe.win32: add /usr/include/borland path truncation workaround
+02-12-10 iffe.sh: add <&$nullin >&$nullout to checkread() $cc
+02-12-06 probe.win32: fix inlcude => include typo, add lcc lib
+ probe.win32: CC.MAKE.OPTIONS = nativepp=0
+02-12-04 mamake.c: fix ${foo-bar} to expand foo if defined
+02-11-28 probe.win32: add C++ and -I- CC.DIALECT checks
+02-11-26 package.sh: package release now checks for second level files
+02-11-22 package.sh: update action now uses HTTP/1.0
+02-11-21 probe.win32: update the vc include dir test
+02-11-20 make.probe: fix CC.LD.ORIGIN typo that expanded make var
+02-11-13 packahe.mk: fix list.install => list.installed typo
+02-11-12 make.probe: add CC.LD.ORIGIN for a.out origin dir relative dll search
+ make.probe: add CC.LD.STRIP for link time a.out strip
+ package.sh: fix package_use vs. PACKAGE_USE check
+02-10-24 WWW.mk: fix bug that required a :WWWBIN: assertion to post
+02-10-23 mamake.c: fix unuinitialized time in make()
+ ratz.c: fix meter buffer overflow
+02-10-20 package.sh: fix lib/probe/C/make/probe update test
+02-10-18 probe.win32: update for mingw
+ make.probe: add bash workaround to SHELLMAGIC test
+ package.sh: work around yet another cygwin hassle
+02-10-17 iffe.sh: short circuit id check for *[-+/\\]*
+02-10-08 regress.sh: unset FIGNORE to avoid rm . errors
+ package.sh: unset FIGNORE to avoid rm . errors
+ package.sh: $CC must at least compile and executable hello world
+02-10-04 package.sh: $INSTALLROOT/lib/package/tgz=>$PACKAGEROOT/lib/package/tgz
+ package.mk: $(ED) => $(STDED), $(EDFLAGS) => $(STDEDFLAGS)
+ iffe.sh: add identifier checks for tests that (implicitly) require them
+ iffe.sh: disambiguate a few --config macros
+02-10-02 iffe.sh: fix shell=bsh `hdr a/b'
+02-09-30 package.sh: handle chmod of -* files
+ package.sh: verify that $SHELL is Bourne compatible
+ package.sh: tighten PACKAGE_USE logic PATH,LIBPATH,etc. validation
+ iffe.sh: fix bug that didn't define mac variable on success
+02-09-22 package.sh: handle admin_action=ditto
+ iffe.sh: --config sizeof(foo) macro is SIZEOF_foo
+ iffe.sh: fix long.long test so it doesn't defeat uwin "typ long.long"
+ mamprobe.sh: convert $("foo") nmake string constants
+02-09-21 mamprobe.sh: "-" info-path writes probe info to stdout
+02-09-11 make.probe: move from nmake src to be part of mamprobe.sh
+ mamprobe: generate from mamprobe.beg C.probe make.probe mamprobe.end
+ mamake.c: pass cc absolute path to mamprobe
+ package.sh: generate mamprobe -- yuk (at least its confined to INIT)
+ iffe.sh: lcl,nxt: drop default sys/ check
+ ditto.sh: tw --logical by default; add --physical
+02-09-10 package.sh: SHELLMAGIC creeps into package too -- duh and fooey
+02-09-09 ditto.sh: test that remote .profile exists before sourcing
+02-09-06 package.sh: don't ditto nfs junk
+ ditto.sh: --show now lists directory ops instead of enumerating all
+02-09-05 ditto.sh: add --remote={rsh|ssh}
+ package.sh: add admin [[{rsh|ssh|-}]:]directory
+02-09-02 iffe.sh: change 'print -r --' to 'print -r -' for ksh86 compatibility
+02-09-01 cc.unix.mc68k: add for ancient 3b1
+02-08-22 package.sh: fix component() to test for components -- duh
+ Makefile: add LICENSE:.DONTCARE to workaround mam
+02-08-11 iffe.sh: provide defaults for LD_* additions
+02-08-07 ratz.c: change -m to use * instead of non-portable inverse video
+02-07-17 mamprobe.sh: close tmp file in trap before rm for cygwin
+ package.sh: fix "type" to handle i1586 (P4)
+ package.sh: add the view action
+02-06-28 package.sh: handle multiple packages for release action
+02-06-27 package.sh: catch sol*.sparc=>sol*.sun4 when CC=gcc
+02-06-14 package.sh: fix admin_action to not include qualifiers
+ package.sh: fix help/html doc typo
+02-06-11 package.sh: fix ditto update doc to `PACKAGEROOT field matching *:*'
+02-06-07 WWW.mk: change substitute $("\n") to \n
+02-06-06 package.sh: clarify output streams for help/html
+02-05-22 mamake.c: fix executable file check to use (S_IXUSR|S_IXGRP|S_IXOTH)
+02-04-04 package.sh: fix update to differentiate *.sun4 and sun4
+02-03-27 package.sh: yacc/bison warning only if both missing
+02-03-24 mamake.c: all shell actions wrapped with -c to avoid #! problems
+02-03-23 package.sh: recover $PACKAGEROOT/bin/package if not in INIT package
+ package.sh: precheck $CC, not `cc'
+ package.sh: fix install to use pax -ps to preserve set-uid/gid
+ package.sh: fix install to use list.installed for existing files only
+02-03-17 package.sh: fix PAX initialization that was sometimes omitted for read
+ package.sh: fix update delta sync fetch
+02-02-14 iffe.sh: fix macro{ }end docs to include "
+ iffe.sh: add dfn to extract #define from headers
+ iffe.sh: handle nxt #include ok but no line sync
+ iffe.sh: drop local header clash logic
+ iffe.sh: add -X, --exclude=dir to exclude -I dirs
+ iffe.sh: lcl,nxt now generate <...> headers instead of "..."
+ package.sh: admin.db root dir matching -* disables host
+ package.mk: fix package.src.pat typo -- too many )
+ package.mk: add { :COVERS: :DESCRIPTION: :REQUIRES: }
+ package.sh: handle { :COVERS: :DESCRIPTION: :REQUIRES: }
+ Makefile: move proto.c generation to the proto component dir
+02-02-02 execrate.sh: add for .exe challenged win32 systems/commands
+ mamprobe.sh: add STD* commands/flags
+ mamake.c: update mamprobe info when older than mamprobe executable
+ package.sh: move ed/ex workaround to mamprobe.sh
+ package.sh: fix `host type' bug that incorrectly assumed sun4 for sol
+ package.sh: add execrate(1) hooks for challenged systems
+ package.sh: add check for { cc ar nm yacc/bison } before make
+ ratz.c: fix "rb" vs. "r" macro tests
+ iffe.sh: add nxt, similar to lcl but defines _nxt_foo for #include
+ iffe.sh,package.sh: remove vaibale from sccs,cvs ident strings -- duh
+02-01-24 C+probe: check CC.DYNAMIC to handle cc that accept but ignore -B*
+ iffe.sh: handle 'mem struct.a.b'
+02-01-22 iffe.sh: cache (internal) `foo vs. struct foo' test results
+ package.sh: uts.370 => uts.390
+02-01-18 package.sh: fix uts hosttype
+02-01-17 package.sh: add 'results failed ...' to list failures only
+ package.sh: change ARCH internal var to all_types to avoid env conflict
+ iffe.sh: fix hdr/lib precheck that missed some -- ouch
+ iffe.sh: fix noexecute test that forgot to check compile first!
+02-01-15 ratz.c: fix path[] type typo
+02-01-01 package.mk: tighten license search
+02-01-08 package.sh: `pwd` => ${PWD:-`pwd`}
+ package.mk: expand license file pattern match
+02-01-04 iffe.sh: fix `exp name "value"' bug that duped "value"
+ iffe.sh: fix initial <sys/types.h> check to honor --config
+01-12-25 iffe.sh: fix bug where -o file restored old file
+01-12-23 package.mk: uniq the closure lists
+01-12-07 ratz.c: fix --meter to retain paths containing " -- "
+01-11-30 ratz.c: use sear_system() to execute; should work on all windows
+01-11-28 ratz.c: fix sear_rm_r() to check SetCurrentDirectory() status
+01-11-26 ditto.sh: drop n+=v for ksh compatibility
+01-11-21 ditto.sh: add rsync script replacement [hey, it works!]
+ package.sh: add [ditto]:directory notation to admin.db
+01-10-31 package.sh: handle *.sum paths with embedded space
+ package.sh: change executable() to onpath()
+ package.sh: executable([!] foo) replaces test [!] -x foo (.exe hack)
+ package.sh: add os2 fix to `host type'
+ mamake.c: add .exe hack
+ iffe.sh: fix intrinsic function lib test
+ mamprobe.sh: update pic probe to match make.probe for linux.ia64
+01-10-30 package.sh: make action skeleton view now checks subdirs
+01-10-20 package.sh: don't recurse into leaf dirs matching $MAKESKIP
+ package.mk: tarball package.notice replaces `license accepted' prompt
+ package.sh: eliminate `license accepted' prompt
+ package.sh: add update to download latest from a url
+ package.sh: use builtin arithmetic when we know its ksh
+ iffe.sh: unkown -> unknown
+01-10-18 package.sh: convert to YYYY-MM-DD delta releases instead of NNNN
+ package.mk: convert to YYYY-MM-DD delta releases instead of NNNN
+ ratz.c: fix -m for paths containing \f\n\r\v
+01-10-16 ratz.c: _SEA_* => SEAR_*
+ ratz.c: preserve stdin for sear_exec()
+ ratz.c: add recursive sear_rm_r() to sear_exec() tmp dir cleanup
+01-10-10 mamprobe.sh: add mam_cc_SHELLMAGIC
+ package.sh: add nfs wakeup call to admin to avoid stale file handles
+01-10-04 cc.darwin.ppc: -flat_namespace is not longer the default (huh)
+01-10-01 package make: prepend $INSTALLROOT/bin/ok to PATH
+ package read: save cpy of bin/package when reading the INIT package
+ mamprobe.sh: allow cc path with optional arguments
+01-09-24 Makefile,package.sh: add $INSTALLROOT/bin/.paths initialization
+01-09-19 package.mk: add recurse to list.package.*
+ package.sh: bootstrap build nmake with _BLD_STATIC for _WIN32
+01-09-11 ratz.c: add _SEA_SKIP & _SEA_COMMAND for self extracting archives
+01-09-07 package.mk: fix output capture to not generate files names with spaces
+01-09-07 package.mk: fix delta release number search
+01-08-11 package.mk: handle single gz executable packages (e.g., for ksh)
+ package.sh: fix package install to require nmake only if no *.sum
+ iffe.sh: drop ancient menu and prompt actions; check ./hdr.h clash
+01-07-17 package: fix use cross compile test to generate files in /tmp
+01-06-27 ratz: handle hard and soft links if possible
+01-06-07 Makefile: fix :MAPLIB: for sco
+01-05-31 crossexec.sh: add
+ iffe.sh: add -x crosstype to run crossexec
+ iffe.sh: exp test now handles pass{}end fail{}end yes{}end no{}end
+ package.sh: add package host canon external-host-type-name
+ package.sh: fix `use USER' lookup for shells that support ~USER
+ cc.*: add -dumpmachine to dump target HOSTTYPE
+01-05-18 iffe.sh: drop $HOME/tmp/t.sh debug trace -- oops
+01-05-01 mamake.c: scan() now handles :PACKAGE: foo:command
+01-04-26 *.sh: expand [a-z][A-Z][0-9] for non-contiguous character codes
+ iffe.sh: fix run *.sh for shells that don't $* across . command
+ cc.mvs.390: recode for /bin/sh
+01-04-25 package.mk: include non cc-g variants by default
+ package.sh: *[._]* => *?[_.]* for mvs.390 /bin/sh
+01-04-24 TEST.mk: no tests for VARIANT=="DLL"
+01-04-22 package.mk,package.sh: tarball text members are ascii encoded
+01-04-18 package.mk: allow package name to be the same as one of its components
+ cc.mvs.390: handle .C .cpp .cxx
+ cc.mvs.390: compensate for -o that does not overwrite
+01-04-01 regress: fix SAME that just skipped it -- we should regress regress!
+ iffe: fix bug that didn't emit _hdr_foo for internal hdr tests
+ iffe: fix lcl bug for cc -E that doesn't emit line syncs
+ ratz: add ascii=>ebcdic conversion for text archive members
+ mamake: fix buffer overlap bug that clobbered the probe file path
+01-03-17 iffe: handle : separator as first arg
+01-03-15 mamake.c,ratz.c,release.c: add <stdlib.h> and <string.h>
+01-02-26 iffe.sh: fix bug that omitted runtime #define for `mac' op
+01-02-22 cc.ibm.risc: handle SF_CLOSE clash in <sfio.h>
+01-02-14 cc.sgi.mips3,cc.sgi.mips4: handle -mips2 -mips3 -mips4 for cross cc
+ C+probe: quote "$cc" when its an argument!
+ mamake: execute actions with $SHELL, ignored signals back to default
+ package.sh: nmake check error output to /dev/null
+ package.sh: fix INIT a.out updates for knr cc
+ package.sh: package list now handles large tgz dirs
+ package.sh: *-ok executables moved to ok/* for *.dll systems
+ iffe.sh: change "exec >&-" to "exec >/dev/null" else linux mkdir fails!
+ mamake: handle `bind -lx [dontcare]'
+01-02-12 ratz.c: fix _PACKAGE_ast includes
+ package.sh: $HOSTTYPE env overrides if $PACKAGEROOT/arch/$HOSTTYPE/
+ package.sh: $CC ^HOSTTYPE=[A-Za-z_0-9.]*$ overrides HOSTTYPE
+ iffe.sh: fix dat code that used previous $tmp.exe
+ iffe.sh: fix dat code for _DLL imports
+01-02-09 iffe.sh: add copy() for shells with the dissappearing here doc bug
+01-02-08 Makefile: guard against null $(CC.HOSTTYPE)
+01-02-06 Makefile: separate out cc,ld,ldd workarounds (so they will be packaged)
+01-02-02 package.sh: fix package use for $INSTALLROOT != */$HOSTTYPE
+ package.sh: create intermediate recursion makefiles when needed
+ package.sh: add $SECONDS to the DEBUG trace prompt
+01-01-01 ratz.c: #ifdef for uwin ncc
+ iffe.sh,package.sh: check PACKAGE_PATH for local installations
+ package.sh: add psrinfo for osf.alpha host cpu
+ package.sh: change pax --meter probe; some hang on /dev/tty
+ package.sh: fix `install flat ARCH'
+ mamake: eliminate loops from scan order
+ C+probe: add probe_verbose -V for aix cc=xlc
+ cc.ibm.risc,ldd.ibm.risc: add
+ package.mk: list refs to top-level licenses only
+ package.mk: add local link table to change log html
+00-12-25 package.sh: `no package archives' is a hard error, duh
+ package.sh: reorder host type logic for lame shells
+ mamake.c: getcwd => getwd for NeXT -- how about posix==default guys
+ iffe.sh: really gross workaround for NeXT -lposix stdout null's
+ iffe.sh: handle cc -E that insists on compiling
+00-12-15 iffe.sh: ancient sh function call blows $*; call only when $# == 0
+ *.sh: `getopts 2>/dev/null` => `(getopts)2>/dev/null` for ancient sh
+ package.sh: fix LD_LIBRARY*_PATH initialization
+ cc.next.m68k: add for _POSIX_SOURCE and linker multiply defined syms
+00-12-12 ratz: add --meter
+ package.sh: a few VPATH fixes
+ Makefile: don't override *.mips* cc if -version not accepted
+00-12-11 package.mk: *.inx now contains name=value
+00-12-07 package.sh: handle PC netscape . => _ pathname mangle
+ WWW.mk: .tar.gz => .tgz
+00-11-27 package.sh: add checklicense() to do license checks at read time
+ package.mk: change component list from preformat to table
+00-10-31 package.mk: *.pkg must assert closure
+ package.mk: add cc- variants to list.package.binary
+ package.sh: omit dups from package list
+ package.sh: invalid arg gives one line Usage
+ package.sh: relax checkaout checks for non-owners
+ package.sh: package use sets NPROC if not already set or [01]
+ proto.c: add $(INSTALLROOT)/include/ast hack
+00-10-26 WWW.mk: add .SOURCE rhs to :WWWPAGE:
+00-10-25 package: fix install
+ package.mk: add list.install
+00-10-22 regress: fix VIEW to skip empty dirs
+00-10-19 package.mk: $(PACKAGEROOT)/bin/nmake => $(PACKAGEROOT)/bin/manmake
+ iffe: validate #define identifiers
+00-10-18 C+probe: mac os10 additions
+ package: add DYLD_LIBRARY_PATH initialization
+ add ldd.$(CC.HOSTTYPE)
+00-10-01 iffe: handle -I* -L* options
+00-09-21 mamake: add libxxx and xxx to makefile ordered prereqs
+00-09-19 C+probe: add probe_longlong
+00-09-11 package: drop manmake and $PACKAGEROOT/bin/nmake
+00-09-08 iffe: verfiy that $cc is a C compiler
+00-06-14 mamprobe: fix win32.* probe
+ mamake: fix bug that used lower view path for generation
+ package: don't clobber $PACKAGEROOT/bin/nmake
+00-06-01 C+probe: fix stdinclude *again*
+ package: fix write delta source to use default pax format
+ package: add disambiguating bias for sgi.mips3 over sgi.mips4
+ package.mk: fix for directory content packages lib ast-locale
+00-05-01 iffe: fix invalid _LIB_ macro identifier
+00-04-11 C+probe: uniq stdinclude and stdlib, fix usrinclude
+00-04-01 regress: fix explicit OUTPUT bug that didn't compare with expected
+00-03-17 package: all archives are .tgz for binary download
+ package: $(PACKAGEROOT)/LICENSES/* in source and binary archives
+ package: implement install and verify actions
+ iffe: add exp, pth file dir ..., fix lib - -lfoo, fix lib - - -la -lb
+ iffe: -L* must affect LD_LIBRARY* hacks for .exe tests -- yuk
+ package.mk: add *.pkg :INDEX:
+00-03-07 package: add admin action
+00-03-06 makefile: install optional make probe override script C+make+probe.lcl
+00-02-14 --- release 1.0 ---
+ ratz: treat "foo/" as a dir, not a regular file
+ package: clarify source and binary installation instructions
+ package: fix so binary packages can install without cc
+ package: "ratz" now a non-archive package (the only one) for bootstrap
+ package: handle VPATH=a:b arg
+ package.mk: "ratz" package adjustments
+ Makefile: use :PACKAGE_INIT: to support binary INIT packages
+ WWW.mk: add :WWWALL:
+ C.probe: fix .so check that let .dll slip through
+ iffe: fix config sh var assignment for HAVE_member_IN_struct
+ iffe: fix config sh var assignment for symbol_DECLARED
+ package: delay PATH export until dll hack exports complete
+ package: don't forget binary package $(INSTALLROOT)/lib(32|64)
+ package: add delta change log for source packages
+00-02-10 mamprobe: add mam_cc_DLLBIG
+ package: fix spelling typos
+ package: add html help output
+ package.mk: beef up source and binary help => html
+00-02-08 package: mkdir man/man[138] in the new arch to cover MAM bug
+00-01-28 package,release: add -rcount to release
+ package: fix linux "host cpu" and "host rating"
+ package: copy *.lic to $PACKAGEBIN for "make" and "write binary"
+ package: fix 'release change log' case match
+00-01-24 package: add copyright action
+ mamprobe: add -D_BLD_DLL to mam_cc_DLL
+00-01-11 package: tsort for package write
+ package: early verification that $CC works
+ package: add non-interactive command arg for use action
+ proto: fix -C intermediate mkdir()
+ mamprobe: unixware.i386 ksh workaround
+ C.probe: move hosttype to C.probe (with unixware.i386 workaround)
+ WWW.mk: fix mm2html option quoting
+ WWW.mk: add .SCAN.mm
+ WWW.mk: don't force static=1; grab dll's instead
+ *.sh: fix getopts test to handle botched implementations like osf.alpha
+ iffe.sh: fix read -r test
+99-12-25 iffe: tweak verbose messages
+ iffe: hand code non-optget getopts parse
+ iffe: fix bash quoting bug again
+ iffe: do test -w . after option parse
+ package: fix PACKAGEROOT search
+99-11-19 --- release 0.2 ---
+99-11-19 first working package & friends
+99-10-31 change from lib0ast to INIT; add MAM and package bootstrap
+ hostinfo: gobbled by package
+99-10-01 iffe: add --config, yes{...}end no{...}end, fix read -r workaround
+99-09-27 iffe: add --all --verbose, --* set options
+99-09-22 regress: -v disables long line truncation
+99-09-11 WWW.mk: WWWDIR and MM2HTMLINFO are now lists searched in $(HOME)
+99-08-11 hostinfo: fix type sgi.mips4
+99-06-24 WWW.mk: add
+99-06-08 hostinfo.sh: ${TMPDIR:-/tmp}
+99-06-07 TEST.mk: add
+99-06-01 iffe: add `siz type' for _siz_type == sizeof(type)
+99-05-11 hostinfo,iffe,regress,use: long options
+99-05-01 C.probe: fix over aggressive stdinclude, e.g., /usr/include/machine
+99-04-01 hostinfo: sgi.mips? -o32 and -n32 checks
+ iffe: check that . is writable
+99-03-17 hostinfo: fix for cc not found
+ dl.c,hello.c,m.c: headers in conditionals to force .DONTCARE
+ C.probe: extra check for include dirs pulled in by <sys/types.h>
+99-03-03 regress: add `UNIT - ...' for extra args
+ Makefile: add (_hosttype_) prereq for cc
+99-01-23 hostinfo: tweak rating, use /proc/cpuinfo if there
+99-01-11 C.probe: shlib before lib, /usr before /
+98-12-25 iffe: work around win32.alpha intrinsic clash with -O
+98-11-11 regress: fix UNIT PATH lookup
+98-11-01 regress: add PROG
+98-10-01 hostinfo: add unixware.*
+ use: export PACKAGE_*
+98-08-11 C.probe: add /usr/include check (for sco CC)
+ hostinfo: handle uwin uname update
+98-05-01 regress: fix bug sometimes didn't list last test
+98-04-01 hostinfo: add cc path arg
+ hostinfo: now works with /bin/sh
+ Makefile: strengthed -lm probe
+98-01-23 Makefile: check for -ldl -lm
+ C.probe: handle gcc -v -E phony include dirs
+ iffe: fix lcl by dropping sort -u -- we need the real first
+ iffe: `mem x' to test if x is a non-opaque struct
+98-01-11 $(INSTALLROOT)/lib32 for sgi.mips3
+ $(INSTALLROOT)/lib64 for sgi.mips4
+ add cc.hp.pa
+98-01-01 cc.sgi.mips*: turn off ld library multiply defined
+97-10-11 regress: add VIEW function for locating data
+97-10-01 Makefile: -ldl test moved to libdll Makefile
+97-08-11 regress: add MOVE
+ regress: add SAME
+ regress: use getopts
+ regress: `EXEC' repeats previous test
+97-07-17 use: tweak PATH and LIBPATH bootstrap order
+ iffe: fix lcl bug that botched pathnames with embedded spaces
+97-06-12 iffe: add npt `needs prototype' test
+97-05-09 hostinfo: mvs.* => mvs.390
+ Makefile: cc.$(_hosttype_) workaround installed here
+ iffe: fix nolink{ ... }end
+ iffe: add [no]static{ ... }end for static link test
+ C.probe: _probe_PATH => _probe_export which must be eval'd
+97-04-01 use: _RLD_ROOT set too
+97-03-17 mm2html: changed inner loop
+ mm2html: handle .if|.ie|.el, .so
+ mm2html: handle different man styles
+ mm2html: differentiate mm/man in some non-obvious cases
+ hostinfo: r5000 is not mips4
+97-02-14 hostinfo: validate type with cc
+96-12-25 C.probe: uwin tweaks
+ iffe: use `...` instead of $(...) for alpha /bin/sh
+ iffe: fix `typ' divide by 0
+ iffe: `lcl' now drops X: prefix
+ iffe: +l* -> -l*
+ iffe: eval around ${...#%...} for bsd /bin/sh
+ use: add sgi.mips LD_LIBRARY<abi>_PATH variants
+ use: add -e to list exports
+ iffe: lcl leaves leading [a-zA-Z]: for dos
+ iffe: fix no{link|output|execute} logic
+ C.probe: don't automatically add /usr/include for non-hosted compilers
+ C.probe: don't automatically place /usr/include last
+ C.probe: check gcc style -v -E for stdinclude usrinclude
+96-11-28 iffe: check BASH_VERSION for IFS botch
+ iffe: typ long.xxx only if sizeof(long xxx) != sizeof(xxx)
+ hostinfo: fix sgi.mips[234] tests
+ hostinfo: fix ncr.i386 tests
+96-10-31 iffe: work around old bsh here doc bug by running separate sh
+96-10-11 iffe: *.iffe and *.iff for iffe src files
+ hostinfo: tighten sgi.mips cpu type check
+96-10-01 C.probe: add probe_libdir to catch alpha /usr/shlib
+96-09-17 iffe: fix typ bug that failed for single id types!
+96-08-31 hostinfo: handle recent sgi hinv cpu changes
+96-07-17 make sure sizeof(long xxx)>sizeof(xxx) for typ long.xxx
+96-05-09 C.probe: drop multiple / in stdinclude
+96-02-29 use: package root must have bin and lib subdir
+ mm2html: add
+ C.probe: probe_members += -whole-archive for gcc
+ iffe: add + fix the blasted `...'...\\...'...`
+96-01-31 use: add pkg dir
+ hostinfo: add tandem
+96-01-01 hostinfo: windows_nt|windows[0-9][0-9] -> win32
+95-11-24 hostinfo: linux-aout.* for non-elf linux
+95-11-11 use: add aix LIBPATH
+95-10-11 hostinfo: no args prints type
+95-08-11 use: add
+95-05-09 save original PATH in _probe_PATH
+ beef up library dir probe
+95-04-01 use c source suffix if it still preserves the dialect
+ add hostinfo
+ add lib/hostinfo/typemap user type map
+ add sol.sun4 cpu count
+ fix C.probe to properly handle C/C++ combined compiler drivers
+ add NeXT to hostinfo
+ bummer: mach has /usr/bin/hostinfo
+95-03-19 fix dialect executable test
+95-03-19 --- release 0.0 ---
diff --git a/lib/package/INIT.html b/lib/package/INIT.html
new file mode 100644
index 0000000..42cb7cc
--- /dev/null
+++ b/lib/package/INIT.html
@@ -0,0 +1,991 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<META name="generator" content="mm2html (AT&amp;T Research) 2012-01-11">
+<META name="description" content="INIT package">
+<META name="keywords" content="software, package">
+<TITLE> INIT package </TITLE>
+<META name="author" content="gsf+dgk+kpv">
+<STYLE type="text/css">
+div.FI { padding-left:2em; text-indent:0em; }
+div.HI { padding-left:4em; text-indent:-2em; }
+dt { float:left; clear:both; }
+dd { margin-left:3em; }
+</STYLE>
+</HEAD>
+<BODY bgcolor=white link=slateblue vlink=teal >
+<TABLE border=0 align=center width=96%>
+<TBODY><TR><TD valign=top align=left>
+<!--INDEX--><!--/INDEX-->
+<P>
+<P><CENTER><FONT color=red><FONT face=courier><H3><A name="INIT package">INIT package</A></H3></FONT></FONT></CENTER>
+The INIT package is required by all but the standalone
+and self extracting archive packages. It contains
+the package command, support scripts, and utilities.
+The package command installs binary packages, makes
+source packages, and generates new package tarballs.
+Components in this package:
+<P>
+<P></P><TABLE border=0 frame=void rules=none width=100%><TBODY><TR><TD>
+<TABLE align=center bgcolor=papayawhip border=0 bordercolor=white cellpadding=2 cellspacing=2 width=99% >
+<TBODY>
+<TR><TD align=left>
+INIT</TD></TR>
+</TBODY></TABLE></TD></TR></TBODY></TABLE>
+<P>
+The software is covered by this license:
+<UL type=square>
+<LI>
+<A href="http://www.eclipse.org/org/documents/epl-v10.html">http://www.eclipse.org/org/documents/epl-v10.html</A>
+</UL>
+Individual components may be covered by separate licenses;
+refer to the component source and/or binaries for more information.
+<P>
+A recent
+<A href="#release change log">release change log</A>
+is also included.
+<P>
+<P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="release change log">release change log</A></H3></FONT></FONT></CENTER>
+<PRE>
+
+All recorded changes follow.
+
+</PRE>
+<P>
+<P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="INIT changes">INIT changes</A></H3></FONT></FONT></CENTER>
+<PRE>
+
+12-02-29 cc.darwin.i386*: handle default cc vs kernel bittedness
+12-02-29 C+probe: add __TIMESTAMP__ to the nopredefined list
+12-02-29 package.sh: don't assume grep -q or /usr/local/lib in LD_LIBRARY_PATH
+12-02-29 package.sh: fix ksh vs -lcmd compatibility checks
+12-02-23 iffe.sh: checkcc() before checkread() for sensible diagnostics
+12-02-14 package.mk: { --clobber --compare --link=lib*.a* } for --mam=static
+12-02-14 package.mk: export LICENSEFILEDEFAULT instead of LICENSEFILE
+12-02-14 package.sh: handle @(cc|ld).${HOSTTYPE}* intercepts
+12-02-07 package.sh: add { clean clobber } actions
+12-02-02 regress.sh: fix ulimit -c defaults for --nokeep
+12-01-18 regress.sh: add INPUT|OUTPUT|ERROR -e 'filter' to filter before comparison
+12-01-21 package.sh: fix `admin make' bug that created unused $INSTALLROOT/lib
+12-01-21 Makefile: :PACKAGE: license=ast -- oops
+12-01-20 cc.darwin,cc.mvs.390: tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+12-01-12 package.sh: add admin make share closure to handle alternate HOSTTYPEs
+11-12-13 iffe.sh: add /*&lt;NOSTDIO&gt;*/ test code comment to disable default #include &lt;stdio.h&gt;
+11-11-11 C+probe: test for .so before .sl
+11-10-26 package.sh: don't forget about *.pkg for admin update
+11-10-18 cc.*-icc: update and add more
+11-10-11 package.sh: handle package make|view when no source installed
+11-09-11 package.sh: count admin '*** termination code' errors
+11-08-31 mamake.c: add -e, ignore use recursive prereq timestamps
+11-08-29 iffe.sh: add ``set stdio try1.h - try2.h ...''
+11-08-29 iffe.sh: trap EXIT =&gt; trap 0 for ancient sh
+11-08-11 iffe.sh: handle ancient sort that doesn't have -k
+11-06-01 make.probe: add more /lib64 logic
+11-05-01 package.sh: fix admin ditto to sync LICENSES too
+11-03-25 package.sh: initialize { $SED $TR } before first use!
+11-03-21 package.sh: fix vpath probes
+11-03-17 iffe.sh: fix cleanup to rm $tmp* instead of $tmp*.*
+11-02-24 package.sh: change curl usage to "curl -L ..."
+11-02-11 package.sh,C+probe,make.probe,mamprobe.sh: add ###.*archiac.*###
+11-02-02 Makefile: add :MAPLIB: check for ancient -lw
+11-02-02 make.probe: handle -print-multi-directory =&gt; 64 =&gt; /usr/lib64 /lib64
+11-02-02 package.sh: HOSTTYPE=*,*cc*&#0091;,-*,...&#0093; sets CC &#0091; and CCFLAGS &#0093;
+11-02-02 make.probe: handle gcc $ORIGIN link but exec failure -- gee thanks
+11-01-25 cc.hp.ia64: bundled cc is a pile of shaving cream
+11-01-07 iffe.sh: check debug==3 for is_hdr() failure
+10-11-22 ditto.sh: fix timing problem between |&amp; and exec &amp;p
+10-11-10 package.sh: fix cc cross compile check to use checkcc absolute path
+10-10-10 package.sh: list main env vars at start of make action
+10-10-10 ratz.c: tweak widnows delays
+10-09-10 ratz.c: add _SEAR_ARGS for _SEAR_EXEC
+10-09-01 package.sh: fix ratz from source logic
+10-08-25 package.mk: consolidate license file search in .package.licenses.
+10-08-22 ratz.c: run sear bootstrap command detached
+10-08-20 C+probe: version_stamp only if version_flags works
+10-08-17 package.sh: unset makerules *DIR variables in env
+10-08-15 package.sh: "make" action now lists some env values
+10-08-11 mktest.sh: add "DO command ..."
+10-07-27 rt.sh: handle "rt X=Y ..."
+10-06-29 ratz.c: non-option sear args passed to sear_exec()
+10-06-25 iffe.sh: "api" op chanegd to not do "map-libc" type mappings
+10-06-25 package.sh: "force admin ditto" =&gt; no ditto --update option
+10-06-22 C+probe: handle cc that require .&#0091;ci&#0093; input for version info
+10-06-21 ditto.sh: change default remote access to ssh (about time)
+10-06-12 regress.sh: DISGNOSTICS &#0091; 1 | 0 | pattern &#0093; and fix EXIT for all
+10-06-09 package.sh: add AT&amp;T to usable nmake check
+10-06-06 iffe.sh,iffe.tst: add { api ver } ops
+10-04-22 package.sh: update "html binary|source" NAME/PASSWORD info
+10-04-15 iffe.sh: don't forget candidate headers for hdr|sys!
+10-04-11 WWW.mk: disable man page metarule -- now done by admin-man(1)
+10-02-14 package.sh: $CC verification needs $INSTALLROOT/bin in PATH
+10-02-11 package.sh: fix package admin make report error count
+10-02-02 package.sh: fix write binary bug that did scp on local fs
+10-02-02 package.mk: up to date binary targets must still be in PACKAGE.*.lst
+10-01-01 package.sh: fix premature $INSTALLROOT/bin during cross compile check
+10-01-01 make.probe: handle &#0091;'"&#0093; in CC.VERSION.STRING
+09-12-04 iffe.sh: add "opt name" to check for name in $PACKAGE_OPTIONS
+09-11-30 mktest.sh: change RESET to STATE.RESET to make it global
+09-11-14 make.probe: use gcc { -print-multi-directory -print-search-dirs }
+09-11-11 package.sh: re-order and combine cc checks
+09-10-27 C+probe,make.probe,probe.win32: add CC.SUFFIX.DEBUG
+09-10-21 iffe.sh,Makefile: test -e is not in ksh88!
+09-10-06 iffe.sh: handle cc -E #error with 0 exit status (sgi)
+09-10-06 package.sh: stub in ar intercept checks -- not used yet
+09-10-06 ar.ibm.risc: add ar intercept because some aix require -Xfoo first!!
+09-09-24 regress.sh: fix UMASK logic to create test support files before umask
+09-08-28 release.c: change docs to mention stdin if no file operands
+09-08-24 package.sh: fix isascii() bug that failed on od(1) trailing space
+09-08-20 make.probe: add CC.SHARED.NAME
+09-08-20 regress.sh: add { JOB CONTINUE EXITED KILL FIFO }
+09-08-11 package.sh: filter lines containing : for package results
+09-07-31 make.probe: add CC.AR.ARFLAGS (for aix ar -xany)
+09-07-31 package.sh,cc.*: fix -dumpmachine to handle 32/64/* bit options
+09-06-24 package.sh: fix admin.db output formatting
+09-05-05 package.sh: export dll hackery environment vars
+09-05-05 package.sh: handle non-identifier hostnames
+09-05-05 mamake.c: pass undefined ${...} identifiers to the shell
+09-05-05 mamake.rt: add macro expansion regression tests
+09-05-01 iffe.sh: fix output initialization *again*
+09-04-28 package.sh: handle admin.db contact field $9
+09-04-15 iffe.sh: add implicit "ini" op to initialize io for subsequent ops
+09-03-31 regress.sh: EXPORT before test =&gt; global ENVIRON&#0091;&#0093;
+09-03-26 package.sh: test fail pattern is 'fail&#0091;es&#0093;'
+09-03-26 UNIT - ... appends (options) to command line
+09-03-19 TEST.mk: x.tst =&gt; x only if x is command target
+09-03-15 regress.sh: add ${MAIN} for base name of main unit
+09-03-10 TEST.mk: add .SOURCE:tests if tests is a dir
+09-03-03 regress.sh: allow command line unit to override UNIT
+09-03-03 mktest.sh: handle IO == $'
+09-02-02 package.sh: delay $INSTALLROOT/bin/.paths generation until mamprobe runs
+09-01-30 cc.mvs.390: c89 balks at &#0091; ()&#0093; in -Dname="..."!
+09-01-27 package.sh: add isascii() to use ratz instead of tar
+09-01-20 hurl.sh: add --size=bytes option
+09-01-08 TEST.mk: add test.* prereqs, multiple arg lists with :T=*: binding
+09-01-03 regress.sh: fix UNIT to allow command line override
+09-01-03 mktest.sh: handle TWD
+08-12-24 package.sh: fix cross-compile HOSTTYPE logic
+08-12-15 package.sh,hurl.sh: handle http codes { 301 302 303 }
+08-10-16 make.probe '-fno-stack-protector -fno-stack-protector-all' to cop out!!
+08-09-30 rt.sh: fix ksh93 regression test signal count
+08-09-26 regress.sh: ignore SIGPIPE for SET pipe-input
+08-09-24 package.sh: package only test foo =&gt; make --recurse=only recurse tests foo
+08-09-20 make.probe: handle another /usr/bin/file shared lib description
+08-09-20 regress.sh: add --pipefail for SET pipe-input ...
+08-09-17 Makefile: add gdbm1.c for &lt;gdbm-ndbm.h&gt;
+08-09-10 make.probe: add CC.NOPROTECT
+08-08-08 mktest.sh: add --width=width
+08-08-05 dbm.req: favor sleepycat ndbm compatibility
+08-08-04 C+probe: fix stdlib initialization logic
+08-06-24 package.sh: fix $INSTALLROOT/bin/cc intercept time stamp file typo
+08-06-20 TEST.mk: make the localyunit before *.rt =&gt; *.tst -- doh
+08-06-20 mktest.sh: prepend $PWD onto PATH for local units -- doh^2
+08-06-11 regress.sh: fix bug that skipped the last test
+08-05-20 regress.sh: add --local to put *.tmp dir in local fs
+08-05-05 regress.sh: add IF command ... ELIF command ... ELSE ... FI
+08-05-01 package.sh: package test =&gt; ulimit -c 0
+08-04-28 regress.sh: fix EXPORT quoting
+08-04-28 regress.sh: fix UNIT set check args too
+08-04-24 rt.sh: exit code &gt; 256 =&gt; signal termination
+08-04-10 C+probe: change probe_so order to check .so last (macos ld workaround)
+08-04-01 package.sh: handle multiple admin HOSTTYPEs per HOST
+08-03-28 C+probe: add C++ #include &lt;iostream&gt; (no extension) dir probes
+08-03-17 regress.sh: fix trap on EXIT, add terminated note to final tally
+08-02-28 make.probe: fix probe_warn to include ld!
+08-02-02 make.probe: add CC.RUNPATH to match default -L order
+08-01-31 package.sh: check lib64 for LD_LIBRARY_PATH
+08-01-31 iffe.sh: tweak ancient /bin/sh workarounds
+08-01-28 make.probe: darwin ld export dynamic is -force_flat_namespace
+08-01-28 C+probe: handle sgi cc error message but exit 0 botch(es)
+08-01-23 package.sh: fix checksum doc typo
+08-01-09 C+probe: add __FUNCTION__ to the undef (don't check) list
+07-12-14 iffe.sh: add set nooptimize
+07-12-03 package.sh: add LC_ALL=C
+07-11-27 package.sh: fix overaggressive *.md5 cleanup
+07-11-20 iffe.sh: treat exit status &gt;= 250 as normal error with no signal
+07-11-05 package.sh: fix write op error count pattern
+07-11-05 package.mk: fix $(~req) .ver binding
+07-08-11 probe.win32: add cl.exe setuid workaround, CC.VERSION&#0091;.STRING&#0093;
+07-08-01 package.sh: handle 'package read lcl|tgz'
+07-05-08 regress.sh: execute basename instead of absolute path for short $0
+07-04-27 cc.sgi.mips&#0091;34&#0093;: for #error to exit non-zero -- a no brainer
+07-04-20 mktest.sh: defer to systems without 'grep -q' -- sigh
+07-04-11 mamprobe.sh: handle $(CC.*) =&gt; ${mam_cc_*}, $(...) =&gt; ${...}
+07-04-11 make.probe: fix CC.PICBIG probe, default { CC.PIC CC.DLL } to BIG
+07-04-04 iffe.sh: prepend ${tst}${ext} to each .c probe
+07-03-28 package.sh: fix binary tgz architecture type duplication
+07-03-28 package.mk: add binary write PACKAGE.$HOSTTYPE.lst
+07-03-28 iffe.sh: add -F header to mac test
+07-03-23 make.probe: handle file(1) that returns 'archive' for .so
+07-03-22 mamprobe.sh: fix STDED probe for implementations that ignore EOF
+07-03-11 package.sh: add nocopyright and tst =&gt; nocopyright
+07-03-11 package.mk: add copyright=0
+07-03-08 C+probe: restore IFS after probe.ini
+07-02-26 mamake.c: expand first of ${mam_lib*} for ${AR}
+07-01-05 package.sh: fix "admin write binary" logic
+07-01-01 iffe.sh: add "cmd" --verbose trace
+07-01-01 iffe.sh: sort =&gt; LC_ALL=C sort
+07-01-01 C+probe: LC_ALL=C
+06-12-22 make.probe: lean on gcc -v for stdlib, but preserve /usr/local!
+06-11-23 package.sh: *.md5 are not tarballs -- doh
+06-11-23 iffe.sh: add -F, --features=feature-test-header
+06-11-11 make.probe: favor lib64 over lib for hosttype==*64
+06-10-31 make.probe: add "-ignore-source-dir -iquote" test
+06-10-31 iffe.sh: add status{...} code block
+06-10-11 regress.sh: fix DO to handle {...} (time for regress.tst?)
+06-10-11 package.sh: handle already gunzip'd *.tgz
+06-10-06 iffe.sh: add reference for header content tests
+06-09-27 regress.sh: fix UMASK to do DO too (duh)
+06-09-22 iffe.sh: drop -O for npt tests (for msvc intrinsics)
+06-09-14 cc.darwin: drop -O until gcc 4.* gets its act together
+06-09-11 package.sh: { cc ld ldd } intercepts check ${HOSTTYPE%.*} too
+06-09-08 regress.sh: add PIPE INPUT|OUTPUT for pipe io
+06-09-05 C+probe: add { probe_version version_stamp version_string }
+06-09-05 make.probe: add version stamp comment, CC.VERSION&#0091;.STRING&#0093;
+06-08-27 regress.sh,mktest.sh: add UMASK
+06-08-25 regress.sh: add -b,--ignore-space,IGNORESPACE
+06-08-25 mktest.sh: add IGNORESPACE
+06-08-24 mktest.sh: handle &nbsp;00 in data
+06-08-24 regress.sh: handle -f* for INPUT|OUTPUT|ERROR
+06-08-16 package.sh: fix 'install flat' logic
+06-08-11 rt.sh: handle style=shell %K date format
+06-07-17 ratz.c: fix __MVS__ FAR definition
+06-07-17 iffe.sh: "header x.h" -- deprecate "include x.h" for .SCAN.iffe
+06-07-17 package.sh: differentiate urls vs. assignments
+06-06-27 rt.sh: add --failed, --heading
+06-06-27 C+probe,TEST.mk,make.probe,mktest.sh,regress.sh: 'ulimit -c 0'
+06-06-26 cc.darwin.ppc: handle -lcc_dynamic disappearance
+06-06-25 mktest.sh: implement PROG
+06-06-11 Makefile: add -ldbm :MAPLIB:, provide public MAPLIB.mk
+06-05-06 package.sh: add PACKAGE_admin_tail_timeout
+06-05-22 ratz.c: upgrade to zlib-1.2.3
+06-05-09 package.sh: fix admin.db docs
+06-03-11 package.sh: fix `package use - command ...'
+06-03-05 make.probe: work around pedantic bash 3.1 mismatched " in `.`
+06-02-14 package.sh: "results failed test" == "results test failed"
+ cc.sgi.*: add _AST_cc_OPTIONS parameterization, -OPT:Olimit=0
+ cc.linux.ia64-icc: add for intel cc
+06-02-02 package.sh: freebsd stuck with os version for all arch
+06-02-01 package.mk: fix locale logic (tw -d requires dir arg)
+06-01-31 package.sh: require $CC only for make|test
+06-01-30 package.sh,hurl.sh: use the backwards-compatible --http-passwd
+ package.sh: add more pdksh =&gt; /bin/sh checks
+06-01-26 package.sh: wget --http-pass =&gt; --http-password
+ package.sh: fix wget error logic
+ hurl.sh: wget --http-pass =&gt; --http-password
+06-01-11 package.mk: pass package.license.class to make --mam too
+ package.mk: variants=pattern =&gt; --variants=pattern
+ package.sh: darwin rel&lt;=7 =&gt; darwin7.ppc
+ package.sh: freebsd rel&lt;=4 =&gt; freebsd4
+ package.sh: freebsd rel&lt;=5 =&gt; freebsd5
+05-12-07 iffe.sh: don't emit &lt;stdio.h&gt; if &lt;sfio.h&gt;|&lt;ast.h&gt; (XXX)
+05-12-05 make.probe: disable readonly.exe core dump via ulimit -c 0
+05-09-22 mktest.sh: add EXEC &#0091; ++NOOUTPUT ++NOERROR ++NOEXIT &#0093;
+05-09-21 mktest.sh: fix --style=shell compare to ignore \r
+05-09-12 TEST.mk: all --force to force %.rt regeneration
+05-09-05 TEST.mk: regenerate from %.rt only if newer, :SAVE: %.tst
+05-08-25 mktest.sh: add
+ TEST.mk: add %.rt=&gt;%.tst for mktest
+05-08-18 package.sh: 'package host cpu' now checks $NPROC first
+05-07-17 iffe.sh: add { define extern include print } ops
+ iffe.sh: accept output{...}end output on success only -- doh
+05-07-01 package.sh: add TARPROBE for tar B flag probe
+05-06-24 package.sh: fix binary read chmod via *.sum
+05-06-06 package.sh: fix KEEP_HOSTTYPE logic to handle synthesized types
+05-06-01 make.probe: verify that cc_pic works for hosted cc
+ cc.lynxos.ppc: make -mshared the default
+ package.sh: note $INSTALLROOT/bin/@(cc|ld|ldd) installation
+05-05-25 make.probe: add CC.INCLUDE.LOCAL instead of -I- in CC.DIALECT
+05-05-24 iffe.sh: really fix grouping logic -- with tests this time
+ package.sh: pipe/socket configuration mismatches =&gt; use /bin/sh
+05-04-28 TEST.mk: add $(TESTS)
+05-04-19 package.sh: package results test uses rt if possible
+ iffe.sh: fix 'op var - ... - ...' grouping logic
+05-04-15 rt.sh: handle autom4ate style
+05-04-11 regress.sh: fix unit name when command line unit also specified
+ rt.sh: handle all ast package test output formats
+ package.sh: fix make docs for options passed to underlying make
+05-04-08 package.sh: cp -p makerules.mo to $OK to preserve mtime
+ regress.sh: add "TITLE name" to change TEST output title
+05-04-01 rt.sh: add pretty make test + regress.sh wrapper
+05-03-29 package.sh: test -e path =&gt; test -f path -o -d path
+05-03-24 make.probe: fix CC.PICBIG probe to prefer -fPIC over -fpic -- doh
+05-03-19 mamake.c: command line name=var also defines name.FORCE=var
+05-03-11 regress.sh: unset LC_ALL when LC_* EXPORT'd
+ package.sh: old make.out saved in circular make.out.&#0091;1-9&#0093;
+ mamake.c: sync with nmake :W=O:
+05-03-01 package.sh: fix flat hierarchy initialization
+ package.sh: admin action now properly resets sibling remote logs
+ package.mk: relax unknown/unwritten package messages to warnings
+ package.sh: handle space in command line name=value
+ make.probe: add mvs -Wc,dll,exportall,longname,rent to CC.DLL probe
+05-02-24 package.sh: hosttype *.powerpc =&gt; *.ppc
+ cc.lynxos.ppc,ldd.lynxos.ppc: add
+05-02-22 mamake.c: fix { -G --debug-symbols -S --strip-symbols } MAMAKEFLAGS bug
+05-02-20 probe.win32: handle /platformsdk mount
+05-02-19 package.sh,package.mk: add write tst for tgz in tst subdir
+05-02-18 package.sh: accept cc -dumpmachine with 0 or 1 -
+05-02-14 package.sh: handle mutiple architectures per host in admin.db
+ Makefile,package.sh: honor $INSTALLROOT/bin/.paths overrides
+ package.sh: normalize trailing &#0091;-_&#0093;bits in host type
+ iffe.sh: some ksh-compatible shells don't do *(pattern)
+05-02-11 iffe.sh: back out 05-01-11 child process stdin hijack
+ cc.lynxos.i386: -dynamic instead of -static default
+05-02-10 package.sh: cyg usr/doc =&gt; usr/share/doc
+05-02-08 package.sh: drop -m with pax -- delta bug fixed 2005-02-08
+ iffe.sh: work around old bash 0&lt;... redirection bug
+05-02-06 package.mk: source.tgz: update generated files only when they change
+05-02-02 *.sh,*probe: IFS may be unset and { ash bsh } don't on startup -- wow
+05-01-11 package.sh: update setup docs to include authorize+password
+ package.mk: fix .source.cyg final directory edit
+ package.mk: notice=1 for conspicuous empty NOTICE file
+ WWW.mk: fix *-index.html installation
+ filter.sh: retain input file suffix in tmp copy
+ mamexec.c: fix non-contiguous "exec" bug that skipped lines
+ iffe.sh: fix candidate lib test to try grouping subsequent libs
+ iffe.sh: fix child process stdin hijack that skipped input lines
+ iffe.sh: --shell=osh to force read -r compatibility command
+ iffe.sh: chop iffe input leading space before # for KnR compatibility
+05-01-05 package.sh: add ${TAR} ${TARFLAGS} and tar B flag for pipes
+ mamake.c: fix makefile scan to ignore lib*.&#0091;hH&#0093;
+ iffe.sh: immunize function/symbol tests from aggressive -O
+04-12-28 WWW.mk: add :WWWPAGE: faq.*.mm index generator
+04-12-21 ratz.c: make sure tmp dir is writable -- doh
+04-12-08 iffe.sh: fix dat test for aggressive -O
+04-12-01 iffe.sh: add `include file' to pull in #define's for `exp'
+04-11-11 package.sh: default MAKESKIP is "*&#0091;-.&#0093;*"
+04-10-22 ratz.c: change docs to note zlib license
+ mamake.c: handle --debug-symbols and --strip-symbols
+ package.sh: make (debug|strip)=1 =&gt; --(debug|strip)-symbols
+ package.mk: add :LICENSE: =&gt; package.license.class
+ mamake.c: fix recursive order logic
+04-10-18 package.mk: add :LICENSE:, :OMIT: to omit package subdirs
+04-10-11 package.sh: add 'authorize name' and 'password password'
+04-10-01 iffe.sh: double check $static link with ! $static
+ Makefile: add BUILTIN_LIB to $INSTALLROOT/bin/.paths
+ make.probe: add CC.DIALECT EXPORT={ALL,REF,EXT,DLL}
+ package.sh: add BUILTIN_LIB to $INSTALLROOT/bin/.paths
+04-09-21 package.mk: $(init)$(name) is now an implicit prereq
+04-09-09 package.sh: copy makerules.mo to $INSTALLROOT/bin/ok
+04-09-01 package.mk,package.sh: rename *.txt =&gt; *.README
+ package.mk: add the runtime package type (no *.&#0091;ah&#0093;)
+ iffe.sh: fix key test reports
+04-08-26 Makefile: { add m2.c m3.c } -lm tests for { frexp&#0091;l&#0093; ldexp&#0091;l&#0093; }
+04-08-11 package.mk: handle HOSTTYPE for solaris &gt; 9
+ package.sh: add `checkaout proto' for { make view }
+ package.sh: check for { md5sum md5 }
+ iffe.sh: add {if|elif|else|endif} test ...
+ iffe.sh: add 'exp - expression' and '( expression )'
+ iffe.sh: add 'name = test ...' user defined macros
+ iffe.sh: add '! test ...' negation
+ TEST.mk: add implied { .c .sh } generated prereq
+ cc.darwin.ppc: handle 10.3 -dylib mess
+04-08-01 package.mk: let include handle nested requirements -- duh
+04-07-31 package.sh: attempt a second ping before admin assumes host down
+04-07-26 package.sh: fix hp.ia64 HOSTTYPE
+04-07-23 probe.win32: generalize #include dir order search
+04-07-17 regress.sh: add INPUT -x for chmod +x
+04-07-01 regress.sh: TMP =&gt; TWD
+04-06-29 regress.sh: put COMMAND in $TWD too
+04-06-21 regress.sh: mkdir -p INPUT and OUTPUT intermediate dirs
+ TEST.mk: add :TEST: -- to disable .c .sh search
+04-06-18 TEST.mk: add .SCAN.tst
+04-06-17 regress.sh: TEST returns true if active, false otherwise
+ regress.sh: add CD to change test pwd from $TWD
+04-06-16 regress.sh: add TWD for ./unit.tmp override
+ regress.sh: DO now flushes previous test
+ regress.sh: INPUT and OUTPUT handle -f for printf instead of print
+04-06-11 package.sh: make sure $INSTALLROOT/bin is in front of $PATH
+ package.sh: skip nmake if older than 2000-10-31
+04-05-20 package.sh: fix arg vs. package parse with - or '' to disambuguate
+04-05-11 package.sh: package verbose update lists closure for package setup
+ package.sh: add src/lib/libardir to nmake proto bootstrap
+ regress.sh: probe for rm -u vs. chmod -R u+rwx
+04-05-01 package.sh: $CC must be C, not C++; allow release command on $PATH
+04-04-15 make.probe: check probe_libdir false positives
+ package.sh: add lib/package/*.lic src package subdirs
+ package.mk: add mamfile=0 to inhibit Mamfile generation
+ iffe.sh: config name_DECLARED =&gt; HAVE_name_DECL
+ iffe.sh: fix mac to handle default value
+04-04-11 iffe.sh: normalize sed &#0091;\\\\/&#0093; quoting
+04-04-04 package.mk: only checksum generated tarballs
+ mamprobe.sh: add STDCHMOD
+04-04-01 C+probe: set export LANG=C for uniform error messages
+ make.probe: another CC.STDLIB tweak
+ package.sh: fix regress core dump pattern, expand &#0091;a-z&#0093; match ranges
+04-03-31 Makefile: add intl :MAPLIB: test
+ make.probe: fix CC.STDLIB search; drop CC.* path duplicates
+04-03-28 iffe.sh: drop unused exec $stdin&lt;&amp;0 dup
+04-03-25 Makefile: add iconv :MAPLIB:
+ package.sh: use ${PING:-ping -c 1 -w 4}, allowing admin.db override
+04-03-24 package.mk: add *.md5 checksum for each *.(c|exe|tgz)
+ package.sh: update base change on md5 sum instead of size
+ iffe.sh: adjust case label &nbsp;and keyword quoting for ancient /bin/sh
+04-03-22 probe.win32: ncc =&gt; nld
+04-03-19 CONVERT.mk: change the instructions and old source dir default
+ package.mk: fix recurse=list check
+ package.mk: add *.md5 checksum for each *.(c|exe|tgz)
+ package.sh: fix update base/delta/sync existence check
+04-03-18 iffe.sh: -d2 does not remove core dumps on exit
+04-03-17 package.sh: fix make recurse arg/action order
+04-02-29 package.sh: add regress action to compare current and previous tests
+ package.sh: fix sgi.mips&#0091;23&#0093; HOSTTYPE test for old irix cc
+ package.sh: add `export variable ...'
+ package.sh: admin action now handles host name with non-id chars
+ package.sh: non-numeric M T W in admin.db disables that action
+ package.sh: fix admin write binary local vs. shared clash
+ cc.hp.pa: add _AST_CC_hp_pa_DEFAULT=+DAportable
+ cc.hp.pa64: sync with cc.hp.pa
+ cc.ibm.risc: -bnolibpath =&gt; -blibpath:/usr/lib:/lib
+ probe.win32: sync with make.probe
+ make.probe: fix last chance dynamic test
+ make.probe: add hp.pa CC.EXPORT.DYNAMIC -Wl,-E
+ make.probe: add ibm.risc CC.EXPORT.DYNAMIC -bexpall
+ make.probe: move probe_dll_def to the end of probe_dll
+ package.mk: capture subcomponent mamfile recursion
+04-02-24 make.probe: strip "..." from cc/ld traces
+ iffe.sh: add ``set &#0091;no&#0093;define'' to disable macro #define/#undef
+04-02-23 make.probe: rework CC.LD search
+04-02-14 make.probe: add CC.EXPORT.DYNAMIC for main dynamic sym export
+ make.probe: resurrect CC.PIC with separate semantics from CC.DLL
+ make.probe: add CC.SHARED.LD for CC.SHARED linker
+ C+probe: clear DISPLAY to stifle interactive windows
+04-02-11 iffe.sh: handle ``siz void*'', add cross{ ... }end
+ make.probe: add { CC.AR CC.SIZE }, fix cross command search
+ cc.darwin.ppc: change $cc =&gt; $CC for old ksh + libast conf bug
+04-02-09 make.probe: drop -nostartfiles from CC.SHARED for C++
+04-02-04 package.sh: fix cross compilation bug that mixed binary formats
+04-02-02 package.sh: package admin now ditto's bin/package too
+04-01-30 cc.sgi.mips3: drop warning 3421
+04-01-11 regress.sh: output label#count for tests in loops
+04-01-05 regress.sh: fix bug that ignored the first SAME
+04-01-04 crossexec.sh: fix typo that did not recognize rcp
+03-12-19 mamake.c: add `foolib:foo:libfoo' to recurse()
+03-10-11 regress.sh: add EXPORT, export COLUMNS=80 for message consistency
+03-09-23 ratz.c: fix tar header number parse bug that skipped to next number
+ regress.sh: rm cleanup now handles files matching -*
+03-09-11 iffe.sh: add unnamed { ... } blocks
+ regress.sh: add COPY from to, like MOVE but comprison still done
+ regress.sh: rm -rfu to handle test dirs w/o u+rwx
+03-08-14 Makfile: add hello.c to the manifest
+03-08-11 package.sh: fix `html binary' generation
+03-06-21 package.sh: fix INITROOT initialization bug
+ package.sh: make sure admin logs exists before tail'ing
+03-06-11 probe.win32: fix $(BINDIR) typo that expanded in sh instead of make
+ cc.mvs.390: return code 4 yields exit code 3 but its *really* ok
+ package.sh: fix onpath function global var conflict
+ make.probe: add CC.DIALECT { GNU -dD }
+ package.mk: add Mamfile to lcl manifest
+03-06-10 package.sh: fix setup action typo that only checked the INIT package
+ package.sh: *.s390x =&gt; *.s390-64
+03-06-09 package.mk: add cyg :POSTINSTALL:
+03-06-08 make.probe: fix CC.STDLIB logic
+ hurl.sh: add User-Agent identification
+ package.sh: tweak source and binary installation instructions
+ cc.hp.pa,ld.hp.pa: +-Wl,+cdp,${INSTALLROOT}/lib/: drops abs lib paths
+ ldd.hp.pa: add
+03-06-06 package.sh: fix $INSTALLROOT/bin/ldd check
+ make.probe: add CC.STDLIB verification
+03-06-04 make.probe: add +forceread +noforceread
+03-05-11 hurl.sh: handle http://host:port/path
+03-05-06 package.sh: fix setup action PACKAGEROOT and INIT logic
+03-05-05 package.mk: fix cygwin tarball names
+03-04-30 package.sh: move (cc|ld|ldd).$HOSTTYPE updates from Makefile
+03-04-27 make.probe: fix mvs CC.PREFIX.SHARED "lib" =&gt; ""
+ make.probe: add CC.DLL.DIR = $(BINDIR) or $(LIBDIR)
+ make.probe: add { CC.LD.LAZY CC.LD.NOLAZY CC.LD.RECORD CC.LD.NORECORD }
+ probe.win32: sync with latest CC.*
+03-04-25 mamprobe.sh: add args to `. $makeprobe' for ancient sh
+03-04-23 package.mk: fix dup "covered by" licenses
+03-04-22 probe.win32: CC.DIALECT += "LIBPP -I-" for all cc's
+ package.sh: fix admin write binary tarball snarf
+03-04-21 package.mk: package covered *.@(pkg|lic) too
+03-04-15 package.mk: don't generate incremental archives for lcl
+ package.mk: add incremental=&#0091;source:1 binary:0&#0093; archive control
+ package.sh: generate $INSTALLROOT/bin/cc wrapper for CC != cc
+ package.sh: admin must ditto lib/package/*.@(pkg|lic) too
+ mamake.c: ignore time of ignore prereqs
+ mamake.c: -D2 lists propagated times
+03-04-11 package.mk: tidy up cyg tarballs
+ package.sh: fix old shell clash between get() and $get
+03-04-05 package.mk: restore *.inx generation somehow lost during cyg additions
+ package.sh: add pthread_num_processors_np() last resort for cpu count
+ package.sh: use `make believe' to accept mamake generated files
+ package.sh: handle `make &#0091;make-flags&#0093; &#0091;target ...&#0093;'
+ mamake.c: ignore -e
+03-03-21 package.mk: fix cyg old make typo
+ package.sh: switch to `package setup' instructions
+03-03-19 package.sh: add registry checks for `host cpu'
+ package.sh: `results failed' now lists core dump messages
+03-03-17 package.sh: on cygwin verify 'ntsec binmode' in $CYGWIN or die
+ Makefile: install gcc wrapper if no cc
+ package.mk: add :DETAILS: { :README: :EXPORT: :INSTALL: :TEST: } ops
+03-03-12 package.mk: add :DETAILS: for style-specific details
+03-03-11 package.sh: add beta setup/update support
+ TEST.mk: add (TESTCC) prereq for .sh tests
+03-03-07 hurl.sh: add
+03-03-06 iffe.sh: fix lib win32 test cygwin vs native incompatibility
+ iffe.sh: change internal stdio.h guard to handle C++ inline vs. macro
+03-03-03 package.sh: check for curl or wget for update
+ package.sh: add setup action == update read make
+ package.sh: fix packageroot() typo that showed up in non ~user shells
+ mamake.c: treat name+=value args like name=value
+ mamake.c: add ${var?*|value?match?no-match?}
+ mamake.c: fix archive vs. dynamic bind logic
+03-02-28 package.sh: add the "cyg" (cygwin) package type
+ package.mk: add "cyg" stubs, :CATEGORY: for category name(s)
+03-02-25 mamake.c: add -D4 system(3) debug trace
+03-02-24 package.mk: change --mismatch to --corrupt=accept
+03-02-14 ratz.c: add _WIN32 setmode(&#0091;01&#0093;,O_BINARY) and fopen "rb"/"wb"
+03-02-12 Makefile: handle getconf LIBPATH with host pattern
+03-01-31 package.mk: fix .lic search
+03-01-30 package.sh: handle { INIT ksh nmake } already installed elsewhere
+ package.sh: admin handles command outside of $PACKAGEROOT/bin
+ Makefile: install $(INSTALLROOT)/lib/make/package.mk
+03-01-28 package.sh: admin remote commands on one line to please syslog
+03-01-23 probe.win32: borland and mingw32 tweaks
+03-01-22 package.sh: fix $CC test to ignore set -x trace -- duh
+03-01-16 ditto.sh: tw --chop on by default
+03-01-14 package.sh: use /bin/cp to copy previous binaries to bin/ok/
+ package.sh: admin now initiates remote exec and copy from local host
+03-01-12 package.sh: handle admin "xxx:" default root
+03-01-03 probe.win32: add /usr/include/borland path truncation workaround
+02-12-10 iffe.sh: add &lt;&amp;$nullin &gt;&amp;$nullout to checkread() $cc
+02-12-06 probe.win32: fix inlcude =&gt; include typo, add lcc lib
+ probe.win32: CC.MAKE.OPTIONS = nativepp=0
+02-12-04 mamake.c: fix ${foo-bar} to expand foo if defined
+02-11-28 probe.win32: add C++ and -I- CC.DIALECT checks
+02-11-26 package.sh: package release now checks for second level files
+02-11-22 package.sh: update action now uses HTTP/1.0
+02-11-21 probe.win32: update the vc include dir test
+02-11-20 make.probe: fix CC.LD.ORIGIN typo that expanded make var
+02-11-13 packahe.mk: fix list.install =&gt; list.installed typo
+02-11-12 make.probe: add CC.LD.ORIGIN for a.out origin dir relative dll search
+ make.probe: add CC.LD.STRIP for link time a.out strip
+ package.sh: fix package_use vs. PACKAGE_USE check
+02-10-24 WWW.mk: fix bug that required a :WWWBIN: assertion to post
+02-10-23 mamake.c: fix unuinitialized time in make()
+ ratz.c: fix meter buffer overflow
+02-10-20 package.sh: fix lib/probe/C/make/probe update test
+02-10-18 probe.win32: update for mingw
+ make.probe: add bash workaround to SHELLMAGIC test
+ package.sh: work around yet another cygwin hassle
+02-10-17 iffe.sh: short circuit id check for *&#0091;-+/\\&#0093;*
+02-10-08 regress.sh: unset FIGNORE to avoid rm . errors
+ package.sh: unset FIGNORE to avoid rm . errors
+ package.sh: $CC must at least compile and executable hello world
+02-10-04 package.sh: $INSTALLROOT/lib/package/tgz=&gt;$PACKAGEROOT/lib/package/tgz
+ package.mk: $(ED) =&gt; $(STDED), $(EDFLAGS) =&gt; $(STDEDFLAGS)
+ iffe.sh: add identifier checks for tests that (implicitly) require them
+ iffe.sh: disambiguate a few --config macros
+02-10-02 iffe.sh: fix shell=bsh `hdr a/b'
+02-09-30 package.sh: handle chmod of -* files
+ package.sh: verify that $SHELL is Bourne compatible
+ package.sh: tighten PACKAGE_USE logic PATH,LIBPATH,etc. validation
+ iffe.sh: fix bug that didn't define mac variable on success
+02-09-22 package.sh: handle admin_action=ditto
+ iffe.sh: --config sizeof(foo) macro is SIZEOF_foo
+ iffe.sh: fix long.long test so it doesn't defeat uwin "typ long.long"
+ mamprobe.sh: convert $("foo") nmake string constants
+02-09-21 mamprobe.sh: "-" info-path writes probe info to stdout
+02-09-11 make.probe: move from nmake src to be part of mamprobe.sh
+ mamprobe: generate from mamprobe.beg C.probe make.probe mamprobe.end
+ mamake.c: pass cc absolute path to mamprobe
+ package.sh: generate mamprobe -- yuk (at least its confined to INIT)
+ iffe.sh: lcl,nxt: drop default sys/ check
+ ditto.sh: tw --logical by default; add --physical
+02-09-10 package.sh: SHELLMAGIC creeps into package too -- duh and fooey
+02-09-09 ditto.sh: test that remote .profile exists before sourcing
+02-09-06 package.sh: don't ditto nfs junk
+ ditto.sh: --show now lists directory ops instead of enumerating all
+02-09-05 ditto.sh: add --remote={rsh|ssh}
+ package.sh: add admin &#0091;&#0091;{rsh|ssh|-}&#0093;:&#0093;directory
+02-09-02 iffe.sh: change 'print -r --' to 'print -r -' for ksh86 compatibility
+02-09-01 cc.unix.mc68k: add for ancient 3b1
+02-08-22 package.sh: fix component() to test for components -- duh
+ Makefile: add LICENSE:.DONTCARE to workaround mam
+02-08-11 iffe.sh: provide defaults for LD_* additions
+02-08-07 ratz.c: change -m to use * instead of non-portable inverse video
+02-07-17 mamprobe.sh: close tmp file in trap before rm for cygwin
+ package.sh: fix "type" to handle i1586 (P4)
+ package.sh: add the view action
+02-06-28 package.sh: handle multiple packages for release action
+02-06-27 package.sh: catch sol*.sparc=&gt;sol*.sun4 when CC=gcc
+02-06-14 package.sh: fix admin_action to not include qualifiers
+ package.sh: fix help/html doc typo
+02-06-11 package.sh: fix ditto update doc to `PACKAGEROOT field matching *:*'
+02-06-07 WWW.mk: change substitute $(") to
+02-06-06 package.sh: clarify output streams for help/html
+02-05-22 mamake.c: fix executable file check to use (S_IXUSR|S_IXGRP|S_IXOTH)
+02-04-04 package.sh: fix update to differentiate *.sun4 and sun4
+02-03-27 package.sh: yacc/bison warning only if both missing
+02-03-24 mamake.c: all shell actions wrapped with -c to avoid #! problems
+02-03-23 package.sh: recover $PACKAGEROOT/bin/package if not in INIT package
+ package.sh: precheck $CC, not `cc'
+ package.sh: fix install to use pax -ps to preserve set-uid/gid
+ package.sh: fix install to use list.installed for existing files only
+02-03-17 package.sh: fix PAX initialization that was sometimes omitted for read
+ package.sh: fix update delta sync fetch
+02-02-14 iffe.sh: fix macro{ }end docs to include "
+ iffe.sh: add dfn to extract #define from headers
+ iffe.sh: handle nxt #include ok but no line sync
+ iffe.sh: drop local header clash logic
+ iffe.sh: add -X, --exclude=dir to exclude -I dirs
+ iffe.sh: lcl,nxt now generate &lt;...&gt; headers instead of "..."
+ package.sh: admin.db root dir matching -* disables host
+ package.mk: fix package.src.pat typo -- too many )
+ package.mk: add { :COVERS: :DESCRIPTION: :REQUIRES: }
+ package.sh: handle { :COVERS: :DESCRIPTION: :REQUIRES: }
+ Makefile: move proto.c generation to the proto component dir
+02-02-02 execrate.sh: add for .exe challenged win32 systems/commands
+ mamprobe.sh: add STD* commands/flags
+ mamake.c: update mamprobe info when older than mamprobe executable
+ package.sh: move ed/ex workaround to mamprobe.sh
+ package.sh: fix `host type' bug that incorrectly assumed sun4 for sol
+ package.sh: add execrate(1) hooks for challenged systems
+ package.sh: add check for { cc ar nm yacc/bison } before make
+ ratz.c: fix "rb" vs. "r" macro tests
+ iffe.sh: add nxt, similar to lcl but defines _nxt_foo for #include
+ iffe.sh,package.sh: remove vaibale from sccs,cvs ident strings -- duh
+02-01-24 C+probe: check CC.DYNAMIC to handle cc that accept but ignore -B*
+ iffe.sh: handle 'mem struct.a.b'
+02-01-22 iffe.sh: cache (internal) `foo vs. struct foo' test results
+ package.sh: uts.370 =&gt; uts.390
+02-01-18 package.sh: fix uts hosttype
+02-01-17 package.sh: add 'results failed ...' to list failures only
+ package.sh: change ARCH internal var to all_types to avoid env conflict
+ iffe.sh: fix hdr/lib precheck that missed some -- ouch
+ iffe.sh: fix noexecute test that forgot to check compile first!
+02-01-15 ratz.c: fix path&#0091;&#0093; type typo
+02-01-01 package.mk: tighten license search
+02-01-08 package.sh: `pwd` =&gt; ${PWD:-`pwd`}
+ package.mk: expand license file pattern match
+02-01-04 iffe.sh: fix `exp name "value"' bug that duped "value"
+ iffe.sh: fix initial &lt;sys/types.h&gt; check to honor --config
+01-12-25 iffe.sh: fix bug where -o file restored old file
+01-12-23 package.mk: uniq the closure lists
+01-12-07 ratz.c: fix --meter to retain paths containing " -- "
+01-11-30 ratz.c: use sear_system() to execute; should work on all windows
+01-11-28 ratz.c: fix sear_rm_r() to check SetCurrentDirectory() status
+01-11-26 ditto.sh: drop n+=v for ksh compatibility
+01-11-21 ditto.sh: add rsync script replacement &#0091;hey, it works!&#0093;
+ package.sh: add &#0091;ditto&#0093;:directory notation to admin.db
+01-10-31 package.sh: handle *.sum paths with embedded space
+ package.sh: change executable() to onpath()
+ package.sh: executable(&#0091;!&#0093; foo) replaces test &#0091;!&#0093; -x foo (.exe hack)
+ package.sh: add os2 fix to `host type'
+ mamake.c: add .exe hack
+ iffe.sh: fix intrinsic function lib test
+ mamprobe.sh: update pic probe to match make.probe for linux.ia64
+01-10-30 package.sh: make action skeleton view now checks subdirs
+01-10-20 package.sh: don't recurse into leaf dirs matching $MAKESKIP
+ package.mk: tarball package.notice replaces `license accepted' prompt
+ package.sh: eliminate `license accepted' prompt
+ package.sh: add update to download latest from a url
+ package.sh: use builtin arithmetic when we know its ksh
+ iffe.sh: unkown -&gt; unknown
+01-10-18 package.sh: convert to YYYY-MM-DD delta releases instead of NNNN
+ package.mk: convert to YYYY-MM-DD delta releases instead of NNNN
+ ratz.c: fix -m for paths containing <\>n</\>\r\v
+01-10-16 ratz.c: _SEA_* =&gt; SEAR_*
+ ratz.c: preserve stdin for sear_exec()
+ ratz.c: add recursive sear_rm_r() to sear_exec() tmp dir cleanup
+01-10-10 mamprobe.sh: add mam_cc_SHELLMAGIC
+ package.sh: add nfs wakeup call to admin to avoid stale file handles
+01-10-04 cc.darwin.ppc: -flat_namespace is not longer the default (huh)
+01-10-01 package make: prepend $INSTALLROOT/bin/ok to PATH
+ package read: save cpy of bin/package when reading the INIT package
+ mamprobe.sh: allow cc path with optional arguments
+01-09-24 Makefile,package.sh: add $INSTALLROOT/bin/.paths initialization
+01-09-19 package.mk: add recurse to list.package.*
+ package.sh: bootstrap build nmake with _BLD_STATIC for _WIN32
+01-09-11 ratz.c: add _SEA_SKIP &amp; _SEA_COMMAND for self extracting archives
+01-09-07 package.mk: fix output capture to not generate files names with spaces
+01-09-07 package.mk: fix delta release number search
+01-08-11 package.mk: handle single gz executable packages (e.g., for ksh)
+ package.sh: fix package install to require nmake only if no *.sum
+ iffe.sh: drop ancient menu and prompt actions; check ./hdr.h clash
+01-07-17 package: fix use cross compile test to generate files in /tmp
+01-06-27 ratz: handle hard and soft links if possible
+01-06-07 Makefile: fix :MAPLIB: for sco
+01-05-31 crossexec.sh: add
+ iffe.sh: add -x crosstype to run crossexec
+ iffe.sh: exp test now handles pass{}end fail{}end yes{}end no{}end
+ package.sh: add package host canon external-host-type-name
+ package.sh: fix `use USER' lookup for shells that support ~USER
+ cc.*: add -dumpmachine to dump target HOSTTYPE
+01-05-18 iffe.sh: drop $HOME/tmp/t.sh debug trace -- oops
+01-05-01 mamake.c: scan() now handles :PACKAGE: foo:command
+01-04-26 *.sh: expand &#0091;a-z&#0093;&#0091;A-Z&#0093;&#0091;0-9&#0093; for non-contiguous character codes
+ iffe.sh: fix run *.sh for shells that don't $* across . command
+ cc.mvs.390: recode for /bin/sh
+01-04-25 package.mk: include non cc-g variants by default
+ package.sh: *&#0091;._&#0093;* =&gt; *?&#0091;_.&#0093;* for mvs.390 /bin/sh
+01-04-24 TEST.mk: no tests for VARIANT=="DLL"
+01-04-22 package.mk,package.sh: tarball text members are ascii encoded
+01-04-18 package.mk: allow package name to be the same as one of its components
+ cc.mvs.390: handle .C .cpp .cxx
+ cc.mvs.390: compensate for -o that does not overwrite
+01-04-01 regress: fix SAME that just skipped it -- we should regress regress!
+ iffe: fix bug that didn't emit _hdr_foo for internal hdr tests
+ iffe: fix lcl bug for cc -E that doesn't emit line syncs
+ ratz: add ascii=&gt;ebcdic conversion for text archive members
+ mamake: fix buffer overlap bug that clobbered the probe file path
+01-03-17 iffe: handle : separator as first arg
+01-03-15 mamake.c,ratz.c,release.c: add &lt;stdlib.h&gt; and &lt;string.h&gt;
+01-02-26 iffe.sh: fix bug that omitted runtime #define for `mac' op
+01-02-22 cc.ibm.risc: handle SF_CLOSE clash in &lt;sfio.h&gt;
+01-02-14 cc.sgi.mips3,cc.sgi.mips4: handle -mips2 -mips3 -mips4 for cross cc
+ C+probe: quote "$cc" when its an argument!
+ mamake: execute actions with $SHELL, ignored signals back to default
+ package.sh: nmake check error output to /dev/null
+ package.sh: fix INIT a.out updates for knr cc
+ package.sh: package list now handles large tgz dirs
+ package.sh: *-ok executables moved to ok/* for *.dll systems
+ iffe.sh: change "exec &gt;&amp;-" to "exec &gt;/dev/null" else linux mkdir fails!
+ mamake: handle `bind -lx &#0091;dontcare&#0093;'
+01-02-12 ratz.c: fix _PACKAGE_ast includes
+ package.sh: $HOSTTYPE env overrides if $PACKAGEROOT/arch/$HOSTTYPE/
+ package.sh: $CC ^HOSTTYPE=&#0091;A-Za-z_0-9.&#0093;*$ overrides HOSTTYPE
+ iffe.sh: fix dat code that used previous $tmp.exe
+ iffe.sh: fix dat code for _DLL imports
+01-02-09 iffe.sh: add copy() for shells with the dissappearing here doc bug
+01-02-08 Makefile: guard against null $(CC.HOSTTYPE)
+01-02-06 Makefile: separate out cc,ld,ldd workarounds (so they will be packaged)
+01-02-02 package.sh: fix package use for $INSTALLROOT != */$HOSTTYPE
+ package.sh: create intermediate recursion makefiles when needed
+ package.sh: add $SECONDS to the DEBUG trace prompt
+01-01-01 ratz.c: #ifdef for uwin ncc
+ iffe.sh,package.sh: check PACKAGE_PATH for local installations
+ package.sh: add psrinfo for osf.alpha host cpu
+ package.sh: change pax --meter probe; some hang on /dev/tty
+ package.sh: fix `install flat ARCH'
+ mamake: eliminate loops from scan order
+ C+probe: add probe_verbose -V for aix cc=xlc
+ cc.ibm.risc,ldd.ibm.risc: add
+ package.mk: list refs to top-level licenses only
+ package.mk: add local link table to change log html
+00-12-25 package.sh: `no package archives' is a hard error, duh
+ package.sh: reorder host type logic for lame shells
+ mamake.c: getcwd =&gt; getwd for NeXT -- how about posix==default guys
+ iffe.sh: really gross workaround for NeXT -lposix stdout null's
+ iffe.sh: handle cc -E that insists on compiling
+00-12-15 iffe.sh: ancient sh function call blows $*; call only when $# == 0
+ *.sh: `getopts 2&gt;/dev/null` =&gt; `(getopts)2&gt;/dev/null` for ancient sh
+ package.sh: fix LD_LIBRARY*_PATH initialization
+ cc.next.m68k: add for _POSIX_SOURCE and linker multiply defined syms
+00-12-12 ratz: add --meter
+ package.sh: a few VPATH fixes
+ Makefile: don't override *.mips* cc if -version not accepted
+00-12-11 package.mk: *.inx now contains name=value
+00-12-07 package.sh: handle PC netscape . =&gt; _ pathname mangle
+ WWW.mk: .tar.gz =&gt; .tgz
+00-11-27 package.sh: add checklicense() to do license checks at read time
+ package.mk: change component list from preformat to table
+00-10-31 package.mk: *.pkg must assert closure
+ package.mk: add cc- variants to list.package.binary
+ package.sh: omit dups from package list
+ package.sh: invalid arg gives one line Usage
+ package.sh: relax checkaout checks for non-owners
+ package.sh: package use sets NPROC if not already set or &#0091;01&#0093;
+ proto.c: add $(INSTALLROOT)/include/ast hack
+00-10-26 WWW.mk: add .SOURCE rhs to :WWWPAGE:
+00-10-25 package: fix install
+ package.mk: add list.install
+00-10-22 regress: fix VIEW to skip empty dirs
+00-10-19 package.mk: $(PACKAGEROOT)/bin/nmake =&gt; $(PACKAGEROOT)/bin/manmake
+ iffe: validate #define identifiers
+00-10-18 C+probe: mac os10 additions
+ package: add DYLD_LIBRARY_PATH initialization
+ add ldd.$(CC.HOSTTYPE)
+00-10-01 iffe: handle -I* -L* options
+00-09-21 mamake: add libxxx and xxx to makefile ordered prereqs
+00-09-19 C+probe: add probe_longlong
+00-09-11 package: drop manmake and $PACKAGEROOT/bin/nmake
+00-09-08 iffe: verfiy that $cc is a C compiler
+00-06-14 mamprobe: fix win32.* probe
+ mamake: fix bug that used lower view path for generation
+ package: don't clobber $PACKAGEROOT/bin/nmake
+00-06-01 C+probe: fix stdinclude *again*
+ package: fix write delta source to use default pax format
+ package: add disambiguating bias for sgi.mips3 over sgi.mips4
+ package.mk: fix for directory content packages lib ast-locale
+00-05-01 iffe: fix invalid _LIB_ macro identifier
+00-04-11 C+probe: uniq stdinclude and stdlib, fix usrinclude
+00-04-01 regress: fix explicit OUTPUT bug that didn't compare with expected
+00-03-17 package: all archives are .tgz for binary download
+ package: $(PACKAGEROOT)/LICENSES/* in source and binary archives
+ package: implement install and verify actions
+ iffe: add exp, pth file dir ..., fix lib - -lfoo, fix lib - - -la -lb
+ iffe: -L* must affect LD_LIBRARY* hacks for .exe tests -- yuk
+ package.mk: add *.pkg :INDEX:
+00-03-07 package: add admin action
+00-03-06 makefile: install optional make probe override script C+make+probe.lcl
+00-02-14 --- release 1.0 ---
+ ratz: treat "foo/" as a dir, not a regular file
+ package: clarify source and binary installation instructions
+ package: fix so binary packages can install without cc
+ package: "ratz" now a non-archive package (the only one) for bootstrap
+ package: handle VPATH=a:b arg
+ package.mk: "ratz" package adjustments
+ Makefile: use :PACKAGE_INIT: to support binary INIT packages
+ WWW.mk: add :WWWALL:
+ C.probe: fix .so check that let .dll slip through
+ iffe: fix config sh var assignment for HAVE_member_IN_struct
+ iffe: fix config sh var assignment for symbol_DECLARED
+ package: delay PATH export until dll hack exports complete
+ package: don't forget binary package $(INSTALLROOT)/lib(32|64)
+ package: add delta change log for source packages
+00-02-10 mamprobe: add mam_cc_DLLBIG
+ package: fix spelling typos
+ package: add html help output
+ package.mk: beef up source and binary help =&gt; html
+00-02-08 package: mkdir man/man&#0091;138&#0093; in the new arch to cover MAM bug
+00-01-28 package,release: add -rcount to release
+ package: fix linux "host cpu" and "host rating"
+ package: copy *.lic to $PACKAGEBIN for "make" and "write binary"
+ package: fix 'release change log' case match
+00-01-24 package: add copyright action
+ mamprobe: add -D_BLD_DLL to mam_cc_DLL
+00-01-11 package: tsort for package write
+ package: early verification that $CC works
+ package: add non-interactive command arg for use action
+ proto: fix -C intermediate mkdir()
+ mamprobe: unixware.i386 ksh workaround
+ C.probe: move hosttype to C.probe (with unixware.i386 workaround)
+ WWW.mk: fix mm2html option quoting
+ WWW.mk: add .SCAN.mm
+ WWW.mk: don't force static=1; grab dll's instead
+ *.sh: fix getopts test to handle botched implementations like osf.alpha
+ iffe.sh: fix read -r test
+99-12-25 iffe: tweak verbose messages
+ iffe: hand code non-optget getopts parse
+ iffe: fix bash quoting bug again
+ iffe: do test -w . after option parse
+ package: fix PACKAGEROOT search
+99-11-19 --- release 0.2 ---
+99-11-19 first working package &amp; friends
+99-10-31 change from lib0ast to INIT; add MAM and package bootstrap
+ hostinfo: gobbled by package
+99-10-01 iffe: add --config, yes{...}end no{...}end, fix read -r workaround
+99-09-27 iffe: add --all --verbose, --* set options
+99-09-22 regress: -v disables long line truncation
+99-09-11 WWW.mk: WWWDIR and MM2HTMLINFO are now lists searched in $(HOME)
+99-08-11 hostinfo: fix type sgi.mips4
+99-06-24 WWW.mk: add
+99-06-08 hostinfo.sh: ${TMPDIR:-/tmp}
+99-06-07 TEST.mk: add
+99-06-01 iffe: add `siz type' for _siz_type == sizeof(type)
+99-05-11 hostinfo,iffe,regress,use: long options
+99-05-01 C.probe: fix over aggressive stdinclude, e.g., /usr/include/machine
+99-04-01 hostinfo: sgi.mips? -o32 and -n32 checks
+ iffe: check that . is writable
+99-03-17 hostinfo: fix for cc not found
+ dl.c,hello.c,m.c: headers in conditionals to force .DONTCARE
+ C.probe: extra check for include dirs pulled in by &lt;sys/types.h&gt;
+99-03-03 regress: add `UNIT - ...' for extra args
+ Makefile: add (_hosttype_) prereq for cc
+99-01-23 hostinfo: tweak rating, use /proc/cpuinfo if there
+99-01-11 C.probe: shlib before lib, /usr before /
+98-12-25 iffe: work around win32.alpha intrinsic clash with -O
+98-11-11 regress: fix UNIT PATH lookup
+98-11-01 regress: add PROG
+98-10-01 hostinfo: add unixware.*
+ use: export PACKAGE_*
+98-08-11 C.probe: add /usr/include check (for sco CC)
+ hostinfo: handle uwin uname update
+98-05-01 regress: fix bug sometimes didn't list last test
+98-04-01 hostinfo: add cc path arg
+ hostinfo: now works with /bin/sh
+ Makefile: strengthed -lm probe
+98-01-23 Makefile: check for -ldl -lm
+ C.probe: handle gcc -v -E phony include dirs
+ iffe: fix lcl by dropping sort -u -- we need the real first
+ iffe: `mem x' to test if x is a non-opaque struct
+98-01-11 $(INSTALLROOT)/lib32 for sgi.mips3
+ $(INSTALLROOT)/lib64 for sgi.mips4
+ add cc.hp.pa
+98-01-01 cc.sgi.mips*: turn off ld library multiply defined
+97-10-11 regress: add VIEW function for locating data
+97-10-01 Makefile: -ldl test moved to libdll Makefile
+97-08-11 regress: add MOVE
+ regress: add SAME
+ regress: use getopts
+ regress: `EXEC' repeats previous test
+97-07-17 use: tweak PATH and LIBPATH bootstrap order
+ iffe: fix lcl bug that botched pathnames with embedded spaces
+97-06-12 iffe: add npt `needs prototype' test
+97-05-09 hostinfo: mvs.* =&gt; mvs.390
+ Makefile: cc.$(_hosttype_) workaround installed here
+ iffe: fix nolink{ ... }end
+ iffe: add &#0091;no&#0093;static{ ... }end for static link test
+ C.probe: _probe_PATH =&gt; _probe_export which must be eval'd
+97-04-01 use: _RLD_ROOT set too
+97-03-17 mm2html: changed inner loop
+ mm2html: handle .if|.ie|.el, .so
+ mm2html: handle different man styles
+ mm2html: differentiate mm/man in some non-obvious cases
+ hostinfo: r5000 is not mips4
+97-02-14 hostinfo: validate type with cc
+96-12-25 C.probe: uwin tweaks
+ iffe: use `...` instead of $(...) for alpha /bin/sh
+ iffe: fix `typ' divide by 0
+ iffe: `lcl' now drops X: prefix
+ iffe: +l* -&gt; -l*
+ iffe: eval around ${...#%...} for bsd /bin/sh
+ use: add sgi.mips LD_LIBRARY&lt;abi&gt;_PATH variants
+ use: add -e to list exports
+ iffe: lcl leaves leading &#0091;a-zA-Z&#0093;: for dos
+ iffe: fix no{link|output|execute} logic
+ C.probe: don't automatically add /usr/include for non-hosted compilers
+ C.probe: don't automatically place /usr/include last
+ C.probe: check gcc style -v -E for stdinclude usrinclude
+96-11-28 iffe: check BASH_VERSION for IFS botch
+ iffe: typ long.xxx only if sizeof(long xxx) != sizeof(xxx)
+ hostinfo: fix sgi.mips&#0091;234&#0093; tests
+ hostinfo: fix ncr.i386 tests
+96-10-31 iffe: work around old bsh here doc bug by running separate sh
+96-10-11 iffe: *.iffe and *.iff for iffe src files
+ hostinfo: tighten sgi.mips cpu type check
+96-10-01 C.probe: add probe_libdir to catch alpha /usr/shlib
+96-09-17 iffe: fix typ bug that failed for single id types!
+96-08-31 hostinfo: handle recent sgi hinv cpu changes
+96-07-17 make sure sizeof(long xxx)&gt;sizeof(xxx) for typ long.xxx
+96-05-09 C.probe: drop multiple / in stdinclude
+96-02-29 use: package root must have bin and lib subdir
+ mm2html: add
+ C.probe: probe_members += -whole-archive for gcc
+ iffe: add + fix the blasted `...'...\...'...`
+96-01-31 use: add pkg dir
+ hostinfo: add tandem
+96-01-01 hostinfo: windows_nt|windows&#0091;0-9&#0093;&#0091;0-9&#0093; -&gt; win32
+95-11-24 hostinfo: linux-aout.* for non-elf linux
+95-11-11 use: add aix LIBPATH
+95-10-11 hostinfo: no args prints type
+95-08-11 use: add
+95-05-09 save original PATH in _probe_PATH
+ beef up library dir probe
+95-04-01 use c source suffix if it still preserves the dialect
+ add hostinfo
+ add lib/hostinfo/typemap user type map
+ add sol.sun4 cpu count
+ fix C.probe to properly handle C/C++ combined compiler drivers
+ add NeXT to hostinfo
+ bummer: mach has /usr/bin/hostinfo
+95-03-19 fix dialect executable test
+95-03-19 --- release 0.0 ---
+</PRE>
+<P>
+<HR>
+<TABLE border=0 align=center width=96%>
+<TR>
+<TD align=left></TD>
+<TD align=center></TD>
+<TD align=right>March 13, 2012</TD>
+</TR>
+</TABLE>
+<P>
+
+</TD></TR></TBODY></TABLE>
+
+</BODY>
+</HTML>
diff --git a/lib/package/INIT.pkg b/lib/package/INIT.pkg
new file mode 100644
index 0000000..32f1456
--- /dev/null
+++ b/lib/package/INIT.pkg
@@ -0,0 +1,12 @@
+INIT :PACKAGE:
+
+:CATEGORY: admin utils
+
+:INDEX: the package command with support scripts and utilities
+
+:DESCRIPTION:
+ The INIT package is required by all but the standalone
+ and self extracting archive packages. It contains
+ the package command, support scripts, and utilities.
+ The package command installs binary packages, makes
+ source packages, and generates new package tarballs.
diff --git a/lib/package/INIT.req b/lib/package/INIT.req
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/package/INIT.req
diff --git a/lib/package/INIT.ver b/lib/package/INIT.ver
new file mode 100644
index 0000000..f681461
--- /dev/null
+++ b/lib/package/INIT.ver
@@ -0,0 +1 @@
+INIT 2012-02-29 2012-02-29 1
diff --git a/lib/package/LICENSES/epl b/lib/package/LICENSES/epl
new file mode 100644
index 0000000..b1dfb87
--- /dev/null
+++ b/lib/package/LICENSES/epl
@@ -0,0 +1,221 @@
++------------------------------------------------------------------------------+
+| This license covers all software that refers to the URL |
+| http://www.eclipse.org/org/documents/epl-v10.html |
++------------------------------------------------------------------------------+
+
+Eclipse Public License - v 1.0
+
+ THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
+ LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+ CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+ 1. DEFINITIONS
+
+ "Contribution" means:
+
+ a) in the case of the initial Contributor, the initial code and
+ documentation distributed under this Agreement, and
+
+ b) in the case of each subsequent Contributor:
+
+ i) changes to the Program, and
+
+ ii) additions to the Program;
+
+ where such changes and/or additions to the Program originate from and are
+ distributed by that particular Contributor. A Contribution 'originates' from
+ a Contributor if it was added to the Program by such Contributor itself or
+ anyone acting on such Contributor's behalf. Contributions do not include
+ additions to the Program which: (i) are separate modules of software
+ distributed in conjunction with the Program under their own license
+ agreement, and (ii) are not derivative works of the Program.
+
+ "Contributor" means any person or entity that distributes the Program.
+
+ "Licensed Patents" mean patent claims licensable by a Contributor which are
+ necessarily infringed by the use or sale of its Contribution alone or when
+ combined with the Program.
+
+ "Program" means the Contributions distributed in accordance with this
+ Agreement.
+
+ "Recipient" means anyone who receives the Program under this Agreement,
+ including all Contributors.
+
+ 2. GRANT OF RIGHTS
+
+ a) Subject to the terms of this Agreement, each Contributor hereby grants
+ Recipient a non-exclusive, worldwide, royalty-free copyright license to
+ reproduce, prepare derivative works of, publicly display, publicly perform,
+ distribute and sublicense the Contribution of such Contributor, if any, and
+ such derivative works, in source code and object code form.
+
+ b) Subject to the terms of this Agreement, each Contributor hereby grants
+ Recipient a non-exclusive, worldwide, royalty-free patent license under
+ Licensed Patents to make, use, sell, offer to sell, import and otherwise
+ transfer the Contribution of such Contributor, if any, in source code and
+ object code form. This patent license shall apply to the combination of the
+ Contribution and the Program if, at the time the Contribution is added by
+ the Contributor, such addition of the Contribution causes such combination
+ to be covered by the Licensed Patents. The patent license shall not apply to
+ any other combinations which include the Contribution. No hardware per se is
+ licensed hereunder.
+
+ c) Recipient understands that although each Contributor grants the licenses
+ to its Contributions set forth herein, no assurances are provided by any
+ Contributor that the Program does not infringe the patent or other
+ intellectual property rights of any other entity. Each Contributor disclaims
+ any liability to Recipient for claims brought by any other entity based on
+ infringement of intellectual property rights or otherwise. As a condition to
+ exercising the rights and licenses granted hereunder, each Recipient hereby
+ assumes sole responsibility to secure any other intellectual property rights
+ needed, if any. For example, if a third party patent license is required to
+ allow Recipient to distribute the Program, it is Recipient's responsibility
+ to acquire that license before distributing the Program.
+
+ d) Each Contributor represents that to its knowledge it has sufficient
+ copyright rights in its Contribution, if any, to grant the copyright license
+ set forth in this Agreement.
+
+ 3. REQUIREMENTS
+
+ A Contributor may choose to distribute the Program in object code form under
+ its own license agreement, provided that:
+
+ a) it complies with the terms and conditions of this Agreement; and
+
+ b) its license agreement:
+
+ i) effectively disclaims on behalf of all Contributors all warranties and
+ conditions, express and implied, including warranties or conditions of title
+ and non-infringement, and implied warranties or conditions of
+ merchantability and fitness for a particular purpose;
+
+ ii) effectively excludes on behalf of all Contributors all liability for
+ damages, including direct, indirect, special, incidental and consequential
+ damages, such as lost profits;
+
+ iii) states that any provisions which differ from this Agreement are offered
+ by that Contributor alone and not by any other party; and
+
+ iv) states that source code for the Program is available from such
+ Contributor, and informs licensees how to obtain it in a reasonable manner
+ on or through a medium customarily used for software exchange.
+
+ When the Program is made available in source code form:
+
+ a) it must be made available under this Agreement; and
+
+ b) a copy of this Agreement must be included with each copy of the Program.
+
+ Contributors may not remove or alter any copyright notices contained within
+ the Program.
+
+ Each Contributor must identify itself as the originator of its Contribution,
+ if any, in a manner that reasonably allows subsequent Recipients to identify
+ the originator of the Contribution.
+
+ 4. COMMERCIAL DISTRIBUTION
+
+ Commercial distributors of software may accept certain responsibilities with
+ respect to end users, business partners and the like. While this license is
+ intended to facilitate the commercial use of the Program, the Contributor
+ who includes the Program in a commercial product offering should do so in a
+ manner which does not create potential liability for other Contributors.
+ Therefore, if a Contributor includes the Program in a commercial product
+ offering, such Contributor ("Commercial Contributor") hereby agrees to
+ defend and indemnify every other Contributor ("Indemnified Contributor")
+ against any losses, damages and costs (collectively "Losses") arising from
+ claims, lawsuits and other legal actions brought by a third party against
+ the Indemnified Contributor to the extent caused by the acts or omissions of
+ such Commercial Contributor in connection with its distribution of the
+ Program in a commercial product offering. The obligations in this section do
+ not apply to any claims or Losses relating to any actual or alleged
+ intellectual property infringement. In order to qualify, an Indemnified
+ Contributor must: a) promptly notify the Commercial Contributor in writing
+ of such claim, and b) allow the Commercial Contributor to control, and
+ cooperate with the Commercial Contributor in, the defense and any related
+ settlement negotiations. The Indemnified Contributor may participate in any
+ such claim at its own expense.
+
+ For example, a Contributor might include the Program in a commercial product
+ offering, Product X. That Contributor is then a Commercial Contributor. If
+ that Commercial Contributor then makes performance claims, or offers
+ warranties related to Product X, those performance claims and warranties are
+ such Commercial Contributor's responsibility alone. Under this section, the
+ Commercial Contributor would have to defend claims against the other
+ Contributors related to those performance claims and warranties, and if a
+ court requires any other Contributor to pay any damages as a result, the
+ Commercial Contributor must pay those damages.
+
+ 5. NO WARRANTY
+
+ EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON
+ AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
+ EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
+ CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A
+ PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the
+ appropriateness of using and distributing the Program and assumes all risks
+ associated with its exercise of rights under this Agreement , including but
+ not limited to the risks and costs of program errors, compliance with
+ applicable laws, damage to or loss of data, programs or equipment, and
+ unavailability or interruption of operations.
+
+ 6. DISCLAIMER OF LIABILITY
+
+ EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+ CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
+ LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+ EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
+ OF SUCH DAMAGES.
+
+ 7. GENERAL
+
+ If any provision of this Agreement is invalid or unenforceable under
+ applicable law, it shall not affect the validity or enforceability of the
+ remainder of the terms of this Agreement, and without further action by the
+ parties hereto, such provision shall be reformed to the minimum extent
+ necessary to make such provision valid and enforceable.
+
+ If Recipient institutes patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Program itself
+ (excluding combinations of the Program with other software or hardware)
+ infringes such Recipient's patent(s), then such Recipient's rights granted
+ under Section 2(b) shall terminate as of the date such litigation is filed.
+
+ All Recipient's rights under this Agreement shall terminate if it fails to
+ comply with any of the material terms or conditions of this Agreement and
+ does not cure such failure in a reasonable period of time after becoming
+ aware of such noncompliance. If all Recipient's rights under this Agreement
+ terminate, Recipient agrees to cease use and distribution of the Program as
+ soon as reasonably practicable. However, Recipient's obligations under this
+ Agreement and any licenses granted by Recipient relating to the Program
+ shall continue and survive.
+
+ Everyone is permitted to copy and distribute copies of this Agreement, but
+ in order to avoid inconsistency the Agreement is copyrighted and may only be
+ modified in the following manner. The Agreement Steward reserves the right
+ to publish new versions (including revisions) of this Agreement from time to
+ time. No one other than the Agreement Steward has the right to modify this
+ Agreement. The Eclipse Foundation is the initial Agreement Steward. The
+ Eclipse Foundation may assign the responsibility to serve as the Agreement
+ Steward to a suitable separate entity. Each new version of the Agreement
+ will be given a distinguishing version number. The Program (including
+ Contributions) may always be distributed subject to the version of the
+ Agreement under which it was received. In addition, after a new version of
+ the Agreement is published, Contributor may elect to distribute the Program
+ (including its Contributions) under the new version. Except as expressly
+ stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
+ licenses to the intellectual property of any Contributor under this
+ Agreement, whether expressly, by implication, estoppel or otherwise. All
+ rights in the Program not expressly granted under this Agreement are
+ reserved.
+
+ This Agreement is governed by the laws of the State of New York and the
+ intellectual property laws of the United States of America. No party to this
+ Agreement will bring a legal action under this Agreement more than one year
+ after the cause of action arose. Each party waives its rights to a jury
+ trial in any resulting litigation.
diff --git a/lib/package/ast-ksh.README b/lib/package/ast-ksh.README
new file mode 100644
index 0000000..7d67d3f
--- /dev/null
+++ b/lib/package/ast-ksh.README
@@ -0,0 +1,5212 @@
+The AT&T Software Technology ast-ksh package from AT&T Research
+contains ksh and support libraries. This is the minimal set of
+components needed to build ksh. This package is a superset of the
+following package: ksh; you won't need this if you download ast-ksh.
+
+Source Package Installation Instructions:
+
+ (1) Do not install packages as root/super-user. Although some components may
+ have setuid executables, few must be owned by root. These are best
+ changed manually when the security implications are understood.
+ (2) Choose a package root directory and cd to it. This will be a local work
+ area for all packages.
+ (3) These instructions bypass the click to download package links on the
+ download site. If you already clicked, or if your system does not have
+ curl(1), hurl(1), lynx(1) or wget(1) then use the alternate instructions
+ for (3),(4),(5) in plan B below. Plan B installs the hurl(1)
+ script which works with ksh and modern bash. The top level URL is:
+ URL=http://www.research.att.com/sw/download
+ (4) If the bin/package script does not exist then run:
+ test -d bin || mkdir bin
+ url=$URL/package
+ (wget -O bin/package $url||curl -L $url||hurl $url) > bin/package
+ chmod +x bin/package
+ (5) Determine the list of package names you want from the download site, then
+ use the package(1) command to do the actual download:
+ bin/package authorize "NAME" password "PASSWORD" \
+ setup source $URL PACKAGE ...
+ (Refer to the AUTHORIZATION paragraph on the main download page for
+ NAME/PASSWORD details.) This downloads the closure of the latest
+ source package(s); covered and up-to-date packages are not downloaded again unless
+ package force ... is specified. Package content is verified using md5sum.
+ If the package root will contain only one architecture then you can install in bin and
+ lib instead of arch/HOSTTYPE/bin and arch/HOSTTYPE/lib by running this
+ instead:
+ bin/package authorize "NAME" password "PASSWORD" \
+ flat setup source $URL PACKAGE ...
+ To update the same packages from the same URL run:
+ bin/package setup source
+ (6) Build and install; all generated files are placed under arch/HOSTTYPE
+ ($INSTALLROOT), where HOSTTYPE is the output of bin/package (with no
+ arguments.) name=value arguments are supported; CC and debug=1 (compile
+ with -g instead of -O) are likely candidates. The output is written to
+ the terminal and captured in $INSTALLROOT/lib/package/gen/make.out:
+ bin/package make
+ (7) List make results and interesting errors:
+ bin/package results
+ Run the regression tests:
+ bin/package test
+ List test results and errors:
+ bin/package results test
+ (8) The generated binaries are position independent, i.e., they do not
+ contain hard-coded paths. However, commands with related files, like
+ file(1) and nmake(1), require the path of the bin directory to be
+ exported in PATH.
+ (9) You can run the binaries directly from the package root, or you can
+ install them in a public root after you are satisfied with the make and
+ test actions (requires the AT&T nmake(1) command):
+ bin/package flat install DIRECTORY PACKAGE
+ This will install in DIRECTORY/bin and DIRECTORY/lib. If you want to
+ preserve the arch/HOSTTYPE hierarchy under DIRECTORY then omit the
+ flat argument. If you don't have nmake(1) then the following will do a
+ flat install:
+ cd $INSTALLROOT
+ cp -p -r bin lib include DIRECTORY
+ (10) To summarize, after the first time the download, build, and test cycle
+ for the latest source release is:
+ bin/package setup source
+ bin/package make
+ bin/package test
+
+Source Package Installation Instructions -- Plan B:
+
+ (3) Create the subdirectory lib/package/tgz and download all package archives
+ into that directory.
+ (4) If the bin/package script does not exist then manually read the INIT
+ source package:
+ gunzip < lib/package/tgz/INIT.YYYY-MM-DD.tgz | tar xvf -
+ Note that some browsers automatically unzip downloaded without warning.
+ If the gunzip fails try:
+ tar xvf - lib/package/tgz/INIT.YYYY-MM-DD.tgz
+ If your system does not have tar(1) or gunzip(1) then download the ratz
+ source package, compile it, and manually read the INIT
+ source package:
+ mkdir bin
+ cp lib/package/tgz/ratz.YYYY-MM-DD.c lib/package/tgz/ratz.c
+ cc -o bin/ratz lib/package/tgz/ratz.c
+ bin/ratz -lm < lib/package/tgz/INIT.YYYY-MM-DD.tgz
+ (5) Read all unread package archive(s):
+ bin/package read
+ Both source and binary packages will be read by this step.
+
+All recorded changes follow.
+
+:::::::: ksh93 ::::::::
+
+12-02-29 --- Release ksh93u+ ---
+12-02-29 A bug which could lead to a core dump when more that four shared
+ libraries were added with the builtin command has been fixed.
+12-02-29 Fixed a few bugs which caused SIGCHLD to be blocked preventing
+ background jobs from being reaped until a foreground job was run.
+12-02-27 A bug in which sh -c for a simple command caused a fork() has been
+ fixed.
+12-02-27 A timing bug on systems such as AIX that doesn't support vfork()
+ that could cause the exist status to get lost has been fixed.
+12-02-22 A private file descriptor that was not close-on-exec for a command
+ substitution and has been fixed.
+12-02-14 A bug in which ^Z did not stop a pipeline when the last component
+ was a shell built-in has been fixed.
+12-02-14 getconf("PATH") used to initialize ed(1) path.
+12-02-13 +In earlier version read from standard input would fail when called
+ from the KEYBD trap. Now read options -N, -n, and -t should work
+ when called from a KEYBD trap.
+12-02-13 If FCEDIT is not set and fc is invoked without the -e option,
+ ed will be invoked if found instead of /bin/ed.
+12-02-10 Another bug in the saving and restoring of IFS in a subshell
+ that caused a core dump has been fixed.
+12-02-08 A bug in which .sh.fun disciplines could be cleared after a
+ function completes has been fixed.
+12-02-08 A bug in job control in which the foregroup process group was not
+ set correctly after restarting a stopped pipeline has been fixed.
+12-02-07 A bug in which numbers with leading zeros could be treated as
+ octal constants outside of ((...)) has been fixed.
+12-02-06 A bug in arithmetic with compound variables containing multiple
+ array elements has been fixed.
+12-02-02 A bug in the ulimit option table was fixed.
+12-01-26 A bug in which a set command that did not change monitor could
+ effect the behavior of the monitor when monitor mode is on is fixed.
+12-01-21 +You can now test whether the shell implements a math function using
+ typeset -f .sh.math.name, where name is the name of the function.
+12-01-21 A bug in which typeset -L and typeset -R did not handle multibyte
+ characters correctly has been fixed.
+12-01-20 A bug that could cause the shell to hang waiting for an incorrect
+ job pid has been fixed.
+12-01-19 A memory leak which occured for a nested command subtiution has been
+ fixed.
+12-01-17 A bug in which typeset -u PS1 could enable the uppercase attribute
+ for some other variables, for exampe, HISTFILE has been fixed.
+12-01-16 A bug in which .sh.match was not correct after a substring match when
+ the replacement string contained a substring match has been fixed.
+12-01-12 +Files that are sourced from profile files are now read and executed
+ one command at a time so that alias definitions take effect as they
+ do for profile files.
+12-01-12 A bug in which whence -p would find a function if one existed and
+ there was no command of that name on PATH.
+12-01-11 Change b_* prototype (int, char**, void*) => (int, char**, Shbltin_t*).
+12-01-05 A bug in which read was not terminating for a signal that had a trap
+ set has been fixed.
+12-01-01 A timing problem with >; has been fixed.
+12-01-01 A macro expansion memory leak has been fixed.
+11-12-26 A bug in array assignments of the form arr=( $arr[i] ...) in which
+ arr was not unset before the assignment has been fixed.
+11-12-20 A number of code changes were made based on the results of errors
+ indicated by static code analysis.
+11-12-13 In vi edit mode a lteral <TAB> can now be entered by preceding it
+ with a backshash.
+11-12-13 When tab is entered for completion after a ' or ", the ' and "
+ characters are no longer deleted.
+11-12-07 A bug in which a program in the current direcotry with a . in the
+ name could fail to execute when both PATH and FPATH end with :. has
+ been fixed.
+11-12-07 I fixed a bug in which a variable expansion in a large here-document
+ could be expanded to a null string.
+11-12-06 An optimization to read was added in the case the the read command
+ was redirected from a file.
+11-12-06 Changes were made to make the line limit for read unlimited by
+ default.
+11-12-05 A bug in which unsetting an array variable did not completely clear
+ the variable in some cases has been fixed.
+11-12-02 +The printf alternative character # when applied to the %q format will
+ quote argument in a form suitable for a field in a .csv format file.
+11-12-02 +A -S option was added to read to be able to read .csv format files.
+11-11-28 A bug in which redirection of standard error in a function called from
+ command substitution caused standard error to be lost has ben fixed.
+11-11-21 [[ (-n foo) ]] no longer requires a space before (.
+11-11-11 The readonly attribute for a variable now applies to compound
+ assignments to that variable.
+11-11-07 Changes were made to reduce the stack size to allow deeper function
+ recursion.
+11-10-10 +Added alternate flag to printf %H for encoding of URI's.
+11-10-10 A bug which could lead to a core dump when the shell was invoked
+ with more than twenty five open files has been fixed.
+11-10-06 A bug in the scoping of name references in functions called by other
+ functions has been fixed.
+11-10-05 A bug in which wait on a pid may return the exit status of an
+ earlier background job with that pid instead has been fixed.
+11-09-22 A bug in which a read timed out with TMOUT did not always restore
+ the terminal state has been fixed.
+11-09-21 An optimization that allowed the last command in a script to use
+ the same process id as the script has been eliminated.
+11-09-21 Added letoctal option that enables the let command to recognize
+ octal constants starting with 0.
+11-09-20 A bug in which ${var.} could cause a core dump has been fixed.
+11-09-20 A bug with SHOPT_EDPREDICT when neither vi or emacs was enabled for
+ lines beginning with # when in a multibyte locale has been fixed.
+11-09-20 A bug in emacs edit mode with SHOPT_EDPREDICT that would cause
+ history searches matching comments lines to generate predictions
+ has been fixed. Only user typed comment lines generate predictions.
+11-09-20 A bug in emacs edit mode with a search that matches a comment line
+ that could cause a core dump has been fixed.
+11-09-16 A bug in which a command name ending in .. could cause the shell to
+ abort has been fixed.
+11-09-16 The characters ! + - % and @ in file names are no longer escaped with
+ file name completion.
+11-09-13 The let command no longer treats numbers starting with 0 as octal
+ constants.
+11-09-08 A bug in which printf "%R" could cause a core dump for invalid shell
+ patterns has been fixed.
+11-08-09 With set -u, ${var#pattern} reported that var was unset for special
+ variables.
+11-08-03 A bug in which the shell did not preserve the exit status for a
+ coprocess has been fixed.
+11-08-02 A bug in the saving and restoring of IFS in command substitution that
+ caused a core dump has been fixed.
+11-07-21 Modified the 10-08-27 bug fix so that background jobs started in for
+ and while loops created interactively generate completion messages.
+11-07-20 I fixed a bug in here documents in which multi-byte characters that
+ crossed buffer boundaries were not processed correctly.
+11-06-22 The shell compiler now supports process substitution.
+11-06-22 +Added code to support process substitution on systems that do
+ not supply the /dev/fd directory.
+11-06-21 Fixed extraneous jobs Done messages when builtin is at the end of a
+ pipeline.
+11-06-20 Fixed two regression tests.
+11-06-20 Fixed a bug introduced on last update.
+11-06-14 A bug with pipefail in which the shell would wait for background
+ jobs to complete has been fixed.
+11-06-09 A bug which caused the options.sh regression test to fail on OS390
+ Linux has been fixed. The bug could also have affected other systems.
+11-06-07 +A number of changes to support the still undocuments namespace option
+ have been added.
+11-06-06 A bug in which command substitution of eval would hang when it had
+ standard error redirected to standard output has been fixed.
+11-06-01 A bug in case statement fall through (;&) ignoring set -e was fixed.
+11-06-01 A bug in which creating a left or right justified upper or lowercase
+ variable with an empty string has been fixed.
+11-06-01 A bug in which the .paths directory wasn't read when a subshell was
+ executed before any other command has been fixed.
+11-05-31 The shell now gives an error when a type variable is assigned to
+ an array instance when the array has been declared a compound variable
+ array.
+11-05-31 A bug in which typeset -m of an array instance did not remove the
+ original instance has been fixed.
+11-05-28 A bug in which typeset -m dest=src fails when src and are passed as
+ name references was fixed.
+11-05-28 A bug in which typeset -m "c.board[1][i]=el", where el is a compound
+ variable core dumps has been fixed.
+11-05-28 Two bugs in the display of arrays of compound variables with print -v
+ have been fixed.
+11-05-27 A bug with command substitution with the shift jis locale has been
+ fixed.
+11-05-25 A bug in which unset -f foo, called within function foo could cause
+ the shell to core dump has been fixed.
+11-05-24 A bug in unsetting arrays of compound variables that could lead to
+ a core dump has been fixed.
+11-05-24 A scoping bug in with typeset -m for variables passed as references
+ has been fixed.
+11-05-09 A bug in which 'typeset +p array[$i]' in a subshell could cause an
+ exception has been fixed.
+11-05-03 Two more scoping bugs with name references and read -C were fixed.
+11-05-03 A potential race condition which occurs when here-documents are
+ processed in asynchronous blocks has been eliminated.
+11-05-02 Another scoping bug with name references defined in a function has
+ been fixed.
+11-05-02 A bug in which the shell discards saved exit status of a job if it is
+ followed by a subshell execution has been fixed.
+11-04-28 The shell now checks for numerical overflows with process ids.
+11-04-28 Another scoping bug with compound variables defined by name references
+ inside a function has been fixed.
+11-04-28 A bug which caused a core dump on 32 bit systems with the basic.sh
+ regression test has been fixed.
+11-04-27 A scope binding error for name references has been fixed.
+11-04-27 Assignment of compound variable to compound array element by name
+ is now working.
+11-04-26 I fixed a bug with SHOPT_FIXEDARRAY compilation that could cause
+ an a core dump for not fixed arrays.
+11-04-25 A bug in the references to two dimensional compound arrays has
+ been fixed.
+11-04-20 A bug in which a name reference to a multidimentional index array
+ index, nameref x=foo[3][4], did not work correctly has been fixed.
+11-04-18 Changes were added to allow fixed size arrays of variable sized
+ objects when the SHOPT_FIXEDARRAY compile option defined on 10-09-28.
+11-04-18 A bug in which name references to array elements could fail has
+ been fixed.
+11-04-15 +A compile option, SHOPT_2DMATCH, has been added which causes
+ .sh.match to be a two dimensional array after ${var//pat/str}
+ where the first dimension is the pattern number and the second is
+ the match instance.
+11-04-11 A bug in which readonly var, where var is exported could cause var
+ to be unset has been fixed.
+11-04-06 A tokenizer bug in which ${x/{3}(\d)/ } would cause in infinite
+ loop has been fixed.
+11-04-05 A bug in which ${!x.} could cause a core dump has been fixed.
+11-04-04 A bug in which cleaning out the history file could terminate before
+ keeping all the recent history events has been fixed.
+11-03-29 A bug in which ${#array[@]} was 1 rather than 0 after issuing
+ typeset array[7] has been fixed.
+11-03-29 The subscript out or range message for fixed arrays has been fixed.
+11-03-29 A bug in which suspend could cause a core dump has been fixed.
+11-03-24 For the showme option added 09-09-09, commands beginning with a ;
+ inside an arithmetic for loop, no longer produce syntax errors.
+11-03-18 A bug in _WINIX ~domain/user expansion has been fixed.
+11-03-16 A bug in the pipefail option which could cause a script to hang
+ has been fixed.
+11-03-12 The shell no longer treats ${##pattern} as a syntax error.
+11-03-11 A bug in typeset -u on systems that don't supply the towctrans()
+ function has been fixed.
+11-03-11 A bug in which a compound assignment of the form var[sub]=(...)
+ would evaluate sub for each assignment has been fixed.
+11-03-07 A bug in which reassigning a compound variable to an associative
+ array index could incorrectly increase the count of the number
+ of elements has been fixed.
+11-03-04 +The tilde expansion on windows has been modified to handle user
+ names of the form domain/user so that ~domain/user now expands
+ to the home directory of that domain user.
+11-03-03 A bug in which the width of the prompt was calculated incorectly
+ which cause the wrong line length for edit commands has been fixed.
+11-03-02 A bug in which a global variables set from within a function inside
+ a subshell can leave side effects in parent shell has been fixed.
+11-03-01 A bug in which whence -a could dump core when the first match
+ was due to : in PATH and the program was in the current directory.
+11-02-28 A bug in emacs mode with SHOPT_EDPREDICT (added on 10-05-20) which
+ disabled prediction on a line starting with # when the cursor was not
+ at the end of line has been fixed.
+11-02-28 The output format for compound variables with set has been fixed.
+11-02-25 A bug which could lead to a core dump occurred when a shell script
+ without #! is invoked by name from a parent shell that has name
+ references defined and the script creates name references of the
+ same name.
+11-02-21 The shell now fails with a syntax error when a here-document in a
+ command substition is not completed before the closing ), for
+ example, $( foobar <<! )
+ here_doc
+ !.
+11-02-18 A bug in which the value of $0 in a function defined by name()
+ was changed to name has been fixed.
+11-02-17 A bug in which the declaration typeset var[100] did not work
+ correctly has been fixed.
+11-02-15 A bug in which [[ -v sh.match ]] did not work correctly has been
+ fixed.
+
+11-02-08 --- Release ksh93u ---
+11-02-08 A bug in which opening standard output after it has been closed with
+ exec 1>&- doesn't work has been fixed.
+11-02-07 A bug on some systems for which a command subtitution could hang
+ has been fixed.
+11-01-28 A bug in file name completion for files containing both multibyte
+ characters shell special characters has been fixed.
+11-01-18 The .sh.match variable now shows elements that do not match as
+ as not set rather than an empty string.
+11-01-18 A bug with typeset -m of an array into an element of an indexed
+ array has been fixed.
+11-01-13 A bug in handling of arrays of compound variables inside ((...)) which
+ reported a syntax error been fixed.
+11-01-10 A bug in arithmetic assignment operators of the form op= for array
+ variables when the same array was referenced on the left and the
+ right hand side with different indices has been fixed.
+11-01-10 A bug in which the output of time was lost when { time...;} 2>&1
+ occurred inside command substition has been fixed.
+11-01-07 [[ -v sh.match[i] ]] was returning false when sh.match[i] was set.
+11-01-05 Added and modified warning messages with sh -n.
+11-01-02 Fixed bugs with typeset -l/-u/-M and arrays.
+10-12-28 Fixed a bug with typeset -l/-u/-M values in arithmetic expressions.
+10-12-26 Fixed a time parsing bug in sleep and localeconv() initialization.
+10-12-23 Prevented the shell from generating a core dump when it sends itself
+ a termination signal because the last command terminated with that
+ signal. This prevents a core dump to be overwritten by the shell.
+10-12-22 A bug in the expansion of ${A[@]} ${B[@]}, introduced in 10-12-01
+ when A="" B=B has been fixed.
+10-12-21 +Use MS_3D in b_vpath() for setting win32 WoW mount defaults.
+10-12-17 A bug in the expansion of ${var:i:j} which caused a core dump when
+ i > ${#var} has been fixed.
+10-12-16 +sleep now treats . as decimal point even in locales that use comma.
+10-12-16 +typeset -M mapname was added to generalize on toupper and tolowwer
+ mapping as provided with wctrans().
+10-12-10 A bug in which typeset -l displayed namespaces as well as lower case
+ variables has been fixed.
+10-12-06 A bug in which a pipeline could terminate prematurely for a pipeline
+ whose right hand side is a builtin, and whose left hand side ends in
+ a simple command that has standard output redirected has been fixed.
+10-12-06 A bug in hexfloat assignments when the right hand side is a string
+ variable starting with 0x has been fixed.
+10-12-01 A bug in the expansion of ${$1+"$@"} which causes the last positional
+ parameter to disappear when it is empty has been fixed.
+10-12-01 A number of changes were made to reduce the startup time.
+10-11-29 When wait is interrupted by a signal that is caught, it now exits
+ with a non-zero exit status.
+10-11-29 When a variable is used directly in an arithmetic expression,
+ leading zeros no longer cause the value to be treated as an
+ octal constant. This was true in previous versions for justified
+ variables.
+10-11-29 An incorrect warning message was eliminated with the -n option for
+ arithmetic expressions with associative arrays.
+10-11-29 Some changes were made to slightly reduces startup time.
+10-11-24 A bug in which a name reference is make to arr[0] when arr is not
+ an array has been fixed.
+10-11-23 If a type definition is made without a compound variable assignment it
+ produces an error message and no longer shows up as a defined type.
+10-11-22 The handling of \ inside [...] for for shell and ~(E) patterns has
+ been fixed.
+10-11-22 A patch was made to pfsh to handle an error case.
+10-11-22 +Modified types defined in namespace so that they do not clash with
+ types in other namespaces. Types can be referenced using
+ .namespace.typename.
+10-11-22 A bug which caused functions addressed as .namespace.funct to not
+ work has been fixed.
+10-11-22 A bug in which if nr was a name reference to an unset associative
+ array subscript, then ${!nr} did not output the subscript correctly
+ has been fixed.
+10-11-18 A bug in which shcomp -n was not processing double quotes correctly
+ has been fixed.
+10-11-18 Fixed a bug in which typeset -T foo; typeset -T could cause a
+ core dump.
+10-11-17 Fixed a bug in which the error message for set -u could come out
+ garbelled.
+10-11-17 Modified the parser so that typeset -a var=(...) no longer checks
+ the first index for aliases and reserved words.
+10-11-17 A bug in which a subshell command consisted of only a for or until
+ command has been fixed.
+10-11-16 Fixed a bug in which typeset -u would display namespace variables
+ as well as upper case variables.
+10-11-16 A bug which could cause a core dump when unsetting a type variable
+ when there are references to type elements has been fixed.
+10-11-15 A bug which could cause a core dump when unsetting a compound
+ array variable when there are references to array subscripts has
+ been fixed.
+10-11-15 A bug in which using typeset -m to move an indexed array instance
+ to another array could cause the array to display incorrectly has
+ been fixed.
+10-11-12 A bug in which the unset discipline function for a type is called
+ when the type is initialized has been fixed.
+10-11-12 The sequences \< and \> are now preserved after patterns containing
+ ~(E) in ${var/pattern/string} expansions.
+10-11-11 A bug in typeset -m when the variables were compound arrary instances
+ has been fixed.
+10-11-10 A bug in output of a compound variable with types containing types
+ has been fixed.
+10-11-10 Fixed ``name=value export [-p]'' to list environment.
+10-11-09 shtests resets SIGPIPE to SIG_DFL for all tests.
+10-11-09 Fixed a bug in expansion of $"..." when used in assignments.
+10-11-09 Fixed a getaddrinfo() memory leak that didn't call freeaddrinfo()
+ after an interrupt.
+10-11-08 Modified the behavior of set -u so that the shell terminates with
+ error message when when var is unset with ${!var} and ${#var}.
+10-11-02 Fix a bug in which a signal received while in a subshell could be
+ ignored.
+10-10-26 Fix a bug where terminal interrupt was ignored while in vi/emacs
+ edit search mode.
+10-10-26 Fix $'a\0b'c to expand to 'ac'.
+10-10-26 Provide user defined round() if not in <math.h>.
+10-10-26 Fix bug where $((undefined_function(1))) dumped core.
+10-10-22 Provide user defined iszero() if not in <math.h>.
+10-10-22 Fixed a bug with BGX compile option that could cause the shell to
+ hang.
+10-10-22 Fixed a bug with user define math function on systems for which
+ char is unsigned.
+10-10-21 A bug in which function autoloaded in a function leaves a file open
+ has been fixed.
+10-10-20 Modified the behavior of set -u so that the shell terminates when
+ when var is unset with ${var op string} when op is #, % or /.
+10-10-20 Fixed a bug with the AUDIT option in which the audit file was not
+ not close-on-exec.
+10-10-20 +Made a number of changes and fixes for the NAMESPACE compile option
+ which as added on 10-06-09 but some problems still remain.
+10-10-15 Fixed a bug in which arithmetic functions (added on 10-03-24) did
+ not work when the function definition was in the same compound
+ command in which the function was referenced.
+10-10-13 A bug in which creating an associative array of compound variables
+ with no members as an element of a compound variable did not work
+ has been fixed.
+10-10-08 A bug in which killing the last command in a function defined
+ with function name, terminated the calling script has been fixed.
+10-10-08 A bug which could cause a core dump if IFS is unset inside a function
+ has been fixed.
+10-10-07 +To reduce unwanted side effects, invoking typeset without the export
+ option and without an assignment now causes the variables to be unset
+ if the variable is inherited from the environment.
+10-10-06 The closing brace for ${ command } is now a token no matter what
+ character follows it.
+10-10-04 The change for $'...' expansion on 10-08-09 did not expand parameters
+ contained in the error message and this has been fixed.
+10-10-04 A bug in which a declaration of indexed array (-a_ in a type
+ definition would be displayed as a compound indexed array (-C -a)
+ has been fixed.
+10-09-30 The C99 math function ldexp has been added.
+10-09-30 A bug with two dimensional arrays with expansion of the form
+ ${ref[0..5]} where ref is a nameref to array[i] has been fixed.
+10-09-29 A bug in which an eval with redirections invoked from a dot script
+ would not restore the file has been fixed.
+10-09-29 A bug in which loading a function from FPATH could leave a file
+ descriptor open has been fixed.
+10-09-28 +A new compile option SHOPT_FIXEDARRAY has been added and is being
+ evaluation. It allows fixed sized indexed arrays be to defined
+ using "typeset array[dim1][dim2]...[dimn]". Fixed sized arrays
+ are used the same way indexed arrays are. Currently, only fixed
+ arrays of fixed objects (float, int, and justifies objects) are
+ supported.
+10-09-22 A bug which could cause an exception when a function with static
+ variables was redefined has been fixed.
+10-09-21 A bug in the processing of (command&) which created a job in the
+ parent process has been fixed.
+10-09-21 A for loop optimization bug with arithmetic expression evaluation
+ has been fixed.
+10-09-21 A bug in which a recursive function containing a pipeline could
+ lead to an exception fixed after 8 levels of recursion has been
+ fixed.
+10-09-18 A bug in which the count of elements in an array was wrong leading
+ to an exception has been fixed.
+10-09-13 A bug which occurred when both xtrace and showme options where
+ specified in which the xtrace option disabled showme has been fixed.
+10-09-13 A bug in which creating a reference to an array variable with any
+ elements could cause subsequent array elements to be treated as
+ compound variables has been fixed.
+10-09-09 A bug which caused ((c.ar[x][y])) to be treated as a syntax error
+ has been fixed.
+10-09-08 A bug in the processing of references to multidimensional arrays
+ in arithmetic expressions has been fixed.
+10-09-08 A bug in the handling of multi-dimensional arrays which caused
+ the number of elements in each dimension to be incorrect has
+ been fixed.
+10-09-07 The change for messages on 10-08-09 did not handle message in
+ assignments and this has been fixed.
+10-09-07 A bug in the indentation of compound variables in arrays when
+ output with print -v has been fixed.
+10-09-07 A rare bug with indexed arrays when assigned a null string that could
+ cause a core dump has been fixed.
+10-09-03 A number of changes were made for jobs pools.
+10-08-31 typeset -p was modified to output name references after other
+ variables so that the output could be used as input.
+10-08-31 A bug with typeset -p in which variables with attributes but
+ without attributes were not displayed correctly has been fixed.
+10-08-27 +When running a subshell, the current pool is unset.
+10-08-27 A bug in which jobs started from within for or while lists in
+ interactive shells could generate completion messages has been fixed.
+10-08-25 Fixed a couple of bugs related to job pools.
+10-08-24 +[[ -e /dev/xxx/ ]] can be used to check whether special files of
+ those names are handled by the shell.
+10-08-24 A bug in the running of a compiled dot script in which only the
+ first command was executed has been fixed.
+10-08-23 A bug which sometimes caused a core dump with a configure script
+ has been fixed.
+10-08-20 A bug in command substitution which caused a configure script to
+ hang has been fixed.
+10-08-19 Eliminated unnecessary ; from output of compound variable with
+ typeset -p.
+10-08-17 Fixed a bug in command substitution in which under certain
+ circumstances a file whose size is a power of 2 plus one, and the last
+ character was not a new-line, could cause memory corruption.
+10-08-13 +Added static discipline functions to type similar to C++ static
+ class functions.
+10-08-11 A bug in time when applied to a pipeline in which the shell did
+ not wait for all elements of the pipeline to complete has been fixed.
+10-08-11 Restored sh_fmtq() quoting to not quote NAME= in NAME=VALUE.
+10-08-09 +Modified the expansion of message strings, $"...", so that they
+ are expanded each time they are referenced rather than expanding
+ them when the script is compiled or read in.
+10-08-06 +The process id for jobs in job pools is now of the form poolname.n
+ where n is the jobid in that pool. Commands that accept job names
+ or numbers now understand names in this format.
+10-08-05 A bug in which an assignment from within an arithmetic expression
+ inside a function would create a local variable has been fixed.
+10-08-04 A bug in the expanding of variables whose names contain multibyte
+ characters has been fixed.
+10-08-04 A bug which caused an exception when processing scripts compiled
+ with shcomp -n has been fixed.
+10-08-02 Tests using very small buffer sizes uncovered a number of bug most
+ connected with here documents which have been fixed.
+10-07-27 The format modifier , used for digit grouping with d and f formats
+ has been documented.
+10-07-26 cd '' now produces and error rather than changing to the current
+ directory.
+10-07-26 A bug in multi-byte locales which the last character of a
+ multi-byte character is a \ or pattern character which could occur
+ when the character was the last character of a command substitution
+ has been fixed.
+10-07-23 Another bug in the processing of ${var:offset;len} in multi-byte
+ locales when len is larger than the number of characters has been
+ fixed.
+10-07-23 Many coding changes have been made to eliminate most of the uses
+ of global variables in the shell code.
+10-07-22 Fixed a bug in which discipline functions were not being invoked
+ when it was invoked as ref.discipline where ref was a name reference
+ to an array instance.
+10-07-22 Fixed a bug in which discipline functions were not being invoked it
+ was invoked on a two dimensional array, i.e., arr[5][9].discipline.
+10-07-19 Fixed a buffering problem which occurred when running a script with
+ ssh and the parent ssh process is killed.
+10-07-14 Modified the parser to treat ((...)) inside [[...]] as ( (...) ) to
+ that it is a nested (...).
+10-07-09 A bug in the handling of process substitution inside command
+ substitution as part of a pipeline has been fixed.
+10-07-07 A bug in the output for compound variables containing
+ multi-dimensional arrays has been fixed.
+10-07-06 ksh now recovers from changes made by bash to the history file without
+ loosing history commands.
+10-06-25 A bug in which a large here document containing command substitutions
+ of a dynamically loaded function that contained a here document
+ could get truncated has been fixed.
+10-06-24 If after executing a script found in FPATH, if a function, builtin,
+ or type name corresponding to that script is not defined, the shell
+ now outputs an error message and returns value 126.
+10-06-23 Floating point functions that happened to return integer values
+ were being treated as if the function returned integers so that
+ integer division could be used instead of floating point division.
+10-06-22 Fixed a bug in earlier ksh93u in which an arithmetic assignment to a
+ variable in the global scope would instead create a local variable if
+ the variable had an attribute but did not have a value.
+10-06-18 Modified trap handling so that if the same signal is received when
+ executing the handler, it is deferred until the handler completes.
+10-06-16 Fixed a bug in which ulimit -v was setting the the cpu limit
+ on Linux.
+10-06-14 +The command 'typeset -T' now generates the list of type definitions
+ in a format that can be used as input to the shell.
+10-06-09 Put in patch from Solaris for output quoting with %q.
+10-06-09 +Made changes to the NAMESPACE compile option so that it now seems
+ to work. With this option, namespace <name> { command;} will
+ run command in the namespace .name so that all variables and
+ functions created by command are accessible outside the name
+ space via .name.var and .name.fun. Variables and functions that
+ are not in the namespace are not modified when running command.
+10-06-07 Change most internal interfaces to take Sh_t* argument.
+10-06-03 +Types can be loaded on first reference by putting definitions in
+ PFPATH.
+10-06-03 +The shell is now able to parse commands which use type statements
+ before the typeset -T command to define the type executes.
+10-06-03 A bug in the quoting for name reference declarations which did
+ not properly handle [ and ] in subscripts for associative arrays.
+10-06-02 A bug in which a discipline function defined by a type instance to
+ override the default was not being registered has been fixed.
+10-06-02 A bug in which read -C of an associative array of compound variables
+ was not working has been fixed.
+10-06-02 A bug in which the error message for an unset parameter with set -u
+ did not contain the name of the variable has been fixed.
+10-06-01 A bug in typeset -m for moving an indexed array instance to a variable
+ has been fixed.
+10-06-01 A bug in which caused memory to be freed twice when unset was called
+ for an indexed array that had get or set disciplines has been fixed.
+10-06-01 A bug in which the %b format of printf was not preserving NUL bytes
+ with \0 has been fixed.
+10-06-01 A bug in the handling of name references to array variables in
+ arithmetic expressions has been fixed.
+10-05-28 Fixed bugs in changing attributes for two dimensional arrays.
+10-05-28 Eliminated a few unreferenced variables and a reference to
+ uninitialized memory.
+10-05-27 Rewrote the subshell code to avoid using pipes an many cases.
+10-05-24 Fixed a bug which cause an exception when both -l and -s were
+ specified with typeset -i.
+10-05-21 Inputting of three dimensional indexed arrays with ( ( (...)...)...)
+ was not working and has been fixed.
+10-05-21 A bug in which adding the attributes -Ai to a variable via a name
+ reference could cause the value to display incorrectly has been fixed.
+10-05-21 A bug in which using $var inside ((...)) did not work when var was
+ a hex float variable.
+10-05-20 +The compile option SHOPT_EDPREDICT has been added. When this option
+ is on, as you type a line beginning with a # the following characters
+ are treated as a shell pattern and cause matching lines from the
+ history file to be displayed as a numbered list as you type.
+ You can scroll up and down this list or you can use <ESC>nTAB
+ to make this the current line (n defaults to 1 of omitted) or
+ <ESC>n<cr> to execute.
+10-05-20 A bug which caused an exception when multiple levels of composite
+ functions in arithemtic expressions has been fixed.
+10-05-19 <<< with an empty string no longer gives an error.
+10-05-19 A bug in arithmetic evaluation when a name reference to an array
+ instance was used has been fixed.
+10-05-14 A bug in which the shell treats a valid index array assignment,
+ typeset -a x=(foo (x=3;y=4) bar) as a syntax error has been fixed.
+10-05-13 A bug in creating name references to associative array variable
+ after a lookup of one of its elements has been fixed.
+10-05-12 Two bugs in the handling of function static type variables in
+ subshells have been fixed. One could cause an exception and the
+ other would leave side effects in the parent shell.
+10-05-10 A bug in which static variables in functions were not being saved and
+ restored properly when running subshells has been fixed.
+10-05-05 A bug in which print -v did not work correctly when an operand was an
+ indexed array element referring to a compound variable has been fixed.
+10-05-05 A change to improve performance by special casing empty string
+ assignments to avoid repeated malloc() and free().
+10-05-05 A bug in which creating a name reference to a non-existent associative
+ array element would create the array element has been fixed.
+10-05-04 A bug in which name references to static variables in the static
+ scope were not found has been fixed.
+10-04-30 Do not use socketpair() on systems that implement ioctl(I_PEEK)
+ on pipes.
+10-04-29 +When the current job pool is set, coprocess are run in a job pool.
+10-04-28 A type defined with a member foo that is an associative array without
+ elements followed by an expansion ${bar.foo[a]} and an assignment
+ bar.foo[a]=b, no longer indicates that ${#bar.foo[@]} has 0 members.
+10-04-27 Another bug in which a nested command substitution could hang if it
+ generated too much data has been fixed.
+10-04-26 A type defined with a member that is an indexed array without elements
+ would behave as if the 0th element of each instance was defined after
+ a non-zero element was specified and this has been fixed.
+10-04-26 A bug in which types defined in a subshell were not undefined when
+ the subshell completed has been fixed.
+10-04-23 For file completion in commmand line editing, file names starting
+ with # are now escaped so that they are not treated as comments.
+10-04-23 A bug in which ${t.var:=value}, where t is an instance of a type
+ variable, could assign value to the type variable rather than to
+ the type instance has been fixed.
+10-04-23 +Added &| which can be used in place of | to have portions of a
+ pipeline executed in the pool.
+10-04-22 +The .sh.pool variable was added for use with job pools.
+10-04-22 A bug in which a nested command substitution could hang if it
+ generated too much data has been fixed.
+10-04-20 A bug which corrupted one byte of memory when read was called with
+ reads that did not use a delimiter has been fixed.
+10-04-19 The display of a compound variable with an embedded array with
+ attributes was sometimes not working correctly and has been fixed.
+10-04-16 A bug in which attributes were not be propagated to elements in
+ an associative array has been fixed.
+10-04-15 A bug which caused scripts containing user defined math functions to
+ fail to compile with shcomp has been fixed.
+10-04-15 +Job pools have been added with the SHOPT_COSHELL compilation option.
+ A job pool allows a collection of background jobs to run either locally
+ or remotely and to be managed as a unit. The command '& name ...'
+ creates or uses a named job pool for subsequent background jobs.
+ kill, wait, and jobs allow the pool name as operands.
+10-04-14 A bug in which a coprocess connection could terminate prematurely
+ when running a nested subshell has been fixed.
+10-04-12 +Enumeration constants can be used in arithmetic expressions with the
+ ==, != and = operators when the left hand side is an enum variable
+ and the right hand side is an enumeration constant.
+10-04-07 A bug in which setting the trap on CHLD to ignore could cause
+ an incorrect exit status has been fixed.
+10-04-06 A bug in which LINENO was not incremented for a here-document when
+ the here-document word was followed by a comment has been fixed.
+10-04-06 The optimization that execs the last process of a script rather
+ than creating a new process has been removed when a trap on
+ interrupt has been set.
+10-04-06 Unsetting the 'C', 'A' or 'a' typeset attribute now produces an
+ error message rather than generating an exception.
+10-04-06 A bug in which .sh.name contained the subscript and .sh.subscript
+ was empty in some cases with discipline functions on array instances
+ has been fixed.
+10-04-05 A bug in the edit modes where preceding the interrupt character with
+ the literal next character did not work has been fixed.
+10-04-05 A bug in the creation of type instances of arrays which could cause
+ an exception has been fixed.
+10-03-30 A bug in the display of a compound variable containing an indexed
+ array of compound variables has been fixed.
+10-03-24 +Arithmetic functions can be defined using the shell function syntax,
+ 'function .sh.math.name x y z{...}' , where name is the function name
+ invoked within ((...)) and x y z are long double arguments passed
+ as name references. y and z are used for functions with two and
+ three arguments respectively. The value of the function is the value
+ of the long double .sh.value variable when the function returns.
+10-03-24 A bug in which integer division was mistakenly used when the
+ numerator was a binary operator with the first operand floating
+ point and the second integer, e.g. (.1**3)/3, has been fixed.
+10-03-24 The >; file operator was modified so that the temporary file is
+ created in the same physical directory as file.
+10-03-23 A warning message was added to sh -n when $var was used inside
+ ((...)) instead of var.
+10-03-19 fmin was added to the list of math function on the man page.
+10-03-19 Fixed the return value for unalias when the alias did not
+ exist.
+10-03-19 A bug in which the SHLVL variable exported the value it had on
+ input rather than the incremented value has been fixed.
+10-03-19 A bug which causes whence -q to go into an infinite loop has been
+ fixed.
+10-03-19 Removed space between Stopped message and (SIGTTIN) and (SIGTTOUT).
+10-03-17 Modified profile shell execution so that when builtins that
+ correspond to executable have extended attributes, they are
+ executed by pfksh instead of being treated as built-ins.
+10-03-16 A bug in whence -a which produced duplicate lines of output has
+ been fixed.
+10-03-16 A bug in the handling of process groups in monitor mode for
+ command substitutions has been fixed.
+10-03-15 Fixed a bug in which read -u[fd] could cause the shell to core
+ dump when fd was greater than open_max.
+10-03-15 +Modified the shell I/O so that the shell will not fail if the
+ ulimit for open_max is increased as part of the script.
+10-03-12 A bug in which a here-document containing command substitutions
+ that contained here-documents did not process correctly has been
+ fixed.
+10-03-12 A bug in which the terminal is not restored to canonical mode
+ after read times out when in a multibyte locale with no edit mode
+ enabled has been fixed.
+
+10-03-05 --- Release ksh93t+ ---
+10-03-05 A variable unset memory leak has been fixed and tests/leaks.sh
+ has been added to verify the fix.
+10-03-04 Documentation, comment, and diagnostic spelling typos corrected.
+10-02-14 Fix sh_getenv() initialization to cooperate with the 3d fs.
+10-02-12 A bug in which the get discipline function was not invoked for
+ associative array subscripts for unset array elements has been fixed.
+10-02-12 A bug which could occur if the last line of a script was an eval
+ that executed multiple commands has been fixed.
+10-02-02 A buffer overflow in read and another in binary type base64
+ encoding were fixed.
+10-01-20 A bug in the evaluation of arithmetic expression in which the
+ subscript was evaluated twice for $((foo[x++]++)) has been fixed.
+10-01-19 A workaround for a double-free of a trap in both a subshell and its
+ parent has been added.
+10-01-18 A bug in type handling of typeset -H has been fixed.
+10-01-15 The "adding empty subscript" warning now only emitted with -x set.
+10-01-01 A bug in the parser in which '$((case i in i):;esac);:))' was not
+ parsed correctly was fixed.
+10-01-01 A bug in the parser in which '$(( 2 , 3.6 ))' dumped core for locales
+ with radix char , and thousands separator . has been fixed.
+09-12-28 A bug in the handling of SIGCLD on systems that generated SIGCLD
+ while blocked waiting for process to complete has been fixed.
+09-12-24 ast setlocale() reworked to differentiate env var changes from user
+ override.
+09-12-18 A bug with the SHOPT_BGX option set which disabled traps for signals
+ < SIGCHLD when a trap for a signal > SIGCHLD was set has been fixed.
+09-12-18 A bug where [[ -v var ]] was incorrect for some variables (including
+ LC_* vars) has been fixed.
+09-12-15 A bug that produced a syntax error when a multibyte character
+ straddled a buffer boundary has been fixed.
+09-12-11 A bug where the subscript of an unset variable was not evaluated has
+ been fixed.
+09-12-09 A bug where shcomp dumped core on certain syntax errors has been fixed.
+09-12-07 A bug where a parent shell environment var reset in a subshell removed
+ the value in subsequent children of the parent shell has been fixed.
+09-12-04 A bug in which in some cases a trap in a function executed in
+ a subshell could trigger twice has been fixed.
+09-12-03 A bug in which SHLVL exported with some attributes could cause
+ the shell to abort at startup has been fixed.
+09-12-02 A bug with pipefail in which the shell could hang waiting for the
+ writer to complete before the last reader command has been fixed.
+09-11-30 A bug in which a trap could be inherited by the first element of
+ a pipeline when the command had more than 63 arguments that did
+ not contain any macro expansions has been fixed.
+09-11-19 When read from a terminal was called from with a while or for loop,
+ and an edit mode was on, a backspace or erase no longer will
+ overwrite the prompt.
+09-11-17 +Change .paths parse to handle BUILTIN_LIB=foo BUILTIN_LIB=foo-1.2.
+09-11-17 Inside a function, typeset foo.bar will bind foo to global variable
+ foo if local variable foo does not exist, instead of creating a
+ local variable.
+09-11-17 "read -n1" from the terminal has been fixed to read exactly one character.
+09-11-11 Job control now works for subshell commands, (...).
+09-11-11 If set -e is on for an interactive shell errors in special builtins
+ now cause the shell to exit.
+09-11-11 A bug in which an interrupt handler processed during the read builtin
+ when IFS did not contain a new line has been fixed.
+09-11-09 A bug in which a variable that has been unset in a subshell and then
+ exported from that subshell does not show up in the environment
+ has been fixed.
+09-11-02 ``,2'' is now a valid numeric constant for locales with
+ decimal_point=','.
+09-11-02 A bug where "return" in .profile did not restore the shell state
+ has been fixed.
+09-10-31 A bug that corrupted saved exit status when pids wrapped around has
+ been fixed.
+09-10-26 A bug in { LANG LC_ALL LC_category } ordering has been fixed in -last.
+09-10-16 A bug where notification to libast that the environment has changed
+ has been fixed.
+09-10-12 A bug in which a function loaded in a subshell could leave side
+ effects in the parent shell has been fixed.
+09-10-12 A bug in converting a printf %d operand to a number when the operand
+ contains multiple subscripts for the same variable has been fixed.
+09-10-09 A bug in the handling of the escape character \ in directory prefixes
+ in command completion has been fixed.
+09-10-09 $PATH processing has been changed to delay dir stat() and .paths
+ lookup until the directory is needed in the path search.
+09-09-28 Call the ast setlocale() intercept on unset too.
+09-09-24 A bug in which LANG=foo; LC_ALL=foo; unset LC_ALL; did not revert
+ LC_CTYPE etc. to the LANG value has been fixed.
+09-09-17 A bug in which unsetting SVLVL could cause a script invoked by
+ name without #! to core dump has been fixed.
+09-09-16 A bug in which a pipeline in a here-document could hang when the
+ pipefail option was on has been fixed.
+09-09-09 A bug in the processing of line joining in here documents which
+ occurred when a buffer began with <escape><new-line> has been fixed.
+09-09-09 +A leading ; with commands in a brace group or parenthesis group
+ no longer causes an error. It now is used for the "showme" option.
+09-09-09 A bug in which a subshell containing a background process could
+ block until the background process completed has been fixed.
+09-09-04 A bug in handing ${var[sub]}, where var is a nameref has been fixed.
+09-09-03 A bug which caused an index array to have the wrong number of elements
+ when it was converted from a compound variable by adding an another
+ element has been fixed.
+09-09-03 Specifying export for a compound variable now generates an error.
+09-09-02 $"..." localizations strings are no longer recognized inside `...`.
+09-09-01 A bug in the for loop optimizer in the handling of type static
+ variables has been fixed.
+09-09-01 An error message is not displayed when * and @ are used as subscripts.
+09-09-01 Several bugs in the processing for types that included an associative
+ array of another type has been fixed.
+09-09-01 A bug in the tracing of [[ a < b ]] and [[ a > b ]] has been fixed.
+09-08-26 The .sh.file variable was not being set for a script that was run
+ by name and didn't start with #! and this has been fixed.
+09-08-25 A bug in which a function called to deeply from command substitution
+ did not display an error message has been fixed.
+09-08-24 +When processing profiles, ksh93 now violates the POSIX standard and
+ treats &> as a redirection operator similar to bash.
+09-08-23 A bug in the handling of the trap on SIGPIPE that could lead to a
+ memory fault has been fixed.
+09-08-21 A bug in the handling of the comma operator in arithmetic expressions
+ that could cause a core dump on some systems has been fixed.
+09-08-20 A bug in which a compound variable containing an array of a type
+ that doesn't have any elements now expands correctly.
+09-08-19 A bug which disabled function tracing inside a function after
+ a call to another function has been fixed.
+09-08-19 A bug in which initializing a compound variable instance to another
+ compound variable by name has been fixed.
+09-08-18 A bug in which compound variable instances could be lost after
+ an instance that invoked a type method discipline has been fixed.
+09-08-18 A bug in which a discipline function for a type applied to an
+ array instance when invoked in a function ignored the subscript
+ has been fixed.
+09-08-18 A scoping error with variables in arithmetic expression with
+ type variables when reference with a name reference has been fixed.
+09-08-10 Several memory leaks were fixed primarily related to subshells.
+09-08-06 A bug in which setting the trap on CHLD to ignore could cause
+ a script to hang has been fixed.
+09-07-08 A bug in the processing of name reference assignments when it
+ contained pattern expansions with quoting has been fixed.
+09-06-22 +The default width for typeset -X has been changed so that there
+ should be no loss of precision when converting to a string.
+09-06-19 A bug in the printing of array elements for binary variables with
+ printf %B has been fixed.
+09-06-19 A bug which caused a core dump with trap DEBUG set with an array
+ assignment with no elements has been fixed.
+09-06-19 A bug with read with typeset -b -Z<num> has been fixed.
+09-06-19 Two bugs related to read -b for array variables has been fixed.
+09-06-19 A bug with typeset for compound variables containing arrays of
+ compound variables has been fixed.
+09-06-18 A bug in appending a compound variable to a an indexed array of
+ compound variables has been fixed.
+09-06-18 A bug which occurs when appending a compound variable to an indexed
+ array element has been fixed.
+09-06-18 Setting VISUAL to a value other than one ending in vi or emacs will
+ no longer unset the edit mode.
+09-06-17 A bug in typeset -m when moving a local compound variable to a
+ global compound variable via a name reference has been fixed.
+09-06-17 A bug in appending to nodes of an array of compound variables when
+ addressing them via nameref has been fixed.
+09-06-17 A bug in typeset -p var, when var is an array of compound variables
+ in which the output only contained on array element has been fixed.
+09-06-17 The prefix expansion ${!y.@} now works when y is a name
+ reference to an element of an array.
+09-06-16 Traps on signals that are ignored when the shell is invoked
+ no longer display. Previously they were ignored as required but
+ would be listed with trap -p.
+09-06-12 A bug in vi edit mode in which hitting the up arrow key at the
+ end of a line longer than 40 characters which caused a core dump
+ has been fixed.
+09-06-11 A bug in which "eval non-builtin &" would create two processes,
+ one for the & and another for non-builtin has been fixed.
+09-06-08 When var is an identifier and is unset, ${var} no longer tries to
+ run command substitution on the command var.
+09-06-08 +Process substitution arguments of the form <(command) can now be
+ used following the < redirection operator to redirect from command.
+09-05-13 A bug in which redirections of the form 2>&1 1>&5 inside command
+ substitution could cause the command substitution to hang has been
+ fixed.
+09-05-12 To conform with POSIX, the -u option only checks for unset variables
+ and subscript elements rather than checking for all parameters.
+09-05-12 A bug which could cause a core dump when a variable whose name
+ begins with a . was referenced as part of a name reference inside
+ a function has been fixed.
+09-05-01 A bug that caused a core dump when SIGWINCH was received and
+ both vi and emacs mode were off has been fixed.
+09-04-22 +Default alias compound='typeset -C' added.
+09-04-15 A bug that caused ${...;} to hang for large files has been fixed.
+09-04-08 A change was made in the -n option which printed out an incorrect
+ warning with <>.
+09-04-07 The emacs edit command M-_ and M_. and the vi command _ was fixed
+ to handle the case there there is no history file.
+09-04-05 A bug in handling new-lines with read -n has been fixed.
+09-04-05 The ENV variable defaults the the file named by $HOME/.kshrc rather
+ then to the string $HOME/.kshrc.
+09-03-31 A bug in which a nested command substitution with redirections could
+ leave a file descriptor open has been fixed.
+09-03-24 +ksh now only uses the value of the _ variable on startup if it can
+ verify that it was set by the invoking process rather than being
+ inherited by some other ancestor.
+09-03-24 +When ksh is invoked without -p and ruid!=euid, and the shell is
+ compiled without SHOPT_P_UID or ruid<SHOPT_P_UID, the shell now
+ enables the -p option. The previous version instead set the
+ euid to the ruid as it does for set +p.
+09-03-24 +When SHOPT_P_UID is defined at compile time and the shell is started
+ without -p and ruid!=euid and ruid>=SHOPT_P_UID then euid is set
+ to ruid. A bug that did the wrong test (ruid<SHOPT_P_UID) was fixed.
+09-03-17 +The sleep(1) builtin now accept and ISO 8601 PnYnMnDTnHnMnS
+ duration or date(1) compatible date/time operand.
+09-03-10 If a variable that was left or right justified or zero-filled was
+ changed with a typeset statement that was left or right justified
+ or zero-filled, then the original justification no longer affects
+ the result.
+09-03-10 A bug in the handling of traps when the last command in a script
+ is a subshell grouping command has been fixed.
+09-03-03 A bug in which an expansion of the form ${!prefix@} could generate
+ an exception after the return from a function has been fixed.
+09-02-02 A bug in restricted mode in which the value of ENV could be
+ changed from within a function has been fixed.
+09-02-02 A bug in which an erroneous message indicating that a process
+ terminated with a coredump has been fixed.
+09-02-02 The exit status when exit was called without an argument from
+ a signal handler was incorrect and has been fixed.
+09-02-02 A bug in which a function autoloaded in a subshell could cause
+ a core dump when the subshell completed has been fixed.
+09-02-02 A bug in which 2>&1 inside a command substitution wasn't working
+ correctly has been fixed.
+09-02-02 A bug in the call stack of arithmetic function with 2 args
+ returning int has been fixed.
+09-01-30 A bug in which 'eval print \$0' inside a function was giving the
+ wrong value for $0 has been fixed.
+09-01-28 A bug in which a command substitution could return an exit status
+ of 127 when the pipefail option is enabled has been fixed.
+09-01-26 ksh93 now generates an error message if you attempt to create
+ a global name reference to a local variable.
+09-01-26 +The [[ -v var ]] operator was modified to test for array elements.
+09-01-23 +The redirection operator <>; was added. It is similar to <>
+ except that if the command it is applied to succeeds, the file
+ is truncated to the offset at the command completion.
+09-01-23 The default file descriptor for <> was changed to 1.
+09-01-20 A bug in which the exit status specified in an exit trap was
+ not used when a process terminated with a signal has been fixed.
+09-01-19 A bug in which a signal whose default action is to terminate
+ a process could be ignored when the process is running a sub-shell
+ has been fixed.
+09-01-19 A bug in which sending SIGWINCH to a process that reads from a pipe
+ could cause a memory fault has been fixed.
+09-01-16 +The -R unary operator was added to [[...]] and test to check whether
+ a variable is a name reference.
+09-01-16 +The -v unary operator was added to [[...]] and test to check whether
+ a variable is set.
+09-01-14 The unset built-in was modified to return 0 exit status when
+ unsetting a variable that was unset to conform with the POSIX
+ standard.
+09-01-14 The unset built-in was modified to continue to unset variables
+ after encountering a variable that it could not unset to
+ conform to the POSIX standard.
+09-01-14 The parameter expansion ${x+value} no longer expands the value of
+ the variable x when determining whether x is set or not.
+09-01-13 A bug in which background jobs and pipelines that were not waited
+ for could, in rare instances, cause the shell to go into an infinite
+ loop or fail has been fixed.
+09-01-06 A bug in indexed arrays of compound variables in which referencing
+ non-existent sub-variable in an arithmetic expression could cause
+ the sub-variable to be created has been fixed.
+09-01-05 A bug in which the \ character did not escape extended regular
+ expression pattern characters has been fixed.
+08-12-24 A bug in which killing the last element of a pipe did not cause
+ a write to the pipe to generate a SIGPIPE has been fixed.
+08-12-19 A bug which could cause command substitution to hang when the
+ last element of a pipeline in a command substitution was a built-in
+ and the output was more that PIPE_BUFF.
+08-12-18 A bug which occurs when a here documented marker embedded in a
+ command substitution occurs on a buffer boundary has been fixed.
+08-12-17 A bug in the output of typeset -p for variables that had attributes
+ but did not have a value has been fixed.
+08-12-16 A bug in which a name reference to a name reference variable that
+ references an array element has been fixed.
+08-12-16 A bug in which a variable given both the -A and -C attribute along
+ with an initial assignment didn't work correctly has been fixed.
+08-12-10 The [[ -t fd ]] test was fixed to handle fd>9.
+08-12-10 A bug where function stack misalignment could cause a bus error
+ has been fixed.
+08-12-09 Command completion was changed to use \ to quote special characters
+ instead of quoting the argument in single quotes.
+08-12-07 A bug in typeset -m which occurred when the target node was an
+ associative array element has been fixed.
+08-12-07 A timing bug on some systems (for example darwin), that could
+ cause the last process of a pipeline entered interactively to fail
+ with an "Exec format error" has been fixed.
+08-12-04 +SHOPT_BGX enables background job extensions. Noted by "J" in
+ the version string when enabled. (1) JOBMAX=n limits the number
+ of concurrent & jobs to n; the n+1 & job will block until a
+ running background job completes. (2) SIGCHLD traps are queued
+ so that each completing background job gets its own trap; $! is
+ set to the job pid and $? is set to the job exit status at the
+ beginning of the trap. (3) sleep -s added to sleep until the time
+ expires or until a signal is delivered.
+08-12-04 The sign of floating point zero is preserved across arithmetic
+ function calls.
+08-12-04 A bug that caused print(1) to produce garbled stdout/stderr
+ output has been fixed.
+08-12-04 A bug in which printf "%d\n" "'<euro>'" did not output the
+ numerical value of the EURO symbol, 8354, has been fixed.
+08-11-24 + /dev/fd* and /dev/std* redirections are first attempted with
+ open() to preserve seek semantics; failing that the corresponding
+ file descriptors are dup()'d.
+08-11-20 A bug which could cause a core dump if a function compiled with
+ shcomp was found has been fixed.
+08-11-20 A bug in which jobs were not cleared from the jobs table for
+ interactive shells when the pipefail option is on has been fixed.
+08-11-11 A bug in which a field that was unset in a type definition and later
+ set for an instance could appear twice when displaying the variable
+ has been fixed.
+08-11-11 A bug in which running a simple command & inside a function would
+ not return the correct process id has been fixed.
+08-11-10 A bug in which the exit status of a command could be lost if the pid
+ was that of the most recent command substitution that had completed
+ has been fixed.
+08-11-10 The maximum depth for subshells has been increased from 256 to 65536.
+08-11-06 A bug which could cause a core dump when the _ reference variable was
+ used as an embedded type with a compound assignment has been fixed.
+
+08-10-31 --- Release ksh93t ---
+08-10-31 Variable scoping/initialization bugs that could dump core were fixed.
+08-10-24 The lexer now accepts all RE characters for patterns prefixed
+ with a ksh ~(...) option expression.
+08-10-24 +For ${var/pat/sub} \0 in sub expands to the text matched by pat.
+08-10-18 A bug in array scoping that could dump core has been fixed.
+08-10-10 read -n and -N fixed to count characters in multibyte locales.
+08-10-10 A bug that mishandled _.array[] type references has been fixed.
+08-10-09 +${.sh.version} now contains a concatenation of the following (after
+ 'Version') denoting compile time features:
+ A SHOPT_AUDIT
+ B SHOPT_BASH
+ L SHOPT_ACCT
+ M SHOPT_MULTIBYTE
+08-10-09 A bug that caused subshell command substitution with redirection
+ to hang has been fixed.
+08-10-08 Output errors, other than to stderr, now result in a diagnostic.
+08-10-08 ksh93 now supports types that contain arrays of other types as
+ members. Earlier versions core dumped in this case.
+08-10-05 A bug which caused the shell to emit a syntax error for an arithmetic
+ statement of the form (( var.name[sub] = value)) has been fixed.
+08-10-01 A bug that caused subshell command substitution to hang has
+ been fixed.
+08-09-29 When the -p export option of typeset is used with other options,
+ only those variables matching the specified options are displayed.
+08-09-29 When the shell reads the environment and finds variables that are
+ not valid shell assignments, it now passes these on to subsequent
+ commands rather than deleting them.
+08-09-29 A bug in the display of compound variables containing an indexed
+ array of compound variables has been fixed.
+08-09-29 A bug in the display of compound variables containing an associative
+ array with a subscript containing a . in the name has been fixed.
+08-09-26 A core dump in the subshell environment restore has been fixed.
+08-09-24 $(...) has been fixed to properly set the exit status in $?.
+08-09-23 $(<...) with IFS=$'\n\n' has been fixed to retain all but the last
+ of multiple trailing newlines.
+08-09-23 The -p option to typeset when used with other attributes, restricts
+ the output to variables with the specified attributes.
+08-09-22 A bug that sometimes lost the exit status of a job has been fixed.
+08-09-21 A bug that retained trailing command substitution newlines in
+ cases where the command caused the shell to fork has been fixed.
+08-09-19 type, whence -v, and command -v were fixed to comply with POSIX
+ by writing 'not found' diagnostics to the standard error.
+08-09-18 test and [...] were fixed to comply with POSIX in the case
+ of test '(' binop ')' where binop is a valid binary test operator.
+08-09-16 +If a method discipline named create is specified when defining a
+ type, this function will be called when an instance is created.
+08-09-15 +The variable _ is now set as a reference to the compound variable
+ when defining a compound variable or a type.
+08-09-10 The shell now prints an error message when the type name specified
+ for an indexed array subscript is not an enumeration type.
+08-09-10 A bug in which a subshell that spawned a background process could
+ loose output that was produced after the foreground completed
+ has been fixed.
+08-09-10 A timing bug on some systems that could cause coprocesses started by a
+ subshell to not clean up and prevent other coprocesses has been fixed.
+08-09-09 The typeset -m option is now able to rename array elements from
+ the same array.
+08-09-09 The exit status of 2 from the DEBUG trap causes the next command
+ to be skipped. An exit value of 255 from a DEBUG trap called from
+ a function causes the function to return.
+08-09-08 A bug in which a coprocess created in a subshell that did not
+ complete when the subshell terminated could prevent a coprocess
+ from being created in the parent shell has been fixed.
+08-09-05 An assignment of the form name1=name2 where name1 and name2
+ are both compound variables causes name1 to get a copy of name2.
+ name1+=name2 causes name2 sub-variables to be appended to name1.
+08-09-05 A bug in which unsetting a compound variable did not unset all
+ the sub-variables has been fixed.
+08-09-01 A bug in the subshell cleanup code that could cause SIGSEGV has
+ been fixed.
+06-08-26 +The SHLVL variable which is an environment variable used by bash
+ and zsh that gets incremented when the shell starts.
+08-08-25 +For an indexed array, a negative subscript now refers to offsets
+ from the end so that -1 refers to the last element.
+08-08-24 An alignment error for shorts on 64 bit architectures has been fixed.
+08-08-22 If oldvar is a compound variable, typeset -C newvar=oldvar creates
+ newvar as a copy of oldvar.
+08-08-19 +The ALRM signal no longer cause the sleep builtin to terminate.
+08-08-13 When used in an arithmetic expression, the .sh.version variable
+ now produces a number that will be increasing for each release.
+08-08-11 A bug in which type instantiation with a compound assignment in
+ a dot script in which the type is defined has been fixed.
+08-08-07 +The -m option has been added to typeset to move or rename a
+ variable. Not documented yet.
+08-08-06 A bug in read when used in a loop when a prompt was specified
+ when reading from a terminal has been fixed.
+08-08-01 A bug with the pipefail option in which a nested pipeline could
+ cause an asynchronous command to block has been fixed.
+08-08-01 A for loop optimizer bug that treats .sh.lineno as an invariant
+ has been fixed.
+08-07-30 A bug in which expanding compound variable that had a get discipline
+ from with a here document could cause a syntax error has been fixed.
+08-07-18 A bug in which a nameref caused a local variable to be created
+ rather than binding to an existing variable in the global scope
+ has been fixed.
+08-07-17 A bug which occurred when a nameref was created from within a
+ function that was part of a pipeline has been fixed.
+08-07-14 +The compile option SHOPT_STATS was added. With this option the
+ compound variable .sh.stats keeps usage statistics that could help
+ with performance tuning.
+08-07-10 +The output of set now always uses a single line for each variable.
+ For array variables, the complete set of values is now displayed.
+08-07-09 +The typeset -C option can be used with arrays to indicate that
+ each element should default to a compound variable.
+08-07-08 +The %B format now outputs compound variables and arrays. The
+ alternate flag # can be used to cause output into a single line.
+08-07-03 When the window change signal, WINCH, is received, the current
+ edit line is redrawn in place.
+08-07-01 A bug in the handling of shared variables when inside an embedded
+ type has been fixed.
+08-06-29 A bug in multiline edit mode which occurred when the prompt length
+ was three characters or less has been fixed.
+08-06-23 A bug in which the SIGCLD was not be triggered when background
+ jobs completed has been fixed.
+08-06-23 _KSH_VERSION added as a name reference to .sh.version.
+08-06-20 type now outputs 'special builtin' for special builtins.
+08-06-19 A couple of bugs in multi-dimensional arrays have been fixed.
+08-06-19 A bug in which a syntax error in a dot script could generated
+ a syntax error in the next subsequent command has been fixed.
+08-06-17 Reduced the maximum function call depth to 2048 to avoid exceptions
+ on some architectures.
+08-06-16 A bug in which printf "%B" could generate an exception when the
+ specified variable was not set has been fixed.
+08-06-16 +When typeset -p is followed by variable names, it now displays
+ the attributes names and values for the specific names.
+08-06-14 A bug that could effect the drawing of the screen from multiline
+ emacs or gmacs mode when walking up the history file has been fixed.
+08-06-13 A bug in which a compound variable defined in a subshell could
+ have side effects into the parent shell has been fixed.
+08-06-13 A number of bugs related to using .sh.level to set the stack from
+ for DEBUG traps have been fixed.
+08-06-13 +The .sh.lineno variable has been added. When .sh.level is changed
+ inside a DEBUG trap, the .sh.lineno contains the calling line number
+ for the specified stack frame.
+08-06-13 The .sh.level variable has been documented and now works.
+08-06-11 +The -C option has been added to read for reading compound command
+ definitions from a file.
+08-06-11 +The . command is now permitted inside a compound command definition.
+ The dot script can contain declaration commands and dot commands.
+08-06-09 +Add -C option to typeset so that typeset -C foo, is equivalent
+ to foo=().
+08-06-09 Added -n warning message for typeset option orderings that are valid
+ with ksh88 but not valid with ksh93, for example Lx5.
+08-06-09 A bug in which the return value for an assignment command containing
+ a command substitution with that failed was zero when the assignment
+ contained redirections has been fixed.
+08-06-09 A bug in the quoting of $ inside a ERE pattern ~(E)(pattern)
+ has been fixed.
+08-06-06 A bug when processing `` command substitution with the character
+ sequence \$' has been fixed.
+08-06-02 +When defining a type, the typeset -r attribute causes this field
+ to be required to be specified for each instance of the type and
+ does not allow a default value.
+08-06-02 Several bugs in which compound variables were modified by
+ subshells have been fixed.
+08-05-22 +The ceil function has been added to the math functions.
+08-05-21 A bug in which a name reference defined in a function and passed
+ as an argument to another function could cause an incorrect binding.
+08-05-21 A bug in freeing compound variables that are local to functions
+ has been fixed.
+08-05-19 +The array expansions ${array[sub1..sub2]} and ${!array[sub1..sub2]}
+ to expand to the value (or subscripts) for array between sub1 and
+ sub2 inclusive. For associative arrays, the range is based on
+ location in the POSIX locale. The .. must be explicit and cannot
+ result from an expansion.
+08-05-15 The trap on SIGCLD is no longer triggered by the completion of
+ the foreground job as with ksh88.
+08-05-14 A bug in the implementation of the editing feature added on
+ 07-09-19 in emacs mode has been fixed.
+08-05-12 A bug in processing the test built-in with parenthesis has been
+ fixed.
+08-05-12 The unset built-in now returns non-zero when deleting an array
+ subscript that is not set.
+08-05-08 +Changing the value of HISTFILE or HISTSIZE will cause the old
+ history file to be close and reopened with the new name or size.
+08-05-08 When FPATH is changed functions that were found via a path search
+ will be searched for again.
+08-05-08 A parser bug in which reserved words and labels were recognized
+ inside compound indexed array assignment after a new-line has
+ been fixed.
+08-05-07 A bug in getopts when handling numerical option arguments has
+ been fixed.
+08-05-07 +The typeset -S option was added for variables outside type
+ definitions to provide a storage class similar to C static
+ inside a function defined with function name. When outside
+ type definitions and outside a function, the -S option cause
+ the specified variable so be unset before the assignment and
+ before the remaining attributes are supplied.
+08-05-07 A bug that affected the cursor movement in multiline mode when
+ a character was deleted from near the beginning of the any
+ line other than the first.
+08-05-01 In multiline edit mode, the refresh operation will now clear
+ the remaining portion of the last line.
+08-05-01 A bug in computing prompt widths for the edit modes for prompts
+ with multibyte characters has been fixed.
+08-05-01 A bug in the multiline edit mode which could cause the current
+ line to be displayed incorrectly when moving backwards from third
+ or higher line to the previous line has been fixed.
+08-05-01 A bug in which options set in functions declared with the function
+ name syntax were carried across into functions invoked by these
+ functions has been fixed.
+08-04-30 A bug which could cause a coprocess to hang when the read end
+ is a builtin command has been fixed.
+08-04-30 +The emacs and vi editors have been modified to handle window
+ change commands as soon as they happen rather than waiting for
+ the next command.
+08-04-28 A bug in which ${!x} did not expand to x when x was unset has been
+ fixed.
+08-04-27 A bug in which the assignment x=(typeset -a foo=([0]=abc)) created
+ x.foo as an associative array has been fixed.
+08-04-25 A bug in which $# did not report correctly when there were more
+ than 32K positional parameters has been fixed.
+08-04-04 Choose the name _ as the sub-variable that holds type or instance
+ specific data used by discipline functions.
+08-03-27 A bug in which the terminal group was not given back to the parent
+ shell when the last part of a pipeline was handled by the parent shell
+ and the other parts of the pipeline complete has been fixed.
+ The symptom was that the pipeline became uninterruptable.
+08-03-25 A bug in restricted mode introduced in ksh93s that caused scripts
+ that did not use #! to executed in restricted mode has been fixed.
+08-03-25 A bug in which the pipefail option did not work for a pipeline
+ within a pipeline has been fixed.
+08-03-24 A bug in which OPTIND was not set correctly in subshells has
+ been fixed.
+08-03-24 A bug which could cause a memory exception when a compound variable
+ containing an indexed array with only element 0 defined was expanded.
+08-03-20 A bug in which ${!var[sub].*} was treated as an error has been fixed.
+08-03-20 Associative array assignments of the form ([name]=value ...)
+ now allow ; as well as space tab and new line to separate elements.
+08-03-18 A buffering problem in which standard error was sometimes
+ not flushed before sleep has been fixed.
+08-03-17 A bug in which a signal sent to $$ while in a subshell would be
+ sent to the subshell rather than the parent has been fixed.
+08-03-17 + A --default option added to set(1) to handle set +o POSIX semantics.
+ set --state added as a long name alias for set +o.
+08-03-14 A bug in which using monitor mode from within a script could
+ cause the terminal group to change has been fixed.
+08-03-10 The new ${...} command substitution will treat the trailing }
+ as a reserved word even if it is not at the beginning of a command,
+ for example, ${ date }.
+08-03-10 If the name of the ENV begins with /./ or ././ then the
+ /etc/ksh.kshrc file will not be executed on systems that support
+ this interactive initialization file.
+08-03-07 A bug in which ksh -i did not run the ENV file has been fixed.
+08-03-07 A bug in which ulimit did not always produce the same output as
+ ulimit -fS has been fixed.
+08-03-04 A bug in multiline mode in emacs and vi mode which could cause the
+ cursor to be on the wrong line when interrupt was hit has been fixed.
+08-03-03 The change made in ksh93s+ on 07-06-18 in which braces became
+ optional for ${a[i]} inside [[...]] was restored in the case
+ where the argument can be a pattern.
+08-03-03 A bug in which creating a name reference to an associative array
+ instance would fail when the subscript contained characters [ or
+ ] has been fixed.
+08-02-29 +The redirection operator >; has been added which for non-special
+ files, generates the output in a temporary file and writes the
+ specified file only of the command has completed successfully.
+08-02-15 A bug in ${var/pattern/string} for patterns of the form ?(*) and +(*)
+ has bee fixed.
+08-02-07 A bug in which test \( ! -e \) produced an error has been fixed.
+08-02-14 +The typeset -a option can now optionally be followed by the name
+ of an enumeration type which allows subscripts to be enumerations.
+08-02-14 +The enum builtin which creates enumeration types has been added.
+08-02-12 The backoff logic when there are no more processes has been fixed.
+08-02-07 The -X option has been added to typeset. The -X option creates
+ a double precision number that gets displayed using the C99 %a
+ format. It can be used along with -l for long double.
+08-01-31 The -T option to typeset has been added for creating typed
+ variables. Also the -h and -S options have been added to
+ typeset that are only applicable when defining a type.
+08-01-31 The prefix expansion operator @ has been added. ${@name}
+ expands to the type of name or yields the attributes.
+07-11-15 A bug in the macro expander for multibyte characters in which
+ part of the character contains a file pattern byte has been fixed.
+07-10-03 A bug in which : was not allowed as part of an alias name has been
+ fixed.
+07-09-26 A bug in which appending a compound variable to a compound variable
+ or to an index array didn't work has been fixed.
+07-09-19 In both emacs and vi edit mode, the escape sequence \E[A (usually
+ cursor up, when the cursor is at the end of the line will fetch
+ the most recent line starting with the current line.
+07-09-18 The value of ${!var} was correct when var was a reference to an
+ array instance.
+07-09-18 The value of ${!var[sub]} was not expanding to var[sub] and this
+ was fixed. It also fixed ${name} where name is a name reference
+ to var[sub].
+07-09-18 +It is now legal to create a name reference without an initialization.
+ It will be bound to a variable on the first assignment.
+07-08-30 +A discipline function can be invoked as ${x.foo} and is equivalent
+ to ${ x.foo;} and can be invoked as x.foo inside ((...)).
+07-07-09 A bug in which typeset -a did not list indexed arrays has been
+ fixed.
+07-07-03 +The command substitution ${ command;} has been added. It behaves
+ like $(command) except that command is executed in the current
+ shell environment. The ${ must be followed by a blank or an
+ operator.
+
+08-04-17 --- Release ksh93s+ ---
+08-04-17 A bug in which umask was not being restored correctly after a
+ subshell has been fixed.
+08-04-15 A bug in which sending a STOP signal to a job control shell started
+ from within a shell function caused cause the invoking shell to
+ terminate has been fixed.
+08-04-11 A bug which caused $(exec > /dev/null) to go into an infinite loop
+ has been fixed.
+08-03-27 A bug in which typeset -LZ was being treated as -RZ has been fixed.
+08-03-06 A bug with ksh -P on systems that support the the profile shell,
+ in which it would exit after running a non-builtin has been fixed.
+08-01-31 A bug in which command substitution inside ((...)) could cause
+ syntax errors or lead to core dumps has been fixed.
+08-01-17 A bug in which discipline functions could be deleted when invoked
+ from a subshell has been fixed.
+08-01-17 A bug in which a command substitution consisting only of
+ assignments was treated as a noop has been fixed.
+08-01-17 A bug in which discipline functions invoked from withing a
+ compound assignment could fail has been fixed.
+08-01-16 Incomplete arithmetic assignments, for example ((x += )), now
+ generate an error message.
+08-01-16 A bug in which a set discipline defined for a variable before
+ an array assignment could cause a core dump has been fixed.
+08-01-03 A bug in on some systems in which exit status 0 is incorrectly
+ returned by a process that catches the SIGCONT signal is stopped
+ and then continued.
+07-12-13 A race condition in which a program that has been stopped and then
+ continued could loose the exit status has been fixed.
+07-12-12 Code to check for file system out of space write errors for all
+ writes has been added.
+07-12-11 A bug in the macro expander for multibyte characters in which
+ part of the character contains a file pattern byte has been fixed.
+07-12-06 A bug in the emacs edit mode when multiline was set that output
+ a backspace before the newline to the screen has been fixed.
+07-12-04 A bug in which using <n>TAB after a variable name listing expansion
+ in the edit modes would cause the $ to disappear has been fixed.
+07-11-28 A bug in which setting IFS to readonly could cause a subsequent
+ command substitution to fail has been fixed.
+07-11-27 A work around for a gcc 4.* C99 "feature" that could cause a job
+ control shell to go into an infinite loop by adding the volatile
+ attribute to some auto vars in functions that call setjmp().
+07-11-27 A bug in which the shell could read ahead on a pipe causing the
+ standard input to be incorrectly positioned has been fixed.
+07-11-27 A bug in which compound variable UTF-8 multibyte values were not
+ expanded or traced properly has been fixed.
+07-11-21 A bug where an unbalanced '[' in a command argument was not treated
+ properly has been fixed.
+07-11-15 A bug in which compatibility mode (no long option names) getopts(1)
+ incorrectly set the value of OPTARG for flag options has been fixed.
+07-11-15 A bug in which "hash -- name" treated "--" as an invalid name operand
+ has been fixed.
+07-11-15 typeset now handles "-t -- [-r] [--]" for s5r4 hash(1) compatibility.
+07-11-15 A bug in which the umask builtin mis-handled symbolic mode operands
+ has been fixed.
+07-11-15 Bugs in which shell arithmetic and the printf builtin mis-handled the
+ signs of { -NaN -Inf -0.0 } have been fixed.
+07-11-15 +The full { SIGRTMIN SIGRTMIN+1 ... SIGRTMAX-1 SIGRTMAX } range
+ of signals, determined at runtime, are now supported.
+07-11-15 A bug in which creating an index array with only subscript 0 created
+ only a simple variable has been fixed.
+07-11-14 A bug in which appending to an indexed array using the form
+ name+=([sub]=value) could cause the array to become an associative
+ array has been fixed.
+07-11-14 A bug in which typeset without arguments could coredump if a
+ variable is declared as in indexed array and has no elements has
+ been fixed.
+07-11-14 A bug in which creating a local SECONDS variable with typeset in
+ a function could corrupt memory has been fixed.
+07-11-14 A bug which could cause a core dump when a script invoked by name
+ from a function used compound variables has been fixed.
+07-11-05 A bug in which printf %d "'AB" did not diagnose unconverted characters
+ has been fixed.
+07-11-05 printf %g "'A" support added for all floating point formats.
+07-11-01 A bug in which typeset -f fun did not display the function definition
+ when invoked in a subshell has been fixed.
+07-10-29 The sleep builtin was fixed so that all floating point constants
+ are valid operands.
+07-10-10 A bug in which the locale was not being restored after
+ LANG=value command has been fixed.
+07-09-20 A bug in which a nameref to a compound variable that was local
+ to the calling function would not expand correctly when displaying
+ is value has been fixed.
+07-09-19 A bug which cause cause a core dump if .sh.edchar returned
+ 80 characters or more from a keyboard trap has been fixed.
+07-09-14 A bug in which could cause a core dump when more than 8 file
+ descriptors were in use has been fixed.
+07-09-10 A bug in which creating a name reference to an instance of
+ an array when the array name is itself a reference has been fixed.
+07-09-10 The file completion code has been modified so that after an = in
+ any word, each : will be considered a path delimiter.
+07-09-06 A bug in which subprocess cleanup could corrupt the malloc() heap
+ has been fixed.
+07-08-26 A bug in which a name reference to an associative array instance
+ could cause the subscript to be evaluated as an arithmetic expression
+ has been fixed.
+07-08-22 A bug in which the value of an array instance was of a compound
+ variable was not expanded correctly has been fixed.
+07-08-14 A bug which could cause a core dump when a compound assignment was
+ made to a compound variable element with a typeset -a attribute
+ has been fixed.
+07-08-08 A bug in which a trap ignored in a subshell caused it to be
+ ignored by the parent has been fixed.
+07-08-07 A bug in which the set command would generated erroneous output
+ for a variable with the -RZ attribute if the variable name had been
+ passed to a function has been fixed.
+07-08-02 A bug in which read x[1] could core dump has been fixed.
+07-08-02 A second bug in which after read x[sub] into an associative array
+ of an element that hasn't been assigned could lead to a core dump
+ has been fixed.
+07-07-31 A bug in which a pipeline that completed correctly could have
+ an exit status of 127 when pipefail was enabled has been fixed.
+07-07-09 +The SHOPT_AUDIT compile option has been added for keyboard logging.
+07-06-25 In vi insert mode, ksh no longer emits a backspace character
+ before the carriage return when the newline is entered.
+07-06-25 A bug in which pipefail would cause a command to return 0
+ when the pipeline was the last command and the failure happened
+ on a component other than the last has been fixed.
+07-06-25 A bug in the expansion of ${var/pattern/rep} when pattern or rep
+ contained a left parenthesis in single quotes has been fixed.
+07-06-18 The braces for a subscripted variable with ${var[sub]} are now
+ optional when inside [[...]], ((...)) or as a subscript.
+07-05-28 A bug in brace expansion in which single and double quotes did
+ not treat the comma as a literal character has been fixed.
+07-05-24 The -p option of whence now disables -v.
+07-05-23 Several bug fixes in compound variables and arrays of arrays
+ have been made.
+07-05-15 A bug in which the %B format of printf was affected by the
+ locale has been fixed.
+07-05-14 A bug in which \ was not removed in the replacement pattern with
+ ${var/pattern/rep} when it was not followed by \ or a digit has
+ been fixed.
+07-05-10 A bug in which ksh -R file core dumped if no script was specified
+ has been fixed. it not displays an error message.
+07-05-07 Added additional Solaris signals to signal table.
+07-04-30 A bug in which a pipeline with command substitution inside a
+ function could cause a pipeline that invokes this function to
+ hang when the pipefail option is on has been fixed.
+07-04-30 +Added -q to whence.
+07-04-18 A small memory leak with each redirection of a non-builtin has
+ been fixed.
+07-03-08 A bug in which set +o output command line options has been fixed.
+07-03-08 A bug in which an error in read (for example, an invalid variable
+ name), could leave the terminal in raw mode has been fixed.
+07-03-06 A bug in which read could core dump when specified with an array
+ variable with a subscript that is an arithmetic expression has
+ been fixed.
+07-03-06 Several serious bugs with the restricted shell were reported and
+ fixed.
+07-03-02 If a job is stopped, and subsequently restarted with a CONT
+ signal and exits normally, ksh93 was incorrectly exiting with
+ the exit status of the stop signal number.
+07-02-26 +M-^L added to emacs mode to clear the screen.
+07-02-26 A bug in which setting a variable readonly in a subshell would
+ cause an unset error when the subshell completed has been fixed.
+07-02-19 +The format with printf uses the new = flag to center the output.
+07-02-19 A bug in which ksh93 did not allow multibyte characters in
+ identifier names has been fixed.
+07-02-19 A bug introduced in ksh93 that causes global compound variable
+ definitions inside functions to exit with "no parent" has been fixed.
+07-02-19 A bug in which using compound commands in process redirection
+ arguments would give syntax errors <(...) and >(...) has been fixed.
+07-01-29 A bug which caused the shell to core dump which can occur when a
+ built-in exits without closing files that it opens has been fixed.
+07-01-26 A bug in which ~(E) in patterns containing \ that are not inside ()
+ has been fixed.
+
+06-12-29 --- Release ksh93s ---
+06-12-29 A bug in which the value of IFS could be changed after a command
+ substitution has been fixed.
+06-12-22 +/dev/(tcp|udp|sctp)/HOST/SEVRICE now handles IPv6 addresses on
+ systems that provide getaddrinfo(3).
+06-12-19 +A -v option was added to read. With this option the value of
+ the first variable name argument will become the default value
+ when read from a terminal device.
+06-11-20 A bug in which "${foo[@]:1}}" expands a null argument (instead of
+ no argument), when foo[0] is not empty has been fixed.
+06-11-16 The discipline functions have been modified to allow each subscript
+ to act independently. Currently the discipline function will not
+ be called when called from a discipline function of the same variable.
+06-11-14 A bug which could cause a core dump if a file descriptor for
+ an internal file was closed from with a subshell has been fixed.
+06-10-30 +The redirections <# pattern, and <## pattern have been added.
+ Both seek forward to the beginning of the next line that contains
+ the pattern. The <## form copies the skipped portion to standard
+ output.
+06-10-26 +On systems that support stream control transport, the virtual file
+ name /dev/sctp/host/port can now be used to establish connections.
+06-10-26 +The printf modifier # when used with d produces units in thousands
+ with a single letter suffix added. The modifier # when used with
+ the i specification provides units of 1024 with a two letter suffix.
+06-10-24 The value of $! is now set to the process id of a job put
+ into the background with the bg command as required by POSIX.
+06-10-23 A bug in which the value of $! was affected by a background
+ job started from a subshell has been fixed.
+06-10-23 A bug in ${var:offset:len} in multibyte locales has been fixed.
+06-10-15 +The remaining math functions from C99 were added for any system
+ that supports them.
+06-10-13 The klockwork.com software detected a few coding errors that
+ have been fixed.
+06-10-12 A bug when skipping over `...` with ${x:=`...`} when x is set
+ has been fixed.
+06-10-11 A bug in process floating constants produced by the %a format
+ of printf has been fixed.
+06-10-06 A bug in which IFS was not being restored correctly in some
+ cases after a subshell has been fixed.
+06-10-06 A bug in which pipefail was not detecting some failures in
+ pipelines with 3 or more states has been fixed.
+06-10-03 A bug in the processing of >(...) with builtins which could
+ cause the builtin to hang has been fixed.
+06-10-03 A bug in the for loop optimizer which causes >(...) process
+ substitution to be ignored has been fixed.
+06-09-17 +The -a option was added to typeset for indexed arrays. This
+ is only needed when using the ([subscript]=value ...) form.
+06-09-06 +The showme option was added. Each simple command not beginning
+ with a redirection and not occurring with in the while, until, if,
+ select condition can be preceded by a semi-colon which will
+ be ignored when showme is off. When showme is on, any command
+ preceded by a colon will be traced but not executed.
+06-08-16 +As a new feature, a leading ~(N) on a pattern has no effect
+ except when used for file expansion. In this case if not
+ matches are found, the pattern is replaced by nothing rather
+ than itself.
+06-08-11 A bug in the expansion of ${.sh.match[i]:${#.shmatch[i]}} has
+ been fixed.
+06-08-10 +The read builtin options -n and -N have been modified to treat
+ the size as characters rather than bytes unless storing into a
+ binary (typeset -B) variable.
+06-07-27 +When the here document operator << is followed directly by a #
+ rather than a -, the first line of the here-document determines
+ how much whitespace is removed for each line.
+06-07-26 A bug in the C-shell history (enabled with set -H) in which the
+ history event !$ was not processed has been fixed.
+06-07-21 A bug on some systems in which assigning PATH on a command line
+ would not take effect has been fixed.
+06-07-20 Add ksh93 and rksh93 as allowable names for ksh binaries.
+06-07-20 Removed the SHOPT_OO compilation option which was only partially
+ implemented.
+06-07-20 The ability to use egrep, grep, and fgrep expressions within
+ shell patterns has been documented.
+06-07-17 A bug with arithmetic command expressions for locales in which
+ the comma is a thousands separator has been fixed.
+06-07-13 +The default HISTSIZE was increased from 128 to 512.
+06-07-13 A multibyte problem with locales that use shift codes has been fixed.
+06-06-23 A number of bug fixes for command, file, and variable completion
+ have been mode.
+06-06-20 +Floating point division by zero now yields the constant Inf or -Inf
+ and floating functions with invalid arguments yield NaN.
+06-06-20 +The floating point constants Inf and NaN can be used in arithmetic
+ expressions.
+06-06-20 +The functions isinf(), isnan(), tanhl() have been added for
+ arithmetic expressions.
+06-06-13 Internal change to use ordering for variables instead of hashing
+ to speed up prefix matching.
+06-06-13 A window between fork/exec in which a signal could get lost
+ and cause a program to hang has been eliminated
+06-06-13 A bug in edit completion with quoted strings has been fixed.
+06-06-07 The restricted options can now be enabled by set as well as on
+ the command line. Once set, it can not be disabled.
+06-06-04 Modified built-in binding so that for systems for which /bin
+ and /usr/bin are the same, a builtin bound to /bin will get
+ selected when either /bin or /usr/bin is scanned.
+06-06-04 +Added literal-next character processing for emacs/gmacs mode.
+ This change is not compatible with earlier versions of ksh93
+ and ksh88 when the stty lnext is control-v. The sequence
+ escape-control-v will display the shell version.
+06-05-31 +Modified emacs and vi mode so that entering a TAB after a partial
+ TAB completion, generates a listing of possible completions.
+ After the second TAB, a number followed by a TAB will perform
+ the completion with the corresponding item.
+06-05-19 +Modified arithmetic so that conversions to strings default to
+ the maximum number of precision digits.
+06-05-16 Bug fixes for multibyte locales.
+06-05-10 The =~ operator was added to [[...]] and [[ string ~= ERE ]]
+ is equivalent to [[ string == ~(E)ERE ]].
+06-04-25 A bug in the vi edit mode which could cause the shell to core dump
+ when switching from emacs mode.
+06-04-17 A bug in which using LANG or LC_ in assignment lists with builtins
+ did not restore the localed correctly has been fixed.
+06-04-04 A bug in which discipline functions could not be added to variables
+ whose names started with .sh has been fixed.
+06-03-28 +The -s option to typeset was added to modify -i to indicate short
+ integers.
+06-03-28 A bug in which variables assignment lists before functions
+ defined with function name were not passed on the functions
+ invoked by this function has been fixed.
+06-03-28 A bug in which name references defined within a function defined
+ with function name could not be used with compound variables has
+ been fixed.
+06-03-27 A bug in which read <&p (print >&p) would cause the coprocess input
+ (output) pipe to close before reading from (after writing to)
+ it has been fixed.
+06-02-28 A bug in which stopping a job created with the hist builtin command
+ would create a job that could not be restarted has been fixed.
+
+06-01-24 --- Release ksh93r ---
+06-01-24 A bug in which running commands with standard output closed would
+ not work as expected has been fixed.
+06-01-23 A bug in which print -u<n> could fail when file descriptor <n> was
+ open for writing has been fixed.
+06-01-19 The ?: arithmetic operator fixed to work when the operation after
+ the colon was an assignment.
+05-12-24 A bug which could lead to a core dump when elements of a compound
+ variable were array elements, i.e. foo=(bar=(1 2)), has been fixed.
+05-12-13 An arithmetic bug in which x+=y+=z was not working has been fixed.
+05-12-13 An arithmetic bug in which x||y was returning x when x was non-zero
+ rather than 1 has been fixed.
+05-12-07 +The aliases for integer and float have been changed to use attributes
+ -li and -lE to handle long long and long double types.
+05-12-07 +The histexpand (-H) option has been added which allows C-shell
+ style history expansions using the history character !.
+05-12-07 +The multiline option was added which changes that way the edit
+ modes handle lines longer than the window width. Instead of
+ horizontal scrolling, multiple lines on the screen are used.
+05-12-05 The whence builtin now returns an absolute pathname when the
+ command is found in the current directory.
+05-11-29 A bug which caused ksh -c '[[ ! ((' to core dump rather than
+ report a syntax error has been fixed.
+05-11-29 A bug when reading fixed length records into typeset -b variables
+ which caused a zero byte to terminate the value has been fixed.
+05-11-22 +The ability to seek to an offset within a file has been added
+ with the new I/O redirection operators, <# and >#. Currently,
+ these redirection operators must be followed by ((expr))
+ but in a future release, it should be able to used to seek forward
+ to the specified shell pattern. In addition $(n<#) expands to the
+ current byte offset for file descriptor n.
+05-11-22 +The .sh.match array variable is now set after each [[ ... ]]
+ pattern match. Previously it was only set for substring matches.
+05-10-17 A bug in which the library path variable could be prefixed
+ with a directory when a .path file was not encountered in
+ the directory of the executable has been fixed.
+05-09-15 A for/while loop optimizer bug in which $OPTIND was not
+ correctly expanded has been fixed.
+05-09-05 A bug in which a history command that invoked a history
+ command could go into an infinite loop has been fixed.
+05-08-31 +In the case that IFS contains to adjacent new-lines so that
+ new-line is not treated as a space delimiter, only a single
+ new-line is deleted at the end of a command substitution.
+05-08-19 +When a tilde substitution expands to the / directory and is
+ followed by a /, it is replaced by the empty string.
+05-08-16 A bug in which n<&m did not synchronize m has been fixed.
+05-08-16 A bug in which process substitution ( <() and >() ) was not
+ working within for and while loops has been fixed.
+05-07-24 A bug in which the pattern ~(E)(foo|bar) was treated as a syntax
+ error has been fixed.
+05-07-24 A bug in completion with <n>=, where n was the one of the
+ previous selection choices has been fixed.
+05-07-21 A bug with multibyte input when no edit mode was specified which
+ caused the input line to shift left/right has been fixed.
+05-06-24 A race condition which could cause the exit status to get lost
+ on some fast systems has been fixed.
+05-06-21 A bug in which nested patterns of the form {m,n}(pat) would cause
+ syntax errors has been fixed.
+05-06-21 A bug in the macro expander has been fixed which could cause a
+ syntax error for an expansion of the form ${x-$(...)} when
+ x is set and the command substitution contained certain strings.
+05-06-08 +On systems for which echo does not do System V style \ expansions,
+ the -e option was added to enable these expansion.
+05-06-08 A bug in which ${var op pattern} to not work when inside an
+ arithmetic expression has been fixed.
+05-05-23 +An extension to shell patterns that allows matching of nested
+ groups while skipping over quoted strings has been added.
+05-05-18 A bug in which the line number for errors was not correct for
+ functions loaded from FPATH has been fixed.
+05-04-18 A bug in which the exit status $? is not set when a trap triggered
+ by the [[...]] command is executed has been fixed.
+05-04-08 +Redirection operators can be directly preceded with {varname}
+ with no intervening space, where varname is a variable name which
+ allows the shell to select a file descriptor > 10 and store it
+ into varname.
+05-04-08 +SHOPT_CMDLIB_BLTIN=1 now includes <cmdlist.h> generated table.
+05-04-07 +[[ -o ?option ]] is true if "option" is a supported option.
+05-04-05 A bug in handling file completion with spaces in the names
+ has been fixed.
+05-03-25 +The SIGWINCH signal is caught by default to keeps the LINES and
+ COLUMNS variables in sync with the actual window size.
+05-03-25 +Building ksh with SHOPT_REMOTE=1 causes ksh to set --rc if stdin is
+ a socket (presumably part of a remote shell invocation.)
+05-03-25 +Building ksh with SHOPT_SYSRC=1 causes interactive ksh to source
+ /etc/ksh.kshrc (if it exists) before sourcing the $ENV file.
+05-03-25 +{first..last[..incr][%fmt]} sequences added to brace expansions
+ when braceexpand is enabled.
+05-03-03 A bug where a SIGCHLD interrupt could cause a fifo open to fail has
+ been fixed.
+05-02-25 A bug in which a builtin command run in the background could
+ keep a file descriptor open which could cause a foreground
+ process to hang has been fixed.
+05-02-24 A bug where builtin library commands (e.g., date and TZ) failed to
+ detect environment variable changes has been fixed.
+05-02-22 +The read builtin and word splitting are now consistent with respect
+ to IFS -- both treat IFS as field delimiters.
+05-02-22 +The read builtin no longer strips off trailing delimiters that
+ are not space characters when there are fewer variables than fields.
+05-02-17 A builtin bug on systems where dlsym(libcmd) returns link-time
+ bindings has been fixed.
+05-02-12 A bug in which the lib_init() function for .paths BUILTIN_LIB
+ libraries was not called has been fixed.
+05-02-06 A bug on some systems in which moving the write end of a co-process
+ to a numbered file descriptor could cause it to close has been fixed.
+05-02-06 A bug in the vi-edit mode in which the character under the cursor
+ was not deleted in some cases with the d% directive has been fixed.
+05-02-06 A bug where external builtin stdout/stderr redirection corrupted
+ stdout has been fixed.
+05-02-04 A bug where times formatting assumed CLK_TCK==60 has been fixed.
+
+05-01-11 --- Release ksh93q ---
+05-01-11 A bug in the integral divide by zero check has been fixed.
+05-01-11 +The -l option has been added to read /etc/profile and
+ $HOME/.profile, if they exist, before the first command.
+05-01-11 An argument parsing bug that caused `kill -s x -- n' to fail has
+ been fixed.
+05-01-11 +The .paths file, introduced in ksh93m, which can appear in
+ any directory in PATH, now allows a line of the form 'BUILTIN_LIB=.'
+ When a command is searched for this directory, and the full path
+ matches the path of the built-in version of the command (listed
+ by the 'builtin' command) then the built-in version of the command
+ is used. When ksh is built with SHOPT_CMDLIB_DIR=1 then all libcmd
+ functions become builtins with the '/opt/ast/bin/' directory prefix.
+05-01-10 A bug in which a nameref to a compound name caused a core dump has
+ been fixed.
+05-01-09 A bug in which some SIGCHLD interrupts (from child processes exiting)
+ caused a fatal print/echo error diagnostic has been fixed.
+04-12-24 A bug in which some SIGCHLD interrupts (from child processes exiting)
+ corrupted the internal process/job list, sometimes causing the shell
+ to hang, has been fixed.
+04-12-01 A bug in which typeset -Fn truncated less than n digits for large
+ numbers has been fixed.
+04-11-25 A bug in which standard error could be closed after a redirection
+ to /dev/stderr has been fixed.
+04-11-17 A bug in which an expansion of the form ${array[@]:3} could expand
+ to ${array[0]} when ${array[3]} was not set has been fixed.
+04-10-22 +The -E or -orc command line option reads ${ENV-$HOME/.kshrc} file.
+04-10-22 +`-o foo' equivalent to `+o nofoo', `-o nobar' equivalent to `+o bar'.
+ `--foo' equivalent to `-o foo', `--nofoo' equivalent to `+o foo'
+04-10-05 +The .paths file, introduced in ksh93m, which can appear in
+ any directory in PATH, now allows a line of the form
+ 'BUILTIN_LIB=libname'. When a command is searched for this directory,
+ the shared library named by libname will first be searched for a
+ built-in version of the command.
+04-09-03 <<< here documents now handle quotes in the word token correctly.
+04-08-08 +The maximum size for read -n and and read -N was increased from
+ 4095 to 32M.
+04-08-04 +printf %q was modified so that if an no operand was supplied, no
+ no output would be generated rather than a quoted empty string.
+04-08-01 +The -n and -N options of the read builtin has been modified
+ when reading variables with the binary attribute so that the
+ data is stored directly rather than through assignment.
+04-08-01 +The shcomp command has been modified to process alias commands
+ under some conditions.
+04-07-31 +The .sh.match variable added in ksh93l, now works like other
+ indexed arrays.
+04-07-08 A loop optimizer bug which occurs when typeset is used in
+ a for or while loop inside a function has been fixed.
+04-06-24 +The number of subexpressions in a pattern was increased to 64
+ from the current number of 20.
+04-06-17 +The -t option to read was modified to allow seconds to be
+ specified as any arithmetic expression rather than just
+ an integral number of seconds, for example even -t 'sin(.5)'
+ is now valid.
+04-06-16 Two small memory leak problems were fixed.
+04-06-15 A bug in ${var/pattern/"string"} which occurred when string
+ contained pattern matching characters has been fixed.
+04-05-08 printf $'%d\n' produced an erroneous error message and has
+ been fixed.
+04-05-24 A bug in which an associative array without any elements could
+ cause a core dump when a script with an associative array with
+ the same name was declared in a script invoked by name has
+ been fixed.
+04-05-11 A bug in which an exec statement could close the script that
+ is being processed in a script that is run by name causing
+ a failure has been fixed.
+04-04-28 +If the first character of assignment to an integer variable was 0,
+ the variable had been treated as unsigned. This behavior was
+ undocumented and has been removed.
+04-04-05 A bug in which the positioning of standard input could be incorrect
+ after reading from standard input from a subshell has been fixed.
+04-03-30 A bug in the for loop optimizer which in rare cases could cause
+ memory corruption has been fixed.
+04-03-29 +The preset alias source='command .' has been added.
+04-03-29 A bug introduced in ksh93p on some systems in which invoked by
+ name with #! on the first line would not get the signals handling
+ initialized correctly has been fixed.
+04-03-29 A bug introduced in ksh93p in which a HUP signal received by
+ a shell that is a session group leader was not passed down to
+ its children has been fixed.
+
+04-02-28 --- Release ksh93p ---
+04-02-28 +The ability to apply an append discipline to any variable has
+ been added.
+04-02-14 A bug in which the exportall option (set -a) would cause incorrect
+ results for arrays has been fixed.
+04-02-02 A bug in which an exported array would pass more than
+ the first element to a script invoked by name has been fixed.
+04-02-02 A bug on some systems in which name=value pairs preceding a script
+ invoked by name was not getting passed to the script has been fixed.
+04-01-20 A bug in which an unset discipline function could cause a core
+ dump on some systems has been fixed.
+04-01-12 A bug in which a continue or break called outside a loop from
+ inside a function defined with name() syntax could affect
+ the invoking function has been fixed.
+04-01-08 If a command name begins with ~, only filename completion will be
+ attempted rather than pathname completion using the builtin editors.
+04-01-08 A bug in the vi edit mode in which the wrong repeat count on
+ multiple word replacements with the . directive has been fixed.
+04-01-06 Backspace characters are now handled correctly in prompt strings.
+04-01-06 +The getopts builtin has been modified to accept numerical
+ arguments of size long long on systems that support this.
+04-01-06 A bug in which unsetting all elements of an associative array
+ would cause it to be treated as an indexed array has been fixed.
+03-12-15 A bug in which a quoted string ending with an unescaped $ would
+ delete the ending $ in certain cases has been fixed.
+03-12-05 A bug in which the shell could hang when set -x tracing a command
+ when an invalid multibyte character is encountered has been fixed.
+03-12-05 On some systems, if the KEYBD trap is set, then commands that use
+ the meta key were not processed until return was hit. This
+ has been fixed.
+03-12-05 A problem which occurred when the login shell was not a group
+ leader that could cause it to fail has been fixed.
+03-12-05 A problem in which a shell could core dump after receiving a signal
+ that should cause it to terminate while it was in the process
+ of acquiring more space has been fixed.
+03-12-05 +If ENV is not specified, the shell will default to $HOME/.kshrc
+ for interactive shells.
+03-11-21 A bug introduced in ksh93o in which the DEBUG trap could get
+ disabled after it triggered has been fixed.
+03-11-04 A bug in which using arithmetic prefix operators ++ or -- on a
+ non-lvalue could cause a core dump has been fixed.
+03-11-04 A bug in which leading zeros were stripped from variable
+ expansions within arithmetic computation to avoid being treated
+ as octal constants when they should not have, has been fixed.
+03-10-08 A bug introduced in ksh93o in which a large here document inside
+ a function definition could get corrupted has been fixed.
+03-09-22 A bug in which the .get discipline function was not being
+ called when a string variable was implicitly referenced from
+ within a numerical expression has been fixed.
+03-09-22 A bug in which a script without a leading #! could get executed
+ by /bin/sh rather than the current shell on some systems has
+ been fixed.
+03-09-12 +To improve conformance with ksh88, leading zeros will be ignored
+ when getting the numerical value of a string variable so that
+ they will not be treated as octal constants.
+03-09-03 +The builtin kill command now processes obsolete invocations
+ such as kill -1 -pid.
+03-09-02 The restriction on modifying FPATH in a restricted shell (sh -r)
+ has been documented.
+03-09-02 +The restricted shell (sh -r) has been modified to disallow
+ executing command -p.
+03-08-07 A bug in which the KEYBD trap was not being invoked when
+ characters with the 8th bit set has been fixed.
+03-08-02 A parser bug introduced in ksh93o which caused the character
+ after () in a Posix function definition to be skipped
+ when reading from standard input has been fixed.
+03-08-01 A bug in which "${foo#pattern}(x)" treated (x) as if it were
+ part of the pattern has been fixed.
+03-08-01 +The command -x option has been modified so that any trailing
+ arguments that do expand to a single word will be included
+ on each invocation, so that commands like command -x mv * dir
+ work as expected.
+
+03-07-20 --- Release ksh93o+ ---
+03-07-20 A bug in which could cause memory corruption when a posix
+ function invoked another one has been fixed.
+03-07-15 A bug in which a file descriptor>2 could be closed before
+ executing a script has been fixed.
+03-07-15 A parsing error for <() and >() process substitutions inside
+ command substitution has been fixed.
+03-07-15 A parsing error for patterns of the form {...}(...) when
+ used inside ${...} has been fixed.
+03-07-15 An error in which expanding an indexed array inside a compound
+ variable could cause a core dump has been fixed.
+03-07-15 A bug in which on rare occasions a job completion interrupt
+ could cause to core dump has been fixed.
+03-06-26 A bug in which process substitution embedded within command
+ substitution would generate a syntax error has been fixed.
+03-96-23 A bug in which ${@:offset:len} could core dump when there
+ were no arguments has been fixed.
+03-96-23 A bug in which ${X[@]:offset:len} could core dump when X
+ was unset has been fixed.
+03-06-22 +The -x option was added to the command builtin. If this
+ option is on, and the number of arguments would exceed ARG_MAX,
+ the command will be invoked multiple times with a subset of
+ the arguments. For example, with alias grep='command -x grep,
+ any number of arguments can be specified.
+03-06-14 A bug in which could cause a core dump on some systems with
+ vi and emacs editors with the MULTIBYTE option has been fixed.
+03-06-06 A bug in which the shell could core dump when a script was
+ run from its directory, and the script name a symlink to a file
+ beginning with .., has been fixed.
+03-06-05 A bug in which the shell could core dump when a child process
+ that it is unaware of terminates while it is calling malloc()
+ has been fixed.
+03-06-02 +An option named globstar (set -G) has been added. When enabled,
+ during pathname expansion, any component that consists only of ** is
+ matches all files and any number of directory levels.
+03-05-30 A bug in which the PATH search could give incorrect results when
+ run from directory foo and PATH contained .:foo:xxx has been fixed.
+03-05-29 +Some changes were made to the code that displays the prompt in edit
+ mode to better handle escape sequences in the prompt.
+03-05-27 I added = to the list of characters that mark the beginning of
+ a word for edit completion so that filenames in assignments
+ can be completed.
+03-05-20 A bug in which read -N could hang on some systems when reading
+ from a terminal or a pipe has been fixed.
+03-05-19 A bug in which the output of uname from a command substitution
+ would go to the standard output of the invoking command when
+ uname was invoked with a non-standard option has been fixed.
+03-05-19 A job control bug which would cause the shell to exit because
+ it hadn't take back the terminal has been fixed. The bug
+ could occur when running a function that contained a pipeline
+ whose last element was a function.
+03-05-19 A job control timing bug introduced in ksh93o on some systems
+ which could cause a pipeline to hang if the first component
+ completed quickly has been fixed.
+03-05-13 +The read builtin has been modified so that the builtin editors
+ will not overwrite output from a previous incomplete line.
+03-05-13 A bug in which the name of an identifier could have the string
+ .sh. prefixed to it after expanding a variable whose name begins
+ with .sh. has been fixed.
+03-05-13 A bug in the expansion of $var for compound variables in which
+ some elements would not be output when the name was a prefix
+ of another name in the compound variable has been fixed.
+03-05-08 The last item in the ksh93o release on 03-01-02 has been
+ altered slightly to preserve the leading 0's when the
+ preceding character is a digit. Thus, with typeset -LZ3 x=10,
+ $(( 1$x)) will be 1010 whereas $(( $x) will be 10.
+03-04-25 A bug in which if x is a name reference, then nameref y=x.foo
+ did not follow x has been fixed.
+
+03-03-18 --- Release ksh93o ---
+03-03-18 +A -N unary operator was added to test and [[...]] which returns
+ true if the file exists and the file has been modified since it
+ was last read.
+03-03-18 +The TIMEFORMAT variable was added to control the format for
+ the time compound command. The formatting description is
+ described in the man page.
+03-03-06 +A -N n option was added to read which causes exactly n bytes
+ to be read unlike -n n which causes at most n bytes to be read.
+03-03-03 +Three new shell variables were added. The variable .sh.file
+ stores the full pathname of the file that the current command
+ was found in. The variable .sh.fun names the current function
+ that is running. The variable .sh.subshell contains the depth
+ of the current subshell or command substitution.
+03-03-03 +When the DEBUG trap is executed, the current command line after
+ expansions is placed in the variable .sh.command. The trap
+ is also now triggered before each iteration of a for, select,
+ and case command and before each assignment and redirection.
+03-02-28 +Function definitions are no longer stored in the history file so
+ that set -o nolog no longer has any meaning.
+03-02-28 +All function definitions can be displayed with typeset -f not
+ just those stored in the history file. In addition, typeset +f
+ displays the function name followed by a comment containing the
+ line number and the path name for the file that defined this function.
+03-02-28 A bug in which the value of $LINENO was not correct when executing
+ command contained inside mult-line command substitutions has been
+ fixed.
+03-02-19 +Since some existing ksh88 scripts use the undocumented and
+ unintended ability to insert a : in front of the % and # parameter
+ expansion operators, ksh93 was modified to accept :% as equivalent
+ to % and :# as equivalent to # with ${name op word}.
+03-02-14 A bug which could cause a core dump when reading from standard
+ error when standard error was a pty has been fixed.
+03-02-14 +The shell arithmetic was modified to use long double on systems
+ that provide this data type.
+03-02-09 A bug in which a function located in the first directory in FPATH
+ would not be found when the last component of PATH was . and the
+ current directory was one of the directories in PATH has been fixed.
+03-02-07 +The trap and kill builtin commands now accept a leading SIG prefix
+ on the signal names as documented.
+03-02-05 A bug in the expansion of ${var/$pattern}, when pattern contained
+ \[ has been fixed.
+03-02-05 A bug in which .sh.match[n], n>0, was not being set for substring
+ matches with % and %% has been fixed.
+03-01-15 A bug in which getopts did not work for numerical arguments specified
+ as n#var in the getopts string has been fixed.
+03-01-09 A bug in which using ${.sh.match} multiple times could lead to
+ a memory exception has been fixed.
+03-01-06 A bug in the expansion of ${var/pattern/$string} in the case that
+ $string contains \digit has been fixed.
+03-01-02 +A -P option was added for systems such as Solaris 8 that support
+ profile shell.
+03-01-02 For backward compatibility with ksh88, arithmetic expansion
+ with ((...)) and let has been modified so that if x is a zero-filled
+ variable, $x will not be treated as an octal constant.
+
+02-12-05 --- Release ksh93n+ ---
+02-11-30 A bug that can show up in evaluating arithmetic statements that
+ are in an autoloaded function when the function is autoload from
+ another function has been fixed.
+02-11-30 An optimization bug in which an expansion of the form ${!name.@},
+ which occurred inside a for or a while loop, when name is a name
+ reference, has been fixed.
+02-11-18 A bug in which modifying array variables in a subshell could leave
+ side effects in the parent shell environment has been fixed.
+02-11-18 A memory leak when unsetting an associative array has been fixed.
+02-11-14 +The code to display compound objects was rewritten to make
+ it easier for runtime extensions to reuse this code.
+02-11-14 +A change was made to allow runtime builtins to be notified when
+ a signal is received so that cleanup can be performed.
+02-10-31 +User applications can now trap the ALRM signal. Previously,
+ the ALRM signal was used internally and could not be used
+ by applications.
+02-10-31 A bug in which signals received while reading from a coprocess
+ for which traps were set was not handled correctly has been fixed.
+02-10-31 A bug in which a file opened with exec inside a subshell could
+ be closed before the subshell completed has been fixed.
+02-10-21 A bug in which setting PATH or FPATH inside a function might not
+ take effect has been fixed.
+02-10-21 A bug which could cause a core dump when a local SECONDS variable
+ is defined in a function has been fixed.
+02-10-15 A bug in which the associate array name operator ${!array[@]}
+ could return the same name multiple times has been fixed.
+02-10-15 A bug in which the zero'th element of an associative array was
+ not getting set when an assignment was made without a subscript
+ specified has been fixed.
+
+02-09-30 --- Release ksh93n ---
+02-09-30 +The maximum indexed array size was increased to 16Megs.
+02-09-30 A bug which could cause a core dump when changing attributes
+ of associative array has been fixed.
+02-09-30 A bug in which exporting an array variable would not export the
+ 0-th element has been fixed.
+02-09-30 A bug in which an array assignment of the form a=($a ...) would unset
+ 'a' before the right hand side was evaluated has been fixed.
+02-09-27 A bug in which the error message for ${var?message} when var was
+ null or unset did not contain the variable name var has been fixed.
+02-09-27 A bug in which closing file descriptors 0 through 2 could
+ cause a subsequent here document to fail has been fixed.
+02-09-14 A bug in whence which occurs when the specified name contained
+ a / has been fixed.
+02-09-14 A bug in the parser for strings of the form name$((expr))=value
+ has been fixed.
+02-09-14 A for loop optimization bug in which the number of elements in
+ an array was treated as an invariant has been fixed.
+02-09-09 A bug in which redirection or closing of a file descriptor between
+ 3 and 9 could cause a subsequent here document to fail has been
+ fixed.
+02-09-09 A bug in which a background job was not removed from the job list
+ when a subshell completed has been fixed, for example (prog&).
+02-09-03 A bug in which an assignment of the form name=(integer x=3)
+ could be interpreted as an array assignment rather than a
+ compound variable assignment has been fixed.
+02-08-19 A command completion bug which occurred on file systems that
+ are case insensitive has been fixed.
+02-08-19 A bug which could lead to an exception on some systems (for
+ example FREEBSD) which occurred when setting PATH has been fixed.
+02-08-11 A bug in arithmetic rounding in which a value input as a decimal
+ string would output as a rounded version of the string has
+ been fixed.
+02-08-11 A bug in which the last character could be deleted from shell
+ traces and from whence when called from a multibyte locale
+ has been fixed.
+02-08-01 A bug which could cause a core dump to occur when a shell script
+ is executed while a coprocess is running that has closed the
+ output pipe has been fixed.
+02-08-01 A bug in which command completion in multibyte mode could
+ corrupt memory for long command lines has been fixed.
+
+02-06-17 --- Release ksh93n- ---
+02-06-17 A bug in which user defined macros could cause a core dump in
+ with MULTIBYTE mode has been fixed.
+02-06-17 A bug in which printf format specifiers of the form %2$s were causing
+ a core dump has been fixed.
+02-06-17 A bug in which setting stty to noecho mode did not prevent the
+ echoing of characters by ksh when emacs or viraw mode
+ was enabled has been fixed.
+02-06-17 A bug in which background job completion could cause the sleep
+ builtin to terminate prematurely has been fixed.
+02-06-17 A bug in which the shell could core dump if getopts was called
+ when the OPTIND variable contained a negative value has been fixed.
+02-06-10 +The edit mode prompt has been modified to handle escape sequences.
+02-06-10 A bug which occurred for interactive shells in which the builtin
+ cat command was used in command substitution on a file whose
+ size was larger than PIPE_BUF has been fixed.
+02-06-10 A bug in which the trap on ERR was not being processed when
+ set inside a function has been fixed.
+02-06-07 A bug in which function definitions could cause the history count
+ to be decremented by one (and even become negative) has been fixed.
+02-06-05 A bug in read in which share mode could be enabled has been fixed.
+02-05-28 A bug which could occur when the last command of a script was
+ a case statement and the action selected ended in ;& instead of ;;
+ has been fixed.
+02-05-23 A bug with unary + introduced in ksh93k has been fixed.
+02-05-07 A bug in substitutions of the form ${var/pattern/string} in which
+ a backslash was inserted in the replacement string when it contained
+ a special pattern character has been fixed.
+02-05-01 A bug in the emacs edit mode which occurred in versions compiled
+ for multibyte character sets which occurred when a repeated search
+ was requested after a long line had been returned for the previous
+ search has been fixed.
+02-04-02 +vi and emacs edit modes were modified so that tab completion is
+ disabled when invoked from the read built-in.
+
+02-03-26 --- Release ksh93m+ ---
+02-03-26 A bug in which \ was not handled correctly when used in file
+ expansion has been fixed.
+02-02-18 A bug in which lines beginning with a # were deleted from here
+ documents when the here-document delimiter was followed by
+ a comment has been fixed.
+02-12-06 An optimization bug in which ${!x[@]) was treated as invariant in
+ a for loop has been fixed.
+02-02-06 A bug in which the ERR trap is not cleared for a script invoked
+ by name from within a function has been fixed.
+02-01-08 A bug in which a shell script executed from within a subshell
+ could cause this script to have an invalid pointer leading
+ to a memory fault has been fixed.
+02-01-07 +Added here documents of the form <<< word (as per zsh) which
+ is equivalent to << delim\nword\ndelim.
+02-01-07 A bug in which the first word of a compound assignment,
+ x=(word ...), was treated as a reserved word has been fixed.
+02-01-07 A bug in the handling of \ when noglob was enabled and a
+ substitution of the form ${word op pattern} occurred in the
+ same word has been fixed.
+02-01-07 +A compilation option, CMDLIB_BLTIN in the file OPTION, has
+ been added. When this options is set, all commands implemented
+ in libcmd become shell builtin commands by default.
+02-01-07 A bug in which builtin foo, where foo is already a builtin
+ would result in the builtin foo getting removed has been fixed.
+02-01-07 A bug which the shell executed a command found in the current
+ directory when PATH have no valid directories has been fixed.
+01-11-28 The value of $? was not being set when called with exit.
+01-11-28 If the last command was of the form (...) and a trap on EXIT or
+ ERR was set, and the command inside () modified the trap, then
+ 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
+ viraw mode will always be on.
+
+01-10-31 --- Release ksh93m ---
+01-10-31 A for loop optimizer bug for subshells contained withing for
+ loops has been fixed.
+01-10-16 typeset without arguments no longer outputs variable names
+ that do not have any attributes that are set.
+01-10-16 A bug introduced in ksh93l in which assignments specified with
+ the exec built-in were not being expanded properly has been
+ fixed.
+01-10-11 An optimization bug in which ${!x) was treated as invariant in
+ a for loop has been fixed.
+01-10-11 Unsigned integer variables in bases other than 10 are printed now
+ expand in that base with the base prefix.
+01-10-10 A number of typos in the self generating man pages for shell
+ built-ins have been fixed.
+01-10-04 The self generated man pages for hist and fc were not working
+ correctly and have been fixed.
+01-10-03 Yet another optimizer bug in which shell patterns were
+ treated as invariants has been fixed.
+01-09-27 Two bugs relating to multibyte history searches and to find
+ have been fixed.
+01-09-27 A bug introduced in ksh93k in which the PATH searching was
+ not restored after running a command with an assignment list
+ has been fixed.
+01-09-26 A bug in which a zero filled field was treated as octal when
+ converted to integer has been fixed.
+01-09-26 Yet another bug in the optimization of for loops related to
+ recursive functions with break or continue statements has been fixed.
+01-09-25 +The exponentiation operator ** was added to the shell arithmetic
+ evaluation. It has higher precedence than * and is left
+ associative.
+01-09-25 The code was modified to use the ast multibyte macros
+ and functions for handing multibyte locales.
+01-09-25 +The expansion ${parameter:offset:length} now handles negative
+ offsets which cause offsets to be measured from the end.
+01-09-25 Some spelling errors in the documentation were corrected.
+01-09-24 +The /dev/tcp/host/port and /dev/udp/host/port now allow
+ the ports to be specified by service name.
+01-09-24 +The change staring with ksh93g in which the the appropriate
+ library path variable is prepended with a corresponding library
+ directory has been modified. With the new method, only the
+ library path defined in the file named .paths in the directory
+ where the executable is found will be modified. See the
+ man page for more details.
+01-09-23 +The .fpath file (see ksh93h) is no longer looked for in each
+ directory on the path to locate function directories. The
+ file named .paths is used instead.
+01-09-23 A bug in which IFS was not being restored after being changed in
+ a subshell has been fixed.
+01-09-16 +With the vi and emacs edit modes, after a list of command
+ or functions is generated with = or M-= respectively,
+ any element from the list can be pasted on the command line
+ by preceding the = or M-= with a numeric parameter specifying
+ the position on the list.
+01-09-16 A bug in ksh93l caused command completion not to find aliases
+ and functions. Command listing from the edit mode was presented
+ in reverse order. This has been fixed.
+01-09-13 Another bug in the optimization of for loops related to subshells
+ when traps were set has been fixed.
+01-09-07 A change in ksh93l caused brace expansion to stop working
+ and this has been fixed.
+01-09-04 A bug introduced in ksh93k in which an arithmetic statement
+ within a function that used name references did not follow the
+ reference has been fixed.
+01-09-04 A bug introduced in ksh93l in which export -p did not prefix
+ each export with the word export has been fixed.
+01-08-29 A bug in multibyte input which occurred when a partial multibyte
+ character was received has been fixed.
+01-08-29 A bug introduced in ksh93l which could cause a core dump
+ when an assignment list containing PATH is specified inside
+ command substitution has been fixed.
+01-08-09 Another bug in the optimization of for loops in ksh93l caused
+ errors in recursive functions using local variables that
+ contained for loops has been fixed.
+01-07-27 A bug in which IFS would be unset after a command substitution
+ inside a here document has been fixed.
+01-07-26 To conform to the POSIX standard, if you invoked ksh name,
+ and name does not contain a /, it will first try to run
+ one in the current directory whether it is executable or not
+ before doing a path search for an executable script. Earlier
+ versions first checked for an executable script using the
+ PATH variable.
+01-07-23 A bug in which unset -f invoked in a subshell could unset a
+ function defined in the parent has been fixed.
+01-07-16 A bug in the optimization of for loops in ksh93l caused
+ name references to be treated as invariants has been fixed.
+01-07-09 A bug in which a discipline function applied to a local variable
+ could cause a shell exception has been fixed. Discipline
+ functions can only be specified for global variables.
+
+01-06-18 --- Release ksh93l ---
+01-06-18 A bug in assigning integers larger than can be represented as
+ long integers to floating point variables has been fixed.
+01-06-18 A bug in the handling of unsigned integers (typeset -ui) has
+ been fixed.
+01-06-04 The evaluation of the PS1 prompt no longer effects the value
+ of the $? variable.
+01-06-01 A small memory leak from subshells has been fixed.
+01-05-22 A bug in which attributes for variables that did not have
+ values would be lost after a subshell has been fixed.
+01-05-22 +The %R format has been added to convert a shell pattern into
+ an extended regular expression.
+01-05-22 +The escape sequences \e, \cX, \C[.collating-element.], and
+ \x{hex} have been added to ASCII-C strings and to printf format
+ strings.
+01-05-20 +Patterns of the form {n}(pattern) and {m,n}(pattern) are now
+ recognized. The first form matches exactly n of pattern whereas,
+ the second form matches from m to n instances of pattern.
+01-05-20 +The shell allows *-(pattern), +-(pattern), ?-(pattern),
+ {m,n}-(pattern}, and @-(pattern) to cause the minimal
+ match of pattern to be selected whenever possible rather
+ than the maximal (greedy) match.
+01-05-20 +The character class [:word:] has been added to patterns.
+ The word class is the union of [:alnum:] and the character _.
+01-05-20 +Inside (...) pattern groups, the \ character is now treated
+ specially even when in an enclosing character class. The
+ sequences, \w, \d, \s are equivalent to the character classes
+ word, digit, and space respectively. The sequences \W, \D,
+ and \S are their complement sets.
+01-05-20 +The shell now recognizes pattern groups of the form
+ ~(options:pattern) where options or :pattern can be omitted.
+ Options use the letters + and - to enable and disable options
+ respectively. The option letters g (greedy), i (ignore case)
+ are used to cause maximal matching and to cause case
+ insensitive matching respectively. If :pattern is also
+ specified, these options are only in effect while this
+ pattern is being processed. Otherwise, these options remain
+ in effect until the end of the pattern group that they are contained
+ in or until another ~(...) is encountered. These pattern groups
+ are not counted with respect to group numbering.
+01-05-14 When edit completion, expansion, or listing occurs in the
+ middle of a quoted string, the leading quote is ignored when
+ performing the completion, expansion, or listing.
+01-05-14 A small memory leak from subshells has been fixed.
+01-05-10 A bug in which open files were not restored after a subshell
+ that had used exec to replace a file has been fixed.
+01-05-10 +Redirection to a null file name now generates an error message.
+01-05-09 The shell now rejects some invalid parameter substitutions that
+ were previously processed in undefined ways.
+01-05-09 A bug in which the output of select was not flushed before the
+ read when input did not come from the terminal has been fixed.
+01-05-08 A bug in which job ids would not be freed for interactive shells
+ when subshells ran built-ins in the background has been fixed.
+01-05-08 +The FPATH variable now requires an explicit . to cause the
+ current directory to be treated as a function directory.
+01-05-08 A bug in read -n when echo mode was disabled has been fixed.
+01-05-07 A bug in which function definitions could be listed as part
+ of the history has been fixed.
+01-04-30 +This release uses a new and often much faster pattern matcher than
+ earlier releases.
+01-04-30 +An optimizer now eliminates invariant parameter expansions from
+ for while and until loops.
+01-04-30 +The variable .sh.match is set after each pattern match (# % or /)
+ in a variable substitution. The variable .sh.match is an
+ indexed array with element 0 being the complete match.
+ The array is only valid until the next subsequent pattern
+ match or until the value of the variable changes which ever
+ comes first.
+01-04-30 +A self generating man page has been added to shcomp. Also,
+ shcomp now stops compiling when it finds an exit or exec
+ command and copies the remainder so that it can be used
+ for standard input.
+01-04-30 +The shcomp command was modified so that it can work in an
+ EBCIDIC environment and that binary scripts are portable
+ across environments.
+01-04-30 A bug in the handling of a trailing : in PATH has been fixed.
+01-04-30 A bug in which the builtin version of a command would get invoked
+ even though the full pathname for the command was specified
+ has been fixed.
+01-04-30 A bug in which read would loose the last character when
+ reading the last line of a file that did not contain a new-line
+ character has been fixed.
+01-04-23 A bug on some systems in which in vi mode the end of file
+ character and end of line character could be swapped has
+ been fixed.
+01-04-23 A bug on some systems in which invoking a shell script that
+ did not have execute permission could set the exit value to
+ 127 rather than 126 has been fixed.
+01-04-20 A bug in which read -n from a pipe would block if fewer than
+ n characters was received has been fixed.
+01-04-09 A bug in which invalid patterns, for example, ) by itself,
+ was not treated as a string has been fixed so that if i=')',
+ then [[ $i == $i ]] is true.
+01-04-09 +The shell arithmetic now interprets C character constants.
+01-04-09 A bug in which a non-zero return from a function defined
+ with the function reserved word did not trigger the ERR
+ trap or exit with set -e has been fixed.
+01-04-02 A bug on some systems, in which characters above 127 were
+ not displayed correctly in vi or emacs edit mode has been fixed.
+01-04-02 A bug on some systems, introduced in the 'k' point release, in
+ which the erase character in viraw mode was moving the cursor
+ to the left without erasing the character has been fixed.
+01-04-02 On some systems the wcwith() function was returning a wrong
+ value for characters and caused characters to be displayed
+ incorrectly from the shell edit modes. A work around for
+ this problem has been added.
+01-03-26 A bug in which valid scripts could produce syntax errors
+ when run with locales that considered characters such as "'"
+ to be space characters has been fixed.
+01-03-20 A bug in which an syntax error in an arithmetic expression
+ entered interactively could cause the shell to go into
+ an infinite loop outputting the error message has been fixed.
+01-03-10 +ksh93 accepts -l as a synonym for -L in test on systems for
+ which /bin/test -l tests for symbolic links.
+01-03-10 A bug in parsing scripts in which { and } are used in place of
+ in and esac in case statements embedded in compound commands
+ has been fixed. Use of { and } for in and esac is obsolete.
+01-03-06 A bug in which an argument of the form foo=bar was not
+ being passed correctly to a traced function whose name
+ was foo has been fixed.
+01-03-02 Using $(trap -p name) did not print the name of the current
+ trap setting for trap name.
+01-02-26 Exported floating point variables gave incorrect results
+ when passing them to ksh88. This has been fixed.
+01-02-25 A race condition in which a coprocess which completed too quickly
+ would not allow subsequent coprocesses to start has been fixed.
+01-02-25 The 'g' format specifier is now handled by printf. It had
+ inadvertently been omitted.
+01-02-20 The + was not being displayed during an execution trace
+ with the += assignment operator.
+01-02-19 The error message which occurs when the interpreter name
+ defined on the #! line does not exist is more informative.
+01-02-19 A bug in which $0 would not be set correctly when a
+ script with #! was invoked by full pathname from the
+ directory of the script has been fixed.
+01-02-19 A shell script did not always pick up tty mode changes
+ made by external commands such as stty which could
+ effect the behavior of read.
+01-02-19 The -u, -g, and -k unary tests did not give the correct
+ results when used with negation and this has been fixed.
+
+01-02-05 --- Release ksh93k+ ---
+01-02-05 The sequence \<newline> inside $'...' was not incrementing
+ the line count and this has been fixed.
+01-02-05 +Modified expansion of "${@-}" so that if no arguments are set
+ it results in null string rather than nothing.
+01-02-02 memory leak problem with local variables in functions fixed.
+01-01-25 +allow arithmetic expressions with float%int and treat them
+ as ((int)float)%int rather than as an error.
+01-01-19 read -n1 was not working and has been fixed.
+01-01-17 +ksh now handles the case in which a here document in command
+ substitution $() is terminated by the trailing ). Previously,
+ a new-line was needed at the end of the delimiter word.
+01-01-02 A bug in which a KEYBD trap would cause a multi-line token
+ to be processed incorrectly has been fixed.
+00-12-10 +Arithmetic integer constants can now have L and U suffices.
+00-12-10 A bug in the processing of arithmetic expressions with compound
+ variables when the -n option is on has been fixed.
+00-12-08 A bug in M-f and M-b from emacs mode has been fixed. This
+ bug only occurs when ksh93 is compiled without MULTIBYTE enabled.
+00-11-29 A bug in which jobs -p would yield 0 for background
+ jobs run in a script has been fixed.
+00-11-21 A bug in integer arrays in which the number of elements is
+ incorrect when the ++ operator is applied to a non-existing
+ element has been fixed. For example, integer x; ((x[3]++)).
+00-11-20 A timing bug in which the shell could reset the terminal
+ group to the wrong value in the case that the a new process
+ changes the terminal group during startup has been fixed.
+
+00-10-27 --- Release ksh93k ---
+00-10-27 Using tab for completion now works only when applied
+ after a non-blank character at the end of the current line.
+ In other case a tab is inserted.
+00-10-27 A bug in the emacs edit mode for ^X^E has been fixed.
+ The ^X^E sequence is supposed to invoke the full editor
+ on the current command.
+00-10-18 A bug in which expansions of the form ${var//pattern/string}
+ did not work correctly when pattern was '/' or "/" has
+ been fixed.
+00-10-18 +The output format for indexed arrays in compound variables
+ has been modified so that it can be used as input.
+00-10-18 Assignments with name references (typeset -n) will now
+ implicitly unreference an existing name reference.
+00-10-17 A bug the += append operator when a single array element
+ is appended to a variable that is not an array has been fixed.
+00-10-16 A bug in which the SIGCONT signal was being sent to
+ each process will kill -0 or kill -n 0 has been fixed.
+00-10-12 +The arithmetic evaluation portion has been rewritten to
+ perform a number of optimizations.
+00-10-10 A bug in which name prefix matching ${!name.*} was not
+ checking name to see if it was a name reference has been fixed.
+00-09-26 A bug in the multibyte version in which the width of for
+ non-printing characters was not correct has been fixed.
+00-09-12 +Made changes to get multibyte editing work on UWIN for windows
+00-09-12 A bug in which multibyte characters would be displayed incorrectly
+ has been fixed.
+00-08-08 Removed build dependency on iswprint() and iswalph().
+00-07-20 In some cases the read builtin would read more than a single
+ line from a pipe on standard input and therefore leave the seek
+ position in the wrong location.
+00-07-05 +If the directory / is on the path, a / will not be inserted
+ between the directory and the file name during path searching
+ to avoid searching // for systems that treat this specially.
+00-06-26 A bug in which on rare occasions wait could return before all
+ jobs have completed has been fixed.
+00-06-21 A bug in which backspace did not work correctly during the
+ R replace directive in vi-mode has been fixed.
+00-06-12 +Added variable name completion/expansion/listing to the set of
+ completions. Variable name completions begin with $ or "$ followed
+ by a letter.
+00-05-09 --- Release ksh93j ---
+00-05-09 Modified command substitution to avoid using /tmp files when
+ run on read-only file systems.
+00-04-17 +Modified printf to handle '%..Xc' and '%..Xs' options where X
+ is not an alpha character. Previous versions core dumped with this.
+00-04-10 +Changes to multibyte editing code were made to use standard
+ ISO C functions rather than methods devised before the standard.
+00-04-09 Add %H options to printf to output strings with <"'&\t> properly
+ converted for use in HTML and XML documents.
+00-04-07 +Modified getopts builtin to handle \f...\f in usage string
+ by invoking specified function.
+00-04-04 Added self generating man pages for bg, fc, fg, disown, jobs,
+ hist, let, ., and ulimit.
+00-03-30 +The append operator += has been added and can be used
+ for all assignments, strings, arrays, and compound variables.
+00-03-30 +Code was modified in several places to support automatic
+ generation of C locale dictionaries.
+00-03-28 A bug in which the set and trap commands invoked with --name
+ type arguments would terminate the invoking script has
+ been fixed.
+00-03-27 A bug in which the library path variable was not updated
+ correctly on some systems as described in the 'g' point
+ release has been fixed.
+00-03-07 printf now returns a non-zero exit status when one of
+ its arguments cannot be converted to the given type.
+00-03-05 The return value and error message for a command that
+ was found on the path but was not executable was set
+ incorrectly.
+00-03-05 A prototype for ioctl() was removed from the vi edit mode.
+
+00-01-28 --- Release ksh93i ---
+00-01-28 +Most of the built-in commands and ksh itself are now
+ self documenting. Running command --man will produce
+ screen output. Running command --html produces the
+ man page in html format.
+00-01-28 +The getopts builtin can process command description
+ strings to produce man pages.
+00-01-28 A bug in which a script could terminate when getopts
+ encountered an error when invoked inside a function
+ has been fixed.
+00-01-28 When a symbolic link was specified as the name of
+ the script to invoke by name, the value of $0 was
+ set to the real file name rather than the link name
+ in some cases and this has been fixed.
+00-01-28 A bug in which the precision given as an argument
+ to printf was not working has been fixed.
+
+99-03-31 --- Release ksh93h ---
+99-03-31 +The PATH search algorithm has been modified to look
+ for a file named .fpath in each bin directory and if
+ found, to search for functions in this directory if
+ it cannot find the command in that directory.
+99-03-31 +When performing pathname expansion, the shell checks
+ to see whether each directory it reads is case sensitive
+ or not, and performs the matching accordingly.
+99-03-31 +The %T format for printing formatted date/time.
+99-03-31 +The emacs and vi modes now handle arrow keys when
+ they use standard ANSI escape sequences.
+99-03-31 +The TAB key can be used for completion in emacs and viraw mode.
+99-03-31 A bug in setting .sh.editchar during the KEYBD trap
+ for the MULTIBYTE option was fixed in release ksh93h.
+99-03-31 A bug in shcomp for compilation of unary operators with [[...]]
+ has been fixed.
+99-03-31 A bug in which the value of $? was changed when executing
+ a keyboard trap has been fixed.
+99-03-31 The handling of SIGCHLD has been changed so that the
+ trap is not triggered while executing trap commands
+ to avoid recursive trap calls.
+99-03-31 A bug in which a local variable in a function declared readonly
+ would generated an error when the function went out of
+ scope has been fixed.
+99-03-31 A bug in which \<new_line> entered from the keyboard
+ with the KEYBD trap enabled has been fixed.
+99-03-31 The error message for a misplaced ((, for example print ((3),
+ was often garbled and has been fixed.
+99-03-31 A bug in the KEYBD trap in which escape sequences of the form
+ <ESC>[#~ were not being handled as a unit has been fixed.
+99-03-31 A bug in which ksh would consider expressions like [[ (a) ]]
+ as syntax errors has been fixed.
+99-03-31 A function defined as foo() without a function body
+ was not reported as a syntax error.
+99-03-31 A bug in which ksh could run out of file descriptors when
+ a stream was repeatedly opened with exec and read from
+ has been fixed.
+
+98-04-30 --- Release ksh93g ---
+98-04-30 +The pipefail option has been added. With pipefail
+ enabled, a pipeline will not complete until all
+ commands are complete, and the return value will
+ be that of the last command to fail, or zero if
+ all complete successfully.
+98-04-30 +The name-value pair library uses the cdt library rather
+ than the hash library. This change should be transparent
+ to applications.
+98-04-30 +On the U/WIN version for Window 95 and Windows NT,
+ when a directory beginning with a letter followed by
+ a colon is given to cd, it is assumed to be an absolute
+ directory
+98-04-30 +When an executable is found on a given path,
+ the appropriate library path variable is prepended
+ with a corresponding library directory.
+98-04-30 A bug in which a name reference could be created to
+ itself and later cause the shell to get into an infinite
+ loop has been fixed.
+98-04-30 A bug in shcomp relating to compound variables was fixed.
+98-04-30 A bug introduced in ksh93e in which leading 0's in -Z
+ fields caused the value to be treated as octal for arithmetic
+ evaluation has been fixed.
+98-04-30 A bug when a name reference with a shorter name than
+ the variable it references was the subject of a compound
+ assignment has been fixed.
+98-04-30 A bug which in which assignment to array variables in
+ a subshell could effect the parent shell has been
+ fixed.
+98-04-30 read name?prompt was putting a 0 byte at the end of the
+ prompt on standard error.
+98-04-30 A bug in [[ string1 > string2 ]] when ksh was run with -x
+ has been fixed.
+98-04-30 A bug in which the escape character was not processed
+ correctly inside {...} when brace expansion is enabled
+ has been fixed, for example {\$foo}.
+98-04-30 A bug in line continuation in here-documents has been
+ fixed.
+98-04-30 The default base when not specified with typeset -i is
+ 10 in accordance with the documentation. Previously,
+ the value was determined by the first assignment.
+98-04-30 A parsing bug in which a # preceded alphanumeric
+ characters inside a command substitution caused
+ a syntax error to be reported has been fixed.
+98-04-30 A bug in which a decimal constant represented as 10#ddd
+ where ddd was more than five digits generated a syntax
+ error has been fixed.
+98-04-30 A bug in here document expansion in which ${...} expansions
+ were split across buffer boundaries has been fixed.
+98-04-30 +The sh_fun() function now takes third argument which
+ is an argument list for the invoked discipline function
+ or built-in.
+98-04-30 +A callback function can be installed which will give
+ notification of file duplications and file closes.
+98-04-30 When ksh is compiled on systems that do not use fork()
+ current option settings where not propagated to sub-shells.
+
+97-06-30 --- Release ksh93f ---
+97-06-30 +Hostnames in addition to host addresses can be given in
+ /dev/tcp/host/port virtual file names.
+97-06-30 File name completion and expansion now quotes special
+ characters in file names from both emacs and vi edit modes.
+97-06-30 An empty for list behave like a for list with null expansions.
+ It produces a warning message with sh -n.
+97-06-30 +The code has been modified to work with EBCDIC as well as ASCII.
+97-06-30 A bug which would cause the secondary prompt to be
+ displayed when a user entered a literal carriage
+ return has been fixed.
+97-06-30 A bug which caused ksh read -s name to core dump was
+ fixed.
+97-06-30 A bug with the expansion of \} and \] inside double
+ quoted strings that also contained variable expansions
+ has been fixed
+97-06-30 Changes in the ksh93e point release caused autoload
+ functions invoked from within command substitution
+ to fail. This has been fixed.
+97-06-30 A bug in the processing of here-documents that could
+ prevent variable substitution to occur after $(...) command
+ substitution for long here documents has been fixed.
+97-06-30 A bug caused by a race condition that could cause SIGTERM
+ to be ignored by a child process has been fixed.
+97-06-30 A bug which prevented the startup of a coprocess immediately
+ after killing a running coprocess has been fixed.
+97-06-30 ulimit foobar, where foobar is not an arithmetic
+ expression, now gives an error message as it did with ksh88
+ instead of setting the file size limit to 0.
+97-06-30 A bug which could cause an interactive shell to terminate when
+ the last process of a pipeline was a POSIX function was fixed.
+97-06-30 A bug which could cause command substitution of a shell script
+ to core dump has been fixed.
+97-06-30 A security hole was fixed in suid_exec.
+97-06-30 Arithmetic functions such as pow() that take more than
+ one argument, did not work if arguments other than the
+ first contained parenthesized sub-expression.
+97-06-30 The error message from a script containing an incomplete
+ arithmetic expression has been corrected.
+97-06-30 A bug which caused a core dump on some machines when
+ the value of a name reference contained a positional
+ parameter and the name reference was not defined inside
+ a function has been fixed.
+97-06-30 Arithmetic expressions now correctly handle hexadecimal
+ constants.
+97-06-30 A bug in which integer variables could be expanded
+ with a leading 10# when declared with typeset -i
+ multiple times has been corrected.
+97-06-30 A bug in which IFS wasn't correctly restored when
+ set within command substitution has been fixed.
+97-06-30 The _ character is now considered as part of a word
+ with the M-f and M-b emacs directives as it was in ksh88.
+97-06-30 A bug in brace pattern expansions that caused expressions
+ such as {foo\,bar,bam} to expand incorrectly have been fixed.
+
+
+96-07-31 --- Release ksh93e ---
+96-07-31 +The math functions, atan2, hypot, fmod, and pow were added.
+96-07-31 +When a shared library is loaded, if the function lib_init()
+ is defined in the library, it is invoked the first time that
+ the library is loaded with builtin -f library.
+96-07-31 The k-shell information abstraction database option, KIA,
+ has been revamped.
+96-07-31 Empty command substitutions of the form $() now work.
+ whence -v foo now gives the correct result after calling
+ builtin -d foo.
+96-07-31 A bug in right to left arithmetic assignment for which
+ the arithmetic expression (( y = x = 1.5 )) did not
+ yield 1 for y when x was declared typeset -i was fixed.
+96-07-31 printf has been fixed to handle format containing \0
+ and/or \0145 correctly. In addition, characters following
+ %b in the format string are no longer displayed when
+ the operand contains \c.
+96-07-31 A bug in printf that could cause the %E format to
+ produce unnormalized results has been fixed.
+96-07-31 A bug which causes some arithmetic expressions to be
+ incorrectly evaluated as integer expressions rather
+ that floating point has been fixed.
+96-07-31 Functions defined inside a subshell no longer remain
+ defined when the subshell completes.
+96-07-31 The error message from sh -c ';echo foo' has been
+ corrected.
+96-07-31 The format for umask -S has been changed to agree
+ with the specification in the POSIX standard.
+96-07-31 A bug that caused side effects in subscript evaluation
+ when tracing was enabled for subscripts using ++ or --
+ has been fixed.
+96-07-31 To conform to the Posix standard getopts has been changed
+ so that the option char is set to ? when it returns with
+ a non-zero exit status.
+96-07-31 The handling of \} inside ${name...} has been fixed so
+ that the \ quotes the }.
+96-07-31 A bug that caused the read builtin to resume execution
+ after processing a trap has been fixed.
+96-07-31 [[ -s file ]] has been fixed so that if file is open
+ by ksh, it is flushed first.
+96-07-31 In some cases attributes and sizes for non exported
+ variables weren't being reset before running a script.
+96-07-31 The value of TMOUT was affected by changes make to
+ it in a subshell.
+96-07-31 The jobs command did not reflect changes make by
+ sending the CONT signal to a command.
+96-07-31 The error message for ksh -o unknown was incorrect.
+96-07-31 Functions invoked as name=value name, did not use
+ values from the calling scope when evaluating value.
+96-07-31 A bug in which the shell would reexecute previously
+ executed code when a shell script or coprocess was
+ run in the background has been fixed.
+96-07-31 A bug in which an empty here-document would leave
+ a file descriptor open has been fixed.
+96-07-31 A bug in which $(set -A array ...) would leave a
+ side effect has been fixed.
+96-07-31 A discipline function for a global variable defined
+ within a function defined with the function keyword,
+ incorrectly created a local variable of the same name
+ and applied the discipline to it.
+
+95-08-28 --- Release ksh93d ---
+95-08-28 The \ character was not handled correctly in replacement
+ patterns with ${x/pattern/replace}.
+95-08-28 A bug with read in which the line did not end with
+ a new-line has been fixed.
+95-08-28 A bug in file name generation which sometimes
+ appended a . for filenames that ended in / has
+ been fixed.
+95-08-28 +If a process is waited for after a status has
+ been returned by a previous wait, wait now
+ returns 127.
+95-08-28 A bug with hist (fc) -e which prevented a command
+ to re-executed after it had been edited has been fixed.
+95-08-28 A bug which prevented quoting from removing the meaning
+ of unary test operators has been fixed.
+95-08-28 A bug with typeahead and KEYBOARD traps with the
+ MULTIBYTE option set has been fixed.
+95-08-28 +Builtin functions can take a third argument which is
+ a void*.
+95-08-28 The nv_scan() function can restrict the scope of a walk
+ to the top scope.
+
+95-04-31 --- Release ksh93c ---
+95-04-31 The expansion of "$@" was incorrect when $1 was the null
+ string.
+95-04-31 A bug which could incorrectly report a syntax error in
+ a backquoted expression when a $ was preceded by \\
+ has been fixed.
+95-04-31 A bug which prevented the shell from exiting after
+ reporting an error when failing to open a script
+ has been fixed.
+95-04-31 A bug that could lead to memory corruption when a
+ large here document that required parameter or command
+ substitution was expanded has been fixed.
+95-04-31 A bug that could cause a core dump on some systems
+ after ksh detected an error when reading a function
+ has been fixed.
+95-04-31 A bug which could cause a coprocess to hang when
+ reading from a process that has terminated has been fixed.
+95-04-31 A bug which caused a script to terminate when set -e
+ was on and the first command of and && or || list
+ failed has been fixed.
+95-04-31 A bug with here documents inside $(...) when the delimiter
+ word is an identifier has been fixed.
+95-04-31 A bug which caused $0 to display the wrong value when
+ a script was invoked as an argument to the . command
+ and the eval command has been fixed.
+95-04-31 A bug that could cause the built-in sleep to hang
+ has been fixed.
+95-04-31 A bug introduces in 12/28/93b which caused the backslash
+ to be removed when it was followed by digit inside double
+ quotes in some instances has been fixed.
+95-04-31 A bug which could cause a core dump if ksh was invoked with
+ standard input closed has been fixed.
+95-04-31 A bug which could cause a core dump if typeset -A was
+ specified for an existing variable has been fixed.
+95-04-31 Variables that were unset but had attributes such as readonly
+ and export were not listed with readonly, export and typeset.
+95-04-31 Several problems with signals have been fixed.
+95-04-31 A bug which prevented ulimit -t from working has been fixed.
+ Also, a bug in which failed ulimits could cause a core dump
+ has also been fixed.
+95-04-31 A bug in expansion of the form ${name/#pattern/string} and
+ ${name/%pattern/string} has been fixed.
+95-04-31 A bug which caused read -r on a line that contained only
+ blanks to get a non-null value has been fixed.
+95-04-31 A bug introduced in the 'a' point release in which
+ ${x='\\'} expanded to \ when x was unset has been fixed.
+95-04-31 A bug which prevented a trap on EXIT from being executed
+ when the last command in a script was a function invocation
+ has been fixed.
+95-04-31 A bug which caused an interactive shell ignore input when
+ standard error was redirected to a file with exec,
+ and then restored with exec 2>&1 has been fixed.
+95-04-31 An interactive shell turns on monitor mode even when
+ standard error has been redirected to a file.
+95-04-31 A bug which could cause standard input to be incorrectly
+ positioned for the last command of a script has been fixed.
+95-04-31 A bug in the edit modes which allowed walking back in
+ the history file for more than HISTSIZE commands has
+ been fixed.
+95-04-31 A bug which could cause a core dump if variable TMPDIR was
+ changed between two command substitutions has been fixed.
+95-04-31. A bug which prevented a trap on EXIT from being cleared
+ has been fixed.
+95-04-31 A bug fixed for the v directive in vi MULTIBYTE has been
+ fixed.
+95-04-31 Code to for IFS handling of multibyte characters has
+ been added.
+95-04-31 The displaying of multibyte strings in export, readonly,
+ typeset, and execution traces has been fixed.
+95-04-31 Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+95-04-31 Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+95-04-31 A few changes have been made to the name-value library
+ that affect built-ins that use disciplines. The
+ changes allow disciplines to be shared by variables
+ and should make it possible to add new disciplines
+ without recompilation.
+95-04-31 +The name-value library interface has undergone significant
+ change for this revision. See the new nval.3 man page.
+
+94-12-31 --- Release ksh93b ---
+94-12-31 +Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+94-12-31 +If IFS contains two consecutive identical characters belonging
+ to the [:space:] class, then this character is treated as
+ a non-space delimiter so that each instance will delimit
+ a field. For example, IFS=$'\t\t' will cause two consecutive
+ tabs to delimit a null field.
+94-12-31 +The getopts command has a -a name option that specifies a
+ name that will be used for usage messages.
+94-12-31 A bug which caused unset RANDOM to dump core has been
+ fixed.
+94-12-31 A bug which prevented return for terminating a profile
+ or ENV file has been fixed.
+94-12-31 A bug which prevented standard input from being
+ directed to /dev/null for background jobs when
+ monitor mode was turned off has been fixed.
+94-12-31 Statements of the form typeset -options var[expr]=value
+ did not perform substitutions on expr as expected.
+94-12-31 A bug which prevented the shell from sending a HUP
+ signal to some background jobs that were not disowned
+ has been fixed.
+94-12-31 A bug which allowed a script to trap signals that are
+ ignored at the time that the shell was invoked by exec
+ has been fixed.
+94-12-31 A bug which could cause a core dump when a discipline
+ function was unset within a discipline was fixed.
+94-12-31 The typeset builtin now accepts a first argument of
+ + or - for compatibility with ksh88.
+94-12-31 For compatibility with ksh88, the results of expansions
+ of command arguments will treat the extended character
+ match characters ()|& as ordinary characters.
+94-12-31 A bug which caused read to fail on a file that was
+ open for read/write with <> when the first operation
+ was print or printf has been fixed.
+94-12-31 When a job is suspended, it is put on the top of
+ the job list as required by the POSIX standard.
+94-12-31 The value of OPTARG when an option that required
+ an argument but didn't have one was incorrect in the
+ case the the option string began with a :.
+94-12-31 A bug which caused the terminal to get into a bad
+ state with some KEYBD traps in vi-mode has been fixed.
+94-12-31 A bug which caused an invalid trap to cause a script
+ to terminate, rather than just return an error, has
+ been fixed.
+94-12-31 Backreferencing sub-expressions in patterns and replacement
+ strings now works.
+94-12-31 A bug in chmod which caused the -R option to fail has
+ been fixed.
+94-12-31 +More signal names have been added for Solaris
+
+94-06-30 --- Release ksh93a ---
+94-06-30 An expansion bug which causes portions of a word after
+ a $((...)) expansion that contains a nested $var expansion
+ to be lost has been fixed.
+94-06-30 A bug that caused a core dump when a script that did not
+ have PWD set and did a cd inside command substitution
+ has been fixed.
+94-06-30 A bug which caused a core dump on some machines when
+ the LANG variable was assigned to has been fixed.
+94-06-30 A bug which incorrectly handled set disciplines that
+ performed arithmetic evaluation when the discipline
+ was called from the arithmetic evaluator has been fixed.
+94-06-30 A bug caused by an EXIT trap inside a function that
+ was executed in a subshell was fixed.
+94-06-30 If foo is a function, and not a program, then command foo
+ now reports that foo isn't found rather than invoking foo.
+94-06-30 The previous version incorrectly listed -A as an
+ invocation option. The -A option is only for set.
+94-06-30 A bug was fixed which caused ksh to loop when execution trace
+ was enabled and the PS4 prompt required command substitution.
+94-06-30 A bug which could cause the job control switch character
+ to be disabled when a script that enabled monitor mode
+ terminated was fixed.
+94-06-30 A bug in the macro expansion global replacement operator //,
+ when the pattern began with a [ or +( has been fixed.
+94-06-30 A bug which prevented ~ expansion from occurring when
+ it was terminated with a colon inside an assignment
+ has been fixed.
+94-06-30 A bug in the dot command which prevented autoload functions
+ from working has been fixed.
+94-06-30 A bug which caused a variable to be unset if the
+ its value were expanded inside a set discipline has
+ been fixed.
+94-06-30 Whence -a now longer reports that a defined function
+ is undefined.
+94-06-30 A bug on some systems in which $0 would be incorrect
+ in scripts invoked by name has been fixed.
+94-06-30 Here documents with an empty body now work.
+94-06-30 A bug which disabled argument passing and resetting
+ of options for a script invoked by name inside a
+ function has been fixed.
+94-06-30 A bug in which an EXIT trap set the caller of a function
+ would be executed if a command called inside a function
+ was not found has been fixed.
+94-06-30 A bug which allowed a script to trap signals that are
+ ignored at the time that the shell was invoked has
+ been fixed.
+94-06-30 A bug which caused 2<&1- when applied to a shell built-in
+ to leave standard input closed has been fixed.
+94-06-30 A bug which caused the shell to incorrectly parse
+ $() command substitutions with nested case statements
+ has been fixed.
+
+
+:::::::: libast ::::::::
+
+12-03-10 misc/optget.c: HELP_index for "PLUGIN" too
+12-02-29 include/shcmd.h: PLUGIN_VERSION 20111111 for cdt disc/meth change
+12-02-29 comp/spawnveg.c: fix sigcritical() to include waitpid() for internal child
+12-02-29 malloc.c: make __malloc_hook initialization thread safe
+12-02-24 comp/iconv.c: fix winix UTF-8 vs UCS-2 over-conversion
+12-02-24 astsa/*.h: clean up header guards
+12-02-24 astsa/astsa.omk: clean up standalone old make makefile interactions
+12-02-21 misc/cmdarg.c: fix bug that set argv[0]
+12-02-10 sfvprintf.c: fix 1 byte too long buffer access
+12-02-07 malloc.c/features/vmalloc: add gnu __malloc_hook tests
+12-02-06 vmmopen.c: fix ALIGN vs sys/param.h macro conflict
+12-02-02 astlicense.c: add license.component for component-specific licenses
+12-01-31 spawnveg.c: fix transient bug that made invalid setpgid() call
+12-01-27 pathpath.c: fix buffer size math when internal allocation requested
+12-01-24 malloc.c: fix _vmkeep() bug that did not return previous state
+12-01-23 malloc.c: add VMALLOC_OPTIONS=break to try sbrk() block allocator first
+12-01-21 astlicense.c: option style only overrides default license.type
+12-01-18 malloc.c: disable multiple regions for tracing or !vmbest or ASO_SIGNAL
+12-01-12 sfpkrd.c: add __sun I_PEEK+rsh runtime workaround
+12-01-10 shcmd.h: void* => Shbltin_t*
+12-01-10 tmxdate.c: handle { n>=1000 } TM_PARTS
+11-12-21 plug up some meory links -- thanks mhlavink
+11-12-21 vmprivate.c: enclose VM_NONMEM exception in CLRLOCK(vm,0) ... SETLOCK(vm,0)
+11-12-13 aso: in -lposix for uwin, not -last -- just like vmalloc
+11-12-13 sfpoll.c: all streams SF_IOINTR => don't ignore EINTR
+11-12-13 sfdcslow.c: set SF_IOINTR
+11-12-09 malloc.c: add _vmkeep() for setlocale() intercept _SYS_setlocale_free_OK
+11-12-04 sfio: _Sfmaxr=0 (unlimited) by default; use ulimit -M|-d or SFIO_OPTIONS
+11-12-01 aso: sync to new api
+11-11-11 optget.c: move .TH to the top for --nroff to get our macros first
+11-11-11 aso,cdt,vmalloc: resync with kpv
+11-11-11 cdt: preserve bits and Dt_link_t for CDT_VERSION < 20111111
+11-10-24 sfvprintf.c: %.-ns truncate from left to n chars
+11-10-21 sfvprintf.c: fix %0s (no width) core dump
+11-10-10 aso: add _WIN32 support
+11-09-26 vmalloc: sync with kpv
+11-08-29 features/{dirent,wchar,wctype}: eliminate #include with no header
+11-08-25 #pragma prototyped tweaks -- sun4 is dead, long live sun4
+11-08-25 ftwalk.c: FTS_SLNONE => FTW_SL
+11-08-11 features/wchar: fix #include _nxt_wchar for K&R C
+11-08-04 optget.c: tweak --html rendering
+11-07-24 mime.c: add %(default)[st] default if arg == ""
+11-07-21 setlocale.c: fix debug locale to treat "<<" as two single byte chars
+11-06-14 spawnveg.c: pgid -1: new session -2: setpgrp()&&tcsetpgid()
+11-06-14 pathprog.c: add darwin _NSGetExecutablePath
+11-05-14 features/common,features/align.c: { _X86_ _X64_ } conditionals for generic uwin
+11-05-13 tm/tminit.c: tweak tzname[] prototype
+11-05-09 astlicense.c: add ". file" parent-relative include and depth 4 input stack
+11-05-05 cmdarg: update to cmdopen_20110505 api
+11-05-03 sfio/sfclose.c: make sure close() errors propagate to sfclose() return value
+11-04-20 port/astlicense.c: add { id name } keys
+11-04-15 fmtdev.c: fix to work for non-{blk,chr} special
+11-04-12 stk: change size args to size_t and stseek() offset to ssize_t
+11-04-12 sfio: sync with kpv to optimize large SF_STRING sfputr() buffer allocation
+11-03-28 misc/fts.c: fix FTS_SLNONE logic to set it when it should!
+11-03-17 misc/stk.c: fixed bug that could delete an active stack frame
+11-03-10 sfio/sfvprintf.c: add %0<width>s to preserve <width> trailing chars in string arg
+11-03-09 misc/magic.c: add %d...%s where if %d==1 then %s=="" else %s=="s"
+11-03-09 misc/magic.tab: add windows ico
+11-02-08 misc/stk.c: change STK_FSIZE to (1024*sizeof(char*)) for 64 bit normalization
+11-02-02 sfio/sfmode.c: don't call sfsetbuf() on unbuffered stream to make it unbuffered
+11-02-02 features/wchar: handle hp.ia64 va_list interactions
+11-02-02 comp/omitted.c: fix mismatch between stat() vs _stat()
+11-01-31 std/wctype,features/wctype: add to handle <wchar.h> interactions
+11-01-28 add -lw for ancient sunos
+11-01-28 include/magic.h,misc/magic.c: add MAGIC_ALL
+11-01-27 tm/tmxfmt.c,tmpoff.c: %_z for SHH:MM
+11-01-25 features/wchar: change <wctype.h> <wchar.h> ordering
+10-12-24 sfstrtof.h: fix thousand grouping bug that did not check last group
+10-12-21 pathkey.c: add win32 { /32 /64 } preroot to hash
+10-12-09 pathprog.c: handle intermediate path != '* and fix invalid pathpath() call
+10-12-01 astconf.c: fix look.standard undefined variable reference
+10-12-01 sfset.c: SF_LINE|SF_WCWIDTH => no need for sfsetbuf() to call isatty()
+10-12-01 sfsetbuf.c: cache /dev/null <dev,ino> to cut down /dev/null stat()'s
+10-12-01 optget.c: delay dictionary initialization until needed
+10-11-30 malloc.c: drop { VMDEBUG VMETHOD VMPROFILE VMTRACE } env checks
+10-11-30 port/astconf.c: eliminate esaccess() calls for OP_universe checks
+10-11-24 regcomp.c: [[=]=]] must at least match itself in non-C locales
+10-11-23 glob.h,glob.c: add GLOB_GROUP => REG_SHELL_GROUP
+10-11-20 glob.c: handle mode switches across /
+10-11-19 regcomp.c: REG_SHELL => REG_CLASS_ESCAPE
+10-11-16 vmalloc.h: add VMFL tracing to vmstrdup()
+10-11-16 ast.h: simplify VMDEBUG _BLD_DEBUG and VMFL logic
+10-11-12 tm/tmlocale.c: ast TM_* extensions default to C locale
+10-11-10 regex/regnexec.c,vmalloc/vmstat.c: eliminate strict-aliasing puns
+10-10-20 misc/translate.c: change debug translation to drop " in (a,b,c,"d")
+10-10-10 misc/glob.c: drop ancient D_FILENO(d)!=0 test and trust readdir()
+10-10-06 misc/translate.c: fix "debug" locale logic
+10-10-04 misc/magic.c: fix magic() skip check to honor the continuation
+10-10-04 regex/regcoll.c: add wchar_t* args to regcollate(), drop ucs name lookup
+10-09-28 comp/setlocale.c: add utf8_wctomb()
+10-09-28 string/chresc.c,regex/regcoll.c: fix \S[.X.] (\C[.X.] never worked!)
+10-09-24 string/chresc.c: \Cc for control c, \S[.X.] for collating symbol X
+10-09-24 string/chresc.c: { \cc \e } deprecated
+10-09-22 regex/regcomp.c: fix off-by-one collation class allocation bug
+10-09-20 regex/regclass.c: fix CTYPES off-by-one bug
+10-09-14 comp/conf.sh: const int conf_elements, prefix_elements;
+10-09-08 add features/sizeof => ast_sizeof.h
+10-08-31 comp/getopt[l].c: export functions for dlls
+10-08-25 port/lc.c: add features/locale check for canonical UTF-8 spelling
+10-08-20 include/ast.h: add export plugin_version() prototype
+10-08-20 comp/conf.tab: add SF_BUFSIZE
+10-08-11 misc/conformance.c: conformance(0,0) => "standard"
+10-08-11 misc/conformance.c: check ast_env_serial for dynamic astconf() changes
+10-08-11 port/lcgen.c: remember to fudge Table_t.count for synthesized entries
+10-08-04 include/ast.h,comp/setlocale.c: add { debug C.UTF-8 } mbalpha() mbwidth()
+10-08-02 misc/translate.c: add NLSPATH message cache check
+10-07-29 string/fmtint.c: fix nasty bug that rendered "1000" as "1"
+10-07-27 setlocale,lsgen,localeconv: handle C vs C_EU decimal thousands sep
+10-07-26 misc/optget.c: fix interaction with nested plugin/builtin calls
+10-06-29 string/strtoi.h: strton() multiplier 1 => power of two suffix
+10-06-28 features/wchar: handle systems that require __va_list => va_list
+10-06-28 comp/conf.tab: another PID_MAX tweak -- default to 99999 for most
+10-06-28 port/astconf.c: lone "CONFORMANCE = standard" => all defaults standard
+10-06-25 misc/optget.c: avoid sfprints() call during initialization
+10-06-01 features/api, ast_api.h: formalized forwards/backwards api compatibility
+10-06-01 _AST_API=20100601: add size_t args for all path*() output buffers
+10-06-01 comp/setlocale.c: handle C.UTF-8 test locale
+10-06-01 include/mc.h: add size_t to mcfind() for result buffer (internal api)
+10-06-01 use strlcpy() instead of strncpy()
+10-05-28 include/ast_version.h: add AST_PLUGIN_VERSION for dllplugin()
+10-05-28 include/shcmd.h: add SH_PLUGIN_VERSION for dllplugin()
+10-05-28 misc/conformance.c: add conformance(3)
+10-05-28 misc/optget.c: add [(id1|id2)...] conformance("id1|id2",0) conditionals
+10-05-25 include/sfhdr.h: adjust SF_NMAP according to _ptr_bits
+10-05-25 include/shcmd.h: add sh_builtin() macro for lib_init() table initialization
+10-05-21 misc/optget.c: --html \bfoo::bar([[:digit:]][[:upper:]]*) => foo-bar.html
+10-05-15 include/proc.h,misc/procopen.c: add PROC_ORPHAN
+10-05-09 misc/optget.c: add --???MAN[section] --???SECTION
+10-05-07 sfio,stdio: fix all snprintf() variants to handle buf==0 and/or n==0
+10-05-04 string/fmtesc.c: add mb iswsoace() and iswcntrl() quoting checks
+10-05-03 fix LC_MESSAGES catalog lookup bugs, check for $set==3, accept $set==1
+10-04-30 string/chresc.c: add chrexp() for FMT_EXP_*
+10-04-30 string/stresc.c: add strexp() for FMT_EXP_*
+10-04-30 string/chresc.c: fix \uXXXXY bug that consumed Y
+10-04-22 misc/optget.c: check for html entities in <A name="...">
+10-04-22 misc/getcwd.c: add features/syscall check for SYSGETCWD() { linux solaris }
+10-04-22 string/stresc.c: wide chars absent locale guidance default to UTF-8
+10-04-12 port/mnt.c: favor bsd getfsstat() over getmntinfo()
+10-04-11 string/strtoi.h: k (1000) and ki (1024) now differentiated
+10-04-10 misc/recstr.c: fix 'd[delimiter]' parse
+10-04-08 include/vmalloc.h,vmalloc/vmstat.c: add Vmstat_t.mode region mode bits
+10-04-05 misc/fts.c: drop 1997-01-07 fts_open()=0 is one file and stat() fails
+10-04-05 misc/optget.c,optlib.h: add Optpass_t.release for --nroff .TH
+10-04-02 misc/optget.c: fix $'[-n?\n...]' --version bug
+10-04-02 regex/regcomp.c: ~(X) => REG_EXTENDED|REG_AUGMENTED, ~(PU) instead of ~(U)
+10-03-24 misc/procopen.c: add PROC_FD_CTTY(fd)
+10-03-24 path/pathtemp.c: fix pointer => int casts
+10-03-15 regex/regcache.c: fix 1 byte buffer overflow (didn't count trailing \0)
+10-03-08 features/tvlib: fix utimensat probe to include all macros/structs
+10-03-07 features/lib: change stream_peek to test pipes only
+10-03-07 string/strelapsed.c: fix next char return overrun
+10-03-06 tm/tvtouch.c: use runtime fallback if utimensat() fails with ENOSYS
+10-03-05 path/pathtemp.c: add pfx /seed for regression testing
+10-03-04 vmalloc/vmwalk.c: add user supplied handle arg
+10-03-04 path/pathtemp.c: properly handle mktemp()-style *+(X) templates
+10-03-03 include/ast_getopt.h: remove NULL guard - _AST_GETOPT_H now handles it
+10-02-24 comp/getopt.h: fix ast_std.h interactions
+10-02-24 vmalloc/malloc.c: empty { VMALLOC_OPTION VMDEBUG ... } => no debug!
+10-02-02 string/base64.c: fix corner case output buffer overflow
+10-02-02 features/fs: sys/mnttab.h requires stdio.h on some systems!!
+10-02-01 misc/optget.c: uppercase --html heading -- doh
+10-01-29 misc/optget.c: [+NAME?...] overrides error_info.id for >= STYLE_man
+10-01-25 vmalloc/vmprivate.c: fix seg ptr initialization bug (24 years old!!)
+10-01-20 misc/optget.c: handle nested {...} rendering
+10-01-20 misc/state.c: add ast.version for runtime api version
+10-01-20 port/astconf.c: "_AST_VERSION" now returns ast.version
+10-01-20 include/ast_std.h: add ast.version for runtime api version
+10-01-19 astlicense.c: add epl
+10-01-01 vmalloc: VMALLOC_OPTIONS env var for all runtime options
+10-01-01 include: change some <ast.h> refs to less intrusive <ast_*.h>
+10-01-01 setlocale.c,translate.c,fmterror.c: AST_LC_internal retains prev state
+10-01-01 comp/setlocale.c: AST_LC_setenv defers to LC_ALL (for sh)
+10-01-01 ast_std.h: add { AST_LC_internal AST_LC_setenv }
+09-12-24 comp/setlocale.c: fix setlocale(LC_ALL,"") when already initialized
+09-12-17 misc/optget.c: handle mixed solaris usage="x:f:(in)yo:(out)"
+09-12-11 regex/regcomp.c: posix semantics for [z-a]
+09-12-11 regex/regcomp.c: fix BRE/ERE ^^ logic
+09-12-11 regex/regcomp.c: fix regcomb() for REG_LEFT|REG_RIGHT
+09-12-11 regex/regcomp.c: bm complete=0 if REX_END
+09-12-11 comp/sigflag.c: add with npt check in features/sig.sh
+09-12-11 tm/tminit.c: fix _tzset_environ logic
+09-12-09 tm/tmlocale.c: include "ast_nl_types.h" to pull nl_langinfo in!
+09-12-04 features/options: add "opt map-libc" check
+09-12-03 tm/tmxdate.c: fix 'next month final day' for dec -> jan
+09-11-21 misc/magic.tab: add gimp XCF
+09-11-20 vmalloc/vmtrace.c: add pid to assertion disgnostics
+09-11-11 regex.h,regcomp.c: add REG_CLASS_ESCAPE, \ inside [...] literal by default
+09-11-03 regex/regcache.c: change to variable length pattern strings
+09-10-28 include/error.h: fix ERROR_translate() arg parens
+09-10-26 port/lcgen.c,comp/setlocale.c: handle LANG init after LC_* already defined
+09-10-05 _sfopen.c: add but ignore 'F' flags for stdio compatibility
+09-09-28 fts.h,ftwalk.h,fts.c: promote { namelen pathlen level } to (s)size_t
+09-09-28 locales: add AST_LC_LANG for $LANG
+09-09-28 setlocale.c: fix logic for dynamic { LANG LC_ALL LC_* } changes
+09-09-17 include/sfio.h,sfio/sfwalk.c: add sfwalk()
+09-09-09 sfio/sfputr.c: add SIGPIPE hang fix
+09-08-24 sfio/sfreserve.c: fix SF_UNBOUND logic with pushed streams
+09-08-18 include/ast_std.h,ast.h: add ast.mb_sync to sync mbchar() after error
+09-08-17 comp/setlocale.c: add AST_LC_utf8 and { utf8_mbtowc() utf8_mblen() }
+09-08-11 comp/setlocale.c: treat "en"/"en_US" AST_LC_MESSAGES as "C"/"POSIX"
+09-08-10 vmalloc/vmhdr.h: add user-defined _AST_PAGESIZE and computed VMHEAPINCR
+09-08-09 comp/conf.tab: add NPROCESSORS_MAX
+09-07-29 astlicense.c: fix first name=value logic error
+09-07-22 string/fmtip6.c: don't drop trailing 0 in 44::1:0:0
+09-06-30 port/astconf.c: standard PATH_RESOLVE is "physical" (not "metaphysical")
+09-06-19 vmalloc: sync with kpv
+09-06-19 include/shcmd.h: add sh_context(p) cast
+09-06-11 misc/magic.tab: differentiate pc 386 32/64 bit dll/exe/obj
+09-06-06 port/astconf.c: fix look->name null pointer reference
+09-06-05 port/astconf.c: fix 'UNIVERSE = value' synthesize logic
+09-05-25 tm/tmxduration.c: add
+09-05-08 comp/syslog.c: add _UWIN /var/log/syslog preference
+09-05-01 comp/setlocale.c: fix _UWIN intercepts to return NiL on unknown locales
+09-04-27 sfio/sfpool.c: fix bug that did not return pool on delete
+09-04-22 include/regex.h,regex/regcomp.c: add REG_REGEXP <regexp.h> compatibility
+09-04-15 tm/tmxdate.c: handle "4th thursday in november"
+09-03-31 string/strvcmp.c,string/strnvcmp.c: add version strcmp(3)
+09-03-31 string/strpcmp.c,string/strnpcmp.c: add path prefix strcmp(3)
+09-03-29 misc/optget.c: clean up num = number casts
+09-03-04 tm/tmxmake.c: add tmxtm() with zone override
+09-03-03 tm/tmxfmt.c: add %(...)<c>, specifically %(...)z for output zone
+09-02-22 tm/tmxdate.c: add iso P... durations
+09-02-02 path/pathprog.c: add
+09-02-02 misc/opthdr.h,optget.c: fix flags mixup, handle old '-' as option
+09-02-02 sfio/sfprints.c: fix sfvaprints() return value to not count trailing '\0'
+09-02-02 misc/cmdarg.c: handle !defined(ARG_MAX)
+09-02-02 port/astconf.c: fix UNIVERSE overwrite of null[] value!
+09-01-31 features/sys: drop header sys/localedef.h
+09-01-28 include/fs3d.h,misc/fs3d.c: mount() => fs3d_mount() for diff std prototypes
+09-01-14 misc/fts_open.c: delay top list reorder until first fts_read()
+09-01-14 include/ls.h: LS_W_INUMBER => 9 to accomodate large st_ino
+09-01-14 misc/optget.c: expand STYLE_usage input text
+09-01-09 features/uwin,stdio/_stdfun.c: iffe for _p__iob and __p__iob
+09-01-09 misc/magic.tab: add ISO filesystem image entries
+09-01-07 string/strtoi.c: strtol() etc. do not consume [lLuU] suffix -- thanks jkf
+09-01-07 sfio/sfstrtof.h: strtod() etc. do not consume [fFlL] suffix -- thanks jkf
+09-01-05 string/strlcat.c: fix logic to match docs (not that easy)
+08-12-30 tm/tmxdate.c,include/tm.h: add TM_WORK { "workday" "working" "work" }
+08-12-28 sfio/sfcvt.c: fix 'a' format rounding
+08-12-21 tm/tmdata.c: add 2008-12-31+23:59:60-0000 leap second event
+08-12-19 tm/tmxdate.c: check for dates near the epoch rolling back to the future
+08-12-19 tm/tmxfmt.c: change %s for now==0 to be the epoch
+08-12-07 include/ast_std.h,misc/getenv.c: no _ast_getenv for uwin ast54 compatibility
+08-12-07 tm/tmxfmt.c: add %[_][EO]K for [space pad] [full|long] iso
+08-12-07 sfio/sfvscanf.c: fix ok[] short by one allocation
+08-12-07 comp/setlocale.c: fix off by one composite initialition loop test
+08-12-07 path/pathkey.c: fix off by one loop test
+08-12-04 vmalloc/vmbest.c: catch sbrk() wraparound
+08-12-04 comp/spawnveg.c: clean up attrs on failure too
+08-11-04 regex/regcomp.c: fix locale [!-...] and [^-...] re-initialization
+08-11-04 stdio: add flockfile.c ftrylockfile.c funlockfile.c
+08-10-24 port/astconf.c: handle multiple/trailing '/' in universe initialization
+08-09-10 misc/magic.c: handle old vcodex() indices
+08-09-10 sfio/sfvprintf.c: drop SF_WCWIDTH, use %Lc or %Ls instead
+08-09-05 Makefile: ibm.risc joins the :NOOPTIMIZE: crowd
+08-09-04 regex/regnexec.c: fix nested delimiter match beyond end of subject
+08-08-20 misc/fts.c: fix st_nlink stat() optimization logic
+08-08-19 sfio/sfpkrd.c: workaround macosx recv(PEEK) data consumption on non-socket
+08-08-19 strn?tol?d: handle long double with smaller exponent range than double
+08-08-18 sfio/sfcvt.c: eliminate excessive multiplies and integral overprecision
+08-08-11 tm/tmxfmt.c: handle %10N and %010N
+08-08-06 include/shcmd.h: add 'int invariant;' for builtin invariant arg count
+08-08-05 features/ndbm: favor sleepycat ndbm compatibility
+08-07-21 include/glob.h,misc/glob.c: GLOB_STARSTAR only forces lstat on chdir
+08-07-17 sfio: sync with kpv
+08-07-17 misc/optget.c: call astwinsize() each time terminal width required
+08-07-16 sfio/sfvscanf.c: fix %% to skip leading space per posix
+08-07-16 vmalloc/vmbest.c: add VMCHECK=m, VM_mmap to favor mmap() alloc
+08-07-16 features/stdio,stdio/f(read|write).c: size_t return value!! ouch
+08-06-24 tm/tmxfmt.c: fix %z to handle tm_isdst -- doh
+08-06-24 misc/astintercept.c,misc/getenv.c: split from misc/setenviron.c
+08-06-17 misc/setenviron.c: add { astintercept() getenv() }
+08-06-09 tm/tmlocale.c: use _DATE_FMT if defined for TM_DEFAULT
+08-06-06 misc/optget.c: handle sub-component about details
+08-06-04 misc/optget.c: fix [-n?\n...\n] version parse
+08-06-04 include/debug.h,misc/debug.c: merge with kpvdebug.h
+08-06-02 features/ndbm: add to tame dbmlib.iffe replication
+08-06-01 comp/resolvepath.c,realpath.c: fix resolvepath() return value type
+08-05-22 tm/tmxdate.c: fix a few ordinal/last/this/next bugs
+08-05-18 string/fmtre.c: fix omitted stack var initialization bug
+08-05-14 regex/regcomp.c,regcoll.c: fix UTF-8 collation sequence logic
+08-05-11 tm/tmxfmt.c: :NOOPTIMIZE:, otherwise %Q/../../ fails
+08-05-01 tm/tmxdate.c: mon 1..12 => mon[13] -- doh
+08-04-30 misc/glob.c,reegex/regcomp.c: ~(R) => ~(O) to avoid pcre clash
+08-04-24 port/astconf.c: 'name = value' does assignment without system init
+08-04-15 port/astconf.c: SC#N treated like 'SC(N)'
+08-04-14 misc/optget.c: clean up nroff output
+08-04-01 port/astconf.c: add RELEASE => /proc/version fallback
+08-03-30 misc/optget.c: [-n]... to enable -number & +number options
+08-03-06 misc/optget.c: ---* and +++* are now operands
+08-03-06 misc/errorx.c: fix old error_info.translate workaround
+08-02-05 regex/regcomp.c: allow REG_SHELL {,n}... => {0,n}...
+08-02-27 misc/stk.c: top element during allocation relocated to top
+08-02-18 include/ip6.h,string/strtoip6.c,fmtip6.c: add ipv6 addr support
+08-02-14 regex/regsubexec.c: fix null match (tricky)
+08-02-14 regex/regsubcomp.c: fix SRE to match ksh
+08-02-11 comp/spawnveg.c: return proper errno on [v]fork() failure
+08-02-11 tm/tmxdate.c,tmdata.c: handle more ISO 8601:2000 forms
+08-02-02 regex/reglib.h: add REGMULTIREF to REG_COMP
+08-02-02 string/strmatch.c: fix str="" pat="" sub values
+08-01-31 comp/conf.sh,conf.tab: handle /bin/sh \ in read data, redir subshell
+08-01-18 misc/magic.tab: amd-x68, 64-bit => x86-64
+08-01-18 string/strnton.c,strntonll.c: add
+07-12-10 string/strelapsed.c: "0" is a valid elapsed time!
+07-12-02 sfio/sfreserve.c: preserve SF_SHARE sfrd() via sfreserve(f,0,0)
+07-11-21 comp/setlocale.c: add sjis_mbtowc() to work around [\~] translation
+07-11-15 features/signal.c: RT(1) .. RT(MAX-1) => RTMIN+1 .. RTMAX-1
+07-11-14 features/float: favor sscanf() due to gnu strto[l]d() nan bugs
+07-10-31 regex/regcomp.c: fix REX_COLL_CLASS node allocation size
+07-10-31 sfio/sfcvt.c: use signbit() if available
+07-10-31 features/isoc99: _ISOC99_SOURCE tests
+07-10-31 port/astmath.c: add -DN=8 for signbit()
+07-10-31 sfio/sfstrtod.h: don't forget about -0.0
+07-10-26 features/map.c: add { optopt optarg optind opterr }
+07-10-26 features/stdio: add _filbuf => _ast__filbuf
+07-10-26 comp/getsubopt.c: fix #undef that interfered with <ast_map.h>
+07-10-26 regex/regcomp.c: fix bug that missed ')' in ~(F)...
+07-10-12 port/astconf.c: fix CONF_ALLOC 16 bit overflow
+07-10-12 misc/fts.c: fix fts_close() to free the handle -- doh
+07-10-11 comp/setlocale.c: second and subsequent setlocale(*,"") reverts to previous
+07-10-11 path/pathprobe.c: add vfs ST_NOSUID check
+07-10-10 comp/conf.tab: add a few more xpg6 deferrals
+07-09-28 astsa: update to share with mainline src via _PACKAGE_astsa
+07-09-25 sfio/sfgetr.c: no limit on string stream line size
+07-09-25 sfio/sfextern.c: increase _Sfmaxr to 256*1024
+07-09-18 misc/procopen.c: tighten up SIGCHLD logic between parent/child
+07-09-18 misc/signal.c: unblock SIG_DFL after setting handler, sig<0 => don't unblock
+07-09-13 misc/fs3d.c: no $LD_PRELOAD => no 3d and avoids invalid mount(2) call
+07-09-11 vmalloc: vmstat(0,0)==1 => region in use, drop VM_primary|VM_secondary
+07-09-05 misc/recstr.c: handle [lL] gobbled by strtol() -- ouch
+07-08-17 path/pathprobe.c: handle '\r' in VERSION string
+07-07-17 regex/regcache.c: regcache(0,n,0) extends cache to size n (no shrinking)
+07-07-16 tm/tmdata.c: add 2005-12-31, drop 1999-12-31 (where did that come from?)
+07-05-21 tm/tmxfmt.c,tmxscan.c: %F => %L (TM_DEFAULT); %F => %Y-%m-%d
+07-05-15 sfio/sfvprintf.c: %h? and SFFMT_SHORT => raw bytes
+07-05-09 features/signal.c,features/siglist: use kill -l & strsignal()
+07-04-25 misc/optctx.c: add for opt_info switching
+07-04-24 misc/cmdarg.c,include/cmdarg.h: add CMD_CHECKED, CMD_SILENT
+07-04-24 misc/procopen.c,include/proc.h: add PROC_CHECK
+07-04-24 misc/procrun.c: add flags arg (current use PROC_ARGMOD)
+07-04-24 misc/cmdarg.c,include/cmdarg.h: move from src/cmd/tw
+07-04-20 port/(lclang.h|lc.c|mc.c|lclib.h|lcgen.c): separate lctab.c
+07-04-20 comp/conf.sh: defer to systems without 'grep -q' -- sigh
+07-04-20 comp/conf.sh: probe for LL integer constant initializer suffix
+07-04-20 include/syslog.h: <namval.h> => <ast_namval.h> for win32
+07-04-20 ast_namval.h: add as copy of include/namval.h for win32
+07-04-19 comp/conf.tab: fix SVID SI entries to probe SI_* (not _SI_*)
+07-04-13 tm/tmxdate.c,tm/tmzone.c: handle [-+]0000 UTC zone offset
+07-04-11 sfio/sfvprintf.c: add %F, propagate SFFMT_UPPER
+07-04-11 sfio/sfcvt.c: handle SFFMT_UPPER => nan/inf vs. NAN/INF
+07-04-02 comp/conf.tab,comp/conf.sh: add C/POSIX <stdint.h> symbols
+07-03-28 misc/optget.c: fix l10n --?-
+07-03-25 features/common: fix { ast_std.h ast_map.h stdint.h } logic
+07-03-21 error.h: move from error_info to (*_error_data_)
+07-03-21 misc/error.c: add errorctx() for error_info switching
+07-03-21 option.h: move from opt_info to (*_opt_data_)
+07-03-19 regex/regdecomp.c: fix REX_ONECHAR escapes and add REX_KMP
+07-03-11 tm/tmxscan.c,regex/regnexec.c: fix strict-alias transgressions
+07-02-27 comp/conf.sh: handle native getconf invalid numeric values
+07-02-21 comp/conf.sh,comp/conf.tab: handle SSIZE_MAX vs _POSIX_SSIZE_MAX
+07-02-20 sfio/sfvprintf.c: handle SF_WCWIDTH justification
+07-02-14 features/common: cover <stdint.h>, move to int_(bits)_t
+07-02-14 include/int.h: drop
+07-02-14 include/sfio.h: add SF_WCWIDTH
+07-02-12 comp/conf.sh: fix CONF_LIMIT bug that missed ULONG_MAX etc.
+07-02-12 comp/conf.tab: *LONGLONG* => *LLONG* to match posix
+07-02-12 features/float: *LONGLONG* => *LLONG* to match posix
+07-02-12 port/astconf.c: handle CONF_LIMITS_DEF with no deferral
+07-02-12 stdio/vasprintf.c: add trailing '\0' -- doh
+07-02-04 string/fmtelapsed.c: fix naive multi month/year logic
+07-02-02 misc/optget.c: add --??posix for getopts(1)/getopt(3)
+07-01-26 string/chresc.c: use mbchar()
+07-01-26 misc/optget.c: handle "o:-:" usage for old-style long options
+07-01-22 sfio/sfdisc.c,sfpool.c: handle push on streams with pending peek
+07-01-22 include/sfio.h: mv Sfieee_t to sfio/sfhdr.h
+07-01-17 tm/tmxfmt.c: fix terminating nil logic which clobbered size-1
+07-01-11 misc/stk.c: a 2 day marathon bug fix (can we release now dr ek?)
+07-01-05 comp/spawnveg.c: posix_spawnattr_setflags(POSIX_SPAWN_SETPGROUP)
+07-01-05 misc/error.c: fix multibyte vs. printable logic
+07-01-01 comp/conf.sh: LC_ALL=C
+06-12-26 tm/tmxdate.c: handle nn*.nnnn* == sec.ns
+06-12-20 features/libpath.sh: generalize sol.* LIBPATH patterns
+06-12-18 comp/setlocale.c: include ast_standards.h and ast_wchar.h !
+06-12-12 string/strperm.c: octal modes are absolute!
+06-12-11 comp/conf.tab: always defer ARG_MAX
+06-12-07 Makefile: fix conftab.c generation CCFLAGS to match build - doh
+06-12-04 sfio/sfcvt.c: fix (int) vs. (long) cast mismatches
+06-12-01 comp/conf.tab: add changes to cover solaris { bin xpg4 xpg6 }
+06-12-01 regex/reginit.c: adjust { SRE KRE } escaped (){}*? inside [...]
+06-12-01 sfio/sfcvt.c: add signbit/copysign tests
+06-11-22 comp/spawnveg.c: fix _real_vfork logic to work with 3d
+06-11-20 features/common: bias _ast_int8_t "long long" before "__int64"
+06-11-20 string/strperm.c: fix X to work with all ops (not just +)
+06-11-15 astconf.c,conf.tab: add CONF_DEFER_* for variable constants
+06-11-11 port/astconf.c: validate path arg w.r.t. underlying calls
+06-11-11 comp/conf.sh: fix S CONF_STANDARD bug, add D to defer to native
+06-11-11 comp/conf.tab: add D to defer to native
+06-11-01 include/vmalloc.h: avoid VM_FLAGS sys/v*.h clash
+06-11-01 include/ast.h: add FMT_PARAM for fmtquote()
+06-10-31 disc/sfdcseekable.c: add SFSK_DISCARD for seekable window control
+06-10-31 comp/spawnveg.c,features/lib: handle posix_spawn exit status 127
+06-10-30 features/lib: fix posix_spawn() fork() prototype conflicts
+06-10-30 string/fmtscale.c: fix 1024 rounding bugs
+06-10-27 disc/sfkeyprintf.c: handle 'i' (=='d') -- oops
+06-10-26 sfio/sfvprintf.c: %#d => fmtscale(1000), %#i => fmtscale(1024)
+06-10-26 features/map.c: _map_libc cleanup
+06-10-26 features/fcntl: add to the circle of trust
+06-10-26 features/sys: add <sys/socket.h> socklen_t
+06-10-26 include/regex.h: handle include before <ast_map.h>
+06-10-25 astconf "SHELL" => "SH" to avoid _POSIX_SHELL conflict
+06-10-25 comp/conf.*: drop no-op duplicate conftab.c entries
+06-10-18 string/fmtscale.c: 1000: n[.]n[n](kMGTPE), 1024: n[.]n[n](KMGTPE)i
+06-10-11 ast_std.h: now implies <sys/stat.h> (did on most before anyway)
+06-10-11 strtoi.h: ignore sign for 0, validate scale shift
+06-10-11 strdup.c,vmstrdup.c: handle 0 arg
+06-10-11 add sfstruse()/sfstropen() error checks
+06-10-10 misc/procopen.c: envv==environ => don't modify environ
+06-10-10 misc/procclose.c: return valid exit(1) status
+06-10-06 port/astconf.c,comp/conf.sh,comp/conf.tab: play nice with getconf(1)
+06-10-01 comp/conf.tab: SHELL default checks { _CS_PATH } X { ksh ksh93 sh }
+06-10-01 comp/conf.sh: export CONF_getconf to shell actions
+06-10-01 comp/putenv.c: always enable setenv() for procopen()
+06-10-01 misc/procopen.c: use pathshell() or astconf("SHELL",0,0) if PARANOID
+06-10-01 path/pathshell.c: localize the shell path patterns and accept ksh93
+06-09-28 Makefile: avoid ast <stdio.h> vix iffe -X ast -- doh
+06-09-27 regex/regdecomp.c: add
+06-09-26 regex/regcomp.c: handle KRE ~(...)<invalid-kre>
+06-09-25 reorganize to avoid native header intercepts
+06-09-15 uwin/crypt.c: _UWIN only!
+06-09-14 Makefile: tweak the ast_common.h bootstrap again (finally?)
+06-09-14 misc/optget.c: noncommercial => OPT_proprietary
+06-09-12 string/strelapsed.c: fix multi-char qualifier parse
+06-09-12 string/strtoi.h: drop [cClLqQwW] multipliers
+06-09-11 misc/optget.c: add numeric arg validity check
+06-09-07 misc/optget.c,tm/tmfix.c: fix uninitialzed var refs
+06-09-05 path/pathprobe.c: add version header verification
+06-08-01 Makefile: handle iffe vs FEATURE/common vs ast_common.h
+06-08-31 Makefile: add ast_map.h to the bootstrap list
+06-08-30 misc/glob.c: fix ~(E)re bug that stripped ~(E) before regcomp
+06-08-30 include/ast.h: add { integralof(x) pointerof(x) }
+06-08-27 string/strelapsed.c: fix off-by-one (too little) parse bug
+06-08-25 misc/optget.c: 0*<n>.* numeric option args => <n>.*
+06-08-22 misc/glob.c: handle ~(...) pattern options
+06-08-16 string/strelapsed.c: fix off-by-one (too far) parse bug
+06-08-16 regex/regcomp.c: accept but ignore ~(N)
+06-08-14 features/libpath.sh: add solaris LD_LIBRARY_PATH_64 check
+06-08-05 sfio/sfpool.c: pool SF_READ|SF_WRITE loop fix
+06-08-02 misc/fts.c: fix FTS_NOSTAT optimization to check for ..
+06-07-28 include/glob.h: add gl_extra for user globlist_t expansion
+06-07-27 features/common: #include "ast_map.h"
+06-07-26 comp/fnmatch.[ch]: allow <ast_map.h> to map fnmatch()
+06-07-22 cdt: snarf from kpv
+06-07-17 string/strperm.c: perm==-1 skips umask(1)
+06-07-17 sfio/sfvprintf.c: handle format invalid mb seq
+06-07-17 regex/regcomp.c: inline REG_SHELL => anchored, otherwise not
+06-07-17 regex/regcomp.c: inline B|G:basic E:REG_EXTENDED F|L:REG_LITERAL
+06-07-17 regex/regcomp.c: inline l:REG_LEFT r:REG_RIGHT
+06-07-17 regex/regcomp.c: inline a:REG_LEFT|REG_RIGHT p:~REG_LENIENT
+06-07-17 string/chresc.c: add \Uxxxxxxxx
+06-07-17 sfio/sfstrtof.h: ignore thousands sep after decimal
+06-07-17 string/tokline.c: splice() => spliceline() for bsd
+06-06-27 features/float,sfio/sfcvt.c: fix Nan logic
+06-06-27 port/astmath.c: fix long double isnan() test
+06-06-27 features/map.c: _map_libc for std => _ast_std
+06-06-25 string/strperm.c: handle posix = w.r.t. umask
+06-06-19 port/mnt.c,features/fs: handle netbsd getmntent api change
+06-06-18 regex/regstat.c: add REG_LITERAL check
+06-06-11 cdt/dtview.c: update from kpv
+06-05-31 sfio/sfhdr.h: fix _SFOPEN() typo
+06-05-09 comp/conf.sh: add native getconf -a names to the mix
+06-04-28 misc/optget.c: add solaris long option name compatibility
+06-03-09 string/strmatch.c: add REG_ADVANCE => REG_* flags
+06-02-14 comp/iconv.c: fix uwin iconv_list() /reg/ generator
+06-02-10 port/astconf.c: relax standard prefix filter
+06-02-08 sfrd.c,sfsync.c: lock logic bug fix
+06-02-01 port/astlicense.c: add { parent incorporation }
+06-01-26 port/astconf.c: fix { LIBPREFIX LIBSUFFIX } length
+06-01-06 features/lib: change _UNIV_DEFAULT probe to use cross{...}
+06-01-04 misc/stk.c: fix n**2 realloc behavior
+06-01-01 include/sfio.h: export { _Sfi _Sfmaxr }
+05-12-13 string/chresc.c: handle \C-X => control-X, \M- => ESC
+05-11-22 regex/regcache.c: add, convert string/strmatch.c to regcache()
+05-10-06 string/ccmap.c: update ebcdic-u to be idempotent
+05-09-28 vmalloc: snarf from kpv; fixes large block brk() thrashing
+05-09-26 misc/magic.c,misc/magic.tab: handle latest vcodex header
+05-09-12 misc/optget.c: reset opt_info.offset on error
+ string/strtoi.h: strton() '.' multiplier only if m>1
+ string/fmtesc.c: add unadvertized FMT_PARM for FMT_SHELL
+05-09-09 string/fmtesc.c: fix FMT_SHELL logic w.r.t. [$`]
+05-08-11 string/strerror.c: fix { sys_errlist sys_nerr } prototypes
+05-08-03 sfio: snarf sfvaprints sfaprints
+05-07-21 port/astconf.c: retain most recent synthesized lookup
+05-07-20 sfio/sfsetbuf.c: default file io size now 64K on all systems
+05-07-17 ccmap*: add microfocus cobol EBCDIC_U
+05-06-29 regex/regcomp.c: fix the A & B inline flag logic
+05-06-15 include/recfmt.h: add fs format flag to fmtrec()
+05-06-14 error.c: add ERROR_OPTIONS { break count match }
+05-06-07 features/stdio: drop FEATURE/limits to fix bootstrap circular dep
+05-06-02 features/*,Makefile: drop vestigel iffeio.h bootstrap workaround
+05-05-31 string/fmtbuf.c: unlock (spin) before each return -- doh
+05-05-30 sfio/sfpkrd.c: work around macos 10.4 recv(MSG_PEEK) bug
+05-05-27 regex: add REX_NEST (?%[S.][T.][OT])
+ magic.tab: ammend bsd db magic
+05-05-23 regex: REX_NEST (?%[D.][E.][L.][Q.][oc]...)
+05-05-21 regex: state.fold[] is now locale specific -- doh
+05-05-19 regex: add REX_NEST (?%\\()<>[]""...) %(...) nested match
+05-05-15 recfmt.h: add recstr() reclen() fmtrec()
+05-05-13 optget.c: allow boolean options to take numeric values
+05-05-12 recfmt.c: add to recfmt.h, adjust Recfmt_t encodings
+05-04-30 sfio: add sfmaxr(), default 64K
+05-04-22 comp/omitted.c: fix magic() logic for files < 512 bytes
+05-04-20 cdt: snarf update from kpv; void* Dt_t.user added
+ misc/error.c: library => ERROR_LIBRARY
+05-04-19 regex/regcomp.c: handle REG_SHELL [^...] == [!...]
+05-04-11 tm/tmxscan.c: handle yyy.mm.dd[-+.]hh.mm.ss.nnnnnn
+05-04-07 regex/regnexec.c: fix out of bounds boundary check -- ouch
+ features/align.c: add jmp_buf to the alignment mix (ia64)
+ vmalloc/vmhdr.h: add jmp_buf to the alignment mix (ia64)
+05-03-31 misc/optget.c: fix option { - _ } separator matching
+05-03-30 misc/glob.c: eliminate superfluous GLOB_NOMATCH stat() calls
+05-03-24 port/astwinsize.c: include <sys/ioctl.h> if possible
+05-03-23 string/ccmap.c: add ebcdic-m mvs cobol table
+05-03-11 comp/omitted.c: handle utime[s](const,const)
+ comp/conf.tab: fix linux PID_MAX probe
+05-03-10 comp/setlocale.c: LC_* value "" => unset -- doh
+ misc/optget.c: reorder _PACKAGE_astsa code for msgcc
+05-03-08 misc/optget.c: delete leading space in STYLE_nroff output
+05-03-07 sfio/sfhdr.h: drop extern _sfdscan -- clashes with sfvscanf.c static
+05-03-01 tm/tminit.c: add tmlocaltime() for tzset() getenv() override workaround
+05-02-20 features/tvlib: tmsettimeofday only for systems that have settimeofday
+ features/float: fix mvs.s390 NaN tests
+05-02-18 tm/tmxmake.c: fix <0 west of GMT bug that warped to 1800's -- wow
+05-02-11 port/mnt.c: handle lynxos MOUNTED=/etc/fstab
+05-02-08 features/float,sfio.h,sfcvt.c,sftable.c: add INF and fix NAN
+05-02-04 features/lib: add _std_strtol (for lynxos)
+ include/ast_std.h: add _std_strtol tests
+ comp/strtod.c: #define S2F_function strtod
+ misc/signal.c: fix ancient bsd SV_INTERRUPT vs. SV_ABORT clash
+05-01-11 sfio/sfmove.c: try to seek(fr) when fw==0
+ comp/omitted.c: intercept utimes() too
+ comp/omitted.c: add DOSPATHVARS env var path value conversions
+ features/tvlib,tm/tvtouch.c: check for utimets()
+ misc/optget.c: handle '-' or '_' option word separators
+ sfio/_sfopen.c: allow stream mode changes after initialization
+ sfio: sync with kpv: SF_SYNCED fix for ksh input loss bug
+05-01-09 tm/tmxfmt.c: fix %6N for n<100000000
+05-01-08 regex/regcomp.c: conj() => con() to avoid C99 clash
+05-01-05 tm/*: fix { %U %V %W } logic -- my head hurts
+04-12-30 tm/tmxtime.c: fix tm_isdst<0 loop
+04-12-23 vmalloc/vmbest.c: fix vmresize bug that didn't 0 new data
+04-12-19 misc/optget.c: broaden - long option match
+04-12-09 string/strtoi.h: fix terabyte 't' suffix math
+ string/strmatch.c: flush cache on locale change
+04-12-01 tm/tmsleep.c: add
+ tv.h,tv*.c,tv.3: move from pax
+ tmx.h,tmx*.c,tmx.3: add high resolution tm(3) counterparts
+ features/lib: add *another* sgi linux.ia64 memccpy bug check
+04-10-31 Makefile: __OBSOLETE__ now computed <6 months ago year>0101
+ ccode.h,ccmapid.c: add ccmaplist(Ccmap_t*) iterator
+ option.h,optesc.c: add 3rd arg, 1 => quote '?' too
+ misc/magic.c: fix bug that terminated `string \0a' at \0
+ misc/magic.c: handle vcodex() via decompose()
+ misc/magic.tab: add vcodex magic
+ features/stdio: handle _LARGEFILE64_SOURCE -- oops
+ stdio/(fseek|ftell|fseeko|fsetpos|fgetpos|ftello).c: oops^2
+04-10-28 string/swapop.c: size==-4 => size=4 and extend op=3 to op=7
+ tm/tmfix.c: fix tm_mon<0 logic
+04-10-22 tm/tmdate.c: handle 'final day feb 2004'
+ port/astlicense.c: add query=all|id|${...}${...}
+ port/astlicense.c: "free" => "mit"
+ comp/omitted.c: revert to the open source license
+ string/stropt.c: drop siz==0 => tab is hash table
+ include/sfio.h: incorporate <sfstr.h>
+ include/sfstr.h: drop
+ disc/sfstrtmp.c: drop -- use sfstrbuf()
+04-10-20 misc/magic.tab: update tar magic
+04-10-18 ufc-crypt.h,crypt_util.c: drop GPL code
+ crypt.c: add BSD code
+ pathpath.c: disable { $0 $_ $PWD } related root search
+04-10-01 normalize ident stamps
+ port/astlicense.c: add type=cpl -- yeah
+04-09-25 string/swapop.c: return op < size -- duh
+04-09-23 comp/spawnveg.c: :NOOPTIMIZE: -- volatile sometimes ignored
+04-09-21 comp/spawnveg.c: exec_errno_ptr is volatile -- duh
+04-09-14 tm/tmscan.c: add %| alternation and %& => tmdate()
+04-09-08 misc/optget.c: add :!value: omitted optional arg value
+ misc/optget.c: fix --noNAME ambiguous option logic
+04-08-26 string/strperm.c: add who^mode to propagate least restrictive up
+ astmath.c: add { frexpl ldexpl } checks for ast.req
+ port/astlicense.c: ignore first option if non-assignment
+ include/ast_dir.h: move d_fileno map before struct defs -- duh
+04-08-24 vmalloc/vmbest.c: add {VM_region} VMCHECK=+r for region segment checks
+ misc/recfmt.c,include/recfmt.h: add
+04-08-23 vmalloc/vmbest.c: add {VM_primary VM_secondary} VMCHECK=-s for primary
+ features/common: punt to <stdarg.h> for unknown va_list
+04-08-11 vmalloc: sync _UWIN libposix hooks
+04-07-27 features/common,features/limits.c: ULL suffix for unsigned _ast_int8_t
+04-07-22 include/ast.h,comp/eaccess.c: add eaccess() for effective access()
+04-07-19 comp/open.c,sfio/_sfopen.c: { O_RDONLY O_WRONLY O_RDWR } are values
+04-06-28 misc/error.c: check level after error_info.auxilliary
+04-06-24 string/strmatch.c: strgrpmatch() match[] now variable size array
+04-06-17 features/common: change _DLL null define to (the standard ast) 1
+04-06-11 misc/optget.c: allow optional [-|+|--|++] optstr() option prefix
+ misc/optget.c: reset optstr() state on 0 return
+ misc/optget.c: text()=>textout() linux.ppc symbol hijack workaround
+04-05-31 sfio/sfreserve.c: no side buffer if user buffer is large enough
+04-05-27 string/fmtbuf.c: handle one concurrent buf > sizeof(buf)
+04-05-24 regcomp.c: fix no-advance initialization
+04-05-05 conf.tab,conf.sh: update to align with standards
+ magic.tab: ms suffix update
+04-05-04 port/lcgen.c: fix territory initialization
+04-04-15 tm/tmdate.c,include/tm.h: fix specific and ordinal days
+04-04-08 astconf: retain { HOSTTYPE LIBPATH LIBPREFIX LIBSUFFIX } strict vals
+04-04-07 vmalloc/vmbest.c: fix alpha tiny block bug
+ vmalloc/malloc.c: re-enable on alpha
+04-03-30 tm/tminit.c: GMT => UCT only if tz.daylight not defined
+04-03-25 vmalloc/malloc.c: _AST_std_malloc=1 for __alpha
+ path/pathprobe.c: per-user probe dir => $HOME/.probe/$HOSTTYPE
+04-03-23 regex/reglib.h: fix isw*() redefines
+04-03-17 features/stdio: no __FILE override for __CYGWIN_ (sys/reent.h clash)
+ sfio/sfhdr.h,sfio/sfsetbuf.c: lower sfmove() default buf size 4x
+04-02-29 comp/omitted.c: move env trace after PATH fixup
+ comp/omitted.c: cygwin spawn _P_DETACH => _P_NOWAIT+setpgid(pid,0)
+ misc/optget.c: fix html mailto: match
+ port/astlicense.c: add type=test for fixed 2001 date
+ features/float: check local NaNQ first
+ vmalloc/vmhdr.h: fix _vmextern_ vm_truncate return type
+ misc/magic.tab: add elf s390 index=22
+04-02-26 vmalloc: VMCHECK a:assertions c:arena-check w:warn-instead-of-abort
+ sfio/sfvscanf.c: fix extf arg selection
+04-02-24 features/dirent: set nodefine to avoid ast_std.h _typ_off64_t undef
+ disc/sfkeyprintf.c: only case pattern must be ()[] balanced
+04-02-14 include/sfio_t.h: add SF_DCDOWN, SFDCNEXT(), SFDCPREV()
+04-02-13 string/strmatch.c: fix bug that didn't save one-time sub[] size
+ vmalloc: -g: export VMCHECK=1 enable malloc/free checks
+ vmalloc: -g: free(0) to check and disable malloc/free checks
+ vmalloc: -g: free(1) to check and enable malloc/free checks
+04-02-11 Makefile: add :P=A: to conf and lcgen exec for cross-compile
+ regex: use MBSIZE() instead of mbsize() to grab 1 char on err
+ vmalloc/vmbest.c: updated to do more comprehensive DEBUG tests
+04-02-04 sfio/sfraise.c: add sfraise(0,a,b) to iterate over all streams
+04-02-01 vmalloc/vmbest.c: _BLD_DEBUG free(0) checks the arena
+04-01-31 features/vmalloc: fix typo that missed _mmap_zero
+04-01-23 string/strerror.c: handle real strerror() return value overwrite
+04-01-11 path/pathpath.c: fix size vs. sizeof(buf) typo
+03-12-22 misc/magic.tab: dos EXE tweaks
+03-12-05 vmalloc: sync with kpv, adding exceptf announcements
+03-12-04 port/astlicense.c: fix expand() loop sentinel bug
+03-12-02 include/ast.h: mbchar() advances by 1 on mbtowc() error
+ misc/fts.c: increase MINNAME to 32
+03-11-21 vmalloc/vmbest.c: export VMCHECK=1 to enable $(CC.DEBUG) vmcheck()
+ vmalloc/vmbest.c: export VMCHECK=2 to disable KPVCOMPACT
+ misc/magic.c: add { cobol copybook pl1 } and suffix preference
+03-11-12 features/stdio: drop cuserid,getopt for SUSV3
+03-11-11 vmalloc/*: merge kpv update -- this should stomp the compaction bug
+03-10-23 comp/iconv.c: fix sfreserve lock fallback
+03-10-20 sfio/_sfopen.c: add to allow user sfopen() intercept
+03-10-17 regnexec.c: fix exec time REG_LEFT, \x.... => wctomb()
+03-10-12 string/strtoi.h: fix strton '.' overconsumption
+03-10-12 comp/iconv.c: identity is always (iconv_t)0
+03-10-09 string/fmtesc.c: fix FMT_SHELL to check for all shell magic chars
+03-10-01 port/astlicense.c: unknown authors copied verbatim (instead of ignored)
+03-09-30 string/chresc.c: handle \u..., \x... consumes all trailing hex digits
+ string/stresc.c: \u... and \x... > UCHAR_MAX => wctomb()
+03-09-29 fnv.h: add
+03-09-23 modedata.c: table is for external modes, so no arch specific hacks
+ optget.c: fix option prefix match translation bug
+ optget.c: add `<length> <name>=<value>\n' to optstr()
+ features/lib: add memcmp() test for sgi optimzation bug
+03-09-22 regex.h,regcomp.c: add regncomp()
+ regclass.c: fix for loop dangling ; in regaddclass()
+03-09-20 sftable.c,sfvprintf.c: fix SFFMT_CHAR handling to match extf api
+03-09-19 sfmode.c: update release to kpv's
+03-09-17 regcomp.c: add pedantic backref error checks
+03-09-16 regnexec.c: exec time REG_LEFT => don't advance past initial position
+ regclass.c: add regaddclass() for user defined [:class:]
+ regexec.h: REG_VERSION_N2X, add redisc_t {re_map} ccode map
+ regstat.c: add regstat_t
+03-09-11 optget.c: --n:=v sets opt_info.assign=':', opt_info.number enabled
+03-09-09 disc/sfkeyprintf.c: *pn on lookup is arg separator; lookup "" arg too
+03-09-05 optget.c: [f:l*?] preserves user long name past '*' in opt_info.name[]
+03-09-03 sfstr.h: add sfstrpend() for #pending bytes in read buffer
+03-08-25 regex: add REG_FIRST, optimize bm
+ features/lib: _AST_no_spawnveg==1 falls back to fork/exec
+03-08-22 features/stdio,stdio/asprintf.c,stdio/vasprintf.c: add
+03-08-21 path/pathnative.c,path/pathposix.c: interix updates
+ features/botched: add cygwin _stat => _stat64
+03-08-15 include/ast.h: map out bsd strmode()
+ features/common: add interix _ast_intmax_t workarounds
+ misc/fs3d.c: 3d mount test now uses "" instead of NiL (or cygwin dumps)
+03-08-11 string/fmtesc.c: fix optional quoting checks
+ tm/tmdate.c: fix > 1 year of seconds arithmetic
+ tm/tmfix.c: fix leap year adjustments
+03-08-01 features/lib: beef up sock_peek test for interix
+03-07-29 features/float: add -lm to frexp... test
+ Makefile: fix -lm astmath test sense
+03-07-26 features/mem.c: favor _mem_sbrk over _mem_mmap_*
+03-07-22 vmalloc/vmbest.c: fall back to sbrk() if mmap() fails
+ features/mem.c: _mem_sbrk means sbrk() and brk() work
+03-07-17 regex/regcomp.c: fix bug that treated KRE X{n,m} like {n,m}(X)
+ misc/magic.c: check MAGIC_VERBOSE for all load() messages
+03-07-14 misc/optget.c: handle [...]{[...]\f...\f...}
+03-06-21 misc/sigcrit.c: block SIGCHLD if _lib_sigprocmask || _lib_sigsetmask
+ comp/spawnveg.c,sfio/sfmode.c: use sigcritical() SIG_REG_* macros
+ comp/spawnveg.c: drop ENOEXEC logic
+ vmalloc/*: snarf kpv KPVCOMPACT() fix
+ vmalloc/vmbest.c: export VMCHECK=2 to disable KPVCOMPACT (just in case)
+ string/strdup.c: drop __strdup() etc. intercepts -- malloc gets it
+ features/mem: define _mem_method and _mem_* possible values
+ vmalloc/malloc.c: _AST_mem_method==_mem_* to force mem get method
+ sfio/sfputr.c: __ia64 memccpy is bogus -- how many tries do they get?
+ path/pathshell.c: verify abs path and access(path,X_OK) -- duh
+ vmalloc/vmhdr.h: add private _Vmessage() for non-sfio ASSERT()
+ port/astconf.c: fix bug that always returned the minmax value
+03-06-11 comp/*.c: reorder macro hding for mvs.390 and <ast_map.h>
+ features/vmalloc: add _lib_brk and _lib_sbrk verification
+ include/ast_std.h,etc.: add _map_malloc for malloc => _ast_malloc
+ comp/conf.sh: fix SI_* and *_SI_* macro redefs
+ ast.h: VMDEBUG or _BLD_DEBUG enable <vmalloc.h> and VMFL tracing
+ vmalloc/vmtrace.c: _PACKAGE_ast __FUNCTION__ is a string
+ vmalloc/vmtrace.c: set trace file fd FD_CLOEXEC
+ vmalloc/vmbest.c: set /dev/zero mmap fd FD_CLOEXEC
+ features/mmap: fix ancient read() vs. mmap() time arithmetic typo
+ vmalloc/malloc.c: _AST_std_malloc==1 to force standard malloc
+03-06-09 comp/omitted.c: add _imp__FUNCTION sybols for __CYGWIN__ static link
+ vmalloc/vmbest.c: handle systems with sbrk() but no brk()
+03-06-04 port/astconf.c: drop non-standard diagnostics
+03-06-03 comp/conf.sh: rework symbol collision logic
+03-05-30 conf.tab,conf.sh,astconf.c: add <sys/systeminfo.h> sysinfo() SI_*
+03-05-29 ccode.h: rework for extensibility, drop obsolete mematoe(), memetoa()
+03-05-28 regex/*: recode to use isw*() directly when needed, is*() otherwise
+03-05-27 features/vmalloc: fix _std_malloc test
+03-05-25 misc/optget.c: fix optstr() ???* internal options
+03-05-24 misc/optget.c: fix (ancient) argv null dereference
+03-05-23 comp/getcwd.c: don't intercept on _WINIX -- unreliable st_ino
+03-05-22 sfio/sfsprintf.c: n<0 => don't append '\0'
+03-05-18 misc/fts.c: re-stat FTS_DP to update nlink/times
+ misc/fts.c: add FTSENT.stack to eliminate getlist() recursion
+ regex/ucs_names.h: use "..." catenation to placate some cc's
+03-05-11 string/strtoi.h: handle "-" "+" "0x" "11#"
+03-05-09 vmalloc/vmbest.c: large memory allocation tweaks
+03-05-06 misc/optget.c: fix getopt_long() prefix==1 bug that missed short flags
+03-04-27 comp/system.c: handle <ast_map.h>
+03-04-24 vmalloc/vmmopen.c: drop dup <unistd.h>
+03-04-21 tm/tmdate.c: fix next hour/min logic
+03-04-15 vmalloc/malloc.c: intercept __malloc() along with __libc_malloc()
+ string/strdup.c: intercept __strdup() along with __libc_strdup()
+ features/mmap: consolidate from features/(lib|sfio|vmalloc)
+ add _NO_MMAP==1 to disable all mmap()/munmap() calls
+ path/pathposix.c: add
+03-04-14 comp/setlocale.c: fix debug_mbtowc() return value for *s==0 || n < 1
+ comp/iconv.c: fix error return errno values
+03-04-11 misc/stk.c: fix stkgrow() realloc bug
+03-04-05 string/tok.c: support readonly single token input strings
+ disc/sfdcdio.c: fix F_DIOINFO and FDIRECT #ifdef's
+ include/ast_std.h: allow _LARGEFILE64_SOURCE on __hppa
+ features/common: fix `tst _foo_' => `tst foo_' typo
+ features/float: fix `tst _foo_' => `tst foo_' typo
+ features/float: add FLTMAX_(UINTMAX_MAX,INTMAX_MAX,INTMAX_MIN)
+ comp/omitted.c: fix pathconf => _pathconf => _ast_pathconf loop
+03-04-03 features/float: add _ast_no_um2fm: no usinged intmax => floatmax cast
+ vmalloc/vmbest.c: add getenv("VMCHECK") to initialize Vmcheck
+03-03-28 include/ast_dir.h: add D_TYPE; { D_FILENO D_TYPE } must be #ifdef'd
+ misc/fts.c|getcwd.c|glob.c,preroot/getpreroot.c: add D_FILENO #ifdef's
+ Makefile: make sure _BLD_ast is defined for all compiles
+03-03-27 ast_vfork.h: generate from features/vfork to pick up headers/pragmas
+03-03-25 comp/omitted.c: drop free() of live environ
+ path/pathshell.c: allow trailing .exe -- pox on that
+ string/strtoi.h: fix bug leading 3 digits before thousands sep bug
+ string/(fmt|str)[gu]id.c: we know root when we see it
+03-03-24 misc/optget.c: handle : and ? in := default value
+03-03-21 ast_std.h: drop all spawn*() but spawnveg()
+ obsolete/spawn.c: add for dropped spawn*()
+ features/lib: _use_spawnveg if spawnveg() is a win over fork()/exec()
+ features/lib: drop NutForkExecve() and _map_spawnve
+ features/lib: fix memccpy test to clean up /tmp droppings
+ comp/spawnveg.c: call posix_spawn() if implemented
+ comp/omitted.c: add spawnve() intercept
+ comp/getoptl.c: set getopt_long() optind even if no options
+ tm/tmfmt.c: add %Q<delim>recent<delim>distant<delim>
+ misc/optget.c: fix trailing '*' for option and option args
+ sfio/sfmode.c: getenv("_AST_SFIO_OPTIONS") [,]SF_LINE[,] for fd {0,1,2}
+ vmalloc/*: kpv sync for uwin build independent of libast
+03-03-18 port/astconf.c: switch to dynamic string values (saves 7K data/bss)
+ string/strmatch.c: switch to dynamic regex cache (saves 3K data/bss)
+ regex/regcoll.c,ucs_names.h: initialize rw tables from smaller ro data
+ features/lib: add vfork test for passing SIG_IGN across exec
+ features/lib: add spawn test for passing SIG_IGN across spawn
+03-03-17 comp/omitted.c: unlink() renames to .deleted dir in case file open
+ sfio/sfpopen.c: handle mode "" for spawn with no pipe
+ features/float,comp/frexp.c,comp/frexpl.c: add pow2() table alternative
+03-03-12 features/lib: fix linux.ia64 memccpy() tests -- now its their turn
+ features/vmalloc: fix /dev/zero test
+ features/align: _ast_intmax_t and _ast_fltmax_t join the union
+ misc/stk.c: fix struct frame size to align data
+ disc/sfdcdos.c: change sfslen() => sfvalue(f)
+03-03-10 misc/optget.c: handle [f\f:x:lll\f?ddd]
+03-03-07 port/astconf.c: uninitialized CONFORMANCE + POSIXLY_CORRECT => standard
+03-03-05 comp/omitted.c: make sure at least /bin is in PATH to find cygwin dlls
+03-03-02 path/pathshell.c: write access to /bin is effectively root
+03-02-28 features/float: add (FLT|DBL|LDBL)_U?(LONG|LONGLONG|INTMAX)_(MIN|MAX)
+03-02-25 features/lib: change vfork() test to use _exit() instead of exit()
+03-02-23 include/error.h: update ERROR_VERSION for error_info.number space
+03-02-22 comp/conf.sh: wrap ksh check in eval to avoid premature exit
+03-02-21 misc/fts.c: verify chdir(..) to avoid malicious dir rename()
+03-02-19 string/strtoip4.c: isspace() instead of ' '||'\t'
+03-02-17 regex/regcomp.c: fix stats.l REX_REP logic that botched REX_BM
+03-02-13 string/base64.c: handle catenated encodings
+03-02-11 features/libpath.sh: change LIBPATH to <dir>[:<env>[:<pat>]][,...]
+03-02-07 path/pathfind.c: allow "/dev/null" to be PATH_REGULAR
+03-02-06 include/ast.h,fmtquote.c: add FMT_ALWAYS|FMT_ESCAPED|FMT_SHELL|FMT_WIDE
+03-02-05 tm/tmdate.c,tm/tmword.c,string/strelapsed.c: '_' treated like ' '
+03-02-01 string/strelapsed.c: handle ps style [day-][hour:]min:sec
+03-01-31 port/astlicense.c: fix author=* match
+03-01-30 include/tm.h: add tmisleapyear() macro
+03-01-29 comp/getopt.h,comp/getoptl.c: add gnu getopt_long(), getopt_long_only()
+ include/ast_getopt.h: for non-gnu part of comp/getopt.h
+ include/ast_std.h: include <ast_getopt.h> instead of <getopt.h>
+03-01-28 ast.h,string/base64.c: add base64encode() and base64decode()
+ path/pathfind.c: verify S_ISREG()
+03-01-24 path/pathexists.c: fix abs dir bug and deal with case ignorance
+03-01-23 path/pathpath.c: honor PATH_ABSOLUTE for the easy case too
+03-01-22 path/pathprobe.c: fix search to find both the probe script and command
+03-01-17 misc/magic.tab: application/zip => appplication/(gzip|pzip|zip)
+03-01-14 misc/optget.c: change href="" to href="."
+03-01-10 include/ast_std.h: strtold() import hackery for static __CYGWIN__
+03-01-03 include/regex.h,regex/regcomp.h: add REG_SHELL_GROUP
+ include/ast.h,string/strmatch.c: add STR_GROUP for REG_SHELL_GROUP
+02-12-15 include/error.h: errorcontext => Error_context_s (compatible til 2004)
+02-12-06 misc/sigdata.c: add NoF(sigdadata) -- why nmake was uninterruptable!
+02-12-03 comp/omitted.c,features/omitted: handle cygwin alarm() return botch
+02-11-27 misc/swapop.c: op=3,size=4 => op=7
+ string/strlcat.c,strlcpy.c: fix uwin decl clash
+02-11-26 sfio/sfvprintf.c: fix sfsprintf() '\0' termination bug
+02-11-22 misc/glob.c: move static struniq() to libast extern
+ string/fmtversion.c,include/ast.h: add fmtversion
+02-11-18 string/strncopy.c: add
+ misc/magic.tab: list size for magicid.h magic
+02-11-14 sfio/sfvprintf.c: add %#c for C escapes
+ include/error.h: add ERROR_NOTIFY context flag for builtin commands
+02-11-11 string/strtoi.h: add S2I_size for strnto*() size_t 2nd arg
+ sfio/sfstrtof.h: add S2I_size for strnto*() size_t 2nd arg
+ comp/putenv.c: add setenv() and unsetenv() wrappers for setenviron()
+02-10-31 path/pathfind.c: add dir of including file to the pathinclude() list
+ misc/optesc.c: add
+02-10-30 string/strtoip4.c: set next char pointer even on error
+02-10-29 comp/resolvepath.c: add (size_t version of realpath())
+ misc/mime.c: fix mimehead() to ignore null content values
+02-10-28 misc/glob.c: add GLOB_STARSTAR for /**/ and GLOB_NOTDIR optimization
+02-10-27 string/struniq.c: add
+02-10-23 features/common: fix off-by-one loop check
+02-10-18 include/ast_std.h: avoid off_t,ftruncate,lseek,truncate redefinitions
+02-10-17 misc/mime.c: handle type/* match, fix bogus header parse
+02-10-04 sfio/sfstrtof.h: S2F_static <0:export =0:private >0:static
+02-10-02 features/common: don't define _WIN32; define _WINIX => unix on windows
+ features/tty: finally stomp the bsd _POSIX_VDISABLE redefinition
+ misc/fastfind.c: add more specific findwrite() error messages
+ comp/omitted.c: fix cygwin utime() to update st_ctime
+ comp/strtol.c,strtoul.c: __CYGWIN__ static link workaround XXX
+ string/fmtls.c,fmttime.c: tmform() => tmfmt()
+02-09-22 port/astconf.c: return values in fmtbuf() buffer instead of stack
+ port/mnt.c: don't set MNT_REMOTE for win32 ?:\* paths
+ sfio/sfvscanf.c: _sfdscan() is library global (not static)
+02-09-21 path/pathkey.c: add tool arg for mamake compatible hash
+ features/fcntl.c: handle iffe _hdr_lcl_* => _lcl_* change
+02-09-15 comp/conf.sh: fix enum vs. macro test
+ cdt: kpv sync
+02-09-11 ast.h,features/common: move _WIN32 macro init to features/common
+ features/common: enable __EXTERN__ and __DEFINE__ for _WIN32&!_UWIN
+ features/float: add -lm to _ast_*_nan_init tests
+ vmalloc: kpv sync with vmresizef => vmgetmem
+ features/iconv: must have both <iconv.h> and iconv_open()!
+ features/vmalloc: alloca test must compile *and* link
+ sfio/sfvscanf.c,sfstrtof.h: add flag arg to char get, fix NaN loop
+02-09-10 vmalloc/vmhdr.h: enable getpagesize() and sbrk() prototypes
+ features/fcntl.c: enable mmap64() prototype
+ include/ast_windows.h: windows.h wrapper with ast namespace workarounds
+02-09-07 misc/mime.c: fix quoted value parse bug that ate the whole line
+02-09-05 features/vmalloc: add free() to _std_malloc test
+ include/ast.h: NoF(x) now defines _DATA_x for !_BLD_DLL too
+ tm/tmlocale.c: { C POSIX en } == unix dadgummit
+02-08-29 path/pathfind.c: initialize Dir_t.next=0
+02-08-28 uwin/rint.c: update
+ features/libpath.sh: "bin" is now the default value
+02-08-22 vmtrace.h: add for debugging
+02-08-20 misc/magic.c: convert to use <cdt.h>
+ vmalloc/vmresizef.c: add for generic discipline resizef default
+ string/strelapsed.c: allow long time component names
+02-08-19 misc/optget.c: add `.fp 5 CW' to --nroff output
+ string/(fmtfs|fmtuid|fmtgid|strgid|struid).c: convert to use <cdt.h>
+ include/dt.h,cdt/dtnew.c: add for dtopen() in specific vm region
+02-08-13 comp/omitted.c: fix bzero logic for e.g. unixware.i386
+ include/ast.h: add fmtbase->fmtbasell; swap in 2003-09-01
+02-08-12 regex/regnexec.c: fix REG_MINIMAL REX_DOT mb bug
+02-08-08 features/iconv: <ast_common.h> instead of <sys/types.h> <ast_common.h>
+02-08-07 regex/regcomp.c: recognize anchors in BRE subexpressions
+02-08-06 comp/iconv.c: handle win32 cpNNNN == windows-NNNN aliases
+02-08-05 cdt/*: sync with kpv src
+02-08-02 features/iconv: include sys/types.h for ast_types.h
+02-08-01 misc/magic.c: magic file "." names the default
+ misc/magic.c: handle addr type (from irix string)
+ features/lib: move malloc tests to features/vmalloc
+ features/vmalloc: snarf tests from features/lib
+ vmalloc/*: sync with kpv src
+ comp/libc.c: dropped -- __libc_* intercepts moved to vmalloc/malloc.c
+02-07-30 features/lib: handle __libc_malloc() in _std_malloc test
+ vmalloc/malloc.c: add gnu pvalloc()
+ features/vmalloc: fix alloca check
+02-07-29 features/limits.c: handle netbsd guards
+02-07-27 sfio/sfpoll.c: handle rw pipes
+02-07-25 features/iconv: include ast_types.h for size_t in ast_iconv.h
+02-07-18 apply LARGEFILE64 header prototype clash patches
+ misc/optget.c: __EXTERN__ _opt_info_ instead of opt_info
+02-07-17 ast_std.h: memzero() now defaults to memset() instead of bzero()
+02-07-16 ast_std.h: add ast.env_serial
+ misc/setenviron.c: increment ast.env_serial
+ include/tm.h: tmset() now calls tminit() directly
+ tm/tminit.c: check ast.env_serial for env change
+ tm/tmfix.c: speed up for large values of tm_mday
+02-07-15 comp/fnmatch.c: fix memory leak caused by missing regfree()
+ comp/strstr.c: fix broken interpretation and implementation
+ comp/iconv.c: intercept (but no-op) null to and from buffer pointers
+02-06-27 ast_std.h: map _sysconf => _ast_sysconf for sun
+02-06-26 cdt,sfio,vmalloc: kpv sync -- is this ever easy?
+02-06-24 sfio: kpv sync, vfwscanf(),fputw() fix (wcslen(x)*sizeof(wchar_t)!!)
+ misc/fts.c: fix symlink chdir() optimzation bug
+02-06-11 sfio/sfwrite.c: string to file fix
+ Makefile: __OBSOLETE__==20020101
+02-06-01 regex/regcomp.c: REG_DELIMITED now consumes the delimiter
+02-05-31 regex/reglib.h,regcomp.c,regnexec.c: null subexpression fixes
+02-05-24 misc/fts.c: disable dir link counts in 3d
+ misc/magic.c: fix "*(mkfile)" sh pattern to "*@(mkfile)"
+02-05-20 regex.h,regex/regsubcomp.c,regex/regsubexec.c: add
+ regex/regsub.c: deprecate
+02-05-16 tm/tmfix.c: fix '60+n min/sec ago' bug for n min/sec after the hour
+02-05-14 regex/regsub.c: fix (^|x) null match early termination bug
+02-05-13 dir/dirlib.h: drop errant extern==__EXPORT__
+ features/uwin: add uwin lib tests
+ uwin/*.c: check features/uwin for stubs
+ features/float: add nan representation generation
+ sfio/sftable.h: used _ast_*_nan_init for huge values
+02-05-09 misc/fts.c: fix virtual top to force ``child'' stat()
+ features/common: define va_copy() only if not in <stdarg.h>
+02-05-01 string/strtoip4.c: cisco inverted quad mask must have 4 parts
+02-04-30 misc/magic.tab: fix pzip version check
+02-04-19 string/strtoip4.c: handle cisco inverted quad mask n.n.n.n/i.i.i.i
+02-04-18 misc/fts.c: add chdir() verification stat() optimizations
+ path/pathkey.c: check PROBE_ATTRIBUTES for list of vars
+02-04-12 port/astlicense.c: type=open tweak, fix author list spacing
+02-04-11 regex/regcomp.c: check for pattern number overflow
+02-04-05 tm/tmfmt.c: add %u
+02-04-04 sfkeyprintf.c: fix %c numeric value
+ path/pathpath.c: check plain path first -- duh
+02-04-03 misc/fts.c: fix (FTS_PHYSICAL|FTS_NOSTAT) stat optimizations
+ ftwalk.c: only clear FTW_DELAY if FTW_CHILDREN
+ ftwalk.h: add FTW_NSOK for FTW_DELAY
+02-03-29 ast.h: drop strerror() prototype -- already in <ast_std.h>
+ features/stdio: check for _SFIO_H redundant _Sfstd* declarations
+02-03-26 misc/glob.c: fix GLOB_LIST gl_flags values
+02-03-24 port/mnt.c: update bsd fstype name and mount option logic
+02-03-23 Makefile: add ast_wchar.h to the .check.hdr list (for mamake)
+02-03-17 features/stdio: hack around g++ 3.* clashes
+ Makefile: add ast_nl_types.h to the .check.hdr list (for mamake)
+ string/strtoip4.c: fix validity check bug that only checked last part
+02-03-14 misc/optget.c: fix --keys to not expand inline \f...\f
+02-03-12 port/astlicense.c: add type=free
+ path/pathaccess.c: sibling ".." search ignores relative dirs
+ sfio/sfvscanf.c: sfstrtof get() must return 0 on eof
+02-03-11 path/pathexists.c: check path by pairs checking {ENOTDIR,ENOENT}
+02-02-14 features/float: copy local min/max macros to avoid printf roundoff
+ features/wchar: include <ast_common.h>, not <ast_std.h>
+ misc/magic.c: match[]=>matches[] to fix K&R match() macro conflict
+ include/vmalloc.h: include <stdlib.h> for !_PACKAGE_ast
+ uwin/mini.sym: add sprintf (now required by features/common)
+ regex/regnexec.c: truncate wide chars for <ctype.h> functions
+ Makefile: fix MAM ast_common.h sequencing bug by making it first
+ cdt/dthash.c: fix DT_DELETE memory leak (DT_DETACH typo)
+ cdt/dthash.c: fix DT_DELETE double free (dt->data->here typo)
+ regex/regcomp.c: fix recomb() to reject RE with backref
+ features/iffeio: explicitly generate stdio.lcl
+ stdio: add {fcloseall,f(get|put)s_unlocked,fmemopen,getdelim,getline}
+ tmmake,tmtime: allow negative time_t if native localtime/gmtime do
+ tmdate: allow years before 1969
+ fmtfmt: add
+ include/ast.h: add { PATH_TOUCH_CREATE PATH_TOUCH_VERBATIM }
+ Makefile: add std/*.h for std header iffe overrides
+ comp/iconv.c: fix non-C win32 sfreserve() loop
+02-02-11 features/common: separate long long / long double tests
+ features/common: verify printf handles long long / long double
+02-02-02 include/ast_std.h,sfio/sfhdr.h: drop _hdr_locale tests -- always on now
+ include/ast_std.h: trust _UWIN <unistd.h>
+02-01-31 port/mnt.c: add aix options field
+02-01-30 comp/strstr.c: add for ancient s5
+ stdio/_flsbuf.c: only on systems that transfer to native (e.g., uwin)
+ string/strtoi.h: cat min/max error return values
+02-01-28 features/tty: add cf[gs]et[io]speed macros for <termio.h>
+ comp/rename.c: punt to (ancient) /usr/lib/mv_dir on EISDIR
+02-01-24 sigcrit.c: fix SIGCLD!=SIGCHLD interrupt loop
+ sfvprintf.c: convert fast io macros to functions for uts.390 cc
+ string/strtoi.h: drop #pragma prototyped for standalone sfio
+ sfdcsubstr.c: rename from sfdcsubstream.c for 14 char fs
+02-01-22 execlp,execvp,execvpe,spawnlp,spawnvp,spawnvpe: fix __EXPORT__
+ spawnlp,spawnve,spawnvp,spawnvpe: handle ms mode arg -- barf
+ sftable.c: ifdef hacks for _WIN32&_ALPHA_ fp exception
+ _stdfun.c: add _UWIN&_ALPHA_ iob map
+02-01-18 sfio/sfstrtof.h: drop #pragma prototyped for standalone sfio
+02-01-17 features/hdr: don't include <stddef.h> after it doesn't check out!
+02-01-16 misc/magic.c: add version type for YYYYMMDD or [a.][b.]c.d
+ misc/magic.c: recode mime %s parse -- sensible and no buffer overflow
+02-01-15 misc/magic.tab,magicid.h: add generic binary magic number and header
+02-01-12 tm/tmlocale.c: override win32 default date for {C,POSIX,en} locales
+ comp/omitted.c: fix cygwin workaround logic bugs
+02-01-09 stdio/fseeko.c,ftello.c: add from UNIX98
+02-01-08 comp/conf.sh: use $cc instead of cc
+02-01-07 string/strlcat.c,string/strlcpy.c: add bsd api
+01-12-18 comp/conf.tab: fix LFS_CFLAGS default for sun _CS_LFS_CFLAGS botch
+ features/common: add hdr stdarg test
+ tm/tmdate.c: handle YYYY/MM/DD
+01-12-10 misc/magic.tab: add generic 0x00010203 binary magic
+01-12-03 path/pathprobe.c: return HOME relative path if readonly/non-suid fs
+01-11-30 misc/optget.c: add simple cache for repeat offenders (like ksh read)
+ sfio/sfhdr.h: preserve errno across SFMMSEQON-SFMMSEQOFF
+01-11-29 magic.tab: fix GIF version number listing
+01-11-28 string/fmtbase.c: p!=0 => base always included in output
+01-11-26 misc/fts.c: empty path is an error
+01-11-14 misc/optget.c: fix --?+SECTION queries to include paragraphs
+01-11-20 regex/regnexec.c: fix REG_MINIMAL character class match bug
+01-11-19 features/lib: retain _lib_confstr for all solaris releases
+01-11-16 comp/setlocale.c: fix !_lib_setlocale typo
+01-10-31 regex/ucs_names.h: add string catenation to keep line length low
+ misc/fastfind.c: handle gnu slocate db read
+ misc/optget.c: add --?+SECTION queries
+ comp/fnmatch.h: add FNM_NOSYS
+01-10-30 tm/tmdate.c: fix cron specs when both wday and mday are specified
+01-10-20 misc/glob.c: fix bug that called \ trim() twice on same path
+ misc/glob.c: fix \ trim() bug that restored / to wrong position
+ string/fmtre.c: fix { ^ . $ } translations
+ misc/optget.c: use original string if translation fails -- duh
+ sfio/sfhdr.h: assume <errno.h> assigns proper atttibutes to errno
+ comp/regcmp.c: __ia64 workaround fixed by proper CC.DLL probe
+ comp/getdate.c: __ia64 workaround fixed by proper CC.DLL probe
+ features/lib: add lib getdate
+01-10-18 features/lib: check for strtod static link collision
+ features/float: add another signed cast for old bsd cc
+ features/wchar: add <stdlib.h> <stdio.h> before <wchar.h> for old bsd
+01-10-17 sfio/sfcvt.c: limit max precision to { FLT_DIG DBL_DIG LDBL_DIG }
+ sfio/sfcvt.c: fix %[aA] format to always have leading 0[xX]1.
+ sfio/sfvprintf.c: handle %C %lc %S %ls for wchar_t args
+ sfio/sfvscanf.c: handle %C %lc %S %ls for wchar_t args
+ string/fmtmode.c: fix bug that omitted trailing '\0'
+01-10-12 misc/optget.c: . => \&. for --??nroff
+ comp/wc.c: fix mbstate_t initialization typo
+ features/float: fix max integer / float loop termiation
+ features/float: fix LDBL_UINTMAX_MAX typo that did DBL_UINTMAX_MAX
+01-10-11 include/sfio.h: fix _Sfstd* import/export
+ features/common: fix _UWIN __DYNAMIC__() definition
+01-10-06 features/fcntl.c: { O_BINARY O_TEXT } default to 0
+ features/omitted: add for comp/omitted.c
+ sfio/sfopen.c: O_BINARY default for _WIN32&&!_UWIN
+01-10-05 misc/glob.c: fix `\(x/*' GLOB_NOMATCH bug that returned `(x'
+ misc/optget.c: fix localization lookup that didn't drop doubled : ? ]
+01-10-04 comp/setlocale.c: handle sizeof(wchar_t)!=4 in debug locale
+ comp/conf.sh: handle sytems where _SC_* is both an enum and a macro
+01-09-25 astconf: add LIBPREFIX
+01-09-20 features/common: add __DYNAMIC__() for dll externs
+01-09-19 cdt: kpv update
+ mb*() macros: update for ksh conversion, extend debug locale
+01-09-16 tm/tmlocale.c: add compiled in defaults for C locale
+ misc/glob.c: add gl_nextdir callback for GLOB_COMPLETE
+01-08-14 clarify _WIN32 vs. _UWIN vs. __CYGWIN__
+ tminit: fix standard & daylight initialization
+01-09-11 pathnative.c: add for native fs representation
+ regex.h: fix regerror_t prototype
+01-09-04 regex/regnexec.c: fix REG_ICASE for multi-char collating elements
+ tm/tmlocale.c: fix old ascii LC_TIME load
+ locale*: add new LC_* categories
+ comp/omitted.c: add CYGWIN workarounds
+ features/lib: add CYGWIN workarounds
+01-08-11 features/common: some compilers have long long but no LL constants!
+ features/lib: add mmap64 implementation test (for linux.s390)
+ regex/regcomp.c: fix \ in [...] parse
+ setlocale: retain user locale spelling in setlocale() return value
+ features/limits.c: don't include ./limits.h -- duh
+ fmtesc: don't escape multibyte chars
+ tm/tmlocale.c: fix native C locale default
+01-08-08 features/float: some compilers (msdev) forget long long vs. double
+01-07-31 misc/optget.c: handle suboptions
+01-07-27 cdt.h: add DTDISC()
+01-07-17 iffeio.h: move to include for stdio bootstrap iffe workarounds
+01-06-25 regex: perl extensions added and tested
+01-06-21 misc/error: add ERROR_OPTIONS=prefix=string for message processing
+01-06-15 string/chresc: only 2 hex digits max for \xxx
+ regex/regsub: handle REG_SHELL ~(nnn) rhs backrefs
+01-06-11 regex: handle embedded \0 in pattern and subject string
+ regex: add (?nnn) for backrefs > 9
+ comp/fnmatch: add FNM_LEADING_DIR for gnu compatibility
+ features/float: _ast_flt_unsigned_max_t for bsd.i386 omission
+01-06-06 misc/optget.c: add o option for old ps,ar,tar with optional leading -
+ regex/regcomp.c: REG_LENIENT|REG_DELIMITED \<newline> => <newline>
+ regex/regcomp.c: REG_LENIENT \000 => NUL
+01-06-04 features/dirent: replace Makefile hack with iffe semi-hack
+ regex/regnexec.c: negation must also check REG_SHELL_DOT
+01-06-03 sprintf.c: change buf size from SF_BUFSIZE to INT_MAX
+01-05-31 glob: fix gl_fignore to ignore leading . by default
+ features/lib: add botch_d_ino_dirent64 for linux botch
+01-05-25 port/lc.tab: add a few missing language_territory's
+01-05-23 string/chresc: \C[.collation-element.]
+ fmtmatch,fmtre: update for <regex.h> syntax extensions
+01-05-21 regex: add perl extensions, unicode names for collation elements
+01-05-11 string/chresc: \e == \E == escape, \cX == control X, \x{..} == \x..
+01-05-09 path/pathtemp.c: pathtemp(0,0,0,"/private",0) for mode S_IRUSR|S_IWUSR
+ port/touch.c: handle utime(2) EPERM to fix bug that truncated
+ regex: change REG_MINIMAL to avoid negation -- much faster now
+01-05-08 *.h: add some off_t macro guards for suse linux
+01-05-03 regcomp.c: optimize ((x)!)* to ((x)!)
+ wchar: add <wchar.h> and stdio wchar routines
+01-05-02 feaures/wchar: add <wchar.h> intercept, add stdio wchar functions
+01-05-01 string/strtoi.h: signed strtoi accepts qualified unsigned constants
+01-04-30 comp/setlocale.c: fix code that relied on 2 simultaneous getenv()'s
+ tm/tmlocale.c: check for UTF-8 encoded LC_TIME files
+ misc/magic.tab: add utf-8 and utf-16 U+FEFF magic
+01-04-26 features/common: some cc's have _ast_int8_t but not LL constants
+01-04-24 features/lib: add _std_strtod for mac os X
+01-04-23 ccode: add CC_sub for ms embedded EOF char on ebcdic -- no joke
+01-04-20 iconv: handle ebcdic<=>utf
+ mc.h,mc.c: add mcindex()
+ ast_std.h: add AST_MESSAGE_SET
+01-04-18 features/libpath.sh: fix mvs probe
+ *: sundry mvs fixes
+ glob: fix GLOB_NOCHECK to avoid stat() and properly trim patterns
+01-04-01 strtod,strtold: add
+ strtol,strtoul,strtoll,strtoull,strton,strtonl: handle locale & ERANGE
+ sfvprintf,sfvscanf: handle locale decimal_point,thousands_sep
+ sfvprintf,sfvscanf: handle %a,%A
+ setlocale: add LC_NUMERIC decimal_point,thousands_sep init
+ ast_std.h: __OPTIMIZE_SIZE__==1 to disable non-std __GNUC__ inlines
+ pathexists: path cache to cut down pathpath() access(2) calls
+ features/stdio: __FILE_TAG == _sfio_s for solaris
+01-03-23 iconv: fix iconv_move buffer boundary bug that stopped at 1 block
+01-03-19 glob: add GLOB_AUGMENTED
+ regex: REG_SHELL syntax error implies REG_LITERAL match
+ strto[ln][ll]: add overflow checks
+01-03-17 locale: reimplemented to provide canonical locale namespace
+ locale: add LC_ALL=local for local system user default
+ tm.h: TM_*_3 => TM_*_ABBREV
+ tmfmt: handle standard E and O format modifiers
+ tmlocale: consult nl_langinfo() if defined
+ fmtquote("\"",1) => shell quote
+01-03-08 regex: handle multibyte chars and collation classes
+ strmatch,strgrpmatch: now a wrapper on regex
+ ast_std.h: add mb*() multibyte and collation support
+ sfvscanf: handle locale decimal and thousand
+ proc*,system: handle ignored SIGCHLD
+ sfkeyprintf: handle %*C
+01-03-06 locale: add locale data cache for efficient multiple locale switching
+ optget: fix LC_MESSAGES!=C --man bug
+01-03-01 Makefile: HEADEROPT is not optional for win32.*
+ comp/syslog.h: comply with the de factos
+ optget(): fix \f...\f stack bug that referenced data after pop
+01-02-27 *locale*: a batch of fixes for native LC_MESSAGE&LC_TIME hooks
+01-02-22 pathprobe: reprobe test now checks probe.ini too
+ sfio_s.h: advertize public Sfio_t members with _ prefix
+ sfio.h,features/stdio: add <sfio_s.h> reference
+ sfhdr.h: map <sfio_s.h> _foo to foo
+ sfio.h: SF_APPEND=>SF_APPENDWR, SF_CLOSE=>SF_CLOSING
+01-02-14 comp/conf.sh: probe <unistd.h> for _(CS|PC|SC)_* getconf symbols
+ stdio/*: update for uwin stdio.dll binary compatibility
+ sfread: finally fixed premature pipe read EOF bug
+ fmtscale: format tenths for number > 0 && number < 10
+01-02-09 _sfmode(),_sftype(),_Sfextern: UWIN binary stdio compatibility exports
+01-02-08 sfgetm,sfputm,_sfputm: fix max clash with k&r max() macro
+ setlocale: undef valid for sun4 k&r valid() macro
+01-02-07 catopen.c: don't do native catopen for the debug locale
+01-02-06 sfraise.c: add SF_FINAL check to avoid (posibly) freed disciplines
+01-01-01 features/common: fix uwin __DEFINE__
+ sftable: initialize decimal and thousand
+ magic.tab: add corel wordperfect document
+ syslog: add LOG_LEVEL, add '\n' only if needed
+ include/tm.h: #undef daylight for _WIN32
+ sfio.h: add _SF_APPEND and _SF_CLOSE for native namespace incursion
+ ast_std.h: add AST_LC_multibyte for MB_CUR_MAX>1
+ setlocale: set AST_LC_multibyte
+ strmatch: check AST_LC_multibyte
+ features/limits.c: add _BITS_POSIX1_LIM_H guard for linux
+ features/libpath.sh: fix for aix LIBPATH
+ procopen,procclose: block SIGCHLD if PROC_FOREGROUND (e.g., system(3))
+ optget.c: add enumerated option argument values
+ optget.c: add <!--INTERNAL--> for private --html
+ optget.c: fix memory leak that hit shell builtins hard
+ sfio: drop sfread small chunk logic
+00-12-25 mnt.c: handle " and ' quoting for fstab
+ sftmp.c: let pathtemp() open the fd O_EXCL
+00-12-15 conf.sh: add -v for verbose trace
+ features/(limits|unistd).c: no FEATURE/types because of _POSIX_SOURCE
+ features/time: add default for CLOCKS_PER_SEC
+ features/lib: std_malloc now handles NeXT
+00-12-13 strton: recognize qualifier only if preceded by a digit
+ features/lib: change return in vfork() test to exit() for linux sparc
+ fmtquote: fix $'...' quote logic
+00-12-11 tmdate: fix cron format bug that mishandled months
+00-12-01 optget: handle $Id: ... $ in --?-version
+ features/fcntl.c: fix _STDPP_ mmap munmap
+00-11-27 magic: drop dup sfclose() in load()
+ optget: handle error_info.id==0
+00-11-22 features/stdio: add _FILEDEFED for sol9.sun4
+ strton,stronll: handle [u|U][l|L][ll|LL] qualifiers
+00-10-31 tmdate: add TM_DATESTYLE and mmddHHMM[cc]yy
+ astlicense.c: #include <hashkey.h> MAM workaround
+ astlicense.c: check for non-empty CONTRIBUTORS
+00-10-26 features/stdio: add _FILE and __FILE for gnu
+ misc/stk.c: fix stack pointer check off-by-one (dgk does it too!)
+00-10-23 syslog.h: sync with bsd values
+00-10-18 _STUB_* now functions instead of common symbols
+ all extern data declared with definition to eliminate common symbols
+ fastfind: add mac/bsd /var/db/locate.database
+00-10-17 features/lib: add apple osX (darwin.ppc) workarounds
+00-10-12 add: fmtbuf(), fmtclock(), fmtip4(), strtoip4()
+ fmt*() now use fmtbuf() for tmp fmt buf allocation
+00-10-05 regex: add REG_DISCIPLINE and regdisc_t for alloc/error disc
+00-09-29 features/lib: pipe_rw==0 for sgi: boot rw == bin incompatibility
+00-09-21 astlicense: handle \' and \" in license values
+00-09-20 sfwrite: fix write() error in sfprintf() loop
+00-08-11 hdr,vmhdr.h: check/hide { getpagesize sbrk } prototypes
+ astlicense: add noncommercial
+00-07-31 fflush: don't seek on pipes
+ sfresize: add
+ setlocale: fix bad newof() call
+00-06-01 strmatch: initialize match.current.beg[0] to avoid dump at line 670
+ sfio/stdio: a few more errno tweaks
+ astquery: sfstdin/sfstderr by default
+00-05-26 sfmode: errno=EBADF for invalid stream use
+00-05-22 rewind: fix for xopen test
+00-05-18 mcfind: returns absolute path
+00-05-16 optget: --keys must catch \f...\f too
+ translate,mc: errno cleanup
+00-05-09 magic: add netbsd binary magic
+ fts: PATH_RESOLVE!=logical => FTS_SEEDOTDIR
+ ftwflags: call fts_flags()
+ astconf: astconf(0,0,0) re-syncs with _AST_FEATURES
+00-05-08 optget: --usage & --keys for last -catalog group only
+00-05-02 iconv.c: add; use codes[] in ccmapid() and ccmapname(); "" for native
+00-05-01 pathtmp: copy env values (libshell or putenv may change)
+00-04-01 optget: drop bar from [-foo?bar] for --??keys
+ sfvscanf: add %X -- duh
+ features/common: fix va_listval() for power pc
+ findopen: fix FIND_GENERATE codes file search
+ magic: add ERROR_translate() and msgcat.key
+ tmlocale: add for LC_TIME locale info
+ tmlex: check tm_info.format and tm_data.format
+ tmfix: fix for tm_wday special case (via nl_langinfo on LC_TIME fields)
+ strftime: fix for nl_langinfo special case
+ ast_std.h: provide LC_* defauls if not defined
+ sfnew: check ${_AST_sfio_bufsize} -- don't tell kpv
+ catopen,nl_types.h: add intercept to mc* routines
+ magic.tab: add ast message catalog
+ strerror: add _ast_strerror intercept with ERROR_translate("errno")
+ fmtquote: escapes >0177 only if (flags&2)
+00-03-17 feof: stdio macro functions only for _UWIN
+ optget: proper ERROR_translate() calls
+ astgetconf: add for thread safe error message control
+ astlicense: fix type=special but with non-null notice
+ errorx: add for ERROR_translate() support
+ ERROR_translate: add locale id args for alternate dictionary
+ option.h: move _OPT_PRIVATE_ to pointer to avoid dll size mismatch
+ ftwalk: fix FTW_CHILDREN bug that hit top level non-dirs twice
+ translate.c: default error_info.translate
+ astconf: fix dup loop thrash that never returns, add _AST_VERSION
+00-03-10 ast_std.h: do _LARGEFILE_SOURCE initialization before std headers
+ fmtquote: handle $'...' quotes
+00-03-07 optget: fix numeric option support test
+ sfkeyprintf: add %q for '...' quoting with ansi escapes
+00-03-06 features/stdio: fix _sfflsbuf prototype (dingold@gte.net)
+00-02-14 pathtmp: fix pid cache bug that sometimes repeated after ~10 attempts
+ optget: "..." attribute quote
+ pathfind: eliminate *: prefix in lib, not type
+ proc: PROC_FOREGROUND for system(3) semantics (wait status return)
+ pathtmp: fix mktemp() logic
+ fts: fix FTS_NOSEEDOTDIR bug that botched ./* in top list
+ include/ast/prototyped.h includes include/prototyped.h
+ pathpath: fix strdup(0) bug
+ optget: --html <foo@bar> => ...mailto:foo@bar...
+ sscanf: fix sfsscanf => sfvsscanf typo
+ magic.tab: strengthen tar recognition
+00-02-08 conf.sh: fix ifdef for systems that think sysconf(FOO) is const
+00-02-04 glob: fix globlist_t.gl_flags
+00-02-02 vm*: add NoF() for data only files
+00-01-27 fts: fix top level .==.. statp bug (thanks to dr. ek)
+00-01-25 conf.tab: fix LFS*_*LAGS typo
+00-01-24 astlicense: handle type=verbose, license.notice, author=*
+00-01-11 pathprobe: generate info for first probe script on PATH - duh
+ ast.h: add NoF(x) for files that define no functions
+ tmpfile: fix implementation
+ global change for string ERROR_translate() dictionary names
+ optget: fix new way but no long names off by one
+ optget: handle [--dictionary?name]
+99-11-19 comp/conf.sh: `expr length XXX` is not universal
+ drop sfstdio; stdio via functions everywhere
+ drop Makefile conditionals (and follow our own advice for once)
+ sfio: new stream after atexit() bug fix
+ tm: Tm_zone_t.daylight=0 for standard time within zone
+ stdio: fopen => _ast_fopen: only way short of binary compatibility
+ Makefile: atmain.C falls back to atmain.c
+ optget: add --keys, s<section> option
+ stdio: _UWIN check for foreign stdio
+99-11-11 astlicense: add
+99-10-31 glob: fix regexec pattern; add PATH_ATTRIBUTES case check
+ pathpath: path==0 means malloc space
+99-10-22 tmfmt: %C=2-digit-century, %k=date(1), %y=2-digit-year-in-century
+99-10-18 fastfind: expanded default db lookup
+99-08-11 magic: fix off by one registry malloc
+ features/fs: add __RENAME checks for stat familiy (netbsd)
+ features/fs: major()/minor() fixes for s5
+ features/libpath.sh: netbsd fix -- ld.so not in std places
+ misc/fastfind: fix codes path generation bug
+ optget: beef up --?* description, fix <TR>...</TR> nesting
+ pathprobe: check for override (writable key file) first
+ features/time: int tmtimeofday(struct timeval*);
+ optget: fix opt_info.num, even if opt_info.arg!=0
+ fts: FTS_PHYSICAL => FTS_SEEDOTDIR, add FTS_CHOP
+ fastfind: init dir tab with logical and physical name
+ glob: add gnu GLOB_ALTDIRFUNC
+99-07-17 sfio: kpv update and sfhdr.h sync!
+99-06-24 stdio: fix fflush() to ignore sfseek(0) return value
+99-06-23 magic: '\r' is text not control to placate m$
+99-06-08 stdio: fix fseek,ftell semantics
+ uwin stdio: fflush() => _doflsh() to avoid __cplusplus clash
+ getopt: call liberror() to avoid error() conflict
+ tmfmt,tmscan: %N zone type (nation code), %z zone minutes west offset
+ tmfmt: - no pad _ space pad 0 leading 0 pad
+99-05-28 magic: fix 'x' == '*' for any number, magic.tab tweaks
+ features/lib: verify that stat64 really works
+99-05-21 tm*: add TM_WINDOW==69 for consistent century windowing guard year
+99-05-18 tmtime: add century leap year calc anticipating unsigned time_t
+99-05-17 sfkeyprintf: handle %o and %x!!
+99-05-09 pathprobe: $HOME/.probe if not suid and st_uid!=geteuid()
+99-04-28 magic,magic.tab: add registry()
+99-04-24 regcomp: fix ksh pattern +! parse
+ regfatalpat: add
+ optget: make : ? ] double escape consistent in all contexts
+99-04-01 features: drop iffeio.h and stdio.h when only printf() used
+ regex: fix stats() .l and .k count
+ fmtquote: added; most general fmtesc() form
+99-03-22 fmtesc.c,ast.h: add fmtnesq()
+ optget: --?x works for -x option flag
+99-03-17 features/limits.c: workaround solaris __EXTENSIONS__ _timespec bug
+ workaround limits.h circular prereq with ignore stdio.h
+ sfvprintf: %04e left-pad zero fixed
+99-03-03 fts: uncle already: add FTS_SEEDOTDIR to retain leading ./
+ regex: REG_MULTIPLE, BM for fixed string alternation
+ optget: embedded `-' optional in long options, prefix={0,1,2}
+99-02-14 fastfind: fix dir format bug that emitted wrong paths
+ astconf: fix redef off by one bug
+99-02-11 pathcanon(): don't cache astconf("PATH_LEADING_SLASHES", NiL, NiL)
+99-01-23 optget: move <old_opt.h> back into <option.h>, no open-close
+ optget: add "[index:long-name:description]" for --long-name
+ comp/gross: add weak __libc_attr for irix < 6.5 compatibility
+ features/limits.c: tweak the guards again
+99-01-11 fastfind: handle old format count byte order
+ magic.tab: fix elf to use real phdr offset
+ magic.c,magic.tab: fix | to act like switch/case
+ comp/fross.c,features/hack: for gross hacks
+ features/stdio: avoid sfio namespace pollution
+98-12-25 tmdate: yyyy.mm.dd
+ pathprobe: fix procrun() cmd path bug
+ fmtesq: add
+ features/common: win32.alpha va_list
+ magic: add pc alpha object
+98-11-11 strmatch: add STR_ICASE
+ pathprobe: punt to $HOME/.probe/<key+HOSTTYPE> if not S_ISUID
+ tmzone,tmdate: handle +-minutes, nn/MMM/yyyy
+ stropt: fix nested quote pop
+ tmfmt: add %K => %Y-%m-%d/%H:%M:%S
+ sfio/stdio: fix fseek() SF_PUBLIC omissions
+ fmtesc: catch '\\' (duh)
+ vmalloc: vmbest round bug fix
+98-11-01 fts.c: no pathcanon() if (fts_flags & FTS_PHYSICAL)
+98-10-01 features/stdio prototype fixes
+ optget: strton() instead of strtol() for #
+98-09-22 regcomp: add REG_DELIMITED and REG_ESCAPE delimited re support
+98-09-15 fix _LARGEFILE64_SOURCE stuff
+ ast_std.h: provide mmap() prototype
+98-08-11 fix sfpopen() to ignore SIGPIPE by ignoresig() for sfio but not stdio
+ fix procopen() to ignore SIGPIPE by ignoresig() for PROC_IGNORE
+ sfio sfpopen/popen update
+ magic.src: fix ustar entry
+98-07-17 fix ftwalk() short by one malloc()
+ add fts_notify()
+98-06-25 sfdcmore,sfdcprefix: add
+98-06-19 tokscan: add %f %g
+98-06-01 disc/sf*.c: memset(0) after disc malloc()
+98-05-11 strelapsed: y==Y
+ fts: pathcanon() top list
+98-04-01 error: error_info.time for all msgs, just after cmd id
+ error: no sfsync(sfstdin)
+ sfio: sfpool, Sffmt_t update
+ magic.tab: sgi core dumps -- why aren't these elf?
+ stropt: (v+n) for unknown option is option value if n!=0
+ procopen: fix setsid() for spawnveg() only
+98-03-19 malloc: add realloc foreign region check
+ sfdisc.h: rename to match kpv disciplines
+ fastfind: fix strcasecmp/strcmp directory prefix mixup
+98-03-17 features/fcntl.c,pathtmp,sftmp: add O_TEMPORARY
+98-03-01 pathcanon: fix PATH_LEADING_SLASHES to stat() both slashes
+ pathcanon: add PATH_VERIFIED
+ tmdate: add skip[] to expand separator char set
+ fastfind: FIND_OLD for old 7 bit db, FIND_TYPE for new 8 bit typed db
+ fastfind: default generates gnu LOCATE02 8 bit db
+ magic: handle %s in mime description
+ cdt: kpv update
+ sfio: kpv update
+ stdio: fpos64_t fseek64(), ftell64(), fgetpos64(), fsetpos64()
+ stdio: fseek() => sfseek(SF_PUBLIC) to avoid locking
+ fts: initialize parent stat[bp] from top level *after* statf done
+ astmath: add -lm requirement test
+ *: Astlong_t => _ast_*_t
+ regex: simplify regcollate() (from doug)
+ tmtime: preserve Tm_t*tm when calling tminit()
+ astconf: add readonly PATH_ATTRIBUTES=[cirw]
+98-02-14 fastfind: add FIND_ICASE to ignore case
+ tmdate,tmgoff: handle (+|-)hh[[:]mm[[:]ss]] absolute timezone
+ tmdate: `<n> <part>' now assumes `next <n> <part>' instead of `this'
+ tmfix: fix leap year bug that forgot to add 1900
+ proc: add PROC_ZOMBIE
+98-02-06 strmatch() char class range bug fix
+ regex char class range bug fix
+98-01-23 _WIN32: changed the #if logic again to accomodate _GNUC_
+ mnt: grab the mount options too
+ ast_std.h: hide getopt,getsubopt from stdlib.h
+ features/limits.c: add gnu guard macros to avoid limits.h recursion
+ features/mode.c: include "limits.h" instead of "FEATURE/limits.lcl"
+98-01-11 sfio.h: use Astlong_t, move Sfio_t Sfdisc_t typedef to top for stdio.h
+ sfhdr.h: #undef SETLOCAL for hpux
+ sfvprintf,sfvscanf: %I*x for sizeof(int_arg)
+ handle ftruncate64 and truncate64
+ dtopen.c: __hppa dll needs Dtset Dtlist Dttree refs here
+97-12-18 fmtnum: add
+97-12-11 magic: handle sgi 64 bit core dumps
+97-12-07 pathtmp: add override for TMPPATH,TMPDIR and cycling
+97-11-11 tm: handle 0 return from gmtime(),localtime() (dos negative time_t)
+ features/stdio: fix fflush() macro to do physical sync
+97-10-31 astconf PATH_RESOLVE is logical if 3d&&!std, metaphysical otherwise
+ magic: fix #! mime bug
+ tm: tmtime() now calls tmfix() and adjusts tm_isdst too=>mtime() works
+97-10-11 dllfind,dlfcn: move to separate -ldll so -last can link static, duh
+ Makefile,state.c: move forced header generation state.c => Makefile
+ sfio: update including SF_WHOLE
+97-10-01 sfdostext: add \r\n => \n sfio discipline
+ stropt: NiL table => p=name for all name=value
+97-08-11 pathtmp: check pid to note forks
+ procopen: FD_CLOEXEC rfd && wfd
+ fts: fts_close() after fts_children() with no fts_read() now works
+97-07-17 error: sfsync(sfstdin,sfstdout,sfstderr) instead of sfsync(NiL)
+ _sfcvinit: add sfio internal interface to base conversion tables
+ strton: use _Sfcv* base conversion tables instead of sfsscanf()
+ sfvscanf: use _Sfcv* base conversion tables
+ mime: x- permutations now matched if exact fails
+ mime: original- stripped from content-* headers
+ tmdate: add yyyy-jjj, yyyy-mm-dd
+ dllfind: add
+ ccmapid: fix buf copy loop limit
+ ccmapname,ccmapcpy: add
+ sfstrtmp: add
+97-05-09 streval: fix up casts for pseudo-ansi cc
+ features/types: use _ast_int_8 vars to verify support
+ string/modedata: check for mvs.390 S_IFMT
+ include/ast(_std).h: add #define __FILE_typedef
+ magic: add ccode text check
+ include/ftwalk.h: FTW_PATH=>FTS_NOCHDIR to avoid FTS_AGAIN (duh)
+ fts: clear status for FTS_AGAIN (fixes rm -r bug)
+ mnt: add mvs openedition w_getmntent()
+ sfhdr: _hdr_float && <float.h> for correct MAXDOUBLE
+ vmalloc/vmbest: if _std_malloc then use malloc()/free() not sbrk()
+ remove: check _std_remove
+ procopen: handle pio[{0,1}]=={0,1}
+ setenviron,features/uinstd: test for mvs.390 dll environ hacks
+96-12-25 <sfio_p.h> -> <ast_common.h>
+ __EXTERN__(type,object)
+ __DEFINE__(type,object,value)
+ magic: check strings in !CC_NATIVE code set too
+ system: cmd==0 means check for shell access (xopen)
+ sfhdr.h: fix sfrsrv prototype
+ add __libc_malloc etc for gnu/linux
+ astconf(NiL,path,name) == astconf(name,path,NiL) + no liberror
+ fts_open: if toplist() stat fails return 0
+ ftwalk: handle fts_open()==0 via one phony userf() call
+ sfmode: S_ISFIFO default is SF_SHARE=0
+ features/lib: _WIN32 _lib_vfork=1 by default
+ unsigned<0 comparison and other fixes via sgi.mips4 cc
+ stk.c: use <align.h> ALIGN_BOUND for stkalloc()
+ features/lib,vfork: uwin fix
+ ast_std.h: fix strto[u]ll prototypes with features/types _ast_int_8
+ getsubopt: add for xopen 4.2 compatibility
+ drop function __IMPORT__
+ magic: more magic
+ change #define FILE from Sfio_t to struct _sfio_s
+ state.c: add generated includes that may be hit by std for MAM
+ bytesex: forgot about sizeof(long)=>7; could we fix the name too?
+ vmalloc.h: fix vmnewof() definition
+ sfio.h,stdio.h,ast_common.h: pollution cleanup
+ magic.c: add | op for switch
+ Makefile: stdio.h was on both HEADERSRC and HEADERGEN -- don't do that
+ drop pp:notice to get <sfio.h> ... <ast.h> to work
+ regex: add [[:<:]]==\< and [[:>:]]==\> for bsd compat
+ mime.c: ignore X-* headers while scanning for Content-*
+ magic.c: check for negative indirect offsets
+ magic.tab: fix dos entry that generated negative indirect offsets
+ vmalloc.h: add vmstrdup() prototype
+ hash.h: add hashgetbucket() macro
+ magic.c: MAGIFILE is now a : file list
+ mnt.c: another 4.4 bsd fix -- users must include <sys/crap.h>
+ common: fix _WIN32 chicken&egg with va_copy
+ sfio: forgot to set f->val along with _Sfi in sfexcept()
+ Makefile: add mini target for uwin libmini.a
+ sfcvt.c: workaround for flaky long double optimizers
+ features/common: fix to work with va_list==void*
+ regexec.c: fix REG_STARTEND subexpression offsets
+ strmatch.c: don't forget <wctype.h>
+ regrexec.c: fix REG_INVERT end boundary bug that missed last record
+ astconf.c: notify(0,0,"a=b") called for each setenviron("a=b")
+ pathcanon.c: check astconf(PATH_LEADING_SLASHES) to preserve //*
+96-11-28 _LARGEFILE64_SOURCE by default if possible: NOTE: assumes xopen
+ regerror: fix for xopen
+ getopt: fix for xopen
+ magic: add ciao virtual database
+ astconf: posix/strict/xopen implies "standard" conformance
+ fs3d.h: hide mount prototype
+ ast_std.h,mnt.c,features/fs: ncr port tweaks
+96-10-31 version 5.0
+ add strtoll() strtoull()
+ sfkeyprintf: upgrade to int_max args
+ ast.h: add ssizeof() to work around unsigned botch
+ conf.sh: add shell actions to conf.tab
+ _DLL*: drop for _BLD_<lib> + __EXPORT__ + __IMPORT__
+ sfio,cdt,vmalloc: kpv update
+96-10-11 <ccode.h>: add character code map support
+ procclose: return shell style exit status
+ features/fs: pun statvfs.f_basetype to statvfs.f_reserved7 for mvs
+ uwin: add subdir for uwin additions
+ ast_std.h: swab() is from <stdlib.h>
+ sfio.h: <ast_std.h> if _PACKAGE_ast
+ magic.tab: add mips[1-4], 64-bit
+ port tweaks for sol.sun4 and sun4
+96-09-06 strerror: add
+ fmterror: uses strerror
+ str*search: use sfiso646() order
+ strpsearch: add
+ magic: add Magic_t.mime mime type return for magictype()
+ mime.h: add
+ strton: use sfsscanf()
+ strperm: factor in umask() if no who
+ pathtmp: add TMPPATH check
+ libevent: add
+ magic: add discipline to magicopen()
+ mime: add discipline to mimeopen()
+96-08-31 regex: fix BM fail table generator
+96-08-11 mntread: fix mnt.type for SCO variant
+ conf.tab: add SCO KERNEL_* sysconf() vars
+ fastfind: add findwrite(), fix findread() FF_OFF omission
+ ftwalk: reimplement on top of fts
+ fnmatch,re_comp,regexp: reimplement on top of regex
+ basename,dirname,fmtmsg,fts,ftw,getdate,getsubopt,glob: add
+ hsearch,nftw,realpath,strftime,strptime,swab,tempnam: add
+ tsearch,wordexp: add
+ getcwd: cache last path for easy test
+96-07-17 error: sfsync(NiL) ... write ... sfsync(sfstderr)
+ astconf: handle readonly *(DEV|DIR) vars
+96-04-01 swapop: fix stupid return value bug
+ features/int.c: fix int_swap generation bug
+ regnexec,regrexec: fix unsigned underflow init error
+ ls.h: fix iblocks() to be in units of LS_BLOCKSIZE
+96-02-29 magic: space before function is definition with no call
+ hash: drop hash_info from public interface
+ hash: OBSOLETE hashlast()
+ hash: add Hash_root_t.Hash_last_t to public interface
+ add strsearch() and strnsearch() to complement strlook()
+ add hashkey.h for keyword->long hash
+ pathpath: pathpath(0,0,"",0) disables $0 $_ $PWD relative search
+ sfio: sfstrtod+sfhdr update
+ regex: fix REG_LENIENT to map BRE \[+?|] to ERE [+?|]
+ change _std_malloc iffe test so it doesn't hang on alpha
+ sfhdr.h: features/sfio generates _lib_cvt instead of _i386_cvt
+ ast_hdr.h: add va_copy(a,b) to copy va_list b to a
+ getopt: fix stupid getopt() -> optget() bug
+ sfvprintf: %h? now downcasts
+ regex: handle strto?l() errno in regcomp()
+ sfstrtod: _Sfstrtod_already_defined -> _STUB_sfstrtod
+ ast_std.h: hide valloc() and ignore <strings.h>
+ sfkeyprintf: pass phony va_list for '2'
+ regex: change HIT var type from int to size_t in special()
+ ast.h: add EXIT_STATUS(x) to convert wait() status to sh exit status
+96-02-14 regex: add _ to \<...\> isalnum test
+ regex: fix BM inner loop breakout
+ features/types: size_t is signed on some systems! => _ast_size_t
+ sfio: sfrd discipline peek optimization
+ vmalloc: vmalloc.h malloc family macro upgrade
+ tokopen: fix newline bug for non-restore open
+ sfio: no inline for gcc until it emits for -g too
+96-02-12 sfio: internal upgrade
+96-02-09 regex: Boyer-Moore boundary fix
+ vmalloc: snarf latest
+96-02-06 regex: add regrecord() and regrexec() for Boyer-Moore record filtering
+ regex: rearrange regnexec() args to match buffer,count arg style
+96-01-31 stk: add STK_NULL to stk.h and stk.c
+ regex: privatize regex.h and fix min re length computation
+ workaround lazy strdup() implementations in features/lib _std_malloc
+ fix stkclose() to free(stream) -- purify missed because of sfio links
+ unused var cleanup
+ port/mnt.c must include <ls.h> to get <ast_fs.h>
+ add SF_FINAL to sfio and stk
+ sfio reads now on natural block boundaries
+ add #!!! <level> <message> !!! to tokline()
+ add REX_BM pre-filter to regcomp/regnexec
+96-01-22 add regcomp env.paren overflow checks
+96-01-11 add Doug McIlroy's regex (converted to C from C++ by gsf)
+ AT&T Research now
+ sfgetr optimization
+ regex buglets
+96-01-05 tweak magic.tab for win32
+95-12-25 add !(...) -> (...)! to fmtre()
+ nt tweaks -- functions with no header proto must be defined extern
+95-11-24 version 4.1
+ add mnt.h mntopen mntread mntclose
+ convert fmtfs to mnt.h
+ add RE_LEFTANCHOR and RE_RIGHTANCHOR
+ gcc inlines must also have global library function instantiation!
+ add hashview()
+ fix strtape() internal buffer flow
+ fix mntread() fs/dir transposition for uts mnttab
+95-10-31 change features/unistd.c includes to break limits-param cycle
+ add cdt from kpv
+ sfio snarf from kpv
+ add [ht]search for _WIN32
+95-10-11 clarify PARANOID pathcheck() warning
+ fix procopen() LIB_SPAWN environ bug with setenviron() cache
+ fix setenviron() bug that forgot to reset environ if == 0
+ add %Z '\0' output format to sfkeyprintf()
+ sfio snarf for sfvprintf fix
+ allow multiple hashscan() with scope caveat
+ add comp/fakelink.h to synthesize a few symlink text patterns
+ add !<xxx> magic to misc/magic.tab
+ add FTW_TOP to inhibit recursion (for ftw side effects on top level)
+ add memfatal() common malloc fatal exception message
+ add dos \r\n test to misc/magic.c/cklang()
+ sftmp() O_EXCL+random to avoid collisions
+ pathtemp() uses sftmp() randomizing
+ features/fs uses SF_APPENDWR
+ sftmp() uses pathtemp() -- don't worry, its not circular
+ a few more _WIN32 compatibility additions
+ realloc fixed to use VM_RSCOPY|VM_RSMOVE instead of obsolete 1
+ add hashlook(tab, oldname, HASH_RENAME, newname)
+ a few more tweaks to satisfy port warnings
+ add _SFIO_INLINE_PRIVATE to provide real function too
+ fix <dirent.h> installation test
+ oops object / shared library compat with _sfgetl2 _sfgetu2
+95-09-11 add getopt() compatibility
+ add fstat,lstat,mknod,stat fixes for _x versions in sys/stat.h
+ add getconf CONFORMANCE - posix for things that aren't ast default
+ sfio_t.h: #ifndef _SFIO_H #include "sfio.h" #endif
+ snarf vmalloc from kpv
+95-08-11 fix malloc bug in magic
+ update linux and bsd 386 magic entries
+ error_info.auxilliary returns new level, |=ERROR_OUTPUT if msg done
+ drop fnmatch from strmatch for sparc (solaris) until it collates
+95-07-17 fix port/astconf universe initialization
+ fix misc/optget opt_info.nopt initialization
+ drop tmset() TZ=... because it only worked when TZ=... was ignored
+95-05-09 mongo <ast.h> namespace cleanup
+ drop > 2 year old obsolete interfaces
+ sfvprintf.c fix for (char:8 short:16 int:32 long:64) architectures
+ TMP_MAX back into conf.tab
+ pathbin() and pathshell() now use astconf()
+ fix pathtemp() to not cache getenv("TMPDIR")
+ fix ftwalk() metaphysical to handle non-dirs too
+ initialize *_info = { 0 }; for ancient ld semantics (NeXT)
+ fix magic() to do vmfree()
+ astconf(X_OK) must prefix lines with "getconf"
+ use <wchar.h> and wctype in strmatch() if available
+ _lib_utime_now checks utime(path,0)
+ _lib_poll_notimer checks poll(x,0,timeout)
+ add another _lib_utime_now check to port/touch.c
+ fix dd_buf cast in dir/opendir.c
+ split getconf.h into conftab.h and conftab.c for :READONLY:
+ use mbtowc() only if MB_LEN_MAX>1
+ sfio char* -> Void_t* cleanup
+ handle old syntax in misc/magic.c
+ sigdata.c holds readonly signal strings
+ pathcheck() does AT&T checks for tools matching PARANOID - yuk
+ unused var cleanup
+ deprecate hash_info in favor of hashlast()
+ fix bad conf.sh ksh integer interactions
+ dll cleanup
+ magic.c falls back to malloc for now
+ add environ to <ast.h> -- C library global data syms are *RESERVED*
+ sfhdr.h memccpy(1,2,3,size_t) prototype
+95-04-01 version 4.0
+ convert to vmalloc
+ allow sigcritical() nesting mismatch to work around vfork() bug
+ add strexpr() primitive for streval() with user handle (like ftwalk)
+ add <magic.h> and magic.c file command magic interface
+ update magic mail message entry
+ fix keyprintf() invisible char count nesting bug
+ add sfstrnew(SF_READ|SF_WRITE) for alternate sfstropen() modes
+ sfstrnew(SF_READ) but reading requires sfseek(), sfreserve()
+ add conf.tab and conf.sh to nail C/POSIX limits/unistd macros
+ add getconf() string interface to *conf*
+ _DLL_INTERMEDIATE_DATA for systems that require indirect globals
+ _DLL for building shared libraries with _DLL_INTERMEDIATE_DATA
+ vecfile() restricted to S_ISREG()
+ add spawnveg() for job control
+ convert procopen() PROC_PGRP(id) to spawnveg()
+ fmterror() returns error text given errno (strerror() does same)
+ fmtsignal() returns signal text given errno (strsignal() does same)
+ {sig_name,sig_text,SIG_MAX} -> sig_info.{name,text,sigmax}
+ liberror("",...) omits [%s library] prefix
+ update features/signal.c table
+ add vmdisc() and change vmnewof() to use vmresize()
+ fix conf.sh to allow refs to previously defined limits
+ fix undefined entries in getconf()
+ magic data in magic.tab
+ fix stropt() pointer cast
+ vmalloc() exception handler replaces nomalloc()
+ merge sigdata.c into fmtsignal.c -- sun link needs function w/ data!
+ sftmp() bug fix
+ drop local <unistd.h> even with _POSIX_SOURCE
+ fix vmstrdup() macro arg miscount
+ fix conf.sh to handle enum'd symbolic constants in unistd.h
+ drop malloc() et.al. prototypes from vmalloc.h
+ fix sfvprintf() %d argument reference
+ add OSF/1 AES symbol(s) to conf.tab
+ determine standards prefix from conf.tab
+ add _CS_SHELL to conf.tab
+ getpath() default is confstr(_CS_PATH)
+ getshell() default is confstr(_CS_SHELL)
+ unify keyprintf user function args (should have learned by now!)
+ add quad type to magic
+ add astfeature() to unify universe style dynamic features
+ add ftwflags() to determine FTW_* flags from astfeature()
+95-03-11 fix stropt() to not modify its *const* arg
+ handle "'\ quotes and chresc() in stropt() values
+ , treated like :space: between stropt() options
+ fix procopen() fd dup to ignore self-dups
+ add library id[] to misc/state.c
+ add ftwalk(FTW_METAPHYSICAL) for posix -H
+ sfvprintf() now handles balanced () in %()
+ add tmfmt() with buffer size check to replace tmform()
+ add fmttime() calling tmfmt() to fit fmt*() mold
+ add <keyprintf.h> and keyprintf() to support %(...)? in commands
+ add Hash_table_t for size==0 in stropt()
+ add EXTTYPE extended header to tar.h
+95-02-14 sfmove() buffer size overflow fix
+ add _SFSTDIO_H to sfio.h
+ rename setenv() to setenviron() -- posix finally decided
+ rename <option.h> opt_* to opt_info.*
+ update features/unistd.c for _SC_* and _PC_* posix additions
+95-01-19 (char*)uchar cast in fmtesc()
+ fix hash bucket memory leak in hashlook() [via John Mocenigo]
+ update strings/strtape()
+ fix optget()/optjoin() to handle leading +
+ add ALIGN_ prefix to <align.h> identifiers
+95-01-11 change tm/*.c tmset(0) to tmset(tm_info.zone) to keep user setting
+ fix tmform() %Z null pointer dereference
+95-01-01 add this RELEASE file
+ fix strperm() to properly handle "644 file"
+ fix tokline() to return last '\0' terminated line in string
+ fix tokscan() to properly handle \\n splice
+ add fmtesc() to complement stresc()
+ add LS_NUMBER to fmtls()
+ drop spurious optusage() ' '
+
+:::::::: libcmd ::::::::
+
+12-02-14 rm.c: --force ignores no file operands specified
+12-01-10 b_* (int, char**, void*) => (int, char**, Shbltin_t*)
+11-08-27 pids.c: add getsid() iffe test
+10-08-16 chmod.c: add -l alias for { -h --symlink }
+11-08-16 chgrp.c: change lchmod() ref to lchown()
+11-05-03 cp.c: do not delete src if mv to dest fails -- doh
+11-03-28 chmod.c,chgrp.c: fix --symlink logic
+11-03-26 rm.c: don't eaccess() check symlinks!
+11-01-27 date: add { -R, --rfc-2822, -T, --rfc-3339=type }
+11-01-03 chgrp.c: --symlink => --physical
+10-12-10 rm.c: fix not-writable logic
+10-12-01 tee.c: add iterrupt logic for slow open(1) -- needs to be generalized
+10-11-30 chgrp.c: add -N,--numeric to bypass name lookup
+10-10-20 cp: add --timestamps (preserv timestamps and permissions)
+10-10-20 ln: fix 'cannot replace existing file' logic
+10-10-10 cp,mv: add --remove-destination
+10-08-11 cp.c,expr.c: use conformance("standard",0) test
+10-08-11 cut.c: use mbnsize() instead of mblen() (for ast C.UTF-8)
+10-07-28 chgrp.c,chmod.c,cksum.c: fts_path for diagnostics, not fts_accpath!
+10-06-14 rm.c: fix -rfu logic
+10-06-12 paste.c: repeat after me: do not modify argv[i]
+10-06-01 sync with ast api 20100601
+10-05-09 tail.c: fix -0f bug that inially listed the entire file
+10-05-06 basename.c: add { -a,--all -s,--suffux=suffix } from BSD
+10-04-12 cat.c: fix -v bug that dumped core and make consistent with cmp --print-chars
+10-04-11 cmp.c: add --print-bytes, --count=n, --differences=n
+10-04-08 vmstate.c: add { method flags } vars for Vmstat_t.mode
+10-04-08 mkdir.c: fix check for { S_ISUID S_ISGID S_ISVTX } after successful mkdir(2)
+10-04-01 stty.c: add --fd=fd option
+10-03-23 tail.c: fix -f large initial offset bug that didn't copy all data
+10-03-07 tail.c: sfsync(sfstdout) after all -f done, fix -f partial line
+10-03-05 mktemp.c: add --regress=seed for testing
+10-03-05 vmstate.c: add
+10-01-26 tail.c: -f sleep(1) only if no progress from last round of checks
+10-01-20 fts_fix.[ch]: use <fts_fix.h> instead of <fts.h> (see fts_fix.c)
+10-01-20 cp.c: free(state) if called from old shell
+09-12-10 join.c: <wctype.h> for iswspace()!
+09-12-04 cmd.h: fix CMD_DYNAMIC logic
+09-12-04 cut.c: handle -d mb
+09-12-03 mkdir.c: add --verbose
+09-11-30 cat.c,date.c,cksum.c: drop setlocale() call already done by optget()
+09-11-30 join.c: handle -t mb
+09-11-28 wclib.c: { -w -L } mb independent of -m
+09-11-28 paste.c: handle -d mb
+09-11-28 uniq.c: handle -s mb
+09-11-28 cksum.c: FTS_SEEDOTDIR by default
+09-09-09 fds.c: add --unit=fd
+09-08-25 tail.c: initialize Tail_t.fifo=0 !!
+09-08-15 tail.c: fix fifo logic
+09-08-11 wc.c: add setlocale(LC_CTYPE,"C") cleanup, add utf8 optimzations
+09-08-10 uniq.c: replace -c 1..9999 sfsprintf() with inline conversion
+09-08-01 join.c: fix empty field null pointer deref
+09-07-23 pathchk.c: add -P,--path and -a,--all
+09-07-02 chgrp.c,chmod.c,cksum.c: fts_flags() default only if not --recursive
+09-06-19 cmd.h,cmdinit.c: add ERROR_CALLBACK for ERROR_NOTIFY main() callback
+09-06-19 mktemp.c: --unsafe now checks and prints path but does create
+09-06-19 tee.c: add ERROR_CALLBACK for tee_cleanup() sfio discipline pop
+09-06-18 rm.c: handle interrupts during interactive query
+09-06-18 cp.c: handle interrupts during interactive query
+09-05-25 tail.c: fix old style option logic to handle --invalid-long-option
+09-05-24 tail.c: -r == +1r
+09-05-01 mktemp.c: handle foo/prefix, add -p dir and -u
+09-03-31 cat.c: handle --no* options
+09-03-15 tail.c: fix --timeout termination logic
+09-03-03 tee.c: clean up sfio disciplines on error
+09-03-03 cat.c: fix -v|-e|-n|-B interaction bugs
+09-02-14 tail.c: fix VSC failures
+09-02-14 join.c: fix VSC failure
+09-02-02 uniq.c: document -number == -fnumber, +number == -snumber
+09-02-02 tail.c: fix usage[] for negative offsets, add sun -b
+09-02-02 mktemp.c: add
+09-02-02 features/utsname: UWIN _UNAME_os_DEFAULT => UWIN
+09-01-31 dirname.c: add experimental { -f -r -x } for pathpath(3)
+09-01-05 cmp.c: fix EOF diagnostic to conform to posix
+09-01-03 mkfifo.c: fix --mode=mode logic
+08-12-07 date.c: add %[_][EO]K for [space pad] [full|long] iso docs
+08-11-10 stty.c: check for -t grouping so -tostop != -t -ostop
+08-10-15 rm.c: handle 'rm -f x x' => exit 0
+08-09-08 stty.c: #ifdef guard TAB[012] -- freebsd: damn the posix, full speed ahead
+08-06-17 shcmd.h: move to libast
+08-04-24 uniq.c: add optget() 'n' option for -1 => -f1
+08-04-24 getconf.c: clarify diffs between "name - value" and "name = value"
+08-04-01 cut.c: add write error check
+08-04-01 paste.c: fix --noserial stream vector access bug
+08-04-01 pids.c: add ls/ps style --format=format
+08-04-01 stty.c: fix off2 unitialized reference
+08-03-28 chgrp.c: add --before=file
+08-03-14 pids.c: add
+08-03-11 chgrp.c: fix -m to use uid:gid as lookup key
+08-02-11 Makefile: add -lmd possibly required by sumlib.o -- hack alert
+08-01-30 expr.c: fix <=0 type that broke substr * 1 * -- wow
+07-12-13 cp.c: fix builtin state reinitialization
+07-11-29 rev.c: honor multibyte locales
+07-11-27 cp.c: open non-existent destination with O_EXCL
+07-11-27 stty.c: add -t,--terminal-group to list tty pgrp
+07-11-27 cksum.c: --silent -s => -S, -s == -x sys5 for gnu compatibility
+07-11-11 tee.c: drop ancient bsd compatibility "-" operand => SIGINT
+07-10-29 cksum.c: add SUM_LEGACY for -r
+07-10-12 cp.c: plug usage string memory leak by using per-builtin state
+07-09-21 cksum.c: add sumprint() default scale arg, --scale, --bsd for solaris
+07-09-10 chmod.c: add --show,-n
+07-07-27 wclib.c: bias <wchar.h> checks for modern unix
+07-07-17 cat.c: fix --squeeze-blank to reduce multiple blank lines to *one*
+07-05-20 cmd.h: handle msvc's balk at if(0)0=0;
+07-05-20 cksum.c: #include <modex.h>
+07-05-11 cmd.h: add _CMD_CONTEXT_OK() to verify >= 20070511 context
+07-05-09 fds.c: handle ipv6 sockets
+07-05-09 cmd.h: <shbltin.h> : cmdquit() => sh_checksig(context)
+07-04-25 mkdir.c: force (S_ISVTX|S_ISUID|S_ISGID) after mkdir(2)
+07-04-24 procrun.c: add -last intercept => sh_run() and whence -q
+07-04-19 uname.c: name operands first checked for CS_NAME, then NAME
+07-03-28 date.c: add --unelapsed=scale, -U: fmtelapsed() => strelapsed()
+07-03-25 wclib.h: iswspace() requires <wctype.h>!
+07-03-11 tty.c: add sysV --line-number, -l
+07-02-26 Makefile: sumlib.o: direct extract from +lsum (vcodex someday)
+07-02-24 Makefile: tweak cmdext.h action for --mam bootstrap
+07-02-09 Makefile: { cmdext.h cmdlist.h } depend on *.c list!
+07-02-09 Makefile: +lsum to bring in static -lsum (no dynamic right now)
+07-02-07 cksum.c: move from src/cmd/std with ftwalk => fts
+07-02-07 getconf.c: handle /bin == /usr/bin in defer logic
+07-01-26 chmod.c: don't FTS_FOLLOW if !FTS_PHYSICAL
+07-01-23 cut.c: Cut_t variable dimension list[] must be last member
+07-01-22 uname.c: fix -h typo that clobbered astconf() state -- ouch
+07-01-02 fmt.c: fix buffer splice off by one bug -- what else
+06-11-23 cmd.h: because of proto cmdinit cannot be a function like macro
+06-11-21 cp.c: fix 06-10-31 const dot[] readonly assignment
+06-11-15 cp.c: fix 06-10-31 ln -s enoent bug
+06-11-11 getconf.c: let astconf() handle "undefined" vs. ""
+06-11-11 getconf.c: fix deferred getconf path search
+06-11-11 fmt.c: handle two char { \t \n } in --usage ouput
+06-10-31 global edit to eliminate most non-const static data0
+06-10-31 use <cmd.h> for all b_*() implementations; drop <cmdlib.h>
+06-10-31 cmd.h: add CMD_ prefix to { BUILTIN DYNAMIC STANDALONE }
+06-10-31 join.c: tone down /tmp usage vi SFSK_DISCARD
+06-10-31 cp.c,rm.c: update to <fts.h> to accomodate non-static data
+06-10-29 date.c: "...%H%..." => "...%H" "%..." to avoid SCCS conflict
+06-10-26 fds.c: handle sctp
+06-10-18 tail.c: fix invalid suffix infinite loop
+06-10-11 chgrp.c,cp.c: add sfstruse() error checks
+06-10-10 tee.c: add --linebuffer, -l
+06-10-06 getconf.c: preserve native getconf(1) known variable behavior
+06-10-04 sync.c: add (thanks to Roland Mainz)
+06-10-04 getconf.c: add -v specification => run native getconf(1)
+06-09-28 stty.c: static setmode() => set() for darwin.i386
+06-09-27 head.c: handle -1c => -c1
+06-09-19 pathchk.c: pathconf() => astconf()
+06-09-11 tail.c: handle compatibility corner cases
+06-09-08 date.c: add output write error diagnostic
+06-09-04 tail.c: fix initial position for -n0, no args => no -f
+06-08-28 uniq.c: add -D,--all-repeated
+06-08-25 wc.c,wclib.c: add -L,--longest-line,WC_LONGEST
+06-08-24 wc.c,wclib.c: implement -m and WC_MBYTE
+06-08-24 rmdir.c: -sp applies to every message, add gnu -e
+06-08-23 rmdir.c: add solaris --suppress, -s
+06-08-23 mkdir.c: don't add 0300 to -p final dir mode
+06-07-17 cut.c: handle last line with no newline
+06-07-17 cut.c: --output-delimiter == --line-delimiter
+06-06-25 chmod.c: mask -c output with S_IPERM
+06-05-09 uname.c: add -o; change -a to match linux
+06-05-03 date.c: add --last -L to list last of multiple time args
+06-02-14 tail.c: fix -f bug that lost fast stream data
+06-02-11 getconf.c: exit 1 if name invalid -- duh
+06-01-28 cp.c,rm.c: fix astquery() 'q' to return and not exit()
+05-08-11 fmt.c: fix -o to handle raw --usage strings
+05-05-17 cat.c,head.c: disable EPIPE error messages
+05-04-14 chgrp.c: -f means all non-syntax error messages
+05-04-11 fds.c: add from old internal open(1)
+05-04-09 cmdext.h,cmdlist.h: generate from source -- about time
+05-03-24 features/symlink: verify { lchmod lchown } implementations
+05-03-07 date.c: add --listzones to list the time zone table
+05-02-14 chmod.c: add --reference=file
+05-01-11 cat.c: restore output stream to binary mode on exit
+04-12-15 cp.c: add --preserve high resolution time support
+04-12-08 date.c: add high resolution time support
+04-12-01 cmp.c: fix %6I*ld => %6I*d -- doh
+ fmt.c: handle "\n\n operands \n\n"
+ head.c: handle -cN -nN, N > 4Gb
+04-11-22 cmp.c: handle >2G chars/lines
+04-11-18 fold.c: add --prepend=text, --append=text
+04-10-31 tail.c: use SF_LOCKR macro
+04-10-28 tail.c: use strtol() for old stype [+-]number[suffix] -- doh
+04-10-22 cp.c: check rename() errno==ENOENT to retain destination
+04-10-11 fmt.c: fix -o,--optget sublist bugs
+ tail.c: use strton() for number conversion
+04-10-08 pathchk.c: add empty path and -p - first component char
+04-10-01 fmt.c: add -o,--optget concatenated usage string format
+ stty.c: context is ERROR_INTERCATIVE
+ rm.c: restore 3d before exit
+04-09-24 pathchk.c: fix docs
+04-09-14 date.c: add %| and %& --parse docs
+04-08-27 cp.c: add FTW_DC check -- duh
+04-08-01 fmt.c: handle last char != '\n'
+04-07-22 date.c,uname.c: access() => eaccess()
+04-07-01 fmt.c: handle large input lines -- ouch
+04-06-11 id.c: fix -r to output something!
+04-05-27 expr.c: fix `:' op subexpression output
+04-04-15 chmod.c: follow symlink for relative mode
+04-04-12 Makefile: add STDCHMOD (for osf.alpha)
+04-03-19 tail.c: handle -f sfreserve() large chunk failure
+04-02-29 cp.c: decouple -f and -i for standard CONFORMANCE
+ cp.c: mv now attempts rename() before remove()+rename()
+ date.c: -f format or +format disables system clock set
+04-02-14 cp.c: add -F --fsync to call fsync(2) for each copied file
+04-01-05 head.c: -s now uses opt_info.number for >2Gb skip
+03-09-18 tail.c: add --log
+03-09-11 rm.c: add --unconditional
+03-08-11 fold.c: add --delimiter=c to break at c
+03-07-28 features/time: change settimeofday() test to 2nd arg of (void*)0
+ expr.c: add {match,substr,index,length,quote}
+03-07-15 fmt.c: fix trailing space bug
+03-06-20 uname.c: fix -p constant string overwrite
+03-06-04 stty.c: add undef to control assignment docs
+03-05-31 uname.c: add -f and sysinfo()/confstr() compatibility via astconf()
+03-05-27 rm.c: fix inappropriate "/.." append path overflow
+ cut.c: snarf from dgk
+03-05-18 rm.c: check st_nlink to verify progress w.r.t. ftwalk/fts
+03-05-15 join.c: fix stealth -v2 bug (thanks ahs)
+03-05-04 wc.c: drop trailing space for `wc -l < file'
+03-03-21 date.c: add %Q/recent/distant/ docs
+03-02-19 date.c: fix %+|!flag docs
+02-11-14 update for cmdinit() 4th arg and ERROR_NOTIFY for interrupt cleanup
+02-10-02 date.c: tmform() => tmfmt()
+02-09-30 date.c,uname.c: change execv() calls to procrun(): exec|exit => bad
+02-09-06 wclib.c: fix 1 char-at-a-time miscount bug
+02-08-19 chgrp.c: convert to use <cdt.h>
+02-07-23 join.c: fix comm snarf typo
+02-04-05 date.c: add %u
+02-01-24 stty.c: ifdef a few more macros for uts (yes, its still running)
+01-12-14 date.c: clarify %z doc
+01-10-31 mkdir.c: mkdir() on existing dir could fail with errno!=EEXIST
+ uname.c: add execve() loop check for unknown options
+01-10-29 tail.c: SF_SHARE on only if not reading through EOF
+01-10-11 getconf.c: fix usage typos
+01-09-11 cp.c,cmd.h: handle . in argv[0]
+ cp.c: add O_BINARY to all open() calls
+01-09-06 tail: input streams must be SF_SHARE -- duh
+01-07-16 stty: fix cntl() macro for CC_NATIVE!=CC_ASCII
+01-05-31 date: fix /bin/date fallback logic
+ stty: fix a few mismatched flags, -a and -g option logic
+ stty: tone down sane to modify current settings rather than from zero
+01-05-01 uname: -i => -h, add sol.sun4 -i, add sgi -R, punt to /usr/bin/uname
+01-04-17 date,rm: add
+01-03-07 cp: fix readonly string mod on "."
+01-01-23 cp: `cp foo' => `cp foo .' only for CONFORMANCE!=standard
+00-12-01 cut: multibyte support
+00-10-31 mkdir: handle races by checking EEXIST
+00-09-20 cp: copy argv to stack before modifying in place
+00-05-18 add setlocale(LC_ALL,"")
+00-04-30 join: drop weird opt_info.argv reference
+00-03-17 expr: add == operator -- duh
+ cp,ln,mv: delay pathcanon() on destination to verify `cp a b/.'
+ getconf: use astgetconf for proper message control
+ ERROR_translate: dictionary update
+00-03-08 tail: handle multiple -f files
+00-03-07 fmt: add
+00-03-07 dirname: handle PATH_LEADING_SLASHES as documented
+ tail: accept + options
+00-02-14 chmod: --ignore-umask to ignore umask(2) in symbolic expressions
+ chmod,chgrp,cp: use FTS_NOSEEDOTDIR for correct path construction
+ cat: fix -n (was ignored, wow)
+00-01-27 getconf: add "-a" and "-v spec" for sol7.* compatibility
+99-09-09 join: fix -j1 vs. -j 1, add --ignorecase
+99-06-22 paste: defualt delim in writable string
+99-06-16 cat: fix --dos-ouput typo
+99-06-11 cp: tighten chown() diagnostics
+99-06-08 expr: nothing for NULL string bug fix
+99-05-21 paste: fix missing newline columnize bug
+99-05-20 mv: do not check for `mv foo foo' since rename() handles it
+99-05-01 cmp,comm,cp/mv/ln,expr,fold,getconf,head: long options
+ join,logname,paste,pathchk,tail,tee: long options
+99-04-10 uname: long options, stdize -a
+ chmod,head,tail,rev: long options
+ cut: long options, pass regression test 02
+99-04-07 cat: long options, fix O_TEXT modes
+99-01-11 tail: fix +n
+ join: another ggs/psm bug
+ join: all 1 and/or 2 to be unseekable
+99-01-01 cp: fix -p
+ chmod: drop -l option because of clash with l (lock) mode
+98-12-25 cat: add -T to sfopen(,,"rt")
+98-11-11 chgrp,chmod: cannot open file stream => not found
+ join: fix another ggs/psm bug; thanks guys
+98-10-20 cp: fix cp -rp to update dir times too
+98-09-22 join: fix ggs null field bug
+98-08-11 join: fix last regression test bug
+98-05-29 join: add jp->common to handle boundary conditions
+98-03-11 cat,cp,rev,tee: fix sfmove() error checks
+98-03-01 join: fix bug that emitted records more than once after eof
+ cp: fix sfmove() error check
+98-02-14 cp: -R physical, -[HLP], -r getconf(PATH_RESOLVE)
+98-01-11 cp: check sfclose() return value
+98-01-07 chown,chgrp,chmod: use fts for -R
+ mkdir: fix -p default mode
+97-12-07 mkdir: fix umask() reset
+97-11-11 chown,chgrp: proper interpretation of -h,-l for lchown()
+ chown,chgrp: only chown() if uid or gid change
+97-10-31 mkdir: do umask right
+97-08-11 cmdinit: clear opt_info.index to allow multiple calls
+ cp,ln,mv: add
+97-07-17 join: fix a few more -a bugs
+97-05-31 expr: optget() only if CONFORMANCE==standard
+97-04-01 join: fix a few bugs that make it work!
+96-12-25 head: sfset(sfstdin,SF_SHARE,1)
+ Makefile: add -last to cmd lib list
+ drop function __IMPORT__
+96-08-11 tail: check for truncated file and rewind for -f
+96-04-08 update <cmd.h>
+96-02-29 uname: -a like std, -l for everything
+ id: add -a (default)
+96-02-14 wc: speed up inner loop newline breakout
+96-01-30 unused var cleanup
+96-01-01 AT&T Research now
+ pathchk: handle getcwd(0,0) error
+ expr: switch to <regex.h>
+95-11-11 add expr.c
+ fix cut exit code and -s optimization
+95-10-11 add extern b_* to cmd.h
+ add void* context 3rd arg to b_main()
+95-05-09 add getconf
+ cat -u avoids mmap
+ add chown|chgrp -m uid|gid map file
+ add chown|chgrp -P for systems with lchown(2)
+ chown|chgrp -P => lstat() too!
+ chmod|chown|chgrp -HLP
+95-04-01 version 1.2
+ add rmdir
+95-02-14 fix mkdir -p symlink bug
+ fix mkdir '/' skip bug that went one too far
+
+:::::::: libcoshell ::::::::
+
+12-02-22 coinit.c: handle non-identifier export var names
+11-12-13 cowait.c: handle sfpoll() error return on interrupt
+11-11-21 cowait.c: poll before blocking read to weed out killed jobs (no 'x' message)
+11-08-30 codata.c,coopen.c: drop macro "..." catenation for old cc
+10-08-11 coinit.c: force _BLD_DLL for environ intercept
+10-06-01 sync with ast api 20100601
+10-05-19 cokill.c: do cowait(co,co,0) to drain pending messages
+10-05-15 coshell.h,coopen.c: add CO_ORPHAN for PROC_ORPHAN
+10-05-11 coopen.c: add PROC_ORPHAN for CO_SHELL
+10-05-10 coopen.c: no atexit() for CO_SHELL
+10-04-15 first ksh93u local job pool tests work (service daemon tbd)
+10-04-14 cowait.c: add 3rd cowait() arg timeout; 0 Coshell_t* operates on all open coshells
+10-04-10 coshell.h: add CO_SHELL for shell using coshell!
+09-12-09 coexport.c: add runtime CO_ENV_EXPORT hook that avoids changing environ
+08-10-28 coopen.c: close write side of parent msgfd -- doh
+08-04-28 coexec.c: check for fd 1,2 equivalence before CO_SERIALIZE 2>&1
+07-10-29 coshell.h,coexec.c: fix procrun()/system() intercept logic
+07-08-15 add CO_SEPARATE,CO_MODE_SEPARATE for separate shell+wait per action
+07-04-09 Makefile: $(CC.PIC) to allow archive to be pulled into other dlls
+06-08-22 coshell.h: procrun => coprocrun, system => cosystem
+06-08-09 coshell.h: export CO_ENV_MSGFD for COSHELL=coshell
+06-08-02 coexec.c: Cojob_t.flags&CO_SERVICE for service requests
+06-08-02 cokill.c: cokill() signal==0 => kill CO_SERVICE jobs
+06-07-27 coexec.c: drop server cowait() that bypassed caller
+06-06-21 coexec.c: add non-block cowait() to drain responses
+06-06-11 fix service intercept cleanup
+06-05-24 add service=name:init lightweight service intercepts
+05-04-19 cowait.c: beef up invalid message tests and diagnostics
+05-04-11 drop fixed CO_MSGFD for $_coshell_msgfd
+05-04-07 coexec.c: fix !_lib_fork&&_map_spawnve close-on-exec redirection
+04-09-22 cowait.c: remove CO_SERIALIZE temporaries after listing -- duh
+04-09-01 co*: add CO_SERIALIZE
+04-07-22 system.c: access() => eaccess()
+04-02-11 coinit.c: fix CO_CROSS PATH initialization
+02-10-30 coclose.c: fix reference-after-free bug in coclose()
+02-01-31 codata.c,coopen.c: fix CO_MSGFD parameterization
+02-01-24 coopen.c: fix small memory leak
+01-10-26 coopen.c: hung sfclose(fp) -> close(sffileno(fp)) -- wow
+01-09-11 coinit.c: fix coident[] for ancient bsh that die on `test == 1'
+ coinit.c: and fix coident[] to weed out buggy ksh88i trap on exit
+01-05-31 co*: add CO_CROSS, expose CO_DEVFD
+01-04-23 coquote: add state.type to avoid getenv() overwrite on some systems
+01-01-01 cokill: killjob => cokilljob, killshell => cokillshell
+00-12-18 coinit: CO_OSH ? "${!-$$}" : "${!:-$$}"
+00-10-25 codata: $ZSH_VERSION is not ksh
+00-02-14 procrun,system: system(3) returns wait() status (not shell status)
+99-11-19 co*: add CO_OSH for bsdi lack of times(1)
+ coexec: CO_IGNORE for all but real ksh
+98-06-22 coinit: quote cd path arg
+
+:::::::: libsum ::::::::
+
+12-02-29 sum-sha2.c: bitcount[] order reversed to allow a single noalias buffer copy
+09-09-28 sumlib.c: use simple (faster) method name match function
+08-06-05 sum-lmd.c: align context to largest int
+08-05-01 sumlib.c: add some -lmd verification checks
+08-02-11 sum-lmd.c,features/sum: add wrapper for solaris -lmd
+07-10-29 sum.h,sumlib.c: add SUM_LEGACY for legacy output format
+07-09-21 sum-sha1.c: reinstate Steve Reid's public domain implementation
+07-07-26 sumlib.c: drop GPL sum-sha1.c
+05-02-14 sumlib.c: split into sum-*.c
+05-02-14 sum-sha2.c: add SHA { 256 384 512 }
+04-02-29 Makefile: compile with $(CC.PIC) for codexlib/sum $(CC.DLL)
+03-12-16 add { crc prng } generic methods and maps[] to these methods
+03-12-16 sum.h,sumlib.c: add sumdata()
+03-09-29 sumlib.c: fix FNV to use ^ instead of +
+03-04-28 sumlib.c: drop md5 `zeroize' for performance
+ sumlib.c: add FIPS 180-1 SHA-1
+
+:::::::: libdll ::::::::
+
+11-10-11 dll_lib.c: add { dllnames() dll_lib() }
+10-10-20 dllscan.c: version arg "-" => 0
+10-10-19 dllplug.c: fix bug that wiped out dlopen() error message
+10-10-19 dllplug.c: un-localize lookup names (happens with cut and paste)
+10-10-19 dllscan.c: still no code for implicit libs missed by dlopen()
+10-08-02 dllplug.c: fix local path dllcheck() call
+10-05-28 dllplug.c: add dllplugin() with dllcheck() version check
+10-05-28 dllcheck.c: add dllcheck() to do plugin_version() checks
+10-05-28 dllerror.c: add dllerror(int retain) for dll*() and dl*() messages
+09-11-17 dllscan.c: handle name[-.]version in dlsopen()
+09-04-15 dllopen.c: add, use dllopen() internally to wrap dlopen()
+08-05-12 dllscan.c: LIBSUFFIX==.dylib => default plugin version match 0.0
+06-10-11 dllscan.c: check sfstruse() return values -- doh
+06-01-25 dllplug.c: add errorf() library message for dlopen() error
+05-02-14 dllscan.c: "" || "-" => NiL
+04-10-01 dllfind.c: drop ksh "builtin" workaround
+ dllscan.c: directory prefix in name limits search to dir and siblings
+04-07-22 dllscan.c: access() => eaccess()
+04-01-30 dllfind.c: dllplug(error_info.id) then dllplug(0)
+04-01-28 dllscan.c: update for new plugin scheme: lib/foo/bar.xxx
+ dllplug.c: add dllplug() for plugin dllfind()
+03-03-12 dllfind.c: dlopen() with RTLD_GLOBAL|RTLD_PARENT defaults
+03-02-11 dllscan.c: change LIBPATH to <dir>[:<env>[:<pat>]][,...]
+03-01-08 dllscan.c: hack version logic again -- is consistency rocket science?
+03-01-07 dlfcn.c: fix darwin.ppc dlopen/dlsym/dlclose
+02-11-18 dllfind.c: add path,size args (with backwards compatibility checks)
+02-11-15 dllfind.c: check for ./path if '.' in path but no '/'
+02-08-30 dllfind.c: fix a bug that returned uninitialized value on not found
+02-08-28 dllscan.c: handle and display bin as a sibling dir
+02-07-31 dllscan.c: add dllsopen,dllsread,dllsclose
+ dllfind.c: use dllsopen,dllsread,dllsclose
+02-07-26 dllfind.c: add dllinfo()
+02-06-27 dllnext.c: define _GNU_SOURCE to enable RTLD_NEXT
+02-03-17 dllfind.c: fix dll prefix search (for cygwin)
+02-01-11 features/dll: include <dlfcn.h> only if _hdr_dlfcn&&_lib_dlopen
+01-10-31 dlfcn.c: change hp.pa dlopen() prototype (<dlfcn.h> but no -ldl!)
+01-09-25 dllfind: add LIBSUFFIX
+01-07-17 dllfind: do at least one dlopen() to prime dlerror()
+01-05-29 dlopen: fix dlopen(0,0) for HP
+01-04-20 dllfind: use getconf HOSTTYPE LIBPATH LIBSUFFIX
+01-02-14 features/dll: fix unbalanced ' quote and ancient hostinfo reference
+00-01-26 dlllook: add -- dlsym() with `_' weak prefix fallback
+99-04-01 features/dll: drop <stdio.h> -- iffe protos printf
+99-03-19 static=1 for all but win32.*
+98-06-01 dllfind: fix version search
+98-03-11 features/dll: probe for _DLL_RLD_SYM
+98-03-01 dllnext: fix to work!
+98-01-23 -ldl test moved to lib0ast
+98-01-11 update for astconf("LIBPATH")
+ add dllnext(flags) to uncover next layer
+ dllfind() and dllnext() in separate files (for 3d)
+97-10-11 move from libast so libast can link static
diff --git a/lib/package/ast-ksh.html b/lib/package/ast-ksh.html
new file mode 100644
index 0000000..4bcc35d
--- /dev/null
+++ b/lib/package/ast-ksh.html
@@ -0,0 +1,5346 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<META name="generator" content="mm2html (AT&amp;T Research) 2012-01-11">
+<META name="description" content="ast-ksh package">
+<META name="keywords" content="software, package">
+<TITLE> ast-ksh package </TITLE>
+<META name="author" content="gsf+dgk+kpv">
+<STYLE type="text/css">
+div.FI { padding-left:2em; text-indent:0em; }
+div.HI { padding-left:4em; text-indent:-2em; }
+dt { float:left; clear:both; }
+dd { margin-left:3em; }
+</STYLE>
+</HEAD>
+<BODY bgcolor=white link=slateblue vlink=teal >
+<TABLE border=0 align=center width=96%>
+<TBODY><TR><TD valign=top align=left>
+<!--INDEX--><!--/INDEX-->
+<P>
+<P><CENTER><FONT color=red><FONT face=courier><H3><A name="ast-ksh package">ast-ksh package</A></H3></FONT></FONT></CENTER>
+The AT&amp;T Software Technology ast-ksh package from AT&amp;T Research
+contains ksh and support libraries. This is the minimal set of
+components needed to build ksh.
+Components in this package:
+<P>
+<P></P><TABLE border=0 frame=void rules=none width=100%><TBODY><TR><TD>
+<TABLE align=center bgcolor=papayawhip border=0 bordercolor=white cellpadding=2 cellspacing=2 width=99% >
+<TBODY>
+<TR><TD align=left>
+<A href="#ksh93">ksh93</A>&nbsp;&nbsp;</TD><TD align=left>&nbsp;&nbsp;libast&nbsp;&nbsp;</TD><TD align=left>&nbsp;&nbsp;libcmd&nbsp;&nbsp;</TD><TD align=left>&nbsp;&nbsp;libcoshell&nbsp;&nbsp;</TD><TD align=left>&nbsp;&nbsp;libdll&nbsp;&nbsp;</TD><TD align=left>&nbsp;&nbsp;libsum</TD></TR>
+</TBODY></TABLE></TD></TR></TBODY></TABLE>
+<P>
+This package is a superset of the following package: ksh; you won't need this if you download ast-ksh.
+The software is covered by this license:
+<UL type=square>
+<LI>
+<A href="http://www.eclipse.org/org/documents/epl-v10.html">http://www.eclipse.org/org/documents/epl-v10.html</A>
+</UL>
+Individual components may be covered by separate licenses;
+refer to the component source and/or binaries for more information.
+<P>
+A recent
+<A href="#release change log">release change log</A>
+is also included.
+<P>
+<P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="ksh93">ksh93</A></H3></FONT></FONT></CENTER>
+KSH-93 is the most recent version of the KornShell Language
+described in
+"The KornShell Command and Programming Language,"
+by Morris Bolsky and David Korn of AT&amp;T Bell Laboratories, ISBN 0-13-182700-6.
+The KornShell is a shell programming language,
+which is upward compatible with "sh" (the Bourne Shell),
+and is intended to conform to the IEEE P1003.2/ISO 9945.2 Shell and
+Utilities standard.
+KSH-93 provides an enhanced programming environment in
+addition to the major command-entry features of the BSD
+shell "csh". With KSH-93, medium-sized programming tasks can be
+performed at shell-level without a significant loss in performance.
+In addition, "sh" scripts can be run on KSH-93 without modification.
+<P>
+The code should conform to the IEEE POSIX 1003.1 standard and to the
+proposed ANSI-C standard so that it should be portable to all
+such systems. Like the previous version, KSH-88,
+it is designed to accept eight bit character sets
+transparently, thereby making it internationally compatible.
+It can support multi-byte characters sets with some characteristics
+of the character set given at run time.
+<P>
+KSH-93 provides the following features, many of which were also inherent
+in KSH-88:
+<UL type=square>
+<LI>
+Enhanced Command Re-entry Capability: The KSH-93 history
+function records commands entered at any shell level and stores
+them, up to a user-specified limit, even after you log off.
+This allows you to re-enter long commands with a few keystrokes
+- even those commands you entered yesterday.
+The history file allows for eight bit characters in
+commands and supports essentially unlimited size histories.
+<LI>
+In-line Editing: In "sh", the only way to fix mistyped
+commands is to backspace or retype the line. KSH-93 allows you
+to edit a command line using a choice of EMACS-TC or "vi"
+functions.
+You can use the in-line editors to complete filenames as
+you type them.
+You may also use this editing feature when entering
+command lines from your history file.
+A user can capture keystrokes and rebind keys to customize the
+editing interface.
+<LI>
+Extended I/O Capabilities: KSH-93 provides several I/O
+capabilities not available in "sh", including the ability to:
+<UL type=circle>
+<LI>
+specify a file descriptor for input and output
+<LI>
+start up and run co-processes
+<LI>
+produce a prompt at the terminal before a read
+<LI>
+easily format and interpret responses to a menu
+<LI>
+echo lines exactly as output without escape processing
+<LI>
+format output using printf formats.
+<LI>
+read and echo lines ending in "&#0092;".
+</UL>
+<LI>
+Improved performance: KSH-93 executes many scripts faster
+than the System V Bourne shell. A major reason for this is
+that many of the standard utilities are built-in.
+To reduce the time to initiate a command, KSH-93 allows
+commands to be added as built-ins at run time
+on systems that support dynamic loading such as System V Release 4.
+<LI>
+Arithmetic: KSH-93 allows you to do integer arithmetic in any
+base from two to sixty-four. You can also do double
+precision floating point arithmetic.
+Almost the complete set of C language operators are available
+with the same syntax and precedence.
+Arithmetic expressions can be used to as an argument expansion
+or as a separate command.
+In addition there is an arithmetic for command that works
+like the for statement in C.
+<LI>
+Arrays: KSH-93 supports both indexed and associative arrays.
+The subscript for an indexed array is an arithmetic expression,
+whereas, the subscript for an associative array is a string.
+<LI>
+Shell Functions and Aliases: Two mechanisms - functions and
+aliases - can be used to assign a user-selected identifier to
+an existing command or shell script.
+Functions allow local variables and provide scoping
+for exception handling.
+Functions can be searched for and loaded on first reference the
+way scripts are.
+<LI>
+Substring Capabilities: KSH-93 allows you to create a
+substring of any given string either by specifying the starting
+offset and length, or by stripping off leading
+or trailing substrings during parameter substitution.
+You can also specify attributes, such as upper and lower case,
+field width, and justification to shell variables.
+<LI>
+More pattern matching capabilities: KSH-93 allows you to specify
+extended regular expressions for file and string matches.
+<LI>
+KSH-93 uses a hierarchal name space for variables.
+Compound variables can be defined and variables can
+be passed by reference. In addition, each variable
+can have one or more disciplines associated with
+it to intercept assignments and references.
+<LI>
+Improved debugging: KSH-93 can generate line numbers on execution
+traces. Also, I/O redirections are now traced.
+There is a DEBUG trap that gets evaluated before each command
+so that errors can be localized.
+<LI>
+Job Control: On systems that support job control, including
+System V Release 4, KSH-93
+provides a job-control mechanism almost identical to that of
+the BSD "csh", version 4.1.
+This feature allows you
+to stop and restart programs, and to move programs between the
+foreground and the background.
+<LI>
+Added security:
+KSH-93 can execute scripts which do not have read permission
+and scripts which have the setuid and/or setgid set when
+invoked by name, rather than as an argument to the shell.
+It is possible to log or control the execution of setuid and/or
+setgid scripts.
+The noclobber option prevents you from accidentally erasing
+a file by redirecting to an existing file.
+<LI>
+KSH-93 can be extended by adding built-in commands at run time.
+In addition, KSH-93 can be used as a library that can
+be embedded into an application to allow scripting.
+</UL>
+Documentation for KSH-93 consists of an "Introduction to KSH-93",
+"Compatibility with the Bourne Shell" and a manual page and a
+README file. In addition, the "New KornShell Command and Programming
+Language," book is available from Prentice Hall.
+
+<P>
+<P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="release change log">release change log</A></H3></FONT></FONT></CENTER>
+<PRE>
+
+All recorded changes follow.
+
+</PRE>
+<P>
+<P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="ksh93 changes">ksh93 changes</A></H3></FONT></FONT></CENTER>
+<PRE>
+
+12-02-29 --- Release ksh93u+ ---
+12-02-29 A bug which could lead to a core dump when more that four shared
+ libraries were added with the builtin command has been fixed.
+12-02-29 Fixed a few bugs which caused SIGCHLD to be blocked preventing
+ background jobs from being reaped until a foreground job was run.
+12-02-27 A bug in which sh -c for a simple command caused a fork() has been
+ fixed.
+12-02-27 A timing bug on systems such as AIX that doesn't support vfork()
+ that could cause the exist status to get lost has been fixed.
+12-02-22 A private file descriptor that was not close-on-exec for a command
+ substitution and has been fixed.
+12-02-14 A bug in which ^Z did not stop a pipeline when the last component
+ was a shell built-in has been fixed.
+12-02-14 getconf("PATH") used to initialize ed(1) path.
+12-02-13 +In earlier version read from standard input would fail when called
+ from the KEYBD trap. Now read options -N, -n, and -t should work
+ when called from a KEYBD trap.
+12-02-13 If FCEDIT is not set and fc is invoked without the -e option,
+ ed will be invoked if found instead of /bin/ed.
+12-02-10 Another bug in the saving and restoring of IFS in a subshell
+ that caused a core dump has been fixed.
+12-02-08 A bug in which .sh.fun disciplines could be cleared after a
+ function completes has been fixed.
+12-02-08 A bug in job control in which the foregroup process group was not
+ set correctly after restarting a stopped pipeline has been fixed.
+12-02-07 A bug in which numbers with leading zeros could be treated as
+ octal constants outside of ((...)) has been fixed.
+12-02-06 A bug in arithmetic with compound variables containing multiple
+ array elements has been fixed.
+12-02-02 A bug in the ulimit option table was fixed.
+12-01-26 A bug in which a set command that did not change monitor could
+ effect the behavior of the monitor when monitor mode is on is fixed.
+12-01-21 +You can now test whether the shell implements a math function using
+ typeset -f .sh.math.name, where name is the name of the function.
+12-01-21 A bug in which typeset -L and typeset -R did not handle multibyte
+ characters correctly has been fixed.
+12-01-20 A bug that could cause the shell to hang waiting for an incorrect
+ job pid has been fixed.
+12-01-19 A memory leak which occured for a nested command subtiution has been
+ fixed.
+12-01-17 A bug in which typeset -u PS1 could enable the uppercase attribute
+ for some other variables, for exampe, HISTFILE has been fixed.
+12-01-16 A bug in which .sh.match was not correct after a substring match when
+ the replacement string contained a substring match has been fixed.
+12-01-12 +Files that are sourced from profile files are now read and executed
+ one command at a time so that alias definitions take effect as they
+ do for profile files.
+12-01-12 A bug in which whence -p would find a function if one existed and
+ there was no command of that name on PATH.
+12-01-11 Change b_* prototype (int, char**, void*) =&gt; (int, char**, Shbltin_t*).
+12-01-05 A bug in which read was not terminating for a signal that had a trap
+ set has been fixed.
+12-01-01 A timing problem with &gt;; has been fixed.
+12-01-01 A macro expansion memory leak has been fixed.
+11-12-26 A bug in array assignments of the form arr=( $arr&#0091;i&#0093; ...) in which
+ arr was not unset before the assignment has been fixed.
+11-12-20 A number of code changes were made based on the results of errors
+ indicated by static code analysis.
+11-12-13 In vi edit mode a lteral &lt;TAB&gt; can now be entered by preceding it
+ with a backshash.
+11-12-13 When tab is entered for completion after a ' or ", the ' and "
+ characters are no longer deleted.
+11-12-07 A bug in which a program in the current direcotry with a . in the
+ name could fail to execute when both PATH and FPATH end with :. has
+ been fixed.
+11-12-07 I fixed a bug in which a variable expansion in a large here-document
+ could be expanded to a null string.
+11-12-06 An optimization to read was added in the case the the read command
+ was redirected from a file.
+11-12-06 Changes were made to make the line limit for read unlimited by
+ default.
+11-12-05 A bug in which unsetting an array variable did not completely clear
+ the variable in some cases has been fixed.
+11-12-02 +The printf alternative character # when applied to the %q format will
+ quote argument in a form suitable for a field in a .csv format file.
+11-12-02 +A -S option was added to read to be able to read .csv format files.
+11-11-28 A bug in which redirection of standard error in a function called from
+ command substitution caused standard error to be lost has ben fixed.
+11-11-21 &#0091;&#0091; (-n foo) &#0093;&#0093; no longer requires a space before (.
+11-11-11 The readonly attribute for a variable now applies to compound
+ assignments to that variable.
+11-11-07 Changes were made to reduce the stack size to allow deeper function
+ recursion.
+11-10-10 +Added alternate flag to printf %H for encoding of URI's.
+11-10-10 A bug which could lead to a core dump when the shell was invoked
+ with more than twenty five open files has been fixed.
+11-10-06 A bug in the scoping of name references in functions called by other
+ functions has been fixed.
+11-10-05 A bug in which wait on a pid may return the exit status of an
+ earlier background job with that pid instead has been fixed.
+11-09-22 A bug in which a read timed out with TMOUT did not always restore
+ the terminal state has been fixed.
+11-09-21 An optimization that allowed the last command in a script to use
+ the same process id as the script has been eliminated.
+11-09-21 Added letoctal option that enables the let command to recognize
+ octal constants starting with 0.
+11-09-20 A bug in which ${var.} could cause a core dump has been fixed.
+11-09-20 A bug with SHOPT_EDPREDICT when neither vi or emacs was enabled for
+ lines beginning with # when in a multibyte locale has been fixed.
+11-09-20 A bug in emacs edit mode with SHOPT_EDPREDICT that would cause
+ history searches matching comments lines to generate predictions
+ has been fixed. Only user typed comment lines generate predictions.
+11-09-20 A bug in emacs edit mode with a search that matches a comment line
+ that could cause a core dump has been fixed.
+11-09-16 A bug in which a command name ending in .. could cause the shell to
+ abort has been fixed.
+11-09-16 The characters ! + - % and @ in file names are no longer escaped with
+ file name completion.
+11-09-13 The let command no longer treats numbers starting with 0 as octal
+ constants.
+11-09-08 A bug in which printf "%R" could cause a core dump for invalid shell
+ patterns has been fixed.
+11-08-09 With set -u, ${var#pattern} reported that var was unset for special
+ variables.
+11-08-03 A bug in which the shell did not preserve the exit status for a
+ coprocess has been fixed.
+11-08-02 A bug in the saving and restoring of IFS in command substitution that
+ caused a core dump has been fixed.
+11-07-21 Modified the 10-08-27 bug fix so that background jobs started in for
+ and while loops created interactively generate completion messages.
+11-07-20 I fixed a bug in here documents in which multi-byte characters that
+ crossed buffer boundaries were not processed correctly.
+11-06-22 The shell compiler now supports process substitution.
+11-06-22 +Added code to support process substitution on systems that do
+ not supply the /dev/fd directory.
+11-06-21 Fixed extraneous jobs Done messages when builtin is at the end of a
+ pipeline.
+11-06-20 Fixed two regression tests.
+11-06-20 Fixed a bug introduced on last update.
+11-06-14 A bug with pipefail in which the shell would wait for background
+ jobs to complete has been fixed.
+11-06-09 A bug which caused the options.sh regression test to fail on OS390
+ Linux has been fixed. The bug could also have affected other systems.
+11-06-07 +A number of changes to support the still undocuments namespace option
+ have been added.
+11-06-06 A bug in which command substitution of eval would hang when it had
+ standard error redirected to standard output has been fixed.
+11-06-01 A bug in case statement fall through (;&amp;) ignoring set -e was fixed.
+11-06-01 A bug in which creating a left or right justified upper or lowercase
+ variable with an empty string has been fixed.
+11-06-01 A bug in which the .paths directory wasn't read when a subshell was
+ executed before any other command has been fixed.
+11-05-31 The shell now gives an error when a type variable is assigned to
+ an array instance when the array has been declared a compound variable
+ array.
+11-05-31 A bug in which typeset -m of an array instance did not remove the
+ original instance has been fixed.
+11-05-28 A bug in which typeset -m dest=src fails when src and are passed as
+ name references was fixed.
+11-05-28 A bug in which typeset -m "c.board&#0091;1&#0093;&#0091;i&#0093;=el", where el is a compound
+ variable core dumps has been fixed.
+11-05-28 Two bugs in the display of arrays of compound variables with print -v
+ have been fixed.
+11-05-27 A bug with command substitution with the shift jis locale has been
+ fixed.
+11-05-25 A bug in which unset -f foo, called within function foo could cause
+ the shell to core dump has been fixed.
+11-05-24 A bug in unsetting arrays of compound variables that could lead to
+ a core dump has been fixed.
+11-05-24 A scoping bug in with typeset -m for variables passed as references
+ has been fixed.
+11-05-09 A bug in which 'typeset +p array&#0091;$i&#0093;' in a subshell could cause an
+ exception has been fixed.
+11-05-03 Two more scoping bugs with name references and read -C were fixed.
+11-05-03 A potential race condition which occurs when here-documents are
+ processed in asynchronous blocks has been eliminated.
+11-05-02 Another scoping bug with name references defined in a function has
+ been fixed.
+11-05-02 A bug in which the shell discards saved exit status of a job if it is
+ followed by a subshell execution has been fixed.
+11-04-28 The shell now checks for numerical overflows with process ids.
+11-04-28 Another scoping bug with compound variables defined by name references
+ inside a function has been fixed.
+11-04-28 A bug which caused a core dump on 32 bit systems with the basic.sh
+ regression test has been fixed.
+11-04-27 A scope binding error for name references has been fixed.
+11-04-27 Assignment of compound variable to compound array element by name
+ is now working.
+11-04-26 I fixed a bug with SHOPT_FIXEDARRAY compilation that could cause
+ an a core dump for not fixed arrays.
+11-04-25 A bug in the references to two dimensional compound arrays has
+ been fixed.
+11-04-20 A bug in which a name reference to a multidimentional index array
+ index, nameref x=foo&#0091;3&#0093;&#0091;4&#0093;, did not work correctly has been fixed.
+11-04-18 Changes were added to allow fixed size arrays of variable sized
+ objects when the SHOPT_FIXEDARRAY compile option defined on 10-09-28.
+11-04-18 A bug in which name references to array elements could fail has
+ been fixed.
+11-04-15 +A compile option, SHOPT_2DMATCH, has been added which causes
+ .sh.match to be a two dimensional array after ${var//pat/str}
+ where the first dimension is the pattern number and the second is
+ the match instance.
+11-04-11 A bug in which readonly var, where var is exported could cause var
+ to be unset has been fixed.
+11-04-06 A tokenizer bug in which ${x/{3}(\d)/ } would cause in infinite
+ loop has been fixed.
+11-04-05 A bug in which ${!x.} could cause a core dump has been fixed.
+11-04-04 A bug in which cleaning out the history file could terminate before
+ keeping all the recent history events has been fixed.
+11-03-29 A bug in which ${#array&#0091;@&#0093;} was 1 rather than 0 after issuing
+ typeset array&#0091;7&#0093; has been fixed.
+11-03-29 The subscript out or range message for fixed arrays has been fixed.
+11-03-29 A bug in which suspend could cause a core dump has been fixed.
+11-03-24 For the showme option added 09-09-09, commands beginning with a ;
+ inside an arithmetic for loop, no longer produce syntax errors.
+11-03-18 A bug in _WINIX ~domain/user expansion has been fixed.
+11-03-16 A bug in the pipefail option which could cause a script to hang
+ has been fixed.
+11-03-12 The shell no longer treats ${##pattern} as a syntax error.
+11-03-11 A bug in typeset -u on systems that don't supply the towctrans()
+ function has been fixed.
+11-03-11 A bug in which a compound assignment of the form var&#0091;sub&#0093;=(...)
+ would evaluate sub for each assignment has been fixed.
+11-03-07 A bug in which reassigning a compound variable to an associative
+ array index could incorrectly increase the count of the number
+ of elements has been fixed.
+11-03-04 +The tilde expansion on windows has been modified to handle user
+ names of the form domain/user so that ~domain/user now expands
+ to the home directory of that domain user.
+11-03-03 A bug in which the width of the prompt was calculated incorectly
+ which cause the wrong line length for edit commands has been fixed.
+11-03-02 A bug in which a global variables set from within a function inside
+ a subshell can leave side effects in parent shell has been fixed.
+11-03-01 A bug in which whence -a could dump core when the first match
+ was due to : in PATH and the program was in the current directory.
+11-02-28 A bug in emacs mode with SHOPT_EDPREDICT (added on 10-05-20) which
+ disabled prediction on a line starting with # when the cursor was not
+ at the end of line has been fixed.
+11-02-28 The output format for compound variables with set has been fixed.
+11-02-25 A bug which could lead to a core dump occurred when a shell script
+ without #! is invoked by name from a parent shell that has name
+ references defined and the script creates name references of the
+ same name.
+11-02-21 The shell now fails with a syntax error when a here-document in a
+ command substition is not completed before the closing ), for
+ example, $( foobar &lt;&lt;! )
+ here_doc
+ !.
+11-02-18 A bug in which the value of $0 in a function defined by name()
+ was changed to name has been fixed.
+11-02-17 A bug in which the declaration typeset var&#0091;100&#0093; did not work
+ correctly has been fixed.
+11-02-15 A bug in which &#0091;&#0091; -v sh.match &#0093;&#0093; did not work correctly has been
+ fixed.
+
+11-02-08 --- Release ksh93u ---
+11-02-08 A bug in which opening standard output after it has been closed with
+ exec 1&gt;&amp;- doesn't work has been fixed.
+11-02-07 A bug on some systems for which a command subtitution could hang
+ has been fixed.
+11-01-28 A bug in file name completion for files containing both multibyte
+ characters shell special characters has been fixed.
+11-01-18 The .sh.match variable now shows elements that do not match as
+ as not set rather than an empty string.
+11-01-18 A bug with typeset -m of an array into an element of an indexed
+ array has been fixed.
+11-01-13 A bug in handling of arrays of compound variables inside ((...)) which
+ reported a syntax error been fixed.
+11-01-10 A bug in arithmetic assignment operators of the form op= for array
+ variables when the same array was referenced on the left and the
+ right hand side with different indices has been fixed.
+11-01-10 A bug in which the output of time was lost when { time...;} 2&gt;&amp;1
+ occurred inside command substition has been fixed.
+11-01-07 &#0091;&#0091; -v sh.match&#0091;i&#0093; &#0093;&#0093; was returning false when sh.match&#0091;i&#0093; was set.
+11-01-05 Added and modified warning messages with sh -n.
+11-01-02 Fixed bugs with typeset -l/-u/-M and arrays.
+10-12-28 Fixed a bug with typeset -l/-u/-M values in arithmetic expressions.
+10-12-26 Fixed a time parsing bug in sleep and localeconv() initialization.
+10-12-23 Prevented the shell from generating a core dump when it sends itself
+ a termination signal because the last command terminated with that
+ signal. This prevents a core dump to be overwritten by the shell.
+10-12-22 A bug in the expansion of ${A&#0091;@&#0093;} ${B&#0091;@&#0093;}, introduced in 10-12-01
+ when A="" B=B has been fixed.
+10-12-21 +Use MS_3D in b_vpath() for setting win32 WoW mount defaults.
+10-12-17 A bug in the expansion of ${var:i:j} which caused a core dump when
+ i &gt; ${#var} has been fixed.
+10-12-16 +sleep now treats . as decimal point even in locales that use comma.
+10-12-16 +typeset -M mapname was added to generalize on toupper and tolowwer
+ mapping as provided with wctrans().
+10-12-10 A bug in which typeset -l displayed namespaces as well as lower case
+ variables has been fixed.
+10-12-06 A bug in which a pipeline could terminate prematurely for a pipeline
+ whose right hand side is a builtin, and whose left hand side ends in
+ a simple command that has standard output redirected has been fixed.
+10-12-06 A bug in hexfloat assignments when the right hand side is a string
+ variable starting with 0x has been fixed.
+10-12-01 A bug in the expansion of ${$1+"$@"} which causes the last positional
+ parameter to disappear when it is empty has been fixed.
+10-12-01 A number of changes were made to reduce the startup time.
+10-11-29 When wait is interrupted by a signal that is caught, it now exits
+ with a non-zero exit status.
+10-11-29 When a variable is used directly in an arithmetic expression,
+ leading zeros no longer cause the value to be treated as an
+ octal constant. This was true in previous versions for justified
+ variables.
+10-11-29 An incorrect warning message was eliminated with the -n option for
+ arithmetic expressions with associative arrays.
+10-11-29 Some changes were made to slightly reduces startup time.
+10-11-24 A bug in which a name reference is make to arr&#0091;0&#0093; when arr is not
+ an array has been fixed.
+10-11-23 If a type definition is made without a compound variable assignment it
+ produces an error message and no longer shows up as a defined type.
+10-11-22 The handling of &nbsp;inside &#0091;...&#0093; for for shell and ~(E) patterns has
+ been fixed.
+10-11-22 A patch was made to pfsh to handle an error case.
+10-11-22 +Modified types defined in namespace so that they do not clash with
+ types in other namespaces. Types can be referenced using
+ .namespace.typename.
+10-11-22 A bug which caused functions addressed as .namespace.funct to not
+ work has been fixed.
+10-11-22 A bug in which if nr was a name reference to an unset associative
+ array subscript, then ${!nr} did not output the subscript correctly
+ has been fixed.
+10-11-18 A bug in which shcomp -n was not processing double quotes correctly
+ has been fixed.
+10-11-18 Fixed a bug in which typeset -T foo; typeset -T could cause a
+ core dump.
+10-11-17 Fixed a bug in which the error message for set -u could come out
+ garbelled.
+10-11-17 Modified the parser so that typeset -a var=(...) no longer checks
+ the first index for aliases and reserved words.
+10-11-17 A bug in which a subshell command consisted of only a for or until
+ command has been fixed.
+10-11-16 Fixed a bug in which typeset -u would display namespace variables
+ as well as upper case variables.
+10-11-16 A bug which could cause a core dump when unsetting a type variable
+ when there are references to type elements has been fixed.
+10-11-15 A bug which could cause a core dump when unsetting a compound
+ array variable when there are references to array subscripts has
+ been fixed.
+10-11-15 A bug in which using typeset -m to move an indexed array instance
+ to another array could cause the array to display incorrectly has
+ been fixed.
+10-11-12 A bug in which the unset discipline function for a type is called
+ when the type is initialized has been fixed.
+10-11-12 The sequences \&lt; and \&gt; are now preserved after patterns containing
+ ~(E) in ${var/pattern/string} expansions.
+10-11-11 A bug in typeset -m when the variables were compound arrary instances
+ has been fixed.
+10-11-10 A bug in output of a compound variable with types containing types
+ has been fixed.
+10-11-10 Fixed ``name=value export &#0091;-p&#0093;'' to list environment.
+10-11-09 shtests resets SIGPIPE to SIG_DFL for all tests.
+10-11-09 Fixed a bug in expansion of $"..." when used in assignments.
+10-11-09 Fixed a getaddrinfo() memory leak that didn't call freeaddrinfo()
+ after an interrupt.
+10-11-08 Modified the behavior of set -u so that the shell terminates with
+ error message when when var is unset with ${!var} and ${#var}.
+10-11-02 Fix a bug in which a signal received while in a subshell could be
+ ignored.
+10-10-26 Fix a bug where terminal interrupt was ignored while in vi/emacs
+ edit search mode.
+10-10-26 Fix $'a&nbsp;b'c to expand to 'ac'.
+10-10-26 Provide user defined round() if not in &lt;math.h&gt;.
+10-10-26 Fix bug where $((undefined_function(1))) dumped core.
+10-10-22 Provide user defined iszero() if not in &lt;math.h&gt;.
+10-10-22 Fixed a bug with BGX compile option that could cause the shell to
+ hang.
+10-10-22 Fixed a bug with user define math function on systems for which
+ char is unsigned.
+10-10-21 A bug in which function autoloaded in a function leaves a file open
+ has been fixed.
+10-10-20 Modified the behavior of set -u so that the shell terminates when
+ when var is unset with ${var op string} when op is #, % or /.
+10-10-20 Fixed a bug with the AUDIT option in which the audit file was not
+ not close-on-exec.
+10-10-20 +Made a number of changes and fixes for the NAMESPACE compile option
+ which as added on 10-06-09 but some problems still remain.
+10-10-15 Fixed a bug in which arithmetic functions (added on 10-03-24) did
+ not work when the function definition was in the same compound
+ command in which the function was referenced.
+10-10-13 A bug in which creating an associative array of compound variables
+ with no members as an element of a compound variable did not work
+ has been fixed.
+10-10-08 A bug in which killing the last command in a function defined
+ with function name, terminated the calling script has been fixed.
+10-10-08 A bug which could cause a core dump if IFS is unset inside a function
+ has been fixed.
+10-10-07 +To reduce unwanted side effects, invoking typeset without the export
+ option and without an assignment now causes the variables to be unset
+ if the variable is inherited from the environment.
+10-10-06 The closing brace for ${ command } is now a token no matter what
+ character follows it.
+10-10-04 The change for $'...' expansion on 10-08-09 did not expand parameters
+ contained in the error message and this has been fixed.
+10-10-04 A bug in which a declaration of indexed array (-a_ in a type
+ definition would be displayed as a compound indexed array (-C -a)
+ has been fixed.
+10-09-30 The C99 math function ldexp has been added.
+10-09-30 A bug with two dimensional arrays with expansion of the form
+ ${ref&#0091;0..5&#0093;} where ref is a nameref to array&#0091;i&#0093; has been fixed.
+10-09-29 A bug in which an eval with redirections invoked from a dot script
+ would not restore the file has been fixed.
+10-09-29 A bug in which loading a function from FPATH could leave a file
+ descriptor open has been fixed.
+10-09-28 +A new compile option SHOPT_FIXEDARRAY has been added and is being
+ evaluation. It allows fixed sized indexed arrays be to defined
+ using "typeset array&#0091;dim1&#0093;&#0091;dim2&#0093;...&#0091;dimn&#0093;". Fixed sized arrays
+ are used the same way indexed arrays are. Currently, only fixed
+ arrays of fixed objects (float, int, and justifies objects) are
+ supported.
+10-09-22 A bug which could cause an exception when a function with static
+ variables was redefined has been fixed.
+10-09-21 A bug in the processing of (command&amp;) which created a job in the
+ parent process has been fixed.
+10-09-21 A for loop optimization bug with arithmetic expression evaluation
+ has been fixed.
+10-09-21 A bug in which a recursive function containing a pipeline could
+ lead to an exception fixed after 8 levels of recursion has been
+ fixed.
+10-09-18 A bug in which the count of elements in an array was wrong leading
+ to an exception has been fixed.
+10-09-13 A bug which occurred when both xtrace and showme options where
+ specified in which the xtrace option disabled showme has been fixed.
+10-09-13 A bug in which creating a reference to an array variable with any
+ elements could cause subsequent array elements to be treated as
+ compound variables has been fixed.
+10-09-09 A bug which caused ((c.ar&#0091;x&#0093;&#0091;y&#0093;)) to be treated as a syntax error
+ has been fixed.
+10-09-08 A bug in the processing of references to multidimensional arrays
+ in arithmetic expressions has been fixed.
+10-09-08 A bug in the handling of multi-dimensional arrays which caused
+ the number of elements in each dimension to be incorrect has
+ been fixed.
+10-09-07 The change for messages on 10-08-09 did not handle message in
+ assignments and this has been fixed.
+10-09-07 A bug in the indentation of compound variables in arrays when
+ output with print -v has been fixed.
+10-09-07 A rare bug with indexed arrays when assigned a null string that could
+ cause a core dump has been fixed.
+10-09-03 A number of changes were made for jobs pools.
+10-08-31 typeset -p was modified to output name references after other
+ variables so that the output could be used as input.
+10-08-31 A bug with typeset -p in which variables with attributes but
+ without attributes were not displayed correctly has been fixed.
+10-08-27 +When running a subshell, the current pool is unset.
+10-08-27 A bug in which jobs started from within for or while lists in
+ interactive shells could generate completion messages has been fixed.
+10-08-25 Fixed a couple of bugs related to job pools.
+10-08-24 +&#0091;&#0091; -e /dev/xxx/ &#0093;&#0093; can be used to check whether special files of
+ those names are handled by the shell.
+10-08-24 A bug in the running of a compiled dot script in which only the
+ first command was executed has been fixed.
+10-08-23 A bug which sometimes caused a core dump with a configure script
+ has been fixed.
+10-08-20 A bug in command substitution which caused a configure script to
+ hang has been fixed.
+10-08-19 Eliminated unnecessary ; from output of compound variable with
+ typeset -p.
+10-08-17 Fixed a bug in command substitution in which under certain
+ circumstances a file whose size is a power of 2 plus one, and the last
+ character was not a new-line, could cause memory corruption.
+10-08-13 +Added static discipline functions to type similar to C++ static
+ class functions.
+10-08-11 A bug in time when applied to a pipeline in which the shell did
+ not wait for all elements of the pipeline to complete has been fixed.
+10-08-11 Restored sh_fmtq() quoting to not quote NAME= in NAME=VALUE.
+10-08-09 +Modified the expansion of message strings, $"...", so that they
+ are expanded each time they are referenced rather than expanding
+ them when the script is compiled or read in.
+10-08-06 +The process id for jobs in job pools is now of the form poolname.n
+ where n is the jobid in that pool. Commands that accept job names
+ or numbers now understand names in this format.
+10-08-05 A bug in which an assignment from within an arithmetic expression
+ inside a function would create a local variable has been fixed.
+10-08-04 A bug in the expanding of variables whose names contain multibyte
+ characters has been fixed.
+10-08-04 A bug which caused an exception when processing scripts compiled
+ with shcomp -n has been fixed.
+10-08-02 Tests using very small buffer sizes uncovered a number of bug most
+ connected with here documents which have been fixed.
+10-07-27 The format modifier , used for digit grouping with d and f formats
+ has been documented.
+10-07-26 cd '' now produces and error rather than changing to the current
+ directory.
+10-07-26 A bug in multi-byte locales which the last character of a
+ multi-byte character is a &nbsp;or pattern character which could occur
+ when the character was the last character of a command substitution
+ has been fixed.
+10-07-23 Another bug in the processing of ${var:offset;len} in multi-byte
+ locales when len is larger than the number of characters has been
+ fixed.
+10-07-23 Many coding changes have been made to eliminate most of the uses
+ of global variables in the shell code.
+10-07-22 Fixed a bug in which discipline functions were not being invoked
+ when it was invoked as ref.discipline where ref was a name reference
+ to an array instance.
+10-07-22 Fixed a bug in which discipline functions were not being invoked it
+ was invoked on a two dimensional array, i.e., arr&#0091;5&#0093;&#0091;9&#0093;.discipline.
+10-07-19 Fixed a buffering problem which occurred when running a script with
+ ssh and the parent ssh process is killed.
+10-07-14 Modified the parser to treat ((...)) inside &#0091;&#0091;...&#0093;&#0093; as ( (...) ) to
+ that it is a nested (...).
+10-07-09 A bug in the handling of process substitution inside command
+ substitution as part of a pipeline has been fixed.
+10-07-07 A bug in the output for compound variables containing
+ multi-dimensional arrays has been fixed.
+10-07-06 ksh now recovers from changes made by bash to the history file without
+ loosing history commands.
+10-06-25 A bug in which a large here document containing command substitutions
+ of a dynamically loaded function that contained a here document
+ could get truncated has been fixed.
+10-06-24 If after executing a script found in FPATH, if a function, builtin,
+ or type name corresponding to that script is not defined, the shell
+ now outputs an error message and returns value 126.
+10-06-23 Floating point functions that happened to return integer values
+ were being treated as if the function returned integers so that
+ integer division could be used instead of floating point division.
+10-06-22 Fixed a bug in earlier ksh93u in which an arithmetic assignment to a
+ variable in the global scope would instead create a local variable if
+ the variable had an attribute but did not have a value.
+10-06-18 Modified trap handling so that if the same signal is received when
+ executing the handler, it is deferred until the handler completes.
+10-06-16 Fixed a bug in which ulimit -v was setting the the cpu limit
+ on Linux.
+10-06-14 +The command 'typeset -T' now generates the list of type definitions
+ in a format that can be used as input to the shell.
+10-06-09 Put in patch from Solaris for output quoting with %q.
+10-06-09 +Made changes to the NAMESPACE compile option so that it now seems
+ to work. With this option, namespace &lt;name&gt; { command;} will
+ run command in the namespace .name so that all variables and
+ functions created by command are accessible outside the name
+ space via .name.var and .name.fun. Variables and functions that
+ are not in the namespace are not modified when running command.
+10-06-07 Change most internal interfaces to take Sh_t* argument.
+10-06-03 +Types can be loaded on first reference by putting definitions in
+ PFPATH.
+10-06-03 +The shell is now able to parse commands which use type statements
+ before the typeset -T command to define the type executes.
+10-06-03 A bug in the quoting for name reference declarations which did
+ not properly handle &#0091; and &#0093; in subscripts for associative arrays.
+10-06-02 A bug in which a discipline function defined by a type instance to
+ override the default was not being registered has been fixed.
+10-06-02 A bug in which read -C of an associative array of compound variables
+ was not working has been fixed.
+10-06-02 A bug in which the error message for an unset parameter with set -u
+ did not contain the name of the variable has been fixed.
+10-06-01 A bug in typeset -m for moving an indexed array instance to a variable
+ has been fixed.
+10-06-01 A bug in which caused memory to be freed twice when unset was called
+ for an indexed array that had get or set disciplines has been fixed.
+10-06-01 A bug in which the %b format of printf was not preserving NUL bytes
+ with &nbsp; has been fixed.
+10-06-01 A bug in the handling of name references to array variables in
+ arithmetic expressions has been fixed.
+10-05-28 Fixed bugs in changing attributes for two dimensional arrays.
+10-05-28 Eliminated a few unreferenced variables and a reference to
+ uninitialized memory.
+10-05-27 Rewrote the subshell code to avoid using pipes an many cases.
+10-05-24 Fixed a bug which cause an exception when both -l and -s were
+ specified with typeset -i.
+10-05-21 Inputting of three dimensional indexed arrays with ( ( (...)...)...)
+ was not working and has been fixed.
+10-05-21 A bug in which adding the attributes -Ai to a variable via a name
+ reference could cause the value to display incorrectly has been fixed.
+10-05-21 A bug in which using $var inside ((...)) did not work when var was
+ a hex float variable.
+10-05-20 +The compile option SHOPT_EDPREDICT has been added. When this option
+ is on, as you type a line beginning with a # the following characters
+ are treated as a shell pattern and cause matching lines from the
+ history file to be displayed as a numbered list as you type.
+ You can scroll up and down this list or you can use &lt;ESC&gt;nTAB
+ to make this the current line (n defaults to 1 of omitted) or
+ &lt;ESC&gt;n&lt;cr&gt; to execute.
+10-05-20 A bug which caused an exception when multiple levels of composite
+ functions in arithemtic expressions has been fixed.
+10-05-19 &lt;&lt;&lt; with an empty string no longer gives an error.
+10-05-19 A bug in arithmetic evaluation when a name reference to an array
+ instance was used has been fixed.
+10-05-14 A bug in which the shell treats a valid index array assignment,
+ typeset -a x=(foo (x=3;y=4) bar) as a syntax error has been fixed.
+10-05-13 A bug in creating name references to associative array variable
+ after a lookup of one of its elements has been fixed.
+10-05-12 Two bugs in the handling of function static type variables in
+ subshells have been fixed. One could cause an exception and the
+ other would leave side effects in the parent shell.
+10-05-10 A bug in which static variables in functions were not being saved and
+ restored properly when running subshells has been fixed.
+10-05-05 A bug in which print -v did not work correctly when an operand was an
+ indexed array element referring to a compound variable has been fixed.
+10-05-05 A change to improve performance by special casing empty string
+ assignments to avoid repeated malloc() and free().
+10-05-05 A bug in which creating a name reference to a non-existent associative
+ array element would create the array element has been fixed.
+10-05-04 A bug in which name references to static variables in the static
+ scope were not found has been fixed.
+10-04-30 Do not use socketpair() on systems that implement ioctl(I_PEEK)
+ on pipes.
+10-04-29 +When the current job pool is set, coprocess are run in a job pool.
+10-04-28 A type defined with a member foo that is an associative array without
+ elements followed by an expansion ${bar.foo&#0091;a&#0093;} and an assignment
+ bar.foo&#0091;a&#0093;=b, no longer indicates that ${#bar.foo&#0091;@&#0093;} has 0 members.
+10-04-27 Another bug in which a nested command substitution could hang if it
+ generated too much data has been fixed.
+10-04-26 A type defined with a member that is an indexed array without elements
+ would behave as if the 0th element of each instance was defined after
+ a non-zero element was specified and this has been fixed.
+10-04-26 A bug in which types defined in a subshell were not undefined when
+ the subshell completed has been fixed.
+10-04-23 For file completion in commmand line editing, file names starting
+ with # are now escaped so that they are not treated as comments.
+10-04-23 A bug in which ${t.var:=value}, where t is an instance of a type
+ variable, could assign value to the type variable rather than to
+ the type instance has been fixed.
+10-04-23 +Added &amp;| which can be used in place of | to have portions of a
+ pipeline executed in the pool.
+10-04-22 +The .sh.pool variable was added for use with job pools.
+10-04-22 A bug in which a nested command substitution could hang if it
+ generated too much data has been fixed.
+10-04-20 A bug which corrupted one byte of memory when read was called with
+ reads that did not use a delimiter has been fixed.
+10-04-19 The display of a compound variable with an embedded array with
+ attributes was sometimes not working correctly and has been fixed.
+10-04-16 A bug in which attributes were not be propagated to elements in
+ an associative array has been fixed.
+10-04-15 A bug which caused scripts containing user defined math functions to
+ fail to compile with shcomp has been fixed.
+10-04-15 +Job pools have been added with the SHOPT_COSHELL compilation option.
+ A job pool allows a collection of background jobs to run either locally
+ or remotely and to be managed as a unit. The command '&amp; name ...'
+ creates or uses a named job pool for subsequent background jobs.
+ kill, wait, and jobs allow the pool name as operands.
+10-04-14 A bug in which a coprocess connection could terminate prematurely
+ when running a nested subshell has been fixed.
+10-04-12 +Enumeration constants can be used in arithmetic expressions with the
+ ==, != and = operators when the left hand side is an enum variable
+ and the right hand side is an enumeration constant.
+10-04-07 A bug in which setting the trap on CHLD to ignore could cause
+ an incorrect exit status has been fixed.
+10-04-06 A bug in which LINENO was not incremented for a here-document when
+ the here-document word was followed by a comment has been fixed.
+10-04-06 The optimization that execs the last process of a script rather
+ than creating a new process has been removed when a trap on
+ interrupt has been set.
+10-04-06 Unsetting the 'C', 'A' or 'a' typeset attribute now produces an
+ error message rather than generating an exception.
+10-04-06 A bug in which .sh.name contained the subscript and .sh.subscript
+ was empty in some cases with discipline functions on array instances
+ has been fixed.
+10-04-05 A bug in the edit modes where preceding the interrupt character with
+ the literal next character did not work has been fixed.
+10-04-05 A bug in the creation of type instances of arrays which could cause
+ an exception has been fixed.
+10-03-30 A bug in the display of a compound variable containing an indexed
+ array of compound variables has been fixed.
+10-03-24 +Arithmetic functions can be defined using the shell function syntax,
+ 'function .sh.math.name x y z{...}' , where name is the function name
+ invoked within ((...)) and x y z are long double arguments passed
+ as name references. y and z are used for functions with two and
+ three arguments respectively. The value of the function is the value
+ of the long double .sh.value variable when the function returns.
+10-03-24 A bug in which integer division was mistakenly used when the
+ numerator was a binary operator with the first operand floating
+ point and the second integer, e.g. (.1**3)/3, has been fixed.
+10-03-24 The &gt;; file operator was modified so that the temporary file is
+ created in the same physical directory as file.
+10-03-23 A warning message was added to sh -n when $var was used inside
+ ((...)) instead of var.
+10-03-19 fmin was added to the list of math function on the man page.
+10-03-19 Fixed the return value for unalias when the alias did not
+ exist.
+10-03-19 A bug in which the SHLVL variable exported the value it had on
+ input rather than the incremented value has been fixed.
+10-03-19 A bug which causes whence -q to go into an infinite loop has been
+ fixed.
+10-03-19 Removed space between Stopped message and (SIGTTIN) and (SIGTTOUT).
+10-03-17 Modified profile shell execution so that when builtins that
+ correspond to executable have extended attributes, they are
+ executed by pfksh instead of being treated as built-ins.
+10-03-16 A bug in whence -a which produced duplicate lines of output has
+ been fixed.
+10-03-16 A bug in the handling of process groups in monitor mode for
+ command substitutions has been fixed.
+10-03-15 Fixed a bug in which read -u&#0091;fd&#0093; could cause the shell to core
+ dump when fd was greater than open_max.
+10-03-15 +Modified the shell I/O so that the shell will not fail if the
+ ulimit for open_max is increased as part of the script.
+10-03-12 A bug in which a here-document containing command substitutions
+ that contained here-documents did not process correctly has been
+ fixed.
+10-03-12 A bug in which the terminal is not restored to canonical mode
+ after read times out when in a multibyte locale with no edit mode
+ enabled has been fixed.
+
+10-03-05 --- Release ksh93t+ ---
+10-03-05 A variable unset memory leak has been fixed and tests/leaks.sh
+ has been added to verify the fix.
+10-03-04 Documentation, comment, and diagnostic spelling typos corrected.
+10-02-14 Fix sh_getenv() initialization to cooperate with the 3d fs.
+10-02-12 A bug in which the get discipline function was not invoked for
+ associative array subscripts for unset array elements has been fixed.
+10-02-12 A bug which could occur if the last line of a script was an eval
+ that executed multiple commands has been fixed.
+10-02-02 A buffer overflow in read and another in binary type base64
+ encoding were fixed.
+10-01-20 A bug in the evaluation of arithmetic expression in which the
+ subscript was evaluated twice for $((foo&#0091;x++&#0093;++)) has been fixed.
+10-01-19 A workaround for a double-free of a trap in both a subshell and its
+ parent has been added.
+10-01-18 A bug in type handling of typeset -H has been fixed.
+10-01-15 The "adding empty subscript" warning now only emitted with -x set.
+10-01-01 A bug in the parser in which '$((case i in i):;esac);:))' was not
+ parsed correctly was fixed.
+10-01-01 A bug in the parser in which '$(( 2 , 3.6 ))' dumped core for locales
+ with radix char , and thousands separator . has been fixed.
+09-12-28 A bug in the handling of SIGCLD on systems that generated SIGCLD
+ while blocked waiting for process to complete has been fixed.
+09-12-24 ast setlocale() reworked to differentiate env var changes from user
+ override.
+09-12-18 A bug with the SHOPT_BGX option set which disabled traps for signals
+ &lt; SIGCHLD when a trap for a signal &gt; SIGCHLD was set has been fixed.
+09-12-18 A bug where &#0091;&#0091; -v var &#0093;&#0093; was incorrect for some variables (including
+ LC_* vars) has been fixed.
+09-12-15 A bug that produced a syntax error when a multibyte character
+ straddled a buffer boundary has been fixed.
+09-12-11 A bug where the subscript of an unset variable was not evaluated has
+ been fixed.
+09-12-09 A bug where shcomp dumped core on certain syntax errors has been fixed.
+09-12-07 A bug where a parent shell environment var reset in a subshell removed
+ the value in subsequent children of the parent shell has been fixed.
+09-12-04 A bug in which in some cases a trap in a function executed in
+ a subshell could trigger twice has been fixed.
+09-12-03 A bug in which SHLVL exported with some attributes could cause
+ the shell to abort at startup has been fixed.
+09-12-02 A bug with pipefail in which the shell could hang waiting for the
+ writer to complete before the last reader command has been fixed.
+09-11-30 A bug in which a trap could be inherited by the first element of
+ a pipeline when the command had more than 63 arguments that did
+ not contain any macro expansions has been fixed.
+09-11-19 When read from a terminal was called from with a while or for loop,
+ and an edit mode was on, a backspace or erase no longer will
+ overwrite the prompt.
+09-11-17 +Change .paths parse to handle BUILTIN_LIB=foo BUILTIN_LIB=foo-1.2.
+09-11-17 Inside a function, typeset foo.bar will bind foo to global variable
+ foo if local variable foo does not exist, instead of creating a
+ local variable.
+09-11-17 "read -n1" from the terminal has been fixed to read exactly one character.
+09-11-11 Job control now works for subshell commands, (...).
+09-11-11 If set -e is on for an interactive shell errors in special builtins
+ now cause the shell to exit.
+09-11-11 A bug in which an interrupt handler processed during the read builtin
+ when IFS did not contain a new line has been fixed.
+09-11-09 A bug in which a variable that has been unset in a subshell and then
+ exported from that subshell does not show up in the environment
+ has been fixed.
+09-11-02 ``,2'' is now a valid numeric constant for locales with
+ decimal_point=','.
+09-11-02 A bug where "return" in .profile did not restore the shell state
+ has been fixed.
+09-10-31 A bug that corrupted saved exit status when pids wrapped around has
+ been fixed.
+09-10-26 A bug in { LANG LC_ALL LC_category } ordering has been fixed in -last.
+09-10-16 A bug where notification to libast that the environment has changed
+ has been fixed.
+09-10-12 A bug in which a function loaded in a subshell could leave side
+ effects in the parent shell has been fixed.
+09-10-12 A bug in converting a printf %d operand to a number when the operand
+ contains multiple subscripts for the same variable has been fixed.
+09-10-09 A bug in the handling of the escape character &nbsp;in directory prefixes
+ in command completion has been fixed.
+09-10-09 $PATH processing has been changed to delay dir stat() and .paths
+ lookup until the directory is needed in the path search.
+09-09-28 Call the ast setlocale() intercept on unset too.
+09-09-24 A bug in which LANG=foo; LC_ALL=foo; unset LC_ALL; did not revert
+ LC_CTYPE etc. to the LANG value has been fixed.
+09-09-17 A bug in which unsetting SVLVL could cause a script invoked by
+ name without #! to core dump has been fixed.
+09-09-16 A bug in which a pipeline in a here-document could hang when the
+ pipefail option was on has been fixed.
+09-09-09 A bug in the processing of line joining in here documents which
+ occurred when a buffer began with &lt;escape&gt;&lt;new-line&gt; has been fixed.
+09-09-09 +A leading ; with commands in a brace group or parenthesis group
+ no longer causes an error. It now is used for the "showme" option.
+09-09-09 A bug in which a subshell containing a background process could
+ block until the background process completed has been fixed.
+09-09-04 A bug in handing ${var&#0091;sub&#0093;}, where var is a nameref has been fixed.
+09-09-03 A bug which caused an index array to have the wrong number of elements
+ when it was converted from a compound variable by adding an another
+ element has been fixed.
+09-09-03 Specifying export for a compound variable now generates an error.
+09-09-02 $"..." localizations strings are no longer recognized inside `...`.
+09-09-01 A bug in the for loop optimizer in the handling of type static
+ variables has been fixed.
+09-09-01 An error message is not displayed when * and @ are used as subscripts.
+09-09-01 Several bugs in the processing for types that included an associative
+ array of another type has been fixed.
+09-09-01 A bug in the tracing of &#0091;&#0091; a &lt; b &#0093;&#0093; and &#0091;&#0091; a &gt; b &#0093;&#0093; has been fixed.
+09-08-26 The .sh.file variable was not being set for a script that was run
+ by name and didn't start with #! and this has been fixed.
+09-08-25 A bug in which a function called to deeply from command substitution
+ did not display an error message has been fixed.
+09-08-24 +When processing profiles, ksh93 now violates the POSIX standard and
+ treats &amp;&gt; as a redirection operator similar to bash.
+09-08-23 A bug in the handling of the trap on SIGPIPE that could lead to a
+ memory fault has been fixed.
+09-08-21 A bug in the handling of the comma operator in arithmetic expressions
+ that could cause a core dump on some systems has been fixed.
+09-08-20 A bug in which a compound variable containing an array of a type
+ that doesn't have any elements now expands correctly.
+09-08-19 A bug which disabled function tracing inside a function after
+ a call to another function has been fixed.
+09-08-19 A bug in which initializing a compound variable instance to another
+ compound variable by name has been fixed.
+09-08-18 A bug in which compound variable instances could be lost after
+ an instance that invoked a type method discipline has been fixed.
+09-08-18 A bug in which a discipline function for a type applied to an
+ array instance when invoked in a function ignored the subscript
+ has been fixed.
+09-08-18 A scoping error with variables in arithmetic expression with
+ type variables when reference with a name reference has been fixed.
+09-08-10 Several memory leaks were fixed primarily related to subshells.
+09-08-06 A bug in which setting the trap on CHLD to ignore could cause
+ a script to hang has been fixed.
+09-07-08 A bug in the processing of name reference assignments when it
+ contained pattern expansions with quoting has been fixed.
+09-06-22 +The default width for typeset -X has been changed so that there
+ should be no loss of precision when converting to a string.
+09-06-19 A bug in the printing of array elements for binary variables with
+ printf %B has been fixed.
+09-06-19 A bug which caused a core dump with trap DEBUG set with an array
+ assignment with no elements has been fixed.
+09-06-19 A bug with read with typeset -b -Z&lt;num&gt; has been fixed.
+09-06-19 Two bugs related to read -b for array variables has been fixed.
+09-06-19 A bug with typeset for compound variables containing arrays of
+ compound variables has been fixed.
+09-06-18 A bug in appending a compound variable to a an indexed array of
+ compound variables has been fixed.
+09-06-18 A bug which occurs when appending a compound variable to an indexed
+ array element has been fixed.
+09-06-18 Setting VISUAL to a value other than one ending in vi or emacs will
+ no longer unset the edit mode.
+09-06-17 A bug in typeset -m when moving a local compound variable to a
+ global compound variable via a name reference has been fixed.
+09-06-17 A bug in appending to nodes of an array of compound variables when
+ addressing them via nameref has been fixed.
+09-06-17 A bug in typeset -p var, when var is an array of compound variables
+ in which the output only contained on array element has been fixed.
+09-06-17 The prefix expansion ${!y.@} now works when y is a name
+ reference to an element of an array.
+09-06-16 Traps on signals that are ignored when the shell is invoked
+ no longer display. Previously they were ignored as required but
+ would be listed with trap -p.
+09-06-12 A bug in vi edit mode in which hitting the up arrow key at the
+ end of a line longer than 40 characters which caused a core dump
+ has been fixed.
+09-06-11 A bug in which "eval non-builtin &amp;" would create two processes,
+ one for the &amp; and another for non-builtin has been fixed.
+09-06-08 When var is an identifier and is unset, ${var} no longer tries to
+ run command substitution on the command var.
+09-06-08 +Process substitution arguments of the form &lt;(command) can now be
+ used following the &lt; redirection operator to redirect from command.
+09-05-13 A bug in which redirections of the form 2&gt;&amp;1 1&gt;&amp;5 inside command
+ substitution could cause the command substitution to hang has been
+ fixed.
+09-05-12 To conform with POSIX, the -u option only checks for unset variables
+ and subscript elements rather than checking for all parameters.
+09-05-12 A bug which could cause a core dump when a variable whose name
+ begins with a . was referenced as part of a name reference inside
+ a function has been fixed.
+09-05-01 A bug that caused a core dump when SIGWINCH was received and
+ both vi and emacs mode were off has been fixed.
+09-04-22 +Default alias compound='typeset -C' added.
+09-04-15 A bug that caused ${...;} to hang for large files has been fixed.
+09-04-08 A change was made in the -n option which printed out an incorrect
+ warning with &lt;&gt;.
+09-04-07 The emacs edit command M-_ and M_. and the vi command _ was fixed
+ to handle the case there there is no history file.
+09-04-05 A bug in handling new-lines with read -n has been fixed.
+09-04-05 The ENV variable defaults the the file named by $HOME/.kshrc rather
+ then to the string $HOME/.kshrc.
+09-03-31 A bug in which a nested command substitution with redirections could
+ leave a file descriptor open has been fixed.
+09-03-24 +ksh now only uses the value of the _ variable on startup if it can
+ verify that it was set by the invoking process rather than being
+ inherited by some other ancestor.
+09-03-24 +When ksh is invoked without -p and ruid!=euid, and the shell is
+ compiled without SHOPT_P_UID or ruid&lt;SHOPT_P_UID, the shell now
+ enables the -p option. The previous version instead set the
+ euid to the ruid as it does for set +p.
+09-03-24 +When SHOPT_P_UID is defined at compile time and the shell is started
+ without -p and ruid!=euid and ruid&gt;=SHOPT_P_UID then euid is set
+ to ruid. A bug that did the wrong test (ruid&lt;SHOPT_P_UID) was fixed.
+09-03-17 +The sleep(1) builtin now accept and ISO 8601 PnYnMnDTnHnMnS
+ duration or date(1) compatible date/time operand.
+09-03-10 If a variable that was left or right justified or zero-filled was
+ changed with a typeset statement that was left or right justified
+ or zero-filled, then the original justification no longer affects
+ the result.
+09-03-10 A bug in the handling of traps when the last command in a script
+ is a subshell grouping command has been fixed.
+09-03-03 A bug in which an expansion of the form ${!prefix@} could generate
+ an exception after the return from a function has been fixed.
+09-02-02 A bug in restricted mode in which the value of ENV could be
+ changed from within a function has been fixed.
+09-02-02 A bug in which an erroneous message indicating that a process
+ terminated with a coredump has been fixed.
+09-02-02 The exit status when exit was called without an argument from
+ a signal handler was incorrect and has been fixed.
+09-02-02 A bug in which a function autoloaded in a subshell could cause
+ a core dump when the subshell completed has been fixed.
+09-02-02 A bug in which 2&gt;&amp;1 inside a command substitution wasn't working
+ correctly has been fixed.
+09-02-02 A bug in the call stack of arithmetic function with 2 args
+ returning int has been fixed.
+09-01-30 A bug in which 'eval print \$0' inside a function was giving the
+ wrong value for $0 has been fixed.
+09-01-28 A bug in which a command substitution could return an exit status
+ of 127 when the pipefail option is enabled has been fixed.
+09-01-26 ksh93 now generates an error message if you attempt to create
+ a global name reference to a local variable.
+09-01-26 +The &#0091;&#0091; -v var &#0093;&#0093; operator was modified to test for array elements.
+09-01-23 +The redirection operator &lt;&gt;; was added. It is similar to &lt;&gt;
+ except that if the command it is applied to succeeds, the file
+ is truncated to the offset at the command completion.
+09-01-23 The default file descriptor for &lt;&gt; was changed to 1.
+09-01-20 A bug in which the exit status specified in an exit trap was
+ not used when a process terminated with a signal has been fixed.
+09-01-19 A bug in which a signal whose default action is to terminate
+ a process could be ignored when the process is running a sub-shell
+ has been fixed.
+09-01-19 A bug in which sending SIGWINCH to a process that reads from a pipe
+ could cause a memory fault has been fixed.
+09-01-16 +The -R unary operator was added to &#0091;&#0091;...&#0093;&#0093; and test to check whether
+ a variable is a name reference.
+09-01-16 +The -v unary operator was added to &#0091;&#0091;...&#0093;&#0093; and test to check whether
+ a variable is set.
+09-01-14 The unset built-in was modified to return 0 exit status when
+ unsetting a variable that was unset to conform with the POSIX
+ standard.
+09-01-14 The unset built-in was modified to continue to unset variables
+ after encountering a variable that it could not unset to
+ conform to the POSIX standard.
+09-01-14 The parameter expansion ${x+value} no longer expands the value of
+ the variable x when determining whether x is set or not.
+09-01-13 A bug in which background jobs and pipelines that were not waited
+ for could, in rare instances, cause the shell to go into an infinite
+ loop or fail has been fixed.
+09-01-06 A bug in indexed arrays of compound variables in which referencing
+ non-existent sub-variable in an arithmetic expression could cause
+ the sub-variable to be created has been fixed.
+09-01-05 A bug in which the &nbsp;character did not escape extended regular
+ expression pattern characters has been fixed.
+08-12-24 A bug in which killing the last element of a pipe did not cause
+ a write to the pipe to generate a SIGPIPE has been fixed.
+08-12-19 A bug which could cause command substitution to hang when the
+ last element of a pipeline in a command substitution was a built-in
+ and the output was more that PIPE_BUFF.
+08-12-18 A bug which occurs when a here documented marker embedded in a
+ command substitution occurs on a buffer boundary has been fixed.
+08-12-17 A bug in the output of typeset -p for variables that had attributes
+ but did not have a value has been fixed.
+08-12-16 A bug in which a name reference to a name reference variable that
+ references an array element has been fixed.
+08-12-16 A bug in which a variable given both the -A and -C attribute along
+ with an initial assignment didn't work correctly has been fixed.
+08-12-10 The &#0091;&#0091; -t fd &#0093;&#0093; test was fixed to handle fd&gt;9.
+08-12-10 A bug where function stack misalignment could cause a bus error
+ has been fixed.
+08-12-09 Command completion was changed to use &nbsp;to quote special characters
+ instead of quoting the argument in single quotes.
+08-12-07 A bug in typeset -m which occurred when the target node was an
+ associative array element has been fixed.
+08-12-07 A timing bug on some systems (for example darwin), that could
+ cause the last process of a pipeline entered interactively to fail
+ with an "Exec format error" has been fixed.
+08-12-04 +SHOPT_BGX enables background job extensions. Noted by "J" in
+ the version string when enabled. (1) JOBMAX=n limits the number
+ of concurrent &amp; jobs to n; the n+1 &amp; job will block until a
+ running background job completes. (2) SIGCHLD traps are queued
+ so that each completing background job gets its own trap; $! is
+ set to the job pid and $? is set to the job exit status at the
+ beginning of the trap. (3) sleep -s added to sleep until the time
+ expires or until a signal is delivered.
+08-12-04 The sign of floating point zero is preserved across arithmetic
+ function calls.
+08-12-04 A bug that caused print(1) to produce garbled stdout/stderr
+ output has been fixed.
+08-12-04 A bug in which printf "%d "'&lt;euro&gt;'" did not output the
+ numerical value of the EURO symbol, 8354, has been fixed.
+08-11-24 + /dev/fd* and /dev/std* redirections are first attempted with
+ open() to preserve seek semantics; failing that the corresponding
+ file descriptors are dup()'d.
+08-11-20 A bug which could cause a core dump if a function compiled with
+ shcomp was found has been fixed.
+08-11-20 A bug in which jobs were not cleared from the jobs table for
+ interactive shells when the pipefail option is on has been fixed.
+08-11-11 A bug in which a field that was unset in a type definition and later
+ set for an instance could appear twice when displaying the variable
+ has been fixed.
+08-11-11 A bug in which running a simple command &amp; inside a function would
+ not return the correct process id has been fixed.
+08-11-10 A bug in which the exit status of a command could be lost if the pid
+ was that of the most recent command substitution that had completed
+ has been fixed.
+08-11-10 The maximum depth for subshells has been increased from 256 to 65536.
+08-11-06 A bug which could cause a core dump when the _ reference variable was
+ used as an embedded type with a compound assignment has been fixed.
+
+08-10-31 --- Release ksh93t ---
+08-10-31 Variable scoping/initialization bugs that could dump core were fixed.
+08-10-24 The lexer now accepts all RE characters for patterns prefixed
+ with a ksh ~(...) option expression.
+08-10-24 +For ${var/pat/sub} &nbsp; in sub expands to the text matched by pat.
+08-10-18 A bug in array scoping that could dump core has been fixed.
+08-10-10 read -n and -N fixed to count characters in multibyte locales.
+08-10-10 A bug that mishandled _.array&#0091;&#0093; type references has been fixed.
+08-10-09 +${.sh.version} now contains a concatenation of the following (after
+ 'Version') denoting compile time features:
+ A SHOPT_AUDIT
+ B SHOPT_BASH
+ L SHOPT_ACCT
+ M SHOPT_MULTIBYTE
+08-10-09 A bug that caused subshell command substitution with redirection
+ to hang has been fixed.
+08-10-08 Output errors, other than to stderr, now result in a diagnostic.
+08-10-08 ksh93 now supports types that contain arrays of other types as
+ members. Earlier versions core dumped in this case.
+08-10-05 A bug which caused the shell to emit a syntax error for an arithmetic
+ statement of the form (( var.name&#0091;sub&#0093; = value)) has been fixed.
+08-10-01 A bug that caused subshell command substitution to hang has
+ been fixed.
+08-09-29 When the -p export option of typeset is used with other options,
+ only those variables matching the specified options are displayed.
+08-09-29 When the shell reads the environment and finds variables that are
+ not valid shell assignments, it now passes these on to subsequent
+ commands rather than deleting them.
+08-09-29 A bug in the display of compound variables containing an indexed
+ array of compound variables has been fixed.
+08-09-29 A bug in the display of compound variables containing an associative
+ array with a subscript containing a . in the name has been fixed.
+08-09-26 A core dump in the subshell environment restore has been fixed.
+08-09-24 $(...) has been fixed to properly set the exit status in $?.
+08-09-23 $(&lt;...) with IFS=$'n' has been fixed to retain all but the last
+ of multiple trailing newlines.
+08-09-23 The -p option to typeset when used with other attributes, restricts
+ the output to variables with the specified attributes.
+08-09-22 A bug that sometimes lost the exit status of a job has been fixed.
+08-09-21 A bug that retained trailing command substitution newlines in
+ cases where the command caused the shell to fork has been fixed.
+08-09-19 type, whence -v, and command -v were fixed to comply with POSIX
+ by writing 'not found' diagnostics to the standard error.
+08-09-18 test and &#0091;...&#0093; were fixed to comply with POSIX in the case
+ of test '(' binop ')' where binop is a valid binary test operator.
+08-09-16 +If a method discipline named create is specified when defining a
+ type, this function will be called when an instance is created.
+08-09-15 +The variable _ is now set as a reference to the compound variable
+ when defining a compound variable or a type.
+08-09-10 The shell now prints an error message when the type name specified
+ for an indexed array subscript is not an enumeration type.
+08-09-10 A bug in which a subshell that spawned a background process could
+ loose output that was produced after the foreground completed
+ has been fixed.
+08-09-10 A timing bug on some systems that could cause coprocesses started by a
+ subshell to not clean up and prevent other coprocesses has been fixed.
+08-09-09 The typeset -m option is now able to rename array elements from
+ the same array.
+08-09-09 The exit status of 2 from the DEBUG trap causes the next command
+ to be skipped. An exit value of 255 from a DEBUG trap called from
+ a function causes the function to return.
+08-09-08 A bug in which a coprocess created in a subshell that did not
+ complete when the subshell terminated could prevent a coprocess
+ from being created in the parent shell has been fixed.
+08-09-05 An assignment of the form name1=name2 where name1 and name2
+ are both compound variables causes name1 to get a copy of name2.
+ name1+=name2 causes name2 sub-variables to be appended to name1.
+08-09-05 A bug in which unsetting a compound variable did not unset all
+ the sub-variables has been fixed.
+08-09-01 A bug in the subshell cleanup code that could cause SIGSEGV has
+ been fixed.
+06-08-26 +The SHLVL variable which is an environment variable used by bash
+ and zsh that gets incremented when the shell starts.
+08-08-25 +For an indexed array, a negative subscript now refers to offsets
+ from the end so that -1 refers to the last element.
+08-08-24 An alignment error for shorts on 64 bit architectures has been fixed.
+08-08-22 If oldvar is a compound variable, typeset -C newvar=oldvar creates
+ newvar as a copy of oldvar.
+08-08-19 +The ALRM signal no longer cause the sleep builtin to terminate.
+08-08-13 When used in an arithmetic expression, the .sh.version variable
+ now produces a number that will be increasing for each release.
+08-08-11 A bug in which type instantiation with a compound assignment in
+ a dot script in which the type is defined has been fixed.
+08-08-07 +The -m option has been added to typeset to move or rename a
+ variable. Not documented yet.
+08-08-06 A bug in read when used in a loop when a prompt was specified
+ when reading from a terminal has been fixed.
+08-08-01 A bug with the pipefail option in which a nested pipeline could
+ cause an asynchronous command to block has been fixed.
+08-08-01 A for loop optimizer bug that treats .sh.lineno as an invariant
+ has been fixed.
+08-07-30 A bug in which expanding compound variable that had a get discipline
+ from with a here document could cause a syntax error has been fixed.
+08-07-18 A bug in which a nameref caused a local variable to be created
+ rather than binding to an existing variable in the global scope
+ has been fixed.
+08-07-17 A bug which occurred when a nameref was created from within a
+ function that was part of a pipeline has been fixed.
+08-07-14 +The compile option SHOPT_STATS was added. With this option the
+ compound variable .sh.stats keeps usage statistics that could help
+ with performance tuning.
+08-07-10 +The output of set now always uses a single line for each variable.
+ For array variables, the complete set of values is now displayed.
+08-07-09 +The typeset -C option can be used with arrays to indicate that
+ each element should default to a compound variable.
+08-07-08 +The %B format now outputs compound variables and arrays. The
+ alternate flag # can be used to cause output into a single line.
+08-07-03 When the window change signal, WINCH, is received, the current
+ edit line is redrawn in place.
+08-07-01 A bug in the handling of shared variables when inside an embedded
+ type has been fixed.
+08-06-29 A bug in multiline edit mode which occurred when the prompt length
+ was three characters or less has been fixed.
+08-06-23 A bug in which the SIGCLD was not be triggered when background
+ jobs completed has been fixed.
+08-06-23 _KSH_VERSION added as a name reference to .sh.version.
+08-06-20 type now outputs 'special builtin' for special builtins.
+08-06-19 A couple of bugs in multi-dimensional arrays have been fixed.
+08-06-19 A bug in which a syntax error in a dot script could generated
+ a syntax error in the next subsequent command has been fixed.
+08-06-17 Reduced the maximum function call depth to 2048 to avoid exceptions
+ on some architectures.
+08-06-16 A bug in which printf "%B" could generate an exception when the
+ specified variable was not set has been fixed.
+08-06-16 +When typeset -p is followed by variable names, it now displays
+ the attributes names and values for the specific names.
+08-06-14 A bug that could effect the drawing of the screen from multiline
+ emacs or gmacs mode when walking up the history file has been fixed.
+08-06-13 A bug in which a compound variable defined in a subshell could
+ have side effects into the parent shell has been fixed.
+08-06-13 A number of bugs related to using .sh.level to set the stack from
+ for DEBUG traps have been fixed.
+08-06-13 +The .sh.lineno variable has been added. When .sh.level is changed
+ inside a DEBUG trap, the .sh.lineno contains the calling line number
+ for the specified stack frame.
+08-06-13 The .sh.level variable has been documented and now works.
+08-06-11 +The -C option has been added to read for reading compound command
+ definitions from a file.
+08-06-11 +The . command is now permitted inside a compound command definition.
+ The dot script can contain declaration commands and dot commands.
+08-06-09 +Add -C option to typeset so that typeset -C foo, is equivalent
+ to foo=().
+08-06-09 Added -n warning message for typeset option orderings that are valid
+ with ksh88 but not valid with ksh93, for example Lx5.
+08-06-09 A bug in which the return value for an assignment command containing
+ a command substitution with that failed was zero when the assignment
+ contained redirections has been fixed.
+08-06-09 A bug in the quoting of $ inside a ERE pattern ~(E)(pattern)
+ has been fixed.
+08-06-06 A bug when processing `` command substitution with the character
+ sequence \$' has been fixed.
+08-06-02 +When defining a type, the typeset -r attribute causes this field
+ to be required to be specified for each instance of the type and
+ does not allow a default value.
+08-06-02 Several bugs in which compound variables were modified by
+ subshells have been fixed.
+08-05-22 +The ceil function has been added to the math functions.
+08-05-21 A bug in which a name reference defined in a function and passed
+ as an argument to another function could cause an incorrect binding.
+08-05-21 A bug in freeing compound variables that are local to functions
+ has been fixed.
+08-05-19 +The array expansions ${array&#0091;sub1..sub2&#0093;} and ${!array&#0091;sub1..sub2&#0093;}
+ to expand to the value (or subscripts) for array between sub1 and
+ sub2 inclusive. For associative arrays, the range is based on
+ location in the POSIX locale. The .. must be explicit and cannot
+ result from an expansion.
+08-05-15 The trap on SIGCLD is no longer triggered by the completion of
+ the foreground job as with ksh88.
+08-05-14 A bug in the implementation of the editing feature added on
+ 07-09-19 in emacs mode has been fixed.
+08-05-12 A bug in processing the test built-in with parenthesis has been
+ fixed.
+08-05-12 The unset built-in now returns non-zero when deleting an array
+ subscript that is not set.
+08-05-08 +Changing the value of HISTFILE or HISTSIZE will cause the old
+ history file to be close and reopened with the new name or size.
+08-05-08 When FPATH is changed functions that were found via a path search
+ will be searched for again.
+08-05-08 A parser bug in which reserved words and labels were recognized
+ inside compound indexed array assignment after a new-line has
+ been fixed.
+08-05-07 A bug in getopts when handling numerical option arguments has
+ been fixed.
+08-05-07 +The typeset -S option was added for variables outside type
+ definitions to provide a storage class similar to C static
+ inside a function defined with function name. When outside
+ type definitions and outside a function, the -S option cause
+ the specified variable so be unset before the assignment and
+ before the remaining attributes are supplied.
+08-05-07 A bug that affected the cursor movement in multiline mode when
+ a character was deleted from near the beginning of the any
+ line other than the first.
+08-05-01 In multiline edit mode, the refresh operation will now clear
+ the remaining portion of the last line.
+08-05-01 A bug in computing prompt widths for the edit modes for prompts
+ with multibyte characters has been fixed.
+08-05-01 A bug in the multiline edit mode which could cause the current
+ line to be displayed incorrectly when moving backwards from third
+ or higher line to the previous line has been fixed.
+08-05-01 A bug in which options set in functions declared with the function
+ name syntax were carried across into functions invoked by these
+ functions has been fixed.
+08-04-30 A bug which could cause a coprocess to hang when the read end
+ is a builtin command has been fixed.
+08-04-30 +The emacs and vi editors have been modified to handle window
+ change commands as soon as they happen rather than waiting for
+ the next command.
+08-04-28 A bug in which ${!x} did not expand to x when x was unset has been
+ fixed.
+08-04-27 A bug in which the assignment x=(typeset -a foo=(&#0091;0&#0093;=abc)) created
+ x.foo as an associative array has been fixed.
+08-04-25 A bug in which $# did not report correctly when there were more
+ than 32K positional parameters has been fixed.
+08-04-04 Choose the name _ as the sub-variable that holds type or instance
+ specific data used by discipline functions.
+08-03-27 A bug in which the terminal group was not given back to the parent
+ shell when the last part of a pipeline was handled by the parent shell
+ and the other parts of the pipeline complete has been fixed.
+ The symptom was that the pipeline became uninterruptable.
+08-03-25 A bug in restricted mode introduced in ksh93s that caused scripts
+ that did not use #! to executed in restricted mode has been fixed.
+08-03-25 A bug in which the pipefail option did not work for a pipeline
+ within a pipeline has been fixed.
+08-03-24 A bug in which OPTIND was not set correctly in subshells has
+ been fixed.
+08-03-24 A bug which could cause a memory exception when a compound variable
+ containing an indexed array with only element 0 defined was expanded.
+08-03-20 A bug in which ${!var&#0091;sub&#0093;.*} was treated as an error has been fixed.
+08-03-20 Associative array assignments of the form (&#0091;name&#0093;=value ...)
+ now allow ; as well as space tab and new line to separate elements.
+08-03-18 A buffering problem in which standard error was sometimes
+ not flushed before sleep has been fixed.
+08-03-17 A bug in which a signal sent to $$ while in a subshell would be
+ sent to the subshell rather than the parent has been fixed.
+08-03-17 + A --default option added to set(1) to handle set +o POSIX semantics.
+ set --state added as a long name alias for set +o.
+08-03-14 A bug in which using monitor mode from within a script could
+ cause the terminal group to change has been fixed.
+08-03-10 The new ${...} command substitution will treat the trailing }
+ as a reserved word even if it is not at the beginning of a command,
+ for example, ${ date }.
+08-03-10 If the name of the ENV begins with /./ or ././ then the
+ /etc/ksh.kshrc file will not be executed on systems that support
+ this interactive initialization file.
+08-03-07 A bug in which ksh -i did not run the ENV file has been fixed.
+08-03-07 A bug in which ulimit did not always produce the same output as
+ ulimit -fS has been fixed.
+08-03-04 A bug in multiline mode in emacs and vi mode which could cause the
+ cursor to be on the wrong line when interrupt was hit has been fixed.
+08-03-03 The change made in ksh93s+ on 07-06-18 in which braces became
+ optional for ${a&#0091;i&#0093;} inside &#0091;&#0091;...&#0093;&#0093; was restored in the case
+ where the argument can be a pattern.
+08-03-03 A bug in which creating a name reference to an associative array
+ instance would fail when the subscript contained characters &#0091; or
+ &#0093; has been fixed.
+08-02-29 +The redirection operator &gt;; has been added which for non-special
+ files, generates the output in a temporary file and writes the
+ specified file only of the command has completed successfully.
+08-02-15 A bug in ${var/pattern/string} for patterns of the form ?(*) and +(*)
+ has bee fixed.
+08-02-07 A bug in which test \( ! -e \) produced an error has been fixed.
+08-02-14 +The typeset -a option can now optionally be followed by the name
+ of an enumeration type which allows subscripts to be enumerations.
+08-02-14 +The enum builtin which creates enumeration types has been added.
+08-02-12 The backoff logic when there are no more processes has been fixed.
+08-02-07 The -X option has been added to typeset. The -X option creates
+ a double precision number that gets displayed using the C99 %a
+ format. It can be used along with -l for long double.
+08-01-31 The -T option to typeset has been added for creating typed
+ variables. Also the -h and -S options have been added to
+ typeset that are only applicable when defining a type.
+08-01-31 The prefix expansion operator @ has been added. ${@name}
+ expands to the type of name or yields the attributes.
+07-11-15 A bug in the macro expander for multibyte characters in which
+ part of the character contains a file pattern byte has been fixed.
+07-10-03 A bug in which : was not allowed as part of an alias name has been
+ fixed.
+07-09-26 A bug in which appending a compound variable to a compound variable
+ or to an index array didn't work has been fixed.
+07-09-19 In both emacs and vi edit mode, the escape sequence \E&#0091;A (usually
+ cursor up, when the cursor is at the end of the line will fetch
+ the most recent line starting with the current line.
+07-09-18 The value of ${!var} was correct when var was a reference to an
+ array instance.
+07-09-18 The value of ${!var&#0091;sub&#0093;} was not expanding to var&#0091;sub&#0093; and this
+ was fixed. It also fixed ${name} where name is a name reference
+ to var&#0091;sub&#0093;.
+07-09-18 +It is now legal to create a name reference without an initialization.
+ It will be bound to a variable on the first assignment.
+07-08-30 +A discipline function can be invoked as ${x.foo} and is equivalent
+ to ${ x.foo;} and can be invoked as x.foo inside ((...)).
+07-07-09 A bug in which typeset -a did not list indexed arrays has been
+ fixed.
+07-07-03 +The command substitution ${ command;} has been added. It behaves
+ like $(command) except that command is executed in the current
+ shell environment. The ${ must be followed by a blank or an
+ operator.
+
+08-04-17 --- Release ksh93s+ ---
+08-04-17 A bug in which umask was not being restored correctly after a
+ subshell has been fixed.
+08-04-15 A bug in which sending a STOP signal to a job control shell started
+ from within a shell function caused cause the invoking shell to
+ terminate has been fixed.
+08-04-11 A bug which caused $(exec &gt; /dev/null) to go into an infinite loop
+ has been fixed.
+08-03-27 A bug in which typeset -LZ was being treated as -RZ has been fixed.
+08-03-06 A bug with ksh -P on systems that support the the profile shell,
+ in which it would exit after running a non-builtin has been fixed.
+08-01-31 A bug in which command substitution inside ((...)) could cause
+ syntax errors or lead to core dumps has been fixed.
+08-01-17 A bug in which discipline functions could be deleted when invoked
+ from a subshell has been fixed.
+08-01-17 A bug in which a command substitution consisting only of
+ assignments was treated as a noop has been fixed.
+08-01-17 A bug in which discipline functions invoked from withing a
+ compound assignment could fail has been fixed.
+08-01-16 Incomplete arithmetic assignments, for example ((x += )), now
+ generate an error message.
+08-01-16 A bug in which a set discipline defined for a variable before
+ an array assignment could cause a core dump has been fixed.
+08-01-03 A bug in on some systems in which exit status 0 is incorrectly
+ returned by a process that catches the SIGCONT signal is stopped
+ and then continued.
+07-12-13 A race condition in which a program that has been stopped and then
+ continued could loose the exit status has been fixed.
+07-12-12 Code to check for file system out of space write errors for all
+ writes has been added.
+07-12-11 A bug in the macro expander for multibyte characters in which
+ part of the character contains a file pattern byte has been fixed.
+07-12-06 A bug in the emacs edit mode when multiline was set that output
+ a backspace before the newline to the screen has been fixed.
+07-12-04 A bug in which using &lt;n&gt;TAB after a variable name listing expansion
+ in the edit modes would cause the $ to disappear has been fixed.
+07-11-28 A bug in which setting IFS to readonly could cause a subsequent
+ command substitution to fail has been fixed.
+07-11-27 A work around for a gcc 4.* C99 "feature" that could cause a job
+ control shell to go into an infinite loop by adding the volatile
+ attribute to some auto vars in functions that call setjmp().
+07-11-27 A bug in which the shell could read ahead on a pipe causing the
+ standard input to be incorrectly positioned has been fixed.
+07-11-27 A bug in which compound variable UTF-8 multibyte values were not
+ expanded or traced properly has been fixed.
+07-11-21 A bug where an unbalanced '&#0091;' in a command argument was not treated
+ properly has been fixed.
+07-11-15 A bug in which compatibility mode (no long option names) getopts(1)
+ incorrectly set the value of OPTARG for flag options has been fixed.
+07-11-15 A bug in which "hash -- name" treated "--" as an invalid name operand
+ has been fixed.
+07-11-15 typeset now handles "-t -- &#0091;-r&#0093; &#0091;--&#0093;" for s5r4 hash(1) compatibility.
+07-11-15 A bug in which the umask builtin mis-handled symbolic mode operands
+ has been fixed.
+07-11-15 Bugs in which shell arithmetic and the printf builtin mis-handled the
+ signs of { -NaN -Inf -0.0 } have been fixed.
+07-11-15 +The full { SIGRTMIN SIGRTMIN+1 ... SIGRTMAX-1 SIGRTMAX } range
+ of signals, determined at runtime, are now supported.
+07-11-15 A bug in which creating an index array with only subscript 0 created
+ only a simple variable has been fixed.
+07-11-14 A bug in which appending to an indexed array using the form
+ name+=(&#0091;sub&#0093;=value) could cause the array to become an associative
+ array has been fixed.
+07-11-14 A bug in which typeset without arguments could coredump if a
+ variable is declared as in indexed array and has no elements has
+ been fixed.
+07-11-14 A bug in which creating a local SECONDS variable with typeset in
+ a function could corrupt memory has been fixed.
+07-11-14 A bug which could cause a core dump when a script invoked by name
+ from a function used compound variables has been fixed.
+07-11-05 A bug in which printf %d "'AB" did not diagnose unconverted characters
+ has been fixed.
+07-11-05 printf %g "'A" support added for all floating point formats.
+07-11-01 A bug in which typeset -f fun did not display the function definition
+ when invoked in a subshell has been fixed.
+07-10-29 The sleep builtin was fixed so that all floating point constants
+ are valid operands.
+07-10-10 A bug in which the locale was not being restored after
+ LANG=value command has been fixed.
+07-09-20 A bug in which a nameref to a compound variable that was local
+ to the calling function would not expand correctly when displaying
+ is value has been fixed.
+07-09-19 A bug which cause cause a core dump if .sh.edchar returned
+ 80 characters or more from a keyboard trap has been fixed.
+07-09-14 A bug in which could cause a core dump when more than 8 file
+ descriptors were in use has been fixed.
+07-09-10 A bug in which creating a name reference to an instance of
+ an array when the array name is itself a reference has been fixed.
+07-09-10 The file completion code has been modified so that after an = in
+ any word, each : will be considered a path delimiter.
+07-09-06 A bug in which subprocess cleanup could corrupt the malloc() heap
+ has been fixed.
+07-08-26 A bug in which a name reference to an associative array instance
+ could cause the subscript to be evaluated as an arithmetic expression
+ has been fixed.
+07-08-22 A bug in which the value of an array instance was of a compound
+ variable was not expanded correctly has been fixed.
+07-08-14 A bug which could cause a core dump when a compound assignment was
+ made to a compound variable element with a typeset -a attribute
+ has been fixed.
+07-08-08 A bug in which a trap ignored in a subshell caused it to be
+ ignored by the parent has been fixed.
+07-08-07 A bug in which the set command would generated erroneous output
+ for a variable with the -RZ attribute if the variable name had been
+ passed to a function has been fixed.
+07-08-02 A bug in which read x&#0091;1&#0093; could core dump has been fixed.
+07-08-02 A second bug in which after read x&#0091;sub&#0093; into an associative array
+ of an element that hasn't been assigned could lead to a core dump
+ has been fixed.
+07-07-31 A bug in which a pipeline that completed correctly could have
+ an exit status of 127 when pipefail was enabled has been fixed.
+07-07-09 +The SHOPT_AUDIT compile option has been added for keyboard logging.
+07-06-25 In vi insert mode, ksh no longer emits a backspace character
+ before the carriage return when the newline is entered.
+07-06-25 A bug in which pipefail would cause a command to return 0
+ when the pipeline was the last command and the failure happened
+ on a component other than the last has been fixed.
+07-06-25 A bug in the expansion of ${var/pattern/rep} when pattern or rep
+ contained a left parenthesis in single quotes has been fixed.
+07-06-18 The braces for a subscripted variable with ${var&#0091;sub&#0093;} are now
+ optional when inside &#0091;&#0091;...&#0093;&#0093;, ((...)) or as a subscript.
+07-05-28 A bug in brace expansion in which single and double quotes did
+ not treat the comma as a literal character has been fixed.
+07-05-24 The -p option of whence now disables -v.
+07-05-23 Several bug fixes in compound variables and arrays of arrays
+ have been made.
+07-05-15 A bug in which the %B format of printf was affected by the
+ locale has been fixed.
+07-05-14 A bug in which &nbsp;was not removed in the replacement pattern with
+ ${var/pattern/rep} when it was not followed by &nbsp;or a digit has
+ been fixed.
+07-05-10 A bug in which ksh -R file core dumped if no script was specified
+ has been fixed. it not displays an error message.
+07-05-07 Added additional Solaris signals to signal table.
+07-04-30 A bug in which a pipeline with command substitution inside a
+ function could cause a pipeline that invokes this function to
+ hang when the pipefail option is on has been fixed.
+07-04-30 +Added -q to whence.
+07-04-18 A small memory leak with each redirection of a non-builtin has
+ been fixed.
+07-03-08 A bug in which set +o output command line options has been fixed.
+07-03-08 A bug in which an error in read (for example, an invalid variable
+ name), could leave the terminal in raw mode has been fixed.
+07-03-06 A bug in which read could core dump when specified with an array
+ variable with a subscript that is an arithmetic expression has
+ been fixed.
+07-03-06 Several serious bugs with the restricted shell were reported and
+ fixed.
+07-03-02 If a job is stopped, and subsequently restarted with a CONT
+ signal and exits normally, ksh93 was incorrectly exiting with
+ the exit status of the stop signal number.
+07-02-26 +M-^L added to emacs mode to clear the screen.
+07-02-26 A bug in which setting a variable readonly in a subshell would
+ cause an unset error when the subshell completed has been fixed.
+07-02-19 +The format with printf uses the new = flag to center the output.
+07-02-19 A bug in which ksh93 did not allow multibyte characters in
+ identifier names has been fixed.
+07-02-19 A bug introduced in ksh93 that causes global compound variable
+ definitions inside functions to exit with "no parent" has been fixed.
+07-02-19 A bug in which using compound commands in process redirection
+ arguments would give syntax errors &lt;(...) and &gt;(...) has been fixed.
+07-01-29 A bug which caused the shell to core dump which can occur when a
+ built-in exits without closing files that it opens has been fixed.
+07-01-26 A bug in which ~(E) in patterns containing &nbsp;that are not inside ()
+ has been fixed.
+
+06-12-29 --- Release ksh93s ---
+06-12-29 A bug in which the value of IFS could be changed after a command
+ substitution has been fixed.
+06-12-22 +/dev/(tcp|udp|sctp)/HOST/SEVRICE now handles IPv6 addresses on
+ systems that provide getaddrinfo(3).
+06-12-19 +A -v option was added to read. With this option the value of
+ the first variable name argument will become the default value
+ when read from a terminal device.
+06-11-20 A bug in which "${foo&#0091;@&#0093;:1}}" expands a null argument (instead of
+ no argument), when foo&#0091;0&#0093; is not empty has been fixed.
+06-11-16 The discipline functions have been modified to allow each subscript
+ to act independently. Currently the discipline function will not
+ be called when called from a discipline function of the same variable.
+06-11-14 A bug which could cause a core dump if a file descriptor for
+ an internal file was closed from with a subshell has been fixed.
+06-10-30 +The redirections &lt;# pattern, and &lt;## pattern have been added.
+ Both seek forward to the beginning of the next line that contains
+ the pattern. The &lt;## form copies the skipped portion to standard
+ output.
+06-10-26 +On systems that support stream control transport, the virtual file
+ name /dev/sctp/host/port can now be used to establish connections.
+06-10-26 +The printf modifier # when used with d produces units in thousands
+ with a single letter suffix added. The modifier # when used with
+ the i specification provides units of 1024 with a two letter suffix.
+06-10-24 The value of $! is now set to the process id of a job put
+ into the background with the bg command as required by POSIX.
+06-10-23 A bug in which the value of $! was affected by a background
+ job started from a subshell has been fixed.
+06-10-23 A bug in ${var:offset:len} in multibyte locales has been fixed.
+06-10-15 +The remaining math functions from C99 were added for any system
+ that supports them.
+06-10-13 The klockwork.com software detected a few coding errors that
+ have been fixed.
+06-10-12 A bug when skipping over `...` with ${x:=`...`} when x is set
+ has been fixed.
+06-10-11 A bug in process floating constants produced by the %a format
+ of printf has been fixed.
+06-10-06 A bug in which IFS was not being restored correctly in some
+ cases after a subshell has been fixed.
+06-10-06 A bug in which pipefail was not detecting some failures in
+ pipelines with 3 or more states has been fixed.
+06-10-03 A bug in the processing of &gt;(...) with builtins which could
+ cause the builtin to hang has been fixed.
+06-10-03 A bug in the for loop optimizer which causes &gt;(...) process
+ substitution to be ignored has been fixed.
+06-09-17 +The -a option was added to typeset for indexed arrays. This
+ is only needed when using the (&#0091;subscript&#0093;=value ...) form.
+06-09-06 +The showme option was added. Each simple command not beginning
+ with a redirection and not occurring with in the while, until, if,
+ select condition can be preceded by a semi-colon which will
+ be ignored when showme is off. When showme is on, any command
+ preceded by a colon will be traced but not executed.
+06-08-16 +As a new feature, a leading ~(N) on a pattern has no effect
+ except when used for file expansion. In this case if not
+ matches are found, the pattern is replaced by nothing rather
+ than itself.
+06-08-11 A bug in the expansion of ${.sh.match&#0091;i&#0093;:${#.shmatch&#0091;i&#0093;}} has
+ been fixed.
+06-08-10 +The read builtin options -n and -N have been modified to treat
+ the size as characters rather than bytes unless storing into a
+ binary (typeset -B) variable.
+06-07-27 +When the here document operator &lt;&lt; is followed directly by a #
+ rather than a -, the first line of the here-document determines
+ how much whitespace is removed for each line.
+06-07-26 A bug in the C-shell history (enabled with set -H) in which the
+ history event !$ was not processed has been fixed.
+06-07-21 A bug on some systems in which assigning PATH on a command line
+ would not take effect has been fixed.
+06-07-20 Add ksh93 and rksh93 as allowable names for ksh binaries.
+06-07-20 Removed the SHOPT_OO compilation option which was only partially
+ implemented.
+06-07-20 The ability to use egrep, grep, and fgrep expressions within
+ shell patterns has been documented.
+06-07-17 A bug with arithmetic command expressions for locales in which
+ the comma is a thousands separator has been fixed.
+06-07-13 +The default HISTSIZE was increased from 128 to 512.
+06-07-13 A multibyte problem with locales that use shift codes has been fixed.
+06-06-23 A number of bug fixes for command, file, and variable completion
+ have been mode.
+06-06-20 +Floating point division by zero now yields the constant Inf or -Inf
+ and floating functions with invalid arguments yield NaN.
+06-06-20 +The floating point constants Inf and NaN can be used in arithmetic
+ expressions.
+06-06-20 +The functions isinf(), isnan(), tanhl() have been added for
+ arithmetic expressions.
+06-06-13 Internal change to use ordering for variables instead of hashing
+ to speed up prefix matching.
+06-06-13 A window between fork/exec in which a signal could get lost
+ and cause a program to hang has been eliminated
+06-06-13 A bug in edit completion with quoted strings has been fixed.
+06-06-07 The restricted options can now be enabled by set as well as on
+ the command line. Once set, it can not be disabled.
+06-06-04 Modified built-in binding so that for systems for which /bin
+ and /usr/bin are the same, a builtin bound to /bin will get
+ selected when either /bin or /usr/bin is scanned.
+06-06-04 +Added literal-next character processing for emacs/gmacs mode.
+ This change is not compatible with earlier versions of ksh93
+ and ksh88 when the stty lnext is control-v. The sequence
+ escape-control-v will display the shell version.
+06-05-31 +Modified emacs and vi mode so that entering a TAB after a partial
+ TAB completion, generates a listing of possible completions.
+ After the second TAB, a number followed by a TAB will perform
+ the completion with the corresponding item.
+06-05-19 +Modified arithmetic so that conversions to strings default to
+ the maximum number of precision digits.
+06-05-16 Bug fixes for multibyte locales.
+06-05-10 The =~ operator was added to &#0091;&#0091;...&#0093;&#0093; and &#0091;&#0091; string ~= ERE &#0093;&#0093;
+ is equivalent to &#0091;&#0091; string == ~(E)ERE &#0093;&#0093;.
+06-04-25 A bug in the vi edit mode which could cause the shell to core dump
+ when switching from emacs mode.
+06-04-17 A bug in which using LANG or LC_ in assignment lists with builtins
+ did not restore the localed correctly has been fixed.
+06-04-04 A bug in which discipline functions could not be added to variables
+ whose names started with .sh has been fixed.
+06-03-28 +The -s option to typeset was added to modify -i to indicate short
+ integers.
+06-03-28 A bug in which variables assignment lists before functions
+ defined with function name were not passed on the functions
+ invoked by this function has been fixed.
+06-03-28 A bug in which name references defined within a function defined
+ with function name could not be used with compound variables has
+ been fixed.
+06-03-27 A bug in which read &lt;&amp;p (print &gt;&amp;p) would cause the coprocess input
+ (output) pipe to close before reading from (after writing to)
+ it has been fixed.
+06-02-28 A bug in which stopping a job created with the hist builtin command
+ would create a job that could not be restarted has been fixed.
+
+06-01-24 --- Release ksh93r ---
+06-01-24 A bug in which running commands with standard output closed would
+ not work as expected has been fixed.
+06-01-23 A bug in which print -u&lt;n&gt; could fail when file descriptor &lt;n&gt; was
+ open for writing has been fixed.
+06-01-19 The ?: arithmetic operator fixed to work when the operation after
+ the colon was an assignment.
+05-12-24 A bug which could lead to a core dump when elements of a compound
+ variable were array elements, i.e. foo=(bar=(1 2)), has been fixed.
+05-12-13 An arithmetic bug in which x+=y+=z was not working has been fixed.
+05-12-13 An arithmetic bug in which x||y was returning x when x was non-zero
+ rather than 1 has been fixed.
+05-12-07 +The aliases for integer and float have been changed to use attributes
+ -li and -lE to handle long long and long double types.
+05-12-07 +The histexpand (-H) option has been added which allows C-shell
+ style history expansions using the history character !.
+05-12-07 +The multiline option was added which changes that way the edit
+ modes handle lines longer than the window width. Instead of
+ horizontal scrolling, multiple lines on the screen are used.
+05-12-05 The whence builtin now returns an absolute pathname when the
+ command is found in the current directory.
+05-11-29 A bug which caused ksh -c '&#0091;&#0091; ! ((' to core dump rather than
+ report a syntax error has been fixed.
+05-11-29 A bug when reading fixed length records into typeset -b variables
+ which caused a zero byte to terminate the value has been fixed.
+05-11-22 +The ability to seek to an offset within a file has been added
+ with the new I/O redirection operators, &lt;# and &gt;#. Currently,
+ these redirection operators must be followed by ((expr))
+ but in a future release, it should be able to used to seek forward
+ to the specified shell pattern. In addition $(n&lt;#) expands to the
+ current byte offset for file descriptor n.
+05-11-22 +The .sh.match array variable is now set after each &#0091;&#0091; ... &#0093;&#0093;
+ pattern match. Previously it was only set for substring matches.
+05-10-17 A bug in which the library path variable could be prefixed
+ with a directory when a .path file was not encountered in
+ the directory of the executable has been fixed.
+05-09-15 A for/while loop optimizer bug in which $OPTIND was not
+ correctly expanded has been fixed.
+05-09-05 A bug in which a history command that invoked a history
+ command could go into an infinite loop has been fixed.
+05-08-31 +In the case that IFS contains to adjacent new-lines so that
+ new-line is not treated as a space delimiter, only a single
+ new-line is deleted at the end of a command substitution.
+05-08-19 +When a tilde substitution expands to the / directory and is
+ followed by a /, it is replaced by the empty string.
+05-08-16 A bug in which n&lt;&amp;m did not synchronize m has been fixed.
+05-08-16 A bug in which process substitution ( &lt;() and &gt;() ) was not
+ working within for and while loops has been fixed.
+05-07-24 A bug in which the pattern ~(E)(foo|bar) was treated as a syntax
+ error has been fixed.
+05-07-24 A bug in completion with &lt;n&gt;=, where n was the one of the
+ previous selection choices has been fixed.
+05-07-21 A bug with multibyte input when no edit mode was specified which
+ caused the input line to shift left/right has been fixed.
+05-06-24 A race condition which could cause the exit status to get lost
+ on some fast systems has been fixed.
+05-06-21 A bug in which nested patterns of the form {m,n}(pat) would cause
+ syntax errors has been fixed.
+05-06-21 A bug in the macro expander has been fixed which could cause a
+ syntax error for an expansion of the form ${x-$(...)} when
+ x is set and the command substitution contained certain strings.
+05-06-08 +On systems for which echo does not do System V style &nbsp;expansions,
+ the -e option was added to enable these expansion.
+05-06-08 A bug in which ${var op pattern} to not work when inside an
+ arithmetic expression has been fixed.
+05-05-23 +An extension to shell patterns that allows matching of nested
+ groups while skipping over quoted strings has been added.
+05-05-18 A bug in which the line number for errors was not correct for
+ functions loaded from FPATH has been fixed.
+05-04-18 A bug in which the exit status $? is not set when a trap triggered
+ by the &#0091;&#0091;...&#0093;&#0093; command is executed has been fixed.
+05-04-08 +Redirection operators can be directly preceded with {varname}
+ with no intervening space, where varname is a variable name which
+ allows the shell to select a file descriptor &gt; 10 and store it
+ into varname.
+05-04-08 +SHOPT_CMDLIB_BLTIN=1 now includes &lt;cmdlist.h&gt; generated table.
+05-04-07 +&#0091;&#0091; -o ?option &#0093;&#0093; is true if "option" is a supported option.
+05-04-05 A bug in handling file completion with spaces in the names
+ has been fixed.
+05-03-25 +The SIGWINCH signal is caught by default to keeps the LINES and
+ COLUMNS variables in sync with the actual window size.
+05-03-25 +Building ksh with SHOPT_REMOTE=1 causes ksh to set --rc if stdin is
+ a socket (presumably part of a remote shell invocation.)
+05-03-25 +Building ksh with SHOPT_SYSRC=1 causes interactive ksh to source
+ /etc/ksh.kshrc (if it exists) before sourcing the $ENV file.
+05-03-25 +{first..last&#0091;..incr&#0093;&#0091;%fmt&#0093;} sequences added to brace expansions
+ when braceexpand is enabled.
+05-03-03 A bug where a SIGCHLD interrupt could cause a fifo open to fail has
+ been fixed.
+05-02-25 A bug in which a builtin command run in the background could
+ keep a file descriptor open which could cause a foreground
+ process to hang has been fixed.
+05-02-24 A bug where builtin library commands (e.g., date and TZ) failed to
+ detect environment variable changes has been fixed.
+05-02-22 +The read builtin and word splitting are now consistent with respect
+ to IFS -- both treat IFS as field delimiters.
+05-02-22 +The read builtin no longer strips off trailing delimiters that
+ are not space characters when there are fewer variables than fields.
+05-02-17 A builtin bug on systems where dlsym(libcmd) returns link-time
+ bindings has been fixed.
+05-02-12 A bug in which the lib_init() function for .paths BUILTIN_LIB
+ libraries was not called has been fixed.
+05-02-06 A bug on some systems in which moving the write end of a co-process
+ to a numbered file descriptor could cause it to close has been fixed.
+05-02-06 A bug in the vi-edit mode in which the character under the cursor
+ was not deleted in some cases with the d% directive has been fixed.
+05-02-06 A bug where external builtin stdout/stderr redirection corrupted
+ stdout has been fixed.
+05-02-04 A bug where times formatting assumed CLK_TCK==60 has been fixed.
+
+05-01-11 --- Release ksh93q ---
+05-01-11 A bug in the integral divide by zero check has been fixed.
+05-01-11 +The -l option has been added to read /etc/profile and
+ $HOME/.profile, if they exist, before the first command.
+05-01-11 An argument parsing bug that caused `kill -s x -- n' to fail has
+ been fixed.
+05-01-11 +The .paths file, introduced in ksh93m, which can appear in
+ any directory in PATH, now allows a line of the form 'BUILTIN_LIB=.'
+ When a command is searched for this directory, and the full path
+ matches the path of the built-in version of the command (listed
+ by the 'builtin' command) then the built-in version of the command
+ is used. When ksh is built with SHOPT_CMDLIB_DIR=1 then all libcmd
+ functions become builtins with the '/opt/ast/bin/' directory prefix.
+05-01-10 A bug in which a nameref to a compound name caused a core dump has
+ been fixed.
+05-01-09 A bug in which some SIGCHLD interrupts (from child processes exiting)
+ caused a fatal print/echo error diagnostic has been fixed.
+04-12-24 A bug in which some SIGCHLD interrupts (from child processes exiting)
+ corrupted the internal process/job list, sometimes causing the shell
+ to hang, has been fixed.
+04-12-01 A bug in which typeset -Fn truncated less than n digits for large
+ numbers has been fixed.
+04-11-25 A bug in which standard error could be closed after a redirection
+ to /dev/stderr has been fixed.
+04-11-17 A bug in which an expansion of the form ${array&#0091;@&#0093;:3} could expand
+ to ${array&#0091;0&#0093;} when ${array&#0091;3&#0093;} was not set has been fixed.
+04-10-22 +The -E or -orc command line option reads ${ENV-$HOME/.kshrc} file.
+04-10-22 +`-o foo' equivalent to `+o nofoo', `-o nobar' equivalent to `+o bar'.
+ `--foo' equivalent to `-o foo', `--nofoo' equivalent to `+o foo'
+04-10-05 +The .paths file, introduced in ksh93m, which can appear in
+ any directory in PATH, now allows a line of the form
+ 'BUILTIN_LIB=libname'. When a command is searched for this directory,
+ the shared library named by libname will first be searched for a
+ built-in version of the command.
+04-09-03 &lt;&lt;&lt; here documents now handle quotes in the word token correctly.
+04-08-08 +The maximum size for read -n and and read -N was increased from
+ 4095 to 32M.
+04-08-04 +printf %q was modified so that if an no operand was supplied, no
+ no output would be generated rather than a quoted empty string.
+04-08-01 +The -n and -N options of the read builtin has been modified
+ when reading variables with the binary attribute so that the
+ data is stored directly rather than through assignment.
+04-08-01 +The shcomp command has been modified to process alias commands
+ under some conditions.
+04-07-31 +The .sh.match variable added in ksh93l, now works like other
+ indexed arrays.
+04-07-08 A loop optimizer bug which occurs when typeset is used in
+ a for or while loop inside a function has been fixed.
+04-06-24 +The number of subexpressions in a pattern was increased to 64
+ from the current number of 20.
+04-06-17 +The -t option to read was modified to allow seconds to be
+ specified as any arithmetic expression rather than just
+ an integral number of seconds, for example even -t 'sin(.5)'
+ is now valid.
+04-06-16 Two small memory leak problems were fixed.
+04-06-15 A bug in ${var/pattern/"string"} which occurred when string
+ contained pattern matching characters has been fixed.
+04-05-08 printf $'%d produced an erroneous error message and has
+ been fixed.
+04-05-24 A bug in which an associative array without any elements could
+ cause a core dump when a script with an associative array with
+ the same name was declared in a script invoked by name has
+ been fixed.
+04-05-11 A bug in which an exec statement could close the script that
+ is being processed in a script that is run by name causing
+ a failure has been fixed.
+04-04-28 +If the first character of assignment to an integer variable was 0,
+ the variable had been treated as unsigned. This behavior was
+ undocumented and has been removed.
+04-04-05 A bug in which the positioning of standard input could be incorrect
+ after reading from standard input from a subshell has been fixed.
+04-03-30 A bug in the for loop optimizer which in rare cases could cause
+ memory corruption has been fixed.
+04-03-29 +The preset alias source='command .' has been added.
+04-03-29 A bug introduced in ksh93p on some systems in which invoked by
+ name with #! on the first line would not get the signals handling
+ initialized correctly has been fixed.
+04-03-29 A bug introduced in ksh93p in which a HUP signal received by
+ a shell that is a session group leader was not passed down to
+ its children has been fixed.
+
+04-02-28 --- Release ksh93p ---
+04-02-28 +The ability to apply an append discipline to any variable has
+ been added.
+04-02-14 A bug in which the exportall option (set -a) would cause incorrect
+ results for arrays has been fixed.
+04-02-02 A bug in which an exported array would pass more than
+ the first element to a script invoked by name has been fixed.
+04-02-02 A bug on some systems in which name=value pairs preceding a script
+ invoked by name was not getting passed to the script has been fixed.
+04-01-20 A bug in which an unset discipline function could cause a core
+ dump on some systems has been fixed.
+04-01-12 A bug in which a continue or break called outside a loop from
+ inside a function defined with name() syntax could affect
+ the invoking function has been fixed.
+04-01-08 If a command name begins with ~, only filename completion will be
+ attempted rather than pathname completion using the builtin editors.
+04-01-08 A bug in the vi edit mode in which the wrong repeat count on
+ multiple word replacements with the . directive has been fixed.
+04-01-06 Backspace characters are now handled correctly in prompt strings.
+04-01-06 +The getopts builtin has been modified to accept numerical
+ arguments of size long long on systems that support this.
+04-01-06 A bug in which unsetting all elements of an associative array
+ would cause it to be treated as an indexed array has been fixed.
+03-12-15 A bug in which a quoted string ending with an unescaped $ would
+ delete the ending $ in certain cases has been fixed.
+03-12-05 A bug in which the shell could hang when set -x tracing a command
+ when an invalid multibyte character is encountered has been fixed.
+03-12-05 On some systems, if the KEYBD trap is set, then commands that use
+ the meta key were not processed until return was hit. This
+ has been fixed.
+03-12-05 A problem which occurred when the login shell was not a group
+ leader that could cause it to fail has been fixed.
+03-12-05 A problem in which a shell could core dump after receiving a signal
+ that should cause it to terminate while it was in the process
+ of acquiring more space has been fixed.
+03-12-05 +If ENV is not specified, the shell will default to $HOME/.kshrc
+ for interactive shells.
+03-11-21 A bug introduced in ksh93o in which the DEBUG trap could get
+ disabled after it triggered has been fixed.
+03-11-04 A bug in which using arithmetic prefix operators ++ or -- on a
+ non-lvalue could cause a core dump has been fixed.
+03-11-04 A bug in which leading zeros were stripped from variable
+ expansions within arithmetic computation to avoid being treated
+ as octal constants when they should not have, has been fixed.
+03-10-08 A bug introduced in ksh93o in which a large here document inside
+ a function definition could get corrupted has been fixed.
+03-09-22 A bug in which the .get discipline function was not being
+ called when a string variable was implicitly referenced from
+ within a numerical expression has been fixed.
+03-09-22 A bug in which a script without a leading #! could get executed
+ by /bin/sh rather than the current shell on some systems has
+ been fixed.
+03-09-12 +To improve conformance with ksh88, leading zeros will be ignored
+ when getting the numerical value of a string variable so that
+ they will not be treated as octal constants.
+03-09-03 +The builtin kill command now processes obsolete invocations
+ such as kill -1 -pid.
+03-09-02 The restriction on modifying FPATH in a restricted shell (sh -r)
+ has been documented.
+03-09-02 +The restricted shell (sh -r) has been modified to disallow
+ executing command -p.
+03-08-07 A bug in which the KEYBD trap was not being invoked when
+ characters with the 8th bit set has been fixed.
+03-08-02 A parser bug introduced in ksh93o which caused the character
+ after () in a Posix function definition to be skipped
+ when reading from standard input has been fixed.
+03-08-01 A bug in which "${foo#pattern}(x)" treated (x) as if it were
+ part of the pattern has been fixed.
+03-08-01 +The command -x option has been modified so that any trailing
+ arguments that do expand to a single word will be included
+ on each invocation, so that commands like command -x mv * dir
+ work as expected.
+
+03-07-20 --- Release ksh93o+ ---
+03-07-20 A bug in which could cause memory corruption when a posix
+ function invoked another one has been fixed.
+03-07-15 A bug in which a file descriptor&gt;2 could be closed before
+ executing a script has been fixed.
+03-07-15 A parsing error for &lt;() and &gt;() process substitutions inside
+ command substitution has been fixed.
+03-07-15 A parsing error for patterns of the form {...}(...) when
+ used inside ${...} has been fixed.
+03-07-15 An error in which expanding an indexed array inside a compound
+ variable could cause a core dump has been fixed.
+03-07-15 A bug in which on rare occasions a job completion interrupt
+ could cause to core dump has been fixed.
+03-06-26 A bug in which process substitution embedded within command
+ substitution would generate a syntax error has been fixed.
+03-96-23 A bug in which ${@:offset:len} could core dump when there
+ were no arguments has been fixed.
+03-96-23 A bug in which ${X&#0091;@&#0093;:offset:len} could core dump when X
+ was unset has been fixed.
+03-06-22 +The -x option was added to the command builtin. If this
+ option is on, and the number of arguments would exceed ARG_MAX,
+ the command will be invoked multiple times with a subset of
+ the arguments. For example, with alias grep='command -x grep,
+ any number of arguments can be specified.
+03-06-14 A bug in which could cause a core dump on some systems with
+ vi and emacs editors with the MULTIBYTE option has been fixed.
+03-06-06 A bug in which the shell could core dump when a script was
+ run from its directory, and the script name a symlink to a file
+ beginning with .., has been fixed.
+03-06-05 A bug in which the shell could core dump when a child process
+ that it is unaware of terminates while it is calling malloc()
+ has been fixed.
+03-06-02 +An option named globstar (set -G) has been added. When enabled,
+ during pathname expansion, any component that consists only of ** is
+ matches all files and any number of directory levels.
+03-05-30 A bug in which the PATH search could give incorrect results when
+ run from directory foo and PATH contained .:foo:xxx has been fixed.
+03-05-29 +Some changes were made to the code that displays the prompt in edit
+ mode to better handle escape sequences in the prompt.
+03-05-27 I added = to the list of characters that mark the beginning of
+ a word for edit completion so that filenames in assignments
+ can be completed.
+03-05-20 A bug in which read -N could hang on some systems when reading
+ from a terminal or a pipe has been fixed.
+03-05-19 A bug in which the output of uname from a command substitution
+ would go to the standard output of the invoking command when
+ uname was invoked with a non-standard option has been fixed.
+03-05-19 A job control bug which would cause the shell to exit because
+ it hadn't take back the terminal has been fixed. The bug
+ could occur when running a function that contained a pipeline
+ whose last element was a function.
+03-05-19 A job control timing bug introduced in ksh93o on some systems
+ which could cause a pipeline to hang if the first component
+ completed quickly has been fixed.
+03-05-13 +The read builtin has been modified so that the builtin editors
+ will not overwrite output from a previous incomplete line.
+03-05-13 A bug in which the name of an identifier could have the string
+ .sh. prefixed to it after expanding a variable whose name begins
+ with .sh. has been fixed.
+03-05-13 A bug in the expansion of $var for compound variables in which
+ some elements would not be output when the name was a prefix
+ of another name in the compound variable has been fixed.
+03-05-08 The last item in the ksh93o release on 03-01-02 has been
+ altered slightly to preserve the leading 0's when the
+ preceding character is a digit. Thus, with typeset -LZ3 x=10,
+ $(( 1$x)) will be 1010 whereas $(( $x) will be 10.
+03-04-25 A bug in which if x is a name reference, then nameref y=x.foo
+ did not follow x has been fixed.
+
+03-03-18 --- Release ksh93o ---
+03-03-18 +A -N unary operator was added to test and &#0091;&#0091;...&#0093;&#0093; which returns
+ true if the file exists and the file has been modified since it
+ was last read.
+03-03-18 +The TIMEFORMAT variable was added to control the format for
+ the time compound command. The formatting description is
+ described in the man page.
+03-03-06 +A -N n option was added to read which causes exactly n bytes
+ to be read unlike -n n which causes at most n bytes to be read.
+03-03-03 +Three new shell variables were added. The variable .sh.file
+ stores the full pathname of the file that the current command
+ was found in. The variable .sh.fun names the current function
+ that is running. The variable .sh.subshell contains the depth
+ of the current subshell or command substitution.
+03-03-03 +When the DEBUG trap is executed, the current command line after
+ expansions is placed in the variable .sh.command. The trap
+ is also now triggered before each iteration of a for, select,
+ and case command and before each assignment and redirection.
+03-02-28 +Function definitions are no longer stored in the history file so
+ that set -o nolog no longer has any meaning.
+03-02-28 +All function definitions can be displayed with typeset -f not
+ just those stored in the history file. In addition, typeset +f
+ displays the function name followed by a comment containing the
+ line number and the path name for the file that defined this function.
+03-02-28 A bug in which the value of $LINENO was not correct when executing
+ command contained inside mult-line command substitutions has been
+ fixed.
+03-02-19 +Since some existing ksh88 scripts use the undocumented and
+ unintended ability to insert a : in front of the % and # parameter
+ expansion operators, ksh93 was modified to accept :% as equivalent
+ to % and :# as equivalent to # with ${name op word}.
+03-02-14 A bug which could cause a core dump when reading from standard
+ error when standard error was a pty has been fixed.
+03-02-14 +The shell arithmetic was modified to use long double on systems
+ that provide this data type.
+03-02-09 A bug in which a function located in the first directory in FPATH
+ would not be found when the last component of PATH was . and the
+ current directory was one of the directories in PATH has been fixed.
+03-02-07 +The trap and kill builtin commands now accept a leading SIG prefix
+ on the signal names as documented.
+03-02-05 A bug in the expansion of ${var/$pattern}, when pattern contained
+ \&#0091; has been fixed.
+03-02-05 A bug in which .sh.match&#0091;n&#0093;, n&gt;0, was not being set for substring
+ matches with % and %% has been fixed.
+03-01-15 A bug in which getopts did not work for numerical arguments specified
+ as n#var in the getopts string has been fixed.
+03-01-09 A bug in which using ${.sh.match} multiple times could lead to
+ a memory exception has been fixed.
+03-01-06 A bug in the expansion of ${var/pattern/$string} in the case that
+ $string contains \digit has been fixed.
+03-01-02 +A -P option was added for systems such as Solaris 8 that support
+ profile shell.
+03-01-02 For backward compatibility with ksh88, arithmetic expansion
+ with ((...)) and let has been modified so that if x is a zero-filled
+ variable, $x will not be treated as an octal constant.
+
+02-12-05 --- Release ksh93n+ ---
+02-11-30 A bug that can show up in evaluating arithmetic statements that
+ are in an autoloaded function when the function is autoload from
+ another function has been fixed.
+02-11-30 An optimization bug in which an expansion of the form ${!name.@},
+ which occurred inside a for or a while loop, when name is a name
+ reference, has been fixed.
+02-11-18 A bug in which modifying array variables in a subshell could leave
+ side effects in the parent shell environment has been fixed.
+02-11-18 A memory leak when unsetting an associative array has been fixed.
+02-11-14 +The code to display compound objects was rewritten to make
+ it easier for runtime extensions to reuse this code.
+02-11-14 +A change was made to allow runtime builtins to be notified when
+ a signal is received so that cleanup can be performed.
+02-10-31 +User applications can now trap the ALRM signal. Previously,
+ the ALRM signal was used internally and could not be used
+ by applications.
+02-10-31 A bug in which signals received while reading from a coprocess
+ for which traps were set was not handled correctly has been fixed.
+02-10-31 A bug in which a file opened with exec inside a subshell could
+ be closed before the subshell completed has been fixed.
+02-10-21 A bug in which setting PATH or FPATH inside a function might not
+ take effect has been fixed.
+02-10-21 A bug which could cause a core dump when a local SECONDS variable
+ is defined in a function has been fixed.
+02-10-15 A bug in which the associate array name operator ${!array&#0091;@&#0093;}
+ could return the same name multiple times has been fixed.
+02-10-15 A bug in which the zero'th element of an associative array was
+ not getting set when an assignment was made without a subscript
+ specified has been fixed.
+
+02-09-30 --- Release ksh93n ---
+02-09-30 +The maximum indexed array size was increased to 16Megs.
+02-09-30 A bug which could cause a core dump when changing attributes
+ of associative array has been fixed.
+02-09-30 A bug in which exporting an array variable would not export the
+ 0-th element has been fixed.
+02-09-30 A bug in which an array assignment of the form a=($a ...) would unset
+ 'a' before the right hand side was evaluated has been fixed.
+02-09-27 A bug in which the error message for ${var?message} when var was
+ null or unset did not contain the variable name var has been fixed.
+02-09-27 A bug in which closing file descriptors 0 through 2 could
+ cause a subsequent here document to fail has been fixed.
+02-09-14 A bug in whence which occurs when the specified name contained
+ a / has been fixed.
+02-09-14 A bug in the parser for strings of the form name$((expr))=value
+ has been fixed.
+02-09-14 A for loop optimization bug in which the number of elements in
+ an array was treated as an invariant has been fixed.
+02-09-09 A bug in which redirection or closing of a file descriptor between
+ 3 and 9 could cause a subsequent here document to fail has been
+ fixed.
+02-09-09 A bug in which a background job was not removed from the job list
+ when a subshell completed has been fixed, for example (prog&amp;).
+02-09-03 A bug in which an assignment of the form name=(integer x=3)
+ could be interpreted as an array assignment rather than a
+ compound variable assignment has been fixed.
+02-08-19 A command completion bug which occurred on file systems that
+ are case insensitive has been fixed.
+02-08-19 A bug which could lead to an exception on some systems (for
+ example FREEBSD) which occurred when setting PATH has been fixed.
+02-08-11 A bug in arithmetic rounding in which a value input as a decimal
+ string would output as a rounded version of the string has
+ been fixed.
+02-08-11 A bug in which the last character could be deleted from shell
+ traces and from whence when called from a multibyte locale
+ has been fixed.
+02-08-01 A bug which could cause a core dump to occur when a shell script
+ is executed while a coprocess is running that has closed the
+ output pipe has been fixed.
+02-08-01 A bug in which command completion in multibyte mode could
+ corrupt memory for long command lines has been fixed.
+
+02-06-17 --- Release ksh93n- ---
+02-06-17 A bug in which user defined macros could cause a core dump in
+ with MULTIBYTE mode has been fixed.
+02-06-17 A bug in which printf format specifiers of the form %2$s were causing
+ a core dump has been fixed.
+02-06-17 A bug in which setting stty to noecho mode did not prevent the
+ echoing of characters by ksh when emacs or viraw mode
+ was enabled has been fixed.
+02-06-17 A bug in which background job completion could cause the sleep
+ builtin to terminate prematurely has been fixed.
+02-06-17 A bug in which the shell could core dump if getopts was called
+ when the OPTIND variable contained a negative value has been fixed.
+02-06-10 +The edit mode prompt has been modified to handle escape sequences.
+02-06-10 A bug which occurred for interactive shells in which the builtin
+ cat command was used in command substitution on a file whose
+ size was larger than PIPE_BUF has been fixed.
+02-06-10 A bug in which the trap on ERR was not being processed when
+ set inside a function has been fixed.
+02-06-07 A bug in which function definitions could cause the history count
+ to be decremented by one (and even become negative) has been fixed.
+02-06-05 A bug in read in which share mode could be enabled has been fixed.
+02-05-28 A bug which could occur when the last command of a script was
+ a case statement and the action selected ended in ;&amp; instead of ;;
+ has been fixed.
+02-05-23 A bug with unary + introduced in ksh93k has been fixed.
+02-05-07 A bug in substitutions of the form ${var/pattern/string} in which
+ a backslash was inserted in the replacement string when it contained
+ a special pattern character has been fixed.
+02-05-01 A bug in the emacs edit mode which occurred in versions compiled
+ for multibyte character sets which occurred when a repeated search
+ was requested after a long line had been returned for the previous
+ search has been fixed.
+02-04-02 +vi and emacs edit modes were modified so that tab completion is
+ disabled when invoked from the read built-in.
+
+02-03-26 --- Release ksh93m+ ---
+02-03-26 A bug in which &nbsp;was not handled correctly when used in file
+ expansion has been fixed.
+02-02-18 A bug in which lines beginning with a # were deleted from here
+ documents when the here-document delimiter was followed by
+ a comment has been fixed.
+02-12-06 An optimization bug in which ${!x&#0091;@&#0093;) was treated as invariant in
+ a for loop has been fixed.
+02-02-06 A bug in which the ERR trap is not cleared for a script invoked
+ by name from within a function has been fixed.
+02-01-08 A bug in which a shell script executed from within a subshell
+ could cause this script to have an invalid pointer leading
+ to a memory fault has been fixed.
+02-01-07 +Added here documents of the form &lt;&lt;&lt; word (as per zsh) which
+ is equivalent to &lt;&lt; delimordelim.
+02-01-07 A bug in which the first word of a compound assignment,
+ x=(word ...), was treated as a reserved word has been fixed.
+02-01-07 A bug in the handling of &nbsp;when noglob was enabled and a
+ substitution of the form ${word op pattern} occurred in the
+ same word has been fixed.
+02-01-07 +A compilation option, CMDLIB_BLTIN in the file OPTION, has
+ been added. When this options is set, all commands implemented
+ in libcmd become shell builtin commands by default.
+02-01-07 A bug in which builtin foo, where foo is already a builtin
+ would result in the builtin foo getting removed has been fixed.
+02-01-07 A bug which the shell executed a command found in the current
+ directory when PATH have no valid directories has been fixed.
+01-11-28 The value of $? was not being set when called with exit.
+01-11-28 If the last command was of the form (...) and a trap on EXIT or
+ ERR was set, and the command inside () modified the trap, then
+ 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
+ viraw mode will always be on.
+
+01-10-31 --- Release ksh93m ---
+01-10-31 A for loop optimizer bug for subshells contained withing for
+ loops has been fixed.
+01-10-16 typeset without arguments no longer outputs variable names
+ that do not have any attributes that are set.
+01-10-16 A bug introduced in ksh93l in which assignments specified with
+ the exec built-in were not being expanded properly has been
+ fixed.
+01-10-11 An optimization bug in which ${!x) was treated as invariant in
+ a for loop has been fixed.
+01-10-11 Unsigned integer variables in bases other than 10 are printed now
+ expand in that base with the base prefix.
+01-10-10 A number of typos in the self generating man pages for shell
+ built-ins have been fixed.
+01-10-04 The self generated man pages for hist and fc were not working
+ correctly and have been fixed.
+01-10-03 Yet another optimizer bug in which shell patterns were
+ treated as invariants has been fixed.
+01-09-27 Two bugs relating to multibyte history searches and to find
+ have been fixed.
+01-09-27 A bug introduced in ksh93k in which the PATH searching was
+ not restored after running a command with an assignment list
+ has been fixed.
+01-09-26 A bug in which a zero filled field was treated as octal when
+ converted to integer has been fixed.
+01-09-26 Yet another bug in the optimization of for loops related to
+ recursive functions with break or continue statements has been fixed.
+01-09-25 +The exponentiation operator ** was added to the shell arithmetic
+ evaluation. It has higher precedence than * and is left
+ associative.
+01-09-25 The code was modified to use the ast multibyte macros
+ and functions for handing multibyte locales.
+01-09-25 +The expansion ${parameter:offset:length} now handles negative
+ offsets which cause offsets to be measured from the end.
+01-09-25 Some spelling errors in the documentation were corrected.
+01-09-24 +The /dev/tcp/host/port and /dev/udp/host/port now allow
+ the ports to be specified by service name.
+01-09-24 +The change staring with ksh93g in which the the appropriate
+ library path variable is prepended with a corresponding library
+ directory has been modified. With the new method, only the
+ library path defined in the file named .paths in the directory
+ where the executable is found will be modified. See the
+ man page for more details.
+01-09-23 +The .fpath file (see ksh93h) is no longer looked for in each
+ directory on the path to locate function directories. The
+ file named .paths is used instead.
+01-09-23 A bug in which IFS was not being restored after being changed in
+ a subshell has been fixed.
+01-09-16 +With the vi and emacs edit modes, after a list of command
+ or functions is generated with = or M-= respectively,
+ any element from the list can be pasted on the command line
+ by preceding the = or M-= with a numeric parameter specifying
+ the position on the list.
+01-09-16 A bug in ksh93l caused command completion not to find aliases
+ and functions. Command listing from the edit mode was presented
+ in reverse order. This has been fixed.
+01-09-13 Another bug in the optimization of for loops related to subshells
+ when traps were set has been fixed.
+01-09-07 A change in ksh93l caused brace expansion to stop working
+ and this has been fixed.
+01-09-04 A bug introduced in ksh93k in which an arithmetic statement
+ within a function that used name references did not follow the
+ reference has been fixed.
+01-09-04 A bug introduced in ksh93l in which export -p did not prefix
+ each export with the word export has been fixed.
+01-08-29 A bug in multibyte input which occurred when a partial multibyte
+ character was received has been fixed.
+01-08-29 A bug introduced in ksh93l which could cause a core dump
+ when an assignment list containing PATH is specified inside
+ command substitution has been fixed.
+01-08-09 Another bug in the optimization of for loops in ksh93l caused
+ errors in recursive functions using local variables that
+ contained for loops has been fixed.
+01-07-27 A bug in which IFS would be unset after a command substitution
+ inside a here document has been fixed.
+01-07-26 To conform to the POSIX standard, if you invoked ksh name,
+ and name does not contain a /, it will first try to run
+ one in the current directory whether it is executable or not
+ before doing a path search for an executable script. Earlier
+ versions first checked for an executable script using the
+ PATH variable.
+01-07-23 A bug in which unset -f invoked in a subshell could unset a
+ function defined in the parent has been fixed.
+01-07-16 A bug in the optimization of for loops in ksh93l caused
+ name references to be treated as invariants has been fixed.
+01-07-09 A bug in which a discipline function applied to a local variable
+ could cause a shell exception has been fixed. Discipline
+ functions can only be specified for global variables.
+
+01-06-18 --- Release ksh93l ---
+01-06-18 A bug in assigning integers larger than can be represented as
+ long integers to floating point variables has been fixed.
+01-06-18 A bug in the handling of unsigned integers (typeset -ui) has
+ been fixed.
+01-06-04 The evaluation of the PS1 prompt no longer effects the value
+ of the $? variable.
+01-06-01 A small memory leak from subshells has been fixed.
+01-05-22 A bug in which attributes for variables that did not have
+ values would be lost after a subshell has been fixed.
+01-05-22 +The %R format has been added to convert a shell pattern into
+ an extended regular expression.
+01-05-22 +The escape sequences &#0092;, <JOIN>X, \C&#0091;.collating-element.&#0093;, and
+ \x{hex} have been added to ASCII-C strings and to printf format
+ strings.
+01-05-20 +Patterns of the form {n}(pattern) and {m,n}(pattern) are now
+ recognized. The first form matches exactly n of pattern whereas,
+ the second form matches from m to n instances of pattern.
+01-05-20 +The shell allows *-(pattern), +-(pattern), ?-(pattern),
+ {m,n}-(pattern}, and @-(pattern) to cause the minimal
+ match of pattern to be selected whenever possible rather
+ than the maximal (greedy) match.
+01-05-20 +The character class &#0091;:word:&#0093; has been added to patterns.
+ The word class is the union of &#0091;:alnum:&#0093; and the character _.
+01-05-20 +Inside (...) pattern groups, the &nbsp;character is now treated
+ specially even when in an enclosing character class. The
+ sequences, \w, \d, \s are equivalent to the character classes
+ word, digit, and space respectively. The sequences \W, \D,
+ and \S are their complement sets.
+01-05-20 +The shell now recognizes pattern groups of the form
+ ~(options:pattern) where options or :pattern can be omitted.
+ Options use the letters + and - to enable and disable options
+ respectively. The option letters g (greedy), i (ignore case)
+ are used to cause maximal matching and to cause case
+ insensitive matching respectively. If :pattern is also
+ specified, these options are only in effect while this
+ pattern is being processed. Otherwise, these options remain
+ in effect until the end of the pattern group that they are contained
+ in or until another ~(...) is encountered. These pattern groups
+ are not counted with respect to group numbering.
+01-05-14 When edit completion, expansion, or listing occurs in the
+ middle of a quoted string, the leading quote is ignored when
+ performing the completion, expansion, or listing.
+01-05-14 A small memory leak from subshells has been fixed.
+01-05-10 A bug in which open files were not restored after a subshell
+ that had used exec to replace a file has been fixed.
+01-05-10 +Redirection to a null file name now generates an error message.
+01-05-09 The shell now rejects some invalid parameter substitutions that
+ were previously processed in undefined ways.
+01-05-09 A bug in which the output of select was not flushed before the
+ read when input did not come from the terminal has been fixed.
+01-05-08 A bug in which job ids would not be freed for interactive shells
+ when subshells ran built-ins in the background has been fixed.
+01-05-08 +The FPATH variable now requires an explicit . to cause the
+ current directory to be treated as a function directory.
+01-05-08 A bug in read -n when echo mode was disabled has been fixed.
+01-05-07 A bug in which function definitions could be listed as part
+ of the history has been fixed.
+01-04-30 +This release uses a new and often much faster pattern matcher than
+ earlier releases.
+01-04-30 +An optimizer now eliminates invariant parameter expansions from
+ for while and until loops.
+01-04-30 +The variable .sh.match is set after each pattern match (# % or /)
+ in a variable substitution. The variable .sh.match is an
+ indexed array with element 0 being the complete match.
+ The array is only valid until the next subsequent pattern
+ match or until the value of the variable changes which ever
+ comes first.
+01-04-30 +A self generating man page has been added to shcomp. Also,
+ shcomp now stops compiling when it finds an exit or exec
+ command and copies the remainder so that it can be used
+ for standard input.
+01-04-30 +The shcomp command was modified so that it can work in an
+ EBCIDIC environment and that binary scripts are portable
+ across environments.
+01-04-30 A bug in the handling of a trailing : in PATH has been fixed.
+01-04-30 A bug in which the builtin version of a command would get invoked
+ even though the full pathname for the command was specified
+ has been fixed.
+01-04-30 A bug in which read would loose the last character when
+ reading the last line of a file that did not contain a new-line
+ character has been fixed.
+01-04-23 A bug on some systems in which in vi mode the end of file
+ character and end of line character could be swapped has
+ been fixed.
+01-04-23 A bug on some systems in which invoking a shell script that
+ did not have execute permission could set the exit value to
+ 127 rather than 126 has been fixed.
+01-04-20 A bug in which read -n from a pipe would block if fewer than
+ n characters was received has been fixed.
+01-04-09 A bug in which invalid patterns, for example, ) by itself,
+ was not treated as a string has been fixed so that if i=')',
+ then &#0091;&#0091; $i == $i &#0093;&#0093; is true.
+01-04-09 +The shell arithmetic now interprets C character constants.
+01-04-09 A bug in which a non-zero return from a function defined
+ with the function reserved word did not trigger the ERR
+ trap or exit with set -e has been fixed.
+01-04-02 A bug on some systems, in which characters above 127 were
+ not displayed correctly in vi or emacs edit mode has been fixed.
+01-04-02 A bug on some systems, introduced in the 'k' point release, in
+ which the erase character in viraw mode was moving the cursor
+ to the left without erasing the character has been fixed.
+01-04-02 On some systems the wcwith() function was returning a wrong
+ value for characters and caused characters to be displayed
+ incorrectly from the shell edit modes. A work around for
+ this problem has been added.
+01-03-26 A bug in which valid scripts could produce syntax errors
+ when run with locales that considered characters such as "'"
+ to be space characters has been fixed.
+01-03-20 A bug in which an syntax error in an arithmetic expression
+ entered interactively could cause the shell to go into
+ an infinite loop outputting the error message has been fixed.
+01-03-10 +ksh93 accepts -l as a synonym for -L in test on systems for
+ which /bin/test -l tests for symbolic links.
+01-03-10 A bug in parsing scripts in which { and } are used in place of
+ in and esac in case statements embedded in compound commands
+ has been fixed. Use of { and } for in and esac is obsolete.
+01-03-06 A bug in which an argument of the form foo=bar was not
+ being passed correctly to a traced function whose name
+ was foo has been fixed.
+01-03-02 Using $(trap -p name) did not print the name of the current
+ trap setting for trap name.
+01-02-26 Exported floating point variables gave incorrect results
+ when passing them to ksh88. This has been fixed.
+01-02-25 A race condition in which a coprocess which completed too quickly
+ would not allow subsequent coprocesses to start has been fixed.
+01-02-25 The 'g' format specifier is now handled by printf. It had
+ inadvertently been omitted.
+01-02-20 The + was not being displayed during an execution trace
+ with the += assignment operator.
+01-02-19 The error message which occurs when the interpreter name
+ defined on the #! line does not exist is more informative.
+01-02-19 A bug in which $0 would not be set correctly when a
+ script with #! was invoked by full pathname from the
+ directory of the script has been fixed.
+01-02-19 A shell script did not always pick up tty mode changes
+ made by external commands such as stty which could
+ effect the behavior of read.
+01-02-19 The -u, -g, and -k unary tests did not give the correct
+ results when used with negation and this has been fixed.
+
+01-02-05 --- Release ksh93k+ ---
+01-02-05 The sequence \&lt;newline&gt; inside $'...' was not incrementing
+ the line count and this has been fixed.
+01-02-05 +Modified expansion of "${@-}" so that if no arguments are set
+ it results in null string rather than nothing.
+01-02-02 memory leak problem with local variables in functions fixed.
+01-01-25 +allow arithmetic expressions with float%int and treat them
+ as ((int)float)%int rather than as an error.
+01-01-19 read -n1 was not working and has been fixed.
+01-01-17 +ksh now handles the case in which a here document in command
+ substitution $() is terminated by the trailing ). Previously,
+ a new-line was needed at the end of the delimiter word.
+01-01-02 A bug in which a KEYBD trap would cause a multi-line token
+ to be processed incorrectly has been fixed.
+00-12-10 +Arithmetic integer constants can now have L and U suffices.
+00-12-10 A bug in the processing of arithmetic expressions with compound
+ variables when the -n option is on has been fixed.
+00-12-08 A bug in M-f and M-b from emacs mode has been fixed. This
+ bug only occurs when ksh93 is compiled without MULTIBYTE enabled.
+00-11-29 A bug in which jobs -p would yield 0 for background
+ jobs run in a script has been fixed.
+00-11-21 A bug in integer arrays in which the number of elements is
+ incorrect when the ++ operator is applied to a non-existing
+ element has been fixed. For example, integer x; ((x&#0091;3&#0093;++)).
+00-11-20 A timing bug in which the shell could reset the terminal
+ group to the wrong value in the case that the a new process
+ changes the terminal group during startup has been fixed.
+
+00-10-27 --- Release ksh93k ---
+00-10-27 Using tab for completion now works only when applied
+ after a non-blank character at the end of the current line.
+ In other case a tab is inserted.
+00-10-27 A bug in the emacs edit mode for ^X^E has been fixed.
+ The ^X^E sequence is supposed to invoke the full editor
+ on the current command.
+00-10-18 A bug in which expansions of the form ${var//pattern/string}
+ did not work correctly when pattern was '/' or "/" has
+ been fixed.
+00-10-18 +The output format for indexed arrays in compound variables
+ has been modified so that it can be used as input.
+00-10-18 Assignments with name references (typeset -n) will now
+ implicitly unreference an existing name reference.
+00-10-17 A bug the += append operator when a single array element
+ is appended to a variable that is not an array has been fixed.
+00-10-16 A bug in which the SIGCONT signal was being sent to
+ each process will kill -0 or kill -n 0 has been fixed.
+00-10-12 +The arithmetic evaluation portion has been rewritten to
+ perform a number of optimizations.
+00-10-10 A bug in which name prefix matching ${!name.*} was not
+ checking name to see if it was a name reference has been fixed.
+00-09-26 A bug in the multibyte version in which the width of for
+ non-printing characters was not correct has been fixed.
+00-09-12 +Made changes to get multibyte editing work on UWIN for windows
+00-09-12 A bug in which multibyte characters would be displayed incorrectly
+ has been fixed.
+00-08-08 Removed build dependency on iswprint() and iswalph().
+00-07-20 In some cases the read builtin would read more than a single
+ line from a pipe on standard input and therefore leave the seek
+ position in the wrong location.
+00-07-05 +If the directory / is on the path, a / will not be inserted
+ between the directory and the file name during path searching
+ to avoid searching // for systems that treat this specially.
+00-06-26 A bug in which on rare occasions wait could return before all
+ jobs have completed has been fixed.
+00-06-21 A bug in which backspace did not work correctly during the
+ R replace directive in vi-mode has been fixed.
+00-06-12 +Added variable name completion/expansion/listing to the set of
+ completions. Variable name completions begin with $ or "$ followed
+ by a letter.
+00-05-09 --- Release ksh93j ---
+00-05-09 Modified command substitution to avoid using /tmp files when
+ run on read-only file systems.
+00-04-17 +Modified printf to handle '%..Xc' and '%..Xs' options where X
+ is not an alpha character. Previous versions core dumped with this.
+00-04-10 +Changes to multibyte editing code were made to use standard
+ ISO C functions rather than methods devised before the standard.
+00-04-09 Add %H options to printf to output strings with &lt;"'&amp;\t&gt; properly
+ converted for use in HTML and XML documents.
+00-04-07 +Modified getopts builtin to handle <.>..</.>< >in usage string</ >
+ by invoking specified function.
+00-04-04 Added self generating man pages for bg, fc, fg, disown, jobs,
+ hist, let, ., and ulimit.
+00-03-30 +The append operator += has been added and can be used
+ for all assignments, strings, arrays, and compound variables.
+00-03-30 +Code was modified in several places to support automatic
+ generation of C locale dictionaries.
+00-03-28 A bug in which the set and trap commands invoked with --name
+ type arguments would terminate the invoking script has
+ been fixed.
+00-03-27 A bug in which the library path variable was not updated
+ correctly on some systems as described in the 'g' point
+ release has been fixed.
+00-03-07 printf now returns a non-zero exit status when one of
+ its arguments cannot be converted to the given type.
+00-03-05 The return value and error message for a command that
+ was found on the path but was not executable was set
+ incorrectly.
+00-03-05 A prototype for ioctl() was removed from the vi edit mode.
+
+00-01-28 --- Release ksh93i ---
+00-01-28 +Most of the built-in commands and ksh itself are now
+ self documenting. Running command --man will produce
+ screen output. Running command --html produces the
+ man page in html format.
+00-01-28 +The getopts builtin can process command description
+ strings to produce man pages.
+00-01-28 A bug in which a script could terminate when getopts
+ encountered an error when invoked inside a function
+ has been fixed.
+00-01-28 When a symbolic link was specified as the name of
+ the script to invoke by name, the value of $0 was
+ set to the real file name rather than the link name
+ in some cases and this has been fixed.
+00-01-28 A bug in which the precision given as an argument
+ to printf was not working has been fixed.
+
+99-03-31 --- Release ksh93h ---
+99-03-31 +The PATH search algorithm has been modified to look
+ for a file named .fpath in each bin directory and if
+ found, to search for functions in this directory if
+ it cannot find the command in that directory.
+99-03-31 +When performing pathname expansion, the shell checks
+ to see whether each directory it reads is case sensitive
+ or not, and performs the matching accordingly.
+99-03-31 +The %T format for printing formatted date/time.
+99-03-31 +The emacs and vi modes now handle arrow keys when
+ they use standard ANSI escape sequences.
+99-03-31 +The TAB key can be used for completion in emacs and viraw mode.
+99-03-31 A bug in setting .sh.editchar during the KEYBD trap
+ for the MULTIBYTE option was fixed in release ksh93h.
+99-03-31 A bug in shcomp for compilation of unary operators with &#0091;&#0091;...&#0093;&#0093;
+ has been fixed.
+99-03-31 A bug in which the value of $? was changed when executing
+ a keyboard trap has been fixed.
+99-03-31 The handling of SIGCHLD has been changed so that the
+ trap is not triggered while executing trap commands
+ to avoid recursive trap calls.
+99-03-31 A bug in which a local variable in a function declared readonly
+ would generated an error when the function went out of
+ scope has been fixed.
+99-03-31 A bug in which \&lt;new_line&gt; entered from the keyboard
+ with the KEYBD trap enabled has been fixed.
+99-03-31 The error message for a misplaced ((, for example print ((3),
+ was often garbled and has been fixed.
+99-03-31 A bug in the KEYBD trap in which escape sequences of the form
+ &lt;ESC&gt;&#0091;#~ were not being handled as a unit has been fixed.
+99-03-31 A bug in which ksh would consider expressions like &#0091;&#0091; (a) &#0093;&#0093;
+ as syntax errors has been fixed.
+99-03-31 A function defined as foo() without a function body
+ was not reported as a syntax error.
+99-03-31 A bug in which ksh could run out of file descriptors when
+ a stream was repeatedly opened with exec and read from
+ has been fixed.
+
+98-04-30 --- Release ksh93g ---
+98-04-30 +The pipefail option has been added. With pipefail
+ enabled, a pipeline will not complete until all
+ commands are complete, and the return value will
+ be that of the last command to fail, or zero if
+ all complete successfully.
+98-04-30 +The name-value pair library uses the cdt library rather
+ than the hash library. This change should be transparent
+ to applications.
+98-04-30 +On the U/WIN version for Window 95 and Windows NT,
+ when a directory beginning with a letter followed by
+ a colon is given to cd, it is assumed to be an absolute
+ directory
+98-04-30 +When an executable is found on a given path,
+ the appropriate library path variable is prepended
+ with a corresponding library directory.
+98-04-30 A bug in which a name reference could be created to
+ itself and later cause the shell to get into an infinite
+ loop has been fixed.
+98-04-30 A bug in shcomp relating to compound variables was fixed.
+98-04-30 A bug introduced in ksh93e in which leading 0's in -Z
+ fields caused the value to be treated as octal for arithmetic
+ evaluation has been fixed.
+98-04-30 A bug when a name reference with a shorter name than
+ the variable it references was the subject of a compound
+ assignment has been fixed.
+98-04-30 A bug which in which assignment to array variables in
+ a subshell could effect the parent shell has been
+ fixed.
+98-04-30 read name?prompt was putting a 0 byte at the end of the
+ prompt on standard error.
+98-04-30 A bug in &#0091;&#0091; string1 &gt; string2 &#0093;&#0093; when ksh was run with -x
+ has been fixed.
+98-04-30 A bug in which the escape character was not processed
+ correctly inside {...} when brace expansion is enabled
+ has been fixed, for example {\$foo}.
+98-04-30 A bug in line continuation in here-documents has been
+ fixed.
+98-04-30 The default base when not specified with typeset -i is
+ 10 in accordance with the documentation. Previously,
+ the value was determined by the first assignment.
+98-04-30 A parsing bug in which a # preceded alphanumeric
+ characters inside a command substitution caused
+ a syntax error to be reported has been fixed.
+98-04-30 A bug in which a decimal constant represented as 10#ddd
+ where ddd was more than five digits generated a syntax
+ error has been fixed.
+98-04-30 A bug in here document expansion in which ${...} expansions
+ were split across buffer boundaries has been fixed.
+98-04-30 +The sh_fun() function now takes third argument which
+ is an argument list for the invoked discipline function
+ or built-in.
+98-04-30 +A callback function can be installed which will give
+ notification of file duplications and file closes.
+98-04-30 When ksh is compiled on systems that do not use fork()
+ current option settings where not propagated to sub-shells.
+
+97-06-30 --- Release ksh93f ---
+97-06-30 +Hostnames in addition to host addresses can be given in
+ /dev/tcp/host/port virtual file names.
+97-06-30 File name completion and expansion now quotes special
+ characters in file names from both emacs and vi edit modes.
+97-06-30 An empty for list behave like a for list with null expansions.
+ It produces a warning message with sh -n.
+97-06-30 +The code has been modified to work with EBCDIC as well as ASCII.
+97-06-30 A bug which would cause the secondary prompt to be
+ displayed when a user entered a literal carriage
+ return has been fixed.
+97-06-30 A bug which caused ksh read -s name to core dump was
+ fixed.
+97-06-30 A bug with the expansion of \} and \&#0093; inside double
+ quoted strings that also contained variable expansions
+ has been fixed
+97-06-30 Changes in the ksh93e point release caused autoload
+ functions invoked from within command substitution
+ to fail. This has been fixed.
+97-06-30 A bug in the processing of here-documents that could
+ prevent variable substitution to occur after $(...) command
+ substitution for long here documents has been fixed.
+97-06-30 A bug caused by a race condition that could cause SIGTERM
+ to be ignored by a child process has been fixed.
+97-06-30 A bug which prevented the startup of a coprocess immediately
+ after killing a running coprocess has been fixed.
+97-06-30 ulimit foobar, where foobar is not an arithmetic
+ expression, now gives an error message as it did with ksh88
+ instead of setting the file size limit to 0.
+97-06-30 A bug which could cause an interactive shell to terminate when
+ the last process of a pipeline was a POSIX function was fixed.
+97-06-30 A bug which could cause command substitution of a shell script
+ to core dump has been fixed.
+97-06-30 A security hole was fixed in suid_exec.
+97-06-30 Arithmetic functions such as pow() that take more than
+ one argument, did not work if arguments other than the
+ first contained parenthesized sub-expression.
+97-06-30 The error message from a script containing an incomplete
+ arithmetic expression has been corrected.
+97-06-30 A bug which caused a core dump on some machines when
+ the value of a name reference contained a positional
+ parameter and the name reference was not defined inside
+ a function has been fixed.
+97-06-30 Arithmetic expressions now correctly handle hexadecimal
+ constants.
+97-06-30 A bug in which integer variables could be expanded
+ with a leading 10# when declared with typeset -i
+ multiple times has been corrected.
+97-06-30 A bug in which IFS wasn't correctly restored when
+ set within command substitution has been fixed.
+97-06-30 The _ character is now considered as part of a word
+ with the M-f and M-b emacs directives as it was in ksh88.
+97-06-30 A bug in brace pattern expansions that caused expressions
+ such as {foo\,bar,bam} to expand incorrectly have been fixed.
+
+
+96-07-31 --- Release ksh93e ---
+96-07-31 +The math functions, atan2, hypot, fmod, and pow were added.
+96-07-31 +When a shared library is loaded, if the function lib_init()
+ is defined in the library, it is invoked the first time that
+ the library is loaded with builtin -f library.
+96-07-31 The k-shell information abstraction database option, KIA,
+ has been revamped.
+96-07-31 Empty command substitutions of the form $() now work.
+ whence -v foo now gives the correct result after calling
+ builtin -d foo.
+96-07-31 A bug in right to left arithmetic assignment for which
+ the arithmetic expression (( y = x = 1.5 )) did not
+ yield 1 for y when x was declared typeset -i was fixed.
+96-07-31 printf has been fixed to handle format containing &nbsp;
+ and/or &nbsp;145 correctly. In addition, characters following
+ %b in the format string are no longer displayed when
+ the operand contains <JOIN>.
+96-07-31 A bug in printf that could cause the %E format to
+ produce unnormalized results has been fixed.
+96-07-31 A bug which causes some arithmetic expressions to be
+ incorrectly evaluated as integer expressions rather
+ that floating point has been fixed.
+96-07-31 Functions defined inside a subshell no longer remain
+ defined when the subshell completes.
+96-07-31 The error message from sh -c ';echo foo' has been
+ corrected.
+96-07-31 The format for umask -S has been changed to agree
+ with the specification in the POSIX standard.
+96-07-31 A bug that caused side effects in subscript evaluation
+ when tracing was enabled for subscripts using ++ or --
+ has been fixed.
+96-07-31 To conform to the Posix standard getopts has been changed
+ so that the option char is set to ? when it returns with
+ a non-zero exit status.
+96-07-31 The handling of \} inside ${name...} has been fixed so
+ that the &nbsp;quotes the }.
+96-07-31 A bug that caused the read builtin to resume execution
+ after processing a trap has been fixed.
+96-07-31 &#0091;&#0091; -s file &#0093;&#0093; has been fixed so that if file is open
+ by ksh, it is flushed first.
+96-07-31 In some cases attributes and sizes for non exported
+ variables weren't being reset before running a script.
+96-07-31 The value of TMOUT was affected by changes make to
+ it in a subshell.
+96-07-31 The jobs command did not reflect changes make by
+ sending the CONT signal to a command.
+96-07-31 The error message for ksh -o unknown was incorrect.
+96-07-31 Functions invoked as name=value name, did not use
+ values from the calling scope when evaluating value.
+96-07-31 A bug in which the shell would reexecute previously
+ executed code when a shell script or coprocess was
+ run in the background has been fixed.
+96-07-31 A bug in which an empty here-document would leave
+ a file descriptor open has been fixed.
+96-07-31 A bug in which $(set -A array ...) would leave a
+ side effect has been fixed.
+96-07-31 A discipline function for a global variable defined
+ within a function defined with the function keyword,
+ incorrectly created a local variable of the same name
+ and applied the discipline to it.
+
+95-08-28 --- Release ksh93d ---
+95-08-28 The &nbsp;character was not handled correctly in replacement
+ patterns with ${x/pattern/replace}.
+95-08-28 A bug with read in which the line did not end with
+ a new-line has been fixed.
+95-08-28 A bug in file name generation which sometimes
+ appended a . for filenames that ended in / has
+ been fixed.
+95-08-28 +If a process is waited for after a status has
+ been returned by a previous wait, wait now
+ returns 127.
+95-08-28 A bug with hist (fc) -e which prevented a command
+ to re-executed after it had been edited has been fixed.
+95-08-28 A bug which prevented quoting from removing the meaning
+ of unary test operators has been fixed.
+95-08-28 A bug with typeahead and KEYBOARD traps with the
+ MULTIBYTE option set has been fixed.
+95-08-28 +Builtin functions can take a third argument which is
+ a void*.
+95-08-28 The nv_scan() function can restrict the scope of a walk
+ to the top scope.
+
+95-04-31 --- Release ksh93c ---
+95-04-31 The expansion of "$@" was incorrect when $1 was the null
+ string.
+95-04-31 A bug which could incorrectly report a syntax error in
+ a backquoted expression when a $ was preceded by \\
+ has been fixed.
+95-04-31 A bug which prevented the shell from exiting after
+ reporting an error when failing to open a script
+ has been fixed.
+95-04-31 A bug that could lead to memory corruption when a
+ large here document that required parameter or command
+ substitution was expanded has been fixed.
+95-04-31 A bug that could cause a core dump on some systems
+ after ksh detected an error when reading a function
+ has been fixed.
+95-04-31 A bug which could cause a coprocess to hang when
+ reading from a process that has terminated has been fixed.
+95-04-31 A bug which caused a script to terminate when set -e
+ was on and the first command of and &amp;&amp; or || list
+ failed has been fixed.
+95-04-31 A bug with here documents inside $(...) when the delimiter
+ word is an identifier has been fixed.
+95-04-31 A bug which caused $0 to display the wrong value when
+ a script was invoked as an argument to the . command
+ and the eval command has been fixed.
+95-04-31 A bug that could cause the built-in sleep to hang
+ has been fixed.
+95-04-31 A bug introduces in 12/28/93b which caused the backslash
+ to be removed when it was followed by digit inside double
+ quotes in some instances has been fixed.
+95-04-31 A bug which could cause a core dump if ksh was invoked with
+ standard input closed has been fixed.
+95-04-31 A bug which could cause a core dump if typeset -A was
+ specified for an existing variable has been fixed.
+95-04-31 Variables that were unset but had attributes such as readonly
+ and export were not listed with readonly, export and typeset.
+95-04-31 Several problems with signals have been fixed.
+95-04-31 A bug which prevented ulimit -t from working has been fixed.
+ Also, a bug in which failed ulimits could cause a core dump
+ has also been fixed.
+95-04-31 A bug in expansion of the form ${name/#pattern/string} and
+ ${name/%pattern/string} has been fixed.
+95-04-31 A bug which caused read -r on a line that contained only
+ blanks to get a non-null value has been fixed.
+95-04-31 A bug introduced in the 'a' point release in which
+ ${x='\'} expanded to &nbsp;when x was unset has been fixed.
+95-04-31 A bug which prevented a trap on EXIT from being executed
+ when the last command in a script was a function invocation
+ has been fixed.
+95-04-31 A bug which caused an interactive shell ignore input when
+ standard error was redirected to a file with exec,
+ and then restored with exec 2&gt;&amp;1 has been fixed.
+95-04-31 An interactive shell turns on monitor mode even when
+ standard error has been redirected to a file.
+95-04-31 A bug which could cause standard input to be incorrectly
+ positioned for the last command of a script has been fixed.
+95-04-31 A bug in the edit modes which allowed walking back in
+ the history file for more than HISTSIZE commands has
+ been fixed.
+95-04-31 A bug which could cause a core dump if variable TMPDIR was
+ changed between two command substitutions has been fixed.
+95-04-31. A bug which prevented a trap on EXIT from being cleared
+ has been fixed.
+95-04-31 A bug fixed for the v directive in vi MULTIBYTE has been
+ fixed.
+95-04-31 Code to for IFS handling of multibyte characters has
+ been added.
+95-04-31 The displaying of multibyte strings in export, readonly,
+ typeset, and execution traces has been fixed.
+95-04-31 Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+95-04-31 Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+95-04-31 A few changes have been made to the name-value library
+ that affect built-ins that use disciplines. The
+ changes allow disciplines to be shared by variables
+ and should make it possible to add new disciplines
+ without recompilation.
+95-04-31 +The name-value library interface has undergone significant
+ change for this revision. See the new nval.3 man page.
+
+94-12-31 --- Release ksh93b ---
+94-12-31 +Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+94-12-31 +If IFS contains two consecutive identical characters belonging
+ to the &#0091;:space:&#0093; class, then this character is treated as
+ a non-space delimiter so that each instance will delimit
+ a field. For example, IFS=$'\t\t' will cause two consecutive
+ tabs to delimit a null field.
+94-12-31 +The getopts command has a -a name option that specifies a
+ name that will be used for usage messages.
+94-12-31 A bug which caused unset RANDOM to dump core has been
+ fixed.
+94-12-31 A bug which prevented return for terminating a profile
+ or ENV file has been fixed.
+94-12-31 A bug which prevented standard input from being
+ directed to /dev/null for background jobs when
+ monitor mode was turned off has been fixed.
+94-12-31 Statements of the form typeset -options var&#0091;expr&#0093;=value
+ did not perform substitutions on expr as expected.
+94-12-31 A bug which prevented the shell from sending a HUP
+ signal to some background jobs that were not disowned
+ has been fixed.
+94-12-31 A bug which allowed a script to trap signals that are
+ ignored at the time that the shell was invoked by exec
+ has been fixed.
+94-12-31 A bug which could cause a core dump when a discipline
+ function was unset within a discipline was fixed.
+94-12-31 The typeset builtin now accepts a first argument of
+ + or - for compatibility with ksh88.
+94-12-31 For compatibility with ksh88, the results of expansions
+ of command arguments will treat the extended character
+ match characters ()|&amp; as ordinary characters.
+94-12-31 A bug which caused read to fail on a file that was
+ open for read/write with &lt;&gt; when the first operation
+ was print or printf has been fixed.
+94-12-31 When a job is suspended, it is put on the top of
+ the job list as required by the POSIX standard.
+94-12-31 The value of OPTARG when an option that required
+ an argument but didn't have one was incorrect in the
+ case the the option string began with a :.
+94-12-31 A bug which caused the terminal to get into a bad
+ state with some KEYBD traps in vi-mode has been fixed.
+94-12-31 A bug which caused an invalid trap to cause a script
+ to terminate, rather than just return an error, has
+ been fixed.
+94-12-31 Backreferencing sub-expressions in patterns and replacement
+ strings now works.
+94-12-31 A bug in chmod which caused the -R option to fail has
+ been fixed.
+94-12-31 +More signal names have been added for Solaris
+
+94-06-30 --- Release ksh93a ---
+94-06-30 An expansion bug which causes portions of a word after
+ a $((...)) expansion that contains a nested $var expansion
+ to be lost has been fixed.
+94-06-30 A bug that caused a core dump when a script that did not
+ have PWD set and did a cd inside command substitution
+ has been fixed.
+94-06-30 A bug which caused a core dump on some machines when
+ the LANG variable was assigned to has been fixed.
+94-06-30 A bug which incorrectly handled set disciplines that
+ performed arithmetic evaluation when the discipline
+ was called from the arithmetic evaluator has been fixed.
+94-06-30 A bug caused by an EXIT trap inside a function that
+ was executed in a subshell was fixed.
+94-06-30 If foo is a function, and not a program, then command foo
+ now reports that foo isn't found rather than invoking foo.
+94-06-30 The previous version incorrectly listed -A as an
+ invocation option. The -A option is only for set.
+94-06-30 A bug was fixed which caused ksh to loop when execution trace
+ was enabled and the PS4 prompt required command substitution.
+94-06-30 A bug which could cause the job control switch character
+ to be disabled when a script that enabled monitor mode
+ terminated was fixed.
+94-06-30 A bug in the macro expansion global replacement operator //,
+ when the pattern began with a &#0091; or +( has been fixed.
+94-06-30 A bug which prevented ~ expansion from occurring when
+ it was terminated with a colon inside an assignment
+ has been fixed.
+94-06-30 A bug in the dot command which prevented autoload functions
+ from working has been fixed.
+94-06-30 A bug which caused a variable to be unset if the
+ its value were expanded inside a set discipline has
+ been fixed.
+94-06-30 Whence -a now longer reports that a defined function
+ is undefined.
+94-06-30 A bug on some systems in which $0 would be incorrect
+ in scripts invoked by name has been fixed.
+94-06-30 Here documents with an empty body now work.
+94-06-30 A bug which disabled argument passing and resetting
+ of options for a script invoked by name inside a
+ function has been fixed.
+94-06-30 A bug in which an EXIT trap set the caller of a function
+ would be executed if a command called inside a function
+ was not found has been fixed.
+94-06-30 A bug which allowed a script to trap signals that are
+ ignored at the time that the shell was invoked has
+ been fixed.
+94-06-30 A bug which caused 2&lt;&amp;1- when applied to a shell built-in
+ to leave standard input closed has been fixed.
+94-06-30 A bug which caused the shell to incorrectly parse
+ $() command substitutions with nested case statements
+ has been fixed.
+
+
+</PRE>
+<P>
+<P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="libast changes">libast changes</A></H3></FONT></FONT></CENTER>
+<PRE>
+
+12-03-10 misc/optget.c: HELP_index for "PLUGIN" too
+12-02-29 include/shcmd.h: PLUGIN_VERSION 20111111 for cdt disc/meth change
+12-02-29 comp/spawnveg.c: fix sigcritical() to include waitpid() for internal child
+12-02-29 malloc.c: make __malloc_hook initialization thread safe
+12-02-24 comp/iconv.c: fix winix UTF-8 vs UCS-2 over-conversion
+12-02-24 astsa/*.h: clean up header guards
+12-02-24 astsa/astsa.omk: clean up standalone old make makefile interactions
+12-02-21 misc/cmdarg.c: fix bug that set argv&#0091;0&#0093;
+12-02-10 sfvprintf.c: fix 1 byte too long buffer access
+12-02-07 malloc.c/features/vmalloc: add gnu __malloc_hook tests
+12-02-06 vmmopen.c: fix ALIGN vs sys/param.h macro conflict
+12-02-02 astlicense.c: add license.component for component-specific licenses
+12-01-31 spawnveg.c: fix transient bug that made invalid setpgid() call
+12-01-27 pathpath.c: fix buffer size math when internal allocation requested
+12-01-24 malloc.c: fix _vmkeep() bug that did not return previous state
+12-01-23 malloc.c: add VMALLOC_OPTIONS=break to try sbrk() block allocator first
+12-01-21 astlicense.c: option style only overrides default license.type
+12-01-18 malloc.c: disable multiple regions for tracing or !vmbest or ASO_SIGNAL
+12-01-12 sfpkrd.c: add __sun I_PEEK+rsh runtime workaround
+12-01-10 shcmd.h: void* =&gt; Shbltin_t*
+12-01-10 tmxdate.c: handle { n&gt;=1000 } TM_PARTS
+11-12-21 plug up some meory links -- thanks mhlavink
+11-12-21 vmprivate.c: enclose VM_NONMEM exception in CLRLOCK(vm,0) ... SETLOCK(vm,0)
+11-12-13 aso: in -lposix for uwin, not -last -- just like vmalloc
+11-12-13 sfpoll.c: all streams SF_IOINTR =&gt; don't ignore EINTR
+11-12-13 sfdcslow.c: set SF_IOINTR
+11-12-09 malloc.c: add _vmkeep() for setlocale() intercept _SYS_setlocale_free_OK
+11-12-04 sfio: _Sfmaxr=0 (unlimited) by default; use ulimit -M|-d or SFIO_OPTIONS
+11-12-01 aso: sync to new api
+11-11-11 optget.c: move .TH to the top for --nroff to get our macros first
+11-11-11 aso,cdt,vmalloc: resync with kpv
+11-11-11 cdt: preserve bits and Dt_link_t for CDT_VERSION &lt; 20111111
+11-10-24 sfvprintf.c: %.-ns truncate from left to n chars
+11-10-21 sfvprintf.c: fix %0s (no width) core dump
+11-10-10 aso: add _WIN32 support
+11-09-26 vmalloc: sync with kpv
+11-08-29 features/{dirent,wchar,wctype}: eliminate #include with no header
+11-08-25 #pragma prototyped tweaks -- sun4 is dead, long live sun4
+11-08-25 ftwalk.c: FTS_SLNONE =&gt; FTW_SL
+11-08-11 features/wchar: fix #include _nxt_wchar for K&amp;R C
+11-08-04 optget.c: tweak --html rendering
+11-07-24 mime.c: add %(default)&#0091;st&#0093; default if arg == ""
+11-07-21 setlocale.c: fix debug locale to treat "&lt;&lt;" as two single byte chars
+11-06-14 spawnveg.c: pgid -1: new session -2: setpgrp()&amp;&amp;tcsetpgid()
+11-06-14 pathprog.c: add darwin _NSGetExecutablePath
+11-05-14 features/common,features/align.c: { _X86_ _X64_ } conditionals for generic uwin
+11-05-13 tm/tminit.c: tweak tzname&#0091;&#0093; prototype
+11-05-09 astlicense.c: add ". file" parent-relative include and depth 4 input stack
+11-05-05 cmdarg: update to cmdopen_20110505 api
+11-05-03 sfio/sfclose.c: make sure close() errors propagate to sfclose() return value
+11-04-20 port/astlicense.c: add { id name } keys
+11-04-15 fmtdev.c: fix to work for non-{blk,chr} special
+11-04-12 stk: change size args to size_t and stseek() offset to ssize_t
+11-04-12 sfio: sync with kpv to optimize large SF_STRING sfputr() buffer allocation
+11-03-28 misc/fts.c: fix FTS_SLNONE logic to set it when it should!
+11-03-17 misc/stk.c: fixed bug that could delete an active stack frame
+11-03-10 sfio/sfvprintf.c: add %0&lt;width&gt;s to preserve &lt;width&gt; trailing chars in string arg
+11-03-09 misc/magic.c: add %d...%s where if %d==1 then %s=="" else %s=="s"
+11-03-09 misc/magic.tab: add windows ico
+11-02-08 misc/stk.c: change STK_FSIZE to (1024*sizeof(char*)) for 64 bit normalization
+11-02-02 sfio/sfmode.c: don't call sfsetbuf() on unbuffered stream to make it unbuffered
+11-02-02 features/wchar: handle hp.ia64 va_list interactions
+11-02-02 comp/omitted.c: fix mismatch between stat() vs _stat()
+11-01-31 std/wctype,features/wctype: add to handle &lt;wchar.h&gt; interactions
+11-01-28 add -lw for ancient sunos
+11-01-28 include/magic.h,misc/magic.c: add MAGIC_ALL
+11-01-27 tm/tmxfmt.c,tmpoff.c: %_z for SHH:MM
+11-01-25 features/wchar: change &lt;wctype.h&gt; &lt;wchar.h&gt; ordering
+10-12-24 sfstrtof.h: fix thousand grouping bug that did not check last group
+10-12-21 pathkey.c: add win32 { /32 /64 } preroot to hash
+10-12-09 pathprog.c: handle intermediate path != '* and fix invalid pathpath() call
+10-12-01 astconf.c: fix look.standard undefined variable reference
+10-12-01 sfset.c: SF_LINE|SF_WCWIDTH =&gt; no need for sfsetbuf() to call isatty()
+10-12-01 sfsetbuf.c: cache /dev/null &lt;dev,ino&gt; to cut down /dev/null stat()'s
+10-12-01 optget.c: delay dictionary initialization until needed
+10-11-30 malloc.c: drop { VMDEBUG VMETHOD VMPROFILE VMTRACE } env checks
+10-11-30 port/astconf.c: eliminate esaccess() calls for OP_universe checks
+10-11-24 regcomp.c: &#0091;&#0091;=&#0093;=&#0093;&#0093; must at least match itself in non-C locales
+10-11-23 glob.h,glob.c: add GLOB_GROUP =&gt; REG_SHELL_GROUP
+10-11-20 glob.c: handle mode switches across /
+10-11-19 regcomp.c: REG_SHELL =&gt; REG_CLASS_ESCAPE
+10-11-16 vmalloc.h: add VMFL tracing to vmstrdup()
+10-11-16 ast.h: simplify VMDEBUG _BLD_DEBUG and VMFL logic
+10-11-12 tm/tmlocale.c: ast TM_* extensions default to C locale
+10-11-10 regex/regnexec.c,vmalloc/vmstat.c: eliminate strict-aliasing puns
+10-10-20 misc/translate.c: change debug translation to drop " in (a,b,c,"d")
+10-10-10 misc/glob.c: drop ancient D_FILENO(d)!=0 test and trust readdir()
+10-10-06 misc/translate.c: fix "debug" locale logic
+10-10-04 misc/magic.c: fix magic() skip check to honor the continuation
+10-10-04 regex/regcoll.c: add wchar_t* args to regcollate(), drop ucs name lookup
+10-09-28 comp/setlocale.c: add utf8_wctomb()
+10-09-28 string/chresc.c,regex/regcoll.c: fix \S&#0091;.X.&#0093; (\C&#0091;.X.&#0093; never worked!)
+10-09-24 string/chresc.c: \Cc for control c, \S&#0091;.X.&#0093; for collating symbol X
+10-09-24 string/chresc.c: { <JOIN>c &#0092; } deprecated
+10-09-22 regex/regcomp.c: fix off-by-one collation class allocation bug
+10-09-20 regex/regclass.c: fix CTYPES off-by-one bug
+10-09-14 comp/conf.sh: const int conf_elements, prefix_elements;
+10-09-08 add features/sizeof =&gt; ast_sizeof.h
+10-08-31 comp/getopt&#0091;l&#0093;.c: export functions for dlls
+10-08-25 port/lc.c: add features/locale check for canonical UTF-8 spelling
+10-08-20 include/ast.h: add export plugin_version() prototype
+10-08-20 comp/conf.tab: add SF_BUFSIZE
+10-08-11 misc/conformance.c: conformance(0,0) =&gt; "standard"
+10-08-11 misc/conformance.c: check ast_env_serial for dynamic astconf() changes
+10-08-11 port/lcgen.c: remember to fudge Table_t.count for synthesized entries
+10-08-04 include/ast.h,comp/setlocale.c: add { debug C.UTF-8 } mbalpha() mbwidth()
+10-08-02 misc/translate.c: add NLSPATH message cache check
+10-07-29 string/fmtint.c: fix nasty bug that rendered "1000" as "1"
+10-07-27 setlocale,lsgen,localeconv: handle C vs C_EU decimal thousands sep
+10-07-26 misc/optget.c: fix interaction with nested plugin/builtin calls
+10-06-29 string/strtoi.h: strton() multiplier 1 =&gt; power of two suffix
+10-06-28 features/wchar: handle systems that require __va_list =&gt; va_list
+10-06-28 comp/conf.tab: another PID_MAX tweak -- default to 99999 for most
+10-06-28 port/astconf.c: lone "CONFORMANCE = standard" =&gt; all defaults standard
+10-06-25 misc/optget.c: avoid sfprints() call during initialization
+10-06-01 features/api, ast_api.h: formalized forwards/backwards api compatibility
+10-06-01 _AST_API=20100601: add size_t args for all path*() output buffers
+10-06-01 comp/setlocale.c: handle C.UTF-8 test locale
+10-06-01 include/mc.h: add size_t to mcfind() for result buffer (internal api)
+10-06-01 use strlcpy() instead of strncpy()
+10-05-28 include/ast_version.h: add AST_PLUGIN_VERSION for dllplugin()
+10-05-28 include/shcmd.h: add SH_PLUGIN_VERSION for dllplugin()
+10-05-28 misc/conformance.c: add conformance(3)
+10-05-28 misc/optget.c: add &#0091;(id1|id2)...&#0093; conformance("id1|id2",0) conditionals
+10-05-25 include/sfhdr.h: adjust SF_NMAP according to _ptr_bits
+10-05-25 include/shcmd.h: add sh_builtin() macro for lib_init() table initialization
+10-05-21 misc/optget.c: --html \bfoo::bar(&#0091;&#0091;:digit:&#0093;&#0093;&#0091;&#0091;:upper:&#0093;&#0093;*) =&gt; foo-bar.html
+10-05-15 include/proc.h,misc/procopen.c: add PROC_ORPHAN
+10-05-09 misc/optget.c: add --???MAN&#0091;section&#0093; --???SECTION
+10-05-07 sfio,stdio: fix all snprintf() variants to handle buf==0 and/or n==0
+10-05-04 string/fmtesc.c: add mb iswsoace() and iswcntrl() quoting checks
+10-05-03 fix LC_MESSAGES catalog lookup bugs, check for $set==3, accept $set==1
+10-04-30 string/chresc.c: add chrexp() for FMT_EXP_*
+10-04-30 string/stresc.c: add strexp() for FMT_EXP_*
+10-04-30 string/chresc.c: fix \uXXXXY bug that consumed Y
+10-04-22 misc/optget.c: check for html entities in &lt;A name="..."&gt;
+10-04-22 misc/getcwd.c: add features/syscall check for SYSGETCWD() { linux solaris }
+10-04-22 string/stresc.c: wide chars absent locale guidance default to UTF-8
+10-04-12 port/mnt.c: favor bsd getfsstat() over getmntinfo()
+10-04-11 string/strtoi.h: k (1000) and ki (1024) now differentiated
+10-04-10 misc/recstr.c: fix 'd&#0091;delimiter&#0093;' parse
+10-04-08 include/vmalloc.h,vmalloc/vmstat.c: add Vmstat_t.mode region mode bits
+10-04-05 misc/fts.c: drop 1997-01-07 fts_open()=0 is one file and stat() fails
+10-04-05 misc/optget.c,optlib.h: add Optpass_t.release for --nroff .TH
+10-04-02 misc/optget.c: fix $'&#0091;-n?..&#0093;' --version bug
+10-04-02 regex/regcomp.c: ~(X) =&gt; REG_EXTENDED|REG_AUGMENTED, ~(PU) instead of ~(U)
+10-03-24 misc/procopen.c: add PROC_FD_CTTY(fd)
+10-03-24 path/pathtemp.c: fix pointer =&gt; int casts
+10-03-15 regex/regcache.c: fix 1 byte buffer overflow (didn't count trailing &nbsp;)
+10-03-08 features/tvlib: fix utimensat probe to include all macros/structs
+10-03-07 features/lib: change stream_peek to test pipes only
+10-03-07 string/strelapsed.c: fix next char return overrun
+10-03-06 tm/tvtouch.c: use runtime fallback if utimensat() fails with ENOSYS
+10-03-05 path/pathtemp.c: add pfx /seed for regression testing
+10-03-04 vmalloc/vmwalk.c: add user supplied handle arg
+10-03-04 path/pathtemp.c: properly handle mktemp()-style *+(X) templates
+10-03-03 include/ast_getopt.h: remove NULL guard - _AST_GETOPT_H now handles it
+10-02-24 comp/getopt.h: fix ast_std.h interactions
+10-02-24 vmalloc/malloc.c: empty { VMALLOC_OPTION VMDEBUG ... } =&gt; no debug!
+10-02-02 string/base64.c: fix corner case output buffer overflow
+10-02-02 features/fs: sys/mnttab.h requires stdio.h on some systems!!
+10-02-01 misc/optget.c: uppercase --html heading -- doh
+10-01-29 misc/optget.c: &#0091;+NAME?...&#0093; overrides error_info.id for &gt;= STYLE_man
+10-01-25 vmalloc/vmprivate.c: fix seg ptr initialization bug (24 years old!!)
+10-01-20 misc/optget.c: handle nested {...} rendering
+10-01-20 misc/state.c: add ast.version for runtime api version
+10-01-20 port/astconf.c: "_AST_VERSION" now returns ast.version
+10-01-20 include/ast_std.h: add ast.version for runtime api version
+10-01-19 astlicense.c: add epl
+10-01-01 vmalloc: VMALLOC_OPTIONS env var for all runtime options
+10-01-01 include: change some &lt;ast.h&gt; refs to less intrusive &lt;ast_*.h&gt;
+10-01-01 setlocale.c,translate.c,fmterror.c: AST_LC_internal retains prev state
+10-01-01 comp/setlocale.c: AST_LC_setenv defers to LC_ALL (for sh)
+10-01-01 ast_std.h: add { AST_LC_internal AST_LC_setenv }
+09-12-24 comp/setlocale.c: fix setlocale(LC_ALL,"") when already initialized
+09-12-17 misc/optget.c: handle mixed solaris usage="x:f:(in)yo:(out)"
+09-12-11 regex/regcomp.c: posix semantics for &#0091;z-a&#0093;
+09-12-11 regex/regcomp.c: fix BRE/ERE ^^ logic
+09-12-11 regex/regcomp.c: fix regcomb() for REG_LEFT|REG_RIGHT
+09-12-11 regex/regcomp.c: bm complete=0 if REX_END
+09-12-11 comp/sigflag.c: add with npt check in features/sig.sh
+09-12-11 tm/tminit.c: fix _tzset_environ logic
+09-12-09 tm/tmlocale.c: include "ast_nl_types.h" to pull nl_langinfo in!
+09-12-04 features/options: add "opt map-libc" check
+09-12-03 tm/tmxdate.c: fix 'next month final day' for dec -&gt; jan
+09-11-21 misc/magic.tab: add gimp XCF
+09-11-20 vmalloc/vmtrace.c: add pid to assertion disgnostics
+09-11-11 regex.h,regcomp.c: add REG_CLASS_ESCAPE, &nbsp;inside &#0091;...&#0093; literal by default
+09-11-03 regex/regcache.c: change to variable length pattern strings
+09-10-28 include/error.h: fix ERROR_translate() arg parens
+09-10-26 port/lcgen.c,comp/setlocale.c: handle LANG init after LC_* already defined
+09-10-05 _sfopen.c: add but ignore 'F' flags for stdio compatibility
+09-09-28 fts.h,ftwalk.h,fts.c: promote { namelen pathlen level } to (s)size_t
+09-09-28 locales: add AST_LC_LANG for $LANG
+09-09-28 setlocale.c: fix logic for dynamic { LANG LC_ALL LC_* } changes
+09-09-17 include/sfio.h,sfio/sfwalk.c: add sfwalk()
+09-09-09 sfio/sfputr.c: add SIGPIPE hang fix
+09-08-24 sfio/sfreserve.c: fix SF_UNBOUND logic with pushed streams
+09-08-18 include/ast_std.h,ast.h: add ast.mb_sync to sync mbchar() after error
+09-08-17 comp/setlocale.c: add AST_LC_utf8 and { utf8_mbtowc() utf8_mblen() }
+09-08-11 comp/setlocale.c: treat "en"/"en_US" AST_LC_MESSAGES as "C"/"POSIX"
+09-08-10 vmalloc/vmhdr.h: add user-defined _AST_PAGESIZE and computed VMHEAPINCR
+09-08-09 comp/conf.tab: add NPROCESSORS_MAX
+09-07-29 astlicense.c: fix first name=value logic error
+09-07-22 string/fmtip6.c: don't drop trailing 0 in 44::1:0:0
+09-06-30 port/astconf.c: standard PATH_RESOLVE is "physical" (not "metaphysical")
+09-06-19 vmalloc: sync with kpv
+09-06-19 include/shcmd.h: add sh_context(p) cast
+09-06-11 misc/magic.tab: differentiate pc 386 32/64 bit dll/exe/obj
+09-06-06 port/astconf.c: fix look-&gt;name null pointer reference
+09-06-05 port/astconf.c: fix 'UNIVERSE = value' synthesize logic
+09-05-25 tm/tmxduration.c: add
+09-05-08 comp/syslog.c: add _UWIN /var/log/syslog preference
+09-05-01 comp/setlocale.c: fix _UWIN intercepts to return NiL on unknown locales
+09-04-27 sfio/sfpool.c: fix bug that did not return pool on delete
+09-04-22 include/regex.h,regex/regcomp.c: add REG_REGEXP &lt;regexp.h&gt; compatibility
+09-04-15 tm/tmxdate.c: handle "4th thursday in november"
+09-03-31 string/strvcmp.c,string/strnvcmp.c: add version strcmp(3)
+09-03-31 string/strpcmp.c,string/strnpcmp.c: add path prefix strcmp(3)
+09-03-29 misc/optget.c: clean up num = number casts
+09-03-04 tm/tmxmake.c: add tmxtm() with zone override
+09-03-03 tm/tmxfmt.c: add %(...)&lt;c&gt;, specifically %(...)z for output zone
+09-02-22 tm/tmxdate.c: add iso P... durations
+09-02-02 path/pathprog.c: add
+09-02-02 misc/opthdr.h,optget.c: fix flags mixup, handle old '-' as option
+09-02-02 sfio/sfprints.c: fix sfvaprints() return value to not count trailing '&nbsp;'
+09-02-02 misc/cmdarg.c: handle !defined(ARG_MAX)
+09-02-02 port/astconf.c: fix UNIVERSE overwrite of null&#0091;&#0093; value!
+09-01-31 features/sys: drop header sys/localedef.h
+09-01-28 include/fs3d.h,misc/fs3d.c: mount() =&gt; fs3d_mount() for diff std prototypes
+09-01-14 misc/fts_open.c: delay top list reorder until first fts_read()
+09-01-14 include/ls.h: LS_W_INUMBER =&gt; 9 to accomodate large st_ino
+09-01-14 misc/optget.c: expand STYLE_usage input text
+09-01-09 features/uwin,stdio/_stdfun.c: iffe for _p__iob and __p__iob
+09-01-09 misc/magic.tab: add ISO filesystem image entries
+09-01-07 string/strtoi.c: strtol() etc. do not consume &#0091;lLuU&#0093; suffix -- thanks jkf
+09-01-07 sfio/sfstrtof.h: strtod() etc. do not consume &#0091;fFlL&#0093; suffix -- thanks jkf
+09-01-05 string/strlcat.c: fix logic to match docs (not that easy)
+08-12-30 tm/tmxdate.c,include/tm.h: add TM_WORK { "workday" "working" "work" }
+08-12-28 sfio/sfcvt.c: fix 'a' format rounding
+08-12-21 tm/tmdata.c: add 2008-12-31+23:59:60-0000 leap second event
+08-12-19 tm/tmxdate.c: check for dates near the epoch rolling back to the future
+08-12-19 tm/tmxfmt.c: change %s for now==0 to be the epoch
+08-12-07 include/ast_std.h,misc/getenv.c: no _ast_getenv for uwin ast54 compatibility
+08-12-07 tm/tmxfmt.c: add %&#0091;_&#0093;&#0091;EO&#0093;K for &#0091;space pad&#0093; &#0091;full|long&#0093; iso
+08-12-07 sfio/sfvscanf.c: fix ok&#0091;&#0093; short by one allocation
+08-12-07 comp/setlocale.c: fix off by one composite initialition loop test
+08-12-07 path/pathkey.c: fix off by one loop test
+08-12-04 vmalloc/vmbest.c: catch sbrk() wraparound
+08-12-04 comp/spawnveg.c: clean up attrs on failure too
+08-11-04 regex/regcomp.c: fix locale &#0091;!-...&#0093; and &#0091;^-...&#0093; re-initialization
+08-11-04 stdio: add flockfile.c ftrylockfile.c funlockfile.c
+08-10-24 port/astconf.c: handle multiple/trailing '/' in universe initialization
+08-09-10 misc/magic.c: handle old vcodex() indices
+08-09-10 sfio/sfvprintf.c: drop SF_WCWIDTH, use %Lc or %Ls instead
+08-09-05 Makefile: ibm.risc joins the :NOOPTIMIZE: crowd
+08-09-04 regex/regnexec.c: fix nested delimiter match beyond end of subject
+08-08-20 misc/fts.c: fix st_nlink stat() optimization logic
+08-08-19 sfio/sfpkrd.c: workaround macosx recv(PEEK) data consumption on non-socket
+08-08-19 strn?tol?d: handle long double with smaller exponent range than double
+08-08-18 sfio/sfcvt.c: eliminate excessive multiplies and integral overprecision
+08-08-11 tm/tmxfmt.c: handle %10N and %010N
+08-08-06 include/shcmd.h: add 'int invariant;' for builtin invariant arg count
+08-08-05 features/ndbm: favor sleepycat ndbm compatibility
+08-07-21 include/glob.h,misc/glob.c: GLOB_STARSTAR only forces lstat on chdir
+08-07-17 sfio: sync with kpv
+08-07-17 misc/optget.c: call astwinsize() each time terminal width required
+08-07-16 sfio/sfvscanf.c: fix %% to skip leading space per posix
+08-07-16 vmalloc/vmbest.c: add VMCHECK=m, VM_mmap to favor mmap() alloc
+08-07-16 features/stdio,stdio/f(read|write).c: size_t return value!! ouch
+08-06-24 tm/tmxfmt.c: fix %z to handle tm_isdst -- doh
+08-06-24 misc/astintercept.c,misc/getenv.c: split from misc/setenviron.c
+08-06-17 misc/setenviron.c: add { astintercept() getenv() }
+08-06-09 tm/tmlocale.c: use _DATE_FMT if defined for TM_DEFAULT
+08-06-06 misc/optget.c: handle sub-component about details
+08-06-04 misc/optget.c: fix &#0091;-n?..#0093; version parse
+08-06-04 include/debug.h,misc/debug.c: merge with kpvdebug.h
+08-06-02 features/ndbm: add to tame dbmlib.iffe replication
+08-06-01 comp/resolvepath.c,realpath.c: fix resolvepath() return value type
+08-05-22 tm/tmxdate.c: fix a few ordinal/last/this/next bugs
+08-05-18 string/fmtre.c: fix omitted stack var initialization bug
+08-05-14 regex/regcomp.c,regcoll.c: fix UTF-8 collation sequence logic
+08-05-11 tm/tmxfmt.c: :NOOPTIMIZE:, otherwise %Q/../../ fails
+08-05-01 tm/tmxdate.c: mon 1..12 =&gt; mon&#0091;13&#0093; -- doh
+08-04-30 misc/glob.c,reegex/regcomp.c: ~(R) =&gt; ~(O) to avoid pcre clash
+08-04-24 port/astconf.c: 'name = value' does assignment without system init
+08-04-15 port/astconf.c: SC#N treated like 'SC(N)'
+08-04-14 misc/optget.c: clean up nroff output
+08-04-01 port/astconf.c: add RELEASE =&gt; /proc/version fallback
+08-03-30 misc/optget.c: &#0091;-n&#0093;... to enable -number &amp; +number options
+08-03-06 misc/optget.c: ---* and +++* are now operands
+08-03-06 misc/errorx.c: fix old error_info.translate workaround
+08-02-05 regex/regcomp.c: allow REG_SHELL {,n}... =&gt; {0,n}...
+08-02-27 misc/stk.c: top element during allocation relocated to top
+08-02-18 include/ip6.h,string/strtoip6.c,fmtip6.c: add ipv6 addr support
+08-02-14 regex/regsubexec.c: fix null match (tricky)
+08-02-14 regex/regsubcomp.c: fix SRE to match ksh
+08-02-11 comp/spawnveg.c: return proper errno on &#0091;v&#0093;fork() failure
+08-02-11 tm/tmxdate.c,tmdata.c: handle more ISO 8601:2000 forms
+08-02-02 regex/reglib.h: add REGMULTIREF to REG_COMP
+08-02-02 string/strmatch.c: fix str="" pat="" sub values
+08-01-31 comp/conf.sh,conf.tab: handle /bin/sh &nbsp;in read data, redir subshell
+08-01-18 misc/magic.tab: amd-x68, 64-bit =&gt; x86-64
+08-01-18 string/strnton.c,strntonll.c: add
+07-12-10 string/strelapsed.c: "0" is a valid elapsed time!
+07-12-02 sfio/sfreserve.c: preserve SF_SHARE sfrd() via sfreserve(f,0,0)
+07-11-21 comp/setlocale.c: add sjis_mbtowc() to work around &#0091;\~&#0093; translation
+07-11-15 features/signal.c: RT(1) .. RT(MAX-1) =&gt; RTMIN+1 .. RTMAX-1
+07-11-14 features/float: favor sscanf() due to gnu strto&#0091;l&#0093;d() nan bugs
+07-10-31 regex/regcomp.c: fix REX_COLL_CLASS node allocation size
+07-10-31 sfio/sfcvt.c: use signbit() if available
+07-10-31 features/isoc99: _ISOC99_SOURCE tests
+07-10-31 port/astmath.c: add -DN=8 for signbit()
+07-10-31 sfio/sfstrtod.h: don't forget about -0.0
+07-10-26 features/map.c: add { optopt optarg optind opterr }
+07-10-26 features/stdio: add _filbuf =&gt; _ast__filbuf
+07-10-26 comp/getsubopt.c: fix #undef that interfered with &lt;ast_map.h&gt;
+07-10-26 regex/regcomp.c: fix bug that missed ')' in ~(F)...
+07-10-12 port/astconf.c: fix CONF_ALLOC 16 bit overflow
+07-10-12 misc/fts.c: fix fts_close() to free the handle -- doh
+07-10-11 comp/setlocale.c: second and subsequent setlocale(*,"") reverts to previous
+07-10-11 path/pathprobe.c: add vfs ST_NOSUID check
+07-10-10 comp/conf.tab: add a few more xpg6 deferrals
+07-09-28 astsa: update to share with mainline src via _PACKAGE_astsa
+07-09-25 sfio/sfgetr.c: no limit on string stream line size
+07-09-25 sfio/sfextern.c: increase _Sfmaxr to 256*1024
+07-09-18 misc/procopen.c: tighten up SIGCHLD logic between parent/child
+07-09-18 misc/signal.c: unblock SIG_DFL after setting handler, sig&lt;0 =&gt; don't unblock
+07-09-13 misc/fs3d.c: no $LD_PRELOAD =&gt; no 3d and avoids invalid mount(2) call
+07-09-11 vmalloc: vmstat(0,0)==1 =&gt; region in use, drop VM_primary|VM_secondary
+07-09-05 misc/recstr.c: handle &#0091;lL&#0093; gobbled by strtol() -- ouch
+07-08-17 path/pathprobe.c: handle '\r' in VERSION string
+07-07-17 regex/regcache.c: regcache(0,n,0) extends cache to size n (no shrinking)
+07-07-16 tm/tmdata.c: add 2005-12-31, drop 1999-12-31 (where did that come from?)
+07-05-21 tm/tmxfmt.c,tmxscan.c: %F =&gt; %L (TM_DEFAULT); %F =&gt; %Y-%m-%d
+07-05-15 sfio/sfvprintf.c: %h? and SFFMT_SHORT =&gt; raw bytes
+07-05-09 features/signal.c,features/siglist: use kill -l &amp; strsignal()
+07-04-25 misc/optctx.c: add for opt_info switching
+07-04-24 misc/cmdarg.c,include/cmdarg.h: add CMD_CHECKED, CMD_SILENT
+07-04-24 misc/procopen.c,include/proc.h: add PROC_CHECK
+07-04-24 misc/procrun.c: add flags arg (current use PROC_ARGMOD)
+07-04-24 misc/cmdarg.c,include/cmdarg.h: move from src/cmd/tw
+07-04-20 port/(lclang.h|lc.c|mc.c|lclib.h|lcgen.c): separate lctab.c
+07-04-20 comp/conf.sh: defer to systems without 'grep -q' -- sigh
+07-04-20 comp/conf.sh: probe for LL integer constant initializer suffix
+07-04-20 include/syslog.h: &lt;namval.h&gt; =&gt; &lt;ast_namval.h&gt; for win32
+07-04-20 ast_namval.h: add as copy of include/namval.h for win32
+07-04-19 comp/conf.tab: fix SVID SI entries to probe SI_* (not _SI_*)
+07-04-13 tm/tmxdate.c,tm/tmzone.c: handle &#0091;-+&#0093;0000 UTC zone offset
+07-04-11 sfio/sfvprintf.c: add %F, propagate SFFMT_UPPER
+07-04-11 sfio/sfcvt.c: handle SFFMT_UPPER =&gt; nan/inf vs. NAN/INF
+07-04-02 comp/conf.tab,comp/conf.sh: add C/POSIX &lt;stdint.h&gt; symbols
+07-03-28 misc/optget.c: fix l10n --?-
+07-03-25 features/common: fix { ast_std.h ast_map.h stdint.h } logic
+07-03-21 error.h: move from error_info to (*_error_data_)
+07-03-21 misc/error.c: add errorctx() for error_info switching
+07-03-21 option.h: move from opt_info to (*_opt_data_)
+07-03-19 regex/regdecomp.c: fix REX_ONECHAR escapes and add REX_KMP
+07-03-11 tm/tmxscan.c,regex/regnexec.c: fix strict-alias transgressions
+07-02-27 comp/conf.sh: handle native getconf invalid numeric values
+07-02-21 comp/conf.sh,comp/conf.tab: handle SSIZE_MAX vs _POSIX_SSIZE_MAX
+07-02-20 sfio/sfvprintf.c: handle SF_WCWIDTH justification
+07-02-14 features/common: cover &lt;stdint.h&gt;, move to int_(bits)_t
+07-02-14 include/int.h: drop
+07-02-14 include/sfio.h: add SF_WCWIDTH
+07-02-12 comp/conf.sh: fix CONF_LIMIT bug that missed ULONG_MAX etc.
+07-02-12 comp/conf.tab: *LONGLONG* =&gt; *LLONG* to match posix
+07-02-12 features/float: *LONGLONG* =&gt; *LLONG* to match posix
+07-02-12 port/astconf.c: handle CONF_LIMITS_DEF with no deferral
+07-02-12 stdio/vasprintf.c: add trailing '&nbsp;' -- doh
+07-02-04 string/fmtelapsed.c: fix naive multi month/year logic
+07-02-02 misc/optget.c: add --??posix for getopts(1)/getopt(3)
+07-01-26 string/chresc.c: use mbchar()
+07-01-26 misc/optget.c: handle "o:-:" usage for old-style long options
+07-01-22 sfio/sfdisc.c,sfpool.c: handle push on streams with pending peek
+07-01-22 include/sfio.h: mv Sfieee_t to sfio/sfhdr.h
+07-01-17 tm/tmxfmt.c: fix terminating nil logic which clobbered size-1
+07-01-11 misc/stk.c: a 2 day marathon bug fix (can we release now dr ek?)
+07-01-05 comp/spawnveg.c: posix_spawnattr_setflags(POSIX_SPAWN_SETPGROUP)
+07-01-05 misc/error.c: fix multibyte vs. printable logic
+07-01-01 comp/conf.sh: LC_ALL=C
+06-12-26 tm/tmxdate.c: handle nn*.nnnn* == sec.ns
+06-12-20 features/libpath.sh: generalize sol.* LIBPATH patterns
+06-12-18 comp/setlocale.c: include ast_standards.h and ast_wchar.h !
+06-12-12 string/strperm.c: octal modes are absolute!
+06-12-11 comp/conf.tab: always defer ARG_MAX
+06-12-07 Makefile: fix conftab.c generation CCFLAGS to match build - doh
+06-12-04 sfio/sfcvt.c: fix (int) vs. (long) cast mismatches
+06-12-01 comp/conf.tab: add changes to cover solaris { bin xpg4 xpg6 }
+06-12-01 regex/reginit.c: adjust { SRE KRE } escaped (){}*? inside &#0091;...&#0093;
+06-12-01 sfio/sfcvt.c: add signbit/copysign tests
+06-11-22 comp/spawnveg.c: fix _real_vfork logic to work with 3d
+06-11-20 features/common: bias _ast_int8_t "long long" before "__int64"
+06-11-20 string/strperm.c: fix X to work with all ops (not just +)
+06-11-15 astconf.c,conf.tab: add CONF_DEFER_* for variable constants
+06-11-11 port/astconf.c: validate path arg w.r.t. underlying calls
+06-11-11 comp/conf.sh: fix S CONF_STANDARD bug, add D to defer to native
+06-11-11 comp/conf.tab: add D to defer to native
+06-11-01 include/vmalloc.h: avoid VM_FLAGS sys/v*.h clash
+06-11-01 include/ast.h: add FMT_PARAM for fmtquote()
+06-10-31 disc/sfdcseekable.c: add SFSK_DISCARD for seekable window control
+06-10-31 comp/spawnveg.c,features/lib: handle posix_spawn exit status 127
+06-10-30 features/lib: fix posix_spawn() fork() prototype conflicts
+06-10-30 string/fmtscale.c: fix 1024 rounding bugs
+06-10-27 disc/sfkeyprintf.c: handle 'i' (=='d') -- oops
+06-10-26 sfio/sfvprintf.c: %#d =&gt; fmtscale(1000), %#i =&gt; fmtscale(1024)
+06-10-26 features/map.c: _map_libc cleanup
+06-10-26 features/fcntl: add to the circle of trust
+06-10-26 features/sys: add &lt;sys/socket.h&gt; socklen_t
+06-10-26 include/regex.h: handle include before &lt;ast_map.h&gt;
+06-10-25 astconf "SHELL" =&gt; "SH" to avoid _POSIX_SHELL conflict
+06-10-25 comp/conf.*: drop no-op duplicate conftab.c entries
+06-10-18 string/fmtscale.c: 1000: n&#0091;.&#0093;n&#0091;n&#0093;(kMGTPE), 1024: n&#0091;.&#0093;n&#0091;n&#0093;(KMGTPE)i
+06-10-11 ast_std.h: now implies &lt;sys/stat.h&gt; (did on most before anyway)
+06-10-11 strtoi.h: ignore sign for 0, validate scale shift
+06-10-11 strdup.c,vmstrdup.c: handle 0 arg
+06-10-11 add sfstruse()/sfstropen() error checks
+06-10-10 misc/procopen.c: envv==environ =&gt; don't modify environ
+06-10-10 misc/procclose.c: return valid exit(1) status
+06-10-06 port/astconf.c,comp/conf.sh,comp/conf.tab: play nice with getconf(1)
+06-10-01 comp/conf.tab: SHELL default checks { _CS_PATH } X { ksh ksh93 sh }
+06-10-01 comp/conf.sh: export CONF_getconf to shell actions
+06-10-01 comp/putenv.c: always enable setenv() for procopen()
+06-10-01 misc/procopen.c: use pathshell() or astconf("SHELL",0,0) if PARANOID
+06-10-01 path/pathshell.c: localize the shell path patterns and accept ksh93
+06-09-28 Makefile: avoid ast &lt;stdio.h&gt; vix iffe -X ast -- doh
+06-09-27 regex/regdecomp.c: add
+06-09-26 regex/regcomp.c: handle KRE ~(...)&lt;invalid-kre&gt;
+06-09-25 reorganize to avoid native header intercepts
+06-09-15 uwin/crypt.c: _UWIN only!
+06-09-14 Makefile: tweak the ast_common.h bootstrap again (finally?)
+06-09-14 misc/optget.c: noncommercial =&gt; OPT_proprietary
+06-09-12 string/strelapsed.c: fix multi-char qualifier parse
+06-09-12 string/strtoi.h: drop &#0091;cClLqQwW&#0093; multipliers
+06-09-11 misc/optget.c: add numeric arg validity check
+06-09-07 misc/optget.c,tm/tmfix.c: fix uninitialzed var refs
+06-09-05 path/pathprobe.c: add version header verification
+06-08-01 Makefile: handle iffe vs FEATURE/common vs ast_common.h
+06-08-31 Makefile: add ast_map.h to the bootstrap list
+06-08-30 misc/glob.c: fix ~(E)re bug that stripped ~(E) before regcomp
+06-08-30 include/ast.h: add { integralof(x) pointerof(x) }
+06-08-27 string/strelapsed.c: fix off-by-one (too little) parse bug
+06-08-25 misc/optget.c: 0*&lt;n&gt;.* numeric option args =&gt; &lt;n&gt;.*
+06-08-22 misc/glob.c: handle ~(...) pattern options
+06-08-16 string/strelapsed.c: fix off-by-one (too far) parse bug
+06-08-16 regex/regcomp.c: accept but ignore ~(N)
+06-08-14 features/libpath.sh: add solaris LD_LIBRARY_PATH_64 check
+06-08-05 sfio/sfpool.c: pool SF_READ|SF_WRITE loop fix
+06-08-02 misc/fts.c: fix FTS_NOSTAT optimization to check for ..
+06-07-28 include/glob.h: add gl_extra for user globlist_t expansion
+06-07-27 features/common: #include "ast_map.h"
+06-07-26 comp/fnmatch.&#0091;ch&#0093;: allow &lt;ast_map.h&gt; to map fnmatch()
+06-07-22 cdt: snarf from kpv
+06-07-17 string/strperm.c: perm==-1 skips umask(1)
+06-07-17 sfio/sfvprintf.c: handle format invalid mb seq
+06-07-17 regex/regcomp.c: inline REG_SHELL =&gt; anchored, otherwise not
+06-07-17 regex/regcomp.c: inline B|G:basic E:REG_EXTENDED F|L:REG_LITERAL
+06-07-17 regex/regcomp.c: inline l:REG_LEFT r:REG_RIGHT
+06-07-17 regex/regcomp.c: inline a:REG_LEFT|REG_RIGHT p:~REG_LENIENT
+06-07-17 string/chresc.c: add \Uxxxxxxxx
+06-07-17 sfio/sfstrtof.h: ignore thousands sep after decimal
+06-07-17 string/tokline.c: splice() =&gt; spliceline() for bsd
+06-06-27 features/float,sfio/sfcvt.c: fix Nan logic
+06-06-27 port/astmath.c: fix long double isnan() test
+06-06-27 features/map.c: _map_libc for std =&gt; _ast_std
+06-06-25 string/strperm.c: handle posix = w.r.t. umask
+06-06-19 port/mnt.c,features/fs: handle netbsd getmntent api change
+06-06-18 regex/regstat.c: add REG_LITERAL check
+06-06-11 cdt/dtview.c: update from kpv
+06-05-31 sfio/sfhdr.h: fix _SFOPEN() typo
+06-05-09 comp/conf.sh: add native getconf -a names to the mix
+06-04-28 misc/optget.c: add solaris long option name compatibility
+06-03-09 string/strmatch.c: add REG_ADVANCE =&gt; REG_* flags
+06-02-14 comp/iconv.c: fix uwin iconv_list() /reg/ generator
+06-02-10 port/astconf.c: relax standard prefix filter
+06-02-08 sfrd.c,sfsync.c: lock logic bug fix
+06-02-01 port/astlicense.c: add { parent incorporation }
+06-01-26 port/astconf.c: fix { LIBPREFIX LIBSUFFIX } length
+06-01-06 features/lib: change _UNIV_DEFAULT probe to use cross{...}
+06-01-04 misc/stk.c: fix n**2 realloc behavior
+06-01-01 include/sfio.h: export { _Sfi _Sfmaxr }
+05-12-13 string/chresc.c: handle \C-X =&gt; control-X, \M- =&gt; ESC
+05-11-22 regex/regcache.c: add, convert string/strmatch.c to regcache()
+05-10-06 string/ccmap.c: update ebcdic-u to be idempotent
+05-09-28 vmalloc: snarf from kpv; fixes large block brk() thrashing
+05-09-26 misc/magic.c,misc/magic.tab: handle latest vcodex header
+05-09-12 misc/optget.c: reset opt_info.offset on error
+ string/strtoi.h: strton() '.' multiplier only if m&gt;1
+ string/fmtesc.c: add unadvertized FMT_PARM for FMT_SHELL
+05-09-09 string/fmtesc.c: fix FMT_SHELL logic w.r.t. &#0091;$`&#0093;
+05-08-11 string/strerror.c: fix { sys_errlist sys_nerr } prototypes
+05-08-03 sfio: snarf sfvaprints sfaprints
+05-07-21 port/astconf.c: retain most recent synthesized lookup
+05-07-20 sfio/sfsetbuf.c: default file io size now 64K on all systems
+05-07-17 ccmap*: add microfocus cobol EBCDIC_U
+05-06-29 regex/regcomp.c: fix the A &amp; B inline flag logic
+05-06-15 include/recfmt.h: add fs format flag to fmtrec()
+05-06-14 error.c: add ERROR_OPTIONS { break count match }
+05-06-07 features/stdio: drop FEATURE/limits to fix bootstrap circular dep
+05-06-02 features/*,Makefile: drop vestigel iffeio.h bootstrap workaround
+05-05-31 string/fmtbuf.c: unlock (spin) before each return -- doh
+05-05-30 sfio/sfpkrd.c: work around macos 10.4 recv(MSG_PEEK) bug
+05-05-27 regex: add REX_NEST (?%&#0091;S.&#0093;&#0091;T.&#0093;&#0091;OT&#0093;)
+ magic.tab: ammend bsd db magic
+05-05-23 regex: REX_NEST (?%&#0091;D.&#0093;&#0091;E.&#0093;&#0091;L.&#0093;&#0091;Q.&#0093;&#0091;oc&#0093;...)
+05-05-21 regex: state.fold&#0091;&#0093; is now locale specific -- doh
+05-05-19 regex: add REX_NEST (?%\\()&lt;&gt;&#0091;&#0093;""...) %(...) nested match
+05-05-15 recfmt.h: add recstr() reclen() fmtrec()
+05-05-13 optget.c: allow boolean options to take numeric values
+05-05-12 recfmt.c: add to recfmt.h, adjust Recfmt_t encodings
+05-04-30 sfio: add sfmaxr(), default 64K
+05-04-22 comp/omitted.c: fix magic() logic for files &lt; 512 bytes
+05-04-20 cdt: snarf update from kpv; void* Dt_t.user added
+ misc/error.c: library =&gt; ERROR_LIBRARY
+05-04-19 regex/regcomp.c: handle REG_SHELL &#0091;^...&#0093; == &#0091;!...&#0093;
+05-04-11 tm/tmxscan.c: handle yyy.mm.dd&#0091;-+.&#0093;hh.mm.ss.nnnnnn
+05-04-07 regex/regnexec.c: fix out of bounds boundary check -- ouch
+ features/align.c: add jmp_buf to the alignment mix (ia64)
+ vmalloc/vmhdr.h: add jmp_buf to the alignment mix (ia64)
+05-03-31 misc/optget.c: fix option { - _ } separator matching
+05-03-30 misc/glob.c: eliminate superfluous GLOB_NOMATCH stat() calls
+05-03-24 port/astwinsize.c: include &lt;sys/ioctl.h&gt; if possible
+05-03-23 string/ccmap.c: add ebcdic-m mvs cobol table
+05-03-11 comp/omitted.c: handle utime&#0091;s&#0093;(const,const)
+ comp/conf.tab: fix linux PID_MAX probe
+05-03-10 comp/setlocale.c: LC_* value "" =&gt; unset -- doh
+ misc/optget.c: reorder _PACKAGE_astsa code for msgcc
+05-03-08 misc/optget.c: delete leading space in STYLE_nroff output
+05-03-07 sfio/sfhdr.h: drop extern _sfdscan -- clashes with sfvscanf.c static
+05-03-01 tm/tminit.c: add tmlocaltime() for tzset() getenv() override workaround
+05-02-20 features/tvlib: tmsettimeofday only for systems that have settimeofday
+ features/float: fix mvs.s390 NaN tests
+05-02-18 tm/tmxmake.c: fix &lt;0 west of GMT bug that warped to 1800's -- wow
+05-02-11 port/mnt.c: handle lynxos MOUNTED=/etc/fstab
+05-02-08 features/float,sfio.h,sfcvt.c,sftable.c: add INF and fix NAN
+05-02-04 features/lib: add _std_strtol (for lynxos)
+ include/ast_std.h: add _std_strtol tests
+ comp/strtod.c: #define S2F_function strtod
+ misc/signal.c: fix ancient bsd SV_INTERRUPT vs. SV_ABORT clash
+05-01-11 sfio/sfmove.c: try to seek(fr) when fw==0
+ comp/omitted.c: intercept utimes() too
+ comp/omitted.c: add DOSPATHVARS env var path value conversions
+ features/tvlib,tm/tvtouch.c: check for utimets()
+ misc/optget.c: handle '-' or '_' option word separators
+ sfio/_sfopen.c: allow stream mode changes after initialization
+ sfio: sync with kpv: SF_SYNCED fix for ksh input loss bug
+05-01-09 tm/tmxfmt.c: fix %6N for n&lt;100000000
+05-01-08 regex/regcomp.c: conj() =&gt; con() to avoid C99 clash
+05-01-05 tm/*: fix { %U %V %W } logic -- my head hurts
+04-12-30 tm/tmxtime.c: fix tm_isdst&lt;0 loop
+04-12-23 vmalloc/vmbest.c: fix vmresize bug that didn't 0 new data
+04-12-19 misc/optget.c: broaden - long option match
+04-12-09 string/strtoi.h: fix terabyte 't' suffix math
+ string/strmatch.c: flush cache on locale change
+04-12-01 tm/tmsleep.c: add
+ tv.h,tv*.c,tv.3: move from pax
+ tmx.h,tmx*.c,tmx.3: add high resolution tm(3) counterparts
+ features/lib: add *another* sgi linux.ia64 memccpy bug check
+04-10-31 Makefile: __OBSOLETE__ now computed &lt;6 months ago year&gt;0101
+ ccode.h,ccmapid.c: add ccmaplist(Ccmap_t*) iterator
+ option.h,optesc.c: add 3rd arg, 1 =&gt; quote '?' too
+ misc/magic.c: fix bug that terminated `string &nbsp;a' at &nbsp;
+ misc/magic.c: handle vcodex() via decompose()
+ misc/magic.tab: add vcodex magic
+ features/stdio: handle _LARGEFILE64_SOURCE -- oops
+ stdio/(fseek|ftell|fseeko|fsetpos|fgetpos|ftello).c: oops^2
+04-10-28 string/swapop.c: size==-4 =&gt; size=4 and extend op=3 to op=7
+ tm/tmfix.c: fix tm_mon&lt;0 logic
+04-10-22 tm/tmdate.c: handle 'final day feb 2004'
+ port/astlicense.c: add query=all|id|${...}${...}
+ port/astlicense.c: "free" =&gt; "mit"
+ comp/omitted.c: revert to the open source license
+ string/stropt.c: drop siz==0 =&gt; tab is hash table
+ include/sfio.h: incorporate &lt;sfstr.h&gt;
+ include/sfstr.h: drop
+ disc/sfstrtmp.c: drop -- use sfstrbuf()
+04-10-20 misc/magic.tab: update tar magic
+04-10-18 ufc-crypt.h,crypt_util.c: drop GPL code
+ crypt.c: add BSD code
+ pathpath.c: disable { $0 $_ $PWD } related root search
+04-10-01 normalize ident stamps
+ port/astlicense.c: add type=cpl -- yeah
+04-09-25 string/swapop.c: return op &lt; size -- duh
+04-09-23 comp/spawnveg.c: :NOOPTIMIZE: -- volatile sometimes ignored
+04-09-21 comp/spawnveg.c: exec_errno_ptr is volatile -- duh
+04-09-14 tm/tmscan.c: add %| alternation and %&amp; =&gt; tmdate()
+04-09-08 misc/optget.c: add :!value: omitted optional arg value
+ misc/optget.c: fix --noNAME ambiguous option logic
+04-08-26 string/strperm.c: add who^mode to propagate least restrictive up
+ astmath.c: add { frexpl ldexpl } checks for ast.req
+ port/astlicense.c: ignore first option if non-assignment
+ include/ast_dir.h: move d_fileno map before struct defs -- duh
+04-08-24 vmalloc/vmbest.c: add {VM_region} VMCHECK=+r for region segment checks
+ misc/recfmt.c,include/recfmt.h: add
+04-08-23 vmalloc/vmbest.c: add {VM_primary VM_secondary} VMCHECK=-s for primary
+ features/common: punt to &lt;stdarg.h&gt; for unknown va_list
+04-08-11 vmalloc: sync _UWIN libposix hooks
+04-07-27 features/common,features/limits.c: ULL suffix for unsigned _ast_int8_t
+04-07-22 include/ast.h,comp/eaccess.c: add eaccess() for effective access()
+04-07-19 comp/open.c,sfio/_sfopen.c: { O_RDONLY O_WRONLY O_RDWR } are values
+04-06-28 misc/error.c: check level after error_info.auxilliary
+04-06-24 string/strmatch.c: strgrpmatch() match&#0091;&#0093; now variable size array
+04-06-17 features/common: change _DLL null define to (the standard ast) 1
+04-06-11 misc/optget.c: allow optional &#0091;-|+|--|++&#0093; optstr() option prefix
+ misc/optget.c: reset optstr() state on 0 return
+ misc/optget.c: text()=&gt;textout() linux.ppc symbol hijack workaround
+04-05-31 sfio/sfreserve.c: no side buffer if user buffer is large enough
+04-05-27 string/fmtbuf.c: handle one concurrent buf &gt; sizeof(buf)
+04-05-24 regcomp.c: fix no-advance initialization
+04-05-05 conf.tab,conf.sh: update to align with standards
+ magic.tab: ms suffix update
+04-05-04 port/lcgen.c: fix territory initialization
+04-04-15 tm/tmdate.c,include/tm.h: fix specific and ordinal days
+04-04-08 astconf: retain { HOSTTYPE LIBPATH LIBPREFIX LIBSUFFIX } strict vals
+04-04-07 vmalloc/vmbest.c: fix alpha tiny block bug
+ vmalloc/malloc.c: re-enable on alpha
+04-03-30 tm/tminit.c: GMT =&gt; UCT only if tz.daylight not defined
+04-03-25 vmalloc/malloc.c: _AST_std_malloc=1 for __alpha
+ path/pathprobe.c: per-user probe dir =&gt; $HOME/.probe/$HOSTTYPE
+04-03-23 regex/reglib.h: fix isw*() redefines
+04-03-17 features/stdio: no __FILE override for __CYGWIN_ (sys/reent.h clash)
+ sfio/sfhdr.h,sfio/sfsetbuf.c: lower sfmove() default buf size 4x
+04-02-29 comp/omitted.c: move env trace after PATH fixup
+ comp/omitted.c: cygwin spawn _P_DETACH =&gt; _P_NOWAIT+setpgid(pid,0)
+ misc/optget.c: fix html mailto: match
+ port/astlicense.c: add type=test for fixed 2001 date
+ features/float: check local NaNQ first
+ vmalloc/vmhdr.h: fix _vmextern_ vm_truncate return type
+ misc/magic.tab: add elf s390 index=22
+04-02-26 vmalloc: VMCHECK a:assertions c:arena-check w:warn-instead-of-abort
+ sfio/sfvscanf.c: fix extf arg selection
+04-02-24 features/dirent: set nodefine to avoid ast_std.h _typ_off64_t undef
+ disc/sfkeyprintf.c: only case pattern must be ()&#0091;&#0093; balanced
+04-02-14 include/sfio_t.h: add SF_DCDOWN, SFDCNEXT(), SFDCPREV()
+04-02-13 string/strmatch.c: fix bug that didn't save one-time sub&#0091;&#0093; size
+ vmalloc: -g: export VMCHECK=1 enable malloc/free checks
+ vmalloc: -g: free(0) to check and disable malloc/free checks
+ vmalloc: -g: free(1) to check and enable malloc/free checks
+04-02-11 Makefile: add :P=A: to conf and lcgen exec for cross-compile
+ regex: use MBSIZE() instead of mbsize() to grab 1 char on err
+ vmalloc/vmbest.c: updated to do more comprehensive DEBUG tests
+04-02-04 sfio/sfraise.c: add sfraise(0,a,b) to iterate over all streams
+04-02-01 vmalloc/vmbest.c: _BLD_DEBUG free(0) checks the arena
+04-01-31 features/vmalloc: fix typo that missed _mmap_zero
+04-01-23 string/strerror.c: handle real strerror() return value overwrite
+04-01-11 path/pathpath.c: fix size vs. sizeof(buf) typo
+03-12-22 misc/magic.tab: dos EXE tweaks
+03-12-05 vmalloc: sync with kpv, adding exceptf announcements
+03-12-04 port/astlicense.c: fix expand() loop sentinel bug
+03-12-02 include/ast.h: mbchar() advances by 1 on mbtowc() error
+ misc/fts.c: increase MINNAME to 32
+03-11-21 vmalloc/vmbest.c: export VMCHECK=1 to enable $(CC.DEBUG) vmcheck()
+ vmalloc/vmbest.c: export VMCHECK=2 to disable KPVCOMPACT
+ misc/magic.c: add { cobol copybook pl1 } and suffix preference
+03-11-12 features/stdio: drop cuserid,getopt for SUSV3
+03-11-11 vmalloc/*: merge kpv update -- this should stomp the compaction bug
+03-10-23 comp/iconv.c: fix sfreserve lock fallback
+03-10-20 sfio/_sfopen.c: add to allow user sfopen() intercept
+03-10-17 regnexec.c: fix exec time REG_LEFT, \x.... =&gt; wctomb()
+03-10-12 string/strtoi.h: fix strton '.' overconsumption
+03-10-12 comp/iconv.c: identity is always (iconv_t)0
+03-10-09 string/fmtesc.c: fix FMT_SHELL to check for all shell magic chars
+03-10-01 port/astlicense.c: unknown authors copied verbatim (instead of ignored)
+03-09-30 string/chresc.c: handle \u..., \x... consumes all trailing hex digits
+ string/stresc.c: \u... and \x... &gt; UCHAR_MAX =&gt; wctomb()
+03-09-29 fnv.h: add
+03-09-23 modedata.c: table is for external modes, so no arch specific hacks
+ optget.c: fix option prefix match translation bug
+ optget.c: add `&lt;length&gt; &lt;name&gt;=&lt;value&gt; to optstr()
+ features/lib: add memcmp() test for sgi optimzation bug
+03-09-22 regex.h,regcomp.c: add regncomp()
+ regclass.c: fix for loop dangling ; in regaddclass()
+03-09-20 sftable.c,sfvprintf.c: fix SFFMT_CHAR handling to match extf api
+03-09-19 sfmode.c: update release to kpv's
+03-09-17 regcomp.c: add pedantic backref error checks
+03-09-16 regnexec.c: exec time REG_LEFT =&gt; don't advance past initial position
+ regclass.c: add regaddclass() for user defined &#0091;:class:&#0093;
+ regexec.h: REG_VERSION_N2X, add redisc_t {re_map} ccode map
+ regstat.c: add regstat_t
+03-09-11 optget.c: --n:=v sets opt_info.assign=':', opt_info.number enabled
+03-09-09 disc/sfkeyprintf.c: *pn on lookup is arg separator; lookup "" arg too
+03-09-05 optget.c: &#0091;f:l*?&#0093; preserves user long name past '*' in opt_info.name&#0091;&#0093;
+03-09-03 sfstr.h: add sfstrpend() for #pending bytes in read buffer
+03-08-25 regex: add REG_FIRST, optimize bm
+ features/lib: _AST_no_spawnveg==1 falls back to fork/exec
+03-08-22 features/stdio,stdio/asprintf.c,stdio/vasprintf.c: add
+03-08-21 path/pathnative.c,path/pathposix.c: interix updates
+ features/botched: add cygwin _stat =&gt; _stat64
+03-08-15 include/ast.h: map out bsd strmode()
+ features/common: add interix _ast_intmax_t workarounds
+ misc/fs3d.c: 3d mount test now uses "" instead of NiL (or cygwin dumps)
+03-08-11 string/fmtesc.c: fix optional quoting checks
+ tm/tmdate.c: fix &gt; 1 year of seconds arithmetic
+ tm/tmfix.c: fix leap year adjustments
+03-08-01 features/lib: beef up sock_peek test for interix
+03-07-29 features/float: add -lm to frexp... test
+ Makefile: fix -lm astmath test sense
+03-07-26 features/mem.c: favor _mem_sbrk over _mem_mmap_*
+03-07-22 vmalloc/vmbest.c: fall back to sbrk() if mmap() fails
+ features/mem.c: _mem_sbrk means sbrk() and brk() work
+03-07-17 regex/regcomp.c: fix bug that treated KRE X{n,m} like {n,m}(X)
+ misc/magic.c: check MAGIC_VERBOSE for all load() messages
+03-07-14 misc/optget.c: handle &#0091;...&#0093;{&#0091;...&#0093;<.>..</.><.>..}</.>
+03-06-21 misc/sigcrit.c: block SIGCHLD if _lib_sigprocmask || _lib_sigsetmask
+ comp/spawnveg.c,sfio/sfmode.c: use sigcritical() SIG_REG_* macros
+ comp/spawnveg.c: drop ENOEXEC logic
+ vmalloc/*: snarf kpv KPVCOMPACT() fix
+ vmalloc/vmbest.c: export VMCHECK=2 to disable KPVCOMPACT (just in case)
+ string/strdup.c: drop __strdup() etc. intercepts -- malloc gets it
+ features/mem: define _mem_method and _mem_* possible values
+ vmalloc/malloc.c: _AST_mem_method==_mem_* to force mem get method
+ sfio/sfputr.c: __ia64 memccpy is bogus -- how many tries do they get?
+ path/pathshell.c: verify abs path and access(path,X_OK) -- duh
+ vmalloc/vmhdr.h: add private _Vmessage() for non-sfio ASSERT()
+ port/astconf.c: fix bug that always returned the minmax value
+03-06-11 comp/*.c: reorder macro hding for mvs.390 and &lt;ast_map.h&gt;
+ features/vmalloc: add _lib_brk and _lib_sbrk verification
+ include/ast_std.h,etc.: add _map_malloc for malloc =&gt; _ast_malloc
+ comp/conf.sh: fix SI_* and *_SI_* macro redefs
+ ast.h: VMDEBUG or _BLD_DEBUG enable &lt;vmalloc.h&gt; and VMFL tracing
+ vmalloc/vmtrace.c: _PACKAGE_ast __FUNCTION__ is a string
+ vmalloc/vmtrace.c: set trace file fd FD_CLOEXEC
+ vmalloc/vmbest.c: set /dev/zero mmap fd FD_CLOEXEC
+ features/mmap: fix ancient read() vs. mmap() time arithmetic typo
+ vmalloc/malloc.c: _AST_std_malloc==1 to force standard malloc
+03-06-09 comp/omitted.c: add _imp__FUNCTION sybols for __CYGWIN__ static link
+ vmalloc/vmbest.c: handle systems with sbrk() but no brk()
+03-06-04 port/astconf.c: drop non-standard diagnostics
+03-06-03 comp/conf.sh: rework symbol collision logic
+03-05-30 conf.tab,conf.sh,astconf.c: add &lt;sys/systeminfo.h&gt; sysinfo() SI_*
+03-05-29 ccode.h: rework for extensibility, drop obsolete mematoe(), memetoa()
+03-05-28 regex/*: recode to use isw*() directly when needed, is*() otherwise
+03-05-27 features/vmalloc: fix _std_malloc test
+03-05-25 misc/optget.c: fix optstr() ???* internal options
+03-05-24 misc/optget.c: fix (ancient) argv null dereference
+03-05-23 comp/getcwd.c: don't intercept on _WINIX -- unreliable st_ino
+03-05-22 sfio/sfsprintf.c: n&lt;0 =&gt; don't append '&nbsp;'
+03-05-18 misc/fts.c: re-stat FTS_DP to update nlink/times
+ misc/fts.c: add FTSENT.stack to eliminate getlist() recursion
+ regex/ucs_names.h: use "..." catenation to placate some cc's
+03-05-11 string/strtoi.h: handle "-" "+" "0x" "11#"
+03-05-09 vmalloc/vmbest.c: large memory allocation tweaks
+03-05-06 misc/optget.c: fix getopt_long() prefix==1 bug that missed short flags
+03-04-27 comp/system.c: handle &lt;ast_map.h&gt;
+03-04-24 vmalloc/vmmopen.c: drop dup &lt;unistd.h&gt;
+03-04-21 tm/tmdate.c: fix next hour/min logic
+03-04-15 vmalloc/malloc.c: intercept __malloc() along with __libc_malloc()
+ string/strdup.c: intercept __strdup() along with __libc_strdup()
+ features/mmap: consolidate from features/(lib|sfio|vmalloc)
+ add _NO_MMAP==1 to disable all mmap()/munmap() calls
+ path/pathposix.c: add
+03-04-14 comp/setlocale.c: fix debug_mbtowc() return value for *s==0 || n &lt; 1
+ comp/iconv.c: fix error return errno values
+03-04-11 misc/stk.c: fix stkgrow() realloc bug
+03-04-05 string/tok.c: support readonly single token input strings
+ disc/sfdcdio.c: fix F_DIOINFO and FDIRECT #ifdef's
+ include/ast_std.h: allow _LARGEFILE64_SOURCE on __hppa
+ features/common: fix `tst _foo_' =&gt; `tst foo_' typo
+ features/float: fix `tst _foo_' =&gt; `tst foo_' typo
+ features/float: add FLTMAX_(UINTMAX_MAX,INTMAX_MAX,INTMAX_MIN)
+ comp/omitted.c: fix pathconf =&gt; _pathconf =&gt; _ast_pathconf loop
+03-04-03 features/float: add _ast_no_um2fm: no usinged intmax =&gt; floatmax cast
+ vmalloc/vmbest.c: add getenv("VMCHECK") to initialize Vmcheck
+03-03-28 include/ast_dir.h: add D_TYPE; { D_FILENO D_TYPE } must be #ifdef'd
+ misc/fts.c|getcwd.c|glob.c,preroot/getpreroot.c: add D_FILENO #ifdef's
+ Makefile: make sure _BLD_ast is defined for all compiles
+03-03-27 ast_vfork.h: generate from features/vfork to pick up headers/pragmas
+03-03-25 comp/omitted.c: drop free() of live environ
+ path/pathshell.c: allow trailing .exe -- pox on that
+ string/strtoi.h: fix bug leading 3 digits before thousands sep bug
+ string/(fmt|str)&#0091;gu&#0093;id.c: we know root when we see it
+03-03-24 misc/optget.c: handle : and ? in := default value
+03-03-21 ast_std.h: drop all spawn*() but spawnveg()
+ obsolete/spawn.c: add for dropped spawn*()
+ features/lib: _use_spawnveg if spawnveg() is a win over fork()/exec()
+ features/lib: drop NutForkExecve() and _map_spawnve
+ features/lib: fix memccpy test to clean up /tmp droppings
+ comp/spawnveg.c: call posix_spawn() if implemented
+ comp/omitted.c: add spawnve() intercept
+ comp/getoptl.c: set getopt_long() optind even if no options
+ tm/tmfmt.c: add %Q&lt;delim&gt;recent&lt;delim&gt;distant&lt;delim&gt;
+ misc/optget.c: fix trailing '*' for option and option args
+ sfio/sfmode.c: getenv("_AST_SFIO_OPTIONS") &#0091;,&#0093;SF_LINE&#0091;,&#0093; for fd {0,1,2}
+ vmalloc/*: kpv sync for uwin build independent of libast
+03-03-18 port/astconf.c: switch to dynamic string values (saves 7K data/bss)
+ string/strmatch.c: switch to dynamic regex cache (saves 3K data/bss)
+ regex/regcoll.c,ucs_names.h: initialize rw tables from smaller ro data
+ features/lib: add vfork test for passing SIG_IGN across exec
+ features/lib: add spawn test for passing SIG_IGN across spawn
+03-03-17 comp/omitted.c: unlink() renames to .deleted dir in case file open
+ sfio/sfpopen.c: handle mode "" for spawn with no pipe
+ features/float,comp/frexp.c,comp/frexpl.c: add pow2() table alternative
+03-03-12 features/lib: fix linux.ia64 memccpy() tests -- now its their turn
+ features/vmalloc: fix /dev/zero test
+ features/align: _ast_intmax_t and _ast_fltmax_t join the union
+ misc/stk.c: fix struct frame size to align data
+ disc/sfdcdos.c: change sfslen() =&gt; sfvalue(f)
+03-03-10 misc/optget.c: handle &#0091;f<:>x:lll</:><?>ddd&#0093;</?>
+03-03-07 port/astconf.c: uninitialized CONFORMANCE + POSIXLY_CORRECT =&gt; standard
+03-03-05 comp/omitted.c: make sure at least /bin is in PATH to find cygwin dlls
+03-03-02 path/pathshell.c: write access to /bin is effectively root
+03-02-28 features/float: add (FLT|DBL|LDBL)_U?(LONG|LONGLONG|INTMAX)_(MIN|MAX)
+03-02-25 features/lib: change vfork() test to use _exit() instead of exit()
+03-02-23 include/error.h: update ERROR_VERSION for error_info.number space
+03-02-22 comp/conf.sh: wrap ksh check in eval to avoid premature exit
+03-02-21 misc/fts.c: verify chdir(..) to avoid malicious dir rename()
+03-02-19 string/strtoip4.c: isspace() instead of ' '||'\t'
+03-02-17 regex/regcomp.c: fix stats.l REX_REP logic that botched REX_BM
+03-02-13 string/base64.c: handle catenated encodings
+03-02-11 features/libpath.sh: change LIBPATH to &lt;dir&gt;&#0091;:&lt;env&gt;&#0091;:&lt;pat&gt;&#0093;&#0093;&#0091;,...&#0093;
+03-02-07 path/pathfind.c: allow "/dev/null" to be PATH_REGULAR
+03-02-06 include/ast.h,fmtquote.c: add FMT_ALWAYS|FMT_ESCAPED|FMT_SHELL|FMT_WIDE
+03-02-05 tm/tmdate.c,tm/tmword.c,string/strelapsed.c: '_' treated like ' '
+03-02-01 string/strelapsed.c: handle ps style &#0091;day-&#0093;&#0091;hour:&#0093;min:sec
+03-01-31 port/astlicense.c: fix author=* match
+03-01-30 include/tm.h: add tmisleapyear() macro
+03-01-29 comp/getopt.h,comp/getoptl.c: add gnu getopt_long(), getopt_long_only()
+ include/ast_getopt.h: for non-gnu part of comp/getopt.h
+ include/ast_std.h: include &lt;ast_getopt.h&gt; instead of &lt;getopt.h&gt;
+03-01-28 ast.h,string/base64.c: add base64encode() and base64decode()
+ path/pathfind.c: verify S_ISREG()
+03-01-24 path/pathexists.c: fix abs dir bug and deal with case ignorance
+03-01-23 path/pathpath.c: honor PATH_ABSOLUTE for the easy case too
+03-01-22 path/pathprobe.c: fix search to find both the probe script and command
+03-01-17 misc/magic.tab: application/zip =&gt; appplication/(gzip|pzip|zip)
+03-01-14 misc/optget.c: change href="" to href="."
+03-01-10 include/ast_std.h: strtold() import hackery for static __CYGWIN__
+03-01-03 include/regex.h,regex/regcomp.h: add REG_SHELL_GROUP
+ include/ast.h,string/strmatch.c: add STR_GROUP for REG_SHELL_GROUP
+02-12-15 include/error.h: errorcontext =&gt; Error_context_s (compatible til 2004)
+02-12-06 misc/sigdata.c: add NoF(sigdadata) -- why nmake was uninterruptable!
+02-12-03 comp/omitted.c,features/omitted: handle cygwin alarm() return botch
+02-11-27 misc/swapop.c: op=3,size=4 =&gt; op=7
+ string/strlcat.c,strlcpy.c: fix uwin decl clash
+02-11-26 sfio/sfvprintf.c: fix sfsprintf() '&nbsp;' termination bug
+02-11-22 misc/glob.c: move static struniq() to libast extern
+ string/fmtversion.c,include/ast.h: add fmtversion
+02-11-18 string/strncopy.c: add
+ misc/magic.tab: list size for magicid.h magic
+02-11-14 sfio/sfvprintf.c: add %#c for C escapes
+ include/error.h: add ERROR_NOTIFY context flag for builtin commands
+02-11-11 string/strtoi.h: add S2I_size for strnto*() size_t 2nd arg
+ sfio/sfstrtof.h: add S2I_size for strnto*() size_t 2nd arg
+ comp/putenv.c: add setenv() and unsetenv() wrappers for setenviron()
+02-10-31 path/pathfind.c: add dir of including file to the pathinclude() list
+ misc/optesc.c: add
+02-10-30 string/strtoip4.c: set next char pointer even on error
+02-10-29 comp/resolvepath.c: add (size_t version of realpath())
+ misc/mime.c: fix mimehead() to ignore null content values
+02-10-28 misc/glob.c: add GLOB_STARSTAR for /**/ and GLOB_NOTDIR optimization
+02-10-27 string/struniq.c: add
+02-10-23 features/common: fix off-by-one loop check
+02-10-18 include/ast_std.h: avoid off_t,ftruncate,lseek,truncate redefinitions
+02-10-17 misc/mime.c: handle type/* match, fix bogus header parse
+02-10-04 sfio/sfstrtof.h: S2F_static &lt;0:export =0:private &gt;0:static
+02-10-02 features/common: don't define _WIN32; define _WINIX =&gt; unix on windows
+ features/tty: finally stomp the bsd _POSIX_VDISABLE redefinition
+ misc/fastfind.c: add more specific findwrite() error messages
+ comp/omitted.c: fix cygwin utime() to update st_ctime
+ comp/strtol.c,strtoul.c: __CYGWIN__ static link workaround XXX
+ string/fmtls.c,fmttime.c: tmform() =&gt; tmfmt()
+02-09-22 port/astconf.c: return values in fmtbuf() buffer instead of stack
+ port/mnt.c: don't set MNT_REMOTE for win32 ?:paths
+ sfio/sfvscanf.c: _sfdscan() is library global (not static)
+02-09-21 path/pathkey.c: add tool arg for mamake compatible hash
+ features/fcntl.c: handle iffe _hdr_lcl_* =&gt; _lcl_* change
+02-09-15 comp/conf.sh: fix enum vs. macro test
+ cdt: kpv sync
+02-09-11 ast.h,features/common: move _WIN32 macro init to features/common
+ features/common: enable __EXTERN__ and __DEFINE__ for _WIN32&amp;!_UWIN
+ features/float: add -lm to _ast_*_nan_init tests
+ vmalloc: kpv sync with vmresizef =&gt; vmgetmem
+ features/iconv: must have both &lt;iconv.h&gt; and iconv_open()!
+ features/vmalloc: alloca test must compile *and* link
+ sfio/sfvscanf.c,sfstrtof.h: add flag arg to char get, fix NaN loop
+02-09-10 vmalloc/vmhdr.h: enable getpagesize() and sbrk() prototypes
+ features/fcntl.c: enable mmap64() prototype
+ include/ast_windows.h: windows.h wrapper with ast namespace workarounds
+02-09-07 misc/mime.c: fix quoted value parse bug that ate the whole line
+02-09-05 features/vmalloc: add free() to _std_malloc test
+ include/ast.h: NoF(x) now defines _DATA_x for !_BLD_DLL too
+ tm/tmlocale.c: { C POSIX en } == unix dadgummit
+02-08-29 path/pathfind.c: initialize Dir_t.next=0
+02-08-28 uwin/rint.c: update
+ features/libpath.sh: "bin" is now the default value
+02-08-22 vmtrace.h: add for debugging
+02-08-20 misc/magic.c: convert to use &lt;cdt.h&gt;
+ vmalloc/vmresizef.c: add for generic discipline resizef default
+ string/strelapsed.c: allow long time component names
+02-08-19 misc/optget.c: add `.fp 5 CW' to --nroff output
+ string/(fmtfs|fmtuid|fmtgid|strgid|struid).c: convert to use &lt;cdt.h&gt;
+ include/dt.h,cdt/dtnew.c: add for dtopen() in specific vm region
+02-08-13 comp/omitted.c: fix bzero logic for e.g. unixware.i386
+ include/ast.h: add fmtbase-&gt;fmtbasell; swap in 2003-09-01
+02-08-12 regex/regnexec.c: fix REG_MINIMAL REX_DOT mb bug
+02-08-08 features/iconv: &lt;ast_common.h&gt; instead of &lt;sys/types.h&gt; &lt;ast_common.h&gt;
+02-08-07 regex/regcomp.c: recognize anchors in BRE subexpressions
+02-08-06 comp/iconv.c: handle win32 cpNNNN == windows-NNNN aliases
+02-08-05 cdt/*: sync with kpv src
+02-08-02 features/iconv: include sys/types.h for ast_types.h
+02-08-01 misc/magic.c: magic file "." names the default
+ misc/magic.c: handle addr type (from irix string)
+ features/lib: move malloc tests to features/vmalloc
+ features/vmalloc: snarf tests from features/lib
+ vmalloc/*: sync with kpv src
+ comp/libc.c: dropped -- __libc_* intercepts moved to vmalloc/malloc.c
+02-07-30 features/lib: handle __libc_malloc() in _std_malloc test
+ vmalloc/malloc.c: add gnu pvalloc()
+ features/vmalloc: fix alloca check
+02-07-29 features/limits.c: handle netbsd guards
+02-07-27 sfio/sfpoll.c: handle rw pipes
+02-07-25 features/iconv: include ast_types.h for size_t in ast_iconv.h
+02-07-18 apply LARGEFILE64 header prototype clash patches
+ misc/optget.c: __EXTERN__ _opt_info_ instead of opt_info
+02-07-17 ast_std.h: memzero() now defaults to memset() instead of bzero()
+02-07-16 ast_std.h: add ast.env_serial
+ misc/setenviron.c: increment ast.env_serial
+ include/tm.h: tmset() now calls tminit() directly
+ tm/tminit.c: check ast.env_serial for env change
+ tm/tmfix.c: speed up for large values of tm_mday
+02-07-15 comp/fnmatch.c: fix memory leak caused by missing regfree()
+ comp/strstr.c: fix broken interpretation and implementation
+ comp/iconv.c: intercept (but no-op) null to and from buffer pointers
+02-06-27 ast_std.h: map _sysconf =&gt; _ast_sysconf for sun
+02-06-26 cdt,sfio,vmalloc: kpv sync -- is this ever easy?
+02-06-24 sfio: kpv sync, vfwscanf(),fputw() fix (wcslen(x)*sizeof(wchar_t)!!)
+ misc/fts.c: fix symlink chdir() optimzation bug
+02-06-11 sfio/sfwrite.c: string to file fix
+ Makefile: __OBSOLETE__==20020101
+02-06-01 regex/regcomp.c: REG_DELIMITED now consumes the delimiter
+02-05-31 regex/reglib.h,regcomp.c,regnexec.c: null subexpression fixes
+02-05-24 misc/fts.c: disable dir link counts in 3d
+ misc/magic.c: fix "*(mkfile)" sh pattern to "*@(mkfile)"
+02-05-20 regex.h,regex/regsubcomp.c,regex/regsubexec.c: add
+ regex/regsub.c: deprecate
+02-05-16 tm/tmfix.c: fix '60+n min/sec ago' bug for n min/sec after the hour
+02-05-14 regex/regsub.c: fix (^|x) null match early termination bug
+02-05-13 dir/dirlib.h: drop errant extern==__EXPORT__
+ features/uwin: add uwin lib tests
+ uwin/*.c: check features/uwin for stubs
+ features/float: add nan representation generation
+ sfio/sftable.h: used _ast_*_nan_init for huge values
+02-05-09 misc/fts.c: fix virtual top to force ``child'' stat()
+ features/common: define va_copy() only if not in &lt;stdarg.h&gt;
+02-05-01 string/strtoip4.c: cisco inverted quad mask must have 4 parts
+02-04-30 misc/magic.tab: fix pzip version check
+02-04-19 string/strtoip4.c: handle cisco inverted quad mask n.n.n.n/i.i.i.i
+02-04-18 misc/fts.c: add chdir() verification stat() optimizations
+ path/pathkey.c: check PROBE_ATTRIBUTES for list of vars
+02-04-12 port/astlicense.c: type=open tweak, fix author list spacing
+02-04-11 regex/regcomp.c: check for pattern number overflow
+02-04-05 tm/tmfmt.c: add %u
+02-04-04 sfkeyprintf.c: fix %c numeric value
+ path/pathpath.c: check plain path first -- duh
+02-04-03 misc/fts.c: fix (FTS_PHYSICAL|FTS_NOSTAT) stat optimizations
+ ftwalk.c: only clear FTW_DELAY if FTW_CHILDREN
+ ftwalk.h: add FTW_NSOK for FTW_DELAY
+02-03-29 ast.h: drop strerror() prototype -- already in &lt;ast_std.h&gt;
+ features/stdio: check for _SFIO_H redundant _Sfstd* declarations
+02-03-26 misc/glob.c: fix GLOB_LIST gl_flags values
+02-03-24 port/mnt.c: update bsd fstype name and mount option logic
+02-03-23 Makefile: add ast_wchar.h to the .check.hdr list (for mamake)
+02-03-17 features/stdio: hack around g++ 3.* clashes
+ Makefile: add ast_nl_types.h to the .check.hdr list (for mamake)
+ string/strtoip4.c: fix validity check bug that only checked last part
+02-03-14 misc/optget.c: fix --keys to not expand inline <.>..</.>\f
+02-03-12 port/astlicense.c: add type=free
+ path/pathaccess.c: sibling ".." search ignores relative dirs
+ sfio/sfvscanf.c: sfstrtof get() must return 0 on eof
+02-03-11 path/pathexists.c: check path by pairs checking {ENOTDIR,ENOENT}
+02-02-14 features/float: copy local min/max macros to avoid printf roundoff
+ features/wchar: include &lt;ast_common.h&gt;, not &lt;ast_std.h&gt;
+ misc/magic.c: match&#0091;&#0093;=&gt;matches&#0091;&#0093; to fix K&amp;R match() macro conflict
+ include/vmalloc.h: include &lt;stdlib.h&gt; for !_PACKAGE_ast
+ uwin/mini.sym: add sprintf (now required by features/common)
+ regex/regnexec.c: truncate wide chars for &lt;ctype.h&gt; functions
+ Makefile: fix MAM ast_common.h sequencing bug by making it first
+ cdt/dthash.c: fix DT_DELETE memory leak (DT_DETACH typo)
+ cdt/dthash.c: fix DT_DELETE double free (dt-&gt;data-&gt;here typo)
+ regex/regcomp.c: fix recomb() to reject RE with backref
+ features/iffeio: explicitly generate stdio.lcl
+ stdio: add {fcloseall,f(get|put)s_unlocked,fmemopen,getdelim,getline}
+ tmmake,tmtime: allow negative time_t if native localtime/gmtime do
+ tmdate: allow years before 1969
+ fmtfmt: add
+ include/ast.h: add { PATH_TOUCH_CREATE PATH_TOUCH_VERBATIM }
+ Makefile: add std/*.h for std header iffe overrides
+ comp/iconv.c: fix non-C win32 sfreserve() loop
+02-02-11 features/common: separate long long / long double tests
+ features/common: verify printf handles long long / long double
+02-02-02 include/ast_std.h,sfio/sfhdr.h: drop _hdr_locale tests -- always on now
+ include/ast_std.h: trust _UWIN &lt;unistd.h&gt;
+02-01-31 port/mnt.c: add aix options field
+02-01-30 comp/strstr.c: add for ancient s5
+ stdio/_flsbuf.c: only on systems that transfer to native (e.g., uwin)
+ string/strtoi.h: cat min/max error return values
+02-01-28 features/tty: add cf&#0091;gs&#0093;et&#0091;io&#0093;speed macros for &lt;termio.h&gt;
+ comp/rename.c: punt to (ancient) /usr/lib/mv_dir on EISDIR
+02-01-24 sigcrit.c: fix SIGCLD!=SIGCHLD interrupt loop
+ sfvprintf.c: convert fast io macros to functions for uts.390 cc
+ string/strtoi.h: drop #pragma prototyped for standalone sfio
+ sfdcsubstr.c: rename from sfdcsubstream.c for 14 char fs
+02-01-22 execlp,execvp,execvpe,spawnlp,spawnvp,spawnvpe: fix __EXPORT__
+ spawnlp,spawnve,spawnvp,spawnvpe: handle ms mode arg -- barf
+ sftable.c: ifdef hacks for _WIN32&amp;_ALPHA_ fp exception
+ _stdfun.c: add _UWIN&amp;_ALPHA_ iob map
+02-01-18 sfio/sfstrtof.h: drop #pragma prototyped for standalone sfio
+02-01-17 features/hdr: don't include &lt;stddef.h&gt; after it doesn't check out!
+02-01-16 misc/magic.c: add version type for YYYYMMDD or &#0091;a.&#0093;&#0091;b.&#0093;c.d
+ misc/magic.c: recode mime %s parse -- sensible and no buffer overflow
+02-01-15 misc/magic.tab,magicid.h: add generic binary magic number and header
+02-01-12 tm/tmlocale.c: override win32 default date for {C,POSIX,en} locales
+ comp/omitted.c: fix cygwin workaround logic bugs
+02-01-09 stdio/fseeko.c,ftello.c: add from UNIX98
+02-01-08 comp/conf.sh: use $cc instead of cc
+02-01-07 string/strlcat.c,string/strlcpy.c: add bsd api
+01-12-18 comp/conf.tab: fix LFS_CFLAGS default for sun _CS_LFS_CFLAGS botch
+ features/common: add hdr stdarg test
+ tm/tmdate.c: handle YYYY/MM/DD
+01-12-10 misc/magic.tab: add generic 0x00010203 binary magic
+01-12-03 path/pathprobe.c: return HOME relative path if readonly/non-suid fs
+01-11-30 misc/optget.c: add simple cache for repeat offenders (like ksh read)
+ sfio/sfhdr.h: preserve errno across SFMMSEQON-SFMMSEQOFF
+01-11-29 magic.tab: fix GIF version number listing
+01-11-28 string/fmtbase.c: p!=0 =&gt; base always included in output
+01-11-26 misc/fts.c: empty path is an error
+01-11-14 misc/optget.c: fix --?+SECTION queries to include paragraphs
+01-11-20 regex/regnexec.c: fix REG_MINIMAL character class match bug
+01-11-19 features/lib: retain _lib_confstr for all solaris releases
+01-11-16 comp/setlocale.c: fix !_lib_setlocale typo
+01-10-31 regex/ucs_names.h: add string catenation to keep line length low
+ misc/fastfind.c: handle gnu slocate db read
+ misc/optget.c: add --?+SECTION queries
+ comp/fnmatch.h: add FNM_NOSYS
+01-10-30 tm/tmdate.c: fix cron specs when both wday and mday are specified
+01-10-20 misc/glob.c: fix bug that called &nbsp;trim() twice on same path
+ misc/glob.c: fix &nbsp;trim() bug that restored / to wrong position
+ string/fmtre.c: fix { ^ . $ } translations
+ misc/optget.c: use original string if translation fails -- duh
+ sfio/sfhdr.h: assume &lt;errno.h&gt; assigns proper atttibutes to errno
+ comp/regcmp.c: __ia64 workaround fixed by proper CC.DLL probe
+ comp/getdate.c: __ia64 workaround fixed by proper CC.DLL probe
+ features/lib: add lib getdate
+01-10-18 features/lib: check for strtod static link collision
+ features/float: add another signed cast for old bsd cc
+ features/wchar: add &lt;stdlib.h&gt; &lt;stdio.h&gt; before &lt;wchar.h&gt; for old bsd
+01-10-17 sfio/sfcvt.c: limit max precision to { FLT_DIG DBL_DIG LDBL_DIG }
+ sfio/sfcvt.c: fix %&#0091;aA&#0093; format to always have leading 0&#0091;xX&#0093;1.
+ sfio/sfvprintf.c: handle %C %lc %S %ls for wchar_t args
+ sfio/sfvscanf.c: handle %C %lc %S %ls for wchar_t args
+ string/fmtmode.c: fix bug that omitted trailing '&nbsp;'
+01-10-12 misc/optget.c: . =&gt; <!--NULL-->. for --??nroff
+ comp/wc.c: fix mbstate_t initialization typo
+ features/float: fix max integer / float loop termiation
+ features/float: fix LDBL_UINTMAX_MAX typo that did DBL_UINTMAX_MAX
+01-10-11 include/sfio.h: fix _Sfstd* import/export
+ features/common: fix _UWIN __DYNAMIC__() definition
+01-10-06 features/fcntl.c: { O_BINARY O_TEXT } default to 0
+ features/omitted: add for comp/omitted.c
+ sfio/sfopen.c: O_BINARY default for _WIN32&amp;&amp;!_UWIN
+01-10-05 misc/glob.c: fix `\(x/*' GLOB_NOMATCH bug that returned `(x'
+ misc/optget.c: fix localization lookup that didn't drop doubled : ? &#0093;
+01-10-04 comp/setlocale.c: handle sizeof(wchar_t)!=4 in debug locale
+ comp/conf.sh: handle sytems where _SC_* is both an enum and a macro
+01-09-25 astconf: add LIBPREFIX
+01-09-20 features/common: add __DYNAMIC__() for dll externs
+01-09-19 cdt: kpv update
+ mb*() macros: update for ksh conversion, extend debug locale
+01-09-16 tm/tmlocale.c: add compiled in defaults for C locale
+ misc/glob.c: add gl_nextdir callback for GLOB_COMPLETE
+01-08-14 clarify _WIN32 vs. _UWIN vs. __CYGWIN__
+ tminit: fix standard &amp; daylight initialization
+01-09-11 pathnative.c: add for native fs representation
+ regex.h: fix regerror_t prototype
+01-09-04 regex/regnexec.c: fix REG_ICASE for multi-char collating elements
+ tm/tmlocale.c: fix old ascii LC_TIME load
+ locale*: add new LC_* categories
+ comp/omitted.c: add CYGWIN workarounds
+ features/lib: add CYGWIN workarounds
+01-08-11 features/common: some compilers have long long but no LL constants!
+ features/lib: add mmap64 implementation test (for linux.s390)
+ regex/regcomp.c: fix &nbsp;in &#0091;...&#0093; parse
+ setlocale: retain user locale spelling in setlocale() return value
+ features/limits.c: don't include ./limits.h -- duh
+ fmtesc: don't escape multibyte chars
+ tm/tmlocale.c: fix native C locale default
+01-08-08 features/float: some compilers (msdev) forget long long vs. double
+01-07-31 misc/optget.c: handle suboptions
+01-07-27 cdt.h: add DTDISC()
+01-07-17 iffeio.h: move to include for stdio bootstrap iffe workarounds
+01-06-25 regex: perl extensions added and tested
+01-06-21 misc/error: add ERROR_OPTIONS=prefix=string for message processing
+01-06-15 string/chresc: only 2 hex digits max for \xxx
+ regex/regsub: handle REG_SHELL ~(nnn) rhs backrefs
+01-06-11 regex: handle embedded &nbsp; in pattern and subject string
+ regex: add (?nnn) for backrefs &gt; 9
+ comp/fnmatch: add FNM_LEADING_DIR for gnu compatibility
+ features/float: _ast_flt_unsigned_max_t for bsd.i386 omission
+01-06-06 misc/optget.c: add o option for old ps,ar,tar with optional leading -
+ regex/regcomp.c: REG_LENIENT|REG_DELIMITED \&lt;newline&gt; =&gt; &lt;newline&gt;
+ regex/regcomp.c: REG_LENIENT &nbsp;00 =&gt; NUL
+01-06-04 features/dirent: replace Makefile hack with iffe semi-hack
+ regex/regnexec.c: negation must also check REG_SHELL_DOT
+01-06-03 sprintf.c: change buf size from SF_BUFSIZE to INT_MAX
+01-05-31 glob: fix gl_fignore to ignore leading . by default
+ features/lib: add botch_d_ino_dirent64 for linux botch
+01-05-25 port/lc.tab: add a few missing language_territory's
+01-05-23 string/chresc: \C&#0091;.collation-element.&#0093;
+ fmtmatch,fmtre: update for &lt;regex.h&gt; syntax extensions
+01-05-21 regex: add perl extensions, unicode names for collation elements
+01-05-11 string/chresc: &#0092; == \E == escape, <JOIN>X == control X, \x{..} == \x..
+01-05-09 path/pathtemp.c: pathtemp(0,0,0,"/private",0) for mode S_IRUSR|S_IWUSR
+ port/touch.c: handle utime(2) EPERM to fix bug that truncated
+ regex: change REG_MINIMAL to avoid negation -- much faster now
+01-05-08 *.h: add some off_t macro guards for suse linux
+01-05-03 regcomp.c: optimize ((x)!)* to ((x)!)
+ wchar: add &lt;wchar.h&gt; and stdio wchar routines
+01-05-02 feaures/wchar: add &lt;wchar.h&gt; intercept, add stdio wchar functions
+01-05-01 string/strtoi.h: signed strtoi accepts qualified unsigned constants
+01-04-30 comp/setlocale.c: fix code that relied on 2 simultaneous getenv()'s
+ tm/tmlocale.c: check for UTF-8 encoded LC_TIME files
+ misc/magic.tab: add utf-8 and utf-16 U+FEFF magic
+01-04-26 features/common: some cc's have _ast_int8_t but not LL constants
+01-04-24 features/lib: add _std_strtod for mac os X
+01-04-23 ccode: add CC_sub for ms embedded EOF char on ebcdic -- no joke
+01-04-20 iconv: handle ebcdic&lt;=&gt;utf
+ mc.h,mc.c: add mcindex()
+ ast_std.h: add AST_MESSAGE_SET
+01-04-18 features/libpath.sh: fix mvs probe
+ *: sundry mvs fixes
+ glob: fix GLOB_NOCHECK to avoid stat() and properly trim patterns
+01-04-01 strtod,strtold: add
+ strtol,strtoul,strtoll,strtoull,strton,strtonl: handle locale &amp; ERANGE
+ sfvprintf,sfvscanf: handle locale decimal_point,thousands_sep
+ sfvprintf,sfvscanf: handle %a,%A
+ setlocale: add LC_NUMERIC decimal_point,thousands_sep init
+ ast_std.h: __OPTIMIZE_SIZE__==1 to disable non-std __GNUC__ inlines
+ pathexists: path cache to cut down pathpath() access(2) calls
+ features/stdio: __FILE_TAG == _sfio_s for solaris
+01-03-23 iconv: fix iconv_move buffer boundary bug that stopped at 1 block
+01-03-19 glob: add GLOB_AUGMENTED
+ regex: REG_SHELL syntax error implies REG_LITERAL match
+ strto&#0091;ln&#0093;&#0091;ll&#0093;: add overflow checks
+01-03-17 locale: reimplemented to provide canonical locale namespace
+ locale: add LC_ALL=local for local system user default
+ tm.h: TM_*_3 =&gt; TM_*_ABBREV
+ tmfmt: handle standard E and O format modifiers
+ tmlocale: consult nl_langinfo() if defined
+ fmtquote("
+01-03-08 regex: handle multibyte chars and collation classes
+ strmatch,strgrpmatch: now a wrapper on regex
+ ast_std.h: add mb*() multibyte and collation support
+ sfvscanf: handle locale decimal and thousand
+ proc*,system: handle ignored SIGCHLD
+ sfkeyprintf: handle %*C
+01-03-06 locale: add locale data cache for efficient multiple locale switching
+ optget: fix LC_MESSAGES!=C --man bug
+01-03-01 Makefile: HEADEROPT is not optional for win32.*
+ comp/syslog.h: comply with the de factos
+ optget(): fix <.>..</.>< >stack bug that referenced data after pop</ >
+01-02-27 *locale*: a batch of fixes for native LC_MESSAGE&amp;LC_TIME hooks
+01-02-22 pathprobe: reprobe test now checks probe.ini too
+ sfio_s.h: advertize public Sfio_t members with _ prefix
+ sfio.h,features/stdio: add &lt;sfio_s.h&gt; reference
+ sfhdr.h: map &lt;sfio_s.h&gt; _foo to foo
+ sfio.h: SF_APPEND=&gt;SF_APPENDWR, SF_CLOSE=&gt;SF_CLOSING
+01-02-14 comp/conf.sh: probe &lt;unistd.h&gt; for _(CS|PC|SC)_* getconf symbols
+ stdio/*: update for uwin stdio.dll binary compatibility
+ sfread: finally fixed premature pipe read EOF bug
+ fmtscale: format tenths for number &gt; 0 &amp;&amp; number &lt; 10
+01-02-09 _sfmode(),_sftype(),_Sfextern: UWIN binary stdio compatibility exports
+01-02-08 sfgetm,sfputm,_sfputm: fix max clash with k&amp;r max() macro
+ setlocale: undef valid for sun4 k&amp;r valid() macro
+01-02-07 catopen.c: don't do native catopen for the debug locale
+01-02-06 sfraise.c: add SF_FINAL check to avoid (posibly) freed disciplines
+01-01-01 features/common: fix uwin __DEFINE__
+ sftable: initialize decimal and thousand
+ magic.tab: add corel wordperfect document
+ syslog: add LOG_LEVEL, add ' only if needed
+ include/tm.h: #undef daylight for _WIN32
+ sfio.h: add _SF_APPEND and _SF_CLOSE for native namespace incursion
+ ast_std.h: add AST_LC_multibyte for MB_CUR_MAX&gt;1
+ setlocale: set AST_LC_multibyte
+ strmatch: check AST_LC_multibyte
+ features/limits.c: add _BITS_POSIX1_LIM_H guard for linux
+ features/libpath.sh: fix for aix LIBPATH
+ procopen,procclose: block SIGCHLD if PROC_FOREGROUND (e.g., system(3))
+ optget.c: add enumerated option argument values
+ optget.c: add &lt;!--INTERNAL--&gt; for private --html
+ optget.c: fix memory leak that hit shell builtins hard
+ sfio: drop sfread small chunk logic
+00-12-25 mnt.c: handle " and ' quoting for fstab
+ sftmp.c: let pathtemp() open the fd O_EXCL
+00-12-15 conf.sh: add -v for verbose trace
+ features/(limits|unistd).c: no FEATURE/types because of _POSIX_SOURCE
+ features/time: add default for CLOCKS_PER_SEC
+ features/lib: std_malloc now handles NeXT
+00-12-13 strton: recognize qualifier only if preceded by a digit
+ features/lib: change return in vfork() test to exit() for linux sparc
+ fmtquote: fix $'...' quote logic
+00-12-11 tmdate: fix cron format bug that mishandled months
+00-12-01 optget: handle $Id: ... $ in --?-version
+ features/fcntl.c: fix _STDPP_ mmap munmap
+00-11-27 magic: drop dup sfclose() in load()
+ optget: handle error_info.id==0
+00-11-22 features/stdio: add _FILEDEFED for sol9.sun4
+ strton,stronll: handle &#0091;u|U&#0093;&#0091;l|L&#0093;&#0091;ll|LL&#0093; qualifiers
+00-10-31 tmdate: add TM_DATESTYLE and mmddHHMM&#0091;cc&#0093;yy
+ astlicense.c: #include &lt;hashkey.h&gt; MAM workaround
+ astlicense.c: check for non-empty CONTRIBUTORS
+00-10-26 features/stdio: add _FILE and __FILE for gnu
+ misc/stk.c: fix stack pointer check off-by-one (dgk does it too!)
+00-10-23 syslog.h: sync with bsd values
+00-10-18 _STUB_* now functions instead of common symbols
+ all extern data declared with definition to eliminate common symbols
+ fastfind: add mac/bsd /var/db/locate.database
+00-10-17 features/lib: add apple osX (darwin.ppc) workarounds
+00-10-12 add: fmtbuf(), fmtclock(), fmtip4(), strtoip4()
+ fmt*() now use fmtbuf() for tmp fmt buf allocation
+00-10-05 regex: add REG_DISCIPLINE and regdisc_t for alloc/error disc
+00-09-29 features/lib: pipe_rw==0 for sgi: boot rw == bin incompatibility
+00-09-21 astlicense: handle ' and
+00-09-20 sfwrite: fix write() error in sfprintf() loop
+00-08-11 hdr,vmhdr.h: check/hide { getpagesize sbrk } prototypes
+ astlicense: add noncommercial
+00-07-31 fflush: don't seek on pipes
+ sfresize: add
+ setlocale: fix bad newof() call
+00-06-01 strmatch: initialize match.current.beg&#0091;0&#0093; to avoid dump at line 670
+ sfio/stdio: a few more errno tweaks
+ astquery: sfstdin/sfstderr by default
+00-05-26 sfmode: errno=EBADF for invalid stream use
+00-05-22 rewind: fix for xopen test
+00-05-18 mcfind: returns absolute path
+00-05-16 optget: --keys must catch <.>..</.>< >too</ >
+ translate,mc: errno cleanup
+00-05-09 magic: add netbsd binary magic
+ fts: PATH_RESOLVE!=logical =&gt; FTS_SEEDOTDIR
+ ftwflags: call fts_flags()
+ astconf: astconf(0,0,0) re-syncs with _AST_FEATURES
+00-05-08 optget: --usage &amp; --keys for last -catalog group only
+00-05-02 iconv.c: add; use codes&#0091;&#0093; in ccmapid() and ccmapname(); "" for native
+00-05-01 pathtmp: copy env values (libshell or putenv may change)
+00-04-01 optget: drop bar from &#0091;-foo?bar&#0093; for --??keys
+ sfvscanf: add %X -- duh
+ features/common: fix va_listval() for power pc
+ findopen: fix FIND_GENERATE codes file search
+ magic: add ERROR_translate() and msgcat.key
+ tmlocale: add for LC_TIME locale info
+ tmlex: check tm_info.format and tm_data.format
+ tmfix: fix for tm_wday special case (via nl_langinfo on LC_TIME fields)
+ strftime: fix for nl_langinfo special case
+ ast_std.h: provide LC_* defauls if not defined
+ sfnew: check ${_AST_sfio_bufsize} -- don't tell kpv
+ catopen,nl_types.h: add intercept to mc* routines
+ magic.tab: add ast message catalog
+ strerror: add _ast_strerror intercept with ERROR_translate("errno")
+ fmtquote: escapes &gt;0177 only if (flags&amp;2)
+00-03-17 feof: stdio macro functions only for _UWIN
+ optget: proper ERROR_translate() calls
+ astgetconf: add for thread safe error message control
+ astlicense: fix type=special but with non-null notice
+ errorx: add for ERROR_translate() support
+ ERROR_translate: add locale id args for alternate dictionary
+ option.h: move _OPT_PRIVATE_ to pointer to avoid dll size mismatch
+ ftwalk: fix FTW_CHILDREN bug that hit top level non-dirs twice
+ translate.c: default error_info.translate
+ astconf: fix dup loop thrash that never returns, add _AST_VERSION
+00-03-10 ast_std.h: do _LARGEFILE_SOURCE initialization before std headers
+ fmtquote: handle $'...' quotes
+00-03-07 optget: fix numeric option support test
+ sfkeyprintf: add %q for '...' quoting with ansi escapes
+00-03-06 features/stdio: fix _sfflsbuf prototype (dingold@gte.net)
+00-02-14 pathtmp: fix pid cache bug that sometimes repeated after ~10 attempts
+ optget: "..." attribute quote
+ pathfind: eliminate *: prefix in lib, not type
+ proc: PROC_FOREGROUND for system(3) semantics (wait status return)
+ pathtmp: fix mktemp() logic
+ fts: fix FTS_NOSEEDOTDIR bug that botched ./* in top list
+ include/ast/prototyped.h includes include/prototyped.h
+ pathpath: fix strdup(0) bug
+ optget: --html <SMALL>&lt;<A href=mailto:foo@bar>foo@bar</A>&gt;</SMALL> =&gt; ...mailto:foo@bar...
+ sscanf: fix sfsscanf =&gt; sfvsscanf typo
+ magic.tab: strengthen tar recognition
+00-02-08 conf.sh: fix ifdef for systems that think sysconf(FOO) is const
+00-02-04 glob: fix globlist_t.gl_flags
+00-02-02 vm*: add NoF() for data only files
+00-01-27 fts: fix top level .==.. statp bug (thanks to dr. ek)
+00-01-25 conf.tab: fix LFS*_*LAGS typo
+00-01-24 astlicense: handle type=verbose, license.notice, author=*
+00-01-11 pathprobe: generate info for first probe script on PATH - duh
+ ast.h: add NoF(x) for files that define no functions
+ tmpfile: fix implementation
+ global change for string ERROR_translate() dictionary names
+ optget: fix new way but no long names off by one
+ optget: handle &#0091;--dictionary?name&#0093;
+99-11-19 comp/conf.sh: `expr length XXX` is not universal
+ drop sfstdio; stdio via functions everywhere
+ drop Makefile conditionals (and follow our own advice for once)
+ sfio: new stream after atexit() bug fix
+ tm: Tm_zone_t.daylight=0 for standard time within zone
+ stdio: fopen =&gt; _ast_fopen: only way short of binary compatibility
+ Makefile: atmain.C falls back to atmain.c
+ optget: add --keys, s&lt;section&gt; option
+ stdio: _UWIN check for foreign stdio
+99-11-11 astlicense: add
+99-10-31 glob: fix regexec pattern; add PATH_ATTRIBUTES case check
+ pathpath: path==0 means malloc space
+99-10-22 tmfmt: %C=2-digit-century, %k=date(1), %y=2-digit-year-in-century
+99-10-18 fastfind: expanded default db lookup
+99-08-11 magic: fix off by one registry malloc
+ features/fs: add __RENAME checks for stat familiy (netbsd)
+ features/fs: major()/minor() fixes for s5
+ features/libpath.sh: netbsd fix -- ld.so not in std places
+ misc/fastfind: fix codes path generation bug
+ optget: beef up --?* description, fix &lt;TR&gt;...&lt;/TR&gt; nesting
+ pathprobe: check for override (writable key file) first
+ features/time: int tmtimeofday(struct timeval*);
+ optget: fix opt_info.num, even if opt_info.arg!=0
+ fts: FTS_PHYSICAL =&gt; FTS_SEEDOTDIR, add FTS_CHOP
+ fastfind: init dir tab with logical and physical name
+ glob: add gnu GLOB_ALTDIRFUNC
+99-07-17 sfio: kpv update and sfhdr.h sync!
+99-06-24 stdio: fix fflush() to ignore sfseek(0) return value
+99-06-23 magic: '\r' is text not control to placate m$
+99-06-08 stdio: fix fseek,ftell semantics
+ uwin stdio: fflush() =&gt; _doflsh() to avoid __cplusplus clash
+ getopt: call liberror() to avoid error() conflict
+ tmfmt,tmscan: %N zone type (nation code), %z zone minutes west offset
+ tmfmt: - no pad _ space pad 0 leading 0 pad
+99-05-28 magic: fix 'x' == '*' for any number, magic.tab tweaks
+ features/lib: verify that stat64 really works
+99-05-21 tm*: add TM_WINDOW==69 for consistent century windowing guard year
+99-05-18 tmtime: add century leap year calc anticipating unsigned time_t
+99-05-17 sfkeyprintf: handle %o and %x!!
+99-05-09 pathprobe: $HOME/.probe if not suid and st_uid!=geteuid()
+99-04-28 magic,magic.tab: add registry()
+99-04-24 regcomp: fix ksh pattern +! parse
+ regfatalpat: add
+ optget: make : ? &#0093; double escape consistent in all contexts
+99-04-01 features: drop iffeio.h and stdio.h when only printf() used
+ regex: fix stats() .l and .k count
+ fmtquote: added; most general fmtesc() form
+99-03-22 fmtesc.c,ast.h: add fmtnesq()
+ optget: --?x works for -x option flag
+99-03-17 features/limits.c: workaround solaris __EXTENSIONS__ _timespec bug
+ workaround limits.h circular prereq with ignore stdio.h
+ sfvprintf: %04e left-pad zero fixed
+99-03-03 fts: uncle already: add FTS_SEEDOTDIR to retain leading ./
+ regex: REG_MULTIPLE, BM for fixed string alternation
+ optget: embedded `-' optional in long options, prefix={0,1,2}
+99-02-14 fastfind: fix dir format bug that emitted wrong paths
+ astconf: fix redef off by one bug
+99-02-11 pathcanon(): don't cache astconf("PATH_LEADING_SLASHES", NiL, NiL)
+99-01-23 optget: move &lt;old_opt.h&gt; back into &lt;option.h&gt;, no open-close
+ optget: add "&#0091;index:long-name:description&#0093;" for --long-name
+ comp/gross: add weak __libc_attr for irix &lt; 6.5 compatibility
+ features/limits.c: tweak the guards again
+99-01-11 fastfind: handle old format count byte order
+ magic.tab: fix elf to use real phdr offset
+ magic.c,magic.tab: fix | to act like switch/case
+ comp/fross.c,features/hack: for gross hacks
+ features/stdio: avoid sfio namespace pollution
+98-12-25 tmdate: yyyy.mm.dd
+ pathprobe: fix procrun() cmd path bug
+ fmtesq: add
+ features/common: win32.alpha va_list
+ magic: add pc alpha object
+98-11-11 strmatch: add STR_ICASE
+ pathprobe: punt to $HOME/.probe/&lt;key+HOSTTYPE&gt; if not S_ISUID
+ tmzone,tmdate: handle +-minutes, nn/MMM/yyyy
+ stropt: fix nested quote pop
+ tmfmt: add %K =&gt; %Y-%m-%d/%H:%M:%S
+ sfio/stdio: fix fseek() SF_PUBLIC omissions
+ fmtesc: catch '\' (duh)
+ vmalloc: vmbest round bug fix
+98-11-01 fts.c: no pathcanon() if (fts_flags &amp; FTS_PHYSICAL)
+98-10-01 features/stdio prototype fixes
+ optget: strton() instead of strtol() for #
+98-09-22 regcomp: add REG_DELIMITED and REG_ESCAPE delimited re support
+98-09-15 fix _LARGEFILE64_SOURCE stuff
+ ast_std.h: provide mmap() prototype
+98-08-11 fix sfpopen() to ignore SIGPIPE by ignoresig() for sfio but not stdio
+ fix procopen() to ignore SIGPIPE by ignoresig() for PROC_IGNORE
+ sfio sfpopen/popen update
+ magic.src: fix ustar entry
+98-07-17 fix ftwalk() short by one malloc()
+ add fts_notify()
+98-06-25 sfdcmore,sfdcprefix: add
+98-06-19 tokscan: add %f %g
+98-06-01 disc/sf*.c: memset(0) after disc malloc()
+98-05-11 strelapsed: y==Y
+ fts: pathcanon() top list
+98-04-01 error: error_info.time for all msgs, just after cmd id
+ error: no sfsync(sfstdin)
+ sfio: sfpool, Sffmt_t update
+ magic.tab: sgi core dumps -- why aren't these elf?
+ stropt: (v+n) for unknown option is option value if n!=0
+ procopen: fix setsid() for spawnveg() only
+98-03-19 malloc: add realloc foreign region check
+ sfdisc.h: rename to match kpv disciplines
+ fastfind: fix strcasecmp/strcmp directory prefix mixup
+98-03-17 features/fcntl.c,pathtmp,sftmp: add O_TEMPORARY
+98-03-01 pathcanon: fix PATH_LEADING_SLASHES to stat() both slashes
+ pathcanon: add PATH_VERIFIED
+ tmdate: add skip&#0091;&#0093; to expand separator char set
+ fastfind: FIND_OLD for old 7 bit db, FIND_TYPE for new 8 bit typed db
+ fastfind: default generates gnu LOCATE02 8 bit db
+ magic: handle %s in mime description
+ cdt: kpv update
+ sfio: kpv update
+ stdio: fpos64_t fseek64(), ftell64(), fgetpos64(), fsetpos64()
+ stdio: fseek() =&gt; sfseek(SF_PUBLIC) to avoid locking
+ fts: initialize parent stat&#0091;bp&#0093; from top level *after* statf done
+ astmath: add -lm requirement test
+ *: Astlong_t =&gt; _ast_*_t
+ regex: simplify regcollate() (from doug)
+ tmtime: preserve Tm_t*tm when calling tminit()
+ astconf: add readonly PATH_ATTRIBUTES=&#0091;cirw&#0093;
+98-02-14 fastfind: add FIND_ICASE to ignore case
+ tmdate,tmgoff: handle (+|-)hh&#0091;&#0091;:&#0093;mm&#0091;&#0091;:&#0093;ss&#0093;&#0093; absolute timezone
+ tmdate: `&lt;n&gt; &lt;part&gt;' now assumes `next &lt;n&gt; &lt;part&gt;' instead of `this'
+ tmfix: fix leap year bug that forgot to add 1900
+ proc: add PROC_ZOMBIE
+98-02-06 strmatch() char class range bug fix
+ regex char class range bug fix
+98-01-23 _WIN32: changed the #if logic again to accomodate _GNUC_
+ mnt: grab the mount options too
+ ast_std.h: hide getopt,getsubopt from stdlib.h
+ features/limits.c: add gnu guard macros to avoid limits.h recursion
+ features/mode.c: include "limits.h" instead of "FEATURE/limits.lcl"
+98-01-11 sfio.h: use Astlong_t, move Sfio_t Sfdisc_t typedef to top for stdio.h
+ sfhdr.h: #undef SETLOCAL for hpux
+ sfvprintf,sfvscanf: %I*x for sizeof(int_arg)
+ handle ftruncate64 and truncate64
+ dtopen.c: __hppa dll needs Dtset Dtlist Dttree refs here
+97-12-18 fmtnum: add
+97-12-11 magic: handle sgi 64 bit core dumps
+97-12-07 pathtmp: add override for TMPPATH,TMPDIR and cycling
+97-11-11 tm: handle 0 return from gmtime(),localtime() (dos negative time_t)
+ features/stdio: fix fflush() macro to do physical sync
+97-10-31 astconf PATH_RESOLVE is logical if 3d&amp;&amp;!std, metaphysical otherwise
+ magic: fix #! mime bug
+ tm: tmtime() now calls tmfix() and adjusts tm_isdst too=&gt;mtime() works
+97-10-11 dllfind,dlfcn: move to separate -ldll so -last can link static, duh
+ Makefile,state.c: move forced header generation state.c =&gt; Makefile
+ sfio: update including SF_WHOLE
+97-10-01 sfdostext: add \r=&gt; sfio discipline
+ stropt: NiL table =&gt; p=name for all name=value
+97-08-11 pathtmp: check pid to note forks
+ procopen: FD_CLOEXEC rfd &amp;&amp; wfd
+ fts: fts_close() after fts_children() with no fts_read() now works
+97-07-17 error: sfsync(sfstdin,sfstdout,sfstderr) instead of sfsync(NiL)
+ _sfcvinit: add sfio internal interface to base conversion tables
+ strton: use _Sfcv* base conversion tables instead of sfsscanf()
+ sfvscanf: use _Sfcv* base conversion tables
+ mime: x- permutations now matched if exact fails
+ mime: original- stripped from content-* headers
+ tmdate: add yyyy-jjj, yyyy-mm-dd
+ dllfind: add
+ ccmapid: fix buf copy loop limit
+ ccmapname,ccmapcpy: add
+ sfstrtmp: add
+97-05-09 streval: fix up casts for pseudo-ansi cc
+ features/types: use _ast_int_8 vars to verify support
+ string/modedata: check for mvs.390 S_IFMT
+ include/ast(_std).h: add #define __FILE_typedef
+ magic: add ccode text check
+ include/ftwalk.h: FTW_PATH=&gt;FTS_NOCHDIR to avoid FTS_AGAIN (duh)
+ fts: clear status for FTS_AGAIN (fixes rm -r bug)
+ mnt: add mvs openedition w_getmntent()
+ sfhdr: _hdr_float &amp;&amp; &lt;float.h&gt; for correct MAXDOUBLE
+ vmalloc/vmbest: if _std_malloc then use malloc()/free() not sbrk()
+ remove: check _std_remove
+ procopen: handle pio&#0091;{0,1}&#0093;=={0,1}
+ setenviron,features/uinstd: test for mvs.390 dll environ hacks
+96-12-25 &lt;sfio_p.h&gt; -&gt; &lt;ast_common.h&gt;
+ __EXTERN__(type,object)
+ __DEFINE__(type,object,value)
+ magic: check strings in !CC_NATIVE code set too
+ system: cmd==0 means check for shell access (xopen)
+ sfhdr.h: fix sfrsrv prototype
+ add __libc_malloc etc for gnu/linux
+ astconf(NiL,path,name) == astconf(name,path,NiL) + no liberror
+ fts_open: if toplist() stat fails return 0
+ ftwalk: handle fts_open()==0 via one phony userf() call
+ sfmode: S_ISFIFO default is SF_SHARE=0
+ features/lib: _WIN32 _lib_vfork=1 by default
+ unsigned&lt;0 comparison and other fixes via sgi.mips4 cc
+ stk.c: use &lt;align.h&gt; ALIGN_BOUND for stkalloc()
+ features/lib,vfork: uwin fix
+ ast_std.h: fix strto&#0091;u&#0093;ll prototypes with features/types _ast_int_8
+ getsubopt: add for xopen 4.2 compatibility
+ drop function __IMPORT__
+ magic: more magic
+ change #define FILE from Sfio_t to struct _sfio_s
+ state.c: add generated includes that may be hit by std for MAM
+ bytesex: forgot about sizeof(long)=&gt;7; could we fix the name too?
+ vmalloc.h: fix vmnewof() definition
+ sfio.h,stdio.h,ast_common.h: pollution cleanup
+ magic.c: add | op for switch
+ Makefile: stdio.h was on both HEADERSRC and HEADERGEN -- don't do that
+ drop pp:notice to get &lt;sfio.h&gt; ... &lt;ast.h&gt; to work
+ regex: add &#0091;&#0091;:&lt;:&#0093;&#0093;==\&lt; and &#0091;&#0091;:&gt;:&#0093;&#0093;==\&gt; for bsd compat
+ mime.c: ignore X-* headers while scanning for Content-*
+ magic.c: check for negative indirect offsets
+ magic.tab: fix dos entry that generated negative indirect offsets
+ vmalloc.h: add vmstrdup() prototype
+ hash.h: add hashgetbucket() macro
+ magic.c: MAGIFILE is now a : file list
+ mnt.c: another 4.4 bsd fix -- users must include &lt;sys/crap.h&gt;
+ common: fix _WIN32 chicken&amp;egg with va_copy
+ sfio: forgot to set f-&gt;val along with _Sfi in sfexcept()
+ Makefile: add mini target for uwin libmini.a
+ sfcvt.c: workaround for flaky long double optimizers
+ features/common: fix to work with va_list==void*
+ regexec.c: fix REG_STARTEND subexpression offsets
+ strmatch.c: don't forget &lt;wctype.h&gt;
+ regrexec.c: fix REG_INVERT end boundary bug that missed last record
+ astconf.c: notify(0,0,"a=b") called for each setenviron("a=b")
+ pathcanon.c: check astconf(PATH_LEADING_SLASHES) to preserve //*
+96-11-28 _LARGEFILE64_SOURCE by default if possible: NOTE: assumes xopen
+ regerror: fix for xopen
+ getopt: fix for xopen
+ magic: add ciao virtual database
+ astconf: posix/strict/xopen implies "standard" conformance
+ fs3d.h: hide mount prototype
+ ast_std.h,mnt.c,features/fs: ncr port tweaks
+96-10-31 version 5.0
+ add strtoll() strtoull()
+ sfkeyprintf: upgrade to int_max args
+ ast.h: add ssizeof() to work around unsigned botch
+ conf.sh: add shell actions to conf.tab
+ _DLL*: drop for _BLD_&lt;lib&gt; + __EXPORT__ + __IMPORT__
+ sfio,cdt,vmalloc: kpv update
+96-10-11 &lt;ccode.h&gt;: add character code map support
+ procclose: return shell style exit status
+ features/fs: pun statvfs.f_basetype to statvfs.f_reserved7 for mvs
+ uwin: add subdir for uwin additions
+ ast_std.h: swab() is from &lt;stdlib.h&gt;
+ sfio.h: &lt;ast_std.h&gt; if _PACKAGE_ast
+ magic.tab: add mips&#0091;1-4&#0093;, 64-bit
+ port tweaks for sol.sun4 and sun4
+96-09-06 strerror: add
+ fmterror: uses strerror
+ str*search: use sfiso646() order
+ strpsearch: add
+ magic: add Magic_t.mime mime type return for magictype()
+ mime.h: add
+ strton: use sfsscanf()
+ strperm: factor in umask() if no who
+ pathtmp: add TMPPATH check
+ libevent: add
+ magic: add discipline to magicopen()
+ mime: add discipline to mimeopen()
+96-08-31 regex: fix BM fail table generator
+96-08-11 mntread: fix mnt.type for SCO variant
+ conf.tab: add SCO KERNEL_* sysconf() vars
+ fastfind: add findwrite(), fix findread() FF_OFF omission
+ ftwalk: reimplement on top of fts
+ fnmatch,re_comp,regexp: reimplement on top of regex
+ basename,dirname,fmtmsg,fts,ftw,getdate,getsubopt,glob: add
+ hsearch,nftw,realpath,strftime,strptime,swab,tempnam: add
+ tsearch,wordexp: add
+ getcwd: cache last path for easy test
+96-07-17 error: sfsync(NiL) ... write ... sfsync(sfstderr)
+ astconf: handle readonly *(DEV|DIR) vars
+96-04-01 swapop: fix stupid return value bug
+ features/int.c: fix int_swap generation bug
+ regnexec,regrexec: fix unsigned underflow init error
+ ls.h: fix iblocks() to be in units of LS_BLOCKSIZE
+96-02-29 magic: space before function is definition with no call
+ hash: drop hash_info from public interface
+ hash: OBSOLETE hashlast()
+ hash: add Hash_root_t.Hash_last_t to public interface
+ add strsearch() and strnsearch() to complement strlook()
+ add hashkey.h for keyword-&gt;long hash
+ pathpath: pathpath(0,0,"",0) disables $0 $_ $PWD relative search
+ sfio: sfstrtod+sfhdr update
+ regex: fix REG_LENIENT to map BRE \&#0091;+?|&#0093; to ERE &#0091;+?|&#0093;
+ change _std_malloc iffe test so it doesn't hang on alpha
+ sfhdr.h: features/sfio generates _lib_cvt instead of _i386_cvt
+ ast_hdr.h: add va_copy(a,b) to copy va_list b to a
+ getopt: fix stupid getopt() -&gt; optget() bug
+ sfvprintf: %h? now downcasts
+ regex: handle strto?l() errno in regcomp()
+ sfstrtod: _Sfstrtod_already_defined -&gt; _STUB_sfstrtod
+ ast_std.h: hide valloc() and ignore &lt;strings.h&gt;
+ sfkeyprintf: pass phony va_list for '2'
+ regex: change HIT var type from int to size_t in special()
+ ast.h: add EXIT_STATUS(x) to convert wait() status to sh exit status
+96-02-14 regex: add _ to \&lt;...\&gt; isalnum test
+ regex: fix BM inner loop breakout
+ features/types: size_t is signed on some systems! =&gt; _ast_size_t
+ sfio: sfrd discipline peek optimization
+ vmalloc: vmalloc.h malloc family macro upgrade
+ tokopen: fix newline bug for non-restore open
+ sfio: no inline for gcc until it emits for -g too
+96-02-12 sfio: internal upgrade
+96-02-09 regex: Boyer-Moore boundary fix
+ vmalloc: snarf latest
+96-02-06 regex: add regrecord() and regrexec() for Boyer-Moore record filtering
+ regex: rearrange regnexec() args to match buffer,count arg style
+96-01-31 stk: add STK_NULL to stk.h and stk.c
+ regex: privatize regex.h and fix min re length computation
+ workaround lazy strdup() implementations in features/lib _std_malloc
+ fix stkclose() to free(stream) -- purify missed because of sfio links
+ unused var cleanup
+ port/mnt.c must include &lt;ls.h&gt; to get &lt;ast_fs.h&gt;
+ add SF_FINAL to sfio and stk
+ sfio reads now on natural block boundaries
+ add #!!! &lt;level&gt; &lt;message&gt; !!! to tokline()
+ add REX_BM pre-filter to regcomp/regnexec
+96-01-22 add regcomp env.paren overflow checks
+96-01-11 add Doug McIlroy's regex (converted to C from C++ by gsf)
+ AT&amp;T Research now
+ sfgetr optimization
+ regex buglets
+96-01-05 tweak magic.tab for win32
+95-12-25 add !(...) -&gt; (...)! to fmtre()
+ nt tweaks -- functions with no header proto must be defined extern
+95-11-24 version 4.1
+ add mnt.h mntopen mntread mntclose
+ convert fmtfs to mnt.h
+ add RE_LEFTANCHOR and RE_RIGHTANCHOR
+ gcc inlines must also have global library function instantiation!
+ add hashview()
+ fix strtape() internal buffer flow
+ fix mntread() fs/dir transposition for uts mnttab
+95-10-31 change features/unistd.c includes to break limits-param cycle
+ add cdt from kpv
+ sfio snarf from kpv
+ add &#0091;ht&#0093;search for _WIN32
+95-10-11 clarify PARANOID pathcheck() warning
+ fix procopen() LIB_SPAWN environ bug with setenviron() cache
+ fix setenviron() bug that forgot to reset environ if == 0
+ add %Z '&nbsp;' output format to sfkeyprintf()
+ sfio snarf for sfvprintf fix
+ allow multiple hashscan() with scope caveat
+ add comp/fakelink.h to synthesize a few symlink text patterns
+ add !&lt;xxx&gt; magic to misc/magic.tab
+ add FTW_TOP to inhibit recursion (for ftw side effects on top level)
+ add memfatal() common malloc fatal exception message
+ add dos \rtest to misc/magic.c/cklang()
+ sftmp() O_EXCL+random to avoid collisions
+ pathtemp() uses sftmp() randomizing
+ features/fs uses SF_APPENDWR
+ sftmp() uses pathtemp() -- don't worry, its not circular
+ a few more _WIN32 compatibility additions
+ realloc fixed to use VM_RSCOPY|VM_RSMOVE instead of obsolete 1
+ add hashlook(tab, oldname, HASH_RENAME, newname)
+ a few more tweaks to satisfy port warnings
+ add _SFIO_INLINE_PRIVATE to provide real function too
+ fix &lt;dirent.h&gt; installation test
+ oops object / shared library compat with _sfgetl2 _sfgetu2
+95-09-11 add getopt() compatibility
+ add fstat,lstat,mknod,stat fixes for _x versions in sys/stat.h
+ add getconf CONFORMANCE - posix for things that aren't ast default
+ sfio_t.h: #ifndef _SFIO_H #include "sfio.h" #endif
+ snarf vmalloc from kpv
+95-08-11 fix malloc bug in magic
+ update linux and bsd 386 magic entries
+ error_info.auxilliary returns new level, |=ERROR_OUTPUT if msg done
+ drop fnmatch from strmatch for sparc (solaris) until it collates
+95-07-17 fix port/astconf universe initialization
+ fix misc/optget opt_info.nopt initialization
+ drop tmset() TZ=... because it only worked when TZ=... was ignored
+95-05-09 mongo &lt;ast.h&gt; namespace cleanup
+ drop &gt; 2 year old obsolete interfaces
+ sfvprintf.c fix for (char:8 short:16 int:32 long:64) architectures
+ TMP_MAX back into conf.tab
+ pathbin() and pathshell() now use astconf()
+ fix pathtemp() to not cache getenv("TMPDIR")
+ fix ftwalk() metaphysical to handle non-dirs too
+ initialize *_info = { 0 }; for ancient ld semantics (NeXT)
+ fix magic() to do vmfree()
+ astconf(X_OK) must prefix lines with "getconf"
+ use &lt;wchar.h&gt; and wctype in strmatch() if available
+ _lib_utime_now checks utime(path,0)
+ _lib_poll_notimer checks poll(x,0,timeout)
+ add another _lib_utime_now check to port/touch.c
+ fix dd_buf cast in dir/opendir.c
+ split getconf.h into conftab.h and conftab.c for :READONLY:
+ use mbtowc() only if MB_LEN_MAX&gt;1
+ sfio char* -&gt; Void_t* cleanup
+ handle old syntax in misc/magic.c
+ sigdata.c holds readonly signal strings
+ pathcheck() does AT&amp;T checks for tools matching PARANOID - yuk
+ unused var cleanup
+ deprecate hash_info in favor of hashlast()
+ fix bad conf.sh ksh integer interactions
+ dll cleanup
+ magic.c falls back to malloc for now
+ add environ to &lt;ast.h&gt; -- C library global data syms are *RESERVED*
+ sfhdr.h memccpy(1,2,3,size_t) prototype
+95-04-01 version 4.0
+ convert to vmalloc
+ allow sigcritical() nesting mismatch to work around vfork() bug
+ add strexpr() primitive for streval() with user handle (like ftwalk)
+ add &lt;magic.h&gt; and magic.c file command magic interface
+ update magic mail message entry
+ fix keyprintf() invisible char count nesting bug
+ add sfstrnew(SF_READ|SF_WRITE) for alternate sfstropen() modes
+ sfstrnew(SF_READ) but reading requires sfseek(), sfreserve()
+ add conf.tab and conf.sh to nail C/POSIX limits/unistd macros
+ add getconf() string interface to *conf*
+ _DLL_INTERMEDIATE_DATA for systems that require indirect globals
+ _DLL for building shared libraries with _DLL_INTERMEDIATE_DATA
+ vecfile() restricted to S_ISREG()
+ add spawnveg() for job control
+ convert procopen() PROC_PGRP(id) to spawnveg()
+ fmterror() returns error text given errno (strerror() does same)
+ fmtsignal() returns signal text given errno (strsignal() does same)
+ {sig_name,sig_text,SIG_MAX} -&gt; sig_info.{name,text,sigmax}
+ liberror("",...) omits &#0091;%s library&#0093; prefix
+ update features/signal.c table
+ add vmdisc() and change vmnewof() to use vmresize()
+ fix conf.sh to allow refs to previously defined limits
+ fix undefined entries in getconf()
+ magic data in magic.tab
+ fix stropt() pointer cast
+ vmalloc() exception handler replaces nomalloc()
+ merge sigdata.c into fmtsignal.c -- sun link needs function w/ data!
+ sftmp() bug fix
+ drop local &lt;unistd.h&gt; even with _POSIX_SOURCE
+ fix vmstrdup() macro arg miscount
+ fix conf.sh to handle enum'd symbolic constants in unistd.h
+ drop malloc() et.al. prototypes from vmalloc.h
+ fix sfvprintf() %d argument reference
+ add OSF/1 AES symbol(s) to conf.tab
+ determine standards prefix from conf.tab
+ add _CS_SHELL to conf.tab
+ getpath() default is confstr(_CS_PATH)
+ getshell() default is confstr(_CS_SHELL)
+ unify keyprintf user function args (should have learned by now!)
+ add quad type to magic
+ add astfeature() to unify universe style dynamic features
+ add ftwflags() to determine FTW_* flags from astfeature()
+95-03-11 fix stropt() to not modify its *const* arg
+ handle "'&nbsp;quotes and chresc() in stropt() values
+ , treated like :space: between stropt() options
+ fix procopen() fd dup to ignore self-dups
+ add library id&#0091;&#0093; to misc/state.c
+ add ftwalk(FTW_METAPHYSICAL) for posix -H
+ sfvprintf() now handles balanced () in %()
+ add tmfmt() with buffer size check to replace tmform()
+ add fmttime() calling tmfmt() to fit fmt*() mold
+ add &lt;keyprintf.h&gt; and keyprintf() to support %(...)? in commands
+ add Hash_table_t for size==0 in stropt()
+ add EXTTYPE extended header to tar.h
+95-02-14 sfmove() buffer size overflow fix
+ add _SFSTDIO_H to sfio.h
+ rename setenv() to setenviron() -- posix finally decided
+ rename &lt;option.h&gt; opt_* to opt_info.*
+ update features/unistd.c for _SC_* and _PC_* posix additions
+95-01-19 (char*)uchar cast in fmtesc()
+ fix hash bucket memory leak in hashlook() &#0091;via John Mocenigo&#0093;
+ update strings/strtape()
+ fix optget()/optjoin() to handle leading +
+ add ALIGN_ prefix to &lt;align.h&gt; identifiers
+95-01-11 change tm/*.c tmset(0) to tmset(tm_info.zone) to keep user setting
+ fix tmform() %Z null pointer dereference
+95-01-01 add this RELEASE file
+ fix strperm() to properly handle "644 file"
+ fix tokline() to return last '&nbsp;' terminated line in string
+ fix tokscan() to properly handle \\n splice
+ add fmtesc() to complement stresc()
+ add LS_NUMBER to fmtls()
+ drop spurious optusage() ' '
+
+</PRE>
+<P>
+<P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="libcmd changes">libcmd changes</A></H3></FONT></FONT></CENTER>
+<PRE>
+
+12-02-14 rm.c: --force ignores no file operands specified
+12-01-10 b_* (int, char**, void*) =&gt; (int, char**, Shbltin_t*)
+11-08-27 pids.c: add getsid() iffe test
+10-08-16 chmod.c: add -l alias for { -h --symlink }
+11-08-16 chgrp.c: change lchmod() ref to lchown()
+11-05-03 cp.c: do not delete src if mv to dest fails -- doh
+11-03-28 chmod.c,chgrp.c: fix --symlink logic
+11-03-26 rm.c: don't eaccess() check symlinks!
+11-01-27 date: add { -R, --rfc-2822, -T, --rfc-3339=type }
+11-01-03 chgrp.c: --symlink =&gt; --physical
+10-12-10 rm.c: fix not-writable logic
+10-12-01 tee.c: add iterrupt logic for slow open(1) -- needs to be generalized
+10-11-30 chgrp.c: add -N,--numeric to bypass name lookup
+10-10-20 cp: add --timestamps (preserv timestamps and permissions)
+10-10-20 ln: fix 'cannot replace existing file' logic
+10-10-10 cp,mv: add --remove-destination
+10-08-11 cp.c,expr.c: use conformance("standard",0) test
+10-08-11 cut.c: use mbnsize() instead of mblen() (for ast C.UTF-8)
+10-07-28 chgrp.c,chmod.c,cksum.c: fts_path for diagnostics, not fts_accpath!
+10-06-14 rm.c: fix -rfu logic
+10-06-12 paste.c: repeat after me: do not modify argv&#0091;i&#0093;
+10-06-01 sync with ast api 20100601
+10-05-09 tail.c: fix -0f bug that inially listed the entire file
+10-05-06 basename.c: add { -a,--all -s,--suffux=suffix } from BSD
+10-04-12 cat.c: fix -v bug that dumped core and make consistent with cmp --print-chars
+10-04-11 cmp.c: add --print-bytes, --count=n, --differences=n
+10-04-08 vmstate.c: add { method flags } vars for Vmstat_t.mode
+10-04-08 mkdir.c: fix check for { S_ISUID S_ISGID S_ISVTX } after successful mkdir(2)
+10-04-01 stty.c: add --fd=fd option
+10-03-23 tail.c: fix -f large initial offset bug that didn't copy all data
+10-03-07 tail.c: sfsync(sfstdout) after all -f done, fix -f partial line
+10-03-05 mktemp.c: add --regress=seed for testing
+10-03-05 vmstate.c: add
+10-01-26 tail.c: -f sleep(1) only if no progress from last round of checks
+10-01-20 fts_fix.&#0091;ch&#0093;: use &lt;fts_fix.h&gt; instead of &lt;fts.h&gt; (see fts_fix.c)
+10-01-20 cp.c: free(state) if called from old shell
+09-12-10 join.c: &lt;wctype.h&gt; for iswspace()!
+09-12-04 cmd.h: fix CMD_DYNAMIC logic
+09-12-04 cut.c: handle -d mb
+09-12-03 mkdir.c: add --verbose
+09-11-30 cat.c,date.c,cksum.c: drop setlocale() call already done by optget()
+09-11-30 join.c: handle -t mb
+09-11-28 wclib.c: { -w -L } mb independent of -m
+09-11-28 paste.c: handle -d mb
+09-11-28 uniq.c: handle -s mb
+09-11-28 cksum.c: FTS_SEEDOTDIR by default
+09-09-09 fds.c: add --unit=fd
+09-08-25 tail.c: initialize Tail_t.fifo=0 !!
+09-08-15 tail.c: fix fifo logic
+09-08-11 wc.c: add setlocale(LC_CTYPE,"C") cleanup, add utf8 optimzations
+09-08-10 uniq.c: replace -c 1..9999 sfsprintf() with inline conversion
+09-08-01 join.c: fix empty field null pointer deref
+09-07-23 pathchk.c: add -P,--path and -a,--all
+09-07-02 chgrp.c,chmod.c,cksum.c: fts_flags() default only if not --recursive
+09-06-19 cmd.h,cmdinit.c: add ERROR_CALLBACK for ERROR_NOTIFY main() callback
+09-06-19 mktemp.c: --unsafe now checks and prints path but does create
+09-06-19 tee.c: add ERROR_CALLBACK for tee_cleanup() sfio discipline pop
+09-06-18 rm.c: handle interrupts during interactive query
+09-06-18 cp.c: handle interrupts during interactive query
+09-05-25 tail.c: fix old style option logic to handle --invalid-long-option
+09-05-24 tail.c: -r == +1r
+09-05-01 mktemp.c: handle foo/prefix, add -p dir and -u
+09-03-31 cat.c: handle --no* options
+09-03-15 tail.c: fix --timeout termination logic
+09-03-03 tee.c: clean up sfio disciplines on error
+09-03-03 cat.c: fix -v|-e|-n|-B interaction bugs
+09-02-14 tail.c: fix VSC failures
+09-02-14 join.c: fix VSC failure
+09-02-02 uniq.c: document -number == -fnumber, +number == -snumber
+09-02-02 tail.c: fix usage&#0091;&#0093; for negative offsets, add sun -b
+09-02-02 mktemp.c: add
+09-02-02 features/utsname: UWIN _UNAME_os_DEFAULT =&gt; UWIN
+09-01-31 dirname.c: add experimental { -f -r -x } for pathpath(3)
+09-01-05 cmp.c: fix EOF diagnostic to conform to posix
+09-01-03 mkfifo.c: fix --mode=mode logic
+08-12-07 date.c: add %&#0091;_&#0093;&#0091;EO&#0093;K for &#0091;space pad&#0093; &#0091;full|long&#0093; iso docs
+08-11-10 stty.c: check for -t grouping so -tostop != -t -ostop
+08-10-15 rm.c: handle 'rm -f x x' =&gt; exit 0
+08-09-08 stty.c: #ifdef guard TAB&#0091;012&#0093; -- freebsd: damn the posix, full speed ahead
+08-06-17 shcmd.h: move to libast
+08-04-24 uniq.c: add optget() 'n' option for -1 =&gt; -f1
+08-04-24 getconf.c: clarify diffs between "name - value" and "name = value"
+08-04-01 cut.c: add write error check
+08-04-01 paste.c: fix --noserial stream vector access bug
+08-04-01 pids.c: add ls/ps style --format=format
+08-04-01 stty.c: fix off2 unitialized reference
+08-03-28 chgrp.c: add --before=file
+08-03-14 pids.c: add
+08-03-11 chgrp.c: fix -m to use uid:gid as lookup key
+08-02-11 Makefile: add -lmd possibly required by sumlib.o -- hack alert
+08-01-30 expr.c: fix &lt;=0 type that broke substr * 1 * -- wow
+07-12-13 cp.c: fix builtin state reinitialization
+07-11-29 rev.c: honor multibyte locales
+07-11-27 cp.c: open non-existent destination with O_EXCL
+07-11-27 stty.c: add -t,--terminal-group to list tty pgrp
+07-11-27 cksum.c: --silent -s =&gt; -S, -s == -x sys5 for gnu compatibility
+07-11-11 tee.c: drop ancient bsd compatibility "-" operand =&gt; SIGINT
+07-10-29 cksum.c: add SUM_LEGACY for -r
+07-10-12 cp.c: plug usage string memory leak by using per-builtin state
+07-09-21 cksum.c: add sumprint() default scale arg, --scale, --bsd for solaris
+07-09-10 chmod.c: add --show,-n
+07-07-27 wclib.c: bias &lt;wchar.h&gt; checks for modern unix
+07-07-17 cat.c: fix --squeeze-blank to reduce multiple blank lines to *one*
+07-05-20 cmd.h: handle msvc's balk at if(0)0=0;
+07-05-20 cksum.c: #include &lt;modex.h&gt;
+07-05-11 cmd.h: add _CMD_CONTEXT_OK() to verify &gt;= 20070511 context
+07-05-09 fds.c: handle ipv6 sockets
+07-05-09 cmd.h: &lt;shbltin.h&gt; : cmdquit() =&gt; sh_checksig(context)
+07-04-25 mkdir.c: force (S_ISVTX|S_ISUID|S_ISGID) after mkdir(2)
+07-04-24 procrun.c: add -last intercept =&gt; sh_run() and whence -q
+07-04-19 uname.c: name operands first checked for CS_NAME, then NAME
+07-03-28 date.c: add --unelapsed=scale, -U: fmtelapsed() =&gt; strelapsed()
+07-03-25 wclib.h: iswspace() requires &lt;wctype.h&gt;!
+07-03-11 tty.c: add sysV --line-number, -l
+07-02-26 Makefile: sumlib.o: direct extract from +lsum (vcodex someday)
+07-02-24 Makefile: tweak cmdext.h action for --mam bootstrap
+07-02-09 Makefile: { cmdext.h cmdlist.h } depend on *.c list!
+07-02-09 Makefile: +lsum to bring in static -lsum (no dynamic right now)
+07-02-07 cksum.c: move from src/cmd/std with ftwalk =&gt; fts
+07-02-07 getconf.c: handle /bin == /usr/bin in defer logic
+07-01-26 chmod.c: don't FTS_FOLLOW if !FTS_PHYSICAL
+07-01-23 cut.c: Cut_t variable dimension list&#0091;&#0093; must be last member
+07-01-22 uname.c: fix -h typo that clobbered astconf() state -- ouch
+07-01-02 fmt.c: fix buffer splice off by one bug -- what else
+06-11-23 cmd.h: because of proto cmdinit cannot be a function like macro
+06-11-21 cp.c: fix 06-10-31 const dot&#0091;&#0093; readonly assignment
+06-11-15 cp.c: fix 06-10-31 ln -s enoent bug
+06-11-11 getconf.c: let astconf() handle "undefined" vs. ""
+06-11-11 getconf.c: fix deferred getconf path search
+06-11-11 fmt.c: handle two char { \t } in --usage ouput
+06-10-31 global edit to eliminate most non-const static data0
+06-10-31 use &lt;cmd.h&gt; for all b_*() implementations; drop &lt;cmdlib.h&gt;
+06-10-31 cmd.h: add CMD_ prefix to { BUILTIN DYNAMIC STANDALONE }
+06-10-31 join.c: tone down /tmp usage vi SFSK_DISCARD
+06-10-31 cp.c,rm.c: update to &lt;fts.h&gt; to accomodate non-static data
+06-10-29 date.c: "...%H%..." =&gt; "...%H" "%..." to avoid SCCS conflict
+06-10-26 fds.c: handle sctp
+06-10-18 tail.c: fix invalid suffix infinite loop
+06-10-11 chgrp.c,cp.c: add sfstruse() error checks
+06-10-10 tee.c: add --linebuffer, -l
+06-10-06 getconf.c: preserve native getconf(1) known variable behavior
+06-10-04 sync.c: add (thanks to Roland Mainz)
+06-10-04 getconf.c: add -v specification =&gt; run native getconf(1)
+06-09-28 stty.c: static setmode() =&gt; set() for darwin.i386
+06-09-27 head.c: handle -1c =&gt; -c1
+06-09-19 pathchk.c: pathconf() =&gt; astconf()
+06-09-11 tail.c: handle compatibility corner cases
+06-09-08 date.c: add output write error diagnostic
+06-09-04 tail.c: fix initial position for -n0, no args =&gt; no -f
+06-08-28 uniq.c: add -D,--all-repeated
+06-08-25 wc.c,wclib.c: add -L,--longest-line,WC_LONGEST
+06-08-24 wc.c,wclib.c: implement -m and WC_MBYTE
+06-08-24 rmdir.c: -sp applies to every message, add gnu -e
+06-08-23 rmdir.c: add solaris --suppress, -s
+06-08-23 mkdir.c: don't add 0300 to -p final dir mode
+06-07-17 cut.c: handle last line with no newline
+06-07-17 cut.c: --output-delimiter == --line-delimiter
+06-06-25 chmod.c: mask -c output with S_IPERM
+06-05-09 uname.c: add -o; change -a to match linux
+06-05-03 date.c: add --last -L to list last of multiple time args
+06-02-14 tail.c: fix -f bug that lost fast stream data
+06-02-11 getconf.c: exit 1 if name invalid -- duh
+06-01-28 cp.c,rm.c: fix astquery() 'q' to return and not exit()
+05-08-11 fmt.c: fix -o to handle raw --usage strings
+05-05-17 cat.c,head.c: disable EPIPE error messages
+05-04-14 chgrp.c: -f means all non-syntax error messages
+05-04-11 fds.c: add from old internal open(1)
+05-04-09 cmdext.h,cmdlist.h: generate from source -- about time
+05-03-24 features/symlink: verify { lchmod lchown } implementations
+05-03-07 date.c: add --listzones to list the time zone table
+05-02-14 chmod.c: add --reference=file
+05-01-11 cat.c: restore output stream to binary mode on exit
+04-12-15 cp.c: add --preserve high resolution time support
+04-12-08 date.c: add high resolution time support
+04-12-01 cmp.c: fix %6I*ld =&gt; %6I*d -- doh
+ fmt.c: handle "n operands n"
+ head.c: handle -cN -nN, N &gt; 4Gb
+04-11-22 cmp.c: handle &gt;2G chars/lines
+04-11-18 fold.c: add --prepend=text, --append=text
+04-10-31 tail.c: use SF_LOCKR macro
+04-10-28 tail.c: use strtol() for old stype &#0091;+-&#0093;number&#0091;suffix&#0093; -- doh
+04-10-22 cp.c: check rename() errno==ENOENT to retain destination
+04-10-11 fmt.c: fix -o,--optget sublist bugs
+ tail.c: use strton() for number conversion
+04-10-08 pathchk.c: add empty path and -p - first component char
+04-10-01 fmt.c: add -o,--optget concatenated usage string format
+ stty.c: context is ERROR_INTERCATIVE
+ rm.c: restore 3d before exit
+04-09-24 pathchk.c: fix docs
+04-09-14 date.c: add %| and %&amp; --parse docs
+04-08-27 cp.c: add FTW_DC check -- duh
+04-08-01 fmt.c: handle last char != '
+04-07-22 date.c,uname.c: access() =&gt; eaccess()
+04-07-01 fmt.c: handle large input lines -- ouch
+04-06-11 id.c: fix -r to output something!
+04-05-27 expr.c: fix `:' op subexpression output
+04-04-15 chmod.c: follow symlink for relative mode
+04-04-12 Makefile: add STDCHMOD (for osf.alpha)
+04-03-19 tail.c: handle -f sfreserve() large chunk failure
+04-02-29 cp.c: decouple -f and -i for standard CONFORMANCE
+ cp.c: mv now attempts rename() before remove()+rename()
+ date.c: -f format or +format disables system clock set
+04-02-14 cp.c: add -F --fsync to call fsync(2) for each copied file
+04-01-05 head.c: -s now uses opt_info.number for &gt;2Gb skip
+03-09-18 tail.c: add --log
+03-09-11 rm.c: add --unconditional
+03-08-11 fold.c: add --delimiter=c to break at c
+03-07-28 features/time: change settimeofday() test to 2nd arg of (void*)0
+ expr.c: add {match,substr,index,length,quote}
+03-07-15 fmt.c: fix trailing space bug
+03-06-20 uname.c: fix -p constant string overwrite
+03-06-04 stty.c: add undef to control assignment docs
+03-05-31 uname.c: add -f and sysinfo()/confstr() compatibility via astconf()
+03-05-27 rm.c: fix inappropriate "/.." append path overflow
+ cut.c: snarf from dgk
+03-05-18 rm.c: check st_nlink to verify progress w.r.t. ftwalk/fts
+03-05-15 join.c: fix stealth -v2 bug (thanks ahs)
+03-05-04 wc.c: drop trailing space for `wc -l &lt; file'
+03-03-21 date.c: add %Q/recent/distant/ docs
+03-02-19 date.c: fix %+|!flag docs
+02-11-14 update for cmdinit() 4th arg and ERROR_NOTIFY for interrupt cleanup
+02-10-02 date.c: tmform() =&gt; tmfmt()
+02-09-30 date.c,uname.c: change execv() calls to procrun(): exec|exit =&gt; bad
+02-09-06 wclib.c: fix 1 char-at-a-time miscount bug
+02-08-19 chgrp.c: convert to use &lt;cdt.h&gt;
+02-07-23 join.c: fix comm snarf typo
+02-04-05 date.c: add %u
+02-01-24 stty.c: ifdef a few more macros for uts (yes, its still running)
+01-12-14 date.c: clarify %z doc
+01-10-31 mkdir.c: mkdir() on existing dir could fail with errno!=EEXIST
+ uname.c: add execve() loop check for unknown options
+01-10-29 tail.c: SF_SHARE on only if not reading through EOF
+01-10-11 getconf.c: fix usage typos
+01-09-11 cp.c,cmd.h: handle . in argv&#0091;0&#0093;
+ cp.c: add O_BINARY to all open() calls
+01-09-06 tail: input streams must be SF_SHARE -- duh
+01-07-16 stty: fix cntl() macro for CC_NATIVE!=CC_ASCII
+01-05-31 date: fix /bin/date fallback logic
+ stty: fix a few mismatched flags, -a and -g option logic
+ stty: tone down sane to modify current settings rather than from zero
+01-05-01 uname: -i =&gt; -h, add sol.sun4 -i, add sgi -R, punt to /usr/bin/uname
+01-04-17 date,rm: add
+01-03-07 cp: fix readonly string mod on "."
+01-01-23 cp: `cp foo' =&gt; `cp foo .' only for CONFORMANCE!=standard
+00-12-01 cut: multibyte support
+00-10-31 mkdir: handle races by checking EEXIST
+00-09-20 cp: copy argv to stack before modifying in place
+00-05-18 add setlocale(LC_ALL,"")
+00-04-30 join: drop weird opt_info.argv reference
+00-03-17 expr: add == operator -- duh
+ cp,ln,mv: delay pathcanon() on destination to verify `cp a b/.'
+ getconf: use astgetconf for proper message control
+ ERROR_translate: dictionary update
+00-03-08 tail: handle multiple -f files
+00-03-07 fmt: add
+00-03-07 dirname: handle PATH_LEADING_SLASHES as documented
+ tail: accept + options
+00-02-14 chmod: --ignore-umask to ignore umask(2) in symbolic expressions
+ chmod,chgrp,cp: use FTS_NOSEEDOTDIR for correct path construction
+ cat: fix -n (was ignored, wow)
+00-01-27 getconf: add "-a" and "-v spec" for sol7.* compatibility
+99-09-09 join: fix -j1 vs. -j 1, add --ignorecase
+99-06-22 paste: defualt delim in writable string
+99-06-16 cat: fix --dos-ouput typo
+99-06-11 cp: tighten chown() diagnostics
+99-06-08 expr: nothing for NULL string bug fix
+99-05-21 paste: fix missing newline columnize bug
+99-05-20 mv: do not check for `mv foo foo' since rename() handles it
+99-05-01 cmp,comm,cp/mv/ln,expr,fold,getconf,head: long options
+ join,logname,paste,pathchk,tail,tee: long options
+99-04-10 uname: long options, stdize -a
+ chmod,head,tail,rev: long options
+ cut: long options, pass regression test 02
+99-04-07 cat: long options, fix O_TEXT modes
+99-01-11 tail: fix +n
+ join: another ggs/psm bug
+ join: all 1 and/or 2 to be unseekable
+99-01-01 cp: fix -p
+ chmod: drop -l option because of clash with l (lock) mode
+98-12-25 cat: add -T to sfopen(,,"rt")
+98-11-11 chgrp,chmod: cannot open file stream =&gt; not found
+ join: fix another ggs/psm bug; thanks guys
+98-10-20 cp: fix cp -rp to update dir times too
+98-09-22 join: fix ggs null field bug
+98-08-11 join: fix last regression test bug
+98-05-29 join: add jp-&gt;common to handle boundary conditions
+98-03-11 cat,cp,rev,tee: fix sfmove() error checks
+98-03-01 join: fix bug that emitted records more than once after eof
+ cp: fix sfmove() error check
+98-02-14 cp: -R physical, -&#0091;HLP&#0093;, -r getconf(PATH_RESOLVE)
+98-01-11 cp: check sfclose() return value
+98-01-07 chown,chgrp,chmod: use fts for -R
+ mkdir: fix -p default mode
+97-12-07 mkdir: fix umask() reset
+97-11-11 chown,chgrp: proper interpretation of -h,-l for lchown()
+ chown,chgrp: only chown() if uid or gid change
+97-10-31 mkdir: do umask right
+97-08-11 cmdinit: clear opt_info.index to allow multiple calls
+ cp,ln,mv: add
+97-07-17 join: fix a few more -a bugs
+97-05-31 expr: optget() only if CONFORMANCE==standard
+97-04-01 join: fix a few bugs that make it work!
+96-12-25 head: sfset(sfstdin,SF_SHARE,1)
+ Makefile: add -last to cmd lib list
+ drop function __IMPORT__
+96-08-11 tail: check for truncated file and rewind for -f
+96-04-08 update &lt;cmd.h&gt;
+96-02-29 uname: -a like std, -l for everything
+ id: add -a (default)
+96-02-14 wc: speed up inner loop newline breakout
+96-01-30 unused var cleanup
+96-01-01 AT&amp;T Research now
+ pathchk: handle getcwd(0,0) error
+ expr: switch to &lt;regex.h&gt;
+95-11-11 add expr.c
+ fix cut exit code and -s optimization
+95-10-11 add extern b_* to cmd.h
+ add void* context 3rd arg to b_main()
+95-05-09 add getconf
+ cat -u avoids mmap
+ add chown|chgrp -m uid|gid map file
+ add chown|chgrp -P for systems with lchown(2)
+ chown|chgrp -P =&gt; lstat() too!
+ chmod|chown|chgrp -HLP
+95-04-01 version 1.2
+ add rmdir
+95-02-14 fix mkdir -p symlink bug
+ fix mkdir '/' skip bug that went one too far
+
+</PRE>
+<P>
+<P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="libcoshell changes">libcoshell changes</A></H3></FONT></FONT></CENTER>
+<PRE>
+
+12-02-22 coinit.c: handle non-identifier export var names
+11-12-13 cowait.c: handle sfpoll() error return on interrupt
+11-11-21 cowait.c: poll before blocking read to weed out killed jobs (no 'x' message)
+11-08-30 codata.c,coopen.c: drop macro "..." catenation for old cc
+10-08-11 coinit.c: force _BLD_DLL for environ intercept
+10-06-01 sync with ast api 20100601
+10-05-19 cokill.c: do cowait(co,co,0) to drain pending messages
+10-05-15 coshell.h,coopen.c: add CO_ORPHAN for PROC_ORPHAN
+10-05-11 coopen.c: add PROC_ORPHAN for CO_SHELL
+10-05-10 coopen.c: no atexit() for CO_SHELL
+10-04-15 first ksh93u local job pool tests work (service daemon tbd)
+10-04-14 cowait.c: add 3rd cowait() arg timeout; 0 Coshell_t* operates on all open coshells
+10-04-10 coshell.h: add CO_SHELL for shell using coshell!
+09-12-09 coexport.c: add runtime CO_ENV_EXPORT hook that avoids changing environ
+08-10-28 coopen.c: close write side of parent msgfd -- doh
+08-04-28 coexec.c: check for fd 1,2 equivalence before CO_SERIALIZE 2&gt;&amp;1
+07-10-29 coshell.h,coexec.c: fix procrun()/system() intercept logic
+07-08-15 add CO_SEPARATE,CO_MODE_SEPARATE for separate shell+wait per action
+07-04-09 Makefile: $(CC.PIC) to allow archive to be pulled into other dlls
+06-08-22 coshell.h: procrun =&gt; coprocrun, system =&gt; cosystem
+06-08-09 coshell.h: export CO_ENV_MSGFD for COSHELL=coshell
+06-08-02 coexec.c: Cojob_t.flags&amp;CO_SERVICE for service requests
+06-08-02 cokill.c: cokill() signal==0 =&gt; kill CO_SERVICE jobs
+06-07-27 coexec.c: drop server cowait() that bypassed caller
+06-06-21 coexec.c: add non-block cowait() to drain responses
+06-06-11 fix service intercept cleanup
+06-05-24 add service=name:init lightweight service intercepts
+05-04-19 cowait.c: beef up invalid message tests and diagnostics
+05-04-11 drop fixed CO_MSGFD for $_coshell_msgfd
+05-04-07 coexec.c: fix !_lib_fork&amp;&amp;_map_spawnve close-on-exec redirection
+04-09-22 cowait.c: remove CO_SERIALIZE temporaries after listing -- duh
+04-09-01 co*: add CO_SERIALIZE
+04-07-22 system.c: access() =&gt; eaccess()
+04-02-11 coinit.c: fix CO_CROSS PATH initialization
+02-10-30 coclose.c: fix reference-after-free bug in coclose()
+02-01-31 codata.c,coopen.c: fix CO_MSGFD parameterization
+02-01-24 coopen.c: fix small memory leak
+01-10-26 coopen.c: hung sfclose(fp) -&gt; close(sffileno(fp)) -- wow
+01-09-11 coinit.c: fix coident&#0091;&#0093; for ancient bsh that die on `test == 1'
+ coinit.c: and fix coident&#0091;&#0093; to weed out buggy ksh88i trap on exit
+01-05-31 co*: add CO_CROSS, expose CO_DEVFD
+01-04-23 coquote: add state.type to avoid getenv() overwrite on some systems
+01-01-01 cokill: killjob =&gt; cokilljob, killshell =&gt; cokillshell
+00-12-18 coinit: CO_OSH ? "${!-$$}" : "${!:-$$}"
+00-10-25 codata: $ZSH_VERSION is not ksh
+00-02-14 procrun,system: system(3) returns wait() status (not shell status)
+99-11-19 co*: add CO_OSH for bsdi lack of times(1)
+ coexec: CO_IGNORE for all but real ksh
+98-06-22 coinit: quote cd path arg
+
+</PRE>
+<P>
+<P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="libsum changes">libsum changes</A></H3></FONT></FONT></CENTER>
+<PRE>
+
+12-02-29 sum-sha2.c: bitcount&#0091;&#0093; order reversed to allow a single noalias buffer copy
+09-09-28 sumlib.c: use simple (faster) method name match function
+08-06-05 sum-lmd.c: align context to largest int
+08-05-01 sumlib.c: add some -lmd verification checks
+08-02-11 sum-lmd.c,features/sum: add wrapper for solaris -lmd
+07-10-29 sum.h,sumlib.c: add SUM_LEGACY for legacy output format
+07-09-21 sum-sha1.c: reinstate Steve Reid's public domain implementation
+07-07-26 sumlib.c: drop GPL sum-sha1.c
+05-02-14 sumlib.c: split into sum-*.c
+05-02-14 sum-sha2.c: add SHA { 256 384 512 }
+04-02-29 Makefile: compile with $(CC.PIC) for codexlib/sum $(CC.DLL)
+03-12-16 add { crc prng } generic methods and maps&#0091;&#0093; to these methods
+03-12-16 sum.h,sumlib.c: add sumdata()
+03-09-29 sumlib.c: fix FNV to use ^ instead of +
+03-04-28 sumlib.c: drop md5 `zeroize' for performance
+ sumlib.c: add FIPS 180-1 SHA-1
+
+</PRE>
+<P>
+<P><HR><CENTER><FONT color=red><FONT face=courier><H3><A name="libdll changes">libdll changes</A></H3></FONT></FONT></CENTER>
+<PRE>
+
+11-10-11 dll_lib.c: add { dllnames() dll_lib() }
+10-10-20 dllscan.c: version arg "-" =&gt; 0
+10-10-19 dllplug.c: fix bug that wiped out dlopen() error message
+10-10-19 dllplug.c: un-localize lookup names (happens with cut and paste)
+10-10-19 dllscan.c: still no code for implicit libs missed by dlopen()
+10-08-02 dllplug.c: fix local path dllcheck() call
+10-05-28 dllplug.c: add dllplugin() with dllcheck() version check
+10-05-28 dllcheck.c: add dllcheck() to do plugin_version() checks
+10-05-28 dllerror.c: add dllerror(int retain) for dll*() and dl*() messages
+09-11-17 dllscan.c: handle name&#0091;-.&#0093;version in dlsopen()
+09-04-15 dllopen.c: add, use dllopen() internally to wrap dlopen()
+08-05-12 dllscan.c: LIBSUFFIX==.dylib =&gt; default plugin version match 0.0
+06-10-11 dllscan.c: check sfstruse() return values -- doh
+06-01-25 dllplug.c: add errorf() library message for dlopen() error
+05-02-14 dllscan.c: "" || "-" =&gt; NiL
+04-10-01 dllfind.c: drop ksh "builtin" workaround
+ dllscan.c: directory prefix in name limits search to dir and siblings
+04-07-22 dllscan.c: access() =&gt; eaccess()
+04-01-30 dllfind.c: dllplug(error_info.id) then dllplug(0)
+04-01-28 dllscan.c: update for new plugin scheme: lib/foo/bar.xxx
+ dllplug.c: add dllplug() for plugin dllfind()
+03-03-12 dllfind.c: dlopen() with RTLD_GLOBAL|RTLD_PARENT defaults
+03-02-11 dllscan.c: change LIBPATH to &lt;dir&gt;&#0091;:&lt;env&gt;&#0091;:&lt;pat&gt;&#0093;&#0093;&#0091;,...&#0093;
+03-01-08 dllscan.c: hack version logic again -- is consistency rocket science?
+03-01-07 dlfcn.c: fix darwin.ppc dlopen/dlsym/dlclose
+02-11-18 dllfind.c: add path,size args (with backwards compatibility checks)
+02-11-15 dllfind.c: check for ./path if '.' in path but no '/'
+02-08-30 dllfind.c: fix a bug that returned uninitialized value on not found
+02-08-28 dllscan.c: handle and display bin as a sibling dir
+02-07-31 dllscan.c: add dllsopen,dllsread,dllsclose
+ dllfind.c: use dllsopen,dllsread,dllsclose
+02-07-26 dllfind.c: add dllinfo()
+02-06-27 dllnext.c: define _GNU_SOURCE to enable RTLD_NEXT
+02-03-17 dllfind.c: fix dll prefix search (for cygwin)
+02-01-11 features/dll: include &lt;dlfcn.h&gt; only if _hdr_dlfcn&amp;&amp;_lib_dlopen
+01-10-31 dlfcn.c: change hp.pa dlopen() prototype (&lt;dlfcn.h&gt; but no -ldl!)
+01-09-25 dllfind: add LIBSUFFIX
+01-07-17 dllfind: do at least one dlopen() to prime dlerror()
+01-05-29 dlopen: fix dlopen(0,0) for HP
+01-04-20 dllfind: use getconf HOSTTYPE LIBPATH LIBSUFFIX
+01-02-14 features/dll: fix unbalanced ' quote and ancient hostinfo reference
+00-01-26 dlllook: add -- dlsym() with `_' weak prefix fallback
+99-04-01 features/dll: drop &lt;stdio.h&gt; -- iffe protos printf
+99-03-19 static=1 for all but win32.*
+98-06-01 dllfind: fix version search
+98-03-11 features/dll: probe for _DLL_RLD_SYM
+98-03-01 dllnext: fix to work!
+98-01-23 -ldl test moved to lib0ast
+98-01-11 update for astconf("LIBPATH")
+ add dllnext(flags) to uncover next layer
+ dllfind() and dllnext() in separate files (for 3d)
+97-10-11 move from libast so libast can link static
+</PRE>
+<P>
+<HR>
+<TABLE border=0 align=center width=96%>
+<TR>
+<TD align=left></TD>
+<TD align=center></TD>
+<TD align=right>March 13, 2012</TD>
+</TR>
+</TABLE>
+<P>
+
+</TD></TR></TBODY></TABLE>
+
+</BODY>
+</HTML>
diff --git a/lib/package/ast-ksh.pkg b/lib/package/ast-ksh.pkg
new file mode 100644
index 0000000..6f2fec8
--- /dev/null
+++ b/lib/package/ast-ksh.pkg
@@ -0,0 +1,89 @@
+ast-ksh :PACKAGE: ksh93 libast libcmd libcoshell libsum libdll
+
+:COVERS: ksh
+
+:LICENSE: *.open
+
+:CATEGORY: shells
+
+:INDEX: ksh and support libraries
+
+:DESCRIPTION:
+ The AT&T Software Technology ast-ksh package from AT&T Research
+ contains ksh and support libraries. This is the minimal set of
+ components needed to build ksh.
+
+:DETAILS: cyg
+ :README:
+ This package installs a standalone ksh93 executable ksh93.exe
+ and its man page ksh93.1. If /bin/ksh.exe does not exist then
+ these symlinks
+ /bin/ksh.exe => ksh93.exe
+ /usr/share/man/man1/ksh93.1 => ksh.1
+ are created. This allows alternative ksh impelementations,
+ e.g., /bin/pdksh.exe, to be selected by changing the ksh.exe
+ and ksh.1 symbolic links. In addition, ksh and ksh93 paths are
+ added to /etc/shells if not already present.
+ $()
+ Each builtin or special command accepts the --man and --html
+ options to list the man page on the standard error. The --???
+ option describes the self documenting options available to all
+ builtin and special commands.
+ $()
+ The stanadlone ksh is statically linked with the ast libcmd
+ library which provides several builtin versions of /bin
+ commands. "builtin | grep /opt/ast/bin" lists the libcmd
+ builtins on the standard output. /opt/ast/bin/FOO accesses
+ the FOO builtin, whether the /opt/ast/bin directory exists
+ or not. "builtin FOO" allows /opt/ast/bin/FOO to be accessed
+ as FOO, bypassing the $PATH setting. To enable all libcmd
+ builtins do one of the following:
+ (a) create the directory /opt/ast/bin and the file
+ /opt/ast/bin/.paths with this line
+ BUILTIN_LIB=.
+ and place /opt/ast/bin before /bin and /usr/bin in $PATH
+ (this will affect all ksh subshells and scripts)
+ (b) run "builtin $( builtin | sed -e '/\//!d' -e 's,.*/,,' )"
+ (this will affect only the current shell)
+ Some scripts may run significantly faster with libcmd builtins
+ enabled.
+ $()
+ The ast library checks the DOSPATHVARS environment variable
+ for variable path values to convert to and from native windows
+ format when cross-executing between cygwin and non-cygwin
+ programs. The value is a space separated list of environment
+ variables to convert. PATH is handled by cygwin so it is not
+ converted by the ast library.
+ $()
+ The astksh cygwin source package provides a bootstrap build
+ environment that is not suited for an edit/build/debug cycle.
+ If you want to explore and modify the source then you should
+ install the (non-cygwinized) ast-base package which includes
+ AT&T nmake. With ast-base you will also be able to regenerate
+ the astksh cygwin source and binary packages.
+ $()
+ For more information on ksh and other AT&T ast tools see
+ http://www.research.att.com/sw/download/
+ :EXPORT:
+ SHOPT_CMDLIB_DIR=1
+ bin/ksh93.exe :INSTALL: bin/ksh.exe
+ share/man/man1/ksh93.1 :INSTALL: man/man1/sh.1
+ :POSTINSTALL:
+ if [ ! -e /bin/ksh.exe ]
+ then ln -fs ksh93.exe /bin/ksh.exe
+ ln -fs ksh93.1 /usr/share/man/man1/ksh.1
+ else echo "/bin/ksh.exe already exists"
+ fi
+ if [ -f /etc/shells ]
+ then for i in /bin/ksh93 /bin/ksh /usr/bin/ksh93 /usr/bin/ksh
+ do if grep $i /etc/shells >/dev/null 2>&1
+ then echo "$i already in /etc/shells"
+ else echo $i >> /etc/shells
+ echo "$i added to /etc/shells"
+ fi
+ done
+ else echo "no /etc/shells file"
+ fi
+ exit 0
+ :TEST: bin/ksh
+ KSH=$<; cd src/cmd/ksh93/tests; CYGWIN="$$CYGWIN ntsec binmode" SHELL=$$KSH $$KSH shtests
diff --git a/lib/package/ast-ksh.req b/lib/package/ast-ksh.req
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/package/ast-ksh.req
diff --git a/lib/package/ast-ksh.ver b/lib/package/ast-ksh.ver
new file mode 100644
index 0000000..eb5fa10
--- /dev/null
+++ b/lib/package/ast-ksh.ver
@@ -0,0 +1 @@
+ast-ksh 2012-02-29 2012-02-29 1
diff --git a/lib/package/ast.def b/lib/package/ast.def
new file mode 100644
index 0000000..57a7796
--- /dev/null
+++ b/lib/package/ast.def
@@ -0,0 +1,47 @@
+#
+# ast default license info
+#
+
+message_set=3
+
+contributor+=(
+ [gsf]="Glenn Fowler <gsf@research.att.com>"
+ [dgk]="David Korn <dgk@research.att.com>"
+ [kpv]="Phong Vo <kpv@research.att.com>"
+
+ [aedgar]="Adam Edgar <aedgar@research.att.com>"
+ [alb]="Adam Buchsbaum <alb@adambuchsbaum.com>"
+ [ashaikh]="Aman Shaikh <ashaikh@research.att.com>"
+ [bala]="Bala Krishnamurthy <bala@research.att.com>"
+ [chen]="Robin Chen <chen@research.att.com>"
+ [dfwc]="Don Caldwell <dfwc@research.att.com>"
+ [ek]="Lefty Koutsofios <ek@research.att.com>"
+ [gruber]="Bob Gruber <bob.gruber@gmail.com>"
+ [jiawang]="Jia Wang <jiawang@research.att.com>"
+ [jlk]="Jeff Korn <@google.com>"
+ [kfisher]="Kathleen Fisher <kfisher@research.att.com>"
+ [kwc]="Ken Church <@microsoft.com>"
+
+ [bwk]="Brian Kernigham <bwk@research.bell-labs.com>"
+ [dmr]="Dennis Ritchie <dmr@research.bell-labs.com>"
+ [doug]="Doug McIlroy <doug@research.bell-labs.com>"
+ [ekrell]="Eduardo Krell <ekrell@adexus.cl>"
+ [jjs]="John Snyder <jjs@adexus.cl>"
+ [rao]="Herman Rao <rao@fareastone.att.com.tw>"
+
+ [ast-users]="AST users mailgroup <ast-users@research.att.com>"
+ [ast-developers]="AST developers mailgroup <ast-developers@research.att.com>"
+)
+
+license+=(
+ organization="Information and Software Systems Research"
+ domain=research.att.com
+ parent="AT&T"
+ corporation="Intellectual Property"
+ company="Research"
+ location="Florham Park NJ"
+
+ package=ast
+ since=1986
+ author=gsf+dgk+kpv
+)
diff --git a/lib/package/ast.lic b/lib/package/ast.lic
new file mode 100644
index 0000000..225faa6
--- /dev/null
+++ b/lib/package/ast.lic
@@ -0,0 +1,5 @@
+. ast.def
+. epl.def
+license+=(
+ start=2011
+)
diff --git a/lib/package/epl.def b/lib/package/epl.def
new file mode 100644
index 0000000..60eea6b
--- /dev/null
+++ b/lib/package/epl.def
@@ -0,0 +1,8 @@
+license+=(
+ type=epl
+ id=eclipse
+ name="Eclipse Public License"
+ version=1.0
+ url=http://www.eclipse.org/org/documents/${license.type}-v${license.version//./}.html
+ urlmd5=b35adb5213ca9657e911e9befb180842
+)
diff --git a/lib/package/ksh.pkg b/lib/package/ksh.pkg
new file mode 100644
index 0000000..4783527
--- /dev/null
+++ b/lib/package/ksh.pkg
@@ -0,0 +1,14 @@
+ksh :PACKAGE:
+
+:LICENSE: *.open
+
+:CATEGORY: shells
+
+:INDEX: standalone AT&T ksh executable
+
+:DESCRIPTION:
+ The AT&T Software Technology ksh package from AT&T Research
+ contains the AT&T ksh executable implemented by David Korn.
+ The download file is a gzipped ksh executable. If you want
+ to build ksh from the source then download one of the ast-ksh,
+ ast-base or ast-open packages.
diff --git a/lib/package/ksh.req b/lib/package/ksh.req
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/package/ksh.req
diff --git a/lib/package/ksh.ver b/lib/package/ksh.ver
new file mode 100644
index 0000000..5efe0a9
--- /dev/null
+++ b/lib/package/ksh.ver
@@ -0,0 +1 @@
+ksh 2012-02-29 2012-02-29 1
diff --git a/lib/package/package.mk b/lib/package/package.mk
new file mode 100644
index 0000000..921fa2d
--- /dev/null
+++ b/lib/package/package.mk
@@ -0,0 +1,1537 @@
+/*
+ * source and binary package support
+ *
+ * @(#)package.mk (AT&T Research) 2012-02-14
+ *
+ * usage:
+ *
+ * cd $INSTALLROOT/lib/package
+ * nmake -f name [closure] [cyg|exp|lcl|pkg|rpm|tgz] [base|delta] type
+ *
+ * where:
+ *
+ * name package description file or component
+ *
+ * type source build source archive, generates
+ * $(PACKAGEDIR)/name.version.release.suffix
+ * binary build binary archive, generates
+ * $(PACKAGEDIR)/name.version.hosttype.release.suffix
+ * runtime build binary archive, generates
+ * $(PACKAGEDIR)/name-run.version.hosttype.release.suffix
+ *
+ * NOTE: $(PACKAGEDIR) is in the lowest view and is shared among all views
+ *
+ * generated archive member files are $(PACKAGEROOT) relative
+ *
+ * main assertions:
+ *
+ * NAME [ name=value ] :PACKAGE: component ...
+ * :OMIT: component ...
+ * :LICENSE: license-class-pattern
+ * :CATEGORY: category-id ...
+ * :COVERS: package ...
+ * :REQURES: package ...
+ * :INDEX: index description line
+ * :DESCRIPTION:
+ * [ verbose description ]
+ * :DETAILS: style
+ * :README:
+ * readme lines
+ * :EXPORT:
+ * name=value
+ * target :INSTALL: [ source ]
+ *
+ * option variables, shown with default values
+ *
+ * format=tgz
+ * archive format
+ *
+ * version=YYYY-MM-DD
+ * package base version (overrides current date)
+ *
+ * release=YYYY-MM-DD
+ * package delta release (overrides current date)
+ *
+ * license=type.class
+ * :LICENSE: type.class pattern override
+ *
+ * notice=1
+ * include the conspicuous empty notice file
+ *
+ * copyright=0
+ * do not prepend source file copyright notice
+ *
+ * strip=0
+ * don't strip non-lcl binary package members
+ *
+ * variants=pattern
+ * include variants matching pattern in binary packages
+ *
+ * incremental=[source:1 binary:0]
+ * if a base archive is generated then also generate an
+ * incremental delta archive from the previous base
+ *
+ * NOTE: the Makerules.mk :PACKAGE: operator defers to :package: when
+ * a target is specified
+ */
+
+/* these are ast centric -- we'll parameterize another day */
+
+org = ast
+url = http://www.research.att.com/sw/download
+
+/* generic defaults */
+
+base =
+category = utils
+checksum = md5
+closure =
+copyright = 1
+delta =
+format = tgz
+incremental =
+index =
+init = INIT
+license =
+licenses = $(org)
+mamfile = 1
+opt =
+name =
+notice =
+release =
+strip = 0
+style = tgz
+suffix = tgz
+type =
+variants = !(cc-g)
+vendor =
+version = $("":T=R%Y-%m-%d)
+
+SUM = sum
+
+package.notice = ------------ NOTICE -- LICENSED SOFTWARE -- SEE README FOR DETAILS ------------
+
+package.readme = $(@.package.readme.)
+
+.package.readme. :
+ This is a package root directory $PACKAGEROOT. Source and binary
+ packages in this directory tree are controlled by the command
+ $()
+ bin/package
+ $()
+ Binary files may be in this directory or in the install root directory
+ $()
+ INSTALLROOT=$PACKAGEROOT/arch/`bin/package`
+ $()
+ For more information run
+ $()
+ bin/package help
+ $()
+ Many of the packaged commands self-document via the --man and --html
+ options; those that do have no separate man page.
+ $()
+ Each package is covered by one of the license files
+ $()
+ $(PACKAGELIB)/LICENSES/<license>
+ $()
+ where <license> is the license type for the package. At the top
+ of each license file is a URL; the license covers all software that
+ refers to this URL. For details run
+ $()
+ bin/package license [<package>]
+ $()
+ Any archives, distributions or packages made from source or
+ binaries covered by license(s) must contain the corresponding
+ license file(s)$(notice:?, this README file, and the empty file$$("\n")$$(package.notice)?.?)
+
+.package.licenses. : .FUNCTION
+ local I F L R T all save text
+ L := $(%)
+ while L == "--*"
+ I := $(L:O=1)
+ if I == "--all"
+ all = 1
+ elif I == "--save"
+ save = 1
+ elif I == "--text"
+ text = 1
+ end
+ L := $(L:O>1)
+ end
+ if "$(L)" == "*-*"
+ L += $(L:/[^-]*-//) $(L:/-.*//)
+ end
+ L += $(licenses)
+ for I $(L:U)
+ if I == "gpl"
+ I = gnu
+ all =
+ end
+ if F = "$(I:D=$(PACKAGESRC):B:S=.lic:T=F)"
+ R += $(F)
+ if save || text
+ T := $(.FIND. lib/package .lic $(F):P=W,query=type)
+ R += $(T:D=$(PACKAGESRC)/LICENSES:B)
+ end
+ if save
+ R += $(F:T=I:N=*.def:D=$(PACKAGESRC):B:S:T=F)
+ elif ! all
+ break
+ end
+ end
+ end
+ return $(R)
+
+/*
+ * glob(3) doesn't handle / in alternation -- should it?
+ */
+
+.package.glob. : .FUNCTION
+ local A D I P S
+ for I $(%)
+ if I == "*/*"
+ D := $(I:C,/.*,,)
+ if ! "$(A:N=$(D))"
+ local S.$(D)
+ A += $(D)
+ end
+ S.$(D) += $(I:C,[^/]*/,,)
+ else
+ P := $(P)$(S)$(I)
+ end
+ S = |
+ end
+ if P == "*\|*"
+ P := ($(P))
+ end
+ for I $(A)
+ P += $(I)/$(.package.glob. $(S.$(I)))
+ end
+ return $(P)
+
+
+.MAKEINIT : .package.init
+
+.package.init : .MAKE .VIRTUAL .FORCE
+ local V
+ V := $(VROOT:T=F:P=L*)
+ if ! PACKAGEROOT
+ PACKAGEROOT := $(V:N!=*/arch/+([!/]):O=1)
+ end
+ if V == "$(PACKAGEROOT)"
+ V :=
+ end
+ V += $(INSTALLROOT) $(PACKAGEROOT)
+ PACKAGEVIEW := $(V:H=RU)
+ INSTALLOFFSET := $(INSTALLROOT:C%$(PACKAGEROOT)/%%)
+ if license
+ license := $(license)|none.none
+ end
+
+PACKAGELIB = lib/package
+PACKAGESRC = $(PACKAGEROOT)/$(PACKAGELIB)
+PACKAGEBIN = $(INSTALLROOT)/$(PACKAGELIB)
+PACKAGEDIR = $(PACKAGESRC)/$(style)
+INSTALLOFFSET = $(INSTALLROOT:C%$(PACKAGEROOT)/%%)
+
+package.omit = -|*/$(init)
+package.glob.all = $(INSTALLROOT)/src/*/*/($(MAKEFILES:/:/|/G))
+package.all = $(package.glob.all:P=G:W=O=$(?$(name):A=.VIRTUAL):N!=$(package.omit):T=F:$(PACKAGEVIEW:C,.*,C;^&/;;,:/ /:/G):U)
+package.glob.pkg = $(.package.glob. $(~$(name):P=U):C%.*%$(INSTALLROOT)/src/*/&/($(MAKEFILES:/:/|/G))%) $(~$(name):P=U:N=$(name):?$$(INSTALLROOT)/src/$$(name)/($$(MAKEFILES:/:/|/G))??)
+package.pkg = $(package.glob.pkg:P=G:D:N!=$(package.omit):T=F:$(PACKAGEVIEW:C,.*,C;^&/;;,:/ /:/G):U)
+package.closure = $(closure:?$$(package.all)?$$(package.pkg)?)
+
+package.init = $(.package.glob. $("$(init)$(name)":P=U):C%.*%$(INSTALLROOT)/src/*/&/($(MAKEFILES:/:/|/G))%:P=G:T=F:D::B)
+package.ini = ignore mamprobe manmake package silent
+package.src.pat = $(PACKAGESRC)/($(name).(ini|pkg))
+package.src = $(package.src.pat:P=G) $(.package.licenses. --save $(name))
+package.bin = $(PACKAGEBIN)/$(name).ini
+
+package.mam = --never --force --mam=static --corrupt=accept --clobber --compare --link='lib*.a*' CC=$(CC.DIALECT:N=C++:?CC?cc?) package.license.class=$(license:Q) $(=) 'dontcare test' install test
+
+op = current
+stamp = [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]
+source = $(PACKAGEDIR)/$(name).$(version)$(release:?.$(release)??).$(suffix)
+binary = $(PACKAGEDIR)/$(name).$(version)$(release:?.$(release)??).$(CC.HOSTTYPE).$(suffix)
+runtime = $(PACKAGEDIR)/$(name)-run.$(version)$(release:?.$(release)??).$(CC.HOSTTYPE).$(suffix)
+old.new.source = $(PACKAGEDIR)/$(name).$(version).$(old.version).$(suffix)
+old.new.binary = $(PACKAGEDIR)/$(name).$(version).$(old.version).$(CC.HOSTTYPE).$(suffix)
+old.new.runtime = $(PACKAGEDIR)/$(name)-run.$(version).$(old.version).$(CC.HOSTTYPE).$(suffix)
+
+source.list = $("$(PACKAGEDIR)/$(name).*$(stamp).$(suffix)":P=G:H=R)
+binary.list = $("$(PACKAGEDIR)/$(name).*$(stamp).$(CC.HOSTTYPE).$(suffix)":P=G:H=R)
+runtime.list = $("$(PACKAGEDIR)/$(name)-run.*$(stamp).$(CC.HOSTTYPE).$(suffix)":P=G:H>)
+
+source.ratz = $("$(INSTALLROOT)/src/cmd/$(init)/ratz.c":T=F)
+binary.ratz = $("$(INSTALLROOT)/src/cmd/$(init)/ratz":T=F)
+
+$(init) : .VIRTUAL $(init)
+
+package.requires = 0
+
+":package:" : .MAKE .OPERATOR
+ local P I R V
+ P := $(<:O=1)
+ $(P) : $(>:V)
+ if ! package.requires
+ if ! name
+ name := $(P)
+ .PACKAGE. := $(P)
+ if name == "$(init)"
+ package.omit = -
+ package.src += $(package.ini:C,^,$(PACKAGEROOT)/bin/,) $(PACKAGESRC)/package.mk
+ else
+ $(P) : $(package.init)
+ end
+ for I $(<:O>1)
+ if I == "*=*"
+ eval
+ $(I)
+ end
+ else
+ version := $(I)
+ end
+ end
+ LICENSEFILEDEFAULT := $(.package.licenses. $(name):@/ /:/G)
+ export LICENSEFILEDEFAULT
+ end
+ if "$(>)"
+ for I $(>:V)
+ $(I) : .VIRTUAL
+ if I == "/*"
+ package.dir += $(I:V)
+ end
+ end
+ end
+ if "$(@)"
+ $(P).README := $(@)
+ else
+ $(P).README := This is the $(P) package.
+ end
+ end
+
+":AUXILIARY:" : .MAKE .OPERATOR
+ package.auxiliary.$(style) += $(>:N=/*:T=F) $(>:N!=/*:C%^%$(INSTALLROOT)/%:T=F)
+
+":CATEGORY:" : .MAKE .OPERATOR
+ if ! package.requires
+ category := $(>)
+ end
+
+.covers. : .FUNCTION
+ local I C D F K=0 L
+ for I $(%)
+ if ! "$(~covers:N=$(I:B))"
+ if F = "$(I:D:B:S=.pkg:T=F)"
+ if D = "$(F:T=I)"
+ covers : $(I:B)
+ for L $(D)
+ if L == ":COVERS:"
+ K = 1
+ elif L == ":*:"
+ if K
+ break
+ end
+ elif K
+ : $(.covers. $(L))
+ end
+ end
+ end
+ else
+ error $(--exec:?3?1?) $(I): unknown package $(I)
+ end
+ end
+ end
+
+":COVERS:" : .MAKE .OPERATOR
+ if ! package.requires
+ : $(.covers. $(>))
+ end
+
+":DESCRIPTION:" : .MAKE .OPERATOR
+ if ! package.requires
+ $(name).README := $(@:V)
+ end
+
+":DETAILS:" : .MAKE .OPERATOR
+ if ! package.requires
+ details.$(>:O=1) := $(@:V)
+ end
+
+":EXPORT:" : .MAKE .OPERATOR
+ if ! package.requires
+ export.$(style) := $(@:/$$("\n")/ /G)
+ end
+
+":INDEX:" : .MAKE .OPERATOR
+ if ! package.requires
+ index := $(>)
+ end
+
+":INSTALL:" : .MAKE .OPERATOR
+ if ! package.requires
+ local T S F X
+ S := $(>)
+ T := $(<)
+ if "$(exe.$(style))" && "$(T)" == "bin/*([!./])"
+ T := $(T).exe
+ end
+ if ! "$(S)"
+ S := $(T)
+ elif "$(exe.$(style))" && "$(S)" == "bin/*([!./])"
+ S := $(S).exe
+ end
+ install.$(style) := $(install.$(style):V)$("\n")install : $$(ROOT)/$(T)$("\n")$$(ROOT)/$(T) : $$(ARCH)/$(S)$("\n\t")cp $< $@
+ if strip && "$(T:N=*.exe)"
+ install.$(style) := $(install.$(style):V)$("\n\t")strip $@ 2>/dev/null
+ end
+ X := $(PACKAGEROOT)/arch/$(CC.HOSTTYPE)/$(S)
+ if strip && "$(X:T=Y)" == "*/?(x-)(dll|exe)"
+ F := filter $(STRIP) $(STRIPFLAGS) $(X)
+ end
+ if "$(filter.$(style):V)"
+ filter.$(style) := $(filter.$(style):V)$$("\n")
+ end
+ filter.$(style) := $(filter.$(style):V);;$(F);$(X);usr/$(T)
+ end
+
+":LICENSE:" : .MAKE .OPERATOR
+ if ! package.requires && ! license
+ license := $(>)
+ end
+
+":OMIT:" : .MAKE .OPERATOR
+ if ! package.requires
+ package.omit := $(package.omit)|$(>:C,^,*/,:/ /|/G)
+ end
+
+":POSTINSTALL:" : .MAKE .OPERATOR
+ if ! package.requires
+ postinstall.$(style) := $(@:V)
+ end
+
+":README:" : .MAKE .OPERATOR
+ if ! package.requires
+ readme.$(style) := $(@:V)
+ end
+
+.requires. : .FUNCTION
+ local I C D F K=0 L V T M=0
+ for I $(%)
+ if ! "$(~requires:N=$(I:B))"
+ if F = "$(I:D:B:S=.pkg:T=F)"
+ if I == "$(init)"
+ package.omit = -
+ else
+ requires : $(I:B)
+ end
+ if V = "$(I:D:B=gen/$(I:B):S=.ver:T=F)"
+ req : $(I:B)
+ else
+ error 1 $(I): package should be written before $(P)
+ end
+ let package.requires = package.requires + 1
+ include "$(F)"
+ let package.requires = package.requires - 1
+ else
+ error 1 $(I): package not found
+ end
+ end
+ end
+
+":REQUIRES:" : .MAKE .OPERATOR
+ : $(.requires. $(>))
+
+":TEST:" : .MAKE .OPERATOR
+ if ! package.requires
+ local T
+ T := $(>)
+ if "$(T)" == "bin/*([!./])"
+ if "$(exe.$(style))"
+ T := $(T).exe
+ end
+ T := $$(PWD)/$$(ARCH)/$(T)
+ end
+ test.$(style) := $(test.$(style):V)$("\n")test : $(T:V)$("\n\t")$(@)
+ end
+
+base delta : .MAKE .VIRTUAL .FORCE
+ op := $(<)
+
+closure : .MAKE .VIRTUAL .FORCE
+ $(<) := 1
+
+cyg exp lcl pkg rpm tgz : .MAKE .VIRTUAL .FORCE
+ style := $(<)
+
+source : .source.init .source.gen .source.$$(style)
+
+.source.init : .MAKE
+ local A B D P V I
+ type := source
+ if ! "$(incremental)"
+ incremental = 1
+ end
+ if "$(source.$(name))"
+ suffix = c
+ end
+ : $(.init.$(style))
+ : $(details.$(style):V:R) :
+ A := $(source.list)
+ B := $(A:N=*.$(stamp).$(suffix):N!=*.$(stamp).$(stamp).*:O=1:T=F)
+ P := $(A:N=*.$(stamp).$(suffix):N!=*.$(stamp).$(stamp).*:O=2:T=F)
+ D := $(A:N=*.$(stamp).$(stamp).$(suffix):O=1:T=F)
+ if op == "delta"
+ if ! B
+ error 3 delta requires a base archive
+ end
+ base := -z $(B)
+ deltaversion := $(B:B:/$(name).//)
+ let deltasince = $(deltaversion:/.*-//) + 1
+ deltasince := $(deltaversion:/[^-]*$/$(deltasince:F=%02d)/)
+ if "$(release)" != "$(stamp)"
+ release := $("":T=R%Y-%m-%d)
+ end
+ source := $(B:D:B:S=.$(release).$(suffix))
+ version := $(source:B:B:/$(name).//)
+ elif B || op == "base"
+ if op == "base"
+ for I $(B) $(P)
+ V := $(I:B:/$(name)\.\([^.]*\).*/\1/)
+ if V == "$(stamp)" && V != "$(version)"
+ old.version := $(V)
+ old.source := $(I)
+ if "$(old.version)" >= "$(version)"
+ error 3 $(name): previous base $(old.version) is newer than $(version)
+ end
+ break
+ end
+ end
+ else
+ source := $(B)
+ end
+ if B == "$(source)"
+ if "$(B:D:B:B)" == "$(D:D:B:B)" && "$(B:B::S)" != "$(D:B::S)"
+ error 3 $(B:B:S): base overwrite would invalidate delta $(D:B:S)
+ end
+ error 1 $(B:B:S): replacing current base
+ end
+ version := $(source:B:S:/^$(name).\(.*\).$(suffix)$/\1/)
+ end
+ PACKAGEGEN := $(PACKAGESRC)/gen
+
+.source.gen : $$(PACKAGEDIR) $$(PACKAGEGEN) $$(PACKAGEGEN)/SOURCE.html $$(PACKAGEGEN)/BINARY.html $$(PACKAGEGEN)/DETAILS.html
+
+BINPACKAGE := $(PATH:/:/ /G:X=package:T=F:O=1)
+
+$$(PACKAGEDIR) $$(PACKAGEGEN) : .IGNORE
+ [[ -d $(<) ]] || mkdir $(<)
+
+$$(PACKAGEGEN)/SOURCE.html : $(BINPACKAGE)
+ $(*) html source > $(<)
+
+$$(PACKAGEGEN)/BINARY.html : $(BINPACKAGE)
+ $(*) html binary > $(<)
+
+$$(PACKAGEGEN)/DETAILS.html : $(BINPACKAGE)
+ $(*) html intro > $(<)
+
+.source.exp .source.pkg .source.rpm : .MAKE
+ error 3 $(style): source package style not supported yet
+
+exe.cyg = .exe
+vendor.cyg = gnu
+
+.name.cyg : .FUNCTION
+ local N
+ N := $(%)
+ if N == "*-*"
+ vendor := $(N:/-.*//)
+ if vendor == "$(vendor.cyg)"
+ vendor :=
+ N := $(N:/[^-]*-//)
+ end
+ N := $(N:/-//G)
+ end
+ return $(N)
+
+.init.cyg : .FUNCTION
+ local N O
+ closure = 1
+ init = .
+ strip = 1
+ suffix = tar.bz2
+ format = tbz
+ vendor := $(licenses:N!=$(vendor.cyg):O=1)
+ package.ini := $(package.ini)
+ package.src.pat := $(package.src.pat)
+ package.src := $(package.src)
+ package.bin := $(package.bin)
+ .source.gen : .CLEAR $(*.source.gen:V:N!=*.html)
+ name.original := $(name)
+ name := $(.name.cyg $(name))
+ if name != "$(name.original)"
+ $(name) : $(~$(name.original))
+ O := $(~covers)
+ covers : .CLEAR
+ for N $(O)
+ covers : $(.name.cyg $(N))
+ end
+ end
+ stamp = [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9]
+ version.original := $(version)
+ version := $(version:/-//G)-1
+ if opt
+ opt := $(opt)/$(vendor)/
+ else
+ opt := $(name)-$(version)/
+ end
+ if type == "source"
+ version := $(version)-src
+ source = $(PACKAGEDIR)/$(name)-$(version)$(release:?.$(release)??).$(suffix)
+ else
+ binary = $(PACKAGEDIR)/$(name)-$(version)$(release:?.$(release)??).$(suffix)
+ end
+
+.source.cyg :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ integer m=0 o
+ cat > $tmp/configure <<'!'
+ echo "you didn't have to do that"
+ !
+ chmod +x $tmp/configure
+ echo ";;;$tmp/configure;configure"
+ cat > $tmp/Makefile0 <<'!'
+ HOSTTYPE := $$(shell bin/package)
+ ROOT = ../..
+ ARCH = arch/$$(HOSTTYPE)
+ all :
+ PACKAGEROOT= CYGWIN="$$CYGWIN ntsec binmode" bin/package make $(export.$(style))
+ install : all
+ $(install.$(style):V)
+ $(test.$(style):V)
+ !
+ echo ";;;$tmp/Makefile0;Makefile"
+ cat > $tmp/CYGWIN-README <<'!'
+ $(readme.$(style):@?$$(readme.$$(style))$$("\n\n")??)To build binaries from source into the ./arch/`bin/package` tree run:
+ $()
+ make
+ $()
+ $(test.$(style):@?To test the binaries after building/installing run:$$("\n\n\t")make test$$("\n\n")??)To build and/or install the binaries run:
+ $()
+ make install
+ $()
+ The bin/package command provides a command line interface for all package
+ operations. The $(opt:/.$//) source and binary packages were generated by:
+ $()
+ package write cyg base source version=$(version.original) $(name.original)
+ package write cyg base binary version=$(version.original) $(name.original)
+ $()
+ using the $(org)-base package. To download and install the latest
+ $(org)-base source package in /opt/$(org) run:
+ $()
+ PATH=/opt/$(org)/bin:$PATH
+ cd /opt/$(org)
+ package authorize "NAME" password "PASSWORD" setup flat source $("\\")
+ $(url) $("\\")
+ $(org)-base
+ package make
+ $()
+ and export /opt/$(org)/bin in PATH to use. The NAME and PASSWORD signify your
+ agreement to the software license(s). All users get the same NAME and PASSWORD.
+ See $(url) for details. If multiple architectures may be built under
+ /opt/$(org) then drop "flat" and export /opt/$(org)/arch/`package`/bin in PATH
+ to use. To update previously downloaded packages from the same url simply run:
+ $()
+ cd /opt/$(org)
+ package setup
+ package make
+ $()
+ To download and install the latest $(org)-base binary package in
+ /opt/$(org) change "source" to "binary" and omit "package make".
+ !
+ echo ";;;$tmp/CYGWIN-README;CYGWIN-PATCHES/README"
+ cat > $(source:/-src.$(suffix)//).setup.hint <<'!'
+ category: $(category:/\(.\).*/\1/U)$(category:/.\(.*\)/\1/L)
+ requires: cygwin
+ sdesc: "$(index)"
+ ldesc: "$($(name.original).README)"
+ !
+ echo ";;;$(source:/-src.$(suffix)//).setup.hint;CYGWIN-PATCHES/setup.hint"
+ echo ";;;$(BINPACKAGE);bin/package"
+ cat > $tmp/Makefile <<'!'
+ :MAKE:
+ !
+ echo ";;;$tmp/Makefile;src/Makefile"
+ echo ";;;$tmp/Makefile;src/cmd/Makefile"
+ echo ";;;$tmp/Makefile;src/lib/Makefile"
+ if [[ '$(mamfile)' == 1 ]]
+ then cat > $tmp/Mamfile1 <<'!'
+ info mam static
+ note source level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*/*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ echo ";;;$tmp/Mamfile1;src/Mamfile"
+ cat > $tmp/Mamfile2 <<'!'
+ info mam static
+ note component level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ echo ";;;$tmp/Mamfile2;src/cmd/Mamfile"
+ echo ";;;$tmp/Mamfile2;src/lib/Mamfile"
+ fi
+ $(package.src:U:T=F:/.*/echo ";;;&"$("\n")/)
+ echo ";;;$(PACKAGEGEN)/$(name.original).req"
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ if [[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
+ then if [[ '$(mamfile)' == 1 ]]
+ then (( o=m ))
+ s=$( $(MAKE) --noexec --recurse=list recurse 2>/dev/null )
+ if [[ $s ]]
+ then for j in $s
+ do if [[ -d $j ]]
+ then cd $j
+ if [[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
+ then (( m++ ))
+ $(MAKE) $(package.mam) $(export.$(style):Q) > $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/$j/Mamfile"
+ fi
+ cd $(INSTALLROOT)/$i
+ fi
+ done
+ if (( o != m ))
+ then (( m++ ))
+ cat > $tmp/$m.mam <<'!'
+ info mam static
+ note subcomponent level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ echo ";;;$tmp/$m.mam;$i/Mamfile"
+ fi
+ else (( m++ ))
+ $(MAKE) $(package.mam) $(export.$(style):Q) > $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/Mamfile"
+ fi
+ fi
+ $(MAKE) --noexec $(-) $(=) recurse list.package.$(type) package.license.class=$(license:Q)
+ fi
+ done
+ set -- $(package.dir:P=G)
+ for i
+ do tw -d $i -e "action:printf(';;;%s;%s\n',path,path);"
+ done
+ } |
+ {
+ : > $tmp/HEAD
+ cat > $tmp/README <<'!'
+ $(package.readme)
+ !
+ echo ";;;$tmp/README;README"
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ --format=$(format) \
+ --local \
+ -wvf $(source) $(base) \
+ $(PACKAGEVIEW:C%.*%-s",^&/,,"%) \
+ $(vendor:?-s",^[^/],$(opt)&,"??)
+ $(SUM) -x $(checksum) < $(source) > $(source:D:B:S=.$(checksum))
+ rm -rf $tmp
+ fi
+
+.source.lcl :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ integer m=0 o
+ $(package.src:U:T=F:/.*/echo ";;;&"$("\n")/)
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ $(MAKE) --noexec $(-) $(=) .FILES.+=Mamfile recurse list.package.local
+ done
+ set -- $(package.dir:P=G)
+ for i
+ do tw -d $i -e "action:printf(';;;%s;%s\n',path,path);"
+ done
+ } |
+ sort -t';' -k5,5 -u |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ -wvf $(source) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ $(PACKAGEVIEW:C%.*%-s",^&/,,"%)
+ rm -rf $tmp
+ fi
+
+.source.tgz :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ integer m=0 o
+ if [[ '$(init)' == '$(name)' ]]
+ then cat > $tmp/Makefile <<'!'
+ :MAKE:
+ !
+ $(CMP) $(CMPFLAGS) $tmp/Makefile $(PACKAGEROOT)/src/Makefile && touch -r $(PACKAGEROOT)/src/Makefile $tmp/Makefile
+ echo ";;;$tmp/Makefile;src/Makefile"
+ cp $tmp/Makefile $tmp/Makefile1
+ $(CMP) $(CMPFLAGS) $tmp/Makefile1 $(PACKAGEROOT)/src/cmd/Makefile && touch -r $(PACKAGEROOT)/src/cmd/Makefile $tmp/Makefile1
+ echo ";;;$tmp/Makefile1;src/cmd/Makefile"
+ cp $tmp/Makefile $tmp/Makefile2
+ $(CMP) $(CMPFLAGS) $tmp/Makefile2 $(PACKAGEROOT)/src/lib/Makefile && touch -r $(PACKAGEROOT)/src/lib/Makefile $tmp/Makefile2
+ echo ";;;$tmp/Makefile2;src/lib/Makefile"
+ if [[ '$(mamfile)' == 1 ]]
+ then cat > $tmp/Mamfile1 <<'!'
+ info mam static
+ note source level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*/*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ $(CMP) $(CMPFLAGS) $tmp/Mamfile1 $(PACKAGEROOT)/src/Mamfile && touch -r $(PACKAGEROOT)/src/Mamfile $tmp/Mamfile1
+ echo ";;;$tmp/Mamfile1;src/Mamfile"
+ cat > $tmp/Mamfile2 <<'!'
+ info mam static
+ note component level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ $(CMP) $(CMPFLAGS) $tmp/Mamfile2 $(PACKAGEROOT)/src/cmd/Mamfile && touch -r $(PACKAGEROOT)/src/cmd/Mamfile $tmp/Mamfile2
+ echo ";;;$tmp/Mamfile2;src/cmd/Mamfile"
+ cp $tmp/Mamfile2 $tmp/Mamfile3
+ $(CMP) $(CMPFLAGS) $tmp/Mamfile3 $(PACKAGEROOT)/src/lib/Mamfile && touch -r $(PACKAGEROOT)/src/lib/Mamfile $tmp/Mamfile3
+ echo ";;;$tmp/Mamfile3;src/lib/Mamfile"
+ fi
+ fi
+ $(package.src:U:T=F:C%^$(PACKAGEROOT)/%%:C%.*%echo ";;;$(PACKAGEROOT)/&;&"$("\n")%)
+ if [[ '$(~covers)' ]]
+ then for i in $(~covers)
+ do for j in lib pkg
+ do if [[ -f $(PACKAGESRC)/$i.$j ]]
+ then echo ";;;$(PACKAGESRC)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ for j in ver req
+ do if [[ -f $(PACKAGEGEN)/$i.$j ]]
+ then echo ";;;$(PACKAGEGEN)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ done
+ for i in $(~covers:D=$(PACKAGESRC):B:S=.lic:T=F:T=I:N=*.def:D=$(PACKAGESRC):B:S:T=F:B:S)
+ do echo ";;;$(PACKAGESRC)/$i;$(PACKAGELIB)/$i"
+ done
+ fi
+ if [[ '$(PACKAGEDIR:B)' == '$(style)' ]]
+ then echo $(name) $(version) $(release|version) 1 > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).ver || cp $tmp/t $(PACKAGEGEN)/$(name).ver
+ echo ";;;$(PACKAGEGEN)/$(name).ver;$(PACKAGELIB)/$(name).ver"
+ sed 's,1$,0,' $(~req:D=$(PACKAGEGEN):B:S=.ver:T=F) < /dev/null > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).req || cp $tmp/t $(PACKAGEGEN)/$(name).req
+ echo ";;;$(PACKAGEGEN)/$(name).req;$(PACKAGELIB)/$(name).req"
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).inx || cp $tmp/t $(PACKAGEGEN)/$(name).inx
+ {
+ {
+ echo '$($(name).README)'
+ if [[ '$(~covers)' ]]
+ then echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
+ fi
+ if [[ '$(~requires)' ]]
+ then echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
+ fi
+ } | fmt
+ package help source
+ package release $(name)
+ } > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).README || cp $tmp/t $(PACKAGEGEN)/$(name).README
+ echo ";;;$(PACKAGEGEN)/$(name).README;$(PACKAGELIB)/$(name).README"
+ {
+ echo '.xx title="$(name) package"'
+ echo '.xx meta.description="$(name) package"'
+ echo '.xx meta.keywords="software, package"'
+ echo '.MT 4'
+ echo '.TL'
+ echo '$(name) package'
+ echo '.H 1 "$(name) package"'
+ echo '$($(name).README)'
+ set -- $(package.closure:C,.*,$(INSTALLROOT)/&/PROMO.mm,:T=F:D::B)
+ hot=
+ for i
+ do hot="$hot -e s/\\(\\<$i\\>\\)/\\\\h'0*1'\\1\\\\h'0'/"
+ done
+ set -- $(package.closure:B)
+ if (( $# ))
+ then echo 'Components in this package:'
+ echo '.P'
+ echo '.TS'
+ echo 'center expand;'
+ echo 'l l l l l l.'
+ if [[ $hot ]]
+ then hot="sed $hot"
+ else hot=cat
+ fi
+ for i
+ do echo $i
+ done |
+ pr -6 -t -s' ' |
+ $hot
+ echo '.TE'
+ fi
+ echo '.P'
+ if [[ '$(~covers)' ]]
+ then echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
+ fi
+ if [[ '$(~requires)' ]]
+ then echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
+ fi
+ set -- $(.package.licenses. --all $(name))
+ case $# in
+ 0) ;;
+ *) case $# in
+ 1) echo 'The software is covered by this license:' ;;
+ *) echo 'The software is covered by these licenses:' ;;
+ esac
+ echo .BL
+ for j
+ do i=$( $(PROTO) -l $j -p -h -o type=usage /dev/null | sed -e 's,.*\[-license?\([^]]*\).*,\1,' )
+ echo .LI
+ echo ".xx link=\"$i\""
+ done
+ echo .LE
+ echo 'Individual components may be covered by separate licenses;'
+ echo 'refer to the component source and/or binaries for more information.'
+ echo .P
+ ;;
+ esac
+ echo 'A recent'
+ echo '.xx link="release change log"'
+ echo 'is also included.'
+ cat $(package.closure:C,.*,$(INSTALLROOT)/&/PROMO.mm,:T=F) < /dev/null
+ echo '.H 1 "release change log"'
+ echo '.xx index'
+ echo '.nf'
+ package release $(name) |
+ sed -e 's/:::::::: \(.*\) ::::::::/.fi\$("\n").H 1 "\1 changes"\$("\n").nf/'
+ echo '.fi'
+ } |
+ $(MM2HTML) $(MM2HTMLFLAGS) -o nohtml.ident > $tmp/t
+ $(STDED) $(STDEDFLAGS) $tmp/t <<'!'
+ /^<!--LABELS-->$/,/^<!--\/LABELS-->$/s/ changes</</
+ /^<!--LABELS-->$/,/^<!--\/LABELS-->$/m/<A name="release change log">/
+ w
+ q
+ !
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).html || cp $tmp/t $(PACKAGEGEN)/$(name).html
+ echo ";;;$(PACKAGEGEN)/$(name).html;$(PACKAGELIB)/$(name).html"
+ if [[ '$(deltasince)' ]]
+ then {
+ echo '.xx title="$(name) package"'
+ echo '.xx meta.description="$(name) package $(version) delta $(release)"'
+ echo '.xx meta.keywords="software, package, delta"'
+ echo '.MT 4'
+ echo '.TL'
+ echo '$(name) package $(deltaversion) delta $(release)'
+ echo '.H 1 "$(name) package $(deltaversion) delta $(release) changes"'
+ echo '.nf'
+ package release $(deltasince) $(name) |
+ sed -e 's/:::::::: \(.*\) ::::::::/.H 2 \1/'
+ echo '.fi'
+ } |
+ $(MM2HTML) $(MM2HTMLFLAGS) -o nohtml.ident > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).$(release).html || cp $tmp/t $(PACKAGEGEN)/$(name).$(release).html
+ echo ";;;$(PACKAGEGEN)/$(name).$(release).html;$(PACKAGELIB)/$(name).$(release).html"
+ fi
+ fi
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ if [[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
+ then if [[ '$(mamfile)' == 1 ]]
+ then (( o=m ))
+ s=$( $(MAKE) --noexec --recurse=list recurse 2>/dev/null )
+ if [[ $s ]]
+ then for j in $s
+ do if [[ -d $j ]]
+ then cd $j
+ if [[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
+ then (( m++ ))
+ $(MAKE) $(package.mam) > $tmp/$m.mam
+ $(CMP) $(CMPFLAGS) $tmp/$m.mam $(PACKAGEROOT)/$i/$j/Mamfile && touch -r $(PACKAGEROOT)/$i/$j/Mamfile $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/$j/Mamfile"
+ fi
+ cd $(INSTALLROOT)/$i
+ fi
+ done
+ if (( o != m ))
+ then (( m++ ))
+ cat > $tmp/$m.mam <<'!'
+ info mam static
+ note subcomponent level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ $(CMP) $(CMPFLAGS) $tmp/$m.mam $(PACKAGEROOT)/$i/Mamfile && touch -r $(PACKAGEROOT)/$i/Mamfile $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/Mamfile"
+ fi
+ else (( m++ ))
+ $(MAKE) $(package.mam) > $tmp/$m.mam
+ $(CMP) $(CMPFLAGS) $tmp/$m.mam $(PACKAGEROOT)/$i/Mamfile && touch -r $(PACKAGEROOT)/$i/Mamfile $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/Mamfile"
+ fi
+ fi
+ $(MAKE) --noexec $(-) $(=) recurse list.package.$(type) package.license.class=$(license:Q) $(copyright:N=1:??LICENSE=?)
+ fi
+ done
+ set -- $(package.dir:P=G)
+ for i
+ do tw -d $i -e "action:printf(';;;%s;%s\n',path,path);"
+ done
+ } |
+ {
+ : > $tmp/HEAD
+ [[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
+ cat > $tmp/README <<'!'
+ $(package.readme)
+ !
+ echo ";;;$tmp/README;README"
+ $(CMP) $(CMPFLAGS) $tmp/README $(PACKAGEROOT)/README && touch -r $(PACKAGEROOT)/README $tmp/README
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ -wvf $(source) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ $(PACKAGEVIEW:C%.*%-s",^&/,,"%)
+ $(SUM) -x $(checksum) < $(source) > $(source:D:B:S=.$(checksum))
+ echo local > $(source:D:B=$(name):S=.tim)
+ if [[ '$(incremental)' == 1 && '$(old.source)' ]]
+ then $(PAX) -rf $(source) -wvf $(old.new.source) -z $(old.source)
+ $(SUM) -x $(checksum) < $(old.new.source) > $(old.new.source:D:B:S=.$(checksum))
+ fi
+ rm -rf $tmp
+ else if [[ '$(old.source)' ]] && $(CMP) $(CMPFLAGS) $(source.$(name)) $(source)
+ then : $(name) is up to date
+ else echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
+ : > $(PACKAGEGEN)/$(name).req
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $(PACKAGEGEN)/$(name).inx
+ {
+ echo '.xx title="$(name) package"'
+ echo '.xx meta.description="$(name) package"'
+ echo '.xx meta.keywords="software, package"'
+ echo '.MT 4'
+ echo '.TL'
+ echo '$(name) package'
+ echo '.H 1'
+ echo '$($(name).README)'
+ } |
+ $(MM2HTML) $(MM2HTMLFLAGS) -o nohtml.ident > $(PACKAGEGEN)/$(name).html
+ if [[ '$(source.$(name))' ]]
+ then {
+ echo '$($(name).README)'
+ package help source
+ } > $(PACKAGEGEN)/$(name).README
+ cp $(source.$(name)) $(source)
+ $(SUM) -x $(checksum) < $(source) > $(source:D:B:S=.$(checksum))
+ fi
+ echo local > $(source:D:B=$(name):S=.tim)
+ fi
+ fi
+
+binary : .binary.init .binary.gen .binary.$$(style)
+
+.binary.init : .MAKE
+ local A B D I P V
+ type := binary
+ if ! "$(incremental)"
+ incremental = 0
+ end
+ if ! "$(~$(name))"
+ if name == "ratz"
+ suffix = exe
+ else
+ suffix = gz
+ end
+ end
+ : $(.init.$(style)) :
+ : $(details.$(style):V:R) :
+ A := $(binary.list)
+ B := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=1:T=F)
+ P := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=2:T=F)
+ D := $(A:N=*.$(stamp).$(stamp).$(CC.HOSTTYPE).$(suffix):O=1:T=F)
+ if op == "delta"
+ if ! B
+ error 3 delta requires a base archive
+ end
+ base := -z $(B)
+ if "$(release)" != "$(stamp)"
+ release := $("":T=R%Y-%m-%d)
+ end
+ binary := $(B:/$(CC.HOSTTYPE).$(suffix)$/$(release).&/)
+ version := $(binary:B:B:/$(name).//)
+ elif B || op == "base"
+ if op == "base"
+ for I $(B) $(P)
+ V := $(I:B:/$(name)\.\([^.]*\).*/\1/)
+ if V == "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" && V != "$(version)"
+ old.version := $(V)
+ old.binary := $(I)
+ if "$(old.version)" >= "$(version)"
+ error 3 $(name): previous base $(old.version) is newer than $(version)
+ end
+ break
+ end
+ end
+ else
+ binary := $(B)
+ end
+ if B == "$(binary)"
+ if "$(B:D:B)" == "$(D:D:B)" && "$(B:S)" != "$(D:S)"
+ error 3 $(B:B:S): base overwrite would invalidate delta $(D:B:S)
+ end
+ error 1 $(B:B:S): replacing current base
+ end
+ version := $(binary:B:/$(name).//:/\..*//)
+ end
+ PACKAGEGEN := $(PACKAGEBIN)/gen
+
+.binary.gen : $$(PACKAGEDIR) $$(PACKAGEGEN)
+
+.binary.exp .binary.pkg .binary.rpm : .MAKE
+ error 3 $(style): binary package style not supported yet
+
+.binary.cyg :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ integer m=0 o
+ {
+ echo '$($(name.original).README)' | fmt
+ cat <<'!'
+ $(readme.$(style):@?$$("\n")$$(readme.$$(style))??)
+ !
+ } > $tmp/README1
+ echo ";;;$tmp/README1;usr/share/doc/Cygwin/$(opt:/.$//).README"
+ {
+ echo '$($(name.original).README)' | fmt
+ cat <<'!'
+ $()
+ The remainder of this file is the README from the source package
+ that was used to generate this binary package. It describes
+ the source build hierarchy, not the current directory.
+ $()
+ $(package.readme)
+ !
+ } > $tmp/README2
+ echo ";;;$tmp/README2;usr/share/doc/$(opt)README"
+ package release $(name.original) > $tmp/RELEASE
+ echo ";;;$tmp/RELEASE;usr/share/doc/$(opt)RELEASE"
+ cat > $(binary:/.$(suffix)//).setup.hint <<'!'
+ category: $(category:/\(.\).*/\1/U)$(category:/.\(.*\)/\1/L)
+ requires: cygwin
+ sdesc: "$(index)"
+ ldesc: "$($(name.original).README)"
+ !
+ set -- $(.package.licenses. --text $(name.original):N!=*.lic)
+ for i
+ do echo ";;;${i};usr/share/doc/$(opt)LICENSE-${i##*/}"
+ done
+ cat <<'!'
+ $(filter.$(style))
+ !
+ if [[ '$(postinstall.$(style):V:O=1:?1??)' ]]
+ then cat >$tmp/postinstall <<'!'
+ $("#")!/bin/sh
+ $(postinstall.$(style))
+ !
+ echo ";;;$tmp/postinstall;etc/postinstall/$(name).sh"
+ fi
+ } |
+ {
+ : > $tmp/HEAD
+ [[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ --format=$(format) \
+ --local \
+ -wvf $(binary)
+ $(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
+ rm -rf $tmp
+ fi
+
+.binary.lcl :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ $(package.src:U:T=F:/.*/echo ";;;&"$("\n")/)
+ $(package.bin:U:T=F:/.*/echo ";;;&"$("\n")/)
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ $(MAKE) --noexec $(-) --variants=$(variants:Q) $(=) recurse list.package.$(type) package.license.class=$(license:Q) cc-
+ done
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ --checksum=md5:$(PACKAGEGEN)/$(name).sum \
+ --install=$(PACKAGEGEN)/$(name).ins \
+ -wvf $(binary) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ -s",^$tmp/,$(INSTALLOFFSET)/," \
+ $(PACKAGEROOT:C%.*%-s",^&/,,"%)
+ $(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
+ echo local > $(binary:D:B=$(name):S=.$(CC.HOSTTYPE).tim)
+ rm -rf $tmp
+ fi
+
+.binary.tgz :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ if [[ '$(init)' == '$(name)' ]]
+ then for i in lib32 lib64
+ do if [[ -d $(INSTALLROOT)/$i ]]
+ then echo ";physical;;$(INSTALLROOT)/$i"
+ fi
+ done
+ fi
+ $(package.src:U:T=F:C%^$(PACKAGEROOT)/%%:C%.*%echo ";;;$(PACKAGEROOT)/&;&"$("\n")%)
+ $(package.bin:U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
+ $(package.auxiliary.$(style):U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
+ if [[ '$(PACKAGEDIR:B)' == '$(style)' ]]
+ then echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
+ echo ";;;$(PACKAGEGEN)/$(name).ver;$(PACKAGELIB)/$(name).ver"
+ if [[ '$(~covers)' ]]
+ then for i in $(~covers)
+ do for j in lic pkg
+ do if [[ -f $(PACKAGESRC)/$i.$j ]]
+ then echo ";;;$(PACKAGESRC)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ for j in ver req
+ do if [[ -f $(PACKAGEGEN)/$i.$j ]]
+ then echo ";;;$(PACKAGEGEN)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ done
+ for i in $(~covers:D=$(PACKAGESRC):B:S=.lic:T=F:T=I:N=*.def:D=$(PACKAGESRC):B:S:T=F:B:S)
+ do echo ";;;$(PACKAGESRC)/$i;$(PACKAGELIB)/$i"
+ done
+ fi
+ sed 's,1$,0,' $(~req:D=$(PACKAGEGEN):B:S=.ver:T=F) < /dev/null > $(PACKAGEGEN)/$(name).req
+ echo ";;;$(PACKAGEGEN)/$(name).req;$(PACKAGELIB)/$(name).req"
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $(PACKAGEGEN)/$(name).inx
+ {
+ {
+ echo '$($(name).README)'
+ if [[ '$(~covers)' ]]
+ then echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
+ fi
+ if [[ '$(~requires)' ]]
+ then echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
+ fi
+ } | fmt
+ package help binary
+ package release $(name)
+ } > $(PACKAGEGEN)/$(name).README
+ echo ";;;$(PACKAGEGEN)/$(name).README;$(PACKAGELIB)/$(name).README"
+ fi
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ $(MAKE) --noexec $(-) --variants=$(variants:Q) $(=) package.strip=$(strip) recurse list.package.$(type) package.license.class=$(license:Q) cc-
+ done
+ } |
+ {
+ : > $tmp/HEAD
+ [[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
+ cat > $tmp/README <<'!'
+ $(package.readme)
+ !
+ echo ";;;$tmp/README;README"
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ --checksum=md5:$(PACKAGEGEN)/$(name).sum \
+ --install=$(PACKAGEGEN)/$(name).ins \
+ -wvf $(binary) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ -s",^$tmp/,$(INSTALLOFFSET)/," \
+ $(PACKAGEROOT:C%.*%-s",^&/,,"%)
+ echo $(binary) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ $(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
+ echo $(binary:D:B:S=.$(checksum)) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ echo local > $(binary:D:B=$(name):S=.$(CC.HOSTTYPE).tim)
+ if [[ '$(incremental)' == 1 && '$(old.binary)' ]]
+ then $(PAX) -rf $(binary) -wvf $(old.new.binary) -z $(old.binary)
+ echo $(old.new.binary) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ $(SUM) -x $(checksum) < $(old.new.binary) > $(old.new.binary:D:B:S=.$(checksum))
+ echo $(old.new.binary:D:B:S=.$(checksum)) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ fi
+ rm -rf $tmp
+ else if [[ '$(binary.$(name))' ]]
+ then exe=$(binary.$(name))
+ else exe=$(INSTALLROOT)/bin/$(name)
+ fi
+ if [[ '$(old.binary)' ]] && $(CMP) $(CMPFLAGS) $exe $(binary)
+ then : $(name) is up to date
+ else echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
+ : > $(PACKAGEGEN)/$(name).req
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $(PACKAGEGEN)/$(name).inx
+ {
+ echo '$($(name).README)'
+ package help binary
+ } > $(PACKAGEGEN)/$(name).README
+ case "$(binary)" in
+ *.gz) gzip < $exe > $(binary) ;;
+ *) cp $exe $(binary) ;;
+ esac
+ $(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
+ echo local > $(binary:D:B=$(name):S=.$(CC.HOSTTYPE).tim)
+ fi
+ echo $(binary) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ echo $(binary:D:B:S=.$(checksum)) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ fi
+
+runtime : .runtime.init .runtime.gen .runtime.$$(style)
+
+.runtime.init : .MAKE
+ local A B D I P V
+ type := runtime
+ if ! "$(incremental)"
+ incremental = 0
+ end
+ if ! "$(~$(name))"
+ if name == "ratz"
+ suffix = exe
+ else
+ suffix = gz
+ end
+ end
+ : $(.init.$(style)) :
+ : $(details.$(style):V:R) :
+ A := $(runtime.list)
+ B := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=1:T=F)
+ P := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=2:T=F)
+ D := $(A:N=*.$(stamp).$(stamp).$(CC.HOSTTYPE).$(suffix):O=1:T=F)
+ if op == "delta"
+ if ! B
+ error 3 delta requires a base archive
+ end
+ base := -z $(B)
+ if "$(release)" != "$(stamp)"
+ release := $("":T=R%Y-%m-%d)
+ end
+ runtime := $(B:/$(CC.HOSTTYPE).$(suffix)$/$(release).&/)
+ version := $(runtime:B:B:/$(name).//)
+ elif B || op == "base"
+ if op == "base"
+ for I $(B) $(P)
+ V := $(I:B:/$(name)-run\.\([^.]*\).*/\1/)
+ if V == "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" && V != "$(version)"
+ old.version := $(V)
+ old.runtime := $(I)
+ if "$(old.version)" >= "$(version)"
+ error 3 $(name): previous base $(old.version) is newer than $(version)
+ end
+ break
+ end
+ end
+ else
+ runtime := $(B)
+ end
+ if B == "$(runtime)"
+ if "$(B:D:B)" == "$(D:D:B)" && "$(B:S)" != "$(D:S)"
+ error 3 $(B:B:S): base overwrite would invalidate delta $(D:B:S)
+ end
+ error 1 $(B:B:S): replacing current base
+ end
+ version := $(runtime:B:/$(name)-run.//:/\..*//)
+ end
+ PACKAGEGEN := $(PACKAGESRC)/gen
+
+.runtime.gen : $$(PACKAGEDIR) $$(PACKAGEGEN)
+
+.runtime.cyg .runtime.exp .runtime.lcl .runtime.pkg .runtime.rpm : .MAKE
+ error 3 $(style): runtime package style not supported yet
+
+.runtime.tgz :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ if [[ '$(init)' == '$(name)' ]]
+ then for i in lib32 lib64
+ do if [[ -d $(INSTALLROOT)/$i ]]
+ then echo ";physical;;$(INSTALLROOT)/$i"
+ fi
+ done
+ fi
+ $(package.src:U:T=F:C%^$(PACKAGEROOT)/%%:C%.*%echo ";;;$(PACKAGEROOT)/&;&"$("\n")%)
+ $(package.bin:U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
+ $(package.auxiliary.$(style):U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
+ echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
+ echo ";;;$(PACKAGEGEN)/$(name).ver;$(PACKAGELIB)/$(name).ver"
+ if [[ '$(~covers)' ]]
+ then for i in $(~covers)
+ do for j in lic pkg
+ do if [[ -f $(PACKAGESRC)/$i.$j ]]
+ then echo ";;;$(PACKAGESRC)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ for j in ver req
+ do if [[ -f $(PACKAGEGEN)/$i.$j ]]
+ then echo ";;;$(PACKAGEGEN)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ done
+ for i in $(~covers:D=$(PACKAGESRC):B:S=.lic:T=F:T=I:N=*.def:D=$(PACKAGESRC):B:S:T=F:B:S)
+ do echo ";;;$(PACKAGESRC)/$i;$(PACKAGELIB)/$i"
+ done
+ fi
+ sed 's,1$,0,' $(~req:D=$(PACKAGEGEN):B:S=.ver:T=F) < /dev/null > $(PACKAGEGEN)/$(name).req
+ echo ";;;$(PACKAGEGEN)/$(name).req;$(PACKAGELIB)/$(name).req"
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $(PACKAGEGEN)/$(name).inx
+ {
+ {
+ echo '$($(name).README)'
+ if [[ '$(~covers)' ]]
+ then echo
+ echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
+ fi
+ if [[ '$(~requires)' ]]
+ then echo
+ echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
+ fi
+ echo
+ echo "To install this $(type) package read the tarball into a directory"
+ echo "suitable for containing bin and lib subdirectories, and run the"
+ echo "$(PACKAGELIB)/gen/$(name)-run.ins script to fix up permissions."
+ echo
+ echo "To use the package export the bin directory in PATH. The commands and"
+ echo "libraries use \$PATH to locate dynamic libraries and related data files."
+ echo
+ } | fmt
+ } > $(PACKAGEGEN)/$(name)-run.README
+ echo ";;;$(PACKAGEGEN)/$(name)-run.README;$(PACKAGELIB)/$(name)-run.README"
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ $(MAKE) --noexec $(-) --variants=$(variants:Q) $(=) package.strip=$(strip) recurse list.package.$(type) package.license.class=$(license:Q) cc-
+ done
+ } |
+ {
+ : > $tmp/HEAD
+ [[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
+ cat > $tmp/README <<'!'
+ $(package.readme)
+ !
+ echo ";;;$tmp/README;README"
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ --checksum=md5:$(PACKAGEGEN)/$(name)-run.sum \
+ --install=$(PACKAGEGEN)/$(name)-run.ins \
+ -wvf $(runtime) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ -s",^$tmp/,$(INSTALLOFFSET)/," \
+ $(PACKAGEROOT:C%.*%-s",^&/,,"%)
+ echo $(runtime) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ $(SUM) -x $(checksum) < $(runtime) > $(runtime:D:B:S=.$(checksum))
+ echo $(runtime:D:B:S=.$(checksum)) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ echo local > $(runtime:D:B=$(name)-run:S=.$(CC.HOSTTYPE).tim)
+ if [[ '$(incremental)' == 1 && '$(old.runtime)' ]]
+ then $(PAX) -rf $(runtime) -wvf $(old.new.runtime) -z $(old.runtime)
+ echo $(old.new.runtime) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ $(SUM) -x $(checksum) < $(old.new.runtime) > $(old.new.runtime:D:B:S=.$(checksum))
+ echo $(old.new.runtime:D:B:S=.$(checksum)) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ fi
+ rm -rf $tmp
+ fi
+
+list.installed list.manifest :
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ ignore $(MAKE) --noexec $(-) $(=) $(<)
+ done
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..a046f68
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1 @@
+:MAKE:
diff --git a/src/Mamfile b/src/Mamfile
new file mode 100644
index 0000000..013f5dd
--- /dev/null
+++ b/src/Mamfile
@@ -0,0 +1,7 @@
+info mam static
+note source level :MAKE: equivalent
+make install
+make all
+exec - ${MAMAKE} -r '*/*' ${MAMAKEARGS}
+done all virtual
+done install virtual
diff --git a/src/cmd/INIT/C+probe b/src/cmd/INIT/C+probe
new file mode 100644
index 0000000..f427742
--- /dev/null
+++ b/src/cmd/INIT/C+probe
@@ -0,0 +1,870 @@
+:
+### this script contains archaic constructs that work with all sh variants ###
+# Glenn Fowler
+# AT&T Research
+#
+# @(#)C probe (AT&T Research) 2012-02-29
+#
+# probe [ -d ] c-compiler-path [ attributes ]
+#
+# common C probe preamble for the tool specific probes
+#
+# NOTE: some cc -E's do syntax analysis!
+
+#
+# probe_* are first eval'd and then attempted from left to right
+#
+
+probe_binding="-dy -dn -Bdynamic -Bstatic '-Wl,-ashared -Wl,+s' -Wl,-aarchive -call_shared -non_shared -dynamic -static -bshared -bstatic '' -static"
+probe_env="CC_OPTIONS CCOPTS LD_OPTIONS LDOPTS LIBPATH LPATH"
+probe_include="stdio.h iostream.h complex.h ctype.h plot.h stdarg.h varargs.h ranlib.h hash.h sys/types.h stab.h cmath cstdio iostream string"
+probe_longlong="long 'long long'"
+probe_longlong_t="__int64_t _int64_t __int64 _int64 int64"
+probe_l="l yyreject m sin mopt sin"
+probe_lxx="C exit ++ exit g++ exit"
+probe_ppprefix="a n"
+probe_size="size"
+probe_src="cxx C cc c"
+probe_sa=".sa"
+probe_sd=".dll .lib .dll .x"
+probe_sdb=".pdb"
+probe_so=".dylib .so .sl"
+probe_symprefix="_"
+probe_verbose="'-v -v' '-# -#' '-d -d' -dryrun '-V -V'"
+probe_version="--version -V -version -v"
+
+#
+# the following are set by the preamble for the tool specific probe
+#
+
+cc=cc
+debug=
+dir=.
+dll=.dll
+dynamic=
+exe=exe
+executable="test -x"
+hosted=
+ifs=${IFS-'
+ '}
+obj=o
+ppenv=
+ppopt=
+predef=
+prepred=
+sa=
+sd=
+sdb=
+so=
+sov=
+static=
+stdlib=
+stdpp=
+suffix_command=
+if test "" != "$TMPDIR" -a -d "$TMPDIR"
+then tmpdir=$TMPDIR
+else tmpdir=/tmp
+fi
+tmpdir=$tmpdir/probe$$
+undef="define defined elif else endif error if ifdef ifndef include line pragma undef __STDC__ __STDPP__ __ARGC__ __BASE__ __BASE_FILE__ __DATE__ __FILE__ __FUNCTION__ __INCLUDE_LEVEL__ __LINE__ __PATH__ __TIME__ __TIMESTAMP__ __VERSION__"
+version_flags=
+version_stamp=
+version_string=
+
+#
+# constrain the environment
+#
+
+DISPLAY=
+LC_ALL=C
+export DISPLAY LC_ALL
+
+#
+# now the common probes
+#
+
+while :
+do case $1 in
+ -d) debug=1 ;;
+ -*) set ''; break ;;
+ *) break ;;
+ esac
+ shift
+done
+
+cc=$1
+case $cc in
+[\\/]*|[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:\\*)
+ ;;
+*) echo "Usage: $0 [ -d ] c-compiler-path [ attributes ]" >&2
+ exit 1
+ ;;
+esac
+ATTRIBUTES=
+eval $2
+_probe_PATH=$PATH
+PATH=/usr/bin:/bin:$PATH
+
+case $0 in
+*[\\/]*) dir=`echo $0 | sed -e 's,[\\/][\\/]*[^\\/]*\$,,'` ;;
+esac
+
+$executable . 2>/dev/null || executable='test -r'
+
+case $SHELL in
+[\\/]*|[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:\\*)
+ sh=$SHELL
+ ;;
+*) sh=/bin/sh
+ ;;
+esac
+
+trap 'code=$?; cd ..; rm -rf $tmpdir; exit $code' 0 1 2 3
+mkdir $tmpdir
+cd $tmpdir
+
+exec 3>&1 4>&2 </dev/null
+case $debug in
+"") exec >/dev/null 2>&1
+ (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0
+ ;;
+*) PS4='+$LINENO+ '
+ set -x
+ ;;
+esac
+
+if (xxx=xxx; unset xxx)
+then UNSET=1
+else UNSET=
+fi
+eval set x $probe_env
+while :
+do shift
+ case $# in
+ 0) break ;;
+ esac
+ eval x='$'$1
+ case $x in
+ '') continue ;;
+ esac
+ case $1 in
+ *PATH) _probe_export="$_probe_export $1='$x'" ;;
+ esac
+ case $UNSET in
+ '') eval $1=
+ export $1
+ ;;
+ *) unset $1
+ ;;
+ esac
+done
+
+if test -f "$dir/probe.ini"
+then . "$dir/probe.ini"
+ IFS=$ifs
+fi
+
+mkdir suffix
+cd suffix
+for src in $probe_src
+do echo "int main(){return 0;}" > ../test.$src
+ rm -f test*
+ if $cc -c ../test.$src
+ then set test.*
+ if test -f "$1"
+ then o="$*"
+ mv $* ..
+ for i in $o
+ do if $cc -o test.exe ../$i
+ then obj=`echo "$i" | sed -e 's,test.,,'`
+ $executable test.exe || executable="test -r"
+ set test*
+ rm *
+ if $cc -o test ../$i
+ then rm $*
+ set test.*
+ if $executable "$1"
+ then exe=`echo "$1" | sed -e 's,test.,,'`
+ suffix_command=.$exe
+ fi
+ fi
+ break 2
+ fi
+ done
+ fi
+ fi
+done
+cd ..
+
+case $src in
+c) ;;
+*) echo '// (
+int
+main()
+{
+ class { public: int i; } j;
+ j.i = 0;
+ int k = j.i + 1;
+ return k;
+}' > dialect.$src
+ if $cc -c dialect.$src && $cc -o dialect.$exe dialect.$obj && $executable dialect.$exe
+ then mv dialect.$src dialect.c
+ rm -f dialect.$obj dialect.$exe
+ if $cc -c dialect.c && $cc -o dialect.$exe dialect.$obj && $executable dialect.$exe
+ then src=c
+ else set x $cc
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ *=*) continue ;;
+ esac
+ case `echo $1 | sed -e 's,.*/,,'` in
+ *CC*|*++*|*[xX][xX]*|*[pP][lL][uU][sS]*) ;;
+ *) src=c ;;
+ esac
+ break
+ done
+ fi
+ else src=c
+ fi
+ ;;
+esac
+
+set x x '(' 1 'int x;' 0
+while :
+do shift
+ shift
+ case $# in
+ [01]) break ;;
+ esac
+ rm -f test.$obj
+ echo "$1" > test.$src
+ $cc -c test.$src
+ r=$?
+ case $r in
+ 0) test -f test.$obj || r=1 ;;
+ *) r=1 ;;
+ esac
+ case $2:$r in
+ 0:0) ;;
+ 0:1) echo "$cc: not a C compiler: failed to compile \`\`$1''" >&4
+ exit 1
+ ;;
+ 1:0) echo "$cc: not a C compiler: successfully compiled \`\`$1''" >&4
+ exit 1
+ ;;
+ esac
+done
+
+hosttype=`package CC="$cc" || $SHELL -c "package CC='$cc'"`
+case $hosttype in
+*[Uu][Ss][Aa][Gg][Ee]:*)
+ hosttype=`PATH=$_probe_PATH; export PATH; package CC="$cc" || $SHELL -c "package CC='$cc'"`
+ ;;
+esac
+
+echo '#include <stdio.h>
+int main(){printf("hello");return 0;}' > dynamic.$src
+echo 'extern int sfclose() { return 0; }' > fun.$src
+if $cc -c dynamic.$src && $cc -c fun.$src
+then eval set x $probe_so
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ for i in foo junk
+ do rm -f dynamic.$exe
+ if $cc -L. -o dynamic.$exe dynamic.$obj -l$i
+ then : "there's really a -l$i"?
+ else rm -f dynamic.$exe
+ cat fun.$obj > lib$i$1
+ $cc -L. -o dynamic.$exe dynamic.$obj -l$i && $executable dynamic.$exe
+ x=$?
+ rm lib$i$1
+ case $x in
+ 0) so=$1
+ rm -f dynamic.$exe > lib$i$1.1
+ $cc -L. -o dynamic.$exe dynamic.$obj -l$i && $executable dynamic.$exe
+ x=$?
+ rm lib$i$1.1
+ case $x in
+ 0) sov=1 ;;
+ esac
+ break 2
+ ;;
+ *) break
+ ;;
+ esac
+ fi
+ done
+ k=
+ for i in "" .1 .2 .3 .4 .5 .6 .7 .8 .9
+ do rm -f dynamic.$exe > libc$1$i
+ $cc -L. -o dynamic.$exe dynamic.$obj && $executable dynamic.$exe
+ x=$?
+ (cd ..; rm $tmpdir/libc$1$i)
+ case $x in
+ 0) ;;
+ *) k=X$k
+ case $k in
+ XXX) break ;;
+ esac
+ ;;
+ esac
+ done
+ case $k in
+ XXX) so=$1
+ sov=1
+ break
+ ;;
+ ?*) so=$1
+ break
+ ;;
+ esac
+ done
+ rm -f dynamic.$exe
+ if $cc -o dynamic.$exe dynamic.$obj 2>e && $executable dynamic.$exe
+ then e=`wc -l e`
+ maybe=
+ eval set x x $probe_binding
+ while :
+ do shift
+ shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f dynamic.$exe
+ $cc -o dynamic.$exe $1 dynamic.$obj 2>e && $executable dynamic.$exe || continue
+ case $1 in
+ ?*) case $maybe in
+ "") maybe=$1 ;;
+ *) maybe=-- ;;
+ esac
+ ;;
+ esac
+ case `wc -l e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ d=`ls -s dynamic.$exe`
+ rm -f dynamic.$exe
+ $cc -o dynamic.$exe $2 dynamic.$obj 2>e && $executable dynamic.$exe || continue
+ case `wc -l e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ case `ls -s dynamic.$exe` in
+ $d) ;;
+ *) dynamic=$1
+ static=$2
+ maybe=
+ break
+ ;;
+ esac
+ done
+ case $maybe in
+ ""|--) ;;
+ *) rm -f dynamic.$exe
+ if $cc -o dynamic.$exe $maybe dynamic.$obj 2>e && $executable dynamic.$exe
+ then e=`wc -l e`
+ if $cc -o dynamic.$exe $maybe-bogus-bogus-bogus dynamic.$obj 2>e && $executable dynamic.$exe
+ then case `wc -l e` in
+ $e) ;;
+ *) dynamic=$maybe ;;
+ esac
+ else dynamic=$maybe
+ fi
+ fi
+ ;;
+ esac
+ fi
+fi
+
+eval set x $probe_version
+shift
+for o in "$@"
+do if $cc $o > version.out 2>&1
+ then version_string=`sed -e '/ is /d' -e 's/;/ /g' version.out | sed -e 1q`
+ case $version_string in
+ ''|*[Ee][Rr][Rr][Oo][Rr]*|*[Ff][Aa][Tt][Aa][Ll]*|*[Ww][Aa][Rr][Nn][Ii][Nn][Gg]*|*[Oo][Pp][Tt][Ii][Oo][Nn]*)
+ ;;
+ *) version_flags=$o
+ version_stamp=";VERSION;$o;$version_string;PATH;$cc"
+ break
+ ;;
+ esac
+ fi
+done
+case $version_stamp in
+'') eval set x $probe_version
+ shift
+ echo 'int main() { return 0; }' > version.i
+ for o in "$@"
+ do if $cc -c $o version.i > version.out 2>&1
+ then version_string=`sed -e '/ is /d' -e 's/;/ /g' version.out | sed -e 1q`
+ case $version_string in
+ ''|*[Ee][Rr][Rr][Oo][Rr]*|*[Ff][Aa][Tt][Aa][Ll]*|*[Ww][Aa][Rr][Nn][Ii][Nn][Gg]*|*[Oo][Pp][Tt][Ii][Oo][Nn]*)
+ ;;
+ *) version_flags=$o
+ break
+ ;;
+ esac
+ fi
+ done
+ ;;
+esac
+
+echo 'int main(){return 0;}' > hosted.$src
+$cc -o hosted.$exe hosted.$src && ./hosted.$exe && hosted=1
+
+echo '#!'$sh'
+echo "" $@' > cpp
+chmod +x cpp
+case `./cpp -Dprobe` in
+*-Dprobe*)
+ ;;
+*) cp /bin/echo cpp
+ chmod u+w cpp
+ ;;
+esac
+for prefix in $probe_ppprefix `echo $cc | sed -e '/cc\$/!d' -e 's,cc\$,,' -e 's,.*/,,'`
+do cp cpp ${prefix}cpp
+done
+
+echo "" > flags.$src
+echo '#pragma pp:version' > libpp.$src
+
+if test `realcppC=./cpp $cc -Dprobe -E flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppenv='realcppC=${ppcmd}'
+elif test `cppC=./cpp $cc -Dprobe -E flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppenv='cppC=${ppcmd}'
+elif test `_CPPNAME=./cpp $cc -Dprobe -E flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppenv='_CPPNAME=${ppcmd}'
+elif test `_CPP=./cpp $cc -Dprobe -E flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppenv='_CPP=${ppcmd}'
+elif test `$cc -Dprobe -E -%p+. flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 && test `$cc -Dprobe -E -%p+. flags.$src | wc -l` -eq 1
+then ppopt='-%p+${ppdir}'
+elif test `$cc -Dprobe -E -Yp,. flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppopt='-Yp,${ppdir}'
+elif test `$cc -Dprobe -E -Qpath $tmpdir flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppopt='-Qpath ${ppdir}'
+elif test `$cc -Dprobe -E -tp -B./ flags.$src 2>err.out | tee cpp.out | grep -c '[-]Dprobe'` -eq 1 -a ! -s err.out
+then ppopt='-tp -B${ppdir}/'
+elif test `$cc -Dprobe -E -B./ flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppopt='-B${ppdir}/'
+elif test `$cc -Dprobe -E -tp -h./ -B flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppopt='-tp -h${ppdir}/ -B'
+elif test `$cc -Dprobe -E -t p,./cpp flags.$src | tee cpp.out | grep -c '[-]Dprobe'` -eq 1
+then ppopt='-t p,${ppcmd}'
+else {
+ eval set x $probe_verbose
+ shift
+ for o in "$@"
+ do $cc -E $o flags.$src
+ done
+ } 2>&1 | sed -e "s/['\"]//g" > cpp.out
+fi
+
+set x `sed -e 's,[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:\\\\,/,g' -e 's,\\\\,/,g' cpp.out`
+def=
+definclude="-I+C -I-H"
+stdinclude=$definclude
+case $hosted in
+"") usrinclude= ;;
+esac
+cmdinclude=
+while :
+do case $# in
+ 0|1) break ;;
+ esac
+ shift
+ case $1 in
+ -A) case $2 in
+ *\(*\)) shift
+ prepred="$prepred `echo $1 | sed 's/\(.*\)(\(.*\))/\1 \2/'`"
+ ;;
+ esac
+ ;;
+ -A\(*\))
+ prepred="$prepred `echo $1 | sed 's/-A\(.*\)(\(.*\))/\1 \2/'`"
+ ;;
+ -[DI][-+][ABCDEFGHIJKLMNOPQRSTUVWXYZ]*)
+ stdpp=1
+ case $1 in
+ -I?[CH]) case $def in
+ ?*) definclude="$definclude $1" ;;
+ *) stdinclude="$stdinclude $1" ;;
+ esac
+ ;;
+ -I-S*|-YI,*) usrinclude="`echo $1 | sed 's/....//'`" ;;
+ -Y?,*) ;;
+ -Y*) usrinclude="`echo $1 | sed 's/..//'`" ;;
+ esac
+ ;;
+ -D) shift
+ case $1 in
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*=*)
+ predef="$predef
+`echo $1 | sed -e 's/=.*//'`"
+ ;;
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*)
+ predef="$predef
+$1"
+ ;;
+ esac
+ ;;
+ -Dprobe);;
+ -D*) case $1 in
+ -D[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*=*)
+ predef="$predef
+`echo $1 | sed -e 's/^-D//' -e 's/=.*//'`"
+ ;;
+ -D[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*)
+ predef="$predef
+`echo $1 | sed -e 's/^-D//'`"
+ ;;
+ esac
+ ;;
+ -I) shift
+ case $1 in
+ /*) case $def in
+ ?*) definclude="$definclude $1" ;;
+ *) stdinclude="$stdinclude $1" ;;
+ esac
+ cmdinclude="$cmdinclude $1"
+ ;;
+ esac
+ ;;
+ -I/*) f=`echo X$1 | sed 's/X-I//'`
+ case $def in
+ ?*) definclude="$definclude $f" ;;
+ *) stdinclude="$stdinclude $f" ;;
+ esac
+ cmdinclude="$cmdinclude $f"
+ ;;
+ -U) shift
+ undef="$undef $1"
+ ;;
+ -U*) undef="$undef `echo $1 | sed 's/^-U//'`"
+ ;;
+ flags.$src)def=
+ ;;
+ esac
+done
+stdinclude="$stdinclude $definclude"
+case " $stdinclude " in
+*\ $usrinclude\ *)
+ case $usrinclude in
+ /usr/include)
+ usrinclude=
+ ;;
+ *) case " $stdinclude " in
+ *\ /usr/include\ *)
+ usrinclude=
+ ;;
+ *) usrinclude=/usr/include
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+
+tstinclude=`$cc -v -E flags.$src 2>&1 | sed -e '1,/[iI][nN][cC][lL][uU][dD][eE][ ]*<[.][.][.]>/d' -e '/^[eE][nN][dD] [oO][fF] [sS][eE][aA][rR][cC][hH]/,\$d'`
+j=$tstinclude
+case $j in
+*/*) ;;
+*) j=$cmdinclude ;;
+esac
+tstinclude=
+good=
+nogood=
+c_hdr="stdio.h ctype.h"
+C_hdr="libc.h"
+for i in $j
+do if test -d "$i"
+ then tstinclude="$tstinclude $i"
+ h=
+ for f in $c_hdr
+ do if test -f "$i/$f"
+ then case $i in
+ */CC) nogood=1 ;;
+ *) good=1 ;;
+ esac
+ else h="$h $f"
+ fi
+ done
+ c_hdr=$h
+ h=
+ for f in $C_hdr
+ do if test -f "$i/$f"
+ then case $i in
+ */CC) nogood=1 ;;
+ *) good=1 ;;
+ esac
+ else h="$h $f"
+ fi
+ done
+ C_hdr=$h
+ fi
+done
+case $nogood in
+1) good=0 ;;
+esac
+case $good in
+1) case $c_hdr in
+ ?*) bad=1
+ usrinclude=/usr/include
+ set '' $tstinclude /usr/include
+ ;;
+ *) set '' $tstinclude
+ ;;
+ esac
+ shift
+ stdinclude=$*
+ echo "#include <sys/types.h>" > include.$src
+ $cc -E include.$src | sed -e '/# 1 "[\\/]/!d' -e 's,[^"]*",,' -e 's,[\\/][^\\/]*".*,,' -e 's,[\\/]sys,,' > include.out
+ for f in `cat include.out`
+ do if test -d "$f"
+ then g=`echo $f | sed -e 's,[\\/][\\/]*[^\\/]*$,,'`
+ case " $stdinclude " in
+ *\ $f\ *|*\ $g\ *)
+ ;;
+ *) stdinclude="$stdinclude $f"
+ case $f in
+ /usr/include) usrinclude=$f ;;
+ esac
+ bad=1
+ ;;
+ esac
+ fi
+ done
+ ;;
+*) case $ppopt$ppenv in
+ ?*) echo '#!'$sh'
+ echo $VIRTUAL_ROOT | sed "s/:.*//"' > cpp
+ chmod +x cpp
+ ppcmd=cpp
+ ppdir=.
+ eval x='`'$ppenv '$'cc -E $ppopt flags.$src'`'
+ case $x in
+ ?*) tstinclude=$x/usr/include
+ ;;
+ esac
+ cp /bin/echo cpp
+ chmod u+w cpp
+ ;;
+ esac
+
+ eval set x $probe_include
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ echo "#include <$1>" > include.$src
+ $cc -E include.$src
+ done > include.out
+
+ ccinclude=
+ x=$stdinclude
+ stdinclude=
+ subinclude=
+ for f in $x $tstinclude `sed -e 's,\\\\,/,g' -e 's,///*,/,g' -e 's,"[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:/,"/,g' -e '/^#[line ]*[0123456789][0123456789]*[ ][ ]*"[\\/]/!d' -e 's/^#[line ]*[0123456789][0123456789]*[ ][ ]*"\(.*\)[\\/].*".*/\1/' include.out | sort -u`
+ do case $f in
+ -*) ;;
+ */) f=`echo $f | sed -e 's,//*\$,,'` ;;
+ */.) f=`echo $f | sed -e 's,//*.\$,,'` ;;
+ esac
+ case $f in
+ -I*) ;;
+ */cc) ccinclude=1
+ ;;
+ */sys) continue
+ ;;
+ */include/*/*)
+ ;;
+ */include/*)
+ subinclude="$subinclude $f"
+ continue
+ ;;
+ esac
+ if test -d "$f"
+ then case " $stdinclude " in
+ *\ $f\ *) ;;
+ *) stdinclude="$stdinclude $f" ;;
+ esac
+ fi
+ done
+ rm include.out
+ case $ccinclude in
+ ?*) eval set x $probe_include
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ echo "#include <cc/$1>" > include.$src
+ if $cc -E include.$src > /dev/null
+ then break
+ fi
+ done
+ case $# in
+ 0) ;;
+ *) x=$stdinclude
+ stdinclude=
+ for f in $x
+ do case $f in
+ */cc) ;;
+ *) stdinclude="$stdinclude $f" ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ esac
+ case $subinclude in
+ ?*) for i in $subinclude
+ do for j in $stdinclude
+ do case $i in
+ $j/*/*) ;;
+ $j/*) both=
+ eval set x $probe_include
+ while :
+ do shift
+ case $# in
+ 0) for k in $both
+ do echo "#include <$k>" > include.$src
+ $cc -E include.$src > include.out
+ I=`grep -c $i/$k < include.out`
+ J=`grep -c $j/$k < include.out`
+ case $I:$J in
+ 0:*) ;;
+ *:0) stdinclude="$i $stdinclude"
+ break
+ ;;
+ esac
+ done
+ continue 3
+ ;;
+ esac
+ if test -f $i/$1
+ then if test ! -f $j/$1
+ then break 2
+ fi
+ both="$both $1"
+ fi
+ done
+ ;;
+ $j) continue 2
+ ;;
+ esac
+ done
+ stdinclude="$i $stdinclude"
+ done
+ ;;
+ esac
+
+ {
+
+ for i in $stdinclude
+ do
+ case $i in
+ $usrinclude) ;;
+ *) echo $i $i ;;
+ esac
+ done
+
+ eval set x $probe_include
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ echo "#include <$1>" > t.c
+ p=
+ for j in `$cc -E t.c | grep "$1" | sed -e 's,\\\\,/,g' -e 's,"[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:/,"/,g' -e '/^#[line ]*1[ ][ ]*"[\\/]/!d' -e 's/^#[line ]*1[ ][ ]*"\(.*\)[\\/].*".*/\1/'`
+ do j=`echo $j | sed -e 's,///*,/,g' -e 's,/$,,'`
+ case $p in
+ ?*) echo $p $j ;;
+ esac
+ p=$j
+ done
+ done
+
+ case $usrinclude in
+ ?*) echo $usrinclude $usrinclude ;;
+ esac
+
+ } | tsort > tmp.tmp
+ tstinclude=`cat tmp.tmp`
+ bad=
+ for i in $stdinclude
+ do case "
+$tstinclude
+" in
+ *"
+$i
+"*) ;;
+ *) bad=1
+ break
+ ;;
+ esac
+ done
+ ;;
+esac
+
+case $bad in
+"") x=$stdinclude
+ stdinclude=
+ z=
+ for i in $tstinclude
+ do case " $x " in
+ *" $i "*)
+ stdinclude="$stdinclude $i"
+ z=$i
+ ;;
+ esac
+ done
+ case $usrinclude in
+ '') usrinclude=$z ;;
+ esac
+ ;;
+esac
+case $hosted in
+"") case $usrinclude in
+ /usr/include) usrinclude= ;;
+ esac
+ ;;
+esac
+
+case $usrinclude in
+?*) case " $stdinclude " in
+ *\ $usrinclude\ *)
+ x=$stdinclude
+ stdinclude=
+ for f in $x
+ do case $f in
+ $usrinclude) ;;
+ *) stdinclude="$stdinclude $f" ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+esac
+
+# drop dups -- they creep in somehow
+
+x=$stdinclude
+stdinclude=
+for f in $x
+do case " $stdinclude $usrinclude " in
+ *" $f "*) ;;
+ *) stdinclude="$stdinclude $f" ;;
+ esac
+done
diff --git a/src/cmd/INIT/CONVERT.mk b/src/cmd/INIT/CONVERT.mk
new file mode 100644
index 0000000..63a60ef
--- /dev/null
+++ b/src/cmd/INIT/CONVERT.mk
@@ -0,0 +1,260 @@
+/*
+ * {automake|configure} => {nmake|iffe} conversion support
+ *
+ * The first command line target overrides the default original source
+ * directory name $(MAKEFILE:D). The hard work is in the makefile using
+ * these assertions, since it must (manually) provide the nmake makefiles
+ * and config equivalent iffe scripts. The conversion makefile is typically
+ * named lib/package/PACKAGE.cvt in an ast package $PACKAGEROOT directory,
+ * and the conversion is run from the $PACKAGEROOT directory, e.g.:
+ *
+ * nmake -I lib/package -f PACKAGE-VERSION/PACKAGE.cvt
+ *
+ * The conversion requires the ast nmake, pax and tw commands.
+ *
+ * After the conversion you will be liberated from ./configure, *.in,
+ * *.am, automake, autom4te, libtool, make depend, and makefile
+ * recursion ordering. You can build from $PACKAGEROOT using the ast
+ * package(1) (which sets up the { HOSTTYPE PATH VPATH } environment):
+ *
+ * package make
+ *
+ * or cd into any arch/$HOSTTYPE/src subdirectory and rebuild that portion
+ * of the hierarchy with the ast nmake(1) (after setting PATH and VPATH):
+ *
+ * nmake
+ *
+ * The conversion assertions are:
+ *
+ * package :CONVERT: file ...
+ *
+ * files in the original source directory are copied
+ * and converted into the ./src and ./lib subdirectories
+ * the default original source directory is ./original
+ *
+ * package package name
+ * file original source file that must exist
+ *
+ * :OMIT: pattern
+ *
+ * files matching pattern are not copied into the converted
+ * directory
+ *
+ * pattern ksh pattern of files to omit
+ *
+ * :COPY: from to [ file ... ]
+ *
+ * files in the from directory are copied to the to directory
+ * the action may contain :MOVE: exceptions to the copy
+ *
+ * from original directory subdirectory
+ * . names the original directory
+ * .. names the
+ * to converted subdirectory
+ * libNAME => src/lib/libNAME
+ * NAME => src/cmd/NAME
+ * file files or files in subdirectories to be copied;
+ * explicit files are copied to the to directory;
+ * if no files are specified then the from hierarchy
+ * is recursively copied to the converted directory
+ *
+ * :MOVE: to file ...
+ *
+ * :COPY: assertion exceptions placed in the assertion's action
+ *
+ * to files or subdirectory files are copied to this directory
+ * file file or files in subdirectories to be copied
+ *
+ * :FILE: to file <<!
+ * contents
+ * !
+ *
+ * the :FILE: action is copied to the named file in the to directory
+ * the :FILE: action is usually specified using the here syntax to
+ * avoid make comment, quote and variable expansion
+ *
+ * :EDIT: to file ... | - pattern <<!
+ * edit script
+ * !
+ *
+ * the :EDIT: action is an ed(1) script applied to each file in the
+ * to directory after it has been copied from the original source
+ * directory; if to is - then the :EDIT: action is a sed(1) script
+ * that is applied to all files matching the file pattern during the
+ * copy from the original source directory; a file may be subject to
+ * both a sed(1) and ed(1) :EDIT:; the :EDIT: action is usually
+ * specified using the here syntax to avoid make comment, quote and
+ * variable expansion
+ */
+
+.CONVERT.ID. = "@(#)$Id: CONVERT (AT&T Research) 2004-03-19 $"
+
+set nojobs noscan nowriteobject writestate=$$(MAKEFILE).ms
+
+package = $(PWD:B)
+here = !-=-=-=-=-!
+hierarchy = src src/cmd src/lib
+omit = .*|*.?(l)[ao]
+original = $(MAKEFILE:D)
+showedit = $(-debug:?p??)
+
+CPFLAGS = -u
+PAXFLAGS = -u -v
+STDEDFLAGS = -
+TW = tw
+TWFLAGS = -CP
+
+all : .VIRTUAL file
+file : .VIRTUAL edit
+edit : .VIRTUAL copy
+copy : .VIRTUAL init
+init : .VIRTUAL
+
+.MAKEINIT : .cvt.init
+
+.cvt.init : .MAKE .VIRTUAL .FORCE
+ local D
+ if D = "$(~.ARGS:O=1)"
+ if "$(D:T>FD)"
+ original := $(D)
+ .ARGS : .CLEAR $(~.ARGS:O>1)
+ end
+ end
+
+.cvt.filter =
+.cvt.package =
+
+.cvt.atom : .FUNCTION
+ local N V
+ V := $(%:O=1)
+ let .cvt.$(V) = .cvt.$(V) + 1
+ return .cvt.$(V).$(.cvt.$(V))
+
+.cvt.omit : .FUNCTION
+ return -s',^\(\(?K)?(*/)($(omit))?(/*))$,,$(showedit)'
+
+.cvt.to : .FUNCTION
+ if "$(%)" == "."
+ return src
+ end
+ if "$(%)" == "*/*"
+ return src/$(%)
+ end
+ if "$(%)" == "lib*"
+ return src/lib/$(%)
+ end
+ return src/cmd/$(%)
+
+":CONVERT:" : .MAKE .OPERATOR
+ local I
+ package := $(<)
+ I := $(hierarchy:C,$,/Makefile)
+ init : .cvt.verify $(I)
+ $(I) : .ACCEPT
+ test -d $(<:D) || $(MKDIR) -p $(<:D)
+ echo :MAKE: > $(<)
+ .cvt.verify : .MAKE .FORCE .REPEAT
+ local I
+ if I = "$(.cvt.package:T!=F)"
+ error 3 $(original): not a $(package) source directory: missing $(I)
+ end
+ .cvt.package := $(>:C,^,$$(original)/,)
+
+":COPY:" : .MAKE .OPERATOR
+ local F T I A
+ F := $(>:O=1)
+ T := $(.cvt.to $(>:O=2))
+ A := $(.cvt.atom copy)
+ copy : $(A)
+ $(A) : .VIRTUAL
+ if F == "."
+ $(A) : $(T)
+ $(T) :
+ test -d $(<) || $(MKDIR) -p $(<)
+ for I $(>:O>2)
+ eval
+ $$(A) : $(I:D=$(T):B:S)
+ $(I:D=$(T):B:S) : $$(original)/$(I)
+ $$(CP) $$(CPFLAGS) $$(*) $$(<)
+ end
+ end
+ elif "$(F:T=FF)" || "$(F:N=*.(pax|t[bg]z))"
+ eval
+ $$(A) : $$(F)
+ test -d $(T) || $$(MKDIR) -p $(T)
+ cd $(T)
+ $$(PAX) $$(PAXFLAGS) -rf $$(*:P=A) -s ',^$(>:O=2)/*,,' $(.cvt.omit) $(.cvt.filter)
+ end
+ else
+ F := $$(original)/$(F)
+ if ! "$(@:V)"
+ eval
+ $$(A) : .FORCE
+ test -d $(T) || $$(MKDIR) -p $(T)
+ cd $(F:V)
+ $$(TW) $$(TWFLAGS) | $$(PAX) $$(PAXFLAGS) -rw $(.cvt.omit) $(.cvt.filter) $(T:P=A)
+ end
+ else
+ .cvt.move =
+ : $(@:V:@R)
+ eval
+ $$(A) : .FORCE
+ test -d $(T) || $$(MKDIR) -p $(T)
+ cd $(F:V)
+ $$(TW) $$(TWFLAGS) | $$(PAX) $$(PAXFLAGS) -rw $(.cvt.omit) $(.cvt.move) $(.cvt.filter) $(T:P=A)
+ end
+ end
+ end
+
+":EDIT:" : .MAKE .OPERATOR
+ local A D F
+ D := $(>:O=1)
+ if D == "-"
+ A := ^$(>:O=2)^$$(SED) -e $(@:Q:/'\n'/ -e /G)
+ .cvt.filter += --action=$(A:@Q)
+ else
+ D := $(.cvt.to $(D))
+ F := $(>:O>1:C,^,$(D)/,)
+ edit : $(F)
+ eval
+ $$(F) :
+ $$(STDED) $$(STDEDFLAGS) $$(<) <<'$(here)'
+ $(@:V)
+ w
+ q
+ $(here)
+ end
+ end
+
+":FILE:" : .MAKE .OPERATOR
+ local ( D F ) $(>)
+ local A
+ A := $(.cvt.atom file)
+ $(A) := $(@:V)
+ D := $(.cvt.to $(D))
+ file : $(D)/$(F)
+ eval
+ $$(D)/$$(F) :
+ test -d $$(<:D) || $$(MKDIR) -p $$(<:D)
+ cat > $$(<) <<'$(here)'
+ $$($(A):V)
+ $(here)
+ end
+
+":MOVE:" : .MAKE .OPERATOR
+ local T I
+ T := ../../../$(.cvt.to $(>:O=1))
+ for I $(>:O>1)
+ if I == "*/"
+ .cvt.move += -s',^\(\(?K)$(I)),$(T)/,$(showedit)'
+ .cvt.move += -s',^\(\(?K)$(I:C%/$%%))$,,$(showedit)'
+ else
+ .cvt.move += -s',^\(\(?K)$(I))$,$(T)/$(I:B:S),$(showedit)'
+ end
+ end
+
+":OMIT:" : .MAKE .OPERATOR
+ local P
+ for P $(>)
+ omit := $(omit)|$(P)
+ end
diff --git a/src/cmd/INIT/MAPLIB.mk b/src/cmd/INIT/MAPLIB.mk
new file mode 100644
index 0000000..5761035
--- /dev/null
+++ b/src/cmd/INIT/MAPLIB.mk
@@ -0,0 +1,45 @@
+/*
+ * normalize local -l* library conventions
+ *
+ * L [ [ G11 ... G1n ] ... [ Gg1 ... Ggn ] ] :MAPLIB: T1.c ... Tn.c
+ *
+ * if Giji not specified then G11 == L
+ * the first Ti.c that compiles/links with group -lGi1 ... -lGin
+ * but does not compile/link with no libraries maps
+ * -lL to to require -lGi1 ... -lGin
+ * otherwise -lL is not required and maps to "no library required"
+ */
+
+":MAPLIB:" : .MAKE .OPERATOR
+ local L P
+ L := $(<:B:O=1)
+ if ! ( P = "$(<:B:O>1)" )
+ P := $(L)
+ end
+ $(LIBDIR)/lib/$(L) :INSTALL: $(L).req
+ eval
+ $(L).req : (CC) $$(>)
+ set -
+ r='-'
+ for i in $$(*)
+ do if $$(CC) -c $i > /dev/null
+ then g=
+ for p in $(P) -
+ do case $p in
+ -) if $$(CC) -o $$(<:B:S=.exe) $i $g > /dev/null 2>&1
+ then $$(CC) -o $$(<:B:S=.exe) $i > /dev/null 2>&1 || {
+ r="$g"
+ break 2
+ }
+ fi
+ g=
+ ;;
+ *) g="$g -l$p"
+ ;;
+ esac
+ done
+ fi
+ done 2>/dev/null
+ echo " $r" > $$(<)
+ rm -f $$(<:B:S=.exe) $$(*:B:S=$$(CC.SUFFIX.OBJECT))
+ end
diff --git a/src/cmd/INIT/MSGFUN.mk b/src/cmd/INIT/MSGFUN.mk
new file mode 100644
index 0000000..0888d00
--- /dev/null
+++ b/src/cmd/INIT/MSGFUN.mk
@@ -0,0 +1,2 @@
+/* stub for pre-2000-05-01 nmake */
+":MSGFUN:" : .MAKE .OPERATOR
diff --git a/src/cmd/INIT/MSGKEY.mk b/src/cmd/INIT/MSGKEY.mk
new file mode 100644
index 0000000..db18559
--- /dev/null
+++ b/src/cmd/INIT/MSGKEY.mk
@@ -0,0 +1,2 @@
+/* stub for pre-2000-05-01 nmake */
+":MSGKEY:" : .MAKE .OPERATOR
diff --git a/src/cmd/INIT/Makefile b/src/cmd/INIT/Makefile
new file mode 100644
index 0000000..b1af6aa
--- /dev/null
+++ b/src/cmd/INIT/Makefile
@@ -0,0 +1,293 @@
+/*
+ * initialization for all packages
+ */
+
+:PACKAGE: license=ast
+
+LICENSE = since=1994,author=gsf
+
+PACKAGEROOT = $(INSTALLROOT:T=F:P=L*:O=n)
+
+hurl :: hurl.sh LICENSE=since=2003,author=gsf
+
+iffe :: iffe.sh LICENSE=since=1994,author=gsf+kpv
+
+mktest :: mktest.sh LICENSE=since=2005,author=gsf
+
+package :: package.sh
+
+regress :: regress.sh LICENSE=since=1995,author=gsf
+
+rt :: rt.sh LICENSE=since=2005,author=gsf
+
+$(PACKAGEROOT)/bin :INSTALLDIR: execrate ignore mamprobe package silent
+
+crossexec :: crossexec.sh
+
+ditto :: ditto.sh LICENSE=since=2001,author=gsf+ek
+
+execrate :: execrate.sh LICENSE=since=2002,author=gsf
+
+filter :: filter.sh
+
+ignore :: ignore.sh
+
+silent :: silent.sh
+
+$(PACKAGEROOT)/lib/package :INSTALLDIR: package.mk CONVERT.mk
+
+$(LIBDIR)/make :INSTALLDIR: package.mk PROBE.mk TEST.mk WWW.mk \
+ MSGFUN.mk MSGKEY.mk MAPLIB.mk
+
+:TEST: iffe mamake
+
+cc ld ldd :PACKAGE_INIT: mamake.c proto.c ratz.c release.c
+
+:: RELEASE hosttype.tst p.c hello.c \
+ ar.ibm.risc \
+ cc.specialize cc.pentium4 \
+ ldd.cygwin.i386 \
+ cc.darwin.i386 cc.darwin.i386-64 cc.darwin ldd.darwin \
+ cc.hp.ia64 cc.hp.pa cc.hp.pa64 ld.hp.pa ldd.hp.pa \
+ cc.ibm.risc cc.ibm.risc.gcc ldd.ibm.risc \
+ cc.linux.ia64-icc cc.linux.i386-icc cc.linux.i386-64-icc \
+ cc.lynxos.i386 cc.lynxos.ppc ldd.lynxos \
+ cc.mvs.390 cc.next.i386 cc.next.m68k ldd.mvs.390 \
+ cc.osf.alpha \
+ cc.sco.i386 \
+ cc.sgi.mips2 cc.sgi.mips3 cc.sgi.mips3-o32 cc.sgi.mips4 \
+ cc.sgi.mips4-n32 ldd.sgi \
+ cc.unix.mc68k
+
+LICENSE : .DONTCARE
+
+if ! CC.HOSTTYPE
+ CC.HOSTTYPE := $(_hosttype_|HOSTTYPE)
+end
+
+$(BINDIR)/mkdir :INSTALL: mkdir.sh
+ if test ! -x $(<) -a -x /bin/mkdir
+ then mkdir -p 2>/dev/null || :
+ if test -d ./-p
+ then rmdir ./-p
+ cp $(*) $(<)
+ chmod +x $(<)
+ fi
+ fi
+
+/*
+ * ksh93 function search on PATH
+ * ksh93 builtin command library -lcmd
+ * ksh93 ld library path search on PATH
+ */
+
+$(BINDIR)/.paths :INSTALL: (CC.DIALECT)
+ if test ! -f $(<) -o -w $(<)
+ then nl="
+"
+ o=`cat $(<) 2>/dev/null` || :
+ v=
+ n=
+ case $nl$o in
+ *${nl}FPATH=*|*#FPATH=*|*[Nn][Oo]FPATH=*)
+ ;;
+ *) case $n in
+ '') ;;
+ *) n="$n$nl" v="$v|" ;;
+ esac
+ n="${n}FPATH=../fun"
+ v="${v}FPATH"
+ ;;
+ esac
+ case $nl$o in
+ *${nl}BUILTIN_LIB=*|*#BUILTIN_LIB=*|*[Nn][Oo]BUILTIN_LIB=*)
+ ;;
+ *) case $n in
+ '') ;;
+ *) n="$n$nl" v="$v|" ;;
+ esac
+ case '$(CC.DIALECT:N=*EXPORT=[AD]LL*)' in
+ ?*) p= c= ;;
+ *) p='XX' ;;
+ esac
+ n="${n}${p}BUILTIN_LIB=cmd"
+ v="${v}BUILTIN_LIB"
+ ;;
+ esac
+ set x x : $(-mam:??$(.GETCONF LIBPATH:/:/ /G:/,/ : /G:Q)?)
+ p=
+ while :
+ do while :
+ do case $# in
+ 0) break ;;
+ esac
+ x=$1
+ shift
+ case $x in
+ :) break ;;
+ esac
+ done
+ case $# in
+ 0|1) break
+ ;;
+ 2) p=$2
+ ;;
+ *) case "$(CC.HOSTTYPE)" in
+ $3) p=$2; break ;;
+ esac
+ ;;
+ esac
+ done
+ case $p in
+ '') if test -x /lib/dld.sl
+ then p=SHLIB_PATH
+ elif test -x /usr/lib/dyld
+ then p=DYLD_LIBRARY_PATH
+ else case "$(CC.HOSTTYPE)" in
+ ibm.*|mvs.*)
+ p=LIBPATH
+ ;;
+ sgi.mips3)
+ p=LD_LIBRARYN32_PATH
+ ;;
+ sgi.mips4)
+ p=LD_LIBRARYN64_PATH
+ ;;
+ *) p=LD_LIBRARY_PATH
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ case $nl$o in
+ *${nl}${p}=*|*#${p}=*|*[Nn][Oo]${p}=*)
+ ;;
+ *) case $n in
+ '') ;;
+ *) n="$n$nl" v="$v|" ;;
+ esac
+ n="${n}${p}=../lib"
+ v="${v}${p}"
+ ;;
+ esac
+ case $n in
+ ?*) case $o in
+ ?*) o=`egrep -v "($v)=" $(<)`$nl ;;
+ esac
+ echo "# use { # no NO } prefix instead of XX to permanently disable #$nl$o$n" > $(<)
+ ;;
+ esac
+ fi
+
+/*
+ * probe initialization
+ */
+
+for T C+probe C+make+probe.lcl C+pp+probe.lcl
+ if T == "*.lcl"
+ $(T) : .DONTCARE
+ end
+ $(LIBDIR)/probe/$(T:C,+,/,G) :INSTALL: $(T)
+end
+
+$(LIBDIR)/probe/C/mam/probe :INSTALL: mprobe
+
+mprobe :: mprobe.sh
+
+$(LIBDIR)/probe/C/make :INSTALLDIR: probe probe.ini
+
+probe.sh : C+probe make.probe
+ cat $(*) > $(<)
+
+probe :: probe.sh
+
+probe.ini : (CC.HOSTTYPE) probe.win32
+ t=$(CC.HOSTTYPE)
+ ifs=$IFS
+ IFS=.
+ set x $t
+ IFS=$ifs
+ t=$2
+ set x $(*)
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ *probe.$t)
+ break
+ esac
+ done
+ case $1 in
+ ?*) cmp -s $1 $(<) || cp $1 $(<) ;;
+ *) : > $(<)
+ esac
+
+/*
+ * proto initialization
+ */
+
+$(INCLUDEDIR) :INSTALLDIR: prototyped.h
+
+prototyped.h : $(BINDIR)/proto
+ proto -f /dev/null > h.$(tmp).h
+ if $(CMP) -s h.$(tmp).h $(<)
+ then $(RM) -f h.$(tmp).h
+ else $(MV) h.$(tmp).h $(<)
+ fi
+
+/*
+ * check if -ldl is required
+ * this allows makefiles to use -ldl on all systems
+ *
+ * NOTE: this works around the sgi botch:
+ * (1) irix 5.* made -ldl optional but warned
+ * (2) irix 6.* has no -ldl
+ * (3) dynamic progs built on irix 5.* and using -ldl fail
+ * at runtime on irix 6.* because -ldl is not there
+ */
+
+dl :MAPLIB: dl.c
+
+/*
+ * requiring these is a botch
+ */
+
+iconv :MAPLIB: iconv.c
+
+w :MAPLIB: w.c w2.c
+
+/*
+ * miscellaneous -l* checks
+ */
+
+intl :MAPLIB: intl.c
+
+m :MAPLIB: m.c m2.c m3.c m4.c m5.c m6.c
+
+nsl :MAPLIB: nsl.c
+
+/*
+ * what was sco smoking
+ * almost all of gethost* are in -lnsl except gethostbyname which
+ * is in -lsocket which isn't needed to resolve socket() but seems
+ * to do the -lnsl job
+ */
+
+socket :MAPLIB: socket.c nsl.c
+
+/*
+ * more substance abuse
+ * gdbm's ndbm "compatibility" doesn't supply <ndbm.h>, instead supplies
+ * <gdbm/ndbm.h> which provides K&R prototypes *and* it requires -lgdbm
+ * some <ndbm.h> implementations use -lndbm, others -ldbm, still others -lc
+ * this is why unix is starting to look like windows
+ * this map allows makefiles to use -ldbm on all systems
+ *
+ * and this just in: sometimes its <gdbm-ndbm.h> and possibly -lgdbm_compat
+ *
+ * at least the -l* buck stops here
+ */
+
+dbm db - gdbm_compat - gdbm - ndbm - dbm :MAPLIB: db.c gdbm.c gdbm1.c gdbm2.c
diff --git a/src/cmd/INIT/Mamfile b/src/cmd/INIT/Mamfile
new file mode 100644
index 0000000..e5826d2
--- /dev/null
+++ b/src/cmd/INIT/Mamfile
@@ -0,0 +1,1332 @@
+info mam static 00000 1994-07-17 make (AT&T Research) 5.7 2012-02-29
+setv INSTALLROOT ../../..
+setv PACKAGEROOT ../../../../..
+setv AR ${mam_cc_AR} ${mam_cc_AR_ARFLAGS}
+setv ARFLAGS rc
+setv AS as
+setv ASFLAGS
+setv CC cc
+setv mam_cc_FLAGS
+setv CCFLAGS ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${mam_cc_OPTIMIZE}?}
+setv CCLDFLAGS ${-strip-symbols?1?${mam_cc_LD_STRIP}??}
+setv COTEMP $$
+setv CPIO cpio
+setv CPIOFLAGS
+setv CPP "${CC} -E"
+setv F77 f77
+setv HOSTCC ${CC}
+setv IGNORE
+setv LD ld
+setv LDFLAGS
+setv LEX lex
+setv LEXFLAGS
+setv LPR lpr
+setv LPRFLAGS
+setv M4FLAGS
+setv NMAKE nmake
+setv NMAKEFLAGS
+setv PR pr
+setv PRFLAGS
+setv SHELL /bin/sh
+setv SILENT
+setv TAR tar
+setv YACC yacc
+setv YACCFLAGS -d
+make ${PACKAGEROOT}/lib/package/ast.lic
+done ${PACKAGEROOT}/lib/package/ast.lic
+make install
+make hurl
+make hurl.sh
+done hurl.sh
+meta hurl %.sh>% hurl.sh hurl
+prev hurl.sh
+setv LICENSE -DLICENSE="since=2003,author=gsf"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : hurl contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n hurl.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp hurl.sh hurl
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < hurl.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - hurl.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2003-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > hurl
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - hurl.sh > hurl <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2003-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w hurl -a -x hurl || chmod u+w,+x hurl
+done hurl generated
+make iffe
+make iffe.sh
+done iffe.sh
+meta iffe %.sh>% iffe.sh iffe
+prev iffe.sh
+setv LICENSE -DLICENSE="since=1994,author=gsf+kpv"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : iffe contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n iffe.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 241 in
+exec - 0) cp iffe.sh iffe
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < iffe.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - iffe.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-author?Phong Vo <kpv@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > iffe
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - iffe.sh > iffe <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-author?Phong Vo <kpv@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w iffe -a -x iffe || chmod u+w,+x iffe
+done iffe generated
+make mktest
+make mktest.sh
+done mktest.sh
+meta mktest %.sh>% mktest.sh mktest
+prev mktest.sh
+setv LICENSE -DLICENSE="since=2005,author=gsf"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : mktest contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n mktest.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp mktest.sh mktest
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < mktest.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - mktest.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2005-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > mktest
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - mktest.sh > mktest <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2005-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w mktest -a -x mktest || chmod u+w,+x mktest
+done mktest generated
+make package
+make package.sh
+done package.sh
+meta package %.sh>% package.sh package
+prev package.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : package contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n package.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp package.sh package
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < package.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - package.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > package
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - package.sh > package <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w package -a -x package || chmod u+w,+x package
+done package generated
+make regress
+make regress.sh
+done regress.sh
+meta regress %.sh>% regress.sh regress
+prev regress.sh
+setv LICENSE -DLICENSE="since=1995,author=gsf"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : regress contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n regress.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp regress.sh regress
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < regress.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - regress.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1995-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > regress
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - regress.sh > regress <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1995-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w regress -a -x regress || chmod u+w,+x regress
+done regress generated
+make rt
+make rt.sh
+done rt.sh
+meta rt %.sh>% rt.sh rt
+prev rt.sh
+setv LICENSE -DLICENSE="since=2005,author=gsf"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : rt contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n rt.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp rt.sh rt
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < rt.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - rt.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2005-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > rt
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - rt.sh > rt <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2005-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w rt -a -x rt || chmod u+w,+x rt
+done rt generated
+make crossexec
+make crossexec.sh
+done crossexec.sh
+meta crossexec %.sh>% crossexec.sh crossexec
+prev crossexec.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : crossexec contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n crossexec.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp crossexec.sh crossexec
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < crossexec.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - crossexec.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > crossexec
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - crossexec.sh > crossexec <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w crossexec -a -x crossexec || chmod u+w,+x crossexec
+done crossexec generated
+make ditto
+make ditto.sh
+done ditto.sh
+meta ditto %.sh>% ditto.sh ditto
+prev ditto.sh
+setv LICENSE -DLICENSE="since=2001,author=gsf+ek"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : ditto contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n ditto.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 248 in
+exec - 0) cp ditto.sh ditto
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < ditto.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - ditto.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-author?Lefty Koutsofios <ek@research.att.com>][-copyright?Copyright (c) 2001-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > ditto
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - ditto.sh > ditto <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-author?Lefty Koutsofios <ek@research.att.com>][-copyright?Copyright (c) 2001-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w ditto -a -x ditto || chmod u+w,+x ditto
+done ditto generated
+make execrate
+make execrate.sh
+done execrate.sh
+meta execrate %.sh>% execrate.sh execrate
+prev execrate.sh
+setv LICENSE -DLICENSE="since=2002,author=gsf"
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : execrate contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n execrate.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp execrate.sh execrate
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < execrate.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - execrate.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2002-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > execrate
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - execrate.sh > execrate <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2002-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w execrate -a -x execrate || chmod u+w,+x execrate
+done execrate generated
+make filter
+make filter.sh
+done filter.sh
+meta filter %.sh>% filter.sh filter
+prev filter.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : filter contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n filter.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 200 in
+exec - 0) cp filter.sh filter
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < filter.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - filter.sh <<'!'
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - } > filter
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - filter.sh > filter <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - USAGE_LICENSE="[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w filter -a -x filter || chmod u+w,+x filter
+done filter generated
+make ignore
+make ignore.sh
+done ignore.sh
+meta ignore %.sh>% ignore.sh ignore
+prev ignore.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : ignore contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n ignore.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 0 in
+exec - 0) cp ignore.sh ignore
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < ignore.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - ignore.sh <<'!'
+exec -
+exec - !
+exec - } > ignore
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - ignore.sh > ignore <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec -
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w ignore -a -x ignore || chmod u+w,+x ignore
+done ignore generated
+make silent
+make silent.sh
+done silent.sh
+meta silent %.sh>% silent.sh silent
+prev silent.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : silent contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n silent.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 0 in
+exec - 0) cp silent.sh silent
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < silent.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - silent.sh <<'!'
+exec -
+exec - !
+exec - } > silent
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - silent.sh > silent <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec -
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w silent -a -x silent || chmod u+w,+x silent
+done silent generated
+make mamake
+make mamake.o
+make mamake.c
+make shlib-compat.h implicit
+done shlib-compat.h dontcare virtual
+make ast.h implicit
+done ast.h dontcare virtual
+done mamake.c
+meta mamake.o %.c>%.o mamake.c mamake
+prev mamake.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"\" -c mamake.c
+done mamake.o generated
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o mamake mamake.o
+done mamake generated
+make proto
+make proto.o
+make proto.c
+done proto.c
+meta proto.o %.c>%.o proto.c proto
+prev proto.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -c proto.c
+done proto.o generated
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o proto proto.o
+done proto generated
+make ratz
+make ratz.o
+make ratz.c
+make unix.h implicit
+done unix.h dontcare virtual
+make alloc.h implicit
+done alloc.h dontcare virtual
+make unixio.h implicit
+done unixio.h dontcare virtual
+make ast_std.h implicit
+done ast_std.h dontcare virtual
+make windows.h implicit
+done windows.h dontcare virtual
+make io.h implicit
+done io.h dontcare virtual
+make direct.h implicit
+done direct.h dontcare virtual
+prev ast.h implicit
+done ratz.c
+meta ratz.o %.c>%.o ratz.c ratz
+prev ratz.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -c ratz.c
+done ratz.o generated
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o ratz ratz.o
+done ratz generated
+make release
+make release.o
+make release.c
+prev ast.h implicit
+done release.c
+meta release.o %.c>%.o release.c release
+prev release.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 1994-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?INIT]"\" -c release.c
+done release.o generated
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o release release.o
+done release generated
+make mprobe
+make mprobe.sh
+done mprobe.sh
+meta mprobe %.sh>% mprobe.sh mprobe
+prev mprobe.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : mprobe contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n mprobe.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 0 in
+exec - 0) cp mprobe.sh mprobe
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < mprobe.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - mprobe.sh <<'!'
+exec -
+exec - !
+exec - } > mprobe
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - mprobe.sh > mprobe <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec -
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w mprobe -a -x mprobe || chmod u+w,+x mprobe
+done mprobe generated
+make probe
+make probe.sh
+make C+probe
+done C+probe
+make make.probe
+done make.probe
+exec - cat C+probe make.probe > probe.sh
+done probe.sh generated
+meta probe %.sh>% probe.sh probe
+prev probe.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : probe contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n probe.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 0 in
+exec - 0) cp probe.sh probe
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < probe.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - probe.sh <<'!'
+exec -
+exec - !
+exec - } > probe
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - probe.sh > probe <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec -
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w probe -a -x probe || chmod u+w,+x probe
+done probe generated
+make ${INSTALLROOT}/bin
+exec - if silent test ! -d ${INSTALLROOT}/bin
+exec - then mkdir -p ${INSTALLROOT}/bin
+exec - fi
+done ${INSTALLROOT}/bin generated
+make ${INSTALLROOT}/bin/hurl
+prev ${INSTALLROOT}/bin
+prev hurl
+exec - test '' = 'hurl' || ${STDCMP} 2>/dev/null -s hurl ${INSTALLROOT}/bin/hurl || { ${STDMV} ${INSTALLROOT}/bin/hurl ${INSTALLROOT}/bin/hurl.old 2>/dev/null || true; ${STDCP} hurl ${INSTALLROOT}/bin/hurl ;}
+done ${INSTALLROOT}/bin/hurl generated
+make ${INSTALLROOT}/bin/iffe
+prev iffe
+exec - test '' = 'iffe' || ${STDCMP} 2>/dev/null -s iffe ${INSTALLROOT}/bin/iffe || { ${STDMV} ${INSTALLROOT}/bin/iffe ${INSTALLROOT}/bin/iffe.old 2>/dev/null || true; ${STDCP} iffe ${INSTALLROOT}/bin/iffe ;}
+done ${INSTALLROOT}/bin/iffe generated
+make ${INSTALLROOT}/bin/mktest
+prev mktest
+exec - test '' = 'mktest' || ${STDCMP} 2>/dev/null -s mktest ${INSTALLROOT}/bin/mktest || { ${STDMV} ${INSTALLROOT}/bin/mktest ${INSTALLROOT}/bin/mktest.old 2>/dev/null || true; ${STDCP} mktest ${INSTALLROOT}/bin/mktest ;}
+done ${INSTALLROOT}/bin/mktest generated
+make ${INSTALLROOT}/bin/package
+prev package
+exec - test '' = 'package' || ${STDCMP} 2>/dev/null -s package ${INSTALLROOT}/bin/package || { ${STDMV} ${INSTALLROOT}/bin/package ${INSTALLROOT}/bin/package.old 2>/dev/null || true; ${STDCP} package ${INSTALLROOT}/bin/package ;}
+done ${INSTALLROOT}/bin/package generated
+make ${INSTALLROOT}/bin/regress
+prev regress
+exec - test '' = 'regress' || ${STDCMP} 2>/dev/null -s regress ${INSTALLROOT}/bin/regress || { ${STDMV} ${INSTALLROOT}/bin/regress ${INSTALLROOT}/bin/regress.old 2>/dev/null || true; ${STDCP} regress ${INSTALLROOT}/bin/regress ;}
+done ${INSTALLROOT}/bin/regress generated
+make ${INSTALLROOT}/bin/rt
+prev rt
+exec - test '' = 'rt' || ${STDCMP} 2>/dev/null -s rt ${INSTALLROOT}/bin/rt || { ${STDMV} ${INSTALLROOT}/bin/rt ${INSTALLROOT}/bin/rt.old 2>/dev/null || true; ${STDCP} rt ${INSTALLROOT}/bin/rt ;}
+done ${INSTALLROOT}/bin/rt generated
+make ${PACKAGEROOT}/bin
+exec - if silent test ! -d ${PACKAGEROOT}/bin
+exec - then mkdir -p ${PACKAGEROOT}/bin
+exec - fi
+done ${PACKAGEROOT}/bin generated
+make ${PACKAGEROOT}/bin/execrate
+prev ${PACKAGEROOT}/bin
+prev execrate
+exec - test '' = 'execrate' || ${STDCMP} 2>/dev/null -s execrate ${PACKAGEROOT}/bin/execrate || { ${STDMV} ${PACKAGEROOT}/bin/execrate ${PACKAGEROOT}/bin/execrate.old 2>/dev/null || true; ${STDCP} execrate ${PACKAGEROOT}/bin/execrate ;}
+done ${PACKAGEROOT}/bin/execrate generated
+make ${PACKAGEROOT}/bin/ignore
+prev ignore
+exec - test '' = 'ignore' || ${STDCMP} 2>/dev/null -s ignore ${PACKAGEROOT}/bin/ignore || { ${STDMV} ${PACKAGEROOT}/bin/ignore ${PACKAGEROOT}/bin/ignore.old 2>/dev/null || true; ${STDCP} ignore ${PACKAGEROOT}/bin/ignore ;}
+done ${PACKAGEROOT}/bin/ignore generated
+make ${PACKAGEROOT}/bin/mamprobe
+make mamprobe
+meta mamprobe %.sh>% mamprobe.sh mamprobe
+make mamprobe.sh
+done mamprobe.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : mamprobe contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n mamprobe.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 0 in
+exec - 0) cp mamprobe.sh mamprobe
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < mamprobe.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - mamprobe.sh <<'!'
+exec -
+exec - !
+exec - } > mamprobe
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - mamprobe.sh > mamprobe <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec -
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w mamprobe -a -x mamprobe || chmod u+w,+x mamprobe
+done mamprobe generated
+exec - test '' = 'mamprobe' || ${STDCMP} 2>/dev/null -s mamprobe ${PACKAGEROOT}/bin/mamprobe || { ${STDMV} ${PACKAGEROOT}/bin/mamprobe ${PACKAGEROOT}/bin/mamprobe.old 2>/dev/null || true; ${STDCP} mamprobe ${PACKAGEROOT}/bin/mamprobe ;}
+done ${PACKAGEROOT}/bin/mamprobe generated
+make ${PACKAGEROOT}/bin/package
+prev package
+exec - test '' = 'package' || ${STDCMP} 2>/dev/null -s package ${PACKAGEROOT}/bin/package || { ${STDMV} ${PACKAGEROOT}/bin/package ${PACKAGEROOT}/bin/package.old 2>/dev/null || true; ${STDCP} package ${PACKAGEROOT}/bin/package ;}
+done ${PACKAGEROOT}/bin/package generated
+make ${PACKAGEROOT}/bin/silent
+prev silent
+exec - test '' = 'silent' || ${STDCMP} 2>/dev/null -s silent ${PACKAGEROOT}/bin/silent || { ${STDMV} ${PACKAGEROOT}/bin/silent ${PACKAGEROOT}/bin/silent.old 2>/dev/null || true; ${STDCP} silent ${PACKAGEROOT}/bin/silent ;}
+done ${PACKAGEROOT}/bin/silent generated
+make ${INSTALLROOT}/bin/crossexec
+prev crossexec
+exec - test '' = 'crossexec' || ${STDCMP} 2>/dev/null -s crossexec ${INSTALLROOT}/bin/crossexec || { ${STDMV} ${INSTALLROOT}/bin/crossexec ${INSTALLROOT}/bin/crossexec.old 2>/dev/null || true; ${STDCP} crossexec ${INSTALLROOT}/bin/crossexec ;}
+done ${INSTALLROOT}/bin/crossexec generated
+make ${INSTALLROOT}/bin/ditto
+prev ditto
+exec - test '' = 'ditto' || ${STDCMP} 2>/dev/null -s ditto ${INSTALLROOT}/bin/ditto || { ${STDMV} ${INSTALLROOT}/bin/ditto ${INSTALLROOT}/bin/ditto.old 2>/dev/null || true; ${STDCP} ditto ${INSTALLROOT}/bin/ditto ;}
+done ${INSTALLROOT}/bin/ditto generated
+make ${INSTALLROOT}/bin/filter
+prev filter
+exec - test '' = 'filter' || ${STDCMP} 2>/dev/null -s filter ${INSTALLROOT}/bin/filter || { ${STDMV} ${INSTALLROOT}/bin/filter ${INSTALLROOT}/bin/filter.old 2>/dev/null || true; ${STDCP} filter ${INSTALLROOT}/bin/filter ;}
+done ${INSTALLROOT}/bin/filter generated
+make ${PACKAGEROOT}/lib/package
+exec - if silent test ! -d ${PACKAGEROOT}/lib/package
+exec - then mkdir -p ${PACKAGEROOT}/lib/package
+exec - fi
+done ${PACKAGEROOT}/lib/package generated
+make ${PACKAGEROOT}/lib/package/package.mk
+prev ${PACKAGEROOT}/lib/package
+make package.mk
+done package.mk
+exec - test '' = 'package.mk' || ${STDCMP} 2>/dev/null -s package.mk ${PACKAGEROOT}/lib/package/package.mk || { ${STDMV} ${PACKAGEROOT}/lib/package/package.mk ${PACKAGEROOT}/lib/package/package.mk.old 2>/dev/null || true; ${STDCP} package.mk ${PACKAGEROOT}/lib/package/package.mk ;}
+done ${PACKAGEROOT}/lib/package/package.mk generated
+make ${PACKAGEROOT}/lib/package/CONVERT.mk
+make CONVERT.mk
+done CONVERT.mk
+exec - test '' = 'CONVERT.mk' || ${STDCMP} 2>/dev/null -s CONVERT.mk ${PACKAGEROOT}/lib/package/CONVERT.mk || { ${STDMV} ${PACKAGEROOT}/lib/package/CONVERT.mk ${PACKAGEROOT}/lib/package/CONVERT.mk.old 2>/dev/null || true; ${STDCP} CONVERT.mk ${PACKAGEROOT}/lib/package/CONVERT.mk ;}
+done ${PACKAGEROOT}/lib/package/CONVERT.mk generated
+make ${INSTALLROOT}/lib/make
+exec - if silent test ! -d ${INSTALLROOT}/lib/make
+exec - then mkdir -p ${INSTALLROOT}/lib/make
+exec - fi
+done ${INSTALLROOT}/lib/make generated
+make ${INSTALLROOT}/lib/make/package.mk
+prev ${INSTALLROOT}/lib/make
+prev package.mk
+exec - test '' = 'package.mk' || ${STDCMP} 2>/dev/null -s package.mk ${INSTALLROOT}/lib/make/package.mk || { ${STDMV} ${INSTALLROOT}/lib/make/package.mk ${INSTALLROOT}/lib/make/package.mk.old 2>/dev/null || true; ${STDCP} package.mk ${INSTALLROOT}/lib/make/package.mk ;}
+done ${INSTALLROOT}/lib/make/package.mk generated
+make ${INSTALLROOT}/lib/make/PROBE.mk
+make PROBE.mk
+done PROBE.mk
+exec - test '' = 'PROBE.mk' || ${STDCMP} 2>/dev/null -s PROBE.mk ${INSTALLROOT}/lib/make/PROBE.mk || { ${STDMV} ${INSTALLROOT}/lib/make/PROBE.mk ${INSTALLROOT}/lib/make/PROBE.mk.old 2>/dev/null || true; ${STDCP} PROBE.mk ${INSTALLROOT}/lib/make/PROBE.mk ;}
+done ${INSTALLROOT}/lib/make/PROBE.mk generated
+make ${INSTALLROOT}/lib/make/TEST.mk
+make TEST.mk
+done TEST.mk
+exec - test '' = 'TEST.mk' || ${STDCMP} 2>/dev/null -s TEST.mk ${INSTALLROOT}/lib/make/TEST.mk || { ${STDMV} ${INSTALLROOT}/lib/make/TEST.mk ${INSTALLROOT}/lib/make/TEST.mk.old 2>/dev/null || true; ${STDCP} TEST.mk ${INSTALLROOT}/lib/make/TEST.mk ;}
+done ${INSTALLROOT}/lib/make/TEST.mk generated
+make ${INSTALLROOT}/lib/make/WWW.mk
+make WWW.mk
+done WWW.mk
+exec - test '' = 'WWW.mk' || ${STDCMP} 2>/dev/null -s WWW.mk ${INSTALLROOT}/lib/make/WWW.mk || { ${STDMV} ${INSTALLROOT}/lib/make/WWW.mk ${INSTALLROOT}/lib/make/WWW.mk.old 2>/dev/null || true; ${STDCP} WWW.mk ${INSTALLROOT}/lib/make/WWW.mk ;}
+done ${INSTALLROOT}/lib/make/WWW.mk generated
+make ${INSTALLROOT}/lib/make/MSGFUN.mk
+make MSGFUN.mk
+done MSGFUN.mk
+exec - test '' = 'MSGFUN.mk' || ${STDCMP} 2>/dev/null -s MSGFUN.mk ${INSTALLROOT}/lib/make/MSGFUN.mk || { ${STDMV} ${INSTALLROOT}/lib/make/MSGFUN.mk ${INSTALLROOT}/lib/make/MSGFUN.mk.old 2>/dev/null || true; ${STDCP} MSGFUN.mk ${INSTALLROOT}/lib/make/MSGFUN.mk ;}
+done ${INSTALLROOT}/lib/make/MSGFUN.mk generated
+make ${INSTALLROOT}/lib/make/MSGKEY.mk
+make MSGKEY.mk
+done MSGKEY.mk
+exec - test '' = 'MSGKEY.mk' || ${STDCMP} 2>/dev/null -s MSGKEY.mk ${INSTALLROOT}/lib/make/MSGKEY.mk || { ${STDMV} ${INSTALLROOT}/lib/make/MSGKEY.mk ${INSTALLROOT}/lib/make/MSGKEY.mk.old 2>/dev/null || true; ${STDCP} MSGKEY.mk ${INSTALLROOT}/lib/make/MSGKEY.mk ;}
+done ${INSTALLROOT}/lib/make/MSGKEY.mk generated
+make ${INSTALLROOT}/lib/make/MAPLIB.mk
+make MAPLIB.mk
+done MAPLIB.mk
+exec - test '' = 'MAPLIB.mk' || ${STDCMP} 2>/dev/null -s MAPLIB.mk ${INSTALLROOT}/lib/make/MAPLIB.mk || { ${STDMV} ${INSTALLROOT}/lib/make/MAPLIB.mk ${INSTALLROOT}/lib/make/MAPLIB.mk.old 2>/dev/null || true; ${STDCP} MAPLIB.mk ${INSTALLROOT}/lib/make/MAPLIB.mk ;}
+done ${INSTALLROOT}/lib/make/MAPLIB.mk generated
+make ${INSTALLROOT}/bin/mamake
+prev mamake
+exec - test '' = 'mamake' || ${STDCMP} 2>/dev/null -s mamake ${INSTALLROOT}/bin/mamake || { ${STDMV} ${INSTALLROOT}/bin/mamake ${INSTALLROOT}/bin/mamake.old 2>/dev/null || true; ${STDCP} mamake ${INSTALLROOT}/bin/mamake ;}
+done ${INSTALLROOT}/bin/mamake generated
+make ${INSTALLROOT}/bin/proto
+prev proto
+exec - test '' = 'proto' || ${STDCMP} 2>/dev/null -s proto ${INSTALLROOT}/bin/proto || { ${STDMV} ${INSTALLROOT}/bin/proto ${INSTALLROOT}/bin/proto.old 2>/dev/null || true; ${STDCP} proto ${INSTALLROOT}/bin/proto ;}
+done ${INSTALLROOT}/bin/proto generated
+make ${INSTALLROOT}/bin/ratz
+prev ratz
+exec - test '' = 'ratz' || ${STDCMP} 2>/dev/null -s ratz ${INSTALLROOT}/bin/ratz || { ${STDMV} ${INSTALLROOT}/bin/ratz ${INSTALLROOT}/bin/ratz.old 2>/dev/null || true; ${STDCP} ratz ${INSTALLROOT}/bin/ratz ;}
+done ${INSTALLROOT}/bin/ratz generated
+make ${INSTALLROOT}/bin/release
+prev release
+exec - test '' = 'release' || ${STDCMP} 2>/dev/null -s release ${INSTALLROOT}/bin/release || { ${STDMV} ${INSTALLROOT}/bin/release ${INSTALLROOT}/bin/release.old 2>/dev/null || true; ${STDCP} release ${INSTALLROOT}/bin/release ;}
+done ${INSTALLROOT}/bin/release generated
+make ${INSTALLROOT}/bin/mkdir
+make mkdir.sh
+done mkdir.sh
+exec - if test ! -x ${INSTALLROOT}/bin/mkdir -a -x /bin/mkdir
+exec - then mkdir -p 2>/dev/null || :
+exec - if test -d ./-p
+exec - then rmdir ./-p
+exec - cp mkdir.sh ${INSTALLROOT}/bin/mkdir
+exec - chmod +x ${INSTALLROOT}/bin/mkdir
+exec - fi
+exec - fi
+done ${INSTALLROOT}/bin/mkdir generated
+make ${INSTALLROOT}/bin/.paths
+exec - if test ! -f ${INSTALLROOT}/bin/.paths -o -w ${INSTALLROOT}/bin/.paths
+exec - then nl="
+exec - "
+exec - o=`cat ${INSTALLROOT}/bin/.paths 2>/dev/null` || :
+exec - v=
+exec - n=
+exec - case $nl$o in
+exec - *${nl}FPATH=*|*#FPATH=*|*[Nn][Oo]FPATH=*)
+exec - ;;
+exec - *) case $n in
+exec - '') ;;
+exec - *) n="$n$nl" v="$v|" ;;
+exec - esac
+exec - n="${n}FPATH=../fun"
+exec - v="${v}FPATH"
+exec - ;;
+exec - esac
+exec - case $nl$o in
+exec - *${nl}BUILTIN_LIB=*|*#BUILTIN_LIB=*|*[Nn][Oo]BUILTIN_LIB=*)
+exec - ;;
+exec - *) case $n in
+exec - '') ;;
+exec - *) n="$n$nl" v="$v|" ;;
+exec - esac
+exec - case '' in
+exec - ?*) p= c= ;;
+exec - *) p='XX' ;;
+exec - esac
+exec - n="${n}${p}BUILTIN_LIB=cmd"
+exec - v="${v}BUILTIN_LIB"
+exec - ;;
+exec - esac
+exec - set x x :
+exec - p=
+exec - while :
+exec - do while :
+exec - do case $# in
+exec - 0) break ;;
+exec - esac
+exec - x=$1
+exec - shift
+exec - case $x in
+exec - :) break ;;
+exec - esac
+exec - done
+exec - case $# in
+exec - 0|1) break
+exec - ;;
+exec - 2) p=$2
+exec - ;;
+exec - *) case "${mam_cc_HOSTTYPE}" in
+exec - $3) p=$2; break ;;
+exec - esac
+exec - ;;
+exec - esac
+exec - done
+exec - case $p in
+exec - '') if test -x /lib/dld.sl
+exec - then p=SHLIB_PATH
+exec - elif test -x /usr/lib/dyld
+exec - then p=DYLD_LIBRARY_PATH
+exec - else case "${mam_cc_HOSTTYPE}" in
+exec - ibm.*|mvs.*)
+exec - p=LIBPATH
+exec - ;;
+exec - sgi.mips3)
+exec - p=LD_LIBRARYN32_PATH
+exec - ;;
+exec - sgi.mips4)
+exec - p=LD_LIBRARYN64_PATH
+exec - ;;
+exec - *) p=LD_LIBRARY_PATH
+exec - ;;
+exec - esac
+exec - fi
+exec - ;;
+exec - esac
+exec - case $nl$o in
+exec - *${nl}${p}=*|*#${p}=*|*[Nn][Oo]${p}=*)
+exec - ;;
+exec - *) case $n in
+exec - '') ;;
+exec - *) n="$n$nl" v="$v|" ;;
+exec - esac
+exec - n="${n}${p}=../lib"
+exec - v="${v}${p}"
+exec - ;;
+exec - esac
+exec - case $n in
+exec - ?*) case $o in
+exec - ?*) o=`egrep -v "($v)=" ${INSTALLROOT}/bin/.paths`$nl ;;
+exec - esac
+exec - echo "# use { # no NO } prefix instead of XX to permanently disable #$nl$o$n" > ${INSTALLROOT}/bin/.paths
+exec - ;;
+exec - esac
+exec - fi
+done ${INSTALLROOT}/bin/.paths generated
+make ${INSTALLROOT}/lib/probe/C
+exec - if silent test ! -d ${INSTALLROOT}/lib/probe/C
+exec - then mkdir -p ${INSTALLROOT}/lib/probe/C
+exec - fi
+done ${INSTALLROOT}/lib/probe/C generated
+make ${INSTALLROOT}/lib/probe/C/probe
+prev ${INSTALLROOT}/lib/probe/C
+prev C+probe
+exec - test '' = 'C+probe' || ${STDCMP} 2>/dev/null -s C+probe ${INSTALLROOT}/lib/probe/C/probe || { ${STDMV} ${INSTALLROOT}/lib/probe/C/probe ${INSTALLROOT}/lib/probe/C/probe.old 2>/dev/null || true; ${STDCP} C+probe ${INSTALLROOT}/lib/probe/C/probe ;}
+done ${INSTALLROOT}/lib/probe/C/probe generated
+make ${INSTALLROOT}/lib/probe/C/make
+exec - if silent test ! -d ${INSTALLROOT}/lib/probe/C/make
+exec - then mkdir -p ${INSTALLROOT}/lib/probe/C/make
+exec - fi
+done ${INSTALLROOT}/lib/probe/C/make generated
+prev ${INSTALLROOT}/lib/probe/C/make
+make ${INSTALLROOT}/lib/probe/C/pp
+exec - if silent test ! -d ${INSTALLROOT}/lib/probe/C/pp
+exec - then mkdir -p ${INSTALLROOT}/lib/probe/C/pp
+exec - fi
+done ${INSTALLROOT}/lib/probe/C/pp generated
+prev ${INSTALLROOT}/lib/probe/C/pp
+make ${INSTALLROOT}/lib/probe/C/mam
+exec - if silent test ! -d ${INSTALLROOT}/lib/probe/C/mam
+exec - then mkdir -p ${INSTALLROOT}/lib/probe/C/mam
+exec - fi
+done ${INSTALLROOT}/lib/probe/C/mam generated
+make ${INSTALLROOT}/lib/probe/C/mam/probe
+prev ${INSTALLROOT}/lib/probe/C/mam
+prev mprobe
+exec - test '' = 'mprobe' || ${STDCMP} 2>/dev/null -s mprobe ${INSTALLROOT}/lib/probe/C/mam/probe || { ${STDMV} ${INSTALLROOT}/lib/probe/C/mam/probe ${INSTALLROOT}/lib/probe/C/mam/probe.old 2>/dev/null || true; ${STDCP} mprobe ${INSTALLROOT}/lib/probe/C/mam/probe ;}
+done ${INSTALLROOT}/lib/probe/C/mam/probe generated
+make ${INSTALLROOT}/lib/probe/C/mam/mprobe
+prev mprobe
+exec - test '' = 'mprobe' || ${STDCMP} 2>/dev/null -s mprobe ${INSTALLROOT}/lib/probe/C/mam/mprobe || { ${STDMV} ${INSTALLROOT}/lib/probe/C/mam/mprobe ${INSTALLROOT}/lib/probe/C/mam/mprobe.old 2>/dev/null || true; ${STDCP} mprobe ${INSTALLROOT}/lib/probe/C/mam/mprobe ;}
+done ${INSTALLROOT}/lib/probe/C/mam/mprobe generated
+make ${INSTALLROOT}/lib/probe/C/make/probe
+prev probe
+exec - test '' = 'probe' || ${STDCMP} 2>/dev/null -s probe ${INSTALLROOT}/lib/probe/C/make/probe || { ${STDMV} ${INSTALLROOT}/lib/probe/C/make/probe ${INSTALLROOT}/lib/probe/C/make/probe.old 2>/dev/null || true; ${STDCP} probe ${INSTALLROOT}/lib/probe/C/make/probe ;}
+done ${INSTALLROOT}/lib/probe/C/make/probe generated
+make ${INSTALLROOT}/lib/probe/C/make/probe.ini
+make probe.ini
+make probe.win32
+done probe.win32
+exec - t=${mam_cc_HOSTTYPE}
+exec - ifs=$IFS
+exec - IFS=.
+exec - set x $t
+exec - IFS=$ifs
+exec - t=$2
+exec - set x probe.win32
+exec - while :
+exec - do shift
+exec - case $# in
+exec - 0) break ;;
+exec - esac
+exec - case $1 in
+exec - *probe.$t)
+exec - break
+exec - esac
+exec - done
+exec - case $1 in
+exec - ?*) cmp -s $1 probe.ini || cp $1 probe.ini ;;
+exec - *) : > probe.ini
+exec - esac
+done probe.ini generated
+exec - test '' = 'probe.ini' || ${STDCMP} 2>/dev/null -s probe.ini ${INSTALLROOT}/lib/probe/C/make/probe.ini || { ${STDMV} ${INSTALLROOT}/lib/probe/C/make/probe.ini ${INSTALLROOT}/lib/probe/C/make/probe.ini.old 2>/dev/null || true; ${STDCP} probe.ini ${INSTALLROOT}/lib/probe/C/make/probe.ini ;}
+done ${INSTALLROOT}/lib/probe/C/make/probe.ini generated
+make ${INSTALLROOT}/include
+exec - if silent test ! -d ${INSTALLROOT}/include
+exec - then mkdir -p ${INSTALLROOT}/include
+exec - fi
+done ${INSTALLROOT}/include generated
+make ${INSTALLROOT}/include/prototyped.h
+prev ${INSTALLROOT}/include
+make prototyped.h
+prev ${INSTALLROOT}/bin/proto
+exec - proto -f /dev/null > h.${COTEMP}.h
+exec - if cmp 2>/dev/null -s h.${COTEMP}.h prototyped.h
+exec - then rm -f h.${COTEMP}.h
+exec - else mv h.${COTEMP}.h prototyped.h
+exec - fi
+done prototyped.h generated
+exec - test '' = 'prototyped.h' || ${STDCMP} 2>/dev/null -s prototyped.h ${INSTALLROOT}/include/prototyped.h || { ${STDMV} ${INSTALLROOT}/include/prototyped.h ${INSTALLROOT}/include/prototyped.h.old 2>/dev/null || true; ${STDCP} prototyped.h ${INSTALLROOT}/include/prototyped.h ;}
+done ${INSTALLROOT}/include/prototyped.h generated
+make ${INSTALLROOT}/lib/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib/lib
+exec - then mkdir -p ${INSTALLROOT}/lib/lib
+exec - fi
+done ${INSTALLROOT}/lib/lib generated
+make ${INSTALLROOT}/lib/lib/dl
+prev ${INSTALLROOT}/lib/lib
+make dl.req
+make dl.c
+done dl.c
+exec - set -
+exec - r='-'
+exec - for i in dl.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in dl -
+exec - do case $p in
+exec - -) if ${CC} -o dl.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o dl.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > dl.req
+exec - rm -f dl.exe dl
+done dl.req generated
+exec - test '' = 'dl.req' || ${STDCMP} 2>/dev/null -s dl.req ${INSTALLROOT}/lib/lib/dl || { ${STDMV} ${INSTALLROOT}/lib/lib/dl ${INSTALLROOT}/lib/lib/dl.old 2>/dev/null || true; ${STDCP} dl.req ${INSTALLROOT}/lib/lib/dl ;}
+done ${INSTALLROOT}/lib/lib/dl generated
+make ${INSTALLROOT}/lib/lib/iconv
+make iconv.req
+make iconv.c
+done iconv.c
+exec - set -
+exec - r='-'
+exec - for i in iconv.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in iconv -
+exec - do case $p in
+exec - -) if ${CC} -o iconv.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o iconv.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > iconv.req
+exec - rm -f iconv.exe iconv
+done iconv.req generated
+exec - test '' = 'iconv.req' || ${STDCMP} 2>/dev/null -s iconv.req ${INSTALLROOT}/lib/lib/iconv || { ${STDMV} ${INSTALLROOT}/lib/lib/iconv ${INSTALLROOT}/lib/lib/iconv.old 2>/dev/null || true; ${STDCP} iconv.req ${INSTALLROOT}/lib/lib/iconv ;}
+done ${INSTALLROOT}/lib/lib/iconv generated
+make ${INSTALLROOT}/lib/lib/w
+make w.req
+make w.c
+done w.c
+make w2.c
+done w2.c
+exec - set -
+exec - r='-'
+exec - for i in w.c w2.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in w -
+exec - do case $p in
+exec - -) if ${CC} -o w.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o w.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > w.req
+exec - rm -f w.exe w w2
+done w.req generated
+exec - test '' = 'w.req' || ${STDCMP} 2>/dev/null -s w.req ${INSTALLROOT}/lib/lib/w || { ${STDMV} ${INSTALLROOT}/lib/lib/w ${INSTALLROOT}/lib/lib/w.old 2>/dev/null || true; ${STDCP} w.req ${INSTALLROOT}/lib/lib/w ;}
+done ${INSTALLROOT}/lib/lib/w generated
+make ${INSTALLROOT}/lib/lib/intl
+make intl.req
+make intl.c
+done intl.c
+exec - set -
+exec - r='-'
+exec - for i in intl.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in intl -
+exec - do case $p in
+exec - -) if ${CC} -o intl.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o intl.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > intl.req
+exec - rm -f intl.exe intl
+done intl.req generated
+exec - test '' = 'intl.req' || ${STDCMP} 2>/dev/null -s intl.req ${INSTALLROOT}/lib/lib/intl || { ${STDMV} ${INSTALLROOT}/lib/lib/intl ${INSTALLROOT}/lib/lib/intl.old 2>/dev/null || true; ${STDCP} intl.req ${INSTALLROOT}/lib/lib/intl ;}
+done ${INSTALLROOT}/lib/lib/intl generated
+make ${INSTALLROOT}/lib/lib/m
+make m.req
+make m.c
+done m.c
+make m2.c
+done m2.c
+make m3.c
+done m3.c
+make m4.c
+done m4.c
+make m5.c
+done m5.c
+make m6.c
+done m6.c
+exec - set -
+exec - r='-'
+exec - for i in m.c m2.c m3.c m4.c m5.c m6.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in m -
+exec - do case $p in
+exec - -) if ${CC} -o m.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o m.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > m.req
+exec - rm -f m.exe m m2 m3 m4 m5 m6
+done m.req generated
+exec - test '' = 'm.req' || ${STDCMP} 2>/dev/null -s m.req ${INSTALLROOT}/lib/lib/m || { ${STDMV} ${INSTALLROOT}/lib/lib/m ${INSTALLROOT}/lib/lib/m.old 2>/dev/null || true; ${STDCP} m.req ${INSTALLROOT}/lib/lib/m ;}
+done ${INSTALLROOT}/lib/lib/m generated
+make ${INSTALLROOT}/lib/lib/nsl
+make nsl.req
+make nsl.c
+done nsl.c
+exec - set -
+exec - r='-'
+exec - for i in nsl.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in nsl -
+exec - do case $p in
+exec - -) if ${CC} -o nsl.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o nsl.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > nsl.req
+exec - rm -f nsl.exe nsl
+done nsl.req generated
+exec - test '' = 'nsl.req' || ${STDCMP} 2>/dev/null -s nsl.req ${INSTALLROOT}/lib/lib/nsl || { ${STDMV} ${INSTALLROOT}/lib/lib/nsl ${INSTALLROOT}/lib/lib/nsl.old 2>/dev/null || true; ${STDCP} nsl.req ${INSTALLROOT}/lib/lib/nsl ;}
+done ${INSTALLROOT}/lib/lib/nsl generated
+make ${INSTALLROOT}/lib/lib/socket
+make socket.req
+make socket.c
+done socket.c
+prev nsl.c
+exec - set -
+exec - r='-'
+exec - for i in socket.c nsl.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in socket -
+exec - do case $p in
+exec - -) if ${CC} -o socket.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o socket.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > socket.req
+exec - rm -f socket.exe socket nsl
+done socket.req generated
+exec - test '' = 'socket.req' || ${STDCMP} 2>/dev/null -s socket.req ${INSTALLROOT}/lib/lib/socket || { ${STDMV} ${INSTALLROOT}/lib/lib/socket ${INSTALLROOT}/lib/lib/socket.old 2>/dev/null || true; ${STDCP} socket.req ${INSTALLROOT}/lib/lib/socket ;}
+done ${INSTALLROOT}/lib/lib/socket generated
+make ${INSTALLROOT}/lib/lib/dbm
+make dbm.req
+make db.c
+done db.c
+make gdbm.c
+done gdbm.c
+make gdbm1.c
+make gdbm-ndbm.h implicit
+done gdbm-ndbm.h dontcare virtual
+done gdbm1.c
+make gdbm2.c
+make ndbm.h implicit
+done ndbm.h dontcare virtual
+done gdbm2.c
+exec - set -
+exec - r='-'
+exec - for i in db.c gdbm.c gdbm1.c gdbm2.c
+exec - do if ${CC} -c $i > /dev/null
+exec - then g=
+exec - for p in db - gdbm_compat - gdbm - ndbm - dbm -
+exec - do case $p in
+exec - -) if ${CC} -o dbm.exe $i $g > /dev/null 2>&1
+exec - then ${CC} -o dbm.exe $i > /dev/null 2>&1 || {
+exec - r="$g"
+exec - break 2
+exec - }
+exec - fi
+exec - g=
+exec - ;;
+exec - *) g="$g -l$p"
+exec - ;;
+exec - esac
+exec - done
+exec - fi
+exec - done 2>/dev/null
+exec - echo " $r" > dbm.req
+exec - rm -f dbm.exe db gdbm gdbm1 gdbm2
+done dbm.req generated
+exec - test '' = 'dbm.req' || ${STDCMP} 2>/dev/null -s dbm.req ${INSTALLROOT}/lib/lib/dbm || { ${STDMV} ${INSTALLROOT}/lib/lib/dbm ${INSTALLROOT}/lib/lib/dbm.old 2>/dev/null || true; ${STDCP} dbm.req ${INSTALLROOT}/lib/lib/dbm ;}
+done ${INSTALLROOT}/lib/lib/dbm generated
+done install virtual
+make test
+make test.iffe
+prev iffe
+make iffe.tst
+done iffe.tst
+exec - regress iffe.tst iffe
+done test.iffe virtual
+make test.mamake
+prev mamake
+make mamake.tst
+meta mamake.tst %.rt>%.tst mamake.rt mamake
+make mamake.rt
+done mamake.rt
+exec - if [[ "1" || "mamake.rt" -nt "mamake.tst" ]]
+exec - then mktest --style=regress mamake.rt > mamake.tst
+exec - fi
+done mamake.tst generated
+exec - regress mamake.tst mamake
+done test.mamake virtual
+done test dontcare virtual
diff --git a/src/cmd/INIT/PROBE.mk b/src/cmd/INIT/PROBE.mk
new file mode 100644
index 0000000..9a8553f
--- /dev/null
+++ b/src/cmd/INIT/PROBE.mk
@@ -0,0 +1,13 @@
+/*
+ * @(#)probe (AT&T Bell Laboratories) 11/11/91
+ *
+ * <lang> <tool> :PROBE: *.probe *.sh *
+ *
+ * common probe script installation
+ * generates probe.sh and probe in .
+ */
+
+":PROBE:" : .MAKE .OPERATOR
+ probe.sh : $(LIBDIR)/probe/$(<:O=1)/probe $(>:N=*.(probe|sh))
+ cat $(*) > $(<)
+ $(LIBDIR)/probe/$(<:O=1)/$(<:O=2) :INSTALLDIR: probe $(>:N!=*.(probe|sh))
diff --git a/src/cmd/INIT/RELEASE b/src/cmd/INIT/RELEASE
new file mode 100644
index 0000000..ebed09f
--- /dev/null
+++ b/src/cmd/INIT/RELEASE
@@ -0,0 +1,918 @@
+12-02-29 cc.darwin.i386*: handle default cc vs kernel bittedness
+12-02-29 C+probe: add __TIMESTAMP__ to the nopredefined list
+12-02-29 package.sh: don't assume grep -q or /usr/local/lib in LD_LIBRARY_PATH
+12-02-29 package.sh: fix ksh vs -lcmd compatibility checks
+12-02-23 iffe.sh: checkcc() before checkread() for sensible diagnostics
+12-02-14 package.mk: { --clobber --compare --link=lib*.a* } for --mam=static
+12-02-14 package.mk: export LICENSEFILEDEFAULT instead of LICENSEFILE
+12-02-14 package.sh: handle @(cc|ld).${HOSTTYPE}* intercepts
+12-02-07 package.sh: add { clean clobber } actions
+12-02-02 regress.sh: fix ulimit -c defaults for --nokeep
+12-01-18 regress.sh: add INPUT|OUTPUT|ERROR -e 'filter' to filter before comparison
+12-01-21 package.sh: fix `admin make' bug that created unused $INSTALLROOT/lib
+12-01-21 Makefile: :PACKAGE: license=ast -- oops
+12-01-20 cc.darwin,cc.mvs.390: tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+12-01-12 package.sh: add admin make share closure to handle alternate HOSTTYPEs
+11-12-13 iffe.sh: add /*<NOSTDIO>*/ test code comment to disable default #include <stdio.h>
+11-11-11 C+probe: test for .so before .sl
+11-10-26 package.sh: don't forget about *.pkg for admin update
+11-10-18 cc.*-icc: update and add more
+11-10-11 package.sh: handle package make|view when no source installed
+11-09-11 package.sh: count admin '*** termination code' errors
+11-08-31 mamake.c: add -e, ignore use recursive prereq timestamps
+11-08-29 iffe.sh: add ``set stdio try1.h - try2.h ...''
+11-08-29 iffe.sh: trap EXIT => trap 0 for ancient sh
+11-08-11 iffe.sh: handle ancient sort that doesn't have -k
+11-06-01 make.probe: add more /lib64 logic
+11-05-01 package.sh: fix admin ditto to sync LICENSES too
+11-03-25 package.sh: initialize { $SED $TR } before first use!
+11-03-21 package.sh: fix vpath probes
+11-03-17 iffe.sh: fix cleanup to rm $tmp* instead of $tmp*.*
+11-02-24 package.sh: change curl usage to "curl -L ..."
+11-02-11 package.sh,C+probe,make.probe,mamprobe.sh: add ###.*archiac.*###
+11-02-02 Makefile: add :MAPLIB: check for ancient -lw
+11-02-02 make.probe: handle -print-multi-directory => 64 => /usr/lib64 /lib64
+11-02-02 package.sh: HOSTTYPE=*,*cc*[,-*,...] sets CC [ and CCFLAGS ]
+11-02-02 make.probe: handle gcc $ORIGIN link but exec failure -- gee thanks
+11-01-25 cc.hp.ia64: bundled cc is a pile of shaving cream
+11-01-07 iffe.sh: check debug==3 for is_hdr() failure
+10-11-22 ditto.sh: fix timing problem between |& and exec &p
+10-11-10 package.sh: fix cc cross compile check to use checkcc absolute path
+10-10-10 package.sh: list main env vars at start of make action
+10-10-10 ratz.c: tweak widnows delays
+10-09-10 ratz.c: add _SEAR_ARGS for _SEAR_EXEC
+10-09-01 package.sh: fix ratz from source logic
+10-08-25 package.mk: consolidate license file search in .package.licenses.
+10-08-22 ratz.c: run sear bootstrap command detached
+10-08-20 C+probe: version_stamp only if version_flags works
+10-08-17 package.sh: unset makerules *DIR variables in env
+10-08-15 package.sh: "make" action now lists some env values
+10-08-11 mktest.sh: add "DO command ..."
+10-07-27 rt.sh: handle "rt X=Y ..."
+10-06-29 ratz.c: non-option sear args passed to sear_exec()
+10-06-25 iffe.sh: "api" op chanegd to not do "map-libc" type mappings
+10-06-25 package.sh: "force admin ditto" => no ditto --update option
+10-06-22 C+probe: handle cc that require .[ci] input for version info
+10-06-21 ditto.sh: change default remote access to ssh (about time)
+10-06-12 regress.sh: DISGNOSTICS [ 1 | 0 | pattern ] and fix EXIT for all
+10-06-09 package.sh: add AT&T to usable nmake check
+10-06-06 iffe.sh,iffe.tst: add { api ver } ops
+10-04-22 package.sh: update "html binary|source" NAME/PASSWORD info
+10-04-15 iffe.sh: don't forget candidate headers for hdr|sys!
+10-04-11 WWW.mk: disable man page metarule -- now done by admin-man(1)
+10-02-14 package.sh: $CC verification needs $INSTALLROOT/bin in PATH
+10-02-11 package.sh: fix package admin make report error count
+10-02-02 package.sh: fix write binary bug that did scp on local fs
+10-02-02 package.mk: up to date binary targets must still be in PACKAGE.*.lst
+10-01-01 package.sh: fix premature $INSTALLROOT/bin during cross compile check
+10-01-01 make.probe: handle ['"] in CC.VERSION.STRING
+09-12-04 iffe.sh: add "opt name" to check for name in $PACKAGE_OPTIONS
+09-11-30 mktest.sh: change RESET to STATE.RESET to make it global
+09-11-14 make.probe: use gcc { -print-multi-directory -print-search-dirs }
+09-11-11 package.sh: re-order and combine cc checks
+09-10-27 C+probe,make.probe,probe.win32: add CC.SUFFIX.DEBUG
+09-10-21 iffe.sh,Makefile: test -e is not in ksh88!
+09-10-06 iffe.sh: handle cc -E #error with 0 exit status (sgi)
+09-10-06 package.sh: stub in ar intercept checks -- not used yet
+09-10-06 ar.ibm.risc: add ar intercept because some aix require -Xfoo first!!
+09-09-24 regress.sh: fix UMASK logic to create test support files before umask
+09-08-28 release.c: change docs to mention stdin if no file operands
+09-08-24 package.sh: fix isascii() bug that failed on od(1) trailing space
+09-08-20 make.probe: add CC.SHARED.NAME
+09-08-20 regress.sh: add { JOB CONTINUE EXITED KILL FIFO }
+09-08-11 package.sh: filter lines containing : for package results
+09-07-31 make.probe: add CC.AR.ARFLAGS (for aix ar -xany)
+09-07-31 package.sh,cc.*: fix -dumpmachine to handle 32/64/* bit options
+09-06-24 package.sh: fix admin.db output formatting
+09-05-05 package.sh: export dll hackery environment vars
+09-05-05 package.sh: handle non-identifier hostnames
+09-05-05 mamake.c: pass undefined ${...} identifiers to the shell
+09-05-05 mamake.rt: add macro expansion regression tests
+09-05-01 iffe.sh: fix output initialization *again*
+09-04-28 package.sh: handle admin.db contact field $9
+09-04-15 iffe.sh: add implicit "ini" op to initialize io for subsequent ops
+09-03-31 regress.sh: EXPORT before test => global ENVIRON[]
+09-03-26 package.sh: test fail pattern is 'fail[es]'
+09-03-26 UNIT - ... appends (options) to command line
+09-03-19 TEST.mk: x.tst => x only if x is command target
+09-03-15 regress.sh: add ${MAIN} for base name of main unit
+09-03-10 TEST.mk: add .SOURCE:tests if tests is a dir
+09-03-03 regress.sh: allow command line unit to override UNIT
+09-03-03 mktest.sh: handle IO == $'\n'
+09-02-02 package.sh: delay $INSTALLROOT/bin/.paths generation until mamprobe runs
+09-01-30 cc.mvs.390: c89 balks at [ ()] in -Dname="..."!
+09-01-27 package.sh: add isascii() to use ratz instead of tar
+09-01-20 hurl.sh: add --size=bytes option
+09-01-08 TEST.mk: add test.* prereqs, multiple arg lists with :T=*: binding
+09-01-03 regress.sh: fix UNIT to allow command line override
+09-01-03 mktest.sh: handle TWD
+08-12-24 package.sh: fix cross-compile HOSTTYPE logic
+08-12-15 package.sh,hurl.sh: handle http codes { 301 302 303 }
+08-10-16 make.probe '-fno-stack-protector -fno-stack-protector-all' to cop out!!
+08-09-30 rt.sh: fix ksh93 regression test signal count
+08-09-26 regress.sh: ignore SIGPIPE for SET pipe-input
+08-09-24 package.sh: package only test foo => make --recurse=only recurse tests foo
+08-09-20 make.probe: handle another /usr/bin/file shared lib description
+08-09-20 regress.sh: add --pipefail for SET pipe-input ...
+08-09-17 Makefile: add gdbm1.c for <gdbm-ndbm.h>
+08-09-10 make.probe: add CC.NOPROTECT
+08-08-08 mktest.sh: add --width=width
+08-08-05 dbm.req: favor sleepycat ndbm compatibility
+08-08-04 C+probe: fix stdlib initialization logic
+08-06-24 package.sh: fix $INSTALLROOT/bin/cc intercept time stamp file typo
+08-06-20 TEST.mk: make the localyunit before *.rt => *.tst -- doh
+08-06-20 mktest.sh: prepend $PWD onto PATH for local units -- doh^2
+08-06-11 regress.sh: fix bug that skipped the last test
+08-05-20 regress.sh: add --local to put *.tmp dir in local fs
+08-05-05 regress.sh: add IF command ... ELIF command ... ELSE ... FI
+08-05-01 package.sh: package test => ulimit -c 0
+08-04-28 regress.sh: fix EXPORT quoting
+08-04-28 regress.sh: fix UNIT set check args too
+08-04-24 rt.sh: exit code > 256 => signal termination
+08-04-10 C+probe: change probe_so order to check .so last (macos ld workaround)
+08-04-01 package.sh: handle multiple admin HOSTTYPEs per HOST
+08-03-28 C+probe: add C++ #include <iostream> (no extension) dir probes
+08-03-17 regress.sh: fix trap on EXIT, add terminated note to final tally
+08-02-28 make.probe: fix probe_warn to include ld!
+08-02-02 make.probe: add CC.RUNPATH to match default -L order
+08-01-31 package.sh: check lib64 for LD_LIBRARY_PATH
+08-01-31 iffe.sh: tweak ancient /bin/sh workarounds
+08-01-28 make.probe: darwin ld export dynamic is -force_flat_namespace
+08-01-28 C+probe: handle sgi cc error message but exit 0 botch(es)
+08-01-23 package.sh: fix checksum doc typo
+08-01-09 C+probe: add __FUNCTION__ to the undef (don't check) list
+07-12-14 iffe.sh: add set nooptimize
+07-12-03 package.sh: add LC_ALL=C
+07-11-27 package.sh: fix overaggressive *.md5 cleanup
+07-11-20 iffe.sh: treat exit status >= 250 as normal error with no signal
+07-11-05 package.sh: fix write op error count pattern
+07-11-05 package.mk: fix $(~req) .ver binding
+07-08-11 probe.win32: add cl.exe setuid workaround, CC.VERSION[.STRING]
+07-08-01 package.sh: handle 'package read lcl|tgz'
+07-05-08 regress.sh: execute basename instead of absolute path for short $0
+07-04-27 cc.sgi.mips[34]: for #error to exit non-zero -- a no brainer
+07-04-20 mktest.sh: defer to systems without 'grep -q' -- sigh
+07-04-11 mamprobe.sh: handle $(CC.*) => ${mam_cc_*}, $(...) => ${...}
+07-04-11 make.probe: fix CC.PICBIG probe, default { CC.PIC CC.DLL } to BIG
+07-04-04 iffe.sh: prepend ${tst}${ext} to each .c probe
+07-03-28 package.sh: fix binary tgz architecture type duplication
+07-03-28 package.mk: add binary write PACKAGE.$HOSTTYPE.lst
+07-03-28 iffe.sh: add -F header to mac test
+07-03-23 make.probe: handle file(1) that returns 'archive' for .so
+07-03-22 mamprobe.sh: fix STDED probe for implementations that ignore EOF
+07-03-11 package.sh: add nocopyright and tst => nocopyright
+07-03-11 package.mk: add copyright=0
+07-03-08 C+probe: restore IFS after probe.ini
+07-02-26 mamake.c: expand first of ${mam_lib*} for ${AR}
+07-01-05 package.sh: fix "admin write binary" logic
+07-01-01 iffe.sh: add "cmd" --verbose trace
+07-01-01 iffe.sh: sort => LC_ALL=C sort
+07-01-01 C+probe: LC_ALL=C
+06-12-22 make.probe: lean on gcc -v for stdlib, but preserve /usr/local!
+06-11-23 package.sh: *.md5 are not tarballs -- doh
+06-11-23 iffe.sh: add -F, --features=feature-test-header
+06-11-11 make.probe: favor lib64 over lib for hosttype==*64
+06-10-31 make.probe: add "-ignore-source-dir -iquote" test
+06-10-31 iffe.sh: add status{...} code block
+06-10-11 regress.sh: fix DO to handle {...} (time for regress.tst?)
+06-10-11 package.sh: handle already gunzip'd *.tgz
+06-10-06 iffe.sh: add reference for header content tests
+06-09-27 regress.sh: fix UMASK to do DO too (duh)
+06-09-22 iffe.sh: drop -O for npt tests (for msvc intrinsics)
+06-09-14 cc.darwin: drop -O until gcc 4.* gets its act together
+06-09-11 package.sh: { cc ld ldd } intercepts check ${HOSTTYPE%.*} too
+06-09-08 regress.sh: add PIPE INPUT|OUTPUT for pipe io
+06-09-05 C+probe: add { probe_version version_stamp version_string }
+06-09-05 make.probe: add version stamp comment, CC.VERSION[.STRING]
+06-08-27 regress.sh,mktest.sh: add UMASK
+06-08-25 regress.sh: add -b,--ignore-space,IGNORESPACE
+06-08-25 mktest.sh: add IGNORESPACE
+06-08-24 mktest.sh: handle \000 in data
+06-08-24 regress.sh: handle -f* for INPUT|OUTPUT|ERROR
+06-08-16 package.sh: fix 'install flat' logic
+06-08-11 rt.sh: handle style=shell %K date format
+06-07-17 ratz.c: fix __MVS__ FAR definition
+06-07-17 iffe.sh: "header x.h" -- deprecate "include x.h" for .SCAN.iffe
+06-07-17 package.sh: differentiate urls vs. assignments
+06-06-27 rt.sh: add --failed, --heading
+06-06-27 C+probe,TEST.mk,make.probe,mktest.sh,regress.sh: 'ulimit -c 0'
+06-06-26 cc.darwin.ppc: handle -lcc_dynamic disappearance
+06-06-25 mktest.sh: implement PROG
+06-06-11 Makefile: add -ldbm :MAPLIB:, provide public MAPLIB.mk
+06-05-06 package.sh: add PACKAGE_admin_tail_timeout
+06-05-22 ratz.c: upgrade to zlib-1.2.3
+06-05-09 package.sh: fix admin.db docs
+06-03-11 package.sh: fix `package use - command ...'
+06-03-05 make.probe: work around pedantic bash 3.1 mismatched " in `.`
+06-02-14 package.sh: "results failed test" == "results test failed"
+ cc.sgi.*: add _AST_cc_OPTIONS parameterization, -OPT:Olimit=0
+ cc.linux.ia64-icc: add for intel cc
+06-02-02 package.sh: freebsd stuck with os version for all arch
+06-02-01 package.mk: fix locale logic (tw -d requires dir arg)
+06-01-31 package.sh: require $CC only for make|test
+06-01-30 package.sh,hurl.sh: use the backwards-compatible --http-passwd
+ package.sh: add more pdksh => /bin/sh checks
+06-01-26 package.sh: wget --http-pass => --http-password
+ package.sh: fix wget error logic
+ hurl.sh: wget --http-pass => --http-password
+06-01-11 package.mk: pass package.license.class to make --mam too
+ package.mk: variants=pattern => --variants=pattern
+ package.sh: darwin rel<=7 => darwin7.ppc
+ package.sh: freebsd rel<=4 => freebsd4
+ package.sh: freebsd rel<=5 => freebsd5
+05-12-07 iffe.sh: don't emit <stdio.h> if <sfio.h>|<ast.h> (XXX)
+05-12-05 make.probe: disable readonly.exe core dump via ulimit -c 0
+05-09-22 mktest.sh: add EXEC [ ++NOOUTPUT ++NOERROR ++NOEXIT ]
+05-09-21 mktest.sh: fix --style=shell compare to ignore \r
+05-09-12 TEST.mk: all --force to force %.rt regeneration
+05-09-05 TEST.mk: regenerate from %.rt only if newer, :SAVE: %.tst
+05-08-25 mktest.sh: add
+ TEST.mk: add %.rt=>%.tst for mktest
+05-08-18 package.sh: 'package host cpu' now checks $NPROC first
+05-07-17 iffe.sh: add { define extern include print } ops
+ iffe.sh: accept output{...}end output on success only -- doh
+05-07-01 package.sh: add TARPROBE for tar B flag probe
+05-06-24 package.sh: fix binary read chmod via *.sum
+05-06-06 package.sh: fix KEEP_HOSTTYPE logic to handle synthesized types
+05-06-01 make.probe: verify that cc_pic works for hosted cc
+ cc.lynxos.ppc: make -mshared the default
+ package.sh: note $INSTALLROOT/bin/@(cc|ld|ldd) installation
+05-05-25 make.probe: add CC.INCLUDE.LOCAL instead of -I- in CC.DIALECT
+05-05-24 iffe.sh: really fix grouping logic -- with tests this time
+ package.sh: pipe/socket configuration mismatches => use /bin/sh
+05-04-28 TEST.mk: add $(TESTS)
+05-04-19 package.sh: package results test uses rt if possible
+ iffe.sh: fix 'op var - ... - ...' grouping logic
+05-04-15 rt.sh: handle autom4ate style
+05-04-11 regress.sh: fix unit name when command line unit also specified
+ rt.sh: handle all ast package test output formats
+ package.sh: fix make docs for options passed to underlying make
+05-04-08 package.sh: cp -p makerules.mo to $OK to preserve mtime
+ regress.sh: add "TITLE name" to change TEST output title
+05-04-01 rt.sh: add pretty make test + regress.sh wrapper
+05-03-29 package.sh: test -e path => test -f path -o -d path
+05-03-24 make.probe: fix CC.PICBIG probe to prefer -fPIC over -fpic -- doh
+05-03-19 mamake.c: command line name=var also defines name.FORCE=var
+05-03-11 regress.sh: unset LC_ALL when LC_* EXPORT'd
+ package.sh: old make.out saved in circular make.out.[1-9]
+ mamake.c: sync with nmake :W=O:
+05-03-01 package.sh: fix flat hierarchy initialization
+ package.sh: admin action now properly resets sibling remote logs
+ package.mk: relax unknown/unwritten package messages to warnings
+ package.sh: handle space in command line name=value
+ make.probe: add mvs -Wc,dll,exportall,longname,rent to CC.DLL probe
+05-02-24 package.sh: hosttype *.powerpc => *.ppc
+ cc.lynxos.ppc,ldd.lynxos.ppc: add
+05-02-22 mamake.c: fix { -G --debug-symbols -S --strip-symbols } MAMAKEFLAGS bug
+05-02-20 probe.win32: handle /platformsdk mount
+05-02-19 package.sh,package.mk: add write tst for tgz in tst subdir
+05-02-18 package.sh: accept cc -dumpmachine with 0 or 1 -
+05-02-14 package.sh: handle mutiple architectures per host in admin.db
+ Makefile,package.sh: honor $INSTALLROOT/bin/.paths overrides
+ package.sh: normalize trailing [-_]bits in host type
+ iffe.sh: some ksh-compatible shells don't do *(pattern)
+05-02-11 iffe.sh: back out 05-01-11 child process stdin hijack
+ cc.lynxos.i386: -dynamic instead of -static default
+05-02-10 package.sh: cyg usr/doc => usr/share/doc
+05-02-08 package.sh: drop -m with pax -- delta bug fixed 2005-02-08
+ iffe.sh: work around old bash 0<... redirection bug
+05-02-06 package.mk: source.tgz: update generated files only when they change
+05-02-02 *.sh,*probe: IFS may be unset and { ash bsh } don't on startup -- wow
+05-01-11 package.sh: update setup docs to include authorize+password
+ package.mk: fix .source.cyg final directory edit
+ package.mk: notice=1 for conspicuous empty NOTICE file
+ WWW.mk: fix *-index.html installation
+ filter.sh: retain input file suffix in tmp copy
+ mamexec.c: fix non-contiguous "exec" bug that skipped lines
+ iffe.sh: fix candidate lib test to try grouping subsequent libs
+ iffe.sh: fix child process stdin hijack that skipped input lines
+ iffe.sh: --shell=osh to force read -r compatibility command
+ iffe.sh: chop iffe input leading space before # for KnR compatibility
+05-01-05 package.sh: add ${TAR} ${TARFLAGS} and tar B flag for pipes
+ mamake.c: fix makefile scan to ignore lib*.[hH]
+ iffe.sh: immunize function/symbol tests from aggressive -O
+04-12-28 WWW.mk: add :WWWPAGE: faq.*.mm index generator
+04-12-21 ratz.c: make sure tmp dir is writable -- doh
+04-12-08 iffe.sh: fix dat test for aggressive -O
+04-12-01 iffe.sh: add `include file' to pull in #define's for `exp'
+04-11-11 package.sh: default MAKESKIP is "*[-.]*"
+04-10-22 ratz.c: change docs to note zlib license
+ mamake.c: handle --debug-symbols and --strip-symbols
+ package.sh: make (debug|strip)=1 => --(debug|strip)-symbols
+ package.mk: add :LICENSE: => package.license.class
+ mamake.c: fix recursive order logic
+04-10-18 package.mk: add :LICENSE:, :OMIT: to omit package subdirs
+04-10-11 package.sh: add 'authorize name' and 'password password'
+04-10-01 iffe.sh: double check $static link with ! $static
+ Makefile: add BUILTIN_LIB to $INSTALLROOT/bin/.paths
+ make.probe: add CC.DIALECT EXPORT={ALL,REF,EXT,DLL}
+ package.sh: add BUILTIN_LIB to $INSTALLROOT/bin/.paths
+04-09-21 package.mk: $(init)$(name) is now an implicit prereq
+04-09-09 package.sh: copy makerules.mo to $INSTALLROOT/bin/ok
+04-09-01 package.mk,package.sh: rename *.txt => *.README
+ package.mk: add the runtime package type (no *.[ah])
+ iffe.sh: fix key test reports
+04-08-26 Makefile: { add m2.c m3.c } -lm tests for { frexp[l] ldexp[l] }
+04-08-11 package.mk: handle HOSTTYPE for solaris > 9
+ package.sh: add `checkaout proto' for { make view }
+ package.sh: check for { md5sum md5 }
+ iffe.sh: add {if|elif|else|endif} test ...
+ iffe.sh: add 'exp - expression' and '( expression )'
+ iffe.sh: add 'name = test ...' user defined macros
+ iffe.sh: add '! test ...' negation
+ TEST.mk: add implied { .c .sh } generated prereq
+ cc.darwin.ppc: handle 10.3 -dylib mess
+04-08-01 package.mk: let include handle nested requirements -- duh
+04-07-31 package.sh: attempt a second ping before admin assumes host down
+04-07-26 package.sh: fix hp.ia64 HOSTTYPE
+04-07-23 probe.win32: generalize #include dir order search
+04-07-17 regress.sh: add INPUT -x for chmod +x
+04-07-01 regress.sh: TMP => TWD
+04-06-29 regress.sh: put COMMAND in $TWD too
+04-06-21 regress.sh: mkdir -p INPUT and OUTPUT intermediate dirs
+ TEST.mk: add :TEST: -- to disable .c .sh search
+04-06-18 TEST.mk: add .SCAN.tst
+04-06-17 regress.sh: TEST returns true if active, false otherwise
+ regress.sh: add CD to change test pwd from $TWD
+04-06-16 regress.sh: add TWD for ./unit.tmp override
+ regress.sh: DO now flushes previous test
+ regress.sh: INPUT and OUTPUT handle -f for printf instead of print
+04-06-11 package.sh: make sure $INSTALLROOT/bin is in front of $PATH
+ package.sh: skip nmake if older than 2000-10-31
+04-05-20 package.sh: fix arg vs. package parse with - or '' to disambuguate
+04-05-11 package.sh: package verbose update lists closure for package setup
+ package.sh: add src/lib/libardir to nmake proto bootstrap
+ regress.sh: probe for rm -u vs. chmod -R u+rwx
+04-05-01 package.sh: $CC must be C, not C++; allow release command on $PATH
+04-04-15 make.probe: check probe_libdir false positives
+ package.sh: add lib/package/*.lic src package subdirs
+ package.mk: add mamfile=0 to inhibit Mamfile generation
+ iffe.sh: config name_DECLARED => HAVE_name_DECL
+ iffe.sh: fix mac to handle default value
+04-04-11 iffe.sh: normalize sed [\\\\/] quoting
+04-04-04 package.mk: only checksum generated tarballs
+ mamprobe.sh: add STDCHMOD
+04-04-01 C+probe: set export LANG=C for uniform error messages
+ make.probe: another CC.STDLIB tweak
+ package.sh: fix regress core dump pattern, expand [a-z] match ranges
+04-03-31 Makefile: add intl :MAPLIB: test
+ make.probe: fix CC.STDLIB search; drop CC.* path duplicates
+04-03-28 iffe.sh: drop unused exec $stdin<&0 dup
+04-03-25 Makefile: add iconv :MAPLIB:
+ package.sh: use ${PING:-ping -c 1 -w 4}, allowing admin.db override
+04-03-24 package.mk: add *.md5 checksum for each *.(c|exe|tgz)
+ package.sh: update base change on md5 sum instead of size
+ iffe.sh: adjust case label \ and keyword quoting for ancient /bin/sh
+04-03-22 probe.win32: ncc => nld
+04-03-19 CONVERT.mk: change the instructions and old source dir default
+ package.mk: fix recurse=list check
+ package.mk: add *.md5 checksum for each *.(c|exe|tgz)
+ package.sh: fix update base/delta/sync existence check
+04-03-18 iffe.sh: -d2 does not remove core dumps on exit
+04-03-17 package.sh: fix make recurse arg/action order
+04-02-29 package.sh: add regress action to compare current and previous tests
+ package.sh: fix sgi.mips[23] HOSTTYPE test for old irix cc
+ package.sh: add `export variable ...'
+ package.sh: admin action now handles host name with non-id chars
+ package.sh: non-numeric M T W in admin.db disables that action
+ package.sh: fix admin write binary local vs. shared clash
+ cc.hp.pa: add _AST_CC_hp_pa_DEFAULT=+DAportable
+ cc.hp.pa64: sync with cc.hp.pa
+ cc.ibm.risc: -bnolibpath => -blibpath:/usr/lib:/lib
+ probe.win32: sync with make.probe
+ make.probe: fix last chance dynamic test
+ make.probe: add hp.pa CC.EXPORT.DYNAMIC -Wl,-E
+ make.probe: add ibm.risc CC.EXPORT.DYNAMIC -bexpall
+ make.probe: move probe_dll_def to the end of probe_dll
+ package.mk: capture subcomponent mamfile recursion
+04-02-24 make.probe: strip "..." from cc/ld traces
+ iffe.sh: add ``set [no]define'' to disable macro #define/#undef
+04-02-23 make.probe: rework CC.LD search
+04-02-14 make.probe: add CC.EXPORT.DYNAMIC for main dynamic sym export
+ make.probe: resurrect CC.PIC with separate semantics from CC.DLL
+ make.probe: add CC.SHARED.LD for CC.SHARED linker
+ C+probe: clear DISPLAY to stifle interactive windows
+04-02-11 iffe.sh: handle ``siz void*'', add cross{ ... }end
+ make.probe: add { CC.AR CC.SIZE }, fix cross command search
+ cc.darwin.ppc: change $cc => $CC for old ksh + libast conf bug
+04-02-09 make.probe: drop -nostartfiles from CC.SHARED for C++
+04-02-04 package.sh: fix cross compilation bug that mixed binary formats
+04-02-02 package.sh: package admin now ditto's bin/package too
+04-01-30 cc.sgi.mips3: drop warning 3421
+04-01-11 regress.sh: output label#count for tests in loops
+04-01-05 regress.sh: fix bug that ignored the first SAME
+04-01-04 crossexec.sh: fix typo that did not recognize rcp
+03-12-19 mamake.c: add `foolib:foo:libfoo' to recurse()
+03-10-11 regress.sh: add EXPORT, export COLUMNS=80 for message consistency
+03-09-23 ratz.c: fix tar header number parse bug that skipped to next number
+ regress.sh: rm cleanup now handles files matching -*
+03-09-11 iffe.sh: add unnamed { ... } blocks
+ regress.sh: add COPY from to, like MOVE but comprison still done
+ regress.sh: rm -rfu to handle test dirs w/o u+rwx
+03-08-14 Makfile: add hello.c to the manifest
+03-08-11 package.sh: fix `html binary' generation
+03-06-21 package.sh: fix INITROOT initialization bug
+ package.sh: make sure admin logs exists before tail'ing
+03-06-11 probe.win32: fix $(BINDIR) typo that expanded in sh instead of make
+ cc.mvs.390: return code 4 yields exit code 3 but its *really* ok
+ package.sh: fix onpath function global var conflict
+ make.probe: add CC.DIALECT { GNU -dD }
+ package.mk: add Mamfile to lcl manifest
+03-06-10 package.sh: fix setup action typo that only checked the INIT package
+ package.sh: *.s390x => *.s390-64
+03-06-09 package.mk: add cyg :POSTINSTALL:
+03-06-08 make.probe: fix CC.STDLIB logic
+ hurl.sh: add User-Agent identification
+ package.sh: tweak source and binary installation instructions
+ cc.hp.pa,ld.hp.pa: +-Wl,+cdp,${INSTALLROOT}/lib/: drops abs lib paths
+ ldd.hp.pa: add
+03-06-06 package.sh: fix $INSTALLROOT/bin/ldd check
+ make.probe: add CC.STDLIB verification
+03-06-04 make.probe: add +forceread +noforceread
+03-05-11 hurl.sh: handle http://host:port/path
+03-05-06 package.sh: fix setup action PACKAGEROOT and INIT logic
+03-05-05 package.mk: fix cygwin tarball names
+03-04-30 package.sh: move (cc|ld|ldd).$HOSTTYPE updates from Makefile
+03-04-27 make.probe: fix mvs CC.PREFIX.SHARED "lib" => ""
+ make.probe: add CC.DLL.DIR = $(BINDIR) or $(LIBDIR)
+ make.probe: add { CC.LD.LAZY CC.LD.NOLAZY CC.LD.RECORD CC.LD.NORECORD }
+ probe.win32: sync with latest CC.*
+03-04-25 mamprobe.sh: add args to `. $makeprobe' for ancient sh
+03-04-23 package.mk: fix dup "covered by" licenses
+03-04-22 probe.win32: CC.DIALECT += "LIBPP -I-" for all cc's
+ package.sh: fix admin write binary tarball snarf
+03-04-21 package.mk: package covered *.@(pkg|lic) too
+03-04-15 package.mk: don't generate incremental archives for lcl
+ package.mk: add incremental=[source:1 binary:0] archive control
+ package.sh: generate $INSTALLROOT/bin/cc wrapper for CC != cc
+ package.sh: admin must ditto lib/package/*.@(pkg|lic) too
+ mamake.c: ignore time of ignore prereqs
+ mamake.c: -D2 lists propagated times
+03-04-11 package.mk: tidy up cyg tarballs
+ package.sh: fix old shell clash between get() and $get
+03-04-05 package.mk: restore *.inx generation somehow lost during cyg additions
+ package.sh: add pthread_num_processors_np() last resort for cpu count
+ package.sh: use `make believe' to accept mamake generated files
+ package.sh: handle `make [make-flags] [target ...]'
+ mamake.c: ignore -e
+03-03-21 package.mk: fix cyg old make typo
+ package.sh: switch to `package setup' instructions
+03-03-19 package.sh: add registry checks for `host cpu'
+ package.sh: `results failed' now lists core dump messages
+03-03-17 package.sh: on cygwin verify 'ntsec binmode' in $CYGWIN or die
+ Makefile: install gcc wrapper if no cc
+ package.mk: add :DETAILS: { :README: :EXPORT: :INSTALL: :TEST: } ops
+03-03-12 package.mk: add :DETAILS: for style-specific details
+03-03-11 package.sh: add beta setup/update support
+ TEST.mk: add (TESTCC) prereq for .sh tests
+03-03-07 hurl.sh: add
+03-03-06 iffe.sh: fix lib win32 test cygwin vs native incompatibility
+ iffe.sh: change internal stdio.h guard to handle C++ inline vs. macro
+03-03-03 package.sh: check for curl or wget for update
+ package.sh: add setup action == update read make
+ package.sh: fix packageroot() typo that showed up in non ~user shells
+ mamake.c: treat name+=value args like name=value
+ mamake.c: add ${var?*|value?match?no-match?}
+ mamake.c: fix archive vs. dynamic bind logic
+03-02-28 package.sh: add the "cyg" (cygwin) package type
+ package.mk: add "cyg" stubs, :CATEGORY: for category name(s)
+03-02-25 mamake.c: add -D4 system(3) debug trace
+03-02-24 package.mk: change --mismatch to --corrupt=accept
+03-02-14 ratz.c: add _WIN32 setmode([01],O_BINARY) and fopen "rb"/"wb"
+03-02-12 Makefile: handle getconf LIBPATH with host pattern
+03-01-31 package.mk: fix .lic search
+03-01-30 package.sh: handle { INIT ksh nmake } already installed elsewhere
+ package.sh: admin handles command outside of $PACKAGEROOT/bin
+ Makefile: install $(INSTALLROOT)/lib/make/package.mk
+03-01-28 package.sh: admin remote commands on one line to please syslog
+03-01-23 probe.win32: borland and mingw32 tweaks
+03-01-22 package.sh: fix $CC test to ignore set -x trace -- duh
+03-01-16 ditto.sh: tw --chop on by default
+03-01-14 package.sh: use /bin/cp to copy previous binaries to bin/ok/
+ package.sh: admin now initiates remote exec and copy from local host
+03-01-12 package.sh: handle admin "xxx:" default root
+03-01-03 probe.win32: add /usr/include/borland path truncation workaround
+02-12-10 iffe.sh: add <&$nullin >&$nullout to checkread() $cc
+02-12-06 probe.win32: fix inlcude => include typo, add lcc lib
+ probe.win32: CC.MAKE.OPTIONS = nativepp=0
+02-12-04 mamake.c: fix ${foo-bar} to expand foo if defined
+02-11-28 probe.win32: add C++ and -I- CC.DIALECT checks
+02-11-26 package.sh: package release now checks for second level files
+02-11-22 package.sh: update action now uses HTTP/1.0
+02-11-21 probe.win32: update the vc include dir test
+02-11-20 make.probe: fix CC.LD.ORIGIN typo that expanded make var
+02-11-13 packahe.mk: fix list.install => list.installed typo
+02-11-12 make.probe: add CC.LD.ORIGIN for a.out origin dir relative dll search
+ make.probe: add CC.LD.STRIP for link time a.out strip
+ package.sh: fix package_use vs. PACKAGE_USE check
+02-10-24 WWW.mk: fix bug that required a :WWWBIN: assertion to post
+02-10-23 mamake.c: fix unuinitialized time in make()
+ ratz.c: fix meter buffer overflow
+02-10-20 package.sh: fix lib/probe/C/make/probe update test
+02-10-18 probe.win32: update for mingw
+ make.probe: add bash workaround to SHELLMAGIC test
+ package.sh: work around yet another cygwin hassle
+02-10-17 iffe.sh: short circuit id check for *[-+/\\]*
+02-10-08 regress.sh: unset FIGNORE to avoid rm . errors
+ package.sh: unset FIGNORE to avoid rm . errors
+ package.sh: $CC must at least compile and executable hello world
+02-10-04 package.sh: $INSTALLROOT/lib/package/tgz=>$PACKAGEROOT/lib/package/tgz
+ package.mk: $(ED) => $(STDED), $(EDFLAGS) => $(STDEDFLAGS)
+ iffe.sh: add identifier checks for tests that (implicitly) require them
+ iffe.sh: disambiguate a few --config macros
+02-10-02 iffe.sh: fix shell=bsh `hdr a/b'
+02-09-30 package.sh: handle chmod of -* files
+ package.sh: verify that $SHELL is Bourne compatible
+ package.sh: tighten PACKAGE_USE logic PATH,LIBPATH,etc. validation
+ iffe.sh: fix bug that didn't define mac variable on success
+02-09-22 package.sh: handle admin_action=ditto
+ iffe.sh: --config sizeof(foo) macro is SIZEOF_foo
+ iffe.sh: fix long.long test so it doesn't defeat uwin "typ long.long"
+ mamprobe.sh: convert $("foo") nmake string constants
+02-09-21 mamprobe.sh: "-" info-path writes probe info to stdout
+02-09-11 make.probe: move from nmake src to be part of mamprobe.sh
+ mamprobe: generate from mamprobe.beg C.probe make.probe mamprobe.end
+ mamake.c: pass cc absolute path to mamprobe
+ package.sh: generate mamprobe -- yuk (at least its confined to INIT)
+ iffe.sh: lcl,nxt: drop default sys/ check
+ ditto.sh: tw --logical by default; add --physical
+02-09-10 package.sh: SHELLMAGIC creeps into package too -- duh and fooey
+02-09-09 ditto.sh: test that remote .profile exists before sourcing
+02-09-06 package.sh: don't ditto nfs junk
+ ditto.sh: --show now lists directory ops instead of enumerating all
+02-09-05 ditto.sh: add --remote={rsh|ssh}
+ package.sh: add admin [[{rsh|ssh|-}]:]directory
+02-09-02 iffe.sh: change 'print -r --' to 'print -r -' for ksh86 compatibility
+02-09-01 cc.unix.mc68k: add for ancient 3b1
+02-08-22 package.sh: fix component() to test for components -- duh
+ Makefile: add LICENSE:.DONTCARE to workaround mam
+02-08-11 iffe.sh: provide defaults for LD_* additions
+02-08-07 ratz.c: change -m to use * instead of non-portable inverse video
+02-07-17 mamprobe.sh: close tmp file in trap before rm for cygwin
+ package.sh: fix "type" to handle i1586 (P4)
+ package.sh: add the view action
+02-06-28 package.sh: handle multiple packages for release action
+02-06-27 package.sh: catch sol*.sparc=>sol*.sun4 when CC=gcc
+02-06-14 package.sh: fix admin_action to not include qualifiers
+ package.sh: fix help/html doc typo
+02-06-11 package.sh: fix ditto update doc to `PACKAGEROOT field matching *:*'
+02-06-07 WWW.mk: change substitute $("\n") to \n
+02-06-06 package.sh: clarify output streams for help/html
+02-05-22 mamake.c: fix executable file check to use (S_IXUSR|S_IXGRP|S_IXOTH)
+02-04-04 package.sh: fix update to differentiate *.sun4 and sun4
+02-03-27 package.sh: yacc/bison warning only if both missing
+02-03-24 mamake.c: all shell actions wrapped with -c to avoid #! problems
+02-03-23 package.sh: recover $PACKAGEROOT/bin/package if not in INIT package
+ package.sh: precheck $CC, not `cc'
+ package.sh: fix install to use pax -ps to preserve set-uid/gid
+ package.sh: fix install to use list.installed for existing files only
+02-03-17 package.sh: fix PAX initialization that was sometimes omitted for read
+ package.sh: fix update delta sync fetch
+02-02-14 iffe.sh: fix macro{ }end docs to include "
+ iffe.sh: add dfn to extract #define from headers
+ iffe.sh: handle nxt #include ok but no line sync
+ iffe.sh: drop local header clash logic
+ iffe.sh: add -X, --exclude=dir to exclude -I dirs
+ iffe.sh: lcl,nxt now generate <...> headers instead of "..."
+ package.sh: admin.db root dir matching -* disables host
+ package.mk: fix package.src.pat typo -- too many )
+ package.mk: add { :COVERS: :DESCRIPTION: :REQUIRES: }
+ package.sh: handle { :COVERS: :DESCRIPTION: :REQUIRES: }
+ Makefile: move proto.c generation to the proto component dir
+02-02-02 execrate.sh: add for .exe challenged win32 systems/commands
+ mamprobe.sh: add STD* commands/flags
+ mamake.c: update mamprobe info when older than mamprobe executable
+ package.sh: move ed/ex workaround to mamprobe.sh
+ package.sh: fix `host type' bug that incorrectly assumed sun4 for sol
+ package.sh: add execrate(1) hooks for challenged systems
+ package.sh: add check for { cc ar nm yacc/bison } before make
+ ratz.c: fix "rb" vs. "r" macro tests
+ iffe.sh: add nxt, similar to lcl but defines _nxt_foo for #include
+ iffe.sh,package.sh: remove vaibale from sccs,cvs ident strings -- duh
+02-01-24 C+probe: check CC.DYNAMIC to handle cc that accept but ignore -B*
+ iffe.sh: handle 'mem struct.a.b'
+02-01-22 iffe.sh: cache (internal) `foo vs. struct foo' test results
+ package.sh: uts.370 => uts.390
+02-01-18 package.sh: fix uts hosttype
+02-01-17 package.sh: add 'results failed ...' to list failures only
+ package.sh: change ARCH internal var to all_types to avoid env conflict
+ iffe.sh: fix hdr/lib precheck that missed some -- ouch
+ iffe.sh: fix noexecute test that forgot to check compile first!
+02-01-15 ratz.c: fix path[] type typo
+02-01-01 package.mk: tighten license search
+02-01-08 package.sh: `pwd` => ${PWD:-`pwd`}
+ package.mk: expand license file pattern match
+02-01-04 iffe.sh: fix `exp name "value"' bug that duped "value"
+ iffe.sh: fix initial <sys/types.h> check to honor --config
+01-12-25 iffe.sh: fix bug where -o file restored old file
+01-12-23 package.mk: uniq the closure lists
+01-12-07 ratz.c: fix --meter to retain paths containing " -- "
+01-11-30 ratz.c: use sear_system() to execute; should work on all windows
+01-11-28 ratz.c: fix sear_rm_r() to check SetCurrentDirectory() status
+01-11-26 ditto.sh: drop n+=v for ksh compatibility
+01-11-21 ditto.sh: add rsync script replacement [hey, it works!]
+ package.sh: add [ditto]:directory notation to admin.db
+01-10-31 package.sh: handle *.sum paths with embedded space
+ package.sh: change executable() to onpath()
+ package.sh: executable([!] foo) replaces test [!] -x foo (.exe hack)
+ package.sh: add os2 fix to `host type'
+ mamake.c: add .exe hack
+ iffe.sh: fix intrinsic function lib test
+ mamprobe.sh: update pic probe to match make.probe for linux.ia64
+01-10-30 package.sh: make action skeleton view now checks subdirs
+01-10-20 package.sh: don't recurse into leaf dirs matching $MAKESKIP
+ package.mk: tarball package.notice replaces `license accepted' prompt
+ package.sh: eliminate `license accepted' prompt
+ package.sh: add update to download latest from a url
+ package.sh: use builtin arithmetic when we know its ksh
+ iffe.sh: unkown -> unknown
+01-10-18 package.sh: convert to YYYY-MM-DD delta releases instead of NNNN
+ package.mk: convert to YYYY-MM-DD delta releases instead of NNNN
+ ratz.c: fix -m for paths containing \f\n\r\v
+01-10-16 ratz.c: _SEA_* => SEAR_*
+ ratz.c: preserve stdin for sear_exec()
+ ratz.c: add recursive sear_rm_r() to sear_exec() tmp dir cleanup
+01-10-10 mamprobe.sh: add mam_cc_SHELLMAGIC
+ package.sh: add nfs wakeup call to admin to avoid stale file handles
+01-10-04 cc.darwin.ppc: -flat_namespace is not longer the default (huh)
+01-10-01 package make: prepend $INSTALLROOT/bin/ok to PATH
+ package read: save cpy of bin/package when reading the INIT package
+ mamprobe.sh: allow cc path with optional arguments
+01-09-24 Makefile,package.sh: add $INSTALLROOT/bin/.paths initialization
+01-09-19 package.mk: add recurse to list.package.*
+ package.sh: bootstrap build nmake with _BLD_STATIC for _WIN32
+01-09-11 ratz.c: add _SEA_SKIP & _SEA_COMMAND for self extracting archives
+01-09-07 package.mk: fix output capture to not generate files names with spaces
+01-09-07 package.mk: fix delta release number search
+01-08-11 package.mk: handle single gz executable packages (e.g., for ksh)
+ package.sh: fix package install to require nmake only if no *.sum
+ iffe.sh: drop ancient menu and prompt actions; check ./hdr.h clash
+01-07-17 package: fix use cross compile test to generate files in /tmp
+01-06-27 ratz: handle hard and soft links if possible
+01-06-07 Makefile: fix :MAPLIB: for sco
+01-05-31 crossexec.sh: add
+ iffe.sh: add -x crosstype to run crossexec
+ iffe.sh: exp test now handles pass{}end fail{}end yes{}end no{}end
+ package.sh: add package host canon external-host-type-name
+ package.sh: fix `use USER' lookup for shells that support ~USER
+ cc.*: add -dumpmachine to dump target HOSTTYPE
+01-05-18 iffe.sh: drop $HOME/tmp/t.sh debug trace -- oops
+01-05-01 mamake.c: scan() now handles :PACKAGE: foo:command
+01-04-26 *.sh: expand [a-z][A-Z][0-9] for non-contiguous character codes
+ iffe.sh: fix run *.sh for shells that don't $* across . command
+ cc.mvs.390: recode for /bin/sh
+01-04-25 package.mk: include non cc-g variants by default
+ package.sh: *[._]* => *?[_.]* for mvs.390 /bin/sh
+01-04-24 TEST.mk: no tests for VARIANT=="DLL"
+01-04-22 package.mk,package.sh: tarball text members are ascii encoded
+01-04-18 package.mk: allow package name to be the same as one of its components
+ cc.mvs.390: handle .C .cpp .cxx
+ cc.mvs.390: compensate for -o that does not overwrite
+01-04-01 regress: fix SAME that just skipped it -- we should regress regress!
+ iffe: fix bug that didn't emit _hdr_foo for internal hdr tests
+ iffe: fix lcl bug for cc -E that doesn't emit line syncs
+ ratz: add ascii=>ebcdic conversion for text archive members
+ mamake: fix buffer overlap bug that clobbered the probe file path
+01-03-17 iffe: handle : separator as first arg
+01-03-15 mamake.c,ratz.c,release.c: add <stdlib.h> and <string.h>
+01-02-26 iffe.sh: fix bug that omitted runtime #define for `mac' op
+01-02-22 cc.ibm.risc: handle SF_CLOSE clash in <sfio.h>
+01-02-14 cc.sgi.mips3,cc.sgi.mips4: handle -mips2 -mips3 -mips4 for cross cc
+ C+probe: quote "$cc" when its an argument!
+ mamake: execute actions with $SHELL, ignored signals back to default
+ package.sh: nmake check error output to /dev/null
+ package.sh: fix INIT a.out updates for knr cc
+ package.sh: package list now handles large tgz dirs
+ package.sh: *-ok executables moved to ok/* for *.dll systems
+ iffe.sh: change "exec >&-" to "exec >/dev/null" else linux mkdir fails!
+ mamake: handle `bind -lx [dontcare]'
+01-02-12 ratz.c: fix _PACKAGE_ast includes
+ package.sh: $HOSTTYPE env overrides if $PACKAGEROOT/arch/$HOSTTYPE/
+ package.sh: $CC ^HOSTTYPE=[A-Za-z_0-9.]*$ overrides HOSTTYPE
+ iffe.sh: fix dat code that used previous $tmp.exe
+ iffe.sh: fix dat code for _DLL imports
+01-02-09 iffe.sh: add copy() for shells with the dissappearing here doc bug
+01-02-08 Makefile: guard against null $(CC.HOSTTYPE)
+01-02-06 Makefile: separate out cc,ld,ldd workarounds (so they will be packaged)
+01-02-02 package.sh: fix package use for $INSTALLROOT != */$HOSTTYPE
+ package.sh: create intermediate recursion makefiles when needed
+ package.sh: add $SECONDS to the DEBUG trace prompt
+01-01-01 ratz.c: #ifdef for uwin ncc
+ iffe.sh,package.sh: check PACKAGE_PATH for local installations
+ package.sh: add psrinfo for osf.alpha host cpu
+ package.sh: change pax --meter probe; some hang on /dev/tty
+ package.sh: fix `install flat ARCH'
+ mamake: eliminate loops from scan order
+ C+probe: add probe_verbose -V for aix cc=xlc
+ cc.ibm.risc,ldd.ibm.risc: add
+ package.mk: list refs to top-level licenses only
+ package.mk: add local link table to change log html
+00-12-25 package.sh: `no package archives' is a hard error, duh
+ package.sh: reorder host type logic for lame shells
+ mamake.c: getcwd => getwd for NeXT -- how about posix==default guys
+ iffe.sh: really gross workaround for NeXT -lposix stdout null's
+ iffe.sh: handle cc -E that insists on compiling
+00-12-15 iffe.sh: ancient sh function call blows $*; call only when $# == 0
+ *.sh: `getopts 2>/dev/null` => `(getopts)2>/dev/null` for ancient sh
+ package.sh: fix LD_LIBRARY*_PATH initialization
+ cc.next.m68k: add for _POSIX_SOURCE and linker multiply defined syms
+00-12-12 ratz: add --meter
+ package.sh: a few VPATH fixes
+ Makefile: don't override *.mips* cc if -version not accepted
+00-12-11 package.mk: *.inx now contains name=value
+00-12-07 package.sh: handle PC netscape . => _ pathname mangle
+ WWW.mk: .tar.gz => .tgz
+00-11-27 package.sh: add checklicense() to do license checks at read time
+ package.mk: change component list from preformat to table
+00-10-31 package.mk: *.pkg must assert closure
+ package.mk: add cc- variants to list.package.binary
+ package.sh: omit dups from package list
+ package.sh: invalid arg gives one line Usage
+ package.sh: relax checkaout checks for non-owners
+ package.sh: package use sets NPROC if not already set or [01]
+ proto.c: add $(INSTALLROOT)/include/ast hack
+00-10-26 WWW.mk: add .SOURCE rhs to :WWWPAGE:
+00-10-25 package: fix install
+ package.mk: add list.install
+00-10-22 regress: fix VIEW to skip empty dirs
+00-10-19 package.mk: $(PACKAGEROOT)/bin/nmake => $(PACKAGEROOT)/bin/manmake
+ iffe: validate #define identifiers
+00-10-18 C+probe: mac os10 additions
+ package: add DYLD_LIBRARY_PATH initialization
+ add ldd.$(CC.HOSTTYPE)
+00-10-01 iffe: handle -I* -L* options
+00-09-21 mamake: add libxxx and xxx to makefile ordered prereqs
+00-09-19 C+probe: add probe_longlong
+00-09-11 package: drop manmake and $PACKAGEROOT/bin/nmake
+00-09-08 iffe: verfiy that $cc is a C compiler
+00-06-14 mamprobe: fix win32.* probe
+ mamake: fix bug that used lower view path for generation
+ package: don't clobber $PACKAGEROOT/bin/nmake
+00-06-01 C+probe: fix stdinclude *again*
+ package: fix write delta source to use default pax format
+ package: add disambiguating bias for sgi.mips3 over sgi.mips4
+ package.mk: fix for directory content packages lib ast-locale
+00-05-01 iffe: fix invalid _LIB_ macro identifier
+00-04-11 C+probe: uniq stdinclude and stdlib, fix usrinclude
+00-04-01 regress: fix explicit OUTPUT bug that didn't compare with expected
+00-03-17 package: all archives are .tgz for binary download
+ package: $(PACKAGEROOT)/LICENSES/* in source and binary archives
+ package: implement install and verify actions
+ iffe: add exp, pth file dir ..., fix lib - -lfoo, fix lib - - -la -lb
+ iffe: -L* must affect LD_LIBRARY* hacks for .exe tests -- yuk
+ package.mk: add *.pkg :INDEX:
+00-03-07 package: add admin action
+00-03-06 makefile: install optional make probe override script C+make+probe.lcl
+00-02-14 --- release 1.0 ---
+ ratz: treat "foo/" as a dir, not a regular file
+ package: clarify source and binary installation instructions
+ package: fix so binary packages can install without cc
+ package: "ratz" now a non-archive package (the only one) for bootstrap
+ package: handle VPATH=a:b arg
+ package.mk: "ratz" package adjustments
+ Makefile: use :PACKAGE_INIT: to support binary INIT packages
+ WWW.mk: add :WWWALL:
+ C.probe: fix .so check that let .dll slip through
+ iffe: fix config sh var assignment for HAVE_member_IN_struct
+ iffe: fix config sh var assignment for symbol_DECLARED
+ package: delay PATH export until dll hack exports complete
+ package: don't forget binary package $(INSTALLROOT)/lib(32|64)
+ package: add delta change log for source packages
+00-02-10 mamprobe: add mam_cc_DLLBIG
+ package: fix spelling typos
+ package: add html help output
+ package.mk: beef up source and binary help => html
+00-02-08 package: mkdir man/man[138] in the new arch to cover MAM bug
+00-01-28 package,release: add -rcount to release
+ package: fix linux "host cpu" and "host rating"
+ package: copy *.lic to $PACKAGEBIN for "make" and "write binary"
+ package: fix 'release change log' case match
+00-01-24 package: add copyright action
+ mamprobe: add -D_BLD_DLL to mam_cc_DLL
+00-01-11 package: tsort for package write
+ package: early verification that $CC works
+ package: add non-interactive command arg for use action
+ proto: fix -C intermediate mkdir()
+ mamprobe: unixware.i386 ksh workaround
+ C.probe: move hosttype to C.probe (with unixware.i386 workaround)
+ WWW.mk: fix mm2html option quoting
+ WWW.mk: add .SCAN.mm
+ WWW.mk: don't force static=1; grab dll's instead
+ *.sh: fix getopts test to handle botched implementations like osf.alpha
+ iffe.sh: fix read -r test
+99-12-25 iffe: tweak verbose messages
+ iffe: hand code non-optget getopts parse
+ iffe: fix bash quoting bug again
+ iffe: do test -w . after option parse
+ package: fix PACKAGEROOT search
+99-11-19 --- release 0.2 ---
+99-11-19 first working package & friends
+99-10-31 change from lib0ast to INIT; add MAM and package bootstrap
+ hostinfo: gobbled by package
+99-10-01 iffe: add --config, yes{...}end no{...}end, fix read -r workaround
+99-09-27 iffe: add --all --verbose, --* set options
+99-09-22 regress: -v disables long line truncation
+99-09-11 WWW.mk: WWWDIR and MM2HTMLINFO are now lists searched in $(HOME)
+99-08-11 hostinfo: fix type sgi.mips4
+99-06-24 WWW.mk: add
+99-06-08 hostinfo.sh: ${TMPDIR:-/tmp}
+99-06-07 TEST.mk: add
+99-06-01 iffe: add `siz type' for _siz_type == sizeof(type)
+99-05-11 hostinfo,iffe,regress,use: long options
+99-05-01 C.probe: fix over aggressive stdinclude, e.g., /usr/include/machine
+99-04-01 hostinfo: sgi.mips? -o32 and -n32 checks
+ iffe: check that . is writable
+99-03-17 hostinfo: fix for cc not found
+ dl.c,hello.c,m.c: headers in conditionals to force .DONTCARE
+ C.probe: extra check for include dirs pulled in by <sys/types.h>
+99-03-03 regress: add `UNIT - ...' for extra args
+ Makefile: add (_hosttype_) prereq for cc
+99-01-23 hostinfo: tweak rating, use /proc/cpuinfo if there
+99-01-11 C.probe: shlib before lib, /usr before /
+98-12-25 iffe: work around win32.alpha intrinsic clash with -O
+98-11-11 regress: fix UNIT PATH lookup
+98-11-01 regress: add PROG
+98-10-01 hostinfo: add unixware.*
+ use: export PACKAGE_*
+98-08-11 C.probe: add /usr/include check (for sco CC)
+ hostinfo: handle uwin uname update
+98-05-01 regress: fix bug sometimes didn't list last test
+98-04-01 hostinfo: add cc path arg
+ hostinfo: now works with /bin/sh
+ Makefile: strengthed -lm probe
+98-01-23 Makefile: check for -ldl -lm
+ C.probe: handle gcc -v -E phony include dirs
+ iffe: fix lcl by dropping sort -u -- we need the real first
+ iffe: `mem x' to test if x is a non-opaque struct
+98-01-11 $(INSTALLROOT)/lib32 for sgi.mips3
+ $(INSTALLROOT)/lib64 for sgi.mips4
+ add cc.hp.pa
+98-01-01 cc.sgi.mips*: turn off ld library multiply defined
+97-10-11 regress: add VIEW function for locating data
+97-10-01 Makefile: -ldl test moved to libdll Makefile
+97-08-11 regress: add MOVE
+ regress: add SAME
+ regress: use getopts
+ regress: `EXEC' repeats previous test
+97-07-17 use: tweak PATH and LIBPATH bootstrap order
+ iffe: fix lcl bug that botched pathnames with embedded spaces
+97-06-12 iffe: add npt `needs prototype' test
+97-05-09 hostinfo: mvs.* => mvs.390
+ Makefile: cc.$(_hosttype_) workaround installed here
+ iffe: fix nolink{ ... }end
+ iffe: add [no]static{ ... }end for static link test
+ C.probe: _probe_PATH => _probe_export which must be eval'd
+97-04-01 use: _RLD_ROOT set too
+97-03-17 mm2html: changed inner loop
+ mm2html: handle .if|.ie|.el, .so
+ mm2html: handle different man styles
+ mm2html: differentiate mm/man in some non-obvious cases
+ hostinfo: r5000 is not mips4
+97-02-14 hostinfo: validate type with cc
+96-12-25 C.probe: uwin tweaks
+ iffe: use `...` instead of $(...) for alpha /bin/sh
+ iffe: fix `typ' divide by 0
+ iffe: `lcl' now drops X: prefix
+ iffe: +l* -> -l*
+ iffe: eval around ${...#%...} for bsd /bin/sh
+ use: add sgi.mips LD_LIBRARY<abi>_PATH variants
+ use: add -e to list exports
+ iffe: lcl leaves leading [a-zA-Z]: for dos
+ iffe: fix no{link|output|execute} logic
+ C.probe: don't automatically add /usr/include for non-hosted compilers
+ C.probe: don't automatically place /usr/include last
+ C.probe: check gcc style -v -E for stdinclude usrinclude
+96-11-28 iffe: check BASH_VERSION for IFS botch
+ iffe: typ long.xxx only if sizeof(long xxx) != sizeof(xxx)
+ hostinfo: fix sgi.mips[234] tests
+ hostinfo: fix ncr.i386 tests
+96-10-31 iffe: work around old bsh here doc bug by running separate sh
+96-10-11 iffe: *.iffe and *.iff for iffe src files
+ hostinfo: tighten sgi.mips cpu type check
+96-10-01 C.probe: add probe_libdir to catch alpha /usr/shlib
+96-09-17 iffe: fix typ bug that failed for single id types!
+96-08-31 hostinfo: handle recent sgi hinv cpu changes
+96-07-17 make sure sizeof(long xxx)>sizeof(xxx) for typ long.xxx
+96-05-09 C.probe: drop multiple / in stdinclude
+96-02-29 use: package root must have bin and lib subdir
+ mm2html: add
+ C.probe: probe_members += -whole-archive for gcc
+ iffe: add + fix the blasted `...'...\\...'...`
+96-01-31 use: add pkg dir
+ hostinfo: add tandem
+96-01-01 hostinfo: windows_nt|windows[0-9][0-9] -> win32
+95-11-24 hostinfo: linux-aout.* for non-elf linux
+95-11-11 use: add aix LIBPATH
+95-10-11 hostinfo: no args prints type
+95-08-11 use: add
+95-05-09 save original PATH in _probe_PATH
+ beef up library dir probe
+95-04-01 use c source suffix if it still preserves the dialect
+ add hostinfo
+ add lib/hostinfo/typemap user type map
+ add sol.sun4 cpu count
+ fix C.probe to properly handle C/C++ combined compiler drivers
+ add NeXT to hostinfo
+ bummer: mach has /usr/bin/hostinfo
+95-03-19 fix dialect executable test
+95-03-19 --- release 0.0 ---
diff --git a/src/cmd/INIT/TEST.mk b/src/cmd/INIT/TEST.mk
new file mode 100644
index 0000000..adc4390
--- /dev/null
+++ b/src/cmd/INIT/TEST.mk
@@ -0,0 +1,197 @@
+/*
+ * regression test support
+ *
+ * @(#)TEST.mk (AT&T Research) 2010-05-19
+ *
+ * test management is still in the design phase
+ */
+
+/*
+ * three forms for :TEST:
+ *
+ * :TEST: xxx yyy ...
+ *
+ * $(REGRESS) $(REGRESSFLAGS) xxx.tst
+ * $(REGRESS) $(REGRESSFLAGS) yyy.tst
+ *
+ * :TEST: xxx.tst yyy ...
+ *
+ * $(REGRESS) $(REGRESSFLAGS) xxx.tst yyy ...
+ *
+ * :TEST: xxx.c [ :: test-prereq ... :: ] [ args [ : args ... ] ]
+ *
+ * :TEST: xxx.sh [ :: test-prereq ... :: ] [ args [ : args ... ] ]
+ *
+ * xxx :TEST: prereq ...
+ * [ action ]
+ *
+ * $(*) if no action
+ */
+
+":TEST:" : .MAKE .OPERATOR
+ local B G P S T
+ test : .INSERT .TESTINIT
+ if "$("tests":T=FD)"
+ .SOURCE : tests
+ end
+ P := $(>:O=1)
+ if "$(P:N=*.tst)" && ! "$(@:V)"
+ B := $(P:B)
+ if ! ( T = "$(<:V)" )
+ T := $(B)
+ end
+ test : - test.$(T)
+ eval
+ test.$$(T) : $$(B).tst
+ $$(REGRESS) $$(REGRESSFLAGS) $$(*) $(>:V:O>1)
+ :SAVE: $$(B).tst
+ end
+ elif "$(P:N=*@(.sh|$(.SUFFIX.c:/ /|/G)|$(.SUFFIX.C:/ /|/G)))"
+ B := $(P:B)
+ if ! ( T = "$(<:V)" )
+ T := $(B)
+ end
+ :INSTALLDIR: $(B)
+ $(B) :: $(P) $(*:-l*|*$(CC.SUFFIX.ARCHIVE))
+ if "$(P:N=*.sh)"
+ TESTCC == $(CC)
+ $(B) : (TESTCC)
+ end
+ test : - test.$(T)
+ if "$(@:V)"
+ eval
+ test.$$(T) : $$(B) $(>:V:O>1)
+ set +x; (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0; set -x
+ $(@:V)
+ end
+ elif "$(>:V:O>1)"
+ local I A V X S R=0
+ for A $(>:V:O>1)
+ if A == "::"
+ let R = !R
+ elif A == ":"
+ let I = I + 1
+ test.$(T).$(I) := $(V:V)
+ V =
+ X := $(X:V)$(S)$$(*) $$(test.$(T).$(I):T=*)
+ S = $("\n")
+ elif A != "-l*|*$(CC.SUFFIX.ARCHIVE)"
+ if R
+ test.$(A) : .VIRTUAL .FORCE
+ test.$(T) : test.$(A)
+ else
+ V += $(A:V)
+ end
+ end
+ end
+ if V
+ let I = I + 1
+ test.$(T).$(I) := $(V:V)
+ X := $(X:V)$(S)$$(*) $$(test.$(T).$(I):T=*)
+ end
+ eval
+ test.$$(T) : $$(B)
+ set +x; (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0; set -x
+ $(X:V)
+ end
+ else
+ eval
+ test.$$(T) : $$(B)
+ set +x; (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0; set -x
+ $$(*)
+ end
+ end
+ elif ! "$(<:V)"
+ G = 1
+ for B $(>)
+ if B == "-|--"
+ let G = !G
+ else
+ if ! G
+ T =
+ elif ! ( T = "$(B:A=.COMMAND)" ) && ! "$(B:A=.TARGET)"
+ for S .c .sh
+ if "$(B:B:S=$(S):T=F)"
+ :INSTALLDIR: $(B)
+ $(B) :: $(B:B:S=$(S))
+ T := $(B)
+ break
+ end
+ end
+ end
+ test : - test.$(B)
+ test.$(B) : $(T) - $(B).tst
+ $(REGRESS) $(REGRESSFLAGS) $(*:N=*.tst) $(*:N!=*.tst)
+ :SAVE: $(B).tst
+ end
+ end
+ else
+ if "$(>:V)" || "$(@:V)"
+ P := $(>)
+ T := $(P:O=1)
+ B := $(T:B)
+ if "$(T)" != "$(B)" && "$(T:G=$(B))"
+ :INSTALLDIR: $(B)
+ $(B) :: $(T) $(P:O>1:N=-*)
+ T := $(B)
+ P := $(B) $(P:O>1:N!=-*)
+ end
+ if "$(<:V)"
+ T := $(<:V)
+ end
+ test : - test.$(T)
+ if "$(@:V)"
+ eval
+ test.$$(T) : $$(P) $(>:V:O>1)
+ set +x; (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0; set -x
+ $(@:V)
+ end
+ else
+ test.$(T) : $(P)
+ set +x; (ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0; set -x
+ $(*)
+ end
+ else
+ test : - test.$(<)
+ test.$(<) : $(<).tst $(<:A=.COMMAND)
+ $(REGRESS) $(REGRESSFLAGS) $(*)
+ end
+ end
+
+.TESTINIT : .MAKE .VIRTUAL .FORCE .REPEAT
+ if VARIANT == "DLL"
+ error 1 :DLL: tests skipped
+ exit 0
+ end
+ set keepgoing
+ REGRESSFLAGS &= $(TESTS:@/ /|/G:/.*/--test=&/:@Q)
+
+.SCAN.tst : .SCAN
+ $(@.SCAN.sh)
+ I| INCLUDE@ % |
+
+.ATTRIBUTE.%.tst : .SCAN.tst
+
+MKTEST = mktest
+MKTESTFLAGS = --style=regress
+
+/*
+ * test scripts are only regenerated from *.rt when --force
+ * is specified or the .rt file is newer than the script
+ * otherwise the script is accepted if it exists
+ *
+ * this avoids the case where a fresh build with no state
+ * would regenerate the test script and capture current
+ * behavior instead of expected behavior
+ */
+
+%.tst : %.rt
+ if [[ "$(-force)" || "$(>)" -nt "$(^|<)" ]]
+ then $(MKTEST) $(MKTESTFLAGS) $(>) > $(<)
+ fi
+
+test%.sh test%.out : %.rt
+ if [[ "$(-force)" || "$(>)" -nt "$(^|<:O=1)" ]]
+ then $(MKTEST) --style=shell $(>) > $(<:N=*.sh)
+ $(SHELL) $(<:N=*.sh) --accept > $(<:N=*.out)
+ fi
diff --git a/src/cmd/INIT/WWW.mk b/src/cmd/INIT/WWW.mk
new file mode 100644
index 0000000..4542dae
--- /dev/null
+++ b/src/cmd/INIT/WWW.mk
@@ -0,0 +1,450 @@
+/*
+ * post stuff to WWWDIR for web access
+ * index generated from *.mm
+ */
+
+WWWDIR = wwwfiles public_html
+WWWSAVE =
+WWWSTYLE =
+WWWTYPES =
+
+.WWW.semaphore : .SEMAPHORE
+
+.EXPORT : WWWSTYLE WWWTYPES
+
+/*
+ * item :WWW: [style=frame] [save=pattern] file ...
+ *
+ * `item'.mm generates index.html
+ * other files copied to $(WWWDIR)/`item'
+ * sets up www.bin
+ */
+
+":WWW:" : .MAKE .OPERATOR
+ local A B D I J L X E P R M
+ .WWW.LOCAL .WWW.REMOTE : .DO.NOTHING
+ WWWDIR := $(HOME:X=$(WWWDIR):T=F:O=1)
+ B := $(*:N=*.mm::O=1:B)
+ D := $(WWWDIR)/$(B)
+ M := $(WWWDIR)/man/man1
+ R := $(>:N!=*=*)
+ for I $(>:N=*=*)
+ A := WWW$(I:/=.*//:F=%(upper)s)
+ $(A) := $(I:/.*=//)
+ end
+ (html_info) : $$(MM2HTMLINFO) $$(MM2HTMLINIT)
+ if WWWSTYLE == "frame"
+ %.html %-index.html : %.mm (html_info)
+ $(MM2HTML) $(MM2HTMLFLAGS) $(%:N=faq.*:?> $(<:O=1)?-f $(%) -x?) -o WWWTYPES=$(WWWTYPES:@Q:@Q) $(WWWSOURCE.$(%)) $(>)
+ else
+ %.html : %.mm (html_info)
+ $(MM2HTML) $(MM2HTMLFLAGS) -o WWWTYPES=$(WWWTYPES:@Q:@Q) $(>) $(WWWSOURCE.$(%)) > $(<)
+ end
+ %.html : %.1 (html_info)
+ $(MM2HTML) $(MM2HTMLFLAGS) $(>) $(WWWSOURCE.$(%)) > $(<)
+ %-man.html : $(BINDIR)/% (html_info)
+ ignore $(>) --html 2> $(<)
+ .DO.WWW.MAN : .USE
+ if { test '' = '$(*)' || { strings $(*) | egrep -q '\[\+NAME\?|libcmd\.|cmd[0-9][0-9]\.' ;} ;} && [[ "$( $(<:B) '--???html' -- 2>&1 )" == version=[1-9]* ]]
+ then ( $(<:B) '--??html' -- 2>$(<) ) || true
+ fi
+ if 0
+ $(M)/%.html : .DONTCARE $(INSTALLROOT)/bin/%
+ $(@.DO.WWW.MAN)
+ end
+ if "$(<)"
+ D := $(<)
+ elif ! "$(R)"
+ return
+ end
+ .WWW .WWW.BIN : $(D) $(M) -
+ $(D) $(M) :
+ $(SILENT) test -d $(<) || mkdir $(<)
+ if ( J = "$(R:N=*.mm)" )
+ for I $(J:G=%.html)
+ if I == "*-index.html"
+ O := $(D)/index.html
+ else
+ O := $(I:D=$(D):B:S)
+ end
+ .WWW : $(O)
+ $(O) :COPY: $(I)
+ end
+ end
+ .WWW.req : .FUNCTION
+ return $(*$(%:T=SR):N=-l*:T=F:P=B:N!=-l*|/*)
+ A = 0
+ for I $(R:N!=*.mm)
+ if I == "-"
+ let A = ! A
+ elif I == "-l*"
+ L := $(I:/-l//)
+ if J = "$(.DLL.NAME. $(L) $($(L).VERSION):T=F)"
+ X += $(J)
+ end
+ elif A || "$(I:A=.COMMAND|.ARCHIVE)" || "$(I:D:D:N=$(INSTALLROOT))" || "$(I:N=*-www)"
+ X += $(I)
+ if "$(I:A=.COMMAND)"
+ X += $$(.WWW.req $(I))
+ J := $(I:/-www$//)
+ eval
+ .WWW : $(J:D=$(M):B:S=.html)
+ $(J:D=$(M):B:S=.html) : $(I) $(I:B:S=.1:T=F:?$(I:B:S=.1)??)
+ if strings $$(*:O=1) | egrep -q '\[\+NAME\?|libcmd\.|cmd[0-9][0-9]\.'
+ then $$(IGNORE) $$(*:O=1) '--??html' -- 2>&1
+ elif test '' != '$$(*:N=*.1)'
+ then $$(MM2HTML) $$(*:N=*.1)
+ fi > $$(<)
+ end
+ end
+ else
+ if I == "*.html"
+ $(I) : .TERMINAL
+ end
+ .WWW : $(D)/$(I)
+ $(D)/$(I) :COPY: $(I)
+ end
+ end
+ if "$(X:V)"
+ .WWW.EDIT. : .FUNCTION
+ local E I J
+ for I $(.INSTALL.LIST.:C,^$(INSTALLROOT)/,,:N!=lib/lib/*)
+ for J $(%)
+ if "$(I:B:S)" == "$(J:B:S)"
+ E += -s ',^$(J)$,$(I),'
+ end
+ end
+ end
+ return $(E)
+ .WWW.LIST. : .FUNCTION
+ local E I J
+ for I $(.INSTALL.LIST.:C,^$(INSTALLROOT)/,,:N!=lib/lib/*)
+ for J $(%)
+ if "$(I:B:S)" == "$(J:B:S)"
+ E += $(I)
+ end
+ end
+ end
+ return $(E)
+ .WWW .WWW.BIN : $(D)/$(B)-$(CC.HOSTTYPE).tgz
+ $(D)/$(B)-$(CC.HOSTTYPE).tgz : $(X:V)
+ cat > X.$(tmp).X <<!
+ This archive contains $(CC.HOSTTYPE) binaries for
+ $(.WWW.LIST. $(*))
+ Add the bin directory to PATH and the lib directory
+ to LD_LIBRARY_PATH or its equivalent for your system.
+ Use the --?help and --man options for online help,
+ documentation and contact info.
+ !
+ $(PAX) -wvf $(<) -x tar:gzip -s "/X.$(tmp).X/README/" $(.WWW.EDIT. $(*)) -s ',\(.*\)-www$,bin/\1,' -s ',.*/lib/,lib/,' X.$(tmp).X $(*:N!=-l*)
+ $(RM) -f X.$(tmp).X
+ end
+
+/*
+ * item ... :WWWBIN: index.mm file ... host:arch ...
+ *
+ * home page control
+ * `host' of type `arch' for www.bin files
+ */
+
+":WWWBIN:" : .MAKE .OPERATOR
+ local HOST ITEM ARCH BINS DIRS G
+ .WWW.NOMAN. += $(<)
+ for HOST $(>)
+ TYPE := $(HOST:/.*://)
+ HOST := $(HOST:/:.*//)
+ WWWTYPES += $(TYPE)
+ ARCH := $(PWD:D:C,/$(CC.HOSTTYPE)/,/$(TYPE)/)
+ BINS :=
+ DIRS :=
+ for ITEM $(<)
+ if TYPE == "$(CC.HOSTTYPE)"
+ G := $("index.mm":G=%.html:D=$(WWWDIR)/$(ITEM):B:S)
+ .WWW.LOCAL : $(G)
+ eval
+ $(G) : .JOINT $(ARCH)/$(ITEM)/$(ITEM).mm (html_info) .WWW.semaphore .FORCE
+ cd $$(*:D)
+ $$(MAKE) $$(-) $$(=) www
+ end
+ else
+ BINS += $(WWWDIR)/$(ITEM)/$(ITEM)-$(TYPE).tgz
+ DIRS += $(ARCH)/$(ITEM)
+ end
+ end
+ .WWW.REMOTE : $(BINS)
+ ARCH := $(ARCH:C,/src/.*,,)
+ eval
+ $(BINS) :JOINT: .FORCE .WWW.semaphore
+ rsh $(HOST) "
+ eval \"\`bin/package debug use\`\"
+ PATH=\$PATH:$(PATH):/usr/ccs/bin
+ umask 022
+ for dir in $(DIRS)
+ do cd \$dir
+ $(MAKE) $(-) $(=) --errorid=\$dir www.bin
+ done
+ "
+ end
+ end
+
+/*
+ * :WWWPOST: [ host [ dir [ tmp ] ] ]
+ *
+ * post local $(WWWDIR) to host:dir putting archives in host:tmp/www-*.pax
+ * defaults: host=www dir=$(WWWDIR) tmp=tmp
+ */
+
+":WWWPOST:" : .MAKE .OPERATOR
+ local ( host dir tmp ignore ... ) $(>) www $(WWWDIR:B:S) tmp ignore
+ :ALL: delta.pax
+ .WWW.ALL : .WWW.REMOTE - .WWW.LOCAL
+ eval
+ .POST : .VIRTUAL base.pax delta.pax
+ case "$$(>)" in
+ '') ;;
+ *) $$(>:C,.*,rcp & $(host):$(tmp)/$(dir)-&;,)
+ rsh $(host) '
+ umask 022
+ PATH=$HOME/bin:$PATH
+ cd $(dir)
+ pax -rvf $HOME/$(tmp)/$(dir)-delta.pax -z $HOME/$(tmp)/$(dir)-base.pax
+ '
+ ;;
+ esac
+ end
+ base.pax :
+ cd $(WWWDIR)
+ pax -wvf $(<:P=A) .
+ .base.list. : .FUNCTION
+ local X
+ X := $(sh pax -f $(%:N=*.pax):C,\n, ,G:C,^,$$(WWWDIR)/,)
+ $(X) : .DONTCARE
+ return $(X)
+ delta.pax : .WWW.ALL base.pax $$(.base.list. $$(*))
+ cd $(WWWDIR)
+ pax -wvf $(<:P=A) -z $(*:N=*.pax:P=A) .
+
+.WWW.FAQ : .USE
+ {
+ set -o noglob
+ print .xx title=\"$(<:B:/\..*//) FAQ index\"
+ print .MT 4
+ print .TL
+ print
+ print .H 1 \"$(<:B:/\..*//) FAQ index\"
+ print .BL
+ for i in $(*)
+ do exec < $i || exit 1
+ e=0 l=0 x=y
+ while read -r op a1 a2
+ do case $op in
+ .H) case $e in
+ 0) e=1 ;;
+ 1) print .LE ;;
+ esac
+ print .sp
+ print .LI
+ a2=${a2//\"/}
+ a2=${a2%\ [Ff][Aa][Qq]}
+ f=${i%.*}.html
+ f=${f#*/}
+ print .xx link=\"$f' '$a2\"
+ print .sp
+ print .NL
+ ;;
+ .AL|.BL|.NL)
+ case $x in
+ y) x=x ;;
+ *) x=xx$x ;;
+ esac
+ ;;
+ .LE) x=${x%xx}
+ ;;
+ .LI) case $x in
+ x) x=
+ print .LI
+ ;;
+ esac
+ ;;
+ .sp) case $x in
+ '') x=x ;;
+ esac
+ ;;
+ *) case $x in
+ '') print -r -- $op $a1 $a2 ;;
+ esac
+ ;;
+ esac
+ done
+ case $e in
+ 1) print .LE ;;
+ esac
+ done
+ print .LE
+ } > $(<)
+
+/*
+ * [ dir ] :WWWPAGE: [ source ... ] file.mm file
+ *
+ * *.mm generates *.html
+ * faq.*.mm generates faq.mm
+ * other files copied to $(WWWDIR)[/dir]
+ * files after - (toggle) are just asserted on ::
+ */
+
+":WWWPAGE:" : .MAKE .OPERATOR
+ local B D I J O P Q S X G A
+ A = 0
+ D := $(<:O=1)
+ P := $(>:N!=*=*)
+ S := $(>:N=*=*)
+ if X = "$(P:B:S:N=faq.*.mm)"
+ Q := $(D:+$(D).)faq.mm
+ $(Q) : .WWW.FAQ $(X)
+ P += $(Q)
+ end
+ if D
+ B := $(D:B)
+ if D != "/*"
+ D := $(WWWDIR)/$(D)
+ $(D) :INSTALLDIR:
+ .WWW.LOCAL : $(D)
+ end
+ for I $(<:B)
+ .WWW.LOCAL : $(WWWDIR)/man/man1/$(I).html
+ $(WWWDIR)/man/man1/$(I).html : .DONTCARE
+ end
+ for I $(P)
+ if I == "-"
+ let A = !A
+ continue
+ end
+ if A || I == "$(WWWSAVE)"
+ :: $(I)
+ continue
+ end
+ if "$(I:T=FD)"
+ .SOURCE : $(I)
+ if "$(<)"
+ WWWSOURCE.$(<:O=1) += $(I:T=F:P=L=*)
+ end
+ continue
+ end
+ if I == "*.html"
+ $(I) : .TERMINAL
+ O := $(I)
+ X := $(I)
+ elif ( G = "$(I:G=%.html)" )
+ $(G) : .IMPLICIT $(S) $(I)
+ if $(G:O) > 1
+ for J $(G)
+ if J == "*-index.html"
+ if J == "faq.*.*"
+ continue
+ end
+ O := index.html
+ else
+ O := $(J)
+ end
+ .WWW.LOCAL : $(D)/$(O)
+ $(D)/$(O) :INSTALL: $(J)
+ end
+ continue
+ end
+ if X
+ X := $(I)
+ else
+ X := index
+ end
+ I := $(I:B:S=.html)
+ O := $(X:B:S=.html)
+ else
+ O := $(I)
+ end
+ $(D)/$(O) :INSTALL: $(I)
+ .WWW.LOCAL : $(D)/$(O)
+ end
+ else
+ for I $(P)
+ if I == "-"
+ let A = !A
+ continue
+ end
+ if A || I == "$(WWWSAVE)"
+ :: $(I)
+ continue
+ end
+ if "$(I:T=FD)"
+ .SOURCE : $(I)
+ continue
+ end
+ if I == "*.html"
+ $(I) : .TERMINAL
+ O := $(I)
+ elif ( O = "$(I:G=%.html)" )
+ $(O) : $(S) .IMPLICIT $(I)
+ end
+ for J $(O)
+ if J == "*-index.html"
+ X := index.html
+ else
+ X := $(J)
+ end
+ X := $(WWWDIR)/$(X)
+ .WWW.LOCAL : $(X)
+ $(X) :COPY: $(J)
+ end
+ end
+ end
+
+/*
+ * rhs done by default
+ */
+
+":WWWALL:" : .MAKE .OPERATOR
+ .WWW.ALL : $(>)
+
+":WWWMAN:" : .MAKE .OPERATOR
+ .INIT : .WWW.MAN
+ .WWW.MAN. := $(>)
+ .WWW.MAN : .MAKE .FORCE
+ local H I
+ for I $(.WWW.MAN.)
+ .WWW.LOCAL : $(WWWDIR)/man/man1/$(I:B).html
+ $(WWWDIR)/man/man1/$(I:B).html : .DO.WWW.MAN $(I)
+ end
+ for I $(sh builtin:B)
+ .WWW.LOCAL : $(WWWDIR)/man/man1/$(I).html
+ $(WWWDIR)/man/man1/$(I).html : .DO.WWW.MAN -
+ end
+ for I $("$(BINDIR)/*([!-.])":P=G:B)
+ if I != "*_*"
+ H := $(WWWDIR)/man/man1/$(I).html
+ if ! "$(*$(H))" && I != "$(.WWW.NOMAN.:/ /|/G)"
+ .WWW.LOCAL : $(H)
+ end
+ elif "$(PATH:/:/ /G:X=$(I:/.*_//):T=F:O=1)"
+ H := $(WWWDIR)/man/man1/$(I:/.*_//).html
+ .WWW.LOCAL : $(H)
+ $(H) : .DO.WWW.MAN $(BINDIR)/$(I)
+ end
+ end
+
+.WWW.SED. : .FUNCTION
+ local E T
+ E = s/^\(\.xx.link=.*\)%HOSTTYPE%\(.*\)%HOSTTYPE%\(.*\)/
+ for T $(%)
+ E := $(E:V)\$$("\n").LI\$$("\n")\1$(T)\2$(T)\3
+ end
+ return $(E:V)/
+
+/*
+ * mm scan support
+ */
+
+.SCAN.mm : .SCAN
+ O|S|
+ I|.sn %|A.DONTCARE|M$$(%)|
+ I|.so %|A.DONTCARE|M$$(%)|
+
+.ATTRIBUTE.%.mm : .SCAN.mm
diff --git a/src/cmd/INIT/ar.ibm.risc b/src/cmd/INIT/ar.ibm.risc
new file mode 100755
index 0000000..0247643
--- /dev/null
+++ b/src/cmd/INIT/ar.ibm.risc
@@ -0,0 +1,9 @@
+: stupid stupid stupid to require a non-standard option for ar to work : 2009-10-06 :
+
+op=$1
+shift
+case $op in
+-*) ;;
+*) op=-$op ;;
+esac
+/usr/bin/ar -Xany "$op" "$@"
diff --git a/src/cmd/INIT/cc.darwin b/src/cmd/INIT/cc.darwin
new file mode 100755
index 0000000..081bd43
--- /dev/null
+++ b/src/cmd/INIT/cc.darwin
@@ -0,0 +1,73 @@
+: unix wrapper for mac osx cc : 2012-01-20 :
+
+HOSTTYPE=darwin.generic
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+CC=/usr/bin/cc
+op=init
+for arg
+do case $op in
+ init) op=ld
+ set ''
+ ;;
+ esac
+ case $arg in
+ -c) op=cc
+ ;;
+ -E) op=cpp
+ continue
+ ;;
+ -G) op=dll
+ continue
+ ;;
+ -lc) continue
+ ;;
+ -lm) continue
+ ;;
+ -O) continue
+ ;;
+ esac
+ set "$@" "$arg"
+done
+case $# in
+0) ;;
+*) shift ;;
+esac
+case $* in
+-v) $CC "$@"; exit ;;
+esac
+case $op in
+init) echo "cc: arguments expected" >&2
+ exit 1
+ ;;
+cpp) $CC -E "$@"
+ ;;
+cc) $CC -DCLK_TCK=100 "$@"
+ ;;
+dll) # what a compatibility mess -- surely they can get the apis to play nice
+ tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+ trap "rm -f $tmp" EXIT
+ case `MACOSX_DEPLOYMENT_TARGET=10.3 ld -undefined dynamic_lookup 2>&1` in
+ *undefined*dynamic_lookup*)
+ ld -m -flat_namespace -undefined suppress -dylib -dynamic \
+ -ldylib1.o "$@" -lcc_dynamic -framework System >$tmp 2>&1
+ status=$?
+ ;;
+ *) MACOSX_DEPLOYMENT_TARGET=10.3 $CC -Wl,-flat_namespace -dynamiclib -undefined dynamic_lookup "$@" >$tmp 2>&1
+ status=$?
+ ;;
+ esac
+ egrep -v ' (warning .*multiple definitions|definition) of ' $tmp >&2
+ exit $status
+ ;;
+ld) tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+ trap "rm -f $tmp" EXIT
+ $CC -Wl,-m -DCLK_TCK=100 "$@" >$tmp 2>&1
+ status=$?
+ egrep -v ' (warning .*multiple definitions of|definition of|as lazy binding|not from earlier dynamic) ' $tmp >&2
+ exit $status
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.darwin.i386 b/src/cmd/INIT/cc.darwin.i386
new file mode 100755
index 0000000..9afde8d
--- /dev/null
+++ b/src/cmd/INIT/cc.darwin.i386
@@ -0,0 +1,73 @@
+: unix wrapper for mac osx cc : 2012-02-29 :
+
+HOSTTYPE=darwin.i386
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+CC='/usr/bin/cc -m32'
+op=init
+for arg
+do case $op in
+ init) op=ld
+ set ''
+ ;;
+ esac
+ case $arg in
+ -c) op=cc
+ ;;
+ -E) op=cpp
+ continue
+ ;;
+ -G) op=dll
+ continue
+ ;;
+ -lc) continue
+ ;;
+ -lm) continue
+ ;;
+ -O) continue
+ ;;
+ esac
+ set "$@" "$arg"
+done
+case $# in
+0) ;;
+*) shift ;;
+esac
+case $* in
+-v) $CC "$@"; exit ;;
+esac
+case $op in
+init) echo "cc: arguments expected" >&2
+ exit 1
+ ;;
+cpp) $CC -E "$@"
+ ;;
+cc) $CC -DCLK_TCK=100 "$@"
+ ;;
+dll) # what a compatibility mess -- surely they can get the apis to play nice
+ tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+ trap "rm -f $tmp" EXIT
+ case `MACOSX_DEPLOYMENT_TARGET=10.3 ld -undefined dynamic_lookup 2>&1` in
+ *undefined*dynamic_lookup*)
+ ld -m -flat_namespace -undefined suppress -dylib -dynamic \
+ -ldylib1.o "$@" -lcc_dynamic -framework System >$tmp 2>&1
+ status=$?
+ ;;
+ *) MACOSX_DEPLOYMENT_TARGET=10.3 $CC -Wl,-flat_namespace -dynamiclib -undefined dynamic_lookup "$@" >$tmp 2>&1
+ status=$?
+ ;;
+ esac
+ egrep -v ' (warning .*multiple definitions|definition) of ' $tmp >&2
+ exit $status
+ ;;
+ld) tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+ trap "rm -f $tmp" EXIT
+ $CC -Wl,-m -DCLK_TCK=100 "$@" >$tmp 2>&1
+ status=$?
+ egrep -v ' (warning .*multiple definitions of|definition of|as lazy binding|not from earlier dynamic) ' $tmp >&2
+ exit $status
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.darwin.i386-64 b/src/cmd/INIT/cc.darwin.i386-64
new file mode 100755
index 0000000..9010d96
--- /dev/null
+++ b/src/cmd/INIT/cc.darwin.i386-64
@@ -0,0 +1,73 @@
+: unix wrapper for mac osx cc : 2012-02-29 :
+
+HOSTTYPE=darwin.i386-64
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+CC=/usr/bin/cc
+op=init
+for arg
+do case $op in
+ init) op=ld
+ set ''
+ ;;
+ esac
+ case $arg in
+ -c) op=cc
+ ;;
+ -E) op=cpp
+ continue
+ ;;
+ -G) op=dll
+ continue
+ ;;
+ -lc) continue
+ ;;
+ -lm) continue
+ ;;
+ -O) continue
+ ;;
+ esac
+ set "$@" "$arg"
+done
+case $# in
+0) ;;
+*) shift ;;
+esac
+case $* in
+-v) $CC "$@"; exit ;;
+esac
+case $op in
+init) echo "cc: arguments expected" >&2
+ exit 1
+ ;;
+cpp) $CC -E "$@"
+ ;;
+cc) $CC -DCLK_TCK=100 "$@"
+ ;;
+dll) # what a compatibility mess -- surely they can get the apis to play nice
+ tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+ trap "rm -f $tmp" EXIT
+ case `MACOSX_DEPLOYMENT_TARGET=10.3 ld -undefined dynamic_lookup 2>&1` in
+ *undefined*dynamic_lookup*)
+ ld -m -flat_namespace -undefined suppress -dylib -dynamic \
+ -ldylib1.o "$@" -lcc_dynamic -framework System >$tmp 2>&1
+ status=$?
+ ;;
+ *) MACOSX_DEPLOYMENT_TARGET=10.3 $CC -Wl,-flat_namespace -dynamiclib -undefined dynamic_lookup "$@" >$tmp 2>&1
+ status=$?
+ ;;
+ esac
+ egrep -v ' (warning .*multiple definitions|definition) of ' $tmp >&2
+ exit $status
+ ;;
+ld) tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+ trap "rm -f $tmp" EXIT
+ $CC -Wl,-m -DCLK_TCK=100 "$@" >$tmp 2>&1
+ status=$?
+ egrep -v ' (warning .*multiple definitions of|definition of|as lazy binding|not from earlier dynamic) ' $tmp >&2
+ exit $status
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.hp.ia64 b/src/cmd/INIT/cc.hp.ia64
new file mode 100755
index 0000000..204bd0e
--- /dev/null
+++ b/src/cmd/INIT/cc.hp.ia64
@@ -0,0 +1,13 @@
+: hp.ia64 cc wrapper for reasonable ansi C defaults : 2011-01-25 :
+
+[ /usr/bin/cc -ef /usr/ccs/bin/cc ] || exit 1
+
+: bundled cc -- really, in the face of gcc you ship a sub-par /usr/bin/cc? :
+
+HOSTTYPE=hp.ia64
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+/usr/bin/cc -D_HPUX_SOURCE -D_INCLUDE__STDC_A1_SOURCE -D_INCLUDE_XOPEN_SOURCE_500 "$@"
diff --git a/src/cmd/INIT/cc.hp.pa b/src/cmd/INIT/cc.hp.pa
new file mode 100755
index 0000000..cd5f576
--- /dev/null
+++ b/src/cmd/INIT/cc.hp.pa
@@ -0,0 +1,13 @@
+: hp.pa cc wrapper for reasonable ansi C defaults : 2004-02-29 :
+
+HOSTTYPE=hp.pa
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+_AST_CC_hp_pa_DEFAULT=${_AST_CC_hp_pa_DEFAULT-"+DAportable"}
+
+/opt/ansic/bin/cc -Ae +e -Wl,+s $_AST_CC_hp_pa_DEFAULT \
+ ${INSTALLROOT:+-Wl,+cdp,${INSTALLROOT}/lib/:} \
+ -Wl,+vnocompatwarnings "$@"
diff --git a/src/cmd/INIT/cc.hp.pa64 b/src/cmd/INIT/cc.hp.pa64
new file mode 100755
index 0000000..49f2395
--- /dev/null
+++ b/src/cmd/INIT/cc.hp.pa64
@@ -0,0 +1,11 @@
+: hp.pa64 cc wrapper for reasonable ansi C defaults : 2001-02-11 :
+
+HOSTTYPE=hp.pa64
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+/opt/ansic/bin/cc +D2.0W -Ae +e -Wl,+s \
+ ${INSTALLROOT:+-Wl,+cdp,${INSTALLROOT}/lib/:} \
+ -Wl,+vnocompatwarnings "$@"
diff --git a/src/cmd/INIT/cc.ibm.risc b/src/cmd/INIT/cc.ibm.risc
new file mode 100755
index 0000000..17a8f70
--- /dev/null
+++ b/src/cmd/INIT/cc.ibm.risc
@@ -0,0 +1,63 @@
+: cc wrapper for aix risc xlc : 2009-09-28 :
+
+hosttype=ibm.risc
+
+case $HOSTTYPE in
+$hosttype-64)
+ case " $* " in
+ *" -q64 "*) ;;
+ *) set -- -q64 "$@" ;;
+ esac
+ ;;
+*) case " $* " in
+ *" -q64 "*) HOSTTYPE=$hosttype-64 ;;
+ *) HOSTTYPE=$hosttype ;;
+ esac
+ ;;
+esac
+
+case " $* " in
+*" -dumpmachine "*)
+ echo $HOSTTYPE
+ exit
+ ;;
+esac
+
+bin=/usr/vac/bin
+cc=$bin/xlc
+
+ccflags="-brtl -qhalt=e -qsuppress=1506-224:1506-507"
+case " $@ " in
+*" -G "*)
+ ccflags="$ccflags -berok"
+ ;;
+esac
+if test -x $bin/c99
+then # the xlc optimizer vintage that supports c99 is flawed and causes the ast build to fail #
+ case " $* " in
+ *" -O "*)
+ set '' "$@" ''
+ shift
+ while :
+ do a=$1
+ shift
+ case $a in
+ '') break ;;
+ -O) ;;
+ *) set '' "$@" $a ;;
+ esac
+ shift
+ done
+ ;;
+ esac
+ $cc $ccflags "$@"
+ code=$?
+else export PATH=/bin:$PATH LIBPATH=/usr/lib:/lib
+ ccflags="$ccflags -blibpath:$LIBPATH"
+fi
+$cc $ccflags "$@"
+code=$?
+case $code in
+127|255) code=1 ;;
+esac
+exit $code
diff --git a/src/cmd/INIT/cc.ibm.risc.gcc b/src/cmd/INIT/cc.ibm.risc.gcc
new file mode 100755
index 0000000..5d4d16b
--- /dev/null
+++ b/src/cmd/INIT/cc.ibm.risc.gcc
@@ -0,0 +1,36 @@
+: cc wrapper for aix risc gcc : 2012-02-14 :
+
+hosttype=ibm.risc
+
+case $HOSTTYPE in
+$hosttype-64)
+ case " $* " in
+ *" -maix64 "*) ;;
+ *) set -- -maix64 "$@" ;;
+ esac
+ ;;
+*) case " $* " in
+ *" -maix64 "*) HOSTTYPE=$hosttype-64 ;;
+ *) HOSTTYPE=$hosttype ;;
+ esac
+ ;;
+esac
+
+case " $* " in
+*" -dumpmachine "*)
+ echo $HOSTTYPE
+ exit
+ ;;
+esac
+
+cc=gcc
+ccflags=
+
+case " $@ " in
+*" -shared "*)
+ ccflags="$ccflags -shared -Wl,-G -Wl,-berok"
+ ;;
+*) ccflags="-Wl,-brtl"
+ ;;
+esac
+$cc $ccflags "$@"
diff --git a/src/cmd/INIT/cc.linux.i386-64-icc b/src/cmd/INIT/cc.linux.i386-64-icc
new file mode 100755
index 0000000..4d945bf
--- /dev/null
+++ b/src/cmd/INIT/cc.linux.i386-64-icc
@@ -0,0 +1,22 @@
+: linux.i386-64 icc wrapper : 2011-10-18 :
+
+HOSTTYPE=linux.i386-64-icc
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+icc=$(which icc 2>/dev/null)
+case $icc in
+"") if test -f /etc/profile.d/icc.sh
+ then . /etc/profile.d/icc.sh
+ fi
+ icc=$(which icc 2>/dev/null)
+ case $icc in
+ "") echo icc: not found >&2
+ exit 127
+ ;;
+ esac
+ ;;
+esac
+$icc "$@"
diff --git a/src/cmd/INIT/cc.linux.i386-icc b/src/cmd/INIT/cc.linux.i386-icc
new file mode 100755
index 0000000..09dc25c
--- /dev/null
+++ b/src/cmd/INIT/cc.linux.i386-icc
@@ -0,0 +1,22 @@
+: linux.ia64 icc wrapper : 2011-10-18 :
+
+HOSTTYPE=linux.ia64-icc
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+icc=$(which icc 2>/dev/null)
+case $icc in
+"") if test -f /etc/profile.d/icc.sh
+ then . /etc/profile.d/icc.sh
+ fi
+ icc=$(which icc 2>/dev/null)
+ case $icc in
+ "") echo icc: not found >&2
+ exit 127
+ ;;
+ esac
+ ;;
+esac
+$icc "$@"
diff --git a/src/cmd/INIT/cc.linux.ia64-icc b/src/cmd/INIT/cc.linux.ia64-icc
new file mode 100755
index 0000000..09dc25c
--- /dev/null
+++ b/src/cmd/INIT/cc.linux.ia64-icc
@@ -0,0 +1,22 @@
+: linux.ia64 icc wrapper : 2011-10-18 :
+
+HOSTTYPE=linux.ia64-icc
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+icc=$(which icc 2>/dev/null)
+case $icc in
+"") if test -f /etc/profile.d/icc.sh
+ then . /etc/profile.d/icc.sh
+ fi
+ icc=$(which icc 2>/dev/null)
+ case $icc in
+ "") echo icc: not found >&2
+ exit 127
+ ;;
+ esac
+ ;;
+esac
+$icc "$@"
diff --git a/src/cmd/INIT/cc.lynxos.i386 b/src/cmd/INIT/cc.lynxos.i386
new file mode 100755
index 0000000..acd0d02
--- /dev/null
+++ b/src/cmd/INIT/cc.lynxos.i386
@@ -0,0 +1,81 @@
+: lynxos.i386 cc wrapper with -dynamic default : 2005-02-14 :
+
+HOSTTYPE=lynxos.i386
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=gcc
+
+link=1
+static=0
+set . "$@" /../
+while :
+do shift
+ case $1 in
+ /../) break ;;
+ esac
+ case $1 in
+ *.[cChHiI]|*.[cChHiI][pPxX][pPxX])
+ set . -D__NO_INCLUDE_WARN__ -I/sys/include/kernel -I/sys/include/family/x86 "$@"
+ shift
+ break
+ ;;
+ -o) case $2 in
+ /../) ;;
+ *) x=$1
+ shift
+ set . "$@" "$x"
+ shift
+ ;;
+ esac
+ ;;
+ -static)static=1
+ ;;
+ -l*) case $static in
+ 0) static=n
+ set . -L/lib/shlib "$@"
+ shift
+ ;;
+ esac
+ ;;
+ -[cE]) link=0
+ ;;
+ esac
+ x=$1
+ shift
+ set . "$@" "$x"
+done
+while :
+do case $1 in
+ /../) shift
+ break
+ ;;
+ -l*) case $static in
+ 0) static=n
+ set . -L/lib/shlib "$@"
+ shift
+ ;;
+ esac
+ ;;
+ -[cE]) link=0
+ ;;
+ esac
+ x=$1
+ shift
+ set . "$@" "$x"
+ shift
+done
+case $link:$static in
+1:0) static=n ;;
+esac
+case $static in
+n) specs=/tmp/cc$$.specs
+ trap 'status=$?; rm -f $specs; exit $status' 0 1 2
+ echo '*link: %{shared:-shared} %{static:-static} %{mshared|shared: %{static: %eerror: -shared and -static may not be combined. }}' > $specs
+ $cc -specs=$specs "$@"
+ ;;
+*) $cc "$@"
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.lynxos.ppc b/src/cmd/INIT/cc.lynxos.ppc
new file mode 100755
index 0000000..32738f2
--- /dev/null
+++ b/src/cmd/INIT/cc.lynxos.ppc
@@ -0,0 +1,85 @@
+: lynxos.ppc cc wrapper with -mshared default : 2005-06-01 :
+
+HOSTTYPE=lynxos.ppc
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=gcc
+
+link=1
+static=0
+set . "$@" /../
+while :
+do shift
+ case $1 in
+ /../) break ;;
+ esac
+ case $1 in
+ *.[cChHiI]|*.[cChHiI][pPxX][pPxX])
+ set . -D__NO_INCLUDE_WARN__ -I/sys/include/kernel -I/sys/include/family/ppc "$@"
+ shift
+ break
+ ;;
+ -o) case $2 in
+ /../) ;;
+ *) x=$1
+ shift
+ set . "$@" "$x"
+ shift
+ ;;
+ esac
+ ;;
+ -static)static=1
+ ;;
+ -mshared)
+ static=n
+ continue
+ ;;
+ -l*) case $static in
+ 0) static=n
+ set . -L/lib/shlib "$@"
+ shift
+ ;;
+ esac
+ ;;
+ -[cE]) link=0
+ ;;
+ esac
+ x=$1
+ shift
+ set . "$@" "$x"
+done
+while :
+do case $1 in
+ /../) shift
+ break
+ ;;
+ -l*) case $static in
+ 0) static=n
+ set . -L/lib/shlib "$@"
+ shift
+ ;;
+ esac
+ ;;
+ -[cE]) link=0
+ ;;
+ esac
+ x=$1
+ shift
+ set . "$@" "$x"
+ shift
+done
+case $link:$static in
+1:0) static=n ;;
+esac
+case $static in
+n) specs=/tmp/cc$$.specs
+ trap 'status=$?; rm -f $specs; exit $status' 0 1 2
+ echo '*link: %{shared:-shared} %{static:-static} %{mshared|shared: %{static: %eerror: -shared and -static may not be combined. }}' > $specs
+ $cc -specs=$specs -mshared "$@"
+ ;;
+*) $cc "$@"
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.mvs.390 b/src/cmd/INIT/cc.mvs.390
new file mode 100755
index 0000000..50bc7d5
--- /dev/null
+++ b/src/cmd/INIT/cc.mvs.390
@@ -0,0 +1,279 @@
+: mvs.390 cc wrapper for unix message and exit code semantics : 2012-01-20 :
+
+HOSTTYPE=mvs.390
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+ar=ar
+cc=/bin/c89
+CC=/bin/c++
+ccflags="-D_ALL_SOURCE -Wc,dll"
+objmax=60
+tmpfiles=
+unbotch=
+
+# -n as *first* arg shows but does not do
+# -Wc,exportall => -Wl,dll
+# -Bdynamic => .c,.o dynamic
+# -Bstatic => .c,.o static
+# *.C => cc=$CC
+# *.cpp => cc=$CC
+# *.cxx => cc=$CC
+# no optimization until the optimizer is fixed:
+# -O dropped (no optimization)
+# -0 dropped (no optimization)
+# -1 -O (default level 1 optimization)
+# -2 -2 (maximal level 2 optimization)
+
+let argc=0 cmp=0 dll=0 libc=0 dynamic=1 dynamic_objc=0 static_objc=0 relc=0 botched=0
+case $1 in
+-n) exec=print
+ shift
+ ;;
+*) exec=
+ ;;
+esac
+export _CC_ACCEPTABLE_RC=1
+export _C89_ACCEPTABLE_RC=$_CC_ACCEPTABLE_RC
+export _CXX_ACCEPTABLE_RC=$_CC_ACCEPTABLE_RC
+case " $* " in
+*.C" "*)let dll=2
+ cc=$CC
+ export _CXXSUFFIX=C
+ ;;
+*.cpp" "*)let dll=2
+ cc=$CC
+ export _CXXSUFFIX=cpp
+ ;;
+*.cxx" "*)let dll=2
+ cc=$CC
+ export _CXXSUFFIX=cxx
+ ;;
+esac
+exe=
+xxx=
+while :
+do case $# in
+ 0) break ;;
+ esac
+ arg=$1
+ case $arg in
+ -1) arg=-O
+ ;;
+ -Bdynamic)
+ let dynamic=1
+ ;;
+ -Bstatic)
+ let dynamic=0
+ ;;
+ -c) let cmp=1
+ ;;
+ -D_ALL_SOURCE|-D_ALL_SOURCE=*)
+ arg=
+ ;;
+ -D*[\ \(\)]*)
+ arg=${arg#-D}
+ botch_macro[botched]=${arg%%=*}
+ botch_value[botched]=${arg#*=}
+ let botched=botched+1
+ arg=
+ ;;
+ -o) argv[argc]=$arg
+ let argc=argc+1
+ shift
+ arg=$1
+ exe=$arg
+ rm -f "$exe"
+ ;;
+ -[O0]) arg=
+ ;;
+ -Wc,dll)arg=
+ ;;
+ -Wc,exportall)
+ let dll=1
+ ;;
+ -Wl,dll)arg=
+ let dll=1
+ ;;
+ *.c) if [[ $botched != 0 ]]
+ then src=$arg
+ arg=${arg##*/}
+ unbotch="$unbotch ${arg%.c}.o"
+ arg=__$arg
+ tmpfiles="$tmpfiles $arg"
+ {
+ while [[ $botched != 0 ]]
+ do let botched=botched-1
+ print -r -- "#define ${botch_macro[botched]} ${botch_value[botched]}"
+ done
+ cat $src
+ } > $arg
+ fi
+ ;;
+ *.o) if test 0 != $dynamic
+ then let dynamic_objc=dynamic_objc+1
+ else let static_objc=static_objc+1
+ fi
+ ;;
+ *.x) a=${arg%.x}.a
+ if test -f $a
+ then argv[argc]=$a
+ let argc=argc+1
+ xxx=-Wl,dll
+ case $a in
+ ast.a|*/ast.a)
+ cc="$CC -u_ast_init"
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ case $arg in
+ ?*) argv[argc]=$arg
+ let argc=argc+1
+ ;;
+ esac
+ shift
+done
+
+tmp=/tmp/cc.${USER:-$LOGNAME}.$$.err
+tmpfiles="$tmp $tmpfiles"
+
+# if any dll .o's are in .a then a .x gets generated
+# but the native cc doesn't jcl for the .x
+# -Wl,dll does that, so we nuke the .x and keep the exe
+
+test 0 != $dll && xxx=
+case $xxx in
+?*) case $exe in
+ ?*) a=${exe##*/}
+ a=${a%.*}
+ case $exe in
+ */*) tmpfiles="$tmpfiles ${exe%/*}/${a}.x" ;;
+ *) tmpfiles="$tmpfiles ${a}.x" ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+if test 0 != $dll
+then if test 0 != $cmp
+ then xxx="-D_SHARE_EXT_VARS $xxx"
+ else xxx="-Wl,dll $xxx"
+ fi
+fi
+set -- $xxx "${argv[@]}"
+
+# can't handle more than objmax .o's
+# -r into intermediates doesn't work, but the cat trick does
+# also, the runtime dll file must be executable but cc -Wl,dll forgets
+
+if test 0 != $dll -a \( $dynamic_objc -ge $objmax -o 0 != $static_objc \)
+then unset argv
+ argc=0 libc=0 dynamic=1 dynamic_objc=0 static_objc=0 endc=0
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -Bdynamic)
+ let dynamic=1
+ ;;
+ -Bstatic)
+ let dynamic=0
+ ;;
+ *.o) if test 0 != $dynamic
+ then dynamic_objv[dynamic_objc]=$1
+ let dynamic_objc=dynamic_objc+1
+ else static_objv[static_objc]=$1
+ let static_objc=static_objc+1
+ fi
+ ;;
+ -l*) libv[libc]=$1
+ let libc=libc+1
+ ;;
+ -o) argv[argc]=$1
+ let argc=argc+1
+ shift
+ argv[argc]=$1
+ let argc=argc+1
+ exe=$1
+ ;;
+ *) argv[argc]=$1
+ let argc=argc+1
+ ;;
+ esac
+ shift
+ done
+ if test 0 != $static_objc
+ then case $exe in
+ ?*) $exec $ar cr ${exe%.*}.a "${static_objv[@]}" ;;
+ esac
+ fi
+ if test 0 != $dynamic_objc
+ then cat=0.0.o
+ tmpfiles="$tmpfiles $cat"
+ cat "${dynamic_objv[@]}" > $cat || exit
+ else cat=
+ fi
+ set -- "${argv[@]}" $cat "${libv[@]}"
+fi
+
+# grep through the warning/error messages to get the true exit code
+# some annoying messages are dropped while we're at it
+
+trap 'rm -f $tmpfiles' 0 1 2 15
+$exec $cc $ccflags "$@" 2> $tmp
+code=$?
+for i in $unbotch
+do test -f __$i && mv __$i $i
+done
+typeset -l lc
+while :
+do if read line
+ then lc=$line
+ case $lc in
+ *'#include file'*'not found'*)
+ code=1
+ ;;
+ *'#pragma ignored'*)
+ continue
+ ;;
+ *'definition side file is not defined'*)
+ continue
+ ;;
+ *'step ended with return code 4'*)
+ code=0
+ continue
+ ;;
+ *'step ended with return code'*)
+ code=1
+ continue
+ ;;
+ *'try again'*)
+ code=1
+ continue
+ ;;
+ *'unknown preprocessing directive'*)
+ code=1
+ case $lc in
+ 'warning '*)
+ set -- $line
+ shift
+ line=$*
+ ;;
+ esac
+ ;;
+ *'unresolved writable static references are detected'*)
+ test 0 != $dll && continue
+ ;;
+ esac
+ else case $code:$exe in
+ 0:?*) $exec chmod +x $exe ;;
+ esac
+ exit $code
+ fi
+ echo "$line" >&2
+done < $tmp
diff --git a/src/cmd/INIT/cc.next.i386 b/src/cmd/INIT/cc.next.i386
new file mode 100755
index 0000000..16df709
--- /dev/null
+++ b/src/cmd/INIT/cc.next.i386
@@ -0,0 +1,158 @@
+: next.i386 cc wrapper for unix message and exit code semantics : 1995-05-09 :
+
+HOSTTYPE=next.i386
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+# 1995-05-09 -lposix termios.o waitpid.o setpgid.o *do* work
+# 1994-11-04 -posix has old redirection hole bug
+# -D_POSIX_SOURCE requires <sys/dirent.h> manual fixes
+# libexpr/exeval.c bombs -O, no -O ok
+
+command=cc
+cc="/bin/cc -D_POSIX_SOURCE"
+nooptimize="exeval"
+
+# first check $INSTALLROOT/botch
+
+case $INSTALLROOT in
+"") echo "$command: INSTALLROOT: must be defined and exported" >&2; exit 1 ;;
+esac
+if test ! -d $INSTALLROOT/botch -a -dryrun != "$1"
+then if mkdir $INSTALLROOT/botch
+ then : ok to initialize
+ else echo "$command: $INSTALLROOT/botch must be initialized by the owner of $INSTALLROOT" 2>&1
+ exit 1
+ fi
+ (
+ cd $INSTALLROOT/botch
+ dir=.
+ for i in lib . include sys
+ do case $i in
+ .) dir=.
+ ;;
+ *) case $i in
+ /*) dir=$i ;;
+ *) dir=$dir/$i ;;
+ esac
+ test -d $dir || mkdir $dir
+ ;;
+ esac
+ done
+ if test ! -f include/sys/dirent.h
+ then echo "#include <dirent.h>" > tmp.c
+ header=`$cc -E tmp.c | sed -e '/^#[ ]*1[ ].*\/sys\/dirent\.h"/!d' -e 's/.*"\(.*\)".*/\1/'`
+ sed -e 's/[ ]off_t[ ][ ]*d_off[ ]*;//' $header > include/sys/dirent.h
+ fi
+ if test ! -f lib/libbotch.a
+ then lipo /usr/lib/libposix.a -thin i386 -output tmp.a
+ ar x tmp.a termios.o waitpid.o setpgid.o
+ ar cr lib/libbotch.a *.o
+ ranlib lib/libbotch.a
+ fi
+ rm -f *.[aco]
+ )
+fi
+
+# now slip in our args
+
+case $nooptimize in
+"") nooptimize=.
+ ;;
+*) optimize=
+ for arg in $nooptimize
+ do case $optimize in
+ ?*) optimize="$optimize|" ;;
+ esac
+ optimize="$optimize$arg.[ci]|*/$arg.[ci]"
+ done
+ nooptimize=$optimize
+ ;;
+esac
+set . "$@" .
+noexec=
+library=
+local=
+optimize=
+verbose=
+while :
+do shift
+ arg=$1
+ shift
+ case $arg in
+ .) break
+ ;;
+ -[cES]) library=1
+ ;;
+ -O) optimize=1
+ ;;
+ -v) verbose=1
+ ;;
+ -dryrun)noexec=1
+ verbose=1
+ ;;
+ -I-) case $local in
+ "") local=1
+ set . "$@" -I$INSTALLROOT/botch/include -I- -I$INSTALLROOT/botch/include
+ ;;
+ *) set . "$@" -I- -I$INSTALLROOT/botch/include
+ ;;
+ esac
+ continue
+ ;;
+ -I*|*.[cChHiI]|*.[cChHiI][pPxX][pPxX])
+ case $optimize in
+ 1) eval "
+ case \$arg in
+ $nooptimize)
+ optimize=0
+ ;;
+ esac
+ "
+ ;;
+ esac
+ case $local in
+ "") local=1
+ set . "$@" -I$INSTALLROOT/botch/include "$arg"
+ continue
+ ;;
+ esac
+ ;;
+ -last|*/libast.a)
+ case $library in
+ "") library=1
+ set . "$@" $INSTALLROOT/botch/lib/libbotch.a "$arg" $INSTALLROOT/botch/lib/libbotch.a
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ set . "$@" "$arg"
+done
+case $library in
+"") set . "$@" $INSTALLROOT/botch/lib/libbotch.a
+ shift
+ ;;
+esac
+case $optimize in
+0) set . "$@" .
+ while :
+ do shift
+ arg=$1
+ shift
+ case $arg in
+ .) break ;;
+ -O) set . "$@" ;;
+ *) set . "$@" "$arg" ;;
+ esac
+ done
+ ;;
+esac
+case $verbose in
+?*) echo $cc "$@" ;;
+esac
+case $noexec in
+"") $cc "$@" ;;
+esac
diff --git a/src/cmd/INIT/cc.next.m68k b/src/cmd/INIT/cc.next.m68k
new file mode 100755
index 0000000..1c2f8b5
--- /dev/null
+++ b/src/cmd/INIT/cc.next.m68k
@@ -0,0 +1,9 @@
+: next.m68k cc wrapper that enables posix : 2000-12-15 :
+
+HOSTTYPE=next.m68k
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+/bin/cc -posix -Xlinker -m "$@"
diff --git a/src/cmd/INIT/cc.osf.alpha b/src/cmd/INIT/cc.osf.alpha
new file mode 100755
index 0000000..fe19bb4
--- /dev/null
+++ b/src/cmd/INIT/cc.osf.alpha
@@ -0,0 +1,9 @@
+: osf.alpha cc wrapper with reasonable namespace defaults : 1998-02-04 :
+
+HOSTTYPE=osf.alpha
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+/usr/bin/cc -std -Dnoshare=_noshare_ -Dreadonly=_readonly_ "$@"
diff --git a/src/cmd/INIT/cc.pentium4 b/src/cmd/INIT/cc.pentium4
new file mode 100755
index 0000000..8794cda
--- /dev/null
+++ b/src/cmd/INIT/cc.pentium4
@@ -0,0 +1,26 @@
+: linux.pentium4 gcc wrapper : 2005-10-24 :
+
+HOSTTYPE=linux.pentium4
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+case " $* " in
+*" -O "*)
+ set -A argv -- "$@"
+ set -A nargv
+ integer i j
+ for ((i = j = 0; i < ${#argv[@]}; i++))
+ do if [[ ${argv[i]} == -O ]]
+ then nargv[j++]=-O3
+ nargv[j++]=-march=pentium4
+ else nargv[j++]=${argv[i]}
+ fi
+ done
+ gcc "${nargv[@]}"
+ exit
+ ;;
+esac
+
+gcc "$@"
diff --git a/src/cmd/INIT/cc.sco.i386 b/src/cmd/INIT/cc.sco.i386
new file mode 100755
index 0000000..d0cba57
--- /dev/null
+++ b/src/cmd/INIT/cc.sco.i386
@@ -0,0 +1,9 @@
+: sco.i386 cc wrapper with reasonable binary and namespace : 1998-02-04 :
+
+HOSTTYPE=sco.i386
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+/bin/cc -b elf -D_SVID3 "$@"
diff --git a/src/cmd/INIT/cc.sgi.mips2 b/src/cmd/INIT/cc.sgi.mips2
new file mode 100755
index 0000000..a0e5d33
--- /dev/null
+++ b/src/cmd/INIT/cc.sgi.mips2
@@ -0,0 +1,68 @@
+: sgi.mips2 cc wrapper that generates mips2 binaries : 2006-02-14 :
+
+HOSTTYPE=sgi.mips2
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=/usr/bin/cc
+debug=
+dynamic=-G0
+flags=-OPT:Olimit=0
+ignore=1685,733,1048,1155,1171,1184,1209,1343,3169,3170,3433
+ldignore=15,84,85,13
+optimize=
+
+case $_AST_cc_OPTIONS in
+?*) eval $_AST_cc_OPTIONS ;;
+esac
+case $ignore in
+?*) ignore="-woff $ignore" ;;
+esac
+case $ldignore in
+?*) ifs=$IFS
+ IFS=,
+ v=$ldignore
+ ldignore=
+ for i in $v
+ do ldignore="$ldignore -Wl,-woff,$i"
+ done
+ IFS=$ifs
+ ;;
+esac
+case $debug in
+?*) integer n=0
+ for i
+ do case $i in
+ -g*) case $debug in
+ -) continue ;;
+ esac
+ i=$debug
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+case $optimize in
+?*) integer n=0
+ for i
+ do case $i in
+ -O*) case $optimize in
+ -) continue ;;
+ esac
+ i=$optimize
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+
+if test -d /usr/lib32
+then LD_LIBRARYN32_PATH=/lib32 $cc -32 -mips2 $flags $dynamic $ldignore $ignore "$@"
+else $cc -mips2 $flags $ignore "$@"
+fi
diff --git a/src/cmd/INIT/cc.sgi.mips3 b/src/cmd/INIT/cc.sgi.mips3
new file mode 100755
index 0000000..426317a
--- /dev/null
+++ b/src/cmd/INIT/cc.sgi.mips3
@@ -0,0 +1,110 @@
+: sgi.mips3 cc wrapper that generates mips3 binaries : 2007-04-27 :
+
+HOSTTYPE=sgi.mips3
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+# ld:
+# 15
+# 84
+# 85
+# 134
+# cc:
+# 1685 (first!!) Invalid error number: X.
+# 1035 cpp #error -- 0 exit status by default - botch botch botch
+# 1048
+# 1155
+# 1171 The indicated expression has no effect.
+# 1184 "=" is used where where "==" may have been intended.
+# 1209 The controlling expression is constant.
+# 1343
+# 3169 X not marked as intrinsic because it is not yet declared
+# 3170 X not marked as intrinsic because it is not yet declared
+# 3421 expecting function name #pragma intrinsic (X)
+# 3433 X not marked as intrinsic because it is not yet declared
+# 3434 X not marked as intrinsic because it is not yet declared
+
+cc=/usr/bin/cc
+debug=
+dynamic=-G0
+flags=-OPT:Olimit=0
+fatal=1035
+ignore=1685,733,1048,1155,1171,1184,1209,1343,3169,3170,3421,3433,3434
+ldignore=15,84,85,13
+optimize=
+
+case $_AST_cc_OPTIONS in
+?*) eval $_AST_cc_OPTIONS ;;
+esac
+case $fatal in
+?*) fatal="-diag_error $fatal" ;;
+esac
+case $ignore in
+?*) ignore="-woff $ignore" ;;
+esac
+case $ldignore in
+?*) ifs=$IFS
+ IFS=,
+ v=$ldignore
+ ldignore=
+ for i in $v
+ do ldignore="$ldignore -Wl,-woff,$i"
+ done
+ IFS=$ifs
+ ;;
+esac
+case $debug in
+?*) integer n=0
+ for i
+ do case $i in
+ -g*) case $debug in
+ -) continue ;;
+ esac
+ i=$debug
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+case $optimize in
+?*) integer n=0
+ for i
+ do case $i in
+ -O*) case $optimize in
+ -) continue ;;
+ esac
+ i=$optimize
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+
+case $1 in
+-mips2) if test -d /usr/lib32
+ then LD_LIBRARYN32_PATH=/lib32 $cc -32 -mips2 $flags $dynamic $ldignore $ignore "$@"
+ else $cc -mips2 $flags $ignore "$@"
+ fi
+ ;;
+-mips4) case " $* " in
+ *" -ldl "*)
+ integer n=0
+ for i
+ do case $i in
+ -ldl) ;;
+ *) a[n++]=$i ;;
+ esac
+ done
+ set -- ${a[@]}
+ esac
+ $cc -64 -mips4 $flags $dynamic $fatal $ldignore $ignore "$@"
+ ;;
+*) $cc -n32 -mips3 $flags $dynamic $fatal $ldignore $ignore "$@"
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.sgi.mips3-o32 b/src/cmd/INIT/cc.sgi.mips3-o32
new file mode 100755
index 0000000..a9c6c9c
--- /dev/null
+++ b/src/cmd/INIT/cc.sgi.mips3-o32
@@ -0,0 +1,65 @@
+: sgi.mips3-o32 cc wrapper that generates mips3 o32 binaries : 2006-02-14 :
+
+HOSTTYPE=sgi.mips3-o32
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=/usr/bin/cc
+debug=
+dynamic=-G0
+flags=
+ignore=1685,733,1048,1155,1171,1184,1209,1343,3169,3170,3433
+ldignore=15,84,85,13
+optimize=
+
+case $_AST_cc_OPTIONS in
+?*) eval $_AST_cc_OPTIONS ;;
+esac
+case $ignore in
+?*) ignore="-woff $ignore" ;;
+esac
+case $ldignore in
+?*) ifs=$IFS
+ IFS=,
+ v=$ldignore
+ ldignore=
+ for i in $v
+ do ldignore="$ldignore -Wl,-woff,$i"
+ done
+ IFS=$ifs
+ ;;
+esac
+case $debug in
+?*) integer n=0
+ for i
+ do case $i in
+ -g*) case $debug in
+ -) continue ;;
+ esac
+ i=$debug
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+case $optimize in
+?*) integer n=0
+ for i
+ do case $i in
+ -O*) case $optimize in
+ -) continue ;;
+ esac
+ i=$optimize
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+
+$cc -o32 -mips3 $flags $dynamic $ldignore $ignore "$@"
diff --git a/src/cmd/INIT/cc.sgi.mips4 b/src/cmd/INIT/cc.sgi.mips4
new file mode 100755
index 0000000..1300cd2
--- /dev/null
+++ b/src/cmd/INIT/cc.sgi.mips4
@@ -0,0 +1,90 @@
+: sgi.mips4 cc wrapper that generates mips4 binaries : 2007-04-27 :
+
+HOSTTYPE=sgi.mips4
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=/usr/bin/cc
+debug=
+dynamic=-G0
+flags=-OPT:Olimit=0
+fatal=1035
+ignore=1685,733,1048,1155,1171,1184,1209,1343,3169,3170,3433
+ldignore=15,84,85,13
+optimize=
+
+case $_AST_cc_OPTIONS in
+?*) eval $_AST_cc_OPTIONS ;;
+esac
+case $fatal in
+?*) fatal="-diag_error $fatal" ;;
+esac
+case $ignore in
+?*) ignore="-woff $ignore" ;;
+esac
+case $ldignore in
+?*) ifs=$IFS
+ IFS=,
+ v=$ldignore
+ ldignore=
+ for i in $v
+ do ldignore="$ldignore -Wl,-woff,$i"
+ done
+ IFS=$ifs
+ ;;
+esac
+case $debug in
+?*) integer n=0
+ for i
+ do case $i in
+ -g*) case $debug in
+ -) continue ;;
+ esac
+ i=$debug
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+case $optimize in
+?*) integer n=0
+ for i
+ do case $i in
+ -O*) case $optimize in
+ -) continue ;;
+ esac
+ i=$optimize
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+
+case $1 in
+-mips2) if test -d /usr/lib32
+ then LD_LIBRARYN32_PATH=/lib32 $cc -32 -mips2 $flags $dynamic $ldignore $ignore "$@"
+ else $cc -mips2 $flags $ignore "$@"
+ fi
+ ;;
+-mips3) $cc -n32 -mips3 $flags $dynamic $fatal $ldignore $ignore "$@"
+ ;;
+*) case " $* " in
+ *" -ldl "*)
+ integer n=0
+ for i
+ do case $i in
+ -ldl) ;;
+ *) a[n++]=$i ;;
+ esac
+ done
+ set -- ${a[@]}
+ esac
+ $cc -64 -mips4 $flags $dynamic $fatal $ldignore $ignore "$@"
+ ;;
+esac
diff --git a/src/cmd/INIT/cc.sgi.mips4-n32 b/src/cmd/INIT/cc.sgi.mips4-n32
new file mode 100755
index 0000000..0e1b562
--- /dev/null
+++ b/src/cmd/INIT/cc.sgi.mips4-n32
@@ -0,0 +1,65 @@
+: sgi.mips4-n32 cc wrapper that generates mips4 n32 binaries : 2006-02-14 :
+
+HOSTTYPE=sgi.mips4-n32
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=/usr/bin/cc
+debug=
+dynamic=-G0
+flags=
+ignore=1685,733,1048,1155,1171,1184,1209,1343,3169,3170,3433
+ldignore=15,84,85,13
+optimize=
+
+case $_AST_cc_OPTIONS in
+?*) eval $_AST_cc_OPTIONS ;;
+esac
+case $ignore in
+?*) ignore="-woff $ignore" ;;
+esac
+case $ldignore in
+?*) ifs=$IFS
+ IFS=,
+ v=$ldignore
+ ldignore=
+ for i in $v
+ do ldignore="$ldignore -Wl,-woff,$i"
+ done
+ IFS=$ifs
+ ;;
+esac
+case $debug in
+?*) integer n=0
+ for i
+ do case $i in
+ -g*) case $debug in
+ -) continue ;;
+ esac
+ i=$debug
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+case $optimize in
+?*) integer n=0
+ for i
+ do case $i in
+ -O*) case $optimize in
+ -) continue ;;
+ esac
+ i=$optimize
+ ;;
+ esac
+ a[n++]=$i
+ done
+ set -- ${a[@]}
+ ;;
+esac
+
+$cc -n32 -mips4 $flags $dynamic $ldignore $ignore "$@"
diff --git a/src/cmd/INIT/cc.specialize b/src/cmd/INIT/cc.specialize
new file mode 100755
index 0000000..87077b5
--- /dev/null
+++ b/src/cmd/INIT/cc.specialize
@@ -0,0 +1,35 @@
+: -O* specialization cc wrapper : 2011-11-11 :
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+cc=cc
+
+CCREPLACE='' # these (possibly empty) options replace -O*
+CCALWAYS='' # these (possibly empty) options always set
+
+case $CCREPLACE in
+'') ;;
+*) case " $* " in
+ *" -O"*)
+ set '' "$@" ''
+ shift
+ while :
+ do a=$1
+ shift
+ case $a in
+ '') break
+ ;;
+ -O*) set '' "$@" $CCREPLACE
+ ;;
+ *) set '' "$@" "$a"
+ ;;
+ esac
+ shift
+ done
+ ;;
+ esac
+ ;;
+esac
+$cc $CCALWAYS "$@"
diff --git a/src/cmd/INIT/cc.unix.mc68k b/src/cmd/INIT/cc.unix.mc68k
new file mode 100755
index 0000000..ebdfa0d
--- /dev/null
+++ b/src/cmd/INIT/cc.unix.mc68k
@@ -0,0 +1,76 @@
+: 3B1/PC7300 unix.mc68k cc wrapper for ANSI C : 2002-09-01 :
+
+HOSTTYPE=unix.mc68k
+
+case " $* " in
+*" -dumpmachine "*) echo $HOSTTYPE; exit ;;
+esac
+
+# /bin/cc predates ANSI C; use gcc
+# some headers depend on SYSTEM5 or mc68k being defined
+# headers for Ethernet software are under /usr/ethernet/include
+# both /usr/lib/libnet.a and /usr/lib/libcurses.a define select()
+# -lcurses uses a version of select for napms(), but that
+# implementation always returns an error if given file
+# descriptors to watch
+# the one in -lnet must be used if fds (instead of or in addition to
+# a timeout) are of interest therefore, -lnet should be
+# specified before -lcurses
+# rename(old, new) in /usr/lib/libnet.a fails if new exists
+# (permitted by ANSI/ISO C-1990 7.9.4.2)
+# gcc -fpic doesn't work as there's no _GLOBAL_OFFSET_TABLE symbol
+
+cc="gcc"
+
+exec=
+show=:
+inc=0
+lib=0
+set '' -DSYSTEM5 -Dmc68k "$@" ''
+shift
+while :
+do a=$1
+ shift
+ case $a in
+ '') break
+ ;;
+ -lcurses|libcurses.a|*/libcurses.a)
+ lib=1
+ set '' "$@" -lnet
+ shift
+ ;;
+ -lnet|libnet.a|*/libnet.a)
+ lib=1
+ ;;
+ -o) a=$1
+ shift
+ set '' "$@" -o
+ shift
+ ;;
+ -fpic) continue
+ ;;
+ -n) exec=:
+ continue
+ ;;
+ -v) show=echo
+ continue
+ ;;
+ -*) ;;
+ *) case $inc in
+ 0) inc=1
+ set '' "$@" -I/usr/ethernet/include
+ shift
+ ;;
+ esac
+ ;;
+ esac
+ set '' "$@" "$a"
+ shift
+done
+case $lib in
+0) set '' "$@" -lnet
+ shift
+ ;;
+esac
+$show $cc "$@"
+$exec $cc "$@"
diff --git a/src/cmd/INIT/crossexec.sh b/src/cmd/INIT/crossexec.sh
new file mode 100644
index 0000000..9d73ee2
--- /dev/null
+++ b/src/cmd/INIT/crossexec.sh
@@ -0,0 +1,139 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: cross compiler a.out execution
+
+command=crossexec
+
+tmp=/tmp/cross$$
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) ARGV0="-a $command"
+ USAGE=$'
+[-?
+@(#)$Id: crossexec (AT&T Labs Research) 2004-01-04 $
+]
+'$USAGE_LICENSE$'
+[+NAME?crossexec - cross compiler a.out execution]
+[+DESCRIPTION?\bcrossexec\b runs a cross-compiled \acommand\a in an environment
+ that supports a cross-compilation architecture different from the
+ current host. The cross environment is determined by \acrosstype\a,
+ usually a host type name produced by \bpackage\b(1). \acrosstype\a
+ is used to find an entry in \b$HOME/.crossexec\b that specifies
+ the cross compiler host and access details.]
+[+?The exit status of \bcrossexec\b is the exit status of \acommand\a.]
+[+CROSS ENVIRONMENT FILE?\b$HOME/.crossexec\b contains one line for each
+ supported \acrosstype\a. Each line contains 5 tab separated fields.
+ Field default values are specified as \b-\b. The fields are:]{
+ [+crosstype?The host type produced by \bpackage\b(1).]
+ [+host?The host name.]
+ [+user?The user name on \ahost\a. The default is the current user.]
+ [+dir?The directory to copy \acommand\a and execute it. The default
+ is the \auser\a \b$HOME\b on \ahost\a.]
+ [+shell?The command used to get shell access to \ahost\a. Currently
+ only \brsh\b and \bssh\b are supported.]
+ [+copy?The command used to copy \acommand\a to \ahost\a. Currently
+ only \brcp\b and \bscp\b are supported.]
+}
+[n:show?Show the underlying commands but do not execute.]
+
+crosstype command [ option ... ] [ file ... ]
+
+[+SEE ALSO?\brcp\b(1), \brsh\b(1), \bscp\b(1), \bssh\b(1)]
+'
+ ;;
+*) ARGV0=""
+ USAGE="crosstype command [ option ... ] [ file ... ]"
+ ;;
+esac
+
+usage()
+{
+ OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+}
+
+exec=
+
+# get the options and operands
+
+while getopts $ARGV0 "$USAGE" OPT
+do case $OPT in
+ n) exec=echo ;;
+ *) usage ;;
+ esac
+done
+shift $OPTIND-1
+case $# in
+[01]) usage ;;
+esac
+
+type=$1
+shift
+cmd=$1
+shift
+
+# get the host info
+
+info=$HOME/.$command
+if test ! -r $info
+then echo "$command: $info: not found" >&2
+ exit 1
+fi
+ifs=${IFS-'
+ '}
+while :
+do IFS=' '
+ read hosttype hostname usr dir sh cp
+ code=$?
+ IFS=$ifs
+ case $code in
+ 0) ;;
+ *) echo "$command: $type: unknown cross compiler host type" >&2
+ exit 1
+ ;;
+ esac
+ case $hosttype in
+ $type) break ;;
+ esac
+done < $info
+
+# fill in the defaults
+
+case $usr in
+-) cpu= shu= ;;
+*) cpu=${usr}@ shu="-l $usr" ;;
+esac
+case $dir in
+-) dir= ;;
+esac
+case $sh in
+''|-) sh=ssh ;;
+esac
+case $cp in
+''|-) cp=scp ;;
+scp) cp="$cp -q" ;;
+esac
+
+trap "rm -f $tmp" 0 1 2 3 15
+$exec $cp $cmd $cpu$hostname:$dir </dev/null || exit 1
+cmd=./${cmd##*/}
+$exec $sh $shu $hostname "cd $dir; LD_LIBRARY_PATH=: $cmd $@ </dev/null 2>/dev/null; code=\$?; rm -f $cmd; echo $command: exit \$code >&2" </dev/null 2>$tmp
+exit `sed -e '/^'$command': exit [0-9][0-9]*$/!d' -e 's/.* //' $tmp`
diff --git a/src/cmd/INIT/db.c b/src/cmd/INIT/db.c
new file mode 100644
index 0000000..5a3a7c1
--- /dev/null
+++ b/src/cmd/INIT/db.c
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for sleepycat dbm compatibility
+ */
+
+#define DB_DBM_HSEARCH 1
+
+#if DB_DBM_HSEARCH
+#include <db.h>
+#endif
+
+int
+main()
+{
+ DBM* dbm = 0;
+
+ dbm_close(dbm);
+ return 0;
+}
diff --git a/src/cmd/INIT/ditto.sh b/src/cmd/INIT/ditto.sh
new file mode 100644
index 0000000..1141a0d
--- /dev/null
+++ b/src/cmd/INIT/ditto.sh
@@ -0,0 +1,460 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: replicate directory hierarchies
+
+COMMAND=ditto
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) ARGV0="-a $COMMAND"
+ USAGE=$'
+[-?
+@(#)$Id: ditto (AT&T Labs Research) 2010-11-22 $
+]
+'$USAGE_LICENSE$'
+[+NAME?ditto - replicate directory hierarchies]
+[+DESCRIPTION?\bditto\b replicates the \asource\a directory hierarchy
+ to the \adestination\a directory hierarchy. Both \asource\a and
+ \adestination\a may be of the form
+ [\auser\a@]][\ahost\a:]][\adirectory\a]]. At least one of
+ \ahost\a: or \adirectory\a must be specified. The current user is used
+ if \auser@\a is omitted, the local host is used if \ahost\a: is
+ omitted, and the user home directory is used if \adirectory\a is
+ omitted.]
+[+?Remote hosts and files are accessed via \bssh\b(1) or \brsh\b(1). \bksh\b(1),
+ \bpax\b(1), and \btw\b(1) must be installed on the local and remote hosts.]
+[+?For each source file \bditto\b does one of these actions:]{
+ [+chmod|chown?change the mode and/or ownership of the destination
+ file to match the source]
+ [+copy?copy the source file to the destination]
+ [+delete?delete the destination file]
+ [+skip?the destination file is not changed]
+}
+[+?The source and destination hierarchies are generated by \btw\b(1) with
+ the \b--logical\b option. An \b--expr\b option may
+ be specified to prune the search. The \btw\b searches are relative to
+ the \asource\a and \adestination\a directories.]
+[c:checksum?Copy if the \btw\b(1) 32x4 checksum mismatches.]
+[d:delete?Delete \adestination\a files that are not in the \asource\a.]
+[e:expr?\btw\b(1) select expression.]:[tw-expression]
+[m!:mode?Preserve file mode.]
+[n:show?Show the operations but do not exectute.]
+[o:owner?Preserve file user and group ownership.]
+[p:physical?Generate source and destination hierarchies by \btw\b(1) with
+ the \b--physical\b option.]
+[r:remote?The remote access protocol; either \bssh\b or
+ \brsh\b.]:[protocol:=ssh]
+[u:update?Copy only if the \asource\a file is newer than the
+ \adestination\a file.]
+[v:verbose?Trace the operations as they are executed.]
+[D:debug?Enable the debug trace.]
+
+source destination
+
+[+SEE ALSO?\brdist\b(1), \brsync\b(1), \brsh\b(1), \bssh\b(1), \btw\b(1)]
+'
+ ;;
+*) ARGV0=""
+ USAGE="de:[tw-expression]mnouvD source destination"
+ ;;
+esac
+
+usage()
+{
+ OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+}
+
+parse() # id user@host:dir
+{
+ typeset id dir user host
+ id=$1
+ dir=$2
+ (( debug || ! exec )) && print -r $id $dir
+ if [[ $dir == *@* ]]
+ then
+ user=${dir%%@*}
+ dir=${dir#${user}@}
+ else
+ user=
+ fi
+ if [[ $dir == *:* ]]
+ then
+ host=${dir%%:*}
+ dir=${dir#${host}:}
+ else
+ host=
+ fi
+ if [[ $user ]]
+ then
+ user="-l $user"
+ if [[ ! $host ]]
+ then
+ host=$(hostname)
+ fi
+ fi
+ eval ${id}_user='$user'
+ eval ${id}_host='$host'
+ eval ${id}_dir='$dir'
+}
+
+# initialize
+
+typeset -A chown chmod
+typeset tw cp rm link
+integer ntw=0 ncp=0 nrm=0 nlink=0 n
+
+typeset src_user src_host src_path src_type src_uid src_gid src_perm src_sum
+typeset dst_user dst_host dst_path dst_type dst_uid dst_gid dst_perm dst_sum
+integer src_size src_mtime src_eof
+integer dst_size dst_mtime dst_eof
+
+integer debug=0 delete=0 exec=1 mode=1 owner=0 update=0 verbose=0 logical
+
+typeset remote=ssh trace
+typeset checksum='"-"' pax="pax"
+typeset paxreadflags="" paxwriteflags="--write --format=tgz --nosummary"
+
+tw[ntw++]=tw
+(( logical=ntw ))
+tw[ntw++]=--logical
+tw[ntw++]=--chop
+tw[ntw++]=--ignore-errors
+tw[ntw++]=--expr=sort:name
+
+# grab the options
+
+while getopts $ARGV0 "$USAGE" OPT
+do case $OPT in
+ c) checksum=checksum ;;
+ d) delete=1 ;;
+ e) tw[ntw++]=--expr=\"$OPTARG\" ;;
+ m) mode=0 ;;
+ n) exec=0 verbose=1 ;;
+ o) owner=1 ;;
+ p) tw[logical]=--physical ;;
+ r) remote=$OPTARG ;;
+ u) update=1 ;;
+ v) verbose=1 ;;
+ D) debug=1 ;;
+ *) usage ;;
+ esac
+done
+shift $OPTIND-1
+if (( $# != 2 ))
+then usage
+fi
+tw[ntw++]=--expr=\''action:printf("%d\t%d\t%s\t%s\t%s\t%-.1s\t%o\t%s\t%s\n", size, mtime, '$checksum', uid, gid, mode, perm, path, symlink);'\'
+if (( exec ))
+then
+ paxreadflags="$paxreadflags --read"
+fi
+if (( verbose ))
+then
+ paxreadflags="$paxreadflags --verbose"
+fi
+
+# start the source and destination path list generators
+
+parse src "$1"
+parse dst "$2"
+
+# the |& command may exit before the exec &p
+# the print sync + read delays the |& until the exec &p finishes
+
+if [[ $src_host ]]
+then ($remote $src_user $src_host "{ test ! -f .profile || . ./.profile ;} && cd $src_dir && read && ${tw[*]}") 2>&1 |&
+else (cd $src_dir && read && eval "${tw[@]}") 2>&1 |&
+fi
+exec 5<&p 7>&p
+print -u7 sync
+exec 7>&-
+
+if [[ $dst_host ]]
+then ($remote $dst_user $dst_host "{ test ! -f .profile || . ./.profile ;} && cd $dst_dir && read && ${tw[*]}") 2>&1 |&
+else (cd $dst_dir && read && eval "${tw[@]}") 2>&1 |&
+fi
+exec 6<&p 7>&p
+print -u7 sync
+exec 7>&-
+
+# scan through the sorted path lists
+
+if (( exec ))
+then
+ src_skip=*
+ dst_skip=*
+else
+ src_skip=
+ dst_skip=
+fi
+src_path='' src_eof=0
+dst_path='' dst_eof=0
+ifs=${IFS-$' \t\n'}
+IFS=$'\t'
+while :
+do
+ # get the next source path
+
+ if [[ ! $src_path ]] && (( ! src_eof ))
+ then
+ if read -r -u5 text src_mtime src_sum src_uid src_gid src_type src_perm src_path src_link
+ then
+ if [[ $text != +([[:digit:]]) ]]
+ then
+ print -u2 $COMMAND: source: "'$text'"
+ src_path=
+ continue
+ fi
+ src_size=$text
+ elif (( dst_eof ))
+ then
+ break
+ elif (( src_size==0 ))
+ then
+ exit 1
+ else
+ src_path=
+ src_eof=1
+ fi
+ fi
+
+ # get the next destination path
+
+ if [[ ! $dst_path ]] && (( ! dst_eof ))
+ then
+ if read -r -u6 text dst_mtime dst_sum dst_uid dst_gid dst_type dst_perm dst_path dst_link
+ then
+ if [[ $text != +([[:digit:]]) ]]
+ then
+ print -u2 $COMMAND: destination: $text
+ dst_path=
+ continue
+ fi
+ dst_size=$text
+ elif (( src_eof ))
+ then
+ break
+ elif (( dst_size==0 ))
+ then
+ exit 1
+ else
+ dst_path=
+ dst_eof=1
+ fi
+ fi
+
+ # determine the { cp rm chmod chown } ops
+
+ if (( debug ))
+ then
+ [[ $src_path ]] && print -r -u2 -f $': src %8s %10s %s %s %s %s %3s %s\n' $src_size $src_mtime $src_sum $src_uid $src_gid $src_type $src_perm "$src_path"
+ [[ $dst_path ]] && print -r -u2 -f $': dst %8s %10s %s %s %s %s %3s %s\n' $dst_size $dst_mtime $dst_sum $dst_uid $dst_gid $dst_type $dst_perm "$dst_path"
+ fi
+ if [[ $src_path == $dst_path ]]
+ then
+ if [[ $src_type != $dst_type ]]
+ then
+ rm[nrm++]=$dst_path
+ if [[ $dst_path != $dst_skip ]]
+ then
+ if [[ $dst_type == d ]]
+ then
+ dst_skip="$dst_path/*"
+ print -r rm -r "'$dst_path'"
+ else
+ dst_skip=
+ print -r rm "'$dst_path'"
+ fi
+ fi
+ fi
+ if [[ $src_type == l ]]
+ then if [[ $src_link != $dst_link ]]
+ then
+ cp[ncp++]=$src_path
+ if [[ $src_path != $src_skip ]]
+ then
+ src_skip=
+ print -r cp "'$src_path'"
+ fi
+ fi
+ elif [[ $src_type != d ]] && { (( update && src_mtime > dst_mtime )) || (( ! update )) && { (( src_size != dst_size )) || [[ $src_sum != $dst_sum ]] ;} ;}
+ then
+ if [[ $src_path != . ]]
+ then
+ cp[ncp++]=$src_path
+ if [[ $src_path != $src_skip ]]
+ then
+ src_skip=
+ print -r cp "'$src_path'"
+ fi
+ fi
+ else
+ if (( owner )) && [[ $src_uid != $dst_uid || $src_gid != $dst_gid ]]
+ then
+ chown[$src_uid.$src_gid]="${chown[$src_uid.$src_gid]} '$src_path'"
+ if [[ $src_path != $src_skip ]]
+ then
+ src_skip=
+ print -r chown $src_uid.$src_gid "'$src_path'"
+ fi
+ if (( (src_perm & 07000) || mode && src_perm != dst_perm ))
+ then
+ chmod[$src_perm]="${chmod[$src_perm]} '$src_path'"
+ if [[ $src_path != $src_skip ]]
+ then
+ src_skip=
+ print -r chmod $src_perm "'$src_path'"
+ fi
+ fi
+ elif (( mode && src_perm != dst_perm ))
+ then
+ chmod[$src_perm]="${chmod[$src_perm]} '$src_path'"
+ if [[ $src_path != $src_skip ]]
+ then
+ src_skip=
+ print -r chmod $src_perm "'$src_path'"
+ fi
+ fi
+ fi
+ src_path=
+ dst_path=
+ elif [[ ! $dst_path || $src_path && $src_path < $dst_path ]]
+ then
+ if [[ $src_path != . ]]
+ then
+ cp[ncp++]=$src_path
+ if [[ $src_path != $src_skip ]]
+ then
+ if [[ $src_type == d ]]
+ then
+ src_skip="$src_path/*"
+ print -r cp -r "'$src_path'"
+ else
+ src_skip=
+ print -r cp "'$src_path'"
+ fi
+ fi
+ fi
+ src_path=
+ elif [[ $dst_path ]]
+ then
+ if (( delete ))
+ then
+ rm[nrm++]=$dst_path
+ if [[ $dst_path != $dst_skip ]]
+ then
+ if [[ $dst_type == d ]]
+ then
+ dst_skip="$dst_path/*"
+ print -r rm -r "'$dst_path'"
+ else
+ dst_skip=
+ print -r rm "'$dst_path'"
+ fi
+ fi
+ fi
+ dst_path=
+ fi
+done
+IFS=$ifs
+
+(( exec )) || exit 0
+
+# generate, transfer and execute the { rm chown chmod } script
+
+if (( ${#rm[@]} || ${#chmod[@]} || ${#chown[@]} ))
+then
+ {
+ if (( verbose ))
+ then
+ print -r -- set -x
+ fi
+ print -nr -- cd "'$dst_dir'"
+ n=0
+ for i in ${rm[@]}
+ do
+ if (( --n <= 0 ))
+ then
+ n=32
+ print
+ print -nr -- rm -rf
+ fi
+ print -nr -- " '$i'"
+ done
+ for i in ${!chown[@]}
+ do
+ n=0
+ for j in ${chown[$i]}
+ do
+ if (( --n <= 0 ))
+ then
+ n=32
+ print
+ print -nr -- chown $i
+ fi
+ print -nr -- " $j"
+ done
+ done
+ for i in ${!chmod[@]}
+ do
+ n=0
+ for j in ${chmod[$i]}
+ do
+ if (( --n <= 0 ))
+ then
+ n=32
+ print
+ print -nr -- chmod $i
+ fi
+ print -nr -- " $j"
+ done
+ done
+ print
+ } | {
+ if (( ! exec ))
+ then
+ cat
+ elif [[ $dst_host ]]
+ then
+ $remote $dst_user $dst_host sh
+ else
+ $SHELL
+ fi
+ }
+fi
+
+# generate, transfer and read back the { cp } tarball
+
+if (( ${#cp[@]} ))
+then
+ {
+ cd $src_dir &&
+ print -r -f $'%s\n' "${cp[@]}" |
+ $pax $paxwriteflags
+ } | {
+ if [[ $dst_host ]]
+ then
+ $remote $dst_user $dst_host "{ test ! -f .profile || . ./.profile ;} && { test -d \"$dst_dir\" || mkdir -p \"$dst_dir\" ;} && cd \"$dst_dir\" && gunzip | $pax $paxreadflags"
+ else
+ ( { test -d "$dst_dir" || mkdir -p "$dst_dir" ;} && cd "$dst_dir" && gunzip | $pax $paxreadflags )
+ fi
+ }
+ wait
+fi
diff --git a/src/cmd/INIT/dl.c b/src/cmd/INIT/dl.c
new file mode 100644
index 0000000..c710ad6
--- /dev/null
+++ b/src/cmd/INIT/dl.c
@@ -0,0 +1,33 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for -ldl
+ */
+
+#ifndef dlopen
+#include <dlfcn.h>
+#endif
+
+int
+main()
+{
+ dlopen("libdl.so",0);
+ return 0;
+}
diff --git a/src/cmd/INIT/execrate.sh b/src/cmd/INIT/execrate.sh
new file mode 100644
index 0000000..71ba78d
--- /dev/null
+++ b/src/cmd/INIT/execrate.sh
@@ -0,0 +1,179 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: wrapper for .exe challenged win32 systems/commands
+
+command=execrate
+
+bins='/bin /usr/bin /usr/sbin'
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) ARGV0="-a $command"
+ USAGE=$'
+[-?
+@(#)$Id: execrate (AT&T Labs Research) 2002-02-02 $
+]
+'$USAGE_LICENSE$'
+[+NAME?execrate - wrapper for .exe challenged commands]
+[+DESCRIPTION?\bexecrate\b runs \acommand\a after checking the \afile\a
+ operands for standard semantics with respect to \bwin32\b \b.exe\b
+ suffix conventions. This command is only needed on \bwin32\b
+ systems that inconsistently handle \b.exe\b across library and
+ command interfaces. \acommand\a may be one of \bcat\b(1), \bchmod\b(1),
+ \bcmp\b(1), \bcp\b(1), \bln\b(1), \bmv\b(1), or \brm\b(1).
+ Only the 2 argument forms of \bcp\b, \bln\b and \bmv\b are handled.
+ Unsupported commands and commands requiring no change are
+ silently executed.]
+[+?With no arguments \bexecrate\b exits with status 0 if the current system
+ is \b.exe\b challenged, 1 if the current system is normal.]
+[n:show?Show the underlying commands but do not execute.]
+
+command [ option ... ] file ...
+
+[+SEE ALSO?\bwebster\b(1)]
+'
+ usage()
+ {
+ OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+ }
+ exec=1
+ while getopts $ARGV0 "$USAGE" OPT
+ do case $OPT in
+ n) exec=0 ;;
+ *) usage ;;
+ esac
+ done
+ shift `expr $OPTIND - 1`
+ ;;
+*) usage()
+ {
+ echo "Usage: execrate [ -n ] [ command [ option ... ] file ... ]" >&2
+ exit 2
+ }
+ exec=1
+ while :
+ do case $1 in
+ -n) exec=0 ;;
+ -*) usage ;;
+ *) break ;;
+ esac
+ shift
+ done
+ ;;
+esac
+case $# in
+0) if test ! -x /bin/cat.exe
+ then exit 1 # normal
+ fi
+ if /bin/cat /bin/cat >/dev/null 2>&1
+ then exit 1 # normal
+ fi
+ exit 0 # challenged
+ ;;
+1) usage
+ ;;
+esac
+case $1 in
+*cat|*rm)
+ NUM=0
+ ;;
+*chgrp|*chmod)
+ NUM=1
+ ;;
+*cmp|*cp|*ln|*mv)
+ NUM=2
+ ;;
+*) case $exec in
+ 0) echo "$@" ;;
+ *) "$@" ;;
+ esac
+ exit
+ ;;
+esac
+CMD=$1
+shift
+case $CMD in
+*/*) ;;
+*) for d in $bins
+ do if test -x $d/$1 -o -x $d/$1.exe
+ then CMD=$d/$1
+ break
+ fi
+ done
+ ;;
+esac
+while :
+do case $1 in
+ -*) CMD="$CMD $1" ;;
+ *) break ;;
+ esac
+ shift
+done
+case $exec in
+0) CMD="echo $CMD" ;;
+esac
+case $NUM:$# in
+*:0) ;;
+1:*) CMD="$CMD $1"
+ NUM=0
+ shift
+ ;;
+esac
+case $NUM:$# in
+0:*) status=0
+ for f
+ do if test "$f" -ef "$f".exe
+ then f=$f.exe
+ fi
+ $CMD "$f"
+ case $? in
+ 0) ;;
+ *) status=$? ;;
+ esac
+ done
+ exit $status
+ ;;
+2:2) f=$1
+ case $f in
+ *.exe) ;;
+ *) if test "$f" -ef "$f".exe
+ then f=$f.exe
+ fi
+ ;;
+ esac
+ case $f in
+ *.exe) if test -d "$2"
+ then t=$2/$f
+ else t=$2
+ fi
+ case $t in
+ */*) b=`basename "$t"` ;;
+ *) b=$t ;;
+ esac
+ case $b in
+ *.*) $CMD "$f" "$t"; exit ;;
+ *) $CMD "$f" "$t".exe; exit ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+$CMD "$@"
diff --git a/src/cmd/INIT/filter.sh b/src/cmd/INIT/filter.sh
new file mode 100644
index 0000000..2637a58
--- /dev/null
+++ b/src/cmd/INIT/filter.sh
@@ -0,0 +1,98 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: convert command that operates on file args to pipeline filter
+
+command=filter
+
+tmp=/tmp/$command$$
+suf=
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) ARGV0="-a $command"
+ USAGE=$'
+[-?
+@(#)$Id: filter (AT&T Labs Research) 2001-05-31 $
+]
+'$USAGE_LICENSE$'
+[+NAME?filter - run a command in stdin/stdout mode]
+[+DESCRIPTION?\bfilter\b runs \acommand\a in a mode that takes input from
+ the \afile\a operands, or from the standard input if no \afile\a
+ operands are specified, and writes the results to the standard output.
+ It can be used to run commands like \bsplit\b(1), that normally modify
+ \afile\a operands in-place, in pipelines. The \afile\a operands are
+ not modified; \acommand\a is run on copies in \b/tmp\b.]
+
+command [ option ... ] [ file ... ]
+
+[+SEE ALSO?\bstrip\b(1)]
+'
+ ;;
+*) ARGV0=""
+ USAGE="command [ option ... ] [ file ... ]"
+ ;;
+esac
+
+usage()
+{
+ OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+}
+
+while getopts $ARGV0 "$USAGE" OPT
+do case $OPT in
+ *) usage ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+case $# in
+0) usage ;;
+esac
+
+cmd=$1
+while :
+do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -*) cmd="$cmd $1" ;;
+ *) break ;;
+ esac
+done
+trap 'rm -f $tmp$suf' 0 1 2 3 15
+case $# in
+0) cat > $tmp
+ $cmd $tmp
+ ;;
+*) for file
+ do suf=${file##*/}
+ case $suf in
+ *.*) suf=.${suf#*.} ;;
+ *) suf= ;;
+ esac
+ cp $file $tmp$suf || exit 1
+ chmod u+rwx $tmp$suf || exit 1
+ $cmd $tmp$suf || exit 1
+ cat $tmp$suf
+ rm -f $tmp$suf
+ done
+ ;;
+esac
diff --git a/src/cmd/INIT/gdbm.c b/src/cmd/INIT/gdbm.c
new file mode 100644
index 0000000..cc0a9f6
--- /dev/null
+++ b/src/cmd/INIT/gdbm.c
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for -lgdbm
+ */
+
+#define _hdr_gdbm_ndbm 1
+
+#if _hdr_gdbm_ndbm
+#include <gdbm/ndbm.h>
+#endif
+
+int
+main()
+{
+ DBM* dbm = 0;
+
+ dbm_close(dbm);
+ return 0;
+}
diff --git a/src/cmd/INIT/gdbm1.c b/src/cmd/INIT/gdbm1.c
new file mode 100644
index 0000000..6ad2071
--- /dev/null
+++ b/src/cmd/INIT/gdbm1.c
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for -lgdbm
+ */
+
+#define _hdr_gdbm_ndbm 1
+
+#if _hdr_gdbm_ndbm
+#include <gdbm-ndbm.h>
+#endif
+
+int
+main()
+{
+ DBM* dbm = 0;
+
+ dbm_close(dbm);
+ return 0;
+}
diff --git a/src/cmd/INIT/gdbm2.c b/src/cmd/INIT/gdbm2.c
new file mode 100644
index 0000000..1b9a48f
--- /dev/null
+++ b/src/cmd/INIT/gdbm2.c
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for -lgdbm
+ */
+
+#define _hdr_ndbm 1
+
+#if _hdr_ndbm
+#include <ndbm.h>
+#endif
+
+int
+main()
+{
+ DBM* dbm = 0;
+
+ dbm_close(dbm);
+ return 0;
+}
diff --git a/src/cmd/INIT/hello.c b/src/cmd/INIT/hello.c
new file mode 100755
index 0000000..2a8e2d1
--- /dev/null
+++ b/src/cmd/INIT/hello.c
@@ -0,0 +1,23 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#ifndef printf
+#include <stdio.h>
+#endif
+int main() { int new = 0; printf("hello world\n"); return new;}
diff --git a/src/cmd/INIT/hosttype.tst b/src/cmd/INIT/hosttype.tst
new file mode 100644
index 0000000..7a64588
--- /dev/null
+++ b/src/cmd/INIT/hosttype.tst
@@ -0,0 +1,6 @@
+hp.pa hostname 9000/730 hp9000s700 HP-UX hostname A.09.01 A
+linux-aout.i386 hostname i586 i386 linux hostname 1.1.59 #1
+sgi.mips2 hostname.domain IP22 mips IRIX hostname 5.2 02282016
+osf.alpha hostname.domain alpha alpha OSF1 hostname.domain V3.2 62
+sun4 hostname.domain sun4 sparc SunOS hostname.domain 4.1.1 1 sun4c
+sol.sun4 hostname.domain sun4 sparc SunOS hostname.domain 5.4 Generic_101945-13
diff --git a/src/cmd/INIT/hurl.sh b/src/cmd/INIT/hurl.sh
new file mode 100644
index 0000000..60e8a6b
--- /dev/null
+++ b/src/cmd/INIT/hurl.sh
@@ -0,0 +1,207 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: copy http url data
+
+command=hurl
+agent="$command/2009-01-20 (AT&T Research)"
+authorize=
+verbose=0
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) ARGV0="-a $command"
+ USAGE=$'
+[-?
+@(#)$Id: hurl (AT&T Research) 2009-01-20 $
+]
+'$USAGE_LICENSE$'
+[+NAME?hurl - copy http url data]
+[+DESCRIPTION?\bhurl\b copies the data for the \bhttp\b \aurl\a operand
+ to the standard output. The \aurl\a must be of the form
+ \b[http://]]\b\ahost\a[\b:\b\aport\a]]\b/\b\apath\a. The default
+ \aport\a is \b80\b.]
+[+?\bhurl\b is a shell script that attempts to access the \aurl\a by
+ these methods:]{
+ [+/dev/tcp/\ahost\a\b/80\b?Supported by \bksh\b(1) and recent
+ \bbash\b(1).]
+ [+wget -nv -O - \aurl\a?]
+ [+lynx -source \aurl\a?]
+ [+curl -s -L -o - \aurl\a?]
+}
+[a:authorize?The url authorization user name and password, separated
+ by \b:\b (one colon character.)]:[user::password]
+[s:size?Terminate the data transmission after \abytes\a have been
+ transferred.]:[bytes]
+[v:verbose?Verbose trace.]
+
+url
+
+[+SEE ALSO?\bcurl\b(1), \blynx\b(1), \bwget\b(1)]
+'
+ ;;
+*) ARGV0=""
+ USAGE="a:v"
+ ;;
+esac
+
+usage()
+{
+ OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+}
+
+integer limit=0 total=0 block=8*1024
+
+while getopts $ARGV0 "$USAGE" OPT
+do case $OPT in
+ a) authorize=$OPTARG ;;
+ s) limit=$OPTARG ;;
+ v) verbose=1 ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
+url=$1
+AUTHORIZE=
+
+exec 9<&0
+
+while :
+do test 0 != $verbose && echo "$command: url=$url" >&2
+ case $url in
+ *://*/*)prot=${url%%:*}
+ url=${url#*://}
+ ;;
+ *) prot=http
+ ;;
+ esac
+ host=$url
+ path=/${host#*/}
+ host=${host%%/*}
+ case $host in
+ *:+([0-9]))
+ port=${host##*:}
+ host=${host%:*}
+ ;;
+ *) port=80
+ ;;
+ esac
+ test 0 != $verbose && echo "$command: prot=$prot host=$host port=$port path=$path" >&2
+ case $prot in
+ http) if (eval "exec >" || exit 0) 2>/dev/null &&
+ eval "exec 8<> /dev/tcp/\$host/$port" 2>/dev/null
+ then test 0 != $verbose && echo "$command: using /dev/tcp/$host/$port" >&2
+ if ! echo "GET $path HTTP/1.0
+Host: $host
+User-Agent: $agent ${AUTHORIZE}
+ " >&8
+ then echo "$command: $host: write error"
+ exit 1
+ fi
+ {
+ if ! read prot code text
+ then echo "$command: $host: read error" >&2
+ exit 1
+ fi
+ code=${code%:*}
+ type=Basic
+ realm=access
+ test 0 != $verbose && echo "$command: prot=$prot code=$code $text" >&2
+ while :
+ do if ! read head data
+ then echo "$command: $host: read error" >&2
+ exit 1
+ fi
+ test 0 != $verbose && echo "$command: head=$head $data" >&2
+ case $head in
+ Location:)
+ case $code in
+ 30[123])url=$data
+ continue 2
+ ;;
+ esac
+ ;;
+ WWW-Authenticate:)
+ set -- $data
+ type=$1
+ shift
+ eval "$@"
+ realm=${realm%$'\r'}
+ ;;
+ ''|?) break
+ ;;
+ esac
+ done
+ case $code in
+ 200) if (( limit ))
+ then (( limit = (limit + block - 1) / block))
+ dd bs=$block count=$limit silent=1
+ else cat
+ fi
+ exit
+ ;;
+ 401) {
+ if [[ $AUTHORIZE || $type != Basic ]]
+ then print authorization failed
+ exit 1
+ fi
+ if [[ ! $authorize ]]
+ then if [[ ! -t 0 ]]
+ then print authorization failed
+ exit 1
+ fi
+ print -n "Enter user name for $realm: "
+ read -u9 user
+ print -n "Password: "
+ trap 'stty echo <&9' 0 1 2 3 15
+ stty -echo
+ read password
+ stty echo
+ print
+ trap - 0 1 2 3 15
+ authorize=$user:$password
+ fi
+ AUTHORIZE=$'\nAuthorization: '$type' '$(print -n -r -- "$authorize" | uuencode -h -x base64)$'\r'
+ } <&9 >&2
+ continue 2
+ ;;
+ *) echo "$0: $url: $code: $text" >&2
+ exit 1
+ ;;
+ esac
+ } <&8
+ elif wget ${authorize:+--http-user="${authorize%:*}"} ${password:+--http-passwd="${password##*:}"} -nv -O - $url 2>/dev/null
+ then test 0 != $verbose && echo "$command: using wget" >&2
+ exit
+ elif lynx ${authorize:+-auth "$authorize"} -source $url 2>/dev/null
+ then test 0 != $verbose && echo "$command: using wget" >&2
+ exit
+ elif curl ${authorize:+-u "$authorize"} -s -L -o - $url 2>/dev/null
+ then test 0 != $verbose && echo "$command: using curl" >&2
+ exit
+ else echo "$command: $url: { /dev/tcp/$host/$port wget curl } failed" >&2
+ exit 1
+ fi
+ ;;
+ *) echo "$command: $prot: protocol not supported" >&2
+ exit 1
+ ;;
+ esac
+done
diff --git a/src/cmd/INIT/iconv.c b/src/cmd/INIT/iconv.c
new file mode 100644
index 0000000..64f2797
--- /dev/null
+++ b/src/cmd/INIT/iconv.c
@@ -0,0 +1,29 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#ifndef iconv
+#include <iconv.h>
+#endif
+
+int
+main()
+{
+ iconv(0, 0, 0, 0, 0);
+ return 0;
+}
diff --git a/src/cmd/INIT/iffe.sh b/src/cmd/INIT/iffe.sh
new file mode 100644
index 0000000..cfd216c
--- /dev/null
+++ b/src/cmd/INIT/iffe.sh
@@ -0,0 +1,4639 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+# Glenn Fowler & Phong Vo
+# AT&T Research
+#
+# test if feature exists
+# this script is written to make it through all sh variants
+#
+# NOTE: .exe a.out suffix and [\\/] in path patterns for dos/nt
+
+case $-:$BASH_VERSION in
+*x*:[0123456789]*) : bash set -x is broken :; set +ex ;;
+esac
+
+command=iffe
+version=2012-02-23 # update in USAGE too #
+
+compile() # $cc ...
+{
+ "$@" 2>$tmp.err
+ _compile_status=$?
+ if test -s $tmp.err
+ then cat $tmp.err >&2
+ case $_compile_status in
+ [1-9]|[1-9][0-9]|1[01][0-9]|12[0-7])
+ if egrep -i -c 'terminated with signal|core dump|segmentation fault' $tmp.err >&$nullout
+ then _compile_status=139
+ fi
+ ;;
+ esac
+ fi
+ case $_compile_status in
+ ?|??|1[01]?|12[0-8]|25?)
+ ;;
+ *) echo "$command: $@" >&$stderr
+ cat $tmp.err >&$stderr
+ echo "$command: $1: core dump or fatal interruption -- results inconclusive" >&$stderr
+ exit $_compile_status
+ ;;
+ esac
+ return $_compile_status
+}
+
+is_hdr() # [ - ] [ file.c ] hdr
+{
+ case $1 in
+ -) _is_hdr_flag=-; shift ;;
+ *) _is_hdr_flag= ;;
+ esac
+ case $1 in
+ *.c) _is_hdr_file=$1; shift ;;
+ *) _is_hdr_file=$tmp.c ;;
+ esac
+ is hdr $1
+ compile $cc -c $_is_hdr_file <&$nullin >&$nullout 2>$tmp.e
+ _is_hdr_status=$?
+ case $_is_hdr_status in
+ 0) if test -s $tmp.e
+ then case `grep '#.*error' $tmp.e` in
+ ?*) _is_hdr_status=1 ;;
+ esac
+ fi
+ ;;
+ esac
+ case $_is_hdr_status in
+ 0) success $_is_hdr_flag
+ ;;
+ *) case $debug in
+ 3) cat $tmp.e >&$stderr ;;
+ esac
+ failure $_is_hdr_flag
+ ;;
+ esac
+ return $_is_hdr_status
+}
+
+pkg() # package
+{
+ case $1 in
+ '') pth=`getconf PATH 2>/dev/null`
+ case $pth in
+ '') pth="/bin /usr/bin" ;;
+ *:*) pth=`echo "$pth" | sed 's/:/ /g'` ;;
+ esac
+ return
+ ;;
+ '<') shift
+ ;;
+ *) return
+ ;;
+ esac
+ case $1 in
+ X|X11*) i="openwin"
+ case $1 in
+ X) set X11 ;;
+ esac
+ case $1 in
+ X11) case $# in
+ 1) set $1 6 5 4 ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) i=
+ ;;
+ esac
+ pth="{ usr . - . contrib local $i - . share - . lib - $1"
+ i=$1
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ '>') shift; break ;;
+ esac
+ pth="$pth ${i}R$1 ${i}.$1"
+ done
+ pth="$pth . } $*"
+}
+
+is() # op name
+{
+ case $verbose in
+ 1) case $complete in
+ 1) failure ;;
+ esac
+ oo=$1
+ shift
+ case $1 in
+ ?*) yy=is
+ ii=$1
+ complete=1
+ case $oo in
+ cmd) mm="a command" ;;
+ dat) mm="a library data symbol" ;;
+ dfn) mm="a macro with extractable value" ;;
+ exp) mm="true" ;;
+ hdr) mm="a header" ;;
+ id) mm="an identifier" ;;
+ lcl) mm="a native header" ;;
+ key) mm="a reserved keyword" ;;
+ lib) mm="a library function" ;;
+ LIB) case $2 in
+ "") mm="a library" ;;
+ *) ii=$*; mm="a library group" ;;
+ esac
+ ;;
+ mac) mm="a macro" ;;
+ mem) mm="a member of $2" ;;
+ mth) mm="a math library symbol" ;;
+ nos) mm="a non-opaque struct" ;;
+ npt) mm="a symbol that needs a prototype" ;;
+ num) mm="a numeric constant or enum" ;;
+ nxt) mm="an include path for the native header" ;;
+ opt) mm="set in \$PACKAGE_OPTIONS" ;;
+ pth) mm="a file" ;;
+ run) yy="capture output of" mm= ;;
+ siz) mm="a type with known size" ;;
+ sym) mm="a typed variable" ;;
+ sys) mm="a system header" ;;
+ typ) mm="a type or typedef" ;;
+ val) yy="determine" mm="value" ;;
+ *) yy= mm= ;;
+ esac
+ case $ii in
+ [abcdefghijklmnopqrstuvwxyz]*[abcdefghijklmnopqrstuvwxyz]'{') ii="$ii ... }end" ;;
+ esac
+ $show "$command: test:" $yy $ii $mm "...$SHOW" >&$stderr
+ complete=1
+ ;;
+ esac
+ ;;
+ esac
+}
+
+success()
+{
+ case $1 in
+ -) shift
+ ;;
+ *) case $result in
+ UNKNOWN) result=SUCCESS ;;
+ esac
+ case $1 in
+ +) return ;;
+ esac
+ ;;
+ esac
+ case $complete:$verbose in
+ 1:1) case $suspended in
+ 1) suspended=0
+ $show "$command: test:" $yy $ii $mm "...$SHOW" >&$stderr
+ ;;
+ esac
+ complete=0
+ case $# in
+ 0) mm="yes" ;;
+ *) mm="'$*'" ;;
+ esac
+ case $debug in
+ 0) echo " $mm" >&$stderr ;;
+ *) echo "$command: ... $mm" >&$stderr ;;
+ esac
+ ;;
+ esac
+}
+
+failure()
+{
+ case $1 in
+ -) shift ;;
+ *) result=FAILURE
+ case $1 in
+ +) return ;;
+ esac
+ ;;
+ esac
+ case $complete:$verbose in
+ 1:1) case $suspended in
+ 1) suspended=0
+ $show "$command: test:" $yy $ii $mm "...$SHOW" >&$stderr
+ ;;
+ esac
+ complete=0
+ case $group in
+ '') case $# in
+ 0) mm="no" ;;
+ *) mm=$* ;;
+ esac
+ ;;
+ *) mm=
+ ;;
+ esac
+ case $debug in
+ 0) echo " $mm" >&$stderr ;;
+ *) echo "$command: ... $mm" >&$stderr ;;
+ esac
+ ;;
+ esac
+}
+
+# report
+#
+# - ignore global status
+# -0 normal sense
+# -1 inverted sense if ! def
+# status test status 0:success *:failure
+# success success comment
+# failure failure comment
+# default default setting comment
+#
+# globals
+#
+# $not invert test sense
+# $M test variable
+# $m test macro
+# $v default macro
+
+report() # [-] [-0] [-1] status value success failure default
+{
+ case $1 in
+ -) _report_ignore=$1
+ shift
+ ;;
+ *) _report_ignore=
+ ;;
+ esac
+ _report_not=$not
+ case $1 in
+ -0) shift
+ ;;
+ -1) shift
+ case $def in
+ ''|-) case $_report_not in
+ 1) _report_not= ;;
+ *) _report_not=1 ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ _report_status=$1
+ case $_report_ignore:$_report_status in
+ -:*) ;;
+ *:0) success $_report_ignore
+ ;;
+ *) failure $_report_ignore
+ case $group in
+ ?*) return ;;
+ esac
+ ;;
+ esac
+ _report_value=$2
+ case $_report_not in
+ 1) case $_report_status in
+ 0) _report_status=1 ;;
+ *) _report_status=0 ;;
+ esac
+ _report_success=$4
+ _report_failure=$3
+ ;;
+ *) _report_success=$3
+ _report_failure=$4
+ ;;
+ esac
+ _report_default=$5
+ case $_report_status in
+ 0) case $M in
+ *-*) ;;
+ *) usr="$usr$nl#define $m $_report_value"
+ case $_report_success in
+ ''|-) ;;
+ *) case $define in
+ 1) echo "#define $m $_report_value /* $_report_success */" ;;
+ n) echo "$m=$_report_value"
+ esac
+ ;;
+ esac
+ eval $m=\'$_report_value\'
+ ;;
+ esac
+ ;;
+ *) case $M in
+ *-*) ;;
+ *) case $_report_failure in
+ ''|-) ;;
+ *) case $define$all$config$undef in
+ 1?1?|1??1)echo "#undef $m /* $_report_failure */" ;;
+ 11??) echo "#define $m 0 /* $_report_failure */" ;;
+ n1?1) echo "$m=" ;;
+ n1??) echo "$m=0" ;;
+ esac
+ ;;
+ esac
+ case $_report_default in
+ ''|-) ;;
+ *) case $define$set in
+ 1?*) echo "#define $v $set /* $_report_default */" ;;
+ n?*) echo "$v=$set" ;;
+ esac
+ ;;
+ esac
+ eval $m=0
+ ;;
+ esac
+ ;;
+ esac
+}
+
+noisy()
+{
+ case $complete:$verbose in
+ 1:1) suspended=1
+ echo >&$stderr
+ ;;
+ esac
+}
+
+here_broken=0
+
+literal() # line that echo might process
+{
+ if cat <<!
+$*
+!
+ then : old here doc botch not present
+ else case $here_broken in
+ 0) here_broken=1
+ echo "$command: your shell botches here documents; this was fixed back in the 80's" >&$stderr
+ ;;
+ esac
+ sh -c "cat <<!
+$*
+!
+"
+ fi
+}
+
+copy() # "output-file" "data-that-must-not-be-processed-by-echo"
+{
+ case $1 in
+ -) case $shell in
+ ksh) print -r - "$2"
+ ;;
+ *) if cat <<!
+$2
+!
+ then : ancient here doc botch not present
+ else case $here_broken in
+ 0) here_broken=1
+ echo "$command: your shell botches here documents; this was fixed back in the 80's" >&$stderr
+ ;;
+ esac
+ sh -c "cat <<!
+$2
+!
+"
+ fi
+ ;;
+ esac
+ ;;
+ *) case $shell in
+ ksh) print -r - "$2" > "$1"
+ ;;
+ *) if cat > "$1" <<!
+$2
+!
+ then : ancient here doc botch not present
+ else case $here_broken in
+ 0) here_broken=1
+ echo "$command: your shell botches here documents; this was fixed back in the 80's" >&$stderr
+ ;;
+ esac
+ sh -c "cat > \"$1\" <<!
+$2
+!
+"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+}
+
+# verify that cc is a C compiler
+
+checkcc()
+{
+ # check for local package root directories
+
+ case $PACKAGE_PATH in
+ ?*) for i in `echo $PACKAGE_PATH | sed 's,:, ,g'`
+ do if test -d $i/include
+ then cc="$cc -I$i/include"
+ occ="$occ -I$i/include"
+ fi
+ if test -d $i/lib
+ then cc="$cc -L$i/lib"
+ occ="$occ -L$i/lib"
+ for y in $libpaths
+ do eval $y=\"\$$y:\$i/lib\$${y}_default\"
+ eval export $y
+ done
+ fi
+ done
+ ;;
+ esac
+ echo "int i = 1;" > $tmp.c
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then echo "(;" > $tmp.c
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then cctest="should not compile '(;'"
+ fi
+ else cctest="should compile 'int i = 1;'"
+ fi
+ case $cctest in
+ "") cctest=0
+ ;;
+ *) echo "$command: $cc: not a C compiler: $cctest" >&$stderr
+ exit 1
+ ;;
+ esac
+}
+
+checkread()
+{
+ case $cctest in
+ "") checkcc ;;
+ esac
+ case $posix_read in
+ -no) ;;
+ *) posix_read=`(read -r _checkread_line; echo $_checkread_line) 2>/dev/null <<!
+a z
+!
+`
+ ;;
+ esac
+ case $posix_read in
+ "a z") posix_read=1
+ ;;
+ *) copy ${tmp}r.c "
+ extern int read();
+ extern int write();
+ int main()
+ {
+ char c;
+ char r;
+ int k;
+ char s[32];
+ k = 0;
+ while (read(0, &c, 1) == 1)
+ {
+ if (k >= 0)
+ {
+ if (c == ' ' || c == '\\t')
+ {
+ if (k < sizeof(s))
+ s[k++] = c;
+ continue;
+ }
+ if (k > 1 && c != '#' && c != '\\n' && c != '\\r')
+ write(1, s + 1, k - 1);
+ k = -1;
+ }
+ if (c == '\\r')
+ {
+ r = c;
+ if (read(0, &c, 1) == 1 && c != '\\n')
+ write(1, &r, 1);
+ }
+ write(1, &c, 1);
+ if (c == '\\n')
+ return 0;
+ }
+ return 1;
+ }"
+ if compile $cc -o ${tmp}r.exe ${tmp}r.c >&$nullout
+ then posix_read=${tmp}r.exe
+ else echo "$command: cannot compile read -r workaround" >&$stderr
+ exit 1
+ fi
+ ;;
+ esac
+}
+
+execute()
+{
+ if test "" != "$cross"
+ then crossexec $cross "$@"
+ _execute_=$?
+ elif test -d /NextDeveloper
+ then "$@" <&$nullin >&$nullout
+ _execute_=$?
+ "$@" <&$nullin | cat
+ else "$@"
+ _execute_=$?
+ fi
+ return $_execute_
+}
+
+exclude()
+{
+ case $excludes in
+ '') return 0 ;;
+ esac
+ for _exclude_var
+ do eval _exclude_old=\$$_exclude_var
+ case $_exclude_old in
+ *" -I"*);;
+ *) continue ;;
+ esac
+ _exclude_new=
+ _exclude_sep=
+ for _exclude_arg in $_exclude_old
+ do _exclude_skip=
+ for _exclude_dir in $excludes
+ do case $_exclude_arg in
+ -I$_exclude_dir|-I*/$_exclude_dir)
+ _exclude_skip=1
+ break;
+ ;;
+ esac
+ done
+ case $_exclude_skip in
+ '') _exclude_new="$_exclude_new$_exclude_sep$_exclude_arg"
+ _exclude_sep=" "
+ ;;
+ esac
+ done
+ eval $_exclude_var=\$_exclude_new
+ case $debug in
+ 0) ;;
+ *) echo $command: exclude $_exclude_var: "$_exclude_old => $_exclude_new" >&$stderr
+ ;;
+ esac
+ done
+}
+
+all=0
+apis=
+binding="-dy -dn -Bdynamic -Bstatic -Wl,-ashared -Wl,-aarchive -call_shared -non_shared '' -static"
+complete=0
+config=0
+defhdr=
+define=1
+explicit=0
+iff=
+usr=
+cross=
+debug=0
+deflib=
+dir=FEATURE
+excludes=
+executable="test -x"
+exists="test -e"
+gothdr=
+gotlib=
+idno=
+idyes=
+ifs=${IFS-'
+ '}
+in=
+includes=
+intrinsic=
+libpaths="LD_LIBRARY_PATH LD_LIBRARYN32_PATH LD_LIBRARY64_PATH LIBPATH SHLIB_PATH"
+ LD_LIBRARY_PATH_default=:/lib:/usr/lib
+ LD_LIBRARYN32_PATH_default=:/lib32:/usr/lib32
+ LD_LIBRARY64_PATH_default=:/lib64:/usr/lib64
+ LIBPATH_default=:/lib:/usr/lib
+ SHLIB_PATH_default=:/shlib:/usr/shlib:/lib:/usr/lib
+nl="
+"
+optimize=1
+occ=cc
+one=
+out=
+posix_read=-check
+case `(set -f && set x * && echo $# && set +f) 2>/dev/null` in
+2) posix_noglob="set -f" posix_glob="set +f" ;;
+*) case `(set -F && set x * && echo $# && set +F) 2>/dev/null` in
+ 2) posix_noglob="set -F" posix_glob="set +F" ;;
+ *) posix_noglob=":" posix_glob=":" ;;
+ esac
+ ;;
+esac
+protoflags=
+puthdr=
+putlib=
+pragma=
+case $RANDOM in
+$RANDOM)shell=bsh
+ ($executable .) 2>/dev/null || executable='test -r'
+ ($exists .) 2>/dev/null || exists='test -r'
+ ;;
+*) case $BASH_VERSION in
+ ?*) shell=bash ;;
+ *) shell=ksh ;;
+ esac
+ ;;
+esac
+reallystatic=
+reallystatictest=
+regress=
+static=.
+statictest=
+case $COTEMP in
+"") case $HOSTNAME in
+ ""|?|??|???|????|????)
+ tmp=${HOSTNAME}
+ ;;
+ *) case $shell in
+ bsh) eval `echo $HOSTNAME | sed 's/\\(....\\).*/tmp=\\1/'` ;;
+ *) eval 'tmp=${HOSTNAME%${HOSTNAME#????}}' ;;
+ esac
+ ;;
+ esac
+ tmp=${tmp}$$
+ ;;
+*) tmp=x${COTEMP}
+ ;;
+esac
+COTEMP=${tmp}
+export COTEMP
+case $tmp in
+./*) ;;
+??????????*)
+ case $shell in
+ bsh) eval `echo $tmp | sed 's/\\(.........\\).*/tmp=\\1/'` ;;
+ *) eval 'tmp=${tmp%${tmp#?????????}}' ;;
+ esac
+ ;;
+?????????)
+ ;;
+????????)
+ tmp=F$tmp
+ ;;
+esac
+case $tmp in
+./*) ;;
+*) tmp=./$tmp ;;
+esac
+undef=0
+verbose=0
+vers=
+
+# options -- `-' for output to stdout otherwise usage
+
+case $1 in
+-) out=-; shift ;;
+esac
+set=
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) USAGE=$'
+[-?
+@(#)$Id: iffe (AT&T Research) 2012-02-23 $
+]
+'$USAGE_LICENSE$'
+[+NAME?iffe - C compilation environment feature probe]
+[+DESCRIPTION?\biffe\b is a command interpreter that probes the C
+ compilation environment for features. A feature is any file, option
+ or symbol that controls or is controlled by the C compiler. \biffe\b
+ tests features by generating and compiling C programs and observing
+ the behavior of the C compiler and generated programs.]
+[+?\biffe\b statements are line oriented. Statements may appear in the
+ operand list with the \b:\b operand or \bnewline\b as the line
+ delimiter. The standard input is read if there are no command
+ line statements or if \afile\a\b.iffe\b is omitted.]
+[+?Though similar in concept to \bautoconf\b(1) and \bconfig\b(1), there
+ are fundamental differences. The latter tend to generate global
+ headers accessed by all components in a package, whereas \biffe\b is
+ aimed at localized, self contained feature testing.]
+[+?Output is generated in \bFEATURE/\b\atest\a by default, where \atest\a is
+ the base name of \afile\a\b.iffe\b or the \biffe\b \brun\b
+ file operand. Output is first generated in a temporary file; the
+ output file is updated if it does not exist or if the temporary file
+ is different. If the first operand is \b-\b then the output is written
+ to the standard output and no update checks are done.]
+[+?Files with suffixes \b.iffe\b and \b.iff\b are assumed to contain
+ \biffe\b statements.]
+[a:all?Define failed test macros \b0\b. By default only successful test macros
+ are defined \b1\b.]
+[c:cc?Sets the C compiler name and flags to be used in the feature
+ tests.]:[C-compiler-name [C-compiler-flags ...]]]
+[C:config?Generate \bconfig\b(1) style \aHAVE_\a* macro names. This implies
+ \b--undef\b. Since \bconfig\b(1) has inconsistent naming conventions,
+ the \bexp\b op may be needed to translate from the (consistent)
+ \biffe\b names. Unless otherwise noted a \bconfig\b macro name
+ is the \biffe\b macro name prefixed with \bHAVE\b and converted to
+ upper case. \b--config\b is set by default if the command arguments
+ contain a \brun\b op on an input file with the base name \bconfig\b.]
+[d:debug?Sets the debug level. Level 0 inhibits most
+ error messages, level 1 shows compiler messages, and
+ level 2 traces internal \biffe\b \bsh\b(1) actions and does
+ not remove core dumps on exit.]#[level]
+[D:define?Successful test macro definitions are emitted. This is the default.]
+[E:explicit?Disable implicit test output.]
+[F:features?Sets the feature test header to \ahdr\a. This header typically
+ defines *_SOURCE feature test macros.]:[hdr:=NONE]
+[i:input?Sets the input file name to \afile\a, which
+ must contain \biffe\b statements.]:[file]
+[I:include?Adds \b-I\b\adir\a to the C compiler flags.]:[dir]
+[L:library?Adds \b-L\b\adir\a to the C compiler flags.]:[dir]
+[n:name-value?Output \aname\a=\avalue\a assignments only.]
+[N!:optimize?\b--nooptimize\b disables compiler optimization options.]
+[o:output?Sets the output file name to \afile\a.]:[file]
+[O:stdio?Sets the standard io header to \ahdr\a.]:[hdr:=stdio.h]
+[e:package?Sets the \bproto\b(1) package name to \aname\a.]:[name]
+[p:prototyped?Emits \b#pragma prototyped\b at the top of the
+ output file. See \bproto\b(1).]
+[P:pragma?Emits \b#pragma\b \atext\a at the top of the output file.]:[text]
+[r:regress?Massage output for regression testing.]
+[s:shell?Sets the internal shell name to \aname\a. Used for debugging
+ Bourne shell compatibility (otherwise \biffe\b uses \aksh\a constructs
+ if available). The supported names are \bksh\b, \bbsh\b, \bbash\b, and
+ \bosh\b. \bosh\b forces the \bread -r\b compatibility read command to
+ be compiled and used instead of \bread -r\b. The default is determined
+ by probing the shell at startup.]:[name]
+[S:static?Sets the C compiler flags that force static linking. If not set
+ then \biffe\b probes the compiler to determine the flags. \biffe\b
+ must use static linking (no dlls) because on some systems missing
+ library symbols are only detected when referenced at runtime from
+ dynamically linked executables.]:[flags]
+[u:undef?\b#undef\b failed test macros. By default only successful test macros
+ are defined \b1\b.]
+[v:verbose?Produce a message line on the standard error for each test as
+ it is performed.]
+[x:cross?Some tests compile an executable (\ba.out\b) and then run it.
+ If the C compiler is a cross compiler and the executable format is
+ incompatible with the execution environment then the generated
+ executables must be run in a different environment, possibly on
+ another host. \acrosstype\a is the HOSTTYPE for generated executables
+ (the \bpackage\b(1) command generates a consistent HOSTTYPE namespace).
+ Generated executables are run via \bcrossexec\b(1) with \acrosstype\a
+ as the first argument. \bcrossexec\b supports remote execution for
+ cross-compiled executables. See \bcrossexec\b(1) for
+ details.]:[crosstype]
+[X:exclude?Removes \b-I\b\adir\a and \b-I\b*/\adir\a C compiler flags.]:[dir]
+
+[ - ] [ file.iffe | statement [ : statement ... ] ]
+
+[+SYNTAX?\biffe\b input consists of a sequence of statement lines. Statements
+ that span more than one line contain \abegin\a\b{\b as the last
+ operand (where \abegin\a is command specific) and zero
+ or more data lines terminated by a line containing
+ \b}end\b as the first operand. The statement syntax is:
+ [\aname\a \b=\b]] [\b!\b]] \atest\a[,\atest\a...]] [\b-\b]]
+ [\aarg\a[,\aarg\a...]]]] [\aprereq\a ...]]
+ [\abegin\a{ ... |\bend\b ...]] [= [\adefault\a]]]].
+ \atest\as and \aarg\as may be combined, separated by commas, to perform
+ a set of tests on a set of arguments. \aname\a \b=\b before \atest\a
+ overrides the default test variable and macro name, and \b-\b after
+ \atest\a performs the test but does not define the test variable and
+ macro values. \b!\b before \atest\a inverts the test sense for \bif\b,
+ \belif\b, and \byes{\b and \bno{\b blocks.]
+[+?\aprereq\as are used when applying the features tests and may be
+ combinations of:]{
+ [+compiler options?\b-D\b*, \b-L\b*, etc.]
+ [+library references?\b-l\b*, *\b.a\b, etc. \b_LIB_\b\aname\a
+ is defined to be 1 if \b-l\b\aname\a is a library.]
+ [+header references?*\b.h\b. \a_dir_name\a is defined to be 1
+ if \adir/name\a\b.h\b is a header, or if \adir\a is
+ omitted, \b_hdr_\b\aname\a is defined to be 1 if
+ \aname\a\b.h\b is a header.]
+ [+-?Prereq grouping mark; prereqs before the first \b-\b are
+ passed to all feature tests. Subsequent groups
+ are attempted in left-to-right order until the first
+ successful group is found.]
+ }
+[+?\abegin\a\b{\b ... \b}end\b delimit multiline code blocks that override
+ or augment the default code provided by \biffe\b. User supplied code
+ blocks should be compatible with the K&R, ANSI, and C++ C language
+ dialects for maximal portability. In addition to all macro definitions
+ generated by previous tests, all generated code contains the
+ following at the top to hide dialect differences:]{
+ [+ ?#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)]
+ [+ ?#define _STD_ 1]
+ [+ ?#define _ARG_(x) x]
+ [+ ?#define _VOID_ void]
+ [+ ?#else]
+ [+ ?#define _STD_ 0]
+ [+ ?#define _ARG_(x) ()]
+ [+ ?#define _VOID_ char]
+ [+ ?#endif]
+ [+ ?#if defined(__cplusplus)]
+ [+ ?#define _BEGIN_EXTERNS_ extern "C" {]
+ [+ ?#define _END_EXTERNS_ }]
+ [+ ?#else]
+ [+ ?#define _BEGIN_EXTERNS_]
+ [+ ?#define _END_EXTERNS_]
+ [+ ?#endif]
+ [+ ?#define _NIL_(x) ((x)0)]
+ [+ ?#include <stdio.h>]
+ }
+[+?= \adefault\a may be specified for the \bkey\b, \blib\b, \bmac\b, \bmth\b
+ and \btyp\b tests. If the test fails for \aarg\a then
+ \b#define\b \aarg\a \adefault\a is emitted. \bkey\b accepts multiple
+ \b= \b\adefault\a values; the first valid one is used.]
+[+?Each test statement generates a portion of a C language header that contains
+ macro defintions, comments, and other text corresponding to the feature
+ tests. \b#ifndef _def_\b\aname\a\b_\b\adirectory\a ...
+ \b#endif\b guards the generated header from multiple \b#include\bs,
+ where \aname\a is determined by either the \brun\b statement input file
+ name if any, or the first \atest\a in the first statement, and \adirectory\a
+ is the basename component of either the \brun\b statement file, if any,
+ or the current working directory. The output file name is determined
+ in this order:]{
+ [+-?If the first command line operand is \b-\b then the output
+ is written to the standard output.]
+ [+--output=\afile\a?Output is \afile\a.]
+ [+set out \afile\a?Output is \afile\a.]
+ [+[run]] [\adirectory\a/]]\abase\a[\a.suffix\a]]?Output is
+ \bFEATURE/\b\abase\a.]
+ }
+[+?Generated \biffe\b headers are often referenced in C source as:
+ \b#include "FEATURE/\b\afile\a". The \bnmake\b(1) base rules contain
+ metarules for generating \bFEATURE/\b\afile\a from
+ \bfeatures/\b\afile\a[\asuffix\a]], where \asuffix\a may be omitted,
+ \b.c\b, or \b.sh\b (see the \brun\b test below). Because
+ \b#include\b prerequisites are automatically detected, \bnmake\b(1)
+ ensures that all prerequisite \biffe\b headers are generated before
+ compilation. Note that the directories are deliberately named
+ \bFEATURE\b and \bfeatures\b to keep case-ignorant file systems
+ happy.]
+[+?The feature tests are:]{
+ [+# \acomment\a?Comment line - ignored.]
+ [+api \aname\a \aYYYYMMDD\a \asymbol ...\a?Emit api compatibility tests
+ for \aname\a and \b#define\b \asymbol\a \asymbol\a_\aYYYYMMDD\a
+ when \aNAME\a_API is >= \aYYYYMMDD\a (\aNAME\a is \aname\a
+ converted to upper case). If \aNAME\a_API is not defined
+ then \asymbol\a maps to the newest \aYYYYMMDD\a for \aname\a.]
+ [+define \aname\a [ (\aarg,...\a) ]] [ \avalue\a ]]?Emit a macro
+ \b#define\b for \aname\a if it is not already defined. The
+ definition is passed to subsequent tests.]
+ [+extern \aname\a \atype\a [ (\aarg,...\a) | [\adimension\a]] ]]?Emit
+ an \bextern\b prototype for \aname\a if one is not already
+ defined. The prototype is passed to subsequent tests.]
+ [+header \aheader\a?Emit \b#include <\b\aheader\a\b>\b if \aheader\a
+ exists. The \b#include\b is passed to subsequent tests.]
+ [+print \atext\a?Copy \atext\a to the output file. \atext\a is passed
+ to subsequent tests.]
+ [+reference \aheader\a?If \aheader\a exists then add \b#include\b
+ \aheader\a to subsequent tests.]
+ [+ver \aname\a \aYYYYMMDD\a?\b#define\b \aNAME\a_VERSION \aYYYYMMDD\a
+ (\aNAME\a is \aname\a converted to upper case).]
+ [+cmd \aname\a?Defines \b_cmd_\b\aname\a if \aname\a is an executable
+ in one of the standard system directories (\b/bin, /etc,
+ /usr/bin, /usr/etc, /usr/ucb\b).
+ \b_\b\adirectory\a\b_\b\aname\a is defined for \adirectory\a
+ in which \aname\a is found (with \b/\b translated to \b_\b).]
+ [+dat \aname\a?Defines \b_dat_\b\aname\a if \aname\a is a data symbol
+ in the default libraries.]
+ [+def \aname\a?Equivalent to \bcmd,dat,hdr,key,lib,mth,sys,typ\b
+ \aname\a.]
+ [+dfn \aname\a?If \aname\a is a macro in the candidate headers then
+ a \b#define\b \aname\a \avalue\a statment is output for the
+ \avalue\a defined in the headers. The definition is \b#ifndef\b
+ guarded.]
+ [+exp \aname\a \aexpression\a?If \aexpression\a is a \"...\" string
+ then \aname\a is defined to be the string, else if the
+ \bexpr\b(1) evaluation of \aexpression\a is not 0 then \aname\a
+ is defined to be 1, otherwise \aname\a is defined to be 0.
+ Identifiers in \aexpression\a may be previously defined names
+ from other \biffe\b tests; undefined names evaluate to 0.
+ If \aname\a was defined in a previous successful test then
+ the current and subsequent \bexp\b test on \aname\a are
+ skipped. If \aname\a is \b-\b then the \aexpression\a is
+ simply evaluated.]
+ [+hdr \aname\a?Defines \b_hdr_\b\aname\a if the header
+ \b<\b\aname\a\b.h>\b exists. The \b--config\b macro name is
+ \bHAVE_\b\aNAME\a\b_H\b.]
+ [+if \astatement\a ... | \belif\b \astatement\a ... | \belse\b | \bendif\b?
+ Nested if-else test control.]
+ [+iff \aname\a?The generated header \b#ifndef-#endif\b macro guard is
+ \b_\b\aname\a\b_H\b.]
+ [+inc \afile\a [ re ]]?Read #define macro names from \afile\a
+ and arrange for those names to evaluate to 1 in \bexp\b
+ expressions. If \are\a is specified then macros not matching
+ \are\a are ignored.]
+ [+key \aname\a?Defines \b_key_\b\aname\a if \aname\a is a reserved
+ word (keyword).]
+ [+lcl \aname\a?Generates a \b#include\b statement for the native version
+ of the header \b<\b\aname\a\b.h>\b if it exists. Defines
+ \b_lcl_\b\aname\a on success. The \b--config\b macro name is
+ \bHAVE_\b\aNAME\a\b_H\b. The default \are\a is \b^HAVE_\b
+ for \b--config\b and \b^_\b otherwise.]
+ [+lib \aname\a?Defines \b_lib_\b\aname\a if \aname\a is an external
+ symbol in the default libraries.]
+ [+mac \aname\a?Defines \b_mac_\b\aname\a if \aname\a is a macro.]
+ [+mem \astruct.member\a?Defines \b_mem_\b\amember\a\b_\b\astruct\a
+ if \amember\a is a member of the structure \astruct\a.]
+ [+mth \aname\a?Defines \b_mth_\b\aname\a if \aname\a is an external
+ symbol in the math library.]
+ [+nop \aname\a?If this is the first test then \aname\a may be used
+ to name the output file and/or the output header guard macro.
+ Otherwise this test is ignored.]
+ [+npt \aname\a?Defines \b_npt_\b\aname\a if the \aname\a symbol
+ requires a prototype. The \b--config\b macro name is
+ \bHAVE_\aNAME\a\b_DECL\b with the opposite sense.]
+ [+num \aname\a?Defines \b_num_\b\aname\a if \aname\a is a numeric
+ constant \aenum\a or \amacro\a.]
+ [+nxt \aname\a?Defines a string macro \b_nxt_\b\aname\a suitable for
+ a \b#include\b statement to include the next (on the include
+ path) or native version of the header \b<\b\aname\a\b.h>\b
+ if it exists. Also defines the \"...\" form
+ \b_nxt_\b\aname\a\b_str\b. The \b--config\b macro name is
+ \bHAVE_\b\aNAME\a\b_NEXT\b.]
+ [+one \aheader\a ...?Generates a \b#include\b statement for the first
+ header found in the \aheader\a list.]
+ [+opt \aname\a?Defines \b_opt_\b\aname\a if \aname\a is a space-separated
+ token in the global environment variable \bPACKAGE_OPTIONS\b.]
+ [+pth \afile\a [ \adir\a ... | { \ag1\a - ... - \agn\a } | < \apkg\a [\aver\a ...]] > ]]?Defines
+ \b_pth_\b\afile\a, with embedded \b/\b chars translated to
+ \b_\b, to the path of the first instance of \afile\a in the
+ \adir\a directories. \b{\b ... \b}\b forms a directory list
+ from the cross-product of \b-\b separated directory groups
+ \ag1\a ... \agn\a. < ... > forms a directory list for the
+ package \apkg\a with optional versions. If no operands are
+ specified then the default PATH directories are used. The
+ \b--config\b macro name is \aNAME\a\b_PATH\b.]
+ [+run \afile\a?Runs the tests in \afile\a based on the \afile\a
+ suffix:]{
+ [+.c?\afile\a is compiled and executed and the output is copied
+ to the \biffe\b output file. Macros and headers supplied
+ to \bbegin{\b ... \b}end\b are also supplied to
+ \afile\a.]
+ [+.sh?\afile\a is executed as a shell script and the output is
+ copied to the \biffe\b output file.]
+ [+.iffe \bor no suffix?\afile\a contains \biffe\b
+ statements.]
+ }
+ [+set \aoption value\a?Sets option values. The options are described
+ above.]
+ [+siz \aname\a?Defines \b_siz_\b\aname\a to be \bsizeof\b(\aname\a) if
+ \aname\a is a type in any of \b<sys/types.h>, <times.h>,
+ <stddef.h>, <stdlib.h>\b. Any \b.\b characters in \aname\a are
+ translated to space before testing and are translated to \b_\b
+ in the output macro name.]
+ [+sym \aname\a?Defines \b_ary_\b\aname\a if \aname\a is an array,
+ \b_fun_\b\aname\a if \aname\a is a function pointer,
+ \b_ptr_\b\aname\a if \aname\a is a pointer, or
+ \b_reg_\b\aname\a if \aname\a is a scalar. In most cases
+ \aname\a is part of a macro expansion.]
+ [+sys \aname\a?Defines \b_sys_\b\aname\a if the header
+ \b<sys/\b\aname\a\b.h>\b exists. The \b--config\b macro name is
+ \bHAVE_SYS_\b\aNAME\a\b_H\b.]
+ [+tst \aname\a?A user defined test on name. A source block must be
+ supplied. Defines \b_\b\aname\a on success. \btst - ...\b is
+ treated as \btst - - ...\b.]
+ [+typ \aname\a?Defines \b_typ_\b\aname\a if \aname\a is a type in any
+ of \b<sys/types.h>, <times.h>, <stddef.h>, <stdlib.h>\b. Any
+ \b.\b characters in \aname\a are translated to space before
+ testing and are translated to \b_\b in the output macro name.]
+ [+val \aname\a?The output of \becho\b \aname\a is written to the
+ output file.]
+ [+var \aname\a?A user defined test on name. A source block must be
+ supplied. Sets the \bexp\b variable \b_\b\aname\a on success
+ but does not define a macro.]
+ [+(\aexpression\a)?Equivalent to \bexp -\b \aexpression\a.]
+}
+[+?Code block names may be prefixed by \bno\b to invert the test sense. The
+ block names are:]{
+ [+cat?The block is copied to the output file.]
+ [+compile?The block is compiled (\bcc -c\b).]
+ [+cross?The block is executed as a shell script using \bcrossexec\b(1)
+ if \b--cross\b is on, or on the local host otherwise, and the
+ output is copied to the output file. Test macros are not
+ exported to the script.]
+ [+execute?The block is compiled, linked, and executed. \b0\b exit
+ status means success.]
+ [+fail?If the test fails then the block text is evaluated by
+ \bsh\b(1).]
+ [+link?The block is compiled and linked (\bcc -o\b).]
+ [+macro?The block is preprocessed (\bcc -E\b) and lines containing
+ text bracketed by \b<<"\b ... \b">>\b (\aless-than less-than
+ double-quote ... double-quote greater-than greater-than\a)
+ are copied to the output file with the brackets omitted.]
+ [+no?If the test fails then the block text is copied to the
+ output file. Deprecated: use { \bif\b \belif\b \belse\b
+ \bendif\b } with unnamed \b{\b ... \b}\b blocks.]
+ [+note?If the test succeeds then the block is copied to the output
+ as a \b/*\b ... \b*/\b comment.]
+ [+output?The block is compiled, linked, and executed, and the output
+ is copied to the output file.]
+ [+pass?If the test succeeds then the block text is evaluated by
+ \bsh\b(1).]
+ [+preprocess?The block is preprocessed (\bcc -E\b).]
+ [+run?The block is executed as a shell script and the output is
+ copied to the output file. Succesful test macros are also
+ defined as shell variables with value \b1\b and are available
+ within the block. Likewise, failed test macros are defined
+ as shell variables with value \b0\b.]
+ [+status?The block is compiled, linked, and executed, and the exit
+ status is the test outcome, 0 for \afailure\a, the value
+ otherwise.]
+ [+yes?If the test succeeds then the block text is copied to the output
+ file. \byes{\b ... \b}end\b is equivalent to the unnamed block
+ \b{\b ... \b}\b. Deprecated: use { \bif\b \belif\b \belse\b
+ \bendif\b } with unnamed \b{\b ... \b}\b blocks.]
+}
+[+SEE ALSO?\bautoconf\b(1), \bconfig\b(1), \bgetconf\b(1), \bcrossexec\b(1),
+ \bnmake\b(1), \bpackage\b(1), \bproto\b(1), \bsh\b(1)]
+'
+ while getopts -a "$command" "$USAGE" OPT
+ do case $OPT in
+ a) set="$set set all :" ;;
+ c) set="$set set cc $OPTARG :" ;;
+ C) set="$set set config :" ;;
+ d) set="$set set debug $OPTARG :" ;;
+ D) set="$set set define :" ;;
+ E) set="$set set explicit :" ;;
+ F) set="$set set features $OPTARG :" ;;
+ i) set="$set set input $OPTARG :" ;;
+ I) set="$set set include $OPTARG :" ;;
+ L) set="$set set library $OPTARG :" ;;
+ n) set="$set set namval $OPTARG :" ;;
+ N) set="$set set nooptimize $OPTARG :" ;;
+ o) set="$set set output $OPTARG :" ;;
+ e) set="$set set package $OPTARG :" ;;
+ p) set="$set set prototyped :" ;;
+ P) set="$set set pragma $OPTARG :" ;;
+ r) set="$set set regress :" ;;
+ s) set="$set set shell $OPTARG :" ;;
+ S) set="$set set static $OPTARG :" ;;
+ O) set="$set set stdio $OPTARG :" ;;
+ u) set="$set set undef :" ;;
+ v) set="$set set verbose :" ;;
+ x) set="$set set cross $OPTARG :" ;;
+ X) set="$set set exclude $OPTARG :" ;;
+ esac
+ done
+ shift `expr $OPTIND - 1`
+ ;;
+*) while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -) break
+ ;;
+ --) shift
+ break
+ ;;
+ --a|--al|--all)
+ REM=a
+ ;;
+ --cc=*) REM=c`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --co|--con|--conf|--confi|--config)
+ REM=C
+ ;;
+ --cr=*|--cro=*|--cros=*|--cross=*)
+ REM=x`echo X$1 | sed -e 's,[^=]*=,,'`
+ ;;
+ --d=*|--de=*|--deb=*|--debu=*|--debug=*)
+ REM=d`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --def|--defi|--defin|--define)
+ REM=D
+ ;;
+ --e=*|--ex=*|--exc=*|--excl=*|--exclu=*|--exclud=*|--exclude=*)
+ REM=X`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --e|--ex|--exp|--expl|--expli|--explic|--explici|--explicit)
+ REM=E
+ ;;
+ --f=*|--fe=*|--fea=*|--feat=*|--featu=*|--featur=*|--feature=*|--features=*)
+ REM=F`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --inp=*|--inpu=*|--input=*)
+ REM=i`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --inc=*|--incl=*|--inclu=*|--includ=*|--include=*)
+ REM=I`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --l=*|--li=*|--lib=*|--libr=*|--libra=*|--librar=*|--library=*)
+ REM=L`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --n|--na|--nam|--name|--name-v|--name-va|--name-val|--name-valu|--name-value)
+ REM=n
+ ;;
+ --o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*)
+ REM=o`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --pa=*|--pac=*|--pack=*|--packa=*|--packag=*|--package=*)
+ REM=e`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --pro|--prot|--proto|--protot|--prototy|--prototyp|--prototype|--prototyped)
+ REM=p
+ ;;
+ --pra=*|--prag=*|--pragma=*)
+ REM=P`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --r|--re|--reg|--regre|--regres|--regress)
+ REM=r
+ ;;
+ --sh=*|--she=*|--shel=*|--shell=*)
+ REM=s`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --sta=*|--stat=*|--stati=*|--static=*)
+ REM=S`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --std=*|--stdi=*|--stdio=*)
+ REM=O`echo X$1 | sed 's,[^=]*=,,'`
+ ;;
+ --u|--un|--und|--unde|--undef)
+ REM=u
+ ;;
+ --v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
+ REM=v
+ ;;
+ --*) echo $command: $1: unknown option >&2
+ exit 2
+ ;;
+ -*) REM=`echo X$1 | sed 's,X-,,'`
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ while :
+ do case $REM in
+ '') break ;;
+ esac
+ eval `echo $REM | sed "s,\(.\)\(.*\),OPT='\1' REM='\2',"`
+ case $OPT in
+ [cdFiILoOePsSxX])
+ case $REM in
+ '') case $# in
+ 0) echo $command: -$OPT: option argument expected >&2
+ exit 1
+ ;;
+ esac
+ OPTARG=$1
+ shift
+ ;;
+ *) OPTARG=$REM
+ REM=''
+ ;;
+ esac
+ esac
+ case $OPT in
+ a) set="$set set all :" ;;
+ c) set="$set set cc $OPTARG :" ;;
+ C) set="$set set config :" ;;
+ d) set="$set set debug $OPTARG :" ;;
+ D) set="$set set define :" ;;
+ E) set="$set set explicit :" ;;
+ F) set="$set set features $OPTARG :" ;;
+ i) set="$set set input $OPTARG :" ;;
+ I) set="$set set include $OPTARG :" ;;
+ L) set="$set set library $OPTARG :" ;;
+ n) set="$set set namval $OPTARG :" ;;
+ N) set="$set set nooptimize $OPTARG :" ;;
+ o) set="$set set output $OPTARG :" ;;
+ e) set="$set set package $OPTARG :" ;;
+ p) set="$set set prototyped :" ;;
+ P) set="$set set pragma $OPTARG :" ;;
+ r) set="$set set regress :" ;;
+ s) set="$set set shell $OPTARG :" ;;
+ S) set="$set set static $OPTARG :" ;;
+ O) set="$set set stdio $OPTARG :" ;;
+ u) set="$set set undef :" ;;
+ v) set="$set set verbose :" ;;
+ x) set="$set set cross $OPTARG :" ;;
+ X) set="$set set exclude $OPTARG :" ;;
+ *) echo "Usage: $command [-aCDEnpruv] [-c C-compiler-name [C-compiler-flags ...]] [-d level]
+ [-F features-header] [-i file] [-o file] [-O stdio-header] [-e name] [-P text]
+ [-s shell-path] [-S[flags]] [-x cross-exec-prefix] [-I dir] [-L dir] [-X dir] [ - ]
+ [ file.iffe | statement [ : statement ... ] ]" >&2
+ exit 2
+ ;;
+ esac
+ done
+ done
+ ;;
+esac
+case $1 in
+-) out=-; shift ;;
+esac
+case $# in
+0) in=- ;;
+esac
+set -- $set "$@"
+case " $* " in
+*' set config '*|*' run config.'*|*' run '*' config.'*|*' run '*'/config.'*)
+ config=1
+ ;;
+esac
+
+# standard error to /dev/null unless debugging
+# standard output to the current output file
+#
+# stdout original standard output
+# stderr original standard error
+# nullin /dev/null input
+# nullout /dev/null output
+
+stdout=5 stderr=6 nullin=7 nullout=8
+eval "exec $nullin</dev/null $nullout>/dev/null $stdout>&1 $stderr>&2"
+case " $* " in
+*" set debug "[3456789]*)
+ ;;
+*) eval "exec 2>&$nullout"
+ ;;
+esac
+
+# prompt complications
+
+case `print -n aha </dev/null 2>/dev/null` in
+aha) show='print -n' SHOW='' ;;
+*) case `echo -n aha 2>/dev/null` in
+ -n*) show=echo SHOW='\c' ;;
+ *) show='echo -n' SHOW='' ;;
+ esac
+ ;;
+esac
+
+# tmp files cleaned up on exit
+# status: 0:success 1:failure 2:interrupt
+
+status=1
+case $debug in
+2) core=
+ ;;
+*) if (ulimit -c 0) >/dev/null 2>&1
+ then ulimit -c 0
+ core=
+ else core="core core.??*"
+ fi
+ ;;
+esac
+trap "rm -f $core $tmp*" 0
+if (:>$tmp.c) 2>/dev/null
+then rm -f $tmp.c
+else echo "$command: cannot create tmp files in current dir" >&2
+ exit 1
+fi
+status=2
+
+# standard header for c source
+
+std='#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
+#define _STD_ 1
+#define _ARG_(x) x
+#define _VOID_ void
+#else
+#define _STD_ 0
+#define _ARG_(x) ()
+#define _VOID_ char
+#endif
+#if defined(__cplusplus)
+#define _BEGIN_EXTERNS_ extern "C" {
+#define _END_EXTERNS_ }
+#else
+#define _BEGIN_EXTERNS_
+#define _END_EXTERNS_
+#endif
+#define _NIL_(x) ((x)0)'
+tst=
+ext="#include <stdio.h>"
+noext='*[<"][Ss][Tt][Dd][Ii][Oo].[Hh][">]*|*<ast.h>*|*<sfio.h>*|*/[*]<NOSTDIO>[*]/*'
+
+# loop on op [ arg [ ... ] ] [ : op [ arg [ ... ] ] ]
+
+argx=0
+cur=.
+can=
+cansep=
+cctest=
+file=
+hdrtest=
+ifelse=NONE
+ifstack=
+ini=
+init=1
+line=0
+nan=
+prototyped=
+while :
+do case $in in
+ "") case $argx:$* in
+ 1:$argv);;
+ 1:*) argx=0
+ set x $argv
+ shift
+ ;;
+ esac
+ ;;
+ *) case $ini in
+ '') if read lin
+ then case $shell in
+ ksh) let line=line+1 ;;
+ *) line=`expr $line + 1` ;;
+ esac
+ $posix_noglob
+ set x $lin
+ $posix_glob
+ case $# in
+ 1) continue ;;
+ esac
+ else set x
+ fi
+ ;;
+ *) $posix_noglob
+ set x $ini
+ $posix_glob
+ ini=
+ ;;
+ esac
+ shift
+ case $init in
+ 1) case $1 in
+ iff) init=0
+ ;;
+ print|ref|set)
+ ;;
+ *) init=0
+ ini=$*
+ set ini
+ ;;
+ esac
+ esac
+ ;;
+ esac
+ case $# in
+ 0) case $ifstack in
+ ?*) echo "$command: $file$line: missing endif" >&$stderr
+ exit 1
+ ;;
+ esac
+ set set out +
+ ;;
+ esac
+
+ # if nesting
+
+ while :
+ do case $1 in
+ "if") ifstack="$ifelse:$ifstack"
+ case $ifelse in
+ KEEP|NONE)
+ ifelse=TEST
+ ;;
+ TEST) ;;
+ *) ifelse=DONE
+ ;;
+ esac
+ shift
+ case $explicit in
+ 1) set '' - "$@"; shift ;;
+ esac
+ ;;
+ "elif") case $ifelse in
+ SKIP) ifelse=TEST
+ ;;
+ TEST) ;;
+ *) ifelse=DONE
+ ;;
+ NONE) echo "$command: $file$line: $1: no matching if" >&$stderr
+ exit 1
+ ;;
+ esac
+ shift
+ case $explicit in
+ 1) set '' - "$@"; shift ;;
+ esac
+ ;;
+ "else") case $ifelse in
+ KEEP) ifelse=DONE
+ ;;
+ SKIP|TEST)
+ ifelse=KEEP
+ ;;
+ NONE) echo "$command: $file$line: $1: no matching if" >&$stderr
+ exit 1
+ ;;
+ esac
+ shift
+ ;;
+ "endif")case $ifelse in
+ NONE) echo "$command: $file$line: $1: no matching if" >&$stderr
+ exit 1
+ ;;
+ esac
+ case $shell in
+ ksh) ifelse=${ifstack%%:*}
+ ifstack=${ifstack#*:}
+ ;;
+ *) eval `echo $ifstack | sed 's,\([^:]*\):\(.*\),ifelse=\1 ifstack=\2,'`
+ ;;
+ esac
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+ done
+
+ # check if "run xxx" is equivalent to "set in xxx"
+
+ case $1 in
+ "("*) set exp - "$@" ;;
+ *.iffe|*.iff) set run "$@" ;;
+ esac
+ case $1 in
+ :) shift
+ continue
+ ;;
+ run) case $shell in
+ bsh) case $2 in
+ */*) x=`echo $2 | sed 's,.*[\\\\/],,'` ;;
+ *) x=$2 ;;
+ esac
+ ;;
+ *) eval 'x=${2##*[\\/]}'
+ ;;
+ esac
+ case $x in
+ *.iffe|*.iff)
+ set set in $2 ;;
+ *.*) ;;
+ *) set set in $2 ;;
+ esac
+ ;;
+ esac
+
+ # { inc set } drop out early
+
+ case $1 in
+ ""|"#"*)continue
+ ;;
+ inc) case $ifelse in
+ DONE|SKIP) set ''; shift; continue ;;
+ esac
+ shift
+ case $# in
+ 0) echo "$command: $file$line: path expected" >&$stderr
+ exit 1
+ ;;
+ esac
+ p=$1
+ shift
+ if test ! -f $p
+ then echo "$command: $file$line: $p: file not found" >&$stderr
+ exit 1
+ fi
+ case $# in
+ 0) case $config in
+ 1) e="^HAVE_" ;;
+ *) e="^_" ;;
+ esac
+ ;;
+ 1) e=$1
+ ;;
+ *) shift
+ echo "$command: $file$line: warning: $*: operands ignored" >&$stderr
+ ;;
+ esac
+ eval `sed -e '/^#define[ ]/!d' -e 's/#define[ ]//' -e 's/[ (].*//' ${e:+"-e/$e/!d"} -e 's/.*/&=1/' $p | LC_ALL=C sort -u`
+ continue
+ ;;
+ set) case $ifelse in
+ DONE|SKIP) set ''; shift; continue ;;
+ esac
+ shift
+ case $1 in
+ ""|"#"*)op=
+ ;;
+ *) arg=
+ op=$1
+ case $op in
+ --*) case $shell in
+ bsh) op=`echo X$op | sed 's/X--//'` ;;
+ *) op=${op#--} ;;
+ esac
+ ;;
+ -*) case $op in
+ -??*) case $shell in
+ bsh) arg=`echo X$op | sed 's/X-.//'`
+ op=`echo X$op | sed 's/X\\(-.\\).*/\\1/'`
+ ;;
+ *) arg=${op#-?}
+ op=${op%$arg}
+ ;;
+ esac
+ ;;
+ esac
+ case $op in
+ a) op=all ;;
+ c) op=cc ;;
+ C) op=config ;;
+ d) op=debug ;;
+ D) op=define ;;
+ E) op=explicit ;;
+ F) op=features ;;
+ i) op=input ;;
+ I) op=include ;;
+ L) op=library ;;
+ n) op=namval ;;
+ N) op=nooptimize ;;
+ o) op=output ;;
+ e) op=package ;;
+ p) op=prototyped ;;
+ P) op=pragma ;;
+ r) op=regress ;;
+ s) op=shell ;;
+ S) op=static ;;
+ O) op=stdio ;;
+ u) op=undef ;;
+ v) op=verbose ;;
+ x) op=cross ;;
+ X) op=exclude ;;
+ esac
+ ;;
+ esac
+ shift
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ *" "*) shift
+ continue
+ ;;
+ ""|"#"*)break
+ ;;
+ :) shift
+ break
+ ;;
+ esac
+ case $arg in
+ "") arg=$1 ;;
+ *) arg="$arg $1" ;;
+ esac
+ shift
+ done
+ ;;
+ esac
+ case $op in
+ all) all=1
+ continue
+ ;;
+ cc) occ=
+ for x in $arg
+ do case $occ in
+ "") case $x in
+ *=*) case $shell in
+ bsh) eval $x
+ export `echo $x | sed 's/=.*//'`
+ ;;
+ *) export $x
+ ;;
+ esac
+ ;;
+ -O*) case $optimize in
+ 1) occ=$x ;;
+ esac
+ ;;
+ *) occ=$x
+ ;;
+ esac
+ ;;
+ *) occ="$occ $x"
+ ;;
+ esac
+ done
+ exclude occ
+ continue
+ ;;
+ config) config=1
+ continue
+ ;;
+ cross) case $arg in
+ ""|-) cross= ;;
+ *) cross="$arg" libpaths= ;;
+ esac
+ continue
+ ;;
+ debug) debug=$arg
+ case $arg in
+ 0) exec 2>&$nullout
+ set -
+ show=echo
+ SHOW=
+ ;;
+ ""|1) exec 2>&$stderr
+ set -
+ show=echo
+ SHOW=
+ ;;
+ 2|3) exec 2>&$stderr
+ case $shell in
+ ksh) eval 'PS4="${PS4%+*([ ])}+\$LINENO+ "'
+ esac
+ show=echo
+ SHOW=
+ set -x
+ ;;
+ *) echo "$command: $arg: debug levels are 0, 1, 2, 3" >&$stderr
+ ;;
+ esac
+ continue
+ ;;
+ define) define=1
+ continue
+ ;;
+ exclude)case $arg in
+ ""|-) excludes= ;;
+ *) excludes="$excludes $arg" ;;
+ esac
+ exclude includes occ
+ continue
+ ;;
+ explicit)
+ explicit=1
+ continue
+ ;;
+ features)case $arg in
+ '') tst= ;;
+ *) tst="#include \"$arg\"" ;;
+ esac
+ continue
+ ;;
+ "in"|input)
+ case $arg in
+ "") in=-
+ ;;
+ *) in=$arg
+ if test ! -r $in
+ then echo "$command: $in: not found" >&$stderr
+ exit 1
+ fi
+ exec < $in
+ file=$in:
+ case $out in
+ "") case $in in
+ *[.\\/]*)
+ case $shell in
+ bsh) eval `echo $in | sed -e 's,.*[\\\\/],,' -e 's/\\.[^.]*//' -e 's/^/out=/'`
+ ;;
+ *) eval 'out=${in##*[\\/]}'
+ eval 'out=${out%.*}'
+ ;;
+ esac
+ ;;
+ *) out=$in
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+ include)case $arg in
+ ""|-) includes= ;;
+ *) includes="$includes -I$arg" ;;
+ esac
+ exclude includes
+ continue
+ ;;
+ library)for y in $libpaths
+ do eval $y=\"\$$y:\$arg\$${y}_default\"
+ eval export $y
+ done
+ continue
+ ;;
+ namval) define=n
+ continue
+ ;;
+ nodebug)exec 2>&$nullout
+ set -
+ continue
+ ;;
+ nodefine)
+ define=0
+ continue
+ ;;
+ nooptimize)
+ optimize=0
+ case $occ in
+ *" -O"*)occ=`echo $occ | sed 's/ -O[^ ]*//g'`
+ cc=$occ
+ ;;
+ esac
+ ;;
+ optimize)
+ optimize=1
+ ;;
+ out|output)
+ out=$arg
+ defhdr=
+ usr=
+ deflib=
+ one=
+ puthdr=
+ putlib=
+ case $op in
+ output) continue ;;
+ esac
+ def=
+ test=
+ ;;
+ package)protoflags="$protoflags -e $arg"
+ continue
+ ;;
+ prototyped|noprototyped)
+ pragma="$pragma $op"
+ case $op in
+ prototyped) prototyped=1 ;;
+ *) prototyped= ;;
+ esac
+ continue
+ ;;
+ pragma) pragma="$pragma $arg"
+ continue
+ ;;
+ regress)regress=1
+ version=1995-03-19
+ continue
+ ;;
+ shell) case $arg in
+ osh) posix_read=-no
+ shell=bsh
+ ;;
+ esac
+ shell=$arg
+ continue
+ ;;
+ static) static=$arg
+ continue
+ ;;
+ stdio) case $arg in
+ '') ext=
+ ;;
+ *) ext=
+ sep=
+ for i in $arg
+ do case $i in
+ -) case $ext in
+ '') continue ;;
+ *) break ;;
+ esac
+ ;;
+ esac
+ echo "#include \"$i\"" > t.c
+ if $cc -E t.c > /dev/null 2>&1
+ then ext="$ext$sep#include \"$arg\""
+ sep=$nl
+ fi
+ done
+ ;;
+ esac
+ continue
+ ;;
+ undef) undef=1
+ continue
+ ;;
+ verbose)verbose=1
+ continue
+ ;;
+ *) echo "$command: $op: unknown option" >&$stderr
+ exit 1
+ ;;
+ esac
+ ;;
+ api|define|extern|header|include|print|reference|ver)
+ op=$1
+ shift
+ arg=
+ ;;
+ *) case $2 in
+ '=') def=$1
+ shift
+ shift
+ ;;
+ *) case $1 in
+ '-'|'?')def=-
+ shift
+ ;;
+ *) def=
+ ;;
+ esac
+ ;;
+ esac
+ case $1 in
+ '!') not=1
+ shift
+ ;;
+ *) not=
+ ;;
+ esac
+ case $1 in
+ *'{') op=-
+ ;;
+ '('*|'"'*'"'|'<'*'>')
+ op=exp
+ case $def in
+ '') def=- ;;
+ esac
+ ;;
+ *) op=$1
+ shift
+ ;;
+ esac
+ arg=
+ cc="$occ $includes"
+ group=
+ groups=
+ fail=
+ hdr=
+ lib=
+ mac=
+ no=
+ note=
+ opt=
+ pass=
+ pth=
+ run=
+ set=
+ src=
+ test=
+ yes=
+ case $# in
+ 0) ;;
+ *) case $1 in
+ "#"*) set x
+ shift
+ ;;
+ *) case $op in
+ ref) ;;
+ *) case $1 in
+ '-') case $op:$2 in
+ tst:*) arg=$1
+ case $2 in
+ -) shift ;;
+ esac
+ ;;
+ *:-*) arg=$1
+ shift
+ ;;
+ *) def=-
+ shift
+ case $1 in
+ '('*|*'{'|'"'*'"'|'<'*'>')
+ arg=-
+ ;;
+ *) arg=$1
+ case $# in
+ 0) ;;
+ *) shift ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ -*|+*|'('*|*'{'|'"'*'"'|'<'*'>')
+ arg=-
+ ;;
+ *) arg=$1
+ shift
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $1 in
+ '('*|'"'*'"'|'<'*'>')
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ *[.{}]*)break ;;
+ esac
+ case $test in
+ '') test=$1 ;;
+ *) test="$test $1" ;;
+ esac
+ shift
+ done
+ case $arg in
+ '') arg=- ;;
+ esac
+ case $op in
+ exp) case $def in
+ ''|'-') ;;
+ *) arg=$def ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ sline=$line
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ "") ;;
+ "#"*) set x
+ ;;
+ "=") shift
+ set=$*
+ case $set in
+ "") set=" " ;;
+ esac
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ shift
+ done
+ break
+ ;;
+ [abcdefghijklmnopqrstuvwxyz]*'{'|'{')
+ v=$1
+ shift
+ x=
+ case $v in
+ "note{")
+ sep=" " ;;
+ *) sep=$nl ;;
+ esac
+ case $v in
+ '{') e='}' ;;
+ *) e='}end' ;;
+ esac
+ n=1
+ SEP=
+ while :
+ do case $# in
+ 0) case $posix_read in
+ -*) checkread ;;
+ esac
+ case $in in
+ "") echo "$command: $file$line: missing }end" >&$stderr
+ exit 1
+ ;;
+ esac
+ while :
+ do case $posix_read in
+ 1) case $shell in
+ ksh) IFS= read -r lin
+ eof=$?
+ while :
+ do lin="${lin#[' ']}"
+ case $lin in
+ [' ']*'#'*);;
+ *) break ;;
+ esac
+ done
+ ;;
+ *) IFS=
+ read -r lin
+ eof=$?
+ IFS=$ifs
+ case $lin in
+ [' ']*) lin=`sed -e 's,^[ ],,' -e 's,^[ ]*#,#,' <<!
+$lin
+!
+`
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) lin=`$posix_read`
+ eof=$?
+ ;;
+ esac
+ case $eof in
+ 0) case $shell in
+ ksh) let line=line+1 ;;
+ *) line=`expr $line + 1` ;;
+ esac
+ $posix_noglob
+ set x $lin
+ $posix_glob
+ case $2 in
+ $v) case $shell in
+ ksh) let n=n+1 ;;
+ *) n=`expr $n + 1` ;;
+ esac
+ ;;
+ $e|$e';')
+ case $n in
+ 1) shift
+ break 2
+ ;;
+ esac
+ case $shell in
+ ksh) let n=n-1 ;;
+ *) n=`expr $n - 1` ;;
+ esac
+ ;;
+ esac
+ x="$x$SEP$lin"
+ SEP=$sep
+ ;;
+ *) echo "$command: $file$line: missing $e" >&$stderr
+ exit 1
+ ;;
+ esac
+ done
+ ;;
+ esac
+ case $1 in
+ $v) case $shell in
+ ksh) let n=n+1 ;;
+ *) n=`expr $n + 1` ;;
+ esac
+ ;;
+ $e|$e';')
+ case $n in
+ 1) break ;;
+ esac
+ case $shell in
+ ksh) let n=n-1 ;;
+ *) n=`expr $n - 1` ;;
+ esac
+ ;;
+ esac
+ x="$x$SEP$1"
+ SEP=$sep
+ shift
+ done
+ case $v in
+ 'note{');;
+ *) x="$x$nl" # \r\n bash needs this barf # ;;
+ esac
+ case $v in
+ 'fail{') fail=$x ;;
+ 'nofail{') pass=$x v='pass{' ;;
+ 'nopass{') fail=$x v='fail{' ;;
+ 'no{') no=$x ;;
+ 'note{') note=$x ;;
+ 'pass{') pass=$x ;;
+ 'test{') test=$x ;;
+ 'yes{'|'{') yes=$x ;;
+ *) src=$x run=$v ;;
+ esac
+ ;;
+ :) shift
+ break
+ ;;
+ *[\"\'\(\)\{\}\ \ ]*)
+ case $op in
+ pth) pth="$pth $1"
+ ;;
+ *) case $test in
+ '') test=$1 ;;
+ *) test="$test $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ -) group=$group$1
+ case $group in
+ -) com_hdr=$hdr
+ com_lib=$lib
+ com_mac=$mac
+ com_opt=$opt
+ com_pth=$pth
+ com_test=$test
+ ;;
+ *) groups="$groups $1"
+ ;;
+ esac
+ ;;
+ -l*) case $group in
+ --*) groups="$groups $1" ;;
+ *) lib="$lib $1" ;;
+ esac
+ ;;
+ +l*) case $shell in
+ bsh) x=`echo X$1 | sed 's/X+/-/'` ;;
+ *) eval 'x=-${1#+}' ;;
+ esac
+ case $group in
+ --*) groups="$groups $x" ;;
+ *) lib="$lib $x" ;;
+ esac
+ ;;
+ -*|+*) case $op in
+ ref) cc="$cc $1"
+ occ="$occ $1"
+ case $1 in
+ -L*) case $shell in
+ ksh) x=${1#-L} ;;
+ *) x=`echo x$1 | sed 's,^x-L,,'` ;;
+ esac
+ for y in $libpaths
+ do eval $y=\"\$$y:\$x\$${y}_default\"
+ eval export $y
+ done
+ ;;
+ esac
+ ;;
+ *) case $group in
+ --*) groups="$groups $1"
+ ;;
+ *) case $op in
+ run) opt="$opt $1"
+ ;;
+ *) case $1 in
+ -D*) mac="$mac $1" ;;
+ *) cc="$cc $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *.[aAxX]|*.[dD][lL][lL]|*.[lL][iI][bB])
+ case $group in
+ --*) groups="$groups $1" ;;
+ *) lib="$lib $1" ;;
+ esac
+ ;;
+ *[.\\/]*)
+ case $group in
+ --*) groups="$groups $1"
+ ;;
+ *) case $op in
+ pth) pth="$pth $1" ;;
+ *) hdr="$hdr $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) case $group in
+ --*) groups="$groups $1"
+ ;;
+ *) case $op in
+ pth) pth="$pth $1"
+ ;;
+ *) case $test in
+ '') test=$1 ;;
+ *) test="$test $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ shift
+ done
+ case $group in
+ -) group= ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $ifelse in
+ DONE|SKIP) continue ;;
+ esac
+
+ # make sure $cc compiles C
+
+ case $cc in
+ "") cc="$occ $includes" ;;
+ esac
+ case $cctest in
+ "") checkcc ;;
+ esac
+
+ # some ops allow no args
+
+ case $arg in
+ '') case $op in
+ api) arg=-
+ case $1:$2 in
+ [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]*:[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
+ a=$1
+ shift
+ case " $apis " in
+ *" $a "*)
+ ;;
+ *) apis="$apis $a"
+ eval api_sym_${a}= api_ver_${a}=
+ ;;
+ esac
+ rel=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
+ rel="$rel $1"
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ done
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :) break ;;
+ esac
+ eval syms='$'api_sym_${a}
+ case $syms in
+ '') sep='' ;;
+ *) sep=$nl ;;
+ esac
+ for r in $rel
+ do syms=$syms$sep${1}:${r}
+ sep=$nl
+ done
+ eval api_sym_${a}='$'syms
+ shift
+ done
+ ;;
+ *) echo "$command: $op: expected: name YYYYMMDD symbol ..." >&$stderr
+ ;;
+ esac
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :) break ;;
+ esac
+ shift
+ done
+ ;;
+ iff|ini)arg=-
+ ;;
+ comment)copy - "/* $* */"
+ continue
+ ;;
+ define) x=$1
+ shift
+ case $1 in
+ '('*')')
+ arg=$1
+ shift
+ ;;
+ esac
+ case $in in
+ "") v=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ t=$1
+ shift
+ case $t in
+ ":") break ;;
+ esac
+ v="$v $t"
+ done
+ ;;
+ *) v=$*
+ ;;
+ esac
+ is mac $x
+ copy $tmp.c "$std
+$usr
+#ifndef $x
+(
+#endif
+int x;
+"
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then success -
+ else failure -
+ copy - "#define $x$arg $v"
+ usr="$usr${nl}#define $x$arg $v"
+ fi
+ continue
+ ;;
+ extern) x=$1
+ shift
+ t=$1
+ shift
+ is npt $x
+ copy $tmp.c "
+$std
+#include <sys/types.h>
+$usr
+_BEGIN_EXTERNS_
+struct _iffe_struct { int _iffe_member; };
+extern struct _iffe_struct* $x _ARG_((struct _iffe_struct*));
+_END_EXTERNS_
+"
+ # some compilers with -O only warn for invalid intrinsic prototypes
+ case " $cc " in
+ *" -O "*) xx=`echo $cc | sed 's/ -O / /g'` ;;
+ *) xx=$cc ;;
+ esac
+ if compile $xx -c $tmp.c <&$nullin >&$nullout
+ then success -
+ while :
+ do case $1 in
+ ''|'('*|'['*)
+ break
+ ;;
+ esac
+ t="$t $1"
+ shift
+ done
+ case $in in
+ "") v=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ t=$1
+ shift
+ case $t in
+ ":") break ;;
+ esac
+ v="$v $t"
+ done
+ ;;
+ *) v=$*
+ ;;
+ esac
+ copy - "extern $t $x$v;"
+ # NOTE: technically if prototyped is on all tests should
+ # be run through proto(1), but we'd like iffe to
+ # work sans proto -- so we drop the extern's in
+ # the test headers
+ case $prototyped in
+ '') usr="$usr${nl}extern $t $x$v;" ;;
+ esac
+ else failure -
+ case $in in
+ "") while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ ":") break ;;
+ esac
+ done
+ ;;
+ esac
+ fi
+ continue
+ ;;
+ header|include|reference)
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ x=$1
+ shift
+ case $x in
+ ":") break ;;
+ esac
+ case " $gothdr " in
+ *" - $x "*)
+ ;;
+ *" + $x "*)
+ case $usr in
+ *"# include <"$x">"*)
+ ;;
+ *) case $op in
+ reference)
+ ;;
+ *) copy - "#include <$x>"
+ ;;
+ esac
+ usr="$usr${nl}#include <$x>"
+ ;;
+ esac
+ ;;
+ *) copy $tmp.c "$std
+$usr
+#include <$x>
+int x;
+"
+ if is_hdr - $x
+ then gothdr="$gothdr + $x"
+ case $op in
+ reference)
+ ;;
+ *) copy - "#include <$x>"
+ ;;
+ esac
+ usr="$usr${nl}#include <$x>"
+ else gothdr="$gothdr - $x"
+ fi
+ ;;
+ esac
+ done
+ continue
+ ;;
+ print) case $in in
+ "") v=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ t=$1
+ shift
+ case $t in
+ ":") break ;;
+ esac
+ v="$v $t"
+ done
+ ;;
+ *) v=$*
+ ;;
+ esac
+ copy - "$*"
+ usr="$usr${nl}$v"
+ continue
+ ;;
+ ver) arg=-
+ case $1:$2 in
+ [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]*:[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
+ vers="$vers$nl$1"
+ eval ver_$1=$2
+ ;;
+ *) echo "$command: $op: expected: name YYYYMMDD" >&$stderr
+ ;;
+ esac
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :) break ;;
+ esac
+ shift
+ done
+ ;;
+ esac
+ ;;
+ esac
+
+ # save $* for ancient shells
+
+ argx=1
+ argv=$*
+
+ # loop on all candidate groups
+
+ while :
+ do
+ # check the candidate macros
+
+ cc="$cc $mac"
+
+ # check for global default headers (some cc -E insist on compiling)
+
+ case $hdrtest in
+ '') hdrtest=1
+ allinc=
+ for x in types
+ do case $config in
+ 0) c=_sys_${x}
+ ;;
+ 1) case $shell in
+ ksh) typeset -u u=$x ;;
+ *) u=`echo $x | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ c=HAVE_SYS_${u}_H
+ ;;
+ esac
+ x=sys/$x.h
+ echo "${allinc}#include <$x>" > $tmp.c
+ if is_hdr $x
+ then gothdr="$gothdr + $x"
+ case $explicit in
+ 0) can="$can$cansep#define $c 1 /* #include <$x> ok */"
+ nan="$nan$cansep$c=1"
+ cansep=$nl
+ ;;
+ esac
+ eval $c=1
+ allinc="${allinc}#include <$x>$nl"
+ else gothdr="$gothdr - $x"
+ case $explicit$all$config$undef in
+ 0?1?|0??1)
+ can="$can$cansep#undef $c /* #include <$x> not ok */"
+ nan="$nan$cansep$c="
+ cansep=$nl
+ ;;
+ 01??) can="$can$cansep#define $c 0 /* #include <$x> not ok */"
+ nan="$nan$cansep$c=0"
+ cansep=$nl
+ ;;
+ esac
+ fi
+ done
+ ;;
+ esac
+
+ # add implicit headers/libraries before the checks
+
+ case $op in
+ npt) hdr="sys/types.h stdlib.h unistd.h $hdr"
+ ;;
+ siz|typ)hdr="sys/types.h time.h sys/time.h sys/times.h stddef.h stdlib.h $hdr"
+ ;;
+ esac
+
+ # check the candidate headers
+
+ case $hdr in
+ ?*) z=$hdr
+ hdr=
+ dis=0
+ for x in $z
+ do case $x in
+ *.h) case " $gothdr " in
+ *" - $x "*)
+ continue
+ ;;
+ *" + $x "*)
+ ;;
+ *) case $shell in
+ bsh) eval `echo $x | sed -e 's,^\\([^\\\\/]*\\).*[\\\\/]\\([^\\\\/]*\\)\$,\\1_\\2,' -e 's/\\..*//' -e 's/^/c=/'`
+ ;;
+ *) eval 'c=${x##*[\\/]}'
+ eval 'c=${c%%.*}'
+ case $x in
+ */*) eval 'c=${x%%[\\/]*}_${c}' ;;
+ esac
+ ;;
+ esac
+ case $explicit in
+ 0) dis=0
+ ;;
+ *) case $x in
+ */*) dis=$c ;;
+ *) dis=hdr ;;
+ esac
+ case ${dis}_ in
+ ${op}_*)dis=0 ;;
+ *) dis=1 ;;
+ esac
+ ;;
+ esac
+ case $config in
+ 0) case $x in
+ */*) c=_${c} ;;
+ *) c=_hdr_${c} ;;
+ esac
+ ;;
+ 1) case $shell in
+ ksh) typeset -u u=$c ;;
+ *) u=`echo $c | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ c=HAVE_${u}_H
+ ;;
+ esac
+ echo "${allinc}#include <$x>" > $tmp.c
+ if is_hdr $x
+ then gothdr="$gothdr + $x"
+ case $dis in
+ 0) can="$can$cansep#define $c 1 /* #include <$x> ok */"
+ nan="$nan$cansep$c=1"
+ cansep=$nl
+ ;;
+ esac
+ eval $c=1
+ else gothdr="$gothdr - $x"
+ case $dis$all$config$undef in
+ 0?1?|0??1)
+ can="$can$cansep#undef $c /* #include <$x> not ok */"
+ nan="$nan$cansep$c="
+ cansep=$nl
+ ;;
+ 01??) can="$can$cansep#define $c 0 /* #include <$x> not ok */"
+ nan="$nan$cansep$c=0"
+ cansep=$nl
+ ;;
+ esac
+ continue
+ fi
+ ;;
+ esac
+ ;;
+ *) test -r $x || continue
+ ;;
+ esac
+ hdr="$hdr $x"
+ done
+ ;;
+ esac
+
+ # check the candidate libraries
+
+ case $lib in
+ ?*) z=$lib
+ lib=
+ p=
+ hit=0
+ echo "int main(){return(0);}" > $tmp.c
+ for x in $z
+ do p=$x
+ case " $gotlib " in
+ *"- $p "*)
+ failure +
+ p=
+ ;;
+ *"+ $p "*)
+ success +
+ lib="$lib $p"
+ ;;
+ *) rm -f $tmp.exe
+ is LIB $p
+ if compile $cc -o $tmp.exe $tmp.c $p <&$nullin >&$nullout
+ then success
+ gotlib="$gotlib + $p"
+ lib="$lib $p"
+ e=0
+ else a=
+ e=1
+ for l in $z
+ do case $l in
+ -) a=
+ continue
+ ;;
+ $p) a=$p
+ continue
+ ;;
+ *) case $gotlib in
+ *" $l "*) continue ;;
+ esac
+ ;;
+ esac
+ case $a in
+ $p) a="$a $l"
+ if compile $cc -o $tmp.exe $tmp.c $a <&$nullin >&$nullout
+ then success
+ gotlib="$gotlib + $p"
+ lib="$lib $p"
+ e=0
+ break
+ fi
+ ;;
+ esac
+ done
+ case $e in
+ 1) failure
+ gotlib="$gotlib - $p"
+ ;;
+ esac
+ fi
+ y=
+ for x in $p
+ do case $shell in
+ bsh) c=`echo X$x | sed 's,X-l,,'` ;;
+ *) eval 'c=${x#-l}' ;;
+ esac
+ case $c in
+ *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*)
+ c=`echo '' $c | sed -e 's,.*[\\\\/],,' -e 's,\.[^.]*$,,' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g' -e '/^lib./s,^lib,,'`
+ ;;
+ esac
+ case $config in
+ 0) case $e$p in
+ 0*' '*) case " $gotlib " in
+ *[-+]" $x "*)
+ ;;
+ *) can="$can$cansep#define _LIB_$c 1 /* $x is a library */"
+ nan="$nan${cansep}_LIB_$c=1"
+ cansep=$nl
+ eval _LIB_$c=1
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ 1) case $shell in
+ ksh) typeset -u u=$c ;;
+ *) u=`echo $c | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ c=$u
+ case $e in
+ 0*' '*) case " $gotlib " in
+ *[-+]" $x "*)
+ ;;
+ *) can="$can$cansep#define HAVE_${c}_LIB 1 /* $x is a library */"
+ nan="$nan${cansep}HAVE_${c}_LIB=1"
+ cansep=$nl
+ eval HAVE_${c}_LIB=1
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ y=${y}_$c
+ done
+ case $config in
+ 0) c=_LIB${y} ;;
+ 1) c=HAVE${y}_LIB ;;
+ esac
+ case $p in
+ *' '*) q="a library group" ;;
+ *) q="a library" ;;
+ esac
+ case $e in
+ 0) can="$can$cansep#define $c 1 /* $p is $q */"
+ nan="$nan$cansep$c=1"
+ cansep=$nl
+ eval $c=1
+ case $hit in
+ 1) break ;;
+ esac
+ ;;
+ 1) case $all$config$undef in
+ ?1?|??1)can="$can$cansep#undef $c /* $p is not $q */"
+ nan="$nan$cansep$c="
+ cansep=$nl
+ ;;
+ 1??) can="$can$cansep#define $c 0 /* $p is not $q */"
+ nan="$nan$cansep$c=0"
+ cansep=$nl
+ ;;
+ esac
+ eval $c=0
+ ;;
+ esac
+ p=
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # last op precheck
+
+ case $op in
+ ref) deflib="$deflib $lib"
+ defhdr="$defhdr $hdr"
+ break
+ ;;
+ esac
+ IFS=" ,"
+ case $shell in
+ bash) op=`echo $op`
+ arg=`echo $arg`
+ ;;
+ *) eval op=\"$op\"
+ eval arg=\"$arg\"
+ ;;
+ esac
+ IFS=$ifs
+
+ # check for op aliases
+
+ x=
+ for o in $op
+ do case $o in
+ def|default) x="$x cmd dat hdr key lib mth sys typ" ;;
+ *) x="$x $o" ;;
+ esac
+ done
+
+ # loop on the ops o and args a
+
+ result=UNKNOWN
+ for o in $x
+ do for a in $arg
+ do c=
+ case $a in
+ *[.\\/]*)
+ case $o in
+ hdr|lcl|nxt|pth|sys)
+ x=$a
+ case $x in
+ *.lcl|*.nxt)
+ case $o in
+ sys) x=sys/$x ;;
+ esac
+ case $shell in
+ bsh) eval `echo $x | sed 's,\\(.*\\)\.\\([^.]*\\),x=\\1 o=\\2,'`
+ ;;
+ *) o=${x##*.}
+ x=${x%.${o}}
+ ;;
+ esac
+ v=$x
+ ;;
+ esac
+ case $x in
+ *[\\/]*)case $shell in
+ bsh) eval `echo $x | sed 's,\\(.*\\)[\\\\//]\\(.*\\),p=\\1 v=\\2,'`
+ ;;
+ *) eval 'p=${x%/*}'
+ eval 'v=${x##*/}'
+ ;;
+ esac
+ ;;
+ *.*) case $shell in
+ bsh) eval `echo $x | sed 's,\\(.*\\)\\.\\(.*\\),p=\\1 v=\\2,'`
+ ;;
+ *) eval 'p=${x%.*}'
+ eval 'v=${x##*.}'
+ ;;
+ esac
+ ;;
+ *) p=
+ ;;
+ esac
+ case $o in
+ lcl|nxt) c=$v.$o ;;
+ *) c=$v ;;
+ esac
+ ;;
+ *) case $shell in
+ bsh) eval `echo $a | sed -e 's,.*[\\\\/],,' -e 's/\\(.*\\)\\.\\(.*\\)/p=\\1 v=\\2/'`
+ ;;
+ *) eval 'p=${a%.*}'
+ eval 'p=${p##*[\\/]}'
+ eval 'v=${a##*.}'
+ eval 'v=${v##*[\\/]}'
+ ;;
+ esac
+ ;;
+ esac
+ case $p in
+ '') f=${v} ;;
+ *) f=${p}/${v} ;;
+ esac
+ case $o in
+ run) v=$p
+ p=
+ m=_${v}
+ ;;
+ mem) case $p in
+ *.*) case $shell in
+ bsh) eval `echo $p | sed 's/\\([^.]*\\)\\.\\(.*\\)/p=\\1 m=\\2/'`
+ ;;
+ *) eval 'm=${p#*.}'
+ eval 'p=${p%%.*}'
+ ;;
+ esac
+ v=${m}.${v}
+ esac
+ case $config in
+ 0) m=_${v}_${p} ;;
+ 1) m=_${v}_in_${p} ;;
+ esac
+ ;;
+ *) case $p in
+ '') m=_${v} ;;
+ *) m=_${p}_${v} ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) p=
+ v=$a
+ f=$a
+ m=_${v}
+ ;;
+ esac
+ case $c in
+ '') c=$v ;;
+ esac
+ M=$m
+ case $o in
+ out) case $a in
+ -) a=-
+ ;;
+ ?*) test="$a $test"
+ a=
+ ;;
+ esac
+ ;;
+ *) case " $idyes " in
+ *" $m "*)
+ i=1
+ ;;
+ *) case " $idno " in
+ *" $m "*)
+ i=0
+ ;;
+ *) case $m in
+ *'*') m=`echo "$m" | sed 's,\*,_ptr,g'` ;;
+ esac
+ case $m in
+ *[-+/\\]*)
+ i=0
+ ;;
+ *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*)
+ is id $m
+ copy $tmp.c "int $m = 0;"
+ if compile $cc -c $tmp.c
+ then success -
+ idyes="$idyes $m"
+ i=1
+ else failure -
+ idno="$idno $m"
+ i=0
+ fi
+ ;;
+ *) i=1
+ ;;
+ esac
+ ;;
+ esac
+ case $i in
+ 0) case $o in
+ dat|dfn|key|lib|mac|mth|nos|npt|siz|sym|typ|val)
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $m in
+ *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*)
+ m=`echo "X$m" | sed -e 's,^.,,' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g'`
+ ;;
+ esac
+
+ # check output redirection
+
+ case $out in
+ $cur) ;;
+ *) case $cur in
+ $a|$c) ;;
+ *) case $cur in
+ .) ;;
+ *) case $vers in
+ ?*) echo
+ for api in $vers
+ do API=`echo $api | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+ eval ver='${'ver_${api}'}'
+ echo "#define ${API}_VERSION ${ver}"
+ done
+ esac
+ case $apis in
+ ?*) for api in $apis
+ do map=
+ sep=
+ eval syms='"${'api_sym_${api}'}"'
+ # old solaris requires -k<space><junk> #
+ set x x `echo "$syms" | sort -t: -u -k 1,1 -k 2,2nr 2>/dev/null | sed 's/:/ /'`
+ case $# in
+ 2) # ancient sort doesn't have -k #
+ set x x `echo "$syms" | sort -t: -u +0 -1 +1 -2nr 2>/dev/null | sed 's/:/ /'`
+ ;;
+ esac
+ sym=
+ while :
+ do shift 2
+ case $# in
+ [01]) break ;;
+ esac
+ prv=$sym
+ sym=$1
+ rel=$2
+ case $prv in
+ $sym) echo "#elif _API_${api} >= $rel"
+ ;;
+ *) case $prv in
+ '') echo
+ echo "#if !defined(_API_${api}) && defined(_API_DEFAULT)"
+ echo "#define _API_${api} _API_DEFAULT"
+ echo "#endif"
+ ;;
+ *) echo "#endif"
+ ;;
+ esac
+ echo
+ echo "#if ( _BLD_${api} || !_API_${api} || _API_${api} >= $rel )"
+ ;;
+ esac
+ echo "#undef ${sym}"
+ echo "#define ${sym} ${sym}_${rel}"
+ map=$map$sep${sym}_${rel}
+ sep=' '
+ done
+ echo "#endif"
+ echo
+ echo "#define _API_${api}_MAP \"$map\""
+ done
+ echo
+ ;;
+ esac
+ case $iff in
+ ?*) echo "#endif" ;;
+ esac
+ case $cur in
+ -) ;;
+ *) exec >/dev/null
+ case $cur in
+ *[\\/]*|*.h) x=$cur ;;
+ *) x=$dir/$cur ;;
+ esac
+ case $define in
+ n) sed '/^#/d' $tmp.h > $tmp.c
+ sed '/^#/d' $x > $tmp.t
+ ;;
+ *) (proto -r $protoflags $tmp.h) >/dev/null 2>&1
+ sed 's,/\*[^/]*\*/, ,g' $tmp.h > $tmp.c
+ sed 's,/\*[^/]*\*/, ,g' $x > $tmp.t
+ ;;
+ esac
+ if cmp -s $tmp.c $tmp.t
+ then rm -f $tmp.h
+ case $verbose in
+ 1) echo "$command: $x: unchanged" >&$stderr ;;
+ esac
+ else case $x in
+ ${dir}[\\/]$cur) test -d $dir || mkdir $dir || exit 1 ;;
+ esac
+ mv $tmp.h $x
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ case $out in
+ +) case $status in
+ 1) ;;
+ *) status=0 ;;
+ esac
+ exit $status
+ ;;
+ -) eval "exec >&$stdout"
+ ;;
+ *) exec >$tmp.h
+ ;;
+ esac
+ case $out in
+ "") case $a in
+ *[\\/]*|???????????????*) cur=$c ;;
+ *) cur=$a ;;
+ esac
+ ;;
+ *) cur=$out
+ ;;
+ esac
+ case $in in
+ ""|-|+) case $o in
+ run) x=" from $a" ;;
+ *) x= ;;
+ esac
+ ;;
+ *) x=" from $in"
+ ;;
+ esac
+
+ # output header comments
+
+ case $define in
+ n) ;;
+ ?) echo "/* : : generated$x by $command version $version : : */"
+ for x in $pragma
+ do echo "#pragma $x"
+ done
+ case $out in
+ ""|-|+) x=$m
+ ;;
+ *.*) case $shell in
+ bsh) eval `echo $in | sed -e 's,\\.,_,g' -e 's/^/x=/'`
+ ;;
+ *) i=$out
+ x=_
+ while :
+ do case $i in
+ *.*) eval 'x=$x${i%%.*}_'
+ eval 'i=${i#*.}'
+ ;;
+ *) x=$x$i
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ *) x=_$out
+ ;;
+ esac
+ case $o in
+ iff) case $M in
+ ""|*-*) ;;
+ *) iff=${m}_H ;;
+ esac
+ ;;
+ *) case $regress in
+ '') case $x in
+ *-*) ;;
+ *) x=`pwd | sed -e 's,.*[\\\\/],,' -e 's,\\..*,,' -e 's,^lib,,' -e 's,^,'${x}_',' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g'`
+ # ksh n+ bug workaround
+ case $x in
+ *[!_]*) ;;
+ *) x=_$$ ;;
+ esac
+ iff=_def${x}
+ ;;
+ esac
+ ;;
+ *) case $x in
+ *-*) ;;
+ *) iff=_REGRESS
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $iff in
+ ?*) echo "#ifndef $iff"
+ echo "#define $iff 1"
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $can in
+ ?*) case $define in
+ 1) echo "$can" ;;
+ n) echo "$nan" ;;
+ esac
+ can=
+ nan=
+ cansep=
+ ;;
+ esac
+
+ # set up the candidate include list
+
+ pre=
+ inc=
+ for x in $defhdr - $hdr
+ do case $x in
+ -) case $pre in
+ ?*) continue ;;
+ esac
+ case $v in
+ *.*) for x in `echo $v | sed 's,\\., ,g'`
+ do pre="$pre
+#undef $x"
+ done
+ ;;
+ *) case $o in
+ siz|typ)case $v in
+ char|short|int|long)
+ ;;
+ *) pre="#undef $v"
+ ;;
+ esac
+ ;;
+ *) pre="#undef $v"
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *.h) case $shell in
+ bsh) eval `echo $x | sed -e 's,^\\([^\\\\/]*\\).*[\\\\/]\\([^\\\\/]*\\)\$,\\1_\\2,' -e 's/\\..*//' -e 's/^/c=/'`
+ ;;
+ *) eval 'c=${x##*[\\/]}'
+ eval 'c=${c%%.*}'
+ case $x in
+ */*) eval 'c=${x%%[\\/]*}_${c}' ;;
+ esac
+ ;;
+ esac
+ case $config in
+ 0) case $x in
+ */*) c=_${c} ;;
+ *) c=_hdr_${c} ;;
+ esac
+ ;;
+ 1) case $shell in
+ ksh) typeset -u u=$c ;;
+ *) u=`echo $c | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ c=HAVE_${u}_H
+ ;;
+ esac
+ case " $puthdr " in
+ *" $c "*)
+ ;;
+ *) puthdr="$puthdr $c"
+ usr="$usr$nl#define $c 1"
+ ;;
+ esac
+ inc="$inc
+#include <$x>"
+ ;;
+ esac
+ done
+
+ # set up the candidate lib list
+
+ for x in $lib $deflib
+ do case $shell in
+ ksh) eval 'c=${x#-l}' ;;
+ *) c=`echo X$x | sed 's,X-l,,'` ;;
+ esac
+ case $c in
+ *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*)
+ c=`echo '' $c | sed -e 's,.*[\\\\/],,' -e 's,\.[^.]*$,,' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g' -e '/^lib./s,^lib,,'`
+ ;;
+ esac
+ case $config in
+ 0) c=_LIB_${c}
+ ;;
+ 1) case $shell in
+ ksh) typeset -u u=$c ;;
+ *) u=`echo $c | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ c=HAVE_${u}_LIB
+ ;;
+ esac
+ case " $putlib " in
+ *" $c "*)
+ ;;
+ *) putlib="$putlib $c"
+ usr="$usr$nl#define $c 1"
+ ;;
+ esac
+ done
+
+ # src overrides builtin test
+
+ case $config:$def in
+ 0:) case $o in
+ tst|var);;
+ *) m=_${o}${m} ;;
+ esac
+ ;;
+ 1:) case $o in
+ tst|var)m=${v} ;;
+ esac
+ case $shell in
+ ksh) typeset -u u=$m ;;
+ *) u=`echo $m | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ case $o in
+ tst|var)case $m in
+ $u) ;;
+ *) case $m in
+ hdr_*|lib_*|sys_*)
+ case $shell in
+ ksh) u=${u#????} ;;
+ *) u=`echo $u | sed 's/....//'` ;;
+ esac
+ ;;
+ esac
+ m=HAVE_${u}
+ ;;
+ esac
+ ;;
+ dat) m=HAVE${u}_DATA ;;
+ hdr|lcl)m=HAVE${u}_H ;;
+ key) m=HAVE${u}_RESERVED ;;
+ mth) m=HAVE${u}_MATH ;;
+ npt) m=HAVE${u}_DECL ;;
+ pth) m=${u}_PATH
+ case $shell in
+ ksh) m=${m#_} ;;
+ *) m=`echo $m | sed 's,^_,,'` ;;
+ esac
+ ;;
+ nxt) m=HAVE${u}_NEXT ;;
+ siz) m=SIZEOF${u} ;;
+ sys) m=HAVE_SYS${u}_H ;;
+ *) m=HAVE${u} ;;
+ esac
+ ;;
+ *) m=$def
+ M=$m
+ ;;
+ esac
+ case $src in
+ ?*) case $src in
+ $noext) EXT= ;;
+ *) EXT="$tst
+$ext"
+ ;;
+ esac
+ copy $tmp.c "$std
+$EXT
+$usr
+$inc
+$src
+"
+ V=1
+ e=0
+ is tst "${note:-$run}"
+ case $run in
+ cat*|nocat*)
+ copy - "$src"
+ ;;
+ cross*|nocross*)
+ copy $tmp.sh "$src"
+ chmod +x $tmp.sh
+ execute $tmp.sh <&$nullin || e=1
+ ;;
+ run*|norun*)
+ (eval "$src") <&$nullin || e=1
+ ;;
+ mac*|nomac*)
+ if compile $cc -E $tmp.c <&$nullin >$tmp.i
+ then sed -e '/<<[ ]*".*"[ ]*>>/!d' -e 's/<<[ ]*"//g' -e 's/"[ ]*>>//g' $tmp.i
+ else e=1
+ fi
+ ;;
+ p*|nop*)compile $cc -DTEST=$p -DID=$v -E $tmp.c <&$nullin >&$nullout || e=1
+ ;;
+ c*|noc*)compile $cc -DTEST=$p -DID=$v -c $tmp.c <&$nullin >&$nullout || e=1
+ ;;
+ *) case $run in
+ status*)ccflags=
+ ;;
+ s*|nos*)case $reallystatictest in
+ '') #UNDENT...
+
+ reallystatictest=.
+ echo "$tst
+$ext
+int main(){printf("hello");return(0);}" > ${tmp}s.c
+ rm -f ${tmp}s.exe
+ if compile $cc -c ${tmp}s.c <&$nullin >&$nullout &&
+ compile $cc -o ${tmp}s.exe ${tmp}s.o <&$nullin >&$nullout 2>${tmp}s.e &&
+ $executable ${tmp}s.exe
+ then e=`wc -l ${tmp}s.e`
+ eval set x x $binding
+ while :
+ do shift
+ shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f ${tmp}s.exe
+ compile $cc -o ${tmp}s.exe $1 ${tmp}s.o <&$nullin >&$nullout 2>${tmp}s.e && $executable ${tmp}s.exe || continue
+ case `wc -l ${tmp}s.e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ d=`ls -s ${tmp}s.exe`
+ rm -f ${tmp}s.exe
+ compile $cc -o ${tmp}s.exe $2 ${tmp}s.o <&$nullin >&$nullout 2>${tmp}s.e && $executable ${tmp}s.exe || continue
+ case `wc -l ${tmp}s.e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ case `ls -s ${tmp}s.exe` in
+ $d) ;;
+ *) reallystatic=$2
+ set x
+ shift
+ break
+ ;;
+ esac
+ done
+ fi
+ rm -f ${tmp}s.*
+ #...INDENT
+ ;;
+ esac
+ ccflags=$reallystatic
+ ;;
+ *) ccflags=
+ ;;
+ esac
+ set x $mac
+ e=1
+ while :
+ do o=
+ shift
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -) break ;;
+ esac
+ o="$o $1"
+ shift
+ done
+ rm -f $tmp.exe
+ if compile $cc $ccflags $o -DTEST=$p -DID=$v -o $tmp.exe $tmp.c $lib $deflib <&$nullin >&$nullout && $executable $tmp.exe
+ then case $run in
+
+ status*)execute $tmp.exe <&$nullin >&$nullout
+ V=$?
+ case $V in
+ 0) e=1 ;;
+ *) e=0 ;;
+ esac
+ break
+ ;;
+ no[ls]*);;
+ [ls]*) e=0 && break ;;
+ noo*) execute $tmp.exe <&$nullin >$tmp.out || break ;;
+ o*) execute $tmp.exe <&$nullin >$tmp.out && e=0 && break ;;
+ no*) execute $tmp.exe <&$nullin >&$nullout || break ;;
+ *) execute $tmp.exe <&$nullin >&$nullout && e=0 && break ;;
+
+ esac
+ else case $run in
+ no[els]*)e=1 && break ;;
+ esac
+ fi
+ case $# in
+ 0) case $run in
+ no*) e=0 ;;
+ esac
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ o=1
+ case $run in
+ no*) case $e in
+ 0) e=1 ;;
+ *) e=0 ;;
+ esac
+ ;;
+ esac
+ case $run in
+ o*|noo*)case $e in
+ 0) cat $tmp.out ;;
+ esac
+ rm -f $tmp.out
+ ;;
+ esac
+ report $e $V "${note:-$run\ passed}" "${note:-$run} failed"
+ continue
+ ;;
+ esac
+
+ # initialize common builtin state
+
+ case $o in
+ dat|lib|mth|run)
+ case $statictest in
+ "") statictest=FoobaR
+ copy $tmp.c "
+$tst
+$ext
+$std
+$usr
+_BEGIN_EXTERNS_
+extern int $statictest;
+_END_EXTERNS_
+int main(){char* i = (char*)&$statictest; return ((unsigned int)i)^0xaaaa;}
+"
+ rm -f $tmp.exe
+ if compile $cc -o $tmp.exe $tmp.c <&$nullin >&$nullout && $executable $tmp.exe
+ then case $static in
+ .) static=
+ copy $tmp.c "
+$tst
+$ext
+int main(){printf("hello");return(0);}
+"
+ rm -f $tmp.exe
+ if compile $cc -c $tmp.c <&$nullin >&$nullout &&
+ compile $cc -o $tmp.exe $tmp.o <&$nullin >&$nullout &&
+ $executable $tmp.exe
+ then e=`wc -l $tmp.e`
+ eval set x x $binding
+ while :
+ do shift
+ shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f $tmp.exe
+ compile $cc -o $tmp.exe $1 $tmp.o <&$nullin >&$nullout && $executable $tmp.exe || continue
+ case `wc -l $tmp.e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ d=`ls -s $tmp.exe`
+ rm -f $tmp.exe
+ compile $cc -o $tmp.exe $2 $tmp.o <&$nullin >&$nullout && $executable $tmp.exe || continue
+ case `wc -l $tmp.e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ case `ls -s $tmp.exe` in
+ $d) ;;
+ *) static=$2
+ set x
+ shift
+ break
+ ;;
+ esac
+ done
+ fi
+ ;;
+ esac
+ else static=
+ fi
+ ;;
+ esac
+ ;;
+ esac
+
+ # builtin tests
+
+ case $o in
+ api) ;;
+ cmd) case $p in
+ ?*) continue ;;
+ esac
+ is $o $a
+ k=1
+ for j in "" usr
+ do case $j in
+ "") d= s= ;;
+ *) d=/$j s=_$j ;;
+ esac
+ for i in bin etc ucb
+ do if test -f $d/$i/$a
+ then case $k in
+ 1) k=0
+ case $M in
+ *-*) ;;
+ *) usr="$usr$nl#define $m 1"
+ case $define in
+ 1) echo "#define $m 1 /* $a in ?(/usr)/(bin|etc|ucb) */" ;;
+ n) echo "$m=1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ c=${s}_${i}_${v}
+ usr="$usr$nl#define $c 1"
+ case $define in
+ 1) echo "#define $c 1 /* $d/$i/$a found */" ;;
+ n) echo "$c=1" ;;
+ esac
+ fi
+ done
+ done
+ case $k in
+ 0) success ;;
+ 1) failure ;;
+ esac
+ ;;
+ dat) case $p in
+ ?*) continue ;;
+ esac
+ {
+ copy - "
+$tst
+$ext
+$std
+$usr
+$pre
+"
+ case $inc in
+ ?*) echo "$inc"
+ ;;
+ *) echo "_BEGIN_EXTERNS_
+extern int $v;
+_END_EXTERNS_"
+ ;;
+ esac
+ echo "
+#ifdef _DLL
+#define _REF_
+#else
+#define _REF_ &
+#endif
+int main(){char* i = (char*) _REF_ $v; return ((unsigned int)i)^0xaaaa;}"
+ } > $tmp.c
+ is $o $v
+ rm -f $tmp.exe
+ compile $cc -c $tmp.c <&$nullin >&$nullout &&
+ compile $cc $static -o $tmp.exe $tmp.o $lib $deflib <&$nullin >&$nullout &&
+ $executable $tmp.exe
+ report $? 1 "$v in default lib(s)" "$v not in default lib(s)"
+ ;;
+ dfn) case $p in
+ ?*) continue ;;
+ esac
+ is dfn $v
+ echo "$pre
+$tst
+$ext
+$inc
+#ifdef $v
+<<\"#ifndef $v\">>
+<<\"#define $v\">> $v <<\"/* native $v */\">>
+<<\"#endif\">>
+#endif" > $tmp.c
+ if compile $cc -E $tmp.c <&$nullin >$tmp.i
+ then sed -e '/<<[ ]*".*"[ ]*>>/!d' -e 's/<<[ ]*"//g' -e 's/"[ ]*>>//g' $tmp.i > $tmp.t
+ if test -s $tmp.t
+ then success
+ cat $tmp.t
+ else failure
+ fi
+ else failure
+ fi
+ ;;
+ exp) case $test in
+ '') echo "$command: $file$sline: test expression expected for $o" >&$stderr
+ exit 1
+ ;;
+ esac
+ case $a in
+ -|'') ;;
+ *) eval x='$'$a
+ case $x in
+ 1) result=FAILURE
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ case $test in
+ [01]|'"'*'"'|'<'*'>')
+ case $a in
+ -|'') ;;
+ *) case $define$note in
+ 1) echo "#define $a $test" ;;
+ 1*) echo "#define $a $test /* $note */" ;;
+ n) echo "$a=$test" ;;
+ esac
+ eval $a='$test'
+ ;;
+ esac
+ ;;
+ *) case $note in
+ '') note=$test ;;
+ esac
+ case $test in
+ '') c=1
+ ;;
+ *) is exp "$note"
+ x=
+ for i in `echo '' $test | sed 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], & ,g'`
+ do case $i in
+ [\ \ ])
+ ;;
+ [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]*)
+ eval i='${'$i'}'
+ case $i in
+ '') i=0
+ ;;
+ '"'*'"');;
+ *[!-+0123456789]*)
+ case $i in
+ *'"'*) i=1 ;;
+ *) i='"'$i'"' ;;
+ esac
+ ;;
+ esac
+ x="$x $i"
+ ;;
+ '!') x="$x 0 ="
+ ;;
+ '&'|'|')case $x in
+ *"$i") ;;
+ *) x="$x \\$i" ;;
+ esac
+ ;;
+ *) x="$x \\$i"
+ ;;
+ esac
+ done
+ c=`eval expr $x 2>&$stderr`
+ ;;
+ esac
+ case $c in
+ 0) c=1 ;;
+ *) c=0 ;;
+ esac
+ M=$a
+ m=$a
+ report $c 1 "$note is true" "$note is false"
+ ;;
+ esac
+ ;;
+ hdr|lcl|nxt|sys)
+ case $o in
+ lcl|nxt)case $M in
+ *-*) continue ;;
+ esac
+ eval x='$'_$m
+ case $x in
+ ?*) continue ;;
+ esac
+ eval _$m=1
+ is $o $f
+ echo "$pre
+$tst
+$ext
+$inc
+#include <$f.h>" > $tmp.c
+ case $f in
+ sys/*) e= ;;
+ *) e='-e /[\\\\\/]sys[\\\\\/]'$f'\\.h"/d' ;;
+ esac
+ if compile $cc -E $tmp.c <&$nullin >$tmp.i
+ then i=`sed -e '/^#[line ]*[0123456789][0123456789]*[ ][ ]*"[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:]*[\\\\\/].*[\\\\\/]'$f'\\.h"/!d' $e -e s'/.*"\\(.*\\)".*/\\1/' -e 's,\\\\,/,g' -e 's,///*,/,g' $tmp.i | sed 1q`
+ case $i in
+ [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]:[\\/]*)
+ ;;
+ */*/*) k=`echo "$i" | sed 's,.*/\([^/]*/[^/]*\)$,../\1,'`
+ echo "$pre
+$tst
+$ext
+$inc
+#include <$k>" > $tmp.c
+ if compile $cc -E $tmp.c <&$nullin >$tmp.i
+ then j=`sed -e '/^#[line ]*[0123456789][0123456789]*[ ][ ]*"[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:]*[\\\\\/].*[\\\\\/]'$f'\\.h"/!d' $e -e s'/.*"\\(.*\\)".*/\\1/' -e 's,\\\\,/,g' -e 's,///*,/,g' $tmp.i | sed 1q`
+ wi=`wc < "$i"`
+ wj=`wc < "$j"`
+ case $wi in
+ $wj) i=$k ;;
+ esac
+ fi
+ ;;
+ *) echo "$pre
+$tst
+$ext
+$inc
+#include <../include/$f.h>" > $tmp.c
+ if compile $cc -E $tmp.c <&$nullin >&$nullout
+ then i=../include/$f.h
+ fi
+ ;;
+ esac
+ else i=
+ fi
+ case $i in
+ [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]:[\\/]*|[\\/]*)
+ success
+ case $o in
+ lcl) echo "#if defined(__STDPP__directive)"
+ echo "__STDPP__directive pragma pp:hosted"
+ echo "#endif"
+ echo "#include <$i> /* the native <$f.h> */"
+ echo "#undef $m"
+ usr="$usr$nl#define $m 1"
+ echo "#define $m 1"
+ ;;
+ nxt) echo "#define $m <$i> /* include path for the native <$f.h> */"
+ echo "#define ${m}_str \"$i\" /* include string for the native <$f.h> */"
+ usr="$usr$nl#define $m <$i>$nl#define ${m}_str \"$i\""
+ eval $m=\\\<$i\\\>
+ ;;
+ esac
+ break
+ ;;
+ ../*/*) success
+ case $o in
+ lcl) echo "#include <$i> /* the native <$f.h> */"
+ echo "#undef $m"
+ usr="$usr$nl#define $m 1"
+ echo "#define $m 1"
+ eval $m=1
+ ;;
+ nxt) echo "#define $m <$i> /* include path for the native <$f.h> */"
+ echo "#define ${m}_str \"$i\" /* include string for the native <$f.h> */"
+ usr="$usr$nl#define $m <$i>$nl#define ${m}_str \"$i\""
+ eval $m=\\\<$i\\\>
+ ;;
+ esac
+ break
+ ;;
+ *) failure
+ case $o in
+ lcl) case $all$config$undef in
+ ?1?|??1)echo "#undef $m /* no native <$f.h> */" ;;
+ 1??) echo "#define $m 0 /* no native <$f.h> */" ;;
+ esac
+ eval $m=0
+ ;;
+ nxt) case $all$config$undef in
+ ?1?|??1)echo "#undef $m /* no include path for the native <$f.h> */" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) case $o in
+ hdr) x=$f.h ;;
+ sys) x=sys/$f.h ;;
+ esac
+ case " $gothdr " in
+ *" - $x "*)
+ failure +
+ ;;
+ *" + $x "*)
+ success +
+ ;;
+ *) echo "
+$tst
+$ext
+$allinc
+$inc
+#include <$x>" > $tmp.c
+ if is_hdr $x
+ then gothdr="$gothdr + $x"
+ case $M in
+ *-*) ;;
+ *) case " $puthdr " in
+ *" $m "*)
+ ;;
+ *) puthdr="$puthdr $m"
+ usr="$usr$nl#define $m 1"
+ ;;
+ esac
+ case $define in
+ 1) echo "#define $m 1 /* #include <$x> ok */" ;;
+ n) echo "$m=1" ;;
+ esac
+ eval $m=1
+ ;;
+ esac
+ else gothdr="$gothdr - $x"
+ case $M in
+ *-*) ;;
+ *) case $define$all$config$undef in
+ 1?1?|1??1)echo "#undef $m /* #include <$x> not ok */" ;;
+ 11??) echo "#define $m 0 /* #include <$x> not ok */" ;;
+ n1?1) echo "$m=" ;;
+ n1??) echo "$m=0" ;;
+ esac
+ eval $m=0
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ continue
+ ;;
+ esac
+ ;;
+ iff) ;;
+ ini) ;;
+ key) case $p in
+ ?*) continue ;;
+ esac
+ w=$v
+ while :
+ do is $o $w
+ echo "$pre
+$tst
+$ext
+int f(){int $w = 1;return($w);}" > $tmp.c
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then failure
+ case $set in
+ *" ="|*" = "*)
+ set x $set
+ shift
+ w=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ =) break ;;
+ esac
+ case $w in
+ '') w=$1 ;;
+ *) w="$w $1" ;;
+ esac
+ shift
+ done
+ case $1 in
+ =) shift
+ case $# in
+ 0) set=" " ;;
+ *) set=$* ;;
+ esac
+ ;;
+ *) set=
+ ;;
+ esac
+ case $shell in
+ ksh) typeset -u u=$w ;;
+ *) u=`echo $w | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;;
+ esac
+ u=_$u
+ M=$w
+ case $M in
+ *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*)
+ M=`echo "X$m" | sed -e 's,^.,,' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g'`
+ ;;
+ esac
+ case $config in
+ 1) m=HAVE${u}_RESERVED ;;
+ *) m=_key_${w} ;;
+ esac
+ continue
+ ;;
+ esac
+ report - 1 - - "$w is not a reserved keyword" "default for reserved keyword $v"
+ else report 0 1 "$w is a reserved keyword" -
+ case $M in
+ *-*) ;;
+ *) case $define$w in
+ 1$v) ;;
+ 1*) echo "#define $v $w /* alternate for reserved keyword $v */" ;;
+ n*) echo "$v=$w" ;;
+ esac
+ ;;
+ esac
+ fi
+ break
+ done
+ ;;
+ lib|mth)case $p in
+ ?*) continue ;;
+ esac
+ case $v in
+ -) continue ;;
+ esac
+ is $o $v
+ copy $tmp.c "
+$tst
+$ext
+$std
+$usr
+$pre
+$inc
+typedef int (*_IFFE_fun)();
+#ifdef _IFFE_extern
+_BEGIN_EXTERNS_
+extern int $v();
+_END_EXTERNS_
+#endif
+static _IFFE_fun i=(_IFFE_fun)$v;int main(){return ((unsigned int)i)^0xaaaa;}
+"
+ d=-D_IFFE_extern
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then d=
+ elif compile $cc $d -c $tmp.c <&$nullin >&$nullout
+ then :
+ else d=error
+ fi
+ if test error != "$d"
+ then rm -f $tmp.exe
+ if compile $cc $d $static -o $tmp.exe $tmp.o $lib $deflib <&$nullin >&$nullout &&
+ $executable $tmp.exe
+ then case $o in
+ lib) c=0 ;;
+ *) c=1 ;;
+ esac
+ report $c 1 "$v() in default lib(s)" "$v() not in default lib(s)" "default for function $v()"
+ else case $o in
+ mth) rm -f $tmp.exe
+ compile $cc $d $static -o $tmp.exe $tmp.o -lm <&$nullin >&$nullout &&
+ $executable $tmp.exe
+ report $? 1 "$v() in math lib" "$v() not in math lib" "default for function $v()"
+ ;;
+ *) report 1 1 - "$v() not in default lib(s)" "default for function $v()"
+ ;;
+ esac
+ fi
+ else case $intrinsic in
+ '') copy $tmp.c "
+$tst
+$ext
+$std
+$usr
+$pre
+$inc
+_BEGIN_EXTERNS_
+extern int foo();
+_END_EXTERNS_
+static int ((*i)())=foo;int main(){return(i==0);}
+"
+ compile $cc -c $tmp.c <&$nullin >&$nullout
+ intrinsic=$?
+ ;;
+ esac
+ case $o in
+ mth) report $intrinsic 1 "$v() in math lib" "$v() not in math lib" "default for function $v()" ;;
+ *) report $intrinsic 1 "$v() in default lib(s)" "$v() not in default lib(s)" "default for function $v()" ;;
+ esac
+ fi
+ ;;
+ mac) case $p in
+ ?*) continue ;;
+ esac
+ is mac $v
+ echo "
+$tst
+$ext
+$pre
+$inc
+#ifdef $v
+'$m:$v'
+#endif" > $tmp.c
+ compile $cc -E $tmp.c <&$nullin | grep -c "'$m:$v'" >&$nullout
+ report $? 1 "$v is a macro" "$v is not a macro" "default for macro $v"
+ ;;
+ mem) case $p in
+ ?*) eval i='$'_iffe_typedef_$p
+ case $i in
+ 0|1) ;;
+ *) echo "$pre
+$tst
+$ext
+$inc
+static $p i;
+int n = sizeof(i);" > $tmp.c
+ is typ $p
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then success -
+ eval _iffe_typedef_$p=1
+ i=1
+ else failure -
+ eval _iffe_typedef_$p=0
+ i=0
+ fi
+ ;;
+ esac
+ case $i in
+ 0) i="$v is not a member of $p" p="struct $p" ;;
+ *) i=- ;;
+ esac
+ is mem $v "$p"
+ echo "$pre
+$tst
+$ext
+$inc
+static $p i;
+int n = sizeof(i.$v);" > $tmp.c
+ compile $cc -c $tmp.c <&$nullin >&$nullout
+ report $? 1 "$v is a member of $p" "$i"
+ ;;
+ *) p=$v
+ eval i='$'_iffe_typedef_$p
+ case $i in
+ 0|1) ;;
+ *) echo "$pre
+$tst
+$ext
+$inc
+static $p i;
+int n = sizeof(i);" > $tmp.c
+ is typ $p
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then success -
+ eval _iffe_typedef_$p=1
+ i=1
+ else failure -
+ eval _iffe_typedef_$p=0
+ i=0
+ fi
+ ;;
+ esac
+ case $i in
+ 0) i="$p is not a non-opaque struct" p="struct $p" ;;
+ *) i=- ;;
+ esac
+ is nos "$p"
+ echo "$pre
+$tst
+$ext
+$inc
+static $p i;
+int n = sizeof(i);" > $tmp.c
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then echo "$pre
+$tst
+$ext
+$inc
+static $p i;
+unsigned long f() { return (unsigned long)i; }" > $tmp.c
+ if compile $cc -c $tmp.c <&$nullin >&$nullout
+ then c=1
+ else c=0
+ fi
+ else c=1
+ fi
+ report $c 1 "$p is a non-opaque struct" "$i"
+ esac
+ ;;
+ nop) ;;
+ npt) is npt $v
+ copy $tmp.c "
+$tst
+$ext
+$std
+$usr
+$pre
+$inc
+_BEGIN_EXTERNS_
+struct _iffe_struct { int _iffe_member; };
+extern struct _iffe_struct* $v _ARG_((struct _iffe_struct*));
+_END_EXTERNS_
+"
+ # some compilers with -O only warn for invalid intrinsic prototypes
+ case " $cc " in
+ *" -O "*) xx=`echo $cc | sed 's/ -O / /g'` ;;
+ *) xx=$cc ;;
+ esac
+ compile $xx -c $tmp.c <&$nullin >&$nullout
+ report -$config $? 1 "$v() needs a prototype" "$v() does not need a prototype"
+ ;;
+ num) is num $v
+ copy $tmp.c "
+$tst
+$ext
+$std
+$usr
+$pre
+$inc
+_BEGIN_EXTERNS_
+int _iffe_int = $v / 2;
+_END_EXTERNS_
+"
+ compile $cc -c $tmp.c <&$nullin >&$nullout
+ report $? 1 "$v is a numeric constant" "$v is not a numeric constant"
+ ;;
+ one) for i in $a $hdr
+ do x="#include <$i>"
+ case " $gothdr " in
+ *" - $i "*)
+ continue
+ ;;
+ *" + $i "*)
+ ;;
+ *) echo "$x" > $tmp.c
+ if is_hdr $x
+ then gothdr="$gothdr + $x"
+ else gothdr="$gothdr - $x"
+ continue
+ fi
+ ;;
+ esac
+ case $one in
+ "") one=$x
+ ;;
+ *"$x"*) break
+ ;;
+ *) echo "$one" > $tmp.c
+ if compile $cc -E $tmp.c <&$nullin >$tmp.i
+ then c=$i
+ case $c in
+ *[\\/]*) c=`echo $c | sed 's,[\\\\/],[\\\\/],g'` ;;
+ esac
+ case `sed -e '/^#[line ]*1[ ][ ]*"[\\\\\/].*[\\\\\/]'$c'"/!d' $tmp.i` in
+ ?*) break ;;
+ esac
+ fi
+ one="$one$nl$x"
+ ;;
+ esac
+ echo "$x"
+ break
+ done
+ ;;
+ opt) M=$m
+ is opt $a
+ case " $PACKAGE_OPTIONS " in
+ *" $a "*) c=0 ;;
+ *) c=1 ;;
+ esac
+ report $c 1 "$a is set in \$PACKAGE_OPTIONS" "$a is not set in \$PACKAGE_OPTIONS"
+ ;;
+ out|output)
+ ;;
+ pth) is pth $a
+ pkg $pth
+ tab=" "
+ e=
+ f=
+ for i in $pth
+ do case $i in
+ '{') e="${nl}}"
+ l=
+ x=i
+ v="\$${x}"
+ t=${nl}${tab}
+ b="fnd()${nl}{${t}for ${x} in"
+ ;;
+ '}') b="${b}${t}do${tab}if $exists ${v}/\${1}${t}${tab}${tab}then${tab}f=${v}/\${1}${t}${tab}${tab}${tab}return${t}${tab}${tab}fi"
+ e="${t}done${e}"
+ eval "${b}${e}"
+ fnd $a
+ case $f in
+ ?*) break ;;
+ esac
+ ;;
+ -) b="${b}${t}do${tab}test \"${v}\" = '' -o -d \"${v}\" &&${t}${tab}${tab}"
+ x=${x}i
+ v="${v}\$${x}"
+ b="${b}for ${x} in"
+ e="${t}done${e}"
+ t="${t}${tab}${tab}"
+ ;;
+ *) case $e in
+ '') if $exists ${i}/${a}
+ then f=${i}/${a}
+ break
+ fi
+ ;;
+ *) case $i in
+ /|.) b="${b} ''" ;;
+ *) b="${b} /${i}" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $f in
+ '') case $set in
+ ' ') f=$a ;;
+ ?*) f=$set ;;
+ esac
+ ;;
+ esac
+ case $f in
+ '') c=1
+ ;;
+ *) c=0
+ f="\"$f\""
+ ;;
+ esac
+ report $c "$f" "${note:-$a path}" "$a path not found"
+ ;;
+ run) is run $a
+ if test ! -r $a
+ then failure not found
+ case $verbose in
+ 0) echo "$command: $file$line: $a: not found" >&$stderr ;;
+ esac
+ exit 1
+ fi
+ noisy
+ case $a in
+ *.c) rm -f $tmp.exe
+ {
+ echo "$tst
+$ext
+$std
+$usr
+$inc"
+ cat $a
+ } > $tmp.c
+ compile $cc -o $tmp.exe $tmp.c $lib $deflib <&$nullin >&$stderr 2>&$stderr &&
+ $executable $tmp.exe &&
+ execute $tmp.exe $opt <&$nullin
+ ;;
+ *.sh) {
+ copy - ":
+set \"cc='$cc' executable='$executable' id='$m' static='$static' tmp='$tmp'\" $opt $hdr $test"
+ cat $a
+ } > $tmp.sh
+ chmod +x $tmp.sh
+ ( . $tmp.sh ) <&$nullin
+ ;;
+ *) false
+ ;;
+ esac
+ case $? in
+ 0) success
+ ;;
+ *) failure cannot run
+ case $verbose in
+ 0) echo "$command: $file$line: $a: cannot run" >&$stderr ;;
+ esac
+ exit 1
+ ;;
+ esac
+ ;;
+ siz) case $p in
+ "") x= ;;
+ *) x="$p " ;;
+ esac
+ is siz "$x$v"
+ {
+ case $p:$v in
+ long:*|*:*[_0123456789]int[_0123456789]*)
+ echo "$pre
+$tst
+$ext
+$inc
+static $x$v i;
+$x$v f() {
+$x$v v; i = 1; v = i;"
+ echo "i = v * i; i = i / v; v = v + i; i = i - v;"
+ case $v in
+ float|double) ;;
+ *) echo "v <<= 4; i = v >> 2; i = 10; i = v % i; i |= v; v ^= i; i = 123; v &= i;" ;;
+ esac
+ echo "return v; }"
+ ;;
+ *) echo "$pre
+$inc
+struct xxx { $x$v mem; };
+static struct xxx v;
+struct xxx* f() { return &v; }"
+ ;;
+ esac
+ case $x in
+ ""|"struct "|"union ")
+ echo "int g() { return 0; }"
+ ;;
+ *) echo "int g() { return sizeof($x$v)<=sizeof($v); }" ;;
+ esac
+ copy - "
+int main() {
+ f();
+ g();
+ printf(\"%u\\n\", sizeof($x$v));
+ return 0;
+}"
+ } > $tmp.c
+ rm -f $tmp.exe $tmp.dat
+ if compile $cc -o $tmp.exe $tmp.c $lib $deflib <&$nullin >&$nullout &&
+ $executable $tmp.exe &&
+ execute $tmp.exe > $tmp.dat
+ then z=`cat $tmp.dat`
+ c=0
+ else z=0
+ c=1
+ fi
+ report $c "$z" "sizeof($x$v)" "$x$v not a type with known size"
+ ;;
+ sym) case $test in
+ "") x=$v ;;
+ *) x=$test ;;
+ esac
+ echo "$pre
+$tst
+$ext
+$inc
+'=' $x '='" > $tmp.c
+ compile $cc -E $tmp.c <&$nullin \
+ | sed \
+ -e "/'='/!d" \
+ -e "s/'='//g" \
+ -e 's/[ ]//g' \
+ -e 's/((([^()]*)))->/->/g' \
+ -e 's/(([^()]*))->/->/g' \
+ -e 's/([^()]*)->/->/g' \
+ -e 's/\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*\)\[/\
+ary \1[/g' \
+ -e 's/\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*\)(/\
+fun \1[/g' \
+ -e 's/\*->\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]\)/->\
+ptr \1/g' \
+ -e 's/->\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]\)/->\
+reg \1/g' \
+ -e "/^$v\$/d" \
+ -e 's/^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*$/\
+nam &/g' \
+ | sed \
+ -e '/^... /!d' \
+ | LC_ALL=C sort \
+ -u \
+ | sed \
+ -e 's/\(...\) \([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*\).*/#ifndef _\1_'$v'\
+#define _\1_'$v' \2\
+#define _\1_'$v'_str "\2"\
+#endif/'
+ ;;
+ typ) case $p in
+ "") x= ;;
+ *) x="$p " ;;
+ esac
+ is typ "$x$v"
+ {
+ case $p:$v in
+ long:*|*:*[_0123456789]int[_0123456789]*)
+ echo "$pre
+$tst
+$ext
+$inc
+static $x$v i;
+$x$v f() {
+$x$v v; i = 1; v = i;"
+ echo "i = v * i; i = i / v; v = v + i; i = i - v;"
+ case $v in
+ float|double) ;;
+ *) echo "v <<= 4; i = v >> 2; i = 10; i = v % i; i |= v; v ^= i; i = 123; v &= i;" ;;
+ esac
+ echo "return v; }"
+ ;;
+ *) echo "$pre
+$tst
+$ext
+$inc
+struct xxx { $x$v mem; };
+static struct xxx v;
+struct xxx* f() { return &v; }"
+ ;;
+ esac
+ case $x in
+ ""|"struct "|"union ")
+ echo "int main() { f(); return 0; }" ;;
+ *) echo "int main() { f(); return sizeof($x$v)<=sizeof($v); }" ;;
+ esac
+ } > $tmp.c
+ rm -f $tmp.exe
+ compile $cc -o $tmp.exe $tmp.c $lib $deflib <&$nullin >&$nullout &&
+ $executable $tmp.exe &&
+ execute $tmp.exe
+ report $? 1 "$x$v is a type" "$x$v is not a type" "default for type $x$v"
+ ;;
+ val) case $arg in
+ '"'*'"')echo $arg=\'$val\' ;;
+ *) echo $arg=\"$val\" ;;
+ esac
+ ;;
+ ver) ;;
+ 0) result=FAILURE
+ ;;
+ 1) result=SUCCESS
+ ;;
+ :) ;;
+ -) ;;
+ *) echo "$command: $file$line: $o: unknown feature test" >&$stderr
+ status=1
+ ;;
+ esac
+ done
+ done
+ case $not in
+ 1) case $result in
+ FAILURE) result=SUCCESS ;;
+ *) result=FAILURE ;;
+ esac
+ ;;
+ esac
+ case $result in
+ FAILURE) user_pf=$fail user_yn=$no ;;
+ *) user_pf=$pass user_yn=$yes ;;
+ esac
+ case $user_pf in
+ ?*) eval "$user_pf" <&$nullin ;;
+ esac
+ case $user_yn in
+ ?*) case $def in
+ -) ;;
+ *) case $note in
+ ?*) case $user_yn in
+ *$nl*) user_yn="/* $note */$nl$user_yn" ;;
+ *) user_yn="$user_yn /* $note */" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ copy - "$user_yn"
+ ;;
+ esac
+ case $ifelse:$result in
+ TEST:SUCCESS) ifelse=KEEP ;;
+ TEST:*) ifelse=SKIP ;;
+ esac
+ case $group:$result in
+ :*|*:SUCCESS) break ;;
+ esac
+ set '' $groups '' "$@"
+ shift
+ case $1 in
+ '') shift; break ;;
+ esac
+ shift
+
+ # set up and try the next group
+
+ hdr=$com_hdr
+ lib=$com_lib
+ mac=$com_mac
+ opt=$com_opt
+ pth=$com_pth
+ test=$com_test
+ cc="$occ $includes"
+ group=
+ groups=
+ while :
+ do case $1 in
+ '') shift; break ;;
+ esac
+ case $1 in
+ *[\"\'\(\)\{\}\ \ ]*)
+ case $op in
+ pth) pth="$pth $1"
+ ;;
+ *) case $test in
+ '') test=$1 ;;
+ *) test="$test $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ -) group=$group$1
+ groups="$groups $1"
+ ;;
+ -l*) case $group in
+ -*) groups="$groups $1" ;;
+ *) lib="$lib $1" ;;
+ esac
+ ;;
+ +l*) case $shell in
+ bsh) x=`echo X$1 | sed 's/X+/-/'` ;;
+ *) eval 'x=-${1#+}' ;;
+ esac
+ case $group in
+ -*) groups="$groups $x" ;;
+ *) lib="$lib $x" ;;
+ esac
+ ;;
+ -*|+*) case $group in
+ -*) groups="$groups $1"
+ ;;
+ *) case $op in
+ run) opt="$opt $1"
+ ;;
+ *) case $1 in
+ -D*) mac="$mac $1" ;;
+ *) cc="$cc $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *.[aAxX]|*.[dD][lL][lL]|*.[lL][iI][bB])
+ case $group in
+ -*) groups="$groups $1" ;;
+ *) lib="$lib $1" ;;
+ esac
+ ;;
+ *[.\\/]*)
+ case $group in
+ -*) groups="$groups $1"
+ ;;
+ *) case $op in
+ pth) pth="$pth $1" ;;
+ *) hdr="$hdr $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) case $group in
+ -*) groups="$groups $1"
+ ;;
+ *) case $op in
+ pth) pth="$pth $1"
+ ;;
+ *) case $test in
+ '') test=$1 ;;
+ *) test="$test $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ shift
+ done
+ done
+done
diff --git a/src/cmd/INIT/iffe.tst b/src/cmd/INIT/iffe.tst
new file mode 100644
index 0000000..115ef62
--- /dev/null
+++ b/src/cmd/INIT/iffe.tst
@@ -0,0 +1,1943 @@
+# regression tests for the iffe command
+
+TEST 01 'command line basics'
+
+ EXEC -r -v - hdr stdio
+ OUTPUT - $'/* : : generated by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes'
+
+ EXEC -r -v -s bsh - hdr stdio
+
+ EXEC -r -v - hdr stdio,limits
+ OUTPUT - $'/* : : generated by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define _hdr_limits 1 /* #include <limits.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is limits.h a header ... yes'
+
+ EXEC -r -v -s bsh - hdr stdio,limits
+
+ EXEC -r -v - hdr,lib no_foo_bar,no_bar_foo stdio.h
+ OUTPUT - $'/* : : generated by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is no_foo_bar.h a header ... no
+iffe: test: is no_bar_foo.h a header ... no
+iffe: test: is no_foo_bar a library function ... no
+iffe: test: is no_bar_foo a library function ... no'
+
+ EXEC -r -v -s bsh - hdr,lib no_foo_bar,no_bar_foo stdio.h
+
+ EXEC -r -v - hdr no_foo_bar,no_bar_foo stdio.h : lib no_foo_bar,no_bar_foo stdio.h
+
+ EXEC -r -v -s bsh - hdr no_foo_bar,no_bar_foo stdio.h : lib no_foo_bar,no_bar_foo stdio.h
+
+TEST 02 'file input basics'
+
+ EXEC -r -v - t1.iffe
+ INPUT t1.iffe $'hdr stdio'
+ OUTPUT - $'/* : : generated from t1.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes'
+
+ EXEC -r -v -s bsh - t1.iffe
+
+ EXEC -r -v - t2.iffe
+ INPUT t2.iffe $'hdr stdio,limits'
+ OUTPUT - $'/* : : generated from t2.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define _hdr_limits 1 /* #include <limits.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is limits.h a header ... yes'
+
+ EXEC -r -v -s bsh - t2.iffe
+
+ EXEC -r -v - t3.iffe
+ INPUT t3.iffe $'hdr,lib no_foo_bar,no_bar_foo stdio.h'
+ OUTPUT - $'/* : : generated from t3.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is no_foo_bar.h a header ... no
+iffe: test: is no_bar_foo.h a header ... no
+iffe: test: is no_foo_bar a library function ... no
+iffe: test: is no_bar_foo a library function ... no'
+
+ EXEC -r -v -s bsh - t3.iffe
+
+ EXEC -r -v - t3.iffe
+ INPUT t3.iffe $'hdr no_foo_bar,no_bar_foo stdio.h
+lib no_foo_bar,no_bar_foo stdio.h'
+
+ EXEC -r -v -s bsh - t3.iffe
+
+TEST 03 'nested if'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if hdr stdio
+ if lib open {
+ HIT 1
+ }
+ elif lib close {
+ HIT 2
+ }
+ else {
+ HIT 3
+ }
+ endif
+elif hdr limits {
+ HIT 4
+}
+else {
+ HIT 5
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define _lib_open 1 /* open() in default lib(s) */
+ HIT 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is open a library function ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if hdr _XXX_stdio
+ if lib open {
+ HIT 1
+ }
+ elif lib close {
+ HIT 2
+ }
+ else {
+ HIT 3
+ }
+ endif
+elif hdr limits {
+ HIT 4
+}
+else {
+ HIT 5
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_limits 1 /* #include <limits.h> ok */
+HIT 4
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is _XXX_stdio.h a header ... no
+iffe: test: is limits.h a header ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if hdr _XXX_stdio
+ if lib open {
+ HIT 1
+ }
+ elif lib close {
+ HIT 2
+ }
+ else {
+ HIT 3
+ }
+ endif
+elif hdr _XXX_limits {
+ HIT 4
+}
+else {
+ HIT 5
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+HIT 5
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is _XXX_stdio.h a header ... no
+iffe: test: is _XXX_limits.h a header ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if hdr stdio
+ if lib _XXX_open {
+ HIT 1
+ }
+ elif lib close {
+ HIT 2
+ }
+ else {
+ HIT 3
+ }
+ endif
+elif hdr limits {
+ HIT 4
+}
+else {
+ HIT 5
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define _lib_close 1 /* close() in default lib(s) */
+ HIT 2
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is _XXX_open a library function ... no
+iffe: test: is close a library function ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if hdr stdio
+ if lib _XXX_open {
+ HIT 1
+ }
+ elif lib _XXX_close {
+ HIT 2
+ }
+ else {
+ HIT 3
+ }
+ endif
+elif hdr limits {
+ HIT 4
+}
+else {
+ HIT 5
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+ HIT 3
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is _XXX_open a library function ... no
+iffe: test: is _XXX_close a library function ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if mem stat.st_atime sys/types.h sys/stat.h {
+ #define ATIME 1
+}
+elif mem stat.st_ctime sys/types.h sys/stat.h {
+ #define CTIME 1
+}
+elif mem stat.st_mtime sys/types.h sys/stat.h {
+ #define MTIME 1
+}
+else pass{ no_stat_time=1 }end {
+ #define NOTIME 1
+}
+endif
+if ( !no_stat_time ) {
+ #define YESTIME 1
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _sys_stat 1 /* #include <sys/stat.h> ok */
+#define _mem_st_atime_stat 1 /* st_atime is a member of struct stat */
+#define ATIME 1
+
+#define YESTIME 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is sys/stat.h a header ... yes
+iffe: test: is stat a type or typedef ... no
+iffe: test: is st_atime a member of struct stat ... yes
+iffe: test: is ( !no_stat_time ) true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if mem foo_stat.st_atime sys/types.h sys/stat.h {
+ #define ATIME 1
+}
+elif mem stat.st_ctime sys/types.h sys/stat.h {
+ #define CTIME 1
+}
+elif mem stat.st_mtime sys/types.h sys/stat.h {
+ #define MTIME 1
+}
+else pass{ no_stat_time=1 }end {
+ #define NOTIME 1
+}
+endif
+if ( !no_stat_time ) {
+ #define YESTIME 1
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _sys_stat 1 /* #include <sys/stat.h> ok */
+#define _mem_st_ctime_stat 1 /* st_ctime is a member of struct stat */
+#define CTIME 1
+
+#define YESTIME 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is sys/stat.h a header ... yes
+iffe: test: is foo_stat a type or typedef ... no
+iffe: test: is st_atime a member of struct foo_stat ... no
+iffe: test: is stat a type or typedef ... no
+iffe: test: is st_ctime a member of struct stat ... yes
+iffe: test: is ( !no_stat_time ) true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if mem foo_stat.st_atime sys/types.h sys/stat.h {
+ #define ATIME 1
+}
+elif mem foo_stat.st_ctime sys/types.h sys/stat.h {
+ #define CTIME 1
+}
+elif mem stat.st_mtime sys/types.h sys/stat.h {
+ #define MTIME 1
+}
+else pass{ no_stat_time=1 }end {
+ #define NOTIME 1
+}
+endif
+if ( !no_stat_time ) {
+ #define YESTIME 1
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _sys_stat 1 /* #include <sys/stat.h> ok */
+#define _mem_st_mtime_stat 1 /* st_mtime is a member of struct stat */
+#define MTIME 1
+
+#define YESTIME 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is sys/stat.h a header ... yes
+iffe: test: is foo_stat a type or typedef ... no
+iffe: test: is st_atime a member of struct foo_stat ... no
+iffe: test: is st_ctime a member of struct foo_stat ... no
+iffe: test: is stat a type or typedef ... no
+iffe: test: is st_mtime a member of struct stat ... yes
+iffe: test: is ( !no_stat_time ) true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff ifelse
+if mem foo_stat.st_atime sys/types.h sys/stat.h {
+ #define ATIME 1
+}
+elif mem foo_stat.st_ctime sys/types.h sys/stat.h {
+ #define CTIME 1
+}
+elif mem foo_stat.st_mtime sys/types.h sys/stat.h {
+ #define MTIME 1
+}
+else pass{ no_stat_time=1 }end {
+ #define NOTIME 1
+}
+endif
+if ( !no_stat_time ) {
+ #define YESTIME 1
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _ifelse_H
+#define _ifelse_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _sys_stat 1 /* #include <sys/stat.h> ok */
+#define NOTIME 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is sys/stat.h a header ... yes
+iffe: test: is foo_stat a type or typedef ... no
+iffe: test: is st_atime a member of struct foo_stat ... no
+iffe: test: is st_ctime a member of struct foo_stat ... no
+iffe: test: is st_mtime a member of struct foo_stat ... no
+iffe: test: is ( !no_stat_time ) true ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'set explicit
+iff previous
+hdr stdio
+if hdr stdio {
+ OK
+}
+else {
+ OK
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _previous_H
+#define _previous_H 1
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+OK
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+TEST 04 'test variable/macro override'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+HAVE_STDIO = hdr stdio'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define HAVE_STDIO 1 /* #include <stdio.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if hdr - stdio {
+ #define HIT 1
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define HIT 1
+
+#endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if - hdr stdio {
+ #define HIT 1
+}
+endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if ? hdr stdio {
+ #define HIT 1
+}
+endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if hdr - stdio {
+ #define HIT 1
+}
+endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if HAVE_STDIO = hdr stdio {
+ #define HIT 1
+}
+endif
+if ( HAVE_STDIO ) {
+ #define TOO ALSO
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define HAVE_STDIO 1 /* #include <stdio.h> ok */
+#define HIT 1
+
+#define TOO ALSO
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is ( HAVE_STDIO ) true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if HAVE_STDIO = hdr stdio {
+ #define HIT 1
+}
+endif
+exp ALSO HAVE_STDIO'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define HAVE_STDIO 1 /* #include <stdio.h> ok */
+#define HIT 1
+
+#define ALSO 1 /* HAVE_STDIO is true */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is HAVE_STDIO true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if HAVE_STDIO = hdr stdio {
+ #define HIT 1
+}
+endif
+ALSO = ( HAVE_STDIO )'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define HAVE_STDIO 1 /* #include <stdio.h> ok */
+#define HIT 1
+
+#define ALSO 1 /* ( HAVE_STDIO ) is true */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is ( HAVE_STDIO ) true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+TEST 05 'test code option sequence'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+tst seq - -DA=1 - -DB=1 note{ long int type }end compile{
+ #if A == 1 && B == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end'
+ OUTPUT - '/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _seq 1 /* long int type */
+#endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+tst seq -DG=1 - -DN=1 - -DN=2 note{ long int type }end compile{
+ #if G == 1 && N == 1
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+tst seq - -DA=1 - -DB=1 note{ long int type }end compile{
+ #if A == 0 && B == 1
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+tst seq -DG=1 - -DN=1 - -DN=2 note{ long int type }end compile{
+ #if G == 1 && N == 2
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+tst seq - -DA=1 - -DB=1 note{ long int type }end compile{
+ #if A == 0 && B == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end'
+ OUTPUT - '/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+tst seq -DG=1 - -DN=1 - -DN=2 note{ long int type }end compile{
+ #if G == 1 && N == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DA=1 - -DB=1 note{ long int type }end compile{
+ #if A == 1 && B == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ OUTPUT - '/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+/* long int type */
+#define seq 1
+
+#endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst -DG=1 - -DN=1 - -DN=2 note{ long int type }end compile{
+ #if G == 1 && N == 1
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DA=1 - -DB=1 note{ long int type }end compile{
+ #if A == 0 && B == 1
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst -DG=1 - -DN=1 - -DN=2 note{ long int type }end compile{
+ #if G == 1 && N == 2
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DA=1 - -DB=1 note{ long int type }end compile{
+ #if A == 0 && B == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ OUTPUT - '/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst -DG=1 - -DN=1 - -DN=2 note{ long int type }end compile{
+ #if G == 1 && N == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DN=1 - -DN=2 - -DN=3 note{ long int type }end compile{
+ #if N == 1
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ OUTPUT - '/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+/* long int type */
+#define seq 1
+
+#endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DN=1 - -DN=2 - -DN=3 note{ long int type }end compile{
+ #if N == 2
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DN=1 - -DN=2 - -DN=3 note{ long int type }end compile{
+ #if N == 3
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ...
+iffe: test: long int type ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff macro
+if tst - -DN=1 - -DN=2 - -DN=3 note{ long int type }end compile{
+ #if N == 0
+ #define t long
+ #else
+ #define t error
+ #endif
+ t n = 0;
+}end {
+ #define seq 1
+}
+endif'
+ OUTPUT - '/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _macro_H
+#define _macro_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#endif'
+ ERROR - 'iffe: test: is sys/types.h a header ... yes
+iffe: test: long int type ...
+iffe: test: long int type ...
+iffe: test: long int type ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+TEST 06 'block side effects'
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'iff -
+tst output{
+ int
+ main()
+ {
+ printf("HIT\\n");
+ return 0;
+ }
+}end'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#define _sys_types 1 /* #include <sys/types.h> ok */
+HIT'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'iff
+tst - output{
+ int
+ main()
+ {
+ printf("HIT\\n");
+ return 0;
+ }
+}end'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'iff
+tst - output{
+ int
+ main()
+ {
+ printf("HIT\\n");
+ return 1;
+ }
+}end'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#define _sys_types 1 /* #include <sys/types.h> ok */'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'iff
+tst - nooutput{
+ int
+ main()
+ {
+ printf("HIT\\n");
+ return 1;
+ }
+}end'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#define _sys_types 1 /* #include <sys/types.h> ok */
+HIT'
+
+ EXEC -r -s bsh - t.iffe
+
+TEST 07 'diagnostics'
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'tst foo'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#endif'
+ ERROR - $'iffe: t.iffe:1: tst: unknown feature test'
+ EXIT 1
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'if (1)'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */'
+ ERROR - $'iffe: t.iffe:1: missing endif'
+ EXIT 1
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'if'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */'
+ ERROR - $'iffe: t.iffe:1: missing endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'endif'
+ ERROR - $'iffe: t.iffe:1: endif: no matching if'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'if {
+}end'
+ ERROR - $'iffe: t.iffe:2: missing }'
+
+ EXEC -r -s bsh - t.iffe
+
+TEST 08 'negation consternation'
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'npt fopen,fooon stdio.h'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdlib 1 /* #include <stdlib.h> ok */
+#define _hdr_unistd 1 /* #include <unistd.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define _npt_fooon 1 /* fooon() needs a prototype */
+#endif'
+
+ EXEC -r -u - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdlib 1 /* #include <stdlib.h> ok */
+#define _hdr_unistd 1 /* #include <unistd.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#undef _npt_fopen /* fopen() does not need a prototype */
+#define _npt_fooon 1 /* fooon() needs a prototype */
+#endif'
+
+ EXEC -r -a - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdlib 1 /* #include <stdlib.h> ok */
+#define _hdr_unistd 1 /* #include <unistd.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define _npt_fopen 0 /* fopen() does not need a prototype */
+#define _npt_fooon 1 /* fooon() needs a prototype */
+#endif'
+
+ EXEC -r -C - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define HAVE_SYS_TYPES_H 1 /* #include <sys/types.h> ok */
+#define HAVE_STDLIB_H 1 /* #include <stdlib.h> ok */
+#define HAVE_UNISTD_H 1 /* #include <unistd.h> ok */
+#define HAVE_STDIO_H 1 /* #include <stdio.h> ok */
+#define HAVE_FOPEN_DECL 1 /* fopen() does not need a prototype */
+#undef HAVE_FOOON_DECL /* fooon() needs a prototype */
+#endif'
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'NEED_FOPEN = npt fopen stdio.h
+HAVE_FOPEN = ! npt fopen stdio.h
+NEED_FOOON = npt fooon stdio.h
+HAVE_FOOON = ! npt fooon stdio.h'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdlib 1 /* #include <stdlib.h> ok */
+#define _hdr_unistd 1 /* #include <unistd.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#define HAVE_FOPEN 1 /* fopen() does not need a prototype */
+#define NEED_FOOON 1 /* fooon() needs a prototype */
+#endif'
+
+ EXEC -r -u - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_stdlib 1 /* #include <stdlib.h> ok */
+#define _hdr_unistd 1 /* #include <unistd.h> ok */
+#define _hdr_stdio 1 /* #include <stdio.h> ok */
+#undef NEED_FOPEN /* fopen() does not need a prototype */
+#define HAVE_FOPEN 1 /* fopen() does not need a prototype */
+#define NEED_FOOON 1 /* fooon() needs a prototype */
+#undef HAVE_FOOON /* fooon() needs a prototype */
+#endif'
+
+ EXEC -r -C - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define HAVE_SYS_TYPES_H 1 /* #include <sys/types.h> ok */
+#define HAVE_STDLIB_H 1 /* #include <stdlib.h> ok */
+#define HAVE_UNISTD_H 1 /* #include <unistd.h> ok */
+#define HAVE_STDIO_H 1 /* #include <stdio.h> ok */
+#undef NEED_FOPEN /* fopen() does not need a prototype */
+#define HAVE_FOPEN 1 /* fopen() does not need a prototype */
+#define NEED_FOOON 1 /* fooon() needs a prototype */
+#undef HAVE_FOOON /* fooon() needs a prototype */
+#endif'
+
+TEST 09 'exp vs. if'
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_false {
+ ONE
+}
+exp _tst_hit !_tst_hit&_tst_true pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&_tst_true {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#define _tst_hit 1 /* !_tst_false is true */
+/* !_tst_false */
+ONE
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_true {
+ ONE
+}
+exp _tst_hit !_tst_hit&_tst_true pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&_tst_true {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#define _tst_hit 1 /* !_tst_hit&_tst_true is true */
+TWO 0 1
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_true {
+ ONE
+}
+exp _tst_hit !_tst_hit&_tst_false pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&_tst_true {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#define _tst_hit 1 /* !_tst_hit&_tst_true is true */
+/* !_tst_hit&_tst_true */
+THREE
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_true {
+ ONE
+}
+exp _tst_hit !_tst_hit&_tst_false pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&_tst_false {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_false {
+ ONE
+}
+exp _tst_hit !_tst_hit&&_tst_true pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&&_tst_true {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#define _tst_hit 1 /* !_tst_false is true */
+/* !_tst_false */
+ONE
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_true {
+ ONE
+}
+exp _tst_hit !_tst_hit&&_tst_true pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&&_tst_true {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#define _tst_hit 1 /* !_tst_hit&&_tst_true is true */
+TWO 0 1
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_true {
+ ONE
+}
+exp _tst_hit !_tst_hit&&_tst_false pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&&_tst_true {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#define _tst_hit 1 /* !_tst_hit&&_tst_true is true */
+/* !_tst_hit&&_tst_true */
+THREE
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+exp _tst_hit !_tst_true {
+ ONE
+}
+exp _tst_hit !_tst_hit&&_tst_false pass{
+cat <<!
+ TWO $_tst_false $_tst_true
+!
+}end
+exp _tst_hit !_tst_hit&&_tst_false {
+ THREE
+}'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+if ( ! _tst_false ) {
+ ONE
+}
+elif ( _tst_true ) pass{
+cat <<!
+ TWO
+!
+}end
+else {
+ THREE
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+ONE
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+if ( ! _tst_true ) {
+ ONE
+}
+elif ( _tst_true ) pass{
+cat <<!
+ TWO
+!
+}end
+else {
+ THREE
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+TWO
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+if ( ! _tst_true ) {
+ ONE
+}
+elif ( _tst_false ) pass{
+cat <<!
+ TWO
+!
+}end
+else {
+ THREE
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+THREE
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+if ( ! _tst_true ) yes{
+ typedef struct
+ {
+ int dd_fd; /* file descriptor */
+ } DIR;
+}end
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+if ( ! _tst_true ) {
+ typedef struct
+ {
+ int dd_fd; /* file descriptor */
+ } DIR;
+}
+else {
+ OK
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _tst_true 1 /* ( 1 ) is true */
+OK
+
+#endif'
+
+ EXEC -r -s bsh - t.iffe
+
+ EXEC -r - t.iffe
+ INPUT t.iffe $'_tst_false = ( 0 )
+_tst_true = ( 1 )
+if ( ! _tst_true ) {
+ typedef struct
+ {
+ int dd_fd; /* file descriptor */
+ };
+}
+else {
+ OK
+}
+endif'
+
+ EXEC -r -s bsh - t.iffe
+
+TEST 10 'exp details'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'_str = "string"
+_hdr = <header>
+_aaa = ( 0 )
+_zzz = ( 1 )
+( _str )
+( ! _str )
+( _hdr )
+( ! _hdr )
+( _aaa )
+( ! _aaa )
+( _zzz )
+( ! _zzz )'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _str "string"
+#define _hdr <header>
+#define _zzz 1 /* ( 1 ) is true */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is ( 0 ) true ... no
+iffe: test: is ( 1 ) true ... yes
+iffe: test: is ( _str ) true ... yes
+iffe: test: is ( ! _str ) true ... no
+iffe: test: is ( _hdr ) true ... yes
+iffe: test: is ( ! _hdr ) true ... no
+iffe: test: is ( _aaa ) true ... no
+iffe: test: is ( ! _aaa ) true ... yes
+iffe: test: is ( _zzz ) true ... yes
+iffe: test: is ( ! _zzz ) true ... no'
+
+ EXEC -r -v -s bsh - t.iffe
+
+TEST 11 'set [no]define'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'set nodefine
+mem stat.st_mtime sys/types.h sys/stat.h
+set define
+mem stat.st_mode sys/types.h sys/stat.h
+if ( _mem_st_mtime_stat ) {
+ 1
+}
+endif
+if ( _mem_st_mode_stat ) {
+ 2
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _mem_st_mode_stat 1 /* st_mode is a member of struct stat */
+1
+
+2
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is sys/stat.h a header ... yes
+iffe: test: is stat a type or typedef ... no
+iffe: test: is st_mtime a member of struct stat ... yes
+iffe: test: is st_mode a member of struct stat ... yes
+iffe: test: is ( _mem_st_mtime_stat ) true ... yes
+iffe: test: is ( _mem_st_mode_stat ) true ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+TEST 12 'non-opaque mem'
+
+ EXEC -r -v - mem OPAQUE -I. t.h
+ INPUT t.h $'typedef struct opaque OPAQUE;'
+ OUTPUT - $'/* : : generated by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_t 1 /* #include <t.h> ok */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is t.h a header ... yes
+iffe: test: is OPAQUE a type or typedef ... no
+iffe: test: is struct OPAQUE a non-opaque struct ... no'
+
+ EXEC -r -v - mem NONOPAQUE -I. t.h
+ INPUT t.h $'struct nonopaque { int pad; };
+typedef struct nonopaque NONOPAQUE;'
+ OUTPUT - $'/* : : generated by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _hdr_t 1 /* #include <t.h> ok */
+#define _mem_NONOPAQUE 1 /* NONOPAQUE is a non-opaque struct */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is t.h a header ... yes
+iffe: test: is NONOPAQUE a type or typedef ... yes
+iffe: test: is NONOPAQUE a non-opaque struct ... yes'
+
+TEST 13 'key states'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'key int
+key const =
+key foo
+key bar =
+key aha = huh = int
+key chr = char = int'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _key_int 1 /* int is a reserved keyword */
+#define _key_const 1 /* const is a reserved keyword */
+#define bar /* default for reserved keyword bar */
+#define aha int /* default for reserved keyword aha */
+#define _key_char 1 /* char is a reserved keyword */
+#define chr char /* alternate for reserved keyword chr */
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is int a reserved keyword ... yes
+iffe: test: is const a reserved keyword ... yes
+iffe: test: is foo a reserved keyword ... no
+iffe: test: is bar a reserved keyword ... no
+iffe: test: is aha a reserved keyword ... no
+iffe: test: is huh a reserved keyword ... no
+iffe: test: is chr a reserved keyword ... no
+iffe: test: is char a reserved keyword ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -u -r -v - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _key_int 1 /* int is a reserved keyword */
+#define _key_const 1 /* const is a reserved keyword */
+#undef _key_foo /* foo is not a reserved keyword */
+#undef _key_bar /* bar is not a reserved keyword */
+#define bar /* default for reserved keyword bar */
+#undef _key_huh /* huh is not a reserved keyword */
+#define aha int /* default for reserved keyword aha */
+#define _key_char 1 /* char is a reserved keyword */
+#define chr char /* alternate for reserved keyword chr */
+#endif'
+
+ EXEC -u -r -v -s bsh - t.iffe
+
+ EXEC -a -r -v - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define _key_int 1 /* int is a reserved keyword */
+#define _key_const 1 /* const is a reserved keyword */
+#define _key_foo 0 /* foo is not a reserved keyword */
+#define _key_bar 0 /* bar is not a reserved keyword */
+#define bar /* default for reserved keyword bar */
+#define _key_huh 0 /* huh is not a reserved keyword */
+#define aha int /* default for reserved keyword aha */
+#define _key_char 1 /* char is a reserved keyword */
+#define chr char /* alternate for reserved keyword chr */
+#endif'
+
+ EXEC -a -r -v -s bsh - t.iffe
+
+ EXEC -C -r -v - t.iffe
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define HAVE_SYS_TYPES_H 1 /* #include <sys/types.h> ok */
+#define HAVE_INT_RESERVED 1 /* int is a reserved keyword */
+#define HAVE_CONST_RESERVED 1 /* const is a reserved keyword */
+#undef HAVE_FOO_RESERVED /* foo is not a reserved keyword */
+#undef HAVE_BAR_RESERVED /* bar is not a reserved keyword */
+#define bar /* default for reserved keyword bar */
+#undef HAVE_HUH_RESERVED /* huh is not a reserved keyword */
+#define aha int /* default for reserved keyword aha */
+#define HAVE_CHAR_RESERVED 1 /* char is a reserved keyword */
+#define chr char /* alternate for reserved keyword chr */
+#endif'
+
+ EXEC -C -r -v -s bsh - t.iffe
+
+TEST 14 'inc file'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'inc t_lib.h
+if ( bar_foo ) {
+ #define all 1
+}
+elif ( _foo_bar ) {
+ #define some 1
+}
+endif'
+ INPUT t_lib.h '#define bar_foo ALL
+#define _foo_bar SOME'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define some 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is ( bar_foo ) true ... no
+iffe: test: is ( _foo_bar ) true ... yes'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'inc t_lib.h .
+if ( bar_foo ) {
+ #define all 1
+}
+elif ( _foo_bar ) {
+ #define ok 1
+}
+endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define all 1
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is ( bar_foo ) true ... yes'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'inc t_lib.h . ?
+if ( bar_foo ) {
+ #define all 1
+}
+elif ( _foo_bar ) {
+ #define ok 1
+}
+endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: t.iffe:1: warning: ?: operands ignored
+iffe: test: is ( bar_foo ) true ... yes'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'inc foo_lib.h'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: t.iffe:1: foo_lib.h: file not found'
+ EXIT 1
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'inc'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: t.iffe:1: path expected'
+
+TEST 15 'KnR compatibility'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'
+if ( 1 ) {
+ #define all 1
+}
+endif
+if ( 2 ) {
+ #define some 1
+}
+endif
+cat{
+#define a 1
+ #define b 2
+ #define c 3
+ #define d 4
+}end'
+#define _foo_bar SOME'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define some 1
+
+#endif'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#define all 1
+
+#define some 1
+
+#define a 1
+#define b 2
+#define c 3
+#define d 4
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is ( 1 ) true ... yes
+iffe: test: is ( 2 ) true ... yes
+iffe: test: cat{ ... }end ... yes'
+
+ EXEC -r -v -s bsh - t.iffe
+
+ EXEC -r -v -s osh - t.iffe
+
+TEST 16 '{ define extern include print }'
+
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'
+print /* test header */
+header stdio.h
+define EOF -1
+define FoobaR (a,b) ((a)+(b))
+define FoomaC -1
+extern fopen FILE* (char*, char*)
+extern BarfoO struct barfoo* (int)
+extern Tab_lE struct barfoo* [10]'
+ OUTPUT - $'/* test header */
+/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _REGRESS
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#include <stdio.h>
+#define FoobaR(a,b) ((a)+(b))
+#define FoomaC -1
+extern struct barfoo* BarfoO(int);
+extern struct barfoo* Tab_lE[10];
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes
+iffe: test: is EOF a macro ... yes
+iffe: test: is FoobaR a macro ... no
+iffe: test: is FoomaC a macro ... no
+iffe: test: is fopen a symbol that needs a prototype ... no
+iffe: test: is BarfoO a symbol that needs a prototype ... yes
+iffe: test: is Tab_lE a symbol that needs a prototype ... yes'
+
+TEST 17 'features/* => FEATURE/*'
+
+ EXEC -r -v run features/stdio
+ INPUT features/stdio $'set prototyped
+header stdio.h'
+ OUTPUT FEATURE/stdio $'
+/* : : generated by proto : : */
+/* : : generated from features/stdio by iffe version 1995-03-19 : : */
+
+#ifndef _REGRESS
+#if !defined(__PROTO__)
+# if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
+# if defined(__cplusplus)
+# define __LINKAGE__ "C"
+# else
+# define __LINKAGE__
+# endif
+# define __STDARG__
+# define __PROTO__(x) x
+# define __OTORP__(x)
+# define __PARAM__(n,o) n
+# if !defined(__STDC__) && !defined(__cplusplus)
+# if !defined(c_plusplus)
+# define const
+# endif
+# define signed
+# define void int
+# define volatile
+# define __V_ char
+# else
+# define __V_ void
+# endif
+# else
+# define __PROTO__(x) ()
+# define __OTORP__(x) x
+# define __PARAM__(n,o) o
+# define __LINKAGE__
+# define __V_ char
+# define const
+# define signed
+# define void int
+# define volatile
+# endif
+# define __MANGLE__ __LINKAGE__
+# if defined(__cplusplus) || defined(c_plusplus)
+# define __VARARG__ ...
+# else
+# define __VARARG__
+# endif
+# if defined(__STDARG__)
+# define __VA_START__(p,a) va_start(p,a)
+# else
+# define __VA_START__(p,a) va_start(p)
+# endif
+# if !defined(__INLINE__)
+# if defined(__cplusplus)
+# define __INLINE__ extern __MANGLE__ inline
+# else
+# if defined(_WIN32) && !defined(__GNUC__)
+# define __INLINE__ __inline
+# endif
+# endif
+# endif
+#endif
+#if !defined(__LINKAGE__)
+#define __LINKAGE__ /* 2004-08-11 transition */
+#endif
+
+#define _REGRESS 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+#include <stdio.h>
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes
+iffe: test: is stdio.h a header ... yes'
+
+TEST 18 'api + ver'
+ EXEC -r -v - t.iffe
+ INPUT t.iffe $'iff api
+ver foo 20100606
+ver bar 19840919
+
+api foo 19991231 dis dat tother
+api foo 20100601 dat
+api foo 20100606 dis
+api bar 19991231 moe larry shemp
+api bar 20020202 curly
+api bar 20030303 shemp
+api bar 20040404 joe_b
+api bar 20050505 joe_d
+'
+ OUTPUT - $'/* : : generated from t.iffe by iffe version 1995-03-19 : : */
+#ifndef _api_H
+#define _api_H 1
+#define _sys_types 1 /* #include <sys/types.h> ok */
+
+#define FOO_VERSION 20100606
+#define BAR_VERSION 19840919
+
+#if !defined(_API_foo) && defined(_API_DEFAULT)
+#define _API_foo _API_DEFAULT
+#endif
+
+#if ( _BLD_foo || !_API_foo || _API_foo >= 20100601 )
+#undef dat
+#define dat dat_20100601
+#elif _API_foo >= 19991231
+#undef dat
+#define dat dat_19991231
+#endif
+
+#if ( _BLD_foo || !_API_foo || _API_foo >= 20100606 )
+#undef dis
+#define dis dis_20100606
+#elif _API_foo >= 19991231
+#undef dis
+#define dis dis_19991231
+#endif
+
+#if ( _BLD_foo || !_API_foo || _API_foo >= 19991231 )
+#undef tother
+#define tother tother_19991231
+#endif
+
+#define _API_foo_MAP "dat_20100601 dat_19991231 dis_20100606 dis_19991231 tother_19991231"
+
+#if !defined(_API_bar) && defined(_API_DEFAULT)
+#define _API_bar _API_DEFAULT
+#endif
+
+#if ( _BLD_bar || !_API_bar || _API_bar >= 20020202 )
+#undef curly
+#define curly curly_20020202
+#endif
+
+#if ( _BLD_bar || !_API_bar || _API_bar >= 20040404 )
+#undef joe_b
+#define joe_b joe_b_20040404
+#endif
+
+#if ( _BLD_bar || !_API_bar || _API_bar >= 20050505 )
+#undef joe_d
+#define joe_d joe_d_20050505
+#endif
+
+#if ( _BLD_bar || !_API_bar || _API_bar >= 19991231 )
+#undef larry
+#define larry larry_19991231
+#endif
+
+#if ( _BLD_bar || !_API_bar || _API_bar >= 19991231 )
+#undef moe
+#define moe moe_19991231
+#endif
+
+#if ( _BLD_bar || !_API_bar || _API_bar >= 20030303 )
+#undef shemp
+#define shemp shemp_20030303
+#elif _API_bar >= 19991231
+#undef shemp
+#define shemp shemp_19991231
+#endif
+
+#define _API_bar_MAP "curly_20020202 joe_b_20040404 joe_d_20050505 larry_19991231 moe_19991231 shemp_20030303 shemp_19991231"
+
+#endif'
+ ERROR - $'iffe: test: is sys/types.h a header ... yes'
diff --git a/src/cmd/INIT/ignore.sh b/src/cmd/INIT/ignore.sh
new file mode 100644
index 0000000..2999645
--- /dev/null
+++ b/src/cmd/INIT/ignore.sh
@@ -0,0 +1,43 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+# non-ksh script for the nmake ignore prefix
+# @(#)ignore (AT&T Research) 1992-08-11
+
+case $-:$BASH_VERSION in
+*x*:[0123456789]*) : bash set -x is broken :; set +ex ;;
+esac
+
+while :
+do case $# in
+ 0) exit 0 ;;
+ esac
+ case $1 in
+ *=*) case $RANDOM in
+ $RANDOM)`echo $1 | sed "s/\\([^=]*\\)=\\(.*\\)/eval \\1='\\2'; export \\1/"` ;;
+ *) export "$1" ;;
+ esac
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+done
+"$@"
+exit 0
diff --git a/src/cmd/INIT/intl.c b/src/cmd/INIT/intl.c
new file mode 100644
index 0000000..1623dd6
--- /dev/null
+++ b/src/cmd/INIT/intl.c
@@ -0,0 +1,29 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#ifndef gettext
+#include <libintl.h>
+#endif
+
+int
+main()
+{
+ gettext(0);
+ return 0;
+}
diff --git a/src/cmd/INIT/ld.hp.pa b/src/cmd/INIT/ld.hp.pa
new file mode 100755
index 0000000..99d39f0
--- /dev/null
+++ b/src/cmd/INIT/ld.hp.pa
@@ -0,0 +1,5 @@
+: hp.pa ld wrapper for reasonable warning defaults
+
+# @(#)ld.hp.pa (AT&T Labs Research) 1998-01-23
+
+/bin/ld +s +vnocompatwarnings "$@"
diff --git a/src/cmd/INIT/ldd.cygwin.i386 b/src/cmd/INIT/ldd.cygwin.i386
new file mode 100755
index 0000000..5976b1f
--- /dev/null
+++ b/src/cmd/INIT/ldd.cygwin.i386
@@ -0,0 +1,22 @@
+#!/bin/env sh
+: cygwin.i386 ldd -- how many ways does this confirm the windows bias?
+for f
+do case $f in
+ *.exe) ;;
+ *) f=$f.exe ;;
+ esac
+ p=$(type $f)
+ case $p in
+ *" not found"*)
+ ;;
+ *) p=${p##* }
+ case $p in
+ ?*) f=$p ;;
+ esac
+ ;;
+ esac
+ cygcheck $(cygpath -aw $f) |
+ for w in $(sed -e 's/^[[:space:]]*//' -e '/^$/d' -e '/^Use /d')
+ do cygpath -u "$w"
+ done
+done
diff --git a/src/cmd/INIT/ldd.darwin b/src/cmd/INIT/ldd.darwin
new file mode 100755
index 0000000..ec75f7b
--- /dev/null
+++ b/src/cmd/INIT/ldd.darwin
@@ -0,0 +1,2 @@
+: mac os10 ldd
+otool -L "$@"
diff --git a/src/cmd/INIT/ldd.hp.pa b/src/cmd/INIT/ldd.hp.pa
new file mode 100755
index 0000000..34874b4
--- /dev/null
+++ b/src/cmd/INIT/ldd.hp.pa
@@ -0,0 +1,21 @@
+: hp.pa ldd
+while :
+do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -*|+*) ;;
+ *) break ;;
+ esac
+ shift
+done
+trap ':' 15
+for cmd
+do case $# in
+ 1) ;;
+ *) echo $cmd: ;;
+ esac
+ _HP_DLDOPTS=-ldd "$cmd" < /dev/null 2> /dev/null | sort -u
+ # chatr "$cmd" |
+ # sed -e '/^[ ]*dynamic[ ][ ]*/!d' -e 's// /'
+done
diff --git a/src/cmd/INIT/ldd.ibm.risc b/src/cmd/INIT/ldd.ibm.risc
new file mode 100755
index 0000000..984ef6d
--- /dev/null
+++ b/src/cmd/INIT/ldd.ibm.risc
@@ -0,0 +1,16 @@
+: ibm.risc ldd
+case $# in
+1) header=0 ;;
+*) header=1 ;;
+esac
+for file
+do case $header in
+ 1) echo "$file:"
+ header=2
+ ;;
+ 2) echo
+ echo "$file:"
+ ;;
+ esac
+ dump -H "$file" | sed '1,/\*\*\*Import/d'
+done
diff --git a/src/cmd/INIT/ldd.lynxos b/src/cmd/INIT/ldd.lynxos
new file mode 100755
index 0000000..43904a8
--- /dev/null
+++ b/src/cmd/INIT/ldd.lynxos
@@ -0,0 +1 @@
+elflook -L "$@" | sed -e '/^NEEDED:/!d' -e 's/.*: *//'
diff --git a/src/cmd/INIT/ldd.mvs.390 b/src/cmd/INIT/ldd.mvs.390
new file mode 100755
index 0000000..341c4cc
--- /dev/null
+++ b/src/cmd/INIT/ldd.mvs.390
@@ -0,0 +1,18 @@
+: mvs.390 ldd
+case $# in
+1) header=0 ;;
+*) header=1 ;;
+esac
+for file
+do case $header in
+ 1) echo "$file:"
+ header=2
+ ;;
+ 2) echo
+ echo "$file:"
+ ;;
+ esac
+ strings $file |
+ sed -e '/\<[[:lower:]][[:alnum:]]*\.dll\>/!d' -e 's/^/ /' |
+ sort -u
+done
diff --git a/src/cmd/INIT/ldd.sgi b/src/cmd/INIT/ldd.sgi
new file mode 100755
index 0000000..d3c5347
--- /dev/null
+++ b/src/cmd/INIT/ldd.sgi
@@ -0,0 +1,2 @@
+: sgi.mips ldd
+odump -Dl "$@"
diff --git a/src/cmd/INIT/m.c b/src/cmd/INIT/m.c
new file mode 100644
index 0000000..b56b99b
--- /dev/null
+++ b/src/cmd/INIT/m.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * -lm test #1
+ */
+
+#ifndef sin
+#include <math.h>
+#endif
+
+int
+main()
+{
+ sin(0.0);
+ fmod(100.234, 11.0);
+ return 0;
+}
diff --git a/src/cmd/INIT/m2.c b/src/cmd/INIT/m2.c
new file mode 100644
index 0000000..cad12b1
--- /dev/null
+++ b/src/cmd/INIT/m2.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * -lm test #2
+ */
+
+#include <math.h>
+
+int
+main()
+{
+ double value = 0;
+ int exp = 0;
+ int r = 0;
+
+ r |= ldexp(value, exp) != 0;
+ r |= frexp(value, &exp) != 0;
+ return r;
+}
diff --git a/src/cmd/INIT/m3.c b/src/cmd/INIT/m3.c
new file mode 100644
index 0000000..5d89991
--- /dev/null
+++ b/src/cmd/INIT/m3.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * -lm test #3
+ */
+
+#include <math.h>
+
+int
+main()
+{
+ long double value = 0;
+ int exp = 0;
+ int r = 0;
+
+ r |= ldexpl(value, exp) != 0;
+ r |= frexpl(value, &exp) != 0;
+ return r;
+}
diff --git a/src/cmd/INIT/m4.c b/src/cmd/INIT/m4.c
new file mode 100644
index 0000000..79b87f0
--- /dev/null
+++ b/src/cmd/INIT/m4.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * -lm test #4
+ */
+
+#include <math.h>
+
+int
+main()
+{
+ double value = 0;
+
+ return isnan(value);
+}
diff --git a/src/cmd/INIT/m5.c b/src/cmd/INIT/m5.c
new file mode 100644
index 0000000..f853921
--- /dev/null
+++ b/src/cmd/INIT/m5.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * -lm test #5
+ */
+
+#include <math.h>
+
+int
+main()
+{
+ long double value = 0;
+
+ return isnanl(value);
+}
diff --git a/src/cmd/INIT/m6.c b/src/cmd/INIT/m6.c
new file mode 100644
index 0000000..4387ea0
--- /dev/null
+++ b/src/cmd/INIT/m6.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * -lm test #6
+ */
+
+#define _ISOC99_SOURCE 1
+
+#include <math.h>
+
+int
+main()
+{
+ double value = -0.0;
+
+ return !signbit(value);
+}
diff --git a/src/cmd/INIT/make.probe b/src/cmd/INIT/make.probe
new file mode 100644
index 0000000..8a3c383
--- /dev/null
+++ b/src/cmd/INIT/make.probe
@@ -0,0 +1,2242 @@
+:
+### this script contains archaic constructs that work with all sh variants ###
+# Glenn Fowler
+# AT&T Research
+#
+# @(#)make.probe (AT&T Research) 2011-06-01
+#
+# C probe for make
+#
+# NOTE: C.probe must be included or .'d here
+#
+
+cc_dll_def=-D_BLD_DLL
+
+probe_ar_arflags="-Xany"
+probe_arflags="-xar"
+probe_ccs="strip size nm ld ar" # longest to shortest
+probe_debug="-g"
+probe_dll="'-G 0' -Wc,dll,exportall,longname,rent -Wc,exportall -dynamic $cc_dll_def"
+probe_export_dynamic="-rdynamic -export-dynamic -Wl,-export-dynamic -Wl,-E -bexpall -force_flat_namespace"
+probe_gcc_optimize="-O2"
+probe_gcc_version="*[Gg][Cc][Cc]*"
+probe_include_local="'-ignore-source-dir -iquote' -iquote -I-"
+probe_ldlazy='-zlazyload -znolazyload -Wl,-zlazyload -Wl,-znolazyload'
+probe_ldlib="LD_LIBRARY_PATH LIBPATH LPATH"
+probe_ldmap="'-Wl,-M' '-Qoption ld -M' '-Wl,-m' '-m'"
+probe_ldorigin="-Wl,-z,origin"
+probe_ldrecord='-zrecord -zignore -Wl,-zrecord -Wl,-zignore'
+probe_ldrunpath="-Wl,-R, -R -Wl,-rpath, -L"
+probe_ldstrip="'-s -mr' -Wl,-s"
+probe_lib="a lib"
+probe_lib_append="/usr/lib/pa1.1"
+probe_lib_all_undef="-all -notall -all -none -Bwhole-archive -Bno-whole-archive -whole-archive -no-whole-archive -Wl,-whole-archive -Wl,-no-whole-archive -all_load '' -Wl,-zallextract -Wl,-zdefaultextract +forceload +noforceload"
+probe_lib_multiple="-Wl,-zmuldefs"
+probe_libdir="shlib lib"
+probe_nmflags="'' -p -B"
+probe_optimize="-O"
+probe_pic="-Kpic -KPIC -fpic -fPIC -pic -PIC +z +Z"
+probe_no_protect="'-fno-stack-protector -fno-stack-protector-all' -GS-"
+probe_readonly="-R -Krodata -xMerge -Wa,-r"
+probe_shared="'' -G -b -c -shared -Wl,dll"
+probe_shared_name="-Wl,-soname= -h"
+probe_shared_nostart="-nostartfiles"
+probe_shared_registry='"-update_registry $probe_shared_registry_file"'
+probe_shared_registry_file='registry.ld'
+probe_shared_registry_path="\$(LIBDIR)/$probe_shared_registry_file"
+probe_strict="'-ansi -pedantic' '-ansi -strict' -strict -ansi"
+probe_stripflags="'-f -s' -f -s"
+probe_unresolved="'-expect_unresolved \"*\"'"
+probe_warn="-Wall -fullwarn -w3 '-A -A' +w1"
+
+echo '#pragma pp:version' > libpp.$src
+echo '#define dDflag on' > dDflag.$src
+echo 'int main(){return 0;}' > doti.$src
+echo 'int code(){return 0;} int main(){return code();}' > export.$src
+echo '#include <stdio.h>' > imstd.$src
+echo '#include "_i_.h"' > imusr.$src
+echo 'int x;' > _i_.h
+mkdir im
+echo '(' > im/stdio.h
+echo '#include "implc_x.h"
+int main(){f(1);return 0;}' > implc.$src
+echo 'template <class T> void f(T){}' > implc_x.$src
+echo 'template <class T> void f(T);' > implc_x.h
+echo 'extern int NotalL(){return(0);}' > notall.$src
+echo '#include <stdio.h>
+extern int i;
+int i = 1;
+extern int f(){return(!i);}
+int main(){FILE* fp=stdin;return(f());}' > pic.$src
+echo 'class x {int n;} m;' > plusplus.$src
+echo 'int prefix(){return 0;}' > prefix.$src
+echo 'template<class T> int gt(T a, T b);
+template<class T> int gt(T a, T b) { return a > b; }
+int main () { return gt(2,1); }' > ptr.$src
+echo 'int main(){return 0;}' > require.$src
+echo '#if mips && !sgi || __CYGWIN__
+( /* some systems choke on this probe */
+#else
+#if test_const
+#define CONST const
+#else
+#define CONST
+#endif
+CONST char x[]={1,2,3,4,5,6,7,8,9,0};
+int main(){*(char*)x=0; return x[0];}
+#endif' > readonly.$src
+# NOTE: sfclose() defined on uwin, not defined on all other systems
+echo 'extern int sfclose(); extern int ShareD(){return(sfclose());}' > shared.$src
+echo '#define g(a,b) a ## b
+volatile int a;
+const int g(x,y)=1;
+extern int c(int);' > stdc.$src
+echo 'extern int f(); int main() { return f(); }' > sovmain.$src
+echo 'int f() { return 0; }' > sovlib.$src
+echo '#include <stdio.h>
+int i;
+int main(){int j;j = i * 10;return j;}' > strip.$src
+echo 'template <class T> void f(T){}
+int main(){f(1);return 0;}' > toucho.$src
+echo '#if defined(__STDC__) || defined(__cplusplus)
+extern type call(int);
+#endif
+int main() {call(0);return(0);}' > tstlib.$src
+echo 'int main(){return 0;}' > warn.$src
+echo 'int f(){return 0;}' > warn1.$src
+echo 'int f(){}' > warn2.$src
+echo 'int f(){int i; return 0;}' > warn3.$src
+echo 'int f(){int i; return i;}' > warn4.$src
+echo 'int f(){return g();}' > warn5.$src
+warn_enum="1 2 3 4 5"
+
+chmod -w *.$src
+
+ar_arflags=
+arflags=
+cc_dll=
+cc_pic=
+cc_PIC=
+dDflag=
+debug=
+dialect=
+dll_dir='$(LIBDIR)'
+dll_libraries=
+dll_variants=
+doti=
+exectype=
+export_dynamic=
+gnu=
+implicitc=
+include_local=
+lddynamic=
+ldlazy=
+ldnolazy=
+ldnorecord=
+ldorigin=
+ldrecord=
+ldrunpath=
+ldscript=
+ldstatic=
+ldstrip=
+Lflag=
+lib_dll=
+lib_all=
+lib_undef=
+libpath=
+libpp=
+makeoptions=
+nmedit=
+nmflags=
+no_protect=
+optimize=
+plusplus=
+prefix_archive=lib
+prefix_dynamic=
+prefix_shared=lib
+ptrcopy=
+ptrimplicit=
+ptrmkdir=
+readonly=
+repository=
+require=
+runpath=
+shared=
+shared_name=
+shared_registry=
+shellmagic=
+soversion=
+stdc=
+strict=
+stripflags=
+symprefix=
+toucho=
+warn=
+
+set $probe_lib
+lib=$1
+
+d=
+for f in $stdinclude $usrinclude
+do case $f in
+ -I*) ;;
+ *) d="$d $f" ;;
+ esac
+done
+stdinclude=$d
+
+set x $cc
+cc_dir=`echo $2 | sed -e 's,/*[^/]*$,,'`
+for c in $probe_ccs
+do if $executable $cc_dir/$c
+ then x=$cc_dir/$c
+ else x=$c
+ fi
+ eval $c='$x'
+done
+ld_dir=
+rm -f doti.$obj
+if $cc -c doti.$src
+then eval set x $probe_verbose
+ shift
+ for o
+ do $cc $o doti.$obj
+ $cc $o doti.$obj -lF0oB@r
+ done 2>&1 | sed -e 's/^[+ ]*//' -e 's/[ ].*//' -e '/^\//!d' -e 's/:$//' -e '/ld[a-zA-Z0-9.]*$/!d' -e 's,///*,/,g' > t
+ for i in `cat t`
+ do rm -f t.$obj
+ if test -x $i && $i -r -o t.$obj doti.$obj && test -f t.$obj
+ then case $ld in
+ ld) ld=$i ;;
+ esac
+ ld_dir=`echo $i | sed 's,/[^/]*$,,'`
+ break
+ fi
+ done
+fi
+IFS=:
+set x $PATH
+IFS=$ifs
+path=$*
+m=
+for c in $probe_ccs
+do eval o='$'$c
+ case $o in
+ $c) ;;
+ *) continue ;;
+ esac
+ C='${c}'
+ for x in $cc_dir $ld_dir
+ do cd $x
+ for p in "${C}" "${C}[!a-zA-Z]*" "*[!a-zA-Z]${C}" "*[!a-zA-Z]${C}[!a-zA-Z]*"
+ do eval set x $p
+ case $# in
+ 2) if $executable $2
+ then case $2 in
+ *$c*$c*);;
+ *) m=$p
+ break 3
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ done
+ done
+done
+cd $tmpdir
+for c in $probe_ccs
+do eval o='$'$c
+ case $o in
+ $c) ;;
+ *) continue ;;
+ esac
+ for x in $cc_dir $ld_dir
+ do if $executable $x/$c
+ then eval $c='$x/$c'
+ continue 2
+ fi
+ case $m in
+ ?*) eval set x $x/$m
+ case $# in
+ 2) if $executable $2
+ then eval $c='$2'
+ continue 2
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ done
+ for x in $path
+ do if $executable $x/$c
+ then eval $c='$x/$c'
+ break
+ fi
+ done
+done
+dld=$cc
+
+rm -f dynamic.$exe
+if $cc -o dynamic.$exe dynamic.$obj && $executable dynamic.$exe
+then mkdir mylib
+ echo > mylib/libc.$lib
+ eval set x $probe_ldlib
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f dynamic.$exe
+ if eval $1=./mylib '$'cc -o dynamic.$exe dynamic.$obj
+ then :
+ else libpath=$1
+ break
+ fi
+ done
+fi
+test `$cc -E libpp.$src | grep -c '^#pragma pp:version "libpp '` -eq 1 && libpp=1
+$cc -E doti.$src > doti.i && $cc -c doti.i && test -s doti.$obj && doti=1
+if $cc -c imusr.$src
+then eval set x $probe_include_local
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ if $cc -c $1 imusr.$src
+ then : "$1 should skip \"_i_.h\" in ."
+ elif $cc -c imstd.$src
+ then if $cc -c -Iim imstd.$src
+ then : '-Idir should find <stdio.h> in dir'
+ elif $cc -c $1 -Iim imstd.$src
+ then : "$1 -Idir should find <stdio.h> in dir"
+ elif $cc -c -Iim $1 imstd.$src
+ then include_local=$1
+ break
+ else : "-Idir $1 should skip <stdio.h> in dir"
+ fi
+ else : should find stdio.h
+ fi
+ done
+else : 'should find "_i_.h" in .'
+fi
+
+if $cc -c pic.$src 2>e
+then e=`wc -l e`
+ s=`$size pic.$obj; wc pic.$obj`
+ eval set x $probe_pic
+ shift
+ while :
+ do case $# in
+ 0|1) break ;;
+ esac
+ pic=$1
+ shift
+ PIC=$1
+ shift
+ rm -f pic.$obj
+ $cc $pic -c pic.$src 2>e && test -f pic.$obj || continue
+ $cc $pic -o pic.$exe pic.$obj && test -f pic.$exe || {
+ rm -f pic.$exe
+ $cc -o pic.$exe pic.$obj && test -f pic.$exe && continue
+ }
+ case `wc -l e` in
+ $e) ;;
+ *) continue ;;
+ esac
+ case $pic in
+ ???*) m=`echo " $pic" | sed -e 's/^ [-+]//g' -e 's/./-& /g' -e 's/[-+] //g'`
+ rm -f pic.$obj pic1.$exe
+ if $cc $m -c pic.$src 2>e && test -f pic.$obj &&
+ $cc -o pic1.$exe pic.$obj && test -f pic1.$exe
+ then case `wc -l e` in
+ $e) cc_pic=$m
+ break
+ ;;
+ esac
+ fi
+ cc_pic=$pic
+ break
+ ;;
+ *) case `$size pic.$obj; wc pic.$obj` in
+ $s) ;;
+ *) cc_pic=$pic
+ break
+ ;;
+ esac
+ ;;
+ esac
+ done
+ # this works around gcc 2.95 sun4 -fpic a.out core dump after exit
+ case $hosted:$cc_pic in
+ 1:?*) if ./pic.$exe
+ then # this catches lynxos.ppc gcc that dumps -fpic and not -mshared
+ echo 'static int* f() { static int v; return &v; }
+int main() { f(); return 0; }' > picok.$src
+ $cc $cc_pic -o picok.$exe picok.$src && ./picok.$exe || cc_pic=
+ else cc_pic=
+ fi
+ ;;
+ esac
+ case $cc_pic in
+ ?*) rm -f pic.$obj
+ if $cc $PIC -c pic.$src 2>e && test -f pic.$obj
+ then cc_PIC=$PIC
+ else cc_PIC=$cc_pic
+ fi
+ ;;
+ *) eval set x $probe_dll
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f pic.$obj pic.$exe
+ $cc $1 -c pic.$src 2>e && test -f pic.$obj || continue
+ $cc $1 -o pic.$exe pic.$obj && test -f pic.$exe || {
+ rm -f pic.$exe
+ $cc -o pic.$exe pic.$obj && test -f pic.$exe && continue
+ }
+ case $1 in
+ -Wc,*exportall*)
+ # get specific since sgi gets this far too
+ rm -f pic.$exe pic.x
+ $cc -Wl,dll -o pic.$exe pic.$obj || continue
+ test -f pic.$exe || continue
+ test -f pic.x || continue
+ cc_dll="-D_SHARE_EXT_VARS $1"
+ so=.x
+ sd=.dll
+ dld=$cc
+ shared=-Wl,dll
+ prefix_shared=
+ probe_sd=
+ probe_shared=
+ #unused# lddynamic=-Bdynamic
+ #unused# ldstatic=-Bstatic
+ lib_dll=SYMBOL
+ break
+ ;;
+ esac
+ case `wc -l e` in
+ $e) cc_dll=$1
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+fi
+
+$cc -c plusplus.$src && plusplus=1
+$cc -E -dD dDflag.$src > t
+case `grep '#define[ ][ ]*dDflag[ ][ ]*on' t` in
+?*) dDflag=1 ;;
+esac
+case `grep '#define.*_GNUC_' t` in
+?*) gnu=1 ;;
+esac
+case $plusplus in
+"") $cc -c stdc.$src && stdc=1 ;;
+*) mkdir ptr
+ cd ptr
+ $cc -c ../ptr.$src &
+ NFS_locks_are_botched=$!
+ cd ..
+ if $cc -c require.$src && $cc require.$obj
+ then set x `$cc require.$obj 2>&1`
+ d=
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -l*) d="$d $1" ;;
+ esac
+ done
+ for f in ++
+ do if $cc require.$obj -l$f
+ then set x `$cc require.$obj -l$f 2>&1`
+ r=
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ -l*) case " $d $r " in
+ *" "$1" "*) ;;
+ *) r="$r $1" ;;
+ esac
+ esac
+ done
+ case $r in
+ ?*) require="$require $f"
+ echo '' $r > req.$f
+ ;;
+ esac
+ fi
+ done
+ fi
+ cd ptr
+ for i in *
+ do if test -d $i
+ then repository=$i
+ break
+ fi
+ done
+ cd ..
+ kill -9 $NFS_locks_are_botched
+ rm -rf ptr
+ case $repository in
+ *?) mkdir ptr
+ cd ptr
+ i=PTR
+ case $repository in
+ $i) i=$i$i ;;
+ esac
+ $cc -ptr$i -c ../ptr.$src &
+ NFS_locks_are_botched=$!
+ cd ..
+ sleep 5
+ if test -d ptr/$i/$repository
+ then ptrimplicit=1
+ fi
+ kill -9 $NFS_locks_are_botched
+ rm -rf ptr
+ ;;
+ esac
+ $cc -o implc implc.$src && $executable implc && implicitc=1
+ if $cc -c toucho.$src && test -f toucho.$obj
+ then o=`ls -l toucho.$obj`
+ if $cc -o toucho toucho.$obj && $executable toucho
+ then n=`ls -l touch.$obj`
+ case $n in
+ "$o") ;;
+ *) toucho=1 ;;
+ esac
+ fi
+ fi
+ ;;
+esac
+
+if $cc -c pic.$src
+then eval set x $probe_nmflags
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case `$nm $1 pic.$obj | grep -c '[0123456789][ ][ ]*T[ ][ ]*[_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]'` in
+ 0) ;;
+ *) nmflags=$1
+ break
+ ;;
+ esac
+ done
+ case $# in
+ 0) case `$nm -gh pic.$obj | grep -c '|\.*[TtDdBbC][EeAaSsOo][XxTtSsMm]'` in
+ 0) ;;
+ *) nmflags=-gh
+ nmedit="-e '/\.*[TtDdBbC][EeAaSsOo][XxTtSsMm]/!d' -e 's/[| ].*//'"
+ ;;
+ esac
+ ;;
+ *) nmedit="-e '/[ ]T[ ][ ]*[_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]/!d' -e 's/.*[ ]T[ ][ ]*//'"
+ ;;
+ esac
+fi
+
+if $cc -c doti.$src
+then eval set x $probe_stripflags
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ if $strip $1 doti.$obj
+ then stripflags=$1
+ break
+ fi
+ done
+fi
+
+rm -f export.$obj export.exe
+if $cc -c export.$src
+then lm=
+ if $cc -o export.exe export.$obj -lm 2>e && lm=-lm ||
+ $cc -o export.exe export.$obj 2>e
+ then z=`wc -c < export.exe; $size export.exe 2>/dev/null`
+ eval set x $probe_export_dynamic
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f export.exe
+ if $cc -o export.exe $1 export.$obj $lm 2>f && $executable export.exe
+ then y=`wc -c < export.exe; $size export.exe 2>/dev/null`
+ case $y in
+ $z) ;;
+ *) if cmp -s e f
+ then export_dynamic=$1
+ break
+ fi
+ ;;
+ esac
+ fi
+ done
+ fi
+fi
+rm -f export.$obj export.exe
+
+rm -f strip.exe
+if $cc -o strip.exe strip.$src
+then z=`wc -c < strip.exe`
+ eval set x $probe_ldstrip
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f strip.exe
+ if $cc -o strip.exe $1 strip.$src
+ then case `wc -c < strip.exe` in
+ $z) ;;
+ *) ldstrip=$1
+ break
+ ;;
+ esac
+ fi
+ done
+fi
+
+rm -f strip.exe strip.$obj
+if $cc -c strip.$src && $cc -o strip.exe strip.$obj 2>e
+then eval set x x $probe_ldlazy
+ while :
+ do shift
+ shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f strip.$exe
+ $cc -o strip.$exe $1 strip.$obj $2 2>f && test -f strip.$exe || continue
+ cmp -s e f || continue
+ ldlazy=$1
+ ldnolazy=$2
+ break
+ done
+ eval set x x $probe_ldrecord
+ while :
+ do shift
+ shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f strip.$exe
+ $cc -o strip.$exe $1 strip.$obj $2 2>f && test -f strip.$exe || continue
+ cmp -s e f || continue
+ ldrecord=$1
+ ldnorecord=$2
+ break
+ done
+fi
+
+case $cc_dll:$cc_pic:$so:$dynamic:$static in
+::::|$cc_dll_def::::)
+ : last chance dynamic checks
+ while :
+ do
+ echo '__declspec(dllexport) int fun() { return 0; }' > exp.$src
+ if $cc -c $cc_dll_def exp.$src
+ then rm -f xxx.dll xxx.lib
+ if $cc -shared -Wl,--enable-auto-image-base -Wl,--out-implib=xxx.lib -o xxx.dll exp.$obj &&
+ test -f xxx.lib -a -f xxx.dll
+ then
+ : cygwin
+ cc_dll=$cc_dll_def
+ dll_dir='$(BINDIR)'
+ sd=.dll
+ so=.dll.a
+ ldscript=".def .exp .ign .res"
+ lib_dll=option
+ lib_all=-Wl,-whole-archive
+ lib_undef=-Wl,-no-whole-archive
+ dld=$cc
+ shared='-shared -Wl,--enable-auto-image-base -Wl,--out-implib=$(<:N=*'$so')'
+ prefix_dynamic=cyg
+ prefix_shared=lib
+ break
+ fi
+ fi
+ break
+ done
+ ;;
+*) if $cc -c $cc_dll $cc_pic shared.$src && $cc -c $cc_dll $cc_pic notall.$src
+ then for xx in "$cc" "$ld"
+ do eval set x $probe_shared
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f xxx$dll
+ # UNDENT ...
+
+ if $xx $1 -o xxx$dll shared.$obj 2>e && test -r xxx$dll
+ then if test -s e && egrep -i 'unknown|invalid|option' e > /dev/null
+ then continue
+ fi
+ case `PATH=/bin:/usr/bin:$PATH file xxx$dll` in
+ *lib*|*obj*|*shared*)
+ ;;
+ "") $executable xxx$dll || continue
+ ;;
+ *ELF*|*elf*)
+ $executable xxx$dll || continue
+ case `strings xxx$dll | sed -e 's,.*[ |],,' | sort -u | egrep -i '^([._](dynamic|dynstr|dynsym))$'` in
+ [012]) continue ;;
+ esac
+ ;;
+ *archive*not*stripped*|*data*dynamic*not*stripped*)
+ $executable xxx$dll || continue
+ ;;
+ *) continue
+ ;;
+ esac
+ dld=$xx
+ shared=$1
+ # does -nostartfiles make sense for C?
+ case $plusplus in
+ '') z=`wc -c < xxx$dll`
+ eval set x $probe_shared_nostart
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f xxx$dll
+ if $dld $shared $1 -o xxx$dll shared.$obj 2>e && test -r xxx$dll
+ then case `wc -c < xxx$dll` in
+ $z) ;;
+ *) if test -s e
+ then case `cat e` in
+ *[Ee][Rr][Rr][Oo][Rr]*|*[Ww][Aa][Rr][Nn][Ii][Nn][Gg]*|*[Oo][Pp][Tt][Ii][Oo][Nn]*)
+ continue
+ ;;
+ esac
+ fi
+ case $shared in
+ '') shared=$1 ;;
+ *) shared="$shared $1" ;;
+ esac
+ break
+ ;;
+ esac
+ fi
+ done
+ ;;
+ esac
+ case $cc_dll in
+ "") cc_dll=$cc_dll_def ;;
+ esac
+ eval set x x $probe_sd
+ while :
+ do shift
+ shift
+ case $# in
+ [01]) break ;;
+ esac
+ rm -f xxx xxx$1 xxx$2
+ if $dld $shared -o xxx shared.$obj 2>e
+ then if test -f xxx$1 -a \( -f xxx$2 -o "$cc_dll" = "$cc_dll_def" \)
+ then sd=$1
+ so=$2
+ lddynamic=-Bdynamic
+ ldstatic=-Bstatic
+ break 2
+ elif test -f xxx -a -f xxx$2
+ then sd=$1
+ so=$2
+ break 2
+ else case $so in
+ '') so=$1 ;;
+ esac
+ break
+ fi
+ fi
+ done
+ rm -f libxxx.$lib
+ $ar cr libxxx.$lib shared.$obj
+ ranlib libxxx.$lib
+ eval set x x $probe_lib_all_undef
+ rm -f xxx$dll
+ if $dld $shared -o xxx$dll libxxx.$lib && test -r xxx$dll
+ then if $nm $nmflags xxx$dll | grep ShareD
+ then lib_dll=OPTION
+ set x x
+ fi
+ fi
+ while :
+ do shift
+ shift
+ case $# in
+ 0|1) break ;;
+ esac
+ rm -f xxx$dll
+ if $dld $shared -o xxx$dll $1 libxxx.$lib $2 && test -r xxx$dll
+ then if $nm $nmflags xxx$dll | grep ShareD
+ then lib_dll=option
+ lib_all=$1
+ lib_undef=$2
+ break
+ fi
+ fi
+ case $2 in
+ ?*) if $dld $shared -o xxx$dll $1 libxxx.$lib && test -r xxx$dll
+ then if $nm $nmflags xxx$dll | grep ShareD
+ then lib_dll=option
+ lib_all=$1
+ break
+ fi
+ fi
+ ;;
+ esac
+ done
+ case $lib_dll in
+ OPTION) lib_dll=option
+ ;;
+ option) case $lib_undef in
+ "") rm -f libyyy.$lib
+ $ar cr libyyy.$lib notall.$obj
+ ranlib libyyy.$lib
+ $cc -c prefix.$src
+ eval set x x $probe_lib_all_undef
+ while :
+ do shift
+ shift
+ case $# in
+ 0|1) break ;;
+ esac
+ rm -f xxx$dll
+ if $dld $shared -o xxx$dll prefix.$obj $lib_all libxxx.$lib $2 libyyy.$lib && test -r xxx$dll
+ then rm -f t
+ $nm $nmflags xxx$dll > t
+ case `grep -c ShareD t`:`grep -c NotalL t` in
+ 0:*) ;;
+ *:0) lib_undef=$2
+ break
+ ;;
+ esac
+ fi
+ done
+ ;;
+ esac
+ case $lib_undef in
+ "") eval set x $probe_lib_multiple
+ rm -f libyyy.$lib
+ cp libxxx.$lib libyyy.$lib
+ rm -f xxx$dll
+ if $dld $shared -o xxx$dll prefix.$obj $lib_all libxxx.$lib libyyy.$lib && test -r xxx$dll
+ then :
+ else while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f xxx$dll
+ if $dld $shared -o xxx$dll prefix.$obj $lib_all $1 libxxx.$lib libyyy.$lib && test -r xxx$dll
+ then rm -f t
+ $nm $nmflags xxx$dll > t
+ case `grep -c ShareD t` in
+ 0) ;;
+ *) lib_all="$lib_all $1"
+ break
+ ;;
+ esac
+ fi
+ done
+ fi
+ lib_dll=symbol
+ ;;
+ esac
+ ;;
+ *) lib_dll=symbol
+ ;;
+ esac
+ case `cat e` in
+ ?*) eval set x $probe_unresolved
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f xxx$dll
+ if eval '$dld $shared' $1 '-o xxx$dll shared.$obj 2>e && test -r xxx$dll'
+ then case `cat e` in
+ "") shared="$shared $1"; break ;;
+ esac
+ fi
+ done
+ ;;
+ esac
+ r=
+ eval set x $probe_shared_registry
+ while :
+ do shift
+ r=x$r
+ case $# in
+ 0) break ;;
+ esac
+ rm -f xxx$dll
+ if eval \$dld \$shared -o xxx\$dll $1 shared.\$obj &&
+ test -r xxx$dll -a -r $probe_shared_registry_file
+ then probe_shared_registry_file='$(CC.SHARED.REGISTRY.PATH)'
+ eval set x $probe_shared_registry
+ i=
+ while :
+ do shift
+ i=x$i
+ case $i in
+ $r) break ;;
+ esac
+ done
+ shared_registry=$1
+ fi
+ done
+ break 2
+ fi
+
+ # ... INDENT
+ done
+ done
+ fi
+ case $so in
+ ?*) rm -f xxx*
+ if $dld $shared -g -o xxx shared.$obj 2>e
+ then set x $probe_sdb
+ while :
+ do shift
+ case $1 in
+ 0) break ;;
+ esac
+ if test -f xxx$1
+ then sdb=$1
+ break
+ fi
+ done
+ fi
+ if $cc -c require.$src
+ then p='
+/usr/proberun/lib:/local/runprobe/lib
+'
+ eval set x $probe_ldrunpath
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f require.exe
+ if $cc -o require.exe $1"$p" require.$obj &&
+ grep -c /proberun/ require.exe >/dev/null &&
+ grep -c /runprobe/ require.exe > /dev/null
+ then ldrunpath=$1
+ eval set x $probe_ldorigin
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f origin.exe
+ if $cc -o origin.exe $1 $ldrunpath'$ORIGIN' require.$obj
+ then if ./origin.exe > /dev/null 2>&1
+ then ldorigin="$1 $ldrunpath"'\$ORIGIN/$(BINDIR:P=R=$(DLLDIR))'
+ fi
+ break
+ fi
+ done
+ break
+ fi
+ done
+ fi
+ rm -f libxxx$so
+ if $cc -c sovmain.$src &&
+ $cc -c $cc_dll $cc_pic sovlib.c &&
+ $dld $shared -o libxxx$so sovlib.$obj &&
+ $cc -o sovmain.$exe -L. sovmain.$obj -lxxx
+ then rm -f sovmain.$exe
+ mv libxxx$so libxxx$so.5.6
+ if $cc -o sovmain.$exe -L. sovmain.$obj -lxxx
+ then soversion=1
+ fi
+ fi
+ rm -f doti.$obj
+ std64=/lib64
+ lcl64=/usr/local/lib64
+ if test -d $std64 -a -d $lcl64 && $cc -c doti.$src
+ then for i in `cd $lcl64; ls *$so 2>/dev/null | sed 's/lib\([^.]*\).*/\1/'`
+ do if $cc -o runpath.$exe doti.$obj -l$i >/dev/null 2>&1
+ then LD_LIBRARY_PATH= ./runpath.$exe >/dev/null 2>&1 && continue
+ if LD_LIBRARY_PATH=$lcl64 ./runpath.$exe >/dev/null 2>&1
+ then runpath=$lcl64
+ break
+ elif LD_LIBRARY_PATH=$std64 ./runpath.$exe >/dev/null 2>&1
+ then runpath=$std64
+ break
+ elif LD_LIBRARY_PATH=$lcl64:$std64 ./runpath.$exe >/dev/null 2>&1
+ then runpath=$lcl64:$std64
+ break
+ fi
+ fi
+ done
+ fi
+ ;;
+ esac
+ ;;
+esac
+
+rm -f shared.$obj
+if $cc -c shared.$src
+then eval set x $probe_ar_arflags
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f libxxx.$lib
+ if $ar $1 r libxxx.$lib shared.$obj && $ar $1 t libxxx.$lib 2>&1 | grep shared.$obj >/dev/null
+ then ar_arflags=$1
+ break
+ fi
+ done
+ eval set x $probe_arflags
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f libxxx.$lib
+ if $cc $1 -o libxxx.$lib shared.$obj && $ar t libxxx.$lib 2>&1 | grep shared.$obj >/dev/null
+ then arflags=$1
+ break
+ fi
+ done
+fi
+
+case $shared in
+-G) case $cc_dll in
+ "") cc_dll=$cc_dll_def ;;
+ esac
+ ;;
+*) case $lib_dll in
+ symbol) echo 'extern int f();
+ int main() { f(); return 0; }' > main.$src
+ echo '#include <stdio.h>
+ int f() { printf("hello world"); return 0; }' > member.$src
+ if $cc -c main.$src && $cc -c member.$src
+ then echo f > lib.exp
+ rm -f lib.$obj main.exe
+ if $ld -o lib.$obj -L: -bexport:lib.exp -berok -bmodtype:SRE -T512 -H512 -lm -lc member.$obj && $cc -o main.exe main.$obj lib.$obj
+ then dld=$ld
+ shared='-T512 -H512 -L$(LIBDIR): -berok -bmodtype:SRE'
+ lib_dll=export
+ dll_libraries='-lm -lc'
+ ldscript=.exp
+ case $cc_dll in
+ "") cc_dll=$cc_dll_def ;;
+ esac
+ case $so in
+ "") so=.$obj ;;
+ esac
+ fi
+ fi
+ ;;
+ esac
+ ;;
+esac
+case $shared in
+?*) if $cc -c $cc_dll $cc_pic shared.$src
+ then eval set x $probe_shared_name
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f xxx$dll
+ if $dld $shared ${1}libfoo.1.2 -o xxx$dll shared.$obj 2>e && test -r xxx$dll
+ then shared_name=$1
+ break
+ fi
+ done
+ fi
+ ;;
+esac
+case " $cc_dll " in
+*" $cc_dll_def "*)
+ ;;
+" ") ;;
+*) cc_dll="$cc_dll_def $cc_dll"
+ ;;
+esac
+
+case $hosttype in
+win32.*|cygwin.*|os2.*)
+ Lflag=1
+ ;;
+*) if $cc -c doti.$src
+ then if $cc -L. doti.$obj -lc >/dev/null
+ then case $cc_dll in
+ '') ;;
+ *) Lflag=1 ;;
+ esac
+ fi
+ fi
+ ;;
+esac
+
+case $lib_dll in
+option) case $hosttype in
+ linux.*) dll_libraries=-lc ;;
+ esac
+ ;;
+SYMBOL) lib_dll=symbol
+ ;;
+symbol) echo "#include <stdio.h>
+extern int fun()
+{
+ puts(\"fun\");
+ return 0;
+}" > dllib.$src
+ echo "extern int fun();
+int
+main()
+{
+ return fun();
+}" > dlmain.$src
+ pwd=`pwd`
+ while :
+ do
+ if $cc -c $cc_dll $cc_pic dlmain.$src &&
+ $cc -c $cc_dll $cc_pic dllib.$src
+ then rm -f libxxx$so
+ if $dld $shared -o libxxx$so dllib.$obj &&
+ chmod 555 libxxx$so
+ then rm -f dlmain.$exe
+ if $cc -o dlmain.$exe dlmain.$obj $pwd/libxxx$so &&
+ (./dlmain.$exe) >/dev/null 2>&1
+ then break
+ fi
+ fi
+ rm -f libxxx$so dlmain.$exe
+ if $dld $shared -o libxxx$so dllib.$obj -lm -lc &&
+ chmod 555 libxxx$so &&
+ $cc -o dlmain.$exe dlmain.$obj $pwd/libxxx$so &&
+ (./dlmain.$exe) >/dev/null 2>&1
+ then dll_libraries='-lm -lc'
+ fi
+ fi
+ break
+ done
+ # the dll_libraries probe is still lame
+ case $dll_libraries in
+ '') case $hosttype in
+ sco.*|sol*.*|sun*) ;;
+ *) dll_libraries='-lm -lc' ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+
+stdlib=
+a=`$cc -print-multi-directory 2>/dev/null`
+case $a in
+.) ;;
+*) for d in `$cc -print-search-dirs 2>/dev/null | sed -e '/^libraries:/!d' -e 's/.*=//' | tr : '\n' | grep /lib/`
+ do if [ -d ${d}${a} ]
+ then stdlib="$stdlib ${d}${a}"
+ else case $d in
+ */lib/) d=`echo '' $d | sed -e 's,/$,,'`
+ if [ -d ${d}${a} ]
+ then stdlib="$stdlib ${d}${a}"
+ fi
+ ;;
+ esac
+ fi
+ done
+ ;;
+esac
+case $stdlib in
+'') stdlib=`$cc -v doti.$src 2>&1 |
+ sed 's/ */\n/g' |
+ sed -e '/^-L/!d' -e 's/^-L//' |
+ while read dir
+ do if test -d "$dir"
+ then (cd "$dir"; pwd)
+ fi
+ done`
+ ;;
+*) eval set x $probe_verbose
+ shift
+ for o in "$@"
+ do stdlib="$stdlib "`$cc $o doti.$src 2>&1 |
+ sed 's/ */\n/g' |
+ sed -e '/^-L/!d' -e '/\/lib64$/!d' -e 's/^-L//'`
+ done
+ ;;
+esac
+case $stdlib in
+?*) keepstdlib=1
+ o=$stdlib
+ stdlib=
+ for dir in $o
+ do case " $stdlib " in
+ *" $o "*) continue ;;
+ esac
+ case $dir in
+ /usr/lib64)
+ i=/usr/local/lib64
+ a=/lib64
+ ;;
+ /lib64) i=/usr/local/lib64
+ a=/usr/lib64
+ ;;
+ /usr/lib)
+ i=/usr/local/lib
+ a=/lib
+ ;;
+ lib) i=/usr/local/lib
+ a=/usr/lib
+ ;;
+ *) i=
+ a=
+ ;;
+ esac
+ if test "" != "$i" -a -d "$i"
+ then case " $o " in
+ *" $i "*)
+ ;;
+ *) stdlib="$stdlib $i"
+ ;;
+ esac
+ fi
+ stdlib="$stdlib $dir"
+ if test "" != "$a" -a -d "$a"
+ then case " $o " in
+ *" $a "*)
+ ;;
+ *) stdlib="$stdlib $a"
+ ;;
+ esac
+ fi
+ done
+ case $hosted in
+ 1) case " $stdlib " in
+ *" /usr/lib "*)
+ ;;
+ *) case " $stdlib " in
+ *" /usr/local/lib "*)
+ ;;
+ *) stdlib="$stdlib /usr/local/lib"
+ ;;
+ esac
+ stdlib="$stdlib /usr/lib"
+ ;;
+ esac
+ case " $stdlib " in
+ *" /lib "*)
+ ;;
+ *) stdlib="$stdlib /lib"
+ ;;
+ esac
+ esac
+ ;;
+*) keepstdlib=0
+ case $dir in
+ */arch/$hosttype/lib/*)
+ notlib=`echo $dir | sed "s,/arch/$hosttype/lib/.*,/arch/$hosttype/lib,"`
+ ;;
+ *) notlib=////
+ ;;
+ esac
+ tstlib=
+ implib=
+ if $cc -c hosted.$src
+ then for f in `(
+ eval set x $probe_verbose
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ $cc $1 hosted.$obj
+ done
+ ) 2>&1 | sed -e 's/[ :]/\\
+ /g' -e 's/-L//g' -e 's/^P,//' -e "s/[\"']//g" -e 's,^[\\\\/]*[\\\\/],/,' | sed -e '/^\$/d' -e '/^[-+]/d' -e '/^[^\\\\\\/]/d' -e '/[\\\\\\/]tmp[\\\\\\/]/d' -e 's/:\$//' -e 's,//*$,,'`
+ do case " $tstlib $implib " in
+ *" $f "*) continue ;;
+ esac
+ case $f in
+ $notlib) continue ;;
+ esac
+ if test -d $f
+ then tstlib="$tstlib $f"
+ elif test -f $f
+ then d=`echo $f | sed -e 's,[\\\\/]*[^\\\\/]*\$,,'`
+ case " $tstlib $implib " in
+ *" $d "*) continue ;;
+ esac
+ case $d in
+ *[\\/]usr[\\/]lib)
+ x=$d
+ d="`echo $d | sed -e 's,[\\\\/][\\\\/]*usr[\\\\/]lib\$,/lib,'`"
+ case " $tstlib $implib " in
+ *" $d "*) ;;
+ *) implib="$implib $d" ;;
+ esac
+ implib="$implib $x"
+ ;;
+ *[\\/]lib)
+ implib="$implib $d"
+ d="`echo $d | sed -e 's,[\\\\/][\\\\/]*lib\$,/usr/lib,'`"
+ case " $tstlib $implib " in
+ *" $d "*) ;;
+ *) implib="$implib $d" ;;
+ esac
+ ;;
+ *) implib="$implib $d"
+ ;;
+ esac
+ fi
+ done
+ fi
+ tstlib="$tstlib $implib"
+ if $cc -Dtype=void -Dcall=exit -c tstlib.$src && mv tstlib.$obj tst.$obj
+ then case $plusplus in
+ '') probe_lxx= ;;
+ esac
+ l=
+ for sym in $probe_l $probe_lxx
+ do case $l in
+ "") l=$sym; continue ;;
+ esac
+ rm -f tstlib.$exe
+ if $cc -o tstlib.$exe tst.$obj -l$l
+ then eval set x $probe_ldmap
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ d=`$cc -Dtype=int -Dcall=$sym $static $1 tstlib.$src -l$l 2>&1 | sed -e '/[\\\\\\/].*[\\\\\\/]lib[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+]*\.[^\\\\\\/]*\$/!d' -e 's,^[^\\\\\/]*,,' -e 's,[\\\\\\/]lib[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+]*\.[^\\\\\\/]*\$,,' -e '/^[\\\\\\/]/!d' | sort -u`
+ case $d in
+ ?*) tstlib="$tstlib $d" ;;
+ esac
+ done
+ fi
+ l=
+ done
+ fi
+ libstd=
+ libset=
+ stdlibroot="/ /usr/"
+ for d in $tstlib
+ do case $d in
+ [\\/]lib|[\\/]usr[\\/]lib)
+ ;;
+ *) case " $stdlib " in
+ *\ $d\ *)
+ ;;
+ *) if ls $d ${PREROOT+$PREROOT/../$d} > tmp.tmp && test -s tmp.tmp
+ then for i in $probe_lib $obj
+ do if grep -i "\\.$i\$" tmp.tmp >/dev/null
+ then case " $probe_lib_append " in
+ *\ $d\ *)
+ libstd="$libstd $d"
+ ;;
+ *) stdlib="$stdlib $d"
+ case $d in
+ /usr/lib|/usr/lib/*)
+ ;;
+ /usr/lib?*)
+ e=`echo $d | sed -e 's,/usr,,'`
+ g=`echo $d/libc.* $e/libc.*`
+ case "$e $g " in
+ *".* "*);;
+ *) stdlib="$stdlib $e"
+ stdlibroot=
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $libset in
+ "") case $i in
+ $obj) ;;
+ *) libset=1
+ lib=$i
+ ;;
+ esac
+ ;;
+ esac
+ break
+ fi
+ done
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ done
+ for d in `$ld --verbose 2>&1 | sed -e '/SEARCH_DIR/!d' -e 's/[ ][ ][ ]*/ /g' -e 's/SEARCH_DIR(\([^ ]*\));/\1/g' -e 's, //[^ ]*,,' -e 's,",,g'`
+ do if test -d $d
+ then case " $stdlib $libstd " in
+ *\ ${d}\ *)
+ ;;
+ *) libstd="$libstd $d"
+ ;;
+ esac
+ fi
+ done
+ case $hosted in
+ "") tstlib= ;;
+ *) tstlib="$stdlibroot /usr/ccs/ /usr/local/" ;;
+ esac
+ case $stdlibroot in
+ ?*) d=
+ for f in $stdinclude
+ do f=`echo $f | sed -e 's,[^\\\\/]*\$,,'`
+ d="$d $f"
+ done
+ tstlib="$d $tstlib"
+ ;;
+ esac
+ $cc -c doti.$src > all.tmp
+ for f in $probe_libdir
+ do for d in $stdlib $libstd $tstlib
+ do if test -d ${d}${f}
+ then ls ${d}${f} ${PREROOT:+$PREROOT/../${d}${f}} |
+ while read i
+ do for j in ${d}${f}/${i} ${PREROOT:+$PREROOT/../${d}${f}/${i}}
+ do if test -f $j -a -r $j -a -s $j
+ then echo $i
+ break
+ fi
+ done
+ done > tmp.tmp
+ if test -s tmp.tmp
+ then if egrep -i "^${prefix_archive}[abcdefghijklmnopqrstuvwxyz0123456789_][abcdefghijklmnopqrstuvwxyz0123456789_]*\\.$lib\$" tmp.tmp >lib.tmp ||
+ egrep -i "\\.$obj\$" tmp.tmp >/dev/null ||
+ egrep -i "^${prefix_shared}[abcdefghijklmnopqrstuvwxyz0123456789_][abcdefghijklmnopqrstuvwxyz0123456789_]*\\$so(.[0-9]+)*\$" tmp.tmp >>lib.tmp
+ then if test -s lib.tmp
+ then sed -e "s,.*/,," -e 's,^'${prefix_archive}'\(.*\)\.'$lib'$,\1,g' -e 's,^'${prefix_shared}'\(.*\)\'$so'[.0-9]*,\1,g' lib.tmp | sort -u > tmp.tmp
+ xs=`sort all.tmp all.tmp tmp.tmp | uniq -u`
+ case $xs in
+ '') continue ;;
+ esac
+ ok=0
+ for x in $xs
+ do case $x in
+ *_p) continue ;; # linux gcc known to hang for -lc_p
+ esac
+ if $cc -o doti.$exe doti.$obj -l$x 2>e
+ then ok=1
+ else if test -s e && egrep -i ":.*[ ](find|found|locate|search|-l$x)[ ]" e > /dev/null
+ then if egrep -i ":.*[ ](access|permission)[ ]" e
+ then : maybe
+ else ok=0
+ break
+ fi
+ fi
+ case $Lflag in
+ 1) if $cc -L${d}${f} -o doti.$exe doti.$obj -l$x
+ then ok=0
+ break
+ fi
+ ;;
+ esac
+ fi
+ done
+ case $ok in
+ 0) continue ;;
+ esac
+ sort -u all.tmp tmp.tmp > lib.tmp
+ mv lib.tmp all.tmp
+ fi
+ case " $stdlib $libstd " in
+ *" ${d}${f} "*)
+ ;;
+ *) if test -d ${d}${f}/fsoft
+ then stdlib="$stdlib ${d}${f}/"'$(FLOAT_OPTION)'
+ fi
+ stdlib="$stdlib ${d}${f}"
+ ;;
+ esac
+ fi
+ fi
+ fi
+ done
+ done
+ stdlib="$stdlib $libstd"
+ case $stdlib in
+ */shlib*)
+ dy=
+ st=
+ for i in $stdlib $libstd
+ do case $i in
+ */shlib) dy="$dy $i" ;;
+ *) st="$st $i" ;;
+ esac
+ done
+ for i in /var
+ do if test -d $i/shlib
+ then dy="$dy $i/shlib"
+ fi
+ done
+ stdlib="$dy $st"
+ ;;
+ esac
+ ;;
+esac
+
+if $cc -c prefix.$src
+then eval set x $probe_symprefix
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ if $nm $nmflags prefix.$obj | grep -c ${1}prefix >/dev/null
+ then symprefix=$1
+ break
+ fi
+ done
+fi
+
+if $cc -c warn.$src 2>e && test -f warn.$obj
+then e=`wc -c < e`
+
+ eval set x $probe_debug
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f warn.$obj
+ $cc $1 -c warn.$src 2>e && test -f warn.$obj || continue
+ case `wc -c < e` in
+ $e) debug=$1; break ;;
+ esac
+ done
+
+ eval set x $probe_no_protect
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f warn.$obj
+ $cc $1 -c warn.$src 2>e && test -f warn.$obj || continue
+ case `wc -c < e` in
+ $e) no_protect=$1; break ;;
+ esac
+ done
+
+ case $version_string in
+ $probe_gcc_version) probe_optimize="$probe_gcc_optimize $probe_optimize" ;;
+ esac
+ eval set x $probe_optimize
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f warn.$obj
+ $cc $1 -c warn.$src 2>e && test -f warn.$obj || continue
+ case `wc -c < e` in
+ $e) optimize=$1; break ;;
+ esac
+ done
+
+ eval set x $probe_strict
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f warn.$obj
+ $cc $1 -c warn.$src 2>e && test -f warn.$obj || continue
+ n=`wc -c < e`
+ if test $n -ge $e
+ then strict=$1
+ break
+ fi
+ done
+
+ $cc -c warn1.$src 2>e
+ o=`wc -c < e`
+ eval set x $probe_warn
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ rm -f warn.$obj warn.$exe
+ $cc -o warn.$exe $1 warn.$src 2>e && test -f warn.$exe || continue
+ n=`wc -c < e`
+ for i in $warn_enum
+ do rm -f warn$i.$obj
+ $cc -c $1 warn$i.$src 2>e && test -f warn$i.$obj || continue
+ n=`wc -c < e`
+ if test $n -gt $o
+ then warn=$1
+ break 2
+ fi
+ done
+ done
+
+fi
+
+while :
+do case $hosted in
+ 1) rm -f readonly.$exe
+ eval set x '""' $probe_readonly
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ for co in '' -Dtest_const
+ do rm -f readonly.$exe
+ if $cc -o readonly.$exe $co $1 readonly.$src && $executable readonly.$exe
+ then if ./readonly.$exe >/dev/null 2>&1
+ then :
+ else readonly=$1
+ break 3
+ fi
+ fi
+ done
+ done
+ rm -f readonly.$exe readonly.s
+ if $cc -S readonly.$src && test -f readonly.s
+ then if sed -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)data/\1text/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)zero[ ][ ]*/\1set .,.+/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*1/\1byte 0/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*2/\1byte 0,0/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*3/\1byte 0,0,0/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*4/\1byte 0,0,0,0/' \
+ readonly.s > ro.s && $cc -o readonly.$exe ro.s && $executable readonly.$exe
+ then if ./readonly.$exe >/dev/null 2>&1
+ then :
+ else readonly='-S.data'
+ break
+ fi
+ fi
+ rm -f readonly.$exe
+ if sed -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)idat/\1code/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)zero[ ][ ]*/\1set .,.+/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*1/\1byte 0/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*2/\1byte 0,0/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*3/\1byte 0,0,0/' \
+ -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)space[ ][ ]*4/\1byte 0,0,0,0/' \
+ readonly.s > ro.s && $cc -o readonly.$exe ro.s && $executable readonly.$exe
+ then if ./readonly.$exe >/dev/null 2>&1
+ then :
+ else readonly='-S.idat'
+ break
+ fi
+ fi
+ if sed -e 's/^\([ ]*[.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$:]*[ ]*\.*\)data/\1rdata/' \
+ readonly.s > ro.s && $cc -o readonly.$exe ro.s && $executable readonly.$exe
+ then if ./readonly.$exe >/dev/null 2>&1
+ then :
+ else readonly='-S.rdata'
+ break
+ fi
+ fi
+ fi
+ ;;
+ esac
+ break
+done
+
+case $stdc in
+?*) dialect="$dialect ANSI" ;;
+esac
+case $plusplus in
+?*) dialect="$dialect C++" ;;
+esac
+case $hosted in
+"") dialect="$dialect CROSS" ;;
+esac
+case $doti in
+?*) dialect="$dialect DOTI" ;;
+esac
+case $gnu in
+?*) dialect="$dialect GNU" ;;
+esac
+case $so:$dynamic:$static in
+::) ;;
+*) dialect="$dialect DYNAMIC"
+ case $soversion in
+ ?*) dialect="$dialect VERSION" ;;
+ esac
+ ;;
+esac
+case $implicitc in
+?*) dialect="$dialect IMPLICITC" ;;
+esac
+case $ptrcopy in
+?*) dialect="$dialect PTRCOPY" ;;
+esac
+case $ptrimplicit in
+?*) dialect="$dialect PTRIMPLICIT" ;;
+esac
+case $ptrmkdir in
+?*) dialect="$dialect PTRMKDIR" ;;
+esac
+case $libpp in
+?*) dialect="$dialect LIBPP" ;;
+esac
+case $toucho in
+?*) dialect="$dialect TOUCHO" ;;
+esac
+case $dDflag in
+?*) dialect="$dialect -dD" ;;
+esac
+# 2005-05-25 use $(CC.INCLUDE.LOCAL) instead
+case $include_local in
+?*) dialect="$dialect -I-" ;;
+esac
+case $Lflag in
+?*) dialect="$dialect -L" ;;
+esac
+
+ppcmd='$(CPP)'
+ppdir='$(CPP:D)'
+eval ppopt='"'$ppopt'"'
+eval ppenv='"'$ppenv'"'
+
+set x "" .$exe
+shift
+exe=
+for i
+do rm -f require$i
+done
+if $cc -o require require.$src
+then for i
+ do if $executable require$i
+ then exe=$i
+ break
+ fi
+ done
+fi
+case $sa:$sd:$so in
+::?*) eval set x $probe_sa
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ for i in $stdlib
+ do eval j="'" $i/lib*$1 "'"
+ case $j in
+ " $i/lib*$1 ")
+ eval j="'" $i/lib*$1.[0123456789]* "'"
+ case $j in
+ " $i/lib*$1.[0123456789]* ")
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ sa=$1
+ lddynamic=-Bdynamic
+ ldstatic=-Bstatic
+ break 2
+ done
+ done
+ ;;
+esac
+case $ldscript in
+"") case $so in
+ .lib) ldscript=".def .exp" ;;
+ *) ldscript=".ld" ;;
+ esac
+ ;;
+esac
+case $hosttype in
+'') hosttype=unknown ;;
+sgi.mips3) dll_variants='sgi.mips2:o32:-mips2 sgi.mips4:64:-mips4' ;;
+sgi.mips4) dll_variants='sgi.mips2:o32:-mips2 sgi.mips3:n32:-mips3' ;;
+esac
+
+case $hosted in
+"") ccnative=`echo $cc | sed -e 's,.*/,,'`
+ ccs=$ccnative
+ for c in cc gcc
+ do case " $ccs " in
+ *" $c "*) ;;
+ *) ccs="$ccs $c" ;;
+ esac
+ done
+ for p in $path
+ do for c in $ccs
+ do if $executable $p/$c
+ then rm -f native.$exe
+ if $p/$c -o native.$exe doti.$src && ./native.$exe
+ then ccnative=$p/$c
+ exectype=`package CC="$ccnative" || $SHELL -c "package CC='$ccnative'"`
+ case $exectype in
+ *[Uu][Ss][Aa][Gg][Ee]:*)
+ exectype=`PATH=$_probe_PATH; export PATH; package CC="$ccnative" || $SHELL -c "package CC='$ccnative'"`
+ ;;
+ esac
+ break 2
+ fi
+ fi
+ done
+ done
+ ;;
+*) ccnative=$cc
+ exectype=$hosttype
+ ;;
+esac
+
+# runtime shared lib exported symbol resolution
+
+case $cc_dll:$shared in
+:|:*|*:);;
+*) cat > cmd.c <<'!'
+#include <stdio.h>
+#include <dlfcn.h>
+typedef int (*Lib_f)(int**, int**, int**);
+int gbl_def = 1;
+int gbl_ref = 1;
+int gbl_ext;
+int main(int argc, char** argv)
+{
+ void* dll;
+ Lib_f lib;
+ int* def;
+ int* ref;
+ int* ext;
+
+ if (!(dll = dlopen(*++argv, RTLD_LAZY)))
+ fprintf(stderr, "library not found\n");
+ else if (!((lib = (Lib_f)dlsym(dll, "lib"))) && !(lib = (Lib_f)dlsym(dll, "_lib")))
+ fprintf(stderr, "symbol not found\n");
+ else if ((*lib)(&def, &ref, &ext))
+ fprintf(stderr, "function failed\n");
+ else if (def == &gbl_def && ref == &gbl_ref && ext == &gbl_ext)
+ printf("ALL\n");
+ else if (ref == &gbl_ref && ext == &gbl_ext)
+ printf("REF\n");
+ else if (ext == &gbl_ext)
+ printf("EXT\n");
+ return 0;
+}
+!
+ cat > lib.c <<'!'
+int gbl_def = 1;
+int gbl_ref;
+int gbl_ext;
+int lib(int** def, int** ref, int** ext)
+{
+ *def = &gbl_def;
+ *ref = &gbl_ref;
+ *ext = &gbl_ext;
+ return 0;
+}
+!
+ if $cc -c $cc_dll $cc_pic cmd.c &&
+ $cc -c $cc_dll $cc_pic lib.c && {
+ $cc $cc_dll $export_dynamic -o cmd.exe cmd.o ||
+ $cc $cc_dll $export_dynamic -o cmd.exe cmd.o -ldl
+ } &&
+ $dld $shared -o libgbl.dll lib.o
+ then x=`./cmd.exe ./libgbl.dll`
+ case $x in
+ ?*) dialect="$dialect EXPORT=$x" ;;
+ esac
+ else case $sd:$hosttype in
+ .dll:*win*) dialect="$dialect EXPORT=DLL" ;;
+ esac
+ fi
+ ;;
+esac
+
+# shellmagic defined if installed shell scripts need magic
+
+echo ': got magic :
+echo ok' > ok
+chmod +x ok
+case `(eval ./ok | /bin/sh) 2>/dev/null` in
+ok) ;;
+*) echo '#!/bin/env sh
+: got magic :
+echo ok' > ok
+ chmod +x ok
+ case `(eval ./ok | /bin/sh) 2>/dev/null` in
+ ok) shellmagic='$("#")!/bin/env sh'
+ ;;
+ *) for i in /emx/bin/bash.exe /emx/bin/sh.exe
+ do if test -x $i
+ then shellmagic='$("#")!'$i
+ break
+ fi
+ done
+ ;;
+ esac
+ ;;
+esac
+
+#
+# path cleanup
+#
+
+for i in ar ccnative dld ld nm size stdinclude stdlib strip
+do eval o='$'$i
+ v=$o
+ case $v in
+ *//*) v=`echo $v | sed 's,///*,/,g'` ;;
+ esac
+ if (test . -ef "`pwd`")
+ then k=
+ for x in $v
+ do case $x in
+ */../*|*/..)
+ case $x in
+ /*) a=/ ;;
+ *) a= ;;
+ esac
+ IFS=/
+ set '' $x
+ IFS=$ifs
+ r=
+ for d
+ do r="$d $r"
+ done
+ p=
+ g=
+ for d in $r
+ do case $d in
+ ..) g="$g $d" ;;
+ *) case $g in
+ '') case $p in
+ '') p=$d ;;
+ *) p=$d/$p ;;
+ esac
+ ;;
+ *) set $g
+ shift
+ g=$*
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $a in
+ '') for d in $g
+ do p=$d/$p
+ done
+ ;;
+ *) p=$a$p
+ ;;
+ esac
+ case $p in
+ /) continue ;;
+ esac
+ test $x -ef $p && x=$p
+ ;;
+ esac
+ k="$k $x"
+ done
+ set '' $k
+ shift
+ v=$1
+ case $# in
+ 0) ;;
+ *) shift
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ k=
+ for d
+ do for j in $v
+ do test $d -ef $j && continue 2
+ done
+ k="$k $d"
+ done
+ set '' $k
+ case $# in
+ 1) break ;;
+ esac
+ shift
+ v="$v $1"
+ shift
+ done
+ ;;
+ esac
+ fi
+ case $v in
+ $o) ;;
+ *) eval $i='$'v ;;
+ esac
+done
+
+case $keepstdlib in
+1) ;;
+*) #
+ # favor lib64 over lib
+ #
+ case $hosttype in
+ *64|*[!0-9]64[!a-zA-Z0-9]*)
+ o=$stdlib
+ stdlib=
+ for i in $o
+ do case " $stdlib " in
+ *" $i "*)
+ continue
+ ;;
+ esac
+ case $i in
+ *64) stdlib="$stdlib $i"
+ continue
+ ;;
+ esac
+ case " $o " in
+ *" ${i}64 "*)
+ case " $stdlib " in
+ *" ${i}64 "*)
+ ;;
+ *) stdlib="$stdlib ${i}64"
+ ;;
+ esac
+ ;;
+ esac
+ stdlib="$stdlib $i"
+ done
+ ;;
+ esac
+ ;;
+esac
+
+#
+# set up for local override
+#
+
+CC_VERSION_STAMP=$version_stamp
+CC_VERSION_STRING=$version_string
+CC_CC=$cc
+CC_NATIVE=$ccnative
+CC_EXECTYPE=$exectype
+CC_HOSTTYPE=$hosttype
+CC_ALTPP_FLAGS=$ppopt
+CC_ALTPP_ENV=$ppenv
+CC_AR=$ar
+CC_AR_ARFLAGS=$ar_arflags
+CC_ARFLAGS=$arflags
+CC_DEBUG=$debug
+CC_DIALECT=$dialect
+CC_PICBIG=$cc_PIC
+CC_PICSMALL=$cc_pic
+CC_PIC=$CC_PICBIG
+CC_DLL_ONLY=$cc_dll
+case $CC_DLL_ONLY in
+'') CC_DLLBIG=
+ CC_DLLSMALL=
+ CC_DLL=
+ ;;
+*) CC_DLLBIG="$CC_DLL_ONLY $CC_PICBIG"
+ CC_DLLSMALL="$CC_DLL_ONLY $CC_PICSMALL"
+ CC_DLL="$CC_DLL_ONLY $CC_PICBIG"
+ ;;
+esac
+CC_DLL_DIR=$dll_dir
+CC_DLL_LIBRARIES=$dll_libraries
+CC_DLL_VARIANTS=$dll_variants
+CC_DYNAMIC=$dynamic
+CC_EXPORT_DYNAMIC=$export_dynamic
+CC_INCLUDE_LOCAL=$include_local
+CC_LD=$ld
+CC_LD_DYNAMIC=$lddynamic
+CC_LD_LAZY=$ldlazy
+CC_LD_NOLAZY=$ldnolazy
+CC_LD_ORIGIN=$ldorigin
+CC_LD_RECORD=$ldrecord
+CC_LD_NORECORD=$ldnorecord
+CC_LD_RUNPATH=$ldrunpath
+CC_LD_STATIC=$ldstatic
+CC_LD_STRIP=$ldstrip
+CC_LIB_DLL=$lib_dll
+CC_LIB_ALL=$lib_all
+CC_LIB_UNDEF=$lib_undef
+CC_MAKE_OPTIONS=$makeoptions
+CC_NM=$nm
+CC_NMEDIT=$nmedit
+CC_NMFLAGS=$nmflags
+CC_NOPROTECT=$no_protect
+CC_OPTIMIZE=$optimize
+CC_READONLY=$readonly
+CC_REPOSITORY=$repository
+CC_REQUIRE=$require
+CC_RUNPATH=$runpath
+CC_SHARED=$shared
+CC_SHARED_LD=$dld
+CC_SHARED_NAME=$shared_name
+CC_SHARED_REGISTRY=$shared_registry
+CC_SHARED_REGISTRY_PATH=$probe_shared_registry_path
+CC_SHELLMAGIC=$shellmagic
+CC_SIZE=$size
+CC_STATIC=$static
+CC_STDINCLUDE=$stdinclude
+CC_STDLIB=$stdlib
+CC_STRICT=$strict
+CC_STRIP=$strip
+CC_STRIP_FLAGS=$stripflags
+CC_PREFIX_ARCHIVE=$prefix_archive
+CC_PREFIX_DYNAMIC=$prefix_dynamic
+CC_PREFIX_SHARED=$prefix_shared
+CC_PREFIX_SYMBOL=$symprefix
+CC_SUFFIX_ARCHIVE=.$lib
+CC_SUFFIX_COMMAND=$suffix_command
+CC_SUFFIX_DEBUG=$sdb
+CC_SUFFIX_DYNAMIC=$sd
+CC_SUFFIX_LD=$ldscript
+CC_SUFFIX_OBJECT=.$obj
+CC_SUFFIX_SHARED=$so
+CC_SUFFIX_SOURCE=.$src
+CC_SUFFIX_STATIC=$sa
+CC_VERSION=$version_flags
+CC_WARN=$warn
+CC_ATTRIBUTES=$ATTRIBUTES
+
+exec >&3
+
+#
+# check for local override
+# all CC_* but { CC_CC CC_VERSION_STAMP CC_VERSION_STRING } may be modified
+# additional CC.* may be printed on stdout
+#
+
+if test -f "$dir/probe.lcl"
+then . "$dir/probe.lcl"
+fi
+
+#
+# the payoff
+#
+
+case $version_stamp in
+?*) echo "# $version_stamp" ;;
+esac
+echo CC.CC = $cc
+echo CC.NATIVE = $CC_NATIVE
+echo CC.EXECTYPE = $CC_EXECTYPE
+echo CC.HOSTTYPE = $CC_HOSTTYPE
+echo CC.ALTPP.FLAGS = $CC_ALTPP_FLAGS
+echo CC.ALTPP.ENV = $CC_ALTPP_ENV
+echo CC.AR = $CC_AR
+echo CC.AR.ARFLAGS = $CC_AR_ARFLAGS
+echo CC.ARFLAGS = $CC_ARFLAGS
+echo CC.DEBUG = $CC_DEBUG
+echo CC.DIALECT = $CC_DIALECT
+echo CC.DLLBIG = $CC_DLLBIG
+echo CC.DLLSMALL = $CC_DLLSMALL
+echo CC.DLL = $CC_DLL
+echo CC.DLL.DEF = $cc_dll_def
+echo CC.DLL.DIR = $CC_DLL_DIR
+echo CC.DLL.LIBRARIES = $CC_DLL_LIBRARIES
+echo CC.DLL.VARIANTS = $CC_DLL_VARIANTS
+echo CC.DYNAMIC = $CC_DYNAMIC
+echo CC.EXPORT.DYNAMIC = $CC_EXPORT_DYNAMIC
+echo CC.INCLUDE.LOCAL = $CC_INCLUDE_LOCAL
+#
+# 2004-02-14 release workaround
+#
+case $CC_SHARED_LD in
+$CC_CC) echo if LDSHARED
+ echo CC.LD = $CC_LD
+ echo else
+ echo CC.LD = $CC_CC
+ echo end
+ ;;
+*) echo CC.LD = $CC_LD
+ ;;
+esac
+echo CC.LD.DYNAMIC = $CC_LD_DYNAMIC
+echo CC.LD.LAZY = $CC_LD_LAZY
+echo CC.LD.NOLAZY = $CC_LD_NOLAZY
+echo CC.LD.ORIGIN = $CC_LD_ORIGIN
+echo CC.LD.RECORD = $CC_LD_RECORD
+echo CC.LD.NORECORD = $CC_LD_NORECORD
+echo CC.LD.RUNPATH = $CC_LD_RUNPATH
+echo CC.LD.STATIC = $CC_LD_STATIC
+echo CC.LD.STRIP = $CC_LD_STRIP
+echo CC.LIB.DLL = $CC_LIB_DLL
+echo CC.LIB.ALL = $CC_LIB_ALL
+echo CC.LIB.UNDEF = $CC_LIB_UNDEF
+echo CC.MAKE.OPTIONS = $CC_MAKE_OPTIONS
+echo CC.NM = $CC_NM
+case $CC_NMEDIT in
+?*) CC_NMEDIT=" $CC_NMEDIT" ;;
+esac
+echo CC.NMEDIT ="$CC_NMEDIT"
+echo CC.NMFLAGS = $CC_NMFLAGS
+echo CC.NOPROTECT = $CC_NOPROTECT
+echo CC.OPTIMIZE = $CC_OPTIMIZE
+echo CC.PICBIG = $CC_PICBIG
+echo CC.PICSMALL = $CC_PICSMALL
+echo CC.PIC = $CC_PIC
+echo CC.READONLY = $CC_READONLY
+echo CC.REPOSITORY = $CC_REPOSITORY
+for f in $CC_REQUIRE
+do echo CC.REQUIRE.$f =`cat req.$f`
+done
+echo CC.RUNPATH = $CC_RUNPATH
+echo CC.SHARED = $CC_SHARED
+echo CC.SHARED.LD = $CC_SHARED_LD
+echo CC.SHARED.NAME = $CC_SHARED_NAME
+echo CC.SHARED.REGISTRY = $CC_SHARED_REGISTRY
+echo CC.SHARED.REGISTRY.PATH = $CC_SHARED_REGISTRY_PATH
+echo CC.SHELLMAGIC = $CC_SHELLMAGIC
+echo CC.SIZE = $CC_SIZE
+echo CC.STATIC = $CC_STATIC
+echo CC.STDINCLUDE = $CC_STDINCLUDE
+echo CC.STDLIB = $CC_STDLIB
+echo CC.STRICT = $CC_STRICT
+echo CC.STRIP = $CC_STRIP
+echo CC.STRIP.FLAGS = $CC_STRIP_FLAGS
+echo CC.PREFIX.ARCHIVE = $CC_PREFIX_ARCHIVE
+echo CC.PREFIX.DYNAMIC = $CC_PREFIX_DYNAMIC
+echo CC.PREFIX.SHARED = $CC_PREFIX_SHARED
+echo CC.PREFIX.SYMBOL = $CC_PREFIX_SYMBOL
+echo CC.SUFFIX.ARCHIVE = $CC_SUFFIX_ARCHIVE
+echo CC.SUFFIX.COMMAND = $CC_SUFFIX_COMMAND
+echo CC.SUFFIX.DEBUG = $CC_SUFFIX_DEBUG
+echo CC.SUFFIX.DYNAMIC = $CC_SUFFIX_DYNAMIC
+echo CC.SUFFIX.LD = $CC_SUFFIX_LD
+echo CC.SUFFIX.OBJECT = $CC_SUFFIX_OBJECT
+echo CC.SUFFIX.SHARED = $CC_SUFFIX_SHARED
+echo CC.SUFFIX.SOURCE = $CC_SUFFIX_SOURCE
+echo CC.SUFFIX.STATIC = $CC_SUFFIX_STATIC
+echo CC.VERSION = $CC_VERSION
+case $CC_VERSION_STRING in
+*\"*) i=`echo " $CC_VERSION_STRING" | sed -e 's,",\\\\",g' -e 's,^ ,,' -e 's,.*,"&",'` ;;
+*\'*) i=\"$CC_VERSION_STRING\" ;;
+*) i=$CC_VERSION_STRING ;;
+esac
+cat <<!
+CC.VERSION.STRING = $i
+!
+echo CC.WARN = $CC_WARN
+
+for i in $CC_ATTRIBUTES
+do eval echo CC.$i = \$$i
+done
diff --git a/src/cmd/INIT/mamake.c b/src/cmd/INIT/mamake.c
new file mode 100644
index 0000000..1f85240
--- /dev/null
+++ b/src/cmd/INIT/mamake.c
@@ -0,0 +1,2375 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * mamake -- MAM make
+ *
+ * coded for portability
+ */
+
+static char id[] = "\n@(#)$Id: mamake (AT&T Research) 2011-08-31 $\0\n";
+
+#if _PACKAGE_ast
+
+#include <ast.h>
+#include <error.h>
+
+static const char usage[] =
+"[-?\n@(#)$Id: mamake (AT&T Research) 2011-08-31 $\n]"
+USAGE_LICENSE
+"[+NAME?mamake - make abstract machine make]"
+"[+DESCRIPTION?\bmamake\b reads \amake abstract machine\a target and"
+" prerequisite file descriptions from a mamfile (see \b-f\b) and executes"
+" actions to update targets that are older than their prerequisites."
+" Mamfiles are generated by the \b--mam\b option of \bnmake\b(1) and"
+" \bgmake\b(1) and are portable to environments that only have"
+" \bsh\b(1) and \bcc\b(1).]"
+"[+?In practice \bmamake\b is used to bootstrap build \bnmake\b(1) and"
+" \bksh\b(1) in new environments. Mamfiles are used rather than"
+" old-\bmake\b makefiles because some features are not reliably supported"
+" across all \bmake\b variants:]{"
+" [+action execution?Multi-line actions are executed as a"
+" unit by \b$SHELL\b. There are some shell constructs"
+" that cannot be expressed in an old-\bmake\b makefile.]"
+" [+viewpathing?\bVPATH\b is properly interpreted. This allows"
+" source to be separate from generated files.]"
+" [+recursion?Ordered subdirectory recursion over unrelated"
+" makefiles.]"
+" }"
+"[+?\bmamprobe\b(1) is called to probe and generate system specific variable"
+" definitions. The probe information is regenerated when it is older"
+" than the \bmamprobe\b command.]"
+"[+?For compatibility with \bnmake\b(1) the \b-K\b option and the"
+" \brecurse\b and \bcc-*\b command line targets are ignored.]"
+"[e:?Explain reason for triggering action. Ignored if -F is on.]"
+"[f:?Read \afile\a instead of the default.]:[file:=Mamfile]"
+"[i:?Ignore action errors.]"
+"[k:?Continue after error with sibling prerequisites.]"
+"[n:?Print actions but do not execute. Recursion actions (see \b-r\b) are still"
+" executed. Use \b-N\b to disable recursion actions too.]"
+"[r:?Recursively make leaf directories matching \apattern\a. Only leaf"
+" directories containing a makefile named \bNmakefile\b, \bnmakefile\b,"
+" \bMakefile\b or \bmakefile\b are considered. The first makefile"
+" found in each leaf directory is scanned for leaf directory"
+" prerequisites; the recusion order is determined by a topological sort"
+" of these prerequisites.]:[pattern]"
+"[C:?Do all work in \adirectory\a. All messages will mention"
+" \adirectory\a.]:[directory]"
+"[D:?Set the debug trace level to \alevel\a. Higher levels produce more"
+" output.]#[level]"
+"[F:?Force all targets to be out of date.]"
+"[K:?Ignored.]"
+"[N:?Like \b-n\b but recursion actions (see \b-r\b) are also disabled.]"
+"[V:?Print the program version and exit.]"
+"[G:debug-symbols?Compile and link with debugging symbol options enabled.]"
+"[S:strip-symbols?Strip link-time static symbols from executables.]"
+
+"\n"
+"\n[ target ... ] [ name=value ... ]\n"
+"\n"
+
+"[+SEE ALSO?\bgmake\b(1), \bmake\b(1), \bmamprobe\b(1),"
+" \bnmake\b(1), \bsh\b(1)]"
+;
+
+#else
+
+#define elementsof(x) (sizeof(x)/sizeof(x[0]))
+#define newof(p,t,n,x) ((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)calloc(1,sizeof(t)*(n)+(x)))
+
+#define NiL ((char*)0)
+
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+
+#if !_PACKAGE_ast && defined(__STDC__)
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#define delimiter(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)==';'||(c)=='('||(c)==')'||(c)=='`'||(c)=='|'||(c)=='&'||(c)=='=')
+
+#define add(b,c) (((b)->nxt >= (b)->end) ? append(b, "") : NiL, *(b)->nxt++ = (c))
+#define get(b) ((b)->nxt-(b)->buf)
+#define set(b,o) ((b)->nxt=(b)->buf+(o))
+#define use(b) (*(b)->nxt=0,(b)->nxt=(b)->buf)
+
+#define CHUNK 1024
+#define KEY(a,b,c,d) ((((unsigned long)(a))<<15)|(((unsigned long)(b))<<10)|(((unsigned long)(c))<<5)|(((unsigned long)(d))))
+#define NOW ((unsigned long)time((time_t*)0))
+#define ROTATE(p,l,r,t) ((t)=(p)->l,(p)->l=(t)->r,(t)->r=(p),(p)=(t))
+
+#define RULE_active 0x0001 /* active target */
+#define RULE_dontcare 0x0002 /* ok if not found */
+#define RULE_error 0x0004 /* not found or not generated */
+#define RULE_exists 0x0008 /* target file exists */
+#define RULE_generated 0x0010 /* generated target */
+#define RULE_ignore 0x0020 /* ignore time */
+#define RULE_implicit 0x0040 /* implicit prerequisite */
+#define RULE_made 0x0080 /* already made */
+#define RULE_virtual 0x0100 /* not a file */
+
+#define STREAM_KEEP 0x0001 /* don't fclose() on pop() */
+#define STREAM_MUST 0x0002 /* push() file must exist */
+#define STREAM_PIPE 0x0004 /* pclose() on pop() */
+
+#ifndef S_IXUSR
+#define S_IXUSR 0100 /* owner execute permission */
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0010 /* group execute permission */
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0001 /* other execute permission */
+#endif
+
+struct Rule_s;
+
+typedef struct stat Stat_t;
+typedef FILE Stdio_t;
+
+typedef struct Buf_s /* buffer stream */
+{
+ struct Buf_s* old; /* next dropped buffer */
+ char* end; /* 1 past end of buffer */
+ char* nxt; /* next char to add */
+ char* buf; /* buffer space */
+} Buf_t;
+
+typedef struct Dict_item_s /* dictionary item */
+{
+ struct Dict_item_s* left; /* left child */
+ struct Dict_item_s* right; /* right child */
+ void* value; /* user defined value */
+ char name[1];/* 0 terminated name */
+} Dict_item_t;
+
+typedef struct Dict_s /* dictionary handle */
+{
+ Dict_item_t* root; /* root item */
+} Dict_t;
+
+typedef struct List_s /* Rule_t list */
+{
+ struct List_s* next; /* next in list */
+ struct Rule_s* rule; /* list item */
+} List_t;
+
+typedef struct Rule_s /* rule item */
+{
+ char* name; /* unbound name */
+ char* path; /* bound path */
+ List_t* prereqs; /* prerequisites */
+ struct Rule_s* leaf; /* recursion leaf alias */
+ int flags; /* RULE_* flags */
+ int making; /* currently make()ing */
+ unsigned long time; /* modification time */
+} Rule_t;
+
+typedef struct Stream_s /* input file stream stack */
+{
+ Stdio_t* fp; /* read stream */
+ char* file; /* stream path */
+ unsigned long line; /* stream line */
+ int flags; /* stream flags */
+} Stream_t;
+
+typedef struct View_s /* viewpath level */
+{
+ struct View_s* next; /* next level in viewpath */
+ int node; /* viewpath node path length */
+ char dir[1]; /* viewpath level dir prefix */
+} View_t;
+
+static struct /* program state */
+{
+ Buf_t* buf; /* work buffer */
+ Buf_t* old; /* dropped buffers */
+ Buf_t* opt; /* option buffer */
+
+ Dict_t* leaf; /* recursion leaf dictionary */
+ Dict_t* libs; /* library dictionary */
+ Dict_t* rules; /* rule dictionary */
+ Dict_t* vars; /* variable dictionary */
+
+ View_t* view; /* viewpath levels */
+
+ char* directory; /* work in this directory */
+ char* id; /* command name */
+ char* file; /* first input file */
+ char* pwd; /* current directory */
+ char* recurse; /* recursion pattern */
+ char* shell; /* ${SHELL} */
+
+ int active; /* targets currently active */
+ int debug; /* negative of debug level */
+ int errors; /* some error(s) occurred */
+ int exec; /* execute actions */
+ int explain; /* explain actions */
+ int force; /* all targets out of date */
+ int ignore; /* ignore command errors */
+ int indent; /* debug indent */
+ int keepgoing; /* do siblings on error */
+ int never; /* never execute */
+ int peek; /* next line already in input */
+ int probed; /* probe already done */
+ int verified; /* don't bother with verify() */
+
+ Stream_t streams[4]; /* input file stream stack */
+ Stream_t* sp; /* input stream stack pointer */
+
+ char input[8*CHUNK]; /* input buffer */
+} state;
+
+static unsigned long make(Rule_t*);
+
+static char mamfile[] = "Mamfile";
+static char sh[] = "/bin/sh";
+
+extern char** environ;
+
+#if !_PACKAGE_ast
+
+#if defined(NeXT) || defined(__NeXT)
+#define getcwd(a,b) getwd(a)
+#endif
+
+/*
+ * emit usage message and exit
+ */
+
+static void
+usage()
+{
+ fprintf(stderr, "Usage: %s [-iknFKNV] [-f mamfile] [-r pattern] [-C directory] [-D level] [target ...] [name=value ...]\n", state.id);
+ exit(2);
+}
+
+#endif
+
+/*
+ * output error message identification
+ */
+
+static void
+identify(Stdio_t* sp)
+{
+ if (state.directory)
+ fprintf(sp, "%s [%s]: ", state.id, state.directory);
+ else
+ fprintf(sp, "%s: ", state.id);
+}
+
+/*
+ * emit error message
+ * level:
+ * <0 debug
+ * 0 info
+ * 1 warning
+ * 2 error
+ * >2 exit(level-2)
+ */
+
+static void
+report(int level, char* text, char* item, unsigned long stamp)
+{
+ int i;
+
+ if (level >= state.debug)
+ {
+ if (level)
+ identify(stderr);
+ if (level < 0)
+ {
+ fprintf(stderr, "debug%d: ", level);
+ for (i = 1; i < state.indent; i++)
+ fprintf(stderr, " ");
+ }
+ else
+ {
+ if (state.sp && state.sp->line)
+ {
+ if (state.sp->file)
+ fprintf(stderr, "%s: ", state.sp->file);
+ fprintf(stderr, "%ld: ", state.sp->line);
+ }
+ if (level == 1)
+ fprintf(stderr, "warning: ");
+ else if (level > 1)
+ state.errors = 1;
+ }
+ if (item)
+ fprintf(stderr, "%s: ", item);
+ fprintf(stderr, "%s", text);
+ if (stamp && state.debug <= -2)
+ fprintf(stderr, " %10lu", stamp);
+ fprintf(stderr, "\n");
+ if (level > 2)
+ exit(level - 2);
+ }
+}
+
+/*
+ * don't know how to make or exit code making
+ */
+
+static void
+dont(Rule_t* r, int code, int keepgoing)
+{
+ identify(stderr);
+ if (!code)
+ fprintf(stderr, "don't know how to make %s\n", r->name);
+ else
+ {
+ fprintf(stderr, "*** exit code %d making %s%s\n", code, r->name, state.ignore ? " ignored" : "");
+ unlink(r->name);
+ if (state.ignore)
+ return;
+ }
+ if (!keepgoing)
+ exit(1);
+ state.errors++;
+ r->flags |= RULE_error;
+}
+
+/*
+ * local strrchr()
+ */
+
+static char*
+last(register char* s, register int c)
+{
+ register char* r = 0;
+
+ for (r = 0; *s; s++)
+ if (*s == c)
+ r = s;
+ return r;
+}
+
+/*
+ * open a buffer stream
+ */
+
+static Buf_t*
+buffer(void)
+{
+ register Buf_t* buf;
+
+ if (buf = state.old)
+ state.old = state.old->old;
+ else if (!(buf = newof(0, Buf_t, 1, 0)) || !(buf->buf = newof(0, char, CHUNK, 0)))
+ report(3, "out of space [buffer]", NiL, (unsigned long)0);
+ buf->end = buf->buf + CHUNK;
+ buf->nxt = buf->buf;
+ return buf;
+}
+
+/*
+ * close a buffer stream
+ */
+
+static void
+drop(Buf_t* buf)
+{
+ buf->old = state.old;
+ state.old = buf;
+}
+
+/*
+ * append str length n to buffer and return the buffer base
+ */
+
+static char*
+appendn(Buf_t* buf, char* str, int n)
+{
+ int m;
+ int i;
+
+ if ((n + 1) >= (buf->end - buf->nxt))
+ {
+ i = buf->nxt - buf->buf;
+ m = (((buf->end - buf->buf) + n + CHUNK + 1) / CHUNK) * CHUNK;
+ if (!(buf->buf = newof(buf->buf, char, m, 0)))
+ report(3, "out of space [buffer resize]", NiL, (unsigned long)0);
+ buf->end = buf->buf + m;
+ buf->nxt = buf->buf + i;
+ }
+ memcpy(buf->nxt, str, n + 1);
+ buf->nxt += n;
+ return buf->buf;
+}
+
+/*
+ * append str to buffer and return the buffer base
+ * if str==0 then next pointer reset to base
+ */
+
+static char*
+append(Buf_t* buf, char* str)
+{
+ if (str)
+ return appendn(buf, str, strlen(str));
+ buf->nxt = buf->buf;
+ return buf->buf;
+}
+
+/*
+ * allocate space for s and return the copy
+ */
+
+static char*
+duplicate(char* s)
+{
+ char* t;
+ int n;
+
+ n = strlen(s);
+ if (!(t = newof(0, char, n, 1)))
+ report(3, "out of space [duplicate]", s, (unsigned long)0);
+ strcpy(t, s);
+ return t;
+}
+
+/*
+ * open a new dictionary
+ */
+
+static Dict_t*
+dictionary(void)
+{
+ Dict_t* dict;
+
+ if (!(dict = newof(0, Dict_t, 1, 0)))
+ report(3, "out of space [dictionary]", NiL, (unsigned long)0);
+ return dict;
+}
+
+/*
+ * return the value for item name in dictionary dict
+ * if value!=0 then name entry value is created if necessary and set
+ * uses top-down splaying (ala Tarjan and Sleator)
+ */
+
+static void*
+search(register Dict_t* dict, char* name, void* value)
+{
+ register int cmp;
+ register Dict_item_t* root;
+ register Dict_item_t* t;
+ register Dict_item_t* left;
+ register Dict_item_t* right;
+ register Dict_item_t* lroot;
+ register Dict_item_t* rroot;
+
+ root = dict->root;
+ left = right = lroot = rroot = 0;
+ while (root)
+ {
+ if (!(cmp = strcmp(name, root->name)))
+ break;
+ else if (cmp < 0)
+ {
+ if (root->left && (cmp = strcmp(name, root->left->name)) <= 0)
+ {
+ ROTATE(root, left, right, t);
+ if (!cmp)
+ break;
+ }
+ if (right)
+ right->left = root;
+ else
+ rroot = root;
+ right = root;
+ root = root->left;
+ right->left = 0;
+ }
+ else
+ {
+ if (root->right && (cmp = strcmp(name, root->right->name)) >= 0)
+ {
+ ROTATE(root, right, left, t);
+ if (!cmp)
+ break;
+ }
+ if (left)
+ left->right = root;
+ else
+ lroot = root;
+ left = root;
+ root = root->right;
+ left->right = 0;
+ }
+ }
+ if (root)
+ {
+ if (right)
+ right->left = root->right;
+ else
+ rroot = root->right;
+ if (left)
+ left->right = root->left;
+ else
+ lroot = root->left;
+ }
+ else if (value)
+ {
+ if (!(root = newof(0, Dict_item_t, 1, strlen(name))))
+ report(3, "out of space [dictionary]", name, (unsigned long)0);
+ strcpy(root->name, name);
+ }
+ if (root)
+ {
+ if (value)
+ root->value = value;
+ root->left = lroot;
+ root->right = rroot;
+ dict->root = root;
+ return value ? (void*)root->name : root->value;
+ }
+ if (left)
+ {
+ left->right = rroot;
+ dict->root = lroot;
+ }
+ else if (right)
+ {
+ right->left = lroot;
+ dict->root = rroot;
+ }
+ return 0;
+}
+
+/*
+ * low level for walk()
+ */
+
+static int
+apply(Dict_t* dict, Dict_item_t* item, int (*func)(Dict_item_t*, void*), void* handle)
+{
+ register Dict_item_t* right;
+
+ do
+ {
+ right = item->right;
+ if (item->left && apply(dict, item->left, func, handle))
+ return -1;
+ if ((*func)(item, handle))
+ return -1;
+ } while (item = right);
+ return 0;
+}
+
+/*
+ * apply func to each dictionary item
+ */
+
+static int
+walk(Dict_t* dict, int (*func)(Dict_item_t*, void*), void* handle)
+{
+ return dict->root ? apply(dict, dict->root, func, handle) : 0;
+}
+
+/*
+ * return a rule pointer for name
+ */
+
+static Rule_t*
+rule(char* name)
+{
+ Rule_t* r;
+
+ if (!(r = (Rule_t*)search(state.rules, name, NiL)))
+ {
+ if (!(r = newof(0, Rule_t, 1, 0)))
+ report(3, "out of space [rule]", name, (unsigned long)0);
+ r->name = (char*)search(state.rules, name, (void*)r);
+ }
+ return r;
+}
+
+/*
+ * prepend p onto rule r prereqs
+ */
+
+static void
+cons(Rule_t* r, Rule_t* p)
+{
+ register List_t* x;
+
+ for (x = r->prereqs; x && x->rule != p; x = x->next);
+ if (!x)
+ {
+ if (!(x = newof(0, List_t, 1, 0)))
+ report(3, "out of space [list]", r->name, (unsigned long)0);
+ x->rule = p;
+ x->next = r->prereqs;
+ r->prereqs = x;
+ }
+}
+
+/*
+ * initialize the viewpath
+ */
+
+static void
+view(void)
+{
+ register char* s;
+ register char* t;
+ register char* p;
+ register View_t* vp;
+
+ View_t* zp;
+ int c;
+ int n;
+
+ Stat_t st;
+ Stat_t ts;
+
+ char buf[CHUNK];
+
+ if (stat(".", &st))
+ report(3, "cannot stat", ".", (unsigned long)0);
+ if ((s = (char*)search(state.vars, "PWD", NiL)) && !stat(s, &ts) &&
+ ts.st_dev == st.st_dev && ts.st_ino == st.st_ino)
+ state.pwd = s;
+ if (!state.pwd)
+ {
+ if (!getcwd(buf, sizeof(buf) - 1))
+ report(3, "cannot determine PWD", NiL, (unsigned long)0);
+ state.pwd = duplicate(buf);
+ search(state.vars, "PWD", state.pwd);
+ }
+ if ((s = (char*)search(state.vars, "VPATH", NiL)) && *s)
+ {
+ zp = 0;
+ for (;;)
+ {
+ for (t = s; *t && *t != ':'; t++);
+ if (c = *t)
+ *t = 0;
+ if (!state.view)
+ {
+ /*
+ * determine the viewpath offset
+ */
+
+ if (stat(s, &st))
+ report(3, "cannot stat top view", s, (unsigned long)0);
+ if (stat(state.pwd, &ts))
+ report(3, "cannot stat", state.pwd, (unsigned long)0);
+ if (ts.st_dev == st.st_dev && ts.st_ino == st.st_ino)
+ p = ".";
+ else
+ {
+ p = state.pwd + strlen(state.pwd);
+ while (p > state.pwd)
+ if (*--p == '/')
+ {
+ if (p == state.pwd)
+ report(3, ". not under VPATH", s, (unsigned long)0);
+ *p = 0;
+ if (stat(state.pwd, &ts))
+ report(3, "cannot stat", state.pwd, (unsigned long)0);
+ *p = '/';
+ if (ts.st_dev == st.st_dev && ts.st_ino == st.st_ino)
+ {
+ p++;
+ break;
+ }
+ }
+ if (p <= state.pwd)
+ report(3, "cannot determine viewpath offset", s, (unsigned long)0);
+ }
+ }
+ n = strlen(s);
+ if (!(vp = newof(0, View_t, 1, strlen(p) + n + 1)))
+ report(3, "out of space [view]", s, (unsigned long)0);
+ vp->node = n + 1;
+ strcpy(vp->dir, s);
+ *(vp->dir + n) = '/';
+ strcpy(vp->dir + n + 1, p);
+ report(-4, vp->dir, "view", (unsigned long)0);
+ if (!state.view)
+ state.view = zp = vp;
+ else
+ zp = zp->next = vp;
+ if (!c)
+ break;
+ *t++ = c;
+ s = t;
+ }
+ }
+}
+
+/*
+ * return next '?' or '}' in nested '}'
+ */
+
+static char*
+cond(register char* s)
+{
+ register int n;
+
+ if (*s == '?')
+ s++;
+ n = 0;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ break;
+ case '{':
+ n++;
+ continue;
+ case '}':
+ if (!n--)
+ break;
+ continue;
+ case '?':
+ if (!n)
+ break;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ return s - 1;
+}
+
+/*
+ * expand var refs from s into buf
+ */
+
+static void
+substitute(Buf_t* buf, register char* s)
+{
+ register char* t;
+ register char* v;
+ register char* q;
+ register char* b;
+ register int c;
+ register int n;
+ int a = 0;
+ int i;
+
+ while (c = *s++)
+ {
+ if (c == '$' && *s == '{')
+ {
+ b = s - 1;
+ i = 1;
+ for (n = *(t = ++s) == '-' ? 0 : '-'; (c = *s) && c != '?' && c != '+' && c != n && c != ':' && c != '=' && c != '[' && c != '}'; s++)
+ if (!isalnum(c) && c != '_')
+ i = 0;
+ *s = 0;
+ if (c == '[')
+ {
+ append(buf, b);
+ *s = c;
+ continue;
+ }
+ v = (char*)search(state.vars, t, NiL);
+ if ((c == ':' || c == '=') && (!v || c == ':' && !*v))
+ {
+ append(buf, b);
+ *s = c;
+ continue;
+ }
+ if (t[0] == 'A' && t[1] == 'R' && t[2] == 0)
+ a = 1;
+ *s = c;
+ if (c && c != '}')
+ {
+ n = 1;
+ for (t = ++s; *s; s++)
+ if (*s == '{')
+ n++;
+ else if (*s == '}' && !--n)
+ break;
+ }
+ switch (c)
+ {
+ case '?':
+ q = cond(t - 1);
+ if (v)
+ {
+ if (((q - t) != 1 || *t != '*') && strncmp(v, t, q - t))
+ v = 0;
+ }
+ else if (q == t)
+ v = s;
+ t = cond(q);
+ if (v)
+ {
+ if (t > q)
+ {
+ c = *t;
+ *t = 0;
+ substitute(buf, q + 1);
+ *t = c;
+ }
+ }
+ else
+ {
+ q = cond(t);
+ if (q > t)
+ {
+ c = *q;
+ *q = 0;
+ substitute(buf, t + 1);
+ *q = c;
+ }
+ }
+ break;
+ case '+':
+ case '-':
+ if ((v == 0 || *v == 0) == (c == '-'))
+ {
+ c = *s;
+ *s = 0;
+ substitute(buf, t);
+ *s = c;
+ break;
+ }
+ if (c != '-')
+ break;
+ /*FALLTHROUGH*/
+ case 0:
+ case '=':
+ case '}':
+ if (v)
+ {
+ if (a && t[0] == 'm' && t[1] == 'a' && t[2] == 'm' && t[3] == '_' && t[4] == 'l' && t[5] == 'i' && t[6] == 'b')
+ {
+ for (t = v; *t == ' '; t++);
+ for (; *t && *t != ' '; t++);
+ if (*t)
+ *t = 0;
+ else
+ t = 0;
+ substitute(buf, v);
+ if (t)
+ *t = ' ';
+ }
+ else
+ substitute(buf, v);
+ }
+ else if (i)
+ {
+ c = *s;
+ *s = 0;
+ append(buf, b);
+ *s = c;
+ continue;
+ }
+ break;
+ }
+ if (*s)
+ s++;
+ }
+ else
+ add(buf, c);
+ }
+}
+
+/*
+ * expand var refs from s into buf and return buf base
+ */
+
+static char*
+expand(Buf_t* buf, char* s)
+{
+ substitute(buf, s);
+ return use(buf);
+}
+
+/*
+ * stat() with .exe check
+ */
+
+static char*
+status(Buf_t* buf, int off, char* path, struct stat* st)
+{
+ int r;
+ char* s;
+ Buf_t* tmp;
+
+ if (!stat(path, st))
+ return path;
+ if (!(tmp = buf))
+ {
+ tmp = buffer();
+ off = 0;
+ }
+ if (off)
+ set(tmp, off);
+ else
+ append(tmp, path);
+ append(tmp, ".exe");
+ s = use(tmp);
+ r = stat(s, st);
+ if (!buf)
+ {
+ drop(tmp);
+ s = path;
+ }
+ if (r)
+ {
+ if (off)
+ s[off] = 0;
+ s = 0;
+ }
+ return s;
+}
+
+/*
+ * return path to file
+ */
+
+static char*
+find(Buf_t* buf, char* file, struct stat* st)
+{
+ char* s;
+ View_t* vp;
+ int node;
+ int c;
+ int o;
+
+ if (s = status(buf, 0, file, st))
+ {
+ report(-3, s, "find", (unsigned long)0);
+ return s;
+ }
+ if (vp = state.view)
+ {
+ node = 0;
+ if (*file == '/')
+ {
+ do
+ {
+ if (!strncmp(file, vp->dir, vp->node))
+ {
+ file += vp->node;
+ node = 2;
+ break;
+ }
+ } while (vp = vp->next);
+ }
+ else
+ vp = vp->next;
+ if (vp)
+ do
+ {
+ if (node)
+ {
+ c = vp->dir[vp->node];
+ vp->dir[vp->node] = 0;
+ append(buf, vp->dir);
+ vp->dir[vp->node] = c;
+ }
+ else
+ {
+ append(buf, vp->dir);
+ append(buf, "/");
+ }
+ append(buf, file);
+ o = get(buf);
+ s = use(buf);
+ if (s = status(buf, o, s, st))
+ {
+ report(-3, s, "find", (unsigned long)0);
+ return s;
+ }
+ } while (vp = vp->next);
+ }
+ return 0;
+}
+
+/*
+ * bind r to a file and return the modify time
+ */
+
+static unsigned long
+bind(Rule_t* r)
+{
+ char* s;
+ Buf_t* buf;
+ struct stat st;
+
+ buf = buffer();
+ if (s = find(buf, r->name, &st))
+ {
+ if (s != r->name)
+ r->path = duplicate(s);
+ r->time = st.st_mtime;
+ r->flags |= RULE_exists;
+ }
+ drop(buf);
+ return r->time;
+}
+
+/*
+ * pop the current input file
+ */
+
+static int
+pop(void)
+{
+ int r;
+
+ if (!state.sp)
+ report(3, "input stack underflow", NiL, (unsigned long)0);
+ if (!state.sp->fp || (state.sp->flags & STREAM_KEEP))
+ r = 0;
+ else if (state.sp->flags & STREAM_PIPE)
+ r = pclose(state.sp->fp);
+ else
+ r = fclose(state.sp->fp);
+ if (state.sp == state.streams)
+ state.sp = 0;
+ else
+ state.sp--;
+ return r;
+}
+
+/*
+ * push file onto the input stack
+ */
+
+static int
+push(char* file, Stdio_t* fp, int flags)
+{
+ char* path;
+ Buf_t* buf;
+ struct stat st;
+
+ if (!state.sp)
+ state.sp = state.streams;
+ else if (++state.sp >= &state.streams[elementsof(state.streams)])
+ report(3, "input stream stack overflow", NiL, (unsigned long)0);
+ if (state.sp->fp = fp)
+ state.sp->file = "pipeline";
+ else if (flags & STREAM_PIPE)
+ report(3, "pipe error", file, (unsigned long)0);
+ else if (!file || !strcmp(file, "-") || !strcmp(file, "/dev/stdin"))
+ {
+ flags |= STREAM_KEEP;
+ state.sp->file = "/dev/stdin";
+ state.sp->fp = stdin;
+ }
+ else
+ {
+ buf = buffer();
+ if (path = find(buf, file, &st))
+ {
+ if (!(state.sp->fp = fopen(path, "r")))
+ report(3, "cannot read", path, (unsigned long)0);
+ state.sp->file = duplicate(path);
+ drop(buf);
+ }
+ else
+ {
+ drop(buf);
+ pop();
+ if (flags & STREAM_MUST)
+ report(3, "not found", file, (unsigned long)0);
+ return 0;
+ }
+ }
+ state.sp->flags = flags;
+ state.sp->line = 0;
+ return 1;
+}
+
+/*
+ * return the next input line
+ */
+
+static char*
+input(void)
+{
+ char* e;
+
+ if (!state.sp)
+ report(3, "no input file stream", NiL, (unsigned long)0);
+ if (state.peek)
+ state.peek = 0;
+ else if (!fgets(state.input, sizeof(state.input), state.sp->fp))
+ return 0;
+ else if (*state.input && *(e = state.input + strlen(state.input) - 1) == '\n')
+ *e = 0;
+ state.sp->line++;
+ return state.input;
+}
+
+/*
+ * pass shell action s to ${SHELL:-/bin/sh}
+ * the -c wrapper ensures that scripts are run in the selected shell
+ * even on systems that otherwise demand #! magic (can you say cygwin)
+ */
+
+static int
+execute(register char* s)
+{
+ register int c;
+ Buf_t* buf;
+
+ if (!state.shell && (!(state.shell = (char*)search(state.vars, "SHELL", NiL)) || !strcmp(state.shell, sh)))
+ state.shell = sh;
+ buf = buffer();
+ append(buf, state.shell);
+ append(buf, " -c '");
+ while (c = *s++)
+ {
+ if (c == '\'')
+ {
+ add(buf, c);
+ for (s--; *s == c; s++)
+ {
+ add(buf, '\\');
+ add(buf, c);
+ }
+ }
+ add(buf, c);
+ }
+ add(buf, '\'');
+ s = use(buf);
+ report(-5, s, "exec", (unsigned long)0);
+ if ((c = system(s)) > 255)
+ c >>= 8;
+ drop(buf);
+ return c;
+}
+
+/*
+ * run action s to update r
+ */
+
+static unsigned long
+run(Rule_t* r, register char* s)
+{
+ register Rule_t* q;
+ register char* t;
+ register int c;
+ register View_t* v;
+ int i;
+ int j;
+ int x;
+ Stat_t st;
+ Buf_t* buf;
+
+ if (r->flags & RULE_error)
+ return r->time;
+ buf = buffer();
+ if (!strncmp(s, "mamake -r ", 10))
+ {
+ state.verified = 1;
+ x = !state.never;
+ }
+ else
+ x = state.exec;
+ if (x)
+ append(buf, "trap - 1 2 3 15\nPATH=.:$PATH\nset -x\n");
+ if (state.view)
+ {
+ do
+ {
+ for (; delimiter(*s); s++)
+ add(buf, *s);
+ for (t = s; *s && !delimiter(*s); s++);
+ c = *s;
+ *s = 0;
+ if (c == '=')
+ {
+ append(buf, t);
+ continue;
+ }
+ if ((q = (Rule_t*)search(state.rules, t, NiL)) && q->path && !(q->flags & RULE_generated))
+ append(buf, q->path);
+ else
+ {
+ append(buf, t);
+ if (*t == '-' && *(t + 1) == 'I' && (*(t + 2) || c))
+ {
+ if (*(t + 2))
+ i = 2;
+ else
+ {
+ for (i = 3; *(t + i) == ' ' || *(t + i) == '\t'; i++);
+ *s = c;
+ for (s = t + i; *s && *s != ' ' && *s != '\t' && *s != '\n'; s++);
+ c = *s;
+ *s = 0;
+ append(buf, t + 2);
+ }
+ if (*(t + i) && *(t + i) != '/')
+ {
+ v = state.view;
+ while (v = v->next)
+ {
+ add(buf, ' ');
+ for (j = 0; j < i; j++)
+ add(buf, *(t + j));
+ append(buf, v->dir);
+ if (*(t + i) != '.' || *(t + i + 1))
+ {
+ add(buf, '/');
+ append(buf, t + i);
+ }
+ }
+ }
+ }
+ }
+ } while (*s = c);
+ s = use(buf);
+ }
+ else if (x)
+ {
+ append(buf, s);
+ s = use(buf);
+ }
+ if (x)
+ {
+ if (c = execute(s))
+ dont(r, c, state.keepgoing);
+ if (status((Buf_t*)0, 0, r->name, &st))
+ {
+ r->time = st.st_mtime;
+ r->flags |= RULE_exists;
+ }
+ else
+ r->time = NOW;
+ }
+ else
+ {
+ fprintf(stdout, "%s\n", s);
+ if (state.debug)
+ fflush(stdout);
+ r->time = NOW;
+ r->flags |= RULE_exists;
+ }
+ drop(buf);
+ return r->time;
+}
+
+/*
+ * return the full path for s using buf workspace
+ */
+
+static char*
+path(Buf_t* buf, char* s, int must)
+{
+ register char* p;
+ register char* d;
+ register char* x;
+ char* e;
+ register int c;
+ int t;
+ int o;
+ Stat_t st;
+
+ for (e = s; *e && *e != ' ' && *e != '\t'; e++);
+ t = *e;
+ if ((x = status(buf, 0, s, &st)) && (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
+ return x;
+ if (!(p = (char*)search(state.vars, "PATH", NiL)))
+ report(3, "variable not defined", "PATH", (unsigned long)0);
+ do
+ {
+ for (d = p; *p && *p != ':'; p++);
+ c = *p;
+ *p = 0;
+ if (*d && (*d != '.' || *(d + 1)))
+ {
+ append(buf, d);
+ add(buf, '/');
+ }
+ *p = c;
+ if (t)
+ *e = 0;
+ append(buf, s);
+ if (t)
+ *e = t;
+ o = get(buf);
+ x = use(buf);
+ if ((x = status(buf, o, x, &st)) && (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
+ return x;
+ } while (*p++);
+ if (must)
+ report(3, "command not found", s, (unsigned long)0);
+ return 0;
+}
+
+/*
+ * generate (if necessary) and read the MAM probe information
+ * done on the first `setv CC ...'
+ */
+
+static void
+probe(void)
+{
+ register char* cc;
+ register char* s;
+ unsigned long h;
+ unsigned long q;
+ Buf_t* buf;
+ Buf_t* pro;
+ Buf_t* tmp;
+ struct stat st;
+
+ static char let[] = "ABCDEFGHIJKLMNOP";
+ static char cmd[] = "mamprobe";
+
+ if (!(cc = (char*)search(state.vars, "CC", NiL)))
+ cc = "cc";
+ buf = buffer();
+ s = path(buf, cmd, 1);
+ q = stat(s, &st) ? (unsigned long)0 : (unsigned long)st.st_mtime;
+ pro = buffer();
+ s = cc = path(pro, cc, 1);
+ for (h = 0; *s; s++)
+ h = h * 0x63c63cd9L + *s + 0x9c39c33dL;
+ if (!(s = (char*)search(state.vars, "INSTALLROOT", NiL)))
+ report(3, "variable must be defined", "INSTALLROOT", (unsigned long)0);
+ append(buf, s);
+ append(buf, "/lib/probe/C/mam/");
+ for (h &= 0xffffffffL; h; h >>= 4)
+ add(buf, let[h & 0xf]);
+ s = use(buf);
+ h = stat(s, &st) ? (unsigned long)0 : (unsigned long)st.st_mtime;
+ if (h < q || !push(s, (Stdio_t*)0, 0))
+ {
+ tmp = buffer();
+ append(tmp, cmd);
+ add(tmp, ' ');
+ append(tmp, s);
+ add(tmp, ' ');
+ append(tmp, cc);
+ if (execute(use(tmp)))
+ report(3, "cannot generate probe info", s, (unsigned long)0);
+ drop(tmp);
+ if (!push(s, (Stdio_t*)0, 0))
+ report(3, "cannot read probe info", s, (unsigned long)0);
+ }
+ drop(pro);
+ drop(buf);
+ make(rule(""));
+ pop();
+}
+
+/*
+ * add attributes in s to r
+ */
+
+static void
+attributes(register Rule_t* r, register char* s)
+{
+ register char* t;
+ register int n;
+
+ for (;;)
+ {
+ for (; *s == ' '; s++);
+ for (t = s; *s && *s != ' '; s++);
+ if (!(n = s - t))
+ break;
+ switch (*t)
+ {
+ case 'd':
+ if (n == 8 && !strncmp(t, "dontcare", n))
+ r->flags |= RULE_dontcare;
+ break;
+ case 'g':
+ if (n == 9 && !strncmp(t, "generated", n))
+ r->flags |= RULE_generated;
+ break;
+ case 'i':
+ if (n == 6 && !strncmp(t, "ignore", n))
+ r->flags |= RULE_ignore;
+ else if (n == 8 && !strncmp(t, "implicit", n))
+ r->flags |= RULE_implicit;
+ break;
+ case 'v':
+ if (n == 7 && !strncmp(t, "virtual", n))
+ r->flags |= RULE_virtual;
+ break;
+ }
+ }
+}
+
+/*
+ * define ${mam_libX} for library reference lib
+ */
+
+static char*
+require(char* lib, int dontcare)
+{
+ register int c;
+ char* s;
+ char* r;
+ FILE* f;
+ Buf_t* buf;
+ Buf_t* tmp;
+ struct stat st;
+
+ static int dynamic = -1;
+
+ if (dynamic < 0)
+ dynamic = (s = search(state.vars, "mam_cc_L", NiL)) ? atoi(s) : 0;
+ if (!(r = search(state.vars, lib, NiL)))
+ {
+ buf = buffer();
+ tmp = buffer();
+ s = 0;
+ for (;;)
+ {
+ if (s)
+ append(buf, s);
+ if (r = search(state.vars, "mam_cc_PREFIX_ARCHIVE", NiL))
+ append(buf, r);
+ append(buf, lib + 2);
+ if (r = search(state.vars, "mam_cc_SUFFIX_ARCHIVE", NiL))
+ append(buf, r);
+ r = expand(tmp, use(buf));
+ if (!stat(r, &st))
+ break;
+ if (s)
+ {
+ r = lib;
+ break;
+ }
+ s = "${INSTALLROOT}/lib/";
+ if (dynamic)
+ {
+ append(buf, s);
+ if (r = search(state.vars, "mam_cc_PREFIX_SHARED", NiL))
+ append(buf, r);
+ append(buf, lib + 2);
+ if (r = search(state.vars, "mam_cc_SUFFIX_SHARED", NiL))
+ append(buf, r);
+ r = expand(tmp, use(buf));
+ if (!stat(r, &st))
+ {
+ r = lib;
+ break;
+ }
+ }
+ }
+ if (r != lib)
+ r = duplicate(r);
+ search(state.vars, lib, r);
+ append(tmp, lib + 2);
+ append(tmp, ".req");
+ if (!(f = fopen(use(tmp), "r")))
+ {
+ append(tmp, "${INSTALLROOT}/lib/lib/");
+ append(tmp, lib + 2);
+ f = fopen(expand(buf, use(tmp)), "r");
+ }
+ if (f)
+ {
+ for (;;)
+ {
+ while ((c = fgetc(f)) == ' ' || c == '\t' || c == '\n');
+ if (c == EOF)
+ break;
+ do
+ {
+ add(tmp, c);
+ } while ((c = fgetc(f)) != EOF && c != ' ' && c != '\t' && c != '\n');
+ s = use(tmp);
+ if (s[0] && (s[0] != '-' || s[1]))
+ {
+ add(buf, ' ');
+ append(buf, require(s, 0));
+ }
+ }
+ fclose(f);
+ r = use(buf);
+ }
+ else if (dontcare)
+ {
+ append(tmp, "set -\n");
+ append(tmp, "cd /tmp\n");
+ append(tmp, "echo 'int main(){return 0;}' > x.${!-$$}.c\n");
+ append(tmp, "${CC} ${CCFLAGS} -o x.${!-$$}.x x.${!-$$}.c ");
+ append(tmp, r);
+ append(tmp, " >/dev/null 2>&1\n");
+ append(tmp, "c=$?\n");
+ append(tmp, "rm -f x.${!-$$}.[cox]\n");
+ append(tmp, "exit $c\n");
+ if (execute(expand(buf, use(tmp))))
+ r = "";
+ }
+ r = duplicate(r);
+ search(state.vars, lib, r);
+ append(tmp, "mam_lib");
+ append(tmp, lib + 2);
+ search(state.vars, use(tmp), r);
+ drop(tmp);
+ drop(buf);
+ }
+ return r;
+}
+
+/*
+ * input() until `done r'
+ */
+
+static unsigned long
+make(Rule_t* r)
+{
+ register char* s;
+ register char* t;
+ register char* u;
+ register char* v;
+ register Rule_t* q;
+ unsigned long z;
+ unsigned long x;
+ Buf_t* buf;
+ Buf_t* cmd;
+
+ r->making++;
+ if (r->flags & RULE_active)
+ state.active++;
+ if (*r->name)
+ {
+ z = bind(r);
+ state.indent++;
+ report(-1, r->name, "make", r->time);
+ }
+ else
+ z = 0;
+ buf = buffer();
+ cmd = 0;
+ while (s = input())
+ {
+ for (; *s == ' '; s++);
+ for (; isdigit(*s); s++);
+ for (; *s == ' '; s++);
+ for (u = s; *s && *s != ' '; s++);
+ if (*s)
+ {
+ for (*s++ = 0; *s == ' '; s++);
+ for (t = s; *s && *s != ' '; s++);
+ if (*s)
+ for (*s++ = 0; *s == ' '; s++);
+ v = s;
+ }
+ else
+ t = v = s;
+ switch (KEY(u[0], u[1], u[2], u[3]))
+ {
+ case KEY('b','i','n','d'):
+ if ((t[0] == '-' || t[0] == '+') && t[1] == 'l' && (s = require(t, !strcmp(v, "dontcare"))) && strncmp(r->name, "FEATURE/", 8) && strcmp(r->name, "configure.h"))
+ for (;;)
+ {
+ for (t = s; *s && *s != ' '; s++);
+ if (*s)
+ *s = 0;
+ else
+ s = 0;
+ if (*t)
+ {
+ q = rule(expand(buf, t));
+ attributes(q, v);
+ x = bind(q);
+ if (z < x)
+ z = x;
+ if (q->flags & RULE_error)
+ r->flags |= RULE_error;
+ }
+ if (!s)
+ break;
+ for (*s++ = ' '; *s == ' '; s++);
+ }
+ continue;
+ case KEY('d','o','n','e'):
+ q = rule(expand(buf, t));
+ if (q != r)
+ report(2, "improper done statement", t, (unsigned long)0);
+ attributes(r, v);
+ if (cmd && state.active && (state.force || r->time < z || !r->time && !z))
+ {
+ if (state.explain && !state.force)
+ {
+ if (!r->time)
+ fprintf(stderr, "%s [not found]\n", r->name);
+ else
+ fprintf(stderr, "%s [%lu] older than prerequisites [%lu]\n", r->name, r->time, z);
+ }
+ substitute(buf, use(cmd));
+ x = run(r, use(buf));
+ if (z < x)
+ z = x;
+ }
+ r->flags |= RULE_made;
+ if (!(r->flags & (RULE_dontcare|RULE_error|RULE_exists|RULE_generated|RULE_implicit|RULE_virtual)))
+ dont(r, 0, state.keepgoing);
+ break;
+ case KEY('e','x','e','c'):
+ r->flags |= RULE_generated;
+ if (r->path)
+ {
+ free(r->path);
+ r->path = 0;
+ r->time = 0;
+ }
+ if (state.active)
+ {
+ if (cmd)
+ add(cmd, '\n');
+ else
+ cmd = buffer();
+ append(cmd, v);
+ }
+ continue;
+ case KEY('m','a','k','e'):
+ q = rule(expand(buf, t));
+ if (!q->making)
+ {
+ attributes(q, v);
+ x = make(q);
+ if (!(q->flags & RULE_ignore) && z < x)
+ z = x;
+ if (q->flags & RULE_error)
+ r->flags |= RULE_error;
+ }
+ continue;
+ case KEY('p','r','e','v'):
+ q = rule(expand(buf, t));
+ if (!q->making)
+ {
+ if (!(q->flags & RULE_ignore) && z < q->time)
+ z = q->time;
+ if (q->flags & RULE_error)
+ r->flags |= RULE_error;
+ state.indent++;
+ report(-2, q->name, "prev", q->time);
+ state.indent--;
+ }
+ continue;
+ case KEY('s','e','t','v'):
+ if (!search(state.vars, t, NiL))
+ {
+ if (*v == '"')
+ {
+ s = v + strlen(v) - 1;
+ if (*s == '"')
+ {
+ *s = 0;
+ v++;
+ }
+ }
+ search(state.vars, t, duplicate(expand(buf, v)));
+ }
+ if (!state.probed && t[0] == 'C' && t[1] == 'C' && !t[2])
+ {
+ state.probed = 1;
+ probe();
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ drop(buf);
+ if (cmd)
+ drop(cmd);
+ if (*r->name)
+ {
+ report(-1, r->name, "done", z);
+ state.indent--;
+ }
+ if (r->flags & RULE_active)
+ state.active--;
+ r->making--;
+ return r->time = z;
+}
+
+/*
+ * verify that active targets were made
+ */
+
+static int
+verify(Dict_item_t* item, void* handle)
+{
+ Rule_t* r = (Rule_t*)item->value;
+
+ if ((r->flags & (RULE_active|RULE_error|RULE_made)) == RULE_active)
+ dont(r, 0, 1);
+ return 0;
+}
+
+/*
+ * return 1 if name is an initializer
+ */
+
+static int
+initializer(char* name)
+{
+ register char* s;
+
+ if (s = last(name, '/'))
+ s++;
+ else
+ s = name;
+ return s[0] == 'I' && s[1] == 'N' && s[2] == 'I' && s[3] == 'T';
+}
+
+/*
+ * update recursion leaf r and its prerequisites
+ */
+
+static int
+update(register Rule_t* r)
+{
+ register List_t* x;
+ Buf_t* buf;
+
+ static char cmd[] = "${MAMAKE} -C ";
+ static char arg[] = " ${MAMAKEARGS}";
+
+ r->flags |= RULE_made;
+ if (r->leaf)
+ r->leaf->flags |= RULE_made;
+ for (x = r->prereqs; x; x = x->next)
+ if (x->rule->leaf && !(x->rule->flags & RULE_made))
+ update(x->rule);
+ buf = buffer();
+ substitute(buf, cmd);
+ append(buf, r->name);
+ substitute(buf, arg);
+ run(r, use(buf));
+ drop(buf);
+ return 0;
+}
+
+/*
+ * scan makefile prereqs
+ */
+
+static int
+scan(Dict_item_t* item, void* handle)
+{
+ register Rule_t* r = (Rule_t*)item->value;
+ register char* s;
+ register char* t;
+ register char* u;
+ register char* w;
+ Rule_t* q;
+ int i;
+ int j;
+ int k;
+ int p;
+ Buf_t* buf;
+
+ static char* files[] =
+ {
+ "Nmakefile",
+ "nmakefile",
+ "Makefile",
+ "makefile"
+ };
+
+ /*
+ * drop non-leaf rules
+ */
+
+ if (!r->leaf)
+ return 0;
+
+ /*
+ * always make initializers
+ */
+
+ if (initializer(r->name))
+ {
+ if (!(r->flags & RULE_made))
+ update(r);
+ return 0;
+ }
+ buf = buffer();
+ for (i = 0; i < elementsof(files); i++)
+ {
+ append(buf, r->name);
+ add(buf, '/');
+ append(buf, files[i]);
+ if (push(use(buf), (Stdio_t*)0, 0))
+ {
+ while (s = input())
+ {
+ j = p = 0;
+ while (*s)
+ {
+ for (k = 1; (i = *s) == ' ' || i == '\t' || i == '"' || i == '\''; s++);
+ for (t = s; (i = *s) && i != ' ' && i != '\t' && i != '"' && i != '\'' && i != '\\' && i != ':'; s++)
+ if (i == '/')
+ t = s + 1;
+ else if (i == '.' && *(s + 1) != 'c' && *(s + 1) != 'C' && *(s + 1) != 'h' && *(s + 1) != 'H' && t[0] == 'l' && t[1] == 'i' && t[2] == 'b')
+ *s = 0;
+ if (*s)
+ *s++ = 0;
+ if (!t[0])
+ k = 0;
+ else if ((t[0] == '-' || t[0] == '+') && t[1] == 'l' && t[2])
+ {
+ append(buf, "lib");
+ append(buf, t + 2);
+ t = use(buf);
+ }
+ else if (p)
+ {
+ if (t[0] == '+' && !t[1])
+ p = 2;
+ else if (p == 1)
+ {
+ if (i != ':' || strncmp(s, "command", 7))
+ {
+ append(buf, "lib");
+ append(buf, t);
+ t = use(buf);
+ }
+ if (i == ':')
+ while (*s && (*s == ' ' || *s == '\t'))
+ s++;
+ }
+ }
+ else if (i == ':')
+ {
+ if (j != ':' || !isupper(*t))
+ k = 0;
+ else if (!strcmp(t, "PACKAGE"))
+ {
+ p = 1;
+ k = 0;
+ }
+ else
+ for (u = t; *u; u++)
+ if (isupper(*u))
+ *u = tolower(*u);
+ else if (!isalnum(*u))
+ {
+ k = 0;
+ break;
+ }
+ }
+ else if (t[0] != 'l' || t[1] != 'i' || t[2] != 'b')
+ k = 0;
+ else
+ for (u = t + 3; *u; u++)
+ if (!isalnum(*u))
+ {
+ k = 0;
+ break;
+ }
+ if (k && ((q = (Rule_t*)search(state.leaf, t, NiL)) && q != r || *t++ == 'l' && *t++ == 'i' && *t++ == 'b' && *t && (q = (Rule_t*)search(state.leaf, t, NiL)) && q != r))
+ {
+ for (t = w = r->name; *w; w++)
+ if (*w == '/')
+ t = w + 1;
+ if (t[0] == 'l' && t[1] == 'i' && t[2] == 'b')
+ t += 3;
+ for (u = w = q->name; *w; w++)
+ if (*w == '/')
+ u = w + 1;
+ if (strcmp(t, u))
+ cons(r, q);
+ }
+ j = i;
+ }
+ }
+ pop();
+ for (s = 0, w = r->name; *w; w++)
+ if (*w == '/')
+ s = w;
+ if (s)
+ {
+ if ((s - r->name) > 3 && *(s - 1) == 'b' && *(s - 2) == 'i' && *(s - 3) == 'l' && *(s - 4) != '/')
+ {
+ /*
+ * foolib : foo : libfoo
+ */
+
+ *(s - 3) = 0;
+ q = (Rule_t*)search(state.leaf, r->name, NiL);
+ if (q && q != r)
+ cons(r, q);
+ for (t = w = r->name; *w; w++)
+ if (*w == '/')
+ t = w + 1;
+ append(buf, "lib");
+ append(buf, t);
+ q = (Rule_t*)search(state.leaf, use(buf), NiL);
+ if (q && q != r)
+ cons(r, q);
+ *(s - 3) = 'l';
+ }
+ else if (((s - r->name) != 3 || *(s - 1) != 'b' || *(s - 2) != 'i' || *(s - 3) != 'l') && (*(s + 1) != 'l' || *(s + 2) != 'i' || *(s + 3) != 'b'))
+ {
+ /*
+ * huh/foobar : lib/libfoo
+ */
+
+ s++;
+ t = s + strlen(s);
+ while (--t > s)
+ {
+ append(buf, "lib/lib");
+ appendn(buf, s, t - s);
+ q = (Rule_t*)search(state.leaf, use(buf), NiL);
+ if (q && q != r)
+ cons(r, q);
+ }
+ }
+ }
+ break;
+ }
+ }
+ drop(buf);
+ return 0;
+}
+
+/*
+ * descend into op and its prereqs
+ */
+
+static int
+descend(Dict_item_t* item, void* handle)
+{
+ Rule_t* r = (Rule_t*)item->value;
+
+ if (!state.active && (!(r->flags & RULE_active) || !(r = (Rule_t*)search(state.leaf, r->name, NiL))))
+ return 0;
+ return r->leaf && !(r->flags & RULE_made) ? update(r) : 0;
+}
+
+/*
+ * append the non-leaf active targets to state.opt
+ */
+
+static int
+active(Dict_item_t* item, void* handle)
+{
+ Rule_t* r = (Rule_t*)item->value;
+
+ if (r->flags & RULE_active)
+ {
+ if (r->leaf || search(state.leaf, r->name, NiL))
+ state.active = 0;
+ else
+ {
+ add(state.opt, ' ');
+ append(state.opt, r->name);
+ }
+ }
+ return 0;
+}
+
+/*
+ * recurse on mamfiles in subdirs matching pattern
+ */
+
+static int
+recurse(char* pattern)
+{
+ register char* s;
+ register char* t;
+ Rule_t* r;
+ Buf_t* buf;
+ Buf_t* tmp;
+ struct stat st;
+
+ /*
+ * first determine the MAM subdirs
+ */
+
+ tmp = buffer();
+ buf = buffer();
+ state.exec = !state.never;
+ state.leaf = dictionary();
+ append(buf, "ls -d ");
+ append(buf, pattern);
+ s = use(buf);
+ push("recurse", popen(s, "r"), STREAM_PIPE);
+ while (s = input())
+ {
+ append(buf, s);
+ add(buf, '/');
+ append(buf, mamfile);
+ if (find(tmp, use(buf), &st))
+ {
+ r = rule(s);
+ if (t = last(r->name, '/'))
+ t++;
+ else
+ t = r->name;
+ r->leaf = rule(t);
+ search(state.leaf, t, r);
+ }
+ }
+ pop();
+ drop(buf);
+ drop(tmp);
+
+ /*
+ * grab the non-leaf active targets
+ */
+
+ if (!state.active)
+ {
+ state.active = 1;
+ walk(state.rules, active, NiL);
+ }
+ search(state.vars, "MAMAKEARGS", duplicate(use(state.opt) + 1));
+
+ /*
+ * scan the makefile and descend
+ */
+
+ walk(state.rules, scan, NiL);
+ state.view = 0;
+ walk(state.rules, descend, NiL);
+ return 0;
+}
+
+int
+main(int argc, char** argv)
+{
+ register char** e;
+ register char* s;
+ register char* t;
+ register char* v;
+ Buf_t* tmp;
+ int c;
+
+ /*
+ * initialize the state
+ */
+
+ state.id = "mamake";
+ state.active = 1;
+ state.exec = 1;
+ state.file = mamfile;
+ state.opt = buffer();
+ state.rules = dictionary();
+ state.vars = dictionary();
+ search(state.vars, "MAMAKE", *argv);
+
+ /*
+ * parse the options
+ */
+
+#if _PACKAGE_ast
+ error_info.id = state.id;
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'e':
+ append(state.opt, " -e");
+ state.explain = 1;
+ continue;
+ case 'i':
+ append(state.opt, " -i");
+ state.ignore = 1;
+ continue;
+ case 'k':
+ append(state.opt, " -k");
+ state.keepgoing = 1;
+ continue;
+ case 'N':
+ state.never = 1;
+ /*FALLTHROUGH*/
+ case 'n':
+ append(state.opt, " -n");
+ state.exec = 0;
+ continue;
+ case 'F':
+ append(state.opt, " -F");
+ state.force = 1;
+ continue;
+ case 'K':
+ continue;
+ case 'V':
+ fprintf(stdout, "%s\n", id + 10);
+ exit(0);
+ case 'f':
+ append(state.opt, " -f ");
+ append(state.opt, opt_info.arg);
+ state.file = opt_info.arg;
+ continue;
+ case 'r':
+ state.recurse = opt_info.arg;
+ continue;
+ case 'C':
+ state.directory = opt_info.arg;
+ continue;
+ case 'D':
+ append(state.opt, " -D");
+ append(state.opt, opt_info.arg);
+ state.debug = -opt_info.num;
+ continue;
+ case 'G':
+ append(state.opt, " -G");
+ search(state.vars, "-debug-symbols", "1");
+ continue;
+ case 'S':
+ append(state.opt, " -S");
+ search(state.vars, "-strip-symbols", "1");
+ continue;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ if (error_info.errors)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ argv += opt_info.index;
+#else
+ while ((s = *++argv) && *s == '-')
+ {
+ if (*(s + 1) == '-')
+ {
+ if (!*(s + 2))
+ {
+ append(state.opt, " --");
+ argv++;
+ break;
+ }
+ for (t = s += 2; *t && *t != '='; t++);
+ if (!strncmp(s, "debug-symbols", t - s) && append(state.opt, " -G") || !strncmp(s, "strip-symbols", t - s) && append(state.opt, " -S"))
+ {
+ if (*t)
+ {
+ v = t + 1;
+ if (t > s && *(t - 1) == '+')
+ t--;
+ c = *t;
+ *t = 0;
+ }
+ else
+ {
+ c = 0;
+ v = "1";
+ }
+ search(state.vars, s - 1, v);
+ if (c)
+ *t = c;
+ continue;
+ }
+ usage();
+ break;
+ }
+ for (;;)
+ {
+ switch (*++s)
+ {
+ case 0:
+ break;
+ case 'e':
+ append(state.opt, " -e");
+ state.explain = 1;
+ continue;
+ case 'i':
+ append(state.opt, " -i");
+ state.ignore = 1;
+ continue;
+ case 'k':
+ append(state.opt, " -k");
+ state.keepgoing = 1;
+ continue;
+ case 'N':
+ state.never = 1;
+ /*FALLTHROUGH*/
+ case 'n':
+ append(state.opt, " -n");
+ state.exec = 0;
+ continue;
+ case 'F':
+ append(state.opt, " -F");
+ state.force = 1;
+ continue;
+ case 'G':
+ append(state.opt, " -G");
+ search(state.vars, "-debug-symbols", "1");
+ continue;
+ case 'K':
+ continue;
+ case 'S':
+ append(state.opt, " -S");
+ search(state.vars, "-strip-symbols", "1");
+ continue;
+ case 'V':
+ fprintf(stdout, "%s\n", id + 10);
+ exit(0);
+ case 'f':
+ case 'r':
+ case 'C':
+ case 'D':
+ t = s;
+ if (!*++s && !(s = *++argv))
+ {
+ report(2, "option value expected", t, (unsigned long)0);
+ usage();
+ }
+ else
+ switch (*t)
+ {
+ case 'f':
+ append(state.opt, " -f ");
+ append(state.opt, s);
+ state.file = s;
+ break;
+ case 'r':
+ state.recurse = s;
+ break;
+ case 'C':
+ state.directory = s;
+ break;
+ case 'D':
+ append(state.opt, " -D");
+ append(state.opt, s);
+ state.debug = -atoi(s);
+ break;
+ }
+ break;
+ default:
+ report(2, "unknown option", s, (unsigned long)0);
+ case '?':
+ usage();
+ break;
+ }
+ break;
+ }
+ }
+#endif
+
+ /*
+ * load the environment
+ */
+
+ for (e = environ; s = *e; e++)
+ for (t = s; *t; t++)
+ if (*t == '=')
+ {
+ *t = 0;
+ search(state.vars, s, t + 1);
+ *t = '=';
+ break;
+ }
+
+ /*
+ * grab the command line targets and variable definitions
+ */
+
+ while (s = *argv++)
+ {
+ for (t = s; *t; t++)
+ if (*t == '=')
+ {
+ v = t + 1;
+ if (t > s && *(t - 1) == '+')
+ t--;
+ c = *t;
+ *t = 0;
+ search(state.vars, s, v);
+ tmp = buffer();
+ append(tmp, s);
+ append(tmp, ".FORCE");
+ search(state.vars, use(tmp), v);
+ drop(tmp);
+ *t = c;
+ break;
+ }
+ if (!*t)
+ {
+ /*
+ * handle a few targets for nmake compatibility
+ */
+
+ if (*s == 'e' && !strncmp(s, "error 0 $(MAKEVERSION:", 22))
+ exit(1);
+ if (*s == 'r' && !strcmp(s, "recurse") || *s == 'c' && !strncmp(s, "cc-", 3))
+ continue;
+ rule(s)->flags |= RULE_active;
+ state.active = 0;
+ if (state.recurse)
+ continue;
+ }
+ add(state.opt, ' ');
+ add(state.opt, '\'');
+ append(state.opt, s);
+ add(state.opt, '\'');
+ }
+
+ /*
+ * initialize the views
+ */
+
+ if (state.directory && chdir(state.directory))
+ report(3, "cannot change working directory", NiL, (unsigned long)0);
+ view();
+
+ /*
+ * recursion drops out here
+ */
+
+ if (state.recurse)
+ return recurse(state.recurse);
+
+ /*
+ * read the mamfile(s) and bring the targets up to date
+ */
+
+ search(state.vars, "MAMAKEARGS", duplicate(use(state.opt) + 1));
+ push(state.file, (Stdio_t*)0, STREAM_MUST);
+ make(rule(""));
+ pop();
+
+ /*
+ * verify that active targets were made
+ */
+
+ if (!state.active && !state.verified)
+ walk(state.rules, verify, NiL);
+
+ /*
+ * done
+ */
+
+ return state.errors != 0;
+}
diff --git a/src/cmd/INIT/mamake.rt b/src/cmd/INIT/mamake.rt
new file mode 100644
index 0000000..5f7603d
--- /dev/null
+++ b/src/cmd/INIT/mamake.rt
@@ -0,0 +1,40 @@
+NOTE regression tests for the mamake command
+
+UNIT mamake
+
+TEST macros
+
+DATA Mamfile <<'!'
+info mam static 00000 1994-07-17 make (AT&T Research) 5.3 2009-05-05
+setv DEFINED defined
+setv EMPTY
+make all
+
+exec - echo DEFINED ${DEFINED}
+exec - echo DEFINED:VALUE ${DEFINED:VALUE}
+exec - echo DEFINED:-VALUE ${DEFINED:-VALUE}
+exec - echo DEFINED=VALUE ${DEFINED=VALUE}
+exec - echo DEFINED[VALUE] ${DEFINED[VALUE]}
+exec - echo DEFINED.COMPONENT ${DEFINED.COMPONENT}
+exec - echo DEFINED.COMPONENT[VALUE] ${DEFINED.COMPONENT[VALUE]}
+
+exec - echo EMPTY ${EMPTY}
+exec - echo EMPTY:VALUE ${EMPTY:VALUE}
+exec - echo EMPTY:-VALUE ${EMPTY:-VALUE}
+exec - echo EMPTY=VALUE ${EMPTY=VALUE}
+exec - echo EMPTY[VALUE] ${EMPTY[VALUE]}
+exec - echo EMPTY.COMPONENT ${EMPTY.COMPONENT}
+exec - echo EMPTY.COMPONENT[VALUE] ${EMPTY.COMPONENT[VALUE]}
+
+exec - echo __NoT_DeFiNeD__ ${__NoT_DeFiNeD__}
+exec - echo __NoT_DeFiNeD__:VALUE ${__NoT_DeFiNeD__:VALUE}
+exec - echo __NoT_DeFiNeD__:-VALUE ${__NoT_DeFiNeD__:-VALUE}
+exec - echo __NoT_DeFiNeD__=VALUE ${__NoT_DeFiNeD__=VALUE}
+exec - echo __NoT_DeFiNeD__[VALUE] ${__NoT_DeFiNeD__[VALUE]}
+exec - echo __NoT_DeFiNeD__.COMPONENT ${__NoT_DeFiNeD__.COMPONENT}
+exec - echo __NoT_DeFiNeD__.COMPONENT[VALUE] ${__NoT_DeFiNeD__.COMPONENT[VALUE]}
+
+done all generated virtual
+!
+
+EXEC -n
diff --git a/src/cmd/INIT/mamake.tst b/src/cmd/INIT/mamake.tst
new file mode 100644
index 0000000..3c7f94d
--- /dev/null
+++ b/src/cmd/INIT/mamake.tst
@@ -0,0 +1,63 @@
+# : : generated from mamake.rt by mktest : : #
+
+# regression tests for the mamake command
+
+UNIT mamake
+
+TEST 01 macros
+
+ EXEC -n
+ INPUT -n -
+ INPUT Mamfile $'info mam static 00000 1994-07-17 make (AT&T Research) 5.3 2009-05-05
+setv DEFINED defined
+setv EMPTY
+make all
+
+exec - echo DEFINED ${DEFINED}
+exec - echo DEFINED:VALUE ${DEFINED:VALUE}
+exec - echo DEFINED:-VALUE ${DEFINED:-VALUE}
+exec - echo DEFINED=VALUE ${DEFINED=VALUE}
+exec - echo DEFINED[VALUE] ${DEFINED[VALUE]}
+exec - echo DEFINED.COMPONENT ${DEFINED.COMPONENT}
+exec - echo DEFINED.COMPONENT[VALUE] ${DEFINED.COMPONENT[VALUE]}
+
+exec - echo EMPTY ${EMPTY}
+exec - echo EMPTY:VALUE ${EMPTY:VALUE}
+exec - echo EMPTY:-VALUE ${EMPTY:-VALUE}
+exec - echo EMPTY=VALUE ${EMPTY=VALUE}
+exec - echo EMPTY[VALUE] ${EMPTY[VALUE]}
+exec - echo EMPTY.COMPONENT ${EMPTY.COMPONENT}
+exec - echo EMPTY.COMPONENT[VALUE] ${EMPTY.COMPONENT[VALUE]}
+
+exec - echo __NoT_DeFiNeD__ ${__NoT_DeFiNeD__}
+exec - echo __NoT_DeFiNeD__:VALUE ${__NoT_DeFiNeD__:VALUE}
+exec - echo __NoT_DeFiNeD__:-VALUE ${__NoT_DeFiNeD__:-VALUE}
+exec - echo __NoT_DeFiNeD__=VALUE ${__NoT_DeFiNeD__=VALUE}
+exec - echo __NoT_DeFiNeD__[VALUE] ${__NoT_DeFiNeD__[VALUE]}
+exec - echo __NoT_DeFiNeD__.COMPONENT ${__NoT_DeFiNeD__.COMPONENT}
+exec - echo __NoT_DeFiNeD__.COMPONENT[VALUE] ${__NoT_DeFiNeD__.COMPONENT[VAL'\
+$'UE]}
+
+done all generated virtual'
+ OUTPUT - $'echo DEFINED defined
+echo DEFINED:VALUE
+echo DEFINED:-VALUE
+echo DEFINED=VALUE defined
+echo DEFINED[VALUE] ${DEFINED[VALUE]}
+echo DEFINED.COMPONENT
+echo DEFINED.COMPONENT[VALUE] ${DEFINED.COMPONENT[VALUE]}
+echo EMPTY
+echo EMPTY:VALUE ${EMPTY:VALUE}
+echo EMPTY:-VALUE ${EMPTY:-VALUE}
+echo EMPTY=VALUE
+echo EMPTY[VALUE] ${EMPTY[VALUE]}
+echo EMPTY.COMPONENT
+echo EMPTY.COMPONENT[VALUE] ${EMPTY.COMPONENT[VALUE]}
+echo __NoT_DeFiNeD__ ${__NoT_DeFiNeD__}
+echo __NoT_DeFiNeD__:VALUE ${__NoT_DeFiNeD__:VALUE}
+echo __NoT_DeFiNeD__:-VALUE ${__NoT_DeFiNeD__:-VALUE}
+echo __NoT_DeFiNeD__=VALUE ${__NoT_DeFiNeD__=VALUE}
+echo __NoT_DeFiNeD__[VALUE] ${__NoT_DeFiNeD__[VALUE]}
+echo __NoT_DeFiNeD__.COMPONENT
+echo __NoT_DeFiNeD__.COMPONENT[VALUE] ${__NoT_DeFiNeD__.COMPONENT[VALUE]}'
+ ERROR -n -
diff --git a/src/cmd/INIT/mamprobe.sh b/src/cmd/INIT/mamprobe.sh
new file mode 100644
index 0000000..6933bea
--- /dev/null
+++ b/src/cmd/INIT/mamprobe.sh
@@ -0,0 +1,267 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+### this script contains archaic constructs that work with all sh variants ###
+# mamprobe - generate MAM cc probe info
+# Glenn Fowler <gsf@research.att.com>
+
+case $-:$BASH_VERSION in
+*x*:[0123456789]*) : bash set -x is broken :; set +ex ;;
+esac
+
+command=mamprobe
+
+# check the options
+
+opt=
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) USAGE=$'
+[-?
+@(#)$Id: mamprobe (AT&T Labs Research) 2011-02-11 $
+]
+[+NAME?mamprobe - generate MAM cc probe info]
+[+DESCRIPTION?\bmamprobe\b generates MAM (make abstract machine) \bcc\b(1)
+ probe information for use by \bmamake\b(1). \acc-path\a is the
+ absolute path of the probed compiler and \ainfo-file\a is where
+ the information is placed. \ainfo-file\a is usually
+ \b$INSTALLROOT/lib/probe/C/mam/\b\ahash\a, where \ahash\a is a hash
+ of \acc-path\a. Any \ainfo-file\a directories are created if needed.
+ If \ainfo-file\a is \b-\b then the probe information is written to
+ the standard output.]
+[+?\bmamprobe\b and \bmamake\b are used in the bootstrap phase of
+ \bpackage\b(1) installation before \bnmake\b(1) is built. The
+ probed variable names are the \bnmake\b(1) names with a \bmam_\b
+ prefix, \bCC\b converted to \bcc\b, and \b.\b converted to \b_\b.
+ Additional variables are:]{
+ [+_hosttype_?the \bpackage\b(1) host type]
+ [+mam_cc_L?\b-L\b\adir\a supported]
+ [+STDCAT?command to execute for \bcat\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDCHMOD?command to execute for \bchmod\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDCMP?command to execute for \bcmp\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDCP?command to execute for \bcp\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDED?command to execute for \bed\b(1) or \bex\b(1)]
+ [+STDEDFLAGS?flags for \bSTDED\b]
+ [+STDLN?command to execute for \bln\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDMV?command to execute for \bmv\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+ [+STDRM?command to execute for \brm\b(1); prefixed by
+ \bexecrate\b(1) on \b.exe\b challenged systems]
+}
+[d:debug?Enable probe script debug trace.]
+
+info-file cc-path
+
+[+SEE ALSO?\bexecrate\b(1), \bpackage\b(1), \bmamake\b(1), \bnmake\b(1),
+ \bprobe\b(1)]
+'
+ while getopts -a "$command" "$USAGE" OPT
+ do case $OPT in
+ d) opt=-d ;;
+ esac
+ done
+ shift `expr $OPTIND - 1`
+ ;;
+*) while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ -) break
+ ;;
+ -d) opt=-d
+ ;;
+ -*) echo $command: $1: unknown option >&2
+ ;;
+ *) break
+ ;;
+ esac
+ set ''
+ break
+ done
+ ;;
+esac
+
+# check the args
+
+case $1 in
+-) ;;
+/*) ;;
+*) set '' ;;
+esac
+case $2 in
+/*) ;;
+*) set '' ;;
+esac
+case $# in
+0|1) echo "Usage: $command info-file cc-path" >&2; exit 2 ;;
+esac
+info=$1
+shift
+cc=$*
+
+# find the make probe script
+
+ifs=${IFS-'
+ '}
+IFS=:
+set $PATH
+IFS=$ifs
+script=lib/probe/C/make/probe
+while :
+do case $# in
+ 0) echo "$0: ../$script: probe script not found on PATH" >&2
+ exit 1
+ ;;
+ esac
+ case $1 in
+ '') continue ;;
+ esac
+ makeprobe=`echo $1 | sed 's,[^/]*$,'$script,`
+ if test -x $makeprobe
+ then break
+ fi
+ shift
+done
+
+# create the info dir if necessary
+
+case $info in
+/*) i=X$info
+ ifs=${IFS-'
+ '}
+ IFS=/
+ set $i
+ IFS=$ifs
+ while :
+ do i=$1
+ shift
+ case $i in
+ X) break ;;
+ esac
+ done
+ case $info in
+ //*) path=/ ;;
+ *) path= ;;
+ esac
+ while :
+ do case $# in
+ 0|1) break ;;
+ esac
+ comp=$1
+ shift
+ case $comp in
+ '') continue ;;
+ esac
+ path=$path/$comp
+ if test ! -d $path
+ then mkdir $path || exit
+ fi
+ done
+ ;;
+esac
+
+# generate info in a tmp file and rename when finished
+
+case $info in
+-) ;;
+*) tmp=/tmp/mam$$
+ trap "exec >/dev/null; rm -f $tmp" 0 1 2 3 15
+ exec > $tmp
+ echo "probing C language processor $cc for mam information" >&2
+ ;;
+esac
+
+echo "note generated by $0 for $cc"
+
+(
+ set '' $opt $cc
+ shift
+ . $makeprobe "$@"
+
+ case " $CC_DIALECT " in
+ *" -L "*) echo "CC.L = 1" ;;
+ esac
+
+) | sed \
+ -e '/^CC\./!d' \
+ -e 's/^CC./setv mam_cc_/' \
+ -e 's/^\([^=.]*\)\./\1_/' \
+ -e 's/^\([^=.]*\)\./\1_/' \
+ -e 's/ =//' \
+ -e 's/\$("\([^"]*\)")/\1/g' \
+ -e 's/\$(\([^)]*\))/${\1}/g' \
+ -e 's/\${CC\./${mam_cc_}/g'
+
+echo 'setv _hosttype_ ${mam_cc_HOSTTYPE}'
+
+# STD* are standard commands/flags with possible execrate(1)
+
+if (
+ed <<!
+q
+!
+) < /dev/null > /dev/null 2>&1
+then STDED=ed
+else STDED=ex
+fi
+STDEDFLAGS=-
+set STDCAT cat STDCHMOD chmod STDCMP cmp STDCP cp STDLN ln STDMV mv STDRM rm
+while :
+do case $# in
+ 0|1) break ;;
+ esac
+ p=$2
+ for d in /bin /usr/bin /usr/sbin
+ do if test -x $d/$p
+ then p=$d/$p
+ break
+ fi
+ done
+ eval $1=\$p
+ shift
+ shift
+done
+if execrate
+then for n in STDCAT STDCHMOD STDCMP STDCP STDLN STDMV STDRM
+ do eval $n=\"execrate \$$n\"
+ done
+fi
+for n in STDCAT STDCHMOD STDCMP STDCP STDED STDEDFLAGS STDLN STDMV STDRM
+do eval echo setv \$n \$$n
+done
+
+# all done
+
+case $info in
+-) ;;
+*) exec >/dev/null
+ test -f $info && rm -f $info
+ cp $tmp $info
+ chmod -w $info
+ ;;
+esac
diff --git a/src/cmd/INIT/mkdir.sh b/src/cmd/INIT/mkdir.sh
new file mode 100644
index 0000000..c929e95
--- /dev/null
+++ b/src/cmd/INIT/mkdir.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: mkdir for systems that do not support -p : 2002-09-01 :
+MKDIR=/bin/mkdir
+CHMOD=chmod
+mode=
+parents=
+while :
+do case $1 in
+ -m) case $# in
+ 1) echo "mkdir: -m: mode argument expected" >&2
+ exit 1
+ ;;
+ esac
+ shift
+ mode=$1
+ ;;
+ -m*) mode=`echo X$1 | sed 's/X-m//'`
+ ;;
+ -p) parents=1
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+done
+if test "" != "$parents"
+then for d
+ do if test ! -d $d
+ then ifs=${IFS-'
+ '}
+ IFS=/
+ set '' $d
+ IFS=$ifs
+ shift
+ dir=$1
+ shift
+ if test -n "$dir" -a ! -d "$dir"
+ then $MKDIR "$dir" || exit 1
+ if test "" != "$mode"
+ then $CHMOD "$mode" "$dir" || exit 1
+ fi
+ fi
+ for d
+ do dir=$dir/$d
+ if test ! -d "$dir"
+ then $MKDIR "$dir" || exit 1
+ if test "" != "$mode"
+ then $CHMOD "$mode" "$dir" || exit 1
+ fi
+ fi
+ done
+ fi
+ done
+else $MKDIR "$@" || exit 1
+ if test "" != "$mode"
+ then for d
+ do $CHMOD "$mode" "$d" || exit 1
+ done
+ fi
+fi
+exit 0
diff --git a/src/cmd/INIT/mktest.sh b/src/cmd/INIT/mktest.sh
new file mode 100755
index 0000000..f24183e
--- /dev/null
+++ b/src/cmd/INIT/mktest.sh
@@ -0,0 +1,641 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: mktest - generate regress or shell regression test scripts
+
+command=mktest
+stdin=8
+stdout=9
+PREFIX=test
+STYLE=regress
+WIDTH=80
+
+eval "exec $stdout>&1"
+
+case $(getopts '[-][123:xyz]' opt --xyz 2>/dev/null; echo 0$opt) in
+0123) ARGV0="-a $command"
+ USAGE=$'
+[-?
+@(#)$Id: mktest (AT&T Labs Research) 2010-08-11 $
+]
+'$USAGE_LICENSE$'
+[+NAME?mktest - generate a regression test scripts]
+[+DESCRIPTION?\bmktest\b generates regression test scripts from test
+ template commands in the \aunit\a.\brt\b file. The generated test
+ script writes temporary output to '$PREFIX$'\aunit\a.tmp and compares
+ it to the expected output in '$PREFIX$'\aunit\a.out. Run the test
+ script with the \b--accept\b option to (re)generate the
+ '$PREFIX$'\aunit\a.out.]
+[s:style?The script style:]:[style:='$STYLE$']
+ {
+ [+regress?\bregress\b(1) command input.]
+ [+shell?Standalone test shell script.]
+ }
+[w:width?Set the output format width to approximately
+ \awidth\a.]:[width:='$WIDTH$']
+
+unit.rt [ unit [ arg ... ] ]
+
+[+INPUT FILES?The regression test command file \aunit\a\b.rt\b is a
+ \bksh\b(1) script that makes calls to the following functions:]
+ {
+ [+DATA \afile\a [ - | [ options ]] data]]?Create input data
+ \afile\a that is empty (-) or contains \adata\a subject to
+ \bprint\b(1) \aoptions\a or that is a copy of the DATA command
+ standard input. Set \afile\a to \b-\b to name the standard
+ input.]
+ [+DIAGNOSTICS?Diagnostic messages of unspecified format are
+ expected.]
+ [+DO \acommand\a [ \aarg\a ... ]]?Execute \acommand\a if the
+ current test is active.]
+ [+EXEC [ \aarg\a ... ]]?Run the command under test with
+ optional arguments. If the standard input is not specified then
+ the standard input of the previous EXEC is used. The standard
+ input of the first EXEC in a TEST group is an empty regular
+ file.]
+ [+EXPORT \aname\a=\avalue\a ...?Export list for subsequent
+ commands in the TEST group or for all TEST groups if before
+ the first TEST group.]
+ [+IGNORESPACE [ 0 | 1 ]
+ ?Ignore space differences when comparing expected output.]
+ [+KEEP \apattern\a ...?File match patterns of files to retain
+ between TEST groups.]
+ [+NOTE \acomment\a?\acomment\a is added to the current test
+ script.]
+ [+PROG \acommand\a [ \aarg\a ... ]]?Run \acommand\a with
+ optional arguments.]
+ [+TEST [ \anumber\a ]] [ \adescription\a ... ]]?Define a new
+ test group with optional \anumber\a and \adescripion\a.]
+ [+TWD [ \adir\a ... ]]?Set the temporary test dir to \adir\a.
+ The default is \aunit\a\b.tmp\b, where \aunit\a is the test
+ input file sans directory and suffix. If \adir\a matches \b/*\b
+ then it is the directory name; if \adir\a is non-null then the
+ prefix \b${TMPDIR:-/tmp}\b is added; otherwise if \adir\a is
+ omitted then
+ \b${TMPDIR:-/tmp}/tst-\b\aunit\a-$$-$RANDOM.\b\aunit\a is
+ used.]
+ [+UMASK [ \amask\a ]]?Run subsequent tests with \bumask\b(1)
+ \amask\a. If \amask\a is omitted then the original \bumask\b is
+ used.]
+ [+UNIT \acommand\a [ \aarg\a ... ]]?Define the command and
+ optional default arguments to be tested. \bUNIT\b explicitly
+ overrides the default command name derived from the test script
+ file name.]
+ [+WIDTH \awidth\a?Set the output format width to approximately
+ \awidth\a.]
+ }
+[+SEE ALSO?\bregress\b(1), \bksh\b(1)]
+'
+ ;;
+*) ARGV0=""
+ USAGE='s: unit.rt [ arg ... ]'
+ ;;
+esac
+
+typeset ARG SCRIPT UNIT TEMP=${TMPDIR:-/tmp}/$command.$$.tmp WORK
+typeset IO INPUT INPUT_N OUTPUT OUTPUT_N ERROR ERROR_N KEEP
+typeset -C STATE
+typeset -A DATA STATE.RESET REMOVE FORMAT
+integer KEEP_UNIT=0 SCRIPT_UNIT=0 TEST=0 CODE=0 EXIT=0 ACCEPT=0 DIAGNOSTICS=0 code
+
+while getopts $ARGV0 "$USAGE" OPT
+do case $OPT in
+ s) case $OPTARG in
+ regress|shell)
+ STYLE=$OPTARG
+ ;;
+ *) print -u2 -r -- $command: --style=$OPTARG: regress or shell expected
+ exit 1
+ ;;
+ esac
+ ;;
+ w) WIDTH=$OPTARG
+ ;;
+ *) OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+ ;;
+ esac
+done
+shift $OPTIND-1
+
+typeset SINGLE= quote='%${SINGLE}..${WIDTH}q'
+
+if [[ $1 == - ]]
+then shift
+fi
+if (( ! $# ))
+then
+ print -u2 -r -- $command: test command script path expected
+ exit 1
+fi
+SCRIPT=$1
+shift
+if [[ ! -r $SCRIPT ]]
+then print -u2 -r -- $command: $SCRIPT: cannot read
+ exit 1
+fi
+(ulimit -c 0) >/dev/null 2>&1 && ulimit -c 0
+if (( $# ))
+then set -A UNIT -- "$@"
+ KEEP_UNIT=1
+else ARG=${SCRIPT##*/}
+ set -A UNIT -- "${ARG%.*}"
+fi
+WORK=${UNIT[0]}.tmp
+rm -rf $WORK
+mkdir $WORK || exit
+export PATH=$PWD:$PATH
+
+function LINE
+{
+ if [[ $STYLE == regress ]]
+ then print -u$stdout
+ fi
+}
+
+function NOTE
+{
+ case $STYLE in
+ regress)LINE
+ print -u$stdout -r -- '#' "$@"
+ ;;
+ shell) print -u$stdout -r -f ": $QUOTE"$'\n' -- "$*"
+ ;;
+ esac
+}
+
+function UNIT
+{
+ (( KEEP_UNIT )) || set -A UNIT -- "$@"
+ case $STYLE in
+ regress)LINE
+ print -u$stdout -r -f $'UNIT'
+ for ARG in "$@"
+ do print -u$stdout -r -f " $QUOTE" -- "$ARG"
+ done
+ print -u$stdout
+ ;;
+ shell) print -u$stdout -r -f $'set x'
+ for ARG in "$@"
+ do print -u$stdout -r -f " $QUOTE" -- "$ARG"
+ done
+ print -u$stdout
+ print -u$stdout shift
+ ;;
+ esac
+}
+
+function TEST
+{
+ typeset i
+ typeset -A REM
+ if (( ${#STATE.RESET[@]} ))
+ then unset ${!STATE.RESET[@]}
+ case $STYLE in
+ shell) print -u$stdout -r -- unset ${!STATE.RESET[@]} ;;
+ esac
+ unset STATE.RESET
+ typeset -A STATE.RESET
+ fi
+ if (( ${#REMOVE[@]} ))
+ then rm -f -- "${!REMOVE[@]}"
+ case $STYLE in
+ shell) print -u$stdout -r -f $'rm -f'
+ for i in ${!REMOVE[@]}
+ do print -u$stdout -r -f " $QUOTE" "$i"
+ done
+ print -u$stdout
+ ;;
+ esac
+ for i in ${!REMOVE[@]}
+ do unset REMOVE[$i]
+ done
+ fi
+ rm -rf $WORK/*
+ if [[ $1 == +([0-9]) ]]
+ then TEST=${1##0}
+ shift
+ else ((TEST++))
+ fi
+ LINE
+ case $STYLE in
+ regress)print -u$stdout -r -f "TEST %02d $QUOTE"$'\n' -- $TEST "$*"
+ ;;
+ shell) print -u$stdout -r -f ": TEST %02d $QUOTE"$'\n' -- $TEST "$*"
+ ;;
+ esac
+ : > $TEMP.INPUT > $TEMP.in
+ INPUT=
+ INPUT_N=
+ OUTPUT=
+ OUTPUT_N=
+ ERROR=
+ ERROR_N=
+ UMASK=$UMASK_ORIG
+ UMASK_DONE=$UMASK
+ CODE=0
+}
+
+function TWD
+{
+ case $STYLE in
+ regress)LINE
+ print -u$stdout -r -f $'TWD'
+ for ARG in "$@"
+ do print -u$stdout -r -f " $QUOTE" -- "$ARG"
+ done
+ print -u$stdout
+ ;;
+ esac
+}
+
+function RUN
+{
+ typeset i n p op unit sep output=1 error=1 exitcode=1
+ op=$1
+ shift
+ while :
+ do case $1 in
+ ++NOOUTPUT) output= ;;
+ ++NOERROR) error= ;;
+ ++NOEXIT) exitcode= ;;
+ ++*) print -u2 -r -- $command: $0: $1: unknown option; exit 1 ;;
+ *) break ;;
+ esac
+ shift
+ done
+ if [[ $op == PROG ]]
+ then unit=$1
+ shift
+ elif (( ! ${#UNIT[@]} ))
+ then print -u2 -r -- $command: $SCRIPT: UNIT statement or operand expected
+ exit 1
+ fi
+ LINE
+ case $STYLE in
+ regress)if [[ $op == PROG ]]
+ then print -u$stdout -r -f $'\t'"$op"$'\t'"$unit"
+ sep=$' '
+ else print -u$stdout -r -f $'\t'"$op"
+ sep=$'\t'
+ fi
+ for ARG in "$@"
+ do LC_CTYPE=C print -u$stdout -r -f "$sep$QUOTE" -- "$ARG"
+ sep=$' '
+ done
+ print -u$stdout
+ [[ ${DATA[-]} || /dev/fd/0 -ef /dev/fd/$stdin ]] || cat > $TEMP.in
+ IO=$(cat $TEMP.in; print :)
+ if [[ $IO == ?*$'\n:' ]]
+ then IO=${IO%??}
+ n=
+ else IO=${IO%?}
+ n=-n
+ fi
+ {
+ [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK
+ cd $WORK
+ if [[ $op == PROG ]]
+ then "$unit" "$@"
+ code=$?
+ else "${UNIT[@]}" "$@"
+ code=$?
+ fi
+ cd ..
+ [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG
+ } < $TEMP.in > $TEMP.out 2> $TEMP.err
+ if [[ $IO != "$INPUT" || $n != "$INPUT_N" ]]
+ then INPUT=$IO
+ INPUT_N=$n
+ if [[ ${FORMAT[-]} ]]
+ then print -u$stdout -n -r -- $'\t\tINPUT'
+ print -u$stdout -r -f " $QUOTE" -- "${FORMAT[-]}"
+ print -u$stdout -r -f " $QUOTE" -- -
+ unset FORMAT[-]
+ else print -u$stdout -n -r -- $'\t\tINPUT' $n -
+ [[ $IO ]] && LC_CTYPE=C print -u$stdout -r -f " $QUOTE" -- "$IO"
+ fi
+ print -u$stdout
+ unset DATA[-]
+ fi
+ for i in ${!DATA[@]}
+ do if [[ ${FORMAT[$i]} ]]
+ then print -u$stdout -n -r -- $'\t\tINPUT'
+ print -u$stdout -r -f " $QUOTE" -- "${FORMAT[$i]}"
+ print -u$stdout -r -f " $QUOTE" -- "$i"
+ unset FORMAT[$i]
+ else case $i in
+ -) p=$TEMP.in ;;
+ *) p=$WORK/$i ;;
+ esac
+ IO=$(cat $p; print :)
+ if [[ $IO == ?*$'\n:' ]]
+ then IO=${IO%??}
+ n=
+ else IO=${IO%?}
+ n=-n
+ fi
+ print -u$stdout -n -r -- $'\t\tINPUT' $n
+ print -u$stdout -r -f " $QUOTE" -- "$i"
+ [[ $IO ]] && LC_CTYPE=C print -u$stdout -r -f " $QUOTE" -- "$IO"
+ fi
+ print -u$stdout
+ unset DATA[$i]
+ done
+ IO=$(cat $TEMP.out; print :)
+ if [[ $IO == ?*$'\n:' ]]
+ then IO=${IO%??}
+ n=
+ else IO=${IO%?}
+ n=-n
+ fi
+ if [[ $IO != "$OUTPUT" || $n != "$OUTPUT_N" ]]
+ then OUTPUT=$IO
+ OUTPUT_N=$n
+ if [[ $output ]]
+ then if [[ ! -s $TEMP.out ]]
+ then print -u$stdout -n -r -- $'\t\tOUTPUT' -
+ elif cmp -s $TEMP.in $TEMP.out
+ then OUTPUT=not-$OUTPUT
+ print -u$stdout -n -r -- $'\t\tSAME OUTPUT INPUT'
+ else print -u$stdout -n -r -- $'\t\tOUTPUT' $n -
+ [[ $IO ]] && LC_CTYPE=C print -u$stdout -r -f " $QUOTE" -- "$IO"
+ fi
+ print -u$stdout
+ fi
+ fi
+ IO=$(cat $TEMP.err; print :)
+ IO=${IO//$command\[*([0-9])\]:\ .\[*([0-9])\]:\ @(EXEC|PROG)\[*([0-9])\]:\ /}
+ if [[ $IO == ?*$'\n:' ]]
+ then IO=${IO%??}
+ n=
+ else IO=${IO%?}
+ n=-n
+ fi
+ if [[ $IO != "$ERROR" || $n != "$ERROR_N" ]]
+ then ERROR=$IO
+ ERROR_N=$n
+ if [[ $error ]]
+ then print -u$stdout -n -r -- $'\t\tERROR' $n -
+ [[ $IO ]] && LC_CTYPE=C print -u$stdout -r -f " $QUOTE" -- "$IO"
+ print -u$stdout
+ fi
+ fi
+ case $output:$error in
+ :) OUTPUT=
+ OUTPUT_N=
+ ERROR=
+ ERROR_N=
+ print -u$stdout -r -- $'\t\tIGNORE OUTPUT ERROR'
+ ;;
+ :1) OUTPUT=
+ OUTPUT_N=
+ print -u$stdout -r -- $'\t\tIGNORE OUTPUT'
+ ;;
+ 1:) ERROR=
+ ERROR_N=
+ print -u$stdout -r -- $'\t\tIGNORE ERROR'
+ ;;
+ esac
+ if [[ $UMASK_DONE != $UMASK ]]
+ then UMASK_DONE=$UMASK
+ print -u$stdout -r -f $'\t\tUMASK %s\n' $UMASK
+ fi
+ if (( code != CODE ))
+ then (( CODE=code ))
+ if [[ $exitcode ]]
+ then print -u$stdout -r -f $'\t\tEXIT %d\n' $CODE
+ fi
+ fi
+ ;;
+ shell) [[ $UMASK != $UMASK_ORIG ]] && print -u$stdout -r -f "{ umask $UMASK; "
+ if [[ $op == PROG ]]
+ then print -u$stdout -r -f $'"'"$unit"$'"'
+ else print -u$stdout -r -f $'"$@"'
+ fi
+ for ARG in "$@"
+ do print -u$stdout -r -f " $QUOTE" -- "$ARG"
+ done
+ [[ $UMASK != $UMASK_ORIG ]] && print -u$stdout -r -f "umask $UMASK_ORIG; } "
+ if [[ ! $output ]]
+ then print -u$stdout -r -f " >/dev/null"
+ fi
+ if [[ ! $error ]]
+ then if [[ ! $output ]]
+ then print -u$stdout -r -f " 2>&1"
+ else print -u$stdout -r -f " 2>/dev/null"
+ fi
+ fi
+ IO=$(cat)
+ if [[ $IO ]]
+ then print -u$stdout -r -- "<<'!TEST-INPUT!'"
+ print -u$stdout -r -- "$IO"
+ print -u$stdout -r -- !TEST-INPUT!
+ else print -u$stdout
+ fi
+ if [[ $exitcode ]]
+ then print -u$stdout -r -- $'CODE=$?\ncase $CODE in\n0) ;;\n*) echo exit status $CODE ;;\nesac'
+ fi
+ ;;
+ esac
+}
+
+function DO
+{
+ LINE
+ print -r $'\t'DO "$@"
+}
+
+function EXEC
+{
+ RUN EXEC "$@"
+}
+
+function DATA
+{
+ typeset f p o
+ f=$1
+ shift
+ case $f in
+ -) p=$TEMP.in ;;
+ *) p=$WORK/$f ;;
+ esac
+ case $1 in
+ '') cat ;;
+ -) ;;
+ *) print -r "$@" ;;
+ esac > $p
+ DATA[$f]=1
+ if (( $# == 1 )) && [[ $1 == -?* ]]
+ then FORMAT[$f]=$1
+ else FORMAT[$f]=
+ fi
+ if [[ $f != $KEEP ]]
+ then REMOVE[$f]=1
+ fi
+ if [[ $STYLE == shell ]]
+ then {
+ print -r -f "cat > $QUOTE <<'!TEST-INPUT!'"$'\n' -- "$f"
+ cat "$p"
+ print -r -- !TEST-INPUT!
+ } >&$stdout
+ fi
+}
+
+function KEEP
+{
+ typeset p
+ for p
+ do if [[ $KEEP ]]
+ then KEEP=$KEEP'|'
+ fi
+ KEEP=$KEEP$p
+ done
+}
+
+function DIAGNOSTICS
+{
+ LINE
+ case $STYLE in
+ regress) print -u$stdout -r $'DIAGNOSTICS' ;;
+ shell) DIAGNOSTICS=1 ;;
+ esac
+}
+
+function EXPORT
+{
+ typeset x n v
+ LINE
+ case $STYLE in
+ regress) print -u$stdout -r -f $'EXPORT' ;;
+ shell) print -u$stdout -r -f $'export' ;;
+ esac
+ for x
+ do n=${x%%=*}
+ v=${x#*=}
+ export "$x"
+ print -u$stdout -r -f " %s=$QUOTE" "$n" "$v"
+ (( TEST )) && STATE.RESET["$n"]=1
+ done
+ print -u$stdout
+}
+
+function PROG
+{
+ RUN PROG "$@"
+}
+
+function WIDTH
+{
+ WIDTH=${1:-80}
+ eval QUOTE='"'$quote'"'
+}
+
+function IGNORESPACE
+{
+ IGNORESPACE=-b
+ LINE
+ print -u$stdout -r IGNORESPACE
+}
+
+function UMASK # [ mask ]
+{
+ [[ $UMASK_ORIG ]] || UMASK_ORIG=$(umask)
+ UMASK=$1
+ [[ $UMASK ]] || UMASK=$UMASK_ORIG
+}
+
+trap 'CODE=$?; rm -rf $TEMP.* $WORK; exit $CODE' 0 1 2 3 15
+
+typeset IGNORESPACE UMASK UMASK_ORIG UMASK_DONE
+UMASK_ORIG=$(umask)
+IFS=$IFS$'\n'
+
+print -u$stdout -r "# : : generated from $SCRIPT by $command : : #"
+case $STYLE in
+shell) cat <<!
+ACCEPT=0
+while :
+do case \$1 in
+ -a|--accept)
+ ACCEPT=1
+ ;;
+ --help|--man)
+ cat 1>&2 <<!!
+Usage: \\\$SHELL $PREFIX${UNIT[0]}.sh [ --accept ] [ unit ... ]
+
+${UNIT[0]} regression test script. Run this script to generate new
+results in $PREFIX${UNIT[0]}.tmp and compare with expected results in
+$PREFIX${UNIT[0]}.out. The --accept option generates $PREFIX${UNIT[0]}.tmp
+and moves it to $PREFIX${UNIT[0]}.out.
+!!
+ exit 2
+ ;;
+ -*) echo \$0: \$1: invalid option >&2
+ exit 1
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+done
+export COLUMNS=80
+{
+!
+ ;;
+esac
+
+export COLUMNS=80
+
+case $STYLE in
+shell) SINGLE='#'
+ eval QUOTE='"'$quote'"'
+ . $SCRIPT < /dev/null | sed -e $'s,\\\\n,\n,g' -e $'s,\\\\t,\t,g' -e $'s,\\$\',\',g'
+ ;;
+*) eval QUOTE='"'$quote'"'
+ : > $TEMP.INPUT > $TEMP.in
+ eval "exec $stdin<$TEMP.INPUT"
+ . $SCRIPT <&$stdin
+ ;;
+esac
+
+case $STYLE in
+shell) cat <<!
+} > $PREFIX${UNIT[0]}.tmp 2>&1 < /dev/null
+case \$ACCEPT in
+0) if grep ' $' $PREFIX${UNIT[0]}.tmp >/dev/null
+ then mv $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.junk
+ sed 's/ $//' < $PREFIX${UNIT[0]}.junk > $PREFIX${UNIT[0]}.tmp
+ rm -f $PREFIX${UNIT[0]}.junk
+ fi
+ if cmp -s $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.out
+ then echo ${UNIT[0]} tests PASSED
+ rm -f $PREFIX${UNIT[0]}.tmp
+ else echo ${UNIT[0]} tests FAILED
+ diff $IGNORESPACE $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.out
+ fi
+ ;;
+
+*) mv $PREFIX${UNIT[0]}.tmp $PREFIX${UNIT[0]}.out
+ ;;
+esac
+!
+ ;;
+esac
diff --git a/src/cmd/INIT/mprobe.sh b/src/cmd/INIT/mprobe.sh
new file mode 100644
index 0000000..975ebb1
--- /dev/null
+++ b/src/cmd/INIT/mprobe.sh
@@ -0,0 +1,30 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: mam probe script
+opt=
+while :
+do case $1 in
+ -d) opt=-d ;;
+ -*) ;;
+ *) break ;;
+ esac
+ shift
+done
+mamprobe $opt - "$1"
diff --git a/src/cmd/INIT/nsl.c b/src/cmd/INIT/nsl.c
new file mode 100644
index 0000000..e961e01
--- /dev/null
+++ b/src/cmd/INIT/nsl.c
@@ -0,0 +1,31 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for -lnsl
+ */
+
+
+extern void* gethostbyname();
+
+int
+main()
+{
+ return gethostbyname(0) == 0;
+}
diff --git a/src/cmd/INIT/p.c b/src/cmd/INIT/p.c
new file mode 100644
index 0000000..387c4bb
--- /dev/null
+++ b/src/cmd/INIT/p.c
@@ -0,0 +1,24 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for prototyping cc
+ */
+
+int main(int argc, char** argv) { return argc || argv; }
diff --git a/src/cmd/INIT/package.mk b/src/cmd/INIT/package.mk
new file mode 100644
index 0000000..921fa2d
--- /dev/null
+++ b/src/cmd/INIT/package.mk
@@ -0,0 +1,1537 @@
+/*
+ * source and binary package support
+ *
+ * @(#)package.mk (AT&T Research) 2012-02-14
+ *
+ * usage:
+ *
+ * cd $INSTALLROOT/lib/package
+ * nmake -f name [closure] [cyg|exp|lcl|pkg|rpm|tgz] [base|delta] type
+ *
+ * where:
+ *
+ * name package description file or component
+ *
+ * type source build source archive, generates
+ * $(PACKAGEDIR)/name.version.release.suffix
+ * binary build binary archive, generates
+ * $(PACKAGEDIR)/name.version.hosttype.release.suffix
+ * runtime build binary archive, generates
+ * $(PACKAGEDIR)/name-run.version.hosttype.release.suffix
+ *
+ * NOTE: $(PACKAGEDIR) is in the lowest view and is shared among all views
+ *
+ * generated archive member files are $(PACKAGEROOT) relative
+ *
+ * main assertions:
+ *
+ * NAME [ name=value ] :PACKAGE: component ...
+ * :OMIT: component ...
+ * :LICENSE: license-class-pattern
+ * :CATEGORY: category-id ...
+ * :COVERS: package ...
+ * :REQURES: package ...
+ * :INDEX: index description line
+ * :DESCRIPTION:
+ * [ verbose description ]
+ * :DETAILS: style
+ * :README:
+ * readme lines
+ * :EXPORT:
+ * name=value
+ * target :INSTALL: [ source ]
+ *
+ * option variables, shown with default values
+ *
+ * format=tgz
+ * archive format
+ *
+ * version=YYYY-MM-DD
+ * package base version (overrides current date)
+ *
+ * release=YYYY-MM-DD
+ * package delta release (overrides current date)
+ *
+ * license=type.class
+ * :LICENSE: type.class pattern override
+ *
+ * notice=1
+ * include the conspicuous empty notice file
+ *
+ * copyright=0
+ * do not prepend source file copyright notice
+ *
+ * strip=0
+ * don't strip non-lcl binary package members
+ *
+ * variants=pattern
+ * include variants matching pattern in binary packages
+ *
+ * incremental=[source:1 binary:0]
+ * if a base archive is generated then also generate an
+ * incremental delta archive from the previous base
+ *
+ * NOTE: the Makerules.mk :PACKAGE: operator defers to :package: when
+ * a target is specified
+ */
+
+/* these are ast centric -- we'll parameterize another day */
+
+org = ast
+url = http://www.research.att.com/sw/download
+
+/* generic defaults */
+
+base =
+category = utils
+checksum = md5
+closure =
+copyright = 1
+delta =
+format = tgz
+incremental =
+index =
+init = INIT
+license =
+licenses = $(org)
+mamfile = 1
+opt =
+name =
+notice =
+release =
+strip = 0
+style = tgz
+suffix = tgz
+type =
+variants = !(cc-g)
+vendor =
+version = $("":T=R%Y-%m-%d)
+
+SUM = sum
+
+package.notice = ------------ NOTICE -- LICENSED SOFTWARE -- SEE README FOR DETAILS ------------
+
+package.readme = $(@.package.readme.)
+
+.package.readme. :
+ This is a package root directory $PACKAGEROOT. Source and binary
+ packages in this directory tree are controlled by the command
+ $()
+ bin/package
+ $()
+ Binary files may be in this directory or in the install root directory
+ $()
+ INSTALLROOT=$PACKAGEROOT/arch/`bin/package`
+ $()
+ For more information run
+ $()
+ bin/package help
+ $()
+ Many of the packaged commands self-document via the --man and --html
+ options; those that do have no separate man page.
+ $()
+ Each package is covered by one of the license files
+ $()
+ $(PACKAGELIB)/LICENSES/<license>
+ $()
+ where <license> is the license type for the package. At the top
+ of each license file is a URL; the license covers all software that
+ refers to this URL. For details run
+ $()
+ bin/package license [<package>]
+ $()
+ Any archives, distributions or packages made from source or
+ binaries covered by license(s) must contain the corresponding
+ license file(s)$(notice:?, this README file, and the empty file$$("\n")$$(package.notice)?.?)
+
+.package.licenses. : .FUNCTION
+ local I F L R T all save text
+ L := $(%)
+ while L == "--*"
+ I := $(L:O=1)
+ if I == "--all"
+ all = 1
+ elif I == "--save"
+ save = 1
+ elif I == "--text"
+ text = 1
+ end
+ L := $(L:O>1)
+ end
+ if "$(L)" == "*-*"
+ L += $(L:/[^-]*-//) $(L:/-.*//)
+ end
+ L += $(licenses)
+ for I $(L:U)
+ if I == "gpl"
+ I = gnu
+ all =
+ end
+ if F = "$(I:D=$(PACKAGESRC):B:S=.lic:T=F)"
+ R += $(F)
+ if save || text
+ T := $(.FIND. lib/package .lic $(F):P=W,query=type)
+ R += $(T:D=$(PACKAGESRC)/LICENSES:B)
+ end
+ if save
+ R += $(F:T=I:N=*.def:D=$(PACKAGESRC):B:S:T=F)
+ elif ! all
+ break
+ end
+ end
+ end
+ return $(R)
+
+/*
+ * glob(3) doesn't handle / in alternation -- should it?
+ */
+
+.package.glob. : .FUNCTION
+ local A D I P S
+ for I $(%)
+ if I == "*/*"
+ D := $(I:C,/.*,,)
+ if ! "$(A:N=$(D))"
+ local S.$(D)
+ A += $(D)
+ end
+ S.$(D) += $(I:C,[^/]*/,,)
+ else
+ P := $(P)$(S)$(I)
+ end
+ S = |
+ end
+ if P == "*\|*"
+ P := ($(P))
+ end
+ for I $(A)
+ P += $(I)/$(.package.glob. $(S.$(I)))
+ end
+ return $(P)
+
+
+.MAKEINIT : .package.init
+
+.package.init : .MAKE .VIRTUAL .FORCE
+ local V
+ V := $(VROOT:T=F:P=L*)
+ if ! PACKAGEROOT
+ PACKAGEROOT := $(V:N!=*/arch/+([!/]):O=1)
+ end
+ if V == "$(PACKAGEROOT)"
+ V :=
+ end
+ V += $(INSTALLROOT) $(PACKAGEROOT)
+ PACKAGEVIEW := $(V:H=RU)
+ INSTALLOFFSET := $(INSTALLROOT:C%$(PACKAGEROOT)/%%)
+ if license
+ license := $(license)|none.none
+ end
+
+PACKAGELIB = lib/package
+PACKAGESRC = $(PACKAGEROOT)/$(PACKAGELIB)
+PACKAGEBIN = $(INSTALLROOT)/$(PACKAGELIB)
+PACKAGEDIR = $(PACKAGESRC)/$(style)
+INSTALLOFFSET = $(INSTALLROOT:C%$(PACKAGEROOT)/%%)
+
+package.omit = -|*/$(init)
+package.glob.all = $(INSTALLROOT)/src/*/*/($(MAKEFILES:/:/|/G))
+package.all = $(package.glob.all:P=G:W=O=$(?$(name):A=.VIRTUAL):N!=$(package.omit):T=F:$(PACKAGEVIEW:C,.*,C;^&/;;,:/ /:/G):U)
+package.glob.pkg = $(.package.glob. $(~$(name):P=U):C%.*%$(INSTALLROOT)/src/*/&/($(MAKEFILES:/:/|/G))%) $(~$(name):P=U:N=$(name):?$$(INSTALLROOT)/src/$$(name)/($$(MAKEFILES:/:/|/G))??)
+package.pkg = $(package.glob.pkg:P=G:D:N!=$(package.omit):T=F:$(PACKAGEVIEW:C,.*,C;^&/;;,:/ /:/G):U)
+package.closure = $(closure:?$$(package.all)?$$(package.pkg)?)
+
+package.init = $(.package.glob. $("$(init)$(name)":P=U):C%.*%$(INSTALLROOT)/src/*/&/($(MAKEFILES:/:/|/G))%:P=G:T=F:D::B)
+package.ini = ignore mamprobe manmake package silent
+package.src.pat = $(PACKAGESRC)/($(name).(ini|pkg))
+package.src = $(package.src.pat:P=G) $(.package.licenses. --save $(name))
+package.bin = $(PACKAGEBIN)/$(name).ini
+
+package.mam = --never --force --mam=static --corrupt=accept --clobber --compare --link='lib*.a*' CC=$(CC.DIALECT:N=C++:?CC?cc?) package.license.class=$(license:Q) $(=) 'dontcare test' install test
+
+op = current
+stamp = [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]
+source = $(PACKAGEDIR)/$(name).$(version)$(release:?.$(release)??).$(suffix)
+binary = $(PACKAGEDIR)/$(name).$(version)$(release:?.$(release)??).$(CC.HOSTTYPE).$(suffix)
+runtime = $(PACKAGEDIR)/$(name)-run.$(version)$(release:?.$(release)??).$(CC.HOSTTYPE).$(suffix)
+old.new.source = $(PACKAGEDIR)/$(name).$(version).$(old.version).$(suffix)
+old.new.binary = $(PACKAGEDIR)/$(name).$(version).$(old.version).$(CC.HOSTTYPE).$(suffix)
+old.new.runtime = $(PACKAGEDIR)/$(name)-run.$(version).$(old.version).$(CC.HOSTTYPE).$(suffix)
+
+source.list = $("$(PACKAGEDIR)/$(name).*$(stamp).$(suffix)":P=G:H=R)
+binary.list = $("$(PACKAGEDIR)/$(name).*$(stamp).$(CC.HOSTTYPE).$(suffix)":P=G:H=R)
+runtime.list = $("$(PACKAGEDIR)/$(name)-run.*$(stamp).$(CC.HOSTTYPE).$(suffix)":P=G:H>)
+
+source.ratz = $("$(INSTALLROOT)/src/cmd/$(init)/ratz.c":T=F)
+binary.ratz = $("$(INSTALLROOT)/src/cmd/$(init)/ratz":T=F)
+
+$(init) : .VIRTUAL $(init)
+
+package.requires = 0
+
+":package:" : .MAKE .OPERATOR
+ local P I R V
+ P := $(<:O=1)
+ $(P) : $(>:V)
+ if ! package.requires
+ if ! name
+ name := $(P)
+ .PACKAGE. := $(P)
+ if name == "$(init)"
+ package.omit = -
+ package.src += $(package.ini:C,^,$(PACKAGEROOT)/bin/,) $(PACKAGESRC)/package.mk
+ else
+ $(P) : $(package.init)
+ end
+ for I $(<:O>1)
+ if I == "*=*"
+ eval
+ $(I)
+ end
+ else
+ version := $(I)
+ end
+ end
+ LICENSEFILEDEFAULT := $(.package.licenses. $(name):@/ /:/G)
+ export LICENSEFILEDEFAULT
+ end
+ if "$(>)"
+ for I $(>:V)
+ $(I) : .VIRTUAL
+ if I == "/*"
+ package.dir += $(I:V)
+ end
+ end
+ end
+ if "$(@)"
+ $(P).README := $(@)
+ else
+ $(P).README := This is the $(P) package.
+ end
+ end
+
+":AUXILIARY:" : .MAKE .OPERATOR
+ package.auxiliary.$(style) += $(>:N=/*:T=F) $(>:N!=/*:C%^%$(INSTALLROOT)/%:T=F)
+
+":CATEGORY:" : .MAKE .OPERATOR
+ if ! package.requires
+ category := $(>)
+ end
+
+.covers. : .FUNCTION
+ local I C D F K=0 L
+ for I $(%)
+ if ! "$(~covers:N=$(I:B))"
+ if F = "$(I:D:B:S=.pkg:T=F)"
+ if D = "$(F:T=I)"
+ covers : $(I:B)
+ for L $(D)
+ if L == ":COVERS:"
+ K = 1
+ elif L == ":*:"
+ if K
+ break
+ end
+ elif K
+ : $(.covers. $(L))
+ end
+ end
+ end
+ else
+ error $(--exec:?3?1?) $(I): unknown package $(I)
+ end
+ end
+ end
+
+":COVERS:" : .MAKE .OPERATOR
+ if ! package.requires
+ : $(.covers. $(>))
+ end
+
+":DESCRIPTION:" : .MAKE .OPERATOR
+ if ! package.requires
+ $(name).README := $(@:V)
+ end
+
+":DETAILS:" : .MAKE .OPERATOR
+ if ! package.requires
+ details.$(>:O=1) := $(@:V)
+ end
+
+":EXPORT:" : .MAKE .OPERATOR
+ if ! package.requires
+ export.$(style) := $(@:/$$("\n")/ /G)
+ end
+
+":INDEX:" : .MAKE .OPERATOR
+ if ! package.requires
+ index := $(>)
+ end
+
+":INSTALL:" : .MAKE .OPERATOR
+ if ! package.requires
+ local T S F X
+ S := $(>)
+ T := $(<)
+ if "$(exe.$(style))" && "$(T)" == "bin/*([!./])"
+ T := $(T).exe
+ end
+ if ! "$(S)"
+ S := $(T)
+ elif "$(exe.$(style))" && "$(S)" == "bin/*([!./])"
+ S := $(S).exe
+ end
+ install.$(style) := $(install.$(style):V)$("\n")install : $$(ROOT)/$(T)$("\n")$$(ROOT)/$(T) : $$(ARCH)/$(S)$("\n\t")cp $< $@
+ if strip && "$(T:N=*.exe)"
+ install.$(style) := $(install.$(style):V)$("\n\t")strip $@ 2>/dev/null
+ end
+ X := $(PACKAGEROOT)/arch/$(CC.HOSTTYPE)/$(S)
+ if strip && "$(X:T=Y)" == "*/?(x-)(dll|exe)"
+ F := filter $(STRIP) $(STRIPFLAGS) $(X)
+ end
+ if "$(filter.$(style):V)"
+ filter.$(style) := $(filter.$(style):V)$$("\n")
+ end
+ filter.$(style) := $(filter.$(style):V);;$(F);$(X);usr/$(T)
+ end
+
+":LICENSE:" : .MAKE .OPERATOR
+ if ! package.requires && ! license
+ license := $(>)
+ end
+
+":OMIT:" : .MAKE .OPERATOR
+ if ! package.requires
+ package.omit := $(package.omit)|$(>:C,^,*/,:/ /|/G)
+ end
+
+":POSTINSTALL:" : .MAKE .OPERATOR
+ if ! package.requires
+ postinstall.$(style) := $(@:V)
+ end
+
+":README:" : .MAKE .OPERATOR
+ if ! package.requires
+ readme.$(style) := $(@:V)
+ end
+
+.requires. : .FUNCTION
+ local I C D F K=0 L V T M=0
+ for I $(%)
+ if ! "$(~requires:N=$(I:B))"
+ if F = "$(I:D:B:S=.pkg:T=F)"
+ if I == "$(init)"
+ package.omit = -
+ else
+ requires : $(I:B)
+ end
+ if V = "$(I:D:B=gen/$(I:B):S=.ver:T=F)"
+ req : $(I:B)
+ else
+ error 1 $(I): package should be written before $(P)
+ end
+ let package.requires = package.requires + 1
+ include "$(F)"
+ let package.requires = package.requires - 1
+ else
+ error 1 $(I): package not found
+ end
+ end
+ end
+
+":REQUIRES:" : .MAKE .OPERATOR
+ : $(.requires. $(>))
+
+":TEST:" : .MAKE .OPERATOR
+ if ! package.requires
+ local T
+ T := $(>)
+ if "$(T)" == "bin/*([!./])"
+ if "$(exe.$(style))"
+ T := $(T).exe
+ end
+ T := $$(PWD)/$$(ARCH)/$(T)
+ end
+ test.$(style) := $(test.$(style):V)$("\n")test : $(T:V)$("\n\t")$(@)
+ end
+
+base delta : .MAKE .VIRTUAL .FORCE
+ op := $(<)
+
+closure : .MAKE .VIRTUAL .FORCE
+ $(<) := 1
+
+cyg exp lcl pkg rpm tgz : .MAKE .VIRTUAL .FORCE
+ style := $(<)
+
+source : .source.init .source.gen .source.$$(style)
+
+.source.init : .MAKE
+ local A B D P V I
+ type := source
+ if ! "$(incremental)"
+ incremental = 1
+ end
+ if "$(source.$(name))"
+ suffix = c
+ end
+ : $(.init.$(style))
+ : $(details.$(style):V:R) :
+ A := $(source.list)
+ B := $(A:N=*.$(stamp).$(suffix):N!=*.$(stamp).$(stamp).*:O=1:T=F)
+ P := $(A:N=*.$(stamp).$(suffix):N!=*.$(stamp).$(stamp).*:O=2:T=F)
+ D := $(A:N=*.$(stamp).$(stamp).$(suffix):O=1:T=F)
+ if op == "delta"
+ if ! B
+ error 3 delta requires a base archive
+ end
+ base := -z $(B)
+ deltaversion := $(B:B:/$(name).//)
+ let deltasince = $(deltaversion:/.*-//) + 1
+ deltasince := $(deltaversion:/[^-]*$/$(deltasince:F=%02d)/)
+ if "$(release)" != "$(stamp)"
+ release := $("":T=R%Y-%m-%d)
+ end
+ source := $(B:D:B:S=.$(release).$(suffix))
+ version := $(source:B:B:/$(name).//)
+ elif B || op == "base"
+ if op == "base"
+ for I $(B) $(P)
+ V := $(I:B:/$(name)\.\([^.]*\).*/\1/)
+ if V == "$(stamp)" && V != "$(version)"
+ old.version := $(V)
+ old.source := $(I)
+ if "$(old.version)" >= "$(version)"
+ error 3 $(name): previous base $(old.version) is newer than $(version)
+ end
+ break
+ end
+ end
+ else
+ source := $(B)
+ end
+ if B == "$(source)"
+ if "$(B:D:B:B)" == "$(D:D:B:B)" && "$(B:B::S)" != "$(D:B::S)"
+ error 3 $(B:B:S): base overwrite would invalidate delta $(D:B:S)
+ end
+ error 1 $(B:B:S): replacing current base
+ end
+ version := $(source:B:S:/^$(name).\(.*\).$(suffix)$/\1/)
+ end
+ PACKAGEGEN := $(PACKAGESRC)/gen
+
+.source.gen : $$(PACKAGEDIR) $$(PACKAGEGEN) $$(PACKAGEGEN)/SOURCE.html $$(PACKAGEGEN)/BINARY.html $$(PACKAGEGEN)/DETAILS.html
+
+BINPACKAGE := $(PATH:/:/ /G:X=package:T=F:O=1)
+
+$$(PACKAGEDIR) $$(PACKAGEGEN) : .IGNORE
+ [[ -d $(<) ]] || mkdir $(<)
+
+$$(PACKAGEGEN)/SOURCE.html : $(BINPACKAGE)
+ $(*) html source > $(<)
+
+$$(PACKAGEGEN)/BINARY.html : $(BINPACKAGE)
+ $(*) html binary > $(<)
+
+$$(PACKAGEGEN)/DETAILS.html : $(BINPACKAGE)
+ $(*) html intro > $(<)
+
+.source.exp .source.pkg .source.rpm : .MAKE
+ error 3 $(style): source package style not supported yet
+
+exe.cyg = .exe
+vendor.cyg = gnu
+
+.name.cyg : .FUNCTION
+ local N
+ N := $(%)
+ if N == "*-*"
+ vendor := $(N:/-.*//)
+ if vendor == "$(vendor.cyg)"
+ vendor :=
+ N := $(N:/[^-]*-//)
+ end
+ N := $(N:/-//G)
+ end
+ return $(N)
+
+.init.cyg : .FUNCTION
+ local N O
+ closure = 1
+ init = .
+ strip = 1
+ suffix = tar.bz2
+ format = tbz
+ vendor := $(licenses:N!=$(vendor.cyg):O=1)
+ package.ini := $(package.ini)
+ package.src.pat := $(package.src.pat)
+ package.src := $(package.src)
+ package.bin := $(package.bin)
+ .source.gen : .CLEAR $(*.source.gen:V:N!=*.html)
+ name.original := $(name)
+ name := $(.name.cyg $(name))
+ if name != "$(name.original)"
+ $(name) : $(~$(name.original))
+ O := $(~covers)
+ covers : .CLEAR
+ for N $(O)
+ covers : $(.name.cyg $(N))
+ end
+ end
+ stamp = [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9]
+ version.original := $(version)
+ version := $(version:/-//G)-1
+ if opt
+ opt := $(opt)/$(vendor)/
+ else
+ opt := $(name)-$(version)/
+ end
+ if type == "source"
+ version := $(version)-src
+ source = $(PACKAGEDIR)/$(name)-$(version)$(release:?.$(release)??).$(suffix)
+ else
+ binary = $(PACKAGEDIR)/$(name)-$(version)$(release:?.$(release)??).$(suffix)
+ end
+
+.source.cyg :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ integer m=0 o
+ cat > $tmp/configure <<'!'
+ echo "you didn't have to do that"
+ !
+ chmod +x $tmp/configure
+ echo ";;;$tmp/configure;configure"
+ cat > $tmp/Makefile0 <<'!'
+ HOSTTYPE := $$(shell bin/package)
+ ROOT = ../..
+ ARCH = arch/$$(HOSTTYPE)
+ all :
+ PACKAGEROOT= CYGWIN="$$CYGWIN ntsec binmode" bin/package make $(export.$(style))
+ install : all
+ $(install.$(style):V)
+ $(test.$(style):V)
+ !
+ echo ";;;$tmp/Makefile0;Makefile"
+ cat > $tmp/CYGWIN-README <<'!'
+ $(readme.$(style):@?$$(readme.$$(style))$$("\n\n")??)To build binaries from source into the ./arch/`bin/package` tree run:
+ $()
+ make
+ $()
+ $(test.$(style):@?To test the binaries after building/installing run:$$("\n\n\t")make test$$("\n\n")??)To build and/or install the binaries run:
+ $()
+ make install
+ $()
+ The bin/package command provides a command line interface for all package
+ operations. The $(opt:/.$//) source and binary packages were generated by:
+ $()
+ package write cyg base source version=$(version.original) $(name.original)
+ package write cyg base binary version=$(version.original) $(name.original)
+ $()
+ using the $(org)-base package. To download and install the latest
+ $(org)-base source package in /opt/$(org) run:
+ $()
+ PATH=/opt/$(org)/bin:$PATH
+ cd /opt/$(org)
+ package authorize "NAME" password "PASSWORD" setup flat source $("\\")
+ $(url) $("\\")
+ $(org)-base
+ package make
+ $()
+ and export /opt/$(org)/bin in PATH to use. The NAME and PASSWORD signify your
+ agreement to the software license(s). All users get the same NAME and PASSWORD.
+ See $(url) for details. If multiple architectures may be built under
+ /opt/$(org) then drop "flat" and export /opt/$(org)/arch/`package`/bin in PATH
+ to use. To update previously downloaded packages from the same url simply run:
+ $()
+ cd /opt/$(org)
+ package setup
+ package make
+ $()
+ To download and install the latest $(org)-base binary package in
+ /opt/$(org) change "source" to "binary" and omit "package make".
+ !
+ echo ";;;$tmp/CYGWIN-README;CYGWIN-PATCHES/README"
+ cat > $(source:/-src.$(suffix)//).setup.hint <<'!'
+ category: $(category:/\(.\).*/\1/U)$(category:/.\(.*\)/\1/L)
+ requires: cygwin
+ sdesc: "$(index)"
+ ldesc: "$($(name.original).README)"
+ !
+ echo ";;;$(source:/-src.$(suffix)//).setup.hint;CYGWIN-PATCHES/setup.hint"
+ echo ";;;$(BINPACKAGE);bin/package"
+ cat > $tmp/Makefile <<'!'
+ :MAKE:
+ !
+ echo ";;;$tmp/Makefile;src/Makefile"
+ echo ";;;$tmp/Makefile;src/cmd/Makefile"
+ echo ";;;$tmp/Makefile;src/lib/Makefile"
+ if [[ '$(mamfile)' == 1 ]]
+ then cat > $tmp/Mamfile1 <<'!'
+ info mam static
+ note source level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*/*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ echo ";;;$tmp/Mamfile1;src/Mamfile"
+ cat > $tmp/Mamfile2 <<'!'
+ info mam static
+ note component level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ echo ";;;$tmp/Mamfile2;src/cmd/Mamfile"
+ echo ";;;$tmp/Mamfile2;src/lib/Mamfile"
+ fi
+ $(package.src:U:T=F:/.*/echo ";;;&"$("\n")/)
+ echo ";;;$(PACKAGEGEN)/$(name.original).req"
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ if [[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
+ then if [[ '$(mamfile)' == 1 ]]
+ then (( o=m ))
+ s=$( $(MAKE) --noexec --recurse=list recurse 2>/dev/null )
+ if [[ $s ]]
+ then for j in $s
+ do if [[ -d $j ]]
+ then cd $j
+ if [[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
+ then (( m++ ))
+ $(MAKE) $(package.mam) $(export.$(style):Q) > $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/$j/Mamfile"
+ fi
+ cd $(INSTALLROOT)/$i
+ fi
+ done
+ if (( o != m ))
+ then (( m++ ))
+ cat > $tmp/$m.mam <<'!'
+ info mam static
+ note subcomponent level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ echo ";;;$tmp/$m.mam;$i/Mamfile"
+ fi
+ else (( m++ ))
+ $(MAKE) $(package.mam) $(export.$(style):Q) > $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/Mamfile"
+ fi
+ fi
+ $(MAKE) --noexec $(-) $(=) recurse list.package.$(type) package.license.class=$(license:Q)
+ fi
+ done
+ set -- $(package.dir:P=G)
+ for i
+ do tw -d $i -e "action:printf(';;;%s;%s\n',path,path);"
+ done
+ } |
+ {
+ : > $tmp/HEAD
+ cat > $tmp/README <<'!'
+ $(package.readme)
+ !
+ echo ";;;$tmp/README;README"
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ --format=$(format) \
+ --local \
+ -wvf $(source) $(base) \
+ $(PACKAGEVIEW:C%.*%-s",^&/,,"%) \
+ $(vendor:?-s",^[^/],$(opt)&,"??)
+ $(SUM) -x $(checksum) < $(source) > $(source:D:B:S=.$(checksum))
+ rm -rf $tmp
+ fi
+
+.source.lcl :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ integer m=0 o
+ $(package.src:U:T=F:/.*/echo ";;;&"$("\n")/)
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ $(MAKE) --noexec $(-) $(=) .FILES.+=Mamfile recurse list.package.local
+ done
+ set -- $(package.dir:P=G)
+ for i
+ do tw -d $i -e "action:printf(';;;%s;%s\n',path,path);"
+ done
+ } |
+ sort -t';' -k5,5 -u |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ -wvf $(source) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ $(PACKAGEVIEW:C%.*%-s",^&/,,"%)
+ rm -rf $tmp
+ fi
+
+.source.tgz :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ integer m=0 o
+ if [[ '$(init)' == '$(name)' ]]
+ then cat > $tmp/Makefile <<'!'
+ :MAKE:
+ !
+ $(CMP) $(CMPFLAGS) $tmp/Makefile $(PACKAGEROOT)/src/Makefile && touch -r $(PACKAGEROOT)/src/Makefile $tmp/Makefile
+ echo ";;;$tmp/Makefile;src/Makefile"
+ cp $tmp/Makefile $tmp/Makefile1
+ $(CMP) $(CMPFLAGS) $tmp/Makefile1 $(PACKAGEROOT)/src/cmd/Makefile && touch -r $(PACKAGEROOT)/src/cmd/Makefile $tmp/Makefile1
+ echo ";;;$tmp/Makefile1;src/cmd/Makefile"
+ cp $tmp/Makefile $tmp/Makefile2
+ $(CMP) $(CMPFLAGS) $tmp/Makefile2 $(PACKAGEROOT)/src/lib/Makefile && touch -r $(PACKAGEROOT)/src/lib/Makefile $tmp/Makefile2
+ echo ";;;$tmp/Makefile2;src/lib/Makefile"
+ if [[ '$(mamfile)' == 1 ]]
+ then cat > $tmp/Mamfile1 <<'!'
+ info mam static
+ note source level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*/*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ $(CMP) $(CMPFLAGS) $tmp/Mamfile1 $(PACKAGEROOT)/src/Mamfile && touch -r $(PACKAGEROOT)/src/Mamfile $tmp/Mamfile1
+ echo ";;;$tmp/Mamfile1;src/Mamfile"
+ cat > $tmp/Mamfile2 <<'!'
+ info mam static
+ note component level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ $(CMP) $(CMPFLAGS) $tmp/Mamfile2 $(PACKAGEROOT)/src/cmd/Mamfile && touch -r $(PACKAGEROOT)/src/cmd/Mamfile $tmp/Mamfile2
+ echo ";;;$tmp/Mamfile2;src/cmd/Mamfile"
+ cp $tmp/Mamfile2 $tmp/Mamfile3
+ $(CMP) $(CMPFLAGS) $tmp/Mamfile3 $(PACKAGEROOT)/src/lib/Mamfile && touch -r $(PACKAGEROOT)/src/lib/Mamfile $tmp/Mamfile3
+ echo ";;;$tmp/Mamfile3;src/lib/Mamfile"
+ fi
+ fi
+ $(package.src:U:T=F:C%^$(PACKAGEROOT)/%%:C%.*%echo ";;;$(PACKAGEROOT)/&;&"$("\n")%)
+ if [[ '$(~covers)' ]]
+ then for i in $(~covers)
+ do for j in lib pkg
+ do if [[ -f $(PACKAGESRC)/$i.$j ]]
+ then echo ";;;$(PACKAGESRC)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ for j in ver req
+ do if [[ -f $(PACKAGEGEN)/$i.$j ]]
+ then echo ";;;$(PACKAGEGEN)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ done
+ for i in $(~covers:D=$(PACKAGESRC):B:S=.lic:T=F:T=I:N=*.def:D=$(PACKAGESRC):B:S:T=F:B:S)
+ do echo ";;;$(PACKAGESRC)/$i;$(PACKAGELIB)/$i"
+ done
+ fi
+ if [[ '$(PACKAGEDIR:B)' == '$(style)' ]]
+ then echo $(name) $(version) $(release|version) 1 > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).ver || cp $tmp/t $(PACKAGEGEN)/$(name).ver
+ echo ";;;$(PACKAGEGEN)/$(name).ver;$(PACKAGELIB)/$(name).ver"
+ sed 's,1$,0,' $(~req:D=$(PACKAGEGEN):B:S=.ver:T=F) < /dev/null > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).req || cp $tmp/t $(PACKAGEGEN)/$(name).req
+ echo ";;;$(PACKAGEGEN)/$(name).req;$(PACKAGELIB)/$(name).req"
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).inx || cp $tmp/t $(PACKAGEGEN)/$(name).inx
+ {
+ {
+ echo '$($(name).README)'
+ if [[ '$(~covers)' ]]
+ then echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
+ fi
+ if [[ '$(~requires)' ]]
+ then echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
+ fi
+ } | fmt
+ package help source
+ package release $(name)
+ } > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).README || cp $tmp/t $(PACKAGEGEN)/$(name).README
+ echo ";;;$(PACKAGEGEN)/$(name).README;$(PACKAGELIB)/$(name).README"
+ {
+ echo '.xx title="$(name) package"'
+ echo '.xx meta.description="$(name) package"'
+ echo '.xx meta.keywords="software, package"'
+ echo '.MT 4'
+ echo '.TL'
+ echo '$(name) package'
+ echo '.H 1 "$(name) package"'
+ echo '$($(name).README)'
+ set -- $(package.closure:C,.*,$(INSTALLROOT)/&/PROMO.mm,:T=F:D::B)
+ hot=
+ for i
+ do hot="$hot -e s/\\(\\<$i\\>\\)/\\\\h'0*1'\\1\\\\h'0'/"
+ done
+ set -- $(package.closure:B)
+ if (( $# ))
+ then echo 'Components in this package:'
+ echo '.P'
+ echo '.TS'
+ echo 'center expand;'
+ echo 'l l l l l l.'
+ if [[ $hot ]]
+ then hot="sed $hot"
+ else hot=cat
+ fi
+ for i
+ do echo $i
+ done |
+ pr -6 -t -s' ' |
+ $hot
+ echo '.TE'
+ fi
+ echo '.P'
+ if [[ '$(~covers)' ]]
+ then echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
+ fi
+ if [[ '$(~requires)' ]]
+ then echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
+ fi
+ set -- $(.package.licenses. --all $(name))
+ case $# in
+ 0) ;;
+ *) case $# in
+ 1) echo 'The software is covered by this license:' ;;
+ *) echo 'The software is covered by these licenses:' ;;
+ esac
+ echo .BL
+ for j
+ do i=$( $(PROTO) -l $j -p -h -o type=usage /dev/null | sed -e 's,.*\[-license?\([^]]*\).*,\1,' )
+ echo .LI
+ echo ".xx link=\"$i\""
+ done
+ echo .LE
+ echo 'Individual components may be covered by separate licenses;'
+ echo 'refer to the component source and/or binaries for more information.'
+ echo .P
+ ;;
+ esac
+ echo 'A recent'
+ echo '.xx link="release change log"'
+ echo 'is also included.'
+ cat $(package.closure:C,.*,$(INSTALLROOT)/&/PROMO.mm,:T=F) < /dev/null
+ echo '.H 1 "release change log"'
+ echo '.xx index'
+ echo '.nf'
+ package release $(name) |
+ sed -e 's/:::::::: \(.*\) ::::::::/.fi\$("\n").H 1 "\1 changes"\$("\n").nf/'
+ echo '.fi'
+ } |
+ $(MM2HTML) $(MM2HTMLFLAGS) -o nohtml.ident > $tmp/t
+ $(STDED) $(STDEDFLAGS) $tmp/t <<'!'
+ /^<!--LABELS-->$/,/^<!--\/LABELS-->$/s/ changes</</
+ /^<!--LABELS-->$/,/^<!--\/LABELS-->$/m/<A name="release change log">/
+ w
+ q
+ !
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).html || cp $tmp/t $(PACKAGEGEN)/$(name).html
+ echo ";;;$(PACKAGEGEN)/$(name).html;$(PACKAGELIB)/$(name).html"
+ if [[ '$(deltasince)' ]]
+ then {
+ echo '.xx title="$(name) package"'
+ echo '.xx meta.description="$(name) package $(version) delta $(release)"'
+ echo '.xx meta.keywords="software, package, delta"'
+ echo '.MT 4'
+ echo '.TL'
+ echo '$(name) package $(deltaversion) delta $(release)'
+ echo '.H 1 "$(name) package $(deltaversion) delta $(release) changes"'
+ echo '.nf'
+ package release $(deltasince) $(name) |
+ sed -e 's/:::::::: \(.*\) ::::::::/.H 2 \1/'
+ echo '.fi'
+ } |
+ $(MM2HTML) $(MM2HTMLFLAGS) -o nohtml.ident > $tmp/t
+ $(CMP) $(CMPFLAGS) $tmp/t $(PACKAGEGEN)/$(name).$(release).html || cp $tmp/t $(PACKAGEGEN)/$(name).$(release).html
+ echo ";;;$(PACKAGEGEN)/$(name).$(release).html;$(PACKAGELIB)/$(name).$(release).html"
+ fi
+ fi
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ if [[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
+ then if [[ '$(mamfile)' == 1 ]]
+ then (( o=m ))
+ s=$( $(MAKE) --noexec --recurse=list recurse 2>/dev/null )
+ if [[ $s ]]
+ then for j in $s
+ do if [[ -d $j ]]
+ then cd $j
+ if [[ ! '$(license)' ]] || $(MAKE) --noexec --silent 'exit $$(LICENSECLASS:N=$(license):?0?1?)' .
+ then (( m++ ))
+ $(MAKE) $(package.mam) > $tmp/$m.mam
+ $(CMP) $(CMPFLAGS) $tmp/$m.mam $(PACKAGEROOT)/$i/$j/Mamfile && touch -r $(PACKAGEROOT)/$i/$j/Mamfile $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/$j/Mamfile"
+ fi
+ cd $(INSTALLROOT)/$i
+ fi
+ done
+ if (( o != m ))
+ then (( m++ ))
+ cat > $tmp/$m.mam <<'!'
+ info mam static
+ note subcomponent level :MAKE: equivalent
+ make install
+ make all
+ exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+ done all virtual
+ done install virtual
+ !
+ $(CMP) $(CMPFLAGS) $tmp/$m.mam $(PACKAGEROOT)/$i/Mamfile && touch -r $(PACKAGEROOT)/$i/Mamfile $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/Mamfile"
+ fi
+ else (( m++ ))
+ $(MAKE) $(package.mam) > $tmp/$m.mam
+ $(CMP) $(CMPFLAGS) $tmp/$m.mam $(PACKAGEROOT)/$i/Mamfile && touch -r $(PACKAGEROOT)/$i/Mamfile $tmp/$m.mam
+ echo ";;;$tmp/$m.mam;$i/Mamfile"
+ fi
+ fi
+ $(MAKE) --noexec $(-) $(=) recurse list.package.$(type) package.license.class=$(license:Q) $(copyright:N=1:??LICENSE=?)
+ fi
+ done
+ set -- $(package.dir:P=G)
+ for i
+ do tw -d $i -e "action:printf(';;;%s;%s\n',path,path);"
+ done
+ } |
+ {
+ : > $tmp/HEAD
+ [[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
+ cat > $tmp/README <<'!'
+ $(package.readme)
+ !
+ echo ";;;$tmp/README;README"
+ $(CMP) $(CMPFLAGS) $tmp/README $(PACKAGEROOT)/README && touch -r $(PACKAGEROOT)/README $tmp/README
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ -wvf $(source) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ $(PACKAGEVIEW:C%.*%-s",^&/,,"%)
+ $(SUM) -x $(checksum) < $(source) > $(source:D:B:S=.$(checksum))
+ echo local > $(source:D:B=$(name):S=.tim)
+ if [[ '$(incremental)' == 1 && '$(old.source)' ]]
+ then $(PAX) -rf $(source) -wvf $(old.new.source) -z $(old.source)
+ $(SUM) -x $(checksum) < $(old.new.source) > $(old.new.source:D:B:S=.$(checksum))
+ fi
+ rm -rf $tmp
+ else if [[ '$(old.source)' ]] && $(CMP) $(CMPFLAGS) $(source.$(name)) $(source)
+ then : $(name) is up to date
+ else echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
+ : > $(PACKAGEGEN)/$(name).req
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $(PACKAGEGEN)/$(name).inx
+ {
+ echo '.xx title="$(name) package"'
+ echo '.xx meta.description="$(name) package"'
+ echo '.xx meta.keywords="software, package"'
+ echo '.MT 4'
+ echo '.TL'
+ echo '$(name) package'
+ echo '.H 1'
+ echo '$($(name).README)'
+ } |
+ $(MM2HTML) $(MM2HTMLFLAGS) -o nohtml.ident > $(PACKAGEGEN)/$(name).html
+ if [[ '$(source.$(name))' ]]
+ then {
+ echo '$($(name).README)'
+ package help source
+ } > $(PACKAGEGEN)/$(name).README
+ cp $(source.$(name)) $(source)
+ $(SUM) -x $(checksum) < $(source) > $(source:D:B:S=.$(checksum))
+ fi
+ echo local > $(source:D:B=$(name):S=.tim)
+ fi
+ fi
+
+binary : .binary.init .binary.gen .binary.$$(style)
+
+.binary.init : .MAKE
+ local A B D I P V
+ type := binary
+ if ! "$(incremental)"
+ incremental = 0
+ end
+ if ! "$(~$(name))"
+ if name == "ratz"
+ suffix = exe
+ else
+ suffix = gz
+ end
+ end
+ : $(.init.$(style)) :
+ : $(details.$(style):V:R) :
+ A := $(binary.list)
+ B := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=1:T=F)
+ P := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=2:T=F)
+ D := $(A:N=*.$(stamp).$(stamp).$(CC.HOSTTYPE).$(suffix):O=1:T=F)
+ if op == "delta"
+ if ! B
+ error 3 delta requires a base archive
+ end
+ base := -z $(B)
+ if "$(release)" != "$(stamp)"
+ release := $("":T=R%Y-%m-%d)
+ end
+ binary := $(B:/$(CC.HOSTTYPE).$(suffix)$/$(release).&/)
+ version := $(binary:B:B:/$(name).//)
+ elif B || op == "base"
+ if op == "base"
+ for I $(B) $(P)
+ V := $(I:B:/$(name)\.\([^.]*\).*/\1/)
+ if V == "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" && V != "$(version)"
+ old.version := $(V)
+ old.binary := $(I)
+ if "$(old.version)" >= "$(version)"
+ error 3 $(name): previous base $(old.version) is newer than $(version)
+ end
+ break
+ end
+ end
+ else
+ binary := $(B)
+ end
+ if B == "$(binary)"
+ if "$(B:D:B)" == "$(D:D:B)" && "$(B:S)" != "$(D:S)"
+ error 3 $(B:B:S): base overwrite would invalidate delta $(D:B:S)
+ end
+ error 1 $(B:B:S): replacing current base
+ end
+ version := $(binary:B:/$(name).//:/\..*//)
+ end
+ PACKAGEGEN := $(PACKAGEBIN)/gen
+
+.binary.gen : $$(PACKAGEDIR) $$(PACKAGEGEN)
+
+.binary.exp .binary.pkg .binary.rpm : .MAKE
+ error 3 $(style): binary package style not supported yet
+
+.binary.cyg :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ integer m=0 o
+ {
+ echo '$($(name.original).README)' | fmt
+ cat <<'!'
+ $(readme.$(style):@?$$("\n")$$(readme.$$(style))??)
+ !
+ } > $tmp/README1
+ echo ";;;$tmp/README1;usr/share/doc/Cygwin/$(opt:/.$//).README"
+ {
+ echo '$($(name.original).README)' | fmt
+ cat <<'!'
+ $()
+ The remainder of this file is the README from the source package
+ that was used to generate this binary package. It describes
+ the source build hierarchy, not the current directory.
+ $()
+ $(package.readme)
+ !
+ } > $tmp/README2
+ echo ";;;$tmp/README2;usr/share/doc/$(opt)README"
+ package release $(name.original) > $tmp/RELEASE
+ echo ";;;$tmp/RELEASE;usr/share/doc/$(opt)RELEASE"
+ cat > $(binary:/.$(suffix)//).setup.hint <<'!'
+ category: $(category:/\(.\).*/\1/U)$(category:/.\(.*\)/\1/L)
+ requires: cygwin
+ sdesc: "$(index)"
+ ldesc: "$($(name.original).README)"
+ !
+ set -- $(.package.licenses. --text $(name.original):N!=*.lic)
+ for i
+ do echo ";;;${i};usr/share/doc/$(opt)LICENSE-${i##*/}"
+ done
+ cat <<'!'
+ $(filter.$(style))
+ !
+ if [[ '$(postinstall.$(style):V:O=1:?1??)' ]]
+ then cat >$tmp/postinstall <<'!'
+ $("#")!/bin/sh
+ $(postinstall.$(style))
+ !
+ echo ";;;$tmp/postinstall;etc/postinstall/$(name).sh"
+ fi
+ } |
+ {
+ : > $tmp/HEAD
+ [[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ --format=$(format) \
+ --local \
+ -wvf $(binary)
+ $(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
+ rm -rf $tmp
+ fi
+
+.binary.lcl :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ $(package.src:U:T=F:/.*/echo ";;;&"$("\n")/)
+ $(package.bin:U:T=F:/.*/echo ";;;&"$("\n")/)
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ $(MAKE) --noexec $(-) --variants=$(variants:Q) $(=) recurse list.package.$(type) package.license.class=$(license:Q) cc-
+ done
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ --checksum=md5:$(PACKAGEGEN)/$(name).sum \
+ --install=$(PACKAGEGEN)/$(name).ins \
+ -wvf $(binary) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ -s",^$tmp/,$(INSTALLOFFSET)/," \
+ $(PACKAGEROOT:C%.*%-s",^&/,,"%)
+ $(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
+ echo local > $(binary:D:B=$(name):S=.$(CC.HOSTTYPE).tim)
+ rm -rf $tmp
+ fi
+
+.binary.tgz :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ if [[ '$(init)' == '$(name)' ]]
+ then for i in lib32 lib64
+ do if [[ -d $(INSTALLROOT)/$i ]]
+ then echo ";physical;;$(INSTALLROOT)/$i"
+ fi
+ done
+ fi
+ $(package.src:U:T=F:C%^$(PACKAGEROOT)/%%:C%.*%echo ";;;$(PACKAGEROOT)/&;&"$("\n")%)
+ $(package.bin:U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
+ $(package.auxiliary.$(style):U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
+ if [[ '$(PACKAGEDIR:B)' == '$(style)' ]]
+ then echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
+ echo ";;;$(PACKAGEGEN)/$(name).ver;$(PACKAGELIB)/$(name).ver"
+ if [[ '$(~covers)' ]]
+ then for i in $(~covers)
+ do for j in lic pkg
+ do if [[ -f $(PACKAGESRC)/$i.$j ]]
+ then echo ";;;$(PACKAGESRC)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ for j in ver req
+ do if [[ -f $(PACKAGEGEN)/$i.$j ]]
+ then echo ";;;$(PACKAGEGEN)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ done
+ for i in $(~covers:D=$(PACKAGESRC):B:S=.lic:T=F:T=I:N=*.def:D=$(PACKAGESRC):B:S:T=F:B:S)
+ do echo ";;;$(PACKAGESRC)/$i;$(PACKAGELIB)/$i"
+ done
+ fi
+ sed 's,1$,0,' $(~req:D=$(PACKAGEGEN):B:S=.ver:T=F) < /dev/null > $(PACKAGEGEN)/$(name).req
+ echo ";;;$(PACKAGEGEN)/$(name).req;$(PACKAGELIB)/$(name).req"
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $(PACKAGEGEN)/$(name).inx
+ {
+ {
+ echo '$($(name).README)'
+ if [[ '$(~covers)' ]]
+ then echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
+ fi
+ if [[ '$(~requires)' ]]
+ then echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
+ fi
+ } | fmt
+ package help binary
+ package release $(name)
+ } > $(PACKAGEGEN)/$(name).README
+ echo ";;;$(PACKAGEGEN)/$(name).README;$(PACKAGELIB)/$(name).README"
+ fi
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ $(MAKE) --noexec $(-) --variants=$(variants:Q) $(=) package.strip=$(strip) recurse list.package.$(type) package.license.class=$(license:Q) cc-
+ done
+ } |
+ {
+ : > $tmp/HEAD
+ [[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
+ cat > $tmp/README <<'!'
+ $(package.readme)
+ !
+ echo ";;;$tmp/README;README"
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ --checksum=md5:$(PACKAGEGEN)/$(name).sum \
+ --install=$(PACKAGEGEN)/$(name).ins \
+ -wvf $(binary) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ -s",^$tmp/,$(INSTALLOFFSET)/," \
+ $(PACKAGEROOT:C%.*%-s",^&/,,"%)
+ echo $(binary) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ $(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
+ echo $(binary:D:B:S=.$(checksum)) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ echo local > $(binary:D:B=$(name):S=.$(CC.HOSTTYPE).tim)
+ if [[ '$(incremental)' == 1 && '$(old.binary)' ]]
+ then $(PAX) -rf $(binary) -wvf $(old.new.binary) -z $(old.binary)
+ echo $(old.new.binary) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ $(SUM) -x $(checksum) < $(old.new.binary) > $(old.new.binary:D:B:S=.$(checksum))
+ echo $(old.new.binary:D:B:S=.$(checksum)) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ fi
+ rm -rf $tmp
+ else if [[ '$(binary.$(name))' ]]
+ then exe=$(binary.$(name))
+ else exe=$(INSTALLROOT)/bin/$(name)
+ fi
+ if [[ '$(old.binary)' ]] && $(CMP) $(CMPFLAGS) $exe $(binary)
+ then : $(name) is up to date
+ else echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
+ : > $(PACKAGEGEN)/$(name).req
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $(PACKAGEGEN)/$(name).inx
+ {
+ echo '$($(name).README)'
+ package help binary
+ } > $(PACKAGEGEN)/$(name).README
+ case "$(binary)" in
+ *.gz) gzip < $exe > $(binary) ;;
+ *) cp $exe $(binary) ;;
+ esac
+ $(SUM) -x $(checksum) < $(binary) > $(binary:D:B:S=.$(checksum))
+ echo local > $(binary:D:B=$(name):S=.$(CC.HOSTTYPE).tim)
+ fi
+ echo $(binary) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ echo $(binary:D:B:S=.$(checksum)) >> $(binary:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ fi
+
+runtime : .runtime.init .runtime.gen .runtime.$$(style)
+
+.runtime.init : .MAKE
+ local A B D I P V
+ type := runtime
+ if ! "$(incremental)"
+ incremental = 0
+ end
+ if ! "$(~$(name))"
+ if name == "ratz"
+ suffix = exe
+ else
+ suffix = gz
+ end
+ end
+ : $(.init.$(style)) :
+ : $(details.$(style):V:R) :
+ A := $(runtime.list)
+ B := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=1:T=F)
+ P := $(A:N=*.$(stamp).$(CC.HOSTTYPE).$(suffix):N!=*.$(stamp).$(stamp).*:O=2:T=F)
+ D := $(A:N=*.$(stamp).$(stamp).$(CC.HOSTTYPE).$(suffix):O=1:T=F)
+ if op == "delta"
+ if ! B
+ error 3 delta requires a base archive
+ end
+ base := -z $(B)
+ if "$(release)" != "$(stamp)"
+ release := $("":T=R%Y-%m-%d)
+ end
+ runtime := $(B:/$(CC.HOSTTYPE).$(suffix)$/$(release).&/)
+ version := $(runtime:B:B:/$(name).//)
+ elif B || op == "base"
+ if op == "base"
+ for I $(B) $(P)
+ V := $(I:B:/$(name)-run\.\([^.]*\).*/\1/)
+ if V == "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" && V != "$(version)"
+ old.version := $(V)
+ old.runtime := $(I)
+ if "$(old.version)" >= "$(version)"
+ error 3 $(name): previous base $(old.version) is newer than $(version)
+ end
+ break
+ end
+ end
+ else
+ runtime := $(B)
+ end
+ if B == "$(runtime)"
+ if "$(B:D:B)" == "$(D:D:B)" && "$(B:S)" != "$(D:S)"
+ error 3 $(B:B:S): base overwrite would invalidate delta $(D:B:S)
+ end
+ error 1 $(B:B:S): replacing current base
+ end
+ version := $(runtime:B:/$(name)-run.//:/\..*//)
+ end
+ PACKAGEGEN := $(PACKAGESRC)/gen
+
+.runtime.gen : $$(PACKAGEDIR) $$(PACKAGEGEN)
+
+.runtime.cyg .runtime.exp .runtime.lcl .runtime.pkg .runtime.rpm : .MAKE
+ error 3 $(style): runtime package style not supported yet
+
+.runtime.tgz :
+ if [[ '$(~$(name))' ]]
+ then tmp=/tmp/pkg$(tmp)
+ mkdir $tmp
+ {
+ if [[ '$(init)' == '$(name)' ]]
+ then for i in lib32 lib64
+ do if [[ -d $(INSTALLROOT)/$i ]]
+ then echo ";physical;;$(INSTALLROOT)/$i"
+ fi
+ done
+ fi
+ $(package.src:U:T=F:C%^$(PACKAGEROOT)/%%:C%.*%echo ";;;$(PACKAGEROOT)/&;&"$("\n")%)
+ $(package.bin:U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
+ $(package.auxiliary.$(style):U:T=F:C%^$(INSTALLROOT)/%%:C%.*%echo ";;;$(INSTALLROOT)/&;&"$("\n")%)
+ echo $(name) $(version) $(release|version) 1 > $(PACKAGEGEN)/$(name).ver
+ echo ";;;$(PACKAGEGEN)/$(name).ver;$(PACKAGELIB)/$(name).ver"
+ if [[ '$(~covers)' ]]
+ then for i in $(~covers)
+ do for j in lic pkg
+ do if [[ -f $(PACKAGESRC)/$i.$j ]]
+ then echo ";;;$(PACKAGESRC)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ for j in ver req
+ do if [[ -f $(PACKAGEGEN)/$i.$j ]]
+ then echo ";;;$(PACKAGEGEN)/$i.$j;$(PACKAGELIB)/$i.$j"
+ fi
+ done
+ done
+ for i in $(~covers:D=$(PACKAGESRC):B:S=.lic:T=F:T=I:N=*.def:D=$(PACKAGESRC):B:S:T=F:B:S)
+ do echo ";;;$(PACKAGESRC)/$i;$(PACKAGELIB)/$i"
+ done
+ fi
+ sed 's,1$,0,' $(~req:D=$(PACKAGEGEN):B:S=.ver:T=F) < /dev/null > $(PACKAGEGEN)/$(name).req
+ echo ";;;$(PACKAGEGEN)/$(name).req;$(PACKAGELIB)/$(name).req"
+ {
+ echo "name='$(name)'"
+ echo "index='$(index)'"
+ echo "covers='$(~covers)'"
+ echo "requires='$(~req)'"
+ } > $(PACKAGEGEN)/$(name).inx
+ {
+ {
+ echo '$($(name).README)'
+ if [[ '$(~covers)' ]]
+ then echo
+ echo "This package is a superset of the following package$(~covers:O=2:?s??): $(~covers); you won't need $(~covers:O=2:?these?this?) if you download $(name)."
+ fi
+ if [[ '$(~requires)' ]]
+ then echo
+ echo 'It requires the following package$(~requires:O=2:?s??): $(~requires).'
+ fi
+ echo
+ echo "To install this $(type) package read the tarball into a directory"
+ echo "suitable for containing bin and lib subdirectories, and run the"
+ echo "$(PACKAGELIB)/gen/$(name)-run.ins script to fix up permissions."
+ echo
+ echo "To use the package export the bin directory in PATH. The commands and"
+ echo "libraries use \$PATH to locate dynamic libraries and related data files."
+ echo
+ } | fmt
+ } > $(PACKAGEGEN)/$(name)-run.README
+ echo ";;;$(PACKAGEGEN)/$(name)-run.README;$(PACKAGELIB)/$(name)-run.README"
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ $(MAKE) --noexec $(-) --variants=$(variants:Q) $(=) package.strip=$(strip) recurse list.package.$(type) package.license.class=$(license:Q) cc-
+ done
+ } |
+ {
+ : > $tmp/HEAD
+ [[ '$(notice)' ]] && echo ";;;$tmp/HEAD;$(package.notice)"
+ cat > $tmp/README <<'!'
+ $(package.readme)
+ !
+ echo ";;;$tmp/README;README"
+ sort -t';' -k5,5 -u
+ : > $tmp/TAIL
+ [[ '$(notice)' ]] && echo ";;;$tmp/TAIL;$(package.notice)"
+ } |
+ $(PAX) --filter=- \
+ --to=ascii \
+ $(op:N=delta:??--format=$(format)?) \
+ --local \
+ --checksum=md5:$(PACKAGEGEN)/$(name)-run.sum \
+ --install=$(PACKAGEGEN)/$(name)-run.ins \
+ -wvf $(runtime) $(base) \
+ $(op:N=delta:?--format=gzip??) \
+ -s",^$tmp/,$(INSTALLOFFSET)/," \
+ $(PACKAGEROOT:C%.*%-s",^&/,,"%)
+ echo $(runtime) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ $(SUM) -x $(checksum) < $(runtime) > $(runtime:D:B:S=.$(checksum))
+ echo $(runtime:D:B:S=.$(checksum)) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ echo local > $(runtime:D:B=$(name)-run:S=.$(CC.HOSTTYPE).tim)
+ if [[ '$(incremental)' == 1 && '$(old.runtime)' ]]
+ then $(PAX) -rf $(runtime) -wvf $(old.new.runtime) -z $(old.runtime)
+ echo $(old.new.runtime) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ $(SUM) -x $(checksum) < $(old.new.runtime) > $(old.new.runtime:D:B:S=.$(checksum))
+ echo $(old.new.runtime:D:B:S=.$(checksum)) >> $(runtime:D:B=PACKAGE:S=.$(CC.HOSTTYPE).lst)
+ fi
+ rm -rf $tmp
+ fi
+
+list.installed list.manifest :
+ set -- $(package.closure)
+ for i
+ do cd $(INSTALLROOT)/$i
+ ignore $(MAKE) --noexec $(-) $(=) $(<)
+ done
diff --git a/src/cmd/INIT/package.sh b/src/cmd/INIT/package.sh
new file mode 100644
index 0000000..3f1ed1b
--- /dev/null
+++ b/src/cmd/INIT/package.sh
@@ -0,0 +1,7302 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+### this script contains archaic constructs that work with all sh variants ###
+# package - source and binary package control
+# Glenn Fowler <gsf@research.att.com>
+
+command=package
+
+case $-:$BASH_VERSION in
+*x*:[0123456789]*) : bash set -x is broken :; set +ex ;;
+esac
+
+# ksh checks -- ksh between 2007-11-05 and 2011-11-11 conflict with new -lcmd -- wea culpa
+checksh()
+{
+ egrep 'Version.*(88|1993)' $1 >/dev/null 2>&1 ||
+ $1 -c '(( .sh.version >= 20111111 ))' >/dev/null 2>&1
+}
+
+case $_AST_BIN_PACKAGE_:$SHELL:$0 in
+1:*|*:/bin/sh:*)
+ ;;
+*:*/*:*/*)
+ _AST_BIN_PACKAGE_=1 # prevent non-interactive sh .rc referencing bin/package recursion #
+ export _AST_BIN_PACKAGE_
+ if checksh $SHELL
+ then : no -lcmd conflict :
+ else case " $* " in
+ *" debug "*|*" DEBUG "*|*" show "*)
+ echo $command: $SHELL: warning: possible -lcmd conflict -- falling back to /bin/sh >&2
+ ;;
+ esac
+ SHELL=/bin/sh
+ export SHELL
+ exec $SHELL "$0" "$@"
+ fi
+ ;;
+esac
+
+LC_ALL=C
+export LC_ALL
+
+src="cmd contrib etc lib"
+use="/usr/common /exp /usr/local /usr/add-on /usr/addon /usr/tools /usr /opt"
+usr="/home"
+lib="" # nee /usr/local/lib /usr/local/shlib
+ccs="/usr/kvm /usr/ccs/bin"
+org="gnu GNU"
+makefiles="Mamfile Nmakefile nmakefile Makefile makefile"
+env="HOSTTYPE NPROC PACKAGEROOT INSTALLROOT PATH"
+checksum=md5sum
+checksum_commands="$checksum md5"
+checksum_empty="d41d8cd98f00b204e9800998ecf8427e"
+
+package_use='=$HOSTTYPE=$PACKAGEROOT=$INSTALLROOT=$EXECROOT=$CC='
+
+PACKAGE_admin_tail_timeout=${PACKAGE_admin_tail_timeout:-"1m"}
+
+CROSS=0
+
+admin_db=admin.db
+admin_env=admin.env
+admin_ditto="ditto --checksum --delete --verbose"
+admin_ditto_update=--update
+admin_ditto_skip="OFFICIAL|core|old|*.core|*.tmp|.nfs*"
+admin_list='PACKAGE.$type.lst'
+admin_ping="ping -c 1 -w 5"
+
+default_url=default.url
+MAKESKIP=${MAKESKIP:-"*[-.]*"}
+RATZ=ratz
+SED=
+TAR=tar
+TARFLAGS=xv
+TARPROBE=B
+TR=
+
+all_types='*.*|sun4' # all but sun4 match *.*
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) USAGE=$'
+[-?
+@(#)$Id: package (AT&T Research) 2012-02-29 $
+]'$USAGE_LICENSE$'
+[+NAME?package - source and binary package control]
+[+DESCRIPTION?The \bpackage\b command controls source and binary
+ packages. It is a \bsh\b(1) script coded for maximal portability. All
+ package files are in the \b$PACKAGEROOT\b directory tree.
+ \b$PACKAGEROOT\b must at minumum contain a \bbin/package\b command or a
+ \blib/package\b directory. Binary package files are in the
+ \b$INSTALLROOT\b (\b$PACKAGEROOT/arch/\b\ahosttype\a) tree, where
+ \ahosttpe\a=`\bpackage\b`. All \aactions\a but \bhost\b and \buse\b
+ require the current directory to be under \b$PACKAGEROOT\b. See
+ \bDETAILS\b for more information.]
+[+?Note that no environment variables need be set by the user;
+ \bpackage\b determines the environment based on the current working
+ directory. The \buse\b action starts a \bsh\b(1) with the environment
+ initialized. \bCC\b, \bCCFLAGS\b, \bHOSTTYPE\b and \bSHELL\b may be set
+ by explicit command argument assignments to override the defaults.]
+[+?Packages are composed of components. Each component is built and
+ installed by an \bast\b \bnmake\b(1) makefile. Each package is also
+ described by an \bnmake\b makefile that lists its components and
+ provides a content description. The package makefile and component
+ makefiles provide all the information required to read, write, build
+ and install packages.]
+[+?Package recipients only need \bsh\b(1) and \bcc\b(1) to build and
+ install source packages, and \bsh\b to install binary packages.
+ \bnmake\b and \bksh93\b are required to write new packages. An
+ \b$INSTALLROOT/bin/cc\b script may be supplied for some architectures.
+ This script supplies a reasonable set of default options for compilers
+ that accept multiple dialects or generate multiple object/executable
+ formats.]
+[+?The command arguments are composed of a sequence of words: zero or
+ more \aqualifiers\a, one \aaction\a, and zero or more action-specific
+ \aarguments\a, and zero or more \aname=value\a definitions. \apackage\a
+ names a particular package. The naming scheme is a \b-\b separated
+ hierarchy; the leftmost parts describe ownership, e.g.,
+ \bgnu-fileutils\b, \bast-base\b. If no packages are specified then all
+ packages are operated on. \boptget\b(3) documentation options are also
+ supported. The default with no arguments is \bhost type\b.]
+[+?The qualifiers are:]
+ {
+ [+authorize \aname\a?Remote authorization user name or license
+ acceptance phrase.]
+ [+debug|environment?Show environment and actions but do not
+ execute.]
+ [+flat?Collapse \b$INSTALLROOT\b { bin fun include lib } onto
+ \b$PACKAGEROOT\b.]
+ [+force?Force the action to override saved state.]
+ [+never?Run make -N and show other actions.]
+ [+only?Only operate on the specified packages.]
+ [+password \apassword\a?Remote authorization or license
+ acceptance password.]
+ [+quiet?Do not list captured action output.]
+ [+show?Run make -n and show other actions.]
+ [+verbose?Provide detailed action output.]
+ [+DEBUG?Trace the package script actions in detail.]
+ }
+[+?The actions are:]
+ {
+ [+admin\b [\ball\b]] [\bdb\b \afile\a]] [\bon\b \apattern\a]][\aaction\a ...]]?Apply
+ \aaction\a ... to the hosts listed in \afile\a. If \afile\a is
+ omitted then \badmin.db\b is assumed. The caller must have
+ \brcp\b(1) and \brsh\b(1) or \bscp\b(1) and \bssh\b(1) access
+ to the hosts. Output for \aaction\a is saved per-host in the
+ file \aaction\a\b.log/\b\ahost\a. Logs can be viewed by
+ \bpackage admin\b [\bon\b \ahost\a]] \bresults\b [\aaction\a]].
+ By default only local PACKAGEROOT hosts are selected from
+ \afile\a; \ball\b selects all hosts. \bon\b \apattern\a selects
+ only hosts matching the \b|\b separated \apattern\a. \afile\a
+ contains four types of lines. Blank lines and lines beginning
+ with \b#\b are ignored. Lines starting with \aid\a=\avalue\a
+ are variable assignments. Set admin_ping to local conventions
+ if \"'$admin_ping$'\" fails. If a package list is not specified
+ on the command line the \aaction\a applies to all packages; a
+ variable assigment \bpackage\b=\"\alist\a\" applies \aaction\a
+ to the packages in \alist\a for subsequent hosts in \afile\a.
+ The remaining line type is a host description consisting of 6
+ tab separated fields. The first 3 are mandatory; the remaining
+ 3 are updated by the \badmin\b action. \afile\a is saved in
+ \afile\a\b.old\b before update. The fields are:]
+ {
+ [+hosttype?The host type as reported by
+ \"\bpackage\b\".]
+ [+[user@]]host?The host name and optionally user name
+ for \brcp\b(1) and \brsh\b(1) access.]
+ [+[remote::[[master]]::]]]]PACKAGEROOT?The absolute remote package
+ root directory and optionally the remote protocol (rsh
+ or ssh) if the directory is on a different server than
+ the master package root directory. If
+ \blib/package/admin/'$admin_env$'\b exists under this
+ directory then it is sourced by \bsh\b(1) before
+ \aaction\a is done. If this field begins with \b-\b
+ then the host is ignored. If this field contains \b:\b
+ then \bditto\b(1) is used to sync the remote \bsrc\b
+ directory hierarchy to the local one. If [\amaster\a]]:
+ is specified then the sync is deferred to the \amaster\a
+ host. If \amaster\a is omitted (two :) then the sync is
+ disabled. These directories must exist on the remote side:
+ \blib/package\b, \bsrc/cmd\b, \bsrc/lib\b.]
+ [+date?\aYYMMDD\a of the last action.]
+ [+time?Elapsed wall time for the last action.]
+ [+M T W?The \badmin\b action \bmake\b, \btest\b and
+ \bwrite\b action error counts. A non-numeric value in
+ any of these fields disables the corresponding action.]
+ }
+ [+clean | clobber?Delete the \barch/\b\aHOSTTYPE\a hierarchy; this
+ deletes all generated files and directories for \aHOSTTYPE\a.
+ The heirarchy can be rebuilt by \bpackage make\b.]
+ [+contents\b [ \apackage\a ... ]]?List description and
+ components for \apackage\a on the standard output.]
+ [+copyright\b [ \apackage\a ... ]]?List the general copyright
+ notice(s) for \apackage\a on the standard output. Note that
+ individual components in \apackage\a may contain additional or
+ replacement notices.]
+ [+export\b [ \avariable\a ...]]?List \aname\a=\avalue\a for
+ \avariable\a, one per line. If the \bonly\b attribute is
+ specified then only the variable values are listed. If no
+ variables are specified then \b'$env$'\b are assumed.]
+ [+help\b [ \aaction\a ]]?Display help text on the standard
+ error (standard output for \aaction\a).]
+ [+host\b [ \aattribute\a ... ]]?List
+ architecture/implementation dependent host information on the
+ standard output. \btype\b is listed if no attributes are
+ specified. Information is listed on a single line in
+ \aattribute\a order. The attributes are:]
+ {
+ [+canon \aname\a?An external host type name to be
+ converted to \bpackage\b syntax.]
+ [+cpu?The number of cpus; 1 if the host is not a
+ multiprocessor.]
+ [+name?The host name.]
+ [+rating?The cpu rating in pseudo mips; the value is
+ useful useful only in comparisons with rating values of
+ other hosts. Other than a vax rating (mercifully) fixed
+ at 1, ratings can vary wildly but consistently from
+ vendor mips ratings. \bcc\b(1) may be required to
+ determine the rating.]
+ [+type?The host type, usually in the form
+ \avendor\a.\aarchitecture\a, with an optional trailing
+ -\aversion\a. The main theme is that type names within
+ a family of architectures are named in a similar,
+ predictable style. OS point release information is
+ avoided as much as possible, but vendor resistance to
+ release incompatibilities has for the most part been
+ futile.]
+ }
+ [+html\b [ \aaction\a ]]?Display html help text on the standard
+ error (standard output for \aaction\a).]
+ [+install\b [ \aarchitecture\a ... ]] \adirectory\a [ \apackage\a ... ]]?Copy
+ the package binary hierarchy to \adirectory\a. If
+ \aarchitecture\a is omitted then all architectures are
+ installed. If \bflat\b is specified then exactly one
+ \aarchitecture\a must be specified; this architecture will be
+ installed in \adirectory\a without the \barch/\b\aHOSTTYPE\a
+ directory prefixes. Otherwise each architecture will be
+ installed in a separate \barch/\b\aHOSTTYPE\a subdirectory of
+ \adirectory\a. The \aarchitecture\a \b-\b names the current
+ architecture. \adirectory\a must be an existing directory. If
+ \apackage\a is omitted then all binary packages are installed.
+ This action requires \bnmake\b.]
+ [+license\b [ \apackage\a ... ]]?List the source license(s) for
+ \apackage\a on the standard output. Note that individual
+ components in \apackage\a may contain additional or replacement
+ licenses.]
+ [+list\b [ \apackage\a ... ]]?List the name, version and
+ prerequisites for \apackage\a on the standard output.]
+ [+make\b [ \apackage\a ]] [ \aoption\a ... ]] [ \atarget\a ... ]]?Build
+ and install. The default \atarget\a is \binstall\b, which makes
+ and installs \apackage\a. If the standard output is a terminal
+ then the output is also captured in
+ \b$INSTALLROOT/lib/package/gen/make.out\b. The build is done in
+ the \b$INSTALLROOT\b directory tree viewpathed on top of the
+ \b$PACKAGEROOT\b directory tree. If \bflat\b is specified then
+ the \b$INSTALLROOT\b { bin fun include lib } directories are
+ linked to the same directories in the package root. Only one
+ architecture may be \bflat\b. Leaf directory names matching the
+ \b|\b-separated shell pattern \b$MAKESKIP\b are ignored. The
+ \bview\b action is done before making. \aoption\a operands are
+ passed to the underlying make command.]
+ [+read\b [ \apackage\a ... | \aarchive\a ... ]]?Read the named
+ package or archive(s). Must be run from the package root
+ directory. Archives are searched for in \b.\b and
+ \blib/package/tgz\b. Each package archive is read only once.
+ The file \blib/package/tgz/\b\apackage\a[.\atype\a]]\b.tim\b
+ tracks the read time. See the \bwrite\b action for archive
+ naming conventions. Text file archive member are assumed to be
+ ASCII or UTF-8 encoded.]
+ [+regress?\bdiff\b(1) the current and previous \bpackage test\b
+ results.]
+ [+release\b [ [\aCC\a]]\aYY-MM-DD\a [ [\acc\a]]\ayy-mm-dd\a ]]]] [ \apackage\a ]]?Display
+ recent changes for the date range [\aCC\a]]\aYY-MM-DD\a (up to
+ [\acc\a]]\ayy-mm-dd\a.), where \b-\b means lowest (or highest.)
+ If no dates are specified then changes for the last 4 months
+ are listed. \apackage\a may be a package or component name.]
+ [+remove\b [ \apackage\a ]]?Remove files installed for
+ \apackage\a.]
+ [+results\b [ \bfailed\b ]] [ \bpath\b ]] [ \bold\b ]] [\bmake\b | \btest\b | \bwrite\b ]]?List
+ results and interesting messages captured by the most recent
+ \bmake\b (default), \btest\b or \bwrite\b action. \bold\b
+ specifies the previous results, if any (current and previous
+ results are retained.) \b$HOME/.pkgresults\b, if it exists,
+ must contain an \begrep\b(1) expression of result lines to be
+ ignored. \bfailed\b lists failures only and \bpath\b lists the
+ results file path name only.]
+ [+setup\b [ beta ]] [ binary ]] [ source ]] [ \aarchitecture\a ... ]] [ \aurl\a ]] [ \apackage\a ... ]]?This
+ action initializes the current directory as a package root, runs the
+ \bupdate\b action to download new or out of date packages, and runs the
+ \bread\b action on those packages. If \bflat\b is specified then the
+ \b$INSTALLROOT\b { bin fun include lib } directories are linked to the
+ same directories in the package root. Only one architecture may be
+ \bflat\b. See the \bupdate\b and \bread\b action descriptions for
+ argument details.]
+ [+test\b [ \apackage\a ]]?Run the regression tests for
+ \apackage\a. If the standard output is a terminal then the
+ output is also captured in
+ \b$INSTALLROOT/lib/package/gen/test.out\b. In general a package
+ must be made before it can be tested. Components tested with
+ the \bregress\b(1) command require \bksh93\b. If \bonly\b is
+ also specified then only the listed package components are
+ tested, otherwise the closure of the components is tested.]
+ [+update\b [ beta ]] [ binary ]] [ source ]] [\aarchitecture\a ... ]] [ \aurl\a ]] [ \apackage\a ... ]]?Download
+ the latest release of the selected and required packages from \aurl\a
+ (e.g., \bhttp://www.research.att.com/sw/download\b) into the directory
+ \b$PACKAGEROOT/lib/package/tgz\b. \bbeta\b acesses beta packages;
+ download these at your own risk. If \aarchitecture\a is omitted then
+ only architectures already present in the \btgz\b directory will be
+ downloaded. If \aarchitecture\a is \b-\b then all posted architectures
+ will be downloaded. If \aurl\a matches \b*.url\b then it is interpreted
+ as a file containing shell variable assignments for \burl\b,
+ \bauthorize\b and \bpassword\b. If \aurl\a is omitted then the
+ definitions for \burl\b, \bauthorize\b and \bpassword\b in
+ \b$PACKAGEROOT/lib/package/tgz/default.url\b, if it exists, are used.
+ If \b$PACKAGEROOT/lib/package/tgz/default.url\b does not exist then it
+ is initialized with the current \burl\b, \bauthorize\b and \bpassword\b
+ values and read permission for the current user only. If \apackage\a is
+ omitted then only packages already present in the tgz directory will be
+ downloaded. If \apackage\a is \b-\b then all posted packages will be
+ downloaded. If \bsource\b and \bbinary\b are omitted then both source
+ and binary packages will be downloaded. If \bonly\b is specified then
+ only the named packages are updated; otherwise the closure of required
+ packages is updated. This action requires \bwget\b(1), \blynx\b(1),
+ \bcurl\b(1) or a shell that supports io to
+ \b/dev/tcp/\b\ahost\a/\aport\a.]
+ [+use\b [ \auid\a | \apackage\a | . [ 32 | 64 ]] | 32 | 64 | - ]] [ command ...]]?Run
+ \acommand\a, or an interactive shell if \acommand\a is omitted,
+ with the environment initialized for using the package (can you
+ say \ashared\a \alibrary\a or \adll\a without cussing?) If
+ \auid\a or \apackage\a or \a.\a is specified then it is used
+ to determine a \b$PACKAGEROOT\b, possibly different from
+ the current directory. For example, to try out bozo`s package:
+ \bpackage use bozo\b. The \buse\b action may be run from any
+ directory. If the file \b$INSTALLROOT/lib/package/profile\b is
+ readable then it is sourced to initialize the environment. 32 or 64
+ implies \b$PACKAGEROOT\b of . and specifies the target architecture
+ word size (which may be silently ignored.)]
+ [+verify\b [ \apackage\a ]]?Verify installed binary files
+ against the checksum files in
+ \b$INSTALLROOT/lib/\b\apackage\a\b/gen/*.sum\b. The checksum
+ files contain mode, user and group information. If the checksum
+ matches for a given file then the mode, user and group are
+ changed as necessary to match the checksum entry. A warning is
+ printed on the standard error for each mismatch. Requires the
+ \bast\b package \bcksum\b(1) command.]
+ [+view\b?Initialize the architecture specific viewpath
+ hierarchy. If \bflat\b is specified then the \b$INSTALLROOT\b {
+ bin fun include lib } directories are linked to the same
+ directories in the package root. Only one architecture may be
+ \bflat\b. The \bmake\b action implicitly calls this action.]
+ [+write\b [\aformat\a]] \atype\a ... [ \apackage\a ...]]?Write
+ a package archive for \apackage\a. All work is done in the
+ \b$PACKAGEROOT/lib/package\b directory. \aformat\a-specific
+ files are placed in the \aformat\a subdirectory. A
+ \apackage\a[.\atype\a]]\b.tim\b file in this directory tracks
+ the write time and prevents a package from being read in the
+ same root it was written. If more than one file is generated
+ for a particular \aformat\a then those files are placed in the
+ \aformat\a/\apackage\a subdirectory. File names in the
+ \aformat\a subdirectory will contain the package name, a
+ \ayyyy-mm-dd\a date, and for binary packages, \aHOSTTYPE\a. If
+ \apackage\a is omitted then an ordered list of previously
+ written packages is generated. If \bonly\b is specified then
+ only the named packages will be written; otherwise prerequisite
+ packages are written first. Package components must be listed
+ in \apackage\a\b.pkg\b. \aformat\a may be one of:]
+ {
+ [+cyg?Generate a \bcygwin\b package.]
+ [+exp?Generate an \bexptools\b maintainer source
+ archive and \aNPD\a file, suitable for \bexpmake\b(1)]
+ [+lcl?Generate a package archive suitable for
+ restoration into the local source tree (i.e., the
+ source is not annotated for licencing.)]
+ [+pkg?Generate a \bpkgmk\b(1) package suitable for
+ \bpkgadd\b(1).]
+ [+rpm?Generate an \brpm\b(1) package.]
+ [+tgz?Generate a \bgzip\b(1) \btar\b(1) package
+ archive. This is the default.]
+ [+tst?Generate a \btgz\b format package archive in the
+ \btst\b subdirectory. Version state files are not updated.]
+ }
+ [+?\btype\b specifies the package type which must be one of
+ \bsource\b, \bbinary\b or \bruntime\b. A source package
+ contains the source needed to build the corresponding binary
+ package. A binary package includes the libraries and headers
+ needed for compiling and linking against the public interfaces.
+ A runtime package contains the commands and required dynamic
+ libraries.]
+ [+?A package may be either a \bbase\b or \bdelta\b. A base
+ package contains a complete copy of all components. A delta
+ package contains only changes from a previous base package.
+ Delta recipients must have the \bast\b \bpax\b(1) command (in
+ the \bast-base\b package.) If neither \bbase\b nor \bdelta\b is
+ specified, then the current base is overwritten if there are no
+ deltas referring to the current base. Only the \btgz\b and
+ \blcl\b formats support \bdelta\b. If \bbase\b is specified
+ then a new base and two delta archives are generated: one delta
+ to generate the new base from the old, and one delta to
+ generate the old base from the new; the old base is then
+ removed. If \bdelta\b is specified then a new delta referring
+ to the current base is written.]
+ [+?\apackage\a\b.pkg\b may reference other packages. By default
+ a pointer to those packages is written. The recipient \bpackage
+ read\b will then check that all required packages have been
+ downloaded. If \bclosure\b is specified then the components for
+ all package references are included in the generated package.
+ This may be useful for \blcl\b and versioning.]
+ [+?All formats but \blcl\b annotate each \bsource\b file (not
+ already annotated) with a license comment as it is written to
+ the package archive using \bproto\b(1).]
+ }
+[+DETAILS?The package directory hierarchy is rooted at
+ \b$PACKAGEROOT\b. All source and binaries reside under this tree. A two
+ level viewpath is used to separate source and binaries. The top view is
+ architecture specific, the bottom view is shared source. All building
+ is done in the architecture specific view; no source view files are
+ intentionally changed. This means that many different binary
+ architectures can be made from a single copy of the source.]
+[+?Independent \b$PACKAGEROOT\b hierarchies can be combined by
+ appending \b$INSTALLROOT:$PACKAGEROOT\b pairs to \bVPATH\b. The
+ \bVPATH\b viewing order is from left to right. Each \b$PACKAGEROOT\b
+ must have a \b$PACKAGEROOT/lib/package\b directory.]
+[+?Each package contains one or more components. Component source for
+ the \afoo\a command is in \b$PACKAGEROOT/src/cmd/\b\afoo\a, and source
+ for the \abar\a library is in \b$PACKAGEROOT/src/lib/lib\b\abar\a. This
+ naming is for convenience only; the underlying makefiles handle
+ inter-component build order. The \bINIT\b component, which contains
+ generic package support files, is always made first, then the
+ components named \bINIT\b*, then the component order determined by the
+ closure of component makefile dependencies.]
+[+?\b$PACKAGEROOT/lib/package\b contains package specific files. The
+ package naming convention is \agroup\a[-\apart\a]]; e.g., \bast-base\b,
+ \bgnu-fileutils\b. The *\b.pkg\b files are ast \bnmake\b(1) makefiles
+ that contain the package name, package components, references to other
+ packages, and a short package description. *\b.pkg\b files are used by
+ \bpackage write\b to generate new source and binary packages.]
+[+?\b$PACKAGEROOT/lib/package/\b\agroup\a\b.lic\b files contain license
+ information that is used by the \bast\b \bproto\b(1) and \bnmake\b(1)
+ commands to generate source and binary license strings. \agroup\a is
+ determined by the first \b:PACKAGE:\b operator name listed in the
+ component \bnmake\b makefile. \agroup\a\b.lic\b files are part of the
+ licensing documentation. Each component may have its own \bLICENSE\b file
+ that overrides the \agroup\a\b.lic\b file. The full text of the licenses
+ are in the \b$PACKAGEROOT/lib/package/LICENSES\b and
+ \b$INSTALLROOT/lib/package/LICENSES\b directories.]
+[+?A few files are generated in \b$PACKAGEROOT/lib/package/gen\b and
+ \b$INSTALLROOT/lib/package/gen\b. \apackage\a\b.ver\b contains one line
+ consisting of \apackage version release\a \b1\b for the most recent
+ instance of \apackage\a read into \b$PACKAGEROOT\b, where \apackage\a
+ is the package name, \aversion\a is the \aYYYY-MM-DD\a base version,
+ and \arelease\a is \aversion\a for the base release or \aYYYY-MM-DD\a
+ for delta releases. \apackage\a\b.req\b contains *\b.ver\b entries for
+ the packages required by \apackage\a, except that the fourth field is
+ \b0\b instead of \b1\b. All packages except \bINIT\b require the
+ \bINIT\b package. A simple sort of \apackage\a\b.pkg\b and *\b.ver\b
+ determines if the required package have been read in. Finally,
+ \apackage\a\b.README\b and \apackage\a\a.html\b contain the README text
+ for \apackage\a and all its components. Included are all changes added
+ to the component \bRELEASE\b, \bCHANGES\b or \bChangeLog\b files dated
+ since the two most recent base releases. Component \bRELEASE\b files
+ contain tag lines of the form [\aYY\a]]\aYY-MM-DD\a [ \atext\a ]] (or
+ \bdate\b(1) format dates) followed by README text, in reverse
+ chronological order (newer entries at the top of the file.) \bpackage
+ release\b lists this information, and \bpackage contents ...\b lists
+ the descriptions and components.]
+[+?\b$HOSTYPE\b names the current binary architecture and is determined
+ by the output of \bpackage\b (no arguments.) The \b$HOSTTYPE\b naming
+ scheme is used to separate incompatible executable and object formats.
+ All architecture specific binaries are placed under \b$INSTALLROOT\b
+ (\b$PACKAGEROOT/arch/$HOSTTYPE\b.) There are a few places that match
+ against \b$HOSTTYPE\b when making binaries; these are limited to
+ makefile compiler workarounds, e.g., if \b$HOSTTYPE\b matches \bhp.*\b
+ then turn off the optimizer for these objects. All other architecture
+ dependent logic is handled either by the \bast\b \biffe\b(1) command or
+ by component specific configure scripts. Explicit \b$HOSTYPE\b
+ values matching *,*cc*[,-*,...]] optionally set the default \bCC\b and
+ \bCCFLAGS\b. This is handy for build farms that support different
+ compilers on the same architecture.]
+[+?Each component contains an \bast\b \bnmake\b(1) makefile (either
+ \bNmakefile\b or \bMakefile\b) and a \bMAM\b (make abstract machine)
+ file (\bMamfile\b.) A Mamfile contains a portable makefile description
+ that is used by \bmamake\b(1) to simulate \bnmake\b. Currently there is
+ no support for old-make/gnu-make makefiles; if the binaries are just
+ being built then \bmamake\b will suffice; if source or makefile
+ modifications are anticipated then \bnmake\b (in the \bast-base\b
+ package) should be used. Mamfiles are automatically generated by
+ \bpackage write\b.]
+[+?Most component C source is prototyped. If \b$CC\b (default value
+ \bcc\b) is not a prototyping C compiler then \bpackage make\b runs
+ \bproto\b(1) on portions of the \b$PACKAGEROOT/src\b tree and places
+ the converted output files in the \b$PACKAGEROOT/proto/src\b tree.
+ Converted files are then viewpathed over the original source.
+ \bproto\b(1) converts an ANSI C subset to code that is compatible with
+ K&R, ANSI, and C++ dialects.]
+[+?All scripts and commands under \b$PACKAGEROOT\b use \b$PATH\b
+ relative pathnames (via the \bast\b \bpathpath\b(3) function); there
+ are no imbedded absolute pathnames. This means that binaries generated
+ under \b$PACKAGEROOT\b may be copied to a different root; users need
+ only change their \b$PATH\b variable to reference the new installation
+ root \bbin\b directory. \bpackage install\b installs binary packages in
+ a new \b$INSTALLROOT\b.]
+
+[ qualifier ... ] [ action ] [ arg ... ] [ n=v ... ]
+
+[+SEE ALSO?\bautoconfig\b(1), \bcksum\b(1), \bexecrate\b(1), \bexpmake\b(1),
+ \bgzip\b(1), \bmake\b(1), \bmamake\b(1), \bnmake\b(1), \bpax\b(1),
+ \bpkgadd\b(1), \bpkgmk\b(1), \bproto\b(1), \bratz\b(1), \brpm\b(1),
+ \bsh\b(1), \btar\b(1), \boptget\b(3)]
+'
+ case $* in
+ help) set -- --man ;;
+ esac
+ while getopts -a $command "$USAGE" OPT
+ do :
+ done
+ shift $OPTIND-1
+ ;;
+esac
+
+# check the args
+
+case $AR in
+'') AR=ar ;;
+esac
+case $CC in
+'') CC=cc ;;
+esac
+case $LD in
+'') LD=ld ;;
+esac
+case $NM in
+'') NM=nm ;;
+esac
+
+action=
+admin_all=1
+admin_on=
+authorize=
+bit=
+exec=
+flat=0
+force=0
+global=
+hi=
+html=0
+ifs=${IFS-'
+ '}
+lo=
+make=
+makeflags='-k -K'
+nmakeflags=
+nmakesep=
+nl="
+"
+noexec=
+only=0
+output=
+package_src=
+password=
+quiet=0
+show=:
+tab=" "
+verbose=0
+AUTHORIZE=
+DEBUG=
+HURL=
+PROTOROOT=-
+SHELLMAGIC=-
+
+unset FIGNORE BINDIR DLLDIR ETCDIR FUNDIR INCLUDEDIR LIBDIR LOCALEDIR MANDIR SHAREDIR 2>/dev/null || true
+
+while :
+do case $# in
+ 0) set host type ;;
+ esac
+ case $1 in
+ admin|clean|clobber|contents|copyright|export|host|install|license|list|make|read|regress|release|remove|results|setup|test|update|use|verify|view|write|TEST)
+ action=$1
+ shift
+ break
+ ;;
+ authorize)
+ case $# in
+ 1) echo $command: $1: authorization user name argument expected >&2; exit 1 ;;
+ esac
+ shift
+ authorize=$1
+ shift
+ continue
+ ;;
+ debug|environment)
+ exec=echo make=echo show=echo
+ ;;
+ flat) flat=1
+ ;;
+ force) force=1
+ ;;
+ never) exec=echo noexec=-N
+ ;;
+ only) only=1
+ ;;
+ password)
+ case $# in
+ 1) echo $command: $1: authorization password argument expected >&2; exit 1 ;;
+ esac
+ shift
+ password=$1
+ shift
+ continue
+ ;;
+ quiet) quiet=1
+ ;;
+ show) exec=echo noexec=-n
+ ;;
+ verbose)verbose=1
+ ;;
+ DEBUG) DEBUG=1
+ PS4='+$LINENO:$SECONDS+ '
+ set -x
+ ;;
+ help|HELP|html|man|--[?m]*)
+ case $1 in
+ help) code=0
+ case $2 in
+ '') exec 1>&2 ;;
+ esac
+ ;;
+ html) code=0 html=1
+ ;;
+ *) code=2
+ exec 1>&2
+ ;;
+ esac
+ case $html in
+ 1) bO="<HTML>
+<HEAD>
+<TITLE>$2 package installation instructions</TITLE>
+<HEAD>
+<BODY bgcolor=white link=teal vlink=dimgray>"
+ eO='</BODY>
+</HTML>'
+ bH="<CENTER><H3><FONT face=courier color=red>"
+ eH='</FONT></H3></CENTER>'
+ bP='<P>'
+ bL='<P><TABLE cellpadding=0 cellspacing=2>'
+ bL2='<P><TABLE border=0 cellpadding=0 cellspacing=2>'
+ eL='</TABLE><P>'
+ bT='<TR><TD align=right valign=top><B>'
+ bD='</B></TD><TD align=left>' eD='</TD></TR>'
+ bB='<B>' eB='</B>'
+ bI='<I>' eI='</I>'
+ bX='<PRE>' eX='</PRE>'
+ bF='<TT>' eF='</TT>'
+ Camp='&amp;'
+ Mcurl='<A href=../../man/man1/curl.html>curl</A>(1)'
+ Mdate='<A href=../../man/man1/date.html>date</A>(1)'
+ Mfile='<A href=../../man/man1/file.html>file</A>(1)'
+ Mgunzip='<A href=../../man/man1/gzip.html>gunzip</A>(1)'
+ Mhurl='<A href=../../man/man1/hurl.html>hurl</A>(1)'
+ Mlynx='<A href=../../man/man1/lynx.html>lynx</A>(1)'
+ Mnmake='<A href=../../man/man1/nmake.html>nmake</A>(1)'
+ Mpackage='<A href=../../man/man1/package.html>package</A>(1)'
+ Mproto='<A href=../../man/man1/proto.html>proto</A>(1)'
+ Mratz='<A href=../../man/man1/ratz.html>ratz</A>'
+ Mtar='<A href=../../man/man1/tar.html>tar</A>(1)'
+ Mwget='<A href=../../man/man1/wget.html>wget</A>(1)'
+ ;;
+ *) bO='' eO=''
+ bH='' eH=':'
+ bP=''
+ bL='' eL=''
+ bL2=''
+ bT=' '
+ bD=' ' eD=''
+ bB='' eB=''
+ bI='' eI=''
+ bX='' eX=''
+ bF='"' eF='"'
+ Camp='&'
+ Mcurl='curl(1)'
+ Mdate='date(1)'
+ Mfile='file(1)'
+ Mgunzip='gunzip(1)'
+ Mhurl='hurl(1)'
+ Mlynx='lynx(1)'
+ Mnmake='nmake(1)'
+ Mpackage='package(1)'
+ Mproto='proto(1)'
+ Mratz='ratz'
+ Mtar='tar(1)'
+ Mwget='wget(1)'
+ ;;
+ esac
+ case $2 in
+ binary) echo "${bO}
+${bH}Binary Package Installation Instructions${eH}
+${bL}
+${bT}(1)${bD}Do not install packages as ${bI}root/super-user${eI}. Although some components may
+ have setuid executables, few must be owned by ${bI}root${eI}. These are best
+ changed manually when the security implications are understood.${eD}
+${bT}(2)${bD}Choose a package root directory and cd to it. This will be a local work
+ area for all packages.${eD}
+${bT}(3)${bD}These instructions bypass the ${bI}click to download${eI} package links on the
+ download site. If you already clicked, or if your system does not have
+ ${Mcurl}, ${Mhurl}, ${Mlynx} or ${Mwget} then use the alternate instructions
+ for (3),(4),(5) in plan ${bB}B${eB} below. Plan ${bB}B${eB} installs the ${Mhurl}
+ script which works with ksh and modern bash. The top level URL is:${bX}
+ URL=http://www.research.att.com/sw/download${eX}${eD}
+${bT}(4)${bD}If the ${bB}bin/package${eB} script does not exist then run:${bX}
+ test -d bin || mkdir bin
+ url=\$URL/package
+ (wget -O bin/package \$url||curl -L \$url||hurl \$url) > bin/package
+ chmod +x bin/package${eX}${eD}
+${bT}(5)${bD}Determine the list of package names you want from the download site, then
+ use the ${Mpackage} command to do the actual download:${bX}
+ bin/package authorize \"${bI}NAME${eI}\" password \"${bI}PASSWORD${eI}\" \\
+ setup binary \$URL ${bI}PACKAGE${eI} ...${eX}
+ (Refer to the ${bB}AUTHORIZATION${eB} paragraph on the main download page for
+ ${bI}NAME${eI}/${bI}PASSWORD${eI} details.) This downloads the closure of the latest
+ binary package(s); covered and up-to-date packages are not downloaded again unless
+ ${bB}package force ...${eB} is specified. Package content is verified using ${bB}${checksum}${eB}.
+ If the package root will contain only one architecture then you can install in ${bB}bin${eB} and
+ ${bB}lib${eB} instead of ${bB}arch/${eB}${bI}HOSTTYPE${eI}${bB}/bin${eB} and ${bB}arch/${eB}${bI}HOSTTYPE${eI}${bB}/lib${eB} by running this
+ instead:${bX}
+ bin/package authorize \"${bI}NAME${eI}\" password \"${bI}PASSWORD${eI}\" \\
+ flat setup binary \$URL ${bB}PACKAGE${eB} ...${eX}
+ To update the same packages from the same URL run:${bX}
+ bin/package setup binary${eX}${eD}
+${bT}(6)${bD}The packaged binaries are position independent, i.e., they do not
+ contain hard-coded paths. However, commands with related files, like
+ ${Mfile} and ${Mnmake}, require the path of the bin directory to be
+ exported in ${bB}PATH${eb}.${eD}
+${bT}(7)${bD}You can run the binaries directly from the package root, or you can
+ install them in a public root (requires the ${bI}AT${Camp}T${eI} ${Mnmake} command):${bX}
+ bin/package flat install ${bI}DIRECTORY PACKAGE${eI}${eX}
+ This will install in ${bI}DIRECTORY${eI}${bB}/bin${eB} and ${bI}DIRECTORY${eI}${bB}/lib${eB}. If you want to
+ preserve the ${bB}arch/${eB}${bI}HOSTTYPE${eI} hierarchy under ${bI}DIRECTORY${eI} then omit the
+ ${bB}flat${eB} argument. If you don't have ${Mnmake} then the following will do a
+ flat install:${bX}
+ cd \$INSTALLROOT
+ cp -p -r bin lib include ${bI}DIRECTORY${eI}${eX}${eD}
+${bT}(8)${bD}To summarize, after the first time, the download cycle for the latest
+ binary release is:${bX}
+ bin/package setup binary${eX}${eD}${eL}
+
+${bH}Binary Package Installation Instructions -- Plan B${eH}
+${bL}
+${bT}(3)${bD}Create the subdirectory ${bB}lib/package/tgz${eB} and download all package archives
+ into that directory.${eD}
+${bT}(4)${bD}If the ${bB}bin/package${eB} script does not exist then manually read the ${bB}INIT${eB}
+ binary package:${bX}
+ gunzip < lib/package/tgz/INIT.${bI}YYYY-MM-DD.HOSTTYPE${eI}.tgz |
+ ${TAR} ${TARFLAGS}f -${eX}
+ Note that some browsers automatically unzip downloaded without warning.
+ If the gunzip fails try:
+ ${TAR} ${TARFLAGS}f -${eX} lib/package/tgz/INIT.${bI}YYYY-MM-DD.HOSTTYPE${eI}.tgz
+ If your system does not have ${Mtar} or ${Mgunzip} then download the ${Mratz}
+ binary package:${bX}
+ mkdir bin
+ cp lib/package/tgz/ratz.${bI}YYYY-MM-DD.HOSTTYPE${eI}.exe bin/ratz
+ chmod +x bin/ratz
+ bin/ratz -lm < lib/package/tgz/INIT.${bI}YYYY-MM-DD/HOSTTYPE${eI}.tgz
+${bT}(5)${bD}Read all unread package archive(s):${bX}
+ bin/package read${eX}
+ Both source and binary packages will be read by this step.${eD}${eL}${eO}"
+ ;;
+ intro) echo "${bO}
+${bH}Package Hierarchy Details${eH}
+${bP}
+The package directory hierarchy is rooted at ${bB}\$PACKAGEROOT${eB}. All source and
+binaries reside under this tree. A two level viewpath is used to separate
+source and binaries. The top view is architecture specific, the bottom view
+is shared source. All building is done in the architecture specific view;
+no source view files are intentionally changed. This means that many
+different binary architectures can be made from a single copy of the source.
+${bP}
+Each package contains one or more components. Component source for the ${bI}FOO${eI}
+command is in ${bB}\$PACKAGEROOT/src/cmd/${eB}${bI}FOO${eI}, and source for the ${bI}BAR${eI} library is
+in ${bB}\$PACKAGEROOT/src/lib/lib${eB}${bI}BAR${eI}. This naming is for convenience only; the
+underlying makefiles handle inter-component build order. The ${bB}INIT${eB} component,
+which contains generic package support files, is always made first, then the
+components named ${bB}INIT${eB}*, then the order determined by the closure of component
+makefile dependencies.
+${bP}
+${bB}\$PACKAGEROOT/lib/package${eB} contains package specific files. The package naming
+convention is ${bI}GROUP${eI}[${bI}-PART${eI}]; e.g., ${bB}ast-base${eB}, ${bB}gnu-fileutils${eB}. The *${bB}.pkg${eB} files
+are ${bB}ast${eB} ${Mnmake} makefiles that contain the package name, package components,
+references to other packages, and a short package description. *${bB}.pkg${eB} files
+are used by ${bF}package write${eF} to generate new source and binary packages.
+${bP}
+${bB}\$PACKAGEROOT/lib/package/${eB}${bI}GROUP${eI}${bB}.lic${eB} files contain license information that
+is used by the ${bB}ast${eB} ${Mproto} and ${Mnmake} commands to generate source and
+binary license strings. ${bI}GROUP${eI} is determined by the first ${bB}:PACKAGE:${eB} operator
+name listed in the component ${bB}nmake${eB} makefile. ${bI}GROUP${eI}${bB}.lic${eB} files are part of the
+licensing documentation. Each component may have its own ${bB}LICENSE${eB} file that
+overrides the ${bI}GROUP${eI}${bB}.lic${eB} file. The full text of the licenses are in the
+${bB}\$PACKAGEROOT/lib/package/LICENSES${eB} and ${bB}\$INSTALLROOT/lib/package/LICENSES${eB}
+directories.
+${bP}
+A few files are generated in ${bB}\$PACKAGEROOT/lib/package/gen${eB} and
+${bB}\$INSTALLROOT/lib/package/gen${eB}. ${bI}PACKAGE${eI}${bB}.ver${eB} contains one line consisting of${bX}
+ ${bI}PACKAGE VERSION RELEASE${eI} 1${eX}
+for the most recent instance of ${bI}PACKAGE${eI} read into ${bB}\$PACKAGEROOT${eB}, where
+${bI}PACKAGE${eI} is the package name, ${bI}VERSION${eI} is the ${bI}YYYY-MM-DD${eI} base version,
+and ${bI}RELEASE${eI} is ${bI}VERSION${eI} for the base release or ${bI}YYYY-MM-DD${eI} for delta releases.
+${bI}PACKAGE${eI}${bB}.req${eB} contains *${bB}.ver${eB} entries for the packages required by
+${bI}PACKAGE${eI}, except that the fourth field is 0 instead of 1. All packages
+except ${bB}INIT${eB} and ${Mratz} require the ${bB}INIT${eB} package. A simple sort of ${bI}PACKAGE${eI}${bB}.pkg${eB}
+and *${bB}.ver${eB} determines if the required package have been read in. Finally,
+${bI}PACKAGE${eI}${bB}.README${eB} contains the ${bB}README${eB} text for ${bI}PACKAGE${eI} and all its
+components. Included are all changes added to the component ${bB}RELEASE${eB},
+${bB}CHANGES${eB} or ${bB}ChangeLog${eB} files dated since the two most recent base
+releases. Component ${bB}RELEASE${eB} files contain tag lines of the form
+[${bI}CC${eI}]${bI}YY-MM-DD${eI} [ ${bI}TEXT${eI} ] (or ${Mdate} format dates) followed by README
+text, in reverse chronological order (newer entries at the top of the
+file.) ${bF}package release${eF} generates this information, and
+${bF}package contents ...${eF} lists the descriptions and components.
+${bP}
+${bB}\$HOSTYPE${eB} names the current binary architecture and is determined by the
+output of ${bF}package${eF} (no arguments.) The ${bB}\$HOSTTYPE${eB} naming scheme is used
+to separate incompatible executable and object formats. All architecture
+specific binaries are placed under ${bB}\$INSTALLROOT${eB} (${bB}\$PACKAGEROOT/arch/\$HOSTTYPE${eB}.)
+There are a few places that match against ${bB}\$HOSTTYPE${eB} when making binaries; these
+are limited to makefile compiler workarounds, e.g., if ${bB}\$HOSTTYPE${eB} matches
+'hp.*' then turn off the optimizer for these objects. All other architecture
+dependent logic is handled either by ${bB}\$INSTALLROOT/bin/iffe${eB} or by component
+specific configure scripts. Explicit ${bB}\$HOSTYPE${eB} values matching *,*cc*[,-*,...]
+optionally set the default ${bB}CC${eB} and ${bB}CCFLAGS${eB}. This is handy for build
+farms that support different compilers on the same architecture.
+${bP}
+Each component contains an ${bB}ast${eB} ${Mnmake} makefile (either ${bB}Nmakefile${eB} or ${bB}Makefile${eB})
+and a ${bI}MAM${eI} (make abstract machine) file (${bB}Mamfile${eB}.) A Mamfile contains a portable
+makefile description that is used by ${bB}\$INSTALLROOT/bin/mamake${eB} to simulate
+${bB}nmake${eB}. Currently there is no support for old-make/gnu-make makefiles; if
+the binaries are just being built then ${bB}mamake${eB} will suffice; if source or
+makefile modifications are anticipated then ${bB}nmake${eB} (from the ${bB}ast-open${eB} or
+${bB}ast-base${eB} package) should be used. Mamfiles are automatically generated by
+${bF}package write${eF}.
+${bP}
+Most component C source is prototyped. If ${bB}\$CC${eB} (default value ${bB}cc${eB}) is not a
+prototyping C compiler then ${bF}package make${eF} runs ${Mproto} on portions of the
+${bB}\$PACKAGEROOT/src${eB} tree and places the converted output files in the
+${bB}\$PACKAGEROOT/proto/src${eB} tree. Converted files are then viewpathed over the
+original source. The ${bB}ast${eB} ${Mproto} command converts an ANSI C subset to code
+that is compatible with K&R, ANSI, and C++ dialects.
+${bP}
+All scripts and commands under ${bB}\$PACKAGEROOT${eB} use ${bB}\$PATH${eB} relative pathnames;
+there are no imbedded absolute pathnames. This means that binaries generated
+under ${bB}\$PACKAGEROOT${eB} may be copied to a different root; users need only change
+their ${bB}\$PATH${eB} variable to reference the new instalation root bin directory.
+${bF}package install${eF} installs binary packages in a new ${bB}\$INSTALLROOT${eB}.
+${eO}"
+ ;;
+ source) echo "${bO}
+${bH}Source Package Installation Instructions${eH}
+${bL}
+${bT}(1)${bD}Do not install packages as ${bI}root/super-user${eI}. Although some components may
+ have setuid executables, few must be owned by ${bI}root${eI}. These are best
+ changed manually when the security implications are understood.${eD}
+${bT}(2)${bD}Choose a package root directory and cd to it. This will be a local work
+ area for all packages.
+${bT}(3)${bD}These instructions bypass the ${bI}click to download${eI} package links on the
+ download site. If you already clicked, or if your system does not have
+ ${Mcurl}, ${Mhurl}, ${Mlynx} or ${Mwget} then use the alternate instructions
+ for (3),(4),(5) in plan ${bB}B${eB} below. Plan ${bB}B${eB} installs the ${Mhurl}
+ script which works with ksh and modern bash. The top level URL is:${bX}
+ URL=http://www.research.att.com/sw/download${eX}${eD}
+${bT}(4)${bD}If the ${bB}bin/package${eB} script does not exist then run:${bX}
+ test -d bin || mkdir bin
+ url=\$URL/package
+ (wget -O bin/package \$url||curl -L \$url||hurl \$url) > bin/package
+ chmod +x bin/package${eX}${eD}
+${bT}(5)${bD}Determine the list of package names you want from the download site, then
+ use the ${Mpackage} command to do the actual download:${bX}
+ bin/package authorize \"${bI}NAME${eI}\" password \"${bI}PASSWORD${eI}\" \\
+ setup source \$URL ${bB}PACKAGE${eB} ...${eX}
+ (Refer to the ${bB}AUTHORIZATION${eB} paragraph on the main download page for
+ ${bI}NAME${eI}/${bI}PASSWORD${eI} details.) This downloads the closure of the latest
+ source package(s); covered and up-to-date packages are not downloaded again unless
+ ${bB}package force ...${eB} is specified. Package content is verified using ${bB}${checksum}${eB}.
+ If the package root will contain only one architecture then you can install in ${bB}bin${eB} and
+ ${bB}lib${eB} instead of ${bB}arch/${eB}${bI}HOSTTYPE${eI}${bB}/bin${eB} and ${bB}arch/${eB}${bI}HOSTTYPE${eI}${bB}/lib${eB} by running this
+ instead:${bX}
+ bin/package authorize \"${bI}NAME${eI}\" password \"${bI}PASSWORD${eI}\" \\
+ flat setup source \$URL ${bB}PACKAGE${eB} ...${eX}
+ To update the same packages from the same URL run:${bX}
+ bin/package setup source${eX}${eD}
+${bT}(6)${bD}Build and install; all generated files are placed under ${bB}arch/${eB}${bI}HOSTTYPE${eI}
+ (${bB}\$INSTALLROOT${eB}), where ${bI}HOSTTYPE${eI} is the output of ${bB}bin/package${eB} (with no
+ arguments.) ${bI}name=value${eI} arguments are supported; ${bB}CC${eB} and ${bB}debug=1${eB} (compile
+ with -g instead of -O) are likely candidates. The output is written to
+ the terminal and captured in ${bB}\$INSTALLROOT/lib/package/gen/make.out${eB}:${bX}
+ bin/package make${eX}${eD}
+${bT}(7)${bD}List make results and interesting errors:${bX}
+ bin/package results${eX}
+ Run the regression tests:${bX}
+ bin/package test${eX}
+ List test results and errors:${bX}
+ bin/package results test${eX}${eD}
+${bT}(8)${bD}The generated binaries are position independent, i.e., they do not
+ contain hard-coded paths. However, commands with related files, like
+ ${Mfile} and ${Mnmake}, require the path of the bin directory to be
+ exported in ${bB}PATH${eb}.${eD}
+${bT}(9)${bD}You can run the binaries directly from the package root, or you can
+ install them in a public root after you are satisfied with the make and
+ test actions (requires the ${bI}AT${Camp}T${eI} ${Mnmake} command):${bX}
+ bin/package flat install ${bI}DIRECTORY PACKAGE${eI}${eX}
+ This will install in ${bI}DIRECTORY${eI}${bB}/bin${eB} and ${bI}DIRECTORY${eI}${bB}/lib${eB}. If you want to
+ preserve the ${bB}arch/${eB}${bI}HOSTTYPE${eI} hierarchy under ${bI}DIRECTORY${eI} then omit the
+ ${bB}flat${eB} argument. If you don't have ${Mnmake} then the following will do a
+ flat install:${bX}
+ cd \$INSTALLROOT
+ cp -p -r bin lib include ${bI}DIRECTORY${eI}${eX}${eD}
+${bT}(10)${bD}To summarize, after the first time the download, build, and test cycle
+ for the latest source release is:${bX}
+ bin/package setup source
+ bin/package make
+ bin/package test${eX}${eD}${eL}
+
+${bH}Source Package Installation Instructions -- Plan B${eH}
+${bL}
+${bT}(3)${bD}Create the subdirectory ${bB}lib/package/tgz${eB} and download all package archives
+ into that directory.${eD}
+${bT}(4)${bD}If the ${bB}bin/package${eB} script does not exist then manually read the ${bB}INIT${eB}
+ source package:${bX}
+ gunzip < lib/package/tgz/INIT.${bI}YYYY-MM-DD${eI}.tgz | ${TAR} ${TARFLAGS}f -${eX}
+ Note that some browsers automatically unzip downloaded without warning.
+ If the gunzip fails try:
+ ${TAR} ${TARFLAGS}f -${eX} lib/package/tgz/INIT.${bI}YYYY-MM-DD${eI}.tgz
+ If your system does not have ${Mtar} or ${Mgunzip} then download the ${Mratz}
+ source package, compile it, and manually read the ${bB}INIT${eB}
+ source package:${bX}
+ mkdir bin
+ cp lib/package/tgz/ratz.${bI}YYYY-MM-DD${eI}.c lib/package/tgz/ratz.c
+ cc -o bin/ratz lib/package/tgz/ratz.c
+ bin/ratz -lm < lib/package/tgz/INIT.${bI}YYYY-MM-DD${eI}.tgz
+${bT}(5)${bD}Read all unread package archive(s):${bX}
+ bin/package read${eX}
+ Both source and binary packages will be read by this step.${eD}${eL}${eO}"
+ ;;
+ *) echo "Usage: $command [ qualifier ... ] [ action ] [ arg ... ] [ n=v ... ]
+
+ The $command command controls source and binary packages. It must be run
+ within the package root directory tree. See \"$command help intro\" for
+ details. In the following, PACKAGE names either a package or a component
+ within a package; if omitted, all packages are operated on. The default
+ action is \"host type\".
+
+ qualifier:
+ authorize NAME Remote authorization name or license acceptance phrase.
+ debug|environment Show environment and actions; do not execute.
+ flat Collapse \$INSTALLROOT { bin fun include lib } onto \$PACKAGEROOT.
+ force Force the action to override saved state.
+ never Run make -N; otherwise show other actions.
+ only Only operate on the specified packages.
+ password PASSWORD Remote authorization or license acceptance password.
+ quiet Do not list captured make and test action output.
+ show Run make -n; otherwise show other actions.
+ DEBUG Trace the package script actions in detail for debugging.
+ action:
+ admin [ all ] [ db FILE ] [ on PATTERN ] [ action ... ]
+ Apply ACTION ... to the hosts listed in FILE. If FILE is
+ omitted then "admin.db" is assumed. The caller must have rcp(1)
+ and rsh(1) or scp(1) and ssh(1) access to the hosts. Output
+ for the action is saved per-host in ACTION.log/HOST. Logs
+ can be viewed by \"package admin [on HOST] results [ACTION]\".
+ By default only local PACKAGEROOT hosts are selected from FILE;
+ \"all\" selects all hosts. \"on PATTERN\" selects only
+ hosts matching the | separated PATTERN. FILE contains four
+ types of lines. Blank lines and lines beginning with # are
+ ignored. Lines starting with id=value are variable assignments.
+ Set admin_ping to local conventions if \"$admin_ping\" fails.
+ If a package list is not specified on the command line the
+ action applies to all packages; a variable assigment
+ package=list applies action to the packages in list for
+ subsequent hosts in FILE. The remaining line type is a host
+ description consisting of 6 tab separated fields. The first 3
+ are mandatory; the remaining 3 are updated by the admin action:
+ hosttype
+ The host type as reported by package.
+ [user@]host
+ The host name and optionally user name for rcp(1)
+ and rsh(1) access.
+ [remote:[[master]:]]PACKAGEROOT
+ The absolute remote package root directory and
+ optionally the remote prorocol (rsh or ssh) if
+ the directory is on a different server than the
+ master package root directory. If
+ lib/package/admin/$admin_env exists under
+ this directory then it is sourced by sh(1)
+ before ACTION is done. If this field begins with -
+ then the host is ignored. If this field contains
+ : then ditto(1) is used to sync the remote src
+ directory hierarchy to the local one. If [master]:
+ is specified then the sync is deferred to the
+ master host. If master is omitted (two :) then
+ the sync is disabled. These directories must exist
+ on the remote side: lib/package, src/cmd, src/lib.
+ date YYMMDD of the last action.
+ date Elapsed wall time of the last action.
+ M T W The admin action make, test and write action error
+ counts. A non-numeric value in any of these fields
+ disables the corresponding action.
+ clean | clobber
+ Delete the arch/HOSTTYPE hierarchy; this deletes all generated
+ files and directories for HOSTTYPE. The heirarchy can be rebuilt
+ by package make.]
+ contents [ package ... ]
+ List description and components for PACKAGE on the standard
+ output.
+ copyright [ package ... ]
+ List the general copyright notice(s) for PACKAGE on the
+ standard output. Note that individual components in PACKAGE
+ may contain additional or replacement notices.
+ export [ VARIABLE ... ]
+ List NAME=VALUE for each VARIABLE, one per line. If the
+ \"only\" attribute is specified then only the variable
+ values are listed. If no variables are specified then
+ $env are assumed.
+ help [ ACTION ]
+ Display help text on the standard error [ standard output
+ for ACTION ].
+ host [ canon cpu name rating type ... ]
+ List architecture/implementation dependent host information
+ on the standard output. type is listed if no attributes are
+ specified. Information is listed on a single line in attributes
+ order. The attributes are:
+ canon The next argument is a host type name to be
+ converted to package syntax.
+ cpu The number of cpus; 1 if the host is not a
+ multiprocessor.
+ name The host name.
+ rating The cpu rating in pseudo mips; the value is useful
+ useful only in comparisons with rating values of
+ other hosts. Other than a vax rating fixed at 1,
+ ratings can vary wildly but consistently from
+ vendor mips ratings. cc(1) may be required to
+ determine the rating.
+ type The host type, usually of the form
+ vendor.architecture, with an optional trailing
+ -version. The main theme is that type names within
+ a family of architectures are named in a similar,
+ predictable style. Os point release information is
+ avoided as much as possible, but vendor resistance
+ to release incompatibilities has for the most part
+ been futile.
+ html [ ACTION ]
+ Display html help text on the standard error [ standard output
+ for ACTION ].
+ install [ ARCHITECTURE ... ] DIR [ PACKAGE ... ]
+ Copy the package binary hierarchy to DIR. If ARCHITECTURE is
+ omitted then all architectures are installed. If the \"flat\"
+ attribute is specified then exactly one ARCHITECTURE must be
+ specified; this architecture will be installed in DIR without
+ the \"arch/HOSTTYPE\" directory prefixes. Otherwise each
+ architecture will be installed in a separate \"arch/HOSTTYPE\"
+ subdirectory of DIR. The ARCHITECTURE - names the current
+ architecture. DIR must be an existing directory. If PACKAGE
+ is omitted then all binary packages are installed. This action
+ requires nmake.
+ license [ package ... ]
+ List the source license(s) for PACKAGE on the standard output.
+ Note that individual components in PACKAGE may contain
+ additional or replacement licenses.
+ list [ PACKAGE ... ]
+ List the name, version and prerequisites for PACKAGE on the
+ standard output.
+ make [ PACKAGE ] [ OPTION ... ] [ TARGET ... ]
+ Build and install. The default TARGET is install, which
+ makes and installs all packages. If the standard output
+ is a terminal then the output is also captured in
+ \$INSTALLROOT/lib/package/gen/make.out. The build is done
+ in the \$INSTALLROOT directory tree viewpathed on top of
+ the \$PACKAGEROOT directory tree. If \"flat\" is specified then
+ the \$INSTALLROOT { bin fun include lib } directories are
+ linked to the same directories in the package root. Only
+ one architecture may be flat. Leaf directory names matching
+ the |-separated shell pattern \$MAKESKIP are ignored. The
+ view action is done before making. OPTION operands are
+ passed to the underlying make command.
+ read [ package ... | archive ... ]
+ Read the named package archive(s). Must be run from the
+ package root directory. Archives are searched for in .
+ and lib/package/tgz. Each package is read only once. The
+ file lib/package/tgz/package[.type].tim tracks the read time.
+ See the write action for archive naming conventions. Text
+ file archive member are assumed to be ASCII or UTF-8 encoded.
+ regress diff(1) the current and previous package test results.
+ release [ [CC]YY-MM-DD [ [cc]yy-mm-dd ] ] [ package ]
+ Display recent changes since [CC]YY-MM-DD (up to [cc]yy-mm-dd),
+ where - means lowest (or highest.) If no dates are specified
+ then changes for the last 4 months are listed. PACKAGE may
+ be a package or component name.
+ remove PACKAGE
+ Remove files installed for PACKAGE.
+ results [ path ] [ old ] [ make | test ]
+ List results and interesting messages captured by the most
+ recent make (default), test or write action. old specifies the
+ previous results, if any (current and previous results are
+ retained.) $HOME/.pkgresults, if it exists, must contain an
+ egrep(1) expression of result lines to be ignored. failed lists
+ failures only and path lists the results file path only.
+ setup [ beta ] [ binary ] [ source ] [ ARCHITECTURE ... ] [ URL ] [ PACKAGE ... ]
+ The action initializes the current directory as a package root,
+ runs the update action to download new or out of date packages,
+ and runs the read action on those packages. If \"flat\" is
+ specified then the \$INSTALLROOT { bin fun include lib }
+ directories are linked to the same directories in the package
+ root. Only one architecture may be flat. See the update and
+ read actions for argument details.
+ test [ PACKAGE ]
+ Run the regression tests for PACKAGE. If the standard output
+ is a terminal then the output is also captured in
+ \$INSTALLROOT/lib/package/gen/test.out. In general a package
+ must be made before it can be tested. Components tested with
+ the \bregress\b(1) command require \bksh93\b. If only is
+ also specified then only the listed package components are
+ tested, otherwise the closure of the components is tested.
+ update [ beta ] [ binary ] [ source ] [ ARCHITECTURE ... ] [ URL ] [ PACKAGE ... ]
+ Download the latest release of the selected and required
+ packages from URL (e.g.,
+ http://www.research.att.com/sw/download) into the directory
+ \$PACKAGEROOT/lib/package/tgz. beta acesses beta packages;
+ download these at your own risk. If ARCHITECTURE is omitted
+ then only architectures already present in the tgz directory
+ will be downloaded. If ARCHITECTURE is - then all posted
+ architectures will be downloaded. If URL matches *.url then
+ it is interpreted as a file containing shell variable
+ assignments for url, authorize and password. If URL is
+ omitted then the definitions for url, authorize and password
+ in \$PACKAGEROOT/lib/package/tgz/$default_url, if it exists,
+ are used. If \$PACKAGEROOT/lib/package/tgz/$default_url does
+ not exist then it is initialized with the current url,
+ authorize and password values and read permission for the
+ current user only. If PACKAGE is omitted then only
+ packages already present in the tgz directory will be
+ downloaded. If PACKAGE is - then all posted packages will be
+ downloaded. If source and binary are omitted then both source
+ and binary packages will be downloaded. If \bonly\b is
+ specified then only the named packages are updated; otherwise
+ the closure of required packages is updated. This action
+ requires wget(1), lynx(1), curl(1) or a shell that supports
+ io to /dev/tcp/HOST/PORT.
+ use [ uid | PACKAGE | . [ 32 | 64 ] | 32 | 64 | - ] [ COMMAND ... ]
+ Run COMMAND or an interactive shell if COMMAND is omitted, with
+ the environment initialized for using the package (can you say
+ shared library without cussing?) If uid or PACKAGE or . is
+ specified then it is used to determine a \$PACKAGEROOT,
+ possibly different from the current directory. For example, to
+ try out bozo's package: \"package use bozo\". In this case the
+ command may be run from any directory. If the file
+ \$INSTALLROOT/lib/package/profile is readable then it is
+ sourced to initialize the environment. 32 or 64 implies
+ \$PACKAGEROOT of . and specifies the target architecture word
+ size (which may be silently ignored.)
+ verify [ PACKAGE ]
+ Verify installed binary files against the checksum files in
+ \$INSTALLROOT/lib/package/gen/*.sum. The checksum files contain
+ mode, user and group information. If the checksum matches
+ for a given file then the mode, user and group are changed
+ as necessary to match the checksum entry. A warning is printed
+ on the standard error for each mismatch. Requires the ast
+ package cksum(1) command.
+ view
+ Initialize the architecture specific viewpath hierarchy. The
+ make action implicitly calls this action. If \"flat\" is specified
+ then the \$INSTALLROOT { bin fun include lib } directories are
+ linked to the same directories in the package root. Only one
+ architecture may be flat.
+ write [closure] [cyg|exp|lcl|pkg|rpm|tgz|tst] [base|delta]
+ [binary|runtime|source] PACKAGE
+ Write a package archive for PACKAGE. All work is done in the
+ \$PACKAGEROOT/lib/package directory. FORMAT-specific files
+ are placed in the FORMAT subdirectory. A PACKAGE[.TYPE].tim
+ file in this directory tracksthe write time and prevents a
+ package from being read in the same root it was written. If
+ more than one file is generated for a particular FORMAT then
+ those files are placed in the FORMAT/PACKAGE subdirectory.
+ File names in the FORMAT subdirectory will contain the package
+ name, a YYYY-MM-DD date, and for binary packages, HOSTTYPE.
+ If PACKAGE is omitted then an ordered list of previously
+ written packages is generated. If \"only\" is specified then
+ only the named packages will be written; otherwise
+ prerequisite packages are written first. Package components
+ must be listed in PACKAGE.pkg. FORMAT may be one of:
+ cyg generate a cygwin package
+ exp generate an exptools(1) maintainer source archive
+ and NPD file in the exp subdirectory, suitable for
+ expmake(1); support files are placed in the
+ exp/PACKAGE subdirectory
+ lcl generate a package archive or delta in the lcl
+ subdirectory, suitable for restoration into the
+ primary source tree (no source licence annotation)
+ pkg generate a pkgmk(1) package, suitable for pkgadd(1)
+ rpm generate an rpm(1) package
+ tgz generate a gzip(1) tar(1) package archive; this is
+ the default
+ tst generate tgz FORMAT package archive in the tst
+ subdirectory; version state files are not updated
+ The package type must be one of source, binary or runtime.
+ A source package contains the source needed to build the
+ corresponding binary package. A binary package includes the
+ libraries and headers needed for compiling and linking
+ against the public interfaces. A runtime package contains
+ the commands and required dynamic libraries. A package may
+ be either a base or delta. A base package contains a
+ complete copy of all components. A delta package contains
+ only changes from a previous base package. Delta recipients
+ must have the ast pax(1) command (in the ast-base package.)
+ If neither base nor delta is specified, then the current
+ base is overwritten if there are no deltas referring to the
+ current base. Only the tgz and lcl formats support delta.
+ If base is specified then a new base and two delta archives
+ are generated: one delta to generate the new base from the
+ old, and one delta to generate the old base from the new;
+ the old base is then removed. If delta is specified then a
+ new delta referring to the current base is written.
+ package.pkg may reference other packages. By default a
+ pointer to those packages is written. The recipient package
+ read will then check that all required packages have been
+ downloaded. If closure is specified then the components for
+ all package references are included in the generated
+ package. This may be useful for lcl and versioning. All
+ formats but lcl annotate each source file (not already
+ annotated) with a license comment as it is written to the
+ package archive using proto(1).
+ name=value:
+ variable definition: typically CC=cc or CCFLAGS=-g."
+ ;;
+ esac
+ exit $code
+ ;;
+ *=*) set DEFAULT host type "$@"
+ ;;
+ *) echo "Usage: $command [ options ] [ qualifier ... ] [ action ] [ arg ... ] [ n=v ... ]" >&2
+ exit 2
+ ;;
+ esac
+ global="$global $1"
+ shift
+done
+
+# gather HOSTTYPE *,* options
+# ,*cc*,-*,... set CC and CCFLAGS
+
+hostopts()
+{
+ _ifs_=$IFS
+ IFS=,
+ set '' $HOSTTYPE
+ IFS=$_ifs_
+ shift
+ while :
+ do case $# in
+ 0|1) break ;;
+ esac
+ shift
+ case $1 in
+ *cc*) CC=$1
+ while :
+ do case $# in
+ 0|1) break ;;
+ esac
+ case $2 in
+ -*) case $assign_CCFLAGS in
+ ?*) assign_CCFLAGS="$assign_CCFLAGS " ;;
+ esac
+ assign_CCFLAGS="$assign_CCFLAGS$2"
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ done
+}
+
+# collect command line targets and definitions
+
+case $_PACKAGE_HOSTTYPE_ in
+?*) HOSTTYPE=$_PACKAGE_HOSTTYPE_
+ KEEP_HOSTTYPE=1
+ ;;
+*) KEEP_HOSTTYPE=0
+ ;;
+esac
+KEEP_PACKAGEROOT=0
+KEEP_SHELL=0
+USER_VPATH=
+args=
+assign=
+assign_CCFLAGS=
+for i
+do case $i in
+ *:*=*) args="$args $i"
+ continue
+ ;;
+ *=*) eval `echo ' ' "$i" | sed 's,^[ ]*\([^=]*\)=\(.*\),n=\1 v='\''\2'\'','`
+ ;;
+ esac
+ case $i in
+ AR=*|LD=*|NM=*)
+ assign="$assign $n='$v'"
+ eval $n='$'v
+ ;;
+ CC=*) eval $n='$'v
+ ;;
+ CCFLAGS=*)
+ eval $n='$'v
+ assign_CCFLAGS="CCFLAGS=\"\$CCFLAGS\""
+ ;;
+ HOSTTYPE=*)
+ eval $n='$'v
+ case $HOSTTYPE in
+ ?*) KEEP_HOSTTYPE=1 ;;
+ esac
+ ;;
+ HURL=*) eval $n='$'v
+ ;;
+ PACKAGEROOT=*)
+ eval $n='$'v
+ case $PACKAGEROOT in
+ ?*) KEEP_PACKAGEROOT=1 ;;
+ esac
+ ;;
+ SHELL=*)eval $n='$'v
+ case $SHELL in
+ ?*) KEEP_SHELL=1 ;;
+ esac
+ ;;
+ TAR=*) eval $n='$'v
+ ;;
+ TARFLAGS=*)
+ eval $n='$'v
+ ;;
+ VPATH=*)eval USER_$n='$'v
+ ;;
+ 'debug=1')
+ makeflags="$makeflags --debug-symbols"
+ ;;
+ 'strip=1')
+ makeflags="$makeflags --strip-symbols"
+ ;;
+ *=*) assign="$assign $n='$v'"
+ ;;
+ *) args="$args $i"
+ ;;
+ esac
+done
+case $HOSTTYPE in
+*,*) hostopts $HOSTTYPE ;;
+esac
+case $assign_CCFLAGS in
+?*) assign="$assign $assign_CCFLAGS"
+esac
+case $CC in
+''|cc) ;;
+*) export CC ;;
+esac
+
+# grab action specific args
+
+case $action in
+admin) while :
+ do case $# in
+ 0) set list
+ break
+ ;;
+ esac
+ case $1 in
+ all) admin_all=1
+ ;;
+ db) case $# in
+ 1) echo $command: $action: $1: db file argument expected >&2
+ exit 1
+ ;;
+ esac
+ shift
+ admin_db=$1
+ ;;
+ on) case $# in
+ 1) echo $command: $action: $1: host pattern argument expected >&2
+ exit 1
+ ;;
+ esac
+ shift
+ admin_on=$1
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ done
+ admin_action=$1
+ admin_args=$*
+ for i
+ do case $i in
+ debug|environment|force|never|only|quiet|show|DEBUG)
+ ;;
+ *) admin_action=$i
+ break
+ ;;
+ esac
+ done
+ ;;
+setup) PACKAGEROOT=${PWD:-`pwd`}
+ export PACKAGEROOT
+ KEEP_PACKAGEROOT=1
+ ;;
+use) case $1 in
+ .|32|64)case $1 in
+ 32|64) bit=$1 ;;
+ esac
+ shift
+
+ # HOSTTYPE specific setup
+
+ case $HOSTTYPE in
+ win32.*)sys=uwin
+ wow=`uname -i`
+ case $bit in
+ 32) case $HOSTTYPE in
+ *-64) HOSTTYPE=${HOSTTYPE%-64} ;;
+ esac
+ case $wow in
+ */32) ;;
+ *) vpath / /$bit ;;
+ esac
+ ;;
+ 64) case $HOSTTYPE in
+ *-64) ;;
+ *) HOSTTYPE=$HOSTTYPE-64 ;;
+ esac
+ case $wow in
+ */32) echo $command: cannot build $bit-bit on $wow $sys >&2; exit 2 ;;
+ *) vpath / /$bit ;;
+ esac
+ ;;
+ esac
+ case $bit in
+ '') PS1="($sys) " ;;
+ *) PS1="($sys-$bit) " ;;
+ esac
+
+ $exec umask 002
+ $exec unset MAKESKIP
+
+ $exec export P=$PWD
+ $exec export A=$P/arch/$HOSTTYPE
+
+ $exec export CDPATH=:..:$A/src/cmd:$A/src/lib:$A/src/uwin:$P/lib/package
+ $exec export INSTALLROOT=$A
+ $exec export PACKAGEROOT=$P
+ $exec export PATH=$A/bin:$P/bin:$PATH
+ $exec export PS1="$PS1"
+ $exec export VPATH=$A:$P
+ $exec export nativepp=/usr/lib
+
+ if test '' != "$INSTALLROOT" -a -d $INSTALLROOT/include/ast
+ then $exec export PACKAGE_ast=$INSTALLROOT
+ elif test -d ${PWD%/*}/ast/arch/$HOSTTYPE
+ then $exec export PACKAGE_ast=${PWD%/*}/ast/arch/$HOSTTYPE
+ fi
+
+ # run the command
+
+ case $# in
+ 0) case $show in
+ ':') $exec exec $SHELL ;;
+ esac
+ ;;
+ *) $exec exec $SHELL -c "$@"
+ ;;
+ esac
+ exit
+ ;;
+ esac
+ PACKAGEROOT=${PWD:-`pwd`}
+ $show export PACKAGEROOT
+ esac
+ ;;
+esac
+
+# true if arg is a valid PACKAGEROOT
+
+packageroot() # dir
+{
+ test -d $1/lib/$command -o -x $1/bin/$command
+}
+
+# true if arg is executable
+
+executable() # [!] command
+{
+ case $1 in
+ '!') test ! -x "$2" -a ! -x "$2.exe"; return ;;
+ *) test -x "$1" -o -x "$1.exe"; return ;;
+ esac
+}
+
+# initialize SHELLMAGIC
+# tangible proof of cygwin's disdain for unix (well, this and execrate)
+
+shellmagic()
+{
+ case $SHELLMAGIC in
+ '') ;;
+ -) if test -f /emx/bin/sh.exe
+ then SHELLMAGIC='#!/emx/bin/sh.exe'$nl
+ elif test -f /bin/env.exe
+ then SHELLMAGIC='#!/bin/env sh'$nl
+ else SHELLMAGIC=
+ fi
+ ;;
+ esac
+}
+
+# true if arg is executable command on $PATH
+
+onpath() # command
+{
+ _onpath_b=$1
+ case $_onpath_b in
+ /*) if executable $_onpath_b
+ then _onpath_=$_onpath_b
+ return 0
+ fi
+ return 1
+ ;;
+ esac
+ IFS=':'
+ set '' $PATH
+ IFS=$ifs
+ shift
+ for _onpath_d
+ do case $_onpath_d in
+ '') _onpath_d=. ;;
+ esac
+ if executable "$_onpath_d/$_onpath_b"
+ then _onpath_=$_onpath_d/$_onpath_b
+ return 0
+ fi
+ done
+ return 1
+}
+
+# true if no nmake or nmake not from AT&T or nmake too old
+
+nonmake() # nmake
+{
+ _nonmake_version=`( $1 -n -f - 'print $(MAKEVERSION:@/.*AT&T.* //:/-//G:@/.* .*/19960101/)' . ) </dev/null 2>/dev/null || echo 19840919`
+ if test $_nonmake_version -lt 20001031
+ then return 0
+ fi
+ return 1
+}
+
+# determine local host attributes
+
+hostinfo() # attribute ...
+{
+ case $DEBUG in
+ 1) set -x ;;
+ esac
+ map=
+ something=
+ path=$PATH
+ for i in $ccs
+ do PATH=$PATH:$i
+ done
+ for i in $use
+ do for j in $org
+ do PATH=$PATH:$i/$j/bin
+ done
+ PATH=$PATH:$i/bin
+ done
+ # LD_LIBRARY_PATH may be out of sync with PATH here
+ case $SED in
+ '') SED=sed
+ $SED 1d < /dev/null > /dev/null 2>&1 ||
+ for dir in /bin /usr/bin
+ do if test -x $dir/$SED
+ then SED=$dir/$SED
+ break
+ fi
+ done
+ TR=tr
+ $TR < /dev/null > /dev/null 2>&1 ||
+ for dir in /bin /usr/bin
+ do if test -x $dir/$TR
+ then TR=$dir/$TR
+ break
+ fi
+ done
+ ;;
+ esac
+ case $PACKAGE_PATH in
+ ?*) for i in `echo $PACKAGE_PATH | $SED 's,:, ,g'`
+ do PATH=$PATH:$i/bin
+ done
+ ;;
+ esac
+
+ # validate the args
+
+ canon=
+ cc=$CC
+ for info
+ do case $canon in
+ -) canon=$info
+ ;;
+ *) case $info in
+ */*|*[cC][cC])
+ cc=$info
+ ;;
+ canon) canon=-
+ something=1
+ ;;
+ cpu|name|rating|type)
+ something=1
+ ;;
+ *) echo "$command: $action: $info: unknown attribute" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $canon in
+ -) echo "$command: $action: canon: host type name expected" >&2
+ exit 1
+ ;;
+ esac
+ case $something in
+ "") set "$@" type ;;
+ esac
+ case $DEBUG in
+ '') exec 9>&2
+ exec 2>/dev/null
+ ;;
+ esac
+
+ # compute the info
+
+ _hostinfo_=
+ for info
+ do
+ case $info in
+ cpu) case $NPROC in
+ [123456789]*)
+ _hostinfo_="$_hostinfo_ $NPROC"
+ continue
+ ;;
+ esac
+ cpu=`grep -ic '^processor[ ][ ]*:[ ]*[0123456789]' /proc/cpuinfo`
+ case $cpu in
+ [123456789]*)
+ _hostinfo_="$_hostinfo_ $cpu"
+ continue
+ ;;
+ esac
+ cpu=1
+ # exact match
+ set \
+ hinv '^Processor [0123456789]' \
+ psrinfo 'on-line' \
+ 'cat /reg/LOCAL_MACHINE/Hardware/Description/System/CentralProcessor' '.' \
+ 'cat /proc/registry/HKEY_LOCAL_MACHINE/Hardware/Description/System/CentralProcessor' '.' \
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ i=`$1 2>/dev/null | grep -c "$2"`
+ case $i in
+ [123456789]*)
+ cpu=$i
+ break
+ ;;
+ esac
+ shift;shift
+ done
+ case $cpu in
+ 0|1) set \
+ /bin/mpstat
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ if executable $1
+ then case `$1 | grep -ic '^cpu '` in
+ 1) cpu=`$1 | grep -ic '^ *[0123456789][0123456789]* '`
+ break
+ ;;
+ esac
+ fi
+ shift
+ done
+ ;;
+ esac
+ case $cpu in
+ 0|1) # token match
+ set \
+ /usr/kvm/mpstat 'cpu[0123456789]' \
+ /usr/etc/cpustatus 'enable' \
+ /usr/alliant/showsched 'CE' \
+ 'ls /config/hw/system/cpu' 'cpu' \
+ prtconf 'cpu-unit' \
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ i=`$1 2>/dev/null | $TR ' ' '
+
+' | grep -c "^$2"`
+ case $i in
+ [123456789]*)
+ cpu=$i
+ break
+ ;;
+ esac
+ shift;shift
+ done
+ ;;
+ esac
+ case $cpu in
+ 0|1) # special match
+ set \
+ \
+ hinv \
+ '/^[0123456789][0123456789]* .* Processors*$/' \
+ '/[ ].*//' \
+ \
+ /usr/bin/hostinfo \
+ '/^[0123456789][0123456789]* .* physically available\.*$/' \
+ '/[ ].*//' \
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ i=`$1 2>/dev/null | $SED -e "${2}!d" -e "s${3}"`
+ case $i in
+ [123456789]*)
+ cpu=$i
+ break
+ ;;
+ esac
+ shift;shift;shift
+ done
+ ;;
+ esac
+ case $cpu in
+ 0|1) cpu=`(
+ cd ${TMPDIR:-/tmp}
+ tmp=hi$$
+ trap 'rm -f $tmp.*' 0 1 2
+ cat > $tmp.c <<!
+#include <stdio.h>
+#include <pthread.h>
+int main()
+{
+ printf("%d\n", pthread_num_processors_np());
+ return 0;
+}
+!
+ for o in -lpthread ''
+ do if $CC $o -O -o $tmp.exe $tmp.c $o >/dev/null 2>&1 ||
+ gcc $o -O -o $tmp.exe $tmp.c $o >/dev/null 2>&1
+ then ./$tmp.exe
+ break
+ fi
+ done
+ )`
+ case $cpu in
+ [0123456789]*) ;;
+ *) cpu=1 ;;
+ esac
+ ;;
+ esac
+ _hostinfo_="$_hostinfo_ $cpu"
+ ;;
+ name) _name_=`hostname || uname -n || cat /etc/whoami || echo local`
+ _hostinfo_="$_hostinfo_ $_name_"
+ ;;
+ rating) for rating in `grep -i ^bogomips /proc/cpuinfo 2>/dev/null | $SED -e 's,.*:[ ]*,,' -e 's,\(...*\)\..*,\1,' -e 's,\(\..\).*,\1,'`
+ do case $rating in
+ [0123456789]*) break ;;
+ esac
+ done
+ case $rating in
+ [0123456789]*) ;;
+ *) cd ${TMPDIR:-/tmp}
+ tmp=hi$$
+ trap 'rm -f $tmp.*' 0 1 2
+ cat > $tmp.c <<!
+#include <stdio.h>
+#include <sys/types.h>
+#if TD || TZ
+#include <sys/time.h>
+#else
+extern time_t time();
+#endif
+int main()
+{
+ register unsigned long i;
+ register unsigned long j;
+ register unsigned long k;
+ unsigned long l;
+ unsigned long m;
+ unsigned long t;
+ int x;
+#if TD || TZ
+ struct timeval b;
+ struct timeval e;
+#if TZ
+ struct timezone z;
+#endif
+#endif
+ l = 500;
+ m = 890;
+ x = 0;
+ for (;;)
+ {
+#if TD || TZ
+#if TZ
+ gettimeofday(&b, &z);
+#else
+ gettimeofday(&b);
+#endif
+#else
+ t = (unsigned long)time((time_t*)0);
+#endif
+ k = 0;
+ for (i = 0; i < l; i++)
+ for (j = 0; j < 50000; j++)
+ k += j;
+#if TD || TZ
+#if TZ
+ gettimeofday(&e, &z);
+#else
+ gettimeofday(&e);
+#endif
+ t = (e.tv_sec - b.tv_sec) * 1000 + (e.tv_usec - b.tv_usec) / 1000;
+ if (!x++ && t < 1000)
+ {
+ t = 10000 / t;
+ l = (l * t) / 10;
+ continue;
+ }
+#else
+ t = ((unsigned long)time((time_t*)0) - t) * 1000;
+ if (!x++ && t < 20000)
+ {
+ t = 200000l / t;
+ l = (l * t) / 10;
+ continue;
+ }
+#endif
+#if PR
+ printf("[ k=%lu l=%lu m=%lu t=%lu ] ", k, l, m, t);
+#endif
+ if (t == 0)
+ t = 1;
+ break;
+ }
+ printf("%lu\n", ((l * m) / 10) / t);
+ return k == 0;
+}
+!
+ rating=
+ for o in -DTZ -DTD ''
+ do if $CC $o -O -o $tmp.exe $tmp.c >/dev/null 2>&1 ||
+ gcc $o -O -o $tmp.exe $tmp.c >/dev/null 2>&1
+ then rating=`./$tmp.exe`
+ break
+ fi
+ done
+ case $rating in
+ [0123456789]*) ;;
+ *) rating=1 ;;
+ esac
+ ;;
+ esac
+ _hostinfo_="$_hostinfo_ $rating"
+ ;;
+ type|canon)
+ case $CROSS:$canon in
+ 0:) case $cc in
+ cc) case $KEEP_HOSTTYPE:$HOSTTYPE in
+ 0:?*) if test -d ${PACKAGEROOT:-.}/arch/$HOSTTYPE
+ then KEEP_HOSTTYPE=1
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ case $KEEP_HOSTTYPE in
+ 1) _hostinfo_="$_hostinfo_ $HOSTTYPE"
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ case $cc in
+ /*) a=`$cc -dumpmachine $CCFLAGS 2>/dev/null`
+ case $a in
+ '') case $CCFLAGS in
+ ?*) a=`$cc -dumpmachine 2>/dev/null` ;;
+ esac
+ ;;
+ esac
+ case $a in
+ ''|*' '*|*/*:*)
+ ;;
+ *.*-*) _hostinfo_="$_hostinfo_ $a"
+ continue
+ ;;
+ *-*-*) case $canon in
+ '') canon=$a ;;
+ esac
+ ;;
+ *) _hostinfo_="$_hostinfo_ $a"
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ IFS=:
+ set /$IFS$PATH
+ IFS=$ifs
+ shift
+ f=../lib/hostinfo/typemap
+ for i
+ do case $i in
+ "") i=. ;;
+ esac
+ case $canon in
+ '') case $cc in
+ /*|cc) ;;
+ *) if executable $i/$cc
+ then a=`$i/$cc -dumpmachine $CCFLAGS 2>/dev/null`
+ case $a in
+ '') case $CCFLAGS in
+ ?*) a=`$cc -dumpmachine 2>/dev/null` ;;
+ esac
+ ;;
+ esac
+ case $a in
+ ''|*' '*|*/*:*)
+ ;;
+ *-*) canon=$a
+ ;;
+ *) _hostinfo_="$_hostinfo_ $a"
+ continue 2
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ if test -f "$i/$f"
+ then map="`grep -v '^#' $i/$f` $map"
+ fi
+ done
+
+ # inconsistent -dumpmachine filtered here
+
+ case -${canon}- in
+ --|*-powerpc-*)
+ h=`hostname || uname -n || cat /etc/whoami`
+ case $h in
+ '') h=local ;;
+ esac
+ a=`arch || uname -m || att uname -m || uname -s || att uname -s`
+ case $a in
+ *[\ \ ]*) a=`echo $a | $SED "s/[ ]/-/g"` ;;
+ esac
+ case $a in
+ '') a=unknown ;;
+ esac
+ m=`mach || machine || uname -p || att uname -p`
+ case $m in
+ *[\ \ ]*) m=`echo $m | $SED "s/[ ]/-/g"` ;;
+ esac
+ case $m in
+ '') m=unknown ;;
+ esac
+ x=`uname -a || att uname -a`
+ case $x in
+ '') x="unknown $host unknown unknown unknown unknown unknown" ;;
+ esac
+ set "" $h $a $m $x
+ expected=$1 host=$2 arch=$3 mach=$4 os=$5 sys=$6 rel=$7 ver=$8
+ ;;
+ *) case $canon in
+ *-*) IFS=-
+ set "" $canon
+ shift
+ IFS=$ifs
+ case $# in
+ 2) host= mach= arch=$1 os=$2 sys= rel= ;;
+ *) host= mach=$2 arch=$1 os=$3 sys= rel= ;;
+ esac
+ case $os in
+ [abcdefghijklmnopqrstuvwxyz]*[0123456789])
+ eval `echo $os | $SED -e 's/^\([^0123456789.]*\)\.*\(.*\)/os=\1 rel=\2/'`
+ ;;
+ esac
+ ;;
+ *) arch=$canon mach= os= sys= rel=
+ ;;
+ esac
+ ;;
+ esac
+ type=unknown
+ case $host in
+ *.*) host=`echo $host | $SED -e 's/\..*//'` ;;
+ esac
+ case $mach in
+ unknown)
+ mach=
+ ;;
+ [Rr][0123][0123456789][0123456789][0123456789])
+ mach=mips1
+ ;;
+ [Rr][4][0123456789][0123456789][0123456789])
+ mach=mips2
+ ;;
+ [Rr][56789][0123456789][0123456789][0123456789]|[Rr][123456789][0123456789][0123456789][0123456789][0123456789])
+ mach=mips4
+ ;;
+ pc) arch=i386
+ mach=
+ ;;
+ [Pp][Oo][Ww][Ee][Rr][Pp][Cc])
+ arch=ppc
+ mach=
+ ;;
+ *) case $arch in
+ 34[0123456789][0123456789])
+ os=ncr
+ arch=i386
+ ;;
+ esac
+ ;;
+ esac
+ case $canon in
+ '') set \
+ \
+ /NextDeveloper -d next - \
+ /config/hw/system/cpu -d tandem mach \
+
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ if test $2 $1
+ then os=$3
+ case $4 in
+ arch) mach=$arch ;;
+ mach) arch=$mach ;;
+ esac
+ break
+ fi
+ shift;shift;shift;shift
+ done
+ ;;
+ esac
+ case $os in
+ AIX*|aix*)
+ type=ibm.risc
+ ;;
+ HP-UX) case $arch in
+ 9000/[78]*)
+ type=hp.pa
+ ;;
+ */*) type=hp.`echo $arch | $SED 's,/,_,g'`
+ ;;
+ *) type=hp.$arch
+ ;;
+ esac
+ ;;
+ [Ii][Rr][Ii][Xx]*)
+ set xx `hinv | $SED -e '/^CPU:/!d' -e 's/CPU:[ ]*\([^ ]*\)[ ]*\([^ ]*\).*/\1 \2/' -e q | $TR ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ shift
+ type=$1
+ n=
+ case $2 in
+ r[0123][0123456789][0123456789][0123456789])
+ n=1
+ ;;
+ r[4][0123][0123456789][0123456789])
+ n=2
+ ;;
+ r[4][456789][0123456789][0123456789]|r[5][0123456789][0123456789][0123456789])
+ n=3
+ ;;
+ r[6789][0123456789][0123456789][0123456789]|r[123456789][0123456789][0123456789][0123456789][0123456789])
+ n=4
+ ;;
+ esac
+ case $rel in
+ [01234].*|5.[012]|5.[012].*)
+ case $n in
+ 1) ;;
+ *) n=2 ;;
+ esac
+ ;;
+ 5.*) case $n in
+ 2) n=3 ;;
+ esac
+ ;;
+ esac
+ if executable $cc
+ then a=$cc
+ else IFS=:
+ set /$IFS$PATH
+ IFS=$ifs
+ shift
+ for i
+ do a=$i/$cc
+ if executable $a
+ then break
+ fi
+ done
+ fi
+ split='
+'
+ a=`strings $a < /dev/null | $SED -e 's/[^abcdefghijklmnopqrstuvwxyz0123456789]/ /g' -e 's/[ ][ ]*/\'"$split"'/g' | $SED -e "/^${type}[0123456789]$/!d" -e "s/^${type}//" -e q`
+ case $a in
+ [0123456789]) n=$a ;;
+ esac
+ case $n in
+ 4) a=`$cc -${type}3 2>&1`
+ case $a in
+ *unknown*|*install*|*conflict*)
+ ;;
+ *) n=3
+ ;;
+ esac
+ ;;
+ esac
+ a=`$cc -show F0oB@r.c 2>&1`
+ case $n:$a in
+ [!2]:*mips2*) n=2 ;;
+ [!23]:*mips3*) n=3 ;;
+ [!234]:*mips4*) n=4 ;;
+ esac
+ case $n:$a in
+ [!2]:*[Oo]32*) abi=-o32 ;;
+ [!3]:*[Nn]32*) abi=-n32 ;;
+ esac
+ mach=${type}$n
+ type=sgi.$mach
+ ;;
+ OSx*|SMP*|pyramid)
+ type=pyr
+ ;;
+ OS/390) type=mvs.390
+ ;;
+ [Ss][Cc][Oo]*)
+ type=sco
+ ;;
+ [Ss]ol*)
+ v=`echo $rel | $SED -e 's/^[25]\.//' -e 's/\.[^.]*$//'`
+ case $v in
+ [6789]|[1-9][0-9])
+ ;;
+ *) v=
+ ;;
+ esac
+ case $arch in
+ '') case $mach in
+ '') arch=sun4 ;;
+ *) arch=$mach ;;
+ esac
+ ;;
+ esac
+ case $arch in
+ sparc) arch=sun4 ;;
+ esac
+ type=sol$v.$arch
+ ;;
+ [Ss]un*)type=`echo $arch | $SED -e 's/\(sun.\).*/\1/'`
+ case $type in
+ sparc) type=sun4 ;;
+ esac
+ case $rel in
+ [01234]*)
+ ;;
+ '') case $os in
+ *[Oo][Ss])
+ ;;
+ *) type=sol.$type
+ ;;
+ esac
+ ;;
+ *) case $type in
+ '') case $mach in
+ sparc*) type=sun4 ;;
+ *) type=$mach ;;
+ esac
+ ;;
+ esac
+ v=`echo $rel | $SED -e 's/^[25]\.//' -e 's/\.[^.]*$//'`
+ case $v in
+ [6789]|[1-9][0-9])
+ ;;
+ *) v=
+ ;;
+ esac
+ type=sol$v.$type
+ ;;
+ esac
+ case $type in
+ sun*|*.*)
+ ;;
+ *) type=sun.$type
+ ;;
+ esac
+ ;;
+ [Uu][Nn][Ii][Xx]_[Ss][Vv])
+ type=unixware
+ ;;
+ UTS*|uts*)
+ if test -x /bin/u370 -o -x /bin/u390
+ then type=uts.390
+ else case $arch in
+ '') arch=$mach ;;
+ esac
+ type=uts.$arch
+ fi
+ ;;
+ $host) type=$arch
+ case $type in
+ *.*|*[0123456789]*86|*68*)
+ ;;
+ *) case $mach in
+ *[0123456789]*86|*68*|mips)
+ type=$type.$mach
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ unknown)
+ case $arch in
+ ?*) case $arch in
+ sun*) mach= ;;
+ esac
+ type=$arch
+ case $mach in
+ ?*) type=$type.$mach ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) case $ver in
+ FTX*|ftx*)
+ case $mach in
+ *[0123456789][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]*)
+ mach=`echo $mach | $SED -e 's/[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]*$//'`
+ ;;
+ esac
+ type=stratus.$mach
+ ;;
+ *) case $arch in
+ [Oo][Ss][-/.]2)
+ type=os2
+ arch=$rel
+ ;;
+ *) type=`echo $os | $SED -e 's/[0123456789].*//' -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789.].*//'`
+ ;;
+ esac
+ case $type in
+ [Cc][Yy][Gg][Ww][Ii][Nn]_*)
+ type=cygwin
+ ;;
+ [Uu][Ww][Ii][Nn]*|[Ww]indows_[0123456789][0123456789]|[Ww]indows_[Nn][Tt])
+ type=win32
+ arch=`echo $arch | $SED -e 's/_[^_]*$//'`
+ ;;
+ esac
+ case $arch in
+ '') case $mach in
+ ?*) type=$type.$mach ;;
+ esac
+ ;;
+ *) type=$type.$arch ;;
+ esac
+ ;;
+ esac
+ esac
+ case $type in
+ [0123456789]*)
+ case $mach in
+ ?*) type=$mach ;;
+ esac
+ case $type in
+ */MC) type=ncr.$type ;;
+ esac
+ ;;
+ *.*) ;;
+ *[0123456789]*86|*68*)
+ case $rel in
+ [34].[0123456789]*)
+ type=att.$type
+ ;;
+ esac
+ ;;
+ [abcdefghijklmnopqrstuvwxyz]*[0123456789])
+ ;;
+ [abcdefghijklmnopqrstuvwxyz]*) case $mach in
+ $type) case $ver in
+ Fault*|fault*|FAULT*)
+ type=ft.$type
+ ;;
+ esac
+ ;;
+ ?*) case $arch in
+ '') type=$type.$mach ;;
+ *) type=$type.$arch ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $type in
+ *[-_]32|*[-_]64|*[-_]128)
+ bits=`echo $type | $SED 's,.*[-_],,'`
+ type=`echo $type | $SED 's,[-_][0-9]*$,,'`
+ ;;
+ *) bits=
+ ;;
+ esac
+ type=`echo $type | $SED -e 's%[-+/].*%%' | $TR ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ case $type in
+ *.*) lhs=`echo $type | $SED -e 's/\..*//'`
+ rhs=`echo $type | $SED -e 's/.*\.//'`
+ case $rhs in
+ [x0123456789]*86) rhs=i$rhs ;;
+ 68*) rhs=m$rhs ;;
+ esac
+ case $rhs in
+ i[x23456789]86|i?[x23456789]86|*86pc)
+ rhs=i386 ;;
+ powerpc) rhs=ppc ;;
+ s[0123456789]*[0123456789]x)
+ rhs=`echo $rhs | $SED -e 's/x$/-64/'` ;;
+ esac
+ case $rhs in
+ arm[abcdefghijklmnopqrstuvwxyz_][0123456789]*)
+ rhs=arm ;;
+ hppa) rhs=pa ;;
+ esac
+ case $lhs in
+ ?*coff|?*dwarf|?*elf)
+ case $lhs in
+ ?*coff) x=coff ;;
+ ?*dwarf)x=coff ;;
+ ?*elf) x=elf ;;
+ esac
+ lhs=`echo ${lhs}XXX | $SED -e "s/${x}XXX//"`
+ ;;
+ esac
+ case $lhs in
+ bsdi) lhs=bsd ;;
+ darwin) case $rel in
+ [01234567].*) lhs=${lhs}7 ;;
+ esac
+ ;;
+ freebsd) case $rel in
+ [01234].*) lhs=${lhs}4 ;;
+ [123456789]*.*) lhs=${lhs}`echo $rel | $SED -e 's/\..*//'` ;;
+ esac
+ ;;
+ hpux) lhs=hp ;;
+ mvs) rhs=390 ;;
+ esac
+ case $lhs in
+ '') type=$rhs ;;
+ $rhs) type=$lhs ;;
+ *) type=$lhs.$rhs ;;
+ esac
+ ;;
+ esac
+ case $type in
+ sgi.mips*)
+ case $mach in
+ mips2) type=sgi.$mach
+ abi=-o32
+ ;;
+ mips3) type=sgi.$mach
+ abi=-n32
+ ;;
+ mips[456789])
+ type=sgi.$mach
+ case $abi in
+ *-n32) ;;
+ *) abi=-64 ;;
+ esac
+ ;;
+ *) pwd=`pwd`
+ cd ${TMPDIR:-/tmp}
+ tmp=hi$$
+ trap 'rm -f $tmp.*' 0 1 2
+ cat > $tmp.a.c <<!
+extern int b();
+int main() { return b(); }
+!
+ cat > $tmp.b.c <<!
+int b() { return 0; }
+!
+ abi=
+ if $cc -c $tmp.a.c
+ then for i in -n32 -o32 -64
+ do if $cc $i -c $tmp.b.c &&
+ $cc -o $tmp.exe $tmp.a.o $tmp.b.o
+ then abi=$i
+ for i in 2 3 4 5 6 7 8 9
+ do case $i:$abi in
+ 2:-n32|2:-64|3:-64)
+ continue
+ ;;
+ esac
+ if $cc $abi -mips$i -c $tmp.b.c &&
+ $cc -o $tmp.exe $tmp.a.o $tmp.b.o
+ then type=`echo $type | $SED -e 's/.$//'`$i
+ break
+ fi
+ done
+ break
+ fi
+ done
+ fi </dev/null >/dev/null 2>&1
+ rm -f $tmp.*
+ trap - 0 1 2
+ cd $pwd
+ ;;
+ esac
+ case $type$abi in
+ sgi.mips2-o32)
+ ;;
+ sgi.mips3)
+ type=$type-o32
+ ;;
+ sgi.mips3-n32)
+ ;;
+ sgi.mips4)
+ type=$type-o32
+ ;;
+ sgi.mips[456789]-64)
+ ;;
+ *) type=$type$abi
+ ;;
+ esac
+ ;;
+ *) case $bits in
+ '') case `file /bin/sh 2>/dev/null` in
+ *universal*64*)
+ pwd=`pwd`
+ cd ${TMPDIR:-/tmp}
+ tmp=hi$$
+ trap 'rm -f $tmp.*' 0 1 2
+ cat > $tmp.a.c <<!
+int main() { return 0; }
+!
+ if $cc -o $tmp.a.exe $tmp.a.c
+ then case `file $tmp.a.exe` in
+ *64*) bits=64 ;;
+ esac
+ fi </dev/null >/dev/null 2>&1
+ rm -f $tmp.*
+ trap - 0 1 2
+ cd $pwd
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $bits in
+ 32) case $type in
+ *.i386) bits= ;;
+ esac
+ ;;
+ esac
+ case $bits in
+ ?*) type=$type-$bits ;;
+ esac
+
+ # last chance mapping
+
+ set "" "" $map
+ while :
+ do case $# in
+ [012]) break ;;
+ esac
+ shift;shift
+ eval " case \$type in
+ $1) type=\$2; break ;;
+ esac"
+ done
+ _hostinfo_="$_hostinfo_ $type"
+ ;;
+ esac
+ done
+ set '' $_hostinfo_
+ shift
+ _hostinfo_=$*
+
+ # restore the global state
+
+ PATH=$path
+ case $DEBUG in
+ '') exec 2>&9
+ exec 9>&-
+ ;;
+ esac
+}
+
+# info message
+
+note() # message ...
+{
+ echo $command: "$@" >&2
+}
+
+# cc checks
+#
+# CC: compiler base name name
+# cc: full path, empty if not found
+
+checkcc()
+{
+ cc=
+ if onpath $CC
+ then cc=$_onpath_
+ else case $CC in
+ cc) if onpath gcc
+ then CC=gcc
+ cc=$_onpath_
+ fi
+ ;;
+ esac
+ fi
+ case $cc in
+ '') case $action in
+ make|test) note "$CC: not found"; exit 1 ;;
+ *) note "warning: $CC: not found" ;;
+ esac
+ ;;
+ esac
+}
+
+# some actions have their own PACKAGEROOT or kick out early
+
+case $action in
+host) eval u=$package_use
+ case $u in
+ $PACKAGE_USE)
+ ;;
+ *) if onpath $0
+ then case $_onpath_ in
+ */arch/$HOSTTYPE/bin/package)
+ KEEP_HOSTTYPE=1
+ ;;
+ *) KEEP_HOSTTYPE=0
+ ;;
+ esac
+ else KEEP_HOSTTYPE=0
+ fi
+ ;;
+ esac
+ hostinfo $args
+ echo $_hostinfo_
+ exit 0
+ ;;
+export|setup|use)
+ x=
+ ;;
+*) x=
+ eval u=$package_use
+ case $u in
+ $PACKAGE_USE)
+ case :$PATH: in
+ *:$INSTALLROOT/bin:*)
+ case $LIBPATH: in
+ $INSTALLROOT/bin:$INSTALLROOT/lib:*)
+ case $SHLIB_PATH: in
+ $INSTALLROOT/lib:*)
+ x=1
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+run=-
+case $x in
+1) : accept the current package use environment
+
+ OK=ok
+ KSH=$EXECROOT/bin/ksh
+ MAKE=nmake
+ NMAKE=$EXECROOT/bin/$MAKE
+ SUM=$EXECROOT/bin/sum
+ TEE=$EXECROOT/bin/tee
+ INITROOT=$PACKAGEROOT/src/cmd/INIT
+ checkcc
+ ;;
+*) hosttype=
+ case $KEEP_PACKAGEROOT in
+ 0) case $action in
+ use) PACKAGEROOT=
+ case $show in
+ echo) exec=echo make=echo show=echo ;;
+ esac
+ set '' $args
+ shift
+ case $# in
+ 0) ;;
+ *) case $1 in
+ -|.) ;;
+ /*) PACKAGEROOT=$1
+ ;;
+ *) i=`echo ~$1`
+ if packageroot $i
+ then PACKAGEROOT=$i
+ else for i in `echo $HOME | sed -e 's,/[^/]*$,,'` $usr $use
+ do if packageroot $i/$1
+ then PACKAGEROOT=$i/$1
+ break
+ fi
+ done
+ case $PACKAGEROOT in
+ '') hosttype=$1 ;;
+ esac
+ fi
+ ;;
+ esac
+ shift
+ ;;
+ esac
+ run="$@"
+ ;;
+ esac
+ case $PACKAGEROOT in
+ '') PACKAGEROOT=${PWD:-`pwd`} ;;
+ esac
+
+ # . must be within the PACKAGEROOT tree
+
+ i=X$PACKAGEROOT
+ IFS=/
+ set $i
+ IFS=$ifs
+ while :
+ do i=$1
+ shift
+ case $i in
+ X) break ;;
+ esac
+ done
+ case $PACKAGEROOT in
+ //*) d=/ ;;
+ *) d= ;;
+ esac
+ case $1 in
+ home) k=1 ;;
+ *) k=0 ;;
+ esac
+ for i
+ do case $i in
+ '') continue ;;
+ esac
+ d=$d/$i
+ case $k in
+ 2) k=1
+ ;;
+ 1) k=0
+ ;;
+ 0) case $i in
+ arch) k=2
+ ;;
+ *) if packageroot $d
+ then PACKAGEROOT=$d
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ done
+ ;;
+ esac
+ INITROOT=$PACKAGEROOT/src/cmd/INIT
+ $show PACKAGEROOT=$PACKAGEROOT
+ $show export PACKAGEROOT
+ export PACKAGEROOT
+
+ # initialize the architecture environment
+
+ case $KEEP_HOSTTYPE in
+ 0) hostinfo type
+ HOSTTYPE=$_hostinfo_
+ ;;
+ 1) _PACKAGE_HOSTTYPE_=$HOSTTYPE
+ export _PACKAGE_HOSTTYPE_
+ ;;
+ esac
+ $show HOSTTYPE=$HOSTTYPE
+ $show export HOSTTYPE
+ export HOSTTYPE
+ INSTALLROOT=$PACKAGEROOT/arch/$HOSTTYPE
+ case $action in
+ admin|install|make|read|remove|test|verify|view|write)
+ ;;
+ *) if test ! -d $INSTALLROOT
+ then INSTALLROOT=$PACKAGEROOT
+ fi
+ ;;
+ esac
+ $show INSTALLROOT=$INSTALLROOT
+ $show export INSTALLROOT
+ export INSTALLROOT
+
+ # HOSTTYPE specific package profile
+
+ if test -r $INSTALLROOT/lib/package/profile
+ then . $INSTALLROOT/lib/package/profile
+ fi
+
+ # check the basic package hierarchy
+
+ case $action in
+ export|use)
+ packageroot $PACKAGEROOT || {
+ echo "$command: $PACKAGEROOT: invalid package root directory" >&2
+ exit 1
+ }
+ case $KEEP_HOSTTYPE:$hosttype in
+ 0:?*) if test -d ${PACKAGEROOT:-.}/arch/$hosttype
+ then KEEP_HOSTTYPE=1
+ HOSTTYPE=$hosttype
+ else echo "$command: $hosttype: package root not found" >&2
+ exit 1
+ fi
+ ;;
+ esac
+ ;;
+ *) packageroot $PACKAGEROOT || {
+ case $KEEP_PACKAGEROOT in
+ 1) ;;
+ *) echo "$command: $PACKAGEROOT: must be in the package root directory tree" >&2
+ exit 1
+ ;;
+ esac
+ }
+
+ case $action in
+ admin) ;;
+ *) for i in arch arch/$HOSTTYPE
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || exit
+ done
+ for i in lib
+ do test -d $INSTALLROOT/$i || $exec mkdir $INSTALLROOT/$i || exit
+ done
+ ;;
+ esac
+
+ # no $INITROOT means INIT already installed elsewhere
+
+ if test -d $INITROOT
+ then
+ # update the basic package commands
+
+ for i in execrate ignore mamprobe silent
+ do test -h $PACKAGEROOT/bin/$i 2>/dev/null ||
+ case `ls -t $INITROOT/$i.sh $PACKAGEROOT/bin/$i 2>/dev/null` in
+ "$INITROOT/$i.sh"*)
+ note update $PACKAGEROOT/bin/$i
+ shellmagic
+ case $SHELLMAGIC in
+ '') $exec cp $INITROOT/$i.sh $PACKAGEROOT/bin/$i || exit
+ ;;
+ *) case $exec in
+ '') {
+ echo "$SHELLMAGIC"
+ cat $INITROOT/$i.sh
+ } > $PACKAGEROOT/bin/$i || exit
+ ;;
+ *) echo "{
+echo \"$SHELLMAGIC\"
+cat $INITROOT/$i.sh
+} > $PACKAGEROOT/bin/$i"
+ ;;
+ esac
+ ;;
+ esac
+ $exec chmod +x $PACKAGEROOT/bin/$i || exit
+ ;;
+ esac
+ done
+ fi
+ ;;
+ esac
+ path=$PATH
+ PATH=$INSTALLROOT/bin:$PACKAGEROOT/bin:$PATH
+ checkcc
+ PATH=$path
+ case $cc in
+ ?*) if test -f $INITROOT/hello.c
+ then
+ # check if $CC (full path $cc) is a cross compiler
+
+ (
+ cd /tmp || exit 3
+ cp $INITROOT/hello.c pkg$$.c || exit 3
+ $cc -o pkg$$.exe pkg$$.c > pkg$$.e 2>&1 || {
+ if $cc -Dnew=old -o pkg$$.exe pkg$$.c > /dev/null 2>&1
+ then echo "$command: ${warn}$CC: must be a C compiler (not C++)" >&2
+ else cat pkg$$.e
+ echo "$command: ${warn}$CC: failed to compile and link $INITROOT/hello.c -- is it a C compiler?" >&2
+ fi
+ exit 2
+ }
+ if ./pkg$$.exe >/dev/null 2>&1
+ then code=0
+ else code=1
+ fi
+ rm -f pkg$$.*
+ exit $code
+ )
+ code=$?
+ case $code in
+ 1) CROSS=1 ;;
+ esac
+ fi
+ ;;
+ esac
+ EXECTYPE=$HOSTTYPE
+ EXECROOT=$INSTALLROOT
+ case $CROSS in
+ 0) # dll hackery -- why is this so complicated?
+
+ abi=
+ case $HOSTTYPE in
+ sgi.mips[0123456789]*)
+ x=rld
+ if executable /lib32/$x || executable /lib64/$x
+ then case $INSTALLROOT in
+ */sgi.mips[0123456789]*)
+ u=`echo $INSTALLROOT | sed -e 's,-[^-/]*$,,' -e 's,.$,,'`
+ ;;
+ *) u=
+ ;;
+ esac
+ for a in "n=2 v= l=" "n=3 v=N32 l=lib32" "n=4-n32 v=N32 l=lib32" "n=4 v=64 l=lib64"
+ do eval $a
+ case $v in
+ N32) case $n:$HOSTTYPE in
+ *-n32:*-n32) ;;
+ *-n32:*) continue ;;
+ *:*-n32) continue ;;
+ esac
+ ;;
+ esac
+ case $l in
+ ?*) if executable ! /$l/$x
+ then continue
+ fi
+ ;;
+ esac
+ case $u in
+ '') case $HOSTTYPE in
+ sgi.mips$n|sgi.mips$n-*)
+ abi="$abi 'd=$INSTALLROOT v=$v'"
+ ;;
+ *) continue
+ ;;
+ esac
+ ;;
+ *) if test -d $u$n
+ then abi="$abi 'd=$u$n v=$v'"
+ fi
+ ;;
+ esac
+ done
+ fi
+ ;;
+ esac
+ case $abi in
+ '') abi="'d=$INSTALLROOT v='" ;;
+ esac
+ p=0
+ eval "
+ for a in $abi
+ do eval \$a
+ eval \"
+ case \\\$LD_LIBRARY\${v}_PATH: in
+ \\\$d/lib:*)
+ ;;
+ *) x=\\\$LD_LIBRARY\${v}_PATH
+ case \\\$x in
+ ''|:*) ;;
+ *) x=:\\\$x ;;
+ esac
+ LD_LIBRARY\${v}_PATH=\$d/lib\\\$x
+ export LD_LIBRARY\${v}_PATH
+ p=1
+ ;;
+ esac
+ \"
+ done
+ "
+ case $LD_LIBRARY_PATH in
+ '') ;;
+ *) for d in $lib
+ do case $HOSTTYPE in
+ *64) if test -d ${d}64
+ then d=${d}64
+ fi
+ ;;
+ esac
+ case :$LD_LIBRARY_PATH: in
+ *:$d:*) ;;
+ *) if test -d $d
+ then LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$d
+ p=1
+ fi
+ ;;
+ esac
+ done
+ ;;
+ esac
+ case $p in
+ 1) $show LD_LIBRARY_PATH=$LD_LIBRARY_PATH
+ $show export LD_LIBRARY_PATH
+ export LD_LIBRARY_PATH
+ ;;
+ esac
+ case $LIBPATH: in
+ $INSTALLROOT/bin:$INSTALLROOT/lib:*)
+ ;;
+ *) case $LIBPATH in
+ '') LIBPATH=/usr/lib:/lib ;;
+ esac
+ LIBPATH=$INSTALLROOT/bin:$INSTALLROOT/lib:$LIBPATH
+ $show LIBPATH=$LIBPATH
+ $show export LIBPATH
+ export LIBPATH
+ ;;
+ esac
+ case $SHLIB_PATH: in
+ $INSTALLROOT/lib:*)
+ ;;
+ *) SHLIB_PATH=$INSTALLROOT/lib${SHLIB_PATH:+:$SHLIB_PATH}
+ $show SHLIB_PATH=$SHLIB_PATH
+ $show export SHLIB_PATH
+ export SHLIB_PATH
+ ;;
+ esac
+ case $DYLD_LIBRARY_PATH: in
+ $INSTALLROOT/lib:*)
+ ;;
+ *) DYLD_LIBRARY_PATH=$INSTALLROOT/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}
+ $show DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH
+ $show export DYLD_LIBRARY_PATH
+ export DYLD_LIBRARY_PATH
+ ;;
+ esac
+ case $_RLD_ROOT in
+ $INSTALLROOT/arch*) ;;
+ ':') _RLD_ROOT=$INSTALLROOT/arch:/ ;;
+ /|*:/) _RLD_ROOT=$INSTALLROOT/arch:$_RLD_ROOT ;;
+ *) _RLD_ROOT=$INSTALLROOT/arch:$_RLD_ROOT:/ ;;
+ esac
+ $show _RLD_ROOT=$_RLD_ROOT
+ $show export _RLD_ROOT
+ export _RLD_ROOT
+
+ # now set up PATH
+ #
+ # NOTE: PACKAGEROOT==INSTALLROOT is possible for binary installations
+
+ case $PATH: in
+ $PACKAGEROOT/bin:*)
+ ;;
+ *) PATH=$PACKAGEROOT/bin:$PATH
+ ;;
+ esac
+ case $PATH: in
+ $INSTALLROOT/bin:*)
+ ;;
+ *) PATH=$INSTALLROOT/bin:$PATH
+ ;;
+ esac
+ $show PATH=$PATH
+ $show export PATH
+ export PATH
+ ;;
+ *) for i in package proto nmake
+ do if onpath $i
+ then EXECROOT=`echo $_onpath_ | sed -e 's,//*[^/]*//*[^/]*$,,'`
+ EXECTYPE=`echo $EXECROOT | sed -e 's,.*/,,'`
+ break
+ fi
+ done
+ case $HOSTTYPE in
+ $EXECTYPE)
+ OCC=$CC
+ CC=cc
+ hostinfo type
+ EXECTYPE=$_hostinfo_
+ case $HOSTTYPE in
+ $EXECTYPE)
+ echo "$command: $CC: seems to be a cross-compiler" >&2
+ echo "$command: set HOSTTYPE to something other than the native $EXECTYPE" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ $show EXECTYPE=$EXECTYPE
+ $show export EXECTYPE
+ export EXECTYPE
+ ;;
+ esac
+ $show EXECROOT=$EXECROOT
+ $show export EXECROOT
+ export EXECROOT
+
+ # use these if possible
+
+ OK=ok
+ KSH=$EXECROOT/bin/ksh
+ MAKE=nmake
+ NMAKE=$EXECROOT/bin/$MAKE
+ SUM=$EXECROOT/bin/sum
+ TEE=$EXECROOT/bin/tee
+
+ # grab a decent default shell
+
+ case $KEEP_SHELL in
+ 0) executable "$SHELL" || SHELL=
+ case $SHELL in
+ ?*) checksh $SHELL || SHELL= ;;
+ esac
+ case $SHELL in
+ ''|/bin/*|/usr/bin/*)
+ case $SHELL in
+ '') SHELL=/bin/sh ;;
+ esac
+ for i in ksh sh bash
+ do if onpath $i && checksh $_onpath_
+ then SHELL=$_onpath_
+ break
+ fi
+ done
+ ;;
+ */*ksh) if executable $KSH
+ then SHELL=$KSH
+ fi
+ ;;
+ esac
+ ;;
+ esac
+
+ # $SHELL must be /bin/sh compatible
+
+ case $SHELL in
+ /bin/sh);;
+ '') SHELL=/bin/sh
+ ;;
+ *) $SHELL -c 'trap "exit 0" 0; exit 1' 2>/dev/null
+ case $? in
+ 1) SHELL=/bin/sh
+ ;;
+ *) # catch (our own) pipe/socket configuration mismatches
+ $SHELL -c "date | $SHELL -c 'read x'"
+ case $? in
+ 0) ;;
+ *) SHELL=/bin/sh ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ export SHELL
+ $show SHELL=$SHELL
+ $show export SHELL
+ COSHELL=$SHELL
+ export COSHELL
+ $show COSHELL=$COSHELL
+ $show export COSHELL
+
+ # tame the environment
+
+ case $action in
+ use) ;;
+ *) ENV=
+ ERROR_OPTIONS=
+ export ENV ERROR_OPTIONS
+ ;;
+ esac
+
+ # finalize the views
+
+ case $USER_VPATH in
+ '') case $VPATH in
+ ?*) IFS=':'
+ set '' $VPATH
+ shift
+ IFS=$ifs
+ USER_VPATH=
+ for i
+ do case $i in
+ */arch/$HOSTTYPE) ;;
+ */arch/*/*) ;;
+ */arch/*) continue ;;
+ esac
+ if packageroot $i
+ then case $USER_VPATH in
+ '') USER_VPATH=$i ;;
+ ?*) USER_VPATH=$USER_VPATH:$i ;;
+ esac
+ fi
+ done
+ esac
+ ;;
+ esac
+ case $USER_VPATH in
+ ?*) IFS=':'
+ set '' $USER_VPATH
+ shift
+ IFS=$ifs
+ USER_VPATH=
+ USER_VPATH_CHAIN=
+ p=$PACKAGEROOT
+ for i
+ do case $i in
+ ''|$PACKAGEROOT|$INSTALLROOT)
+ ;;
+ ?*) USER_VPATH=$USER_VPATH:$i
+ USER_VPATH_CHAIN="$USER_VPATH_CHAIN $p $i"
+ p=$i
+ case $PROTOROOT in
+ -) executable $i/bin/mamake && PROTOROOT= ;;
+ esac
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+esac
+PACKAGESRC=$PACKAGEROOT/lib/package
+PACKAGEBIN=$INSTALLROOT/lib/package
+case $action:$run in
+use:-) set '' $args
+ shift
+ case $# in
+ 0) ;;
+ *) shift ;;
+ esac
+ run="$@"
+ ;;
+esac
+
+# more cygwin hassles
+
+case $HOSTTYPE in
+cygwin.*)
+ lose=
+ case $CYGWIN in
+ *nontsec*)
+ lose=ntsec
+ ;;
+ *ntsec*);;
+ *) exe=/tmp/pkg$$.exe
+ rm -f $exe
+ : > $exe
+ if test -x $exe
+ then lose=ntsec
+ fi
+ ;;
+ esac
+ case $CYGWIN in
+ *nobinmode*)
+ case $lose in
+ '') lose=binmode ;;
+ *) lose="$lose binmode" ;;
+ esac
+ ;;
+ esac
+ case $lose in
+ ?*) echo "$command: $HOSTTYPE: export '$lose' in CYGWIN or languish in windows" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+esac
+
+# set up the view state
+
+VIEW_bin=$INSTALLROOT VIEW_src=$PACKAGEROOT VIEW_all="$INSTALLROOT $PACKAGEROOT"
+if (vpath $INSTALLROOT $PACKAGEROOT $USER_VPATH_CHAIN) >/dev/null 2>&1 &&
+ vpath $INSTALLROOT $PACKAGEROOT $USER_VPATH_CHAIN
+then $show vpath $INSTALLROOT $PACKAGEROOT $USER_VPATH_CHAIN
+else VPATH=$INSTALLROOT:$PACKAGEROOT$USER_VPATH
+ $show VPATH=$VPATH
+ $show export VPATH
+ export VPATH
+ IFS=':'
+ set '' $VPATH
+ shift
+ IFS=$ifs
+ for i
+ do case $i in
+ */arch/*/*)
+ VIEW_src="$VIEW_src $i"
+ ;;
+ */arch/*)
+ VIEW_bin="$VIEW_bin $i"
+ ;;
+ *)
+ VIEW_src="$VIEW_src $i"
+ ;;
+ esac
+ VIEW_all="$VIEW_all $i"
+ done
+fi
+
+# return 0 if arg in src|bin|all view
+
+view() # [test] [-|type] [src|bin|all] file
+{
+ case $1 in
+ -[dfsx])_view_T_=$1; shift ;;
+ *) _view_T_=-f ;;
+ esac
+ case $1 in
+ -) _view_t_= ;;
+ *) _view_t_=$1 ;;
+ esac
+ shift
+ case $1 in
+ all) shift; _view_v_=$VIEW_all ;;
+ bin) shift; _view_v_=$VIEW_bin ;;
+ src) shift; _view_v_=$VIEW_src ;;
+ *) _view_v_=$VIEW_all ;;
+ esac
+ case $1 in
+ /*) if test $_view_T_ $1
+ then _view_=$1
+ return 0
+ fi
+ ;;
+ *) for _view_d_ in $_view_v_
+ do if test $_view_T_ $_view_d_/$1
+ then _view_=$_view_d_/$1
+ return 0
+ fi
+ done
+ ;;
+ esac
+ _view_=
+ case $_view_t_ in
+ ?*) echo $command: $1: $_view_t_ not found >&2 ;;
+ esac
+ return 1
+}
+
+# determine the package and targets
+
+case $action in
+admin) case $admin_action in
+ results)action=$admin_action
+ set '' $admin_args
+ shift;shift
+ admin_args="admin $*"
+ case $admin_on in
+ '') target=$admin_args ;;
+ *) target="on $admin_on $admin_args" ;;
+ esac
+ ;;
+ esac
+ ;;
+release)set '' $args
+ target=
+ while :
+ do shift
+ case $1 in
+ -|[0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789])
+ target="$target $1"
+ ;;
+ *) break
+ ;;
+ esac
+ done
+ package=$*
+ ;;
+setup) # { update read } with optional (bin|fun|include|lib) symlinks
+ # flat option sets up { bin fun include lib } symlinks from
+ # $INSTALLROOT to $PACKAGEROOT
+
+ # . is the package root
+
+ set '' $args
+ shift
+ types=
+ url=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ flat) flat=1 # backwards compatibility -- documentation dropped
+ ;;
+ *://*|*.url)
+ url=$1
+ shift
+ break
+ ;;
+ *) types="$types $1"
+ ;;
+ esac
+ shift
+ done
+ if test ! -d $PACKAGEROOT/lib/package/tgz
+ then $exec mkdir -p $PACKAGEROOT/lib/package/tgz || exit
+ fi
+ case " $types " in
+ *" source "*)
+ case " $* " in
+ ' ') ;;
+ *" INIT "*)
+ ;;
+ *) view - all src/cmd/INIT ||
+ set INIT "$@"
+ ;;
+ esac
+ ;;
+ esac
+ packages=`$0 $global authorize "$authorize" password "$password" update setup $types $url "$@" PACKAGEROOT=$PACKAGEROOT`
+ case $packages in
+ ?*) $0 $global read $packages PACKAGEROOT=$PACKAGEROOT
+ esac
+ exit
+ ;;
+*) package=
+ target=
+ set '' $args
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ ''|-) target="$target $package"
+ package=
+ ;;
+ *) if view - src "lib/package/$1.pkg"
+ then package="$package $1"
+ else target="$target $package $1"
+ package=
+ fi
+ ;;
+ esac
+ done
+ ;;
+esac
+
+# flatten -- assumes symlink support
+
+case $flat in
+1) case $action in
+ make|read|setup|update|use|view)
+ if test ! -d $INSTALLROOT
+ then $exec mkdir -p $INSTALLROOT || exit
+ fi
+ for i in bin include lib fun man share
+ do if test ! -d $INSTALLROOT/../../$i
+ then $exec mkdir $INSTALLROOT/../../$i
+ fi
+ if test ! -d $INSTALLROOT/$i
+ then if test ! -h $INSTALLROOT/$i
+ then $exec ln -s ../../$i $INSTALLROOT/$i
+ fi
+ elif test ! -h $INSTALLROOT/$i
+ then for x in $INSTALLROOT/$i/.[a-z]* $INSTALLROOT/$i/*
+ do if test -f $x -o -d $x
+ then if test ! -d $INSTALLROOT/$i/$x || test ! -d $INSTALLROOT/../../$i/$x
+ then $exec mv $x $INSTALLROOT/../../$i
+ fi
+ fi
+ done
+ $exec rm -rf $INSTALLROOT/$i
+ $exec ln -s ../../$i $INSTALLROOT/$i
+ fi
+ done
+ ;;
+ esac
+ ;;
+esac
+
+# check that cmd args are up to date a.out's
+
+checkaout() # cmd ...
+{
+ case $PROTOROOT in
+ -) PROTOROOT=
+ case $* in
+ ratz) if test -f $INITROOT/ratz.c -a -w $PACKAGEROOT
+ then test -f $INITROOT/hello.c || {
+ cat > $INITROOT/hello.c <<'!'
+#ifndef printf
+#include <stdio.h>
+#endif
+int main() { int new = 0; printf("hello world\n"); return new;}
+!
+ }
+ test -f $INITROOT/p.c || {
+ cat > $INITROOT/p.c <<'!'
+/*
+ * small test for prototyping cc
+ */
+
+int main(int argc, char** argv) { return argc || argv; }
+!
+ }
+ fi
+ ;;
+ esac
+ test -f $INITROOT/hello.c -a -f $INITROOT/p.c -a -w $PACKAGEROOT || {
+ for i
+ do onpath $i || {
+ echo "$command: $i: command not found" >&2
+ return 1
+ }
+ done
+ return 0
+ }
+ case $cc in
+ '') _PACKAGE_cc=0
+ ;;
+ *) _PACKAGE_cc=1
+ test -f $INITROOT/hello.c -a -f $INITROOT/p.c || {
+ echo "$command: $INITROOT: INIT package source not found" >&2
+ return 1
+ }
+ executable $INSTALLROOT/bin/nmake || {
+ # check for prototyping cc
+ # NOTE: proto.c must be K&R compatible
+
+ $CC -c $INITROOT/p.c >/dev/null 2>&1
+ c=$?
+ rm -f p.*
+ test 0 != "$c" && {
+ checkaout proto || return
+ PROTOROOT=$PACKAGEROOT/proto
+ $show PROTOROOT=$PACKAGEROOT/proto
+ export PROTOROOT
+ INITPROTO=$PROTOROOT/src/cmd/INIT
+ note proto convert $PACKAGEROOT/src into $PROTOROOT/src
+ if test -d $PACKAGEROOT/src/cmd/nmake
+ then dirs="src/cmd/INIT src/lib/libast src/lib/libardir src/lib/libcoshell src/lib/libpp src/cmd/probe src/cmd/cpp src/cmd/nmake"
+ else dirs="src"
+ fi
+ (
+ if test -f $PROTOROOT/UPDATE
+ then newer="-newer $PROTOROOT/UPDATE"
+ else newer=""
+ fi
+ case $exec in
+ '') cd $PACKAGEROOT
+ find $dirs -name '*.[CcHh]' $newer -print | proto -v -L - -C proto
+ ;;
+ *) $exec cd $PACKAGEROOT
+ $exec "find $dirs -name '*.[CcHh]' $newer -print | proto -L - -C proto"
+ ;;
+ esac
+ $exec touch $PROTOROOT/UPDATE
+ )
+ if (vpath $INSTALLROOT - $INSTALLROOT $PROTOROOT $PROTOROOT $PACKAGEROOT) >/dev/null 2>&1 &&
+ vpath $INSTALLROOT - $INSTALLROOT $PROTOROOT $PROTOROOT $PACKAGEROOT
+ then $show vpath $INSTALLROOT $PROTOROOT $PROTOROOT $PACKAGEROOT $USER_VPATH_CHAIN
+ else VPATH=$INSTALLROOT:$PROTOROOT:$PACKAGEROOT$USER_VPATH
+ $show VPATH=$VPATH
+ export VPATH
+ fi
+ }
+ }
+ for i in arch arch/$HOSTTYPE arch/$HOSTTYPE/bin
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || return
+ done
+ ;;
+ esac
+ ;;
+ esac
+ case $_PACKAGE_cc in
+ '') case $cc in
+ '') _PACKAGE_cc=0 ;;
+ *) _PACKAGE_cc=1 ;;
+ esac
+ ;;
+ esac
+ for i
+ do eval j=\$_PACKAGE_AOUT_$i
+ case $j in
+ '') eval _PACKAGE_AOUT_$i=1 ;;
+ *) continue ;;
+ esac
+ k=$_PACKAGE_cc
+ if test -f $INITROOT/$i.c
+ then k=${k}1
+ else k=${k}0
+ fi
+ if executable $EXECROOT/bin/$i
+ then k=${k}1
+ else k=${k}0
+ fi
+ : $k : compiler : source : binary :
+ case $k in
+ *00) view - bin/$i && continue ;;
+ esac
+ case $k in
+ 000) echo "$command: $i: not found: download the INIT package $HOSTTYPE binary to continue" >&2
+ return 1
+ ;;
+ 010) echo "$command: $i: not found: set CC=C-compiler or download the INIT package $HOSTTYPE binary to continue" >&2
+ return 1
+ ;;
+ 100) echo "$command: $i: not found: download the INIT package source or $HOSTTYPE binary to continue" >&2
+ return 1
+ ;;
+ 110) case $CROSS in
+ 1) echo "$command: $i: not found: make the local $EXECTYPE binary package before $HOSTTYPE" >&2
+ return 1
+ ;;
+ esac
+ ;;
+ ?01) : accept binary
+ continue
+ ;;
+ 011) : accept binary
+ continue
+ ;;
+ ??1) case $CROSS in
+ 1) continue ;;
+ esac
+ ;;
+ esac
+ case `ls -t $INITROOT/$i.c $INSTALLROOT/bin/$i 2>/dev/null` in
+ "$INITROOT/$i.c"*)
+ note update $INSTALLROOT/bin/$i
+ if test proto != "$i" && executable $INSTALLROOT/bin/proto
+ then case $exec in
+ '') $INSTALLROOT/bin/proto -p $INITROOT/$i.c > $i.c || return ;;
+ *) $exec "$INSTALLROOT/bin/proto -p $INITROOT/$i.c > $i.c" ;;
+ esac
+ $exec $CC $CCFLAGS -o $INSTALLROOT/bin/$i $i.c || return
+ $exec rm -f $i.c
+ else if test ! -d $INSTALLROOT/bin
+ then for j in arch arch/$HOSTTYPE arch/$HOSTTYPE/bin
+ do test -d $PACKAGEROOT/$j || $exec mkdir $PACKAGEROOT/$j || return
+ done
+ fi
+ if test '' != "$PROTOROOT" -a -f $INITPROTO/$i.c
+ then $exec $CC $CCFLAGS -o $INSTALLROOT/bin/$i $INITPROTO/$i.c || return
+ else $exec $CC $CCFLAGS -o $INSTALLROOT/bin/$i $INITROOT/$i.c || return
+ fi
+ case $i:$exec in
+ proto:) test -d $INSTALLROOT/include || mkdir $INSTALLROOT/include
+ $INSTALLROOT/bin/proto -f /dev/null > $i.c
+ cmp -s $i.c $INSTALLROOT/include/prototyped.h 2>/dev/null || cp $i.c $INSTALLROOT/include/prototyped.h
+ rm $i.c
+ ;;
+ esac
+ fi
+ test -f $i.o && $exec rm -f $i.o
+ i=$PATH
+ PATH=/bin
+ PATH=$i
+ ;;
+ esac
+ done
+ return 0
+}
+
+# check package requirements against received packages
+
+requirements() # source|binary [ package ]
+{
+ case $1 in
+ binary) r=$VIEW_BIN ;;
+ source) r=$VIEW_SRC ;;
+ *) r=$VIEW_ALL ;;
+ esac
+ shift
+ case $1 in
+ '') x= ;;
+ *) x=$* ;;
+ esac
+ set ''
+ for d in $r
+ do set "$@" $d/gen/*.ver
+ case $x in
+ '') set "$@" $d/gen/*.req
+ ;;
+ *) for p in $x
+ do set "$@" $d/gen/$p.req
+ done
+ ;;
+ esac
+ done
+ shift
+ e=0
+ x=$*
+ y=
+ n=
+ set ''
+ for i in $x
+ do p=`echo $i | sed -e 's,.*/,,' -e 's,\....$,,'`
+ if test -f $i
+ then set "$@" $i
+ y="$y $p"
+ else case $p in
+ '*') ;;
+ *) n="$n $p" ;;
+ esac
+ fi
+ done
+ for i in $n
+ do case " $y " in
+ *" $i "*)
+ ;;
+ *) echo "$command: $i: must read or write package" >&2
+ e=1
+ ;;
+ esac
+ done
+ case $e in
+ 1) exit 1 ;;
+ esac
+ shift
+ test 0 != "$#" && release=`sort -r "$@" | {
+ q=
+ e=0
+ o=
+ while read p v r s
+ do q="$q
+$v $r"
+ case $p in
+ $o) continue ;;
+ esac
+ case $s in
+ 0) e=1
+ case $r in
+ base) echo "$command: base package $p.$v or newer required" >&2 ;;
+ *) echo "$command: delta package $p.$v.$r or newer required" >&2 ;;
+ esac
+ ;;
+ esac
+ o=$p
+ done
+ case $e in
+ 0) echo "$q" | sort | { read v r; read v r; echo $v; } ;;
+ 1) echo ERROR ;;
+ esac
+ }`
+ case $release in
+ ERROR) case $force in
+ 0) exit 1 ;;
+ esac
+ ;;
+ ?*) eval `echo $release | sed -e 's,\(.*\)-\(.*\)-\(.*\),yy=\1 mm=\2 dd=\3,'`
+ # slide back 4 months
+ case $mm in
+ 01) mm=09 dd=1 ;;
+ 02) mm=10 dd=1 ;;
+ 03) mm=11 dd=1 ;;
+ 04) mm=12 dd=1 ;;
+ 05) mm=01 dd=0 ;;
+ 06) mm=02 dd=0 ;;
+ 07) mm=03 dd=0 ;;
+ 08) mm=04 dd=0 ;;
+ 09) mm=05 dd=0 ;;
+ 10) mm=06 dd=0 ;;
+ 11) mm=07 dd=0 ;;
+ 12) mm=08 dd=0 ;;
+ esac
+ case $dd in
+ 1) yy=`expr $yy - 1` ;;
+ esac
+ release=$yy-$mm-01
+ count=1
+ lo=$release
+ release="-f $release -r $count"
+ ;;
+ esac
+}
+
+# write ordered package prerequisite list to the standard output
+
+order() # [ package ]
+{
+ _order_t_=lib/package/tgz
+ case $action in
+ binary) _order_a_=.$HOSTTYPE ;;
+ *) _order_a_= ;;
+ esac
+ _order_n_=$#
+ case $_order_n_ in
+ 0) _order_p_=
+ for _order_v_ in $VIEW_all
+ do for _order_f_ in $_order_v_/lib/package/*.pkg
+ do if test -f $_order_f_
+ then _order_p_="$_order_p_ $_order_f_"
+ fi
+ done
+ done
+ set '' $_order_p_
+ shift
+ esac
+ {
+ if test ratz != "$*"
+ then for _order_f_ in ratz INIT
+ do if view -s - src $_order_t_/$_order_f_$_order_a_.tim
+ then echo $_order_f_ $_order_f_
+ fi
+ done
+ fi
+ for _order_f_
+ do while :
+ do view - src $_order_f_ && break
+ case $_order_f_ in
+ *.pkg) ;;
+ *) _order_f_=$_order_f_.pkg; view - src $_order_f_ && break ;;
+ esac
+ case $_order_f_ in
+ */*) ;;
+ *) _order_f_=lib/package/$_order_f_; view - src $_order_f_ && break ;;
+ esac
+ echo "$command: $_order_f_: not a package" >&2
+ continue 2
+ done
+ _order_f_=$_view_
+ _order_p_=`echo $_order_f_ | sed -e 's,.*/,,' -e 's,\.pkg$,,'`
+ case $_order_n_ in
+ 0) view -s - src $_order_t_/$_order_p_$_order_a_.tim || continue ;;
+ esac
+ echo $_order_p_ $_order_p_
+ case $_order_p_ in
+ INIT|ratz)
+ ;;
+ *) echo INIT $_order_p_
+ ;;
+ esac
+ {
+ req= req_sep=
+ op=::
+ while read line
+ do IFS=' \\'
+ set '' $line
+ IFS=$ifs
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :*:) op=$1
+ ;;
+ INIT|'$('*|*')')
+ ;;
+ *) case $op in
+ :REQUIRES:)
+ req="$req$req_sep$1"
+ req_sep=" "
+ ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ for _order_i_ in $req
+ do if view - src lib/package/$_order_i_.pkg
+ then case $_order_u_ in
+ 0) view -s - src $_order_t_/$_order_i_$_order_a_.tim || continue ;;
+ esac
+ echo $_order_i_ $_order_i_; echo INIT $_order_i_; echo $_order_i_ $_order_p_
+ fi
+ done
+ } < $_order_f_
+ done
+ } | tsort
+}
+
+# generate the package component list in _components_
+
+components() # [ package ]
+{
+ _components_=
+ for p
+ do case $p in
+ '') ;;
+ INIT) case " $_components_ " in
+ *" $p "*) ;;
+ *) _components_="$_components_ $p" ;;
+ esac
+ ;;
+ *) if view - src lib/package/$p.pkg
+ then p=$_view_
+ op=::
+ exec < $p
+ while read line
+ do IFS=' \\'
+ set '' $line
+ IFS=$ifs
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :*:) op=$1
+ ;;
+ INIT|'$('*|*')')
+ ;;
+ *) case $op in
+ :PACKAGE:)
+ case " $_components_ " in
+ *" $1 "*) ;;
+ *) _components_="$_components_ $1" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ exec < /dev/null
+ elif test -d $PACKAGEROOT/src/cmd/$p -o -d $PACKAGEROOT/src/lib/$p
+ then _components_="$_components_ $p"
+ else echo "$command: $p: package or component not found" >&2
+ exit 1
+ fi
+ ;;
+ esac
+ done
+}
+
+# list main environment values
+
+showenv()
+{
+ case $1 in
+ ''|make)for __i__ in CC SHELL $env
+ do eval echo $__i__='$'$__i__
+ done
+ ;;
+ esac
+}
+
+# capture command output
+
+capture() # file command ...
+{
+ case $make:$noexec in
+ :) case $action in
+ install|make|view)
+ o=$action
+ ;;
+ *) case $package in
+ ''|*' '*)
+ o=$action
+ ;;
+ *) o=$package
+ ;;
+ esac
+ ;;
+ esac
+ case $action in
+ write) d=$PACKAGESRC/gen ;;
+ *) d=$PACKAGEBIN/gen ;;
+ esac
+ test -d $d || $exec mkdir $d
+ o=$d/$o
+ case $o in
+ $output)o=$o.out
+ s=
+ ;;
+ *) output=$o
+ if test -f $o.old
+ then mv $o.old $o.out.1
+ if test -f $o.out
+ then mv $o.out $o.out.2
+ fi
+ elif test -f $o.out
+ then for i in `ls -t $o.out.? 2>/dev/null`
+ do break
+ done
+ case $i in
+ *.1) i=2 ;;
+ *.2) i=3 ;;
+ *.3) i=4 ;;
+ *.4) i=5 ;;
+ *.5) i=6 ;;
+ *.6) i=7 ;;
+ *.7) i=8 ;;
+ *.8) i=9 ;;
+ *) i=1 ;;
+ esac
+ mv $o.out $o.out.$i
+ fi
+ o=$o.out
+ : > $o
+ note $action output captured in $o
+ s="$command: $action start at `date` in $INSTALLROOT"
+ case $quiet in
+ 0) trap "echo \"$command: $action done at \`date\`\" in $INSTALLROOT 2>&1 | \$TEE -a $o" 0 1 2 ;;
+ *) trap "echo \"$command: $action done at \`date\`\" in $INSTALLROOT >> $o" 0 1 2 ;;
+ esac
+ ;;
+ esac
+ case $quiet in
+ 0) if executable ! $TEE
+ then TEE=tee
+ fi
+ {
+ case $s in
+ ?*) echo "$s" ;;
+ esac
+ showenv $action
+ "$@"
+ } < /dev/null 2>&1 | $TEE -a $o
+ ;;
+ *) {
+ case $s in
+ ?*) echo "$s" ;;
+ esac
+ showenv $action
+ "$@"
+ } < /dev/null > $o 2>&1
+ ;;
+ esac
+ ;;
+ *) $make "$@"
+ ;;
+ esac
+}
+
+package_install() # dest sum
+{
+ dest=$1 sum=$2
+ ot=
+ code=0
+ sed -e '/ /!d' -e 's,[^ ]* ,,' -e 's, \(arch/[^/]*\)/, \1 ,' -e '/ arch\//!s,^[^ ]* [^ ]* [^ ]*,& .,' -e 's,/\([^ /]*\)$, \1,' $sum |
+ while read mode user group arch dir file
+ do case $flat:$arch in
+ 1:*|?:.)t=$dest/$dir ;;
+ *) t=$dest/$arch/$dir ;;
+ esac
+ case $t in
+ $ot) ;;
+ *) if test ! -d "$t"
+ then $exec mkdir -p "$t" || exit
+ fi
+ ot=$t
+ ;;
+ esac
+ case $file in
+ ?*) case $arch in
+ .) f=$dir/$file ;;
+ *) f=$arch/$dir/$file ;;
+ esac
+ if test -f "$f"
+ then t=$t/$file
+ case $quiet in
+ 0) echo "$t" ;;
+ esac
+ $exec cp -f "$f" "$t" || code=1
+ $exec chmod $mode "$t" || code=1
+ fi
+ ;;
+ esac
+ done
+ return $code
+}
+
+package_verify() # sum
+{
+ $exec $SUM -cp $1
+}
+
+make_recurse() # dir
+{
+ for _make_recurse_j in $makefiles
+ do if view - $1/$_make_recurse_j
+ then return
+ fi
+ done
+ if test -d $1
+ then case $exec in
+ '') echo :MAKE: > $1/Makefile || exit ;;
+ *) $exec "echo :MAKE: > $1/Makefile" ;;
+ esac
+ fi
+}
+
+get() # host path [ file size ]
+{
+ case $HURL in
+ '') HURL=.
+ for i in wget lynx curl
+ do if onpath $i
+ then HURL=$i
+ break;
+ fi
+ done
+ AUTHORIZE="User-Agent: package AT&T Research\\r\\n"
+ case $HURL:$authorize in
+ .:?*) AUTHORIZE="${AUTHORIZE}Authorization: Basic `print -n -r -- $authorize:$password | uuencode -h -x base64`\\r\\n" ;;
+ esac
+ ;;
+ esac
+ getfd=8
+ case $3 in
+ '') case $HURL in
+ .) host=$1
+ path=$2
+ while :
+ do eval "exec $getfd<> /dev/tcp/$host/80" || exit
+ case $path in
+ /*) ;;
+ *) path=/$path ;;
+ esac
+ print "GET $path HTTP/1.0\\r\\nHost: $host\\r\\n$AUTHORIZE\\r" >&$getfd
+ cat <&8 > get.tmp
+ got=`sed -e 1q get.tmp`
+ case $got in
+ *" "200" "*)
+ got=`sed -e '1,/^.$/d' -e '/^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]/!d' get.tmp`
+ : > get.err
+ code=0
+ break
+ ;;
+ *" "30[123]" "*)
+ got=`sed -e '/^Location: /!d' -e 's,^Location: \(.*\)://\([^/]*\)\(/.*\),prot='\''\1'\'' host='\''\2'\'' path='\''\3'\'',' get.tmp`
+ case $got in
+ '') rm get.tmp
+ echo "$command: $action: $url: redirect error" >&2
+ exit 1
+ ;;
+ esac
+ eval $got
+ ;;
+ *) rm get.tmp
+ echo "$command: $action: $url: $got" >&2
+ echo '' "$got" > get.err
+ code=1
+ break
+ ;;
+ esac
+ done
+ ;;
+ curl) case $authorize in
+ '') curl -s -L -o get.tmp http://$1/$2 2> get.err; code=$? ;;
+ *) curl -s -L -o get.tmp -u "$authorize":"$password" http://$1/$2 2> get.err; code=$? ;;
+ esac
+ got=`grep '^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]' get.tmp 2>/dev/null`
+ case $code in
+ 0) if grep '^<H1>Authorization Required</H1>' get.tmp > get.err
+ then code=1
+ fi
+ ;;
+ esac
+ ;;
+ hurl) case $authorize in
+ '') hurl http://$1/$2 > get.tmp 2> get.err; code=$? ;;
+ *) hurl -a "$authorize":"$password" http://$1/$2 > get.tmp 2> get.err; code=$? ;;
+ esac
+ got=`grep '^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]' get.tmp`
+ ;;
+ lynx) case $authorize in
+ '') lynx -source http://$1/$2 > get.tmp 2> get.err; code=$? ;;
+ *) lynx -source -auth "$authorize":"$password" http://$1/$2 > get.tmp 2> get.err; code=$? ;;
+ esac
+ got=`grep '^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]' get.tmp`
+ ;;
+ wget) wget -nv -O get.tmp ${authorize:+--http-user="$authorize"} ${password:+--http-passwd="$password"} http://$1/$2 2> get.err
+ code=$?
+ got=`grep '^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ]' get.tmp 2>/dev/null`
+ ;;
+ *) echo $command: $action: $HURL: url get command not found >&2
+ exit 1
+ ;;
+ esac
+ if test 0 != "$code"
+ then case `cat get.err get.tmp 2>/dev/null` in
+ *[Aa][Uu][Tt][Hh][Oo][Rr][Ii][SsZz]*|*[Dd][Ee][Nn][Ii][Ee][Dd]*)
+ echo $command: $action: authorization required -- see $url for license acceptance authorization name and password >&2
+ ;;
+ *) cat get.err
+ ;;
+ esac
+ rm -f get.tmp get.err
+ echo $command: $action: $2: download failed >&2
+ exit 1
+ fi
+ rm -f get.tmp get.err
+ ;;
+ *) case $exec in
+ '') echo "$3 ($4 bytes):" >&2
+ case $HURL in
+ .) eval "exec $getfd<> /dev/tcp/$1/80" || exit
+ path=$2/$3
+ case $path in
+ /*) ;;
+ *) path=/$path ;;
+ esac
+ print "GET $path HTTP/1.0\\r\\nHost: $host\\r\\n$AUTHORIZE\\r" >&$getfd
+ read got <&$getfd
+ case $got in
+ *" 200 "*)
+ code=0
+ : > get.err
+ ;;
+ *) echo '' "$got" > get.err
+ code=1
+ ;;
+ esac
+ while read got <&$getfd
+ do case $got in
+ ''|?) break ;;
+ esac
+ done
+ cat <&$getfd > get.tmp
+ ;;
+ curl) case $authorize in
+ '') curl -s -L -o get.tmp http://$1/$2/$3 2> get.err; code=$? ;;
+ *) curl -s -L -o get.tmp -u "$authorize":"$password" http://$1/$2/$3 2> get.err; code=$?
+ esac
+ case $code in
+ 0) if grep '^<H1>Authorization Required</H1>' get.tmp > get.err
+ then code=1
+ fi
+ ;;
+ esac
+ ;;
+ hurl) case $authorize in
+ '') ksh -x hurl http://$1/$2/$3 > get.tmp 2> get.err; code=$? ;;
+ *) ksh -x hurl -a "$authorize":"$password" http://$1/$2/$3 > get.tmp 2> get.err; code=$? ;;
+ esac
+ ;;
+ lynx) case $authorize in
+ '') lynx -source http://$1/$2/$3 > get.tmp 2> get.err; code=$? ;;
+ *) lynx -source -auth "$authorize":"$password" http://$1/$2/$3 > get.tmp 2> get.err; code=$? ;;
+ esac
+ ;;
+ wget) wget -nv -O get.tmp ${authorize:+--http-user="$authorize"} ${password:+--http-passwd="$password"} http://$1/$2/$3 2> get.err
+ code=$?
+ ;;
+ *) echo $command: $action: $HURL: url get command not found >&2
+ exit 1
+ ;;
+ esac
+ if test 0 != "$code"
+ then case `cat get.err get.tmp` in
+ *[Aa][Uu][Tt][Hh][Oo][Rr][Ii][SsZz]*|*[Dd][Ee][Nn][Ii][Ee][Dd]*)
+ echo $command: $action: authorization required -- see $url for license acceptance authorization name and password >&2
+ ;;
+ *) cat get.err
+ ;;
+ esac
+ rm get.tmp get.err
+ echo $command: $action: $3: download failed >&2
+ exit 1
+ fi
+ rm get.err
+ case $checksum:$5 in
+ :*|*:-) z=`wc -c < get.tmp`
+ case " $z " in
+ *" $4 "*)
+ ;;
+ *) rm -f get.tmp
+ echo $command: $3: download error: expected $4 bytes, got $z >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ *) z=`$checksum < get.tmp | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'`
+ case " $z " in
+ *" $5 "*)
+ ;;
+ *) rm -f get.tmp
+ echo $command: $3: download $checksum error: expected $5, got $z >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ mv get.tmp $3 || exit
+ ;;
+ *) echo "$3 ($4 bytes)" >&2
+ ;;
+ esac
+ esac
+}
+
+# generate copyright notice
+
+copyright()
+{
+ if test -f $1.lic
+ then echo $1 package general copyright notice
+ echo
+ proto -c'#' -p -s -l $1.lic -o type=verbose,author='*' /dev/null
+ return 0
+ fi
+ case $1 in
+ *-*) eval `echo '' $1 | sed 's/\([^-]*\)-\(.*\)/__j__="\1" __i__="\2"/'`
+ if copyright $__i__ || copyright $__j__
+ then return 0
+ fi
+ ;;
+ esac
+ return 1
+}
+
+# run remote make on host
+
+remote() # host no-exec-background
+{
+ host=$1
+ background=$2
+ eval name=\$${host}_name user=\$${host}_user snarf=\$${host}_snarf type=\$${host}_type rsh=\$${host}_rsh root=\$${host}_root keep=\$${host}_keep log=\$${host}_log
+ case $keep in
+ 1*) ;;
+ *) return ;;
+ esac
+ case $host in
+ $main) ;;
+ *) case $exec in
+ '') exec > $admin_log/$log 2>&1 ;;
+ *) echo "exec > $admin_log/$log 2>&1" ;;
+ esac
+ ;;
+ esac
+ if $admin_ping $name >/dev/null 2>&1 || $admin_ping $name >/dev/null 2>&1
+ then cmd=". ./.profile"
+ case $root in
+ .) root=
+ ;;
+ *) cmd="$cmd && cd $root"
+ root=$root/
+ ;;
+ esac
+ cmd="$cmd && { test -f lib/package/admin/$admin_env && . ./lib/package/admin/$admin_env || true ;} && PATH=\${PWD:-\`pwd\`}/bin:\$PATH \${SHELL:-/bin/sh} -c 'package $admin_args PACKAGEROOT=\${PWD:-\`pwd\`} HOSTTYPE=$type VPATH='"
+ case $admin_binary in
+ '') snarf= ;;
+ esac
+ case $snarf in
+ '') $exec $rsh $user$name "$cmd" $background
+ ;;
+ *?) rcp=`echo $rsh | sed 's/\(.\).*/\1/'`cp
+ case $background in
+ ?*) $exec "{" ;;
+ esac
+ $exec $rsh $user$name "$cmd"
+ eval lst=$admin_list
+ case $admin_pkgs in
+ '') filter=cat ;;
+ *) filter="egrep lib/package/tgz/($admin_pkgs)\\." ;;
+ esac
+ if $exec $rcp $user$name:${root}lib/package/tgz/$lst $PACKAGESRC/tgz
+ then $exec $rcp `$filter $PACKAGESRC/tgz/$lst | sed "s,^,$user$name:,"` $PACKAGESRC/tgz
+ else echo "$command: $user$name:${root}lib/package/tgz/$lst: not found" >&2
+ fi
+ case $background in
+ ?*) $exec "} $background" ;;
+ esac
+ ;;
+ esac
+ else echo "$command: $name: down" >&2
+ fi
+}
+
+# update package_src
+
+checksrc()
+{
+ case $package_src in
+ '') package_src=$src
+ for _i_ in `cd $PACKAGESRC; ls *.def *.lic *.pkg 2>/dev/null | sed 's/[-.].*//'`
+ do case " $package_src " in
+ *" $_i_ "*)
+ ;;
+ *) package_src="$package_src $_i_"
+ ;;
+ esac
+ done
+ ;;
+ esac
+}
+
+# check for native ascii 0:yes 1:no
+
+__isascii__=
+
+isascii()
+{
+ case $__isascii__ in
+ '') case `echo A | od -o | sed -e 's/[ ]*$//' -e '/[ ]/!d' -e 's/.*[ ]//'` in
+ 005101|040412) __isascii__=0 ;;
+ *) __isascii__=1 ;;
+ esac
+ esac
+ return $__isascii__
+}
+
+case $action in
+
+admin) while test ! -f $admin_db
+ do case $admin_db in
+ /*) echo $command: $action: $admin_db: data file not found >&2
+ exit 1
+ ;;
+ esac
+ view file src lib/package/admin/$admin_db || exit 1
+ admin_db=$_view_
+ done
+ admin_components=
+ case $admin_action in
+ list) cat $admin_db
+ exit
+ ;;
+ test) set $admin_args
+ while :
+ do case $# in
+ 1) break ;;
+ esac
+ shift
+ case $1 in
+ *=*) ;;
+ *) admin_components=-$1
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ : all work done in $PACKAGESRC/admin
+ cd $PACKAGESRC/admin || exit
+ checksrc
+ packages=
+ admin_log=${admin_action}${admin_components}.log
+ exec < $admin_db || exit
+ test -d $admin_log || $exec mkdir $admin_log || exit
+ case $admin_on in
+ '') admin_on="*" ;;
+ esac
+ hostname=
+ hosts=
+ logs=
+ local_hosts=
+ local_types=
+ pids=
+ remote_hosts=
+ sync_hosts=
+ admin_host=_admin_host_
+ admin_out=
+ case " $admin_args " in
+ *" write binary "*|*" write "*" binary "*)
+ admin_binary=1
+ ;;
+ *) admin_binary=
+ ;;
+ esac
+ case $only in
+ 1) admin_args="only $admin_args" ;;
+ esac
+ trap 'kill $pids >/dev/null 2>&1' 1 2 3 15
+ index=0
+ while read type host root date time make test write comment
+ do case $type in
+ ''|'#'*);;
+ *=*) eval "$type $host $root $date $time $make $test $write $comment"
+ ;;
+ *) case $admin_action in
+ make|test|write)
+ eval f='$'$admin_action
+ case $f in
+ *[!0123456789]*) continue ;;
+ esac
+ ;;
+ esac
+ rsh=rsh
+ case $host in
+ *@*) IFS=@
+ set '' $host
+ IFS=$ifs
+ user=${2}@
+ host=$3
+ ;;
+ *) user=
+ ;;
+ esac
+ : type=$type host=$host root=$root date=$date time=$time make=$make test=$test write=$write :
+ name=$host
+ host=`echo $name | sed 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789],__,g'`
+ eval x='$'${host}_index
+ eval ${host}_index=1
+ case $x in
+ 1) i=0
+ while :
+ do case $i in
+ $index) h=''
+ break
+ ;;
+ esac
+ i=`expr $i + 1`
+ eval h='$'${admin_host}${i}_name
+ case $h in
+ $host) host=${admin_host}${i}
+ eval user='$'${host}_user root='$'${host}_rsh:$host:'$'${host}_root
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ case $root in
+ *:$name:*)root=`echo '' $root | sed 's,:.*,:,'` ;;
+ esac
+ case $root in
+ *:*:*) index=`expr $index + 1`
+ host=${admin_host}$index
+ ;;
+ *:*) case " $sync_hosts " in
+ *" $name ${admin_host}"*)
+ set '' '' $sync_hosts
+ while :
+ do shift
+ shift
+ case $1 in
+ $name) host=$2
+ break
+ ;;
+ esac
+ done
+ ;;
+ *) index=`expr $index + 1`
+ host=${admin_host}$index
+ sync_hosts="$sync_hosts $name $host"
+ ;;
+ esac
+ ;;
+ *) index=`expr $index + 1`
+ host=${admin_host}$index
+ ;;
+ esac
+ case $root in
+ -*) continue
+ ;;
+ *:*) case $admin_all in
+ 0) continue ;;
+ esac
+ case $root in
+ *:) root=${root}. ;;
+ esac
+ IFS=:
+ set '' $root
+ IFS=$ifs
+ sync=$host
+ case $hostname in
+ '') hostinfo name
+ hostname=$_hostinfo_
+ ;;
+ esac
+ shift
+ case $# in
+ 0) ;;
+ 1) root=$1
+ ;;
+ 2) rsh=$1 root=$2
+ ;;
+ *) rsh=$1 sync=$2 root=$3
+ case $sync in
+ ${admin_host}*)
+ ;;
+ ?*) case " $sync_hosts " in
+ *" $sync ${admin_host}"*)
+ set '' '' $sync_hosts
+ while :
+ do shift
+ shift
+ case $1 in
+ $sync) sync=$2
+ break
+ ;;
+ esac
+ done
+ ;;
+ *) index=`expr $index + 1`
+ x=${admin_host}$index
+ sync_hosts="$sync_hosts $sync $x"
+ sync=$x
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) sync=
+ ;;
+ esac
+ case $name in
+ $admin_on)
+ keep=1
+ ;;
+ *) case " $admin_on " in
+ *" $name "*) keep=1 ;;
+ *) keep=0 ;;
+ esac
+ ;;
+ esac
+ case " $admin_out " in
+ *" $name "*)
+ log=$name.$type
+ ;;
+ *) admin_out="$admin_out $name"
+ log=$name
+ ;;
+ esac
+ case $sync in
+ '') local_types="$local_types $type" ;;
+ esac
+ case $sync in
+ $host) remote_hosts="$remote_hosts $host"
+ ;;
+ ?*) eval ${sync}_share=\"\$${sync}_share $host\"
+ ;;
+ '') local_hosts="$local_hosts $host"
+ ;;
+ esac
+ eval ${host}_name='$'name ${host}_type='$'type ${host}_user='$'user ${host}_sync='$'sync ${host}_snarf='$'sync ${host}_rsh='$'rsh ${host}_root='$'root ${host}_keep='$'keep ${host}_log='$'log
+ ;;
+ esac
+ done
+ p=
+ for i in $admin_args
+ do p="$i $p"
+ done
+ admin_pkgs=
+ for i in $p
+ do if view - src "lib/package/$i.pkg"
+ then case $admin_pkgs in
+ '') admin_pkgs="$i" ;;
+ *) admin_pkgs="$admin_pkgs|$i" ;;
+ esac
+ fi
+ done
+ : "admin_binary :" $admin_binary
+ : "admin_args :" $admin_args
+ : "admin_pkgs :" $admin_pkgs
+ : "admin_on :" "$admin_on"
+ : "local_hosts :" $local_hosts
+ : "local_types :" $local_types
+ : "remote_hosts :" $remote_hosts
+ : "sync_hosts :" $sync_hosts
+ : "sync_share :" $sync_share
+ case $admin_binary in
+ 1) admin_bin_types=
+ admin_bin_main=
+ for main in $local_hosts $remote_hosts
+ do eval share=\$${main}_share keep=\$${main}_keep
+ case $keep in
+ 0*) continue ;;
+ esac
+ for host in $main $share
+ do case " $admin_bin_hosts " in
+ *" $host "*)
+ continue
+ ;;
+ esac
+ eval type=\$${host}_type
+ case " $admin_bin_types " in
+ *" $type "*)
+ continue
+ ;;
+ esac
+ case " $types " in
+ " ") ;;
+ *" $type "*)
+ ;;
+ *) continue
+ ;;
+ esac
+ admin_bin_hosts="$admin_bin_hosts $host"
+ admin_bin_types="$admin_bin_types $type"
+ case " $admin_bin_hosts " in
+ *" $main "*)
+ ;;
+ *) case " $admin_bin_main " in
+ *" $main "*)
+ ;;
+ *) admin_bin_main="$admin_bin_main $main"
+ ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ local=
+ remote=
+ for host in $admin_bin_main $admin_bin_hosts
+ do case " $local_hosts " in
+ *" $host "*)
+ local="$local $host"
+ ;;
+ *) case " $remote_hosts " in
+ *" $host "*)
+ remote="$remote $host"
+ ;;
+ esac
+ ;;
+ esac
+ done
+ local_hosts=$local
+ remote_hosts=$remote
+ ;;
+ esac
+ for host in $remote_hosts $local_hosts
+ do eval share=\$${host}_share
+ case $share in
+ ?*) while :
+ do oshare=$share
+ for s in $share
+ do eval r='$'${s}_share
+ case $r in
+ ?*) case " $share " in
+ *" $r "*) ;;
+ *) share="$share $r" ;;
+ esac
+ ;;
+ esac
+ done
+ case $share in
+ $oshare) eval ${host}_share="'$share'"
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ done
+ for host in $remote_hosts
+ do eval type=\$${host}_type
+ case " $local_types " in
+ *" $type "*)
+ eval ${host}_snarf=
+ ;;
+ esac
+ eval name=\$${host}_name keep=\$${host}_keep share=\$${host}_share
+ for share in $share
+ do eval type=\$${share}_type keep=\$keep\$${share}_keep
+ case " $local_types " in
+ *" $type "*)
+ eval ${share}_snarf=
+ ;;
+ esac
+ done
+ case $keep in
+ 0*1*) keep=2$keep ;;
+ *1*) ;;
+ *) keep=0 ;;
+ esac
+ eval ${host}_keep=$keep
+ done
+ for host in $remote_hosts $local_hosts
+ do eval name=\$${host}_name user=\$${host}_user type=\$${host}_type sync=\$${host}_sync snarf=\$${host}_snarf share=\$${host}_share rsh=\$${host}_rsh root=\$${host}_root keep=\$${host}_keep
+ case $keep in
+ 0*) continue ;;
+ esac
+ case $sync in
+ '') case $admin_action in
+ ditto) continue ;;
+ esac
+ case $admin_binary in
+ 1) case $keep in
+ 1*|?*1*);;
+ *) continue ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ eval main_log='$'${host}_log
+ main=
+ share_keep=
+ for i in $host $share
+ do eval n='$'${i}_name t='$'${i}_type q='$'${i}_sync s='$'${i}_snarf l='$'${i}_log k='$'${i}_keep
+ case $main:$k in
+ :*) ;;
+ *:0) continue ;;
+ esac
+ case $admin_binary in
+ 1) case $s:$q in
+ :?*) continue ;;
+ esac
+ case " $admin_bin_hosts " in
+ *" $i "*)
+ ;;
+ *) continue
+ ;;
+ esac
+ ;;
+ esac
+ case $main in
+ '') main=$i ;;
+ *) share_keep="$share_keep $i" ;;
+ esac
+ echo package "$admin_args" "[ $n $t ]"
+ case $exec in
+ '') : > $admin_log/$l ;;
+ *) $exec ": > $admin_log/$l" ;;
+ esac
+ done
+ host=$main
+ share=$share_keep
+ case $force in
+ 0) admin_ditto_update=--update ;;
+ *) admin_ditto_update= ;;
+ esac
+ case $exec in
+ '') {
+ case $admin_binary:$sync in
+ :?*) eval syncname='$'${sync}_name
+ test -x $PACKAGEROOT/bin/package && $admin_ditto $admin_ditto_update --remote=$rsh --expr="name=='package'" $PACKAGEROOT/bin $user$syncname:$root/bin
+ test -d $PACKAGESRC && $admin_ditto $admin_ditto_update --remote=$rsh --expr="if(level>1&&path!='LICENSES/*')status=SKIP;path=='LICENSES*|*.(pkg|lic|def)'" $PACKAGESRC $user$syncname:$root/lib/package
+ for dir in $package_src
+ do case $MAKESKIP in
+ '') expr="--expr=if(name=='$admin_ditto_skip')status=SKIP" ;;
+ *) expr="--expr=if(name=='$admin_ditto_skip'||level==1&&name=='$MAKESKIP')status=SKIP" ;;
+ esac
+ test -d $PACKAGEROOT/src/$dir && $admin_ditto $admin_ditto_update --remote=$rsh "$expr" $PACKAGEROOT/src/$dir $user$syncname:$root/src/$dir
+ done
+ ;;
+ esac
+ case $admin_action in
+ ditto) ;;
+ ?*) pids=
+ set '' $host $share
+ while :
+ do shift
+ case $# in
+ 0) break
+ ;;
+ 1) remote $1
+ ;;
+ *) remote $1 &
+ pids="$pids $!"
+ ;;
+ esac
+ done
+ case $pids in
+ ?*) wait $pids ;;
+ esac
+ ;;
+ esac
+ } < /dev/null > $admin_log/$main_log 2>&1 &
+ pids="$pids $!"
+ ;;
+ *) echo "{"
+ case $admin_binary:$sync in
+ :?*) eval syncname='$'${sync}_name
+ test -d $PACKAGESRC && echo $admin_ditto $admin_ditto_update --remote=$rsh --expr="if(level>1)status=SKIP;name=='*.(pkg|lic|def)'" $PACKAGESRC $user$syncname:$root/lib/package
+ for dir in $package_src
+ do case $MAKESKIP in
+ '') expr="--expr=if(name=='$admin_ditto_skip')status=SKIP" ;;
+ *) expr="--expr=if(name=='$admin_ditto_skip'||level==1&&name=='$MAKESKIP')status=SKIP" ;;
+ esac
+ test -d $PACKAGEROOT/src/$dir && echo $admin_ditto $admin_ditto_update --remote=$rsh "$expr" $PACKAGEROOT/src/$dir $user$syncname:$root/src/$dir
+ done
+ ;;
+ esac
+ case $admin_action in
+ ditto) ;;
+ ?*) pids=
+ set '' $host $share
+ while :
+ do shift
+ case $# in
+ 0) break
+ ;;
+ 1) remote $1
+ ;;
+ *) remote $1 "&"
+ pids=1
+ ;;
+ esac
+ done
+ case $pids in
+ 1) echo wait ;;
+ esac
+ ;;
+ esac
+ echo "} < /dev/null > $admin_log/$main_log 2>&1 &"
+ ;;
+ esac
+ eval name='$'${main}_name
+ hosts="$hosts $name"
+ logs="$logs $main_log"
+ for share in $share
+ do eval keep=\$${share}_keep
+ case $keep in
+ 1) eval name='$'${share}_name log='$'${share}_log
+ hosts="$hosts $name"
+ logs="$logs $log"
+ ;;
+ esac
+ done
+ done
+ case $exec in
+ '') # track the progress
+ case $quiet in
+ 0) cd $admin_log
+ tail -t $PACKAGE_admin_tail_timeout -f $logs
+ cd ..
+ ;;
+ esac
+ # wait for the remote actions to complete
+ wait
+ trap - 1 2 3 15
+ # update the db
+ exec < $admin_db || exit
+ exec 9>&1
+ D=`date +%y%m%d`
+ while read line
+ do set -- $line
+ case $1 in
+ ''|'#'*|*=*)
+ ;;
+ *) case " $hosts " in
+ *" $2 "*)
+ : ast date command assumed :
+ E=`eval date -E \`egrep '[ ](start|done)[ ][ ]*at[ ]' $admin_log/$2 | sed -e 's/.*[ ][ ]*at[ ][ ]*//' -e 's/[ ][ ]*in[ ].*$//' -e 's/.*/"&"/'\``
+ M=$6 T=$7 W=$8
+ case $admin_action in
+ make|view)
+ M=`egrep -c ']:.* (\*\*\*.* code|don'\''t know) | \*\*\* termination code ' $admin_log/$2` ;;
+ test) T=`grep -ci 'fail[es]' $admin_log/$2` ;;
+ *) W=`grep '^[abcdefghijklmnopqrstuvwxyz][abcdefghijklmnopqrstuvwxyz]*:.' $admin_log/$2 | egrep -cv 'start at|done at|output captured|warning:|: package not found|whence: command not found'` ;;
+ esac
+ case $1 in
+ ?|??|???|????|?????|??????|???????)
+ t1=' '
+ ;;
+ ????????|?????????|??????????|???????????|????????????|?????????????|??????????????|???????????????)
+ t1=' '
+ ;;
+ *) t1=''
+ ;;
+ esac
+ case $2 in
+ ?|??|???|????|?????|??????|???????)
+ t2=' '
+ ;;
+ *) t2=''
+ ;;
+ esac
+ case $3 in
+ ?|??|???|????|?????|??????|???????)
+ t3=' '
+ ;;
+ *) t3=''
+ ;;
+ esac
+ case $E in
+ ?????) E=" $E" ;;
+ ????) E=" $E" ;;
+ ???) E=" $E" ;;
+ ??) E=" $E" ;;
+ ?) E=" $E" ;;
+ esac
+ case $M in
+ ???) M="$M" ;;
+ ??) M=" $M" ;;
+ ?) M=" $M" ;;
+ '') M=" 0" ;;
+ esac
+ case $T in
+ ???) T="$T" ;;
+ ??) T=" $T" ;;
+ ?) T=" $T" ;;
+ '') T=" 0" ;;
+ esac
+ case $W in
+ ???) W="$W" ;;
+ ??) W=" $W" ;;
+ ?) W=" $W" ;;
+ '') W=" 0" ;;
+ esac
+ A=$1$t1
+ H=$2$t2
+ R=$3$t3
+ case $# in
+ [0-8]) C=
+ ;;
+ *) shift 8
+ C=" $*"
+ ;;
+ esac
+ echo "$A $H $R $D $E $M $T $W$C"
+ echo "$A $H $R $D $E $M $T $W$C" >&9
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ echo "$line"
+ done > $admin_db.new
+ mv $admin_db $admin_db.old
+ mv $admin_db.new $admin_db
+ ;;
+ esac
+ ;;
+
+clean|clobber)
+ cd $PACKAGEROOT
+ $exec rm -rf $INSTALLROOT
+ exit
+ ;;
+
+contents|list)
+ # all work in $PACKAGESRC
+
+ cd $PACKAGESRC
+
+ # generate the package list
+
+ set '' $target $package
+ shift
+ argc=$#
+ case $# in
+ 0) set '' *.pkg
+ case $2 in
+ '*.pkg')
+ echo $command: $action: no packages >&2
+ exit 1
+ ;;
+ esac
+ set '' `echo $* | sed 's,\.pkg,,g'`
+ shift
+ ;;
+ esac
+ sep="$nl "
+ echo packages in $PACKAGEROOT
+ case $action in
+ list) echo
+ echo "NAME${nl}VERSION${nl}RELEASE${nl}TYPE${nl}STATUS${nl}REQUIRES${nl}----${nl}-------${nl}-------${nl}----${nl}------${nl}--------" | pr -6 -a -o4 -t
+ ;;
+ esac
+ {
+ omit=:
+ for pkg
+ do if test ! -f $pkg.pkg
+ then echo $command: $action: $pkg: not a package >&2
+ else if test -f gen/$pkg.ver
+ then set '' `cat gen/$pkg.ver`
+ case $3 in
+ $2) ver=base ;;
+ *) ver=$3 ;;
+ esac
+ if test -s tgz/$pkg.tim
+ then sts=local
+ else sts=
+ fi
+ else ver=
+ sts=unwritten
+ fi
+ typ=
+ txt=
+ cmp= cmp_sep=
+ req= req_sep=
+ op=::
+ exec < $pkg.pkg
+ while read line
+ do IFS=' \\'
+ set '' $line
+ IFS=$ifs
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ :*:) op=$1
+ ;;
+ INIT|'$('*|*')')
+ ;;
+ *) case $op in
+ :DESCRIPTION:)
+ txt="$txt$sep$line"
+ break
+ ;;
+ :PACKAGE:)
+ cmp="$cmp$cmp_sep$1"
+ cmp_sep=$nl
+ ;;
+ :REQUIRES:)
+ req="$req$req_sep$1"
+ req_sep=" "
+ ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ exec < /dev/null
+ case $txt in
+ ?*) txt="$nl$txt" ;;
+ esac
+ case :$ver: in
+ *::*) ;;
+ *) case $action in
+ list) case $sts in
+ '') case `ls -t "tgz/$pkg.$ver.base" "tgz/$pkg.tim" 2>/dev/null` in
+ "tgz/$pkg.tim"*)
+ sts=read
+ ;;
+ *) sts=unread
+ ;;
+ esac
+ ;;
+ esac
+ echo "$pkg${nl}$ver${nl}base${nl}$typ${nl}$sts${nl}$req"
+ case $typ in
+ '') omit=$omit$pkg.$ver.base: ;;
+ esac
+ ;;
+ *) case $req in
+ ?*) req=": $req" ;;
+ esac
+ echo
+ echo $pkg $ver $req "$txt"
+ case $cmp in
+ ?*) echo "${sep}Components in this package:$nl"
+ echo "$cmp" | pr -4 -o4 -t ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ case $argc:$action in
+ 0:list) if test -d tgz
+ then cd tgz
+ # f:file p:package v:version r:release t:type u:update
+ for f in `find . -name '*?[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]*' -print | sed 's,^\./,,' | sort -r`
+ do eval `echo "$f" | sed -e 's,\.c$,,' -e 's,\.gz$,,' -e 's,\.exe$,,' -e 's,\.tgz$,,' -e 's,\([^_.]*\)[_.]\([0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]\)[_.]\([0123456789][0123456789][0123456789][0123456789][^_.]*\)[_.]*\(.*\),p=\1 v=\2 r=\3 t=\4,' -e 's,\([^_.]*\)[_.]\([0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]\)[_.]*\(.*\),p=\1 v=\2 r=base t=\3,'`
+ case $t in
+ '') case $omit in
+ *:$p.$v.$r:*) continue ;;
+ esac
+ u=$p.tim
+ ;;
+ *) u=$p.$t.tim
+ ;;
+ esac
+ if test -s "$u"
+ then s=local
+ elif test -f "$u"
+ then case `ls -t "$f" "$u" 2>/dev/null` in
+ "$u"*) s=read ;;
+ *) s=unread ;;
+ esac
+ else s=unread
+ fi
+ echo "$p$nl$v$nl$r$nl$t$nl$s$nl"
+ done
+ fi
+ ;;
+ esac
+ } |
+ case $action in
+ list) pr -6 -a -o4 -t | sort -u ;;
+ *) cat ;;
+ esac
+ case $argc in
+ 0) if test -d $PACKAGEROOT/arch
+ then echo
+ echo architectures in $PACKAGEROOT
+ echo
+ for i in `ls $PACKAGEROOT/arch`
+ do if test -f $PACKAGEROOT/arch/$i/lib/package/gen/host
+ then h=`cat $PACKAGEROOT/arch/$i/lib/package/gen/host`
+ else h=
+ fi
+ echo $i
+ echo $h
+ echo
+ echo
+ done | pr -4 -a -o4 -t
+ fi
+ ;;
+ esac
+ ;;
+
+copyright)
+ # all work in $PACKAGESRC
+
+ cd $PACKAGESRC
+
+ # generate the package list
+
+ set '' $target $package
+ shift
+ argc=$#
+ case $# in
+ 0) set '' `echo *.lic | sed 's,\.lic,,g'`
+ shift
+ case $1 in
+ '*') echo $command: $action: no packages >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ checkaout proto || exit
+ for i
+ do copyright $i
+ done
+ ;;
+
+export) case $INSTALLROOT in
+ $PACKAGEROOT)
+ INSTALLROOT=$INSTALLROOT/arch/$HOSTTYPE
+ ;;
+ esac
+ case $only in
+ 0) v='$i=' ;;
+ *) v= ;;
+ esac
+ set '' $target $package
+ case $# in
+ 1) set '' $env ;;
+ esac
+ while :
+ do case $# in
+ 1) break ;;
+ esac
+ shift
+ i=$1
+ eval echo ${v}'$'${i}
+ done
+ ;;
+
+install)cd $PACKAGEROOT
+ set '' $package
+ shift
+ case $only in
+ 0) set '' `order "$@"`
+ shift
+ ;;
+ esac
+ case $# in
+ 0) echo "$command: at least one package name expected" >&2
+ exit 1
+ ;;
+ esac
+ package=$*
+ requirements - $package
+ set '' $target
+ shift
+ case $1 in
+ flat) flat=1 # backwards compatibility -- documentation dropped
+ shift
+ ;;
+ esac
+ case $# in
+ 0) echo "$command: $action: target directory argument expected" >&2
+ exit 1
+ ;;
+ esac
+ target=
+ while :
+ do case $# in
+ 1) directory=$1
+ break
+ ;;
+ esac
+ target="$target $1"
+ shift
+ done
+ if test ! -d $directory
+ then echo "$command: $action: $directory: target directory not found" >&2
+ exit 1
+ fi
+ case $target in
+ '') cd arch
+ set '' *
+ shift
+ target=$*
+ cd ..
+ ;;
+ esac
+ code=0
+ makecheck=1
+ for a in $target
+ do case $a in
+ -) a=$HOSTTYPE ;;
+ esac
+ case $flat:$a in
+ 1:*|?:.)dest=$directory
+ ;;
+ *) dest=$directory/arch/$a
+ if test "" = "$exec" -a ! -d $dest
+ then mkdir -p $dest || {
+ echo "$command: $dest: destination directory must exist" >&2
+ exit 1
+ }
+ fi
+ ;;
+ esac
+ for i in $package
+ do if test "ratz" = "$i"
+ then : skip
+ elif test -f arch/$a/lib/package/gen/$i.sum
+ then package_install $directory arch/$a/lib/package/gen/$i.sum || code=1
+ elif test ! -d arch/$a/bin
+ then echo "$command: $a: invalid architecture" >&2
+ elif test ! -d $dest
+ then echo "$command: $dest: destination directory must exist" >&2
+ else if test "" != "$makecheck"
+ then if onpath $MAKE
+ then MAKE=$_onpath_
+ else echo "$command: $MAKE: not found" >&2
+ exit 1
+ fi
+ makecheck=
+ fi
+ if test "" != "$exec"
+ then (
+ trap - 0 1 2 15
+ echo "=== $i installation manifest ==="
+ cd arch/$a
+ (
+ cd lib/package
+ INSTALLROOT=$PACKAGEROOT/arch/$a
+ VPATH=$INSTALLROOT:$PACKAGEROOT:$VPATH
+ export INSTALLROOT VPATH
+ $MAKE -s $makeflags -f $i.pkg $qualifier list.installed $assign
+ ) | sort -u
+ )
+ else (
+ set -
+ cd arch/$a
+ (
+ cd lib/package
+ INSTALLROOT=$PACKAGEROOT/arch/$a
+ VPATH=$INSTALLROOT:$PACKAGEROOT:$VPATH
+ export INSTALLROOT VPATH
+ echo lib/$command
+ $MAKE -s $makeflags -f $i.pkg $qualifier list.installed $assign
+ ) | sort -u | pax -drw -ps $dest
+ )
+ fi
+ fi
+ done
+ done
+ exit $code
+ ;;
+
+license)# all work in $PACKAGESRC/LICENSES
+
+ cd $PACKAGESRC/LICENSES || exit
+
+ # generate the package list
+
+ set '' $target $package
+ shift
+ argc=$#
+ case $# in
+ 0) set '' *
+ shift
+ case $1 in
+ '*') echo $command: $action: no licenses >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ *) checkaout proto || exit
+ a=
+ for i
+ do while :
+ do if test -f ../$i.lic
+ then j=`proto -df -l ../$i.lic -o query=type /dev/null 2>/dev/null`
+ case $j in
+ ?*) if test -f $j
+ then case " $a " in
+ *" $j "*) ;;
+ *) a="$a $j" ;;
+ esac
+ fi
+ break
+ ;;
+ esac
+ fi
+ case $i in
+ *-*) i=`echo $i | sed 's/-[^-]*$//'`
+ ;;
+ *) echo "$command: $i: package license not found" >&2
+ break
+ ;;
+ esac
+ done
+ done
+ set '' $a
+ shift
+ ;;
+ esac
+ for i
+ do case $exec in
+ '') echo
+ echo " --- $i source license ---"
+ echo
+ cat $i
+ ;;
+ *) echo $PACKAGESRC/LICENSES/$i
+ ;;
+ esac
+ done
+ ;;
+
+make|view)
+ cd $PACKAGEROOT
+ case $package in
+ '') lic="lib/package/*.lic"
+ ;;
+ *) for i in $package
+ do lic="$lic lib/package/$i.lic"
+ case $i in
+ *-*) lic="$lic lib/package/"`echo $i | sed 's,-.*,,'`".lic" ;;
+ esac
+ done
+ ;;
+ esac
+ checksrc
+ requirements source $package
+ components $package
+ package=$_components_
+
+ # check for some required commands
+
+ must="$AR"
+ warn="$NM yacc bison"
+ test="$must $warn"
+ have=
+ IFS=:
+ set /$IFS$PATH
+ IFS=$ifs
+ shift
+ for t in $test
+ do if executable $t
+ then have="$have $t"
+ fi
+ done
+ for d
+ do for t in $test
+ do case " $have " in
+ *" $t "*)
+ ;;
+ *) if executable $d/$t
+ then have="$have $t"
+ fi
+ ;;
+ esac
+ done
+ done
+ case " $have " in
+ *" bison "*) ;;
+ *" yacc "*) have="$have bison" ;;
+ esac
+ case " $have " in
+ *" yacc "*) ;;
+ *" bison "*) have="$have yacc" ;;
+ esac
+ for t in $test
+ do case " $have " in
+ *" $t "*)
+ ;;
+ *) case " $must " in
+ *" $t "*)
+ echo "$command: $t: not found -- must be on PATH to $action" >&2
+ exit 1
+ ;;
+ *) echo "$command: warning: $t: not found -- some $action actions may fail" >&2
+ ;;
+ esac
+ ;;
+ esac
+ done
+
+ # verify the top view
+
+ if test ! -d $PACKAGEROOT/src
+ then note no source packages to make
+ exit 0
+ elif test ! -d $INSTALLROOT/src
+ then note initialize the $INSTALLROOT view
+ fi
+ for i in arch arch/$HOSTTYPE
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || exit
+ done
+ for i in bin bin/$OK bin/$OK/lib fun include lib lib/package lib/package/gen src man man/man1 man/man3 man/man8
+ do test -d $INSTALLROOT/$i || $exec mkdir $INSTALLROOT/$i || exit
+ done
+ make_recurse src
+ o= k=
+ for i in $makefiles
+ do case $o in
+ ?*) o="$o -o" k="$k|" ;;
+ esac
+ o="$o -name $i"
+ k="$k$i"
+ done
+ o="( $o ) -print"
+ for d in $package_src
+ do i=src/$d
+ if test -d $i
+ then test -d $INSTALLROOT/$i || $exec mkdir $INSTALLROOT/$i || exit
+ make_recurse $i
+ for j in `cd $i; find . $o 2>/dev/null | sed -e 's,^\./,,' -e '/\//!d' -e 's,/[^/]*$,,' | sort -u`
+ do case $j in
+ $k|$MAKESKIP) continue ;;
+ esac
+ test -d $INSTALLROOT/$i/$j ||
+ $exec mkdir -p $INSTALLROOT/$i/$j || exit
+ done
+ fi
+ done
+ def=
+ for i in $lic
+ do test -f $i || continue
+ cmp -s $i $INSTALLROOT/$i 2>/dev/null ||
+ $exec cp $PACKAGEROOT/$i $INSTALLROOT/$i
+ for j in `grep '^. .*\.def$' $i`
+ do case $j in
+ .) ;;
+ *) case " $def " in
+ *" $i "*) ;;
+ *) def="$def $i" ;;
+ esac
+ ;;
+ esac
+ done
+ done
+ for i in $def
+ do i=lib/package/$i
+ test -f $i || continue
+ cmp -s $i $INSTALLROOT/$i 2>/dev/null ||
+ $exec cp $PACKAGEROOT/$i $INSTALLROOT/$i
+ done
+
+ # check $CC and { ar cc ld ldd } intercepts
+
+ h="${HOSTTYPE} ${HOSTTYPE}.*"
+ case $HOSTTYPE in
+ *.*) t=`echo $HOSTTYPE | sed 's/[.][^.]*//'`
+ h="$h $t"
+ ;;
+ *) t=$HOSTTYPE
+ ;;
+ esac
+ case $t in
+ *[0123456789])
+ t=`echo $t | sed 's/[0123456789]*$//'`
+ h="$h $t"
+ ;;
+ esac
+ case $CC in
+ cc) c=cc
+ b=$INSTALLROOT/bin/$c
+ t=$INSTALLROOT/lib/package/gen/$c.tim
+ intercept=0
+ for k in $h
+ do for s in $INITROOT/$c.$k
+ do test -x "$s" || continue
+ if cmp -s "$s" "$b" >/dev/null 2>&1
+ then intercept=1
+ break 2
+ fi
+ case `ls -t "$t" "$b" "$s" 2>/dev/null` in
+ $t*) ;;
+ $b*) cc=$b
+ ;;
+ $s*) cd $INSTALLROOT/lib/package/gen
+ tmp=pkg$$
+ eval '$'exec echo "'int main(){return 0;}' > $tmp.c"
+ if $exec $s -o $tmp.exe $tmp.c >/dev/null 2>&1 &&
+ test -x $tmp.exe
+ then case $HOSTTYPE in
+ *.mips*)$s -version >/dev/null 2>&1 || s= ;;
+ esac
+ case $s in
+ ?*) $exec sed "s/^HOSTTYPE=.*/HOSTTYPE=$HOSTTYPE/" < "$s" > "$b" || exit
+ $exec chmod +x "$b" || exit
+ cc=$b
+ intercept=1
+ note update $b
+ ;;
+ esac
+ fi
+ $exec rm -f $tmp.*
+ $exec touch "$t"
+ cd $PACKAGEROOT
+ ;;
+ esac
+ break 2
+ done
+ done
+ case $intercept in
+ 1) c=ld
+ b=$INSTALLROOT/bin/$c
+ for k in $h
+ do for s in $INITROOT/$c.$k
+ do test -x "$s" || continue
+ case `ls -t "$b" "$s" 2>/dev/null` in
+ $b*) ;;
+ $s*) $exec cp "$s" "$b"
+ note update $b
+ ;;
+ esac
+ done
+ done
+ ;;
+ esac
+ ;;
+ esac
+ c=ldd
+ b=$INSTALLROOT/bin/$c
+ for t in $h
+ do s=$INITROOT/$c.$t
+ test -x "$s" || continue
+ onpath $c ||
+ case `ls -t "$b" "$s" 2>/dev/null` in
+ $b*) ;;
+ $s*) $exec cp "$s" "$b"
+ note update $b
+ ;;
+ esac
+ done
+# following code stubbed out just in case ar.ibm.risc is needed
+# c=ar
+# b=$INSTALLROOT/bin/$c
+# for t in $h
+# do s=$INITROOT/$c.$t
+# test -x "$s" || continue
+# onpath $c ||
+# case `ls -t "$b" "$s" 2>/dev/null` in
+# $b*) ;;
+# $s*) x=`$s -tv /foo/bar.a 2>&1 | egrep -i 'option|usage'`
+# case $x in
+# '') $exec cp "$s" "$b"
+# note update $b
+# ;;
+# esac
+# ;;
+# esac
+# done
+ case $cc in
+ /*) ;;
+ *) echo "$command: $CC: not found -- set CC=C-compiler" >&2
+ exit 1
+ ;;
+ esac
+ case $exec in
+ '') cd $INSTALLROOT/lib/package/gen
+ tmp=pkg$$
+ echo 'int main(){return 0;}' > $tmp.c
+ if $CC -o $tmp.exe $tmp.c > /dev/null 2> $tmp.err &&
+ test -x $tmp.exe
+ then : ok
+ else echo "$command: $CC: failed to compile this program:" >&2
+ cat $tmp.c >&2
+ if test -s $tmp.err
+ then cat $tmp.err >&2
+ else echo "$command: $CC: not a C compiler" >&2
+ fi
+ rm -f $tmp.*
+ exit 1
+ fi
+ rm -f $tmp.*
+ cd $PACKAGEROOT
+ ;;
+ esac
+
+ # remember the default $CC
+
+ case $CC in
+ cc) ;;
+ *) if test -x $INSTALLROOT/bin/cc
+ then case `sed 1q $INSTALLROOT/bin/cc` in
+ ": $CC :")
+ CC=cc
+ export CC
+ ;;
+ *) assign="$assign CC=\"\$CC\""
+ ;;
+ esac
+ else case $CROSS in
+ 1) assign="$assign CC=\"\$CC\""
+ ;;
+ *) case $exec in
+ '') {
+ echo ": $CC :"
+ echo "$CC \"\$@\""
+ } > $INSTALLROOT/bin/cc
+ chmod +x $INSTALLROOT/bin/cc
+ ;;
+ *) note generate a $INSTALLROOT/bin/cc wrapper for $CC
+ ;;
+ esac
+ CC=cc
+ export CC
+ ;;
+ esac
+ fi
+ ;;
+ esac
+
+ # no $INITROOT means INIT already installed elsewhere
+
+ if test -d $INITROOT
+ then
+ # update probe scripts
+
+ for i in lib/probe lib/probe/C lib/probe/C/make
+ do test -d $INSTALLROOT/$i || $exec mkdir $INSTALLROOT/$i || exit
+ done
+ i=$INSTALLROOT/lib/probe/C/make/probe
+ j=$INITROOT/C+probe
+ k=$INITROOT/make.probe
+ case `ls -t $i $j $k 2>/dev/null` in
+ $i*) ;;
+ *) if test -f $j -a -f $k
+ then note update $i
+ shellmagic
+ case $exec in
+ '') {
+ case $SHELLMAGIC in
+ ?*) echo "$SHELLMAGIC" ;;
+ esac
+ cat $j $k
+ } > $i || exit
+ ;;
+ *) echo "{
+echo $SHELLMAGIC
+cat $j $k
+} > $i"
+ ;;
+ esac
+ $exec chmod +x $i || exit
+ fi
+ ;;
+ esac
+ fi
+
+ # initialize a few mamake related commands
+
+ checkaout mamake proto ratz release || exit
+
+ # execrate if necessary
+
+ if (execrate) >/dev/null 2>&1
+ then execrate=execrate
+ $make cd $INSTALLROOT/bin
+ for i in chmod chgrp cmp cp ln mv rm
+ do if test ! -x $OK/$i -a -x /bin/$i.exe
+ then shellmagic
+ case $exec in
+ '') echo "$SHELLMAGIC"'execrate /bin/'$i' "$@"' > $OK/$i
+ chmod +x $OK/$i
+ ;;
+ *) $exec echo \'"$SHELLMAGIC"'execrate /bin/'$i' "$@"'\'' >' $OK/$i
+ $exec chmod +x $OK/$i
+ ;;
+ esac
+ fi
+ done
+ PATH=$INSTALLROOT/bin/$OK:$PATH
+ export PATH
+ else execrate=
+ fi
+ case $action in
+ view) exit 0 ;;
+ esac
+
+ # all work under $INSTALLROOT/src
+
+ $make cd $INSTALLROOT/src
+
+ # record the build host name
+
+ case $noexec in
+ '') hostinfo name
+ echo "$_hostinfo_" | sed 's,\..*,,' > $PACKAGEBIN/gen/host
+ ;;
+ esac
+
+ # make in parallel if possible
+
+ case $NPROC in
+ '') hostinfo cpu
+ case $_hostinfo_ in
+ 0|1) ;;
+ *) NPROC=$_hostinfo_
+ $show NPROC=$NPROC
+ $show export NPROC
+ export NPROC
+ ;;
+ esac
+ ;;
+ esac
+
+ # separate flags from target list
+
+ case $target in
+ *-*) a=
+ for t in $target
+ do case $t in
+ -[eiknFKNV]*|--*-symbols)
+ makeflags="$makeflags $t"
+ ;;
+ -*) nmakeflags="$nmakeflags $t"
+ ;;
+ *) a="$a $t"
+ ;;
+ esac
+ done
+ target=$a
+ ;;
+ esac
+
+ # generate nmake first if possible
+
+ if executable ! $NMAKE && test -d $PACKAGEROOT/src/cmd/nmake
+ then if nonmake $MAKE
+ then note make $NMAKE with mamake
+ c=$CC
+ a=$assign
+ case $HOSTTYPE in
+ win32*|cygwin*)
+ CC="$CC -D_BLD_STATIC"
+ accept="libast"
+ case $assign in
+ *' CC='*) ;;
+ *) assign="$assign CC=\"\$CC\"" ;;
+ esac
+ ;;
+ *) accept=nmake
+ ;;
+ esac
+ eval capture mamake \$makeflags \$nmakeflags \$noexec install nmake $assign
+ assign=$a
+ CC=$c
+ case $make$noexec in
+ '') if executable ! $NMAKE
+ then echo "$command: $action: errors making $NMAKE" >&2
+ exit 1
+ fi
+ ;;
+ *) make=echo
+ ;;
+ esac
+ if test '' != "$PROTOROOT"
+ then if (vpath $INSTALLROOT - $PROTOROOT - $INSTALLROOT $PACKAGEROOT) >/dev/null 2>&1 &&
+ vpath $INSTALLROOT - $PROTOROOT - $INSTALLROOT $PACKAGEROOT
+ then $show vpath $INSTALLROOT $PACKAGEROOT $USER_VPATH_CHAIN
+ else VPATH=$INSTALLROOT:$PACKAGEROOT$USER_VPATH
+ $show VPATH=$VPATH
+ export VPATH
+ fi
+ fi
+ note believe generated files for $accept
+ eval capture \$NMAKE \$makeflags \$nmakeflags \$noexec recurse believe \$nmakesep $accept $assign
+ $exec touch $INSTALLROOT/bin/.paths
+ note make the remaining targets with $NMAKE
+ else eval capture $MAKE \$makeflags \$nmakeflags \$noexec install nmake $assign
+ case $make$noexec in
+ '') if executable ! $NMAKE
+ then echo "$command: $action: errors making $NMAKE" >&2
+ exit 1
+ fi
+ ;;
+ *) make=echo
+ ;;
+ esac
+ fi
+ fi
+
+ # generate ksh next if possible
+
+ if nonmake $MAKE
+ then : no need to generate ksh next -- it could be the only package
+ elif test "$KEEP_SHELL" != 1 -a -d $PACKAGEROOT/src/cmd/ksh93 && executable ! $KSH
+ then eval capture nmake $nmakeflags \$makeflags \$noexec install ksh93 $assign
+ case $make$noexec in
+ '') if executable ! $KSH
+ then echo "$command: $action: errors making $KSH" >&2
+ exit 1
+ fi
+ ;;
+ *) make=echo
+ ;;
+ esac
+ fi
+
+ # mamprobe data should have been generated by this point
+
+ case $exec in
+ '') if test ! -f $INSTALLROOT/bin/.paths -o -w $INSTALLROOT/bin/.paths
+ then nl="
+"
+ o=`cat $INSTALLROOT/bin/.paths 2>/dev/null`
+ v=
+ n=
+ case $nl$o in
+ *${nl}FPATH=*|*#FPATH=*|*[Nn][Oo]FPATH=*)
+ ;;
+ *) case $n in
+ '') ;;
+ *) n="$n$nl" v="$v|" ;;
+ esac
+ n="${n}FPATH=../fun"
+ v="${v}FPATH"
+ ;;
+ esac
+ case $nl$o in
+ *${nl}BUILTIN_LIB=*|*#BUILTIN_LIB=*|*[Nn][Oo]BUILTIN_LIB=*)
+ ;;
+ *) case $n in
+ '') ;;
+ *) n="$n$nl" v="$v|" ;;
+ esac
+ if grep '^setv mam_cc_DIALECT .* EXPORT=[AD]LL' $INSTALLROOT/lib/probe/C/mam/* >/dev/null 2>&1
+ then x=
+ else x='no'
+ fi
+ n="${n}${x}BUILTIN_LIB=cmd"
+ v="${v}BUILTIN_LIB"
+ ;;
+ esac
+ case $n in
+ ?*) case $o in
+ ?*) o=`egrep -v "($v)=" $INSTALLROOT/bin/.paths`$nl ;;
+ esac
+ echo "# use { # no NO } prefix instead of XX to permanently disable #$nl$o$n" > $INSTALLROOT/bin/.paths
+ ;;
+ esac
+ fi
+ ;;
+ esac
+
+ # run from separate copies since nmake and ksh may be rebuilt
+
+ case $EXECROOT in
+ $INSTALLROOT)
+ $make cd $INSTALLROOT/bin
+ if executable /bin/cp
+ then cp=/bin/cp
+ else cp=cp
+ fi
+ if executable /bin/mv
+ then mv=/bin/mv
+ else mv=mv
+ fi
+ if executable /bin/rm
+ then rm=/bin/rm
+ else rm=rm
+ fi
+ for i in \
+ ksh nmake tee cp ln mv rm \
+ *ast*.dll *cmd*.dll *dll*.dll *shell*.dll
+ do executable $i && {
+ cmp -s $i $OK/$i 2>/dev/null || {
+ test -f $OK/$i &&
+ $exec $execrate $rm $OK/$i </dev/null
+ test -f $OK/$i &&
+ $exec $execrate $mv $OK/$i $OK/$i.old </dev/null
+ test -f $OK/$i &&
+ case $exec:$i in
+ :nmake|:ksh)
+ echo "$command: $OK/$i: cannot update [may be in use by a running process] remove manually and try again" >&2
+ exit 1
+ ;;
+ esac
+ $exec $execrate $cp $i $OK/$i
+ }
+ }
+ done
+ if test -f ../lib/make/makerules.mo
+ then cmp -s ../lib/make/makerules.mo $OK/lib/makerules.mo ||
+ $exec $execrate $cp -p ../lib/make/makerules.mo $OK/lib/makerules.mo ||
+ $exec $execrate $cp ../lib/make/makerules.mo $OK/lib/makerules.mo
+ fi
+ if executable $OK/nmake
+ then MAKE="$INSTALLROOT/bin/$OK/nmake LOCALRULESPATH=$INSTALLROOT/bin/$OK/lib"
+ fi
+ if executable $OK/tee
+ then TEE=$INSTALLROOT/bin/$OK/tee
+ fi
+ if test "$KEEP_SHELL" != 1 && executable $OK/ksh
+ then SHELL=$INSTALLROOT/bin/$OK/ksh
+ export SHELL
+ COSHELL=$SHELL
+ export COSHELL
+ fi
+ case :$PATH: in
+ *:$INSTALLROOT/bin/$OK:*)
+ ;;
+ *) PATH=$INSTALLROOT/bin/$OK:$PATH
+ export PATH
+ ;;
+ esac
+ $make cd $INSTALLROOT/src
+ ;;
+ esac
+
+ # fall back to mamake if nmake not found or too old
+
+ if nonmake $MAKE
+ then note make with mamake
+ case $target in
+ '') target="install" ;;
+ esac
+ eval capture mamake \$makeflags \$noexec \$target $assign
+ else case $target in
+ '') target="install cc-" ;;
+ esac
+ eval capture \$MAKE \$makeflags \$nmakeflags \$noexec recurse \$target \$nmakesep \$package $assign
+ fi
+ ;;
+
+read) case ${PWD:-`pwd`} in
+ $PACKAGEROOT)
+ ;;
+ *) echo "$command: must be in package root directory" >&2
+ exit 1
+ ;;
+ esac
+ PAX=
+ if onpath pax
+ then case `$_onpath_ -rw --?meter 2>&1` in
+ *--meter*) PAX=pax ;;
+ esac
+ fi
+ code=0
+ i=
+ x=
+ remove=
+ touch=
+ set '' $target
+ case $2 in
+ lcl|tgz)tgz=$2
+ shift 2
+ target=$*
+ ;;
+ *) tgz=tgz
+ ;;
+ esac
+ set '' $package $target
+ case $# in
+ 1) verbose=:
+ set '' `ls lib/package/$tgz/*?[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]* 2>/dev/null`
+ ;;
+ *) verbose=
+ ;;
+ esac
+ shift
+ files=
+ for f
+ do if test -f "$f"
+ then : ok
+ elif test -f "lib/package/$tgz/$f"
+ then f=lib/package/$tgz/$f
+ else set '' `ls -r ${f}[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]* 2>/dev/null`
+ if test '' != "$2" -a -f "$2"
+ then f=$2
+ else set '' `ls -r lib/package/$tgz/${f}[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]* 2>/dev/null`
+ if test '' != "$2" -a -f "$2"
+ then f=$2
+ else echo "$command: $f: package archive not found" >&2
+ continue
+ fi
+ fi
+ fi
+ files="$files $f"
+ done
+ case $files in
+ '') echo "$command: lib/package/$tgz: no package archives" >&2
+ exit 1
+ ;;
+ esac
+ set '' `ls -r $files 2>/dev/null`
+ shift
+ f1= f2= f3= f4=
+ for f
+ do case $f in
+ ratz.*|*/ratz.*)
+ f1="$f1 $f"
+ ;;
+ INIT.*|*/INIT.*)
+ f2="$f2 $f"
+ ;;
+ INIT*|*/INIT*)
+ f3="$f3 $f"
+ ;;
+ *) f4="$f4 $f"
+ ;;
+ esac
+ done
+ gen=
+ set '' $f1 $f2 $f3 $f4
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ f=$1
+ case $f in
+ *.gz) : standalone packages unbundled manually
+ continue
+ ;;
+ *.md5) : tarball checksum
+ continue
+ ;;
+ *?[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]*)
+ ;;
+ *) echo "$command: $f: not a package archive" >&2
+ code=1
+ continue
+ ;;
+ esac
+ case $f in
+ */*) eval `echo "$f" | sed -e 's,\(.*/\)\(.*\),d=\1 a=\2,'` ;;
+ *) d= a=$f ;;
+ esac
+ # f:file d:dir a:base p:package v:version r:release t:type
+ eval `echo "$a" | sed -e 's,\.c$,,' -e 's,\.gz$,,' -e 's,\.exe$,,' -e 's,\.tgz$,,' -e 's,\([^_.]*\)[_.]\([0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]\)[_.]\([0123456789][0123456789][0123456789][0123456789][^_.]*\)[_.]*\(.*\),p=\1 v=\2 r=\3 t=\4,' -e 's,\([^_.]*\)[_.]\([0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]\)[_.]*\(.*\),p=\1 v=\2 r=base t=\3,'`
+ case $r in
+ base) y=$p.base ;;
+ *) y=$p.delta ;;
+ esac
+ case " $x " in
+ *" $y "*)
+ continue
+ ;;
+ esac
+ case $t in
+ '') w=$PACKAGESRC
+ q=
+ Q=
+ m=
+ ;;
+ *) w=$PACKAGEROOT/arch/$t/lib/package
+ q=".$t"
+ Q="_$t"
+ m="[_.]$t"
+ ;;
+ esac
+ u=$d$p$q.tim
+ if test -s "$u"
+ then continue
+ else case $force in
+ 0) case `ls -t "$f" "$u" 2>/dev/null` in
+ "$u"*) case $verbose in
+ 1) note $p already read ;;
+ esac
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ case $p in
+ INIT) if test -f $PACKAGEROOT/bin/package
+ then $exec mv $PACKAGEROOT/bin/package $PACKAGEROOT/bin/package.old
+ fi
+ ;;
+ esac
+ z=
+ case $r in
+ base) # base archive
+ if test ratz = "$p"
+ then # ratz packages are not archives
+ case $t in
+ '') for i in src src/cmd src/cmd/INIT
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || exit
+ done
+ $exec cp $f $PACKAGEROOT/src/cmd/INIT/$p.c
+ ;;
+ *) for i in arch arch/$t arch/$t/bin
+ do test -d $PACKAGEROOT/$i || $exec mkdir $PACKAGEROOT/$i || exit
+ done
+ $exec cp $f $PACKAGEROOT/arch/$t/bin/$p &&
+ $exec chmod +x $PACKAGEROOT/arch/$t/bin/$p
+ ;;
+ esac
+ elif test "" != "$PAX"
+ then $exec pax -L --from=ascii --local -m -ps -rvf "$f" || {
+ code=1
+ continue
+ }
+ else if onpath gunzip && onpath $TAR && isascii
+ then case $TARPROBE in
+ ?*) for i in $TARPROBE
+ do if $TAR ${i}f - /dev/null > /dev/null 2>&1
+ then TARFLAGS=$TARFLAGS$i
+ fi
+ done
+ TARPROBE=
+ ;;
+ esac
+ if gunzip -l < "$f" > /dev/null 2>&1
+ then case $exec in
+ '') $exec gunzip < "$f" | $TAR ${TARFLAGS}f - ;;
+ *) $exec "gunzip < $f | $TAR ${TARFLAGS}f -" ;;
+ esac || {
+ code=1
+ continue
+ }
+ else $exec $TAR ${TARFLAGS}f "$f" || {
+ code=1
+ continue
+ }
+ fi
+ else checkaout ratz && onpath ratz || {
+ code=1
+ continue
+ }
+ RATZ=$_onpath_
+ case $exec in
+ '') echo $f:
+ $exec $RATZ -lm < "$f"
+ ;;
+ *) $exec "$RATZ -lm < $f"
+ ;;
+ esac || {
+ code=1
+ continue
+ }
+ fi
+ if test -f $PACKAGEBIN/gen/$p.sum
+ then while read md5 mode usr grp file
+ do case $file in
+ -*) file=./$file ;;
+ esac
+ case $mode in
+ [01234567][01234567][01234567][01234567])
+ case $grp in
+ -) ;;
+ *) $exec chgrp $grp "$file" ;;
+ esac
+ case $usr in
+ -) ;;
+ *) $exec chown $usr "$file" ;;
+ esac
+ $exec chmod $mode "$file"
+ ;;
+ esac
+ done < $PACKAGEBIN/gen/$p.sum
+ fi
+ fi
+ ;;
+ *) # delta archive
+ test "" != "$PAX" || {
+ echo "$command: $f: pax required to read delta archive" >&2
+ code=1
+ continue
+ }
+ case `echo "$v:
+$r:" | sort` in
+ $r:*) y=$p.base
+ b=${d}${p}_${r}${Q}.tgz
+ test -f "$b" || b=${d}${p}.${r}${q}.tgz
+ test -f "$b" || {
+ case " $gen " in
+ *" $b "*)
+ ;;
+ *) case $# in
+ 1) echo "$command: $f: base archive $b required to read delta" >&2
+ code=1
+ ;;
+ *) shift
+ y=$1
+ shift
+ set '' $y $f "$@"
+ esac
+ continue
+ ;;
+ esac
+ }
+ # -m with delta bug fixed 2005-02-08
+ $exec pax -L --from=ascii --local -ps -rvf "$f" -z "$b" || {
+ code=1
+ continue
+ }
+ note $f: generate new base $d$p.$v$q.tgz
+ $exec pax -rf "$f" -z "$b" -wf $d$p.$v$q.tgz -x tgz || {
+ code=1
+ continue
+ }
+ case $exec in
+ '') echo $p $v $v 1 > $w/gen/$p.ver
+ ;;
+ *) z=$d${p}[_.]$v$q.tgz
+ $exec "echo $p $v $v 1 > $w/gen/$p.ver"
+ gen="$gen $d$p.$v$q.tgz"
+ ;;
+ esac
+ case " $remove " in
+ *" $f "*) ;;
+ *) remove="$remove $f" ;;
+ esac
+ ;;
+ *) b=${d}${p}_${v}${Q}.tgz
+ test -f "$b" || b=${d}${p}.${v}${q}.tgz
+ test -f "$b" || {
+ case " $gen " in
+ *" $b "*)
+ ;;
+ *) case $# in
+ 1) echo "$command: $f: base archive $b required to read delta" >&2
+ code=1
+ ;;
+ *) shift
+ y=$1
+ shift
+ set '' $y $f "$@"
+ esac
+ continue
+ ;;
+ esac
+ }
+ # -m with delta bug fixed 2005-02-08
+ $exec pax -L --from=ascii --local -ps -rvf "$f" -z "$b" || {
+ code=1
+ continue
+ }
+ ;;
+ esac
+ ;;
+ *) echo "$command: $f: unknown archive type" >&2
+ code=1
+ continue
+ ;;
+ esac
+
+ # check for ini files
+
+ if executable $w/$p.ini
+ then $exec $w/$p.ini read || {
+ code=1
+ continue
+ }
+ fi
+
+ # add to the obsolete list
+
+ k=
+ for i in `ls $d$p[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.]????$m* $z 2>/dev/null`
+ do case $i in
+ *.md5) continue
+ ;;
+ $d${p}[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789][_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]$m*)
+ ;;
+ $d${p}[_.][0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]$m*)
+ continue
+ ;;
+ esac
+ case $k in
+ ?*) case " $remove " in
+ *" $k "*) ;;
+ *) remove="$remove $k" ;;
+ esac
+ ;;
+ esac
+ k=$i
+ done
+ x="$x $y"
+ case " $touch " in
+ *" $u "*) ;;
+ *) touch="$touch $u" ;;
+ esac
+ done
+ if test ! -f $PACKAGEROOT/bin/package -a -f $PACKAGEROOT/bin/package.old
+ then $exec cp $PACKAGEROOT/bin/package.old $PACKAGEROOT/bin/package
+ fi
+
+ # drop obsolete archives
+
+ case $remove in
+ ?*) $exec rm -f $remove ;;
+ esac
+
+ # mark the updated archives
+
+ case $touch in
+ ?*) sleep 1; $exec touch $touch ;;
+ esac
+
+ # check the requirements
+
+ case $code$exec in
+ 0) requirements - $x ;;
+ esac
+ exit $code
+ ;;
+
+regress)if test ! -d $PACKAGEBIN/gen
+ then echo "$command: 'package make' and 'package test' required for regression" >&2
+ exit 1
+ fi
+ dir=$PACKAGEBIN/gen
+ cd $dir
+ for s in out old
+ do case `ls -t regress.$s test.$s 2>/dev/null` in
+ regress*)
+ ;;
+ test*) if test -f regress.$s
+ then $exec mv regress.$s regress.old
+ fi
+ case $exec in
+ '') egrep -i '\*\*\*|FAIL|^TEST.* [123456789][0123456789]* error|core.*dump' test.$s |
+ sed -e '/\*\*\* [0123456789]/d' \
+ -e '/^TEST.\//s,/[^ ]*/,,' \
+ -e 's,[ ][ ]*$,,' \
+ -e 's/[0123456789][0123456789]*:* \([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 ]*([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 ]*[Cc][Oo][Rr][Ee][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 ]*)\)/\1/' \
+ -e 's/\.sh failed at .* with /.sh failed /' \
+ > regress.$s
+ ;;
+ *) $exec filter test failures from $dir/test.$s to $dir/regress.$s
+ ;;
+ esac
+ ;;
+ esac
+ done
+ if test -f regress.out -a -f regress.old
+ then $exec diff -b regress.out regress.old
+ else echo "$command: at least 2 test runs required for regression" >&2
+ exit 1
+ fi
+ ;;
+
+release)count= lo= hi=
+ checksrc
+ checkaout release || exit
+ requirements source $package
+ components $package
+ package=$_components_
+ set '' $target
+ shift
+ case $# in
+ 0) ;;
+ *) case $1 in
+ -|[0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789])
+ case $1 in
+ -) lo= release= ;;
+ *) lo=$1 release="-f $1" ;;
+ esac
+ shift
+ case $1 in
+ -|[0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789]-[0123456789][0123456789]-[0123456789][0123456789])
+ case $1 in
+ -) hi= ;;
+ *) hi=$1 release="$release -t $1" ;;
+ esac
+ shift
+ ;;
+ esac
+ ;;
+ [0123456789]|[0123456789][0123456789]|[0123456789][0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789]|[0123456789][0123456789][0123456789][0123456789][0123456789]*)
+ count=$1
+ release="-r $count"
+ shift
+ ;;
+ esac
+ ;;
+ esac
+ case $# in
+ 0) case $package in
+ '') package=* ;;
+ esac
+ ;;
+ *) case $package in
+ '') package=$*
+ ;;
+ *) echo $command: $*: lo-date hi-date arguments expected >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ echo
+ case $count:$lo:$hi in
+ ::) echo "All recorded changes follow." ;;
+ 1::) echo "Changes since the last release follow." ;;
+ ?*::) echo "Changes since the last $count releases follow." ;;
+ 1:?*:) echo "Changes since $lo or the last release follow." ;;
+ *:?*:*) echo "Changes since $lo follow." ;;
+ *::?*) echo "Changes before $hi follow." ;;
+ *) echo "Changes between $lo and $hi follow." ;;
+ esac
+ x=
+ for r in $INSTALLROOT $PACKAGEROOT
+ do for s in $package_src
+ do d=$r/src/$s
+ if test -d $d
+ then cd $d
+ for i in $package
+ do if test -h $i 2>/dev/null
+ then continue
+ fi
+ case " $x " in
+ *" $i "*) continue ;;
+ esac
+ for f in RELEASE CHANGES ChangeLog
+ do if test -f $i/$f
+ then $exec release $release $i/$f
+ x="$x $i"
+ for f in $i/*/$f
+ do if test -f $f
+ then $exec release $release $f
+ fi
+ done
+ break
+ fi
+ done
+ done
+ fi
+ done
+ done
+ ;;
+
+remove) echo "$command: $action: not implemented yet" >&2
+ exit 1
+ ;;
+
+results)set '' $target
+ shift
+ def=make
+ dir=$PACKAGEBIN/gen
+ case $verbose in
+ 0) filter=yes ;;
+ *) filter=cat ;;
+ esac
+ path=0
+ suf=out
+ on=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ admin) dir=$PACKAGESRC/admin
+ ;;
+ error*|fail*)
+ filter=errors
+ ;;
+ make|test|view|write)
+ def=$1
+ case $filter:$1:$SHELL in
+ errors:*:*) ;;
+ *:test:*/ksh*) filter=rt ;;
+ esac
+ ;;
+ old) suf=old
+ ;;
+ on) case $# in
+ 1) echo $command: $action: $1: host pattern argument expected >&2
+ exit 1
+ ;;
+ esac
+ shift
+ case $on in
+ ?*) on="$on|" ;;
+ esac
+ on="$on$1"
+ ;;
+ path) path=1
+ ;;
+ test) def=test
+ filter=rt
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ done
+ case $dir in
+ */admin)case $on in
+ '') on="*" ;;
+ *) on="@($on)" ;;
+ esac
+ def=$def.log/$on
+ ;;
+ esac
+ case $# in
+ 0) set "$def" ;;
+ esac
+ m=
+ t=
+ for i
+ do k=0
+ eval set '""' $i - $i.$suf - $dir/$i - $dir/$i.$suf -
+ shift
+ for j
+ do case $j in
+ -) case $k in
+ 1) continue 2 ;;
+ esac
+ ;;
+ *) if test -f $j
+ then k=1
+ case /$j in
+ */test.*) t="$t $j" ;;
+ *) m="$m $j" ;;
+ esac
+ fi
+ ;;
+ esac
+ done
+ echo "$command: $i action output not found" >&2
+ exit 1
+ done
+ sep=
+ case $t in
+ ?*) case $path in
+ 0) for j in $t
+ do echo "$sep==> $j <=="
+ sep=$nl
+ case $filter in
+ cat) $exec cat $j
+ ;;
+ errors) $exec egrep -i '\*\*\*|FAIL[ES]|^TEST.* [123456789][0123456789]* error|core.*dump' $j | sed -e '/^TEST.\//s,/[^ ]*/,,'
+ ;;
+ rt) $exec rt - $j
+ ;;
+ *) $exec egrep -i '^TEST|FAIL' $j
+ ;;
+ esac
+ done
+ ;;
+ 1) echo $t
+ ;;
+ esac
+ ;;
+ esac
+ case $m in
+ ?*) case $path in
+ 0) case $filter in
+ cat) cat $m
+ ;;
+ *) if test -f $HOME/.pkgresults
+ then i="`cat $HOME/.pkgresults`"
+ case $i in
+ '|'*) ;;
+ *) i="|$i" ;;
+ esac
+ else i=
+ fi
+ for j in $m
+ do echo "$sep==> $j <=="
+ sep=$nl
+ case $filter in
+ errors) $exeg egrep '^pax:|\*\*\*' $j
+ ;;
+ *) $exec egrep -iv '^($||[\+\[]|cc[^-:]|kill |make.*(file system time|has been replaced)|so|[0123456789]+ error|uncrate |[0123456789]+ block|ar: creat|iffe: test: |conf: (check|generate|test)|[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*=|gsf@research|ar:.*warning|cpio:|ld:.*(duplicate symbol|to obtain more information)|[0123456789]*$|(checking|creating|touch) [/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789])| obsolete predefined symbol | is (almost always misused|dangerous|deprecated|not implemented)| trigraph| assigned to | cast .* different size| integer overflow .*<<| optimization may be attained | passed as |::__builtin|pragma.*prototyped|^creating.*\.a$|warning.*not optimized|exceeds size thresh|ld:.*preempts|is unchanged|with value >=|(-l|lib)\*|/(ast|sys)/(dir|limits|param|stropts)\.h.*redefined|usage|base registers|`\.\.\.` obsolete'"$i" $j |
+ $exec grep :
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ 1) echo $m
+ ;;
+ esac
+ esac
+ ;;
+
+test) requirements source $package
+ components $package
+ package=$_components_
+ case $only in
+ 0) only= ;;
+ 1) only=--recurse=only ;;
+ esac
+
+ # must have nmake
+
+ if nonmake $MAKE
+ then echo $command: $action: must have $MAKE to test >&2
+ exit 1
+ fi
+
+ # all work under $INSTALLROOT/src
+
+ $make cd $INSTALLROOT/src
+
+ # disable core dumps (could be disasterous over nfs)
+
+ (ulimit -c 0) > /dev/null 2>&1 && ulimit -c 0
+
+ # do the tests
+
+ eval capture \$MAKE \$makeflags \$noexec \$only recurse test \$target \$nmakesep \$package $assign
+ ;;
+
+update) # download the latest release.version for selected packages
+
+ # all work in $PACKAGEROOT/lib/package/tgz
+
+ if test ! -d $PACKAGEROOT/lib/package/tgz
+ then $exec mkdir -p $PACKAGEROOT/lib/package/tgz || exit
+ $exec cd $PACKAGEROOT/lib/package/tgz
+ else cd $PACKAGEROOT/lib/package/tgz
+ fi
+
+ # get the architectures, update query url, and packages
+
+ set '' $args
+ op=update
+ tgz=tgz
+ source=
+ binary=
+ setup=
+ types=
+ url=
+ urlfile=$default_url
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ beta) op=beta
+ tgz=beta
+ ;;
+ binary) binary=1
+ ;;
+ setup) setup=1
+ ;;
+ source) source=1
+ ;;
+ *://*) url=$1
+ shift
+ break
+ ;;
+ *.url) urlfile=$1
+ if test ! -s $urlfile
+ then echo $command: $urlfile: not found >&2; exit 1
+ fi
+ break
+ ;;
+ $all_types)
+ binary=1
+ types="$types $1"
+ ;;
+ *) break
+ ;;
+ esac
+ done
+ case $source:$binary in
+ :) source=1 binary=1
+ ;;
+ :1) case $types in
+ '') types=$HOSTTYPE ;;
+ esac
+ ;;
+ esac
+ case $url in
+ '') case $urlfile in
+ $default_url)
+ if test ! -s $urlfile
+ then echo $command: url argument expected >&2; exit 1
+ fi
+ ;;
+ *) default_url=
+ ;;
+ esac
+ url=
+ if grep '^url=' $urlfile >/dev/null
+ then a=$authorize
+ p=$password
+ case $urlfile in
+ */*) ;;
+ *) urlfile=./$urlfile ;;
+ esac
+ . $urlfile
+ case $a:$p in
+ $authorize:$password)
+ default_url=
+ ;;
+ *) case $a in
+ ?*) authorize=$a ;;
+ esac
+ case $p in
+ ?*) password=$p ;;
+ esac
+ ;;
+ esac
+ else url=`cat $urlfile`
+ fi
+ ;;
+ esac
+ case $exec in
+ ?*) default_url= ;;
+ esac
+
+ # get the update list
+
+ eval `echo $url | sed 's,\(.*\)://\([^/]*\)/\(.*\),prot=\"\1\" host=\"\2\" dir=\"\3\",'`
+ get $host $dir/$op.html
+
+ # get/check the package names
+
+ case " $* " in
+ *" - "*)case $source in
+ 1) source_packages=$* ;;
+ *) source_packages= ;;
+ esac
+ case $binary in
+ 1) binary_packages=$* ;;
+ *) binary_packages= ;;
+ esac
+ package_hit=$*
+ ;;
+ " ") nl="
+"
+ case $source in
+ 1) p=
+ for f in `ls *.????-??-??.* 2>/dev/null`
+ do case $f in
+ *.????-??-??.????-??-??.*.*)
+ ;;
+ *.????-??-??.????-??-??.*)
+ p=$p$nl$f
+ ;;
+ *.????-??-??.*.*)
+ ;;
+ *.????-??-??.*)
+ p=$p$nl$f
+ ;;
+ esac
+ done
+ set '' `echo "$p" | sed 's,\..*,,' | sort -u`
+ shift
+ source_packages=$*
+ ;;
+ *) source_packages=
+ ;;
+ esac
+ case $binary in
+ 1) p=
+ for f in `ls *.????-??-??.* 2>/dev/null`
+ do case $f in
+ *.????-??-??.????-??-??.*.*)
+ p=$p$nl$f
+ ;;
+ *.????-??-??.????-??-??.*)
+ ;;
+ *.????-??-??.*.*)
+ p=$p$nl$f
+ ;;
+ *.????-??-??.*)
+ ;;
+ esac
+ done
+ set '' `echo "$p" | sed 's,\..*,,' | sort -u`
+ shift
+ binary_packages=$*
+ ;;
+ *) binary_packages=
+ ;;
+ esac
+ package_hit="$source_packages $binary_packages"
+ ;;
+ *) case $source in
+ 1) source_packages=$* ;;
+ *) source_packages= ;;
+ esac
+ case $binary in
+ 1) binary_packages=$* ;;
+ *) binary_packages= ;;
+ esac
+ package_hit=
+ ;;
+ esac
+
+ # get the latest updates
+
+ types_test=
+ types_local=
+ dir=$dir/$tgz
+ case $default_url in
+ ?*) echo "url='$url' authorize='$authorize' password='$password'" > $default_url
+ case $authorize in
+ ?*) chmod go-rwx $default_url ;;
+ esac
+ ;;
+ esac
+ echo "$got" > got.tmp
+ case $only in
+ 0) exec < got.tmp
+ covered=
+ while read name suffix type base base_size delta delta_size sync sync_size requires covers base_sum delta_sum sync_sum comment
+ do case $requires in
+ ''|-*) continue ;;
+ esac
+ IFS=:
+ set '' $requires
+ IFS=$ifs
+ case $type in
+ -) case " $source_packages " in
+ *" $name "*|*" - "*)
+ for name
+ do case " $source_packages " in
+ *" $name "*)
+ ;;
+ *) source_packages="$source_packages $name"
+ covered=$covered:$covers
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ *) case " $binary_packages " in
+ *" $name "*|*" - "*)
+ for name
+ do case " $binary_packages " in
+ *" $name "*)
+ ;;
+ *) binary_packages="$binary_packages $name"
+ covered=$covered:$covers
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $covered in
+ ?*) x=$source_packages
+ source_packages=
+ for name in $x
+ do case :$covered: in
+ *:$name:*) ;;
+ *) source_packages="$source_packages $name" ;;
+ esac
+ done
+ x=$binary_packages
+ binary_packages=
+ for name in $x
+ do case :$covered: in
+ *:$name:*) ;;
+ *) binary_packages="$binary_packages $name" ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ esac
+ checksum=
+ for i in $checksum_commands
+ do case `( $i ) < /dev/null 2> /dev/null` in
+ ${checksum_empty}|${checksum_empty}[\ \ ]*)
+ checksum=$i
+ break
+ ;;
+ esac
+ done
+ case $checksum in
+ '') echo $command: warning: '{' $checksum_commands '}' command not found -- only download sizes will be checked >&2 ;;
+ esac
+ exec < got.tmp
+ while read name suffix type base base_size delta delta_size sync sync_size requires covers base_sum delta_sum sync_sum comment
+ do case $verbose in
+ 1) case $type in
+ -) i= ;;
+ *) i=.$type ;;
+ esac
+ j="$name.$base$i.$suffix"
+ case $delta in
+ -) j="$j -" ;;
+ *) j="$j $name.$base.$delta$i.$suffix" ;;
+ esac
+ case $sync in
+ -) j="$j -" ;;
+ *) j="$j $name.$base.$sync$i.$suffix" ;;
+ esac
+ echo $command: $j $base_size:$base_sum $delta_size:$delta_sum $sync_size:$sync_sum $requires >&2
+ esac
+ case " $package_hit " in
+ *" $name "*|*" - "*)
+ ;;
+ *) package_hit="$package_hit $name"
+ ;;
+ esac
+ case $type in
+ -) case " $source_packages " in
+ *" $name "*|*" - "*)
+ if test -s $name.tim
+ then continue
+ fi
+ lcl=$name.$base.$suffix
+ if test -f $lcl
+ then case $checksum:$base_sum in
+ :*|*:-) size=`wc -c < $lcl | sed 's, ,,g'` sum=$base_sum ;;
+ *) size=$base_size sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'` ;;
+ esac
+ else size=X sum=X
+ fi
+ if test "0" != "$force" -a "X-" = "X$delta" -o "$base_size" != "$size" -o "$base_sum" != "$sum"
+ then rmt=
+ case $sync:$sync_size in
+ -*|*[-:])
+ ;;
+ *) lcl=$name.$base.$sync.$suffix
+ if test -f $lcl
+ then rmt=1
+ get $host $dir $lcl $sync_size $sync_sum
+ fi
+ ;;
+ esac
+ case $base:$base_size in
+ -*|*[-:])
+ ;;
+ *) case $rmt in
+ '') lcl=$name.$base.$suffix
+ get $host $dir $lcl $base_size $base_sum
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ case $delta:$delta_size in
+ -*|*[-:])
+ ;;
+ *) lcl=$name.$delta.$base.$suffix
+ if test -f $lcl
+ then case $checksum:$delta_sum in
+ :*|*:-) size=`wc -c < $lcl | sed 's, ,,g'` sum=$delta_sum ;;
+ *) size=$base_size sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'` ;;
+ esac
+ else size=X sum=X
+ fi
+ if test "0" != "$force" -o "$delta_size" != "$size" -o "$delta_sum" != "$sum"
+ then get $host $dir $lcl $delta_size $delta_sum
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) case " $binary_packages " in
+ *" $name "*|*" - "*)
+ if test -s $name.$type.tim
+ then continue
+ fi
+ case " $types " in
+ *" - "*);;
+ " ") case " $types_test " in
+ *" $type "*)
+ ;;
+ *) types_test="$types_test $type"
+ for i in *.????-??-??.$type.* *.????-??-??.????-??-??.$type.*
+ do if test -f $i
+ then types_local="$types_local $type"
+ fi
+ break
+ done
+ ;;
+ esac
+ case " $types_local " in
+ *" $type "*)
+ ;;
+ *) continue
+ ;;
+ esac
+ ;;
+ *) case " $types " in
+ *" $type "*)
+ ;;
+ *) continue
+ ;;
+ esac
+ ;;
+ esac
+ lcl=$name.$base.$type.$suffix
+ if test -f $lcl
+ then case $checksum:$base_sum in
+ :*|*:-) size=`wc -c < $lcl | sed 's, ,,g'` sum=$base_sum ;;
+ *) size=$base_size sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'` ;;
+ esac
+ else size=X sum=X
+ fi
+ if test "0" != "$force" -a "X-" = "X$delta" -o "$base_size" != "$size" -o "$base_sum" != "$sum"
+ then rmt=
+ case $sync:$sync_size in
+ -*|*[-:])
+ ;;
+ *) lcl=$name.$base.$sync.$type.$suffix
+ if test -f $lcl
+ then rmt=1
+ get $host $dir $lcl $sync_size $sync_sum
+ fi
+ ;;
+ esac
+ case $base:$base_size in
+ -*|*[-:])
+ ;;
+ *) case $rmt in
+ '') lcl=$name.$base.$type.$suffix
+ get $host $dir $lcl $base_size $base_sum
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ case $delta:$delta_size in
+ -*|*[-:])
+ ;;
+ *) lcl=$name.$delta.$base.$type.$suffix
+ if test -f $lcl
+ then sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'`
+ else sum=X
+ fi
+ if test -f $lcl
+ then case $checksum:$delta_sum in
+ :*|*:-) size=`wc -c < $lcl | sed 's, ,,g'` sum=$delta_sum ;;
+ *) size=$base_size sum=`$checksum < $lcl | sed -e 's,^[ ][ ]*,,' -e 's,[ ].*,,'` ;;
+ esac
+ else size=X sum=X
+ fi
+ if test "0" != "$force" -o "$delta_size" != "$size" -o "$delta_sum" != "$sum"
+ then get $host $dir $lcl $delta_size $delta_sum
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ closure=
+ for name in $source_packages $binary_packages
+ do case $name in
+ -) ;;
+ *) case " $package_hit " in
+ *" $name "*)
+ case $setup in
+ 1) case " $closure " in
+ *" $name "*)
+ ;;
+ *) closure="$closure $name"
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) echo $command: $name: unknown package >&2
+ ;;
+ esac
+ ;;
+ esac
+ done
+ exec <&-
+ rm -f got.tmp
+ case $closure in
+ ?*) echo $closure ;;
+ esac
+ ;;
+
+use) # finalize the environment
+
+ x=:..
+ for d in `( cd $PACKAGEROOT; ls src/*/Makefile src/*/Nmakefile 2>/dev/null | sed 's,/[^/]*$,,' | sort -u )`
+ do x=$x:$INSTALLROOT/$d
+ done
+ x=$x:$INSTALLROOT
+ case $CDPATH: in
+ $x:*) ;;
+ *) CDPATH=$x:$CDPATH
+ $show CDPATH=$CDPATH
+ $show export CDPATH
+ export CDPATH
+ ;;
+ esac
+ P=$PACKAGEROOT
+ $show P=$P
+ $show export P
+ export P
+ A=$INSTALLROOT
+ $show A=$A
+ $show export A
+ export A
+ case $NPROC in
+ '') hostinfo cpu
+ case $_hostinfo_ in
+ 0|1) ;;
+ *) NPROC=$_hostinfo_
+ $show NPROC=$NPROC
+ $show export NPROC
+ export NPROC
+ ;;
+ esac
+ ;;
+ esac
+ eval PACKAGE_USE=$package_use
+ export PACKAGE_USE
+
+ # run the command
+
+ case $run in
+ '') case $show in
+ ':') $exec exec $SHELL ;;
+ esac
+ ;;
+ *) $exec exec $SHELL -c "$run"
+ ;;
+ esac
+ ;;
+
+verify) cd $PACKAGEROOT
+ requirements binary $package
+ if executable ! $SUM
+ then echo "$command: $action: $SUM command required" >&2
+ exit 1
+ fi
+ case $target in
+ '') cd arch
+ set '' *
+ shift
+ target=$*
+ cd ..
+ ;;
+ esac
+ code=0
+ for a in $target
+ do case $package in
+ '') set '' arch/$a/lib/package/gen/*.sum
+ shift
+ if test -f $1
+ then for i
+ do package_verify $i || code=1
+ done
+ else echo "$command: warning: $a: no binary packages" >&2
+ fi
+ ;;
+ *) for i in $package
+ do if test -f arch/$a/lib/package/gen/$i.sum
+ then package_verify arch/$a/lib/package/gen/$i.sum || code=1
+ else echo "$command: warning: $a: no binary package for $i" >&2
+ fi
+ done
+ ;;
+ esac
+ done
+ exit $code
+ ;;
+
+write) set '' $target
+ shift
+ action=
+ list=
+ qualifier=
+ while :
+ do case $1 in
+ base|closure|delta|exp|lcl|pkg|rpm|tgz)
+ qualifier="$qualifier $1"
+ ;;
+ binary) action=$1
+ type=$HOSTTYPE
+ eval list=$PACKAGESRC/tgz/$admin_list
+ ;;
+ cyg) qualifier="$qualifier $1"
+ assign="$assign closure=1"
+ only=1
+ ;;
+ runtime|source)
+ action=$1
+ ;;
+ tst) qualifier="$qualifier tgz"
+ assign="$assign copyright=0 'PACKAGEDIR=\$(PACKAGESRC)/tst'"
+ ;;
+ nocopyright)
+ assign="$assign copyright=0"
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+ done
+ case $action in
+ '') echo "$command: binary or source operand expected" >&2
+ exit 1
+ ;;
+ esac
+ set '' "$@" $package
+ shift
+ case $only in
+ 0) set '' `order "$@"`
+ shift
+ ;;
+ esac
+ case $# in
+ 0) echo "$command: at least one package name expected" >&2
+ exit 1
+ ;;
+ esac
+ if nonmake $MAKE
+ then echo "$command: must have $MAKE to generate archives" >&2
+ exit 1
+ fi
+
+ # all work under $PACKAGEBIN
+
+ $make cd $PACKAGEBIN
+ case $list in
+ ?*) $exec rm -f $list ;;
+ esac
+
+ # go for it
+
+ for package
+ do if view - all $package.pkg || view - all lib/package/$package.pkg
+ then eval capture \$MAKE \$makeflags -X ignore \$noexec -f \$package.pkg \$qualifier \$action $assign
+ else echo "$command: $package: not a package" >&2
+ fi
+ done
+ ;;
+
+TEST) set '' $target $package
+ shift
+ case $1 in
+ binary|source)
+ action=$1
+ shift
+ ;;
+ esac
+ order "$@"
+ ;;
+
+*) echo "$command: $action: internal error" >&2
+ exit 1
+ ;;
+
+esac
diff --git a/src/cmd/INIT/probe.win32 b/src/cmd/INIT/probe.win32
new file mode 100644
index 0000000..7939fcc
--- /dev/null
+++ b/src/cmd/INIT/probe.win32
@@ -0,0 +1,283 @@
+:
+# @(#)probe.win32 (AT&T Research) 2010-01-01
+#
+# win32 specific make C probe initialization
+# wrapped cc's are easy on uwin
+#
+# 2> easy.err to avoid mysterious hang with bcc
+
+# begin preamble shared with the pp probe.ini
+
+IFS=$'\n'
+
+chmod 777 . # cl.exe setuid workaround
+
+typeset -A header version
+
+# we are probing on behalf of libpp and nmake
+# so the native preprocessor must be forced in
+# order to bootstrap libpp and nmake
+
+nativepp=-1
+export nativepp
+
+probe_header="
+stddef.h
+"
+for inc in syslimits.h winerror.h ostream bits/ctype_base.h stream.h
+do echo "#include <$inc>" > easy.c
+ if $cc -E easy.c > /dev/null 2> easy.err
+ then probe_header="$probe_header
+$inc
+"
+ fi
+done
+
+{
+for i in $probe_header
+do echo "#include <$i>"
+done
+echo '#ifdef __cplusplus'
+echo "int _Pr0b3_cplus=__cplusplus;"
+echo '#endif'
+echo '#ifdef _UWIN'
+echo "int _Pr0b3_uwin=_UWIN;"
+echo '#endif'
+echo '#ifdef __BORLANDC__'
+echo "int _Pr0b3_version_BORLAND=__BORLANDC__;"
+echo '#endif'
+echo '#ifdef __DMC__'
+echo "int _Pr0b3_version_DM=__DMC__;"
+echo '#endif'
+echo '#ifdef _MSC_VER'
+echo "int _Pr0b3_version_MS=_MSC_VER;"
+echo '#endif'
+echo '#ifdef __ICL'
+echo "int _Pr0b3_version_ICL=__ICL;"
+echo '#endif'
+echo '#ifdef __LCC__'
+echo "int _Pr0b3_version_LCC=0+__LCC__;"
+echo '#endif'
+echo '#ifdef __MINGW32__'
+echo "int _Pr0b3_version_MINGW=__MINGW32__;"
+echo '#endif'
+echo '#ifdef __INTERIX'
+echo "int _Pr0b3_version_INTERIX=__INTERIX;"
+echo '#endif'
+echo '#ifdef __WATCOMC__'
+echo "int _Pr0b3_version_WATCOM=__WATCOMC__;"
+echo '#endif'
+} > easy.c
+
+include=
+uwin=
+cplus=
+
+$cc -E easy.c 2>&1 |
+egrep -i '^(#(line)? 1 .*\.[hH]| *int +_Pr0b3_[a-zA-Z_]* *= *[0-9])' |
+sed -e 's,_Pr0b3_,,' \
+ -e 's/.*"\(.*\)".*/\1/' \
+ -e 's,^ *,,' \
+ -e 's, *$,,' \
+ -e 's, *= *,=,' \
+ -e 's,^\(.\):[\\/]*,/\1/,' \
+ -e 's,[\\/][\\/]*,/,g' \
+ -e 's,^\(/.*\)/\(.*\)$,header[\2]="\1",' \
+ -e 's, *int *\(.*\);.*,\1,' \
+ -e 's,^version_\(.*\)=,version[\1]=,' \
+ > easy.sh
+. ./easy.sh
+
+include=
+for i in $probe_header
+do d=${header[$i]}
+ if [[ $d ]]
+ then include="$include
+$d"
+ elif [[ $i == */* ]]
+ then d=${header[${i##*/}]}
+ if [[ $d == */${i%/*} ]]
+ then include="$include
+${d%/${i%/*}}"
+ fi
+ fi
+done
+
+i=$($cc -V 2> easy.err)
+if test "" != "$i" -a -d "$i/include"
+then include="$i/include
+$include"
+fi
+
+stdinclude=
+for inc in $include
+do if [[ ${inc%/*} -ef /msdev/platformsdk ]]
+ then inc=/msdev/platformsdk/${inc##*/}
+ elif [[ ${inc%/*} -ef /platformsdk ]]
+ then inc=/platformsdk/${inc##*/}
+ fi
+ for dup in $stdinclude
+ do [[ $inc -ef $dup ]] && continue 2
+ done
+ stdinclude="$stdinclude
+$inc"
+done
+
+# end preamble shared with the pp probe.ini
+
+if [[ ${version[@]} == [0-9]* && $stdinclude ]]
+then : the payoff
+ set -- $cc
+ cmd=$1
+ shift
+ set -- $(whence $cmd) "$@"
+ typ=$(package)
+ dialect="ANSI CLOSURE DYNAMIC EXPORT=DLL LIBPP -I-"
+ case ${cc##*/} in
+ *CC*) dialect="$dialect C++"
+ cplus=1
+ ;;
+ esac
+ ld=${cc%cc}ld
+ if [[ ! -x $ld ]]
+ then ld=${cc%/*}/ld
+ if [[ ! -x $ld ]]
+ then case $cc in
+ */ncc) ld=/usr/bin/nld ;;
+ *) ld=/usr/bin/ld ;;
+ esac
+ fi
+ fi
+ {
+ if $cc -v >/dev/null 2>&1
+ then v=$($cc -v 2>/dev/null)
+ if [[ $v ]]
+ then print "# ;VERSION;-v;$v;PATH;$cc"
+ fi
+ else v=
+ fi
+ cat <<!
+CC.CC = $*
+CC.NATIVE = $*
+CC.EXECTYPE = $typ
+CC.HOSTTYPE = $typ
+CC.ALTPP.FLAGS = -Yp,\$(CPP:D)
+CC.ALTPP.ENV =
+CC.AR = ar
+CC.ARFLAGS =
+CC.DEBUG = -g
+CC.DIALECT = $dialect
+CC.DLL = -D_BLD_DLL
+CC.DLLBIG = -D_BLD_DLL
+CC.DLL.DEF = -D_BLD_DLL
+CC.DLL.DIR = \$(BINDIR)
+CC.DLL.LIBRARIES =
+CC.DLL.VARIANTS =
+CC.DYNAMIC =
+CC.EXPORT.DYNAMIC =
+CC.LD = $ld
+CC.LD.DYNAMIC = -Bdynamic
+CC.LD.LAZY =
+CC.LD.NOLAZY =
+CC.LD.ORIGIN =
+CC.LD.RECORD =
+CC.LD.NORECORD =
+CC.LD.RUNPATH =
+CC.LD.STATIC = -Bstatic
+CC.LD.STRIP =
+CC.LIB.DLL = option
+CC.LIB.ALL = -Bwhole-archive
+CC.LIB.UNDEF = -Bno-whole-archive
+CC.MAKE.OPTIONS = nativepp=0
+CC.NM = nm
+CC.NMEDIT =
+CC.NMFLAGS =
+CC.OPTIMIZE = -O
+CC.PIC =
+CC.PICBIG =
+CC.READONLY =
+CC.REPOSITORY =
+CC.SHARED = -G
+CC.SHARED.LD = $ld
+CC.SHARED.REGISTRY =
+CC.SHARED.REGISTRY.PATH =
+CC.SHELLMAGIC =
+CC.SIZE = size
+CC.STATIC = -Bstatic
+!
+ inc=
+ lib=
+ if [[ ${version[LCC]} ]]
+ then lib=/lcc
+ fi
+ if [[ $stdinclude == *' '* ]]
+ then stdinclude=${stdinclude//' '/''}
+ fi
+ stdinc=
+ stdlib=
+ for inc in $stdinclude
+ do stdinc="$stdinc $inc"
+ d=${inc%/*}/lib
+ if [[ -d $d ]]
+ then stdlib="$stdlib $d"
+ fi
+ done
+ case $uwin in
+ [0-9]*) cat <<!
+CC.STDINCLUDE = /usr/include $stdinc
+CC.STDLIB = /usr/lib$lib $stdlib
+!
+ ;;
+ *) cat <<!
+CC.STDINCLUDE = $stdinc
+CC.STDLIB = $stdlib
+!
+ ;;
+ esac
+ cat <<!
+CC.STRICT =
+CC.STRIP = strip
+CC.STRIP.FLAGS =
+CC.PREFIX.ARCHIVE = lib
+CC.PREFIX.DYNAMIC =
+CC.PREFIX.SHARED =
+CC.PREFIX.SYMBOL = _
+CC.SUFFIX.ARCHIVE = .a
+CC.SUFFIX.COMMAND =
+CC.SUFFIX.DEBUG = .pdb
+CC.SUFFIX.DYNAMIC = .dll
+CC.SUFFIX.LD = .def .exp .ign .res
+CC.SUFFIX.OBJECT = .o
+CC.SUFFIX.SHARED = .lib
+CC.SUFFIX.SOURCE = .c
+CC.SUFFIX.STATIC =
+!
+ if [[ $v ]]
+ then case $v in
+ *\"*) v=$(print -r -- | sed -e 's,",\\",g' -e 's,^ ,,' -e 's,.*,"&",') ;;
+ *\'*) v=\"$v\" ;;
+ esac
+ cat <<!
+CC.VERSION = -v
+CC.VERSION.STRING = $v
+!
+ else cat <<!
+CC.VERSION =
+CC.VERSION.STRING =
+!
+ fi
+ if [[ ${version[MINGW]} || ${version[MS]} ]]
+ then cat <<!
+CC.WARN = -Wall
+!
+ else cat <<!
+CC.WARN =
+!
+ fi
+ cat <<!
+CC.PREROOT =
+CC.UNIVERSE = att
+!
+ } >&3
+ exit 0
+fi
diff --git a/src/cmd/INIT/proto.c b/src/cmd/INIT/proto.c
new file mode 100644
index 0000000..d030a1d
--- /dev/null
+++ b/src/cmd/INIT/proto.c
@@ -0,0 +1,5283 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+
+/* : : generated by proto : : */
+
+#if !defined(__PROTO__)
+# if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
+# if defined(__cplusplus)
+# define __LINKAGE__ "C"
+# else
+# define __LINKAGE__
+# endif
+# define __STDARG__
+# define __PROTO__(x) x
+# define __OTORP__(x)
+# define __PARAM__(n,o) n
+# if !defined(__STDC__) && !defined(__cplusplus)
+# if !defined(c_plusplus)
+# define const
+# endif
+# define signed
+# define void int
+# define volatile
+# define __V_ char
+# else
+# define __V_ void
+# endif
+# else
+# define __PROTO__(x) ()
+# define __OTORP__(x) x
+# define __PARAM__(n,o) o
+# define __LINKAGE__
+# define __V_ char
+# define const
+# define signed
+# define void int
+# define volatile
+# endif
+# define __MANGLE__ __LINKAGE__
+# if defined(__cplusplus) || defined(c_plusplus)
+# define __VARARG__ ...
+# else
+# define __VARARG__
+# endif
+# if defined(__STDARG__)
+# define __VA_START__(p,a) va_start(p,a)
+# else
+# define __VA_START__(p,a) va_start(p)
+# endif
+# if !defined(__INLINE__)
+# if defined(__cplusplus)
+# define __INLINE__ extern __MANGLE__ inline
+# else
+# if defined(_WIN32) && !defined(__GNUC__)
+# define __INLINE__ __inline
+# endif
+# endif
+# endif
+#endif
+#if !defined(__LINKAGE__)
+#define __LINKAGE__ /* 2004-08-11 transition */
+#endif
+#line 1 "proto.c"
+
+
+#line 151
+# ifndef __STDC__
+# ifndef creat
+# define creat _huh_creat
+# endif
+# if 1
+# ifndef access
+# define access _huh_access
+# endif
+# ifndef ctime
+# define ctime _huh_ctime
+# endif
+# ifndef mkdir
+# define mkdir _huh_mkdir
+# endif
+# endif
+# endif
+
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# if 1
+# include <stdio.h>
+# else
+# include <time.h>
+# endif
+
+# ifndef __STDC__
+# undef access
+# undef ctime
+# undef creat
+# undef mkdir
+# endif
+
+# ifndef O_RDONLY
+# define O_RDONLY 0
+# endif
+
+# ifndef S_IRUSR
+# define S_IRUSR 0400
+# endif
+# ifndef S_IWUSR
+# define S_IWUSR 0200
+# endif
+# ifndef S_IXUSR
+# define S_IXUSR 0100
+# endif
+# ifndef S_IRGRP
+# define S_IRGRP 0040
+# endif
+# ifndef S_IWGRP
+# define S_IWGRP 0020
+# endif
+# ifndef S_IXGRP
+# define S_IXGRP 0010
+# endif
+# ifndef S_IROTH
+# define S_IROTH 0004
+# endif
+# ifndef S_IWOTH
+# define S_IWOTH 0002
+# endif
+# ifndef S_IXOTH
+# define S_IXOTH 0001
+# endif
+
+# ifndef __STDC__
+# if !_WIN32 && !_WINIX
+# define remove(x) unlink(x)
+# define rename(x,y) ((link(x,y)||remove(x))?-1:0)
+# endif
+
+# if 1
+extern __MANGLE__ int access __PROTO__((const char*, int));
+extern __MANGLE__ int mkdir __PROTO__((const char*, int));
+# endif
+
+# endif
+
+# if 1
+extern __MANGLE__ int utime __PROTO__((const char*, time_t*));
+# endif
+
+
+
+
+
+
+int
+replace __PARAM__((const char* newfile, const char* oldfile, int preserve), (newfile, oldfile, preserve)) __OTORP__(const char* newfile; const char* oldfile; int preserve;){
+ struct stat st;
+ time_t ut[2];
+
+ if (stat(oldfile, &st))
+ {
+ if (preserve)
+ return -1;
+ st.st_mode = 0;
+ }
+ if (remove(oldfile) || rename(newfile, oldfile))
+ return -1;
+ if (st.st_mode &= (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))
+ chmod(oldfile, st.st_mode);
+ if (preserve)
+ {
+ ut[0] = st.st_atime;
+ ut[1] = st.st_mtime;
+ preserve = utime(oldfile, ut);
+ }
+ return preserve;
+}
+
+# undef utime
+# define utime ______utime
+
+#line 1 "../../lib/libpp/ppproto.c"
+
+#line 13
+static const char id[] = "\n@(#)$Id: proto (AT&T Research) 2012-04-14 $\000\n";
+
+#line 1 "../../lib/libpp/ppfsm.c"
+
+#line 1 "../../lib/libpp/pplib.h"
+
+#line 108
+struct ppsymbol;
+struct ppindex;
+
+typedef char* (*PPBUILTIN) __PROTO__((char*, const char*, const char*));
+typedef void (*PPCOMMENT) __PROTO__((const char*, const char*, const char*, int));
+typedef void (*PPINCREF) __PROTO__((const char*, const char*, int, int));
+typedef void (*PPLINESYNC) __PROTO__((int, const char*));
+typedef void (*PPMACREF) __PROTO__((struct ppsymbol*, const char*, int, int, unsigned long));
+typedef int (*PPOPTARG) __PROTO__((int, int, const char*));
+typedef void (*PPPRAGMA) __PROTO__((const char*, const char*, const char*, const char*, int));
+
+struct ppinstk
+{
+ char* nextchr;
+ struct ppinstk* next;
+ struct ppinstk* prev;
+ long* control;
+ char* buffer;
+ char* file;
+ char* prefix;
+ struct ppsymbol* symbol;
+
+ struct ppindex* index;
+ int buflen;
+
+ int line;
+ int vendor;
+ short fd;
+ short hide;
+ short flags;
+ char type;
+};
+
+
+
+
+
+
+
+
+
+struct pplist
+{
+ char* value;
+ struct pplist* next;
+};
+
+struct oplist
+{
+ int op;
+ char* value;
+ struct oplist* next;
+};
+
+struct pphide
+{
+ struct ppmacro* macro;
+ unsigned long flags;
+ int level;
+};
+
+struct ppmacstk
+{
+ struct ppmacstk* next;
+ struct ppmacstk* prev;
+ int line;
+ char* arg[1];
+};
+
+struct ppmember
+{
+ struct ppdirs* archive;
+ unsigned long offset;
+ unsigned long size;
+};
+
+struct counter
+{
+ int candidate;
+ int function;
+ int macro;
+ int pplex;
+ int push;
+ int terminal;
+ int token;
+};
+
+struct pptuple
+{
+ struct pptuple* nomatch;
+ struct pptuple* match;
+ char token[1];
+};
+
+struct ppfileid
+{
+ unsigned long st_dev;
+ unsigned long st_ino;
+};
+
+struct pathid
+{
+ char* path;
+ struct ppfileid id;
+};
+
+#line 1 "../../lib/libpp/pp.h"
+
+#line 206
+
+#line 217
+
+#line 329
+struct ppdirs
+{
+ char* name;
+ struct ppdirs* next;
+
+
+ unsigned char c; unsigned char index; unsigned char type; union { char* buffer; char* sp; struct ppdirs* subdir; } info; struct ppfileid id;
+
+
+};
+
+struct ppkeyword
+{
+ char* name;
+ int value;
+};
+
+struct ppmacro
+{
+ int arity;
+ char* value;
+
+
+ struct pptuple* tuple; char* formals; int size;
+
+
+};
+
+struct ppsymbol
+{
+ int hash_header;
+ unsigned long flags;
+ struct ppmacro* macro;
+ __V_* value;
+
+
+ struct pphide* hidden;
+
+
+};
+
+#line 378
+struct ppglobals
+{
+ const char* version;
+ char* lineid;
+ char* outfile;
+ char* pass;
+ char* token;
+ struct ppsymbol* symbol;
+
+
+
+ char* outb;
+ char* outbuf;
+ char* outp;
+ char* oute;
+ unsigned long offset;
+
+
+ struct ppdirs* lcldirs; struct ppdirs* stddirs; int flags; char* symtab;
+
+
+
+ struct ppcontext* context; long state; long mode; long option; long test; struct { char* sp; long flags; } filedeps; struct ppdirs* firstdir; struct ppdirs* lastdir; int hide; int column; int pending; char* firstfile; char* lastfile; char* ignore; char* probe; char* filtab; char* prdtab; char* date; char* time; char* maps; long ro_state; long ro_mode; long ro_option; long ro_op[2]; struct pathid cdir; struct pathid hostdir; char* ppdefault; struct ppindex* firstindex; struct ppindex* lastindex; struct oplist* firstop; struct oplist* lastop; struct oplist* firsttx; struct oplist* lasttx; unsigned char arg_file; unsigned char arg_mode; unsigned char arg_style; unsigned char c; unsigned char hosted; unsigned char ignoresrc; unsigned char initialized; unsigned char standalone; unsigned char spare_1;
+
+
+
+ char* checkpoint; int constack; struct ppinstk* in; char* addp; char* args; char* addbuf; char* catbuf; char* hdrbuf; char* hidebuf; char* path; char* tmpbuf; char* valbuf; char* optflags; int lastout; char* include; char* prefix; struct ppmember* member; int hidden; int hiding; int level; struct { int input; int output; } pool; struct { long ro_state; long ro_mode; long ro_option; long ro_op[2]; int on; char* symtab; } reset; int truncate; struct ppmacstk* macp; char* maxmac; char* mactop; char* toknxt; long* control; long* maxcon; struct oplist* chop; struct ppfile* insert; struct ppfile* original; struct ppdirs* found; int vendor; char* dirtab; char* strtab; PPBUILTIN builtin; PPCOMMENT comment; PPINCREF incref; PPLINESYNC linesync; PPLINESYNC olinesync; PPMACREF macref; PPOPTARG optarg; PPPRAGMA pragma; struct counter counter; char funbuf[256];
+
+
+};
+
+
+
+
+
+
+
+extern __MANGLE__ struct ppglobals pp;
+extern __MANGLE__ char _pp_ctype[];
+
+extern __MANGLE__ int ppargs __PROTO__((char**, int));
+extern __MANGLE__ void ppcpp __PROTO__((void));
+extern __MANGLE__ void ppcomment __PROTO__((char*, char*, char*, int));
+extern __MANGLE__ __V_* ppcontext __PROTO__((__V_*, int));
+extern __MANGLE__ void pperror __PROTO__((int, ...));
+extern __MANGLE__ void ppincref __PROTO__((char*, char*, int, int));
+extern __MANGLE__ void ppinput __PROTO__((char*, char*, int));
+extern __MANGLE__ int pplex __PROTO__((void));
+extern __MANGLE__ void ppline __PROTO__((int, char*));
+extern __MANGLE__ void ppmacref __PROTO__((struct ppsymbol*, char*, int, int, unsigned long));
+extern __MANGLE__ void ppop __PROTO__((int, ...));
+extern __MANGLE__ void pppragma __PROTO__((char*, char*, char*, char*, int));
+extern __MANGLE__ int ppprintf __PROTO__((char*, ...));
+extern __MANGLE__ int ppsync __PROTO__((void));
+
+#line 368 "../../lib/libpp/pplib.h"
+
+#line 1 "../../lib/libpp/ppdef.h"
+
+#line 369 "../../lib/libpp/pplib.h"
+
+#line 1 "../../lib/libpp/ppkey.h"
+
+#line 16
+
+#line 125
+extern __MANGLE__ struct ppkeyword ppkey[];
+
+#line 370 "../../lib/libpp/pplib.h"
+
+#line 683
+struct ppcontext
+{
+ struct ppdirs* lcldirs; struct ppdirs* stddirs; int flags; char* symtab;
+ struct ppcontext* context; long state; long mode; long option; long test; struct { char* sp; long flags; } filedeps; struct ppdirs* firstdir; struct ppdirs* lastdir; int hide; int column; int pending; char* firstfile; char* lastfile; char* ignore; char* probe; char* filtab; char* prdtab; char* date; char* time; char* maps; long ro_state; long ro_mode; long ro_option; long ro_op[2]; struct pathid cdir; struct pathid hostdir; char* ppdefault; struct ppindex* firstindex; struct ppindex* lastindex; struct oplist* firstop; struct oplist* lastop; struct oplist* firsttx; struct oplist* lasttx; unsigned char arg_file; unsigned char arg_mode; unsigned char arg_style; unsigned char c; unsigned char hosted; unsigned char ignoresrc; unsigned char initialized; unsigned char standalone; unsigned char spare_1;
+};
+
+struct ppfile
+{
+ int hash_header;
+ struct ppsymbol* guard;
+ struct ppfile* bound[4];
+ int flags;
+};
+
+
+
+struct ppindex
+{
+ struct ppindex* next;
+ struct ppfile* file;
+ unsigned long begin;
+ unsigned long end;
+};
+
+
+
+struct ppsymkey
+{
+ struct ppsymbol sym;
+ int lex;
+};
+
+#line 729
+# ifdef __STDC__
+
+# include <stdlib.h>
+# include <unistd.h>
+# include <time.h>
+# include <string.h>
+
+# else
+
+# define size_t int
+
+extern __MANGLE__ __V_* realloc __PROTO__((__V_*, size_t));
+extern __MANGLE__ __V_* calloc __PROTO__((size_t, size_t));
+extern __MANGLE__ char* ctime __PROTO__((time_t*));
+extern __MANGLE__ void free __PROTO__((__V_*));
+
+# ifndef O_RDONLY
+
+extern __MANGLE__ int access __PROTO__((const char*, int));
+extern __MANGLE__ int close __PROTO__((int));
+extern __MANGLE__ int creat __PROTO__((const char*, int));
+extern __MANGLE__ void exit __PROTO__((int));
+extern __MANGLE__ int link __PROTO__((const char*, const char*));
+extern __MANGLE__ int open __PROTO__((const char*, int, ...));
+extern __MANGLE__ int read __PROTO__((int, __V_*, int));
+extern __MANGLE__ time_t time __PROTO__((time_t*));
+extern __MANGLE__ int unlink __PROTO__((const char*));
+extern __MANGLE__ int write __PROTO__((int, const __V_*, int));
+
+# endif
+
+# endif
+
+#line 802
+extern __MANGLE__ void ppassert __PROTO__((int, char*, char*));
+extern __MANGLE__ void ppbuiltin __PROTO__((void));
+extern __MANGLE__ int ppcall __PROTO__((struct ppsymbol*, int));
+extern __MANGLE__ int ppcontrol __PROTO__((void));
+extern __MANGLE__ void ppdump __PROTO__((void));
+extern __MANGLE__ char* ppexpand __PROTO__((char*));
+extern __MANGLE__ long ppexpr __PROTO__((int*));
+extern __MANGLE__ void ppfsm __PROTO__((int, char*));
+extern __MANGLE__ char* ppinstr __PROTO__((struct ppinstk*));
+extern __MANGLE__ char* ppkeyname __PROTO__((int, int));
+extern __MANGLE__ char* pplexstr __PROTO__((int));
+extern __MANGLE__ void ppload __PROTO__((char*));
+extern __MANGLE__ void ppmapinclude __PROTO__((char*, char*));
+extern __MANGLE__ char* ppmodestr __PROTO__((long));
+extern __MANGLE__ int ppmultiple __PROTO__((struct ppfile*, struct ppsymbol*));
+extern __MANGLE__ void ppnest __PROTO__((void));
+extern __MANGLE__ int ppoption __PROTO__((char*));
+extern __MANGLE__ char* ppoptionstr __PROTO__((long));
+extern __MANGLE__ void pppclose __PROTO__((char*));
+extern __MANGLE__ int pppdrop __PROTO__((char*));
+extern __MANGLE__ char* pppopen __PROTO__((char*, int, char*, char*, char*, char*, int));
+extern __MANGLE__ int pppread __PROTO__((char*));
+extern __MANGLE__ int pppredargs __PROTO__((void));
+extern __MANGLE__ void pppush __PROTO__((int, char*, char*, int));
+extern __MANGLE__ struct ppsymbol* pprefmac __PROTO__((char*, int));
+extern __MANGLE__ int ppsearch __PROTO__((char*, int, int));
+extern __MANGLE__ int ppset __PROTO__((long*, long, int));
+extern __MANGLE__ char* ppstatestr __PROTO__((long));
+extern __MANGLE__ char* pptokstr __PROTO__((char*, int));
+extern __MANGLE__ void pptrace __PROTO__((int));
+
+#line 11 "../../lib/libpp/ppfsm.c"
+
+#line 1 "../../lib/libpp/ppfsm.h"
+
+#line 185
+
+#line 249
+extern __MANGLE__ short _pp_fsmtab[(0+28)+1][255+1];
+
+
+
+
+
+extern __MANGLE__ char _pp_trigraph[255+1];
+
+extern __MANGLE__ void _pp_refill __PROTO__((int));
+
+#line 12 "../../lib/libpp/ppfsm.c"
+
+
+#line 67
+struct fsminit
+{
+ int state;
+ unsigned char ch[4];
+ int nextstate;
+};
+
+static struct fsminit fsminit[] =
+{
+
+ { 0, { 023 }, ((0+28)+11), },
+ { 0, { 002 }, (0), },
+ { 0, { 001 }, (0+23), },
+ { 0, { '.' }, (0+25), },
+ { 0, { 021 }, (0+19), },
+ { 0, { 'L' }, (0+20), },
+ { 0, { 'd', 'e', 'f', 'i' }, (0+1), },
+ { 0, { 'r', 's', 't', 'v' }, (0+1), },
+ { 0, { 'w', 'N' }, (0+1), },
+ { 0, { '"', '\'' }, ((0+28)+3), },
+ { 0, { '/' }, (0+12), },
+ { 0, { '\n' }, ((0+28)+7), },
+ { 0, { ' ','\t','\f','\013' }, (0+27), },
+
+
+ { (0+1), { 023 }, ((0+28)+6), },
+ { (0+1), { 021, 001 }, (0+19), },
+ { (0+1), { 'a' }, (0+2), },
+ { (0+1), { 'e' }, (0+3), },
+ { (0+1), { 'f' }, (0+4), },
+ { (0+1), { 'h' }, (0+5), },
+ { (0+1), { 'l' }, (0+6), },
+ { (0+1), { 'n' }, (0+7), },
+ { (0+1), { 'o' }, (0+8), },
+ { (0+1), { 't' }, (0+9), },
+ { (0+1), { 'x' }, (0+10), },
+ { (0+1), { 'y' }, (0+11), },
+
+
+ { (0+2), { 023 }, (((0+28)+12)), },
+ { (0+2), { 021, 001 }, (0+19), },
+ { (0+2), { '_','s','t','a' }, (0+2), },
+ { (0+2), { 'r' }, (0+2), },
+
+
+ { (0+3), { 023 }, (((0+28)+12)), },
+ { (0+3), { 021, 001 }, (0+19), },
+ { (0+3), { 't','u','r','n' }, (0+3), },
+
+
+ { (0+4), { 023 }, (((0+28)+12)), },
+ { (0+4), { 021, 001 }, (0+19), },
+
+
+ { (0+5), { 023 }, (((0+28)+12)), },
+ { (0+5), { 021, 001 }, (0+19), },
+ { (0+5), { 'i','l','e' }, (0+5), },
+
+
+ { (0+6), { 023 }, (((0+28)+12)), },
+ { (0+6), { 021, 001 }, (0+19), },
+ { (0+6), { 's','e' }, (0+6), },
+
+
+ { (0+7), { 023 }, (((0+28)+12)), },
+ { (0+7), { 021, 001 }, (0+19), },
+ { (0+7), { 'l','i','n','e' }, (0+7), },
+
+
+ { (0+8), { 023 }, (((0+28)+12)), },
+ { (0+8), { 021, 001 }, (0+19), },
+ { (0+8), { 'r','i','d','N' }, (0+8), },
+
+
+ { (0+9), { 023 }, (((0+28)+12)), },
+ { (0+9), { 021, 001 }, (0+19), },
+ { (0+9), { 'a','t','i','c' }, (0+9), },
+
+
+ { (0+10), { 023 }, (((0+28)+12)), },
+ { (0+10), { 021, 001 }, (0+19), },
+ { (0+10), { 't','e','r','n' }, (0+10), },
+
+
+ { (0+11), { 023 }, (((0+28)+12)), },
+ { (0+11), { 021, 001 }, (0+19), },
+ { (0+11), { 'p','e','d','f' }, (0+11), },
+
+
+ { (0+12), { 023 }, ((0+28)+0), },
+ { (0+12), { '*' }, (0+13), },
+
+ { (0+12), { '/' }, (0+16), },
+
+
+
+ { (0+13), { 023 }, (0+13), },
+ { (0+13), { '\n', 002 }, ((0+28)+1), },
+ { (0+13), { '/' }, (0+15), },
+ { (0+13), { '*' }, (0+14), },
+ { (0+13), { '#', ';', ')' }, ((( (0+13))<<(7+1))|(((0+28)+8))), },
+
+
+ { (0+14), { 023 }, (0+13), },
+ { (0+14), { '\n', 002 }, ((0+28)+1), },
+ { (0+14), { '#', ';', ')' }, ((( (0+13))<<(7+1))|(((0+28)+8))), },
+ { (0+14), { '*' }, (0+14), },
+ { (0+14), { '/' }, ((0+28)+1), },
+
+
+ { (0+15), { 023 }, (0+13), },
+ { (0+15), { '*', '\n', 002 }, ((0+28)+1), },
+ { (0+15), { '/' }, (0+15), },
+
+
+ { (0+16), { 023 }, (0+16), },
+ { (0+16), { '\n', 002 }, ((0+28)+1), },
+ { (0+16), { '/' }, (0+17), },
+ { (0+16), { '*' }, (0+18), },
+
+
+ { (0+17), { 023 }, (0+16), },
+ { (0+17), { '*', '\n', 002 }, ((0+28)+1), },
+ { (0+17), { '/' }, (0+17), },
+
+
+ { (0+18), { 023 }, (0+16), },
+ { (0+18), { '\n', 002 }, ((0+28)+1), },
+ { (0+18), { '*' }, (0+18), },
+ { (0+18), { '/' }, ((0+28)+1), },
+
+
+ { (0+19), { 023 }, ((0+28)+6), },
+ { (0+19), { 021, 001 }, (0+19), },
+
+
+ { (0+25), { 023 }, ((0+28)+0), },
+ { (0+25), { '.' }, (0+26), },
+ { (0+25), { 001 }, (0+23), },
+
+
+ { (0+26), { 023 }, (((( (0401+1))-0401)<<(7+1))|( ((0+28)+14))), },
+ { (0+26), { '.' }, (((( (0401+29))-0401)<<(7+1))|( ((0+28)+13))), },
+
+
+ { (0+20), { 023 }, ((0+28)+6), },
+ { (0+20), { 021, 001 }, (0+19), },
+ { (0+20), { '"', '\'' }, ((( (0+21))<<(7+1))|(((0+28)+8))), },
+
+
+ { (0+21), { 023 }, (0+21), },
+ { (0+21), { '"', '\'' }, ((0+28)+4), },
+ { (0+21), { '\n', 002 }, ((0+28)+4), },
+ { (0+21), { '\\' }, (0+22), },
+
+
+ { (0+22), { 023 }, ((0+28)+5), },
+ { (0+22), { '\n', 002 }, ((0+28)+4), },
+
+
+ { (0+23), { 023 }, (((( (0401+1))-0401)<<(7+1))|( ((0+28)+14))), },
+ { (0+23), { 021, 001, '.' }, (0+23), },
+ { (0+23), { 'e', 'E' }, (0+24), },
+
+
+ { (0+24), { 023 }, (((( (0401+1))-0401)<<(7+1))|( ((0+28)+14))), },
+ { (0+24), { 021, 001, '.' }, (0+23), },
+ { (0+24), { '+', '-' }, (0+23), },
+
+
+ { (0+27), { 023 }, ((0+28)+15), },
+ { (0+27), { ' ', '\t' }, (0+27), },
+ { (0+27), { '\f', '\013' }, ((0+28)+10), },
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#line 528
+ { (-1), { 0 }, 0, }
+};
+
+short _pp_fsmtab[(0+28)+1][255+1];
+
+char _pp_trigraph[255+1];
+
+
+static char spl[] = { '\\', '\r', 0 };
+static char aln[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$@";
+
+
+
+
+static char* let = &aln[10];
+static char hex[] = "fedcbaFEDCBA9876543210";
+static char* dec = &hex[12];
+static char* oct = &hex[14];
+
+
+
+
+
+
+void
+ppfsm __PARAM__((int op, register char* s), (op, s)) __OTORP__(int op; register char* s;){
+ register int c;
+ register int n;
+ register int i;
+ register short* rp;
+ register struct fsminit* fp;
+
+
+
+
+
+ switch (op)
+ {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ case 4:
+ for (fp = fsminit;; fp++)
+ {
+ if ((n = fp->nextstate) >= (0+28)) n = ~n;
+ if (fp->state == (-1))
+ {
+
+
+
+
+
+
+
+
+
+
+
+
+
+ break;
+ }
+ rp = _pp_fsmtab[fp->state];
+ for (i = 0; i < sizeof(fp->ch) && (c = fp->ch[i]); i++)
+ {
+ switch (c)
+ {
+ case 023:
+ for (c = 0; c <= 255; c++)
+ rp[c] = n;
+
+
+ case 002:
+ _pp_fsmtab[(0+28)][fp->state+1] = n < 0 ? ~n : n;
+ continue;
+
+ case 021:
+ s = let;
+ break;
+
+ case 003:
+ s = hex;
+ break;
+
+ case 001:
+ s = dec;
+ break;
+
+ case 022:
+ s = oct;
+ break;
+
+ default:
+ rp[c] = n;
+ continue;
+ }
+ while (c = *s++)
+ rp[c] = n;
+ }
+ }
+
+
+
+
+
+
+ for (i = 0; i < (0+28); i++)
+ {
+ rp = _pp_fsmtab[i];
+ s = spl;
+ while (c = *s++)
+ if (c != '@' || !(( rp)>=_pp_fsmtab[(0+13)]&&( rp)<=_pp_fsmtab[(0+18)]))
+ {
+ if (rp[c] >= 0) rp[c] = ~rp[c];
+ rp[c] &= ~(1<<7);
+ }
+ rp[0] = ~((0+28)+2);
+ for (c = 0; c <= 255; c++)
+ if (rp[c] == i)
+ rp[c] = 0;
+ }
+ _pp_fsmtab[(0+28)][0] = ~((0+28)+2);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#line 707
+ break;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#line 860
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#line 18 "../../lib/libpp/ppproto.c"
+
+#line 1 "../../../include/ast/hashkey.h"
+
+#line 24
+
+
+#line 68
+extern __MANGLE__ long strkey __PROTO__((const char*));
+
+#line 20 "../../lib/libpp/ppproto.c"
+
+#line 41
+typedef struct Key_s
+{
+ const char* name;
+ size_t size;
+ int hit;
+ int val;
+} Key_t;
+
+typedef struct Proto_s
+{
+ int brace;
+ int call;
+ int fd;
+ char* file;
+ long flags;
+ long options;
+ char* package;
+ int line;
+ int test;
+
+ char* tp;
+
+ int iz;
+ char* ib;
+ char* ip;
+
+ int oz;
+ char* ob;
+ char* op;
+ char* ox;
+
+ char cc[3];
+ char pushback[4];
+
+ char variadic[256];
+
+
+
+
+} Proto_t;
+
+
+#line 171
+static const Key_t pragmas[] =
+{
+ { "prototyped",sizeof( "prototyped")-1, 0x01, 1},
+ { "noprototyped",sizeof( "noprototyped")-1, 0x01, 0},
+ { "noticed",sizeof( "noticed")-1, 0x02, 1},
+ { "nonoticed",sizeof( "nonoticed")-1, 0x02, 0},
+};
+
+static const Key_t notices[] =
+{
+ { "Copyright",sizeof( "Copyright")-1, 0x02, 1},
+ { "COPYRIGHT",sizeof( "COPYRIGHT")-1, 0x02, 1},
+ { "copyright",sizeof( "copyright")-1, 0x02, 1},
+ { "Public Domain",sizeof( "Public Domain")-1, 0x02, 0},
+ { "PUBLIC DOMAIN",sizeof( "PUBLIC DOMAIN")-1, 0x02, 0},
+};
+
+
+
+
+
+
+static char*
+number __PARAM__((register char* p, register long n), (p, n)) __OTORP__(register char* p; register long n;){
+ register long d;
+
+ for (d = 1000000; d > 1; d /= 10)
+ if (n >= d) *p++ = '0' + (n / d) % 10;
+ *p++ = '0' + n % 10;
+ return p;
+}
+
+
+
+static int errors;
+
+
+#line 224
+
+
+
+
+static int
+sstrlen __PARAM__((register const char* s), (s)) __OTORP__(register const char* s;){
+ register const char* b;
+
+ for (b = s; *s; s++);
+ return s - b;
+}
+
+
+
+
+
+static int
+sstrncmp __PARAM__((register const char* s, register const char* t, register int n), (s, t, n)) __OTORP__(register const char* s; register const char* t; register int n;){
+ register const char* e = s + n;
+
+ while (s < e)
+ {
+ if (*s != *t || !*s)
+ return *s - *t;
+ s++;
+ t++;
+ }
+ return 0;
+}
+
+
+
+
+
+static char*
+strcopy __PARAM__((register char* s, register const char* t), (s, t)) __OTORP__(register char* s; register const char* t;){
+ while (*s++ = *t++);
+ return s - 1;
+}
+
+
+
+static void
+proto_error __PARAM__((char* iob, int level, char* msg, char* arg), (iob, level, msg, arg)) __OTORP__(char* iob; int level; char* msg; char* arg;){
+ register char* p;
+ char buf[1024];
+
+ p = strcopy(buf, "proto: ");
+ if (iob)
+ {
+ register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t));
+
+ if (proto->line)
+ {
+ if (proto->file)
+ {
+ *p++ = '"';
+ p = strcopy(p, proto->file);
+ *p++ = '"';
+ *p++ = ',';
+ *p++ = ' ';
+ }
+ p = strcopy(p, "line ");
+ p = number(p, proto->line);
+ }
+ else if (proto->file)
+ p = strcopy(p, proto->file);
+ }
+ else
+ {
+ p = strcopy(p, msg);
+ msg = arg;
+ arg = 0;
+ }
+ if (*(p - 1) != ' ')
+ {
+ *p++ = ':';
+ *p++ = ' ';
+ }
+ if (level == 1)
+ p = strcopy(p, "warning: ");
+ p = strcopy(p, msg);
+ if (arg)
+ {
+ *p++ = ' ';
+ p = strcopy(p, arg);
+ }
+ *p++ = '\n';
+ write(2, buf, p - buf);
+ if (level >= 3)
+ exit(level - 2);
+ if (level >= 2)
+ errors++;
+}
+
+
+
+
+
+static char*
+memcopy __PARAM__((register char* s, register char* t, int n), (s, t, n)) __OTORP__(register char* s; register char* t; int n;){
+ register char* e = t + n;
+
+ while (t < e) *s++ = *t++;
+ return s;
+}
+
+#line 1 "../../lib/libast/port/astlicense.c"
+
+
+
+#line 84
+typedef struct Buffer_s
+{
+ char* buf;
+ char* nxt;
+ char* end;
+ int siz;
+} Buffer_t;
+
+typedef struct Item_s
+{
+ char* data;
+ int size;
+ int quote;
+} Item_t;
+
+typedef struct Id_s
+{
+ Item_t name;
+ Item_t value;
+} Id_t;
+
+
+
+
+
+
+
+static const Item_t key[] =
+{
+ { "author",sizeof( "author")-1,0},
+ { "class",sizeof( "class")-1,0},
+ { "company",sizeof( "company")-1,0},
+ { "component",sizeof( "component")-1,0},
+ { "contributor",sizeof( "contributor")-1,0},
+ { "corporation",sizeof( "corporation")-1,0},
+ { "domain",sizeof( "domain")-1,0},
+ { "id",sizeof( "id")-1,0},
+ { "incorporation",sizeof( "incorporation")-1,0},
+ { "license",sizeof( "license")-1,0},
+ { "location",sizeof( "location")-1,0},
+ { "name",sizeof( "name")-1,0},
+ { "notice",sizeof( "notice")-1,0},
+ { "organization",sizeof( "organization")-1,0},
+ { "package",sizeof( "package")-1,0},
+ { "parent",sizeof( "parent")-1,0},
+ { "query",sizeof( "query")-1,0},
+ { "since",sizeof( "since")-1,0},
+ { "source",sizeof( "source")-1,0},
+ { "start",sizeof( "start")-1,0},
+ { "type",sizeof( "type")-1,0},
+ { "url",sizeof( "url")-1,0},
+ { "urlmd5",sizeof( "urlmd5")-1,0},
+ { "version",sizeof( "version")-1,0},
+ {0}
+};
+
+
+
+
+
+static const Item_t lic[] =
+{
+ { "none",sizeof( "none")-1, 0},
+ { "inline",sizeof( "inline")-1, 12},
+ { "test",sizeof( "test")-1, 2},
+ { "verbose",sizeof( "verbose")-1, 3},
+ { "usage",sizeof( "usage")-1, 4},
+ { "open",sizeof( "open")-1, 5},
+ { "cpl",sizeof( "cpl")-1, 5},
+ { "epl",sizeof( "epl")-1, 5},
+ { "bsd",sizeof( "bsd")-1, 5},
+ { "zlib",sizeof( "zlib")-1, 5},
+ { "mit",sizeof( "mit")-1, 5},
+ { "gpl",sizeof( "gpl")-1, 11},
+ { "special",sizeof( "special")-1, 12},
+ { "nonexclusive",sizeof( "nonexclusive")-1, 12},
+ { "noncommercial",sizeof( "noncommercial")-1, 12},
+ { "proprietary",sizeof( "proprietary")-1, 15},
+ {0}
+};
+
+typedef struct Notice_s
+{
+ int test;
+ int type;
+ int verbose;
+ int ids;
+ Item_t item[(sizeof(key)/sizeof(key[0])-1)];
+ Id_t id[64];
+ char cc[3];
+} Notice_t;
+
+
+
+
+
+static int
+lookup __PARAM__((register const Item_t* item, const char* name, int size), (item, name, size)) __OTORP__(register const Item_t* item; const char* name; int size;){
+ register int c;
+ register int i;
+
+ c = name[0];
+ for (i = 0; item[i].data; i++)
+ if (c == item[i].data[0] && size == item[i].size && !sstrncmp( name, item[i].data, size))
+ return i;
+ return -1;
+}
+
+
+
+
+
+
+static void
+copy __PARAM__((register Buffer_t* b, register char* s, int n), (b, s, n)) __OTORP__(register Buffer_t* b; register char* s; int n;){
+ if (n < 0)
+ n = sstrlen( s);
+ while (n--)
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( *s++)):(( *s++),(-1)));
+}
+
+
+#line 217
+static void
+comment __PARAM__((Notice_t* notice, register Buffer_t* b, register char* s, register int n, int u), (notice, b, s, n, u)) __OTORP__(Notice_t* notice; register Buffer_t* b; register char* s; register int n; int u;){
+ register int i;
+ register int m;
+ register int x;
+ int cc;
+
+ cc = notice->cc[1];
+ if (!s)
+ {
+ if (n)
+ {
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( notice->cc[n > 0 ? 0 : 1])):(( notice->cc[n > 0 ? 0 : 1]),(-1)));
+ for (i = 0; i < 70; i++)
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( cc)):(( cc),(-1)));
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( notice->cc[n > 0 ? 1 : 2])):(( notice->cc[n > 0 ? 1 : 2]),(-1)));
+ }
+ else
+ s = "";
+ }
+ if (s)
+ {
+ if (n > 70)
+ n = 70;
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( cc)):(( cc),(-1)));
+ m = (u < 0) ? 1 : (70 - n) / 2;
+ if ((x = 70 - m - n) < 0)
+ n--;
+ while (m-- > 0)
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( ' ')):(( ' '),(-1)));
+ while (n-- > 0)
+ {
+ i = *s++;
+ if (u > 0 && i >= 'a' && i <= 'z')
+ i = i - 'a' + 'A';
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( i)):(( i),(-1)));
+ }
+ while (x-- > 0)
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( ' ')):(( ' '),(-1)));
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( cc)):(( cc),(-1)));
+ }
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( '\n')):(( '\n'),(-1)));
+}
+
+
+
+
+
+static void
+expand __PARAM__((Notice_t* notice, register Buffer_t* b, const Item_t* item), (notice, b, item)) __OTORP__(Notice_t* notice; register Buffer_t* b; const Item_t* item;){
+ register char* t;
+ register char* e;
+ register int q;
+ register char* x;
+ register char* z;
+ register int c;
+ int m;
+ int i;
+ int k;
+
+ if (t = item->data)
+ {
+ q = item->quote;
+ e = t + item->size;
+ i = 0;
+ while (t < e)
+ {
+ if (*t == '$' && t < (e + 2) && *(t + 1) == '{')
+ {
+ k = m = 0;
+ x = t += 2;
+ while (t < e && (c = *t++) != '}')
+ if (c == '.')
+ x = t;
+ else if (c == '-')
+ {
+ k = 1;
+ break;
+ }
+ else if (c == '/')
+ {
+ m = 1;
+ break;
+ }
+ if ((c = lookup(key, x, t - x - 1)) >= 0 && (x = notice->item[c].data))
+ {
+ z = x + notice->item[c].size;
+ while (x < z)
+ {
+ c = *x++;
+ if (!m || c >= '0' && c <= '9')
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( c)):(( c),(-1)));
+ }
+ }
+ else if (k)
+ {
+ k = 0;
+ i++;
+ }
+ if (k || m)
+ {
+ k = 1;
+ while (t < e)
+ if ((c = *t++) == '{')
+ k++;
+ else if (c == '}' && !--k)
+ break;
+ }
+ }
+ else if (q > 0 && *t == '\\' && (*(t + 1) == q || *(t + 1) == '\\'))
+ t++;
+ else if (*t == '}' && i)
+ {
+ t++;
+ i--;
+ }
+ else
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( *t++)):(( *t++),(-1)));
+ }
+ }
+}
+
+
+
+
+
+static void
+copyright __PARAM__((Notice_t* notice, register Buffer_t* b), (notice, b)) __OTORP__(Notice_t* notice; register Buffer_t* b;){
+ register char* x;
+ register char* t;
+ time_t clock;
+
+ copy(b, "Copyright (c) ", -1);
+ if (notice->test)
+ clock = (time_t)1000212300;
+ else if (!(t = notice->item[18].data))
+ {
+ time(&clock);
+ t = ctime(&clock) + 20;
+ }
+ if ((x = notice->item[19].data) && sstrncmp( t, x, 4) < 0)
+ t = x;
+ if ((x = notice->item[17].data) && sstrncmp( x, t, 4) < 0)
+ {
+ expand(notice, b, &notice->item[17]);
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( '-')):(( '-'),(-1)));
+ }
+ copy(b, t, 4);
+ if (notice->item[15].data)
+ {
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( ' ')):(( ' '),(-1)));
+ expand(notice, b, &notice->item[15]);
+ }
+ if (notice->item[5].data)
+ {
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( ' ')):(( ' '),(-1)));
+ expand(notice, b, &notice->item[5]);
+ if (notice->item[8].data)
+ {
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( ' ')):(( ' '),(-1)));
+ expand(notice, b, &notice->item[8]);
+ }
+ }
+ else if (notice->item[2].data)
+ {
+ ((( b)->nxt<( b)->end)?(*( b)->nxt++=( ' ')):(( ' '),(-1)));
+ expand(notice, b, &notice->item[2]);
+ }
+}
+
+typedef struct Stack_s
+{
+ char* info;
+ char* file;
+ int line;
+ int size;
+} Stack_t;
+
+static int
+push __PARAM__((Stack_t* sp, char* file, char* parent, char* info, int size, Buffer_t* buf), (sp, file, parent, info, size, buf)) __OTORP__(Stack_t* sp; char* file; char* parent; char* info; int size; Buffer_t* buf;){
+ char* s;
+ char* t;
+ int i;
+ int n;
+ char path[1024];
+
+ if (size <= 8)
+ {
+ copy(buf, file, -1);
+ copy(buf, ": no space", -1);
+ ((( buf)->nxt<( buf)->end)?(*( buf)->nxt++=( 0)):(( 0),(-1)));
+ return -1;
+ }
+ if (*file != '/' && parent && (s = strrchr(parent, '/')))
+ {
+ n = s - parent + 1;
+ if ((sstrlen( file) + n + 1) <= sizeof(path))
+ {
+ memcopy( path, parent, n);
+ strcopy( path + n, file);
+ file = path;
+ }
+ }
+ if ((i = open(file, O_RDONLY)) < 0)
+ {
+
+ if (file == path)
+ for (s = path; *s; s++)
+ if (s[0] == '/' && s[1] == 'a' && s[2] == 'r' && s[3] == 'c' && s[4] == 'h' && s[5] == '/')
+ {
+ t = s;
+ for (s += 6; *s && *s != '/'; s++);
+ while (*t++ = *s++);
+ i = open(file, O_RDONLY);
+ }
+ if (i < 0)
+ {
+ copy(buf, file, -1);
+ copy(buf, ": cannot open", -1);
+ ((( buf)->nxt<( buf)->end)?(*( buf)->nxt++=( 0)):(( 0),(-1)));
+ return -1;
+ }
+ }
+ n = read(i, info, size - 1);
+ close(i);
+ if (n < 0)
+ {
+ copy(buf, file, -1);
+ copy(buf, ": cannot read", -1);
+ ((( buf)->nxt<( buf)->end)?(*( buf)->nxt++=( 0)):(( 0),(-1)));
+ return -1;
+ }
+ info[n++] = 0;
+ sp->file = file;
+ sp->info = info;
+ sp->line = 0;
+ sp->size = n;
+ return 0;
+}
+
+
+
+
+
+
+
+int
+astlicense __PARAM__((char* p, int size, char* file, char* options, int cc1, int cc2, int cc3), (p, size, file, options, cc1, cc2, cc3)) __OTORP__(char* p; int size; char* file; char* options; int cc1; int cc2; int cc3;){
+ register char* s;
+ register char* v;
+ register char* x;
+ register int c;
+ int i;
+ int h;
+ int k;
+ int n;
+ int q;
+ int contributor;
+ int first;
+ int level;
+ int quote;
+ char* data;
+ char tmpbuf[(70+4)];
+ char info[8 * 1024];
+ Stack_t input[4];
+ Notice_t notice;
+ Item_t item;
+ Buffer_t buf;
+ Buffer_t tmp;
+
+ buf.end = (buf.buf = buf.nxt = p) + size;
+ tmp.end = (tmp.buf = tmp.nxt = tmpbuf) + sizeof(tmpbuf);
+ level = 0;
+ data = info;
+ level = -1;
+ if (options)
+ {
+ level++;
+ input[level].file = "<options>";
+ input[level].info = options;
+ input[level].line = 0;
+ }
+ if (file && *file)
+ {
+ if (push(&input[++level], file, 0, data, &info[sizeof(info)] - data, &buf))
+ return -1;
+ data += input[level].size;
+ }
+ if (level < 0)
+ return 0;
+ s = input[level].info;
+ notice.test = 0;
+ notice.type = 0;
+ notice.verbose = 0;
+ notice.ids = 0;
+ notice.cc[0] = cc1;
+ notice.cc[1] = cc2;
+ notice.cc[2] = cc3;
+ for (i = 0; i < (sizeof(key)/sizeof(key[0])-1); i++)
+ notice.item[i].data = 0;
+ notice.item[20] = notice.item[1] = lic[notice.type];
+ notice.item[20].quote = notice.item[1].quote = 0;
+ contributor = i = k = 0;
+ for (;;)
+ {
+ first = 1;
+ while (c = *s)
+ {
+ while (c == ' ' || c == '\t' || c == '\n' && ++input[level].line || c == '\r' || c == ',' || c == ';' || c == ')')
+ c = *++s;
+ if (!c)
+ break;
+ if (c == '#')
+ {
+ while (*++s && *s != '\n');
+ if (*s)
+ s++;
+ input[level].line++;
+ continue;
+ }
+ if (c == '.')
+ {
+ while ((c = *++s) && (c == ' ' || c == '\t'));
+ file = s;
+ while (c && c != ' ' && c != '\t' && c != '\r' && c != '\n')
+ c = *++s;
+ *s = 0;
+ while (c && c != '\n')
+ c = *++s;
+ if (*file)
+ {
+ input[level].info = s + (c != 0);
+ if (++level >= (sizeof(input) / sizeof(input[0])) || push(&input[level], file, input[level-1].file, data, &info[sizeof(info)] - data, &buf))
+ return -1;
+ data += input[level].size;
+ s = input[level].info;
+ }
+ continue;
+ }
+ if (c == '\n')
+ {
+ s++;
+ input[level].line++;
+ continue;
+ }
+ if (c == '[')
+ c = *++s;
+ x = s;
+ n = 0;
+ while (c && c != '+' && c != '=' && c != ']' && c != ')' && c != ',' && c != ' ' && c != '\t' && c != '\n' && c != '\r')
+ c = *++s;
+ n = s - x;
+ h = lookup(key, x, n);
+ if (c == '+' || c == ']')
+ c = *++s;
+ quote = 0;
+ if (c == '=' || first)
+ {
+ if (c == '=')
+ {
+ q = ((c = *++s) == '"' || c == '\'') ? *s++ : 0;
+ if (c == '(')
+ {
+ s++;
+ if (h == 9)
+ contributor = 0;
+ else if (h == 4)
+ contributor = 1;
+ else
+ {
+ q = 1;
+ i = 0;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ s--;
+ break;
+ case '(':
+ if (!i)
+ q++;
+ continue;
+ case ')':
+ if (!i && !--q)
+ break;
+ continue;
+ case '"':
+ case '\'':
+ if (!i)
+ i = *(s - 1);
+ else if (i == *(s - 1))
+ i = 0;
+ continue;
+ case '\\':
+ if (*s == i && i == '"')
+ i++;
+ continue;
+ case '\n':
+ input[level].line++;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ }
+ continue;
+ }
+ v = s;
+ while ((c = *s) && (q == '"' && (c == '\\' && (*(s + 1) == '"' || *(s + 1) == '\\') && s++ && (quote = q)) || q && c != q || !q && c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != ',' && c != ';'))
+ {
+ if (c == '\n')
+ input[level].line++;
+ s++;
+ }
+ }
+ else
+ {
+ h = 20;
+ v = x;
+ }
+ if (c == '\n')
+ input[level].line++;
+ if (contributor)
+ {
+ for (i = 0; i < notice.ids; i++)
+ if (n == notice.id[i].name.size && !sstrncmp( x, notice.id[i].name.data, n))
+ break;
+ if (i < 64)
+ {
+ notice.id[i].name.data = x;
+ notice.id[i].name.size = n;
+ notice.id[i].name.quote = 0;
+ notice.id[i].value.data = v;
+ notice.id[i].value.size = s - v;
+ notice.id[i].value.quote = quote;
+ if (notice.ids <= i)
+ notice.ids = i + 1;
+ }
+ }
+ else if (h == 16)
+ {
+ if ((s - v) == 3 && v[0] == 'a' && v[1] == 'l' && v[2] == 'l')
+ {
+ for (i = 0; i < (sizeof(key)/sizeof(key[0])-1); i++)
+ if (notice.item[i].size)
+ {
+ expand(&notice, &buf, &key[i]);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( '=')):(( '='),(-1)));
+ for (h = 0;; h++)
+ if (h >= notice.item[i].size)
+ {
+ h = 0;
+ break;
+ }
+ else if (notice.item[i].data[h] == ' ' || notice.item[i].data[h] == '\t')
+ break;
+ if (h)
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( '\'')):(( '\''),(-1)));
+ expand(&notice, &buf, &notice.item[i]);
+ if (h)
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( '\'')):(( '\''),(-1)));
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( '\n')):(( '\n'),(-1)));
+ }
+ }
+ else
+ {
+ if ((h = lookup(key, v, s - v)) < 0)
+ {
+ item.data = v;
+ item.size = s - v;
+ item.quote = 0;
+ expand(&notice, &buf, &item);
+ }
+ else
+ expand(&notice, &buf, &notice.item[h]);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( '\n')):(( '\n'),(-1)));
+ }
+ return (*(( &buf)->nxt>=( &buf)->end?(( &buf)->nxt=( &buf)->end-1):( &buf)->nxt)=0,( &buf)->nxt-( &buf)->buf);
+ }
+ else
+ {
+ if (h == 20)
+ switch (c = lookup(lic, v, s - v))
+ {
+ case 0:
+ return 0;
+ case 2:
+ notice.test = 1;
+ h = -1;
+ break;
+ case 3:
+ notice.verbose = 1;
+ h = -1;
+ break;
+ case 4:
+ notice.type = c;
+ h = -1;
+ break;
+ case -1:
+ c = 12;
+
+ default:
+ notice.type = c;
+ notice.item[1].data = lic[lic[c].quote].data;
+ notice.item[1].size = lic[lic[c].quote].size;
+ if (notice.item[20].data != lic[0].data)
+ h = -1;
+ break;
+ }
+ if (h >= 0)
+ {
+ notice.item[h].data = (notice.item[h].size = s - v) ? v : (char*)0;
+ notice.item[h].quote = quote;
+ k = 1;
+ }
+ }
+ }
+ else
+ {
+ if (input[level].file)
+ {
+ copy(&buf, "\"", -1);
+ copy(&buf, input[level].file, -1);
+ copy(&buf, "\", line ", -1);
+ x = &tmpbuf[sizeof(tmpbuf)];
+ *--x = 0;
+ n = ++input[level].line;
+ do *--x = ("0123456789")[n % 10]; while (n /= 10);
+ copy(&buf, x, -1);
+ copy(&buf, ": ", -1);
+ }
+ copy(&buf, "option error: assignment expected", -1);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( 0)):(( 0),(-1)));
+ return -1;
+ }
+ if (*s)
+ s++;
+ first = 0;
+ }
+ if (!level--)
+ break;
+ s = input[level].info;
+ }
+ if (!k)
+ return 0;
+ if (notice.type == 1 && (!notice.verbose || !notice.item[12].data))
+ return 0;
+ if (notice.type != 4)
+ {
+ if (!notice.type)
+ notice.type = 12;
+ comment(&notice, &buf, ((char*)0), 1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ if (notice.item[14].data)
+ {
+ copy(&tmp, "This software is part of the ", -1);
+ expand(&notice, &tmp, &notice.item[14]);
+ copy(&tmp, " package", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ if (notice.type >= 5)
+ {
+ copyright(&notice, &tmp);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.type >= 12)
+ comment( &notice, &buf, "All Rights Reserved",sizeof( "All Rights Reserved")-1, 0);
+ }
+ if (notice.type == 6 || notice.type == 7)
+ {
+ copy(&tmp, notice.item[14].data ? "and": "This software", -1);
+ copy(&tmp, " is licensed under the", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.type == 7)
+ copy(&tmp, "Eclipse Public License", -1);
+ else
+ copy(&tmp, "Common Public License", -1);
+ if (notice.item[23].data)
+ {
+ copy(&tmp, ", Version ", -1);
+ expand(&notice, &tmp, &notice.item[23]);
+ }
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[5].data || notice.item[2].data)
+ {
+ copy(&tmp, "by ", -1);
+ if (notice.item[15].data)
+ {
+ expand(&notice, &tmp, &notice.item[15]);
+ copy(&tmp, " ", -1);
+ }
+ if (notice.item[5].data)
+ {
+ expand(&notice, &tmp, &notice.item[5]);
+ if (notice.item[8].data)
+ {
+ copy(&tmp, " ", -1);
+ expand(&notice, &tmp, &notice.item[8]);
+ }
+ }
+ else if (notice.item[2].data)
+ expand(&notice, &tmp, &notice.item[2]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "A copy of the License is available at",sizeof( "A copy of the License is available at")-1, 0);
+ if (notice.item[21].data)
+ {
+ expand(&notice, &tmp, &notice.item[21]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[22].data)
+ {
+ copy(&tmp, "(with md5 checksum ", -1);
+ expand(&notice, &tmp, &notice.item[22]);
+ copy(&tmp, ")", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ }
+ else if (notice.type == 7)
+ comment( &notice, &buf, "http://www.eclipse.org/org/documents/epl-v10.html",sizeof( "http://www.eclipse.org/org/documents/epl-v10.html")-1, 0);
+ else
+ comment( &notice, &buf, "http://www.opensource.org/licenses/cpl",sizeof( "http://www.opensource.org/licenses/cpl")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 5)
+ {
+ copy(&tmp, notice.item[14].data ? "and it": "This software", -1);
+ copy(&tmp, " may only be used by you under license from", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[i = 5].data)
+ {
+ if (notice.item[15].data)
+ {
+ expand(&notice, &tmp, &notice.item[i = 15]);
+ copy(&tmp, " ", -1);
+ }
+ expand(&notice, &tmp, &notice.item[5]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ else if (notice.item[i = 2].data)
+ {
+ if (notice.item[15].data)
+ {
+ expand(&notice, &tmp, &notice.item[i = 15]);
+ copy(&tmp, " ", -1);
+ }
+ expand(&notice, &tmp, &notice.item[2]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ else
+ i = -1;
+ if (notice.item[21].data)
+ {
+ comment( &notice, &buf, "A copy of the Source Code Agreement is available",sizeof( "A copy of the Source Code Agreement is available")-1, 0);
+ copy(&tmp, "at the ", -1);
+ if (i >= 0)
+ expand(&notice, &tmp, &notice.item[i]);
+ copy(&tmp, " Internet web site URL", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ expand(&notice, &tmp, &notice.item[21]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[22].data)
+ {
+ copy(&tmp, "(with an md5 checksum of ", -1);
+ expand(&notice, &tmp, &notice.item[22]);
+ copy(&tmp, ")", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ comment( &notice, &buf, "If you have copied or used this software without agreeing",sizeof( "If you have copied or used this software without agreeing")-1, 0);
+ comment( &notice, &buf, "to the terms of the license you are infringing on",sizeof( "to the terms of the license you are infringing on")-1, 0);
+ comment( &notice, &buf, "the license and copyright and are violating",sizeof( "the license and copyright and are violating")-1, 0);
+ if (i >= 0)
+ expand(&notice, &tmp, &notice.item[i]);
+ copy(&tmp, "'s", -1);
+ if (n >= (70-32))
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ else
+ ((( &tmp)->nxt<( &tmp)->end)?(*( &tmp)->nxt++=( ' ')):(( ' '),(-1)));
+ copy(&tmp, "intellectual property rights.", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 11)
+ {
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "This is free software; you can redistribute it and/or",sizeof( "This is free software; you can redistribute it and/or")-1, 0);
+ comment( &notice, &buf, "modify it under the terms of the GNU General Public License",sizeof( "modify it under the terms of the GNU General Public License")-1, 0);
+ comment( &notice, &buf, "as published by the Free Software Foundation;",sizeof( "as published by the Free Software Foundation;")-1, 0);
+ comment( &notice, &buf, "either version 2, or (at your option) any later version.",sizeof( "either version 2, or (at your option) any later version.")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "This software is distributed in the hope that it",sizeof( "This software is distributed in the hope that it")-1, 0);
+ comment( &notice, &buf, "will be useful, but WITHOUT ANY WARRANTY;",sizeof( "will be useful, but WITHOUT ANY WARRANTY;")-1, 0);
+ comment( &notice, &buf, "without even the implied warranty of MERCHANTABILITY",sizeof( "without even the implied warranty of MERCHANTABILITY")-1, 0);
+ comment( &notice, &buf, "or FITNESS FOR A PARTICULAR PURPOSE.",sizeof( "or FITNESS FOR A PARTICULAR PURPOSE.")-1, 0);
+ comment( &notice, &buf, "See the GNU General Public License for more details.",sizeof( "See the GNU General Public License for more details.")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "You should have received a copy of the",sizeof( "You should have received a copy of the")-1, 0);
+ comment( &notice, &buf, "GNU General Public License",sizeof( "GNU General Public License")-1, 0);
+ comment( &notice, &buf, "along with this software (see the file COPYING.)",sizeof( "along with this software (see the file COPYING.)")-1, 0);
+ comment( &notice, &buf, "If not, a copy is available at",sizeof( "If not, a copy is available at")-1, 0);
+ comment( &notice, &buf, "http://www.gnu.org/copyleft/gpl.html",sizeof( "http://www.gnu.org/copyleft/gpl.html")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 8)
+ {
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "Redistribution and use in source and binary forms, with or",sizeof( "Redistribution and use in source and binary forms, with or")-1, -1);
+ comment( &notice, &buf, "without modification, are permitted provided that the following",sizeof( "without modification, are permitted provided that the following")-1, -1);
+ comment( &notice, &buf, "conditions are met:",sizeof( "conditions are met:")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, " 1. Redistributions of source code must retain the above",sizeof( " 1. Redistributions of source code must retain the above")-1, -1);
+ comment( &notice, &buf, " copyright notice, this list of conditions and the",sizeof( " copyright notice, this list of conditions and the")-1, -1);
+ comment( &notice, &buf, " following disclaimer.",sizeof( " following disclaimer.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, " 2. Redistributions in binary form must reproduce the above",sizeof( " 2. Redistributions in binary form must reproduce the above")-1, -1);
+ comment( &notice, &buf, " copyright notice, this list of conditions and the",sizeof( " copyright notice, this list of conditions and the")-1, -1);
+ comment( &notice, &buf, " following disclaimer in the documentation and/or other",sizeof( " following disclaimer in the documentation and/or other")-1, -1);
+ comment( &notice, &buf, " materials provided with the distribution.",sizeof( " materials provided with the distribution.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ copy(&tmp, " 3. Neither the name of ", -1);
+ if (notice.item[i = 15].data || notice.item[i = 5].data || notice.item[i = 2].data)
+ expand(&notice, &tmp, &notice.item[i]);
+ else
+ copy(&tmp, "the copyright holder", -1);
+ copy(&tmp, " nor the", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), -1);
+ comment( &notice, &buf, " names of its contributors may be used to endorse or",sizeof( " names of its contributors may be used to endorse or")-1, -1);
+ comment( &notice, &buf, " promote products derived from this software without",sizeof( " promote products derived from this software without")-1, -1);
+ comment( &notice, &buf, " specific prior written permission.",sizeof( " specific prior written permission.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND",sizeof( "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND")-1, -1);
+ comment( &notice, &buf, "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,",sizeof( "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,")-1, -1);
+ comment( &notice, &buf, "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF",sizeof( "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF")-1, -1);
+ comment( &notice, &buf, "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE",sizeof( "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE")-1, -1);
+ comment( &notice, &buf, "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS",sizeof( "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS")-1, -1);
+ comment( &notice, &buf, "BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,",sizeof( "BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,")-1, -1);
+ comment( &notice, &buf, "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED",sizeof( "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED")-1, -1);
+ comment( &notice, &buf, "TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,",sizeof( "TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,")-1, -1);
+ comment( &notice, &buf, "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON",sizeof( "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON")-1, -1);
+ comment( &notice, &buf, "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,",sizeof( "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,")-1, -1);
+ comment( &notice, &buf, "OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY",sizeof( "OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY")-1, -1);
+ comment( &notice, &buf, "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE",sizeof( "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE")-1, -1);
+ comment( &notice, &buf, "POSSIBILITY OF SUCH DAMAGE.",sizeof( "POSSIBILITY OF SUCH DAMAGE.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 9)
+ {
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "This software is provided 'as-is', without any express or implied",sizeof( "This software is provided 'as-is', without any express or implied")-1, -1);
+ comment( &notice, &buf, "warranty. In no event will the authors be held liable for any",sizeof( "warranty. In no event will the authors be held liable for any")-1, -1);
+ comment( &notice, &buf, "damages arising from the use of this software.",sizeof( "damages arising from the use of this software.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "Permission is granted to anyone to use this software for any",sizeof( "Permission is granted to anyone to use this software for any")-1, -1);
+ comment( &notice, &buf, "purpose, including commercial applications, and to alter it and",sizeof( "purpose, including commercial applications, and to alter it and")-1, -1);
+ comment( &notice, &buf, "redistribute it freely, subject to the following restrictions:",sizeof( "redistribute it freely, subject to the following restrictions:")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, " 1. The origin of this software must not be misrepresented;",sizeof( " 1. The origin of this software must not be misrepresented;")-1, -1);
+ comment( &notice, &buf, " you must not claim that you wrote the original software. If",sizeof( " you must not claim that you wrote the original software. If")-1, -1);
+ comment( &notice, &buf, " you use this software in a product, an acknowledgment in the",sizeof( " you use this software in a product, an acknowledgment in the")-1, -1);
+ comment( &notice, &buf, " product documentation would be appreciated but is not",sizeof( " product documentation would be appreciated but is not")-1, -1);
+ comment( &notice, &buf, " required.",sizeof( " required.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, " 2. Altered source versions must be plainly marked as such,",sizeof( " 2. Altered source versions must be plainly marked as such,")-1, -1);
+ comment( &notice, &buf, " and must not be misrepresented as being the original",sizeof( " and must not be misrepresented as being the original")-1, -1);
+ comment( &notice, &buf, " software.",sizeof( " software.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, " 3. This notice may not be removed or altered from any source",sizeof( " 3. This notice may not be removed or altered from any source")-1, -1);
+ comment( &notice, &buf, " distribution.",sizeof( " distribution.")-1, -1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 10)
+ {
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "Permission is hereby granted, free of charge, to any person",sizeof( "Permission is hereby granted, free of charge, to any person")-1, 0);
+ comment( &notice, &buf, "obtaining a copy of this software and associated",sizeof( "obtaining a copy of this software and associated")-1, 0);
+ comment( &notice, &buf, "documentation files (the \"Software\"), to deal in the",sizeof( "documentation files (the \"Software\"), to deal in the")-1, 0);
+ comment( &notice, &buf, "Software without restriction, including without limitation",sizeof( "Software without restriction, including without limitation")-1, 0);
+ comment( &notice, &buf, "the rights to use, copy, modify, merge, publish, distribute,",sizeof( "the rights to use, copy, modify, merge, publish, distribute,")-1, 0);
+ comment( &notice, &buf, "sublicense, and/or sell copies of the Software, and to",sizeof( "sublicense, and/or sell copies of the Software, and to")-1, 0);
+ comment( &notice, &buf, "permit persons to whom the Software is furnished to do so,",sizeof( "permit persons to whom the Software is furnished to do so,")-1, 0);
+ comment( &notice, &buf, "subject to the following conditions:",sizeof( "subject to the following conditions:")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "The above copyright notice and this permission notice shall",sizeof( "The above copyright notice and this permission notice shall")-1, 0);
+ comment( &notice, &buf, "be included in all copies or substantial portions of the",sizeof( "be included in all copies or substantial portions of the")-1, 0);
+ comment( &notice, &buf, "Software.",sizeof( "Software.")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ comment( &notice, &buf, "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY",sizeof( "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY")-1, 0);
+ comment( &notice, &buf, "KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE",sizeof( "KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE")-1, 0);
+ comment( &notice, &buf, "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR",sizeof( "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR")-1, 0);
+ comment( &notice, &buf, "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS",sizeof( "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS")-1, 0);
+ comment( &notice, &buf, "OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR",sizeof( "OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR")-1, 0);
+ comment( &notice, &buf, "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR",sizeof( "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR")-1, 0);
+ comment( &notice, &buf, "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE",sizeof( "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE")-1, 0);
+ comment( &notice, &buf, "SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",sizeof( "SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else
+ {
+ if (notice.type == 15)
+ {
+ if (notice.item[i = 15].data || notice.item[i = 5].data || notice.item[i = 2].data)
+ {
+ expand(&notice, &tmp, &notice.item[i]);
+ copy(&tmp, " - ", -1);
+ }
+ else
+ i = -1;
+ copy(&tmp, "Proprietary", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ if (notice.item[21].data)
+ {
+ copy(&tmp, "This is proprietary source code", -1);
+ if (i >= 0)
+ copy(&tmp, " licensed by", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 1);
+ if (notice.item[15].data)
+ {
+ expand(&notice, &tmp, &notice.item[15]);
+ copy(&tmp, " ", -1);
+ }
+ if (notice.item[5].data)
+ {
+ expand(&notice, &tmp, &notice.item[5]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 1);
+ }
+ else if (notice.item[2].data)
+ {
+ expand(&notice, &tmp, &notice.item[2]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 1);
+ }
+ }
+ else
+ {
+ copy(&tmp, "This is unpublished proprietary source code", -1);
+ if (i >= 0)
+ copy(&tmp, " of", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 1);
+ if (notice.item[i = 15].data || notice.item[i = 5].data)
+ expand(&notice, &tmp, &notice.item[i]);
+ if (notice.item[2].data)
+ {
+ if ((( &tmp)->nxt-( &tmp)->buf))
+ ((( &tmp)->nxt<( &tmp)->end)?(*( &tmp)->nxt++=( ' ')):(( ' '),(-1)));
+ expand(&notice, &tmp, &notice.item[2]);
+ }
+ if ((( &tmp)->nxt-( &tmp)->buf))
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 1);
+ comment( &notice, &buf, "and is not to be disclosed or used except in",sizeof( "and is not to be disclosed or used except in")-1, 1);
+ comment( &notice, &buf, "accordance with applicable agreements",sizeof( "accordance with applicable agreements")-1, 1);
+ }
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 13)
+ {
+ comment( &notice, &buf, "For nonexclusive individual use",sizeof( "For nonexclusive individual use")-1, 1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 14)
+ {
+ comment( &notice, &buf, "For noncommercial use",sizeof( "For noncommercial use")-1, 1);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ if (notice.type >= 15 && !notice.item[21].data)
+ {
+ comment( &notice, &buf, "Unpublished & Not for Publication",sizeof( "Unpublished & Not for Publication")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ if (notice.item[21].data)
+ {
+ copy(&tmp, "This software is licensed", -1);
+ if (notice.item[5].data || notice.item[2].data)
+ {
+ copy(&tmp, " by", -1);
+ if ((notice.item[15].size + (notice.item[5].data ? (notice.item[5].size + notice.item[8].size) : notice.item[2].size)) >= ((70-32) - 6))
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ else
+ ((( &tmp)->nxt<( &tmp)->end)?(*( &tmp)->nxt++=( ' ')):(( ' '),(-1)));
+ if (notice.item[15].data)
+ {
+ expand(&notice, &tmp, &notice.item[15]);
+ copy(&tmp, " ", -1);
+ }
+ if (notice.item[5].data)
+ {
+ expand(&notice, &tmp, &notice.item[5]);
+ if (notice.item[8].data)
+ {
+ copy(&tmp, " ", -1);
+ expand(&notice, &tmp, &notice.item[8]);
+ }
+ }
+ else if (notice.item[2].data)
+ expand(&notice, &tmp, &notice.item[2]);
+ }
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ comment( &notice, &buf, "under the terms and conditions of the license in",sizeof( "under the terms and conditions of the license in")-1, 0);
+ expand(&notice, &tmp, &notice.item[21]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[22].data)
+ {
+ copy(&tmp, "(with an md5 checksum of ", -1);
+ expand(&notice, &tmp, &notice.item[22]);
+ copy(&tmp, ")", -1);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ else if (notice.type == 15)
+ {
+ comment( &notice, &buf, "The copyright notice above does not evidence any",sizeof( "The copyright notice above does not evidence any")-1, 0);
+ comment( &notice, &buf, "actual or intended publication of such source code",sizeof( "actual or intended publication of such source code")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ }
+ if (v = notice.item[12].data)
+ {
+ x = v + notice.item[12].size;
+ if (*v == '\n')
+ v++;
+ item.quote = notice.item[12].quote;
+ do
+ {
+ for (item.data = v; v < x && *v != '\n'; v++);
+ if ((item.size = v - item.data) && *item.data == '\t')
+ {
+ item.data++;
+ item.size--;
+ h = 0;
+ }
+ else
+ h = -1;
+ expand(&notice, &tmp, &item);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), h);
+ } while (v++ < x);
+ if (item.size)
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ if (notice.item[13].data)
+ {
+ expand(&notice, &tmp, &notice.item[13]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[i = 15].data || notice.item[i = 5].data)
+ expand(&notice, &tmp, &notice.item[i]);
+ if (notice.item[2].data)
+ {
+ if ((( &tmp)->nxt-( &tmp)->buf))
+ ((( &tmp)->nxt<( &tmp)->end)?(*( &tmp)->nxt++=( ' ')):(( ' '),(-1)));
+ expand(&notice, &tmp, &notice.item[2]);
+ }
+ if ((( &tmp)->nxt-( &tmp)->buf))
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ if (notice.item[10].data)
+ {
+ expand(&notice, &tmp, &notice.item[10]);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ }
+ if (v = notice.item[0].data)
+ {
+ x = v + notice.item[0].size;
+ q = (x - v) == 1 && (*v == '*' || *v == '-');
+ k = q && notice.type != 4 ? -1 : 0;
+ for (;;)
+ {
+ if (!q)
+ {
+ while (v < x && (*v == ' ' || *v == '\t' || *v == '\r' || *v == '\n' || *v == ',' || *v == '+'))
+ v++;
+ if (v >= x)
+ break;
+ item.data = v;
+ while (v < x && *v != ',' && *v != '+' && *v++ != '>');
+ item.size = v - item.data;
+ item.quote = notice.item[0].quote;
+ }
+ h = 0;
+ for (i = 0; i < notice.ids; i++)
+ if (q || item.size == notice.id[i].name.size && !sstrncmp( item.data, notice.id[i].name.data, item.size))
+ {
+ h = 1;
+ if (notice.type == 4)
+ {
+ copy(&buf, "[-author?", -1);
+ expand(&notice, &buf, &notice.id[i].value);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( ']')):(( ']'),(-1)));
+ }
+ else
+ {
+ if (k < 0)
+ {
+ comment( &notice, &buf, "CONTRIBUTORS",sizeof( "CONTRIBUTORS")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ k = 1;
+ expand(&notice, &tmp, &notice.id[i].value);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ if (!q)
+ break;
+ }
+ if (q)
+ break;
+ if (!h)
+ {
+ if (notice.type == 4)
+ {
+ copy(&buf, "[-author?", -1);
+ expand(&notice, &buf, &item);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( ']')):(( ']'),(-1)));
+ }
+ else
+ {
+ if (k < 0)
+ {
+ comment( &notice, &buf, "CONTRIBUTORS",sizeof( "CONTRIBUTORS")-1, 0);
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ k = 1;
+ expand(&notice, &tmp, &item);
+ comment(&notice, &buf, (( &tmp)->buf), (( &tmp)->siz=( &tmp)->nxt-( &tmp)->buf,( &tmp)->nxt=( &tmp)->buf,( &tmp)->siz), 0);
+ }
+ }
+ }
+ if (k > 0)
+ comment(&notice, &buf, ((char*)0), 0, 0);
+ }
+ if (notice.type == 4)
+ {
+ copy(&buf, "[-copyright?", -1);
+ copyright(&notice, &buf);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( ']')):(( ']'),(-1)));
+ if (notice.item[21].data)
+ {
+ copy(&buf, "[-license?", -1);
+ expand(&notice, &buf, &notice.item[21]);
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( ']')):(( ']'),(-1)));
+ }
+ ((( &buf)->nxt<( &buf)->end)?(*( &buf)->nxt++=( '\n')):(( '\n'),(-1)));
+ }
+ else
+ comment(&notice, &buf, ((char*)0), -1, 0);
+ return (*(( &buf)->nxt>=( &buf)->end?(( &buf)->nxt=( &buf)->end-1):( &buf)->nxt)=0,( &buf)->nxt-( &buf)->buf);
+}
+#line 336 "../../lib/libpp/ppproto.c"
+
+#line 348
+static char*
+linesync __PARAM__((register Proto_t* proto, register char* p, register long n), (proto, p, n)) __OTORP__(register Proto_t* proto; register char* p; register long n;){
+
+ if (proto->flags & (1L<<13))
+
+ {
+
+ p = strcopy(p, "\n#line ");
+
+
+
+ p = number(p, n);
+ *p++ = '\n';
+ }
+ return p;
+}
+
+
+
+
+
+
+static char*
+init __PARAM__((Proto_t* proto, char* op, int flags), (proto, op, flags)) __OTORP__(Proto_t* proto; char* op; int flags;){
+ register char* s;
+
+ if (flags & (1L<<10))
+ {
+ op = strcopy(op, "\
+\n\
+#if !defined(__PROTO__)\n\
+# if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)\n\
+# if defined(__cplusplus)\n\
+# define __LINKAGE__ \"C\"\n\
+# else\n\
+# define __LINKAGE__\n\
+# endif\n\
+# define __STDARG__\n\
+# define __PROTO__(x) x\n\
+# define __OTORP__(x)\n\
+# define __PARAM__(n,o) n\n\
+# if !defined(__STDC__) && !defined(__cplusplus)\n\
+# if !defined(c_plusplus)\n\
+# define const\n\
+# endif\n\
+# define signed\n\
+# define void int\n\
+# define volatile\n\
+# define __V_ char\n\
+# else\n\
+# define __V_ void\n\
+# endif\n\
+# else\n\
+# define __PROTO__(x) ()\n\
+# define __OTORP__(x) x\n\
+# define __PARAM__(n,o) o\n\
+# define __LINKAGE__\n\
+# define __V_ char\n\
+# define const\n\
+# define signed\n\
+# define void int\n\
+# define volatile\n\
+# endif\n\
+# define __MANGLE__ __LINKAGE__\n\
+# if defined(__cplusplus) || defined(c_plusplus)\n\
+# define __VARARG__ ...\n\
+# else\n\
+# define __VARARG__\n\
+# endif\n\
+# if defined(__STDARG__)\n\
+# define __VA_START__(p,a) va_start(p,a)\n\
+# else\n\
+# define __VA_START__(p,a) va_start(p)\n\
+# endif\n\
+# if !defined(__INLINE__)\n\
+# if defined(__cplusplus)\n\
+# define __INLINE__ extern __MANGLE__ inline\n\
+# else\n\
+# if defined(_WIN32) && !defined(__GNUC__)\n\
+# define __INLINE__ __inline\n\
+# endif\n\
+# endif\n\
+# endif\n\
+#endif\n\
+#if !defined(__LINKAGE__)\n\
+#define __LINKAGE__ /* 2004-08-11 transition */\n\
+#endif\n\
+");
+ }
+ else
+ op = strcopy(op, "\
+\n\
+#if !defined(__PROTO__)\n\
+#include <prototyped.h>\n\
+#endif\n\
+#if !defined(__LINKAGE__)\n\
+#define __LINKAGE__ /* 2004-08-11 transition */\n\
+#endif\n\
+");
+ if (proto->package)
+ {
+ s = "\
+#ifndef __MANGLE_%_DATA__\n\
+# ifdef _BLD_%\n\
+# ifdef __EXPORT__\n\
+# define __MANGLE_%_DATA__ __MANGLE__ __EXPORT__\n\
+# else\n\
+# define __MANGLE_%_DATA__ __MANGLE__\n\
+# endif\n\
+# define __MANGLE_%_FUNC__ __MANGLE__\n\
+# else\n\
+# ifdef __IMPORT__\n\
+# define __MANGLE_%_DATA__ __MANGLE__ __IMPORT__\n\
+# else\n\
+# define __MANGLE_%_DATA__ __MANGLE__\n\
+# endif\n\
+# define __MANGLE_%_FUNC__ __MANGLE__\n\
+# endif\n\
+#endif\n\
+";
+ for (;;)
+ {
+ switch (*op++ = *s++)
+ {
+ case 0:
+ op--;
+ break;
+ case '%':
+ op = strcopy(op - 1, proto->package);
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ }
+ return op;
+}
+
+
+#line 422
+static char*
+nns __PARAM__((register char* s), (s)) __OTORP__(register char* s;){
+ while (*s == ' ' || *s == '\t' || *s == '\n')
+ s++;
+ return s;
+}
+
+
+#line 439
+static int
+directive __PARAM__((register char* s, int dir), (s, dir)) __OTORP__(register char* s; int dir;){
+ switch (*(s = nns(s)))
+ {
+ case 'e':
+ case 'i':
+ dir <<= 2;
+ switch (*++s)
+ {
+ case 'f':
+ dir |= 01;
+ break;
+ case 'l':
+ dir |= 02;
+ break;
+ case 'n':
+ dir |= 03;
+ break;
+ }
+ break;
+ }
+ return dir;
+}
+
+
+
+
+
+
+
+static int
+lex __PARAM__((register Proto_t* proto, register long flags), (proto, flags)) __OTORP__(register Proto_t* proto; register long flags;){
+ register char* ip;
+ register char* op;
+ register int c;
+ register int state;
+ register short* rp;
+ char* m;
+ char* e;
+ char* t;
+ char* bp;
+ char* v;
+ char* im;
+ char* ko;
+ char* aom;
+ int n;
+ int line;
+ int quot;
+ int brack;
+ int sub;
+ int x;
+ int vc;
+
+ char* ie = 0;
+ char* om = 0;
+ char* aim = 0;
+ char* aie = 0;
+ char* func = 0;
+ int call = 0;
+ int dir = 0;
+ int group = 0;
+ int last = 0;
+ int paren = 0;
+
+ char* qe = 0;
+ int qn = 0;
+ int args = 0;
+
+
+ do{(ip=proto->ip);(op=proto->op);call=proto->call;}while(0);
+
+ if (flags & (1L<<5)) (ko=op);
+
+ fsm_start:
+ proto->tp = ip;
+ state = 0;
+ bp = ip;
+ do
+ {
+ rp = _pp_fsmtab[state];
+ fsm_get:
+ while (!(state = rp[c = (*(unsigned char*)ip++)]));
+ fsm_next:
+ ;
+ } while (state > 0);
+ if ((n = ip - bp - 1) > 0)
+ {
+ ip = bp;
+ do switch( n) { default : memcopy( op, ip, n); op += n; ip += n; break; case 7 : * op++ = * ip++; case 6 : * op++ = * ip++; case 5 : * op++ = * ip++; case 4 : * op++ = * ip++; case 3 : * op++ = * ip++; case 2 : * op++ = * ip++; case 1 : * op++ = * ip++; case 0 : break; } while (0);
+ ip++;
+ }
+ state = ~state;
+ fsm_terminal:
+ switch ((( state)&((1<<(7+1))-1)))
+ {
+ case ((0+28)+11):
+ if (op > proto->ob && *(op - 1) == '=' && (op == proto->ob + 1 || *(op - 2) != '=')) switch (c)
+ {
+ case '+':
+ case '-':
+ case '*':
+ case '&':
+ (*op++=( ' '));
+ break;
+ }
+ (*op++=( c));
+ break;
+
+ case ((0+28)+0):
+ (ip--);
+ c = (*(op-1));
+ break;
+
+ case ((0+28)+1):
+ switch (c)
+ {
+ case '\n':
+ if ((( rp)>=_pp_fsmtab[(0+16)]&&( rp)<=_pp_fsmtab[(0+18)])) goto fsm_newline;
+ (*op++=( c));
+ proto->line++;
+ rp = _pp_fsmtab[(0+13)];
+ break;
+ case '/':
+
+ if ((flags & ((1L<<5)|(1L<<15))) == (1L<<5)) (op=ko);
+ else
+
+ (*op++=( c));
+ if ((( rp)>=_pp_fsmtab[(0+16)]&&( rp)<=_pp_fsmtab[(0+18)]))
+ {
+ rp = _pp_fsmtab[(0+16)];
+ break;
+ }
+ goto fsm_start;
+ case (255+1):
+ break;
+ default:
+
+ if ((flags & ((1L<<5)|(1L<<15))) == (1L<<5)) (op=ko);
+ else
+
+ (*op++=( c));
+ rp = _pp_fsmtab[(( rp)>=_pp_fsmtab[(0+16)]&&( rp)<=_pp_fsmtab[(0+18)]) ? (0+16) : (0+14)];
+ break;
+ }
+ bp = ip;
+ goto fsm_get;
+
+ case ((0+28)+2):
+ if (c)
+ {
+ if (state = _pp_fsmtab[(0+28)][((( rp)-_pp_fsmtab[0])/(255+1))+1])
+ goto fsm_terminal;
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return 0;
+ }
+ (ip--);
+ fsm_eob:
+ if ((flags & ((1L<<1)|((1L<<16))|(1L<<21))) == ((1L<<16)) && (proto->flags & (1L<<16)))
+ {
+
+ if (!(flags & (1L<<5)))
+
+ flags |= (1L<<24);
+ c = ip - proto->ib;
+ if (!(flags & (1L<<15)))
+ im = proto->tp;
+ if (ip > proto->ib)
+ {
+ n = ip - im;
+ if (ip - n < proto->ib)
+ proto->flags |= (1L<<4);
+ memcopy(proto->ib - n, ip - n, n);
+ ip = proto->ib;
+ }
+ proto->tp -= c;
+ if (flags & (1L<<15))
+ {
+ im -= c;
+ ie -= c;
+ }
+ if (aim)
+ aim -= c;
+ if (aie)
+ aie -= c;
+ if ((n = read(proto->fd, ip, proto->iz)) > 0)
+ {
+ if ((proto->options & (1L<<0)) && n < proto->iz)
+ {
+ proto->flags &= ~(1L<<16);
+ close(proto->fd);
+ }
+ *(ip + n) = 0;
+ if (state & (1<<7))
+ goto fsm_splice;
+ bp = ip;
+ goto fsm_get;
+ }
+ *ip = 0;
+ proto->flags &= ~(1L<<16);
+ close(proto->fd);
+ }
+ if (state & (1<<7))
+ goto fsm_splice;
+
+ if (!(flags & (1L<<21)) && (state = rp[c = (255+1)]))
+ {
+ bp = ip;
+ goto fsm_next;
+ }
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return 0;
+
+ case ((0+28)+3):
+ quot = c;
+
+ if (c == '"' && qe)
+ {
+ for (n = 0, t = qe + 1; t < op && (*t == ' ' || *t == '\t' || *t == '\n' && ++n || *t >= 'A' && *t <= 'Z' || *t == '_'); t++);
+ if (t == op)
+ {
+ op = qe;
+ qe = 0;
+ qn = n;
+ }
+ else (*op++=( c));
+ }
+ else
+
+ (*op++=( c));
+ rp = _pp_fsmtab[(0+21)];
+ bp = ip;
+ goto fsm_get;
+
+ case ((0+28)+4):
+ if (c == quot)
+ {
+
+ if (!(flags & (1L<<3)))
+ qe = (c == '"') ? op : (char*)0;
+
+ (*op++=( c));
+
+ while (qn > 0)
+ {
+ qn--;
+ (*op++=( '\n'));
+ }
+
+ }
+ else if (c != '\n' && c != (255+1))
+ {
+ (*op++=( c));
+ bp = ip;
+ goto fsm_get;
+ }
+ else
+ {
+
+ while (qn > 0)
+ {
+ qn--;
+ (*op++=( '\n'));
+ }
+
+ (ip--);
+ }
+ c = (0401+1);
+ break;
+
+ case ((0+28)+5):
+
+ if (flags & (1L<<0)) (*op++=( c));
+ else
+
+ switch (c)
+ {
+ case 'a':
+ n = (('A'==0301)?0057:0007);
+ goto fsm_oct;
+ case 'E':
+ n = (('A'==0301)?0047:0033);
+ goto fsm_oct;
+ case 'v':
+ n = 0013;
+ goto fsm_oct;
+ case 'x':
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ lex(proto, (flags & ((1L<<16))) | (1L<<21));
+ for (n = x = 0; (c = (*(unsigned char*)ip++)), x < 3; x++) switch (c)
+ {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ case '8': case '9':
+ n = (n << 4) + c - '0';
+ break;
+ case 'a': case 'b': case 'c': case 'd':
+ case 'e': case 'f':
+ n = (n << 4) + c - 'a' + 10;
+ break;
+ case 'A': case 'B': case 'C': case 'D':
+ case 'E': case 'F':
+ n = (n << 4) + c - 'A' + 10;
+ break;
+ default:
+ goto fsm_hex;
+ }
+ fsm_hex:
+ (ip--);
+ fsm_oct:
+ (*op++=( ((n >> 6) & 07) + '0'));
+ (*op++=( ((n >> 3) & 07) + '0'));
+ (*op++=( (n & 07) + '0'));
+ break;
+ default:
+ (*op++=( c));
+ break;
+ }
+ rp = _pp_fsmtab[(0+21)];
+ bp = ip;
+ goto fsm_get;
+
+ case ((0+28)+6):
+ (ip--);
+
+ if ((flags & (1L<<5)) && *proto->tp == 's' && !sstrncmp( proto->tp, "static", 6))
+ {
+ c = ((0500+4)+9);
+ break;
+ }
+
+ if (*proto->tp == '_' && !sstrncmp( proto->tp, "__STDPP__directive", 6)) c = '#';
+ else c = (0401+0);
+
+ break;
+
+ case ((0+28)+7):
+ fsm_newline:
+ proto->line++;
+
+ if (flags & (1L<<5))
+ {
+ if (op != proto->ob && (*(op-1)) != ' ' && (*(op-1)) != '\n')
+ (*op++=( ' '));
+ }
+ else
+
+ (*op++=( c));
+ if (flags & (1L<<3))
+ {
+
+ if (flags & (1L<<0))
+ {
+ if (flags & (1L<<5)) (op=ko);
+ if (flags & (1L<<12))
+ {
+ *(ip - 1) = 0;
+ op = strcopy(om, "/* ");
+ op = strcopy(op, im);
+ op = strcopy(op, " */\n");
+ }
+ flags &= ~((1L<<2)|(1L<<3)|(1L<<7)|(1L<<8)|(1L<<12)|(1L<<15)|(1L<<22)|(1L<<26));
+ }
+ else
+
+ {
+ if ((flags & ((1L<<2)|(1L<<22))) == ((1L<<2)|(1L<<22)))
+ {
+ *(ip - 1) = 0;
+ op = strcopy(om, "#if defined(__STDC__) || defined(__STDPP__)\n");
+ op = strcopy(op, im);
+ op = strcopy(op, "\n#else\n");
+ bp = ip;
+ ip = im;
+ *op++ = *ip++;
+ while (*op = *ip++)
+ if (*op++ == '#' && *ip != '(')
+ {
+ op--;
+ while (*--op == ' ' || *op == '\t');
+ if (*ip == '#')
+ {
+ op = strcopy(op + 1, "/**/");
+ while (*++ip == ' ' || *ip == '\t');
+ }
+ else
+ {
+ if (*op != '"') *++op = '"';
+ op++;
+ while (*ip == ' ' || *ip == '\t') ip++;
+ while ((c = *ip) >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9' || c == '_') *op++ = *ip++;
+ while (*ip == ' ' || *ip == '\t') ip++;
+ if (*ip == '"') ip++;
+ else *op++ = '"';
+ }
+ }
+ ip = bp;
+ op = strcopy(op, "\n#endif\n");
+ op = linesync(proto, op, proto->line);
+ }
+ flags &= ~((1L<<2)|(1L<<3)|(1L<<7)|(1L<<8)|(1L<<15)|(1L<<17)|(1L<<22)|(1L<<23)|(1L<<25)|(1L<<26));
+ }
+ call = 0;
+ group = 0;
+ paren = 0;
+ last = '\n';
+ }
+ if (paren == 0 && (flags & ((1L<<15)|(1L<<21)|(1L<<23)|(1L<<24))) == (1L<<24))
+ {
+
+ if (flags & (1L<<5)) (op=ko);
+
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return 0;
+ }
+ goto fsm_start;
+
+ case ((0+28)+8):
+ (*op++=( c));
+ rp = _pp_fsmtab[((( state)>>(7+1))&((1<<7)-1))];
+ bp = ip;
+ goto fsm_get;
+
+ case ((0+28)+13):
+ (*op++=( c));
+ c = (((( state)>>(7+1))&((1<<7)-1))+0401);
+ break;
+
+ case ((0+28)+14):
+ (ip--);
+ c = (((( state)>>(7+1))&((1<<7)-1))+0401);
+ break;
+
+ case (((0+28)+12)):
+ (ip--);
+ c = (0401+0);
+ if (!(flags & (1L<<1))) switch (((((long)( *proto->tp))<<16)|(((long)( *(ip - 1)))<<8)|((long)( ip - proto->tp))))
+ {
+ case ((((long)( 'N'))<<16)|(((long)( 'N'))<<8)|((long)( 3))):
+ if (proto->tp[1] == 'o')
+ c = ((0500+4)+6);
+ break;
+ case ((((long)( 'd'))<<16)|(((long)( 'o'))<<8)|((long)( 2))):
+ c = ((0500+4)+6);
+ break;
+ case ((((long)( 'e'))<<16)|(((long)( 'e'))<<8)|((long)( 4))):
+ if (!(flags & (1L<<21)) && (flags & ((1L<<3)|(1L<<25))) != (1L<<3) && !sstrncmp( proto->tp, "else", 4))
+ {
+ c = ((0500+4)+8);
+ goto fsm_id;
+ }
+ break;
+ case ((((long)( 'e'))<<16)|(((long)( 'n'))<<8)|((long)( 6))):
+ if (!sstrncmp( proto->tp, "extern", 6))
+ c = ((0500+4)+9);
+ break;
+ case ((((long)( 'f'))<<16)|(((long)( 'r'))<<8)|((long)( 3))):
+ if (!(flags & (1L<<21)) && !sstrncmp( proto->tp, "for", 3))
+ {
+ c = ((0500+4)+11);
+ goto fsm_id;
+ }
+ break;
+ case ((((long)( 'i'))<<16)|(((long)( 'f'))<<8)|((long)( 2))):
+ c = ((0500+4)+13);
+ break;
+ case ((((long)( 'i'))<<16)|(((long)( 'e'))<<8)|((long)( 6))):
+ if (!sstrncmp( proto->tp, "inline", 6) && !(flags & ((1L<<15)|(1L<<23)|(1L<<25)|(1L<<26))) && proto->brace == 0 && paren == 0 && group == 0 && (last == ';' || last == '}' || last == '\n' || last == 0))
+ {
+ flags |= (1L<<23);
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ line = proto->line;
+ op = strcopy(op - 6, "__INLINE__");
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ }
+ break;
+ case ((((long)( 'r'))<<16)|(((long)( 'n'))<<8)|((long)( 6))):
+ if (!(flags & (1L<<21)) && !sstrncmp( proto->tp, "return", 6))
+ {
+ c = ((0500+4)+17);
+ goto fsm_id;
+ }
+ break;
+ case ((((long)( 's'))<<16)|(((long)( 'c'))<<8)|((long)( 6))):
+ if ((proto->options & (1L<<6)) && !sstrncmp( proto->tp, "static", 6))
+ {
+ proto->ox = op - 6;
+ flags |= (1L<<6);
+ }
+ break;
+ case ((((long)( 't'))<<16)|(((long)( 'f'))<<8)|((long)( 7))):
+ if (!(flags & (1L<<21)) && !sstrncmp( proto->tp, "typedef", 7))
+ {
+ flags |= (1L<<26);
+ c = ((0500+4)+9);
+ }
+ break;
+ case ((((long)( 'v'))<<16)|(((long)( 't'))<<8)|((long)( 8))):
+ if (*ip == '(' && !sstrncmp( proto->tp, "va_start", 8)) c = (0500+1);
+ break;
+ case ((((long)( 'v'))<<16)|(((long)( 'd'))<<8)|((long)( 4))):
+ if (!sstrncmp( proto->tp, "void", 4))
+ {
+ if (flags & ((1L<<0)|(1L<<19)|(1L<<10)|(1L<<11))) c = ((0500+4)+30);
+ else
+ {
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ line = proto->line;
+ if (lex(proto, (flags & ((1L<<16))) | (1L<<21)) == '*')
+ {
+ memcopy(op - 4, "__V_", 4);
+ memcopy(ip - 4, "__V_", 4);
+ }
+ else c = ((0500+4)+30);
+ proto->line = line;
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ bp = ip;
+ }
+ }
+ break;
+ case ((((long)( 'w'))<<16)|(((long)( 'e'))<<8)|((long)( 5))):
+ if (!(flags & (1L<<21)) && !sstrncmp( proto->tp, "while", 5))
+ {
+ c = ((0500+4)+26);
+ goto fsm_id;
+ }
+ break;
+ }
+
+ if ((flags & (1L<<0)) && c != ((0500+4)+9))
+ c = (0401+0);
+
+ break;
+
+ case ((0+28)+10):
+ goto fsm_start;
+
+ case ((0+28)+15):
+ (ip--);
+
+ if ((flags & ((1L<<5)|(1L<<15))) == (1L<<5))
+ {
+ while (op > proto->ob && (*(op - 1) == ' ' || *(op - 1) == '\t'))
+ op--;
+ if (op > proto->ob && *(op - 1) != '\n') *op++ = ' ';
+ }
+
+ goto fsm_start;
+
+ default:
+ if (state & (1<<7))
+ {
+ if (c == '\\')
+ {
+ if (!(n = (*(unsigned char*)ip++)))
+ {
+ goto fsm_eob;
+ fsm_splice:
+ c = '\\';
+ n = (*(unsigned char*)ip++);
+ }
+ if (n == '\n')
+ {
+ proto->line++;
+ (*op++=( '\\'));
+ (*op++=( '\n'));
+ bp = ip;
+ goto fsm_get;
+ }
+ (ip--);
+ }
+ state &= ~(1<<7);
+ if (state >= (0+28))
+ goto fsm_terminal;
+ rp = _pp_fsmtab[state];
+ }
+ (*op++=( c));
+ bp = ip;
+ goto fsm_get;
+ }
+ if (!(flags & ((1L<<10)|(1L<<11)|(1L<<21))))
+ {
+ if (!(flags & (1L<<3))) switch (c)
+ {
+ case '(':
+
+ if (!(flags & (1L<<0)) || proto->brace == 0)
+
+ {
+ if (paren++ == 0)
+ {
+
+ if (!(flags & (1L<<0)) || group <= 1)
+
+ {
+
+ args = 0;
+
+ if (group++ == 0) group++;
+ else if (flags & (1L<<8)) call++;
+ flags |= (1L<<15);
+ im = ip - 1;
+ om = op - 1;
+ }
+ sub = 0;
+ }
+ else if (paren == 2 && !aim)
+ {
+ sub++;
+ if (last == '(')
+ {
+ flags &= ~(1L<<15);
+ om = 0;
+ }
+ else if (flags & (1L<<8))
+ {
+ aim = ip - 1;
+ aom = op - 1;
+ }
+ else if ((flags & ((1L<<15)|(1L<<25))) == (1L<<15))
+ {
+ for (m = ip - 2; m > im && (*m == ' ' || *m == '\t'); m--);
+ if (m != im && sub == 1)
+ {
+ m = im + (*nns(ip) == '*');
+ }
+ if (m == im)
+ {
+ flags &= ~(1L<<15);
+ om = 0;
+ }
+ }
+ else if ((flags & (1L<<15)) && sub == 1 && *nns(ip) != '*')
+ {
+ flags &= ~(1L<<15);
+ om = 0;
+ }
+ }
+ flags &= ~(1L<<25);
+ }
+ break;
+ case ')':
+
+ if (!(flags & (1L<<0)) || proto->brace == 0)
+
+ if (--paren == 0)
+ {
+
+ if (flags & (1L<<0))
+ {
+ if (group != 2)
+ {
+ c = (0401+0);
+ break;
+ }
+ group++;
+ }
+
+ ie = ip;
+ }
+ else if (paren == 1 && (flags & (1L<<8)) && !aie)
+ aie = ip;
+ break;
+ case '*':
+ if (last == '(' && group == 2)
+ {
+ group--;
+ if (paren == 1)
+ {
+ flags |= (1L<<8);
+ aim = aie = 0;
+ }
+ }
+ break;
+ case '#':
+ dir = directive(ip, dir);
+ if (proto->brace == 0 && paren == 0 && last != '=' && (flags & ((1L<<0)|(1L<<1)|(1L<<3)|(1L<<15)|(1L<<19)|(1L<<23)|(1L<<25))) == ((1L<<15)|(1L<<25)) && ((dir & 03) != 03 || ((dir>>2) & 03) != 01))
+ flags |= (1L<<3);
+ else if (!(flags & ((1L<<1)|(1L<<3))))
+ {
+ flags |= (1L<<3);
+ if (!(flags & (1L<<19)))
+ {
+ bp = ip;
+ while (*ip == ' ' || *ip == '\t') ip++;
+ if (*ip == 'l' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e')
+ {
+ if (*++ip == ' ' || *ip == '\t')
+ {
+ proto->line = 0;
+ while (*++ip >= '0' && *ip <= '9')
+ proto->line = proto->line * 10 + *ip - '0';
+ proto->line--;
+ }
+ }
+
+ else if ((flags & ((1L<<0)|(1L<<5))) == (1L<<0))
+ {
+ n = 0;
+ t = ip + 6;
+ while (ip < t && *ip >= 'a' && *ip <= 'z')
+ n = ((( n)<<5)+(( *ip++)-('a'-1)));
+ switch (n)
+ {
+ case ((( ((( ((( (( 'e')-('a'-1)))<<5)+(( 'l')-('a'-1))))<<5)+(( 's')-('a'-1))))<<5)+(( 'e')-('a'-1))):
+ case ((( ((( ((( ((( (( 'e')-('a'-1)))<<5)+(( 'n')-('a'-1))))<<5)+(( 'd')-('a'-1))))<<5)+(( 'i')-('a'-1))))<<5)+(( 'f')-('a'-1))):
+ while (*ip == ' ' || *ip == '\t') ip++;
+ if (*ip != '\n' && *ip != '/' && *(ip + 1) != '*')
+ {
+ flags |= (1L<<12)|(1L<<15);
+ im = ip;
+ om = op + (ip - bp);
+ }
+ break;
+ case ((( ((( ((( (( 'e')-('a'-1)))<<5)+(( 'l')-('a'-1))))<<5)+(( 'i')-('a'-1))))<<5)+(( 'f')-('a'-1))):
+ case ((( ((( ((( ((( (( 'e')-('a'-1)))<<5)+(( 'r')-('a'-1))))<<5)+(( 'r')-('a'-1))))<<5)+(( 'o')-('a'-1))))<<5)+(( 'r')-('a'-1))):
+ case ((( (( 'i')-('a'-1)))<<5)+(( 'f')-('a'-1))):
+ case ((( ((( ((( ((( (( 'i')-('a'-1)))<<5)+(( 'f')-('a'-1))))<<5)+(( 'd')-('a'-1))))<<5)+(( 'e')-('a'-1))))<<5)+(( 'f')-('a'-1))):
+ case ((( ((( ((( ((( ((( (( 'i')-('a'-1)))<<5)+(( 'f')-('a'-1))))<<5)+(( 'n')-('a'-1))))<<5)+(( 'd')-('a'-1))))<<5)+(( 'e')-('a'-1))))<<5)+(( 'f')-('a'-1))):
+ case ((( ((( ((( ((( (( 'u')-('a'-1)))<<5)+(( 'n')-('a'-1))))<<5)+(( 'd')-('a'-1))))<<5)+(( 'e')-('a'-1))))<<5)+(( 'f')-('a'-1))):
+ break;
+ case ((( ((( ((( ((( ((( (( 'i')-('a'-1)))<<5)+(( 'n')-('a'-1))))<<5)+(( 'c')-('a'-1))))<<5)+(( 'l')-('a'-1))))<<5)+(( 'u')-('a'-1))))<<5)+(( 'd')-('a'-1))):
+ if (*ip == 'e') ip++;
+
+ case ((( ((( ((( ((( ((( (( 'd')-('a'-1)))<<5)+(( 'e')-('a'-1))))<<5)+(( 'f')-('a'-1))))<<5)+(( 'i')-('a'-1))))<<5)+(( 'n')-('a'-1))))<<5)+(( 'e')-('a'-1))):
+ case ((( ((( ((( ((( ((( (( 'p')-('a'-1)))<<5)+(( 'r')-('a'-1))))<<5)+(( 'a')-('a'-1))))<<5)+(( 'g')-('a'-1))))<<5)+(( 'm')-('a'-1))))<<5)+(( 'a')-('a'-1))):
+ if (*ip < 'a' || *ip > 'z') break;
+
+ default:
+ flags |= (1L<<12)|(1L<<15);
+ im = bp - 1;
+ om = op - 1;
+ break;
+ }
+ }
+ else
+
+ {
+ if (*ip == 'i' && *++ip == 'n' && *++ip == 'c' && *++ip == 'l' && *++ip == 'u' && *++ip == 'd' && *++ip == 'e')
+ {
+ while (*++ip == ' ' || *ip == '\t');
+ if (*ip++ == '<' && *ip++ == 's' && *ip++ == 't' && *ip++ == 'd' && *ip++ == 'a' && *ip++ == 'r' && *ip++ == 'g' && *ip++ == '.' && *ip++ == 'h' && *ip++ == '>')
+ {
+ op = strcopy(op, "\
+if !defined(va_start)\n\
+#if defined(__STDARG__)\n\
+#include <stdarg.h>\n\
+#else\n\
+#include <varargs.h>\n\
+#endif\n\
+#endif\n\
+");
+ op = linesync(proto, op, proto->line);
+ break;
+ }
+ }
+ else if (*ip == 'd' && *++ip == 'e' && *++ ip == 'f' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e' && (*++ip == ' ' || *ip == '\t'))
+ {
+ while (*++ip == ' ' || *ip == '\t');
+ if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t'))
+ {
+ t = ip;
+ while (*++t == ' ' || *t == '\t');
+ if (*t == 'e' && *++t == 'x' && *++ t == 't' && *++t == 'e' && *++t == 'r' && *++t == 'n' && (*++t == ' ' || *t == '\t' || *t == '\n' || *t == '\r'))
+ ip = t;
+ t = ip;
+ while (*++t == ' ' || *t == '\t');
+ if (*t == '_' && *(t + 1) == '_')
+ {
+ op = strcopy(op, "undef __MANGLE__\n");
+ op = linesync(proto, op, proto->line);
+ op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
+ break;
+ }
+ }
+ flags |= (1L<<2)|(1L<<15);
+ im = bp - 1;
+ om = op - 1;
+ }
+ else if (*ip == 'u' && *++ip == 'n' && *++ ip == 'd' && *++ip == 'e' && *++ip == 'f' && (*++ip == ' ' || *ip == '\t'))
+ {
+ while (*++ip == ' ' || *ip == '\t');
+ if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t' || *ip == '\n' || *ip == '\r'))
+ {
+ op = strcopy(op, "undef __MANGLE__\n");
+ op = linesync(proto, op, proto->line);
+ op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
+ break;
+ }
+ flags |= (1L<<2)|(1L<<15);
+ im = bp - 1;
+ om = op - 1;
+ }
+ }
+ ip = bp;
+ }
+ break;
+ }
+ else
+ break;
+
+ case '{':
+ if (proto->brace++ == 0 && paren == 0)
+ {
+ if (last == '=') flags |= (1L<<9);
+
+ else if (flags & (1L<<0))
+ {
+ if ((flags & ((1L<<15)|(1L<<17)|(1L<<23))) == (1L<<15))
+ {
+ if (args)
+ {
+ v = number(op, args < 0 ? -args : args);
+ v = strcopy(v, " argument actual/formal mismatch");
+ *v++ = ' ';
+ v = memcopy(v, im, ie - im);
+ *v = 0;
+ proto_error((char*)proto + sizeof(Proto_t), 2, op, ((char*)0));
+ }
+ ip--;
+
+ v = ie;
+ while (ie < ip)
+ if (*ie++ == '/' && *ie == '*')
+ {
+ e = ie - 1;
+ while (++ie < ip)
+ {
+ if (*ie == '*')
+ {
+ while (ie < ip && *ie == '*') ie++;
+ if (ie < ip && *ie == '/')
+ {
+ while (++ie < ip && (*ie == ' ' || *ie == '\t'));
+ while (e > v && (*(e - 1) == ' ' || *(e - 1) == '\t')) e--;
+ if (e > v && *e != '\n') *e++ = ' ';
+ t = ie;
+ while (--e >= v)
+ *--t = *e;
+ v = t;
+ break;
+ }
+ }
+ }
+ }
+ ie = v;
+
+ op = om++;
+ if (flags & (1L<<5))
+ {
+ v = op;
+ while (v > ko && *--v != ' ');
+ if (*v != ' ')
+ {
+ om = (v = (op += 4)) + 1;
+ while (v >= ko + 4)
+ {
+ *v = *(v - 4);
+ v--;
+ }
+ memcopy(ko, "int ", 4);
+ }
+ if (*v == ' ')
+ {
+ while (*(v + 1) == '*')
+ *v++ = '*';
+ *v = '\t';
+ if ((v - ko) <= 8)
+ {
+ om = (e = ++op) + 1;
+ while (e > v)
+ {
+ *e = *(e - 1);
+ e--;
+ }
+ }
+ }
+ om = (v = (op += 7)) + 1;
+ while (v >= ko + 7)
+ {
+ *v = *(v - 7);
+ v--;
+ }
+ memcopy(ko, "extern ", 7);
+ }
+ (*op++=( '('));
+ t = op;
+ e = 0;
+
+ while (ie < ip)
+ {
+ if ((c = *ie) == ' ' || c == '\t' || c == '\n')
+ {
+ while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
+ if (ie >= ip) break;
+ if (c != '*' && op > om) (*op++=( ' '));
+ }
+ if ((n = ((c = *ie) == ',')) || c == ';')
+ {
+ if (flags & (1L<<5))
+ {
+ m = op;
+ while (op > om && ((c = *(op - 1)) == '(' || c == ')' || c == '[' || c == ']'))
+ op--;
+ v = op;
+ while (op > om && (c = *(op - 1)) != ' ' && c != '*')
+ op--;
+ while (*(op - 1) == ' ')
+ op--;
+ if (!e)
+ {
+ e = op;
+ while (e > om && *(e - 1) == '*')
+ e--;
+ }
+
+
+
+
+ if (op <= om)
+ op = strcopy(op, "int");
+ else if (*(op - 1) == ',')
+ op = strcopy(op, " int");
+
+ while (v < m)
+ (*op++=( *v++));
+ }
+ (*op++=( ','));
+ if (n)
+ {
+ if (x = !e) e = op - 1;
+ (*op++=( ' '));
+ m = t;
+ while (m < e)
+ (*op++=( *m++));
+ if (x)
+ {
+ m = e;
+ while (*--e != ' ');
+ while (*(e - 1) == '*') e--;
+ op -= m - e;
+ }
+ }
+ while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
+ if (ie >= ip) (op--);
+ else (*op++=( ' '));
+ if (!n)
+ {
+ t = op;
+ e = 0;
+ }
+ }
+ else if (*ie == '*')
+ {
+ if (op > om && (c = *(op - 1)) == ' ') op--;
+ while (*ie == '*') (*op++=( *ie++));
+ while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
+ if (c != '(') (*op++=( ' '));
+ }
+ else if (*ie == '(')
+ {
+ if (op > om && *(op - 1) == ' ') op--;
+ (*op++=( *ie++));
+ while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
+ }
+ else if (*ie == ')')
+ {
+ if (op > om && *(op - 1) == '(')
+ proto_error((char*)proto + sizeof(Proto_t), 1, "function pointer argument prototype omitted", ((char*)0));
+ (*op++=( *ie++));
+ while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
+ }
+ else if ((flags & (1L<<5)) && (op == om || *(op - 1) == ' ') && *ie == 'r' && !sstrncmp( ie, "register", 8) && (*(ie + 8) == ' ' || *(ie + 8) == '\t' || *(ie + 8) == '\n'))
+ {
+ ie += 8;
+ if (op > om) (op--);
+ }
+ else (*op++=( *ie++));
+ }
+
+ if (op <= om) op = strcopy(op, "void");
+ (*op++=( ')'));
+ if (flags & (1L<<5))
+ {
+ (*op++=( ';'));
+ (*op++=( '\n'));
+ (proto->op=op);
+ (ko=op);
+ }
+ else
+ {
+ (*op++=( '\n'));
+ (*op++=( *ip));
+ }
+ ip++;
+ flags &= ~((1L<<15)|(1L<<23));
+ }
+ }
+
+ else if ((flags & ((1L<<15)|(1L<<19)|(1L<<23)|(1L<<25))) == ((1L<<15)|(1L<<25)))
+ {
+ line = proto->line;
+ op = strcopy(om, " __PARAM__(");
+ op = memcopy(op, im, ie - im);
+ (*op++=( ','));
+ (*op++=( ' '));
+ (*op++=( '('));
+ flags &= ~((1L<<15)|(1L<<23));
+ if (flags & (1L<<27))
+ {
+ if ((vc = ie - im + 1) > sizeof(proto->variadic)) vc = sizeof(proto->variadic);
+ memcopy(proto->variadic, im, vc);
+ op = strcopy(op, "va_alist)) __OTORP__(va_dcl)\n{");
+ }
+ else
+ {
+ flags |= (1L<<23);
+ proto->ip = im;
+ proto->op = op;
+ group = 0;
+ brack = 0;
+ for (;;)
+ {
+ switch (lex(proto, (flags & ((1L<<16))) | (1L<<21)))
+ {
+ case '[':
+ brack++;
+ continue;
+ case ']':
+ brack--;
+ continue;
+ case '(':
+ if (paren++) group++;
+ continue;
+ case ')':
+ if (--paren == 0)
+ {
+ group = 0;
+ if (flags & (1L<<15))
+ {
+ flags &= ~((1L<<15)|(1L<<23));
+ op = memcopy(op, m, e - m);
+ }
+ break;
+ }
+ continue;
+ case ',':
+ if (paren == 1)
+ {
+ group = 0;
+ if (flags & (1L<<15))
+ {
+ flags &= ~((1L<<15)|(1L<<23));
+ op = memcopy(op, m, e - m);
+ }
+ (*op++=( ','));
+ (*op++=( ' '));
+ proto->op = op;
+ }
+ continue;
+ case (0401+0):
+ if (group <= 1 && !brack)
+ {
+ flags |= (1L<<15);
+ m = proto->tp;
+ e = proto->ip;
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ (*op++=( ')'));
+ (*op++=( ')'));
+ }
+ if (!(flags & (1L<<23)))
+ {
+ flags |= (1L<<23);
+ proto->op = strcopy(op, " __OTORP__(");
+ proto->ip = im + 1;
+ n = *(ie - 1);
+ *(ie - 1) = ';';
+ c = *ie;
+ *ie = 0;
+ lex(proto, (flags & ((1L<<16))) | (1L<<1));
+ *(ie - 1) = n;
+ *ie = c;
+ proto->ip = ie;
+ op = proto->op;
+ (*op++=( ')'));
+ }
+ if (flags & (1L<<6)) memcopy( proto->ox, "extern", 6);
+ op = linesync(proto, op, proto->line = line);
+ if (flags & (1L<<3))
+ {
+ proto->brace = 0;
+ (*op++=( '\n'));
+ (*op++=( '#'));
+ }
+ else if (!(flags & (1L<<27))) (*op++=( '{'));
+ }
+ }
+ flags &= ~((1L<<7)|(1L<<8)|(1L<<15)|(1L<<17)|(1L<<23));
+ call = 0;
+ group = 0;
+ break;
+ case '}':
+ flags &= ~((1L<<7)|(1L<<8)|(1L<<15)|(1L<<17)|(1L<<23)|(1L<<25));
+ if (--proto->brace == 0)
+ {
+ flags &= ~((1L<<9)|(1L<<27)|(1L<<28));
+
+ if (flags & (1L<<5)) (op=ko);
+
+ }
+ call = 0;
+ group = 0;
+ paren = 0;
+ break;
+ case '=':
+ if (last == '?') flags |= (1L<<3);
+ else if (paren == 0 && (flags & ((1L<<9)|(1L<<15)|(1L<<23))) == (1L<<15))
+ {
+ if (last == ')' && proto->brace && (group != 2 || call != 2)) flags |= (1L<<23);
+ else goto fsm_statement;
+ }
+ goto fsm_other;
+ case ',':
+
+ if (flags & (1L<<0))
+ {
+ if (paren == 1) args++;
+ else
+ {
+ args--;
+ flags &= ~(1L<<15);
+ }
+ break;
+ }
+
+ if (paren == 0 && (flags & (1L<<1))) *(op - 1) = c = ';';
+
+ case ';':
+ fsm_statement:
+ if (flags & (1L<<9)) ;
+
+ else if (flags & (1L<<0))
+ {
+ if (paren == 0)
+ {
+ if ((flags & (1L<<15)) && last == ')')
+ flags &= ~(1L<<15);
+ if (!(flags & (1L<<15)))
+ {
+ call = 0;
+ group = 0;
+ flags &= ~(1L<<23);
+ if (flags & (1L<<5)) (op=ko);
+ if (flags & (1L<<24))
+ {
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return 0;
+ }
+ }
+ else
+ {
+ args--;
+ if ((flags & ((1L<<5)|(1L<<23))) == ((1L<<5)|(1L<<23)))
+ (op=ko);
+ }
+ }
+ }
+
+ else if (paren == 0)
+ {
+ if ((flags & ((1L<<15)|(1L<<17)|(1L<<23))) == (1L<<15) && call > 1)
+ {
+ if ((flags & (1L<<14)) && func)
+ {
+ func[0] = 'F';
+ func[1] = 'U';
+ func[2] = 'N';
+ func[3] = 'C';
+ func = 0;
+ }
+ if ((flags & ((1L<<1)|(1L<<8))) == (1L<<8) && aim && aie < im)
+ {
+ while (aie < ip && (*aie == ' ' || *aie == '\t' || *aie == '\n')) aie++;
+ v = aim;
+ while (v < aie)
+ if (*v++ == ')') break;
+ while (v < aie && (*v == ' ' || *v == '\t' || *v == '\n')) v++;
+ if (v == aie || !(flags & (1L<<20)))
+ {
+ if (flags & (1L<<20)) n = 3;
+ else if (v == aie && *v == '(') n = 10;
+ else n = 11;
+ ko = op;
+ om += n;
+ v = op += n;
+ while (v >= ko + n)
+ {
+ *v = *(v - n);
+ v--;
+ }
+ if (flags & (1L<<20)) memcopy(aom, "(...))", 6);
+ else if (n == 10) memcopy(aom, "(__VARARG__))", 13);
+ else
+ {
+ ko = strcopy(aom, " __PROTO__(");
+ ko = memcopy(ko, aim, aie - aim);
+ *ko = ')';
+ if (++ko >= om)
+ {
+ *ko++ = ')';
+ om = ko;
+ }
+ }
+ }
+ }
+ else if (flags & (1L<<26))
+ {
+ op = om;
+ while (*--op == ' ' || *op == '\t' || *op == '\n');
+ if (*op != ')')
+ {
+ op = om += 14;
+ *--op = ')';
+ while ((x = *(op - 14)) >= 'A' && x <= 'Z' || x >= 'a' && x <= 'z' || x >= '0' && x <= '9' || x == '_')
+ *--op = x;
+ memcopy(op - 13, "(__OTORP__(*)", 13);
+ }
+ }
+ if (flags & (1L<<17))
+ ;
+ else if (flags & (1L<<20))
+ {
+ op = om;
+ if (!(flags & (1L<<25))) op = strcopy(op, "(...)");
+ else op = memcopy(op, im, ie - im);
+ (*op++=( c));
+ }
+ else
+ {
+ if (flags & (1L<<1)) op = strcopy(om, "()");
+ else if (!(flags & (1L<<25))) op = strcopy(om, "(__VARARG__)");
+ else
+ {
+ op = strcopy(om, " __PROTO__(");
+ op = memcopy(op, im, ie - im);
+ (*op++=( ')'));
+ }
+ if (flags & (1L<<6)) memcopy( proto->ox, "extern", 6);
+ (*op++=( c));
+ }
+ flags &= ~((1L<<15)|(1L<<27)|(1L<<28));
+ if (c == ',' && !(flags & (1L<<8)))
+ {
+ call = 1;
+ group = 0;
+ break;
+ }
+ }
+ else if (flags & ((1L<<17)|(1L<<23))) call = 0;
+ if (c == ';')
+ {
+ flags &= ~((1L<<6)|(1L<<14)|(1L<<25)|(1L<<26));
+ call = 0;
+ if (flags & (1L<<24))
+ {
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return 0;
+ }
+ }
+ else call = call > 1 && c == ',';
+ group = 0;
+ flags &= ~((1L<<7)|(1L<<8)|(1L<<15)|(1L<<17)|(1L<<23));
+ }
+ else if (paren == 1 && group == 1 && !(flags & ((1L<<7)|(1L<<14)))) flags |= (1L<<25)|(1L<<17);
+ break;
+ case ((0500+4)+6):
+ case ((0500+4)+13):
+ flags |= (1L<<25)|(1L<<23);
+ break;
+ case ((0500+4)+9):
+
+ if (flags & (1L<<0))
+ {
+ if (proto->brace == 0)
+ flags |= (1L<<23);
+ }
+ else
+
+ if (paren == 0 && !(flags & (1L<<26)))
+ {
+ flags |= (1L<<14);
+ if (!(flags & (1L<<19)) || proto->package)
+ {
+ op = strcopy(op, " __MANGLE__");
+ if (proto->package)
+ {
+ op = strcopy(op - 1, proto->package);
+ func = op + 1;
+ op = strcopy(op, "_DATA__");
+ }
+ }
+ else
+ func = 0;
+ }
+ break;
+ case (0401+29):
+ if (paren == 0 && (flags & ((1L<<1)|(1L<<27))) == (1L<<1))
+ {
+ op -= 3;
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return c;
+ }
+ if (paren == 1 && !(flags & (1L<<23)))
+ flags |= (1L<<27);
+ flags |= (1L<<25);
+ break;
+ case ((0500+4)+30):
+ goto fsm_id;
+ case (0500+1):
+ if ((flags & ((1L<<19)|(1L<<27))) == (1L<<27))
+ {
+ flags &= ~(1L<<15);
+ line = proto->line;
+ op = strcopy(op - 8, "__VA_START__");
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ for (;;)
+ {
+ switch (lex(proto, (flags & ((1L<<16))) | (1L<<21)))
+ {
+ case 0:
+ case ';':
+ break;
+ case (0401+0):
+ if (!(flags & (1L<<15)))
+ {
+ flags |= (1L<<15);
+ m = proto->tp;
+ e = proto->ip;
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ do{(ip=proto->ip);(op=proto->op);call=proto->call;}while(0);
+ if (flags & (1L<<15))
+ {
+ v = m;
+ n = e - m;
+ }
+ else
+ {
+ v = "ap";
+ n = 2;
+ }
+ op = strcopy(op, " __OTORP__(");
+ proto->ip = proto->variadic;
+ proto->op = op;
+ flags &= ~(1L<<15);
+ group = 0;
+ bp = proto->ip + 1;
+ if (*bp == 'r' && !sstrncmp( bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
+ for (;;)
+ {
+ switch (lex(proto, (flags & ((1L<<16))) | (1L<<21)))
+ {
+ case '(':
+ if (paren++) group++;
+ continue;
+ case ')':
+ if (--paren == 0)
+ {
+ if (flags & (1L<<15))
+ {
+ flags &= ~(1L<<15);
+ if (!(flags & (1L<<28)))
+ {
+ op = memcopy(op, m, e - m);
+ op = strcopy(op, " = ");
+ }
+ op = strcopy(op, "va_arg(");
+ op = memcopy(op, v, n);
+ (*op++=( ','));
+ (*op++=( ' '));
+ if (m > bp) op = memcopy(op, bp, m - bp);
+ else op = strcopy(op, "int ");
+ if (group > 1) op = strcopy(op, ")()");
+ else op = memcopy(op, e, proto->ip - e - 1);
+ (*op++=( ')'));
+ (*op++=( ';'));
+ }
+ group = 0;
+ break;
+ }
+ continue;
+ case ',':
+ if (paren == 1)
+ {
+ if (flags & (1L<<15))
+ {
+ flags &= ~(1L<<15);
+ if (!(flags & (1L<<28)))
+ {
+ op = memcopy(op, m, e - m);
+ op = strcopy(op, " = ");
+ }
+ op = strcopy(op, "va_arg(");
+ op = memcopy(op, v, n);
+ (*op++=( ','));
+ (*op++=( ' '));
+ if (m > bp) op = memcopy(op, bp, m - bp);
+ else op = strcopy(op, "int ");
+ if (group > 1) op = strcopy(op, ")()");
+ else op = memcopy(op, e, proto->ip - e - 1);
+ (*op++=( ')'));
+ (*op++=( ';'));
+ bp = proto->ip + 1;
+ if (*bp == 'r' && !sstrncmp( bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
+ }
+ group = 0;
+ proto->op = op;
+ }
+ continue;
+ case (0401+0):
+ if (group <= 1)
+ {
+ flags |= (1L<<15);
+ m = proto->tp;
+ e = proto->ip;
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ op = strcopy(op, ")");
+ flags |= (1L<<28);
+ proto->line = line;
+ call = 0;
+ break;
+ }
+
+ case (0401+0):
+ fsm_id:
+
+ if (flags & (1L<<0))
+ {
+ if (!args && paren == 1) args++;
+ break;
+ }
+
+ if (paren == 0)
+ {
+ if (last == ')')
+ {
+ if (proto->brace == 0 && !(flags & (1L<<1))) flags |= (1L<<23);
+ call = !call;
+ }
+ else if ((flags & (1L<<23)) || c == (0401+0) || c == ((0500+4)+30)) call++;
+ else flags |= (1L<<23);
+ if (last == (0401+0)) flags |= (1L<<7);
+ }
+ c = (0401+0);
+ flags |= (1L<<25);
+ break;
+ case (0401+1):
+ if (*proto->tp >= '0' && *proto->tp <= '9')
+ {
+ n = 0;
+ for (;; op--)
+ {
+ switch (*(op - 1))
+ {
+ case 'f':
+ case 'F':
+ t = op;
+ while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
+ if (*t == '.')
+ op--;
+ n = 0;
+ break;
+ case 'l':
+ case 'L':
+ if (!(n & 01))
+ {
+ n |= 01;
+ t = op;
+ while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
+ if (*t == '.')
+ {
+ n = 0;
+ op--;
+ break;
+ }
+ }
+ continue;
+ case 'u':
+ case 'U':
+ n |= 02;
+ continue;
+ }
+ break;
+ }
+ if (n & 01)
+ *op++ = 'L';
+ if (n & 02)
+ {
+ m = op;
+ t = op = m + 10;
+ while ((c = *--m) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
+ *--t = c;
+ c = *t;
+ strcopy(m + 1, "(unsigned)");
+ *t = c;
+ break;
+ }
+ }
+ goto fsm_other;
+
+ case '[':
+ if ((flags & (1L<<0)) && paren == 0 && group <= 2) flags |= (1L<<23);
+
+
+ default:
+ fsm_other:
+
+ if (flags & (1L<<0)) break;
+
+ flags |= (1L<<25);
+ if (paren == 0) flags |= (1L<<17);
+ break;
+ }
+ else if (c == '#' && *ip != '(') flags |= (1L<<22);
+ last = c;
+
+ if ((flags & ((1L<<5)|(1L<<15))) == ((1L<<5)|(1L<<15)) && ((flags & ((1L<<3)|(1L<<23))) || proto->brace || c != '(' && c != ')' && c != '*' && c != (0401+0)))
+ (op=proto->op);
+ else
+
+ (proto->op=op);
+ goto fsm_start;
+ }
+ else if (flags & ((1L<<10)|(1L<<11)))
+ {
+
+ if ((flags & (1L<<29)) && c == '%' && *ip == '{')
+ t = 0;
+ else
+
+ {
+ if (c == '#')
+ {
+ for (t = ip; *t == ' ' || *t == '\t'; t++);
+ if (*t++ == 'i' && *t++ == 'f' && *t++ == 'n' && *t++ == 'd' && *t++ == 'e' && *t++ == 'f')
+ {
+
+
+
+
+ t = 0;
+ }
+ }
+ else
+ t = "";
+ }
+ if (t)
+ {
+
+ n = ip - proto->tp;
+ ip -= n;
+ op -= n;
+
+
+
+
+ }
+ else
+ while (*ip != '\n')
+ *op++ = *ip++;
+ op = init(proto, op, flags);
+ op = linesync(proto, op, proto->line);
+ flags &= ~((1L<<10)|(1L<<11));
+ proto->flags &= ~((1L<<10)|(1L<<11));
+ goto fsm_start;
+ }
+ do{(proto->ip=ip);(proto->op=op);proto->flags&=~((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->flags|=flags&((1L<<5)|(1L<<9)|(1L<<17)|(1L<<27)|(1L<<28));proto->call=call;}while(0);
+ return c;
+}
+
+
+
+
+
+void
+pppclose __PARAM__((char* iob), (iob)) __OTORP__(char* iob;){
+ register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t));
+
+ if (proto->flags & (1L<<16)) close(proto->fd);
+ free((char*)proto);
+}
+
+
+#line 2055
+char*
+pppopen __PARAM__((char* file, int fd, char* notice, char* options, char* package, char* comment, int flags), (file, fd, notice, options, package, comment, flags)) __OTORP__(char* file; int fd; char* notice; char* options; char* package; char* comment; int flags;){
+ register Proto_t* proto;
+ register char* iob;
+ register long n;
+ register char* s;
+ char* t;
+ int pragma;
+ int clr;
+ int hit;
+ int i;
+ int z;
+ char* b;
+
+ int comlen;
+ char com[80];
+
+ int m = 0;
+
+ static int retain;
+
+
+
+
+
+
+ if (flags & (1<<0)) flags &= ~(1<<5);
+
+ if (flags & (1<<11)) flags &= ~retain;
+ else retain &= (1<<6);
+ if (file && (fd = open(file, O_RDONLY)) < 0) return 0;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+
+
+
+
+ n = (16*1024);
+ if (!(proto = (( 0)?( Proto_t*)realloc((char*)( 0),sizeof( Proto_t)*( 1)+( 5 * n + 2)):( Proto_t*)calloc(1,sizeof( Proto_t)*( 1)+( 5 * n + 2)))))
+ return 0;
+ proto->iz = n;
+ proto->oz = 3 * n;
+ proto->flags |= (1L<<16);
+ }
+ proto->fd = fd;
+ proto->package = package;
+ iob = (char*)proto + sizeof(Proto_t);
+ proto->op = proto->ob = iob;
+ proto->ip = proto->ib = iob + proto->oz + n;
+ if (m) proto->options |= (1L<<0);
+ if (!comment)
+ comment = "/*";
+ if (!(proto->cc[0] = comment[0]))
+ notice = options = 0;
+ else if (comment[1])
+ {
+ proto->cc[1] = comment[1];
+ proto->cc[2] = comment[2] ? comment[2] : comment[0];
+ }
+ else
+ proto->cc[1] = proto->cc[2] = comment[0];
+
+
+
+
+
+ n = read(fd, proto->ip, proto->iz);
+ if (!(proto->flags & (1L<<16)))
+ close(fd);
+ if (n < 0)
+ {
+ pppclose(iob);
+ return 0;
+ }
+ *(proto->ip + n) = 0;
+
+
+#line 2165
+ if (!notice && !options || (comlen = astlicense(com, sizeof(com), ((char*)0), "type=check", proto->cc[0], proto->cc[1], proto->cc[2])) <= 0)
+ *com = 0;
+
+ hit = (notice || options) ? 0 : 0x02;
+ pragma = -1;
+ s = proto->ip;
+ m = 80;
+ while (m-- > 0 && *s && hit != (0x01|0x02))
+ {
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (*s == '#')
+ {
+ b = s++;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (*s == *"pragma"&& !sstrncmp( s, "pragma", sizeof("pragma") - 1) && (*(s += sizeof("pragma") - 1) == ' ' || *s == '\t'))
+ {
+ clr = 0;
+ while (*s && *s != '\r' && *s != '\n')
+ {
+ for (; *s == ' ' || *s == '\t'; s++);
+ for (t = s; *s && *s != ' ' && *s != '\t' && *s != '\r' && *s != '\n'; s++);
+ z = s - t;
+ for (i = 0; i < (sizeof( pragmas)/sizeof( pragmas[0])); i++)
+ if (pragmas[i].size == z && !sstrncmp( t, pragmas[i].name, z))
+ {
+ clr = 1;
+ hit |= pragmas[i].hit;
+ switch (pragmas[i].hit)
+ {
+ case 0x02:
+ notice = options = 0;
+ break;
+ case 0x01:
+ pragma = pragmas[i].val;
+ break;
+ }
+ }
+ }
+ if (clr)
+ {
+
+ if (!(flags & (1<<1)) || (flags & (1<<8)))
+
+ for (; b < s; *b++ = ' ');
+ }
+ }
+ }
+ else if (*s == *"/* : : generated by proto : : */\n"&& !sstrncmp( s, "/* : : generated by proto : : */\n", sizeof("/* : : generated by proto : : */\n") - 1))
+ {
+ pragma = 0;
+ break;
+ }
+
+ else if (*s == '%' && *(s + 1) == '{')
+ proto->flags |= (1L<<29);
+ else if (!(hit & 0x02))
+ {
+ if (*s == *com && !sstrncmp( s, com, comlen))
+ {
+ hit |= 0x02;
+ notice = options = 0;
+ }
+ else
+ for (; *s && *s != '\n' && !(hit & 0x02); s++)
+ for (i = 0; i < (sizeof( notices)/sizeof( notices[0])); i++)
+ if (*s == notices[i].name[0] && !sstrncmp( s, notices[i].name, notices[i].size))
+ {
+ s += notices[i].size;
+ if (notices[i].val)
+ {
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (*s == '(' && (*(s + 1) == 'c' || *(s + 1) == 'C') && *(s + 2) == ')' || *s >= '0' && *s <= '9' && *(s + 1) >= '0' && *(s + 1) <= '9')
+ {
+ hit |= notices[i].hit;
+ notice = options = 0;
+ }
+ }
+ else
+ {
+ hit |= notices[i].hit;
+ notice = options = 0;
+ }
+ break;
+ }
+ }
+
+ while (*s && *s++ != '\n');
+ }
+ if (flags & (1<<10)) proto->flags |= (1L<<20);
+ if (flags & (1<<12)) proto->test = 1;
+ if (flags & (1<<2)) proto->options |= (1L<<6);
+
+ if (flags & (1<<0)) pragma = -pragma;
+ if (flags & (1<<1)) pragma = 0;
+ if (flags & (1<<7)) proto->flags |= (1L<<13);
+ if (!(proto->flags & (1L<<29)) && file && (m = sstrlen( file)) > 2 && file[--m] == 'y' && file[--m] == '.')
+ proto->flags |= (1L<<29);
+
+ if (pragma <= 0)
+ {
+ if (flags & (1<<10))
+ {
+ flags &= ~((1<<4)|(1<<5));
+ proto->flags |= (1L<<19);
+ }
+ else if (!(flags & ((1<<3)|(1<<9))))
+ {
+ pppclose(iob);
+ return 0;
+ }
+ else if ((flags & ((1<<3)|(1<<9))) == (1<<9) || !pragma)
+ {
+ proto->flags |= (1L<<18);
+ if (proto->flags & (1L<<16))
+ proto->oz += proto->iz;
+ proto->iz = n;
+ if (notice || options)
+ {
+ if (proto->cc[0] == '#' && proto->ip[0] == '#' && proto->ip[1] == '!')
+ {
+ s = proto->ip;
+ while (*s && *s++ != '\n');
+ m = s - proto->ip;
+ proto->op = memcopy(proto->op, proto->ip, m);
+ proto->ip = s;
+ proto->iz = n -= m;
+ }
+
+ if (proto->cc[0])
+ {
+ if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
+ proto_error((char*)proto + sizeof(Proto_t), 1, proto->op, ((char*)0));
+ else
+ proto->op += comlen;
+ }
+ if (!(flags & (1<<0)) && !(proto->flags & (1L<<29)))
+
+ proto->op = linesync(proto, proto->op, 1);
+ proto->iz += proto->op - proto->ob;
+ }
+ memcopy(proto->op, proto->ip, n);
+ return iob;
+ }
+ }
+
+ if (!(retain & (1<<6)))
+ {
+ retain |= (1<<6);
+ ppfsm(4, ((char*)0));
+ }
+
+ proto->line = 1;
+
+ if (notice || options || (flags & ((1<<4)|(1<<5))))
+ {
+
+ if (notice || options)
+ {
+ if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
+ proto_error((char*)proto + sizeof(Proto_t), 1, proto->op, ((char*)0));
+ else
+ proto->op += comlen;
+ }
+
+ if (flags & (1<<5))
+ {
+ proto->flags |= (1L<<11);
+ if (flags & (1<<11))
+ retain |= (1<<5);
+ }
+ else if (flags & (1<<4))
+ {
+ if (flags & (1<<11)) retain |= (1<<4);
+
+ if (flags & (1<<0))
+ {
+ *proto->op++ = '#';
+ proto->op = strcopy(proto->op, "pragma");
+ *proto->op++ = ' ';
+ proto->op = strcopy(proto->op, pragmas[0].name);
+ *proto->op++ = '\n';
+ }
+ else
+
+ proto->flags |= (1L<<10);
+ }
+
+ if (!(flags & (1<<0)))
+ {
+ if (proto->flags & (1L<<29))
+ {
+ proto->op = strcopy(proto->op, "\n%{\n"+ !notice);
+ proto->op = strcopy(proto->op, "/* : : generated by proto : : */\n");
+ proto->op = strcopy(proto->op, "%}\n");
+ }
+ else
+ {
+ if (n || notice || options)
+ *proto->op++ = '\n';
+ proto->op = strcopy(proto->op, "/* : : generated by proto : : */\n");
+ if (n)
+ proto->op = linesync(proto, proto->op, proto->line);
+ else if (proto->flags & ((1L<<10)|(1L<<11)))
+ proto->op = init(proto, proto->op, proto->flags);
+ }
+ }
+
+ }
+
+
+ proto->file = file;
+ if (flags & (1<<0))
+ {
+ proto->flags |= (1L<<0);
+ if (!(flags & (1<<4))) proto->flags |= (1L<<5);
+ }
+
+ return iob;
+}
+
+
+
+
+
+
+int
+pppread __PARAM__((char* iob), (iob)) __OTORP__(char* iob;){
+ register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t));
+ register int n;
+
+ if (proto->flags & (1L<<18))
+ {
+ if (proto->iz)
+ {
+ n = proto->iz;
+ proto->iz = 0;
+ }
+ else if (!(proto->flags & (1L<<16))) n = 0;
+ else if ((n = read(proto->fd, proto->ob, proto->oz)) <= 0 || (proto->options & (1L<<0)) && n < proto->oz)
+ {
+ proto->flags &= ~(1L<<16);
+ close(proto->fd);
+ }
+ }
+ else
+ {
+ if (proto->op == proto->ob)
+ {
+ if (proto->flags & (1L<<4)) return -1;
+
+ if (proto->flags & (1L<<29))
+ {
+ register char* ip = proto->ip;
+ register char* op = proto->ob;
+ register char* ep = proto->ob + proto->oz - 2;
+
+ if (!*ip)
+ {
+ ip = proto->ip = proto->ib;
+ if (!(proto->flags & (1L<<16))) n = 0;
+ else if ((n = read(proto->fd, ip, proto->iz)) <= 0 || (proto->options & (1L<<0)) && n < proto->iz)
+ {
+ if (n < 0) n = 0;
+ proto->flags &= ~(1L<<16);
+ close(proto->fd);
+ }
+ ip[n] = 0;
+ }
+ if (proto->flags & (1L<<30))
+ {
+ proto->flags &= ~(1L<<30);
+ if (*ip == '%')
+ {
+ *op++ = *ip++;
+ if (proto->flags & (1L<<31)) proto->flags &= ~(1L<<29);
+ else proto->flags |= (1L<<31);
+ }
+ }
+ if (proto->flags & (1L<<29))
+ while (op < ep && (n = *op++ = *ip))
+ {
+ ip++;
+ if (n == '%')
+ {
+ if (*ip == '%' && (ip == proto->ip + 1 || *(ip - 2) == '\n'))
+ {
+ *op++ = *ip++;
+ if (proto->flags & (1L<<31)) proto->flags &= ~(1L<<29);
+ else proto->flags |= (1L<<31);
+ break;
+ }
+ if (!*ip)
+ {
+ *op++ = '%';
+ proto->flags |= (1L<<30);
+ break;
+ }
+ }
+ else if (n == '\n') proto->line++;
+ }
+ proto->op = memcopy(proto->ob, proto->ip, ip - proto->ip);
+ proto->ip = ip;
+ }
+ else
+
+ lex(proto, proto->flags);
+ if ((proto->flags & ((1L<<4)|(1L<<16))) == (1L<<4))
+ proto->op = strcopy(proto->op, "/* NOTE: some constructs may not have been converted */\n");
+ }
+ n = proto->op - proto->ob;
+ proto->op = proto->ob;
+ }
+ return n;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+#line 269 "proto.c"
+
+
+
+
+
+static int
+proto __PARAM__((char* file, char* license, char* options, char* package, char* copy, char* comment, int flags), (file, license, options, package, copy, comment, flags)) __OTORP__(char* file; char* license; char* options; char* package; char* copy; char* comment; int flags;){
+ char* b;
+ char* e;
+ char* p;
+ int n;
+ int m;
+ int x;
+ int fd;
+ char buf[1024];
+
+ if (file && access(file, 4))
+ proto_error(((char*)0), 2, file, "not found");
+ else if (b = pppopen(file, 0, license, options, package, comment, flags))
+ {
+ if (!file)
+ fd = 1;
+ else if (flags & ((1<<13)<<1))
+ {
+ e = file + sstrlen( file) - 1;
+ x = *e;
+ *e = '_';
+ if ((fd = creat(file, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
+ {
+ proto_error(b, 2, file, "cannot create temporary file");
+ pppclose(b);
+ return flags | ((1<<13)<<0);
+ }
+ *e = x;
+ }
+ else if (copy)
+ {
+ if (((n = sstrlen( copy)) + sstrlen( file) + 2) > sizeof(buf))
+ {
+ proto_error(b, 2, copy, "copy path too long");
+ pppclose(b);
+ return flags | ((1<<13)<<0);
+ }
+ strcopy( buf, copy);
+ e = buf + n;
+ if (*file != '/')
+ *e++ = '/';
+ strcopy( e, file);
+ if ((fd = creat(buf, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
+ {
+ for (e = buf; *e == '/'; e++);
+ do
+ {
+ if (*e == '/')
+ {
+ *e = 0;
+ if (access(buf, 0) && mkdir(buf, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH))
+ {
+ proto_error(b, 2, buf, "cannot create copy directory");
+ pppclose(b);
+ return flags | ((1<<13)<<0);
+ }
+ *e = '/';
+ }
+ } while (*e++);
+ if ((fd = creat(buf, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
+ {
+ proto_error(b, 2, buf, "cannot create copy file");
+ pppclose(b);
+ return flags | ((1<<13)<<0);
+ }
+ }
+ file = buf;
+ }
+ else
+ fd = 1;
+ if (file && (flags & ((1<<13)<<2)))
+ proto_error(b, 0, "convert to", file);
+ while ((n = pppread(b)) > 0)
+ {
+ p = b;
+ for (;;)
+ {
+ if ((m = write(fd, p, n)) <= 0)
+ {
+ proto_error(b, 2, "write error", ((char*)0));
+ flags |= ((1<<13)<<0);
+ break;
+ }
+ if ((n -= m) <= 0)
+ break;
+ p += m;
+ }
+ if (m < 0)
+ break;
+ }
+ if (fd > 1)
+ close(fd);
+ if (file && (flags & ((1<<13)<<1)))
+ {
+ *e = '_';
+ strcopy( b, file);
+ *e = x;
+ if (replace(b, file, !(flags & (1<<0))))
+ proto_error(b, 2, "cannot rename to", file);
+ }
+ pppclose(b);
+ }
+ return flags;
+}
+
+
+
+
+
+typedef struct Sufcom_s
+{
+ char suffix[4];
+ char comment[4];
+} Sufcom_t;
+
+static const Sufcom_t sufcom[] =
+{
+ "c", "/*",
+ "cpp", "/*",
+ "cxx", "/*",
+ "c++", "/*",
+ "C", "/*",
+ "CPP", "/*",
+ "CXX", "/*",
+ "C++", "/*",
+ "f", "C",
+ "F", "C",
+ "h", "/*",
+ "hpp", "/*",
+ "hxx", "/*",
+ "H", "/*",
+ "HPP", "/*",
+ "HXX", "/*",
+ "ksh", "#",
+ "KSH", "#",
+ "l", "/*",
+ "L", "/*",
+ "p", "(*)",
+ "pas", "(*)",
+ "P", "(*)",
+ "PAS", "(*)",
+ "pl", "#",
+ "PL", "#",
+ "pl1", "/*",
+ "pli", "/*",
+ "PL1", "/*",
+ "PLI", "/*",
+ "sh", "#",
+ "SH", "#",
+ "sml", "(*)",
+ "SML", "(*)",
+ "y", "/*",
+ "Y", "/*",
+};
+
+
+
+
+
+static char*
+type __PARAM__((register char* file, char* comment), (file, comment)) __OTORP__(register char* file; char* comment;){
+ register char* suffix;
+ register int i;
+
+ if (file && (!comment || !*comment))
+ {
+ suffix = 0;
+ while (*file)
+ if (*file++ == '.')
+ suffix = file;
+ if (suffix && sstrlen( suffix) <= 3)
+ for (i = 0; i < sizeof(sufcom) / sizeof(sufcom[0]); i++)
+ if (!strcmp(suffix, sufcom[i].suffix))
+ return (char*)sufcom[i].comment;
+ }
+ return comment;
+}
+
+int
+main __PARAM__((int argc, char** argv), (argc, argv)) __OTORP__(int argc; char** argv;){
+ char* b;
+ char* file;
+ int fd;
+ int n;
+ char* op;
+ char* oe;
+ char* comment = 0;
+ char* copy = 0;
+ char* list = 0;
+ char* license = 0;
+ char* options = 0;
+ char* package = 0;
+ int flags = (1<<4);
+ char buf[1024];
+ char opt[4 * 1024];
+
+ ;
+
+ while ((file = *++argv) && *file == '-' && *(file + 1))
+ {
+ for (;;)
+ {
+ switch (*++file)
+ {
+ case 0:
+ break;
+ case 'c':
+ if (!*(comment = ++file))
+ comment = *++argv;
+ break;
+ case 'd':
+ flags |= (1<<1);
+ continue;
+ case 'e':
+ if (!*(package = ++file) && !(package = *++argv))
+ {
+ file = "??";
+ continue;
+ }
+ break;
+ case 'f':
+ flags |= (1<<3);
+ continue;
+ case 'h':
+ flags &= ~(1<<4);
+ continue;
+ case 'i':
+ flags |= (1<<0);
+ continue;
+ case 'l':
+ if (!*(license = ++file) && !(license = *++argv))
+ {
+ file = "??";
+ continue;
+ }
+ break;
+ case 'n':
+ flags |= (1<<7);
+ continue;
+ case 'o':
+ if (!*(b = ++file) && !(b = *++argv))
+ {
+ file = "??";
+ continue;
+ }
+ if (!options)
+ {
+ options = op = opt;
+ oe = op + sizeof(opt) - 1;
+ }
+ n = sstrlen( b);
+ if ((n + 1) >= (oe - op))
+ proto_error(((char*)0), 3, b, "too many options");
+ else
+ {
+ *op++ = '\n';
+ memcopy( op, b, n + 1);
+ op += n;
+ }
+ break;
+ case 'p':
+ flags |= (1<<9);
+ continue;
+ case 'r':
+ flags |= ((1<<13)<<1);
+ continue;
+ case 's':
+ flags |= (1<<5);
+ continue;
+ case 't':
+ flags |= (1<<12);
+ continue;
+ case 'v':
+ flags |= ((1<<13)<<2);
+ continue;
+ case 'x':
+ flags |= (1<<2);
+ continue;
+ case 'z':
+ flags |= (1<<1)|(1<<8);
+ continue;
+ case 'C':
+ if (!*(copy = ++file) && !(copy = *++argv))
+ {
+ file = "??";
+ continue;
+ }
+ break;
+ case 'L':
+ if (!*(list = ++file) && !(list = *++argv))
+ {
+ file = "??";
+ continue;
+ }
+ break;
+ case 'P':
+ case '+':
+ flags |= (1<<10);
+ continue;
+ case 'S':
+ comment = "#";
+ continue;
+ default:
+ proto_error(((char*)0), 2, file, "unknown option");
+
+ case '?':
+ b = "Usage: proto [-dfhinprstvzP+S] [-C directory] [-e package] [-l file]\n [-o \"name='value' ...\"] [-L file] file ...\n";
+ write(2, b, sstrlen( b));
+ return 2;
+ }
+ break;
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if (list)
+ {
+ if (*list == '-' && !*(list + 1))
+ fd = 0;
+ else if ((fd = open(list, O_RDONLY)) < 0)
+ proto_error(((char*)0), 3, list, "not found");
+ do
+ {
+ for (b = buf; (n = read(fd, b, 1)) > 0 && *b != '\n' && b < &buf[sizeof(buf) - 1]; b++);
+ if (b > buf)
+ {
+ *b = 0;
+ flags = proto(buf, license, options, package, copy, type(buf, comment), flags);
+ }
+ } while (n > 0);
+ if (fd > 0)
+ close(fd);
+ }
+ if (file)
+ do flags = proto(file, license, options, package, copy, type(file, comment), flags); while (file = *++argv);
+ else if (!list)
+ flags = proto(file, license, options, package, copy, type(file, comment), flags);
+ return errors ? 1 : (flags & ((1<<13)<<0)) ? 2 : 0;
+}
diff --git a/src/cmd/INIT/ratz.c b/src/cmd/INIT/ratz.c
new file mode 100644
index 0000000..df7d1e3
--- /dev/null
+++ b/src/cmd/INIT/ratz.c
@@ -0,0 +1,5293 @@
+/*
+ * ratz -- read a tar gzip archive from the standard input
+ *
+ * coded for portability
+ * _SEAR_* macros for win32 self extracting archives -- see sear(1).
+ */
+
+static char id[] = "\n@(#)$Id: ratz (Jean-loup Gailly, Mark Adler, Glenn Fowler) 1.2.3 2010-10-10 $\0\n";
+
+#if _PACKAGE_ast
+
+#include <ast.h>
+#include <error.h>
+
+static const char usage[] =
+"[-?\n@(#)$Id: ratz (Jean-loup Gailly, Mark Adler, Glenn Fowler) 1.2.3 2010-10-10 $\n]"
+"[-author?Jean-loup Gailly]"
+"[-author?Mark Adler]"
+"[-author?Glenn Fowler <gsf@research.att.com>]"
+"[-copyright?Copyright (c) 1995-2005 Jean-loup Gailly and Mark Adler]"
+"[-license?http://www.opensource.org/licenses/zlib-license]"
+"[+NAME?ratz - read a tar gzip archive]"
+"[+DESCRIPTION?\bratz\b extracts files and directories from a tar gzip"
+" archive on the standard input. It is a standalone program for systems"
+" that do not have \bpax\b(1), \btar\b(1) or \bgunzip\b(1). Only regular"
+" files and directories are extracted; all other file types are ignored.]"
+"[+?\b.exe\b files generated by \bsear\b(1) are fully functional \bratz\b"
+" executables, so any \bratz\b option may be used on a \bsear\b file."
+" This allows \bsear\b file contents to be examined and extracted without"
+" executing any embedded installation scripts.]"
+"[c:cat|uncompress?Uncompress the standard input and copy it to the standard"
+" output.]"
+#if defined(_SEAR_EXEC)
+"[i!:install?Execute the sear installation script.]"
+#endif
+"[l:local?Reject files that traverse outside the current directory.]"
+"[m:meter?Display a one line text meter showing archive read progress.]"
+"[n!:convert?In ebcdic environments convert text archive members from ascii"
+" to the native ebcdic.]"
+"[t:list?List each file path on the standard output but do not extract.]"
+"[v:verbose?List each file path on the standard output as it is extracted.]"
+"[V?Print the program version and exit.]"
+"[+SEE ALSO?\bgunzip\b(1), \bpackage\b(1), \bpax\b(1), \bsear\b(1), \btar\b(1)]"
+;
+
+#else
+
+#define NiL ((char*)0)
+
+#endif
+
+#define METER_width 80
+#define METER_parts 20
+
+#ifndef _GUNZIP_H
+#define _GUNZIP_H 1
+
+/*
+ * stripped down zlib containing public gzfopen()+gzread() in one file
+ * USE THE REAL ZLIB AFTER BOOTSTRAP
+ */
+
+#define ZLIB_INTERNAL 1
+#define NO_GZCOMPRESS 1
+
+#define gz_headerp voidp
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#if _PACKAGE_ast || defined(__STDC__) || defined(_SEAR_EXEC) || defined(_WIN32)
+
+#define FOPEN_READ "rb"
+#define FOPEN_WRITE "wb"
+
+#else
+
+#define FOPEN_READ "r"
+#define FOPEN_WRITE "w"
+
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#if _PACKAGE_ast
+
+#define setmode(d,m)
+
+#else
+
+#if !defined(_WINIX) && (_UWIN || __CYGWIN__ || __EMX__)
+#define _WINIX 1
+#endif
+
+#if _WIN32 && !_WINIX
+
+#include <direct.h>
+#include <io.h>
+#include <fcntl.h>
+#include <windows.h>
+
+#define access _access
+#define chmod _chmod
+#define close _close
+#define dup _dup
+#define lseek _lseek
+#define open _open
+#define read _read
+#define setmode _setmode
+#define unlink _unlink
+
+#define mkdir(a,b) _mkdir(a)
+
+#else
+
+#define HAVE_UNISTD_H 1
+
+#include <unistd.h>
+#include <errno.h>
+
+#define setmode(d,m)
+
+#endif
+
+#if defined(__STDC__)
+
+#include <stdlib.h>
+#include <string.h>
+
+#endif
+
+#endif
+
+#ifndef _ZLIB_H
+#define _ZLIB_H 1
+
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.3, July 18th, 2005
+
+ Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZCONF_H
+#define _ZCONF_H 1
+
+#if _PACKAGE_ast
+#include <ast_std.h> /* for { _WINIX __IMPORT__ __EXPORT__ } */
+#define z_off_t int32_t
+#if _typ_int64_t
+#define z_off64_t int64_t
+#endif
+#else
+#if !defined(_WINIX) && (_UWIN || __CYGWIN__ || __EMX__)
+#define _WINIX 1
+#endif
+#endif
+
+#if _BLD_z && defined(__EXPORT__)
+#define ZEXTERN __EXPORT__
+#define ZEXPORT
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if HAVE_UNISTD_H
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if defined(__OS400__)
+# define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+# define NO_vsnprintf
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(deflateBound,"DEBND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(compressBound,"CMBND")
+# pragma map(inflate_table,"INTABL")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* _ZCONF_H */
+
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip streams in memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+#endif /* _ZLIB_H */
+
+#ifndef _ZUTIL_H
+#define _ZUTIL_H 1
+
+#if !_PACKAGE_ast && !defined(STDC)
+#if defined(__STDC__)
+# include <stddef.h>
+#endif
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+# define OS_CODE 0x00
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# include <malloc.h>
+# endif
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 0x01
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 0x02
+# define F_OPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 0x05
+#endif
+
+#ifdef OS2
+# define OS_CODE 0x06
+# ifdef M_I86
+ #include <malloc.h>
+# endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+# define OS_CODE 0x07
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
+# endif
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#ifdef WIN32
+# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
+# define OS_CODE 0x0b
+# endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define OS_CODE 0x0f
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+# if defined(_WIN32_WCE)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# ifndef _PTRDIFF_T_DEFINED
+ typedef int ptrdiff_t;
+# define _PTRDIFF_T_DEFINED
+# endif
+# else
+# define fdopen(fd,type) _fdopen(fd,type)
+# endif
+#endif
+
+ /* common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+#if defined(__CYGWIN__)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+#ifndef HAVE_VSNPRINTF
+# ifdef MSDOS
+ /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+ but for now we just assume it doesn't. */
+# define NO_vsnprintf
+# endif
+# ifdef __TURBOC__
+# define NO_vsnprintf
+# endif
+# ifdef WIN32
+ /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+# if !defined(vsnprintf) && !defined(NO_vsnprintf)
+# define vsnprintf _vsnprintf
+# endif
+# endif
+# ifdef __SASC
+# define NO_vsnprintf
+# endif
+#endif
+#ifdef VMS
+# define NO_vsnprintf
+#endif
+
+#if defined(pyr)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+ extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef Z_DEBUG
+# include <stdio.h>
+ extern int z_verbose;
+ extern void z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void zcfree OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+#endif /* _ZUTIL_H */
+
+#ifndef _ZUTIL_C
+#define _ZUTIL_C
+
+#if 0 && !_PACKAGE_ast && !defined(STDC)
+extern void exit OF((int));
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+ Bytef* dest;
+ const Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+ const Bytef* s1;
+ const Bytef* s2;
+ uInt len;
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void zmemzero(dest, len)
+ Bytef* dest;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf = opaque; /* just to make some compilers happy */
+ ulg bsize = (ulg)items*size;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ int n;
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ ptr = opaque; /* just to make some compilers happy */
+ Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ return _halloc((long)items, size);
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#if 0 && !_PACKAGE_ast
+#ifndef STDC
+extern voidp malloc OF((uInt size));
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
+#endif
+#endif
+
+voidpf zcalloc (opaque, items, size)
+ voidpf opaque;
+ unsigned items;
+ unsigned size;
+{
+ if (opaque) items += size - size; /* make compiler happy */
+ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+ (voidpf)calloc(items, size);
+}
+
+void zcfree (opaque, ptr)
+ voidpf opaque;
+ voidpf ptr;
+{
+ free(ptr);
+ if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
+
+#endif /* _ZUTIL_C */
+
+#ifndef _CRC32_H
+#define _CRC32_H 1
+
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+#ifndef TBLS
+#define TBLS 1
+#endif
+
+local const unsigned long FAR crc_table[TBLS][256] =
+{
+ {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d
+ },
+};
+
+#endif /* _CRC32_H */
+
+#ifndef _CRC32_C
+#define _CRC32_C 1
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ if (buf == Z_NULL) return 0;
+
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+ if (sizeof(void *) == sizeof(ptrdiff_t)) {
+ u4 endian;
+
+ endian = 1;
+ if (*((unsigned char *)(&endian)))
+ return crc32_little(crc, buf, len);
+ else
+ return crc32_big(crc, buf, len);
+ }
+#endif /* BYFOUR */
+ crc = crc ^ 0xffffffff;
+ while (len >= 8) {
+ DO8;
+ len -= 8;
+ }
+ if (len) do {
+ DO1;
+ } while (--len);
+ return crc ^ 0xffffffff;
+}
+
+#undef DO1
+#undef DO8
+
+#endif /* _CRC32_C */
+
+#ifndef _ADLER32_C
+#define _ADLER32_C 1
+
+#define BASE 65521 /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware */
+#ifdef NO_DIVIDE
+# define MOD(a) \
+ do { \
+ if (a >= (BASE << 16)) a -= (BASE << 16); \
+ if (a >= (BASE << 15)) a -= (BASE << 15); \
+ if (a >= (BASE << 14)) a -= (BASE << 14); \
+ if (a >= (BASE << 13)) a -= (BASE << 13); \
+ if (a >= (BASE << 12)) a -= (BASE << 12); \
+ if (a >= (BASE << 11)) a -= (BASE << 11); \
+ if (a >= (BASE << 10)) a -= (BASE << 10); \
+ if (a >= (BASE << 9)) a -= (BASE << 9); \
+ if (a >= (BASE << 8)) a -= (BASE << 8); \
+ if (a >= (BASE << 7)) a -= (BASE << 7); \
+ if (a >= (BASE << 6)) a -= (BASE << 6); \
+ if (a >= (BASE << 5)) a -= (BASE << 5); \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+# define MOD4(a) \
+ do { \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+#else
+# define MOD(a) a %= BASE
+# define MOD4(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+ uLong adler;
+ const Bytef *buf;
+ uInt len;
+{
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD4(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ DO16(buf);
+ buf += 16;
+ }
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+#endif /* _ADLER32_C */
+
+#ifndef _DEFLATE_H
+#define _DEFLATE_H 1
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE 42
+#define EXTRA_STATE 69
+#define NAME_STATE 73
+#define COMMENT_STATE 91
+#define HCRC_STATE 103
+#define BUSY_STATE 113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ uInt pending; /* nb of bytes in the pending buffer */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ uInt gzindex; /* where in extra, name, or comment */
+ Byte method; /* STORED (for zip only) or DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to supress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *l_buf; /* buffer for literals or lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt last_lit; /* running index in l_buf */
+
+ ushf *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uInt matches; /* number of string matches in current block */
+ int last_eob_len; /* bit length of EOB code for last block */
+
+#ifdef Z_DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+ /* in trees.c */
+void _tr_init OF((deflate_state *s));
+int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+void _tr_align OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+
+#define d_code(dist) \
+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef Z_DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+ extern uch _length_code[];
+ extern uch _dist_code[];
+#else
+ extern const uch _length_code[];
+ extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->d_buf[s->last_lit] = 0; \
+ s->l_buf[s->last_lit++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (length); \
+ ush dist = (distance); \
+ s->d_buf[s->last_lit] = dist; \
+ s->l_buf[s->last_lit++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+ flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* _DEFLATE_H */
+
+#ifndef _INFTREES_H
+#define _INFTREES_H 1
+
+typedef struct {
+ unsigned char op; /* operation, extra bits, table bits */
+ unsigned char bits; /* bits in this part of the code */
+ unsigned short val; /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+ 00000000 - literal
+ 0000tttt - table link, tttt != 0 is the number of table index bits
+ 0001eeee - length or distance, eeee is the number of extra bits
+ 01100000 - end of block
+ 01000000 - invalid code
+ */
+
+/* Maximum size of dynamic tree. The maximum found in a long but non-
+ exhaustive search was 1444 code structures (852 for length/literals
+ and 592 for distances, the latter actually the result of an
+ exhaustive search). The true maximum is not known, but the value
+ below is more than safe. */
+#define ENOUGH 2048
+#define MAXD 592
+
+/* Type of code to build for inftable() */
+typedef enum {
+ CODES,
+ LENS,
+ DISTS
+} codetype;
+
+#endif /* _INFTREES_H */
+
+#ifndef _INFLATE_H
+#define _INFLATE_H 1
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+ HEAD, /* i: waiting for magic header */
+ FLAGS, /* i: waiting for method and flags (gzip) */
+ TIME, /* i: waiting for modification time (gzip) */
+ OS, /* i: waiting for extra flags and operating system (gzip) */
+ EXLEN, /* i: waiting for extra length (gzip) */
+ EXTRA, /* i: waiting for extra bytes (gzip) */
+ NAME, /* i: waiting for end of file name (gzip) */
+ COMMENT, /* i: waiting for end of comment (gzip) */
+ HCRC, /* i: waiting for header crc (gzip) */
+ DICTID, /* i: waiting for dictionary check value */
+ DICT, /* waiting for inflateSetDictionary() call */
+ TYPE, /* i: waiting for type bits, including last-flag bit */
+ TYPEDO, /* i: same, but skip check to exit inflate on new block */
+ STORED, /* i: waiting for stored size (length and complement) */
+ COPY, /* i/o: waiting for input or output to copy stored block */
+ TABLE, /* i: waiting for dynamic block table lengths */
+ LENLENS, /* i: waiting for code length code lengths */
+ CODELENS, /* i: waiting for length/lit and distance code lengths */
+ LEN, /* i: waiting for length/lit code */
+ LENEXT, /* i: waiting for length extra bits */
+ DIST, /* i: waiting for distance code */
+ DISTEXT, /* i: waiting for distance extra bits */
+ MATCH, /* o: waiting for output space to copy string */
+ LIT, /* o: waiting for output space to write literal */
+ CHECK, /* i: waiting for 32-bit check value */
+ LENGTH, /* i: waiting for 32-bit length (gzip) */
+ DONE, /* finished check, done -- remain here until reset */
+ BAD, /* got a data error -- remain here until reset */
+ MEM, /* got an inflate() memory error -- remain here until reset */
+ SYNC /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+ State transitions between above modes -
+
+ (most modes can go to the BAD or MEM mode -- not shown for clarity)
+
+ Process header:
+ HEAD -> (gzip) or (zlib)
+ (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
+ NAME -> COMMENT -> HCRC -> TYPE
+ (zlib) -> DICTID or TYPE
+ DICTID -> DICT -> TYPE
+ Read deflate blocks:
+ TYPE -> STORED or TABLE or LEN or CHECK
+ STORED -> COPY -> TYPE
+ TABLE -> LENLENS -> CODELENS -> LEN
+ Read deflate codes:
+ LEN -> LENEXT or LIT or TYPE
+ LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+ LIT -> LEN
+ Process trailer:
+ CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls. Approximately 7K bytes. */
+struct inflate_state {
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags (0 if zlib) */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+};
+#endif /* _INFLATE_H */
+
+#ifndef _INFTREES_C
+#define _INFTREES_C 1
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+ " inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+ */
+int inflate_table(type, lens, codes, table, bits, work)
+codetype type;
+unsigned short FAR *lens;
+unsigned codes;
+code FAR * FAR *table;
+unsigned FAR *bits;
+unsigned short FAR *work;
+{
+ unsigned len; /* a code's length in bits */
+ unsigned sym; /* index of code symbols */
+ unsigned min, max; /* minimum and maximum code lengths */
+ unsigned root; /* number of index bits for root table */
+ unsigned curr; /* number of index bits for current table */
+ unsigned drop; /* code bits to drop for sub-table */
+ int left; /* number of prefix codes available */
+ unsigned used; /* code entries in table used */
+ unsigned huff; /* Huffman code */
+ unsigned incr; /* for incrementing code, index */
+ unsigned fill; /* index for replicating entries */
+ unsigned low; /* low bits for current root entry */
+ unsigned mask; /* mask for low root bits */
+ code this; /* table entry for duplication */
+ code FAR *next; /* next available space in table */
+ const unsigned short FAR *base; /* base value table to use */
+ const unsigned short FAR *extra; /* extra bits table to use */
+ int end; /* use base and extra for symbol > end */
+ unsigned short count[MAXBITS+1]; /* number of codes of each length */
+ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
+ static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
+ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0};
+ static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64};
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = *bits;
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) { /* no symbols to code at all */
+ this.op = (unsigned char)64; /* invalid code marker */
+ this.bits = (unsigned char)1;
+ this.val = (unsigned short)0;
+ *(*table)++ = this; /* make a table to force an error */
+ *(*table)++ = this;
+ *bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min <= MAXBITS; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1))
+ return -1; /* incomplete set */
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked when a LENS table is being made
+ against the space in *table, ENOUGH, minus the maximum space needed by
+ the worst case distance code, MAXD. This should never happen, but the
+ sufficiency of ENOUGH has not been proven exhaustively, hence the check.
+ This assumes that when type == LENS, bits == 9.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ end = 19;
+ break;
+ case LENS:
+ base = lbase;
+ base -= 257;
+ extra = lext;
+ extra -= 257;
+ end = 256;
+ break;
+ default: /* DISTS */
+ base = dbase;
+ extra = dext;
+ end = -1;
+ }
+
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = *table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = (unsigned)(-1); /* trigger new sub-table when len > root */
+ used = ((unsigned int)1) << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ this.bits = (unsigned char)(len - drop);
+ if ((int)(work[sym]) < end) {
+ this.op = (unsigned char)0;
+ this.val = work[sym];
+ }
+ else if ((int)(work[sym]) > end) {
+ this.op = (unsigned char)(extra[work[sym]]);
+ this.val = base[work[sym]];
+ }
+ else {
+ this.op = (unsigned char)(32 + 64); /* end of block */
+ this.val = 0;
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = ((unsigned int)1) << (len - drop);
+ fill = ((unsigned int)1) << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ next[(huff >> drop) + fill] = this;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = ((unsigned int)1) << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (int)(1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += ((unsigned int)1) << curr;
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ (*table)[low].op = (unsigned char)curr;
+ (*table)[low].bits = (unsigned char)root;
+ (*table)[low].val = (unsigned short)(next - *table);
+ }
+ }
+
+ /*
+ Fill in rest of table for incomplete codes. This loop is similar to the
+ loop above in incrementing huff for table indices. It is assumed that
+ len is equal to curr + drop, so there is no loop needed to increment
+ through high index bits. When the current sub-table is filled, the loop
+ drops back to the root table to fill in any remaining entries there.
+ */
+ this.op = (unsigned char)64; /* invalid code marker */
+ this.bits = (unsigned char)(len - drop);
+ this.val = (unsigned short)0;
+ while (huff != 0) {
+ /* when done with sub-table, drop back to root table */
+ if (drop != 0 && (huff & mask) != low) {
+ drop = 0;
+ len = root;
+ next = *table;
+ this.bits = (unsigned char)len;
+ }
+
+ /* put invalid code marker in table */
+ next[huff >> drop] = this;
+
+ /* backwards increment the len-bit code huff */
+ incr = ((unsigned int)1) << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+ }
+
+ /* set return parameters */
+ *table += used;
+ *bits = root;
+ return 0;
+}
+
+#endif /* _INFTREES_C */
+
+#ifndef _INFFAST_C
+#define _INFFAST_C 1
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+ Based on testing to date,
+ Pre-increment preferred for:
+ - PowerPC G3 (Adler)
+ - MIPS R5000 (Randers-Pehrson)
+ Post-increment preferred for:
+ - none
+ No measurable difference:
+ - Pentium III (Anderson)
+ - M68060 (Nikl)
+ */
+#undef OFF /* (ancient) sunos <locale.h> */
+#ifdef POSTINC
+# define OFF 0
+# define PUP(a) *(a)++
+#else
+# define OFF 1
+# define PUP(a) *++(a)
+#endif
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+void inflate_fast(strm, start)
+z_streamp strm;
+unsigned start; /* inflate()'s starting value for strm->avail_out */
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *in; /* local strm->next_in */
+ unsigned char FAR *last; /* while in < last, enough input available */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ unsigned long hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code this; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in - OFF;
+ last = in + (strm->avail_in - 5);
+ out = strm->next_out - OFF;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ write = state->write;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (((unsigned int)1) << state->lenbits) - 1;
+ dmask = (((unsigned int)1) << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ this = lcode[hold & lmask];
+ dolen:
+ op = (unsigned)(this.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(this.op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", this.val));
+ PUP(out) = (unsigned char)(this.val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(this.val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ len += (unsigned)hold & ((((unsigned int)1) << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ this = dcode[hold & dmask];
+ dodist:
+ op = (unsigned)(this.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(this.op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(this.val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ }
+ dist += (unsigned)hold & ((((unsigned int)1) << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ from = window - OFF;
+ if (write == 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ else if (write < op) { /* wrap around window */
+ from += wsize + write - op;
+ op -= write;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = window - OFF;
+ if (write < len) { /* some from start of window */
+ op = write;
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += write - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ while (len > 2) {
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ }
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ else {
+ from = out - dist; /* copy direct from output */
+ do { /* minimum length is three */
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ } while (len > 2);
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ this = dcode[this.val + (hold & ((((unsigned int)1) << op) - 1))];
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ this = lcode[this.val + (hold & ((((unsigned int)1) << op) - 1))];
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (((unsigned int)1) << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in + OFF;
+ strm->next_out = out + OFF;
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and write == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* _INFFAST_C */
+
+#ifndef _INFLATE_C
+#define _INFLATE_C 1
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, unsigned out));
+#ifdef BUILDFIXED
+ void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+ unsigned len));
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ strm->total_in = strm->total_out = state->total = 0;
+ strm->msg = Z_NULL;
+ strm->adler = 1; /* to support ill-conceived Java test suite */
+ state->mode = HEAD;
+ state->last = 0;
+ state->havedict = 0;
+ state->dmax = 32768;
+ state->head = Z_NULL;
+ state->wsize = 0;
+ state->whave = 0;
+ state->write = 0;
+ state->hold = 0;
+ state->bits = 0;
+ state->lencode = state->distcode = state->next = state->codes;
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+ value &= (1L << bits) - 1;
+ state->hold += value << state->bits;
+ state->bits += bits;
+ return Z_OK;
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+ state = (struct inflate_state FAR *)
+ ZALLOC(strm, 1, sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ if (windowBits < 0) {
+ state->wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ state->wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+ if (windowBits < 48) windowBits &= 15;
+#endif
+ }
+ if (windowBits < 8 || windowBits > 15) {
+ ZFREE(strm, state);
+ strm->state = Z_NULL;
+ return Z_STREAM_ERROR;
+ }
+ state->wbits = (unsigned)windowBits;
+ state->window = Z_NULL;
+ return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+ return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifndef _INFFIXED_H
+#define _INFFIXED_H 1
+ static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+ };
+
+ static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+ };
+#endif /* _INFFIXED_H */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, out)
+z_streamp strm;
+unsigned out;
+{
+ struct inflate_state FAR *state;
+ unsigned copy, dist;
+
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state->window == Z_NULL) {
+ state->window = (unsigned char FAR *)
+ ZALLOC(strm, ((unsigned int)1) << state->wbits,
+ sizeof(unsigned char));
+ if (state->window == Z_NULL) return 1;
+ }
+
+ /* if window not in use yet, initialize */
+ if (state->wsize == 0) {
+ state->wsize = ((unsigned int)1) << state->wbits;
+ state->write = 0;
+ state->whave = 0;
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ copy = out - strm->avail_out;
+ if (copy >= state->wsize) {
+ zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+ state->write = 0;
+ state->whave = state->wsize;
+ }
+ else {
+ dist = state->wsize - state->write;
+ if (dist > copy) dist = copy;
+ zmemcpy(state->window + state->write, strm->next_out - copy, dist);
+ copy -= dist;
+ if (copy) {
+ zmemcpy(state->window, strm->next_out - copy, copy);
+ state->write = copy;
+ state->whave = state->wsize;
+ }
+ else {
+ state->write += dist;
+ if (state->write == state->wsize) state->write = 0;
+ if (state->whave < state->wsize) state->whave += dist;
+ }
+ }
+ return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE(check, buf, len) \
+ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+# define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+# define CRC2(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ check = crc32(check, hbuf, 2); \
+ } while (0)
+
+# define CRC4(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ hbuf[2] = (unsigned char)((word) >> 16); \
+ hbuf[3] = (unsigned char)((word) >> 24); \
+ check = crc32(check, hbuf, 4); \
+ } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ if (have == 0) goto inf_leave; \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((((unsigned int)1) << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Reverse the bytes in a 32-bit value */
+#define REVERSE(q) \
+ ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
+ break;
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned in, out; /* save starting available input and output */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code this; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+#ifdef GUNZIP
+ unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
+#endif
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0))
+ return Z_STREAM_ERROR;
+
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
+ LOAD();
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state->mode) {
+ case HEAD:
+ if (state->wrap == 0) {
+ state->mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ state->check = crc32(0L, Z_NULL, 0);
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = FLAGS;
+ break;
+ }
+ state->flags = 0; /* expect zlib header */
+ if (state->head != Z_NULL)
+ state->head->done = -1;
+ if (!(state->wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm->msg = (char *)"incorrect header check";
+ state->mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (len > state->wbits) {
+ strm->msg = (char *)"invalid window size";
+ state->mode = BAD;
+ break;
+ }
+ state->dmax = ((unsigned int)1) << len;
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state->flags = (int)(hold);
+ if ((state->flags & 0xff) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ if (state->flags & 0xe000) {
+ strm->msg = (char *)"unknown header flags set";
+ state->mode = BAD;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = TIME;
+ case TIME:
+ NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
+ if (state->flags & 0x0200) CRC4(state->check, hold);
+ INITBITS();
+ state->mode = OS;
+ case OS:
+ NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = EXLEN;
+ case EXLEN:
+ if (state->flags & 0x0400) {
+ NEEDBITS(16);
+ state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ }
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
+ state->mode = EXTRA;
+ case EXTRA:
+ if (state->flags & 0x0400) {
+ copy = state->length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL) {
+ len = state->head->extra_len - state->length;
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ state->length -= copy;
+ }
+ if (state->length) goto inf_leave;
+ }
+ state->length = 0;
+ state->mode = NAME;
+ case NAME:
+ if (state->flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
+ state->mode = COMMENT;
+ case COMMENT:
+ if (state->flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
+ state->mode = HCRC;
+ case HCRC:
+ if (state->flags & 0x0200) {
+ NEEDBITS(16);
+ if (hold != (state->check & 0xffff)) {
+ strm->msg = (char *)"header crc mismatch";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
+ strm->adler = state->check = crc32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm->adler = state->check = REVERSE(hold);
+ INITBITS();
+ state->mode = DICT;
+ case DICT:
+ if (state->havedict == 0) {
+ RESTORE();
+ return Z_NEED_DICT;
+ }
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ case TYPE:
+ if (flush == Z_BLOCK) goto inf_leave;
+ case TYPEDO:
+ if (state->last) {
+ BYTEBITS();
+ state->mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+ state->mode = COPY;
+ case COPY:
+ copy = state->length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state->have = 0;
+ state->mode = LENLENS;
+ case LENLENS:
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state->have = 0;
+ state->mode = CODELENS;
+ case CODELENS:
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ this = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (this.val < 16) {
+ NEEDBITS(this.bits);
+ DROPBITS(this.bits);
+ state->lens[state->have++] = this.val;
+ }
+ else {
+ if (this.val == 16) {
+ NEEDBITS(this.bits + 2);
+ DROPBITS(this.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = state->lens[state->have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (this.val == 17) {
+ NEEDBITS(this.bits + 3);
+ DROPBITS(this.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(this.bits + 7);
+ DROPBITS(this.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* build code tables */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ inflate_fast(strm, out);
+ LOAD();
+ break;
+ }
+ for (;;) {
+ this = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (this.op && (this.op & 0xf0) == 0) {
+ last = this;
+ for (;;) {
+ this = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(this.bits);
+ state->length = (unsigned)this.val;
+ if ((int)(this.op) == 0) {
+ Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", this.val));
+ state->mode = LIT;
+ break;
+ }
+ if (this.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ if (this.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ state->extra = (unsigned)(this.op) & 15;
+ state->mode = LENEXT;
+ case LENEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+ state->mode = DIST;
+ case DIST:
+ for (;;) {
+ this = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((this.op & 0xf0) == 0) {
+ last = this;
+ for (;;) {
+ this = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(this.bits);
+ if (this.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)this.val;
+ state->extra = (unsigned)(this.op) & 15;
+ state->mode = DISTEXT;
+ case DISTEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ if (state->offset > state->whave + out - left) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state->mode = MATCH;
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->write) {
+ copy -= state->write;
+ from = state->window + (state->wsize - copy);
+ }
+ else
+ from = state->window + (state->write - copy);
+ if (copy > state->length) copy = state->length;
+ }
+ else { /* copy from output */
+ from = put - state->offset;
+ copy = state->length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ case CHECK:
+ if (state->wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm->total_out += out;
+ state->total += out;
+ if (out)
+ strm->adler = state->check =
+ UPDATE(state->check, put - out, out);
+ out = left;
+ if ((
+#ifdef GUNZIP
+ state->flags ? hold :
+#endif
+ REVERSE(hold)) != state->check) {
+ strm->msg = (char *)"incorrect data check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state->mode = LENGTH;
+ case LENGTH:
+ if (state->wrap && state->flags) {
+ NEEDBITS(32);
+ if (hold != (state->total & 0xffffffff)) {
+ strm->msg = (char *)"incorrect length check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state->mode = DONE;
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ RESTORE();
+ if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
+ if (updatewindow(strm, out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm->avail_in;
+ out -= strm->avail_out;
+ strm->total_in += in;
+ strm->total_out += out;
+ state->total += out;
+ if (state->wrap && out)
+ strm->adler = state->check =
+ UPDATE(state->check, strm->next_out - out, out);
+ strm->data_type = state->bits + (state->last ? 64 : 0) +
+ (state->mode == TYPE ? 128 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->window != Z_NULL) ZFREE(strm, state->window);
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+ struct inflate_state FAR *state;
+ unsigned long id;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->wrap != 0 && state->mode != DICT)
+ return Z_STREAM_ERROR;
+
+ /* check for correct dictionary id */
+ if (state->mode == DICT) {
+ id = adler32(0L, Z_NULL, 0);
+ id = adler32(id, dictionary, dictLength);
+ if (id != state->check)
+ return Z_DATA_ERROR;
+ }
+
+ /* copy dictionary to window */
+ if (updatewindow(strm, strm->avail_out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ if (dictLength > state->wsize) {
+ zmemcpy(state->window, dictionary + dictLength - state->wsize,
+ state->wsize);
+ state->whave = state->wsize;
+ }
+ else {
+ zmemcpy(state->window + state->wsize - dictLength, dictionary,
+ dictLength);
+ state->whave = dictLength;
+ }
+ state->havedict = 1;
+ Tracev((stderr, "inflate: dictionary set\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+ /* save header structure */
+ state->head = head;
+#ifdef GUNZIP
+ head->done = 0;
+#endif
+ return Z_OK;
+}
+
+/*
+ Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
+ or when out of input. When called, *have is the number of pattern bytes
+ found in order so far, in 0..3. On return *have is updated to the new
+ state. If on return *have equals four, then the pattern was found and the
+ return value is how many bytes were read including the last byte of the
+ pattern. If *have is less than four, then the pattern has not been found
+ yet and the return value is len. In the latter case, syncsearch() can be
+ called again with more data and the *have state. *have is initialized to
+ zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+unsigned char FAR *buf;
+unsigned len;
+{
+ unsigned got;
+ unsigned next;
+
+ got = *have;
+ next = 0;
+ while (next < len && got < 4) {
+ if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+ got++;
+ else if (buf[next])
+ got = 0;
+ else
+ got = 4 - got;
+ next++;
+ }
+ *have = got;
+ return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+ unsigned len; /* number of bytes to look at or looked at */
+ unsigned long in, out; /* temporary to save total_in and total_out */
+ unsigned char buf[4]; /* to restore bit buffer to byte string */
+ struct inflate_state FAR *state;
+
+ /* check parameters */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+ /* if first time, start search in bit buffer */
+ if (state->mode != SYNC) {
+ state->mode = SYNC;
+ state->hold <<= state->bits & 7;
+ state->bits -= state->bits & 7;
+ len = 0;
+ while (state->bits >= 8) {
+ buf[len++] = (unsigned char)(state->hold);
+ state->hold >>= 8;
+ state->bits -= 8;
+ }
+ state->have = 0;
+ syncsearch(&(state->have), buf, len);
+ }
+
+ /* search available input */
+ len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+ strm->avail_in -= len;
+ strm->next_in += len;
+ strm->total_in += len;
+
+ /* return no joy or set up to restart inflate() on a new block */
+ if (state->have != 4) return Z_DATA_ERROR;
+ in = strm->total_in; out = strm->total_out;
+ inflateReset(strm);
+ strm->total_in = in; strm->total_out = out;
+ state->mode = TYPE;
+ return Z_OK;
+}
+
+/*
+ Returns true if inflate is currently at the end of a block generated by
+ Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ implementation to provide an additional safety check. PPP uses
+ Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+ block. When decompressing, PPP checks that at the end of input packet,
+ inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+ struct inflate_state FAR *state;
+ struct inflate_state FAR *copy;
+ unsigned char FAR *window;
+ unsigned wsize;
+
+ /* check input */
+ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
+ source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)source->state;
+
+ /* allocate space */
+ copy = (struct inflate_state FAR *)
+ ZALLOC(source, 1, sizeof(struct inflate_state));
+ if (copy == Z_NULL) return Z_MEM_ERROR;
+ window = Z_NULL;
+ if (state->window != Z_NULL) {
+ window = (unsigned char FAR *)
+ ZALLOC(source, ((unsigned int)1) << state->wbits, sizeof(unsigned char));
+ if (window == Z_NULL) {
+ ZFREE(source, copy);
+ return Z_MEM_ERROR;
+ }
+ }
+
+ /* copy state */
+ zmemcpy(dest, source, sizeof(z_stream));
+ zmemcpy(copy, state, sizeof(struct inflate_state));
+ if (state->lencode >= state->codes &&
+ state->lencode <= state->codes + ENOUGH - 1) {
+ copy->lencode = copy->codes + (state->lencode - state->codes);
+ copy->distcode = copy->codes + (state->distcode - state->codes);
+ }
+ copy->next = copy->codes + (state->next - state->codes);
+ if (window != Z_NULL) {
+ wsize = ((unsigned int)1) << state->wbits;
+ zmemcpy(window, state->window, wsize);
+ }
+ copy->window = window;
+ dest->state = (struct internal_state FAR *)copy;
+ return Z_OK;
+}
+
+#endif /* _INFLATE_C */
+
+#ifndef _GZIO_C
+#define _GZIO_C 1
+
+typedef voidp gzFile;
+
+#ifndef Z_BUFSIZE
+# ifdef MAXSEG_64K
+# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
+# else
+# define Z_BUFSIZE 16384
+# endif
+#endif
+#ifndef Z_PRINTF_BUFSIZE
+# define Z_PRINTF_BUFSIZE 4096
+#endif
+
+#ifdef __MVS__
+# pragma map (fdopen , "\174\174FDOPEN")
+ FILE *fdopen(int, const char *);
+#endif
+
+#if 0 && !_PACKAGE_ast
+#ifndef STDC
+extern voidp malloc OF((uInt size));
+extern void free OF((voidpf ptr));
+#endif
+#endif
+
+#define ALLOC(size) malloc(size)
+#define TRYFREE(p) {if (p) free(p);}
+
+static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+
+typedef struct gz_stream {
+ z_stream stream;
+ int z_err; /* error code for last stream operation */
+ int z_eof; /* set if end of input file */
+ FILE *file; /* .gz file */
+ Byte *inbuf; /* input buffer */
+ Byte *outbuf; /* output buffer */
+ uLong crc; /* crc32 of uncompressed data */
+ char *msg; /* error message */
+ char *path; /* path name for debugging only */
+ int transparent; /* 1 if input file is not a .gz file */
+#if _PACKAGE_ast
+ int fatal; /* fatal stream error => all other ops fail */
+ int nocrc; /* 1 to skip 'r' crc checks */
+ int noclose; /* 1 to skip destroy fclose */
+ int verified;/* 2-byte magic read and verified ('v') */
+#endif
+ char mode; /* 'w' or 'r' */
+ z_off_t start; /* start of compressed data in file (header skipped) */
+ z_off_t in; /* bytes into deflate or inflate */
+ z_off_t out; /* bytes out of deflate or inflate */
+ int back; /* one character push-back */
+ int last; /* true if push-back is last character */
+} gz_stream;
+
+
+local gzFile gz_open OF((const char *path, const char *mode, FILE* fp));
+local int get_byte OF((gz_stream *s));
+local void check_header OF((gz_stream *s));
+local int destroy OF((gz_stream *s));
+local uLong getLong OF((gz_stream *s));
+
+/* ===========================================================================
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb"). The file is given either by FILE pointer
+ or path name (if fp == 0).
+ gz_open returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR).
+*/
+local gzFile gz_open (path, mode, fp)
+ const char *path;
+ const char *mode;
+ FILE *fp;
+{
+ int err;
+ int level = Z_DEFAULT_COMPRESSION; /* compression level */
+ int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
+ char *p = (char*)mode;
+ gz_stream *s;
+ char fmode[80]; /* copy of mode, without the compression level */
+ char *m = fmode;
+
+ if (!path || !mode) return Z_NULL;
+
+ s = (gz_stream *)ALLOC(sizeof(gz_stream));
+ if (!s) return Z_NULL;
+
+ s->stream.zalloc = (alloc_func)0;
+ s->stream.zfree = (free_func)0;
+ s->stream.opaque = (voidpf)0;
+ s->stream.next_in = s->inbuf = Z_NULL;
+ s->stream.next_out = s->outbuf = Z_NULL;
+ s->stream.avail_in = s->stream.avail_out = 0;
+ s->file = NULL;
+ s->z_err = Z_OK;
+ s->z_eof = 0;
+ s->in = 0;
+ s->out = 0;
+ s->back = EOF;
+ s->crc = crc32(0L, Z_NULL, 0);
+#if _PACKAGE_ast
+ s->fatal = 0;
+ s->nocrc = 0;
+ s->verified = 0;
+#endif
+ s->msg = NULL;
+ s->transparent = 0;
+
+ s->path = (char*)ALLOC(strlen(path)+1);
+ if (s->path == NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ strcpy(s->path, path); /* do this early for debugging */
+
+ s->mode = '\0';
+ do {
+ if (*p == 'r') s->mode = 'r';
+ if (*p == 'w' || *p == 'a') s->mode = 'w';
+ if (*p >= '0' && *p <= '9') {
+ level = *p - '0';
+ } else if (*p == 'f') {
+ strategy = Z_FILTERED;
+ } else if (*p == 'h') {
+ strategy = Z_HUFFMAN_ONLY;
+ } else if (*p == 'R') {
+ strategy = Z_RLE;
+#if _PACKAGE_ast
+ } else if (*p == 'n') {
+ s->nocrc = 1;
+ } else if (*p == 'o') {
+ s->noclose = 1;
+ } else if (*p == 'v') {
+ s->verified = 1;
+#endif
+ } else {
+ *m++ = *p; /* copy the mode */
+ }
+ } while (*p++ && m != fmode + sizeof(fmode));
+ if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
+
+ if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+ err = Z_STREAM_ERROR;
+#else
+#if _PACKAGE_ast
+ s->nocrc = 0;
+#endif
+ err = deflateInit2(&(s->stream), level,
+ Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
+ /* windowBits is passed < 0 to suppress zlib header */
+
+ s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+#endif
+ if (err != Z_OK || s->outbuf == Z_NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ } else {
+ s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
+
+ err = inflateInit2(&(s->stream), -MAX_WBITS);
+ /* windowBits is passed < 0 to tell that there is no zlib header.
+ * Note that in this case inflate *requires* an extra "dummy" byte
+ * after the compressed stream in order to complete decompression and
+ * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
+ * present after the compressed stream.
+ */
+ if (err != Z_OK || s->inbuf == Z_NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ }
+ s->stream.avail_out = Z_BUFSIZE;
+
+ errno = 0;
+
+ if (!(s->file = fp) && !(s->file = F_OPEN(path, fmode))) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ if (s->mode == 'w') {
+ /* Write a very simple .gz header:
+ */
+ fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
+ Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
+ s->start = 10L;
+ /* We use 10L instead of ftell(s->file) to because ftell causes an
+ * fflush on some systems. This version of the library doesn't use
+ * start anyway in write mode, so this initialization is not
+ * necessary.
+ */
+ } else {
+#if _PACKAGE_ast
+ sfsetbuf(s->file, (void*)s->file, SF_UNBOUND);
+#endif
+ check_header(s); /* skip the .gz header */
+ s->start = ftell(s->file) - s->stream.avail_in;
+ }
+
+ return (gzFile)s;
+}
+
+/* ===========================================================================
+ Associate a gzFile with the stdio stream fp.
+*/
+gzFile ZEXPORT gzfopen (fp, mode)
+ FILE* fp;
+ const char *mode;
+{
+ FILE* sp = (FILE*)fp;
+ char name[20];
+
+ if (!sp)
+ return (gzFile)Z_NULL;
+ sprintf(name, "<fd:%d>", fileno(sp)); /* for debugging */
+
+ return gz_open (name, mode, sp);
+}
+
+/* ===========================================================================
+ Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+ for end of file.
+ IN assertion: the stream s has been sucessfully opened for reading.
+*/
+local int get_byte(s)
+ gz_stream *s;
+{
+ if (s->z_eof) return EOF;
+ if (s->stream.avail_in == 0) {
+ errno = 0;
+ s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ if (s->stream.avail_in == 0) {
+ s->z_eof = 1;
+ if (ferror(s->file)) s->z_err = Z_ERRNO;
+ return EOF;
+ }
+ s->stream.next_in = s->inbuf;
+ }
+ s->stream.avail_in--;
+ return *(s->stream.next_in)++;
+}
+
+/* ===========================================================================
+ Check the gzip header of a gz_stream opened for reading. Set the stream
+ mode to transparent if the gzip magic header is not present; set s->err
+ to Z_DATA_ERROR if the magic header is present but the rest of the header
+ is incorrect.
+ IN assertion: the stream s has already been created sucessfully;
+ s->stream.avail_in is zero for the first time, but may be non-zero
+ for concatenated .gz files.
+*/
+local void check_header(s)
+ gz_stream *s;
+{
+ int method; /* method byte */
+ int flags; /* flags byte */
+ uInt len;
+ int c;
+
+#if _PACKAGE_ast
+ if (!s->verified)
+ for (len = 0; len < 2; len++) {
+ c = get_byte(s);
+ if (c != gz_magic[len]) {
+ if (len != 0) s->stream.avail_in++, s->stream.next_in--;
+ if (c != EOF) {
+ s->stream.avail_in++, s->stream.next_in--;
+ s->transparent = 1;
+ }
+ s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
+ return;
+ }
+ }
+#else
+ /* Assure two bytes in the buffer so we can peek ahead -- handle case
+ where first byte of header is at the end of the buffer after the last
+ gzip segment */
+ len = s->stream.avail_in;
+ if (len < 2) {
+ if (len) s->inbuf[0] = s->stream.next_in[0];
+ errno = 0;
+ len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
+ if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
+ s->stream.avail_in += len;
+ s->stream.next_in = s->inbuf;
+ if (s->stream.avail_in < 2) {
+ s->transparent = s->stream.avail_in;
+ return;
+ }
+ }
+
+ /* Peek ahead to check the gzip magic header */
+ if (s->stream.next_in[0] != gz_magic[0] ||
+ s->stream.next_in[1] != gz_magic[1]) {
+ s->transparent = 1;
+ return;
+ }
+ s->stream.avail_in -= 2;
+ s->stream.next_in += 2;
+#endif
+
+ /* Check the rest of the gzip header */
+ method = get_byte(s);
+ flags = get_byte(s);
+ if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+ s->z_err = Z_DATA_ERROR;
+ return;
+ }
+
+ /* Discard time, xflags and OS code: */
+ for (len = 0; len < 6; len++) (void)get_byte(s);
+
+ if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+ len = (uInt)get_byte(s);
+ len += ((uInt)get_byte(s))<<8;
+ /* len is garbage if EOF but the loop below will quit anyway */
+ while (len-- != 0 && get_byte(s) != EOF) ;
+ }
+ if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+ while ((c = get_byte(s)) != 0 && c != EOF) ;
+ }
+ if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
+ while ((c = get_byte(s)) != 0 && c != EOF) ;
+ }
+ if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
+ for (len = 0; len < 2; len++) (void)get_byte(s);
+ }
+ s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
+}
+
+ /* ===========================================================================
+ * Cleanup then free the given gz_stream. Return a zlib error code.
+ Try freeing in the reverse order of allocations.
+ */
+local int destroy (s)
+ gz_stream *s;
+{
+ int err = Z_OK;
+
+ if (!s) return Z_STREAM_ERROR;
+
+ TRYFREE(s->msg);
+
+ if (s->stream.state != NULL) {
+ if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+ err = Z_STREAM_ERROR;
+#else
+ err = deflateEnd(&(s->stream));
+#endif
+ } else if (s->mode == 'r') {
+ err = inflateEnd(&(s->stream));
+ }
+ }
+#if _PACKAGE_ast
+ if (s->file != NULL && (s->noclose ? (s->mode == 'r' ? 0 : fflush(s->file)) : fclose(s->file))) {
+#else
+ if (s->file != NULL && fclose(s->file)) {
+#endif
+#ifdef ESPIPE
+ if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
+#endif
+ err = Z_ERRNO;
+ }
+ if (s->z_err < 0) err = s->z_err;
+
+ TRYFREE(s->inbuf);
+ TRYFREE(s->outbuf);
+ TRYFREE(s->path);
+ TRYFREE(s);
+ return err;
+}
+
+/* ===========================================================================
+ Reads the given number of uncompressed bytes from the compressed file.
+ gzread returns the number of bytes actually read (0 for end of file).
+*/
+int ZEXPORT gzread (file, buf, len)
+ gzFile file;
+ voidp buf;
+ unsigned len;
+{
+ gz_stream *s = (gz_stream*)file;
+ Bytef *start = (Bytef*)buf; /* starting point for crc computation */
+ Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
+
+ if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
+
+ if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
+ if (s->z_err == Z_STREAM_END) return 0; /* EOF */
+
+ next_out = (Byte*)buf;
+ s->stream.next_out = (Bytef*)buf;
+ s->stream.avail_out = len;
+
+ if (s->stream.avail_out && s->back != EOF) {
+ *next_out++ = s->back;
+ s->stream.next_out++;
+ s->stream.avail_out--;
+ s->back = EOF;
+ s->out++;
+ start++;
+ if (s->last) {
+ s->z_err = Z_STREAM_END;
+ return 1;
+ }
+ }
+
+ while (s->stream.avail_out != 0) {
+
+ if (s->transparent) {
+ /* Copy first the lookahead bytes: */
+ uInt n = s->stream.avail_in;
+ if (n > s->stream.avail_out) n = s->stream.avail_out;
+ if (n > 0) {
+ zmemcpy(s->stream.next_out, s->stream.next_in, n);
+ next_out += n;
+ s->stream.next_out = next_out;
+ s->stream.next_in += n;
+ s->stream.avail_out -= n;
+ s->stream.avail_in -= n;
+ }
+ if (s->stream.avail_out > 0) {
+ s->stream.avail_out -=
+ (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
+ }
+ len -= s->stream.avail_out;
+ s->in += len;
+ s->out += len;
+ if (len == 0) s->z_eof = 1;
+ return (int)len;
+ }
+ if (s->stream.avail_in == 0 && !s->z_eof) {
+
+ errno = 0;
+ s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ if (s->stream.avail_in == 0) {
+ s->z_eof = 1;
+ if (ferror(s->file)) {
+ s->z_err = Z_ERRNO;
+ break;
+ }
+ }
+ s->stream.next_in = s->inbuf;
+ }
+ s->in += s->stream.avail_in;
+ s->out += s->stream.avail_out;
+ s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
+ s->in -= s->stream.avail_in;
+ s->out -= s->stream.avail_out;
+
+ if (s->z_err == Z_STREAM_END) {
+ /* Check CRC and original size */
+#if _PACKAGE_ast
+ if (!s->nocrc)
+#endif
+ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+ start = s->stream.next_out;
+
+#if _PACKAGE_ast
+ if (getLong(s) != s->crc && !s->nocrc) {
+#else
+ if (getLong(s) != s->crc) {
+#endif
+ s->z_err = Z_DATA_ERROR;
+ } else {
+ (void)getLong(s);
+ /* The uncompressed length returned by above getlong() may be
+ * different from s->out in case of concatenated .gz files.
+ * Check for such files:
+ */
+ check_header(s);
+ if (s->z_err == Z_OK) {
+ inflateReset(&(s->stream));
+#if _PACKAGE_ast
+ if (!s->nocrc)
+#endif
+ s->crc = crc32(0L, Z_NULL, 0);
+#if _PACKAGE_ast
+ else
+ s->z_err = Z_STREAM_END;
+#endif
+ }
+ }
+ }
+ if (s->z_err != Z_OK || s->z_eof) break;
+ }
+#if _PACKAGE_ast
+ if (!s->nocrc)
+#endif
+ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+
+ if (len == s->stream.avail_out &&
+ (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
+ return -1;
+ return (int)(len - s->stream.avail_out);
+}
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets z_err in case
+ of error.
+*/
+local uLong getLong (s)
+ gz_stream *s;
+{
+ uLong x = (uLong)get_byte(s);
+ int c;
+
+ x += ((uLong)get_byte(s))<<8;
+ x += ((uLong)get_byte(s))<<16;
+ c = get_byte(s);
+ if (c == EOF) s->z_err = Z_DATA_ERROR;
+ x += ((uLong)c)<<24;
+ return x;
+}
+
+#endif /* _GZIO_C */
+
+#endif /* _GUNZIP_H */
+
+#undef local
+
+#ifndef _RATZ_C
+#define _RATZ_C 1
+
+#include <sys/stat.h>
+
+#ifndef S_IRUSR
+#define S_IRUSR 0400
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR 0200
+#endif
+#ifndef S_IXUSR
+#define S_IXUSR 0100
+#endif
+#ifndef S_IRGRP
+#define S_IRGRP 0040
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP 0020
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0010
+#endif
+#ifndef S_IROTH
+#define S_IROTH 0004
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH 0002
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0001
+#endif
+
+/*
+ * Standard Archive Format
+ * USTAR - Uniform Standard Tape ARchive
+ */
+
+#define TBLOCK 512
+#define NAMSIZ 100
+#define PFXSIZ 155
+
+#define TMODLEN 8
+#define TUIDLEN 8
+#define TGIDLEN 8
+#define TSIZLEN 12
+#define TMTMLEN 12
+#define TCKSLEN 8
+
+#define TMAGIC "ustar" /* ustar and a null */
+#define TMAGLEN 6
+#define TVERSION "00" /* 00 and no null */
+#define TVERSLEN 2
+#define TUNMLEN 32
+#define TGNMLEN 32
+#define TDEVLEN 8
+#define TPADLEN 12
+
+/*
+ * values used in typeflag field
+ */
+
+#define REGTYPE '0' /* regular file */
+#define AREGTYPE 0 /* alternate REGTYPE */
+#define LNKTYPE '1' /* hard link */
+#define SYMTYPE '2' /* soft link */
+#define CHRTYPE '3' /* character special */
+#define BLKTYPE '4' /* block special */
+#define DIRTYPE '5' /* directory */
+#define FIFOTYPE '6' /* FIFO special */
+#define CONTTYPE '7' /* reserved */
+#define SOKTYPE '8' /* socket -- reserved */
+#define VERTYPE 'V' /* version -- reserved */
+#define EXTTYPE 'x' /* extended header -- reserved */
+
+/*
+ * bits used in mode field
+ */
+
+#define TSUID 04000 /* set uid on exec */
+#define TSGID 02000 /* set gid on exec */
+#define TSVTX 01000 /* sticky bit -- reserved */
+
+/*
+ * file permissions
+ */
+
+#define TUREAD 00400 /* read by owner */
+#define TUWRITE 00200 /* write by owner */
+#define TUEXEC 00100 /* execute by owner */
+#define TGREAD 00040 /* read by group */
+#define TGWRITE 00020 /* execute by group */
+#define TGEXEC 00010 /* write by group */
+#define TOREAD 00004 /* read by other */
+#define TOWRITE 00002 /* write by other */
+#define TOEXEC 00001 /* execute by other */
+
+#define TAR_SUMASK ((1L<<(TCKSLEN-1)*3)-1)
+
+typedef struct
+{
+ char name[NAMSIZ];
+ char mode[TMODLEN];
+ char uid[TUIDLEN];
+ char gid[TGIDLEN];
+ char size[TSIZLEN];
+ char mtime[TMTMLEN];
+ char chksum[TCKSLEN];
+ char typeflag;
+ char linkname[NAMSIZ];
+ char magic[TMAGLEN];
+ char version[TVERSLEN];
+ char uname[TUNMLEN];
+ char gname[TGNMLEN];
+ char devmajor[TDEVLEN];
+ char devminor[TDEVLEN];
+ char prefix[PFXSIZ];
+ char pad[TPADLEN];
+} Header_t;
+
+static struct
+{
+ char* id;
+ unsigned long blocks;
+ unsigned long files;
+} state;
+
+#if !_PACKAGE_ast
+
+static void
+usage()
+{
+ fprintf(stderr, "Usage: %s [-clmntvV] < input.tgz\n", state.id);
+ exit(2);
+}
+
+#endif
+
+/*
+ * the X/Open dd EBCDIC table
+ */
+
+static const unsigned char a2e[] =
+{
+ 0000,0001,0002,0003,0067,0055,0056,0057,
+ 0026,0005,0045,0013,0014,0015,0016,0017,
+ 0020,0021,0022,0023,0074,0075,0062,0046,
+ 0030,0031,0077,0047,0034,0035,0036,0037,
+ 0100,0132,0177,0173,0133,0154,0120,0175,
+ 0115,0135,0134,0116,0153,0140,0113,0141,
+ 0360,0361,0362,0363,0364,0365,0366,0367,
+ 0370,0371,0172,0136,0114,0176,0156,0157,
+ 0174,0301,0302,0303,0304,0305,0306,0307,
+ 0310,0311,0321,0322,0323,0324,0325,0326,
+ 0327,0330,0331,0342,0343,0344,0345,0346,
+ 0347,0350,0351,0255,0340,0275,0232,0155,
+ 0171,0201,0202,0203,0204,0205,0206,0207,
+ 0210,0211,0221,0222,0223,0224,0225,0226,
+ 0227,0230,0231,0242,0243,0244,0245,0246,
+ 0247,0250,0251,0300,0117,0320,0137,0007,
+ 0040,0041,0042,0043,0044,0025,0006,0027,
+ 0050,0051,0052,0053,0054,0011,0012,0033,
+ 0060,0061,0032,0063,0064,0065,0066,0010,
+ 0070,0071,0072,0073,0004,0024,0076,0341,
+ 0101,0102,0103,0104,0105,0106,0107,0110,
+ 0111,0121,0122,0123,0124,0125,0126,0127,
+ 0130,0131,0142,0143,0144,0145,0146,0147,
+ 0150,0151,0160,0161,0162,0163,0164,0165,
+ 0166,0167,0170,0200,0212,0213,0214,0215,
+ 0216,0217,0220,0152,0233,0234,0235,0236,
+ 0237,0240,0252,0253,0254,0112,0256,0257,
+ 0260,0261,0262,0263,0264,0265,0266,0267,
+ 0270,0271,0272,0273,0274,0241,0276,0277,
+ 0312,0313,0314,0315,0316,0317,0332,0333,
+ 0334,0335,0336,0337,0352,0353,0354,0355,
+ 0356,0357,0372,0373,0374,0375,0376,0377,
+};
+
+/*
+ * the X/Open dd IBM table
+ */
+
+static const unsigned char a2i[] =
+{
+ 0000,0001,0002,0003,0067,0055,0056,0057,
+ 0026,0005,0045,0013,0014,0015,0016,0017,
+ 0020,0021,0022,0023,0074,0075,0062,0046,
+ 0030,0031,0077,0047,0034,0035,0036,0037,
+ 0100,0132,0177,0173,0133,0154,0120,0175,
+ 0115,0135,0134,0116,0153,0140,0113,0141,
+ 0360,0361,0362,0363,0364,0365,0366,0367,
+ 0370,0371,0172,0136,0114,0176,0156,0157,
+ 0174,0301,0302,0303,0304,0305,0306,0307,
+ 0310,0311,0321,0322,0323,0324,0325,0326,
+ 0327,0330,0331,0342,0343,0344,0345,0346,
+ 0347,0350,0351,0255,0340,0275,0137,0155,
+ 0171,0201,0202,0203,0204,0205,0206,0207,
+ 0210,0211,0221,0222,0223,0224,0225,0226,
+ 0227,0230,0231,0242,0243,0244,0245,0246,
+ 0247,0250,0251,0300,0117,0320,0241,0007,
+ 0040,0041,0042,0043,0044,0025,0006,0027,
+ 0050,0051,0052,0053,0054,0011,0012,0033,
+ 0060,0061,0032,0063,0064,0065,0066,0010,
+ 0070,0071,0072,0073,0004,0024,0076,0341,
+ 0101,0102,0103,0104,0105,0106,0107,0110,
+ 0111,0121,0122,0123,0124,0125,0126,0127,
+ 0130,0131,0142,0143,0144,0145,0146,0147,
+ 0150,0151,0160,0161,0162,0163,0164,0165,
+ 0166,0167,0170,0200,0212,0213,0214,0215,
+ 0216,0217,0220,0232,0233,0234,0235,0236,
+ 0237,0240,0252,0253,0254,0255,0256,0257,
+ 0260,0261,0262,0263,0264,0265,0266,0267,
+ 0270,0271,0272,0273,0274,0275,0276,0277,
+ 0312,0313,0314,0315,0316,0317,0332,0333,
+ 0334,0335,0336,0337,0352,0353,0354,0355,
+ 0356,0357,0372,0373,0374,0375,0376,0377,
+};
+
+/*
+ * the mvs OpenEdition EBCDIC table
+ */
+
+static const unsigned char a2o[] =
+{
+ 0000,0001,0002,0003,0067,0055,0056,0057,
+ 0026,0005,0025,0013,0014,0015,0016,0017,
+ 0020,0021,0022,0023,0074,0075,0062,0046,
+ 0030,0031,0077,0047,0034,0035,0036,0037,
+ 0100,0132,0177,0173,0133,0154,0120,0175,
+ 0115,0135,0134,0116,0153,0140,0113,0141,
+ 0360,0361,0362,0363,0364,0365,0366,0367,
+ 0370,0371,0172,0136,0114,0176,0156,0157,
+ 0174,0301,0302,0303,0304,0305,0306,0307,
+ 0310,0311,0321,0322,0323,0324,0325,0326,
+ 0327,0330,0331,0342,0343,0344,0345,0346,
+ 0347,0350,0351,0255,0340,0275,0137,0155,
+ 0171,0201,0202,0203,0204,0205,0206,0207,
+ 0210,0211,0221,0222,0223,0224,0225,0226,
+ 0227,0230,0231,0242,0243,0244,0245,0246,
+ 0247,0250,0251,0300,0117,0320,0241,0007,
+ 0040,0041,0042,0043,0044,0045,0006,0027,
+ 0050,0051,0052,0053,0054,0011,0012,0033,
+ 0060,0061,0032,0063,0064,0065,0066,0010,
+ 0070,0071,0072,0073,0004,0024,0076,0377,
+ 0101,0252,0112,0261,0237,0262,0152,0265,
+ 0273,0264,0232,0212,0260,0312,0257,0274,
+ 0220,0217,0352,0372,0276,0240,0266,0263,
+ 0235,0332,0233,0213,0267,0270,0271,0253,
+ 0144,0145,0142,0146,0143,0147,0236,0150,
+ 0164,0161,0162,0163,0170,0165,0166,0167,
+ 0254,0151,0355,0356,0353,0357,0354,0277,
+ 0200,0375,0376,0373,0374,0272,0256,0131,
+ 0104,0105,0102,0106,0103,0107,0234,0110,
+ 0124,0121,0122,0123,0130,0125,0126,0127,
+ 0214,0111,0315,0316,0313,0317,0314,0341,
+ 0160,0335,0336,0333,0334,0215,0216,0337,
+};
+
+/*
+ * ascii text vs. control
+ */
+
+static const unsigned char ascii_text[] =
+{
+ 0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
+
+static int
+block(fp, gz, buf)
+FILE* fp;
+gzFile gz;
+char* buf;
+{
+ int r;
+
+ if (gz)
+ r = gzread(gz, buf, sizeof(Header_t)) == sizeof(Header_t);
+ else
+ r = fread(buf, sizeof(Header_t), 1, fp) == 1;
+ if (r)
+ state.blocks++;
+ return r;
+}
+
+static int
+skip(fp, gz, buf, n)
+FILE* fp;
+gzFile gz;
+char* buf;
+unsigned long n;
+{
+ while (n > 0)
+ {
+ if (!block(fp, gz, buf))
+ {
+ fprintf(stderr, "%s: unexpected EOF\n", state.id);
+ return 1;
+ }
+ if (n <= sizeof(Header_t))
+ break;
+ n -= sizeof(Header_t);
+ }
+ return 0;
+}
+
+static unsigned long
+number(s)
+register char* s;
+{
+ unsigned long n = 0;
+
+ while (*s == ' ')
+ s++;
+ while (*s >= '0' && *s <= '7')
+ n = (n << 3) + (*s++ - '0');
+ return n;
+}
+
+#if defined(_SEAR_EXEC) || defined(_SEAR_SEEK)
+
+#ifndef PATH_MAX
+#define PATH_MAX 256
+#endif
+
+#define EXIT(n) return(sear_exec((char*)0,(char**)0,(char*)0),(n))
+
+static int sear_stdin;
+static char* sear_tmp;
+static char sear_buf[PATH_MAX];
+
+static int
+sear_seek(off_t offset, int tmp)
+{
+ int n;
+ char cmd[PATH_MAX];
+
+ GetModuleFileName(NULL, cmd, sizeof(cmd));
+ sear_stdin = dup(0);
+ close(0);
+ if (open(cmd, O_BINARY|O_RDONLY) || lseek(0, offset, 0) != offset)
+ {
+ fprintf(stderr, "%s: %s: cannot seek to data offset\n", state.id, cmd);
+ return -1;
+ }
+ if (tmp)
+ {
+ if ((n = GetTempPath(sizeof(cmd), cmd)) <= 0 || n > sizeof(cmd))
+ {
+ fprintf(stderr, "%s: cannot determine temporary directory path\n", state.id);
+ return -1;
+ }
+ if (!GetTempFileName(cmd, "SEA", 0, sear_buf))
+ {
+ fprintf(stderr, "%s: cannot determine temporary file path\n", state.id);
+ return -1;
+ }
+ sear_tmp = sear_buf;
+ if (!DeleteFile(sear_tmp))
+ {
+ fprintf(stderr, "%s: %s: cannot initialize temporary directory\n", state.id, sear_tmp);
+ return -1;
+ }
+ if (!CreateDirectory(sear_tmp, NULL))
+ {
+ fprintf(stderr, "%s: %s: cannot create temporary directory\n", state.id, sear_tmp);
+ return -1;
+ }
+ if (!SetCurrentDirectory(sear_tmp))
+ {
+ fprintf(stderr, "%s: %s: cannot cd to temporary directory\n", state.id, sear_tmp);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * remove dir and its subdirs
+ */
+
+static void
+sear_rm_r(char* dir)
+{
+ WIN32_FIND_DATA info;
+ HANDLE hp;
+
+ if (!SetCurrentDirectory(dir))
+ return;
+ if ((hp = FindFirstFile("*.*", &info)) != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ SetFileAttributes(info.cFileName, info.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
+ DeleteFile(info.cFileName);
+ }
+ else if (info.cFileName[0] != '.' || info.cFileName[1] != 0 && (info.cFileName[1] != '.' || info.cFileName[2] != 0))
+ sear_rm_r(info.cFileName);
+ } while(FindNextFile(hp, &info));
+ FindClose(hp);
+ }
+ if (SetCurrentDirectory(".."))
+ RemoveDirectory(dir);
+}
+
+/*
+ * system(3) without PATH search that should work on all windows variants
+ */
+
+static int
+sear_system(const char* command, int nowindow)
+{
+ PROCESS_INFORMATION pinfo;
+ STARTUPINFO sinfo;
+ char* cp;
+ char path[PATH_MAX];
+ int n = *command == '"';
+ DWORD flags = NORMAL_PRIORITY_CLASS;
+
+ strncpy(path, &command[n], PATH_MAX - 4);
+ n = n ? '"' : ' ';
+ for (cp = path; *cp; *cp++)
+ if (*cp == n)
+ break;
+ *cp = 0;
+ if (GetFileAttributes(path) == 0xffffffff && GetLastError() == ERROR_FILE_NOT_FOUND)
+ strcpy(cp, ".exe");
+ ZeroMemory(&sinfo, sizeof(sinfo));
+ if (nowindow)
+ flags |= CREATE_NO_WINDOW;
+ if (!CreateProcess(path, (char*)command, 0, 0, TRUE, flags, NULL, NULL, &sinfo, &pinfo))
+ n = GetLastError() == ERROR_FILE_NOT_FOUND ? 127 : 126;
+ else
+ {
+ CloseHandle(pinfo.hThread);
+ WaitForSingleObject(pinfo.hProcess, INFINITE);
+ if (!GetExitCodeProcess(pinfo.hProcess, &n))
+ n = 1;
+ CloseHandle(pinfo.hProcess);
+ Sleep(2 * 1000);
+ }
+ return n;
+}
+
+/*
+ * copy t to f but no farther than e
+ * next t returned
+ */
+
+static char*
+copy(char* t, const char* f, char* e)
+{
+ while (t < e && *f)
+ *t++ = *f++;
+ return t;
+}
+
+/*
+ * execute cmd, chdir .., and remove sear_tmp
+ */
+
+static int
+sear_exec(const char* cmd, char* const* arg, char* operands)
+{
+ const char* a;
+ char* b;
+ char* e;
+ int r;
+ int sh;
+ int nowindow;
+ char buf[1024];
+
+ fflush(stdout);
+ fflush(stderr);
+ if (sear_tmp)
+ {
+ close(0);
+ dup(sear_stdin);
+ close(sear_stdin);
+ nowindow = 0;
+ if (cmd)
+ {
+ if (arg)
+ for (r = 0; arg[r]; r++)
+ if (!strcmp(arg[r], "remote"))
+ {
+ nowindow = 1;
+ break;
+ }
+ sh = 0;
+ for (a = cmd; *a && *a != ' '; a++)
+ if (a[0] == '.' && a[1] == 's' && a[2] == 'h' && (!a[3] || a[3] == ' '))
+ {
+ sh = 1;
+ break;
+ }
+ b = buf;
+ e = buf + sizeof(buf) - 1;
+ if (sh || arg)
+ {
+ if (sh)
+ {
+ b = copy(b, "ksh.exe ", e);
+ if (*cmd && *cmd != '/')
+ b = copy(b, "./", e);
+ }
+ b = copy(b, cmd, e);
+ while (a = *arg++)
+ {
+ if ((e - b) < 3)
+ break;
+ b = copy(b, " \"", e);
+ b = copy(b, a, e);
+ b = copy(b, "\"", e);
+ }
+ }
+ if (operands)
+ {
+ if (b == buf)
+ b = copy(b, cmd, e);
+ b = copy(b, " -- ", e);
+ b = copy(b, operands, e);
+ }
+ if (b > buf)
+ {
+ *b = 0;
+ cmd = (const char*)buf;
+ }
+ }
+ r = cmd ? sear_system(cmd, nowindow) : 1;
+ sear_rm_r(sear_tmp);
+ }
+ else
+ r = cmd ? 0 : 1;
+ return r;
+}
+
+#else
+
+#define EXIT(n) return(n)
+
+#endif
+
+int
+main(argc, argv)
+int argc;
+char** argv;
+{
+ register int c;
+ register char* s;
+ register char* t;
+ register char* e;
+ unsigned long n;
+ unsigned long m;
+ const unsigned char* a2x;
+ int clear;
+ int list;
+ int local;
+ int meter;
+ int unzip;
+ int verbose;
+ unsigned int mode;
+ unsigned long total;
+ off_t pos;
+ gzFile gz;
+ FILE* fp;
+ Header_t header;
+ unsigned char num[4];
+ char path[sizeof(header.prefix) + sizeof(header.name) + 4];
+ char buf[sizeof(header)];
+#if defined(_SEAR_OPTS)
+ char* opts[4];
+#endif
+
+#if defined(_SEAR_EXEC) || defined(_SEAR_SEEK)
+ int install = 1;
+#endif
+
+ setmode(0, O_BINARY);
+ setmode(1, O_BINARY);
+ clear = 0;
+ list = 0;
+ local = 0;
+ meter = 0;
+ unzip = 0;
+ verbose = 0;
+ if (s = *argv)
+ {
+ t = s;
+ while (*s)
+ if (*s++ == '/')
+ t = s;
+ if (!strcmp(t, "gunzip"))
+ unzip = 1;
+ state.id = t;
+ }
+ else
+ state.id = "ratz";
+ switch ('~')
+ {
+ case 0241:
+ switch ('\n')
+ {
+ case 0025:
+ a2x = a2o;
+ break;
+ default:
+ a2x = a2e;
+ break;
+ }
+ break;
+ case 0137:
+ a2x = a2i;
+ break;
+ default:
+ a2x = 0;
+ break;
+ }
+#if defined(_SEAR_OPTS)
+ opts[0] = argv[0];
+ opts[1] = _SEAR_OPTS;
+ opts[2] = argv[1];
+ opts[3] = 0;
+ argv = opts;
+#endif
+#if _PACKAGE_ast
+ error_info.id = state.id;
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'c':
+ unzip = 1;
+ continue;
+#if defined(_SEAR_EXEC) || defined(_SEAR_SEEK)
+ case 'i':
+ install = 0;
+ continue;
+#endif
+ case 'l':
+ local = 1;
+ continue;
+ case 'm':
+ meter = 1;
+ continue;
+ case 'n':
+ a2x = 0;
+ continue;
+ case 't':
+ list = 1;
+ continue;
+ case 'v':
+ verbose = 1;
+ continue;
+ case 'V':
+ sfprintf(sfstdout, "%s\n", id + 10);
+ return 0;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ if (error_info.errors)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ argv += opt_info.index;
+#else
+ while ((s = *++argv) && *s == '-' && *(s + 1))
+ {
+ if (*(s + 1) == '-')
+ {
+ if (!*(s + 2))
+ {
+ argv++;
+ break;
+ }
+ usage();
+ break;
+ }
+ for (;;)
+ {
+ switch (c = *++s)
+ {
+ case 0:
+ break;
+ case 'c':
+ unzip = 1;
+ continue;
+#if defined(_SEAR_EXEC) || defined(_SEAR_SEEK)
+ case 'i':
+ install = 0;
+ continue;
+#endif
+ case 'l':
+ local = 1;
+ continue;
+ case 'm':
+ meter = 1;
+ continue;
+ case 'n':
+ a2x = 0;
+ continue;
+ case 't':
+ list = 1;
+ continue;
+ case 'v':
+ verbose = 1;
+ continue;
+ case 'V':
+ fprintf(stdout, "%s\n", id + 10);
+ return 0;
+ default:
+ fprintf(stderr, "%s: -%c: unknown option\n", state.id, c);
+ /*FALLTHROUGH*/
+ case '?':
+ usage();
+ break;
+ }
+ break;
+ }
+ }
+#endif
+
+#if defined(_SEAR_SEEK)
+ if (sear_seek((off_t)_SEAR_SEEK, install && !list))
+ {
+ Sleep(2 * 1000);
+ return 1;
+ }
+#endif
+
+ /*
+ * commit on the first gzip magic char
+ */
+
+ if ((c = getchar()) == EOF)
+ EXIT(0);
+ ungetc(c, stdin);
+ if (c != gz_magic[0])
+ gz = 0;
+ else if (!(gz = gzfopen(stdin, FOPEN_READ)))
+ {
+ fprintf(stderr, "%s: gunzip open error\n", state.id);
+ EXIT(1);
+ }
+ if (unzip)
+ {
+ if (!gz)
+ {
+ fprintf(stderr, "%s: not a gzip file\n", state.id);
+ EXIT(1);
+ }
+ while ((c = gzread(gz, buf, sizeof(buf))) > 0)
+ if (fwrite(buf, c, 1, stdout) != 1)
+ {
+ fprintf(stderr, "%s: write error\n", state.id);
+ EXIT(1);
+ }
+ if (c < 0)
+ {
+ fprintf(stderr, "%s: read error\n", state.id);
+ EXIT(1);
+ }
+ if (fflush(stdout))
+ {
+ fprintf(stderr, "%s: flush error\n", state.id);
+ EXIT(1);
+ }
+ EXIT(0);
+ }
+ if (meter)
+ {
+ if ((pos = lseek(0, (off_t)0, SEEK_CUR)) < 0)
+ meter = 0;
+ else
+ {
+ if (lseek(0, (off_t)(-4), SEEK_END) < 0 || read(0, num, 4) != 4)
+ meter = 0;
+ else if (!(total = ((num[0]|(num[1]<<8)|(num[2]<<16)|(num[3]<<24)) + sizeof(Header_t) - 1) / sizeof(Header_t)))
+ total = 1;
+ lseek(0, pos, SEEK_SET);
+ }
+ }
+
+ /*
+ * loop on all the header blocks
+ */
+
+ while (block(stdin, gz, (char*)&header))
+ {
+ /*
+ * last 2 blocks are NUL
+ */
+
+ if (!*header.name)
+ break;
+
+ /*
+ * verify the checksum
+ */
+
+ s = header.chksum;
+ e = header.chksum + sizeof(header.chksum);
+ if (a2x)
+ {
+ for (; s < e; s++)
+ *s = a2x[*(unsigned char*)s];
+ s = header.chksum;
+ }
+ n = number(s) & TAR_SUMASK;
+ while (s < e)
+ *s++ = 040;
+ m = 0;
+ s = (char*)&header;
+ e = (char*)&header + sizeof(header);
+ while (s < e)
+ m += *(unsigned char*)s++;
+ m &= TAR_SUMASK;
+ if (m != n)
+ {
+ if (state.files)
+ fprintf(stderr, "%s: archive corrupted\n", state.id);
+ else
+ fprintf(stderr, "%s: not a tar archive\n", state.id);
+ fprintf(stderr, "check sum %lu != %lu\n", m, n);
+ EXIT(1);
+ }
+
+ /*
+ * convert to the native charset
+ */
+
+ if (a2x)
+ for (e = (s = (char*)&header) + sizeof(header); s < e; s++)
+ *s = a2x[*(unsigned char*)s];
+
+ /*
+ * get the pathname, type and size
+ */
+
+ state.files++;
+ t = path;
+ if (!strncmp(header.magic, TMAGIC, sizeof(header.magic)) && *header.prefix)
+ {
+ s = header.prefix;
+ e = header.prefix + sizeof(header.prefix);
+ while (s < e && (c = *s++))
+ *t++ = c;
+ *t++ = '/';
+ }
+ s = header.name;
+ e = header.name + sizeof(header.name);
+ while (s < e && (c = *s++))
+ *t++ = c;
+ *t = 0;
+
+ /*
+ * verify the dir prefix
+ */
+
+ t = 0;
+ s = path;
+ while (*s)
+ if (*s++ == '/')
+ t = s;
+ if (t)
+ {
+ *--t = 0;
+ if (!list && access(path, 0))
+ {
+ s = path;
+ do
+ {
+ if (!(c = *s) || c == '/')
+ {
+ *s = 0;
+ if (access(path, 0) && mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH))
+ {
+ fprintf(stderr, "%s: %s: cannot create directory\n", state.id, path);
+ EXIT(1);
+ }
+ *s = c;
+ }
+ } while (*s++);
+ }
+ if (*(t + 1))
+ *t = '/';
+ else
+ header.typeflag = DIRTYPE;
+ }
+
+ /*
+ * check for non-local paths
+ */
+
+ if (local && (path[0] == '/' || path[0] == '.' && path[1] == '.' && (!path[2] || path[2] == '/')))
+ {
+ fprintf(stderr, "%s: %s: non-local path rejected", state.id, path);
+ if ((header.typeflag == REGTYPE || header.typeflag == AREGTYPE) && (n = number(header.size)))
+ while (n > 0)
+ {
+ if (!block(stdin, gz, buf))
+ {
+ fprintf(stderr, "%s: unexpected EOF\n", state.id);
+ EXIT(1);
+ }
+ if (n <= sizeof(header))
+ break;
+ n -= sizeof(header);
+ }
+ continue;
+ }
+
+ /*
+ * create and grab the data
+ */
+
+ n = number(header.mode);
+ mode = 0;
+ if (n & TUREAD)
+ mode |= S_IRUSR;
+ if (n & TUWRITE)
+ mode |= S_IWUSR;
+ if (n & TUEXEC)
+ mode |= S_IXUSR;
+ if (n & TGREAD)
+ mode |= S_IRGRP;
+ if (n & TGWRITE)
+ mode |= S_IWGRP;
+ if (n & TGEXEC)
+ mode |= S_IXGRP;
+ if (n & TOREAD)
+ mode |= S_IROTH;
+ if (n & TOWRITE)
+ mode |= S_IWOTH;
+ if (n & TOEXEC)
+ mode |= S_IXOTH;
+ if (list || meter)
+ {
+ if (meter)
+ {
+ int i;
+ int j;
+ int k;
+ int n;
+ int p;
+ char bar[METER_parts + 1];
+
+ for (s = path; *s; s++)
+ if (s[0] == ' ' && s[1] == '-' && s[2] == '-' && s[3] == ' ')
+ break;
+ if (*s)
+ {
+ if (clear)
+ {
+ fprintf(stderr, "%*s", clear, "\r");
+ clear = 0;
+ }
+ fprintf(stderr, "\n%s\n\n", path);
+ }
+ else
+ {
+ n = (int)strlen(s = path);
+ p = (state.blocks * 100) / total;
+ if (n > (METER_width - METER_parts - 1))
+ {
+ s += n - (METER_width - METER_parts - 1);
+ n = METER_width - METER_parts - 1;
+ }
+ j = n + METER_parts + 2;
+ if (!clear)
+ clear = j + 5;
+ if ((k = clear - j - 5) < 0)
+ k = 0;
+ if ((i = (p / (100 / METER_parts))) >= sizeof(bar))
+ i = sizeof(bar) - 1;
+ n = 0;
+ while (n < i)
+ bar[n++] = '*';
+ while (n < sizeof(bar) - 1)
+ bar[n++] = ' ';
+ bar[n] = 0;
+ clear = fprintf(stderr, "%02d%% |%s| %s%*s", p, bar, s, k, "\r");
+ }
+ }
+ else
+ {
+ if (verbose)
+ {
+ switch (header.typeflag)
+ {
+ case REGTYPE:
+ case AREGTYPE:
+ c = '-';
+ break;
+ case DIRTYPE:
+ c = 'd';
+ break;
+ case LNKTYPE:
+ c = 'h';
+ break;
+ case SYMTYPE:
+ c = 'l';
+ break;
+ default:
+ c = '?';
+ break;
+ }
+ printf("%c", c);
+ m = 0400;
+ while (m)
+ {
+ printf("%c", (n & m) ? 'r' : '-');
+ m >>= 1;
+ printf("%c", (n & m) ? 'w' : '-');
+ m >>= 1;
+ printf("%c", (n & m) ? 'x' : '-');
+ m >>= 1;
+ }
+ printf(" %10lu ", number(header.size));
+ }
+ switch (header.typeflag)
+ {
+ case LNKTYPE:
+ printf("%s == %s\n", path, header.linkname);
+ break;
+ case SYMTYPE:
+ printf("%s => %s\n", path, header.linkname);
+ break;
+ default:
+ printf("%s\n", path);
+ break;
+ }
+ }
+ if (list)
+ {
+ if (skip(stdin, gz, buf, number(header.size)))
+ EXIT(1);
+ continue;
+ }
+ }
+ else if (verbose)
+ printf("%s\n", path);
+ switch (header.typeflag)
+ {
+ case REGTYPE:
+ case AREGTYPE:
+ while (!(fp = fopen(path, FOPEN_WRITE)))
+ if (unlink(path))
+ {
+ fprintf(stderr, "%s: warning: %s: cannot create file\n", state.id, path);
+ break;
+ }
+ n = number(header.size);
+ c = a2x ? 0 : -1;
+ while (n > 0)
+ {
+ if (!block(stdin, gz, buf))
+ {
+ fprintf(stderr, "%s: unexpected EOF\n", state.id);
+ EXIT(1);
+ }
+ switch (c)
+ {
+ case 0:
+ if ((m = n) < 4)
+ {
+ for (e = (s = buf) + m; s < e; s++)
+ if (a2x[*(unsigned char*)s] != '\n')
+ break;
+ }
+ else
+ {
+ if (m > 256)
+ m = 256;
+ for (e = (s = buf) + m; s < e; s++)
+ if (!ascii_text[*(unsigned char*)s])
+ break;
+ }
+ if (s < e)
+ {
+ c = -1;
+ break;
+ }
+ c = 1;
+ /*FALLTHROUGH*/
+ case 1:
+ for (e = (s = buf) + sizeof(header); s < e; s++)
+ *s = a2x[*(unsigned char*)s];
+ break;
+ }
+ if (fp && fwrite(buf, n > sizeof(header) ? sizeof(header) : n, 1, fp) != 1)
+ {
+ fprintf(stderr, "%s: %s: write error\n", state.id, path);
+ EXIT(1);
+ }
+ if (n <= sizeof(header))
+ break;
+ n -= sizeof(header);
+ }
+ if (fp && fclose(fp))
+ {
+ fprintf(stderr, "%s: %s: write error\n", state.id, path);
+ EXIT(1);
+ }
+ break;
+ case DIRTYPE:
+ if (access(path, 0) && mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH))
+ {
+ fprintf(stderr, "%s: %s: cannot create directory\n", state.id, path);
+ EXIT(1);
+ }
+ break;
+ case SYMTYPE:
+#if defined(S_IFLNK) || defined(S_ISLNK)
+ while (symlink(header.linkname, path))
+ if (unlink(path))
+ {
+ fprintf(stderr, "%s: %s: cannot symlink to %s\n", state.id, path, header.linkname);
+ EXIT(1);
+ }
+ continue;
+#endif
+#if !_WIN32 || _WINIX
+ case LNKTYPE:
+ while (link(header.linkname, path))
+ if (unlink(path))
+ {
+ fprintf(stderr, "%s: %s: cannot link to %s\n", state.id, path, header.linkname);
+ EXIT(1);
+ }
+ continue;
+#endif
+ default:
+ fprintf(stderr, "%s: %s: file type %c ignored\n", state.id, path, header.typeflag);
+ if (skip(stdin, gz, buf, number(header.size)))
+ EXIT(1);
+ continue;
+ }
+ if (chmod(path, mode))
+ fprintf(stderr, "%s: %s: cannot change mode to %03o\n", state.id, path, mode);
+ }
+ if (clear)
+ fprintf(stderr, "%*s", clear, "\r");
+ if (!state.files)
+ fprintf(stderr, "%s: warning: empty archive\n", state.id);
+ else if (verbose)
+ fprintf(stderr, "%lu file%s, %lu block%s\n", state.files, state.files == 1 ? "" : "s", state.blocks, state.blocks == 1 ? "" : "s");
+#if defined(_SEAR_EXEC)
+#if !defined(_SEAR_ARGS)
+#define _SEAR_ARGS 0
+#endif
+ if (install && sear_exec(_SEAR_EXEC, argv, _SEAR_ARGS))
+ {
+ Sleep(2 * 1000);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+#endif /* _RATZ_C */
diff --git a/src/cmd/INIT/regress.sh b/src/cmd/INIT/regress.sh
new file mode 100644
index 0000000..a4417c4
--- /dev/null
+++ b/src/cmd/INIT/regress.sh
@@ -0,0 +1,1463 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: regress - run regression tests in command.tst
+
+command=regress
+case $(getopts '[-][123:xyz]' opt --xyz 2>/dev/null; echo 0$opt) in
+0123) USAGE=$'
+[-?
+@(#)$Id: regress (AT&T Research) 2012-02-02 $
+]
+'$USAGE_LICENSE$'
+[+NAME?regress - run regression tests]
+[+DESCRIPTION?\bregress\b runs the tests in \aunit\a, or
+ \aunit\a\b.tst\b if \aunit\a does not exist. If \acommand\a is omitted
+ then it is assumed to be the base name of \aunit\a. All testing is done
+ in the temporary directory \aunit\a\b.tmp\b.]
+[+?Default test output lists the \anumber\a and \adescription\a for
+ each active \bTEST\b group and the \anumber\a:\aline\a for each
+ individual \bEXEC\b test. Each test that fails results in a diagnostic
+ that contains the word \bFAILED\b; no other diagnostics contain this
+ word.]
+[b:ignore-space?Ignore space differences when comparing expected
+ output.]
+[i:pipe-input?Repeat each test with the standard input redirected through a
+ pipe.]
+[k:keep?Enable \bcore\b dumps, exit after the first test that fails,
+ and do not remove the temporary directory \aunit\a\b.tmp\b.]
+[l:local-fs?Force \aunit\a\b.tmp\b to be in a local filesystem.]
+[o:pipe-output?Repeat each test with the standard output redirected through
+ a pipe.]
+[p:pipe-io?Repeat each test with the standard input and standard output
+ redirected through pipes.]
+[q:quiet?Output information on \bFAILED\b tests only.]
+[r!:regular?Run each test with the standard input and standard output
+ redirected through regular files.]
+[t:test?Run only tests matching \apattern\a. Tests are numbered and
+ consist of at least two digits (0 filled if necessary.) Tests matching
+ \b+(0)\b are always run.]:[pattern]
+[x:trace?Enable debug tracing.]
+[v:verbose?List differences between actual (<) and expected (>) output,
+ errors and exit codes. Also disable long output line truncation.]
+
+unit [ command [ arg ... ] ]
+
+[+INPUT FILES?The regression test file \aunit\a\b.tst\b is a \bksh\b(1)
+ script that is executed in an environment with the following functions
+ defined:]
+ {
+ [+BODY \b{ ... }?Defines the test body; used for complex tests.]
+ [+CD \b\adirectory\a?Create and change to working directory for
+ one test.]
+ [+CLEANUP \b\astatus\a?Called at exit time to remove the
+ temporary directory \aunit\a\b.tmp\b, list the tests totals via
+ \bTALLY\b, and exit with status \astatus\a.]
+ [+COMMAND \b\aarg\a ...?Runs the current command under test with
+ \aarg\a ... appended to the default args.]
+ [+CONTINUE?The background job must be running.]
+ [+COPY \b\afrom to\a?Copy file \afrom\a to \ato\a. \afrom\a may
+ be a regular file or \bINPUT\b, \bOUTPUT\b or \bERROR\b. Post
+ test comparisons are still done for \afrom\a.]
+ [+DIAGNOSTICS \b[ \b1\b | \b0\b | \apattern\a ]]?No argument or an
+ argument of \b1\b declares that diagnostics are to expected for
+ the remainder of the current \bTEST\b; \b0\b reverts to the default
+ state that diagnostics are not expected; otherwise the argument
+ is a \bksh\b(1) pattern that must match the non-empty contents
+ of the standard error.]
+ [+DO \b\astatement\a?Defines additional statements to be executed
+ for the current test. \astatement\a may be a { ... } group.]
+ [+EMPTY \bINPUT|OUTPUT|ERROR|SAME?The corresponding file is
+ expected to be empty.]
+ [+ERROR \b[ \b-e\b \afilter\a ]] [ \b-n\b ]] \afile\a | - \adata\a ...?The
+ standard error is expected to match either the contents
+ of \afile\a or the line \adata\a. \bERROR -n\b does not
+ append a newline to \adata\a. \afilter\a is a shell command
+ or pipeline that reads standard input and writes standard
+ output that is applied to ERROR before comparison with the
+ expected contents.]
+ [+EXEC \b[ \aarg\a ... ]]?Runs the command under test with
+ optional arguments. \bINPUT\b, \bOUTPUT\b, \bERROR\b, \bEXIT\b
+ and \bSAME\b calls following this \bEXEC\b up until the next
+ \bEXEC\b or the end of the script provide details for the
+ expected results. If no arguments are specified then the
+ arguments from the previious \bEXEC\b in the current \bTEST\b
+ group are used, or no arguments if this is the first \bEXEC\b
+ in the group.]
+ [+EXIT \b\astatus\a?The command exit status is expected to match
+ the pattern \astatus\a.]
+ [+EXITED?The background job must have exited.]
+ [+EXPORT \b[-]] \aname\a=\avalue\a ...?Export environment
+ variables for one test.]
+ [+FATAL \b\amessage\a ...?\amessage\a is printed on the standard
+ error and \bregress\b exits with status \b1\b.]
+ [+FIFO \bINPUT|OUTPUT|ERROR\b [ \b-n\b ]] \afile\a | - \adata\a ...?The
+ \bIO\B file is a fifo.]
+ [+IF \b\acommand\a [\anote\a]]?If the \bsh\b(1) \acommand\a exits
+ 0 then tests until the next \bELIF\b, \bELSE\b or \bFI\b are
+ enabled. Otherwise those tests are skipped. \bIF\b ... \bFI\b
+ may be nested, but must not cross \bTEST\b boundaries. \anote\a
+ is listed on the standard error if the correspoding test block
+ is enabled; \bIF\b, \bELIF\b, \bELSE\b may nave a \anote\a
+ operand.]
+ [+IGNORE \b\afile\a ...?\afile\a is ignored for subsequent result
+ comparisons. \afile\a may be \bOUTPUT\b or \bERROR\b.]
+ [+IGNORESPACE?Ignore space differences when comparing expected
+ output.]
+ [+INCLUDE \b\afile\a ...?One or more \afile\a operands are read
+ via the \bksh\b(1) \b.\b(1) command. \bVIEW\b is used to locate
+ the files.]
+ [+INFO \b\adescription\a?\adescription\a is printed on the
+ standard error.]
+ [+INITIALIZE?Called by \bregress\b to initialize a each
+ \bTEST\b group.]
+ [+INPUT \b[ \b-e\b \afilter\a ]] [ \b-n\b ]] \afile\a | - \adata\a ...?The
+ standard input is set to either the contents of \afile\a
+ or the line \adata\a. \bINPUT -n\b does not append a newline
+ to \adata\a. \afilter\a is a shell command or pipeline that
+ reads standard input and writes standard output that is
+ applied to OUTPUT before comparison with the expected contents.]
+ [+INTRO?Called by \bregress\b to introduce all \bTEST\b
+ groups.]
+ [+IO \b[ \bFIFO\b | \bPIPE\b ]] \bINPUT|OUTPUT|ERROR\b [ \b-e\b \afilter\a ]] [ \b-n\b ]] \afile\a | - \adata\a ...?Internal
+ support for the \bINPUT\b, \bOUTPUT\b and \bERROR\b functions.]
+ [+JOB \b\aop\a [ ... ]]?Like \bEXEC\b except the command is run
+ as a background job for the duration of the group or until it
+ is killed via \bKILL\b.]
+ [+KEEP \b\apattern\a ...?The temporary directory is cleared for
+ each test. Files matching \apattern\a are retained between
+ tests.]
+ [+KILL \b[ \asignal\a ]]?Kill the background job with \asignal\a
+ [ \bSIGKILL\b ]].]
+ [+MOVE \b\afrom to\a?Rename file \afrom\a to \ato\a. \afrom\a may
+ be a regular file or \bINPUT\b, \bOUTPUT\b or \bERROR\b. Post
+ test comparisons are ignored for \afrom\a.]
+ [+NOTE \b\acomment\a?\acomment\a is added to the current test
+ trace output.]
+ [+OUTPUT \b[ \b-e\b \afilter\a ]] [ \b-n\b ]] \afile\a | - \adata\a ...?The
+ standard output is expected to match either the contents
+ of \afile\a or the line \adata\a. \bOUTPUT -n\b does not
+ append a newline to \adata\a. \afilter\a is a shell command
+ or pipeline that reads standard input and writes standard
+ output that is applied to ERROR before comparison with the
+ expected contents.]
+ [+PIPE \bINPUT|OUTPUT|ERROR\b [ \b-n\b ]] \afile\a | - \adata\a ...?The
+ \bIO\B file is a pipe.]
+ [+PROG \b\acommand\a [ \aarg\a ... ]]?\acommand\a is run with
+ optional arguments.]
+ [+REMOVE \b\afile\a ...?\afile\a ... are removed after the
+ current test is done.]
+ [+RUN?Called by \bregress\b to run the current test.]
+ [+SAME \b\anew old\a?\anew\a is expected to be the same as
+ \aold\a after the current test completes.]
+ [+SET \b[\bno\b]]\aname\a[=\avalue\a]]?Set the command line
+ option --\aname\a. The setting is in effect for all tests until
+ the next explicit \bSET\b.]
+ [+TALLY?Called by \bregress\b display the \bTEST\b results.]
+ [+TEST \b\anumber\a [ \adescription\a ... ]]?Define a new test
+ group labelled \anumber\a with optional \adescripion\a.]
+ [+TITLE \b[+]] \atext\a?Set the \bTEST\b output title to
+ \atext\a. If \b+\b is specified then \atext\a is appended to
+ the default title. The default title is the test file base
+ name, and, if different from the test file base name, the test
+ unit base name.]
+ [+TWD \b[ \adir\a ... ]]?Set the temporary test dir to \adir\a.
+ The default is \aunit\a\b.tmp\b, where \aunit\a is the test
+ input file sans directory and suffix. If \adir\a matches \b/*\b
+ then it is the directory name; if \adir\a is non-null then the
+ prefix \b${TMPDIR:-/tmp}\b is added; otherwise if \adir\a is
+ omitted then
+ \b${TMPDIR:-/tmp}/tst-\b\aunit\a-$$-$RANDOM.\b\aunit\a is
+ used.]
+ [+UMASK \b[ \amask\a ]]?Run subsequent tests with \bumask\b(1)
+ \amask\a. If \amask\a is omitted then the original \bumask\b is
+ used.]
+ [+UNIT \b\acommand\a [ \aarg\a ... ]]?Define the command and
+ optional default arguments to be tested. \bUNIT\b explicitly
+ overrides the default command name derived from the test script
+ file name. A \acommand\a operand with optional arguments
+ overrides the \bUNIT\b \acommand\a and arguments, with the
+ exception that if the \bUNIT\b \acommand\a is \b-\b or \b+\b
+ the \bUNIT\b arguments are appended to the operand or default
+ unit command and arguments.]
+ [+VIEW \b\avar\a [ \afile\a ]]?\avar\a is set to the full
+ pathname of \avar\a [ \afile\a ]] in the current \b$VPATH\b
+ view if defined.]
+ }
+[+SEE ALSO?\bnmake\b(1), \bksh\b(1)]
+'
+ ;;
+*) USAGE='ko:[[no]name[=value]]t:[test]v unit [path [arg ...]]'
+ ;;
+esac
+
+function FATAL # message
+{
+ print -r -u2 "$command: $*"
+ GROUP=FINI
+ exit 1
+}
+
+function EMPTY
+{
+ typeset i
+ typeset -n ARRAY=$1
+ for i in ${!ARRAY[@]}
+ do unset ARRAY[$i]
+ done
+}
+
+function INITIALIZE # void
+{
+ typeset i j
+ cd "$TWD"
+ case $KEEP in
+ "") RM *
+ ;;
+ *) for i in *
+ do case $i in
+ !($KEEP)) j="$j $i" ;;
+ esac
+ done
+ case $j in
+ ?*) RM $j ;;
+ esac
+ ;;
+ esac
+ : >INPUT >OUTPUT.ex >ERROR.ex
+ BODY=""
+ COPY=""
+ DIAGNOSTICS=""
+ DONE=""
+ ERROR=""
+ EXIT=0
+ IGNORE=""
+ INIT=""
+ INPUT=""
+ MOVE=""
+ OUTPUT=""
+ EMPTY FILE
+ EMPTY FILTER
+ EMPTY SAME
+ EMPTY TYPE
+}
+
+function INTRO
+{
+ typeset base command
+
+ if [[ ! $TEST_quiet ]]
+ then base=${REGRESS##*/}
+ base=${base%.tst}
+ command=${COMMAND##*/}
+ command=${command%' '*}
+ set -- $TITLE
+ TITLE=
+ case $1 in
+ ''|+) if [[ $command == $base ]]
+ then TITLE=$COMMAND
+ else TITLE="$COMMAND, $base"
+ fi
+ if (( $# ))
+ then shift
+ fi
+ ;;
+ esac
+ while (( $# ))
+ do if [[ $TITLE ]]
+ then TITLE="$TITLE, $1"
+ else TITLE="$1"
+ fi
+ shift
+ done
+ print -u2 "TEST $TITLE"
+ fi
+}
+
+function TALLY # extra message text
+{
+ typeset msg
+ case $GROUP in
+ INIT) ;;
+ *) msg="TEST $TITLE, $TESTS test"
+ case $TESTS in
+ 1) ;;
+ *) msg=${msg}s ;;
+ esac
+ msg="$msg, $ERRORS error"
+ case $ERRORS in
+ 1) ;;
+ *) msg=${msg}s ;;
+ esac
+ if (( $# ))
+ then msg="$msg, $*"
+ fi
+ print -u2 "$msg"
+ GROUP=INIT
+ TESTS=0
+ ERRORS=0
+ ;;
+ esac
+}
+
+function TITLE # text
+{
+ TITLE=$@
+}
+
+function UNWIND
+{
+ while (( COND > 1 ))
+ do print -r -u2 "$command: line $LINE: no matching FI for IF on line ${COND_LINE[COND]}"
+ (( COND-- ))
+ done
+ if (( COND > 0 ))
+ then (( COND = 0 ))
+ FATAL "line $LINE: no matching FI for IF on line ${COND_LINE[COND+1]}"
+ fi
+ if [[ $JOBPID ]]
+ then if [[ $JOBPID != 0 ]]
+ then kill -KILL $JOBPID 2>/dev/null
+ wait
+ fi
+ JOBPID=
+ fi
+ JOBSTATUS=
+ JOBOP=
+ wait
+}
+
+function CLEANUP # status
+{
+ typeset note
+
+ if [[ $GROUP != INIT ]]
+ then if [[ ! $TEST_keep ]]
+ then cd $SOURCE
+ if [[ $TEST_local ]]
+ then RM ${TEST_local}
+ fi
+ RM "$TWD"
+ fi
+ if (( $1 )) && [[ $GROUP != FINI ]]
+ then note=terminated
+ fi
+ fi
+ TALLY $note
+ [[ $TEST_keep ]] || UNWIND
+ exit $1
+}
+
+function RUN # [ op ]
+{
+ typeset i r=1
+ [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG
+#print -u2 AHA#$LINENO $0 GROUP=$GROUP ITEM=$ITEM FLUSHED=$FLUSHED JOBOP=$JOBOP
+ case $GROUP in
+ INIT) RM "$TWD"
+ if [[ $TEST_local ]]
+ then TEST_local=${TMPDIR:-/tmp}/rt-$$/${TWD##*/}
+ mkdir -p "$TEST_local" && ln -s "$TEST_local" "$TWD" || FATAL "$TWD": cannot create directory
+ TEST_local=${TEST_local%/*}
+ else mkdir "$TWD" || FATAL "$TWD": cannot create directory
+ fi
+ cd "$TWD"
+ TWD=$PWD
+ : > rmu
+ if rm -u rmu >/dev/null 2>&1
+ then TEST_rmu=-u
+ else rm rmu
+ fi
+ if [[ $UNIT ]]
+ then set -- "${ARGV[@]}"
+ case $1 in
+ ""|[-+]*)
+ UNIT $UNIT "${ARGV[@]}"
+ ;;
+ *) UNIT "${ARGV[@]}"
+ ;;
+ esac
+ fi
+ INTRO
+ ;;
+ FINI) ;;
+ $TEST_select)
+ if [[ $ITEM == $FLUSHED ]]
+ then return 0
+ fi
+ FLUSHED=$ITEM
+ if (( COND_SKIP[COND] ))
+ then return 1
+ fi
+ ((COUNT++))
+ if (( $ITEM <= $LASTITEM ))
+ then LABEL=$TEST#$COUNT
+ else LASTITEM=$ITEM
+ LABEL=$TEST:$ITEM
+ fi
+ TEST_file=""
+ exec >/dev/null
+ for i in $INPUT
+ do case " $OUTPUT " in
+ *" $i "*)
+ if [[ -f $i.sav ]]
+ then cp $i.sav $i
+ COMPARE="$COMPARE $i"
+ elif [[ -f $i ]]
+ then cp $i $i.sav
+ COMPARE="$COMPARE $i"
+ fi
+ ;;
+ esac
+ done
+ for i in $OUTPUT
+ do case " $COMPARE " in
+ *" $i "*)
+ ;;
+ *) COMPARE="$COMPARE $i"
+ ;;
+ esac
+ done
+ for i in $INIT
+ do $i $TEST INIT
+ done
+#print -u2 AHA#$LINENO $0 GROUP=$GROUP ITEM=$ITEM JOBOP=$JOBOP JOBPID=$JOBPID JOBSTATUS=$JOBSTATUS
+ if [[ $JOBPID != 0 && ( $JOBPID || $JOBSTATUS ) ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ RESULTS
+ elif [[ $BODY ]]
+ then SHOW=$NOTE
+ if [[ ! $TEST_quiet ]]
+ then print -r -u2 " $SHOW"
+ fi
+ for i in $BODY
+ do $i $TEST BODY
+ done
+ else SHOW=
+ if [[ ${TYPE[INPUT]} == PIPE ]]
+ then if [[ ${TYPE[OUTPUT]} == PIPE ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ cat <$TWD/INPUT | COMMAND "${ARGS[@]}" | cat >$TWD/OUTPUT
+ RESULTS 'pipe input'
+ else if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ cat <$TWD/INPUT | COMMAND "${ARGS[@]}" >$TWD/OUTPUT
+ RESULTS 'pipe io'
+ fi
+ elif [[ ${TYPE[OUTPUT]} == PIPE ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ COMMAND "${ARGS[@]}" <$TWD/INPUT | cat >$TWD/OUTPUT
+ RESULTS 'pipe output'
+ else if [[ $TEST_regular ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ if [[ ${TYPE[INPUT]} == FIFO ]]
+ then COMMAND "${ARGS[@]}" >$TWD/OUTPUT
+ else COMMAND "${ARGS[@]}" <$TWD/INPUT >$TWD/OUTPUT
+ fi
+ RESULTS
+ fi
+ if [[ $TEST_pipe_input ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ (trap '' PIPE; cat <$TWD/INPUT 2>/dev/null; exit 0) | COMMAND "${ARGS[@]}" >$TWD/OUTPUT
+ STATUS=$?
+ RESULTS 'pipe input'
+ fi
+ if [[ $TEST_pipe_output ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ COMMAND "${ARGS[@]}" <$TWD/INPUT | cat >$TWD/OUTPUT
+ STATUS=$?
+ RESULTS 'pipe output'
+ fi
+ if [[ $TEST_pipe_io ]]
+ then if [[ ! $TEST_quiet ]]
+ then print -nu2 "$LABEL"
+ fi
+ (trap '' PIPE; cat <$TWD/INPUT 2>/dev/null; exit 0) | COMMAND "${ARGS[@]}" | cat >$TWD/OUTPUT
+ STATUS=$?
+ RESULTS 'pipe io'
+ fi
+ fi
+ set -- $COPY
+ COPY=""
+ while :
+ do case $# in
+ 0|1) break ;;
+ *) cp $1 $2 ;;
+ esac
+ shift 2
+ done
+ set -- $MOVE
+ MOVE=""
+ while (( $# > 1 ))
+ do mv $1 $2
+ shift 2
+ done
+ fi
+ for i in $DONE
+ do $i $TEST DONE $STATUS
+ done
+ COMPARE=""
+ r=0
+ ;;
+ esac
+ if [[ $COMMAND_ORIG ]]
+ then COMMAND=$COMMAND_ORIG
+ COMMAND_ORIG=
+ ARGS=(${ARGS_ORIG[@]})
+ fi
+ return $r
+}
+
+function DO # cmd ...
+{
+ [[ $GROUP == $TEST_select ]] || return 1
+ (( COND_SKIP[COND] )) && return 1
+ [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK
+ return 0
+}
+
+function UNIT # cmd arg ...
+{
+ typeset cmd=$1
+ case $cmd in
+ [-+]) shift
+ if (( UNIT_READONLY ))
+ then COMMAND="$COMMAND $*"
+ else #BUG# ARGV=("${ARGV[@]}" "$@")
+ set -- "${ARGV[@]}" "$@"
+ ARGV=("$@")
+ fi
+ return
+ ;;
+ esac
+ (( UNIT_READONLY )) && return
+ if [[ $UNIT ]] && (( $# <= 1 ))
+ then set -- "${ARGV[@]}"
+ case $1 in
+ "") set -- "$cmd" ;;
+ [-+]*) set -- "$cmd" "${ARGV[@]}" ;;
+ *) cmd=$1 ;;
+ esac
+ fi
+ UNIT=
+ COMMAND=$cmd
+ shift
+ typeset cmd=$(whence $COMMAND)
+ if [[ ! $cmd ]]
+ then FATAL $COMMAND: not found
+ elif [[ ! $cmd ]]
+ then FATAL $cmd: not found
+ fi
+ case $# in
+ 0) ;;
+ *) COMMAND="$COMMAND $*" ;;
+ esac
+}
+
+function TWD # [ dir ]
+{
+ case $1 in
+ '') TWD=${TWD##*/}; TWD=${TMPDIR:-/tmp}/tst-${TWD%.*}-$$-$RANDOM ;;
+ /*) TWD=$1 ;;
+ *) TWD=${TMPDIR:-/tmp}/$1 ;;
+ esac
+}
+
+function TEST # number description arg ...
+{
+ RUN
+ LINE=$TESTLINE
+ UNWIND
+ COUNT=0
+ LASTITEM=0
+ case $1 in
+ -) ((LAST++)); TEST=$LAST ;;
+ +([0123456789])) LAST=$1 TEST=$1 ;;
+ *) LAST=0${1/[!0123456789]/} TEST=$1 ;;
+ esac
+ NOTE=
+ if [[ ! $TEST_quiet && $TEST == $TEST_select ]] && (( ! COND_SKIP[COND] ))
+ then print -r -u2 "$TEST $2"
+ fi
+ unset ARGS
+ unset EXPORT
+ EXPORTS=0
+ TEST_file=""
+ if [[ $TEST != ${GROUP}* ]]
+ then GROUP=${TEST%%+([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ])}
+ if [[ $GROUP == $TEST_select ]] && (( ! COND_SKIP[COND] ))
+ then INITIALIZE
+ fi
+ fi
+ ((SUBTESTS=0))
+ [[ $TEST == $TEST_select ]] && (( ! COND_SKIP[COND] ))
+}
+
+function EXEC # arg ...
+{
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ if ((SUBTESTS++))
+ then RUN
+ fi
+ case $# in
+ 0) set -- "${ARGS[@]}" ;;
+ esac
+ ITEM=$LINE
+ NOTE="$(print -r -f '%q ' -- $COMMAND_ORIG "$@")${JOBPID:+&}"
+ ARGS=("$@")
+}
+
+function JOB # arg ...
+{
+ JOBPID=0
+ EXEC "$@"
+}
+
+function CONTINUE
+{
+ RUN || return
+ JOBOP=CONTINUE
+ ITEM=$LINE
+ NOTE="$(print -r -f '%q ' -- $JOBOP)"
+#print -u2 AHA#$LINENO JOBOP=$JOBOP ITEM=$ITEM NOTE=$NOTE
+}
+
+function EXITED
+{
+ RUN || return
+ JOBOP=EXITED
+ ITEM=$LINE
+ NOTE="$(print -r -f '%q ' -- $JOBOP)"
+#print -u2 AHA#$LINENO JOBOP=$JOBOP ITEM=$ITEM NOTE=$NOTE
+}
+
+function KILL # [ signal ]
+{
+ RUN || return
+ JOBOP=$2
+ [[ $JOBOP ]] || JOBOP=KILL
+ ITEM=$LINE
+ NOTE="$(print -r -f '%q ' -- $JOBOP)"
+}
+
+function CD
+{
+ RUN
+ if [[ $GROUP == $TEST_select ]] && (( ! COND_SKIP[COND] ))
+ then mkdir -p "$@" && cd "$@" || FATAL cannot initialize working directory "$@"
+ fi
+}
+
+function EXPORT
+{
+ typeset x n v
+ if [[ $GROUP == INIT ]]
+ then for x
+ do n=${x%%=*}
+ v=${x#*=}
+ ENVIRON[ENVIRONS++]=$n="'$v'"
+ done
+ else RUN
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ for x
+ do n=${x%%=*}
+ v=${x#*=}
+ EXPORT[EXPORTS++]=$n="'$v'"
+ done
+ fi
+}
+
+function FLUSH
+{
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ if ((SUBTESTS++))
+ then RUN
+ fi
+}
+
+function PROG # cmd arg ...
+{
+ typeset command args
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ ITEM=$LINE
+ NOTE="$(print -r -f '%q ' -- "$@")"
+ COMMAND_ORIG=$COMMAND
+ COMMAND=$1
+ shift
+ ARGS_ORIG=(${ARGS[@]})
+ ARGS=("$@")
+}
+
+function NOTE # description
+{
+ NOTE=$*
+}
+
+function IO # [ PIPE ] INPUT|OUTPUT|ERROR [-f*|-n] file|- data ...
+{
+ typeset op i v f file type x
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG
+ while :
+ do case $1 in
+ FIFO|PIPE) type=$1; shift ;;
+ *) break ;;
+ esac
+ done
+ op=$1
+ shift
+ [[ $type ]] && TYPE[$op]=$type
+ FILTER[$op]=
+ file=$TWD/$op
+ while :
+ do case $1 in
+ -x) x=1
+ shift
+ ;;
+ -e) (( $# > 1 )) && shift
+ FILTER[$op]=$1
+ shift
+ ;;
+ -e*) FILTER[$op]=${1#-e}
+ shift
+ ;;
+ -f*|-n) f=$1
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+ done
+ case $# in
+ 0) ;;
+ *) case $1 in
+ -) ;;
+ *) file=$1
+ eval i='$'$op
+ case " $i " in
+ *" $file "*)
+ ;;
+ *) eval $op='"$'$op' $file"'
+ ;;
+ esac
+ ;;
+ esac
+ shift
+ ;;
+ esac
+ case " $IGNORE " in
+ *" $file "*)
+ for i in $IGNORE
+ do case $i in
+ $file) ;;
+ *) v="$v $i" ;;
+ esac
+ done
+ IGNORE=$v
+ ;;
+ esac
+ FILE[$op]=$file
+ case $op in
+ OUTPUT|ERROR)
+ file=$file.ex
+ if [[ $file != /* ]]
+ then file=$TWD/$file
+ fi
+ ;;
+ esac
+ #unset SAME[$op]
+ SAME[$op]=
+ if [[ $file == /* ]]
+ then RM $file.sav
+ else RM $TWD/$file.sav
+ fi
+ if [[ $file == */* ]]
+ then mkdir -p ${file%/*}
+ fi
+ if [[ $file != */ ]]
+ then if [[ $type == FIFO ]]
+ then rm -f $file
+ mkfifo $file
+ fi
+ if [[ ${TYPE[$op]} != FIFO ]]
+ then if [[ $JOBOP ]]
+ then case $#:$f in
+ 0:) ;;
+ *:-f) printf -- "$@" ;;
+ *:-f*) printf -- "${f#-f}""$@" ;;
+ *) print $f -r -- "$@" ;;
+ esac >> $file
+ else case $#:$f in
+ 0:) ;;
+ *:-f) printf -- "$@" ;;
+ *:-f*) printf -- "${f#-f}""$@" ;;
+ *) print $f -r -- "$@" ;;
+ esac > $file
+ fi
+ elif [[ $#:$f != 0: ]]
+ then case $#:$f in
+ *:-f) printf -- "$@" ;;
+ *:-f*) printf -- "${f#-f}""$@" ;;
+ *) print $f -r -- "$@" ;;
+ esac >> $file &
+ fi
+ if [[ $x ]]
+ then chmod +x $file
+ fi
+ fi
+}
+
+function INPUT # file|- data ...
+{
+ IO $0 "$@"
+}
+
+function COPY # from to
+{
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ COPY="$COPY $@"
+}
+
+function MOVE # from to
+{
+ typeset f
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ for f
+ do case $f in
+ INPUT|OUTPUT|ERROR)
+ f=$TWD/$f
+ ;;
+ /*) ;;
+ *) f=$PWD/$f
+ ;;
+ esac
+ MOVE="$MOVE $f"
+ done
+}
+
+function SAME # new old
+{
+ typeset i file v
+ if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] ))
+ then return
+ fi
+ case $# in
+ 2) case $1 in
+ INPUT) cat $2 > $1; return ;;
+ esac
+ SAME[$1]=$2
+ file=$1
+ COMPARE="$COMPARE $1"
+ ;;
+ 3) SAME[$2]=$3
+ file=$2
+ eval i='$'$1
+ case " $i " in
+ *" $2 "*)
+ ;;
+ *) eval $1='"$'$1' $2"'
+ ;;
+ esac
+ COMPARE="$COMPARE $2"
+ ;;
+ esac
+ case " $IGNORE " in
+ *" $file "*)
+ for i in $IGNORE
+ do case $i in
+ $file) ;;
+ *) v="$v $i" ;;
+ esac
+ done
+ IGNORE=$v
+ ;;
+ esac
+}
+
+function OUTPUT # file|- data ...
+{
+ IO $0 "$@"
+}
+
+function ERROR # file|- data ...
+{
+ IO $0 "$@"
+}
+
+function RM # rm(1) args
+{
+ if [[ ! $TEST_rmu ]]
+ then chmod -R u+rwx "$@" >/dev/null 2>&1
+ fi
+ rm $TEST_rmu $TEST_rmflags "$@"
+}
+
+function REMOVE # file ...
+{
+ typeset i
+ for i
+ do RM $i $i.sav
+ done
+}
+
+function IGNORE # file ...
+{
+ typeset i
+ for i
+ do case $i in
+ INPUT|OUTPUT|ERROR)
+ i=$TWD/$i
+ ;;
+ esac
+ case " $IGNORE " in
+ *" $i "*)
+ ;;
+ *) IGNORE="$IGNORE $i"
+ ;;
+ esac
+ done
+}
+
+function KEEP # pattern ...
+{
+ typeset i
+ for i
+ do case $KEEP in
+ "") KEEP="$i" ;;
+ *) KEEP="$KEEP|$i" ;;
+ esac
+ done
+}
+
+function DIAGNOSTICS # [ 1 | 0 ]
+{
+ case $#:$1 in
+ 0:|1:1) DIAGNOSTICS=1
+ EXIT='*'
+ ;;
+ 1:|1:0) DIAGNOSTICS=""
+ EXIT=0
+ ;;
+ *) DIAGNOSTICS=$1
+ EXIT='*'
+ ;;
+ esac
+}
+
+function IGNORESPACE
+{
+ : ${IGNORESPACE=-b}
+}
+
+function EXIT # status
+{
+ EXIT=$1
+}
+
+function INFO # info description
+{
+ typeset -R15 info=$1
+ if [[ ! $1 ]]
+ then info=no
+ fi
+ shift
+ if [[ ! $TEST_quiet ]]
+ then print -r -u2 "$info " "$@"
+ fi
+}
+
+function COMMAND # arg ...
+{
+ typeset input
+ ((TESTS++))
+ case " ${ENVIRON[*]} ${EXPORT[*]}" in
+ *' 'LC_ALL=*)
+ ;;
+ *' 'LC_+([A-Z])=*)
+ EXPORT[EXPORTS++]="LC_ALL="
+ ;;
+ esac
+ if [[ $TEST_keep ]]
+ then (
+ PS4=''
+ set -x
+ print -r -- "${ENVIRON[@]}" "${EXPORT[@]}" "PATH=$PATH" $COMMAND "$@"
+ ) 2>&1 >/dev/null |
+ sed -e 's,^print -r -- ,,' -e 's,$, "$@",' >$TWD/COMMAND
+ chmod +x $TWD/COMMAND
+ fi
+ if [[ $UMASK != $UMASK_ORIG ]]
+ then : >$TWD/ERROR
+ umask $UMASK
+ fi
+ if [[ ${TYPE[INPUT]} == FIFO && ${FILE[INPUT]} == */INPUT ]]
+ then input="< ${FILE[INPUT]}"
+ fi
+ if [[ $TEST_trace ]]
+ then set +x
+ eval print -u2 "$PS4" "${ENVIRON[@]}" "${EXPORT[@]}" PATH='$PATH' '$'COMMAND '"$@"' '$input' '"2>$TWD/ERROR"' '"${JOBPID:+&}"'
+ fi
+ eval "${ENVIRON[@]}" "${EXPORT[@]}" PATH='$PATH' '$'COMMAND '"$@"' $input "2>$TWD/ERROR" "${JOBPID:+&}"
+ STATUS=$?
+ [[ $TEST_trace ]] && set -x
+ if [[ $JOBPID ]]
+ then JOBPID=$!
+ fi
+ [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG
+ return $STATUS
+}
+
+function RESULTS # pipe*
+{
+ typeset i j k s failed ignore io op
+ if [[ $1 ]]
+ then io="$1 "
+ fi
+ [[ $JOBOP || $JOBPID || $JOBSTATUS ]] && sleep 1
+ for i in $COMPARE $TWD/OUTPUT $TWD/ERROR
+ do case " $IGNORE $ignore $MOVE " in
+ *" $i "*) continue ;;
+ esac
+ ignore="$ignore $i"
+ op=${i##*/}
+ if [[ ${FILTER[$op]} ]]
+ then eval "{ ${FILTER[$op]} ;} < $i > $i.fi"
+ mv $i.fi $i
+ fi
+ j=${SAME[$op]}
+ if [[ ! $j ]]
+ then if [[ $i == /* ]]
+ then k=$i
+ else k=$TWD/$i
+ fi
+ for s in ex sav err
+ do [[ -f $k.$s ]] && break
+ done
+ j=$k.$s
+ fi
+ if [[ "$DIAGNOSTICS" && $i == */ERROR ]]
+ then if [[ $STATUS == 0 && ! -s $TWD/ERROR || $DIAGNOSTICS != 1 && $(<$i) != $DIAGNOSTICS ]]
+ then failed=$failed${failed:+,}DIAGNOSTICS
+ if [[ $TEST_verbose && $DIAGNOSTICS != 1 ]]
+ then print -u2 " ===" "diagnostic pattern '$DIAGNOSTICS' did not match" ${i#$TWD/} "==="
+ cat $i >&2
+ fi
+ fi
+ continue
+ fi
+ diff $IGNORESPACE $i $j >$i.diff 2>&1
+ if [[ -s $i.diff ]]
+ then failed=$failed${failed:+,}${i#$TWD/}
+ if [[ $TEST_verbose ]]
+ then print -u2 " ===" diff $IGNORESPACE ${i#$TWD/} "<actual >expected ==="
+ cat $i.diff >&2
+ fi
+ fi
+ done
+ if [[ $JOBOP ]]
+ then if [[ $JOBPID ]] && ! kill -0 $JOBPID 2>/dev/null
+ then wait $JOBPID
+ JOBSTATUS=$?
+ JOBPID=
+ fi
+#print -u2 AHA#$LINENO JOBOP=$JOBOP JOBPID=$JOBPID JOBSTATUS=$JOBSTATUS
+ case $JOBOP in
+ CONTINUE)
+ if [[ ! $JOBPID ]]
+ then failed=$failed${failed:+,}EXITED
+ fi
+ ;;
+ EXITED) if [[ $JOBPID ]]
+ then failed=$failed${failed:+,}RUNNING
+ fi
+ ;;
+ *) if [[ ! $JOBPID ]]
+ then failed=$failed${failed:+,}EXITED
+ fi
+ if ! kill -$JOBOP $JOBPID 2>/dev/null
+ then failed=$failed${failed:+,}KILL-$JOBOP
+ fi
+ ;;
+ esac
+ JOBOP=
+ fi
+ if [[ ! $failed && $STATUS != $EXIT ]]
+ then failed="exit code $EXIT expected -- got $STATUS"
+ fi
+ if [[ $failed ]]
+ then ((ERRORS++))
+ if [[ ! $TEST_quiet ]]
+ then SHOW="FAILED ${io}[ $failed ] $NOTE"
+ print -r -u2 " $SHOW"
+ fi
+ if [[ $TEST_keep ]]
+ then GROUP=FINI
+ exit
+ fi
+ elif [[ ! $TEST_quiet ]]
+ then SHOW=$NOTE
+ print -r -u2 " $SHOW"
+ fi
+}
+
+function SET # [no]name[=value]
+{
+ typeset i r
+ if [[ $TEST ]]
+ then RUN
+ fi
+ for i
+ do if [[ $i == - ]]
+ then r=1
+ elif [[ $i == + ]]
+ then r=
+ else if [[ $i == no?* ]]
+ then i=${i#no}
+ v=
+ elif [[ $i == *=* ]]
+ then v=${i#*=}
+ if [[ $v == 0 ]]
+ then v=
+ fi
+ i=${i%%=*}
+ else v=1
+ fi
+ i=${i//-/_}
+ if [[ $r ]]
+ then READONLY[$i]=1
+ elif [[ ${READONLY[$i]} ]]
+ then continue
+ fi
+ eval TEST_$i=$v
+ fi
+ done
+}
+
+function VIEW # var [ file ]
+{
+ nameref var=$1
+ typeset i bwd file pwd view root offset
+ if [[ $var ]]
+ then return 0
+ fi
+ case $# in
+ 1) file=$1 ;;
+ *) file=$2 ;;
+ esac
+ pwd=${TWD%/*}
+ bwd=${PMP%/*}
+ if [[ -r $file ]]
+ then if [[ ! -d $file ]]
+ then var=$PWD/$file
+ return 0
+ fi
+ for i in $file/*
+ do if [[ -r $i ]]
+ then var=$PWD/$file
+ return 0
+ fi
+ break
+ done
+ fi
+ for view in ${VIEWS[@]}
+ do case $view in
+ /*) ;;
+ *) view=$pwd/$view ;;
+ esac
+ case $offset in
+ '') case $pwd in
+ $view/*) offset=${pwd#$view} ;;
+ *) offset=${bwd#$view} ;;
+ esac
+ ;;
+ esac
+ if [[ -r $view$offset/$file ]]
+ then if [[ ! -d $view$offset/$file ]]
+ then var=$view$offset/$file
+ return 0
+ fi
+ for i in $view$offset/$file/*
+ do if [[ -f $i ]]
+ then var=$view$offset/$file
+ return 0
+ fi
+ break
+ done
+ fi
+ done
+ var=
+ return 1
+}
+
+function INCLUDE # file ...
+{
+ typeset f v x
+ for f
+ do if VIEW v $f || [[ $PREFIX && $f != /* ]] && VIEW v $PREFIX$f
+ then x=$x$'\n'". $v"
+ else FATAL $f: not found
+ fi
+ done
+ [[ $x ]] && trap "$x" 0
+}
+
+function UMASK # [ mask ]
+{
+ if (( $# ))
+ then UMASK=$1
+ else UMASK=$UMASK_ORIG
+ fi
+}
+
+function PIPE # INPUT|OUTPUT|ERROR file|- data ...
+{
+ IO $0 "$@"
+}
+
+function FIFO # INPUT|OUTPUT|ERROR file|- data ...
+{
+ IO $0 "$@"
+}
+
+function IF # command(s) [note]
+{
+ [[ $GROUP == $TEST_select ]] || return
+ RUN
+ (( COND++ ))
+ COND_LINE[COND]=$LINE
+ if (( COND > 1 && COND_SKIP[COND-1] ))
+ then (( COND_KEPT[COND] = 1 ))
+ (( COND_SKIP[COND] = 1 ))
+ elif eval "{ $1 ;} >/dev/null 2>&1"
+ then (( COND_KEPT[COND] = 1 ))
+ (( COND_SKIP[COND] = 0 ))
+ [[ $2 && ! $TEST_quiet ]] && print -u2 "NOTE $2"
+ else (( COND_KEPT[COND] = 0 ))
+ (( COND_SKIP[COND] = 1 ))
+ fi
+}
+
+function ELIF # command(s) [note]
+{
+ [[ $GROUP == $TEST_select ]] || return
+ RUN
+ if (( COND <= 0 ))
+ then FATAL line $LINE: no matching IF for ELIF
+ fi
+ if (( COND_KEPT[COND] ))
+ then (( COND_SKIP[COND] = 0 ))
+ elif eval "$* > /dev/null 2>&1"
+ then (( COND_KEPT[COND] = 1 ))
+ (( COND_SKIP[COND] = 0 ))
+ [[ $2 && ! $TEST_quiet ]] && print -u2 "NOTE $2"
+ else (( COND_SKIP[COND] = 1 ))
+ fi
+}
+
+function ELSE # [note]
+{
+ [[ $GROUP == $TEST_select ]] || return
+ RUN
+ if (( COND <= 0 ))
+ then FATAL line $LINE: no matching IF for ELSE
+ fi
+ if (( COND_KEPT[COND] ))
+ then (( COND_SKIP[COND] = 1 ))
+ else (( COND_KEPT[COND] = 1 ))
+ (( COND_SKIP[COND] = 0 ))
+ [[ $1 && ! $TEST_quiet ]] && print -u2 "NOTE $1"
+ fi
+}
+
+function FI
+{
+ [[ $GROUP == $TEST_select ]] || return
+ RUN
+ if (( COND <= 0 ))
+ then FATAL line $LINE: no matching IF for FI on line $LINE
+ fi
+ (( ! COND_KEPT[COND] )) && [[ $1 && ! $TEST_quiet ]] && print -u2 "NOTE $1"
+ (( COND-- ))
+}
+
+# main
+
+integer ERRORS=0 ENVIRONS=0 EXPORTS=0 TESTS=0 SUBTESTS=0 LINE=0 TESTLINE=0
+integer ITEM=0 LASTITEM=0 COND=0 UNIT_READONLY=0 COUNT
+typeset ARGS COMMAND COPY DIAGNOSTICS ERROR EXEC FLUSHED=0 GROUP=INIT
+typeset IGNORE INPUT KEEP OUTPUT TEST SOURCE MOVE NOTE UMASK UMASK_ORIG
+typeset ARGS_ORIG COMMAND_ORIG TITLE UNIT ARGV PREFIX OFFSET IGNORESPACE
+typeset COMPARE MAIN JOBPID='' JOBSTATUS=''
+typeset TEST_file TEST_keep TEST_pipe_input TEST_pipe_io TEST_pipe_output TEST_local
+typeset TEST_quiet TEST_regular=1 TEST_rmflags='-rf --' TEST_rmu TEST_select
+
+typeset -A SAME VIEWS FILE TYPE READONLY FILTER
+typeset -a COND_LINE COND_SKIP COND_KEPT ENVIRON EXPORT
+typeset -Z LAST=00
+
+unset FIGNORE
+
+while getopts -a $command "$USAGE" OPT
+do case $OPT in
+ b) (( $OPTARG )) && IGNORESPACE=-b
+ ;;
+ i) SET - pipe-input=$OPTARG
+ ;;
+ k) SET - keep=$OPTARG
+ ;;
+ l) SET - local
+ ;;
+ o) SET - pipe-output=$OPTARG
+ ;;
+ p) SET - pipe-io=$OPTARG
+ ;;
+ q) SET - quiet=$OPTARG
+ ;;
+ r) SET - regular=$OPTARG
+ ;;
+ t) if [[ $TEST_select ]]
+ then TEST_select="$TEST_select|${OPTARG//,/\|}"
+ else TEST_select="${OPTARG//,/\|}"
+ fi
+ ;;
+ x) SET - trace=$OPTARG
+ ;;
+ v) SET - verbose=$OPTARG
+ ;;
+ *) GROUP=FINI
+ exit 2
+ ;;
+ esac
+done
+shift $OPTIND-1
+case $# in
+0) FATAL test unit name omitted ;;
+esac
+export COLUMNS=80
+SOURCE=$PWD
+PATH=$SOURCE:${PATH#?(.):}
+PATH=${PATH%%:?(.)}:/usr/5bin:/bin:/usr/bin
+UNIT=$1
+shift
+if [[ -f $UNIT && ! -x $UNIT ]]
+then REGRESS=$UNIT
+else REGRESS=${UNIT%.tst}
+ REGRESS=$REGRESS.tst
+ [[ -f $REGRESS ]] || FATAL $REGRESS: regression tests not found
+fi
+UNIT=${UNIT##*/}
+UNIT=${UNIT%.tst}
+MAIN=$UNIT
+if [[ $VPATH ]]
+then set -A VIEWS ${VPATH//:/' '}
+ OFFSET=${SOURCE#${VIEWS[0]}}
+ if [[ $OFFSET ]]
+ then OFFSET=${OFFSET#/}/
+ fi
+fi
+if [[ $REGRESS == */* ]]
+then PREFIX=${REGRESS%/*}
+ if [[ ${#VIEWS[@]} ]]
+ then for i in ${VIEWS[@]}
+ do PREFIX=${PREFIX#$i/}
+ done
+ fi
+ PREFIX=${PREFIX#$OFFSET}
+ if [[ $PREFIX ]]
+ then PREFIX=$PREFIX/
+ fi
+fi
+TWD=$PWD/$UNIT.tmp
+PMP=$(pwd -P)/$UNIT.tmp
+UMASK_ORIG=$(umask)
+UMASK=$UMASK_ORIG
+ARGV=("$@")
+if [[ ${ARGV[0]} && ${ARGV[0]} != [-+]* ]]
+then UNIT "${ARGV[@]}"
+ UNIT_READONLY=1
+fi
+trap 'code=$?; CLEANUP $code' EXIT
+if [[ ! $TEST_select ]]
+then TEST_select="[0123456789]*"
+fi
+TEST_select="@($TEST_select|+(0))"
+if [[ $TEST_trace ]]
+then export PS4=':$LINENO: '
+ typeset -ft $(typeset +f)
+ set -x
+fi
+if [[ $TEST_verbose ]]
+then typeset SHOW
+else typeset -L70 SHOW
+fi
+if [[ ! $TEST_keep ]] && (ulimit -c 0) >/dev/null 2>&1
+then ulimit -c 0
+fi
+set --pipefail
+
+# some last minute shenanigans
+
+alias BODY='BODY=BODY; function BODY'
+alias CONTINUE='LINE=$LINENO; CONTINUE'
+alias DO='(( $ITEM != $FLUSHED )) && RUN DO; DO &&'
+alias DONE='DONE=DONE; function DONE'
+alias EXEC='LINE=$LINENO; EXEC'
+alias EXITED='LINE=$LINENO; EXITED'
+alias INIT='INIT=INIT; function INIT'
+alias JOB='LINE=$LINENO; JOB'
+alias KILL='LINE=$LINENO; KILL'
+alias PROG='LINE=$LINENO; FLUSH; PROG'
+alias TEST='TESTLINE=$LINENO; TEST'
+alias IF='LINE=$LINENO; FLUSH; IF'
+alias ELIF='LINE=$LINENO; FLUSH; ELIF'
+alias ELSE='LINE=$LINENO; FLUSH; ELSE'
+alias FI='LINE=$LINENO; FLUSH; FI'
+
+# do the tests
+
+. $REGRESS
+RUN
+GROUP=FINI
diff --git a/src/cmd/INIT/release.c b/src/cmd/INIT/release.c
new file mode 100644
index 0000000..7b4b1b0
--- /dev/null
+++ b/src/cmd/INIT/release.c
@@ -0,0 +1,366 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * release -- list recent release changes
+ *
+ * coded for portability
+ */
+
+static char id[] = "\n@(#)$Id: release (AT&T Research) 2000-01-28 $\0\n";
+
+#if _PACKAGE_ast
+
+#include <ast.h>
+#include <error.h>
+
+static const char usage[] =
+"[-?\n@(#)$Id: release (AT&T Research) 2000-01-28 $\n]"
+USAGE_LICENSE
+"[+NAME?release - list recent changes]"
+"[+DESCRIPTION?\brelease\b lists the changes within the date range specified"
+" by the \b--from\b and \b--to\b options. The input files are assumed to"
+" contain date tag lines of the form [\acc\a]]\ayy-mm-dd\a [ \atext\a ]]"
+" (or \bdate\b(1) default format), where \acc\a is determined by a Y2K"
+" window year of 69 (we can produce an example coding dated 1991 - this"
+" can be patented?, how about 1+1=2?.) The date tag lines are followed by"
+" \areadme\a text in reverse chronological order (newer entries at the"
+" top of the file.) If no selection options are spcified then all"
+" changes are listed. If no \afile\a operands are specified then the"
+" standard input is read.]"
+"[+?The entries for each \afile\a are annotated with the file directory name.]"
+"[f:from?Entries older than \adate\a are omitted.]:[date]"
+"[r:release?List all changes that include the first \acount\a release marks."
+" A release mark has a date tag followed by optional space and at least"
+" three \b-\b characters. Changes from release mark \acount\a+1 are not"
+" listed. If there are no release marks then the date range is used;"
+" if there is at least one release mark then the date range is ignored"
+" and at most \acount\a release marks will be listed.]#[count]"
+"[t:to?Entries newer than \adate\a are omitted.]:[date]"
+"[V?Print the program version and exit.]"
+
+"\n"
+"\n[ file ... ]\n"
+"\n"
+
+"[+SEE ALSO?\bpackage\b(1)]"
+;
+
+#else
+
+#define elementsof(x) ((int)(sizeof(x)/sizeof(x[0])))
+
+#define NiL ((char*)0)
+
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#if !_PACKAGE_ast && defined(__STDC__)
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+static char mon[] = "janfebmaraprmayjunjulaugsepoctnovdec";
+static char day[] = "sunmontuewedthufrisat";
+
+#if !_PACKAGE_ast
+
+static void
+usage()
+{
+ fprintf(stderr, "Usage: release [-V] [-h hi-date] [-l lo-date] [-r count] [ file ...]\n");
+ exit(2);
+}
+
+#endif
+
+static unsigned long
+number(register char* s, char** e)
+{
+ unsigned long q = 0;
+
+ while (isspace(*s))
+ s++;
+ while (isdigit(*s))
+ q = q * 10 + *s++ - '0';
+ if (e)
+ *e = s;
+ return q;
+}
+
+unsigned long
+string(register char* s, char* tab, int num, int siz, char** e)
+{
+ register int i;
+ register int j;
+ char buf[16];
+
+ while (isspace(*s))
+ s++;
+ for (i = 0; i < siz; i++)
+ buf[i] = isupper(s[i]) ? tolower(s[i]) : s[i];
+ for (i = 0; i < num; i += siz)
+ for (j = 0; j < siz && buf[j] == tab[j+i]; j++)
+ if (j == (siz - 1))
+ {
+ *e = s + siz;
+ return i / siz + 1;
+ }
+ return 0;
+}
+
+static unsigned long
+date(char* s, char** e)
+{
+ char* t;
+ unsigned long y;
+ unsigned long m;
+ unsigned long d;
+
+ if (isdigit(*s))
+ {
+ y = number(s, &t);
+ if (*t != '-')
+ return 0;
+ switch (t - s)
+ {
+ case 2:
+ y += 1900;
+ if (y <= 1969)
+ y += 100;
+ break;
+ case 4:
+ if (y < 1969)
+ return 0;
+ break;
+ }
+ if (!(m = number(++t, &s)))
+ return 0;
+ if ((s - t) != 2 || *s != '-' || m < 1 || m > 12)
+ return 0;
+ if (!(d = number(++s, &t)))
+ return 0;
+ if ((t - s) != 2 || d < 1 || d > 31)
+ return 0;
+ }
+ else
+ {
+ if (string(s, day, elementsof(day), 3, &t))
+ s = t;
+ if (!(m = string(s, mon, elementsof(mon), 3, &t)))
+ return 0;
+ if (!(d = number(t, &s)))
+ return 0;
+ for (y = 1969; *s; s++)
+ if ((y = number(s, &t)) && (t - s) == 4)
+ {
+ if (y < 1969)
+ return 0;
+ break;
+ }
+ }
+ if (e)
+ {
+ while (isspace(*t))
+ t++;
+ *e = t;
+ }
+ return ((y - 1969) * 13 + m) * 32 + d;
+}
+
+int
+main(int argc, char** argv)
+{
+ register char* s;
+ register char* u;
+ register char* v;
+ char* p;
+ char* e;
+ int i;
+ unsigned long t;
+ unsigned long lo;
+ unsigned long hi;
+ int mk;
+ FILE* f;
+ char buf[1024];
+
+ mk = 0;
+ lo = hi = 0;
+#if _PACKAGE_ast
+ error_info.id = "release";
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'f':
+ if (!(lo = date(opt_info.arg, &e)) || *e)
+ {
+ error(2, "%s: invalid from date [%s]", opt_info.arg, e);
+ return 1;
+ }
+ continue;
+ case 'r':
+ mk = opt_info.num + 1;
+ continue;
+ case 't':
+ if (!(hi = date(opt_info.arg, &e)) || *e)
+ {
+ error(2, "%s: invalid to date [%s]", opt_info.arg, e);
+ return 1;
+ }
+ continue;
+ case 'V':
+ sfprintf(sfstdout, "%s\n", id + 10);
+ return 0;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ if (error_info.errors)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ argv += opt_info.index;
+#else
+ while ((s = *++argv) && *s == '-' && *(s + 1))
+ {
+ if (*(s + 1) == '-')
+ {
+ if (!*(s + 2))
+ {
+ argv++;
+ break;
+ }
+ usage();
+ break;
+ }
+ for (;;)
+ {
+ switch (i = *++s)
+ {
+ case 0:
+ break;
+ case 'f':
+ case 't':
+ if (!*(v = ++s) && !(v = *++argv))
+ {
+ s = "??";
+ continue;
+ }
+ if (!(t = date(v, &e)) || *e)
+ {
+ fprintf(stderr, "release: -%c%s: invalid date [%s]\n", i, s, e);
+ return 1;
+ }
+ switch (i)
+ {
+ case 'f':
+ lo = t;
+ break;
+ case 't':
+ hi = t;
+ break;
+ }
+ break;
+ case 'r':
+ if (!*(v = ++s) && !(v = *++argv))
+ {
+ s = "??";
+ continue;
+ }
+ mk = number(v, &e) + 1;
+ if (*e)
+ {
+ fprintf(stderr, "release: -%c%s: invalid count\n", i, s);
+ return 1;
+ }
+ break;
+ case 'V':
+ fprintf(stdout, "%s\n", id + 10);
+ return 0;
+ default:
+ fprintf(stderr, "release: -%c: unknown option\n", i);
+ /*FALLTHROUGH*/
+ case '?':
+ usage();
+ break;
+ }
+ break;
+ }
+ }
+#endif
+ do
+ {
+ if (!(p = *argv++) || !*p || *p == '-' && !*(p + 1))
+ {
+ argv--;
+ p = "";
+ f = stdin;
+ }
+ else if (!(f = fopen(p, "r")))
+ {
+ fprintf(stderr, "release: %s: cannot read", p);
+ return 1;
+ }
+ while (s = fgets(buf, sizeof(buf), f))
+ {
+ if (t = date(s, &e))
+ {
+ if (mk && e[0] == '-' && e[1] == '-' && e[2] == '-' && !--mk)
+ break;
+ if (t < lo)
+ break;
+ if (hi && t > hi)
+ continue;
+ if (p)
+ {
+ if (*p)
+ {
+ for (u = v = p; *p; p++)
+ if (*p == '/')
+ {
+ v = u;
+ u = p + 1;
+ }
+ printf("\n:::::::: ");
+ while ((i = *v++) && i != '/')
+ fputc(i, stdout);
+ printf(" ::::::::\n\n");
+ }
+ p = 0;
+ }
+ }
+ if (!p)
+ fputs(s, stdout);
+ }
+ if (f == stdin)
+ break;
+ fclose(f);
+ } while (*argv);
+ return 0;
+}
diff --git a/src/cmd/INIT/rt.sh b/src/cmd/INIT/rt.sh
new file mode 100644
index 0000000..2b8b840
--- /dev/null
+++ b/src/cmd/INIT/rt.sh
@@ -0,0 +1,479 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+: rt - nmake test output filter
+
+command=rt
+flags='--silent --keepgoing'
+failed=0
+heading=1
+verbose=0
+
+case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
+0123) ARGV0="-a $command"
+ USAGE=$'
+[-?
+@(#)$Id: rt (AT&T Research) 2010-07-27 $
+]
+'$USAGE_LICENSE$'
+[+NAME?rt - run "nmake test" and filter output]
+[+DESCRIPTION?\brt\b runs \vnmake test\v and filters the regression
+ test output to contain only test summary lines. If no \atest\a
+ operands are specified then \btest\b is assumed. If \b-\b is
+ specified then the \afile\a operands, or the standard input
+ if no \afile\a operands are specified, are filtered instead
+ of the output from \bnmake\b.]
+[f:failed?Only list failed test results.]
+[h!:heading?Enable per-file heading when more than one \afile\a operand
+ follows \b-\b.]
+[v:verbose?Run with \vREGRESSFLAGS=-v\v.]
+
+[ test ... | - [ file ... ] ]
+
+[+SEE ALSO?\bnmake\b(1), \bregress\b(1)]
+[+CAVEATS?\brt\b guesses the regression test output style. Garbled
+ output indicates a bad guess.]
+'
+ ;;
+*) ARGV0=""
+ USAGE="fhv"
+ ;;
+esac
+
+function usage
+{
+ OPTIND=0
+ getopts $ARGV0 "$USAGE" OPT '-?'
+ exit 2
+}
+
+while getopts $ARGV0 "$USAGE" OPT
+do case $OPT in
+ f) failed=1 ;;
+ h) heading=0 ;;
+ v) (( verbose=$OPTARG )) && flags="$flags REGRESSFLAGS=-v" ;;
+ esac
+done
+shift `expr $OPTIND - 1`
+
+ifs=${IFS:-$' \t\n'}
+set -o noglob
+component=
+dots='............................................'
+bad=' ***'
+style=unknown
+integer tests errors signals lineno=0 skip=0
+typeset -l lower
+
+function results # tests errors signals
+{
+ integer t=$1 e=$2 s=$3
+ typeset label note
+ if [[ $style != unknown ]] && (( errors >= 0 ))
+ then style=unknown
+ if (( !failed || errors ))
+ then if (( failed ))
+ then print -r -n -- "$unit"
+ fi
+ if (( t >= 0 ))
+ then if (( t == 1))
+ then label="test "
+ else label=tests
+ fi
+ printf $'%s%5d %s' "$prefix" "$t" "$label"
+ prefix=
+ else prefix="$prefix..........."
+ fi
+ if (( s ))
+ then label=signal
+ (( e=s ))
+ else label=error
+ fi
+ if (( e != 1))
+ then label=${label}s
+ fi
+ if (( e == 1 ))
+ then note=" $bad"
+ elif (( e > 1 ))
+ then note=$bad
+ fi
+ printf $'%s%5d %s%s\n' "$prefix" "$e" "$label" "$note"
+ fi
+ fi
+}
+
+function unit
+{
+ typeset x
+ if [[ $component ]]
+ then x=${component##*/}
+ if [[ " $x " != *' '$unit' '* && " $unit " != *' '$x' '* ]]
+ then if [[ $component == cmd/?*lib/* ]]
+ then unit="$unit $x"
+ else unit="$x $unit"
+ fi
+ fi
+ fi
+ unit="$unit ${dots:1:${#dots}-${#unit}}"
+ if [[ $1 ]]
+ then unit="$unit..........."
+ fi
+ if (( ! failed ))
+ then print -r -n -- "$unit"
+ fi
+}
+
+if [[ $1 == - ]]
+then shift
+ if (( $# <= 1 ))
+ then heading=0
+ fi
+ if (( heading ))
+ then for i
+ do print test heading $i
+ cat -- "$i"
+ done
+ else cat "$@"
+ fi
+else if [[ $1 == *=* ]]
+ then set test "$@"
+ elif (( ! $# ))
+ then set test
+ fi
+ nmake "$@" $flags 2>&1
+fi |
+while read -r line
+do set '' $line
+ shift
+ case $line in
+ TEST[' ']*', '*' error'*)
+ IFS=${IFS}","
+ set '' $line
+ IFS=$ifs
+ set '' $*
+ while :
+ do case $2 in
+ '') break
+ ;;
+ error|errors)
+ errors=$1
+ break
+ ;;
+ test|tests)
+ tests=$1
+ ;;
+ esac
+ shift
+ done
+ results $tests $errors
+ continue
+ ;;
+ TEST[' ']*)
+ results $tests $errors
+ IFS=${IFS}","
+ set '' $line
+ IFS=$ifs
+ set '' $*
+ unit=${3##*/}
+ case $4 in
+ [a-zA-Z]*) unit="$unit $4" ;;
+ esac
+ unit
+ prefix=
+ errors=0
+ signals=0
+ style=regress
+ continue
+ ;;
+ 'pathname and options of item under test')
+ read -r line || break
+ results $tests $errors $signals
+ set '' $line
+ unit=${2##*/}
+ unit
+ tests=0
+ errors=0
+ signals=0
+ style=script
+ continue
+ ;;
+ 'test heading '*)
+ if (( heading ))
+ then if (( heading > 1 ))
+ then print
+ else heading=2
+ fi
+ set '' $line
+ shift 3
+ print -r -- "==> $* <=="
+ fi
+ continue
+ ;;
+ 'test '*' begins at '????-??-??+??:??:??|'test '*' begins at '*' '*' '*' '*' '*)
+ results $tests $errors $signals
+ unit=${2##*/}
+ unit=${unit%.sh}
+ unit
+ prefix=
+ tests=-1
+ errors=0
+ signals=0
+ style=shell
+ continue
+ ;;
+ 'test '*' at '????-??-??+??:??:??' [ '*' ]'|'test '*' at '*' '*' '*' '*' '*)
+ case $line in
+ *' [ '*test*error*' ]')
+ while :
+ do case $1 in
+ '[') tests=$2
+ errors=$4
+ if (( errors > 256 ))
+ then (( signals++ ))
+ fi
+ break
+ ;;
+ esac
+ shift
+ done
+ ;;
+ *' [ '*test*signal*' ]')
+ while :
+ do case $1 in
+ '[') tests=$2
+ signals=$4
+ if (( signals ))
+ then (( errors++ ))
+ fi
+ break
+ ;;
+ esac
+ shift
+ done
+ ;;
+ *) if [[ $3 != passed ]]
+ then (( errors )) || (( errors++ ))
+ fi
+ ;;
+ esac
+ results $tests $errors $signals
+ continue
+ ;;
+ '## ---'*(-)'--- ##')
+ (( ++lineno > skip )) || continue
+ read -r line || break
+ lower=$line
+ set '' $lower
+ case $lower in
+ '##'*'test suite:'*'##')
+ results $tests $errors $signals
+ set -- ${lower//*suite:}
+ set -- ${*//[.#]/}
+ unit=$*
+ if [[ $unit == *' tests' ]]
+ then unit=${unit/' tests'/}
+ fi
+ main=$unit
+ prefix=
+ tests=0
+ errors=0
+ signals=0
+ category=
+ style=autotest
+ (( skip = lineno + 1 ))
+ unit
+ continue
+ ;;
+ esac
+ ;;
+ +(-)) case $style in
+ regress) continue ;;
+ esac
+ (( ++lineno > skip )) || continue
+ read -r line || break
+ set '' $line
+ case $line in
+ 'Running tests for '*)
+ results $tests $errors $signals
+ shift 4
+ unit=
+ while (( $# ))
+ do if [[ $1 == on ]]
+ then break
+ fi
+ if [[ $unit ]]
+ then unit="$unit "
+ fi
+ unit=$unit${1##*/}
+ shift
+ done
+ main=$unit
+ prefix=
+ tests=-1
+ errors=-1
+ category=
+ style=perl
+ (( skip = lineno + 1 ))
+ continue
+ ;;
+ *' : '*)results $tests $errors $signals
+ unit=${2##*/}
+ unit=${unit%.sh}
+ unit
+ prefix=
+ tests=0
+ errors=0
+ signals=0
+ style=timing
+ (( skip = lineno + 1 ))
+ continue
+ ;;
+ esac
+ ;;
+ +([0-9])*([a-zA-Z0-9])' '*)
+ case $style in
+ script) case $line in
+ *FAILED*|*failed*)
+ (( errors++ ))
+ ;;
+ *) (( tests++ ))
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ make:*|'make ['*']:'*)
+ case $line in
+ *': warning:'*|*'making test'*|*'action'?(s)' failed'*|*': *** '*)
+ ;;
+ *) results $tests $errors $signals
+ print -r -u2 -- "$line"
+ ;;
+ esac
+ continue
+ ;;
+ +([/a-zA-Z_0-9]):)
+ component=${line%:}
+ ;;
+ '') continue
+ ;;
+ esac
+ case $style in
+ autotest)
+ case $line in
+ +([0-9]):*ok)
+ (( tests++ ))
+ ;;
+ +([0-9]):*FAILED*)
+ (( tests++ ))
+ (( errors++ ))
+ if (( $verbose ))
+ then if [[ ! $prefix ]]
+ then prefix=$unit
+ print
+ fi
+ print -r -- " ${line//*'FAILED '/}"
+ fi
+ ;;
+ esac
+ continue
+ ;;
+ perl) case $line in
+ *'........ '*)
+ if [[ $1 == */* ]]
+ then cat=${1%%/*}
+ if [[ $cat != $category ]]
+ then results $tests $errors $signals
+ category=$cat
+ unit="$main $category"
+ unit
+ prefix=
+ tests=0
+ errors=0
+ signals=0
+ fi
+ (( tests++ ))
+ case $line in
+ *' ok') ;;
+ *) (( errors++ ))
+ if (( $verbose ))
+ then if [[ ! $prefix ]]
+ then prefix=$unit
+ print
+ fi
+ print -r -- "$line"
+ fi
+ ;;
+ esac
+ else results $tests $errors $signals
+ case $line in
+ *' ok') errors=0 ;;
+ *) errors=1 ;;
+ esac
+ unit="$main $1"
+ unit
+ if (( $verbose && errors ))
+ then prefix=$unit
+ print
+ shift 2
+ print -r -- "$@"
+ else prefix=
+ fi
+ results $tests $errors $signals
+ tests=-1
+ errors=-1
+ category=
+ fi
+ style=perl
+ ;;
+ esac
+ continue
+ ;;
+ esac
+ case $line in
+ *FAILED*|*failed*)
+ (( errors++ ))
+ ;;
+ *) case $style in
+ regress)case $line in
+ ['<>']*);;
+ *) continue ;;
+ esac
+ ;;
+ script) continue
+ ;;
+ shell) ((errors++ ))
+ ;;
+ timing) (( tests++ ))
+ continue
+ ;;
+ unknown)continue
+ ;;
+ esac
+ ;;
+ esac
+ if (( $verbose ))
+ then if [[ ! $prefix ]]
+ then prefix=$unit
+ print
+ fi
+ print -r -- "$line"
+ fi
+done
+results $tests $errors $signals
diff --git a/src/cmd/INIT/silent.sh b/src/cmd/INIT/silent.sh
new file mode 100644
index 0000000..be99aa6
--- /dev/null
+++ b/src/cmd/INIT/silent.sh
@@ -0,0 +1,42 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1994-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+# non-ksh stub for the nmake silent prefix
+# @(#)silent (AT&T Research) 1992-08-11
+
+case $-:$BASH_VERSION in
+*x*:[01234567899]*) : bash set -x is broken :; set +ex ;;
+esac
+
+while :
+do case $# in
+ 0) exit 0 ;;
+ esac
+ case $1 in
+ *=*) case $RANDOM in
+ $RANDOM)`echo $1 | sed "s/\\([^=]*\\)=\\(.*\\)/eval \\1='\\2'; export \\1/"` ;;
+ *) export "$1" ;;
+ esac
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+done
+"$@"
diff --git a/src/cmd/INIT/socket.c b/src/cmd/INIT/socket.c
new file mode 100644
index 0000000..51d74eb
--- /dev/null
+++ b/src/cmd/INIT/socket.c
@@ -0,0 +1,33 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * small test for -lnsl
+ */
+
+#ifndef socket
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+int
+main()
+{
+ return socket(0, 0, 0) < 0;
+}
diff --git a/src/cmd/INIT/w.c b/src/cmd/INIT/w.c
new file mode 100644
index 0000000..0f6bc7d
--- /dev/null
+++ b/src/cmd/INIT/w.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#ifndef DONTCARE
+#include <wchar.h>
+#include <wctype.h>
+#endif
+
+int
+main()
+{
+ wchar_t w = ' ';
+ return iswspace(w) == 0;
+}
diff --git a/src/cmd/INIT/w2.c b/src/cmd/INIT/w2.c
new file mode 100644
index 0000000..00efd25
--- /dev/null
+++ b/src/cmd/INIT/w2.c
@@ -0,0 +1,27 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1994-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#include <wchar.h>
+
+int
+main()
+{
+ wchar_t w = ' ';
+ return iswspace(w) == 0;
+}
diff --git a/src/cmd/Makefile b/src/cmd/Makefile
new file mode 100644
index 0000000..a046f68
--- /dev/null
+++ b/src/cmd/Makefile
@@ -0,0 +1 @@
+:MAKE:
diff --git a/src/cmd/Mamfile b/src/cmd/Mamfile
new file mode 100644
index 0000000..7b439a5
--- /dev/null
+++ b/src/cmd/Mamfile
@@ -0,0 +1,7 @@
+info mam static
+note component level :MAKE: equivalent
+make install
+make all
+exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+done all virtual
+done install virtual
diff --git a/src/cmd/ksh93/COMPATIBILITY b/src/cmd/ksh93/COMPATIBILITY
new file mode 100644
index 0000000..cf26076
--- /dev/null
+++ b/src/cmd/ksh93/COMPATIBILITY
@@ -0,0 +1,136 @@
+
+ KSH-93 VS. KSH-88
+
+
+The following is a list of known incompatibilities between ksh-93 and ksh-88.
+I have not include cases that are clearly bugs in ksh-88. I also have
+omitted features that are completely upward compatible.
+
+1. Functions, defined with name() with ksh-93 are compatible with
+ the POSIX standard, not with ksh-88. No local variables are
+ permitted, and there is no separate scope. Functions defined
+ with the function name syntax, maintain compatibility.
+ This also affects function traces.
+
+2. ! is now a reserved word. As a result, any command by that
+ name will no longer work with ksh-93.
+
+3. The -x attribute of alias and typeset -f is no longer
+ effective and the ENV file is only read for interactive
+ shells. You need to use FPATH to make function definitions
+ visible to scripts.
+
+4. A built-in command named command has been added which is
+ always found before the PATH search. Any script which uses
+ this name as the name of a command (or function) will not
+ be compatible.
+
+5. The output format for some built-ins has changed. In particular
+ the output format for set, typeset and alias now have single
+ quotes around values that have special characters. The output
+ for trap without arguments has a format that can be used as input.
+
+6. With ksh-88, a dollar sign ($') followed by a single quote was
+ interpreted literally. Now it is an ANSI-C string. You
+ must quote the dollar sign to get the previous behavior.
+ Also, a $ in front of a " indicates that the string needs
+ to be translated for locales other than C or POSIX. The $
+ is ignored in the C and POSIX locale.
+
+7. With ksh-88, tilde expansion did not take place inside ${...}.
+ with ksh-93, ${foo-~} will cause tilde expansion if foo is
+ not set. You need to escape the ~ for the previous behavior.
+
+8. Some changes in the tokenizing rules where made that might
+ cause some scripts with previously ambiguous use of quoting
+ to produce syntax errors.
+
+9. Programs that rely on specific exit values for the shell,
+ (rather than 0 or non-zero) may not be compatible. The
+ exit status for many shell failures has been changed.
+
+10. Built-ins in ksh-88 were always executed before looking for
+ the command in the PATH variable. This is no longer true.
+ Thus, with ksh-93, if you have the current directory first
+ in your PATH, and you have a program named test in your
+ directory, it will be executed when you type test; the
+ built-in version will be run at the point /bin is found
+ in your PATH.
+
+11. Some undocumented combinations of argument passing to ksh
+ builtins no longer works since ksh-93 is getopts conforming
+ with respect to its built-ins. For example, typeset -8i
+ previously would work as a synonym for typeset -i8.
+
+12. Command substitution and arithmetic expansion are now performed
+ on PS1, PS3, and ENV when they are expanded. Thus, ` and $(
+ as part of the value of these variables must be preceded by a \
+ to preserve their previous behavior.
+
+13. The ERRNO variable has been dropped.
+
+14. If the file name following a redirection symbol contain pattern
+ characters they will only be expanded for interactive shells.
+
+15. The arguments to a dot script will be restored when it completes.
+
+16. The list of tracked aliases is not displayed with alias unless
+ the -t option is specified.
+
+17. The POSIX standard requires that test "$arg" have exit status
+ of 0, if and only if $arg is null. However, since this breaks
+ programs that use test -t, ksh-93 treats an explicit test -t
+ as if the user had entered test -t 1.
+
+18. The ^T directive of emacs mode has been changed to work the
+ way it does in gnu-emacs.
+
+19. ksh-88 allowed unbalanced parenthes within ${name op val} whereas
+ ksh-93 does not. Thus, ${foo-(} needs to be written as ${foo-\(}
+ which works with both versions.
+
+20. kill -l in ksh-93 lists only the signal names, not their numerical
+ values.
+
+21. Local variables defined by typeset are statically scoped in
+ ksh-93. In ksh-88 they were dynamically scoped although this
+ behavior was never documented.
+
+22. The value of the variable given to getopts is set to ? when
+ the end-of-options is reached to conform to the POSIX standard.
+
+23. Since the POSIX standard requires that octal constants be
+ recongnized, doing arithmetic on typeset -Z variables can
+ yield different results that with ksh-88. Most of these
+ differences were eliminated in ksh-93o. Starting in ksh-93u+, the
+ let command no longer recognizes octal constants starting with 0
+ for compatibility with ksh-88 unless the option letoctal is on.
+
+24. Starting after ksh-93l, If you run ksh name, where name does
+ not contain a /, the current directory will be searched
+ before doing a path search on name as required by the POSIX
+ shell standard.
+
+25. In ksh-93, cd - will output the directory that it changes
+ to on standard output as required by X/Open. With ksh-88,
+ this only happened for interactive shells.
+
+26. As an undocumented feature of ksh-88, a leading 0 to an
+ assignment of an integer variable caused that variable
+ to be treated as unsigned. This behavior was removed
+ starting in ksh-93p.
+
+27. The getopts builtin in ksh-93 requires that optstring contain
+ a leading + to allow options to begin with a +.
+
+28. In emacs/gmacs mode, control-v will not display the version when
+ the stty lnext character is set to control-v or is unset.
+ The sequence escape control-v will display the shell version.
+
+29. In ksh-88, DEBUG traps were executed. after each command. In ksh-93
+ DEBUG traps are exeucted before each command.
+
+30. In ksh-88, a redirection to a file name given by an empty string was
+ ignored. In ksh-93, this is an error.
+I am interested in expanding this list so please let me know if you
+uncover any others.
diff --git a/src/cmd/ksh93/DESIGN b/src/cmd/ksh93/DESIGN
new file mode 100644
index 0000000..c11c0af
--- /dev/null
+++ b/src/cmd/ksh93/DESIGN
@@ -0,0 +1,170 @@
+Here is an overview of the source code organization for ksh93.
+
+Directory layout:
+
+ The directory include contains header files for ksh93.
+ The files nval.h and shell.h are intended to be public
+ headers and can be used to add runtime builtin command.
+ The remainder are private.
+
+ The directory data contains readonly data files for ksh93.
+ The man pages for built-ins are in builtins.c rather
+ than included as statics with the implementations in the
+ bltins directory because some systems don't make static const
+ data readonly and we want these to be shared by all running
+ shells.
+
+ The directory edit contains the code for command line
+ editing and history.
+
+ The fun directory contains some shell function such as
+ pushd, popd, and dirs.
+
+ The directory features contains files that are used to generate
+ header files in the FEATURE directory. Most of these files
+ are in a format that is processed by iffe.
+
+ The directory bltins contains code for most of the built-in
+ commands. Additional built-in commands are part of libcmd.
+
+ The directory sh contains most of the code for ksh93.
+
+ The directory tests contains a number of regression tests.
+ In most cases, when a bug gets fixed, a test is added to
+ one of these files. The regression tests can be run by
+ going to this directory and running
+ SHELL=shell_path shell_path shtests
+ where shell_path is an absolute pathname for the shell to
+ be tested.
+
+ The top level directory contains the nmake Makefile, a README,
+ and several documentation files. The RELEASE file contains
+ the list of bug fixes and new features since the original
+ ksh93 release. The file COMPATIBILITY is a list of all
+ known incompatibilities with ksh88.
+
+ The bash_pre_rc.sh is a startup script used when emulating
+ bash if the shell is compiled with SHOPT_BASH and the shell
+ is invoked as bash. The bash emulation is not complete.
+
+Include directory:
+ 1. argnod.h contains the type definitions for command
+ nodes, io nodes, argument nodes, and for positional
+ parameters.a It defines the prototypes for
+ all the positional parameters functions.
+ 2. builtins.h contains prototypes for builtins as well
+ as symbolic constants that refer to the name-pairs
+ that are associated with some of the built-ins.
+ It also contains prototypes for many of the strings.
+ 3. defs.h is the catch all for all definitions that
+ don't fit elsewhere and it includes several other
+ headers. It defines a strucuture that contains ksh
+ global data, sh, and a structure that contains per
+ function data, sh.st.
+ 4. edit.h contains definitions that are common to both
+ vi and emacs edit modes.
+ 5. env.h contains interfaces for creating and modifying
+ environment variables.
+ 6. fault.h contains prototypes for signal related
+ functions and trap and fault handling.
+ 7. fcin.h contains macro and function definitions for
+ reading from a file or string.
+ 8. history.h contains macros and functions definitions
+ related to history file processing.
+ 9. jobs.h contains the definitions relating to job
+ processing and control.
+ 10. lexstates.h contains the states associated with
+ lexical processing.
+ 11. name.h contains the internal definitions related
+ to name-value pair processing.
+ 12. national.h contains a few I18N definitions, mostly
+ obsolete.
+ 13. nval.h is the public interface to the name-value
+ pair library that is documented with nval.3.
+ 14. path.h contains the interface for pathname processing
+ and pathname searching.
+ 15. shell.h is the public interface for shell functions
+ that are documented int shell.3.
+ 16. shlex.h contains the lexical token definitions and
+ interfaces for lexical analysis.
+ 17. shnodes.h contains the definition of the structures
+ for each of the parse nodes and flags for the attributes.
+ 18. shtable.h contains some interfaces and functions for
+ table lookup.
+ 19. streval.h contains the interface to the arithmetic
+ functions.
+ 20. terminal.h is a header file that includes the appropriate
+ terminal include.
+ 21. test.h contains the definitions for the test and [[...]]
+ commands.
+ 22. timeout.h contains the define constant for the maximum
+ shell timeout.
+ 23. ulimit.h includes the appropriate resource header.
+ 24. variables.h contains symbolic constants for the built-in
+ shell variables.
+
+sh directory:
+ 1. args.c contains functions for parsing shell options
+ and for processing positional parameters.
+ 2. arith.c contains callback functions for the streval.c
+ library and the interface to shell arithmetic.
+ 3. array.c contains the code for indexed and associative
+ arrays.
+ 4. bash.h contains code used when compiling with SHOPT_BASH
+ to add bash specific features such as shopt.
+ 5. defs.c contains the data definitions for global symbols.
+ 6. deparse.c contains code to generate shell script from
+ a parse tree.
+ 7. env.c contains code to add and delete environment variables
+ to an environment list.
+ 8. expand.c contains code for file name expansion and
+ file name generation.
+ 9. fault.c contains code for signal processing, trap
+ handling and termination.
+ 10. fcin.c contains code for reading and writing a character
+ at a time from a file or string.
+ 11. init.c contains initialization code and callbacks
+ for get and set functions for built-in variables.
+ 12. io.o contains code for redirections and managing file
+ descriptors and file streams.
+ 13. jobs.c contains the code for job management.
+ 14. lex.c contains the code for the lexical analyzer.
+ 15. macro.c contains code for the $ macro expansions, including
+ here-documents.
+ 16. main.c contains the calls to initialization, profile
+ processing and the main evaluation loop as well as
+ mail processing.
+ 17. name.c contains the name-value pair routines that are
+ built on the hash library in libast.
+ 18. nvdisc.c contains code related to name-value pair disciplines.
+ 19. nvtree.c contains code for compound variables and for
+ walking the namespace.
+ 20. nvtype.c contains most of the code related to types that
+ are created with typeset -T.
+ 21. parse.c contains the code for the shell parser.
+ 22. path.c contains the code for pathname lookup and
+ some path functions. It also contains the code
+ that executes commands and scripts.
+ 23. pmain.c is just a calls sh_main() so that all of the
+ rest of the shell can be in a shared library.
+ 24. shcomp.c contains the main program to the shell
+ compiler. This program parses a script and creates
+ a file that the shell can read containing the parse tree.
+ 25. streval.c is an C arithmetic evaluator.
+ 26. string.c contains some string related functions.
+ 27. subshell.c contains the code to save and restore
+ environments so that subshells can run without creating
+ a new process.
+ 28. suid_exec.c contains the program from running execute
+ only and/or setuid/setgid scripts.
+ 29. tdump.c contains the code to dump a parse tree into
+ a file.
+ 30. timers.c contains code for multiple event timeouts.
+ 31. trestore contians the code for restoring the parse
+ tree from the file created by tdump.
+ 32. userinit.c contains a dummy userinit() function.
+ This is now obsolete with the new version of sh_main().
+ 33. waitevent.c contains the sh_waitnotify function so
+ that builtins can handle processing events when the
+ shell is waiting for input or for process completion.
+ 34. xec.c is the main shell executuion loop.
diff --git a/src/cmd/ksh93/Makefile b/src/cmd/ksh93/Makefile
new file mode 100644
index 0000000..3ad44c6
--- /dev/null
+++ b/src/cmd/ksh93/Makefile
@@ -0,0 +1,248 @@
+/*
+ * ksh makefile
+ */
+
+SH := $(PWD:B:/[0-9]*$//:N=ksh*:-ksh) /* name of the shell program */
+VERSION = 1.1
+LICENSE = since=1982,author=dgk
+CATALOG = libshell
+ERROR_CONTEXT_T == Error_context_t /* workaround until switch from errorpush()/errorpop() => errorctx() */
+RELEASE := $(SH:/.*sh//)
+SHCOMP := shcomp$(RELEASE)
+
+/*
+ * set these variables to 1 to enable, 0 to disable, null to probe
+ * override SHOPT_foo=1 can be placed one per line in the build dir Makeargs
+ */
+
+SHOPT_2DMATCH == 1 /* two dimensional .sh.match for ${var//pat/str} */
+SHOPT_ACCT == /* accounting */
+SHOPT_ACCTFILE == /* per user accounting info */
+SHOPT_AUDIT ==
+SHOPT_AUDITFILE == "/etc/ksh_audit" /* auditing file */
+SHOPT_BASH == /* bash compatibility code */
+SHOPT_BGX == 1 /* one SIGCHLD trap per completed job */
+SHOPT_BRACEPAT == 1 /* C-shell {...,...} expansions (, required) */
+SHOPT_CMDLIB_HDR == /* -lcmd builtin list: <cmdlist.h> */
+SHOPT_CMDLIB_DIR == /* SHOPT_CMDLIB_HDR prefix SH_CMDLIB_DIR + <cmdlist.h> */
+SHOPT_COSHELL == 1 /* build with connection to coshell */
+SHOPT_CRNL == /* accept <cr><nl> for <nl> */
+SHOPT_DYNAMIC == 1 /* dynamic loading for builtins */
+SHOPT_ECHOPRINT == /* make echo equivalent to print */
+SHOPT_EDPREDICT == 1 /* predictive editing */
+SHOPT_ESH == 1 /* emacs/gmacs edit mode */
+SHOPT_FILESCAN == 1 /* fast file scan */
+SHOPT_FIXEDARRAY == 1 /* fixed dimension indexed array */
+SHOPT_FS_3D == /* 3d file system */
+SHOPT_HISTEXPAND == 1 /* csh-style history file expansions */
+SHOPT_KIA == 1 /* shell information database generation */
+SHOPT_MULTIBYTE == 1 /* multibyte character handling */
+SHOPT_NAMESPACE == 1 /* allow namespaces */
+SHOPT_OLDTERMIO == /* support both TCGETA and TCGETS */
+SHOPT_OPTIMIZE == 1 /* optimize loop invariants */
+SHOPT_PFSH == 1 /* solaris exec_attr(4) profile execution */
+SHOPT_P_SUID == /* real uid's that require -p for set[ug]id */
+SHOPT_RAWONLY == 1 /* make viraw the only vi mode */
+SHOPT_REGRESS == /* enable __regress__ builtin and instrumented intercepts for testing */
+SHOPT_REMOTE == /* enable --rc if running as a remote shell */
+SHOPT_SEVENBIT == /* strip the eigth bit from characters */
+SHOPT_SPAWN == /* use spawnveg for fork/exec */
+SHOPT_STATS == 1 /* add .sh.stats variable */
+SHOPT_SUID_EXEC == 1 /* allow (safe) suid/sgid shell scripts */
+SHOPT_SYSRC == /* attempt . /etc/ksh.kshrc if interactive */
+SHOPT_TIMEOUT == /* number of seconds for shell timeout */
+SHOPT_TYPEDEF == 1 /* enable typeset type definitions */
+SHOPT_VSH == 1 /* vi edit mode */
+
+if CC.HOSTTYPE == "linux.alpha"
+ /* workaround for "BUG IN DYNAMIC LINKER ld.so" */
+ :PACKAGE: - m:static:noinclude /*noCC.EXPORT.DYNAMIC*/
+end
+
+if CC.HOSTTYPE == "*.s390-64"
+ CC.DLL = $(CC.DLLBIG)
+end
+
+if SHOPT_DYNAMIC && ( "$(CC.DIALECT:N=EXPORT=DLL)" || "$(PACKAGE_OPTIONS:N=optimize-space)" )
+ CCFLAGS += $$(CC.DLL) $$(CC.SUFFIX.DEBUG:+$$(CC.DEBUG))
+ LIBS_req = -lshell$(RELEASE)
+else
+ if VARIANT
+ SHOPT_DYNAMIC = 1
+ else
+ libtype = :static
+ end
+ if SHOPT_DYNAMIC
+ CCLDFLAGS += $$(CC.EXPORT.DYNAMIC)
+ end
+ LIBS_req = +lshell$(RELEASE)
+end
+
+:PACKAGE: ast$(libtype):20100309 coshell:order --clobber=!($(SH))
+
+.SOURCE : edit sh bltins data tests fun
+.SOURCE.h : include
+
+/* documentation files */
+DOCFILES = sh.memo builtins.mm README RELEASE TYPES PROMO.mm COMPATIBILITY \
+ DESIGN OBSOLETE RELEASE93 RELEASE88
+
+KSHELL == 1 /* this is ksh */
+
+SH_CMDLIB_DIR == /* SHOPT_CMDLIB_DIR dir prefix */
+SH_DICT == /* message catalog */
+DEBUG == /* debugging purposes only */
+
+if CC.HOSTTYPE == "win32*"
+ SHOPT_CRNL == 1 /* <cr><nl> is eqivalent to <nl> */
+end
+
+if SHOPT_BASH
+ BASH_HOSTTYPE == "$(CC.HOSTTYPE:S:/\.//)"
+ BASH_MACHTYPE == "$(BASH_HOSTTYPE)-unknown-$(CC.HOSTTYPE:B)"
+end
+
+/* use the following libraries only if they exist */
+LIBS_opt := +ljobs +li
+
+if CC.HOSTTYPE == "sol([89]|[1-9][0-9]).*"
+ LDFLAGS += $(CC.LD.LAZY) $(CC.LD.NORECORD)
+end
+
+if "$(-mam:N=static*)"
+ LIBS_opt += -lsocket -lnsl
+elif CC.HOSTTYPE == "sol?([789]|[1-9][0-9]).*"
+ LIBS_opt += +lsocket -lnsl
+elif CC.HOSTTYPE != "sgi.mips*"
+ LIBS_opt += +lsocket +lnsl
+end
+if CC.HOSTTYPE == "linux.sparc*"
+ /* the linux.sparc linker still has some problems */
+ LIBS_opt += -ldll
+end
+LIBS_opt += -lsecdb
+if CC.HOSTTYPE == "sol.*"
+ LIBS_opt += +lw
+end
+$(LIBS_opt) : .DONTCARE
+
+LDLIBRARIES = $(LIBS_opt)
+
+FILES_opt = /* optional file list enabled by vars above */
+if SHOPT_ESH
+ FILES_opt += emacs.c
+end
+if SHOPT_VSH
+ FILES_opt += vi.c
+end
+if SHOPT_BASH
+ FILES_opt += bash.c bash_pre_rc.c
+ SHOPT_HISTEXPAND == 1
+end
+if SHOPT_HISTEXPAND
+ FILES_opt += hexpand.c
+end
+if SHOPT_DYNAMIC
+ FILES_opt += -ldll
+end
+if SHOPT_X
+ LDFLAGS += -u _XtAppInitialize -L/usr/add-on/X11/lib
+end
+
+:ALL: $(SH) $(SHCOMP) $(SHOPT_SUID_EXEC:+suid_exec) $(SHOPT_BASH:+bash$(RELEASE))
+
+$(SH) :: sh.1 pmain.c $(LIBS_req)
+
+DATAFILES = limits.c msg.c strdata.c testops.c keywords.c options.c \
+ signals.c aliases.c builtins.c variables.c lexstates.c
+
+shell$(RELEASE) $(VERSION) id=shell :LIBRARY: shell.3 nval.3 alarm.c cd_pwd.c cflow.c deparse.c \
+ enum.c getopts.c hist.c misc.c print.c read.c sleep.c trap.c test.c \
+ typeset.c ulimit.c umask.c whence.c main.c nvdisc.c nvtype.c \
+ arith.c args.c array.c completion.c defs.c edit.c expand.c regress.c \
+ fault.c fcin.c history.c init.c io.c jobs.c lex.c macro.c name.c \
+ nvtree.c parse.c path.c string.c streval.c subshell.c tdump.c timers.c \
+ trestore.c waitevent.c xec.c env.c $(DATAFILES) $(FILES_opt) \
+ $(SHOPT_COSHELL:+-lcoshell) -lcmd -last -lm
+
+"sol*.i386*" :NOOPTIMIZE: main.c
+"win32*" :NOOPTIMIZE: strdata.c trestore.c
+
+if CC.HOSTTYPE == "win32*"
+:DLL: $(CC.DEBUG)
+else
+:DLL: $(CC.OPTIMIZE)
+end
+
+:READONLY: $(DATAFILES)
+
+$(INCLUDEDIR) :INSTALLPROTO: nval.h shell.h history.h
+
+LIBCMD = $(.LIB.NAME. cmd:T=F)
+
+if SHOPT_SUID_EXEC && ! "$(RELEASE)"
+suid_exec :: CC.DLL= suid_exec.c +last
+end
+
+$(SHCOMP) :: CC.DLL= SH_DICT='"libshell"' shcomp.c $(LIBS_req)
+
+$(FUNDIR) :INSTALLDIR: mode=+x dirs popd pushd
+
+shcomp.o : _BLD_DLL= $(CC.HOSTTYPE:N=cygwin.*:??_BLD_shell=?)
+
+if SHOPT_BASH
+
+bash$(RELEASE) :LINK: $(SH)
+
+bash_pre_rc.c : bash_pre_rc.sh
+ echo "const char bash_pre_rc[] = " > $(<)
+ sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/'"'"'/\\'"'"'/g' -e 's/^[[:space:]]*\(.*\)$/\"\1\\n\"/' $(*) >> $(<)
+ echo ";" >> $(<)
+
+end
+
+:: math.tab syscall.s mamexec mamstate.c $(DOCFILES) \
+ bash.c bash_pre_rc.sh hexpand.c mkservice.c \
+ shopen.mk shopen.c
+
+:: shtests \
+ alias.sh append.sh arith.sh arrays.sh arrays2.sh \
+ attributes.sh basic.sh bracket.sh builtins.sh case.sh \
+ comvar.sh comvario.sh coprocess.sh cubetype.sh enum.sh exit.sh \
+ expand.sh functions.sh glob.sh grep.sh heredoc.sh io.sh \
+ leaks.sh locale.sh math.sh nameref.sh options.sh path.sh \
+ pointtype.sh pty.sh quoting.sh quoting2.sh readcsv.sh recttype.sh \
+ restricted.sh return.sh select.sh shtests sigchld.sh \
+ signal.sh statics.sh subshell.sh substring.sh tilde.sh \
+ timetype.sh treemove.sh types.sh variables.sh \
+ vartree1.sh vartree2.sh
+
+:: ksh-regress.rt ksh-regress.tst
+
+if "$(PWD:B:N=cc-*)"
+
+test : .NULL
+
+else
+
+test : test.ksh
+
+test.ksh : $(BINDIR)/$(SH) $(SH) shtests
+ $(SILENT) $(CMP) $(CMPFLAGS) $(*:O=1) $(*:O=2) 2>/dev/null ||
+ echo "make install to run the tests on the latest $(SH)" >&2
+ cd $(*:O=3:P=L!:D)
+ SHELL=$(*:O=1:P=A) $(*:O=1:P=A) $(*:O=3:B) $(SHTESTSFLAGS)
+
+test.% : %.sh COSHELL_OPTIONS=separate $(BINDIR)/$(SH) $(SH) shtests
+ $(SILENT) $(CMP) $(CMPFLAGS) $(*:O=2) $(*:O=3) 2>/dev/null ||
+ echo "make install to run the tests on the latest $(SH)" >&2
+ cd $(*:O=4:P=L!:D)
+ SHELL=$(*:O=2:P=A) $(*:O=2:P=A) $(*:O=4:B) $(SHTESTSFLAGS) $(*:O=1:P=A)
+
+if RELEASE
+
+.INSTALL : .CLEAR $(*.INSTALL:N=*$(RELEASE)*([!/]))
+
+end
+
+end
diff --git a/src/cmd/ksh93/Mamfile b/src/cmd/ksh93/Mamfile
new file mode 100644
index 0000000..5a55040
--- /dev/null
+++ b/src/cmd/ksh93/Mamfile
@@ -0,0 +1,1527 @@
+info mam static 00000 1994-07-17 make (AT&T Research) 5.7 2012-02-29
+setv INSTALLROOT ../../..
+setv PACKAGE_ast_INCLUDE ${INSTALLROOT}/include/ast
+setv PACKAGE_ast_LIB ${INSTALLROOT}/lib
+setv PACKAGEROOT ../../../../..
+setv AR ${mam_cc_AR} ${mam_cc_AR_ARFLAGS}
+setv ARFLAGS rc
+setv AS as
+setv ASFLAGS
+setv CC cc
+setv mam_cc_FLAGS
+setv CCFLAGS ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${mam_cc_OPTIMIZE}?}
+setv CCLDFLAGS ${-strip-symbols?1?${mam_cc_LD_STRIP}??}
+setv COTEMP $$
+setv CPIO cpio
+setv CPIOFLAGS
+setv CPP "${CC} -E"
+setv F77 f77
+setv HOSTCC ${CC}
+setv IGNORE
+setv LD ld
+setv LDFLAGS
+setv LEX lex
+setv LEXFLAGS
+setv LPR lpr
+setv LPRFLAGS
+setv M4FLAGS
+setv NMAKE nmake
+setv NMAKEFLAGS
+setv PR pr
+setv PRFLAGS
+setv SHELL /bin/sh
+setv SILENT
+setv TAR tar
+setv YACC yacc
+setv YACCFLAGS -d
+make ${PACKAGEROOT}/lib/package/ast.lic
+done ${PACKAGEROOT}/lib/package/ast.lic
+make install
+make ksh
+make pmain.o
+make sh/pmain.c
+make FEATURE/externs implicit
+meta FEATURE/externs features/%>FEATURE/% features/externs externs
+make features/externs
+done features/externs
+exec - set -
+exec - echo 'int main(){return 0;}' > 1.${COTEMP}.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -c 1.${COTEMP}.c &&
+exec - x=`${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l'*' 2>&1 | sed -e 's/[][()+@?]/#/g' || :` &&
+exec - {
+exec - case "" in
+exec - *?) echo " " ;;
+exec - esac
+exec - for i in shell dll coshell cmd ast m jobs i socket nsl secdb
+exec - do case $i in
+exec - "shell"|shell)
+exec - ;;
+exec - *) if test -f ${INSTALLROOT}/lib/lib/$i
+exec - then y=`cat ${INSTALLROOT}/lib/lib/$i`
+exec - case $y in
+exec - *-?*) echo "" $y ;;
+exec - esac
+exec - continue
+exec - elif test ! -f ${INSTALLROOT}/lib/lib$i.a
+exec - then case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -L${INSTALLROOT}/lib ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) continue ;;
+exec - esac
+exec - ;;
+exec - esac
+exec - fi
+exec - ;;
+exec - esac
+exec - echo " -l$i"
+exec - done
+exec - } > shell.req
+exec - rm -f 1.${COTEMP}.*
+bind -ldll
+bind -lcoshell
+bind -lcmd
+bind -last
+bind -lm dontcare
+bind -lnsl dontcare
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/externs
+done FEATURE/externs generated
+make include/shell.h implicit
+make ${PACKAGE_ast_INCLUDE}/cmd.h implicit
+make ${PACKAGE_ast_INCLUDE}/dlldefs.h implicit
+done ${PACKAGE_ast_INCLUDE}/dlldefs.h dontcare
+make ${PACKAGE_ast_INCLUDE}/cmdext.h implicit
+make ${PACKAGE_ast_INCLUDE}/shcmd.h implicit
+make ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+make ${INSTALLROOT}/include/prototyped.h implicit
+done ${INSTALLROOT}/include/prototyped.h dontcare
+done ${PACKAGE_ast_INCLUDE}/prototyped.h dontcare
+done ${PACKAGE_ast_INCLUDE}/shcmd.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/cmdext.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/shcmd.h implicit
+make ${PACKAGE_ast_INCLUDE}/stak.h implicit
+make ${PACKAGE_ast_INCLUDE}/stk.h implicit
+make ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+make ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
+done ${PACKAGE_ast_INCLUDE}/sfio_s.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_map.h dontcare
+make ${PACKAGE_ast_INCLUDE}/endian.h implicit
+make ${PACKAGE_ast_INCLUDE}/bytesex.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+done ${PACKAGE_ast_INCLUDE}/bytesex.h dontcare
+done ${PACKAGE_ast_INCLUDE}/endian.h dontcare
+done ${PACKAGE_ast_INCLUDE}/ast_common.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+make ${PACKAGE_ast_INCLUDE}/regex.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+make ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wctype.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wctype.h dontcare
+done ${PACKAGE_ast_INCLUDE}/wctype.h dontcare
+make ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_stdio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_stdio.h dontcare
+done ${PACKAGE_ast_INCLUDE}/stdio.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wchar.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/regex.h dontcare
+make ${PACKAGE_ast_INCLUDE}/getopt.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_getopt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_getopt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/getopt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_botch.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_botch.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_limits.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_limits.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_fcntl.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_fs.h dontcare
+done ${PACKAGE_ast_INCLUDE}/ast_fcntl.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_getopt.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_sys.h implicit
+prev ${PACKAGE_ast_INCLUDE}/getopt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_sys.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_lib.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_lib.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_std.h dontcare
+done ${PACKAGE_ast_INCLUDE}/sfio.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/stk.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/stak.h dontcare
+make ${PACKAGE_ast_INCLUDE}/error.h implicit
+make ${PACKAGE_ast_INCLUDE}/option.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_api.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_api.h dontcare
+make ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/vmalloc.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/option.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/error.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/cmd.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/shcmd.h implicit
+make include/nval.h implicit
+prev ${PACKAGE_ast_INCLUDE}/option.h implicit
+make ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/cdt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/nval.h dontcare
+make include/name.h implicit
+prev include/nval.h implicit
+prev ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/name.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/shell.h
+done sh/pmain.c
+meta pmain.o %.c>%.o sh/pmain.c pmain
+prev sh/pmain.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -c sh/pmain.c
+done pmain.o generated
+make libshell.a archive
+prev shell.req
+make alarm.o
+make bltins/alarm.c
+make FEATURE/time implicit
+meta FEATURE/time features/%>FEATURE/% features/time time
+make features/time
+done features/time
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/time
+make ${PACKAGE_ast_INCLUDE}/times.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_time.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_time.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/times.h dontcare
+done FEATURE/time generated
+make include/builtins.h implicit
+make include/shtable.h implicit
+done include/shtable.h dontcare
+make FEATURE/dynamic implicit
+meta FEATURE/dynamic features/%>FEATURE/% features/dynamic dynamic
+make features/dynamic
+done features/dynamic
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/dynamic
+make ${PACKAGE_ast_INCLUDE}/fs3d.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/fs3d.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/dlldefs.h implicit
+done FEATURE/dynamic dontcare generated
+make FEATURE/options implicit
+meta FEATURE/options features/%>FEATURE/% features/options options
+make features/options
+done features/options
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/options
+done FEATURE/options dontcare generated
+prev ${PACKAGE_ast_INCLUDE}/option.h implicit
+done include/builtins.h
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+make include/defs.h implicit
+make include/regress.h implicit
+done include/regress.h dontcare
+prev include/shtable.h implicit
+prev include/shell.h implicit
+make include/env.h implicit
+done include/env.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev include/name.h implicit
+make include/argnod.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+done include/argnod.h dontcare
+make include/fault.h implicit
+make FEATURE/sigfeatures implicit
+meta FEATURE/sigfeatures features/%>FEATURE/% features/sigfeatures sigfeatures
+make features/sigfeatures
+done features/sigfeatures
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/sigfeatures
+done FEATURE/sigfeatures dontcare generated
+make FEATURE/setjmp implicit
+meta FEATURE/setjmp features/%>FEATURE/% features/setjmp setjmp
+make features/setjmp
+done features/setjmp
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/setjmp
+done FEATURE/setjmp dontcare generated
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+make ${PACKAGE_ast_INCLUDE}/sig.h implicit
+done ${PACKAGE_ast_INCLUDE}/sig.h dontcare
+done include/fault.h dontcare
+make include/history.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/history.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev FEATURE/options implicit
+prev FEATURE/externs implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/defs.h
+done bltins/alarm.c
+meta alarm.o %.c>%.o bltins/alarm.c alarm
+prev bltins/alarm.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DERROR_CONTEXT_T=Error_context_t -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/alarm.c
+done alarm.o generated
+make cd_pwd.o
+make bltins/cd_pwd.c
+make ${PACKAGE_ast_INCLUDE}/ls.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_mode.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ls.h
+prev include/builtins.h implicit
+prev include/name.h implicit
+make include/path.h implicit
+make FEATURE/acct implicit
+meta FEATURE/acct >FEATURE/% acct
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : def acct
+done FEATURE/acct dontcare generated
+prev include/defs.h implicit
+prev include/nval.h implicit
+prev FEATURE/options implicit
+done include/path.h
+make include/variables.h implicit
+prev FEATURE/dynamic implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/option.h implicit
+done include/variables.h
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev include/defs.h implicit
+done bltins/cd_pwd.c
+meta cd_pwd.o %.c>%.o bltins/cd_pwd.c cd_pwd
+prev bltins/cd_pwd.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -c bltins/cd_pwd.c
+done cd_pwd.o generated
+make cflow.o
+make bltins/cflow.c
+prev include/builtins.h implicit
+make include/shnodes.h implicit
+prev include/argnod.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/shnodes.h
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev include/defs.h implicit
+done bltins/cflow.c
+meta cflow.o %.c>%.o bltins/cflow.c cflow
+prev bltins/cflow.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DERROR_CONTEXT_T=Error_context_t -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/cflow.c
+done cflow.o generated
+make deparse.o
+make sh/deparse.c
+make include/test.h implicit
+prev include/shtable.h implicit
+prev include/defs.h implicit
+prev FEATURE/options implicit
+done include/test.h
+prev include/shnodes.h implicit
+prev include/defs.h implicit
+done sh/deparse.c
+meta deparse.o %.c>%.o sh/deparse.c deparse
+prev sh/deparse.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/deparse.c
+done deparse.o generated
+make enum.o
+make bltins/enum.c
+prev include/shell.h implicit
+done bltins/enum.c
+meta enum.o %.c>%.o bltins/enum.c enum
+prev bltins/enum.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -Iinclude -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libshell"\" -DUSAGE_LICENSE=\""[-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1982-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libshell]"\" -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -c bltins/enum.c
+done enum.o generated
+make getopts.o
+make bltins/getopts.c
+prev include/builtins.h implicit
+prev include/nval.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+done bltins/getopts.c
+meta getopts.o %.c>%.o bltins/getopts.c getopts
+prev bltins/getopts.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DERROR_CONTEXT_T=Error_context_t -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/getopts.c
+done getopts.o generated
+make hist.o
+make bltins/hist.c
+make include/edit.h implicit
+make include/national.h implicit
+done include/national.h dontcare
+make include/terminal.h implicit
+make FEATURE/ttys implicit
+meta FEATURE/ttys features/%>FEATURE/% features/ttys ttys
+make features/ttys
+done features/ttys
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/ttys
+done FEATURE/ttys dontcare generated
+done include/terminal.h dontcare
+prev FEATURE/setjmp implicit
+prev ${PACKAGE_ast_INCLUDE}/sig.h implicit
+make FEATURE/locale implicit
+meta FEATURE/locale features/%>FEATURE/% features/locale locale
+make features/locale
+done features/locale
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/locale
+done FEATURE/locale dontcare generated
+prev FEATURE/options implicit
+done include/edit.h dontcare
+prev include/builtins.h implicit
+prev include/history.h implicit
+prev include/name.h implicit
+make include/io.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/io.h
+prev include/variables.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev include/defs.h implicit
+done bltins/hist.c
+meta hist.o %.c>%.o bltins/hist.c hist
+prev bltins/hist.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DSHOPT_MULTIBYTE -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -D_PACKAGE_ast -DSHOPT_PFSH -D_BLD_shell -DSHOPT_DYNAMIC -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DERROR_CONTEXT_T=Error_context_t -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -c bltins/hist.c
+done hist.o generated
+make misc.o
+make bltins/misc.c
+make include/jobs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+prev include/terminal.h implicit
+make ${PACKAGE_ast_INCLUDE}/coshell.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/coshell.h dontcare
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/jobs.h
+prev include/builtins.h implicit
+prev include/history.h implicit
+prev include/name.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/shnodes.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+done bltins/misc.c
+meta misc.o %.c>%.o bltins/misc.c misc
+prev bltins/misc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -DSHOPT_BGX -D_API_ast=20100309 -DSHOPT_COSHELL -DSHOPT_MULTIBYTE -DSHOPT_PFSH -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_ESH -DSHOPT_FIXEDARRAY -DKSHELL -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -c bltins/misc.c
+done misc.o generated
+make print.o
+make bltins/print.c
+make ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_ccode.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_ccode.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ccode.h
+make ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+make ${PACKAGE_ast_INCLUDE}/tv.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done ${PACKAGE_ast_INCLUDE}/tv.h dontcare
+make ${PACKAGE_ast_INCLUDE}/tm.h implicit
+prev ${PACKAGE_ast_INCLUDE}/times.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/tm.h dontcare
+done ${PACKAGE_ast_INCLUDE}/tmx.h
+make include/streval.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_float.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_float.h dontcare
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done include/streval.h
+prev include/builtins.h implicit
+prev include/history.h implicit
+prev include/name.h implicit
+prev include/io.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/defs.h implicit
+done bltins/print.c
+meta print.o %.c>%.o bltins/print.c print
+prev bltins/print.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_MULTIBYTE -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DKSHELL -c bltins/print.c
+done print.o generated
+make read.o
+make bltins/read.c
+prev include/edit.h implicit
+prev include/terminal.h implicit
+prev include/history.h implicit
+prev include/builtins.h implicit
+prev include/name.h implicit
+prev include/io.h implicit
+make include/lexstates.h implicit
+prev ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+make ${PACKAGE_ast_INCLUDE}/wchar.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+done ${PACKAGE_ast_INCLUDE}/wchar.h dontcare
+prev FEATURE/locale implicit
+done include/lexstates.h
+prev include/variables.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done bltins/read.c
+meta read.o %.c>%.o bltins/read.c read
+prev bltins/read.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_MULTIBYTE -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_FIXEDARRAY -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DERROR_CONTEXT_T=Error_context_t -c bltins/read.c
+done read.o generated
+make sleep.o
+make bltins/sleep.c
+make FEATURE/poll implicit
+meta FEATURE/poll features/%>FEATURE/% features/poll poll
+make features/poll
+done features/poll
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/poll
+done FEATURE/poll generated
+prev FEATURE/time implicit
+prev include/builtins.h implicit
+prev ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/defs.h implicit
+done bltins/sleep.c
+meta sleep.o %.c>%.o bltins/sleep.c sleep
+prev bltins/sleep.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DERROR_CONTEXT_T=Error_context_t -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/sleep.c
+done sleep.o generated
+make trap.o
+make bltins/trap.c
+prev include/builtins.h implicit
+prev include/jobs.h implicit
+prev include/defs.h implicit
+done bltins/trap.c
+meta trap.o %.c>%.o bltins/trap.c trap
+prev bltins/trap.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DSHOPT_BGX -DSHOPT_COSHELL -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/trap.c
+done trap.o generated
+make test.o
+make bltins/test.c
+prev ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+prev FEATURE/poll implicit
+prev FEATURE/externs implicit
+prev include/builtins.h implicit
+prev include/test.h implicit
+prev include/terminal.h implicit
+prev include/io.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/defs.h implicit
+done bltins/test.c
+meta test.o %.c>%.o bltins/test.c test
+prev bltins/test.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DKSHELL -c bltins/test.c
+done test.o generated
+make typeset.o
+make bltins/typeset.c
+prev FEATURE/dynamic implicit
+prev include/variables.h implicit
+prev include/builtins.h implicit
+prev include/history.h implicit
+prev include/name.h implicit
+prev include/path.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/defs.h implicit
+done bltins/typeset.c
+meta typeset.o %.c>%.o bltins/typeset.c typeset
+prev bltins/typeset.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_FIXEDARRAY -DSHOPT_DYNAMIC -DSHOPT_NAMESPACE -DSHOPT_TYPEDEF -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -D_BLD_shell -DSHOPT_ESH -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -c bltins/typeset.c
+done typeset.o generated
+make ulimit.o
+make bltins/ulimit.c
+make include/ulimit.h implicit
+make FEATURE/rlimits implicit
+meta FEATURE/rlimits features/%>FEATURE/% features/rlimits rlimits
+make features/rlimits
+done features/rlimits
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/rlimits
+done FEATURE/rlimits dontcare generated
+prev FEATURE/time implicit
+done include/ulimit.h
+prev include/name.h implicit
+prev include/builtins.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done bltins/ulimit.c
+meta ulimit.o %.c>%.o bltins/ulimit.c ulimit
+prev bltins/ulimit.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_FIXEDARRAY -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -c bltins/ulimit.c
+done ulimit.o generated
+make umask.o
+make bltins/umask.c
+prev include/builtins.h implicit
+prev include/shell.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done bltins/umask.c
+meta umask.o %.c>%.o bltins/umask.c umask
+prev bltins/umask.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c bltins/umask.c
+done umask.o generated
+make whence.o
+make bltins/whence.c
+prev include/builtins.h implicit
+make include/shlex.h implicit
+prev include/lexstates.h implicit
+prev include/shtable.h implicit
+prev include/shnodes.h implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+done include/shlex.h
+prev include/path.h implicit
+prev include/name.h implicit
+prev include/shtable.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/defs.h implicit
+done bltins/whence.c
+meta whence.o %.c>%.o bltins/whence.c whence
+prev bltins/whence.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DSHOPT_KIA -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/whence.c
+done whence.o generated
+make main.o
+make sh/main.c
+make execargs.h implicit
+done execargs.h dontcare virtual
+make ${PACKAGE_ast_INCLUDE}/fts.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/fts.h dontcare
+make nc.h implicit
+done nc.h dontcare virtual
+prev FEATURE/externs implicit
+make FEATURE/execargs implicit
+meta FEATURE/execargs >FEATURE/% execargs
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : def execargs
+done FEATURE/execargs generated
+make FEATURE/pstat implicit
+meta FEATURE/pstat >FEATURE/% pstat
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : def pstat
+done FEATURE/pstat generated
+prev FEATURE/time implicit
+make include/timeout.h implicit
+done include/timeout.h
+prev include/history.h implicit
+prev include/shnodes.h implicit
+prev include/shlex.h implicit
+prev include/jobs.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+make include/fcin.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+done include/fcin.h
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/main.c
+meta main.o %.c>%.o sh/main.c main
+prev sh/main.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${DEBUG+-DDEBUG=${DEBUG}} ${SHOPT_TIMEOUT+-DSHOPT_TIMEOUT=${SHOPT_TIMEOUT}} ${SHOPT_ACCT+-DSHOPT_ACCT=${SHOPT_ACCT}} ${SH_DICT+-DSH_DICT=${SH_DICT}} ${SHOPT_SYSRC+-DSHOPT_SYSRC=${SHOPT_SYSRC}} ${SHOPT_BASH+-DSHOPT_BASH=${SHOPT_BASH}} ${SHOPT_REMOTE+-DSHOPT_REMOTE=${SHOPT_REMOTE}} ${SHOPT_OLDTERMIO+-DSHOPT_OLDTERMIO=${SHOPT_OLDTERMIO}} ${SHOPT_SPAWN+-DSHOPT_SPAWN=${SHOPT_SPAWN}} ${SH_CMDLIB_DIR+-DSH_CMDLIB_DIR=${SH_CMDLIB_DIR}} ${SHOPT_P_SUID+-DSHOPT_P_SUID=${SHOPT_P_SUID}} ${SHOPT_REGRESS+-DSHOPT_REGRESS=${SHOPT_REGRESS}} ${SHOPT_FS_3D+-DSHOPT_FS_3D=${SHOPT_FS_3D}} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_ESH -D_BLD_shell -DSHOPT_KIA -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DSHOPT_BGX -DSHOPT_COSHELL -DKSHELL -DSHOPT_SUID_EXEC -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c sh/main.c
+done main.o generated
+make nvdisc.o
+make sh/nvdisc.c
+prev include/path.h implicit
+prev include/builtins.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+done sh/nvdisc.c
+meta nvdisc.o %.c>%.o sh/nvdisc.c nvdisc
+prev sh/nvdisc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_TYPEDEF -DSHOPT_SUID_EXEC -DSHOPT_PFSH -DSHOPT_BRACEPAT -D_BLD_shell -DSHOPT_STATS -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/nvdisc.c
+done nvdisc.o generated
+make nvtype.o
+make sh/nvtype.c
+prev include/variables.h implicit
+prev include/io.h implicit
+prev include/defs.h implicit
+done sh/nvtype.c
+meta nvtype.o %.c>%.o sh/nvtype.c nvtype
+prev sh/nvtype.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_TYPEDEF -DSHOPT_FIXEDARRAY -DSHOPT_NAMESPACE -DUSAGE_LICENSE=\""[-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1982-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libshell]"\" -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -D_BLD_shell -DKSHELL -DSHOPT_STATS -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -c sh/nvtype.c
+done nvtype.o generated
+make arith.o
+make sh/arith.c
+prev include/builtins.h implicit
+prev include/variables.h implicit
+prev include/streval.h implicit
+prev include/name.h implicit
+prev include/lexstates.h implicit
+prev include/defs.h implicit
+done sh/arith.c
+meta arith.o %.c>%.o sh/arith.c arith
+prev sh/arith.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_FIXEDARRAY -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -c sh/arith.c
+done arith.o generated
+make args.o
+make sh/args.c
+prev include/io.h implicit
+prev include/shlex.h implicit
+prev FEATURE/poll implicit
+prev include/edit.h implicit
+prev include/terminal.h implicit
+prev include/builtins.h implicit
+prev include/path.h implicit
+prev include/defs.h implicit
+done sh/args.c
+meta args.o %.c>%.o sh/args.c args
+prev sh/args.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_OPTIMIZE -DSHOPT_RAWONLY -DSHOPT_HISTEXPAND -DSHOPT_PFSH -D_BLD_shell -DKSHELL -D_PACKAGE_ast -D_API_ast=20100309 -DSHOPT_KIA -DSHOPT_MULTIBYTE -DSHOPT_EDPREDICT -DSHOPT_ESH -DSHOPT_VSH -DSHOPT_DYNAMIC -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c sh/args.c
+done args.o generated
+make array.o
+make sh/array.c
+prev include/name.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev include/defs.h implicit
+done sh/array.c
+meta array.o %.c>%.o sh/array.c array
+prev sh/array.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_TYPEDEF -DSHOPT_FIXEDARRAY -D_BLD_shell -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/array.c
+done array.o generated
+make completion.o
+make edit/completion.c
+prev include/history.h implicit
+prev include/edit.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/lexstates.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+prev include/defs.h implicit
+done edit/completion.c
+meta completion.o %.c>%.o edit/completion.c completion
+prev edit/completion.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_MULTIBYTE -DSHOPT_ESH -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DKSHELL -DSHOPT_VSH -DSHOPT_PFSH -D_BLD_shell -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c edit/completion.c
+done completion.o generated
+make defs.o
+make sh/defs.c
+prev include/timeout.h implicit
+prev include/edit.h implicit
+prev include/shlex.h implicit
+prev include/jobs.h implicit
+prev include/defs.h implicit
+done sh/defs.c
+meta defs.o %.c>%.o sh/defs.c defs
+prev sh/defs.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DSHOPT_MULTIBYTE -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -D_PACKAGE_ast -DSHOPT_PFSH -DSHOPT_KIA -D_BLD_shell -D_API_ast=20100309 -DSHOPT_BGX -DSHOPT_COSHELL -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c sh/defs.c
+done defs.o generated
+make edit.o
+make edit/edit.c
+prev include/edit.h implicit
+prev include/history.h implicit
+prev include/terminal.h implicit
+prev include/io.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+make FEATURE/cmds implicit
+meta FEATURE/cmds features/%>FEATURE/% features/cmds cmds
+make features/cmds
+done features/cmds
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/cmds
+done FEATURE/cmds generated
+prev FEATURE/time implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done edit/edit.c
+meta edit.o %.c>%.o edit/edit.c edit
+prev edit/edit.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_EDPREDICT -DSHOPT_RAWONLY -DSHOPT_ESH -DSHOPT_VSH -DSHOPT_MULTIBYTE -DSHOPT_HISTEXPAND -DKSHELL -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c edit/edit.c
+done edit.o generated
+make expand.o
+make sh/expand.c
+prev include/path.h implicit
+prev include/io.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_dir.h implicit
+make ${PACKAGE_ast_INCLUDE}/dirent.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_dirent.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_dirent.h dontcare
+done ${PACKAGE_ast_INCLUDE}/dirent.h dontcare
+make dirlib.h implicit
+done dirlib.h dontcare virtual
+prev ${PACKAGE_ast_INCLUDE}/ast_lib.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_dir.h
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+make ${PACKAGE_ast_INCLUDE}/glob.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/glob.h
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev include/test.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+done sh/expand.c
+meta expand.o %.c>%.o sh/expand.c expand
+prev sh/expand.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -DSHOPT_SUID_EXEC -DSHOPT_PFSH -D_BLD_shell -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -DKSHELL -c sh/expand.c
+done expand.o generated
+make regress.o
+make bltins/regress.c
+prev ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+prev include/builtins.h implicit
+prev include/io.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/defs.h implicit
+done bltins/regress.c
+meta regress.o %.c>%.o bltins/regress.c regress
+prev bltins/regress.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DUSAGE_LICENSE=\""[-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1982-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libshell]"\" -D_API_ast=20100309 -D_PACKAGE_ast -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DKSHELL -DERROR_CONTEXT_T=Error_context_t -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c bltins/regress.c
+done regress.o generated
+make fault.o
+make sh/fault.c
+prev ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+prev include/ulimit.h implicit
+prev include/builtins.h implicit
+prev include/path.h implicit
+prev include/jobs.h implicit
+prev include/variables.h implicit
+prev include/shlex.h implicit
+prev include/history.h implicit
+prev include/io.h implicit
+prev include/fcin.h implicit
+prev include/defs.h implicit
+done sh/fault.c
+meta fault.o %.c>%.o sh/fault.c fault
+prev sh/fault.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_KIA -DSHOPT_ESH -DSHOPT_VSH -DSHOPT_TYPEDEF -DSHOPT_BGX -D_PACKAGE_ast -D_API_ast=20100309 -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -DSHOPT_PFSH -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DKSHELL -c sh/fault.c
+done fault.o generated
+make fcin.o
+make sh/fcin.c
+prev include/fcin.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/fcin.c
+meta fcin.o %.c>%.o sh/fcin.c fcin
+prev sh/fcin.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -c sh/fcin.c
+done fcin.o generated
+make history.o
+make edit/history.c
+prev ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+prev include/history.h implicit
+prev include/io.h implicit
+prev include/builtins.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev FEATURE/time implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done edit/history.c
+meta history.o %.c>%.o edit/history.c history
+prev edit/history.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_VSH -DSHOPT_ESH -DSHOPT_MULTIBYTE -DSHOPT_AUDITFILE=\""/etc/ksh_audit"\" -D_API_ast=20100309 -D_PACKAGE_ast -D_BLD_shell -DKSHELL -DSHOPT_DYNAMIC -DSHOPT_PFSH -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c edit/history.c
+done history.o generated
+make init.o
+make sh/init.c
+prev ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+make include/version.h implicit
+done include/version.h
+prev include/lexstates.h implicit
+prev FEATURE/externs implicit
+prev FEATURE/dynamic implicit
+prev FEATURE/time implicit
+prev include/builtins.h implicit
+prev include/shlex.h implicit
+prev include/io.h implicit
+prev include/jobs.h implicit
+prev include/edit.h implicit
+prev include/name.h implicit
+prev include/fault.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev include/defs.h implicit
+done sh/init.c
+meta init.o %.c>%.o sh/init.c init
+prev sh/init.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_2DMATCH -DSHOPT_PFSH -DSHOPT_MULTIBYTE -DSHOPT_BGX -DSHOPT_COSHELL -D_PACKAGE_ast -DSHOPT_DYNAMIC -D_API_ast=20100309 -D_BLD_shell -DSHOPT_KIA -DKSHELL -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DSHOPT_ESH -DSHOPT_VSH -DSHOPT_FIXEDARRAY -DERROR_CONTEXT_T=Error_context_t -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -c sh/init.c
+done init.o generated
+make io.o
+make sh/io.c
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev FEATURE/poll implicit
+prev FEATURE/dynamic implicit
+prev FEATURE/externs implicit
+prev include/timeout.h implicit
+prev include/edit.h implicit
+prev include/history.h implicit
+prev include/shnodes.h implicit
+prev include/jobs.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev ${PACKAGE_ast_INCLUDE}/regex.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev include/fcin.h implicit
+prev include/defs.h implicit
+done sh/io.c
+meta io.o %.c>%.o sh/io.c io
+prev sh/io.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_RAWONLY -DSHOPT_VSH -DSHOPT_ESH -DSHOPT_HISTEXPAND -DSHOPT_COSHELL -DSHOPT_DYNAMIC -DSHOPT_EDPREDICT -DSHOPT_MULTIBYTE -DKSHELL -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -D_BLD_shell -DSHOPT_BGX -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c sh/io.c
+done io.o generated
+make jobs.o
+make sh/jobs.c
+prev include/history.h implicit
+prev include/jobs.h implicit
+prev include/io.h implicit
+make ${PACKAGE_ast_INCLUDE}/wait.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wait.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wait.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/wait.h
+prev include/defs.h implicit
+done sh/jobs.c
+meta jobs.o %.c>%.o sh/jobs.c jobs
+prev sh/jobs.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_VSH -DSHOPT_COSHELL -DSHOPT_BGX -DSHOPT_ESH -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_MULTIBYTE -DSHOPT_PFSH -D_BLD_shell -DKSHELL -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c sh/jobs.c
+done jobs.o generated
+make lex.o
+make sh/lex.c
+prev include/shlex.h implicit
+prev include/io.h implicit
+prev include/lexstates.h implicit
+prev include/test.h implicit
+prev include/argnod.h implicit
+prev include/shell.h implicit
+prev include/defs.h implicit
+prev FEATURE/options implicit
+prev include/nval.h implicit
+prev include/fcin.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/lex.c
+meta lex.o %.c>%.o sh/lex.c lex
+prev sh/lex.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_TYPEDEF -DSHOPT_MULTIBYTE -DSHOPT_KIA -D_PACKAGE_ast -D_BLD_shell -D_API_ast=20100309 -DSHOPT_PFSH -DKSHELL -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c sh/lex.c
+done lex.o generated
+make macro.o
+make sh/macro.c
+prev include/streval.h implicit
+prev include/national.h implicit
+prev include/path.h implicit
+prev include/shnodes.h implicit
+prev include/jobs.h implicit
+prev include/io.h implicit
+prev include/shlex.h implicit
+prev include/variables.h implicit
+prev include/name.h implicit
+prev include/fcin.h implicit
+prev include/defs.h implicit
+done sh/macro.c
+meta macro.o %.c>%.o sh/macro.c macro
+prev sh/macro.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -DKSHELL -DSHOPT_COSHELL -DSHOPT_OPTIMIZE -DSHOPT_FIXEDARRAY -DSHOPT_TYPEDEF -DSHOPT_FILESCAN -DSHOPT_MULTIBYTE -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_ESH -DSHOPT_SUID_EXEC -DSHOPT_BGX -DSHOPT_KIA -c sh/macro.c
+done macro.o generated
+make name.o
+make sh/name.c
+prev include/builtins.h implicit
+prev include/shnodes.h implicit
+prev include/streval.h implicit
+prev FEATURE/externs implicit
+prev include/timeout.h implicit
+prev include/lexstates.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+done sh/name.c
+meta name.o %.c>%.o sh/name.c name
+prev sh/name.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_OPTIMIZE -DSHOPT_FIXEDARRAY -DSHOPT_NAMESPACE -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DSHOPT_TYPEDEF -DSHOPT_STATS -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -c sh/name.c
+done name.o generated
+make nvtree.o
+make sh/nvtree.c
+prev include/lexstates.h implicit
+prev include/argnod.h implicit
+prev include/name.h implicit
+prev include/defs.h implicit
+done sh/nvtree.c
+meta nvtree.o %.c>%.o sh/nvtree.c nvtree
+prev sh/nvtree.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_FIXEDARRAY -DSHOPT_MULTIBYTE -D_PACKAGE_ast -D_BLD_shell -D_API_ast=20100309 -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -c sh/nvtree.c
+done nvtree.o generated
+make parse.o
+make sh/parse.c
+prev include/path.h implicit
+prev include/test.h implicit
+prev include/builtins.h implicit
+prev include/history.h implicit
+prev include/shlex.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/fcin.h implicit
+prev include/shell.h implicit
+prev include/defs.h implicit
+done sh/parse.c
+meta parse.o %.c>%.o sh/parse.c parse
+prev sh/parse.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_SUID_EXEC -DSHOPT_PFSH -DSHOPT_BRACEPAT -D_BLD_shell -DSHOPT_STATS -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -DSHOPT_KIA -DKSHELL -c sh/parse.c
+done parse.o generated
+make path.o
+make sh/path.c
+prev FEATURE/time implicit
+make ${PACKAGE_ast_INCLUDE}/ast_vfork.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_vfork.h dontcare
+make exec_attr.h implicit
+done exec_attr.h dontcare virtual
+prev FEATURE/externs implicit
+prev FEATURE/dynamic implicit
+prev include/test.h implicit
+prev include/history.h implicit
+prev include/jobs.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev include/nval.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev include/fcin.h implicit
+prev include/defs.h implicit
+done sh/path.c
+meta path.o %.c>%.o sh/path.c path
+prev sh/path.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_SUID_EXEC -DSHOPT_NAMESPACE -DSHOPT_DYNAMIC -DSHOPT_PFSH -DSHOPT_STATS -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -DSHOPT_BGX -DKSHELL -DSHOPT_BRACEPAT -c sh/path.c
+done path.o generated
+make string.o
+make sh/string.c
+prev ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+prev include/national.h implicit
+prev include/lexstates.h implicit
+prev include/shtable.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/string.c
+meta string.o %.c>%.o sh/string.c string
+prev sh/string.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c sh/string.c
+done string.o generated
+make streval.o
+make sh/streval.c
+prev include/defs.h implicit
+prev FEATURE/externs implicit
+prev ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev include/streval.h implicit
+done sh/streval.c
+meta streval.o %.c>%.o sh/streval.c streval
+prev sh/streval.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/streval.c
+done streval.o generated
+make subshell.o
+make sh/subshell.c
+prev include/path.h implicit
+prev include/variables.h implicit
+prev include/jobs.h implicit
+prev include/shlex.h implicit
+prev include/shnodes.h implicit
+prev include/fault.h implicit
+prev include/io.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev include/defs.h implicit
+done sh/subshell.c
+meta subshell.o %.c>%.o sh/subshell.c subshell
+prev sh/subshell.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_COSHELL -DSHOPT_SUID_EXEC -DSHOPT_PFSH -DSHOPT_BRACEPAT -D_BLD_shell -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -DSHOPT_BGX -DSHOPT_KIA -DKSHELL -c sh/subshell.c
+done subshell.o generated
+make tdump.o
+make sh/tdump.c
+prev ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/shnodes.h implicit
+prev include/defs.h implicit
+done sh/tdump.c
+meta tdump.o %.c>%.o sh/tdump.c tdump
+prev sh/tdump.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DKSHELL -D_PACKAGE_ast -D_API_ast=20100309 -DSHOPT_SUID_EXEC -DSHOPT_PFSH -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/tdump.c
+done tdump.o generated
+make timers.o
+make sh/timers.c
+prev FEATURE/time implicit
+prev FEATURE/sigfeatures implicit
+prev include/defs.h implicit
+prev include/fault.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sig.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/timers.c
+meta timers.o %.c>%.o sh/timers.c timers
+prev sh/timers.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/timers.c
+done timers.o generated
+make trestore.o
+make sh/trestore.c
+prev ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/shnodes.h implicit
+prev include/defs.h implicit
+done sh/trestore.c
+meta trestore.o %.c>%.o sh/trestore.c trestore
+prev sh/trestore.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${SHOPT_BASH+-DSHOPT_BASH=${SHOPT_BASH}} ${SHOPT_SYSRC+-DSHOPT_SYSRC=${SHOPT_SYSRC}} ${SHOPT_ACCT+-DSHOPT_ACCT=${SHOPT_ACCT}} ${SHOPT_SPAWN+-DSHOPT_SPAWN=${SHOPT_SPAWN}} ${SH_CMDLIB_DIR+-DSH_CMDLIB_DIR=${SH_CMDLIB_DIR}} ${SH_DICT+-DSH_DICT=${SH_DICT}} ${SHOPT_P_SUID+-DSHOPT_P_SUID=${SHOPT_P_SUID}} ${SHOPT_REGRESS+-DSHOPT_REGRESS=${SHOPT_REGRESS}} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_BLD_shell -DKSHELL -D_PACKAGE_ast -D_API_ast=20100309 -DSHOPT_SUID_EXEC -DSHOPT_PFSH -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/trestore.c
+done trestore.o generated
+make waitevent.o
+make sh/waitevent.c
+prev include/defs.h implicit
+done sh/waitevent.c
+meta waitevent.o %.c>%.o sh/waitevent.c waitevent
+prev sh/waitevent.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c sh/waitevent.c
+done waitevent.o generated
+make xec.o
+make sh/xec.c
+prev ${PACKAGE_ast_INCLUDE}/ast_vfork.h implicit
+prev ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+prev include/streval.h implicit
+prev FEATURE/locale implicit
+prev FEATURE/externs implicit
+prev FEATURE/time implicit
+prev include/builtins.h implicit
+prev include/test.h implicit
+prev include/jobs.h implicit
+prev include/shnodes.h implicit
+prev include/io.h implicit
+prev include/name.h implicit
+prev include/path.h implicit
+prev include/variables.h implicit
+prev include/fcin.h implicit
+prev include/defs.h implicit
+done sh/xec.c
+meta xec.o %.c>%.o sh/xec.c xec
+prev sh/xec.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_FILESCAN -DSHOPT_BGX -DSHOPT_TYPEDEF -DSHOPT_PFSH -DSHOPT_COSHELL -DSHOPT_NAMESPACE -DSHOPT_OPTIMIZE -D_PACKAGE_ast -DSHOPT_STATS -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -DKSHELL -DSHOPT_SUID_EXEC -DSHOPT_BRACEPAT -c sh/xec.c
+done xec.o generated
+make env.o
+make sh/env.c
+prev include/env.h implicit
+prev ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/env.c
+meta env.o %.c>%.o sh/env.c env
+prev sh/env.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -Iinclude -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_API_ast=20100309 -c sh/env.c
+done env.o generated
+make limits.o
+make data/limits.c
+prev include/ulimit.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done data/limits.c
+meta limits.o %.c>%.o data/limits.c limits
+prev data/limits.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -D_PACKAGE_ast -c data/limits.c
+done limits.o generated
+make msg.o
+make data/msg.c
+prev FEATURE/cmds implicit
+prev include/edit.h implicit
+prev include/jobs.h implicit
+prev include/builtins.h implicit
+prev include/history.h implicit
+prev include/timeout.h implicit
+prev include/shlex.h implicit
+prev include/io.h implicit
+prev include/path.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done data/msg.c
+meta msg.o %.c>%.o data/msg.c msg
+prev data/msg.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_SUID_EXEC -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DSHOPT_MULTIBYTE -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -D_PACKAGE_ast -DSHOPT_PFSH -DSHOPT_BGX -D_API_ast=20100309 -D_BLD_shell -DSHOPT_DYNAMIC -DSHOPT_KIA -DSHOPT_BRACEPAT -DSHOPT_STATS -DSHOPT_NAMESPACE -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c data/msg.c
+done msg.o generated
+make strdata.o
+make data/strdata.c
+make FEATURE/math implicit
+meta FEATURE/math features/%.sh>FEATURE/% features/math.sh math
+make features/math.sh
+make data/math.tab implicit
+done data/math.tab
+done features/math.sh dontcare
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcoshell} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/math.sh data/math.tab
+make ${PACKAGE_ast_INCLUDE}/ast_standards.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_standards.h dontcare
+done FEATURE/math generated
+prev include/streval.h implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_standards.h implicit
+done data/strdata.c
+meta strdata.o %.c>%.o data/strdata.c strdata
+prev data/strdata.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${SHOPT_BASH+-DSHOPT_BASH=${SHOPT_BASH}} ${SH_CMDLIB_DIR+-DSH_CMDLIB_DIR=${SH_CMDLIB_DIR}} ${SH_DICT+-DSH_DICT=${SH_DICT}} ${SHOPT_P_SUID+-DSHOPT_P_SUID=${SHOPT_P_SUID}} ${SHOPT_REGRESS+-DSHOPT_REGRESS=${SHOPT_REGRESS}} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c data/strdata.c
+done strdata.o generated
+make testops.o
+make data/testops.c
+prev include/test.h implicit
+prev include/defs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done data/testops.c
+meta testops.o %.c>%.o data/testops.c testops
+prev data/testops.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DUSAGE_LICENSE=\""[-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1982-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libshell]"\" -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c data/testops.c
+done testops.o generated
+make keywords.o
+make data/keywords.c
+prev FEATURE/options implicit
+prev include/shlex.h implicit
+prev include/shell.h implicit
+done data/keywords.c
+meta keywords.o %.c>%.o data/keywords.c keywords
+prev data/keywords.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_NAMESPACE -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -DSHOPT_KIA -D_BLD_shell -D_API_ast=20100309 -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c data/keywords.c
+done keywords.o generated
+make options.o
+make data/options.c
+prev include/shtable.h implicit
+prev include/name.h implicit
+prev include/defs.h implicit
+done data/options.c
+meta options.o %.c>%.o data/options.c options
+prev data/options.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_FIXEDARRAY -D_BLD_shell -D_API_ast=20100309 -D_PACKAGE_ast -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -DSHOPT_MULTIBYTE -c data/options.c
+done options.o generated
+make signals.o
+make data/signals.c
+prev include/defs.h implicit
+done data/signals.c
+meta signals.o %.c>%.o data/signals.c signals
+prev data/signals.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -D_BLD_shell -D_PACKAGE_ast -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -c data/signals.c
+done signals.o generated
+make aliases.o
+make data/aliases.c
+prev FEATURE/dynamic implicit
+prev FEATURE/options implicit
+prev include/defs.h implicit
+done data/aliases.c
+meta aliases.o %.c>%.o data/aliases.c aliases
+prev data/aliases.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_DYNAMIC -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c data/aliases.c
+done aliases.o generated
+make builtins.o
+make data/builtins.c
+prev FEATURE/cmds implicit
+prev include/jobs.h implicit
+prev include/builtins.h implicit
+prev include/version.h implicit
+prev include/name.h implicit
+prev include/ulimit.h implicit
+prev include/shtable.h implicit
+prev include/defs.h implicit
+done data/builtins.c
+meta builtins.o %.c>%.o data/builtins.c builtins
+prev data/builtins.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_TYPEDEF -DSHOPT_KIA -DSHOPT_PFSH -DUSAGE_LICENSE=\""[-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1982-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libshell]"\" -DSHOPT_BRACEPAT -DSHOPT_HISTEXPAND -DSHOPT_COSHELL -D_PACKAGE_ast -DSHOPT_BGX -D_API_ast=20100309 -DSHOPT_MULTIBYTE -D_BLD_shell -DSHOPT_DYNAMIC -DKSHELL -DSHOPT_FIXEDARRAY -DSHOPT_STATS -DSHOPT_NAMESPACE -DERROR_CONTEXT_T=Error_context_t -DSHOPT_ESH -c data/builtins.c
+done builtins.o generated
+make variables.o
+make data/variables.c
+prev include/builtins.h implicit
+prev include/variables.h implicit
+prev include/defs.h implicit
+prev include/name.h implicit
+prev include/shtable.h implicit
+prev include/shell.h implicit
+prev FEATURE/dynamic implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done data/variables.c
+meta variables.o %.c>%.o data/variables.c variables
+prev data/variables.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_STATS -DSHOPT_MULTIBYTE -D_BLD_shell -DSHOPT_DYNAMIC -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_HISTEXPAND -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -c data/variables.c
+done variables.o generated
+make lexstates.o
+make data/lexstates.c
+prev include/lexstates.h implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done data/lexstates.c
+meta lexstates.o %.c>%.o data/lexstates.c lexstates
+prev data/lexstates.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -DSHOPT_TYPEDEF -DSHOPT_NAMESPACE -DSHOPT_MULTIBYTE -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -c data/lexstates.c
+done lexstates.o generated
+make emacs.o
+make edit/emacs.c
+prev include/terminal.h implicit
+prev include/edit.h implicit
+prev include/history.h implicit
+prev include/io.h implicit
+prev include/defs.h implicit
+prev FEATURE/cmds implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done edit/emacs.c
+meta emacs.o %.c>%.o edit/emacs.c emacs
+prev edit/emacs.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_EDPREDICT -DSHOPT_MULTIBYTE -DSHOPT_HISTEXPAND -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -D_PACKAGE_ast -DSHOPT_PFSH -D_API_ast=20100309 -D_BLD_shell -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c edit/emacs.c
+done emacs.o generated
+make vi.o
+make edit/vi.c
+prev include/lexstates.h implicit
+prev FEATURE/time implicit
+prev include/terminal.h implicit
+prev include/edit.h implicit
+prev include/history.h implicit
+prev include/io.h implicit
+prev FEATURE/options implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev include/defs.h implicit
+done edit/vi.c
+meta vi.o %.c>%.o edit/vi.c vi
+prev edit/vi.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_EDPREDICT -DSHOPT_RAWONLY -DSHOPT_MULTIBYTE -D_PACKAGE_ast -D_API_ast=20100309 -DSHOPT_HISTEXPAND -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -DSHOPT_PFSH -D_BLD_shell -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -c edit/vi.c
+done vi.o generated
+make hexpand.o
+make edit/hexpand.c
+prev include/edit.h implicit
+prev include/defs.h implicit
+done edit/hexpand.c
+meta hexpand.o %.c>%.o edit/hexpand.c hexpand
+prev edit/hexpand.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_HISTEXPAND -DSHOPT_EDPREDICT -DSHOPT_MULTIBYTE -DKSHELL -DSHOPT_ESH -DSHOPT_VSH -D_PACKAGE_ast -DSHOPT_PFSH -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_DYNAMIC -D_BLD_shell -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -DSHOPT_FIXEDARRAY -c edit/hexpand.c
+done hexpand.o generated
+exec - ${AR} rc libshell.a alarm.o cd_pwd.o cflow.o deparse.o enum.o getopts.o hist.o misc.o print.o read.o sleep.o trap.o test.o typeset.o ulimit.o umask.o whence.o main.o nvdisc.o nvtype.o arith.o args.o array.o completion.o defs.o edit.o expand.o regress.o fault.o fcin.o
+exec - ${AR} rc libshell.a history.o init.o io.o jobs.o lex.o macro.o name.o nvtree.o parse.o path.o string.o streval.o subshell.o tdump.o timers.o trestore.o waitevent.o xec.o env.o limits.o msg.o strdata.o testops.o keywords.o options.o signals.o aliases.o builtins.o variables.o lexstates.o emacs.o vi.o hexpand.o
+exec - (ranlib libshell.a) >/dev/null 2>&1 || true
+done libshell.a generated
+bind -lshell
+prev +ljobs
+prev +li
+prev ${mam_libsocket}
+prev ${mam_libsecdb}
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -o ksh pmain.o ${mam_libshell} ${mam_libnsl} ${mam_libast}
+done ksh generated
+make shcomp
+make shcomp.o
+make sh/shcomp.c
+prev include/shnodes.h implicit
+prev include/defs.h implicit
+prev include/shell.h implicit
+done sh/shcomp.c
+meta shcomp.o %.c>%.o sh/shcomp.c shcomp
+prev sh/shcomp.c
+setv CC.DLL -UCC.DLL
+setv SH_DICT -DSH_DICT="\"libshell\""
+setv _BLD_shell -U_BLD_shell
+setv _BLD_DLL -U_BLD_DLL
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DSHOPT_BRACEPAT -DSH_DICT=\""libshell"\" -D_PACKAGE_ast -D_API_ast=20100309 -DSHOPT_STATS -DSHOPT_NAMESPACE -DSHOPT_COSHELL -DSHOPT_PFSH -DSHOPT_HISTEXPAND -DSHOPT_DYNAMIC -DERROR_CONTEXT_T=Error_context_t -DSHOPT_FIXEDARRAY -DSHOPT_ESH -DSHOPT_MULTIBYTE -DUSAGE_LICENSE=\""[-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1982-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libshell]"\" -c sh/shcomp.c
+done shcomp.o generated
+prev libshell.a archive
+prev +ljobs
+prev +li
+prev ${mam_libsocket}
+prev ${mam_libsecdb}
+setv CC.DLL -UCC.DLL
+setv SH_DICT -DSH_DICT="\"libshell\""
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -o shcomp shcomp.o ${mam_libshell} ${mam_libnsl} ${mam_libast}
+done shcomp generated
+make suid_exec
+make suid_exec.o
+make sh/suid_exec.c
+prev include/version.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sig.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev FEATURE/externs implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done sh/suid_exec.c
+meta suid_exec.o %.c>%.o sh/suid_exec.c suid_exec
+prev sh/suid_exec.c
+setv CC.DLL -UCC.DLL
+setv _BLD_shell -U_BLD_shell
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -DERROR_CONTEXT_T=Error_context_t -D_API_ast=20100309 -D_PACKAGE_ast -c sh/suid_exec.c
+done suid_exec.o generated
+prev +ljobs
+prev +li
+prev ${mam_libsocket}
+prev ${mam_libsecdb}
+setv CC.DLL -UCC.DLL
+exec - ${CC} ${CCLDFLAGS} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -o suid_exec suid_exec.o ${mam_libast} ${mam_libnsl} ${mam_libast}
+done suid_exec generated
+make shell
+prev libshell.a archive
+done shell virtual
+prev libshell.a archive
+make ${INSTALLROOT}/bin
+exec - if silent test ! -d ${INSTALLROOT}/bin
+exec - then mkdir -p ${INSTALLROOT}/bin
+exec - fi
+done ${INSTALLROOT}/bin generated
+make ${INSTALLROOT}/bin/ksh
+prev ${INSTALLROOT}/bin
+prev ksh
+exec - test '' = 'ksh' || ${STDCMP} 2>/dev/null -s ksh ${INSTALLROOT}/bin/ksh || { ${STDMV} ${INSTALLROOT}/bin/ksh ${INSTALLROOT}/bin/ksh.old 2>/dev/null || true; ${STDCP} ksh ${INSTALLROOT}/bin/ksh ;}
+done ${INSTALLROOT}/bin/ksh generated
+make ${INSTALLROOT}/man/man1
+exec - if silent test ! -d ${INSTALLROOT}/man/man1
+exec - then mkdir -p ${INSTALLROOT}/man/man1
+exec - fi
+done ${INSTALLROOT}/man/man1 generated
+make ${INSTALLROOT}/man/man1/sh.1
+prev ${INSTALLROOT}/man/man1
+make sh.1
+done sh.1
+exec - test '' = 'sh.1' || ${STDCMP} 2>/dev/null -s sh.1 ${INSTALLROOT}/man/man1/sh.1 || { ${STDMV} ${INSTALLROOT}/man/man1/sh.1 ${INSTALLROOT}/man/man1/sh.1.old 2>/dev/null || true; ${STDCP} sh.1 ${INSTALLROOT}/man/man1/sh.1 ;}
+done ${INSTALLROOT}/man/man1/sh.1 generated
+make ${INSTALLROOT}/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib
+exec - then mkdir -p ${INSTALLROOT}/lib
+exec - fi
+done ${INSTALLROOT}/lib generated
+make ${INSTALLROOT}/lib/libshell.a archive
+prev ${INSTALLROOT}/lib
+prev libshell.a archive
+exec - test '' = 'libshell.a' || ${STDCMP} 2>/dev/null -s libshell.a ${INSTALLROOT}/lib/libshell.a || { ${STDMV} ${INSTALLROOT}/lib/libshell.a ${INSTALLROOT}/lib/libshell.a.old 2>/dev/null || true; ${STDCP} libshell.a ${INSTALLROOT}/lib/libshell.a ;}
+exec - (ranlib ${INSTALLROOT}/lib/libshell.a) >/dev/null 2>&1 || true
+done ${INSTALLROOT}/lib/libshell.a generated
+make ${INSTALLROOT}/man/man3
+exec - if silent test ! -d ${INSTALLROOT}/man/man3
+exec - then mkdir -p ${INSTALLROOT}/man/man3
+exec - fi
+done ${INSTALLROOT}/man/man3 generated
+make ${INSTALLROOT}/man/man3/shell.3
+prev ${INSTALLROOT}/man/man3
+make shell.3
+done shell.3
+exec - test '' = 'shell.3' || ${STDCMP} 2>/dev/null -s shell.3 ${INSTALLROOT}/man/man3/shell.3 || { ${STDMV} ${INSTALLROOT}/man/man3/shell.3 ${INSTALLROOT}/man/man3/shell.3.old 2>/dev/null || true; ${STDCP} shell.3 ${INSTALLROOT}/man/man3/shell.3 ;}
+done ${INSTALLROOT}/man/man3/shell.3 generated
+make ${INSTALLROOT}/man/man3/nval.3
+make nval.3
+done nval.3
+exec - test '' = 'nval.3' || ${STDCMP} 2>/dev/null -s nval.3 ${INSTALLROOT}/man/man3/nval.3 || { ${STDMV} ${INSTALLROOT}/man/man3/nval.3 ${INSTALLROOT}/man/man3/nval.3.old 2>/dev/null || true; ${STDCP} nval.3 ${INSTALLROOT}/man/man3/nval.3 ;}
+done ${INSTALLROOT}/man/man3/nval.3 generated
+make ${INSTALLROOT}/lib/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib/lib
+exec - then mkdir -p ${INSTALLROOT}/lib/lib
+exec - fi
+done ${INSTALLROOT}/lib/lib generated
+make ${INSTALLROOT}/lib/lib/shell
+prev ${INSTALLROOT}/lib/lib
+prev shell.req
+exec - test '' = 'shell.req' || ${STDCMP} 2>/dev/null -s shell.req ${INSTALLROOT}/lib/lib/shell || { ${STDMV} ${INSTALLROOT}/lib/lib/shell ${INSTALLROOT}/lib/lib/shell.old 2>/dev/null || true; ${STDCP} shell.req ${INSTALLROOT}/lib/lib/shell ;}
+done ${INSTALLROOT}/lib/lib/shell generated
+make ${PACKAGE_ast_INCLUDE}
+exec - if silent test ! -d ${PACKAGE_ast_INCLUDE}
+exec - then mkdir -p ${PACKAGE_ast_INCLUDE}
+exec - fi
+done ${PACKAGE_ast_INCLUDE} generated
+make ${PACKAGE_ast_INCLUDE}/nval.h
+prev ${PACKAGE_ast_INCLUDE}
+prev include/nval.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1982,author=dgk' include/nval.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${PACKAGE_ast_INCLUDE}/nval.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${PACKAGE_ast_INCLUDE}/nval.h
+exec - fi
+done ${PACKAGE_ast_INCLUDE}/nval.h generated
+make ${PACKAGE_ast_INCLUDE}/shell.h
+prev include/shell.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1982,author=dgk' include/shell.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${PACKAGE_ast_INCLUDE}/shell.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${PACKAGE_ast_INCLUDE}/shell.h
+exec - fi
+done ${PACKAGE_ast_INCLUDE}/shell.h generated
+make ${PACKAGE_ast_INCLUDE}/history.h
+prev include/history.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1982,author=dgk' include/history.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${PACKAGE_ast_INCLUDE}/history.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${PACKAGE_ast_INCLUDE}/history.h
+exec - fi
+done ${PACKAGE_ast_INCLUDE}/history.h generated
+make ${INSTALLROOT}/bin/suid_exec
+prev suid_exec
+exec - test '' = 'suid_exec' || ${STDCMP} 2>/dev/null -s suid_exec ${INSTALLROOT}/bin/suid_exec || { ${STDMV} ${INSTALLROOT}/bin/suid_exec ${INSTALLROOT}/bin/suid_exec.old 2>/dev/null || true; ${STDCP} suid_exec ${INSTALLROOT}/bin/suid_exec ;}
+done ${INSTALLROOT}/bin/suid_exec generated
+make ${INSTALLROOT}/bin/shcomp
+prev shcomp
+exec - test '' = 'shcomp' || ${STDCMP} 2>/dev/null -s shcomp ${INSTALLROOT}/bin/shcomp || { ${STDMV} ${INSTALLROOT}/bin/shcomp ${INSTALLROOT}/bin/shcomp.old 2>/dev/null || true; ${STDCP} shcomp ${INSTALLROOT}/bin/shcomp ;}
+done ${INSTALLROOT}/bin/shcomp generated
+make ${INSTALLROOT}/fun
+exec - if silent test ! -d ${INSTALLROOT}/fun
+exec - then mkdir -p ${INSTALLROOT}/fun
+exec - fi
+done ${INSTALLROOT}/fun generated
+make ${INSTALLROOT}/fun/dirs
+prev ${INSTALLROOT}/fun
+make fun/dirs
+done fun/dirs
+setv mode -Dmode="+x"
+exec - test '' = 'fun/dirs' || ${STDCMP} 2>/dev/null -s fun/dirs ${INSTALLROOT}/fun/dirs || { ${STDMV} ${INSTALLROOT}/fun/dirs ${INSTALLROOT}/fun/dirs.old 2>/dev/null || true; ${STDCP} fun/dirs ${INSTALLROOT}/fun/dirs && chmod ugo+x ${INSTALLROOT}/fun/dirs ;}
+done ${INSTALLROOT}/fun/dirs generated
+make ${INSTALLROOT}/fun/popd
+make fun/popd
+done fun/popd
+setv mode -Dmode="+x"
+exec - test '' = 'fun/popd' || ${STDCMP} 2>/dev/null -s fun/popd ${INSTALLROOT}/fun/popd || { ${STDMV} ${INSTALLROOT}/fun/popd ${INSTALLROOT}/fun/popd.old 2>/dev/null || true; ${STDCP} fun/popd ${INSTALLROOT}/fun/popd && chmod ugo+x ${INSTALLROOT}/fun/popd ;}
+done ${INSTALLROOT}/fun/popd generated
+make ${INSTALLROOT}/fun/pushd
+make fun/pushd
+done fun/pushd
+setv mode -Dmode="+x"
+exec - test '' = 'fun/pushd' || ${STDCMP} 2>/dev/null -s fun/pushd ${INSTALLROOT}/fun/pushd || { ${STDMV} ${INSTALLROOT}/fun/pushd ${INSTALLROOT}/fun/pushd.old 2>/dev/null || true; ${STDCP} fun/pushd ${INSTALLROOT}/fun/pushd && chmod ugo+x ${INSTALLROOT}/fun/pushd ;}
+done ${INSTALLROOT}/fun/pushd generated
+done install virtual
+make test
+make test.ksh
+prev ${INSTALLROOT}/bin/ksh
+prev ksh
+make tests/shtests
+done tests/shtests
+exec - silent cmp 2>/dev/null -s ${INSTALLROOT}/bin/ksh ksh 2>/dev/null ||
+exec - echo "make install to run the tests on the latest ksh" >&2
+exec - cd ${PACKAGEROOT}/src/cmd/ksh93/tests
+exec - SHELL=${INSTALLROOT}/bin/ksh ${INSTALLROOT}/bin/ksh shtests
+done test.ksh virtual
+done test dontcare virtual
diff --git a/src/cmd/ksh93/OBSOLETE b/src/cmd/ksh93/OBSOLETE
new file mode 100644
index 0000000..c29cb8b
--- /dev/null
+++ b/src/cmd/ksh93/OBSOLETE
@@ -0,0 +1,152 @@
+.sp 3
+.tl ''Ksh Features That Are Obsolete in Ksh93''
+.sp 2
+.AL 1
+.LI
+Using a pair of grave accents \^\fB\(ga\fR ... \fB\(ga\fR\^
+for command substition. Use \fB$(\fR ... \fB)\fR instead.
+.LI
+.B FCEDIT
+is an obsolete name for
+the default editor name for the
+.B hist
+command.
+.B FCEDIT
+is not used when
+.B HISTEDIT
+is set. Use
+.B HISTEDIT
+instead.
+.LI
+The newtest (\fB[[\fR ... \fB]]\fR) operator
+\fB\-a\fP \fIfile\fP
+is obsolete. Use
+\fB\-e\fP instead.
+.LI
+The newtest (\fB[[\fR ... \fB]]\fR) operator
+.BR = ,
+as used in
+\fIstring\fP \fB=\fP \fIpattern\fP
+is obsolete. Use
+\fB==\fP instead.
+.LI
+The following obsolete arithmetic comparisons are also permitted:
+.in +5
+.VL 20
+.LI "\fIexp1\fP \fB\-eq\fP \fIexp2\fP"
+True, if
+.I exp1
+is equal to
+.IR exp2 .
+.LI "\fIexp1\fP \fB\-ne\fP \fIexp2\fP"
+True, if
+.I exp1
+is not equal to
+.IR exp2 .
+.LI "\fIexp1\fP \fB\-lt\fP \fIexp2\fP"
+True, if
+.I exp1
+is less than
+.IR exp2 .
+.LI "\fIexp1\fP \fB\-gt\fP \fIexp2\fP"
+True, if
+.I exp1
+is greater than
+.IR exp2 .
+.LI "\fIexp1\fP \fB\-le\fP \fIexp2\fP"
+True, if
+.I exp1
+is less than or equal to
+.IR exp2 .
+.LI "\fIexp1\fP \fB\-ge\fP \fIexp2\fP"
+True, if
+.I exp1
+is greater than or equal to
+.IR exp2 .
+.LE \" End .VL
+.in -5
+.LI
+Using test -t or [ -t ] without specifying the file unit number.
+.LI
+The
+.B \-k
+option to the \fBset\fR builtin is obsolete. It causes
+.I all\^
+variable assignment arguments are placed in the environment,
+even if they occur after the command name.
+The following
+first prints
+.B "a=b c"
+and then
+.BR c :
+There is no alternative.
+.LI
+The obsolete
+.B \-xf
+option of the
+.B typeset
+command allows a function to be exported
+to scripts that are executed without a separate
+invocation of the shell.
+Functions that need to be defined across separate
+invocations of the shell should
+be placed in a directory and the
+.B FPATH
+variable should contains the name of this directory.
+They may also
+be specified in the
+.B ENV
+file with the
+.B \-xf
+option of
+.BR typeset .
+.LI
+The shell environment variable
+.B FCEDIT
+is obsolete. Use
+.B HISTEDIT
+instead.
+.LI
+In the
+.B \-s
+option
+(to \fBfc\fR or \fBhist\fR command???)
+(
+and in obsolete versions, the editor name
+.B \-
+)
+is used to skip the editing phase and
+to re-execute the command.
+.LI
+The
+.B \-t
+option to \fBalias\fR builtin is is obsolete. It
+is used to set and list tracked aliases.
+There is no replacement.
+.LI
+The shell command line option
+.B \-t
+is obsolete. This option cause the shell to exit after reading
+and executing one command. The is no replacement (although ending
+\&"command" with the exit builtin should have the same effect).
+.LI
+As an obsolete feature of the "set" builtin,
+if the first
+.I arg\^
+is
+.B \-
+then the
+.B \-x
+and
+.B \-v
+options are turned off and the next
+.I arg
+is treated as the first argument.
+Using
+.B \+
+rather than
+.B \-
+causes these options to be turned off.
+These options can also be used upon invocation of the shell.
+.LE
+
diff --git a/src/cmd/ksh93/PROMO.mm b/src/cmd/ksh93/PROMO.mm
new file mode 100644
index 0000000..def4552
--- /dev/null
+++ b/src/cmd/ksh93/PROMO.mm
@@ -0,0 +1,141 @@
+.H 1 ksh93
+KSH-93 is the most recent version of the KornShell Language
+described in
+"The KornShell Command and Programming Language,"
+by Morris Bolsky and David Korn of AT&T Bell Laboratories, ISBN 0-13-182700-6.
+The KornShell is a shell programming language,
+which is upward compatible with "sh" (the Bourne Shell),
+and is intended to conform to the IEEE P1003.2/ISO 9945.2 Shell and
+Utilities standard.
+KSH-93 provides an enhanced programming environment in
+addition to the major command-entry features of the BSD
+shell "csh". With KSH-93, medium-sized programming tasks can be
+performed at shell-level without a significant loss in performance.
+In addition, "sh" scripts can be run on KSH-93 without modification.
+.P
+The code should conform to the IEEE POSIX 1003.1 standard and to the
+proposed ANSI-C standard so that it should be portable to all
+such systems. Like the previous version, KSH-88,
+it is designed to accept eight bit character sets
+transparently, thereby making it internationally compatible.
+It can support multi-byte characters sets with some characteristics
+of the character set given at run time.
+.P
+KSH-93 provides the following features, many of which were also inherent
+in KSH-88:
+.BL
+.LI
+Enhanced Command Re-entry Capability: The KSH-93 history
+function records commands entered at any shell level and stores
+them, up to a user-specified limit, even after you log off.
+This allows you to re-enter long commands with a few keystrokes
+- even those commands you entered yesterday.
+The history file allows for eight bit characters in
+commands and supports essentially unlimited size histories.
+.LI
+In-line Editing: In "sh", the only way to fix mistyped
+commands is to backspace or retype the line. KSH-93 allows you
+to edit a command line using a choice of EMACS-TC or "vi"
+functions.
+You can use the in-line editors to complete filenames as
+you type them.
+You may also use this editing feature when entering
+command lines from your history file.
+A user can capture keystrokes and rebind keys to customize the
+editing interface.
+.LI
+Extended I/O Capabilities: KSH-93 provides several I/O
+capabilities not available in "sh", including the ability to:
+.BL
+.LI
+specify a file descriptor for input and output
+.LI
+start up and run co-processes
+.LI
+produce a prompt at the terminal before a read
+.LI
+easily format and interpret responses to a menu
+.LI
+echo lines exactly as output without escape processing
+.LI
+format output using printf formats.
+.LI
+read and echo lines ending in "\e".
+.LE
+.LI
+Improved performance: KSH-93 executes many scripts faster
+than the System V Bourne shell. A major reason for this is
+that many of the standard utilities are built-in.
+To reduce the time to initiate a command, KSH-93 allows
+commands to be added as built-ins at run time
+on systems that support dynamic loading such as System V Release 4.
+.LI
+Arithmetic: KSH-93 allows you to do integer arithmetic in any
+base from two to sixty-four. You can also do double
+precision floating point arithmetic.
+Almost the complete set of C language operators are available
+with the same syntax and precedence.
+Arithmetic expressions can be used to as an argument expansion
+or as a separate command.
+In addition there is an arithmetic for command that works
+like the for statement in C.
+.LI
+Arrays: KSH-93 supports both indexed and associative arrays.
+The subscript for an indexed array is an arithmetic expression,
+whereas, the subscript for an associative array is a string.
+.LI
+Shell Functions and Aliases: Two mechanisms - functions and
+aliases - can be used to assign a user-selected identifier to
+an existing command or shell script.
+Functions allow local variables and provide scoping
+for exception handling.
+Functions can be searched for and loaded on first reference the
+way scripts are.
+.LI
+Substring Capabilities: KSH-93 allows you to create a
+substring of any given string either by specifying the starting
+offset and length, or by stripping off leading
+or trailing substrings during parameter substitution.
+You can also specify attributes, such as upper and lower case,
+field width, and justification to shell variables.
+.LI
+More pattern matching capabilities: KSH-93 allows you to specify
+extended regular expressions for file and string matches.
+.LI
+KSH-93 uses a hierarchal name space for variables.
+Compound variables can be defined and variables can
+be passed by reference. In addition, each variable
+can have one or more disciplines associated with
+it to intercept assignments and references.
+.LI
+Improved debugging: KSH-93 can generate line numbers on execution
+traces. Also, I/O redirections are now traced.
+There is a DEBUG trap that gets evaluated before each command
+so that errors can be localized.
+.LI
+Job Control: On systems that support job control, including
+System V Release 4, KSH-93
+provides a job-control mechanism almost identical to that of
+the BSD "csh", version 4.1.
+This feature allows you
+to stop and restart programs, and to move programs between the
+foreground and the background.
+.LI
+Added security:
+KSH-93 can execute scripts which do not have read permission
+and scripts which have the setuid and/or setgid set when
+invoked by name, rather than as an argument to the shell.
+It is possible to log or control the execution of setuid and/or
+setgid scripts.
+The noclobber option prevents you from accidentally erasing
+a file by redirecting to an existing file.
+.LI
+KSH-93 can be extended by adding built-in commands at run time.
+In addition, KSH-93 can be used as a library that can
+be embedded into an application to allow scripting.
+.LE
+Documentation for KSH-93 consists of an "Introduction to KSH-93",
+"Compatibility with the Bourne Shell" and a manual page and a
+README file. In addition, the "New KornShell Command and Programming
+Language," book is available from Prentice Hall.
+
diff --git a/src/cmd/ksh93/README b/src/cmd/ksh93/README
new file mode 100644
index 0000000..1feeec8
--- /dev/null
+++ b/src/cmd/ksh93/README
@@ -0,0 +1,232 @@
+This directory, and its subdirectories contain the source code
+for ksh-93; the language described in the second addition of
+the book, "The KornShell Command and Programming Language," by
+Morris Bolsky and David Korn which is published by Prentice Hall.
+ksh-93 has been compiled and run on several machines with several
+operating systems. The end of this file contains a partial list of
+operating systems and machines that ksh-93 has been known to run on.
+
+The layout of files for ksh-93 has changed somewhat since ksh-88,
+the last major release. Most of the source code for ksh remains in
+the sh directory. However, the shell editing and history routines
+are in the edit sub-directory. The code for shell built-ins is
+in the bltins directory. The data directory contains read-only
+data tables and messages that are used by the shell. The include
+files remain in the include directory and the shlib directory
+is gone. The features directory replaces the older install
+directory. The method for generating systems specific feature
+information has changed substantially.
+
+The Makefile file contains several compilation options that can be set
+before compiling ksh. Options are of the form SHOPT_option and become
+#define inside the code. These options are set to their recommended
+value and some of these may disappear as options in future releases.
+A value of 0, or no value represents off, 1 represents on.
+Note that == is needed, not =, because these are nmake state variables
+and changing their value will cause all modules that could be affected
+by this change to be recompiled.
+The options have the following defaults and meanings:
+ ACCT off Shell accounting.
+ ACCTFILE off Enable per user accounting info.
+ AUDIT off For auditing specific users
+ AUDITFILE "/etc/ksh_audit"
+ APPEND on Allows var+=val string and array append.
+ BASH off Bash compatibility mode. It is not fully implemented
+ and is experimental.
+ BRACEPAT on C-shell type abc{d,e}f style file generation
+ CMDLIB_BLTIN off Makes all commands in libcmd.a builtins. The
+ SH_CMDLIB_DIR nmake state variable can be used to
+ specify a directory.
+ CMDLIB_DIR off Sets CMDLIB_BLTIN=1 and provides a default value
+ of "/opt/ast/bin" for SH_CMDLIB_DIR.
+ COMPOUND_ARRAY
+ on Allows all components of compound variables except the
+ first to be any string by enclosing in [...]. It also
+ allows components other than the last to be arrays.
+ This is experimental and only partially complete.
+ CRNL off <cr><nl> treated as <nl> in shell grammar.
+ DYNAMIC on Dynamic loading of builtins. (Requires dlopen() interface.)
+ ECHOPRINT off Make echo equivalent to print.
+ ESH on Compile with emacs command line editing. The original
+ emacs line editor code was provided by Mike Veach at IH.
+ FILESCAN on Experimental option that allows fast reading of files
+ using while < file;do ...; done and allowing fields in
+ each line to be accessed as positional parameters.
+ FS_3D off For use with 3-D file system. Enabled automatically for
+ sytems with dynamic linking.
+ KIA off Allow generation of shell cross reference database with -I.
+ MULTIBYTE on Multibyte character handling. Requires mblen() and
+ mbctowc().
+ NAMESPACE on Allows namespaces. This is experimental, incomplete
+ and undocumented.
+ OLDTERMIO off Use either termios or termio at runtime.
+ OO on Experimental object oriented extension. This option
+ should disappear soon.
+ OPTIMIZE on Optimize loop invariants for with for and while loops.
+ P_SUID off If set, all real uids, greater than or equal to this
+ value will require the -p flag to run suid/sgid scripts.
+ PFSH off Compile with support for profile shell.
+ RAWONLY off Turn on if the vi line mode doesn't work right unless
+ you do a set -o viraw.
+ SEVENBIT off Strip the eigth bit from characters.
+ SPAWN off Use spawn as combined fork/exec. May improve speed on
+ some systems.
+ STATS on Add .sh.stats compound variable.
+ SUID_EXEC on Execute /etc/suid_exec for setuid, setgid script.
+ TIMEOUT off Set this to the number of seconds for timing out and
+ exiting the shell when you don't enter a command. If
+ non-zero, TMOUT can not be set larger than this value.
+ TYPEDEF on Enable typeset type definitions.
+ VSH on Compile with vi command line editing. The original vi
+ line editor code was provided by Pat Sullivan at CB.
+
+The following compile options are set automatically by the feature testing:
+ DEVFD Set when /dev/fd is a directory that names open files.
+ SHELLMAGIC
+ Set on systems that recognize script beginning with #! specially.
+ VPIX Set on systems the have /usr/bin/vpix program for running MS-DOS.
+
+
+In most instances, you will generate ksh from a higher level directory
+which also generates libcmd and libast libraries on which ksh depends.
+However, it is possible to generate ksh, with by running make -f ksh.mk
+in this directory. The ksh.mk file was generated from the nmake Makefile.
+If you do not have make or nmake, but do have a Version 7 UNIX compatible
+shell, then you can run the script mamexec < Mamfile to build ksh.
+If you have nmake, version 2.3 or later, you can use it without the -f ksh.mk.
+In either case, ksh relies on libraries libast and libcmd which must be
+built first. The binary for ksh becomes the file named ./ksh which can
+be copied to where ever you install it.
+
+If you use old make or the Mamfile, and you system has dynamic shared
+libraries, then you should define the variables mam_cc_static and
+mam_cc_dynanamic as the compiler options that request static linking
+and dynamic linking respectively. This will decrease the number of
+shared libraries that ksh need and cut startup time substantially.
+
+The makefile should also generate shcomp, a program that will precompile
+a script. ksh93 is able to recognize files in this format and process
+them as scripts. You can use shcomp to send out scripts when you
+don't want to give away the original script source.
+
+It is advisable that you put the line PWD=$HOME;export PWD into the
+/etc/profile file to reduce initialization time for ksh.
+
+To be able to run setuid/setgid shell scripts, or scripts without read
+permission, the SUID_EXEC compile option must be on, and ksh must be installed
+in the /bin directory, the /usr/bin directory, the /usr/lbin directory,
+or the /usr/local/bin directory and the name must end in sh. The program
+suid_exec must be installed in the /etc directory, must be owned by root,
+and must be a suid program. If you must install ksh in some other directory
+and want to be able to run setuid/setgid and execute only scripts, then
+you will have to change the source code file sh/suid_exec.c explicitly.
+If you do not have ksh in one of these secure locations, /bin/sh will
+be invoked with the -p options and will fail when you execute a setuid/setgid
+and/or execute only script. Note, that ksh does not read the .profile
+or $ENV file when it the real and effective user/group id's are not
+equal.
+
+The tests sub-directory contains a number of regression tests for ksh.
+To run all these tests with the shell you just built, go to the tests
+directory and run the command
+ SHELL=$dir/ksh $dir/ksh shtests
+where dir is the directory of the ksh you want to test.
+
+The file PROMO.mm is an advertisement that extolls the virtues of ksh.
+The file sh.1 contains the troff (man) description of this Shell.
+The file nval.3 contains the troff (man) description of the name-value
+pair library that is needed for writing built-ins that need to
+access shell variables.
+
+The file sh.memo contains a draft troff (mm) memo describing ksh. The
+file RELEASE88 contains the changes made for ksh88. The file RELEASE93
+contains the changes made in this release since ksh-88. The file
+RELEASE contains bug fixes made in this release since ksh-88. The file
+COMPATIBILITY contains a list of incompatibilities with ksh-88. The
+file bltins.mm is a draft troff (mm) memo describing how to write
+built-in commands that can be loaded at run time.
+
+Most of the work for internationalization has been done with ksh93.
+The file ksh.msg is a generated file that contains error messages
+that need to be translated. In addition, the function translate()
+in sh/init.c has to be completed to interface with the dictionary
+lookup. The translate function takes two argument, the string
+that is to be translated and a type which is
+ 0 when a library string needs translation.
+ 1 when one of the error messages in ksh.msg needs translation.
+ 2 when a string in a script needs translation. You use a $ in front
+ of a double quoted string in a script to indicate that it
+ needs translation. The -D option for ksh builds the dictionary.
+The translate routine needs to return the translated message.
+For dictionaries that need to use a numeric key, it should be
+possible to use the strhash() function to generate numbers to
+go along with each of the messages and to use this number both
+when generating the dictionary and when converting strings.
+If you encounter error messages of type 1 that are not be translated via
+this translate() function send mail to the address below.
+
+Please report any problems or suggestions to:
+
+dgk@research.att.com
+
+
+ksh93 has been compiled and alpha tested on the following. An asterisk
+signifies that ksh has been installed as /bin/sh on this machine.
+
+* Sun OS 4.1.[123] on sparc.
+ Sun OS 4.1.1 on sun.
+ Solaris 2.[1-9] on sparc.
+ Solaris 2.[4-8] on X86.
+ HP/UX 8 on HP-9000/730.
+ HP/UX 9 on HP-9000/730.
+ HP/UX 10 on HP-9000/857.
+ HP/UX 11 on pa-risc.
+ System V Release 3 on Counterpoint C19
+ System V Release 4 on AT&T Intel 486.
+ System V Release 4 on NCR 4850 Intel 486.
+ IRIX Release 4.0.? System V on SGI-MIPS.
+ IRIX Release 5.1 System V on SGI-MIPS.
+ IRIX Release 6.[1-5] System V on SGI-MIPS.
+ System V Release 3.2 on 3B2.
+ UTS 5.2.6 on Amdahl 3090,5990,580.
+ System V Release 3.2 on i386.
+ SMP_DC.OSx olivetti dcosx MIServer-S 2/128.
+ SMP_DC.OSx Pyramid dcosx MIServer-S 2/160 r3000.
+ 4.3BSD on Vax 8650.
+ AIX release 2 on RS6000.
+ AIX 3.2 on RS6000.
+ Linux 1.X on Intel
+ Linux 2.X on Intel
+ Linux 2.X on Alpha
+ Linux 2.X on Alpha
+ Linux 2.X on OS/390
+ Linux 2.X on sparc
+ Linux 2.4 on intel itanium 64
+ Linux Slackware on sparc64
+* Linux ARM on i-PAQ
+ OSF1 on DEC alpha.
+ OSF4 on DEC alpha.
+ UMIPS 4.52 on mips.
+ BSD-i [2-4] on X86.
+ OpenBSD on X86
+ NetBSD on X86
+ FreeBSD on X86
+ NeXT on Intel X86.
+ NeXT on HP.
+* Windows NT using UWIN on X86
+* Windows NT using UWIN on alpha
+ Windows NT using Cygwin on X86
+ Windows NT with NutCracker libraries.
+ Windows NT with Portage libraries.
+ Windows 3.1 using custom C library.
+ OpenEdition on MVS
+ Darwin OS X on PPC
+ MVS on OS 390
+ SCO Openserver 3.2 on X86
+ Unixware 7 on X86
+
+Good luck!!
+
+David Korn
+dgk@research.att.com
+
diff --git a/src/cmd/ksh93/RELEASE b/src/cmd/ksh93/RELEASE
new file mode 100644
index 0000000..2f95505
--- /dev/null
+++ b/src/cmd/ksh93/RELEASE
@@ -0,0 +1,2888 @@
+12-02-29 --- Release ksh93u+ ---
+12-02-29 A bug which could lead to a core dump when more that four shared
+ libraries were added with the builtin command has been fixed.
+12-02-29 Fixed a few bugs which caused SIGCHLD to be blocked preventing
+ background jobs from being reaped until a foreground job was run.
+12-02-27 A bug in which sh -c for a simple command caused a fork() has been
+ fixed.
+12-02-27 A timing bug on systems such as AIX that doesn't support vfork()
+ that could cause the exist status to get lost has been fixed.
+12-02-22 A private file descriptor that was not close-on-exec for a command
+ substitution and has been fixed.
+12-02-14 A bug in which ^Z did not stop a pipeline when the last component
+ was a shell built-in has been fixed.
+12-02-14 getconf("PATH") used to initialize ed(1) path.
+12-02-13 +In earlier version read from standard input would fail when called
+ from the KEYBD trap. Now read options -N, -n, and -t should work
+ when called from a KEYBD trap.
+12-02-13 If FCEDIT is not set and fc is invoked without the -e option,
+ ed will be invoked if found instead of /bin/ed.
+12-02-10 Another bug in the saving and restoring of IFS in a subshell
+ that caused a core dump has been fixed.
+12-02-08 A bug in which .sh.fun disciplines could be cleared after a
+ function completes has been fixed.
+12-02-08 A bug in job control in which the foregroup process group was not
+ set correctly after restarting a stopped pipeline has been fixed.
+12-02-07 A bug in which numbers with leading zeros could be treated as
+ octal constants outside of ((...)) has been fixed.
+12-02-06 A bug in arithmetic with compound variables containing multiple
+ array elements has been fixed.
+12-02-02 A bug in the ulimit option table was fixed.
+12-01-26 A bug in which a set command that did not change monitor could
+ effect the behavior of the monitor when monitor mode is on is fixed.
+12-01-21 +You can now test whether the shell implements a math function using
+ typeset -f .sh.math.name, where name is the name of the function.
+12-01-21 A bug in which typeset -L and typeset -R did not handle multibyte
+ characters correctly has been fixed.
+12-01-20 A bug that could cause the shell to hang waiting for an incorrect
+ job pid has been fixed.
+12-01-19 A memory leak which occured for a nested command subtiution has been
+ fixed.
+12-01-17 A bug in which typeset -u PS1 could enable the uppercase attribute
+ for some other variables, for exampe, HISTFILE has been fixed.
+12-01-16 A bug in which .sh.match was not correct after a substring match when
+ the replacement string contained a substring match has been fixed.
+12-01-12 +Files that are sourced from profile files are now read and executed
+ one command at a time so that alias definitions take effect as they
+ do for profile files.
+12-01-12 A bug in which whence -p would find a function if one existed and
+ there was no command of that name on PATH.
+12-01-11 Change b_* prototype (int, char**, void*) => (int, char**, Shbltin_t*).
+12-01-05 A bug in which read was not terminating for a signal that had a trap
+ set has been fixed.
+12-01-01 A timing problem with >; has been fixed.
+12-01-01 A macro expansion memory leak has been fixed.
+11-12-26 A bug in array assignments of the form arr=( $arr[i] ...) in which
+ arr was not unset before the assignment has been fixed.
+11-12-20 A number of code changes were made based on the results of errors
+ indicated by static code analysis.
+11-12-13 In vi edit mode a lteral <TAB> can now be entered by preceding it
+ with a backshash.
+11-12-13 When tab is entered for completion after a ' or ", the ' and "
+ characters are no longer deleted.
+11-12-07 A bug in which a program in the current direcotry with a . in the
+ name could fail to execute when both PATH and FPATH end with :. has
+ been fixed.
+11-12-07 I fixed a bug in which a variable expansion in a large here-document
+ could be expanded to a null string.
+11-12-06 An optimization to read was added in the case the the read command
+ was redirected from a file.
+11-12-06 Changes were made to make the line limit for read unlimited by
+ default.
+11-12-05 A bug in which unsetting an array variable did not completely clear
+ the variable in some cases has been fixed.
+11-12-02 +The printf alternative character # when applied to the %q format will
+ quote argument in a form suitable for a field in a .csv format file.
+11-12-02 +A -S option was added to read to be able to read .csv format files.
+11-11-28 A bug in which redirection of standard error in a function called from
+ command substitution caused standard error to be lost has ben fixed.
+11-11-21 [[ (-n foo) ]] no longer requires a space before (.
+11-11-11 The readonly attribute for a variable now applies to compound
+ assignments to that variable.
+11-11-07 Changes were made to reduce the stack size to allow deeper function
+ recursion.
+11-10-10 +Added alternate flag to printf %H for encoding of URI's.
+11-10-10 A bug which could lead to a core dump when the shell was invoked
+ with more than twenty five open files has been fixed.
+11-10-06 A bug in the scoping of name references in functions called by other
+ functions has been fixed.
+11-10-05 A bug in which wait on a pid may return the exit status of an
+ earlier background job with that pid instead has been fixed.
+11-09-22 A bug in which a read timed out with TMOUT did not always restore
+ the terminal state has been fixed.
+11-09-21 An optimization that allowed the last command in a script to use
+ the same process id as the script has been eliminated.
+11-09-21 Added letoctal option that enables the let command to recognize
+ octal constants starting with 0.
+11-09-20 A bug in which ${var.} could cause a core dump has been fixed.
+11-09-20 A bug with SHOPT_EDPREDICT when neither vi or emacs was enabled for
+ lines beginning with # when in a multibyte locale has been fixed.
+11-09-20 A bug in emacs edit mode with SHOPT_EDPREDICT that would cause
+ history searches matching comments lines to generate predictions
+ has been fixed. Only user typed comment lines generate predictions.
+11-09-20 A bug in emacs edit mode with a search that matches a comment line
+ that could cause a core dump has been fixed.
+11-09-16 A bug in which a command name ending in .. could cause the shell to
+ abort has been fixed.
+11-09-16 The characters ! + - % and @ in file names are no longer escaped with
+ file name completion.
+11-09-13 The let command no longer treats numbers starting with 0 as octal
+ constants.
+11-09-08 A bug in which printf "%R" could cause a core dump for invalid shell
+ patterns has been fixed.
+11-08-09 With set -u, ${var#pattern} reported that var was unset for special
+ variables.
+11-08-03 A bug in which the shell did not preserve the exit status for a
+ coprocess has been fixed.
+11-08-02 A bug in the saving and restoring of IFS in command substitution that
+ caused a core dump has been fixed.
+11-07-21 Modified the 10-08-27 bug fix so that background jobs started in for
+ and while loops created interactively generate completion messages.
+11-07-20 I fixed a bug in here documents in which multi-byte characters that
+ crossed buffer boundaries were not processed correctly.
+11-06-22 The shell compiler now supports process substitution.
+11-06-22 +Added code to support process substitution on systems that do
+ not supply the /dev/fd directory.
+11-06-21 Fixed extraneous jobs Done messages when builtin is at the end of a
+ pipeline.
+11-06-20 Fixed two regression tests.
+11-06-20 Fixed a bug introduced on last update.
+11-06-14 A bug with pipefail in which the shell would wait for background
+ jobs to complete has been fixed.
+11-06-09 A bug which caused the options.sh regression test to fail on OS390
+ Linux has been fixed. The bug could also have affected other systems.
+11-06-07 +A number of changes to support the still undocuments namespace option
+ have been added.
+11-06-06 A bug in which command substitution of eval would hang when it had
+ standard error redirected to standard output has been fixed.
+11-06-01 A bug in case statement fall through (;&) ignoring set -e was fixed.
+11-06-01 A bug in which creating a left or right justified upper or lowercase
+ variable with an empty string has been fixed.
+11-06-01 A bug in which the .paths directory wasn't read when a subshell was
+ executed before any other command has been fixed.
+11-05-31 The shell now gives an error when a type variable is assigned to
+ an array instance when the array has been declared a compound variable
+ array.
+11-05-31 A bug in which typeset -m of an array instance did not remove the
+ original instance has been fixed.
+11-05-28 A bug in which typeset -m dest=src fails when src and are passed as
+ name references was fixed.
+11-05-28 A bug in which typeset -m "c.board[1][i]=el", where el is a compound
+ variable core dumps has been fixed.
+11-05-28 Two bugs in the display of arrays of compound variables with print -v
+ have been fixed.
+11-05-27 A bug with command substitution with the shift jis locale has been
+ fixed.
+11-05-25 A bug in which unset -f foo, called within function foo could cause
+ the shell to core dump has been fixed.
+11-05-24 A bug in unsetting arrays of compound variables that could lead to
+ a core dump has been fixed.
+11-05-24 A scoping bug in with typeset -m for variables passed as references
+ has been fixed.
+11-05-09 A bug in which 'typeset +p array[$i]' in a subshell could cause an
+ exception has been fixed.
+11-05-03 Two more scoping bugs with name references and read -C were fixed.
+11-05-03 A potential race condition which occurs when here-documents are
+ processed in asynchronous blocks has been eliminated.
+11-05-02 Another scoping bug with name references defined in a function has
+ been fixed.
+11-05-02 A bug in which the shell discards saved exit status of a job if it is
+ followed by a subshell execution has been fixed.
+11-04-28 The shell now checks for numerical overflows with process ids.
+11-04-28 Another scoping bug with compound variables defined by name references
+ inside a function has been fixed.
+11-04-28 A bug which caused a core dump on 32 bit systems with the basic.sh
+ regression test has been fixed.
+11-04-27 A scope binding error for name references has been fixed.
+11-04-27 Assignment of compound variable to compound array element by name
+ is now working.
+11-04-26 I fixed a bug with SHOPT_FIXEDARRAY compilation that could cause
+ an a core dump for not fixed arrays.
+11-04-25 A bug in the references to two dimensional compound arrays has
+ been fixed.
+11-04-20 A bug in which a name reference to a multidimentional index array
+ index, nameref x=foo[3][4], did not work correctly has been fixed.
+11-04-18 Changes were added to allow fixed size arrays of variable sized
+ objects when the SHOPT_FIXEDARRAY compile option defined on 10-09-28.
+11-04-18 A bug in which name references to array elements could fail has
+ been fixed.
+11-04-15 +A compile option, SHOPT_2DMATCH, has been added which causes
+ .sh.match to be a two dimensional array after ${var//pat/str}
+ where the first dimension is the pattern number and the second is
+ the match instance.
+11-04-11 A bug in which readonly var, where var is exported could cause var
+ to be unset has been fixed.
+11-04-06 A tokenizer bug in which ${x/{3}(\d)/ } would cause in infinite
+ loop has been fixed.
+11-04-05 A bug in which ${!x.} could cause a core dump has been fixed.
+11-04-04 A bug in which cleaning out the history file could terminate before
+ keeping all the recent history events has been fixed.
+11-03-29 A bug in which ${#array[@]} was 1 rather than 0 after issuing
+ typeset array[7] has been fixed.
+11-03-29 The subscript out or range message for fixed arrays has been fixed.
+11-03-29 A bug in which suspend could cause a core dump has been fixed.
+11-03-24 For the showme option added 09-09-09, commands beginning with a ;
+ inside an arithmetic for loop, no longer produce syntax errors.
+11-03-18 A bug in _WINIX ~domain/user expansion has been fixed.
+11-03-16 A bug in the pipefail option which could cause a script to hang
+ has been fixed.
+11-03-12 The shell no longer treats ${##pattern} as a syntax error.
+11-03-11 A bug in typeset -u on systems that don't supply the towctrans()
+ function has been fixed.
+11-03-11 A bug in which a compound assignment of the form var[sub]=(...)
+ would evaluate sub for each assignment has been fixed.
+11-03-07 A bug in which reassigning a compound variable to an associative
+ array index could incorrectly increase the count of the number
+ of elements has been fixed.
+11-03-04 +The tilde expansion on windows has been modified to handle user
+ names of the form domain/user so that ~domain/user now expands
+ to the home directory of that domain user.
+11-03-03 A bug in which the width of the prompt was calculated incorectly
+ which cause the wrong line length for edit commands has been fixed.
+11-03-02 A bug in which a global variables set from within a function inside
+ a subshell can leave side effects in parent shell has been fixed.
+11-03-01 A bug in which whence -a could dump core when the first match
+ was due to : in PATH and the program was in the current directory.
+11-02-28 A bug in emacs mode with SHOPT_EDPREDICT (added on 10-05-20) which
+ disabled prediction on a line starting with # when the cursor was not
+ at the end of line has been fixed.
+11-02-28 The output format for compound variables with set has been fixed.
+11-02-25 A bug which could lead to a core dump occurred when a shell script
+ without #! is invoked by name from a parent shell that has name
+ references defined and the script creates name references of the
+ same name.
+11-02-21 The shell now fails with a syntax error when a here-document in a
+ command substition is not completed before the closing ), for
+ example, $( foobar <<! )
+ here_doc
+ !.
+11-02-18 A bug in which the value of $0 in a function defined by name()
+ was changed to name has been fixed.
+11-02-17 A bug in which the declaration typeset var[100] did not work
+ correctly has been fixed.
+11-02-15 A bug in which [[ -v sh.match ]] did not work correctly has been
+ fixed.
+
+11-02-08 --- Release ksh93u ---
+11-02-08 A bug in which opening standard output after it has been closed with
+ exec 1>&- doesn't work has been fixed.
+11-02-07 A bug on some systems for which a command subtitution could hang
+ has been fixed.
+11-01-28 A bug in file name completion for files containing both multibyte
+ characters shell special characters has been fixed.
+11-01-18 The .sh.match variable now shows elements that do not match as
+ as not set rather than an empty string.
+11-01-18 A bug with typeset -m of an array into an element of an indexed
+ array has been fixed.
+11-01-13 A bug in handling of arrays of compound variables inside ((...)) which
+ reported a syntax error been fixed.
+11-01-10 A bug in arithmetic assignment operators of the form op= for array
+ variables when the same array was referenced on the left and the
+ right hand side with different indices has been fixed.
+11-01-10 A bug in which the output of time was lost when { time...;} 2>&1
+ occurred inside command substition has been fixed.
+11-01-07 [[ -v sh.match[i] ]] was returning false when sh.match[i] was set.
+11-01-05 Added and modified warning messages with sh -n.
+11-01-02 Fixed bugs with typeset -l/-u/-M and arrays.
+10-12-28 Fixed a bug with typeset -l/-u/-M values in arithmetic expressions.
+10-12-26 Fixed a time parsing bug in sleep and localeconv() initialization.
+10-12-23 Prevented the shell from generating a core dump when it sends itself
+ a termination signal because the last command terminated with that
+ signal. This prevents a core dump to be overwritten by the shell.
+10-12-22 A bug in the expansion of ${A[@]} ${B[@]}, introduced in 10-12-01
+ when A="" B=B has been fixed.
+10-12-21 +Use MS_3D in b_vpath() for setting win32 WoW mount defaults.
+10-12-17 A bug in the expansion of ${var:i:j} which caused a core dump when
+ i > ${#var} has been fixed.
+10-12-16 +sleep now treats . as decimal point even in locales that use comma.
+10-12-16 +typeset -M mapname was added to generalize on toupper and tolowwer
+ mapping as provided with wctrans().
+10-12-10 A bug in which typeset -l displayed namespaces as well as lower case
+ variables has been fixed.
+10-12-06 A bug in which a pipeline could terminate prematurely for a pipeline
+ whose right hand side is a builtin, and whose left hand side ends in
+ a simple command that has standard output redirected has been fixed.
+10-12-06 A bug in hexfloat assignments when the right hand side is a string
+ variable starting with 0x has been fixed.
+10-12-01 A bug in the expansion of ${$1+"$@"} which causes the last positional
+ parameter to disappear when it is empty has been fixed.
+10-12-01 A number of changes were made to reduce the startup time.
+10-11-29 When wait is interrupted by a signal that is caught, it now exits
+ with a non-zero exit status.
+10-11-29 When a variable is used directly in an arithmetic expression,
+ leading zeros no longer cause the value to be treated as an
+ octal constant. This was true in previous versions for justified
+ variables.
+10-11-29 An incorrect warning message was eliminated with the -n option for
+ arithmetic expressions with associative arrays.
+10-11-29 Some changes were made to slightly reduces startup time.
+10-11-24 A bug in which a name reference is make to arr[0] when arr is not
+ an array has been fixed.
+10-11-23 If a type definition is made without a compound variable assignment it
+ produces an error message and no longer shows up as a defined type.
+10-11-22 The handling of \ inside [...] for for shell and ~(E) patterns has
+ been fixed.
+10-11-22 A patch was made to pfsh to handle an error case.
+10-11-22 +Modified types defined in namespace so that they do not clash with
+ types in other namespaces. Types can be referenced using
+ .namespace.typename.
+10-11-22 A bug which caused functions addressed as .namespace.funct to not
+ work has been fixed.
+10-11-22 A bug in which if nr was a name reference to an unset associative
+ array subscript, then ${!nr} did not output the subscript correctly
+ has been fixed.
+10-11-18 A bug in which shcomp -n was not processing double quotes correctly
+ has been fixed.
+10-11-18 Fixed a bug in which typeset -T foo; typeset -T could cause a
+ core dump.
+10-11-17 Fixed a bug in which the error message for set -u could come out
+ garbelled.
+10-11-17 Modified the parser so that typeset -a var=(...) no longer checks
+ the first index for aliases and reserved words.
+10-11-17 A bug in which a subshell command consisted of only a for or until
+ command has been fixed.
+10-11-16 Fixed a bug in which typeset -u would display namespace variables
+ as well as upper case variables.
+10-11-16 A bug which could cause a core dump when unsetting a type variable
+ when there are references to type elements has been fixed.
+10-11-15 A bug which could cause a core dump when unsetting a compound
+ array variable when there are references to array subscripts has
+ been fixed.
+10-11-15 A bug in which using typeset -m to move an indexed array instance
+ to another array could cause the array to display incorrectly has
+ been fixed.
+10-11-12 A bug in which the unset discipline function for a type is called
+ when the type is initialized has been fixed.
+10-11-12 The sequences \< and \> are now preserved after patterns containing
+ ~(E) in ${var/pattern/string} expansions.
+10-11-11 A bug in typeset -m when the variables were compound arrary instances
+ has been fixed.
+10-11-10 A bug in output of a compound variable with types containing types
+ has been fixed.
+10-11-10 Fixed ``name=value export [-p]'' to list environment.
+10-11-09 shtests resets SIGPIPE to SIG_DFL for all tests.
+10-11-09 Fixed a bug in expansion of $"..." when used in assignments.
+10-11-09 Fixed a getaddrinfo() memory leak that didn't call freeaddrinfo()
+ after an interrupt.
+10-11-08 Modified the behavior of set -u so that the shell terminates with
+ error message when when var is unset with ${!var} and ${#var}.
+10-11-02 Fix a bug in which a signal received while in a subshell could be
+ ignored.
+10-10-26 Fix a bug where terminal interrupt was ignored while in vi/emacs
+ edit search mode.
+10-10-26 Fix $'a\0b'c to expand to 'ac'.
+10-10-26 Provide user defined round() if not in <math.h>.
+10-10-26 Fix bug where $((undefined_function(1))) dumped core.
+10-10-22 Provide user defined iszero() if not in <math.h>.
+10-10-22 Fixed a bug with BGX compile option that could cause the shell to
+ hang.
+10-10-22 Fixed a bug with user define math function on systems for which
+ char is unsigned.
+10-10-21 A bug in which function autoloaded in a function leaves a file open
+ has been fixed.
+10-10-20 Modified the behavior of set -u so that the shell terminates when
+ when var is unset with ${var op string} when op is #, % or /.
+10-10-20 Fixed a bug with the AUDIT option in which the audit file was not
+ not close-on-exec.
+10-10-20 +Made a number of changes and fixes for the NAMESPACE compile option
+ which as added on 10-06-09 but some problems still remain.
+10-10-15 Fixed a bug in which arithmetic functions (added on 10-03-24) did
+ not work when the function definition was in the same compound
+ command in which the function was referenced.
+10-10-13 A bug in which creating an associative array of compound variables
+ with no members as an element of a compound variable did not work
+ has been fixed.
+10-10-08 A bug in which killing the last command in a function defined
+ with function name, terminated the calling script has been fixed.
+10-10-08 A bug which could cause a core dump if IFS is unset inside a function
+ has been fixed.
+10-10-07 +To reduce unwanted side effects, invoking typeset without the export
+ option and without an assignment now causes the variables to be unset
+ if the variable is inherited from the environment.
+10-10-06 The closing brace for ${ command } is now a token no matter what
+ character follows it.
+10-10-04 The change for $'...' expansion on 10-08-09 did not expand parameters
+ contained in the error message and this has been fixed.
+10-10-04 A bug in which a declaration of indexed array (-a_ in a type
+ definition would be displayed as a compound indexed array (-C -a)
+ has been fixed.
+10-09-30 The C99 math function ldexp has been added.
+10-09-30 A bug with two dimensional arrays with expansion of the form
+ ${ref[0..5]} where ref is a nameref to array[i] has been fixed.
+10-09-29 A bug in which an eval with redirections invoked from a dot script
+ would not restore the file has been fixed.
+10-09-29 A bug in which loading a function from FPATH could leave a file
+ descriptor open has been fixed.
+10-09-28 +A new compile option SHOPT_FIXEDARRAY has been added and is being
+ evaluation. It allows fixed sized indexed arrays be to defined
+ using "typeset array[dim1][dim2]...[dimn]". Fixed sized arrays
+ are used the same way indexed arrays are. Currently, only fixed
+ arrays of fixed objects (float, int, and justifies objects) are
+ supported.
+10-09-22 A bug which could cause an exception when a function with static
+ variables was redefined has been fixed.
+10-09-21 A bug in the processing of (command&) which created a job in the
+ parent process has been fixed.
+10-09-21 A for loop optimization bug with arithmetic expression evaluation
+ has been fixed.
+10-09-21 A bug in which a recursive function containing a pipeline could
+ lead to an exception fixed after 8 levels of recursion has been
+ fixed.
+10-09-18 A bug in which the count of elements in an array was wrong leading
+ to an exception has been fixed.
+10-09-13 A bug which occurred when both xtrace and showme options where
+ specified in which the xtrace option disabled showme has been fixed.
+10-09-13 A bug in which creating a reference to an array variable with any
+ elements could cause subsequent array elements to be treated as
+ compound variables has been fixed.
+10-09-09 A bug which caused ((c.ar[x][y])) to be treated as a syntax error
+ has been fixed.
+10-09-08 A bug in the processing of references to multidimensional arrays
+ in arithmetic expressions has been fixed.
+10-09-08 A bug in the handling of multi-dimensional arrays which caused
+ the number of elements in each dimension to be incorrect has
+ been fixed.
+10-09-07 The change for messages on 10-08-09 did not handle message in
+ assignments and this has been fixed.
+10-09-07 A bug in the indentation of compound variables in arrays when
+ output with print -v has been fixed.
+10-09-07 A rare bug with indexed arrays when assigned a null string that could
+ cause a core dump has been fixed.
+10-09-03 A number of changes were made for jobs pools.
+10-08-31 typeset -p was modified to output name references after other
+ variables so that the output could be used as input.
+10-08-31 A bug with typeset -p in which variables with attributes but
+ without attributes were not displayed correctly has been fixed.
+10-08-27 +When running a subshell, the current pool is unset.
+10-08-27 A bug in which jobs started from within for or while lists in
+ interactive shells could generate completion messages has been fixed.
+10-08-25 Fixed a couple of bugs related to job pools.
+10-08-24 +[[ -e /dev/xxx/ ]] can be used to check whether special files of
+ those names are handled by the shell.
+10-08-24 A bug in the running of a compiled dot script in which only the
+ first command was executed has been fixed.
+10-08-23 A bug which sometimes caused a core dump with a configure script
+ has been fixed.
+10-08-20 A bug in command substitution which caused a configure script to
+ hang has been fixed.
+10-08-19 Eliminated unnecessary ; from output of compound variable with
+ typeset -p.
+10-08-17 Fixed a bug in command substitution in which under certain
+ circumstances a file whose size is a power of 2 plus one, and the last
+ character was not a new-line, could cause memory corruption.
+10-08-13 +Added static discipline functions to type similar to C++ static
+ class functions.
+10-08-11 A bug in time when applied to a pipeline in which the shell did
+ not wait for all elements of the pipeline to complete has been fixed.
+10-08-11 Restored sh_fmtq() quoting to not quote NAME= in NAME=VALUE.
+10-08-09 +Modified the expansion of message strings, $"...", so that they
+ are expanded each time they are referenced rather than expanding
+ them when the script is compiled or read in.
+10-08-06 +The process id for jobs in job pools is now of the form poolname.n
+ where n is the jobid in that pool. Commands that accept job names
+ or numbers now understand names in this format.
+10-08-05 A bug in which an assignment from within an arithmetic expression
+ inside a function would create a local variable has been fixed.
+10-08-04 A bug in the expanding of variables whose names contain multibyte
+ characters has been fixed.
+10-08-04 A bug which caused an exception when processing scripts compiled
+ with shcomp -n has been fixed.
+10-08-02 Tests using very small buffer sizes uncovered a number of bug most
+ connected with here documents which have been fixed.
+10-07-27 The format modifier , used for digit grouping with d and f formats
+ has been documented.
+10-07-26 cd '' now produces and error rather than changing to the current
+ directory.
+10-07-26 A bug in multi-byte locales which the last character of a
+ multi-byte character is a \ or pattern character which could occur
+ when the character was the last character of a command substitution
+ has been fixed.
+10-07-23 Another bug in the processing of ${var:offset;len} in multi-byte
+ locales when len is larger than the number of characters has been
+ fixed.
+10-07-23 Many coding changes have been made to eliminate most of the uses
+ of global variables in the shell code.
+10-07-22 Fixed a bug in which discipline functions were not being invoked
+ when it was invoked as ref.discipline where ref was a name reference
+ to an array instance.
+10-07-22 Fixed a bug in which discipline functions were not being invoked it
+ was invoked on a two dimensional array, i.e., arr[5][9].discipline.
+10-07-19 Fixed a buffering problem which occurred when running a script with
+ ssh and the parent ssh process is killed.
+10-07-14 Modified the parser to treat ((...)) inside [[...]] as ( (...) ) to
+ that it is a nested (...).
+10-07-09 A bug in the handling of process substitution inside command
+ substitution as part of a pipeline has been fixed.
+10-07-07 A bug in the output for compound variables containing
+ multi-dimensional arrays has been fixed.
+10-07-06 ksh now recovers from changes made by bash to the history file without
+ loosing history commands.
+10-06-25 A bug in which a large here document containing command substitutions
+ of a dynamically loaded function that contained a here document
+ could get truncated has been fixed.
+10-06-24 If after executing a script found in FPATH, if a function, builtin,
+ or type name corresponding to that script is not defined, the shell
+ now outputs an error message and returns value 126.
+10-06-23 Floating point functions that happened to return integer values
+ were being treated as if the function returned integers so that
+ integer division could be used instead of floating point division.
+10-06-22 Fixed a bug in earlier ksh93u in which an arithmetic assignment to a
+ variable in the global scope would instead create a local variable if
+ the variable had an attribute but did not have a value.
+10-06-18 Modified trap handling so that if the same signal is received when
+ executing the handler, it is deferred until the handler completes.
+10-06-16 Fixed a bug in which ulimit -v was setting the the cpu limit
+ on Linux.
+10-06-14 +The command 'typeset -T' now generates the list of type definitions
+ in a format that can be used as input to the shell.
+10-06-09 Put in patch from Solaris for output quoting with %q.
+10-06-09 +Made changes to the NAMESPACE compile option so that it now seems
+ to work. With this option, namespace <name> { command;} will
+ run command in the namespace .name so that all variables and
+ functions created by command are accessible outside the name
+ space via .name.var and .name.fun. Variables and functions that
+ are not in the namespace are not modified when running command.
+10-06-07 Change most internal interfaces to take Sh_t* argument.
+10-06-03 +Types can be loaded on first reference by putting definitions in
+ PFPATH.
+10-06-03 +The shell is now able to parse commands which use type statements
+ before the typeset -T command to define the type executes.
+10-06-03 A bug in the quoting for name reference declarations which did
+ not properly handle [ and ] in subscripts for associative arrays.
+10-06-02 A bug in which a discipline function defined by a type instance to
+ override the default was not being registered has been fixed.
+10-06-02 A bug in which read -C of an associative array of compound variables
+ was not working has been fixed.
+10-06-02 A bug in which the error message for an unset parameter with set -u
+ did not contain the name of the variable has been fixed.
+10-06-01 A bug in typeset -m for moving an indexed array instance to a variable
+ has been fixed.
+10-06-01 A bug in which caused memory to be freed twice when unset was called
+ for an indexed array that had get or set disciplines has been fixed.
+10-06-01 A bug in which the %b format of printf was not preserving NUL bytes
+ with \0 has been fixed.
+10-06-01 A bug in the handling of name references to array variables in
+ arithmetic expressions has been fixed.
+10-05-28 Fixed bugs in changing attributes for two dimensional arrays.
+10-05-28 Eliminated a few unreferenced variables and a reference to
+ uninitialized memory.
+10-05-27 Rewrote the subshell code to avoid using pipes an many cases.
+10-05-24 Fixed a bug which cause an exception when both -l and -s were
+ specified with typeset -i.
+10-05-21 Inputting of three dimensional indexed arrays with ( ( (...)...)...)
+ was not working and has been fixed.
+10-05-21 A bug in which adding the attributes -Ai to a variable via a name
+ reference could cause the value to display incorrectly has been fixed.
+10-05-21 A bug in which using $var inside ((...)) did not work when var was
+ a hex float variable.
+10-05-20 +The compile option SHOPT_EDPREDICT has been added. When this option
+ is on, as you type a line beginning with a # the following characters
+ are treated as a shell pattern and cause matching lines from the
+ history file to be displayed as a numbered list as you type.
+ You can scroll up and down this list or you can use <ESC>nTAB
+ to make this the current line (n defaults to 1 of omitted) or
+ <ESC>n<cr> to execute.
+10-05-20 A bug which caused an exception when multiple levels of composite
+ functions in arithemtic expressions has been fixed.
+10-05-19 <<< with an empty string no longer gives an error.
+10-05-19 A bug in arithmetic evaluation when a name reference to an array
+ instance was used has been fixed.
+10-05-14 A bug in which the shell treats a valid index array assignment,
+ typeset -a x=(foo (x=3;y=4) bar) as a syntax error has been fixed.
+10-05-13 A bug in creating name references to associative array variable
+ after a lookup of one of its elements has been fixed.
+10-05-12 Two bugs in the handling of function static type variables in
+ subshells have been fixed. One could cause an exception and the
+ other would leave side effects in the parent shell.
+10-05-10 A bug in which static variables in functions were not being saved and
+ restored properly when running subshells has been fixed.
+10-05-05 A bug in which print -v did not work correctly when an operand was an
+ indexed array element referring to a compound variable has been fixed.
+10-05-05 A change to improve performance by special casing empty string
+ assignments to avoid repeated malloc() and free().
+10-05-05 A bug in which creating a name reference to a non-existent associative
+ array element would create the array element has been fixed.
+10-05-04 A bug in which name references to static variables in the static
+ scope were not found has been fixed.
+10-04-30 Do not use socketpair() on systems that implement ioctl(I_PEEK)
+ on pipes.
+10-04-29 +When the current job pool is set, coprocess are run in a job pool.
+10-04-28 A type defined with a member foo that is an associative array without
+ elements followed by an expansion ${bar.foo[a]} and an assignment
+ bar.foo[a]=b, no longer indicates that ${#bar.foo[@]} has 0 members.
+10-04-27 Another bug in which a nested command substitution could hang if it
+ generated too much data has been fixed.
+10-04-26 A type defined with a member that is an indexed array without elements
+ would behave as if the 0th element of each instance was defined after
+ a non-zero element was specified and this has been fixed.
+10-04-26 A bug in which types defined in a subshell were not undefined when
+ the subshell completed has been fixed.
+10-04-23 For file completion in commmand line editing, file names starting
+ with # are now escaped so that they are not treated as comments.
+10-04-23 A bug in which ${t.var:=value}, where t is an instance of a type
+ variable, could assign value to the type variable rather than to
+ the type instance has been fixed.
+10-04-23 +Added &| which can be used in place of | to have portions of a
+ pipeline executed in the pool.
+10-04-22 +The .sh.pool variable was added for use with job pools.
+10-04-22 A bug in which a nested command substitution could hang if it
+ generated too much data has been fixed.
+10-04-20 A bug which corrupted one byte of memory when read was called with
+ reads that did not use a delimiter has been fixed.
+10-04-19 The display of a compound variable with an embedded array with
+ attributes was sometimes not working correctly and has been fixed.
+10-04-16 A bug in which attributes were not be propagated to elements in
+ an associative array has been fixed.
+10-04-15 A bug which caused scripts containing user defined math functions to
+ fail to compile with shcomp has been fixed.
+10-04-15 +Job pools have been added with the SHOPT_COSHELL compilation option.
+ A job pool allows a collection of background jobs to run either locally
+ or remotely and to be managed as a unit. The command '& name ...'
+ creates or uses a named job pool for subsequent background jobs.
+ kill, wait, and jobs allow the pool name as operands.
+10-04-14 A bug in which a coprocess connection could terminate prematurely
+ when running a nested subshell has been fixed.
+10-04-12 +Enumeration constants can be used in arithmetic expressions with the
+ ==, != and = operators when the left hand side is an enum variable
+ and the right hand side is an enumeration constant.
+10-04-07 A bug in which setting the trap on CHLD to ignore could cause
+ an incorrect exit status has been fixed.
+10-04-06 A bug in which LINENO was not incremented for a here-document when
+ the here-document word was followed by a comment has been fixed.
+10-04-06 The optimization that execs the last process of a script rather
+ than creating a new process has been removed when a trap on
+ interrupt has been set.
+10-04-06 Unsetting the 'C', 'A' or 'a' typeset attribute now produces an
+ error message rather than generating an exception.
+10-04-06 A bug in which .sh.name contained the subscript and .sh.subscript
+ was empty in some cases with discipline functions on array instances
+ has been fixed.
+10-04-05 A bug in the edit modes where preceding the interrupt character with
+ the literal next character did not work has been fixed.
+10-04-05 A bug in the creation of type instances of arrays which could cause
+ an exception has been fixed.
+10-03-30 A bug in the display of a compound variable containing an indexed
+ array of compound variables has been fixed.
+10-03-24 +Arithmetic functions can be defined using the shell function syntax,
+ 'function .sh.math.name x y z{...}' , where name is the function name
+ invoked within ((...)) and x y z are long double arguments passed
+ as name references. y and z are used for functions with two and
+ three arguments respectively. The value of the function is the value
+ of the long double .sh.value variable when the function returns.
+10-03-24 A bug in which integer division was mistakenly used when the
+ numerator was a binary operator with the first operand floating
+ point and the second integer, e.g. (.1**3)/3, has been fixed.
+10-03-24 The >; file operator was modified so that the temporary file is
+ created in the same physical directory as file.
+10-03-23 A warning message was added to sh -n when $var was used inside
+ ((...)) instead of var.
+10-03-19 fmin was added to the list of math function on the man page.
+10-03-19 Fixed the return value for unalias when the alias did not
+ exist.
+10-03-19 A bug in which the SHLVL variable exported the value it had on
+ input rather than the incremented value has been fixed.
+10-03-19 A bug which causes whence -q to go into an infinite loop has been
+ fixed.
+10-03-19 Removed space between Stopped message and (SIGTTIN) and (SIGTTOUT).
+10-03-17 Modified profile shell execution so that when builtins that
+ correspond to executable have extended attributes, they are
+ executed by pfksh instead of being treated as built-ins.
+10-03-16 A bug in whence -a which produced duplicate lines of output has
+ been fixed.
+10-03-16 A bug in the handling of process groups in monitor mode for
+ command substitutions has been fixed.
+10-03-15 Fixed a bug in which read -u[fd] could cause the shell to core
+ dump when fd was greater than open_max.
+10-03-15 +Modified the shell I/O so that the shell will not fail if the
+ ulimit for open_max is increased as part of the script.
+10-03-12 A bug in which a here-document containing command substitutions
+ that contained here-documents did not process correctly has been
+ fixed.
+10-03-12 A bug in which the terminal is not restored to canonical mode
+ after read times out when in a multibyte locale with no edit mode
+ enabled has been fixed.
+
+10-03-05 --- Release ksh93t+ ---
+10-03-05 A variable unset memory leak has been fixed and tests/leaks.sh
+ has been added to verify the fix.
+10-03-04 Documentation, comment, and diagnostic spelling typos corrected.
+10-02-14 Fix sh_getenv() initialization to cooperate with the 3d fs.
+10-02-12 A bug in which the get discipline function was not invoked for
+ associative array subscripts for unset array elements has been fixed.
+10-02-12 A bug which could occur if the last line of a script was an eval
+ that executed multiple commands has been fixed.
+10-02-02 A buffer overflow in read and another in binary type base64
+ encoding were fixed.
+10-01-20 A bug in the evaluation of arithmetic expression in which the
+ subscript was evaluated twice for $((foo[x++]++)) has been fixed.
+10-01-19 A workaround for a double-free of a trap in both a subshell and its
+ parent has been added.
+10-01-18 A bug in type handling of typeset -H has been fixed.
+10-01-15 The "adding empty subscript" warning now only emitted with -x set.
+10-01-01 A bug in the parser in which '$((case i in i):;esac);:))' was not
+ parsed correctly was fixed.
+10-01-01 A bug in the parser in which '$(( 2 , 3.6 ))' dumped core for locales
+ with radix char , and thousands separator . has been fixed.
+09-12-28 A bug in the handling of SIGCLD on systems that generated SIGCLD
+ while blocked waiting for process to complete has been fixed.
+09-12-24 ast setlocale() reworked to differentiate env var changes from user
+ override.
+09-12-18 A bug with the SHOPT_BGX option set which disabled traps for signals
+ < SIGCHLD when a trap for a signal > SIGCHLD was set has been fixed.
+09-12-18 A bug where [[ -v var ]] was incorrect for some variables (including
+ LC_* vars) has been fixed.
+09-12-15 A bug that produced a syntax error when a multibyte character
+ straddled a buffer boundary has been fixed.
+09-12-11 A bug where the subscript of an unset variable was not evaluated has
+ been fixed.
+09-12-09 A bug where shcomp dumped core on certain syntax errors has been fixed.
+09-12-07 A bug where a parent shell environment var reset in a subshell removed
+ the value in subsequent children of the parent shell has been fixed.
+09-12-04 A bug in which in some cases a trap in a function executed in
+ a subshell could trigger twice has been fixed.
+09-12-03 A bug in which SHLVL exported with some attributes could cause
+ the shell to abort at startup has been fixed.
+09-12-02 A bug with pipefail in which the shell could hang waiting for the
+ writer to complete before the last reader command has been fixed.
+09-11-30 A bug in which a trap could be inherited by the first element of
+ a pipeline when the command had more than 63 arguments that did
+ not contain any macro expansions has been fixed.
+09-11-19 When read from a terminal was called from with a while or for loop,
+ and an edit mode was on, a backspace or erase no longer will
+ overwrite the prompt.
+09-11-17 +Change .paths parse to handle BUILTIN_LIB=foo BUILTIN_LIB=foo-1.2.
+09-11-17 Inside a function, typeset foo.bar will bind foo to global variable
+ foo if local variable foo does not exist, instead of creating a
+ local variable.
+09-11-17 "read -n1" from the terminal has been fixed to read exactly one character.
+09-11-11 Job control now works for subshell commands, (...).
+09-11-11 If set -e is on for an interactive shell errors in special builtins
+ now cause the shell to exit.
+09-11-11 A bug in which an interrupt handler processed during the read builtin
+ when IFS did not contain a new line has been fixed.
+09-11-09 A bug in which a variable that has been unset in a subshell and then
+ exported from that subshell does not show up in the environment
+ has been fixed.
+09-11-02 ``,2'' is now a valid numeric constant for locales with
+ decimal_point=','.
+09-11-02 A bug where "return" in .profile did not restore the shell state
+ has been fixed.
+09-10-31 A bug that corrupted saved exit status when pids wrapped around has
+ been fixed.
+09-10-26 A bug in { LANG LC_ALL LC_category } ordering has been fixed in -last.
+09-10-16 A bug where notification to libast that the environment has changed
+ has been fixed.
+09-10-12 A bug in which a function loaded in a subshell could leave side
+ effects in the parent shell has been fixed.
+09-10-12 A bug in converting a printf %d operand to a number when the operand
+ contains multiple subscripts for the same variable has been fixed.
+09-10-09 A bug in the handling of the escape character \ in directory prefixes
+ in command completion has been fixed.
+09-10-09 $PATH processing has been changed to delay dir stat() and .paths
+ lookup until the directory is needed in the path search.
+09-09-28 Call the ast setlocale() intercept on unset too.
+09-09-24 A bug in which LANG=foo; LC_ALL=foo; unset LC_ALL; did not revert
+ LC_CTYPE etc. to the LANG value has been fixed.
+09-09-17 A bug in which unsetting SVLVL could cause a script invoked by
+ name without #! to core dump has been fixed.
+09-09-16 A bug in which a pipeline in a here-document could hang when the
+ pipefail option was on has been fixed.
+09-09-09 A bug in the processing of line joining in here documents which
+ occurred when a buffer began with <escape><new-line> has been fixed.
+09-09-09 +A leading ; with commands in a brace group or parenthesis group
+ no longer causes an error. It now is used for the "showme" option.
+09-09-09 A bug in which a subshell containing a background process could
+ block until the background process completed has been fixed.
+09-09-04 A bug in handing ${var[sub]}, where var is a nameref has been fixed.
+09-09-03 A bug which caused an index array to have the wrong number of elements
+ when it was converted from a compound variable by adding an another
+ element has been fixed.
+09-09-03 Specifying export for a compound variable now generates an error.
+09-09-02 $"..." localizations strings are no longer recognized inside `...`.
+09-09-01 A bug in the for loop optimizer in the handling of type static
+ variables has been fixed.
+09-09-01 An error message is not displayed when * and @ are used as subscripts.
+09-09-01 Several bugs in the processing for types that included an associative
+ array of another type has been fixed.
+09-09-01 A bug in the tracing of [[ a < b ]] and [[ a > b ]] has been fixed.
+09-08-26 The .sh.file variable was not being set for a script that was run
+ by name and didn't start with #! and this has been fixed.
+09-08-25 A bug in which a function called to deeply from command substitution
+ did not display an error message has been fixed.
+09-08-24 +When processing profiles, ksh93 now violates the POSIX standard and
+ treats &> as a redirection operator similar to bash.
+09-08-23 A bug in the handling of the trap on SIGPIPE that could lead to a
+ memory fault has been fixed.
+09-08-21 A bug in the handling of the comma operator in arithmetic expressions
+ that could cause a core dump on some systems has been fixed.
+09-08-20 A bug in which a compound variable containing an array of a type
+ that doesn't have any elements now expands correctly.
+09-08-19 A bug which disabled function tracing inside a function after
+ a call to another function has been fixed.
+09-08-19 A bug in which initializing a compound variable instance to another
+ compound variable by name has been fixed.
+09-08-18 A bug in which compound variable instances could be lost after
+ an instance that invoked a type method discipline has been fixed.
+09-08-18 A bug in which a discipline function for a type applied to an
+ array instance when invoked in a function ignored the subscript
+ has been fixed.
+09-08-18 A scoping error with variables in arithmetic expression with
+ type variables when reference with a name reference has been fixed.
+09-08-10 Several memory leaks were fixed primarily related to subshells.
+09-08-06 A bug in which setting the trap on CHLD to ignore could cause
+ a script to hang has been fixed.
+09-07-08 A bug in the processing of name reference assignments when it
+ contained pattern expansions with quoting has been fixed.
+09-06-22 +The default width for typeset -X has been changed so that there
+ should be no loss of precision when converting to a string.
+09-06-19 A bug in the printing of array elements for binary variables with
+ printf %B has been fixed.
+09-06-19 A bug which caused a core dump with trap DEBUG set with an array
+ assignment with no elements has been fixed.
+09-06-19 A bug with read with typeset -b -Z<num> has been fixed.
+09-06-19 Two bugs related to read -b for array variables has been fixed.
+09-06-19 A bug with typeset for compound variables containing arrays of
+ compound variables has been fixed.
+09-06-18 A bug in appending a compound variable to a an indexed array of
+ compound variables has been fixed.
+09-06-18 A bug which occurs when appending a compound variable to an indexed
+ array element has been fixed.
+09-06-18 Setting VISUAL to a value other than one ending in vi or emacs will
+ no longer unset the edit mode.
+09-06-17 A bug in typeset -m when moving a local compound variable to a
+ global compound variable via a name reference has been fixed.
+09-06-17 A bug in appending to nodes of an array of compound variables when
+ addressing them via nameref has been fixed.
+09-06-17 A bug in typeset -p var, when var is an array of compound variables
+ in which the output only contained on array element has been fixed.
+09-06-17 The prefix expansion ${!y.@} now works when y is a name
+ reference to an element of an array.
+09-06-16 Traps on signals that are ignored when the shell is invoked
+ no longer display. Previously they were ignored as required but
+ would be listed with trap -p.
+09-06-12 A bug in vi edit mode in which hitting the up arrow key at the
+ end of a line longer than 40 characters which caused a core dump
+ has been fixed.
+09-06-11 A bug in which "eval non-builtin &" would create two processes,
+ one for the & and another for non-builtin has been fixed.
+09-06-08 When var is an identifier and is unset, ${var} no longer tries to
+ run command substitution on the command var.
+09-06-08 +Process substitution arguments of the form <(command) can now be
+ used following the < redirection operator to redirect from command.
+09-05-13 A bug in which redirections of the form 2>&1 1>&5 inside command
+ substitution could cause the command substitution to hang has been
+ fixed.
+09-05-12 To conform with POSIX, the -u option only checks for unset variables
+ and subscript elements rather than checking for all parameters.
+09-05-12 A bug which could cause a core dump when a variable whose name
+ begins with a . was referenced as part of a name reference inside
+ a function has been fixed.
+09-05-01 A bug that caused a core dump when SIGWINCH was received and
+ both vi and emacs mode were off has been fixed.
+09-04-22 +Default alias compound='typeset -C' added.
+09-04-15 A bug that caused ${...;} to hang for large files has been fixed.
+09-04-08 A change was made in the -n option which printed out an incorrect
+ warning with <>.
+09-04-07 The emacs edit command M-_ and M_. and the vi command _ was fixed
+ to handle the case there there is no history file.
+09-04-05 A bug in handling new-lines with read -n has been fixed.
+09-04-05 The ENV variable defaults the the file named by $HOME/.kshrc rather
+ then to the string $HOME/.kshrc.
+09-03-31 A bug in which a nested command substitution with redirections could
+ leave a file descriptor open has been fixed.
+09-03-24 +ksh now only uses the value of the _ variable on startup if it can
+ verify that it was set by the invoking process rather than being
+ inherited by some other ancestor.
+09-03-24 +When ksh is invoked without -p and ruid!=euid, and the shell is
+ compiled without SHOPT_P_UID or ruid<SHOPT_P_UID, the shell now
+ enables the -p option. The previous version instead set the
+ euid to the ruid as it does for set +p.
+09-03-24 +When SHOPT_P_UID is defined at compile time and the shell is started
+ without -p and ruid!=euid and ruid>=SHOPT_P_UID then euid is set
+ to ruid. A bug that did the wrong test (ruid<SHOPT_P_UID) was fixed.
+09-03-17 +The sleep(1) builtin now accept and ISO 8601 PnYnMnDTnHnMnS
+ duration or date(1) compatible date/time operand.
+09-03-10 If a variable that was left or right justified or zero-filled was
+ changed with a typeset statement that was left or right justified
+ or zero-filled, then the original justification no longer affects
+ the result.
+09-03-10 A bug in the handling of traps when the last command in a script
+ is a subshell grouping command has been fixed.
+09-03-03 A bug in which an expansion of the form ${!prefix@} could generate
+ an exception after the return from a function has been fixed.
+09-02-02 A bug in restricted mode in which the value of ENV could be
+ changed from within a function has been fixed.
+09-02-02 A bug in which an erroneous message indicating that a process
+ terminated with a coredump has been fixed.
+09-02-02 The exit status when exit was called without an argument from
+ a signal handler was incorrect and has been fixed.
+09-02-02 A bug in which a function autoloaded in a subshell could cause
+ a core dump when the subshell completed has been fixed.
+09-02-02 A bug in which 2>&1 inside a command substitution wasn't working
+ correctly has been fixed.
+09-02-02 A bug in the call stack of arithmetic function with 2 args
+ returning int has been fixed.
+09-01-30 A bug in which 'eval print \$0' inside a function was giving the
+ wrong value for $0 has been fixed.
+09-01-28 A bug in which a command substitution could return an exit status
+ of 127 when the pipefail option is enabled has been fixed.
+09-01-26 ksh93 now generates an error message if you attempt to create
+ a global name reference to a local variable.
+09-01-26 +The [[ -v var ]] operator was modified to test for array elements.
+09-01-23 +The redirection operator <>; was added. It is similar to <>
+ except that if the command it is applied to succeeds, the file
+ is truncated to the offset at the command completion.
+09-01-23 The default file descriptor for <> was changed to 1.
+09-01-20 A bug in which the exit status specified in an exit trap was
+ not used when a process terminated with a signal has been fixed.
+09-01-19 A bug in which a signal whose default action is to terminate
+ a process could be ignored when the process is running a sub-shell
+ has been fixed.
+09-01-19 A bug in which sending SIGWINCH to a process that reads from a pipe
+ could cause a memory fault has been fixed.
+09-01-16 +The -R unary operator was added to [[...]] and test to check whether
+ a variable is a name reference.
+09-01-16 +The -v unary operator was added to [[...]] and test to check whether
+ a variable is set.
+09-01-14 The unset built-in was modified to return 0 exit status when
+ unsetting a variable that was unset to conform with the POSIX
+ standard.
+09-01-14 The unset built-in was modified to continue to unset variables
+ after encountering a variable that it could not unset to
+ conform to the POSIX standard.
+09-01-14 The parameter expansion ${x+value} no longer expands the value of
+ the variable x when determining whether x is set or not.
+09-01-13 A bug in which background jobs and pipelines that were not waited
+ for could, in rare instances, cause the shell to go into an infinite
+ loop or fail has been fixed.
+09-01-06 A bug in indexed arrays of compound variables in which referencing
+ non-existent sub-variable in an arithmetic expression could cause
+ the sub-variable to be created has been fixed.
+09-01-05 A bug in which the \ character did not escape extended regular
+ expression pattern characters has been fixed.
+08-12-24 A bug in which killing the last element of a pipe did not cause
+ a write to the pipe to generate a SIGPIPE has been fixed.
+08-12-19 A bug which could cause command substitution to hang when the
+ last element of a pipeline in a command substitution was a built-in
+ and the output was more that PIPE_BUFF.
+08-12-18 A bug which occurs when a here documented marker embedded in a
+ command substitution occurs on a buffer boundary has been fixed.
+08-12-17 A bug in the output of typeset -p for variables that had attributes
+ but did not have a value has been fixed.
+08-12-16 A bug in which a name reference to a name reference variable that
+ references an array element has been fixed.
+08-12-16 A bug in which a variable given both the -A and -C attribute along
+ with an initial assignment didn't work correctly has been fixed.
+08-12-10 The [[ -t fd ]] test was fixed to handle fd>9.
+08-12-10 A bug where function stack misalignment could cause a bus error
+ has been fixed.
+08-12-09 Command completion was changed to use \ to quote special characters
+ instead of quoting the argument in single quotes.
+08-12-07 A bug in typeset -m which occurred when the target node was an
+ associative array element has been fixed.
+08-12-07 A timing bug on some systems (for example darwin), that could
+ cause the last process of a pipeline entered interactively to fail
+ with an "Exec format error" has been fixed.
+08-12-04 +SHOPT_BGX enables background job extensions. Noted by "J" in
+ the version string when enabled. (1) JOBMAX=n limits the number
+ of concurrent & jobs to n; the n+1 & job will block until a
+ running background job completes. (2) SIGCHLD traps are queued
+ so that each completing background job gets its own trap; $! is
+ set to the job pid and $? is set to the job exit status at the
+ beginning of the trap. (3) sleep -s added to sleep until the time
+ expires or until a signal is delivered.
+08-12-04 The sign of floating point zero is preserved across arithmetic
+ function calls.
+08-12-04 A bug that caused print(1) to produce garbled stdout/stderr
+ output has been fixed.
+08-12-04 A bug in which printf "%d\n" "'<euro>'" did not output the
+ numerical value of the EURO symbol, 8354, has been fixed.
+08-11-24 + /dev/fd* and /dev/std* redirections are first attempted with
+ open() to preserve seek semantics; failing that the corresponding
+ file descriptors are dup()'d.
+08-11-20 A bug which could cause a core dump if a function compiled with
+ shcomp was found has been fixed.
+08-11-20 A bug in which jobs were not cleared from the jobs table for
+ interactive shells when the pipefail option is on has been fixed.
+08-11-11 A bug in which a field that was unset in a type definition and later
+ set for an instance could appear twice when displaying the variable
+ has been fixed.
+08-11-11 A bug in which running a simple command & inside a function would
+ not return the correct process id has been fixed.
+08-11-10 A bug in which the exit status of a command could be lost if the pid
+ was that of the most recent command substitution that had completed
+ has been fixed.
+08-11-10 The maximum depth for subshells has been increased from 256 to 65536.
+08-11-06 A bug which could cause a core dump when the _ reference variable was
+ used as an embedded type with a compound assignment has been fixed.
+
+08-10-31 --- Release ksh93t ---
+08-10-31 Variable scoping/initialization bugs that could dump core were fixed.
+08-10-24 The lexer now accepts all RE characters for patterns prefixed
+ with a ksh ~(...) option expression.
+08-10-24 +For ${var/pat/sub} \0 in sub expands to the text matched by pat.
+08-10-18 A bug in array scoping that could dump core has been fixed.
+08-10-10 read -n and -N fixed to count characters in multibyte locales.
+08-10-10 A bug that mishandled _.array[] type references has been fixed.
+08-10-09 +${.sh.version} now contains a concatenation of the following (after
+ 'Version') denoting compile time features:
+ A SHOPT_AUDIT
+ B SHOPT_BASH
+ L SHOPT_ACCT
+ M SHOPT_MULTIBYTE
+08-10-09 A bug that caused subshell command substitution with redirection
+ to hang has been fixed.
+08-10-08 Output errors, other than to stderr, now result in a diagnostic.
+08-10-08 ksh93 now supports types that contain arrays of other types as
+ members. Earlier versions core dumped in this case.
+08-10-05 A bug which caused the shell to emit a syntax error for an arithmetic
+ statement of the form (( var.name[sub] = value)) has been fixed.
+08-10-01 A bug that caused subshell command substitution to hang has
+ been fixed.
+08-09-29 When the -p export option of typeset is used with other options,
+ only those variables matching the specified options are displayed.
+08-09-29 When the shell reads the environment and finds variables that are
+ not valid shell assignments, it now passes these on to subsequent
+ commands rather than deleting them.
+08-09-29 A bug in the display of compound variables containing an indexed
+ array of compound variables has been fixed.
+08-09-29 A bug in the display of compound variables containing an associative
+ array with a subscript containing a . in the name has been fixed.
+08-09-26 A core dump in the subshell environment restore has been fixed.
+08-09-24 $(...) has been fixed to properly set the exit status in $?.
+08-09-23 $(<...) with IFS=$'\n\n' has been fixed to retain all but the last
+ of multiple trailing newlines.
+08-09-23 The -p option to typeset when used with other attributes, restricts
+ the output to variables with the specified attributes.
+08-09-22 A bug that sometimes lost the exit status of a job has been fixed.
+08-09-21 A bug that retained trailing command substitution newlines in
+ cases where the command caused the shell to fork has been fixed.
+08-09-19 type, whence -v, and command -v were fixed to comply with POSIX
+ by writing 'not found' diagnostics to the standard error.
+08-09-18 test and [...] were fixed to comply with POSIX in the case
+ of test '(' binop ')' where binop is a valid binary test operator.
+08-09-16 +If a method discipline named create is specified when defining a
+ type, this function will be called when an instance is created.
+08-09-15 +The variable _ is now set as a reference to the compound variable
+ when defining a compound variable or a type.
+08-09-10 The shell now prints an error message when the type name specified
+ for an indexed array subscript is not an enumeration type.
+08-09-10 A bug in which a subshell that spawned a background process could
+ loose output that was produced after the foreground completed
+ has been fixed.
+08-09-10 A timing bug on some systems that could cause coprocesses started by a
+ subshell to not clean up and prevent other coprocesses has been fixed.
+08-09-09 The typeset -m option is now able to rename array elements from
+ the same array.
+08-09-09 The exit status of 2 from the DEBUG trap causes the next command
+ to be skipped. An exit value of 255 from a DEBUG trap called from
+ a function causes the function to return.
+08-09-08 A bug in which a coprocess created in a subshell that did not
+ complete when the subshell terminated could prevent a coprocess
+ from being created in the parent shell has been fixed.
+08-09-05 An assignment of the form name1=name2 where name1 and name2
+ are both compound variables causes name1 to get a copy of name2.
+ name1+=name2 causes name2 sub-variables to be appended to name1.
+08-09-05 A bug in which unsetting a compound variable did not unset all
+ the sub-variables has been fixed.
+08-09-01 A bug in the subshell cleanup code that could cause SIGSEGV has
+ been fixed.
+06-08-26 +The SHLVL variable which is an environment variable used by bash
+ and zsh that gets incremented when the shell starts.
+08-08-25 +For an indexed array, a negative subscript now refers to offsets
+ from the end so that -1 refers to the last element.
+08-08-24 An alignment error for shorts on 64 bit architectures has been fixed.
+08-08-22 If oldvar is a compound variable, typeset -C newvar=oldvar creates
+ newvar as a copy of oldvar.
+08-08-19 +The ALRM signal no longer cause the sleep builtin to terminate.
+08-08-13 When used in an arithmetic expression, the .sh.version variable
+ now produces a number that will be increasing for each release.
+08-08-11 A bug in which type instantiation with a compound assignment in
+ a dot script in which the type is defined has been fixed.
+08-08-07 +The -m option has been added to typeset to move or rename a
+ variable. Not documented yet.
+08-08-06 A bug in read when used in a loop when a prompt was specified
+ when reading from a terminal has been fixed.
+08-08-01 A bug with the pipefail option in which a nested pipeline could
+ cause an asynchronous command to block has been fixed.
+08-08-01 A for loop optimizer bug that treats .sh.lineno as an invariant
+ has been fixed.
+08-07-30 A bug in which expanding compound variable that had a get discipline
+ from with a here document could cause a syntax error has been fixed.
+08-07-18 A bug in which a nameref caused a local variable to be created
+ rather than binding to an existing variable in the global scope
+ has been fixed.
+08-07-17 A bug which occurred when a nameref was created from within a
+ function that was part of a pipeline has been fixed.
+08-07-14 +The compile option SHOPT_STATS was added. With this option the
+ compound variable .sh.stats keeps usage statistics that could help
+ with performance tuning.
+08-07-10 +The output of set now always uses a single line for each variable.
+ For array variables, the complete set of values is now displayed.
+08-07-09 +The typeset -C option can be used with arrays to indicate that
+ each element should default to a compound variable.
+08-07-08 +The %B format now outputs compound variables and arrays. The
+ alternate flag # can be used to cause output into a single line.
+08-07-03 When the window change signal, WINCH, is received, the current
+ edit line is redrawn in place.
+08-07-01 A bug in the handling of shared variables when inside an embedded
+ type has been fixed.
+08-06-29 A bug in multiline edit mode which occurred when the prompt length
+ was three characters or less has been fixed.
+08-06-23 A bug in which the SIGCLD was not be triggered when background
+ jobs completed has been fixed.
+08-06-23 _KSH_VERSION added as a name reference to .sh.version.
+08-06-20 type now outputs 'special builtin' for special builtins.
+08-06-19 A couple of bugs in multi-dimensional arrays have been fixed.
+08-06-19 A bug in which a syntax error in a dot script could generated
+ a syntax error in the next subsequent command has been fixed.
+08-06-17 Reduced the maximum function call depth to 2048 to avoid exceptions
+ on some architectures.
+08-06-16 A bug in which printf "%B" could generate an exception when the
+ specified variable was not set has been fixed.
+08-06-16 +When typeset -p is followed by variable names, it now displays
+ the attributes names and values for the specific names.
+08-06-14 A bug that could effect the drawing of the screen from multiline
+ emacs or gmacs mode when walking up the history file has been fixed.
+08-06-13 A bug in which a compound variable defined in a subshell could
+ have side effects into the parent shell has been fixed.
+08-06-13 A number of bugs related to using .sh.level to set the stack from
+ for DEBUG traps have been fixed.
+08-06-13 +The .sh.lineno variable has been added. When .sh.level is changed
+ inside a DEBUG trap, the .sh.lineno contains the calling line number
+ for the specified stack frame.
+08-06-13 The .sh.level variable has been documented and now works.
+08-06-11 +The -C option has been added to read for reading compound command
+ definitions from a file.
+08-06-11 +The . command is now permitted inside a compound command definition.
+ The dot script can contain declaration commands and dot commands.
+08-06-09 +Add -C option to typeset so that typeset -C foo, is equivalent
+ to foo=().
+08-06-09 Added -n warning message for typeset option orderings that are valid
+ with ksh88 but not valid with ksh93, for example Lx5.
+08-06-09 A bug in which the return value for an assignment command containing
+ a command substitution with that failed was zero when the assignment
+ contained redirections has been fixed.
+08-06-09 A bug in the quoting of $ inside a ERE pattern ~(E)(pattern)
+ has been fixed.
+08-06-06 A bug when processing `` command substitution with the character
+ sequence \$' has been fixed.
+08-06-02 +When defining a type, the typeset -r attribute causes this field
+ to be required to be specified for each instance of the type and
+ does not allow a default value.
+08-06-02 Several bugs in which compound variables were modified by
+ subshells have been fixed.
+08-05-22 +The ceil function has been added to the math functions.
+08-05-21 A bug in which a name reference defined in a function and passed
+ as an argument to another function could cause an incorrect binding.
+08-05-21 A bug in freeing compound variables that are local to functions
+ has been fixed.
+08-05-19 +The array expansions ${array[sub1..sub2]} and ${!array[sub1..sub2]}
+ to expand to the value (or subscripts) for array between sub1 and
+ sub2 inclusive. For associative arrays, the range is based on
+ location in the POSIX locale. The .. must be explicit and cannot
+ result from an expansion.
+08-05-15 The trap on SIGCLD is no longer triggered by the completion of
+ the foreground job as with ksh88.
+08-05-14 A bug in the implementation of the editing feature added on
+ 07-09-19 in emacs mode has been fixed.
+08-05-12 A bug in processing the test built-in with parenthesis has been
+ fixed.
+08-05-12 The unset built-in now returns non-zero when deleting an array
+ subscript that is not set.
+08-05-08 +Changing the value of HISTFILE or HISTSIZE will cause the old
+ history file to be close and reopened with the new name or size.
+08-05-08 When FPATH is changed functions that were found via a path search
+ will be searched for again.
+08-05-08 A parser bug in which reserved words and labels were recognized
+ inside compound indexed array assignment after a new-line has
+ been fixed.
+08-05-07 A bug in getopts when handling numerical option arguments has
+ been fixed.
+08-05-07 +The typeset -S option was added for variables outside type
+ definitions to provide a storage class similar to C static
+ inside a function defined with function name. When outside
+ type definitions and outside a function, the -S option cause
+ the specified variable so be unset before the assignment and
+ before the remaining attributes are supplied.
+08-05-07 A bug that affected the cursor movement in multiline mode when
+ a character was deleted from near the beginning of the any
+ line other than the first.
+08-05-01 In multiline edit mode, the refresh operation will now clear
+ the remaining portion of the last line.
+08-05-01 A bug in computing prompt widths for the edit modes for prompts
+ with multibyte characters has been fixed.
+08-05-01 A bug in the multiline edit mode which could cause the current
+ line to be displayed incorrectly when moving backwards from third
+ or higher line to the previous line has been fixed.
+08-05-01 A bug in which options set in functions declared with the function
+ name syntax were carried across into functions invoked by these
+ functions has been fixed.
+08-04-30 A bug which could cause a coprocess to hang when the read end
+ is a builtin command has been fixed.
+08-04-30 +The emacs and vi editors have been modified to handle window
+ change commands as soon as they happen rather than waiting for
+ the next command.
+08-04-28 A bug in which ${!x} did not expand to x when x was unset has been
+ fixed.
+08-04-27 A bug in which the assignment x=(typeset -a foo=([0]=abc)) created
+ x.foo as an associative array has been fixed.
+08-04-25 A bug in which $# did not report correctly when there were more
+ than 32K positional parameters has been fixed.
+08-04-04 Choose the name _ as the sub-variable that holds type or instance
+ specific data used by discipline functions.
+08-03-27 A bug in which the terminal group was not given back to the parent
+ shell when the last part of a pipeline was handled by the parent shell
+ and the other parts of the pipeline complete has been fixed.
+ The symptom was that the pipeline became uninterruptable.
+08-03-25 A bug in restricted mode introduced in ksh93s that caused scripts
+ that did not use #! to executed in restricted mode has been fixed.
+08-03-25 A bug in which the pipefail option did not work for a pipeline
+ within a pipeline has been fixed.
+08-03-24 A bug in which OPTIND was not set correctly in subshells has
+ been fixed.
+08-03-24 A bug which could cause a memory exception when a compound variable
+ containing an indexed array with only element 0 defined was expanded.
+08-03-20 A bug in which ${!var[sub].*} was treated as an error has been fixed.
+08-03-20 Associative array assignments of the form ([name]=value ...)
+ now allow ; as well as space tab and new line to separate elements.
+08-03-18 A buffering problem in which standard error was sometimes
+ not flushed before sleep has been fixed.
+08-03-17 A bug in which a signal sent to $$ while in a subshell would be
+ sent to the subshell rather than the parent has been fixed.
+08-03-17 + A --default option added to set(1) to handle set +o POSIX semantics.
+ set --state added as a long name alias for set +o.
+08-03-14 A bug in which using monitor mode from within a script could
+ cause the terminal group to change has been fixed.
+08-03-10 The new ${...} command substitution will treat the trailing }
+ as a reserved word even if it is not at the beginning of a command,
+ for example, ${ date }.
+08-03-10 If the name of the ENV begins with /./ or ././ then the
+ /etc/ksh.kshrc file will not be executed on systems that support
+ this interactive initialization file.
+08-03-07 A bug in which ksh -i did not run the ENV file has been fixed.
+08-03-07 A bug in which ulimit did not always produce the same output as
+ ulimit -fS has been fixed.
+08-03-04 A bug in multiline mode in emacs and vi mode which could cause the
+ cursor to be on the wrong line when interrupt was hit has been fixed.
+08-03-03 The change made in ksh93s+ on 07-06-18 in which braces became
+ optional for ${a[i]} inside [[...]] was restored in the case
+ where the argument can be a pattern.
+08-03-03 A bug in which creating a name reference to an associative array
+ instance would fail when the subscript contained characters [ or
+ ] has been fixed.
+08-02-29 +The redirection operator >; has been added which for non-special
+ files, generates the output in a temporary file and writes the
+ specified file only of the command has completed successfully.
+08-02-15 A bug in ${var/pattern/string} for patterns of the form ?(*) and +(*)
+ has bee fixed.
+08-02-07 A bug in which test \( ! -e \) produced an error has been fixed.
+08-02-14 +The typeset -a option can now optionally be followed by the name
+ of an enumeration type which allows subscripts to be enumerations.
+08-02-14 +The enum builtin which creates enumeration types has been added.
+08-02-12 The backoff logic when there are no more processes has been fixed.
+08-02-07 The -X option has been added to typeset. The -X option creates
+ a double precision number that gets displayed using the C99 %a
+ format. It can be used along with -l for long double.
+08-01-31 The -T option to typeset has been added for creating typed
+ variables. Also the -h and -S options have been added to
+ typeset that are only applicable when defining a type.
+08-01-31 The prefix expansion operator @ has been added. ${@name}
+ expands to the type of name or yields the attributes.
+07-11-15 A bug in the macro expander for multibyte characters in which
+ part of the character contains a file pattern byte has been fixed.
+07-10-03 A bug in which : was not allowed as part of an alias name has been
+ fixed.
+07-09-26 A bug in which appending a compound variable to a compound variable
+ or to an index array didn't work has been fixed.
+07-09-19 In both emacs and vi edit mode, the escape sequence \E[A (usually
+ cursor up, when the cursor is at the end of the line will fetch
+ the most recent line starting with the current line.
+07-09-18 The value of ${!var} was correct when var was a reference to an
+ array instance.
+07-09-18 The value of ${!var[sub]} was not expanding to var[sub] and this
+ was fixed. It also fixed ${name} where name is a name reference
+ to var[sub].
+07-09-18 +It is now legal to create a name reference without an initialization.
+ It will be bound to a variable on the first assignment.
+07-08-30 +A discipline function can be invoked as ${x.foo} and is equivalent
+ to ${ x.foo;} and can be invoked as x.foo inside ((...)).
+07-07-09 A bug in which typeset -a did not list indexed arrays has been
+ fixed.
+07-07-03 +The command substitution ${ command;} has been added. It behaves
+ like $(command) except that command is executed in the current
+ shell environment. The ${ must be followed by a blank or an
+ operator.
+
+08-04-17 --- Release ksh93s+ ---
+08-04-17 A bug in which umask was not being restored correctly after a
+ subshell has been fixed.
+08-04-15 A bug in which sending a STOP signal to a job control shell started
+ from within a shell function caused cause the invoking shell to
+ terminate has been fixed.
+08-04-11 A bug which caused $(exec > /dev/null) to go into an infinite loop
+ has been fixed.
+08-03-27 A bug in which typeset -LZ was being treated as -RZ has been fixed.
+08-03-06 A bug with ksh -P on systems that support the the profile shell,
+ in which it would exit after running a non-builtin has been fixed.
+08-01-31 A bug in which command substitution inside ((...)) could cause
+ syntax errors or lead to core dumps has been fixed.
+08-01-17 A bug in which discipline functions could be deleted when invoked
+ from a subshell has been fixed.
+08-01-17 A bug in which a command substitution consisting only of
+ assignments was treated as a noop has been fixed.
+08-01-17 A bug in which discipline functions invoked from withing a
+ compound assignment could fail has been fixed.
+08-01-16 Incomplete arithmetic assignments, for example ((x += )), now
+ generate an error message.
+08-01-16 A bug in which a set discipline defined for a variable before
+ an array assignment could cause a core dump has been fixed.
+08-01-03 A bug in on some systems in which exit status 0 is incorrectly
+ returned by a process that catches the SIGCONT signal is stopped
+ and then continued.
+07-12-13 A race condition in which a program that has been stopped and then
+ continued could loose the exit status has been fixed.
+07-12-12 Code to check for file system out of space write errors for all
+ writes has been added.
+07-12-11 A bug in the macro expander for multibyte characters in which
+ part of the character contains a file pattern byte has been fixed.
+07-12-06 A bug in the emacs edit mode when multiline was set that output
+ a backspace before the newline to the screen has been fixed.
+07-12-04 A bug in which using <n>TAB after a variable name listing expansion
+ in the edit modes would cause the $ to disappear has been fixed.
+07-11-28 A bug in which setting IFS to readonly could cause a subsequent
+ command substitution to fail has been fixed.
+07-11-27 A work around for a gcc 4.* C99 "feature" that could cause a job
+ control shell to go into an infinite loop by adding the volatile
+ attribute to some auto vars in functions that call setjmp().
+07-11-27 A bug in which the shell could read ahead on a pipe causing the
+ standard input to be incorrectly positioned has been fixed.
+07-11-27 A bug in which compound variable UTF-8 multibyte values were not
+ expanded or traced properly has been fixed.
+07-11-21 A bug where an unbalanced '[' in a command argument was not treated
+ properly has been fixed.
+07-11-15 A bug in which compatibility mode (no long option names) getopts(1)
+ incorrectly set the value of OPTARG for flag options has been fixed.
+07-11-15 A bug in which "hash -- name" treated "--" as an invalid name operand
+ has been fixed.
+07-11-15 typeset now handles "-t -- [-r] [--]" for s5r4 hash(1) compatibility.
+07-11-15 A bug in which the umask builtin mis-handled symbolic mode operands
+ has been fixed.
+07-11-15 Bugs in which shell arithmetic and the printf builtin mis-handled the
+ signs of { -NaN -Inf -0.0 } have been fixed.
+07-11-15 +The full { SIGRTMIN SIGRTMIN+1 ... SIGRTMAX-1 SIGRTMAX } range
+ of signals, determined at runtime, are now supported.
+07-11-15 A bug in which creating an index array with only subscript 0 created
+ only a simple variable has been fixed.
+07-11-14 A bug in which appending to an indexed array using the form
+ name+=([sub]=value) could cause the array to become an associative
+ array has been fixed.
+07-11-14 A bug in which typeset without arguments could coredump if a
+ variable is declared as in indexed array and has no elements has
+ been fixed.
+07-11-14 A bug in which creating a local SECONDS variable with typeset in
+ a function could corrupt memory has been fixed.
+07-11-14 A bug which could cause a core dump when a script invoked by name
+ from a function used compound variables has been fixed.
+07-11-05 A bug in which printf %d "'AB" did not diagnose unconverted characters
+ has been fixed.
+07-11-05 printf %g "'A" support added for all floating point formats.
+07-11-01 A bug in which typeset -f fun did not display the function definition
+ when invoked in a subshell has been fixed.
+07-10-29 The sleep builtin was fixed so that all floating point constants
+ are valid operands.
+07-10-10 A bug in which the locale was not being restored after
+ LANG=value command has been fixed.
+07-09-20 A bug in which a nameref to a compound variable that was local
+ to the calling function would not expand correctly when displaying
+ is value has been fixed.
+07-09-19 A bug which cause cause a core dump if .sh.edchar returned
+ 80 characters or more from a keyboard trap has been fixed.
+07-09-14 A bug in which could cause a core dump when more than 8 file
+ descriptors were in use has been fixed.
+07-09-10 A bug in which creating a name reference to an instance of
+ an array when the array name is itself a reference has been fixed.
+07-09-10 The file completion code has been modified so that after an = in
+ any word, each : will be considered a path delimiter.
+07-09-06 A bug in which subprocess cleanup could corrupt the malloc() heap
+ has been fixed.
+07-08-26 A bug in which a name reference to an associative array instance
+ could cause the subscript to be evaluated as an arithmetic expression
+ has been fixed.
+07-08-22 A bug in which the value of an array instance was of a compound
+ variable was not expanded correctly has been fixed.
+07-08-14 A bug which could cause a core dump when a compound assignment was
+ made to a compound variable element with a typeset -a attribute
+ has been fixed.
+07-08-08 A bug in which a trap ignored in a subshell caused it to be
+ ignored by the parent has been fixed.
+07-08-07 A bug in which the set command would generated erroneous output
+ for a variable with the -RZ attribute if the variable name had been
+ passed to a function has been fixed.
+07-08-02 A bug in which read x[1] could core dump has been fixed.
+07-08-02 A second bug in which after read x[sub] into an associative array
+ of an element that hasn't been assigned could lead to a core dump
+ has been fixed.
+07-07-31 A bug in which a pipeline that completed correctly could have
+ an exit status of 127 when pipefail was enabled has been fixed.
+07-07-09 +The SHOPT_AUDIT compile option has been added for keyboard logging.
+07-06-25 In vi insert mode, ksh no longer emits a backspace character
+ before the carriage return when the newline is entered.
+07-06-25 A bug in which pipefail would cause a command to return 0
+ when the pipeline was the last command and the failure happened
+ on a component other than the last has been fixed.
+07-06-25 A bug in the expansion of ${var/pattern/rep} when pattern or rep
+ contained a left parenthesis in single quotes has been fixed.
+07-06-18 The braces for a subscripted variable with ${var[sub]} are now
+ optional when inside [[...]], ((...)) or as a subscript.
+07-05-28 A bug in brace expansion in which single and double quotes did
+ not treat the comma as a literal character has been fixed.
+07-05-24 The -p option of whence now disables -v.
+07-05-23 Several bug fixes in compound variables and arrays of arrays
+ have been made.
+07-05-15 A bug in which the %B format of printf was affected by the
+ locale has been fixed.
+07-05-14 A bug in which \ was not removed in the replacement pattern with
+ ${var/pattern/rep} when it was not followed by \ or a digit has
+ been fixed.
+07-05-10 A bug in which ksh -R file core dumped if no script was specified
+ has been fixed. it not displays an error message.
+07-05-07 Added additional Solaris signals to signal table.
+07-04-30 A bug in which a pipeline with command substitution inside a
+ function could cause a pipeline that invokes this function to
+ hang when the pipefail option is on has been fixed.
+07-04-30 +Added -q to whence.
+07-04-18 A small memory leak with each redirection of a non-builtin has
+ been fixed.
+07-03-08 A bug in which set +o output command line options has been fixed.
+07-03-08 A bug in which an error in read (for example, an invalid variable
+ name), could leave the terminal in raw mode has been fixed.
+07-03-06 A bug in which read could core dump when specified with an array
+ variable with a subscript that is an arithmetic expression has
+ been fixed.
+07-03-06 Several serious bugs with the restricted shell were reported and
+ fixed.
+07-03-02 If a job is stopped, and subsequently restarted with a CONT
+ signal and exits normally, ksh93 was incorrectly exiting with
+ the exit status of the stop signal number.
+07-02-26 +M-^L added to emacs mode to clear the screen.
+07-02-26 A bug in which setting a variable readonly in a subshell would
+ cause an unset error when the subshell completed has been fixed.
+07-02-19 +The format with printf uses the new = flag to center the output.
+07-02-19 A bug in which ksh93 did not allow multibyte characters in
+ identifier names has been fixed.
+07-02-19 A bug introduced in ksh93 that causes global compound variable
+ definitions inside functions to exit with "no parent" has been fixed.
+07-02-19 A bug in which using compound commands in process redirection
+ arguments would give syntax errors <(...) and >(...) has been fixed.
+07-01-29 A bug which caused the shell to core dump which can occur when a
+ built-in exits without closing files that it opens has been fixed.
+07-01-26 A bug in which ~(E) in patterns containing \ that are not inside ()
+ has been fixed.
+
+06-12-29 --- Release ksh93s ---
+06-12-29 A bug in which the value of IFS could be changed after a command
+ substitution has been fixed.
+06-12-22 +/dev/(tcp|udp|sctp)/HOST/SEVRICE now handles IPv6 addresses on
+ systems that provide getaddrinfo(3).
+06-12-19 +A -v option was added to read. With this option the value of
+ the first variable name argument will become the default value
+ when read from a terminal device.
+06-11-20 A bug in which "${foo[@]:1}}" expands a null argument (instead of
+ no argument), when foo[0] is not empty has been fixed.
+06-11-16 The discipline functions have been modified to allow each subscript
+ to act independently. Currently the discipline function will not
+ be called when called from a discipline function of the same variable.
+06-11-14 A bug which could cause a core dump if a file descriptor for
+ an internal file was closed from with a subshell has been fixed.
+06-10-30 +The redirections <# pattern, and <## pattern have been added.
+ Both seek forward to the beginning of the next line that contains
+ the pattern. The <## form copies the skipped portion to standard
+ output.
+06-10-26 +On systems that support stream control transport, the virtual file
+ name /dev/sctp/host/port can now be used to establish connections.
+06-10-26 +The printf modifier # when used with d produces units in thousands
+ with a single letter suffix added. The modifier # when used with
+ the i specification provides units of 1024 with a two letter suffix.
+06-10-24 The value of $! is now set to the process id of a job put
+ into the background with the bg command as required by POSIX.
+06-10-23 A bug in which the value of $! was affected by a background
+ job started from a subshell has been fixed.
+06-10-23 A bug in ${var:offset:len} in multibyte locales has been fixed.
+06-10-15 +The remaining math functions from C99 were added for any system
+ that supports them.
+06-10-13 The klockwork.com software detected a few coding errors that
+ have been fixed.
+06-10-12 A bug when skipping over `...` with ${x:=`...`} when x is set
+ has been fixed.
+06-10-11 A bug in process floating constants produced by the %a format
+ of printf has been fixed.
+06-10-06 A bug in which IFS was not being restored correctly in some
+ cases after a subshell has been fixed.
+06-10-06 A bug in which pipefail was not detecting some failures in
+ pipelines with 3 or more states has been fixed.
+06-10-03 A bug in the processing of >(...) with builtins which could
+ cause the builtin to hang has been fixed.
+06-10-03 A bug in the for loop optimizer which causes >(...) process
+ substitution to be ignored has been fixed.
+06-09-17 +The -a option was added to typeset for indexed arrays. This
+ is only needed when using the ([subscript]=value ...) form.
+06-09-06 +The showme option was added. Each simple command not beginning
+ with a redirection and not occurring with in the while, until, if,
+ select condition can be preceded by a semi-colon which will
+ be ignored when showme is off. When showme is on, any command
+ preceded by a colon will be traced but not executed.
+06-08-16 +As a new feature, a leading ~(N) on a pattern has no effect
+ except when used for file expansion. In this case if not
+ matches are found, the pattern is replaced by nothing rather
+ than itself.
+06-08-11 A bug in the expansion of ${.sh.match[i]:${#.shmatch[i]}} has
+ been fixed.
+06-08-10 +The read builtin options -n and -N have been modified to treat
+ the size as characters rather than bytes unless storing into a
+ binary (typeset -B) variable.
+06-07-27 +When the here document operator << is followed directly by a #
+ rather than a -, the first line of the here-document determines
+ how much whitespace is removed for each line.
+06-07-26 A bug in the C-shell history (enabled with set -H) in which the
+ history event !$ was not processed has been fixed.
+06-07-21 A bug on some systems in which assigning PATH on a command line
+ would not take effect has been fixed.
+06-07-20 Add ksh93 and rksh93 as allowable names for ksh binaries.
+06-07-20 Removed the SHOPT_OO compilation option which was only partially
+ implemented.
+06-07-20 The ability to use egrep, grep, and fgrep expressions within
+ shell patterns has been documented.
+06-07-17 A bug with arithmetic command expressions for locales in which
+ the comma is a thousands separator has been fixed.
+06-07-13 +The default HISTSIZE was increased from 128 to 512.
+06-07-13 A multibyte problem with locales that use shift codes has been fixed.
+06-06-23 A number of bug fixes for command, file, and variable completion
+ have been mode.
+06-06-20 +Floating point division by zero now yields the constant Inf or -Inf
+ and floating functions with invalid arguments yield NaN.
+06-06-20 +The floating point constants Inf and NaN can be used in arithmetic
+ expressions.
+06-06-20 +The functions isinf(), isnan(), tanhl() have been added for
+ arithmetic expressions.
+06-06-13 Internal change to use ordering for variables instead of hashing
+ to speed up prefix matching.
+06-06-13 A window between fork/exec in which a signal could get lost
+ and cause a program to hang has been eliminated
+06-06-13 A bug in edit completion with quoted strings has been fixed.
+06-06-07 The restricted options can now be enabled by set as well as on
+ the command line. Once set, it can not be disabled.
+06-06-04 Modified built-in binding so that for systems for which /bin
+ and /usr/bin are the same, a builtin bound to /bin will get
+ selected when either /bin or /usr/bin is scanned.
+06-06-04 +Added literal-next character processing for emacs/gmacs mode.
+ This change is not compatible with earlier versions of ksh93
+ and ksh88 when the stty lnext is control-v. The sequence
+ escape-control-v will display the shell version.
+06-05-31 +Modified emacs and vi mode so that entering a TAB after a partial
+ TAB completion, generates a listing of possible completions.
+ After the second TAB, a number followed by a TAB will perform
+ the completion with the corresponding item.
+06-05-19 +Modified arithmetic so that conversions to strings default to
+ the maximum number of precision digits.
+06-05-16 Bug fixes for multibyte locales.
+06-05-10 The =~ operator was added to [[...]] and [[ string ~= ERE ]]
+ is equivalent to [[ string == ~(E)ERE ]].
+06-04-25 A bug in the vi edit mode which could cause the shell to core dump
+ when switching from emacs mode.
+06-04-17 A bug in which using LANG or LC_ in assignment lists with builtins
+ did not restore the localed correctly has been fixed.
+06-04-04 A bug in which discipline functions could not be added to variables
+ whose names started with .sh has been fixed.
+06-03-28 +The -s option to typeset was added to modify -i to indicate short
+ integers.
+06-03-28 A bug in which variables assignment lists before functions
+ defined with function name were not passed on the functions
+ invoked by this function has been fixed.
+06-03-28 A bug in which name references defined within a function defined
+ with function name could not be used with compound variables has
+ been fixed.
+06-03-27 A bug in which read <&p (print >&p) would cause the coprocess input
+ (output) pipe to close before reading from (after writing to)
+ it has been fixed.
+06-02-28 A bug in which stopping a job created with the hist builtin command
+ would create a job that could not be restarted has been fixed.
+
+06-01-24 --- Release ksh93r ---
+06-01-24 A bug in which running commands with standard output closed would
+ not work as expected has been fixed.
+06-01-23 A bug in which print -u<n> could fail when file descriptor <n> was
+ open for writing has been fixed.
+06-01-19 The ?: arithmetic operator fixed to work when the operation after
+ the colon was an assignment.
+05-12-24 A bug which could lead to a core dump when elements of a compound
+ variable were array elements, i.e. foo=(bar=(1 2)), has been fixed.
+05-12-13 An arithmetic bug in which x+=y+=z was not working has been fixed.
+05-12-13 An arithmetic bug in which x||y was returning x when x was non-zero
+ rather than 1 has been fixed.
+05-12-07 +The aliases for integer and float have been changed to use attributes
+ -li and -lE to handle long long and long double types.
+05-12-07 +The histexpand (-H) option has been added which allows C-shell
+ style history expansions using the history character !.
+05-12-07 +The multiline option was added which changes that way the edit
+ modes handle lines longer than the window width. Instead of
+ horizontal scrolling, multiple lines on the screen are used.
+05-12-05 The whence builtin now returns an absolute pathname when the
+ command is found in the current directory.
+05-11-29 A bug which caused ksh -c '[[ ! ((' to core dump rather than
+ report a syntax error has been fixed.
+05-11-29 A bug when reading fixed length records into typeset -b variables
+ which caused a zero byte to terminate the value has been fixed.
+05-11-22 +The ability to seek to an offset within a file has been added
+ with the new I/O redirection operators, <# and >#. Currently,
+ these redirection operators must be followed by ((expr))
+ but in a future release, it should be able to used to seek forward
+ to the specified shell pattern. In addition $(n<#) expands to the
+ current byte offset for file descriptor n.
+05-11-22 +The .sh.match array variable is now set after each [[ ... ]]
+ pattern match. Previously it was only set for substring matches.
+05-10-17 A bug in which the library path variable could be prefixed
+ with a directory when a .path file was not encountered in
+ the directory of the executable has been fixed.
+05-09-15 A for/while loop optimizer bug in which $OPTIND was not
+ correctly expanded has been fixed.
+05-09-05 A bug in which a history command that invoked a history
+ command could go into an infinite loop has been fixed.
+05-08-31 +In the case that IFS contains to adjacent new-lines so that
+ new-line is not treated as a space delimiter, only a single
+ new-line is deleted at the end of a command substitution.
+05-08-19 +When a tilde substitution expands to the / directory and is
+ followed by a /, it is replaced by the empty string.
+05-08-16 A bug in which n<&m did not synchronize m has been fixed.
+05-08-16 A bug in which process substitution ( <() and >() ) was not
+ working within for and while loops has been fixed.
+05-07-24 A bug in which the pattern ~(E)(foo|bar) was treated as a syntax
+ error has been fixed.
+05-07-24 A bug in completion with <n>=, where n was the one of the
+ previous selection choices has been fixed.
+05-07-21 A bug with multibyte input when no edit mode was specified which
+ caused the input line to shift left/right has been fixed.
+05-06-24 A race condition which could cause the exit status to get lost
+ on some fast systems has been fixed.
+05-06-21 A bug in which nested patterns of the form {m,n}(pat) would cause
+ syntax errors has been fixed.
+05-06-21 A bug in the macro expander has been fixed which could cause a
+ syntax error for an expansion of the form ${x-$(...)} when
+ x is set and the command substitution contained certain strings.
+05-06-08 +On systems for which echo does not do System V style \ expansions,
+ the -e option was added to enable these expansion.
+05-06-08 A bug in which ${var op pattern} to not work when inside an
+ arithmetic expression has been fixed.
+05-05-23 +An extension to shell patterns that allows matching of nested
+ groups while skipping over quoted strings has been added.
+05-05-18 A bug in which the line number for errors was not correct for
+ functions loaded from FPATH has been fixed.
+05-04-18 A bug in which the exit status $? is not set when a trap triggered
+ by the [[...]] command is executed has been fixed.
+05-04-08 +Redirection operators can be directly preceded with {varname}
+ with no intervening space, where varname is a variable name which
+ allows the shell to select a file descriptor > 10 and store it
+ into varname.
+05-04-08 +SHOPT_CMDLIB_BLTIN=1 now includes <cmdlist.h> generated table.
+05-04-07 +[[ -o ?option ]] is true if "option" is a supported option.
+05-04-05 A bug in handling file completion with spaces in the names
+ has been fixed.
+05-03-25 +The SIGWINCH signal is caught by default to keeps the LINES and
+ COLUMNS variables in sync with the actual window size.
+05-03-25 +Building ksh with SHOPT_REMOTE=1 causes ksh to set --rc if stdin is
+ a socket (presumably part of a remote shell invocation.)
+05-03-25 +Building ksh with SHOPT_SYSRC=1 causes interactive ksh to source
+ /etc/ksh.kshrc (if it exists) before sourcing the $ENV file.
+05-03-25 +{first..last[..incr][%fmt]} sequences added to brace expansions
+ when braceexpand is enabled.
+05-03-03 A bug where a SIGCHLD interrupt could cause a fifo open to fail has
+ been fixed.
+05-02-25 A bug in which a builtin command run in the background could
+ keep a file descriptor open which could cause a foreground
+ process to hang has been fixed.
+05-02-24 A bug where builtin library commands (e.g., date and TZ) failed to
+ detect environment variable changes has been fixed.
+05-02-22 +The read builtin and word splitting are now consistent with respect
+ to IFS -- both treat IFS as field delimiters.
+05-02-22 +The read builtin no longer strips off trailing delimiters that
+ are not space characters when there are fewer variables than fields.
+05-02-17 A builtin bug on systems where dlsym(libcmd) returns link-time
+ bindings has been fixed.
+05-02-12 A bug in which the lib_init() function for .paths BUILTIN_LIB
+ libraries was not called has been fixed.
+05-02-06 A bug on some systems in which moving the write end of a co-process
+ to a numbered file descriptor could cause it to close has been fixed.
+05-02-06 A bug in the vi-edit mode in which the character under the cursor
+ was not deleted in some cases with the d% directive has been fixed.
+05-02-06 A bug where external builtin stdout/stderr redirection corrupted
+ stdout has been fixed.
+05-02-04 A bug where times formatting assumed CLK_TCK==60 has been fixed.
+
+05-01-11 --- Release ksh93q ---
+05-01-11 A bug in the integral divide by zero check has been fixed.
+05-01-11 +The -l option has been added to read /etc/profile and
+ $HOME/.profile, if they exist, before the first command.
+05-01-11 An argument parsing bug that caused `kill -s x -- n' to fail has
+ been fixed.
+05-01-11 +The .paths file, introduced in ksh93m, which can appear in
+ any directory in PATH, now allows a line of the form 'BUILTIN_LIB=.'
+ When a command is searched for this directory, and the full path
+ matches the path of the built-in version of the command (listed
+ by the 'builtin' command) then the built-in version of the command
+ is used. When ksh is built with SHOPT_CMDLIB_DIR=1 then all libcmd
+ functions become builtins with the '/opt/ast/bin/' directory prefix.
+05-01-10 A bug in which a nameref to a compound name caused a core dump has
+ been fixed.
+05-01-09 A bug in which some SIGCHLD interrupts (from child processes exiting)
+ caused a fatal print/echo error diagnostic has been fixed.
+04-12-24 A bug in which some SIGCHLD interrupts (from child processes exiting)
+ corrupted the internal process/job list, sometimes causing the shell
+ to hang, has been fixed.
+04-12-01 A bug in which typeset -Fn truncated less than n digits for large
+ numbers has been fixed.
+04-11-25 A bug in which standard error could be closed after a redirection
+ to /dev/stderr has been fixed.
+04-11-17 A bug in which an expansion of the form ${array[@]:3} could expand
+ to ${array[0]} when ${array[3]} was not set has been fixed.
+04-10-22 +The -E or -orc command line option reads ${ENV-$HOME/.kshrc} file.
+04-10-22 +`-o foo' equivalent to `+o nofoo', `-o nobar' equivalent to `+o bar'.
+ `--foo' equivalent to `-o foo', `--nofoo' equivalent to `+o foo'
+04-10-05 +The .paths file, introduced in ksh93m, which can appear in
+ any directory in PATH, now allows a line of the form
+ 'BUILTIN_LIB=libname'. When a command is searched for this directory,
+ the shared library named by libname will first be searched for a
+ built-in version of the command.
+04-09-03 <<< here documents now handle quotes in the word token correctly.
+04-08-08 +The maximum size for read -n and and read -N was increased from
+ 4095 to 32M.
+04-08-04 +printf %q was modified so that if an no operand was supplied, no
+ no output would be generated rather than a quoted empty string.
+04-08-01 +The -n and -N options of the read builtin has been modified
+ when reading variables with the binary attribute so that the
+ data is stored directly rather than through assignment.
+04-08-01 +The shcomp command has been modified to process alias commands
+ under some conditions.
+04-07-31 +The .sh.match variable added in ksh93l, now works like other
+ indexed arrays.
+04-07-08 A loop optimizer bug which occurs when typeset is used in
+ a for or while loop inside a function has been fixed.
+04-06-24 +The number of subexpressions in a pattern was increased to 64
+ from the current number of 20.
+04-06-17 +The -t option to read was modified to allow seconds to be
+ specified as any arithmetic expression rather than just
+ an integral number of seconds, for example even -t 'sin(.5)'
+ is now valid.
+04-06-16 Two small memory leak problems were fixed.
+04-06-15 A bug in ${var/pattern/"string"} which occurred when string
+ contained pattern matching characters has been fixed.
+04-05-08 printf $'%d\n' produced an erroneous error message and has
+ been fixed.
+04-05-24 A bug in which an associative array without any elements could
+ cause a core dump when a script with an associative array with
+ the same name was declared in a script invoked by name has
+ been fixed.
+04-05-11 A bug in which an exec statement could close the script that
+ is being processed in a script that is run by name causing
+ a failure has been fixed.
+04-04-28 +If the first character of assignment to an integer variable was 0,
+ the variable had been treated as unsigned. This behavior was
+ undocumented and has been removed.
+04-04-05 A bug in which the positioning of standard input could be incorrect
+ after reading from standard input from a subshell has been fixed.
+04-03-30 A bug in the for loop optimizer which in rare cases could cause
+ memory corruption has been fixed.
+04-03-29 +The preset alias source='command .' has been added.
+04-03-29 A bug introduced in ksh93p on some systems in which invoked by
+ name with #! on the first line would not get the signals handling
+ initialized correctly has been fixed.
+04-03-29 A bug introduced in ksh93p in which a HUP signal received by
+ a shell that is a session group leader was not passed down to
+ its children has been fixed.
+
+04-02-28 --- Release ksh93p ---
+04-02-28 +The ability to apply an append discipline to any variable has
+ been added.
+04-02-14 A bug in which the exportall option (set -a) would cause incorrect
+ results for arrays has been fixed.
+04-02-02 A bug in which an exported array would pass more than
+ the first element to a script invoked by name has been fixed.
+04-02-02 A bug on some systems in which name=value pairs preceding a script
+ invoked by name was not getting passed to the script has been fixed.
+04-01-20 A bug in which an unset discipline function could cause a core
+ dump on some systems has been fixed.
+04-01-12 A bug in which a continue or break called outside a loop from
+ inside a function defined with name() syntax could affect
+ the invoking function has been fixed.
+04-01-08 If a command name begins with ~, only filename completion will be
+ attempted rather than pathname completion using the builtin editors.
+04-01-08 A bug in the vi edit mode in which the wrong repeat count on
+ multiple word replacements with the . directive has been fixed.
+04-01-06 Backspace characters are now handled correctly in prompt strings.
+04-01-06 +The getopts builtin has been modified to accept numerical
+ arguments of size long long on systems that support this.
+04-01-06 A bug in which unsetting all elements of an associative array
+ would cause it to be treated as an indexed array has been fixed.
+03-12-15 A bug in which a quoted string ending with an unescaped $ would
+ delete the ending $ in certain cases has been fixed.
+03-12-05 A bug in which the shell could hang when set -x tracing a command
+ when an invalid multibyte character is encountered has been fixed.
+03-12-05 On some systems, if the KEYBD trap is set, then commands that use
+ the meta key were not processed until return was hit. This
+ has been fixed.
+03-12-05 A problem which occurred when the login shell was not a group
+ leader that could cause it to fail has been fixed.
+03-12-05 A problem in which a shell could core dump after receiving a signal
+ that should cause it to terminate while it was in the process
+ of acquiring more space has been fixed.
+03-12-05 +If ENV is not specified, the shell will default to $HOME/.kshrc
+ for interactive shells.
+03-11-21 A bug introduced in ksh93o in which the DEBUG trap could get
+ disabled after it triggered has been fixed.
+03-11-04 A bug in which using arithmetic prefix operators ++ or -- on a
+ non-lvalue could cause a core dump has been fixed.
+03-11-04 A bug in which leading zeros were stripped from variable
+ expansions within arithmetic computation to avoid being treated
+ as octal constants when they should not have, has been fixed.
+03-10-08 A bug introduced in ksh93o in which a large here document inside
+ a function definition could get corrupted has been fixed.
+03-09-22 A bug in which the .get discipline function was not being
+ called when a string variable was implicitly referenced from
+ within a numerical expression has been fixed.
+03-09-22 A bug in which a script without a leading #! could get executed
+ by /bin/sh rather than the current shell on some systems has
+ been fixed.
+03-09-12 +To improve conformance with ksh88, leading zeros will be ignored
+ when getting the numerical value of a string variable so that
+ they will not be treated as octal constants.
+03-09-03 +The builtin kill command now processes obsolete invocations
+ such as kill -1 -pid.
+03-09-02 The restriction on modifying FPATH in a restricted shell (sh -r)
+ has been documented.
+03-09-02 +The restricted shell (sh -r) has been modified to disallow
+ executing command -p.
+03-08-07 A bug in which the KEYBD trap was not being invoked when
+ characters with the 8th bit set has been fixed.
+03-08-02 A parser bug introduced in ksh93o which caused the character
+ after () in a Posix function definition to be skipped
+ when reading from standard input has been fixed.
+03-08-01 A bug in which "${foo#pattern}(x)" treated (x) as if it were
+ part of the pattern has been fixed.
+03-08-01 +The command -x option has been modified so that any trailing
+ arguments that do expand to a single word will be included
+ on each invocation, so that commands like command -x mv * dir
+ work as expected.
+
+03-07-20 --- Release ksh93o+ ---
+03-07-20 A bug in which could cause memory corruption when a posix
+ function invoked another one has been fixed.
+03-07-15 A bug in which a file descriptor>2 could be closed before
+ executing a script has been fixed.
+03-07-15 A parsing error for <() and >() process substitutions inside
+ command substitution has been fixed.
+03-07-15 A parsing error for patterns of the form {...}(...) when
+ used inside ${...} has been fixed.
+03-07-15 An error in which expanding an indexed array inside a compound
+ variable could cause a core dump has been fixed.
+03-07-15 A bug in which on rare occasions a job completion interrupt
+ could cause to core dump has been fixed.
+03-06-26 A bug in which process substitution embedded within command
+ substitution would generate a syntax error has been fixed.
+03-96-23 A bug in which ${@:offset:len} could core dump when there
+ were no arguments has been fixed.
+03-96-23 A bug in which ${X[@]:offset:len} could core dump when X
+ was unset has been fixed.
+03-06-22 +The -x option was added to the command builtin. If this
+ option is on, and the number of arguments would exceed ARG_MAX,
+ the command will be invoked multiple times with a subset of
+ the arguments. For example, with alias grep='command -x grep,
+ any number of arguments can be specified.
+03-06-14 A bug in which could cause a core dump on some systems with
+ vi and emacs editors with the MULTIBYTE option has been fixed.
+03-06-06 A bug in which the shell could core dump when a script was
+ run from its directory, and the script name a symlink to a file
+ beginning with .., has been fixed.
+03-06-05 A bug in which the shell could core dump when a child process
+ that it is unaware of terminates while it is calling malloc()
+ has been fixed.
+03-06-02 +An option named globstar (set -G) has been added. When enabled,
+ during pathname expansion, any component that consists only of ** is
+ matches all files and any number of directory levels.
+03-05-30 A bug in which the PATH search could give incorrect results when
+ run from directory foo and PATH contained .:foo:xxx has been fixed.
+03-05-29 +Some changes were made to the code that displays the prompt in edit
+ mode to better handle escape sequences in the prompt.
+03-05-27 I added = to the list of characters that mark the beginning of
+ a word for edit completion so that filenames in assignments
+ can be completed.
+03-05-20 A bug in which read -N could hang on some systems when reading
+ from a terminal or a pipe has been fixed.
+03-05-19 A bug in which the output of uname from a command substitution
+ would go to the standard output of the invoking command when
+ uname was invoked with a non-standard option has been fixed.
+03-05-19 A job control bug which would cause the shell to exit because
+ it hadn't take back the terminal has been fixed. The bug
+ could occur when running a function that contained a pipeline
+ whose last element was a function.
+03-05-19 A job control timing bug introduced in ksh93o on some systems
+ which could cause a pipeline to hang if the first component
+ completed quickly has been fixed.
+03-05-13 +The read builtin has been modified so that the builtin editors
+ will not overwrite output from a previous incomplete line.
+03-05-13 A bug in which the name of an identifier could have the string
+ .sh. prefixed to it after expanding a variable whose name begins
+ with .sh. has been fixed.
+03-05-13 A bug in the expansion of $var for compound variables in which
+ some elements would not be output when the name was a prefix
+ of another name in the compound variable has been fixed.
+03-05-08 The last item in the ksh93o release on 03-01-02 has been
+ altered slightly to preserve the leading 0's when the
+ preceding character is a digit. Thus, with typeset -LZ3 x=10,
+ $(( 1$x)) will be 1010 whereas $(( $x) will be 10.
+03-04-25 A bug in which if x is a name reference, then nameref y=x.foo
+ did not follow x has been fixed.
+
+03-03-18 --- Release ksh93o ---
+03-03-18 +A -N unary operator was added to test and [[...]] which returns
+ true if the file exists and the file has been modified since it
+ was last read.
+03-03-18 +The TIMEFORMAT variable was added to control the format for
+ the time compound command. The formatting description is
+ described in the man page.
+03-03-06 +A -N n option was added to read which causes exactly n bytes
+ to be read unlike -n n which causes at most n bytes to be read.
+03-03-03 +Three new shell variables were added. The variable .sh.file
+ stores the full pathname of the file that the current command
+ was found in. The variable .sh.fun names the current function
+ that is running. The variable .sh.subshell contains the depth
+ of the current subshell or command substitution.
+03-03-03 +When the DEBUG trap is executed, the current command line after
+ expansions is placed in the variable .sh.command. The trap
+ is also now triggered before each iteration of a for, select,
+ and case command and before each assignment and redirection.
+03-02-28 +Function definitions are no longer stored in the history file so
+ that set -o nolog no longer has any meaning.
+03-02-28 +All function definitions can be displayed with typeset -f not
+ just those stored in the history file. In addition, typeset +f
+ displays the function name followed by a comment containing the
+ line number and the path name for the file that defined this function.
+03-02-28 A bug in which the value of $LINENO was not correct when executing
+ command contained inside mult-line command substitutions has been
+ fixed.
+03-02-19 +Since some existing ksh88 scripts use the undocumented and
+ unintended ability to insert a : in front of the % and # parameter
+ expansion operators, ksh93 was modified to accept :% as equivalent
+ to % and :# as equivalent to # with ${name op word}.
+03-02-14 A bug which could cause a core dump when reading from standard
+ error when standard error was a pty has been fixed.
+03-02-14 +The shell arithmetic was modified to use long double on systems
+ that provide this data type.
+03-02-09 A bug in which a function located in the first directory in FPATH
+ would not be found when the last component of PATH was . and the
+ current directory was one of the directories in PATH has been fixed.
+03-02-07 +The trap and kill builtin commands now accept a leading SIG prefix
+ on the signal names as documented.
+03-02-05 A bug in the expansion of ${var/$pattern}, when pattern contained
+ \[ has been fixed.
+03-02-05 A bug in which .sh.match[n], n>0, was not being set for substring
+ matches with % and %% has been fixed.
+03-01-15 A bug in which getopts did not work for numerical arguments specified
+ as n#var in the getopts string has been fixed.
+03-01-09 A bug in which using ${.sh.match} multiple times could lead to
+ a memory exception has been fixed.
+03-01-06 A bug in the expansion of ${var/pattern/$string} in the case that
+ $string contains \digit has been fixed.
+03-01-02 +A -P option was added for systems such as Solaris 8 that support
+ profile shell.
+03-01-02 For backward compatibility with ksh88, arithmetic expansion
+ with ((...)) and let has been modified so that if x is a zero-filled
+ variable, $x will not be treated as an octal constant.
+
+02-12-05 --- Release ksh93n+ ---
+02-11-30 A bug that can show up in evaluating arithmetic statements that
+ are in an autoloaded function when the function is autoload from
+ another function has been fixed.
+02-11-30 An optimization bug in which an expansion of the form ${!name.@},
+ which occurred inside a for or a while loop, when name is a name
+ reference, has been fixed.
+02-11-18 A bug in which modifying array variables in a subshell could leave
+ side effects in the parent shell environment has been fixed.
+02-11-18 A memory leak when unsetting an associative array has been fixed.
+02-11-14 +The code to display compound objects was rewritten to make
+ it easier for runtime extensions to reuse this code.
+02-11-14 +A change was made to allow runtime builtins to be notified when
+ a signal is received so that cleanup can be performed.
+02-10-31 +User applications can now trap the ALRM signal. Previously,
+ the ALRM signal was used internally and could not be used
+ by applications.
+02-10-31 A bug in which signals received while reading from a coprocess
+ for which traps were set was not handled correctly has been fixed.
+02-10-31 A bug in which a file opened with exec inside a subshell could
+ be closed before the subshell completed has been fixed.
+02-10-21 A bug in which setting PATH or FPATH inside a function might not
+ take effect has been fixed.
+02-10-21 A bug which could cause a core dump when a local SECONDS variable
+ is defined in a function has been fixed.
+02-10-15 A bug in which the associate array name operator ${!array[@]}
+ could return the same name multiple times has been fixed.
+02-10-15 A bug in which the zero'th element of an associative array was
+ not getting set when an assignment was made without a subscript
+ specified has been fixed.
+
+02-09-30 --- Release ksh93n ---
+02-09-30 +The maximum indexed array size was increased to 16Megs.
+02-09-30 A bug which could cause a core dump when changing attributes
+ of associative array has been fixed.
+02-09-30 A bug in which exporting an array variable would not export the
+ 0-th element has been fixed.
+02-09-30 A bug in which an array assignment of the form a=($a ...) would unset
+ 'a' before the right hand side was evaluated has been fixed.
+02-09-27 A bug in which the error message for ${var?message} when var was
+ null or unset did not contain the variable name var has been fixed.
+02-09-27 A bug in which closing file descriptors 0 through 2 could
+ cause a subsequent here document to fail has been fixed.
+02-09-14 A bug in whence which occurs when the specified name contained
+ a / has been fixed.
+02-09-14 A bug in the parser for strings of the form name$((expr))=value
+ has been fixed.
+02-09-14 A for loop optimization bug in which the number of elements in
+ an array was treated as an invariant has been fixed.
+02-09-09 A bug in which redirection or closing of a file descriptor between
+ 3 and 9 could cause a subsequent here document to fail has been
+ fixed.
+02-09-09 A bug in which a background job was not removed from the job list
+ when a subshell completed has been fixed, for example (prog&).
+02-09-03 A bug in which an assignment of the form name=(integer x=3)
+ could be interpreted as an array assignment rather than a
+ compound variable assignment has been fixed.
+02-08-19 A command completion bug which occurred on file systems that
+ are case insensitive has been fixed.
+02-08-19 A bug which could lead to an exception on some systems (for
+ example FREEBSD) which occurred when setting PATH has been fixed.
+02-08-11 A bug in arithmetic rounding in which a value input as a decimal
+ string would output as a rounded version of the string has
+ been fixed.
+02-08-11 A bug in which the last character could be deleted from shell
+ traces and from whence when called from a multibyte locale
+ has been fixed.
+02-08-01 A bug which could cause a core dump to occur when a shell script
+ is executed while a coprocess is running that has closed the
+ output pipe has been fixed.
+02-08-01 A bug in which command completion in multibyte mode could
+ corrupt memory for long command lines has been fixed.
+
+02-06-17 --- Release ksh93n- ---
+02-06-17 A bug in which user defined macros could cause a core dump in
+ with MULTIBYTE mode has been fixed.
+02-06-17 A bug in which printf format specifiers of the form %2$s were causing
+ a core dump has been fixed.
+02-06-17 A bug in which setting stty to noecho mode did not prevent the
+ echoing of characters by ksh when emacs or viraw mode
+ was enabled has been fixed.
+02-06-17 A bug in which background job completion could cause the sleep
+ builtin to terminate prematurely has been fixed.
+02-06-17 A bug in which the shell could core dump if getopts was called
+ when the OPTIND variable contained a negative value has been fixed.
+02-06-10 +The edit mode prompt has been modified to handle escape sequences.
+02-06-10 A bug which occurred for interactive shells in which the builtin
+ cat command was used in command substitution on a file whose
+ size was larger than PIPE_BUF has been fixed.
+02-06-10 A bug in which the trap on ERR was not being processed when
+ set inside a function has been fixed.
+02-06-07 A bug in which function definitions could cause the history count
+ to be decremented by one (and even become negative) has been fixed.
+02-06-05 A bug in read in which share mode could be enabled has been fixed.
+02-05-28 A bug which could occur when the last command of a script was
+ a case statement and the action selected ended in ;& instead of ;;
+ has been fixed.
+02-05-23 A bug with unary + introduced in ksh93k has been fixed.
+02-05-07 A bug in substitutions of the form ${var/pattern/string} in which
+ a backslash was inserted in the replacement string when it contained
+ a special pattern character has been fixed.
+02-05-01 A bug in the emacs edit mode which occurred in versions compiled
+ for multibyte character sets which occurred when a repeated search
+ was requested after a long line had been returned for the previous
+ search has been fixed.
+02-04-02 +vi and emacs edit modes were modified so that tab completion is
+ disabled when invoked from the read built-in.
+
+02-03-26 --- Release ksh93m+ ---
+02-03-26 A bug in which \ was not handled correctly when used in file
+ expansion has been fixed.
+02-02-18 A bug in which lines beginning with a # were deleted from here
+ documents when the here-document delimiter was followed by
+ a comment has been fixed.
+02-12-06 An optimization bug in which ${!x[@]) was treated as invariant in
+ a for loop has been fixed.
+02-02-06 A bug in which the ERR trap is not cleared for a script invoked
+ by name from within a function has been fixed.
+02-01-08 A bug in which a shell script executed from within a subshell
+ could cause this script to have an invalid pointer leading
+ to a memory fault has been fixed.
+02-01-07 +Added here documents of the form <<< word (as per zsh) which
+ is equivalent to << delim\nword\ndelim.
+02-01-07 A bug in which the first word of a compound assignment,
+ x=(word ...), was treated as a reserved word has been fixed.
+02-01-07 A bug in the handling of \ when noglob was enabled and a
+ substitution of the form ${word op pattern} occurred in the
+ same word has been fixed.
+02-01-07 +A compilation option, CMDLIB_BLTIN in the file OPTION, has
+ been added. When this options is set, all commands implemented
+ in libcmd become shell builtin commands by default.
+02-01-07 A bug in which builtin foo, where foo is already a builtin
+ would result in the builtin foo getting removed has been fixed.
+02-01-07 A bug which the shell executed a command found in the current
+ directory when PATH have no valid directories has been fixed.
+01-11-28 The value of $? was not being set when called with exit.
+01-11-28 If the last command was of the form (...) and a trap on EXIT or
+ ERR was set, and the command inside () modified the trap, then
+ 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
+ viraw mode will always be on.
+
+01-10-31 --- Release ksh93m ---
+01-10-31 A for loop optimizer bug for subshells contained withing for
+ loops has been fixed.
+01-10-16 typeset without arguments no longer outputs variable names
+ that do not have any attributes that are set.
+01-10-16 A bug introduced in ksh93l in which assignments specified with
+ the exec built-in were not being expanded properly has been
+ fixed.
+01-10-11 An optimization bug in which ${!x) was treated as invariant in
+ a for loop has been fixed.
+01-10-11 Unsigned integer variables in bases other than 10 are printed now
+ expand in that base with the base prefix.
+01-10-10 A number of typos in the self generating man pages for shell
+ built-ins have been fixed.
+01-10-04 The self generated man pages for hist and fc were not working
+ correctly and have been fixed.
+01-10-03 Yet another optimizer bug in which shell patterns were
+ treated as invariants has been fixed.
+01-09-27 Two bugs relating to multibyte history searches and to find
+ have been fixed.
+01-09-27 A bug introduced in ksh93k in which the PATH searching was
+ not restored after running a command with an assignment list
+ has been fixed.
+01-09-26 A bug in which a zero filled field was treated as octal when
+ converted to integer has been fixed.
+01-09-26 Yet another bug in the optimization of for loops related to
+ recursive functions with break or continue statements has been fixed.
+01-09-25 +The exponentiation operator ** was added to the shell arithmetic
+ evaluation. It has higher precedence than * and is left
+ associative.
+01-09-25 The code was modified to use the ast multibyte macros
+ and functions for handing multibyte locales.
+01-09-25 +The expansion ${parameter:offset:length} now handles negative
+ offsets which cause offsets to be measured from the end.
+01-09-25 Some spelling errors in the documentation were corrected.
+01-09-24 +The /dev/tcp/host/port and /dev/udp/host/port now allow
+ the ports to be specified by service name.
+01-09-24 +The change staring with ksh93g in which the the appropriate
+ library path variable is prepended with a corresponding library
+ directory has been modified. With the new method, only the
+ library path defined in the file named .paths in the directory
+ where the executable is found will be modified. See the
+ man page for more details.
+01-09-23 +The .fpath file (see ksh93h) is no longer looked for in each
+ directory on the path to locate function directories. The
+ file named .paths is used instead.
+01-09-23 A bug in which IFS was not being restored after being changed in
+ a subshell has been fixed.
+01-09-16 +With the vi and emacs edit modes, after a list of command
+ or functions is generated with = or M-= respectively,
+ any element from the list can be pasted on the command line
+ by preceding the = or M-= with a numeric parameter specifying
+ the position on the list.
+01-09-16 A bug in ksh93l caused command completion not to find aliases
+ and functions. Command listing from the edit mode was presented
+ in reverse order. This has been fixed.
+01-09-13 Another bug in the optimization of for loops related to subshells
+ when traps were set has been fixed.
+01-09-07 A change in ksh93l caused brace expansion to stop working
+ and this has been fixed.
+01-09-04 A bug introduced in ksh93k in which an arithmetic statement
+ within a function that used name references did not follow the
+ reference has been fixed.
+01-09-04 A bug introduced in ksh93l in which export -p did not prefix
+ each export with the word export has been fixed.
+01-08-29 A bug in multibyte input which occurred when a partial multibyte
+ character was received has been fixed.
+01-08-29 A bug introduced in ksh93l which could cause a core dump
+ when an assignment list containing PATH is specified inside
+ command substitution has been fixed.
+01-08-09 Another bug in the optimization of for loops in ksh93l caused
+ errors in recursive functions using local variables that
+ contained for loops has been fixed.
+01-07-27 A bug in which IFS would be unset after a command substitution
+ inside a here document has been fixed.
+01-07-26 To conform to the POSIX standard, if you invoked ksh name,
+ and name does not contain a /, it will first try to run
+ one in the current directory whether it is executable or not
+ before doing a path search for an executable script. Earlier
+ versions first checked for an executable script using the
+ PATH variable.
+01-07-23 A bug in which unset -f invoked in a subshell could unset a
+ function defined in the parent has been fixed.
+01-07-16 A bug in the optimization of for loops in ksh93l caused
+ name references to be treated as invariants has been fixed.
+01-07-09 A bug in which a discipline function applied to a local variable
+ could cause a shell exception has been fixed. Discipline
+ functions can only be specified for global variables.
+
+01-06-18 --- Release ksh93l ---
+01-06-18 A bug in assigning integers larger than can be represented as
+ long integers to floating point variables has been fixed.
+01-06-18 A bug in the handling of unsigned integers (typeset -ui) has
+ been fixed.
+01-06-04 The evaluation of the PS1 prompt no longer effects the value
+ of the $? variable.
+01-06-01 A small memory leak from subshells has been fixed.
+01-05-22 A bug in which attributes for variables that did not have
+ values would be lost after a subshell has been fixed.
+01-05-22 +The %R format has been added to convert a shell pattern into
+ an extended regular expression.
+01-05-22 +The escape sequences \e, \cX, \C[.collating-element.], and
+ \x{hex} have been added to ASCII-C strings and to printf format
+ strings.
+01-05-20 +Patterns of the form {n}(pattern) and {m,n}(pattern) are now
+ recognized. The first form matches exactly n of pattern whereas,
+ the second form matches from m to n instances of pattern.
+01-05-20 +The shell allows *-(pattern), +-(pattern), ?-(pattern),
+ {m,n}-(pattern}, and @-(pattern) to cause the minimal
+ match of pattern to be selected whenever possible rather
+ than the maximal (greedy) match.
+01-05-20 +The character class [:word:] has been added to patterns.
+ The word class is the union of [:alnum:] and the character _.
+01-05-20 +Inside (...) pattern groups, the \ character is now treated
+ specially even when in an enclosing character class. The
+ sequences, \w, \d, \s are equivalent to the character classes
+ word, digit, and space respectively. The sequences \W, \D,
+ and \S are their complement sets.
+01-05-20 +The shell now recognizes pattern groups of the form
+ ~(options:pattern) where options or :pattern can be omitted.
+ Options use the letters + and - to enable and disable options
+ respectively. The option letters g (greedy), i (ignore case)
+ are used to cause maximal matching and to cause case
+ insensitive matching respectively. If :pattern is also
+ specified, these options are only in effect while this
+ pattern is being processed. Otherwise, these options remain
+ in effect until the end of the pattern group that they are contained
+ in or until another ~(...) is encountered. These pattern groups
+ are not counted with respect to group numbering.
+01-05-14 When edit completion, expansion, or listing occurs in the
+ middle of a quoted string, the leading quote is ignored when
+ performing the completion, expansion, or listing.
+01-05-14 A small memory leak from subshells has been fixed.
+01-05-10 A bug in which open files were not restored after a subshell
+ that had used exec to replace a file has been fixed.
+01-05-10 +Redirection to a null file name now generates an error message.
+01-05-09 The shell now rejects some invalid parameter substitutions that
+ were previously processed in undefined ways.
+01-05-09 A bug in which the output of select was not flushed before the
+ read when input did not come from the terminal has been fixed.
+01-05-08 A bug in which job ids would not be freed for interactive shells
+ when subshells ran built-ins in the background has been fixed.
+01-05-08 +The FPATH variable now requires an explicit . to cause the
+ current directory to be treated as a function directory.
+01-05-08 A bug in read -n when echo mode was disabled has been fixed.
+01-05-07 A bug in which function definitions could be listed as part
+ of the history has been fixed.
+01-04-30 +This release uses a new and often much faster pattern matcher than
+ earlier releases.
+01-04-30 +An optimizer now eliminates invariant parameter expansions from
+ for while and until loops.
+01-04-30 +The variable .sh.match is set after each pattern match (# % or /)
+ in a variable substitution. The variable .sh.match is an
+ indexed array with element 0 being the complete match.
+ The array is only valid until the next subsequent pattern
+ match or until the value of the variable changes which ever
+ comes first.
+01-04-30 +A self generating man page has been added to shcomp. Also,
+ shcomp now stops compiling when it finds an exit or exec
+ command and copies the remainder so that it can be used
+ for standard input.
+01-04-30 +The shcomp command was modified so that it can work in an
+ EBCIDIC environment and that binary scripts are portable
+ across environments.
+01-04-30 A bug in the handling of a trailing : in PATH has been fixed.
+01-04-30 A bug in which the builtin version of a command would get invoked
+ even though the full pathname for the command was specified
+ has been fixed.
+01-04-30 A bug in which read would loose the last character when
+ reading the last line of a file that did not contain a new-line
+ character has been fixed.
+01-04-23 A bug on some systems in which in vi mode the end of file
+ character and end of line character could be swapped has
+ been fixed.
+01-04-23 A bug on some systems in which invoking a shell script that
+ did not have execute permission could set the exit value to
+ 127 rather than 126 has been fixed.
+01-04-20 A bug in which read -n from a pipe would block if fewer than
+ n characters was received has been fixed.
+01-04-09 A bug in which invalid patterns, for example, ) by itself,
+ was not treated as a string has been fixed so that if i=')',
+ then [[ $i == $i ]] is true.
+01-04-09 +The shell arithmetic now interprets C character constants.
+01-04-09 A bug in which a non-zero return from a function defined
+ with the function reserved word did not trigger the ERR
+ trap or exit with set -e has been fixed.
+01-04-02 A bug on some systems, in which characters above 127 were
+ not displayed correctly in vi or emacs edit mode has been fixed.
+01-04-02 A bug on some systems, introduced in the 'k' point release, in
+ which the erase character in viraw mode was moving the cursor
+ to the left without erasing the character has been fixed.
+01-04-02 On some systems the wcwith() function was returning a wrong
+ value for characters and caused characters to be displayed
+ incorrectly from the shell edit modes. A work around for
+ this problem has been added.
+01-03-26 A bug in which valid scripts could produce syntax errors
+ when run with locales that considered characters such as "'"
+ to be space characters has been fixed.
+01-03-20 A bug in which an syntax error in an arithmetic expression
+ entered interactively could cause the shell to go into
+ an infinite loop outputting the error message has been fixed.
+01-03-10 +ksh93 accepts -l as a synonym for -L in test on systems for
+ which /bin/test -l tests for symbolic links.
+01-03-10 A bug in parsing scripts in which { and } are used in place of
+ in and esac in case statements embedded in compound commands
+ has been fixed. Use of { and } for in and esac is obsolete.
+01-03-06 A bug in which an argument of the form foo=bar was not
+ being passed correctly to a traced function whose name
+ was foo has been fixed.
+01-03-02 Using $(trap -p name) did not print the name of the current
+ trap setting for trap name.
+01-02-26 Exported floating point variables gave incorrect results
+ when passing them to ksh88. This has been fixed.
+01-02-25 A race condition in which a coprocess which completed too quickly
+ would not allow subsequent coprocesses to start has been fixed.
+01-02-25 The 'g' format specifier is now handled by printf. It had
+ inadvertently been omitted.
+01-02-20 The + was not being displayed during an execution trace
+ with the += assignment operator.
+01-02-19 The error message which occurs when the interpreter name
+ defined on the #! line does not exist is more informative.
+01-02-19 A bug in which $0 would not be set correctly when a
+ script with #! was invoked by full pathname from the
+ directory of the script has been fixed.
+01-02-19 A shell script did not always pick up tty mode changes
+ made by external commands such as stty which could
+ effect the behavior of read.
+01-02-19 The -u, -g, and -k unary tests did not give the correct
+ results when used with negation and this has been fixed.
+
+01-02-05 --- Release ksh93k+ ---
+01-02-05 The sequence \<newline> inside $'...' was not incrementing
+ the line count and this has been fixed.
+01-02-05 +Modified expansion of "${@-}" so that if no arguments are set
+ it results in null string rather than nothing.
+01-02-02 memory leak problem with local variables in functions fixed.
+01-01-25 +allow arithmetic expressions with float%int and treat them
+ as ((int)float)%int rather than as an error.
+01-01-19 read -n1 was not working and has been fixed.
+01-01-17 +ksh now handles the case in which a here document in command
+ substitution $() is terminated by the trailing ). Previously,
+ a new-line was needed at the end of the delimiter word.
+01-01-02 A bug in which a KEYBD trap would cause a multi-line token
+ to be processed incorrectly has been fixed.
+00-12-10 +Arithmetic integer constants can now have L and U suffices.
+00-12-10 A bug in the processing of arithmetic expressions with compound
+ variables when the -n option is on has been fixed.
+00-12-08 A bug in M-f and M-b from emacs mode has been fixed. This
+ bug only occurs when ksh93 is compiled without MULTIBYTE enabled.
+00-11-29 A bug in which jobs -p would yield 0 for background
+ jobs run in a script has been fixed.
+00-11-21 A bug in integer arrays in which the number of elements is
+ incorrect when the ++ operator is applied to a non-existing
+ element has been fixed. For example, integer x; ((x[3]++)).
+00-11-20 A timing bug in which the shell could reset the terminal
+ group to the wrong value in the case that the a new process
+ changes the terminal group during startup has been fixed.
+
+00-10-27 --- Release ksh93k ---
+00-10-27 Using tab for completion now works only when applied
+ after a non-blank character at the end of the current line.
+ In other case a tab is inserted.
+00-10-27 A bug in the emacs edit mode for ^X^E has been fixed.
+ The ^X^E sequence is supposed to invoke the full editor
+ on the current command.
+00-10-18 A bug in which expansions of the form ${var//pattern/string}
+ did not work correctly when pattern was '/' or "/" has
+ been fixed.
+00-10-18 +The output format for indexed arrays in compound variables
+ has been modified so that it can be used as input.
+00-10-18 Assignments with name references (typeset -n) will now
+ implicitly unreference an existing name reference.
+00-10-17 A bug the += append operator when a single array element
+ is appended to a variable that is not an array has been fixed.
+00-10-16 A bug in which the SIGCONT signal was being sent to
+ each process will kill -0 or kill -n 0 has been fixed.
+00-10-12 +The arithmetic evaluation portion has been rewritten to
+ perform a number of optimizations.
+00-10-10 A bug in which name prefix matching ${!name.*} was not
+ checking name to see if it was a name reference has been fixed.
+00-09-26 A bug in the multibyte version in which the width of for
+ non-printing characters was not correct has been fixed.
+00-09-12 +Made changes to get multibyte editing work on UWIN for windows
+00-09-12 A bug in which multibyte characters would be displayed incorrectly
+ has been fixed.
+00-08-08 Removed build dependency on iswprint() and iswalph().
+00-07-20 In some cases the read builtin would read more than a single
+ line from a pipe on standard input and therefore leave the seek
+ position in the wrong location.
+00-07-05 +If the directory / is on the path, a / will not be inserted
+ between the directory and the file name during path searching
+ to avoid searching // for systems that treat this specially.
+00-06-26 A bug in which on rare occasions wait could return before all
+ jobs have completed has been fixed.
+00-06-21 A bug in which backspace did not work correctly during the
+ R replace directive in vi-mode has been fixed.
+00-06-12 +Added variable name completion/expansion/listing to the set of
+ completions. Variable name completions begin with $ or "$ followed
+ by a letter.
+00-05-09 --- Release ksh93j ---
+00-05-09 Modified command substitution to avoid using /tmp files when
+ run on read-only file systems.
+00-04-17 +Modified printf to handle '%..Xc' and '%..Xs' options where X
+ is not an alpha character. Previous versions core dumped with this.
+00-04-10 +Changes to multibyte editing code were made to use standard
+ ISO C functions rather than methods devised before the standard.
+00-04-09 Add %H options to printf to output strings with <"'&\t> properly
+ converted for use in HTML and XML documents.
+00-04-07 +Modified getopts builtin to handle \f...\f in usage string
+ by invoking specified function.
+00-04-04 Added self generating man pages for bg, fc, fg, disown, jobs,
+ hist, let, ., and ulimit.
+00-03-30 +The append operator += has been added and can be used
+ for all assignments, strings, arrays, and compound variables.
+00-03-30 +Code was modified in several places to support automatic
+ generation of C locale dictionaries.
+00-03-28 A bug in which the set and trap commands invoked with --name
+ type arguments would terminate the invoking script has
+ been fixed.
+00-03-27 A bug in which the library path variable was not updated
+ correctly on some systems as described in the 'g' point
+ release has been fixed.
+00-03-07 printf now returns a non-zero exit status when one of
+ its arguments cannot be converted to the given type.
+00-03-05 The return value and error message for a command that
+ was found on the path but was not executable was set
+ incorrectly.
+00-03-05 A prototype for ioctl() was removed from the vi edit mode.
+
+00-01-28 --- Release ksh93i ---
+00-01-28 +Most of the built-in commands and ksh itself are now
+ self documenting. Running command --man will produce
+ screen output. Running command --html produces the
+ man page in html format.
+00-01-28 +The getopts builtin can process command description
+ strings to produce man pages.
+00-01-28 A bug in which a script could terminate when getopts
+ encountered an error when invoked inside a function
+ has been fixed.
+00-01-28 When a symbolic link was specified as the name of
+ the script to invoke by name, the value of $0 was
+ set to the real file name rather than the link name
+ in some cases and this has been fixed.
+00-01-28 A bug in which the precision given as an argument
+ to printf was not working has been fixed.
+
+99-03-31 --- Release ksh93h ---
+99-03-31 +The PATH search algorithm has been modified to look
+ for a file named .fpath in each bin directory and if
+ found, to search for functions in this directory if
+ it cannot find the command in that directory.
+99-03-31 +When performing pathname expansion, the shell checks
+ to see whether each directory it reads is case sensitive
+ or not, and performs the matching accordingly.
+99-03-31 +The %T format for printing formatted date/time.
+99-03-31 +The emacs and vi modes now handle arrow keys when
+ they use standard ANSI escape sequences.
+99-03-31 +The TAB key can be used for completion in emacs and viraw mode.
+99-03-31 A bug in setting .sh.editchar during the KEYBD trap
+ for the MULTIBYTE option was fixed in release ksh93h.
+99-03-31 A bug in shcomp for compilation of unary operators with [[...]]
+ has been fixed.
+99-03-31 A bug in which the value of $? was changed when executing
+ a keyboard trap has been fixed.
+99-03-31 The handling of SIGCHLD has been changed so that the
+ trap is not triggered while executing trap commands
+ to avoid recursive trap calls.
+99-03-31 A bug in which a local variable in a function declared readonly
+ would generated an error when the function went out of
+ scope has been fixed.
+99-03-31 A bug in which \<new_line> entered from the keyboard
+ with the KEYBD trap enabled has been fixed.
+99-03-31 The error message for a misplaced ((, for example print ((3),
+ was often garbled and has been fixed.
+99-03-31 A bug in the KEYBD trap in which escape sequences of the form
+ <ESC>[#~ were not being handled as a unit has been fixed.
+99-03-31 A bug in which ksh would consider expressions like [[ (a) ]]
+ as syntax errors has been fixed.
+99-03-31 A function defined as foo() without a function body
+ was not reported as a syntax error.
+99-03-31 A bug in which ksh could run out of file descriptors when
+ a stream was repeatedly opened with exec and read from
+ has been fixed.
+
+98-04-30 --- Release ksh93g ---
+98-04-30 +The pipefail option has been added. With pipefail
+ enabled, a pipeline will not complete until all
+ commands are complete, and the return value will
+ be that of the last command to fail, or zero if
+ all complete successfully.
+98-04-30 +The name-value pair library uses the cdt library rather
+ than the hash library. This change should be transparent
+ to applications.
+98-04-30 +On the U/WIN version for Window 95 and Windows NT,
+ when a directory beginning with a letter followed by
+ a colon is given to cd, it is assumed to be an absolute
+ directory
+98-04-30 +When an executable is found on a given path,
+ the appropriate library path variable is prepended
+ with a corresponding library directory.
+98-04-30 A bug in which a name reference could be created to
+ itself and later cause the shell to get into an infinite
+ loop has been fixed.
+98-04-30 A bug in shcomp relating to compound variables was fixed.
+98-04-30 A bug introduced in ksh93e in which leading 0's in -Z
+ fields caused the value to be treated as octal for arithmetic
+ evaluation has been fixed.
+98-04-30 A bug when a name reference with a shorter name than
+ the variable it references was the subject of a compound
+ assignment has been fixed.
+98-04-30 A bug which in which assignment to array variables in
+ a subshell could effect the parent shell has been
+ fixed.
+98-04-30 read name?prompt was putting a 0 byte at the end of the
+ prompt on standard error.
+98-04-30 A bug in [[ string1 > string2 ]] when ksh was run with -x
+ has been fixed.
+98-04-30 A bug in which the escape character was not processed
+ correctly inside {...} when brace expansion is enabled
+ has been fixed, for example {\$foo}.
+98-04-30 A bug in line continuation in here-documents has been
+ fixed.
+98-04-30 The default base when not specified with typeset -i is
+ 10 in accordance with the documentation. Previously,
+ the value was determined by the first assignment.
+98-04-30 A parsing bug in which a # preceded alphanumeric
+ characters inside a command substitution caused
+ a syntax error to be reported has been fixed.
+98-04-30 A bug in which a decimal constant represented as 10#ddd
+ where ddd was more than five digits generated a syntax
+ error has been fixed.
+98-04-30 A bug in here document expansion in which ${...} expansions
+ were split across buffer boundaries has been fixed.
+98-04-30 +The sh_fun() function now takes third argument which
+ is an argument list for the invoked discipline function
+ or built-in.
+98-04-30 +A callback function can be installed which will give
+ notification of file duplications and file closes.
+98-04-30 When ksh is compiled on systems that do not use fork()
+ current option settings where not propagated to sub-shells.
+
+97-06-30 --- Release ksh93f ---
+97-06-30 +Hostnames in addition to host addresses can be given in
+ /dev/tcp/host/port virtual file names.
+97-06-30 File name completion and expansion now quotes special
+ characters in file names from both emacs and vi edit modes.
+97-06-30 An empty for list behave like a for list with null expansions.
+ It produces a warning message with sh -n.
+97-06-30 +The code has been modified to work with EBCDIC as well as ASCII.
+97-06-30 A bug which would cause the secondary prompt to be
+ displayed when a user entered a literal carriage
+ return has been fixed.
+97-06-30 A bug which caused ksh read -s name to core dump was
+ fixed.
+97-06-30 A bug with the expansion of \} and \] inside double
+ quoted strings that also contained variable expansions
+ has been fixed
+97-06-30 Changes in the ksh93e point release caused autoload
+ functions invoked from within command substitution
+ to fail. This has been fixed.
+97-06-30 A bug in the processing of here-documents that could
+ prevent variable substitution to occur after $(...) command
+ substitution for long here documents has been fixed.
+97-06-30 A bug caused by a race condition that could cause SIGTERM
+ to be ignored by a child process has been fixed.
+97-06-30 A bug which prevented the startup of a coprocess immediately
+ after killing a running coprocess has been fixed.
+97-06-30 ulimit foobar, where foobar is not an arithmetic
+ expression, now gives an error message as it did with ksh88
+ instead of setting the file size limit to 0.
+97-06-30 A bug which could cause an interactive shell to terminate when
+ the last process of a pipeline was a POSIX function was fixed.
+97-06-30 A bug which could cause command substitution of a shell script
+ to core dump has been fixed.
+97-06-30 A security hole was fixed in suid_exec.
+97-06-30 Arithmetic functions such as pow() that take more than
+ one argument, did not work if arguments other than the
+ first contained parenthesized sub-expression.
+97-06-30 The error message from a script containing an incomplete
+ arithmetic expression has been corrected.
+97-06-30 A bug which caused a core dump on some machines when
+ the value of a name reference contained a positional
+ parameter and the name reference was not defined inside
+ a function has been fixed.
+97-06-30 Arithmetic expressions now correctly handle hexadecimal
+ constants.
+97-06-30 A bug in which integer variables could be expanded
+ with a leading 10# when declared with typeset -i
+ multiple times has been corrected.
+97-06-30 A bug in which IFS wasn't correctly restored when
+ set within command substitution has been fixed.
+97-06-30 The _ character is now considered as part of a word
+ with the M-f and M-b emacs directives as it was in ksh88.
+97-06-30 A bug in brace pattern expansions that caused expressions
+ such as {foo\,bar,bam} to expand incorrectly have been fixed.
+
+
+96-07-31 --- Release ksh93e ---
+96-07-31 +The math functions, atan2, hypot, fmod, and pow were added.
+96-07-31 +When a shared library is loaded, if the function lib_init()
+ is defined in the library, it is invoked the first time that
+ the library is loaded with builtin -f library.
+96-07-31 The k-shell information abstraction database option, KIA,
+ has been revamped.
+96-07-31 Empty command substitutions of the form $() now work.
+ whence -v foo now gives the correct result after calling
+ builtin -d foo.
+96-07-31 A bug in right to left arithmetic assignment for which
+ the arithmetic expression (( y = x = 1.5 )) did not
+ yield 1 for y when x was declared typeset -i was fixed.
+96-07-31 printf has been fixed to handle format containing \0
+ and/or \0145 correctly. In addition, characters following
+ %b in the format string are no longer displayed when
+ the operand contains \c.
+96-07-31 A bug in printf that could cause the %E format to
+ produce unnormalized results has been fixed.
+96-07-31 A bug which causes some arithmetic expressions to be
+ incorrectly evaluated as integer expressions rather
+ that floating point has been fixed.
+96-07-31 Functions defined inside a subshell no longer remain
+ defined when the subshell completes.
+96-07-31 The error message from sh -c ';echo foo' has been
+ corrected.
+96-07-31 The format for umask -S has been changed to agree
+ with the specification in the POSIX standard.
+96-07-31 A bug that caused side effects in subscript evaluation
+ when tracing was enabled for subscripts using ++ or --
+ has been fixed.
+96-07-31 To conform to the Posix standard getopts has been changed
+ so that the option char is set to ? when it returns with
+ a non-zero exit status.
+96-07-31 The handling of \} inside ${name...} has been fixed so
+ that the \ quotes the }.
+96-07-31 A bug that caused the read builtin to resume execution
+ after processing a trap has been fixed.
+96-07-31 [[ -s file ]] has been fixed so that if file is open
+ by ksh, it is flushed first.
+96-07-31 In some cases attributes and sizes for non exported
+ variables weren't being reset before running a script.
+96-07-31 The value of TMOUT was affected by changes make to
+ it in a subshell.
+96-07-31 The jobs command did not reflect changes make by
+ sending the CONT signal to a command.
+96-07-31 The error message for ksh -o unknown was incorrect.
+96-07-31 Functions invoked as name=value name, did not use
+ values from the calling scope when evaluating value.
+96-07-31 A bug in which the shell would reexecute previously
+ executed code when a shell script or coprocess was
+ run in the background has been fixed.
+96-07-31 A bug in which an empty here-document would leave
+ a file descriptor open has been fixed.
+96-07-31 A bug in which $(set -A array ...) would leave a
+ side effect has been fixed.
+96-07-31 A discipline function for a global variable defined
+ within a function defined with the function keyword,
+ incorrectly created a local variable of the same name
+ and applied the discipline to it.
+
+95-08-28 --- Release ksh93d ---
+95-08-28 The \ character was not handled correctly in replacement
+ patterns with ${x/pattern/replace}.
+95-08-28 A bug with read in which the line did not end with
+ a new-line has been fixed.
+95-08-28 A bug in file name generation which sometimes
+ appended a . for filenames that ended in / has
+ been fixed.
+95-08-28 +If a process is waited for after a status has
+ been returned by a previous wait, wait now
+ returns 127.
+95-08-28 A bug with hist (fc) -e which prevented a command
+ to re-executed after it had been edited has been fixed.
+95-08-28 A bug which prevented quoting from removing the meaning
+ of unary test operators has been fixed.
+95-08-28 A bug with typeahead and KEYBOARD traps with the
+ MULTIBYTE option set has been fixed.
+95-08-28 +Builtin functions can take a third argument which is
+ a void*.
+95-08-28 The nv_scan() function can restrict the scope of a walk
+ to the top scope.
+
+95-04-31 --- Release ksh93c ---
+95-04-31 The expansion of "$@" was incorrect when $1 was the null
+ string.
+95-04-31 A bug which could incorrectly report a syntax error in
+ a backquoted expression when a $ was preceded by \\
+ has been fixed.
+95-04-31 A bug which prevented the shell from exiting after
+ reporting an error when failing to open a script
+ has been fixed.
+95-04-31 A bug that could lead to memory corruption when a
+ large here document that required parameter or command
+ substitution was expanded has been fixed.
+95-04-31 A bug that could cause a core dump on some systems
+ after ksh detected an error when reading a function
+ has been fixed.
+95-04-31 A bug which could cause a coprocess to hang when
+ reading from a process that has terminated has been fixed.
+95-04-31 A bug which caused a script to terminate when set -e
+ was on and the first command of and && or || list
+ failed has been fixed.
+95-04-31 A bug with here documents inside $(...) when the delimiter
+ word is an identifier has been fixed.
+95-04-31 A bug which caused $0 to display the wrong value when
+ a script was invoked as an argument to the . command
+ and the eval command has been fixed.
+95-04-31 A bug that could cause the built-in sleep to hang
+ has been fixed.
+95-04-31 A bug introduces in 12/28/93b which caused the backslash
+ to be removed when it was followed by digit inside double
+ quotes in some instances has been fixed.
+95-04-31 A bug which could cause a core dump if ksh was invoked with
+ standard input closed has been fixed.
+95-04-31 A bug which could cause a core dump if typeset -A was
+ specified for an existing variable has been fixed.
+95-04-31 Variables that were unset but had attributes such as readonly
+ and export were not listed with readonly, export and typeset.
+95-04-31 Several problems with signals have been fixed.
+95-04-31 A bug which prevented ulimit -t from working has been fixed.
+ Also, a bug in which failed ulimits could cause a core dump
+ has also been fixed.
+95-04-31 A bug in expansion of the form ${name/#pattern/string} and
+ ${name/%pattern/string} has been fixed.
+95-04-31 A bug which caused read -r on a line that contained only
+ blanks to get a non-null value has been fixed.
+95-04-31 A bug introduced in the 'a' point release in which
+ ${x='\\'} expanded to \ when x was unset has been fixed.
+95-04-31 A bug which prevented a trap on EXIT from being executed
+ when the last command in a script was a function invocation
+ has been fixed.
+95-04-31 A bug which caused an interactive shell ignore input when
+ standard error was redirected to a file with exec,
+ and then restored with exec 2>&1 has been fixed.
+95-04-31 An interactive shell turns on monitor mode even when
+ standard error has been redirected to a file.
+95-04-31 A bug which could cause standard input to be incorrectly
+ positioned for the last command of a script has been fixed.
+95-04-31 A bug in the edit modes which allowed walking back in
+ the history file for more than HISTSIZE commands has
+ been fixed.
+95-04-31 A bug which could cause a core dump if variable TMPDIR was
+ changed between two command substitutions has been fixed.
+95-04-31. A bug which prevented a trap on EXIT from being cleared
+ has been fixed.
+95-04-31 A bug fixed for the v directive in vi MULTIBYTE has been
+ fixed.
+95-04-31 Code to for IFS handling of multibyte characters has
+ been added.
+95-04-31 The displaying of multibyte strings in export, readonly,
+ typeset, and execution traces has been fixed.
+95-04-31 Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+95-04-31 Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+95-04-31 A few changes have been made to the name-value library
+ that affect built-ins that use disciplines. The
+ changes allow disciplines to be shared by variables
+ and should make it possible to add new disciplines
+ without recompilation.
+95-04-31 +The name-value library interface has undergone significant
+ change for this revision. See the new nval.3 man page.
+
+94-12-31 --- Release ksh93b ---
+94-12-31 +Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+94-12-31 +If IFS contains two consecutive identical characters belonging
+ to the [:space:] class, then this character is treated as
+ a non-space delimiter so that each instance will delimit
+ a field. For example, IFS=$'\t\t' will cause two consecutive
+ tabs to delimit a null field.
+94-12-31 +The getopts command has a -a name option that specifies a
+ name that will be used for usage messages.
+94-12-31 A bug which caused unset RANDOM to dump core has been
+ fixed.
+94-12-31 A bug which prevented return for terminating a profile
+ or ENV file has been fixed.
+94-12-31 A bug which prevented standard input from being
+ directed to /dev/null for background jobs when
+ monitor mode was turned off has been fixed.
+94-12-31 Statements of the form typeset -options var[expr]=value
+ did not perform substitutions on expr as expected.
+94-12-31 A bug which prevented the shell from sending a HUP
+ signal to some background jobs that were not disowned
+ has been fixed.
+94-12-31 A bug which allowed a script to trap signals that are
+ ignored at the time that the shell was invoked by exec
+ has been fixed.
+94-12-31 A bug which could cause a core dump when a discipline
+ function was unset within a discipline was fixed.
+94-12-31 The typeset builtin now accepts a first argument of
+ + or - for compatibility with ksh88.
+94-12-31 For compatibility with ksh88, the results of expansions
+ of command arguments will treat the extended character
+ match characters ()|& as ordinary characters.
+94-12-31 A bug which caused read to fail on a file that was
+ open for read/write with <> when the first operation
+ was print or printf has been fixed.
+94-12-31 When a job is suspended, it is put on the top of
+ the job list as required by the POSIX standard.
+94-12-31 The value of OPTARG when an option that required
+ an argument but didn't have one was incorrect in the
+ case the the option string began with a :.
+94-12-31 A bug which caused the terminal to get into a bad
+ state with some KEYBD traps in vi-mode has been fixed.
+94-12-31 A bug which caused an invalid trap to cause a script
+ to terminate, rather than just return an error, has
+ been fixed.
+94-12-31 Backreferencing sub-expressions in patterns and replacement
+ strings now works.
+94-12-31 A bug in chmod which caused the -R option to fail has
+ been fixed.
+94-12-31 +More signal names have been added for Solaris
+
+94-06-30 --- Release ksh93a ---
+94-06-30 An expansion bug which causes portions of a word after
+ a $((...)) expansion that contains a nested $var expansion
+ to be lost has been fixed.
+94-06-30 A bug that caused a core dump when a script that did not
+ have PWD set and did a cd inside command substitution
+ has been fixed.
+94-06-30 A bug which caused a core dump on some machines when
+ the LANG variable was assigned to has been fixed.
+94-06-30 A bug which incorrectly handled set disciplines that
+ performed arithmetic evaluation when the discipline
+ was called from the arithmetic evaluator has been fixed.
+94-06-30 A bug caused by an EXIT trap inside a function that
+ was executed in a subshell was fixed.
+94-06-30 If foo is a function, and not a program, then command foo
+ now reports that foo isn't found rather than invoking foo.
+94-06-30 The previous version incorrectly listed -A as an
+ invocation option. The -A option is only for set.
+94-06-30 A bug was fixed which caused ksh to loop when execution trace
+ was enabled and the PS4 prompt required command substitution.
+94-06-30 A bug which could cause the job control switch character
+ to be disabled when a script that enabled monitor mode
+ terminated was fixed.
+94-06-30 A bug in the macro expansion global replacement operator //,
+ when the pattern began with a [ or +( has been fixed.
+94-06-30 A bug which prevented ~ expansion from occurring when
+ it was terminated with a colon inside an assignment
+ has been fixed.
+94-06-30 A bug in the dot command which prevented autoload functions
+ from working has been fixed.
+94-06-30 A bug which caused a variable to be unset if the
+ its value were expanded inside a set discipline has
+ been fixed.
+94-06-30 Whence -a now longer reports that a defined function
+ is undefined.
+94-06-30 A bug on some systems in which $0 would be incorrect
+ in scripts invoked by name has been fixed.
+94-06-30 Here documents with an empty body now work.
+94-06-30 A bug which disabled argument passing and resetting
+ of options for a script invoked by name inside a
+ function has been fixed.
+94-06-30 A bug in which an EXIT trap set the caller of a function
+ would be executed if a command called inside a function
+ was not found has been fixed.
+94-06-30 A bug which allowed a script to trap signals that are
+ ignored at the time that the shell was invoked has
+ been fixed.
+94-06-30 A bug which caused 2<&1- when applied to a shell built-in
+ to leave standard input closed has been fixed.
+94-06-30 A bug which caused the shell to incorrectly parse
+ $() command substitutions with nested case statements
+ has been fixed.
+
diff --git a/src/cmd/ksh93/RELEASE88 b/src/cmd/ksh93/RELEASE88
new file mode 100644
index 0000000..2466e39
--- /dev/null
+++ b/src/cmd/ksh93/RELEASE88
@@ -0,0 +1,422 @@
+This is a list of changes that have been made since the 11/16/88 version
+of ksh.
+
+1. New features in 12/28/93
+ a. Associative arrays. The new version of ksh supports both
+ associate arrays and the older indexed arrays with the same
+ array syntax. A new -A option of typeset is used to declare
+ an array to be associative. As with indexed arrays, $name is
+ equivalent to ${name[0]}. The prefix operator ! was added
+ to the parameter expansion syntax to expand to the list of
+ indices. For example, ${!name[@]} expands to the list of array
+ indices for variable name.
+
+ b. Several additions have been made to shell arithmetic:
+ 1. The shell now performs floating point arithmetic. The
+ typeset options -F and -E have been added for floating
+ point and scientific notation respectively.
+ 2. The prefix and postfix ++ and -- operators.
+ 3. The comma and ?: operators.
+ 4. The math library functions.
+ 5. An arithmetic for statement of the form
+ for ((expr1; expr2; expr3))
+ do ...
+ done
+ 6. Integer arithmetic extended up to base 64.
+
+ c. Some additions to the macro expansion syntax have been made
+ to specify substrings and sub-arrays:
+ 1. ${name:expr} expands to the substring of ${name} starting at
+ the character position defined by arithmetic expression expr.
+ 2. ${name:expr1:expr2} expands to the substring of ${name} starting
+ at expr1 and consisting of at most expr2 characters.
+ 3. ${name[@]:expr} expands to the values of ${name[@]} starting at
+ the element defined by arithmetic expression expr.
+ 4. ${name[@]:expr1:expr2} expands to at most expr2 values of
+ ${name} starting at expr1.
+ 5. ${@:expr} expands the positional parameters starting at expr.
+ 6. ${@:expr1:expr2} expands to at most expr2 positional parameters
+ starting at expr1.
+ 7. ${!name} expands to the name of the variable named by name.
+ It will expand to name unless name is reference variable.
+ 8. ${!name[sub]} expands to the name of the subscript of the
+ given variable. If sub is @ or * the list of subscripts
+ is generated.
+ 9. ${!prefix*} and ${!prefix@} expand to the list of variable
+ names beginning with prefix.
+ 10. The substring operators, # and % can be now be applied
+ with aggregates (@ or *) and are applied to each.
+ 11. ${name/pattern/string} expands to the value of name with
+ the first occurrence of pattern replaced by string.
+ With aggregates (@ or *) this operation is applied to each.
+ 12. ${name/#pattern/string} Same as above but the pattern
+ to be replaced must match at the beginning.
+ 13. ${name/%pattern/string} Same as above but the pattern
+ to be replaced must match at the end.
+ 14. ${name//pattern/string} expands to the value of name with
+ the each occurrence of pattern replaced by string.
+ With aggregates (@ or *) this operation is applied to each.
+
+ d. The name space for variables has been extended. The character '.'
+ can be used at the beginning of a name, and to separate identifiers
+ within a name. However, to create a name of the form, foo.bar,
+ the variable foo must exist. The namespace starting with .sh
+ is reserved for shell implementation variables. Exported
+ variable cannot contain a '.'.
+
+ e. Compound assignments. The assignment syntax, varname=value,
+ has been extended to allow assignments of the form
+ varname=(assignment_list). As elsewhere in the shell
+ spaces or tabs are optional around the parentheses, and
+ no space is permitted between the varname and the =. The
+ assignment_list can be one of the following:
+ 1. A list of words. In this case each word is expanded as
+ in a for list and the resulting items become elements
+ of the indexed array varname.
+ 2. A list of subscript assignments in the form
+ [subscript]=value. In this, these elements become
+ elements of the associative array varname.
+ 3. A list of assignments; simple or compound. In this
+ case, each assignment is made to varname.name, where
+ name is the name of the enclosed assignment.
+ 4. Assignments in the form of readonly or typeset
+ statements. In this case each assignment is made as
+ in 3 above, and the attributes are given to the
+ corresponding variable.
+ In case 3 and 4 above, the value of "$varname" after
+ the above assignment is (assignment_list), where the
+ assignment_list produced would reproduce all of the
+ variables under varname.*.
+
+ f. Function names of the form variable.action (called discipline
+ functions) can be defined where variable is any valid variable
+ name and action is get, set, or unset. The function variable.get
+ is invoked each time the variable is referenced. The set
+ discipline is invoked each time the variable is assigned to.
+ The unset discipline is invoked when a variable is unset.
+ The new variables .sh.name, .sh.subscript, and .sh.value are
+ defined inside the function body. Other shell extensions
+ may have their own set of discipline functions.
+
+ g. The compound command !, which negates the return value of the
+ following pipeline, has been added.
+
+ h. On systems that support dynamic loading with dlopen(), it is
+ now possible to add built-in commands at runtime with the
+ a builtin command named builtin.
+
+ i. The following builtins have been added:
+ 1. command name [ ... ]
+ 2. sleep [decimal-seconds]
+ 3. builtin [-ds] [-f file] [name...]
+ 4. getconf name [pathname]
+ 5. disown [job...]
+
+ j. An addition format for literal strings, $'....' can
+ be used where ever literal strings are valid. The string
+ inside the single quotes will be converted using the ANSI-C
+ escape conventions. Additionally, the escape sequence \E
+ expands to the escape character (default \033) whenever ANSI-C
+ escape sequences are recognized.
+
+ k. A typeset -n option has been added which causes the value of a
+ variable to be treated as a reference to another variable so that
+ variables can be indirectly named. For example, if $1 contains
+ the name of a variable, then typeset -n foo=$1 causes the variable
+ foo to be synonymous with the variable whose name is $1. A builtin
+ alias, nameref='typeset -n' has been added to aid mnemonics.
+ Reference names cannot contain a '.'. Whenever that portion of
+ a variable up to the first '.' matches a reference name, the
+ reference value is substituted. For example, with nameref foo=.top,
+ then ${foo.bar} is equivalent to ${.top.bar}. When used as the
+ index of a for or select loop, each assignment causes a
+ new name reference to occur.
+
+ l. The KEYBD trap has been added which is triggered when a key
+ or escape sequence is typed while reading from the keyboard
+ in an edit mode. This, combined with some new variables
+ makes it possible to program your key bindings in ksh.
+
+ m. New variables have been added:
+ 1. FIGNORE defines a set of file names to be ignored in each
+ directory when performing pathname expansion, replacing
+ the rule that requires that a leading . be matched explicitly.
+ 2. Variable sh.edchar contains the value of the keyboard character
+ that has been entered when processing a KEYBD trap. If the value
+ is changed as part of the trap action, then the new value replaces
+ the key or keys that caused the trap.
+ 3. Variable sh.edcol is set to the character position of the cursor
+ within the input buffer during a KEYBD trap.
+ 4. Variable sh.edmode is set to the escape character when in vi
+ insert mode.
+ 5. Variable sh.edtext is set to the contents of the input buffer
+ during a KEYBD trap.
+ 6. HISTEDIT is checked before FCEDIT. FCEDIT is obsolete.
+ 7. HISTCMD is the number of the current command in the history
+ file.
+ 8. Variable .sh.version is set to the version string for
+ this shell.
+ 9. Variable .sh.name is set to the name of the variable
+ that that was referenced or assigned to when executing a get
+ or set discipline function.
+ 10. Variable .sh.subscript is set to the subscript for the variable
+ that was referenced or assign to when executing a get or
+ set discipline function.
+ 11. Variable .sh.value is set to the new value for the variable
+ that was assigned to when executing the set discipline function.
+
+ n. New invocation and set -o options have been added:
+ 1. set -o notify (or set -b) causes background completion messages
+ to be displayed as soon as the job completes.
+ 2. There is a compile time option named KIA which enables
+ creation of a relational database for commands, variables
+ and functions defined and referenced by a script. The
+ option -I <filename>, causes the database to be generated
+ in <filename>. The database format can be queried via
+ the cql command.
+ o. ksh93 can read and evaluate pre-compiled scripts generated by
+ a separate program called shcomp.
+ p. More work on internationalization has been added:
+ 1. The decimal point character is processed per locale
+ 2. A $ can be placed in front of each string to indicate
+ that the string needs translation but is otherwise ignored.
+ This means that if a message catalog of all $"..." strings
+ is generated, then a program such as print $"hello world"
+ could display "bonjour monde" in the french locale.
+ q. Backreferences have been added to pattern matching. The sequence
+ \d, where d is a digit from 1-9, matches the same string as
+ the d-th previous parenthesis group. Backreferences
+ can be used within patterns, and within replacement strings
+ with any of the ${name/...} operators.
+
+2. Changes made in 12/28/93
+ a. The output format of many commands has changed as follows:
+ 1. System error messages are displayed whenever a failure
+ is caused by a system call.
+ 2. The exit status has changed in many cases:
+ a. USAGE messages cause an exit status of 2.
+ b. Commands not found cause exit - 127.
+ c. Command found, but not executable - 126.
+ d. Terminated because of signal - 256+sig
+ 3. The output of values from built-ins that contain special
+ characters are quoted in a manner that then can be re-input.
+ 4. The trace output puts quotes around the output so that it
+ can be reused as input.
+ 5. The output for trap is in a format that can be reinput the
+ the shell to restore the traps.
+ 6. kill -l lists the signal names without numbers as
+ required by the POSIX standard.
+
+ b. The following changes have been made to shell functions:
+ 1. The semantics of functions declared with name() has changed
+ to conform with the IEEE-POSIX 1003.2 standard. In particular,
+ these functions are executed in a dot script environment rather
+ than a separated function environment so that there are no
+ local variables and no scoping for traps.
+ 2. Functions declared as function name, preserve the old ksh
+ semantics can be also used as the first argument to the dot (.)
+ command to have them executed in a dot script environment.
+
+ c. The command search rules have changed as follows:
+ 1. Special built-ins (those with a dagger in front of them) are
+ executed first.
+ 2. Functions are executed next.
+ 3. Other built-ins that do not require an executable version
+ (for example cd and read) come next.
+ 4. If the command name contains a slash, the pathname corresponding
+ to the command name is executed.
+ 5. If name corresponds to a previously encountered pathname
+ on the PATH variable, the corresponding command is executed.
+ 6. If the command name does not contain a slash, then the PATH
+ variable is used to find an executable by that name. If
+ the directory that the command is found is also contained in
+ the FPATH variable, then the command treated as a function.
+ If the shell has a built-in version of the command corresponding
+ to this command, then the built-in version of this command
+ is executed. Otherwise, the shell remembers that pathname
+ corresponding to this command name and executes this pathname.
+ 7. If the name is not found on PATH, then the directories in
+ FPATH are searched. If found, then the command is executed
+ as a function.
+
+ d. Built-in commands options now conform to the IEEE-POSIX 1003.2
+ conventions with some additions. In particular,
+ name -?
+ will now print a Usage line for name, except for true, false,
+ colon, login, newgrp, echo, [, and command.
+
+ e. Tilde expansion is now performed as part of the word expansions.
+ The effect of this is that if word begins with ~ in ${name op word},
+ it will be expanded unless escaped.
+
+ f. Pathname expansion is no longer performed on redirection words
+ unless the shell is interactive.
+
+ g. Changes to shell and options:
+ 1. The -n option has been enhanced to produce more warning and
+ portability messages.
+ 2. The -C option is equivalent to -o noclobber. Files are
+ created with O_EXCL when -C is on.
+
+ h. The following changes have been made to [[...]]:
+ 1. A string by itself is equivalent to -n string.
+ 2. -e has been added as equivalent to -a.
+ 3. == has been added as equivalent =.
+ 4. -a and = are now considered obsolete.
+ 5. Arithmetic comparisons are now considered obsolete.
+
+ i. kill has been changed as follows:
+ 1. Signal names can be upper case or lower case.
+ 2. Numerical arguments to kill -l cause the given signal names to
+ be displayed.
+ 3. String arguments to kill -l cause the given signal numbers to
+ be displayed.
+ 4. Synopsis changed for getopts conformance.
+
+ j. print has a -f format option which is equivalent to
+ the IEEE POSIX printf. Both print -f format, and
+ printf have the following extensions from IEEE POSIX:
+ 1. Floating point formats are supported.
+ 2. Size and precision specifications can be *.
+ 3. The %d option can take an argument after precision to
+ specify the base that the number will be displayed.
+ 4. A %q format can be used to output a string quoted so
+ that it can be re-input to the shell.
+ 5. A %P format can be used to output the shell pattern which
+ corresponds to the give extended regular expression.
+ 6. For numerical fields, the arguments can be arithmetic
+ expressions which will be evaluated.
+ 7. The %n format works as described in ANSI-C.
+
+ k. The following changes have been made to fc:
+ 1. It has been renamed hist. fc is now a predefined alias.
+ 2. hist uses ${HISTEDIT:-$FCEDIT}. FCEDIT is obsolete.
+ 3. A new -s option is equivalent to the obsolete -e -.
+ 4. If the first argument refers to a command earlier than the
+ first accessible command, it now implies the first accessible
+ command, so that hist -l 1 lists all accessible history commands.
+
+ l. The dot command (.) has changed as follows:
+ 1. The argument can be the name of a function declared as
+ function name. The function will execute without creating a
+ new scope.
+ 2. If there are arguments to the given script or function,
+ the positional parameters are restored to their original
+ value when . completes.
+
+ m. The read built-in has been changed as follows:
+ 1. A -A option to read has been added to allow the fields to be
+ read into an indexed array.
+ 2. A -t n option has been added which causes read to
+ timeout after n seconds when reading from a slow device.
+ 3. A -d char option has been added which causes the read
+ to terminate at char rather than at new-line.
+
+ n. The trap command has been changed as follows:
+ 1. Trap names can be either upper case or lower case.
+ 2. Trap -p cause only the specified trap values to be displayed.
+ 3. The value of trap in a subshell will be the value in the parent
+ shell until a call to trap which changes the trap settings has
+ been made. Thus, savetraps=$(trap) works as required by the
+ POSIX standard.
+
+ o. The exec command has been extended as follows:
+ 1. The -c option clears the environment first.
+ 2. The -a name option sets argv[0] to name for the program.
+
+ p. true and false are built-ins, not aliases to built-ins.
+
+ q. test has been modified to conform to the IEEE-POSIX 1003.2
+ standard when there are three or less arguments.
+
+ r. umask -S option displays the mask in a symbolic format.
+
+ s. wait now returns the correct exit status of any previous
+ background job that has not been waited for, not just
+ the most recent one.
+
+ t. The whence built-in has an option -a which causes all
+ uses for the given command name to be reported.
+
+ u. unalias has -a option to clear all the aliases.
+
+ v. The times built-in command has been removed. The time
+ reserved word, without a command, gives time cumulative
+ time for the shell and its children. A built-in alias
+ for times should enable scripts using times to continue
+ to run.
+
+ w. Command substitution and arithmetic substitution will now be
+ performed for PS1, ENV, and PS4 evaluation in addition to
+ parameter expansion.
+
+ x. The SECONDS variable now displays elapsed time in floating
+ point seconds with 3 places after the decimal point by
+ default.
+
+ y. The getopts built-in now handles the complete libast optget
+ functionality. If any errors have occurred with getopts
+ when it has reached the end of arguments, then the Usage
+ message will be generated from the option string and the
+ exit status from getopts will be 2 rather than 1. The
+ usage message will be stored in the OPTARG variable if
+ the option string contains a leading colon; otherwise
+ it will be printed on standard error automatically.
+
+ z. THE ENV file is only processed for interactive shell
+ invocations. In addition, the -x attributes for
+ aliases and functions is ignored.
+
+ aa. The built-in edit modes have been changed as follows:
+ 1. The pathname completion and pathname listing options
+ now perform command completion and command listing
+ when applied to a word in the command position.
+ 2. In emacs mode ^N as the first related command after
+ the prompt will move to the next command relative to the
+ last known history position.
+ 3. In emacs mode, successive kill and delete commands will
+ accumulate their data in the kill buffer, by appending or
+ prepending as appropriate. This mode will be reset by any
+ command not adding something to the kill buffer.
+ 4. The control-T of emacs mode has been changed to behave like
+ control-T in gnu-emacs.
+ bb. The TMOUT variable also sets a limit for select timeouts
+ and default timeouts for read.
+
+
+4. The source code has undergone significant modification.
+ a. Much of the code has been rewritten, In many cases this has
+ resulted in significant performance improvement.
+
+ b. The code is organized differently. See the README files
+ for more details.
+
+ c. Most configuration parameters now get generated using
+ the FEATURE mechanism of nmake. Other options are set
+ in the OPTIONS file.
+
+ c. The are several new compile time options. See the README
+ file for details. Some of the old ones have been removed.
+
+ d. The install script is a Mamfile that is generated by
+ nmake and processed by a script that comes with the
+ distribution.
+
+ e. There are far fewer global names. This should make it
+ must easier to add built-in commands without worrying
+ about conflicts.
+
+ f. The code uses the sfio library which makes it possible
+ to mix with stdio.
+
+ g. The code is written in ANSI C with full prototypes.
+ The code is based on the IEEE POSIX 1003.1 standard.
+ The code can be compiled with K&R C and with C++ by
+ using the ANSI cpp that comes with nmake or running
+ the code through the proto filter before pre-processing.
+ This happens automatically with our shipping system.
+
+ h. There is a programming interface for capturing references
+ and assignment to shell variables. It is also possible
+ to intercept variable creation and supply the array processing
+ function for that variable. See nval.3 for a description.
diff --git a/src/cmd/ksh93/RELEASE93 b/src/cmd/ksh93/RELEASE93
new file mode 100644
index 0000000..e99c878
--- /dev/null
+++ b/src/cmd/ksh93/RELEASE93
@@ -0,0 +1,455 @@
+This is a list of changes that have been made since the 12/28/93 version
+of ksh.
+
+1. New features in 12/28/93b
+ a. If IFS contains two consecutive identical characters belonging
+ to the [:space:] class, then this character is treated as
+ a non-space delimiter so that each instance will delimit
+ a field. For example, IFS=$'\t\t' will cause two consecutive
+ tabs to delimit a null field.
+ b. The getopts command has a -a name option that specifies a
+ name that will be used for usage messages.
+
+2. New features in 12/28/93e
+ a. The math functions, atan2, hypot, fmod, and pow were added.
+ b. When a shared library is loaded, if the function lib_init()
+ is defined in the library, it is invoked the first time that
+ the library is loaded with builtin -f library.
+
+3. New features in 12/28/93f
+ a. Hostnames in addition to host addresses can be given in
+ /dev/tcp/host/port virtual file names.
+ b. File name completion and expansion now quotes special
+ characters in file names from both emacs and vi edit modes.
+
+4. New features in 12/28/93g
+ a. The pipefail option has been added. With pipefail
+ enabled, a pipeline will not complete until all
+ commands are complete, and the return value will
+ be that of the last command to fail, or zero if
+ all complete successfully.
+ b. When an executable is found on a given path,
+ the appropriate library path variable is prepended
+ with a corresponding library directory.
+5. New features in 12/28/93h
+ a. The PATH search algorithm has been modified to look
+ for a file named .fpath in each bin directory and if
+ found, to search for functions in this directory if
+ it cannot find the command in that directory.
+ b. When performing pathname expansion, the shell checks
+ to see whether each directory it reads is case sensitive
+ or not, and performs the matching accordingly.
+ c. The %T format for printing formatted date/time.
+6. New features in 12/28/93i
+ a. Most of the built-in commands and ksh itself are now
+ self documenting. Running command --man will produce
+ screen output. Running command --html produces the
+ man page in html format.
+ b. The getopts builtin can process command description
+ strings to produce man pages.
+
+7. Bugs fixed in 12/28/93a for default OPTIONS
+ a. An expansion bug which causes portions of a word after
+ a $((...)) expansion that contains a nested $var expansion
+ to be lost has been fixed.
+ b. A bug that caused a core dump when a script that did not
+ have PWD set and did a cd inside command substitution
+ has been fixed.
+ c. A bug which caused a core dump on some machines when
+ the LANG variable was assigned to has been fixed.
+ d. A bug which incorrectly handled set disciplines that
+ performed arithmetic evaluation when the discipline
+ was called from the arithmetic evaluator has been fixed.
+ e. A bug caused by an EXIT trap inside a function that
+ was executed in a subshell was fixed.
+ f. If foo is a function, and not a program, then command foo
+ now reports that foo isn't found rather than invoking foo.
+ g. The previous version incorrectly listed -A as an
+ invocation option. The -A option is only for set.
+ h. A bug was fixed which caused ksh to loop when execution trace
+ was enabled and the PS4 prompt required command substitution.
+ i. A bug which could cause the job control switch character
+ to be disabled when a script that enabled monitor mode
+ terminated was fixed.
+ j. A bug in the macro expansion global replacement operator //,
+ when the pattern began with a [ or +( has been fixed.
+ k. A bug which prevented ~ expansion from occurring when
+ it was terminated with a colon inside an assignment
+ has been fixed.
+ l. A bug in the dot command which prevented autoload functions
+ from working has been fixed.
+ m. A bug which caused a variable to be unset if the
+ its value were expanded inside a set discipline has
+ been fixed.
+ n. Whence -a now longer reports that a defined function
+ is undefined.
+ o. A bug on some systems in which $0 would be incorrect
+ in scripts invoked by name has been fixed.
+ p. Here documents with an empty body now work.
+ 1. A bug which disabled argument passing and resetting
+ of options for a script invoked by name inside a
+ function has been fixed.
+ r. A bug in which an EXIT trap set the caller of a function
+ would be executed if a command called inside a function
+ was not found has been fixed.
+ s. A bug which allowed a script to trap signals that are
+ ignored at the time that the shell was invoked has
+ been fixed.
+ t. A bug which caused 2<&1- when applied to a shell built-in
+ to leave standard input closed has been fixed.
+ u. A bug which caused the shell to incorrectly parse
+ $() command substitutions with nested case statements
+ has been fixed.
+
+8. Bugs fixed in 12/28/93b for default OPTIONS
+ a. A bug which caused unset RANDOM to dump core has been
+ fixed.
+ b. A bug which prevented return for terminating a profile
+ or ENV file has been fixed.
+ c. A bug which prevented standard input from being
+ directed to /dev/null for background jobs when
+ monitor mode was turned off has been fixed.
+ d. Statements of the form typeset -options var[expr]=value
+ did not perform substitutions on expr as expected.
+ e. A bug which prevented the shell from sending a HUP
+ signal to some background jobs that were not disowned
+ has been fixed.
+ f. A bug which allowed a script to trap signals that are
+ ignored at the time that the shell was invoked by exec
+ has been fixed.
+ g. A bug which could cause a core dump when a discipline
+ function was unset within a discipline was fixed.
+ h. The typeset builtin now accepts a first argument of
+ + or - for compatibility with ksh88.
+ i. For compatibility with ksh88, the results of expansions
+ of command arguments will treat the extended character
+ match characters ()|& as ordinary characters.
+ j. A bug which caused read to fail on a file that was
+ open for read/write with <> when the first operation
+ was print or printf has been fixed.
+ k. When a job is suspended, it is put on the top of
+ the job list as required by the POSIX standard.
+ l. The value of OPTARG when an option that required
+ an argument but didn't have one was incorrect in the
+ case the the option string began with a :.
+ m. A bug which caused the terminal to get into a bad
+ state with some KEYBD traps in vi-mode has been fixed.
+ n. A bug which caused an invalid trap to cause a script
+ to terminate, rather than just return an error, has
+ been fixed.
+ o. Backreferencing sub-expressions in patterns and replacement
+ strings now works.
+ p. A bug in chmod which caused the -R option to fail has
+ been fixed.
+
+9. Bugs fixed in 12/28/93c for default OPTIONS
+ a. The expansion of "$@" was incorrect when $1 was the null
+ string.
+ b. A bug which could incorrectly report a syntax error in
+ a backquoted expression when a $ was preceded by \\
+ has been fixed.
+ c. A bug which prevented the shell from exiting after
+ reporting an error when failing to open a script
+ has been fixed.
+ d. A bug that could lead to memory corruption when a
+ large here document that required parameter or command
+ substitution was expanded has been fixed.
+ e. A bug that could cause a core dump on some systems
+ after ksh detected an error when reading a function
+ has been fixed.
+ f. A bug which could cause a coprocess to hang when
+ reading from a process that has terminated has been fixed.
+ g. A bug which caused a script to terminate when set -e
+ was on and the first command of and && or || list
+ failed has been fixed.
+ h. A bug with here documents inside $(...) when the delimiter
+ word is an identifier has been fixed.
+ i. A bug which caused $0 to display the wrong value when
+ a script was invoked as an argument to the . command
+ and the eval command has been fixed.
+ j. A bug that could cause the built-in sleep to hang
+ has been fixed.
+ k. A bug introduces in 12/28/93b which caused the backslash
+ to be removed when it was followed by digit inside double
+ quotes in some instances has been fixed.
+ l. A bug which could cause a core dump if ksh was invoked with
+ standard input closed has been fixed.
+ m. A bug which could cause a core dump if typeset -A was
+ specified for an existing variable has been fixed.
+ n. Variables that were unset but had attributes such as readonly
+ and export were not listed with readonly, export and typeset.
+ o. Several problems with signals have been fixed.
+ p. A bug which prevented ulimit -t from working has been fixed.
+ Also, a bug in which failed ulimits could cause a core dump
+ has also been fixed.
+ q. A bug in expansion of the form ${name/#pattern/string} and
+ ${name/%pattern/string} has been fixed.
+ r. A bug which caused read -r on a line that contained only
+ blanks to get a non-null value has been fixed.
+ s. A bug introduced in the 'a' point release in which
+ ${x='\\'} expanded to \ when x was unset has been fixed.
+ t. A bug which prevented a trap on EXIT from being executed
+ when the last command in a script was a function invocation
+ has been fixed.
+ u. A bug which caused an interactive shell ignore input when
+ standard error was redirected to a file with exec,
+ and then restored with exec 2>&1 has been fixed.
+ v. An interactive shell turns on monitor mode even when
+ standard error has been redirected to a file.
+ w. A bug which could cause standard input to be incorrectly
+ positioned for the last command of a script has been fixed.
+ y. A bug in the edit modes which allowed walking back in
+ the history file for more than HISTSIZE commands has
+ beed fixed.
+ z. A bug which could cause a core dump if variable TMPDIR was
+ changed between two command substitutions has been fixed.
+ aa. A bug which prevented a trap on EXIT from being cleared
+ has been fixed.
+
+10. Bugs fixed in 12/28/93d for default OPTIONS
+ a. The \ character was not handled correctly in replacement
+ patterns with ${x/pattern/replace}.
+ b. A bug with read in which the line did not end with
+ a new-line has been fixed.
+ c. A bug in file name generation which sometimes
+ appended a . for filenames that ended in / has
+ been fixed.
+ d. If a process is waited for after a status has
+ been returned by a previous wait, wait now
+ returns 127.
+ e. A bug with hist (fc) -e which prevented a command
+ to re-executed after it had been edited has been fixed.
+ f. A bug which prevented quoting from removing the meaning
+ of unary test operators has been fixed.
+
+11. Bugs fixed in 12/28/93e for default OPTIONS
+ a. Empty command substitutions of the form $() now work.
+ b. whence -v foo now gives the correct result after calling
+ builtin -d foo.
+ c. A bug in right to left arithmetic assignment for which
+ the arithmetic expression (( y = x = 1.5 )) did not
+ yield 1 for y when x was declared typeset -i was fixed.
+ d. printf has been fixed to handle format containing \0
+ and/or \0145 correctly. In addition, characters following
+ %b in the format string are no longer displayed when
+ the operand contains \c.
+ e. A bug in printf that could cause the %E format to
+ produce unnormalized results has been fixed.
+ f. A bug which causes some arithmetic expressions to be
+ incorrectly evaluated as integer expressions rather
+ that floating point has been fixed.
+ g. Functions defined inside a subshell no longer remain
+ defined when the subshell completes.
+ h. The error message from sh -c ';echo foo' has been
+ corrected.
+ i. The format for umask -S has been changed to agree
+ with the specification in the POSIX standard.
+ j. A bug that caused side effects in subscript evaluation
+ when tracing was enabled for subscripts using ++ or --
+ has been fixed.
+ k. To conform to the Posix standard getopts has been changed
+ so that the option char is set to ? when it returns with
+ a non-zero exit status.
+ l. The handling of \} inside ${name...} has been fixed so
+ that the \ quotes the }.
+ m. A bug that caused the read builtin to resume execution
+ after processing a trap has been fixed.
+ n. [[ -s file ]] has been fixed so that if file is open
+ by ksh, it is flushed first.
+ o. In some cases attributes and sizes for non exported
+ variables weren't being reset before running a script.
+ p. The value of TMOUT was affected by changes make to
+ it in a subshell.
+ q. The jobs command did not reflect changes make by
+ sending the CONT signal to a command.
+ r. The error message for ksh -o unknown was incorrect.
+ s. Functions invoked as name=value name, did not use
+ values from the calling scope when evaluating value.
+ t. A bug in which the shell would reexecute previously
+ executed code when a shell script or coprocess was
+ run in the background has been fixed.
+ u. A bug in which an empty here-document would leave
+ a file descriptor open has been fixed.
+ v. A bug in which $(set -A array ...) would leave a
+ side effect has been fixed.
+ w. A discipline function for a global variable defined
+ within a function defined with the function keyword,
+ incorrectly created a local variable of the same name
+ and applied the discipline to it.
+
+12. Bugs fixed in 12/28/93f for default OPTIONS
+ a. A bug which would cause the secondary prompt to be
+ displayed when a user entered a literal carriage
+ return has been fixed.
+ b. I bug which caused ksh read -s name to core dump was
+ fixed.
+ c. I bug with the expansion of \} and \] inside double
+ quoted strings that also contained variable expansions
+ has been fixed
+ d. Changes in the 'e' point release caused autoload
+ functions invoked from within command substitution
+ to fail. This has been fixed.
+ e. A bug in the processing of here-documents that could
+ prevent variable substitution to occur after $(...) command
+ substitution for long here documents has been fixed.
+ f. A bug caused by a race condition that could cause SIGTERM
+ to be ignored by a child process has been fixed.
+ g. A bug which prevented the startup of a coprocess immediately
+ after killing a running coprocess has been fixed.
+ h. ulimit foobar, where foobar is not an arithmetic
+ expression, now gives an error message as it did with ksh88
+ instead of setting the file size limit to 0.
+ i. A bug which could cause an interactive shell to terminate when
+ the last process of a pipeline was a POSIX function was fixed.
+ j. A bug which could cause command substitution of a shell script
+ to core dump has been fixed.
+ k. A security hole was fixed in suid_exec.
+ l. Arithmetic functions such as pow() that take more than
+ one argument, did not work if arguments other than the
+ first contained parenthesized sub-expression.
+ m. The error message from a script containing an incomplete
+ arithmetic expression has been corrected.
+ n. A bug which caused a core dump on some machines when
+ the value of a name reference contained a positional
+ parameter and the name reference was not defined inside
+ a function has been fixed.
+ o. Arithmetic expressions now correctly handle hexidecimal
+ constants.
+ p. A bug in which integer variables could be expanded
+ with a leading 10# when declared with typeset -i
+ multiple times has been corrected.
+ q. A bug in which IFS wasn't correctly restored when
+ set within command substitution has been fixed.
+ r. The _ character is now considered as part of a word
+ with the M-f and M-b emacs directives as it was in ksh88.
+
+13. Bugs fixed in 12/28/93g for default OPTIONS
+ a. A bug in which a name reference could be created to
+ itself and later cause the shell to get into an infinite
+ loop has been fixed.
+ b. A bug in shcomp relating to compound variables was fixed.
+ c. A bug introduced in 'e' in which leading 0's in -Z
+ fields caused the value to be treated as octal for arithmetic
+ evaluation has been fixed.
+ d. A bug when a name reference with a shorter name than
+ the variable it references was the subject of a compound
+ assignment has been fixed.
+ e. A bug which in which assignment to array variables in
+ a subshell could effect the parent shell has been
+ fixed.
+ f. read name?prompt was putting a 0 byte at the end of the
+ prompt on standard error.
+ g. A bug in [[ string1 > string2 ]] when ksh was run with -x
+ has been fixed.
+ k. A bug in which the escape character was not processed
+ correctly inside {...} when brace expansion is enabled
+ has been fixed, for example {\$foo}.
+ l. A bug in line continuation in here-documents has been
+ fixed.
+ m. The default base when not specified with typeset -i is
+ 10 in accordance with the documentation. Previously,
+ the value was determined by the first assignment.
+ n. A parsing bug in which a # preceded alphanumeric
+ characters inside a command substitution caused
+ a syntax error to be reported has been fixed.
+ o. A bug in which a decimal constant represented as 10#ddd
+ where ddd was more than five digits generated a syntax
+ error has been fixed.
+ p. A bug in here document expansion in which ${...} expansions
+ were split across buffer boundaries has been fixed.
+
+14. Bugs fixed in 12/28/93h for default OPTIONS
+ a. I bug in shcomp for compilation of unary operators with [[...]]
+ has been fixed.
+ b. A bug in which the value of $? was changed when executing
+ a keyboard trap has been fixed.
+ c. The handling of SIGCHLD has been changed so that the
+ trap is not triggered while executing trap commands
+ to avoid recursive trap calls.
+ d. I bug in which a local variable in a function declared readonly
+ would generated an error when the function went out of
+ scope has been fixed.
+ e. I bug in which \<new_line> entered from the keyboard
+ with the KEYBD trap enabled has been fixed.
+ f. The error message for a misplaced ((, for example print ((3),
+ was often garbled and has been fixed.
+ g. I bug in the KEYBD trap in which escape sequences of the form
+ <ESC>[#~ were not being handled as a unit has been fixed.
+ h. A bug in which ksh would consider expressions like [[ (a) ]]
+ as syntax errors has been fixed.
+ i. A function defined as foo() without a function body
+ was not reported as a syntax error.
+ j. A bug in which ksh could run out of file descriptors when
+ a stream was repeatedly opened with exec and read from
+ has been fixed.
+ k. A bug introduced when fixing item n from the 'g' point
+ release has been fixed.
+
+15. Bugs fixed in 12/28/93i for default OPTIONS
+ a. A bug in which a script could terminate when getopts
+ encountered an error when invoked inside a function
+ has been fixed.
+ b. When a symbolic link was specified as the name of
+ the script to invoke by name, the value of $0 was
+ set to the real file name rather than the link name
+ in some cases and this has been fixed.
+
+16. Bug fixes for specific non-default option combinations.
+ a. More signal names have been added for Solaris
+ b. A bug fixed for the v directive in vi MULTIBYTE has been
+ fixed.
+ c. Code to for IFS handling of multibyte characters has
+ been added.
+ d. The displaying of multibyte strings in export, readonly,
+ typeset, and execution traces has been fixed.
+ e. A bug with type ahead and KEYBOARD traps with the
+ MULTIBYTE option set has been fixed.
+ f. The k-shell information abstraction database option, KIA,
+ has been revamped for the 'e' point release.
+ g. A bug in brace pattern expansions that caused expressions
+ such as {foo\,bar,bam} to expand incorrectly have been fixed.
+ h. On the U/WIN version for Window 95 and Windows NT,
+ when a directory beginning with a letter followed by
+ a colon is given to cd, it is assumed to be an absolute
+ directory.
+ i. There was a bug in the compile option that does not
+ use fork() in which the current option settings where
+ not propagated to sub-shells.
+ j. A bug in setting .sh.editchar during the KEYBD trap
+ for the MULTIBYTE option was fixed in release 'h'.
+ k. A bug in which the precision given as an argument
+ to printf was not working has been fixed.
+
+17. Other changes to 12/28/93[abcdefghi]
+ a. A couple of minor changes to make adding built-ins easier.
+ b. Variables inside functions are now statically scoped.
+ The previous behavior was never documented.
+ c. A few changes have been made to the name-value library
+ that affect built-ins that use disciplines. The
+ changes allow disciplines to be shared by variables
+ and should make it possible to add new disciplines
+ without recompilation.
+ d. The name-value library interface has undergone significant
+ change for this revision. See the new nval.3 man page.
+ e. Builtin functions can take a third argument which is
+ a void*.
+ f. The nv_scan() function can restrict the scope of a walk
+ to the top scope. Starting in 'f', nv_scan() has an
+ additional pointer argument that is passed to each invoked
+ function.
+ g. Starting with release 'f', an empty for list behave like
+ a for list with null expansions. It produces a warning
+ message with sh -n.
+ h. Starting with release 'f' the code has been modified to
+ work with EBCDIC as well as ASCII.
+ i. Starting with the release 'g', the name-value pair library
+ uses the cdt library rather than the hash library.
+ j. The sh_fun() function now takes third argument which
+ is an argument list for the invoked discipline function
+ or built-in.
+ k. A callback function can be installed which will give
+ notification of file duplications and file closes.
+
+18. Incompatibilities with 12/28/93 version.
+ None intentional.
+
diff --git a/src/cmd/ksh93/TYPES b/src/cmd/ksh93/TYPES
new file mode 100644
index 0000000..6eb6f41
--- /dev/null
+++ b/src/cmd/ksh93/TYPES
@@ -0,0 +1,182 @@
+
+The ability for users to define types has been added to ksh93t.
+Here is a quick summary of how types are defined and used in ksh93t.
+This is still a work in progress so some changes and additions
+are likely.
+
+A type can be defined either by a shared library or by using the new
+typeset -T option to the shell. The method for defining types via
+a shared library is not described here. However, the source file
+bltins/enum.c is an example of a builtin that creates enumeration types.
+
+By convention, typenames begin with a capitol letter and end in _t.
+To define a type, use
+ typeset -T Type_t=(
+ definition
+ )
+where definition contains assignment commands, declaration commands,
+and function definitions. A declaration command (for example typeset,
+readonly, and export), is a built-in that differs from other builtins in
+that tilde substitution is performed on arguments after an =, assignments
+do not have to precede the command name, and field splitting and pathname
+expansion is not performed on the arguments.
+For example,
+ typeset -T Pt_t=(
+ float -h 'length in inches' x=1
+ float -h 'width in inches' y=0
+ integer -S count=0
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y)))
+ }
+ set()
+ {
+ (( _.count++))
+ }
+ )
+
+defines a type Pt_t that has three variables x, y, and count defined as well
+as the discipline functions len and set. The variable x has an initial value
+of 1 and the variable y has an initial value of 0. The new -h option argument,
+is used for documentations purposes as described later and is ignored outside
+of a type definition.
+
+
+The variable count has the new -S attribute which means that it is shared
+between all instances of the type. The -S option to typeset is ignored
+outside of a type definition. Note the variable named _ that is used inside
+the function definition for len and set. It will be a reference to the
+instance of Pt_t that invoked the function. The functions len and set
+could also have been defined with function len and function set, but
+since there are no local variables, the len() and set() form are more
+efficient since they don't need to set up a context for local variables
+and for saving and restoring traps.
+
+If the discipline function named create is defined it will be
+invoked when creating each instance for that type. A function named
+create cannot be defined by any instance.
+
+When a type is defined, a declaration built-in command by this name
+is added to ksh. As with other shell builtins, you can get the man page
+for this newly added command by invoking Pt_t --man. The information from
+the -h options will be embedded in this man page. Any functions that
+use getopts to process arguments will be cross referenced on the generated
+man page.
+
+Since Pt_t is now a declaration command it can be used in the definition
+of other types, for example
+ typeset -T Rect_t=( Pt_t ur ll)
+
+Because a type definition is a command, it can be loaded on first reference
+by putting the definition into a file that is found on FPATH.
+Thus, if this definition is in a file named Pt_t on FPATH, then
+a program can create instances of Pt_t without first including
+the definition.
+
+A type definition is readonly and cannot be unset. Unsetting non-shared
+elements of a type restores them to their default value. Unsetting a
+shared element has no effect.
+
+The Pt_t command is used to create an instance of Pt_t.
+ Pt_t p1
+creates an instance named p1 with the initial value for p1.x set to 1
+and the initial value of p1.y set to 0.
+ Pt_t p2=(x=3 y=4)
+creates an instance with the specified initial values. The len function
+gives the distance of the point to the origin. Thus, p1.len will output
+1 and p2.len will output 5.
+
+ksh93t also introduces a more efficient command substitution mechanism.
+Instead of $(command), the new command substitution ${ command;}
+can be used. Unlike (and ) which are always special, the { and } are
+reserved words and require the space after { and a newline or ; before }.
+Unlike $(), the ${ ;} command substitution executes the command in
+the current shell context saving the need to save and restore
+changes, therefore also allowing side effects.
+
+When trying to expand an element of a type, if the element does not exist,
+ksh will look for a discipline function with that name and treat this as if
+it were the ${ ;} command substitution. Thus, ${p1.len} is equivalent to
+${ p1.len;} and within an arithmetic expression, p1.len will be expanded
+via the new command substitution method.
+
+The type of any variable can be obtained from the new prefix
+operator @. Thus, ${@p1} will output Pt_t.
+
+By default, each instance inherits all the discipline functions defined
+by the type definition other than create. However, each instance can define
+a function by the same name that will override this definition.
+However, only discipline functions with the same name as those defined
+by the type or the standard get, set, append, and unset disciplines
+can be defined by each instance.
+
+Each instance of the type Pt_t behaves like a compound variable except
+that only the variables defined by the type can be referenced or set.
+Thus, p2.x=9 is valid, but p2.z=9 is not. Unless a set discipline function
+does otherwise, the value of $p1 will be expanded to the form of a compound
+variable that can be used for reinput into ksh.
+
+If the variables var1 and var2 are of the same type, then the assignment
+ var2=var1
+will create a copy of the variable var1 into var2. This is equivalent to
+ eval var2="$var1"
+but is faster since the variable does not need to get expanded or reparsed.
+
+The type Pt_t can be referenced as if it were a variable using the name
+.sh.type.Pt_t. To change the default point location for subsequent
+instances of Pt_t, you can do
+ .sh.type.Pt_t=(x=5 y=12)
+so that
+ Pt_t p3
+ p3.len
+would be 13.
+
+Types can be defined for simple variables as well as for compound
+objects such as Pt_t. In this case, the variable named . inside
+the definition refers to the real value for the variable. For example,
+the type definition
+ typeset -T Time_t=(
+ integer .=0
+ _='%H:%M:%S'
+ get()
+ {
+ .sh.value=$(printf "%(${_._})T" "#$((_))" )
+ }
+ set()
+ {
+ .sh.value=$(printf "%(%#)T" "${.sh.value}")
+
+ }
+ )
+
+The sub-variable name _ is reserved for data used by discipline functions
+and will not be included with data written with the %B option to printf.
+In this case it is used to specify a date format.
+
+In this case
+ Time_t t1 t2=now
+will define t1 as the time at the beginning of the epoch and t2
+as the current time. Unlike the previous case, $t2 will output
+the current time in the date format specified by the value t2._.
+However, the value of ${t2.} will expand the instance to a form
+that can be used as input to the shell.
+
+Finally, types can be derived from an existing type. If the first
+element in a type definition is named _, then the new type
+consists of all the elements and discipline functions from the
+type of _ extended by elements and discipline functions defined
+by new type definition. For example,
+
+ typeset -T Pq_t=(
+ Pt_t _
+ float z=0.
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y + _.z*_.z)))
+ }
+ )
+
+defines a new type Pq_t which is based on Pq_t and contains an additional
+field z and a different len discipline function. It is also possible
+to create a new type Pt_t based on the original Pt_t. In this case
+the original Pt_t is no longer accessible.
diff --git a/src/cmd/ksh93/bltins/alarm.c b/src/cmd/ksh93/bltins/alarm.c
new file mode 100644
index 0000000..50261c6
--- /dev/null
+++ b/src/cmd/ksh93/bltins/alarm.c
@@ -0,0 +1,276 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * alarm [-r] [varname [+]when]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <error.h>
+#include <stak.h>
+#include "builtins.h"
+#include "FEATURE/time"
+
+#define R_FLAG 1
+#define L_FLAG 2
+
+struct tevent
+{
+ Namfun_t fun;
+ Namval_t *node;
+ Namval_t *action;
+ struct tevent *next;
+ long milli;
+ int flags;
+ void *timeout;
+ Shell_t *sh;
+};
+
+static const char ALARM[] = "alarm";
+
+static void trap_timeout(void*);
+
+/*
+ * insert timeout item on current given list in sorted order
+ */
+static void *time_add(struct tevent *item, void *list)
+{
+ register struct tevent *tp = (struct tevent*)list;
+ if(!tp || item->milli < tp->milli)
+ {
+ item->next = tp;
+ list = (void*)item;
+ }
+ else
+ {
+ while(tp->next && item->milli > tp->next->milli)
+ tp = tp->next;
+ item->next = tp->next;
+ tp->next = item;
+ }
+ tp = item;
+ tp->timeout = (void*)sh_timeradd(tp->milli,tp->flags&R_FLAG,trap_timeout,(void*)tp);
+ return(list);
+}
+
+/*
+ * delete timeout item from current given list, delete timer
+ */
+static void *time_delete(register struct tevent *item, void *list)
+{
+ register struct tevent *tp = (struct tevent*)list;
+ if(item==tp)
+ list = (void*)tp->next;
+ else
+ {
+ while(tp && tp->next != item)
+ tp = tp->next;
+ if(tp)
+ tp->next = item->next;
+ }
+ if(item->timeout)
+ timerdel((void*)item->timeout);
+ return(list);
+}
+
+static void print_alarms(void *list)
+{
+ register struct tevent *tp = (struct tevent*)list;
+ while(tp)
+ {
+ if(tp->timeout)
+ {
+ register char *name = nv_name(tp->node);
+ if(tp->flags&R_FLAG)
+ {
+ double d = tp->milli;
+ sfprintf(sfstdout,e_alrm1,name,d/1000.);
+ }
+ else
+ sfprintf(sfstdout,e_alrm2,name,nv_getnum(tp->node));
+ }
+ tp = tp->next;
+ }
+}
+
+static void trap_timeout(void* handle)
+{
+ register struct tevent *tp = (struct tevent*)handle;
+ tp->sh->trapnote |= SH_SIGALRM;
+ if(!(tp->flags&R_FLAG))
+ tp->timeout = 0;
+ tp->flags |= L_FLAG;
+ tp->sh->sigflag[SIGALRM] |= SH_SIGALRM;
+ if(sh_isstate(SH_TTYWAIT))
+ sh_timetraps(tp->sh);
+}
+
+void sh_timetraps(Shell_t *shp)
+{
+ register struct tevent *tp, *tpnext;
+ register struct tevent *tptop;
+ while(1)
+ {
+ shp->sigflag[SIGALRM] &= ~SH_SIGALRM;
+ tptop= (struct tevent*)shp->st.timetrap;
+ for(tp=tptop;tp;tp=tpnext)
+ {
+ tpnext = tp->next;
+ if(tp->flags&L_FLAG)
+ {
+ tp->flags &= ~L_FLAG;
+ if(tp->action)
+ sh_fun(tp->action,tp->node,(char**)0);
+ tp->flags &= ~L_FLAG;
+ if(!tp->flags)
+ {
+ nv_unset(tp->node);
+ nv_close(tp->node);
+ }
+ }
+ }
+ if(!(shp->sigflag[SIGALRM]&SH_SIGALRM))
+ break;
+ }
+}
+
+
+/*
+ * This trap function catches "alarm" actions only
+ */
+static char *setdisc(Namval_t *np, const char *event, Namval_t* action, Namfun_t
+ *fp)
+{
+ register struct tevent *tp = (struct tevent*)fp;
+ if(!event)
+ return(action?"":(char*)ALARM);
+ if(strcmp(event,ALARM)!=0)
+ {
+ /* try the next level */
+ return(nv_setdisc(np, event, action, fp));
+ }
+ if(action==np)
+ action = tp->action;
+ else
+ tp->action = action;
+ return(action?(char*)action:"");
+}
+
+/*
+ * catch assignments and set alarm traps
+ */
+static void putval(Namval_t* np, const char* val, int flag, Namfun_t* fp)
+{
+ register struct tevent *tp = (struct tevent*)fp;
+ register double d;
+ Shell_t *shp = tp->sh;
+ if(val)
+ {
+ double now;
+#ifdef timeofday
+ struct timeval tmp;
+ timeofday(&tmp);
+ now = tmp.tv_sec + 1.e-6*tmp.tv_usec;
+#else
+ now = (double)time(NIL(time_t*));
+#endif /* timeofday */
+ nv_putv(np,val,flag,fp);
+ d = nv_getnum(np);
+ if(*val=='+')
+ {
+ double x = d + now;
+ nv_putv(np,(char*)&x,NV_INTEGER|NV_DOUBLE,fp);
+ }
+ else
+ d -= now;
+ tp->milli = 1000*(d+.0005);
+ if(tp->timeout)
+ shp->st.timetrap = time_delete(tp,shp->st.timetrap);
+ if(tp->milli > 0)
+ shp->st.timetrap = time_add(tp,shp->st.timetrap);
+ }
+ else
+ {
+ tp = (struct tevent*)nv_stack(np, (Namfun_t*)0);
+ shp->st.timetrap = time_delete(tp,shp->st.timetrap);
+ if(tp->action)
+ nv_close(tp->action);
+ nv_unset(np);
+ free((void*)fp);
+ }
+}
+
+static const Namdisc_t alarmdisc =
+{
+ sizeof(struct tevent),
+ putval,
+ 0,
+ 0,
+ setdisc,
+};
+
+int b_alarm(int argc,char *argv[],Shbltin_t *context)
+{
+ register int n,rflag=0;
+ register Namval_t *np;
+ register struct tevent *tp;
+ register Shell_t *shp = context->shp;
+ while (n = optget(argv, sh_optalarm)) switch (n)
+ {
+ case 'r':
+ rflag = R_FLAG;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argc -= opt_info.index;
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
+ if(argc==0)
+ {
+ print_alarms(shp->st.timetrap);
+ return(0);
+ }
+ if(argc!=2)
+ errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
+ np = nv_open(argv[0],shp->var_tree,NV_NOARRAY|NV_VARNAME|NV_NOASSIGN);
+ if(!nv_isnull(np))
+ nv_unset(np);
+ nv_setattr(np, NV_DOUBLE);
+ if(!(tp = newof(NIL(struct tevent*),struct tevent,1,0)))
+ errormsg(SH_DICT,ERROR_exit(1),e_nospace);
+ tp->fun.disc = &alarmdisc;
+ tp->flags = rflag;
+ tp->node = np;
+ tp->sh = shp;
+ nv_stack(np,(Namfun_t*)tp);
+ nv_putval(np, argv[1], 0);
+ return(0);
+}
+
diff --git a/src/cmd/ksh93/bltins/cd_pwd.c b/src/cmd/ksh93/bltins/cd_pwd.c
new file mode 100644
index 0000000..fb0dcda
--- /dev/null
+++ b/src/cmd/ksh93/bltins/cd_pwd.c
@@ -0,0 +1,250 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * cd [-LP] [dirname]
+ * cd [-LP] [old] [new]
+ * pwd [-LP]
+ *
+ * David Korn
+ * AT&T Labs
+ * research!dgk
+ *
+ */
+
+#include "defs.h"
+#include <stak.h>
+#include <error.h>
+#include "variables.h"
+#include "path.h"
+#include "name.h"
+#include "builtins.h"
+#include <ls.h>
+
+/*
+ * Invalidate path name bindings to relative paths
+ */
+static void rehash(register Namval_t *np,void *data)
+{
+ Pathcomp_t *pp = (Pathcomp_t*)np->nvalue.cp;
+ NOT_USED(data);
+ if(pp && *pp->name!='/')
+ _nv_unset(np,0);
+}
+
+int b_cd(int argc, char *argv[],Shbltin_t *context)
+{
+ register char *dir;
+ Pathcomp_t *cdpath = 0;
+ register const char *dp;
+ register Shell_t *shp = context->shp;
+ int saverrno=0;
+ int rval,flag=0;
+ char *oldpwd;
+ Namval_t *opwdnod, *pwdnod;
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted+4);
+ while((rval = optget(argv,sh_optcd))) switch(rval)
+ {
+ case 'L':
+ flag = 0;
+ break;
+ case 'P':
+ flag = 1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ dir = argv[0];
+ if(error_info.errors>0 || argc >2)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ oldpwd = (char*)shp->pwd;
+ opwdnod = (shp->subshell?sh_assignok(OLDPWDNOD,1):OLDPWDNOD);
+ pwdnod = (shp->subshell?sh_assignok(PWDNOD,1):PWDNOD);
+ if(argc==2)
+ dir = sh_substitute(oldpwd,dir,argv[1]);
+ else if(!dir)
+ dir = nv_getval(HOME);
+ else if(*dir == '-' && dir[1]==0)
+ dir = nv_getval(opwdnod);
+ if(!dir || *dir==0)
+ errormsg(SH_DICT,ERROR_exit(1),argc==2?e_subst+4:e_direct);
+#if _WINIX
+ if(*dir != '/' && (dir[1]!=':'))
+#else
+ if(*dir != '/')
+#endif /* _WINIX */
+ {
+ if(!(cdpath = (Pathcomp_t*)shp->cdpathlist) && (dp=sh_scoped(shp,CDPNOD)->nvalue.cp))
+ {
+ if(cdpath=path_addpath(shp,(Pathcomp_t*)0,dp,PATH_CDPATH))
+ {
+ shp->cdpathlist = (void*)cdpath;
+ cdpath->shp = shp;
+ }
+ }
+ if(!oldpwd)
+ oldpwd = path_pwd(shp,1);
+ }
+ if(*dir=='.')
+ {
+ /* test for pathname . ./ .. or ../ */
+ if(*(dp=dir+1) == '.')
+ dp++;
+ if(*dp==0 || *dp=='/')
+ cdpath = 0;
+ }
+ rval = -1;
+ do
+ {
+ dp = cdpath?cdpath->name:"";
+ cdpath = path_nextcomp(shp,cdpath,dir,0);
+#if _WINIX
+ if(*stakptr(PATH_OFFSET+1)==':' && isalpha(*stakptr(PATH_OFFSET)))
+ {
+ *stakptr(PATH_OFFSET+1) = *stakptr(PATH_OFFSET);
+ *stakptr(PATH_OFFSET)='/';
+ }
+#endif /* _WINIX */
+ if(*stakptr(PATH_OFFSET)!='/')
+
+ {
+ char *last=(char*)stakfreeze(1);
+ stakseek(PATH_OFFSET);
+ stakputs(oldpwd);
+ /* don't add '/' of oldpwd is / itself */
+ if(*oldpwd!='/' || oldpwd[1])
+ stakputc('/');
+ stakputs(last+PATH_OFFSET);
+ stakputc(0);
+ }
+ if(!flag)
+ {
+ register char *cp;
+ stakseek(PATH_MAX+PATH_OFFSET);
+#if SHOPT_FS_3D
+ if(!(cp = pathcanon(stakptr(PATH_OFFSET),PATH_DOTDOT)))
+ continue;
+ /* eliminate trailing '/' */
+ while(*--cp == '/' && cp>stakptr(PATH_OFFSET))
+ *cp = 0;
+#else
+ if(*(cp=stakptr(PATH_OFFSET))=='/')
+ if(!pathcanon(cp,PATH_DOTDOT))
+ continue;
+#endif /* SHOPT_FS_3D */
+ }
+ if((rval=chdir(path_relative(shp,stakptr(PATH_OFFSET)))) >= 0)
+ goto success;
+ if(errno!=ENOENT && saverrno==0)
+ saverrno=errno;
+ }
+ while(cdpath);
+ if(rval<0 && *dir=='/' && *(path_relative(shp,stakptr(PATH_OFFSET)))!='/')
+ rval = chdir(dir);
+ /* use absolute chdir() if relative chdir() fails */
+ if(rval<0)
+ {
+ if(saverrno)
+ errno = saverrno;
+ errormsg(SH_DICT,ERROR_system(1),"%s:",dir);
+ }
+success:
+ if(dir == nv_getval(opwdnod) || argc==2)
+ dp = dir; /* print out directory for cd - */
+ if(flag)
+ {
+ dir = stakptr(PATH_OFFSET);
+ if (!(dir=pathcanon(dir,PATH_PHYSICAL)))
+ {
+ dir = stakptr(PATH_OFFSET);
+ errormsg(SH_DICT,ERROR_system(1),"%s:",dir);
+ }
+ stakseek(dir-stakptr(0));
+ }
+ dir = (char*)stakfreeze(1)+PATH_OFFSET;
+ if(*dp && (*dp!='.'||dp[1]) && strchr(dir,'/'))
+ sfputr(sfstdout,dir,'\n');
+ if(*dir != '/')
+ return(0);
+ nv_putval(opwdnod,oldpwd,NV_RDONLY);
+ if(oldpwd)
+ free(oldpwd);
+ flag = strlen(dir);
+ /* delete trailing '/' */
+ while(--flag>0 && dir[flag]=='/')
+ dir[flag] = 0;
+ nv_putval(pwdnod,dir,NV_RDONLY);
+ nv_onattr(pwdnod,NV_NOFREE|NV_EXPORT);
+ shp->pwd = pwdnod->nvalue.cp;
+ nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED);
+ path_newdir(shp,shp->pathlist);
+ path_newdir(shp,shp->cdpathlist);
+ return(0);
+}
+
+int b_pwd(int argc, char *argv[],Shbltin_t *context)
+{
+ register int n, flag = 0;
+ register char *cp;
+ register Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ while((n = optget(argv,sh_optpwd))) switch(n)
+ {
+ case 'L':
+ flag = 0;
+ break;
+ case 'P':
+ flag = 1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(*(cp = path_pwd(shp,0)) != '/')
+ errormsg(SH_DICT,ERROR_system(1), e_pwd);
+ if(flag)
+ {
+#if SHOPT_FS_3D
+ if(shp->gd->lim.fs3d && (flag = mount(e_dot,NIL(char*),FS3D_GET|FS3D_VIEW,0))>=0)
+ {
+ cp = (char*)stakseek(++flag+PATH_MAX);
+ mount(e_dot,cp,FS3D_GET|FS3D_VIEW|FS3D_SIZE(flag),0);
+ }
+ else
+#endif /* SHOPT_FS_3D */
+ cp = strcpy(stakseek(strlen(cp)+PATH_MAX),cp);
+ pathcanon(cp,PATH_PHYSICAL);
+ }
+ sfputr(sfstdout,cp,'\n');
+ return(0);
+}
+
diff --git a/src/cmd/ksh93/bltins/cflow.c b/src/cmd/ksh93/bltins/cflow.c
new file mode 100644
index 0000000..c78659f
--- /dev/null
+++ b/src/cmd/ksh93/bltins/cflow.c
@@ -0,0 +1,117 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * break [n]
+ * continue [n]
+ * return [n]
+ * exit [n]
+ *
+ * David Korn
+ * AT&T Labs
+ * dgk@research.att.com
+ *
+ */
+
+#include "defs.h"
+#include <ast.h>
+#include <error.h>
+#include "shnodes.h"
+#include "builtins.h"
+
+/*
+ * return and exit
+ */
+#if 0
+ /* for the dictionary generator */
+ int b_exit(int n, register char *argv[],Shbltin_t *context){}
+#endif
+int b_return(register int n, register char *argv[],Shbltin_t *context)
+{
+ register char *arg;
+ register Shell_t *shp = context->shp;
+ struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ const char *options = (**argv=='r'?sh_optreturn:sh_optexit);
+ while((n = optget(argv,options))) switch(n)
+ {
+ case ':':
+ if(!strmatch(argv[opt_info.index],"[+-]+([0-9])"))
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ goto done;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+done:
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ pp->mode = (**argv=='e'?SH_JMPEXIT:SH_JMPFUN);
+ argv += opt_info.index;
+ n = (((arg= *argv)?(int)strtol(arg, (char**)0, 10)&SH_EXITMASK:shp->oldexit));
+ /* return outside of function, dotscript and profile is exit */
+ if(shp->fn_depth==0 && shp->dot_depth==0 && !sh_isstate(SH_PROFILE))
+ pp->mode = SH_JMPEXIT;
+ sh_exit(shp->savexit=n);
+ return(1);
+}
+
+
+/*
+ * break and continue
+ */
+#if 0
+ /* for the dictionary generator */
+ int b_continue(int n, register char *argv[],Shbltin_t *context){}
+#endif
+int b_break(register int n, register char *argv[],Shbltin_t *context)
+{
+ char *arg;
+ register int cont= **argv=='c';
+ register Shell_t *shp = context->shp;
+ while((n = optget(argv,cont?sh_optcont:sh_optbreak))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ n=1;
+ if(arg= *argv)
+ {
+ n = strtol(arg,&arg,10);
+ if(n<=0 || *arg)
+ errormsg(SH_DICT,ERROR_exit(1),e_nolabels,*argv);
+ }
+ if(shp->st.loopcnt)
+ {
+ shp->st.execbrk = shp->st.breakcnt = n;
+ if(shp->st.breakcnt > shp->st.loopcnt)
+ shp->st.breakcnt = shp->st.loopcnt;
+ if(cont)
+ shp->st.breakcnt = -shp->st.breakcnt;
+ }
+ return(0);
+}
+
diff --git a/src/cmd/ksh93/bltins/enum.c b/src/cmd/ksh93/bltins/enum.c
new file mode 100644
index 0000000..5cc749c
--- /dev/null
+++ b/src/cmd/ksh93/bltins/enum.c
@@ -0,0 +1,284 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#include <shell.h>
+
+static const char enum_usage[] =
+"[-?@(#)$Id: enum (AT&T Research) 2008-01-08 $\n]"
+USAGE_LICENSE
+"[+NAME?enum - create an enumeration type]"
+"[+DESCRIPTION?\benum\b is a declaration command that creates an enumeration "
+ "type \atypename\a that can only store any one of the values in the indexed "
+ "array variable \atypename\a.]"
+"[+?If the list of \avalue\as is omitted, then \atypename\a must name an "
+ "indexed array variable with at least two elements.]"
+"[i:ignorecase?The values are case insensitive.]"
+"\n"
+"\n\atypename\a[\b=(\b \avalue\a ... \b)\b]\n"
+"\n"
+"[+EXIT STATUS]"
+ "{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+ "}"
+"[+SEE ALSO?\bksh\b(1), \btypeset\b(1).]"
+;
+
+static const char enum_type[] =
+"[-1c?\n@(#)$Id: type (AT&T Labs Research) 2008-01-08 $\n]"
+USAGE_LICENSE
+"[+NAME?\f?\f - create an instance of type \b\f?\f\b]"
+"[+DESCRIPTION?\b\f?\f\b creates a variable for each \aname\a with "
+ "enumeration type \b\f?\f\b where \b\f?\f\b is a type that has been "
+ "created with the \benum\b(1) command.]"
+"[+?The variable can have one of the following values\fvalues\f. "
+ "The the values are \fcase\fcase sensitive.]"
+"[+?If \b=\b\avalue\a is omitted, the default is \fdefault\f.]"
+"[+?If no \aname\as are specified then the names and values of all "
+ "variables of this type are written to standard output.]"
+"[+?\b\f?\f\b is built-in to the shell as a declaration command so that "
+ "field splitting and pathname expansion are not performed on "
+ "the arguments. Tilde expansion occurs on \avalue\a.]"
+"[r?Enables readonly. Once enabled, the value cannot be changed or unset.]"
+"[a?index array. Each \aname\a will converted to an index "
+ "array of type \b\f?\f\b. If a variable already exists, the current "
+ "value will become index \b0\b.]"
+"[A?Associative array. Each \aname\a will converted to an associate "
+ "array of type \b\f?\f\b. If a variable already exists, the current "
+ "value will become subscript \b0\b.]"
+"[h]:[string?Used within a type definition to provide a help string "
+ "for variable \aname\a. Otherwise, it is ignored.]"
+"[S?Used with a type definition to indicate that the variable is shared by "
+ "each instance of the type. When used inside a function defined "
+ "with the \bfunction\b reserved word, the specified variables "
+ "will have function static scope. Otherwise, the variable is "
+ "unset prior to processing the assignment list.]"
+#if 0
+"[p?Causes the output to be in a form of \b\f?\f\b commands that can be "
+ "used as input to the shell to recreate the current type of "
+ "these variables.]"
+#endif
+"\n"
+"\n[name[=value]...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\benum\b(1), \btypeset\b(1)]"
+;
+
+struct Enum
+{
+ Namfun_t hdr;
+ short nelem;
+ short iflag;
+ const char *values[1];
+};
+
+static int enuminfo(Opt_t* op, Sfio_t *out, const char *str, Optdisc_t *fp)
+{
+ Namval_t *np;
+ struct Enum *ep;
+ int n=0;
+ const char *v;
+ np = *(Namval_t**)(fp+1);
+ ep = (struct Enum*)np->nvfun;
+ if(strcmp(str,"default")==0)
+#if 0
+ sfprintf(out,"\b%s\b%c",ep->values[0],0);
+#else
+ sfprintf(out,"\b%s\b",ep->values[0]);
+#endif
+ else if(strcmp(str,"case")==0)
+ {
+ if(ep->iflag)
+ sfprintf(out,"not ");
+ }
+ else while(v=ep->values[n++])
+ {
+ sfprintf(out,", \b%s\b",v);
+ }
+ return(0);
+}
+
+static Namfun_t *clone_enum(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ struct Enum *ep, *pp=(struct Enum*)fp;
+ ep = newof(0,struct Enum,1,pp->nelem*sizeof(char*));
+ memcpy((void*)ep,(void*)pp,sizeof(struct Enum)+pp->nelem*sizeof(char*));
+ return(&ep->hdr);
+}
+
+static void put_enum(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ struct Enum *ep = (struct Enum*)fp;
+ register const char *v;
+ unsigned short i=0, n;
+ if(!val)
+ {
+ nv_putv(np, val, flags,fp);
+ nv_disc(np,&ep->hdr,NV_POP);
+ if(!ep->hdr.nofree)
+ free((void*)ep);
+ return;
+ }
+ if(flags&NV_INTEGER)
+ {
+ nv_putv(np,val,flags,fp);
+ return;
+ }
+ while(v=ep->values[i])
+ {
+ if(ep->iflag)
+ n = strcasecmp(v,val);
+ else
+ n = strcmp(v,val);
+ if(n==0)
+ {
+ nv_putv(np, (char*)&i, NV_UINT16, fp);
+ return;
+ }
+ i++;
+ }
+ if(nv_isattr(np,NV_NOFREE))
+ error(ERROR_exit(1), "%s: invalid value %s",nv_name(np),val);
+}
+
+static char* get_enum(register Namval_t* np, Namfun_t *fp)
+{
+ static char buff[6];
+ struct Enum *ep = (struct Enum*)fp;
+ long n = nv_getn(np,fp);
+ if(n < ep->nelem)
+ return((char*)ep->values[n]);
+ sfsprintf(buff,sizeof(buff),"%u%c",n,0);
+ return(buff);
+}
+
+static Sfdouble_t get_nenum(register Namval_t* np, Namfun_t *fp)
+{
+ return(nv_getn(np,fp));
+}
+
+const Namdisc_t ENUM_disc = { 0, put_enum, get_enum, get_nenum, 0,0,clone_enum };
+
+#ifdef STANDALONE
+static int enum_create(int argc, char** argv, Shbltin_t *context)
+#else
+int b_enum(int argc, char** argv, Shbltin_t *context)
+#endif
+{
+ int sz,i,n,iflag = 0;
+ Namval_t *np, *tp;
+ Namarr_t *ap;
+ char *cp,*sp;
+ struct Enum *ep;
+ Shell_t *shp = context->shp;
+ struct {
+ Optdisc_t opt;
+ Namval_t *np;
+ } optdisc;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
+ for (;;)
+ {
+ switch (optget(argv, enum_usage))
+ {
+ case 'i':
+ iflag = 'i';
+ continue;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || !*argv || *(argv + 1))
+ {
+ error(ERROR_USAGE|2, "%s", optusage(NiL));
+ return 1;
+ }
+ while(cp = *argv++)
+ {
+ if(!(np = nv_open(cp, (void*)0, NV_VARNAME|NV_NOADD)) || !(ap=nv_arrayptr(np)) || ap->fun || (sz=ap->nelem&(((1L<<ARRAY_BITS)-1))) < 2)
+ error(ERROR_exit(1), "%s must name an array containing at least two elements",cp);
+ n = staktell();
+ sfprintf(stkstd,"%s.%s%c",NV_CLASS,np->nvname,0);
+ tp = nv_open(stakptr(n), shp->var_tree, NV_VARNAME);
+ stakseek(n);
+ n = sz;
+ i = 0;
+ nv_onattr(tp, NV_UINT16);
+ nv_putval(tp, (char*)&i, NV_INTEGER);
+ nv_putsub(np, (char*)0, ARRAY_SCAN);
+ do
+ {
+ sz += strlen(nv_getval(np));
+ }
+ while(nv_nextsub(np));
+ sz += n*sizeof(char*);
+ if(!(ep = newof(0,struct Enum,1,sz)))
+ error(ERROR_system(1), "out of space");
+ ep->iflag = iflag;
+ ep->nelem = n;
+ cp = (char*)&ep->values[n+1];
+ nv_putsub(np, (char*)0, ARRAY_SCAN);
+ ep->values[n] = 0;
+ i = 0;
+ do
+ {
+ ep->values[i++] = cp;
+ sp = nv_getval(np);
+ n = strlen(sp);
+ memcpy(cp,sp,n+1);
+ cp += n+1;
+ }
+ while(nv_nextsub(np));
+ ep->hdr.dsize = sizeof(struct Enum)+sz;
+ ep->hdr.disc = &ENUM_disc;
+ ep->hdr.type = tp;
+ nv_onattr(tp, NV_RDONLY);
+ nv_disc(tp, &ep->hdr,NV_FIRST);
+ memset(&optdisc,0,sizeof(optdisc));
+ optdisc.opt.infof = enuminfo;
+ optdisc.np = tp;
+ nv_addtype(tp, enum_type, &optdisc.opt, sizeof(optdisc));
+ }
+ return error_info.errors != 0;
+}
+
+#ifdef STANDALONE
+void lib_init(int flag, void* context)
+{
+ Shell_t *shp = ((Shbltin_t*)context)->shp;
+ Namval_t *mp,*bp;
+ if(flag)
+ return;
+ bp = sh_addbuiltin("Enum", enum_create, (void*)0);
+ mp = nv_search("typeset",shp->bltin_tree,0);
+ nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
+}
+#endif
diff --git a/src/cmd/ksh93/bltins/getopts.c b/src/cmd/ksh93/bltins/getopts.c
new file mode 100644
index 0000000..8b92b73
--- /dev/null
+++ b/src/cmd/ksh93/bltins/getopts.c
@@ -0,0 +1,199 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * getopts optstring name [arg...]
+ *
+ * David Korn
+ * AT&T Labs
+ * research!dgk
+ *
+ */
+
+#include "defs.h"
+#include "variables.h"
+#include <error.h>
+#include <nval.h>
+#include "builtins.h"
+
+static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
+{
+ Shell_t *shp = *(Shell_t**)(dp+1);
+ Stk_t *stkp = shp->stk;
+ if(nv_search(s,shp->fun_tree,0))
+ {
+ int savtop = stktell(stkp);
+ char *savptr = stkfreeze(stkp,0);
+ sfputc(stkp,'$');
+ sfputc(stkp,'(');
+ sfputr(stkp,s,')');
+ sfputr(sp,sh_mactry(shp,stkfreeze(stkp,1)),-1);
+ stkset(stkp,savptr,savtop);
+ }
+ return(1);
+}
+
+int b_getopts(int argc,char *argv[],Shbltin_t *context)
+{
+ register char *options=error_info.context->id;
+ register Namval_t *np;
+ register int flag, mode;
+ register Shell_t *shp = context->shp;
+ char value[2], key[2];
+ int jmpval,extended;
+ volatile int r= -1;
+ struct checkpt buff, *pp;
+ struct {
+ Optdisc_t hdr;
+ Shell_t *sh;
+ } disc;
+ memset(&disc, 0, sizeof(disc));
+ disc.hdr.version = OPT_VERSION;
+ disc.hdr.infof = infof;
+ disc.sh = shp;
+ value[1] = 0;
+ key[1] = 0;
+ while((flag = optget(argv,sh_optgetopts))) switch(flag)
+ {
+ case 'a':
+ options = opt_info.arg;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if(error_info.errors || argc<2)
+ errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
+ error_info.context->flags |= ERROR_SILENT;
+ error_info.id = options;
+ options = argv[0];
+ np = nv_open(argv[1],shp->var_tree,NV_NOASSIGN|NV_VARNAME);
+ if(argc>2)
+ {
+ argv +=1;
+ argc -=1;
+ }
+ else
+ {
+ argv = shp->st.dolv;
+ argc = shp->st.dolc;
+ }
+ opt_info.index = shp->st.optindex;
+ opt_info.offset = shp->st.optchar;
+ if(mode= (*options==':'))
+ options++;
+ extended = *options=='\n' && *(options+1)=='[' || *options=='[' && *(options+1)=='-';
+ sh_pushcontext(shp,&buff,1);
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval)
+ {
+ sh_popcontext(shp,&buff);
+ shp->st.opterror = 1;
+ if(r==0)
+ return(2);
+ pp = (struct checkpt*)shp->jmplist;
+ pp->mode = SH_JMPERREXIT;
+ sh_exit(2);
+ }
+ opt_info.disc = &disc.hdr;
+ switch(opt_info.index>=0 && opt_info.index<=argc?(opt_info.num= LONG_MIN,flag=optget(argv,options)):0)
+ {
+ case '?':
+ if(mode==0)
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ opt_info.option[1] = '?';
+ /* FALL THRU */
+ case ':':
+ key[0] = opt_info.option[1];
+ if(strmatch(opt_info.arg,"*unknown*"))
+ flag = '?';
+ if(mode)
+ opt_info.arg = key;
+ else
+ {
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ opt_info.arg = 0;
+ flag = '?';
+ }
+ *(options = value) = flag;
+ shp->st.opterror = 1;
+ if (opt_info.offset != 0 && !argv[opt_info.index][opt_info.offset])
+ {
+ opt_info.offset = 0;
+ opt_info.index++;
+ }
+ break;
+ case 0:
+ if(shp->st.opterror)
+ {
+ char *com[2];
+ com[0] = "-?";
+ com[1] = 0;
+ flag = opt_info.index;
+ opt_info.index = 0;
+ optget(com,options);
+ opt_info.index = flag;
+ if(!mode && strchr(options,' '))
+ errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
+ }
+ opt_info.arg = 0;
+ options = value;
+ *options = '?';
+ r=1;
+ opt_info.offset = 0;
+ break;
+ default:
+ options = opt_info.option + (*opt_info.option!='+');
+ }
+ if(r<0)
+ r = 0;
+ error_info.context->flags &= ~ERROR_SILENT;
+ shp->st.optindex = opt_info.index;
+ shp->st.optchar = opt_info.offset;
+ nv_putval(np, options, 0);
+ nv_close(np);
+ np = nv_open(nv_name(OPTARGNOD),shp->var_tree,NV_NOSCOPE);
+ if(opt_info.num == LONG_MIN)
+ nv_putval(np, opt_info.arg, NV_RDONLY);
+ else if (opt_info.arg && opt_info.num > 0 && isalpha((char)opt_info.num) && !isdigit(opt_info.arg[0]) && opt_info.arg[0] != '-' && opt_info.arg[0] != '+')
+ {
+ key[0] = (char)opt_info.num;
+ key[1] = 0;
+ nv_putval(np, key, NV_RDONLY);
+ }
+ else if(extended)
+ {
+ Sfdouble_t d;
+ d = opt_info.number;
+ nv_putval(np, (char*)&d, NV_LDOUBLE|NV_RDONLY);
+ }
+ else
+ nv_putval(np, opt_info.arg, NV_RDONLY);
+ nv_close(np);
+ sh_popcontext(shp,&buff);
+ opt_info.disc = 0;
+ return(r);
+}
+
diff --git a/src/cmd/ksh93/bltins/hist.c b/src/cmd/ksh93/bltins/hist.c
new file mode 100644
index 0000000..1c2bc72
--- /dev/null
+++ b/src/cmd/ksh93/bltins/hist.c
@@ -0,0 +1,312 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#include "defs.h"
+#include <stak.h>
+#include <ls.h>
+#include <error.h>
+#include "variables.h"
+#include "io.h"
+#include "name.h"
+#include "history.h"
+#include "builtins.h"
+#if SHOPT_HISTEXPAND
+# include "edit.h"
+#endif
+
+#define HIST_RECURSE 5
+
+static void hist_subst(const char*, int fd, char*);
+
+#if 0
+ /* for the benefit of the dictionary generator */
+ int b_fc(int argc,char *argv[], Shbltin_t *context){}
+#endif
+int b_hist(int argc,char *argv[], Shbltin_t *context)
+{
+ register History_t *hp;
+ register char *arg;
+ register int flag,fdo;
+ register Shell_t *shp = context->shp;
+ Sfio_t *outfile;
+ char *fname;
+ int range[2], incr, index2, indx= -1;
+ char *edit = 0; /* name of editor */
+ char *replace = 0; /* replace old=new */
+ int lflag = 0, nflag = 0, rflag = 0;
+#if SHOPT_HISTEXPAND
+ int pflag = 0;
+#endif
+ Histloc_t location;
+ NOT_USED(argc);
+ if(!sh_histinit((void*)shp))
+ errormsg(SH_DICT,ERROR_system(1),e_histopen);
+ hp = shp->gd->hist_ptr;
+ while((flag = optget(argv,sh_opthist))) switch(flag)
+ {
+ case 'e':
+ edit = opt_info.arg;
+ break;
+ case 'n':
+ nflag++;
+ break;
+ case 'l':
+ lflag++;
+ break;
+ case 'r':
+ rflag++;
+ break;
+ case 's':
+ edit = "-";
+ break;
+#if SHOPT_HISTEXPAND
+ case 'p':
+ pflag++;
+ break;
+#endif
+ case 'N':
+ if(indx<=0)
+ {
+ if((flag = hist_max(hp) - opt_info.num-1) < 0)
+ flag = 1;
+ range[++indx] = flag;
+ break;
+ }
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += (opt_info.index-1);
+#if SHOPT_HISTEXPAND
+ if(pflag)
+ {
+ hist_cancel(hp);
+ pflag = 0;
+ while(arg=argv[1])
+ {
+ flag = hist_expand(arg,&replace);
+ if(!(flag & HIST_ERROR))
+ sfputr(sfstdout, replace, '\n');
+ else
+ pflag = 1;
+ if(replace)
+ free(replace);
+ argv++;
+ }
+ return pflag;
+ }
+#endif
+ flag = indx;
+ while(flag<1 && (arg=argv[1]))
+ {
+ /* look for old=new argument */
+ if(!replace && strchr(arg+1,'='))
+ {
+ replace = arg;
+ argv++;
+ continue;
+ }
+ else if(isdigit(*arg) || *arg == '-')
+ {
+ /* see if completely numeric */
+ do arg++;
+ while(isdigit(*arg));
+ if(*arg==0)
+ {
+ arg = argv[1];
+ range[++flag] = (int)strtol(arg, (char**)0, 10);
+ if(*arg == '-')
+ range[flag] += (hist_max(hp)-1);
+ argv++;
+ continue;
+ }
+ }
+ /* search for last line starting with string */
+ location = hist_find(hp,argv[1],hist_max(hp)-1,0,-1);
+ if((range[++flag] = location.hist_command) < 0)
+ errormsg(SH_DICT,ERROR_exit(1),e_found,argv[1]);
+ argv++;
+ }
+ if(flag <0)
+ {
+ /* set default starting range */
+ if(lflag)
+ {
+ flag = hist_max(hp)-16;
+ if(flag<1)
+ flag = 1;
+ }
+ else
+ flag = hist_max(hp)-2;
+ range[0] = flag;
+ flag = 0;
+ }
+ index2 = hist_min(hp);
+ if(range[0]<index2)
+ range[0] = index2;
+ if(flag==0)
+ /* set default termination range */
+ range[1] = ((lflag && !edit)?hist_max(hp)-1:range[0]);
+ if(range[1]>=(flag=(hist_max(hp) - !lflag)))
+ range[1] = flag;
+ /* check for valid ranges */
+ if(range[1]<index2 || range[0]>=flag)
+ errormsg(SH_DICT,ERROR_exit(1),e_badrange,range[0],range[1]);
+ if(edit && *edit=='-' && range[0]!=range[1])
+ errormsg(SH_DICT,ERROR_exit(1),e_eneedsarg);
+ /* now list commands from range[rflag] to range[1-rflag] */
+ incr = 1;
+ flag = rflag>0;
+ if(range[1-flag] < range[flag])
+ incr = -1;
+ if(lflag)
+ {
+ outfile = sfstdout;
+ arg = "\n\t";
+ }
+ else
+ {
+ if(!(fname=pathtmp(NIL(char*),0,0,NIL(int*))))
+ errormsg(SH_DICT,ERROR_exit(1),e_create,"");
+ if((fdo=open(fname,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_create,fname);
+ outfile= sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fdo,SF_WRITE);
+ arg = "\n";
+ nflag++;
+ }
+ while(1)
+ {
+ if(nflag==0)
+ sfprintf(outfile,"%d\t",range[flag]);
+ else if(lflag)
+ sfputc(outfile,'\t');
+ hist_list(shp->gd->hist_ptr,outfile,hist_tell(shp->gd->hist_ptr,range[flag]),0,arg);
+ if(lflag)
+ sh_sigcheck(shp);
+ if(range[flag] == range[1-flag])
+ break;
+ range[flag] += incr;
+ }
+ if(lflag)
+ return(0);
+ sfclose(outfile);
+ hist_eof(hp);
+ arg = edit;
+ if(!arg && !(arg=nv_getval(sh_scoped(shp,HISTEDIT))) && !(arg=nv_getval(sh_scoped(shp,FCEDNOD))))
+ {
+ arg = (char*)e_defedit;
+ if(*arg!='/')
+ errormsg(SH_DICT,ERROR_exit(1),"ed not found set FCEDIT");
+ }
+#ifdef apollo
+ /*
+ * Code to support the FC using the pad editor.
+ * Exampled of how to use: HISTEDIT=pad
+ */
+ if (strcmp (arg, "pad") == 0)
+ {
+ extern int pad_create(char*);
+ sh_close(fdo);
+ fdo = pad_create(fname);
+ pad_wait(fdo);
+ unlink(fname);
+ strcat(fname, ".bak");
+ unlink(fname);
+ lseek(fdo,(off_t)0,SEEK_SET);
+ }
+ else
+ {
+#endif /* apollo */
+ if(*arg != '-')
+ {
+ char *com[3];
+ com[0] = arg;
+ com[1] = fname;
+ com[2] = 0;
+ error_info.errors = sh_eval(sh_sfeval(com),0);
+ }
+ fdo = sh_chkopen(fname);
+ unlink(fname);
+ free((void*)fname);
+#ifdef apollo
+ }
+#endif /* apollo */
+ /* don't history fc itself unless forked */
+ error_info.flags |= ERROR_SILENT;
+ if(!sh_isstate(SH_FORKED))
+ hist_cancel(hp);
+ sh_onstate(SH_HISTORY);
+ sh_onstate(SH_VERBOSE); /* echo lines as read */
+ if(replace)
+ hist_subst(error_info.id,fdo,replace);
+ else if(error_info.errors == 0)
+ {
+ char buff[IOBSIZE+1];
+ Sfio_t *iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fdo,SF_READ);
+ /* read in and run the command */
+ if(shp->hist_depth++ > HIST_RECURSE)
+ errormsg(SH_DICT,ERROR_exit(1),e_toodeep,"history");
+ sh_eval(iop,1);
+ shp->hist_depth--;
+ }
+ else
+ {
+ sh_close(fdo);
+ if(!sh_isoption(SH_VERBOSE))
+ sh_offstate(SH_VERBOSE);
+ sh_offstate(SH_HISTORY);
+ }
+ return(shp->exitval);
+}
+
+
+/*
+ * given a file containing a command and a string of the form old=new,
+ * execute the command with the string old replaced by new
+ */
+
+static void hist_subst(const char *command,int fd,char *replace)
+{
+ register char *newp=replace;
+ register char *sp;
+ register int c;
+ off_t size;
+ char *string;
+ while(*++newp != '='); /* skip to '=' */
+ if((size = lseek(fd,(off_t)0,SEEK_END)) < 0)
+ return;
+ lseek(fd,(off_t)0,SEEK_SET);
+ c = (int)size;
+ string = stakalloc(c+1);
+ if(read(fd,string,c)!=c)
+ return;
+ string[c] = 0;
+ *newp++ = 0;
+ if((sp=sh_substitute(string,replace,newp))==0)
+ errormsg(SH_DICT,ERROR_exit(1),e_subst,command);
+ *(newp-1) = '=';
+ sh_eval(sfopen(NIL(Sfio_t*),sp,"s"),1);
+}
+
diff --git a/src/cmd/ksh93/bltins/misc.c b/src/cmd/ksh93/bltins/misc.c
new file mode 100644
index 0000000..d810a05
--- /dev/null
+++ b/src/cmd/ksh93/bltins/misc.c
@@ -0,0 +1,590 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * exec [arg...]
+ * eval [arg...]
+ * jobs [-lnp] [job...]
+ * login [arg...]
+ * let expr...
+ * . file [arg...]
+ * :, true, false
+ * vpath [top] [base]
+ * vmap [top] [base]
+ * wait [job...]
+ * shift [n]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include "variables.h"
+#include "shnodes.h"
+#include "path.h"
+#include "io.h"
+#include "name.h"
+#include "history.h"
+#include "builtins.h"
+#include "jobs.h"
+
+#define DOTMAX MAXDEPTH /* maximum level of . nesting */
+
+static void noexport(Namval_t*,void*);
+
+struct login
+{
+ Shell_t *sh;
+ int clear;
+ char *arg0;
+};
+
+int b_exec(int argc,char *argv[], Shbltin_t *context)
+{
+ struct login logdata;
+ register int n;
+ logdata.clear = 0;
+ logdata.arg0 = 0;
+ logdata.sh = context->shp;
+ logdata.sh->st.ioset = 0;
+ while (n = optget(argv, sh_optexec)) switch (n)
+ {
+ case 'a':
+ logdata.arg0 = opt_info.arg;
+ argc = 0;
+ break;
+ case 'c':
+ logdata.clear=1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(*argv)
+ B_login(0,argv,(Shbltin_t*)&logdata);
+ return(0);
+}
+
+static void noexport(register Namval_t* np, void *data)
+{
+ NOT_USED(data);
+ nv_offattr(np,NV_EXPORT);
+}
+
+int B_login(int argc,char *argv[],Shbltin_t *context)
+{
+ struct checkpt *pp;
+ register struct login *logp=0;
+ register Shell_t *shp;
+ const char *pname;
+ if(argc)
+ shp = context->shp;
+ else
+ {
+ logp = (struct login*)context;
+ shp = logp->sh;
+ }
+ pp = (struct checkpt*)shp->jmplist;
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,argv[0]);
+ else
+ {
+ register struct argnod *arg=shp->envlist;
+ register Namval_t* np;
+ register char *cp;
+ if(shp->subshell && !shp->subshare)
+ sh_subfork();
+ if(logp && logp->clear)
+ {
+#ifdef _ENV_H
+ env_close(shp->env);
+ shp->env = env_open((char**)0,3);
+#else
+ nv_scan(shp->var_tree,noexport,0,NV_EXPORT,NV_EXPORT);
+#endif
+ }
+ while(arg)
+ {
+ if((cp=strchr(arg->argval,'=')) &&
+ (*cp=0,np=nv_search(arg->argval,shp->var_tree,0)))
+ {
+ nv_onattr(np,NV_EXPORT);
+ sh_envput(shp->env,np);
+ }
+ if(cp)
+ *cp = '=';
+ arg=arg->argnxt.ap;
+ }
+ pname = argv[0];
+ if(logp && logp->arg0)
+ argv[0] = logp->arg0;
+#ifdef JOBS
+ if(job_close(shp) < 0)
+ return(1);
+#endif /* JOBS */
+ /* force bad exec to terminate shell */
+ pp->mode = SH_JMPEXIT;
+ sh_sigreset(2);
+ sh_freeup(shp);
+ path_exec(shp,pname,argv,NIL(struct argnod*));
+ sh_done(shp,0);
+ }
+ return(1);
+}
+
+int b_let(int argc,char *argv[],Shbltin_t *context)
+{
+ register int r;
+ register char *arg;
+ Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ while (r = optget(argv,sh_optlet)) switch (r)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors || !*argv)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ while(arg= *argv++)
+ r = !sh_arith(shp,arg);
+ return(r);
+}
+
+int b_eval(int argc,char *argv[], Shbltin_t *context)
+{
+ register int r;
+ register Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ while (r = optget(argv,sh_opteval)) switch (r)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg);
+ return(2);
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ if(*argv && **argv)
+ {
+ sh_offstate(SH_MONITOR);
+ sh_eval(sh_sfeval(argv),0);
+ }
+ return(shp->exitval);
+}
+
+int b_dot_cmd(register int n,char *argv[],Shbltin_t *context)
+{
+ register char *script;
+ register Namval_t *np;
+ register int jmpval;
+ register Shell_t *shp = context->shp;
+ struct sh_scoped savst, *prevscope = shp->st.self;
+ char *filename=0;
+ int fd;
+ struct dolnod *argsave=0, *saveargfor;
+ struct checkpt buff;
+ Sfio_t *iop=0;
+ short level;
+ while (n = optget(argv,sh_optdot)) switch (n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg);
+ return(2);
+ }
+ argv += opt_info.index;
+ script = *argv;
+ if(error_info.errors || !script)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(shp->dot_depth+1 > DOTMAX)
+ errormsg(SH_DICT,ERROR_exit(1),e_toodeep,script);
+ if(!(np=shp->posix_fun))
+ {
+ /* check for KornShell style function first */
+ np = nv_search(script,shp->fun_tree,0);
+ if(np && is_afunction(np) && !nv_isattr(np,NV_FPOSIX))
+ {
+ if(!np->nvalue.ip)
+ {
+ path_search(shp,script,NIL(Pathcomp_t**),0);
+ if(np->nvalue.ip)
+ {
+ if(nv_isattr(np,NV_FPOSIX))
+ np = 0;
+ }
+ else
+ errormsg(SH_DICT,ERROR_exit(1),e_found,script);
+ }
+ }
+ else
+ np = 0;
+ if(!np)
+ {
+ if((fd=path_open(shp,script,path_get(shp,script))) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_open,script);
+ filename = path_fullname(shp,stkptr(shp->stk,PATH_OFFSET));
+ }
+ }
+ *prevscope = shp->st;
+ shp->st.lineno = np?((struct functnod*)nv_funtree(np))->functline:1;
+ shp->st.var_local = shp->st.save_tree = shp->var_tree;
+ if(filename)
+ {
+ shp->st.filename = filename;
+ shp->st.lineno = 1;
+ }
+ level = shp->fn_depth+shp->dot_depth+1;
+ nv_putval(SH_LEVELNOD,(char*)&level,NV_INT16);
+ shp->st.prevst = prevscope;
+ shp->st.self = &savst;
+ shp->topscope = (Shscope_t*)shp->st.self;
+ prevscope->save_tree = shp->var_tree;
+ if(np)
+ shp->st.filename = np->nvalue.rp->fname;
+ nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE);
+ shp->posix_fun = 0;
+ if(np || argv[1])
+ argsave = sh_argnew(shp,argv,&saveargfor);
+ sh_pushcontext(shp,&buff,SH_JMPDOT);
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval == 0)
+ {
+ shp->dot_depth++;
+ if(np)
+ sh_exec((Shnode_t*)(nv_funtree(np)),sh_isstate(SH_ERREXIT));
+ else
+ {
+ char buff[IOBSIZE+1];
+ iop = sfnew(NIL(Sfio_t*),buff,IOBSIZE,fd,SF_READ);
+ sh_offstate(SH_NOFORK);
+ sh_eval(iop,sh_isstate(SH_PROFILE)?SH_FUNEVAL:0);
+ }
+ }
+ sh_popcontext(shp,&buff);
+ if(!np)
+ free((void*)shp->st.filename);
+ shp->dot_depth--;
+ if((np || argv[1]) && jmpval!=SH_JMPSCRIPT)
+ sh_argreset(shp,argsave,saveargfor);
+ else
+ {
+ prevscope->dolc = shp->st.dolc;
+ prevscope->dolv = shp->st.dolv;
+ }
+ if (shp->st.self != &savst)
+ *shp->st.self = shp->st;
+ /* only restore the top Shscope_t portion for posix functions */
+ memcpy((void*)&shp->st, (void*)prevscope, sizeof(Shscope_t));
+ shp->topscope = (Shscope_t*)prevscope;
+ nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE);
+ if(jmpval && jmpval!=SH_JMPFUN)
+ siglongjmp(*shp->jmplist,jmpval);
+ return(shp->exitval);
+}
+
+/*
+ * null, true command
+ */
+int b_true(int argc,register char *argv[],Shbltin_t *context)
+{
+ NOT_USED(argc);
+ NOT_USED(argv[0]);
+ NOT_USED(context);
+ return(0);
+}
+
+/*
+ * false command
+ */
+int b_false(int argc,register char *argv[], Shbltin_t *context)
+{
+ NOT_USED(argc);
+ NOT_USED(argv[0]);
+ NOT_USED(context);
+ return(1);
+}
+
+int b_shift(register int n, register char *argv[], Shbltin_t *context)
+{
+ register char *arg;
+ register Shell_t *shp = context->shp;
+ while((n = optget(argv,sh_optshift))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s",opt_info.arg);
+ return(2);
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ n = ((arg= *argv)?(int)sh_arith(shp,arg):1);
+ if(n<0 || shp->st.dolc<n)
+ errormsg(SH_DICT,ERROR_exit(1),e_number,arg);
+ else
+ {
+ shp->st.dolv += n;
+ shp->st.dolc -= n;
+ }
+ return(0);
+}
+
+int b_wait(int n,register char *argv[],Shbltin_t *context)
+{
+ register Shell_t *shp = context->shp;
+ while((n = optget(argv,sh_optwait))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ job_bwait(argv);
+ return(shp->exitval);
+}
+
+#ifdef JOBS
+# if 0
+ /* for the dictionary generator */
+ int b_fg(int n,char *argv[],Shbltin_t *context){}
+ int b_disown(int n,char *argv[],Shbltin_t *context){}
+# endif
+int b_bg(register int n,register char *argv[],Shbltin_t *context)
+{
+ register int flag = **argv;
+ register Shell_t *shp = context->shp;
+ register const char *optstr = sh_optbg;
+ if(*argv[0]=='f')
+ optstr = sh_optfg;
+ else if(*argv[0]=='d')
+ optstr = sh_optdisown;
+ while((n = optget(argv,optstr))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ if(!sh_isoption(SH_MONITOR) || !job.jobcontrol)
+ {
+ if(sh_isstate(SH_INTERACTIVE))
+ errormsg(SH_DICT,ERROR_exit(1),e_no_jctl);
+ return(1);
+ }
+ if(flag=='d' && *argv==0)
+ argv = (char**)0;
+ if(job_walk(sfstdout,job_switch,flag,argv))
+ errormsg(SH_DICT,ERROR_exit(1),e_no_job);
+ return(shp->exitval);
+}
+
+int b_jobs(register int n,char *argv[],Shbltin_t *context)
+{
+ register int flag = 0;
+ register Shell_t *shp = context->shp;
+ while((n = optget(argv,sh_optjobs))) switch(n)
+ {
+ case 'l':
+ flag = JOB_LFLAG;
+ break;
+ case 'n':
+ flag = JOB_NFLAG;
+ break;
+ case 'p':
+ flag = JOB_PFLAG;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(*argv==0)
+ argv = (char**)0;
+ if(job_walk(sfstdout,job_list,flag,argv))
+ errormsg(SH_DICT,ERROR_exit(1),e_no_job);
+ job_wait((pid_t)0);
+ return(shp->exitval);
+}
+#endif
+
+#ifdef _cmd_universe
+/*
+ * There are several universe styles that are masked by the getuniv(),
+ * setuniv() calls.
+ */
+int b_universe(int argc, char *argv[],Shbltin_t *context)
+{
+ register char *arg;
+ register int n;
+ NOT_USED(context);
+ while((n = optget(argv,sh_optuniverse))) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if(error_info.errors || argc>1)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(arg = argv[0])
+ {
+ if(!astconf("UNIVERSE",0,arg))
+ errormsg(SH_DICT,ERROR_exit(1), e_badname,arg);
+ }
+ else
+ {
+ if(!(arg=astconf("UNIVERSE",0,0)))
+ errormsg(SH_DICT,ERROR_exit(1),e_nouniverse);
+ else
+ sfputr(sfstdout,arg,'\n');
+ }
+ return(0);
+}
+#endif /* cmd_universe */
+
+#if SHOPT_FS_3D
+#if _UWIN
+#include <sys/mount.h>
+#endif
+# if 0
+ /* for the dictionary generator */
+ int b_vmap(int argc,char *argv[], Shbltin_t *context){}
+# endif
+ int b_vpath(register int argc,char *argv[], Shbltin_t *context)
+ {
+ register int flag, n;
+ register const char *optstr;
+ register char *vend;
+ register Shell_t *shp = context->shp;
+ if(argv[0][1]=='p')
+ {
+ optstr = sh_optvpath;
+ flag = FS3D_VIEW;
+ }
+ else
+ {
+ optstr = sh_optvmap;
+ flag = FS3D_VERSION;
+ }
+ while(n = optget(argv, optstr)) switch(n)
+ {
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+#ifdef MS_3D
+ flag |= MS_3D;
+#else
+ if(!shp->gd->lim.fs3d)
+ goto failed;
+#endif
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ switch(argc)
+ {
+ case 0:
+ case 1:
+ flag |= FS3D_GET;
+ if((n = mount(*argv,(char*)0,flag,0)) >= 0)
+ {
+ vend = stkalloc(shp->stk,++n);
+ n = mount(*argv,vend,flag|FS3D_SIZE(n),0);
+ }
+ if(n < 0)
+ goto failed;
+ if(argc==1)
+ {
+ sfprintf(sfstdout,"%s\n",vend);
+ break;
+ }
+ n = 0;
+ while(flag = *vend++)
+ {
+ if(flag==' ')
+ {
+ flag = e_sptbnl[n+1];
+ n = !n;
+ }
+ sfputc(sfstdout,flag);
+ }
+ if(n)
+ sfputc(sfstdout,'\n');
+ break;
+ default:
+ if((argc&1))
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ /*FALLTHROUGH*/
+ case 2:
+ if(shp->subshell && !shp->subshare)
+ sh_subfork();
+ for(n=0;n<argc;n+=2)
+ if(mount(argv[n+1],argv[n],flag,0)<0)
+ goto failed;
+ }
+ return(0);
+failed:
+ errormsg(SH_DICT,ERROR_exit(1),(argc>1)?e_cantset:e_cantget,(flag&FS3D_VIEW)?e_mapping:e_versions);
+ return(1);
+ }
+#endif /* SHOPT_FS_3D */
+
diff --git a/src/cmd/ksh93/bltins/mkservice.c b/src/cmd/ksh93/bltins/mkservice.c
new file mode 100644
index 0000000..0cbba25
--- /dev/null
+++ b/src/cmd/ksh93/bltins/mkservice.c
@@ -0,0 +1,494 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * mkservice varname pathname
+ * eloop [-t timeout]
+ * Written by David Korn
+ * AT&T Labs
+ */
+
+static const char mkservice_usage[] =
+"[-?\n@(#)$Id: mkservice (AT&T Research) 2001-06-13 $\n]"
+USAGE_LICENSE
+"[+NAME? mkservice - create a shell server ]"
+"[+DESCRIPTION?\bmkservice\b creates a tcp or udp server that is "
+ "implemented by shell functions.]"
+"[+?The \aservice_path\a must be of the form \b/dev/tcp/localhost/\b\aportno\a "
+ "or \b/dev/udp/localhost/\b\aportno\a depending on whether the "
+ "\btcp\b or \budp\b protocol is used. \aportno\a is the port "
+ "number that the service will use.]"
+"[+?The shell variable \avarname\a is associated with the service. This "
+ "variable can have subvariables that keeps the state of all "
+ "active connections. The functions \avarname\a\b.accept\b, "
+ "\avarname\a\b.action\b and \avarname\a\b.close\b implement the "
+ "service as follows:]{"
+ "[+accept?This function is invoked when a client tries to connect "
+ "to the service. It is called with an argument which "
+ "is the file descriptor number associated with the "
+ "accepted connection. If the function returns a non-zero "
+ "value, this connection will be closed.]"
+ "[+action?This function is invoked when there is data waiting "
+ "to be read from one of the active connections. It is "
+ "called with the file descriptor number that has data "
+ "to be read. If the function returns a non-zero "
+ "value, this connection will be closed.]"
+ "[+close?This function is invoked when the connection is closed.]"
+ "}"
+"[+?If \avarname\a is unset, then all active connection, and the service "
+ "itself will be closed.]"
+""
+"\n"
+"\nvarname service_path\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Success.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\beloop\b(1)]"
+;
+
+
+static const char eloop_usage[] =
+"[-?\n@(#)$Id: eloop (AT&T Research) 2001-06-13 $\n]"
+USAGE_LICENSE
+"[+NAME? eloop - process event loop]"
+"[+DESCRIPTION?\beloop\b causes the shell to block waiting for events "
+ "to process. By default, \beloop\b does not return.]"
+"[t]#[timeout?\atimeout\a is the number of milliseconds to wait "
+ "without receiving any events to process.]"
+"\n"
+"\n\n"
+"\n"
+"[+EXIT STATUS?If no timeout is specified, \beloop\b will not return "
+ "unless interrupted. Otherwise]{"
+ "[+0?The specified timeout interval occurred.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bmkservice\b(1)]"
+;
+
+
+#include "defs.h"
+
+#include <cmd.h>
+#include <error.h>
+#include <nval.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#define ACCEPT 0
+#define ACTION 1
+#define CLOSE 2
+
+#ifndef O_SERVICE
+# define O_SERVICE O_NOCTTY
+#endif
+
+static const char* disctab[] =
+{
+ "accept",
+ "action",
+ "close",
+ 0
+};
+
+typedef struct Service_s Service_t;
+
+struct Service_s
+{
+ Namfun_t fun;
+ short fd;
+ int refcount;
+ int (*acceptf)(Service_t*,int);
+ int (*actionf)(Service_t*,int,int);
+ int (*errorf)(Service_t*,int,const char*, ...);
+ void *context;
+ Namval_t* node;
+ Namval_t* disc[elementsof(disctab)-1];
+};
+
+static short *file_list;
+static Sfio_t **poll_list;
+static Service_t **service_list;
+static int npoll;
+static int nready;
+static int ready;
+static int (*covered_fdnotify)(int, int);
+
+static int fdclose(Service_t *sp, register int fd)
+{
+ register int i;
+ service_list[fd] = 0;
+ if(sp->fd==fd)
+ sp->fd = -1;
+ for(i=0; i < npoll; i++)
+ {
+ if(file_list[i]==fd)
+ {
+ file_list[i] = file_list[npoll--];
+ if(sp->actionf)
+ (*sp->actionf)(sp, fd, 1);
+ return(1);
+ }
+ }
+ return(0);
+}
+
+static int fdnotify(int fd1, int fd2)
+{
+ Service_t *sp;
+ if (covered_fdnotify)
+ (*covered_fdnotify)(fd1, fd2);
+ if(fd2!=SH_FDCLOSE)
+ {
+ register int i;
+ service_list[fd2] = service_list[fd1];
+ service_list[fd1] = 0;
+ for(i=0; i < npoll; i++)
+ {
+ if(file_list[i]==fd1)
+ {
+ file_list[i] = fd2;
+ return(0);
+ }
+ }
+ }
+ else if(sp = service_list[fd1])
+ {
+ fdclose(sp,fd1);
+ if(--sp->refcount==0)
+ nv_unset(sp->node);
+ }
+ return(0);
+}
+
+static void process_stream(Sfio_t* iop)
+{
+ int r=0, fd = sffileno(iop);
+ Service_t * sp = service_list[fd];
+ if(fd==sp->fd) /* connection socket */
+ {
+ struct sockaddr addr;
+ socklen_t addrlen = sizeof(addr);
+ fd = accept(fd, &addr, &addrlen);
+ service_list[fd] = sp;
+ sp->refcount++;
+ file_list[npoll++] = fd;
+ if(fd>=0)
+ {
+ if(sp->acceptf)
+ r = (*sp->acceptf)(sp,fd);
+ }
+ }
+ else if(sp->actionf)
+ {
+ service_list[fd] = 0;
+ r = (*sp->actionf)(sp, fd, 0);
+ service_list[fd] = sp;
+ if(r<0)
+ close(fd);
+ }
+}
+
+static int waitnotify(int fd, long timeout, int rw)
+{
+ Sfio_t *special=0, **pstream;
+ register int i;
+
+ if (fd >= 0)
+ special = sh_fd2sfio(fd);
+ while(1)
+ {
+ pstream = poll_list;
+ while(ready < nready)
+ process_stream(pstream[ready++]);
+ if(special)
+ *pstream++ = special;
+ for(i=0; i < npoll; i++)
+ {
+ if(service_list[file_list[i]])
+ *pstream++ = sh_fd2sfio(file_list[i]);
+ }
+#if 1
+ for(i=0; i < pstream-poll_list; i++)
+ sfset(poll_list[i],SF_WRITE,0);
+#endif
+ nready = ready = 0;
+ errno = 0;
+#ifdef DEBUG
+ sfprintf(sfstderr,"before poll npoll=%d",pstream-poll_list);
+ for(i=0; i < pstream-poll_list; i++)
+ sfprintf(sfstderr," %d",sffileno(poll_list[i]));
+ sfputc(sfstderr,'\n');
+#endif
+ nready = sfpoll(poll_list,pstream-poll_list,timeout);
+#ifdef DEBUG
+ sfprintf(sfstderr,"after poll nready=%d",nready);
+ for(i=0; i < nready; i++)
+ sfprintf(sfstderr," %d",sffileno(poll_list[i]));
+ sfputc(sfstderr,'\n');
+#endif
+#if 1
+ for(i=0; i < pstream-poll_list; i++)
+ sfset(poll_list[i],SF_WRITE,1);
+#endif
+ if(nready<=0)
+ return(errno? -1: 0);
+ if(special && poll_list[0]==special)
+ {
+ ready = 1;
+ return(fd);
+ }
+ }
+}
+
+static int service_init(void)
+{
+ file_list = newof(NULL,short,n,0);
+ poll_list = newof(NULL,Sfio_t*,n,0);
+ service_list = newof(NULL,Service_t*,n,0);
+ covered_fdnotify = sh_fdnotify(fdnotify);
+ sh_waitnotify(waitnotify);
+ return(1);
+}
+
+void service_add(Service_t *sp)
+{
+ static int init;
+ if (!init)
+ init = service_init();
+ service_list[sp->fd] = sp;
+ file_list[npoll++] = sp->fd;
+}
+
+static int Accept(register Service_t *sp, int accept_fd)
+{
+ register Namval_t* nq = sp->disc[ACCEPT];
+ int fd;
+
+ fd = fcntl(accept_fd, F_DUPFD, 10);
+ if (fd >= 0)
+ {
+ close(accept_fd);
+ if (nq)
+ {
+ char* av[3];
+ char buff[20];
+
+ av[1] = buff;
+ av[2] = 0;
+ sfsprintf(buff, sizeof(buff), "%d", fd);
+ if (sh_fun(nq, sp->node, av))
+ {
+ close(fd);
+ return -1;
+ }
+ }
+ }
+ sfsync(NiL);
+ return fd;
+}
+
+static int Action(Service_t *sp, int fd, int close)
+{
+ register Namval_t* nq;
+ int r=0;
+
+ if(close)
+ nq = sp->disc[CLOSE];
+ else
+ nq = sp->disc[ACTION];
+ if (nq)
+ {
+ char* av[3];
+ char buff[20];
+
+ av[1] = buff;
+ av[2] = 0;
+ sfsprintf(buff, sizeof(buff), "%d", fd);
+ r=sh_fun(nq, sp->node, av);
+ }
+ sfsync(NiL);
+ return r > 0 ? -1 : 1;
+}
+
+static int Error(Service_t *sp, int level, const char* arg, ...)
+{
+ va_list ap;
+
+ va_start(ap, arg);
+ if(sp->node)
+ nv_unset(sp->node);
+ free((void*)sp);
+ errorv(NiL, ERROR_exit(1), ap);
+ va_end(ap);
+ return 0;
+}
+
+static char* setdisc(Namval_t* np, const char* event, Namval_t* action, Namfun_t* fp)
+{
+ register Service_t* sp = (Service_t*)fp;
+ register const char* cp;
+ register int i;
+ register int n = strlen(event) - 1;
+ register Namval_t* nq;
+
+ for (i = 0; cp = disctab[i]; i++)
+ {
+ if (memcmp(event, cp, n))
+ continue;
+ if (action == np)
+ action = sp->disc[i];
+ else
+ {
+ if (nq = sp->disc[i])
+ free((void*)nq);
+ if (action)
+ sp->disc[i] = action;
+ else
+ sp->disc[i] = 0;
+ }
+ return action ? (char*)action : "";
+ }
+ /* try the next level */
+ return nv_setdisc(np, event, action, fp);
+}
+
+static void putval(Namval_t* np, const char* val, int flag, Namfun_t* fp)
+{
+ register Service_t* sp = (Service_t*)fp;
+ if (!val)
+ fp = nv_stack(np, NiL);
+ nv_putv(np, val, flag, fp);
+ if (!val)
+ {
+ register int i;
+ for(i=0; i< sh.lim.open_max; i++)
+ {
+ if(service_list[i]==sp)
+ {
+ close(i);
+ if(--sp->refcount<=0)
+ break;
+ }
+ }
+ free((void*)fp);
+ return;
+ }
+}
+
+static const Namdisc_t servdisc =
+{
+ sizeof(Service_t),
+ putval,
+ 0,
+ 0,
+ setdisc
+};
+
+int b_mkservice(int argc, char** argv, Shbltin_t *context)
+{
+ register char* var;
+ register char* path;
+ register Namval_t* np;
+ register Service_t* sp;
+ register int fd;
+
+ NOT_USED(argc);
+ NOT_USED(context);
+ for (;;)
+ {
+ switch (optget(argv, mkservice_usage))
+ {
+ case 0:
+ break;
+ case ':':
+ error(2, opt_info.arg);
+ continue;
+ case '?':
+ error(ERROR_usage(2), opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || !(var = *argv++) || !(path = *argv++) || *argv)
+ error(ERROR_usage(2), optusage(NiL));
+ if (!(sp = newof(0, Service_t, 1, 0)))
+ error(ERROR_exit(1), "out of space");
+ sp->acceptf = Accept;
+ sp->actionf = Action;
+ sp->errorf = Error;
+ sp->refcount = 1;
+ sp->context = context;
+ sp->node = 0;
+ sp->fun.disc = &servdisc;
+ if((fd = sh_open(path, O_SERVICE|O_RDWR))<=0)
+ {
+ free((void*)sp);
+ error(ERROR_exit(1), "%s: cannot start service", path);
+ }
+ if((sp->fd = fcntl(fd, F_DUPFD, 10))>=10)
+ close(fd);
+ else
+ sp->fd = fd;
+ np = nv_open(var,sh.var_tree,NV_ARRAY|NV_VARNAME|NV_NOASSIGN);
+ sp->node = np;
+ nv_putval(np, path, 0);
+ nv_stack(np, (Namfun_t*)sp);
+ service_add(sp);
+ return(0);
+}
+
+int b_eloop(int argc, char** argv, Shbltin_t *context)
+{
+ register long timeout = -1;
+ NOT_USED(argc);
+ NOT_USED(context);
+ for (;;)
+ {
+ switch (optget(argv, eloop_usage))
+ {
+ case 0:
+ break;
+ case 't':
+ timeout = opt_info.num;
+ continue;
+ case ':':
+ error(2, opt_info.arg);
+ continue;
+ case '?':
+ error(ERROR_usage(2), opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || *argv)
+ error(ERROR_usage(2), optusage(NiL));
+ while(1)
+ {
+ if(waitnotify(-1, timeout, 0)==0)
+ break;
+ sfprintf(sfstderr,"interrupted\n");
+ }
+ return(errno != 0);
+}
diff --git a/src/cmd/ksh93/bltins/print.c b/src/cmd/ksh93/bltins/print.c
new file mode 100644
index 0000000..011bccd
--- /dev/null
+++ b/src/cmd/ksh93/bltins/print.c
@@ -0,0 +1,1058 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * echo [arg...]
+ * print [-nrps] [-f format] [-u filenum] [arg...]
+ * printf format [arg...]
+ *
+ * David Korn
+ * AT&T Labs
+ */
+
+#include "defs.h"
+#include <error.h>
+#include <stak.h>
+#include "io.h"
+#include "name.h"
+#include "history.h"
+#include "builtins.h"
+#include "streval.h"
+#include <tmx.h>
+#include <ccode.h>
+
+union types_t
+{
+ unsigned char c;
+ short h;
+ int i;
+ long l;
+ Sflong_t ll;
+ Sfdouble_t ld;
+ double d;
+ float f;
+ char *s;
+ int *ip;
+ char **p;
+};
+
+struct printf
+{
+ Sffmt_t hdr;
+ int argsize;
+ int intvar;
+ char **nextarg;
+ char *lastarg;
+ char cescape;
+ char err;
+ Shell_t *sh;
+};
+
+static int extend(Sfio_t*,void*, Sffmt_t*);
+static const char preformat[] = "";
+static char *genformat(char*);
+static int fmtvecho(const char*, struct printf*);
+static ssize_t fmtbase64(Sfio_t*, char*, int);
+
+struct print
+{
+ Shell_t *sh;
+ const char *options;
+ char raw;
+ char echon;
+};
+
+static char* nullarg[] = { 0, 0 };
+
+#if !SHOPT_ECHOPRINT
+ int B_echo(int argc, char *argv[],Shbltin_t *context)
+ {
+ static char bsd_univ;
+ struct print prdata;
+ prdata.options = sh_optecho+5;
+ prdata.raw = prdata.echon = 0;
+ prdata.sh = context->shp;
+ NOT_USED(argc);
+ /* This mess is because /bin/echo on BSD is different */
+ if(!prdata.sh->universe)
+ {
+ register char *universe;
+ if(universe=astconf("UNIVERSE",0,0))
+ bsd_univ = (strcmp(universe,"ucb")==0);
+ prdata.sh->universe = 1;
+ }
+ if(!bsd_univ)
+ return(b_print(0,argv,(Shbltin_t*)&prdata));
+ prdata.options = sh_optecho;
+ prdata.raw = 1;
+ while(argv[1] && *argv[1]=='-')
+ {
+ if(strcmp(argv[1],"-n")==0)
+ prdata.echon = 1;
+#if !SHOPT_ECHOE
+ else if(strcmp(argv[1],"-e")==0)
+ prdata.raw = 0;
+ else if(strcmp(argv[1],"-ne")==0 || strcmp(argv[1],"-en")==0)
+ {
+ prdata.raw = 0;
+ prdata.echon = 1;
+ }
+#endif /* SHOPT_ECHOE */
+ else
+ break;
+ argv++;
+ }
+ return(b_print(0,argv,(Shbltin_t*)&prdata));
+ }
+#endif /* SHOPT_ECHOPRINT */
+
+int b_printf(int argc, char *argv[],Shbltin_t *context)
+{
+ struct print prdata;
+ NOT_USED(argc);
+ memset(&prdata,0,sizeof(prdata));
+ prdata.sh = context->shp;
+ prdata.options = sh_optprintf;
+ return(b_print(-1,argv,(Shbltin_t*)&prdata));
+}
+
+/*
+ * argc==0 when called from echo
+ * argc==-1 when called from printf
+ */
+
+int b_print(int argc, char *argv[], Shbltin_t *context)
+{
+ register Sfio_t *outfile;
+ register int exitval=0,n, fd = 1;
+ register Shell_t *shp = context->shp;
+ const char *options, *msg = e_file+4;
+ char *format = 0;
+ int sflag = 0, nflag=0, rflag=0, vflag=0;
+ if(argc>0)
+ {
+ options = sh_optprint;
+ nflag = rflag = 0;
+ format = 0;
+ }
+ else
+ {
+ struct print *pp = (struct print*)context;
+ shp = pp->sh;
+ options = pp->options;
+ if(argc==0)
+ {
+ nflag = pp->echon;
+ rflag = pp->raw;
+ argv++;
+ goto skip;
+ }
+ }
+ while((n = optget(argv,options))) switch(n)
+ {
+ case 'n':
+ nflag++;
+ break;
+ case 'p':
+ fd = shp->coutpipe;
+ msg = e_query;
+ break;
+ case 'f':
+ format = opt_info.arg;
+ break;
+ case 's':
+ /* print to history file */
+ if(!sh_histinit((void*)shp))
+ errormsg(SH_DICT,ERROR_system(1),e_history);
+ fd = sffileno(shp->gd->hist_ptr->histfp);
+ sh_onstate(SH_HISTORY);
+ sflag++;
+ break;
+ case 'e':
+ rflag = 0;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 'u':
+ fd = (int)strtol(opt_info.arg,&opt_info.arg,10);
+ if(*opt_info.arg)
+ fd = -1;
+ else if(!sh_iovalidfd(shp,fd))
+ fd = -1;
+ else if(!(shp->inuse_bits&(1<<fd)) && (sh_inuse(shp,fd) || (shp->gd->hist_ptr && fd==sffileno(shp->gd->hist_ptr->histfp))))
+
+ fd = -1;
+ break;
+ case 'v':
+ vflag='v';
+ break;
+ case 'C':
+ vflag='C';
+ break;
+ case ':':
+ /* The following is for backward compatibility */
+#if OPT_VERSION >= 19990123
+ if(strcmp(opt_info.name,"-R")==0)
+#else
+ if(strcmp(opt_info.option,"-R")==0)
+#endif
+ {
+ rflag = 1;
+ if(error_info.errors==0)
+ {
+ argv += opt_info.index+1;
+ /* special case test for -Rn */
+ if(strchr(argv[-1],'n'))
+ nflag++;
+ if(*argv && strcmp(*argv,"-n")==0)
+ {
+
+ nflag++;
+ argv++;
+ }
+ goto skip2;
+ }
+ }
+ else
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors || (argc<0 && !(format = *argv++)))
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(vflag && format)
+ errormsg(SH_DICT,ERROR_usage(2),"-%c and -f are mutually exclusive",vflag);
+skip:
+ if(format)
+ format = genformat(format);
+ /* handle special case of '-' operand for print */
+ if(argc>0 && *argv && strcmp(*argv,"-")==0 && strcmp(argv[-1],"--"))
+ argv++;
+skip2:
+ if(fd < 0)
+ {
+ errno = EBADF;
+ n = 0;
+ }
+ else if(!(n=shp->fdstatus[fd]))
+ n = sh_iocheckfd(shp,fd);
+ if(!(n&IOWRITE))
+ {
+ /* don't print error message for stdout for compatibility */
+ if(fd==1)
+ return(1);
+ errormsg(SH_DICT,ERROR_system(1),msg);
+ }
+ if(!(outfile=shp->sftable[fd]))
+ {
+ sh_onstate(SH_NOTRACK);
+ n = SF_WRITE|((n&IOREAD)?SF_READ:0);
+ shp->sftable[fd] = outfile = sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fd,n);
+ sh_offstate(SH_NOTRACK);
+ sfpool(outfile,shp->outpool,SF_WRITE);
+ }
+ /* turn off share to guarantee atomic writes for printf */
+ n = sfset(outfile,SF_SHARE|SF_PUBLIC,0);
+ if(format)
+ {
+ /* printf style print */
+ Sfio_t *pool;
+ struct printf pdata;
+ memset(&pdata, 0, sizeof(pdata));
+ pdata.sh = shp;
+ pdata.hdr.version = SFIO_VERSION;
+ pdata.hdr.extf = extend;
+ pdata.nextarg = argv;
+ sh_offstate(SH_STOPOK);
+ pool=sfpool(sfstderr,NIL(Sfio_t*),SF_WRITE);
+ do
+ {
+ if(shp->trapnote&SH_SIGSET)
+ break;
+ pdata.hdr.form = format;
+ sfprintf(outfile,"%!",&pdata);
+ } while(*pdata.nextarg && pdata.nextarg!=argv);
+ if(pdata.nextarg == nullarg && pdata.argsize>0)
+ sfwrite(outfile,stakptr(staktell()),pdata.argsize);
+ if(sffileno(outfile)!=sffileno(sfstderr))
+ sfsync(outfile);
+ sfpool(sfstderr,pool,SF_WRITE);
+ exitval = pdata.err;
+ }
+ else if(vflag)
+ {
+ while(*argv)
+ {
+ fmtbase64(outfile,*argv++,vflag=='C');
+ if(!nflag)
+ sfputc(outfile,'\n');
+ }
+ }
+ else
+ {
+ /* echo style print */
+ if(nflag && !argv[0])
+ sfsync((Sfio_t*)0);
+ else if(sh_echolist(shp,outfile,rflag,argv) && !nflag)
+ sfputc(outfile,'\n');
+ }
+ if(sflag)
+ {
+ hist_flush(shp->gd->hist_ptr);
+ sh_offstate(SH_HISTORY);
+ }
+ else if(n&SF_SHARE)
+ {
+ sfset(outfile,SF_SHARE|SF_PUBLIC,1);
+ sfsync(outfile);
+ }
+ return(exitval);
+}
+
+/*
+ * echo the argument list onto <outfile>
+ * if <raw> is non-zero then \ is not a special character.
+ * returns 0 for \c otherwise 1.
+ */
+
+int sh_echolist(Shell_t *shp,Sfio_t *outfile, int raw, char *argv[])
+{
+ register char *cp;
+ register int n;
+ struct printf pdata;
+ pdata.cescape = 0;
+ pdata.err = 0;
+ while(!pdata.cescape && (cp= *argv++))
+ {
+ if(!raw && (n=fmtvecho(cp,&pdata))>=0)
+ {
+ if(n)
+ sfwrite(outfile,stakptr(staktell()),n);
+ }
+ else
+ sfputr(outfile,cp,-1);
+ if(*argv)
+ sfputc(outfile,' ');
+ sh_sigcheck(shp);
+ }
+ return(!pdata.cescape);
+}
+
+/*
+ * modified version of stresc for generating formats
+ */
+static char strformat(char *s)
+{
+ register char* t;
+ register int c;
+ char* b;
+ char* p;
+#if SHOPT_MULTIBYTE && defined(FMT_EXP_WIDE)
+ int w;
+#endif
+
+ b = t = s;
+ for (;;)
+ {
+ switch (c = *s++)
+ {
+ case '\\':
+ if(*s==0)
+ break;
+#if SHOPT_MULTIBYTE && defined(FMT_EXP_WIDE)
+ c = chrexp(s - 1, &p, &w, FMT_EXP_CHAR|FMT_EXP_LINE|FMT_EXP_WIDE);
+#else
+ c = chresc(s - 1, &p);
+#endif
+ s = p;
+#if SHOPT_MULTIBYTE
+#if defined(FMT_EXP_WIDE)
+ if(w)
+ {
+ t += mbwide() ? mbconv(t, c) : wc2utf8(t, c);
+ continue;
+ }
+#else
+ if(c>UCHAR_MAX && mbwide())
+ {
+ t += mbconv(t, c);
+ continue;
+ }
+#endif /* FMT_EXP_WIDE */
+#endif /* SHOPT_MULTIBYTE */
+ if(c=='%')
+ *t++ = '%';
+ else if(c==0)
+ {
+ *t++ = '%';
+ c = 'Z';
+ }
+ break;
+ case 0:
+ *t = 0;
+ return(t - b);
+ }
+ *t++ = c;
+ }
+}
+
+
+static char *genformat(char *format)
+{
+ register char *fp;
+ stakseek(0);
+ stakputs(preformat);
+ stakputs(format);
+ fp = (char*)stakfreeze(1);
+ strformat(fp+sizeof(preformat)-1);
+ return(fp);
+}
+
+static char *fmthtml(const char *string, int flags)
+{
+ register const char *cp = string;
+ register int c, offset = staktell();
+ if(!(flags&SFFMT_ALTER))
+ {
+ while(c= *(unsigned char*)cp++)
+ {
+#if SHOPT_MULTIBYTE
+ register int s;
+ if((s=mbsize(cp-1)) > 1)
+ {
+ cp += (s-1);
+ continue;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ if(c=='<')
+ stakputs("&lt;");
+ else if(c=='>')
+ stakputs("&gt;");
+ else if(c=='&')
+ stakputs("&amp;");
+ else if(c=='"')
+ stakputs("&quot;");
+ else if(c=='\'')
+ stakputs("&apos;");
+ else if(c==' ')
+ stakputs("&nbsp;");
+ else if(!isprint(c) && c!='\n' && c!='\r')
+ sfprintf(stkstd,"&#%X;",CCMAPC(c,CC_NATIVE,CC_ASCII));
+ else
+ stakputc(c);
+ }
+ }
+ else
+ {
+ while(c= *(unsigned char*)cp++)
+ {
+ if(strchr("!*'();@&+$,#[]<>~.\"{}|\\-`^% ",c) || (!isprint(c) && c!='\n' && c!='\r'))
+ sfprintf(stkstd,"%%%02X",CCMAPC(c,CC_NATIVE,CC_ASCII));
+ else
+ stakputc(c);
+ }
+ }
+ stakputc(0);
+ return(stakptr(offset));
+}
+
+#if 1
+static ssize_t fmtbase64(Sfio_t *iop, char *string, int alt)
+#else
+static void *fmtbase64(char *string, ssize_t *sz, int alt)
+#endif
+{
+ char *cp;
+ Sfdouble_t d;
+ ssize_t size;
+ Namval_t *np = nv_open(string, NiL, NV_VARNAME|NV_NOASSIGN|NV_NOADD);
+ Namarr_t *ap;
+ static union types_t number;
+ if(!np || nv_isnull(np))
+ {
+ if(sh_isoption(SH_NOUNSET))
+ errormsg(SH_DICT,ERROR_exit(1),e_notset,string);
+ return(0);
+ }
+ if(nv_isattr(np,NV_INTEGER))
+ {
+ d = nv_getnum(np);
+ if(nv_isattr(np,NV_DOUBLE))
+ {
+ if(nv_isattr(np,NV_LONG))
+ {
+ size = sizeof(Sfdouble_t);
+ number.ld = d;
+ }
+ else if(nv_isattr(np,NV_SHORT))
+ {
+ size = sizeof(float);
+ number.f = (float)d;
+ }
+ else
+ {
+ size = sizeof(double);
+ number.d = (double)d;
+ }
+ }
+ else
+ {
+ if(nv_isattr(np,NV_LONG))
+ {
+ size = sizeof(Sflong_t);
+ number.ll = (Sflong_t)d;
+ }
+ else if(nv_isattr(np,NV_SHORT))
+ {
+ size = sizeof(short);
+ number.h = (short)d;
+ }
+ else
+ {
+ size = sizeof(short);
+ number.i = (int)d;
+ }
+ }
+#if 1
+ return(sfwrite(iop, (void*)&number, size));
+#else
+ if(sz)
+ *sz = size;
+ return((void*)&number);
+#endif
+ }
+ if(nv_isattr(np,NV_BINARY))
+#if 1
+ {
+ Namfun_t *fp;
+ for(fp=np->nvfun; fp;fp=fp->next)
+ {
+ if(fp->disc && fp->disc->writef)
+ break;
+ }
+ if(fp)
+ return (*fp->disc->writef)(np, iop, 0, fp);
+ else
+ {
+ int n = nv_size(np);
+ if(nv_isarray(np))
+ {
+ nv_onattr(np,NV_RAW);
+ cp = nv_getval(np);
+ nv_offattr(np,NV_RAW);
+ }
+ else
+ cp = (char*)np->nvalue.cp;
+ if((size = n)==0)
+ size = strlen(cp);
+ size = sfwrite(iop, cp, size);
+ return(n?n:size);
+ }
+ }
+ else if(nv_isarray(np) && (ap=nv_arrayptr(np)) && array_elem(ap) && (ap->nelem&(ARRAY_UNDEF|ARRAY_SCAN)))
+ {
+ nv_outnode(np,iop,(alt?-1:0),0);
+ sfputc(iop,')');
+ return(sftell(iop));
+ }
+ else
+ {
+ if(alt && nv_isvtree(np))
+ nv_onattr(np,NV_EXPORT);
+ else
+ alt = 0;
+ cp = nv_getval(np);
+ if(alt)
+ nv_offattr(np,NV_EXPORT);
+ if(!cp)
+ return(0);
+ size = strlen(cp);
+ return(sfwrite(iop,cp,size));
+ }
+#else
+ nv_onattr(np,NV_RAW);
+ cp = nv_getval(np);
+ if(nv_isattr(np,NV_BINARY))
+ nv_offattr(np,NV_RAW);
+ if((size = nv_size(np))==0)
+ size = strlen(cp);
+ if(sz)
+ *sz = size;
+ return((void*)cp);
+#endif
+}
+
+static int varname(const char *str, int n)
+{
+ register int c,dot=1,len=1;
+ if(n < 0)
+ {
+ if(*str=='.')
+ str++;
+ n = strlen(str);
+ }
+ for(;n > 0; n-=len)
+ {
+#ifdef SHOPT_MULTIBYTE
+ len = mbsize(str);
+ c = mbchar(str);
+#else
+ c = *(unsigned char*)str++;
+#endif
+ if(dot && !(isalpha(c)||c=='_'))
+ break;
+ else if(dot==0 && !(isalnum(c) || c=='_' || c == '.'))
+ break;
+ dot = (c=='.');
+ }
+ return(n==0);
+}
+
+static int extend(Sfio_t* sp, void* v, Sffmt_t* fe)
+{
+ char* lastchar = "";
+ register int neg = 0;
+ Sfdouble_t d;
+ Sfdouble_t longmin = LDBL_LLONG_MIN;
+ Sfdouble_t longmax = LDBL_LLONG_MAX;
+ int format = fe->fmt;
+ int n;
+ int fold = fe->base;
+ union types_t* value = (union types_t*)v;
+ struct printf* pp = (struct printf*)fe;
+ Shell_t *shp = pp->sh;
+ register char* argp = *pp->nextarg;
+ char *w,*s;
+
+ if(fe->n_str>0 && varname(fe->t_str,fe->n_str) && (!argp || varname(argp,-1)))
+ {
+ if(argp)
+ pp->lastarg = argp;
+ else
+ argp = pp->lastarg;
+ if(argp)
+ {
+ sfprintf(pp->sh->strbuf,"%s.%.*s%c",argp,fe->n_str,fe->t_str,0);
+ argp = sfstruse(pp->sh->strbuf);
+ }
+ }
+ else
+ pp->lastarg = 0;
+ fe->flags |= SFFMT_VALUE;
+ if(!argp || format=='Z')
+ {
+ switch(format)
+ {
+ case 'c':
+ value->c = 0;
+ fe->flags &= ~SFFMT_LONG;
+ break;
+ case 'q':
+ format = 's';
+ /* FALL THROUGH */
+ case 's':
+ case 'H':
+ case 'B':
+ case 'P':
+ case 'R':
+ case 'Z':
+ case 'b':
+ fe->fmt = 's';
+ fe->size = -1;
+ fe->base = -1;
+ value->s = "";
+ fe->flags &= ~SFFMT_LONG;
+ break;
+ case 'a':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'A':
+ case 'E':
+ case 'F':
+ case 'G':
+ if(SFFMT_LDOUBLE)
+ value->ld = 0.;
+ else
+ value->d = 0.;
+ break;
+ case 'n':
+ value->ip = &pp->intvar;
+ break;
+ case 'Q':
+ value->ll = 0;
+ break;
+ case 'T':
+ fe->fmt = 'd';
+ value->ll = tmxgettime();
+ break;
+ default:
+ if(!strchr("DdXxoUu",format))
+ errormsg(SH_DICT,ERROR_exit(1),e_formspec,format);
+ fe->fmt = 'd';
+ value->ll = 0;
+ break;
+ }
+ }
+ else
+ {
+ switch(format)
+ {
+ case 'p':
+ value->p = (char**)strtol(argp,&lastchar,10);
+ break;
+ case 'n':
+ {
+ Namval_t *np;
+ np = nv_open(argp,shp->var_tree,NV_VARNAME|NV_NOASSIGN|NV_NOARRAY);
+ _nv_unset(np,0);
+ nv_onattr(np,NV_INTEGER);
+ if (np->nvalue.lp = new_of(int32_t,0))
+ *np->nvalue.lp = 0;
+ nv_setsize(np,10);
+ if(sizeof(int)==sizeof(int32_t))
+ value->ip = (int*)np->nvalue.lp;
+ else
+ {
+ int32_t sl = 1;
+ value->ip = (int*)(((char*)np->nvalue.lp) + (*((char*)&sl) ? 0 : sizeof(int)));
+ }
+ nv_close(np);
+ break;
+ }
+ case 'q':
+ case 'b':
+ case 's':
+ case 'B':
+ case 'H':
+ case 'P':
+ case 'R':
+ fe->fmt = 's';
+ fe->size = -1;
+ if(format=='s' && fe->base>=0)
+ {
+ value->p = pp->nextarg;
+ pp->nextarg = nullarg;
+ }
+ else
+ {
+ fe->base = -1;
+ value->s = argp;
+ }
+ fe->flags &= ~SFFMT_LONG;
+ break;
+ case 'c':
+ if(mbwide() && (n = mbsize(argp)) > 1)
+ {
+ fe->fmt = 's';
+ fe->size = n;
+ value->s = argp;
+ }
+ else if(fe->base >=0)
+ value->s = argp;
+ else
+ value->c = *argp;
+ fe->flags &= ~SFFMT_LONG;
+ break;
+ case 'o':
+ case 'x':
+ case 'X':
+ case 'u':
+ case 'U':
+ longmax = LDBL_ULLONG_MAX;
+ case '.':
+ if(fe->size==2 && strchr("bcsqHPRQTZ",*fe->form))
+ {
+ value->ll = ((unsigned char*)argp)[0];
+ break;
+ }
+ case 'd':
+ case 'D':
+ case 'i':
+ switch(*argp)
+ {
+ case '\'':
+ case '"':
+ w = argp + 1;
+ if(mbwide() && mbsize(w) > 1)
+ value->ll = mbchar(w);
+ else
+ value->ll = *(unsigned char*)w++;
+ if(w[0] && (w[0] != argp[0] || w[1]))
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_charconst,argp);
+ pp->err = 1;
+ }
+ break;
+ default:
+ d = sh_strnum(argp,&lastchar,0);
+ if(d<longmin)
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_overflow,argp);
+ pp->err = 1;
+ d = longmin;
+ }
+ else if(d>longmax)
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_overflow,argp);
+ pp->err = 1;
+ d = longmax;
+ }
+ value->ll = (Sflong_t)d;
+ if(lastchar == *pp->nextarg)
+ {
+ value->ll = *argp;
+ lastchar = "";
+ }
+ break;
+ }
+ if(neg)
+ value->ll = -value->ll;
+ fe->size = sizeof(value->ll);
+ break;
+ case 'a':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'A':
+ case 'E':
+ case 'F':
+ case 'G':
+ d = sh_strnum(*pp->nextarg,&lastchar,0);
+ switch(*argp)
+ {
+ case '\'':
+ case '"':
+ d = ((unsigned char*)argp)[1];
+ if(argp[2] && (argp[2] != argp[0] || argp[3]))
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_charconst,argp);
+ pp->err = 1;
+ }
+ break;
+ default:
+ d = sh_strnum(*pp->nextarg,&lastchar,0);
+ break;
+ }
+ if(SFFMT_LDOUBLE)
+ {
+ value->ld = d;
+ fe->size = sizeof(value->ld);
+ }
+ else
+ {
+ value->d = d;
+ fe->size = sizeof(value->d);
+ }
+ break;
+ case 'Q':
+ value->ll = (Sflong_t)strelapsed(*pp->nextarg,&lastchar,1);
+ break;
+ case 'T':
+ value->ll = (Sflong_t)tmxdate(*pp->nextarg,&lastchar,TMX_NOW);
+ break;
+ default:
+ value->ll = 0;
+ fe->fmt = 'd';
+ fe->size = sizeof(value->ll);
+ errormsg(SH_DICT,ERROR_exit(1),e_formspec,format);
+ break;
+ }
+ if (format == '.')
+ value->i = value->ll;
+ if(*lastchar)
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_argtype,format);
+ pp->err = 1;
+ }
+ pp->nextarg++;
+ }
+ switch(format)
+ {
+ case 'Z':
+ fe->fmt = 'c';
+ fe->base = -1;
+ value->c = 0;
+ break;
+ case 'b':
+ if((n=fmtvecho(value->s,pp))>=0)
+ {
+ if(pp->nextarg == nullarg)
+ {
+ pp->argsize = n;
+ return -1;
+ }
+ value->s = stakptr(staktell());
+ fe->size = n;
+ }
+ break;
+ case 'B':
+ if(!shp->strbuf2)
+ shp->strbuf2 = sfstropen();
+ fe->size = fmtbase64(shp->strbuf2,value->s, fe->flags&SFFMT_ALTER);
+ value->s = sfstruse(shp->strbuf2);
+ fe->flags |= SFFMT_SHORT;
+ break;
+ case 'H':
+ value->s = fmthtml(value->s, fe->flags);
+ break;
+ case 'q':
+ value->s = sh_fmtqf(value->s, !!(fe->flags & SFFMT_ALTER), fold);
+ break;
+ case 'P':
+ s = fmtmatch(value->s);
+ if(!s || *s==0)
+ errormsg(SH_DICT,ERROR_exit(1),e_badregexp,value->s);
+ value->s = s;
+ break;
+ case 'R':
+ s = fmtre(value->s);
+ if(!s || *s==0)
+ errormsg(SH_DICT,ERROR_exit(1),e_badregexp,value->s);
+ value->s = s;
+ break;
+ case 'Q':
+ if (fe->n_str>0)
+ {
+ fe->fmt = 'd';
+ fe->size = sizeof(value->ll);
+ }
+ else
+ {
+ value->s = fmtelapsed(value->ll, 1);
+ fe->fmt = 's';
+ fe->size = -1;
+ }
+ break;
+ case 'T':
+ if(fe->n_str>0)
+ {
+ n = fe->t_str[fe->n_str];
+ fe->t_str[fe->n_str] = 0;
+ value->s = fmttmx(fe->t_str, value->ll);
+ fe->t_str[fe->n_str] = n;
+ }
+ else value->s = fmttmx(NIL(char*), value->ll);
+ fe->fmt = 's';
+ fe->size = -1;
+ break;
+ }
+ return 0;
+}
+
+/*
+ * construct System V echo string out of <cp>
+ * If there are not escape sequences, returns -1
+ * Otherwise, puts null terminated result on stack, but doesn't freeze it
+ * returns length of output.
+ */
+
+static int fmtvecho(const char *string, struct printf *pp)
+{
+ register const char *cp = string, *cpmax;
+ register int c;
+ register int offset = staktell();
+#if SHOPT_MULTIBYTE
+ int chlen;
+ if(mbwide())
+ {
+ while(1)
+ {
+ if ((chlen = mbsize(cp)) > 1)
+ /* Skip over multibyte characters */
+ cp += chlen;
+ else if((c= *cp++)==0 || c == '\\')
+ break;
+ }
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ while((c= *cp++) && (c!='\\'));
+ if(c==0)
+ return(-1);
+ c = --cp - string;
+ if(c>0)
+ stakwrite((void*)string,c);
+ for(; c= *cp; cp++)
+ {
+#if SHOPT_MULTIBYTE
+ if (mbwide() && ((chlen = mbsize(cp)) > 1))
+ {
+ stakwrite(cp,chlen);
+ cp += (chlen-1);
+ continue;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ if( c=='\\') switch(*++cp)
+ {
+ case 'E':
+ c = ('a'==97?'\033':39); /* ASCII/EBCDIC */
+ break;
+ case 'a':
+ c = '\a';
+ break;
+ case 'b':
+ c = '\b';
+ break;
+ case 'c':
+ pp->cescape++;
+ pp->nextarg = nullarg;
+ goto done;
+ case 'f':
+ c = '\f';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 'v':
+ c = '\v';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ case '\\':
+ c = '\\';
+ break;
+ case '0':
+ c = 0;
+ cpmax = cp + 4;
+ while(++cp<cpmax && *cp>='0' && *cp<='7')
+ {
+ c <<= 3;
+ c |= (*cp-'0');
+ }
+ default:
+ cp--;
+ }
+ stakputc(c);
+ }
+done:
+ c = staktell()-offset;
+ stakputc(0);
+ stakseek(offset);
+ return(c);
+}
diff --git a/src/cmd/ksh93/bltins/read.c b/src/cmd/ksh93/bltins/read.c
new file mode 100644
index 0000000..75fc478
--- /dev/null
+++ b/src/cmd/ksh93/bltins/read.c
@@ -0,0 +1,802 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * read [-ACprs] [-d delim] [-u filenum] [-t timeout] [-n n] [-N n] [name...]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <error.h>
+#include "defs.h"
+#include "variables.h"
+#include "lexstates.h"
+#include "io.h"
+#include "name.h"
+#include "builtins.h"
+#include "history.h"
+#include "terminal.h"
+#include "edit.h"
+
+#define R_FLAG 1 /* raw mode */
+#define S_FLAG 2 /* save in history file */
+#define A_FLAG 4 /* read into array */
+#define N_FLAG 8 /* fixed size read at most */
+#define NN_FLAG 0x10 /* fixed size read exact */
+#define V_FLAG 0x20 /* use default value */
+#define C_FLAG 0x40 /* read into compound variable */
+#define D_FLAG 8 /* must be number of bits for all flags */
+#define SS_FLAG 0x80 /* read .csv format file */
+
+struct read_save
+{
+ char **argv;
+ char *prompt;
+ short fd;
+ short plen;
+ int flags;
+ long timeout;
+};
+
+int b_read(int argc,char *argv[], Shbltin_t *context)
+{
+ Sfdouble_t sec;
+ register char *name;
+ register int r, flags=0, fd=0;
+ register Shell_t *shp = context->shp;
+ long timeout = 1000*shp->st.tmout;
+ int save_prompt, fixargs=context->invariant;
+ struct read_save *rp;
+ static char default_prompt[3] = {ESC,ESC};
+ rp = (struct read_save*)(context->data);
+ if(argc==0)
+ {
+ if(rp)
+ free((void*)rp);
+ return(0);
+ }
+ if(rp)
+ {
+ flags = rp->flags;
+ timeout = rp->timeout;
+ fd = rp->fd;
+ argv = rp->argv;
+ name = rp->prompt;
+ r = rp->plen;
+ goto bypass;
+ }
+ while((r = optget(argv,sh_optread))) switch(r)
+ {
+ case 'A':
+ flags |= A_FLAG;
+ break;
+ case 'C':
+ flags |= C_FLAG;
+ break;
+ case 't':
+ sec = sh_strnum(opt_info.arg, (char**)0,1);
+ timeout = sec ? 1000*sec : 1;
+ break;
+ case 'd':
+ if(opt_info.arg && *opt_info.arg!='\n')
+ {
+ char *cp = opt_info.arg;
+ flags &= ~((1<<D_FLAG)-1);
+ flags |= (mbchar(cp)<< D_FLAG);
+ }
+ break;
+ case 'p':
+ if((fd = shp->cpipe[0])<=0)
+ errormsg(SH_DICT,ERROR_exit(1),e_query);
+ break;
+ case 'n': case 'N':
+ flags &= ((1<<D_FLAG)-1);
+ flags |= (r=='n'?N_FLAG:NN_FLAG);
+ r = (int)opt_info.num;
+ if((unsigned)r > (1<<((8*sizeof(int))-D_FLAG))-1)
+ errormsg(SH_DICT,ERROR_exit(1),e_overlimit,opt_info.name);
+ flags |= (r<< D_FLAG);
+ break;
+ case 'r':
+ flags |= R_FLAG;
+ break;
+ case 's':
+ /* save in history file */
+ flags |= S_FLAG;
+ break;
+ case 'S':
+ flags |= SS_FLAG;
+ break;
+ case 'u':
+ fd = (int)opt_info.num;
+ if(sh_inuse(shp,fd))
+ fd = -1;
+ break;
+ case 'v':
+ flags |= V_FLAG;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2), "%s", optusage((char*)0));
+ if(!((r=shp->fdstatus[fd])&IOREAD) || !(r&(IOSEEK|IONOSEEK)))
+ r = sh_iocheckfd(shp,fd);
+ if(fd<0 || !(r&IOREAD))
+ errormsg(SH_DICT,ERROR_system(1),e_file+4);
+ /* look for prompt */
+ if((name = *argv) && (name=strchr(name,'?')) && (r&IOTTY))
+ r = strlen(name++);
+ else
+ r = 0;
+ if(argc==fixargs && (rp=newof(NIL(struct read_save*),struct read_save,1,0)))
+ {
+ context->data = (void*)rp;
+ rp->fd = fd;
+ rp->flags = flags;
+ rp->timeout = timeout;
+ rp->argv = argv;
+ rp->prompt = name;
+ rp->plen = r;
+ }
+bypass:
+ shp->prompt = default_prompt;
+ if(r && (shp->prompt=(char*)sfreserve(sfstderr,r,SF_LOCKR)))
+ {
+ memcpy(shp->prompt,name,r);
+ sfwrite(sfstderr,shp->prompt,r-1);
+ }
+ shp->timeout = 0;
+ save_prompt = shp->nextprompt;
+ shp->nextprompt = 0;
+ r=sh_readline(shp,argv,fd,flags,timeout);
+ shp->nextprompt = save_prompt;
+ if(r==0 && (r=(sfeof(shp->sftable[fd])||sferror(shp->sftable[fd]))))
+ {
+ if(fd == shp->cpipe[0] && errno!=EINTR)
+ sh_pclose(shp->cpipe);
+ }
+ return(r);
+}
+
+/*
+ * here for read timeout
+ */
+static void timedout(void *handle)
+{
+ sfclrlock((Sfio_t*)handle);
+ sh_exit(1);
+}
+
+/*
+ * This is the code to read a line and to split it into tokens
+ * <names> is an array of variable names
+ * <fd> is the file descriptor
+ * <flags> is union of -A, -r, -s, and contains delimiter if not '\n'
+ * <timeout> is number of milli-seconds until timeout
+ */
+
+int sh_readline(register Shell_t *shp,char **names, int fd, int flags,long timeout)
+{
+ register ssize_t c;
+ register unsigned char *cp;
+ register Namval_t *np;
+ register char *name, *val;
+ register Sfio_t *iop;
+ Namfun_t *nfp;
+ char *ifs;
+ unsigned char *cpmax;
+ unsigned char *del;
+ char was_escape = 0;
+ char use_stak = 0;
+ volatile char was_write = 0;
+ volatile char was_share = 1;
+ int rel, wrd, keytrap;
+ long array_index = 0;
+ void *timeslot=0;
+ int delim = '\n';
+ int jmpval=0;
+ ssize_t size = 0;
+ int binary;
+ int oflags=NV_ASSIGN|NV_VARNAME;
+ char inquote = 0;
+ struct checkpt buff;
+ Edit_t *ep = (struct edit*)shp->gd->ed_context;
+ if(!(iop=shp->sftable[fd]) && !(iop=sh_iostream(shp,fd)))
+ return(1);
+ sh_stats(STAT_READS);
+ if(names && (name = *names))
+ {
+ Namval_t *mp;
+ if(val= strchr(name,'?'))
+ *val = 0;
+ if(flags&C_FLAG)
+ oflags |= NV_ARRAY;
+ np = nv_open(name,shp->var_tree,oflags);
+ if(np && nv_isarray(np) && (mp=nv_opensub(np)))
+ np = mp;
+ if((flags&V_FLAG) && shp->gd->ed_context)
+ ((struct edit*)shp->gd->ed_context)->e_default = np;
+ if(flags&A_FLAG)
+ {
+ flags &= ~A_FLAG;
+ array_index = 1;
+ nv_unset(np);
+ nv_putsub(np,NIL(char*),0L);
+ }
+ else if(flags&C_FLAG)
+ {
+ char *sp = np->nvenv;
+ delim = -1;
+ nv_unset(np);
+ if(!nv_isattr(np,NV_MINIMAL))
+ np->nvenv = sp;
+ nv_setvtree(np);
+ }
+ else
+ name = *++names;
+ if(val)
+ *val = '?';
+ }
+ else
+ {
+ name = 0;
+ if(dtvnext(shp->var_tree) || shp->namespace)
+ np = nv_open(nv_name(REPLYNOD),shp->var_tree,0);
+ else
+ np = REPLYNOD;
+ }
+ keytrap = ep?ep->e_keytrap:0;
+ if(flags>>D_FLAG) /* delimiter not new-line or fixed size read */
+ {
+ if(flags&(N_FLAG|NN_FLAG))
+ size = ((unsigned)flags)>>D_FLAG;
+ else
+ delim = ((unsigned)flags)>>D_FLAG;
+ if((shp->fdstatus[fd]&IOTTY) && !keytrap)
+ tty_raw(fd,1);
+ }
+ binary = nv_isattr(np,NV_BINARY);
+ if(!binary && !(flags&(N_FLAG|NN_FLAG)))
+ {
+ Namval_t *mp;
+ /* set up state table based on IFS */
+ ifs = nv_getval(mp=sh_scoped(shp,IFSNOD));
+ if((flags&R_FLAG) && shp->ifstable['\\']==S_ESC)
+ shp->ifstable['\\'] = 0;
+ else if(!(flags&R_FLAG) && shp->ifstable['\\']==0)
+ shp->ifstable['\\'] = S_ESC;
+ if(delim>0)
+ shp->ifstable[delim] = S_NL;
+ if(delim!='\n')
+ {
+ shp->ifstable['\n'] = 0;
+ nv_putval(mp, ifs, NV_RDONLY);
+ }
+ shp->ifstable[0] = S_EOF;
+ if((flags&SS_FLAG))
+ {
+ shp->ifstable['"'] = S_QUOTE;
+ shp->ifstable['\r'] = S_ERR;
+ }
+ }
+ sfclrerr(iop);
+ for(nfp=np->nvfun; nfp; nfp = nfp->next)
+ {
+ if(nfp->disc && nfp->disc->readf)
+ {
+ Namval_t *mp = nv_open(name,shp->var_tree,oflags|NV_NOREF);
+ if((c=(*nfp->disc->readf)(mp,iop,delim,nfp))>=0)
+ return(c);
+ }
+ }
+ if(binary && !(flags&(N_FLAG|NN_FLAG)))
+ {
+ flags |= NN_FLAG;
+ size = nv_size(np);
+ }
+ was_write = (sfset(iop,SF_WRITE,0)&SF_WRITE)!=0;
+ if(fd==0)
+ was_share = (sfset(iop,SF_SHARE,shp->redir0!=2)&SF_SHARE)!=0;
+ if(timeout || (shp->fdstatus[fd]&(IOTTY|IONOSEEK)))
+ {
+ sh_pushcontext(shp,&buff,1);
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval)
+ goto done;
+ if(timeout)
+ timeslot = (void*)sh_timeradd(timeout,0,timedout,(void*)iop);
+ }
+ if(flags&(N_FLAG|NN_FLAG))
+ {
+ char buf[256],*var=buf,*cur,*end,*up,*v;
+ /* reserved buffer */
+ if((c=size)>=sizeof(buf))
+ {
+ if(!(var = (char*)malloc(c+1)))
+ sh_exit(1);
+ end = var + c;
+ }
+ else
+ end = var + sizeof(buf) - 1;
+ up = cur = var;
+ if((sfset(iop,SF_SHARE,1)&SF_SHARE) && fd!=0)
+ was_share = 1;
+ if(size==0)
+ {
+ cp = sfreserve(iop,0,0);
+ c = 0;
+ }
+ else
+ {
+ ssize_t m;
+ int f;
+ for (;;)
+ {
+ c = size;
+ if(keytrap)
+ {
+ cp = 0;
+ f = 0;
+ m = 0;
+ while(c-->0 && (buf[m]=ed_getchar(ep,0)))
+ m++;
+ if(m>0)
+ cp = (unsigned char*)buf;
+ }
+ else
+ {
+ f = 1;
+ if(cp = sfreserve(iop,c,SF_LOCKR))
+ m = sfvalue(iop);
+ else if(flags&NN_FLAG)
+ {
+ c = size;
+ m = (cp = sfreserve(iop,c,0)) ? sfvalue(iop) : 0;
+ f = 0;
+ }
+ else
+ {
+ c = sfvalue(iop);
+ m = (cp = sfreserve(iop,c,SF_LOCKR)) ? sfvalue(iop) : 0;
+ }
+ }
+ if(m>0 && (flags&N_FLAG) && !binary && (v=memchr(cp,'\n',m)))
+ {
+ *v++ = 0;
+ m = v-(char*)cp;
+ }
+ if((c=m)>size)
+ c = size;
+ if(c>0)
+ {
+ if(c > (end-cur))
+ {
+ ssize_t cx = cur - var, ux = up - var;
+ m = (end - var) + (c - (end - cur));
+ if (var == buf)
+ {
+ v = (char*)malloc(m+1);
+ var = memcpy(v, var, cur - var);
+ }
+ else
+ var = newof(var, char, m, 1);
+ end = var + m;
+ cur = var + cx;
+ up = var + ux;
+ }
+ if(cur!=(char*)cp)
+ memcpy((void*)cur,cp,c);
+ if(f)
+ sfread(iop,cp,c);
+ cur += c;
+#if SHOPT_MULTIBYTE
+ if(!binary && mbwide())
+ {
+ int x;
+ int z;
+
+ mbinit();
+ *cur = 0;
+ x = z = 0;
+ while (up < cur && (z = mbsize(up)) > 0)
+ {
+ up += z;
+ x++;
+ }
+ if((size -= x) > 0 && (up >= cur || z < 0) && ((flags & NN_FLAG) || z < 0 || m > c))
+ continue;
+ }
+#endif
+ }
+#if SHOPT_MULTIBYTE
+ if(!binary && mbwide() && (up == var || (flags & NN_FLAG) && size))
+ cur = var;
+#endif
+ *cur = 0;
+ if(c>=size || (flags&N_FLAG) || m==0)
+ {
+ if(m)
+ sfclrerr(iop);
+ break;
+ }
+ size -= c;
+ }
+ }
+ if(timeslot)
+ timerdel(timeslot);
+ if(binary && !((size=nv_size(np)) && nv_isarray(np) && c!=size))
+ {
+ if((c==size) && np->nvalue.cp && !nv_isarray(np))
+ memcpy((char*)np->nvalue.cp,var,c);
+ else
+ {
+ Namval_t *mp;
+ if(var==buf)
+ var = memdup(var,c+1);
+ nv_putval(np,var,NV_RAW);
+ nv_setsize(np,c);
+ if(!nv_isattr(np,NV_IMPORT|NV_EXPORT) && (mp=(Namval_t*)np->nvenv))
+ nv_setsize(mp,c);
+ }
+ }
+ else
+ {
+ nv_putval(np,var,0);
+ if(var!=buf)
+ free((void*)var);
+ }
+ goto done;
+ }
+ else if(cp = (unsigned char*)sfgetr(iop,delim,0))
+ c = sfvalue(iop);
+ else if(cp = (unsigned char*)sfgetr(iop,delim,-1))
+ {
+ c = sfvalue(iop)+1;
+ if(!sferror(iop) && sfgetc(iop) >=0)
+ errormsg(SH_DICT,ERROR_exit(1),e_overlimit,"line length");
+ }
+ if(timeslot)
+ timerdel(timeslot);
+ if((flags&S_FLAG) && !shp->gd->hist_ptr)
+ {
+ sh_histinit((void*)shp);
+ if(!shp->gd->hist_ptr)
+ flags &= ~S_FLAG;
+ }
+ if(cp)
+ {
+ cpmax = cp + c;
+#if SHOPT_CRNL
+ if(delim=='\n' && c>=2 && cpmax[-2]=='\r')
+ cpmax--;
+#endif /* SHOPT_CRNL */
+ if(*(cpmax-1) != delim)
+ *(cpmax-1) = delim;
+ if(flags&S_FLAG)
+ sfwrite(shp->gd->hist_ptr->histfp,(char*)cp,c);
+ c = shp->ifstable[*cp++];
+#if !SHOPT_MULTIBYTE
+ if(!name && (flags&R_FLAG)) /* special case single argument */
+ {
+ /* skip over leading blanks */
+ while(c==S_SPACE)
+ c = shp->ifstable[*cp++];
+ /* strip trailing delimiters */
+ if(cpmax[-1] == '\n')
+ cpmax--;
+ if(cpmax>cp)
+ {
+ while((c=shp->ifstable[*--cpmax])==S_DELIM || c==S_SPACE);
+ cpmax[1] = 0;
+ }
+ else
+ *cpmax =0;
+ if(nv_isattr(np, NV_RDONLY))
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
+ jmpval = 1;
+ }
+ else
+ nv_putval(np,(char*)cp-1,0);
+ goto done;
+ }
+#endif /* !SHOPT_MULTIBYTE */
+ }
+ else
+ c = S_NL;
+ shp->nextprompt = 2;
+ rel= staktell();
+ /* val==0 at the start of a field */
+ val = 0;
+ del = 0;
+ while(1)
+ {
+ switch(c)
+ {
+#if SHOPT_MULTIBYTE
+ case S_MBYTE:
+ if(val==0)
+ val = (char*)(cp-1);
+ if(sh_strchr(ifs,(char*)cp-1)>=0)
+ {
+ c = mbsize((char*)cp-1);
+ if(name)
+ cp[-1] = 0;
+ if(c>1)
+ cp += (c-1);
+ c = S_DELIM;
+ }
+ else
+ c = 0;
+ continue;
+#endif /*SHOPT_MULTIBYTE */
+ case S_QUOTE:
+ c = shp->ifstable[*cp++];
+ inquote = !inquote;
+ goto skip;
+ case S_ESC:
+ /* process escape character */
+ if((c = shp->ifstable[*cp++]) == S_NL)
+ was_escape = 1;
+ else
+ c = 0;
+ skip:
+ if(val)
+ {
+ stakputs(val);
+ use_stak = 1;
+ *val = 0;
+ }
+ continue;
+
+ case S_ERR:
+ cp++;
+ case S_EOF:
+ /* check for end of buffer */
+ if(val && *val)
+ {
+ stakputs(val);
+ use_stak = 1;
+ }
+ val = 0;
+ if(cp>=cpmax)
+ {
+ c = S_NL;
+ break;
+ }
+ /* eliminate null bytes */
+ c = shp->ifstable[*cp++];
+ if(!name && val && (c==S_SPACE||c==S_DELIM||c==S_MBYTE))
+ c = 0;
+ continue;
+ case S_NL:
+ if(was_escape)
+ {
+ was_escape = 0;
+ if(cp = (unsigned char*)sfgetr(iop,delim,0))
+ c = sfvalue(iop);
+ else if(cp=(unsigned char*)sfgetr(iop,delim,-1))
+ c = sfvalue(iop)+1;
+ if(cp)
+ {
+ if(flags&S_FLAG)
+ sfwrite(shp->gd->hist_ptr->histfp,(char*)cp,c);
+ cpmax = cp + c;
+ c = shp->ifstable[*cp++];
+ val=0;
+ if(!name && (c==S_SPACE || c==S_DELIM || c==S_MBYTE))
+ c = 0;
+ continue;
+ }
+ }
+ c = S_NL;
+ break;
+
+ case S_SPACE:
+ /* skip over blanks */
+ while((c=shp->ifstable[*cp++])==S_SPACE);
+ if(!val)
+ continue;
+#if SHOPT_MULTIBYTE
+ if(c==S_MBYTE)
+ {
+ if(sh_strchr(ifs,(char*)cp-1)>=0)
+ {
+ if((c = mbsize((char*)cp-1))>1)
+ cp += (c-1);
+ c = S_DELIM;
+ }
+ else
+ c = 0;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ if(c!=S_DELIM)
+ break;
+ /* FALL THRU */
+
+ case S_DELIM:
+ if(!del)
+ del = cp - 1;
+ if(name)
+ {
+ /* skip over trailing blanks */
+ while((c=shp->ifstable[*cp++])==S_SPACE);
+ break;
+ }
+ /* FALL THRU */
+
+ case 0:
+ if(val==0 || was_escape)
+ {
+ val = (char*)(cp-1);
+ was_escape = 0;
+ }
+ /* skip over word characters */
+ wrd = -1;
+ while(1)
+ {
+ while((c=shp->ifstable[*cp++])==0)
+ if(!wrd)
+ wrd = 1;
+ if(inquote)
+ {
+ if(c==S_QUOTE)
+ {
+ if(shp->ifstable[*cp]==S_QUOTE)
+ {
+ if(val)
+ {
+ stakwrite(val,cp-(unsigned char*)val);
+ use_stak = 1;
+ }
+ val = (char*)++cp;
+ }
+ else
+ break;
+ }
+ if(c && c!=S_EOF)
+ {
+ if(c==S_NL)
+ {
+ if(val)
+ {
+ stakwrite(val,cp-(unsigned char*)val);
+ use_stak=1;
+ }
+ if(cp = (unsigned char*)sfgetr(iop,delim,0))
+ c = sfvalue(iop);
+ else if(cp = (unsigned char*)sfgetr(iop,delim,-1))
+ c = sfvalue(iop)+1;
+ val = (char*)cp;
+ }
+ continue;
+ }
+ }
+ if(!del&&c==S_DELIM)
+ del = cp - 1;
+ if(name || c==S_NL || c==S_ESC || c==S_EOF || c==S_MBYTE)
+ break;
+ if(wrd<0)
+ wrd = 0;
+ }
+ if(wrd>0)
+ del = (unsigned char*)"";
+ if(c!=S_MBYTE)
+ cp[-1] = 0;
+ continue;
+ }
+ /* assign value and advance to next variable */
+ if(!val)
+ val = "";
+ if(use_stak)
+ {
+ stakputs(val);
+ stakputc(0);
+ val = stakptr(rel);
+ }
+ if(!name && *val)
+ {
+ /* strip off trailing space delimiters */
+ register unsigned char *vp = (unsigned char*)val + strlen(val);
+ while(shp->ifstable[*--vp]==S_SPACE);
+ if(vp==del)
+ {
+ if(vp==(unsigned char*)val)
+ vp--;
+ else
+ while(shp->ifstable[*--vp]==S_SPACE);
+ }
+ vp[1] = 0;
+ }
+ if(nv_isattr(np, NV_RDONLY))
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
+ jmpval = 1;
+ }
+ else
+ nv_putval(np,val,0);
+ val = 0;
+ del = 0;
+ if(use_stak)
+ {
+ stakseek(rel);
+ use_stak = 0;
+ }
+ if(array_index)
+ {
+ nv_putsub(np, NIL(char*), array_index++);
+ if(c!=S_NL)
+ continue;
+ name = *++names;
+ }
+ while(1)
+ {
+ if(sh_isoption(SH_ALLEXPORT)&&!strchr(nv_name(np),'.') && !nv_isattr(np,NV_EXPORT))
+ {
+ nv_onattr(np,NV_EXPORT);
+ sh_envput(shp->env,np);
+ }
+ if(name)
+ {
+ nv_close(np);
+ np = nv_open(name,shp->var_tree,NV_NOASSIGN|NV_VARNAME);
+ name = *++names;
+ }
+ else
+ np = 0;
+ if(c!=S_NL)
+ break;
+ if(!np)
+ goto done;
+ if(nv_isattr(np, NV_RDONLY))
+ {
+ errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
+ jmpval = 1;
+ }
+ else
+ nv_putval(np, "", 0);
+ }
+ }
+done:
+ if(timeout || (shp->fdstatus[fd]&(IOTTY|IONOSEEK)))
+ sh_popcontext(shp,&buff);
+ if(was_write)
+ sfset(iop,SF_WRITE,1);
+ if(!was_share)
+ sfset(iop,SF_SHARE,0);
+ nv_close(np);
+ if((shp->fdstatus[fd]&IOTTY) && !keytrap)
+ tty_cooked(fd);
+ if(flags&S_FLAG)
+ hist_flush(shp->gd->hist_ptr);
+ if(jmpval > 1)
+ siglongjmp(*shp->jmplist,jmpval);
+ return(jmpval);
+}
+
diff --git a/src/cmd/ksh93/bltins/regress.c b/src/cmd/ksh93/bltins/regress.c
new file mode 100644
index 0000000..25f3c25
--- /dev/null
+++ b/src/cmd/ksh93/bltins/regress.c
@@ -0,0 +1,343 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * regression test intercept control
+ * enable with SHOPT_REGRESS==1 in Makefile
+ * not for production use
+ * see --man for details
+ * all string constants inline here instead of in data/...
+ *
+ * David Korn
+ * at&t research
+ */
+
+#include "defs.h"
+
+#if SHOPT_REGRESS
+
+#include <error.h>
+#include <ls.h>
+#include "io.h"
+#include "builtins.h"
+#include <tmx.h>
+
+#define REGRESS_HEADER "ksh:REGRESS:"
+
+#define TRACE(r,i,f) sh_regress(REGRESS_##r, i, sfprints f, __LINE__, __FILE__)
+
+static const char usage[] =
+"[-1p0?\n@(#)$Id: __regress__ (AT&T Research) 2009-03-29 $\n]"
+USAGE_LICENSE
+"[+NAME?__regress__ - shell regression test intercept control]"
+"[+DESCRIPTION?\b__regress__\b controls the regression test intercepts "
+ "for shells compiled with SHOPT_REGRESS==1. Shells compiled this way are "
+ "for testing only. In addition to \b__regress__\b and the \b--regress\b "
+ "command line option, these shells may contain system library function "
+ "intercepts that behave different from the native counterparts.]"
+"[+?Each option controls a different test and possibly a different set "
+ "of intercepts. The options are interpreted \bdd\b(1) style -- '-' or "
+ "'--' prefix not required. This simplifies the specification of the "
+ "command line \b--regress\b=\avalue\a option, where \avalue\a is passed "
+ "as an option to the \b__regress__\b builtin. Typically regression test "
+ "intercepts are enabled with one or more command line \b--regress\b "
+ "options, with optional specific calls to \b__regress__\b in test "
+ "scripts to enable/disable intercepts as the test progresses.]"
+"[+?Each enabled intercept may result in trace lines of the form \b" REGRESS_HEADER
+ "\aoption\a:\aintercept\a:\ainfo\a on the standard error, where "
+ "\aoption\a is one of the options below, \aintercept\a is the name of "
+ "the specific intercept for \aoption\a, and \ainfo\a is \aoption\a "
+ "specific information. Unless noted otherwise, one regression test trace "
+ "line is produced each time an enabled intercept is called.]"
+"[101:egid?The intercept effective gid is set to \aoriginal-egid\a. The "
+ "effective gid of the underlying system process is not affected. The "
+ "trace line info is either \begid==rgid\b or \begid!=rgid\b. The "
+ "intercepts are:]#?[original-egid:=1]"
+ "{"
+ "[+getegid()?The intercept effecive gid is returned. The "
+ "\bsetgid\b() intercept may change this between the real gid and "
+ "\aoriginal-egid\a.]"
+ "[+setgid(gid)?Sets the intercept effective gid to \agid\a. "
+ "Fails if \agid\a is neither the real gid nor "
+ "\aoriginal-egid\a.]"
+ "}"
+"[102:euid?The intercept effective uid is set to \aoriginal-euid\a. The "
+ "effective uid of the underlying system process is not affected. The "
+ "trace line info is either \beuid==ruid\b or \beuid!=ruid\b. The "
+ "intercepts are:]#?[original-euid:=1]"
+ "{"
+ "[+geteuid()?The intercept effecive uid is returned. The "
+ "\bsetuid\b() intercept may change this between the real uid and "
+ "\aoriginal-euid\a.]"
+ "[+setuid(uid)?Sets the intercept effective uid to \auid\a. "
+ "Fails if \auid\a is neither the real uid nor "
+ "\aoriginal-euid\a.]"
+ "}"
+"[103:p_suid?Specifies a value for SHOPT_P_SUID. Effective uids greater "
+ "than the non-privileged-uid disable the priveleged mode. The intercepts "
+ "are:]#?[non-privileged-uid:=1]"
+ "{"
+ "[+SHOPT_P_SUID?The SHOPT_P_SUID macro value is overridden by "
+ "\bp_suid\b. A trace line is output for each SHOPT_P_SUID "
+ "access.]"
+ "}"
+"[104:source?The intercepts are:]"
+ "{"
+ "[+sh_source()?The trace line info is the path of the script "
+ "being sourced. Used to trace shell startup scripts.]"
+ "}"
+"[105:etc?Map file paths matching \b/etc/\b* to \aetc-dir\a/*. The "
+ "intercepts are:]:[etc-dir:=/etc]"
+ "{"
+ "[+sh_open()?Paths matching \b/etc/\b* are changed to "
+ "\aetc-dir\a/*.]"
+ "}"
+"[+SEE ALSO?\bksh\b(1), \bregress\b(1), \brt\b(1)]"
+;
+
+static const char* regress_options[] =
+{
+ "ERROR",
+ "egid",
+ "euid",
+ "p_suid",
+ "source",
+ "etc",
+};
+
+void sh_regress_init(Shell_t* shp)
+{
+ static Regress_t state;
+
+ shp->regress = &state;
+}
+
+/*
+ * regress info trace output
+ */
+
+void sh_regress(unsigned int index, const char* intercept, const char* info, unsigned int line, const char* file)
+{
+ char* name;
+ char buf[16];
+
+ if (index >= 1 && index <= elementsof(regress_options))
+ name = (char*)regress_options[index];
+ else
+ sfsprintf(name = buf, sizeof(buf), "%u", index);
+ sfprintf(sfstderr, REGRESS_HEADER "%s:%s:%s\n", name, intercept, fmtesc(info));
+}
+
+/*
+ * egid intercepts
+ */
+
+static gid_t intercept_sgid = 0;
+static gid_t intercept_egid = -1;
+static gid_t intercept_rgid = -1;
+
+gid_t getegid(void)
+{
+ if (intercept_rgid == -1)
+ intercept_rgid = getgid();
+ if (sh_isregress(REGRESS_egid))
+ {
+ TRACE(egid, "getegid", ("%s", intercept_egid == intercept_rgid ? "egid==rgid" : "egid!=rgid"));
+ return intercept_egid;
+ }
+ return intercept_rgid;
+}
+
+int setgid(gid_t gid)
+{
+ if (intercept_rgid == -1)
+ intercept_rgid = getgid();
+ if (sh_isregress(REGRESS_egid))
+ {
+ if (gid != intercept_rgid && gid != intercept_sgid)
+ {
+ TRACE(egid, "setgid", ("%s", "EPERM"));
+ errno = EPERM;
+ return -1;
+ }
+ intercept_egid = gid;
+ TRACE(egid, "setgid", ("%s", intercept_egid == intercept_rgid ? "egid==rgid" : "egid!=rgid"));
+ }
+ else if (gid != intercept_rgid)
+ {
+ errno = EPERM;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * euid intercepts
+ */
+
+static uid_t intercept_suid = 0;
+static uid_t intercept_euid = -1;
+static uid_t intercept_ruid = -1;
+
+uid_t geteuid(void)
+{
+ if (intercept_ruid == -1)
+ intercept_ruid = getuid();
+ if (sh_isregress(REGRESS_euid))
+ {
+ TRACE(euid, "geteuid", ("%s", intercept_euid == intercept_ruid ? "euid==ruid" : "euid!=ruid"));
+ return intercept_euid;
+ }
+ return intercept_ruid;
+}
+
+int setuid(uid_t uid)
+{
+ if (intercept_ruid == -1)
+ intercept_ruid = getuid();
+ if (sh_isregress(REGRESS_euid))
+ {
+ if (uid != intercept_ruid && uid != intercept_suid)
+ {
+ TRACE(euid, "setuid", ("%s", "EPERM"));
+ errno = EPERM;
+ return -1;
+ }
+ intercept_euid = uid;
+ TRACE(euid, "setuid", ("%s", intercept_euid == intercept_ruid ? "euid==ruid" : "euid!=ruid"));
+ }
+ else if (uid != intercept_ruid)
+ {
+ errno = EPERM;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * p_suid intercept
+ */
+
+static uid_t intercept_p_suid = 0x7fffffff;
+
+uid_t sh_regress_p_suid(unsigned int line, const char* file)
+{
+ REGRESS(p_suid, "SHOPT_P_SUID", ("%d", intercept_p_suid));
+ return intercept_p_suid;
+}
+
+/*
+ * p_suid intercept
+ */
+
+static char* intercept_etc = 0;
+
+char* sh_regress_etc(const char* path, unsigned int line, const char* file)
+{
+ REGRESS(etc, "sh_open", ("%s => %s%s", path, intercept_etc, path+4));
+ return intercept_etc;
+}
+
+/*
+ * __regress__ builtin
+ */
+
+int b___regress__(int argc, char** argv, Shbltin_t *context)
+{
+ register Shell_t* shp = context->shp;
+ int n;
+
+ for (;;)
+ {
+ switch (n = optget(argv, usage))
+ {
+ case '?':
+ errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ case ':':
+ errormsg(SH_DICT, 2, "%s", opt_info.arg);
+ break;
+ case 0:
+ break;
+ default:
+ if (n < -100)
+ {
+ n = -(n + 100);
+ if (opt_info.arg || opt_info.number)
+ sh_onregress(n);
+ else
+ sh_offregress(n);
+ switch (n)
+ {
+ case REGRESS_egid:
+ if (sh_isregress(n))
+ {
+ intercept_egid = intercept_sgid = (gid_t)opt_info.number;
+ TRACE(egid, argv[0], ("%d", intercept_egid));
+ }
+ else
+ TRACE(egid, argv[0], ("%s", "off"));
+ break;
+ case REGRESS_euid:
+ if (sh_isregress(n))
+ {
+ intercept_euid = intercept_suid = (uid_t)opt_info.number;
+ TRACE(euid, argv[0], ("%d", intercept_euid));
+ }
+ else
+ TRACE(euid, argv[0], ("%s", "off"));
+ break;
+ case REGRESS_p_suid:
+ if (sh_isregress(n))
+ {
+ intercept_p_suid = (uid_t)opt_info.number;
+ TRACE(p_suid, argv[0], ("%d", intercept_p_suid));
+ }
+ else
+ TRACE(p_suid, argv[0], ("%s", "off"));
+ break;
+ case REGRESS_source:
+ TRACE(source, argv[0], ("%s", sh_isregress(n) ? "on" : "off"));
+ break;
+ case REGRESS_etc:
+ if (sh_isregress(n))
+ {
+ intercept_etc = opt_info.arg;
+ TRACE(etc, argv[0], ("%s", intercept_etc));
+ }
+ else
+ TRACE(etc, argv[0], ("%s", "off"));
+ break;
+ }
+ }
+ continue;
+ }
+ break;
+ }
+ if (error_info.errors || *(argv + opt_info.index))
+ errormsg(SH_DICT, ERROR_usage(2), "%s", optusage(NiL));
+ return 0;
+}
+
+#else
+
+NoN(regress)
+
+#endif
diff --git a/src/cmd/ksh93/bltins/sleep.c b/src/cmd/ksh93/bltins/sleep.c
new file mode 100644
index 0000000..ca9d055
--- /dev/null
+++ b/src/cmd/ksh93/bltins/sleep.c
@@ -0,0 +1,235 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * sleep delay
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#define sleep ______sleep
+#include "defs.h"
+#undef sleep
+#include <error.h>
+#include <errno.h>
+#include <tmx.h>
+#include "builtins.h"
+#include "FEATURE/time"
+#include "FEATURE/poll"
+#ifdef _NEXT_SOURCE
+# define sleep _ast_sleep
+#endif /* _NEXT_SOURCE */
+#ifdef _lib_poll_notimer
+# undef _lib_poll
+#endif /* _lib_poll_notimer */
+
+int b_sleep(register int argc,char *argv[],Shbltin_t *context)
+{
+ register char *cp;
+ register double d=0;
+ register Shell_t *shp = context->shp;
+ int sflag=0;
+ time_t tloc = 0;
+ char *last;
+ if(!(shp->sigflag[SIGALRM]&(SH_SIGFAULT|SH_SIGOFF)))
+ sh_sigtrap(SIGALRM);
+ while((argc = optget(argv,sh_optsleep))) switch(argc)
+ {
+ case 's':
+ sflag=1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(cp = *argv)
+ {
+ d = strtod(cp, &last);
+ if(*last)
+ {
+ Time_t now,ns;
+ char* pp;
+ now = TMX_NOW;
+ if(*cp == 'P' || *cp == 'p')
+ ns = tmxdate(cp, &last, now);
+ else if(*last=='.' && shp->decomma && d==(unsigned long)d)
+ {
+ *(pp=last) = ',';
+ if(!strchr(cp,'.'))
+ d = strtod(cp,&last);
+ *pp = '.';
+ if(*last==0)
+ goto skip;
+ }
+ else if(*last!='.' && *last!=',')
+ {
+ if(pp = sfprints("exact %s", cp))
+ ns = tmxdate(pp, &last, now);
+ if(*last && (pp = sfprints("p%s", cp)))
+ ns = tmxdate(pp, &last, now);
+ }
+ if(*last)
+ errormsg(SH_DICT,ERROR_exit(1),e_number,*argv);
+ d = ns - now;
+ d /= TMX_RESOLUTION;
+ }
+skip:
+ if(argv[1])
+ errormsg(SH_DICT,ERROR_exit(1),e_oneoperand);
+ }
+ else if(!sflag)
+ errormsg(SH_DICT,ERROR_exit(1),e_oneoperand);
+ if(d > .10)
+ {
+ time(&tloc);
+ tloc += (time_t)(d+.5);
+ }
+ if(sflag && d==0)
+ pause();
+ else while(1)
+ {
+ time_t now;
+ errno = 0;
+ shp->lastsig=0;
+ sh_delay(d);
+ if(sflag || tloc==0 || errno!=EINTR || shp->lastsig)
+ break;
+ sh_sigcheck(shp);
+ if(tloc < (now=time(NIL(time_t*))))
+ break;
+ d = (double)(tloc-now);
+ if(shp->sigflag[SIGALRM]&SH_SIGTRAP)
+ sh_timetraps(shp);
+ }
+ return(0);
+}
+
+static void completed(void * handle)
+{
+ char *expired = (char*)handle;
+ *expired = 1;
+}
+
+unsigned int sleep(unsigned int sec)
+{
+ Shell_t *shp = sh_getinterp();
+ pid_t newpid, curpid=getpid();
+ void *tp;
+ char expired = 0;
+ shp->lastsig = 0;
+ tp = (void*)sh_timeradd(1000*sec, 0, completed, (void*)&expired);
+ do
+ {
+ if(!shp->gd->waitevent || (*shp->gd->waitevent)(-1,-1L,0)==0)
+ pause();
+ if(shp->sigflag[SIGALRM]&SH_SIGTRAP)
+ sh_timetraps(shp);
+ if((newpid=getpid()) != curpid)
+ {
+ curpid = newpid;
+ shp->lastsig = 0;
+ shp->trapnote &= ~SH_SIGSET;
+ if(expired)
+ expired = 0;
+ else
+ timerdel(tp);
+ tp = (void*)sh_timeradd(1000*sec, 0, completed, (void*)&expired);
+ }
+ }
+ while(!expired && shp->lastsig==0);
+ if(!expired)
+ timerdel(tp);
+ sh_sigcheck(shp);
+ return(0);
+}
+
+/*
+ * delay execution for time <t>
+ */
+
+void sh_delay(double t)
+{
+ register int n = (int)t;
+ Shell_t *shp = sh_getinterp();
+#ifdef _lib_poll
+ struct pollfd fd;
+ if(t<=0)
+ return;
+ else if(n > 30)
+ {
+ sleep(n);
+ t -= n;
+ }
+ if(n=(int)(1000*t))
+ {
+ if(!shp->gd->waitevent || (*shp->gd->waitevent)(-1,(long)n,0)==0)
+ poll(&fd,0,n);
+ }
+#else
+# if defined(_lib_select) && defined(_mem_tv_usec_timeval)
+ struct timeval timeloc;
+ if(t<=0)
+ return;
+ if(n=(int)(1000*t) && shp->gd->waitevent && (*shp->gd->waitevent)(-1,(long)n,0))
+ return;
+ n = (int)t;
+ timeloc.tv_sec = n;
+ timeloc.tv_usec = 1000000*(t-(double)n);
+ select(0,(fd_set*)0,(fd_set*)0,(fd_set*)0,&timeloc);
+# else
+# ifdef _lib_select
+ /* for 9th edition machines */
+ if(t<=0)
+ return;
+ if(n > 30)
+ {
+ sleep(n);
+ t -= n;
+ }
+ if(n=(int)(1000*t))
+ {
+ if(!shp->gd->waitevent || (*shp->gd->waitevent)(-1,(long)n,0)==0)
+ select(0,(fd_set*)0,(fd_set*)0,n);
+ }
+# else
+ struct tms tt;
+ if(t<=0)
+ return;
+ sleep(n);
+ t -= n;
+ if(t)
+ {
+ clock_t begin = times(&tt);
+ if(begin==0)
+ return;
+ t *= shp->gd->lim.clk_tck;
+ n += (t+.5);
+ while((times(&tt)-begin) < n);
+ }
+# endif
+# endif
+#endif /* _lib_poll */
+}
diff --git a/src/cmd/ksh93/bltins/test.c b/src/cmd/ksh93/bltins/test.c
new file mode 100644
index 0000000..52cb7cd
--- /dev/null
+++ b/src/cmd/ksh93/bltins/test.c
@@ -0,0 +1,667 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * test expression
+ * [ expression ]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+
+#include "defs.h"
+#include <error.h>
+#include <ls.h>
+#include "io.h"
+#include "terminal.h"
+#include "test.h"
+#include "builtins.h"
+#include "FEATURE/externs"
+#include "FEATURE/poll"
+#include <tmx.h>
+
+#if !_lib_setregid
+# undef _lib_setreuid
+#endif /* _lib_setregid */
+
+#ifdef S_ISSOCK
+# if _pipe_socketpair
+# if _socketpair_shutdown_mode
+# define isapipe(f,p) (test_stat(f,p)>=0&&S_ISFIFO((p)->st_mode)||S_ISSOCK((p)->st_mode)&&(p)->st_ino&&((p)->st_mode&(S_IRUSR|S_IWUSR))!=(S_IRUSR|S_IWUSR))
+# else
+# define isapipe(f,p) (test_stat(f,p)>=0&&S_ISFIFO((p)->st_mode)||S_ISSOCK((p)->st_mode)&&(p)->st_ino)
+# endif
+# else
+# define isapipe(f,p) (test_stat(f,p)>=0&&S_ISFIFO((p)->st_mode)||S_ISSOCK((p)->st_mode)&&(p)->st_ino)
+# endif
+# define isasock(f,p) (test_stat(f,p)>=0&&S_ISSOCK((p)->st_mode))
+#else
+# define isapipe(f,p) (test_stat(f,p)>=0&&S_ISFIFO((p)->st_mode))
+# define isasock(f,p) (0)
+#endif
+
+#define permission(a,f) (sh_access(a,f)==0)
+static time_t test_time(const char*, const char*);
+static int test_stat(const char*, struct stat*);
+static int test_mode(const char*);
+
+/* single char string compare */
+#define c_eq(a,c) (*a==c && *(a+1)==0)
+/* two character string compare */
+#define c2_eq(a,c1,c2) (*a==c1 && *(a+1)==c2 && *(a+2)==0)
+
+struct test
+{
+ Shell_t *sh;
+ int ap;
+ int ac;
+ char **av;
+};
+
+static char *nxtarg(struct test*,int);
+static int expr(struct test*,int);
+static int e3(struct test*);
+
+static int test_strmatch(Shell_t *shp,const char *str, const char *pat)
+{
+ int match[2*(MATCH_MAX+1)],n;
+ register int c, m=0;
+ register const char *cp=pat;
+ while(c = *cp++)
+ {
+ if(c=='(')
+ m++;
+ if(c=='\\' && *cp)
+ cp++;
+ }
+ if(m)
+ m++;
+ else
+ match[0] = 0;
+ if(m > elementsof(match)/2)
+ m = elementsof(match)/2;
+ n = strgrpmatch(str, pat, match, m, STR_GROUP|STR_MAXIMAL|STR_LEFT|STR_RIGHT);
+ if(m==0 && n==1)
+ match[1] = strlen(str);
+ if(n)
+ sh_setmatch(shp, str, -1, n, match, 0);
+ return(n);
+}
+
+int b_test(int argc, char *argv[],Shbltin_t *context)
+{
+ struct test tdata;
+ register char *cp = argv[0];
+ register int not;
+ tdata.sh = context->shp;
+ tdata.av = argv;
+ tdata.ap = 1;
+ if(c_eq(cp,'['))
+ {
+ cp = argv[--argc];
+ if(!c_eq(cp, ']'))
+ errormsg(SH_DICT,ERROR_exit(2),e_missing,"']'");
+ }
+ if(argc <= 1)
+ return(1);
+ cp = argv[1];
+ if(c_eq(cp,'(') && argc<=6 && c_eq(argv[argc-1],')'))
+ {
+ /* special case ( binop ) to conform with standard */
+ if(!(argc==4 && (not=sh_lookup(cp=argv[2],shtab_testops))))
+ {
+ cp = (++argv)[1];
+ argc -= 2;
+ }
+ }
+ not = c_eq(cp,'!');
+ /* posix portion for test */
+ switch(argc)
+ {
+ case 5:
+ if(!not)
+ break;
+ argv++;
+ /* fall through */
+ case 4:
+ {
+ register int op = sh_lookup(cp=argv[2],shtab_testops);
+ if(op&TEST_BINOP)
+ break;
+ if(!op)
+ {
+ if(argc==5)
+ break;
+ if(not && cp[0]=='-' && cp[2]==0)
+ return(test_unop(tdata.sh,cp[1],argv[3])!=0);
+ else if(argv[1][0]=='-' && argv[1][2]==0)
+ return(!test_unop(tdata.sh,argv[1][1],cp));
+ errormsg(SH_DICT,ERROR_exit(2),e_badop,cp);
+ }
+ return(test_binop(tdata.sh,op,argv[1],argv[3])^(argc!=5));
+ }
+ case 3:
+ if(not)
+ return(*argv[2]!=0);
+ if(cp[0] != '-' || cp[2] || cp[1]=='?')
+ {
+ if(cp[0]=='-' && (cp[1]=='-' || cp[1]=='?') &&
+ strcmp(argv[2],"--")==0)
+ {
+ char *av[3];
+ av[0] = argv[0];
+ av[1] = argv[1];
+ av[2] = 0;
+ optget(av,sh_opttest);
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ return(2);
+ }
+ break;
+ }
+ return(!test_unop(tdata.sh,cp[1],argv[2]));
+ case 2:
+ return(*cp==0);
+ }
+ tdata.ac = argc;
+ return(!expr(&tdata,0));
+}
+
+/*
+ * evaluate a test expression.
+ * flag is 0 on outer level
+ * flag is 1 when in parenthesis
+ * flag is 2 when evaluating -a
+ */
+static int expr(struct test *tp,register int flag)
+{
+ register int r;
+ register char *p;
+ r = e3(tp);
+ while(tp->ap < tp->ac)
+ {
+ p = nxtarg(tp,0);
+ /* check for -o and -a */
+ if(flag && c_eq(p,')'))
+ {
+ tp->ap--;
+ break;
+ }
+ if(*p=='-' && *(p+2)==0)
+ {
+ if(*++p == 'o')
+ {
+ if(flag==2)
+ {
+ tp->ap--;
+ break;
+ }
+ r |= expr(tp,3);
+ continue;
+ }
+ else if(*p == 'a')
+ {
+ r &= expr(tp,2);
+ continue;
+ }
+ }
+ if(flag==0)
+ break;
+ errormsg(SH_DICT,ERROR_exit(2),e_badsyntax);
+ }
+ return(r);
+}
+
+static char *nxtarg(struct test *tp,int mt)
+{
+ if(tp->ap >= tp->ac)
+ {
+ if(mt)
+ {
+ tp->ap++;
+ return(0);
+ }
+ errormsg(SH_DICT,ERROR_exit(2),e_argument);
+ }
+ return(tp->av[tp->ap++]);
+}
+
+
+static int e3(struct test *tp)
+{
+ register char *arg, *cp;
+ register int op;
+ char *binop;
+ arg=nxtarg(tp,0);
+ if(arg && c_eq(arg, '!'))
+ return(!e3(tp));
+ if(c_eq(arg, '('))
+ {
+ op = expr(tp,1);
+ cp = nxtarg(tp,0);
+ if(!cp || !c_eq(cp, ')'))
+ errormsg(SH_DICT,ERROR_exit(2),e_missing,"')'");
+ return(op);
+ }
+ cp = nxtarg(tp,1);
+ if(cp!=0 && (c_eq(cp,'=') || c2_eq(cp,'!','=')))
+ goto skip;
+ if(c2_eq(arg,'-','t'))
+ {
+ if(cp)
+ {
+ op = strtol(cp,&binop, 10);
+ return(*binop?0:tty_check(op));
+ }
+ else
+ {
+ /* test -t with no arguments */
+ tp->ap--;
+ return(tty_check(1));
+ }
+ }
+ if(*arg=='-' && arg[2]==0)
+ {
+ op = arg[1];
+ if(!cp)
+ {
+ /* for backward compatibility with new flags */
+ if(op==0 || !strchr(test_opchars+10,op))
+ return(1);
+ errormsg(SH_DICT,ERROR_exit(2),e_argument);
+ }
+ if(strchr(test_opchars,op))
+ return(test_unop(tp->sh,op,cp));
+ }
+ if(!cp)
+ {
+ tp->ap--;
+ return(*arg!=0);
+ }
+skip:
+ op = sh_lookup(binop=cp,shtab_testops);
+ if(!(op&TEST_BINOP))
+ cp = nxtarg(tp,0);
+ if(!op)
+ errormsg(SH_DICT,ERROR_exit(2),e_badop,binop);
+ if(op==TEST_AND || op==TEST_OR)
+ tp->ap--;
+ return(test_binop(tp->sh,op,arg,cp));
+}
+
+int test_unop(Shell_t *shp,register int op,register const char *arg)
+{
+ struct stat statb;
+ int f;
+ switch(op)
+ {
+ case 'r':
+ return(permission(arg, R_OK));
+ case 'w':
+ return(permission(arg, W_OK));
+ case 'x':
+ return(permission(arg, X_OK));
+ case 'V':
+#if SHOPT_FS_3D
+ {
+ register int offset = staktell();
+ if(stat(arg,&statb)<0 || !S_ISREG(statb.st_mode))
+ return(0);
+ /* add trailing / */
+ stakputs(arg);
+ stakputc('/');
+ stakputc(0);
+ arg = (const char*)stakptr(offset);
+ stakseek(offset);
+ /* FALL THRU */
+ }
+#else
+ return(0);
+#endif /* SHOPT_FS_3D */
+ case 'd':
+ return(test_stat(arg,&statb)>=0 && S_ISDIR(statb.st_mode));
+ case 'c':
+ return(test_stat(arg,&statb)>=0 && S_ISCHR(statb.st_mode));
+ case 'b':
+ return(test_stat(arg,&statb)>=0 && S_ISBLK(statb.st_mode));
+ case 'f':
+ return(test_stat(arg,&statb)>=0 && S_ISREG(statb.st_mode));
+ case 'u':
+ return(test_mode(arg)&S_ISUID);
+ case 'g':
+ return(test_mode(arg)&S_ISGID);
+ case 'k':
+#ifdef S_ISVTX
+ return(test_mode(arg)&S_ISVTX);
+#else
+ return(0);
+#endif /* S_ISVTX */
+#if SHOPT_TEST_L
+ case 'l':
+#endif
+ case 'L':
+ case 'h': /* undocumented, and hopefully will disappear */
+ if(*arg==0 || arg[strlen(arg)-1]=='/' || lstat(arg,&statb)<0)
+ return(0);
+ return(S_ISLNK(statb.st_mode));
+
+ case 'C':
+#ifdef S_ISCTG
+ return(test_stat(arg,&statb)>=0 && S_ISCTG(statb.st_mode));
+#else
+ return(0);
+#endif /* S_ISCTG */
+ case 'H':
+#ifdef S_ISCDF
+ {
+ register int offset = staktell();
+ if(test_stat(arg,&statb)>=0 && S_ISCDF(statb.st_mode))
+ return(1);
+ stakputs(arg);
+ stakputc('+');
+ stakputc(0);
+ arg = (const char*)stakptr(offset);
+ stakseek(offset);
+ return(test_stat(arg,&statb)>=0 && S_ISCDF(statb.st_mode));
+ }
+#else
+ return(0);
+#endif /* S_ISCDF */
+
+ case 'S':
+ return(isasock(arg,&statb));
+ case 'N':
+ return(test_stat(arg,&statb)>=0 && tmxgetmtime(&statb) > tmxgetatime(&statb));
+ case 'p':
+ return(isapipe(arg,&statb));
+ case 'n':
+ return(*arg != 0);
+ case 'z':
+ return(*arg == 0);
+ case 's':
+ sfsync(sfstdout);
+ case 'O':
+ case 'G':
+ if(*arg==0 || test_stat(arg,&statb)<0)
+ return(0);
+ if(op=='s')
+ return(statb.st_size>0);
+ else if(op=='O')
+ return(statb.st_uid==shp->gd->userid);
+ return(statb.st_gid==shp->gd->groupid);
+ case 'a':
+ case 'e':
+ if(memcmp(arg,"/dev/",5)==0 && sh_open(arg,O_NONBLOCK))
+ return(1);
+ return(permission(arg, F_OK));
+ case 'o':
+ f=1;
+ if(*arg=='?')
+ return(sh_lookopt(arg+1,&f)>0);
+ op = sh_lookopt(arg,&f);
+ return(op && (f==(sh_isoption(op)!=0)));
+ case 't':
+ {
+ char *last;
+ op = strtol(arg,&last, 10);
+ return(*last?0:tty_check(op));
+ }
+ case 'v':
+ case 'R':
+ {
+ Namval_t *np;
+ Namarr_t *ap;
+ int isref;
+ if(!(np = nv_open(arg,shp->var_tree,NV_VARNAME|NV_NOFAIL|NV_NOADD|NV_NOREF)))
+ return(0);
+ isref = nv_isref(np);
+ if(op=='R')
+ return(isref);
+ if(isref)
+ {
+ if(np->nvalue.cp)
+ np = nv_refnode(np);
+ else
+ return(0);
+
+ }
+ if(ap = nv_arrayptr(np))
+ return(nv_arrayisset(np,ap));
+ return(!nv_isnull(np) || nv_isattr(np,NV_INTEGER));
+ }
+ default:
+ {
+ static char a[3] = "-?";
+ a[1]= op;
+ errormsg(SH_DICT,ERROR_exit(2),e_badop,a);
+ /* NOTREACHED */
+ return(0);
+ }
+ }
+}
+
+int test_binop(Shell_t *shp,register int op,const char *left,const char *right)
+{
+ register double lnum,rnum;
+ if(op&TEST_ARITH)
+ {
+ while(*left=='0')
+ left++;
+ while(*right=='0')
+ right++;
+ lnum = sh_arith(shp,left);
+ rnum = sh_arith(shp,right);
+ }
+ switch(op)
+ {
+ /* op must be one of the following values */
+ case TEST_AND:
+ case TEST_OR:
+ return(*left!=0);
+ case TEST_PEQ:
+ return(test_strmatch(shp, left, right));
+ case TEST_PNE:
+ return(!test_strmatch(shp, left, right));
+ case TEST_SGT:
+ return(strcoll(left, right)>0);
+ case TEST_SLT:
+ return(strcoll(left, right)<0);
+ case TEST_SEQ:
+ return(strcmp(left, right)==0);
+ case TEST_SNE:
+ return(strcmp(left, right)!=0);
+ case TEST_EF:
+ return(test_inode(left,right));
+ case TEST_NT:
+ return(test_time(left,right)>0);
+ case TEST_OT:
+ return(test_time(left,right)<0);
+ case TEST_EQ:
+ return(lnum==rnum);
+ case TEST_NE:
+ return(lnum!=rnum);
+ case TEST_GT:
+ return(lnum>rnum);
+ case TEST_LT:
+ return(lnum<rnum);
+ case TEST_GE:
+ return(lnum>=rnum);
+ case TEST_LE:
+ return(lnum<=rnum);
+ }
+ /* NOTREACHED */
+ return(0);
+}
+
+/*
+ * returns the modification time of f1 - modification time of f2
+ */
+
+static time_t test_time(const char *file1,const char *file2)
+{
+ Time_t t1, t2;
+ struct stat statb1,statb2;
+ int r=test_stat(file2,&statb2);
+ if(test_stat(file1,&statb1)<0)
+ return(r<0?0:-1);
+ if(r<0)
+ return(1);
+ t1 = tmxgetmtime(&statb1);
+ t2 = tmxgetmtime(&statb2);
+ if (t1 > t2)
+ return(1);
+ if (t1 < t2)
+ return(-1);
+ return(0);
+}
+
+/*
+ * return true if inode of two files are the same
+ */
+
+int test_inode(const char *file1,const char *file2)
+{
+ struct stat stat1,stat2;
+ if(test_stat(file1,&stat1)>=0 && test_stat(file2,&stat2)>=0)
+ if(stat1.st_dev == stat2.st_dev && stat1.st_ino == stat2.st_ino)
+ return(1);
+ return(0);
+}
+
+
+/*
+ * This version of access checks against effective uid/gid
+ * The static buffer statb is shared with test_mode.
+ */
+
+int sh_access(register const char *name, register int mode)
+{
+ Shell_t *shp = sh_getinterp();
+ struct stat statb;
+ if(*name==0)
+ return(-1);
+ if(sh_isdevfd(name))
+ return(sh_ioaccess((int)strtol(name+8, (char**)0, 10),mode));
+ /* can't use access function for execute permission with root */
+ if(mode==X_OK && shp->gd->euserid==0)
+ goto skip;
+ if(shp->gd->userid==shp->gd->euserid && shp->gd->groupid==shp->gd->egroupid)
+ return(access(name,mode));
+#ifdef _lib_setreuid
+ /* swap the real uid to effective, check access then restore */
+ /* first swap real and effective gid, if different */
+ if(shp->gd->groupid==shp->gd->euserid || setregid(shp->gd->egroupid,shp->gd->groupid)==0)
+ {
+ /* next swap real and effective uid, if needed */
+ if(shp->gd->userid==shp->gd->euserid || setreuid(shp->gd->euserid,shp->gd->userid)==0)
+ {
+ mode = access(name,mode);
+ /* restore ids */
+ if(shp->gd->userid!=shp->gd->euserid)
+ setreuid(shp->gd->userid,shp->gd->euserid);
+ if(shp->gd->groupid!=shp->gd->egroupid)
+ setregid(shp->gd->groupid,shp->gd->egroupid);
+ return(mode);
+ }
+ else if(shp->gd->groupid!=shp->gd->egroupid)
+ setregid(shp->gd->groupid,shp->gd->egroupid);
+ }
+#endif /* _lib_setreuid */
+skip:
+ if(test_stat(name, &statb) == 0)
+ {
+ if(mode == F_OK)
+ return(mode);
+ else if(shp->gd->euserid == 0)
+ {
+ if(!S_ISREG(statb.st_mode) || mode!=X_OK)
+ return(0);
+ /* root needs execute permission for someone */
+ mode = (S_IXUSR|S_IXGRP|S_IXOTH);
+ }
+ else if(shp->gd->euserid == statb.st_uid)
+ mode <<= 6;
+ else if(shp->gd->egroupid == statb.st_gid)
+ mode <<= 3;
+#ifdef _lib_getgroups
+ /* on some systems you can be in several groups */
+ else
+ {
+ static int maxgroups;
+ gid_t *groups;
+ register int n;
+ if(maxgroups==0)
+ {
+ /* first time */
+ if((maxgroups=getgroups(0,(gid_t*)0)) <= 0)
+ {
+ /* pre-POSIX system */
+ maxgroups=NGROUPS_MAX;
+ }
+ }
+ groups = (gid_t*)stakalloc((maxgroups+1)*sizeof(gid_t));
+ n = getgroups(maxgroups,groups);
+ while(--n >= 0)
+ {
+ if(groups[n] == statb.st_gid)
+ {
+ mode <<= 3;
+ break;
+ }
+ }
+ }
+# endif /* _lib_getgroups */
+ if(statb.st_mode & mode)
+ return(0);
+ }
+ return(-1);
+}
+
+/*
+ * Return the mode bits of file <file>
+ * If <file> is null, then the previous stat buffer is used.
+ * The mode bits are zero if the file doesn't exist.
+ */
+
+static int test_mode(register const char *file)
+{
+ struct stat statb;
+ statb.st_mode = 0;
+ if(file && (*file==0 || test_stat(file,&statb)<0))
+ return(0);
+ return(statb.st_mode);
+}
+
+/*
+ * do an fstat() for /dev/fd/n, otherwise stat()
+ */
+static int test_stat(const char *name,struct stat *buff)
+{
+ if(*name==0)
+ {
+ errno = ENOENT;
+ return(-1);
+ }
+ if(sh_isdevfd(name))
+ return(fstat((int)strtol(name+8, (char**)0, 10),buff));
+ else
+ return(stat(name,buff));
+}
diff --git a/src/cmd/ksh93/bltins/trap.c b/src/cmd/ksh93/bltins/trap.c
new file mode 100644
index 0000000..f5dbedc
--- /dev/null
+++ b/src/cmd/ksh93/bltins/trap.c
@@ -0,0 +1,420 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * trap [-p] action sig...
+ * kill [-l] [sig...]
+ * kill [-s sig] pid...
+ *
+ * David Korn
+ * AT&T Labs
+ * research!dgk
+ *
+ */
+
+#include "defs.h"
+#include "jobs.h"
+#include "builtins.h"
+
+#define L_FLAG 1
+#define S_FLAG 2
+
+static const char trapfmt[] = "trap -- %s %s\n";
+
+static int sig_number(Shell_t*,const char*);
+static void sig_list(Shell_t*,int);
+
+int b_trap(int argc,char *argv[],Shbltin_t *context)
+{
+ register char *arg = argv[1];
+ register int sig, clear = 0, dflag = 0, pflag = 0;
+ register Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ while (sig = optget(argv, sh_opttrap)) switch (sig)
+ {
+ case 'p':
+ pflag=1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
+ if(arg = *argv)
+ {
+ char *action = arg;
+ if(!dflag && !pflag)
+ {
+ /* first argument all digits or - means clear */
+ while(isdigit(*arg))
+ arg++;
+ clear = (arg!=action && *arg==0);
+ if(!clear)
+ {
+ ++argv;
+ if(*action=='-' && action[1]==0)
+ clear++;
+ /*
+ * NOTE: 2007-11-26: workaround for tests/signal.sh
+ * if function semantics can be worked out then it
+ * may merit a -d,--default option
+ */
+ else if(*action=='+' && action[1]==0 && shp->st.self == &shp->global)
+ {
+ clear++;
+ dflag++;
+ }
+ }
+ if(!argv[0])
+ errormsg(SH_DICT,ERROR_exit(1),e_condition);
+ }
+ while(arg = *argv++)
+ {
+ sig = sig_number(shp,arg);
+ if(sig<0)
+ {
+ errormsg(SH_DICT,2,e_trap,arg);
+ return(1);
+ }
+ /* internal traps */
+ if(sig&SH_TRAP)
+ {
+ sig &= ~SH_TRAP;
+ if(sig>SH_DEBUGTRAP)
+ {
+ errormsg(SH_DICT,2,e_trap,arg);
+ return(1);
+ }
+ if(pflag)
+ {
+ if(arg=shp->st.trap[sig])
+ sfputr(sfstdout,sh_fmtq(arg),'\n');
+ continue;
+ }
+ if(shp->st.trap[sig])
+ free(shp->st.trap[sig]);
+ shp->st.trap[sig] = 0;
+ if(!clear && *action)
+ shp->st.trap[sig] = strdup(action);
+ if(sig == SH_DEBUGTRAP)
+ {
+ if(shp->st.trap[sig])
+ shp->trapnote |= SH_SIGTRAP;
+ else
+ shp->trapnote = 0;
+ }
+ continue;
+ }
+ if(sig>shp->gd->sigmax)
+ {
+ errormsg(SH_DICT,2,e_trap,arg);
+ return(1);
+ }
+ else if(pflag)
+ {
+ char **trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom);
+ if(arg=trapcom[sig])
+ sfputr(sfstdout,arg,'\n');
+ }
+ else if(clear)
+ {
+ sh_sigclear(sig);
+ if(dflag)
+ signal(sig,SIG_DFL);
+ }
+ else
+ {
+ if(sig >= shp->st.trapmax)
+ shp->st.trapmax = sig+1;
+ arg = shp->st.trapcom[sig];
+ sh_sigtrap(sig);
+ shp->st.trapcom[sig] = (shp->sigflag[sig]&SH_SIGOFF) ? Empty : strdup(action);
+ if(arg && arg != Empty)
+ free(arg);
+ }
+ }
+ }
+ else /* print out current traps */
+ sig_list(shp,-1);
+ return(0);
+}
+
+int b_kill(int argc,char *argv[],Shbltin_t *context)
+{
+ register char *signame;
+ register int sig=SIGTERM, flag=0, n;
+ register Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ while((n = optget(argv,sh_optkill))) switch(n)
+ {
+ case ':':
+ if((signame=argv[opt_info.index++]) && (sig=sig_number(shp,signame+1))>=0)
+ goto endopts;
+ opt_info.index--;
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case 'n':
+ sig = (int)opt_info.num;
+ goto endopts;
+ case 's':
+ flag |= S_FLAG;
+ signame = opt_info.arg;
+ goto endopts;
+ case 'l':
+ flag |= L_FLAG;
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+endopts:
+ argv += opt_info.index;
+ if(*argv && strcmp(*argv,"--")==0 && strcmp(*(argv-1),"--")!=0)
+ argv++;
+ if(error_info.errors || flag==(L_FLAG|S_FLAG) || (!(*argv) && !(flag&L_FLAG)))
+ errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
+ /* just in case we send a kill -9 $$ */
+ sfsync(sfstderr);
+ if(flag&L_FLAG)
+ {
+ if(!(*argv))
+ sig_list(shp,0);
+ else while(signame = *argv++)
+ {
+ if(isdigit(*signame))
+ sig_list(shp,((int)strtol(signame, (char**)0, 10)&0177)+1);
+ else
+ {
+ if((sig=sig_number(shp,signame))<0)
+ {
+ shp->exitval = 2;
+ errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame);
+ }
+ sfprintf(sfstdout,"%d\n",sig);
+ }
+ }
+ return(shp->exitval);
+ }
+ if(flag&S_FLAG)
+ {
+ if((sig=sig_number(shp,signame)) < 0 || sig > shp->gd->sigmax)
+ errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame);
+ }
+ if(job_walk(sfstdout,job_kill,sig,argv))
+ shp->exitval = 1;
+ return(shp->exitval);
+}
+
+/*
+ * Given the name or number of a signal return the signal number
+ */
+
+static int sig_number(Shell_t *shp,const char *string)
+{
+ const Shtable_t *tp;
+ register int n,o,sig=0;
+ char *last, *name;
+ if(isdigit(*string))
+ {
+ n = strtol(string,&last,10);
+ if(*last)
+ n = -1;
+ }
+ else
+ {
+ register int c;
+ o = staktell();
+ do
+ {
+ c = *string++;
+ if(islower(c))
+ c = toupper(c);
+ stakputc(c);
+ }
+ while(c);
+ stakseek(o);
+ if(memcmp(stakptr(o),"SIG",3)==0)
+ {
+ sig = 1;
+ o += 3;
+ if(isdigit(*stakptr(o)))
+ {
+ n = strtol(stakptr(o),&last,10);
+ if(!*last)
+ return(n);
+ }
+ }
+ tp = sh_locate(stakptr(o),(const Shtable_t*)shtab_signals,sizeof(*shtab_signals));
+ n = tp->sh_number;
+ if(sig==1 && (n>=(SH_TRAP-1) && n < (1<<SH_SIGBITS)))
+ {
+ /* sig prefix cannot match internal traps */
+ n = 0;
+ tp = (Shtable_t*)((char*)tp + sizeof(*shtab_signals));
+ if(strcmp(stakptr(o),tp->sh_name)==0)
+ n = tp->sh_number;
+ }
+ if((n>>SH_SIGBITS)&SH_SIGRUNTIME)
+ n = shp->gd->sigruntime[(n&((1<<SH_SIGBITS)-1))-1];
+ else
+ {
+ n &= (1<<SH_SIGBITS)-1;
+ if(n < SH_TRAP)
+ n--;
+ }
+ if(n<0 && shp->gd->sigruntime[1] && (name=stakptr(o)) && *name++=='R' && *name++=='T')
+ {
+ if(name[0]=='M' && name[1]=='I' && name[2]=='N' && name[3]=='+')
+ {
+ if((sig=(int)strtol(name+4,&name,10)) >= 0 && !*name)
+ n = shp->gd->sigruntime[SH_SIGRTMIN] + sig;
+ }
+ else if(name[0]=='M' && name[1]=='A' && name[2]=='X' && name[3]=='-')
+ {
+ if((sig=(int)strtol(name+4,&name,10)) >= 0 && !*name)
+ n = shp->gd->sigruntime[SH_SIGRTMAX] - sig;
+ }
+ else if((sig=(int)strtol(name,&name,10)) > 0 && !*name)
+ n = shp->gd->sigruntime[SH_SIGRTMIN] + sig - 1;
+ if(n<shp->gd->sigruntime[SH_SIGRTMIN] || n>shp->gd->sigruntime[SH_SIGRTMAX])
+ n = -1;
+ }
+ }
+ return(n);
+}
+
+/*
+ * synthesize signal name for sig in buf
+ * pfx!=0 prepends SIG to default signal number
+ */
+static char* sig_name(Shell_t *shp,int sig, char* buf, int pfx)
+{
+ register int i;
+
+ i = 0;
+ if(sig>shp->gd->sigruntime[SH_SIGRTMIN] && sig<shp->gd->sigruntime[SH_SIGRTMAX])
+ {
+ buf[i++] = 'R';
+ buf[i++] = 'T';
+ buf[i++] = 'M';
+ if(sig>shp->gd->sigruntime[SH_SIGRTMIN]+(shp->gd->sigruntime[SH_SIGRTMAX]-shp->gd->sigruntime[SH_SIGRTMIN])/2)
+ {
+ buf[i++] = 'A';
+ buf[i++] = 'X';
+ buf[i++] = '-';
+ sig = shp->gd->sigruntime[SH_SIGRTMAX]-sig;
+ }
+ else
+ {
+ buf[i++] = 'I';
+ buf[i++] = 'N';
+ buf[i++] = '+';
+ sig = sig-shp->gd->sigruntime[SH_SIGRTMIN];
+ }
+ }
+ else if(pfx)
+ {
+ buf[i++] = 'S';
+ buf[i++] = 'I';
+ buf[i++] = 'G';
+ }
+ i += sfsprintf(buf+i, 8, "%d", sig);
+ buf[i] = 0;
+ return buf;
+}
+
+/*
+ * if <flag> is positive, then print signal name corresponding to <flag>
+ * if <flag> is zero, then print all signal names
+ * if <flag> is negative, then print all traps
+ */
+static void sig_list(register Shell_t *shp,register int flag)
+{
+ register const struct shtable2 *tp;
+ register int sig;
+ register char *sname;
+ char name[10];
+ const char *names[SH_TRAP];
+ const char *traps[SH_DEBUGTRAP+1];
+ tp=shtab_signals;
+ if(flag<=0)
+ {
+ /* not all signals may be defined, so initialize */
+ for(sig=shp->gd->sigmax; sig>=0; sig--)
+ names[sig] = 0;
+ for(sig=SH_DEBUGTRAP; sig>=0; sig--)
+ traps[sig] = 0;
+ }
+ for(; *tp->sh_name; tp++)
+ {
+ sig = tp->sh_number&((1<<SH_SIGBITS)-1);
+ if (((tp->sh_number>>SH_SIGBITS) & SH_SIGRUNTIME) && (sig = shp->gd->sigruntime[sig-1]+1) == 1)
+ continue;
+ if(sig==flag)
+ {
+ sfprintf(sfstdout,"%s\n",tp->sh_name);
+ return;
+ }
+ else if(sig&SH_TRAP)
+ traps[sig&~SH_TRAP] = (char*)tp->sh_name;
+ else if(sig-- && sig < elementsof(names))
+ names[sig] = (char*)tp->sh_name;
+ }
+ if(flag > 0)
+ sfputr(sfstdout, sig_name(shp,flag-1,name,0), '\n');
+ else if(flag<0)
+ {
+ /* print the traps */
+ register char *trap,**trapcom;
+ sig = shp->st.trapmax;
+ /* use parent traps if otrapcom is set (for $(trap) */
+ trapcom = (shp->st.otrapcom?shp->st.otrapcom:shp->st.trapcom);
+ while(--sig >= 0)
+ {
+ if(!(trap=trapcom[sig]))
+ continue;
+ if(sig > shp->gd->sigmax || !(sname=(char*)names[sig]))
+ sname = sig_name(shp,sig,name,1);
+ sfprintf(sfstdout,trapfmt,sh_fmtq(trap),sname);
+ }
+ for(sig=SH_DEBUGTRAP; sig>=0; sig--)
+ {
+ if(!(trap=shp->st.trap[sig]))
+ continue;
+ sfprintf(sfstdout,trapfmt,sh_fmtq(trap),traps[sig]);
+ }
+ }
+ else
+ {
+ /* print all the signal names */
+ for(sig=1; sig <= shp->gd->sigmax; sig++)
+ {
+ if(!(sname=(char*)names[sig]))
+ sname = sig_name(shp,sig,name,1);
+ sfputr(sfstdout,sname,'\n');
+ }
+ }
+}
diff --git a/src/cmd/ksh93/bltins/typeset.c b/src/cmd/ksh93/bltins/typeset.c
new file mode 100644
index 0000000..f5618a1
--- /dev/null
+++ b/src/cmd/ksh93/bltins/typeset.c
@@ -0,0 +1,1471 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * export [-p] [arg...]
+ * readonly [-p] [arg...]
+ * typeset [options] [arg...]
+ * alias [-ptx] [arg...]
+ * unalias [arg...]
+ * builtin [-sd] [-f file] [name...]
+ * set [options] [name...]
+ * unset [-fnv] [name...]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <error.h>
+#include "path.h"
+#include "name.h"
+#include "history.h"
+#include "builtins.h"
+#include "variables.h"
+#include "FEATURE/dynamic"
+
+struct tdata
+{
+ Shell_t *sh;
+ Namval_t *tp;
+ const char *wctname;
+ Sfio_t *outfile;
+ char *prefix;
+ char *tname;
+ char *help;
+ short aflag;
+ short pflag;
+ int argnum;
+ int scanmask;
+ Dt_t *scanroot;
+ char **argnam;
+ int indent;
+ int noref;
+};
+
+
+static int print_namval(Sfio_t*, Namval_t*, int, struct tdata*);
+static void print_attribute(Namval_t*,void*);
+static void print_all(Sfio_t*, Dt_t*, struct tdata*);
+static void print_scan(Sfio_t*, int, Dt_t*, int, struct tdata*);
+static int unall(int, char**, Dt_t*, Shell_t*);
+static int setall(char**, int, Dt_t*, struct tdata*);
+static void pushname(Namval_t*,void*);
+static void(*nullscan)(Namval_t*,void*);
+
+static Namval_t *load_class(const char *name)
+{
+ errormsg(SH_DICT,ERROR_exit(1),"%s: type not loadable",name);
+ return(0);
+}
+
+/*
+ * Note export and readonly are the same
+ */
+#if 0
+ /* for the dictionary generator */
+ int b_export(int argc,char *argv[],Shbltin_t *context){}
+#endif
+int b_readonly(int argc,char *argv[],Shbltin_t *context)
+{
+ register int flag;
+ char *command = argv[0];
+ struct tdata tdata;
+ NOT_USED(argc);
+ memset((void*)&tdata,0,sizeof(tdata));
+ tdata.sh = context->shp;
+ tdata.aflag = '-';
+ while((flag = optget(argv,*command=='e'?sh_optexport:sh_optreadonly))) switch(flag)
+ {
+ case 'p':
+ tdata.prefix = command;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),optusage(NIL(char*)));
+ argv += (opt_info.index-1);
+ if(*command=='r')
+ flag = (NV_ASSIGN|NV_RDONLY|NV_VARNAME);
+#ifdef _ENV_H
+ else if(!argv[1])
+ {
+ char *cp,**env=env_get(tdata.sh->env);
+ while(cp = *env++)
+ {
+ if(tdata.prefix)
+ sfputr(sfstdout,tdata.prefix,' ');
+ sfprintf(sfstdout,"%s\n",sh_fmtq(cp));
+ }
+ return(0);
+ }
+#endif
+ else
+ {
+ flag = (NV_ASSIGN|NV_EXPORT|NV_IDENT);
+ if(!tdata.sh->prefix)
+ tdata.sh->prefix = "";
+ }
+ return(setall(argv,flag,tdata.sh->var_tree, &tdata));
+}
+
+
+int b_alias(int argc,register char *argv[],Shbltin_t *context)
+{
+ register unsigned flag = NV_NOARRAY|NV_NOSCOPE|NV_ASSIGN;
+ register Dt_t *troot;
+ register int n;
+ struct tdata tdata;
+ NOT_USED(argc);
+ memset((void*)&tdata,0,sizeof(tdata));
+ tdata.sh = context->shp;
+ troot = tdata.sh->alias_tree;
+ if(*argv[0]=='h')
+ flag = NV_TAGGED;
+ if(argv[1])
+ {
+ opt_info.offset = 0;
+ opt_info.index = 1;
+ *opt_info.option = 0;
+ tdata.argnum = 0;
+ tdata.aflag = *argv[1];
+ while((n = optget(argv,sh_optalias))) switch(n)
+ {
+ case 'p':
+ tdata.prefix = argv[0];
+ break;
+ case 't':
+ flag |= NV_TAGGED;
+ break;
+ case 'x':
+ flag |= NV_EXPORT;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
+ argv += (opt_info.index-1);
+ if(flag&NV_TAGGED)
+ {
+ /* hacks to handle hash -r | -- */
+ if(argv[1] && argv[1][0]=='-')
+ {
+ if(argv[1][1]=='r' && argv[1][2]==0)
+ {
+ Namval_t *np = nv_search((char*)PATHNOD,tdata.sh->var_tree,HASH_BUCKET);
+ nv_putval(np,nv_getval(np),NV_RDONLY);
+ argv++;
+ if(!argv[1])
+ return(0);
+ }
+ if(argv[1][0]=='-')
+ {
+ if(argv[1][1]=='-' && argv[1][2]==0)
+ argv++;
+ else
+ errormsg(SH_DICT, ERROR_exit(1), e_option, argv[1]);
+ }
+ }
+ troot = tdata.sh->track_tree;
+ }
+ }
+ return(setall(argv,flag,troot,&tdata));
+}
+
+
+#if 0
+ /* for the dictionary generator */
+ int b_local(int argc,char *argv[],Shbltin_t *context){}
+#endif
+int b_typeset(int argc,register char *argv[],Shbltin_t *context)
+{
+ register int n, flag = NV_VARNAME|NV_ASSIGN;
+ struct tdata tdata;
+ const char *optstring = sh_opttypeset;
+ Namdecl_t *ntp = (Namdecl_t*)context->ptr;
+ Dt_t *troot;
+ int isfloat=0, shortint=0, sflag=0;
+ NOT_USED(argc);
+ memset((void*)&tdata,0,sizeof(tdata));
+ tdata.sh = context->shp;
+ if(ntp)
+ {
+ tdata.tp = ntp->tp;
+ opt_info.disc = (Optdisc_t*)ntp->optinfof;
+ optstring = ntp->optstring;
+ }
+ troot = tdata.sh->var_tree;
+ while((n = optget(argv,optstring)))
+ {
+ if(tdata.aflag==0)
+ tdata.aflag = *opt_info.option;
+ switch(n)
+ {
+ case 'a':
+ flag |= NV_IARRAY;
+ if(opt_info.arg && *opt_info.arg!='[')
+ {
+ opt_info.index--;
+ goto endargs;
+ }
+ tdata.tname = opt_info.arg;
+ break;
+ case 'A':
+ flag |= NV_ARRAY;
+ break;
+ case 'C':
+ flag |= NV_COMVAR;
+ break;
+ case 'E':
+ /* The following is for ksh88 compatibility */
+ if(opt_info.offset && !strchr(argv[opt_info.index],'E'))
+ {
+ tdata.argnum = (int)opt_info.num;
+ break;
+ }
+ case 'F':
+ case 'X':
+ if(!opt_info.arg || (tdata.argnum = opt_info.num) <0)
+ tdata.argnum = (n=='X'?2*sizeof(Sfdouble_t):10);
+ isfloat = 1;
+ if(n=='E')
+ {
+ flag &= ~NV_HEXFLOAT;
+ flag |= NV_EXPNOTE;
+ }
+ else if(n=='X')
+ {
+ flag &= ~NV_EXPNOTE;
+ flag |= NV_HEXFLOAT;
+ }
+ break;
+ case 'b':
+ flag |= NV_BINARY;
+ break;
+ case 'm':
+ flag |= NV_MOVE;
+ break;
+ case 'n':
+ flag &= ~NV_VARNAME;
+ flag |= (NV_REF|NV_IDENT);
+ break;
+ case 'H':
+ flag |= NV_HOST;
+ break;
+ case 'T':
+ flag |= NV_TYPE;
+ tdata.prefix = opt_info.arg;
+ break;
+ case 'L': case 'Z': case 'R':
+ if(tdata.argnum==0)
+ tdata.argnum = (int)opt_info.num;
+ if(tdata.argnum < 0)
+ errormsg(SH_DICT,ERROR_exit(1), e_badfield, tdata.argnum);
+ if(n=='Z')
+ flag |= NV_ZFILL;
+ else
+ {
+ flag &= ~(NV_LJUST|NV_RJUST);
+ flag |= (n=='L'?NV_LJUST:NV_RJUST);
+ }
+ break;
+ case 'M':
+ if((tdata.wctname = opt_info.arg) && !nv_mapchar((Namval_t*)0,tdata.wctname))
+ errormsg(SH_DICT, ERROR_exit(1),e_unknownmap, tdata.wctname);
+ if(tdata.wctname && strcmp(tdata.wctname,e_tolower)==0)
+ flag |= NV_UTOL;
+ else
+ flag |= NV_LTOU;
+ if(!tdata.wctname)
+ flag |= NV_UTOL;
+ break;
+ case 'f':
+ flag &= ~(NV_VARNAME|NV_ASSIGN);
+ troot = tdata.sh->fun_tree;
+ break;
+ case 'i':
+ if(!opt_info.arg || (tdata.argnum = opt_info.num) <0)
+ tdata.argnum = 10;
+ flag |= NV_INTEGER;
+ break;
+ case 'l':
+ tdata.wctname = e_tolower;
+ flag |= NV_UTOL;
+ break;
+ case 'p':
+ tdata.prefix = argv[0];
+ tdata.pflag = 1;
+ flag &= ~NV_ASSIGN;
+ break;
+ case 'r':
+ flag |= NV_RDONLY;
+ break;
+#ifdef SHOPT_TYPEDEF
+ case 'S':
+ sflag=1;
+ break;
+ case 'h':
+ tdata.help = opt_info.arg;
+ break;
+#endif /*SHOPT_TYPEDEF*/
+ case 's':
+ shortint=1;
+ break;
+ case 't':
+ flag |= NV_TAGGED;
+ break;
+ case 'u':
+ tdata.wctname = e_toupper;
+ flag |= NV_LTOU;
+ break;
+ case 'x':
+ flag &= ~NV_VARNAME;
+ flag |= (NV_EXPORT|NV_IDENT);
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ opt_info.disc = 0;
+ return(2);
+ }
+ }
+endargs:
+ argv += opt_info.index;
+ opt_info.disc = 0;
+ /* handle argument of + and - specially */
+ if(*argv && argv[0][1]==0 && (*argv[0]=='+' || *argv[0]=='-'))
+ tdata.aflag = *argv[0];
+ else
+ argv--;
+ if((flag&NV_ZFILL) && !(flag&NV_LJUST))
+ flag |= NV_RJUST;
+ if((flag&NV_INTEGER) && (flag&(NV_LJUST|NV_RJUST|NV_ZFILL)))
+ error_info.errors++;
+ if((flag&NV_BINARY) && (flag&(NV_LJUST|NV_UTOL|NV_LTOU)))
+ error_info.errors++;
+ if((flag&NV_MOVE) && (flag&~(NV_MOVE|NV_VARNAME|NV_ASSIGN)))
+ error_info.errors++;
+ if((flag&NV_REF) && (flag&~(NV_REF|NV_IDENT|NV_ASSIGN)))
+ error_info.errors++;
+ if((flag&NV_TYPE) && (flag&~(NV_TYPE|NV_VARNAME|NV_ASSIGN)))
+ error_info.errors++;
+ if(troot==tdata.sh->fun_tree && ((isfloat || flag&~(NV_FUNCT|NV_TAGGED|NV_EXPORT|NV_LTOU))))
+ error_info.errors++;
+ if(sflag && troot==tdata.sh->fun_tree)
+ {
+ /* static function */
+ sflag = 0;
+ flag |= NV_STATICF;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s", optusage(NIL(char*)));
+ if(isfloat)
+ flag |= NV_DOUBLE;
+ if(shortint)
+ {
+ flag &= ~NV_LONG;
+ flag |= NV_SHORT|NV_INTEGER;
+ }
+ if(sflag)
+ {
+ if(tdata.sh->mktype)
+ flag |= NV_REF|NV_TAGGED;
+ else if(!tdata.sh->typeinit)
+ flag |= NV_STATIC|NV_IDENT;
+ }
+ if(tdata.sh->fn_depth && !tdata.pflag)
+ flag |= NV_NOSCOPE;
+ if(tdata.help)
+ tdata.help = strdup(tdata.help);
+ if(flag&NV_TYPE)
+ {
+ Stk_t *stkp = tdata.sh->stk;
+ int off=0,offset = stktell(stkp);
+ if(!tdata.prefix)
+ return(sh_outtype(tdata.sh,sfstdout));
+ sfputr(stkp,NV_CLASS,-1);
+#if SHOPT_NAMESPACE
+ if(tdata.sh->namespace)
+ {
+ off = stktell(stkp)+1;
+ sfputr(stkp,nv_name(tdata.sh->namespace),'.');
+ }
+ else
+#endif /* SHOPT_NAMESPACE */
+ if(NV_CLASS[sizeof(NV_CLASS)-2]!='.')
+ sfputc(stkp,'.');
+ sfputr(stkp,tdata.prefix,0);
+ tdata.tp = nv_open(stkptr(stkp,offset),tdata.sh->var_tree,NV_VARNAME|NV_NOARRAY|NV_NOASSIGN);
+#if SHOPT_NAMESPACE
+ if(!tdata.tp && off)
+ {
+ *stkptr(stkp,off)=0;
+ tdata.tp = nv_open(stkptr(stkp,offset),tdata.sh->var_tree,NV_VARNAME|NV_NOARRAY|NV_NOASSIGN);
+ }
+#endif /* SHOPT_NAMESPACE */
+ stkseek(stkp,offset);
+ if(!tdata.tp)
+ errormsg(SH_DICT,ERROR_exit(1),"%s: unknown type",tdata.prefix);
+ else if(nv_isnull(tdata.tp))
+ nv_newtype(tdata.tp);
+ tdata.tp->nvenv = tdata.help;
+ flag &= ~NV_TYPE;
+ }
+ else if(tdata.aflag==0 && ntp && ntp->tp)
+ tdata.aflag = '-';
+ if(!tdata.sh->mktype)
+ tdata.help = 0;
+ if(tdata.aflag=='+' && (flag&(NV_ARRAY|NV_IARRAY|NV_COMVAR)))
+ errormsg(SH_DICT,ERROR_exit(1),e_nounattr);
+ return(setall(argv,flag,troot,&tdata));
+}
+
+static void print_value(Sfio_t *iop, Namval_t *np, struct tdata *tp)
+{
+ char *name;
+ int aflag=tp->aflag;
+ if(nv_isnull(np))
+ {
+ if(!np->nvflag)
+ return;
+ aflag = '+';
+ }
+ else if(nv_istable(np))
+ {
+ Dt_t *root = tp->sh->last_root;
+ Namval_t *nsp = tp->sh->namespace;
+ char *cp = name = nv_name(np);
+ if(*name=='.')
+ name++;
+ if(tp->indent)
+ sfnputc(iop,'\t',tp->indent);
+ sfprintf(iop,"namespace %s\n", name);
+ if(tp->indent)
+ sfnputc(iop,'\t',tp->indent);
+ sfprintf(iop,"{\n", name);
+ tp->indent++;
+ /* output types from namespace */
+ tp->sh->namespace = 0;
+ tp->sh->prefix = nv_name(np)+1;
+ sh_outtype(tp->sh,iop);
+ tp->sh->prefix = 0;
+ tp->sh->namespace = np;
+ tp->sh->last_root = root;
+ /* output variables from namespace */
+ print_scan(iop,NV_NOSCOPE,nv_dict(np),aflag=='+',tp);
+ tp->wctname = cp;
+ tp->sh->namespace = 0;
+ /* output functions from namespace */
+ print_scan(iop,NV_FUNCTION|NV_NOSCOPE,tp->sh->fun_tree,aflag=='+',tp);
+ tp->wctname = 0;
+ tp->sh->namespace = nsp;
+ if(--tp->indent)
+ sfnputc(iop,'\t',tp->indent);
+ sfwrite(iop,"}\n",2);
+ return;
+ }
+ sfputr(iop,nv_name(np),aflag=='+'?'\n':'=');
+ if(aflag=='+')
+ return;
+ if(nv_isarray(np) && nv_arrayptr(np))
+ {
+ nv_outnode(np,iop,-1,0);
+ sfwrite(iop,")\n",2);
+ }
+ else
+ {
+ if(nv_isvtree(np))
+ nv_onattr(np,NV_EXPORT);
+ if(!(name = nv_getval(np)))
+ name = Empty;
+ if(!nv_isvtree(np))
+ name = sh_fmtq(name);
+ sfputr(iop,name,'\n');
+ }
+}
+
+static int setall(char **argv,register int flag,Dt_t *troot,struct tdata *tp)
+{
+ register char *name;
+ char *last = 0;
+ int nvflags=(flag&(NV_ARRAY|NV_NOARRAY|NV_VARNAME|NV_IDENT|NV_ASSIGN|NV_STATIC|NV_MOVE));
+ int r=0, ref=0, comvar=(flag&NV_COMVAR),iarray=(flag&NV_IARRAY);
+ Shell_t *shp =tp->sh;
+ if(!shp->prefix)
+ {
+ if(!tp->pflag)
+ nvflags |= NV_NOSCOPE;
+ }
+ else if(*shp->prefix==0)
+ shp->prefix = 0;
+ if(*argv[0]=='+')
+ nvflags |= NV_NOADD;
+ flag &= ~(NV_NOARRAY|NV_NOSCOPE|NV_VARNAME|NV_IDENT|NV_STATIC|NV_COMVAR|NV_IARRAY);
+ if(argv[1])
+ {
+ if(flag&NV_REF)
+ {
+ flag &= ~NV_REF;
+ ref=1;
+ if(tp->aflag!='-')
+ nvflags |= NV_NOREF;
+ }
+ if(tp->pflag)
+ nvflags |= NV_NOREF;
+ while(name = *++argv)
+ {
+ register unsigned newflag;
+ register Namval_t *np;
+ Namarr_t *ap;
+ Namval_t *mp;
+ unsigned curflag;
+ if(troot == shp->fun_tree)
+ {
+ /*
+ *functions can be exported or
+ * traced but not set
+ */
+ flag &= ~NV_ASSIGN;
+ if(flag&NV_LTOU)
+ {
+ /* Function names cannot be special builtin */
+ if((np=nv_search(name,shp->bltin_tree,0)) && nv_isattr(np,BLT_SPC))
+ errormsg(SH_DICT,ERROR_exit(1),e_badfun,name);
+#if SHOPT_NAMESPACE
+ if(shp->namespace)
+ np = sh_fsearch(shp,name,NV_ADD|HASH_NOSCOPE);
+ else
+#endif /* SHOPT_NAMESPACE */
+ np = nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE);
+ }
+ else
+ {
+ if(shp->prefix)
+ {
+ sfprintf(shp->strbuf,"%s.%s%c",shp->prefix,name,0);
+ name = sfstruse(shp->strbuf);
+ }
+#if SHOPT_NAMESPACE
+ np = 0;
+ if(shp->namespace)
+ np = sh_fsearch(shp,name,HASH_NOSCOPE);
+ if(!np)
+#endif /* SHOPT_NAMESPACE */
+ if(np=nv_search(name,troot,0))
+ {
+ if(!is_afunction(np))
+ np = 0;
+ }
+ else if(memcmp(name,".sh.math.",9)==0 && sh_mathstd(name+9))
+ continue;
+ }
+ if(np && ((flag&NV_LTOU) || !nv_isnull(np) || nv_isattr(np,NV_LTOU)))
+ {
+ if(flag==0 && !tp->help)
+ {
+ print_namval(sfstdout,np,tp->aflag=='+',tp);
+ continue;
+ }
+ if(shp->subshell && !shp->subshare)
+ sh_subfork();
+ if(tp->aflag=='-')
+ nv_onattr(np,flag|NV_FUNCTION);
+ else if(tp->aflag=='+')
+ nv_offattr(np,flag);
+ }
+ else
+ r++;
+ if(tp->help)
+ {
+ int offset = stktell(shp->stk);
+ if(!np)
+ {
+ sfputr(shp->stk,shp->prefix,'.');
+ sfputr(shp->stk,name,0);
+ np = nv_search(stkptr(shp->stk,offset),troot,0);
+ stkseek(shp->stk,offset);
+ }
+ if(np && np->nvalue.cp)
+ np->nvalue.rp->help = tp->help;
+ }
+ continue;
+ }
+ /* tracked alias */
+ if(troot==shp->track_tree && tp->aflag=='-')
+ {
+ np = nv_search(name,troot,NV_ADD);
+ path_alias(np,path_absolute(shp,nv_name(np),NIL(Pathcomp_t*)));
+ continue;
+ }
+ np = nv_open(name,troot,nvflags|((nvflags&NV_ASSIGN)?0:NV_ARRAY)|((iarray|(nvflags&NV_REF))?NV_FARRAY:0));
+ if(!np)
+ continue;
+ if(nv_isnull(np) && !nv_isarray(np) && nv_isattr(np,NV_NOFREE))
+ nv_offattr(np,NV_NOFREE);
+ else if(tp->tp && !nv_isattr(np,NV_MINIMAL|NV_EXPORT) && (mp=(Namval_t*)np->nvenv) && (ap=nv_arrayptr(mp)) && (ap->nelem&ARRAY_TREE))
+#if 0
+ errormsg(SH_DICT,ERROR_exit(1),e_typecompat,nv_name(np));
+#else
+ errormsg(SH_DICT,ERROR_exit(1),"%s: typecompat",nv_name(np));
+#endif
+ else if((ap=nv_arrayptr(np)) && nv_aindex(np)>0 && ap->nelem==1 && nv_getval(np)==Empty)
+ {
+ ap->nelem++;
+ _nv_unset(np,0);
+ ap->nelem--;
+ }
+ if(tp->pflag)
+ {
+ if(!nv_istable(np))
+ nv_attribute(np,sfstdout,tp->prefix,1);
+ print_value(sfstdout,np,tp);
+ continue;
+ }
+ if(flag==NV_ASSIGN && !ref && tp->aflag!='-' && !strchr(name,'='))
+ {
+ if(troot!=shp->var_tree && (nv_isnull(np) || !print_namval(sfstdout,np,0,tp)))
+ {
+ sfprintf(sfstderr,sh_translate(e_noalias),name);
+ r++;
+ }
+ if(!comvar && !iarray)
+ continue;
+ }
+ if(!nv_isarray(np) && !strchr(name,'=') && !(shp->envlist && nv_onlist(shp->envlist,name)))
+ {
+ if(comvar || (shp->last_root==shp->var_tree && (tp->tp || (!shp->st.real_fun && (nvflags&NV_STATIC)) || (!(flag&(NV_EXPORT|NV_RDONLY)) && nv_isattr(np,(NV_EXPORT|NV_IMPORT))==(NV_EXPORT|NV_IMPORT)))))
+{
+ _nv_unset(np,0);
+}
+ }
+ if(troot==shp->var_tree)
+ {
+ if(iarray)
+ {
+ if(tp->tname)
+ nv_atypeindex(np,tp->tname+1);
+ else if(nv_isnull(np))
+ nv_onattr(np,NV_ARRAY|(comvar?NV_NOFREE:0));
+ else
+ {
+ if(ap && comvar)
+ ap->nelem |= ARRAY_TREE;
+ nv_putsub(np, (char*)0, 0);
+ }
+ }
+ else if(nvflags&NV_ARRAY)
+ {
+ if(comvar)
+ {
+ Namarr_t *ap=nv_arrayptr(np);
+ if(ap)
+ ap->nelem |= ARRAY_TREE;
+ else
+ {
+ _nv_unset(np,NV_RDONLY);
+ nv_onattr(np,NV_NOFREE);
+ }
+ }
+ nv_setarray(np,nv_associative);
+ }
+ else if(comvar && !nv_isvtree(np) && !nv_rename(np,flag|NV_COMVAR))
+ nv_setvtree(np);
+ }
+ if(flag&NV_MOVE)
+ {
+ nv_rename(np, flag);
+ nv_close(np);
+ continue;
+ }
+ if(tp->tp && nv_type(np)!=tp->tp)
+ {
+ nv_settype(np,tp->tp,tp->aflag=='-'?0:NV_APPEND);
+ flag = (np->nvflag&NV_NOCHANGE);
+ }
+ flag &= ~NV_ASSIGN;
+ if(last=strchr(name,'='))
+ *last = 0;
+ if (shp->typeinit)
+ continue;
+ curflag = np->nvflag;
+ if(!(flag&NV_INTEGER) && (flag&(NV_LTOU|NV_UTOL)))
+ {
+ Namfun_t *fp;
+ char *cp;
+ if(!tp->wctname)
+ errormsg(SH_DICT,ERROR_exit(1),e_mapchararg,nv_name(np));
+ cp = (char*)nv_mapchar(np,0);
+ if(fp=nv_mapchar(np,tp->wctname))
+ {
+ if(tp->aflag=='+')
+ {
+ if(cp && strcmp(cp,tp->wctname)==0)
+ {
+ nv_disc(np,fp,NV_POP);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ nv_offattr(np,flag&(NV_LTOU|NV_UTOL));
+ }
+ }
+ else if(!cp || strcmp(cp,tp->wctname))
+ {
+ nv_disc(np,fp,NV_LAST);
+ nv_onattr(np,flag&(NV_LTOU|NV_UTOL));
+ }
+ }
+ }
+ if (tp->aflag == '-')
+ {
+ if((flag&NV_EXPORT) && (strchr(name,'.') || nv_isvtree(np)))
+ errormsg(SH_DICT,ERROR_exit(1),e_badexport,name);
+#if SHOPT_BSH
+ if(flag&NV_EXPORT)
+ nv_offattr(np,NV_IMPORT);
+#endif /* SHOPT_BSH */
+ newflag = curflag;
+ if(flag&~NV_NOCHANGE)
+ newflag &= NV_NOCHANGE;
+ newflag |= flag;
+ if (flag & (NV_LJUST|NV_RJUST))
+ {
+ if(!(flag&NV_RJUST))
+ newflag &= ~NV_RJUST;
+
+ else if(!(flag&NV_LJUST))
+ newflag &= ~NV_LJUST;
+ }
+ }
+ else
+ {
+ if((flag&NV_RDONLY) && (curflag&NV_RDONLY))
+ errormsg(SH_DICT,ERROR_exit(1),e_readonly,nv_name(np));
+ newflag = curflag & ~flag;
+ }
+ if (tp->aflag && (tp->argnum>0 || (curflag!=newflag)))
+ {
+ if(shp->subshell)
+ sh_assignok(np,1);
+ if(troot!=shp->var_tree)
+ nv_setattr(np,newflag&~NV_ASSIGN);
+ else
+ {
+ char *oldname=0;
+ int len=strlen(name);
+ if(tp->argnum==1 && newflag==NV_INTEGER && nv_isattr(np,NV_INTEGER))
+ tp->argnum = 10;
+ /* use reference name for export */
+ if((newflag^curflag)&NV_EXPORT)
+ {
+ oldname = np->nvname;
+ np->nvname = name;
+ }
+ if(np->nvfun && !nv_isarray(np) && name[len-1]=='.')
+ newflag |= NV_NODISC;
+ nv_newattr (np, newflag&~NV_ASSIGN,tp->argnum);
+ if(oldname)
+ np->nvname = oldname;
+ }
+ }
+ if(tp->help && !nv_isattr(np,NV_MINIMAL|NV_EXPORT))
+ {
+ np->nvenv = tp->help;
+ nv_onattr(np,NV_EXPORT);
+ }
+ if(last)
+ *last = '=';
+ /* set or unset references */
+ if(ref)
+ {
+ if(tp->aflag=='-')
+ {
+ Dt_t *hp=0;
+ if(nv_isattr(np,NV_PARAM) && shp->st.prevst)
+ {
+ if(!(hp=(Dt_t*)shp->st.prevst->save_tree))
+ hp = dtvnext(shp->var_tree);
+ }
+ if(tp->sh->mktype)
+ nv_onattr(np,NV_REF|NV_FUNCT);
+ else
+ nv_setref(np,hp,NV_VARNAME);
+ }
+ else
+ nv_unref(np);
+ }
+ nv_close(np);
+ }
+ }
+ else
+ {
+ if(shp->prefix)
+ errormsg(SH_DICT,2, e_subcomvar,shp->prefix);
+ if(tp->aflag)
+ {
+ if(troot==shp->fun_tree)
+ {
+ flag |= NV_FUNCTION;
+ tp->prefix = 0;
+ }
+ else if(troot==shp->var_tree)
+ {
+ flag |= (nvflags&NV_ARRAY);
+ if(flag&NV_IARRAY)
+ flag |= NV_ARRAY;
+ if(!(flag&~NV_ASSIGN))
+ tp->noref = 1;
+ }
+ if((flag&(NV_UTOL|NV_LTOU)) ==(NV_UTOL|NV_LTOU))
+ {
+ print_scan(sfstdout,flag&~NV_UTOL,troot,tp->aflag=='+',tp);
+ flag &= ~NV_LTOU;
+ }
+ print_scan(sfstdout,flag,troot,tp->aflag=='+',tp);
+ if(tp->noref)
+ {
+ tp->noref = 0;
+ print_scan(sfstdout,flag|NV_REF,troot,tp->aflag=='+',tp);
+ }
+ }
+ else if(troot==shp->alias_tree)
+ print_scan(sfstdout,0,troot,0,tp);
+ else
+ print_all(sfstdout,troot,tp);
+ sfsync(sfstdout);
+ }
+ return(r);
+}
+
+typedef void (*Iptr_t)(int,void*);
+
+#define GROWLIB 4
+
+static void **liblist;
+static unsigned short *libattr;
+static int nlib;
+static int maxlib;
+
+/*
+ * This allows external routines to load from the same library */
+void **sh_getliblist(void)
+{
+ return(liblist);
+}
+
+/*
+ * add library to loaded list
+ * call (*lib_init)() on first load if defined
+ * always move to head of search list
+ * return: 0: already loaded 1: first load
+ */
+#if SHOPT_DYNAMIC
+int sh_addlib(Shell_t *shp,void* library)
+{
+ register int n;
+ register int r;
+ Iptr_t initfn;
+ Shbltin_t *sp = &shp->bltindata;
+
+ sp->nosfio = 0;
+ for (n = r = 0; n < nlib; n++)
+ {
+ if (r)
+ {
+ liblist[n-1] = liblist[n];
+ libattr[n-1] = libattr[n];
+ }
+ else if (liblist[n] == library)
+ r++;
+ }
+ if (r)
+ nlib--;
+ else if ((initfn = (Iptr_t)dlllook(library, "lib_init")))
+ (*initfn)(0,sp);
+ if (nlib >= maxlib)
+ {
+ maxlib += GROWLIB;
+ if (liblist)
+ {
+ liblist = (void**)realloc((void*)liblist, (maxlib+1)*sizeof(void*));
+ libattr = (unsigned short*)realloc((void*)libattr, (maxlib+1)*sizeof(unsigned short));
+ }
+ else
+ {
+ liblist = (void**)malloc((maxlib+1)*sizeof(void*));
+ libattr = (unsigned short*)malloc((maxlib+1)*sizeof(unsigned short));
+ }
+ }
+ libattr[nlib] = (sp->nosfio?BLT_NOSFIO:0);
+ liblist[nlib++] = library;
+ liblist[nlib] = 0;
+ return !r;
+}
+#else
+int sh_addlib(Shell_t *shp,void* library)
+{
+ return 0;
+}
+#endif /* SHOPT_DYNAMIC */
+
+/*
+ * add change or list built-ins
+ * adding builtins requires dlopen() interface
+ */
+int b_builtin(int argc,char *argv[],Shbltin_t *context)
+{
+ register char *arg=0, *name;
+ register int n, r=0, flag=0;
+ register Namval_t *np;
+ long dlete=0;
+ struct tdata tdata;
+ Shbltin_f addr;
+ Stk_t *stkp;
+ void *library=0;
+ char *errmsg;
+#ifdef SH_PLUGIN_VERSION
+ unsigned long ver;
+ int list = 0;
+ char path[1024];
+#endif
+ NOT_USED(argc);
+ memset(&tdata,0,sizeof(tdata));
+ tdata.sh = context->shp;
+ stkp = tdata.sh->stk;
+ if(!tdata.sh->pathlist)
+ path_absolute(tdata.sh,argv[0],NIL(Pathcomp_t*));
+ while (n = optget(argv,sh_optbuiltin)) switch (n)
+ {
+ case 's':
+ flag = BLT_SPC;
+ break;
+ case 'd':
+ dlete=1;
+ break;
+ case 'f':
+#if SHOPT_DYNAMIC
+ arg = opt_info.arg;
+#else
+ errormsg(SH_DICT,2, "adding built-ins not supported");
+ error_info.errors++;
+#endif /* SHOPT_DYNAMIC */
+ break;
+ case 'l':
+#ifdef SH_PLUGIN_VERSION
+ list = 1;
+#endif
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s", optusage(NIL(char*)));
+ if(arg || *argv)
+ {
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,argv[-opt_info.index]);
+ if(sh_isoption(SH_PFSH))
+ errormsg(SH_DICT,ERROR_exit(1),e_pfsh,argv[-opt_info.index]);
+ if(tdata.sh->subshell && !tdata.sh->subshare)
+ sh_subfork();
+ }
+#if SHOPT_DYNAMIC
+ if(arg)
+ {
+#ifdef SH_PLUGIN_VERSION
+ if(!(library = dllplugin(SH_ID, arg, NiL, SH_PLUGIN_VERSION, &ver, RTLD_LAZY, path, sizeof(path))))
+ {
+ errormsg(SH_DICT,ERROR_exit(0),"%s: %s",arg,dllerror(0));
+ return(1);
+ }
+ if(list)
+ sfprintf(sfstdout, "%s %08lu %s\n", arg, ver, path);
+#else
+#if (_AST_VERSION>=20040404)
+ if(!(library = dllplug(SH_ID,arg,NIL(char*),RTLD_LAZY,NIL(char*),0)))
+#else
+ if(!(library = dllfind(arg,NIL(char*),RTLD_LAZY,NIL(char*),0)))
+#endif
+ {
+ errormsg(SH_DICT,ERROR_exit(0),"%s: %s",arg,dlerror());
+ return(1);
+ }
+#endif
+ sh_addlib(tdata.sh,library);
+ }
+ else
+#endif /* SHOPT_DYNAMIC */
+ if(*argv==0 && !dlete)
+ {
+ print_scan(sfstdout, flag, tdata.sh->bltin_tree, 1, &tdata);
+ return(0);
+ }
+ r = 0;
+ flag = stktell(stkp);
+ while(arg = *argv)
+ {
+ name = path_basename(arg);
+ sfwrite(stkp,"b_",2);
+ sfputr(stkp,name,0);
+ errmsg = 0;
+ addr = 0;
+ for(n=(nlib?nlib:dlete); --n>=0;)
+ {
+ /* (char*) added for some sgi-mips compilers */
+#if SHOPT_DYNAMIC
+ if(dlete || (addr = (Shbltin_f)dlllook(liblist[n],stkptr(stkp,flag))))
+#else
+ if(dlete)
+#endif /* SHOPT_DYNAMIC */
+ {
+ if(np = sh_addbuiltin(arg, addr,pointerof(dlete)))
+ {
+ if(dlete || nv_isattr(np,BLT_SPC))
+ errmsg = "restricted name";
+ else
+ nv_onattr(np,libattr[n]);
+ }
+ break;
+ }
+ }
+ if(!dlete && !addr)
+ {
+ np = sh_addbuiltin(arg, 0 ,0);
+ if(np && nv_isattr(np,BLT_SPC))
+ errmsg = "restricted name";
+ else if(!np)
+ errmsg = "not found";
+ }
+ if(errmsg)
+ {
+ errormsg(SH_DICT,ERROR_exit(0),"%s: %s",*argv,errmsg);
+ r = 1;
+ }
+ stkseek(stkp,flag);
+ argv++;
+ }
+ return(r);
+}
+
+int b_set(int argc,register char *argv[],Shbltin_t *context)
+{
+ struct tdata tdata;
+ int was_monitor = sh_isoption(SH_MONITOR);
+ memset(&tdata,0,sizeof(tdata));
+ tdata.sh = context->shp;
+ tdata.prefix=0;
+ if(argv[1])
+ {
+ if(sh_argopts(argc,argv,tdata.sh) < 0)
+ return(2);
+ if(sh_isoption(SH_VERBOSE))
+ sh_onstate(SH_VERBOSE);
+ else
+ sh_offstate(SH_VERBOSE);
+ if(sh_isoption(SH_MONITOR) && !was_monitor)
+ sh_onstate(SH_MONITOR);
+ else if(!sh_isoption(SH_MONITOR) && was_monitor)
+ sh_offstate(SH_MONITOR);
+ }
+ else
+ /*scan name chain and print*/
+ print_scan(sfstdout,0,tdata.sh->var_tree,0,&tdata);
+ return(0);
+}
+
+/*
+ * The removing of Shell variable names, aliases, and functions
+ * is performed here.
+ * Unset functions with unset -f
+ * Non-existent items being deleted give non-zero exit status
+ */
+
+int b_unalias(int argc,register char *argv[],Shbltin_t *context)
+{
+ Shell_t *shp = context->shp;
+ return(unall(argc,argv,shp->alias_tree,shp));
+}
+
+int b_unset(int argc,register char *argv[],Shbltin_t *context)
+{
+ Shell_t *shp = context->shp;
+ return(unall(argc,argv,shp->var_tree,shp));
+}
+
+static int unall(int argc, char **argv, register Dt_t *troot, Shell_t* shp)
+{
+ register Namval_t *np;
+ register const char *name;
+ register int r;
+ Dt_t *dp;
+ int nflag=0,all=0,isfun,jmpval;
+ struct checkpt buff;
+ NOT_USED(argc);
+ if(troot==shp->alias_tree)
+ {
+ name = sh_optunalias;
+ if(shp->subshell)
+ troot = sh_subaliastree(0);
+ }
+ else
+ name = sh_optunset;
+ while(r = optget(argv,name)) switch(r)
+ {
+ case 'f':
+ troot = sh_subfuntree(1);
+ break;
+ case 'a':
+ all=1;
+ break;
+ case 'n':
+ nflag = NV_NOREF;
+ case 'v':
+ troot = shp->var_tree;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(2);
+ }
+ argv += opt_info.index;
+ if(error_info.errors || (*argv==0 &&!all))
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
+ if(!troot)
+ return(1);
+ r = 0;
+ if(troot==shp->var_tree)
+ nflag |= NV_VARNAME;
+ else
+ nflag = NV_NOSCOPE;
+ if(all)
+ {
+ dtclear(troot);
+ return(r);
+ }
+ sh_pushcontext(shp,&buff,1);
+ while(name = *argv++)
+ {
+ jmpval = sigsetjmp(buff.buff,0);
+ np = 0;
+ if(jmpval==0)
+ {
+#if SHOPT_NAMESPACE
+ if(shp->namespace && troot!=shp->var_tree)
+ np = sh_fsearch(shp,name,nflag?HASH_NOSCOPE:0);
+ if(!np)
+#endif /* SHOPT_NAMESPACE */
+ np=nv_open(name,troot,NV_NOADD|nflag);
+ }
+ else
+ {
+ r = 1;
+ continue;
+ }
+ if(np)
+ {
+ if(is_abuiltin(np) || nv_isattr(np,NV_RDONLY))
+ {
+ if(nv_isattr(np,NV_RDONLY))
+ errormsg(SH_DICT,ERROR_warn(0),e_readonly, nv_name(np));
+ r = 1;
+ continue;
+ }
+ isfun = is_afunction(np);
+ if(troot==shp->var_tree)
+ {
+ Namarr_t *ap;
+#if SHOPT_FIXEDARRAY
+ if((ap=nv_arrayptr(np)) && !ap->fixed && name[strlen(name)-1]==']' && !nv_getsub(np))
+#else
+ if(nv_isarray(np) && name[strlen(name)-1]==']' && !nv_getsub(np))
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ r=1;
+ continue;
+ }
+
+ if(shp->subshell)
+ np=sh_assignok(np,0);
+ }
+ if(!nv_isnull(np))
+ _nv_unset(np,0);
+ if(troot==shp->var_tree && shp->st.real_fun && (dp=shp->var_tree->walk) && dp==shp->st.real_fun->sdict)
+ nv_delete(np,dp,NV_NOFREE);
+ else if(isfun)
+ nv_delete(np,troot,NV_NOFREE);
+#if 0
+ /* causes unsetting local variable to expose global */
+ else if(shp->var_tree==troot && shp->var_tree!=shp->var_base && nv_search((char*)np,shp->var_tree,HASH_BUCKET|HASH_NOSCOPE))
+ nv_delete(np,shp->var_tree,0);
+#endif
+ else
+ nv_close(np);
+
+ }
+ else if(troot==shp->alias_tree)
+ r = 1;
+ }
+ sh_popcontext(shp,&buff);
+ return(r);
+}
+
+/*
+ * print out the name and value of a name-value pair <np>
+ */
+
+static int print_namval(Sfio_t *file,register Namval_t *np,register int flag, struct tdata *tp)
+{
+ register char *cp;
+ int indent=tp->indent, outname=0, isfun;
+ sh_sigcheck(tp->sh);
+ if(flag)
+ flag = '\n';
+ if(tp->noref && nv_isref(np))
+ return(0);
+ if(nv_istable(np))
+ {
+ print_value(file,np,tp);
+ return(0);
+ }
+ if(nv_isattr(np,NV_NOPRINT|NV_INTEGER)==NV_NOPRINT)
+ {
+ if(is_abuiltin(np))
+ sfputr(file,nv_name(np),'\n');
+ return(0);
+ }
+ isfun = is_afunction(np);
+ if(tp->prefix)
+ {
+ outname = (*tp->prefix=='t' && (!nv_isnull(np) || nv_isattr(np,NV_FLOAT|NV_RDONLY|NV_BINARY|NV_RJUST|NV_NOPRINT)));
+ if(indent && (isfun || outname || *tp->prefix!='t'))
+ {
+ sfnputc(file,'\t',indent);
+ indent = 0;
+ }
+ if(!isfun)
+ {
+ if(*tp->prefix=='t')
+ nv_attribute(np,tp->outfile,tp->prefix,tp->aflag);
+ else
+ sfputr(file,tp->prefix,' ');
+ }
+ }
+ if(isfun)
+ {
+ Sfio_t *iop=0;
+ char *fname=0;
+ if(nv_isattr(np,NV_NOFREE))
+ return(0);
+ if(!flag && !np->nvalue.ip)
+ sfputr(file,"typeset -fu",' ');
+ else if(!flag && !nv_isattr(np,NV_FPOSIX))
+ sfputr(file,"function",' ');
+ cp = nv_name(np);
+ if(tp->wctname)
+ cp += strlen(tp->wctname)+1;
+ sfputr(file,cp,-1);
+ if(nv_isattr(np,NV_FPOSIX))
+ sfwrite(file,"()",2);
+ if(np->nvalue.ip && np->nvalue.rp->hoffset>=0)
+ fname = np->nvalue.rp->fname;
+ else
+ flag = '\n';
+ if(flag)
+ {
+ if(tp->pflag && np->nvalue.ip && np->nvalue.rp->hoffset>=0)
+ sfprintf(file," #line %d %s\n",np->nvalue.rp->lineno,fname?sh_fmtq(fname):"");
+ else
+ sfputc(file, '\n');
+ }
+ else
+ {
+ if(nv_isattr(np,NV_FTMP))
+ {
+ fname = 0;
+ iop = tp->sh->heredocs;
+ }
+ else if(fname)
+ iop = sfopen(iop,fname,"r");
+ else if(tp->sh->gd->hist_ptr)
+ iop = (tp->sh->gd->hist_ptr)->histfp;
+ if(iop && sfseek(iop,(Sfoff_t)np->nvalue.rp->hoffset,SEEK_SET)>=0)
+ sfmove(iop,file, nv_size(np), -1);
+ else
+ flag = '\n';
+ if(fname)
+ sfclose(iop);
+ }
+ return(nv_size(np)+1);
+ }
+ if(nv_arrayptr(np))
+ {
+ if(indent)
+ sfnputc(file,'\t',indent);
+ print_value(file,np,tp);
+ return(0);
+ }
+ if(nv_isvtree(np))
+ nv_onattr(np,NV_EXPORT);
+ if(cp=nv_getval(np))
+ {
+ if(indent)
+ sfnputc(file,'\t',indent);
+ sfputr(file,nv_name(np),-1);
+ if(!flag)
+ flag = '=';
+ sfputc(file,flag);
+ if(flag != '\n')
+ {
+ if(nv_isref(np) && nv_refsub(np))
+ {
+ sfputr(file,sh_fmtq(cp),-1);
+ sfprintf(file,"[%s]\n", sh_fmtq(nv_refsub(np)));
+ }
+ else
+#if SHOPT_TYPEDEF
+ sfputr(file,nv_isvtree(np)?cp:sh_fmtq(cp),'\n');
+#else
+ sfputr(file,sh_fmtq(cp),'\n');
+#endif /* SHOPT_TYPEDEF */
+ }
+ return(1);
+ }
+ else if(outname || (tp->scanmask && tp->scanroot==tp->sh->var_tree))
+ sfputr(file,nv_name(np),'\n');
+ return(0);
+}
+
+/*
+ * print attributes at all nodes
+ */
+static void print_all(Sfio_t *file,Dt_t *root, struct tdata *tp)
+{
+ tp->outfile = file;
+ nv_scan(root, print_attribute, (void*)tp, 0, 0);
+}
+
+/*
+ * print the attributes of name value pair give by <np>
+ */
+static void print_attribute(register Namval_t *np,void *data)
+{
+ register struct tdata *dp = (struct tdata*)data;
+ nv_attribute(np,dp->outfile,dp->prefix,dp->aflag);
+}
+
+/*
+ * print the nodes in tree <root> which have attributes <flag> set
+ * of <option> is non-zero, no subscript or value is printed.
+ */
+
+static void print_scan(Sfio_t *file, int flag, Dt_t *root, int option,struct tdata *tp)
+{
+ register char **argv;
+ register Namval_t *np;
+ register int namec;
+ Namval_t *onp = 0;
+ char *name=0;
+ int len;
+ tp->sh->last_table=0;
+ flag &= ~NV_ASSIGN;
+ tp->scanmask = flag&~NV_NOSCOPE;
+ tp->scanroot = root;
+ tp->outfile = file;
+#if SHOPT_TYPEDEF
+ if(!tp->prefix && tp->tp)
+ tp->prefix = nv_name(tp->tp);
+#endif /* SHOPT_TYPEDEF */
+ if(flag&NV_INTEGER)
+ tp->scanmask |= (NV_DOUBLE|NV_EXPNOTE);
+ if(flag==NV_LTOU || flag==NV_UTOL)
+ tp->scanmask |= NV_UTOL|NV_LTOU;
+ namec = nv_scan(root,nullscan,(void*)tp,tp->scanmask,flag);
+ argv = tp->argnam = (char**)stkalloc(tp->sh->stk,(namec+1)*sizeof(char*));
+ namec = nv_scan(root, pushname, (void*)tp, tp->scanmask, flag&~NV_IARRAY);
+ if(mbcoll())
+ strsort(argv,namec,strcoll);
+ if(namec==0 && tp->sh->namespace && nv_dict(tp->sh->namespace)==root)
+ {
+ sfnputc(file,'\t',tp->indent);
+ sfwrite(file,":\n",2);
+ }
+ else while(namec--)
+ {
+ if((np=nv_search(*argv++,root,0)) && np!=onp && (!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE)))
+ {
+ onp = np;
+ if(name)
+ {
+ char *newname = nv_name(np);
+ if(memcmp(name,newname,len)==0 && newname[len]== '.')
+ continue;
+ name = 0;
+ }
+ if(flag&NV_ARRAY)
+ {
+ if(nv_aindex(np)>=0)
+ {
+ if(!(flag&NV_IARRAY))
+ continue;
+ }
+ else if((flag&NV_IARRAY))
+ continue;
+
+ }
+ tp->scanmask = flag&~NV_NOSCOPE;
+ tp->scanroot = root;
+ print_namval(file,np,option,tp);
+ if(nv_isvtree(np))
+ {
+ name = nv_name(np);
+ len = strlen(name);
+ }
+ }
+ }
+}
+
+/*
+ * add the name of the node to the argument list argnam
+ */
+
+static void pushname(Namval_t *np,void *data)
+{
+ struct tdata *tp = (struct tdata*)data;
+ *tp->argnam++ = nv_name(np);
+}
+
diff --git a/src/cmd/ksh93/bltins/ulimit.c b/src/cmd/ksh93/bltins/ulimit.c
new file mode 100644
index 0000000..c537a81
--- /dev/null
+++ b/src/cmd/ksh93/bltins/ulimit.c
@@ -0,0 +1,216 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * ulimit [-HSacdfmnstuv] [limit]
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <sfio.h>
+#include <error.h>
+#include "defs.h"
+#include "builtins.h"
+#include "name.h"
+#include "ulimit.h"
+#ifndef SH_DICT
+# define SH_DICT "libshell"
+#endif
+
+#ifdef _no_ulimit
+ int b_ulimit(int argc,char *argv[],Shbltin_t *context)
+ {
+ NOT_USED(argc);
+ NOT_USED(argv);
+ NOT_USED(context);
+ errormsg(SH_DICT,ERROR_exit(2),e_nosupport);
+ return(0);
+ }
+#else
+
+static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
+{
+ register const Limit_t* tp;
+
+ for (tp = shtab_limits; tp->option; tp++)
+ {
+ sfprintf(sp, "[%c=%d:%s?The %s", tp->option, tp - shtab_limits + 1, tp->name, tp->description);
+ if(tp->type != LIM_COUNT)
+ sfprintf(sp, " in %ss", e_units[tp->type]);
+ sfprintf(sp, ".]");
+ }
+ return(1);
+}
+
+#define HARD 2
+#define SOFT 4
+
+int b_ulimit(int argc,char *argv[],Shbltin_t *context)
+{
+ register char *limit;
+ register int mode=0, n;
+ register unsigned long hit = 0;
+ Shell_t *shp = context->shp;
+#ifdef _lib_getrlimit
+ struct rlimit rlp;
+#endif /* _lib_getrlimit */
+ const Limit_t* tp;
+ char* conf;
+ int label, unit, nosupport;
+ rlim_t i;
+ char tmp[32];
+ Optdisc_t disc;
+ memset(&disc, 0, sizeof(disc));
+ disc.version = OPT_VERSION;
+ disc.infof = infof;
+ opt_info.disc = &disc;
+ while((n = optget(argv,sh_optulimit))) switch(n)
+ {
+ case 'H':
+ mode |= HARD;
+ continue;
+ case 'S':
+ mode |= SOFT;
+ continue;
+ case 'a':
+ hit = ~0;
+ break;
+ default:
+ if(n < 0)
+ hit |= (1L<<(-(n+1)));
+ else
+ errormsg(SH_DICT,2, e_notimp, opt_info.name);
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ opt_info.disc = 0;
+ /* default to -f */
+ limit = argv[opt_info.index];
+ if(hit==0)
+ for(n=0; shtab_limits[n].option; n++)
+ if(shtab_limits[n].index == RLIMIT_FSIZE)
+ {
+ hit |= (1L<<n);
+ break;
+ }
+ /* only one option at a time for setting */
+ label = (hit&(hit-1));
+ if(error_info.errors || (limit && label) || argc>opt_info.index+1)
+ errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
+ if(mode==0)
+ mode = (HARD|SOFT);
+ for(tp = shtab_limits; tp->option && hit; tp++,hit>>=1)
+ {
+ if(!(hit&1))
+ continue;
+ nosupport = (n = tp->index) == RLIMIT_UNKNOWN;
+ unit = shtab_units[tp->type];
+ if(limit)
+ {
+ if(shp->subshell && !shp->subshare)
+ sh_subfork();
+ if(strcmp(limit,e_unlimited)==0)
+ i = INFINITY;
+ else
+ {
+ char *last;
+ /* an explicit suffix unit overrides the default */
+ if((i=strtol(limit,&last,0))!=INFINITY && !*last)
+ i *= unit;
+ else if((i=strton(limit,&last,NiL,0))==INFINITY || *last)
+ {
+ if((i=sh_strnum(limit,&last,2))==INFINITY || *last)
+ errormsg(SH_DICT,ERROR_system(1),e_number,limit);
+ i *= unit;
+ }
+ }
+ if(nosupport)
+ errormsg(SH_DICT,ERROR_system(1),e_readonly,tp->name);
+ else
+ {
+#ifdef _lib_getrlimit
+ if(getrlimit(n,&rlp) <0)
+ errormsg(SH_DICT,ERROR_system(1),e_number,limit);
+ if(mode&HARD)
+ rlp.rlim_max = i;
+ if(mode&SOFT)
+ rlp.rlim_cur = i;
+ if(setrlimit(n,&rlp) <0)
+ errormsg(SH_DICT,ERROR_system(1),e_overlimit,limit);
+#else
+ if((i=vlimit(n,i)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_number,limit);
+#endif /* _lib_getrlimit */
+ }
+ }
+ else
+ {
+ if(!nosupport)
+ {
+#ifdef _lib_getrlimit
+ if(getrlimit(n,&rlp) <0)
+ errormsg(SH_DICT,ERROR_system(1),e_number,limit);
+ if(mode&HARD)
+ i = rlp.rlim_max;
+ if(mode&SOFT)
+ i = rlp.rlim_cur;
+#else
+# ifdef _lib_ulimit
+ n--;
+# endif /* _lib_ulimit */
+ i = -1;
+ if((i=vlimit(n,i)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_number,limit);
+#endif /* _lib_getrlimit */
+ }
+ if(label)
+ {
+ if(tp->type != LIM_COUNT)
+ sfsprintf(tmp,sizeof(tmp),"%s (%ss)", tp->description, e_units[tp->type]);
+ else
+ sfsprintf(tmp,sizeof(tmp),"%s", tp->name);
+ sfprintf(sfstdout,"%-30s (-%c) ",tmp,tp->option);
+ }
+ if(nosupport)
+ {
+ if(!tp->conf || !*(conf = astconf(tp->conf, NiL, NiL)))
+ conf = (char*)e_nosupport;
+ sfputr(sfstdout,conf,'\n');
+ }
+ else if(i!=INFINITY)
+ {
+ i += (unit-1);
+ sfprintf(sfstdout,"%I*d\n",sizeof(i),i/unit);
+ }
+ else
+ sfputr(sfstdout,e_unlimited,'\n');
+ }
+ }
+ return(0);
+}
+#endif /* _no_ulimit */
diff --git a/src/cmd/ksh93/bltins/umask.c b/src/cmd/ksh93/bltins/umask.c
new file mode 100644
index 0000000..19978ac
--- /dev/null
+++ b/src/cmd/ksh93/bltins/umask.c
@@ -0,0 +1,98 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * umask [-S] [mask]
+ *
+ * David Korn
+ * AT&T Labs
+ * research!dgk
+ *
+ */
+
+#include <ast.h>
+#include <sfio.h>
+#include <error.h>
+#include <ctype.h>
+#include <ls.h>
+#include <shell.h>
+#include "builtins.h"
+#ifndef SH_DICT
+# define SH_DICT "libshell"
+#endif
+
+int b_umask(int argc,char *argv[],Shbltin_t *context)
+{
+ register char *mask;
+ register int flag = 0, sflag = 0;
+ NOT_USED(context);
+ while((argc = optget(argv,sh_optumask))) switch(argc)
+ {
+ case 'S':
+ sflag++;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ argv += opt_info.index;
+ if(mask = *argv)
+ {
+ register int c;
+ if(isdigit(*mask))
+ {
+ while(c = *mask++)
+ {
+ if (c>='0' && c<='7')
+ flag = (flag<<3) + (c-'0');
+ else
+ errormsg(SH_DICT,ERROR_exit(1),e_number,*argv);
+ }
+ }
+ else
+ {
+ char *cp = mask;
+ flag = umask(0);
+ c = strperm(cp,&cp,~flag&0777);
+ if(*cp)
+ {
+ umask(flag);
+ errormsg(SH_DICT,ERROR_exit(1),e_format,mask);
+ }
+ flag = (~c&0777);
+ }
+ umask(flag);
+ }
+ else
+ {
+ umask(flag=umask(0));
+ if(sflag)
+ sfprintf(sfstdout,"%s\n",fmtperm(~flag&0777));
+ else
+ sfprintf(sfstdout,"%0#4o\n",flag);
+ }
+ return(0);
+}
+
diff --git a/src/cmd/ksh93/bltins/whence.c b/src/cmd/ksh93/bltins/whence.c
new file mode 100644
index 0000000..7843ca7
--- /dev/null
+++ b/src/cmd/ksh93/bltins/whence.c
@@ -0,0 +1,294 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * command [-pvVx] name [arg...]
+ * whence [-afvp] name...
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <error.h>
+#include "shtable.h"
+#include "name.h"
+#include "path.h"
+#include "shlex.h"
+#include "builtins.h"
+
+#define P_FLAG 1
+#define V_FLAG 2
+#define A_FLAG 4
+#define F_FLAG 010
+#define X_FLAG 020
+#define Q_FLAG 040
+
+static int whence(Shell_t *,char**, int);
+
+/*
+ * command is called with argc==0 when checking for -V or -v option
+ * In this case return 0 when -v or -V or unknown option, otherwise
+ * the shift count to the command is returned
+ */
+int b_command(register int argc,char *argv[],Shbltin_t *context)
+{
+ register int n, flags=0;
+ register Shell_t *shp = context->shp;
+ opt_info.index = opt_info.offset = 0;
+ while((n = optget(argv,sh_optcommand))) switch(n)
+ {
+ case 'p':
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,"-p");
+ sh_onstate(SH_DEFPATH);
+ break;
+ case 'v':
+ flags |= X_FLAG;
+ break;
+ case 'V':
+ flags |= V_FLAG;
+ break;
+ case 'x':
+ shp->xargexit = 1;
+ break;
+ case ':':
+ if(argc==0)
+ return(0);
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ if(argc==0)
+ return(0);
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ if(argc==0)
+ return(flags?0:opt_info.index);
+ argv += opt_info.index;
+ if(error_info.errors || !*argv)
+ errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
+ return(whence(shp,argv, flags));
+}
+
+/*
+ * for the whence command
+ */
+int b_whence(int argc,char *argv[],Shbltin_t *context)
+{
+ register int flags=0, n;
+ register Shell_t *shp = context->shp;
+ NOT_USED(argc);
+ if(*argv[0]=='t')
+ flags = V_FLAG;
+ while((n = optget(argv,sh_optwhence))) switch(n)
+ {
+ case 'a':
+ flags |= A_FLAG;
+ /* FALL THRU */
+ case 'v':
+ flags |= V_FLAG;
+ break;
+ case 'f':
+ flags |= F_FLAG;
+ break;
+ case 'p':
+ flags |= P_FLAG;
+ flags &= ~V_FLAG;
+ break;
+ case 'q':
+ flags |= Q_FLAG;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors || !*argv)
+ errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
+ return(whence(shp, argv, flags));
+}
+
+static int whence(Shell_t *shp,char **argv, register int flags)
+{
+ register const char *name;
+ register Namval_t *np;
+ register const char *cp;
+ register int aflag,r=0;
+ register const char *msg;
+ int tofree;
+ Dt_t *root;
+ Namval_t *nq;
+ char *notused;
+ Pathcomp_t *pp=0;
+ int notrack = 1;
+ if(flags&Q_FLAG)
+ flags &= ~A_FLAG;
+ while(name= *argv++)
+ {
+ tofree=0;
+ aflag = ((flags&A_FLAG)!=0);
+ cp = 0;
+ np = 0;
+ if(flags&P_FLAG)
+ goto search;
+ if(flags&Q_FLAG)
+ goto bltins;
+ /* reserved words first */
+ if(sh_lookup(name,shtab_reserved))
+ {
+ sfprintf(sfstdout,"%s%s\n",name,(flags&V_FLAG)?sh_translate(is_reserved):"");
+ if(!aflag)
+ continue;
+ aflag++;
+ }
+ /* non-tracked aliases */
+ if((np=nv_search(name,shp->alias_tree,0))
+ && !nv_isnull(np) && !(notrack=nv_isattr(np,NV_TAGGED))
+ && (cp=nv_getval(np)))
+ {
+ if(flags&V_FLAG)
+ {
+ if(nv_isattr(np,NV_EXPORT))
+ msg = sh_translate(is_xalias);
+ else
+ msg = sh_translate(is_alias);
+ sfprintf(sfstdout,msg,name);
+ }
+ sfputr(sfstdout,sh_fmtq(cp),'\n');
+ if(!aflag)
+ continue;
+ cp = 0;
+ aflag++;
+ }
+ /* built-ins and functions next */
+ bltins:
+ root = (flags&F_FLAG)?shp->bltin_tree:shp->fun_tree;
+ if(np= nv_bfsearch(name, root, &nq, &notused))
+ {
+ if(is_abuiltin(np) && nv_isnull(np))
+ goto search;
+ cp = "";
+ if(flags&V_FLAG)
+ {
+ if(nv_isnull(np))
+ cp = sh_translate(is_ufunction);
+ else if(is_abuiltin(np))
+ {
+ if(nv_isattr(np,BLT_SPC))
+ cp = sh_translate(is_spcbuiltin);
+ else
+ cp = sh_translate(is_builtin);
+ }
+ else
+ cp = sh_translate(is_function);
+ }
+ if(flags&Q_FLAG)
+ continue;
+ sfprintf(sfstdout,"%s%s\n",name,cp);
+ if(!aflag)
+ continue;
+ cp = 0;
+ aflag++;
+ }
+ search:
+ if(sh_isstate(SH_DEFPATH))
+ {
+ cp=0;
+ notrack=1;
+ }
+ do
+ {
+ if(path_search(shp,name,&pp,2+(aflag>1)))
+ {
+ cp = name;
+ if((flags&P_FLAG) && *cp!='/')
+ cp = 0;
+ }
+ else
+ {
+ cp = stakptr(PATH_OFFSET);
+ if(*cp==0)
+ cp = 0;
+ else if(*cp!='/')
+ {
+ cp = path_fullname(shp,cp);
+ tofree=1;
+ }
+ }
+ if(flags&Q_FLAG)
+ {
+ pp = 0;
+ r |= !cp;
+ }
+ else if(cp)
+ {
+ if(flags&V_FLAG)
+ {
+ if(*cp!= '/')
+ {
+ if(!np && (np=nv_search(name,shp->track_tree,0)))
+ sfprintf(sfstdout,"%s %s %s/%s\n",name,sh_translate(is_talias),path_pwd(shp,0),cp);
+ else if(!np || nv_isnull(np))
+ sfprintf(sfstdout,"%s%s\n",name,sh_translate(is_ufunction));
+ continue;
+ }
+ sfputr(sfstdout,sh_fmtq(name),' ');
+ /* built-in version of program */
+ if(*cp=='/' && (np=nv_search(cp,shp->bltin_tree,0)))
+ msg = sh_translate(is_builtver);
+ /* tracked aliases next */
+ else if(aflag>1 || !notrack || strchr(name,'/'))
+ msg = sh_translate("is");
+ else
+ msg = sh_translate(is_talias);
+ sfputr(sfstdout,msg,' ');
+ }
+ sfputr(sfstdout,sh_fmtq(cp),'\n');
+ if(aflag)
+ {
+ if(aflag<=1)
+ aflag++;
+ if (pp)
+ pp = pp->next;
+ }
+ else
+ pp = 0;
+ if(tofree)
+ {
+ free((char*)cp);
+ tofree = 0;
+ }
+ }
+ else if(aflag<=1)
+ {
+ r |= 1;
+ if(flags&V_FLAG)
+ errormsg(SH_DICT,ERROR_exit(0),e_found,sh_fmtq(name));
+ }
+ } while(pp);
+ }
+ return(r);
+}
+
diff --git a/src/cmd/ksh93/builtins.mm b/src/cmd/ksh93/builtins.mm
new file mode 100644
index 0000000..0a4ef7c
--- /dev/null
+++ b/src/cmd/ksh93/builtins.mm
@@ -0,0 +1,648 @@
+.fp 5 CW
+.ds DT January 9, 2012 \" use troff -mm
+.nr C 3
+.nr N 2
+.SA 1 \" right justified
+.TL "311466-6713" "49059-6" \" charging case filing case
+Guidelines for writing \f5ksh-93\fP built-in commands
+.AU "David G. Korn" DGK FP 11267 8062 D-237 "(research!dgk)"
+.AF
+.TM 11267-930???-93 \" technical memo + TM numbers
+.MT 4
+.AS 2 \" abstract start for TM
+One of the features of \f5ksh93\fP, the latest version of \f5ksh\fP,
+is the ability to add built-in commands at run time.
+This feature only works on operating systems that have the ability
+to load and link code into the current process at run time.
+Some examples of the systems that have this feature
+are Linux, System V Release 4, Solaris, Sun OS, HP-UX Release 8 and above,
+AIX 3.2 and above, and Microsoft Windows systems.
+.P
+This memo describes how to write and compile programs
+that can be loaded into \f5ksh\fP at run time as built-in
+commands.
+.AE \" abstract end
+.H 1 INTRODUCTION
+A built-in command is executed without creating a separate process.
+Instead, the command is invoked as a C function by \f5ksh\fP.
+If this function has no side effects in the shell process,
+then the behavior of this built-in is identical to that of
+the equivalent stand-alone command. The primary difference
+in this case is performance. The overhead of process creation
+is eliminated. For commands of short duration, the effect
+can be dramatic. For example, on SUN OS 4.1, the time to
+run \f5wc\fP on a small file of about 1000 bytes, runs
+about 50 times faster as a built-in command.
+.P
+In addition, built-in commands may have side effects on the
+shell environment.
+This is usually done to extend the application domain for
+shell programming. For example, there is a group of X-windows extension
+built-ins that make heavy use of the shell variable namespace.
+These built-ins are added at run time and
+result in a windowing shell that can be used to write
+X-windows applications.
+.P
+While there are definite advantages to adding built-in
+commands, there are some disadvantages as well.
+Since the built-in command and \f5ksh\fP share the same
+address space, a coding error in the built-in program
+may affect the behavior of \f5ksh\fP; perhaps causing
+it to core dump or hang.
+Debugging is also more complex since your code is now
+a part of a larger entity.
+The isolation provided by a separate process
+guarantees that all resources used by the command
+will be freed when the command completes.
+Resources used by a built-in must be meticulously maintained and freed.
+Also, since the address space of \f5ksh\fP will be larger when built-in are loaded,
+it may increase the time it takes \f5ksh\fP to fork() and
+exec() non-built-in commands.
+It makes no sense to add a built-in command that takes
+a long time to run or that is run only once, since the performance
+benefits will be negligible.
+Built-ins that have side effects in the current shell
+environment have the disadvantage of increasing the
+coupling between the built-in and \f5ksh\fP, making
+the overall system less modular and more monolithic.
+.P
+Despite these drawbacks, in many cases extending
+\f5ksh\fP by adding built-in
+commands makes sense and allows reuse of the shell
+scripting ability in an application specific domain.
+This memo describes how to write \f5ksh\fP extensions.
+.H 1 "WRITING BUILT-IN COMMANDS"
+There is a development kit available for writing \f5ksh\fP
+built-ins as part of the AST (AT&T Software Technology) Toolkit.
+The development kit has three directories,
+\f5include\fP, \f5lib\fP, and \f5bin\fP.
+It is best to set the value of the environment variable
+\f5PACKAGE_ast\fP to the pathname of the directory
+containing the development kit.
+The \f5include\fP directory contains a sub-directory
+named \f5ast\fP that contains interface prototypes
+for functions that you can call from built-ins. The \f5lib\fP
+directory contains the \f5ast\fP library
+and a library named \f5cmd\fP that contains a version
+of several of the standard POSIX\*(Rf
+.RS
+.I "POSIX \- Part 2: Shell and Utilities,"
+IEEE Std 1003.2-1992, ISO/IEC 9945-2:1993.
+.RF
+utilities that can be made run time built-ins.
+The \f5lib/ksh\fP directory contains shared libraries
+that implement other \f5ksh\fP built-ins.
+The \f5bin\fP directory contains build tools such as \f5nmake\fP\*(Rf.
+.RS
+Glenn Fowler,
+.IR "A Case for make" ,
+Software - Practice and Experience, Vol. 20 No. S1, pp. 30-46, June 1990.
+.RF
+To add built-ins at runtime, it is necessary to build a shared library
+containing one or more built-ins that you wish to add.
+The built-ins are then added by running \f5builtin \-f\fP \fIshared_lib\fP.
+Since the procedure for building share libraries is system dependent,
+it is best to use
+\f5nmake\fP
+using the sample nmake makefile below as a prototype.
+The AST Toolkit also contains some examples of built-in libraries under
+the \f5src/cmd/kshlib\fP directory.
+.P
+There are two ways to code adding built-ins. One method is to replace
+the function \f5main\fP with a function
+\f5b_\fP\fIname\fP, where \fIname\fP is the name
+of the built-in you wish to define.
+A built-in command has a calling convention similar to
+the \f5main\fP function of a program,
+\f5int main(int argc, char *argv[])\fP.
+except that it takes a third argument of type \f5Shbltin_t*\fP which can
+be passed as \f5\s-1NULL\s+1\fP if it is not used. The definition for
+\f5Shbltin_t*\fP is in \f5<ast/shcmd.h>\fP.
+Instead of \f5exit\fP, you need to use \f5return\fP
+to terminate your command.
+The return value will become the exit status of the command.
+The \f5open\fP built-in, installed in \f5lib/ksh\fP in the AST Toolkit, uses this method.
+The \f5Shbltin_t\fP structure contains a field named \f5shp\fP which is
+a pointer the the shell data that is needed for \f5shell\fP library callbacks.
+It also contains the fields, \f5shrun\fP, \f5shtrap\fP, \f5shexit\fP,
+and \f5shbltin\fP
+that are function pointers to the \f5shell\fP library functions \f5sh_run\fP, \f5sh_trap\fP
+\f5sh_exit\fP, and \f5sh_addbuiltin\fP, respectively. These functions
+can be invoked without the need for runtime symbol lookup when the
+shell is statically linked with \f5libshell\fP.
+.P
+The alternative method is to create a function \f5lib_init\fP and
+use the \f5Shbltin_t.shbltin()\fP function to add one or more built-ins.
+The \f5lib_init\fP function will be called with two arguments. The
+first argument will be 0 when the library is loaded and the second
+argument will be of type \f5Shbltin_t*\fP.
+The \f5dbm_t\fP and \f5dss\fP shell built-ins use this method.
+.P
+No matter which way you add built-ins you should add the line
+\f5SHLIB(\fP\fIidentifier\fP\f5)\fP as the last line of one
+of the built-in source file, where \fIidentifier\fP is any C identifier.
+This line provides version information to the shell \f5builtin\fP command
+that it uses to verify compatibility between the built-in and \f5ksh\fP
+implementation versions. \f5builtin\fP fails with a diagnostic on version
+mismatch. The diagnostic helps determine whether \f5ksh\fP is out of
+date and requires an upgrade or the built-in is out of date and requires
+recompilation.
+.P
+The steps necessary to create and add a run time built-in are
+illustrated in the following simple example.
+Suppose you wish to add a built-in command named \f5hello\fP
+which requires one argument and prints the word hello followed
+by its argument. First, write the following program in the file
+\f5hello.c\fP:
+.EX
+#include <stdio.h>
+int b_hello(int argc, char *argv[], void *context)
+{
+ if(argc != 2)
+ {
+ fprintf(stderr,"Usage: hello arg\en");
+ return(2);
+ }
+ printf("hello %s\en",argv[1]);
+ return(0);
+}
+SHLIB(hello)
+.EE
+.P
+Next, the program needs to be compiled.
+If you are building with AT&T \f5nmake\fP use the following \f5Makefile\fP:
+.EX
+:PACKAGE: --shared ast
+hello plugin=ksh :LIBRARY: hello.c
+.EE
+and run \f5nmake install\fP to compile, link, and install the built-in shared library
+in \f5lib/ksh/\fP under \f5PACKAGE_ast\fP.
+If the built-in extension uses several \f5.c\fP files, list all of these on
+the \f5:LIBRARY:\fP line.
+.P
+Otherwise you will have to compile \f5hello.c\fP with an option
+to pick up the AST include directory
+(since the AST \f5<stdio.h>\fP is required for \f5ksh\fP compatibility)
+and options required for generating shared libraries.
+For example, on Linux use this to compile:
+.EX
+cc -fpic -I$PACKAGE_ast/include/ast -c hello.c
+.EE
+and use the appropriate link line.
+It really is best to use \f5nmake\fP because the 2 line Makefile above
+will work on all systems that have \f5ksh\fP installed.
+.P
+If you have several built-ins, it is desirable
+to build a shared library that contains them all.
+.P
+The final step is using the built-in.
+This can be done with the \f5ksh\fP command \f5builtin\fP.
+To load the shared library \f5libhello.so\fP from the current directory
+and add the built-in \f5hello\fP, invoke the command,
+.EX
+builtin -f ./libhello.so hello
+.EE
+The shared library prefix (\f5lib\fP here) and suffix (\f5.so\fP here) be omitted;
+the shell will add an appropriate suffix
+for the system that it is loading from.
+If you install the shared library in \f5lib/ksh/\fP, where \f5../lib/ksh/\fP is
+a directory on \fB$PATH\fP, the command
+.EX
+builtin -f hello hello
+.EE
+will automatically find, load and install the built-in on any system.
+Once this command has been invoked, you can invoke \f5hello\fP
+as you do any other command.
+If you are using \f5lib_init\fP method to add built-ins then no arguments
+follow the \f5\-f\fP option.
+.P
+It is often desirable to make a command \fIbuilt-in\fP
+the first time that it is referenced. The first
+time \f5hello\fP is invoked, \f5ksh\fP should load and execute it,
+whereas for subsequent invocations \f5ksh\fP should just execute the built-in.
+This can be done by creating a file named \f5hello\fP
+with the following contents:
+.EX
+function hello
+{
+ unset -f hello
+ builtin -f hello hello
+ hello "$@"
+}
+.EE
+This file \f5hello\fP needs to be placed in a directory that is
+in your \fB\s-1FPATH\s+1\fP variable, and the built-in shared library
+should be installed in \f5lib/ksh/\fP, as described above.
+.H 1 "CODING REQUIREMENTS AND CONVENTIONS"
+As mentioned above, the entry point for built-ins must either be of
+the form \f5b_\fP\fIname\fP or else be loaded from a function named
+\f5lib_init\fP.
+Your built-ins can call functions from the standard C library,
+the \f5ast\fP library, interface functions provided by \f5ksh\fP,
+and your own functions.
+You should avoid using any global symbols beginning with
+.BR sh_ ,
+.BR nv_ ,
+and
+.B ed_
+since these are used by \f5ksh\fP itself.
+\f5#define\fP constants in \f5ksh\fP interface
+files use symbols beginning with \f5SH_\fP and \f5NV_\fP,
+so avoid using names beginning with these too.
+.H 2 "Header Files"
+The development kit provides a portable interface
+to the C library and to libast.
+The header files in the development kit are compatible with
+K&R C\*(Rf,
+.RS
+Brian W. Kernighan and Dennis M. Ritchie,
+.IR "The C Programming Language" ,
+Prentice Hall, 1978.
+.RF
+ANSI-C\*(Rf,
+.RS
+American National Standard for Information Systems \- Programming
+Language \- C, ANSI X3.159-1989.
+.RF
+and C++\*(Rf.
+.RS
+Bjarne Stroustroup,
+.IR "C++" ,
+Addison Wesley, xxxx
+.RF
+.P
+The best thing to do is to include the header file \f5<shell.h>\fP.
+This header file causes the \f5<ast.h>\fP header, the
+\f5<error.h>\fP header and the \f5<stak.h>\fP
+header to be included as well as defining prototypes
+for functions that you can call to get shell
+services for your builtins.
+The header file \f5<ast.h>\fP
+provides prototypes for many \fBlibast\fP functions
+and all the symbol and function definitions from the
+ANSI-C headers, \f5<stddef.h>\fP,
+\f5<stdlib.h>\fP, \f5<stdarg.h>\fP, \f5<limits.h>\fP,
+and \f5<string.h>\fP.
+It also provides all the symbols and definitions for the
+POSIX\*(Rf
+.RS
+.I "POSIX \- Part 1: System Application Program Interface,"
+IEEE Std 1003.1-1990, ISO/IEC 9945-1:1990.
+.RF
+headers \f5<sys/types.h>\fP, \f5<fcntl.h>\fP, and
+\f5<unistd.h>\fP.
+You should include \f5<ast.h>\fP instead of one or more of
+these headers.
+The \f5<error.h>\fP header provides the interface to the error
+and option parsing routines defined below.
+The \f5<stak.h>\fP header provides the interface to the memory
+allocation routines described below.
+.P
+Programs that want to use the information in \f5<sys/stat.h>\fP
+should include the file \f5<ls.h>\fP instead.
+This provides the complete POSIX interface to \f5stat()\fP
+related functions even on non-POSIX systems.
+.P
+.H 2 "Input/Output"
+\f5ksh\fP uses \fBsfio\fP,
+the Safe/Fast I/O library\*(Rf,
+.RS
+David Korn and Kiem-Phong Vo,
+.IR "SFIO - A Safe/Fast Input/Output library,"
+Proceedings of the Summer Usenix,
+pp. , 1991.
+.RF
+to perform all I/O operations.
+The \fBsfio\fP library, which is part of \fBlibast\fP,
+provides a superset of the functionality provided by the standard
+I/O library defined in ANSI-C.
+If none of the additional functionality is required,
+and if you are not familiar with \fBsfio\fP and
+you do not want to spend the time learning it,
+then you can use \f5sfio\fP via the \f5stdio\fP library
+interface. The development kit contains the header \f5<stdio.h>\fP
+which maps \f5stdio\fP calls to \f5sfio\fP calls.
+In most instances the mapping is done
+by macros or inline functions so that there is no overhead.
+The man page for the \f5sfio\fP library is in an Appendix.
+.P
+However, there are some very nice extensions and
+performance improvements in \f5sfio\fP
+and if you plan any major extensions I recommend
+that you use it natively.
+.H 2 "Error Handling"
+For error messages it is best to use the \f5ast\fP library
+function \f5errormsg()\fP rather that sending output to
+\f5stderr\fP or the equivalent \f5sfstderr\fP directly.
+Using \f5errormsg()\fP will make error message appear
+more uniform to the user.
+Furthermore, using \f5errormsg()\fP should make it easier
+to do error message translation for other locales
+in future versions of \f5ksh\fP.
+.P
+The first argument to
+\f5errormsg()\fP specifies the dictionary in which the string
+will be searched for translation.
+The second argument to \f5errormsg()\fP contains that error type
+and value. The third argument is a \fIprintf\fP style format
+and the remaining arguments are arguments to be printed
+as part of the message. A new-line is inserted at the
+end of each message and therefore, should not appear as
+part of the format string.
+The second argument should be one of the following:
+.VL .5i
+.LI \f5ERROR_exit(\fP\fIn\fP\f5)\fP:
+If \fIn\fP is not-zero, the builtin will exit value \fIn\fP after
+printing the message.
+.LI \f5ERROR_system(\fP\fIn\fP\f5)\fP:
+Exit builtin with exit value \fIn\fP after printing the message.
+The message will display the message corresponding to \f5errno\fP
+enclosed within \f5[\ ]\fP at the end of the message.
+.LI \f5ERROR_usage(\fP\fIn\fP\f5)\fP:
+Will generate a usage message and exit. If \fIn\fP is non-zero,
+the exit value will be 2. Otherwise the exit value will be 0.
+.LI \f5ERROR_debug(\fP\fIn\fP\f5)\fP:
+Will print a level \fIn\fP debugging message and will then continue.
+.LI \f5ERROR_warn(\fP\fIn\fP\f5)\fP:
+Prints a warning message. \fIn\fP is ignored.
+.H 2 "Option Parsing"
+The first thing that a built-in should do is to check
+the arguments for correctness and to print any usage
+messages on standard error.
+For consistency with the rest of \f5ksh\fP, it is best
+to use the \f5libast\fP functions \f5optget()\fP and
+\f5optusage()\fPfor this
+purpose.
+The header \f5<error.h>\fP includes prototypes for
+these functions.
+The \f5optget()\fP function is similar to the
+System V C library function \f5getopt()\fP,
+but provides some additional capabilities.
+Built-ins that use \f5optget()\fP provide a more
+consistent user interface.
+.P
+The \f5optget()\fP function is invoked as
+.EX
+int optget(char *\fIargv\fP[], const char *\fIoptstring\fP)
+.EE
+where \f5argv\fP is the argument list and \f5optstring\fP
+is a string that specifies the allowable arguments and
+additional information that is used to format \fIusage\fP
+messages.
+In fact a complete man page in \f5troff\fP or \f5html\fP
+can be generated by passing a usage string as described
+by the \f5getopts\fP command.
+Like \f5getopt()\fP,
+single letter options are represented by the letter itself,
+and options that take a string argument are followed by the \f5:\fP
+character.
+Option strings have the following special characters:
+.VL .5i
+.LI \f5:\fP
+Used after a letter option to indicate that the option
+takes an option argument.
+The variable \f5opt_info.arg\fP will point to this
+value after the given argument is encountered.
+.LI \f5#\fP
+Used after a letter option to indicate that the option
+can only take a numerical value.
+The variable \f5opt_info.num\fP will contain this
+value after the given argument is encountered.
+.LI \f5?\fP
+Used after a \f5:\fP or \f5#\fP (and after the optional \f5?\fP)
+to indicate the the
+preceding option argument is not required.
+.LI \f5[\fP...\f5]\fP
+After a \f5:\fP or \f5#\fP, the characters contained
+inside the brackets are used to identify the option
+argument when generating a \fIusage\fP message.
+.LI \fIspace\fP
+The remainder of the string will only be used when generating
+usage messages.
+.LE
+.P
+The \f5optget()\fP function returns the matching option letter if
+one of the legal option is matched.
+Otherwise, \f5optget()\fP returns
+.VL .5i
+.LI \f5':'\fP
+If there is an error. In this case the variable \f5opt_info.arg\fP
+contains the error string.
+.LI \f50\fP
+Indicates the end of options.
+The variable \f5opt_info.index\fP contains the number of arguments
+processed.
+.LI \f5'?'\fP
+A usage message has been required.
+You normally call \f5optusage()\fP to generate and display
+the usage message.
+.LE
+.P
+The following is an example of the option parsing portion
+of the \f5wc\fP utility.
+.EX
+#include <shell.h>
+while(1) switch(n=optget(argv,"xf:[file]"))
+{
+ case 'f':
+ file = opt_info.arg;
+ break;
+ case ':':
+ error(ERROR_exit(0), opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), opt_info.arg);
+ break;
+}
+.EE
+.H 2 "Storage Management"
+It is important that any memory used by your built-in
+be returned. Otherwise, if your built-in is called frequently,
+\f5ksh\fP will eventually run out of memory.
+You should avoid using \f5malloc()\fP for memory that must
+be freed before returning from you built-in, because by default,
+\f5ksh\fP will terminate you built-in in the event of an
+interrupt and the memory will not be freed.
+.P
+The best way to to allocate variable sized storage is
+through calls to the \fBstak\fP library
+which is included in \fBlibast\fP
+and which is used extensively by \f5ksh\fP itself.
+Objects allocated with the \f5stakalloc()\fP
+function are freed when you function completes
+or aborts.
+The \fBstak\fP library provides a convenient way to
+build variable length strings and other objects dynamically.
+The man page for the \fBstak\fP library is contained
+in the Appendix.
+.P
+Before \f5ksh\fP calls each built-in command, it saves
+the current stack location and restores it after
+it returns.
+It is not necessary to save and restore the stack
+location in the \f5b_\fP entry function,
+but you may want to write functions that use this stack
+are restore it when leaving the function.
+The following coding convention will do this in
+an efficient manner:
+.EX
+\fIyourfunction\fP()
+{
+ char *savebase;
+ int saveoffset;
+ if(saveoffset=staktell())
+ savebase = stakfreeze(0);
+ \fR...\fP
+ if(saveoffset)
+ stakset(savebase,saveoffset);
+ else
+ stakseek(0);
+}
+.EE
+.H 1 "CALLING \f5ksh\fP SERVICES"
+Some of the more interesting applications are those that extend
+the functionality of \f5ksh\fP in application specific directions.
+A prime example of this is the X-windows extension which adds
+builtins to create and delete widgets.
+The \fBnval\fP library is used to interface with the shell
+name space.
+The \fBshell\fP library is used to access other shell services.
+.H 2 "The nval library"
+A great deal of power is derived from the ability to use
+portions of the hierarchal variable namespace provided by \f5ksh-93\fP
+and turn these names into active objects.
+.P
+The \fBnval\fP library is used to interface with shell
+variables.
+A man page for this file is provided in an Appendix.
+You need to include the header \f5<nval.h>\fP
+to access the functions defined in the \fBnval\fP library.
+All the functions provided by the \fBnval\fP library begin
+with the prefix \f5nv_\fP.
+Each shell variable is an object in an associative table
+that is referenced by name.
+The type \f5Namval_t*\fP is pointer to a shell variable.
+To operate on a shell variable, you first get a handle
+to the variable with the \f5nv_open()\fP function
+and then supply the handle returned as the first
+argument of the function that provides an operation
+on the variable.
+You must call \f5nv_close()\fP when you are finished
+using this handle so that the space can be freed once
+the value is unset.
+The two most frequent operations are to get the value of
+the variable, and to assign value to the variable.
+The \f5nv_getval()\fP returns a pointer the the
+value of the variable.
+In some cases the pointer returned is to a region that
+will be overwritten by the next \f5nv_getval()\fP call
+so that if the value isn't used immediately, it should
+be copied.
+Many variables can also generate a numeric value.
+The \f5nv_getnum()\fP function returns a numeric
+value for the given variable pointer, calling the
+arithmetic evaluator if necessary.
+.P
+The \f5nv_putval()\fP function is used to assign a new
+value to a given variable.
+The second argument to \f5putval()\fP is the value
+to be assigned
+and the third argument is a \fIflag\fP which
+is used in interpreting the second argument.
+.P
+Each shell variable can have one or more attributes.
+The \f5nv_isattr()\fP is used to test for the existence
+of one or more attributes.
+See the appendix for a complete list of attributes.
+.P
+By default, each shell variable passively stores the string you
+give with with \f5nv_putval()\fP, and returns the value
+with \f5getval()\fP. However, it is possible to turn
+any node into an active entity by assigning functions
+to it that will be called whenever \f5nv_putval()\fP
+and/or \f5nv_getval()\fP is called.
+In fact there are up to five functions that can
+associated with each variable to override the
+default actions.
+The type \f5Namfun_t\fP is used to define these functions.
+Only those that are non-\f5NULL\fP override the
+default actions.
+To override the default actions, you must allocate an
+instance of \f5Namfun_t\fP, and then assign
+the functions that you wish to override.
+The \f5putval()\fP
+function is called by the \f5nv_putval()\fP function.
+A \f5NULL\fP for the \fIvalue\fP argument
+indicates a request to unset the variable.
+The \fItype\fP argument might contain the \f5NV_INTEGER\fP
+bit so you should be prepared to do a conversion if
+necessary.
+The \f5getval()\fP
+function is called by \f5nv_getval()\fP
+value and must return a string.
+The \f5getnum()\fP
+function is called by by the arithmetic evaluator
+and must return double.
+If omitted, then it will call \f5nv_getval()\fP and
+convert the result to a number.
+.P
+The functionality of a variable can further be increased
+by adding discipline functions that
+can be associated with the variable.
+A discipline function allows a script that uses your
+variable to define functions whose name is
+\fIvarname\fP\f5.\fP\fIdiscname\fP
+where \fIvarname\fP is the name of the variable, and \fIdiscname\fP
+is the name of the discipline.
+When the user defines such a function, the \f5settrap()\fP
+function will be called with the name of the discipline and
+a pointer to the parse tree corresponding to the discipline
+function.
+The application determines when these functions are actually
+executed.
+By default, \f5ksh\fP defines \f5get\fP,
+\f5set\fP, and \f5unset\fP as discipline functions.
+.P
+In addition, it is possible to provide a data area that
+will be passed as an argument to
+each of these functions whenever any of these functions are called.
+To have private data, you need to define and allocate a structure
+that looks like
+.EX
+struct \fIyours\fP
+{
+ Namfun_t fun;
+ \fIyour_data_fields\fP;
+};
+.EE
+.H 2 "The shell library"
+There are several functions that are used by \f5ksh\fP itself
+that can also be called from built-in commands.
+The man page for these routines are in the Appendix.
+.P
+The \f5sh_addbuiltin()\fP function can be used to add or delete
+builtin commands. It takes the name of the built-in, the
+address of the function that implements the built-in, and
+a \f5void*\fP pointer that will be passed to this function
+as the third agument whenever it is invoked.
+If the function address is \f5NULL\fP, the specified built-in
+will be deleted. However, special built-in functions cannot
+be deleted or modified.
+.P
+The \f5sh_fmtq()\fP function takes a string and returns
+a string that is quoted as necessary so that it can
+be used as shell input.
+This function is used to implement the \f5%q\fP option
+of the shell built-in \f5printf\fP command.
+.P
+The \f5sh_parse()\fP function returns a parse tree corresponding
+to a give file stream. The tree can be executed by supplying
+it as the first argument to
+the \f5sh_trap()\fP function and giving a value of \f51\fP as the
+second argument.
+Alternatively, the \f5sh_trap()\fP function can parse and execute
+a string by passing the string as the first argument and giving \f50\fP
+as the second argument.
+.P
+The \f5sh_isoption()\fP function can be used to set to see whether one
+or more of the option settings is enabled.
diff --git a/src/cmd/ksh93/data/aliases.c b/src/cmd/ksh93/data/aliases.c
new file mode 100644
index 0000000..d9eca14
--- /dev/null
+++ b/src/cmd/ksh93/data/aliases.c
@@ -0,0 +1,57 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#include "defs.h"
+#include <signal.h>
+#include "FEATURE/options"
+#include "FEATURE/dynamic"
+
+/*
+ * This is the table of built-in aliases. These should be exported.
+ */
+
+const struct shtable2 shtab_aliases[] =
+{
+#if SHOPT_FS_3D
+ "2d", NV_NOFREE, "set -f;_2d",
+#endif /* SHOPT_FS_3D */
+ "autoload", NV_NOFREE, "typeset -fu",
+ "command", NV_NOFREE, "command ",
+ "compound", NV_NOFREE, "typeset -C",
+ "fc", NV_NOFREE, "hist",
+ "float", NV_NOFREE, "typeset -lE",
+ "functions", NV_NOFREE, "typeset -f",
+ "hash", NV_NOFREE, "alias -t --",
+ "history", NV_NOFREE, "hist -l",
+ "integer", NV_NOFREE, "typeset -li",
+ "nameref", NV_NOFREE, "typeset -n",
+ "nohup", NV_NOFREE, "nohup ",
+ "r", NV_NOFREE, "hist -s",
+ "redirect", NV_NOFREE, "command exec",
+ "source", NV_NOFREE, "command .",
+#ifdef SIGTSTP
+ "stop", NV_NOFREE, "kill -s STOP",
+ "suspend", NV_NOFREE, "kill -s STOP $$",
+#endif /*SIGTSTP */
+ "times", NV_NOFREE, "{ { time;} 2>&1;}",
+ "type", NV_NOFREE, "whence -v",
+ "", 0, (char*)0
+};
+
diff --git a/src/cmd/ksh93/data/bash_pre_rc.sh b/src/cmd/ksh93/data/bash_pre_rc.sh
new file mode 100644
index 0000000..4f8a451
--- /dev/null
+++ b/src/cmd/ksh93/data/bash_pre_rc.sh
@@ -0,0 +1,255 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# bash compatibility startup script
+#
+# Author:
+# Karsten Fleischer
+# Omnium Software Engineering
+# An der Luisenburg 7
+# D-51379 Leverkusen
+# Germany
+#
+# <K.Fleischer@omnium.de>
+#
+
+alias declare=typeset
+
+nameref FUNCNAME=.sh.fun
+integer SHLVL
+export SHLVL
+SHLVL+=1
+
+if [[ ! $EUID ]]
+then EUID=$(id -u)
+ readonly EUID
+fi
+
+if [[ ! $UID ]]
+then UID=$(id -u)
+ readonly UID
+fi
+
+readonly SHELLOPTS
+if ! shopt -qo restricted; then
+ IFS=:
+ for i in $SHELLOPTS
+ do
+ [[ -n "$i" ]] && set -o $i
+ done
+ unset IFS
+fi
+function SHELLOPTS.get
+{
+ .sh.value=$(shopt -so)
+ .sh.value=${.sh.value//+([[:space:]])on*([[:space:]])/:}
+ .sh.value=${.sh.value%:}
+}
+
+set -A GROUPS $(id -G)
+function GROUPS.set
+{
+ return 1
+}
+function GROUPS.unset
+{
+ unset -f GROUPS.set
+ unset -f GROUPS.unset
+}
+
+typeset -A DIRSTACK
+function DIRSTACK.get
+{
+ set -A .sh.value $(dirs)
+}
+function DIRSTACK.set
+{
+ integer index
+ index=_push_max-.sh.subscript
+ (( index == _push_max || index < _push_top )) && return
+ _push_stack[index]=${.sh.value}
+}
+function DIRSTACK.unset
+{
+ unset -f DIRSTACK.get
+ unset -f DIRSTACK.set
+ unset -f DIRSTACK.unset
+}
+
+function PS1.set
+{
+ typeset prefix remaining=${.sh.value} var= n= k=
+ while [[ $remaining ]]
+ do prefix=${remaining%%'\'*}
+ remaining=${remaining#$prefix}
+ var+="$prefix"
+ case ${remaining:1:1} in
+ t) var+="\$(printf '%(%H:%M:%S)T')";;
+ d) var+="\$(printf '%(%a %b:%e)T')";;
+ n) var+=$'\n';;
+ s) var+=ksh;;
+ w) var+="\$(pwd)";;
+ W) var+="\$(basename \"\$(pwd)\")";;
+ u) var+=$USER;;
+ h) var+=$(hostname -s);;
+ '#') var+=!;;
+ !) var+=!;;
+ @) var+="\$(printf '%(%I:%M%p)T')";;
+ '$') if (( $(id -u) == 0 ))
+ then var+='#'
+ else var+='$'
+ fi;;
+ '\') var+='\\';;
+ '['|']') ;;
+ [0-7]) case ${remaining:1:3} in
+ [0-7][0-7][0-7])
+ k=4;;
+ [0-7][0-7])
+ k=3;;
+ *) k=2;;
+ esac
+ eval n="\$'"${remaining:0:k}"'"
+ var+=$n
+ remaining=${remaining:k}
+ continue
+ ;;
+ "") ;;
+ *) var+='\'${remaining:0:2};;
+ esac
+ remaining=${remaining:2}
+ done
+ .sh.value=$var
+}
+function logout
+{
+ if shopt -q login_shell; then
+ exit
+ else
+ print ${BASH##*/}: $0: not login shell: use 'exit' >&2
+ return 1
+ fi
+}
+PS1="bash$ "
+
+function source
+{
+ if ! shopt -qpo posix; then
+ unset OPATH
+ typeset OPATH=$PATH
+ typeset PATH=$PATH
+ if shopt -q sourcepath; then
+ PATH=$OPATH:.
+ else
+ PATH=.
+ fi
+ fi
+ . "$@"
+}
+unalias .
+alias .=source
+
+alias enable=builtin
+
+function help
+{
+ typeset b cmd usage try_cmd man
+ function has_help_option
+ {
+ [[ $1 == @(''|/*|:|echo|false|true|login|test|'[') ]] && return 1
+ return 0
+ }
+ typeset -A short_use=(
+ [echo]='Usage: echo [ options ] [arg]...'
+ [:]='Usage: : ...'
+ [true]='Usage: true ...'
+ [false]='Usage: false ...'
+ [login]='Usage: login [-p] [name]'
+ ['[']='Usage: [ EXPRESSION ] | [ OPTION'
+ [test]='Usage: test EXPRESSION | test'
+ )
+ b=$(builtin)
+ if (( $# == 0))
+ then print 'The following is the current list of built-in commands:'
+ print -r $'Type help *name* for more information about name\n'
+ for cmd in $b
+ do if has_help_option $cmd
+ then usage=$($cmd --short 2>&1)
+ print -r -- "${usage:7}"
+ else print -r -- ${short_use[$cmd]:7}
+ fi
+ done
+ return
+ fi
+ b=${b/'['/}
+ man=--man
+ [[ $1 == -s ]] && man=--short && shift
+ for try_cmd
+ do if has_help_option $try_cmd
+ then if [[ $try_cmd == @(${b//$'\n'/'|'}) ]]
+ then $try_cmd $man
+ else man $try_cmd
+ fi
+ elif [[ $man == '--short' ]]
+ then print -r -- ${short_use[$try_cmd]}
+ else man $try_cmd
+ fi
+ done
+}
+
+function cd
+{
+
+ local msg
+ local args
+ local i
+ local a
+ local ret
+
+ if ! shopt -q cdable_vars; then
+ command cd "$@"
+ else
+ msg=$(command cd "$@" 2>&1)
+ ret=$?
+ if [[ $ret != 0 ]]; then
+ for i
+ do
+ case $i in
+ -*) args="$args $i" ;;
+ */*) args="$args $i" ;;
+ *) eval a="$"$i
+ if [[ -n $a ]]; then args="$args $a"
+ else args="$args $i"
+ fi
+ ;;
+ esac
+ done
+
+ command cd $args
+ else
+ print -- $msg
+ return $ret
+ fi
+ fi
+}
+
+typeset BASH=$0
+! shopt -qo posix && HISTFILE=~/.bash_history
+HOSTNAME=$(hostname)
+nameref BASH_SUBSHELL=.sh.subshell
diff --git a/src/cmd/ksh93/data/builtins.c b/src/cmd/ksh93/data/builtins.c
new file mode 100644
index 0000000..98300fa
--- /dev/null
+++ b/src/cmd/ksh93/data/builtins.c
@@ -0,0 +1,1902 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+
+#include "defs.h"
+#include "shtable.h"
+#include <signal.h>
+#include "ulimit.h"
+#include "name.h"
+#include "version.h"
+#if KSHELL
+# include "builtins.h"
+# include "jobs.h"
+# include "FEATURE/cmds"
+# define bltin(x) (b_##x)
+ /* The following is for builtins that do not accept -- options */
+# define Bltin(x) (B_##x)
+#else
+# define bltin(x) 0
+#endif
+
+#if defined(SHOPT_CMDLIB_DIR) && !defined(SHOPT_CMDLIB_HDR)
+# define SHOPT_CMDLIB_HDR <cmdlist.h>
+#endif
+#define Q(f) #f /* libpp cpp workaround -- fixed 2005-04-11 */
+#define CMDLIST(f) SH_CMDLIB_DIR "/" Q(f), NV_BLTIN|NV_BLTINOPT|NV_NOFREE, bltin(f),
+
+#undef basename
+#undef dirname
+
+/*
+ * The order up through "[" is significant
+ */
+const struct shtable3 shtab_builtins[] =
+{
+ "login", NV_BLTIN|BLT_ENV|BLT_SPC, Bltin(login),
+ "exec", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(exec),
+ "set", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(set),
+ ":", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(true),
+ "true", NV_BLTIN|BLT_ENV, bltin(true),
+ "command", NV_BLTIN|BLT_ENV|BLT_EXIT, bltin(command),
+ "cd", NV_BLTIN|BLT_ENV, bltin(cd),
+ "break", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(break),
+ "continue", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(break),
+ "typeset", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_DCL,bltin(typeset),
+ "test", NV_BLTIN|BLT_ENV, bltin(test),
+ "[", NV_BLTIN|BLT_ENV, bltin(test),
+ "let", NV_BLTIN|BLT_ENV, bltin(let),
+ "export", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_DCL,bltin(readonly),
+ ".", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(dot_cmd),
+ "return", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(return),
+#if SHOPT_BASH
+ "local", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_DCL,bltin(typeset),
+#endif
+#if _bin_newgrp || _usr_bin_newgrp
+ "newgrp", NV_BLTIN|BLT_ENV|BLT_SPC, Bltin(login),
+#endif /* _bin_newgrp || _usr_bin_newgrp */
+ "alias", NV_BLTIN|BLT_SPC|BLT_DCL, bltin(alias),
+ "hash", NV_BLTIN|BLT_SPC|BLT_DCL, bltin(alias),
+ "enum", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_DCL,bltin(enum),
+ "eval", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_EXIT,bltin(eval),
+ "exit", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(return),
+ "fc", NV_BLTIN|BLT_ENV|BLT_EXIT, bltin(hist),
+ "hist", NV_BLTIN|BLT_ENV|BLT_EXIT, bltin(hist),
+ "readonly", NV_BLTIN|BLT_ENV|BLT_SPC|BLT_DCL,bltin(readonly),
+ "shift", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(shift),
+ "trap", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(trap),
+ "unalias", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(unalias),
+ "unset", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(unset),
+ "builtin", NV_BLTIN, bltin(builtin),
+#if SHOPT_ECHOPRINT
+ "echo", NV_BLTIN|BLT_ENV, bltin(print),
+#else
+ "echo", NV_BLTIN|BLT_ENV, Bltin(echo),
+#endif /* SHOPT_ECHOPRINT */
+#ifdef JOBS
+# ifdef SIGTSTP
+ "bg", NV_BLTIN|BLT_ENV, bltin(bg),
+ "fg", NV_BLTIN|BLT_ENV|BLT_EXIT, bltin(bg),
+ "disown", NV_BLTIN|BLT_ENV, bltin(bg),
+ "kill", NV_BLTIN|BLT_ENV, bltin(kill),
+# else
+ "/bin/kill", NV_BLTIN|BLT_ENV, bltin(kill),
+# endif /* SIGTSTP */
+ "jobs", NV_BLTIN|BLT_ENV, bltin(jobs),
+#endif /* JOBS */
+ "false", NV_BLTIN|BLT_ENV, bltin(false),
+ "getopts", NV_BLTIN|BLT_ENV, bltin(getopts),
+ "print", NV_BLTIN|BLT_ENV, bltin(print),
+ "printf", NV_BLTIN|BLT_ENV, bltin(printf),
+ "pwd", NV_BLTIN, bltin(pwd),
+ "read", NV_BLTIN|BLT_ENV, bltin(read),
+ "sleep", NV_BLTIN, bltin(sleep),
+ "alarm", NV_BLTIN, bltin(alarm),
+ "ulimit", NV_BLTIN|BLT_ENV, bltin(ulimit),
+ "umask", NV_BLTIN|BLT_ENV, bltin(umask),
+#ifdef _cmd_universe
+ "universe", NV_BLTIN|BLT_ENV, bltin(universe),
+#endif /* _cmd_universe */
+#if SHOPT_FS_3D
+ "vpath", NV_BLTIN|BLT_ENV, bltin(vpath),
+ "vmap", NV_BLTIN|BLT_ENV, bltin(vpath),
+#endif /* SHOPT_FS_3D */
+ "wait", NV_BLTIN|BLT_ENV|BLT_EXIT, bltin(wait),
+ "type", NV_BLTIN|BLT_ENV, bltin(whence),
+ "whence", NV_BLTIN|BLT_ENV, bltin(whence),
+#ifdef SHOPT_CMDLIB_HDR
+#include SHOPT_CMDLIB_HDR
+#else
+ CMDLIST(basename)
+ CMDLIST(chmod)
+ CMDLIST(dirname)
+ CMDLIST(getconf)
+ CMDLIST(head)
+ CMDLIST(mkdir)
+ CMDLIST(logname)
+ CMDLIST(cat)
+ CMDLIST(cmp)
+ CMDLIST(cut)
+ CMDLIST(uname)
+ CMDLIST(wc)
+ CMDLIST(sync)
+#endif
+#if SHOPT_REGRESS
+ "__regress__", NV_BLTIN|BLT_ENV, bltin(__regress__),
+#endif
+ "", 0, 0
+};
+
+#if SHOPT_COSHELL
+# define _JOB_ "[+?Each \ajob\a can be specified as one of the following:]{" \
+ "[+\anumber\a?\anumber\a refers to a process id.]" \
+ "[+-\anumber\a?\anumber\a refers to a process group id.]" \
+ "[+\apool\a.\anum\a?refers to job \anum\a in background pool named \apool\a.]" \
+ "[+\apool\a?refers to all jobs in background pool named \apool\a.]" \
+ "[+%\anumber\a?\anumber\a refer to a job number.]" \
+ "[+%\astring\a?Refers to a job whose name begins with \astring\a.]" \
+ "[+%??\astring\a?Refers to a job whose name contains \astring\a.]" \
+ "[+%+ \bor\b %%?Refers to the current job.]" \
+ "[+%-?Refers to the previous job.]" \
+ "}"
+#else
+# define _JOB_ "[+?Each \ajob\a can be specified as one of the following:]{" \
+ "[+\anumber\a?\anumber\a refers to a process id.]" \
+ "[+-\anumber\a?\anumber\a refers to a process group id.]" \
+ "[+%\anumber\a?\anumber\a refer to a job number.]" \
+ "[+%\astring\a?Refers to a job whose name begins with \astring\a.]" \
+ "[+%??\astring\a?Refers to a job whose name contains \astring\a.]" \
+ "[+%+ \bor\b %%?Refers to the current job.]" \
+ "[+%-?Refers to the previous job.]" \
+ "}"
+#endif
+
+
+const char sh_set[] =
+"[a?Set the export attribute for each variable whose name does not "
+ "contain a \b.\b that you assign a value in the current shell "
+ "environment.]"
+"[b?The shell writes a message to standard error as soon it detects that "
+ "a background job completes rather than waiting until the next prompt.]"
+"[e?A simple command that has an non-zero exit status will cause the shell "
+ "to exit unless the simple command is:]{"
+ "[++?contained in an \b&&\b or \b||\b list.]"
+ "[++?the command immediately following \bif\b, \bwhile\b, or \buntil\b.]"
+ "[++?contained in the pipeline following \b!\b.]"
+"}"
+"[f?Pathname expansion is disabled.]"
+"[h?Obsolete. Causes each command whose name has the syntax of an "
+ "alias to become a tracked alias when it is first encountered.]"
+"[k?This is obsolete. All arguments of the form \aname\a\b=\b\avalue\a "
+ "are removed and placed in the variable assignment list for "
+ "the command. Ordinarily, variable assignments must precede "
+ "command arguments.]"
+"[m?When enabled, the shell runs background jobs in a separate process "
+ "group and displays a line upon completion. This mode is enabled "
+ "by default for interactive shells on systems that support job "
+ "control.]"
+"[n?The shell reads commands and checks for syntax errors, but does "
+ "not execute the command. Usually specified on command invocation.]"
+"[o]:?[option?If \aoption\a is not specified, the list of options and "
+ "their current settings will be written to standard output. When "
+ "invoked with a \b+\b the options will be written in a format "
+ "that can be reinput to the shell to restore the settings. "
+ "This option can be repeated to enable/disable multiple options. "
+ "The value of \aoption\a must be one of the following:]{"
+ "[+allexport?Equivalent to \b-a\b.]"
+ "[+bgnice?Runs background jobs at lower priorities.]"
+ "[+braceexpand?Equivalent to \b-B\b.] "
+ "[+emacs?Enables/disables \bemacs\b editing mode.]"
+ "[+errexit?Equivalent to \b-e\b.]"
+ "[+globstar?Equivalent to \b-G\b.]"
+ "[+gmacs?Enables/disables \bgmacs\b editing mode. \bgmacs\b "
+ "editing mode is the same as \bemacs\b editing mode "
+ "except for the handling of \b^T\b.]"
+#if SHOPT_BASH
+ "[+hashall?Equivalent to \b-h\b and \b-o trackall\b. Available "
+ "in bash compatibility mode only.]"
+ "[+history?Enable command history. Available in bash "
+ "compatibility mode only. On by default in interactive "
+ "shells.]"
+#endif
+#if SHOPT_HISTEXPAND
+ "[+histexpand?Equivalent to \b-H\b.]"
+#endif
+ "[+ignoreeof?Prevents an interactive shell from exiting on "
+ "reading an end-of-file.]"
+ "[+keyword?Equivalent to \b-k\b.]"
+ "[+letoctal?The \blet\b builtin recognizes octal constants "
+ "with leading 0.]"
+ "[+markdirs?A trailing \b/\b is appended to directories "
+ "resulting from pathname expansion.]"
+ "[+monitor?Equivalent to \b-m\b.]"
+ "[+multiline?Use multiple lines when editing lines that are "
+ "longer than the window width.]"
+ "[+noclobber?Equivalent to \b-C\b.]"
+ "[+noexec?Equivalent to \b-n\b.]"
+ "[+noglob?Equivalent to \b-f\b.]"
+ "[+nolog?This has no effect. It is provided for backward "
+ "compatibility.]"
+ "[+notify?Equivalent to \b-b\b.]"
+ "[+nounset?Equivalent to \b-u\b.]"
+#if SHOPT_BASH
+ "[+onecmd?Equivalent to \b-t\b. Available in bash compatibility "
+ "mode only.]"
+ "[+physical?Equivalent to \b-P\b. Available in bash "
+ "compatibility mode only.]"
+ "[+posix?Turn on POSIX compatibility. Available in bash "
+ "compatibility mode only. Bash in POSIX mode is not the "
+ "same as ksh.]"
+#endif
+ "[+pipefail?A pipeline will not complete until all components "
+ "of the pipeline have completed, and the exit status "
+ "of the pipeline will be the value of the last "
+ "command to exit with non-zero exit status, or will "
+ "be zero if all commands return zero exit status.]"
+ "[+privileged?Equivalent to \b-p\b.]"
+ "[+showme?Simple commands preceded by a \b;\b will be traced "
+ "as if \b-x\b were enabled but not executed.]"
+ "[+trackall?Equivalent to \b-h\b.]"
+ "[+verbose?Equivalent to \b-v\b.]"
+ "[+vi?Enables/disables \bvi\b editing mode.]"
+ "[+viraw?Does not use canonical input mode when using \bvi\b "
+ "edit mode.]"
+ "[+xtrace?Equivalent to \b-x\b.]"
+"}"
+"[p?Privileged mode. Disabling \b-p\b sets the effective user id to the "
+ "real user id, and the effective group id to the real group id. "
+ "Enabling \b-p\b restores the effective user and group ids to their "
+ "values when the shell was invoked. The \b-p\b option is on "
+ "whenever the real and effective user id is not equal or the "
+ "real and effective group id is not equal. User profiles are "
+ "not processed when \b-p\b is enabled.]"
+"[r?restricted. Enables restricted shell. This option cannot be unset once "
+ "enabled.]"
+"[t?Obsolete. The shell reads one command and then exits.]"
+"[u?If enabled, the shell displays an error message when it tries to expand "
+ "a variable that is unset.]"
+"[v?Verbose. The shell displays its input onto standard error as it "
+ "reads it.]"
+"[x?Execution trace. The shell will display each command after all "
+ "expansion and before execution preceded by the expanded value "
+ "of the \bPS4\b parameter.]"
+#if SHOPT_BASH
+ "\fbash1\f"
+#endif
+#if SHOPT_BRACEPAT
+"[B?Enable {...} group expansion. On by default.]"
+#endif
+"[C?Prevents existing regular files from being overwritten using the \b>\b "
+ "redirection operator. The \b>|\b redirection overrides this "
+ "\bnoclobber\b option.]"
+"[G?Causes \b**\b by itself to also match all sub-directories during pathname "
+ "expansion.]"
+#if SHOPT_HISTEXPAND
+ "[H?Enable \b!\b-style history expansion similar to \bcsh\b.]"
+#endif
+;
+
+const char sh_optbreak[] =
+"[-1c?\n@(#)$Id: break (AT&T Research) 1999-04-07 $\n]"
+USAGE_LICENSE
+"[+NAME?break - break out of loop ]"
+"[+DESCRIPTION?\bbreak\b is a shell special built-in that exits the "
+ "smallest enclosing \bfor\b, \bselect\b, \bwhile\b, or \buntil\b loop, "
+ "or the \an\a-th enclosing loop if \an\a is specified. "
+ "Execution continues at the command following the loop(s).]"
+"[+?If \an\a is given, it must be a positive integer >= 1. If \an\a "
+ "is larger than the number of enclosing loops, the last enclosing "
+ "loop will be exited.]"
+"\n"
+"\n[n]\n"
+"\n"
+"[+EXIT STATUS?0]"
+"[+SEE ALSO?\bcontinue\b(1), \breturn\b(1)]"
+;
+
+const char sh_optcont[] =
+"[-1c?\n@(#)$Id: continue (AT&T Research) 1999-04-07 $\n]"
+USAGE_LICENSE
+"[+NAME?continue - continue execution at top of the loop]"
+"[+DESCRIPTION?\bcontinue\b is a shell special built-in that continues "
+ "execution at the top of smallest enclosing enclosing \bfor\b, "
+ "\bselect\b, \bwhile\b, or \buntil\b loop, if any; or the top of "
+ "the \an\a-th enclosing loop if \an\a is specified.]"
+"[+?If \an\a is given, it must be a positive integer >= 1. If \an\a "
+ "is larger than the number of enclosing loops, the last enclosing "
+ " loop will be used.]"
+
+"\n"
+"\n[n]\n"
+"\n"
+"[+SEE ALSO?\bbreak\b(1)]"
+;
+
+const char sh_optalarm[] = "r [varname seconds]";
+const char sh_optalias[] =
+"[-1c?\n@(#)$Id: alias (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?alias - define or display aliases]"
+"[+DESCRIPTION?\balias\b creates or redefines alias definitions "
+ "or writes the existing alias definitions to standard output. "
+ "An alias definitions provides a string value that will replace "
+ "a command name when the command is read. Alias names can "
+ "contain any printable character which is not special to the shell. "
+ "If an alias value ends in a space or tab, then the word "
+ "following the command name the alias replaces is also checked "
+ "to see whether it is an alias.]"
+"[+?If no \aname\as are specified then the names and values of all "
+ "aliases are written to standard output. Otherwise, for "
+ "each \aname\a that is specified, and \b=\b\avalue\a is not "
+ "specified, the current value of the alias corresponding to "
+ "\aname\a is written to standard output. If \b=\b\avalue\a is "
+ "specified, the alias \aname\a will be created or redefined.]"
+"[+?\balias\b is built-in to the shell as a declaration command so that "
+ "field splitting and pathname expansion are not performed on "
+ "the arguments. Tilde expansion occurs on \avalue\a. An alias "
+ "definition only affects scripts read by the current shell "
+ "environment. It does not effect scripts run by this shell.]"
+"[p?Causes the output to be in the form of alias commands that can be used "
+ "as input to the shell to recreate the current aliases.]"
+"[t?Used for tracked aliases. These are aliases that connect a "
+ "command name to the pathname of the command and are reset "
+ "when the \bPATH\b variable is unset. The tracked aliases feature is "
+ "now obsolete.]"
+"[x?Ignored, this option is obsolete.]"
+"\n"
+"\n[name[=value]...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?One or more \aname\a operands did not have an alias "
+ "definition, or an error occurred.]"
+"}"
+
+"[+SEE ALSO?\bsh\b(1), \bunalias\b(1)]"
+;
+
+const char sh_optbuiltin[] =
+"[-1c?\n@(#)$Id: builtin (AT&T Research) 2010-08-04 $\n]"
+USAGE_LICENSE
+"[+NAME?builtin - add, delete, or display shell built-ins]"
+"[+DESCRIPTION?\bbuiltin\b can be used to add, delete, or display "
+ "built-in commands in the current shell environment. A built-in command "
+ "executes in the current shell process and can have side effects in the "
+ "current shell. On most systems, the invocation time for built-in "
+ "commands is one or two orders of magnitude less than commands that "
+ "create a separate process.]"
+"[+?For each \apathname\a specified, the basename of the pathname "
+ "determines the name of the built-in. For each basename, the shell looks "
+ "for a C level function in the current shell whose name is determined by "
+ "prepending \bb_\b to the built-in name. If \apathname\a contains a "
+ "\b/\b, then the built-in is bound to this pathname. A built-in bound to "
+ "a pathname will only be executed if \apathname\a is the first "
+ "executable found during a path search. Otherwise, built-ins are found "
+ "prior to performing the path search.]"
+"[+?If no \apathname\a operands are specified, then \bbuiltin\b displays "
+ "the current list of built-ins, or just the special built-ins if \b-s\b "
+ "is specified, on standard output. The full pathname for built-ins that "
+ "are bound to pathnames are displayed.]"
+"[+?Libraries containing built-ins can be specified with the \b-f\b "
+ "option. If the library contains a function named \blib_init\b(), this "
+ "function will be invoked with argument \b0\b when the library is "
+ "loaded. The \blib_init\b() function can load built-ins by invoking an "
+ "appropriate C level function. In this case there is no restriction on "
+ "the C level function name.]"
+"[+?The C level function will be invoked with three arguments. The first "
+ "two are the same as \bmain\b() and the third one is a pointer.]"
+"[+?\bbuiltin\b cannot be invoked from a restricted shell.]"
+"[d?Deletes each of the specified built-ins. Special built-ins cannot be "
+ "deleted.]"
+"[f]:[lib?On systems with dynamic linking, \alib\a names a shared "
+ "library to load and search for built-ins. Libraries are searched for "
+ "in \b../lib/ksh\b and \b../lib\b on \b$PATH\b and in system dependent "
+ "library directories. The system "
+ "dependent shared library prefix and/or suffix may be omitted. Once a "
+ "library is loaded, its symbols become available for the current and "
+ "subsequent invocations of \bbuiltin\b. Multiple libraries can be "
+ "specified with separate invocations of \bbuiltin\b. Libraries are "
+ "searched in the reverse order in which they are specified.]"
+"[l?List the library base name, plugin YYYYMMDD version stamp, and full "
+ "path for \b-f\b\alib\a on one line on the standard output.]"
+"[s?Display only the special built-ins.]"
+"\n"
+"\n[pathname ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All \apathname\a operands and \b-f\b options processed "
+ "successfully.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bwhence\b(1)]"
+;
+
+const char sh_optcd[] =
+"[-1c?\n@(#)$Id: cd (AT&T Research) 1999-06-05 $\n]"
+USAGE_LICENSE
+"[+NAME?cd - change working directory ]"
+"[+DESCRIPTION?\bcd\b changes the current working directory of the "
+ "current shell environment.]"
+"[+?In the first form with one operand, if \adirectory\a begins with "
+ "\b/\b, or if the first component is \b.\b or \b..\b, the "
+ "directory will be changed to this directory. If directory is \b-\b, "
+ "the directory will be changed to the last directory visited. "
+ "Otherwise, if the \bCDPATH\b environment variable is set, \bcd\b "
+ "searches for \adirectory\a relative to each directory named in "
+ "the colon separated list of directories defined by \bCDPATH\b. "
+ "If \bCDPATH\b not set, \bcd\b changes to the directory specified "
+ "by \adirectory\a.]"
+"[+?In the second form, the first occurrence of the string \aold\a "
+ "contained in the pathname of the present working directory "
+ "is replaced by the string \anew\a and the resulting string "
+ "is used as the directory to which to change.]"
+"[+?When invoked without operands and when the \bHOME\b environment "
+ "variable is set to a nonempty value, the directory named by "
+ "the \bHOME\b environment variable will be used. If \bHOME\b "
+ "is empty or unset, \bcd\b will fail.]"
+"[+?When \bcd\b is successful, the \bPWD\b environment variable will be set "
+ "to the name of an absolute pathname that does not contain any "
+ "\b..\b components corresponding to the new directory. The "
+ "environment variable \bOLDPWD\b will be set to the previous "
+ "value of \bPWD\b. If the new directory is found by searching "
+ "the directories named by \bCDPATH\b, or if \adirectory\a is \b-\b, "
+ "or if the two operand form is used, the new value of \bPWD\b will be "
+ "written to standard output.]"
+"[+?If both \b-L\b and \b-P\b are specified, the last one specified will "
+ "be used. If neither \b-P\b or \b-L\b is specified then the "
+ "behavior will be determined by the \bgetconf\b parameter "
+ "\bPATH_RESOLVE\b. If \bPATH_RESOLVE\b is \bphysical\b, "
+ "then the behavior will be as if \b-P\b were specified. Otherwise, "
+ "the behavior will be as if \b-L\b were specified.]"
+"[L?Handle each pathname component \b..\b in a logical fashion by moving "
+ "up one level by name in the present working directory.]"
+"[P?The present working directory is first converted to an absolute pathname "
+ "that does not contain symbolic link components and symbolic name "
+ "components are expanded in the resulting directory name.]"
+"\n"
+"\n[directory]\n"
+"old new\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Directory successfully changed.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bpwd\b(1), \bgetconf\b(1)]"
+;
+
+const char sh_optcommand[] =
+"[-1c?\n@(#)$Id: command (AT&T Research) 2003-08-01 $\n]"
+USAGE_LICENSE
+"[+NAME?command - execute a simple command]"
+"[+DESCRIPTION?Without \b-v\b or \b-V\b, \bcommand\b executes \acommand\a "
+ "with arguments given by \aarg\a, suppressing the shell function lookup "
+ "that normally occurs. In addition, if \acommand\a is a special "
+ "built-in command, then the special properties are removed so that "
+ "failures will not cause the script that executes it to terminate.]"
+"[+?With the \b-v\b or \b-V\b options, \bcommand\b is equivalent to the "
+ "\bwhence\b(1) command.]"
+"[p?Causes a default path to be searched rather than the one defined by the "
+ "value of \bPATH\b.]"
+"[v?Equivalent to \bwhence\b \acommand\a [\aarg\a ...]].]"
+"[x?If \acommand\a fails because there are too many \aarg\as, it will be "
+ "invoked multiple times with a subset of the arguments on each "
+ "invocation. Arguments that occur prior to the first word that expand "
+ "to multiple arguments and arguments that occur after the last word "
+ "that expands to multiple arguments will be passed on each invocation. "
+ "The exit status will be the maximum invocation exit status.]"
+"[V?Equivalent to \bwhence \b-v\b \acommand\a [\aarg\a ...]].]"
+"\n"
+"\n[command [arg ...]]\n"
+"\n"
+"[+EXIT STATUS?If \acommand\a is invoked, the exit status of \bcommand\b "
+ "will be that of \acommand\a. Otherwise, it will be one of "
+ "the following:]{"
+ "[+0?\bcommand\b completed successfully.]"
+ "[+>0?\b-v\b or \b-V\b has been specified and an error occurred.]"
+ "[+126?\acommand\a was found but could not be invoked.]"
+ "[+127?\acommand\a could not be found.]"
+"}"
+
+"[+SEE ALSO?\bwhence\b(1), \bgetconf\b(1)]"
+;
+
+const char sh_optdot[] =
+"[-1c?@(#)$Id: \b.\b (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?\b.\b - execute commands in the current environment]"
+"[+DESCRIPTION?\b.\b is a special built-in command that executes commands "
+ "from a function or a file in the current environment.]"
+"[+?If \aname\a refers to a function defined with the \bfunction\b \aname\a "
+ "syntax, the function executes in the current environment as "
+ "if it had been defined with the \aname\a\b()\b syntax so that "
+ "there is no scoping. Otherwise, commands from the file defined "
+ "by \aname\a are executed in the current environment. Note that "
+ "the complete script is read before it begins to execute so that "
+ "any aliases defined in this script will not take effect until "
+ "the script completes execution.]"
+"[+?When \aname\a refers to a file, the \bPATH\b variable is searched "
+ "for the file containing commands. In this case execute permission "
+ "is not required for \aname\a.]"
+"[+?If any \aarg\as are specified, these become the positional parameters "
+ "for the duration of the function or script and are restored "
+ "upon completion.]"
+"\n"
+"\n name [arg ...]\n"
+"\n"
+"[+EXIT STATUS?If \aname\a is found, then the exit status is that "
+ "of the last command executed. Otherwise, since this is a special "
+ "built-in, an error will cause a non-interactive shell to exit with "
+ "a non-zero exit status. An interactive shell returns a non-zero exit "
+ "status to indicate an error.]"
+
+"[+SEE ALSO?\bcommand\b(1), \bksh\b(1)]"
+;
+
+#ifndef ECHOPRINT
+ const char sh_optecho[] = " [-n] [arg...]";
+#endif /* !ECHOPRINT */
+
+const char sh_opteval[] =
+"[-1c?\n@(#)$Id: eval (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?eval - create a shell command and process it]"
+"[+DESCRIPTION?\beval\b is a shell special built-in command that constructs "
+ "a command by concatenating the \aarg\as together, separating each "
+ "with a space. The resulting string is then taken as input to "
+ "the shell and evaluated in the current environment. Note that "
+ "command words are expanded twice; once to construct \aarg\a, and "
+ "again when the shell executes the constructed command.]"
+"[+?It is not an error if \aarg\a is not given.]"
+"\n"
+"\n[arg...]\n"
+"\n"
+"[+EXIT STATUS?If \aarg\a is not specified, the exit status is \b0\b. "
+ "Otherwise, it is the exit status of the command defined by the "
+ "\aarg\a operands.]"
+"[+SEE ALSO?\bexec\b(1), \btrap\b(1), \b.\b(1)]"
+;
+
+const char sh_optexec[] =
+"[-1c?\n@(#)$Id: exec (AT&T Research) 1999-07-10 $\n]"
+USAGE_LICENSE
+"[+NAME?exec - execute command, open/close and duplicate file descriptors]"
+"[+DESCRIPTION?\bexec\b is a special built-in command that can be used to "
+ "manipulate file descriptors or to replace the current shell "
+ "with a new command.]"
+"[+?If \acommand\a is specified, then the current shell process will be "
+ "replaced by \acommand\a rather than running \acommand\a and waiting "
+ "for it to complete. Note that there is no need to use "
+ "\bexec\b to enhance performance since the shell implicitly "
+ "uses the exec mechanism internally whenever possible.]"
+"[+?If no operands are specified, \bexec\b can be used to open or "
+ "close files, or to manipulate file descriptors from \b0\b to "
+ "\b9\b in the current shell environment using the standard "
+ "redirection mechanism available with all commands. The "
+ "close-on-exec flags will be set on file descriptor numbers "
+ "greater than \b2\b that are opened this way so that they "
+ "will be closed when another program is invoked.]"
+"[+?Because \bexec\b is a special command, any failure will cause the "
+ "script that invokes it to exit. This can be prevented by "
+ "invoking \bexec\b from the \bcommand\b utility.]"
+"[+?\bexec\b cannot be invoked from a restricted shell to create "
+ "files or to open a file for writing or appending.]"
+"[c?Clear all environment variables before executions except variable "
+ "assignments that are part of the current \bexec\b command.]"
+"[a]:[name?\bargv[0]]\b will be set to \aname\a for \acommand\a]"
+"\n"
+"\n[command [arg ...]]\n"
+"\n"
+"[+EXIT STATUS?If \acommand\a is specified, \bexec\b does not return. "
+ "Otherwise, the exit status is one of the following:]{"
+ "[+0?All I/O redirections were successful.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bcommand\b(1), \beval\b(1)]"
+;
+
+
+const char sh_optexit[] =
+"[-1c?\n@(#)$Id: exit (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?exit - exit the current shell]"
+"[+DESCRIPTION?\bexit\b is shell special built-in that causes the "
+ "shell that invokes it to exit. Before exiting the shell, if the "
+ "\bEXIT\b trap is set it will be invoked.]"
+"[+?If \an\a is given, it will be used to set the exit status.]"
+"\n"
+"\n[n]\n"
+"\n"
+"[+EXIT STATUS?If \an\a is specified, the exit status is the least significant "
+ "eight bits of the value of \an\a. Otherwise, the exit status is the "
+ "exit status of preceding command. When invoked inside a trap, the "
+ "preceding command means the command that invoked the trap.]"
+"[+SEE ALSO?\bbreak\b(1), \breturn\b(1)]"
+;
+
+const char sh_optexport[] =
+"[-1c?\n@(#)$Id: export (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?export - set export attribute on variables]"
+"[+DESCRIPTION?\bexport\b sets the export attribute on each of "
+ "the variables specified by \aname\a which causes them "
+ "to be in the environment of subsequently executed commands. "
+ "If \b=\b\avalue\a is specified, the variable \aname\a is "
+ "set to \avalue\a.]"
+"[+?If no \aname\as are specified then the names and values of all "
+ "exported variables are written to standard output.]"
+"[+?\bexport\b is built-in to the shell as a declaration command so that "
+ "field splitting and pathname expansion are not performed on "
+ "the arguments. Tilde expansion occurs on \avalue\a.]"
+"[p?Causes the output to be in the form of \bexport\b commands that can be "
+ "used as input to the shell to recreate the current exports.]"
+"\n"
+"\n[name[=value]...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\bsh\b(1), \btypeset\b(1)]"
+;
+
+const char sh_optgetopts[] =
+":[-1c?\n@(#)$Id: getopts (AT&T Research) 2005-01-01 $\n]"
+"[-author?Glenn Fowler <gsf@research.att.com>]"
+USAGE_LICENSE
+"[+NAME?\f?\f - parse utility options]"
+"[+DESCRIPTION?The \bgetopts\b utility can be used to retrieve options and "
+ "arguments from a list of arguments given by \aargs\a or the positional "
+ "parameters if \aargs\a is omitted. It can also generate usage messages "
+ "and a man page for the command based on the information in \aoptstring\a.]"
+"[+?Each time it is invoked, the \bgetopts\b utility places the value "
+ "of the next option in the shell variable specified by the \aname\a "
+ "operand and the index of the next argument to be processed in the "
+ "shell variable \bOPTIND\b. When the shell is invoked \bOPTIND\b "
+ "is initialized to \b1\b. When an option requires or permits an option "
+ "argument, \bgetopts\b places the option argument in the shell "
+ "variable \bOPTARG\b. Otherwise \bOPTARG\b is set to \b1\b when the "
+ "option is set and \b0\b when the option is unset.]"
+"[+?The \aoptstring\a string consists of alpha-numeric characters, "
+ "the special characters +, -, ?, :, and <space>, or character groups "
+ "enclosed in [...]]. Character groups may be nested in {...}. "
+ "Outside of a [...]] group, a single new-line followed by zero or "
+ "more blanks is ignored. One or more blank lines separate the "
+ "options from the command argument synopsis.]"
+"[+?Each [...]] group consists of an optional label, "
+ "optional attributes separated by :, and an "
+ "optional description string following ?. The characters from the ? "
+ "to the end of the next ]] are ignored for option parsing and short "
+ "usage messages. They are used for generating verbose help or man pages. "
+ "The : character may not appear in the label. "
+ "The ? character must be specified as ?? in the label and the ]] character "
+ "must be specified as ]]]] in the description string. "
+ "Text between two \\b (backspace) characters indicates "
+ "that the text should be emboldened when displayed. "
+ "Text between two \\a (bell) characters indicates that the text should "
+ "be emphasized or italicized when displayed. "
+ "Text between two \\v (vertical tab) characters indicates "
+ "that the text should displayed in a fixed width font. "
+ "Text between two \\f (formfeed) characters will be replaced by the "
+ "output from the shell function whose name is that of the enclosed text.]"
+"[+?All output from this interface is written to the standard error.]"
+"[+?There are several group types:]{"
+ "[+1.?A group of the form "
+ "[-[\aversion\a]][\aflag\a[\anumber\a]]]]...[?\atext\a]]]] "
+ "appearing as the first group enables the extended interface. \aversion\a "
+ "specifies the interface version, currently \b1\b. The latest version is "
+ "assumed if \aversion\a is omitted. Future enhancements "
+ "may increment \aversion\a, but all versions will be supported. \atext\a "
+ "typically specifies an SCCS or CVS identification string. Zero or more "
+ "\aflags\a with optional \anumber\a values may be specified to control "
+ "option parsing. "
+ "The flags are:]{"
+ "[++?Arguments beginning with + are considered options.]"
+ "[+c?Cache this \aoptstring\a for multiple passes. Used to optimize "
+ "builtins that may be called many times within the same process.]"
+ "[+i?Ignore this \aoptstring\a when generating help. Used when "
+ "combining \aoptstring\a values from multiple passes.]"
+ "[+l?Display only \alongname\a options in help messages.]"
+ "[+n?Associate -\anumber\a and +\anumber\a options with the first "
+ "option with numeric arguments.]"
+ "[+o?The \b-\b option character prefix is optional (supports "
+ "obsolete \bps\b(1) option syntax.)]"
+ "[+p?\anumber\a specifies the number of \b-\b characters that must "
+ "prefix long option names. The default is \b2\b; \b0\b, \b1\b or "
+ "\b2\b are accepted (e.g., \bp0\b for \bdd\b(1) and \bp1\b for "
+ "\bfind\b(1).)]"
+ "[+s?\anumber\a specifies the \b--??man\b section number, "
+ "\b1\b by default.]"
+ "}"
+ "[+2.?An option specification of the form "
+ "[\aoption\a[!]][=\anumber\a]][:\alongname\a]][?\atext\a]]]]. In this "
+ "case the first field is the option character; this is the value returned "
+ "in the \aname\a operand when the option is matched. If there is no "
+ "option character then a two or more digit number should be specified. "
+ "This number will be returned as the value of the \aname\a operand if the "
+ "long option is matched. If \aoption\a is followed by \b!\b then the option "
+ "character sense is the inverse of the longname sense. For options that do "
+ "not take values \bOPTARG\b will be set to \b0\b for \b!\b inverted option "
+ "characters and \b1\b otherwise. =\anumber\a optionally specifies a number to "
+ "be returned in the \aname\a operand instead of the option character. A "
+ "longname is specified by \b--\b\alongname\a and is matched by the shortest "
+ "non-ambiguous prefix of all long options. * in the \alongname\a field "
+ "indicates that only characters up to that point need to match, provided "
+ "any additional characters match exactly. The enclosing [ and ]] can be "
+ "omitted for an option that does not have a longname or descriptive text.]"
+ "[+3.?An option argument specification. "
+ "Options that take arguments can be followed by : (string value) or # "
+ "(numeric value) and an option argument specification. An option argument "
+ "specification consists of the option argument name as field 1. "
+ "The remaining \b:\b separated fields are a type name and zero or more of "
+ "the special attribute words \blistof\b, \boneof\b, and \bignorecase\b. "
+ "A default option value may be specified in the final field as "
+ "\b:=\b\adefault\a. The option argument specification may be followed "
+ "by a list of option value descriptions enclosed in braces. "
+ "A long option that takes an argument is specified as "
+ "\b--\b\alongname\a=\avalue\a. If the : or # is followed by ? then the "
+ "option argument is optional. If only the option character form is "
+ "specified then the optional argument value is not set if the next "
+ "argument starts with - or +. The special attributes are currently "
+ "informational with respect to \boptget\b(3), but may be useful to "
+ "applications that parse \b--api\b output. The special attributes are:]{"
+ "[+listof?zero or more of the possible option values may be specified, "
+ "separated by \b,\b or space.]"
+ "[+oneof?exactly one of the possible option values must be specified]"
+ "[+ignorecase?case ignored in matching the long option name]"
+ "}"
+ "[+4.?A option value description.]"
+ "[+5.?A argument specification. A list of valid option argument values "
+ "can be specified by enclosing them inside a {...} following "
+ "the option argument specification. Each of the permitted "
+ "values can be specified with a [...]] containing the "
+ "value followed by a description.]"
+ "[+6.?A group of the form [+\\n...]] will display the characters "
+ "representing ... in fixed with font without adding line breaks.]"
+ "[+7.?A group of the form [+\aname\a?\atext\a]] specifies a section "
+ "\aname\a with descriptive \atext\a. If \aname\a is omitted then "
+ "\atext\a is placed in a new paragraph.]"
+ "[+8.?A group of the form [-\aname\a?\atext\a]] specifies entries "
+ "for the \bIMPLEMENTATION\b section.]"
+"}"
+"[+?A leading : character in \aoptstring\a "
+ "affects the way errors are handled. If an option character or longname "
+ "argument not specified in \aoptstring\a is encountered when processing "
+ "options, the shell variable whose name is \aname\a will be set to the ? "
+ "character. The shell variable \bOPTARG\b will be set to "
+ "the character found. If an option argument is missing or has an invalid "
+ "value, then \aname\a will be set to the : character and the shell variable "
+ "\bOPTARG\b will be set to the option character found. "
+ "Without the leading :, \aname\a will be set to the ? character, \bOPTARG\b "
+ "will be unset, and an error message will be written to standard error "
+ "when errors are encountered.]"
+"[+?A leading + character or a + following a leading : in \aoptstring\a "
+ "specifies that arguments beginning with + will also be considered options.]"
+"[+?The end of options occurs when:]{"
+ "[+1.?The special argument \b--\b is encountered.]"
+ "[+2.?An argument that does not begin with a \b-\b is encountered.]"
+ "[+3.?A help argument is specified.]"
+ "[+4.?An error is encountered.]"
+"}"
+"[+?If \bOPTIND\b is set to the value \b1\b, a new set of arguments "
+ "can be used.]"
+"[+?\bgetopts\b can also be used to generate help messages containing command "
+ "usage and detailed descriptions. Specify \aargs\a as:]"
+"{ "
+ "[+-???To generate a usage synopsis.]"
+ "[+--?????To generate a verbose usage message.]"
+ "[+--????man?To generate a formatted man page.]"
+ "[+--????api?To generate an easy to parse usage message.]"
+ "[+--????html?To generate a man page in \bhtml\b format.]"
+ "[+--????nroff?To generate a man page in \bnroff\b format.]"
+ "[+--????usage?List the current \aoptstring\a.]"
+ "[+--??????\aname\a?List \bversion=\b\an\a, \an\a>0, "
+ "if the option \aname\a is recognized by \bgetopts\b.]"
+"}"
+"[+?When the end of options is encountered, \bgetopts\b exits with a "
+ "non-zero return value and the variable \bOPTIND\b is set to the "
+ "index of the first non-option argument.]"
+"[+?The obsolete long option forms \aflag\a(\along-name\a) and "
+ "\aflag\a:(\along-name\a) for options that take arguments is supported "
+ "for backwards compatibility.]"
+"a:[name?Use \aname\a instead of the command name in usage messages.]"
+"\n"
+"\nopstring name [args...]\n"
+"\n"
+"[+EXIT STATUS]{"
+ "[+0?An option specified was found.]"
+ "[+1?An end of options was encountered.]"
+ "[+2?A usage or information message was generated.]"
+"}"
+;
+
+const char sh_optbg[] =
+"[-1c?@(#)$Id: bg (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?bg - resume jobs in the background]"
+"[+DESCRIPTION?\bbg\b places the given \ajob\as into the background "
+ "and sends them a \bCONT\b signal to start them running.]"
+"[+?If \ajob\a is omitted, the most recently started or stopped "
+ "background job is resumed or continued in the background.]"
+_JOB_
+"\n"
+"\n[job ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?If all background jobs are started.]"
+ "[+>0?If one more jobs does not exist or there are no background "
+ "jobs.]"
+"}"
+
+"[+SEE ALSO?\bwait\b(1), \bfg\b(1), \bdisown\b(1), \bjobs\b(1)]"
+;
+
+const char sh_optfg[] =
+"[-1c?@(#)$Id: fg (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?fg - move jobs to the foreground]"
+"[+DESCRIPTION?\bfg\b places the given \ajob\as into the foreground "
+ "in sequence and sends them a \bCONT\b signal to start each running.]"
+"[+?If \ajob\a is omitted, the most recently started or stopped "
+ "background job is moved to the foreground.]"
+_JOB_
+"\n"
+"\n[job ...]\n"
+"\n"
+"[+EXIT STATUS?If \bfg\b brings one or more jobs into the foreground, "
+ "the exit status of \bfg\b will be that of the last \ajob\a. "
+ "If one or more jobs does not exist or has completed, \bfg\b will "
+ "return a non-zero exit status.]"
+"}"
+
+"[+SEE ALSO?\bwait\b(1), \bbg\b(1), \bjobs\b(1)]"
+;
+
+const char sh_optdisown[] =
+"[-1c?@(#)$Id: disown (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?disown - disassociate a job with the current shell]"
+"[+DESCRIPTION?\bdisown\b prevents the current shell from sending "
+ "a \bHUP\b signal to each of the given \ajob\as when "
+ "the current shell terminates a login session.]"
+"[+?If \ajob\a is omitted, the most recently started or stopped "
+ "background job is used.]"
+_JOB_
+"\n"
+"\n[job ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?If all jobs are successfully disowned.]"
+ "[+>0?If one more \ajob\as does not exist.]"
+"}"
+
+"[+SEE ALSO?\bwait\b(1), \bbg\b(1), \bjobs\b(1)]"
+;
+
+const char sh_optjobs[] =
+"[-1c?@(#)$Id: jobs (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?jobs - display status of jobs]"
+"[+DESCRIPTION?\bjobs\b displays information about specified \ajob\as "
+ "that were started by the current shell environment on standard "
+ "output. The information contains the job number enclosed in "
+ "[...]], the status, and the command line that started the job.]"
+"[+?If \ajob\a is omitted, \bjobs\b displays the status of all stopped jobs, "
+ "background jobs, and all jobs whose status has changed since last "
+ "reported by the shell.]"
+"[+?When \bjobs\b reports the termination status of a job, the "
+ "shell removes the jobs from the list of known jobs in "
+ "the current shell environment.]"
+_JOB_
+"[l?\bjobs\b displays process id's after the job number in addition "
+ "to the usual information]"
+"[n?Only the jobs whose status has changed since the last prompt "
+ "is displayed.]"
+"[p?The process group leader id's for the specified jobs are displayed.]"
+"\n"
+"\n[job ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?The information for each job is written to standard output.]"
+ "[+>0?One or more jobs does not exist.]"
+"}"
+
+"[+SEE ALSO?\bwait\b(1), \bps\b(1), \bfg\b(1), \bbg\b(1)]"
+;
+
+const char sh_opthist[] =
+"[-1cn?@(#)$Id: hist (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?\f?\f - process command history list]"
+"[+DESCRIPTION?\b\f?\f\b lists, edits, or re-executes, commands "
+ "previously entered into the current shell environment.]"
+"[+?The command history list references commands by number. The first number "
+ "in the list is selected arbitrarily. The relationship of a number "
+ "to its command does not change during a login session. When the "
+ "number reaches 32767 the number wraps around to 1 but "
+ "maintains the ordering.]"
+"[+?When commands are edited (when the \b-l\b option is not specified), the "
+ "resulting lines will be entered at the end of the history list and "
+ "then reexecuted by the current shell. The \b\f?\f\b command that "
+ "caused the editing will not be entered into the history list. If the "
+ "editor returns a non-zero exit status, this will suppress the "
+ "entry into the history list and the command reexecution. Command "
+ "line variable assignments and redirections affect both the \f?\f "
+ "command and the commands that are reexecuted.]"
+"[+?\afirst\a and \alast\a define the range of commands. \afirst\a and "
+ "\alast\a can be one of the following:]{"
+ "[+\anumber\a?A positive number representing a command "
+ "number. A \b+\b sign can precede \anumber\a.]"
+ "[+-\anumber\a?A negative number representing a command "
+ "that was executed \anumber\a commands previously. "
+ "For example, \b-1\b is the previous command.]"
+ "[+\astring\a?\astring\a indicates the most recently "
+ "entered command that begins with \astring\a. "
+ "\astring\a should not contain an \b=\b.]"
+ "}"
+"[+?If \afirst\a is omitted, the previous command is used, unless \b-l\b "
+ "is specified, in which case it will default to \b-16\b and \alast\a "
+ "will default to \b-1\b.]"
+"[+?If \afirst\a is specified and \alast\a is omitted, then \alast\a will "
+ "default to \afirst\a unless \b-l\b is specified in which case "
+ "it will default to \b-1\b.]"
+"[+?If no editor is specified, then the editor specfied by the \bHISTEDIT\b "
+ "variable will be used if set, or the \bFCEDIT\b variable will be "
+ "used if set, otherwise, \bed\b will be used.]"
+"[e]:[editor?\aeditor\a specifies the editor to use to edit the history "
+ "command. A value of \b-\b for \aeditor\a is equivalent to "
+ "specifiying the \b-s\b option.]"
+"[l?List the commands rather than editing and reexecuting them.]"
+"[N]#[num?Start at \anum\a commands back.]"
+"[n?Suppress the command numbers when the commands are listed.]"
+#if SHOPT_HISTEXPAND
+"[p?Writes the result of history expansion for each operand to standard "
+ "output. All other options are ignored.]"
+#endif
+"[r?Reverse the order of the commands.]"
+"[s?Reexecute the command without invoking an editor. In this case "
+ "an operand of the form \aold\a\b=\b\anew\a can be specified "
+ "to change the first occurrence of the string \aold\a in the "
+ "command to \anew\a before reexecuting the command.]"
+
+"\n"
+"\n[first [last] ]\n"
+"\n"
+"[+EXIT STATUS?If a command is reexecuted, the exit status is that of "
+ "the command that gets reexecuted. Otherwise, it is one of the "
+ "following:]{"
+ "[+0?Successfully completion of the listing.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\bksh\b(1), \bsh\b(1), \bed\b(1)]"
+;
+
+const char sh_optkill[] =
+"[-1c?\n@(#)$Id: kill (AT&T Research) 1999-06-17 $\n]"
+USAGE_LICENSE
+"[+NAME?kill - terminate or signal process]"
+"[+DESCRIPTION?With the first form in which \b-l\b is not specified, "
+ "\bkill\b sends a signal to one or more processes specified by "
+ "\ajob\a. This normally terminates the processes unless the signal "
+ "is being caught or ignored.]"
+_JOB_
+"[+?If the signal is not specified with either the \b-n\b or the \b-s\b "
+ "option, the \bSIGTERM\b signal is used.]"
+"[+?If \b-l\b is specified, and no \aarg\a is specified, then \bkill\b "
+ "writes the list of signals to standard output. Otherwise, \aarg\a "
+ "can be either a signal name, or a number representing either a "
+ "signal number or exit status for a process that was terminated "
+ "due to a signal. If a name is given the corresponding signal "
+ "number will be written to standard output. If a number is given "
+ "the corresponding signal name will be written to standard output.]"
+"[l?List signal names or signal numbers rather than sending signals as "
+ "described above. "
+ "The \b-n\b and \b-s\b options cannot be specified.]"
+"[n]#[signum?Specify a signal number to send. Signal numbers are not "
+ "portable across platforms, except for the following:]{"
+ "[+0?No signal]"
+ "[+1?\bHUP\b]"
+ "[+2?\bINT\b]"
+ "[+3?\bQUIT\b]"
+ "[+6?\bABRT\b]"
+ "[+9?\bKILL\b]"
+ "[+14?\bALRM\b]"
+ "[+15?\bTERM\b]"
+ "}"
+"[s]:[signame?Specify a signal name to send. The signal names are derived "
+ "from their names in \b<signal.h>\b without the \bSIG\b prefix and "
+ "are case insensitive. \bkill -l\b will generate the list of "
+ "signals on the current platform.]"
+"\n"
+"\njob ...\n"
+" -l [arg ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?At least one matching process was found for each \ajob\a "
+ "operand, and the specified signal was successfully sent to at "
+ "least one matching process.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bps\b(1), \bjobs\b(1), \bkill\b(2), \bsignal\b(2)]"
+;
+
+const char sh_optlet[] =
+"[-1c?@(#)$Id: let (AT&T Research) 2000-04-02 $\n]"
+USAGE_LICENSE
+"[+NAME?let - evaluate arithmetic expressions]"
+"[+DESCRIPTION?\blet\b evaluates each \aexpr\a in the current "
+ "shell environment as an arithmetic expression using ANSI C "
+ "syntax. Variables names are shell variables and they "
+ "are recursively evaluated as arithmetic expressions to "
+ "get numerical values.]"
+"[+?\blet\b has been made obsolete by the \b((\b...\b))\b syntax "
+ "of \bksh\b(1) which does not require quoting of the operators "
+ "to pass them as command arguments.]"
+"\n"
+"\n[expr ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?The last \aexpr\a evaluates to a non-zero value.]"
+ "[+>0?The last \aexpr\a evaluates to \b0\b or an error occurred.]"
+"}"
+
+"[+SEE ALSO?\bexpr\b(1), \btest\b(1), \bksh\b(1)]"
+;
+
+const char sh_optprint[] =
+"[-1c?\n@(#)$Id: print (AT&T Research) 2008-11-26 $\n]"
+USAGE_LICENSE
+"[+NAME?print - write arguments to standard output]"
+"[+DESCRIPTION?By default, \bprint\b writes each \astring\a operand to "
+ "standard output and appends a newline character.]"
+"[+?Unless, the \b-r\b or \b-f\b option is specified, each \b\\\b "
+ "character in each \astring\a operand is processed specially as "
+ "follows:]{"
+ "[+\\a?Alert character.]"
+ "[+\\b?Backspace character.]"
+ "[+\\c?Terminate output without appending newline. The "
+ "remaining \astring\a operands are ignored.]"
+ "[+\\f?Formfeed character.]"
+ "[+\\n?Newline character.]"
+ "[+\\t?Tab character.]"
+ "[+\\v?Vertical tab character.]"
+ "[+\\\\?Backslash character.]"
+ "[+\\E?Escape character (ASCII octal 033).]"
+ "[+\\0\ax\a?The 8-bit character whose ASCII code is the "
+ "1-, 2-, or 3-digit octal number \ax\a.]"
+ "}"
+"[+?If both \b-e\b and \b-r\b are specified, the last one specified is "
+ "the one that is used.]"
+"[+?When the \b-f\b option is specified and there are more \astring\a "
+ "operands than format specifiers, the format string is "
+ "reprocessed from the beginning. If there are fewer \astring\a "
+ "operands than format specifiers, then outputting will end "
+ "at the first unneeded format specifier.]"
+"[e?Unless \b-f\b is specified, process \b\\\b sequences in each \astring\a "
+ "operand as described above. This is the default behavior.]"
+"[n?Do not append a new-line character to the output.]"
+"[f]:[format?Write the \astring\a arguments using the format string "
+ "\aformat\a and do not append a new-line. See \bprintf\b for "
+ "details on how to specify \aformat\a.]"
+"[p?Write to the current co-process instead of standard output.]"
+"[r?Do not process \b\\\b sequences in each \astring\a operand as described "
+ "above.]"
+"[s?Write the output as an entry in the shell history file instead of "
+ "standard output.]"
+"[u]:[fd:=1?Write to file descriptor number \afd\a instead of standard output.]"
+"[v?Treat each \astring\a as a variable name and write the value in \b%B\b "
+ "format. Cannot be used with \b-f\b.]"
+"[C?Treat each \astring\a as a variable name and write the value in \b%#B\b "
+ "format. Cannot be used with \b-f\b.]"
+"\n"
+"\n[string ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\becho\b(1), \bprintf\b(1), \bread\b(1)]"
+;
+
+const char sh_optprintf[] =
+"[-1c?\n@(#)$Id: printf (AT&T Research) 2009-02-02 $\n]"
+USAGE_LICENSE
+"[+NAME?printf - write formatted output]"
+"[+DESCRIPTION?\bprintf\b writes each \astring\a operand to "
+ "standard output using \aformat\a to control the output format.]"
+"[+?The \aformat\a operands supports the full range of ANSI C formatting "
+ "specifiers plus the following additional specifiers:]{"
+ "[+%b?Each character in the \astring\a operand is processed "
+ "specially as follows:]{"
+ "[+\\a?Alert character.]"
+ "[+\\b?Backspace character.]"
+ "[+\\c?Terminate output without appending newline. "
+ "The remaining \astring\a operands are ignored.]"
+ "[+\\f?Formfeed character.]"
+ "[+\\n?Newline character.]"
+ "[+\\t?Tab character.]"
+ "[+\\v?Vertical tab character.]"
+ "[+\\\\?Backslash character.]"
+ "[+\\E?Escape character (ASCII octal 033).]"
+ "[+\\0\ax\a?The 8-bit character whose ASCII code is "
+ "the 1-, 2-, or 3-digit octal number \ax\a.]"
+ "}"
+ "[+%q?Output \astring\a quoted in a manner that it can be read in "
+ "by the shell to get back the same string. However, empty "
+ "strings resulting from missing \astring\a operands will "
+ "not be quoted.]"
+ "[+%B?Treat the argument as a variable name and output the value "
+ "without converting it to a string. This is most useful for "
+ "variables of type \b-b\b.]"
+ "[+%H?Output \astring\a with characters \b<\b, \b&\b, \b>\b, "
+ "\b\"\b, and non-printable characters properly escaped for "
+ "use in HTML and XML documents. The alternate flag \b#\b "
+ "formats the output for use as a URI.]"
+ "[+%P?Treat \astring\a as an extended regular expression and "
+ "convert it to a shell pattern.]"
+ "[+%R?Treat \astring\a as an shell pattern expression and "
+ "convert it to an extended regular expression.]"
+ "[+%T?Treat \astring\a as a date/time string and format it. The "
+ "\bT\b can be preceded by \b(\b\adformat\a\b)\b, where "
+ "\adformat\a is a date format as defined by the \bdate\b "
+ "command.]"
+ "[+%Z?Output a byte whose value is \b0\b.]"
+"}"
+"[+?The format modifier flag \bL\b can precede the width and/or precision "
+ "specifiers for the \bc\b and \bs\b to cause the width and/or "
+ "precision to be measured in character width rather than byte count.]"
+"[+?When performing conversions of \astring\a to satisfy a numeric "
+ "format specifier, if the first character of \astring\a "
+ "is \b\"\b or \b'\b, then the value will be the numeric value "
+ "in the underlying code set of the character following the "
+ "\b\"\b or \b'\b. Otherwise, \astring\a is treated like a shell "
+ "arithmetic expression and evaluated.]"
+"[+?If a \astring\a operand cannot be completely converted into a value "
+ "appropriate for that format specifier, an error will occur, "
+ "but remaining \astring\a operands will continue to be processed.]"
+"[+?In addition to the format specifier extensions, the following "
+ "extensions of ANSI-C are permitted in format specifiers:]{"
+ "[+-?The escape sequences \b\\E\b and \b\\e\b expand to the escape "
+ "character which is octal \b033\b in ASCII.]"
+ "[+-?The escape sequence \b\\c\b\ax\a expands to Control-\ax\a.]"
+ "[+-?The escape sequence \b\\C[.\b\aname\a\b.]]\b expands to "
+ "the collating element \aname\a.]"
+ "[+-?The escape sequence \b\\x{\b\ahex\a\b}\b expands to the "
+ "character corresponding to the hexidecimal value \ahex\a.]"
+ "[+-?The format modifier flag \b=\b can be used to center a field to "
+ "a specified width.]"
+ "[+-?The format modifier flag \bL\b can be used with the \bc\b and "
+ "\bs\b formats to treat precision as character width instead "
+ "of byte count.]"
+ "[+-?The format modifier flag \b,\b can be used with \bd\b and \bf\f "
+ "formats to cause group of digits.]"
+ "[+-?Each of the integral format specifiers can have a third "
+ "modifier after width and precision that specifies the "
+ "base of the conversion from 2 to 64. In this case the "
+ "\b#\b modifier will cause \abase\a\b#\b to be prepended to "
+ "the value.]"
+ "[+-?The \b#\b modifier can be used with the \bd\b specifier when "
+ "no base is specified cause the output to be written in units "
+ "of \b1000\b with a suffix of one of \bk M G T P E\b.]"
+ "[+-?The \b#\b modifier can be used with the \bi\b specifier to "
+ "cause the output to be written in units of \b1024\b with "
+ "a suffix of one of \bKi Mi Gi Ti Pi Ei\b.]"
+ "}"
+"[+?If there are more \astring\a operands than format specifiers, the "
+ "\aformat\a string is reprocessed from the beginning. If there are "
+ "fewer \astring\a operands than format specifiers, then string "
+ "specifiers will be treated as if empty strings were supplied, "
+ "numeric conversions will be treated as if 0 were supplied, and "
+ "time conversions will be treated as if \bnow\b were supplied.]"
+"[+?\bprintf\b is equivalent to \bprint -f\b which allows additional "
+ "options to be specified.]"
+"\n"
+"\nformat [string ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bdate\b(1), \bprint\b(1), \bread\b(1)]"
+;
+
+const char sh_optpwd[] =
+"[-1c?\n@(#)$Id: pwd (AT&T Research) 1999-06-07 $\n]"
+USAGE_LICENSE
+"[+NAME?pwd - write working directory name]"
+"[+DESCRIPTION?\bpwd\b writes an absolute pathname of the current working "
+ "directory to standard output. An absolute pathname is a "
+ "pathname that begins with \b/\b that does not contains any "
+ "\b.\b or \b..\b components.]"
+"[+?If both \b-L\b and \b-P\b are specified, the last one specified will "
+ "be used. If neither \b-P\b or \b-L\b is specified then the "
+ "behavior will be determined by the \bgetconf\b parameter "
+ "\bPATH_RESOLVE\b. If \bPATH_RESOLVE\b is \bphysical\b, "
+ "then the behavior will be as if \b-P\b were specified. Otherwise, "
+ "the behavior will be as if \b-L\b were specified.]"
+"[L?The absolute pathname may contains symbolic link components. This is "
+ "the default.]"
+"[P?The absolute pathname will not contain any symbolic link components.]"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bcd\b(1), \bgetconf\b(1)]"
+;
+
+const char sh_optread[] =
+"[-1c?\n@(#)$Id: read (AT&T Research) 2006-12-19 $\n]"
+USAGE_LICENSE
+"[+NAME?read - read a line from standard input]"
+"[+DESCRIPTION?\bread\b reads a line from standard input and breaks it "
+ "into fields using the characters in value of the \bIFS\b variable "
+ "as separators. The escape character, \b\\\b, is used to remove "
+ "any special meaning for the next character and for line continuation "
+ "unless the \b-r\b option is specified.]"
+"[+?If there are more variables than fields, the remaining variables are "
+ "set to empty strings. If there are fewer variables than fields, "
+ "the leftover fields and their intervening separators are assigned "
+ "to the last variable. If no \avar\a is specified then the variable "
+ "\bREPLY\b is used.]"
+"[+?When \avar\a has the binary attribute and \b-n\b or \b-N\b is specified, "
+ "the bytes that are read are stored directly into \bvar\b.]"
+"[+?If you specify \b?\b\aprompt\a after the first \avar\a, then \bread\b "
+ "will display \aprompt\a on standard error when standard input "
+ "is a terminal or pipe.]"
+"[+?If an end of file is encountered while reading a line the data is "
+ "read and processed but \bread\b returns with a non-zero exit status.]"
+"[A?Unset \avar\a and then create an indexed array containing each field in "
+ "the line starting at index 0.]"
+"[C?Unset \avar\a and read \avar\a as a compound variable.]"
+"[d]:[delim?Read until delimiter \adelim\a instead of to the end of line.]"
+"[p?Read from the current co-process instead of standard input. An end of "
+ "file causes \bread\b to disconnect the co-process so that another "
+ "can be created.]"
+"[r?Do not treat \b\\\b specially when processing the input line.]"
+"[s?Save a copy of the input as an entry in the shell history file.]"
+"[S?Treat the input as if it was saved from a spreasheet in csv format.]"
+"[u]#[fd:=0?Read from file descriptor number \afd\a instead of standard input.]"
+"[t]:[timeout?Specify a timeout \atimeout\a in seconds when reading from "
+ "a terminal or pipe.]"
+"[n]#[count?Read at most \acount\a characters. For binary fields \acount\a "
+ "is the number of bytes.]"
+"[N]#[count?Read exactly \ancount\a characters. For binary fields \acount\a "
+ "is the number of bytes.]"
+"[v?When reading from a terminal the value of the first variable is displayed "
+ "and used as a default value.]"
+"\n"
+"\n[var?prompt] [var ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0? Successful completion.]"
+ "[+>0?End of file was detected or an error occurred.]"
+"}"
+"[+SEE ALSO?\bprint\b(1), \bprintf\b(1), \bcat\b(1)]"
+;
+
+const char sh_optreadonly[] =
+"[-1c?\n@(#)$Id: readonly (AT&T Research) 2008-06-16 $\n]"
+USAGE_LICENSE
+"[+NAME?readonly - set readonly attribute on variables]"
+"[+DESCRIPTION?\breadonly\b sets the readonly attribute on each of "
+ "the variables specified by \aname\a which prevents their "
+ "values from being changed. If \b=\b\avalue\a is specified, "
+ "the variable \aname\a is set to \avalue\a before the variable "
+ "is made readonly.]"
+"[+?Within a type definition, if the value is not specified, then a "
+ "value must be specified when creating each instance of the type "
+ "and the value is readonly for each instance.]"
+"[+?If no \aname\as are specified then the names and values of all "
+ "readonly variables are written to standard output.]"
+"[+?\breadonly\b is built-in to the shell as a declaration command so that "
+ "field splitting and pathname expansion are not performed on "
+ "the arguments. Tilde expansion occurs on \avalue\a.]"
+"[p?Causes the output to be in a form of \breadonly\b commands that can be "
+ "used as input to the shell to recreate the current set of "
+ "readonly variables.]"
+"\n"
+"\n[name[=value]...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\bsh\b(1), \btypeset\b(1)]"
+;
+
+const char sh_optreturn[] =
+"[-1c?\n@(#)$Id: return (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?return - return from a function or dot script ]"
+"[+DESCRIPTION?\breturn\b is a shell special built-in that causes the "
+ "function or dot script that invokes it to exit. "
+ "If \breturn\b is invoked outside of a function or dot script "
+ "it is equivalent to \bexit\b.]"
+"[+?If \breturn\b is invoked inside a function defined with the \bfunction\b "
+ "reserved word syntax, then any \bEXIT\b trap set within the "
+ "then function will be invoked in the context of the caller "
+ "before the function returns.]"
+"[+?If \an\a is given, it will be used to set the exit status.]"
+"\n"
+"\n[n]\n"
+"\n"
+"[+EXIT STATUS?If \an\a is specified, the exit status is the least significant "
+ "eight bits of the value of \an\a. Otherwise, the exit status is the "
+ "exit status of preceding command.]"
+"[+SEE ALSO?\bbreak\b(1), \bexit\b(1)]"
+;
+
+
+const char sh_optksh[] =
+"+[-1?\n@(#)$Id: sh (AT&T Research) "SH_RELEASE" $\n]"
+USAGE_LICENSE
+"[+NAME?\b\f?\f\b - Shell, the standard command language interpreter]"
+"[+DESCRIPTION?\b\f?\f\b is a command language interpreter that "
+ "executes commands read from a command line string, the "
+ "standard input, or a specified file.]"
+"[+?If the \b-i\b option is present, or there are no \aarg\as and "
+ "the standard input and standard error are attached to a "
+ "terminal, the shell is considered to be interactive.]"
+"[+?The \b-s\b and \b-c\b options are mutually exclusive. If the \b-c\b "
+ "option is specified, the first \aarg\a is the command-line string "
+ "and must be specified. Any remaining \aarg\as will be used "
+ "to initialize \b$0\b and positional parameters.]"
+"[+?If the neither \b-s\b nor \b-c\b is specified, then the first \barg\b "
+ "will be the pathname of the file containing commands and \b$0\b "
+ "will be set to this value. If there is no file with this pathname, "
+ "and this pathame does not contain a \b/\b, then the \bPATH\b "
+ "will be searched for an executable with this name. Any remaining "
+ "\aarg\as will be used to initialize the positional parmaeters.]"
+"[+?Any option can use a \b+\b instead of a \b-\b to disable the corresponding "
+ "option.]"
+"[c?Read the commands from the first \aarg\a.]"
+"[i?Specifies that the shell is interactive.]"
+"[l?Invoke the shell as a login shell; \b/etc/profile\b and \b$HOME/.profile\b, "
+ "if they exist, are read before the first command.]"
+"[r\f:restricted\f?Invoke the shell in a restricted mode. A restricted "
+ "shell does not permit any of the following:]{"
+ "[+-?Changing the working directory.]"
+ "[+-?Setting values or attributes of the variables \bSHELL\b, "
+ "\bENV\b, \bFPATH\b, or \bPATH\b.]"
+ "[+-?Executing any command whose name as a \b/\b in it.]"
+ "[+-?Redirecting output of a command with \b>\b, \b>|\b, "
+ "\b<>\b, or \b>>\b.]"
+ "[+-?Adding or deleting built-in commands or libraries with "
+ "\bbuiltin\b.]"
+ "[+-?Executing \bcommand -p\b \a...\a .]"
+ "}"
+"[s?Read the commands from standard input. The positional parameters will be "
+ "initialized from \aarg\a.]"
+"[D\f:dump-strings\f?Do not execute the script, but output the set of double "
+ "quoted strings preceded by a \b$\b. These strings are needed for "
+ "localization of the script to different locales.]"
+"[E?Reads the file "
+#if SHOPT_SYSRC
+ "\b/etc/ksh.kshrc\b, if it exists, as a profile, followed by "
+#endif
+ "\b${ENV-$HOME/.kshrc}\b, if it exists, as a profile. "
+ "On by default for interactive shells; use \b+E\b to disable.]"
+#if SHOPT_PFSH
+"[P?Invoke the shell as a profile shell. See \bpfexec\b(1).]"
+#endif
+#if SHOPT_KIA
+"[R]:[file?Do not execute the script, but create a cross reference database "
+ "in \afile\a that can be used a separate shell script browser. The "
+ "-R option requires a script to be specified as the first operand.]"
+#endif /* SHOPT_KIA */
+#if SHOPT_REGRESS
+"[I:regress]:[intercept?Enable the regression test \aintercept\a. Must be "
+ "the first command line option(s).]"
+#endif
+#if SHOPT_BASH
+ "\fbash2\f"
+#endif
+"\fabc\f"
+"?"
+"[T?Enable implementation specific test code defined by mask.]#[mask]"
+"\n"
+"\n[arg ...]\n"
+"\n"
+"[+EXIT STATUS?If \b\f?\f\b executes command, the exit status will be that "
+ "of the last command executed. Otherwise, it will be one of "
+ "the following:]{"
+ "[+0?The script or command line to be executed consists entirely "
+ "of zero or more blank lines or comments.]"
+ "[+>1-125?A noninteractive shell detected a syntax error, a variable "
+ "assignment error, or an error in a special built-in.]"
+ "[+126?\b-c\b and \b-s\b were not specified and the command script "
+ "was found on \bPATH\b but was not executable.]"
+ "[+127?\b-c\b and \b-s\b were not specified and the command script "
+ "corresponding to \aarg\a could not be found.]"
+"}"
+
+"[+SEE ALSO?\bset\b(1), \bbuiltin\b(1)]"
+;
+const char sh_optset[] =
+"+[-1c?\n@(#)$Id: set (AT&T Research) 1999-09-28 $\n]"
+USAGE_LICENSE
+"[+NAME?set - set/unset options and positional parameters]"
+"[+DESCRIPTION?\bset\b sets or unsets options and positional parameters. "
+ "Options that are specified with a \b-\b cause the options to "
+ "be set. Options that are specified with a \b+\b cause the "
+ "option to be unset.]"
+"[+?\bset\b without any options or arguments displays the names and "
+ "values of all shell variables in the order of the collation "
+ "sequence in the current locale. The values are quoted so that "
+ "they are suitable for reinput to the shell.]"
+"[+?If no \aarg\as are specified, not even the end of options argument \b--\b, "
+ "the positional parameters are unchanged. Otherwise, unless "
+ "the \b-A\b options has been specified, the positional parameters "
+ "are replaced by the list of \aarg\as. A first \aarg\a of "
+ "\b--\b is ignored when setting positional parameters.]"
+"[+?For backward compatibility, a \bset\b command without any options "
+ "specified whose first \aarg\a is \b-\b will turn off "
+ "the \b-v\b and \b-x\b options. If any additional \aarg\as "
+ "are specified, they will replace the positional parameters.]"
+"[s?Sort the positional parameters.]"
+"[A]:[name?Assign the arguments sequentially to the array named by \aname\a "
+ "starting at subscript 0 rather than to the positional parameters.]"
+"\fabc\f"
+"[06:default?Restore all non-command line options to the default settings.]"
+"[07:state?List the current option state in the form of a \bset\b command "
+ "that can be executed to restore the state.]"
+"\n"
+"\n[arg ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?No errors occurred.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\btypeset\b(1), \bshift\b(1)]"
+;
+
+
+
+const char sh_optshift[] =
+"[-1c?\n@(#)$Id: shift (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?shift - shift positional parameters]"
+"[+DESCRIPTION?\bshift\b is a shell special built-in that shifts the "
+ "positional parameters to the left by the number of places "
+ "defined by \an\a, or \b1\b if \an\a is omitted. The number of "
+ "positional parameters remaining will be reduced by the "
+ "number of places that are shifted.]"
+"[+?If \an\a is given, it will be evaluated as an arithmetic expression "
+ "to determinate the number of places to shift. It is an error "
+ "to shift more than the number of positional parameters or a "
+ "negative number of places.]"
+"\n"
+"\n[n]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?The positional parameters were successfully shifted.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bset\b(1)]"
+;
+
+const char sh_optsleep[] =
+"[-1c?\n@(#)$Id: sleep (AT&T Research) 2009-03-12 $\n]"
+USAGE_LICENSE
+"[+NAME?sleep - suspend execution for an interval]"
+"[+DESCRIPTION?\bsleep\b suspends execution for at least the time specified "
+ "by \aduration\a or until a \bSIGALRM\b signal is received. "
+ "\aduration\a may be one of the following:]"
+"{"
+ "[+integer?The number of seconds to sleep.]"
+ "[+floating point?The number of seconds to sleep. The actual "
+ "granularity depends on the underlying system, normally "
+ "around 1 millisecond.]"
+ "[+P\an\a\bY\b\an\a\bM\b\an\a\bDT\b\an\a\bH\b\an\a\bM\b\an\a\bS?An ISO 8601 duration "
+ "where at least one of the duration parts must be specified.]"
+ "[+P\an\a\bW?An ISO 8601 duration specifying \an\a weeks.]"
+ "[+p\an\a\bY\b\an\a\bM\b\an\a\bDT\b\an\a\bH\b\an\a\bm\b\an\a\bS?A case insensitive "
+ "ISO 8601 duration except that \bM\b specifies months, \bm\b before \bs\b or \bS\b "
+ "specifies minutes and after specifies milliseconds, \bu\b or \bU\b specifies "
+ "microseconds, and \bn\b specifies nanoseconds.]"
+ "[+date/time?Sleep until the \bdate\b(1) compatible date/time.]"
+"}"
+"[s?Sleep until a signal or a timeout is received. If \aduration\a is omitted "
+ "or 0 then no timeout will be used.]"
+"\n"
+"\n[ duration ]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?The execution was successfully suspended for at least \aduration\a "
+ "or a \bSIGALRM\b signal was received.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bdate\b(1), \btime\b(1), \bwait\b(1)]"
+;
+
+const char sh_opttrap[] =
+"[-1c?\n@(#)$Id: trap (AT&T Research) 1999-07-17 $\n]"
+USAGE_LICENSE
+"[+NAME?trap - trap signals and conditions]"
+"[+DESCRIPTION?\btrap\b is a special built-in that defines actions to be "
+ "taken when conditions such as receiving a signal occur. Also, "
+ "\btrap\b can be used to display the current trap settings on "
+ "standard output.]"
+"[+?If \aaction\a is \b-\b, \btrap\b resets each \acondition\a "
+ "to the default value. If \aaction\a is an empty string, the "
+ "shell ignores each of the \acondition\as if they arise. "
+ "Otherwise, the argument \aaction\a will be read and executed "
+ "by the shell as if it were processed by \beval\b(1) when one "
+ "of the corresponding conditions arise. The action of the trap "
+ "will override any previous action associated with each specified "
+ "\acondition\a. The value of \b$?\b is not altered by the trap "
+ "execution.]"
+"[+?\acondition\a can be the name or number of a signal, or one of the "
+ "following:]{"
+ "[+EXIT?This trap is executed when the shell exits. If defined "
+ "within a function defined with the \bfunction\b reserved "
+ "word, the trap is executed in the caller's environment "
+ "when the function returns and the trap action is restored "
+ "to the value it had when it called the function.]"
+ "[+0?Same as EXIT.]"
+ "[+DEBUG?Executed before each simple command is executed but after "
+ "the arguments are expanded.]"
+ "[+ERR?Executed whenever \bset -e\b would cause the shell to exit.]"
+ "[+KEYBD?Executed when a key is entered from a terminal device.]"
+"}"
+"[+?Signal names are case insensitive and the \bsig\b prefix is optional. "
+ "Signals that were ignored on entry to a noninteractive shell cannot "
+ "trapped or reset although doing so will not report an error. The "
+ "use of signal numbers other than \b1\b, \b2\b, \b3\b, \b6\b, "
+ "\b9\b, \b14\b, and \b15\b is not portable.]"
+"[+?Although \btrap\b is a special built-in, specifying a condition that "
+ "the shell does not know about causes \btrap\b to exit with a "
+ "non-zero exit status, but does not terminate the invoking shell.]"
+"[+?If no \aaction\a or \acondition\as are specified then all the current "
+ "trap settings are written to standard output.]"
+"[p?Causes the current traps to be output in a format that can be processed "
+ "as input to the shell to recreate the current traps.]"
+"\n"
+"\n[action condition ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\bkill\b(1), \beval\b(1), \bsignal\b(3)]"
+;
+
+const char sh_opttypeset[] =
+"+[-1c?\n@(#)$Id: typeset (AT&T Research) 2010-12-08 $\n]"
+USAGE_LICENSE
+"[+NAME?\f?\f - declare or display variables with attributes]"
+"[+DESCRIPTION?Without the \b-f\b option, \b\f?\f\b sets, unsets, "
+ "or displays attributes of variables as specified with the "
+ "options. If the first option is specified with a \b-\b "
+ "then the attributes are set for each of the given \aname\as. "
+ "If the first option is specified with a \b+\b, then the specified "
+ "attributes are unset. If \b=\b\avalue\a is specified value is "
+ "assigned before the attributes are set.]"
+"[+?When \b\f?\f\b is called inside a function defined with the "
+ "\bfunction\b reserved word, and \aname\a does not contain a "
+ "\b.\b, then a local variable statically scoped to that function "
+ "will be created.]"
+"[+?Not all option combinations are possible. For example, the numeric "
+ "options \b-i\b, \b-E\b, and \b-F\b cannot be specified with "
+ "the justification options \b-L\b, \b-R\b, and \b-Z\b.]"
+"[+?Note that the following preset aliases are set by the shell:]{"
+ "[+compound?\b\f?\f -C\b.]"
+ "[+float?\b\f?\f -lE\b.]"
+ "[+functions?\b\f?\f -f\b.]"
+ "[+integer?\b\f?\f -li\b.]"
+ "[+nameref?\b\f?\f -n\b.]"
+"}"
+"[+?If no \aname\as are specified then variables that have the specified "
+ "options are displayed. If the first option is specified with "
+ "a leading \b-\b then the name and value of each variable is "
+ "written to standard output. Otherwise, only the names are "
+ "written. If no options are specified or just \b-p\b is "
+ "specified, then the names and attributes of all variables that have "
+ "attributes are written to standard output. When \b-f\b is specified, "
+ "the names displayed will be function names.]"
+"[+?If \b-f\b is specified, then each \aname\a refers to a function "
+ "and the only valid options are \b-u\b and \b-t\b. In this "
+ "case no \b=\b\avalue\a can be specified.]"
+"[+?\b\f?\f\b is built-in to the shell as a declaration command so that "
+ "field splitting and pathname expansion are not performed on "
+ "the arguments. Tilde expansion occurs on \avalue\a.]"
+#if 1
+"[a]:?[type?Indexed array. This is the default. If \b[\b\atype\a\b]]\b is "
+ "specified, each subscript is interpreted as a value of type \atype\a.]"
+#else
+"[a?Indexed array. this is the default.]"
+#endif
+"[b?Each \aname\a may contain binary data. Its value is the mime "
+ "base64 encoding of the data. It can be used with \b-Z\b, "
+ "to specify fixed sized fields.]"
+"[f?Each of the options and \aname\as refers to a function.]"
+"[i]#?[base:=10?An integer. \abase\a represents the arithmetic base "
+ "from 2 to 64.]"
+"[l?Without \b-i\b, sets character mapping to \btolower\b. When used "
+ "with \b-i\b, \b-E\b, or \b-F\b indicates long variant.]"
+"[m?Move. The value is the name of a variable whose value will be "
+ "moved to \aname\a. The orignal variable will be unset. Cannot be "
+ "used with any other options.]"
+"[n?Name reference. The value is the name of a variable that \aname\a "
+ "references. \aname\a cannot contain a \b.\b. Cannot be use with "
+ "any other options.]"
+"[p?Causes the output to be in a format that can be used as input to the "
+ "shell to recreate the attributes for variables.]"
+"[r?Enables readonly. Once enabled it cannot be disabled. See "
+ "\breadonly\b(1).]"
+"[s?Used with \b-i\b to restrict integer size to short.]"
+"[t?When used with \b-f\b, enables tracing for each of the specified "
+ "functions. Otherwise, \b-t\b is a user defined attribute and "
+ "has no meaning to the shell.]"
+"[u?Without \b-f\b or \b-i\b, sets character mapping to \btoupper\b. When "
+ "used with \b-f\b specifies that \aname\a is a function "
+ "that hasn't been loaded yet. With \b-i\b specifies that the "
+ "value will be displayed as an unsigned integer.]"
+"[x?Puts each \aname\a on the export list. See \bexport\b(1). \aname\a "
+ "cannot contain a \b.\b.]"
+"[A?Associative array. Each \aname\a will converted to an associate "
+ "array. If a variable already exists, the current value will "
+ "become index \b0\b.]"
+"[C?Compound variable. Each \aname\a will be a compound variable. If "
+ "\avalue\a names a compound variable it will be copied to \aname\a. "
+ "Otherwise if the variable already exists, it will first be unset.]"
+"[E]#?[n:=10?Floating point number represented in scientific notation. "
+ "\an\a specifies the number of significant figures when the "
+ "value is expanded.]"
+"[F]#?[n:=10?Floating point. \an\a is the number of places after the "
+ "decimal point when the value is expanded.]"
+"[H?Hostname mapping. Each \aname\a holds a native pathname. Assigning a "
+ "UNIX format pathname will cause it to be converted to a pathname "
+ "suitable for the current host. This has no effect when the "
+ "native system is UNIX.]"
+"[L]#?[n?Left justify. If \an\a is given it represents the field width. If "
+ "the \b-Z\b attribute is also specified, then leading zeros are "
+ "stripped.]"
+"[M]:?[mapping?\amapping\a is the name of a character mapping known by "
+ "\bwctrans\b(3) such as \btolower\b or \btoupper\b. When the option "
+ "value \bmapping\b is omitted and there are no operands, all mapped "
+ "variables are displayed.]"
+"[R]#?[n?Right justify. If \an\a is given it represents the field width. If "
+ "the \b-Z\b attribute is also specified, then zeros will "
+ "be used as the fill character. Otherwise, spaces are used.]"
+"[X]#?[n:=2*sizeof(long long)?Floating point number represented in hexadecimal "
+ "notation. \an\a specifies the number of significant figures when the "
+ "value is expanded.]"
+
+#ifdef SHOPT_TYPEDEF
+"[h]:[string?Used within a type definition to provide a help string "
+ "for variable \aname\a. Otherwise, it is ignored.]"
+"[S?Used with a type definition to indicate that the variable is shared by "
+ "each instance of the type. When used inside a function defined "
+ "with the \bfunction\b reserved word, the specified variables "
+ "will have function static scope. Otherwise, the variable is "
+ "unset prior to processing the assignment list.]"
+#endif
+"[T]:?[tname?\atname\a is the name of a type name given to each \aname\a.]"
+"[Z]#?[n?Zero fill. If \an\a is given it represents the field width.]"
+"\n"
+"\n[name[=value]...]\n"
+" -f [name...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?No errors occurred.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\breadonly\b(1), \bexport\b(1)]"
+;
+
+const char sh_optulimit[] =
+"[-1c?@(#)$Id: ulimit (AT&T Research) 2003-06-21 $\n]"
+USAGE_LICENSE
+"[+NAME?ulimit - set or display resource limits]"
+"[+DESCRIPTION?\bulimit\b sets or displays resource limits. These "
+ "limits apply to the current process and to each child process "
+ "created after the resource limit has been set. If \alimit\a "
+ "is specified, the resource limit is set, otherwise, its current value "
+ "is displayed on standard output.]"
+"[+?Increasing the limit for a resource usually requires special privileges. "
+ "Some systems allow you to lower resource limits and later increase "
+ "them. These are called soft limits. Once a hard limit is "
+ "set the resource can not be increased.]"
+"[+?Different systems allow you to specify different resources and some "
+ "restrict how much you can raise the limit of the resource.]"
+"[+?The value of \alimit\a depends on the unit of the resource listed "
+ "for each resource. In addition, \alimit\a can be \bunlimited\b "
+ "to indicate no limit for that resource.]"
+"[+?If you do not specify \b-H\b or \b-S\b, then \b-S\b is used for "
+ "listing and both \b-S\b and \b-H\b are used for setting resources.]"
+"[+?If you do not specify any resource, the default is \b-f\b.]"
+"[H?A hard limit is set or displayed.]"
+"[S?A soft limit is set or displayed.]"
+"[a?Displays all current resource limits]"
+"\flimits\f"
+"\n"
+"\n[limit]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?A request for a higher limit was rejected or an error occurred.]"
+"}"
+
+"[+SEE ALSO?\bulimit\b(2), \bgetrlimit\b(2)]"
+;
+
+const char sh_optumask[] =
+"[-1c?\n@(#)$Id: umask (AT&T Research) 1999-04-07 $\n]"
+USAGE_LICENSE
+"[+NAME?umask - get or set the file creation mask]"
+"[+DESCRIPTION?\bumask\b sets the file creation mask of the current "
+ "shell execution environment to the value specified by the "
+ "\amask\a operand. This mask affects the file permission bits "
+ "of subsequently created files. \amask\a can either be an "
+ "octal number or a symbolic value as described in \bchmod\b(1). "
+ "If a symbolic value is given, the new file creation mask is the "
+ "complement of the result of applying \amask\a to the complement "
+ "of the current file creation mask.]"
+"[+?If \amask\a is not specified, \bumask\b writes the value of the "
+ "file creation mask for the current process to standard output.]"
+"[S?Causes the file creation mask to be written or treated as a symbolic value "
+ "rather than an octal number.]"
+"\n"
+"\n[mask]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?The file creation mask was successfully changed, or no "
+ "\amask\a operand was supplied.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bchmod\b(1)]"
+;
+const char sh_optuniverse[] = " [name]";
+const char sh_optunset[] =
+"[-1c?\n@(#)$Id: unset (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?unset - unset values and attributes of variables and functions]"
+"[+DESCRIPTION?For each \aname\a specified, \bunset\b unsets the variable, "
+ "or function if \b-f\b is specified, from the current shell "
+ "execution environment. Readonly variables cannot be unset.]"
+"[n?If \aname\a refers to variable that is a reference, the variable \aname\a "
+ "will be unset rather than the variable it references. Otherwise, "
+ "is is equivalent to \b-v\b.]"
+"[f?\aname\a refers to a function name and the shell will unset the "
+ "function definition.]"
+"[v?\aname\a refers to a variable name and the shell will unset it and "
+ "remove it from the environment. This is the default behavior.]"
+"\n"
+"\nname...\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All \aname\as were successfully unset.]"
+ "[+>0?One or more \aname\a operands could not be unset "
+ "or an error occurred.]"
+"}"
+
+"[+SEE ALSO?\btypeset\b(1)]"
+;
+
+const char sh_optunalias[] =
+"[-1c?\n@(#)$Id: unalias (AT&T Research) 1999-07-07 $\n]"
+USAGE_LICENSE
+"[+NAME?unalias - remove alias definitions]"
+"[+DESCRIPTION?\bunalias\b removes the definition of each named alias "
+ "from the current shell execution environment, or all aliases if "
+ "\b-a\b is specified. It will not affect any commands that "
+ "have already been read and subsequently executed.]"
+"[a?Causes all alias definitions to be removed. \aname\a operands "
+ "are optional and ignored in this case.]"
+"\n"
+"\nname...\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?\b-a\b was not specified and one or more \aname\a operands "
+ "did not have an alias definition, or an error occurred.]"
+"}"
+
+"[+SEE ALSO?\balias\b(1)]"
+;
+
+const char sh_optwait[] =
+"[-1c?\n@(#)$Id: wait (AT&T Research) 1999-06-17 $\n]"
+USAGE_LICENSE
+"[+NAME?wait - wait for process or job completion]"
+"[+DESCRIPTION?\bwait\b with no operands, waits until all jobs "
+ "known to the invoking shell have terminated. If one or more "
+ "\ajob\a operands are specified, \bwait\b waits until all of them "
+ "have completed.]"
+_JOB_
+"[+?If one ore more \ajob\a operands is a process id or process group id "
+ "not known by the current shell environment, \bwait\b treats each "
+ "of them as if it were a process that exited with status 127.]"
+"\n"
+"\n[job ...]\n"
+"\n"
+"[+EXIT STATUS?If \await\a is invoked with one or more \ajob\as, and all of "
+ "them have terminated or were not known by the invoking shell, "
+ "the exit status of \bwait\b will be that of the last \ajob\a. "
+ "Otherwise, it will be one of the following:]{"
+ "[+0?\bwait\b utility was invoked with no operands and all "
+ "processes known by the invoking process have terminated.]"
+ "[+127?\ajob\a is a process id or process group id that is unknown "
+ "to the current shell environment.]"
+"}"
+
+"[+SEE ALSO?\bjobs\b(1), \bps\b(1)]"
+;
+
+#if SHOPT_FS_3D
+ const char sh_optvpath[] = " [top] [base]";
+ const char sh_optvmap[] = " [dir] [list]";
+#endif /* SHOPT_FS_3D */
+
+const char sh_optwhence[] =
+"[-1c?\n@(#)$Id: whence (AT&T Research) 2007-04-24 $\n]"
+USAGE_LICENSE
+"[+NAME?whence - locate a command and describe its type]"
+"[+DESCRIPTION?Without \b-v\b, \bwhence\b writes on standard output an "
+ "absolute pathname, if any, corresponding to \aname\a based "
+ "on the complete search order that the shell uses. If \aname\a "
+ "is not found, then no output is produced.]"
+"[+?If \b-v\b is specified, the output will also contain information "
+ "that indicates how the given \aname\a would be interpreted by "
+ "the shell in the current execution environment.]"
+"[a?Displays all uses for each \aname\a rather than the first.]"
+"[f?Do not check for functions.]"
+"[p?Do not check to see if \aname\a is a reserved word, a built-in, "
+ "an alias, or a function. This turns off the \b-v\b option.]"
+"[q?Quiet mode. Returns 0 if all arguments are built-ins, functions, or are "
+ "programs found on the path.]"
+"[v?For each name you specify, the shell displays a line that indicates "
+ "if that name is one of the following:]{"
+ "[+?Reserved word]"
+ "[+?Alias]"
+ "[+?Built-in]"
+ "[+?Undefined function]"
+ "[+?Function]"
+ "[+?Tracked alias]"
+ "[+?Program]"
+"}"
+"\n"
+"\nname ...\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Each \aname\a was found by the shell.]"
+ "[+1?One or more \aname\as were not found by the shell.]"
+ "[+>1?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\bcommand\b(1)]"
+;
+
+
+const char e_alrm1[] = "alarm -r %s +%.3g\n";
+const char e_alrm2[] = "alarm %s %.3f\n";
+const char e_baddisc[] = "%s: invalid discipline function";
+const char e_nospace[] = "out of memory";
+const char e_nofork[] = "cannot fork";
+const char e_nosignal[] = "%s: unknown signal name";
+const char e_condition[] = "condition(s) required";
+const char e_cneedsarg[] = "-c requires argument";
diff --git a/src/cmd/ksh93/data/keywords.c b/src/cmd/ksh93/data/keywords.c
new file mode 100644
index 0000000..fed2cf0
--- /dev/null
+++ b/src/cmd/ksh93/data/keywords.c
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#include "shell.h"
+#include "shlex.h"
+#include "FEATURE/options"
+
+/*
+ * table of reserved words in shell language
+ * This list must be in in ascii sorted order
+ */
+
+const Shtable_t shtab_reserved[] =
+{
+ "!", NOTSYM,
+ "[[", BTESTSYM,
+ "case", CASESYM,
+ "do", DOSYM,
+ "done", DONESYM,
+ "elif", ELIFSYM,
+ "else", ELSESYM,
+ "esac", ESACSYM,
+ "fi", FISYM,
+ "for", FORSYM,
+ "function", FUNCTSYM,
+ "if", IFSYM,
+ "in", INSYM,
+#if SHOPT_NAMESPACE
+ "namespace", NSPACESYM,
+#endif /* SHOPT_NAMESPACE */
+ "select", SELECTSYM,
+ "then", THENSYM,
+ "time", TIMESYM,
+ "until", UNTILSYM,
+ "while", WHILESYM,
+ "{", LBRACE,
+ "}", RBRACE,
+ "", 0,
+};
+
+const char e_unexpected[] = "unexpected";
+const char e_unmatched[] = "unmatched";
+const char e_endoffile[] = "end of file";
+const char e_newline[] = "newline";
+
diff --git a/src/cmd/ksh93/data/lexstates.c b/src/cmd/ksh93/data/lexstates.c
new file mode 100644
index 0000000..90938c1
--- /dev/null
+++ b/src/cmd/ksh93/data/lexstates.c
@@ -0,0 +1,417 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#include "FEATURE/options"
+#include "lexstates.h"
+
+
+/*
+ * This is the initial state for tokens
+ */
+static const char sh_lexstate0[256] =
+{
+ S_EOF, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+#if SHOPT_CRNL
+ S_REG, 0, S_NLTOK,S_REG, S_REG, 0, S_REG, S_REG,
+#else
+ S_REG, 0, S_NLTOK,S_REG, S_REG, S_REG, S_REG, S_REG,
+#endif /* SHOPT_CRNL */
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+
+ 0, S_REG, S_REG, S_COM, S_REG, S_REG, S_OP, S_REG,
+ S_OP, S_OP, S_REG, S_REG, S_REG, S_REG, S_NAME, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_OP, S_OP, S_REG, S_OP, S_REG,
+
+ S_REG, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME,
+ S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME,
+ S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME,
+ S_NAME, S_NAME, S_NAME, S_REG, S_REG, S_REG, S_REG, S_NAME,
+
+ S_REG, S_NAME, S_NAME, S_RES, S_RES, S_RES, S_RES, S_NAME,
+#if SHOPT_NAMESPACE
+ S_NAME, S_RES, S_NAME, S_NAME, S_NAME, S_NAME, S_RES, S_NAME,
+#else
+ S_NAME, S_RES, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME, S_NAME,
+#endif /* SHOPT_NAMESPACE */
+ S_NAME, S_NAME, S_NAME, S_RES, S_RES, S_RES, S_NAME, S_RES,
+ S_NAME, S_NAME, S_NAME, S_BRACE,S_OP, S_BRACE,S_TILDE,S_REG,
+
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+};
+
+/*
+ * This state is for identifiers
+ */
+static const char sh_lexstate1[256] =
+{
+ S_EOF, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+#if SHOPT_CRNL
+ S_REG, S_BREAK,S_BREAK,S_REG, S_REG, S_BREAK,S_REG, S_REG,
+#else
+ S_REG, S_BREAK,S_BREAK,S_REG, S_REG, S_REG, S_REG, S_REG,
+#endif /* SHOPT_CRNL */
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+
+ S_BREAK,S_EPAT, S_QUOTE,S_REG, S_DOL, S_EPAT, S_BREAK,S_LIT,
+ S_BREAK,S_BREAK,S_PAT, S_EPAT, S_REG, S_EPAT, S_DOT, S_REG,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_LABEL,S_BREAK,S_BREAK,S_EQ, S_BREAK,S_PAT,
+
+ S_EPAT, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACT,S_ESC, S_REG, S_REG, 0,
+
+ S_GRAVE,0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACE,S_BREAK,S_BRACE,S_EPAT, S_REG,
+
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+ S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG, S_REG,
+};
+
+static const char sh_lexstate2[256] =
+{
+ S_EOF, 0, 0, 0, 0, 0, 0, 0,
+#if SHOPT_CRNL
+ 0, S_BREAK,S_BREAK,0, 0, S_BREAK,0, 0,
+#else
+ 0, S_BREAK,S_BREAK,0, 0, 0, 0, 0,
+#endif /* SHOPT_CRNL */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ S_BREAK,S_EPAT, S_QUOTE,0, S_DOL, S_EPAT, S_BREAK,S_LIT,
+ S_BREAK,S_BREAK,S_PAT, S_EPAT, 0, S_EPAT, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_COLON,S_BREAK,S_BREAK,0, S_BREAK,S_PAT,
+
+ S_EPAT, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_PAT, S_ESC, 0, 0, 0,
+
+ S_GRAVE,0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACE,S_BREAK,S_BRACE,S_EPAT, 0,
+};
+
+/*
+ * for skipping over '...'
+ */
+static const char sh_lexstate3[256] =
+{
+ S_EOF, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_NL, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, S_LIT,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, S_ESC2, 0, 0, 0
+};
+
+/*
+ * for skipping over "..." and `...`
+ */
+static const char sh_lexstate4[256] =
+{
+ S_EOF, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_NL, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_QUOTE,0, S_DOL, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, S_ESC, 0, 0, 0,
+ S_GRAVE,0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, S_RBRA, 0, 0
+};
+
+/*
+ * for skipping over ?(...), [...]
+ */
+static const char sh_lexstate5[256] =
+{
+ S_EOF, 0, 0, 0, 0, 0, 0, 0,
+ 0, S_BLNK, S_NL, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ S_BLNK, 0, S_QUOTE,0, S_DOL, 0, S_META, S_LIT,
+ S_PUSH, S_POP, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_POP, S_META, 0, S_META, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACT,S_ESC, S_POP, 0, 0,
+ S_GRAVE,0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACE,S_META, S_POP, S_TILDE,0
+};
+
+/*
+ * Defines valid expansion characters
+ */
+static const char sh_lexstate6[256] =
+{
+ S_EOF, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+
+ S_ERR, S_SPC1, S_ERR, S_SPC1, S_SPC2, S_ERR, S_ERR, S_LIT,
+ S_PAR, S_ERR, S_SPC2, S_ERR, S_ERR, S_SPC2, S_ALP, S_ERR,
+ S_DIG, S_DIG, S_DIG, S_DIG, S_DIG, S_DIG, S_DIG, S_DIG,
+ S_DIG, S_DIG, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_SPC2,
+
+#if SHOPT_TYPEDEF
+ S_SPC1, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+#else
+ S_SPC2, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+#endif
+ S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+ S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+ S_ALP, S_ALP, S_ALP, S_ERR, S_ERR, S_ERR, S_ERR, S_ALP,
+
+ S_ERR, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+ S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+ S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP, S_ALP,
+ S_ALP, S_ALP, S_ALP, S_LBRA, S_ERR, S_RBRA, S_ERR, S_ERR,
+
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+};
+
+/*
+ * for skipping over ${...} until modifier
+ */
+static const char sh_lexstate7[256] =
+{
+ S_EOF, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+
+ S_ERR, S_ERR, S_ERR, S_MOD2, S_ERR, S_MOD2, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_MOD1, S_MOD1, S_ERR, S_MOD1, S_DOT, S_MOD2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_MOD1, S_ERR, S_ERR, S_MOD1, S_ERR, S_MOD1,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACT,S_ESC, S_ERR, S_ERR, 0,
+
+ S_ERR, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_ERR, S_ERR, S_POP, S_ERR, S_ERR,
+
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+ S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR, S_ERR,
+};
+
+/*
+ * This state is for $name
+ */
+static const char sh_lexstate8[256] =
+{
+ S_EOF, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+
+ S_EDOL, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_EDOL, S_EDOL, S_EDOL, S_EDOL, 0,
+
+ S_EDOL,0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+ S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL, S_EDOL,
+};
+
+/*
+ * This is used for macro expansion
+ */
+static const char sh_lexstate9[256] =
+{
+ S_EOF, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, S_QUOTE,0, S_DOL, 0, S_PAT, S_LIT,
+ S_PAT, S_PAT, S_PAT, 0, S_COM, 0, S_DOT, S_SLASH,
+ S_DIG, S_DIG, S_DIG, S_DIG, S_DIG, S_DIG, S_DIG, S_DIG,
+ S_DIG, S_DIG, S_COLON,0, 0, S_EQ, 0, S_PAT,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, S_BRACT,S_ESC, S_ENDCH,0, 0,
+ S_GRAVE,0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+#if SHOPT_BRACEPAT
+ 0, 0, 0, S_BRACE,S_PAT, S_ENDCH,0, 0
+#else
+ 0, 0, 0, 0, S_PAT, S_ENDCH,0, 0
+#endif /* SHOPT_BRACEPAT */
+};
+
+const char *sh_lexrstates[ST_NONE] =
+{
+ sh_lexstate0, sh_lexstate1, sh_lexstate2, sh_lexstate3,
+ sh_lexstate4, sh_lexstate5, sh_lexstate6, sh_lexstate7,
+ sh_lexstate8, sh_lexstate9, sh_lexstate5
+};
+
+
+const char e_lexversion[] = "%d: invalid binary script version";
+const char e_lexspace[] = "line %d: use space or tab to separate operators %c and %c";
+const char e_lexslash[] = "line %d: $ not preceded by \\";
+const char e_lexsyntax1[] = "syntax error at line %d: `%s' %s";
+const char e_lexsyntax2[] = "syntax error: `%s' %s";
+const char e_lexsyntax3[] = "syntax error at line %d: duplicate label %s";
+const char e_lexsyntax4[] = "syntax error at line %d: invalid reference list";
+const char e_lexsyntax5[] = "syntax error at line %d: `<<%s' here-document not contained within command substitution";
+const char e_lexwarnvar[] = "line %d: variable expansion makes arithmetic evaluation less efficient";
+const char e_lexlabignore[] = "line %d: label %s ignored";
+const char e_lexlabunknown[] = "line %d: %s unknown label";
+const char e_lexobsolete1[] = "line %d: `...` obsolete, use $(...)";
+const char e_lexobsolete2[] = "line %d: -a obsolete, use -e";
+const char e_lexobsolete3[] = "line %d: '=' obsolete, use '=='";
+const char e_lexobsolete4[] = "line %d: %s within [[...]] obsolete, use ((...))";
+const char e_lexobsolete5[] = "line %d: set %s obsolete";
+const char e_lexobsolete6[] = "line %d: `{' instead of `in' is obsolete";
+const char e_lexnonstandard[] = "line %d: `&>file' is nonstandard -- interpreted as `>file 2>&1' for profile input only";
+const char e_lexusebrace[] = "line %d: use braces to avoid ambiguities with $id[...]";
+const char e_lexusequote[] = "line %d: %c within ${} should be quoted";
+const char e_lexescape[] = "line %d: escape %c to avoid ambiguities";
+const char e_lexquote[] = "line %d: quote %c to avoid ambiguities";
+const char e_lexnested[] = "line %d: spaces required for nested subshell";
+const char e_lexbadchar[] = "%c: invalid character in expression - %s";
+const char e_lexfuture[] = "line %d: \\ in front of %c reserved for future use";
+const char e_lexlongquote[] = "line %d: %c quote may be missing";
+const char e_lexzerobyte[] = "zero byte";
+const char e_lexemptyfor[] = "line %d: empty for list";
+const char e_lextypeset[] = "line %d: %s invalid typeset option order";
+const char e_lexcharclass[] = "line %d: '^' as first character in character class not portable";
diff --git a/src/cmd/ksh93/data/limits.c b/src/cmd/ksh93/data/limits.c
new file mode 100644
index 0000000..9ce9968
--- /dev/null
+++ b/src/cmd/ksh93/data/limits.c
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include "ulimit.h"
+
+/*
+ * This is the list of resouce limits controlled by ulimit
+ * This command requires getrlimit(), vlimit(), or ulimit()
+ */
+
+#ifndef _no_ulimit
+
+const char e_unlimited[] = "unlimited";
+const char* e_units[] = { 0, "block", "byte", "kbyte", "second" };
+
+const int shtab_units[] = { 1, 512, 1, 1024, 1 };
+
+const Limit_t shtab_limits[] =
+{
+"as", "address space limit", RLIMIT_AS, 0, 'M', LIM_KBYTE,
+"core", "core file size", RLIMIT_CORE, 0, 'c', LIM_BLOCK,
+"cpu", "cpu time", RLIMIT_CPU, 0, 't', LIM_SECOND,
+"data", "data size", RLIMIT_DATA, 0, 'd', LIM_KBYTE,
+"fsize", "file size", RLIMIT_FSIZE, 0, 'f', LIM_BLOCK,
+"locks", "number of file locks", RLIMIT_LOCKS, 0, 'x', LIM_COUNT,
+"memlock", "locked address space", RLIMIT_MEMLOCK, 0, 'l', LIM_KBYTE,
+"msgqueue", "message queue size", RLIMIT_MSGQUEUE,0, 'q', LIM_KBYTE,
+"nice", "scheduling priority", RLIMIT_NICE, 0, 'e', LIM_COUNT,
+"nofile", "number of open files", RLIMIT_NOFILE, "OPEN_MAX", 'n', LIM_COUNT,
+"nproc", "number of processes", RLIMIT_NPROC, "CHILD_MAX", 'u', LIM_COUNT,
+"pipe", "pipe buffer size", RLIMIT_PIPE, "PIPE_BUF", 'p', LIM_BYTE,
+"rss", "max memory size", RLIMIT_RSS, 0, 'm', LIM_KBYTE,
+"rtprio", "max real time priority",RLIMIT_RTPRIO, 0, 'r', LIM_COUNT,
+"sbsize", "socket buffer size", RLIMIT_SBSIZE, "PIPE_BUF", 'b', LIM_BYTE,
+"sigpend", "signal queue size", RLIMIT_SIGPENDING,"SIGQUEUE_MAX",'i', LIM_COUNT,
+"stack", "stack size", RLIMIT_STACK, 0, 's', LIM_KBYTE,
+"swap", "swap size", RLIMIT_SWAP, 0, 'w', LIM_KBYTE,
+"threads", "number of threads", RLIMIT_PTHREAD, "THREADS_MAX", 'T', LIM_COUNT,
+"vmem", "process size", RLIMIT_VMEM, 0, 'v', LIM_KBYTE,
+{ 0 }
+};
+
+#endif
diff --git a/src/cmd/ksh93/data/math.tab b/src/cmd/ksh93/data/math.tab
new file mode 100644
index 0000000..3750c15
--- /dev/null
+++ b/src/cmd/ksh93/data/math.tab
@@ -0,0 +1,75 @@
+# <return type: i:integer f:floating-point> <#floating-point-args> <function-name> [<alias> ...]
+# <function-name>l variants are handled by features/math.sh
+# @(#)math.tab (AT&T Research) 2010-10-26
+f 1 acos
+f 1 acosh
+f 1 asin
+f 1 asinh
+f 1 atan
+f 2 atan2
+f 1 atanh
+f 1 cbrt
+f 1 ceil
+f 2 copysign
+f 1 cos
+f 1 cosh
+f 1 erf
+f 1 erfc
+f 1 exp
+f 1 exp2
+f 1 expm1
+f 1 fabs abs
+f 2 fdim
+f 1 finite
+f 1 floor int
+f 3 fma
+f 2 fmax
+f 2 fmin
+f 2 fmod
+i 1 fpclassify
+i 1 fpclass
+f 2 hypot
+i 1 ilogb
+i 1 isfinite
+i 2 isgreater
+i 2 isgreaterequal
+i 1 isinf
+i 1 isinfinite
+i 2 isless
+i 2 islessequal
+i 2 islessgreater
+i 1 isnan
+i 1 isnormal
+i 1 issubnormal fpclassify=FP_SUBNORMAL
+i 2 isunordered
+i 1 iszero fpclassify=FP_ZERO fpclass=FP_NZERO|FP_PZERO {return a1==0.0||a1==-0.0;}
+f 1 j0
+f 1 j1
+f 2 jn
+x 2 ldexp
+f 1 lgamma
+f 1 log
+f 1 log10
+f 1 log1p
+f 1 log2
+f 1 logb
+f 1 nearbyint
+f 2 nextafter
+f 2 nexttoward
+f 2 pow
+f 2 remainder
+f 1 rint
+f 1 round {Sfdouble_t r;Sflong_t y;y=floor(2*a1);r=rint(a1);if(2*a1==y)r+=(r<a1)-(a1<0);return r;}
+f 2 scalb
+f 2 scalbn
+i 1 signbit
+f 1 sin
+f 1 sinh
+f 1 sqrt
+f 1 tan
+f 1 tanh
+f 1 tgamma {Sfdouble_t r=exp(lgamma(a1));return (signgam<0)?-r:r;}
+f 1 trunc
+f 1 y0
+f 1 y1
+f 2 yn
diff --git a/src/cmd/ksh93/data/msg.c b/src/cmd/ksh93/data/msg.c
new file mode 100644
index 0000000..a4eead9
--- /dev/null
+++ b/src/cmd/ksh93/data/msg.c
@@ -0,0 +1,215 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * UNIX shell
+ * S. R. Bourne
+ * Rewritten by David Korn
+ *
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <errno.h>
+#include "defs.h"
+#include "path.h"
+#include "io.h"
+#include "shlex.h"
+#include "timeout.h"
+#include "history.h"
+#include "builtins.h"
+#include "jobs.h"
+#include "edit.h"
+
+#include "FEATURE/cmds"
+
+/* error messages */
+const char e_timewarn[] = "\r\n\ashell will timeout in 60 seconds due to inactivity";
+const char e_runvi[] = "\\hist -e \"${VISUAL:-${EDITOR:-vi}}\" ";
+const char e_timeout[] = "timed out waiting for input";
+const char e_mailmsg[] = "you have mail in $_";
+const char e_query[] = "no query process";
+const char e_history[] = "no history file";
+const char e_histopen[] = "history file cannot open";
+const char e_option[] = "%s: bad option(s)";
+const char e_toomany[] = "open file limit exceeded";
+const char e_argtype[] = "invalid argument of type %c";
+const char e_oneoperand[] = "one operand expected";
+const char e_formspec[] = "%c: unknown format specifier";
+const char e_badregexp[] = "%s: invalid regular expression";
+const char e_number[] = "%s: bad number";
+const char e_badlocale[] = "%s: unknown locale";
+const char e_nullset[] = "%s: parameter null";
+const char e_notset[] = "%s: parameter not set";
+const char e_noparent[] = "%s: no parent";
+const char e_subst[] = "%s: bad substitution";
+const char e_create[] = "%s: cannot create";
+const char e_tmpcreate[] = "cannot create temporary file";
+const char e_restricted[] = "%s: restricted";
+const char e_pfsh[] = "%s: disabled in profile shell";
+const char e_pexists[] = "process already exists";
+const char e_exists[] = "%s: file already exists";
+const char e_pipe[] = "cannot create pipe";
+const char e_alarm[] = "cannot set alarm";
+const char e_open[] = "%s: cannot open";
+const char e_notseek[] = "%s: not seekable";
+const char e_badseek[] = "%s: invalid seek offset";
+const char e_badpattern[] = "%s: invalid shell pattern";
+const char e_noread[] = "%s: pattern seek requires read access";
+const char e_logout[] = "Use 'exit' to terminate this shell";
+const char e_exec[] = "%s: cannot execute";
+const char e_pwd[] = "cannot access parent directories";
+const char e_found[] = "%s: not found";
+const char e_defined[] = "%s: function not defined";
+const char e_nointerp[] = "%s: interpreter not found";
+const char e_subscript[] = "%s: subscript out of range";
+const char e_toodeep[] = "%s: recursion too deep";
+const char e_access[] = "permission denied";
+#ifdef _cmd_universe
+ const char e_nouniverse[] = "universe not accessible";
+#endif /* _cmd_universe */
+const char e_direct[] = "bad directory";
+const char e_file[] = "%s: bad file unit number";
+const char e_redirect[] = "redirection failed";
+const char e_trap[] = "%s: bad trap";
+const char e_readonly[] = "%s: is read only";
+const char e_badfield[] = "%d: negative field size";
+const char e_ident[] = "%s: is not an identifier";
+const char e_badname[] = "%s: invalid name";
+const char e_varname[] = "%s: invalid variable name";
+const char e_badfun[] = "%s: invalid function name";
+const char e_aliname[] = "%s: invalid alias name";
+const char e_badexport[] = "%s: only simple variables can be exported";
+const char e_badref[] = "%s: reference variable cannot be an array";
+const char e_badsubscript[] = "%c: invalid subscript in assignment";
+const char e_noarray[] = "%s: cannot be an array";
+const char e_badappend[] = "%s: invalid append to associative array";
+const char e_noref[] = "%s: no reference name";
+const char e_nounattr[] = "cannot unset attribute C or A or a";
+const char e_selfref[] = "%s: invalid self reference";
+const char e_globalref[] = "%s: global reference cannot refer to local variable";
+const char e_noalias[] = "%s: alias not found\n";
+const char e_format[] = "%s: bad format";
+const char e_redef[] = "%s: type cannot be redefined";
+const char e_required[] = "%s: is a required element of %s";
+const char e_badtformat[] = "%c: bad format character in time format";
+const char e_nolabels[] = "%s: label not implemented";
+const char e_notimp[] = "%s: not implemented";
+const char e_notelem[] = "%.*s: is not an element of %s";
+const char e_notenum[] = "%s: not an enumeration type";
+const char e_unknowntype[] = "%.*s: unknown type";
+const char e_unknownmap[] = "%s: unknown mapping name";
+const char e_mapchararg[] = "-M requires argument when operands are specified";
+const char e_subcomvar[] = "%s: compound assignment requires sub-variable name";
+const char e_badtypedef[] = "%s: type definition requires compound assignment";
+const char e_typecompat[] = "%s: array instance incompatible with type assignment";
+const char e_nosupport[] = "not supported";
+const char e_badrange[] = "%d-%d: invalid range";
+const char e_eneedsarg[] = "-e - requires single argument";
+const char e_badbase[] = "%s unknown base";
+const char e_loop[] = "%s: would cause loop";
+const char e_overlimit[] = "%s: limit exceeded";
+const char e_badsyntax[] = "incorrect syntax";
+const char e_badwrite[] = "write to %d failed";
+const char e_staticfun[] = "%s: defined as a static function in type %s and cannot be redefined";
+const char e_on [] = "on";
+const char e_off[] = "off";
+const char is_reserved[] = " is a keyword";
+const char is_builtin[] = " is a shell builtin";
+const char is_spcbuiltin[] = " is a special shell builtin";
+const char is_builtver[] = "is a shell builtin version of";
+const char is_alias[] = "%s is an alias for ";
+const char is_xalias[] = "%s is an exported alias for ";
+const char is_talias[] = "is a tracked alias for";
+const char is_function[] = " is a function";
+const char is_ufunction[] = " is an undefined function";
+#ifdef JOBS
+# ifdef SIGTSTP
+ const char e_newtty[] = "Switching to new tty driver...";
+ const char e_oldtty[] = "Reverting to old tty driver...";
+ const char e_no_start[] = "Cannot start job control";
+# endif /*SIGTSTP */
+ const char e_no_jctl[] = "No job control";
+ const char e_terminate[] = "You have stopped jobs";
+ const char e_done[] = " Done";
+ const char e_nlspace[] = "\n ";
+ const char e_running[] = " Running";
+ const char e_ambiguous[] = "%s: Ambiguous";
+ const char e_jobsrunning[] = "You have running jobs";
+ const char e_no_job[] = "no such job";
+ const char e_no_proc[] = "no such process";
+ const char e_badpid[] = "%s: invalid process id";
+# if SHOPT_COSHELL
+ const char e_jobusage[] = "%s: Arguments must be %%job, process ids, or job pool names";
+# else
+ const char e_jobusage[] = "%s: Arguments must be %%job or process ids";
+# endif /* SHOPT_COSHELL */
+#endif /* JOBS */
+const char e_coredump[] = "(coredump)";
+const char e_alphanum[] = "[_[:alpha:]]*([_[:alnum:]])";
+const char e_devfdNN[] = "/dev/fd/+([0-9])";
+const char e_devfdstd[] = "/dev/@(fd/+([0-9])|std@(in|out|err))";
+const char e_signo[] = "Signal %d";
+#if SHOPT_FS_3D
+ const char e_cantget[] = "cannot get %s";
+ const char e_cantset[] = "cannot set %s";
+ const char e_mapping[] = "mapping";
+ const char e_versions[] = "versions";
+#endif /* SHOPT_FS_3D */
+
+/* string constants */
+const char e_heading[] = "Current option settings";
+const char e_sptbnl[] = " \t\n";
+const char e_tolower[] = "tolower";
+const char e_toupper[] = "toupper";
+const char e_defpath[] = "/bin:/usr/bin:";
+const char e_defedit[] = _pth_ed;
+const char e_unknown [] = "<command unknown>";
+const char e_devnull[] = "/dev/null";
+const char e_traceprompt[] = "+ ";
+const char e_supprompt[] = "# ";
+const char e_stdprompt[] = "$ ";
+const char e_profile[] = "$HOME/.profile";
+const char e_sysprofile[] = "/etc/profile";
+const char e_suidprofile[] = "/etc/suid_profile";
+#if SHOPT_SYSRC
+const char e_sysrc[] = "/etc/ksh.kshrc";
+#endif
+#if SHOPT_BASH
+#if SHOPT_SYSRC
+const char e_bash_sysrc[] = "/etc/bash.bashrc";
+#endif
+const char e_bash_rc[] = "$HOME/.bashrc";
+const char e_bash_login[] = "$HOME/.bash_login";
+const char e_bash_logout[] = "$HOME/.bash_logout";
+const char e_bash_profile[] = "$HOME/.bash_profile";
+#endif
+const char e_crondir[] = "/usr/spool/cron/atjobs";
+const char e_prohibited[] = "login setuid/setgid shells prohibited";
+#if SHOPT_SUID_EXEC
+ const char e_suidexec[] = "/etc/suid_exec";
+#endif /* SHOPT_SUID_EXEC */
+const char hist_fname[] = "/.sh_history";
+const char e_dot[] = ".";
+const char e_envmarker[] = "A__z";
+const char e_timeformat[] = "\nreal\t%2lR\nuser\t%2lU\nsys\t%2lS";
+const char e_dict[] = "libshell";
+const char e_funload[] = "function, built-in or type definition for %s not found in %s";
diff --git a/src/cmd/ksh93/data/options.c b/src/cmd/ksh93/data/options.c
new file mode 100644
index 0000000..73617f1
--- /dev/null
+++ b/src/cmd/ksh93/data/options.c
@@ -0,0 +1,149 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "defs.h"
+#include "name.h"
+#include "shtable.h"
+
+#if SHOPT_BASH
+# define bashopt(a,b) a, b|SH_BASHOPT,
+# define bashextra(a,b) a, b|SH_BASHEXTRA,
+#else
+# define bashopt(a,b)
+# define bashextra(a,b)
+#endif
+
+/*
+ * This is the list of invocation and set options
+ * This list must be in in ascii sorted order
+ */
+
+const Shtable_t shtab_options[] =
+{
+ "allexport", SH_ALLEXPORT,
+#if SHOPT_BASH
+ "bash", (SH_BASH|SH_COMMANDLINE),
+#endif
+ "bgnice", SH_BGNICE,
+ "braceexpand", SH_BRACEEXPAND,
+ bashopt("cdable_vars", SH_CDABLE_VARS)
+ bashopt("cdspell", SH_CDSPELL)
+ bashopt("checkhash", SH_CHECKHASH)
+ bashopt("checkwinsize", SH_CHECKWINSIZE)
+ "noclobber", SH_NOCLOBBER,
+ bashopt("dotglob", SH_DOTGLOB)
+ "emacs", SH_EMACS,
+ "errexit", SH_ERREXIT,
+ "noexec", SH_NOEXEC,
+ bashopt("execfail", SH_EXECFAIL)
+ bashopt("expand_aliases", SH_EXPAND_ALIASES)
+ bashopt("extglob", SH_EXTGLOB)
+ "noglob", SH_NOGLOB,
+ "globstar", SH_GLOBSTARS,
+ "gmacs", SH_GMACS,
+ bashextra("hashall", SH_TRACKALL)
+ bashopt("histappend", SH_HISTAPPEND)
+#if SHOPT_HISTEXPAND
+ "histexpand", SH_HISTEXPAND,
+#else
+ bashextra("histexpand", SH_HISTEXPAND)
+#endif
+ bashextra("history", SH_HISTORY2)
+ bashopt("histreedit", SH_HISTREEDIT)
+ bashopt("histverify", SH_HISTVERIFY)
+ bashopt("hostcomplete", SH_HOSTCOMPLETE)
+ bashopt("huponexit", SH_HUPONEXIT)
+ "ignoreeof", SH_IGNOREEOF,
+ "interactive", SH_INTERACTIVE|SH_COMMANDLINE,
+ bashextra("interactive_comments", SH_INTERACTIVE_COMM)
+ "keyword", SH_KEYWORD,
+ "letoctal", SH_LETOCTAL,
+ bashopt("lithist", SH_LITHIST)
+ "nolog", SH_NOLOG,
+ "login_shell", SH_LOGIN_SHELL|SH_COMMANDLINE,
+ bashopt("mailwarn", SH_MAILWARN)
+ "markdirs", SH_MARKDIRS,
+ "monitor", SH_MONITOR,
+ "multiline", SH_MULTILINE,
+ bashopt("no_empty_cmd_completion", SH_NOEMPTYCMDCOMPL)
+ bashopt("nocaseglob", SH_NOCASEGLOB)
+ "notify", SH_NOTIFY,
+ bashopt("nullglob", SH_NULLGLOB)
+ bashextra("onecmd", SH_TFLAG)
+ "pipefail", SH_PIPEFAIL,
+ bashextra("physical", SH_PHYSICAL)
+ bashextra("posix", SH_POSIX)
+ "privileged", SH_PRIVILEGED,
+#if SHOPT_BASH
+ "profile", SH_LOGIN_SHELL|SH_COMMANDLINE,
+# if SHOPT_PFSH
+ "pfsh", SH_PFSH|SH_COMMANDLINE,
+# endif
+#else
+# if SHOPT_PFSH
+ "profile", SH_PFSH|SH_COMMANDLINE,
+# endif
+#endif
+ bashopt("progcomp", SH_PROGCOMP)
+ bashopt("promptvars", SH_PROMPTVARS)
+ "rc", SH_RC|SH_COMMANDLINE,
+ "restricted", SH_RESTRICTED,
+ bashopt("restricted_shell", SH_RESTRICTED2|SH_COMMANDLINE)
+ bashopt("shift_verbose", SH_SHIFT_VERBOSE)
+ "showme", SH_SHOWME,
+ bashopt("sourcepath", SH_SOURCEPATH)
+ "trackall", SH_TRACKALL,
+ "nounset", SH_NOUNSET,
+ "verbose", SH_VERBOSE,
+ "vi", SH_VI,
+ "viraw", SH_VIRAW,
+ bashopt("xpg_echo", SH_XPG_ECHO)
+ "xtrace", SH_XTRACE,
+ "", 0
+};
+
+const Shtable_t shtab_attributes[] =
+{
+ {"-Sshared", NV_REF|NV_TAGGED},
+ {"-nnameref", NV_REF},
+ {"-xexport", NV_EXPORT},
+ {"-rreadonly", NV_RDONLY},
+ {"-ttagged", NV_TAGGED},
+ {"-Aassociative array", NV_ARRAY},
+ {"-aindexed array", NV_ARRAY},
+ {"-llong", (NV_DOUBLE|NV_LONG)},
+ {"-Eexponential",(NV_DOUBLE|NV_EXPNOTE)},
+ {"-Xhexfloat", (NV_DOUBLE|NV_HEXFLOAT)},
+ {"-Ffloat", NV_DOUBLE},
+ {"-llong", (NV_INTEGER|NV_LONG)},
+ {"-sshort", (NV_INTEGER|NV_SHORT)},
+ {"-uunsigned", (NV_INTEGER|NV_UNSIGN)},
+ {"-iinteger", NV_INTEGER},
+ {"-Hfilename", NV_HOST},
+ {"-bbinary", NV_BINARY},
+ {"-ltolower", NV_UTOL},
+ {"-utoupper", NV_LTOU},
+ {"-Zzerofill", NV_ZFILL},
+ {"-Lleftjust", NV_LJUST},
+ {"-Rrightjust", NV_RJUST},
+ {"++namespace", NV_TABLE},
+ {"", 0}
+};
diff --git a/src/cmd/ksh93/data/signals.c b/src/cmd/ksh93/data/signals.c
new file mode 100644
index 0000000..802fe97
--- /dev/null
+++ b/src/cmd/ksh93/data/signals.c
@@ -0,0 +1,244 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#include "defs.h"
+
+#if defined(SIGCLD) && !defined(SIGCHLD)
+# define SIGCHLD SIGCLD
+#endif
+
+#define VAL(sig,mode) ((sig+1)|((mode)<<SH_SIGBITS))
+#define TRAP(n) (((n)|SH_TRAP)-1)
+
+#ifndef ERROR_dictionary
+# define ERROR_dictionary(s) (s)
+#endif
+#define S(s) ERROR_dictionary(s)
+
+/*
+ * This is a table that gives numbers and default settings to each signal.
+ * The signal numbers go in the low bits and the attributes go in the high bits.
+ * The names must be ASCII sorted lo-hi.
+ */
+
+const struct shtable2 shtab_signals[] =
+{
+#ifdef SIGABRT
+ "ABRT", VAL(SIGABRT,SH_SIGDONE), S("Abort"),
+#endif /*SIGABRT */
+#ifdef SIGAIO
+ "AIO", VAL(SIGAIO,SH_SIGIGNORE), S("Asynchronous I/O"),
+#endif /*SIGAIO */
+#ifdef SIGALRM
+ "ALRM", VAL(SIGALRM,SH_SIGDONE), S("Alarm call"),
+#endif /* SIGALRM */
+#ifdef SIGALRM1
+ "ALRM1", VAL(SIGALRM1,SH_SIGDONE), S("Scheduling - reserved"),
+#endif /* SIGALRM */
+#ifdef SIGAPOLLO
+ "APOLLO", VAL(SIGAPOLLO,0), S("SIGAPOLLO"),
+#endif /* SIGAPOLLO */
+#ifdef SIGBUS
+ "BUS", VAL(SIGBUS,SH_SIGDONE), S("Bus error"),
+#endif /* SIGBUS */
+#ifdef SIGCANCEL
+ "CANCEL", VAL(SIGCANCEL,SH_SIGIGNORE), S("Thread cancellation"),
+#endif /*SIGCANCEL */
+#ifdef SIGCHLD
+ "CHLD", VAL(SIGCHLD,SH_SIGFAULT), S("Death of Child"),
+# ifdef SIGCLD
+# if SIGCLD!=SIGCHLD
+ "CLD", VAL(SIGCLD,SH_SIGFAULT), S("Death of Child"),
+# endif
+# endif /* SIGCLD */
+#else
+# ifdef SIGCLD
+ "CLD", VAL(SIGCLD,SH_SIGFAULT), S("Death of Child"),
+# endif /* SIGCLD */
+#endif /* SIGCHLD */
+#ifdef SIGCONT
+ "CONT", VAL(SIGCONT,SH_SIGIGNORE), S("Stopped process continued"),
+#endif /* SIGCONT */
+#ifdef SIGCPUFAIL
+ "CPUFAIL", VAL(SIGCPUFAIL,0), S("Predictive processor deconfiguration"),
+#endif /* SIGRETRACT */
+ "DEBUG", VAL(TRAP(SH_DEBUGTRAP),0), "",
+#ifdef SIGDANGER
+ "DANGER", VAL(SIGDANGER,0), S("System crash soon"),
+#endif /* SIGDANGER */
+#ifdef SIGDIL
+ "DIL", VAL(SIGDIL,0), S("DIL signal"),
+#endif /* SIGDIL */
+#ifdef SIGEMT
+ "EMT", VAL(SIGEMT,SH_SIGDONE), S("EMT trap"),
+#endif /* SIGEMT */
+ "ERR", VAL(TRAP(SH_ERRTRAP),0), "",
+#ifdef SIGERR
+ "ERR", VAL(SIGERR,0), "",
+#endif /* SIGERR */
+ "EXIT", VAL(0,0), "",
+ "FPE", VAL(SIGFPE,SH_SIGDONE), S("Floating exception"),
+#ifdef SIGFREEZE
+ "FREEZE", VAL(SIGFREEZE,SH_SIGIGNORE), S("Special signal used by CPR"),
+#endif /* SIGFREEZE */
+#ifdef SIGGRANT
+ "GRANT", VAL(SIGGRANT,0), S("Grant monitor mode"),
+#endif /* SIGGRANT */
+ "HUP", VAL(SIGHUP,SH_SIGDONE), S("Hangup"),
+ "ILL", VAL(SIGILL,SH_SIGDONE), S("Illegal instruction"),
+#ifdef JOBS
+ "INT", VAL(SIGINT,SH_SIGINTERACTIVE), S("Interrupt"),
+#else
+ "INT", VAL(SIGINT,SH_SIGINTERACTIVE), "",
+#endif /* JOBS */
+#ifdef SIGIO
+ "IO", VAL(SIGIO,SH_SIGDONE), S("IO signal"),
+#endif /* SIGIO */
+#ifdef SIGIOT
+ "IOT", VAL(SIGIOT,SH_SIGDONE), S("Abort"),
+#endif /* SIGIOT */
+#ifdef SIGJVM1
+ "JVM1", VAL(SIGJVM1,SH_SIGIGNORE), S("Special signal used by Java Virtual Machine"),
+#endif /*SIGJVM1 */
+#ifdef SIGJVM2
+ "JVM2", VAL(SIGJVM2,SH_SIGIGNORE), S("Special signal used by Java Virtual Machine"),
+#endif /*SIGJVM2 */
+ "KEYBD", VAL(TRAP(SH_KEYTRAP),0), "",
+#ifdef SIGKILL
+ "KILL", VAL(SIGKILL,0), S("Killed"),
+#endif /* SIGKILL */
+#ifdef SIGLAB
+ "LAB", VAL(SIGLAB,0), S("Security label changed"),
+#endif /* SIGLAB */
+#ifdef SIGLOST
+ "LOST", VAL(SIGLOST,SH_SIGDONE), S("Resources lost"),
+#endif /* SIGLOST */
+#ifdef SIGLWP
+ "LWP", VAL(SIGLWP,SH_SIGIGNORE), S("Special signal used by thread library"),
+#endif /* SIGLWP */
+#ifdef SIGMIGRATE
+ "MIGRATE", VAL(SIGMIGRATE,0), S("Migrate process"),
+#endif /* SIGMIGRATE */
+#ifdef SIGMSG
+ "MSG", VAL(SIGMSG,0), S("Ring buffer input data"),
+#endif /* SIGMSG */
+#ifdef SIGPHONE
+ "PHONE", VAL(SIGPHONE,0), S("Phone interrupt"),
+#endif /* SIGPHONE */
+#ifdef SIGPIPE
+#ifdef JOBS
+ "PIPE", VAL(SIGPIPE,SH_SIGDONE), S("Broken Pipe"),
+#else
+ "PIPE", VAL(SIGPIPE,SH_SIGDONE), "",
+#endif /* JOBS */
+#endif /* SIGPIPE */
+#ifdef SIGPOLL
+ "POLL", VAL(SIGPOLL,SH_SIGDONE), S("Polling alarm"),
+#endif /* SIGPOLL */
+#ifdef SIGPROF
+ "PROF", VAL(SIGPROF,SH_SIGDONE), S("Profiling time alarm"),
+#endif /* SIGPROF */
+#ifdef SIGPRE
+ "PRE", VAL(SIGPRE,SH_SIGDONE), S("Programming exception"),
+#endif /* SIGPRE */
+#ifdef SIGPWR
+# if SIGPWR>0
+ "PWR", VAL(SIGPWR,SH_SIGIGNORE), S("Power fail"),
+# endif
+#endif /* SIGPWR */
+#ifdef SIGQUIT
+ "QUIT", VAL(SIGQUIT,SH_SIGDONE|SH_SIGINTERACTIVE), S("Quit"),
+#endif /* SIGQUIT */
+#ifdef SIGRETRACT
+ "RETRACT", VAL(SIGRETRACT,0), S("Relinquish monitor mode"),
+#endif /* SIGRETRACT */
+#ifdef SIGRTMIN
+ "RTMIN", VAL(SH_SIGRTMIN,SH_SIGRUNTIME), S("Lowest priority realtime signal"),
+#endif /* SIGRTMIN */
+#ifdef SIGRTMAX
+ "RTMAX", VAL(SH_SIGRTMAX,SH_SIGRUNTIME), S("Highest priority realtime signal"),
+#endif /* SIGRTMAX */
+#ifdef SIGSAK
+ "SAK", VAL(SIGSAK,0), S("Secure attention key"),
+#endif /* SIGSAK */
+ "SEGV", VAL(SIGSEGV,0), S("Memory fault"),
+#ifdef SIGSOUND
+ "SOUND", VAL(SIGSOUND,0), S("Sound completed"),
+#endif /* SIGSOUND */
+#ifdef SIGSTOP
+ "STOP", VAL(SIGSTOP,0), S("Stopped (SIGSTOP)"),
+#endif /* SIGSTOP */
+#ifdef SIGSYS
+ "SYS", VAL(SIGSYS,SH_SIGDONE), S("Bad system call"),
+#endif /* SIGSYS */
+ "TERM", VAL(SIGTERM,SH_SIGDONE|SH_SIGINTERACTIVE), S("Terminated"),
+#ifdef SIGTHAW
+ "THAW", VAL(SIGTHAW,SH_SIGIGNORE), S("Special signal used by CPR"),
+#endif /* SIGTHAW */
+#ifdef SIGTINT
+# ifdef JOBS
+ "TINT", VAL(SIGTINT,0), S("Interrupt"),
+# else
+ "TINT", VAL(SIGTINT,0), "",
+# endif /* JOBS */
+#endif /* SIGTINT */
+#ifdef SIGTRAP
+ "TRAP", VAL(SIGTRAP,SH_SIGDONE), S("Trace/BPT trap"),
+#endif /* SIGTRAP */
+#ifdef SIGTSTP
+ "TSTP", VAL(SIGTSTP,0), S("Stopped"),
+#endif /* SIGTSTP */
+#ifdef SIGTTIN
+ "TTIN", VAL(SIGTTIN,0), S("Stopped (SIGTTIN)"),
+#endif /* SIGTTIN */
+#ifdef SIGTTOU
+ "TTOU", VAL(SIGTTOU,0), S("Stopped (SIGTTOU)"),
+#endif /* SIGTTOU */
+#ifdef SIGURG
+ "URG", VAL(SIGURG,SH_SIGIGNORE), S("Socket interrupt"),
+#endif /* SIGURG */
+#ifdef SIGUSR1
+ "USR1", VAL(SIGUSR1,SH_SIGDONE), S("User signal 1"),
+#endif /* SIGUSR1 */
+#ifdef SIGUSR2
+ "USR2", VAL(SIGUSR2,SH_SIGDONE), S("User signal 2"),
+#endif /* SIGUSR2 */
+#ifdef SIGVIRT
+ "VIRT", VAL(SIGVIRT,0), S("Virtual timer alarm"),
+#endif /* SIGVIRT */
+#ifdef SIGVTALRM
+ "VTALRM", VAL(SIGVTALRM,SH_SIGDONE), S("Virtual time alarm"),
+#endif /* SIGVTALRM */
+#ifdef SIGWAITING
+ "WAITING", VAL(SIGWAITING,SH_SIGIGNORE), S("All threads blocked"),
+#endif /* SIGWAITING */
+#ifdef SIGWINCH
+ "WINCH", VAL(SIGWINCH,SH_SIGIGNORE), S("Window size change"),
+#endif /* SIGWINCH */
+#ifdef SIGXCPU
+ "XCPU", VAL(SIGXCPU,SH_SIGDONE|SH_SIGINTERACTIVE), S("Exceeded CPU time limit"),
+#endif /* SIGXCPU */
+#ifdef SIGXFSZ
+ "XFSZ", VAL(SIGXFSZ,SH_SIGDONE|SH_SIGINTERACTIVE), S("Exceeded file size limit"),
+#endif /* SIGXFSZ */
+#ifdef SIGXRES
+ "XRES", VAL(SIGXRES,SH_SIGDONE|SH_SIGINTERACTIVE), S("Exceeded resource control"),
+#endif /* SIGRES */
+ "", 0, 0
+};
diff --git a/src/cmd/ksh93/data/strdata.c b/src/cmd/ksh93/data/strdata.c
new file mode 100644
index 0000000..976c850
--- /dev/null
+++ b/src/cmd/ksh93/data/strdata.c
@@ -0,0 +1,104 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * data for string evaluator library
+ */
+
+#include <ast_standards.h>
+#include "FEATURE/options"
+#include "streval.h"
+
+const unsigned char strval_precedence[35] =
+ /* opcode precedence,assignment */
+{
+ /* DEFAULT */ MAXPREC|NOASSIGN,
+ /* DONE */ 0|NOASSIGN|RASSOC,
+ /* NEQ */ 10|NOASSIGN,
+ /* NOT */ MAXPREC|NOASSIGN,
+ /* MOD */ 14,
+ /* ANDAND */ 6|NOASSIGN|SEQPOINT,
+ /* AND */ 9|NOFLOAT,
+ /* LPAREN */ MAXPREC|NOASSIGN|SEQPOINT,
+ /* RPAREN */ 1|NOASSIGN|RASSOC|SEQPOINT,
+ /* POW */ 14|NOASSIGN|RASSOC,
+ /* TIMES */ 14,
+ /* PLUSPLUS */ 15|NOASSIGN|NOFLOAT|SEQPOINT,
+ /* PLUS */ 13,
+ /* COMMA */ 1|NOASSIGN|SEQPOINT,
+ /* MINUSMINUS */ 15|NOASSIGN|NOFLOAT|SEQPOINT,
+ /* MINUS */ 13,
+ /* DIV */ 14,
+ /* LSHIFT */ 12|NOFLOAT,
+ /* LE */ 11|NOASSIGN,
+ /* LT */ 11|NOASSIGN,
+ /* EQ */ 10|NOASSIGN,
+ /* ASSIGNMENT */ 2|RASSOC,
+ /* COLON */ 0|NOASSIGN,
+ /* RSHIFT */ 12|NOFLOAT,
+ /* GE */ 11|NOASSIGN,
+ /* GT */ 11|NOASSIGN,
+ /* QCOLON */ 3|NOASSIGN|SEQPOINT,
+ /* QUEST */ 3|NOASSIGN|SEQPOINT|RASSOC,
+ /* XOR */ 8|NOFLOAT,
+ /* OROR */ 5|NOASSIGN|SEQPOINT,
+ /* OR */ 7|NOFLOAT,
+ /* DEFAULT */ MAXPREC|NOASSIGN,
+ /* DEFAULT */ MAXPREC|NOASSIGN,
+ /* DEFAULT */ MAXPREC|NOASSIGN,
+ /* DEFAULT */ MAXPREC|NOASSIGN
+};
+
+/*
+ * This is for arithmetic expressions
+ */
+const char strval_states[64] =
+{
+ A_EOF, A_REG, A_REG, A_REG, A_REG, A_REG, A_REG, A_REG,
+ A_REG, 0, 0, A_REG, A_REG, A_REG, A_REG, A_REG,
+ A_REG, A_REG, A_REG, A_REG, A_REG, A_REG, A_REG, A_REG,
+ A_REG, A_REG, A_REG, A_REG, A_REG, A_REG, A_REG, A_REG,
+
+ 0, A_NOT, 0, A_REG, A_REG, A_MOD, A_AND, A_LIT,
+ A_LPAR, A_RPAR, A_TIMES,A_PLUS, A_COMMA,A_MINUS,A_DOT, A_DIV,
+ A_DIG, A_DIG, A_DIG, A_DIG, A_DIG, A_DIG, A_DIG, A_DIG,
+ A_DIG, A_DIG, A_COLON,A_REG, A_LT, A_ASSIGN,A_GT, A_QUEST
+
+};
+
+
+const char e_argcount[] = "%s: function has wrong number of arguments";
+const char e_badnum[] = "%s: bad number";
+const char e_moretokens[] = "%s: more tokens expected";
+const char e_paren[] = "%s: unbalanced parenthesis";
+const char e_badcolon[] = "%s: invalid use of :";
+const char e_divzero[] = "%s: divide by zero";
+const char e_synbad[] = "%s: arithmetic syntax error";
+const char e_notlvalue[] = "%s: assignment requires lvalue";
+const char e_recursive[] = "%s: recursion too deep";
+const char e_questcolon[] = "%s: ':' expected for '?' operator";
+const char e_function[] = "%s: unknown function";
+const char e_incompatible[] = "%s: invalid floating point operation";
+const char e_overflow[] = "%s: overflow exception";
+const char e_domain[] = "%s: domain exception";
+const char e_singularity[] = "%s: singularity exception";
+const char e_charconst[] = "%s: invalid character constant";
+
+#include "FEATURE/math"
diff --git a/src/cmd/ksh93/data/testops.c b/src/cmd/ksh93/data/testops.c
new file mode 100644
index 0000000..fa07d59
--- /dev/null
+++ b/src/cmd/ksh93/data/testops.c
@@ -0,0 +1,174 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * tables for the test builin [[...]] and [...]
+ */
+
+#include <ast.h>
+
+#include "defs.h"
+#include "test.h"
+
+/*
+ * This is the list of binary test and [[...]] operators
+ */
+
+const Shtable_t shtab_testops[] =
+{
+ "!=", TEST_SNE,
+ "-a", TEST_AND,
+ "-ef", TEST_EF,
+ "-eq", TEST_EQ,
+ "-ge", TEST_GE,
+ "-gt", TEST_GT,
+ "-le", TEST_LE,
+ "-lt", TEST_LT,
+ "-ne", TEST_NE,
+ "-nt", TEST_NT,
+ "-o", TEST_OR,
+ "-ot", TEST_OT,
+ "=", TEST_SEQ,
+ "==", TEST_SEQ,
+ "=~", TEST_REP,
+ "<", TEST_SLT,
+ ">", TEST_SGT,
+ "]]", TEST_END,
+ "", 0
+};
+
+const char sh_opttest[] =
+"[-1c?\n@(#)$Id: test (AT&T Research) 2003-03-18 $\n]"
+USAGE_LICENSE
+"[+NAME?test - evaluate expression]"
+"[+DESCRIPTION?\btest\b evaluates expressions and indicates its "
+ "results based on the exit status. Option parsing is not "
+ "performed so that all arguments, including \b--\b are processed "
+ " as operands. The evaluation of the "
+ "expression depends on the number of operands as follows:]{"
+ "[+0?Evaluates to false.]"
+ "[+1?True if argument is not an empty string.]"
+ "[+2?If first operand is \b!\b, the result is True if the second "
+ "operand an empty string. Otherwise, it is evaluated "
+ "as one of the unary expressions defined below. If the "
+ "unary operator is invalid and the second argument is \b--\b,"
+ "then the first argument is processed as an option argument.]"
+ "[+3?If first operand is \b!\b, the result is True if the second "
+ "and third operand evaluated as a unary expression is False. "
+ "Otherwise, the three operands are evaluaged as one of the "
+ "binary expressions listed below.]"
+ "[+4?If first operand is \b!\b, the result is True if the next "
+ "three operands are a valid binary expression that is False.]"
+"}"
+"[If any \afile\a is of the form \b/dev/fd/\b\an\a, then file descriptor "
+ "\an\a is checked.]"
+"[+?Unary expressions can be one of the following:]{"
+ "[+-a \afile\a?True if \afile\a exists, obsolete.]"
+ "[+-b \afile\a?True if \afile\a exists and is a block special file.]"
+ "[+-c \afile\a?True if \afile\a exists and is a character special "
+ "file.]"
+ "[+-d \afile\a?True if \afile\a exists and is a directory.]"
+ "[+-e \afile\a?True if \afile\a exists.]"
+ "[+-f \afile\a?True if \afile\a exists and is a regular file.]"
+ "[+-g \afile\a?True if \afile\a exists and has its set-group-id bit "
+ "set.]"
+ "[+-h \afile\a?True if \afile\a exists and is a symbolic link.]"
+ "[+-k \afile\a?True if \afile\a exists and has its sticky bit on.]"
+#if SHOPT_TEST_L
+ "[+-l \afile\a?True if \afile\a exists and is a symbolic link.]"
+#endif
+ "[+-n \astring\a?True if length of \astring\a is non-zero.]"
+ "[+-o \aoption\a?True if the shell option \aoption\a is enabled.]"
+ "[+-p \afile\a?True if \afile\a exists and is a pipe or fifo.]"
+ "[+-r \afile\a?True if \afile\a exists and is readable.]"
+ "[+-s \afile\a?True if \afile\a exists and has size > 0.]"
+ "[+-t \afildes\a?True if file descriptor number \afildes\a is "
+ "open and is associated with a terminal device.]"
+ "[+-u \afile\a?True if \afile\a exists and has its set-user-id bit "
+ "set.]"
+ "[+-v \avarname\a?True if \avarname\a is a valid variable name that is set.]"
+ "[+-w \afile\a?True if \afile\a exists and is writable.]"
+ "[+-x \afile\a?True if \afile\a exists and is executable. For a "
+ "directory it means that it can be searched.]"
+ "[+-z \astring\a?True if \astring\a is a zero length string.]"
+ "[+-G \afile\a?True if \afile\a exists and group is the effective "
+ "group id of the current process.]"
+ "[+-L \afile\a?True if \afile\a exists and is a symbolic link.]"
+ "[+-N \afile\a?True if \afile\a exists and has been modified since "
+ "it was last read.]"
+ "[+-O \afile\a?True if \afile\a exists and owner is the effective "
+ "user id of the current process.]"
+ "[+-R \avarname\a?True if \avarname\a is a name reference.]"
+ "[+-S \afile\a?True if \afile\a exists and is a socket.]"
+#if SHOPT_FS_3D
+ "[+-V \afile\a?True if \afile\a exists and is a version "
+ "directory.]"
+#endif /* SHOPT_FS_3D */
+"}"
+"[+?Binary expressions can be one of the following:]{"
+ "[+\astring1\a = \astring2\a?True if \astring1\a is equal to "
+ "\astring2\a.]"
+ "[+\astring1\a == \astring2\a?True if \astring1\a is equal to "
+ "\astring2\a.]"
+ "[+\astring1\a != \astring2\a?True if \astring1\a is not equal to "
+ "\astring2\a.]"
+ "[+\anum1\a -eq \anum2\a?True if numerical value of \anum1\a is "
+ "equal to \anum2\a.]"
+ "[+\anum1\a -ne \anum2\a?True if numerical value of \anum1\a is not "
+ "equal to \anum2\a.]"
+ "[+\anum1\a -lt \anum2\a?True if numerical value of \anum1\a is less "
+ "than \anum2\a.]"
+ "[+\anum1\a -le \anum2\a?True if numerical value of \anum1\a is less "
+ "than or equal to \anum2\a.]"
+ "[+\anum1\a -gt \anum2\a?True if numerical value of \anum1\a is "
+ "greater than \anum2\a.]"
+ "[+\anum1\a -ge \anum2\a?True if numerical value of \anum1\a is "
+ "greater than or equal to \anum2\a.]"
+ "[+\afile1\a -nt \afile2\a?True if \afile1\a is newer than \afile2\a "
+ "or \afile2\a does not exist.]"
+ "[+\afile1\a -ot \afile2\a?True if \afile1\a is older than \afile2\a "
+ "or \afile2\a does not exist.]"
+ "[+\afile1\a -ef \afile2\a?True if \afile1\a is another name for "
+ "\afile2\a. This will be true if \afile1\a is a hard link "
+ "or a symbolic link to \afile2\a.]"
+"}"
+"\n"
+"\n[expression]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Indicates that the specified expression is True.]"
+ "[+1?Indicates that the specified expression is False.]"
+ "[+>1?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\blet\b(1), \bexpr\b(1)]"
+;
+
+const char test_opchars[] = "HLNRSVOGCaeohrwxdcbfugkv"
+#if SHOPT_TEST_L
+ "l"
+#endif
+ "psnzt";
+const char e_argument[] = "argument expected";
+const char e_missing[] = "%s missing";
+const char e_badop[] = "%s: unknown operator";
+const char e_tstbegin[] = "[[ ! ";
+const char e_tstend[] = " ]]\n";
diff --git a/src/cmd/ksh93/data/variables.c b/src/cmd/ksh93/data/variables.c
new file mode 100644
index 0000000..3dce5b3
--- /dev/null
+++ b/src/cmd/ksh93/data/variables.c
@@ -0,0 +1,136 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include "FEATURE/options"
+#include "FEATURE/dynamic"
+#include <shell.h>
+#include "shtable.h"
+#include "name.h"
+#include "defs.h"
+#include "variables.h"
+#include "builtins.h"
+
+/*
+ * This is the list of built-in shell variables and default values
+ * and default attributes.
+ */
+
+const struct shtable2 shtab_variables[] =
+{
+ "PATH", 0, (char*)0,
+ "PS1", 0, (char*)0,
+ "PS2", NV_NOFREE, "> ",
+ "IFS", NV_NOFREE, " \t\n",
+ "PWD", 0, (char*)0,
+ "HOME", 0, (char*)0,
+ "MAIL", 0, (char*)0,
+ "REPLY", 0, (char*)0,
+ "SHELL", NV_NOFREE, "/bin/" SH_STD,
+ "EDITOR", 0, (char*)0,
+ "MAILCHECK", NV_NOFREE|NV_INTEGER, (char*)0,
+ "RANDOM", NV_NOFREE|NV_INTEGER, (char*)0,
+ "ENV", NV_NOFREE, (char*)0,
+ "HISTFILE", 0, (char*)0,
+ "HISTSIZE", 0, (char*)0,
+ "HISTEDIT", NV_NOFREE, (char*)0,
+ "HISTCMD", NV_NOFREE|NV_INTEGER, (char*)0,
+ "FCEDIT", NV_NOFREE, &e_defedit[0],
+ "CDPATH", 0, (char*)0,
+ "MAILPATH", 0, (char*)0,
+ "PS3", NV_NOFREE, "#? ",
+ "OLDPWD", 0, (char*)0,
+ "VISUAL", 0, (char*)0,
+ "COLUMNS", 0, (char*)0,
+ "LINES", 0, (char*)0,
+ "PPID", NV_NOFREE|NV_INTEGER, (char*)0,
+ "_", NV_EXPORT, (char*)0,
+ "TMOUT", NV_NOFREE|NV_INTEGER, (char*)0,
+ "SECONDS", NV_NOFREE|NV_INTEGER|NV_DOUBLE, (char*)0,
+ "LINENO", NV_NOFREE|NV_INTEGER, (char*)0,
+ "OPTARG", 0, (char*)0,
+ "OPTIND", NV_NOFREE|NV_INTEGER, (char*)0,
+ "PS4", 0, (char*)0,
+ "FPATH", 0, (char*)0,
+ "LANG", 0, (char*)0,
+ "LC_ALL", 0, (char*)0,
+ "LC_COLLATE", 0, (char*)0,
+ "LC_CTYPE", 0, (char*)0,
+ "LC_MESSAGES", 0, (char*)0,
+ "LC_NUMERIC", 0, (char*)0,
+ "FIGNORE", 0, (char*)0,
+ "KSH_VERSION", 0, (char*)0,
+ "JOBMAX", NV_NOFREE|NV_INTEGER, (char*)0,
+ ".sh", NV_TABLE|NV_NOFREE|NV_NOPRINT, (char*)0,
+ ".sh.edchar", 0, (char*)0,
+ ".sh.edcol", 0, (char*)0,
+ ".sh.edtext", 0, (char*)0,
+ ".sh.edmode", 0, (char*)0,
+ ".sh.name", 0, (char*)0,
+ ".sh.subscript",0, (char*)0,
+ ".sh.value", 0, (char*)0,
+ ".sh.version", NV_NOFREE, (char*)(&e_version[10]),
+ ".sh.dollar", 0, (char*)0,
+ ".sh.match", 0, (char*)0,
+ ".sh.command", 0, (char*)0,
+ ".sh.file", 0, (char*)0,
+ ".sh.fun", 0, (char*)0,
+ ".sh.subshell", NV_INTEGER|NV_SHORT|NV_NOFREE, (char*)0,
+ ".sh.level", 0, (char*)0,
+ ".sh.lineno", NV_INTEGER, (char*)0,
+ ".sh.stats", 0, (char*)0,
+ ".sh.math", 0, (char*)0,
+ ".sh.pool", 0, (char*)0,
+ "SHLVL", NV_INTEGER|NV_NOFREE|NV_EXPORT, (char*)0,
+#if SHOPT_FS_3D
+ "VPATH", 0, (char*)0,
+#endif /* SHOPT_FS_3D */
+#if SHOPT_MULTIBYTE
+ "CSWIDTH", 0, (char*)0,
+#endif /* SHOPT_MULTIBYTE */
+#ifdef apollo
+ "SYSTYPE", 0, (char*)0,
+#endif /* apollo */
+ "", 0, (char*)0
+};
+
+const char *nv_discnames[] = { "get", "set", "append", "unset", "getn", 0 };
+
+#ifdef SHOPT_STATS
+const Shtable_t shtab_stats[] =
+{
+ "arg_cachehits", STAT_ARGHITS,
+ "arg_expands", STAT_ARGEXPAND,
+ "comsubs", STAT_COMSUB,
+ "forks", STAT_FORKS,
+ "funcalls", STAT_FUNCT,
+ "globs", STAT_GLOBS,
+ "linesread", STAT_READS,
+ "nv_cachehit", STAT_NVHITS,
+ "nv_opens", STAT_NVOPEN,
+ "pathsearch", STAT_PATHS,
+ "posixfuncall", STAT_SVFUNCT,
+ "simplecmds", STAT_SCMDS,
+ "spawns", STAT_SPAWN,
+ "subshell", STAT_SUBSHELL
+};
+#endif /* SHOPT_STATS */
+
diff --git a/src/cmd/ksh93/edit/completion.c b/src/cmd/ksh93/edit/completion.c
new file mode 100644
index 0000000..da81f94
--- /dev/null
+++ b/src/cmd/ksh93/edit/completion.c
@@ -0,0 +1,572 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * completion.c - command and file completion for shell editors
+ *
+ */
+
+#include "defs.h"
+#include <ast_wchar.h>
+#include "lexstates.h"
+#include "path.h"
+#include "io.h"
+#include "edit.h"
+#include "history.h"
+
+#if !SHOPT_MULTIBYTE
+#define mbchar(p) (*(unsigned char*)p++)
+#endif
+
+static char *fmtx(const char *string)
+{
+ register const char *cp = string;
+ register int n,c;
+ unsigned char *state = (unsigned char*)sh_lexstates[2];
+ int offset = staktell();
+ if(*cp=='#' || *cp=='~')
+ stakputc('\\');
+ while((c=mbchar(cp)),(c>UCHAR_MAX)||(n=state[c])==0 || n==S_EPAT);
+ if(n==S_EOF && *string!='#')
+ return((char*)string);
+ stakwrite(string,--cp-string);
+ for(string=cp;c=mbchar(cp);string=cp)
+ {
+ if((n=cp-string)==1)
+ {
+ if((n=state[c]) && n!=S_EPAT)
+ stakputc('\\');
+ stakputc(c);
+ }
+ else
+ stakwrite(string,n);
+ }
+ stakputc(0);
+ return(stakptr(offset));
+}
+
+static int charcmp(int a, int b, int nocase)
+{
+ if(nocase)
+ {
+ if(isupper(a))
+ a = tolower(a);
+ if(isupper(b))
+ b = tolower(b);
+ }
+ return(a==b);
+}
+
+/*
+ * overwrites <str> to common prefix of <str> and <newstr>
+ * if <str> is equal to <newstr> returns <str>+strlen(<str>)+1
+ * otherwise returns <str>+strlen(<str>)
+ */
+static char *overlaid(register char *str,register const char *newstr,int nocase)
+{
+ register int c,d;
+ while((c= *(unsigned char *)str) && ((d= *(unsigned char*)newstr++),charcmp(c,d,nocase)))
+ str++;
+ if(*str)
+ *str = 0;
+ else if(*newstr==0)
+ str++;
+ return(str);
+}
+
+
+/*
+ * returns pointer to beginning of expansion and sets type of expansion
+ */
+static char *find_begin(char outbuff[], char *last, int endchar, int *type)
+{
+ register char *cp=outbuff, *bp, *xp;
+ register int c,inquote = 0, inassign=0;
+ int mode=*type;
+ bp = outbuff;
+ *type = 0;
+ while(cp < last)
+ {
+ xp = cp;
+ switch(c= mbchar(cp))
+ {
+ case '\'': case '"':
+ if(!inquote)
+ {
+ inquote = c;
+ bp = xp;
+ break;
+ }
+ if(inquote==c)
+ inquote = 0;
+ break;
+ case '\\':
+ if(inquote != '\'')
+ mbchar(cp);
+ break;
+ case '$':
+ if(inquote == '\'')
+ break;
+ c = *(unsigned char*)cp;
+ if(mode!='*' && (isaletter(c) || c=='{'))
+ {
+ int dot = '.';
+ if(c=='{')
+ {
+ xp = cp;
+ mbchar(cp);
+ c = *(unsigned char*)cp;
+ if(c!='.' && !isaletter(c))
+ break;
+ }
+ else
+ dot = 'a';
+ while(cp < last)
+ {
+ if((c= mbchar(cp)) , c!=dot && !isaname(c))
+ break;
+ }
+ if(cp>=last)
+ {
+ if(c==dot || isaname(c))
+ {
+ *type='$';
+ return(++xp);
+ }
+ if(c!='}')
+ bp = cp;
+ }
+ }
+ else if(c=='(')
+ {
+ *type = mode;
+ xp = find_begin(cp,last,')',type);
+ if(*(cp=xp)!=')')
+ bp = xp;
+ else
+ cp++;
+ }
+ break;
+ case '=':
+ if(!inquote)
+ {
+ bp = cp;
+ inassign = 1;
+ }
+ break;
+ case ':':
+ if(!inquote && inassign)
+ bp = cp;
+ break;
+ case '~':
+ if(*cp=='(')
+ break;
+ /* fall through */
+ default:
+ if(c && c==endchar)
+ return(xp);
+ if(!inquote && ismeta(c))
+ {
+ bp = cp;
+ inassign = 0;
+ }
+ break;
+ }
+ }
+ if(inquote && *bp==inquote)
+ *type = *bp++;
+ return(bp);
+}
+
+/*
+ * file name generation for edit modes
+ * non-zero exit for error, <0 ring bell
+ * don't search back past beginning of the buffer
+ * mode is '*' for inline expansion,
+ * mode is '\' for filename completion
+ * mode is '=' cause files to be listed in select format
+ */
+
+int ed_expand(Edit_t *ep, char outbuff[],int *cur,int *eol,int mode, int count)
+{
+ struct comnod *comptr;
+ struct argnod *ap;
+ register char *out;
+ char *av[2], *begin , *dir=0;
+ int addstar=0, rval=0, var=0, strip=1;
+ int nomarkdirs = !sh_isoption(SH_MARKDIRS);
+ sh_onstate(SH_FCOMPLETE);
+ if(ep->e_nlist)
+ {
+ if(mode=='=' && count>0)
+ {
+ if(count> ep->e_nlist)
+ return(-1);
+ mode = '?';
+ av[0] = ep->e_clist[count-1];
+ av[1] = 0;
+ }
+ else
+ {
+ stakset(ep->e_stkptr,ep->e_stkoff);
+ ep->e_nlist = 0;
+ }
+ }
+ comptr = (struct comnod*)stakalloc(sizeof(struct comnod));
+ ap = (struct argnod*)stakseek(ARGVAL);
+#if SHOPT_MULTIBYTE
+ {
+ register int c = *cur;
+ register genchar *cp;
+ /* adjust cur */
+ cp = (genchar *)outbuff + *cur;
+ c = *cp;
+ *cp = 0;
+ *cur = ed_external((genchar*)outbuff,(char*)stakptr(0));
+ *cp = c;
+ *eol = ed_external((genchar*)outbuff,outbuff);
+ }
+#endif /* SHOPT_MULTIBYTE */
+ out = outbuff + *cur + (sh_isoption(SH_VI)!=0);
+ if(out[-1]=='"' || out[-1]=='\'')
+ {
+ rval = -(sh_isoption(SH_VI)!=0);
+ goto done;
+ }
+ comptr->comtyp = COMSCAN;
+ comptr->comarg = ap;
+ ap->argflag = (ARG_MAC|ARG_EXP);
+ ap->argnxt.ap = 0;
+ ap->argchn.cp = 0;
+ {
+ register int c;
+ char *last = out;
+ c = *(unsigned char*)out;
+ var = mode;
+ begin = out = find_begin(outbuff,last,0,&var);
+ /* addstar set to zero if * should not be added */
+ if(var=='$')
+ {
+ stakputs("${!");
+ stakwrite(out,last-out);
+ stakputs("@}");
+ out = last;
+ }
+ else
+ {
+ addstar = '*';
+ while(out < last)
+ {
+ c = *(unsigned char*)out;
+ if(isexp(c))
+ addstar = 0;
+ if (c == '/')
+ {
+ if(addstar == 0)
+ strip = 0;
+ dir = out+1;
+ }
+ stakputc(c);
+ out++;
+ }
+ }
+ if(mode=='?')
+ mode = '*';
+ if(var!='$' && mode=='\\' && out[-1]!='*')
+ addstar = '*';
+ if(*begin=='~' && !strchr(begin,'/'))
+ addstar = 0;
+ stakputc(addstar);
+ ap = (struct argnod*)stakfreeze(1);
+ }
+ if(mode!='*')
+ sh_onoption(SH_MARKDIRS);
+ {
+ register char **com;
+ char *cp=begin, *left=0, *saveout=".";
+ int nocase=0,narg,cmd_completion=0;
+ register int size='x';
+ while(cp>outbuff && ((size=cp[-1])==' ' || size=='\t'))
+ cp--;
+ if(!var && !strchr(ap->argval,'/') && (((cp==outbuff&&ep->sh->nextprompt==1) || (strchr(";&|(",size)) && (cp==outbuff+1||size=='('||cp[-2]!='>') && *begin!='~' )))
+ {
+ cmd_completion=1;
+ sh_onstate(SH_COMPLETE);
+ }
+ if(ep->e_nlist)
+ {
+ narg = 1;
+ com = av;
+ if(dir)
+ begin += (dir-begin);
+ }
+ else
+ {
+ com = sh_argbuild(ep->sh,&narg,comptr,0);
+ /* special handling for leading quotes */
+ if(begin>outbuff && (begin[-1]=='"' || begin[-1]=='\''))
+ begin--;
+ }
+ sh_offstate(SH_COMPLETE);
+ /* allow a search to be aborted */
+ if(ep->sh->trapnote&SH_SIGSET)
+ {
+ rval = -1;
+ goto done;
+ }
+ /* match? */
+ if (*com==0 || (narg <= 1 && (strcmp(ap->argval,*com)==0) || (addstar && com[0][strlen(*com)-1]=='*')))
+ {
+ rval = -1;
+ goto done;
+ }
+ if(mode=='=')
+ {
+ if (strip && !cmd_completion)
+ {
+ register char **ptrcom;
+ for(ptrcom=com;*ptrcom;ptrcom++)
+ /* trim directory prefix */
+ *ptrcom = path_basename(*ptrcom);
+ }
+ sfputc(sfstderr,'\n');
+ sh_menu(sfstderr,narg,com);
+ sfsync(sfstderr);
+ ep->e_nlist = narg;
+ ep->e_clist = com;
+ goto done;
+ }
+ /* see if there is enough room */
+ size = *eol - (out-begin);
+ if(mode=='\\')
+ {
+ int c;
+ if(dir)
+ {
+ c = *dir;
+ *dir = 0;
+ saveout = begin;
+ }
+ if(saveout=astconf("PATH_ATTRIBUTES",saveout,(char*)0))
+ nocase = (strchr(saveout,'c')!=0);
+ if(dir)
+ *dir = c;
+ /* just expand until name is unique */
+ size += strlen(*com);
+ }
+ else
+ {
+ size += narg;
+ {
+ char **savcom = com;
+ while (*com)
+ size += strlen(cp=fmtx(*com++));
+ com = savcom;
+ }
+ }
+ /* see if room for expansion */
+ if(outbuff+size >= &outbuff[MAXLINE])
+ {
+ com[0] = ap->argval;
+ com[1] = 0;
+ }
+ /* save remainder of the buffer */
+ if(*out)
+ left=stakcopy(out);
+ if(cmd_completion && mode=='\\')
+ out = strcopy(begin,path_basename(cp= *com++));
+ else if(mode=='*')
+ {
+ if(ep->e_nlist && dir && var)
+ {
+ if(*cp==var)
+ cp++;
+ else
+ *begin++ = var;
+ out = strcopy(begin,cp);
+ var = 0;
+ }
+ else
+ out = strcopy(begin,fmtx(*com));
+ com++;
+ }
+ else
+ out = strcopy(begin,*com++);
+ if(mode=='\\')
+ {
+ saveout= ++out;
+ while (*com && *begin)
+ {
+ if(cmd_completion)
+ out = overlaid(begin,path_basename(*com++),nocase);
+ else
+ out = overlaid(begin,*com++,nocase);
+ }
+ mode = (out==saveout);
+ if(out[-1]==0)
+ out--;
+ if(mode && out[-1]!='/')
+ {
+ if(cmd_completion)
+ {
+ Namval_t *np;
+ /* add as tracked alias */
+ Pathcomp_t *pp;
+ if(*cp=='/' && (pp=path_dirfind(ep->sh->pathlist,cp,'/')) && (np=nv_search(begin,ep->sh->track_tree,NV_ADD)))
+ path_alias(np,pp);
+ out = strcopy(begin,cp);
+ }
+ /* add quotes if necessary */
+ if((cp=fmtx(begin))!=begin)
+ out = strcopy(begin,cp);
+ if(var=='$' && begin[-1]=='{')
+ *out = '}';
+ else
+ *out = ' ';
+ *++out = 0;
+ }
+ else if((cp=fmtx(begin))!=begin)
+ {
+ out = strcopy(begin,cp);
+ if(out[-1] =='"' || out[-1]=='\'')
+ *--out = 0;
+ }
+ if(*begin==0)
+ ed_ringbell();
+ }
+ else
+ {
+ while (*com)
+ {
+ *out++ = ' ';
+ out = strcopy(out,fmtx(*com++));
+ }
+ }
+ if(ep->e_nlist)
+ {
+ cp = com[-1];
+ if(cp[strlen(cp)-1]!='/')
+ {
+ if(var=='$' && begin[-1]=='{')
+ *out = '}';
+ else
+ *out = ' ';
+ out++;
+ }
+ else if(out[-1] =='"' || out[-1]=='\'')
+ out--;
+ *out = 0;
+ }
+ *cur = (out-outbuff);
+ /* restore rest of buffer */
+ if(left)
+ out = strcopy(out,left);
+ *eol = (out-outbuff);
+ }
+ done:
+ sh_offstate(SH_FCOMPLETE);
+ if(!ep->e_nlist)
+ stakset(ep->e_stkptr,ep->e_stkoff);
+ if(nomarkdirs)
+ sh_offoption(SH_MARKDIRS);
+#if SHOPT_MULTIBYTE
+ {
+ register int c,n=0;
+ /* first re-adjust cur */
+ c = outbuff[*cur];
+ outbuff[*cur] = 0;
+ for(out=outbuff; *out;n++)
+ mbchar(out);
+ outbuff[*cur] = c;
+ *cur = n;
+ outbuff[*eol+1] = 0;
+ *eol = ed_internal(outbuff,(genchar*)outbuff);
+ }
+#endif /* SHOPT_MULTIBYTE */
+ return(rval);
+}
+
+/*
+ * look for edit macro named _i
+ * if found, puts the macro definition into lookahead buffer and returns 1
+ */
+int ed_macro(Edit_t *ep, register int i)
+{
+ register char *out;
+ Namval_t *np;
+ genchar buff[LOOKAHEAD+1];
+ if(i != '@')
+ ep->e_macro[1] = i;
+ /* undocumented feature, macros of the form <ESC>[c evoke alias __c */
+ if(i=='_')
+ ep->e_macro[2] = ed_getchar(ep,1);
+ else
+ ep->e_macro[2] = 0;
+ if (isalnum(i)&&(np=nv_search(ep->e_macro,ep->sh->alias_tree,HASH_SCOPE))&&(out=nv_getval(np)))
+ {
+#if SHOPT_MULTIBYTE
+ /* copy to buff in internal representation */
+ int c = 0;
+ if( strlen(out) > LOOKAHEAD )
+ {
+ c = out[LOOKAHEAD];
+ out[LOOKAHEAD] = 0;
+ }
+ i = ed_internal(out,buff);
+ if(c)
+ out[LOOKAHEAD] = c;
+#else
+ strncpy((char*)buff,out,LOOKAHEAD);
+ buff[LOOKAHEAD] = 0;
+ i = strlen((char*)buff);
+#endif /* SHOPT_MULTIBYTE */
+ while(i-- > 0)
+ ed_ungetchar(ep,buff[i]);
+ return(1);
+ }
+ return(0);
+}
+
+/*
+ * Enter the fc command on the current history line
+ */
+int ed_fulledit(Edit_t *ep)
+{
+ register char *cp;
+ if(!shgd->hist_ptr)
+ return(-1);
+ /* use EDITOR on current command */
+ if(ep->e_hline == ep->e_hismax)
+ {
+ if(ep->e_eol<0)
+ return(-1);
+#if SHOPT_MULTIBYTE
+ ep->e_inbuf[ep->e_eol+1] = 0;
+ ed_external(ep->e_inbuf, (char *)ep->e_inbuf);
+#endif /* SHOPT_MULTIBYTE */
+ sfwrite(shgd->hist_ptr->histfp,(char*)ep->e_inbuf,ep->e_eol+1);
+ sh_onstate(SH_HISTORY);
+ hist_flush(shgd->hist_ptr);
+ }
+ cp = strcopy((char*)ep->e_inbuf,e_runvi);
+ cp = strcopy(cp, fmtbase((long)ep->e_hline,10,0));
+ ep->e_eol = ((unsigned char*)cp - (unsigned char*)ep->e_inbuf)-(sh_isoption(SH_VI)!=0);
+ return(0);
+}
diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c
new file mode 100644
index 0000000..b050f60
--- /dev/null
+++ b/src/cmd/ksh93/edit/edit.c
@@ -0,0 +1,1806 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * edit.c - common routines for vi and emacs one line editors in shell
+ *
+ * David Korn P.D. Sullivan
+ * AT&T Labs
+ *
+ * Coded April 1983.
+ */
+
+#include <ast.h>
+#include <errno.h>
+#include <ccode.h>
+#include "FEATURE/options"
+#include "FEATURE/time"
+#include "FEATURE/cmds"
+#ifdef _hdr_utime
+# include <utime.h>
+# include <ls.h>
+#endif
+
+#if KSHELL
+# include "defs.h"
+# include "variables.h"
+#else
+# include <ctype.h>
+ extern char ed_errbuf[];
+ char e_version[] = "\n@(#)$Id: Editlib version 1993-12-28 r $\0\n";
+#endif /* KSHELL */
+#include "io.h"
+#include "terminal.h"
+#include "history.h"
+#include "edit.h"
+
+static char CURSOR_UP[20] = { ESC, '[', 'A', 0 };
+static char KILL_LINE[20] = { ESC, '[', 'J', 0 };
+
+
+
+#if SHOPT_MULTIBYTE
+# define is_cntrl(c) ((c<=STRIP) && iscntrl(c))
+# define is_print(c) ((c&~STRIP) || isprint(c))
+#else
+# define is_cntrl(c) iscntrl(c)
+# define is_print(c) isprint(c)
+#endif
+
+#if (CC_NATIVE == CC_ASCII)
+# define printchar(c) ((c) ^ ('A'-cntl('A')))
+#else
+ static int printchar(int c)
+ {
+ switch(c)
+ {
+
+ case cntl('A'): return('A');
+ case cntl('B'): return('B');
+ case cntl('C'): return('C');
+ case cntl('D'): return('D');
+ case cntl('E'): return('E');
+ case cntl('F'): return('F');
+ case cntl('G'): return('G');
+ case cntl('H'): return('H');
+ case cntl('I'): return('I');
+ case cntl('J'): return('J');
+ case cntl('K'): return('K');
+ case cntl('L'): return('L');
+ case cntl('M'): return('M');
+ case cntl('N'): return('N');
+ case cntl('O'): return('O');
+ case cntl('P'): return('P');
+ case cntl('Q'): return('Q');
+ case cntl('R'): return('R');
+ case cntl('S'): return('S');
+ case cntl('T'): return('T');
+ case cntl('U'): return('U');
+ case cntl('V'): return('V');
+ case cntl('W'): return('W');
+ case cntl('X'): return('X');
+ case cntl('Y'): return('Y');
+ case cntl('Z'): return('Z');
+ case cntl(']'): return(']');
+ case cntl('['): return('[');
+ }
+ return('?');
+ }
+#endif
+#define MINWINDOW 15 /* minimum width window */
+#define DFLTWINDOW 80 /* default window width */
+#define RAWMODE 1
+#define ALTMODE 2
+#define ECHOMODE 3
+#define SYSERR -1
+
+#if SHOPT_OLDTERMIO
+# undef tcgetattr
+# undef tcsetattr
+#endif /* SHOPT_OLDTERMIO */
+
+#ifdef RT
+# define VENIX 1
+#endif /* RT */
+
+
+#ifdef _hdr_sgtty
+# ifdef TIOCGETP
+ static int l_mask;
+ static struct tchars l_ttychars;
+ static struct ltchars l_chars;
+ static char l_changed; /* set if mode bits changed */
+# define L_CHARS 4
+# define T_CHARS 2
+# define L_MASK 1
+# endif /* TIOCGETP */
+#endif /* _hdr_sgtty */
+
+#if KSHELL
+ static int keytrap(Edit_t *,char*, int, int, int);
+#else
+ Edit_t editb;
+#endif /* KSHELL */
+
+
+#ifndef _POSIX_DISABLE
+# define _POSIX_DISABLE 0
+#endif
+
+#ifdef future
+ static int compare(const char*, const char*, int);
+#endif /* future */
+#if SHOPT_VSH || SHOPT_ESH
+# define ttyparm (ep->e_ttyparm)
+# define nttyparm (ep->e_nttyparm)
+ static const char bellchr[] = "\a"; /* bell char */
+#endif /* SHOPT_VSH || SHOPT_ESH */
+
+
+/*
+ * This routine returns true if fd refers to a terminal
+ * This should be equivalent to isatty
+ */
+int tty_check(int fd)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ struct termios tty;
+ ep->e_savefd = -1;
+ return(tty_get(fd,&tty)==0);
+}
+
+/*
+ * Get the current terminal attributes
+ * This routine remembers the attributes and just returns them if it
+ * is called again without an intervening tty_set()
+ */
+
+int tty_get(register int fd, register struct termios *tty)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ if(fd == ep->e_savefd)
+ *tty = ep->e_savetty;
+ else
+ {
+ while(tcgetattr(fd,tty) == SYSERR)
+ {
+ if(errno !=EINTR)
+ return(SYSERR);
+ errno = 0;
+ }
+ /* save terminal settings if in cannonical state */
+ if(ep->e_raw==0)
+ {
+ ep->e_savetty = *tty;
+ ep->e_savefd = fd;
+ }
+ }
+ return(0);
+}
+
+/*
+ * Set the terminal attributes
+ * If fd<0, then current attributes are invalidated
+ */
+
+int tty_set(int fd, int action, struct termios *tty)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ if(fd >=0)
+ {
+#ifdef future
+ if(ep->e_savefd>=0 && compare(&ep->e_savetty,tty,sizeof(struct termios)))
+ return(0);
+#endif
+ while(tcsetattr(fd, action, tty) == SYSERR)
+ {
+ if(errno !=EINTR)
+ return(SYSERR);
+ errno = 0;
+ }
+ ep->e_savetty = *tty;
+ }
+ ep->e_savefd = fd;
+ return(0);
+}
+
+#if SHOPT_ESH || SHOPT_VSH
+/*{ TTY_COOKED( fd )
+ *
+ * This routine will set the tty in cooked mode.
+ * It is also called by error.done().
+ *
+}*/
+
+void tty_cooked(register int fd)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ ep->e_keytrap = 0;
+ if(ep->e_raw==0)
+ return;
+ if(fd < 0)
+ fd = ep->e_savefd;
+#ifdef L_MASK
+ /* restore flags */
+ if(l_changed&L_MASK)
+ ioctl(fd,TIOCLSET,&l_mask);
+ if(l_changed&T_CHARS)
+ /* restore alternate break character */
+ ioctl(fd,TIOCSETC,&l_ttychars);
+ if(l_changed&L_CHARS)
+ /* restore alternate break character */
+ ioctl(fd,TIOCSLTC,&l_chars);
+ l_changed = 0;
+#endif /* L_MASK */
+ /*** don't do tty_set unless ttyparm has valid data ***/
+ if(tty_set(fd, TCSANOW, &ttyparm) == SYSERR)
+ return;
+ ep->e_raw = 0;
+ return;
+}
+
+/*{ TTY_RAW( fd )
+ *
+ * This routine will set the tty in raw mode.
+ *
+}*/
+
+int tty_raw(register int fd, int echomode)
+{
+ int echo = echomode;
+#ifdef L_MASK
+ struct ltchars lchars;
+#endif /* L_MASK */
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ if(ep->e_raw==RAWMODE)
+ return(echo?-1:0);
+ else if(ep->e_raw==ECHOMODE)
+ return(echo?0:-1);
+#if !SHOPT_RAWONLY
+ if(ep->e_raw != ALTMODE)
+#endif /* SHOPT_RAWONLY */
+ {
+ if(tty_get(fd,&ttyparm) == SYSERR)
+ return(-1);
+ }
+#if L_MASK || VENIX
+ if(ttyparm.sg_flags&LCASE)
+ return(-1);
+ if(!(ttyparm.sg_flags&ECHO))
+ {
+ if(!echomode)
+ return(-1);
+ echo = 0;
+ }
+ nttyparm = ttyparm;
+ if(!echo)
+ nttyparm.sg_flags &= ~(ECHO | TBDELAY);
+# ifdef CBREAK
+ nttyparm.sg_flags |= CBREAK;
+# else
+ nttyparm.sg_flags |= RAW;
+# endif /* CBREAK */
+ ep->e_erase = ttyparm.sg_erase;
+ ep->e_kill = ttyparm.sg_kill;
+ ep->e_eof = cntl('D');
+ ep->e_werase = cntl('W');
+ ep->e_lnext = cntl('V');
+ if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR )
+ return(-1);
+ ep->e_ttyspeed = (ttyparm.sg_ospeed>=B1200?FAST:SLOW);
+# ifdef TIOCGLTC
+ /* try to remove effect of ^V and ^Y and ^O */
+ if(ioctl(fd,TIOCGLTC,&l_chars) != SYSERR)
+ {
+ lchars = l_chars;
+ lchars.t_lnextc = -1;
+ lchars.t_flushc = -1;
+ lchars.t_dsuspc = -1; /* no delayed stop process signal */
+ if(ioctl(fd,TIOCSLTC,&lchars) != SYSERR)
+ l_changed |= L_CHARS;
+ }
+# endif /* TIOCGLTC */
+#else
+ if (!(ttyparm.c_lflag & ECHO ))
+ {
+ if(!echomode)
+ return(-1);
+ echo = 0;
+ }
+# ifdef FLUSHO
+ ttyparm.c_lflag &= ~FLUSHO;
+# endif /* FLUSHO */
+ nttyparm = ttyparm;
+# ifndef u370
+ nttyparm.c_iflag &= ~(IGNPAR|PARMRK|INLCR|IGNCR|ICRNL);
+ nttyparm.c_iflag |= BRKINT;
+# else
+ nttyparm.c_iflag &=
+ ~(IGNBRK|PARMRK|INLCR|IGNCR|ICRNL|INPCK);
+ nttyparm.c_iflag |= (BRKINT|IGNPAR);
+# endif /* u370 */
+ if(echo)
+ nttyparm.c_lflag &= ~(ICANON|ISIG);
+ else
+ nttyparm.c_lflag &= ~(ICANON|ISIG|ECHO|ECHOK);
+ nttyparm.c_cc[VTIME] = 0;
+ nttyparm.c_cc[VMIN] = 1;
+# ifdef VREPRINT
+ nttyparm.c_cc[VREPRINT] = _POSIX_DISABLE;
+# endif /* VREPRINT */
+# ifdef VDISCARD
+ nttyparm.c_cc[VDISCARD] = _POSIX_DISABLE;
+# endif /* VDISCARD */
+# ifdef VDSUSP
+ nttyparm.c_cc[VDSUSP] = _POSIX_DISABLE;
+# endif /* VDSUSP */
+# ifdef VWERASE
+ if(ttyparm.c_cc[VWERASE] == _POSIX_DISABLE)
+ ep->e_werase = cntl('W');
+ else
+ ep->e_werase = nttyparm.c_cc[VWERASE];
+ nttyparm.c_cc[VWERASE] = _POSIX_DISABLE;
+# else
+ ep->e_werase = cntl('W');
+# endif /* VWERASE */
+# ifdef VLNEXT
+ if(ttyparm.c_cc[VLNEXT] == _POSIX_DISABLE )
+ ep->e_lnext = cntl('V');
+ else
+ ep->e_lnext = nttyparm.c_cc[VLNEXT];
+ nttyparm.c_cc[VLNEXT] = _POSIX_DISABLE;
+# else
+ ep->e_lnext = cntl('V');
+# endif /* VLNEXT */
+ ep->e_intr = ttyparm.c_cc[VINTR];
+ ep->e_eof = ttyparm.c_cc[VEOF];
+ ep->e_erase = ttyparm.c_cc[VERASE];
+ ep->e_kill = ttyparm.c_cc[VKILL];
+ if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR )
+ return(-1);
+ ep->e_ttyspeed = (cfgetospeed(&ttyparm)>=B1200?FAST:SLOW);
+#endif
+ ep->e_raw = (echomode?ECHOMODE:RAWMODE);
+ return(0);
+}
+
+#if !SHOPT_RAWONLY
+
+/*
+ *
+ * Get tty parameters and make ESC and '\r' wakeup characters.
+ *
+ */
+
+# ifdef TIOCGETC
+int tty_alt(register int fd)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ int mask;
+ struct tchars ttychars;
+ switch(ep->e_raw)
+ {
+ case ECHOMODE:
+ return(-1);
+ case ALTMODE:
+ return(0);
+ case RAWMODE:
+ tty_cooked(fd);
+ }
+ l_changed = 0;
+ if( ep->e_ttyspeed == 0)
+ {
+ if((tty_get(fd,&ttyparm) != SYSERR))
+ ep->e_ttyspeed = (ttyparm.sg_ospeed>=B1200?FAST:SLOW);
+ ep->e_raw = ALTMODE;
+ }
+ if(ioctl(fd,TIOCGETC,&l_ttychars) == SYSERR)
+ return(-1);
+ if(ioctl(fd,TIOCLGET,&l_mask)==SYSERR)
+ return(-1);
+ ttychars = l_ttychars;
+ mask = LCRTBS|LCRTERA|LCTLECH|LPENDIN|LCRTKIL;
+ if((l_mask|mask) != l_mask)
+ l_changed = L_MASK;
+ if(ioctl(fd,TIOCLBIS,&mask)==SYSERR)
+ return(-1);
+ if(ttychars.t_brkc!=ESC)
+ {
+ ttychars.t_brkc = ESC;
+ l_changed |= T_CHARS;
+ if(ioctl(fd,TIOCSETC,&ttychars) == SYSERR)
+ return(-1);
+ }
+ return(0);
+}
+# else
+# ifndef PENDIN
+# define PENDIN 0
+# endif /* PENDIN */
+# ifndef IEXTEN
+# define IEXTEN 0
+# endif /* IEXTEN */
+
+int tty_alt(register int fd)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ switch(ep->e_raw)
+ {
+ case ECHOMODE:
+ return(-1);
+ case ALTMODE:
+ return(0);
+ case RAWMODE:
+ tty_cooked(fd);
+ }
+ if((tty_get(fd, &ttyparm)==SYSERR) || (!(ttyparm.c_lflag&ECHO)))
+ return(-1);
+# ifdef FLUSHO
+ ttyparm.c_lflag &= ~FLUSHO;
+# endif /* FLUSHO */
+ nttyparm = ttyparm;
+ ep->e_eof = ttyparm.c_cc[VEOF];
+# ifdef ECHOCTL
+ /* escape character echos as ^[ */
+ nttyparm.c_lflag |= (ECHOE|ECHOK|ECHOCTL|PENDIN|IEXTEN);
+ nttyparm.c_cc[VEOL] = ESC;
+# else
+ /* switch VEOL2 and EOF, since EOF isn't echo'd by driver */
+ nttyparm.c_lflag |= (ECHOE|ECHOK);
+ nttyparm.c_cc[VEOF] = ESC; /* make ESC the eof char */
+# ifdef VEOL2
+ nttyparm.c_iflag &= ~(IGNCR|ICRNL);
+ nttyparm.c_iflag |= INLCR;
+ nttyparm.c_cc[VEOL] = '\r'; /* make CR an eol char */
+ nttyparm.c_cc[VEOL2] = ep->e_eof; /* make EOF an eol char */
+# else
+ nttyparm.c_cc[VEOL] = ep->e_eof; /* make EOF an eol char */
+# endif /* VEOL2 */
+# endif /* ECHOCTL */
+# ifdef VREPRINT
+ nttyparm.c_cc[VREPRINT] = _POSIX_DISABLE;
+# endif /* VREPRINT */
+# ifdef VDISCARD
+ nttyparm.c_cc[VDISCARD] = _POSIX_DISABLE;
+# endif /* VDISCARD */
+# ifdef VWERASE
+ if(ttyparm.c_cc[VWERASE] == _POSIX_DISABLE)
+ nttyparm.c_cc[VWERASE] = cntl('W');
+ ep->e_werase = nttyparm.c_cc[VWERASE];
+# else
+ ep->e_werase = cntl('W');
+# endif /* VWERASE */
+# ifdef VLNEXT
+ if(ttyparm.c_cc[VLNEXT] == _POSIX_DISABLE )
+ nttyparm.c_cc[VLNEXT] = cntl('V');
+ ep->e_lnext = nttyparm.c_cc[VLNEXT];
+# else
+ ep->e_lnext = cntl('V');
+# endif /* VLNEXT */
+ ep->e_erase = ttyparm.c_cc[VERASE];
+ ep->e_kill = ttyparm.c_cc[VKILL];
+ if( tty_set(fd, TCSADRAIN, &nttyparm) == SYSERR )
+ return(-1);
+ ep->e_ttyspeed = (cfgetospeed(&ttyparm)>=B1200?FAST:SLOW);
+ ep->e_raw = ALTMODE;
+ return(0);
+}
+
+# endif /* TIOCGETC */
+#endif /* SHOPT_RAWONLY */
+
+/*
+ * ED_WINDOW()
+ *
+ * return the window size
+ */
+int ed_window(void)
+{
+ int rows,cols;
+ register char *cp = nv_getval(COLUMNS);
+ if(cp)
+ cols = (int)strtol(cp, (char**)0, 10)-1;
+ else
+ {
+ astwinsize(2,&rows,&cols);
+ if(--cols <0)
+ cols = DFLTWINDOW-1;
+ }
+ if(cols < MINWINDOW)
+ cols = MINWINDOW;
+ else if(cols > MAXWINDOW)
+ cols = MAXWINDOW;
+ return(cols);
+}
+
+/* E_FLUSH()
+ *
+ * Flush the output buffer.
+ *
+ */
+
+void ed_flush(Edit_t *ep)
+{
+ register int n = ep->e_outptr-ep->e_outbase;
+ register int fd = ERRIO;
+ if(n<=0)
+ return;
+ write(fd,ep->e_outbase,(unsigned)n);
+ ep->e_outptr = ep->e_outbase;
+}
+
+/*
+ * send the bell character ^G to the terminal
+ */
+
+void ed_ringbell(void)
+{
+ write(ERRIO,bellchr,1);
+}
+
+/*
+ * send a carriage return line feed to the terminal
+ */
+
+void ed_crlf(register Edit_t *ep)
+{
+#ifdef cray
+ ed_putchar(ep,'\r');
+#endif /* cray */
+#ifdef u370
+ ed_putchar(ep,'\r');
+#endif /* u370 */
+#ifdef VENIX
+ ed_putchar(ep,'\r');
+#endif /* VENIX */
+ ed_putchar(ep,'\n');
+ ed_flush(ep);
+}
+
+/* ED_SETUP( max_prompt_size )
+ *
+ * This routine sets up the prompt string
+ * The following is an unadvertised feature.
+ * Escape sequences in the prompt can be excluded from the calculated
+ * prompt length. This is accomplished as follows:
+ * - if the prompt string starts with "%\r, or contains \r%\r", where %
+ * represents any char, then % is taken to be the quote character.
+ * - strings enclosed by this quote character, and the quote character,
+ * are not counted as part of the prompt length.
+ */
+
+void ed_setup(register Edit_t *ep, int fd, int reedit)
+{
+ Shell_t *shp = ep->sh;
+ register char *pp;
+ register char *last, *prev;
+ char *ppmax;
+ int myquote = 0, n;
+ register int qlen = 1, qwid;
+ char inquote = 0;
+ ep->e_fd = fd;
+ ep->e_multiline = sh_isoption(SH_MULTILINE)!=0;
+#ifdef SIGWINCH
+ if(!(shp->sigflag[SIGWINCH]&SH_SIGFAULT))
+ {
+ signal(SIGWINCH,sh_fault);
+ shp->sigflag[SIGWINCH] |= SH_SIGFAULT;
+ }
+ pp = shp->st.trapcom[SIGWINCH];
+ shp->st.trapcom[SIGWINCH] = 0;
+ sh_fault(SIGWINCH);
+ shp->st.trapcom[SIGWINCH] = pp;
+ ep->sh->winch = 0;
+#endif
+#if SHOPT_EDPREDICT
+ ep->hlist = 0;
+ ep->nhlist = 0;
+ ep->hoff = 0;
+#endif /* SHOPT_EDPREDICT */
+#if KSHELL
+ ep->e_stkptr = stakptr(0);
+ ep->e_stkoff = staktell();
+ if(!(last = shp->prompt))
+ last = "";
+ shp->prompt = 0;
+#else
+ last = ep->e_prbuff;
+#endif /* KSHELL */
+ if(shp->gd->hist_ptr)
+ {
+ register History_t *hp = shp->gd->hist_ptr;
+ ep->e_hismax = hist_max(hp);
+ ep->e_hismin = hist_min(hp);
+ }
+ else
+ {
+ ep->e_hismax = ep->e_hismin = ep->e_hloff = 0;
+ }
+ ep->e_hline = ep->e_hismax;
+ if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
+ ep->e_wsize = MAXLINE;
+ else
+ ep->e_wsize = ed_window()-2;
+ ep->e_winsz = ep->e_wsize+2;
+ ep->e_crlf = 1;
+ ep->e_plen = 0;
+ pp = ep->e_prompt;
+ ppmax = pp+PRSIZE-1;
+ *pp++ = '\r';
+ {
+ register int c;
+ while(prev = last, c = mbchar(last)) switch(c)
+ {
+ case ESC:
+ {
+ int skip=0;
+ ep->e_crlf = 0;
+ *pp++ = c;
+ for(n=1; c = *last++; n++)
+ {
+ if(pp < ppmax)
+ *pp++ = c;
+ if(c=='\a' || c==ESC || c=='\r')
+ break;
+ if(skip || (c>='0' && c<='9'))
+ {
+ skip = 0;
+ continue;
+ }
+ if(n>1 && c==';')
+ skip = 1;
+ else if(n>2 || (c!= '[' && c!= ']'))
+ break;
+ }
+ if(c==0 || c==ESC || c=='\r')
+ last--;
+ qlen += (n+1);
+ break;
+ }
+ case '\b':
+ if(pp>ep->e_prompt+1)
+ pp--;
+ break;
+ case '\r':
+ if(pp == (ep->e_prompt+2)) /* quote char */
+ myquote = *(pp-1);
+ /*FALLTHROUGH*/
+
+ case '\n':
+ /* start again */
+ ep->e_crlf = 1;
+ qlen = 1;
+ inquote = 0;
+ pp = ep->e_prompt+1;
+ break;
+
+ case '\t':
+ /* expand tabs */
+ while((pp-ep->e_prompt)%TABSIZE)
+ {
+ if(pp >= ppmax)
+ break;
+ *pp++ = ' ';
+ }
+ break;
+
+ case '\a':
+ /* cut out bells */
+ break;
+
+ default:
+ if(c==myquote)
+ {
+ qlen += inquote;
+ inquote ^= 1;
+ }
+ if(pp < ppmax)
+ {
+ if(inquote)
+ qlen++;
+ else if(!is_print(c))
+ ep->e_crlf = 0;
+ if((qwid = last - prev) > 1)
+ qlen += qwid - mbwidth(c);
+ while(prev < last && pp < ppmax)
+ *pp++ = *prev++;
+ }
+ break;
+ }
+ }
+ if(pp-ep->e_prompt > qlen)
+ ep->e_plen = pp - ep->e_prompt - qlen;
+ *pp = 0;
+ if(!ep->e_multiline && (ep->e_wsize -= ep->e_plen) < 7)
+ {
+ register int shift = 7-ep->e_wsize;
+ ep->e_wsize = 7;
+ pp = ep->e_prompt+1;
+ strcpy(pp,pp+shift);
+ ep->e_plen -= shift;
+ last[-ep->e_plen-2] = '\r';
+ }
+ sfsync(sfstderr);
+ if(fd == sffileno(sfstderr))
+ {
+ /* can't use output buffer when reading from stderr */
+ static char *buff;
+ if(!buff)
+ buff = (char*)malloc(MAXLINE);
+ ep->e_outbase = ep->e_outptr = buff;
+ ep->e_outlast = ep->e_outptr + MAXLINE;
+ return;
+ }
+ qlen = sfset(sfstderr,SF_READ,0);
+ /* make sure SF_READ not on */
+ ep->e_outbase = ep->e_outptr = (char*)sfreserve(sfstderr,SF_UNBOUND,SF_LOCKR);
+ ep->e_outlast = ep->e_outptr + sfvalue(sfstderr);
+ if(qlen)
+ sfset(sfstderr,SF_READ,1);
+ sfwrite(sfstderr,ep->e_outptr,0);
+ ep->e_eol = reedit;
+ if(ep->e_multiline)
+ {
+#ifdef _cmd_tput
+ char *term;
+ if(!ep->e_term)
+ ep->e_term = nv_search("TERM",shp->var_tree,0);
+ if(ep->e_term && (term=nv_getval(ep->e_term)) && strlen(term)<sizeof(ep->e_termname) && strcmp(term,ep->e_termname))
+ {
+ sh_trap(".sh.subscript=$(tput cuu1 2>/dev/null)",0);
+ if(pp=nv_getval(SH_SUBSCRNOD))
+ strncpy(CURSOR_UP,pp,sizeof(CURSOR_UP)-1);
+ nv_unset(SH_SUBSCRNOD);
+ strcpy(ep->e_termname,term);
+ }
+#endif
+ ep->e_wsize = MAXLINE - (ep->e_plen+1);
+ }
+ if(ep->e_default && (pp = nv_getval(ep->e_default)))
+ {
+ n = strlen(pp);
+ if(n > LOOKAHEAD)
+ n = LOOKAHEAD;
+ ep->e_lookahead = n;
+ while(n-- > 0)
+ ep->e_lbuf[n] = *pp++;
+ ep->e_default = 0;
+ }
+}
+
+static void ed_putstring(register Edit_t *ep, const char *str)
+{
+ register int c;
+ while(c = *str++)
+ ed_putchar(ep,c);
+}
+
+static void ed_nputchar(register Edit_t *ep, int n, int c)
+{
+ while(n-->0)
+ ed_putchar(ep,c);
+}
+
+/*
+ * Do read, restart on interrupt unless SH_SIGSET or SH_SIGTRAP is set
+ * Use sfpkrd() to poll() or select() to wait for input if possible
+ * Unfortunately, systems that get interrupted from slow reads update
+ * this access time for for the terminal (in violation of POSIX).
+ * The fixtime() macro, resets the time to the time at entry in
+ * this case. This is not necessary for systems that can handle
+ * sfpkrd() correctly (i,e., those that support poll() or select()
+ */
+int ed_read(void *context, int fd, char *buff, int size, int reedit)
+{
+ register Edit_t *ep = (Edit_t*)context;
+ register int rv= -1;
+ register int delim = (ep->e_raw==RAWMODE?'\r':'\n');
+ Shell_t *shp = ep->sh;
+ int mode = -1;
+ int (*waitevent)(int,long,int) = shp->gd->waitevent;
+ if(ep->e_raw==ALTMODE)
+ mode = 1;
+ if(size < 0)
+ {
+ mode = 1;
+ size = -size;
+ }
+ sh_onstate(SH_TTYWAIT);
+ errno = EINTR;
+ shp->gd->waitevent = 0;
+ while(rv<0 && errno==EINTR)
+ {
+ if(shp->trapnote&(SH_SIGSET|SH_SIGTRAP))
+ goto done;
+ if(ep->sh->winch && sh_isstate(SH_INTERACTIVE) && (sh_isoption(SH_VI) || sh_isoption(SH_EMACS)))
+ {
+ Edpos_t lastpos;
+ int n, rows, newsize;
+ /* move cursor to start of first line */
+ ed_putchar(ep,'\r');
+ ed_flush(ep);
+ astwinsize(2,&rows,&newsize);
+ n = (ep->e_plen+ep->e_cur)/++ep->e_winsz;
+ while(n--)
+ ed_putstring(ep,CURSOR_UP);
+ if(ep->e_multiline && newsize>ep->e_winsz && (lastpos.line=(ep->e_plen+ep->e_peol)/ep->e_winsz))
+ {
+ /* clear the current command line */
+ n = lastpos.line;
+ while(lastpos.line--)
+ {
+ ed_nputchar(ep,ep->e_winsz,' ');
+ ed_putchar(ep,'\n');
+ }
+ ed_nputchar(ep,ep->e_winsz,' ');
+ while(n--)
+ ed_putstring(ep,CURSOR_UP);
+ }
+ ep->sh->winch = 0;
+ ed_flush(ep);
+ sh_delay(.05);
+ astwinsize(2,&rows,&newsize);
+ ep->e_winsz = newsize-1;
+ if(ep->e_winsz < MINWINDOW)
+ ep->e_winsz = MINWINDOW;
+ if(!ep->e_multiline && ep->e_wsize < MAXLINE)
+ ep->e_wsize = ep->e_winsz-2;
+ ep->e_nocrnl=1;
+ if(*ep->e_vi_insert)
+ {
+ buff[0] = ESC;
+ buff[1] = cntl('L');
+ buff[2] = 'a';
+ return(3);
+ }
+ if(sh_isoption(SH_EMACS) || sh_isoption(SH_VI))
+ buff[0] = cntl('L');
+ return(1);
+ }
+ else
+ ep->sh->winch = 0;
+ /* an interrupt that should be ignored */
+ errno = 0;
+ if(!waitevent || (rv=(*waitevent)(fd,-1L,0))>=0)
+ rv = sfpkrd(fd,buff,size,delim,-1L,mode);
+ }
+ if(rv < 0)
+ {
+#ifdef _hdr_utime
+# define fixtime() if(isdevtty)utime(ep->e_tty,&utimes)
+ int isdevtty=0;
+ struct stat statb;
+ struct utimbuf utimes;
+ if(errno==0 && !ep->e_tty)
+ {
+ if((ep->e_tty=ttyname(fd)) && stat(ep->e_tty,&statb)>=0)
+ {
+ ep->e_tty_ino = statb.st_ino;
+ ep->e_tty_dev = statb.st_dev;
+ }
+ }
+ if(ep->e_tty_ino && fstat(fd,&statb)>=0 && statb.st_ino==ep->e_tty_ino && statb.st_dev==ep->e_tty_dev)
+ {
+ utimes.actime = statb.st_atime;
+ utimes.modtime = statb.st_mtime;
+ isdevtty=1;
+ }
+#else
+# define fixtime()
+#endif /* _hdr_utime */
+ while(1)
+ {
+ rv = read(fd,buff,size);
+ if(rv>=0 || errno!=EINTR)
+ break;
+ if(shp->trapnote&(SH_SIGSET|SH_SIGTRAP))
+ goto done;
+ /* an interrupt that should be ignored */
+ fixtime();
+ }
+ }
+ else if(rv>=0 && mode>0)
+ rv = read(fd,buff,rv>0?rv:1);
+done:
+ shp->gd->waitevent = waitevent;
+ sh_offstate(SH_TTYWAIT);
+ return(rv);
+}
+
+
+/*
+ * put <string> of length <nbyte> onto lookahead stack
+ * if <type> is non-zero, the negation of the character is put
+ * onto the stack so that it can be checked for KEYTRAP
+ * putstack() returns 1 except when in the middle of a multi-byte char
+ */
+static int putstack(Edit_t *ep,char string[], register int nbyte, int type)
+{
+ register int c;
+#if SHOPT_MULTIBYTE
+ char *endp, *p=string;
+ int size, offset = ep->e_lookahead + nbyte;
+ *(endp = &p[nbyte]) = 0;
+ endp = &p[nbyte];
+ do
+ {
+ c = (int)((*p) & STRIP);
+ if(c< 0x80 && c!='<')
+ {
+ if (type)
+ c = -c;
+# ifndef CBREAK
+ if(c == '\0')
+ {
+ /*** user break key ***/
+ ep->e_lookahead = 0;
+# if KSHELL
+ sh_fault(SIGINT);
+ siglongjmp(ep->e_env, UINTR);
+# endif /* KSHELL */
+ }
+# endif /* CBREAK */
+
+ }
+ else
+ {
+ again:
+ if((c=mbchar(p)) >=0)
+ {
+ p--; /* incremented below */
+ if(type)
+ c = -c;
+ }
+#ifdef EILSEQ
+ else if(errno == EILSEQ)
+ errno = 0;
+#endif
+ else if((endp-p) < mbmax())
+ {
+ if ((c=ed_read(ep,ep->e_fd,endp, 1,0)) == 1)
+ {
+ *++endp = 0;
+ goto again;
+ }
+ return(c);
+ }
+ else
+ {
+ ed_ringbell();
+ c = -(int)((*p) & STRIP);
+ offset += mbmax()-1;
+ }
+ }
+ ep->e_lbuf[--offset] = c;
+ p++;
+ }
+ while (p < endp);
+ /* shift lookahead buffer if necessary */
+ if(offset -= ep->e_lookahead)
+ {
+ for(size=offset;size < nbyte;size++)
+ ep->e_lbuf[ep->e_lookahead+size-offset] = ep->e_lbuf[ep->e_lookahead+size];
+ }
+ ep->e_lookahead += nbyte-offset;
+#else
+ while (nbyte > 0)
+ {
+ c = string[--nbyte] & STRIP;
+ ep->e_lbuf[ep->e_lookahead++] = (type?-c:c);
+# ifndef CBREAK
+ if( c == '\0' )
+ {
+ /*** user break key ***/
+ ep->e_lookahead = 0;
+# if KSHELL
+ sh_fault(SIGINT);
+ siglongjmp(ep->e_env, UINTR);
+# endif /* KSHELL */
+ }
+# endif /* CBREAK */
+ }
+#endif /* SHOPT_MULTIBYTE */
+ return(1);
+}
+
+/*
+ * routine to perform read from terminal for vi and emacs mode
+ * <mode> can be one of the following:
+ * -2 vi insert mode - key binding is in effect
+ * -1 vi control mode - key binding is in effect
+ * 0 normal command mode - key binding is in effect
+ * 1 edit keys not mapped
+ * 2 Next key is literal
+ */
+int ed_getchar(register Edit_t *ep,int mode)
+{
+ register int n, c;
+ char readin[LOOKAHEAD+1];
+ if(!ep->e_lookahead)
+ {
+ ed_flush(ep);
+ ep->e_inmacro = 0;
+ /* The while is necessary for reads of partial multbyte chars */
+ *ep->e_vi_insert = (mode==-2);
+ if((n=ed_read(ep,ep->e_fd,readin,-LOOKAHEAD,0)) > 0)
+ n = putstack(ep,readin,n,1);
+ *ep->e_vi_insert = 0;
+ }
+ if(ep->e_lookahead)
+ {
+ /* check for possible key mapping */
+ if((c = ep->e_lbuf[--ep->e_lookahead]) < 0)
+ {
+ if(mode<=0 && -c == ep->e_intr)
+ {
+ sh_fault(SIGINT);
+ siglongjmp(ep->e_env, UINTR);
+ }
+ if(mode<=0 && ep->sh->st.trap[SH_KEYTRAP])
+ {
+ ep->e_keytrap = 1;
+ n=1;
+ if((readin[0]= -c) == ESC)
+ {
+ while(1)
+ {
+ if(!ep->e_lookahead)
+ {
+ if((c=sfpkrd(ep->e_fd,readin+n,1,'\r',(mode?400L:-1L),0))>0)
+ putstack(ep,readin+n,c,1);
+ }
+ if(!ep->e_lookahead)
+ break;
+ if((c=ep->e_lbuf[--ep->e_lookahead])>=0)
+ {
+ ep->e_lookahead++;
+ break;
+ }
+ c = -c;
+ readin[n++] = c;
+ if(c>='0' && c<='9' && n>2)
+ continue;
+ if(n>2 || (c!= '[' && c!= 'O'))
+ break;
+ }
+ }
+ if(n=keytrap(ep,readin,n,LOOKAHEAD-n,mode))
+ {
+ putstack(ep,readin,n,0);
+ c = ep->e_lbuf[--ep->e_lookahead];
+ }
+ else
+ c = ed_getchar(ep,mode);
+ ep->e_keytrap = 0;
+ }
+ else
+ c = -c;
+ }
+ /*** map '\r' to '\n' ***/
+ if(c == '\r' && mode!=2)
+ c = '\n';
+ if(ep->e_tabcount && !(c=='\t'||c==ESC || c=='\\' || c=='=' || c==cntl('L') || isdigit(c)))
+ ep->e_tabcount = 0;
+ }
+ else
+ siglongjmp(ep->e_env,(n==0?UEOF:UINTR));
+ return(c);
+}
+
+void ed_ungetchar(Edit_t *ep,register int c)
+{
+ if (ep->e_lookahead < LOOKAHEAD)
+ ep->e_lbuf[ep->e_lookahead++] = c;
+ return;
+}
+
+/*
+ * put a character into the output buffer
+ */
+
+void ed_putchar(register Edit_t *ep,register int c)
+{
+ char buf[8];
+ register char *dp = ep->e_outptr;
+ register int i,size=1;
+ if(!dp)
+ return;
+ buf[0] = c;
+#if SHOPT_MULTIBYTE
+ /* check for place holder */
+ if(c == MARKER)
+ return;
+ if((size = mbconv(buf, (wchar_t)c)) > 1)
+ {
+ for (i = 0; i < (size-1); i++)
+ *dp++ = buf[i];
+ c = buf[i];
+ }
+ else
+ {
+ buf[0] = c;
+ size = 1;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ if (buf[0] == '_' && size==1)
+ {
+ *dp++ = ' ';
+ *dp++ = '\b';
+ }
+ *dp++ = c;
+ *dp = '\0';
+ if(dp >= ep->e_outlast)
+ ed_flush(ep);
+ else
+ ep->e_outptr = dp;
+}
+
+/*
+ * returns the line and column corresponding to offset <off> in the physical buffer
+ * if <cur> is non-zero and <= <off>, then correspodning <curpos> will start the search
+ */
+Edpos_t ed_curpos(Edit_t *ep,genchar *phys, int off, int cur, Edpos_t curpos)
+{
+ register genchar *sp=phys;
+ register int c=1, col=ep->e_plen;
+ Edpos_t pos;
+#if SHOPT_MULTIBYTE
+ char p[16];
+#endif /* SHOPT_MULTIBYTE */
+ if(cur && off>=cur)
+ {
+ sp += cur;
+ off -= cur;
+ pos = curpos;
+ col = pos.col;
+ }
+ else
+ {
+ pos.line = 0;
+ while(col > ep->e_winsz)
+ {
+ pos.line++;
+ col -= (ep->e_winsz+1);
+ }
+ }
+ while(off-->0)
+ {
+ if(c)
+ c = *sp++;
+#if SHOPT_MULTIBYTE
+ if(c && (mbconv(p, (wchar_t)c))==1 && p[0]=='\n')
+#else
+ if(c=='\n')
+#endif /* SHOPT_MULTIBYTE */
+ col = 0;
+ else
+ col++;
+ if(col > ep->e_winsz)
+ col = 0;
+ if(col==0)
+ pos.line++;
+ }
+ pos.col = col;
+ return(pos);
+}
+
+int ed_setcursor(register Edit_t *ep,genchar *physical,register int old,register int new,int first)
+{
+ static int oldline;
+ register int delta;
+ int clear = 0;
+ Edpos_t newpos;
+
+ delta = new - old;
+ if(first < 0)
+ {
+ first = 0;
+ clear = 1;
+ }
+ if( delta == 0 && !clear)
+ return(new);
+ if(ep->e_multiline)
+ {
+ ep->e_curpos = ed_curpos(ep, physical, old,0,ep->e_curpos);
+ if(clear && old>=ep->e_peol && (clear=ep->e_winsz-ep->e_curpos.col)>0)
+ {
+ ed_nputchar(ep,clear,' ');
+ ed_nputchar(ep,clear,'\b');
+ return(new);
+ }
+ newpos = ed_curpos(ep, physical, new,old,ep->e_curpos);
+ if(ep->e_curpos.col==0 && ep->e_curpos.line>0 && oldline<ep->e_curpos.line && delta<0)
+ ed_putstring(ep,"\r\n");
+ oldline = newpos.line;
+ if(ep->e_curpos.line > newpos.line)
+ {
+ int n,pline,plen=ep->e_plen;
+ for(;ep->e_curpos.line > newpos.line; ep->e_curpos.line--)
+ ed_putstring(ep,CURSOR_UP);
+ pline = plen/(ep->e_winsz+1);
+ if(newpos.line <= pline)
+ plen -= pline*(ep->e_winsz+1);
+ else
+ plen = 0;
+ if((n=plen- ep->e_curpos.col)>0)
+ {
+ ep->e_curpos.col += n;
+ ed_putchar(ep,'\r');
+ if(!ep->e_crlf && pline==0)
+ ed_putstring(ep,ep->e_prompt);
+ else
+ {
+ int m = ep->e_winsz+1-plen;
+ ed_putchar(ep,'\n');
+ n = plen;
+ if(m < ed_genlen(physical))
+ {
+ while(physical[m] && n-->0)
+ ed_putchar(ep,physical[m++]);
+ }
+ ed_nputchar(ep,n,' ');
+ ed_putstring(ep,CURSOR_UP);
+ }
+ }
+ }
+ else if(ep->e_curpos.line < newpos.line)
+ {
+ ed_nputchar(ep, newpos.line-ep->e_curpos.line,'\n');
+ ep->e_curpos.line = newpos.line;
+ ed_putchar(ep,'\r');
+ ep->e_curpos.col = 0;
+ }
+ delta = newpos.col - ep->e_curpos.col;
+ old = new - delta;
+ }
+ else
+ newpos.line=0;
+ if(delta<0)
+ {
+ int bs= newpos.line && ep->e_plen>ep->e_winsz;
+ /*** move to left ***/
+ delta = -delta;
+ /*** attempt to optimize cursor movement ***/
+ if(!ep->e_crlf || bs || (2*delta <= ((old-first)+(newpos.line?0:ep->e_plen))) )
+ {
+ ed_nputchar(ep,delta,'\b');
+ delta = 0;
+ }
+ else
+ {
+ if(newpos.line==0)
+ ed_putstring(ep,ep->e_prompt);
+ else
+ {
+ first = 1+(newpos.line*ep->e_winsz - ep->e_plen);
+ ed_putchar(ep,'\r');
+ }
+ old = first;
+ delta = new-first;
+ }
+ }
+ while(delta-->0)
+ ed_putchar(ep,physical[old++]);
+ return(new);
+}
+
+/*
+ * copy virtual to physical and return the index for cursor in physical buffer
+ */
+int ed_virt_to_phys(Edit_t *ep,genchar *virt,genchar *phys,int cur,int voff,int poff)
+{
+ register genchar *sp = virt;
+ register genchar *dp = phys;
+ register int c;
+ genchar *curp = sp + cur;
+ genchar *dpmax = phys+MAXLINE;
+ int d, r;
+ sp += voff;
+ dp += poff;
+ for(r=poff;c= *sp;sp++)
+ {
+ if(curp == sp)
+ r = dp - phys;
+#if SHOPT_MULTIBYTE
+ d = mbwidth((wchar_t)c);
+ if(d==1 && is_cntrl(c))
+ d = -1;
+ if(d>1)
+ {
+ /* multiple width character put in place holders */
+ *dp++ = c;
+ while(--d >0)
+ *dp++ = MARKER;
+ /* in vi mode the cursor is at the last character */
+ if(dp>=dpmax)
+ break;
+ continue;
+ }
+ else
+#else
+ d = (is_cntrl(c)?-1:1);
+#endif /* SHOPT_MULTIBYTE */
+ if(d<0)
+ {
+ if(c=='\t')
+ {
+ c = dp-phys;
+ if(sh_isoption(SH_VI))
+ c += ep->e_plen;
+ c = TABSIZE - c%TABSIZE;
+ while(--c>0)
+ *dp++ = ' ';
+ c = ' ';
+ }
+ else
+ {
+ *dp++ = '^';
+ c = printchar(c);
+ }
+ /* in vi mode the cursor is at the last character */
+ if(curp == sp && sh_isoption(SH_VI))
+ r = dp - phys;
+ }
+ *dp++ = c;
+ if(dp>=dpmax)
+ break;
+ }
+ *dp = 0;
+ ep->e_peol = dp-phys;
+ return(r);
+}
+
+#if SHOPT_MULTIBYTE
+/*
+ * convert external representation <src> to an array of genchars <dest>
+ * <src> and <dest> can be the same
+ * returns number of chars in dest
+ */
+
+int ed_internal(const char *src, genchar *dest)
+{
+ register const unsigned char *cp = (unsigned char *)src;
+ register int c;
+ register wchar_t *dp = (wchar_t*)dest;
+ if(dest == (genchar*)roundof(cp-(unsigned char*)0,sizeof(genchar)))
+ {
+ genchar buffer[MAXLINE];
+ c = ed_internal(src,buffer);
+ ed_gencpy((genchar*)dp,buffer);
+ return(c);
+ }
+ while(*cp)
+ *dp++ = mbchar(cp);
+ *dp = 0;
+ return(dp-(wchar_t*)dest);
+}
+
+/*
+ * convert internal representation <src> into character array <dest>.
+ * The <src> and <dest> may be the same.
+ * returns number of chars in dest.
+ */
+
+int ed_external(const genchar *src, char *dest)
+{
+ register genchar wc;
+ register int c,size;
+ register char *dp = dest;
+ char *dpmax = dp+sizeof(genchar)*MAXLINE-2;
+ if((char*)src == dp)
+ {
+ char buffer[MAXLINE*sizeof(genchar)];
+ c = ed_external(src,buffer);
+
+#ifdef _lib_wcscpy
+ wcscpy((wchar_t *)dest,(const wchar_t *)buffer);
+#else
+ strcpy(dest,buffer);
+#endif
+ return(c);
+ }
+ while((wc = *src++) && dp<dpmax)
+ {
+ if((size = mbconv(dp, wc)) < 0)
+ {
+ /* copy the character as is */
+ size = 1;
+ *dp = wc;
+ }
+ dp += size;
+ }
+ *dp = 0;
+ return(dp-dest);
+}
+
+/*
+ * copy <sp> to <dp>
+ */
+
+void ed_gencpy(genchar *dp,const genchar *sp)
+{
+ dp = (genchar*)roundof((char*)dp-(char*)0,sizeof(genchar));
+ sp = (const genchar*)roundof((char*)sp-(char*)0,sizeof(genchar));
+ while(*dp++ = *sp++);
+}
+
+/*
+ * copy at most <n> items from <sp> to <dp>
+ */
+
+void ed_genncpy(register genchar *dp,register const genchar *sp, int n)
+{
+ dp = (genchar*)roundof((char*)dp-(char*)0,sizeof(genchar));
+ sp = (const genchar*)roundof((char*)sp-(char*)0,sizeof(genchar));
+ while(n-->0 && (*dp++ = *sp++));
+}
+
+#endif /* SHOPT_MULTIBYTE */
+/*
+ * find the string length of <str>
+ */
+
+int ed_genlen(register const genchar *str)
+{
+ register const genchar *sp = str;
+ sp = (const genchar*)roundof((char*)sp-(char*)0,sizeof(genchar));
+ while(*sp++);
+ return(sp-str-1);
+}
+#endif /* SHOPT_ESH || SHOPT_VSH */
+
+#ifdef future
+/*
+ * returns 1 when <n> bytes starting at <a> and <b> are equal
+ */
+static int compare(register const char *a,register const char *b,register int n)
+{
+ while(n-->0)
+ {
+ if(*a++ != *b++)
+ return(0);
+ }
+ return(1);
+}
+#endif
+
+#if SHOPT_OLDTERMIO
+
+# include <sys/termio.h>
+
+#ifndef ECHOCTL
+# define ECHOCTL 0
+#endif /* !ECHOCTL */
+#define ott ep->e_ott
+
+/*
+ * For backward compatibility only
+ * This version will use termios when possible, otherwise termio
+ */
+
+int tcgetattr(int fd, struct termios *tt)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ register int r,i;
+ ep->e_tcgeta = 0;
+ ep->e_echoctl = (ECHOCTL!=0);
+ if((r=ioctl(fd,TCGETS,tt))>=0 || errno!=EINVAL)
+ return(r);
+ if((r=ioctl(fd,TCGETA,&ott)) >= 0)
+ {
+ tt->c_lflag = ott.c_lflag;
+ tt->c_oflag = ott.c_oflag;
+ tt->c_iflag = ott.c_iflag;
+ tt->c_cflag = ott.c_cflag;
+ for(i=0; i<NCC; i++)
+ tt->c_cc[i] = ott.c_cc[i];
+ ep->e_tcgeta++;
+ ep->e_echoctl = 0;
+ }
+ return(r);
+}
+
+int tcsetattr(int fd,int mode,struct termios *tt)
+{
+ register Edit_t *ep = (Edit_t*)(shgd->ed_context);
+ register int r;
+ if(ep->e_tcgeta)
+ {
+ register int i;
+ ott.c_lflag = tt->c_lflag;
+ ott.c_oflag = tt->c_oflag;
+ ott.c_iflag = tt->c_iflag;
+ ott.c_cflag = tt->c_cflag;
+ for(i=0; i<NCC; i++)
+ ott.c_cc[i] = tt->c_cc[i];
+ if(tt->c_lflag&ECHOCTL)
+ {
+ ott.c_lflag &= ~(ECHOCTL|IEXTEN);
+ ott.c_iflag &= ~(IGNCR|ICRNL);
+ ott.c_iflag |= INLCR;
+ ott.c_cc[VEOF]= ESC; /* ESC -> eof char */
+ ott.c_cc[VEOL] = '\r'; /* CR -> eol char */
+ ott.c_cc[VEOL2] = tt->c_cc[VEOF]; /* EOF -> eol char */
+ }
+ switch(mode)
+ {
+ case TCSANOW:
+ mode = TCSETA;
+ break;
+ case TCSADRAIN:
+ mode = TCSETAW;
+ break;
+ case TCSAFLUSH:
+ mode = TCSETAF;
+ }
+ return(ioctl(fd,mode,&ott));
+ }
+ return(ioctl(fd,mode,tt));
+}
+#endif /* SHOPT_OLDTERMIO */
+
+#if KSHELL
+/*
+ * Execute keyboard trap on given buffer <inbuff> of given size <isize>
+ * <mode> < 0 for vi insert mode
+ */
+static int keytrap(Edit_t *ep,char *inbuff,register int insize, int bufsize, int mode)
+{
+ register char *cp;
+ int savexit;
+ Shell_t *shp = ep->sh;
+#if SHOPT_MULTIBYTE
+ char buff[MAXLINE];
+ ed_external(ep->e_inbuf,cp=buff);
+#else
+ cp = ep->e_inbuf;
+#endif /* SHOPT_MULTIBYTE */
+ inbuff[insize] = 0;
+ ep->e_col = ep->e_cur;
+ if(mode== -2)
+ {
+ ep->e_col++;
+ *ep->e_vi_insert = ESC;
+ }
+ else
+ *ep->e_vi_insert = 0;
+ nv_putval(ED_CHRNOD,inbuff,NV_NOFREE);
+ nv_putval(ED_COLNOD,(char*)&ep->e_col,NV_NOFREE|NV_INTEGER);
+ nv_putval(ED_TXTNOD,(char*)cp,NV_NOFREE);
+ nv_putval(ED_MODENOD,ep->e_vi_insert,NV_NOFREE);
+ savexit = shp->savexit;
+ sh_trap(shp->st.trap[SH_KEYTRAP],0);
+ shp->savexit = savexit;
+ if((cp = nv_getval(ED_CHRNOD)) == inbuff)
+ nv_unset(ED_CHRNOD);
+ else if(bufsize>0)
+ {
+ strncpy(inbuff,cp,bufsize);
+ inbuff[bufsize-1]='\0';
+ insize = strlen(inbuff);
+ }
+ else
+ insize = 0;
+ nv_unset(ED_TXTNOD);
+ return(insize);
+}
+#endif /* KSHELL */
+
+#if SHOPT_EDPREDICT
+static int ed_sortdata(const char *s1, const char *s2)
+{
+ Histmatch_t *m1 = (Histmatch_t*)s1;
+ Histmatch_t *m2 = (Histmatch_t*)s2;
+ return(strcmp(m1->data,m2->data));
+}
+
+static int ed_sortindex(const char *s1, const char *s2)
+{
+ Histmatch_t *m1 = (Histmatch_t*)s1;
+ Histmatch_t *m2 = (Histmatch_t*)s2;
+ return(m2->index-m1->index);
+}
+
+static int ed_histlencopy(const char *cp, char *dp)
+{
+ int c,n=1,col=1;
+ const char *oldcp=cp;
+ for(n=0;c = mbchar(cp);oldcp=cp,col++)
+ {
+ if(c=='\n' && *cp)
+ {
+ n += 2;
+ if(dp)
+ {
+ *dp++ = '^';
+ *dp++ = 'J';
+ col +=2;
+ }
+ }
+ else if(c=='\t')
+ {
+ n++;
+ if(dp)
+ *dp++ = ' ';
+ }
+ else
+ {
+ n += cp-oldcp;
+ if(dp)
+ {
+ while(oldcp < cp)
+ *dp++ = *oldcp++;
+ }
+ }
+
+ }
+ return(n);
+}
+
+int ed_histgen(Edit_t *ep,const char *pattern)
+{
+ Histmatch_t *mp,*mplast=0;
+ History_t *hp;
+ off_t offset;
+ int ac=0,l,m,n,index1,index2;
+ char *cp, **argv, **av, **ar;
+ if(!(hp=ep->sh->gd->hist_ptr))
+ return(0);
+ if(*pattern=='#')
+ pattern++;
+ cp = stakalloc(m=strlen(pattern)+6);
+ sfsprintf(cp,m,"@(%s)*%c",pattern,0);
+ if(ep->hlist)
+ {
+ m = strlen(ep->hpat)-4;
+ if(memcmp(pattern,ep->hpat+2,m)==0)
+ {
+ n = strcmp(cp,ep->hpat)==0;
+ for(argv=av=(char**)ep->hlist,mp=ep->hfirst; mp;mp= mp->next)
+ {
+ if(n || strmatch(mp->data,cp))
+ *av++ = (char*)mp;
+ }
+ *av = 0;
+ return(ep->hmax=av-argv);
+ }
+ stakset(ep->e_stkptr,ep->e_stkoff);
+ }
+ pattern = ep->hpat = cp;
+ index1 = (int)hp->histind;
+ for(index2=index1-hp->histsize; index1>index2; index1--)
+ {
+ offset = hist_tell(hp,index1);
+ sfseek(hp->histfp,offset,SEEK_SET);
+ if(!(cp = sfgetr(hp->histfp,0,0)))
+ continue;
+ if(*cp=='#')
+ continue;
+ if(strmatch(cp,pattern))
+ {
+ l = ed_histlencopy(cp,(char*)0);
+ mp = (Histmatch_t*)stakalloc(sizeof(Histmatch_t)+l);
+ mp->next = mplast;
+ mplast = mp;
+ mp->len = l;
+ ed_histlencopy(cp,mp->data);
+ mp->count = 1;
+ mp->data[l] = 0;
+ mp->index = index1;
+ ac++;
+ }
+ }
+ if(ac>0)
+ {
+ l = ac;
+ argv = av = (char**)stakalloc((ac+1)*sizeof(char*));
+ for(mplast=0; l>=0 && (*av= (char*)mp); mplast=mp,mp=mp->next,av++)
+ {
+ l--;
+ }
+ *av = 0;
+ strsort(argv,ac,ed_sortdata);
+ mplast = (Histmatch_t*)argv[0];
+ for(ar= av= &argv[1]; mp=(Histmatch_t*)*av; av++)
+ {
+ if(strcmp(mp->data,mplast->data)==0)
+ {
+ mplast->count++;
+ if(mp->index> mplast->index)
+ mplast->index = mp->index;
+ continue;
+ }
+ *ar++ = (char*)(mplast=mp);
+ }
+ *ar = 0;
+ mplast->next = 0;
+ ac = ar-argv;
+ strsort(argv,ac,ed_sortindex);
+ mplast = (Histmatch_t*)argv[0];
+ for(av= &argv[1]; mp=(Histmatch_t*)*av; av++, mplast=mp)
+ mplast->next = mp;
+ mplast->next = 0;
+ }
+ ep->hlist = (Histmatch_t**)argv;
+ ep->hfirst = ep->hlist?ep->hlist[0]:0;
+ return(ep->hmax=ac);
+}
+
+void ed_histlist(Edit_t *ep,int n)
+{
+ Histmatch_t *mp,**mpp = ep->hlist+ep->hoff;
+ int i,last=0,save[2];
+ if(n)
+ {
+ /* don't bother updating the screen if there is typeahead */
+ if(!ep->e_lookahead && sfpkrd(ep->e_fd,save,1,'\r',200L,-1)>0)
+ ed_ungetchar(ep,save[0]);
+ if(ep->e_lookahead)
+ return;
+ ed_putchar(ep,'\n');
+ ed_putchar(ep,'\r');
+ }
+ else
+ {
+ stakset(ep->e_stkptr,ep->e_stkoff);
+ ep->hlist = 0;
+ ep->nhlist = 0;
+ }
+ ed_putstring(ep,KILL_LINE);
+ if(n)
+ {
+ for(i=1; (mp= *mpp) && i <= 16 ; i++,mpp++)
+ {
+ last = 0;
+ if(mp->len >= ep->e_winsz-4)
+ {
+ last = ep->e_winsz-4;
+ save[0] = mp->data[last-1];
+ save[1] = mp->data[last];
+ mp->data[last-1] = '\n';
+ mp->data[last] = 0;
+ }
+ ed_putchar(ep,i<10?' ':'1');
+ ed_putchar(ep,i<10?'0'+i:'0'+i-10);
+ ed_putchar(ep,')');
+ ed_putchar(ep,' ');
+ ed_putstring(ep,mp->data);
+ if(last)
+ {
+ mp->data[last-1] = save[0];
+ mp->data[last] = save[1];
+ }
+ ep->nhlist = i;
+ }
+ last = i-1;
+ while(i-->0)
+ ed_putstring(ep,CURSOR_UP);
+ }
+ ed_flush(ep);
+}
+#endif /* SHOPT_EDPREDICT */
+
+void *ed_open(Shell_t *shp)
+{
+ Edit_t *ed = newof(0,Edit_t,1,0);
+ ed->sh = shp;
+ strcpy(ed->e_macro,"_??");
+ return((void*)ed);
+}
diff --git a/src/cmd/ksh93/edit/emacs.c b/src/cmd/ksh93/edit/emacs.c
new file mode 100644
index 0000000..cb686b7
--- /dev/null
+++ b/src/cmd/ksh93/edit/emacs.c
@@ -0,0 +1,1571 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/* Original version by Michael T. Veach
+ * Adapted for ksh by David Korn */
+/* EMACS_MODES: c tabstop=4
+
+One line screen editor for any program
+
+*/
+
+
+/* The following is provided by:
+ *
+ * Matthijs N. Melchior
+ * AT&T Network Systems International
+ * APT Nederland
+ * HV BZ335 x2962
+ * hvlpb!mmelchio
+ *
+ * These are now on by default
+ *
+ * ESH_NFIRST
+ * - A ^N as first history related command after the prompt will move
+ * to the next command relative to the last known history position.
+ * It will not start at the position where the last command was entered
+ * as is done by the ^P command. Every history related command will
+ * set both the current and last position. Executing a command will
+ * only set the current position.
+ *
+ * ESH_KAPPEND
+ * - Successive kill and delete commands will accumulate their data
+ * in the kill buffer, by appending or prepending as appropriate.
+ * This mode will be reset by any command not adding something to the
+ * kill buffer.
+ *
+ * ESH_BETTER
+ * - Some enhancements:
+ * - argument for a macro is passed to its replacement
+ * - ^X^H command to find out about history position (debugging)
+ * - ^X^D command to show any debugging info
+ *
+ * I do not pretend these for changes are completely independent,
+ * but you can use them to seperate features.
+ */
+
+#include <ast.h>
+#include "FEATURE/cmds"
+#if KSHELL
+# include "defs.h"
+#else
+# include <ctype.h>
+#endif /* KSHELL */
+#include "io.h"
+
+#include "history.h"
+#include "edit.h"
+#include "terminal.h"
+
+#define ESH_NFIRST
+#define ESH_KAPPEND
+#define ESH_BETTER
+
+#undef putchar
+#define putchar(ed,c) ed_putchar(ed,c)
+#define beep() ed_ringbell()
+
+
+#if SHOPT_MULTIBYTE
+# define gencpy(a,b) ed_gencpy(a,b)
+# define genncpy(a,b,n) ed_genncpy(a,b,n)
+# define genlen(str) ed_genlen(str)
+ static int print(int);
+ static int _isword(int);
+# define isword(c) _isword(out[c])
+
+#else
+# define gencpy(a,b) strcpy((char*)(a),(char*)(b))
+# define genncpy(a,b,n) strncpy((char*)(a),(char*)(b),n)
+# define genlen(str) strlen(str)
+# define print(c) isprint(c)
+# define isword(c) (isalnum(out[c]) || (out[c]=='_'))
+#endif /*SHOPT_MULTIBYTE */
+
+typedef struct _emacs_
+{
+ genchar *screen; /* pointer to window buffer */
+ genchar *cursor; /* Cursor in real screen */
+ int mark;
+ int in_mult;
+ char cr_ok;
+ char CntrlO;
+ char overflow; /* Screen overflow flag set */
+ char scvalid; /* Screen is up to date */
+ char lastdraw; /* last update type */
+ int offset; /* Screen offset */
+ enum
+ {
+ CRT=0, /* Crt terminal */
+ PAPER /* Paper terminal */
+ } terminal;
+ Histloc_t _location;
+ int prevdirection;
+ Edit_t *ed; /* pointer to edit data */
+} Emacs_t;
+
+#define editb (*ep->ed)
+#define eol editb.e_eol
+#define cur editb.e_cur
+#define hline editb.e_hline
+#define hloff editb.e_hloff
+#define hismin editb.e_hismin
+#define usrkill editb.e_kill
+#define usrlnext editb.e_lnext
+#define usreof editb.e_eof
+#define usrerase editb.e_erase
+#define crallowed editb.e_crlf
+#define Prompt editb.e_prompt
+#define plen editb.e_plen
+#define kstack editb.e_killbuf
+#define lstring editb.e_search
+#define lookahead editb.e_lookahead
+#define env editb.e_env
+#define raw editb.e_raw
+#define histlines editb.e_hismax
+#define w_size editb.e_wsize
+#define drawbuff editb.e_inbuf
+#define killing editb.e_mode
+#define location ep->_location
+
+#define LBUF 100
+#define KILLCHAR UKILL
+#define ERASECHAR UERASE
+#define EOFCHAR UEOF
+#define LNEXTCHAR ULNEXT
+#define DELETE ('a'==97?0177:7)
+
+/**********************
+A large lookahead helps when the user is inserting
+characters in the middle of the line.
+************************/
+
+
+typedef enum
+{
+ FIRST, /* First time thru for logical line, prompt on screen */
+ REFRESH, /* Redraw entire screen */
+ APPEND, /* Append char before cursor to screen */
+ UPDATE, /* Update the screen as need be */
+ FINAL /* Update screen even if pending look ahead */
+} Draw_t;
+
+static void draw(Emacs_t*,Draw_t);
+static int escape(Emacs_t*,genchar*, int);
+static void putstring(Emacs_t*,char*);
+static void search(Emacs_t*,genchar*,int);
+static void setcursor(Emacs_t*,int, int);
+static void show_info(Emacs_t*,const char*);
+static void xcommands(Emacs_t*,int);
+
+int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
+{
+ Edit_t *ed = (Edit_t*)context;
+ register int c;
+ register int i;
+ register genchar *out;
+ register int count;
+ register Emacs_t *ep = ed->e_emacs;
+ int adjust,oadjust;
+ char backslash;
+ genchar *kptr;
+ char prompt[PRSIZE];
+ genchar Screen[MAXLINE];
+ memset(Screen,0,sizeof(Screen));
+ if(!ep)
+ {
+ ep = ed->e_emacs = newof(0,Emacs_t,1,0);
+ ep->ed = ed;
+ ep->prevdirection = 1;
+ location.hist_command = -5;
+ }
+ Prompt = prompt;
+ ep->screen = Screen;
+ ep->lastdraw = FINAL;
+ if(tty_raw(ERRIO,0) < 0)
+ {
+ return(reedit?reedit:ed_read(context, fd,buff,scend,0));
+ }
+ raw = 1;
+ /* This mess in case the read system call fails */
+
+ ed_setup(ep->ed,fd,reedit);
+ out = (genchar*)buff;
+#if SHOPT_MULTIBYTE
+ out = (genchar*)roundof(buff-(char*)0,sizeof(genchar));
+ if(reedit)
+ ed_internal(buff,out);
+#endif /* SHOPT_MULTIBYTE */
+ if(!kstack)
+ {
+ kstack = (genchar*)malloc(CHARSIZE*MAXLINE);
+ kstack[0] = '\0';
+ }
+ drawbuff = out;
+#ifdef ESH_NFIRST
+ if (location.hist_command == -5) /* to be initialized */
+ {
+ kstack[0] = '\0'; /* also clear kstack... */
+ location.hist_command = hline;
+ location.hist_line = hloff;
+ }
+ if (location.hist_command <= hismin) /* don't start below minimum */
+ {
+ location.hist_command = hismin + 1;
+ location.hist_line = 0;
+ }
+ ep->in_mult = hloff; /* save pos in last command */
+#endif /* ESH_NFIRST */
+ i = sigsetjmp(env,0);
+ if (i !=0)
+ {
+ if(ep->ed->e_multiline)
+ {
+ cur = eol;
+ draw(ep,FINAL);
+ ed_flush(ep->ed);
+ }
+ tty_cooked(ERRIO);
+ if (i == UEOF)
+ {
+ return(0); /* EOF */
+ }
+ return(-1); /* some other error */
+ }
+ out[reedit] = 0;
+ if(scend+plen > (MAXLINE-2))
+ scend = (MAXLINE-2)-plen;
+ ep->mark = 0;
+ cur = eol;
+ draw(ep,reedit?REFRESH:FIRST);
+ adjust = -1;
+ backslash = 0;
+ if (ep->CntrlO)
+ {
+#ifdef ESH_NFIRST
+ ed_ungetchar(ep->ed,cntl('N'));
+#else
+ location = hist_locate(shgd->hist_ptr,location.hist_command,location.hist_line,1);
+ if (location.hist_command < histlines)
+ {
+ hline = location.hist_command;
+ hloff = location.hist_line;
+ hist_copy((char*)kstack,MAXLINE, hline,hloff);
+# if SHOPT_MULTIBYTE
+ ed_internal((char*)kstack,kstack);
+# endif /* SHOPT_MULTIBYTE */
+ ed_ungetchar(ep->ed,cntl('Y'));
+ }
+#endif /* ESH_NFIRST */
+ }
+ ep->CntrlO = 0;
+ while ((c = ed_getchar(ep->ed,0)) != (-1))
+ {
+ if (backslash)
+ {
+ backslash = 0;
+ if (c==usrerase||c==usrkill||(!print(c) &&
+ (c!='\r'&&c!='\n')))
+ {
+ /* accept a backslashed character */
+ cur--;
+ out[cur++] = c;
+ out[eol] = '\0';
+ draw(ep,APPEND);
+ continue;
+ }
+ }
+ if (c == usrkill)
+ {
+ c = KILLCHAR ;
+ }
+ else if (c == usrerase)
+ {
+ c = ERASECHAR ;
+ }
+ else if (c == usrlnext)
+ {
+ c = LNEXTCHAR ;
+ }
+ else if ((c == usreof)&&(eol == 0))
+ {
+ c = EOFCHAR;
+ }
+#ifdef ESH_KAPPEND
+ if (--killing <= 0) /* reset killing flag */
+ killing = 0;
+#endif
+ oadjust = count = adjust;
+ if(count<0)
+ count = 1;
+ adjust = -1;
+ i = cur;
+ switch(c)
+ {
+ case LNEXTCHAR:
+ c = ed_getchar(ep->ed,2);
+ goto do_default_processing;
+ case cntl('V'):
+ show_info(ep,fmtident(e_version));
+ continue;
+ case '\0':
+ ep->mark = i;
+ continue;
+ case cntl('X'):
+ xcommands(ep,count);
+ continue;
+ case EOFCHAR:
+ ed_flush(ep->ed);
+ tty_cooked(ERRIO);
+ return(0);
+#ifdef u370
+ case cntl('S') :
+ case cntl('Q') :
+ continue;
+#endif /* u370 */
+ case '\t':
+ if(cur>0 && ep->ed->sh->nextprompt)
+ {
+ if(ep->ed->e_tabcount==0)
+ {
+ ep->ed->e_tabcount=1;
+ ed_ungetchar(ep->ed,ESC);
+ goto do_escape;
+ }
+ else if(ep->ed->e_tabcount==1)
+ {
+ ed_ungetchar(ep->ed,'=');
+ goto do_escape;
+ }
+ ep->ed->e_tabcount = 0;
+ }
+ do_default_processing:
+ default:
+
+ if ((eol+1) >= (scend)) /* will not fit on line */
+ {
+ ed_ungetchar(ep->ed,c); /* save character for next line */
+ goto process;
+ }
+ for(i= ++eol; i>cur; i--)
+ out[i] = out[i-1];
+ backslash = (c == '\\');
+ out[cur++] = c;
+ draw(ep,APPEND);
+ continue;
+ case cntl('Y') :
+ {
+ c = genlen(kstack);
+ if ((c + eol) > scend)
+ {
+ beep();
+ continue;
+ }
+ ep->mark = i;
+ for(i=eol;i>=cur;i--)
+ out[c+i] = out[i];
+ kptr=kstack;
+ while (i = *kptr++)
+ out[cur++] = i;
+ draw(ep,UPDATE);
+ eol = genlen(out);
+ continue;
+ }
+ case '\n':
+ case '\r':
+ c = '\n';
+ goto process;
+
+ case DELETE: /* delete char 0x7f */
+ case '\b': /* backspace, ^h */
+ case ERASECHAR :
+ if (count > i)
+ count = i;
+#ifdef ESH_KAPPEND
+ kptr = &kstack[count]; /* move old contents here */
+ if (killing) /* prepend to killbuf */
+ {
+ c = genlen(kstack) + CHARSIZE; /* include '\0' */
+ while(c--) /* copy stuff */
+ kptr[c] = kstack[c];
+ }
+ else
+ *kptr = 0; /* this is end of data */
+ killing = 2; /* we are killing */
+ i -= count;
+ eol -= count;
+ genncpy(kstack,out+i,cur-i);
+#else
+ while ((count--)&&(i>0))
+ {
+ i--;
+ eol--;
+ }
+ genncpy(kstack,out+i,cur-i);
+ kstack[cur-i] = 0;
+#endif /* ESH_KAPPEND */
+ gencpy(out+i,out+cur);
+ ep->mark = i;
+ goto update;
+ case cntl('W') :
+#ifdef ESH_KAPPEND
+ ++killing; /* keep killing flag */
+#endif
+ if (ep->mark > eol )
+ ep->mark = eol;
+ if (ep->mark == i)
+ continue;
+ if (ep->mark > i)
+ {
+ adjust = ep->mark - i;
+ ed_ungetchar(ep->ed,cntl('D'));
+ continue;
+ }
+ adjust = i - ep->mark;
+ ed_ungetchar(ep->ed,usrerase);
+ continue;
+ case cntl('D') :
+ ep->mark = i;
+#ifdef ESH_KAPPEND
+ if (killing)
+ kptr = &kstack[genlen(kstack)]; /* append here */
+ else
+ kptr = kstack;
+ killing = 2; /* we are now killing */
+#else
+ kptr = kstack;
+#endif /* ESH_KAPPEND */
+ while ((count--)&&(eol>0)&&(i<eol))
+ {
+ *kptr++ = out[i];
+ eol--;
+ while(1)
+ {
+ if ((out[i] = out[(i+1)])==0)
+ break;
+ i++;
+ }
+ i = cur;
+ }
+ *kptr = '\0';
+ goto update;
+ case cntl('C') :
+ case cntl('F') :
+ {
+ int cntlC = (c==cntl('C'));
+ while (count-- && eol>i)
+ {
+ if (cntlC)
+ {
+ c = out[i];
+#if SHOPT_MULTIBYTE
+ if((c&~STRIP)==0 && islower(c))
+#else
+ if(islower(c))
+#endif /* SHOPT_MULTIBYTE */
+ {
+ c += 'A' - 'a';
+ out[i] = c;
+ }
+ }
+ i++;
+ }
+ goto update;
+ }
+ case cntl(']') :
+ c = ed_getchar(ep->ed,1);
+ if ((count == 0) || (count > eol))
+ {
+ beep();
+ continue;
+ }
+ if (out[i])
+ i++;
+ while (i < eol)
+ {
+ if (out[i] == c && --count==0)
+ goto update;
+ i++;
+ }
+ i = 0;
+ while (i < cur)
+ {
+ if (out[i] == c && --count==0)
+ break;
+ i++;
+ };
+
+update:
+ cur = i;
+ draw(ep,UPDATE);
+ continue;
+
+ case cntl('B') :
+ if (count > i)
+ count = i;
+ i -= count;
+ goto update;
+ case cntl('T') :
+ if ((sh_isoption(SH_EMACS))&& (eol!=i))
+ i++;
+ if (i >= 2)
+ {
+ c = out[i - 1];
+ out[i-1] = out[i-2];
+ out[i-2] = c;
+ }
+ else
+ {
+ if(sh_isoption(SH_EMACS))
+ i--;
+ beep();
+ continue;
+ }
+ goto update;
+ case cntl('A') :
+ i = 0;
+ goto update;
+ case cntl('E') :
+ i = eol;
+ goto update;
+ case cntl('U') :
+ adjust = 4*count;
+ continue;
+ case KILLCHAR :
+ cur = 0;
+ oadjust = -1;
+ case cntl('K') :
+ if(oadjust >= 0)
+ {
+#ifdef ESH_KAPPEND
+ killing = 2; /* set killing signal */
+#endif
+ ep->mark = count;
+ ed_ungetchar(ep->ed,cntl('W'));
+ continue;
+ }
+ i = cur;
+ eol = i;
+ ep->mark = i;
+#ifdef ESH_KAPPEND
+ if (killing) /* append to kill buffer */
+ gencpy(&kstack[genlen(kstack)], &out[i]);
+ else
+ gencpy(kstack,&out[i]);
+ killing = 2; /* set killing signal */
+#else
+ gencpy(kstack,&out[i]);
+#endif /* ESH_KAPPEND */
+ out[i] = 0;
+ draw(ep,UPDATE);
+ if (c == KILLCHAR)
+ {
+ if (ep->terminal == PAPER)
+ {
+ putchar(ep->ed,'\n');
+ putstring(ep,Prompt);
+ }
+ c = ed_getchar(ep->ed,0);
+ if (c != usrkill)
+ {
+ ed_ungetchar(ep->ed,c);
+ continue;
+ }
+ if (ep->terminal == PAPER)
+ ep->terminal = CRT;
+ else
+ {
+ ep->terminal = PAPER;
+ putchar(ep->ed,'\n');
+ putstring(ep,Prompt);
+ }
+ }
+ continue;
+ case cntl('L'):
+ if(!ep->ed->e_nocrnl)
+ ed_crlf(ep->ed);
+ draw(ep,REFRESH);
+ ep->ed->e_nocrnl = 0;
+ continue;
+ case cntl('[') :
+ do_escape:
+ adjust = escape(ep,out,oadjust);
+ continue;
+ case cntl('R') :
+ search(ep,out,count);
+ goto drawline;
+ case cntl('P') :
+#if SHOPT_EDPREDICT
+ if(ep->ed->hlist)
+ {
+ if(ep->ed->hoff == 0)
+ {
+ beep();
+ continue;
+ }
+ ep->ed->hoff--;
+ goto hupdate;
+ }
+#endif /* SHOPT_EDPREDICT */
+ if (count <= hloff)
+ hloff -= count;
+ else
+ {
+ hline -= count - hloff;
+ hloff = 0;
+ }
+#ifdef ESH_NFIRST
+ if (hline <= hismin)
+#else
+ if (hline < hismin)
+#endif /* ESH_NFIRST */
+ {
+ hline = hismin+1;
+ beep();
+#ifndef ESH_NFIRST
+ continue;
+#endif
+ }
+ goto common;
+
+ case cntl('O') :
+ location.hist_command = hline;
+ location.hist_line = hloff;
+ ep->CntrlO = 1;
+ c = '\n';
+ goto process;
+ case cntl('N') :
+#if SHOPT_EDPREDICT
+ if(ep->ed->hlist)
+ {
+ if(ep->ed->hoff >= ep->ed->hmax)
+ {
+ beep();
+ continue;
+ }
+ ep->ed->hoff++;
+ hupdate:
+ ed_histlist(ep->ed,*ep->ed->hlist!=0);
+ draw(ep,REFRESH);
+ continue;
+ }
+#endif /* SHOPT_EDPREDICT */
+#ifdef ESH_NFIRST
+ hline = location.hist_command; /* start at saved position */
+ hloff = location.hist_line;
+#endif /* ESH_NFIRST */
+ location = hist_locate(shgd->hist_ptr,hline,hloff,count);
+ if (location.hist_command > histlines)
+ {
+ beep();
+#ifdef ESH_NFIRST
+ location.hist_command = histlines;
+ location.hist_line = ep->in_mult;
+#else
+ continue;
+#endif /* ESH_NFIRST */
+ }
+ hline = location.hist_command;
+ hloff = location.hist_line;
+ common:
+#ifdef ESH_NFIRST
+ location.hist_command = hline; /* save current position */
+ location.hist_line = hloff;
+#endif
+ cur = 0;
+ draw(ep,UPDATE);
+ hist_copy((char*)out,MAXLINE, hline,hloff);
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)(out),out);
+#endif /* SHOPT_MULTIBYTE */
+ drawline:
+ eol = genlen(out);
+ cur = eol;
+ draw(ep,UPDATE);
+ continue;
+ }
+
+ }
+
+process:
+
+ if (c == (-1))
+ {
+ lookahead = 0;
+ beep();
+ *out = '\0';
+ }
+ draw(ep,FINAL);
+ tty_cooked(ERRIO);
+ if(ed->e_nlist)
+ {
+ ed->e_nlist = 0;
+ stakset(ed->e_stkptr,ed->e_stkoff);
+ }
+ if(c == '\n')
+ {
+ out[eol++] = '\n';
+ out[eol] = '\0';
+ ed_crlf(ep->ed);
+ }
+#if SHOPT_MULTIBYTE
+ ed_external(out,buff);
+#endif /* SHOPT_MULTIBYTE */
+ i = strlen(buff);
+ if (i)
+ return(i);
+ return(-1);
+}
+
+static void show_info(Emacs_t *ep,const char *str)
+{
+ register genchar *out = drawbuff;
+ register int c;
+ genchar string[LBUF];
+ int sav_cur = cur;
+ /* save current line */
+ genncpy(string,out,sizeof(string)/sizeof(*string));
+ *out = 0;
+ cur = 0;
+#if SHOPT_MULTIBYTE
+ ed_internal(str,out);
+#else
+ gencpy(out,str);
+#endif /* SHOPT_MULTIBYTE */
+ draw(ep,UPDATE);
+ c = ed_getchar(ep->ed,0);
+ if(c!=' ')
+ ed_ungetchar(ep->ed,c);
+ /* restore line */
+ cur = sav_cur;
+ genncpy(out,string,sizeof(string)/sizeof(*string));
+ draw(ep,UPDATE);
+}
+
+static void putstring(Emacs_t* ep,register char *sp)
+{
+ register int c;
+ while (c= *sp++)
+ putchar(ep->ed,c);
+}
+
+
+static int escape(register Emacs_t* ep,register genchar *out,int count)
+{
+ register int i,value;
+ int digit,ch;
+ digit = 0;
+ value = 0;
+ while ((i=ed_getchar(ep->ed,0)),isdigit(i))
+ {
+ value *= 10;
+ value += (i - '0');
+ digit = 1;
+ }
+ if (digit)
+ {
+ ed_ungetchar(ep->ed,i) ;
+#ifdef ESH_KAPPEND
+ ++killing; /* don't modify killing signal */
+#endif
+ return(value);
+ }
+ value = count;
+ if(value<0)
+ value = 1;
+ switch(ch=i)
+ {
+ case cntl('V'):
+ show_info(ep,fmtident(e_version));
+ return(-1);
+ case ' ':
+ ep->mark = cur;
+ return(-1);
+
+#ifdef ESH_KAPPEND
+ case '+': /* M-+ = append next kill */
+ killing = 2;
+ return -1; /* no argument for next command */
+#endif
+
+ case 'p': /* M-p == ^W^Y (copy stack == kill & yank) */
+ ed_ungetchar(ep->ed,cntl('Y'));
+ ed_ungetchar(ep->ed,cntl('W'));
+#ifdef ESH_KAPPEND
+ killing = 0; /* start fresh */
+#endif
+ return(-1);
+
+ case 'l': /* M-l == lower-case */
+ case 'd':
+ case 'c':
+ case 'f':
+ {
+ i = cur;
+ while(value-- && i<eol)
+ {
+ while ((out[i])&&(!isword(i)))
+ i++;
+ while ((out[i])&&(isword(i)))
+ i++;
+ }
+ if(ch=='l')
+ {
+ value = i-cur;
+ while (value-- > 0)
+ {
+ i = out[cur];
+#if SHOPT_MULTIBYTE
+ if((i&~STRIP)==0 && isupper(i))
+#else
+ if(isupper(i))
+#endif /* SHOPT_MULTIBYTE */
+ {
+ i += 'a' - 'A';
+ out[cur] = i;
+ }
+ cur++;
+ }
+ draw(ep,UPDATE);
+ return(-1);
+ }
+
+ else if(ch=='f')
+ goto update;
+ else if(ch=='c')
+ {
+ ed_ungetchar(ep->ed,cntl('C'));
+ return(i-cur);
+ }
+ else
+ {
+ if (i-cur)
+ {
+ ed_ungetchar(ep->ed,cntl('D'));
+#ifdef ESH_KAPPEND
+ ++killing; /* keep killing signal */
+#endif
+ return(i-cur);
+ }
+ beep();
+ return(-1);
+ }
+ }
+
+
+ case 'b':
+ case DELETE :
+ case '\b':
+ case 'h':
+ {
+ i = cur;
+ while(value-- && i>0)
+ {
+ i--;
+ while ((i>0)&&(!isword(i)))
+ i--;
+ while ((i>0)&&(isword(i-1)))
+ i--;
+ }
+ if(ch=='b')
+ goto update;
+ else
+ {
+ ed_ungetchar(ep->ed,usrerase);
+#ifdef ESH_KAPPEND
+ ++killing;
+#endif
+ return(cur-i);
+ }
+ }
+
+ case '>':
+ ed_ungetchar(ep->ed,cntl('N'));
+#ifdef ESH_NFIRST
+ if (ep->in_mult)
+ {
+ location.hist_command = histlines;
+ location.hist_line = ep->in_mult - 1;
+ }
+ else
+ {
+ location.hist_command = histlines - 1;
+ location.hist_line = 0;
+ }
+#else
+ hline = histlines-1;
+ hloff = 0;
+#endif /* ESH_NFIRST */
+ return(0);
+
+ case '<':
+ ed_ungetchar(ep->ed,cntl('P'));
+ hloff = 0;
+#ifdef ESH_NFIRST
+ hline = hismin + 1;
+ return 0;
+#else
+ return(hline-hismin);
+#endif /* ESH_NFIRST */
+
+
+ case '#':
+ ed_ungetchar(ep->ed,'\n');
+ ed_ungetchar(ep->ed,(out[0]=='#')?cntl('D'):'#');
+ ed_ungetchar(ep->ed,cntl('A'));
+ return(-1);
+ case '_' :
+ case '.' :
+ {
+ genchar name[MAXLINE];
+ char buf[MAXLINE];
+ char *ptr;
+ ptr = hist_word(buf,MAXLINE,(count?count:-1));
+ if(ptr==0)
+ {
+ beep();
+ break;
+ }
+ if ((eol - cur) >= sizeof(name))
+ {
+ beep();
+ return(-1);
+ }
+ ep->mark = cur;
+ gencpy(name,&out[cur]);
+ while(*ptr)
+ {
+ out[cur++] = *ptr++;
+ eol++;
+ }
+ gencpy(&out[cur],name);
+ draw(ep,UPDATE);
+ return(-1);
+ }
+#if KSHELL
+
+#if SHOPT_EDPREDICT
+ case '\n': case '\t':
+ if(!ep->ed->hlist)
+ {
+ beep();
+ break;
+ }
+ if(ch=='\n')
+ ed_ungetchar(ep->ed,'\n');
+#endif /* SHOPT_EDPREDICT */
+ /* file name expansion */
+ case cntl('[') : /* filename completion */
+#if SHOPT_EDPREDICT
+ if(ep->ed->hlist)
+ {
+ value += ep->ed->hoff;
+ if(value > ep->ed->nhlist)
+ beep();
+ else
+ {
+ value = histlines - ep->ed->hlist[value-1]->index;
+ ed_histlist(ep->ed,0);
+ ed_ungetchar(ep->ed,cntl('P'));
+ return(value);
+ }
+ }
+#endif /* SHOPT_EDPREDICT */
+ i = '\\';
+ case '*': /* filename expansion */
+ case '=': /* escape = - list all matching file names */
+ ep->mark = cur;
+ if(ed_expand(ep->ed,(char*)out,&cur,&eol,i,count) < 0)
+ {
+ if(ep->ed->e_tabcount==1)
+ {
+ ep->ed->e_tabcount=2;
+ ed_ungetchar(ep->ed,cntl('\t'));
+ return(-1);
+ }
+ beep();
+ }
+ else if(i=='=')
+ {
+ draw(ep,REFRESH);
+ if(count>0)
+ ep->ed->e_tabcount=0;
+ else
+ {
+ i=ed_getchar(ep->ed,0);
+ ed_ungetchar(ep->ed,i);
+ if(isdigit(i))
+ ed_ungetchar(ep->ed,ESC);
+ }
+ }
+ else
+ {
+ if(i=='\\' && cur>ep->mark && (out[cur-1]=='/' || out[cur-1]==' '))
+ ep->ed->e_tabcount=0;
+ draw(ep,UPDATE);
+ }
+ return(-1);
+
+ /* search back for character */
+ case cntl(']'): /* feature not in book */
+ {
+ int c = ed_getchar(ep->ed,1);
+ if ((value == 0) || (value > eol))
+ {
+ beep();
+ return(-1);
+ }
+ i = cur;
+ if (i > 0)
+ i--;
+ while (i >= 0)
+ {
+ if (out[i] == c && --value==0)
+ goto update;
+ i--;
+ }
+ i = eol;
+ while (i > cur)
+ {
+ if (out[i] == c && --value==0)
+ break;
+ i--;
+ };
+
+ }
+ update:
+ cur = i;
+ draw(ep,UPDATE);
+ return(-1);
+
+#ifdef _cmd_tput
+ case cntl('L'): /* clear screen */
+ sh_trap("tput clear", 0);
+ draw(ep,REFRESH);
+ return(-1);
+#endif
+ case '[': /* feature not in book */
+ switch(i=ed_getchar(ep->ed,1))
+ {
+ case 'A':
+#if SHOPT_EDPREDICT
+ if(!ep->ed->hlist && cur>0 && eol==cur && (cur<(SEARCHSIZE-2) || ep->prevdirection == -2))
+#else
+ if(cur>0 && eol==cur && (cur<(SEARCHSIZE-2) || ep->prevdirection == -2))
+#endif /* SHOPT_EDPREDICT */
+ {
+ if(ep->lastdraw==APPEND && ep->prevdirection != -2)
+ {
+ out[cur] = 0;
+ gencpy((genchar*)lstring+1,out);
+#if SHOPT_MULTIBYTE
+ ed_external((genchar*)lstring+1,lstring+1);
+#endif /* SHOPT_MULTIBYTE */
+ *lstring = '^';
+ ep->prevdirection = -2;
+ }
+ if(*lstring)
+ {
+ ed_ungetchar(ep->ed,'\r');
+ ed_ungetchar(ep->ed,cntl('R'));
+ return(-1);
+ }
+ }
+ *lstring = 0;
+ ed_ungetchar(ep->ed,cntl('P'));
+ return(-1);
+ case 'B':
+ ed_ungetchar(ep->ed,cntl('N'));
+ return(-1);
+ case 'C':
+ ed_ungetchar(ep->ed,cntl('F'));
+ return(-1);
+ case 'D':
+ ed_ungetchar(ep->ed,cntl('B'));
+ return(-1);
+ case 'H':
+ ed_ungetchar(ep->ed,cntl('A'));
+ return(-1);
+ case 'Y':
+ ed_ungetchar(ep->ed,cntl('E'));
+ return(-1);
+ default:
+ ed_ungetchar(ep->ed,i);
+ }
+ i = '_';
+
+ default:
+ /* look for user defined macro definitions */
+ if(ed_macro(ep->ed,i))
+# ifdef ESH_BETTER
+ return(count); /* pass argument to macro */
+# else
+ return(-1);
+# endif /* ESH_BETTER */
+#else
+ update:
+ cur = i;
+ draw(ep,UPDATE);
+ return(-1);
+
+ default:
+#endif /* KSHELL */
+ beep();
+ return(-1);
+ }
+ return(-1);
+}
+
+
+/*
+ * This routine process all commands starting with ^X
+ */
+
+static void xcommands(register Emacs_t *ep,int count)
+{
+ register int i = ed_getchar(ep->ed,0);
+ NOT_USED(count);
+ switch(i)
+ {
+ case cntl('X'): /* exchange dot and mark */
+ if (ep->mark > eol)
+ ep->mark = eol;
+ i = ep->mark;
+ ep->mark = cur;
+ cur = i;
+ draw(ep,UPDATE);
+ return;
+
+#if KSHELL
+# ifdef ESH_BETTER
+ case cntl('E'): /* invoke emacs on current command */
+ if(ed_fulledit(ep->ed)==-1)
+ beep();
+ else
+ {
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)drawbuff,drawbuff);
+#endif /* SHOPT_MULTIBYTE */
+ ed_ungetchar(ep->ed,'\n');
+ }
+ return;
+
+# define itos(i) fmtbase((long)(i),0,0)/* want signed conversion */
+
+ case cntl('H'): /* ^X^H show history info */
+ {
+ char hbuf[MAXLINE];
+
+ strcpy(hbuf, "Current command ");
+ strcat(hbuf, itos(hline));
+ if (hloff)
+ {
+ strcat(hbuf, " (line ");
+ strcat(hbuf, itos(hloff+1));
+ strcat(hbuf, ")");
+ }
+ if ((hline != location.hist_command) ||
+ (hloff != location.hist_line))
+ {
+ strcat(hbuf, "; Previous command ");
+ strcat(hbuf, itos(location.hist_command));
+ if (location.hist_line)
+ {
+ strcat(hbuf, " (line ");
+ strcat(hbuf, itos(location.hist_line+1));
+ strcat(hbuf, ")");
+ }
+ }
+ show_info(ep,hbuf);
+ return;
+ }
+# if 0 /* debugging, modify as required */
+ case cntl('D'): /* ^X^D show debugging info */
+ {
+ char debugbuf[MAXLINE];
+
+ strcpy(debugbuf, "count=");
+ strcat(debugbuf, itos(count));
+ strcat(debugbuf, " eol=");
+ strcat(debugbuf, itos(eol));
+ strcat(debugbuf, " cur=");
+ strcat(debugbuf, itos(cur));
+ strcat(debugbuf, " crallowed=");
+ strcat(debugbuf, itos(crallowed));
+ strcat(debugbuf, " plen=");
+ strcat(debugbuf, itos(plen));
+ strcat(debugbuf, " w_size=");
+ strcat(debugbuf, itos(w_size));
+
+ show_info(ep,debugbuf);
+ return;
+ }
+# endif /* debugging code */
+# endif /* ESH_BETTER */
+#endif /* KSHELL */
+
+ default:
+ beep();
+ return;
+ }
+}
+
+static void search(Emacs_t* ep,genchar *out,int direction)
+{
+#ifndef ESH_NFIRST
+ Histloc_t location;
+#endif
+ register int i,sl;
+ genchar str_buff[LBUF];
+ register genchar *string = drawbuff;
+ /* save current line */
+ int sav_cur = cur;
+ genncpy(str_buff,string,sizeof(str_buff)/sizeof(*str_buff));
+ string[0] = '^';
+ string[1] = 'R';
+ string[2] = '\0';
+ sl = 2;
+ cur = sl;
+ draw(ep,UPDATE);
+ while ((i = ed_getchar(ep->ed,1))&&(i != '\r')&&(i != '\n'))
+ {
+ if (i==usrerase || i==DELETE || i=='\b' || i==ERASECHAR)
+ {
+ if (sl > 2)
+ {
+ string[--sl] = '\0';
+ cur = sl;
+ draw(ep,UPDATE);
+ }
+ else
+ goto restore;
+ continue;
+ }
+ if(i == ep->ed->e_intr)
+ goto restore;
+ if (i==usrkill)
+ {
+ beep();
+ goto restore;
+ }
+ if (i == '\\')
+ {
+ string[sl++] = '\\';
+ string[sl] = '\0';
+ cur = sl;
+ draw(ep,APPEND);
+ i = ed_getchar(ep->ed,1);
+ string[--sl] = '\0';
+ }
+ string[sl++] = i;
+ string[sl] = '\0';
+ cur = sl;
+ draw(ep,APPEND);
+ }
+ i = genlen(string);
+
+ if(ep->prevdirection == -2 && i!=2 || direction!=1)
+ ep->prevdirection = -1;
+ if (direction < 1)
+ {
+ ep->prevdirection = -ep->prevdirection;
+ direction = 1;
+ }
+ else
+ direction = -1;
+ if (i != 2)
+ {
+#if SHOPT_MULTIBYTE
+ ed_external(string,(char*)string);
+#endif /* SHOPT_MULTIBYTE */
+ strncpy(lstring,((char*)string)+2,SEARCHSIZE);
+ lstring[SEARCHSIZE-1] = 0;
+ ep->prevdirection = direction;
+ }
+ else
+ direction = ep->prevdirection ;
+ location = hist_find(shgd->hist_ptr,(char*)lstring,hline,1,direction);
+ i = location.hist_command;
+ if(i>0)
+ {
+ hline = i;
+#ifdef ESH_NFIRST
+ hloff = location.hist_line = 0; /* display first line of multi line command */
+#else
+ hloff = location.hist_line;
+#endif /* ESH_NFIRST */
+ hist_copy((char*)out,MAXLINE, hline,hloff);
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)out,out);
+#endif /* SHOPT_MULTIBYTE */
+ return;
+ }
+ if (i < 0)
+ {
+ beep();
+#ifdef ESH_NFIRST
+ location.hist_command = hline;
+ location.hist_line = hloff;
+#else
+ hloff = 0;
+ hline = histlines;
+#endif /* ESH_NFIRST */
+ }
+restore:
+ genncpy(string,str_buff,sizeof(str_buff)/sizeof(*str_buff));
+ cur = sav_cur;
+ return;
+}
+
+
+/* Adjust screen to agree with inputs: logical line and cursor */
+/* If 'first' assume screen is blank */
+/* Prompt is always kept on the screen */
+
+static void draw(register Emacs_t *ep,Draw_t option)
+{
+#define NORMAL ' '
+#define LOWER '<'
+#define BOTH '*'
+#define UPPER '>'
+
+ register genchar *sptr; /* Pointer within screen */
+ genchar nscreen[2*MAXLINE]; /* New entire screen */
+ genchar *ncursor; /* New cursor */
+ register genchar *nptr; /* Pointer to New screen */
+ char longline; /* Line overflow */
+ genchar *logcursor;
+ genchar *nscend; /* end of logical screen */
+ register int i;
+
+ nptr = nscreen;
+ sptr = drawbuff;
+ logcursor = sptr + cur;
+ longline = NORMAL;
+ ep->lastdraw = option;
+
+ if (option == FIRST || option == REFRESH)
+ {
+ ep->overflow = NORMAL;
+ ep->cursor = ep->screen;
+ ep->offset = 0;
+ ep->cr_ok = crallowed;
+ if (option == FIRST)
+ {
+ ep->scvalid = 1;
+ return;
+ }
+ *ep->cursor = '\0';
+ putstring(ep,Prompt); /* start with prompt */
+ }
+
+ /*********************
+ Do not update screen if pending characters
+ **********************/
+
+ if ((lookahead)&&(option != FINAL))
+ {
+
+ ep->scvalid = 0; /* Screen is out of date, APPEND will not work */
+
+ return;
+ }
+
+ /***************************************
+ If in append mode, cursor at end of line, screen up to date,
+ the previous character was a 'normal' character,
+ and the window has room for another character.
+ Then output the character and adjust the screen only.
+ *****************************************/
+
+
+ i = *(logcursor-1); /* last character inserted */
+#if SHOPT_EDPREDICT
+ if(option==FINAL)
+ {
+ if(ep->ed->hlist)
+ ed_histlist(ep->ed,0);
+ }
+ else if((option==UPDATE||option==APPEND) && drawbuff[0]=='#' && cur>1 && cur==eol && drawbuff[cur-1]!='*')
+ {
+ int n;
+ drawbuff[cur+1]=0;
+# if SHOPT_MULTIBYTE
+ ed_external(drawbuff,(char*)drawbuff);
+# endif /*SHOPT_MULTIBYTE */
+ n = ed_histgen(ep->ed,(char*)drawbuff);
+# if SHOPT_MULTIBYTE
+ ed_internal((char*)drawbuff,drawbuff);
+# endif /*SHOPT_MULTIBYTE */
+ if(ep->ed->hlist)
+ {
+ ed_histlist(ep->ed,n);
+ putstring(ep,Prompt);
+ ed_setcursor(ep->ed,ep->screen,0,ep->cursor-ep->screen, 0);
+ }
+ else
+ ed_ringbell();
+
+ }
+#endif /* SHOPT_EDPREDICT */
+
+ if ((option == APPEND)&&(ep->scvalid)&&(*logcursor == '\0')&&
+ print(i)&&((ep->cursor-ep->screen)<(w_size-1)))
+ {
+ putchar(ep->ed,i);
+ *ep->cursor++ = i;
+ *ep->cursor = '\0';
+ return;
+ }
+
+ /* copy the line */
+ ncursor = nptr + ed_virt_to_phys(ep->ed,sptr,nptr,cur,0,0);
+ nptr += genlen(nptr);
+ sptr += genlen(sptr);
+ nscend = nptr - 1;
+ if(sptr == logcursor)
+ ncursor = nptr;
+
+ /*********************
+ Does ncursor appear on the screen?
+ If not, adjust the screen offset so it does.
+ **********************/
+
+ i = ncursor - nscreen;
+
+ if ((ep->offset && i<=ep->offset)||(i >= (ep->offset+w_size)))
+ {
+ /* Center the cursor on the screen */
+ ep->offset = i - (w_size>>1);
+ if (--ep->offset < 0)
+ ep->offset = 0;
+ }
+
+ /*********************
+ Is the range of screen[0] thru screen[w_size] up-to-date
+ with nscreen[offset] thru nscreen[offset+w_size] ?
+ If not, update as need be.
+ ***********************/
+
+ nptr = &nscreen[ep->offset];
+ sptr = ep->screen;
+
+ i = w_size;
+
+ while (i-- > 0)
+ {
+
+ if (*nptr == '\0')
+ {
+ *(nptr + 1) = '\0';
+ *nptr = ' ';
+ }
+ if (*sptr == '\0')
+ {
+ *(sptr + 1) = '\0';
+ *sptr = ' ';
+ }
+ if (*nptr == *sptr)
+ {
+ nptr++;
+ sptr++;
+ continue;
+ }
+ setcursor(ep,sptr-ep->screen,*nptr);
+ *sptr++ = *nptr++;
+#if SHOPT_MULTIBYTE
+ while(*nptr==MARKER)
+ {
+ if(*sptr=='\0')
+ *(sptr + 1) = '\0';
+ *sptr++ = *nptr++;
+ i--;
+ ep->cursor++;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ }
+ if(ep->ed->e_multiline && option == REFRESH && ep->ed->e_nocrnl==0)
+ ed_setcursor(ep->ed, ep->screen, ep->cursor-ep->screen, ep->ed->e_peol, -1);
+
+
+ /******************
+
+ Screen overflow checks
+
+ ********************/
+
+ if (nscend >= &nscreen[ep->offset+w_size])
+ {
+ if (ep->offset > 0)
+ longline = BOTH;
+ else
+ longline = UPPER;
+ }
+ else
+ {
+ if (ep->offset > 0)
+ longline = LOWER;
+ }
+
+ /* Update screen overflow indicator if need be */
+
+ if (longline != ep->overflow)
+ {
+ setcursor(ep,w_size,longline);
+ ep->overflow = longline;
+ }
+ i = (ncursor-nscreen) - ep->offset;
+ setcursor(ep,i,0);
+ if(option==FINAL && ep->ed->e_multiline)
+ setcursor(ep,nscend+1-nscreen,0);
+ ep->scvalid = 1;
+ return;
+}
+
+/*
+ * put the cursor to the <newp> position within screen buffer
+ * if <c> is non-zero then output this character
+ * cursor is set to reflect the change
+ */
+
+static void setcursor(register Emacs_t *ep,register int newp,int c)
+{
+ register int oldp = ep->cursor - ep->screen;
+ newp = ed_setcursor(ep->ed, ep->screen, oldp, newp, 0);
+ if(c)
+ {
+ putchar(ep->ed,c);
+ newp++;
+ }
+ ep->cursor = ep->screen+newp;
+ return;
+}
+
+#if SHOPT_MULTIBYTE
+static int print(register int c)
+{
+ return((c&~STRIP)==0 && isprint(c));
+}
+
+static int _isword(register int c)
+{
+ return((c&~STRIP) || isalnum(c) || c=='_');
+}
+#endif /* SHOPT_MULTIBYTE */
diff --git a/src/cmd/ksh93/edit/hexpand.c b/src/cmd/ksh93/edit/hexpand.c
new file mode 100644
index 0000000..3e2d396
--- /dev/null
+++ b/src/cmd/ksh93/edit/hexpand.c
@@ -0,0 +1,734 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * bash style history expansion
+ *
+ * Author:
+ * Karsten Fleischer
+ * Omnium Software Engineering
+ * An der Luisenburg 7
+ * D-51379 Leverkusen
+ * Germany
+ *
+ * <K.Fleischer@omnium.de>
+ */
+
+
+#include "defs.h"
+#include "edit.h"
+
+#if ! SHOPT_HISTEXPAND
+
+NoN(hexpand)
+
+#else
+
+static char *modifiers = "htrepqxs&";
+static int mod_flags[] = { 0, 0, 0, 0, HIST_PRINT, HIST_QUOTE, HIST_QUOTE|HIST_QUOTE_BR, 0, 0 };
+
+#define DONE() {flag |= HIST_ERROR; cp = 0; stakseek(0); goto done;}
+
+struct subst
+{
+ char *str[2]; /* [0] is "old", [1] is "new" string */
+};
+
+
+/*
+ * parse an /old/new/ string, delimiter expected as first char.
+ * if "old" not specified, keep sb->str[0]
+ * if "new" not specified, set sb->str[1] to empty string
+ * read up to third delimeter char, \n or \0, whichever comes first.
+ * return adress is one past the last valid char in s:
+ * - the address containing \n or \0 or
+ * - one char beyond the third delimiter
+ */
+
+static char *parse_subst(const char *s, struct subst *sb)
+{
+ char *cp,del;
+ int off,n = 0;
+
+ /* build the strings on the stack, mainly for '&' substition in "new" */
+ off = staktell();
+
+ /* init "new" with empty string */
+ if(sb->str[1])
+ free(sb->str[1]);
+ sb->str[1] = strdup("");
+
+ /* get delimiter */
+ del = *s;
+
+ cp = (char*) s + 1;
+
+ while(n < 2)
+ {
+ if(*cp == del || *cp == '\n' || *cp == '\0')
+ {
+ /* delimiter or EOL */
+ if(staktell() != off)
+ {
+ /* dupe string on stack and rewind stack */
+ stakputc('\0');
+ if(sb->str[n])
+ free(sb->str[n]);
+ sb->str[n] = strdup(stakptr(off));
+ stakseek(off);
+ }
+ n++;
+
+ /* if not delimiter, we've reached EOL. Get outta here. */
+ if(*cp != del)
+ break;
+ }
+ else if(*cp == '\\')
+ {
+ if(*(cp+1) == del) /* quote delimiter */
+ {
+ stakputc(del);
+ cp++;
+ }
+ else if(*(cp+1) == '&' && n == 1)
+ { /* quote '&' only in "new" */
+ stakputc('&');
+ cp++;
+ }
+ else
+ stakputc('\\');
+ }
+ else if(*cp == '&' && n == 1 && sb->str[0])
+ /* substitute '&' with "old" in "new" */
+ stakputs(sb->str[0]);
+ else
+ stakputc(*cp);
+ cp++;
+ }
+
+ /* rewind stack */
+ stakseek(off);
+
+ return cp;
+}
+
+/*
+ * history expansion main routine
+ */
+
+int hist_expand(const char *ln, char **xp)
+{
+ int off, /* stack offset */
+ q, /* quotation flags */
+ p, /* flag */
+ c, /* current char */
+ flag=0; /* HIST_* flags */
+ Sfoff_t n, /* history line number, counter, etc. */
+ i, /* counter */
+ w[2]; /* word range */
+ char *sp, /* stack pointer */
+ *cp, /* current char in ln */
+ *str, /* search string */
+ *evp, /* event/word designator string, for error msgs */
+ *cc=0, /* copy of current line up to cp; temp ptr */
+ hc[3], /* default histchars */
+ *qc="\'\"`"; /* quote characters */
+ Sfio_t *ref=0, /* line referenced by event designator */
+ *tmp=0, /* temporary line buffer */
+ *tmp2=0;/* temporary line buffer */
+ Histloc_t hl; /* history location */
+ static Namval_t *np = 0; /* histchars variable */
+ static struct subst sb = {0,0}; /* substition strings */
+ static Sfio_t *wm=0; /* word match from !?string? event designator */
+
+ if(!wm)
+ wm = sfopen(NULL, NULL, "swr");
+
+ hc[0] = '!';
+ hc[1] = '^';
+ hc[2] = 0;
+ if((np = nv_open("histchars",sh.var_tree,0)) && (cp = nv_getval(np)))
+ {
+ if(cp[0])
+ {
+ hc[0] = cp[0];
+ if(cp[1])
+ {
+ hc[1] = cp[1];
+ if(cp[2])
+ hc[2] = cp[2];
+ }
+ }
+ }
+
+ /* save shell stack */
+ if(off = staktell())
+ sp = stakfreeze(0);
+
+ cp = (char*)ln;
+
+ while(cp && *cp)
+ {
+ /* read until event/quick substitution/comment designator */
+ if((*cp != hc[0] && *cp != hc[1] && *cp != hc[2])
+ || (*cp == hc[1] && cp != ln))
+ {
+ if(*cp == '\\') /* skip escaped designators */
+ stakputc(*cp++);
+ else if(*cp == '\'') /* skip quoted designators */
+ {
+ do
+ stakputc(*cp);
+ while(*++cp && *cp != '\'');
+ }
+ stakputc(*cp++);
+ continue;
+ }
+
+ if(hc[2] && *cp == hc[2]) /* history comment designator, skip rest of line */
+ {
+ stakputc(*cp++);
+ stakputs(cp);
+ DONE();
+ }
+
+ n = -1;
+ str = 0;
+ flag &= HIST_EVENT; /* save event flag for returning later */
+ evp = cp;
+ ref = 0;
+
+ if(*cp == hc[1]) /* shortcut substitution */
+ {
+ flag |= HIST_QUICKSUBST;
+ goto getline;
+ }
+
+ if(*cp == hc[0] && *(cp+1) == hc[0]) /* refer to line -1 */
+ {
+ cp += 2;
+ goto getline;
+ }
+
+ switch(c = *++cp) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\0':
+ case '=':
+ case '(':
+ stakputc(hc[0]);
+ continue;
+ case '#': /* the line up to current position */
+ flag |= HIST_HASH;
+ cp++;
+ n = staktell(); /* terminate string and dup */
+ stakputc('\0');
+ cc = strdup(stakptr(0));
+ stakseek(n); /* remove null byte again */
+ ref = sfopen(ref, cc, "s"); /* open as file */
+ n = 0; /* skip history file referencing */
+ break;
+ case '-': /* back reference by number */
+ if(!isdigit(*(cp+1)))
+ goto string_event;
+ cp++;
+ case '0': /* reference by number */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = 0;
+ while(isdigit(*cp))
+ n = n * 10 + (*cp++) - '0';
+ if(c == '-')
+ n = -n;
+ break;
+ case '$':
+ n = -1;
+ case ':':
+ break;
+ case '?':
+ cp++;
+ flag |= HIST_QUESTION;
+ string_event:
+ default:
+ /* read until end of string or word designator/modifier */
+ str = cp;
+ while(*cp)
+ {
+ cp++;
+ if((!(flag&HIST_QUESTION) &&
+ (*cp == ':' || isspace(*cp)
+ || *cp == '^' || *cp == '$'
+ || *cp == '*' || *cp == '-'
+ || *cp == '%')
+ )
+ || ((flag&HIST_QUESTION) && (*cp == '?' || *cp == '\n')))
+ {
+ c = *cp;
+ *cp = '\0';
+ }
+ }
+ break;
+ }
+
+getline:
+ flag |= HIST_EVENT;
+ if(str) /* !string or !?string? event designator */
+ {
+
+ /* search history for string */
+ hl = hist_find(shgd->hist_ptr, str,
+ shgd->hist_ptr->histind,
+ flag&HIST_QUESTION, -1);
+ if((n = hl.hist_command) == -1)
+ n = 0; /* not found */
+ }
+ if(n)
+ {
+ if(n < 0) /* determine index for backref */
+ n = shgd->hist_ptr->histind + n;
+ /* search and use history file if found */
+ if(n > 0 && hist_seek(shgd->hist_ptr, n) != -1)
+ ref = shgd->hist_ptr->histfp;
+
+ }
+ if(!ref)
+ {
+ /* string not found or command # out of range */
+ c = *cp;
+ *cp = '\0';
+ errormsg(SH_DICT, ERROR_ERROR, "%s: event not found", evp);
+ *cp = c;
+ DONE();
+ }
+
+ if(str) /* string search: restore orig. line */
+ {
+ if(flag&HIST_QUESTION)
+ *cp++ = c; /* skip second question mark */
+ else
+ *cp = c;
+ }
+
+ /* colon introduces either word designators or modifiers */
+ if(*(evp = cp) == ':')
+ cp++;
+
+ w[0] = 0; /* -1 means last word, -2 means match from !?string? */
+ w[1] = -1; /* -1 means last word, -2 means suppress last word */
+
+ if(flag & HIST_QUICKSUBST) /* shortcut substitution */
+ goto getsel;
+
+ n = 0;
+ while(n < 2)
+ {
+ switch(c = *cp++) {
+ case '^': /* first word */
+ if(n == 0)
+ {
+ w[0] = w[1] = 1;
+ goto skip;
+ }
+ else
+ goto skip2;
+ case '$': /* last word */
+ w[n] = -1;
+ goto skip;
+ case '%': /* match from !?string? event designator */
+ if(n == 0)
+ {
+ if(!str)
+ {
+ w[0] = 0;
+ w[1] = -1;
+ ref = wm;
+ }
+ else
+ {
+ w[0] = -2;
+ w[1] = sftell(ref) + hl.hist_char;
+ }
+ sfseek(wm, 0, SEEK_SET);
+ goto skip;
+ }
+ default:
+ skip2:
+ cp--;
+ n = 2;
+ break;
+ case '*': /* until last word */
+ if(n == 0)
+ w[0] = 1;
+ w[1] = -1;
+ skip:
+ flag |= HIST_WORDDSGN;
+ n = 2;
+ break;
+ case '-': /* until last word or specified index */
+ w[1] = -2;
+ flag |= HIST_WORDDSGN;
+ n = 1;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': /* specify index */
+ if((*evp == ':') || w[1] == -2)
+ {
+ w[n] = c - '0';
+ while(isdigit(c=*cp++))
+ w[n] = w[n] * 10 + c - '0';
+ flag |= HIST_WORDDSGN;
+ if(n == 0)
+ w[1] = w[0];
+ n++;
+ }
+ else
+ n = 2;
+ cp--;
+ break;
+ }
+ }
+
+ if(w[0] != -2 && w[1] > 0 && w[0] > w[1])
+ {
+ c = *cp;
+ *cp = '\0';
+ errormsg(SH_DICT, ERROR_ERROR, "%s: bad word specifier", evp);
+ *cp = c;
+ DONE();
+ }
+
+ /* no valid word designator after colon, rewind */
+ if(!(flag & HIST_WORDDSGN) && (*evp == ':'))
+ cp = evp;
+
+getsel:
+ /* open temp buffer, let sfio do the (re)allocation */
+ tmp = sfopen(NULL, NULL, "swr");
+
+ /* push selected words into buffer, squash
+ whitespace into single blank or a newline */
+ n = i = q = 0;
+
+ while((c = sfgetc(ref)) > 0)
+ {
+ if(isspace(c))
+ {
+ flag |= (c == '\n' ? HIST_NEWLINE : 0);
+ continue;
+ }
+
+ if(n >= w[0] && ((w[0] != -2) ? (w[1] < 0 || n <= w[1]) : 1))
+ {
+ if(w[0] < 0)
+ sfseek(tmp, 0, SEEK_SET);
+ else
+ i = sftell(tmp);
+
+ if(i > 0)
+ sfputc(tmp, flag & HIST_NEWLINE ? '\n' : ' ');
+
+ flag &= ~HIST_NEWLINE;
+ p = 1;
+ }
+ else
+ p = 0;
+
+ do
+ {
+ cc = strchr(qc, c);
+ q ^= cc ? 1<<(int)(cc - qc) : 0;
+ if(p)
+ sfputc(tmp, c);
+ }
+ while((c = sfgetc(ref)) > 0 && (!isspace(c) || q));
+
+ if(w[0] == -2 && sftell(ref) > w[1])
+ break;
+
+ flag |= (c == '\n' ? HIST_NEWLINE : 0);
+ n++;
+ }
+ if(w[0] != -2 && w[1] >= 0 && w[1] >= n)
+ {
+ c = *cp;
+ *cp = '\0';
+ errormsg(SH_DICT, ERROR_ERROR, "%s: bad word specifier", evp);
+ *cp = c;
+ DONE();
+ }
+ else if(w[1] == -2) /* skip last word */
+ sfseek(tmp, i, SEEK_SET);
+
+ /* remove trailing newline */
+ if(sftell(tmp))
+ {
+ sfseek(tmp, -1, SEEK_CUR);
+ if(sfgetc(tmp) == '\n')
+ sfungetc(tmp, '\n');
+ }
+
+ sfputc(tmp, '\0');
+
+ if(str)
+ {
+ if(wm)
+ sfclose(wm);
+ wm = tmp;
+ }
+
+ if(cc && (flag&HIST_HASH))
+ {
+ /* close !# temp file */
+ sfclose(ref);
+ flag &= ~HIST_HASH;
+ free(cc);
+ cc = 0;
+ }
+
+ evp = cp;
+
+ /* selected line/words are now in buffer, now go for the modifiers */
+ while(*cp == ':' || (flag & HIST_QUICKSUBST))
+ {
+ if(flag & HIST_QUICKSUBST)
+ {
+ flag &= ~HIST_QUICKSUBST;
+ c = 's';
+ cp--;
+ }
+ else
+ c = *++cp;
+
+ sfseek(tmp, 0, SEEK_SET);
+ tmp2 = sfopen(tmp2, NULL, "swr");
+
+ if(c == 'g') /* global substitution */
+ {
+ flag |= HIST_GLOBALSUBST;
+ c = *++cp;
+ }
+
+ if(cc = strchr(modifiers, c))
+ flag |= mod_flags[cc - modifiers];
+ else
+ {
+ errormsg(SH_DICT, ERROR_ERROR, "%c: unrecognized history modifier", c);
+ DONE();
+ }
+
+ if(c == 'h' || c == 'r') /* head or base */
+ {
+ n = -1;
+ while((c = sfgetc(tmp)) > 0)
+ { /* remember position of / or . */
+ if((c == '/' && *cp == 'h') || (c == '.' && *cp == 'r'))
+ n = sftell(tmp2);
+ sfputc(tmp2, c);
+ }
+ if(n > 0)
+ { /* rewind to last / or . */
+ sfseek(tmp2, n, SEEK_SET);
+ /* end string there */
+ sfputc(tmp2, '\0');
+ }
+ }
+ else if(c == 't' || c == 'e') /* tail or suffix */
+ {
+ n = 0;
+ while((c = sfgetc(tmp)) > 0)
+ { /* remember position of / or . */
+ if((c == '/' && *cp == 't') || (c == '.' && *cp == 'e'))
+ n = sftell(tmp);
+ }
+ /* rewind to last / or . */
+ sfseek(tmp, n, SEEK_SET);
+ /* copy from there on */
+ while((c = sfgetc(tmp)) > 0)
+ sfputc(tmp2, c);
+ }
+ else if(c == 's' || c == '&')
+ {
+ cp++;
+
+ if(c == 's')
+ {
+ /* preset old with match from !?string? */
+ if(!sb.str[0] && wm)
+ sb.str[0] = strdup(sfsetbuf(wm, (Void_t*)1, 0));
+ cp = parse_subst(cp, &sb);
+ }
+
+ if(!sb.str[0] || !sb.str[1])
+ {
+ c = *cp;
+ *cp = '\0';
+ errormsg(SH_DICT, ERROR_ERROR,
+ "%s%s: no previous substitution",
+ (flag & HIST_QUICKSUBST) ? ":s" : "",
+ evp);
+ *cp = c;
+ DONE();
+ }
+
+ /* need pointer for strstr() */
+ str = sfsetbuf(tmp, (Void_t*)1, 0);
+
+ flag |= HIST_SUBSTITUTE;
+ while(flag & HIST_SUBSTITUTE)
+ {
+ /* find string */
+ if(cc = strstr(str, sb.str[0]))
+ { /* replace it */
+ c = *cc;
+ *cc = '\0';
+ sfputr(tmp2, str, -1);
+ sfputr(tmp2, sb.str[1], -1);
+ *cc = c;
+ str = cc + strlen(sb.str[0]);
+ }
+ else if(!sftell(tmp2))
+ { /* not successfull */
+ c = *cp;
+ *cp = '\0';
+ errormsg(SH_DICT, ERROR_ERROR,
+ "%s%s: substitution failed",
+ (flag & HIST_QUICKSUBST) ? ":s" : "",
+ evp);
+ *cp = c;
+ DONE();
+ }
+ /* loop if g modifier specified */
+ if(!cc || !(flag & HIST_GLOBALSUBST))
+ flag &= ~HIST_SUBSTITUTE;
+ }
+ /* output rest of line */
+ sfputr(tmp2, str, -1);
+ if(*cp)
+ cp--;
+ }
+
+ if(sftell(tmp2))
+ { /* if any substitions done, swap buffers */
+ if(wm != tmp)
+ sfclose(tmp);
+ tmp = tmp2;
+ tmp2 = 0;
+ }
+ cc = 0;
+ if(*cp)
+ cp++;
+ }
+
+ /* flush temporary buffer to stack */
+ if(tmp)
+ {
+ sfseek(tmp, 0, SEEK_SET);
+
+ if(flag & HIST_QUOTE)
+ stakputc('\'');
+
+ while((c = sfgetc(tmp)) > 0)
+ {
+ if(isspace(c))
+ {
+ flag = flag & ~HIST_NEWLINE;
+
+ /* squash white space to either a
+ blank or a newline */
+ do
+ flag |= (c == '\n' ? HIST_NEWLINE : 0);
+ while((c = sfgetc(tmp)) > 0 && isspace(c));
+
+ sfungetc(tmp, c);
+
+ c = (flag & HIST_NEWLINE) ? '\n' : ' ';
+
+ if(flag & HIST_QUOTE_BR)
+ {
+ stakputc('\'');
+ stakputc(c);
+ stakputc('\'');
+ }
+ else
+ stakputc(c);
+ }
+ else if((c == '\'') && (flag & HIST_QUOTE))
+ {
+ stakputc('\'');
+ stakputc('\\');
+ stakputc(c);
+ stakputc('\'');
+ }
+ else
+ stakputc(c);
+ }
+ if(flag & HIST_QUOTE)
+ stakputc('\'');
+ }
+ }
+
+ stakputc('\0');
+
+done:
+ if(cc && (flag&HIST_HASH))
+ {
+ /* close !# temp file */
+ sfclose(ref);
+ free(cc);
+ cc = 0;
+ }
+
+ /* error? */
+ if(staktell() && !(flag & HIST_ERROR))
+ *xp = strdup(stakfreeze(1));
+
+ /* restore shell stack */
+ if(off)
+ stakset(sp,off);
+ else
+ stakseek(0);
+
+ /* drop temporary files */
+
+ if(tmp && tmp != wm)
+ sfclose(tmp);
+ if(tmp2)
+ sfclose(tmp2);
+
+ return (flag & HIST_ERROR ? HIST_ERROR : flag & HIST_FLAG_RETURN_MASK);
+}
+
+#endif
diff --git a/src/cmd/ksh93/edit/history.c b/src/cmd/ksh93/edit/history.c
new file mode 100644
index 0000000..99fc01d
--- /dev/null
+++ b/src/cmd/ksh93/edit/history.c
@@ -0,0 +1,1222 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * History file manipulation routines
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+/*
+ * Each command in the history file starts on an even byte is null terminated.
+ * The first byte must contain the special character HIST_UNDO and the second
+ * byte is the version number. The sequence HIST_UNDO 0, following a command,
+ * nullifies the previous command. A six byte sequence starting with
+ * HIST_CMDNO is used to store the command number so that it is not necessary
+ * to read the file from beginning to end to get to the last block of
+ * commands. This format of this sequence is different in version 1
+ * then in version 0. Version 1 allows commands to use the full 8 bit
+ * character set. It can understand version 0 format files.
+ */
+
+
+#define HIST_MAX (sizeof(int)*HIST_BSIZE)
+#define HIST_BIG (0100000-1024) /* 1K less than maximum short */
+#define HIST_LINE 32 /* typical length for history line */
+#define HIST_MARKSZ 6
+#define HIST_RECENT 600
+#define HIST_UNDO 0201 /* invalidate previous command */
+#define HIST_CMDNO 0202 /* next 3 bytes give command number */
+#define HIST_BSIZE 4096 /* size of history file buffer */
+#define HIST_DFLT 512 /* default size of history list */
+
+#if SHOPT_AUDIT
+# define _HIST_AUDIT Sfio_t *auditfp; \
+ char *tty; \
+ int auditmask;
+#else
+# define _HIST_AUDIT
+#endif
+
+#define _HIST_PRIVATE \
+ void *histshell; \
+ off_t histcnt; /* offset into history file */\
+ off_t histmarker; /* offset of last command marker */ \
+ int histflush; /* set if flushed outside of hflush() */\
+ int histmask; /* power of two mask for histcnt */ \
+ char histbuff[HIST_BSIZE+1]; /* history file buffer */ \
+ int histwfail; \
+ _HIST_AUDIT \
+ off_t histcmds[2]; /* offset for recent commands, must be last */
+
+#define hist_ind(hp,c) ((int)((c)&(hp)->histmask))
+
+#include <ast.h>
+#include <sfio.h>
+#include "FEATURE/time"
+#include <error.h>
+#include <ls.h>
+#if KSHELL
+# include "defs.h"
+# include "variables.h"
+# include "path.h"
+# include "builtins.h"
+# include "io.h"
+#else
+# include <ctype.h>
+#endif /* KSHELL */
+#include "history.h"
+
+#if !KSHELL
+# define new_of(type,x) ((type*)malloc((unsigned)sizeof(type)+(x)))
+# define NIL(type) ((type)0)
+# define path_relative(s,x) (s,x)
+# ifdef __STDC__
+# define nv_getval(s) getenv(#s)
+# else
+# define nv_getval(s) getenv("s")
+# endif /* __STDC__ */
+# define e_unknown "unknown"
+# define sh_translate(x) (x)
+ char login_sh = 0;
+ char hist_fname[] = "/.history";
+#endif /* KSHELL */
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif /* O_BINARY */
+
+int _Hist = 0;
+static void hist_marker(char*,long);
+static History_t* hist_trim(History_t*, int);
+static int hist_nearend(History_t*,Sfio_t*, off_t);
+static int hist_check(int);
+static int hist_clean(int);
+#ifdef SF_BUFCONST
+ static ssize_t hist_write(Sfio_t*, const void*, size_t, Sfdisc_t*);
+ static int hist_exceptf(Sfio_t*, int, void*, Sfdisc_t*);
+#else
+ static int hist_write(Sfio_t*, const void*, int, Sfdisc_t*);
+ static int hist_exceptf(Sfio_t*, int, Sfdisc_t*);
+#endif
+
+
+static int histinit;
+static mode_t histmode;
+static History_t *wasopen;
+static History_t *hist_ptr;
+
+#if SHOPT_ACCTFILE
+ static int acctfd;
+ static char *logname;
+# include <pwd.h>
+
+ static int acctinit(History_t *hp)
+ {
+ register char *cp, *acctfile;
+ Namval_t *np = nv_search("ACCTFILE",((Shell_t*)hp->histshell)->var_tree,0);
+
+ if(!np || !(acctfile=nv_getval(np)))
+ return(0);
+ if(!(cp = getlogin()))
+ {
+ struct passwd *userinfo = getpwuid(getuid());
+ if(userinfo)
+ cp = userinfo->pw_name;
+ else
+ cp = "unknown";
+ }
+ logname = strdup(cp);
+ if((acctfd=sh_open(acctfile,
+ O_BINARY|O_WRONLY|O_APPEND|O_CREAT,S_IRUSR|S_IWUSR))>=0 &&
+ (unsigned)acctfd < 10)
+ {
+ int n;
+ if((n = fcntl(acctfd, F_DUPFD, 10)) >= 0)
+ {
+ close(acctfd);
+ acctfd = n;
+ }
+ }
+ if(acctfd < 0)
+ {
+ acctfd = 0;
+ return(0);
+ }
+ if(sh_isdevfd(acctfile))
+ {
+ char newfile[16];
+ sfsprintf(newfile,sizeof(newfile),"%.8s%d\0",e_devfdNN,acctfd);
+ nv_putval(np,newfile,NV_RDONLY);
+ }
+ else
+ fcntl(acctfd,F_SETFD,FD_CLOEXEC);
+ return(1);
+ }
+#endif /* SHOPT_ACCTFILE */
+
+#if SHOPT_AUDIT
+static int sh_checkaudit(History_t *hp, const char *name, char *logbuf, size_t len)
+{
+ char *buff, *cp, *last;
+ int id1, id2, r=0, n, fd;
+ if((fd=open(name, O_RDONLY)) < 0)
+ return(0);
+ if((n = read(fd, logbuf,len-1)) < 0)
+ goto done;
+ while(logbuf[n-1]=='\n')
+ n--;
+ logbuf[n] = 0;
+ if(!(cp=strchr(logbuf,';')) && !(cp=strchr(logbuf,' ')))
+ goto done;
+ *cp = 0;
+ do
+ {
+ cp++;
+ id1 = id2 = strtol(cp,&last,10);
+ if(*last=='-')
+ id1 = strtol(last+1,&last,10);
+ if(shgd->euserid >=id1 && shgd->euserid <= id2)
+ r |= 1;
+ if(shgd->userid >=id1 && shgd->userid <= id2)
+ r |= 2;
+ cp = last;
+ }
+ while(*cp==';' || *cp==' ');
+done:
+ close(fd);
+ return(r);
+
+}
+#endif /*SHOPT_AUDIT*/
+
+static const unsigned char hist_stamp[2] = { HIST_UNDO, HIST_VERSION };
+static const Sfdisc_t hist_disc = { NULL, hist_write, NULL, hist_exceptf, NULL};
+
+static void hist_touch(void *handle)
+{
+ touch((char*)handle, (time_t)0, (time_t)0, 0);
+}
+
+/*
+ * open the history file
+ * if HISTNAME is not given and userid==0 then no history file.
+ * if login_sh and HISTFILE is longer than HIST_MAX bytes then it is
+ * cleaned up.
+ * hist_open() returns 1, if history file is open
+ */
+int sh_histinit(void *sh_context)
+{
+ Shell_t *shp = (Shell_t*)sh_context;
+ register int fd;
+ register History_t *hp;
+ register char *histname;
+ char *fname=0;
+ int histmask, maxlines, hist_start=0;
+ register char *cp;
+ register off_t hsize = 0;
+
+ if(shgd->hist_ptr=hist_ptr)
+ return(1);
+ if(!(histname = nv_getval(HISTFILE)))
+ {
+ int offset = staktell();
+ if(cp=nv_getval(HOME))
+ stakputs(cp);
+ stakputs(hist_fname);
+ stakputc(0);
+ stakseek(offset);
+ histname = stakptr(offset);
+ }
+#ifdef future
+ if(hp=wasopen)
+ {
+ /* reuse history file if same name */
+ wasopen = 0;
+ shgd->hist_ptr = hist_ptr = hp;
+ if(strcmp(histname,hp->histname)==0)
+ return(1);
+ else
+ hist_free();
+ }
+#endif
+retry:
+ cp = path_relative(shp,histname);
+ if(!histinit)
+ histmode = S_IRUSR|S_IWUSR;
+ if((fd=open(cp,O_BINARY|O_APPEND|O_RDWR|O_CREAT,histmode))>=0)
+ {
+ hsize=lseek(fd,(off_t)0,SEEK_END);
+ }
+ if((unsigned)fd <=2)
+ {
+ int n;
+ if((n=fcntl(fd,F_DUPFD,10))>=0)
+ {
+ close(fd);
+ fd=n;
+ }
+ }
+ /* make sure that file has history file format */
+ if(hsize && hist_check(fd))
+ {
+ close(fd);
+ hsize = 0;
+ if(unlink(cp)>=0)
+ goto retry;
+ fd = -1;
+ }
+ if(fd < 0)
+ {
+#if KSHELL
+ /* don't allow root a history_file in /tmp */
+ if(shgd->userid)
+#endif /* KSHELL */
+ {
+ if(!(fname = pathtmp(NIL(char*),0,0,NIL(int*))))
+ return(0);
+ fd = open(fname,O_BINARY|O_APPEND|O_CREAT|O_RDWR,S_IRUSR|S_IWUSR);
+ }
+ }
+ if(fd<0)
+ return(0);
+ /* set the file to close-on-exec */
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ if(cp=nv_getval(HISTSIZE))
+ maxlines = (unsigned)strtol(cp, (char**)0, 10);
+ else
+ maxlines = HIST_DFLT;
+ for(histmask=16;histmask <= maxlines; histmask <<=1 );
+ if(!(hp=new_of(History_t,(--histmask)*sizeof(off_t))))
+ {
+ close(fd);
+ return(0);
+ }
+ shgd->hist_ptr = hist_ptr = hp;
+ hp->histshell = (void*)shp;
+ hp->histsize = maxlines;
+ hp->histmask = histmask;
+ hp->histfp= sfnew(NIL(Sfio_t*),hp->histbuff,HIST_BSIZE,fd,SF_READ|SF_WRITE|SF_APPENDWR|SF_SHARE);
+ memset((char*)hp->histcmds,0,sizeof(off_t)*(hp->histmask+1));
+ hp->histind = 1;
+ hp->histcmds[1] = 2;
+ hp->histcnt = 2;
+ hp->histname = strdup(histname);
+ hp->histdisc = hist_disc;
+ if(hsize==0)
+ {
+ /* put special characters at front of file */
+ sfwrite(hp->histfp,(char*)hist_stamp,2);
+ sfsync(hp->histfp);
+ }
+ /* initialize history list */
+ else
+ {
+ int first,last;
+ off_t mark,size = (HIST_MAX/4)+maxlines*HIST_LINE;
+ hp->histind = first = hist_nearend(hp,hp->histfp,hsize-size);
+ histinit = 1;
+ hist_eof(hp); /* this sets histind to last command */
+ if((hist_start = (last=(int)hp->histind)-maxlines) <=0)
+ hist_start = 1;
+ mark = hp->histmarker;
+ while(first > hist_start)
+ {
+ size += size;
+ first = hist_nearend(hp,hp->histfp,hsize-size);
+ hp->histind = first;
+ }
+ histinit = hist_start;
+ hist_eof(hp);
+ if(!histinit)
+ {
+ sfseek(hp->histfp,hp->histcnt=hsize,SEEK_SET);
+ hp->histind = last;
+ hp->histmarker = mark;
+ }
+ histinit = 0;
+ }
+ if(fname)
+ {
+ unlink(fname);
+ free((void*)fname);
+ }
+ if(hist_clean(fd) && hist_start>1 && hsize > HIST_MAX)
+ {
+#ifdef DEBUG
+ sfprintf(sfstderr,"%d: hist_trim hsize=%d\n",getpid(),hsize);
+ sfsync(sfstderr);
+#endif /* DEBUG */
+ hp = hist_trim(hp,(int)hp->histind-maxlines);
+ }
+ sfdisc(hp->histfp,&hp->histdisc);
+#if KSHELL
+ (HISTCUR)->nvalue.lp = (&hp->histind);
+#endif /* KSHELL */
+ sh_timeradd(1000L*(HIST_RECENT-30), 1, hist_touch, (void*)hp->histname);
+#if SHOPT_ACCTFILE
+ if(sh_isstate(SH_INTERACTIVE))
+ acctinit(hp);
+#endif /* SHOPT_ACCTFILE */
+#if SHOPT_AUDIT
+ {
+ char buff[SF_BUFSIZE];
+ hp->auditfp = 0;
+ if(sh_isstate(SH_INTERACTIVE) && (hp->auditmask=sh_checkaudit(hp,SHOPT_AUDITFILE, buff, sizeof(buff))))
+ {
+ if((fd=sh_open(buff,O_BINARY|O_WRONLY|O_APPEND|O_CREAT,S_IRUSR|S_IWUSR))>=0 && fd < 10)
+ {
+ int n;
+ if((n = sh_fcntl(fd,F_DUPFD, 10)) >= 0)
+ {
+ sh_close(fd);
+ fd = n;
+ }
+ }
+ if(fd>=0)
+ {
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ hp->tty = strdup(ttyname(2));
+ hp->auditfp = sfnew((Sfio_t*)0,NULL,-1,fd,SF_WRITE);
+ }
+ }
+ }
+#endif
+ return(1);
+}
+
+/*
+ * close the history file and free the space
+ */
+
+void hist_close(register History_t *hp)
+{
+ sfclose(hp->histfp);
+#if SHOPT_AUDIT
+ if(hp->auditfp)
+ {
+ if(hp->tty)
+ free((void*)hp->tty);
+ sfclose(hp->auditfp);
+ }
+#endif /* SHOPT_AUDIT */
+ free((char*)hp);
+ hist_ptr = 0;
+ shgd->hist_ptr = 0;
+#if SHOPT_ACCTFILE
+ if(acctfd)
+ {
+ close(acctfd);
+ acctfd = 0;
+ }
+#endif /* SHOPT_ACCTFILE */
+}
+
+/*
+ * check history file format to see if it begins with special byte
+ */
+static int hist_check(register int fd)
+{
+ unsigned char magic[2];
+ lseek(fd,(off_t)0,SEEK_SET);
+ if((read(fd,(char*)magic,2)!=2) || (magic[0]!=HIST_UNDO))
+ return(1);
+ return(0);
+}
+
+/*
+ * clean out history file OK if not modified in HIST_RECENT seconds
+ */
+static int hist_clean(int fd)
+{
+ struct stat statb;
+ return(fstat(fd,&statb)>=0 && (time((time_t*)0)-statb.st_mtime) >= HIST_RECENT);
+}
+
+/*
+ * Copy the last <n> commands to a new file and make this the history file
+ */
+
+static History_t* hist_trim(History_t *hp, int n)
+{
+ register char *cp;
+ register int incmd=1, c=0;
+ register History_t *hist_new, *hist_old = hp;
+ char *buff, *endbuff, *tmpname=0;
+ off_t oldp,newp;
+ struct stat statb;
+ unlink(hist_old->histname);
+ if(access(hist_old->histname,F_OK) >= 0)
+ {
+ /* The unlink can fail on windows 95 */
+ int fd;
+ char *last, *name=hist_old->histname;
+ close(sffileno(hist_old->histfp));
+ tmpname = (char*)malloc(strlen(name)+14);
+ if(last = strrchr(name,'/'))
+ {
+ *last = 0;
+ pathtmp(tmpname,name,"hist",NIL(int*));
+ *last = '/';
+ }
+ else
+ pathtmp(tmpname,".","hist",NIL(int*));
+ if(rename(name,tmpname) < 0)
+ {
+ free(tmpname);
+ tmpname = name;
+ }
+ fd = open(tmpname,O_RDONLY);
+ sfsetfd(hist_old->histfp,fd);
+ if(tmpname==name)
+ tmpname = 0;
+ }
+ hist_ptr = 0;
+ if(fstat(sffileno(hist_old->histfp),&statb)>=0)
+ {
+ histinit = 1;
+ histmode = statb.st_mode;
+ }
+ if(!sh_histinit(hp->histshell))
+ {
+ /* use the old history file */
+ return hist_ptr = hist_old;
+ }
+ hist_new = hist_ptr;
+ hist_ptr = hist_old;
+ if(--n < 0)
+ n = 0;
+ newp = hist_seek(hist_old,++n);
+ while(1)
+ {
+ if(!incmd)
+ {
+ c = hist_ind(hist_new,++hist_new->histind);
+ hist_new->histcmds[c] = hist_new->histcnt;
+ if(hist_new->histcnt > hist_new->histmarker+HIST_BSIZE/2)
+ {
+ char locbuff[HIST_MARKSZ];
+ hist_marker(locbuff,hist_new->histind);
+ sfwrite(hist_new->histfp,locbuff,HIST_MARKSZ);
+ hist_new->histcnt += HIST_MARKSZ;
+ hist_new->histmarker = hist_new->histcmds[hist_ind(hist_new,c)] = hist_new->histcnt;
+ }
+ oldp = newp;
+ newp = hist_seek(hist_old,++n);
+ if(newp <=oldp)
+ break;
+ }
+ if(!(buff=(char*)sfreserve(hist_old->histfp,SF_UNBOUND,0)))
+ break;
+ *(endbuff=(cp=buff)+sfvalue(hist_old->histfp)) = 0;
+ /* copy to null byte */
+ incmd = 0;
+ while(*cp++);
+ if(cp > endbuff)
+ incmd = 1;
+ else if(*cp==0)
+ cp++;
+ if(cp > endbuff)
+ cp = endbuff;
+ c = cp-buff;
+ hist_new->histcnt += c;
+ sfwrite(hist_new->histfp,buff,c);
+ }
+ hist_cancel(hist_new);
+ sfclose(hist_old->histfp);
+ if(tmpname)
+ {
+ unlink(tmpname);
+ free(tmpname);
+ }
+ free((char*)hist_old);
+ return hist_ptr = hist_new;
+}
+
+/*
+ * position history file at size and find next command number
+ */
+static int hist_nearend(History_t *hp, Sfio_t *iop, register off_t size)
+{
+ register unsigned char *cp, *endbuff;
+ register int n, incmd=1;
+ unsigned char *buff, marker[4];
+ if(size <= 2L || sfseek(iop,size,SEEK_SET)<0)
+ goto begin;
+ /* skip to marker command and return the number */
+ /* numbering commands occur after a null and begin with HIST_CMDNO */
+ while(cp=buff=(unsigned char*)sfreserve(iop,SF_UNBOUND,SF_LOCKR))
+ {
+ n = sfvalue(iop);
+ *(endbuff=cp+n) = 0;
+ while(1)
+ {
+ /* check for marker */
+ if(!incmd && *cp++==HIST_CMDNO && *cp==0)
+ {
+ n = cp+1 - buff;
+ incmd = -1;
+ break;
+ }
+ incmd = 0;
+ while(*cp++);
+ if(cp>endbuff)
+ {
+ incmd = 1;
+ break;
+ }
+ if(*cp==0 && ++cp>endbuff)
+ break;
+ }
+ size += n;
+ sfread(iop,(char*)buff,n);
+ if(incmd < 0)
+ {
+ if((n=sfread(iop,(char*)marker,4))==4)
+ {
+ n = (marker[0]<<16)|(marker[1]<<8)|marker[2];
+ if(n < size/2)
+ {
+ hp->histmarker = hp->histcnt = size+4;
+ return(n);
+ }
+ n=4;
+ }
+ if(n >0)
+ size += n;
+ incmd = 0;
+ }
+ }
+begin:
+ sfseek(iop,(off_t)2,SEEK_SET);
+ hp->histmarker = hp->histcnt = 2L;
+ return(1);
+}
+
+/*
+ * This routine reads the history file from the present position
+ * to the end-of-file and puts the information in the in-core
+ * history table
+ * Note that HIST_CMDNO is only recognized at the beginning of a command
+ * and that HIST_UNDO as the first character of a command is skipped
+ * unless it is followed by 0. If followed by 0 then it cancels
+ * the previous command.
+ */
+
+void hist_eof(register History_t *hp)
+{
+ register char *cp,*first,*endbuff;
+ register int incmd = 0;
+ register off_t count = hp->histcnt;
+ int oldind,n,skip=0;
+ off_t last = sfseek(hp->histfp,(off_t)0,SEEK_END);
+ if(last < count)
+ {
+ last = -1;
+ count = 2+HIST_MARKSZ;
+ oldind = hp->histind;
+ if((hp->histind -= hp->histsize) < 0)
+ hp->histind = 1;
+ }
+again:
+ sfseek(hp->histfp,count,SEEK_SET);
+ while(cp=(char*)sfreserve(hp->histfp,SF_UNBOUND,0))
+ {
+ n = sfvalue(hp->histfp);
+ *(endbuff = cp+n) = 0;
+ first = cp += skip;
+ while(1)
+ {
+ while(!incmd)
+ {
+ if(cp>first)
+ {
+ count += (cp-first);
+ n = hist_ind(hp, ++hp->histind);
+#ifdef future
+ if(count==hp->histcmds[n])
+ {
+ sfprintf(sfstderr,"count match n=%d\n",n);
+ if(histinit)
+ {
+ histinit = 0;
+ return;
+ }
+ }
+ else if(n>=histinit)
+#endif
+ hp->histcmds[n] = count;
+ first = cp;
+ }
+ switch(*((unsigned char*)(cp++)))
+ {
+ case HIST_CMDNO:
+ if(*cp==0)
+ {
+ hp->histmarker=count+2;
+ cp += (HIST_MARKSZ-1);
+ hp->histind--;
+ if(!histinit && (cp <= endbuff))
+ {
+ unsigned char *marker = (unsigned char*)(cp-4);
+ hp->histind = ((marker[0]<<16)|(marker[1]<<8)|marker[2] -1);
+ }
+ }
+ break;
+ case HIST_UNDO:
+ if(*cp==0)
+ {
+ cp+=1;
+ hp->histind-=2;
+ }
+ break;
+ default:
+ cp--;
+ incmd = 1;
+ }
+ if(cp > endbuff)
+ {
+ cp++;
+ goto refill;
+ }
+ }
+ first = cp;
+ while(*cp++);
+ if(cp > endbuff)
+ break;
+ incmd = 0;
+ while(*cp==0)
+ {
+ if(++cp > endbuff)
+ goto refill;
+ }
+ }
+ refill:
+ count += (--cp-first);
+ skip = (cp-endbuff);
+ if(!incmd && !skip)
+ hp->histcmds[hist_ind(hp,++hp->histind)] = count;
+ }
+ hp->histcnt = count;
+ if(incmd && last)
+ {
+ sfputc(hp->histfp,0);
+ hist_cancel(hp);
+ count = 2;
+ skip = 0;
+ oldind -= hp->histind;
+ hp->histind = hp->histind-hp->histsize + oldind +2;
+ if(hp->histind<0)
+ hp->histind = 1;
+ if(last<0)
+ {
+ char buff[HIST_MARKSZ];
+ int fd = open(hp->histname,O_RDWR);
+ if(fd>=0)
+ {
+ hist_marker(buff,hp->histind);
+ write(fd,(char*)hist_stamp,2);
+ write(fd,buff,HIST_MARKSZ);
+ close(fd);
+ }
+ }
+ last = 0;
+ goto again;
+ }
+}
+
+/*
+ * This routine will cause the previous command to be cancelled
+ */
+
+void hist_cancel(register History_t *hp)
+{
+ register int c;
+ if(!hp)
+ return;
+ sfputc(hp->histfp,HIST_UNDO);
+ sfputc(hp->histfp,0);
+ sfsync(hp->histfp);
+ hp->histcnt += 2;
+ c = hist_ind(hp,--hp->histind);
+ hp->histcmds[c] = hp->histcnt;
+}
+
+/*
+ * flush the current history command
+ */
+
+void hist_flush(register History_t *hp)
+{
+ register char *buff;
+ if(hp)
+ {
+ if(buff=(char*)sfreserve(hp->histfp,0,SF_LOCKR))
+ {
+ hp->histflush = sfvalue(hp->histfp)+1;
+ sfwrite(hp->histfp,buff,0);
+ }
+ else
+ hp->histflush=0;
+ if(sfsync(hp->histfp)<0)
+ {
+ hist_close(hp);
+ if(!sh_histinit(hp->histshell))
+ sh_offoption(SH_HISTORY);
+ }
+ hp->histflush = 0;
+ }
+}
+
+/*
+ * This is the write discipline for the history file
+ * When called from hist_flush(), trailing newlines are deleted and
+ * a zero byte. Line sequencing is added as required
+ */
+
+#ifdef SF_BUFCONST
+static ssize_t hist_write(Sfio_t *iop,const void *buff,register size_t insize,Sfdisc_t* handle)
+#else
+static int hist_write(Sfio_t *iop,const void *buff,register int insize,Sfdisc_t* handle)
+#endif
+{
+ register History_t *hp = (History_t*)handle;
+ register char *bufptr = ((char*)buff)+insize;
+ register int c,size = insize;
+ register off_t cur;
+ int saved=0;
+ char saveptr[HIST_MARKSZ];
+ if(!hp->histflush)
+ return(write(sffileno(iop),(char*)buff,size));
+ if((cur = lseek(sffileno(iop),(off_t)0,SEEK_END)) <0)
+ {
+ errormsg(SH_DICT,2,"hist_flush: EOF seek failed errno=%d",errno);
+ return(-1);
+ }
+ hp->histcnt = cur;
+ /* remove whitespace from end of commands */
+ while(--bufptr >= (char*)buff)
+ {
+ c= *bufptr;
+ if(!isspace(c))
+ {
+ if(c=='\\' && *(bufptr+1)!='\n')
+ bufptr++;
+ break;
+ }
+ }
+ /* don't count empty lines */
+ if(++bufptr <= (char*)buff)
+ return(insize);
+ *bufptr++ = '\n';
+ *bufptr++ = 0;
+ size = bufptr - (char*)buff;
+#if SHOPT_AUDIT
+ if(hp->auditfp)
+ {
+ time_t t=time((time_t*)0);
+ sfprintf(hp->auditfp,"%u;%u;%s;%*s%c",sh_isoption(SH_PRIVILEGED)?shgd->euserid:shgd->userid,t,hp->tty,size,buff,0);
+ sfsync(hp->auditfp);
+ }
+#endif /* SHOPT_AUDIT */
+#if SHOPT_ACCTFILE
+ if(acctfd)
+ {
+ int timechars, offset;
+ offset = staktell();
+ stakputs(buff);
+ stakseek(staktell() - 1);
+ timechars = sfprintf(staksp, "\t%s\t%x\n",logname,time(NIL(long *)));
+ lseek(acctfd, (off_t)0, SEEK_END);
+ write(acctfd, stakptr(offset), size - 2 + timechars);
+ stakseek(offset);
+
+ }
+#endif /* SHOPT_ACCTFILE */
+ if(size&01)
+ {
+ size++;
+ *bufptr++ = 0;
+ }
+ hp->histcnt += size;
+ c = hist_ind(hp,++hp->histind);
+ hp->histcmds[c] = hp->histcnt;
+ if(hp->histflush>HIST_MARKSZ && hp->histcnt > hp->histmarker+HIST_BSIZE/2)
+ {
+ memcpy((void*)saveptr,(void*)bufptr,HIST_MARKSZ);
+ saved=1;
+ hp->histcnt += HIST_MARKSZ;
+ hist_marker(bufptr,hp->histind);
+ hp->histmarker = hp->histcmds[hist_ind(hp,c)] = hp->histcnt;
+ size += HIST_MARKSZ;
+ }
+ errno = 0;
+ size = write(sffileno(iop),(char*)buff,size);
+ if(saved)
+ memcpy((void*)bufptr,(void*)saveptr,HIST_MARKSZ);
+ if(size>=0)
+ {
+ hp->histwfail = 0;
+ return(insize);
+ }
+ return(-1);
+}
+
+/*
+ * Put history sequence number <n> into buffer <buff>
+ * The buffer must be large enough to hold HIST_MARKSZ chars
+ */
+
+static void hist_marker(register char *buff,register long cmdno)
+{
+ *buff++ = HIST_CMDNO;
+ *buff++ = 0;
+ *buff++ = (cmdno>>16);
+ *buff++ = (cmdno>>8);
+ *buff++ = cmdno;
+ *buff++ = 0;
+}
+
+/*
+ * return byte offset in history file for command <n>
+ */
+off_t hist_tell(register History_t *hp, int n)
+{
+ return(hp->histcmds[hist_ind(hp,n)]);
+}
+
+/*
+ * seek to the position of command <n>
+ */
+off_t hist_seek(register History_t *hp, int n)
+{
+ return(sfseek(hp->histfp,hp->histcmds[hist_ind(hp,n)],SEEK_SET));
+}
+
+/*
+ * write the command starting at offset <offset> onto file <outfile>.
+ * if character <last> appears before newline it is deleted
+ * each new-line character is replaced with string <nl>.
+ */
+
+void hist_list(register History_t *hp,Sfio_t *outfile, off_t offset,int last, char *nl)
+{
+ register int oldc=0;
+ register int c;
+ if(offset<0 || !hp)
+ {
+ sfputr(outfile,sh_translate(e_unknown),'\n');
+ return;
+ }
+ sfseek(hp->histfp,offset,SEEK_SET);
+ while((c = sfgetc(hp->histfp)) != EOF)
+ {
+ if(c && oldc=='\n')
+ sfputr(outfile,nl,-1);
+ else if(last && (c==0 || (c=='\n' && oldc==last)))
+ return;
+ else if(oldc)
+ sfputc(outfile,oldc);
+ oldc = c;
+ if(c==0)
+ return;
+ }
+ return;
+}
+
+/*
+ * find index for last line with given string
+ * If flag==0 then line must begin with string
+ * direction < 1 for backwards search
+*/
+
+Histloc_t hist_find(register History_t*hp,char *string,register int index1,int flag,int direction)
+{
+ register int index2;
+ off_t offset;
+ int *coffset=0;
+ Histloc_t location;
+ location.hist_command = -1;
+ location.hist_char = 0;
+ location.hist_line = 0;
+ if(!hp)
+ return(location);
+ /* leading ^ means beginning of line unless escaped */
+ if(flag)
+ {
+ index2 = *string;
+ if(index2=='\\')
+ string++;
+ else if(index2=='^')
+ {
+ flag=0;
+ string++;
+ }
+ }
+ if(flag)
+ coffset = &location.hist_char;
+ index2 = (int)hp->histind;
+ if(direction<0)
+ {
+ index2 -= hp->histsize;
+ if(index2<1)
+ index2 = 1;
+ if(index1 <= index2)
+ return(location);
+ }
+ else if(index1 >= index2)
+ return(location);
+ while(index1!=index2)
+ {
+ direction>0?++index1:--index1;
+ offset = hist_tell(hp,index1);
+ if((location.hist_line=hist_match(hp,offset,string,coffset))>=0)
+ {
+ location.hist_command = index1;
+ return(location);
+ }
+#if KSHELL
+ /* allow a search to be aborted */
+ if(((Shell_t*)hp->histshell)->trapnote&SH_SIGSET)
+ break;
+#endif /* KSHELL */
+ }
+ return(location);
+}
+
+/*
+ * search for <string> in history file starting at location <offset>
+ * If coffset==0 then line must begin with string
+ * returns the line number of the match if successful, otherwise -1
+ */
+
+int hist_match(register History_t *hp,off_t offset,char *string,int *coffset)
+{
+ register unsigned char *first, *cp;
+ register int m,n,c=1,line=0;
+#if SHOPT_MULTIBYTE
+ mbinit();
+#endif /* SHOPT_MULTIBYTE */
+ sfseek(hp->histfp,offset,SEEK_SET);
+ if(!(cp = first = (unsigned char*)sfgetr(hp->histfp,0,0)))
+ return(-1);
+ m = sfvalue(hp->histfp);
+ n = strlen(string);
+ while(m > n)
+ {
+ if(*cp==*string && memcmp(cp,string,n)==0)
+ {
+ if(coffset)
+ *coffset = (cp-first);
+ return(line);
+ }
+ if(!coffset)
+ break;
+ if(*cp=='\n')
+ line++;
+#if SHOPT_MULTIBYTE
+ if((c=mbsize(cp)) < 0)
+ c = 1;
+#endif /* SHOPT_MULTIBYTE */
+ cp += c;
+ m -= c;
+ }
+ return(-1);
+}
+
+
+#if SHOPT_ESH || SHOPT_VSH
+/*
+ * copy command <command> from history file to s1
+ * at most <size> characters copied
+ * if s1==0 the number of lines for the command is returned
+ * line=linenumber for emacs copy and only this line of command will be copied
+ * line < 0 for full command copy
+ * -1 returned if there is no history file
+ */
+
+int hist_copy(char *s1,int size,int command,int line)
+{
+ register int c;
+ register History_t *hp = shgd->hist_ptr;
+ register int count = 0;
+ register char *s1max = s1+size;
+ if(!hp)
+ return(-1);
+ hist_seek(hp,command);
+ while ((c = sfgetc(hp->histfp)) && c!=EOF)
+ {
+ if(c=='\n')
+ {
+ if(count++ ==line)
+ break;
+ else if(line >= 0)
+ continue;
+ }
+ if(s1 && (line<0 || line==count))
+ {
+ if(s1 >= s1max)
+ {
+ *--s1 = 0;
+ break;
+ }
+ *s1++ = c;
+ }
+
+ }
+ sfseek(hp->histfp,(off_t)0,SEEK_END);
+ if(s1==0)
+ return(count);
+ if(count && (c= *(s1-1)) == '\n')
+ s1--;
+ *s1 = '\0';
+ return(count);
+}
+
+/*
+ * return word number <word> from command number <command>
+ */
+
+char *hist_word(char *string,int size,int word)
+{
+ register int c;
+ register char *s1 = string;
+ register unsigned char *cp = (unsigned char*)s1;
+ register int flag = 0;
+ History_t *hp = hist_ptr;
+ if(!hp)
+ return(NIL(char*));
+ hist_copy(string,size,(int)hp->histind-1,-1);
+ for(;c = *cp;cp++)
+ {
+ c = isspace(c);
+ if(c && flag)
+ {
+ *cp = 0;
+ if(--word==0)
+ break;
+ flag = 0;
+ }
+ else if(c==0 && flag==0)
+ {
+ s1 = (char*)cp;
+ flag++;
+ }
+ }
+ *cp = 0;
+ if(s1 != string)
+ strcpy(string,s1);
+ return(string);
+}
+
+#endif /* SHOPT_ESH */
+
+#if SHOPT_ESH
+/*
+ * given the current command and line number,
+ * and number of lines back or foward,
+ * compute the new command and line number.
+ */
+
+Histloc_t hist_locate(History_t *hp,register int command,register int line,int lines)
+{
+ Histloc_t next;
+ line += lines;
+ if(!hp)
+ {
+ command = -1;
+ goto done;
+ }
+ if(lines > 0)
+ {
+ register int count;
+ while(command <= hp->histind)
+ {
+ count = hist_copy(NIL(char*),0, command,-1);
+ if(count > line)
+ goto done;
+ line -= count;
+ command++;
+ }
+ }
+ else
+ {
+ register int least = (int)hp->histind-hp->histsize;
+ while(1)
+ {
+ if(line >=0)
+ goto done;
+ if(--command < least)
+ break;
+ line += hist_copy(NIL(char*),0, command,-1);
+ }
+ command = -1;
+ }
+done:
+ next.hist_line = line;
+ next.hist_command = command;
+ return(next);
+}
+#endif /* SHOPT_ESH */
+
+
+/*
+ * Handle history file exceptions
+ */
+#ifdef SF_BUFCONST
+static int hist_exceptf(Sfio_t* fp, int type, void *data, Sfdisc_t *handle)
+#else
+static int hist_exceptf(Sfio_t* fp, int type, Sfdisc_t *handle)
+#endif
+{
+ register int newfd,oldfd;
+ History_t *hp = (History_t*)handle;
+ if(type==SF_WRITE)
+ {
+ if(errno==ENOSPC || hp->histwfail++ >= 10)
+ return(0);
+ /* write failure could be NFS problem, try to re-open */
+ close(oldfd=sffileno(fp));
+ if((newfd=open(hp->histname,O_BINARY|O_APPEND|O_CREAT|O_RDWR,S_IRUSR|S_IWUSR)) >= 0)
+ {
+ if(fcntl(newfd, F_DUPFD, oldfd) !=oldfd)
+ return(-1);
+ fcntl(oldfd,F_SETFD,FD_CLOEXEC);
+ close(newfd);
+ if(lseek(oldfd,(off_t)0,SEEK_END) < hp->histcnt)
+ {
+ register int index = hp->histind;
+ lseek(oldfd,(off_t)2,SEEK_SET);
+ hp->histcnt = 2;
+ hp->histind = 1;
+ hp->histcmds[1] = 2;
+ hist_eof(hp);
+ hp->histmarker = hp->histcnt;
+ hp->histind = index;
+ }
+ return(1);
+ }
+ errormsg(SH_DICT,2,"History file write error-%d %s: file unrecoverable",errno,hp->histname);
+ return(-1);
+ }
+ return(0);
+}
diff --git a/src/cmd/ksh93/edit/vi.c b/src/cmd/ksh93/edit/vi.c
new file mode 100644
index 0000000..376e349
--- /dev/null
+++ b/src/cmd/ksh93/edit/vi.c
@@ -0,0 +1,2753 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/* Adapted for ksh by David Korn */
+/*+ VI.C P.D. Sullivan
+ *
+ * One line editor for the shell based on the vi editor.
+ *
+ * Questions to:
+ * P.D. Sullivan
+ * cbosgd!pds
+-*/
+
+
+#if KSHELL
+# include "defs.h"
+#else
+# include <ast.h>
+# include "FEATURE/options"
+# include <ctype.h>
+#endif /* KSHELL */
+#include "io.h"
+
+#include "history.h"
+#include "edit.h"
+#include "terminal.h"
+#include "FEATURE/time"
+
+#if SHOPT_OLDTERMIO
+# undef ECHOCTL
+# define echoctl (vp->ed->e_echoctl)
+#else
+# ifdef ECHOCTL
+# define echoctl ECHOCTL
+# else
+# define echoctl 0
+# endif /* ECHOCTL */
+#endif /*SHOPT_OLDTERMIO */
+
+#ifndef FIORDCHK
+# define NTICKS 5 /* number of ticks for typeahead */
+#endif /* FIORDCHK */
+
+#define MAXCHAR MAXLINE-2 /* max char per line */
+
+#if SHOPT_MULTIBYTE
+# include "lexstates.h"
+# define gencpy(a,b) ed_gencpy(a,b)
+# define genncpy(a,b,n) ed_genncpy(a,b,n)
+# define genlen(str) ed_genlen(str)
+# define digit(c) ((c&~STRIP)==0 && isdigit(c))
+# define is_print(c) ((c&~STRIP) || isprint(c))
+# if !_lib_iswprint && !defined(iswprint)
+# define iswprint(c) ((c&~0177) || isprint(c))
+# endif
+ static int _isalph(int);
+ static int _ismetach(int);
+ static int _isblank(int);
+# undef isblank
+# define isblank(v) _isblank(virtual[v])
+# define isalph(v) _isalph(virtual[v])
+# define ismetach(v) _ismetach(virtual[v])
+#else
+ static genchar _c;
+# define gencpy(a,b) strcpy((char*)(a),(char*)(b))
+# define genncpy(a,b,n) strncpy((char*)(a),(char*)(b),n)
+# define genlen(str) strlen(str)
+# define isalph(v) ((_c=virtual[v])=='_'||isalnum(_c))
+# undef isblank
+# define isblank(v) isspace(virtual[v])
+# define ismetach(v) ismeta(virtual[v])
+# define digit(c) isdigit(c)
+# define is_print(c) isprint(c)
+#endif /* SHOPT_MULTIBYTE */
+
+#if ( 'a' == 97) /* ASCII? */
+# define fold(c) ((c)&~040) /* lower and uppercase equivalent */
+#else
+# define fold(c) ((c)|0100) /* lower and uppercase equivalent */
+#endif
+
+#ifndef iswascii
+#define iswascii(c) (!((c)&(~0177)))
+#endif
+
+typedef struct _vi_
+{
+ int direction;
+ int lastmacro;
+ char addnl; /* boolean - add newline flag */
+ char last_find; /* last find command */
+ char last_cmd; /* last command */
+ char repeat_set;
+ char nonewline;
+ int findchar; /* last find char */
+ genchar *lastline;
+ int first_wind; /* first column of window */
+ int last_wind; /* last column in window */
+ int lastmotion; /* last motion */
+ int long_char; /* line bigger than window */
+ int long_line; /* line bigger than window */
+ int ocur_phys; /* old current physical position */
+ int ocur_virt; /* old last virtual position */
+ int ofirst_wind; /* old window first col */
+ int o_v_char; /* prev virtual[ocur_virt] */
+ int repeat; /* repeat count for motion cmds */
+ int lastrepeat; /* last repeat count for motion cmds */
+ int u_column; /* undo current column */
+ int U_saved; /* original virtual saved */
+ genchar *U_space; /* used for U command */
+ genchar *u_space; /* used for u command */
+#ifdef FIORDCHK
+ clock_t typeahead; /* typeahead occurred */
+#else
+ int typeahead; /* typeahead occurred */
+#endif /* FIORDCHK */
+#if SHOPT_MULTIBYTE
+ int bigvi;
+#endif
+ Edit_t *ed; /* pointer to edit data */
+} Vi_t;
+
+#define editb (*vp->ed)
+
+#undef putchar
+#define putchar(c) ed_putchar(vp->ed,c)
+
+#define crallowed editb.e_crlf
+#define cur_virt editb.e_cur /* current virtual column */
+#define cur_phys editb.e_pcur /* current phys column cursor is at */
+#define curhline editb.e_hline /* current history line */
+#define first_virt editb.e_fcol /* first allowable column */
+#define globals editb.e_globals /* local global variables */
+#define histmin editb.e_hismin
+#define histmax editb.e_hismax
+#define last_phys editb.e_peol /* last column in physical */
+#define last_virt editb.e_eol /* last column */
+#define lsearch editb.e_search /* last search string */
+#define lookahead editb.e_lookahead /* characters in buffer */
+#define previous editb.e_lbuf /* lookahead buffer */
+#define max_col editb.e_llimit /* maximum column */
+#define Prompt editb.e_prompt /* pointer to prompt */
+#define plen editb.e_plen /* length of prompt */
+#define physical editb.e_physbuf /* physical image */
+#define usreof editb.e_eof /* user defined eof char */
+#define usrerase editb.e_erase /* user defined erase char */
+#define usrlnext editb.e_lnext /* user defined next literal */
+#define usrkill editb.e_kill /* user defined kill char */
+#define virtual editb.e_inbuf /* pointer to virtual image buffer */
+#define window editb.e_window /* window buffer */
+#define w_size editb.e_wsize /* window size */
+#define inmacro editb.e_inmacro /* true when in macro */
+#define yankbuf editb.e_killbuf /* yank/delete buffer */
+
+
+#define ABORT -2 /* user abort */
+#define APPEND -10 /* append chars */
+#define BAD -1 /* failure flag */
+#define BIGVI -15 /* user wants real vi */
+#define CONTROL -20 /* control mode */
+#define ENTER -25 /* enter flag */
+#define GOOD 0 /* success flag */
+#define INPUT -30 /* input mode */
+#define INSERT -35 /* insert mode */
+#define REPLACE -40 /* replace chars */
+#define SEARCH -45 /* search flag */
+#define TRANSLATE -50 /* translate virt to phys only */
+
+#define INVALID (-1) /* invalid column */
+
+static const char paren_chars[] = "([{)]}"; /* for % command */
+
+static void cursor(Vi_t*, int);
+static void del_line(Vi_t*,int);
+static int getcount(Vi_t*,int);
+static void getline(Vi_t*,int);
+static int getrchar(Vi_t*);
+static int mvcursor(Vi_t*,int);
+static void pr_string(Vi_t*,const char*);
+static void putstring(Vi_t*,int, int);
+static void refresh(Vi_t*,int);
+static void replace(Vi_t*,int, int);
+static void restore_v(Vi_t*);
+static void save_last(Vi_t*);
+static void save_v(Vi_t*);
+static int search(Vi_t*,int);
+static void sync_cursor(Vi_t*);
+static int textmod(Vi_t*,int,int);
+
+/*+ VI_READ( fd, shbuf, nchar )
+ *
+ * This routine implements a one line version of vi and is
+ * called by _filbuf.c
+ *
+-*/
+
+/*
+ * if reedit is non-zero, initialize edit buffer with reedit chars
+ */
+int ed_viread(void *context, int fd, register char *shbuf, int nchar, int reedit)
+{
+ Edit_t *ed = (Edit_t*)context;
+ register int i; /* general variable */
+ register int term_char=0; /* read() termination character */
+ register Vi_t *vp = ed->e_vi;
+ char prompt[PRSIZE+2]; /* prompt */
+ genchar Physical[2*MAXLINE]; /* physical image */
+ genchar Ubuf[MAXLINE]; /* used for U command */
+ genchar ubuf[MAXLINE]; /* used for u command */
+ genchar Window[MAXLINE]; /* window image */
+ int Globals[9]; /* local global variables */
+ int esc_or_hang=0; /* <ESC> or hangup */
+ char cntl_char=0; /* TRUE if control character present */
+#if SHOPT_RAWONLY
+# define viraw 1
+#else
+ int viraw = (sh_isoption(SH_VIRAW) || ed->sh->st.trap[SH_KEYTRAP]);
+# ifndef FIORDCHK
+ clock_t oldtime, newtime;
+ struct tms dummy;
+# endif /* FIORDCHK */
+#endif /* SHOPT_RAWONLY */
+ if(!vp)
+ {
+ ed->e_vi = vp = newof(0,Vi_t,1,0);
+ vp->lastline = (genchar*)malloc(MAXLINE*CHARSIZE);
+ vp->direction = -1;
+ vp->ed = ed;
+ }
+
+ /*** setup prompt ***/
+
+ Prompt = prompt;
+ ed_setup(vp->ed,fd, reedit);
+ shbuf[reedit] = 0;
+
+#if !SHOPT_RAWONLY
+ if(!viraw)
+ {
+ /*** Change the eol characters to '\r' and eof ***/
+ /* in addition to '\n' and make eof an ESC */
+ if(tty_alt(ERRIO) < 0)
+ return(reexit?reedit:ed_read(context, fd, shbuf, nchar,0));
+
+#ifdef FIORDCHK
+ ioctl(fd,FIORDCHK,&vp->typeahead);
+#else
+ /* time the current line to determine typeahead */
+ oldtime = times(&dummy);
+#endif /* FIORDCHK */
+#if KSHELL
+ /* abort of interrupt has occurred */
+ if(ed->sh->trapnote&SH_SIGSET)
+ i = -1;
+ else
+#endif /* KSHELL */
+ /*** Read the line ***/
+ i = ed_read(context, fd, shbuf, nchar, 0);
+#ifndef FIORDCHK
+ newtime = times(&dummy);
+ vp->typeahead = ((newtime-oldtime) < NTICKS);
+#endif /* FIORDCHK */
+ if(echoctl)
+ {
+ if( i <= 0 )
+ {
+ /*** read error or eof typed ***/
+ tty_cooked(ERRIO);
+ return(i);
+ }
+ term_char = shbuf[--i];
+ if( term_char == '\r' )
+ term_char = '\n';
+ if( term_char=='\n' || term_char==ESC )
+ shbuf[i--] = '\0';
+ else
+ shbuf[i+1] = '\0';
+ }
+ else
+ {
+ register int c = shbuf[0];
+
+ /*** Save and remove the last character if its an eol, ***/
+ /* changing '\r' to '\n' */
+
+ if( i == 0 )
+ {
+ /*** ESC was typed as first char of line ***/
+ esc_or_hang = 1;
+ term_char = ESC;
+ shbuf[i--] = '\0'; /* null terminate line */
+ }
+ else if( i<0 || c==usreof )
+ {
+ /*** read error or eof typed ***/
+ tty_cooked(ERRIO);
+ if( c == usreof )
+ i = 0;
+ return(i);
+ }
+ else
+ {
+ term_char = shbuf[--i];
+ if( term_char == '\r' )
+ term_char = '\n';
+#if !defined(VEOL2) && !defined(ECHOCTL)
+ if(term_char=='\n')
+ {
+ tty_cooked(ERRIO);
+ return(i+1);
+ }
+#endif
+ if( term_char=='\n' || term_char==usreof )
+ {
+ /*** remove terminator & null terminate ***/
+ shbuf[i--] = '\0';
+ }
+ else
+ {
+ /** terminator was ESC, which is not xmitted **/
+ term_char = ESC;
+ shbuf[i+1] = '\0';
+ }
+ }
+ }
+ }
+ else
+#endif /* SHOPT_RAWONLY */
+ {
+ /*** Set raw mode ***/
+
+#if !SHOPT_RAWONLY
+ if( editb.e_ttyspeed == 0 )
+ {
+ /*** never did TCGETA, so do it ***/
+ /* avoids problem if user does 'sh -o viraw' */
+ tty_alt(ERRIO);
+ }
+#endif /* SHOPT_RAWONLY */
+ if(tty_raw(ERRIO,0) < 0 )
+ return(reedit?reedit:ed_read(context, fd, shbuf, nchar,0));
+ i = last_virt-1;
+ }
+
+ /*** Initialize some things ***/
+
+ virtual = (genchar*)shbuf;
+#if SHOPT_MULTIBYTE
+ virtual = (genchar*)roundof((char*)virtual-(char*)0,sizeof(genchar));
+ shbuf[i+1] = 0;
+ i = ed_internal(shbuf,virtual)-1;
+#endif /* SHOPT_MULTIBYTE */
+ globals = Globals;
+ cur_phys = i + 1;
+ cur_virt = i;
+ first_virt = 0;
+ vp->first_wind = 0;
+ last_virt = i;
+ last_phys = i;
+ vp->last_wind = i;
+ vp->long_line = ' ';
+ vp->long_char = ' ';
+ vp->o_v_char = '\0';
+ vp->ocur_phys = 0;
+ vp->ocur_virt = MAXCHAR;
+ vp->ofirst_wind = 0;
+ physical = Physical;
+ vp->u_column = INVALID - 1;
+ vp->U_space = Ubuf;
+ vp->u_space = ubuf;
+ window = Window;
+ window[0] = '\0';
+
+ if(!yankbuf)
+ yankbuf = (genchar*)malloc(MAXLINE*CHARSIZE);
+ if( vp->last_cmd == '\0' )
+ {
+ /*** first time for this shell ***/
+
+ vp->last_cmd = 'i';
+ vp->findchar = INVALID;
+ vp->lastmotion = '\0';
+ vp->lastrepeat = 1;
+ vp->repeat = 1;
+ *yankbuf = 0;
+ }
+
+ /*** fiddle around with prompt length ***/
+ if( nchar+plen > MAXCHAR )
+ nchar = MAXCHAR - plen;
+ max_col = nchar - 2;
+
+ if( !viraw )
+ {
+ int kill_erase = 0;
+ for(i=(echoctl?last_virt:0); i<last_virt; ++i )
+ {
+ /*** change \r to \n, check for control characters, ***/
+ /* delete appropriate ^Vs, */
+ /* and estimate last physical column */
+
+ if( virtual[i] == '\r' )
+ virtual[i] = '\n';
+ if(!echoctl)
+ {
+ register int c = virtual[i];
+ if( c<=usrerase)
+ {
+ /*** user typed escaped erase or kill char ***/
+ cntl_char = 1;
+ if(is_print(c))
+ kill_erase++;
+ }
+ else if( !is_print(c) )
+ {
+ cntl_char = 1;
+
+ if( c == usrlnext )
+ {
+ if( i == last_virt )
+ {
+ /*** eol/eof was escaped ***/
+ /* so replace ^V with it */
+ virtual[i] = term_char;
+ break;
+ }
+
+ /*** delete ^V ***/
+ gencpy((&virtual[i]), (&virtual[i+1]));
+ --cur_virt;
+ --last_virt;
+ }
+ }
+ }
+ }
+
+ /*** copy virtual image to window ***/
+ if(last_virt > 0)
+ last_phys = ed_virt_to_phys(vp->ed,virtual,physical,last_virt,0,0);
+ if( last_phys >= w_size )
+ {
+ /*** line longer than window ***/
+ vp->last_wind = w_size - 1;
+ }
+ else
+ vp->last_wind = last_phys;
+ genncpy(window, virtual, vp->last_wind+1);
+
+ if( term_char!=ESC && (last_virt==INVALID
+ || virtual[last_virt]!=term_char) )
+ {
+ /*** Line not terminated with ESC or escaped (^V) ***/
+ /* eol, so return after doing a total update */
+ /* if( (speed is greater or equal to 1200 */
+ /* and something was typed) and */
+ /* (control character present */
+ /* or typeahead occurred) ) */
+
+ tty_cooked(ERRIO);
+ if( editb.e_ttyspeed==FAST && last_virt!=INVALID
+ && (vp->typeahead || cntl_char) )
+ {
+ refresh(vp,TRANSLATE);
+ pr_string(vp,Prompt);
+ putstring(vp,0, last_phys+1);
+ if(echoctl)
+ ed_crlf(vp->ed);
+ else
+ while(kill_erase-- > 0)
+ putchar(' ');
+ }
+
+ if( term_char=='\n' )
+ {
+ if(!echoctl)
+ ed_crlf(vp->ed);
+ virtual[++last_virt] = '\n';
+ }
+ vp->last_cmd = 'i';
+ save_last(vp);
+#if SHOPT_MULTIBYTE
+ virtual[last_virt+1] = 0;
+ last_virt = ed_external(virtual,shbuf);
+ return(last_virt);
+#else
+ return(++last_virt);
+#endif /* SHOPT_MULTIBYTE */
+ }
+
+ /*** Line terminated with escape, or escaped eol/eof, ***/
+ /* so set raw mode */
+
+ if( tty_raw(ERRIO,0) < 0 )
+ {
+ tty_cooked(ERRIO);
+ /*
+ * The following prevents drivers that return 0 on
+ * causing an infinite loop
+ */
+ if(esc_or_hang)
+ return(-1);
+ virtual[++last_virt] = '\n';
+#if SHOPT_MULTIBYTE
+ virtual[last_virt+1] = 0;
+ last_virt = ed_external(virtual,shbuf);
+ return(last_virt);
+#else
+ return(++last_virt);
+#endif /* SHOPT_MULTIBYTE */
+ }
+
+ if(echoctl) /*** for cntl-echo erase the ^[ ***/
+ pr_string(vp,"\b\b\b\b \b\b");
+
+
+ if(crallowed)
+ {
+ /*** start over since there may be ***/
+ /*** a control char, or cursor might not ***/
+ /*** be at left margin (this lets us know ***/
+ /*** where we are ***/
+ cur_phys = 0;
+ window[0] = '\0';
+ pr_string(vp,Prompt);
+ if( term_char==ESC && (last_virt<0 || virtual[last_virt]!=ESC))
+ refresh(vp,CONTROL);
+ else
+ refresh(vp,INPUT);
+ }
+ else
+ {
+ /*** just update everything internally ***/
+ refresh(vp,TRANSLATE);
+ }
+ }
+
+ /*** Handle usrintr, usrquit, or EOF ***/
+
+ i = sigsetjmp(editb.e_env,0);
+ if( i != 0 )
+ {
+ if(vp->ed->e_multiline)
+ {
+ cur_virt = last_virt;
+ sync_cursor(vp);
+ }
+ virtual[0] = '\0';
+ tty_cooked(ERRIO);
+
+ switch(i)
+ {
+ case UEOF:
+ /*** EOF ***/
+ return(0);
+
+ case UINTR:
+ /** interrupt **/
+ return(-1);
+ }
+ return(-1);
+ }
+
+ /*** Get a line from the terminal ***/
+
+ vp->U_saved = 0;
+ if(reedit)
+ {
+ cur_phys = vp->first_wind;
+ vp->ofirst_wind = INVALID;
+ refresh(vp,INPUT);
+ }
+ if(viraw)
+ getline(vp,APPEND);
+ else if(last_virt>=0 && virtual[last_virt]==term_char)
+ getline(vp,APPEND);
+ else
+ getline(vp,ESC);
+ if(vp->ed->e_multiline)
+ cursor(vp, last_phys);
+ /*** add a new line if user typed unescaped \n ***/
+ /* to cause the shell to process the line */
+ tty_cooked(ERRIO);
+ if(ed->e_nlist)
+ {
+ ed->e_nlist = 0;
+ stakset(ed->e_stkptr,ed->e_stkoff);
+ }
+ if( vp->addnl )
+ {
+ virtual[++last_virt] = '\n';
+ ed_crlf(vp->ed);
+ }
+ if( ++last_virt >= 0 )
+ {
+#if SHOPT_MULTIBYTE
+ if(vp->bigvi)
+ {
+ vp->bigvi = 0;
+ shbuf[last_virt-1] = '\n';
+ }
+ else
+ {
+ virtual[last_virt] = 0;
+ last_virt = ed_external(virtual,shbuf);
+ }
+#endif /* SHOPT_MULTIBYTE */
+#if SHOPT_EDPREDICT
+ if(vp->ed->nhlist)
+ ed_histlist(vp->ed,0);
+#endif /* SHOPT_EDPREDICT */
+ return(last_virt);
+ }
+ else
+ return(-1);
+}
+
+
+/*{ APPEND( char, mode )
+ *
+ * This routine will append char after cur_virt in the virtual image.
+ * mode = APPEND, shift chars right before appending
+ * REPLACE, replace char if possible
+ *
+}*/
+
+static void append(Vi_t *vp,int c, int mode)
+{
+ register int i,j;
+
+ if( last_virt<max_col && last_phys<max_col )
+ {
+ if( mode==APPEND || (cur_virt==last_virt && last_virt>=0))
+ {
+ j = (cur_virt>=0?cur_virt:0);
+ for(i = ++last_virt; i > j; --i)
+ virtual[i] = virtual[i-1];
+ }
+ virtual[++cur_virt] = c;
+ }
+ else
+ ed_ringbell();
+ return;
+}
+
+/*{ BACKWORD( nwords, cmd )
+ *
+ * This routine will position cur_virt at the nth previous word.
+ *
+}*/
+
+static void backword(Vi_t *vp,int nwords, register int cmd)
+{
+ register int tcur_virt = cur_virt;
+ while( nwords-- && tcur_virt > first_virt )
+ {
+ if( !isblank(tcur_virt) && isblank(tcur_virt-1)
+ && tcur_virt>first_virt )
+ --tcur_virt;
+ else if(cmd != 'B')
+ {
+ register int last = isalph(tcur_virt-1);
+ register int cur = isalph(tcur_virt);
+ if((!cur && last) || (cur && !last))
+ --tcur_virt;
+ }
+ while( isblank(tcur_virt) && tcur_virt>=first_virt )
+ --tcur_virt;
+ if( cmd == 'B' )
+ {
+ while( !isblank(tcur_virt) && tcur_virt>=first_virt )
+ --tcur_virt;
+ }
+ else
+ {
+ if(isalph(tcur_virt))
+ while( isalph(tcur_virt) && tcur_virt>=first_virt )
+ --tcur_virt;
+ else
+ while( !isalph(tcur_virt) && !isblank(tcur_virt)
+ && tcur_virt>=first_virt )
+ --tcur_virt;
+ }
+ cur_virt = ++tcur_virt;
+ }
+ return;
+}
+
+/*{ CNTLMODE()
+ *
+ * This routine implements the vi command subset.
+ * The cursor will always be positioned at the char of interest.
+ *
+}*/
+
+static int cntlmode(Vi_t *vp)
+{
+ register int c;
+ register int i;
+ genchar tmp_u_space[MAXLINE]; /* temporary u_space */
+ genchar *real_u_space; /* points to real u_space */
+ int tmp_u_column = INVALID; /* temporary u_column */
+ int was_inmacro;
+
+ if(!vp->U_saved)
+ {
+ /*** save virtual image if never done before ***/
+ virtual[last_virt+1] = '\0';
+ gencpy(vp->U_space, virtual);
+ vp->U_saved = 1;
+ }
+
+ save_last(vp);
+
+ real_u_space = vp->u_space;
+ curhline = histmax;
+ first_virt = 0;
+ vp->repeat = 1;
+ if( cur_virt > INVALID )
+ {
+ /*** make sure cursor is at the last char ***/
+ sync_cursor(vp);
+ }
+
+ /*** Read control char until something happens to cause a ***/
+ /* return to APPEND/REPLACE mode */
+
+ while( c=ed_getchar(vp->ed,-1) )
+ {
+ vp->repeat_set = 0;
+ was_inmacro = inmacro;
+ if( c == '0' )
+ {
+ /*** move to leftmost column ***/
+ cur_virt = 0;
+ sync_cursor(vp);
+ continue;
+ }
+
+ if( digit(c) )
+ {
+ c = getcount(vp,c);
+ if( c == '.' )
+ vp->lastrepeat = vp->repeat;
+ }
+
+ /*** see if it's a move cursor command ***/
+
+ if(mvcursor(vp,c))
+ {
+ sync_cursor(vp);
+ vp->repeat = 1;
+ continue;
+ }
+
+ /*** see if it's a repeat of the last command ***/
+
+ if( c == '.' )
+ {
+ c = vp->last_cmd;
+ vp->repeat = vp->lastrepeat;
+ i = textmod(vp,c, c);
+ }
+ else
+ {
+ i = textmod(vp,c, 0);
+ }
+
+ /*** see if it's a text modification command ***/
+
+ switch(i)
+ {
+ case BAD:
+ break;
+
+ default: /** input mode **/
+ if(!was_inmacro)
+ {
+ vp->last_cmd = c;
+ vp->lastrepeat = vp->repeat;
+ }
+ vp->repeat = 1;
+ if( i == GOOD )
+ continue;
+ return(i);
+ }
+
+ switch( c )
+ {
+ /***** Other stuff *****/
+
+ case cntl('L'): /** Redraw line **/
+ /*** print the prompt and ***/
+ /* force a total refresh */
+ if(vp->nonewline==0 && !vp->ed->e_nocrnl)
+ putchar('\n');
+ vp->nonewline = 0;
+ pr_string(vp,Prompt);
+ window[0] = '\0';
+ cur_phys = vp->first_wind;
+ vp->ofirst_wind = INVALID;
+ vp->long_line = ' ';
+ break;
+
+ case cntl('V'):
+ {
+ register const char *p = fmtident(e_version);
+ save_v(vp);
+ del_line(vp,BAD);
+ while(c = *p++)
+ append(vp,c,APPEND);
+ refresh(vp,CONTROL);
+ ed_getchar(vp->ed,-1);
+ restore_v(vp);
+ break;
+ }
+
+ case '/': /** Search **/
+ case '?':
+ case 'N':
+ case 'n':
+ save_v(vp);
+ switch( search(vp,c) )
+ {
+ case GOOD:
+ /*** force a total refresh ***/
+ window[0] = '\0';
+ goto newhist;
+
+ case BAD:
+ /*** no match ***/
+ ed_ringbell();
+
+ default:
+ if( vp->u_column == INVALID )
+ del_line(vp,BAD);
+ else
+ restore_v(vp);
+ break;
+ }
+ break;
+
+ case 'j': /** get next command **/
+ case '+': /** get next command **/
+#if SHOPT_EDPREDICT
+ if(vp->ed->hlist)
+ {
+ if(vp->ed->hoff >= vp->ed->hmax)
+ goto ringbell;
+ vp->ed->hoff++;
+ goto hupdate;
+ }
+#endif /* SHOPT_EDPREDICT */
+ curhline += vp->repeat;
+ if( curhline > histmax )
+ {
+ curhline = histmax;
+ goto ringbell;
+ }
+ else if(curhline==histmax && tmp_u_column!=INVALID )
+ {
+ vp->u_space = tmp_u_space;
+ vp->u_column = tmp_u_column;
+ restore_v(vp);
+ vp->u_space = real_u_space;
+ break;
+ }
+ save_v(vp);
+ cur_virt = INVALID;
+ goto newhist;
+
+ case 'k': /** get previous command **/
+ case '-': /** get previous command **/
+#if SHOPT_EDPREDICT
+ if(vp->ed->hlist)
+ {
+ if(vp->ed->hoff == 0)
+ goto ringbell;
+ vp->ed->hoff--;
+ hupdate:
+ ed_histlist(vp->ed,*vp->ed->hlist!=0);
+ vp->nonewline++;
+ ed_ungetchar(vp->ed,cntl('L'));
+ continue;
+ }
+#endif /* SHOPT_EDPREDICT */
+ if( curhline == histmax )
+ {
+ vp->u_space = tmp_u_space;
+ i = vp->u_column;
+ save_v(vp);
+ vp->u_space = real_u_space;
+ tmp_u_column = vp->u_column;
+ vp->u_column = i;
+ }
+
+ curhline -= vp->repeat;
+ if( curhline <= histmin )
+ {
+ curhline += vp->repeat;
+ goto ringbell;
+ }
+ save_v(vp);
+ cur_virt = INVALID;
+ newhist:
+ if(curhline!=histmax || cur_virt==INVALID)
+ hist_copy((char*)virtual, MAXLINE, curhline,-1);
+ else
+ {
+ strcpy((char*)virtual,(char*)vp->u_space);
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)vp->u_space,vp->u_space);
+#endif /* SHOPT_MULTIBYTE */
+ }
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)virtual,virtual);
+#endif /* SHOPT_MULTIBYTE */
+ if((last_virt=genlen(virtual)-1) >= 0 && cur_virt == INVALID)
+ cur_virt = 0;
+#if SHOPT_EDPREDICT
+ if(vp->ed->hlist)
+ {
+ ed_histlist(vp->ed,0);
+ if(c=='\n')
+ ed_ungetchar(vp->ed,c);
+ ed_ungetchar(vp->ed,cntl('L'));
+ vp->nonewline = 1;
+ cur_virt = 0;
+ }
+#endif /*SHOPT_EDPREDICT */
+ break;
+
+
+ case 'u': /** undo the last thing done **/
+ restore_v(vp);
+ break;
+
+ case 'U': /** Undo everything **/
+ save_v(vp);
+ if( virtual[0] == '\0' )
+ goto ringbell;
+ else
+ {
+ gencpy(virtual, vp->U_space);
+ last_virt = genlen(vp->U_space) - 1;
+ cur_virt = 0;
+ }
+ break;
+
+#if KSHELL
+ case 'v':
+ if(vp->repeat_set==0)
+ goto vcommand;
+#endif /* KSHELL */
+
+ case 'G': /** goto command repeat **/
+ if(vp->repeat_set==0)
+ vp->repeat = histmin+1;
+ if( vp->repeat <= histmin || vp->repeat > histmax )
+ {
+ goto ringbell;
+ }
+ curhline = vp->repeat;
+ save_v(vp);
+ if(c == 'G')
+ {
+ cur_virt = INVALID;
+ goto newhist;
+ }
+
+#if KSHELL
+ vcommand:
+ if(ed_fulledit(vp->ed)==GOOD)
+ return(BIGVI);
+ else
+ goto ringbell;
+#endif /* KSHELL */
+
+ case '#': /** insert(delete) # to (no)comment command **/
+ if( cur_virt != INVALID )
+ {
+ register genchar *p = &virtual[last_virt+1];
+ *p = 0;
+ /*** see whether first char is comment char ***/
+ c = (virtual[0]=='#');
+ while(p-- >= virtual)
+ {
+ if(*p=='\n' || p<virtual)
+ {
+ if(c) /* delete '#' */
+ {
+ if(p[1]=='#')
+ {
+ last_virt--;
+ gencpy(p+1,p+2);
+ }
+ }
+ else
+ {
+ cur_virt = p-virtual;
+ append(vp,'#', APPEND);
+ }
+ }
+ }
+ if(c)
+ {
+ curhline = histmax;
+ cur_virt = 0;
+ break;
+ }
+ refresh(vp,INPUT);
+ }
+
+ case '\n': /** send to shell **/
+#if SHOPT_EDPREDICT
+ if(!vp->ed->hlist)
+ return(ENTER);
+ case '\t': /** bring choice to edit **/
+ if(vp->ed->hlist)
+ {
+ if(vp->repeat > vp->ed->nhlist-vp->ed->hoff)
+ goto ringbell;
+ curhline = vp->ed->hlist[vp->repeat+vp->ed->hoff-1]->index;
+ goto newhist;
+ }
+ goto ringbell;
+#else
+ return(ENTER);
+#endif /* SHOPT_EDPREDICT */
+ case ESC:
+ /* don't ring bell if next char is '[' */
+ if(!lookahead)
+ {
+ char x;
+ if(sfpkrd(editb.e_fd,&x,1,'\r',400L,-1)>0)
+ ed_ungetchar(vp->ed,x);
+ }
+ if(lookahead)
+ {
+ ed_ungetchar(vp->ed,c=ed_getchar(vp->ed,1));
+ if(c=='[')
+ {
+ vp->repeat = 1;
+ continue;
+ }
+ }
+ default:
+ ringbell:
+ ed_ringbell();
+ vp->repeat = 1;
+ continue;
+ }
+
+ refresh(vp,CONTROL);
+ vp->repeat = 1;
+ }
+/* NOTREACHED */
+ return(0);
+}
+
+/*{ CURSOR( new_current_physical )
+ *
+ * This routine will position the virtual cursor at
+ * physical column x in the window.
+ *
+}*/
+
+static void cursor(Vi_t *vp,register int x)
+{
+#if SHOPT_MULTIBYTE
+ while(physical[x]==MARKER)
+ x++;
+#endif /* SHOPT_MULTIBYTE */
+ cur_phys = ed_setcursor(vp->ed, physical, cur_phys,x,vp->first_wind);
+}
+
+/*{ DELETE( nchars, mode )
+ *
+ * Delete nchars from the virtual space and leave cur_virt positioned
+ * at cur_virt-1.
+ *
+ * If mode = 'c', do not save the characters deleted
+ * = 'd', save them in yankbuf and delete.
+ * = 'y', save them in yankbuf but do not delete.
+ *
+}*/
+
+static void cdelete(Vi_t *vp,register int nchars, int mode)
+{
+ register int i;
+ register genchar *cp;
+
+ if( cur_virt < first_virt )
+ {
+ ed_ringbell();
+ return;
+ }
+ if( nchars > 0 )
+ {
+ cp = virtual+cur_virt;
+ vp->o_v_char = cp[0];
+ if( (cur_virt-- + nchars) > last_virt )
+ {
+ /*** set nchars to number actually deleted ***/
+ nchars = last_virt - cur_virt;
+ }
+
+ /*** save characters to be deleted ***/
+
+ if( mode != 'c' )
+ {
+ i = cp[nchars];
+ cp[nchars] = 0;
+ gencpy(yankbuf,cp);
+ cp[nchars] = i;
+ }
+
+ /*** now delete these characters ***/
+
+ if( mode != 'y' )
+ {
+ gencpy(cp,cp+nchars);
+ last_virt -= nchars;
+ }
+ }
+ return;
+}
+
+/*{ DEL_LINE( mode )
+ *
+ * This routine will delete the line.
+ * mode = GOOD, do a save_v()
+ *
+}*/
+static void del_line(register Vi_t *vp, int mode)
+{
+ if( last_virt == INVALID )
+ return;
+
+ if( mode == GOOD )
+ save_v(vp);
+
+ cur_virt = 0;
+ first_virt = 0;
+ cdelete(vp,last_virt+1, BAD);
+ refresh(vp,CONTROL);
+
+ cur_virt = INVALID;
+ cur_phys = 0;
+ vp->findchar = INVALID;
+ last_phys = INVALID;
+ last_virt = INVALID;
+ vp->last_wind = INVALID;
+ vp->first_wind = 0;
+ vp->o_v_char = '\0';
+ vp->ocur_phys = 0;
+ vp->ocur_virt = MAXCHAR;
+ vp->ofirst_wind = 0;
+ window[0] = '\0';
+ return;
+}
+
+/*{ DELMOTION( motion, mode )
+ *
+ * Delete thru motion.
+ *
+ * mode = 'd', save deleted characters, delete
+ * = 'c', do not save characters, change
+ * = 'y', save characters, yank
+ *
+ * Returns 1 if operation successful; else 0.
+ *
+}*/
+
+static int delmotion(Vi_t *vp,int motion, int mode)
+{
+ register int begin, end, delta;
+ /* the following saves a register */
+
+ if( cur_virt == INVALID )
+ return(0);
+ if( mode != 'y' )
+ save_v(vp);
+ begin = cur_virt;
+
+ /*** fake out the motion routines by appending a blank ***/
+
+ virtual[++last_virt] = ' ';
+ end = mvcursor(vp,motion);
+ virtual[last_virt--] = 0;
+ if(!end)
+ return(0);
+
+ end = cur_virt;
+ if( mode=='c' && end>begin && strchr("wW", motion) )
+ {
+ /*** called by change operation, user really expects ***/
+ /* the effect of the eE commands, so back up to end of word */
+ while( end>begin && isblank(end-1) )
+ --end;
+ if( end == begin )
+ ++end;
+ }
+
+ delta = end - begin;
+ if( delta >= 0 )
+ {
+ cur_virt = begin;
+ if( strchr("eE;,TtFf%", motion) )
+ ++delta;
+ }
+ else
+ {
+ delta = -delta + (motion=='%');
+ }
+
+ cdelete(vp,delta, mode);
+ if( mode == 'y' )
+ cur_virt = begin;
+ return(1);
+}
+
+
+/*{ ENDWORD( nwords, cmd )
+ *
+ * This routine will move cur_virt to the end of the nth word.
+ *
+}*/
+
+static void endword(Vi_t *vp, int nwords, register int cmd)
+{
+ register int tcur_virt = cur_virt;
+ while( nwords-- )
+ {
+ if( !isblank(tcur_virt) && tcur_virt<=last_virt )
+ ++tcur_virt;
+ while( isblank(tcur_virt) && tcur_virt<=last_virt )
+ ++tcur_virt;
+ if( cmd == 'E' )
+ {
+ while( !isblank(tcur_virt) && tcur_virt<=last_virt )
+ ++tcur_virt;
+ }
+ else
+ {
+ if( isalph(tcur_virt) )
+ while( isalph(tcur_virt) && tcur_virt<=last_virt )
+ ++tcur_virt;
+ else
+ while( !isalph(tcur_virt) && !isblank(tcur_virt)
+ && tcur_virt<=last_virt )
+ ++tcur_virt;
+ }
+ if( tcur_virt > first_virt )
+ tcur_virt--;
+ }
+ cur_virt = tcur_virt;
+ return;
+}
+
+/*{ FORWARD( nwords, cmd )
+ *
+ * This routine will move cur_virt forward to the next nth word.
+ *
+}*/
+
+static void forward(Vi_t *vp,register int nwords, int cmd)
+{
+ register int tcur_virt = cur_virt;
+ while( nwords-- )
+ {
+ if( cmd == 'W' )
+ {
+ while( !isblank(tcur_virt) && tcur_virt < last_virt )
+ ++tcur_virt;
+ }
+ else
+ {
+ if( isalph(tcur_virt) )
+ {
+ while( isalph(tcur_virt) && tcur_virt<last_virt )
+ ++tcur_virt;
+ }
+ else
+ {
+ while( !isalph(tcur_virt) && !isblank(tcur_virt)
+ && tcur_virt < last_virt )
+ ++tcur_virt;
+ }
+ }
+ while( isblank(tcur_virt) && tcur_virt < last_virt )
+ ++tcur_virt;
+ }
+ cur_virt = tcur_virt;
+ return;
+}
+
+
+
+/*{ GETCOUNT(c)
+ *
+ * Set repeat to the user typed number and return the terminating
+ * character.
+ *
+}*/
+
+static int getcount(register Vi_t *vp,register int c)
+{
+ register int i;
+
+ /*** get any repeat count ***/
+
+ if( c == '0' )
+ return(c);
+
+ vp->repeat_set++;
+ i = 0;
+ while( digit(c) )
+ {
+ i = i*10 + c - '0';
+ c = ed_getchar(vp->ed,-1);
+ }
+
+ if( i > 0 )
+ vp->repeat *= i;
+ return(c);
+}
+
+
+/*{ GETLINE( mode )
+ *
+ * This routine will fetch a line.
+ * mode = APPEND, allow escape to cntlmode subroutine
+ * appending characters.
+ * = REPLACE, allow escape to cntlmode subroutine
+ * replacing characters.
+ * = SEARCH, no escape allowed
+ * = ESC, enter control mode immediately
+ *
+ * The cursor will always be positioned after the last
+ * char printed.
+ *
+ * This routine returns when cr, nl, or (eof in column 0) is
+ * received (column 0 is the first char position).
+ *
+}*/
+
+static void getline(register Vi_t* vp,register int mode)
+{
+ register int c;
+ register int tmp;
+ int max_virt=0, last_save=0;
+ genchar saveline[MAXLINE];
+ vp->addnl = 1;
+
+ if( mode == ESC )
+ {
+ /*** go directly to control mode ***/
+ goto escape;
+ }
+
+ for(;;)
+ {
+ if( (c=ed_getchar(vp->ed,mode==SEARCH?1:-2)) == usreof )
+ c = UEOF;
+ else if( c == usrerase )
+ c = UERASE;
+ else if( c == usrkill )
+ c = UKILL;
+ else if( c == editb.e_werase )
+ c = UWERASE;
+ else if( c == usrlnext )
+ c = ULNEXT;
+ else if(mode==SEARCH && c==editb.e_intr)
+ c = UINTR;
+
+ if( c == ULNEXT)
+ {
+ /*** implement ^V to escape next char ***/
+ c = ed_getchar(vp->ed,2);
+ append(vp,c, mode);
+ refresh(vp,INPUT);
+ continue;
+ }
+
+ switch( c )
+ {
+ case ESC: /** enter control mode **/
+ if(!sh_isoption(SH_VI))
+ {
+ append(vp,c, mode);
+ break;
+ }
+ if( mode == SEARCH )
+ {
+ ed_ringbell();
+ continue;
+ }
+ else
+ {
+ escape:
+ if( mode == REPLACE )
+ {
+ c = max_virt-cur_virt;
+ if(c > 0 && last_save>=cur_virt)
+ {
+ genncpy((&virtual[cur_virt]),&saveline[cur_virt],c);
+ if(last_virt>=last_save)
+ last_virt=last_save-1;
+ refresh(vp,INPUT);
+ }
+ --cur_virt;
+ }
+ tmp = cntlmode(vp);
+ if( tmp == ENTER || tmp == BIGVI )
+ {
+#if SHOPT_MULTIBYTE
+ vp->bigvi = (tmp==BIGVI);
+#endif /* SHOPT_MULTIBYTE */
+ return;
+ }
+ if( tmp == INSERT )
+ {
+ mode = APPEND;
+ continue;
+ }
+ mode = tmp;
+ if(mode==REPLACE)
+ {
+ c = last_save = last_virt+1;
+ if(c >= MAXLINE)
+ c = MAXLINE-1;
+ genncpy(saveline, virtual, c);
+ }
+ }
+ break;
+
+ case UINTR:
+ first_virt = 0;
+ cdelete(vp,cur_virt+1, BAD);
+ cur_virt = -1;
+ return;
+ case UERASE: /** user erase char **/
+ /*** treat as backspace ***/
+
+ case '\b': /** backspace **/
+ if( virtual[cur_virt] == '\\' )
+ {
+ cdelete(vp,1, BAD);
+ append(vp,usrerase, mode);
+ }
+ else
+ {
+ if( mode==SEARCH && cur_virt==0 )
+ {
+ first_virt = 0;
+ cdelete(vp,1, BAD);
+ return;
+ }
+ if(mode==REPLACE || (last_save>0 && last_virt<=last_save))
+ {
+ if(cur_virt<=first_virt)
+ ed_ringbell();
+ else if(mode==REPLACE)
+ --cur_virt;
+ mode = REPLACE;
+ sync_cursor(vp);
+ continue;
+ }
+ else
+ cdelete(vp,1, BAD);
+ }
+ break;
+
+ case UWERASE: /** delete back word **/
+ if( cur_virt > first_virt &&
+ !isblank(cur_virt) &&
+ !ispunct(virtual[cur_virt]) &&
+ isblank(cur_virt-1) )
+ {
+ cdelete(vp,1, BAD);
+ }
+ else
+ {
+ tmp = cur_virt;
+ backword(vp,1, 'W');
+ cdelete(vp,tmp - cur_virt + 1, BAD);
+ }
+ break;
+
+ case UKILL: /** user kill line char **/
+ if( virtual[cur_virt] == '\\' )
+ {
+ cdelete(vp,1, BAD);
+ append(vp,usrkill, mode);
+ }
+ else
+ {
+ if( mode == SEARCH )
+ {
+ cur_virt = 1;
+ delmotion(vp, '$', BAD);
+ }
+ else if(first_virt)
+ {
+ tmp = cur_virt;
+ cur_virt = first_virt;
+ cdelete(vp,tmp - cur_virt + 1, BAD);
+ }
+ else
+ del_line(vp,GOOD);
+ }
+ break;
+
+ case UEOF: /** eof char **/
+ if( cur_virt != INVALID )
+ continue;
+ vp->addnl = 0;
+
+ case '\n': /** newline or return **/
+ if( mode != SEARCH )
+ save_last(vp);
+ refresh(vp,INPUT);
+ last_phys++;
+ return;
+
+ case '\t': /** command completion **/
+ if(mode!=SEARCH && last_virt>=0 && (vp->ed->e_tabcount|| !isblank(cur_virt)) && vp->ed->sh->nextprompt)
+ {
+ if(virtual[cur_virt]=='\\')
+ {
+ virtual[cur_virt] = '\t';
+ break;
+ }
+ if(vp->ed->e_tabcount==0)
+ {
+ ed_ungetchar(vp->ed,'\\');
+ vp->ed->e_tabcount=1;
+ goto escape;
+ }
+ else if(vp->ed->e_tabcount==1)
+ {
+ ed_ungetchar(vp->ed,'=');
+ goto escape;
+ }
+ vp->ed->e_tabcount = 0;
+ }
+ /* FALL THRU*/
+ default:
+ if( mode == REPLACE )
+ {
+ if( cur_virt < last_virt )
+ {
+ replace(vp,c, 1);
+ if(cur_virt>max_virt)
+ max_virt = cur_virt;
+ continue;
+ }
+ cdelete(vp,1, BAD);
+ mode = APPEND;
+ max_virt = last_virt+3;
+ }
+ append(vp,c, mode);
+ break;
+ }
+ refresh(vp,INPUT);
+
+ }
+}
+
+/*{ MVCURSOR( motion )
+ *
+ * This routine will move the virtual cursor according to motion
+ * for repeat times.
+ *
+ * It returns GOOD if successful; else BAD.
+ *
+}*/
+
+static int mvcursor(register Vi_t* vp,register int motion)
+{
+ register int count;
+ register int tcur_virt;
+ register int incr = -1;
+ register int bound = 0;
+
+ switch(motion)
+ {
+ /***** Cursor move commands *****/
+
+ case '0': /** First column **/
+ tcur_virt = 0;
+ break;
+
+ case '^': /** First nonblank character **/
+ tcur_virt = first_virt;
+ while( isblank(tcur_virt) && tcur_virt < last_virt )
+ ++tcur_virt;
+ break;
+
+ case '|':
+ tcur_virt = vp->repeat-1;
+ if(tcur_virt <= last_virt)
+ break;
+ /* fall through */
+
+ case '$': /** End of line **/
+ tcur_virt = last_virt;
+ break;
+
+ case '[':
+ switch(motion=getcount(vp,ed_getchar(vp->ed,-1)))
+ {
+ case 'A':
+#if SHOPT_EDPREDICT
+ if(!vp->ed->hlist && cur_virt>=0 && cur_virt<(SEARCHSIZE-2) && cur_virt == last_virt)
+#else
+ if(cur_virt>=0 && cur_virt<(SEARCHSIZE-2) && cur_virt == last_virt)
+#endif /* SHOPT_EDPREDICT */
+ {
+ virtual[last_virt + 1] = '\0';
+#if SHOPT_MULTIBYTE
+ ed_external(virtual,lsearch+1);
+#else
+ strcpy(lsearch+1,virtual);
+#endif /* SHOPT_MULTIBYTE */
+ *lsearch = '^';
+ vp->direction = -2;
+ ed_ungetchar(vp->ed,'n');
+ }
+ else if(cur_virt==0 && vp->direction == -2)
+ ed_ungetchar(vp->ed,'n');
+ else
+ ed_ungetchar(vp->ed,'k');
+ return(1);
+ case 'B':
+ ed_ungetchar(vp->ed,'j');
+ return(1);
+ case 'C':
+ motion = last_virt;
+ incr = 1;
+ goto walk;
+ case 'D':
+ motion = first_virt;
+ goto walk;
+ case 'H':
+ tcur_virt = 0;
+ break;
+ case 'Y':
+ tcur_virt = last_virt;
+ break;
+ default:
+ ed_ungetchar(vp->ed,motion);
+ return(0);
+ }
+ break;
+
+ case 'h': /** Left one **/
+ case '\b':
+ motion = first_virt;
+ goto walk;
+
+ case ' ':
+ case 'l': /** Right one **/
+ motion = last_virt;
+ incr = 1;
+ walk:
+ tcur_virt = cur_virt;
+ if( incr*tcur_virt < motion)
+ {
+ tcur_virt += vp->repeat*incr;
+ if( incr*tcur_virt > motion)
+ tcur_virt = motion;
+ }
+ else
+ return(0);
+ break;
+
+ case 'B':
+ case 'b': /** back word **/
+ tcur_virt = cur_virt;
+ backword(vp,vp->repeat, motion);
+ if( cur_virt == tcur_virt )
+ return(0);
+ return(1);
+
+ case 'E':
+ case 'e': /** end of word **/
+ tcur_virt = cur_virt;
+ if(tcur_virt >=0)
+ endword(vp, vp->repeat, motion);
+ if( cur_virt == tcur_virt )
+ return(0);
+ return(1);
+
+ case ',': /** reverse find old char **/
+ case ';': /** find old char **/
+ switch(vp->last_find)
+ {
+ case 't':
+ case 'f':
+ if(motion==';')
+ {
+ bound = last_virt;
+ incr = 1;
+ }
+ goto find_b;
+
+ case 'T':
+ case 'F':
+ if(motion==',')
+ {
+ bound = last_virt;
+ incr = 1;
+ }
+ goto find_b;
+
+ default:
+ return(0);
+ }
+
+
+ case 't': /** find up to new char forward **/
+ case 'f': /** find new char forward **/
+ bound = last_virt;
+ incr = 1;
+
+ case 'T': /** find up to new char backward **/
+ case 'F': /** find new char backward **/
+ vp->last_find = motion;
+ if((vp->findchar=getrchar(vp))==ESC)
+ return(1);
+find_b:
+ tcur_virt = cur_virt;
+ count = vp->repeat;
+ while( count-- )
+ {
+ while( incr*(tcur_virt+=incr) <= bound
+ && virtual[tcur_virt] != vp->findchar );
+ if( incr*tcur_virt > bound )
+ {
+ return(0);
+ }
+ }
+ if( fold(vp->last_find) == 'T' )
+ tcur_virt -= incr;
+ break;
+
+ case '%':
+ {
+ int nextmotion;
+ int nextc;
+ tcur_virt = cur_virt;
+ while( tcur_virt <= last_virt
+ && strchr(paren_chars,virtual[tcur_virt])==(char*)0)
+ tcur_virt++;
+ if(tcur_virt > last_virt )
+ return(0);
+ nextc = virtual[tcur_virt];
+ count = strchr(paren_chars,nextc)-paren_chars;
+ if(count < 3)
+ {
+ incr = 1;
+ bound = last_virt;
+ nextmotion = paren_chars[count+3];
+ }
+ else
+ nextmotion = paren_chars[count-3];
+ count = 1;
+ while(count >0 && incr*(tcur_virt+=incr) <= bound)
+ {
+ if(virtual[tcur_virt] == nextmotion)
+ count--;
+ else if(virtual[tcur_virt]==nextc)
+ count++;
+ }
+ if(count)
+ return(0);
+ break;
+ }
+
+ case 'W':
+ case 'w': /** forward word **/
+ tcur_virt = cur_virt;
+ forward(vp,vp->repeat, motion);
+ if( tcur_virt == cur_virt )
+ return(0);
+ return(1);
+
+ default:
+ return(0);
+ }
+ cur_virt = tcur_virt;
+
+ return(1);
+}
+
+/*
+ * print a string
+ */
+
+static void pr_string(register Vi_t *vp, register const char *sp)
+{
+ /*** copy string sp ***/
+ register char *ptr = editb.e_outptr;
+ while(*sp)
+ *ptr++ = *sp++;
+ editb.e_outptr = ptr;
+ return;
+}
+
+/*{ PUTSTRING( column, nchars )
+ *
+ * Put nchars starting at column of physical into the workspace
+ * to be printed.
+ *
+}*/
+
+static void putstring(register Vi_t *vp,register int col, register int nchars)
+{
+ while( nchars-- )
+ putchar(physical[col++]);
+ return;
+}
+
+/*{ REFRESH( mode )
+ *
+ * This routine will refresh the crt so the physical image matches
+ * the virtual image and display the proper window.
+ *
+ * mode = CONTROL, refresh in control mode, ie. leave cursor
+ * positioned at last char printed.
+ * = INPUT, refresh in input mode; leave cursor positioned
+ * after last char printed.
+ * = TRANSLATE, perform virtual to physical translation
+ * and adjust left margin only.
+ *
+ * +-------------------------------+
+ * | | | virtual | | |
+ * +-------------------------------+
+ * cur_virt last_virt
+ *
+ * +-----------------------------------------------+
+ * | | | physical | | |
+ * +-----------------------------------------------+
+ * cur_phys last_phys
+ *
+ * 0 w_size - 1
+ * +-----------------------+
+ * | | | window |
+ * +-----------------------+
+ * cur_window = cur_phys - first_wind
+}*/
+
+static void refresh(register Vi_t* vp, int mode)
+{
+ register int p;
+ register int v;
+ register int first_w = vp->first_wind;
+ int p_differ;
+ int new_lw;
+ int ncur_phys;
+ int opflag; /* search optimize flag */
+
+# define w v
+
+ /*** find out if it's necessary to start translating at beginning ***/
+
+ if(lookahead>0)
+ {
+ p = previous[lookahead-1];
+ if(p != ESC && p != '\n' && p != '\r')
+ mode = TRANSLATE;
+ }
+ v = cur_virt;
+#if SHOPT_EDPREDICT
+ if(mode==INPUT && v>0 && virtual[0]=='#' && v==last_virt && virtual[v]!='*' && sh_isoption(SH_VI))
+ {
+ int n;
+ virtual[last_virt+1] = 0;
+# if SHOPT_MULTIBYTE
+ ed_external(virtual,(char*)virtual);
+# endif /* SHOPT_MULTIBYTE */
+ n = ed_histgen(vp->ed,(char*)virtual);
+# if SHOPT_MULTIBYTE
+ ed_internal((char*)virtual,virtual);
+# endif /* SHOPT_MULTIBYTE */
+ if(vp->ed->hlist)
+ {
+ ed_histlist(vp->ed,n);
+ pr_string(vp,Prompt);
+ vp->ocur_virt = INVALID;
+ ed_setcursor(vp->ed,physical,0,cur_phys,0);
+ }
+ else
+ ed_ringbell();
+ }
+ else if(mode==INPUT && v<=1 && vp->ed->hlist)
+ ed_histlist(vp->ed,0);
+#endif /* SHOPT_EDPREDICT */
+ if( v<vp->ocur_virt || vp->ocur_virt==INVALID
+ || ( v==vp->ocur_virt
+ && (!is_print(virtual[v]) || !is_print(vp->o_v_char))) )
+ {
+ opflag = 0;
+ p = 0;
+ v = 0;
+ }
+ else
+ {
+ opflag = 1;
+ p = vp->ocur_phys;
+ v = vp->ocur_virt;
+ if( !is_print(virtual[v]) )
+ {
+ /*** avoid double ^'s ***/
+ ++p;
+ ++v;
+ }
+ }
+ virtual[last_virt+1] = 0;
+ ncur_phys = ed_virt_to_phys(vp->ed,virtual,physical,cur_virt,v,p);
+ p = genlen(physical);
+ if( --p < 0 )
+ last_phys = 0;
+ else
+ last_phys = p;
+
+ /*** see if this was a translate only ***/
+
+ if( mode == TRANSLATE )
+ return;
+
+ /*** adjust left margin if necessary ***/
+
+ if( ncur_phys<first_w || ncur_phys>=(first_w + w_size) )
+ {
+ cursor(vp,first_w);
+ first_w = ncur_phys - (w_size>>1);
+ if( first_w < 0 )
+ first_w = 0;
+ vp->first_wind = cur_phys = first_w;
+ }
+
+ /*** attempt to optimize search somewhat to find ***/
+ /*** out where physical and window images differ ***/
+
+ if( first_w==vp->ofirst_wind && ncur_phys>=vp->ocur_phys && opflag==1 )
+ {
+ p = vp->ocur_phys;
+ w = p - first_w;
+ }
+ else
+ {
+ p = first_w;
+ w = 0;
+ }
+
+ for(; (p<=last_phys && w<=vp->last_wind); ++p, ++w)
+ {
+ if( window[w] != physical[p] )
+ break;
+ }
+ p_differ = p;
+
+ if( (p>last_phys || p>=first_w+w_size) && w>vp->last_wind
+ && cur_virt==vp->ocur_virt )
+ {
+ /*** images are identical ***/
+ return;
+ }
+
+ /*** copy the physical image to the window image ***/
+
+ if( last_virt != INVALID )
+ {
+ while( p <= last_phys && w < w_size )
+ window[w++] = physical[p++];
+ }
+ new_lw = w;
+
+ /*** erase trailing characters if needed ***/
+
+ while( w <= vp->last_wind )
+ window[w++] = ' ';
+ vp->last_wind = --w;
+
+ p = p_differ;
+
+ /*** move cursor to start of difference ***/
+
+ cursor(vp,p);
+
+ /*** and output difference ***/
+
+ w = p - first_w;
+ while( w <= vp->last_wind )
+ putchar(window[w++]);
+
+ cur_phys = w + first_w;
+ vp->last_wind = --new_lw;
+
+ if( last_phys >= w_size )
+ {
+ if( first_w == 0 )
+ vp->long_char = '>';
+ else if( last_phys < (first_w+w_size) )
+ vp->long_char = '<';
+ else
+ vp->long_char = '*';
+ }
+ else
+ vp->long_char = ' ';
+
+ if( vp->long_line != vp->long_char )
+ {
+ /*** indicate lines longer than window ***/
+ while( w++ < w_size )
+ {
+ putchar(' ');
+ ++cur_phys;
+ }
+ putchar(vp->long_char);
+ ++cur_phys;
+ vp->long_line = vp->long_char;
+ }
+
+ if(vp->ed->e_multiline && vp->ofirst_wind==INVALID && !vp->ed->e_nocrnl)
+ ed_setcursor(vp->ed, physical, last_phys+1, last_phys+1, -1);
+ vp->ed->e_nocrnl = 0;
+ vp->ocur_phys = ncur_phys;
+ vp->ocur_virt = cur_virt;
+ vp->ofirst_wind = first_w;
+
+ if( mode==INPUT && cur_virt>INVALID )
+ ++ncur_phys;
+
+ cursor(vp,ncur_phys);
+ ed_flush(vp->ed);
+ return;
+}
+
+/*{ REPLACE( char, increment )
+ *
+ * Replace the cur_virt character with char. This routine attempts
+ * to avoid using refresh().
+ *
+ * increment = 1, increment cur_virt after replacement.
+ * = 0, leave cur_virt where it is.
+ *
+}*/
+
+static void replace(register Vi_t *vp, register int c, register int increment)
+{
+ register int cur_window;
+
+ if( cur_virt == INVALID )
+ {
+ /*** can't replace invalid cursor ***/
+ ed_ringbell();
+ return;
+ }
+ cur_window = cur_phys - vp->first_wind;
+ if( vp->ocur_virt == INVALID || !is_print(c)
+ || !is_print(virtual[cur_virt])
+ || !is_print(vp->o_v_char)
+#if SHOPT_MULTIBYTE
+ || !iswascii(c) || mbwidth(vp->o_v_char)>1
+ || !iswascii(virtual[cur_virt])
+#endif /* SHOPT_MULTIBYTE */
+ || (increment && (cur_window==w_size-1)
+ || !is_print(virtual[cur_virt+1])) )
+ {
+ /*** must use standard refresh routine ***/
+
+ cdelete(vp,1, BAD);
+ append(vp,c, APPEND);
+ if( increment && cur_virt<last_virt )
+ ++cur_virt;
+ refresh(vp,CONTROL);
+ }
+ else
+ {
+ virtual[cur_virt] = c;
+ physical[cur_phys] = c;
+ window[cur_window] = c;
+ putchar(c);
+ if(increment)
+ {
+ c = virtual[++cur_virt];
+ ++cur_phys;
+ }
+ else
+ {
+ putchar('\b');
+ }
+ vp->o_v_char = c;
+ ed_flush(vp->ed);
+ }
+ return;
+}
+
+/*{ RESTORE_V()
+ *
+ * Restore the contents of virtual space from u_space.
+ *
+}*/
+
+static void restore_v(register Vi_t *vp)
+{
+ register int tmpcol;
+ genchar tmpspace[MAXLINE];
+
+ if( vp->u_column == INVALID-1 )
+ {
+ /*** never saved anything ***/
+ ed_ringbell();
+ return;
+ }
+ gencpy(tmpspace, vp->u_space);
+ tmpcol = vp->u_column;
+ save_v(vp);
+ gencpy(virtual, tmpspace);
+ cur_virt = tmpcol;
+ last_virt = genlen(tmpspace) - 1;
+ vp->ocur_virt = MAXCHAR; /** invalidate refresh optimization **/
+ return;
+}
+
+/*{ SAVE_LAST()
+ *
+ * If the user has typed something, save it in last line.
+ *
+}*/
+
+static void save_last(register Vi_t* vp)
+{
+ register int i;
+
+ if( (i = cur_virt - first_virt + 1) > 0 )
+ {
+ /*** save last thing user typed ***/
+ if(i >= MAXLINE)
+ i = MAXLINE-1;
+ genncpy(vp->lastline, (&virtual[first_virt]), i);
+ vp->lastline[i] = '\0';
+ }
+ return;
+}
+
+/*{ SAVE_V()
+ *
+ * This routine will save the contents of virtual in u_space.
+ *
+}*/
+
+static void save_v(register Vi_t *vp)
+{
+ if(!inmacro)
+ {
+ virtual[last_virt + 1] = '\0';
+ gencpy(vp->u_space, virtual);
+ vp->u_column = cur_virt;
+ }
+ return;
+}
+
+/*{ SEARCH( mode )
+ *
+ * Search history file for regular expression.
+ *
+ * mode = '/' require search string and search new to old
+ * mode = '?' require search string and search old to new
+ * mode = 'N' repeat last search in reverse direction
+ * mode = 'n' repeat last search
+ *
+}*/
+
+/*
+ * search for <string> in the current command
+ */
+static int curline_search(Vi_t *vp, const char *string)
+{
+ register int len=strlen(string);
+ register const char *dp,*cp=string, *dpmax;
+#if SHOPT_MULTIBYTE
+ ed_external(vp->u_space,(char*)vp->u_space);
+#endif /* SHOPT_MULTIBYTE */
+ for(dp=(char*)vp->u_space,dpmax=dp+strlen(dp)-len; dp<=dpmax; dp++)
+ {
+ if(*dp==*cp && memcmp(cp,dp,len)==0)
+ return(dp-(char*)vp->u_space);
+ }
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)vp->u_space,vp->u_space);
+#endif /* SHOPT_MULTIBYTE */
+ return(-1);
+}
+
+static int search(register Vi_t* vp,register int mode)
+{
+ register int new_direction;
+ register int oldcurhline;
+ register int i;
+ Histloc_t location;
+
+ if( vp->direction == -2 && mode != 'n')
+ vp->direction = -1;
+ if( mode == '/' || mode == '?')
+ {
+ /*** new search expression ***/
+ del_line(vp,BAD);
+ append(vp,mode, APPEND);
+ refresh(vp,INPUT);
+ first_virt = 1;
+ getline(vp,SEARCH);
+ first_virt = 0;
+ virtual[last_virt + 1] = '\0'; /*** make null terminated ***/
+ vp->direction = mode=='/' ? -1 : 1;
+ }
+
+ if( cur_virt == INVALID )
+ {
+ /*** no operation ***/
+ return(ABORT);
+ }
+
+ if( cur_virt==0 || fold(mode)=='N' )
+ {
+ /*** user wants repeat of last search ***/
+ del_line(vp,BAD);
+ strcpy( ((char*)virtual)+1, lsearch);
+#if SHOPT_MULTIBYTE
+ *((char*)virtual) = '/';
+ ed_internal((char*)virtual,virtual);
+#endif /* SHOPT_MULTIBYTE */
+ }
+
+ if( mode == 'N' )
+ new_direction = -vp->direction;
+ else
+ new_direction = vp->direction;
+
+
+ /*** now search ***/
+
+ oldcurhline = curhline;
+#if SHOPT_MULTIBYTE
+ ed_external(virtual,(char*)virtual);
+#endif /* SHOPT_MULTIBYTE */
+ if(mode=='?' && (i=curline_search(vp,((char*)virtual)+1))>=0)
+ {
+ location.hist_command = curhline;
+ location.hist_char = i;
+ }
+ else
+ {
+ i = INVALID;
+ if( new_direction==1 && curhline >= histmax )
+ curhline = histmin + 1;
+ location = hist_find(shgd->hist_ptr,((char*)virtual)+1, curhline, 1, new_direction);
+ }
+ cur_virt = i;
+ strncpy(lsearch, ((char*)virtual)+1, SEARCHSIZE);
+ lsearch[SEARCHSIZE-1] = 0;
+ if( (curhline=location.hist_command) >=0 )
+ {
+ vp->ocur_virt = INVALID;
+ return(GOOD);
+ }
+
+ /*** could not find matching line ***/
+
+ curhline = oldcurhline;
+ return(BAD);
+}
+
+/*{ SYNC_CURSOR()
+ *
+ * This routine will move the physical cursor to the same
+ * column as the virtual cursor.
+ *
+}*/
+
+static void sync_cursor(register Vi_t *vp)
+{
+ register int p;
+ register int v;
+ register int c;
+ int new_phys;
+
+ if( cur_virt == INVALID )
+ return;
+
+ /*** find physical col that corresponds to virtual col ***/
+
+ new_phys = 0;
+ if(vp->first_wind==vp->ofirst_wind && cur_virt>vp->ocur_virt && vp->ocur_virt!=INVALID)
+ {
+ /*** try to optimize search a little ***/
+ p = vp->ocur_phys + 1;
+#if SHOPT_MULTIBYTE
+ while(physical[p]==MARKER)
+ p++;
+#endif /* SHOPT_MULTIBYTE */
+ v = vp->ocur_virt + 1;
+ }
+ else
+ {
+ p = 0;
+ v = 0;
+ }
+ for(; v <= last_virt; ++p, ++v)
+ {
+#if SHOPT_MULTIBYTE
+ int d;
+ c = virtual[v];
+ if((d = mbwidth(c)) > 1)
+ {
+ if( v != cur_virt )
+ p += (d-1);
+ }
+ else if(!iswprint(c))
+#else
+ c = virtual[v];
+ if(!isprint(c))
+#endif /* SHOPT_MULTIBYTE */
+ {
+ if( c == '\t' )
+ {
+ p -= ((p+editb.e_plen)%TABSIZE);
+ p += (TABSIZE-1);
+ }
+ else
+ {
+ ++p;
+ }
+ }
+ if( v == cur_virt )
+ {
+ new_phys = p;
+ break;
+ }
+ }
+
+ if( new_phys < vp->first_wind || new_phys >= vp->first_wind + w_size )
+ {
+ /*** asked to move outside of window ***/
+
+ window[0] = '\0';
+ refresh(vp,CONTROL);
+ return;
+ }
+
+ cursor(vp,new_phys);
+ ed_flush(vp->ed);
+ vp->ocur_phys = cur_phys;
+ vp->ocur_virt = cur_virt;
+ vp->o_v_char = virtual[vp->ocur_virt];
+
+ return;
+}
+
+/*{ TEXTMOD( command, mode )
+ *
+ * Modify text operations.
+ *
+ * mode != 0, repeat previous operation
+ *
+}*/
+
+static int textmod(register Vi_t *vp,register int c, int mode)
+{
+ register int i;
+ register genchar *p = vp->lastline;
+ register int trepeat = vp->repeat;
+ genchar *savep;
+
+ if(mode && (fold(vp->lastmotion)=='F' || fold(vp->lastmotion)=='T'))
+ vp->lastmotion = ';';
+
+ if( fold(c) == 'P' )
+ {
+ /*** change p from lastline to yankbuf ***/
+ p = yankbuf;
+ }
+
+addin:
+ switch( c )
+ {
+ /***** Input commands *****/
+
+#if KSHELL
+ case '\t':
+ if(vp->ed->e_tabcount!=1)
+ return(BAD);
+ c = '=';
+ case '*': /** do file name expansion in place **/
+ case '\\': /** do file name completion in place **/
+ if( cur_virt == INVALID )
+ return(BAD);
+ case '=': /** list file name expansions **/
+ save_v(vp);
+ i = last_virt;
+ ++last_virt;
+ mode = cur_virt-1;
+ virtual[last_virt] = 0;
+ if(ed_expand(vp->ed,(char*)virtual, &cur_virt, &last_virt, c, vp->repeat_set?vp->repeat:-1)<0)
+ {
+ if(vp->ed->e_tabcount)
+ {
+ vp->ed->e_tabcount=2;
+ ed_ungetchar(vp->ed,'\t');
+ --last_virt;
+ return(APPEND);
+ }
+ last_virt = i;
+ ed_ringbell();
+ }
+ else if(c == '=' && !vp->repeat_set)
+ {
+ last_virt = i;
+ vp->nonewline++;
+ ed_ungetchar(vp->ed,cntl('L'));
+ return(GOOD);
+ }
+ else
+ {
+ --cur_virt;
+ --last_virt;
+ vp->ocur_virt = MAXCHAR;
+ if(c=='=' || (mode<cur_virt && (virtual[cur_virt]==' ' || virtual[cur_virt]=='/')))
+ vp->ed->e_tabcount = 0;
+ return(APPEND);
+ }
+ break;
+
+ case '@': /** macro expansion **/
+ if( mode )
+ c = vp->lastmacro;
+ else
+ if((c=getrchar(vp))==ESC)
+ return(GOOD);
+ if(!inmacro)
+ vp->lastmacro = c;
+ if(ed_macro(vp->ed,c))
+ {
+ save_v(vp);
+ inmacro++;
+ return(GOOD);
+ }
+ ed_ringbell();
+ return(BAD);
+
+#endif /* KSHELL */
+ case '_': /** append last argument of prev command **/
+ save_v(vp);
+ {
+ genchar tmpbuf[MAXLINE];
+ if(vp->repeat_set==0)
+ vp->repeat = -1;
+ p = (genchar*)hist_word((char*)tmpbuf,MAXLINE,vp->repeat);
+ if(p==0)
+ {
+ ed_ringbell();
+ break;
+ }
+#if SHOPT_MULTIBYTE
+ ed_internal((char*)p,tmpbuf);
+ p = tmpbuf;
+#endif /* SHOPT_MULTIBYTE */
+ i = ' ';
+ do
+ {
+ append(vp,i,APPEND);
+ }
+ while(i = *p++);
+ return(APPEND);
+ }
+
+ case 'A': /** append to end of line **/
+ cur_virt = last_virt;
+ sync_cursor(vp);
+
+ case 'a': /** append **/
+ if( fold(mode) == 'A' )
+ {
+ c = 'p';
+ goto addin;
+ }
+ save_v(vp);
+ if( cur_virt != INVALID )
+ {
+ first_virt = cur_virt + 1;
+ cursor(vp,cur_phys + 1);
+ ed_flush(vp->ed);
+ }
+ return(APPEND);
+
+ case 'I': /** insert at beginning of line **/
+ cur_virt = first_virt;
+ sync_cursor(vp);
+
+ case 'i': /** insert **/
+ if( fold(mode) == 'I' )
+ {
+ c = 'P';
+ goto addin;
+ }
+ save_v(vp);
+ if( cur_virt != INVALID )
+ {
+ vp->o_v_char = virtual[cur_virt];
+ first_virt = cur_virt--;
+ }
+ return(INSERT);
+
+ case 'C': /** change to eol **/
+ c = '$';
+ goto chgeol;
+
+ case 'c': /** change **/
+ if( mode )
+ c = vp->lastmotion;
+ else
+ c = getcount(vp,ed_getchar(vp->ed,-1));
+chgeol:
+ vp->lastmotion = c;
+ if( c == 'c' )
+ {
+ del_line(vp,GOOD);
+ return(APPEND);
+ }
+
+ if(!delmotion(vp, c, 'c'))
+ return(BAD);
+
+ if( mode == 'c' )
+ {
+ c = 'p';
+ trepeat = 1;
+ goto addin;
+ }
+ first_virt = cur_virt + 1;
+ return(APPEND);
+
+ case 'D': /** delete to eol **/
+ c = '$';
+ goto deleol;
+
+ case 'd': /** delete **/
+ if( mode )
+ c = vp->lastmotion;
+ else
+ c = getcount(vp,ed_getchar(vp->ed,-1));
+deleol:
+ vp->lastmotion = c;
+ if( c == 'd' )
+ {
+ del_line(vp,GOOD);
+ break;
+ }
+ if(!delmotion(vp, c, 'd'))
+ return(BAD);
+ if( cur_virt < last_virt )
+ ++cur_virt;
+ break;
+
+ case 'P':
+ if( p[0] == '\0' )
+ return(BAD);
+ if( cur_virt != INVALID )
+ {
+ i = virtual[cur_virt];
+ if(!is_print(i))
+ vp->ocur_virt = INVALID;
+ --cur_virt;
+ }
+
+ case 'p': /** print **/
+ if( p[0] == '\0' )
+ return(BAD);
+
+ if( mode != 's' && mode != 'c' )
+ {
+ save_v(vp);
+ if( c == 'P' )
+ {
+ /*** fix stored cur_virt ***/
+ ++vp->u_column;
+ }
+ }
+ if( mode == 'R' )
+ mode = REPLACE;
+ else
+ mode = APPEND;
+ savep = p;
+ for(i=0; i<trepeat; ++i)
+ {
+ while(c= *p++)
+ append(vp,c,mode);
+ p = savep;
+ }
+ break;
+
+ case 'R': /* Replace many chars **/
+ if( mode == 'R' )
+ {
+ c = 'P';
+ goto addin;
+ }
+ save_v(vp);
+ if( cur_virt != INVALID )
+ first_virt = cur_virt;
+ return(REPLACE);
+
+ case 'r': /** replace **/
+ if( mode )
+ c = *p;
+ else
+ if((c=getrchar(vp))==ESC)
+ return(GOOD);
+ *p = c;
+ save_v(vp);
+ while(trepeat--)
+ replace(vp,c, trepeat!=0);
+ return(GOOD);
+
+ case 'S': /** Substitute line - cc **/
+ c = 'c';
+ goto chgeol;
+
+ case 's': /** substitute **/
+ save_v(vp);
+ cdelete(vp,vp->repeat, BAD);
+ if( mode )
+ {
+ c = 'p';
+ trepeat = 1;
+ goto addin;
+ }
+ first_virt = cur_virt + 1;
+ return(APPEND);
+
+ case 'Y': /** Yank to end of line **/
+ c = '$';
+ goto yankeol;
+
+ case 'y': /** yank thru motion **/
+ if( mode )
+ c = vp->lastmotion;
+ else
+ c = getcount(vp,ed_getchar(vp->ed,-1));
+yankeol:
+ vp->lastmotion = c;
+ if( c == 'y' )
+ {
+ gencpy(yankbuf, virtual);
+ }
+ else if(!delmotion(vp, c, 'y'))
+ {
+ return(BAD);
+ }
+ break;
+
+ case 'x': /** delete repeat chars forward - dl **/
+ c = 'l';
+ goto deleol;
+
+ case 'X': /** delete repeat chars backward - dh **/
+ c = 'h';
+ goto deleol;
+
+ case '~': /** invert case and advance **/
+ if( cur_virt != INVALID )
+ {
+ save_v(vp);
+ i = INVALID;
+ while(trepeat-->0 && i!=cur_virt)
+ {
+ i = cur_virt;
+ c = virtual[cur_virt];
+#if SHOPT_MULTIBYTE
+ if((c&~STRIP)==0)
+#endif /* SHOPT_MULTIBYTE */
+ if( isupper(c) )
+ c = tolower(c);
+ else if( islower(c) )
+ c = toupper(c);
+ replace(vp,c, 1);
+ }
+ return(GOOD);
+ }
+ else
+ return(BAD);
+
+ default:
+ return(BAD);
+ }
+ refresh(vp,CONTROL);
+ return(GOOD);
+}
+
+
+#if SHOPT_MULTIBYTE
+ static int _isalph(register int v)
+ {
+#ifdef _lib_iswalnum
+ return(iswalnum(v) || v=='_');
+#else
+ return((v&~STRIP) || isalnum(v) || v=='_');
+#endif
+ }
+
+
+ static int _isblank(register int v)
+ {
+ return((v&~STRIP)==0 && isspace(v));
+ }
+
+ static int _ismetach(register int v)
+ {
+ return((v&~STRIP)==0 && ismeta(v));
+ }
+
+#endif /* SHOPT_MULTIBYTE */
+
+/*
+ * get a character, after ^V processing
+ */
+static int getrchar(register Vi_t *vp)
+{
+ register int c;
+ if((c=ed_getchar(vp->ed,1))== usrlnext)
+ c = ed_getchar(vp->ed,2);
+ return(c);
+}
diff --git a/src/cmd/ksh93/features/cmds b/src/cmd/ksh93/features/cmds
new file mode 100644
index 0000000..c759068
--- /dev/null
+++ b/src/cmd/ksh93/features/cmds
@@ -0,0 +1,4 @@
+cmd newgrp,test,id,wc,cut,logname,universe,pfexec,tput
+pth ed fail{
+ echo '#define _pth_ed "ed" /* ed not found on standard PATH */'
+}end
diff --git a/src/cmd/ksh93/features/dynamic b/src/cmd/ksh93/features/dynamic
new file mode 100644
index 0000000..33f2d13
--- /dev/null
+++ b/src/cmd/ksh93/features/dynamic
@@ -0,0 +1,12 @@
+cat{
+ #if SHOPT_DYNAMIC
+ #include <dlldefs.h>
+ #endif
+ #if !defined(SHOPT_FS_3D) && SHOPT_DYNAMIC
+ # define SHOPT_FS_3D 1
+ #endif /* !SHOPT_FS_3D */
+ #if SHOPT_FS_3D
+ # undef mount
+ # include <fs3d.h>
+ #endif /* SHOPT_FS_3D */
+}end
diff --git a/src/cmd/ksh93/features/externs b/src/cmd/ksh93/features/externs
new file mode 100644
index 0000000..bc26759
--- /dev/null
+++ b/src/cmd/ksh93/features/externs
@@ -0,0 +1,13 @@
+set prototyped
+hdr nc,exec_attr
+mem exception.name,_exception.name math.h
+lib setreuid,setregid,nice,fork,spawnveg,fchdir
+lib pathnative,pathposix,uwin_path,uwin_unpath,fts_notify
+lib memcntl sys/mman.h
+lib getexecuser,free_execattr exec_attr.h -lsecdb
+
+reference unistd.h
+
+extern nice int (int)
+extern setreuid int (uid_t,uid_t)
+extern setregid int (gid_t,gid_t)
diff --git a/src/cmd/ksh93/features/locale b/src/cmd/ksh93/features/locale
new file mode 100644
index 0000000..4155b53
--- /dev/null
+++ b/src/cmd/ksh93/features/locale
@@ -0,0 +1,27 @@
+hdr locale,wchar,wctype
+lib locale,localeconv,wctype,iswctype,iswblank
+lib wctrans,towctrans wctype.h
+typ wctrans_t wctype.h
+cat{
+ #if _PACKAGE_ast
+ # undef _hdr_locale
+ # define _hdr_locale 1
+ #else
+ # ifdef _hdr_locale
+ # include <locale.h>
+ # ifndef LC_MESSAGES
+ # define LC_MESSAGES LC_ALL
+ # endif /* LC_MESSAGES */
+ # endif /* _hdr_locale */
+ #endif /* _PACKAGE_ast */
+ #ifdef _hdr_locale
+ # ifdef _lib_localeconv
+ static struct lconv *lp;
+ # define GETDECIMAL(x) (((lp=localeconv()) && lp->decimal_point && *lp->decimal_point) ? *lp->decimal_point : '.' )
+ # else
+ # define GETDECIMAL(x) ('.')
+ # endif /* _lib_localeconv */
+ #else
+ # define GETDECIMAL(x) ('.')
+ #endif /* _hdr_locale */
+}end
diff --git a/src/cmd/ksh93/features/math.sh b/src/cmd/ksh93/features/math.sh
new file mode 100644
index 0000000..c2b6b3b
--- /dev/null
+++ b/src/cmd/ksh93/features/math.sh
@@ -0,0 +1,305 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+: generate the ksh math builtin table
+: include math.tab
+
+# @(#)math.sh (AT&T Research) 2010-10-26
+
+command=$0
+iffeflags="-n -v"
+iffehdrs="math.h"
+iffelibs="-lm"
+table=/dev/null
+
+eval $1
+shift
+table=$1
+
+: check long double
+
+eval `iffe $iffeflags -c "$cc" - typ long.double 2>&$stderr`
+
+: check ast_standards.h
+
+eval `iffe $iffeflags -F ast_standards.h -c "$cc" - tst use_ast_standards -lm 'note{' 'math.h needs ast_standards.h' '}end' 'link{' '#include <math.h>' '#ifndef isgreater' '#define isgreater(a,b) 0' '#endif' 'int main() { return isgreater(0.0,1.0); }' '}end'`
+case $_use_ast_standards in
+1) iffeflags="$iffeflags -F ast_standards.h" ;;
+esac
+eval `iffe $iffeflags -c "$cc" - tst use_ieeefp -lm 'note{' 'ieeefp.h plays nice' '}end' 'link{' '#include <math.h>' '#include <ieeefp.h>' 'int main() { return 0; }' '}end'`
+case $_use_ieeefp in
+1) iffehdrs="$iffehdrs ieeefp.h" ;;
+esac
+
+: read the table
+
+exec < $table
+ifs=$IFS
+libs=
+names=
+nums=
+while read type args name aka
+do case $type in
+ [fix]) names="$names $name"
+ libs="$libs,$name"
+ case $_typ_long_double in
+ 1) libs="$libs,${name}l" ;;
+ esac
+ for a in $aka
+ do case $a in
+ '{'*) break
+ ;;
+ *=*) IFS='=|'
+ set $a
+ IFS=$ifs
+ case ",$libs" in
+ *,$1,*) ;;
+ *) names="$names $1"
+ libs="$libs,$1"
+ case $_typ_long_double in
+ 1) libs="$libs,${1}l" ;;
+ esac
+ ;;
+ esac
+ shift
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case ",$nums" in
+ *,$1,*) ;;
+ *) nums="$nums,$1" ;;
+ esac
+ shift
+ done
+ ;;
+ esac
+ done
+ eval TYPE_$name='$type' ARGS_$name='$args' AKA_$name='$aka'
+ ;;
+ esac
+done
+
+: check the math library
+
+eval `iffe $iffeflags -c "$cc" - lib $libs $iffehdrs $iffelibs 2>&$stderr`
+lib=
+for name in $names
+do eval x='$'_lib_${name}l y='$'_lib_${name}
+ case $x in
+ 1) lib="$lib,${name}l" ;;
+ esac
+ case $y in
+ 1) case $x in
+ '') lib="$lib,${name}" ;;
+ esac
+ ;;
+ esac
+done
+eval `iffe $iffeflags -c "$cc" - dat,npt,mac $lib $iffehdrs $iffelibs 2>&$stderr`
+eval `iffe $iffeflags -c "$cc" - num $nums $iffehdrs $iffelibs 2>&$stderr`
+
+cat <<!
+#pragma prototyped
+
+/* : : generated by $command from $table : : */
+
+typedef Sfdouble_t (*Math_f)(Sfdouble_t,...);
+
+!
+case $_use_ast_standards in
+1) echo "#include <ast_standards.h>" ;;
+esac
+echo "#include <math.h>"
+case $_hdr_ieeefp in
+1) echo "#include <ieeefp.h>" ;;
+esac
+echo
+
+: generate the intercept functions and table entries
+
+nl='
+'
+ht=' '
+tab=
+for name in $names
+do eval x='$'_lib_${name}l y='$'_lib_${name} r='$'TYPE_${name} a='$'ARGS_${name} aka='$'AKA_${name}
+ case $r in
+ i) L=int R=1 ;;
+ x) L=Sfdouble_t R=4 ;;
+ *) L=Sfdouble_t R=0 ;;
+ esac
+ F=local_$name
+ case $x:$y in
+ 1:*) f=${name}l
+ t=Sfdouble_t
+ local=
+ ;;
+ *:1) f=${name}
+ t=double
+ local=$_typ_long_double
+ ;;
+ *) body=
+ for k in $aka
+ do case $body in
+ ?*) body="$body $k"
+ continue
+ ;;
+ esac
+ case $k in
+ '{'*) body=$k
+ ;;
+ *=*) IFS='=|'
+ set $k
+ IFS=$ifs
+ f=$1
+ shift
+ v=$*
+ eval x='$'_lib_${f}l y='$'_lib_${f}
+ case $x:$y in
+ 1:*) f=${f}l
+ ;;
+ *:1) ;;
+ *) continue
+ ;;
+ esac
+ y=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ eval x='$'_num_$1
+ case $x in
+ 1) case $y in
+ ?*) y="$y || " ;;
+ esac
+ y="${y}q == $1"
+ ;;
+ esac
+ shift
+ done
+ case $y in
+ '') ;;
+ *) r=int R=1
+ echo "static $r $F(Sfdouble_t a1) { $r q = $f(a1); return $y; }"
+ tab="$tab$nl$ht\"\\0${R}${a}${name}\",$ht(Math_f)${F},"
+ break
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $body in
+ ?*) code="static $L $F("
+ sep=
+ ta=
+ tc=
+ td=
+ for p in 1 2 3 4 5 6 7 8 9
+ do case $R:$p in
+ 4:2) T=int ;;
+ *) T=Sfdouble_t ;;
+ esac
+ code="$code${sep}$T a$p"
+ ta="$ta${sep}a$p"
+ tc="$tc${sep}0"
+ td="${td}$T a$p;"
+ case $a in
+ $p) break ;;
+ esac
+ sep=","
+ done
+ _it_links_=0
+ eval `iffe $iffeflags -c "$cc" - tst it_links_ note{ $F function links }end link{ "static $L $F($ta)$td${body}int main(){return $F($tc)!=0;}" }end sfio.h $iffehdrs $iffelibs 2>&$stderr`
+ case $_it_links_ in
+ 1) code="$code)$body"
+ echo "$code"
+ tab="$tab$nl$ht\"\\0${R}${a}${name}\",$ht(Math_f)${F},"
+ ;;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+ esac
+ case $r in
+ i) r=int ;;
+ *) r=$t ;;
+ esac
+ eval n='$'_npt_$f m='$'_mac_$f d='$'_dat_$f
+ case $d:$m:$n in
+ 1:*:*|*:1:*)
+ ;;
+ *:*:1) code="extern $r $f("
+ sep=
+ for p in 1 2 3 4 5 6 7
+ do code="$code${sep}$t"
+ case $a in
+ $p) break ;;
+ esac
+ sep=","
+ done
+ code="$code);"
+ echo "$code"
+ ;;
+ esac
+ case $local:$m:$n:$d in
+ 1:*:*:*|*:1:*:*|*:*:1:)
+ args=
+ code="static $L local_$f("
+ sep=
+ for p in 1 2 3 4 5 6 7 8 9
+ do args="$args${sep}a$p"
+ case $R:$p in
+ 4:2) T=int ;;
+ *) T=Sfdouble_t ;;
+ esac
+ code="$code${sep}$T a$p"
+ case $a in
+ $p) break ;;
+ esac
+ sep=","
+ done
+ code="$code){return $f($args);}"
+ echo "$code"
+ f=local_$f
+ ;;
+ esac
+ for x in $name $aka
+ do case $x in
+ '{'*) break
+ ;;
+ *=*) continue
+ ;;
+ esac
+ tab="$tab$nl$ht\"\\0${R}${a}${x}\",$ht(Math_f)$f,"
+ done
+done
+tab="$tab$nl$ht\"\",$ht$ht(Math_f)0"
+
+cat <<!
+
+/*
+ * first byte is two-digit octal number. Last digit is number of args
+ * first digit is 0 if return value is double, 1 for integer
+ */
+const struct mathtab shtab_math[] =
+{$tab
+};
+!
diff --git a/src/cmd/ksh93/features/options b/src/cmd/ksh93/features/options
new file mode 100755
index 0000000..c3f48b6
--- /dev/null
+++ b/src/cmd/ksh93/features/options
@@ -0,0 +1,47 @@
+# SHOPT_* option probe
+
+tst cross{
+ : check for shell magic #!
+ cat > /tmp/file$$ <<!
+ #! /bin/echo
+ exit 1
+ !
+ chmod 755 /tmp/file$$
+ if /tmp/file$$ > /dev/null
+ then echo "#define SHELLMAGIC 1"
+ fi
+ rm -f /tmp/file$$
+
+ option() # name value
+ {
+ case $2 in
+ 0) echo "#ifndef SHOPT_$1"
+ echo "# define SHOPT_$1 1"
+ echo "#endif"
+ ;;
+ *) echo "#undef SHOPT_$1"
+ ;;
+ esac
+ }
+
+ ls /dev/fd/9 9<&0 >/dev/null 2>&1
+ option DEVFD $?
+ exec 9<&-
+ case `echo a | tr a '\012' | wc -l` in
+ *1*) option MULTIBYTE 0 ;;
+ esac
+ test -x /bin/pfexec -o -x /usr/bin/pfexec
+ option PFSH $?
+ /bin/test ! -l . 2> /dev/null
+ option TEST_L $?
+ test -f /etc/ksh.kshrc -o -f /etc/bash.bashrc &&
+ option SYSRC 0
+ test -f /bin/universe && univ=`/bin/universe` > /dev/null 2>&1 -a ucb = "$univ"
+ option UCB $?
+}end
+
+cat{
+ #if !_PACKAGE_ast && ( (MB_LEN_MAX-1)<=0 || !defined(_lib_mbtowc) )
+ # undef SHOPT_MULTIBYTE
+ #endif
+}end
diff --git a/src/cmd/ksh93/features/poll b/src/cmd/ksh93/features/poll
new file mode 100644
index 0000000..da21990
--- /dev/null
+++ b/src/cmd/ksh93/features/poll
@@ -0,0 +1,157 @@
+ref -lsocket -lnsl
+hdr,sys poll,socket,netinet/in
+lib select,poll,socket
+lib htons,htonl sys/types.h sys/socket.h netinet/in.h
+lib getaddrinfo sys/types.h sys/socket.h netdb.h
+typ fd_set sys/socket.h sys/select.h
+typ socklen_t unistd.h sys/socket.h = unsigned int
+tst pipe_socketpair note{ use socketpair() for peekable pipe() }end execute{
+ #include <ast.h>
+ #include <signal.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #ifndef SHUT_RD
+ #define SHUT_RD 0
+ #endif
+ #ifndef SHUT_WR
+ #define SHUT_WR 1
+ #endif
+ static void handler(sig)
+ int sig;
+ {
+ _exit(0);
+ }
+ int main()
+ {
+ int n;
+ int pfd[2];
+ int sfd[2];
+ char buf[256];
+ pid_t pid;
+ static char msg[] = "hello world\n";
+ close(0);
+ if (pipe(pfd) < 0 ||
+ socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0 ||
+ shutdown(sfd[1], SHUT_RD) < 0 ||
+ shutdown(sfd[0], SHUT_WR) < 0)
+ return(1);
+ if ((pid = fork()) < 0)
+ return(1);
+ if (pid)
+ {
+ close(pfd[1]);
+ close(sfd[1]);
+ wait(&n);
+ if (sfpkrd(pfd[0], buf, sizeof(buf), '\n', -1, 1) >= 0 ||
+ sfpkrd(sfd[0], buf, sizeof(buf), '\n', -1, 1) < 0)
+ return(1);
+ }
+ else
+ {
+ close(pfd[0]);
+ close(sfd[0]);
+ write(pfd[1], msg, sizeof(msg) - 1);
+ write(sfd[1], msg, sizeof(msg) - 1);
+ return(0);
+ }
+ close(pfd[0]);
+ close(sfd[0]);
+ signal(SIGPIPE, handler);
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0 ||
+ shutdown(sfd[1], SHUT_RD) < 0 ||
+ shutdown(sfd[0], SHUT_WR) < 0)
+ return(1);
+ close(sfd[0]);
+ write(sfd[1], msg, sizeof(msg) - 1);
+ return(1);
+ }
+}end
+tst socketpair_devfd note{ /dev/fd/N handles socketpair() }end execute{
+ #include <ast.h>
+ #include <fs3d.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ int main()
+ {
+ int devfd;
+ int n;
+ int sfd[2];
+ fs3d(FS3D_OFF);
+ close(0);
+ open("/dev/null", O_RDONLY);
+ if ((n = open("/dev/fd/0", O_RDONLY)) < 0)
+ return(1);
+ close(n);
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0 ||
+ shutdown(sfd[0], 1) < 0 ||
+ shutdown(sfd[1], 0) < 0)
+ return(1);
+ close(0);
+ dup(sfd[0]);
+ close(sfd[0]);
+ if ((n = open("/dev/fd/0", O_RDONLY)) < 0)
+ return(1);
+ return(0);
+ }
+}end
+tst socketpair_shutdown_mode note{ fchmod() after socketpair() shutdown() }end execute{
+ #include <ast.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/socket.h>
+ int main()
+ {
+ int sfd[2];
+ struct stat st0;
+ struct stat st1;
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0 ||
+ shutdown(sfd[0], 1) < 0 ||
+ shutdown(sfd[1], 0) < 0)
+ return(1);
+ if (fstat(sfd[0], &st0) < 0 || fstat(sfd[1], &st1) < 0)
+ return(1);
+ if ((st0.st_mode & (S_IRUSR|S_IWUSR)) == S_IRUSR &&
+ (st1.st_mode & (S_IRUSR|S_IWUSR)) == S_IWUSR)
+ return(1);
+ if (fchmod(sfd[0], S_IRUSR) < 0 ||
+ fstat(sfd[0], &st0) < 0 ||
+ (st0.st_mode & (S_IRUSR|S_IWUSR)) != S_IRUSR)
+ return(1);
+ if (fchmod(sfd[1], S_IWUSR) < 0 ||
+ fstat(sfd[1], &st1) < 0 ||
+ (st1.st_mode & (S_IRUSR|S_IWUSR)) != S_IWUSR)
+ return(1);
+ return(0);
+ }
+}end
+cat{
+ #pragma prototyped
+ #ifdef _lib_poll
+ # define poll _SYS_poll
+ #else
+ # undef _hdr_poll
+ # undef _sys_poll
+ #endif /* _lib_poll */
+ #ifdef _hdr_poll
+ # include <poll.h>
+ #else
+ # ifdef _sys_poll
+ # include <sys/poll.h>
+ # endif /* _sys_poll */
+ #endif /* _hdr_poll */
+ #ifdef _lib_poll
+ # undef poll
+ extern int poll(struct pollfd*,unsigned long,int);
+ #endif /* _lib_poll */
+ #ifdef _lib_select
+ # ifndef FD_ZERO
+ # define FD_ZERO(x) (*(x)=0)
+ # endif /* FD_ZERO */
+ # ifndef FD_SET
+ # define FD_SET(n,x) (*(x)|=(1L<<(n)))
+ # endif /* FD_SET */
+ # ifndef _typ_fd_set
+ typedef long fd_set;
+ # endif /*_typ_fd_set */
+ #endif /* _lib_select */
+}end
diff --git a/src/cmd/ksh93/features/rlimits b/src/cmd/ksh93/features/rlimits
new file mode 100644
index 0000000..ad7d2e1
--- /dev/null
+++ b/src/cmd/ksh93/features/rlimits
@@ -0,0 +1,3 @@
+hdr,sys resource,vlimit sys/time.h
+lib getrlimit,ulimit,vlimit
+typ rlim_t sys/types.h sys/time.h sys/resource.h
diff --git a/src/cmd/ksh93/features/setjmp b/src/cmd/ksh93/features/setjmp
new file mode 100644
index 0000000..a3504ee
--- /dev/null
+++ b/src/cmd/ksh93/features/setjmp
@@ -0,0 +1,18 @@
+lib sigsetjmp,_setjmp,_longjmp
+typ sigjmp_buf setjmp.h
+cat{
+ #undef sigsetjmp
+ #undef siglongjmp
+ #undef sigjmp_buf
+ #define sigjmp_buf jmp_buf
+ #ifdef _lib__setjmp
+ # define sigsetjmp(a,b) _setjmp(a)
+ #else
+ # define sigsetjmp(a,b) setjmp(a)
+ #endif /* _lib__setjmp */
+ #ifdef _lib__longjmp
+ # define siglongjmp(a,b) _longjmp(a,b)
+ #else
+ # define siglongjmp(a,b) longjmp(a,b)
+ #endif /* _lib__longjmp */
+}end
diff --git a/src/cmd/ksh93/features/sigfeatures b/src/cmd/ksh93/features/sigfeatures
new file mode 100644
index 0000000..58beaf8
--- /dev/null
+++ b/src/cmd/ksh93/features/sigfeatures
@@ -0,0 +1,49 @@
+lib sigblock,sigrelse,sigsetmask,sigprocmask,sigvec
+typ sigset_t ast.h signal.h
+mem sigvec.sv_mask signal.h
+cat{
+ #ifndef _mem_sigvec_sv_mask
+ # undef _lib_sigvec
+ #endif
+ #ifdef _lib_sigprocmask
+ # define sh_sigaction(s,action) do { sigset_t ss;\
+ sigemptyset(&ss); \
+ if(s) sigaddset(&ss,(s)); \
+ sigprocmask(action,&ss,0); \
+ }while(0)
+ # define sigrelease(s) sh_sigaction(s,SIG_UNBLOCK)
+ # define sigblock(s) sh_sigaction(s,SIG_BLOCK)
+ # define sig_begin() sh_sigaction(0,SIG_SETMASK)
+ #else
+ # ifndef _lib_sigblock
+ # define sigblock(s)
+ # endif
+ # ifdef _lib_sigsetmask
+ # define sigrelease(s) sigsetmask(0)
+ # define sig_begin() sigsetmask(0)
+ # else
+ # ifdef _lib_sigrelse
+ # define sigrelease sigrelse
+ # define sig_begin()
+ # else
+ # define sig_begin() (0)
+ # define sigrelease(s) (0)
+ # endif /* _lib_sigrelse */
+ # endif /* _lib_sigsetmask */
+ #endif /* _lib_sigprocmask */
+}end
+tst output{
+ #include <signal.h>
+ int main()
+ {
+ #ifdef SIGRTMIN
+ printf("#undef _SIGRTMIN\n");
+ printf("#define _SIGRTMIN %d\n", SIGRTMIN);
+ #endif
+ #ifdef SIGRTMAX
+ printf("#undef _SIGRTMAX\n");
+ printf("#define _SIGRTMAX %d\n", SIGRTMAX);
+ #endif
+ return 0;
+ }
+}end
diff --git a/src/cmd/ksh93/features/time b/src/cmd/ksh93/features/time
new file mode 100644
index 0000000..f8d2129
--- /dev/null
+++ b/src/cmd/ksh93/features/time
@@ -0,0 +1,35 @@
+hdr utime
+lib gettimeofday,setitimer
+mem timeval.tv_usec sys/time.h
+tst lib_2_timeofday note{ 2 arg gettimeofday() }end link{
+ #include <sys/types.h>
+ #include <sys/time.h>
+ int main()
+ {
+ struct timeval tv;
+ struct timezone tz;
+ return gettimeofday(&tv, &tz);
+ }
+}end
+tst lib_1_timeofday note{ 1 arg gettimeofday() }end link{
+ #include <sys/types.h>
+ #include <sys/time.h>
+ int main()
+ {
+ struct timeval tv;
+ return gettimeofday(&tv);
+ }
+}end
+cat{
+ #undef _def_time
+ #include <times.h>
+ #define _def_time 1
+ #undef timeofday
+ #if _lib_2_timeofday
+ #define timeofday(p) gettimeofday(p,(struct timezone*)0)
+ #else
+ #if _lib_1_timeofday
+ #define timeofday(p) gettimeofday(p)
+ #endif
+ #endif
+}end
diff --git a/src/cmd/ksh93/features/ttys b/src/cmd/ksh93/features/ttys
new file mode 100644
index 0000000..693dbd1
--- /dev/null
+++ b/src/cmd/ksh93/features/ttys
@@ -0,0 +1,3 @@
+hdr termios,termio,sgtty
+sys termios,termio,ioctl,bsdtty,nttyio,filio
+lib tcgetattr,tcgetpgrp termios.h
diff --git a/src/cmd/ksh93/fun/dirs b/src/cmd/ksh93/fun/dirs
new file mode 100755
index 0000000..0329970
--- /dev/null
+++ b/src/cmd/ksh93/fun/dirs
@@ -0,0 +1,108 @@
+#
+# DIRECTORY MANIPULATION FUNCTIONS, REPLACES CD
+#
+# Uses global parameters _push_max _push_top _push_stack
+integer _push_max=${CDSTACK-32} _push_top=${CDSTACK-32}
+unalias cd
+alias cd=_cd
+# Display directory stack -- $HOME displayed as ~
+function dirs
+{
+ typeset dir="${PWD#$HOME/}"
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ PS3=
+ select i in "$dir" "${_push_stack[@]}"
+ do :
+ done < /dev/null
+}
+
+# Change directory and put directory on front of stack
+function _cd
+{
+ typeset dir=
+ integer n=0 type=4
+ case $1 in
+ -|-1|2) # \cd -
+ n=_push_top type=1
+ ;;
+ -[1-9]*([0-9])) # \cd -n
+ n=_push_top+${1#-}-1 type=2
+ ;;
+ 1) # keep present directory
+ print -r - "$PWD"
+ return
+ ;;
+ [1-9]*([0-9])) # \cd n
+ n=_push_top+${1}-2 type=2
+ ;;
+ *) if ((_push_top <= 0))
+ then type=3 n=_push_max
+ fi
+ esac
+ if ((type<3))
+ then if ((n >= _push_max+1))
+ then print -u2 cd: Directory stack not that deep.
+ return 1
+ else dir=${_push_stack[n]}
+ fi
+ fi
+ case $dir in
+ \~*) dir=$HOME${dir#\~}
+ esac
+ \cd "${dir:-$@}" >| /dev/null || return 1
+ dir=${OLDPWD#$HOME/}
+ case $TERM in
+ 630)
+ print "\033[?${#PWD};2v$PWD\c"
+ ;;
+ esac
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ case $type in
+ 1) # swap first two elements
+ _push_stack[_push_top]=$dir
+ ;;
+ 2|3) # put $dir on top and shift down by one until top
+ integer i=_push_top
+ for dir in "$dir" "${_push_stack[@]}"
+ do ((i > n)) && break
+ _push_stack[i]=$dir
+ i=i+1
+ done
+ ;;
+ 4) # push name
+ _push_stack[_push_top=_push_top-1]=$dir
+ ;;
+ esac
+ print -r - "$PWD"
+}
+
+# Menu driven change directory command
+function mcd
+{
+ typeset dir="${PWD#$HOME/}"
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ PS3='Select by number or enter a name: '
+ select dir in "$dir" "${_push_stack[@]}"
+ do if _cd $REPLY
+ then return
+ fi
+ done
+}
diff --git a/src/cmd/ksh93/fun/popd b/src/cmd/ksh93/fun/popd
new file mode 100755
index 0000000..1bc9346
--- /dev/null
+++ b/src/cmd/ksh93/fun/popd
@@ -0,0 +1,111 @@
+#
+# DIRECTORY MANIPULATION FUNCTIONS PUSHD, POPD AND DIRS
+#
+# Uses global parameters _push_max _push_top _push_stack
+integer _push_max=100 _push_top=100
+# Display directory stack -- $HOME displayed as ~
+function dirs
+{
+ typeset dir="${PWD#$HOME/}"
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ print -r - "$dir ${_push_stack[@]}"
+}
+
+# Change directory and put directory on front of stack
+function pushd
+{
+ typeset dir= type=0
+ integer i
+ case $1 in
+ "") # pushd
+ if ((_push_top >= _push_max))
+ then print pushd: No other directory.
+ return 1
+ fi
+ type=1 dir=${_push_stack[_push_top]}
+ ;;
+ +[1-9]|+[1-9][0-9]) # pushd +n
+ integer i=_push_top$1-1
+ if ((i >= _push_max))
+ then print pushd: Directory stack not that deep.
+ return 1
+ fi
+ type=2 dir=${_push_stack[i]}
+ ;;
+ *) if ((_push_top <= 0))
+ then print pushd: Directory stack overflow.
+ return 1
+ fi
+ esac
+ case $dir in
+ \~*) dir=$HOME${dir#\~}
+ esac
+ cd "${dir:-$1}" > /dev/null || return 1
+ dir=${OLDPWD#$HOME/}
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ case $type in
+ 0) # pushd name
+ _push_stack[_push_top=_push_top-1]=$dir
+ ;;
+ 1) # pushd
+ _push_stack[_push_top]=$dir
+ ;;
+ 2) # push +n
+ type=${1#+} i=_push_top-1
+ set -- "${_push_stack[@]}" "$dir" "${_push_stack[@]}"
+ shift $type
+ for dir
+ do (((i=i+1) < _push_max)) || break
+ _push_stack[i]=$dir
+ done
+ esac
+ dirs
+}
+
+# Pops the top directory
+function popd
+{
+ typeset dir
+ if ((_push_top >= _push_max))
+ then print popd: Nothing to pop.
+ return 1
+ fi
+ case $1 in
+ "")
+ dir=${_push_stack[_push_top]}
+ case $dir in
+ \~*) dir=$HOME${dir#\~}
+ esac
+ cd "$dir" || return 1
+ ;;
+ +[1-9]|+[1-9][0-9])
+ typeset savedir
+ integer i=_push_top$1-1
+ if ((i >= _push_max))
+ then print pushd: Directory stack not that deep.
+ return 1
+ fi
+ while ((i > _push_top))
+ do _push_stack[i]=${_push_stack[i-1]}
+ i=i-1
+ done
+ ;;
+ *) print pushd: Bad directory.
+ return 1
+ esac
+ unset '_push_stack[_push_top]'
+ _push_top=_push_top+1
+ dirs
+}
diff --git a/src/cmd/ksh93/fun/pushd b/src/cmd/ksh93/fun/pushd
new file mode 100755
index 0000000..1bc9346
--- /dev/null
+++ b/src/cmd/ksh93/fun/pushd
@@ -0,0 +1,111 @@
+#
+# DIRECTORY MANIPULATION FUNCTIONS PUSHD, POPD AND DIRS
+#
+# Uses global parameters _push_max _push_top _push_stack
+integer _push_max=100 _push_top=100
+# Display directory stack -- $HOME displayed as ~
+function dirs
+{
+ typeset dir="${PWD#$HOME/}"
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ print -r - "$dir ${_push_stack[@]}"
+}
+
+# Change directory and put directory on front of stack
+function pushd
+{
+ typeset dir= type=0
+ integer i
+ case $1 in
+ "") # pushd
+ if ((_push_top >= _push_max))
+ then print pushd: No other directory.
+ return 1
+ fi
+ type=1 dir=${_push_stack[_push_top]}
+ ;;
+ +[1-9]|+[1-9][0-9]) # pushd +n
+ integer i=_push_top$1-1
+ if ((i >= _push_max))
+ then print pushd: Directory stack not that deep.
+ return 1
+ fi
+ type=2 dir=${_push_stack[i]}
+ ;;
+ *) if ((_push_top <= 0))
+ then print pushd: Directory stack overflow.
+ return 1
+ fi
+ esac
+ case $dir in
+ \~*) dir=$HOME${dir#\~}
+ esac
+ cd "${dir:-$1}" > /dev/null || return 1
+ dir=${OLDPWD#$HOME/}
+ case $dir in
+ $HOME)
+ dir=\~
+ ;;
+ /*) ;;
+ *) dir=\~/$dir
+ esac
+ case $type in
+ 0) # pushd name
+ _push_stack[_push_top=_push_top-1]=$dir
+ ;;
+ 1) # pushd
+ _push_stack[_push_top]=$dir
+ ;;
+ 2) # push +n
+ type=${1#+} i=_push_top-1
+ set -- "${_push_stack[@]}" "$dir" "${_push_stack[@]}"
+ shift $type
+ for dir
+ do (((i=i+1) < _push_max)) || break
+ _push_stack[i]=$dir
+ done
+ esac
+ dirs
+}
+
+# Pops the top directory
+function popd
+{
+ typeset dir
+ if ((_push_top >= _push_max))
+ then print popd: Nothing to pop.
+ return 1
+ fi
+ case $1 in
+ "")
+ dir=${_push_stack[_push_top]}
+ case $dir in
+ \~*) dir=$HOME${dir#\~}
+ esac
+ cd "$dir" || return 1
+ ;;
+ +[1-9]|+[1-9][0-9])
+ typeset savedir
+ integer i=_push_top$1-1
+ if ((i >= _push_max))
+ then print pushd: Directory stack not that deep.
+ return 1
+ fi
+ while ((i > _push_top))
+ do _push_stack[i]=${_push_stack[i-1]}
+ i=i-1
+ done
+ ;;
+ *) print pushd: Bad directory.
+ return 1
+ esac
+ unset '_push_stack[_push_top]'
+ _push_top=_push_top+1
+ dirs
+}
diff --git a/src/cmd/ksh93/include/argnod.h b/src/cmd/ksh93/include/argnod.h
new file mode 100644
index 0000000..2ed7302
--- /dev/null
+++ b/src/cmd/ksh93/include/argnod.h
@@ -0,0 +1,145 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef ARG_RAW
+/*
+ * struct to hold a word argument
+ * Written by David Korn
+ *
+ */
+
+#include <stak.h>
+
+struct ionod
+{
+ unsigned iofile;
+ char *ioname;
+ struct ionod *ionxt;
+ struct ionod *iolst;
+ char *iodelim;
+ off_t iooffset;
+ long iosize;
+ char *iovname;
+};
+
+struct comnod
+{
+ int comtyp;
+ struct ionod *comio;
+ struct argnod *comarg;
+ struct argnod *comset;
+ void *comnamp;
+ void *comnamq;
+ void *comstate;
+ int comline;
+};
+
+#define COMBITS 4
+#define COMMSK ((1<<COMBITS)-1)
+#define COMSCAN (01<<COMBITS)
+#define COMFIXED (02<<COMBITS)
+
+struct slnod /* struct for link list of stacks */
+{
+ struct slnod *slnext;
+ struct slnod *slchild;
+ Stak_t *slptr;
+ /* slpad aligns struct functnod = struct slnod + 1 on some architectures */
+ struct slnod *slpad;
+};
+
+/*
+ * This struct is use to hold $* lists and arrays
+ */
+
+struct dolnod
+{
+ int dolrefcnt; /* reference count */
+ int dolmax; /* size of dolval array */
+ int dolnum; /* number of elements */
+ int dolbot; /* current first element */
+ struct dolnod *dolnxt; /* used when list are chained */
+ char *dolval[1]; /* array of value pointers */
+};
+
+/*
+ * This struct is used to hold word arguments of variable size during
+ * parsing and during expansion. The flags indicate what processing
+ * is required on the argument.
+ */
+
+struct argnod
+{
+ union
+ {
+ struct argnod *ap;
+ char *cp;
+ } argnxt;
+ union
+ {
+ struct argnod *ap;
+ char *cp;
+ int len;
+ } argchn;
+ unsigned char argflag;
+ char argval[4];
+};
+
+
+
+/* The following should evaluate to the offset of argval in argnod */
+#define ARGVAL offsetof(struct argnod,argval[0])
+#define sh_argstr(ap) ((ap)->argflag&ARG_RAW?sh_fmtq((ap)->argval):(ap)->argval)
+#define ARG_SPARE 1
+
+
+/* legal argument flags */
+#define ARG_RAW 0x1 /* string needs no processing */
+#define ARG_MAKE 0x2 /* bit set during argument expansion */
+#define ARG_COMSUB 0x2 /* command sub */
+#define ARG_MAC 0x4 /* string needs macro expansion */
+#define ARG_EXP 0x8 /* string needs file expansion */
+#define ARG_ASSIGN 0x10 /* argument is an assignment */
+#define ARG_QUOTED 0x20 /* word contained quote characters */
+#define ARG_MESSAGE 0x40 /* contains international string */
+#define ARG_APPEND 0x80 /* for += assignment */
+/* The following can be passed as options to sh_macexpand() */
+#define ARG_ARITH 0x100 /* arithmetic expansion */
+#define ARG_OPTIMIZE 0x200 /* try to optimize */
+#define ARG_NOGLOB 0x400 /* no file name expansion */
+#define ARG_LET 0x800 /* processing let command arguments */
+#define ARG_ARRAYOK 0x1000 /* $x[sub] ==> ${x[sub]} */
+
+extern struct dolnod *sh_argcreate(char*[]);
+extern char *sh_argdolminus(void*);
+extern int sh_argopts(int,char*[],void*);
+
+
+extern const char e_heading[];
+extern const char e_off[];
+extern const char e_on[];
+extern const char e_sptbnl[];
+extern const char e_subst[];
+extern const char e_option[];
+extern const char e_exec[];
+extern const char e_devfdNN[];
+extern const char e_devfdstd[];
+
+#endif /* ARG_RAW */
diff --git a/src/cmd/ksh93/include/builtins.h b/src/cmd/ksh93/include/builtins.h
new file mode 100644
index 0000000..b9b4233
--- /dev/null
+++ b/src/cmd/ksh93/include/builtins.h
@@ -0,0 +1,202 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef SYSDECLARE
+
+#include <option.h>
+#include "FEATURE/options"
+#include "FEATURE/dynamic"
+#include "shtable.h"
+
+#define SYSLOGIN (shgd->bltin_cmds)
+#define SYSEXEC (shgd->bltin_cmds+1)
+#define SYSSET (shgd->bltin_cmds+2)
+#define SYSTRUE (shgd->bltin_cmds+4)
+#define SYSCOMMAND (shgd->bltin_cmds+5)
+#define SYSCD (shgd->bltin_cmds+6)
+#define SYSBREAK (shgd->bltin_cmds+7)
+#define SYSCONT (shgd->bltin_cmds+8)
+#define SYSTYPESET (shgd->bltin_cmds+9)
+#define SYSTEST (shgd->bltin_cmds+10)
+#define SYSBRACKET (shgd->bltin_cmds+11)
+#define SYSLET (shgd->bltin_cmds+12)
+#define SYSEXPORT (shgd->bltin_cmds+13)
+#define SYSDOT (shgd->bltin_cmds+14)
+#define SYSRETURN (shgd->bltin_cmds+15)
+#if SHOPT_BASH
+# define SYSLOCAL (shgd->bltin_cmds+16)
+#else
+# define SYSLOCAL 0
+#endif
+
+/* entry point for shell special builtins */
+
+#if _BLD_shell && defined(__EXPORT__)
+# define extern __EXPORT__
+#endif
+
+extern int b_alias(int, char*[],Shbltin_t*);
+extern int b_break(int, char*[],Shbltin_t*);
+extern int b_dot_cmd(int, char*[],Shbltin_t*);
+extern int b_enum(int, char*[],Shbltin_t*);
+extern int b_exec(int, char*[],Shbltin_t*);
+extern int b_eval(int, char*[],Shbltin_t*);
+extern int b_return(int, char*[],Shbltin_t*);
+extern int B_login(int, char*[],Shbltin_t*);
+extern int b_true(int, char*[],Shbltin_t*);
+extern int b_false(int, char*[],Shbltin_t*);
+extern int b_readonly(int, char*[],Shbltin_t*);
+extern int b_set(int, char*[],Shbltin_t*);
+extern int b_shift(int, char*[],Shbltin_t*);
+extern int b_trap(int, char*[],Shbltin_t*);
+extern int b_typeset(int, char*[],Shbltin_t*);
+extern int b_unset(int, char*[],Shbltin_t*);
+extern int b_unalias(int, char*[],Shbltin_t*);
+
+/* The following are for job control */
+#if defined(SIGCLD) || defined(SIGCHLD)
+ extern int b_jobs(int, char*[],Shbltin_t*);
+ extern int b_kill(int, char*[],Shbltin_t*);
+# ifdef SIGTSTP
+ extern int b_bg(int, char*[],Shbltin_t*);
+# endif /* SIGTSTP */
+#endif
+
+/* The following utilities are built-in because of side-effects */
+extern int b_builtin(int, char*[],Shbltin_t*);
+extern int b_cd(int, char*[],Shbltin_t*);
+extern int b_command(int, char*[],Shbltin_t*);
+extern int b_getopts(int, char*[],Shbltin_t*);
+extern int b_hist(int, char*[],Shbltin_t*);
+extern int b_let(int, char*[],Shbltin_t*);
+extern int b_read(int, char*[],Shbltin_t*);
+extern int b_ulimit(int, char*[],Shbltin_t*);
+extern int b_umask(int, char*[],Shbltin_t*);
+#ifdef _cmd_universe
+ extern int b_universe(int, char*[],Shbltin_t*);
+#endif /* _cmd_universe */
+#if SHOPT_FS_3D
+ extern int b_vpath(int, char*[],Shbltin_t*);
+#endif /* SHOPT_FS_3D */
+extern int b_wait(int, char*[],Shbltin_t*);
+extern int b_whence(int, char*[],Shbltin_t*);
+
+extern int b_alarm(int, char*[],Shbltin_t*);
+extern int b_print(int, char*[],Shbltin_t*);
+extern int b_printf(int, char*[],Shbltin_t*);
+extern int b_pwd(int, char*[],Shbltin_t*);
+extern int b_sleep(int, char*[],Shbltin_t*);
+extern int b_test(int, char*[],Shbltin_t*);
+#if !SHOPT_ECHOPRINT
+ extern int B_echo(int, char*[],Shbltin_t*);
+#endif /* SHOPT_ECHOPRINT */
+
+#undef extern
+
+extern const char e_alrm1[];
+extern const char e_alrm2[];
+extern const char e_badfun[];
+extern const char e_baddisc[];
+extern const char e_nofork[];
+extern const char e_nosignal[];
+extern const char e_nolabels[];
+extern const char e_notimp[];
+extern const char e_nosupport[];
+extern const char e_badbase[];
+extern const char e_overlimit[];
+
+extern const char e_eneedsarg[];
+extern const char e_oneoperand[];
+extern const char e_toodeep[];
+extern const char e_badname[];
+extern const char e_badsyntax[];
+#ifdef _cmd_universe
+ extern const char e_nouniverse[];
+#endif /* _cmd_universe */
+extern const char e_histopen[];
+extern const char e_condition[];
+extern const char e_badrange[];
+extern const char e_trap[];
+extern const char e_direct[];
+extern const char e_defedit[];
+extern const char e_cneedsarg[];
+extern const char e_defined[];
+#if SHOPT_FS_3D
+ extern const char e_cantset[];
+ extern const char e_cantget[];
+ extern const char e_mapping[];
+ extern const char e_versions[];
+#endif /* SHOPT_FS_3D */
+
+/* for option parsing */
+extern const char sh_set[];
+extern const char sh_optalarm[];
+extern const char sh_optalias[];
+extern const char sh_optbreak[];
+extern const char sh_optbuiltin[];
+extern const char sh_optcd[];
+extern const char sh_optcommand[];
+extern const char sh_optcont[];
+extern const char sh_optdot[];
+#ifndef ECHOPRINT
+ extern const char sh_optecho[];
+#endif /* !ECHOPRINT */
+extern const char sh_opteval[];
+extern const char sh_optexec[];
+extern const char sh_optexit[];
+extern const char sh_optexport[];
+extern const char sh_optgetopts[];
+extern const char sh_optbg[];
+extern const char sh_optdisown[];
+extern const char sh_optfg[];
+extern const char sh_opthist[];
+extern const char sh_optjobs[];
+extern const char sh_optkill[];
+extern const char sh_optksh[];
+extern const char sh_optlet[];
+extern const char sh_optprint[];
+extern const char sh_optprintf[];
+extern const char sh_optpwd[];
+extern const char sh_optread[];
+extern const char sh_optreadonly[];
+extern const char sh_optreturn[];
+extern const char sh_optset[];
+extern const char sh_optshift[];
+extern const char sh_optsleep[];
+extern const char sh_opttrap[];
+extern const char sh_opttypeset[];
+extern const char sh_optulimit[];
+extern const char sh_optumask[];
+extern const char sh_optunalias[];
+extern const char sh_optwait[];
+#ifdef _cmd_universe
+ extern const char sh_optuniverse[];
+#endif /* _cmd_universe */
+extern const char sh_optunset[];
+#if SHOPT_FS_3D
+ extern const char sh_optvpath[];
+ extern const char sh_optvmap[];
+#endif /* SHOPT_FS_3D */
+extern const char sh_optwhence[];
+#endif /* SYSDECLARE */
+
+extern const char e_dict[];
+
diff --git a/src/cmd/ksh93/include/defs.h b/src/cmd/ksh93/include/defs.h
new file mode 100644
index 0000000..dd80552
--- /dev/null
+++ b/src/cmd/ksh93/include/defs.h
@@ -0,0 +1,509 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * Shell interface private definitions
+ *
+ */
+#ifndef defs_h_defined
+#define defs_h_defined
+
+#include <ast.h>
+#include <sfio.h>
+#include <error.h>
+#include "FEATURE/externs"
+#include "FEATURE/options"
+#include <cdt.h>
+#include <history.h>
+#include "fault.h"
+#include "argnod.h"
+#include "name.h"
+#include <ctype.h>
+
+#ifndef pointerof
+#define pointerof(x) ((void*)((char*)0+(x)))
+#endif
+
+#define Empty ((char*)(e_sptbnl+3))
+
+#define env_change() (++ast.env_serial)
+#if SHOPT_ENV
+# include <env.h>
+#else
+# define Env_t void
+# define sh_envput(e,p) env_change()
+# define env_delete(e,p) env_change()
+#endif
+
+extern char* sh_getenv(const char*);
+extern char* sh_setenviron(const char*);
+
+/*
+ * note that the first few fields have to be the same as for
+ * Shscoped_t in <shell.h>
+ */
+
+
+struct sh_scoped
+{
+ struct sh_scoped *prevst; /* pointer to previous state */
+ int dolc;
+ char **dolv;
+ char *cmdname;
+ char *filename;
+ char *funname;
+ int lineno;
+ Dt_t *save_tree; /* var_tree for calling function */
+ struct sh_scoped *self; /* pointer to copy of this scope*/
+ Dt_t *var_local; /* local level variables for name() */
+ struct slnod *staklist; /* link list of function stacks */
+ int states;
+ int breakcnt;
+ int execbrk;
+ int loopcnt;
+ int firstline;
+ int32_t optindex;
+ int32_t optnum;
+ int32_t tmout; /* value for TMOUT */
+ short optchar;
+ short opterror;
+ int ioset;
+ unsigned short trapmax;
+ char *trap[SH_DEBUGTRAP+1];
+ char **trapcom;
+ char **otrapcom;
+ void *timetrap;
+ struct Ufunction *real_fun; /* current 'function name' function */
+};
+
+struct limits
+{
+ long arg_max; /* max arg+env exec() size */
+ int open_max; /* maximum number of file descriptors */
+ int clk_tck; /* number of ticks per second */
+ int child_max; /* maxumum number of children */
+ int ngroups_max; /* maximum number of process groups */
+ unsigned char posix_version; /* posix version number */
+ unsigned char posix_jobcontrol;/* non-zero for job control systems */
+ unsigned char fs3d; /* non-zero for 3-d file system */
+};
+
+#ifndef SH_wait_f_defined
+ typedef int (*Shwait_f)(int, long, int);
+# define SH_wait_f_defined
+#endif
+
+
+struct shared
+{
+ struct limits lim;
+ uid_t userid;
+ uid_t euserid;
+ gid_t groupid;
+ gid_t egroupid;
+ pid_t pid;
+ int32_t ppid;
+ unsigned char sigruntime[2];
+ Namval_t *bltin_nodes;
+ Namval_t *bltin_cmds;
+ History_t *hist_ptr;
+ char *shpath;
+ char *user;
+ char **sigmsg;
+ char *rcfile;
+ char **login_files;
+ void *ed_context;
+ void *init_context;
+ void *job_context;
+ int *stats;
+ int bltin_nnodes; /* number of bltins nodes */
+ int sigmax;
+ int nforks;
+ Shwait_f waitevent;
+};
+
+#define _SH_PRIVATE \
+ struct shared *gd; /* global data */ \
+ struct sh_scoped st; /* scoped information */ \
+ Stk_t *stk; /* stack poiter */ \
+ Sfio_t *heredocs; /* current here-doc temp file */ \
+ Sfio_t *funlog; /* for logging function definitions */ \
+ int **fdptrs; /* pointer to file numbers */ \
+ int savexit; \
+ char *lastarg; \
+ char *lastpath; /* last alsolute path found */ \
+ int path_err; /* last error on path search */ \
+ Dt_t *track_tree; /* for tracked aliases*/ \
+ Dt_t *var_base; /* global level variables */ \
+ Namval_t *namespace; /* current active namespace*/ \
+ Namval_t *last_table; /* last table used in last nv_open */ \
+ Namval_t *prev_table; /* previous table used in nv_open */ \
+ Sfio_t *outpool; /* ouput stream pool */ \
+ long timeout; /* read timeout */ \
+ short curenv; /* current subshell number */ \
+ short jobenv; /* subshell number for jobs */ \
+ int infd; /* input file descriptor */ \
+ short nextprompt; /* next prompt is PS<nextprompt> */ \
+ short poolfiles; \
+ Namval_t *posix_fun; /* points to last name() function */ \
+ char *outbuff; /* pointer to output buffer */ \
+ char *errbuff; /* pointer to stderr buffer */ \
+ char *prompt; /* pointer to prompt string */ \
+ char *shname; /* shell name */ \
+ char *comdiv; /* points to sh -c argument */ \
+ char *prefix; /* prefix for compound assignment */ \
+ sigjmp_buf *jmplist; /* longjmp return stack */ \
+ char *fifo; /* fifo name for process sub */ \
+ int oldexit; \
+ pid_t bckpid; /* background process id */ \
+ pid_t cpid; \
+ pid_t spid; /* subshell process id */ \
+ pid_t pipepid; \
+ pid_t outpipepid; \
+ int topfd; \
+ int savesig; \
+ unsigned char *sigflag; /* pointer to signal states */ \
+ char openmatch; \
+ char intrap; \
+ char login_sh; \
+ char lastbase; \
+ char forked; \
+ char binscript; \
+ char deftype; \
+ char funload; \
+ char used_pos; /* used postional parameter */\
+ char universe; \
+ char winch; \
+ char inarith; /* set when in ((...)) */ \
+ char indebug; /* set when in debug trap */ \
+ unsigned char ignsig; /* ignored signal in subshell */ \
+ unsigned char lastsig; /* last signal received */ \
+ char pathinit; /* pathinit called from subshell */ \
+ char comsub; /* set when in $() comsub */ \
+ char subshare; /* set when in ${..} comsub */ \
+ char toomany; /* set when out of fd's */ \
+ char instance; /* in set_instance */ \
+ char decomma; /* decimal_point=',' */ \
+ char redir0; /* redirect of 0 */ \
+ char *readscript; /* set before reading a script */ \
+ int subdup; /* bitmask for dups of 1 */ \
+ int *inpipe; /* input pipe pointer */ \
+ int *outpipe; /* output pipe pointer */ \
+ int cpipe[3]; \
+ int coutpipe; \
+ int inuse_bits; \
+ struct argnod *envlist; \
+ struct dolnod *arglist; \
+ int fn_depth; \
+ int fn_reset; \
+ int dot_depth; \
+ int hist_depth; \
+ int xargmin; \
+ int xargmax; \
+ int xargexit; \
+ int nenv; \
+ mode_t mask; \
+ Env_t *env; \
+ void *init_context; \
+ void *mac_context; \
+ void *lex_context; \
+ void *arg_context; \
+ void *job_context; \
+ void *pathlist; \
+ void *defpathlist; \
+ void *cdpathlist; \
+ char **argaddr; \
+ void *optlist; \
+ struct sh_scoped global; \
+ struct checkpt checkbase; \
+ Shinit_f userinit; \
+ Shbltin_f bltinfun; \
+ Shbltin_t bltindata; \
+ char *cur_line; \
+ int offsets[10]; \
+ Sfio_t **sftable; \
+ unsigned char *fdstatus; \
+ const char *pwd; \
+ void *jmpbuffer; \
+ void *mktype; \
+ Sfio_t *strbuf; \
+ Sfio_t *strbuf2; \
+ Dt_t *first_root; \
+ Dt_t *prefix_root; \
+ Dt_t *last_root; \
+ Dt_t *prev_root; \
+ Dt_t *fpathdict; \
+ Dt_t *typedict; \
+ Dt_t *inpool; \
+ Dt_t *transdict; \
+ char ifstable[256]; \
+ unsigned long test; \
+ Shopt_t offoptions; \
+ Shopt_t glob_options; \
+ Namval_t *typeinit; \
+ Namfun_t nvfun; \
+ char *mathnodes; \
+ void *coshell; \
+ struct Regress_s*regress;
+
+#include <shell.h>
+
+#include "shtable.h"
+#include "regress.h"
+
+/* error exits from various parts of shell */
+#define NIL(type) ((type)0)
+
+#define new_of(type,x) ((type*)malloc((unsigned)sizeof(type)+(x)))
+
+#define exitset() (sh.savexit=sh.exitval)
+
+#ifndef SH_DICT
+#define SH_DICT (void*)e_dict
+#endif
+
+#ifndef SH_CMDLIB_DIR
+#define SH_CMDLIB_DIR "/opt/ast/bin"
+#endif
+
+/* states */
+/* low numbered states are same as options */
+#define SH_NOFORK 0 /* set when fork not necessary */
+#define SH_FORKED 7 /* set when process has been forked */
+#define SH_PROFILE 8 /* set when processing profiles */
+#define SH_NOALIAS 9 /* do not expand non-exported aliases */
+#define SH_NOTRACK 10 /* set to disable sftrack() function */
+#define SH_STOPOK 11 /* set for stopable builtins */
+#define SH_GRACE 12 /* set for timeout grace period */
+#define SH_TIMING 13 /* set while timing pipelines */
+#define SH_DEFPATH 14 /* set when using default path */
+#define SH_INIT 15 /* set when initializing the shell */
+#define SH_TTYWAIT 16 /* waiting for keyboard input */
+#define SH_FCOMPLETE 17 /* set for filename completion */
+#define SH_PREINIT 18 /* set with SH_INIT before parsing options */
+#define SH_COMPLETE 19 /* set for command completion */
+
+#define SH_BASH 41
+#define SH_BRACEEXPAND 42
+#define SH_POSIX 46
+#define SH_MULTILINE 47
+
+#define SH_NOPROFILE 78
+#define SH_NOUSRPROFILE 79
+#define SH_LOGIN_SHELL 67
+#define SH_COMMANDLINE 0x100
+#define SH_BASHEXTRA 0x200
+#define SH_BASHOPT 0x400
+
+#define SH_ID "ksh" /* ksh id */
+#define SH_STD "sh" /* standard sh id */
+
+/* defines for sh_type() */
+
+#define SH_TYPE_SH 001
+#define SH_TYPE_KSH 002
+#define SH_TYPE_BASH 004
+#define SH_TYPE_LOGIN 010
+#define SH_TYPE_PROFILE 020
+#define SH_TYPE_RESTRICTED 040
+
+#if SHOPT_BASH
+# ifndef SHOPT_HISTEXPAND
+# define SHOPT_HISTEXPAND 1
+# endif
+/*
+ * define for all the bash options
+ */
+# define SH_CDABLE_VARS 51
+# define SH_CDSPELL 52
+# define SH_CHECKHASH 53
+# define SH_CHECKWINSIZE 54
+# define SH_CMDHIST 55
+# define SH_DOTGLOB 56
+# define SH_EXECFAIL 57
+# define SH_EXPAND_ALIASES 58
+# define SH_EXTGLOB 59
+# define SH_HOSTCOMPLETE 63
+# define SH_HUPONEXIT 64
+# define SH_INTERACTIVE_COMM 65
+# define SH_LITHIST 66
+# define SH_MAILWARN 68
+# define SH_NOEMPTYCMDCOMPL 69
+# define SH_NOCASEGLOB 70
+# define SH_NULLGLOB 71
+# define SH_PHYSICAL 45
+# define SH_PROGCOMP 72
+# define SH_PROMPTVARS 73
+# define SH_RESTRICTED2 74
+# define SH_SHIFT_VERBOSE 75
+# define SH_SOURCEPATH 76
+# define SH_XPG_ECHO 77
+#endif
+
+#if SHOPT_HISTEXPAND
+# define SH_HISTAPPEND 60
+# define SH_HISTEXPAND 43
+# define SH_HISTORY2 44
+# define SH_HISTREEDIT 61
+# define SH_HISTVERIFY 62
+#endif
+
+#ifndef PIPE_BUF
+# define PIPE_BUF 512
+#endif
+
+#if SHOPT_PFSH && ( !_lib_getexecuser || !_lib_free_execattr )
+# undef SHOPT_PFSH
+#endif
+
+#define MATCH_MAX 64
+
+#define SH_READEVAL 0x4000 /* for sh_eval */
+#define SH_FUNEVAL 0x10000 /* for sh_eval for function load */
+
+extern struct shared *shgd;
+extern Shell_t *nv_shell(Namval_t*);
+extern int sh_addlib(Shell_t*,void*);
+extern void sh_applyopts(Shell_t*,Shopt_t);
+extern char **sh_argbuild(Shell_t*,int*,const struct comnod*,int);
+extern struct dolnod *sh_argfree(Shell_t *, struct dolnod*,int);
+extern struct dolnod *sh_argnew(Shell_t*,char*[],struct dolnod**);
+extern void *sh_argopen(Shell_t*);
+extern struct argnod *sh_argprocsub(Shell_t*,struct argnod*);
+extern void sh_argreset(Shell_t*,struct dolnod*,struct dolnod*);
+extern Namval_t *sh_assignok(Namval_t*,int);
+extern struct dolnod *sh_arguse(Shell_t*);
+extern char *sh_checkid(char*,char*);
+extern void sh_chktrap(Shell_t*);
+extern void sh_deparse(Sfio_t*,const Shnode_t*,int);
+extern int sh_debug(Shell_t *shp,const char*,const char*,const char*,char *const[],int);
+extern int sh_echolist(Shell_t*,Sfio_t*, int, char**);
+extern struct argnod *sh_endword(Shell_t*,int);
+extern char **sh_envgen(void);
+#if SHOPT_ENV
+extern void sh_envput(Env_t*, Namval_t*);
+#endif
+extern void sh_envnolocal(Namval_t*,void*);
+extern Sfdouble_t sh_arith(Shell_t*,const char*);
+extern void *sh_arithcomp(Shell_t *,char*);
+extern pid_t sh_fork(Shell_t*,int,int*);
+extern pid_t _sh_fork(Shell_t*,pid_t, int ,int*);
+extern char *sh_mactrim(Shell_t*,char*,int);
+extern int sh_macexpand(Shell_t*,struct argnod*,struct argnod**,int);
+extern int sh_macfun(Shell_t*,const char*,int);
+extern void sh_machere(Shell_t*,Sfio_t*, Sfio_t*, char*);
+extern void *sh_macopen(Shell_t*);
+extern char *sh_macpat(Shell_t*,struct argnod*,int);
+extern Sfdouble_t sh_mathfun(Shell_t*, void*, int, Sfdouble_t*);
+extern int sh_outtype(Shell_t*, Sfio_t*);
+extern char *sh_mactry(Shell_t*,char*);
+extern int sh_mathstd(const char*);
+extern void sh_printopts(Shopt_t,int,Shopt_t*);
+extern int sh_readline(Shell_t*,char**,int,int,long);
+extern Sfio_t *sh_sfeval(char*[]);
+extern void sh_setmatch(Shell_t*,const char*,int,int,int[],int);
+extern Dt_t *sh_subaliastree(int);
+extern void sh_scope(Shell_t*, struct argnod*, int);
+extern Namval_t *sh_scoped(Shell_t*, Namval_t*);
+extern Dt_t *sh_subfuntree(int);
+extern void sh_subjobcheck(pid_t);
+extern int sh_subsavefd(int);
+extern void sh_subtmpfile(Shell_t*);
+extern char *sh_substitute(const char*,const char*,char*);
+extern void sh_timetraps(Shell_t*);
+extern const char *_sh_translate(const char*);
+extern int sh_trace(Shell_t*,char*[],int);
+extern void sh_trim(char*);
+extern int sh_type(const char*);
+extern void sh_unscope(Shell_t*);
+extern void sh_utol(const char*, char*);
+extern int sh_whence(char**,int);
+#if SHOPT_COSHELL
+ extern int sh_coaddfile(Shell_t*,char*);
+ extern int sh_copipe(Shell_t*, int[], int);
+ extern int sh_coaccept(Shell_t*,int[],int);
+#endif /* SHOPT_COSHELL */
+#if SHOPT_NAMESPACE
+ extern Namval_t *sh_fsearch(Shell_t*,const char *,int);
+#endif /* SHOPT_NAMESPACE */
+
+#ifndef ERROR_dictionary
+# define ERROR_dictionary(s) (s)
+#endif
+#define sh_translate(s) _sh_translate(ERROR_dictionary(s))
+
+#define WBITS (sizeof(long)*8)
+#define WMASK (0xff)
+
+#define is_option(s,x) ((s)->v[((x)&WMASK)/WBITS] & (1L << ((x) % WBITS)))
+#define on_option(s,x) ((s)->v[((x)&WMASK)/WBITS] |= (1L << ((x) % WBITS)))
+#define off_option(s,x) ((s)->v[((x)&WMASK)/WBITS] &= ~(1L << ((x) % WBITS)))
+#define sh_isoption(x) is_option(&sh.options,x)
+#define sh_onoption(x) on_option(&sh.options,x)
+#define sh_offoption(x) off_option(&sh.options,x)
+
+
+#define sh_state(x) ( 1<<(x))
+#define sh_isstate(x) (sh.st.states&sh_state(x))
+#define sh_onstate(x) (sh.st.states |= sh_state(x))
+#define sh_offstate(x) (sh.st.states &= ~sh_state(x))
+#define sh_getstate() (sh.st.states)
+#define sh_setstate(x) (sh.st.states = (x))
+
+#define sh_sigcheck(shp) do{if(shp->trapnote&SH_SIGSET)sh_exit(SH_EXITSIG);} while(0)
+
+extern int32_t sh_mailchk;
+extern const char e_dict[];
+
+/* sh_printopts() mode flags -- set --[no]option by default */
+
+#define PRINT_VERBOSE 0x01 /* option on|off list */
+#define PRINT_ALL 0x02 /* list unset options too */
+#define PRINT_NO_HEADER 0x04 /* omit listing header */
+#define PRINT_SHOPT 0x08 /* shopt -s|-u */
+#define PRINT_TABLE 0x10 /* table of all options */
+
+#ifdef SHOPT_STATS
+ /* performance statistics */
+# define STAT_ARGHITS 0
+# define STAT_ARGEXPAND 1
+# define STAT_COMSUB 2
+# define STAT_FORKS 3
+# define STAT_FUNCT 4
+# define STAT_GLOBS 5
+# define STAT_READS 6
+# define STAT_NVHITS 7
+# define STAT_NVOPEN 8
+# define STAT_PATHS 9
+# define STAT_SVFUNCT 10
+# define STAT_SCMDS 11
+# define STAT_SPAWN 12
+# define STAT_SUBSHELL 13
+ extern const Shtable_t shtab_stats[];
+# define sh_stats(x) (shgd->stats[(x)]++)
+#else
+# define sh_stats(x)
+#endif /* SHOPT_STATS */
+
+
+#endif
diff --git a/src/cmd/ksh93/include/edit.h b/src/cmd/ksh93/include/edit.h
new file mode 100644
index 0000000..239158e
--- /dev/null
+++ b/src/cmd/ksh93/include/edit.h
@@ -0,0 +1,286 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef SEARCHSIZE
+/*
+ * edit.h - common data structure for vi and emacs edit options
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#define SEARCHSIZE 80
+
+#include "FEATURE/options"
+#include "FEATURE/locale"
+#if !SHOPT_VSH && !SHOPT_ESH
+# define ed_winsize() (SEARCHSIZE)
+#else
+
+#if !KSHELL
+# include <setjmp.h>
+# include <sig.h>
+# include <ctype.h>
+#endif /* KSHELL */
+
+#include "FEATURE/setjmp"
+#include "terminal.h"
+
+#define STRIP 0377
+#define LOOKAHEAD 80
+
+#if SHOPT_MULTIBYTE
+# ifndef ESS_MAXCHAR
+# include "national.h"
+# endif /* ESS_MAXCHAR */
+ typedef wchar_t genchar;
+# define CHARSIZE (sizeof(wchar_t)<=2?3:sizeof(wchar_t))
+#else
+ typedef char genchar;
+# define CHARSIZE 1
+#endif /* SHOPT_MULTIBYTE */
+
+#define TABSIZE 8
+#define PRSIZE 160
+#define MAXLINE 1024 /* longest edit line permitted */
+
+typedef struct _edit_pos
+{
+ unsigned short line;
+ unsigned short col;
+} Edpos_t;
+
+#if SHOPT_EDPREDICT
+typedef struct Histmatch
+{
+ struct Histmatch *next;
+ int index;
+ short len;
+ short count;
+ char data[1];
+} Histmatch_t;
+#endif /* SHOPT_EDPREDICT */
+
+
+
+typedef struct edit
+{
+ sigjmp_buf e_env;
+ int e_intr;
+ int e_kill;
+ int e_erase;
+ int e_werase;
+ int e_eof;
+ int e_lnext;
+ int e_fchar;
+ int e_plen; /* length of prompt string */
+ char e_crlf; /* zero if cannot return to beginning of line */
+ char e_nocrnl; /* don't put a new-line with ^L */
+ char e_keytrap; /* set when in keytrap */
+ int e_llimit; /* line length limit */
+ int e_hline; /* current history line number */
+ int e_hloff; /* line number offset for command */
+ int e_hismin; /* minimum history line number */
+ int e_hismax; /* maximum history line number */
+ int e_raw; /* set when in raw mode or alt mode */
+ int e_cur; /* current line position */
+ int e_eol; /* end-of-line position */
+ int e_pcur; /* current physical line position */
+ int e_peol; /* end of physical line position */
+ int e_mode; /* edit mode */
+ int e_lookahead; /* index in look-ahead buffer */
+ int e_repeat;
+ int e_saved;
+ int e_fcol; /* first column */
+ int e_ucol; /* column for undo */
+ int e_wsize; /* width of display window */
+ char *e_outbase; /* pointer to start of output buffer */
+ char *e_outptr; /* pointer to position in output buffer */
+ char *e_outlast; /* pointer to end of output buffer */
+ genchar *e_inbuf; /* pointer to input buffer */
+ char *e_prompt; /* pointer to buffer containing the prompt */
+ genchar *e_ubuf; /* pointer to the undo buffer */
+ genchar *e_killbuf; /* pointer to delete buffer */
+ char e_search[SEARCHSIZE]; /* search string */
+ genchar *e_Ubuf; /* temporary workspace buffer */
+ genchar *e_physbuf; /* temporary workspace buffer */
+ int e_lbuf[LOOKAHEAD];/* pointer to look-ahead buffer */
+ int e_fd; /* file descriptor */
+ int e_ttyspeed; /* line speed, also indicates tty parms are valid */
+ int e_tabcount;
+#ifdef _hdr_utime
+ ino_t e_tty_ino;
+ dev_t e_tty_dev;
+ char *e_tty;
+#endif
+#if SHOPT_OLDTERMIO
+ char e_echoctl;
+ char e_tcgeta;
+ struct termio e_ott;
+#endif
+#if SHOPT_MULTIBYTE
+ int e_curchar;
+ int e_cursize;
+#endif
+ int *e_globals; /* global variables */
+ genchar *e_window; /* display window image */
+ char e_inmacro; /* processing macro expansion */
+#if KSHELL
+ char e_vi_insert[2]; /* for sh_keytrap */
+ int32_t e_col; /* for sh_keytrap */
+#else
+ char e_prbuff[PRSIZE]; /* prompt buffer */
+#endif /* KSHELL */
+ struct termios e_ttyparm; /* initial tty parameters */
+ struct termios e_nttyparm; /* raw tty parameters */
+ struct termios e_savetty; /* saved terminal state */
+ int e_savefd; /* file descriptor for saved terminal state */
+ char e_macro[4]; /* macro buffer */
+ void *e_vi; /* vi specific data */
+ void *e_emacs; /* emacs specific data */
+ Shell_t *sh; /* interpreter pointer */
+ char *e_stkptr; /* saved stack pointer */
+ int e_stkoff; /* saved stack offset */
+ char **e_clist; /* completion list after <ESC>= */
+ int e_nlist; /* number of elements on completion list */
+ int e_multiline; /* allow multiple lines for editing */
+ int e_winsz; /* columns in window */
+ Edpos_t e_curpos; /* cursor line and column */
+ Namval_t *e_default; /* variable containing default value */
+ Namval_t *e_term; /* TERM variable */
+ char e_termname[80]; /* terminal name */
+#if SHOPT_EDPREDICT
+ Histmatch_t **hlist;
+ Histmatch_t *hfirst;
+ unsigned short nhlist;
+ unsigned short hoff;
+ unsigned short hmax;
+ char *hpat;
+ char *hstak;
+#endif /* SHOPT_EDPREDICT */
+} Edit_t;
+
+#undef MAXWINDOW
+#define MAXWINDOW 300 /* maximum width window */
+#define FAST 2
+#define SLOW 1
+#define ESC cntl('[')
+#define UEOF -2 /* user eof char synonym */
+#define UINTR -3 /* user intr char synonym */
+#define UERASE -4 /* user erase char synonym */
+#define UKILL -5 /* user kill char synonym */
+#define UWERASE -6 /* user word erase char synonym */
+#define ULNEXT -7 /* user next literal char synonym */
+
+#if ( 'a' == 97) /* ASCII? */
+# define cntl(x) (x&037)
+#else
+# define cntl(c) (c=='D'?55:(c=='E'?45:(c=='F'?46:(c=='G'?'\a':(c=='H'?'\b': \
+ (c=='I'?'\t':(c=='J'?'\n':(c=='T'?60:(c=='U'?61:(c=='V'?50: \
+ (c=='W'?38:(c=='Z'?63:(c=='['?39:(c==']'?29: \
+ (c<'J'?c+1-'A':(c+10-'J'))))))))))))))))
+#endif
+
+#if !KSHELL
+# define STRIP 0377
+# define GMACS 1
+# define EMACS 2
+# define VIRAW 4
+# define EDITVI 8
+# define NOHIST 16
+# define EDITMASK 15
+# define is_option(m) (opt_flag&(m))
+ extern char opt_flag;
+# ifdef SYSCALL
+# define read(fd,buff,n) syscall(3,fd,buff,n)
+# else
+# define read(fd,buff,n) rEAd(fd,buff,n)
+# endif /* SYSCALL */
+#endif /* KSHELL */
+
+extern void ed_crlf(Edit_t*);
+extern void ed_putchar(Edit_t*, int);
+extern void ed_ringbell(void);
+extern void ed_setup(Edit_t*,int, int);
+extern void ed_flush(Edit_t*);
+extern int ed_getchar(Edit_t*,int);
+extern int ed_virt_to_phys(Edit_t*,genchar*,genchar*,int,int,int);
+extern int ed_window(void);
+extern void ed_ungetchar(Edit_t*,int);
+extern int ed_viread(void*, int, char*, int, int);
+extern int ed_read(void*, int, char*, int, int);
+extern int ed_emacsread(void*, int, char*, int, int);
+extern Edpos_t ed_curpos(Edit_t*, genchar*, int, int, Edpos_t);
+extern int ed_setcursor(Edit_t*, genchar*, int, int, int);
+#if KSHELL
+ extern int ed_macro(Edit_t*,int);
+ extern int ed_expand(Edit_t*, char[],int*,int*,int,int);
+ extern int ed_fulledit(Edit_t*);
+ extern void *ed_open(Shell_t*);
+#endif /* KSHELL */
+# if SHOPT_MULTIBYTE
+ extern int ed_internal(const char*, genchar*);
+ extern int ed_external(const genchar*, char*);
+ extern void ed_gencpy(genchar*,const genchar*);
+ extern void ed_genncpy(genchar*,const genchar*,int);
+ extern int ed_genlen(const genchar*);
+ extern int ed_setwidth(const char*);
+# endif /* SHOPT_MULTIBYTE */
+#if SHOPT_EDPREDICT
+ extern int ed_histgen(Edit_t*, const char*);
+ extern void ed_histlist(Edit_t*, int);
+#endif /* SHOPT_EDPREDICT */
+
+extern const char e_runvi[];
+#if !KSHELL
+ extern const char e_version[];
+#endif /* KSHELL */
+
+#if SHOPT_HISTEXPAND
+
+/* flags */
+
+#define HIST_EVENT 0x1 /* event designator seen */
+#define HIST_QUESTION 0x2 /* question mark event designator */
+#define HIST_HASH 0x4 /* hash event designator */
+#define HIST_WORDDSGN 0x8 /* word designator seen */
+#define HIST_QUICKSUBST 0x10 /* quick substition designator seen */
+#define HIST_SUBSTITUTE 0x20 /* for substition loop */
+#define HIST_NEWLINE 0x40 /* newline in squashed white space */
+
+/* modifier flags */
+
+#define HIST_PRINT 0x100 /* print new command */
+#define HIST_QUOTE 0x200 /* quote resulting history line */
+#define HIST_QUOTE_BR 0x400 /* quote every word on space break */
+#define HIST_GLOBALSUBST 0x800 /* apply substition globally */
+
+#define HIST_ERROR 0x1000 /* an error ocurred */
+
+/* flags to be returned */
+
+#define HIST_FLAG_RETURN_MASK (HIST_EVENT|HIST_PRINT|HIST_ERROR)
+
+extern int hist_expand(const char *, char **);
+#endif
+
+#endif
+#endif
diff --git a/src/cmd/ksh93/include/env.h b/src/cmd/ksh93/include/env.h
new file mode 100644
index 0000000..0224aa4
--- /dev/null
+++ b/src/cmd/ksh93/include/env.h
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef _ENV_H
+#define _ENV_H 1
+
+#ifdef _BLD_env
+# ifdef __EXPORT__
+# define export __EXPORT__
+# endif
+#else
+ typedef void *Env_t;
+#endif
+
+/* for use with env_open */
+#define ENV_STABLE (-1)
+
+/* for third agument to env_add */
+#define ENV_MALLOCED 1
+#define ENV_STRDUP 2
+
+extern void env_close(Env_t*);
+extern int env_add(Env_t*, const char*, int);
+extern int env_delete(Env_t*, const char*);
+extern char **env_get(Env_t*);
+extern Env_t *env_open(char**,int);
+extern Env_t *env_scope(Env_t*,int);
+
+#undef extern
+
+#endif
+
+
diff --git a/src/cmd/ksh93/include/fault.h b/src/cmd/ksh93/include/fault.h
new file mode 100644
index 0000000..e327903
--- /dev/null
+++ b/src/cmd/ksh93/include/fault.h
@@ -0,0 +1,127 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef SH_SIGBITS
+/*
+ * UNIX shell
+ * S. R. Bourne
+ * Rewritten by David Korn
+ *
+ */
+
+#include <sig.h>
+#include <setjmp.h>
+#include <error.h>
+#include <sfio.h>
+#include "FEATURE/setjmp"
+#include "FEATURE/sigfeatures"
+
+
+#ifndef SIGWINCH
+# ifdef SIGWIND
+# define SIGWINCH SIGWIND
+# else
+# ifdef SIGWINDOW
+# define SIGWINCH SIGWINDOW
+# endif
+# endif
+#endif
+
+typedef void (*SH_SIGTYPE)(int,void(*)(int));
+
+#define SH_FORKLIM 16 /* fork timeout interval */
+
+#define SH_TRAP 0200 /* bit for internal traps */
+#define SH_ERRTRAP 0 /* trap for non-zero exit status */
+#define SH_KEYTRAP 1 /* trap for keyboard event */
+#define SH_DEBUGTRAP 4 /* must be last internal trap */
+
+#define SH_SIGBITS 8
+#define SH_SIGFAULT 1 /* signal handler is sh_fault */
+#define SH_SIGOFF 2 /* signal handler is SIG_IGN */
+#define SH_SIGSET 4 /* pending signal */
+#define SH_SIGTRAP 010 /* pending trap */
+#define SH_SIGDONE 020 /* default is exit */
+#define SH_SIGIGNORE 040 /* default is ingore signal */
+#define SH_SIGINTERACTIVE 0100 /* handle interactive specially */
+#define SH_SIGTSTP 0200 /* tstp signal received */
+#define SH_SIGALRM 0200 /* timer alarm received */
+#define SH_SIGTERM SH_SIGOFF /* term signal received */
+#define SH_SIGRUNTIME 0400 /* runtime value */
+
+#define SH_SIGRTMIN 0 /* sh.sigruntime[] index */
+#define SH_SIGRTMAX 1 /* sh.sigruntime[] index */
+
+/*
+ * These are longjmp values
+ */
+
+#define SH_JMPDOT 2
+#define SH_JMPEVAL 3
+#define SH_JMPTRAP 4
+#define SH_JMPIO 5
+#define SH_JMPCMD 6
+#define SH_JMPFUN 7
+#define SH_JMPERRFN 8
+#define SH_JMPSUB 9
+#define SH_JMPERREXIT 10
+#define SH_JMPEXIT 11
+#define SH_JMPSCRIPT 12
+
+struct openlist
+{
+ Sfio_t *strm;
+ struct openlist *next;
+};
+
+struct checkpt
+{
+ sigjmp_buf buff;
+ sigjmp_buf *prev;
+ int topfd;
+ int mode;
+ struct openlist *olist;
+#if (ERROR_VERSION >= 20030214L)
+ Error_context_t err;
+#else
+ struct errorcontext err;
+#endif
+};
+
+#define sh_pushcontext(shp,bp,n)( (bp)->mode=(n) , (bp)->olist=0, \
+ (bp)->topfd=shp->topfd, (bp)->prev=shp->jmplist, \
+ (bp)->err = *ERROR_CONTEXT_BASE, \
+ shp->jmplist = (sigjmp_buf*)(&(bp)->buff) \
+ )
+#define sh_popcontext(shp,bp) (shp->jmplist=(bp)->prev, errorpop(&((bp)->err)))
+
+extern void sh_fault(int);
+extern void sh_done(void*,int);
+extern void sh_sigclear(int);
+extern void sh_sigdone(void);
+extern void sh_siginit(void*);
+extern void sh_sigtrap(int);
+extern void sh_sigreset(int);
+extern void *sh_timeradd(unsigned long,int ,void (*)(void*),void*);
+extern void timerdel(void*);
+
+extern const char e_alarm[];
+
+#endif /* !SH_SIGBITS */
diff --git a/src/cmd/ksh93/include/fcin.h b/src/cmd/ksh93/include/fcin.h
new file mode 100644
index 0000000..1459a3a
--- /dev/null
+++ b/src/cmd/ksh93/include/fcin.h
@@ -0,0 +1,71 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef fcgetc
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * Fast character input with sfio text streams and strings
+ *
+ */
+
+#include <sfio.h>
+
+typedef struct _fcin
+{
+ Sfio_t *_fcfile; /* input file pointer */
+ unsigned char *fcbuff; /* pointer to input buffer */
+ unsigned char *fclast; /* pointer to end of input buffer */
+ unsigned char *fcptr; /* pointer to next input char */
+ unsigned char fcchar; /* saved character */
+ short fclen; /* last multibyte char len */
+ void (*fcfun)(Sfio_t*,const char*,int,void*); /* advance function */
+ void *context; /* context pointer */
+ int fcleft; /* for multibyte boundary */
+ Sfoff_t fcoff; /* offset for last read */
+} Fcin_t;
+
+#if SHOPT_MULTIBYTE
+# define fcmbget(x) (mbwide()?_fcmbget(x):fcget())
+#else
+# define fcmbget(x) (fcget())
+#endif
+#define fcfile() (_Fcin._fcfile)
+#define fcgetc(c) (((c=fcget()) || (c=fcfill())), c)
+#define fcget() ((int)(*_Fcin.fcptr++))
+#define fcpeek(n) ((int)_Fcin.fcptr[n])
+#define fcseek(n) ((char*)(_Fcin.fcptr+=(n)))
+#define fcfirst() ((char*)_Fcin.fcbuff)
+#define fclast() ((char*)_Fcin.fclast)
+#define fcleft() (_Fcin.fclast-_Fcin.fcptr)
+#define fcsopen(s) (_Fcin._fcfile=(Sfio_t*)0,_Fcin.fclen=1,_Fcin.fcbuff=_Fcin.fcptr=(unsigned char*)(s))
+#define fctell() (_Fcin.fcoff + (_Fcin.fcptr-_Fcin.fcbuff))
+#define fcsave(x) (*(x) = _Fcin)
+#define fcrestore(x) (_Fcin = *(x))
+extern int fcfill(void);
+extern int fcfopen(Sfio_t*);
+extern int fcclose(void);
+void fcnotify(void(*)(Sfio_t*,const char*,int,void*),void*);
+extern int _fcmbget(short*);
+
+extern Fcin_t _Fcin; /* used by macros */
+
+#endif /* fcgetc */
diff --git a/src/cmd/ksh93/include/history.h b/src/cmd/ksh93/include/history.h
new file mode 100644
index 0000000..034a3d3
--- /dev/null
+++ b/src/cmd/ksh93/include/history.h
@@ -0,0 +1,75 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef HIST_VERSION
+/*
+ * Interface for history mechanism
+ * written by David Korn
+ *
+ */
+
+#include <ast.h>
+
+#define HIST_CHAR '!'
+#define HIST_VERSION 1 /* history file format version no. */
+
+typedef struct
+{
+ Sfdisc_t histdisc; /* discipline for history */
+ Sfio_t *histfp; /* history file stream pointer */
+ char *histname; /* name of history file */
+ int32_t histind; /* current command number index */
+ int histsize; /* number of accessible history lines */
+#ifdef _HIST_PRIVATE
+ _HIST_PRIVATE
+#endif /* _HIST_PRIVATE */
+} History_t;
+
+typedef struct
+{
+ int hist_command;
+ int hist_line;
+ int hist_char;
+} Histloc_t;
+
+/* the following are readonly */
+extern const char hist_fname[];
+
+extern int _Hist;
+#define hist_min(hp) ((_Hist=((int)((hp)->histind-(hp)->histsize)))>=0?_Hist:0)
+#define hist_max(hp) ((int)((hp)->histind))
+/* these are the history interface routines */
+extern int sh_histinit(void *);
+extern void hist_cancel(History_t*);
+extern void hist_close(History_t*);
+extern int hist_copy(char*, int, int, int);
+extern void hist_eof(History_t*);
+extern Histloc_t hist_find(History_t*,char*,int, int, int);
+extern void hist_flush(History_t*);
+extern void hist_list(History_t*,Sfio_t*, off_t, int, char*);
+extern int hist_match(History_t*,off_t, char*, int*);
+extern off_t hist_tell(History_t*,int);
+extern off_t hist_seek(History_t*,int);
+extern char *hist_word(char*, int, int);
+#if SHOPT_ESH
+ extern Histloc_t hist_locate(History_t*,int, int, int);
+#endif /* SHOPT_ESH */
+
+#endif /* HIST_VERSION */
diff --git a/src/cmd/ksh93/include/io.h b/src/cmd/ksh93/include/io.h
new file mode 100644
index 0000000..c01dd12
--- /dev/null
+++ b/src/cmd/ksh93/include/io.h
@@ -0,0 +1,126 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * UNIX shell
+ * David Korn
+ *
+ */
+
+#include <ast.h>
+#include <sfio.h>
+
+#ifndef IOBSIZE
+# define IOBSIZE SF_BUFSIZE
+#endif /* IOBSIZE */
+#define IOMAXTRY 20
+
+#ifndef SF_CLOSING
+#define SF_CLOSING SF_CLOSE
+#endif
+#ifndef SF_APPENDWR
+#define SF_APPENDWR SF_APPEND
+#endif
+
+/* used for output of shell errors */
+#define ERRIO 2
+
+#define IOREAD 001
+#define IOWRITE 002
+#define IODUP 004
+#define IOSEEK 010
+#define IONOSEEK 020
+#define IOTTY 040
+#define IOCLEX 0100
+#define IOCLOSE (IOSEEK|IONOSEEK)
+
+#define IOSUBSHELL 0x8000 /* must be larger than any file descriptor */
+
+/*
+ * The remainder of this file is only used when compiled with shell
+ */
+
+#if KSHELL
+
+#ifndef ARG_RAW
+ struct ionod;
+#endif /* !ARG_RAW */
+
+extern int sh_iocheckfd(Shell_t*,int);
+extern void sh_ioinit(Shell_t*);
+extern int sh_iomovefd(int);
+extern int sh_iorenumber(Shell_t*,int,int);
+extern void sh_pclose(int[]);
+extern void sh_iorestore(Shell_t*,int,int);
+#if defined(__EXPORT__) && defined(_BLD_DLL) && defined(_BLD_shell)
+ __EXPORT__
+#endif
+extern Sfio_t *sh_iostream(Shell_t*,int);
+extern int sh_redirect(Shell_t*,struct ionod*,int);
+extern void sh_iosave(Shell_t *, int,int,char*);
+extern int sh_iovalidfd(Shell_t*, int);
+extern int sh_inuse(Shell_t*, int);
+extern void sh_iounsave(Shell_t*);
+extern int sh_chkopen(const char*);
+extern int sh_ioaccess(int,int);
+extern int sh_devtofd(const char*);
+extern int sh_isdevfd(const char*);
+extern int sh_source(Shell_t*, Sfio_t*, const char*);
+
+/* the following are readonly */
+extern const char e_pexists[];
+extern const char e_query[];
+extern const char e_history[];
+extern const char e_argtype[];
+extern const char e_create[];
+extern const char e_tmpcreate[];
+extern const char e_exists[];
+extern const char e_file[];
+extern const char e_redirect[];
+extern const char e_formspec[];
+extern const char e_badregexp[];
+extern const char e_open[];
+extern const char e_notseek[];
+extern const char e_noread[];
+extern const char e_badseek[];
+extern const char e_badwrite[];
+extern const char e_badpattern[];
+extern const char e_toomany[];
+extern const char e_pipe[];
+extern const char e_unknown[];
+extern const char e_devnull[];
+extern const char e_profile[];
+extern const char e_sysprofile[];
+#if SHOPT_SYSRC
+extern const char e_sysrc[];
+#endif
+#if SHOPT_BASH
+#if SHOPT_SYSRC
+extern const char e_bash_sysrc[];
+#endif
+extern const char e_bash_rc[];
+extern const char e_bash_login[];
+extern const char e_bash_logout[];
+extern const char e_bash_profile[];
+#endif
+extern const char e_stdprompt[];
+extern const char e_supprompt[];
+extern const char e_ambiguous[];
+#endif /* KSHELL */
diff --git a/src/cmd/ksh93/include/jobs.h b/src/cmd/ksh93/include/jobs.h
new file mode 100644
index 0000000..b67b097
--- /dev/null
+++ b/src/cmd/ksh93/include/jobs.h
@@ -0,0 +1,216 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef JOB_NFLAG
+/*
+ * Interface to job control for shell
+ * written by David Korn
+ *
+ */
+
+#define JOBTTY 2
+
+#include <ast.h>
+#include <sfio.h>
+#ifndef SIGINT
+# include <signal.h>
+#endif /* !SIGINT */
+#include "FEATURE/options"
+
+#if SHOPT_COSHELL
+# include <coshell.h>
+# define COPID_BIT (1L<<30)
+ struct cosh
+ {
+ struct cosh *next;
+ Coshell_t *coshell;
+ Cojob_t *cojob;
+ char *name;
+ short id;
+ };
+
+ extern pid_t sh_copid(struct cosh*);
+ extern char *sh_pid2str(Shell_t*,pid_t);
+#endif /* SHOPT_COSHELL */
+
+#undef JOBS
+#if defined(SIGCLD) && !defined(SIGCHLD)
+# define SIGCHLD SIGCLD
+#endif
+#ifdef SIGCHLD
+# define JOBS 1
+# include "terminal.h"
+# ifdef FIOLOOKLD
+ /* Ninth edition */
+ extern int tty_ld, ntty_ld;
+# define OTTYDISC tty_ld
+# define NTTYDISC ntty_ld
+# endif /* FIOLOOKLD */
+#else
+# undef SIGTSTP
+# undef SH_MONITOR
+# define SH_MONITOR 0
+# define job_set(x)
+# define job_reset(x)
+#endif
+
+struct process
+{
+ struct process *p_nxtjob; /* next job structure */
+ struct process *p_nxtproc; /* next process in current job */
+ Shell_t *p_shp; /* shell that posted the job */
+#if SHOPT_COSHELL
+ Cojob_t *p_cojob; /* coshell job */
+#endif /* SHOPT_COSHELL */
+ int *p_exitval; /* place to store the exitval */
+ pid_t p_pid; /* process id */
+ pid_t p_pgrp; /* process group */
+ pid_t p_fgrp; /* process group when stopped */
+ short p_job; /* job number of process */
+ unsigned short p_exit; /* exit value or signal number */
+ unsigned short p_exitmin; /* minimum exit value for xargs */
+ unsigned short p_flag; /* flags - see below */
+ int p_env; /* subshell environment number */
+#ifdef JOBS
+ off_t p_name; /* history file offset for command */
+ struct termios p_stty; /* terminal state for job */
+#endif /* JOBS */
+};
+
+struct jobs
+{
+ struct process *pwlist; /* head of process list */
+ int *exitval; /* pipe exit values */
+ pid_t curpgid; /* current process gid id */
+ pid_t parent; /* set by fork() */
+ pid_t mypid; /* process id of shell */
+ pid_t mypgid; /* process group id of shell */
+ pid_t mytgid; /* terminal group id of shell */
+ int curjobid;
+ unsigned int in_critical; /* >0 => in critical region */
+ int savesig; /* active signal */
+ int numpost; /* number of posted jobs */
+#ifdef SHOPT_BGX
+ int numbjob; /* number of background jobs */
+#endif /* SHOPT_BGX */
+ short fd; /* tty descriptor number */
+#ifdef JOBS
+ int suspend; /* suspend character */
+ int linedisc; /* line dicipline */
+#endif /* JOBS */
+ char jobcontrol; /* turned on for real job control */
+ char waitsafe; /* wait will not block */
+ char waitall; /* wait for all jobs in pipe */
+ char toclear; /* job table needs clearing */
+ unsigned char *freejobs; /* free jobs numbers */
+#if SHOPT_COSHELL
+ struct cosh *colist; /* coshell job list */
+#endif /* SHOPT_COSHELL */
+};
+
+/* flags for joblist */
+#define JOB_LFLAG 1
+#define JOB_NFLAG 2
+#define JOB_PFLAG 4
+#define JOB_NLFLAG 8
+
+extern struct jobs job;
+
+#ifdef JOBS
+
+#if !_std_malloc
+#include <vmalloc.h>
+#ifdef vmlocked
+#define vmbusy() vmlocked(Vmregion)
+#else
+#if VMALLOC_VERSION >= 20070911L
+#define vmbusy() (vmstat(0,0)!=0)
+#endif
+#endif
+#endif
+#ifndef vmbusy
+#define vmbusy() 0
+#endif
+
+#define job_lock() (job.in_critical++)
+#define job_unlock() \
+ do { \
+ int sig; \
+ if (!--job.in_critical && (sig = job.savesig)) \
+ { \
+ if (!job.in_critical++ && !vmbusy()) \
+ job_reap(sig); \
+ job.in_critical--; \
+ } \
+ } while(0)
+
+extern const char e_jobusage[];
+extern const char e_done[];
+extern const char e_running[];
+extern const char e_coredump[];
+extern const char e_no_proc[];
+extern const char e_no_job[];
+extern const char e_badpid[];
+extern const char e_jobsrunning[];
+extern const char e_nlspace[];
+extern const char e_access[];
+extern const char e_terminate[];
+extern const char e_no_jctl[];
+extern const char e_signo[];
+#ifdef SIGTSTP
+ extern const char e_no_start[];
+#endif /* SIGTSTP */
+#ifdef NTTYDISC
+ extern const char e_newtty[];
+ extern const char e_oldtty[];
+#endif /* NTTYDISC */
+#endif /* JOBS */
+
+/*
+ * The following are defined in jobs.c
+ */
+
+extern void job_clear(void);
+extern void job_bwait(char**);
+extern int job_walk(Sfio_t*,int(*)(struct process*,int),int,char*[]);
+extern int job_kill(struct process*,int);
+extern int job_wait(pid_t);
+extern int job_post(Shell_t*,pid_t,pid_t);
+extern void *job_subsave(void);
+extern void job_subrestore(void*);
+#ifdef SHOPT_BGX
+extern void job_chldtrap(Shell_t*, const char*,int);
+#endif /* SHOPT_BGX */
+#ifdef JOBS
+ extern void job_init(Shell_t*,int);
+ extern int job_close(Shell_t*);
+ extern int job_list(struct process*,int);
+ extern int job_terminate(struct process*,int);
+ extern int job_switch(struct process*,int);
+ extern void job_fork(pid_t);
+ extern int job_reap(int);
+#else
+# define job_init(s,flag)
+# define job_close(s) (0)
+# define job_fork(p)
+#endif /* JOBS */
+
+
+#endif /* !JOB_NFLAG */
diff --git a/src/cmd/ksh93/include/lexstates.h b/src/cmd/ksh93/include/lexstates.h
new file mode 100644
index 0000000..a078e35
--- /dev/null
+++ b/src/cmd/ksh93/include/lexstates.h
@@ -0,0 +1,157 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef S_BREAK
+#define S_BREAK 1 /* end of token */
+#define S_EOF 2 /* end of buffer */
+#define S_NL 3 /* new-line when not a token */
+#define S_RES 4 /* first character of reserved word */
+#define S_NAME 5 /* other identifier characters */
+#define S_REG 6 /* non-special characters */
+#define S_TILDE 7 /* first char is tilde */
+#define S_PUSH 8
+#define S_POP 9
+#define S_BRACT 10
+#define S_LIT 11 /* literal quote character */
+#define S_NLTOK 12 /* new-line token */
+#define S_OP 13 /* operator character */
+#define S_PAT 14 /* pattern characters * and ? */
+#define S_EPAT 15 /* pattern char when followed by ( */
+#define S_EQ 16 /* assignment character */
+#define S_COM 17 /* comment character */
+#define S_MOD1 18 /* ${...} modifier character - old quoting */
+#define S_MOD2 19 /* ${...} modifier character - new quoting */
+#define S_ERR 20 /* invalid character in ${...} */
+#define S_SPC1 21 /* special prefix characters after $ */
+#define S_SPC2 22 /* special characters after $ */
+#define S_DIG 23 /* digit character after $*/
+#define S_ALP 24 /* alpahbetic character after $ */
+#define S_LBRA 25 /* left brace after $ */
+#define S_RBRA 26 /* right brace after $ */
+#define S_PAR 27 /* set for $( */
+#define S_ENDCH 28 /* macro expansion terminator */
+#define S_SLASH 29 /* / character terminates ~ expansion */
+#define S_COLON 30 /* for character : */
+#define S_LABEL 31 /* for goto label */
+#define S_EDOL 32 /* ends $identifier */
+#define S_BRACE 33 /* left brace */
+#define S_DOT 34 /* . char */
+#define S_META 35 /* | & ; < > inside ${...} reserved for future use */
+#define S_SPACE S_BREAK /* IFS space characters */
+#define S_DELIM S_RES /* IFS delimter characters */
+#define S_MBYTE S_NAME /* IFS first byte of multi-byte char */
+#define S_BLNK 36 /* space or tab */
+/* The following must be the highest numbered states */
+#define S_QUOTE 37 /* double quote character */
+#define S_GRAVE 38 /* old comsub character */
+#define S_ESC 39 /* escape character */
+#define S_DOL 40 /* $ subsitution character */
+#define S_ESC2 41 /* escape character inside '...' */
+
+/* These are the lexical state table names */
+#define ST_BEGIN 0
+#define ST_NAME 1
+#define ST_NORM 2
+#define ST_LIT 3
+#define ST_QUOTE 4
+#define ST_NESTED 5
+#define ST_DOL 6
+#define ST_BRACE 7
+#define ST_DOLNAME 8
+#define ST_MACRO 9
+#define ST_QNEST 10
+#define ST_NONE 11
+
+#include "FEATURE/locale"
+
+#if _hdr_wchar
+# include <wchar.h>
+# if _hdr_wctype
+# include <wctype.h>
+# undef isalpha
+# define isalpha(x) iswalpha(x)
+# if defined(iswblank) || _lib_iswblank
+# undef isblank
+# define isblank(x) iswblank(x)
+# else
+# if _lib_wctype && _lib_iswctype
+# define _lib_iswblank -1
+# undef isblank
+# define isblank(x) local_iswblank(x)
+ extern int local_iswblank(wchar_t);
+# endif
+# endif
+# endif
+#endif
+#ifndef isblank
+# define isblank(x) ((x)==' '||(x)=='\t')
+#endif
+
+#undef LEN
+#if SHOPT_MULTIBYTE
+# define LEN _Fcin.fclen
+# define isaname(c) ((c)>0x7f?isalpha(c): sh_lexstates[ST_NAME][(c)]==0)
+# define isaletter(c) ((c)>0x7f?isalpha(c): sh_lexstates[ST_DOL][(c)]==S_ALP && (c)!='.')
+#else
+# undef mbwide
+# define mbwide() (0)
+# define LEN 1
+# define isaname(c) (sh_lexstates[ST_NAME][c]==0)
+# define isaletter(c) (sh_lexstates[ST_DOL][c]==S_ALP && (c)!='.')
+#endif
+#define STATE(s,c) (s[mbwide()?((c=fcmbget(&LEN)),LEN>1?'a':c):(c=fcget())])
+#define isadigit(c) (sh_lexstates[ST_DOL][c]==S_DIG)
+#define isastchar(c) ((c)=='@' || (c)=='*')
+#define isexp(c) (sh_lexstates[ST_MACRO][c]==S_PAT||(c)=='$'||(c)=='`')
+#define ismeta(c) (sh_lexstates[ST_NAME][c]==S_BREAK)
+
+extern char *sh_lexstates[ST_NONE];
+extern const char *sh_lexrstates[ST_NONE];
+extern const char e_lexversion[];
+extern const char e_lexspace[];
+extern const char e_lexslash[];
+extern const char e_lexlabignore[];
+extern const char e_lexlabunknown[];
+extern const char e_lexsyntax1[];
+extern const char e_lexsyntax2[];
+extern const char e_lexsyntax3[];
+extern const char e_lexsyntax4[];
+extern const char e_lexsyntax5[];
+extern const char e_lexwarnvar[];
+extern const char e_lexobsolete1[];
+extern const char e_lexobsolete2[];
+extern const char e_lexobsolete3[];
+extern const char e_lexobsolete4[];
+extern const char e_lexobsolete5[];
+extern const char e_lexobsolete6[];
+extern const char e_lexnonstandard[];
+extern const char e_lexusebrace[];
+extern const char e_lexusequote[];
+extern const char e_lexescape[];
+extern const char e_lexquote[];
+extern const char e_lexnested[];
+extern const char e_lexbadchar[];
+extern const char e_lexlongquote[];
+extern const char e_lexfuture[];
+extern const char e_lexzerobyte[];
+extern const char e_lexemptyfor[];
+extern const char e_lextypeset[];
+extern const char e_lexcharclass[];
+#endif
diff --git a/src/cmd/ksh93/include/name.h b/src/cmd/ksh93/include/name.h
new file mode 100644
index 0000000..9768c05
--- /dev/null
+++ b/src/cmd/ksh93/include/name.h
@@ -0,0 +1,268 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef _NV_PRIVATE
+/*
+ * This is the implementation header file for name-value pairs
+ */
+
+#define _NV_PRIVATE \
+ Namfun_t *nvfun; /* pointer to trap functions */ \
+ union Value nvalue; /* value field */ \
+ char *nvenv; /* pointer to environment name */
+
+#include <ast.h>
+#include <cdt.h>
+
+typedef int (*Nambfp_f)(int, char**, void*);
+
+/* Nodes can have all kinds of values */
+union Value
+{
+ const char *cp;
+ int *ip;
+ char c;
+ int i;
+ unsigned int u;
+ int32_t *lp;
+ Sflong_t *llp; /* for long long arithmetic */
+ int16_t s;
+ int16_t *sp;
+ double *dp; /* for floating point arithmetic */
+ Sfdouble_t *ldp; /* for long floating point arithmetic */
+ struct Namarray *array; /* for array node */
+ struct Namval *np; /* for Namval_t node */
+ union Value *up; /* for indirect node */
+ struct Ufunction *rp; /* shell user defined functions */
+ struct Namfun *funp; /* discipline pointer */
+ struct Namref *nrp; /* name reference */
+ Nambfp_f bfp; /* builtin entry point function pointer */
+};
+
+#include "nval.h"
+
+/* used for arrays */
+
+#define ARRAY_MAX (1L<<ARRAY_BITS) /* maximum number of elements in an array */
+#define ARRAY_MASK (ARRAY_MAX-1) /* For index values */
+
+#define ARRAY_INCR 32 /* number of elements to grow when array
+ bound exceeded. Must be a power of 2 */
+#define ARRAY_FILL (8L<<ARRAY_BITS) /* used with nv_putsub() */
+#define ARRAY_NOCLONE (16L<<ARRAY_BITS) /* do not clone array disc */
+#define ARRAY_NOCHILD (32L<<ARRAY_BITS) /* skip compound arrays */
+#define ARRAY_SETSUB (64L<<ARRAY_BITS) /* set subscript */
+#define ARRAY_NOSCOPE (128L<<ARRAY_BITS) /* top level scope only */
+#define ARRAY_TREE (256L<<ARRAY_BITS) /* arrays of compound vars */
+#if SHOPT_FIXEDARRAY
+# define ARRAY_FIXED ARRAY_NOCLONE /* For index values */
+#endif /* SHOPT_FIXEDARRAY */
+#define NV_FARRAY 0x10000000 /* fixed sized arrays */
+#define NV_ASETSUB 8 /* set subscript */
+
+/* These flags are used as options to array_get() */
+#define ARRAY_ASSIGN 0
+#define ARRAY_LOOKUP 1
+#define ARRAY_DELETE 2
+
+
+struct Namref
+{
+ Namval_t *np;
+ Namval_t *table;
+ Dt_t *root;
+ char *sub;
+#if SHOPT_FIXEDARRAY
+ int curi;
+ char dim;
+#endif /* SHOPT_FIXEDARRAY */
+};
+
+/* This describes a user shell function node */
+struct Ufunction
+{
+ int *ptree; /* address of parse tree */
+ int lineno; /* line number of function start */
+ short argc; /* number of references */
+ char **argv; /* reference argument list */
+ off_t hoffset; /* offset into source or history file */
+ Namval_t *nspace; /* pointer to name space */
+ char *fname; /* file name where function defined */
+ char *help; /* help string */
+ Dt_t *sdict; /* dictionary for statics */
+ Dt_t *fdict; /* dictionary node belongs to */
+ Namval_t *np; /* function node pointer */
+};
+
+#ifndef ARG_RAW
+ struct argnod;
+#endif /* !ARG_RAW */
+
+/* attributes of Namval_t items */
+
+/* The following attributes are for internal use */
+#define NV_NOCHANGE (NV_EXPORT|NV_IMPORT|NV_RDONLY|NV_TAGGED|NV_NOFREE|NV_ARRAY)
+#define NV_ATTRIBUTES (~(NV_NOSCOPE|NV_ARRAY|NV_NOARRAY|NV_IDENT|NV_ASSIGN|NV_REF|NV_VARNAME|NV_STATIC))
+#define NV_PARAM NV_NODISC /* expansion use positional params */
+
+/* This following are for use with nodes which are not name-values */
+#define NV_TYPE 0x1000000
+#define NV_STATIC 0x2000000
+#define NV_COMVAR 0x4000000
+#define NV_UNJUST 0x8000000 /* clear justify attributes */
+#define NV_FUNCTION (NV_RJUST|NV_FUNCT) /* value is shell function */
+#define NV_FPOSIX NV_LJUST /* posix function semantics */
+#define NV_FTMP NV_ZFILL /* function source in tmpfile */
+#define NV_STATICF NV_INTEGER /* static class function */
+
+#define NV_NOPRINT (NV_LTOU|NV_UTOL) /* do not print */
+#define NV_NOALIAS (NV_NOPRINT|NV_IMPORT)
+#define NV_NOEXPAND NV_RJUST /* do not expand alias */
+#define NV_BLTIN (NV_NOPRINT|NV_EXPORT)
+#define BLT_ENV (NV_RDONLY) /* non-stoppable,
+ * can modify enviornment */
+#define BLT_SPC (NV_LJUST) /* special built-ins */
+#define BLT_EXIT (NV_RJUST) /* exit value can be > 255 */
+#define BLT_DCL (NV_TAGGED) /* declaration command */
+#define BLT_NOSFIO (NV_IMPORT) /* doesn't use sfio */
+#define NV_OPTGET (NV_BINARY) /* function calls getopts */
+#define nv_isref(n) (nv_isattr((n),NV_REF|NV_TAGGED|NV_FUNCT)==NV_REF)
+#define is_abuiltin(n) (nv_isattr(n,NV_BLTIN|NV_INTEGER)==NV_BLTIN)
+#define is_afunction(n) (nv_isattr(n,NV_FUNCTION|NV_REF)==NV_FUNCTION)
+#define nv_funtree(n) ((n)->nvalue.rp->ptree)
+#define funptr(n) ((n)->nvalue.bfp)
+
+#define NV_SUBQUOTE (NV_ADD<<1) /* used with nv_endsubscript */
+
+/* NAMNOD MACROS */
+/* ... for attributes */
+
+#define nv_setattr(n,f) ((n)->nvflag = (f))
+#define nv_context(n) ((void*)(n)->nvfun) /* for builtins */
+/* The following are for name references */
+#define nv_refnode(n) ((n)->nvalue.nrp->np)
+#define nv_reftree(n) ((n)->nvalue.nrp->root)
+#define nv_reftable(n) ((n)->nvalue.nrp->table)
+#define nv_refsub(n) ((n)->nvalue.nrp->sub)
+#if SHOPT_FIXEDARRAY
+# define nv_refindex(n) ((n)->nvalue.nrp->curi)
+# define nv_refdimen(n) ((n)->nvalue.nrp->dim)
+#endif /* SHOPT_FIXEDARRAY */
+
+/* ... etc */
+
+#define nv_setsize(n,s) ((n)->nvsize = (s))
+#undef nv_size
+#define nv_size(np) ((np)->nvsize)
+#define _nv_hasget(np) ((np)->nvfun && (np)->nvfun->disc && nv_hasget(np))
+#define nv_isnull(np) (!(np)->nvalue.cp && (nv_isattr(np,NV_SHORT|NV_INTEGER)!=(NV_SHORT|NV_INTEGER)) && !_nv_hasget(np))
+
+/* ... for arrays */
+
+#define array_elem(ap) ((ap)->nelem&ARRAY_MASK)
+#define array_assoc(ap) ((ap)->fun)
+
+extern int array_maxindex(Namval_t*);
+extern char *nv_endsubscript(Namval_t*, char*, int);
+extern Namfun_t *nv_cover(Namval_t*);
+extern Namarr_t *nv_arrayptr(Namval_t*);
+extern int nv_arrayisset(Namval_t*, Namarr_t*);
+extern int nv_arraysettype(Namval_t*, Namval_t*,const char*,int);
+extern int nv_aimax(Namval_t*);
+extern int nv_atypeindex(Namval_t*, const char*);
+extern int nv_setnotify(Namval_t*,char **);
+extern int nv_unsetnotify(Namval_t*,char **);
+extern void nv_setlist(struct argnod*, int, Namval_t*);
+extern struct argnod* nv_onlist(struct argnod*, const char*);
+extern void nv_optimize(Namval_t*);
+extern void nv_outname(Sfio_t*,char*, int);
+extern void nv_unref(Namval_t*);
+extern void _nv_unset(Namval_t*,int);
+extern int nv_hasget(Namval_t*);
+extern int nv_clone(Namval_t*, Namval_t*, int);
+void clone_all_disc(Namval_t*, Namval_t*, int);
+extern Namfun_t *nv_clone_disc(Namfun_t*, int);
+extern void *nv_diropen(Namval_t*, const char*);
+extern char *nv_dirnext(void*);
+extern void nv_dirclose(void*);
+extern char *nv_getvtree(Namval_t*, Namfun_t*);
+extern void nv_attribute(Namval_t*, Sfio_t*, char*, int);
+extern Namval_t *nv_bfsearch(const char*, Dt_t*, Namval_t**, char**);
+extern Namval_t *nv_mkclone(Namval_t*);
+extern Namval_t *nv_mktype(Namval_t**, int);
+extern Namval_t *nv_addnode(Namval_t*, int);
+extern Namval_t *nv_parent(Namval_t*);
+extern char *nv_getbuf(size_t);
+extern Namval_t *nv_mount(Namval_t*, const char *name, Dt_t*);
+extern Namval_t *nv_arraychild(Namval_t*, Namval_t*, int);
+extern int nv_compare(Dt_t*, Void_t*, Void_t*, Dtdisc_t*);
+extern void nv_outnode(Namval_t*,Sfio_t*, int, int);
+extern int nv_subsaved(Namval_t*);
+extern void nv_typename(Namval_t*, Sfio_t*);
+extern void nv_newtype(Namval_t*);
+extern int nv_istable(Namval_t*);
+extern size_t nv_datasize(Namval_t*, size_t*);
+extern Namfun_t *nv_mapchar(Namval_t*, const char*);
+#if SHOPT_FIXEDARRAY
+ extern int nv_arrfixed(Namval_t*, Sfio_t*, int, char*);
+#endif /* SHOPT_FIXEDARRAY */
+
+extern const Namdisc_t RESTRICTED_disc;
+extern const Namdisc_t ENUM_disc;
+extern char nv_local;
+extern Dtdisc_t _Nvdisc;
+extern const char *nv_discnames[];
+extern const char e_subscript[];
+extern const char e_nullset[];
+extern const char e_notset[];
+extern const char e_noparent[];
+extern const char e_notelem[];
+extern const char e_readonly[];
+extern const char e_badfield[];
+extern const char e_restricted[];
+extern const char e_ident[];
+extern const char e_varname[];
+extern const char e_noalias[];
+extern const char e_noarray[];
+extern const char e_notenum[];
+extern const char e_nounattr[];
+extern const char e_aliname[];
+extern const char e_badexport[];
+extern const char e_badref[];
+extern const char e_badsubscript[];
+extern const char e_noref[];
+extern const char e_selfref[];
+extern const char e_staticfun[];
+extern const char e_envmarker[];
+extern const char e_badlocale[];
+extern const char e_loop[];
+extern const char e_redef[];
+extern const char e_required[];
+extern const char e_badappend[];
+extern const char e_unknowntype[];
+extern const char e_unknownmap[];
+extern const char e_mapchararg[];
+extern const char e_subcomvar[];
+extern const char e_badtypedef[];
+extern const char e_typecompat[];
+extern const char e_globalref[];
+extern const char e_tolower[];
+extern const char e_toupper[];
+#endif /* _NV_PRIVATE */
diff --git a/src/cmd/ksh93/include/national.h b/src/cmd/ksh93/include/national.h
new file mode 100644
index 0000000..4c1888b
--- /dev/null
+++ b/src/cmd/ksh93/include/national.h
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * national.h - definitions for multibyte character sets
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#if SHOPT_MULTIBYTE
+
+# ifndef MARKER
+# define MARKER 0xdfff /* Must be invalid character */
+# endif
+
+ extern int sh_strchr(const char*,const char*);
+
+#endif /* SHOPT_MULTIBYTE */
diff --git a/src/cmd/ksh93/include/nval.h b/src/cmd/ksh93/include/nval.h
new file mode 100644
index 0000000..6d8a503
--- /dev/null
+++ b/src/cmd/ksh93/include/nval.h
@@ -0,0 +1,311 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef NV_DEFAULT
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * Interface definitions of structures for name-value pairs
+ * These structures are used for named variables, functions and aliases
+ *
+ */
+
+
+#include <ast.h>
+#include <cdt.h>
+#include <option.h>
+
+/* for compatibility with old hash library */
+#define Hashtab_t Dt_t
+#define HASH_BUCKET 1
+#define HASH_NOSCOPE 2
+#define HASH_SCOPE 4
+#define hashscope(x) dtvnext(x)
+
+typedef struct Namval Namval_t;
+typedef struct Namfun Namfun_t;
+typedef struct Namdisc Namdisc_t;
+typedef struct Nambfun Nambfun_t;
+typedef struct Namarray Namarr_t;
+typedef struct Namdecl Namdecl_t;
+
+/*
+ * This defines the template for nodes that have their own assignment
+ * and or lookup functions
+ */
+struct Namdisc
+{
+ size_t dsize;
+ void (*putval)(Namval_t*, const char*, int, Namfun_t*);
+ char *(*getval)(Namval_t*, Namfun_t*);
+ Sfdouble_t (*getnum)(Namval_t*, Namfun_t*);
+ char *(*setdisc)(Namval_t*, const char*, Namval_t*, Namfun_t*);
+ Namval_t *(*createf)(Namval_t*, const char*, int, Namfun_t*);
+ Namfun_t *(*clonef)(Namval_t*, Namval_t*, int, Namfun_t*);
+ char *(*namef)(Namval_t*, Namfun_t*);
+ Namval_t *(*nextf)(Namval_t*, Dt_t*, Namfun_t*);
+ Namval_t *(*typef)(Namval_t*, Namfun_t*);
+ int (*readf)(Namval_t*, Sfio_t*, int, Namfun_t*);
+ int (*writef)(Namval_t*, Sfio_t*, int, Namfun_t*);
+};
+
+struct Namfun
+{
+ const Namdisc_t *disc;
+ char nofree;
+ unsigned char subshell;
+ unsigned short dsize;
+ Namfun_t *next;
+ char *last;
+ Namval_t *type;
+};
+
+struct Nambfun
+{
+ Namfun_t fun;
+ int num;
+ const char **bnames;
+ Namval_t *bltins[1];
+};
+
+/* This is an array template header */
+struct Namarray
+{
+ Namfun_t hdr;
+ long nelem; /* number of elements */
+ void *(*fun)(Namval_t*,const char*,int); /* associative arrays */
+ void *fixed; /* for fixed sized arrays */
+ Dt_t *table; /* for subscripts */
+ void *scope; /* non-zerp when scoped */
+};
+
+/* The context pointer for declaration command */
+struct Namdecl
+{
+ Namval_t *tp; /* point to type */
+ const char *optstring;
+ void *optinfof;
+};
+
+/* attributes of name-value node attribute flags */
+
+#define NV_DEFAULT 0
+/* This defines the attributes for an attributed name-value pair node */
+struct Namval
+{
+ Dtlink_t nvlink; /* space for cdt links */
+ char *nvname; /* pointer to name of the node */
+ unsigned short nvflag; /* attributes */
+ unsigned short nvsize; /* size or base */
+#ifdef _NV_PRIVATE
+ _NV_PRIVATE
+#else
+ Namfun_t *nvfun;
+ char *nvalue;
+ char *nvprivate;
+#endif /* _NV_PRIVATE */
+};
+
+#define NV_CLASS ".sh.type"
+#define NV_DATA "_" /* special class or instance variable */
+#define NV_MINSZ (sizeof(struct Namval)-sizeof(Dtlink_t)-sizeof(char*))
+#define nv_namptr(p,n) ((Namval_t*)((char*)(p)+(n)*NV_MINSZ-sizeof(Dtlink_t)))
+
+/* The following attributes are for internal use */
+#define NV_NOFREE 0x200 /* don't free the space when releasing value */
+#define NV_ARRAY 0x400 /* node is an array */
+#define NV_REF 0x4000 /* reference bit */
+#define NV_TABLE 0x800 /* node is a dictionary table */
+#define NV_IMPORT 0x1000 /* value imported from environment */
+#define NV_MINIMAL NV_IMPORT /* node does not contain all fields */
+
+#define NV_INTEGER 0x2 /* integer attribute */
+/* The following attributes are valid only when NV_INTEGER is off */
+#define NV_LTOU 0x4 /* convert to uppercase */
+#define NV_UTOL 0x8 /* convert to lowercase */
+#define NV_ZFILL 0x10 /* right justify and fill with leading zeros */
+#define NV_RJUST 0x20 /* right justify and blank fill */
+#define NV_LJUST 0x40 /* left justify and blank fill */
+#define NV_BINARY 0x100 /* fixed size data buffer */
+#define NV_RAW NV_LJUST /* used only with NV_BINARY */
+#define NV_HOST (NV_RJUST|NV_LJUST) /* map to host filename */
+
+/* The following attributes do not effect the value */
+#define NV_RDONLY 0x1 /* readonly bit */
+#define NV_EXPORT 0x2000 /* export bit */
+#define NV_TAGGED 0x8000 /* user define tag bit */
+
+/* The following are used with NV_INTEGER */
+#define NV_SHORT (NV_RJUST) /* when integers are not long */
+#define NV_LONG (NV_UTOL) /* for long long and long double */
+#define NV_UNSIGN (NV_LTOU) /* for unsigned quantities */
+#define NV_DOUBLE (NV_INTEGER|NV_ZFILL) /* for floating point */
+#define NV_EXPNOTE (NV_LJUST) /* for scientific notation */
+#define NV_HEXFLOAT (NV_LTOU) /* for C99 base16 float notation */
+
+/* options for nv_open */
+
+#define NV_APPEND 0x10000 /* append value */
+#define NV_MOVE 0x8000000 /* for use with nv_clone */
+#define NV_ADD 8
+ /* add node if not found */
+#define NV_ASSIGN NV_NOFREE /* assignment is possible */
+#define NV_NOASSIGN 0 /* backward compatibility */
+#define NV_NOARRAY 0x200000 /* array name not possible */
+#define NV_IARRAY 0x400000 /* for indexed array */
+#define NV_NOREF NV_REF /* don't follow reference */
+#define NV_IDENT 0x80 /* name must be identifier */
+#define NV_VARNAME 0x20000 /* name must be ?(.)id*(.id) */
+#define NV_NOADD 0x40000 /* do not add node */
+#define NV_NOSCOPE 0x80000 /* look only in current scope */
+#define NV_NOFAIL 0x100000 /* return 0 on failure, no msg */
+#define NV_NODISC NV_IDENT /* ignore disciplines */
+
+#define NV_FUNCT NV_IDENT /* option for nv_create */
+#define NV_BLTINOPT NV_ZFILL /* mark builtins in libcmd */
+
+#define NV_PUBLIC (~(NV_NOSCOPE|NV_ASSIGN|NV_IDENT|NV_VARNAME|NV_NOADD))
+
+/* numeric types */
+#define NV_INT16P (NV_LJUST|NV_SHORT|NV_INTEGER)
+#define NV_INT16 (NV_SHORT|NV_INTEGER)
+#define NV_UINT16 (NV_UNSIGN|NV_SHORT|NV_INTEGER)
+#define NV_UINT16P (NV_LJUSTNV_UNSIGN|NV_SHORT|NV_INTEGER)
+#define NV_INT32 (NV_INTEGER)
+#define NV_UNT32 (NV_UNSIGN|NV_INTEGER)
+#define NV_INT64 (NV_LONG|NV_INTEGER)
+#define NV_UINT64 (NV_UNSIGN|NV_LONG|NV_INTEGER)
+#define NV_FLOAT (NV_SHORT|NV_DOUBLE)
+#define NV_LDOUBLE (NV_LONG|NV_DOUBLE)
+
+/* name-value pair macros */
+#define nv_isattr(np,f) ((np)->nvflag & (f))
+#define nv_onattr(n,f) ((n)->nvflag |= (f))
+#define nv_offattr(n,f) ((n)->nvflag &= ~(f))
+#define nv_isarray(np) (nv_isattr((np),NV_ARRAY))
+
+/* The following are operations for associative arrays */
+#define NV_AINIT 1 /* initialize */
+#define NV_AFREE 2 /* free array */
+#define NV_ANEXT 3 /* advance to next subscript */
+#define NV_ANAME 4 /* return subscript name */
+#define NV_ADELETE 5 /* delete current subscript */
+#define NV_AADD 6 /* add subscript if not found */
+#define NV_ACURRENT 7 /* return current subscript Namval_t* */
+#define NV_ASETSUB 8 /* set current subscript */
+
+/* The following are for nv_disc */
+#define NV_FIRST 1
+#define NV_LAST 2
+#define NV_POP 3
+#define NV_CLONE 4
+
+/* The following are operations for nv_putsub() */
+#define ARRAY_BITS 22
+#define ARRAY_ADD (1L<<ARRAY_BITS) /* add subscript if not found */
+#define ARRAY_SCAN (2L<<ARRAY_BITS) /* For ${array[@]} */
+#define ARRAY_UNDEF (4L<<ARRAY_BITS) /* For ${array} */
+
+
+/* These are disciplines provided by the library for use with nv_discfun */
+#define NV_DCADD 0 /* used to add named disciplines */
+#define NV_DCRESTRICT 1 /* variable that are restricted in rsh */
+
+#if defined(__EXPORT__) && defined(_DLL)
+# ifdef _BLD_shell
+# define extern __EXPORT__
+# else
+# define extern __IMPORT__
+# endif /* _BLD_shell */
+#endif /* _DLL */
+/* prototype for array interface*/
+extern Namarr_t *nv_arrayptr(Namval_t*);
+extern Namarr_t *nv_setarray(Namval_t*,void*(*)(Namval_t*,const char*,int));
+extern int nv_arraynsub(Namarr_t*);
+extern void *nv_associative(Namval_t*,const char*,int);
+extern int nv_aindex(Namval_t*);
+extern int nv_nextsub(Namval_t*);
+extern char *nv_getsub(Namval_t*);
+extern Namval_t *nv_putsub(Namval_t*, char*, long);
+extern Namval_t *nv_opensub(Namval_t*);
+
+/* name-value pair function prototypes */
+extern int nv_adddisc(Namval_t*, const char**, Namval_t**);
+extern int nv_clone(Namval_t*, Namval_t*, int);
+extern void nv_close(Namval_t*);
+extern void *nv_context(Namval_t*);
+extern Namval_t *nv_create(const char*, Dt_t*, int,Namfun_t*);
+extern void nv_delete(Namval_t*, Dt_t*, int);
+extern Dt_t *nv_dict(Namval_t*);
+extern Sfdouble_t nv_getn(Namval_t*, Namfun_t*);
+extern Sfdouble_t nv_getnum(Namval_t*);
+extern char *nv_getv(Namval_t*, Namfun_t*);
+extern char *nv_getval(Namval_t*);
+extern Namfun_t *nv_hasdisc(Namval_t*, const Namdisc_t*);
+extern int nv_isnull(Namval_t*);
+extern Namfun_t *nv_isvtree(Namval_t*);
+extern Namval_t *nv_lastdict(void);
+extern Namval_t *nv_mkinttype(char*, size_t, int, const char*, Namdisc_t*);
+extern void nv_newattr(Namval_t*,unsigned,int);
+extern void nv_newtype(Namval_t*);
+extern Namval_t *nv_open(const char*,Dt_t*,int);
+extern void nv_putval(Namval_t*,const char*,int);
+extern void nv_putv(Namval_t*,const char*,int,Namfun_t*);
+extern int nv_rename(Namval_t*,int);
+extern int nv_scan(Dt_t*,void(*)(Namval_t*,void*),void*,int,int);
+extern char *nv_setdisc(Namval_t*,const char*,Namval_t*,Namfun_t*);
+extern void nv_setref(Namval_t*, Dt_t*,int);
+extern int nv_settype(Namval_t*, Namval_t*, int);
+extern void nv_setvec(Namval_t*,int,int,char*[]);
+extern void nv_setvtree(Namval_t*);
+extern int nv_setsize(Namval_t*,int);
+extern Namfun_t *nv_disc(Namval_t*,Namfun_t*,int);
+extern void nv_unset(Namval_t*); /*obsolete */
+extern void _nv_unset(Namval_t*,int);
+extern Namval_t *nv_search(const char *, Dt_t*, int);
+extern char *nv_name(Namval_t*);
+extern Namval_t *nv_type(Namval_t*);
+extern void nv_addtype(Namval_t*,const char*, Optdisc_t*, size_t);
+extern const Namdisc_t *nv_discfun(int);
+
+#ifdef _DLL
+# undef extern
+#endif /* _DLL */
+
+#define nv_unset(np) _nv_unset(np,0)
+#define nv_size(np) nv_setsize((np),-1)
+#define nv_stack(np,nf) nv_disc(np,nf,0)
+
+#if 0
+/*
+ * The names of many functions were changed in early '95
+ * Here is a mapping to the old names
+ */
+# define nv_istype(np) nv_isattr(np)
+# define nv_newtype(np) nv_newattr(np)
+# define nv_namset(np,a,b) nv_open(np,a,b)
+# define nv_free(np) nv_unset(np,0)
+# define nv_settype(np,a,b,c) nv_setdisc(np,a,b,c)
+# define nv_search(np,a,b) nv_open(np,a,((b)?0:NV_NOADD))
+# define settype setdisc
+#endif
+
+#endif /* NV_DEFAULT */
diff --git a/src/cmd/ksh93/include/path.h b/src/cmd/ksh93/include/path.h
new file mode 100644
index 0000000..f15dc4c
--- /dev/null
+++ b/src/cmd/ksh93/include/path.h
@@ -0,0 +1,147 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef PATH_OFFSET
+
+/*
+ * UNIX shell path handling interface
+ * Written by David Korn
+ * These are the definitions for the lexical analyzer
+ */
+
+#include "FEATURE/options"
+#include <nval.h>
+#include "defs.h"
+
+#if !defined(SHOPT_SPAWN)
+# if _UWIN || _use_spawnveg || !_lib_fork
+# define SHOPT_SPAWN 1
+# endif
+#endif /* !SHOPT_SPAWN */
+
+#define PATH_PATH 0001
+#define PATH_FPATH 0002
+#define PATH_CDPATH 0004
+#define PATH_BFPATH 0010
+#define PATH_SKIP 0020
+#define PATH_BUILTIN_LIB 0040
+#define PATH_STD_DIR 0100 /* directory is on $(getconf PATH) */
+
+#define PATH_OFFSET 2 /* path offset for path_join */
+#define MAXDEPTH (sizeof(char*)==2?64:1024) /* maximum recursion depth*/
+
+/*
+ * path component structure for path searching
+ */
+typedef struct pathcomp
+{
+ struct pathcomp *next;
+ int refcount;
+ dev_t dev;
+ ino_t ino;
+ time_t mtime;
+ char *name;
+ char *lib;
+ char *blib;
+ void *bltin_lib;
+ unsigned short len;
+ unsigned short flags;
+ Shell_t *shp;
+} Pathcomp_t;
+
+#ifndef ARG_RAW
+ struct argnod;
+#endif /* !ARG_RAW */
+
+/* pathname handling routines */
+extern void path_newdir(Shell_t*,Pathcomp_t*);
+extern Pathcomp_t *path_dirfind(Pathcomp_t*,const char*,int);
+extern Pathcomp_t *path_unsetfpath(Shell_t*);
+extern Pathcomp_t *path_addpath(Shell_t*,Pathcomp_t*,const char*,int);
+extern Pathcomp_t *path_dup(Pathcomp_t*);
+extern void path_delete(Pathcomp_t*);
+extern void path_alias(Namval_t*,Pathcomp_t*);
+extern Pathcomp_t *path_absolute(Shell_t*, const char*, Pathcomp_t*);
+extern char *path_basename(const char*);
+extern char *path_fullname(Shell_t*,const char*);
+extern int path_expand(Shell_t*,const char*, struct argnod**);
+extern void path_exec(Shell_t*,const char*,char*[],struct argnod*);
+extern pid_t path_spawn(Shell_t*,const char*,char*[],char*[],Pathcomp_t*,int);
+#if defined(__EXPORT__) && defined(_BLD_DLL) && defined(_BLD_shell)
+# define extern __EXPORT__
+#endif
+extern int path_open(Shell_t*,const char*,Pathcomp_t*);
+extern Pathcomp_t *path_get(Shell_t*,const char*);
+#undef extern
+extern char *path_pwd(Shell_t*,int);
+extern Pathcomp_t *path_nextcomp(Shell_t*,Pathcomp_t*,const char*,Pathcomp_t*);
+extern int path_search(Shell_t*,const char*,Pathcomp_t**,int);
+extern char *path_relative(Shell_t*,const char*);
+extern int path_complete(Shell_t*,const char*, const char*,struct argnod**);
+#if SHOPT_BRACEPAT
+ extern int path_generate(Shell_t*,struct argnod*,struct argnod**);
+#endif /* SHOPT_BRACEPAT */
+#if SHOPT_PFSH
+ extern int path_xattr(Shell_t*, const char*, char*);
+#endif /* SHOPT_PFSH */
+
+/* constant strings needed for whence */
+extern const char e_timeformat[];
+extern const char e_badtformat[];
+extern const char e_dot[];
+extern const char e_funload[];
+extern const char e_pfsh[];
+extern const char e_pwd[];
+extern const char e_logout[];
+extern const char e_alphanum[];
+extern const char e_mailmsg[];
+extern const char e_suidprofile[];
+extern const char e_sysprofile[];
+extern const char e_traceprompt[];
+extern const char e_crondir[];
+#if SHOPT_SUID_EXEC
+ extern const char e_suidexec[];
+#endif /* SHOPT_SUID_EXEC */
+extern const char is_alias[];
+extern const char is_builtin[];
+extern const char is_spcbuiltin[];
+extern const char is_builtver[];
+extern const char is_reserved[];
+extern const char is_talias[];
+extern const char is_xalias[];
+extern const char is_function[];
+extern const char is_ufunction[];
+#ifdef SHELLMAGIC
+ extern const char e_prohibited[];
+#endif /* SHELLMAGIC */
+
+#if SHOPT_ACCT
+# include "FEATURE/acct"
+# ifdef _sys_acct
+ extern void sh_accinit(void);
+ extern void sh_accbegin(const char*);
+ extern void sh_accend(void);
+ extern void sh_accsusp(void);
+# else
+# undef SHOPT_ACCT
+# endif /* _sys_acct */
+#endif /* SHOPT_ACCT */
+
+#endif /*! PATH_OFFSET */
diff --git a/src/cmd/ksh93/include/regress.h b/src/cmd/ksh93/include/regress.h
new file mode 100644
index 0000000..83c1824
--- /dev/null
+++ b/src/cmd/ksh93/include/regress.h
@@ -0,0 +1,66 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * Shell interface private definitions
+ *
+ */
+
+#ifndef _REGRESS_H
+#define _REGRESS_H 1
+
+#if SHOPT_REGRESS
+
+typedef struct Regress_s
+{
+ Shopt_t options;
+} Regress_t;
+
+#define sh_isregress(r) is_option(&sh.regress->options,r)
+#define sh_onregress(r) on_option(&sh.regress->options,r)
+#define sh_offregress(r) off_option(&sh.regress->options,r)
+
+#define REGRESS(r,i,f) do { if (sh_isregress(REGRESS_##r)) sh_regress(REGRESS_##r, i, sfprints f, __LINE__, __FILE__); } while (0)
+
+#define REGRESS_egid 1
+#define REGRESS_euid 2
+#define REGRESS_p_suid 3
+#define REGRESS_source 4
+#define REGRESS_etc 5
+
+#undef SHOPT_P_SUID
+#define SHOPT_P_SUID sh_regress_p_suid(__LINE__, __FILE__)
+
+extern int b___regress__(int, char**, Shbltin_t*);
+extern void sh_regress_init(Shell_t*);
+extern void sh_regress(unsigned int, const char*, const char*, unsigned int, const char*);
+extern uid_t sh_regress_p_suid(unsigned int, const char*);
+extern char* sh_regress_etc(const char*, unsigned int, const char*);
+
+#else
+
+#define REGRESS(r,i,f)
+
+#endif /* SHOPT_REGRESS */
+
+#endif /* _REGRESS_H */
diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h
new file mode 100644
index 0000000..ac80629
--- /dev/null
+++ b/src/cmd/ksh93/include/shell.h
@@ -0,0 +1,259 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef SH_INTERACTIVE
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * Interface definitions for shell command language
+ *
+ */
+
+#define SH_VERSION 20071012
+
+#include <ast.h>
+#include <cdt.h>
+#ifdef _SH_PRIVATE
+# include "name.h"
+#else
+# include <nval.h>
+#endif /* _SH_PRIVATE */
+
+#undef NOT_USED
+#define NOT_USED(x) (&x,1)
+
+/* options */
+typedef struct
+{
+ unsigned long v[4];
+}
+Shopt_t;
+
+typedef struct Shell_s Shell_t;
+
+#include <shcmd.h>
+
+typedef void (*Shinit_f)(Shell_t*, int);
+#ifndef SH_wait_f_defined
+ typedef int (*Shwait_f)(int, long, int);
+# define SH_wait_f_defined
+#endif
+
+union Shnode_u;
+typedef union Shnode_u Shnode_t;
+
+#define SH_CFLAG 0
+#define SH_HISTORY 1 /* used also as a state */
+#define SH_ERREXIT 2 /* used also as a state */
+#define SH_VERBOSE 3 /* used also as a state */
+#define SH_MONITOR 4 /* used also as a state */
+#define SH_INTERACTIVE 5 /* used also as a state */
+#define SH_RESTRICTED 6
+#define SH_XTRACE 7
+#define SH_KEYWORD 8
+#define SH_NOUNSET 9
+#define SH_NOGLOB 10
+#define SH_ALLEXPORT 11
+#define SH_PFSH 12
+#define SH_IGNOREEOF 13
+#define SH_NOCLOBBER 14
+#define SH_MARKDIRS 15
+#define SH_BGNICE 16
+#define SH_VI 17
+#define SH_VIRAW 18
+#define SH_TFLAG 19
+#define SH_TRACKALL 20
+#define SH_SFLAG 21
+#define SH_NOEXEC 22
+#define SH_GMACS 24
+#define SH_EMACS 25
+#define SH_PRIVILEGED 26
+#define SH_SUBSHARE 27 /* subshell shares state with parent */
+#define SH_NOLOG 28
+#define SH_NOTIFY 29
+#define SH_DICTIONARY 30
+#define SH_PIPEFAIL 32
+#define SH_GLOBSTARS 33
+#define SH_XARGS 34
+#define SH_RC 35
+#define SH_SHOWME 36
+#define SH_LETOCTAL 37
+
+/*
+ * passed as flags to builtins in Nambltin_t struct when BLT_OPTIM is on
+ */
+#define SH_BEGIN_OPTIM 0x1
+#define SH_END_OPTIM 0x2
+
+/* The following type is used for error messages */
+
+/* error messages */
+extern const char e_defpath[];
+extern const char e_found[];
+extern const char e_nospace[];
+extern const char e_format[];
+extern const char e_number[];
+extern const char e_restricted[];
+extern const char e_recursive[];
+extern char e_version[];
+
+typedef struct sh_scope
+{
+ struct sh_scope *par_scope;
+ int argc;
+ char **argv;
+ char *cmdname;
+ char *filename;
+ char *funname;
+ int lineno;
+ Dt_t *var_tree;
+ struct sh_scope *self;
+} Shscope_t;
+
+/*
+ * Saves the state of the shell
+ */
+
+struct Shell_s
+{
+ Shopt_t options; /* set -o options */
+ Dt_t *var_tree; /* for shell variables */
+ Dt_t *fun_tree; /* for shell functions */
+ Dt_t *alias_tree; /* for alias names */
+ Dt_t *bltin_tree; /* for builtin commands */
+ Shscope_t *topscope; /* pointer to top-level scope */
+ int inlineno; /* line number of current input file */
+ int exitval; /* most recent exit value */
+ unsigned char trapnote; /* set when trap/signal is pending */
+ char shcomp; /* set when runing shcomp */
+ short subshell; /* set for virtual subshell */
+#ifdef _SH_PRIVATE
+ _SH_PRIVATE
+#endif /* _SH_PRIVATE */
+};
+
+/* flags for sh_parse */
+#define SH_NL 1 /* Treat new-lines as ; */
+#define SH_EOF 2 /* EOF causes syntax error */
+
+/* symbolic values for sh_iogetiop */
+#define SH_IOCOPROCESS (-2)
+#define SH_IOHISTFILE (-3)
+
+#include <cmd.h>
+
+/* symbolic value for sh_fdnotify */
+#define SH_FDCLOSE (-1)
+
+#undef getenv /* -lshell provides its own */
+
+#if defined(__EXPORT__) && defined(_DLL)
+# ifdef _BLD_shell
+# define extern __EXPORT__
+# endif /* _BLD_shell */
+#endif /* _DLL */
+
+extern Dt_t *sh_bltin_tree(void);
+extern void sh_subfork(void);
+extern Shell_t *sh_init(int,char*[],Shinit_f);
+extern int sh_reinit(char*[]);
+extern int sh_eval(Sfio_t*,int);
+extern void sh_delay(double);
+extern void *sh_parse(Shell_t*, Sfio_t*,int);
+extern int sh_trap(const char*,int);
+extern int sh_fun(Namval_t*,Namval_t*, char*[]);
+extern int sh_funscope(int,char*[],int(*)(void*),void*,int);
+extern Sfio_t *sh_iogetiop(int,int);
+extern int sh_main(int, char*[], Shinit_f);
+extern int sh_run(int, char*[]);
+extern void sh_menu(Sfio_t*, int, char*[]);
+extern Namval_t *sh_addbuiltin(const char*, int(*)(int, char*[],Shbltin_t*), void*);
+extern char *sh_fmtq(const char*);
+extern char *sh_fmtqf(const char*, int, int);
+extern Sfdouble_t sh_strnum(const char*, char**, int);
+extern int sh_access(const char*,int);
+extern int sh_close(int);
+extern int sh_dup(int);
+extern void sh_exit(int);
+extern int sh_fcntl(int, int, ...);
+extern Sfio_t *sh_fd2sfio(int);
+extern int (*sh_fdnotify(int(*)(int,int)))(int,int);
+extern Shell_t *sh_getinterp(void);
+extern int sh_open(const char*, int, ...);
+extern int sh_openmax(void);
+extern Sfio_t *sh_pathopen(const char*);
+extern ssize_t sh_read(int, void*, size_t);
+extern ssize_t sh_write(int, const void*, size_t);
+extern off_t sh_seek(int, off_t, int);
+extern int sh_pipe(int[]);
+extern mode_t sh_umask(mode_t);
+extern void *sh_waitnotify(Shwait_f);
+extern Shscope_t *sh_getscope(int,int);
+extern Shscope_t *sh_setscope(Shscope_t*);
+extern void sh_sigcheck(void);
+extern unsigned long sh_isoption(int);
+extern unsigned long sh_onoption(int);
+extern unsigned long sh_offoption(int);
+extern int sh_waitsafe(void);
+extern int sh_exec(const Shnode_t*,int);
+
+#if SHOPT_DYNAMIC
+ extern void **sh_getliblist(void);
+#endif /* SHOPT_DYNAMIC */
+
+/*
+ * direct access to sh is obsolete, use sh_getinterp() instead
+ */
+#if !defined(_SH_PRIVATE) && defined(__IMPORT__) && !defined(_BLD_shell)
+ extern __IMPORT__ Shell_t sh;
+#else
+ extern Shell_t sh;
+#endif
+
+#ifdef _DLL
+# undef extern
+#endif /* _DLL */
+
+#ifndef _SH_PRIVATE
+# define access(a,b) sh_access(a,b)
+# define close(a) sh_close(a)
+# define exit(a) sh_exit(a)
+# define fcntl(a,b,c) sh_fcntl(a,b,c)
+# define pipe(a) sh_pipe(a)
+# define read(a,b,c) sh_read(a,b,c)
+# define write(a,b,c) sh_write(a,b,c)
+# define umask(a) sh_umask(a)
+# define dup sh_dup
+# if _lib_lseek64
+# define open64 sh_open
+# define lseek64 sh_seek
+# else
+# define open sh_open
+# define lseek sh_seek
+# endif
+#endif /* !_SH_PRIVATE */
+
+#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 /* SH_INTERACTIVE */
diff --git a/src/cmd/ksh93/include/shlex.h b/src/cmd/ksh93/include/shlex.h
new file mode 100644
index 0000000..b8e5034
--- /dev/null
+++ b/src/cmd/ksh93/include/shlex.h
@@ -0,0 +1,171 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef NOTSYM
+/*
+ * UNIX shell
+ * Written by David Korn
+ * These are the definitions for the lexical analyzer
+ */
+
+#include <cdt.h>
+#include "FEATURE/options"
+#include "shnodes.h"
+#include "shtable.h"
+#include "lexstates.h"
+
+
+typedef struct _shlex_
+{
+ Shell_t *sh; /* pointer to the interpreter */
+ struct argnod *arg; /* current word */
+ struct ionod *heredoc; /* pending here document list */
+ int token; /* current token number */
+ int lastline; /* last line number */
+ int lasttok; /* previous token number */
+ int digits; /* numerical value with word token */
+ int nonstandard; /* nonstandard construct in profile */
+ char aliasok; /* on when alias is legal */
+ char assignok; /* on when name=value is legal */
+ char inexec; /* on when processing exec */
+ char intypeset; /* on when processing typeset */
+ char comp_assign; /* in compound assignment */
+ char comsub; /* parsing command substitution */
+ char noreserv; /* reserved works not legal */
+ int inlineno; /* saved value of sh.inlineno */
+ int firstline; /* saved value of sh.st.firstline */
+#if SHOPT_KIA
+ Sfio_t *kiafile; /* kia output file */
+ Sfio_t *kiatmp; /* kia reference file */
+ unsigned long script; /* script entity number */
+ unsigned long fscript; /* script file entity number */
+ unsigned long current; /* current entity number */
+ unsigned long unknown; /* <unknown> entity number */
+ off_t kiabegin; /* offset of first entry */
+ char *scriptname; /* name of script file */
+ Dt_t *entity_tree; /* for entity ids */
+#endif /* SHOPT_KIA */
+#ifdef _SHLEX_PRIVATE
+ _SHLEX_PRIVATE
+#endif
+} Lex_t;
+
+/* symbols for parsing */
+#define NL '\n'
+#define NOTSYM '!'
+#define SYMRES 0400 /* reserved word symbols */
+#define DOSYM (SYMRES|01)
+#define FISYM (SYMRES|02)
+#define ELIFSYM (SYMRES|03)
+#define ELSESYM (SYMRES|04)
+#define INSYM (SYMRES|05)
+#define THENSYM (SYMRES|06)
+#define DONESYM (SYMRES|07)
+#define ESACSYM (SYMRES|010)
+#define IFSYM (SYMRES|011)
+#define FORSYM (SYMRES|012)
+#define WHILESYM (SYMRES|013)
+#define UNTILSYM (SYMRES|014)
+#define CASESYM (SYMRES|015)
+#define FUNCTSYM (SYMRES|016)
+#define SELECTSYM (SYMRES|017)
+#define TIMESYM (SYMRES|020)
+#define NSPACESYM (SYMRES|021)
+
+#define SYMREP 01000 /* symbols for doubled characters */
+#define BREAKCASESYM (SYMREP|';')
+#define ANDFSYM (SYMREP|'&')
+#define ORFSYM (SYMREP|'|')
+#define IOAPPSYM (SYMREP|'>')
+#define IODOCSYM (SYMREP|'<')
+#define EXPRSYM (SYMREP|'(')
+#define BTESTSYM (SYMREP|'[')
+#define ETESTSYM (SYMREP|']')
+
+#define SYMMASK 0170000
+#define SYMPIPE 010000 /* trailing '|' */
+#define SYMLPAR 020000 /* trailing LPAREN */
+#define SYMAMP 040000 /* trailing '&' */
+#define SYMGT 0100000 /* trailing '>' */
+#define SYMSEMI 0110000 /* trailing ';' */
+#define SYMSHARP 0120000 /* trailing '#' */
+#define IOSEEKSYM (SYMSHARP|'<')
+#define IOMOV0SYM (SYMAMP|'<')
+#define IOMOV1SYM (SYMAMP|'>')
+#define FALLTHRUSYM (SYMAMP|';')
+#define COOPSYM (SYMAMP|'|')
+#define IORDWRSYM (SYMGT|'<')
+#define IORDWRSYMT (SYMSEMI|'<')
+#define IOCLOBSYM (SYMPIPE|'>')
+#define PIPESYM2 (SYMPIPE|'&')
+#define IPROCSYM (SYMLPAR|'<')
+#define OPROCSYM (SYMLPAR|'>')
+#define EOFSYM 04000 /* end-of-file */
+#define TESTUNOP 04001
+#define TESTBINOP 04002
+#define LABLSYM 04003
+#define IOVNAME 04004
+
+/* additional parser flag, others in <shell.h> */
+#define SH_EMPTY 04
+#define SH_NOIO 010
+#define SH_ASSIGN 020
+#define SH_FUNDEF 040
+#define SH_ARRAY 0100
+#define SH_SEMI 0200 /* semi-colon after NL ok */
+
+#define SH_COMPASSIGN 010 /* allow compound assignments only */
+
+#if 0
+typedef struct _shlex_
+{
+ struct shlex_t _shlex;
+#ifdef _SHLEX_PRIVATE
+ _SHLEX_PRIVATE
+#endif
+} Lex_t;
+
+#define shlex (((Lex_t*)(sh.lex_context))->_shlex)
+#endif
+extern const char e_unexpected[];
+extern const char e_unmatched[];
+extern const char e_endoffile[];
+extern const char e_newline[];
+
+/* odd chars */
+#define LBRACE '{'
+#define RBRACE '}'
+#define LPAREN '('
+#define RPAREN ')'
+#define LBRACT '['
+#define RBRACT ']'
+
+extern int sh_lex(Lex_t*);
+extern Shnode_t *sh_dolparen(Lex_t*);
+extern Lex_t *sh_lexopen(Lex_t*, Shell_t*, int);
+extern void sh_lexskip(Lex_t*,int,int,int);
+extern void sh_syntax(Lex_t*);
+#if SHOPT_KIA
+ extern int kiaclose(Lex_t *);
+ extern unsigned long kiaentity(Lex_t*, const char*,int,int,int,int,unsigned long,int,int,const char*);
+#endif /* SHOPT_KIA */
+
+
+#endif /* !NOTSYM */
diff --git a/src/cmd/ksh93/include/shnodes.h b/src/cmd/ksh93/include/shnodes.h
new file mode 100644
index 0000000..6e0eb55
--- /dev/null
+++ b/src/cmd/ksh93/include/shnodes.h
@@ -0,0 +1,221 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef _SHNODES_H
+#define _SHNODES_H 1
+/*
+ * UNIX shell
+ * Written by David Korn
+ *
+ */
+
+
+#include <ast.h>
+#include "argnod.h"
+
+/* command tree for tretyp */
+#define FINT (02<<COMBITS) /* non-interruptable */
+#define FAMP (04<<COMBITS) /* background */
+#define FPIN (010<<COMBITS) /* input is a pipe */
+#define FPOU (040<<COMBITS) /* output is a pipe */
+#define FPCL (0100<<COMBITS) /* close the pipe */
+#define FCOOP (0200<<COMBITS) /* cooperating process */
+#define FSHOWME (0400<<COMBITS) /* set for showme commands */
+#define FALTPIPE (02000<<COMBITS) /* alternate pipes &| */
+#define FPOSIX (02<<COMBITS) /* posix semantics function */
+#define FLINENO (04<<COMBITS) /* for/case has line number */
+#define FOPTGET (010<<COMBITS) /* function calls getopts */
+
+#define TNEGATE (01<<COMBITS) /* ! inside [[...]] */
+#define TBINARY (02<<COMBITS) /* binary operator in [[...]] */
+#define TUNARY (04<<COMBITS) /* unary operator in [[...]] */
+#define TTEST (010<<COMBITS)
+#define TPAREN (TBINARY|TUNARY)
+#define TSHIFT (COMBITS+4)
+#define TNSPACE (TFUN|COMSCAN)
+
+#define TCOM 0
+#define TPAR 1
+#define TFIL 2
+#define TLST 3
+#define TIF 4
+#define TWH 5
+#define TUN (TWH|COMSCAN)
+#define TTST 6
+#define TSW 7
+#define TAND 8
+#define TORF 9
+#define TFORK 10
+#define TFOR 11
+#define TSELECT (TFOR|COMSCAN)
+#define TARITH 12
+#define TTIME 13
+#define TSETIO 14
+#define TFUN 15
+
+/* this node is a proforma for those that follow */
+
+struct trenod
+{
+ int tretyp;
+ struct ionod *treio;
+};
+
+
+struct forknod
+{
+ int forktyp;
+ struct ionod *forkio;
+ Shnode_t *forktre;
+ int forkline;
+};
+
+
+struct ifnod
+{
+ int iftyp;
+ Shnode_t *iftre;
+ Shnode_t *thtre;
+ Shnode_t *eltre;
+};
+
+struct whnod
+{
+ int whtyp;
+ Shnode_t *whtre;
+ Shnode_t *dotre;
+ struct arithnod *whinc;
+};
+
+struct fornod
+{
+ int fortyp;
+ char *fornam;
+ Shnode_t *fortre;
+ struct comnod *forlst;
+ int forline;
+};
+
+struct swnod
+{
+ int swtyp;
+ struct argnod *swarg;
+ struct regnod *swlst;
+ struct ionod *swio;
+ int swline;
+};
+
+struct regnod
+{
+ struct argnod *regptr;
+ Shnode_t *regcom;
+ struct regnod *regnxt;
+ char regflag;
+};
+
+struct parnod
+{
+ int partyp;
+ Shnode_t *partre;
+};
+
+struct lstnod
+{
+ int lsttyp;
+ Shnode_t *lstlef;
+ Shnode_t *lstrit;
+};
+
+/* tst is same as lst, but with extra field for line number */
+struct tstnod
+{
+ struct lstnod tstlst;
+ int tstline;
+};
+
+struct functnod
+{
+ int functtyp;
+ char *functnam;
+ Shnode_t *functtre;
+ int functline;
+ off_t functloc;
+ struct slnod *functstak;
+ struct comnod *functargs;
+};
+
+struct arithnod
+{
+ int artyp;
+ int arline;
+ struct argnod *arexpr;
+ void *arcomp;
+};
+
+
+/* types of ionodes stored in iofile */
+#define IOUFD 0x3f /* file descriptor number mask */
+#define IOPUT 0x40 /* > redirection operator */
+#define IOAPP 0x80 /* >> redirection operator */
+#define IODOC 0x100 /* << redirection operator */
+#define IOMOV 0x200 /* <& or >& operators */
+#define IOCLOB 0x400 /* noclobber bit */
+#define IORDW 0x800 /* <> redirection operator */
+#define IORAW 0x1000 /* no expansion needed for filename */
+#define IOSTRG 0x2000 /* here-document stored as incore string */
+#define IOSTRIP 0x4000 /* strip leading tabs for here-document */
+#define IOQUOTE 0x8000 /* here-document delimiter was quoted */
+#define IOVNM 0x10000 /* iovname field is non-zero */
+#define IOLSEEK 0x20000 /* seek operators <# or ># */
+#define IOARITH 0x40000 /* arithmetic seek <# ((expr)) */
+#define IOREWRITE 0x80000 /* arithmetic seek <# ((expr)) */
+#define IOCOPY IOCLOB /* copy skipped lines onto standard output */
+#define IOPROCSUB IOARITH /* process substitution redirection */
+
+union Shnode_u
+{
+ struct argnod arg;
+ struct ionod io;
+ struct whnod wh;
+ struct swnod sw;
+ struct ifnod if_;
+ struct dolnod dol;
+ struct comnod com;
+ struct trenod tre;
+ struct forknod fork;
+ struct fornod for_;
+ struct regnod reg;
+ struct parnod par;
+ struct lstnod lst;
+ struct tstnod tst;
+ struct functnod funct;
+ struct arithnod ar;
+};
+
+extern void sh_freeup(Shell_t*);
+extern void sh_funstaks(struct slnod*,int);
+extern Sfio_t *sh_subshell(Shell_t*,Shnode_t*, int, int);
+#if defined(__EXPORT__) && defined(_BLD_DLL) && defined(_BLD_shell)
+ __EXPORT__
+#endif
+extern int sh_tdump(Sfio_t*, const Shnode_t*);
+extern Shnode_t *sh_trestore(Shell_t*, Sfio_t*);
+
+#endif /* _SHNODES_H */
diff --git a/src/cmd/ksh93/include/shtable.h b/src/cmd/ksh93/include/shtable.h
new file mode 100644
index 0000000..e851ae5
--- /dev/null
+++ b/src/cmd/ksh93/include/shtable.h
@@ -0,0 +1,65 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef _SHTABLE_H
+
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * Interface definitions read-only data tables for shell
+ *
+ */
+
+#define _SHTABLE_H 1
+
+typedef struct shtable1
+{
+ const char *sh_name;
+ const unsigned sh_number;
+} Shtable_t;
+
+struct shtable2
+{
+ const char *sh_name;
+ const unsigned sh_number;
+ const char *sh_value;
+};
+
+struct shtable3
+{
+ const char *sh_name;
+ const unsigned sh_number;
+ int (*sh_value)(int, char*[], Shbltin_t*);
+};
+
+#define sh_lookup(name,value) (sh_locate(name,(Shtable_t*)(value),sizeof(*(value)))->sh_number)
+extern const Shtable_t shtab_testops[];
+extern const Shtable_t shtab_options[];
+extern const Shtable_t shtab_attributes[];
+extern const struct shtable2 shtab_variables[];
+extern const struct shtable2 shtab_aliases[];
+extern const struct shtable2 shtab_signals[];
+extern const struct shtable3 shtab_builtins[];
+extern const Shtable_t shtab_reserved[];
+extern const Shtable_t *sh_locate(const char*, const Shtable_t*, int);
+extern int sh_lookopt(const char*, int*);
+
+#endif /* SH_TABLE_H */
diff --git a/src/cmd/ksh93/include/streval.h b/src/cmd/ksh93/include/streval.h
new file mode 100644
index 0000000..30008b5
--- /dev/null
+++ b/src/cmd/ksh93/include/streval.h
@@ -0,0 +1,207 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef SEQPOINT
+/*
+ * D. G. Korn
+ *
+ * arithmetic expression evaluator
+ */
+
+/* The following only is needed for const */
+#include <ast.h>
+#include <math.h>
+#include "defs.h"
+#if _AST_VERSION >= 20030127L
+# include <ast_float.h>
+#endif
+
+#if _ast_fltmax_double
+#define LDBL_LLONG_MAX DBL_LLONG_MAX
+#define LDBL_ULLONG_MAX DBL_ULLONG_MAX
+#define LDBL_LLONG_MIN DBL_LLONG_MIN
+#endif
+
+#ifndef LDBL_LLONG_MAX
+# ifdef LLONG_MAX
+# define LDBL_LLONG_MAX ((Sfdouble_t)LLONG_MAX)
+# else
+# ifdef LLONG_MAX
+# define LDBL_LLONG_MAX ((Sfdouble_t)LLONG_MAX)
+# else
+# define LDBL_LLONG_MAX ((Sfdouble_t)((((Sflong_t)1) << (8*sizeof(Sflong_t)-1)) -1 ))
+# endif
+# endif
+#endif
+#ifndef LDBL_ULLONG_MAX
+# ifdef ULLONG_MAX
+# define LDBL_ULLONG_MAX ((Sfdouble_t)ULLONG_MAX)
+# else
+# define LDBL_ULLONG_MAX (2.*((Sfdouble_t)LDBL_LLONG_MAX))
+# endif
+#endif
+#ifndef LDBL_LLONG_MIN
+# ifdef LLONG_MIN
+# define LDBL_LLONG_MIN ((Sfdouble_t)LLONG_MIN)
+# else
+# define LDBL_LLONG_MIN (-LDBL_LLONG_MAX)
+# endif
+#endif
+#ifndef LDBL_DIG
+# define LDBL_DIG DBL_DIG
+#endif
+
+struct lval
+{
+ Shell_t *shp;
+ char *value;
+ char *ovalue;
+ Sfdouble_t (*fun)(Sfdouble_t,...);
+ const char *expr;
+ const void *ptr;
+ int nosub;
+ short flag;
+ short nargs;
+ short emode;
+ short level;
+ short elen;
+ char eflag;
+ char isfloat;
+};
+
+struct mathtab
+{
+ char fname[16];
+ Sfdouble_t (*fnptr)(Sfdouble_t,...);
+};
+
+typedef struct _arith_
+{
+ Shell_t *shp;
+ unsigned char *code;
+ const char *expr;
+ Sfdouble_t (*fun)(const char**,struct lval*,int,Sfdouble_t);
+ short size;
+ short staksize;
+ short emode;
+ short elen;
+} Arith_t;
+#define ARITH_COMP 04 /* set when compile separate from execute */
+#define ARITH_ASSIGNOP 010 /* set during assignment operators */
+
+#define MAXPREC 15 /* maximum precision level */
+#define SEQPOINT 0200 /* sequence point */
+#define NOASSIGN 0100 /* assignment legal with this operator */
+#define RASSOC 040 /* right associative */
+#define NOFLOAT 020 /* illegal with floating point */
+#define PRECMASK 017 /* precision bit mask */
+
+#define A_EOF 1
+#define A_NEQ 2
+#define A_NOT 3
+#define A_MOD 4
+#define A_ANDAND 5
+#define A_AND 6
+#define A_LPAR 7
+#define A_RPAR 8
+#define A_POW 9
+#define A_TIMES 10
+#define A_PLUSPLUS 11
+#define A_PLUS 12
+#define A_COMMA 13
+#define A_MINUSMINUS 14
+#define A_MINUS 15
+#define A_DIV 16
+#define A_LSHIFT 17
+#define A_LE 18
+#define A_LT 19
+#define A_EQ 20
+#define A_ASSIGN 21
+#define A_COLON 22
+#define A_RSHIFT 23
+#define A_GE 24
+#define A_GT 25
+#define A_QCOLON 26
+#define A_QUEST 27
+#define A_XOR 28
+#define A_OROR 29
+#define A_OR 30
+#define A_TILDE 31
+#define A_REG 32
+#define A_DIG 33
+#define A_INCR 34
+#define A_DECR 35
+#define A_PUSHV 36
+#define A_PUSHL 37
+#define A_PUSHN 38
+#define A_PUSHF 39
+#define A_STORE 40
+#define A_POP 41
+#define A_SWAP 42
+#define A_UMINUS 43
+#define A_JMPZ 44
+#define A_JMPNZ 45
+#define A_JMP 46
+#define A_CALL1F 47
+#define A_CALL2F 48
+#define A_CALL3F 49
+#define A_CALL1I 50
+#define A_CALL2I 51
+#define A_DOT 52
+#define A_LIT 53
+#define A_NOTNOT 54
+#define A_ASSIGNOP 55
+#define A_ENUM 56
+#define A_ASSIGNOP1 57
+
+
+/* define error messages */
+extern const unsigned char strval_precedence[35];
+extern const char strval_states[64];
+extern const char e_moretokens[];
+extern const char e_argcount[];
+extern const char e_paren[];
+extern const char e_badnum[];
+extern const char e_badcolon[];
+extern const char e_recursive[];
+extern const char e_divzero[];
+extern const char e_synbad[];
+extern const char e_notlvalue[];
+extern const char e_function[];
+extern const char e_questcolon[];
+extern const char e_incompatible[];
+extern const char e_domain[];
+extern const char e_overflow[];
+extern const char e_singularity[];
+extern const char e_dict[];
+extern const char e_charconst[];
+extern const struct mathtab shtab_math[];
+
+/* function code for the convert function */
+
+#define LOOKUP 0
+#define ASSIGN 1
+#define VALUE 2
+#define MESSAGE 3
+
+extern Sfdouble_t strval(Shell_t*,const char*,char**,Sfdouble_t(*)(const char**,struct lval*,int,Sfdouble_t),int);
+extern Arith_t *arith_compile(Shell_t *,const char*,char**,Sfdouble_t(*)(const char**,struct lval*,int,Sfdouble_t),int);
+extern Sfdouble_t arith_exec(Arith_t*);
+#endif /* !SEQPOINT */
diff --git a/src/cmd/ksh93/include/terminal.h b/src/cmd/ksh93/include/terminal.h
new file mode 100644
index 0000000..4999ca3
--- /dev/null
+++ b/src/cmd/ksh93/include/terminal.h
@@ -0,0 +1,195 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _terminal_
+#define _terminal_ 1
+
+#include "FEATURE/ttys"
+/*
+ * terminal interface
+ * complicated by the fact that there are so many variations
+ * This will use POSIX <termios.h> interface where available
+ */
+
+#ifdef _hdr_termios
+# include <termios.h>
+# if __sgi__ || sgi /* special hack to eliminate ^M problem */
+# ifndef ECHOCTL
+# define ECHOCTL ECHOE
+# endif /* ECHOCTL */
+# ifndef CNSUSP
+# define CNSUSP CNSWTCH
+# endif /* CNSUSP */
+# endif /* sgi */
+# ifdef _NEXT_SOURCE
+# define _lib_tcgetattr 1
+# define _lib_tcgetpgrp 1
+# endif /* _NEXT_SOURCE */
+#else
+# if defined(_sys_termios) && defined(_lib_tcgetattr)
+# include <sys/termios.h>
+# define _hdr_termios
+# else
+# undef _sys_termios
+# endif /* _sys_termios */
+#endif /* _hdr_termios */
+
+#ifdef _hdr_termios
+# undef _hdr_sgtty
+# undef tcgetattr
+# undef tcsetattr
+# undef tcgetpgrp
+# undef tcsetpgrp
+# undef cfgetospeed
+# ifndef TCSANOW
+# define TCSANOW TCSETS
+# define TCSADRAIN TCSETSW
+# define TCSAFLUSH TCSETSF
+# endif /* TCSANOW */
+ /* The following corrects bugs in some implementations */
+# if defined(TCSADFLUSH) && !defined(TCSAFLUSH)
+# define TCSAFLUSH TCSADFLUSH
+# endif /* TCSADFLUSH */
+# ifndef _lib_tcgetattr
+# undef tcgetattr
+# define tcgetattr(fd,tty) ioctl(fd, TCGETS, tty)
+# undef tcsetattr
+# define tcsetattr(fd,action,tty) ioctl(fd, action, tty)
+# undef cfgetospeed
+# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
+# endif /* _lib_tcgetattr */
+# undef TIOCGETC
+# if SHOPT_OLDTERMIO /* use both termios and termio */
+# ifdef _hdr_termio
+# include <termio.h>
+# else
+# ifdef _sys_termio
+# include <sys/termio.h>
+# define _hdr_termio 1
+# else
+# undef SHOPT_OLDTERMIO
+# endif /* _sys_termio */
+# endif /* _hdr_termio */
+# endif /* SHOPT_OLDTERMIO */
+#else
+# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
+# undef SHOPT_OLDTERMIO
+# ifdef _hdr_termio
+# include <termio.h>
+# else
+# ifdef _sys_termio
+# include <sys/termio.h>
+# define _hdr_termio 1
+# endif /* _sys_termio */
+# endif /* _hdr_termio */
+# ifdef _hdr_termio
+# define termios termio
+# undef TIOCGETC
+# define tcgetattr(fd,tty) ioctl(fd, TCGETA, tty)
+# define tcsetattr(fd,action,tty) ioctl(fd, action, tty)
+
+# ifdef _sys_bsdtty
+# include <sys/bsdtty.h>
+# endif /* _sys_bsdtty */
+# else
+# ifdef _hdr_sgtty
+# include <sgtty.h>
+# ifndef LPENDIN
+# ifdef _sys_nttyio
+# include <sys/nttyio.h>
+# endif /* _sys_nttyio */
+# endif /* LPENDIN */
+# define termios sgttyb
+# ifdef TIOCSETN
+# undef TCSETAW
+# endif /* TIOCSETN */
+# ifdef TIOCGETP
+# define tcgetattr(fd,tty) ioctl(fd, TIOCGETP, tty)
+# define tcsetattr(fd,action,tty) ioctl(fd, action, tty)
+# else
+# define tcgetattr(fd,tty) gtty(fd, tty)
+# define tcsetattr(fd,action,tty) stty(fd, tty)
+# endif /* TIOCGETP */
+# endif /* _hdr_sgtty */
+# endif /* hdr_termio */
+
+# ifndef TCSANOW
+# ifdef TCSETAW
+# define TCSANOW TCSETA
+# ifdef u370
+ /* delays are too long, don't wait for output to drain */
+# define TCSADRAIN TCSETA
+# else
+# define TCSADRAIN TCSETAW
+# endif /* u370 */
+# define TCSAFLUSH TCSETAF
+# else
+# ifdef TIOCSETN
+# define TCSANOW TIOCSETN
+# define TCSADRAIN TIOCSETN
+# define TCSAFLUSH TIOCSETP
+# endif /* TIOCSETN */
+# endif /* TCSETAW */
+# endif /* TCSANOW */
+#endif /* _hdr_termios */
+
+/* set ECHOCTL if driver can echo control charaters as ^c */
+#ifdef LCTLECH
+# ifndef ECHOCTL
+# define ECHOCTL LCTLECH
+# endif /* !ECHOCTL */
+#endif /* LCTLECH */
+#ifdef LNEW_CTLECH
+# ifndef ECHOCTL
+# define ECHOCTL LNEW_CTLECH
+# endif /* !ECHOCTL */
+#endif /* LNEW_CTLECH */
+#ifdef LNEW_PENDIN
+# ifndef PENDIN
+# define PENDIN LNEW_PENDIN
+# endif /* !PENDIN */
+#endif /* LNEW_PENDIN */
+#ifndef ECHOCTL
+# ifndef VEOL
+# define RAWONLY 1
+# endif /* !VEOL */
+#endif /* !ECHOCTL */
+
+#ifdef _sys_filio
+# ifndef FIONREAD
+# include <sys/filio.h>
+# endif /* FIONREAD */
+#endif /* _sys_filio */
+/* set FIORDCHK if you can check for characters in input queue */
+#ifdef FIONREAD
+# ifndef FIORDCHK
+# define FIORDCHK FIONREAD
+# endif /* !FIORDCHK */
+#endif /* FIONREAD */
+
+extern int tty_alt(int);
+extern void tty_cooked(int);
+extern int tty_get(int,struct termios*);
+extern int tty_raw(int,int);
+extern int tty_check(int);
+extern int tty_set(int, int, struct termios*);
+
+#endif /* _terminal_ */
diff --git a/src/cmd/ksh93/include/test.h b/src/cmd/ksh93/include/test.h
new file mode 100644
index 0000000..a9ed37b
--- /dev/null
+++ b/src/cmd/ksh93/include/test.h
@@ -0,0 +1,72 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef TEST_ARITH
+/*
+ * UNIX shell
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "FEATURE/options"
+#include "defs.h"
+#include "shtable.h"
+/*
+ * These are the valid test operators
+ */
+
+#define TEST_ARITH 040 /* arithmetic operators */
+#define TEST_BINOP 0200 /* binary operator */
+#define TEST_PATTERN 0100 /* turn off bit for pattern compares */
+
+#define TEST_NE (TEST_ARITH|9)
+#define TEST_EQ (TEST_ARITH|4)
+#define TEST_GE (TEST_ARITH|5)
+#define TEST_GT (TEST_ARITH|6)
+#define TEST_LE (TEST_ARITH|7)
+#define TEST_LT (TEST_ARITH|8)
+#define TEST_OR (TEST_BINOP|1)
+#define TEST_AND (TEST_BINOP|2)
+#define TEST_SNE (TEST_PATTERN|1)
+#define TEST_SEQ (TEST_PATTERN|14)
+#define TEST_PNE 1
+#define TEST_PEQ 14
+#define TEST_EF 3
+#define TEST_NT 10
+#define TEST_OT 12
+#define TEST_SLT 16
+#define TEST_SGT 17
+#define TEST_END 8
+#define TEST_REP 20
+
+extern int test_unop(Shell_t*,int, const char*);
+extern int test_inode(const char*, const char*);
+extern int test_binop(Shell_t*,int, const char*, const char*);
+
+extern const char sh_opttest[];
+extern const char test_opchars[];
+extern const char e_argument[];
+extern const char e_missing[];
+extern const char e_badop[];
+extern const char e_tstbegin[];
+extern const char e_tstend[];
+
+#endif /* TEST_ARITH */
diff --git a/src/cmd/ksh93/include/timeout.h b/src/cmd/ksh93/include/timeout.h
new file mode 100644
index 0000000..a12c752
--- /dev/null
+++ b/src/cmd/ksh93/include/timeout.h
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * UNIX shell
+ *
+ * AT&T Labs
+ *
+ */
+
+#define TGRACE 60 /* grace period before termination */
+ /* The time_warn message contains this number */
+extern const char e_timeout[];
+extern const char e_timewarn[];
diff --git a/src/cmd/ksh93/include/ulimit.h b/src/cmd/ksh93/include/ulimit.h
new file mode 100644
index 0000000..a0e6330
--- /dev/null
+++ b/src/cmd/ksh93/include/ulimit.h
@@ -0,0 +1,174 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+#ifndef _ULIMIT_H
+#define _ULIMIT_H 1
+/*
+ * This is for the ulimit built-in command
+ */
+
+#include "FEATURE/time"
+#include "FEATURE/rlimits"
+#if defined(_sys_resource) && defined(_lib_getrlimit)
+# include <sys/resource.h>
+# if !defined(RLIMIT_FSIZE) && defined(_sys_vlimit)
+ /* This handles hp/ux problem */
+# include <sys/vlimit.h>
+# define RLIMIT_FSIZE (LIM_FSIZE-1)
+# define RLIMIT_DATA (LIM_DATA-1)
+# define RLIMIT_STACK (LIM_STACK-1)
+# define RLIMIT_CORE (LIM_CORE-1)
+# define RLIMIT_CPU (LIM_CPU-1)
+# ifdef LIM_MAXRSS
+# define RLIMIT_RSS (LIM_MAXRSS-1)
+# endif /* LIM_MAXRSS */
+# endif
+# undef _lib_ulimit
+#else
+# ifdef _sys_vlimit
+# include <sys/vlimit.h>
+# undef _lib_ulimit
+# define RLIMIT_FSIZE LIM_FSIZE
+# define RLIMIT_DATA LIM_DATA
+# define RLIMIT_STACK LIM_STACK
+# define RLIMIT_CORE LIM_CORE
+# define RLIMIT_CPU LIM_CPU
+# ifdef LIM_MAXRSS
+# define RLIMIT_RSS LIM_MAXRSS
+# endif /* LIM_MAXRSS */
+# else
+# ifdef _lib_ulimit
+# define vlimit ulimit
+# endif /* _lib_ulimit */
+# endif /* _lib_vlimit */
+#endif
+
+#ifdef RLIM_INFINITY
+# define INFINITY RLIM_INFINITY
+#else
+# ifndef INFINITY
+# define INFINITY ((rlim_t)-1L)
+# endif /* INFINITY */
+#endif /* RLIM_INFINITY */
+
+#if defined(_lib_getrlimit) || defined(_lib_vlimit) || defined(_lib_ulimit)
+# ifndef RLIMIT_VMEM
+# ifdef RLIMIT_AS
+# define RLIMIT_VMEM RLIMIT_AS
+# endif
+# endif /* !RLIMIT_VMEM */
+#else
+# define _no_ulimit
+#endif
+#ifndef _typ_rlim_t
+ typedef long rlim_t;
+#endif
+
+#if !defined(RLIMIT_NOFILE) && defined(RLIMIT_OFILE)
+#define RLIMIT_NOFILE RLIMIT_OFILE
+#endif
+
+#ifndef RLIMIT_UNKNOWN
+#define RLIMIT_UNKNOWN (-9999)
+#endif
+#ifndef RLIMIT_AS
+#define RLIMIT_AS RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_CORE
+#define RLIMIT_CORE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_CPU
+#define RLIMIT_CPU RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_DATA
+#define RLIMIT_DATA RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_FSIZE
+#define RLIMIT_FSIZE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_LOCKS
+#define RLIMIT_LOCKS RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_MEMLOCK
+#define RLIMIT_MEMLOCK RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_MSGQUEUE
+#define RLIMIT_MSGQUEUE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_NOFILE
+#define RLIMIT_NOFILE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_NICE
+#define RLIMIT_NICE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_NPROC
+#define RLIMIT_NPROC RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_PIPE
+#define RLIMIT_PIPE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_PTHREAD
+#define RLIMIT_PTHREAD RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_RSS
+#define RLIMIT_RSS RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_RTPRIO
+#define RLIMIT_RTPRIO RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_SBSIZE
+#define RLIMIT_SBSIZE RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_SIGPENDING
+#define RLIMIT_SIGPENDING RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_STACK
+#define RLIMIT_STACK RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_SWAP
+#define RLIMIT_SWAP RLIMIT_UNKNOWN
+#endif
+#ifndef RLIMIT_VMEM
+#define RLIMIT_VMEM RLIMIT_UNKNOWN
+#endif
+
+#define LIM_COUNT 0
+#define LIM_BLOCK 1
+#define LIM_BYTE 2
+#define LIM_KBYTE 3
+#define LIM_SECOND 4
+
+typedef struct Limit_s
+{
+ const char name[16];
+ const char* description;
+ int index;
+ const char* conf;
+ unsigned char option;
+ unsigned char type;
+} Limit_t;
+
+extern const Limit_t shtab_limits[];
+extern const int shtab_units[];
+
+extern const char e_unlimited[];
+extern const char* e_units[];
+
+#endif /* _ULIMIT_H */
diff --git a/src/cmd/ksh93/include/variables.h b/src/cmd/ksh93/include/variables.h
new file mode 100644
index 0000000..edaa865
--- /dev/null
+++ b/src/cmd/ksh93/include/variables.h
@@ -0,0 +1,111 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef SH_VALNOD
+
+#include <option.h>
+#include "FEATURE/options"
+#include "FEATURE/dynamic"
+
+/* The following defines are coordinated with data in data/variables.c */
+
+#define PATHNOD (shgd->bltin_nodes)
+#define PS1NOD (shgd->bltin_nodes+1)
+#define PS2NOD (shgd->bltin_nodes+2)
+#define IFSNOD (shgd->bltin_nodes+3)
+#define PWDNOD (shgd->bltin_nodes+4)
+#define HOME (shgd->bltin_nodes+5)
+#define MAILNOD (shgd->bltin_nodes+6)
+#define REPLYNOD (shgd->bltin_nodes+7)
+#define SHELLNOD (shgd->bltin_nodes+8)
+#define EDITNOD (shgd->bltin_nodes+9)
+#define MCHKNOD (shgd->bltin_nodes+10)
+#define RANDNOD (shgd->bltin_nodes+11)
+#define ENVNOD (shgd->bltin_nodes+12)
+#define HISTFILE (shgd->bltin_nodes+13)
+#define HISTSIZE (shgd->bltin_nodes+14)
+#define HISTEDIT (shgd->bltin_nodes+15)
+#define HISTCUR (shgd->bltin_nodes+16)
+#define FCEDNOD (shgd->bltin_nodes+17)
+#define CDPNOD (shgd->bltin_nodes+18)
+#define MAILPNOD (shgd->bltin_nodes+19)
+#define PS3NOD (shgd->bltin_nodes+20)
+#define OLDPWDNOD (shgd->bltin_nodes+21)
+#define VISINOD (shgd->bltin_nodes+22)
+#define COLUMNS (shgd->bltin_nodes+23)
+#define LINES (shgd->bltin_nodes+24)
+#define PPIDNOD (shgd->bltin_nodes+25)
+#define L_ARGNOD (shgd->bltin_nodes+26)
+#define TMOUTNOD (shgd->bltin_nodes+27)
+#define SECONDS (shgd->bltin_nodes+28)
+#define LINENO (shgd->bltin_nodes+29)
+#define OPTARGNOD (shgd->bltin_nodes+30)
+#define OPTINDNOD (shgd->bltin_nodes+31)
+#define PS4NOD (shgd->bltin_nodes+32)
+#define FPATHNOD (shgd->bltin_nodes+33)
+#define LANGNOD (shgd->bltin_nodes+34)
+#define LCALLNOD (shgd->bltin_nodes+35)
+#define LCCOLLNOD (shgd->bltin_nodes+36)
+#define LCTYPENOD (shgd->bltin_nodes+37)
+#define LCMSGNOD (shgd->bltin_nodes+38)
+#define LCNUMNOD (shgd->bltin_nodes+39)
+#define FIGNORENOD (shgd->bltin_nodes+40)
+#define VERSIONNOD (shgd->bltin_nodes+41)
+#define JOBMAXNOD (shgd->bltin_nodes+42)
+#define DOTSHNOD (shgd->bltin_nodes+43)
+#define ED_CHRNOD (shgd->bltin_nodes+44)
+#define ED_COLNOD (shgd->bltin_nodes+45)
+#define ED_TXTNOD (shgd->bltin_nodes+46)
+#define ED_MODENOD (shgd->bltin_nodes+47)
+#define SH_NAMENOD (shgd->bltin_nodes+48)
+#define SH_SUBSCRNOD (shgd->bltin_nodes+49)
+#define SH_VALNOD (shgd->bltin_nodes+50)
+#define SH_VERSIONNOD (shgd->bltin_nodes+51)
+#define SH_DOLLARNOD (shgd->bltin_nodes+52)
+#define SH_MATCHNOD (shgd->bltin_nodes+53)
+#define SH_COMMANDNOD (shgd->bltin_nodes+54)
+#define SH_PATHNAMENOD (shgd->bltin_nodes+55)
+#define SH_FUNNAMENOD (shgd->bltin_nodes+56)
+#define SH_SUBSHELLNOD (shgd->bltin_nodes+57)
+#define SH_LEVELNOD (shgd->bltin_nodes+58)
+#define SH_LINENO (shgd->bltin_nodes+59)
+#define SH_STATS (shgd->bltin_nodes+60)
+#define SH_MATHNOD (shgd->bltin_nodes+61)
+#define SH_JOBPOOL (shgd->bltin_nodes+62)
+#define SHLVL (shgd->bltin_nodes+63)
+#if SHOPT_FS_3D
+# define VPATHNOD (shgd->bltin_nodes+64)
+# define NFS_3D 1
+#else
+# define NFS_3D 0
+#endif /* SHOPT_FS_3D */
+#if SHOPT_VPIX
+# define DOSPATHNOD (shgd->bltin_nodes+64+NFS_3D)
+# define VPIXNOD (shgd->bltin_nodes+65+NFS_3D)
+# define NVPIX (NFS_3D+2)
+#else
+# define NVPIX NFS_3D
+#endif /* SHOPT_VPIX */
+#ifdef apollo
+# define SYSTYPENOD (shgd->bltin_nodes+63+NVPIX)
+#endif /* apollo */
+
+#endif /* SH_VALNOD */
diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h
new file mode 100644
index 0000000..5b2bc90
--- /dev/null
+++ b/src/cmd/ksh93/include/version.h
@@ -0,0 +1,20 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#define SH_RELEASE "93u+ 2012-02-29"
diff --git a/src/cmd/ksh93/ksh-regress.rt b/src/cmd/ksh93/ksh-regress.rt
new file mode 100644
index 0000000..d3d71a1
--- /dev/null
+++ b/src/cmd/ksh93/ksh-regress.rt
@@ -0,0 +1,71 @@
+NOTE regression tests for --regress enabled ksh
+
+UNIT ksh-regress
+
+EXPORT HOME=. ENV=.env.sh LC_ALL=C HISTFILE=
+
+TEST mode suid/sgid combinations
+
+# these tests are the product { all modes combinations } X { tests }
+
+defaults=(
+ "etc=$HOME"
+ "source"
+)
+modes=(
+ interactive
+ login
+ privileged
+ rc
+ restricted
+)
+tests=(
+ ""
+ "euid=0"
+ "euid=0 p_suid=0"
+ "euid=0 p_suid=99999"
+ "euid=1"
+ "euid=1 p_suid=0"
+ "euid=1 p_suid=99999"
+ "egid=1"
+ "egid=1 p_suid=0"
+ "egid=1 p_suid=99999"
+)
+
+integer n=1 m=${#modes[@]}
+d=
+for o in ${defaults[@]}
+do d="$d --regress=$o"
+done
+for ((b=0; b<m; b++))
+do (( n *= 3 ))
+done
+for (( b=0; b<n; b++ ))
+do k=
+ z=$(printf "%0$m..3u" $b)
+ for (( i=0; i<m; i++ ))
+ do case $z in
+ 1*) k="$k --no${modes[i]}" ;;
+ 2*) k="$k --${modes[i]}" ;;
+ esac
+ z=${z#?}
+ done
+ for t in "${tests[@]}"
+ do o=$d
+ for r in $t
+ do o="$o --regress=$r"
+ done
+ o="$o $k"
+
+EXEC $o <<!
+set --state
+!
+
+ done
+done
+
+TEST privileged/noprivileged sequence
+
+EXEC --regress=etc=. --regress=euid=1 --privileged <<!
+set --state; set --noprivileged; set --state; set --privileged; set --state; set --noprivileged; set --state
+!
diff --git a/src/cmd/ksh93/ksh-regress.tst b/src/cmd/ksh93/ksh-regress.tst
new file mode 100644
index 0000000..4565028
--- /dev/null
+++ b/src/cmd/ksh93/ksh-regress.tst
@@ -0,0 +1,22544 @@
+# : : generated from ksh-regress.rt by mktest : : #
+
+# regression tests for --regress enabled ksh
+
+UNIT ksh-regress
+
+EXPORT HOME=. ENV=.env.sh LC_ALL=C HISTFILE=''
+
+TEST 01 'mode suid/sgid combinations'
+
+ EXEC --regress=etc=. --regress=source
+ INPUT - 'set --state'
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --noprivileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --privileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nologin --noprivileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nologin --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nologin --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --noprivileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --login --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --login --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --noprivileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --noprivileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --nologin --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --nologin --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --noprivileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --norc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --norc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --norc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --norc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --rc
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --rc
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --rc --norestricted
+ OUTPUT - 'set --default --braceexpand --privileged --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --nointeractive --login --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --nointeractive --login --privileged --rc --restricted
+ OUTPUT - 'set --default --braceexpand --privileged --restricted --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --nointeractive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT'
+
+ EXEC --regress=etc=. --regress=source --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --noprivileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --privileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --privileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --noprivileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --nologin --privileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.\nksh:REGRESS:source:__regress__:on\n'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --nologin --privileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --nologin --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --noprivileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:0
+ksh:REGRESS:egid:setgid:egid==rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --noprivileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:p_suid:SHOPT_P_SUID:99999
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:source:sh_source:./.profile:ENOENT
+ksh:REGRESS:source:sh_source:.profile:ENOENT
+ksh:REGRESS:source:sh_source:.env.sh:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --norc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --norc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --norc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --norc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --norc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --norc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --rc
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --rc
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --rc --norestricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --rc --norestricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --interactive --login --privileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --restricted --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --interactive --login --privileged --rc --restricted
+ OUTPUT - 'set --default --bgnice --braceexpand --monitor --privileged --restricted --v'\
+'i --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=0 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=0 --regress=p_suid=99999 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:0
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=0 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=euid=1 --regress=p_suid=99999 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=0 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:0
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+ EXEC --regress=etc=. --regress=source --regress=egid=1 --regress=p_suid=99999 --interactive --login --privileged --rc --restricted
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:source:__regress__:on
+ksh:REGRESS:egid:__regress__:1
+ksh:REGRESS:p_suid:__regress__:99999
+ksh:REGRESS:egid:getegid:egid!=rgid
+ksh:REGRESS:etc:sh_open:/etc/profile => ./profile
+ksh:REGRESS:source:sh_source:/etc/profile:ENOENT
+ksh:REGRESS:etc:sh_open:/etc/suid_profile => ./suid_profile
+ksh:REGRESS:source:sh_source:/etc/suid_profile:ENOENT
+'
+
+TEST 02 'privileged/noprivileged sequence'
+
+ EXEC --regress=etc=. --regress=euid=1 --privileged
+ INPUT - 'set --state; set --noprivileged; set --state; set --privileged; set --state;'\
+' set --noprivileged; set --state'
+ OUTPUT - $'set --default --braceexpand --privileged --trackall --vi --viraw
+set --default --braceexpand --trackall --vi --viraw
+set --default --braceexpand --privileged --trackall --vi --viraw
+set --default --braceexpand --trackall --vi --viraw'
+ ERROR - $'ksh:REGRESS:etc:__regress__:.
+ksh:REGRESS:euid:__regress__:1
+ksh:REGRESS:euid:geteuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid
+ksh:REGRESS:euid:setuid:euid!=ruid
+ksh:REGRESS:euid:setuid:euid==ruid'
diff --git a/src/cmd/ksh93/mamexec b/src/cmd/ksh93/mamexec
new file mode 100755
index 0000000..e36a846
--- /dev/null
+++ b/src/cmd/ksh93/mamexec
@@ -0,0 +1,307 @@
+:
+#
+# Glenn Fowler
+# AT&T Bell Laboratories
+#
+# make abstract machine executor with state
+#
+# @(#)mamexec (gsf@research.att.com) 07/17/94
+#
+# mamexec [ -dfins ] [ target ... ] < mam-file
+#
+# NOTE: variables defined in this script may conflict with
+# mam-file variables
+#
+
+_command_=mamexec
+_debug_=:
+_diff_=.
+_error_='exit 1'
+_exec_=eval
+_force_=
+_list_=
+_same_=.
+_set_=
+_silent_=
+_state_list_=MAMlist
+_state_time_=MAMtime
+_tmp_=/tmp/mam.$$.mam
+
+trap 'rm -f $_tmp_' 0
+trap 'exit 2' 1 2
+while :
+do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ --) shift
+ break
+ ;;
+ -*) case $1 in
+ -*[abceghjklmopqrtuvwxyz_A-Z0-9]*) # [!...] not portable
+ echo "Usage: $_command_ [ -dfins ] [ target ... ] < mam-file" >&2; exit 2
+ ;;
+ *) case $1 in
+ *d*) _debug_="eval echo $_command_: debug: >&2" ;;
+ esac
+ case $1 in
+ *f*) _force_=1 ;;
+ esac
+ case $1 in
+ *i*) _error_=: ;;
+ esac
+ case $1 in
+ *n*) _exec_=echo ;;
+ esac
+ case $1 in
+ *s*) _silent_=1 ;;
+ esac
+ ;;
+ esac
+ ;;
+ *) break
+ ;;
+ esac
+ shift
+done
+_select_=
+while :
+do case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ *=*) eval $1
+ ;;
+ *) case $_select_ in
+ "") _select_=$1 ;;
+ *) _select_="$_select_|$1" ;;
+ esac
+ ;;
+ esac
+ shift
+done
+case $_select_ in
+"") _select_="*" ;;
+esac
+(set -e; false || true) && _set_=e || echo $_command_: command errors ignored because of shell botch >&2
+case $_silent_ in
+"") _set_=x$_set_
+ ;;
+*) case $_exec_ in
+ "echo") _exec_=: ;;
+ esac
+ ;;
+esac
+case $_exec_ in
+"eval") _begin_="("
+ _end_=") </dev/null"
+ case $_set_ in
+ ?*) _set_="set -$_set_;" ;;
+ esac
+ ;;
+*) _set_=
+ ;;
+esac
+
+if test -f $_state_list_ -a -f $_state_time_
+then mamstate $_state_list_ < $_state_list_ | sort > $_tmp_
+ for _i_ in `comm -12 $_state_time_ $_tmp_ | sed 's/ .*//'`
+ do case $_same_ in
+ .) _same_=$_i_ ;;
+ *) _same_="$_same_|$_i_" ;;
+ esac
+ done
+fi
+
+_index_=_
+_match_=
+case `(echo ok | (read -r a; echo $a) 2>/dev/null)` in
+ok) _read_='read -r'
+ ;;
+*) # read strips \ -- thanks a lot
+ # tmp file avoids char at a time read
+ _read_=read
+ sed 's/\\/\\\\/g' > $_tmp_
+ exec < $_tmp_
+ rm -f $_tmp_
+ ;;
+esac
+_old_=1
+_ifs_=$IFS
+while IFS=' '; $_read_ _op_ _arg_ _val_
+do IFS=$_ifs_
+ case $_op_ in
+ "note") continue
+ ;;
+ "info") case $_arg_ in
+ "mam") _old_= ;;
+ esac
+ continue
+ ;;
+ "setv") eval _data_='$'$_arg_
+ case $_index_:$_data_ in
+ __*:*|*:)
+ case $_exec_ in
+ "eval") ;;
+ *) echo "$_arg_=$_val_" ;;
+ esac
+ eval $_arg_="$_val_" "</dev/null"
+ ;;
+ esac
+ case $_arg_:$mam_cc_L in
+ "CC:") (
+ set -
+ mkdir /tmp/mam$$
+ cd /tmp/mam$$
+ echo 'main(){return 0;}' > main.c
+ code=1
+ if $CC -c main.c 2>/dev/null
+ then if $CC -L. main.o -lc 2>/dev/null
+ then $CC -L. main.o -lc > libc.a 2>/dev/null || code=0
+ fi
+ fi
+ cd /tmp
+ rm -rf /tmp/mam$$
+ exit $code
+ ) </dev/null && mam_cc_L=' '
+ ;;
+ esac
+ continue
+ ;;
+ "make") eval _name_$_index_=$_name_
+ eval _prev_$_index_=$_prev_
+ eval _cmds_$_index_='"$_cmds_"'
+ eval _attr_$_index_=$_attr_
+ eval _name_=$_arg_
+ _prev_=$_index_
+ case " $_val_ " in
+ *" metarule "*) _attr_=m$_attr_ ;;
+ esac
+ _cmds_=
+ eval " case \"$_name_\" in
+ $_select_)
+ case \"$_select_\" in
+ \"*\") _select_=$_name_ ;;
+ esac
+ _match_=1
+ _attr_=x$_attr_
+ ;;
+ esac"
+ case $_force_ in
+ "") eval " case \"$_name_\" in
+ $_diff_)_attr_=u$_attr_ ;;
+ $_same_);;
+ *) _attr_=u$_attr_ ;;
+ esac"
+ ;;
+ *) _attr_=u$_attr_
+ ;;
+ esac
+ case $_attr_ in
+ *u*) case $_diff_ in
+ .) _diff_=$_name_ ;;
+ *) _diff_="$_diff_|$_name_" ;;
+ esac
+ ;;
+ esac
+ _index_=_$_index_
+ eval _name_$_index_=$_name_
+ eval _prev_$_index_=$_prev_
+ eval _cmds_$_index_=$_cmds_
+ eval _attr_$_index_=$_attr_
+ eval _list_='"'"$_list_"'
+'$_name_'"'
+ continue
+ ;;
+ "prev") case $_force_ in
+ "") eval " case \"$_arg_\" in
+ $_diff_)_attr_=u$_attr_ ;;
+ $_same_) ;;
+ *) _attr_=u$_attr_ ;;
+ esac"
+ ;;
+ *) _attr_=u$_attr_
+ ;;
+ esac
+ continue
+ ;;
+ esac
+ case $_index_ in
+ _) echo $_op_: missing make op >&2; continue ;;
+ esac
+ case $_op_ in
+ "attr") case $_val_ in
+ "meta"|"suff") _attr_=m$_attr_ ;;
+ esac
+ ;;
+ "exec"|"....")
+ case $_old_ in
+ "") _arg_=$_val_
+ ;;
+ *) case $_val_ in
+ ?*) _arg_="$_arg_ $_val_" ;;
+ esac
+ ;;
+ esac
+ case $_cmds_ in
+ "") _cmds_=$_arg_
+ ;;
+ *) _cmds_="$_cmds_
+$_arg_"
+ ;;
+ esac
+ ;;
+ "done") eval _arg_=$_arg_
+ _prop_=
+ case $_arg_ in
+ $_name_)case $_attr_ in
+ *m*) ;;
+ *x*u*|*u*x*)
+ case $_cmds_ in
+ "") case $_attr_ in
+ *u*) _prop_=u ;;
+ esac
+ ;;
+ *) $_exec_ "$_begin_$_set_$_cmds_$_end_" ||
+ {
+ _code_=$?
+ case $_set_ in
+ *-*e*) ;;
+ *) case $_cmds_ in
+ *if*then*fi*|"||") _code_=0 ;;
+ esac
+ ;;
+ esac
+ case $_code_ in
+ 0) ;;
+ *) echo "*** exit code $_code_ making $_name_" >&2
+ $_error_
+ ;;
+ esac
+ }
+ _prop_=u
+ ;;
+ esac
+ ;;
+ esac
+ _index_=$_prev_
+ eval _name_='$'_name_$_index_
+ eval _prev_='$'_prev_$_index_
+ eval _cmds_='$'_cmds_$_index_
+ eval _attr_=$_prop_'$'_attr_$_index_
+ ;;
+ *) echo $_val_: $_op_ $_name_ expected >&2
+ ;;
+ esac
+ ;;
+ esac
+done
+IFS=$_ifs_
+case $_match_ in
+"") echo "$_command_: don't know how to make $_select_" >&2; $_error_ ;;
+esac
+case $_exec_ in
+"eval") echo "$_list_" > $_state_list_
+ mamstate $_state_list_ < $_state_list_ | sort > $_state_time_
+ ;;
+esac
diff --git a/src/cmd/ksh93/mamstate.c b/src/cmd/ksh93/mamstate.c
new file mode 100644
index 0000000..7a0e459
--- /dev/null
+++ b/src/cmd/ksh93/mamstate.c
@@ -0,0 +1,73 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * AT&T Bell Laboratories
+ * make abstract machine file state support
+ *
+ * mamstate reference [ file ... | <files ]
+ *
+ * stdout is list of <file,delta> pairs where delta
+ * is diff between reference and file times
+ * non-existent files are not listed
+ */
+
+#if !lint
+static char id[] = "\n@(#)$Id: mamstate (AT&T Bell Laboratories) 1989-06-26 $\0\n";
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+main(argc, argv)
+int argc;
+register char** argv;
+{
+ register char* s;
+ register int c;
+ long ref;
+ struct stat st;
+ char buf[1024];
+
+ if (!(s = *++argv) || stat(s, &st))
+ {
+ fprintf(stderr, "Usage: mamstate reference [ file ... | <files ]\n");
+ exit(1);
+ }
+ ref = (long)st.st_mtime;
+ if (s = *++argv) do
+ {
+ if (!stat(s, &st))
+ printf("%s %ld\n", s, (long)st.st_mtime - ref);
+ } while (s = *++argv);
+ else do
+ {
+ s = buf;
+ while ((c = getchar()) != EOF && c != ' ' && c != '\n')
+ if (s < buf + sizeof(buf) - 1) *s++ = c;
+ if (s > buf)
+ {
+ *s = 0;
+ if (!stat(buf, &st))
+ printf("%s %ld\n", buf, (long)st.st_mtime - ref);
+ }
+ } while (c != EOF);
+ exit(0);
+}
diff --git a/src/cmd/ksh93/nval.3 b/src/cmd/ksh93/nval.3
new file mode 100644
index 0000000..9dc09a5
--- /dev/null
+++ b/src/cmd/ksh93/nval.3
@@ -0,0 +1,688 @@
+.fp 5 CW
+.TH NVAL 3 "12 Feb 2003"
+.SH NAME
+\fBnval\fR \- the \f5ksh\fP name/value library
+.SH SYNOPSIS
+.ta .8i 1.6i 2.4i 3.2i 4.0i
+.SS "HEADERS/LIBRARIES"
+.nf
+.ft 5
+#include <nval.h>
+libshell.a -lshell
+.ft R
+.fi
+.SS "DATA TYPES"
+.nf
+.ft 5
+Namval_t;
+Namfun_t;
+Namarr_t;
+Namdisc_t;
+.ft R
+.fi
+.SS "OPENING/CLOSING"
+.nf
+.ft 5
+Namval_t *nv_open(const char *\fIname\fP, Dt_t *\fIdict\fP, int \fIflags\fP);
+Namval_t *nv_create(const char *\fIname\fP, Dt_t *\fIdict\fP, int \fIflags\fP, Namfun_t *\fIfp\fP);
+Namval_t *nv_namptr(void *\fIptr\fP, int \fIindx\fP);
+void nv_close(Namval_t *\fInp\fP);
+void nv_delete(Namval_t *\fInp\fP, Dt_t *\fIdict\fP, int \fInofree\fP);
+.ft R
+.fi
+.SS "GETTING AND SETTING VALUES"
+.nf
+.ft 5
+char *nv_getval(Namval_t *\fInp\fP);
+Sfdouble_t nv_getnum(Namval_t *\fInp\fP);
+char *nv_name(Namval_t *\fInp\fP);
+void nv_putval(Namval_t *\fInp\fP, const char *\fIval\fP, int \fIflags\fP);
+void nv_unset(Namval_t *\fInp\fP, int \fIflags\fP);
+int nv_clone(Namval_t *\fIsrc\fP, Namval_t *\fIdest\fP, int \fIflags\fP);
+.ft R
+.fi
+.SS "ATTRIBUTES AND SIZE"
+.nf
+.ft 5
+int nv_isnull(Namval_t *\fInp\fP);
+int nv_setsize(Namval_t *\fInp\fP, int \fIsize\fP);
+int nv_size(Namval_t *\fInp\fP);
+unsigned nv_isattr(Namval_t *\fInp\fP, unsigned \fIflags\fP);
+Namfun_t *nv_isvtree(Namval_t *\fInp\fP);
+unsigned nv_onattr(Namval_t *\fInp\fP, unsigned \fIflags\fP);
+unsigned nv_offattr(Namval_t *\fInp\fP, unsigned \fIflags\fP);
+void nv_newattr(Namval_t *\fInp\fP, unsigned \fIflags\fP, int \fIsize\fP);
+.ft R
+.fi
+
+.SS "ARRAY HANDLING"
+.nf
+.ft 5
+unsigned nv_isarray(Namval_t *\fInp\fP);
+Namarr_t *nv_setarray(Namval_t *\fInp\fP,void*(*\fIfun\fP)(Namval_t*,const char*,int));
+Namarr_t *nv_arrayptr(Namval_t *\fInp\fP);
+Namval_t *nv_putsub(Namval_t *\fInp\fP, char *\fIname\fP, long \fImode\fP);
+Namval_t *nv_opensub(Namval_t *\fInp\fP);
+void nv_setvec(Namval_t *\fInp\fP, int \fIappend\fP, int \fIargc\fP, char *\fIargv\fP[]);
+char *nv_getsub(Namval_t *\fInp\fP);
+int nv_nextsub(Namval_t *\fInp\fP);
+int nv_aindex(Namval_t *\fInp\fP);
+.ft R
+.fi
+.SS "DISCIPLINES"
+.nf
+.ft 5
+Namfun_t *nv_disc(Namval_t *\fInp\fP, Namfun_t *\fIfp\fP, int \fIflags\fP);
+Namfun_t *nv_hasdisc(Namval_t *\fInp\fP, const Namdisc_t *\fIdp\fP);
+char *nv_getv(Namval_t *\fInp\fP, Namfun_t *\fIfp\fP);
+Sfdouble_t nv_getn(Namval_t *\fInp\fP, Namfun_t *\fIfp\fP);
+void nv_putv(Namval_t *\fInp\fP, const char *\fIval\fP, int \fIflags\fP, Namfun_t *\fIfp\fP);
+char *nv_setdisc(Namval_t *\fInp\fP, const char *\fIa\fP, Namval_t *\fIf\fP, Namfun_t *\fIfp\fP);
+char *nv_adddisc(Namval_t *\fInp\fP, const char **\fInames\fP);
+const Namdisc_t *nv_discfun(int \fIwhich\fP);
+.ft R
+.fi
+.SS "TYPES"
+.nf
+.ft 5
+Namval_t *nv_type(Namval_t *\fInp\fP);
+int *nv_settype(Namval_t *\fInp\fP, Namval_t *\fItp\fP, int \fIflags\fP);
+Namval_t *nv_mkinttype(char *\fIname\fP, size_t \fIsz\fP, int \fIus\fP, const char *\fIstr\fP, Namdisc_t *\fIdp\fP);
+void nv_addtype(Namval_t *\fInp\fP, const char *\fIstr\fP, Optdisc_t* *\fIop\fP, size_t \fIsz\fP);
+.ft R
+.fi
+.SS "MISCELLANEOUS FUNCTIONS"
+.nf
+.ft 5
+int nv_scan(Dt_t *\fIdict\fP, void(*\fIfn\fP)(Namval_t*,void*), void *\fIdata\fP, int \fImask\fP, int \fIflags\fP);
+Dt_t *nv_dict(Namval_t *\fInp\fP);
+void nv_setvtree(Namval_t *\fInp\fP);
+void nv_setref(Namval_t *\fInp\fP, Dt_t *\fIdp\fP, int \fIflags\fP);
+Namval_t *nv_lastdict(void);
+.ft R
+.fi
+.SH DESCRIPTION
+\fINval\fP is a library of functions for interacting with name-value
+pairs as used in \f5ksh\fP.
+It is built on top the container dictionary type library facility
+in \f5libcdt\fP. (See cdt(3)).
+Each name-value pair is represented by a
+type named \f5Namval_t\fP.
+A \f5Namval_t\fP contains the name, value and
+attributes of a variable.
+Some attributes can have an associated number that
+represents the field width, arithmetic base, or precision.
+Additionally, each name-value pair can be associated with
+one or more processing disciplines that affect
+its behavior.
+.PP
+The function \f5nv_open()\fP returns a pointer to a name-value
+pair corresponding to the given \fIname\fP.
+It can also assign a value and give attributes to a name-value pair.
+The argument \fIdict\fP defines the dictionary to search.
+A \f5NULL\fP value causes the shell global variable dictionary to be searched.
+.PP
+The \fIflags\fP argument consists of the bitwise-or of zero or more
+of the attributes listed later and zero or more of the following:
+.IP
+\f5NV_VARNAME\fP:
+An invalid variable name causes an error.
+.IP
+\f5NV_IDENTIFIER\fP:
+A variable name that is not an identifier causes an error.
+.IP
+\f5NV_ASSIGN\fP:
+The \fIname\fP argument can contain an assignment.
+.IP
+\f5NV_NOARRAY\fP:
+The \fIname\fP argument cannot contain a subscript.
+.IP
+\f5NV_NOREF\fP:
+Do not follow references when finding the name-value pair.
+.IP
+\f5NV_NOADD\fP:
+The name-value pair will not be added if it doesn't exist.
+Instead, a \f5NULL\fP pointer will be returned.
+.IP
+\f5NV_NOSCOPE\fP:
+Only the top level scope is used.
+.IP
+\f5NV_NOFAIL\fP:
+Just return \f5NULL\fP when an error occurs.
+By default an error message is displayed and the current command
+is aborted.
+.IP
+.PP
+If a name-value pair by this name does not already exist, it is
+created unless \fIflags\fP contains the \f5NV_NOADD\fP flag.
+If \f5NV_VARNAME\fP, \f5NV_IDENTIFIER\fP and \f5NV_ASSIGN\fP are
+all not specified, then no validity check is performed on the \fIname\fP
+argument and no further processing is performed.
+Otherwise, if \f5NV_ASSIGN\fP is specified, then the characters up
+to the first \f5=\fP or \f5+=\fP are used to find the name-value pair,
+and the characters after the \f5=\fP are used to define
+the value that will be assigned to this name-value pair.
+If \fIname\fP does not contain an \f5=\fP, than no assignment
+will be made.
+If the first identifier in \fIname\fP is a reference and is not
+preceded by a \fB.\fP,
+it will be replaced by the value of the reference
+to find the name of a variable.
+Unless \fIflags\fP contains the \f5NV_NOREF\fP flag,
+if the name-value pair give by \fIname\fP has the \f5NV_REF\fP
+attribute, it will be replaced by the variable whose name
+is the value of this name-value pair.
+If \f5NV_ASSIGN\fP is set in the \fIflags\fP argument,
+the \fIname\fP variable can contain an \f5=\fP
+and a value that will be assigned to the name-value pair.
+Any attributes appearing in the \fIflags\fP argument
+will be applied to the name-value pair after any value is assigned.
+.PP
+It is possible for an application to create additional dictionaries
+with the cdt library and associate them with name-value pairs.
+The \f5nv_dict()\fP function returns the dictionary associated with
+the specified name-value pair, or if no dictionary was specified,
+\f5NULL\fP is returned.
+The \f5nv_lastdict()\fP function returns a pointer the the
+name-value pair that contains
+the last dictionary searched on the previous \f5nv_open()\fP.
+.PP
+Name-value pairs can also be allocated without belonging to
+a dictionary. They will typically be looked up by a \fIcreate\fP
+discipline associated with a parent node. In this case the
+node size will be \f5NV_MINSZ\fP and \fIn\fP nodes can be allocated
+vial \f5calloc(5NV_MINSZ,\fIn\fP)\fP(3).
+The \f5nv_namptr\fP function can be used on the pointer returned by
+\f5calloc\fP along with the element number to return the
+corresponding node.
+Each of these nodes must be given the \f5NV_MINIMAL\fP attributes.
+.PP
+The \f5nv_close()\fP indicates that the pointer returned by
+\f5nv_open()\fP or \f5nv_opensub()\fP will not be referenced again. If the
+name-value pair is unset, and not referenced elsewhere,
+the name-value pair may be freed.
+.PP
+The \f5nv_delete()\fP function will remove the node \fInp\fP from
+the dictionary \fIdict\fP. Unless \fInofree\fP is non-zero, the
+node \fInp\fP will also be freed.
+.PP
+The \f5nv_name()\fP function returns the name of the given name-value
+pair \fInp\fP.
+The \f5nv_setsize()\fP function returns the size of the field for
+justified variables, the arithmetic base for integer variables,
+and the precision or number of places after the decimal point
+for floating point variables. If \fIsize\fP is greater than or
+equal to zero, the current size is changed to this value.
+The \f5nv_size()\fP function is equivalent to \f5nv_setsize()\fP
+with the second argument negative.
+.PP
+The \f5nv_getval()\fP function returns the value of the given
+name-value pair as a string. A \f5NULL\fP return value indicates
+that the name-value pair is unset.
+The \f5nv_getnum()\fP function returns the value of the given
+name-value pair as a double precision number using the \f5Sfio\fP
+library (See Sfio(3)) type \f5Sfdouble_t\fP.
+For name-value pairs without the \f5NV_INTEGER\fP attribute,
+the string value is evaluated as an arithmetic expression to
+arrive at a numerical value.
+.PP
+The \f5nv_putval()\fP function is used to assign a \fIvalue\fP to
+the name-value pair \fInp\fP.
+The \fIflags\fP argument consists zero or more of the bitwise-or
+of \f5NV_LONG\fP, \f5NV_SHORT\fP, \f5NV_DOUBLE\fP, \f5NV_INTEGER\fP,
+\f5NV_RDONLY\fP, \f5NV_REF\fP, \f5NV_BINARY\fP, and \f5NV_NOFREE\fP.
+The presence of \f5NV_RDONLY\fP allows the assignment to occur
+even if the name-value pair has the \f5NV_RDONLY\fP attribute.
+The presence of \f5NV_INTEGER\fP indicates that the \fIvalue\fP
+argument is actually a pointer to a numerical type.
+By default this type is \f5long\fP, but can be modified with
+\f5NV_LONG\fP, \f5NV_SHORT\fP, and \f5NV_DOUBLE\fP
+to represent \f5long long\fP, \f5short\fP, \f5double\fP, \f5long double\fP,
+and \f5float\fP.
+The presence of \f5NV_REF\fP indicates that the \fIvalue\fP
+argument is actually a pointer to a name-value pair
+and \f5np\fP should become a reference to this name-value pair.
+If \f5NV_NOFREE\fP is specified, \fIvalue\fP itself becomes
+the value of the name-value pair \fInp\fP.
+Otherwise, a copy of the value is stored
+as the value for \fInp\fP.
+.PP
+The \f5nv_unset()\fP function clears out the value and attributes
+of the given name-value function but does not free the name-value
+pair.
+If called from the \f5putval\fP discipline function, use the \fIflags\fP
+argument as the \fIflags\fP to \f5nv_unset()\fP. Otherwise, use 0.
+.PP
+The following attributes can be associated with a name-value pair:
+.IP
+\f5NV_EXPORT\fP:
+The export attribute.
+.IP
+\f5NV_RDONLY\fP:
+The readonly attribute.
+.IP
+\f5NV_LTOU\fP:
+Lower case characters are converted to upper case characters.
+.IP
+\f5NV_UTOL\fP:
+Upper case characters are converted to lower case characters.
+.IP
+\f5NV_RJUST\fP:
+Right justify and blank fill.
+This attribute has an associated size that defines the
+string length of the value.
+.IP
+\f5NV_LJUST\fP:
+Left justify and blank fill.
+This attribute has an associated size that defines the
+string length of the value.
+.IP
+\f5NV_ZFILL\fP:
+Without \f5NV_LJUST\fP, right justifies and fills with leading zeros.
+With \f5NV_LJUST\fP, left justify and strip leading zeros.
+Left justify and blank fill.
+This attribute has an associated size that defines the
+string length of the value.
+.IP
+\f5NV_TAGGED\fP:
+Indicates the tagged attribute.
+.IP
+\f5NV_INTEGER\fP:
+Causes value to be represented by a number.
+This attribute has an associated number that defines the
+arithmetic base to be used when the value is expanded as a string.
+.IP
+\f5NV_DOUBLE\fP:
+Used in conjunction with \f5NV_INTEGER\fP to cause value
+to be stored as a double precision floating point number.
+This attribute has an associated number that defines the
+number of places after the decimal point to be used when
+the value is expanded as a string.
+.IP
+\f5NV_EXPNOTE\fP:
+Used in conjunction with \f5NV_INTEGER\fP and \f5NV_DOUBLE\fP to
+cause the value to be represented in scientific notation when
+expanded as a string.
+This attribute has an associated number that defines the
+the precision of the mantissa.
+.IP
+\f5NV_HEXFLOAT\fP:
+Used in conjunction with \f5NV_INTEGER\fP and \f5NV_DOUBLE\fP to
+cause the value to be represented in C99 %a format when expanded as
+a string.
+.IP
+\f5NV_BINARY\fP:
+The name-value pair contains a buffer of binary data and \f5nv_size()\fP
+is the number of bytes for this data. By default the value
+will be represented by the base64 encoding of the buffer.
+The \f5NV_LJUST\fP flag may also be specified and causes the buffer
+size to be fixed and data either truncated or filled with \f50\fP bytes.
+.IP
+\f5NV_REF\fP:
+The name-value pair is a name reference variable.
+.IP
+\f5NV_MINIMAL\fP:
+The name-value pair node is not embedded in a dictionary
+and is minimal size, \f5NV_MINSZ\fP.
+.IP
+\f5NV_NODISC\fP:
+All discipline functions are ignored when performing assignments
+and lookups.
+.PP
+The \f5nv_isattr()\fP function can test whether or not any of
+the attributes given by \fIflags\fP is set.
+The \f5nv_onattr()\fP and \f5nv_offattr()\fP functions turn attributes
+on or off respectively. Only attributes that do not affect the
+value can be set in this way.
+The \f5nv_newattr()\fP function can be used to change the
+attributes and size of the given name-value pair which may result
+in the value being changed to conform to the new attributes and size.
+The \fIsize\fP argument is needed for attributes that require
+an additional argument such as justifies variables.
+Changing the attribute may require changing the value
+to agree with the new attributes.
+For an array variable, the values for each of the
+subscripts will be changed.
+.PP
+The \f5nv_isvtree()\fP function returns a pointer to the compound
+variable discipline if the node \fInp\fP is a compound variable
+or \f5NULL\fP otherwise.
+.PP
+The \f5nv_isarray()\fP function returns a non-zero value if the specified
+name-value pair is an array.
+.PP
+The \f5nv_scan()\fP function is used to walk through
+all name-value pairs in the dictionary given by \fIdict\fP.
+If the \f5flags\fP variable contains the \f5NV_NOSCOPE\fP
+flag, then only the top scope will be examined.
+The remaining flags will be used in conjunction with \fImask\fP
+to further restrict the walk.
+If \fImask\fP is non-zero, only the nodes for which
+\f5nv_isattr(\fP\fInode\fP\f5,\fP\fImask\fP\f5)\fP
+is equal to \fIflags\fP will be visited.
+If \fIfn\fP is non-zero, then this function will be executed
+for each name-value pair in the walk.
+The arguments to \fIfn\fP will be a pointer to the name-value pair
+and the \fIdata\fP pointer passed to \f5nv_scan()\fP.
+The number of elements visited will be returned.
+.PP
+The \f5nv_clone()\fP function is used make a copy of the contents of
+name-value pair \fIsrc\fP to another name-value pair \fIdest\fP.
+.PP
+Disciplines provide a way to
+intercept the lookup and assignment operations,
+to manage the creation of sub-variables,
+and to extend the operations permitted on a name-value pair.
+A discipline consists of a set of one or more functions and related
+data that are used to override and extend the operations
+on a name-value pair.
+A discipline is defined by the types
+\f5Namfun_t\fP and \f5Namdisc_t\fP.
+The \f5Namdisc_t\fP is not modified by any of these functions and
+can therefore be shared by several name-value pairs.
+It contains following public fields in the order listed:
+.nf
+ \f5size_t dsize;\fP
+ \f5void (*putval)(Namval_t*,const char*,int,Namfun_t*);\fP
+ \f5char *(*getval)(Namval_t*,Namfun_t*);\fP
+ \f5double (*getnum)(Namval_t*,Namfun_t*);\fP
+ \f5char *(*setdisc)(Namval_t*,const char*,Namval_t*,Namfun_t*);\fP
+ \f5Namval_t *(*createf)(Namval_t*,const char*,Namfun_t*);\fP
+ \f5Namfun_t *(*clonef)(Namval_t*,Namval_t*,int,Namfun_t*);\fP
+ \f5char *(*namef)(Namval_t*,Namfun_t*);\fP
+ \f5Namval_t *(*nextf)(Namval_t*,Dt_t*,Namfun_t*);\fP
+ \f5Namval_t *(*typef)(Namval_t*,Namfun_t*);\fP
+.fi
+The \f5Namfun_t\fP type contains a member named
+\f5disc\fP which points to a \f5Namdisc_t\fP structure.
+To create a discipline with additional user data,
+define a structure with an instance of \f5Namfun_t\fP
+as the first element.
+An application must initialize the \f5Namfun_t\fP portion of
+the structure to zero and then set the \fIdisc\fP field to point
+to the \f5Namdisc_t\fP structure.
+The \f5dsize\fP field of the \f5Namdisc_t\fP structure must be
+the size of this structure. A value of 0,
+indicates that there are no additional fields and is equivalent
+to \f5sizeof(Namfun_t)\fP.
+If different instances of this structure uses different sizes, then
+the \f5size\fP field in the \f5Namfun_t\fP can must be set to
+this size and overrides the value in the \f5Namdisc_t\fP structure.
+.PP
+When a variable is referenced by calling the \f5nv_getval()\fP function,
+and the \f5NV_NODISC\fP attribute is not set,
+the \f5getval()\fP discipline function is called with a pointer
+to the name-value pair, \fInp\fP, and a pointer to the discipline,
+\fIfp\fP.
+Inside the \f5getval()\fP function, the \f5nv_getv()\fP function
+can be called to get the value of the name-value pair that
+would have resulted if the discipline were not used.
+The \f5getnum()\fP discipline is called whenever a numerical
+value is needed for the name-value pair \fInp\fP
+and the \f5NV_NODISC\fP attribute is not set,
+The \f5nv_getn()\fP function can be called from within
+the \f5getnum()\fP discipline to get the value that would
+have resulted if there were no \f5getnum()\fP discipline.
+.PP
+The \f5putval\fP\f5()\fP discipline function is used to
+override the assignment of values
+to a name-value pair.
+It is called whenever a value is assigned with \f5nv_putval()\fP
+and the \f5NV_NODISC\fP attribute is not set,
+or when a name-value pair is unset with \f5nv_unset()\fP.
+When a name-value pair is unset, \f5putval\fP\f5()\fP
+is called with \fIvalue\fP set to \f5NULL\fP.
+The \f5nv_putv()\fP function is used within the \f5putval()\fP
+to perform the assignment or unset that would have occurred
+if the discipline had not been installed.
+.PP
+The \f5createf()\fP discipline function is called from
+\f5nv_open()\fP or \f5nv_create()\fP when the name-value pair preceding a
+.B \s+2.\s-2
+is found.
+This function is passed the name-value pointer plus the remaining string and
+the current \fIflags\fP argument.
+The \f5createf()\fP discipline function
+must return the created name-value pair, otherwise the default action
+will be taken.
+If the name-value pair that is returned is the same as the
+one given, then the the behavior will be the same as if
+an invalid name had been given to \f5nv_open()\fP.
+The \f5nv_create()\fP function may be called within
+the \f5createf()\fP discipline function
+to perform the action that would have occurred
+by an earlier \f5nv_open()\fP function.
+.PP
+The \f5setdisc()\fP discipline function is used
+to extend the set of available shell level discipline functions
+associated with a name-value pair by allowing
+builtins or functions whose name is of the
+form \fIvarname\fP\f5.\fP\fIaction\fP to be defined.
+By default, each name-value pair can have a \f5get\fP,
+\f5set\fP, and \f5unset\fP discipline associated with it.
+Whenever a builtin or function whose name is of the
+form \fIvarname\fP\f5.\fP\fIaction\fP is defined or is unset,
+and \fIaction\fP is not \f5get\fP,
+\f5set\fP, or \f5unset\fP, the \fIsetdisc\fP\f5()\fP function is invoked
+with the same argument format as \f5nv_setdisc\fP\f5()\fP.
+The argument \fIf\fP points to the name-value pair associated
+with the function being defined, or \f5NULL\fP if the function is
+being unset.
+If the given action \fIa\fP is not known by this discipline,
+it should return the value returned by calling
+\f5nv_setdisc(\fP\fInp\fP\f5,\fP\fIa\fP\f5,\fP\fIf\fP\f5,\fP\fIfp\fP\f5)\fP
+so that it can be searched for in previously stacked disciplines.
+Otherwise, the \fIsetdisc\fP\f5()\fP function should save the function
+name-value pair pointer, and return a non-\f5NULL\fP value.
+The name-value pointer to the function can be used to invoke
+the function at an application defined point.
+If the action \fIa\fP is \f5NULL\fP, then \fIf\fP points to
+an action name instead of a name-value pair pointer.
+The \fIsetdisc\fP\f5()\fP must return the
+name of the action that follows the action name given by
+\fIf\fP. If \fIf\fP is also \f5NULL\fP, the name of the first action
+must be returned.
+This allows an application to get the list of valid discipline
+action names allowed by a given name-value pair.
+.PP
+The \f5nv_adddisc()\fP function is a higher level function that
+adds a \fIsetdisc\fP discipline to the name-value pair that allows
+shell level disciplines to be created for each of the name specified
+in \f5names\fP.
+.PP
+The \f5nv_discfun()\fP function can be used to get a pointer to
+discipline functions that are provided by the library.
+Currently, the only one that is provided is the ones used to
+implement \f5nv_adddisc()\fP which can be returned with an
+argument of \f5NV_DCADD\fP.
+.PP
+The \f5clonef()\fP discipline function is called by \f5nv_clone()\fP
+when making a copy of the \f5Namfun_t\fP discipline to the new node.
+The first argument is the original node, the second argument is
+the new node, and the third argument is the flags that were passed
+down to \f5nv_clone()\fP.
+It must return a new instance of the \f5Namfun_t*\fP \f5fp\fP.
+If omitted, then memory whose size is determinated by the \f5size\fP
+field of \f5fp\fP, if non-zero, or \f5fp->disc\fP, will be allocated
+and copied from \f5fp\fP.
+.PP
+The \f5namef()\fP discipline function returns the name for this name-value pair.
+.PP
+The \f5nextf()\fP is used for walking through the list of sub-variables
+associated with this name-value pair. If the dictionary argument is
+\f5NULL\fP, it must return the first sub-variable. Otherwise,
+it must return the next sub-variable, or \f5NULL\fP if there are
+no more variables.
+.PP
+A discipline is installed or removed with the
+\f5nv_disc()\fP function.
+The following flags can be specified:
+.IP
+\f5NV_FIRST\fP:
+If \fIfp\fP is non-\f5NULL\fP, the discipline is moved to the top
+of the stack or pushed onto the top of the stack of disciplines
+associated with the given name-value
+pair \fInp\fP if not already present.
+Otherwise, the top of the discipline stack is returned.
+.IP
+\f5NV_LAST\fP:
+If \fIfp\fP is non-\f5NULL\fP, the discipline is moved to the bottom
+of the stack or pushed onto the bottom of the stack of disciplines
+associated with the given name-value
+pair \fInp\fP if not already present.
+Otherwise, the bottom of the discipline stack is returned.
+.IP
+\f5NV_POP\fP:
+If \fIfp\fP is non-\f5NULL\fP and it is on the stack,
+it is removed and \fIfp\fP is returned. If \fIfp\fP is non-\f5NULL\fP
+and is not on the stack, \f5NULL\fP is returned.
+Otherwise, the the top discipline is popped
+and returned.
+.IP
+\f5NV_CLONE\fP:
+If \fIfp\fP is non-\f5NULL\fP and it is on the stack,
+it is replace by a copy created by \f5malloc\fP(3).
+The \f5nofree\fP field is set to \f50\fP.
+The new discipline is returned.
+Otherwise, \f5NULL\fP is returned.
+.IP
+\f50\fP:
+If \fIfp\fP is non-\f5NULL\fP then it is equivalent to \f5NV_FIRST\fP.
+Otherwise, it is equivalent to \f5NV_POP\fP.
+.PP
+The
+\f5nv_hasdisc()\fP function can be used to tell whether a discipline
+whose discipline functions are those defined in \fIdp\fP.
+A pointer to this discipline is returned.
+.PP
+The \f5nv_aindex()\fP function returns
+the current index for
+the indexed array given by the name-value pair pointer \fInp\fP.
+The return value is negative if \fInp\fP refers to
+an associative array.
+.PP
+The \f5nv_setarray()\fP function is used to create an associative array
+from a name-value pair node.
+The function \fIfun\fP defines the semantics of the associative
+array.
+Using \fIfun\fP equal to \f5nv_associative()\fP implements the default
+associative array semantics
+that are used with \f5typeset\ -A\fP.
+The function \fIfun\fP will be called with third argument as follows:
+.IP
+\f5NV_AINIT\fP:
+This will be called at initialization.
+The function you supply must return a pointer to a structure
+that contains the type \f5Namarr_t\fP as the first element.
+All other calls receive this value as an argument.
+.IP
+\f5NV_AFREE\fP:
+This will be called after all elements of the name-value pair have been
+deleted and the array is to be freed.
+.IP
+\f5NV_ADELETE\fP:
+The current element should be deleted.
+.IP
+\f5NV_ANEXT\fP:
+This means that the array subscript should be advanced to the
+next subscript. A \f5NULL\fP return indicates that there are
+no more subscripts.
+.IP
+\f5NV_ANAME\fP:
+The name of the current subscript must be returned.
+.IP
+\f5NV_ACURRENT\fP:
+Returns a pointer to a name-value pair corresponding to the
+current subscript, or \f5NULL\fP if this array type doesn't
+create represent each element as a name-value pair.
+.IP
+\f5NV_ASETSUB\fP:
+Set the current subscript to the name-value pair passed in
+as the second argument.
+.PP
+If \fInp\fP refers to an array,
+\f5nv_arrayptr()\fP returns a pointer to
+the array discipline structure \f5Namarr_t\fP.
+Otherwise \f5nv_arrayptr()\fP returns \f5NULL\fP.
+.PP
+If \fInp\fP refers to an array,
+the \f5nv_getsub()\fP returns a pointer to
+the name of the current subscript.
+Otherwise, \f5nv_getsub()\fP
+returns \f5NULL\fP.
+.PP
+The \f5nv_opensub()\fP function returns
+a pointer to the name-value pair corresponding
+to the current subscript in an associative array.
+Note that the \f5nv_close()\fP function should be called
+when the pointer is no longer needed.
+.PP
+The \f5nv_putsub()\fP function is used to
+set the subscript for the next reference to \f5np\fP.
+If the \f5name\fP argument is not \f5NULL\fP,
+it defines the value of the next subscript.
+The \f5mode\fP argument can contain one or more of the following flags:
+.IP
+\f5ARRAY_ADD\fP:
+Add the subscript if not found.
+Otherwise, \f5nv_putsub()\fP returns \f5NULL\fP if the
+given subscript is not found.
+.IP
+\f5ARRAY_SCAN\fP:
+Begin a walk through the subscripts starting at the subscript
+given by \f5name\fP. If \f5name\fP is \f5NULL\fP
+the walk is started from the beginning.
+.IP
+\f5ARRAY_UNDEF\fP:
+This causes any current scan to terminate and leaves the
+subscript in an undefined state.
+.PP
+If \f5ARRAY_ADD\fP is not given and the subscript
+does not exist, a \f5NULL\fP value is returned.
+.PP
+The \f5nv_nextsub()\fP function is used to advance to the
+next subscript.
+It returns 0 if there are no more subscripts or if called
+when not in a scan.
+.PP
+The \f5nv_setref()\fP function makes the name-value pair \f5np\fP
+into a reference to the variable whose name is given by
+the value of \f5np\fP. The \f5nv_open()\fP open function is
+called with this name, the dictionary given by \f5dp\fP,
+and the \f5flags\fP argument.
+A \f5NULL\fP value causes the shell global variable dictionary to be searched.
+.PP
+The \f5nv_setvtree()\fP function makes the name-value pair \f5np\fP
+into a tree structured variable so that \f5nv_getval()\fP
+will return a string containing all the names and values of
+children nodes in a format that can be used in
+a shell compound assignment.
+.PP
+The \f5nv_type()\fP function returns a name_value pair pointer
+that contains the type definition for the specified name-value pair.
+The \fInvname\fP field contains the name for the type.
+.PP
+The \f5nv_settype()\fP function converts the name-value pair
+given by \fInp\fP into the type given by \fItp\fP.
+.PP
+The \f5nv_addtype()\fP function adds the name of the type given by
+\fInp\fP to the list of declaration built-ins. The \fIstr\fP
+argument contains the string used by \f5optget\fP(3) to generate
+the man page and process the options. The \fIop\fP argument
+specifies the callback discipline used by \f5optget\fP(3) and
+\fIsz\fP specifies the size of the callback information so
+that the discipline \fBoptget\fP(3) can be extended with private
+data used by the callback function.
+.P
+The \f5nv_mkinttype()\fP function creates named integer types
+of the specified \fIname\fP. The \fIsize\fP parameter is the size
+in bytes of the integer variable and \fIus\fP is non-zero
+for unsigned integer types. If \fIdp\fP is specified then integer
+variables of this type will all use this discipline.
+.SH SEE ALSO
+calloc(3)
+cdt(3)
+shell(3)
+optget(3)
+.SH AUTHOR
+David G. Korn (dgk@research.att.com).
diff --git a/src/cmd/ksh93/sh.1 b/src/cmd/ksh93/sh.1
new file mode 100644
index 0000000..27d8a9e
--- /dev/null
+++ b/src/cmd/ksh93/sh.1
@@ -0,0 +1,8142 @@
+.\"
+.\" David Korn
+.\" AT&T Bell Laboratories
+.\"
+.\" @(#)sh.1 (dgk@research.att.com) 12/28/93
+.\"
+.nr Z 1 \" set to 1 when command name is ksh, 2 for ksh93
+.ds OK [\|
+.ds CK \|]
+.ds ' \s+4\v@.3m@\'\v@-.3m@\s-4
+.ds ` \s+4\v@.3m@\`\v@-.3m@\s-4
+.if \nZ=0 \{\
+.TH SH 1
+.\}
+.if \nZ=1 \{\
+.TH KSH 1
+.\}
+.if \nZ=2 \{\
+.TH KSH93 1
+.\}
+.SH NAME
+.if \nZ=0 \{\
+sh, rsh, pfsh \- shell, the standard/restricted command and programming language
+.\}
+.if \nZ=1 \{\
+ksh, rksh, pfksh \- KornShell, a standard/restricted command and programming language
+.\}
+.if \nZ=2 \{\
+ksh93, rksh93, pfksh93 \- KornShell, a standard/restricted command and programming language
+.\}
+.SH SYNOPSIS
+.if \nZ=0 \{\
+.B sh
+.\}
+.if \nZ=1 \{\
+.B ksh
+.\}
+.if \nZ=2 \{\
+.B ksh93
+.\}
+[
+.B \(+-abcefhikmnoprstuvxBCDP
+] [
+.B \-R
+file ] [
+.B \(+-o
+option ] .\|.\|. [
+.B \-
+] [ arg .\|.\|. ]
+.br
+.if \nZ=0 \{\
+.B rsh
+.\}
+.if \nZ=1 \{\
+.B rksh
+.\}
+.if \nZ=2 \{\
+.B rksh93
+.\}
+[
+.B \(+-abcefhikmnoprstuvxBCD
+] [
+.B \-R
+file ] [
+.B \(+-o
+option ] .\|.\|. [
+.B \-
+] [ arg .\|.\|. ]
+.SH DESCRIPTION
+.if \nZ=0 .I Sh\^
+.if \nZ=1 .I Ksh\^
+.if \nZ=2 .I Ksh93\^
+is a command and programming language
+that executes commands read from a terminal
+or a file.
+.if \nZ=0 .I Rsh\^
+.if \nZ=1 .I Rksh\^
+.if \nZ=2 .I Rksh93\^
+is a restricted version of the
+.if \nZ=0 standard
+command interpreter
+.if \nZ=0 .IR sh ;
+.if \nZ=1 .IR ksh ;
+.if \nZ=2 .IR ksh93 ;
+it is used to set up login names and execution environments whose
+capabilities are more controlled than those of the standard shell.
+.if \nZ=0 .I Rpfsh\^
+.if \nZ=1 .I Rpfksh\^
+.if \nZ=2 .I Rpfksh93\^
+is a profile shell version of the
+.if \nZ=0 standard
+command interpreter
+.if \nZ=0 .IR sh ;
+.if \nZ=1 .IR ksh ;
+.if \nZ=2 .IR ksh93 ;
+it is used to to execute commands with the attributes specified by
+the user's profiles (see
+.IR pfexec (1)).
+See
+.I Invocation\^
+below
+for the meaning of arguments to the shell.
+.SS Definitions.
+A
+.I metacharacter\^
+is one of the following characters:
+.PP
+.RS
+\f3; & ( ) \(bv < > new-line space tab\fP
+.RE
+.PP
+A
+.I blank\^
+is a
+.B tab
+or a
+.BR space .
+An
+.I identifier\^
+is a sequence of letters, digits, or underscores
+starting with a letter or underscore.
+Identifiers are used as components of
+.I variable\^
+names.
+A
+.I vname\^
+is a sequence of one or more identifiers
+separated by a \fB\s+2.\s-2\fP and optionally preceded
+by a \fB\s+2.\s-2\fP.
+Vnames are used as function and variable names.
+A
+.I word\^
+is a sequence of
+.I characters\^
+from the character set defined by the current locale,
+excluding non-quoted
+.IR metacharacters .
+.PP
+A
+.I command\^
+is a sequence of characters in the syntax
+of the shell language.
+The shell reads each command and
+carries out the desired action either directly or by invoking
+separate utilities.
+A built-in command is a command that is carried out by the
+shell itself without creating a separate process.
+Some commands are built-in purely for convenience
+and are not documented here.
+Built-ins that cause
+side effects in the shell environment and
+built-ins that are found before performing a
+path search (see
+.I Execution\^
+below)
+are documented here.
+For historical reasons, some of
+these built-ins behave differently than
+other built-ins and are called
+.IR "special built-ins" .
+.SS Commands.
+A
+.I simple-command\^
+is a list of variable assignments
+(see
+.I Variable Assignments\^
+below)
+or a sequence of
+.I blank\^
+separated words
+which may be preceded by a list of variable assignments
+(see
+.I Environment\^
+below).
+The first word specifies the name of the command to
+be executed.
+Except as specified below,
+the remaining words are passed as arguments
+to the invoked command.
+The command name is passed as argument 0
+(see
+.IR exec (2)).
+The
+.I value\^
+of a simple-command is its exit status; 0-255
+if it terminates normally; 256+\f2signum\^\fP if
+it terminates abnormally (the name of the signal corresponding
+to the exit status can be
+obtained via the
+.B \-l
+option of the
+.B kill\^
+built-in utility).
+.PP
+A
+.I pipeline\^
+is a sequence of one or more
+.I commands\^
+separated by
+.BR \(bv .
+The standard output of each command but the last
+is connected by a
+.IR pipe (2)
+to the standard input of the next command.
+Each command,
+except possibly the last,
+is run as a separate process;
+the shell waits for the last command to terminate.
+The exit status of a pipeline is the exit
+status of the last command unless the
+.B pipefail
+option is enabled.
+Each pipeline can be preceded by the
+.I "reserved word"
+.B !
+which causes the exit status of the pipeline to become
+0 if the exit status of the last command is non-zero, and
+1 if the exit status of the last command is 0.
+.PP
+A
+.I list\^
+is a sequence of one or more
+pipelines
+separated by
+.BR ; ,
+.BR & ,
+.BR \(bv& ,
+.BR && ,
+or
+.BR \(bv\|\(bv ,
+and optionally terminated by
+.BR ; ,
+.BR & ,
+or
+.BR \(bv& .
+Of these five symbols,
+.BR ; ,
+.BR & ,
+and
+.B \(bv&
+have equal precedence,
+which is lower than that of
+.B &&
+and
+.BR \(bv\|\(bv .
+The symbols
+.B &&
+and
+.B \(bv\|\(bv
+also have equal precedence.
+A semicolon
+.RB ( ; )
+causes sequential execution of the preceding pipeline; an ampersand
+.RB ( & )
+causes asynchronous execution of the preceding pipeline (i.e., the shell does
+.I not\^
+wait for that pipeline to finish).
+The symbol
+.B \(bv&
+causes asynchronous execution of the preceding pipeline
+with a two-way pipe established to the parent shell;
+the standard input and output of the spawned pipeline
+can be written to and read from by the parent shell
+by applying
+the redirection operators
+.B <&
+and
+.B >&
+with arg
+.B p
+to commands and by using
+.B \-p
+option of
+the built-in commands
+.B read
+and
+.B print
+described later.
+The symbol
+.B &&
+.RB (\| \(bv\|\(bv \^)
+causes the
+.I list\^
+following it to be executed only if the preceding
+pipeline
+returns a zero (non-zero) value.
+One or more new-lines may appear in a
+.I list\^
+instead of a semicolon,
+to delimit a command.
+The first
+.I item \^
+of the first
+.I pipeline\^
+of a
+.I list\^
+that is a simple command not beginning
+with a redirection, and not occurring within a
+.BR while ,
+.BR until ,
+or
+.B if
+.IR list ,
+can be preceded by a semicolon.
+This semicolon
+is ignored unless the
+.B showme
+option is enabled as described with
+the
+.B set
+built-in below.
+.PP
+A
+.I command\^
+is either a simple-command
+or one of the following.
+Unless otherwise stated,
+the value returned by a command is that of the
+last simple-command executed in the command.
+.TP
+\f3for\fP \f2vname\^\fP \*(OK \f3in\fP \f2word\^\fP .\|.\|. \*(CK \f3;do\fP \f2list\^\fP \f3;done\fP
+Each time a
+.B for
+command is executed,
+.I vname\^
+is set to the next
+.I word\^
+taken from the
+.B in
+.I word\^
+list.
+If
+.BI in " word\^"
+\&.\|.\|.
+is omitted, then
+the
+.B for
+command executes the \f3do\fP \f2list\^\fP once for each positional parameter
+that is set starting from
+.B 1
+(see
+.I "Parameter Expansion\^"
+below).
+Execution ends when there are no more words in the list.
+.TP
+\f3for ((\fP \*(OK\f2expr1\^\fP\*(CK \f3;\fP \*(OK\f2expr2\^\fP\*(CK \f3;\fP \*(OK\f2expr3\^\fP\*(CK \f3))\fP \f3;do\fP \f2list\^\fP \f3;done\fP
+The arithmetic expression
+.I expr1
+is evaluated first
+(see
+.I "Arithmetic evaluation"
+below).
+The arithmetic expression
+.I expr2
+is repeatedly evaluated until it evaluates to zero and when non-zero,
+.I list
+is executed and the arithmetic expression
+.I expr3
+evaluated.
+If any expression
+is omitted, then it behaves as if it evaluated to 1.
+.TP
+\f3select\fP \f2vname\^\fP \*(OK \f3in\fP \f2word\^\fP .\|.\|. \*(CK \f3;do\fP \f2list\^\fP \f3;done\fP
+A
+.B select
+command prints on standard error (file descriptor 2) the set of
+.IR word s,
+each preceded by a number.
+If
+.BI in " word\^"
+\&.\|.\|.
+is omitted, then
+the
+positional parameters starting from
+.B 1
+are used instead
+(see
+.I "Parameter Expansion\^"
+below).
+The
+.SM
+.B PS3
+prompt is printed
+and a line is read from the standard input.
+If this line consists of the number
+of one of the listed
+.IR word s,
+then the value of the variable
+.I vname\^
+is set to the
+.I word\^
+corresponding to this number.
+If this line is empty, the selection list is
+printed again.
+Otherwise the value of the variable
+.I vname\^
+is set to
+.IR null .
+The contents of the line read from standard input is
+saved in
+the variable
+.SM
+.BR REPLY .
+The
+.I list\^
+is executed for each selection until a
+.B break\^
+or
+.I end-of-file\^
+is encountered.
+If the
+.SM
+.B REPLY
+variable is set to
+.I null\^
+by the execution of
+.IR list ,
+then the selection list is printed before
+displaying the
+.SM
+.B PS3
+prompt for the next selection.
+.TP
+\f3case\fP \f2word\^\fP \f3in\fP \*(OK \*(OK\f3(\fP\*(CK\f2pattern\^\fP \*(OK \(bv \f2pattern\^\fP \*(CK .\|.\|. \f3)\fP \f2list\^\fP \f3;;\fP \*(CK .\|.\|. \f3esac\fP
+A
+.B case
+command executes the
+.I list\^
+associated with the first
+.I pattern\^
+that matches
+.IR word .
+The form of the patterns is
+the same as that used for
+file-name generation (see
+.I "File Name Generation\^"
+below).
+The
+.B ;;
+operator causes execution of
+.B case
+to terminate.
+If
+.B ;&
+is used in place of
+.B ;;
+the next subsequent list, if any, is executed.
+.TP
+\f3if\fP \f2list\^\fP \f3;then\fP \f2list\^\fP \*(OK \
+\f3;elif\fP \f2list\^\fP \f3;then\fP \f2list\^\fP \*(CK .\|.\|. \
+\*(OK \f3;else\fP \f2list\^\fP \*(CK \f3;f\&i\fP
+The
+.I list\^
+following \f3if\fP is executed and,
+if it
+returns a zero exit status, the
+.I list\^
+following
+the first
+.B then
+is executed.
+Otherwise, the
+.I list\^
+following \f3elif\fP
+is executed and, if its value is zero,
+the
+.I list\^
+following
+the next
+.B then
+is executed.
+Failing each successive
+.B elif
+.IR list\^ ,
+the
+.B else
+.I list\^
+is executed.
+If the
+.B if
+.I list\^
+has non-zero exit status
+and there is no
+.B else
+.IR list ,
+then the
+.B if
+command returns a zero exit status.
+.TP
+.PD 0
+\f3while\fP \f2list\^\fP \f3;do\fP \f2list\^\fP \f3;done\fP
+.TP
+\f3until\fP \f2list\^\fP \f3;do\fP \f2list\^\fP \f3;done\fP
+.PD
+A
+.B while
+command repeatedly executes the
+.B while
+.I list\^
+and, if the exit status of the last command in the list is zero, executes
+the
+.B do
+.IR list ;
+otherwise the loop terminates.
+If no commands in the
+.B do
+.I list\^
+are executed, then the
+.B while
+command returns a zero exit status;
+.B until
+may be used in place of
+.B while
+to negate
+the loop termination test.
+.TP
+\f3((\fP\f2expression\^\fP\f3))\fP
+.br
+The
+.I expression\^
+is evaluated using the rules for arithmetic evaluation described below.
+If the value of the arithmetic expression is non-zero, the exit
+status is 0, otherwise the exit status is 1.
+.TP
+\f3(\fP\f2list\^\fP\f3)\fP
+.br
+Execute
+.I list\^
+in a separate environment.
+Note, that if two adjacent open parentheses are
+needed for nesting, a space must be inserted to avoid
+evaluation as an arithmetic command as described above.
+.TP
+\f3{ \fP\f2list\^\fP\f3;}\fP
+.br
+.I list\^
+is simply executed.
+Note that unlike the metacharacters
+.B (
+and
+.BR ) ,
+.B {
+and
+.B }
+are
+.IR "reserved word" s
+and must occur
+at the beginning of a line or after a
+.B ;
+in order to be recognized.
+.TP
+\f3[[\fP\f2 expression \^\fP\f3]]\fP
+.br
+Evaluates
+.I expression\^
+and returns a zero exit status when
+.I expression\^
+is true.
+See
+.I "Conditional Expressions\^"
+below, for a description of
+.IR expression .
+.TP
+.PD 0
+\f3function\fP \f2varname\^\fP \f3{\fP \f2list\^\fP \f3;}\fP
+.TP
+\f2varname\^\fP \f3() {\fP \f2list\^\fP \f3;}\fP
+.PD
+Define a function which is referenced by
+.IR varname .
+A function whose
+.I varname\^
+contains a
+.B \s+2.\s-2
+is called a discipline function and the portion
+of the
+.I varname\^
+preceding the last
+.B \s+2.\s-2
+must refer to an existing variable.
+The body of the function is the
+.I list\^
+of commands between
+.B {
+and
+.BR } .
+A function defined with the \f3function\fP \f2varname\^\fP
+syntax can also be used as an argument to the \f3.\fP
+special built-in command to get the equivalent behavior
+as if the \f2varname\^\fP\f3()\fP syntax were used to define it.
+(See
+.I Functions\^
+below.)
+.TP
+\f3namespace\fP \f2identifier\^\fP \f3{\fP \f2list\^\fP \f3;}\fP
+.br
+Defines or uses the name space
+.I identifier\^
+and runs the commands in
+.I list\^
+in this name space.
+(See
+.I Name Spaces\^
+below.)
+.TP
+\f3&\fP \*(OK \f2name\^\fP \*(OK \f2arg...\^\fP \*(CK \*(CK
+Causes subsequent
+.I list\^
+commands terminated by
+.B &
+to be placed in the background job pool
+.IR name .
+If
+.I name\^
+is omitted a default unnamed pool is used.
+Commands in a named background pool may be executed remotely.
+.TP
+\f3time\fP \*(OK \f2pipeline\^\fP \*(CK
+.br
+If \f2pipeline\^\fP is omitted the user and system time for
+the current shell and completed child processes is printed
+on standard error.
+Otherwise,
+.I pipeline\^
+is executed and the elapsed time as well as
+the user and system time are printed on standard error.
+The
+.SM
+.B TIMEFORMAT
+variable may be set to a format string that specifies how the timing
+information should be displayed.
+See
+.B "Shell Variables"
+below
+for a description of the
+.SM
+.B TIMEFORMAT
+variable.
+.PP
+The following reserved words
+are recognized as reserved only when they are the first word of a command
+and are not quoted:
+.PP
+.if t .RS
+.B
+.if n if then else elif fi case esac for while until do done { } function select time [[ ]] !
+.if t if then else elif fi case esac for while until do done { } function select time [[ ]] !
+.if t .RE
+.SS Variable Assignments.
+One or more variable assignments can start a simple command
+or can be arguments to the
+.BR typeset ,
+.BR enum ,
+.BR export ,
+or
+.B readonly
+special built-in commands as well as
+to other declaration commands created as types.
+The syntax for an \f2assignment\^\fP is of the form:
+.TP
+.PD 0
+\f2varname\^\fP\f3=\fP\f2word\^\fP
+.TP
+\f2varname\^\fP\f3[\fP\f2word\^\fP\f3]\fP=\fP\f2word\^\fP
+.PD
+No space is permitted between \f2varname\^\fP and the \f3=\fP or
+between \f3=\fP and \fIword\^\fP.
+.TP
+\f2varname\^\fP\f3=(\fP\f2assign_list\^\fP\f3)\fP
+No space is permitted between \f2varname\^\fP and the \f3=\fP.
+The variable
+.I varname
+is unset before the assignment.
+An \f2assign_list\^\fP can be one of the following:
+.RS 15
+.PD 0
+.TP
+\f2word\^\fP ...
+Indexed array assignment.
+.TP
+\f3[\fP\f2word\^\fP\f3]=\fP\f2word\^\fP .\|.\|.
+Associative array assignment.
+If preceded by
+.B typeset \-a
+this will create an indexed array instead.
+.TP
+\f2assignment\^\fP .\|.\|.
+Compound variable assignment.
+This creates a compound variable \f2varname\^\fP with
+sub-variables of the form \f2varname\^\fP\f3.\fP\f2name\^\fP,
+where \f2name\^\fP is the name portion of \f2assignment\^\fP.
+The value of \f2varname\^\fP will contain all the assignment elements.
+Additional assignments made to sub-variables of \f2varname\^\fP
+will also be displayed as part of the value of \f2varname\^\fP.
+If no \f2assignment\fPs are specified, \f2varname\^\fP will be
+a compound variable allowing subsequence child elements to be defined.
+.TP
+\f3typeset\fP \*(OK\f2options\fP\*(CK \f2assignment\^\fP .\|.\|.
+Nested variable assignment. Multiple assignments
+can be specified by separating each of them with a \f3;\fP.
+The previous value is unset before the assignment.
+Other declaration commands such as
+.BR readonly,
+.BR enum ,
+and
+other declaration commands can be used in place of
+.BR typeset .
+.TP
+\f3\|.\fP \f2filename\^\fP
+Include the assignment commands contained in
+.IR filename .
+.PD
+.RE
+.PP
+In addition, a \f3+=\fP can be used in place of the \f3=\fP
+to signify adding to or appending to the previous value.
+When \f3+=\fP is applied to an arithmetic type, \f2word\^\fP
+is evaluated as an arithmetic expression and added to the current value.
+When applied to a string variable, the value defined by \f2word\^\fP
+is appended to the value. For compound assignments, the previous
+value is not unset and the new values are appended to the
+current ones provided that the types are compatible.
+.PP
+The right hand side of a variable assignment undergoes all the expansion
+listed below except word splitting, brace expansion, and file name generation.
+When the left hand side is an assignment is a compound variable and
+the right hand is the name of a compound variable, the compound variable
+on the right will be copied or appended to the compound variable on the left.
+.SS Comments.
+.PD 0
+A word beginning with
+.B #
+causes that word and all the following characters up to a new-line
+to be ignored.
+.SS Aliasing.
+The first word of each command is replaced by the text of an
+.B alias
+if an
+.B alias
+for this word has been defined.
+An
+.B alias
+name consists of any number of characters excluding metacharacters,
+quoting characters,
+file expansion characters,
+parameter expansion and command substitution
+characters,
+the characters
+.B /
+and
+.BR = .
+The replacement string can contain any
+valid shell script
+including the metacharacters listed above.
+The first word of each command in the
+replaced text,
+other than
+any that are in the process of being replaced,
+will be tested for aliases.
+If the last character of the alias value is a
+.I blank\^
+then the word following the alias will also be checked for alias
+substitution.
+Aliases can be used to redefine
+built-in commands but cannot be used to redefine
+the reserved words listed above.
+Aliases can be created and listed with the
+.B alias
+command and can be removed with the
+.B unalias
+command.
+.PP
+.I Aliasing\^
+is performed when
+scripts are read,
+not while they are executed.
+Therefore,
+for an alias to take effect,
+the
+.B
+alias
+definition command has to be executed before
+the command which references the alias is read.
+.PP
+The following aliases
+are compiled into the shell
+but can be unset or redefined:
+.RS 20
+.PD 0
+.TP
+.B "autoload=\(fmtypeset \-fu\(fm"
+.TP
+.B "command=\(fmcommand \(fm"
+.TP
+.B "compound=\(fmtypeset \-C\(fm"
+.TP
+.B "fc=hist"
+.TP
+.B "float=\(fmtypeset \-lE\(fm"
+.TP
+.B "functions=\(fmtypeset \-f\(fm"
+.TP
+.B "hash=\(fmalias \-t \-\^\-\(fm"
+.TP
+.B "history=\(fmhist \-l\(fm"
+.TP
+.B "integer=\(fmtypeset \-li\(fm"
+.TP
+.B "nameref=\(fmtypeset \-n\(fm"
+.TP
+.B "nohup=\(fmnohup \(fm"
+.TP
+.B "r=\(fmhist \-s\(fm"
+.TP
+.B "redirect=\(fmcommand exec\(fm"
+.TP
+.B "source=\(fmcommand \s+2.\s-2\(fm"
+.TP
+.B "stop=\(fmkill \-s \s-1STOP\s+1\(fm"
+.TP
+.B "suspend=\(fmkill \-s \s-1STOP\s+1 $$\(fm"
+.TP
+.B "times=\(fm{ { time;} 2>&1;}\(fm"
+.TP
+.B "type=\(fmwhence \-v\(fm"
+.PD
+.RE
+.SS Tilde Substitution.
+After alias substitution is performed, each word
+is checked to see if it begins with an unquoted
+.BR \(ap .
+For tilde substitution,
+.I word\^
+also refers to the
+.I word\^
+portion of parameter expansion
+(see
+.I "Parameter Expansion\^"
+below).
+If it does, then the word up to a
+.B /
+is checked to see if it matches a user name in the
+password database (See
+.IR getpwname (3).)
+If a match is found, the
+.B \(ap
+and the matched login name are replaced by the
+login directory of the matched user.
+If no match is found, the original text is left unchanged.
+A
+.B \(ap
+by itself, or in front of a
+.BR / ,
+is replaced by
+.SM
+.BR $HOME .
+A
+.B \(ap
+followed by a
+.B +
+or
+.B \-
+is replaced by the value of
+.B
+.SM $PWD
+and
+.B
+.SM $OLDPWD
+respectively.
+.PP
+In addition,
+when expanding a
+.IR "variable assignment" ,
+.I tilde
+substitution is attempted when
+the value of the assignment
+begins with a
+.BR \(ap ,
+and when a
+.B \(ap
+appears after a
+.BR : .
+The
+.B :
+also terminates a
+.B \(ap
+login name.
+.SS Command Substitution.
+The standard output from a command list enclosed in
+parentheses preceded by a dollar sign (
+\f3$(\fP\f2list\^\fP\f3)\fP
+),
+or in a brace group preceded by a dollar sign (
+\f3${ \fP\f2list\^\fP\f3;}\fP
+), or in a pair of grave accents (\^\f3\*`\^\*`\fP\^)
+may be used as part or all
+of a word;
+trailing new-lines are removed.
+In the second case, the \f3{\fP and \f3}\fP are treated as a reserved words
+so that \f3{\fP must be followed by a \f2blank\^\fP and \f3}\fP must
+appear at the beginning of the line or follow a \f3;\fP.
+In the third (obsolete) form, the string between the quotes is processed
+for special quoting characters before the command is executed (see
+.I Quoting\^
+below).
+The command substitution
+\^\f3$(\^cat file\^)\fP\^
+can be replaced by the equivalent but faster
+\^\f3$(\^<file\^)\fP\^.
+The command substitution
+\^\f3$(\^\fP\f2n\^\fP\f3<#\^)\fP
+will expand to the current byte offset for file descriptor
+.IR n .
+Except for the second form, the command list is run in a subshell so that no
+side effects are possible.
+For the second form, the final
+.B }
+will be recognized as a reserved word after any token.
+.SS Arithmetic Substitution.
+An arithmetic expression enclosed in double
+parentheses preceded by a dollar sign (
+.B $((\|))
+)
+is replaced by the value of the arithmetic expression
+within the double parentheses.
+.SS Process Substitution.
+Each command argument of the form
+\f3<(\fP\f2list\^\fP\f3)\fP
+or
+\f3>(\fP\f2list\^\fP\f3)\fP
+will run process
+.I list
+asynchronously connected to some file in
+.B /dev/fd
+if this directory exists, or else a fifo a temporary directory.
+The name of this file will become the argument to the command.
+If the form with
+.B >
+is selected then writing on this file will provide input for
+.IR list .
+If
+.B <
+is used,
+then the file passed as an argument will contain the output of the
+.I list
+process.
+For example,
+.PP
+.RS
+\f3paste <(cut \-f1\fP \f2file1\fP\f3) <(cut \-f3\fP \f2file2\f3) | tee >(\fP\f2process1\fP\f3) >(\fP\f2process2\fP\f3)\fP
+.RE
+.PP
+.I cuts
+fields 1 and 3 from
+the files
+.I file1
+and
+.I file2
+respectively,
+.I pastes
+the results together, and
+sends it
+to the processes
+.I process1
+and
+.IR process2 ,
+as well as putting it onto the standard output.
+Note that the file, which is passed as an argument to the command,
+is a UNIX
+.IR pipe (2)
+so programs that expect to
+.IR lseek (2)
+on the file will not work.
+.PP
+Process substitution of the form
+\f3<(\fP\f2list\^\fP\f3)\fP
+can also be used with the
+.B <
+redirection operator which causes the output of
+.I list\^
+to be standard input or the input for whatever file descriptor is specified.
+.SS Parameter Expansion.
+A
+.I parameter\^
+is a
+.IR variable ,
+one or more digits,
+or any of the characters
+.BR \(** ,
+.BR @ ,
+.BR # ,
+.BR ? ,
+.BR \- ,
+.BR $ ,
+and
+.BR !\\^ .
+A
+.I variable\^
+is denoted by a \f2vname\fP.
+To create a variable whose
+.I vname\^
+contains a \f3\s+2.\s-2\fP,
+a variable whose
+.I vname\^
+consists of everything before the last \f3\s+2.\s-2\fP must already exist.
+A
+.I variable\^
+has a
+.I value\^
+and zero or more
+.IR attributes .
+.I Variables\^
+can be assigned
+.I values\^
+and
+.I attributes
+by using the
+.B typeset\^
+special built-in command.
+The attributes supported by the shell are described
+later with the
+.B typeset\^
+special built-in command.
+Exported variables pass values and attributes to
+the environment.
+.PP
+The shell supports both indexed and associative arrays.
+An element of an array variable is referenced by a
+.IR subscript .
+A
+.I subscript\^
+for an indexed array is denoted by
+an
+.I arithmetic expression\^
+(see
+.I "Arithmetic evaluation"
+below)
+between a
+.B [
+and a
+.BR ] .
+To assign values to an indexed array, use
+\f2vname\fP\f3=(\fP\f2value\fP .\|.\|.\f3)\fP or
+\f3set \-A\fP \f2vname\fP \f2value\fP .\|.\|. .
+The value of all non-negative
+subscripts must be in the
+range of
+0 through 4,194,303.
+A negative subscript is treated as an offset from the maximum
+current index +1 so that \-1 refers to the last element.
+Indexed arrays can be declared with the
+.B \-a
+option to
+.BR typeset.
+Indexed arrays need not be declared.
+Any reference to a variable
+with a valid subscript is
+legal and an array will be created if necessary.
+.PP
+An associative array is created with the
+.B \-A
+option to
+.BR typeset.
+A
+.I subscript\^
+for an associative array is denoted by
+a string enclosed between
+.B [
+and
+.BR ] .
+.PP
+Referencing any array without a subscript
+is equivalent to referencing the array with subscript 0.
+.PP
+The
+.I value\^
+of a
+.I variable\^
+may be assigned by writing:
+.PP
+.RS
+.IB vname = value\^\|
+\*(OK
+.IB vname = value\^
+\*(CK .\|.\|.
+.RE
+.PP
+.PD 0
+or
+.PP
+.RS
+.IB vname [ subscript ]= value\^\|
+\*(OK
+.IB vname [ subscript ]= value\^
+\*(CK .\|.\|.
+.sp .5
+.RE
+Note that no space is allowed before or after the
+.BR = .
+.sp .5
+.PP
+.PD 0
+Attributes assigned by the
+.I typeset\^
+special built-in command apply to all elements of the array.
+An array element can be a simple variable, a compound variable or an
+array variable. An element of an indexed array can be either an indexed
+array or an associative array. An element of an associative array can also
+be either. To refer to an array element that is part of an array
+element, concatenate the subscript in brackets. For example, to refer
+to the
+.I foobar\^
+element of an associative array that is defined as the
+third element of the indexed array, use
+.BI ${ vname [ 3 ][ foobar ]}
+.sp .5
+.PP
+.PD 0
+A
+.I nameref\^
+is a variable that is a reference to another variable.
+A nameref is created with the
+.B \-n
+attribute of
+.BR typeset .
+The value of the variable at the time of the
+.B typeset
+command becomes the variable that will be referenced whenever
+the nameref variable is used.
+The name of a nameref cannot contain a \fB\s+2.\s-2\fP.
+When a variable or function name contains a \fB\s+2.\s-2\fP, and the portion
+of the name up to the first \fB\s+2.\s-2\fP matches the
+name of a nameref, the variable referred to is obtained by
+replacing the nameref portion with the name of the variable
+referenced by the nameref.
+If a nameref is used as the index of a \fBfor\fP loop,
+a name reference is established for each item in the list.
+A nameref provides a convenient way to refer to the variable
+inside a function whose name is passed as an argument to a function.
+For example, if the name of a variable is passed as the first
+argument to a function, the command
+.PP
+.RS
+\fBtypeset \-n var=$1\fR
+.RE
+.PP
+inside the function causes references and assignments to
+.B var
+to be references and assignments to the variable whose
+name has been passed to the function.
+.sp .5
+.PP
+If any of the floating point attributes,
+.BR \-E ,
+.BR \-F ,
+or
+.BR \-X ,
+or the integer attribute,
+.BR \-i ,
+is set for
+.IR vname ,
+then the
+.I value\^
+is subject to arithmetic evaluation as described below.
+.sp .5
+.PP
+Positional parameters,
+parameters denoted by a number,
+may be assigned values with the
+.B set\^
+special built-in command.
+Parameter
+.B $0
+is set from argument zero when the shell
+is invoked.
+.sp .5
+.PP
+The character
+.B $
+is used to introduce substitutable
+.IR parameters .
+.TP
+\f3${\fP\f2parameter\^\fP\f3}\fP
+The shell
+reads all the characters from
+.B ${
+to the matching
+.B }
+as part of the same word even if it contains
+braces or metacharacters.
+The value, if any, of the parameter is substituted.
+The braces are required when
+.I parameter\^
+is followed by a letter, digit, or underscore
+that is not to be interpreted as part of its name,
+when the variable name contains a \fB\s+2.\s-2\fP.
+The braces are also required when a variable is subscripted
+unless it is part of an Arithmetic Expression
+or a Conditional Expression.
+If
+.I parameter\^
+is one or more digits then it is a positional parameter.
+A positional parameter of more than one digit must be
+enclosed in braces.
+If
+.I parameter\^
+is
+.B \(**
+or
+.BR @ ,
+then all the positional
+parameters, starting with
+.BR $1 ,
+are substituted
+(separated by a field separator character).
+If an array
+.I vname\^
+with last subscript
+.B \(**
+.BR @ ,
+or for index arrays of the form
+.I sub1\^
+.B ..
+.IR sub2 .
+is used,
+then the value
+for each of the
+elements between
+.I sub1\^
+and
+.I sub2\^
+inclusive (or all elements for
+.B \(**
+and
+.BR @ )
+is substituted,
+separated by
+the first character of
+the value of
+.SM
+.BR IFS .
+.TP
+\f3${#\fP\f2parameter\^\fP\f3}\fP
+If
+.I parameter\^
+is
+.B \(**
+or
+.BR @ ,
+the number of positional parameters is substituted.
+Otherwise, the length of the value of the
+.I parameter\^
+is substituted.
+.TP
+.PD 0
+\f3${#\fP\f2vname\fP\f3[*]}\fP
+.TP
+.PD
+\f3${#\fP\f2vname\fP\f3[@]}\fP
+The number of elements in the array
+.I vname\^
+is substituted.
+.TP
+.PD 0
+\f3${@\fP\f2vname\^\fP\f3}\fP
+Expands to the type name (See
+.I "Type Variables"\^
+below) or attributes of the variable referred to by
+.IR vname .
+.TP
+\f3${!\fP\f2vname\^\fP\f3}\fP
+Expands to the name of the variable referred to by
+.IR vname .
+This will be
+.I vname\^
+except when
+.I vname\^
+is a name reference.
+.TP
+\f3${!\fP\f2vname\^\fP\f3[\f2subscript\^\f3]}\fP
+Expands to name of the subscript unless
+.I subscript\^
+is
+.BR * ,
+.BR @ .
+or of the form
+.I sub1\^
+.B ..
+.IR sub2 .
+When
+.I subscript\^
+is
+.BR * ,
+the list of array subscripts for \f2vname\^\fP
+is generated.
+For a variable that is not an array, the value is 0 if the variable
+is set. Otherwise it is null.
+When
+.I subscript\^
+is
+.BR @ ,
+same as above, except that when used in double quotes,
+each array subscript yields a separate
+argument.
+When
+.I subscript\^
+is of the form
+.I sub1\^
+.B ..
+.I sub2\^
+it expands
+to the list of subscripts between
+.I sub1\^
+and
+.I sub2\^
+inclusive using the same quoting rules as
+.BR @ .
+.TP
+\f3${!\fP\f2prefix\^\fP\f3*}\fP
+Expands to the names of the variables whose names begin with
+.IR prefix .
+.TP
+\f3${\fP\f2parameter\^\fP\f3:\-\fP\f2word\^\fP\f3}\fP
+If
+.I parameter\^
+is set and is non-null then substitute its value;
+otherwise substitute
+.IR word .
+.TP
+\f3${\fP\f2parameter\^\fP\f3:=\fP\f2word\^\fP\f3}\fP
+If
+.I parameter\^
+is not set or is null then set it to
+.IR word ;
+the value of the parameter is then substituted.
+Positional parameters may not be assigned to
+in this way.
+.TP
+\f3${\fP\f2parameter\^\fP\f3:?\fP\f2word\^\fP\f3}\fP
+If
+.I parameter\^
+is set and is non-null then substitute its value;
+otherwise, print
+.I word\^
+and exit from the shell (if not interactive).
+If
+.I word\^
+is omitted then a standard message is printed.
+.TP
+\f3${\fP\f2parameter\^\fP\f3:+\fP\f2word\^\fP\f3}\fP
+If
+.I parameter\^
+is set and is non-null then substitute
+.IR word ;
+otherwise substitute nothing.
+.PP
+In the above,
+.I word\^
+is not evaluated unless it is
+to be used as the substituted string,
+so that, in the following example,
+.B pwd
+is executed only if
+.B d
+is not set or is null:
+.PP
+.RS
+print \|${d:\-\^$(\^pwd\^)\^}
+.RE
+.PP
+If the colon (
+.B : )
+is omitted from the above expressions,
+then the shell only checks whether
+.I parameter\^
+is set or not.
+.TP
+.PD 0
+\f3${\fP\f2parameter\^\fP\f3:\fP\f2offset\^\fP\f3:\fP\f2length\^\fP\f3}\fP
+.TP
+\f3${\fP\f2parameter\^\fP\f3:\fP\f2offset\^\fP\f3}\fP
+Expands to the portion of the value of
+.I parameter\^
+starting at the character (counting from
+.BR 0\^ )
+determined by expanding
+.I offset\^
+as an arithmetic expression and consisting of the
+number of characters determined by the arithmetic expression
+defined by
+.IR length.
+In the second form, the remainder of the value is used.
+If
+A negative
+.I offset\^
+counts backwards from the end of
+.IR parameter .
+Note that one or more
+.IR blank s
+is required in front of a minus sign
+to prevent the shell from interpreting the operator as
+.BR :\- .
+If
+.I parameter\^
+is
+.B \(**
+or
+.BR @ ,
+or is an array name indexed by
+.B \(**
+or
+.BR @ ,
+then
+.I offset\^
+and
+.I length\^
+refer to the array index and number
+of elements respectively.
+A negative
+.I offset\^
+is taken relative to one greater than the highest subscript
+for indexed arrays.
+The order for associate arrays is unspecified.
+.TP
+.PD 0
+\f3${\fP\f2parameter\^\fP\f3#\fP\f2pattern\^\fP\f3}\fP
+.TP
+\f3${\fP\f2parameter\^\fP\f3##\fP\f2pattern\^\fP\f3}\fP
+.PD
+If
+the shell
+.I pattern\^
+matches the beginning of the value of
+.IR parameter ,
+then the value of
+this expansion is the value of the
+.I parameter\^
+with the matched portion deleted;
+otherwise the value of this
+.I parameter\^
+is substituted.
+In the first form the smallest matching pattern is deleted and in the
+second form the largest matching pattern is deleted.
+When
+.I parameter\^
+is
+.BR @ ,
+.BR * ,
+or an array variable with subscript
+.B @
+or
+.BR * ,
+the substring operation is applied to each element in turn.
+.TP
+.PD 0
+\f3${\fP\f2parameter\^\fP\f3%\fP\f2pattern\^\fP\f3}\fP
+.TP
+\f3${\fP\f2parameter\^\fP\f3%%\fP\f2pattern\^\fP\f3}\fP
+.PD
+If
+the shell
+.I pattern\^
+matches the end of the value of
+.IR parameter ,
+then the value of
+this expansion is the value of the
+.I parameter\^
+with the matched part deleted;
+otherwise substitute the value of
+.IR parameter .
+In the first form the smallest matching pattern is deleted and in the
+second form the largest matching pattern is deleted.
+When
+.I parameter\^
+is
+.BR @ ,
+.BR * ,
+or an array variable with subscript
+.B @
+or
+.BR * ,
+the substring operation is applied to each element in turn.
+.TP
+.PD 0
+\f3${\fP\f2parameter\^\fP\f3/\fP\f2pattern\^\fP\f3/\f2string\^\fP\f3}\fP
+.TP
+\f3${\fP\f2parameter\^\fP\f3//\fP\f2pattern\^\fP\f3/\f2string\^\fP\f3}\fP
+.TP
+\f3${\fP\f2parameter\^\fP\f3/#\fP\f2pattern\^\fP\f3/\f2string\^\fP\f3}\fP
+.TP
+\f3${\fP\f2parameter\^\fP\f3/%\fP\f2pattern\^\fP\f3/\f2string\^\fP\f3}\fP
+.PD
+Expands
+.I parameter\^
+and replaces the longest match of
+.I pattern\^
+with the given
+.IR string.
+Each occurrence of \f3\e\fP\f2n\^\fP in
+.I string
+is replaced by the portion of \f2parameter\^\fP
+that matches the \f2n\^\fP-th sub-pattern.
+In the first form,
+only the first occurrence of
+.I pattern\^
+is replaced.
+In the second form,
+each match for
+.I pattern\^
+is replaced by the given
+.IR string.
+The third form restricts the pattern match to the beginning of the string
+while the fourth form restricts the pattern match to the end of
+the string.
+When
+.I string\^
+is null, the
+.I pattern\^
+will be deleted and the
+.B /
+in front of
+.I string\^
+may be omitted.
+When
+.I parameter\^
+is
+.BR @ ,
+.BR * ,
+or an array variable with subscript
+.B @
+or
+.BR * ,
+the substitution operation is applied to each element in turn.
+In this case, the
+.I string\^
+portion of
+.I word\^
+will be re-evaluated for each element.
+.PP
+The following
+parameters
+are automatically set by the shell:
+.RS
+.PD 0
+.TP
+.B #
+The number of positional parameters in decimal.
+.TP
+.B \-
+Options supplied to the shell on invocation or by
+the
+.B set
+command.
+.TP
+.B ?
+The decimal value returned by the last executed command.
+.TP
+.B $
+The process number of this shell.
+.TP
+.B _
+Initially, the value of
+.B _
+is an absolute pathname of the shell or script being executed
+as passed in the
+.IR environment .
+Subsequently it is assigned the last argument of the previous command.
+This parameter is not set for commands which are asynchronous.
+This parameter is also used to hold the name of the matching
+.B
+.SM MAIL
+file when checking for mail.
+While defining a compound variable or a type,
+.B _
+is initialized as a reference to the compound variable or type.
+When a discipline function is invoked,
+.B _
+is initialized as a reference to the variable associated with
+the call to this function.
+Finally when
+.B _
+is used as the name of the first variable of a type definition,
+the new type is derived from the type of the first variable (See
+.I "Type Variables"\^
+below.).
+.TP
+.B !
+The process id or the pool name and job number of the last background command
+invoked or the most recent job put in the background with the
+.B bg
+built-in command.
+Background jobs started in a named pool will be in the form
+.IB pool . number
+where
+.I pool\^
+is the pool name and
+.I number\^
+is the job number within that pool.
+.TP
+.B .sh.command
+When processing a
+.SM
+.B DEBUG
+trap, this variable contains the current command line
+that is about to run.
+.TP
+.B .sh.edchar
+This variable contains the value of the keyboard character
+(or sequence of characters if the first character is an ESC, ascii
+.BR 033\^ )
+that has
+been entered when processing a
+.B
+.SM KEYBD
+trap
+(see
+.I "Key Bindings\^"
+below).
+If the value is changed as part of the trap action, then the new
+value replaces the key (or key sequence) that caused the trap.
+.TP
+.B .sh.edcol
+The character position of the cursor at the time of the most recent
+.B
+.SM KEYBD
+trap.
+.TP
+.B .sh.edmode
+The value is set to ESC when processing a
+.B
+.SM KEYBD
+trap while in
+.B vi
+insert mode. (See
+.I "Vi Editing Mode"\^
+below.)
+Otherwise,
+.B .sh.edmode
+is null when processing a
+.B
+.SM KEYBD
+trap.
+.TP
+.B .sh.edtext
+The characters in the input buffer at the time of the most recent
+.B
+.SM KEYBD
+trap.
+The value is null when not processing a
+.B
+.SM KEYBD
+trap.
+.TP
+.B .sh.file
+The pathname of the file than contains the current command.
+.TP
+.B .sh.fun
+The name of the current function that is being executed.
+.TP
+.B .sh.level
+Set to the current function depth. This can be changed
+inside a DEBUG trap and will set the context to the specified
+level.
+.TP
+.B .sh.lineno
+Set during a DEBUG trap to the line number for the caller of
+each function.
+.TP
+.B .sh.match
+An indexed array which stores the most recent match and sub-pattern
+matches after conditional pattern matches that match and after
+variables expansions using the operators
+.BR # ,
+.BR % ,
+or
+.BR / .
+The
+.BR 0 -th
+element stores the complete match and the
+.IR i\^ -th.
+element stores the
+.IR i\^ -th
+submatch.
+The
+.B .sh.match
+variable
+becomes unset when the variable that has expanded
+is assigned a new value.
+.TP
+.B .sh.math
+Used for defining arithmetic functions
+(see
+.I "Arithmetic evaluation"
+below).
+and stores the list of user defined arithmetic functions.
+.TP
+.B .sh.name
+Set to the name of the variable at the time that a
+discipline function is invoked.
+.TP
+.B .sh.subscript
+Set to the name subscript of the variable at the time that a
+discipline function is invoked.
+.TP
+.B .sh.subshell
+The current depth for subshells and command substitution.
+.TP
+.B .sh.value
+Set to the value of the variable at the time that the
+.B set
+or
+.B append
+discipline function is invoked.
+When a user defined arithmetic function is invoked, the value
+of
+.B .sh.value
+is saved and
+.B .sh.value
+is set to long double precision floating point.
+.B .sh.value
+is restored when the function returns.
+.TP
+.B .sh.version
+Set to a value that identifies the version of this shell.
+.TP
+.B
+.SM KSH_VERSION
+A name reference to
+.BR .sh.version .
+.TP
+.B
+.SM LINENO
+The current line number within the script or
+function being executed.
+.TP
+.B
+.SM OLDPWD
+The previous working directory set by the
+.B cd
+command.
+.TP
+.B
+.SM OPTARG
+The value of the last option argument processed by the
+.B getopts
+built-in command.
+.TP
+.B
+.SM OPTIND
+The index of the last option argument processed by the
+.B getopts
+built-in command.
+.TP
+.B
+.SM PPID
+The process number of the parent of the shell.
+.TP
+.B
+.SM PWD
+The present working directory set by the
+.B cd
+command.
+.TP
+.B
+.SM RANDOM
+Each time this variable is referenced, a random integer,
+uniformly distributed between 0 and 32767, is generated.
+The sequence of random numbers can be initialized by assigning
+a numeric value to
+.SM
+.BR RANDOM .
+.TP
+.B
+.SM REPLY
+This variable is set by the
+.B select
+statement and by
+the
+.B read
+built-in command when no arguments are supplied.
+.TP
+.B
+.SM SECONDS
+Each time this variable is referenced, the number of
+seconds since shell invocation is returned.
+If this variable is
+assigned a value, then the value returned upon reference will
+be the value that was assigned plus the number of seconds since the assignment.
+.TP
+.SM
+.B SHLVL
+An integer variable the is incremented each time the shell
+is invoked and is exported.
+If
+.SM
+.B SHLVL
+is not in the environment when the shell is invoked, it is set
+to 1.
+.PD
+.RE
+.PP
+The following
+variables
+are used by the shell:
+.RS
+.PD 0
+.TP
+.B
+.SM CDPATH
+The search path for the
+.B cd
+command.
+.TP
+.B
+.SM COLUMNS
+If this variable is set,
+the value is used to define the width of the edit window
+for the shell edit modes and for printing
+.B select
+lists.
+.TP
+.B
+.SM EDITOR
+If the
+.B
+.SM VISUAL
+variable is not set,
+the value of this variable will be checked for the patterns
+as described with
+.B
+.SM VISUAL
+below and the corresponding editing option
+(see Special Command
+.B set
+below)
+will be turned on.
+.TP
+.SM
+.B ENV
+If this variable is set, then
+parameter expansion, command substitution, and arithmetic substitution
+are performed on
+the value to generate
+the pathname of the script that will be
+executed when the shell
+is invoked interactively
+(see
+.I Invocation\^
+below).
+This file is typically used for
+.B alias
+and
+.B function
+definitions.
+The default value is \fB$HOME/.kshrc\fP.
+On systems that support a system wide \fB/etc/ksh.kshrc\fP initialization file,
+if the filename generated by the expansion of
+.SM
+.B ENV
+begins with
+.B /./
+or
+.B .\^/.\^/
+the system wide initialization file will not be executed.
+.TP
+.B
+.SM FCEDIT
+Obsolete name for
+the default editor name for the
+.B hist
+command.
+.B
+.SM FCEDIT
+is not used when
+.B
+.SM HISTEDIT
+is set.
+.TP
+.SM
+.B FIGNORE
+A pattern that defines the set of filenames that will be
+ignored when performing filename matching.
+.TP
+.SM
+.B FPATH
+The search path for function definitions.
+The directories in this path are searched for a file with the same name
+as the function or command when a function with the
+.B \-u
+attribute is referenced and when a command is not found.
+If an executable file with the name of that command is found,
+then it is read and executed
+in the current environment.
+Unlike
+.SM
+.BR PATH ,
+the current directory must be represented
+explicitly by
+.B .
+rather than by adjacent
+.B :
+characters or a beginning or ending
+.BR : .
+.TP
+.B
+.SM HISTCMD
+Number of the current command in the history file.
+.TP
+.B
+.SM HISTEDIT
+Name for
+the default editor name for the
+.B hist
+command.
+.TP
+.SM
+.B HISTFILE
+If this variable is set when the shell is invoked, then
+the value is the pathname of the file that will be
+used to store the command history (see
+.I "Command Re-entry\^"
+below).
+.TP
+.SM
+.B HISTSIZE
+If this variable is set when the shell is invoked, then
+the number of previously entered commands that
+are accessible by this shell
+will be greater than or equal to this number.
+The default is 512.
+.TP
+.B
+.SM HOME
+The default argument (home directory) for the
+.B cd
+command.
+.TP
+.SM
+.B IFS
+Internal field separators,
+normally
+.BR space ,
+.BR tab ,
+and
+.B new-line
+that are used to separate the results of
+command substitution or parameter expansion
+and to separate fields with the built-in command
+.BR read .
+The first character of the
+.SM
+.B IFS
+variable is used to separate arguments for the
+.B
+"$\(**"
+substitution (see
+.I Quoting
+below).
+Each single occurrence of
+an
+.SM
+.B IFS
+character in the string to be split,
+that is not in the \f2isspace\^\fP character class, and any
+adjacent characters in
+.SM
+.B IFS
+that are in the \f2isspace\^\fP character class, delimit a field.
+One or more
+characters in
+.SM
+.B IFS
+that belong to the \f2isspace\^\fP character class,
+delimit a field.
+In addition, if the same \f2isspace\^\fP character appears
+consecutively inside
+.SM
+.BR IFS ,
+this character is treated as if it were not in the \f2isspace\^\fP
+class, so that if
+.SM
+.BR IFS
+consists of two
+.B tab
+characters,
+then two adjacent
+.B tab
+characters delimit a null field.
+.TP
+.B
+.SM JOBMAX
+This variable defines the maximum number running background jobs
+that can run at a time. When this limit is reached, the
+shell will wait for a job to complete before staring a new job.
+.TP
+.B
+.SM LANG
+This variable determines the locale category for any
+category not specifically selected with a variable
+starting with
+.B
+.SM LC_
+or
+.SM
+.BR LANG .
+.TP
+.B
+.SM LC_ALL
+This variable overrides the value of the
+.B
+.SM LANG
+variable and any other
+.B
+.SM LC_
+variable.
+.TP
+.B
+.SM LC_COLLATE
+This variable determines the locale category for character
+collation information.
+.TP
+.B
+.SM LC_CTYPE
+This variable determines the locale category for character
+handling functions.
+It determines the character classes for pattern matching (see
+.I "File Name Generation\^"
+below).
+.TP
+.B
+.SM LC_NUMERIC
+This variable determines the locale category for the
+decimal point character.
+.TP
+.B
+.SM LINES
+If this variable is set,
+the value is used to determine the column length for printing
+.B select
+lists.
+Select lists will print vertically until about two-thirds of
+.B
+.SM LINES
+lines are filled.
+.TP
+.B
+.SM MAIL
+If this variable is set to the name of a mail file
+.I and\^
+the
+.B
+.SM MAILPATH
+variable is not set,
+then the shell informs the user of arrival of mail
+in the specified file.
+.TP
+.B
+.SM MAILCHECK
+This variable specifies how often (in seconds) the
+shell will check for changes in the modification time
+of any of the files specified by the
+.B
+.SM MAILPATH
+or
+.B
+.SM MAIL
+variables.
+The default value is 600 seconds.
+When the time has elapsed
+the shell will check before issuing the next prompt.
+.TP
+.B
+.SM MAILPATH
+A colon (
+.B :
+)
+separated list of file names.
+If this variable is set,
+then the shell informs the user of
+any modifications to the specified files
+that have occurred within the last
+.B
+.SM MAILCHECK
+seconds.
+Each file name can be followed by a
+.B ?
+and a message that will be printed.
+The message will undergo parameter expansion, command substitution,
+and arithmetic substitution
+with the variable
+.B $_
+defined as the name of the file that has changed.
+The default message is
+.I you have mail in $_\^.
+.TP
+.B
+.SM PATH
+The search path for commands (see
+.I Execution\^
+below).
+The user may not change
+.B \s-1PATH\s+1
+if executing under
+.if \nZ=0 .B rsh
+.if \nZ=1 .B rksh
+.if \nZ=2 .B rksh93
+(except in
+.BR .profile\^).
+.TP
+.SM
+.B PS1
+The value of this variable is expanded for parameter
+expansion, command substitution, and arithmetic substitution to define the
+primary prompt string which by default is
+.RB `` "$\|\|\|" ''.
+The character
+.B !
+in the primary prompt string is replaced by the
+.I command\^
+number (see
+.I "Command Re-entry\^"
+below).
+Two successive occurrences of
+.B !
+will produce a single
+.B !
+when the prompt string is printed.
+.TP
+.SM
+.B PS2
+Secondary prompt string, by default
+.RB `` "> \|" ''.
+.TP
+.SM
+.B PS3
+Selection prompt string
+used within a
+.B select
+loop, by default
+.RB `` "#? \|" ''.
+.TP
+.SM
+.B PS4
+The value of this variable is expanded for parameter evaluation,
+command substitution, and arithmetic substitution
+and precedes each line of an execution trace.
+By default,
+.SM
+.B PS4
+is
+.RB `` "+ \|" ''.
+In addition
+when
+.SM
+.B PS4
+is unset,
+the execution trace prompt is also
+.RB `` "+ \|" ''.
+.TP
+.SM
+.B SHELL
+The pathname of the
+.I shell\^
+is kept in the environment.
+At invocation, if the basename of this variable is
+.BR rsh ,
+.BR rksh ,
+or
+.BR krsh ,
+then the shell becomes restricted.
+If it is
+.BR pfsh
+or
+.BR pfksh ,
+then the shell becomes a profile shell (see
+.IR pfexec (1)).
+.TP
+.SM
+.B TIMEFORMAT
+The value of this parameter is used as a format string specifying
+how the timing information for pipelines prefixed with the
+.B time
+reserved word should be displayed.
+The \fB%\fP character introduces a format sequence that is
+expanded to a time value or other information.
+The format sequences and their meanings are as follows.
+.sp .5
+.RS
+.PD 0
+.TP 10
+.B %%
+A literal \fB%\fP.
+.TP
+.B %[\fIp\fP][l]R
+The elapsed time in seconds.
+.TP
+.B %[\fIp\fP][l]U
+The number of CPU seconds spent in user mode.
+.TP
+.B %[\fIp\fP][l]S
+The number of CPU seconds spent in system mode.
+.TP
+.B %P
+The CPU percentage, computed as (U + S) / R.
+.PD
+.RE
+.IP
+The brackets denote optional portions.
+The optional \fIp\fP is a digit specifying the \fIprecision\fP,
+the number of fractional digits after a decimal point.
+A value of 0 causes no decimal point or fraction to be output.
+At most three places after the decimal point can be displayed;
+values of \fIp\fP greater than 3 are treated as 3.
+If \fIp\fP is not specified, the value 3 is used.
+.IP
+The optional \fBl\fP specifies a longer format, including
+hours if greater than zero,
+minutes, and seconds of the form \fIHH\fPh\fIMM\fPm\fISS\fP.\fIFF\fPs.
+The value of \fIp\fP determines whether or not the fraction is
+included.
+.IP
+All other characters are output without change and a trailing
+newline is added.
+If unset, the default value, \fB$'\enreal\et%2lR\enuser\et%2lU\ensys\t%2lS'\fP,
+is used. If the value is null, no timing information is displayed.
+.TP
+.B
+.SM TMOUT
+If set to a value greater than zero,
+.B
+.SM TMOUT
+will be the default timeout value for the
+.B read
+built-in command.
+The
+.B select
+compound command terminates after
+.B
+.SM TMOUT
+seconds when input is from a terminal.
+Otherwise,
+the shell will terminate if a line is not entered within
+the prescribed number of seconds while reading from a terminal.
+(Note that the shell can be compiled with a maximum bound
+for this value which cannot be exceeded.)
+.TP
+.B
+.SM VISUAL
+If the value of this variable matches the pattern
+.IR *[Vv][Ii]* ,
+then the
+.B vi
+option
+(see Special Command
+.B set
+below)
+is turned on.
+If the value matches the pattern
+.I *gmacs* ,
+the
+.B gmacs
+option is turned on.
+If the value matches the pattern
+.IR *macs* ,
+then the
+.B emacs
+option
+will be turned on.
+The value of
+.B
+.SM VISUAL
+overrides the value of
+.B
+.SM EDITOR.
+.PD
+.RE
+.PP
+The shell gives default values to
+\f3\s-1PATH\s+1\fP, \f3\s-1PS1\s+1\fP, \f3\s-1PS2\s+1\fP,
+\f3\s-1PS3\s+1\fP, \f3\s-1PS4\s+1\fP, \f3\s-1MAILCHECK\s+1\fP, \f3\s-1FCEDIT\s+1\fP,
+\f3\s-1TMOUT\s+1\fP and \f3\s-1IFS\s+1\fP,
+while
+.SM
+.BR HOME ,
+.SM
+.BR SHELL ,
+.SM
+.BR ENV ,
+and
+.SM
+.B MAIL
+are
+not set at all by the shell (although
+.SM
+.B HOME
+.I is\^
+set by
+.IR login (1)).
+On some systems
+.SM
+.B MAIL
+and
+.SM
+.B SHELL
+are also
+set by
+.IR login (1).
+.SS Field Splitting.
+After parameter expansion and command substitution,
+the results of substitutions are scanned for the field separator
+characters (those found in
+.SM
+.B IFS\^\c
+)
+and split into distinct fields where such characters are found.
+Explicit null fields (\^\f3"\^"\fP or \f3\(fm\^\(fm\fP\^) are retained.
+Implicit null fields
+(those resulting from
+.I parameters\^
+that have no values or command substitutions with no output) are removed.
+.PP
+If the
+.B braceexpand
+.RB ( \-B )
+option is set then each of the fields resulting from
+.SM
+.B IFS
+are checked to see if they contain one or more of the brace patterns
+.BR {*,*} ,
+.BI { l1 .. l2 }
+,
+.BI { n1 .. n2 }
+,
+.BI { n1 .. n2 %
+.IB fmt }
+,
+.BI { n1 .. n2
+.BI .. n3 }
+, or
+.BI { n1 .. n2
+.BI .. n3 % fmt }
+, where
+.B *
+represents any character,
+.IR l1\^ , l2\^
+are letters and
+.IR n1\^ , n2\^ , n3\^
+are signed numbers and
+.I fmt\^
+is a format specified as used by
+.BR printf .
+In each case, fields are created
+by prepending the characters before the
+.B {
+and appending the characters after the
+.B }
+to each of the strings generated by the characters between
+the
+.B {
+and
+.BR } .
+The resulting fields are checked to see if they have any
+brace patterns.
+.PP
+In the first form, a field is created for each string between
+.BR {
+and
+.BR , ,
+between
+.BR ,
+and
+.BR , ,
+and between
+.BR ,
+and
+.BR } .
+The string represented by
+.B *
+can contain embedded matching
+.B {
+and
+.B }
+without quoting.
+Otherwise, each
+.B {
+and
+.B }
+with
+.B *
+must be quoted.
+.PP
+In the seconds form,
+.I l1\^
+and
+.I l2\^
+must both be either upper case or both be lower case characters
+in the C locale. In this case a field is created for each character
+from
+.I l1\^
+thru
+.IR l2\^ .
+.PP
+In the remaining forms, a field is created for each number starting at
+.I n1\^
+and continuing until it reaches
+.I n2\^
+incrementing
+.I n1\^
+by
+.IR n3\^ .
+The cases where
+.I n3\^
+is not specified behave as if
+.I n3\^
+where
+.B 1
+if
+.IB n1 <= n2
+and
+.B \-1
+otherwise.
+If forms which specify
+.BI % fmt\^
+any format flags, widths and precisions can be specified
+and
+.I fmt\^
+can end in any of the specifiers
+.BR cdiouxX .
+For example,
+.B {a,z}{1..5..3%02d}{b..c}x
+expands to the 8 fields,
+.BR a01bx ,
+.BR a01cx ,
+.BR a04bx ,
+.BR a04cx ,
+.BR z01bx ,
+.BR z01cx ,
+.B z04bx
+and
+.BR z4cx .
+.SS File Name Generation.
+Following splitting, each field is scanned for the characters
+.BR \(** ,
+.BR ? ,
+.BR ( ,
+and
+.B \*(OK\^
+unless the
+.B \-f
+option has been set.
+If one of these characters appears,
+then the word is regarded as a
+.IR pattern .
+Each file name component that contains any pattern character
+is replaced with a lexicographically sorted set of names
+that matches the pattern
+from
+that directory.
+If no file name is found that matches the pattern, then
+that component of the filename is left unchanged unless
+the pattern is prefixed with
+.B \(ap(N)\fP
+in which case it is removed as described below.
+If
+.SM
+.B FIGNORE
+is set,
+then each file name component
+that matches the pattern defined by the value of
+.SM
+.B FIGNORE
+is ignored when generating the matching filenames.
+The names
+.B .
+and
+.B ..
+are also ignored.
+If
+.SM
+.B FIGNORE
+is not set,
+the character
+.B .
+at the start of each file name component
+will be ignored unless the first character of the pattern
+corresponding to this component is the character
+.BR .
+itself.
+Note, that for other
+uses of pattern matching the
+.B /
+and
+.B .
+are not treated specially.
+.PP
+.PD 0
+.RS
+.TP
+.B \(**
+Matches any string, including the null string.
+When used for filename expansion,
+if the
+.B globstar
+option is on, two adjacent
+.BR \(** 's
+by itself
+will match all files and zero or more directories
+and subdirectories.
+If followed by a
+.B /
+then only directories and subdirectories will match.
+.TP
+.B ?
+Matches any single character.
+.TP
+.BR \*(OK \^.\|.\|.\^ \*(CK
+Matches any one of the enclosed characters.
+A pair of characters separated by
+.B \-
+matches any
+character lexically between the pair, inclusive.
+If the first character following the opening
+.B \*(OK\^
+is a
+.B !
+or
+.B ^
+then any character not enclosed is matched.
+A
+.B \-
+can be included in the character set by putting it as the
+first or last character.
+.br
+Within
+.B \*(OK\^
+and
+.BR \*(CK\^ ,
+character classes can be specified with the syntax
+\f3[:\fP\f2class\fP\f3:]\fP
+where class is one of the following classes defined in the ANSI-C standard:
+(Note that \f3word\fP is equivalent to \f3alnum\fP plus the character \f3_\fP.)
+.br
+.B
+.if n alnum alpha blank cntrl digit graph lower print punct space upper word xdigit
+.if t alnum alpha blank cntrl digit graph lower print punct space upper word xdigit
+.br
+Within
+.B \*(OK\^
+and
+.BR \*(CK\^ ,
+an equivalence class can be specified with the syntax
+\f3[=\fP\f2c\fP\f3=]\fP
+which matches all characters with the same primary
+collation weight (as defined by the current locale) as
+the character \f2c\fP.
+Within
+.B \*(OK\^
+and
+.BR \*(CK\^ ,
+\f3[.\fP\f2symbol\fP\f3.]\fP
+matches the collating symbol \f2symbol\fP.
+.RE
+.PD
+A
+.I pattern-list
+is a list of one or more patterns separated from each other
+with a
+.B &
+or
+.BR \(bv .
+A
+.B &
+signifies that all patterns must be matched whereas
+.BR \(bv
+requires that only one pattern be matched.
+Composite patterns can be formed with one or more of the following sub-patterns:
+.PD 0
+.RS
+.TP
+\f3?(\fP\f2pattern-list\^\fP\f3)\fP
+Optionally matches any one of the given patterns.
+.TP
+\f3*(\fP\f2pattern-list\^\fP\f3)\fP
+Matches zero or more occurrences of the given patterns.
+.TP
+\f3+(\fP\f2pattern-list\^\fP\f3)\fP
+Matches one or more occurrences of the given patterns.
+.TP
+\f3{\fP\f2n\^\fP\f3}\fP(\fP\f2pattern-list\^\fP\f3)\fP
+Matches \f2n\^\fP occurrences of the given patterns.
+.TP
+\f3{\fP\f2m\^\fP\f3,\fP\f2n\^\fP\f3}\fP(\fP\f2pattern-list\^\fP\f3)\fP
+Matches from \f2m\^\fP to \f2n\^\fP occurrences of the given patterns.
+If \f2m\^\fP is omitted, \f30\fP will be used. If \f2n\^\fP
+is omitted at least \f2m\^\fP occurrences will be matched.
+.TP
+\f3\&@\&(\fP\f2pattern-list\^\fP\f3)\fP
+Matches exactly one of the given patterns.
+.br
+.TP
+\f3!(\fP\f2pattern-list\^\fP\f3)\fP
+Matches anything except one of the given patterns.
+.PD
+.RE
+By default, each pattern, or sub-pattern will match the
+longest string possible consistent with generating
+the longest overall match. If more than one match is
+possible, the one starting closest to the beginning
+of the string will be chosen. However, for each of the above
+compound patterns a \f3\-\fP can be inserted in front of the \f3(\fP
+to cause the shortest match to the specified \f2pattern-list\^\fP
+to be used.
+.PP
+When \f2pattern-list\^\fP is contained within parentheses,
+the backslash character \f3\e\fP is treated specially even
+when inside a character class. All ANSI-C character escapes are
+recognized and match the specified character. In addition
+the following escape sequences are recognized:
+.PD 0
+.RS
+.TP
+.B \ed
+Matches any character in the \f3digit\fP class.
+.TP
+.B \eD
+Matches any character not in the \f3digit\fP class.
+.TP
+.B \es
+Matches any character in the \f3space\fP class.
+.TP
+.B \eS
+Matches any character not in the \f3space\fP class.
+.TP
+.B \ew
+Matches any character in the \f3word\fP class.
+.TP
+.B \eW
+Matches any character not in the \f3word\fP class.
+.PD
+.RE
+.PP
+A pattern of the form
+\f3%(\fP\f2pattern-pair\^\fP(s)\f3)\fP
+is a sub-pattern that
+can be used to match nested character expressions.
+Each
+.I pattern-pair\^
+is a two character sequence which cannot contain
+.B &
+or
+.BR \(bv .
+The first
+.I pattern-pair\^
+specifies the starting and ending characters for the match.
+Each subsequent
+.I pattern-pair\^
+represents the beginning and ending characters of a nested group that
+will be skipped over when counting starting and ending character matches.
+The behavior is unspecified when the first character of a
+.I pattern-pair\^
+is alpha-numeric
+except for the following:
+.PD 0
+.RS
+.TP
+.B D
+Causes the ending character to terminate the search for this pattern without
+finding a match.
+.TP
+.B E
+Causes the ending character to be interpreted as an escape character.
+.TP
+.B L
+Causes the ending character to be interpreted as a quote character
+causing all characters to be ignored when looking for a match.
+.TP
+.B Q
+Causes the ending character to be interpreted as a quote character
+causing all characters other than any escape character to be ignored
+when looking for a match.
+.PD
+.RE
+Thus,
+\f3%(\^{\^}Q"E\e\^)\fP,
+matches characters starting at
+.B {
+until the matching
+.B }
+is found not counting any
+.B {
+or
+.B }
+that is inside a double quoted string or preceded by the escape character
+.BR \e .
+Without the
+.B {\^}
+this pattern matches any C language string.
+.PP
+Each sub-pattern in a composite pattern is numbered,
+starting at 1, by the location of the \f3(\fP within
+the pattern.
+The sequence \f3\e\fP\f2n\^\fP, where \f2n\^\fP
+is a single digit and \f3\e\fP\f2n\^\fP comes after
+the \f2n\fP-th. sub-pattern,
+matches the same string as the sub-pattern itself.
+.PP
+Finally a pattern can contain sub-patterns of the form
+\f3\(ap(\fP\f2options\^\fP\f3:\fP\f2pattern-list\^\fP\f3)\fP,
+where either \f2options\^\fP or \f3:\fP\f2pattern-list\^\fP
+can be omitted. Unlike the other compound patterns,
+these sub-patterns are not counted in the numbered sub-patterns.
+\f3:\fP\f2pattern-list\^\fP must be omitted for the upper-case options below.
+If \f2options\^\fP is present, it can consist of one or more
+of the following:
+.PD 0
+.RS
+.TP
+.B +
+Enable the following options. This is the default.
+.TP
+.B \-
+Disable the following options.
+.TP
+.B E
+The remainder of the pattern uses extended regular expression syntax
+like the
+.IR egrep (1)
+command.
+.TP
+.B F
+The remainder of the pattern uses
+.IR fgrep (1)
+expression syntax.
+.TP
+.B G
+The remainder of the pattern uses basic regular expression syntax
+like the
+.IR grep (1)
+command.
+.TP
+.B K
+The remainder of the pattern uses shell pattern syntax.
+This is the default.
+.TP
+.B N
+This is ignored. However, when it is the first letter and is
+used with file name generation, and no matches occur,
+the file pattern expands to the empty string.
+.TP
+.B X
+The remainder of the pattern uses augmented regular expression syntax
+like the
+.IR xgrep (1)
+command.
+.TP
+.B P
+The remainder of the pattern uses
+.IR perl (1)
+regular expression syntax. Not all perl regular expression syntax is
+currently implemented.
+.TP
+.B i
+Treat the match as case insensitive.
+.TP
+.B g
+File the longest match (greedy). This is the default.
+.TP
+.B l
+Left anchor the pattern. This is the default for
+.B K
+style patterns.
+.TP
+.B r
+Right anchor the pattern. This is the default for
+.B K
+style patterns.
+.PD
+.RE
+If both \f2options\^\fP and \f3:\fP\f2pattern-list\^\fP
+are specified, then the options apply only to \f2pattern-list\^\fP.
+Otherwise, these options remain in effect until they are disabled
+by a subsequent \f3\(ap(\fP\f2...\^\fP\f3)\fP or at the end of
+the sub-pattern containing \f3\(ap(\fP\f2...\^\fP\f3)\fP.
+.SS Quoting.
+Each of the
+.I metacharacters\^
+listed earlier (see
+.I Definitions\^
+above)
+has a special meaning to the shell
+and causes termination of a word unless quoted.
+A character may be
+.I quoted\^
+(i.e., made to stand for itself)
+by preceding
+it with a
+.BR \e .
+The pair
+.B \enew-line
+is removed.
+All characters enclosed between a pair of single quote marks
+(\^\f3\(fm\^\(fm\fP\^)
+that is not preceded by a
+.B $
+are quoted.
+A single quote cannot appear within the single quotes.
+A single quoted string preceded by an unquoted
+.B $
+is processed as an ANSI-C string
+except for the following:
+.PD 0
+.TP
+.B \e0
+Causes the remainder of the string to be ignored.
+.TP
+.B \eE
+Equivalent to the escape character
+(ascii
+.BR 033 ),
+.TP
+.B \ee
+Equivalent to the escape character
+(ascii
+.BR 033 ),
+.TP
+.BI \ec x
+Expands to the character control-\f2x\fP.
+.TP
+.BI \eC[. name .]
+Expands to the collating element \f2name\fP.
+.PD
+.PP
+Inside double quote marks
+(\f3"\^"\fP),
+parameter and command substitution occur and
+.B \e
+quotes the characters
+.BR \e ,
+.BR \*` ,
+\f3"\fP,
+and
+.BR $ .
+A
+.B $
+in front of a double quoted string will be ignored
+in the "C" or "POSIX" locale, and may cause
+the string to be replaced by a locale specific string otherwise.
+The meaning of
+.B "$\(**"
+and
+.B "$@"
+is identical when not quoted or when used as a variable assignment value
+or as a file name.
+However, when used as a command argument,
+.B
+"$\(**"
+is equivalent to
+\f3"$1\fP\f2d\fP\f3\|$2\fP\f2d\fP\|.\|.\|.\f3"\fP,
+where
+.I d
+is the first character of the
+.SM
+.B IFS
+variable, whereas
+.B
+"$@"
+is equivalent to
+.B
+"$1"\|
+.B
+"$2"\|
+\&.\|.\|.\^.
+Inside grave quote marks
+(\f3\*`\^\*`\fP),
+.B \e
+quotes the characters
+.BR \e ,
+.BR \*` ,
+and
+.BR $ .
+If the grave quotes occur within double quotes, then
+.B \e
+also quotes the character
+\f3"\fP.
+.PP
+The special meaning of reserved words or aliases can be removed by quoting any
+character of the reserved word.
+The recognition of function names or built-in command names listed below
+cannot be altered by quoting them.
+.SS Arithmetic Evaluation.
+The shell performs arithmetic evaluation for
+arithmetic substitution, to evaluate an arithmetic command,
+to evaluate an indexed array subscript,
+and to evaluate arguments to
+the built-in commands
+.B shift\^
+and
+.BR let .
+Evaluations are performed using
+double precision floating point
+arithmetic or long double precision floating point for
+systems that provide this data type.
+Floating point constants follow the ANSI-C programming language
+floating point conventions.
+The floating point constants
+.B Nan
+and
+.B Inf
+can be use to represent "not a number" and infinity respectfully.
+Integer constants follow the ANSI-C programming language
+integer constant conventions although only single byte
+character constants are recognized and character casts
+are not recognized.
+In addition constants can be of the form
+\*(OK\f2base\f3#\^\f1\*(CK\f2n\^\fP
+where
+.I base\^
+is a decimal number between two and sixty-four
+representing the arithmetic base
+and
+.I n\^
+is a number in that base.
+The digits above 9 are represented
+by the lower case letters, the upper case letters,
+.BR @ ,
+and
+.B _
+respectively.
+For bases less than or equal to 36, upper and lower case
+characters can be used interchangeably.
+.PP
+An arithmetic expression uses the same syntax, precedence, and
+associativity of
+expression as the C language.
+All the C language operators
+that apply to floating point quantities can be used.
+In addition, the operator
+.B **
+can be used for exponentiation.
+It has higher precedence than multiplication and is left associative.
+In addition, when the value of an arithmetic variable
+or sub-expression can be represented as a long integer,
+all C language integer arithmetic operations can be performed.
+Variables can be referenced by name within an arithmetic expression
+without using the parameter expansion syntax.
+When a variable is referenced, its value is evaluated as
+an arithmetic expression.
+.PP
+Any of the following math library functions that are in the C math library
+can be used within an arithmetic expression:
+.PP
+.if t .RS
+.B
+.if n abs acos acosh asin asinh atan atan2 atanh cbrt ceil copysign cos cosh erf erfc exp exp2 expm1 fabs fpclassify fdim finite floor fma fmax fmin fmod hypot ilogb int isfinite sinf isnan isnormal issubnormal issubordered iszero j0 j1 jn lgamma log log10 log2 logb nearbyint nextafter nexttoward pow remainder rint round scanb signbit sin sinh sqrt tan tanh tgamma trunc y0 y1 yn
+.if t abs acos acosh asin asinh atan atan2 atanh cbrt ceil copysign cos cosh erf erfc exp exp2 expm1 fabs fpclassify fdim finite floor fma fmax fmod j0 j1 jn hypot ilogb int isfinite isinf isnan isnormal issubnormal issubordered iszero lgamma log log10 log2 logb nearbyint nextafter nexttoward pow rint round scalb signbit sin sinh sqrt tan tanh tgamma trunc y0 y1 yn
+.if t .RE
+In addition, arithmetic functions can be define as shell functions with a
+variant of the
+.B function
+.I name\^
+syntax,
+.TP
+.PD 0
+\f3function .sh.math.\fP\f2name ident\^\fP ... \f3{\fP \f2list\^\fP \f3;}\fP
+.PD
+where
+.I name\^
+is the function name used in the arithmetic expression and each identifier,
+.I ident\^
+is a name reference to the long double precision floating point argument.
+The value of
+.B .sh.value
+when the function returns is the value of this function.
+User defined functions can take up to 3 arguments and override C math library
+functions.
+.PP
+An internal representation of a
+.I variable\^
+as a double precision floating point can be specified with the
+\f3\-E\fP \*(OK\f2n\^\fP\*(CK,
+\f3\-F\fP \*(OK\f2n\^\fP\*(CK,
+or
+\f3\-X\fP \*(OK\f2n\^\fP\*(CK
+option of the
+.B typeset
+special built-in command.
+The
+.B \-E
+option causes the expansion of the value to be represented using
+scientific notation when it is expanded.
+The optional option argument
+.I n
+defines the number of significant figures.
+The
+.B \-F
+option causes the expansion to be represented as a floating decimal number
+when it is expanded.
+The
+.B \-X
+option cause the expansion to be represented using the
+.B %a
+format defined by ISO C-99.
+The optional option argument
+.I n
+defines the number of places after the decimal (or radix) point in this case.
+.PP
+An internal integer representation of a
+.I variable\^
+can be specified with the
+\f3\-i\fP \*(OK\f2n\^\fP\*(CK
+option of the
+.B typeset
+special built-in command.
+The optional option argument
+.I n
+specifies an arithmetic base to be used when expanding the variable.
+If you do not specify an arithmetic base,
+base 10 will be used.
+.PP
+Arithmetic evaluation is performed on the value of each
+assignment to a variable with the
+.BR \-E ,
+.BR \-F ,
+.BR \-X ,
+or
+.B \-i
+attribute.
+Assigning a floating point number to a
+variable whose type is an integer causes the fractional
+part to be truncated.
+.PP
+.SS Prompting.
+When used interactively,
+the shell prompts with the value of
+.SM
+.B PS1
+after expanding it for parameter expansion, command substitution, and
+arithmetic substitution,
+before reading a command.
+In addition, each single
+.B !
+in the prompt is replaced by the command number.
+A
+.B !!
+is required to place
+.B !
+in the prompt.
+If at any time a new-line is typed and further input is needed
+to complete a command, then the secondary prompt
+(i.e., the value of
+.BR \s-1PS2\s+1 )
+is issued.
+.SS Conditional Expressions.
+A
+.I "conditional expression"
+is used with the
+.B [[
+compound command to test attributes of files and to compare
+strings.
+Field splitting and file name generation are
+not performed on the words between
+.B [[
+and
+.BR ]] .
+Each expression can be constructed from one or more
+of the following unary or binary expressions:
+.PD 0
+.TP
+\f2string\fP
+True, if
+.I string
+is not null.
+.TP
+\f3\-a\fP \f2file\fP
+Same as \f3\-e\fP below.
+This is obsolete.
+.TP
+\f3\-b\fP \f2file\fP
+True, if
+.I file\^
+exists and is a block special file.
+.TP
+\f3\-c\fP \f2file\fP
+True, if
+.I file\^
+exists and is a character special file.
+.TP
+\f3\-d\fP \f2file\fP
+True, if
+.I file\^
+exists and is a directory.
+.TP
+\f3\-e\fP \f2file\fP
+True, if
+.I file\^
+exists.
+.TP
+\f3\-f\fP \f2file\fP
+True, if
+.I file\^
+exists and is an ordinary file.
+.TP
+\f3\-g\fP \f2file\fP
+True, if
+.I file\^
+exists and it has its setgid bit set.
+.TP
+\f3\-k\fP \f2file\fP
+True, if
+.I file\^
+exists and it has its sticky bit set.
+.TP
+\f3\-n\fP \f2string\fP
+True, if length of
+.I string\^
+is non-zero.
+.TP
+\f3\-o\fP \f3?\fP\f2option\fP
+True, if option named
+.I option\^
+is a valid option name.
+.TP
+\f3\-o\fP \f2option\fP
+True, if option named
+.I option\^
+is on.
+.TP
+\f3\-p\fP \f2file\fP
+True, if
+.I file\^
+exists and is a fifo special file or a pipe.
+.TP
+\f3\-r\fP \f2file\fP
+True, if
+.I file\^
+exists and is readable by current process.
+.TP
+\f3\-s\fP \f2file\fP
+True, if
+.I file\^
+exists and has size greater than zero.
+.TP
+\f3\-t\fP \f2fildes\fP
+True, if file descriptor number
+.I fildes\^
+is open and associated with a terminal device.
+.TP
+\f3\-u\fP \f2file\fP
+True, if
+.I file\^
+exists and it has its setuid bit set.
+.TP
+\f3\-w\fP \f2file\fP
+True, if
+.I file\^
+exists and is writable by current process.
+.TP
+\f3\-x\fP \f2file\fP
+True, if
+.I file\^
+exists and is executable by current process.
+If
+.I file\^
+exists and is a directory, then true if the current process
+has permission to search in the directory.
+.TP
+\f3\-z\fP \f2string\fP
+True, if length of
+.I string\^
+is zero.
+.TP
+\f3\-L\fP \f2file\fP
+True, if
+.I file\^
+exists and is a symbolic link.
+.TP
+\f3\-h\fP \f2file\fP
+True, if
+.I file\^
+exists and is a symbolic link.
+.TP
+\f3\-N\fP \f2file\fP
+True, if
+.I file\^
+exists and the modification time is greater than the last access time.
+.TP
+\f3\-O\fP \f2file\fP
+True, if
+.I file\^
+exists and is owned by the effective user id of this process.
+.TP
+\f3\-G\fP \f2file\fP
+True, if
+.I file\^
+exists and its group matches the effective group id of this process.
+.TP
+\f3\-S\fP \f2file\fP
+True, if
+.I file\^
+exists and is a socket.
+.TP
+\f2file1\fP \f3\-nt\fP \f2file2\fP
+True, if
+.I file1\^
+exists and
+.I file2\^
+does not, or
+.I file1\^
+is newer than
+.IR file2 .
+.TP
+\f2file1\fP \f3\-ot\fP \f2file2\fP
+True, if
+.I file2\^
+exists and
+.I file1\^
+does not, or
+.I file1\^
+is older than
+.IR file2 .
+.TP
+\f2file1\fP \f3\-ef\fP \f2file2\fP
+True, if
+.I file1\^
+and
+.I file2\^
+exist and refer to the same file.
+.TP
+\f2string\fP \f3==\fP \f2pattern\fP
+True, if
+.I string\^
+matches
+.IR pattern .
+Any part of
+.I pattern\^
+can be quoted to cause it to be matched as a string.
+With a successful match to a pattern, the
+.B .sh.match
+array variable will contain the match and sub-pattern matches.
+.TP
+\f2string\fP \f3=\fP \f2pattern\fP
+Same as \f3==\fP above, but is obsolete.
+.TP
+\f2string\fP \f3!=\fP \f2pattern\fP
+True, if
+.I string\^
+does not match
+.IR pattern .
+When the
+.I string\^
+matches the
+.I pattern\^
+the
+.B .sh.match
+array variable will contain the match and sub-pattern matches.
+.TP
+\f2string\fP \f3=\(ap\fP \f2ere\fP
+True if
+.I string\^
+matches the pattern
+.BI \(ap(E) ere\^
+where
+.I ere\^
+is an extended regular expression.
+.TP
+\f2string1\fP \f3<\fP \f2string2\fP
+True, if
+.I string1\^
+comes before
+.I string2\^
+based on ASCII value of their characters.
+.TP
+\f2string1\fP \f3>\fP \f2string2\fP
+True, if
+.I string1\^
+comes after
+.I string2\^
+based on ASCII value of their characters.
+.PP
+The following obsolete arithmetic comparisons are also permitted:
+.PD 0
+.TP
+\f2exp1\fP \f3\-eq\fP \f2exp2\fP
+True, if
+.I exp1\^
+is equal to
+.IR exp2 .
+.TP
+\f2exp1\fP \f3\-ne\fP \f2exp2\fP
+True, if
+.I exp1\^
+is not equal to
+.IR exp2 .
+.TP
+\f2exp1\fP \f3\-lt\fP \f2exp2\fP
+True, if
+.I exp1\^
+is less than
+.IR exp2 .
+.TP
+\f2exp1\fP \f3\-gt\fP \f2exp2\fP
+True, if
+.I exp1\^
+is greater than
+.IR exp2 .
+.TP
+\f2exp1\fP \f3\-le\fP \f2exp2\fP
+True, if
+.I exp1\^
+is less than or equal to
+.IR exp2 .
+.TP
+\f2exp1\fP \f3\-ge\fP \f2exp2\fP
+True, if
+.I exp1\^
+is greater than or equal to
+.IR exp2 .
+.PD
+.PP
+In each of the above expressions, if
+.I file\^
+is of the form
+\f3/dev/fd/\fP\f2n\fP,
+where
+.I n\^
+is an integer,
+then the test is applied to the open file whose
+descriptor number is
+.IR n .
+.PP
+A compound expression can be constructed from these primitives by
+using any of the following, listed in decreasing order of precedence.
+.PD 0
+.TP
+\f3(\fP\f2expression\fP\f3)\fP
+True, if
+.I expression\^
+is true.
+Used to group expressions.
+.TP
+\f3!\fP \f2expression\fP
+True if
+.I expression\^
+is false.
+.TP
+\f2expression1\fP \f3&&\fP \f2expression2\fP
+True, if
+.I expression1\^
+and
+.I expression2\^
+are both true.
+.TP
+\f2expression1\fP \f3\(bv\(bv\fP \f2expression2\fP
+True, if either
+.I expression1\^
+or
+.I expression2\^
+is true.
+.PD
+.SS Input/Output.
+Before a command is executed, its input and output
+may be redirected using a special notation interpreted by the shell.
+The following may appear anywhere in a simple-command
+or may precede or follow a
+.I command\^
+and are
+.I not\^
+passed on to the invoked command.
+Command substitution, parameter expansion,
+and arithmetic substitution occur before
+.I word\^
+or
+.I digit\^
+is used except as noted below.
+File name generation
+occurs only if the shell is interactive and
+the pattern matches a single file.
+Field splitting is not performed.
+.PP
+In each of the following redirections, if
+.I file\^
+is of the form
+\f3/dev/sctp/\fP\f2host\fP\f3/\fP\f2port\fP,
+\f3/dev/tcp/\fP\f2host\fP\f3/\fP\f2port\fP,
+or
+\f3/dev/udp/\fP\f2host\fP\f3/\fP\f2port\fP,
+where
+.I host\^
+is a hostname or host address,
+and
+.I port\^
+is a service given by name or an integer port number,
+then the redirection attempts to make a
+\f3tcp\fP, \f3sctp\fP or \f3udp\fP connection to the corresponding
+socket.
+.PP
+No intervening space is allowed between the characters of redirection operators.
+.TP 14
+.BI < word
+Use file
+.I word\^
+as standard input (file descriptor 0).
+.TP
+.BI > word
+Use file
+.I word\^
+as standard output (file descriptor 1).
+If the file does not exist then it is created.
+If the file exists, and the
+.B noclobber
+option is on,
+this causes an error;
+otherwise, it is truncated to zero length.
+.TP
+.BI >| word
+Sames as
+.BR > ,
+except that it overrides the
+.B noclobber
+option.
+.TP
+.BI >; word
+Write output to a temporary file. If the command completes
+successfully rename it to
+.IR word ,
+otherwise, delete the temporary file.
+.BI >; word
+cannot be used with the
+.IR exec (2).
+built-in.
+.TP
+.BI >> word
+Use file
+.I word\^
+as standard output.
+If the file exists, then output is appended to it (by first seeking to the end-of-file);
+otherwise, the file is created.
+.TP
+.BI <> word
+Open file
+.I word\^
+for reading and writing
+as standard output.
+.TP
+.BI <>; word
+The same as
+.BI <> word
+except that if the command completes successfully,
+.I word\^
+is truncated to the offset at command completion.
+.BI <>; word
+cannot be used with the
+.IR exec (2).
+built-in.
+.TP
+\f3<<\fP\*(OK\f3\-\fP\*(CK\f2word\fP
+The shell input is read up to a line that is the same as
+.IR word
+after any quoting has been removed,
+or to an end-of-file.
+No parameter substitution, command substitution, arithmetic substitution or
+file name generation is performed on
+.IR word .
+The resulting document,
+called a
+.IR here-document ,
+becomes
+the standard input.
+If any character of
+.I word\^
+is quoted, then no interpretation
+is placed upon the characters of the document;
+otherwise, parameter expansion, command substitution, and arithmetic
+substitution occur,
+.B \enew-line
+is ignored,
+and
+.B \e
+must be used to quote the characters
+.BR \e ,
+.BR $ ,
+.BR \*` .
+If
+.B \-
+is appended to
+.BR << ,
+then all leading tabs are stripped from
+.I word\^
+and from the document.
+If
+.B #
+is appended to
+.BR << ,
+then leading spaces and tabs will be stripped off the first
+line of the document and up to an equivalent indentation will
+be stripped from the remaining lines and from
+.IR word .
+A tab stop is assumed to occur at every 8 columns for the
+purposes of determining the indentation.
+.TP
+\f3<<<\fP\f2word\fP
+A short form of here document in which \f2word\fP becomes the
+contents of the here-document after any
+parameter expansion, command substitution, and arithmetic
+substitution occur.
+.TP
+.BI <& digit
+The standard input is duplicated from file descriptor
+.I digit
+(see
+.IR dup (2)).
+Similarly for the standard output using
+\f3>&\^\f2digit\fR.
+.TP
+.BI <& digit \-
+The file descriptor given by
+.I digit
+is moved to standard input.
+Similarly for the standard output using
+\f3>&\^\f2digit\f3\-\fR.
+.TP
+.B <&\-
+The standard input is closed.
+Similarly for the standard output using
+.BR >&\- .
+.TP
+.B <&p
+The input from the co-process is moved to standard input.
+.TP
+.B >&p
+The output to the co-process is moved to standard output.
+.TP
+.BI <# \^\^\^ (( expr ))
+Evaluate arithmetic expression
+.I expr\^
+and position file descriptor 0
+to the resulting value
+bytes from the start of the file.
+The variables
+.B CUR
+and
+.B EOF
+evaluate to the current offset and end-of-file offset
+respectively when evaluating
+.IR expr.
+.TP
+.BI ># \^\^\^ (( offset ))
+The same as
+.B <#
+except applies to file descriptor 1.
+.TP
+.BI <# pattern
+Seeks forward to the beginning of the next line containing
+.IR pattern .
+.TP
+.BI <## pattern
+The same as
+.B <#
+except that the portion of the file that is skipped is copied to
+standard output.
+.PP
+If one of the above is preceded by a digit,
+with no intervening space, then the
+file descriptor number referred to is that specified
+by the digit
+(instead of the default 0 or 1).
+If one of the above, other than
+.BR >&\-
+and the
+.B >#
+and
+.B <#
+forms,
+is preceded by
+.BI { varname }
+with no intervening space,
+then a file descriptor number > 10
+will be selected by
+the shell and stored in the variable
+.IR varname .
+If
+.B >&\-
+or the any of the
+.B >#
+and
+.B <#
+forms
+is preceded by
+.BI { varname }
+the value of
+.I varname\^
+defines the file descriptor to close or position.
+For example:
+.PP
+.RS
+\fB\&.\|.\|. \|2>&1\fR
+.RE
+.PP
+means file descriptor 2 is to be opened
+for writing as a duplicate
+of file descriptor 1 and
+.PP
+.RS
+\fBexec {n}<file\fR
+.RE
+.PP
+means open file named
+.B file
+for reading and store
+the file descriptor number in variable
+.BR n .
+.PP
+The order in which redirections are specified is significant.
+The shell evaluates each redirection in terms of the
+.RI ( "file descriptor" ", " file )
+association at the time of evaluation.
+For example:
+.PP
+.RS
+\fB\&.\|.\|. \|1>\f2fname\^\fP 2>&1\fR
+.RE
+.PP
+first associates file descriptor 1 with file
+.IR fname\^ .
+It then associates file descriptor 2 with the file associated with file
+descriptor 1 (i.e.
+.IR fname\^ ).
+If the order of redirections were reversed, file descriptor 2 would be associated
+with the terminal (assuming file descriptor 1 had been) and then file descriptor
+1 would be associated with file
+.IR fname\^ .
+.PP
+If a command is followed by
+.B &
+and job control is not active,
+then the default standard input
+for the command
+is the empty file
+.BR /dev/null .
+Otherwise, the environment for the execution of a command contains the
+file descriptors of the invoking shell as modified by
+input/output specifications.
+.SS Environment.
+The
+.I environment\^
+(see
+.IR environ (7))
+is a list of name-value pairs that is passed to
+an executed program in the same way as a normal argument list.
+The names must be
+.I identifiers\^
+and the values are character strings.
+The shell interacts with the environment in several ways.
+On invocation, the shell scans the environment
+and creates a
+variable
+for each name found,
+giving it the corresponding value and attributes and marking it
+.IR export .
+Executed commands inherit the environment.
+If the user modifies the values of these
+variables
+or creates new ones,
+using the
+.B export
+or
+.B typeset \-x
+commands, they become part of the
+environment.
+The environment seen by any executed command is thus composed
+of any name-value pairs originally inherited by the shell,
+whose values may be modified by the current shell,
+plus any additions
+which must be noted in
+.B export
+or
+.B typeset \-x
+commands.
+.PP
+The environment for any
+.I simple-command\^
+or function
+may be augmented by prefixing it with one or more variable assignments.
+A variable assignment argument is a word of the form
+.IR identifier=value .
+Thus:
+.PP
+.RS
+\fB\s-1TERM\s+1=450 \|cmd \|args\fR and
+.br
+\fB(export \|\s-1TERM\s+1; \|\s-1TERM\s+1=450; \|cmd \|args)\fR
+.RE
+.PP
+are equivalent (as far as the above execution of
+.I cmd\^
+is concerned except for special built-in commands listed below \-
+those that are
+preceded with a dagger).
+.PP
+If the obsolete
+.B \-k
+option is set,
+.I all\^
+variable assignment arguments are placed in the environment,
+even if they occur after the command name.
+The following
+first prints
+.B "a=b c"
+and then
+.BR c :
+.PP
+.RS
+.nf
+.ft B
+echo \|a=b \|c
+set \|\-k
+echo \|a=b \|c
+.ft R
+.fi
+.RE
+This feature is intended for use with scripts written
+for early versions of the shell and its use in new scripts
+is strongly discouraged.
+It is likely to disappear someday.
+.SS Functions.
+.PP
+For historical reasons, there are two
+ways to define functions,
+the
+.IB name (\^)
+syntax and
+the
+.B function
+.I name\^
+syntax, described in the
+.I Commands
+section above.
+Shell functions are read in and stored internally.
+Alias names are resolved when the function is read.
+Functions are executed like commands with the arguments
+passed as positional parameters.
+(See
+.I Execution
+below.)
+.PP
+Functions defined by the
+.B function
+.I name
+syntax and called by name execute in the same process as the caller and
+share all files
+and present working directory with the
+caller.
+Traps caught by the caller are reset to their default action
+inside the function.
+A trap condition that is not caught or ignored by the
+function causes the function to terminate and the condition
+to be passed on to the caller.
+A trap on
+.SM
+.B EXIT
+set inside a function
+is executed
+in the environment
+of the caller
+after the function completes.
+Ordinarily,
+variables are shared between the calling program
+and the function.
+However,
+the
+.B typeset
+special built-in command used within a function
+defines local variables whose scope includes
+the current function.
+They can be passed to functions that they call in the
+variable assignment list that precedes the call or as arguments
+passed as name references.
+Errors within functions return control to the caller.
+.PP
+Functions defined with the
+.IB name (\^)
+syntax and functions defined with the
+.B function
+.I name
+syntax that are invoked with the \f3\s+2.\s-2\fP
+special built-in
+are executed in the caller's
+environment and share all variables
+and traps with the caller.
+Errors within these function executions cause the script that contains
+them to abort.
+.PP
+The special built-in command
+.B return
+is used to return
+from function calls.
+.PP
+Function names
+can be listed with the
+.B \-f
+or
+.B +f
+option of the
+.B typeset
+special built-in command.
+The text of functions, when available, will also
+be listed with
+.BR \-f .
+Functions can be undefined with the
+.B \-f
+option of the
+.B unset
+special built-in command.
+.PP
+Ordinarily, functions are unset when the shell executes a shell script.
+Functions that need to be defined across separate
+invocations of the shell should
+be placed in a directory and the
+.B
+.SM
+FPATH
+variable should contain the name of this directory.
+They may also
+be specified in the
+.B
+.SM
+ENV
+file.
+.SS Discipline Functions.
+Each variable can have zero or more discipline functions
+associated with it.
+The shell initially understands the discipline names \f3get\fP,
+\f3set\fP, \f3append\fP, and \f3unset\fP but can be added
+when defining new types. On most systems
+others can be added at run time via the
+C programming interface extension provided by the
+.B builtin
+built-in utility.
+If the \f3get\fP discipline is defined for a variable, it is invoked
+whenever the given variable is referenced.
+If the variable \f3.sh.value\fP is assigned a value inside
+the discipline function, the referenced variable will evaluate
+to this value instead.
+If the \f3set\fP discipline is defined for a variable, it is invoked
+whenever the given variable is assigned a value.
+If the \f3append\fP discipline is defined for a variable, it is invoked
+whenever a value is appended to the given variable.
+The variable \f3.sh.value\fP is given the value
+of the variable before invoking the discipline, and
+the variable will be assigned the value of \f3.sh.value\fP
+after the discipline completes.
+If \f3.sh.value\fP is unset inside the discipline, then
+that value is unchanged.
+If the \f3unset\fP discipline is defined for a variable, it is invoked
+whenever the given variable is unset.
+The variable will not be unset unless it is unset explicitly
+from within this discipline function.
+.PP
+The variable
+.B .sh.name
+contains the name of the variable for which the discipline function is called,
+.B .sh.subscript
+is the subscript of the variable, and
+.B .sh.value
+will contain the value being assigned inside the
+.B set
+discipline function.
+The variable
+.B _
+is a reference to the variable including the subscript if any.
+For the \f3set\fP discipline,
+changing
+.B .sh.value
+will change the value that gets assigned.
+Finally, the expansion \f3${\fP\f2var\^\fP\f3.\fP\f2name\^\fP\f3}\fP,
+when \f2name\^\fP is the name of a discipline, and there is
+no variable of this name, is equivalent to the command substitution
+\f3${ \fP\f2var\^\fP\f3.\fP\f2name\^\fP\f3;}\fP.
+
+.SS Name Spaces.
+Commands and functions that are executed as part of the
+.I list\^
+of a
+.B namespace
+command that modify variables or create new ones, create
+a new variable whose
+name is the name of the name space
+as given by
+.I identifier\^
+preceded by \fB\s+2.\s-2\fP.
+When a variable whose name is
+.I name\^
+is referenced, it is
+first searched for
+using \fB\s+2.\s-2\fP\f2identifier\fP\fB\s+2.\s-2\fP\f2name\fP.
+Similarly, a function defined by a command in the
+.B namespace
+.I list\^
+is created using the name space name preceded by a \fB\s+2.\s-2\fP.
+.PP
+When the
+.I list\^
+of a
+.B namespace
+command contains a
+.B namespace
+command, the names of variable and functions that are created consist
+of the variable or function name preceded by the list of
+.IR identifier\^ s
+each preceded by \fB\s+2.\s-2\fP.
+.PP
+Outside of a name space, a variable or function created inside a
+names space can be referenced by preceding it with the name space name.
+.PP
+By default, variables staring with
+\fB\s+2.\s-2sh\fP are in the
+.B sh
+name space.
+
+.SS Type Variables.
+Typed variables provide a way to create data structure and objects.
+A type can be defined either by a shared library, by the
+.B enum
+built-in command described below, or by using the new
+.B \-T
+option of the
+.B typeset
+built-in command.
+With the
+.B \-T
+option of
+.BR typeset ,
+the type name, specified as an option argument to
+.BR \-T ,
+is set with a compound variable assignment that defines the type.
+Function definitions can appear inside the compound variable
+assignment and these become discipline functions for this type and
+can be invoked or redefined by each instance of the type.
+The function name
+.B create
+is treated specially. It is invoked for each instance of
+the type that is created but is not inherited and cannot be
+redefined for each instance.
+.PP
+When a type is defined a special built-in command of that name
+is added. These built-ins are declaration commands and follow the
+same expansion rules as all the special built-in commands defined
+below that are preceded by \(dg\(dg. These commands can subsequently
+be used inside further type definitions. The man page for these commands can
+be generated by using the
+.B \-\-man
+option or any of the other
+.B \-\-
+options described with
+.BR getopts .
+The
+.BR \-r ,
+.BR \-a ,
+.BR \-A ,
+.BR \-h ,
+and
+.B \-S
+options of
+.B typeset
+are permitted with each of these new built-ins.
+.PP
+An instance of a type is created by invoking the type name
+followed by one or more instance names.
+Each instance of the type is initialized with a copy of the sub-variables
+except for sub-variables that are defined with the
+.B \-S
+option. Variables defined with the
+.B \-S
+are shared by all instances of the type.
+Each instance can change the value of any sub-variable and can also
+define new discipline functions of the same names
+as those defined by the type definition as well as any
+standard discipline names.
+No additional sub-variables can be defined for any instance.
+.PP
+When defining a type,
+if the value of a sub-variable is not set and the
+.B \-r
+attribute is specified, it causes the sub-variable
+to be a required sub-variable.
+Whenever an instance of a type is created, all required sub-variables
+must be specified.
+These sub-variables become readonly in each instance.
+.PP
+When
+.B unset
+is invoked on a sub-variable within a type,
+and the
+.B \-r
+attribute has not been specified for this field,
+the value is reset to the default value associative with
+the type.
+Invoking
+.B unset
+on a type instance not contained within another type deletes
+all sub-variables and the variable itself.
+.PP
+A type definition can be derived from another type definition
+by defining the first sub-variable name as
+.B _
+and defining its type as the base type.
+Any remaining definitions will be additions and modifications
+that apply to the new type.
+If the new type name is the same is that of the base type,
+the type will be replaced and the original type will
+no longer be accessible.
+.PP
+The
+.B typeset
+command with the
+.B \-T
+and no option argument or operands will write all the type definitions to
+standard output in a form that that can be read in to create all they types.
+.SS Jobs.
+.PP
+If the
+.B monitor
+option of the
+.B set
+command is turned on,
+an interactive shell associates a \fIjob\fR with each pipeline.
+It keeps
+a table of current jobs, printed by the
+.B jobs
+command, and assigns them small integer numbers.
+When a job is started asynchronously with
+.BR & ,
+the shell prints a line which looks
+like:
+.PP
+.DT
+ [1] 1234
+.PP
+indicating that the job which was started asynchronously was job number
+1 and had one (top-level) process, whose process id was 1234.
+.PP
+This paragraph and the next require features that are
+not in all versions of UNIX and may not apply.
+If you are running a job and wish to do something else you may hit the key
+\fB^Z\fR (control-Z) which sends a STOP signal to the current job.
+The shell will then normally indicate that the job has been `Stopped',
+and print another prompt.
+You can then manipulate the state of this job,
+putting it in the background with the
+.B bg
+command, or run some other
+commands and then eventually bring the job back into the foreground with
+the foreground command
+.BR fg .
+A \fB^Z\fR takes effect immediately and
+is like an interrupt in that pending output and unread input are discarded
+when it is typed.
+.PP
+A job being run in the background will stop if it tries to read
+from the terminal.
+Background jobs are normally allowed to produce output,
+but this can be disabled by giving the command
+.BR "stty tostop" .
+If you set this
+tty option, then background jobs will stop when they try to produce
+output like they do when they try to read input.
+.PP
+A job pool is a collection of jobs started with
+.I list\^
+.B &
+associated with a name.
+.PP
+There are several ways to refer to jobs in the shell.
+A job can be referred to by the process id of any process of the job
+or by one of the following:
+.PD 0
+.TP
+.BI % number
+The job with the given number.
+.TP
+.I pool\^
+All the jobs in the job pool named by
+.IR pool .
+.TP
+.IB pool . number
+The job number
+.I number\^
+in the job pool named by
+.IR pool .
+.TP
+.BI % string
+Any job whose command line begins with
+.IR string .
+.TP
+.BI %? string
+Any job whose command line contains
+.IR string .
+.TP
+.BI %%
+Current job.
+.TP
+.BI %+
+Equivalent to
+.BR %% .
+.TP
+.BI %\-
+Previous job.
+.PD
+In addition, unless noted otherwise, wherever a job can be specified,
+the name of a background job pool can be used to represent all the
+jobs in that pool.
+.PP
+The shell learns immediately whenever a process changes state.
+It normally informs you whenever a job becomes blocked so that
+no further progress is possible, but only just before it prints
+a prompt.
+This is done so that it does not otherwise disturb your work.
+The
+.B notify
+option of the
+.B set
+command causes
+the shell to print these job change messages
+as soon as they occur.
+.PP
+When the
+.B monitor
+option is on, each background job that completes
+triggers any trap set for
+.BR CHLD .
+.PP
+When you try to leave the shell while jobs are running or stopped, you will
+be warned that `You have stopped(running) jobs.'
+You may use the
+.B jobs
+command to see what they are.
+If you immediately try to
+exit again, the shell will not warn you a second time, and the stopped
+jobs will be terminated.
+When a login shell receives a HUP signal, it sends
+a HUP signal to each job that has not been disowned with the
+.B disown
+built-in command described below.
+.SS Signals.
+The \s-1INT\s+1 and \s-1QUIT\s+1 signals for an invoked
+command are ignored if the command is followed by
+.B &
+and the
+.B monitor
+option is not active.
+Otherwise, signals have the values
+inherited by the shell from its parent
+(but see also
+the
+.B trap
+built-in command below).
+.SS Execution.
+Each time a command is read, the above substitutions
+are carried out.
+If the command name matches one
+of the
+.I "Special Built-in Commands\^"
+listed below,
+it is executed within the
+current shell process.
+Next, the command name is checked to see if
+it matches a user defined function.
+If it does,
+the positional parameters are saved
+and then reset to the arguments of the
+.I function\^
+call.
+A function is also executed in the
+current shell process.
+When the
+.I function\^
+completes or issues a
+.BR return ,
+the positional parameter list is restored.
+For functions defined with the
+.B function
+.I name\^
+syntax,
+any trap set on
+.SM
+.B EXIT
+within the function is executed.
+The exit value of a
+.I function\^
+is the value of the last command executed.
+If a command name is not a
+.I "special built-in command\^"
+or a user defined
+.IR function ,
+but it is one of the built-in commands listed below,
+it is executed in the current shell process.
+.PP
+The shell variable
+.B
+.SM PATH
+defines the search path for
+the directory containing the command.
+Alternative directory names are separated by
+a colon
+.RB ( : ).
+The default path is
+.B /bin:/usr/bin:
+(specifying
+.BR /bin ,
+.BR /usr/bin ,
+and the current directory
+in that order).
+The current directory can be specified by
+two or more adjacent colons, or by a colon
+at the beginning or end of the path list.
+If the command name contains a \f3/\fP, then the search path
+is not used.
+Otherwise, each directory in the path is
+searched for an executable file
+of the given name
+that is not a directory.
+If found, and if the shell
+determines that there is a built-in version
+of a command corresponding to a given pathname,
+this built-in is invoked in the current process.
+If found, and this directory is also contained in the value of the
+.B
+.SM FPATH
+variable,
+then this file is loaded into the current shell environment
+as if it were the argument to the \fB.\fP command
+except that only preset aliases are expanded,
+and a function of the given name is executed
+as described above.
+If not found, and the file
+.B .paths
+is found, and this file contains a line of the form
+.BI FPATH= path
+where
+.I path\^
+names an
+existing directory, and this directory contains
+a file of the given name,
+then this file is loaded into the current shell environment
+as if it were the argument to the \fB.\fP special built-in command
+and a function of the given name is executed.
+Otherwise, if found,
+a process is created and
+an attempt is made to execute the command via
+.IR exec (2).
+.P
+When an executable is found, the directory where it is found
+in is searched for a file named
+.BR .paths .
+If this file is found and it contains a line of the form
+.BI BUILTIN_LIB= value\^
+, then the library named by
+.I value\^
+will be searched for as if it were an option argument to
+.BR "builtin -f" ,
+and if it contains a built-in of the specified name
+this will be executed instead of a command by this name.
+Otherwise, if this file is found and it contains a line of the form
+.IB name\^ = value\^
+in the first or second line, then the environment variable
+.I name\^
+is modified by prepending the directory specified by
+.I value\^
+to the directory list.
+If
+.I value\^
+is not an absolute directory, then it
+specifies a directory relative to the directory that the
+executable was found.
+If the environment variable
+.I name\^
+does not already exist it will be added to the environment
+list for the specified command.
+.P
+If the file has execute permission but is not an
+.B a.out
+file,
+it is assumed to be a file containing shell commands.
+A separate shell is spawned to read it.
+All non-exported variables are removed in this case.
+If the shell command
+file doesn't have read permission,
+or if the
+.I setuid
+and/or
+.I setgid
+bits are set on the file,
+then the shell executes an agent whose job it is to
+set up the permissions and execute the shell with the
+shell command file passed down as an open file.
+A parenthesized command is executed in
+a sub-shell without removing non-exported variables.
+.SS Command Re-entry.
+The text of the last
+.B
+.SM
+HISTSIZE
+(default 512)
+commands entered from a terminal device
+is saved in a
+.I history
+file.
+The file
+.B \s-1$HOME\s+1/.sh_history
+is used if the
+.B
+.SM
+HISTFILE
+variable is not set
+or if the file it names is not writable.
+A shell can access the commands of
+all
+.I interactive
+shells which use the same named
+.SM
+.BR HISTFILE .
+The built-in command
+.B hist\^
+is used to list or
+edit a portion of this file.
+The portion of the file to be edited or listed can be selected by
+number or by giving the first character or
+characters of the command.
+A single command or range of commands can be specified.
+If you do not specify an editor program as
+an argument to
+.B hist\^
+then the value of the variable
+.SM
+.B HISTEDIT
+is used.
+If
+.SM
+.B HISTEDIT
+is unset, the obsolete variable
+.SM
+.B FCEDIT
+is used.
+If
+.SM
+.B FCEDIT
+is not defined, then
+.B /bin/ed
+is used.
+The edited command(s) is printed and re-executed upon
+leaving the editor unless you quit without writing.
+The
+.B \-s
+option
+(and in obsolete versions, the editor name
+.BR \-\^ )
+is used to skip the editing phase and
+to re-execute the command.
+In this case a substitution parameter of the form
+\f2old\fP\f3=\fP\f2new\fP
+can be used to modify the command before execution.
+For example, with the preset alias
+.BR r ,
+which is aliased to
+.BR "\(fmhist \-s\(fm" ,
+typing
+`\f3r bad=good c\fP'
+will re-execute the most recent command which starts with the letter
+.BR c ,
+replacing the first occurrence of the string
+.B bad
+with the string
+.BR good .
+.SS In-line Editing Options.
+Normally, each command line entered from a terminal device is simply
+typed followed by a \f3new-line\fP (`RETURN' or `LINE\ FEED').
+If either the
+.BR emacs ,
+.BR gmacs ,
+or
+.B vi
+option is active, the user can edit the command line.
+To be in either of these edit modes
+.B set
+the corresponding
+option.
+An editing option is automatically selected each time the
+.SM
+.B VISUAL
+or
+.SM
+.B EDITOR
+variable is assigned a value ending in either of these
+option names.
+.PP
+The editing features require that the user's terminal
+accept `RETURN' as carriage return without line feed
+and that a space (`\ ') must overwrite the current character on
+the screen.
+.PP
+Unless the
+.B multiline
+option is on,
+the editing modes implement a concept where the user is looking through a
+window at the current line.
+The window width is the value of
+.SM
+.B COLUMNS
+if it is defined, otherwise 80.
+If the window width is too small to display the prompt and leave
+at least 8 columns to enter input, the prompt is truncated from the
+left.
+If the line is longer than the window width minus two, a mark is
+displayed at the end of the window to notify the user.
+As the cursor moves and reaches the window boundaries the window will be
+centered about the cursor.
+The mark is a
+.BR > " (<" ,
+.BR * )
+if the line extends on the
+right (left, both) side(s) of the window.
+.PP
+The search commands in each edit mode provide access to the history file.
+Only strings are matched, not patterns, although a leading
+.B ^
+in the string restricts the match
+to begin at the first character in the line.
+.PP
+Each of the edit modes has an operation to list the files
+or commands that match a partially entered word.
+When applied to the first word on the line,
+or the first word after a
+.BR ; ,
+.BR \(bv ,
+.BR & ,
+or
+.BR ( ,
+and the word does not begin with
+.B \(ap
+or contain a
+.BR / ,
+the list of aliases, functions, and executable commands
+defined by the
+.B
+.SM PATH
+variable that could match the partial word is displayed.
+Otherwise, the list of files that match the given
+word is displayed.
+If the partially entered word does not contain any
+file expansion characters, a
+.B *
+is appended before generating these lists.
+After displaying the generated list, the input line
+is redrawn.
+These operations are called command name listing and file name listing,
+respectively.
+There are additional operations, referred to as command name
+completion and file name completion, which compute the list
+of matching commands or files, but instead of printing the list,
+replace
+the current word with a complete or partial match.
+For file name completion,
+if the match is unique, a
+.B /
+is appended if the file is a directory and a space is
+appended if the file is not a directory.
+Otherwise, the longest common prefix for all the matching
+files replaces the word.
+For command name completion, only the portion of the file names
+after the last
+.B /
+are used to find the longest command prefix.
+If only a single name matches this prefix, then the
+word is replaced with the command name followed by a space.
+When using a
+.I tab\^
+for completion that does not yield a unique match,
+a subsequent
+.I tab\^
+will provide a numbered list of matching alternatives.
+A specific selection can be made by entering the
+selection number followed by a
+.IR tab .
+.SS Key Bindings.
+The
+.B
+.SM KEYBD
+trap can be used to intercept keys as they are typed
+and change the characters that are actually seen by
+the shell.
+This trap is executed after each character
+(or sequence of characters when the first character is ESC)
+is entered while reading from a terminal.
+The variable
+.B .sh.edchar
+contains the character or character sequence which
+generated the trap.
+Changing the value of
+.B .sh.edchar
+in the trap action causes the shell to behave as if the
+new value were entered from the keyboard rather than
+the original value.
+.PP
+The variable
+.B .sh.edcol
+is set to the input column number of the cursor at the time
+of the input.
+The variable
+.B .sh.edmode
+is set to
+ESC
+when in
+.B vi
+insert mode (see below) and is null otherwise.
+By prepending
+.B ${.sh.editmode}
+to a value assigned to
+.B .sh.edchar
+it will cause the shell
+to change to control mode if it is not already in this mode.
+.PP
+This trap is not invoked for characters entered as arguments to
+editing directives, or while reading input for a character search.
+.SS Emacs Editing Mode.
+This mode is entered by enabling either the
+.B emacs
+or
+.B gmacs
+option.
+The only difference between these two modes is the way
+they handle
+.BR ^T .
+To edit, the user
+moves the cursor to the point needing correction and
+then inserts or deletes characters or words as needed.
+All the editing commands are control characters or escape
+sequences.
+The notation for control characters is caret
+.RB ( ^ )
+followed
+by the character.
+For example,
+.B ^F
+is the notation for control
+.BR F .
+This is entered by depressing `f' while holding down the
+`CTRL' (control) key.
+The `SHIFT' key is
+.I not
+depressed.
+(The notation
+.B ^?
+indicates the DEL (delete) key.)
+.PP
+The notation for escape sequences is
+.B M-
+followed by a
+character.
+For example,
+.B M-f
+(pronounced Meta f)
+is entered by depressing ESC
+(ascii
+.BR 033 )
+followed by `f'.
+.RB ( M-F
+would be the notation for ESC followed by `SHIFT' (capital) `F'.)
+.PP
+All edit commands
+operate from any place on the line
+(not just at the beginning).
+Neither the `RETURN' nor the `LINE FEED' key is
+entered after edit commands except when noted.
+.PP
+.PD 0
+.TP 10
+.BI ^F
+Move cursor forward (right) one character.
+.PP
+.TP 10
+.BI M-[C
+Move cursor forward (right) one character.
+.PP
+.TP 10
+.BI M-f
+Move cursor forward one word.
+(The
+.B emacs
+editor's idea of a word is a string of characters
+consisting of only letters, digits and underscores.)
+.PP
+.TP 10
+.BI ^B
+Move cursor backward (left) one character.
+.PP
+.TP 10
+.BI M-[D
+Move cursor backward (left) one character.
+.PP
+.TP 10
+.BI M-b
+Move cursor backward one word.
+.PP
+.TP 10
+.BI ^A
+Move cursor to start of line.
+.PP
+.TP 10
+.BI M-[H
+Move cursor to start of line.
+.PP
+.TP 10
+.BI ^E
+Move cursor to end of line.
+.PP
+.TP 10
+.BI M-[Y
+Move cursor to end of line.
+.PP
+.TP 10
+.BI ^] char
+Move cursor forward to character
+.I char
+on current line.
+.PP
+.TP 10
+.BI M-^] char
+Move cursor backward to character
+.I char
+on current line.
+.PP
+.TP 10
+.BI ^X^X
+Interchange the cursor and mark.
+.PP
+.TP 10
+.I erase
+(User defined erase character as defined
+by the
+.IR stty (1)
+command, usually
+.B ^H
+or
+.BR # .)
+Delete previous character.
+.PP
+.TP 10
+.I lnext
+(User defined literal next character as defined
+by the
+.IR stty (1)
+command,
+or
+.B ^V
+if not defined.)
+Removes the next character's
+editing features (if any).
+.PP
+.TP 10
+.BI ^D
+Delete current character.
+.PP
+.TP 10
+.BI M-d
+Delete current word.
+.PP
+.TP 10
+.BI M-^H
+(Meta-backspace) Delete previous word.
+.PP
+.TP 10
+.BI M-h
+Delete previous word.
+.PP
+.TP 10
+.BI M-^?
+(Meta-DEL) Delete previous word (if your interrupt character is
+.B ^?
+(DEL, the default) then this command will not work).
+.PP
+.TP 10
+.BI ^T
+Transpose current character with previous character
+and advance the cursor
+in
+.I emacs
+mode.
+Transpose two previous characters in
+.I gmacs
+mode.
+.PP
+.TP 10
+.BI ^C
+Capitalize current character.
+.PP
+.TP 10
+.BI M-c
+Capitalize current word.
+.PP
+.TP 10
+.BI M-l
+Change the current word to lower case.
+.PP
+.TP 10
+.BI ^K
+Delete from the cursor to the end of the line.
+If preceded by a numerical parameter whose value is less than the
+current cursor position, then delete from given position
+up to the cursor.
+If preceded by a numerical parameter whose value is greater than the
+current cursor position, then delete from cursor up to
+given cursor position.
+.PP
+.TP 10
+.BI ^W
+Kill from the cursor to the mark.
+.PP
+.TP 10
+.BI M-p
+Push the region from the cursor to the mark on the stack.
+.PP
+.TP 10
+.I kill
+(User defined kill character as defined
+by the stty command, usually
+.B ^G
+or
+.BR @ .)
+Kill the entire current line.
+If two
+.I kill
+characters are entered in succession, all
+kill characters from then on cause a line feed
+(useful when using paper terminals).
+.PP
+.TP 10
+.BI ^Y
+Restore last item removed from line. (Yank item back to the line.)
+.PP
+.TP 10
+.BI ^L
+Line feed and print current line.
+.PP
+.TP 10
+.BI M-^L
+Clear the screen.
+.PP
+.TP 10
+.BI ^@
+(Null character) Set mark.
+.PP
+.TP 10
+.BI M- space
+(Meta space) Set mark.
+.PP
+.TP 10
+.BI ^J
+(New\ line) Execute the current line.
+.PP
+.TP 10
+.BI ^M
+(Return) Execute the current line.
+.PP
+.TP 10
+.I eof
+End-of-file character,
+normally
+.BR ^D ,
+is processed as an End-of-file only
+if the current line is null.
+.PP
+.TP 10
+.BI ^P
+Fetch previous command.
+Each time
+.B ^P
+is entered
+the previous command back in time is accessed.
+Moves back one line when not on the first line of a multi-line command.
+.PP
+.TP 10
+.BI M-[A
+If the cursor is at the end of the line, it is equivalent to
+.B ^R
+with
+.I string\^
+set to the contents of the current line.
+Otherwise, it is
+equivalent to
+.BR ^P.
+.PP
+.TP 10
+.BI M-<
+Fetch the least recent (oldest) history line.
+.PP
+.TP 10
+.BI M->
+Fetch the most recent (youngest) history line.
+.PP
+.TP 10
+.BI ^N
+Fetch next command line.
+Each time
+.B ^N
+is entered
+the next command line forward in time is accessed.
+.PP
+.TP 10
+.BI M-[B
+Equivalent to
+.BR ^N.
+.PP
+.TP 10
+.BI ^R string
+Reverse search history for a previous command line containing
+.IR string .
+If a parameter of zero is given, the search is forward.
+.I String
+is terminated by a `RETURN' or `NEW\ LINE'.
+If string is preceded by a
+.BR ^ ,
+the matched line must begin with
+.IR string .
+If
+.I string
+is omitted,
+then the next command line containing the most recent
+.I string
+is accessed.
+In this case a parameter of zero
+reverses the direction of the search.
+.PP
+.TP 10
+.B ^O
+Operate \- Execute the current line and fetch
+the next line relative to current line from the
+history file.
+.PP
+.TP 10
+.BI M- digits
+(Escape) Define numeric parameter, the digits
+are taken as a parameter to the next command.
+The commands that accept a parameter are
+.BR ^F ,
+.BR ^B ,
+.IR erase ,
+.BR ^C ,
+.BR ^D ,
+.BR ^K ,
+.BR ^R ,
+.BR ^P ,
+.BR ^N ,
+.BR ^] ,
+.BR M-. ,
+.BR M-^] ,
+.BR M-_ ,
+.BR M-= ,
+.BR M-b ,
+.BR M-c ,
+.BR M-d ,
+.BR M-f ,
+.BR M-h ,
+.B M-l
+and
+.BR M-^H .
+.PP
+.TP 10
+.BI M- letter
+Soft-key \- Your alias list is searched for an
+alias by the name
+.BI _ letter
+and if an alias of this name is defined, its
+value will be inserted on the input queue.
+The
+.I letter
+must not be one of the above meta-functions.
+.PP
+.TP 10
+.BI M-[ letter
+Soft-key \- Your alias list is searched for an
+alias by the name
+.BI _\&_ letter
+and if an alias of this name is defined, its
+value will be inserted on the input queue.
+This can be used to program function keys on many terminals.
+.PP
+.TP 10
+.B M-.
+The last word of the previous command is inserted
+on the line.
+If preceded by a numeric parameter, the value
+of this parameter determines which word to insert rather than
+the last word.
+.PP
+.TP 10
+.B M-_
+Same as
+.BR M-. .
+.PP
+.TP 10
+.B M-*
+Attempt file name generation on the current word.
+An asterisk is appended if the word doesn't match any file
+or contain any special
+pattern characters.
+.PP
+.TP 10
+.B M-ESC
+Command or file name completion as described above.
+.PP
+.TP 10
+.BI ^I " tab"
+Attempts command or file name completion as described above.
+If a partial completion occurs, repeating this will
+behave as if
+.B M-=
+were entered.
+If no match is found or entered after
+.IR space\^ ,
+a
+.I tab\^
+is inserted.
+.PP
+.TP 10
+.B M-=
+If not preceded by a numeric parameter,
+it generates the list of matching commands or
+file names as described above.
+Otherwise, the word under the cursor is replaced by
+the item corresponding to the value of the numeric parameter
+from the most recently generated command or file list.
+If the cursor is not on a word, it is inserted instead.
+.PP
+.TP 10
+.BI ^U
+Multiply parameter of next command by 4.
+.PP
+.TP 10
+.BI \e
+Escape next character.
+Editing characters, the user's erase, kill and
+interrupt (normally
+.BR ^? )
+characters
+may be entered
+in a command line or in a search string if preceded by a
+.BR \e .
+The
+.B \e
+removes the next character's
+editing features (if any).
+.PP
+.TP 10
+.B M-^V
+Display version of the shell.
+.PP
+.TP 10
+.B M-#
+If the line does not begin with a
+.BR # ,
+a
+.B #
+is inserted
+at the beginning of the line
+and after each new-line,
+and the line is entered.
+This causes a comment to be inserted in the history file.
+If the line begins with a
+.BR # ,
+the
+.B #
+is deleted and one
+.B #
+after each new-line is also deleted.
+.PD
+.SS Vi Editing Mode.
+There are two typing modes.
+Initially, when you enter a command you are in the
+.I input\^
+mode.
+To edit, the user enters
+.I control\^
+mode by typing ESC
+.RB ( 033 )
+and moves the cursor to the point needing correction and
+then inserts or deletes characters or words as needed.
+Most control commands accept an optional repeat
+.I count
+prior to the command.
+.PP
+When in
+.B vi
+mode on most systems,
+canonical processing is initially enabled and the
+command will be echoed again if the speed is 1200 baud or greater and it
+contains any control characters or less than one second has elapsed
+since the prompt was printed.
+The ESC character terminates canonical processing for the remainder of the command
+and the user can then modify the command line.
+This scheme has the advantages of canonical processing with the type-ahead
+echoing of raw mode.
+.PP
+If the option
+.B viraw
+is also set, the terminal will always have canonical processing
+disabled.
+This mode is implicit for systems that do not support two
+alternate end of line delimiters,
+and may be helpful for certain terminals.
+.SS "\ \ \ \ \ Input Edit Commands"
+.PP
+.RS
+By default the editor is in input mode.
+.PD 0
+.TP 10
+.I erase
+(User defined erase character as defined
+by the stty command, usually
+.B ^H
+or
+.BR # .)
+Delete previous character.
+.TP 10
+.BI ^W
+Delete the previous blank separated word.
+On some systems the \f3viraw\fP option
+may be required for this to work.
+.TP 10
+.I eof
+As the first character of the line causes
+the shell to terminate unless the \f3ignoreeof\fP
+option is set.
+Otherwise this character is ignored.
+.TP 10
+.I lnext
+(User defined literal next character as defined
+by the
+.IR stty (1)
+or
+.B ^V
+if not defined.)
+Removes the next character's
+editing features (if any).
+On some systems the \f3viraw\fP option
+may be required for this to work.
+.TP 10
+.BI \e
+Escape the next
+.I erase
+or
+.I kill
+character.
+.TP 10
+.BI ^I " tab"
+Attempts command or file name completion as described above
+and returns to input mode.
+If a partial completion occurs, repeating this will
+behave as if
+.B =
+were entered from control mode.
+If no match is found or entered after
+.IR space\^ ,
+a
+.I tab\^
+is inserted.
+.RE
+.SS "\ \ \ \ \ Motion Edit Commands"
+.RS
+These commands will move the cursor.
+.TP 10
+[\f2count\fP]\f3l\fP
+Cursor forward (right) one character.
+.TP 10
+[\f2count\fP]\f3[C\fP
+Cursor forward (right) one character.
+.TP 10
+[\f2count\fP]\f3w\fP
+Cursor forward one alpha-numeric word.
+.TP 10
+[\f2count\fP]\f3W\fP
+Cursor to the beginning of the next word that follows a blank.
+.TP 10
+[\f2count\fP]\f3e\fP
+Cursor to end of word.
+.TP 10
+[\f2count\fP]\f3E\fP
+Cursor to end of the current blank delimited word.
+.TP 10
+[\f2count\fP]\f3h\fP
+Cursor backward (left) one character.
+.TP 10
+[\f2count\fP]\f3[D\fP
+Cursor backward (left) one character.
+.TP 10
+[\f2count\fP]\f3b\fP
+Cursor backward one word.
+.TP 10
+[\f2count\fP]\f3B\fP
+Cursor to preceding blank separated word.
+.TP 10
+[\f2count\fP]\f3\(bv\fP
+Cursor to column
+.IR count .
+.TP 10
+[\f2count\fP]\f3f\fP\f2c\fP
+Find the next character \fIc\fP in the current line.
+.TP 10
+[\f2count\fP]\f3F\fP\f2c\fP
+Find the previous character \fIc\fP in the current line.
+.TP 10
+[\f2count\fP]\f3t\fP\f2c\fP
+Equivalent to
+.B f
+followed by
+.BR h .
+.TP 10
+[\f2count\fP]\f3T\fP\f2c\fP
+Equivalent to
+.B F
+followed by
+.BR l .
+.TP 10
+[\f2count\fP]\f3;\fP
+Repeats
+.I count
+times,
+the last single character find command,
+.BR f ,
+.BR F ,
+.BR t ,
+or
+.BR T .
+.TP 10
+[\f2count\fP]\f3,\fP
+Reverses the last single character find command
+.I count
+times.
+.TP 10
+.B 0
+Cursor to start of line.
+.TP 10
+.B ^
+Cursor to start of line.
+.TP 10
+.B [H
+Cursor to first non-blank character in line.
+.TP 10
+.B $
+Cursor to end of line.
+.TP 10
+.B [Y
+Cursor to end of line.
+.TP 10
+.B %
+Moves to balancing
+.BR ( ,
+.BR ) ,
+.BR { ,
+.BR } ,
+.BR [ ,
+or
+.BR ] .
+If cursor is not on one of the above characters,
+the remainder of the line is searched for the first
+occurrence of one of the above characters first.
+.RE
+.SS "\ \ \ \ \ Search Edit Commands"
+.RS
+These commands access your command history.
+.TP 10
+[\f2count\fP]\f3k\fP
+Fetch previous command.
+Each time
+.B k
+is entered
+the previous command back in time is accessed.
+.TP 10
+[\f2count\fP]\f3\-\fP
+Equivalent to
+.BR k .
+.TP 10
+[\f2count\fP]\f3[A\fP
+If cursor is at the end of the line it is equivalent to
+.B /
+with
+.I string^\
+set to the contents of the current line.
+Otherwise, it is equivalent to
+.BR k .
+.TP 10
+[\f2count\fP]\f3j\fP
+Fetch next command.
+Each time
+.B j
+is entered
+the next command forward in time is accessed.
+.TP 10
+[\f2count\fP]\f3+\fP
+Equivalent to
+.BR j .
+.TP 10
+[\f2count\fP]\f3[B\fP
+Equivalent to
+.BR j .
+.TP 10
+[\f2count\fP]\f3G\fP
+The command number
+.I count
+is fetched.
+The default is the least recent history command.
+.TP 10
+.BI / string
+Search backward through history for a previous command containing
+.IR string .
+.I String
+is terminated by a `RETURN' or `NEW\ LINE'.
+If string is preceded by a
+.BR ^ ,
+the matched line must begin with
+.IR string .
+If \fIstring\fP is null, the previous string will be used.
+.TP 10
+.BI ? string
+Same as
+.B /
+except that search will be in the forward direction.
+.TP 10
+.B n
+Search for next match of the last pattern to
+.B /
+or
+.B ?
+commands.
+.TP 10
+.B N
+Search for next match of the last pattern to
+.B /
+or
+.BR ? ,
+but in reverse direction.
+.RE
+.SS "\ \ \ \ \ Text Modification Edit Commands"
+.RS
+These commands will modify the line.
+.TP 10
+.B a
+Enter input mode and enter text after the current character.
+.TP 10
+.B A
+Append text to the end of the line.
+Equivalent to
+.BR $a .
+.TP 10
+[\f2count\fP]\f3c\fP\f2motion\fP
+.TP 10
+\f3c\fP[\f2count\fP]\f2motion\fP
+Delete current character through the character that
+.I motion
+would move the cursor to and enter input mode.
+If \fImotion\fP is
+.BR c ,
+the entire line will be deleted and
+input mode entered.
+.TP 10
+.B C
+Delete the current character through the end of line and enter input mode.
+Equivalent to
+.BR c$ .
+.TP 10
+.B S
+Equivalent to
+.BR cc .
+.TP 10
+[\f2count\fP]\f3s\fP
+Replace characters under the cursor in input mode.
+.TP 10
+.B D
+Delete the current character through the end of line.
+Equivalent to
+.BR d$ .
+.TP 10
+[\f2count\fP]\f3d\fP\f2motion\fP
+.TP 10
+\f3d\fP[\f2count\fP]\f2motion\fP
+Delete current character through the character that
+.I motion
+would move to.
+If \fImotion\fP is
+.B d ,
+the entire line will be deleted.
+.TP 10
+.B i
+Enter input mode and insert text before the current character.
+.TP 10
+.B I
+Insert text before the beginning of the line.
+Equivalent to
+.BR 0i .
+.TP 10
+[\f2count\fP]\f3P\fP
+Place the previous text modification before the cursor.
+.TP 10
+[\f2count\fP]\f3p\fP
+Place the previous text modification after the cursor.
+.TP 10
+.B R
+Enter input mode and
+replace characters on the screen with characters you type overlay fashion.
+.TP 10
+[\f2count\fP]\f3r\fP\f2c\fP
+Replace the
+.I count
+character(s) starting at the current cursor position with
+.IR c ,
+and advance the cursor.
+.TP 10
+[\f2count\fP]\f3x\fP
+Delete current character.
+.TP 10
+[\f2count\fP]\f3X\fP
+Delete preceding character.
+.TP 10
+[\f2count\fP]\f3.\fP
+Repeat the previous text modification command.
+.TP 10
+[\f2count\fP]\f3\(ap\fP
+Invert the case of the
+.I count
+character(s) starting at the current cursor position and advance the cursor.
+.TP 10
+[\f2count\fP]\f3_\fP
+Causes the
+.I count\^
+word of the previous command to be appended and
+input mode entered.
+The last word is used
+if
+.I count\^
+is omitted.
+.TP 10
+.B *
+Causes an
+.B *
+to be appended to the current word and file name generation attempted.
+If no match is found,
+it rings the bell.
+Otherwise, the word is replaced
+by the matching pattern and input mode is entered.
+.TP 10
+.B \e
+Command or file name completion as described above.
+.RE
+.SS "\ \ \ \ \ Other Edit Commands"
+.RS
+Miscellaneous commands.
+.TP 10
+[\f2count\fP]\f3y\fP\f2motion\fP
+.TP 10
+\f3y\fP[\f2count\fP]\f2motion\fP
+Yank current character through character that
+.I motion
+would move the cursor to and puts them into the delete buffer.
+The text and cursor are unchanged.
+.TP 10
+.B yy
+Yanks the entire line.
+.TP 10
+.B Y
+Yanks from current position to end of line.
+Equivalent to
+.BR y$ .
+.TP 10
+.B u
+Undo the last text modifying command.
+.TP 10
+.B U
+Undo all the text modifying commands performed on the line.
+.TP 10
+[\f2count\fP]\f3v\fP
+Returns the command
+.BI "hist \-e ${\s-1VISUAL\s+1:\-${\s-1EDITOR\s+1:\-vi}}" " count"
+in the input buffer.
+If
+.I count\^
+is omitted, then the current line is used.
+.TP 10
+.BI ^L
+Line feed and print current line.
+Has effect only in control mode.
+.TP 10
+.BI ^J
+(New\ line) Execute the current line, regardless of mode.
+.TP 10
+.BI ^M
+(Return) Execute the current line, regardless of mode.
+.TP 10
+.B #
+If the first character of the command is a
+.BR # ,
+then this command deletes this
+.B #
+and each
+.B #
+that follows a newline.
+Otherwise,
+sends the line after
+inserting a
+.B #
+in front of each line in the command.
+Useful for causing the current line to be
+inserted in the history as a comment and
+uncommenting previously commented commands
+in the history file.
+.TP 10
+[\f2count\fP]\f3=\fP
+If \f2count\fP is not specified,
+it generates the list of matching commands or
+file names as described above.
+Otherwise, the word under the the cursor is replaced by the
+\f2count\fP item from the most recently generated command or file list.
+If the cursor is not on a word, it is inserted instead.
+.TP 10
+.BI @ letter
+Your alias list is searched for an
+alias by the name
+.BI _ letter
+and if an alias of this name is defined, its
+value will be inserted on the input queue for processing.
+.TP 10
+.BI ^V
+Display version of the shell.
+.RE
+.PD
+.SS Built-in Commands.
+The following simple-commands are executed in the shell process.
+Input/Output redirection is permitted.
+Unless otherwise indicated, the output is written on file descriptor 1
+and the exit status, when there is no syntax error, is zero.
+Except for
+.BR : ,
+.BR true ,
+.BR false ,
+.BR echo ,
+.BR newgrp ,
+and
+.BR login ,
+all built-in commands accept
+.B \-\-
+to indicate end of options.
+They also interpret the option
+.B \-\-man
+as a request to display the man page onto
+standard error and
+.B \-?
+as a help request which prints a
+.I usage\^
+message
+on standard error.
+Commands that are preceded by one or two \(dg symbols
+are special built-in commands and
+are treated specially in the following ways:
+.PD 0
+.TP
+1.
+Variable assignment lists preceding the command
+remain in effect when the command completes.
+.TP
+2.
+I/O redirections are processed after variable assignments.
+.TP
+3.
+Errors
+cause a script
+that contains them to abort.
+.TP
+4.
+They are not valid function names.
+.TP
+5.
+Words
+following a command preceded by \(dg\(dg
+that are in the format of a variable assignment
+are expanded with the same rules as a variable assignment.
+This means that
+tilde substitution is performed after the
+.B =
+sign and field splitting and file name generation are not
+performed.
+These are called
+.I declaration\^
+built-ins.
+.PD
+.TP
+\(dg \f3:\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+The command only expands parameters.
+.br
+.ne 2
+.TP
+\(dg \f3\|. \f2name\^\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+If
+.I name\^
+is a function defined with the
+.B function
+.I name\^
+reserved word syntax,
+the function is executed in the current environment
+(as if it had been defined with the
+.IB name ()
+syntax.)
+Otherwise if
+.I name\^
+refers to a file, the
+file is read in its entirety and the commands are
+executed in the current shell environment.
+The search path
+specified by
+.B
+.SM PATH
+is used to find the directory containing the file.
+If any arguments
+.I arg\^
+are given,
+they become the positional parameters while processing
+the
+.B .
+command and the original positional parameters are restored upon completion.
+Otherwise the positional parameters are unchanged.
+The exit status is the exit status of the last command executed.
+.TP
+\(dg\(dg \f3alias\fP \*(OK \f3\-ptx\fP \*(CK \*(OK \f2name\fP\*(OK \f3=\fP\f2value\^\fP \*(CK \*(CK .\|.\|.
+.B alias\^
+with no arguments prints the list of aliases
+in the form
+.I name=value\^
+on standard output.
+The
+.B \-p
+option
+causes the word
+.B alias
+to be inserted before each one.
+When one or more arguments are given,
+an
+.I alias\^
+is defined
+for each
+.I name\^
+whose
+.I value\^
+is given.
+A trailing space in
+.I value\^
+causes the next word to be checked for
+alias substitution.
+The obsolete
+.B \-t
+option is used to set and list tracked aliases.
+The value of a tracked alias is the full pathname
+corresponding to the given
+.IR name .
+The value becomes undefined when the value of
+.SM
+.B PATH
+is reset but the alias remains tracked.
+Without the
+.B \-t
+option,
+for each
+.I name\^
+in the argument list
+for which no
+.I value\^
+is given, the name
+and value of the alias is printed.
+The obsolete
+.B \-x
+option has no effect.
+The exit status is non-zero if a
+.I name\^
+is given, but no value, and no alias has been defined for the
+.IR name\^ .
+.TP
+\f3bg\fP \*(OK \f2job\^\fP.\|.\|. \*(CK
+This command is only on systems that support job control.
+Puts each specified
+.I job\^
+into the background.
+The current job is put in the background
+if
+.I job\^
+is not specified.
+See
+.I Jobs
+for a description of the format of
+.IR job .
+.TP
+\(dg \f3break\fP \*(OK \f2n\^\fP \*(CK
+Exit from the enclosing
+.BR for\^ ,
+.BR while\^ ,
+.BR until\^ ,
+or
+.B select\^
+loop, if any.
+If
+.I n\^
+is specified, then break
+.I n\^
+levels.
+.TP
+\f3builtin\fP \*(OK \f3\-ds\fP \*(CK \*(OK \f3\-f\fP \f2file\^\fP \*(CK \*(OK \f2name\^\fP .\|.\|. \*(CK
+If
+.I name\^
+is not specified,
+and no
+.B \-f
+option is specified,
+the built-ins are printed on standard output.
+The
+.B \-s
+option prints only the special built-ins.
+Otherwise, each
+.I name\^
+represents the pathname whose basename is the name of the built-in.
+The entry point function name is determined by prepending
+.B b_
+to the built-in name.
+The ISO C/C++ prototype is
+\f3b_\fP\f2mycommand\fP\f3(int\fP \f2argc\fP, \f3char *\fP\f2argv\fP\f3[]\fP, \f3void *\fP\f2context\fP\f3)\fP
+for the builtin command
+.I mycommand\^
+where
+.I argv\^
+is array an of
+.I argc\^
+elements and context is an optional pointer to a
+.B Shell_t
+structure as described in
+.BR <ast/shell.h> .
+.sp .5
+Special built-ins cannot be bound to a pathname or deleted.
+The
+.B \-d
+option deletes each of the given built-ins.
+On systems that support dynamic loading, the
+.B \-f
+option names a shared library containing the code for built-ins.
+The shared library prefix and/or suffix, which depend on the system,
+can be omitted.
+Once a library is loaded, its symbols become available
+for subsequent invocations of
+.BR builtin .
+Multiple libraries can be specified with separate invocations
+of the
+.B builtin
+command.
+Libraries are searched in the reverse order in which they are specified.
+When a library is loaded, it looks for a function in the library
+whose name is
+.B lib_init()
+and invokes this function with an argument of
+.BR 0 .
+.TP
+.PD 0
+\f3cd\fP \*(OK \f3\-LP\fP \*(CK \*(OK \f2arg\^\fP \*(CK
+.TP
+\f3cd\fP \*(OK \f3\-LP\fP \*(CK \f2old\^\fP \f2new\^\fP
+.PD
+This command can be in either of two forms.
+In the first form it
+changes the current directory to
+.IR arg .
+If
+.I arg\^
+is
+.B \-
+the directory is changed to the previous
+directory.
+The shell
+variable
+.B
+.SM HOME
+is the default
+.IR arg .
+The variable
+.SM
+.B PWD
+is set to the current directory.
+The shell variable
+.B
+.SM CDPATH
+defines the search path for
+the directory containing
+.IR arg .
+Alternative directory names are separated by
+a colon
+.RB ( : ).
+The default path is
+.B <null>
+(specifying the current directory).
+Note that the current directory is specified by a null path name,
+which can appear immediately after the equal sign
+or between the colon delimiters anywhere else in the path list.
+If
+.I arg
+begins with a \f3/\fP then the search path
+is not used.
+Otherwise, each directory in the path is
+searched for
+.IR arg .
+.sp .5
+The second form of
+.B cd
+substitutes the string
+.I new
+for the string
+.I old
+in the current directory name,
+.SM
+.BR PWD ,
+and tries to change to this new directory.
+.sp .5
+By default, symbolic link names are treated literally when
+finding the directory name.
+This is equivalent to the
+.B \-L
+option.
+The
+.B \-P
+option causes
+symbolic links to be resolved when determining the directory.
+The last instance of
+.B \-L
+or
+.B \-P
+on the command line
+determines which method is used.
+.sp .5
+The
+.B cd\^
+command may not be executed by
+.if \nZ=0 .B rsh\^.
+.if \nZ=1 .B rksh\^.
+.if \nZ=1 .B rksh93\^.
+.TP
+\f3command\fP \*(OK \f3\-pvxV\fP \*(CK \f2name\^\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+Without the
+.B \-v
+or
+.B \-V
+options,
+.B command
+executes
+.I name\^
+with the arguments given by
+.IR arg .
+The
+.B \-p
+option causes
+a default path to be searched
+rather than the one defined by the value of
+.SM
+.BR PATH .
+Functions will not be searched for when finding
+.IR name .
+In addition, if
+.I name\^
+refers to a special built-in,
+none of the special properties associated with the leading
+daggers will be honored.
+(For example, the predefined alias
+.B "redirect=\(fmcommand exec\(fm"
+prevents a script from terminating when an invalid
+redirection is given.)
+With the
+.B \-x
+option,
+if command execution would result in a failure because
+there are too many arguments, errno
+.SM
+.BR E2BIG ,
+the shell will invoke command
+.I name\^
+multiple times with a subset of the arguments on each invocation.
+Arguments that occur prior to the first word that
+expands to multiple arguments and after the last word
+that expands to multiple arguments will be passed on each invocation.
+The exit status will be the maximum invocation exit status.
+With the
+.B \-v
+option,
+.B command
+is equivalent to the built-in
+.B whence
+command described below.
+The
+.B \-V
+option causes
+.B command
+to act like
+.BR "whence \-v" .
+.TP
+\(dg \f3continue\fP \*(OK \f2n\^\fP \*(CK
+Resume the next iteration of the enclosing
+.BR for\^ ,
+.BR while\^ ,
+.BR until\^ ,
+or
+.B select\^
+loop.
+If
+.I n\^
+is specified, then resume at the
+.IR n -th
+enclosing loop.
+.TP
+\f3disown\fP \*(OK \f2job\^\fP.\|.\|. \*(CK
+Causes the shell not to send a HUP signal to
+each given
+.IR job ,
+or all active jobs if
+.I job
+is omitted,
+when a login shell terminates.
+.TP
+\f3echo\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+When the first
+.I arg\^
+does not begin with a \-, and
+none of the arguments contain a \e,
+then
+.B echo
+prints each of its arguments separated by a space
+and terminated by a new-line.
+Otherwise, the behavior of
+.B echo
+is system dependent
+and
+.B print
+or
+.B printf
+described below should be used.
+See
+.IR echo (1)
+for usage and description.
+.TP
+\(dg\(dg \f3enum\fP \*(OK \f3\-i\fP \*(CK \f2type\^\fP\*(OK=(\f2value\^\fP .\|.\|.) \*(CK
+Creates a declaration command named \f2type\^\fP that is an
+integer type that allows one of the specified \f2value\fPs as
+enumeration names. If \f3=(\fP\f2value\^\ .\|.\|.\|\fP\f3)\fP is
+omitted, then \f2type\^\fP must be an indexed array variable with at
+least two elements and the values are taken from this array variable.
+If
+.B -i
+is specified the values are case insensitive.
+.TP
+\(dg \f3eval\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+The arguments are read as input
+to the shell
+and the resulting command(s) executed.
+.TP
+\(dg \f3exec\fP \*(OK \f3\-c\fP \*(CK \*(OK \f3\-a\fP \f2name\^\fP \*(CK \*(OK \f2arg\^\fP .\|.\|. \*(CK
+If
+.I arg\^
+is given,
+the command specified by
+the arguments is executed in place of this shell
+without creating a new process.
+The
+.B \-c
+option causes the environment to be cleared before applying
+variable assignments associated with the
+.B exec
+invocation.
+The
+.B \-a
+option
+causes
+.I name\^
+rather than the first
+.IR arg ,
+to become
+.B argv[0]
+for the new process.
+Input/output arguments may appear and
+affect the current process.
+If
+.I arg\^
+is not given,
+the effect of this command is to
+modify file descriptors
+as prescribed by the input/output redirection list.
+In this case,
+any file descriptor numbers greater than 2 that are
+opened with this mechanism are closed when invoking
+another program.
+.TP
+\(dg \f3exit\fP \*(OK \f2n\^\fP \*(CK
+Causes the shell to exit
+with the exit status specified by
+.IR n .
+The value will be the least significant 8 bits of the specified status.
+If
+.I n\^
+is omitted, then the exit status is that of the last command executed.
+An end-of-file will also cause the shell to exit
+except for a
+shell which has the
+.B ignoreeof
+option (see
+.B set
+below) turned on.
+.TP
+\(dg\(dg \f3export\fP \*(OK \f3\-p\fP \*(CK \*(OK \f2name\^\fP\*(OK\f3=\fP\f2value\^\fP\*(CK \*(CK .\|.\|.
+If
+.I name\^
+is not given,
+the names and values of each variable with
+the export attribute are printed with the values
+quoted in a manner that allows them to be re-input.
+The
+.B export
+command is the same as
+.B typeset \-x
+except that if you use
+.B export
+within a function, no local
+variable is created.
+The
+.B \-p
+option
+causes the word
+.B export
+to be inserted before each one.
+Otherwise, the given
+.IR name s
+are marked for automatic
+export to the
+.I environment\^
+of subsequently-executed commands.
+.TP
+\f3false\fP
+Does nothing, and exits 1. Used with
+.B until
+for infinite loops.
+.TP
+\f3fg\fP \*(OK \f2job\^\fP.\|.\|. \*(CK
+This command is only on systems that support job control.
+Each
+.I job\^
+specified is brought to the foreground and waited for in
+the specified order.
+Otherwise, the current job is
+brought into the foreground.
+See
+.I Jobs
+for a description of the format of
+.IR job .
+.TP
+\f3getconf\fP \*(OK \f2name\^\fP \*(OK \f2pathname\^\fP \*(CK \*(CK
+Prints the current value of the configuration parameter given by
+.IR name .
+The configuration parameters are defined by the IEEE POSIX 1003.1
+and IEEE POSIX 1003.2 standards.
+(See
+.IR pathconf (2)
+and
+.IR sysconf (2).)
+The
+.I pathname
+argument is required for parameters whose value depends on
+the location in the file system.
+If no arguments are given,
+.B getconf
+prints the names and values of the current configuration
+parameters.
+The pathname
+.B /
+is used for each of the parameters that requires
+.IR pathname .
+.TP
+\f3getopts\fP \*(OK \f3\ \-a\fP \f2name\^\fP \*(CK \f2optstring vname\^\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+Checks
+.I arg
+for legal options.
+If
+.I arg
+is omitted,
+the positional parameters are used.
+An option argument begins with a
+.B +
+or a
+.BR \- .
+An option not beginning with
+.B +
+or
+.B \-
+or the argument
+.B \-\|\-
+ends the options.
+Options beginning with
+.B +
+are only recognized when
+.I optstring\^
+begins with a
+.BR + .
+.I optstring\^
+contains the letters that
+.B getopts
+recognizes.
+If a letter is followed by a
+.BR : ,
+that option is expected to have an argument.
+The options can be separated from the argument by blanks.
+The option
+.B \-?
+causes
+.B getopts
+to generate a usage message on standard error.
+The
+.B \-a
+argument can be used to specify the name to use for the
+usage message, which defaults to
+.BR $0 .
+.sp .5
+.B
+getopts
+places the next option letter it finds inside variable
+.I vname\^
+each time it is invoked.
+The option letter will be prepended with a
+.B +
+when
+.I arg
+begins with a
+.BR + .
+The index of the next
+.I arg
+is stored in
+.SM
+.BR OPTIND .
+The option argument,
+if any,
+gets stored in
+.SM
+.BR OPTARG .
+.sp .5
+A leading
+.B :
+in
+.I optstring
+causes
+.B getopts
+to store the letter of an invalid
+option in
+.SM
+.BR OPTARG ,
+and to set
+.I vname
+to
+.B ?
+for an unknown option and to
+.B :
+when a required option argument is missing.
+Otherwise,
+.B getopts
+prints an error message.
+The exit status is non-zero when there are no more options.
+.sp .5
+There is no way to specify any of the options
+.BR : ,
+.BR + ,
+.BR \- ,
+.BR ? ,
+.BR [ ,
+and
+.BR ] .
+The option
+.B #
+can only be specified as the first option.
+.TP
+.PD 0
+\f3hist\fP \*(OK \f3\-e\fP \f2ename\^\fP \ \*(CK \*(OK \f3\-nlr\^\fP \*(CK \*(OK \f2first\^\fP \*(OK \f2last\^\fP \*(CK \*(CK
+.TP
+\f3hist \-s \fP \*(OK \f2old\fP\f3\=\fP\f2new\^\fP \*(CK \*(OK \f2command\^\fP \*(CK
+.PD
+In the first form,
+a range of commands from
+.I first\^
+to
+.I last\^
+is selected from the last
+.SM
+.B HISTSIZE
+commands that were typed at the terminal.
+The arguments
+.I first\^
+and
+.I last\^
+may be specified as a number or as a string.
+A string is used to locate the most recent command starting with
+the given string.
+A negative number is used as an offset to the current command number.
+If the
+.B \-l
+option
+is selected,
+the commands are listed on standard output.
+Otherwise, the editor program
+.I ename\^
+is invoked on a file containing these
+keyboard commands.
+If
+.I ename\^
+is not supplied, then the value of the variable
+.SM
+.B HISTEDIT
+is used.
+If
+.SM
+.B HISTEDIT
+is not set, then
+.SM
+.B FCEDIT
+(default
+.BR /bin/ed\^ )
+is used as the editor.
+When editing is complete, the edited command(s)
+is executed if the changes have been saved.
+If
+.I last\^
+is not specified,
+then it will be set to
+.IR first .
+If
+.I first\^
+is not specified,
+the default is the previous command
+for editing and \-16 for listing.
+The option
+.B \-r
+reverses the order of the commands and
+the option
+.B \-n
+suppresses command numbers when listing.
+In the second form,
+.I command\^
+is interpreted as
+.I first\^
+described above
+and defaults to the last command executed.
+The resulting command is executed
+after the optional substitution
+\f2old\^\fP\f3=\fP\f2new\^\fP
+is performed.
+.TP
+\f3jobs\fP \*(OK \f3\-lnp\^\fP \*(CK \*(OK \f2job\^\fP \.\|.\|. \*(CK
+Lists information about each given job; or all active jobs if
+.I job
+is omitted.
+The
+.B \-l
+option lists process ids in addition to the normal information.
+The
+.B \-n
+option only displays jobs that have stopped or exited since last
+notified.
+The
+.B \-p
+option causes only the process group to be listed.
+See
+.I Jobs
+for a description of the format of
+.IR job .
+.TP
+.PD 0
+\f3kill\fP \*(OK \f3\-s\fP \f2signame\^\fP \*(CK \f2job\^\fP .\|.\|.
+.TP
+.PD 0
+\f3kill\fP \*(OK \f3\-n\fP \f2signum\^\fP \*(CK \f2job\^\fP .\|.\|.
+.TP
+\f3kill\fP \f3\-l\fP \*(OK \f2sig\^\fP .\|.\|. \*(CK
+.PD
+Sends either the TERM (terminate) signal or the
+specified signal to the specified jobs or processes.
+Signals are either given by number with the
+.B \-n
+option or by name with the
+.B \-s
+option
+(as given in
+.BR <signal.h> ,
+stripped of the prefix ``SIG'' with
+the exception that SIGCLD is named CHLD).
+For backward compatibility, the
+.B n
+and
+.B s
+can be omitted and the number or name placed immediately
+after the
+.BR \- .
+If the signal being sent is TERM (terminate) or HUP (hangup),
+then the job or process will be sent a CONT (continue) signal
+if it is stopped.
+The argument
+.I job\^
+can be the process id of a process that is not a member of one of the
+active jobs.
+See
+.I Jobs
+for a description of the format of
+.IR job .
+In the third form,
+.BR "kill \-l" ,
+if
+.I sig\^
+is not specified,
+the signal names are listed.
+Otherwise, for each
+.I sig\^
+that is a name, the corresponding signal number is listed.
+For each
+.I sig\^
+that is a number, the signal name corresponding to the
+least significant 8 bits of
+.I sig\^
+is listed.
+.TP
+\f3let\fP \f2arg\^\fP .\|.\|.
+Each
+.I arg
+is a separate
+.I "arithmetic expression"
+to be evaluated.
+.B let
+only recognizes octal constants starting with
+.B 0
+when the
+.B set
+option
+.B letoctal
+is on.
+See
+.I "Arithmetic Evaluation"
+above, for a description of arithmetic expression evaluation.
+.sp .5
+The exit status is
+0 if the value of the last expression
+is non-zero, and 1 otherwise.
+.TP
+\(dg \f3newgrp\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+Equivalent to
+.BI "exec /bin/newgrp" " arg\^"
+\&.\|.\|.\^.
+.TP
+\f3print\fP \*(OK \f3\-CRenprsv\^\fP \*(CK \*(OK \f3\-u\fP \f2unit\^\fP\*(CK \*(OK \f3\-f\fP \f2format\^\fP \*(CK \*(OK \f2arg\^\fP .\|.\|. \*(CK
+With no options or with option
+.B \-
+or
+.BR \-\|\- ,
+each
+.I arg
+is printed
+on standard output.
+The
+.B \-f
+option causes the arguments to be printed as
+described by
+.BR printf .
+In this case, any
+.BR e ,
+.BR n ,
+.BR r ,
+.B R
+options are ignored.
+Otherwise,
+unless the
+.BR \-C ,
+.BR \-R ,
+.BR \-r ,
+or
+.B \-v
+are specified, the following
+escape conventions will be applied:
+.RS
+.PD 0
+.TP
+.B \ea
+The alert character (ascii
+.BR 07 ).
+.TP
+.B \eb
+The backspace character (ascii
+.BR 010 ).
+.TP
+.B \ec
+Causes
+.B print
+to end without processing more arguments and
+not adding a new-line.
+.TP
+.B \ef
+The formfeed character (ascii
+.BR 014 ).
+.TP
+.B \en
+The new-line character (ascii
+.BR 012 ).
+.TP
+.B \er
+The carriage return character (ascii
+.BR 015 ).
+.TP
+.B \et
+The tab character (ascii
+.BR 011 ).
+.TP
+.B \ev
+The vertical tab character (ascii
+.BR 013 ).
+.TP
+.B \eE
+The escape character (ascii
+.BR 033 ).
+.TP
+.B \e\e
+The backslash character \e.
+.TP
+.BI \e0 x
+The character defined by the 1, 2, or 3-digit octal
+string given by \fIx\fP.
+.PD
+.PP
+The
+.B \-R
+option will print all subsequent arguments and options
+other than
+.BR \-n .
+The
+.B \-e
+causes the above escape conventions to be applied.
+This is the default behavior.
+It reverses the effect of an earlier
+.BR \-r .
+The
+.B \-p
+option causes the
+arguments to be written onto the pipe
+of the process spawned with
+.B \(bv&
+instead of standard output.
+The
+.B \-v
+option treats each
+.I arg\^
+as a variable name and writes the value in
+the
+.B printf
+.B %B
+format.
+The
+.B \-C
+option treats each
+.I arg\^
+as a variable name and writes the value in
+the
+.B printf
+.B %#B
+format.
+The
+.B \-s
+option causes the
+arguments to be written onto the history file
+instead of standard output.
+The
+.B \-u
+option can be used to specify a one digit
+file descriptor unit number
+.I unit\^
+on which the
+output will be placed.
+The default is 1.
+If the option
+.B \-n
+is used, no
+.B new-line\^
+is added to the output.
+.RE
+.TP
+\f3printf\fP \f2format\^\fP \*(OK \f2arg\^\fP .\|.\|. \*(CK
+The arguments
+.I arg\^
+are printed on standard output
+in accordance with the ANSI-C
+formatting rules associated with the format string
+.IR format .
+If the number of arguments exceeds the number of
+format specifications, the
+.B format\^
+string is reused to format remaining arguments.
+The following extensions can also be used:
+.RS
+.PD 0
+.TP
+.B %b
+A
+.B %b
+format can be used instead of
+.B %s
+to cause escape sequences in the corresponding
+.I arg\^
+to be expanded as described in
+.BR print.
+.TP
+.B %B
+A
+.B %B
+option causes each of the arguments to be treated
+as variable names and the binary value of variable
+will be printed.
+The alternate flag
+.B #
+causes a compound variable to be output on a single line.
+This is most useful for compound variables and variables whose attribute
+is
+.BR \-b .
+.TP
+.B %H
+A
+.B %H
+format can be used instead of
+.B %s
+to cause characters in
+.I arg\^
+that are special in HTML and XML
+to be output as their entity name.
+The alternate flag
+.B #
+formats the output for use as a URI.
+.TP
+.B %P
+A
+.B %P
+format can be used instead of
+.B %s
+to cause
+.I arg\^
+to be interpreted as an extended regular
+expression and be printed as a shell pattern.
+.TP
+.B %R
+A
+.B %R
+format can be used instead of
+.B %s
+to cause
+.I arg\^
+to be interpreted as a shell pattern
+and to be printed as an extended regular expression.
+.TP
+.B %q
+A
+.B %q
+format can be used instead of
+.B %s
+to cause the resulting string to be quoted in a manner than can
+be reinput to the shell.
+When
+.B q
+is preceded by the alternative format specifier,
+.BR # ,
+The string is quoted in manner suitable as a field in a
+.B .csv
+format file.
+.TP
+.BI %( date-format )T
+A
+.BI %( date-format )T
+format can be use to treat an argument as a date/time string
+and to format the date/time according to the
+.I date-format\^
+as defined for the
+.BR date (1)
+command.
+.TP
+.B %Z
+A
+.B %Z
+format will output a byte whose value is 0.
+.TP
+.B %d
+The precision field of the
+.B %d
+format can be followed by a
+.B .
+and the output base.
+In this case, the
+.B #
+flag character causes
+.IB base #
+to be prepended.
+.TP
+.B #
+The
+.B #
+flag, when used with the
+.B %d
+format without an output base,
+displays the output in powers of 1000 indicated by one of the following suffixes:
+.BR "k M G T P E" ,
+and when used with the
+.B %i
+format displays the output in powers of 1024 indicated by one of the following suffixes:
+.BR "Ki Mi Gi Ti Pi Ei" .
+.TP
+.B =
+The
+.B =
+flag centers the output within the specified field width.
+.TP
+.B L
+The
+.B L
+flag, when used with the
+.B %c
+or
+.B %s
+formats, treats precision as character width instead of byte count.
+.TP
+.B ,
+The
+.B ,
+flag, when used with the
+.B %d
+or
+.B %f
+formats, separates groups of digits with the grouping delimiter
+.RB ( ,
+on groups of 3 in the C locale.)
+.PD
+.PP
+.RE
+.TP
+\f3pwd\fP \*(OK \f3\-LP\fP \*(CK
+Outputs the value of the current working
+directory.
+The
+.B \-L
+option is the default; it prints the logical name of the current directory.
+If the
+.B \-P
+option is given,
+all symbolic links are resolved from the name.
+The last instance of
+.B \-L
+or
+.B \-P
+on the command line
+determines which method is used.
+.TP
+\f3read\fP \*(OK \f3\-ACSprsv\^\fP \*(CK \*(OK \f3\-d\fP \f2delim\^\fP\*(CK \*(OK \f3\-n\fP \f2n\^\fP\*(CK \*(OK \*(OK \f3\-N\fP \f2n\^\fP\*(CK \*(OK \*(OK \f3\-t\fP \f2timeout\^\fP\*(CK \*(OK \f3\-u\fP \f2unit\^\fP\*(CK \*(OK \f2vname\f3?\f2prompt\^\f1 \*(CK \*(OK \f2vname\^\fP .\|.\|. \*(CK
+The shell input mechanism.
+One line is read and
+is broken up into fields using the characters in
+.B
+.SM IFS
+as separators.
+The escape character,
+.BR \e ,
+is used to remove any special meaning for the next
+character and for line continuation.
+The
+.B \-d
+option
+causes the read to continue to the first character of
+.I delim\^
+rather than new-line.
+The
+.B \-n
+option causes at most
+.I n\^
+bytes to read rather a full line
+but will return when reading from a slow device
+as soon as any characters have been read.
+The
+.B \-N
+option causes exactly
+.I n\^
+to be read unless an end-of-file has been encountered or
+the read times out because of the
+.B \-t
+option.
+In raw mode,
+.B \-r,
+the
+.B \e
+character is not treated specially.
+The first
+field is assigned to the first
+.IR vname ,
+the second field
+to the second
+.IR vname ,
+etc., with leftover fields assigned to the last
+.IR vname .
+When
+.IR vname
+has the binary attribute and
+.B \-n
+or
+.B \-N
+is specified, the bytes that are read are stored directly
+into the variable.
+If the
+.B \-v
+is specified, then the value of the first
+.I vname\^
+will be used as a default value when reading from a terminal device.
+The
+.B \-A
+option causes the variable
+.I vname\^
+to be unset and each field that is read to be stored in
+successive elements of the indexed array
+.IR vname.
+The
+.B \-C
+option causes the variable
+.I vname\^
+to be read as a compound variable. Blanks will be ignored when
+finding the beginning open parenthesis.
+The \-S
+option causes the line to be treated like a record in a
+.B .csv
+format file so that double quotes can be used to allow the delimiter
+character and the new-line character to appear within a field.
+The
+.B \-p
+option causes the input line
+to be taken from the input pipe
+of a process spawned by the shell
+using
+.BR \(bv& .
+If the
+.B \-s
+option is present,
+the input will be saved as a command in the history file.
+The option
+.B \-u
+can be used to specify a one digit file
+descriptor unit
+.I unit\^
+to read from.
+The file descriptor can be opened with the
+.B exec\^
+special built-in command.
+The default value of unit
+.I n\^
+is 0.
+The option
+.B \-t
+is used to specify a timeout in
+seconds when reading from a terminal or pipe.
+If
+.I vname\^
+is omitted, then
+.SM
+.B REPLY
+is used as the default
+.IR vname .
+An end-of-file with the
+.B \-p
+option causes cleanup for this process
+so that another can be spawned.
+If the first argument contains a
+.BR ? ,
+the remainder of this word is used as a
+.I prompt\^
+on standard error
+when the shell is interactive.
+The exit status is 0 unless an end-of-file is encountered
+or
+.B read
+has timed out.
+.TP
+\(dg\(dg \f3readonly\fP \*(OK \f3\-p\fP \*(CK \*(OK \f2vname\fP\*(OK\f3=\fP\f2value\^\fP\*(CK \*(CK .\|.\|.
+If
+.I vname\^
+is not given,
+the names and values of each variable with
+the readonly attribute is printed with the values
+quoted in a manner that allows them to be re-inputted.
+The
+.B \-p
+option
+causes the word
+.B readonly
+to be inserted before each one.
+Otherwise, the given
+.IR vname s
+are marked
+readonly and these
+names cannot be changed
+by subsequent assignment.
+When defining a type, if the value of a readonly sub-variable is not defined
+the value is required when creating each instance.
+.TP
+\(dg \f3return\fP \*(OK \f2n\^\fP \*(CK
+Causes a shell
+.I function
+or
+\f3\|.\fP
+script to return
+to the invoking script
+with the exit status specified by
+.IR n .
+The value will be the least significant 8 bits of the specified status.
+If
+.I n\^
+is omitted, then the return status is that of the last command executed.
+If
+.B return
+is invoked while not in a
+.I function
+or a
+\f3\|.\fP
+script,
+then it behaves the same as
+.BR exit .
+.TP
+\(dg \f3set\fP \*(OK \f3\(+-BCGabefhkmnoprstuvx\fP \*(CK \*(OK \f3\(+-o\fP \*(OK \f2option\^\fP \*(CK \*(CK .\|.\|. \*(OK \f3\(+-A\fP \f2vname\^\fP \*(CK \*(OK \f2arg\^\fP .\|.\|. \*(CK
+The options for this command have meaning as follows:
+.RS
+.PD 0
+.TP 8
+.B \-A
+Array assignment.
+Unset the variable
+.I vname
+and assign values sequentially from the
+.I arg\^
+list.
+If
+.B +A
+is used, the variable
+.I vname
+is not unset first.
+.TP 8
+.B \-B
+Enable brace pattern field generation.
+This is the default behavior.
+.TP 8
+.B \-B
+Enable brace group expansion. On by default.
+.TP 8
+.B \-C
+Prevents redirection
+.B >
+from truncating existing files.
+Files that are created are opened with the O_EXCL mode.
+Requires
+.B >\(bv
+to truncate a file when turned on.
+.TP 8
+.B \-G
+Causes the pattern
+.B \(**\(**
+by itself to match files and zero or more directories and sub-directories
+when used for file name generation.
+If followed by a
+.B /
+only directories and sub-directories are matched.
+.TP 8
+.B \-a
+All subsequent variables that are defined are automatically exported.
+.TP 8
+.B \-b
+Prints job completion messages as soon as a background job changes
+state rather than waiting for the next prompt.
+.TP 8
+.B \-e
+Unless contained in a
+.B \(bv\(bv
+or
+.B &&
+command, or the command following an
+.B if
+.B while
+or
+.B until
+command or in the pipeline following
+.BR ! ,
+if a command has a non-zero exit status,
+execute the
+.SM
+.B ERR
+trap, if set,
+and exit.
+This mode is disabled while reading profiles.
+.TP 8
+.B \-f
+Disables file name generation.
+.TP 8
+.B \-h
+Each command
+becomes a tracked alias when first encountered.
+.TP 8
+.B \-k
+(Obsolete). All variable assignment arguments are placed in the environment for a command,
+not just those that precede the command name.
+.TP 8
+.B \-m
+Background jobs will run in a separate process group
+and a line will print upon completion.
+The exit status of background jobs is reported in a completion message.
+On systems with job control,
+this option is turned on automatically for
+interactive shells.
+.TP 8
+.B \-n
+Read commands and check them for syntax errors, but do not execute them.
+Ignored for interactive shells.
+.TP 8
+.B \-o
+The following argument can be one of the following option names:
+.RS
+.TP 8
+.B allexport
+Same as
+.BR \-a .
+.TP 8
+.B errexit
+Same as
+.BR \-e .
+.TP 8
+.B bgnice
+All background jobs are run at a lower priority.
+This is the default mode.
+.TP 8
+.B braceexpand
+Same as
+.BR \-B .
+.TP 8
+.B emacs
+Puts you in an
+.I emacs
+style in-line editor for command entry.
+.TP 8
+.B globstar
+Same as
+.BR \-G .
+.TP 8
+.B gmacs
+Puts you in a
+.I gmacs
+style in-line editor for command entry.
+.TP 8
+.B ignoreeof
+The shell will not exit on end-of-file.
+The command
+.B exit
+must be used.
+.TP 8
+.B keyword
+Same as
+.BR \-k .
+.TP 8
+.B letoctal
+The
+.B let
+command allows octal constants starting with
+.BR 0 .
+.TP 8
+.B markdirs
+All directory names resulting from file name generation have a trailing
+.B /
+appended.
+.TP 8
+.B monitor
+Same as
+.BR \-m .
+.TP 8
+.B multiline
+The built-in editors will use multiple lines on the screen for lines
+that are longer than the width of the screen. This may not work
+for all terminals.
+.TP 8
+.B noclobber
+Same as
+.BR \-C .
+.TP 8
+.B noexec
+Same as
+.BR \-n .
+.TP 8
+.B noglob
+Same as
+.BR \-f .
+.TP 8
+.B nolog
+Do not save function definitions in the history file.
+.TP 8
+.B notify
+Same as
+.BR \-b .
+.TP 8
+.B nounset
+Same as
+.BR \-u .
+.TP 8
+.B pipefail
+A pipeline will not complete until all components
+of the pipeline have completed, and the return value
+will be the value of the last non-zero command
+to fail or zero if no command has failed.
+.TP 8
+.B showme
+When enabled, simple commands or pipelines preceded by a semicolon
+.RB ( ; )
+will be displayed as if the
+.B xtrace
+option were enabled but will not be executed.
+Otherwise, the leading
+.B ;
+will be ignored.
+.TP 8
+.B privileged
+Same as
+.BR \-p .
+.TP 8
+.B verbose
+Same as
+.BR \-v .
+.TP 8
+.B trackall
+Same as
+.BR \-h .
+.TP 8
+.B vi
+Puts you in insert mode of a
+.I vi\^
+style in-line editor
+until you hit the escape character
+.BR 033 .
+This puts you in control mode.
+A return sends the line.
+.TP 8
+.B viraw
+Each character is processed as it is typed
+in
+.I vi\^
+mode.
+.TP 8
+.B xtrace
+Same as
+.BR \-x .
+.PP
+If no option name is supplied, then the current option settings are printed.
+.RE
+.TP 8
+.B \-p
+Disables processing of the
+.B \s-1$HOME\s+1/.profile
+file and uses the file
+.B /etc/suid_profile
+instead of the
+.SM
+.B ENV
+file.
+This mode is on whenever the effective uid (gid)
+is not equal to the real uid (gid).
+Turning this off causes the effective uid and gid to be
+set to the real uid and gid.
+.TP 8
+.B \-r
+Enables the restricted shell. This option cannot be unset
+once set.
+.TP 8
+.B \-s
+Sort the positional parameters lexicographically.
+.TP 8
+.B \-t
+(Obsolete). Exit after reading and executing one command.
+.TP 8
+.B \-u
+Treat unset parameters as an error when substituting.
+.TP 8
+.B \-v
+Print shell input lines as they are read.
+.TP 8
+.B \-x
+Print commands and their arguments as they are executed.
+.TP 8
+.B \-\|\-
+Do not change any of the options; useful in setting
+.B $1
+to a value beginning with
+.BR \- .
+If no arguments follow this option then the positional parameters are unset.
+.PD
+.PP
+As an obsolete feature,
+if the first
+.I arg\^
+is
+.B \-
+then the
+.B \-x
+and
+.B \-v
+options are turned off and the next
+.I arg
+is treated as the first argument.
+Using
+.B \+
+rather than
+.B \-
+causes these options to be turned off.
+These options can also be used upon invocation of the shell.
+The current set of options may be found in
+.BR $\- .
+Unless
+.B \-A
+is specified,
+the remaining arguments are positional
+parameters and are assigned, in order, to
+.B $1
+.B $2
+\&.\|.\|.\^.
+If no arguments are given, then the names and values
+of all variables are printed on the standard output.
+.RE
+.TP
+\(dg \f3shift\fP \*(OK \f2n\^\fP \*(CK
+.br
+The positional parameters from
+\f3$\fP\f2n\fP\f3+1\fP
+\&.\|.\|.
+are renamed
+.B $1
+\&.\|.\|.\^
+, default
+.I n\^
+is 1.
+The parameter
+.I n\^
+can be any arithmetic expression that evaluates to a non-negative
+number less than or equal to
+.BR $# .
+.TP
+\f3sleep\fP \f2seconds\^\fP
+Suspends execution for the number of decimal seconds or fractions of a
+second given by
+.IR seconds .
+.TP
+\(dg \f3trap\fP \*(OK \f3\-p\fP \*(CK \*(OK \f2action\^\fP \*(CK \*(OK \f2sig\^\fP \*(CK .\|.\|.
+The
+.B \-p
+option causes the trap
+action associated with each trap as specified by the arguments
+to be printed with appropriate quoting.
+Otherwise,
+.I action\^
+will be processed as if it were an argument to
+.B eval
+when the shell
+receives signal(s)
+.IR sig .
+Each
+.I sig\^
+can be given as a number or as the name of the signal.
+Trap commands are executed in order of signal number.
+Any attempt to set a trap on a signal that
+was ignored on entry to the current shell
+is ineffective.
+If
+.I action\^
+is omitted and the first
+.I sig\^
+is a number, or if
+.I action\^
+is
+.BR \- ,
+then the trap(s) for each
+.I sig\^
+are reset
+to their original values.
+If
+.I action\^
+is the null
+string then this signal is ignored by the shell and by the commands
+it invokes.
+If
+.I sig\^
+is
+.SM
+.B ERR
+then
+.I action\^
+will be executed whenever a command has a non-zero exit status.
+If
+.I sig\^
+is
+.SM
+.B DEBUG
+then
+.I action\^
+will be executed before each command.
+The variable
+.B .sh.command
+will contain the contents of the current command line
+when
+.I action\^
+is running.
+If the exit status of the trap is
+.B 2
+the command will not be executed.
+If the exit status of the trap is
+.B 255
+and inside a function or a dot script,
+the function or dot script will return.
+If
+.I sig\^
+is
+.B 0
+or
+.SM
+.B EXIT
+and the
+.B trap
+statement is executed inside the body of a function defined with the
+.B function
+.I name\^
+syntax,
+then the command
+.I action\^
+is executed
+after the function completes.
+If
+.I sig\^
+is
+.B 0
+or
+.SM
+.B EXIT
+for a
+.B trap
+set outside any function
+then the command
+.I action\^
+is executed
+on exit from the shell.
+If
+.I sig\^
+is
+.SM
+.BR KEYBD ,
+then
+.I action\^
+will be executed whenever a key is read
+while in
+.BR emacs ,
+.BR gmacs ,
+or
+.B vi\^
+mode.
+The
+.B trap
+command
+with no arguments prints a list
+of commands associated with each signal number.
+.PP
+An
+.B exit
+or
+.B return
+without an argument in a trap action will
+preserve the exit status of the command that invoked the trap.
+.TP
+\f3true\fP
+Does nothing, and exits 0. Used with
+.B while
+for infinite loops.
+.TP
+\(dg\(dg \f3typeset\fP \*(OK \f3\(+-ACHSfblmnprtux\^\fP \*(CK \*(OK \f3\(+-EFLRXZi\*(OK\f2n\^\fP\*(CK \*(CK \*(OK \f3\+-M \*(OK \f2mapname\fP \*(CK \*(CK \*(OK \f3\-T \*(OK \f2tname\fP=(\f2assign_list\fP) \*(CK \*(CK \*(OK \f3\-h \f2str\fP \*(CK \*(OK \f3\-a\fP \*(OK\f2type\fP\*(CK \*(CK \*(OK \f2vname\^\fP\*(OK\f3=\fP\f2value\^\fP \*(CK \^ \*(CK .\|.\|.
+Sets attributes and values for shell variables and functions.
+When invoked inside a function defined with the
+.B function
+.I name\^
+syntax,
+a new instance of the variable
+.I vname\^
+is created,
+and the variable's value and type are restored
+when the function completes.
+The following list of attributes may be specified:
+.RS
+.PD 0
+.TP
+.B \-A
+Declares
+.I vname\^
+to be an associative array.
+Subscripts are strings rather than arithmetic
+expressions.
+.TP
+.B \-C
+causes each
+.I vname\^
+to be a compound variable.
+.I value\^
+names a compound variable it is copied into
+.IR vname .
+Otherwise, it unsets each
+.IR vname .
+.TP
+.B \-a
+Declares
+.I vname\^
+to be an indexed array.
+If
+.I type\^
+is specified, it must be the name of an enumeration
+type created with the
+.B enum
+command and it allows enumeration constants to be used
+as subscripts.
+.TP
+.B \-E
+Declares
+.I vname\^
+to be a double precision floating point number.
+If
+.I n\^
+is non-zero, it defines the number of significant figures
+that are used when expanding
+.IR vname .
+Otherwise, ten significant figures will be used.
+.TP
+.B \-F
+Declares
+.I vname\^
+to be a double precision floating point number.
+If
+.I n\^
+is non-zero, it defines the number of places after the
+decimal point that are used when expanding
+.IR vname .
+Otherwise ten places after the decimal point will be used.
+.TP
+.B \-H
+This option provides UNIX to host-name file mapping on non-UNIX
+machines.
+.TP
+.B \-L
+Left justify and remove leading blanks from
+.IR value .
+If
+.I n\^
+is non-zero, it defines the width
+of the field,
+otherwise it is determined by the width of the value of
+first assignment.
+When the variable is assigned to, it is
+filled on the right with blanks or truncated, if necessary, to
+fit into the field.
+The
+.B \-R
+option is turned off.
+.TP
+.B \-M
+Use the character mapping
+.I mapping\^
+defined by
+.IR wctrans (3).
+such as
+.B tolower
+and
+.B toupper
+when assigning a value to each of the specified operands.
+When
+.I mapping\^
+is specified and there are not operands, all variables
+that use this mapping are written to standard output.
+When
+.I mapping\^
+is omitted and there are no operands, all mapped
+variables are written to standard output.
+.TP
+.B \-R
+Right justify and fill with leading blanks.
+If
+.I n\^
+is non-zero, it defines the width
+of the field,
+otherwise it is determined by the width of the value of
+first assignment.
+The field is left filled with blanks or
+truncated from the end if the
+variable is reassigned.
+The
+.B \-L
+option is turned off.
+.TP
+.B \-S
+When used within the
+.I assign_list\^
+of a type definition, it causes the specified sub-variable
+to be shared by all instances of the type.
+When used inside a function defined with the
+.B function
+reserved word, the specified variables will have
+.I "function static\^"
+scope.
+Otherwise, the variable is unset prior to processing the assignment list.
+.TP
+.B \-T
+If followed by \fItname\^\fP, it
+creates a type named by \fItname\^\fP using the compound
+assignment
+.I assign_list\^
+to \f2tname\fP.
+Otherwise, it writes all the type definitions to standard output.
+.TP
+.B \-X
+Declares
+.I vname\^
+to be a double precision floating point number
+and expands using the
+.B %a
+format of ISO-C99.
+If
+.I n\^
+is non-zero, it defines the number of hex digits after
+the radix point that is used when expanding
+.IR vname .
+The default is 10.
+.TP
+.B \-Z
+Right justify and fill with leading zeros if
+the first non-blank character is a digit and the
+.B \-L
+option has not been set.
+Remove leading zeros if the
+.B \-L
+option is also set.
+If
+.I n\^
+is non-zero, it defines the width
+of the field,
+otherwise it is determined by the width of the value of
+first assignment.
+.TP
+.B \-f
+The names refer to function names rather than
+variable names.
+No assignments can be made and the only other
+valid options are
+.BR \-S ,
+.BR \-t ,
+.B \-u
+and
+.BR \-x .
+The \-S
+can be used with discipline functions defined in a type to indicate that
+the function is static. For a static function, the same method will be used by all instances of that type no matter which instance references it. In addition,
+it can only use value of variables from the original type definition. These
+discipline functions cannot be redefined in any type instance.
+The
+.B \-t
+option
+turns on execution tracing for this function.
+The
+.B \-u
+option
+causes this function to be marked undefined.
+The
+.SM
+.B FPATH
+variable will be searched to find the function definition
+when the function is referenced.
+If no options other than
+.B \-f
+is specified, then the function definition will be displayed
+on standard output. If
+.B +f
+is specified, then a line containing the function name followed
+by a shell comment containing the line number and path name of the
+file where this function was defined, if any, is displayed.
+The exit status can be used to determine whether the function is
+defined so that
+.BI "typeset \-f .sh.math." name\^
+will return 0 when math function
+.I name\^
+is defined and non-zero otherwise.
+.TP
+.B \-b
+The variable can hold any number of bytes of data.
+The data can be text or binary.
+The value is represented by the base64 encoding of the data.
+If
+.B \-Z
+is also specified, the size in bytes of the
+data in the buffer will be determined by the size associated with the
+.BR \-Z .
+If the base64 string assigned results in more data, it will be
+truncated. Otherwise, it will be filled with bytes
+whose value is zero.
+The
+.B printf
+format
+.B %B
+can be used to output the actual data in this buffer instead
+of the base64 encoding of the data.
+.TP
+.B \-h
+Used within type definitions to add information when generating
+information about the sub-variable on the man page.
+It is ignored when used outside of a type definition.
+When used with
+.B \-f
+the information is associated with the corresponding discipline
+function.
+.TP
+.B \-i
+Declares
+.I vname\^
+to be represented internally as integer.
+The right hand side of an assignment is evaluated as an
+arithmetic expression when assigning to an integer.
+If
+.I n\^
+is non-zero, it defines the output arithmetic base,
+otherwise the output base will be ten.
+.TP
+.B \-l
+Used with
+.BR \-i ,
+.B \-E
+or
+.BR \-F ,
+to indicate long integer, or long float.
+Otherwise, all upper-case characters are
+converted to lower-case.
+The upper-case option,
+.BR \-u ,
+is turned off.
+Equivalent to
+.B "\-M tolower" .
+.TP
+.B \-m
+moves or renames the variable.
+The value is the name of a variable whose value will be moved to
+.IR vname\^ .
+The original variable will be unset.
+Cannot be used with any other options.
+.TP
+.B \-n
+Declares
+.I vname\^
+to be a reference to the variable whose name is
+defined by the value of variable
+.IR vname .
+This is usually used to reference a variable inside
+a function whose name has been passed as an argument.
+Cannot be used with any other options.
+.TP
+.B \-p
+The name, attributes and values for the given
+.IR vname s
+are written on standard output in a form that can be
+used as shell input.
+If
+.B +p
+is specified, then the values are not displayed.
+.TP
+.B \-r
+The given
+.IR vname s
+are marked
+readonly and these
+names cannot be changed
+by subsequent assignment.
+.TP
+.B \-t
+Tags the variables.
+Tags are user definable and have no special
+meaning to the shell.
+.TP
+.B \-u
+When given along with
+.BR \-i ,
+specifies unsigned integer.
+Otherwise, all lower-case characters are converted
+to upper-case.
+The lower-case option,
+.BR \-l ,
+is turned off.
+Equivalent to
+.B "\-M toupper" .
+.TP
+.B \-x
+The given
+.IR vname s
+are marked for automatic
+export to the
+.I environment\^
+of subsequently-executed commands.
+Variables whose names contain a \fB\s+2.\s-2\fP
+cannot be exported.
+.PD
+.PP
+The
+.B \-i
+attribute cannot be specified along with
+.BR \-R ,
+.BR \-L ,
+.BR \-Z ,
+or
+.BR \-f .
+.PP
+Using
+.B \+
+rather than
+.B \-
+causes these options to be turned off.
+If no
+.I vname\^
+arguments are given,
+a list of
+.I vnames\^
+(and optionally the
+.IR values\^ )
+of the
+.I variables\^
+is printed.
+(Using
+.B \+
+rather than
+.B \-
+keeps the
+values from being printed.)
+The
+.B \-p
+option causes
+.B typeset
+followed by the option letters
+to be printed before each name
+rather than the names of the options.
+If any option other than
+.B \-p
+is given,
+only those variables
+which have all of the given
+options are printed.
+Otherwise, the
+.IR vname s
+and
+.I attributes\^
+of all
+.I variables\^
+that have attributes
+are printed.
+.RE
+.TP
+\f3ulimit\fP \*(OK \f3\-HSacdfmnpstv\fP \*(CK \*(OK \f2limit\^\fP \*(CK
+Set or display a resource limit.
+The available resource limits are listed below.
+Many systems do not support one or more of these limits.
+The limit for a specified resource is set when
+.I limit\^
+is specified.
+The value of
+.I limit\^
+can be a number in the unit specified below with each resource,
+or the value
+.BR unlimited .
+The
+.B \-H
+and
+.B \-S
+options specify whether the hard limit or the
+soft limit for the given resource is set.
+A hard limit cannot be increased once it is set. A soft
+limit can be increased up to the value of the hard limit.
+If neither the
+.B H
+nor
+.B S
+option is specified, the limit applies to both.
+The current resource limit is printed when
+.I limit\^
+is omitted.
+In this case, the soft limit is printed unless
+.B H
+is specified.
+When more than one resource is specified, then the limit
+name and unit is printed before the value.
+.RS
+.PD 0
+.TP
+.B \-a
+Lists all of the current resource limits.
+.TP
+.B \-c
+The number of 512-byte blocks on the size of core dumps.
+.TP
+.B \-d
+The number of K-bytes on the size of the data area.
+.TP
+.B \-f
+The number of 512-byte blocks on files that can be written by the
+current process or by child processes (files of any size may be read).
+.TP
+.B \-m
+The number of K-bytes on the size of physical memory.
+.TP
+.B \-n
+The number of file descriptors plus 1.
+.TP
+.B \-p
+The number of 512-byte blocks for pipe buffering.
+.TP
+.B \-s
+The number of K-bytes on the size of the stack area.
+.TP
+.B \-t
+The number of CPU seconds to be used by each process.
+.TP
+.B \-v
+The number of K-bytes for virtual memory.
+.PD
+.PP
+If no option is given,
+.B \-f
+is assumed.
+.RE
+.TP
+\f3umask\fP \*(OK \f3\-S\fP \*(CK \*(OK \f2mask\^\fP \*(CK
+The user file-creation mask is set to
+.I mask\^
+(see
+.IR umask (2)).
+.I mask
+can either be an octal number or
+a symbolic value as described in
+.IR chmod (1).
+If a symbolic value is given,
+the new
+umask value is the complement of the result of
+applying
+.I mask\^
+to the complement of the previous umask value.
+If
+.I mask\^
+is omitted, the current value of the mask is printed.
+The
+.B \-S
+option causes the mode to be printed as a symbolic
+value. Otherwise, the
+mask is printed in octal.
+.TP
+\(dg \f3unalias\fP \*(OK \f3\-a\fP \*(CK \f2name\^\fP .\|.\|.
+The aliases
+given by the list of
+.IR name s
+are removed from the alias list.
+The
+.B \-a
+option causes all the
+aliases to be unset.
+.TP
+\(dg\f3unset\fP \*(OK \f3\-fnv\fP \*(CK \f2vname\^\fP .\|.\|.
+The variables given by the list of
+.IR vname s
+are unassigned,
+i.e.,
+except for sub-variables within a type,
+their values and attributes are erased.
+For sub-variables of a type, the values are reset to the
+default value from the type definition.
+Readonly variables cannot be unset.
+If the
+.B \-f
+option
+is set, then the names refer to
+.I function\^
+names.
+If the
+.B \-v
+option is set, then the names refer to
+.I variable\^
+names.
+The
+.B \-f
+option overrides
+.BR \-v .
+If
+.B \-n
+is set and
+.I name\^
+is a name reference, then
+.I name\^
+will be unset rather than the variable
+that it references.
+The default is equivalent to
+.BR \-v .
+Unsetting
+.SM
+.BR LINENO ,
+.SM
+.BR MAILCHECK ,
+.SM
+.BR OPTARG ,
+.SM
+.BR OPTIND ,
+.SM
+.BR RANDOM ,
+.SM
+.BR SECONDS ,
+.SM
+.BR TMOUT ,
+and
+.SM
+.B _
+removes their special meaning even if they are
+subsequently assigned to.
+.TP
+\f3wait\fP \*(OK \f2job\^\fP .\|.\|. \*(CK
+Wait for the specified
+.I job
+and
+report its termination status.
+If
+.I job\^
+is not given, then all currently active child processes are waited for.
+The exit status from this command is that of
+the last process waited for if
+.I job\^
+is specified; otherwise it is zero.
+See
+.I Jobs
+for a description of the format of
+.IR job .
+.TP
+\f3whence\fP \*(OK \f3\-afpv\fP \*(CK \f2name\^\fP .\|.\|.
+For each
+.IR name ,
+indicate how it
+would be interpreted if used as a command name.
+.sp .5
+The
+.B \-v
+option
+produces a more verbose report.
+The
+.B \-f
+option skips the search for functions.
+The
+.B \-p
+option
+does a path search for
+.I name\^
+even if name is an alias, a function, or a reserved word.
+The
+.B \-p
+option turns off the
+.B \-v
+option.
+The
+.B \-a
+option
+is similar to the
+.B \-v
+option but causes
+all interpretations of the given name to be reported.
+.SS Invocation.
+If the shell is invoked by
+.IR exec (2),
+and the first character of argument zero
+.RB ( $0 )
+is
+.BR \- ,
+then the shell is assumed to be a
+.I login
+shell and
+commands are read from
+.B /etc/profile
+and then from either
+.B .profile
+in the current directory or
+.BR \s-1$HOME\s+1/.profile ,
+if either file exists.
+Next, for interactive shells, commands are read from
+the file named by
+performing parameter expansion, command substitution,
+and arithmetic substitution on
+the value of the environment variable
+.SM
+.B ENV
+if the file exists.
+If the
+.B \-s
+option is not present and
+.I arg\^
+and a file by the name of
+.I arg\^
+exists, then it reads and executes this script.
+Otherwise, if the first
+.I arg\^
+does not contain a
+.BR / ,
+a path search is performed on the first
+.I arg\^
+to determine the name of the script to execute.
+The script
+.I arg\^
+must have execute permission and any
+.I setuid
+and
+.I setgid
+settings will be ignored.
+If the script is not found on the path,
+.I arg\^
+is processed as if it named a built-in command or function.
+Commands are then read as described below;
+the following options are interpreted by the shell
+when it is invoked:
+.PP
+.PD 0
+.TP 8
+.B \-D
+Do not execute the script, but output the set of double quoted strings
+preceded by a
+.BR $ .
+These strings are needed for localization of the script to different locales.
+.TP 8
+.B \-E
+Reads the file named by the
+.B ENV
+variable or by
+\s-1$HOME\s+1/\f3.\fPkshrc
+if not defined after the profiles.
+.TP 10
+.BI \-c
+If the
+.B \-c
+option is present, then
+commands are read from the first
+.IR arg .
+Any remaining arguments become
+positional parameters starting at
+.BR 0 .
+.TP
+.B \-s
+If the
+.B \-s
+option is present or if no
+arguments remain,
+then commands are read from the standard input.
+Shell output,
+except for the output of the
+.I Special Commands\^
+listed above,
+is written to
+file descriptor 2.
+.TP
+.B \-i
+If the
+.B \-i
+option is present or
+if the shell input and output are attached to a terminal (as told by
+.IR tcgetattr (2)),
+then this shell is
+.IR interactive .
+In this case \s-1TERM\s+1 is ignored (so that \f3kill 0\fP
+does not kill an interactive shell) and \s-1INTR\s+1 is caught and ignored
+(so that
+.B wait
+is ).
+In all cases, \s-1QUIT\s+1 is ignored by the shell.
+.TP
+.B \-r
+If the
+.B \-r
+option is present, the shell is a restricted shell.
+.TP
+.B \-D
+A list of all double quoted strings that are preceded by a
+.B $
+will be printed on standard output and the shell will exit.
+This set of strings will be subject to language translation
+when the locale is not C or POSIX.
+No commands will be executed.
+.PD
+.TP
+.B \-P
+If
+.B \-P
+or
+.B \-o profile
+is present, the shell is a profile shell (see
+.IR pfexec (1)).
+.TP
+.BI \-R " filename\^"
+The
+.B \-R
+.I filename\^
+option is used
+to generate a cross reference database
+that can be used by a separate utility
+to find definitions and references for variables and commands.
+.PP
+The remaining options and arguments are described under the
+.B set
+command above.
+An optional
+.B \-
+as the first argument is ignored.
+.if \nZ=0 \{.SS Rsh Only.
+.I Rsh\}
+.if \nZ=1 \{.SS Rksh Only.
+.I Rksh\}
+.if \nZ=2 \{.SS Rksh93 Only.
+.I Rksh93\}
+is used to set up login names and execution environments whose
+capabilities are more controlled than those of the standard shell.
+The actions of
+.if \nZ=0 .B rsh\^
+.if \nZ=1 .B rksh\^
+.if \nZ=2 .B rksh93\^
+are identical to those of
+.if \nZ=0 .BR sh\^ ,
+.if \nZ=1 .BR ksh\^ ,
+.if \nZ=2 .BR ksh93\^ ,
+except that the following are disallowed:
+.RS
+.PD 0
+.PP
+Unsetting the restricted option.
+.br
+changing directory (see
+.IR cd (1)),
+.br
+setting or unsetting the value or attributes of
+.SM
+.BR SHELL ,
+.SM
+.BR ENV ,
+.SM
+.BR FPATH ,
+or
+.SM
+.BR PATH\*S,
+.br
+specifying path or
+command names containing
+.BR / ,
+.br
+redirecting output
+.RB ( > ,
+.BR >| ,
+.BR <> ,
+and
+.BR >> ).
+.br
+adding or deleting built-in commands.
+.br
+using
+.B "command -p"
+to invoke a command.
+.PD
+.RE
+.PP
+The restrictions above are enforced
+after \f3.profile\fP and the
+.SM
+.B ENV
+files are interpreted.
+.PP
+When a command to be executed is found to be a shell procedure,
+.if \nZ=0 \{.B rsh\^
+invokes
+.I sh\^\}
+.if \nZ=1 \{.B rksh\^
+invokes
+.I ksh\^\}
+.if \nZ=2 \{.B rksh93\^
+invokes
+.I ksh93\^\}
+to execute it.
+Thus, it is possible to provide to the end-user shell procedures
+that have access to the full power of
+the standard shell,
+while imposing a limited menu of commands;
+this scheme assumes that the end-user does not have write and
+execute permissions in the same directory.
+.PP
+The net effect of these rules is that the writer of the
+.B .profile
+has complete control over user actions,
+by performing guaranteed setup actions
+and leaving the user in an appropriate directory
+(probably
+.I not\^
+the login directory).
+.PP
+The system administrator often sets up a directory
+of commands
+(e.g.,
+.BR /usr/rbin )
+that can be safely invoked by
+.if \nZ=0 .BR rsh .
+.if \nZ=1 .BR rksh .
+.if \nZ=2 .BR rksh93 .
+.SH EXIT STATUS
+Errors detected by the shell, such as syntax errors,
+cause the shell
+to return a non-zero exit status.
+If the shell is being used non-interactively,
+then execution of the shell file is abandoned
+unless the error occurs inside a subshell in which case
+the subshell is abandoned.
+Otherwise, the shell returns the exit status of
+the last command executed (see also the
+.B exit
+command above).
+Run time errors detected by the shell are reported by
+printing the command or function name and the error condition.
+If the line number that the error occurred on is greater than one,
+then the line number is also printed in square brackets
+.RB ( "[]" )
+after the command or function name.
+.SH FILES
+.TP
+.B /etc/profile
+The system wide initialization file, executed for login shells.
+.if \nZ=2 \{.br
+.TP
+.B /etc/ksh.kshrc
+The system wide startup file, executed for interactive shells.
+\}
+.TP
+.B \s-1$HOME\s+1/\f3.\fPprofile
+The personal initialization file, executed for login shells after /etc/profile.
+.TP
+\s-1$HOME\s+1/\f3.\fP.kshrc
+Default personal initialization file, executed for interactive shells when
+.SM
+.B ENV
+is not set.
+.TP
+.B /etc/suid_profile
+Alternative initialization file, executed instead of the personal initialization
+file when the real and effective user or group id do not match.
+.TP
+.B /dev/null
+NULL device
+.SH SEE ALSO
+cat(1),
+cd(1),
+chmod(1),
+cut(1),
+egrep(1),
+echo(1),
+emacs(1),
+env(1),
+fgrep(1),
+gmacs(1),
+grep(1),
+newgrp(1),
+pfexec(1),
+stty(1),
+test(1),
+umask(1),
+vi(1),
+dup(2),
+exec(2),
+fork(2),
+getpwnam(3),
+ioctl(2),
+lseek(2),
+paste(1),
+pathconf(2),
+pipe(2),
+sysconf(2),
+umask(2),
+ulimit(2),
+wait(2),
+wctrans(3),
+rand(3),
+a.out(5),
+profile(5),
+environ(7).
+.PP
+Morris I. Bolsky and David G. Korn,
+.IR "The New KornShell Command and Programming Language" ,
+Prentice Hall, 1995.
+.PP
+.I "POSIX \- Part 2: Shell and Utilities,"
+IEEE Std 1003.2-1992, ISO/IEC 9945-2, IEEE, 1993.
+.SH CAVEATS
+.PP
+If a command
+is executed, and then a command with the same name is
+installed in a directory in the search path before the directory where the
+original command was found, the shell will continue to
+.I exec\^
+the original command.
+Use the
+.B \-t
+option of the
+.B alias\^
+command to correct this situation.
+.PP
+Some very old shell scripts contain a
+.B ^
+as a synonym for the pipe character
+.BR \(bv .
+.PP
+Using the
+.B hist\^
+built-in command within a compound command will cause the whole
+command to disappear from the history file.
+.PP
+The built-in command \f3\|.\fP \f2file\^\fP
+reads the whole file before any commands are executed.
+Therefore,
+.B alias
+and
+.B unalias
+commands in the file
+will not apply to any commands defined in the file.
+.PP
+Traps are not processed while a job is waiting for a foreground process.
+Thus, a trap on
+.B CHLD
+won't be executed until the foreground job terminates.
+.PP
+It is a good idea to leave a space after the comma operator in
+arithmetic expressions to prevent the comma from being interpreted
+as the decimal point character in certain locales.
diff --git a/src/cmd/ksh93/sh.memo b/src/cmd/ksh93/sh.memo
new file mode 100644
index 0000000..9f321e6
--- /dev/null
+++ b/src/cmd/ksh93/sh.memo
@@ -0,0 +1,3248 @@
+. \" use troff -mm
+.nr C 3
+.nr N 2
+.SA 1 \" right justified
+.ND "December 21, 1993"
+.TL "311466-6713" "61175" \" charging case filing case
+Introduction to \f5ksh-93\fP
+.AU "David G. Korn" DGK MH 11267 7975 3C-526B "(research!dgk)"
+.TM 11267-931221-26 \" technical memo + TM numbers
+.MT 1 \" memo type
+.OK Shell "Command interpreter" Language UNIX \" keyword
+.AS 2 \" abstract start for TM
+\f5ksh-93\fP is a
+major rewrite of \f5ksh\fP,
+a program that serves as a command language
+(shell) for the UNIX*
+.FS *
+UNIX is a registered trademark of Novell.
+.FE
+operating system.
+As with \f5ksh\fP, \f5ksh-93\fP
+is essentially compatible with the System V version of the Bourne shell\*(Rf,
+.RS
+S. R. Bourne,
+.I "An Introduction to the UNIX
+Shell,"
+BSTJ - Vol. 57, No. 6 part 2, pages 1947-1972, 1978.
+.RF
+and compatible with previous versions of \f5ksh\fP.
+\f5ksh-93\fP is intended to comply with the IEEE POSIX 1003.2
+and ISO 9945-2\*(Rf
+.RS
+.I "POSIX \- Part 2: Shell and Utilities,"
+IEEE Std 1003.2-1992, ISO/IEC 9945-2, IEEE, 1993.
+.RF
+shell standard.
+In addition to changes in the language required
+by these standards, the primary focus of \f5ksh-93\fP
+is related to shell programming.
+\f5ksh-93\fP provides the programming power of several
+other interpretive languages such as \f5awk\fP\*(Rf,
+.RS
+Al Aho,
+Brian Kernighan,
+and
+Peter Weinberger,
+.I "The AWK Programming Language,"
+Addison Wesley, 1988.
+.RF
+\f5FIT\fP\*(Rf,
+.RS
+Lloyd H. Nakatani and Laurence W. Ruedisueli,
+.I "The FIT Programming Language Primer",
+TM 1126-920301-03, 1992.
+.RF
+\f5PERL\fP\*(Rf,
+.RS
+Larry Wall and Randal Schwartz,
+.I "Programming perl,"
+O'Reilly & Assoc, 1990.
+.RF
+and
+\f5tcl\fP\*(Rf.
+.RS
+John K. Ousterhout,
+.I "Tcl: An Embeddable Command Language",
+Proceedings of the Washington USENIX meeting, pp. 133-146, 1990.
+.RF
+.P
+This memo
+assumes that the reader is already familiar with the Bourne shell.
+It introduces most of the features of \f5ksh-93\fP
+relative to the Bourne shell; both
+as a command language and as a programming language.
+The Appendix contains
+a sample script written in \f5ksh-93\fP.
+.AE \" abstract end
+.H 1 "INTRODUCTION"
+.P
+The term "shell" is used to describe a program that provides
+a command language
+interface.
+Because the UNIX*\
+.FS *
+UNIX is a registered trademark of USL
+.FE
+system shell is a user level program, and not part of
+the operating system itself,
+anyone can write a new shell or modify an existing one.
+This has caused an evolutionary progress
+in the design and implementation of shells,
+with the better ones surviving.
+The most widely available UNIX system shells are the Bourne shell\*(Rf,
+.RS
+S. R. Bourne,
+.IR "An Introduction to the UNIX Shell" ,
+Bell System Technical Journal,
+Vol. 57, No. 6, Part 2, pp. 1947-1972, July 1978.
+.RF
+written by Steve Bourne
+at AT&T Bell Laboratories,
+the C shell\*(Rf,
+.RS
+W. Joy,
+.IR "An Introduction to the C Shell" ,
+Unix Programmer's Manual, Berkeley Software Distribution,
+University of California, Berkeley, 1980.
+.RF
+written by Bill Joy at the University of California, Berkeley,
+and the KornShell language \*(Rf,
+.RS
+Morris Bolsky and David Korn,
+.IR "The KornShell Command and Programming Language" ,
+Prentice Hall, 1989.
+.RF
+written by David Korn
+at AT&T Bell Laboratories.
+The Bourne shell is available on almost all versions of the UNIX
+system.
+The C Shell is available with all Berkeley Software Distribution (BSD) UNIX systems and on many other systems.
+The KornShell
+is available on System V Release 4 systems.
+In addition, it is available on many other systems.
+The source for the KornShell language is available from the AT&T Toolchest,
+an electronic software distribution system.
+It runs on all known versions of the UNIX system and
+on many UNIX system look-alikes.
+.P
+There have been several articles comparing the UNIX system shells.
+Jason Levitt\*(Rf
+.RS
+Jason Levitt,
+.IR "The Korn Shell: An Emerging Standard" ,
+UNIX/World, pp. 74-81, September 1986.
+.RF
+highlights some of the new features
+introduced by the KornShell language.
+Rich Bilancia\*(Rf
+.RS
+Rich Bilancia,
+.IR "Proficiency and Power are Yours With the Korn Shell" ,
+UNIX/World, pp. 103-107, September 1987.
+.RF
+explains some of the advantages of using the KornShell language.
+John Sebes\*(Rf
+.RS
+John Sebes,
+.I "Comparing UNIX Shells,"
+UNIX Papers,
+Edited by the Waite Group, Howard W. Sams & Co., 1987.
+.RF
+provides a more detailed comparison of the three shells,
+both as a command language and as a programming language.
+.P
+The KornShell language is a superset of the
+Bourne shell. The KornShell language has many of the popular C shell features,
+plus additional features of its own.
+Its initial popularity stems primarily from its improvements as
+a command language.
+The primary interactive benefit of the KornShell command language
+is a visual command line editor that allows you to
+make corrections to your current command line
+or to earlier command lines,
+without having to retype them.
+.P
+However,
+in the long run,
+the power of the KornShell language as a high-level programming language,
+as described by Dolotta and Mashey\*(Rf,
+.RS
+T. A. Dolotta and J. R. Mashey,
+.I "Using the shell as a Primary Programming Tool,"
+Proc. 2nd. Int. Conf. on Software Engineering, 1976,
+pages 169-176.
+.RF
+may prove to be of greater significance.
+\f5ksh-93\fP provides the programming power of several
+other interpretive languages such as \f5awk\fP,
+\f5FIT\fP,
+\f5PERL\fP,
+and
+\f5tcl\fP.
+An application that was originally written in the C programming language
+was rewritten in the KornShell language.
+More than 20,000 lines of C code were replaced with KornShell scripts
+totaling fewer than 700 lines.
+In most instances there was no perceptible difference in performance
+between the two versions of the code.
+.P
+The KornShell language has been embedded into windowing systems
+allowing graphical user interfaces to be developed in shell
+rather than having to build applications that need to be
+compiled.
+The \f5wksh\fP program\*(Rf
+.RS
+J. S. Pendergrast,
+.IR "WKSH - Korn Shell with X-Windows Support",
+USL. 1991.
+.RF
+provides a method of developing OpenLook or Motif
+applications as \f5ksh\fP scripts.
+.P
+This memo is an introduction to \f5ksh-93\fP,
+the program that implements an enhanced version
+of the KornShell language.
+It is referred to as \f5ksh\fP in the rest of this memo.
+The memo describes the KornShell language based on the
+features of the 12/28/93 release of \f5ksh\fP.
+This memo is not a tutorial, only an introduction.
+The second edition of reference [9] gives
+a more complete treatment of the KornShell language.
+.P
+A concerted effort has been made to achieve both System V Bourne shell
+compatibility and IEEE POSIX compatibility
+so that scripts written for either of these shells
+can run without modification with \f5ksh\fP.
+In addition, \f5ksh-93\fP attempts to
+be compatible with older versions of \f5ksh\fP.
+When there are conflicts between versions of the shell,
+\f5ksh-93\fP selects the behavior dictated by the IEEE POSIX
+standard.
+The description of features in this memo assumes
+that the reader is already familiar with the Bourne shell.
+.H 1 "COMMAND LANGUAGE"
+There is no separate command language.
+All features of the language, except job control,
+can be
+used both within a script and interactively from a terminal.
+However, features that are more likely to be used
+while running commands interactively from a terminal
+are presented here.
+.H 2 "Setting Options"
+By convention, UNIX commands
+consist of a command name followed by options and other arguments.
+Options are either of the form \f5-\fP\fIletter\fP,
+or \f5-\fP\fIletter value\fP.
+In the former case, several options may be grouped after a single \f5-\fP.
+The argument \f5--\fP signifies an end to the option list and is
+only required when the first non-option argument begins with
+a \f5-\fP.
+Most commands print an error message which
+shows which options are permitted
+when given incorrect arguments.
+In addition, the option sequence \f5-?\fP causes most commands
+to print a usage message which lists the valid options.
+.P
+Ordinarily, \f5ksh\fP executes a command by
+using the command name to locate a program to run
+and by running the program as a separate process.
+Some commands, referred to as
+.IR built-ins ,
+are carried out by \f5ksh\fP itself,
+without creating a separate process.
+The reasons that some commands are built-in are presented later.
+In nearly all cases the distinction
+between a command that is built-in and one that
+is not is invisible to the user.
+However, nearly
+all commands that are built-in follow command line conventions.
+.P
+\f5ksh\fP has several options that can be set by the user
+as command line arguments at invocation and as option arguments to the
+\f5set\fP command.
+Most other options can be set with a single letter option or as a name
+that follows the \f5-o\fP option.
+Use
+\f5set\ -o\fP
+to display the current option settings.
+Some of these options, such as
+.B interactive
+and
+.B monitor
+(see
+.I "Job Control"
+below),
+are enabled automatically by \f5ksh\fP
+when the shell is connected to a terminal device.
+Other options, such as
+.B noclobber
+and
+.BR ignoreeof ,
+are normally placed in a startup file.
+The
+.B noclobber
+option causes
+\f5ksh\fP
+to print an error message when you use
+.B >
+to redirect output to a file that already exists.
+If you want to redirect to an existing file, then
+you have to use
+.B >|
+to override
+the
+.B noclobber
+option.
+The
+.B ignoreeof
+option
+is used to prevent the
+.I end-of-file
+character, normally
+.B ^D
+(Control- d),
+from exiting the shell and possibly logging you out.
+You must type \f5exit\fP
+to log out.
+Most of the options are described in this memo as appropriate.
+.H 2 "Command Aliases"
+.P
+Command aliases provide a mechanism of associating a command name and
+arguments with a shorter name.
+Aliases are defined with the \f5alias\fP
+built-in.
+The form of an \f5alias\fP
+command definition is:
+.ce
+\f5alias\fP \fIname\fP\f5=\fP\fIvalue\fP
+As with most other shell assignments, no space is allowed before or after
+the \f5=\fP.
+The characters of an alias name cannot be characters that are
+special to the shell.
+The replacement string,
+.I value,
+can contain any valid shell script,
+including meta-characters such as pipe symbols and i/o-redirection
+provided that they are quoted.
+Unlike
+\f5csh\fP,
+aliases in
+\f5ksh\fP
+cannot take arguments.
+The equivalent functionality of aliases with arguments can
+be achieved with shell functions, described later.
+.P
+As a command is being read,
+the command name is checked against a list of
+.I alias
+names.
+If it is found,
+the name is replaced by the alias value associated with the
+.I alias
+and then rescanned.
+When rescanning the value for an alias, alias substitutions
+are performed except for an alias that is currently being processed.
+This prevents infinite loops in alias substitutions.
+For example with the aliases, \f5alias\ l=ls\ 'ls=ls\ -C'\fP,
+the command name \f5l\fP becomes \f5ls\fP, which becomes \f5ls\ -C\fP.
+Ordinarily, only the command name word is processed for alias substitution.
+However, if the value of an alias ends in a space,
+then the word following the alias is also checked for alias substitution.
+This makes it possible
+to define an alias whose first argument is the name of a command
+and have alias substitution performed on this argument,
+for example
+\f5nohup='nohup\ '\fP.
+.P
+Aliases can be used to redefine built-in commands so that
+the alias,
+.ce
+\f5alias test=./test\fP
+can be used to look for \f5test\fP
+in your current working directory rather than
+using the built-in \f5test\fP command.
+Reserved words such as
+\f5for\fP and \f5while\fP
+cannot be changed by aliasing.
+The command \f5alias\fP,
+without arguments, generates
+a list of aliases and corresponding alias values.
+The \f5unalias\fP command removes the name and text of an alias.
+.P
+Aliases are used to save typing and to improve readability of scripts.
+Several aliases are predefined by \f5ksh\fP.
+For example, the predefined alias
+.ce
+\f5alias integer='typeset -i'\fP
+allows the integer variables \f5i\fP and \f5j\fP
+to be declared and initialized with the command
+.ce
+\f5integer i=0 j=1\fP
+.P
+While aliases can be defined in scripts,
+it is not recommended.
+The location of an alias command can be important
+since aliases are only processed when a command is read.
+A \fB\s+2.\s-2\fP
+procedure (the shell equivalent of an include file)
+is read all at once (unlike
+start up files
+which are read a command at
+a time) so that any aliases defined there will not effect any commands
+within this script.
+Predefined aliases do not have this problem.
+.H 2 "Command Re-entry"
+.P
+When run interactively,
+\f5ksh\fP saves the
+commands you type at a terminal in a file.
+If the variable
+\fB\s-1HISTFILE\s+1\fP
+is set to the name of a file to which the user
+has write access,
+then the commands are stored in this
+.I history
+file.
+Otherwise the file
+\fB$\s-1HOME\s+1/.sh_history\fP
+is checked for write access and if this fails
+an unnamed file is used to hold the history lines.
+Commands are always appended to this file.
+Instances of \f5ksh\fP
+that run concurrently and use the same history file
+name, share access to the history file so that a command
+entered in one shell will be available for editing in another
+shell.
+The file may be truncated when \f5ksh\fP
+determines that no other shell is using the history file.
+The number of commands accessible to the user is determined by the value of the
+\fB\s-1HISTSIZE\s+1\fP
+variable at the time the shell is invoked.
+The default value is 256.
+Each command may consist of one or more lines since a compound
+command is considered one command.
+If the character
+.B !
+is placed within the
+.I "primary prompt"
+string,
+\fB\s-1PS1\s+1\fP,
+then it is replaced by the command number each time the prompt is given.
+.P
+A built-in command named \f5hist\fP
+is used to list and/or edit
+any of these saved commands.
+The option
+.B \-l
+is used to specify listing of previous commands.
+The command can always be specified with
+a range of one or more commands.
+The range can be specified by giving the command
+number, relative or absolute, or by giving
+the first character or characters of the command.
+When given without specifying the range,
+the last 16
+commands are listed, each
+preceded by the command number.
+.P
+If the listing option is not selected,
+then the range of commands specified,
+or the last command if no range is given,
+is passed to an editor program before
+being re-executed by \f5ksh\fP.
+The editor to be used may be specified
+with the option
+.B \-e
+and following it with the editor name.
+If this option is not specified, the
+value of the shell variable
+\fB\s-1HISTEDIT\s+1\fP
+is used as the name of the editor,
+providing that this variable has a non-null value.
+If this variable is not set, or is null,
+and the
+.B \-e
+option has not been selected,
+then
+\f5/bin/ed\fP
+is used.
+When editing has been complete,
+the edited text automatically becomes
+the input for \f5ksh\fP.
+As this text is read by \f5ksh\fP, it is echoed onto the terminal.
+.P
+The
+.B \-s
+option causes the editing to be bypassed
+and just re-executes the command.
+In this case only a single command can be specified as the range
+and an optional argument of the form
+\fIold\fP\fB=\fP\fInew\fP
+may be added which requests a simple string substitution
+prior to evaluation.
+A convenient alias,
+.ce
+\f5alias r='hist -s'\fP
+has been pre-defined so that
+the single key-stroke
+\f5r\fP
+can be used to re-execute the previous command
+and the key-stroke sequence,
+\f5r\ abc=def\ c\fP
+can be used to re-execute the last command that starts with
+the letter \f5c\fP
+with the first occurrence of the string \f5abc\fP
+replaced with the string \f5def\fP.
+Typing
+\f5r\ c\ >\ file\fP
+re-executes the most recent command starting with the letter \f5c\fP,
+with standard output redirected to
+.IR file .
+.H 2 "In-line editing"
+.P
+Lines typed from a terminal frequently need changes made
+before entering them.
+With the Bourne shell the only method to fix up commands
+is by backspacing or killing the whole line.
+\f5ksh\fP offers options that allow the user to edit parts of the
+current command line before submitting the command.
+The in-line edit options make the command line into a single
+line screen edit window.
+When the command is longer than the width of the terminal,
+only a portion of the command is visible.
+Moving within the line automatically makes that portion visible.
+Editing can be performed on this window until the
+.I return
+key is pressed.
+The editing modes have editing directives that access the history file
+in which previous commands are saved.
+A user can copy any of the most recent
+\fB\s-1HISTSIZE\s+1\fP
+commands from this file into the input edit window.
+You can locate commands by searching or by position.
+.P
+The in-line editing options do not use the
+.I termcap
+or
+.I terminfo
+databases.
+They work on most standard terminals.
+They only require that the backspace character moves the cursor left
+and the space character overwrites the current character on the screen
+and moves the cursor to the right.
+Very few terminals or terminal emulators do not have
+this behavior.
+.P
+There is a choice of editor options.
+The
+.BR emacs ,
+.BR gmacs ,
+or
+.B vi
+option is selected by turning on the
+corresponding
+option of the \f5set\fP
+command.
+If the value of the
+\fB\s-1EDITOR\s+1\fP
+or
+\fB\s-1VISUAL\s+1\fP
+variables ends with any of these suffixes
+the corresponding option is turned on.
+A large subset of each of these editors'
+features is available within the shell. Additional
+functions, such as file name completion, have also been added.
+.P
+In the
+.B emacs
+or
+.B gmacs
+mode the user positions the cursor to the point
+needing correction and inserts, deletes, or replaces
+characters as needed.
+The only difference between these two modes is the
+meaning of the directive
+.BR ^T .
+Control keys and escape sequences are used for cursor
+positioning and control functions.
+The available editing functions are listed in the manual page.
+.P
+The
+.B vi
+editing mode
+starts in insert mode and enters control mode when the
+user types ESC ( 033 ).
+The
+.I return
+key, which submits the current command for processing,
+can be entered from either mode.
+The cursor can be anywhere on the line.
+A subset of commonly used
+.I vi
+editing directives are available.
+The
+.B k
+and
+.B j
+directives that normally move up and down by one
+.IR line ,
+move up and down one
+.I command
+in the history file,
+copying the command into the input edit window.
+For reasons of efficiency,
+the terminal is kept in canonical mode until an
+ESC
+is typed.
+On some terminals,
+and on earlier versions of the UNIX operating system,
+this doesn't work correctly.
+The
+.B viraw
+option,
+which always uses
+.I raw
+or
+.I cbreak
+mode,
+must be used in this case.
+.P
+Most of the code for the editing options does not rely on the
+\f5ksh\fP code and can be used in a stand-alone mode with most any command
+to add in-line edit capability.
+However,
+all versions of the in-line editors have some features that
+use some shell specific code. For example,
+with all edit modes, the
+ESC-=
+directive applied to command words
+(the first word on the line,
+or the first word after a
+.BR ; ,
+.BR | ,
+.BR ( ,
+or
+.BR & )
+lists all aliases, functions, or commands
+that match the portion of the given current word.
+When applied to other words, this directive
+prints the names of files that match the current
+word.
+The ESC\fB-*\fP directive
+adds the expanded list of matching files to the command line.
+A trailing
+.B *
+is added to the word if it doesn't contain any file pattern matching
+characters before the expansion.
+In
+.B emacs
+and
+.B gmacs
+mode,
+ESC-ESC
+indicates command completion when applied to
+command names, otherwise it indicates pathname completion.
+With command or pathname completion,
+the list generated by the
+ESC-= directive is examined to find
+the longest common prefix.
+With command completion, only the last component of
+the pathname is used to compute the longest command prefix.
+If the longest common prefix is a complete match,
+then the word is replaced by the pathname, and a
+.B /
+is appended if
+pathname is a directory, otherwise a space is added.
+In
+.B vi
+mode,
+.B \e
+from control mode gives the same behavior.
+.H 2 "Key Binding"
+.P
+It is possible to intercept keys as they are entered and
+apply new meanings or bindings.
+A trap named
+\fB\s-1KEYBD\s+1\fP
+is evaluated each time
+\f5ksh\fP processes characters entered
+from the keyboard,
+other than those typed
+while entering a search string or an argument to an
+edit directive such as
+.B r
+in vi-mode.
+The action associated with this trap can change the value of
+the entered key to cause the key to perform a different
+operation.
+.P
+When the
+\fB\s-1KEYBD\s+1\fP
+trap is entered,
+the \fB.sh.edtext\fP
+variable contains the contents of the current input line
+and the \fB.sh.edcol\fP
+variable gives the current cursor position within this line.
+The \fB.sh.edmode\fP
+variable contains the
+.B ESC
+character when the trap is entered from
+.B vi
+insert mode.
+Otherwise, this value is null.
+The \fB.sh.edchar\fP
+variable contains the character or
+escape sequence that caused the trap.
+A key sequence is either a single character,
+.B ESC
+followed by a single character,
+or
+.B ESC[
+followed by a single character.
+In the \fBvi\fP edit mode,
+the characters after the
+.B ESC
+must be entered within half a second after the
+.BR ESC .
+The value of \fB.sh.edchar\fP
+at the end of the trap will be used as
+the input sequence.
+.P
+Using the associative array facility of \f5ksh\fP described later,
+and the function facility of \f5ksh\fP, it is easy to write
+a single trap so that keys can be bound dynamically. For example,
+.sp
+.nf
+.in .5i
+.ta 4i
+\f5typeset -A Keytable
+trap 'eval "${Keytable[${.sh.edchar}]}"' KEYBD
+function keybind # key action
+{
+ typeset key=$(print -f "%q" "$2")
+ case $# in
+ 2) Keytable[$1]='.sh.edchar=${.sh.edmode}'"$key"
+ ;;
+ 1) unset Keytable[$1]
+ ;;
+ *) print -u2 "Usage: $0 key [action]"
+ ;;
+ esac
+}\fP
+.ta
+.in
+.fi
+.sp
+.H 2 "Job Control"
+.P
+The job control mechanism
+is almost identical to the version introduced in \f5csh\fP
+of the Berkeley UNIX operating system,
+version 4.1 and later.
+The job control feature allows the user to stop and
+restart programs, and to move programs to and from the
+foreground and the background.
+It will only work on systems that provide support for
+these features.
+However,
+even systems without job control have a
+.B monitor
+option which, when enabled, will report the progress
+of background jobs and enable the user to \f5kill\fP
+jobs by job number or job name.
+.P
+An interactive shell associates a
+.I job
+with each pipeline typed in from the terminal
+and assigns it a small integer number
+called the job number.
+If the job is run asynchronously,
+the job number is printed at the terminal.
+At any given time, only one job owns the terminal,
+i.e., keyboard signals are only sent to the processes in one job.
+When \f5ksh\fP creates a foreground job,
+it gives it ownership of the terminal.
+If you are running a job and wish to stop
+it you hit the key
+.B ^Z
+(control-\fBZ\fP)
+which sends a
+\fB\s-1STOP\s+1\fP
+signal to all processes in the current job.
+The shell receives notification that the processes
+have stopped and takes back control of the terminal.
+.P
+There are commands to continue programs in the foreground
+and background.
+There are several ways to refer to jobs.
+The character
+.B %
+introduces a job name.
+You can refer to jobs by name or number as described in the manual page.
+The built-in command \f5bg\fP
+allows you to continue a job in the background,
+while the built-in command \f5fg\fP
+allows you to continue a job in the foreground even
+though you may have started it in the background.
+.P
+A job being run in the background will stop if it tries
+to read from the terminal.
+It is also possible to stop background jobs that try to write on
+the terminal by setting the terminal options
+appropriately.
+.P
+There is a built-in command \f5jobs\fP
+that lists the status of all running and stopped jobs.
+In addition,
+you are informed of the change of state (running or stopped)
+of any background
+jobs just before each prompt.
+If you want to be notified about background job completions
+as soon as they occur without waiting for a prompt, then use the
+.B notify
+option.
+When you try to exit the shell while jobs are stopped or running,
+you will receive a message from \f5ksh\fP.
+If you ignore this message and try to exit again,
+all stopped processes will be terminated.
+In addition, for login shells, the
+\fB\s-1HUP\s+1\fP
+signal will be sent to
+all background jobs
+unless the job has been disowned with the
+.B disown
+command.
+.P
+A built-in version of \f5kill\fP
+makes it possible to use
+.I job
+numbers as targets for signals.
+Signals can be selected by number or name.
+The name of the signal is the name found in the
+.I include
+file
+.B /usr/include/sys/signal.h
+with the prefix
+.B \s-1SIG\s+1
+removed.
+The
+.B \-l
+option of \f5kill\fP
+provides a means to map individual signal names to and from
+signal number.
+In addition, if no signal name or number is given,
+\f5kill\ -l\fP
+generates a list of valid signal names.
+.H 2 "Changing Directories"
+By default,
+\f5ksh\fP
+maintains a logical view of the file system hierarchy
+which makes symbolic links transparent.
+For systems that have symbolic links,
+this means that if \f5/bin\fP is a symbolic link to \f5/usr/bin\fP
+and you change directory to \f5/bin\fP, \f5pwd\fP will indicate
+that you are in \f5/bin\fP, not \f5/usr/bin\fP.
+\f5pwd\ -P\fP
+generates the physical pathname of the present working
+directory by resolving all the symbolic links.
+By default,
+the \f5cd\fP
+command will take you where you expect to go even if you cross
+symbolic links.
+A subsequent \f5cd\ ..\fP in the example above
+will place you in \f5/\fP, not \f5/usr\fP.
+On systems with symbolic links,
+\f5cd\ -P\fP
+causes
+.B ..
+to be treated physically.
+.P
+\f5ksh\fP remembers your last directory
+in the variable
+\fB\s-1OLDPWD\s+1\fP.
+The \f5cd\fP
+built-in can be given with argument
+.B \-
+to return to the previous directory
+and print the name of the directory.
+Note that \f5cd\ -\fP
+done twice returns you to the starting directory,
+not the second previous directory.
+A directory
+.I stack
+manager has been written as shell
+.I functions
+to
+.I push
+and
+.I pop
+directories from the stack.
+.H 2 "Prompts"
+.P
+When \f5ksh\fP
+reads commands from a terminal,
+it issues a prompt whenever it is ready
+to accept more input and then
+waits for the user to respond.
+The
+\fB\s-1TMOUT\s+1\fP
+variable
+can be set to be the number of seconds that the shell will wait for
+input before terminating.
+A 60 second warning message is printed
+before terminating.
+.P
+The shell uses two prompts.
+The primary prompt,
+defined by the value of the
+\fB\s-1PS1\s+1\fP
+variable,
+is issued at the start of each command.
+The secondary prompt,
+defined by the value of the
+\fB\s-1PS2\s+1\fP
+variable,
+is issued when more input is needed to complete a command.
+.P
+\f5ksh\fP allows the user to specify a list of files or directories
+to check before issuing the
+\fB\s-1PS1\s+1\fP
+prompt.
+The variable
+\fB\s-1MAILPATH\s+1\fP
+is a colon (
+.B :
+) separated list of file names to be checked for changes
+periodically. The user is notified
+before the next prompt.
+Each of the names in this list can be followed by a
+.B ?
+and a message to be given when a change has been detected in the file.
+The prompt will be evaluated for parameter expansion, command
+substitution and arithmetic expansion which are described later.
+The parameter
+.B $_
+within a mail message will evaluate to the name of the file that
+has changed.
+The parameter
+\fB\s-1MAILCHECK\s+1\fP
+is used to specify the minimal interval in seconds before
+new mail is checked for.
+.P
+In addition to replacing each
+.B !
+in the prompt with the command number,
+\f5ksh\fP expands
+the value of the
+.B \s-1PS1\s+1
+variable
+for parameter expansions, arithmetic expansions,
+and command substitutions as described below
+to generate the prompt.
+The expansion characters that are to be applied when
+the prompt is issued must be quoted to prevent the
+expansions from occurring when assigning the value to
+.B \s-1PS1\s+1.
+For example,
+\f3\s-1PS1\s+1="$\s-1PWD\s+1"\fP
+causes
+.B \s-1PS1\s+1
+to be set to the value of
+.B \s-1PWD\s+1
+at the time of the assignment whereas
+.B \s-1PS1\s+1='$\s-1PWD\s+1'
+causes
+.B \s-1PWD\s+1
+to be expanded at the time the prompt is issued.
+.P
+Command substitution may require a separate process
+to execute and cause the prompt display to be somewhat
+slow, especially
+when the return key is pressed several times in a row.
+Therefore, its use
+within
+.B \s-1PS1\s+1
+is discouraged.
+Some variables are maintained by \f5ksh\fP
+so that their values can be used with
+.B \s-1PS1\s+1.
+The
+.B \s-1PWD\s+1
+variable stores the pathname of the current working directory.
+The value of
+.B \s-1SECONDS\s+1
+variable
+is the value of the most
+recent assignment plus the elapsed time.
+By default, the time is measured in milli-seconds,
+but since
+.B \s-1SECONDS\s+1
+is a floating point variable, the
+number of places after the decimal point in the expanded
+value can be
+specified with
+\f5typeset\ -F\fP\fIplaces\fP\f5\ SECONDS\fP.
+In a roundabout way, this variable
+can be used to generate a time stamp into the
+.B \s-1PS1\s+1
+prompt without creating a process at each prompt.
+The following code explains how you can do this on
+System V. On BSD, you need a different command to initialize
+the
+.B \s-1SECONDS\s+1
+variable.
+\f5
+.sp
+.nf
+.in .5i
+# . this script and use $TIME as part of your PS1 string to
+# get the time of day in your prompt
+typeset -RZ2 _x1 _x2 _x3
+(( SECONDS=$(date '+3600*%H+60*%M+%S') ))
+_s='_x1=(SECONDS/3600)%24,_x2=(SECONDS/60)%60,_x3=SECONDS%60,0'
+TIME='"${_d[_s]}$_x1:$_x2:$_x3"'
+# PS1=${TIME}whatever
+.fi
+.ta
+.in
+.sp
+\fP
+.H 2 "Tilde substitution"
+.P
+The character
+.B \(ap
+at the beginning of a word has special meaning to \f5ksh\fP.
+If the characters after the
+.B \(ap
+up to a
+.B /
+match a user login name in the password database, then the
+.B \(ap
+and the name are replaced by
+that user's login directory.
+If no match is found, the original word
+is unchanged.
+A
+.B \(ap
+by itself, or in front of a
+.BR / ,
+is replaced by the value of the
+\fB\s-1HOME\s+1\fP
+parameter.
+A
+.B \(ap
+followed by a
+.B +
+or
+.B \-
+is replaced by the value of
+.B $\s-1PWD\s+1
+or
+.B $\s-1OLDPWD\s+1
+respectively.
+.H 2 "Output formats"
+The output of built-in commands and traces have values quoted so that they
+can be re-input to the shell.
+This makes it easy to cut and paste shell output on systems
+which use a pointing device such as a mouse.
+In addition, output can be saved in a file for reuse.
+.P
+.H 2 "The \fB\s-1ENV\s+1\fP file"
+When an interactive \f5ksh\fP starts, it evaluates the
+.B $\s-1ENV\s+1
+variable to arrive at a file name.
+If this value is not null,
+\f5ksh\fP attempts to read and process
+commands in a file by this name.
+Earlier versions of \f5ksh\fP read the \fB\s-1ENV\s+1\fP file
+for all invocations of the shell primarily to allow
+function definitions to be available for all shell
+invocations.
+The function search path, \fB\s-1FPATH\s+1\fP, described later,
+eliminated the primary need for this capability and it was
+removed because the high performance cost was no longer
+deemed acceptable.
+.H 1 "PROGRAMMING LANGUAGE"
+The KornShell vastly extends the set of applications that
+can be implemented efficiently at the shell level.
+It does this by providing simple yet powerful mechanisms
+to perform arithmetic, pattern matching,
+substring generation,
+and arrays.
+Users can write applications as separate functions that can
+be defined in the same file or in a library of functions
+stored in a directory and loaded on demand.
+.H 2 "String Processing"
+The shell is primarily a string processing language.
+By default, variables hold variable length strings.
+There are no limits to the length of strings. Storage
+management is handled by the shell automatically.
+Declarations are not required.
+With most programming languages, string constants are designated
+by enclosing characters in single quotes or double quotes.
+Since most of the words in the language are strings, the shell
+requires quotes only when a string contains characters that
+are normally processed specially by the shell, but their
+literal meaning is intended.
+However, since the shell is a string processing language,
+and some characters can occur as literals and as language metacharacters,
+quoting is an important part of the language.
+.P
+There are four quoting mechanisms in \f5ksh\fP.
+The simplest is to enclose a sequence of characters inside single quotes.
+All characters between a pair of single quotes have their literal meaning;
+the single quote itself cannot appear.
+A
+.B $
+immediately preceding
+a single quoted string
+causes all the characters until the matching single quote
+to be interpreted as an ANSI-C language string.
+Thus, \f5'\en'\fP represents characters \f5\e\fP and
+\f5n\fP, whereas, \f5$'\en'\fP
+represents the new-line character.
+Double quoted strings remove the special meaning of all characters
+except
+.BR $ ,
+.BR \(ga ,
+and
+.BR \e ,
+so that parameter expansion and command substitution (defined below)
+are performed.
+The final mechanism for quoting a character is by preceding it with the
+escape character
+.BR \e\^ .
+This mechanism works outside of quoted strings and for the characters
+.BR $ ,
+.BR \(ga ,
+\fB"\fP,
+and
+.B \e
+in double quoted strings.
+.P
+Variables are designated by
+one or more
+strings of alphanumeric
+characters beginning with an alphabetic character
+separated by a \fB\s+2.\s-2\fP.
+Upper and lower case characters are distinct, so that the variable
+.B A
+and
+.B a
+are names of different variables.
+There is no
+limit to the length of the name of a variable.
+You do not have to declare variables.
+You can assign a value to a variable by writing the name of the
+variable, followed by an equal sign, followed by a character string
+that represents its value.
+To create a variable whose name
+contains a \fB\s+2.\s-2\fP,
+the variable whose name consists of
+the characters before the last \fB\s+2.\s-2\fP
+must already exist.
+You reference a variable by
+putting the name inside curly braces and
+preceding the braces with a dollar sign.
+The braces may be omitted when the name
+is alphanumeric.
+If \f5x\fP and \f5y\fP
+are two shell variables, then
+to define a new variable,
+\f5z\fP,
+whose value is
+the concatenation of the values of
+\f5x\fP and \f5y\fP,
+you just say
+\f5z=$x$y\fP.
+It is that easy.
+.P
+The
+.B $
+can be thought of as meaning
+"value of."
+You can also capture the output of any command with the notation
+.BI $( command ) .
+This is referred to as command substitution.
+For example,
+\f5x=$(date)\fP
+assigns the output from the \f5date\fP
+command to the variable \f5x\fP.
+Command substitution in the
+Bourne shell is denoted by enclosing the command between
+backquotes,
+(\fB\(ga\^\(ga\fP).
+This notation
+suffers from some
+complicated quoting rules.
+Thus, it is hard to write \f5sed\fP
+patterns which contains back slashes within command substitution.
+Putting the pattern in single quotes
+is of little help.
+\f5ksh\fP accepts the Bourne shell command substitution syntax
+for backward compatibility.
+The
+.BI $( command )
+notation allows
+the \fIcommand\fP itself to contain quoted strings even if the substitution
+occurs within double quotes. Nesting is legal.
+.P
+The special command substitution of the form
+\f5$(cat\ file)\fP
+can be replaced by
+\f5$(<\ file)\fP,
+which is faster because
+the \f5cat\fP
+command doesn't have to run.
+.H 2 "Shell Parameters and Variables"
+.P
+There are three types of parameters used by \f5ksh\fP,
+special parameters, positional parameters, and named
+parameters which are called variables.
+\f5ksh\fP defines the same special parameters,
+.BR 0 ,
+.BR * ,
+.BR @ ,
+.BR # ,
+.BR ? ,
+.BR $ ,
+.BR ! ,
+and
+.BR \- ,
+as in the Bourne shell.
+.P
+Positional parameters are set when the shell is invoked,
+as arguments to the \f5set\fP built-in,
+and by calls to functions (see below) and \fB\s+2.\s-2\fP
+procedures.
+They are named by numbers starting at 1.
+.P
+The third type of parameter is a variable.
+As mentioned earlier,
+\f5ksh\fP uses variables whose names
+consist of one or more
+alpha-numeric strings separated by a \fB\s+2.\s-2\fP.
+There is no need to specify the
+.I type
+of a variable in the shell because, by default,
+variables store strings of arbitrary length
+and values will automatically be converted to numbers
+when used in an arithmetic context.
+However, \f5ksh\fP variables
+can have one or more
+.I attributes
+that control the internal representation of the variable,
+the way the variable is printed, and its access or
+scope.
+In addition,
+\f5ksh\fP
+allows variables to represent arrays of values
+and references to other variables.
+The \f5typeset\fP
+built-in command of \f5ksh\fP
+assigns attributes to variables.
+Two of the attributes,
+.I readonly
+and
+.IR export ,
+are available in the Bourne shell.
+Most of the remaining attributes are discussed here.
+The complete list of attributes appears in the manual.
+The \f5unset\fP
+built-in of \f5ksh\fP removes
+values and attributes of variables.
+When a variable is exported, certain of its attributes are also exported.
+.P
+Whenever a value is assigned to a variable,
+the value is transformed according to the attributes of the variable.
+Changing the attribute of a variable can change its value.
+The attributes
+.B \-L
+and
+.B \-R
+are for left and right field justification respectively.
+They are useful for aligning columns in a report.
+For each of these attributes, a width can be defined explicitly or else
+it is defined the first time an assignment is made to the variable.
+Each assignment causes justification of the field, truncating
+if necessary.
+Assignment to fixed sized variables
+provides one way to generate a substring consisting of
+a fixed number of characters from
+the beginning or end of a string.
+Other methods are discussed later.
+.P
+The attributes
+.B \-u
+and
+.B \-l
+are used for upper case and lower case
+formatting, respectively.
+Since it makes no sense to have both attributes on simultaneously,
+turning on either of these attributes turns the other off.
+The following script,
+using \f5read\fP and \f5print\fP which are described later,
+provides an example of the use of shell variables
+with attributes.
+This script reads a file of lines each consisting of five fields separated by
+.B :
+and prints fields 4 and 2 in upper case in columns 1-15, left justified,
+and columns 20-25 right-justified respectively.
+.sp
+.nf
+.in .5i
+.ta 3.4i
+\f5typeset -uL15 f4 # 15 character left justified
+typeset -uR6 f2 # 6 character right justified
+IFS=: # set field separator to :
+while read -r f1 f2 f3 f4 f5 # read line, split into fields
+do print -r -- "$f4 $f2" # print fields 4 and 2
+done\fP
+.fi
+.ta
+.in
+.sp
+.P
+The
+.BR \-i ,
+.BR \-E ,
+and
+.BR \-F ,
+attributes are used to represent numbers.
+Each can be followed by a decimal number.
+The
+.B \-i
+attribute causes the value to be represented as an integer and it
+can be followed by a number representing the numeric base when expanding
+its value.
+Whenever a value is assigned to an integer variable, it is evaluated
+as an arithmetic expression
+and then truncated to an integer.
+.P
+The
+.B \-E
+attribute causes the value to be represented in scientific
+notation whenever its value is expanded. The number following the
+.B \-E
+determines the number of significant figures, and defaults to 6.
+The
+.B \-F
+attribute causes the value to be represented with a fixed number
+of places after the decimal point.
+Assignments to variables with the
+.B \-E
+or
+.B \-F
+attributes cause the evaluation of the right hand side of the assignment.
+.P
+\f5ksh\fP allows one-dimensional
+.I arrays
+in addition to simple variables.
+There are two types of arrays; associative arrays
+and indexed arrays.
+The subscript for an associative array is an arbitrary
+string, whereas the subscript for an indexed array is
+an arithmetic expression that is evaluated to yield an integer
+index.
+Any variable can become an indexed array
+by referring to it with
+an integer
+.IR subscript .
+All elements of an array need not exist.
+Subscripts for arrays
+must evaluate to an
+integer between 0 and some maximum value, otherwise
+an error results.
+The maximum value may vary from one machine to another but
+is at least 4095.
+Evaluation of subscripts is described in
+the next section.
+Attributes apply to the whole array.
+.P
+Assignments to array variables can be made to individual elements
+via parameter
+assignment commands or the
+.B typeset
+built-in.
+Additionally, values can be assigned sequentially with
+compound assignment as described below, or by the
+.B \-A
+.I name
+option of the \f5set\fP command.
+Referencing of subscripted variables requires the character
+.BR $ ,
+but also requires braces around the array element name.
+The braces are needed to avoid conflicts with the
+file name generation mechanism.
+The form of any array element reference is:
+.ce
+.BI ${ name [ subscript ]}
+Subscript values of
+.B *
+and
+.B @
+can be used to generate all elements of an array,
+as they are used for expansion of positional parameters.
+The list of currently defined subscripts for a given
+variable can be generated with
+.BI ${! name [@]} ,
+or
+.BI ${! name [*]} .
+.P
+The
+.B \-n
+or
+.I nameref
+attribute causes the variable to be treated
+as a reference to the variable defined by its value.
+Once this attribute is set, all references to this variable
+become references to the variable named by the value
+of this variable.
+For example, if \f5foo=bar\fP, then setting the reference
+attribute on \f5foo\fP will cause all subsequent references
+to \f5foo\fP to behave as the variable whose name is \f5$foo\fP
+was referenced, which in this case is the variable \f5bar\fP.
+Unsetting this attribute breaks the association.
+Reference variables are usually used inside functions whose
+arguments are the names of shell variables.
+The names for reference variables cannot contain a \fB\s+2.\s-2\fP.
+Whenever a shell variable is referenced, the portion of the
+variable up to the first \fB\s+2.\s-2\fP
+is checked to see whether it matches the name of a reference
+variable.
+If it does, then the name of the variable actually used
+consists of the concatenation of the name of the variable
+defined by the reference plus the remaining portion of the
+original variable name.
+For example, using the predefined alias, \f5alias\ nameref='typeset\ -n'\fP,
+.sp
+.nf
+.in .5i
+.ta 3.4i
+\f5\^.bar.home.bam="hello world"
+nameref foo=.bar.home
+print ${foo.bam}
+\fBhello world\fP\fP
+.fi
+.ta
+.in
+.sp
+.H 2 "Compound Assignment"
+Compound assignments are used to assign values to arrays
+and compound data structures.
+The syntax for a compound assignment is
+.IB name =( assignment-list )
+where
+\fIname\fP
+is the name of the variable to which you want to assign values.
+No space is permitted between the variable name and the \fB=\fP
+but can appear between the \fB=\fP and the open parenthesis.
+New-lines can appear between the parentheses.
+.P
+The \fIassignment-list\fP can be in several different forms
+yielding different results.
+If \fIassignment-list\fP is simply a list of words, then
+the words are processed as they are with the \f5for\fP command
+and assigned sequentially as an indexed array.
+For example,
+.ce
+\f5foo=( * )\fP
+creates an indexed array \f5foo\fP and assigns the
+file names in the current directory to each index starting
+at zero.
+.P
+The second form for \fIassignment-list\fP is a list of assignments
+of the special form \fB[\fP\fIword\fP\fB]=\fP\fIword\fP.
+No space is permitted before or after the \fB=\fP.
+In this case, the variable given by \fIname\fP becomes
+an associative array with the given arguments as subscripts.
+For example,
+.ce
+\f5bar=( [color]=red [shape]=box )\fP
+creates an associate array named \f5bar\fP whose
+subscripts are \f5color\fP and \f5shape\fP.
+.P
+The third form for \fIassignment-list\fP is a list of
+normal assignments, including compound assignments.
+These assignments cause sub-variables to be assigned
+corresponding to the given assignments.
+In addition to assignments, the \fIassignment-list\fP
+can contain \f5typeset\fP commands.
+In addition to creating sub-variables,
+the effect of a compound assignment is to make
+the value of the original variable be a parenthesized
+assignment list of its components.
+For example, the assignment
+.sp
+.nf
+.in .5i
+.ta 3.4i
+\f5foo=(
+ left=bar
+ typeset -i count=3
+ point=(
+ x=50
+ y=60
+ )
+ colors=( red green yellow )
+ right=bam
+) \fP
+.ta
+.in
+.fi
+.sp
+is equivalent to the assignments
+.sp
+.nf
+.in .5i
+.ta 3.4i
+\f5foo.left=bar
+foo.count=3
+foo.point.x=50
+foo.point.y=60
+foo.colors=( red green yellow )
+foo.right=bam\fP
+.ta
+.in
+.fi
+.sp
+In addition, the value of \f5"$foo"\fP is
+.sp
+.nf
+.in .5i
+.ta 3.4i
+\f5(
+ colors=( red green yellow )
+ left=bar
+ typeset -i count=3
+ point=(
+ y=60
+ x=50
+ )
+ right=bam
+)\fP
+.ta
+.in
+.fi
+.sp
+.H 2 "Substring Generation"
+The expansion of a variable or parameter can be modified so that
+only a portion of the value results.
+It is often necessary to extract a portion of a shell variable or
+a portion of an array.
+There are several parameter expansion operators that can do this.
+One method to generate a substring is with an expansion of
+the form \fB${\fP\fIname\fP\fB:\fP\fIoffset\fP\fB:\fP\fIlength\fP\fB}\fP
+where \fIoffset\^\fP is an arithmetic expression that defines the
+offset of the first character starting from 0, and
+\fIlength\^\fP is an arithmetic expression that defines the
+length of the substring.
+If
+.BI : length\^
+is omitted,
+the length of the value of
+.I name\^
+starting at
+.I offset\^
+is used.
+The
+.BI : offset : length
+operators can also be applied to array expansions and to parameters
+.B *
+and
+.B @
+to generate portions of an array.
+For example, the expansion, \fB${\fP\fIname\fP\fB[@]:\fP\fIoffset\fP\fB:\fP\fIlength\fP\fB}\fP, yields up to \fIlength\fP elements of the array \fIname\fP
+starting at the element \fIoffset\fP.
+.P
+The other parameter expansion modifiers use shell patterns
+to describe portions of the string to modify and delete.
+A description of shell patterns is contained below.
+When these
+modifiers are applied to special parameters
+.B @
+and
+.B *
+or to array parameters given as
+\fIname\fP\fB[@]\fP or \fIname\fP\fB[*]\fP,
+the operation is performed on each element.
+There are four parameter expansion modifiers that
+strip off leading and trailing substrings
+during parameter expansion
+by removing the characters matching a given pattern.
+An expansion of
+the form \fB${\fP\fIname\fP\fB#\fP\fIpattern\fP\fB}\fP
+causes the smallest matching prefix of the value of
+.I name\^
+to be removed.
+The largest prefix matching
+.I pattern\^
+is removed by using
+.B ##
+instead of
+.BR # .
+Similarly,
+an expansion of
+the form \fB${\fP\fIname\fP\fB%\fP\fIpattern\fP\fB}\fP
+causes the smallest matching substring at the end of
+.I name\^
+to be removed.
+Again, using
+.B %%
+instead of
+.BR % ,
+causes the largest matching trailing substring to be deleted.
+For example, if the shell variable
+.B file
+has value
+.BR foo.c ,
+then the expression
+.B ${file%.c}.o
+has value
+.BR foo.o .
+.P
+The value of an expansion can be changed by
+specifying a pattern that matches the part that needs to be changed
+after the
+the parameter expansion modifier
+.BR / .
+An expansion of the form
+\fB${\fP\fIname\fP\fB/\fP\fIpattern\fP\fB/\fP\fIstring\fP\fB}\fP
+replaces the first match of \fIpattern\fP with
+the value of variable \fIname\fP to \fIstring\fP.
+The second
+.B /
+is not necessary when \fIstring\fP is null.
+The expansion
+\fB${\fP\fIname\fP\fB//\fP\fIpattern\fP\fB/\fP\fIstring\fP\fB}\fP
+changes all occurrences of the \fIpattern\fP into \fIstring\fP.
+The parameter expansion modifiers
+.B /#
+and
+.B /%
+cause the matching pattern to be anchored to the beginning and
+end respectively.
+.P
+Finally, there are parameter expansion modifiers that yield
+the name of the variable, the string length of the value, or the number
+of elements of an array.
+\fB${!\fP\fIname\fP\fB}\fP
+yields the name of the variable which will be \fIname\fP itself
+except when \fIname\fP is a reference variable. In this case
+it will yield the name of the variable it refers to.
+When applied to an array variable,
+\fB${!\fP\fIname\fP\fB[@]}\fP and
+\fB${!\fP\fIname\fP\fB[*]}\fP
+generate the names of all subscripts.
+\fB${#\fP\fIname\fP\fB}\fP
+will be the length in bytes of
+\fB$\fP\fIname\fP.
+For an array variable
+\fB${#\fP\fIname\fP\fB[*]}\fP
+gives the number of elements in the array.
+.H 2 "Arithmetic Evaluation"
+.P
+For the most part, the shell is a string processing
+language. However, the need for arithmetic has
+long been obvious.
+Many of the characters that are special to the
+Bourne shell are needed as arithmetic operators.
+To make arithmetic easy to use, and to maintain
+compatibility with the Bourne shell, \f5ksh\fP uses matching
+.B ((
+and
+.B ))
+to delineate arithmetic expressions.
+While single parentheses might have been
+more desirable, these already mean
+.I subshell\^
+so that another notation was required.
+The arithmetic expression
+inside the double parentheses
+follows the same syntax, associativity and precedence
+as the ANSI-C\*(Rf
+.RS
+American National Standard for Information Systems \- Programming
+Language \- C, ANSI X3.159-1989.
+.RF
+programming language.
+The characters between the matching double parentheses
+are processed with the same rules used for double
+quotes so that spaces can be used to aid readability
+without additional quoting.
+.P
+All arithmetic evaluations are performed using
+double precision floating point arithmetic.
+Floating point constants follow the same rules as
+the ANSI-C programming language.
+Integer arithmetic constants are written as
+.ce
+.IB base # number,
+where
+.I base\^
+is a decimal integer between
+two and sixty-four and
+.I number\^
+is any non-negative number.
+Base ten is used
+when no base is specified.
+The digits are represented by the characters
+.BR 0-9a-zA-Z_@ .
+For bases less than or equal to 36,
+upper and lower case characters can
+be used interchangeably to represent the digits
+from 10 thru 35.
+.P
+Arithmetic expressions are made from constants,
+variables, and operators.
+Parentheses may be used for grouping.
+The contents inside the double parentheses
+are processed with the same expansions as occurs in a double quoted string,
+so that all
+.B $
+expansions are performed before the expression is evaluated.
+However, there is usually no need to use the
+.B $
+to get the value of a variable
+because the arithmetic evaluator replaces the name of the variable
+by its value within an arithmetic expression.
+The
+.B $
+cannot be used when the variable is the subject of assignment
+or an increment operation.
+As a rule it is better not to use
+.B $
+in front of variables in an arithmetic expression.
+.P
+An arithmetic command of the form
+.B
+(( ... ))
+.R
+is a command that evaluates the enclosed arithmetic expression.
+For example, the command
+.ce
+\f5(( x++ ))\fP
+can be used to
+increment the variable \f5x\fP,
+assuming that \f5x\fP contains some numerical value.
+The arithmetic command is true (return value 0), when the resulting
+expression is non-zero, and false (return value 1) when the
+expression evaluates to zero.
+This makes the command easy to use with the \f5if\fP and \f5while\fP
+compound commands.
+.P
+The \f5for\fP compound command
+has been extended for use in arithmetic contexts.
+The syntax,
+.ce
+\f5for\fP \fB((\fP \fIexpr1\fP\fB;\fP \fIexpr2\fP \fB;\fP \fIexpr3 \fP\fB))\fP
+can be used as the first line of a \f5for\fP loop with the same semantics
+as the \f5for\fP statement in the ANSI-C programming language.
+.P
+Arithmetic evaluations can also be performed as part of the evaluation
+of a command line.
+The syntax
+.B
+$((\ ...\ ))
+.R
+expands to the value of the enclosed arithmetic expression.
+This expansion can occur wherever parameter expansion is performed.
+For example using the \f5ksh\fP command \f5print\fP (described
+later)
+.ce
+\f5print $((2+2))\fP
+prints the number 4.
+.P
+The following script prints the first
+.I n
+lines of its standard input onto its standard output,
+where
+.I n
+can be supplied as an optional argument whose default value is 20.
+.sp
+.nf
+.in .5i
+.ta 4i
+\f5integer n=${1-20} # set n
+while (( n-- >=0 )) && read -r line # at most n lines
+do print -r -- "$line"
+done\fP
+.fi
+.ta
+.in
+.sp
+.H 2 "Shell Expansions"
+.P
+The commands you enter from the terminal or from a script
+are divided into words and each word undergoes several
+expansions to generate the command name and its arguments.
+This is done in two phases.
+The first phase recognizes reserved words, spaces and operators
+to decide where command boundaries lie.
+Alias substitutions take place during this phase.
+The second phase performs expansions in the following order:
+.BL
+.LI
+Tilde substitution,
+parameter expansion,
+arithmetic expansion,
+and command substitution
+are performed from left to right.
+The option
+.B \-u
+or
+.BR nounset ,
+will cause an error to occur when any variable
+that is not set is expanded.
+.LI
+The characters that result from parameter expansion and
+command substitution above are checked with the characters
+in the
+\fB\s-1IFS\s+1\fP variable
+for possible
+field splitting.
+(See a description of \f5read\fP below to see how
+\fB\s-1IFS\s+1\fP is used.)
+Setting
+\fB\s-1IFS\s+1\fP to a null
+value causes field splitting to be skipped.
+.LI
+Pathname generation (as described below)
+is performed on each of the fields.
+Any field that doesn't match a pathname is left alone.
+The option,
+.B \-f
+or
+.BR noglob ,
+is used to disable pathname generation.
+.LE
+.H 2 "Pattern Matching"
+The shell is primarily a string processing language and uses
+patterns for matching file names as well as for matching strings.
+The characters
+.BR ? ,
+.BR * ,
+and
+.B [
+are processed specially
+by the shell when not quoted.
+These characters are used to form patterns that
+match strings.
+Patterns are used by the shell to match pathnames,
+to specify substrings,
+and for
+.B case
+commands.
+The character
+.B ?
+matches any one character.
+The character
+.B *
+matches zero or more characters.
+The character sequence
+.BR [ ... ]
+defines a character class
+that matches any character contained within
+.BR [\^] .
+A range of characters can be specified by putting a
+.B \-
+between the first and last character of the range.
+An exclamation mark,
+.BR ! ,
+immediately after the
+.BR [ ,
+means match all characters except the characters specified.
+For example, the pattern
+\f5a?c*.[!a-z]\fP
+matches any string beginning with an
+.BR a ,
+whose third character is a
+.BR c ,
+and that ends in
+.B .
+(dot) followed by any character except the lower case letters,
+.BR a\-z .
+The sequence \f5[:alpha:]\fP
+inside a character class, matches any set of characters in
+the ANSI-C
+.B alpha
+class.
+Similarly, \f5[:\fP\fIclass\fP\f5:]\fP matches
+each of the characters in the given \fIclass\fP
+for all the ANSI-C character classes.
+For example, \f5[[:alnum:]_]\fP
+matches any alpha-numeric character or the character
+.BR _ .
+.P
+\f5ksh\fP
+treats
+strings of the form
+.BI ( pattern-list
+.BR ) ,
+where
+.I pattern-list
+is a list of one or more patterns separated by a
+.BR \(bv ,
+specially when preceded by
+.BR * ,
+.BR ? ,
+.BR + ,
+.BR @ ,
+or
+.BR ! .
+A
+.B ?
+preceding
+.BI ( pattern-list )
+means that the pattern list enclosed in
+.B (\^)
+is optional.
+An
+.BI @( pattern-list )
+matches any pattern in the list of patterns enclosed in
+.BR () .
+A
+.BI *( pattern-list )
+matches any string that contains zero or more of each of the enclosed
+patterns,
+whereas
+.BI +( pattern-list )
+requires a match of one or more of any of the given patterns.
+For instance, the pattern
+.B +([0\-9])?(.)
+matches one or more digits optionally followed by a
+.BR . (dot).
+A
+.BI !( pattern-list )
+matches anything except any of the given patterns.
+For example,
+\f5print\ !(*.o)\fP
+displays all file names in the current directory that do not end in
+.BR .o .
+.P
+When patterns are used to generate pathnames when expanding
+commands several other rules apply.
+A separate match is made
+for each file name component of the pathname.
+Read permission is required for
+any portion of the pathname that contains any special
+pattern character.
+Search permission is required for every component except
+possibly the last.
+.P
+By default,
+file names in each directory that begin with \fB\s+2.\s-2\fP
+are skipped when performing a match.
+If the pattern to be matched starts with a leading \fB\s+2.\s-2\fP,
+then only files beginning with a \fB\s+2.\s-2\fP,
+are examined when reading each directory to find matching files.
+If the
+\fB\s-1FIGNORE\s+1\fP variable
+is set,
+then only files that do not match this pattern
+are considered.
+This overrides the special meaning of \fB\s+2.\s-2\fP
+in a pattern and in a file name.
+.P
+If the
+.B markdirs
+option is set,
+each matching pathname that is the name
+of a directory has a trailing
+.B /
+appended to the name.
+.P
+.H 2 "Conditional Expressions"
+The Bourne shell uses the \f5test\fP
+command, or the equivalent \f5[\fP
+command, to test files for attributes
+and to compare strings or numbers.
+The problem with \f5test\fP
+is that the shell has expanded the words of the \f5test\fP
+command and
+split them into arguments before \f5test\fP begins execution.
+\f5test\fP
+cannot distinguish between operators and operands.
+In most cases
+\f5test\ "$1"\fP
+will test whether argument 1 is non-null.
+However,
+if argument 1 is
+.BR \-f ,
+then \f5test\fP
+will treat
+.B \-f
+as an operator and
+yield a syntax error.
+One of the most frequent errors with
+\f5test\fP
+occurs when its operands are not within double quotes.
+In this case, the argument may expand to more than a single
+argument or to no argument at all. In either case this
+will likely cause a syntax error.
+What makes this most insidious is that these errors are frequently
+data dependent. A script that appears to run correctly may abort
+if given unexpected data.
+.P
+To get around these problems,
+\f5ksh\fP
+has a compound command for conditional expression testing
+as part of the language.
+The reserved words
+.B [[
+and
+.B ]]
+delimit the range of the command.
+Because they are reserved words, not operator characters,
+they require spaces to separate them
+from arguments.
+The words between
+.B [[
+and
+.B ]]
+are not processed for field splitting or for pathname generation.
+In addition, since \f5ksh\fP
+determines the operators before parameter expansion,
+expansions that yield no argument cause no problem.
+The operators within
+.BR [[ ... ]]
+are almost the same as those for the \f5test\fP
+command.
+All unary operators are of the form
+.BI \- letter
+and are followed by a single operand.
+Instead of
+.B \-a
+and
+.BR \-o ,
+.BR [[ ... ]]
+uses
+.B &&
+and
+.B \(bv\(bv
+to indicate "and" and "or".
+Parentheses are used without quoting for grouping.
+.P
+The right hand side of the string comparison operators
+.B ==
+and
+.B !=
+takes a pattern and tests whether the left hand operand
+matches this pattern. Quoting the pattern results
+is a string comparison rather than the pattern match.
+The operators
+.B <
+and
+.B >
+within
+.BR [[ ... ]]
+designate lexicographical comparison.
+.P
+In addition there are several other new comparison primitives.
+The binary operators
+.B \-ot
+and
+.B \-nt
+compare the modification times
+of two files to see which file is
+.I "older than"
+or
+.I "newer than"
+the other.
+The binary operator
+.B \-ef
+tests whether two files
+have the same device and i-node number,
+i.\ e., a link to the same file.
+.P
+The unary operator
+.B \-L
+returns true if its operand is a symbolic link.
+The unary operator
+.B \-O
+(\fB\-G\fP)
+returns true if the owner (or group) of the file operand matches
+that of the caller.
+The unary operator
+.B \-o
+returns true when its operand is the name of an option that is
+currently on.
+.P
+The following script illustrates some of the uses of
+.BR [[ ... ]] .
+The reference manual contains the complete list of operators.
+.sp
+.nf
+.in .5i
+.ta 4i
+\f5for i
+do # execute foo for numeric directory
+ if [[ \-d $i && $i == +([0\-9]) ]]
+ then foo
+ # otherwise if writable or executable file and not mine
+ elif [[ (\-w $i\(bv\(bv\-x $i) && ! \-O $i ]]
+ then bar
+ fi
+done\fP
+.fi
+.ta
+.in
+.sp
+.H 2 "Input and Output"
+\f5ksh\fP has
+extended I/O capabilities to enhance the
+use of the shell as a programming language.
+As with the Bourne shell,
+you use the I/O redirection operator,
+.BR < ,
+to control where input comes from,
+and the I/O redirection operator,
+.BR > ,
+to control where output goes to.
+Each of these operators can be preceded with a single digit that
+specifies a file unit number to associate with the file stream.
+Ordinarily you specify these I/O redirection operators with a specific
+command to which it applies.
+However, if you specify I/O redirections with the \f5exec\fP
+command,
+and don't specify arguments to \f5exec\fP,
+then the I/O redirection applies to the current program.
+For example, the command
+\f5exec\ <\ foobar\fP
+opens file \f5foobar\fP
+for reading.
+The \f5exec\fP
+command is also used to close files.
+A file descriptor unit can be opened as a copy of an existing
+file descriptor unit by using either of the
+.B <&
+or
+.B >&
+operators and putting the file descriptor unit of the original file
+after the
+.BR & .
+Thus, \f52>&1\fP means open standard error (file descriptor 2)
+as a copy of standard output (file descriptor 1).
+A file descriptor value of
+.B \-
+after the
+.B &
+indicates that the file should be closed.
+To close file unit 5, specify
+\f5exec\ 5<&-\fP.
+There are two additional redirection operators with \f5ksh\fP
+and the POSIX shell that are not part of the Bourne shell.
+The
+.B >|
+operator overrides the effect of the
+.B noclobber
+option described earlier.
+The
+.B <\^>
+operator causes a file to be opened for both reading and writing.
+.P
+\f5ksh\fP recognizes certain pathnames and treats them
+specially.
+Pathnames of the form
+.BI /dev/fd/ n\^
+are treated as equivalent to the file defined by file descriptor
+.IR n .
+These name can be used as the script argument to \f5ksh\fP
+and in conditional testing as described above.
+On underlying systems that support
+.B /dev/fd
+in the file system, these names can be passed to other commands.
+Pathnames of the form
+.BI /dev/tcp/ hostid / port
+and
+.BI /dev/udp/ hostid / port
+can be used to create
+.B tcp
+and
+.B udp
+connections to services given by the
+.I hostid\^
+number and
+.I port\^
+number.
+The
+.I hostid\^
+cannot use symbolic values. In practice these
+numbers are typically generated by command substitution.
+For example,
+\f5exec\ 5>\ /dev/tcp/$(service\ name)\fP
+would open file descriptor 5 for sending messages
+to hostid and port number defined by the output of \f5service\ name\fP.
+.P
+The Bourne shell has a built-in command \f5read\fP
+for reading lines from standard input (file descriptor 0)
+and splitting it into fields based on the value of the
+.B \s-1IFS\s+1
+variable, and a command \f5echo\fP
+to write strings to standard output.
+(On some systems, \f5echo\fP
+is not a built-in command and incurs considerable overhead to use.)
+Unfortunately, neither of these commands
+is able to perform some very basic tasks.
+For example.
+with the Bourne shell,
+the \f5read\fP
+built-in cannot read a single line that ends in
+.BR \e .
+With \f5ksh\fP
+the \f5read\fP
+built-in has a
+.B \-r
+option to remove the special meaning for
+.B \e
+which allows it to be
+treated as a regular
+character rather than the line continuation character.
+With the Bourne shell,
+there is no simple way to have more than one file open
+at any time for reading.
+\f5ksh\fP has options on the \f5read\fP
+command to specify the file
+descriptor for the input.
+The fields that are read from a line can be stored into an indexed
+array with the
+.B \-A
+option to read.
+This allows a line to be split into an arbitrary number of fields.
+.P
+The way the Bourne shell uses the
+\fB\s-1IFS\s+1\fP variable to
+split lines into fields greatly limits its utility.
+Often data files consist of lines that use a character such
+as
+.B :
+to delimit fields with two adjacent delimiters that denote
+a null field.
+The Bourne shell treats adjacent delimiters as a single
+field delimiter.
+With \f5ksh\fP,
+delimiters that are considered white space characters
+have the behavior of the Bourne shell, but other
+adjacent delimiters separate
+null fields.
+.P
+The \f5read\fP command is often used in scripts that interact
+with the user by prompting the user and then requesting some
+input.
+With the Bourne shell two commands are needed; one to
+prompt the user, the other to read the reply.
+\f5ksh\fP allows these two commands to be combined.
+The first argument of the \f5read\fP
+command can be followed by a
+.B ?
+and a prompt string which is used whenever the input
+device is a terminal.
+Because the prompt is associated with the \f5read\fP built-in,
+the built-in command line editors will be able to re-output
+the prompt whenever the line needs to be refreshed when
+reading from a terminal device.
+.P
+With the Bourne shell,
+there is no way to set a time limit for waiting for the user
+response to read.
+The
+.B \-t
+option to \f5read\fP takes a floating
+point argument that gives the time in seconds,
+or fractions of seconds that the shell should wait for a reply.
+.P
+The version of the \f5echo\fP command in System V
+treats certain sequences beginning with
+.B \e
+as control sequences.
+This makes it hard to output strings without interpretation.
+Most BSD derived systems do not interpret
+.B \e
+control sequences.
+Unfortunately, the BSD versions of \f5echo\fP accepts a
+.B \-n
+option to prevent a trailing new-line, but has no way to
+cause the string
+.B \-n
+to be printed.
+Neither of these versions is adequate. Also, because they
+are incompatible, it is very hard to write portable shell scripts
+using \f5echo\fP.
+The \f5ksh\fP built-in, \f5print\fP,
+outputs characters to the terminal or to a file and
+subsumes the functions of all versions of \f5echo\fP.
+Ordinarily, escape sequences in arguments beginning with
+.B \e
+are processed the same as for the System V \f5echo\fP command.
+However \f5print\fP follows the standard conventions for
+options and has options that make \f5print\fP very versatile.
+The
+.B \-r
+option can be used to output the arguments without any special meaning.
+The
+.B \-n
+option can be used here to suppress the trailing new-line
+that is ordinarily appended.
+As with \f5read\fP, it is possible to specify the file descriptor number
+as an option to the command to avoid having to use
+redirection operators with each occurrence of the command.
+.P
+The IEEE POSIX shell and utilities standard committee was unable
+to reconcile the differences between the System V and BSD
+versions of \f5echo\fP.
+They introduced a new command named \f5printf\fP
+which takes an ANSI-C format string and a list of options
+and outputs the strings using the ANSI-C formatting rules.
+Since \f5ksh\fP is POSIX conforming, it accepts \f5printf\fP.
+However, there is a
+.B \-f
+options to \f5print\fP that can be used to specify
+a format string which processes the arguments the same way that
+\f5printf\fP does.
+.P
+The format processing for \f5print\fP and \f5printf\fP has
+been extended slightly.
+There are three additional formatting directives.
+The
+.B %b
+format causes the
+.B \e
+escape sequences to be expanded as they are with the System V \f5echo\fP
+command.
+The
+.B %q
+format causes quotes to
+be placed on the output as required
+so that it can be used as shell input.
+Special characters in the output of most \f5ksh\fP built-in commands
+and in the output from an execution trace
+are quoted in an equivalent fashion.
+The
+.B %P
+format causes an extended regular expression string to
+be converted into a shell pattern.
+This is useful for writing shell applications that have
+to accept regular expressions as input.
+Finally, the escape sequence
+.B \e\^E
+which expands to the terminal escape character (octal 033)
+has been added.
+.P
+The shell is frequently used as a programming language for
+interactive dialogues.
+The
+\f5select\fP
+statement has been added to the language
+to make it easier to
+present menu selection alternatives to the
+user and evaluate the reply.
+The list of alternatives is numbered and put in columns.
+A user settable prompt,
+\fB\s-1PS3\s+1\fP,
+is issued and if the answer is
+a number corresponding to one of the alternatives,
+the select loop variable is set to this value.
+In any case, the
+.B \s-1REPLY\s+1
+variable is used to store the user entered reply.
+The shell variables
+.B \s-1LINES\s+1
+and
+.B \s-1COLUMNS\s+1
+are used to control the layout of select lists.
+.H 2 "Option Parsing"
+The \f5getopts\fP built-in command can be used
+to process command arguments in a manner consistent
+with the way \f5ksh\fP does for its own built-in commands.
+.P
+The \f5getopts\fP built-in allows users to specify options
+as separate arguments or to group options that do not
+take arguments together. Options that require arguments
+do not require space to separate them from the option argument.
+The
+.B \s-1OPTARG\s+1
+variable stores the value of the option argument
+after finding a variable that takes an argument.
+The
+.B \s-1OPTIND\s+1
+variable holds the index of the current options argument.
+After processing options, the arguments should be
+shifted by
+.B \s-1OPTIND\s+1\-1
+to make the
+remaining arguments be \f5"$@"\fP.
+.P
+The \f5getopts\fP argument description allows additional
+information to be specified along with the options
+that is used to generate \fIusage\fP messages for
+incorrect arguments and for the option argument \fB\-?\fP.
+The example in the APPENDIX uses \f5getopts\fP to process
+its arguments.
+.H 2 "Co-process"
+\f5ksh\fP can spawn a
+.I co-process
+by adding a
+.B "|&"
+after a command.
+This process will be run with its standard input and its
+standard output connected to the shell. The built-in command \f5print\fP
+with the
+.B \-p
+option will write into the standard input of this
+process and
+the built-in command \f5read\fP
+with the
+.B \-p
+option will read from the output of this process.
+.P
+In addition, the I/O redirection operators \fB<&\fP and \fB>&\fP can
+be used to move the input or output pipe of the co-process
+to a numbered file descriptor.
+Use \f5exec\ 3>&\ p\fP to move the input of the co-process
+to file descriptor \fB3\fP.
+After you have connected to file descriptor \fB3\fP, you
+can direct the output of any command to the co-process
+by running \fIcommand\fP\f5\ >&3\fP.
+Also, by moving the input of the co-process to a numbered descriptor,
+it is possible to run a second co-process.
+The output of both co-processes will be the file descriptor
+associated with \f5read\ -p\fP.
+You can use \f5exec\ 4<&\ p\fP to cause the output of these
+co-processes to go to file descriptor \fB4\fP of the shell.
+Once you have moved the pipe to descriptor \fB4\fP, it is possible
+to connect a server to the co-process by running \fIcommand\fP\f5\ 4<&\ p\fP
+or to close the co-process pipe with \f5exec\ 4<&\ -\fP.
+.H 2 "Functions"
+.P
+Function definitions are of the form
+.sp
+.in +.5i
+.nf
+\f5function\fP \fIname\fP
+.br
+.B {
+.br
+ any shell script
+.br
+.B }
+.fi
+.sp
+.in
+A function whose name contains a \fB\s+2.\s-2\fP
+is called a \fIdiscipline\fP function.
+The portion of the name after the last \fB\s+2.\s-2\fP
+is the name of the discipline.
+Discipline functions named \f5get\fP, \f5set\fP, and \f5unset\fP
+can be assigned to any variable to intercept lookups,
+assignments and unsetting of the variable
+defined by the portion of the name before the last \fB\s+2.\s-2\fP.
+Applications can create additional disciplines for variables
+that are created as part of user defined built-ins.
+The portion of the name before the last \fB\s+2.\s-2\fP
+must refer to the name of an existing variable.
+Thus, if \f5p\fP is a reference to \f5PATH\fP, then
+the function name \f5p.get\fP and \f5PATH.get\fP
+refer to the same function.
+.P
+The function is invoked either
+by specifying
+.I name
+as the command name
+and optionally following it with arguments
+or by using it as an option to the \fB\s+2.\s-2\fP
+built-in command.
+Positional parameters are saved before each
+function call and restored when completed.
+The arguments that follow the function name on the calling
+line become positional parameters inside the function.
+The \f5return\fP
+built-in can be used to cause the function to return to
+the statement following
+the point of invocation.
+.P
+Functions can also be defined with the System V notation,
+.sp
+.in +.5i
+.nf
+\fIname\fP \f5()\fP
+.br
+.B {
+.br
+ any shell script
+.br
+.B }
+.fi
+.sp
+.in
+Functions defined with this syntax cannot be used as the first
+argument to a \fB\s+2.\s-2\fP procedure.
+\f5ksh\fP accepts this notation for compatibility only.
+There is no need to use this notation when writing
+\f5ksh\fP scripts.
+.P
+Functions defined with the \f5function\fP\ \fIname\fP syntax
+and invoked by name
+are executed in the current shell environment
+and can share named variables with the calling program.
+Options, other than execution trace
+.BR \-x ,
+set by the calling program are
+passed down to a function.
+The options are
+not shared with
+the function so that any options set within a function are
+restored when the function exits.
+Traps ignored by the caller are ignored within the function
+and cannot be enabled.
+Traps caught by the calling program are reset to their
+default action within the function.
+In most instances, the default action is
+to cause the function to terminate.
+A trap on
+\fB\s-1EXIT\s+1\fP
+defined within a function executes after the function
+completes but
+before the caller resumes.
+Therefore,
+any variable assignments and
+any options set as part of a trap action will be effective
+after the caller resumes.
+.P
+By default, variables are inherited by the function and shared
+by the calling program.
+However,
+for functions defined with the \f5function\fP\ \fIname\fP syntax
+that are invoked by name,
+environment substitutions preceding the function call
+apply only to the scope of the function call.
+Also, variables whose names do not contain a \fB\s+2.\s-2\fP
+that are defined with the \f5typeset\fP
+built-in command are local to the function that they are declared in.
+Thus, for the function defined
+.sp
+.nf
+.in .5i
+\f5function name
+{
+ typeset -i x=10
+ let z=x+y
+ print $z
+}\fP
+.fi
+.ta
+.in
+.sp
+invoked as
+\f5y=13\ name\fP,
+\f5x\fP and \f5y\fP
+are local variables with respect to the function
+\f5name\fP
+while
+\f5z\fP
+is global.
+.P
+Functions defined with the \fIname\fP\f5()\fP syntax,
+and functions invoked as an argument to the \fB\s+2.\s-2\fP
+command,
+share everything other than positional parameters with the caller.
+Assignments that precede the call remain in effect after the
+function completes.
+.P
+Alias and function names are not passed down to shell scripts
+or carried across separate
+invocations of \f5ksh\fP.
+The
+.B $\s-1FPATH\s+1
+variable gives a colon separated list of directories that
+is searched for function definitions when trying to resolve
+the command name.
+Whenever a file name contained in
+.B $\s-1FPATH\s+1
+is found, the complete file is read and all functions
+contained within become defined.
+.P
+Calls that reference functions can be recursive.
+Except for special built-ins,
+function names take precedence over built-in names and names
+of programs when used as command names.
+To write a replacement function that invokes the command that
+you wish to replace,
+you can use the \f5command\fP built-in command.
+The arguments to \f5command\fP are the name and arguments
+of the program you want to execute.
+For example to write a
+.B cd
+function which changes the directory and prints out the directory name,
+you can write
+.sp
+.nf
+.in .5i
+\f5function cd
+{
+ if command cd "$@"
+ then print -r -- $PWD
+ fi
+}\fP
+.fi
+.ta
+.in
+.sp
+.P
+The
+\fB\s-1FPATH\s+1\fP
+variable is a colon separated list that \f5ksh\fP
+uses to search for function definitions.
+When
+\f5ksh\fP
+encounters an autoload function,
+it runs the
+.B .
+command on the script containing the function,
+and then executes the function.
+.P
+For interactive shells,
+function definitions may also be placed in the
+\fB\s-1ENV\s+1\fP
+file.
+However, this
+causes the shell to take longer to begin executing.
+.H 2 "Process Substitution"
+.P
+This feature is only available
+on versions of the UNIX operating system which support the
+.B /dev/fd
+directory for naming open files.
+Each command argument of the form
+\fB<(\fP\fIlist\^\fP\fB)\fP
+or
+\fB>(\fP\fIlist\^\fP\fB)\fP
+will run process
+.I list
+asynchronously connected to some file in the
+.B /dev/fd
+directory.
+The name of this file will become the argument to the command.
+If the form with
+.B >
+is selected then writing on this file will provide input for
+.IR list .
+If
+.B <
+is used,
+then the file passed as an argument will contain the output of the
+.I list
+process.
+For example,
+.sp
+.nf
+.in .5i
+\f5paste <(cut \-f1 \fP\fIfile1\fP\f5) <(cut \-f2 \fP\fIfile2\fP\f5) | tee >(\fP\fIprocess1\fP\f5) >(\fP\fIprocess2\fP\f5)\fP
+.fi
+.ta
+.in
+.sp
+extracts
+fields 1 and 3 from
+the files
+.I file1
+and
+.I file2
+respectively,
+places the
+results side by side, and
+sends it
+to the processes
+.I process1
+and
+.IR process2 ,
+as well as putting it onto the standard output.
+Note that the file which is passed as an argument to the command is
+a UNIX system
+.IR pipe (2)
+so that the programs that expect to
+.IR lseek (2)
+on the file will not work.
+.H 2 "Finding Commands"
+.P
+The addition of aliases, functions,
+and more built-ins
+has made it substantially more difficult to know what
+a given command name really means.
+.P
+Commands that begin with reserved words
+are an integral part of the shell language itself
+and typically define the control flow of the language.
+Some control flow commands are not reserved words in
+the language but are \fIspecial\fP built-ins.
+Special built-ins are built-ins that are considered a
+part of the language rather than user definable commands.
+The best examples of commands that fit this description
+are \f5break\fP and \f5continue\fP.
+Because they are not reserved words, they can be the
+result of shell expansions and are not effected by quoting.
+These commands have the following special properties:
+.BL
+.LI
+Assignments that precede them apply to the current shell process,
+not just to the given command.
+.LI
+An error in the format of these commands cause a shell script
+or function that contains them to abort.
+.LI
+They cannot be overridden by shell functions.
+.LE
+.P
+Other commands are built-in because they perform side effects
+on the current environment that would be nearly impossible
+to implement otherwise.
+Built-ins such as \f5cd\fP and \f5read\fP
+are examples of such built-ins.
+These built-ins are semantically equivalent to commands that
+are not built-in except that they don't take a path search
+to locate.
+.P
+A third reason to have a command built-in is so that
+it will be unaffected by the setting of the
+.B \s-1PATH\s+1
+variable.
+The \f5print\fP command fits this category.
+Scripts that use \f5print\fP will be portable
+to all sites that run \f5ksh\fP.
+.P
+The final reason for having a command be a built-in is
+for performance.
+On most systems it is more than an order of magnitude
+faster to initiate a command that is built-in than
+to create a separate process to run the command.
+Examples that fit this category are \f5test\fP
+and \f5pwd\fP.
+.P
+Given a command name \f5ksh\fP decides what it means using
+the following order:
+.BL
+.LI
+Reserved words define commands that form part of the shell
+grammar.
+They cannot be quoted.
+.LI
+Alias substitutions occur first as part of the reading of commands.
+Using quotes in the command name will prevent alias substitutions.
+.LI
+Special built-ins.
+.LI
+Functions.
+.LI
+Commands that are built-in that are not associated with a pathname
+such as \f5cd\fP and \f5print\fP.
+.LI
+If the command name contains a
+.BR / ,
+the program or script corresponding to the given name is executed.
+.LI
+A path search locates the pathname corresponding to the command.
+If the pathname where it is found matches the pathname associated
+with a built-in command, the built-in command is executed.
+If the directory where the command is found is listed in the
+.B \s-1FPATH\s+1
+variable, the file is read into the shell
+like a dot script, and a function by that name is invoked.
+Once a pathname is found, \f5ksh\fP remembers its location
+and only checks relative directories in \fB\s-1PATH\s+1\fP
+the next time the command name is used.
+Assigning a value to \fB\s-1PATH\s+1\fP
+causes \f5ksh\fP to forget the location of all command names.
+.LI
+The
+.B \s-1FPATH\s+1
+variable is searched and files found are treated as described above.
+.LE
+.P
+The first argument of the \f5command\fP built-in, described earlier,
+skips the checks for reserved words and for function definitions.
+In all other ways, \f5command\fP behaves like a built-in
+that is not associated with a pathname.
+As a result, if the first argument of \f5command\fP is
+a special built-in, the special properties of this built-in
+do not apply.
+For example, whereas, \f5exec\ 3<\ foo\fP will cause a script containing
+it to abort if the open fails, \f5command\ exec\ 3<\ foo\fP
+results in a non-zero exit status but does not abort the script.
+.P
+You can get a complete list of the special built-in commands
+with \f5builtin\ -s\fP.
+In addition \f5builtin\fP without arguments gives a list of
+the current built-ins and the pathname that they are associated with.
+A built-in can be bound to another pathname by giving
+the pathname for the built-in. The basename of this path must
+be the name of an existing built-in for this to succeed.
+Specifying the name of the built-in without a pathname causes
+this built-in to be found before a path search.
+A built-in can be deleted with the \fB\-d\fP option.
+.P
+On systems with run time loading of libraries, built-in commands
+can be added with the \f5builtin\fP command.
+Each command that is to be built-in must be written as a
+C function whose name is of the form \f5b_\fP\fIname\fP, where
+\fIname\fP is the name of the built-in that is to be added.
+The function has the same argument calling convention as
+\f5main\fP. The lower eight bits of the return value become
+the exit status for this built-in.
+Builtins are added by specifying the pathname of the library
+as an argument to the \fB\-f\fP option of \f5builtin\fP.
+.P
+The built-in command,
+\f5whence\fP,
+when used with the
+.B \-v
+option, tells how a given command is bound.
+A line is printed for each argument to \f5whence\fP
+telling what would happen if this argument were used as a command name.
+It reports on reserved words, aliases, built-ins, and
+functions.
+If the command is none of the above,
+it follows the path search rules and prints the full path-name,
+if any, otherwise it prints an error message.
+.H 2 "Symbolic Names"
+To avoid implementation dependencies, \f5ksh\fP
+accepts and generates symbolic names
+for built-ins that use numerical values in the Bourne shell.
+The
+.B \-S
+option of the
+\f5umask\fP built-in command
+accepts and displays
+default file creation permissions
+symbolically.
+It uses the same symbolic notation as the \f5chmod\fP command.
+.P
+The \f5trap\fP and \f5kill\fP built-in commands
+allows the signal names to be given symbolically.
+The names of signals and traps
+corresponding to signals are the same as the signal name with
+the
+.B \s-1SIG\s+1
+prefix removed.
+The trap
+.B 0
+is named
+\fB\s-1EXIT\s+1\fP.
+.H 2 "Additional Variables"
+In addition to the variables discussed earlier, \f5ksh\fP
+has other variables that it handles specially.
+The variable \fB\s-1RANDOM\s+1\fP
+produces a random number in the range 0 to 32767 each time it is referenced.
+Assignment to this variable sets the seed for the
+random number generator.
+.P
+The parameter \fB\s-1PPID\s+1\fP
+is used to generate the process id of the process which invoked this shell.
+.H 2 "Added Traps"
+A new trap named
+\fB\s-1ERR\s+1\fP
+has been added.
+This trap is invoked whenever the shell would exit if the
+.B \-e
+option were set.
+This trap is used by
+Fourth Generation Make\*(Rf
+.RS
+G. S. Fowler,
+.I "The Fourth Generation Make,"
+Proceedings of the Portland USENIX meeting, pp. 159-174, 1985.
+.RF
+which runs \f5ksh\fP
+as a co-process.
+.P
+A trap named
+\fB\s-1DEBUG\s+1\fP
+gets executed after each command.
+This trap can be used for debugging and other purposes.
+.P
+The
+\fB\s-1KEYBD\s+1\fP
+trap was described earlier.
+.H 2 Debugging
+The primary method for debugging Bourne shell scripts is to
+use the
+.B \-x
+option to enable the execution trace.
+After all
+the expansions have been performed,
+but before each command is executed,
+the trace writes to standard error the name and arguments
+of each command preceded by a
+.BR + .
+While the trace is very useful, there is no way
+to find out what line of source a given trace line
+corresponds to.
+With
+\f5ksh\fP
+the
+\fB\s-1PS4\s+1\fP
+variable
+is evaluated for parameter expansion and
+is displayed before each command,
+instead of the
+.BR + .
+.P
+The
+\fB\s-1LINENO\s+1\fP
+variable is set to the current line number relative to the
+beginning of the current script or function.
+It is most useful as part of the
+\fB\s-1PS4\s+1\fP
+prompt.
+.P
+The
+\fB\s-1DEBUG\s+1\fP
+trap can be used to write a break point shell
+debugger in \f5ksh\fP.
+An example of such a debugger is \f5kshdb\fP.\*(Rf
+.RS
+Bill Rosenblatt,
+.IR "Debugging Shell Scripts with \f5kshdb\fP" ,
+Unix World, Volume X, No. 5, 1993.
+.RF
+.H 2 "Timing Commands"
+.P
+Finding the time it takes to execute commands
+has been a serious problem with the Bourne shell.
+Since the \f5time\fP command is not part of the
+language, it is necessary to write a script
+in order to time a \f5for\fP or \f5while\fP loop.
+The extra time in invoking the shell and processing
+the script is accumulated along with the time
+to execute the script.
+.P
+More seriously, the Bourne shell does not give correct
+times for pipelines.
+The reason for this is that the times for some members
+of a pipeline are not counted when computing the time.
+As an extreme example,
+running \f5time\fP on the script
+.ce
+\f5cat < /dev/null | sort -u bigfile | wc\fP
+with the Bourne shell will show very little
+user and system time no matter how
+large \f5bigfile\fP is.
+.P
+To correct these problems,
+a reserved word \f5time\fP
+has been added to replace
+the \f5time\fP
+command.
+Any function, command or pipeline can be preceded by this reserved word
+to obtain information about the elapsed, user, and system times.
+Since I/O redirections bind to the command, not to
+\f5time\fP,
+parentheses should be used to redirect the timing information which
+is normally printed on file descriptor 2.
+.H 1 SECURITY
+There are several documented problems associated with the security of
+shell procedures\*(Rf.
+.RS
+F. T. Grampp and R. H. Morris,
+.I "UNIX Operating System Security,"
+AT&T Bell Labs Tech. Journal, Vol. 63, No. 8, Part 2, pp. 1649-1671, 1984.
+.RF
+These security holes occur primarily because a user can manipulate the
+.I environment
+to subvert the intent of a
+.I setuid
+shell procedure.
+Sometimes, shell procedures are initiated from
+binary programs, without the author's
+awareness, by library routines which invoke shells to carry out
+their tasks.
+When the binary program is run
+.I setuid
+then the shell procedure runs with the permissions afforded to the
+owner of the binary file.
+.P
+In the Bourne shell,
+the
+.B \s-1IFS\s+1
+parameter is used to split each word into separate command arguments.
+If a user knows that some
+.I setuid
+program will run
+\f5sh\ -c\ /bin/pwd\fP
+(or any other command in
+.BR /bin )
+then the user sets and exports
+.BR \s-1IFS\s+1=\^/ .
+Instead of running
+.B /bin/pwd
+the shell will run
+.B bin
+with
+.B pwd
+as an argument.
+The user puts his or her own \f5bin\fP
+program into the current directory.
+This program can
+create a copy of the shell,
+make this shell
+.IR setuid ,
+and then run the \f5/bin/pwd\fP
+program so that the original program continues to run successfully.
+This kind of penetration is not possible with
+\f5ksh\fP
+since the
+.B \s-1IFS\s+1
+parameter only splits arguments that result from command or parameter
+substitution.
+.P
+Some
+.I setuid
+programs run programs using
+.I system()
+without giving the full pathname.
+If the
+user sets the
+.B \s-1PATH\s+1
+variable so that the desired command will be found
+in his or her local bin, then the same technique described above can
+be employed to compromise the security of the system.
+To close up this and other security holes,
+\f5ksh\fP
+resets the effective user id to the real user id and the effective
+group id to the real group id unless the
+.I privileged
+option
+.RB ( \-p\^ )
+is specified at invocation.
+In
+this mode, the
+.B privileged
+mode, the
+.B .profile
+and
+.B \s-1ENV\s+1
+files are not processed.
+Instead, the file
+.B /etc/suid_profile
+is read and executed.
+This gives an administrator control over the
+environment to set the
+.B \s-1PATH\s+1
+variable or to log setuid shell invocations.
+Clearly security of the system is compromised if
+.B /etc
+or this file is publicly writable.
+.P
+Some versions of the UNIX operating system look for the characters
+\f5#!\fP
+as the first two characters of an executable file.
+If these characters are found, then the next word on this line is taken
+as the interpreter to
+invoke
+for this command and the interpreter is
+.IR exec ed
+with the name of the script as argument zero and argument one.
+If the
+.I setuid
+or
+.I setgid
+bits are on for this file, then the interpreter
+is run with the effective uid and/or gid set accordingly.
+This scheme has three major drawbacks.
+First of all,
+putting the pathname of the interpreter into the script
+makes the script less portable since the interpreter
+may be installed in a different directory on another system.
+Secondly, using the
+\f5#!\fP
+notation forces an
+.B exec
+of the interpreter even when the call is invoked from the interpreter
+which it must exec. This is inefficient since
+\f5ksh\fP can handle a failed exec much faster than starting up
+again.
+More importantly,
+.I setuid
+and
+.I setgid
+procedures provide an easy target for intrusion.
+By linking a
+.I setuid
+or
+.I setgid
+procedure to a name beginning with a
+.B \-
+the interpreter is fooled into thinking that it is being invoked with
+a command line option rather than the name of a file.
+When the interpreter is the shell, the user gets a privileged
+interactive shell.
+There is code in
+\f5ksh\fP
+to guard against this simple form of intrusion.
+.P
+A more reliable way to handle
+.I setuid
+and
+.I setgid
+procedures is provided with
+\f5ksh\fP.
+The technique does not require any changes to the operating system
+and provides better security.
+Another advantage to this method is that it also allows scripts which
+have execute permission but no read permission to run. Taking away read
+permission makes scripts more secure.
+.P
+The method relies on a setuid
+.B root
+program to authenticate the
+request and exec the shell with the correct mode bits to carry out
+the task. This shell is invoked with the requested file already open
+for reading. A script which cannot be opened for reading or which
+has its setuid and/or setgid bits turned on causes this setuid
+.B root
+program to get \fBexec\fPed.
+For security reasons, this program is given the full
+pathname
+\f5/etc/suid_exec\fP.
+A description of the implementation of the
+\f5/etc/suid_exec\fP
+program can be found in
+a separate paper\*(Rf.
+.RS
+D. G Korn
+.I "Parlez-vous Kanji?"
+TM-59554-860602-03, 1986.
+.RF
+.H 1 "CODE CHANGES"
+\f5ksh\fP is written in ANSI-C as a reusable library.
+The code can be compiled with C++ and older K&R C as well.
+The code uses the IEEE POSIX 1003.1 and ISO 9945-1 standard\*(Rf
+.RS
+.I "POSIX \- Part 1: System Application Program Interface,"
+IEEE Std 1003.1-1990, ISO/IEC 9945-1:1990.
+.RF
+wherever possible so that \f5ksh\fP should be able to run
+on any POSIX compliant system. In addition, it is possible
+to compile \f5ksh\fP for older systems.
+.P
+Unlike earlier version of the Bourne shell,
+\f5ksh\fP treats eight bit characters transparently
+without stripping off the
+leading bit.
+There is also a compile time switch to enable handling multi-byte
+and multi-width characters sets.
+.P
+On systems with dynamic libraries, it is possible to add built-in
+commands at run time with the built-in command \f5builtin\fP
+described earlier.
+It is also possible to embed \f5ksh\fP in applications in
+a manner analogous to \f5tcl\fP.
+.H 1 "EXAMPLE"
+.P
+An example of a \f5ksh\fP script is included
+in the Appendix.
+This one page program is a variant of the UNIX system
+\f5grep\fP(1) program.
+Pattern matching for this version of \f5grep\fP
+means shell patterns.
+.P
+The first half uses the \f5getopts\fP command to
+find the option flags.
+Nearly all options have been implemented.
+The second half goes through each line of each file
+to look for a pattern match.
+.P
+This program is not intended to serve as a
+replacement for \f5grep\fP
+which has been highly tuned for performance.
+It does
+illustrate the programming power of \f5ksh\fP.
+Note that no auxiliary processes are spawned by this script.
+It was written and debugged in under two hours.
+While performance is acceptable for small files,
+this program runs at only one tenth
+the speed of \f5grep\fP
+for large files.
+.H 1 "PERFORMANCE"
+.P
+\f5ksh\fP executes many scripts faster than the System V Bourne shell;
+in some cases more than 10 times as fast.
+The primary reason for this is that \f5ksh\fP creates fewer
+processes.
+The time to execute a built-in command or a function is one or two
+orders of magnitude faster than performing a \f5fork\fP() and
+\f5exec\fP() to create a separate process.
+Command substitution and commands inside parentheses
+are performed without creating another process, unless necessary
+to preserve correct behavior.
+.P
+Another reason for improved performance is the use of the \fBsfio\fP\*(Rf,
+.RS
+David Korn and Kiem-Phong Vo,
+.IR "SFIO - A Safe/Fast String/File I/O,"
+Proceedings of the Summer Usenix,
+pp. 235-255, 1991.
+.RF
+library for I/O. The \fBsfio\fP library buffers all I/O
+and buffers are flushed only when required.
+The algorithms used in \fBsfio\fP perform better than
+traditional versions of standard I/O so that programs that
+spend most of their time
+formatting output may actually perform better
+than versions written in C.
+.P
+Several of the internal algorithms have been changed
+so that the number of subroutine calls has been
+substantially reduced.
+\f5ksh\fP uses variable sized hash tables for variables.
+Scripts that rely heavily on referencing variables execute faster.
+More processing is performed while reading the script
+so that execution time is saved while running loops.
+These changes are not noticeable for scripts that \f5fork()\fP
+and run processes,
+but they reduce the time that it takes to interpret commands by
+more than a factor of two.
+.P
+Most importantly, \f5ksh\fP provide mechanisms to write applications
+that do not require as many processes.
+The arithmetic provided by the shell eliminates the need for the
+\f5expr\fP command.
+The pattern matching and substring capabilities eliminate the
+need to use \f5sed\fP or \f5awk\fP to process strings.
+.P
+The architecture of \f5ksh\fP makes it easy to make commands
+built-ins without changing the semantics at all.
+Systems that have run-time binding of libraries allow
+applications to be sped up by supplying the critical
+programs as shell built-in commands.
+Implementations on other systems can add built-in commands
+at compile time.
+The procedure for writing built-in commands that can be loaded
+at run time is in a separate document.\*(Rf,
+.RS
+David Korn,
+.IR "Guidelines for writing \f5ksh-93\fP built-in commands,"
+to be published, 1994.
+.RF
+.H 1 "CONCLUSION"
+.P
+The 1988 version of \f5ksh\fP has tens of thousands of regular users
+and is a suitable replacement for the Bourne shell.
+The 1993 version of \f5ksh\fP is essentially upward compatible with
+both the 1988 version of \f5ksh\fP and with the recent IEEE POSIX
+and ISO shell standard.
+The 1993 version offers many advantages for programming applications,
+and it has been rewritten so that it can be used in embedded applications.
+It also offers improved performance.
+.SG dgk \" signature typist initials
+\" .CS 14 24 38 0 0 16 \" cover sheet for TM
+.bp
+.ce
+\fIAPPENDIX\fP
+.nf
+\f5
+.ta .66i 1.33i 2i 2.66i 3.33i 4i 4.66i 5.33i 6i 6.66i 7.33i 8i
+.so grep.mm
+.fi
+\fP
+
+
diff --git a/src/cmd/ksh93/sh/args.c b/src/cmd/ksh93/sh/args.c
new file mode 100644
index 0000000..4d27580
--- /dev/null
+++ b/src/cmd/ksh93/sh/args.c
@@ -0,0 +1,892 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Rewritten by David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include "path.h"
+#include "builtins.h"
+#include "terminal.h"
+#include "edit.h"
+#include "FEATURE/poll"
+#if SHOPT_KIA
+# include "shlex.h"
+# include "io.h"
+#endif /* SHOPT_KIA */
+#if SHOPT_PFSH
+# define PFSHOPT "P"
+#else
+# define PFSHOPT
+#endif
+#if SHOPT_BASH
+# define BASHOPT "\374"
+#else
+# define BASHOPT
+#endif
+#if SHOPT_HISTEXPAND
+# define HFLAG "H"
+#else
+# define HFLAG ""
+#endif
+
+#define SORT 1
+#define PRINT 2
+
+static char *null;
+
+/* The following order is determined by sh_optset */
+static const char optksh[] = PFSHOPT BASHOPT "DircabefhkmnpstuvxBCGEl" HFLAG;
+static const int flagval[] =
+{
+#if SHOPT_PFSH
+ SH_PFSH,
+#endif
+#if SHOPT_BASH
+ SH_POSIX,
+#endif
+ SH_DICTIONARY, SH_INTERACTIVE, SH_RESTRICTED, SH_CFLAG,
+ SH_ALLEXPORT, SH_NOTIFY, SH_ERREXIT, SH_NOGLOB, SH_TRACKALL,
+ SH_KEYWORD, SH_MONITOR, SH_NOEXEC, SH_PRIVILEGED, SH_SFLAG, SH_TFLAG,
+ SH_NOUNSET, SH_VERBOSE, SH_XTRACE, SH_BRACEEXPAND, SH_NOCLOBBER,
+ SH_GLOBSTARS, SH_RC, SH_LOGIN_SHELL,
+#if SHOPT_HISTEXPAND
+ SH_HISTEXPAND,
+#endif
+ 0
+};
+
+#define NUM_OPTS (sizeof(flagval)/sizeof(*flagval))
+
+typedef struct _arg_
+{
+ Shell_t *sh;
+ struct dolnod *argfor; /* linked list of blocks to be cleaned up */
+ struct dolnod *dolh;
+ char flagadr[NUM_OPTS+1];
+#if SHOPT_KIA
+ char *kiafile;
+#endif /* SHOPT_KIA */
+} Arg_t;
+
+static int arg_expand(Shell_t*,struct argnod*,struct argnod**,int);
+static void sh_argset(Arg_t*, char *[]);
+
+
+/* ======== option handling ======== */
+
+void *sh_argopen(Shell_t *shp)
+{
+ void *addr = newof(0,Arg_t,1,0);
+ Arg_t *ap = (Arg_t*)addr;
+ ap->sh = shp;
+ return(addr);
+}
+
+static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
+{
+#if SHOPT_BASH
+ extern const char sh_bash1[], sh_bash2[];
+ if(strcmp(s,"bash1")==0)
+ {
+ if(sh_isoption(SH_BASH))
+ sfputr(sp,sh_bash1,-1);
+ }
+ else if(strcmp(s,"bash2")==0)
+ {
+ if(sh_isoption(SH_BASH))
+ sfputr(sp,sh_bash2,-1);
+ }
+ else if(*s==':' && sh_isoption(SH_BASH))
+ sfputr(sp,s,-1);
+ else
+#endif
+ if(*s!=':')
+ sfputr(sp,sh_set,-1);
+ return(1);
+}
+
+/*
+ * This routine turns options on and off
+ * The options "PDicr" are illegal from set command.
+ * The -o option is used to set option by name
+ * This routine returns the number of non-option arguments
+ */
+int sh_argopts(int argc,register char *argv[], void *context)
+{
+ Shell_t *shp = (Shell_t*)context;
+ register int n,o;
+ register Arg_t *ap = (Arg_t*)(shp->arg_context);
+ Lex_t *lp = (Lex_t*)(shp->lex_context);
+ Shopt_t newflags;
+ int setflag=0, action=0, trace=(int)sh_isoption(SH_XTRACE);
+ Namval_t *np = NIL(Namval_t*);
+ const char *cp;
+ int verbose,f;
+ Optdisc_t disc;
+ newflags=ap->sh->options;
+ memset(&disc, 0, sizeof(disc));
+ disc.version = OPT_VERSION;
+ disc.infof = infof;
+ opt_info.disc = &disc;
+
+ if(argc>0)
+ setflag = 4;
+ else
+ argc = -argc;
+ while((n = optget(argv,setflag?sh_optset:sh_optksh)))
+ {
+ o=0;
+ f=*opt_info.option=='-' && (opt_info.num || opt_info.arg);
+ switch(n)
+ {
+ case 'A':
+ np = nv_open(opt_info.arg,ap->sh->var_tree,NV_NOASSIGN|NV_ARRAY|NV_VARNAME);
+ if(f)
+ nv_unset(np);
+ continue;
+#if SHOPT_BASH
+ case 'O': /* shopt options, only in bash mode */
+ if(!sh_isoption(SH_BASH))
+ errormsg(SH_DICT,ERROR_exit(1), e_option, opt_info.name);
+#endif
+ case 'o': /* set options */
+ byname:
+ if(!opt_info.arg||!*opt_info.arg||*opt_info.arg=='-')
+ {
+ action = PRINT;
+ /* print style: -O => shopt options
+ * bash => print unset options also, no heading
+ */
+ verbose = (f?PRINT_VERBOSE:PRINT_NO_HEADER)|
+ (n=='O'?PRINT_SHOPT:0)|
+ (sh_isoption(SH_BASH)?PRINT_ALL|PRINT_NO_HEADER:0)|
+ ((opt_info.arg&&(!*opt_info.arg||*opt_info.arg=='-'))?(PRINT_TABLE|PRINT_NO_HEADER):0);
+ continue;
+ }
+ o = sh_lookopt(opt_info.arg,&f);
+ if(o<=0
+ || (!sh_isoption(SH_BASH) && (o&SH_BASHEXTRA))
+ || ((!sh_isoption(SH_BASH) || n=='o') && (o&SH_BASHOPT))
+
+ || (setflag && (o&SH_COMMANDLINE)))
+ {
+ errormsg(SH_DICT,2, e_option, opt_info.arg);
+ error_info.errors++;
+ }
+ o &= 0xff;
+ if(sh_isoption(SH_RESTRICTED) && !f && o==SH_RESTRICTED)
+ errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg);
+ break;
+#if SHOPT_BASH
+ case -1: /* --rcfile */
+ ap->sh->gd->rcfile = opt_info.arg;
+ continue;
+ case -2: /* --noediting */
+ if (!f)
+ {
+ off_option(&newflags,SH_VI);
+ off_option(&newflags,SH_EMACS);
+ off_option(&newflags,SH_GMACS);
+ }
+ continue;
+ case -3: /* --profile */
+ n = 'l';
+ goto skip;
+ case -4: /* --posix */
+ /* mask lower 8 bits to find char in optksh string */
+ n&=0xff;
+ goto skip;
+ case -5: /* --version */
+ sfputr(sfstdout, "ksh bash emulation, version ",-1);
+ np = nv_open("BASH_VERSION",ap->sh->var_tree,0);
+ sfputr(sfstdout, nv_getval(np),-1);
+ np = nv_open("MACHTYPE",ap->sh->var_tree,0);
+ sfprintf(sfstdout, " (%s)\n", nv_getval(np));
+ sh_exit(0);
+#endif
+ case -6: /* --default */
+ {
+ register const Shtable_t *tp;
+ for(tp=shtab_options; o = tp->sh_number; tp++)
+ if(!(o&SH_COMMANDLINE) && is_option(&newflags,o&0xff))
+ off_option(&newflags,o&0xff);
+ }
+ continue;
+ case -7:
+ f = 0;
+ goto byname;
+ case 'D':
+ on_option(&newflags,SH_NOEXEC);
+ goto skip;
+ case 'T':
+ if (opt_info.num)
+ ap->sh->test |= opt_info.num;
+ else
+ ap->sh->test = 0;
+ continue;
+ case 's':
+ if(setflag)
+ {
+ action = SORT;
+ continue;
+ }
+#if SHOPT_KIA
+ goto skip;
+ case 'R':
+ if(setflag)
+ n = ':';
+ else
+ {
+ ap->kiafile = opt_info.arg;
+ n = 'n';
+ }
+ /*FALLTHROUGH*/
+#endif /* SHOPT_KIA */
+#if SHOPT_REGRESS
+ goto skip;
+ case 'I':
+ continue;
+#endif /* SHOPT_REGRESS */
+ skip:
+ default:
+ if(cp=strchr(optksh,n))
+ o = flagval[cp-optksh];
+ break;
+ case ':':
+ if(opt_info.name[0]=='-'&&opt_info.name[1]=='-')
+ {
+ opt_info.arg = argv[opt_info.index-1] + 2;
+ f = 1;
+ goto byname;
+ }
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ continue;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(-1);
+ }
+ if(f)
+ {
+ if(o==SH_VI || o==SH_EMACS || o==SH_GMACS)
+ {
+ off_option(&newflags,SH_VI);
+ off_option(&newflags,SH_EMACS);
+ off_option(&newflags,SH_GMACS);
+ }
+ on_option(&newflags,o);
+ off_option(&ap->sh->offoptions,o);
+ }
+ else
+ {
+ if(o==SH_XTRACE)
+ trace = 0;
+ off_option(&newflags,o);
+ if(setflag==0)
+ on_option(&ap->sh->offoptions,o);
+ }
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
+ /* check for '-' or '+' argument */
+ if((cp=argv[opt_info.index]) && cp[1]==0 && (*cp=='+' || *cp=='-') &&
+ strcmp(argv[opt_info.index-1],"--"))
+ {
+ opt_info.index++;
+ off_option(&newflags,SH_XTRACE);
+ off_option(&newflags,SH_VERBOSE);
+ trace = 0;
+ }
+ if(trace)
+ sh_trace(shp,argv,1);
+ argc -= opt_info.index;
+ argv += opt_info.index;
+ if(action==PRINT)
+ sh_printopts(newflags,verbose,0);
+ if(setflag)
+ {
+ if(action==SORT)
+ {
+ if(argc>0)
+ strsort(argv,argc,strcoll);
+ else
+ strsort(ap->sh->st.dolv+1,ap->sh->st.dolc,strcoll);
+ }
+ if(np)
+ {
+ nv_setvec(np,0,argc,argv);
+ nv_close(np);
+ }
+ else if(argc>0 || ((cp=argv[-1]) && strcmp(cp,"--")==0))
+ sh_argset(ap,argv-1);
+ }
+ else if(is_option(&newflags,SH_CFLAG))
+ {
+ if(!(ap->sh->comdiv = *argv++))
+ {
+ errormsg(SH_DICT,2,e_cneedsarg);
+ errormsg(SH_DICT,ERROR_usage(2),optusage(NIL(char*)));
+ }
+ argc--;
+ }
+ /* handling SH_INTERACTIVE and SH_PRIVILEGED has been moved to
+ * sh_applyopts(), so that the code can be reused from b_shopt(), too
+ */
+ sh_applyopts(ap->sh,newflags);
+#if SHOPT_KIA
+ if(ap->kiafile)
+ {
+ if(!argv[0])
+ errormsg(SH_DICT,ERROR_usage(2),"-R requires scriptname");
+ if(!(lp->kiafile=sfopen(NIL(Sfio_t*),ap->kiafile,"w+")))
+ errormsg(SH_DICT,ERROR_system(3),e_create,ap->kiafile);
+ if(!(lp->kiatmp=sftmp(2*SF_BUFSIZE)))
+ errormsg(SH_DICT,ERROR_system(3),e_tmpcreate);
+ sfputr(lp->kiafile,";vdb;CIAO/ksh",'\n');
+ lp->kiabegin = sftell(lp->kiafile);
+ lp->entity_tree = dtopen(&_Nvdisc,Dtbag);
+ lp->scriptname = strdup(sh_fmtq(argv[0]));
+ lp->script=kiaentity(lp,lp->scriptname,-1,'p',-1,0,0,'s',0,"");
+ lp->fscript=kiaentity(lp,lp->scriptname,-1,'f',-1,0,0,'s',0,"");
+ lp->unknown=kiaentity(lp,"<unknown>",-1,'p',-1,0,0,'0',0,"");
+ kiaentity(lp,"<unknown>",-1,'p',0,0,lp->unknown,'0',0,"");
+ lp->current = lp->script;
+ ap->kiafile = 0;
+ }
+#endif /* SHOPT_KIA */
+ return(argc);
+}
+
+/* apply new options */
+
+void sh_applyopts(Shell_t* shp,Shopt_t newflags)
+{
+ /* cannot set -n for interactive shells since there is no way out */
+ if(sh_isoption(SH_INTERACTIVE))
+ off_option(&newflags,SH_NOEXEC);
+ if(is_option(&newflags,SH_PRIVILEGED))
+ on_option(&newflags,SH_NOUSRPROFILE);
+ if(!sh_isstate(SH_INIT) && is_option(&newflags,SH_PRIVILEGED) != sh_isoption(SH_PRIVILEGED) || sh_isstate(SH_INIT) && is_option(&((Arg_t*)shp->arg_context)->sh->offoptions,SH_PRIVILEGED) && shp->gd->userid!=shp->gd->euserid)
+ {
+ if(!is_option(&newflags,SH_PRIVILEGED))
+ {
+ setuid(shp->gd->userid);
+ setgid(shp->gd->groupid);
+ if(shp->gd->euserid==0)
+ {
+ shp->gd->euserid = shp->gd->userid;
+ shp->gd->egroupid = shp->gd->groupid;
+ }
+ }
+ else if((shp->gd->userid!=shp->gd->euserid && setuid(shp->gd->euserid)<0) ||
+ (shp->gd->groupid!=shp->gd->egroupid && setgid(shp->gd->egroupid)<0) ||
+ (shp->gd->userid==shp->gd->euserid && shp->gd->groupid==shp->gd->egroupid))
+ off_option(&newflags,SH_PRIVILEGED);
+ }
+#if SHOPT_BASH
+ on_option(&newflags,SH_CMDHIST);
+ on_option(&newflags,SH_CHECKHASH);
+ on_option(&newflags,SH_EXECFAIL);
+ on_option(&newflags,SH_EXPAND_ALIASES);
+ on_option(&newflags,SH_HISTAPPEND);
+ on_option(&newflags,SH_INTERACTIVE_COMM);
+ on_option(&newflags,SH_LITHIST);
+ on_option(&newflags,SH_NOEMPTYCMDCOMPL);
+
+ if(!is_option(&newflags,SH_XPG_ECHO) && sh_isoption(SH_XPG_ECHO))
+ astconf("UNIVERSE", 0, "ucb");
+ if(is_option(&newflags,SH_XPG_ECHO) && !sh_isoption(SH_XPG_ECHO))
+ astconf("UNIVERSE", 0, "att");
+ if(!is_option(&newflags,SH_PHYSICAL) && sh_isoption(SH_PHYSICAL))
+ astconf("PATH_RESOLVE", 0, "metaphysical");
+ if(is_option(&newflags,SH_PHYSICAL) && !sh_isoption(SH_PHYSICAL))
+ astconf("PATH_RESOLVE", 0, "physical");
+ if(is_option(&newflags,SH_HISTORY2) && !sh_isoption(SH_HISTORY2))
+ {
+ sh_onstate(SH_HISTORY);
+ sh_onoption(SH_HISTORY);
+ }
+ if(!is_option(&newflags,SH_HISTORY2) && sh_isoption(SH_HISTORY2))
+ {
+ sh_offstate(SH_HISTORY);
+ sh_offoption(SH_HISTORY);
+ }
+#endif
+ shp->options = newflags;
+}
+
+/*
+ * returns the value of $-
+ */
+char *sh_argdolminus(void* context)
+{
+ register Arg_t *ap = (Arg_t*)context;
+ register const char *cp=optksh;
+ register char *flagp=ap->flagadr;
+ while(cp< &optksh[NUM_OPTS])
+ {
+ int n = flagval[cp-optksh];
+ if(sh_isoption(n))
+ *flagp++ = *cp;
+ cp++;
+ }
+ *flagp = 0;
+ return(ap->flagadr);
+}
+
+/*
+ * set up positional parameters
+ */
+static void sh_argset(Arg_t *ap,char *argv[])
+{
+ sh_argfree(ap->sh,ap->dolh,0);
+ ap->dolh = sh_argcreate(argv);
+ /* link into chain */
+ ap->dolh->dolnxt = ap->argfor;
+ ap->argfor = ap->dolh;
+ ap->sh->st.dolc = ap->dolh->dolnum-1;
+ ap->sh->st.dolv = ap->dolh->dolval;
+}
+
+/*
+ * free the argument list if the use count is 1
+ * If count is greater than 1 decrement count and return same blk
+ * Free the argument list if the use count is 1 and return next blk
+ * Delete the blk from the argfor chain
+ * If flag is set, then the block dolh is not freed
+ */
+struct dolnod *sh_argfree(Shell_t *shp, struct dolnod *blk,int flag)
+{
+ register struct dolnod* argr=blk;
+ register struct dolnod* argblk;
+ register Arg_t *ap = (Arg_t*)shp->arg_context;
+ if(argblk=argr)
+ {
+ if((--argblk->dolrefcnt)==0)
+ {
+ argr = argblk->dolnxt;
+ if(flag && argblk==ap->dolh)
+ ap->dolh->dolrefcnt = 1;
+ else
+ {
+ /* delete from chain */
+ if(ap->argfor == argblk)
+ ap->argfor = argblk->dolnxt;
+ else
+ {
+ for(argr=ap->argfor;argr;argr=argr->dolnxt)
+ if(argr->dolnxt==argblk)
+ break;
+ if(!argr)
+ return(NIL(struct dolnod*));
+ argr->dolnxt = argblk->dolnxt;
+ argr = argblk->dolnxt;
+ }
+ free((void*)argblk);
+ }
+ }
+ }
+ return(argr);
+}
+
+/*
+ * grab space for arglist and copy args
+ * The strings are copied after the argment vector
+ */
+struct dolnod *sh_argcreate(register char *argv[])
+{
+ register struct dolnod *dp;
+ register char **pp=argv, *sp;
+ register int size=0,n;
+ /* count args and number of bytes of arglist */
+ while(sp= *pp++)
+ size += strlen(sp);
+ n = (pp - argv)-1;
+ dp=new_of(struct dolnod,n*sizeof(char*)+size+n);
+ dp->dolrefcnt=1; /* use count */
+ dp->dolnum = n;
+ dp->dolnxt = 0;
+ pp = dp->dolval;
+ sp = (char*)dp + sizeof(struct dolnod) + n*sizeof(char*);
+ while(n--)
+ {
+ *pp++ = sp;
+ sp = strcopy(sp, *argv++) + 1;
+ }
+ *pp = NIL(char*);
+ return(dp);
+}
+
+/*
+ * used to set new arguments for functions
+ */
+struct dolnod *sh_argnew(Shell_t *shp,char *argi[], struct dolnod **savargfor)
+{
+ register Arg_t *ap = (Arg_t*)shp->arg_context;
+ register struct dolnod *olddolh = ap->dolh;
+ *savargfor = ap->argfor;
+ ap->dolh = 0;
+ ap->argfor = 0;
+ sh_argset(ap,argi);
+ return(olddolh);
+}
+
+/*
+ * reset arguments as they were before function
+ */
+void sh_argreset(Shell_t *shp,struct dolnod *blk, struct dolnod *afor)
+{
+ register Arg_t *ap = (Arg_t*)shp->arg_context;
+ while(ap->argfor=sh_argfree(shp,ap->argfor,0));
+ ap->argfor = afor;
+ if(ap->dolh = blk)
+ {
+ shp->st.dolc = ap->dolh->dolnum-1;
+ shp->st.dolv = ap->dolh->dolval;
+ }
+}
+
+/*
+ * increase the use count so that an sh_argset will not make it go away
+ */
+struct dolnod *sh_arguse(Shell_t* shp)
+{
+ register struct dolnod *dh;
+ register Arg_t *ap = (Arg_t*)shp->arg_context;
+ if(dh=ap->dolh)
+ dh->dolrefcnt++;
+ return(dh);
+}
+
+/*
+ * Print option settings on standard output
+ * if mode is inclusive or of PRINT_*
+ * if <mask> is set, only options with this mask value are displayed
+ */
+void sh_printopts(Shopt_t oflags,register int mode, Shopt_t *mask)
+{
+ register const Shtable_t *tp;
+ const char *name;
+ int on;
+ int value;
+ if(!(mode&PRINT_NO_HEADER))
+ sfputr(sfstdout,sh_translate(e_heading),'\n');
+ if(mode&PRINT_TABLE)
+ {
+ int w;
+ int c;
+ int r;
+ int i;
+
+ c = 0;
+ for(tp=shtab_options; value=tp->sh_number; tp++)
+ {
+ if(mask && !is_option(mask,value&0xff))
+ continue;
+ name = tp->sh_name;
+ if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
+ name += 2;
+ if(c<(w=strlen(name)))
+ c = w;
+ }
+ c += 4;
+ if((w = ed_window()) < (2*c))
+ w = 2*c;
+ r = w / c;
+ i = 0;
+ for(tp=shtab_options; value=tp->sh_number; tp++)
+ {
+ if(mask && !is_option(mask,value&0xff))
+ continue;
+ on = !!is_option(&oflags,value);
+ value &= 0xff;
+ name = tp->sh_name;
+ if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
+ {
+ name += 2;
+ on = !on;
+ }
+ if(++i>=r)
+ {
+ i = 0;
+ sfprintf(sfstdout, "%s%s\n", on ? "" : "no", name);
+ }
+ else
+ sfprintf(sfstdout, "%s%-*s", on ? "" : "no", on ? c : (c-2), name);
+ }
+ if(i)
+ sfputc(sfstdout,'\n');
+ return;
+ }
+#if SHOPT_RAWONLY
+ on_option(&oflags,SH_VIRAW);
+#endif
+ if(!(mode&(PRINT_ALL|PRINT_VERBOSE))) /* only print set options */
+ {
+ if(mode&PRINT_SHOPT)
+ sfwrite(sfstdout,"shopt -s",3);
+ else
+ sfwrite(sfstdout,"set --default",13);
+ }
+ for(tp=shtab_options; value=tp->sh_number; tp++)
+ {
+ if(mask && !is_option(mask,value&0xff))
+ continue;
+ if(sh_isoption(SH_BASH))
+ {
+ if (!(mode&PRINT_SHOPT) != !(value&SH_BASHOPT))
+ continue;
+ }
+ else if (value&(SH_BASHEXTRA|SH_BASHOPT))
+ continue;
+ on = !!is_option(&oflags,value);
+ name = tp->sh_name;
+ if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
+ {
+ name += 2;
+ on = !on;
+ }
+ if(mode&PRINT_VERBOSE)
+ {
+ sfputr(sfstdout,name,' ');
+ sfnputc(sfstdout,' ',24-strlen(name));
+ sfputr(sfstdout,on ? sh_translate(e_on) : sh_translate(e_off),'\n');
+ }
+ else if(mode&PRINT_ALL) /* print unset options also */
+ {
+ if(mode&PRINT_SHOPT)
+ sfprintf(sfstdout, "shopt -%c %s\n",
+ on?'s':'u',
+ name);
+ else
+ sfprintf(sfstdout, "set %co %s\n",
+ on?'-':'+',
+ name);
+ }
+ else if(!(value&SH_COMMANDLINE) && is_option(&oflags,value&0xff))
+ sfprintf(sfstdout," %s%s%s",(mode&PRINT_SHOPT)?"":"--",on?"":"no",name);
+ }
+ if(!(mode&(PRINT_VERBOSE|PRINT_ALL)))
+ sfputc(sfstdout,'\n');
+}
+
+/*
+ * build an argument list
+ */
+char **sh_argbuild(Shell_t *shp,int *nargs, const struct comnod *comptr,int flag)
+{
+ register struct argnod *argp;
+ struct argnod *arghead=0;
+ shp->xargmin = 0;
+ {
+ register const struct comnod *ac = comptr;
+ register int n;
+ /* see if the arguments have already been expanded */
+ if(!ac->comarg)
+ {
+ *nargs = 0;
+ return(&null);
+ }
+ else if(!(ac->comtyp&COMSCAN))
+ {
+ register struct dolnod *ap = (struct dolnod*)ac->comarg;
+ *nargs = ap->dolnum;
+ return(ap->dolval+ap->dolbot);
+ }
+ shp->lastpath = 0;
+ *nargs = 0;
+ if(ac)
+ {
+ if(ac->comnamp == SYSLET)
+ flag |= ARG_LET;
+ argp = ac->comarg;
+ while(argp)
+ {
+ n = arg_expand(shp,argp,&arghead,flag);
+ if(n>1)
+ {
+ if(shp->xargmin==0)
+ shp->xargmin = *nargs;
+ shp->xargmax = *nargs+n;
+ }
+ *nargs += n;
+ argp = argp->argnxt.ap;
+ }
+ argp = arghead;
+ }
+ }
+ {
+ register char **comargn;
+ register int argn;
+ register char **comargm;
+ argn = *nargs;
+ /* allow room to prepend args */
+ argn += 1;
+
+ comargn=(char**)stkalloc(shp->stk,(unsigned)(argn+1)*sizeof(char*));
+ comargm = comargn += argn;
+ *comargn = NIL(char*);
+ if(!argp)
+ {
+ /* reserve an extra null pointer */
+ *--comargn = 0;
+ return(comargn);
+ }
+ while(argp)
+ {
+ struct argnod *nextarg = argp->argchn.ap;
+ argp->argchn.ap = 0;
+ *--comargn = argp->argval;
+ if(!(argp->argflag&ARG_RAW))
+ sh_trim(*comargn);
+ if(!(argp=nextarg) || (argp->argflag&ARG_MAKE))
+ {
+ if((argn=comargm-comargn)>1)
+ strsort(comargn,argn,strcoll);
+ comargm = comargn;
+ }
+ }
+ shp->last_table = 0;
+ return(comargn);
+ }
+}
+
+#if _pipe_socketpair && !_socketpair_devfd
+# define sh_pipe arg_pipe
+/*
+ * create a real pipe (not a socket) and print message on failure
+ */
+static int arg_pipe(register int pv[])
+{
+ Shell_t *shp = sh_getinterp();
+ int fd[2];
+ if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0)
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
+ pv[0] = sh_iomovefd(pv[0]);
+ pv[1] = sh_iomovefd(pv[1]);
+ shp->fdstatus[pv[0]] = IONOSEEK|IOREAD;
+ shp->fdstatus[pv[1]] = IONOSEEK|IOWRITE;
+ sh_subsavefd(pv[0]);
+ sh_subsavefd(pv[1]);
+ return(0);
+}
+#endif
+
+struct argnod *sh_argprocsub(Shell_t *shp,struct argnod *argp)
+{
+ /* argument of the form <(cmd) or >(cmd) */
+ register struct argnod *ap;
+ int monitor, fd, pv[3];
+ int subshell = shp->subshell;
+ ap = (struct argnod*)stkseek(shp->stk,ARGVAL);
+ ap->argflag |= ARG_MAKE;
+ ap->argflag &= ~ARG_RAW;
+ fd = argp->argflag&ARG_RAW;
+ if(fd==0 && shp->subshell)
+ sh_subtmpfile(shp);
+#if SHOPT_DEVFD
+ sfwrite(shp->stk,e_devfdNN,8);
+ pv[2] = 0;
+ sh_pipe(pv);
+#else
+ pv[0] = -1;
+ shp->fifo = pathtemp(0,0,0,"ksh.fifo",0);
+ mkfifo(shp->fifo,S_IRUSR|S_IWUSR);
+ sfputr(shp->stk,shp->fifo,0);
+#endif /* SHOPT_DEVFD */
+ sfputr(shp->stk,fmtbase((long)pv[fd],10,0),0);
+ ap = (struct argnod*)stkfreeze(shp->stk,0);
+ shp->inpipe = shp->outpipe = 0;
+ if(monitor = (sh_isstate(SH_MONITOR)!=0))
+ sh_offstate(SH_MONITOR);
+ shp->subshell = 0;
+ if(fd)
+ {
+ shp->inpipe = pv;
+ sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT));
+ }
+ else
+ {
+ shp->outpipe = pv;
+ sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT));
+ }
+ shp->subshell = subshell;
+ if(monitor)
+ sh_onstate(SH_MONITOR);
+#if SHOPT_DEVFD
+ close(pv[1-fd]);
+ sh_iosave(shp,-pv[fd], shp->topfd, (char*)0);
+#else
+ free(shp->fifo);
+ shp->fifo = 0;
+#endif /* SHOPT_DEVFD */
+ return(ap);
+}
+
+/* Argument expansion */
+static int arg_expand(Shell_t *shp,register struct argnod *argp, struct argnod **argchain,int flag)
+{
+ register int count = 0;
+ argp->argflag &= ~ARG_MAKE;
+ if(*argp->argval==0 && (argp->argflag&ARG_EXP))
+ {
+ struct argnod *ap;
+ ap = sh_argprocsub(shp,argp);
+ ap->argchn.ap = *argchain;
+ *argchain = ap;
+ count++;
+ }
+ else
+ if(!(argp->argflag&ARG_RAW))
+ {
+#if SHOPT_OPTIMIZE
+ struct argnod *ap;
+ sh_stats(STAT_ARGEXPAND);
+ if(flag&ARG_OPTIMIZE)
+ argp->argchn.ap=0;
+ if(ap=argp->argchn.ap)
+ {
+ sh_stats(STAT_ARGHITS);
+ count = 1;
+ ap->argchn.ap = *argchain;
+ ap->argflag |= ARG_RAW;
+ ap->argflag &= ~ARG_EXP;
+ *argchain = ap;
+ }
+ else
+#endif /* SHOPT_OPTIMIZE */
+ count = sh_macexpand(shp,argp,argchain,flag);
+ }
+ else
+ {
+ argp->argchn.ap = *argchain;
+ *argchain = argp;
+ argp->argflag |= ARG_MAKE;
+ count++;
+ }
+ return(count);
+}
+
diff --git a/src/cmd/ksh93/sh/arith.c b/src/cmd/ksh93/sh/arith.c
new file mode 100644
index 0000000..f1814fa
--- /dev/null
+++ b/src/cmd/ksh93/sh/arith.c
@@ -0,0 +1,549 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Shell arithmetic - uses streval library
+ * David Korn
+ * AT&T Labs
+ */
+
+#include "defs.h"
+#include "lexstates.h"
+#include "name.h"
+#include "streval.h"
+#include "variables.h"
+#include "builtins.h"
+
+#ifndef LLONG_MAX
+#define LLONG_MAX LONG_MAX
+#endif
+
+typedef Sfdouble_t (*Math_f)(Sfdouble_t, ...);
+
+extern const Namdisc_t ENUM_disc;
+static Sfdouble_t NaN, Inf, Fun;
+static Namval_t Infnod =
+{
+ { 0 },
+ "Inf",
+ NV_NOFREE|NV_LDOUBLE,NV_RDONLY
+};
+
+static Namval_t NaNnod =
+{
+ { 0 },
+ "NaN",
+ NV_NOFREE|NV_LDOUBLE,NV_RDONLY
+};
+
+static Namval_t FunNode =
+{
+ { 0 },
+ "?",
+ NV_NOFREE|NV_LDOUBLE,NV_RDONLY
+};
+
+static Namval_t *scope(register Namval_t *np,register struct lval *lvalue,int assign)
+{
+ register int flag = lvalue->flag;
+ register char *sub=0, *cp=(char*)np;
+ register Namval_t *mp;
+ Shell_t *shp = lvalue->shp;
+ int flags = HASH_NOSCOPE|HASH_SCOPE|HASH_BUCKET;
+ int c=0,nosub = lvalue->nosub;
+ Dt_t *sdict = (shp->st.real_fun? shp->st.real_fun->sdict:0);
+ Dt_t *nsdict = (shp->namespace?nv_dict(shp->namespace):0);
+ Dt_t *root = shp->var_tree;
+ assign = assign?NV_ASSIGN:NV_NOASSIGN;
+ lvalue->nosub = 0;
+ if(nosub<0 && lvalue->ovalue)
+ return((Namval_t*)lvalue->ovalue);
+ lvalue->ovalue = 0;
+ if(cp>=lvalue->expr && cp < lvalue->expr+lvalue->elen)
+ {
+ int offset;
+ /* do binding to node now */
+ int c = cp[flag];
+ cp[flag] = 0;
+ if((!(np = nv_open(cp,shp->var_tree,assign|NV_VARNAME|NV_NOADD|NV_NOFAIL)) || nv_isnull(np)) && sh_macfun(shp,cp, offset = staktell()))
+ {
+ Fun = sh_arith(shp,sub=stakptr(offset));
+ FunNode.nvalue.ldp = &Fun;
+ cp[flag] = c;
+ return(&FunNode);
+ }
+ if(!np && assign)
+ np = nv_open(cp,shp->var_tree,assign|NV_VARNAME);
+ cp[flag] = c;
+ if(!np)
+ return(0);
+ root = shp->last_root;
+ if(cp[flag+1]=='[')
+ flag++;
+ else
+ flag = 0;
+ cp = (char*)np;
+ }
+ else if(assign==NV_ASSIGN && nv_isnull(np) && !nv_isattr(np, ~(NV_MINIMAL|NV_NOFREE)))
+ flags |= NV_ADD;
+ if((lvalue->emode&ARITH_COMP) && dtvnext(root) && ((sdict && (mp=nv_search(cp,sdict,flags&~NV_ADD))) || (mp=nv_search(cp,root,flags&~(NV_ADD))) || (nsdict && (mp=nv_search(cp,nsdict,flags&~(NV_ADD|HASH_NOSCOPE)))) ))
+ np = mp;
+ while(nv_isref(np))
+ {
+#if SHOPT_FIXEDARRAY
+ int n,dim;
+ dim = nv_refdimen(np);
+ n = nv_refindex(np);
+#endif /* SHOPT_FIXEDARRAY */
+ sub = nv_refsub(np);
+ np = nv_refnode(np);
+#if SHOPT_FIXEDARRAY
+ if(n)
+ {
+ Namarr_t *ap = nv_arrayptr(np);
+ ap->nelem = dim;
+ nv_putsub(np,(char*)0,n);
+ }
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if(sub)
+ nv_putsub(np,sub,assign==NV_ASSIGN?ARRAY_ADD:0);
+ }
+ if(!nosub && flag)
+ {
+ int hasdot = 0;
+ cp = (char*)&lvalue->expr[flag];
+ if(sub)
+ {
+ goto skip;
+ }
+ sub = cp;
+ while(1)
+ {
+ Namarr_t *ap;
+ Namval_t *nq;
+ cp = nv_endsubscript(np,cp,0);
+ if(c || *cp=='.')
+ {
+ c = '.';
+ while(*cp=='.')
+ {
+ hasdot=1;
+ cp++;
+ while(c=mbchar(cp),isaname(c));
+ }
+ if(c=='[')
+ continue;
+ }
+ flag = *cp;
+ *cp = 0;
+ if(c || hasdot)
+ {
+ sfprintf(shp->strbuf,"%s%s%c",nv_name(np),sub,0);
+ sub = sfstruse(shp->strbuf);
+ }
+ if(strchr(sub,'$'))
+ sub = sh_mactrim(shp,sub,0);
+ *cp = flag;
+ if(c || hasdot)
+ {
+ np = nv_open(sub,shp->var_tree,NV_VARNAME|assign);
+ return(np);
+ }
+#if SHOPT_FIXEDARRAY
+ ap = nv_arrayptr(np);
+ cp = nv_endsubscript(np,sub,NV_ADD|NV_SUBQUOTE|(ap&&ap->fixed?NV_FARRAY:0));
+#else
+ cp = nv_endsubscript(np,sub,NV_ADD|NV_SUBQUOTE);
+#endif /* SHOPT_FIXEDARRAY */
+ if(*cp!='[')
+ break;
+ skip:
+ if(nq = nv_opensub(np))
+ np = nq;
+ else
+ {
+ ap = nv_arrayptr(np);
+ if(ap && !ap->table)
+ ap->table = dtopen(&_Nvdisc,Dtoset);
+ if(ap && ap->table && (nq=nv_search(nv_getsub(np),ap->table,NV_ADD)))
+ nq->nvenv = (char*)np;
+ if(nq && nv_isnull(nq))
+ np = nv_arraychild(np,nq,0);
+ }
+ sub = cp;
+ }
+ }
+ else if(nosub>0)
+ nv_putsub(np,(char*)0,nosub-1);
+ return(np);
+}
+
+static Math_f sh_mathstdfun(const char *fname, size_t fsize, short * nargs)
+{
+ register const struct mathtab *tp;
+ register char c = fname[0];
+ for(tp=shtab_math; *tp->fname; tp++)
+ {
+ if(*tp->fname > c)
+ break;
+ if(tp->fname[1]==c && tp->fname[fsize+1]==0 && strncmp(&tp->fname[1],fname,fsize)==0)
+ {
+ if(nargs)
+ *nargs = *tp->fname;
+ return(tp->fnptr);
+ }
+ }
+ return(0);
+}
+
+int sh_mathstd(const char *name)
+{
+ return(sh_mathstdfun(name,strlen(name),NULL)!=0);
+}
+
+static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdouble_t n)
+{
+ Shell_t *shp = lvalue->shp;
+ register Sfdouble_t r= 0;
+ char *str = (char*)*ptr;
+ register char *cp;
+ switch(type)
+ {
+ case ASSIGN:
+ {
+ register Namval_t *np = (Namval_t*)(lvalue->value);
+ np = scope(np,lvalue,1);
+ nv_putval(np, (char*)&n, NV_LDOUBLE);
+ if(lvalue->eflag)
+ lvalue->ptr = (void*)nv_hasdisc(np,&ENUM_disc);
+ lvalue->eflag = 0;
+ r=nv_getnum(np);
+ lvalue->value = (char*)np;
+ break;
+ }
+ case LOOKUP:
+ {
+ register int c = *str;
+ register char *xp=str;
+ lvalue->value = (char*)0;
+ if(c=='.')
+ str++;
+ c = mbchar(str);
+ if(isaletter(c))
+ {
+ register Namval_t *np;
+ int dot=0;
+ while(1)
+ {
+ while(xp=str, c=mbchar(str), isaname(c));
+ str = xp;
+ while(c=='[' && dot==NV_NOADD)
+ {
+ str = nv_endsubscript((Namval_t*)0,str,0);
+ c = *str;
+ }
+ if(c!='.')
+ break;
+ dot=NV_NOADD;
+ if((c = *++str) !='[')
+ continue;
+ str = nv_endsubscript((Namval_t*)0,cp=str,NV_SUBQUOTE)-1;
+ if(sh_checkid(cp+1,(char*)0))
+ str -=2;
+ }
+ if(c=='(')
+ {
+ int off=stktell(shp->stk);
+ int fsize = str- (char*)(*ptr);
+ const struct mathtab *tp;
+ Namval_t *np;
+ c = **ptr;
+ lvalue->fun = 0;
+ sfprintf(shp->stk,".sh.math.%.*s%c",fsize,*ptr,0);
+ stkseek(shp->stk,off);
+ if(np=nv_search(stkptr(shp->stk,off),shp->fun_tree,0))
+ {
+ lvalue->nargs = -np->nvalue.rp->argc;
+ lvalue->fun = (Math_f)np;
+ break;
+ }
+ if(fsize<=(sizeof(tp->fname)-2))
+ lvalue->fun = (Math_f)sh_mathstdfun(*ptr,fsize,&lvalue->nargs);
+ if(lvalue->fun)
+ break;
+ if(lvalue->emode&ARITH_COMP)
+ lvalue->value = (char*)e_function;
+ else
+ lvalue->value = (char*)ERROR_dictionary(e_function);
+ return(r);
+ }
+ if((lvalue->emode&ARITH_COMP) && dot)
+ {
+ lvalue->value = (char*)*ptr;
+ lvalue->flag = str-lvalue->value;
+ break;
+ }
+ *str = 0;
+ if(sh_isoption(SH_NOEXEC))
+ np = L_ARGNOD;
+ else
+ {
+ int offset = staktell();
+ char *saveptr = stakfreeze(0);
+ Dt_t *root = (lvalue->emode&ARITH_COMP)?shp->var_base:shp->var_tree;
+ *str = c;
+ cp = str;
+ while(c=='[' || c=='.')
+ {
+ if(c=='[')
+ {
+ str = nv_endsubscript(np,str,0);
+ if((c= *str)!='[' && c!='.')
+ {
+ str = cp;
+ c = '[';
+ break;
+ }
+ }
+ else
+ {
+ dot = NV_NOADD|NV_NOFAIL;
+ str++;
+ while(xp=str, c=mbchar(str), isaname(c));
+ str = xp;
+ }
+ }
+ *str = 0;
+ cp = (char*)*ptr;
+ if ((cp[0] == 'i' || cp[0] == 'I') && (cp[1] == 'n' || cp[1] == 'N') && (cp[2] == 'f' || cp[2] == 'F') && cp[3] == 0)
+ {
+ Inf = strtold("Inf", NiL);
+ Infnod.nvalue.ldp = &Inf;
+ np = &Infnod;
+ }
+ else if ((cp[0] == 'n' || cp[0] == 'N') && (cp[1] == 'a' || cp[1] == 'A') && (cp[2] == 'n' || cp[2] == 'N') && cp[3] == 0)
+ {
+ NaN = strtold("NaN", NiL);
+ NaNnod.nvalue.ldp = &NaN;
+ np = &NaNnod;
+ }
+ else if(!(np = nv_open(*ptr,root,NV_NOREF|NV_NOASSIGN|NV_VARNAME|dot)))
+ {
+ lvalue->value = (char*)*ptr;
+ lvalue->flag = str-lvalue->value;
+ }
+ if(saveptr != stakptr(0))
+ stakset(saveptr,offset);
+ else
+ stakseek(offset);
+ }
+ *str = c;
+ if(!np && lvalue->value)
+ break;
+ lvalue->value = (char*)np;
+ /* bind subscript later */
+ if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
+ lvalue->isfloat=1;
+ lvalue->flag = 0;
+ if(c=='[')
+ {
+ lvalue->flag = (str-lvalue->expr);
+ do
+ {
+ while(c=='.')
+ {
+ str++;
+ while(xp=str, c=mbchar(str), isaname(c));
+ c = *(str = xp);
+ }
+ if(c=='[')
+ str = nv_endsubscript(np,str,0);
+ }
+ while((c= *str)=='[' || c=='.');
+ break;
+ }
+ }
+ else
+ {
+ char lastbase=0, *val = xp, oerrno = errno;
+ lvalue->eflag = 0;
+ errno = 0;
+ if(shp->bltindata.bnode==SYSLET && !sh_isoption(SH_LETOCTAL))
+ {
+ while(*val=='0' && isdigit(val[1]))
+ val++;
+ }
+ r = strtonll(val,&str, &lastbase,-1);
+ if(*str=='8' || *str=='9')
+ {
+ lastbase=10;
+ errno = 0;
+ r = strtonll(val,&str, &lastbase,-1);
+ }
+ if(lastbase<=1)
+ lastbase=10;
+ if(*val=='0')
+ {
+ while(*val=='0')
+ val++;
+ if(*val==0 || *val=='.' || *val=='x' || *val=='X')
+ val--;
+ }
+ if(r==LLONG_MAX && errno)
+ c='e';
+ else
+ c = *str;
+ if(c==GETDECIMAL(0) || c=='e' || c == 'E' || lastbase ==
+ 16 && (c == 'p' || c == 'P'))
+ {
+ lvalue->isfloat=1;
+ r = strtold(val,&str);
+ }
+ else if(lastbase==10 && val[1])
+ {
+ if(val[2]=='#')
+ val += 3;
+ if((str-val)>2*sizeof(Sflong_t))
+ {
+ Sfdouble_t rr;
+ rr = strtold(val,&str);
+ if(rr!=r)
+ {
+ r = rr;
+ lvalue->isfloat=1;
+ }
+ }
+ }
+ errno = oerrno;
+ }
+ break;
+ }
+ case VALUE:
+ {
+ register Namval_t *np = (Namval_t*)(lvalue->value);
+ if(sh_isoption(SH_NOEXEC))
+ return(0);
+ np = scope(np,lvalue,0);
+ if(!np)
+ {
+ if(sh_isoption(SH_NOUNSET))
+ {
+ *ptr = lvalue->value;
+ goto skip;
+ }
+ return(0);
+ }
+ lvalue->ovalue = (char*)np;
+ if(lvalue->eflag)
+ lvalue->ptr = (void*)nv_hasdisc(np,&ENUM_disc);
+ else if((Namfun_t*)lvalue->ptr && !nv_hasdisc(np,&ENUM_disc) && !nv_isattr(np,NV_INTEGER))
+ {
+ Namval_t *mp,node;
+ mp = ((Namfun_t*)lvalue->ptr)->type;
+ memset(&node,0,sizeof(node));
+ nv_clone(mp,&node,0);
+ nv_offattr(&node,NV_RDONLY|NV_NOFREE);
+ nv_putval(&node,np->nvname,0);
+ if(nv_isattr(&node,NV_NOFREE))
+ return(r=nv_getnum(&node));
+ }
+ lvalue->eflag = 0;
+ if(((lvalue->emode&2) || lvalue->level>1 || sh_isoption(SH_NOUNSET)) && nv_isnull(np) && !nv_isattr(np,NV_INTEGER))
+ {
+ *ptr = nv_name(np);
+ skip:
+ lvalue->value = (char*)ERROR_dictionary(e_notset);
+ lvalue->emode |= 010;
+ return(0);
+ }
+ r = nv_getnum(np);
+ if(nv_isattr(np,NV_INTEGER|NV_BINARY)==(NV_INTEGER|NV_BINARY))
+ lvalue->isfloat= (r!=(Sflong_t)r);
+ else if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
+ lvalue->isfloat=1;
+ if((lvalue->emode&ARITH_ASSIGNOP) && nv_isarray(np))
+ lvalue->nosub = nv_aindex(np)+1;
+ return(r);
+ }
+
+ case MESSAGE:
+ sfsync(NIL(Sfio_t*));
+#if 0
+ if(warn)
+ errormsg(SH_DICT,ERROR_warn(0),lvalue->value,*ptr);
+ else
+#endif
+ if(lvalue->emode&ARITH_COMP)
+ return(-1);
+
+ errormsg(SH_DICT,ERROR_exit((lvalue->emode&3)!=0),lvalue->value,*ptr);
+ }
+ *ptr = str;
+ return(r);
+}
+
+/*
+ * convert number defined by string to a Sfdouble_t
+ * ptr is set to the last character processed
+ * if mode>0, an error will be fatal with value <mode>
+ */
+
+Sfdouble_t sh_strnum(register const char *str, char** ptr, int mode)
+{
+ Shell_t *shp = sh_getinterp();
+ register Sfdouble_t d;
+ char base=(shp->inarith?0:10), *last;
+ if(*str==0)
+ {
+ if(ptr)
+ *ptr = (char*)str;
+ return(0);
+ }
+ errno = 0;
+ d = strtonll(str,&last,&base,-1);
+ if(*last || errno)
+ {
+ if(!last || *last!='.' || last[1]!='.')
+ d = strval(shp,str,&last,arith,mode);
+ if(!ptr && *last && mode>0)
+ errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*last,str);
+ }
+ else if (!d && *str=='-')
+ d = -0.0;
+ if(ptr)
+ *ptr = last;
+ return(d);
+}
+
+Sfdouble_t sh_arith(Shell_t *shp,register const char *str)
+{
+ return(sh_strnum(str, (char**)0, 1));
+}
+
+void *sh_arithcomp(Shell_t *shp,register char *str)
+{
+ const char *ptr = str;
+ Arith_t *ep;
+ ep = arith_compile(shp,str,(char**)&ptr,arith,ARITH_COMP|1);
+ if(*ptr)
+ errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*ptr,str);
+ return((void*)ep);
+}
diff --git a/src/cmd/ksh93/sh/array.c b/src/cmd/ksh93/sh/array.c
new file mode 100644
index 0000000..658d5a2
--- /dev/null
+++ b/src/cmd/ksh93/sh/array.c
@@ -0,0 +1,1843 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Array processing routines
+ *
+ * David Korn
+ * AT&T Labs
+ * dgk@research.att.com
+ *
+ */
+
+#include "defs.h"
+#include <stak.h>
+#include "name.h"
+
+#define NUMSIZE (4+(ARRAY_MAX>999)+(ARRAY_MAX>9999)+(ARRAY_MAX>99999))
+#define is_associative(ap) array_assoc((Namarr_t*)(ap))
+#define array_setbit(cp, n, b) (cp[n] |= (b))
+#define array_clrbit(cp, n, b) (cp[n] &= ~(b))
+#define array_isbit(cp, n, b) (cp[n] & (b))
+#define NV_CHILD NV_EXPORT
+#define ARRAY_CHILD 1
+#define ARRAY_NOFREE 2
+
+struct index_array
+{
+ Namarr_t header;
+ void *xp; /* if set, subscripts will be converted */
+ int cur; /* index of current element */
+ int maxi; /* maximum index for array */
+ unsigned char *bits; /* bit array for child subscripts */
+ union Value val[1]; /* array of value holders */
+};
+
+struct assoc_array
+{
+ Namarr_t header;
+ Namval_t *pos;
+ Namval_t *nextpos;
+ Namval_t *cur;
+};
+
+#if SHOPT_FIXEDARRAY
+ struct fixed_array
+ {
+ unsigned char ndim;
+ unsigned char dim;
+ unsigned char level;
+ unsigned char ptr;
+ short size;
+ int nelem;
+ int curi;
+ int *max;
+ int *incr;
+ int *cur;
+ char *data;
+ };
+# define array_fixed_data(ap) ((ap)?((struct fixed_array*)((ap)->fixed))->data:0)
+ static void array_fixed_setdata(Namval_t*,Namarr_t*,struct fixed_array*);
+#endif /* SHOPT_FIXEDARRAY */
+
+static Namarr_t *array_scope(Namval_t *np, Namarr_t *ap, int flags)
+{
+ Namarr_t *aq;
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp;
+#endif /* SHOPT_FIXEDARRAY */
+ struct index_array *ar;
+ size_t size = ap->hdr.dsize;
+ if(size==0)
+ size = ap->hdr.disc->dsize;
+ if(!(aq=newof(NIL(Namarr_t*),Namarr_t,1,size-sizeof(Namarr_t))))
+ return(0);
+ memcpy(aq,ap,size);
+ aq->hdr.nofree &= ~1;
+ aq->hdr.nofree |= (flags&NV_RDONLY)?1:0;
+ if(is_associative(aq))
+ {
+ aq->scope = (void*)dtopen(&_Nvdisc,Dtoset);
+ dtview((Dt_t*)aq->scope,aq->table);
+ aq->table = (Dt_t*)aq->scope;
+ return(aq);
+ }
+#if SHOPT_FIXEDARRAY
+ else if(fp = (struct fixed_array*)ap->fixed)
+ {
+ aq->scope = (void*)ap;
+ fp = (struct fixed_array*)(aq+1);
+ aq->fixed = (void*)fp;
+ fp->max = (int*)(fp+1);
+ fp->incr = fp->max+fp->ndim;
+ fp->cur = fp->incr+fp->ndim;
+ return(aq);
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ aq->scope = (void*)ap;
+ ar = (struct index_array*)aq;
+ memset(ar->val, 0, ar->maxi*sizeof(char*));
+ ar->bits = (unsigned char*)&ar->val[ar->maxi];
+ return(aq);
+}
+
+static int array_unscope(Namval_t *np,Namarr_t *ap)
+{
+ Namfun_t *fp;
+ if(!ap->scope)
+ return(0);
+ if(is_associative(ap))
+ (*ap->fun)(np, NIL(char*), NV_AFREE);
+ if((fp = nv_disc(np,(Namfun_t*)ap,NV_POP)) && !(fp->nofree&1))
+ free((void*)fp);
+ nv_delete(np,(Dt_t*)0,0);
+ return(1);
+}
+
+static void array_syncsub(Namarr_t *ap, Namarr_t *aq)
+{
+ ((struct index_array*)ap)->cur = ((struct index_array*)aq)->cur;
+}
+
+static int array_covered(Namval_t *np, struct index_array *ap)
+{
+ struct index_array *aq = (struct index_array*)ap->header.scope;
+ if(!ap->header.fun && aq)
+#if SHOPT_FIXEDARRAY
+ return (ap->header.fixed || ((ap->cur<aq->maxi) && aq->val[ap->cur].cp));
+#else
+ return ((ap->cur<aq->maxi) && aq->val[ap->cur].cp);
+#endif /* SHOPT_FIXEDARRAY */
+ return(0);
+}
+
+/*
+ * replace discipline with new one
+ */
+static void array_setptr(register Namval_t *np, struct index_array *old, struct index_array *new)
+{
+ register Namfun_t **fp = &np->nvfun;
+ while(*fp && *fp!= &old->header.hdr)
+ fp = &((*fp)->next);
+ if(*fp)
+ {
+ new->header.hdr.next = (*fp)->next;
+ *fp = &new->header.hdr;
+ }
+ else sfprintf(sfstderr,"discipline not replaced\n");
+}
+
+/*
+ * Calculate the amount of space to be allocated to hold an
+ * indexed array into which <maxi> is a legal index. The number of
+ * elements that will actually fit into the array (> <maxi>
+ * but <= ARRAY_MAX) is returned.
+ *
+ */
+static int arsize(struct index_array *ap, register int maxi)
+{
+ if(ap && maxi < 2*ap->maxi)
+ maxi = 2*ap->maxi;
+ maxi = roundof(maxi,ARRAY_INCR);
+ return (maxi>ARRAY_MAX?ARRAY_MAX:maxi);
+}
+
+static struct index_array *array_grow(Namval_t*, struct index_array*,int);
+
+/* return index of highest element of an array */
+int array_maxindex(Namval_t *np)
+{
+ register struct index_array *ap = (struct index_array*)nv_arrayptr(np);
+ register int i = ap->maxi;
+ if(is_associative(ap))
+ return(-1);
+ while(i>0 && ap->val[--i].cp==0);
+ return(i+1);
+}
+
+static union Value *array_getup(Namval_t *np, Namarr_t *arp, int update)
+{
+ register struct index_array *ap = (struct index_array*)arp;
+ register union Value *up;
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp;
+#endif /* SHOPT_FIXEDARRAY */
+ int nofree;
+ if(!arp)
+ return(&np->nvalue);
+ if(is_associative(ap))
+ {
+ Namval_t *mp;
+ mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT));
+ if(mp)
+ {
+ nofree = nv_isattr(mp,NV_NOFREE);
+ up = &mp->nvalue;
+ }
+ else
+ return((union Value*)((*arp->fun)(np,NIL(char*),0)));
+ }
+#if SHOPT_FIXEDARRAY
+ else if(fp = (struct fixed_array*)arp->fixed)
+ {
+ if(!fp->data)
+ array_fixed_setdata(np,arp,fp);
+ up = &np->nvalue;
+ if(fp->ptr)
+ up->cp = *(((char**)fp->data)+fp->curi);
+ else
+ up->cp = fp->data+fp->size*fp->curi;
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ else
+ {
+ if(ap->cur >= ap->maxi)
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np));
+ up = &(ap->val[ap->cur]);
+ nofree = array_isbit(ap->bits,ap->cur,ARRAY_NOFREE);
+ }
+ if(update)
+ {
+ if(nofree)
+ nv_onattr(np,NV_NOFREE);
+ else
+ nv_offattr(np,NV_NOFREE);
+ }
+ return(up);
+}
+
+int nv_arrayisset(Namval_t *np, Namarr_t *arp)
+{
+ register struct index_array *ap = (struct index_array*)arp;
+ union Value *up;
+ if(is_associative(ap))
+ return((np = nv_opensub(np)) && !nv_isnull(np));
+ if(ap->cur >= ap->maxi)
+ return(0);
+ up = &(ap->val[ap->cur]);
+ if(up->cp==Empty)
+ {
+ Namfun_t *fp = &arp->hdr;
+ for(fp=fp->next; fp; fp = fp->next)
+ {
+ if(fp->disc && (fp->disc->getnum || fp->disc->getval))
+ return(1);
+ }
+ }
+ return(up->cp && up->cp!=Empty);
+}
+
+/*
+ * Get the Value pointer for an array.
+ * Delete space as necessary if flag is ARRAY_DELETE
+ * After the lookup is done the last @ or * subscript is incremented
+ */
+static Namval_t *array_find(Namval_t *np,Namarr_t *arp, int flag)
+{
+ register struct index_array *ap = (struct index_array*)arp;
+ register union Value *up;
+ Namval_t *mp;
+ int wasundef;
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp=(struct fixed_array*)(arp->fixed);
+#endif /* SHOPT_FIXEDARRAY */
+ if(flag&ARRAY_LOOKUP)
+ ap->header.nelem &= ~ARRAY_NOSCOPE;
+ else
+ ap->header.nelem |= ARRAY_NOSCOPE;
+ if(wasundef = ap->header.nelem&ARRAY_UNDEF)
+ {
+ ap->header.nelem &= ~ARRAY_UNDEF;
+ /* delete array is the same as delete array[@] */
+ if(flag&ARRAY_DELETE)
+ {
+#if SHOPT_FIXEDARRAY
+ nv_putsub(np, NIL(char*), ARRAY_SCAN|ARRAY_NOSCOPE|(ap->header.fixed?(ARRAY_UNDEF|ARRAY_FIXED):0));
+#else
+ nv_putsub(np, NIL(char*), ARRAY_SCAN|ARRAY_NOSCOPE);
+#endif /* SHOPT_FIXEDARRAY */
+ ap->header.nelem |= ARRAY_SCAN;
+ }
+ else /* same as array[0] */
+ {
+ if(is_associative(ap))
+ (*ap->header.fun)(np,"0",flag==ARRAY_ASSIGN?NV_AADD:0);
+#if SHOPT_FIXEDARRAY
+ else if(fp)
+ {
+ int n=fp->ndim;
+ fp->curi = 0;
+ while(--n>=0)
+ fp->cur[n] = 0;
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ else
+ ap->cur = 0;
+ }
+ }
+ if(is_associative(ap))
+ {
+ mp = (Namval_t*)((*arp->fun)(np,NIL(char*),NV_ACURRENT));
+ if(!mp)
+ up = (union Value*)&mp;
+ else if(nv_isarray(mp))
+ {
+ if(wasundef)
+ nv_putsub(mp,NIL(char*),ARRAY_UNDEF);
+ return(mp);
+ }
+ else
+ {
+ up = &mp->nvalue;
+ if(nv_isvtree(mp))
+ {
+ if(!up->cp && flag==ARRAY_ASSIGN)
+ {
+ nv_arraychild(np,mp,0);
+ ap->header.nelem++;
+ }
+ return(mp);
+ }
+ }
+ }
+#if SHOPT_FIXEDARRAY
+ else if(fp)
+ {
+ char *data = array_fixed_data((Namarr_t*)ap->header.scope);
+ if(flag==ARRAY_ASSIGN && data==fp->data)
+ {
+ if(data)
+ {
+ fp->data = (char*)malloc(fp->nelem*fp->size);
+ memcpy(fp->data,data,fp->nelem*fp->size);
+ }
+ else
+ array_fixed_setdata(np,&ap->header,fp);
+ }
+ if(fp->ptr)
+ {
+ if(!fp->data)
+ array_fixed_setdata(np,&ap->header,fp);
+ np->nvalue.cp = *(((char**)fp->data)+fp->curi);
+ }
+ else
+ np->nvalue.cp = fp->data+fp->size*fp->curi;
+ return(np);
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ else
+ {
+ if(!(ap->header.nelem&ARRAY_SCAN) && ap->cur >= ap->maxi)
+ ap = array_grow(np, ap, (int)ap->cur);
+ if(ap->cur>=ap->maxi)
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript,nv_name(np));
+ up = &(ap->val[ap->cur]);
+ if((!up->cp||up->cp==Empty) && nv_type(np) && nv_isvtree(np))
+ {
+ char *cp;
+ if(!ap->header.table)
+ ap->header.table = dtopen(&_Nvdisc,Dtoset);
+ sfprintf(sh.strbuf,"%d",ap->cur);
+ cp = sfstruse(sh.strbuf);
+ mp = nv_search(cp, ap->header.table, NV_ADD);
+ mp->nvenv = (char*)np;
+ nv_arraychild(np,mp,0);
+ }
+ if(up->np && array_isbit(ap->bits,ap->cur,ARRAY_CHILD))
+ {
+ if(wasundef && nv_isarray(up->np))
+ nv_putsub(up->np,NIL(char*),ARRAY_UNDEF);
+ return(up->np);
+ }
+ }
+ np->nvalue.cp = up->cp;
+ if(!up->cp)
+ {
+ char *xp = nv_setdisc(np,"get",np,(Namfun_t*)np);
+ if(flag!=ARRAY_ASSIGN)
+ return(xp && xp!=(char*)np?np:0);
+ if(!array_covered(np,ap))
+ ap->header.nelem++;
+ }
+ return(np);
+}
+
+#if SHOPT_TYPEDEF
+int nv_arraysettype(Namval_t *np, Namval_t *tp, const char *sub, int flags)
+{
+ Namval_t *nq;
+ char *av[2];
+ int rdonly = nv_isattr(np,NV_RDONLY);
+ int xtrace = sh_isoption(SH_XTRACE);
+ Namarr_t *ap = nv_arrayptr(np);
+ av[1] = 0;
+ sh.last_table = 0;
+ if(!ap->table)
+ ap->table = dtopen(&_Nvdisc,Dtoset);
+ if(nq = nv_search(sub, ap->table, NV_ADD))
+ {
+ if(!nq->nvfun && nq->nvalue.cp && *nq->nvalue.cp==0)
+ _nv_unset(nq,NV_RDONLY);
+ nv_arraychild(np,nq,0);
+ if(!nv_isattr(tp,NV_BINARY))
+ {
+ sfprintf(sh.strbuf,"%s=%s",nv_name(nq),nv_getval(np));
+ av[0] = strdup(sfstruse(sh.strbuf));
+ }
+ if(!nv_clone(tp,nq,flags|NV_NOFREE))
+ return(0);
+ ap->nelem |= ARRAY_SCAN;
+ if(!rdonly)
+ nv_offattr(nq,NV_RDONLY);
+ if(!nv_isattr(tp,NV_BINARY))
+ {
+ if(xtrace)
+ sh_offoption(SH_XTRACE);
+ ap->nelem &= ~ARRAY_SCAN;
+ sh_eval(sh_sfeval(av),0);
+ ap->nelem |= ARRAY_SCAN;
+ free((void*)av[0]);
+ if(xtrace)
+ sh_onoption(SH_XTRACE);
+ }
+ return(1);
+ }
+ return(0);
+}
+#endif /* SHOPT_TYPEDEF */
+
+
+static Namfun_t *array_clone(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ Namarr_t *ap = (Namarr_t*)fp;
+ Namval_t *nq, *mq;
+ char *name, *sub=0;
+ int nelem, skipped=0;
+ Dt_t *otable=ap->table;
+ struct index_array *aq = (struct index_array*)ap, *ar;
+ Shell_t *shp = sh_getinterp();
+ if(flags&NV_MOVE)
+ {
+ if((flags&NV_COMVAR) && nv_putsub(np,NIL(char*),ARRAY_SCAN))
+ {
+ do
+ {
+ if(nq=nv_opensub(np))
+ nq->nvenv = (void*)mp;
+ }
+ while(nv_nextsub(np));
+ }
+ return(fp);
+ }
+ nelem = ap->nelem;
+ if(nelem&ARRAY_NOCLONE)
+ return(0);
+ if((flags&NV_TYPE) && !ap->scope)
+ {
+ ap = array_scope(np,ap,flags);
+ return(&ap->hdr);
+ }
+ ap = (Namarr_t*)nv_clone_disc(fp,0);
+ if(flags&NV_COMVAR)
+ {
+ ap->scope = 0;
+ ap->nelem = 0;
+ sh.prev_table = sh.last_table;
+ sh.prev_root = sh.last_root;
+ }
+ if(ap->table)
+ {
+ ap->table = dtopen(&_Nvdisc,Dtoset);
+ if(ap->scope && !(flags&NV_COMVAR))
+ {
+ ap->scope = ap->table;
+ dtview(ap->table, otable->view);
+ }
+ }
+ mp->nvfun = (Namfun_t*)ap;
+ mp->nvflag &= NV_MINIMAL;
+ mp->nvflag |= (np->nvflag&~(NV_MINIMAL|NV_NOFREE));
+ if(!(nelem&(ARRAY_SCAN|ARRAY_UNDEF)) && (sub=nv_getsub(np)))
+ sub = strdup(sub);
+ ar = (struct index_array*)ap;
+ if(!is_associative(ap))
+ ar->bits = (unsigned char*)&ar->val[ar->maxi];
+ if(!nv_putsub(np,NIL(char*),ARRAY_SCAN|((flags&NV_COMVAR)?0:ARRAY_NOSCOPE)))
+ {
+ if(ap->fun)
+ (*ap->fun)(np,(char*)np,0);
+ skipped=1;
+ goto skip;
+ }
+ do
+ {
+ name = nv_getsub(np);
+ nv_putsub(mp,name,ARRAY_ADD|ARRAY_NOSCOPE);
+ mq = 0;
+ if(nq=nv_opensub(np))
+ mq = nv_search(name,ap->table,NV_ADD);
+ if(nq && (((flags&NV_COMVAR) && nv_isvtree(nq)) || nv_isarray(nq)))
+ {
+ mq->nvalue.cp = 0;
+ if(!is_associative(ap))
+ ar->val[ar->cur].np = mq;
+ nv_clone(nq,mq,flags);
+ }
+ else if(flags&NV_ARRAY)
+ {
+ if((flags&NV_NOFREE) && !is_associative(ap))
+ array_setbit(aq->bits,aq->cur,ARRAY_NOFREE);
+ else if(nq && (flags&NV_NOFREE))
+ {
+ mq->nvalue = nq->nvalue;
+ nv_onattr(nq,NV_NOFREE);
+ }
+ }
+ else if(nv_isattr(np,NV_INTEGER))
+ {
+ Sfdouble_t d= nv_getnum(np);
+ if(!is_associative(ap))
+ ar->val[ar->cur].cp = 0;
+ nv_putval(mp,(char*)&d,NV_LDOUBLE);
+ }
+ else
+ {
+ if(!is_associative(ap))
+ ar->val[ar->cur].cp = 0;
+ nv_putval(mp,nv_getval(np),NV_RDONLY);
+ }
+ aq->header.nelem |= ARRAY_NOSCOPE;
+ }
+ while(nv_nextsub(np));
+skip:
+ if(sub)
+ {
+ if(!skipped)
+ nv_putsub(np,sub,0L);
+ free((void*)sub);
+ }
+ aq->header.nelem = ap->nelem = nelem;
+ return(&ap->hdr);
+}
+
+static char *array_getval(Namval_t *np, Namfun_t *disc)
+{
+ register Namarr_t *aq,*ap = (Namarr_t*)disc;
+ register Namval_t *mp;
+ register char *cp=0;
+ if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np)
+ {
+ if(!mp && !is_associative(ap) && (aq=(Namarr_t*)ap->scope))
+ {
+ array_syncsub(aq,ap);
+ if((mp=array_find(np,aq,ARRAY_LOOKUP))==np)
+ return(nv_getv(np,&aq->hdr));
+ }
+ if(mp)
+ {
+ cp = nv_getval(mp);
+ nv_offattr(mp,NV_EXPORT);
+ }
+ return(cp);
+ }
+#if SHOPT_FIXEDARRAY
+ if(ap->fixed && nv_isattr(np,NV_INT16P) == NV_INT16)
+ np->nvalue.s = *np->nvalue.sp;
+#endif /* SHOPT_FIXEDARRAY */
+ return(nv_getv(np,&ap->hdr));
+}
+
+static Sfdouble_t array_getnum(Namval_t *np, Namfun_t *disc)
+{
+ register Namarr_t *aq,*ap = (Namarr_t*)disc;
+ register Namval_t *mp;
+ if((mp=array_find(np,ap,ARRAY_LOOKUP))!=np)
+ {
+ if(!mp && !is_associative(ap) && (aq=(Namarr_t*)ap->scope))
+ {
+ array_syncsub(aq,ap);
+ if((mp=array_find(np,aq,ARRAY_LOOKUP))==np)
+ return(nv_getn(np,&aq->hdr));
+ }
+ return(mp?nv_getnum(mp):0);
+ }
+ return(nv_getn(np,&ap->hdr));
+}
+
+static void array_putval(Namval_t *np, const char *string, int flags, Namfun_t *dp)
+{
+ register Namarr_t *ap = (Namarr_t*)dp;
+ register union Value *up;
+ register Namval_t *mp;
+ register struct index_array *aq = (struct index_array*)ap;
+ int scan,nofree = nv_isattr(np,NV_NOFREE);
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp;
+#endif /* SHOPT_FIXEDARRAY */
+ do
+ {
+ int xfree = is_associative(ap)?0:array_isbit(aq->bits,aq->cur,ARRAY_NOFREE);
+ mp = array_find(np,ap,string?ARRAY_ASSIGN:ARRAY_DELETE);
+ scan = ap->nelem&ARRAY_SCAN;
+ if(mp && mp!=np)
+ {
+ if(!is_associative(ap) && string && !(flags&NV_APPEND) && !nv_type(np) && nv_isvtree(mp) && !(ap->nelem&ARRAY_TREE))
+
+ {
+ if(!nv_isattr(np,NV_NOFREE))
+ _nv_unset(mp,flags&NV_RDONLY);
+ array_clrbit(aq->bits,aq->cur,ARRAY_CHILD);
+ aq->val[aq->cur].cp = 0;
+ if(!nv_isattr(mp,NV_NOFREE))
+ nv_delete(mp,ap->table,0);
+ goto skip;
+ }
+ if(!xfree)
+ nv_putval(mp, string, flags);
+ if(string)
+ {
+#if SHOPT_TYPEDEF
+ if(ap->hdr.type && ap->hdr.type!=nv_type(mp))
+ nv_arraysettype(np,ap->hdr.type,nv_getsub(np),0);
+#endif /* SHOPT_TYPEDEF */
+ continue;
+ }
+ ap->nelem |= scan;
+ }
+ if(!string)
+ {
+ if(mp)
+ {
+ if(is_associative(ap))
+ {
+ (*ap->fun)(np,NIL(char*),NV_ADELETE);
+ np->nvalue.cp = 0;
+ }
+ else
+ {
+ if(mp!=np)
+ {
+ array_clrbit(aq->bits,aq->cur,ARRAY_CHILD);
+ aq->val[aq->cur].cp = 0;
+ if(!xfree)
+ nv_delete(mp,ap->table,0);
+ }
+ if(!array_covered(np,(struct index_array*)ap))
+ {
+ if(array_elem(ap))
+ ap->nelem--;
+ }
+#if SHOPT_FIXEDARRAY
+ else if(fp=(struct fixed_array*)ap->fixed)
+ {
+ char *data = array_fixed_data((Namarr_t*)ap->scope);
+ int n = fp->size*fp->curi;
+ if(data)
+ {
+ memcpy(fp->data+n,data+n,fp->size);
+ continue;
+ }
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ }
+ }
+ if(array_elem(ap)==0 && (ap->nelem&ARRAY_SCAN))
+ {
+ if(is_associative(ap))
+ (*ap->fun)(np, NIL(char*), NV_AFREE);
+ else if(ap->table)
+ dtclose(ap->table);
+ nv_offattr(np,NV_ARRAY);
+ }
+ if(!mp || mp!=np || is_associative(ap))
+ continue;
+ }
+ skip:
+ /* prevent empty string from being deleted */
+ up = array_getup(np,ap,!nofree);
+ if(up->cp == Empty)
+ up->cp = 0;
+#if SHOPT_FIXEDARRAY
+ if(nv_isarray(np) && !ap->fixed)
+#else
+ if(nv_isarray(np))
+#endif /* SHOPT_FIXEDARRAY */
+ np->nvalue.up = up;
+ nv_putv(np,string,flags,&ap->hdr);
+#if SHOPT_FIXEDARRAY
+ if(fp = (struct fixed_array*)ap->fixed)
+ {
+ if(fp->ptr)
+ {
+ char **cp = (char**)fp->data;
+ cp[fp->curi] = (char*)(np->nvalue.cp?np->nvalue.cp:Empty);
+ }
+ }
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if(!is_associative(ap))
+ {
+ if(string)
+ array_clrbit(aq->bits,aq->cur,ARRAY_NOFREE);
+ else if(mp==np)
+ aq->val[aq->cur].cp = 0;
+ }
+#if SHOPT_TYPEDEF
+ if(string && ap->hdr.type && nv_isvtree(np))
+ nv_arraysettype(np,ap->hdr.type,nv_getsub(np),0);
+#endif /* SHOPT_TYPEDEF */
+ }
+ while(!string && nv_nextsub(np));
+ if(ap)
+ ap->nelem &= ~ARRAY_NOSCOPE;
+ if(nofree)
+ nv_onattr(np,NV_NOFREE);
+ else
+ nv_offattr(np,NV_NOFREE);
+ if(!string && !nv_isattr(np,NV_ARRAY))
+ {
+ Namfun_t *nfp;
+#if SHOPT_FIXEDARRAY
+ char *data = array_fixed_data((Namarr_t*)ap->scope);
+ fp = (struct fixed_array*)ap->fixed;
+ if(fp && (!ap->scope || data!=fp->data))
+ {
+ if(fp->ptr)
+ {
+ int n = fp->nelem;
+ char **cp = (char**)fp->data;
+ while(n-->0)
+ {
+ if(cp && *cp!=Empty)
+ free(*cp);
+ cp++;
+ }
+ }
+ free((void*)fp->data);
+ if(data)
+ fp->data = data;
+ }
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if(!is_associative(ap) && aq->xp)
+ {
+ _nv_unset(nv_namptr(aq->xp,0),NV_RDONLY);
+ free((void*)aq->xp);
+ }
+ if((nfp = nv_disc(np,(Namfun_t*)ap,NV_POP)) && !(nfp->nofree&1))
+ free((void*)nfp);
+ if(!nv_isnull(np))
+ {
+ nv_onattr(np,NV_NOFREE);
+ _nv_unset(np,flags);
+ }
+ else
+ nv_offattr(np,NV_NOFREE);
+ if(np->nvalue.cp==Empty)
+ np->nvalue.cp = 0;
+ }
+ if(!string && (flags&NV_TYPE))
+ array_unscope(np,ap);
+}
+
+static const Namdisc_t array_disc =
+{
+ sizeof(Namarr_t),
+ array_putval,
+ array_getval,
+ array_getnum,
+ 0,
+ 0,
+ array_clone
+};
+
+static void array_copytree(Namval_t *np, Namval_t *mp)
+{
+ Namfun_t *fp = nv_disc(np,NULL,NV_POP);
+ nv_offattr(np,NV_ARRAY);
+ nv_clone(np,mp,0);
+ if(np->nvalue.cp && !nv_isattr(np,NV_NOFREE))
+ free((void*)np->nvalue.cp);
+ np->nvalue.cp = 0;
+ np->nvalue.up = &mp->nvalue;
+ fp->nofree &= ~1;
+ nv_disc(np,(Namfun_t*)fp, NV_FIRST);
+ fp->nofree |= 1;
+ nv_onattr(np,NV_ARRAY);
+ mp->nvenv = (char*)np;
+}
+
+/*
+ * Increase the size of the indexed array of elements in <arp>
+ * so that <maxi> is a legal index. If <arp> is 0, an array
+ * of the required size is allocated. A pointer to the
+ * allocated Namarr_t structure is returned.
+ * <maxi> becomes the current index of the array.
+ */
+static struct index_array *array_grow(Namval_t *np, register struct index_array *arp,int maxi)
+{
+ register struct index_array *ap;
+ register int i;
+ register int newsize = arsize(arp,maxi+1);
+ if (maxi >= ARRAY_MAX)
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript, fmtbase((long)maxi,10,0));
+ i = (newsize-1)*sizeof(union Value*)+newsize;
+ ap = new_of(struct index_array,i);
+ memset((void*)ap,0,sizeof(*ap)+i);
+ ap->maxi = newsize;
+ ap->cur = maxi;
+ ap->bits = (unsigned char*)&ap->val[newsize];
+ memset(ap->bits, 0, newsize);
+ if(arp)
+ {
+ ap->header = arp->header;
+ ap->header.hdr.dsize = sizeof(*ap) + i;
+ for(i=0;i < arp->maxi;i++)
+ {
+ ap->bits[i] = arp->bits[i];
+ ap->val[i].cp = arp->val[i].cp;
+ }
+ memcpy(ap->bits, arp->bits, arp->maxi);
+ array_setptr(np,arp,ap);
+ free((void*)arp);
+ }
+ else
+ {
+ Namval_t *mp=0;
+ ap->header.hdr.dsize = sizeof(*ap) + i;
+ i = 0;
+ ap->header.fun = 0;
+ if((nv_isnull(np)||np->nvalue.cp==Empty) && nv_isattr(np,NV_NOFREE))
+ {
+ i = ARRAY_TREE;
+ nv_offattr(np,NV_NOFREE);
+ }
+ if(np->nvalue.cp==Empty)
+ np->nvalue.cp=0;
+ if(nv_hasdisc(np,&array_disc) || (nv_type(np) && nv_isvtree(np)))
+ {
+ ap->header.table = dtopen(&_Nvdisc,Dtoset);
+ mp = nv_search("0", ap->header.table,NV_ADD);
+ if(mp && nv_isnull(mp))
+ {
+ Namfun_t *fp;
+ ap->val[0].np = mp;
+ array_setbit(ap->bits,0,ARRAY_CHILD);
+ for(fp=np->nvfun; fp && !fp->disc->readf; fp=fp->next);
+ if(fp && fp->disc && fp->disc->readf)
+ (*fp->disc->readf)(mp,(Sfio_t*)0,0,fp);
+ i++;
+ }
+ }
+ else
+ if((ap->val[0].cp=np->nvalue.cp))
+ i++;
+ else if(nv_isattr(np,NV_INTEGER) && !nv_isnull(np))
+ {
+ Sfdouble_t d= nv_getnum(np);
+ i++;
+ }
+ ap->header.nelem = i;
+ ap->header.hdr.disc = &array_disc;
+ nv_disc(np,(Namfun_t*)ap, NV_FIRST);
+ nv_onattr(np,NV_ARRAY);
+ if(mp)
+ {
+ array_copytree(np,mp);
+ ap->header.hdr.nofree &= ~1;
+ }
+ }
+ for(;i < newsize;i++)
+ ap->val[i].cp = 0;
+ return(ap);
+}
+
+int nv_atypeindex(Namval_t *np, const char *tname)
+{
+ Namval_t *tp;
+ int offset = staktell();
+ int n = strlen(tname)-1;
+ sfprintf(stkstd,"%s.%.*s%c",NV_CLASS,n,tname,0);
+ tp = nv_open(stakptr(offset), sh.var_tree, NV_NOADD|NV_VARNAME);
+ stakseek(offset);
+ if(tp)
+ {
+ struct index_array *ap = (struct index_array*)nv_arrayptr(np);
+ if(!nv_hasdisc(tp,&ENUM_disc))
+ errormsg(SH_DICT,ERROR_exit(1),e_notenum,tp->nvname);
+ if(!ap)
+ ap = array_grow(np,ap,1);
+ ap->xp = calloc(NV_MINSZ,1);
+ np = nv_namptr(ap->xp,0);
+ np->nvname = tp->nvname;
+ nv_onattr(np,NV_MINIMAL);
+ nv_clone(tp,np,NV_NOFREE);
+ nv_offattr(np,NV_RDONLY);
+ return(1);
+ }
+ errormsg(SH_DICT,ERROR_exit(1),e_unknowntype, n,tname);
+ return(0);
+}
+
+Namarr_t *nv_arrayptr(register Namval_t *np)
+{
+ if(nv_isattr(np,NV_ARRAY))
+ return((Namarr_t*)nv_hasdisc(np, &array_disc));
+ return(0);
+}
+
+/*
+ * Verify that argument is an indexed array and convert to associative,
+ * freeing relevant storage
+ */
+static Namarr_t *nv_changearray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int))
+{
+ register Namarr_t *ap;
+ char numbuff[NUMSIZE+1];
+ unsigned dot, digit, n;
+ union Value *up;
+ struct index_array *save_ap;
+ register char *string_index=&numbuff[NUMSIZE];
+ numbuff[NUMSIZE]='\0';
+
+ if(!fun || !(ap = nv_arrayptr(np)) || is_associative(ap))
+ return(NIL(Namarr_t*));
+
+ nv_stack(np,&ap->hdr);
+ save_ap = (struct index_array*)nv_stack(np,0);
+ ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT));
+ ap->nelem = 0;
+ ap->fun = fun;
+ nv_onattr(np,NV_ARRAY);
+
+ for(dot = 0; dot < (unsigned)save_ap->maxi; dot++)
+ {
+ if(save_ap->val[dot].cp)
+ {
+ if ((digit = dot)== 0)
+ *--string_index = '0';
+ else while( n = digit )
+ {
+ digit /= 10;
+ *--string_index = '0' + (n-10*digit);
+ }
+ nv_putsub(np, string_index, ARRAY_ADD);
+ up = (union Value*)((*ap->fun)(np,NIL(char*),0));
+ up->cp = save_ap->val[dot].cp;
+ save_ap->val[dot].cp = 0;
+ }
+ string_index = &numbuff[NUMSIZE];
+ }
+ free((void*)save_ap);
+ return(ap);
+}
+
+/*
+ * set the associative array processing method for node <np> to <fun>
+ * The array pointer is returned if sucessful.
+ */
+Namarr_t *nv_setarray(Namval_t *np, void *(*fun)(Namval_t*,const char*,int))
+{
+ register Namarr_t *ap;
+ char *value=0;
+ Namfun_t *fp;
+ int nelem = 0;
+ if(fun && (ap = nv_arrayptr(np)))
+ {
+ /*
+ * if it's already an indexed array, convert to
+ * associative structure
+ */
+ if(!is_associative(ap))
+ ap = nv_changearray(np, fun);
+ return(ap);
+ }
+ if(nv_isnull(np) && nv_isattr(np,NV_NOFREE))
+ {
+ nelem = ARRAY_TREE;
+ nv_offattr(np,NV_NOFREE);
+ }
+ if(!(fp=nv_isvtree(np)))
+ value = nv_getval(np);
+ if(fun && !ap && (ap = (Namarr_t*)((*fun)(np, NIL(char*), NV_AINIT))))
+ {
+ /* check for preexisting initialization and save */
+ ap->nelem = nelem;
+ ap->fun = fun;
+ nv_onattr(np,NV_ARRAY);
+ if(fp || value)
+ {
+ nv_putsub(np, "0", ARRAY_ADD);
+ if(value)
+ nv_putval(np, value, 0);
+ else
+ {
+ Namval_t *mp = (Namval_t*)((*fun)(np,NIL(char*),NV_ACURRENT));
+ array_copytree(np,mp);
+ }
+ }
+ return(ap);
+ }
+ return(NIL(Namarr_t*));
+}
+
+/*
+ * move parent subscript into child
+ */
+Namval_t *nv_arraychild(Namval_t *np, Namval_t *nq, int c)
+{
+ Namfun_t *fp;
+ register Namarr_t *ap = nv_arrayptr(np);
+ union Value *up;
+ Namval_t *tp;
+ if(!nq)
+ return(ap?array_find(np,ap, ARRAY_LOOKUP):0);
+ if(!ap)
+ {
+ nv_putsub(np, NIL(char*), ARRAY_FILL);
+ ap = nv_arrayptr(np);
+ }
+ if(!(up = array_getup(np,ap,0)))
+ return((Namval_t*)0);
+ np->nvalue.cp = up->cp;
+ if((tp=nv_type(np)) || c)
+ {
+ ap->nelem |= ARRAY_NOCLONE;
+ nq->nvenv = (char*)np;
+ if(c=='t')
+ nv_clone(tp,nq, 0);
+ else
+ nv_clone(np, nq, NV_NODISC);
+ nv_offattr(nq,NV_ARRAY);
+ ap->nelem &= ~ARRAY_NOCLONE;
+ }
+ nq->nvenv = (char*)np;
+ if((fp=nq->nvfun) && fp->disc && fp->disc->setdisc && (fp = nv_disc(nq,fp,NV_POP)))
+ free((void*)fp);
+ if(!ap->fun)
+ {
+ struct index_array *aq = (struct index_array*)ap;
+ array_setbit(aq->bits,aq->cur,ARRAY_CHILD);
+ if(c=='.' && !nq->nvalue.cp)
+ ap->nelem++;
+ up->np = nq;
+ }
+ if(c=='.')
+ nv_setvtree(nq);
+ return(nq);
+}
+
+/*
+ * This routine sets subscript of <np> to the next element, if any.
+ * The return value is zero, if there are no more elements
+ * Otherwise, 1 is returned.
+ */
+int nv_nextsub(Namval_t *np)
+{
+ register struct index_array *ap = (struct index_array*)nv_arrayptr(np);
+ register unsigned dot;
+ struct index_array *aq=0, *ar=0;
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp;
+#endif /* SHOPT_FIXEDARRAY */
+ if(!ap || !(ap->header.nelem&ARRAY_SCAN))
+ return(0);
+ if(is_associative(ap))
+ {
+ Namval_t *nq;
+ if(nq=(*ap->header.fun)(np,NIL(char*),NV_ANEXT))
+ {
+ if(nv_isattr(nq,NV_CHILD))
+ nv_putsub(nq->nvalue.np,NIL(char*),ARRAY_UNDEF);
+ return(1);
+ }
+ ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD);
+ return(0);
+ }
+#if SHOPT_FIXEDARRAY
+ else if(fp = (struct fixed_array*)ap->header.fixed)
+ {
+ if(ap->header.nelem&ARRAY_FIXED)
+ {
+ while(++fp->curi < fp->nelem)
+ {
+ nv_putsub(np,0,fp->curi|ARRAY_FIXED|ARRAY_SCAN);
+ if(fp->ptr && *(((char**)fp->data)+fp->curi))
+ return(1);
+ }
+ ap->header.nelem &= ~ARRAY_FIXED;
+ return(0);
+ }
+ dot = fp->dim;
+ if((fp->cur[dot]+1) < fp->max[dot])
+ {
+ fp->cur[dot]++;
+ for(fp->curi=0,dot=0; dot < fp->ndim; dot++)
+ fp->curi += fp->incr[dot]*fp->cur[dot];
+ return(1);
+ }
+ if(fp->level)
+ {
+ dot= --fp->dim;
+ while((dot+1) < fp->ndim)
+ fp->cur[++dot] = 0;
+ fp->level--;
+ fp->curi = 0;
+ }
+ else
+ ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD);
+ return(0);
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ if(!(ap->header.nelem&ARRAY_NOSCOPE))
+ ar = (struct index_array*)ap->header.scope;
+ for(dot=ap->cur+1; dot < (unsigned)ap->maxi; dot++)
+ {
+ aq = ap;
+ if(!ap->val[dot].cp && !(ap->header.nelem&ARRAY_NOSCOPE))
+ {
+ if(!(aq=ar) || dot>=(unsigned)aq->maxi)
+ continue;
+ }
+ if(aq->val[dot].cp==Empty && array_elem(&aq->header) < nv_aimax(np)+1) {
+ ap->cur = dot;
+ if(nv_getval(np)==Empty)
+ continue;
+ }
+ if(aq->val[dot].cp)
+ {
+ ap->cur = dot;
+ if(array_isbit(aq->bits, dot,ARRAY_CHILD))
+ {
+ Namval_t *mp = aq->val[dot].np;
+ if((aq->header.nelem&ARRAY_NOCHILD) && nv_isvtree(mp) && !mp->nvfun->dsize)
+ continue;
+ if(nv_isarray(mp))
+ nv_putsub(mp,NIL(char*),ARRAY_SCAN);
+ }
+ return(1);
+ }
+ }
+ ap->header.nelem &= ~(ARRAY_SCAN|ARRAY_NOCHILD);
+ ap->cur = 0;
+ return(0);
+}
+
+/*
+ * Set an array subscript for node <np> given the subscript <sp>
+ * An array is created if necessary.
+ * <mode> can be a number, plus or more of symbolic constants
+ * ARRAY_SCAN, ARRAY_UNDEF, ARRAY_ADD
+ * The node pointer is returned which can be NULL if <np> is
+ * not already array and the ARRAY_ADD bit of <mode> is not set.
+ * ARRAY_FILL sets the specified subscript to the empty string when
+ * ARRAY_ADD is specified and there is no value or sets all
+ * the elements up to the number specified if ARRAY_ADD is not specified
+ */
+Namval_t *nv_putsub(Namval_t *np,register char *sp,register long mode)
+{
+ register struct index_array *ap = (struct index_array*)nv_arrayptr(np);
+ register int size = (mode&ARRAY_MASK);
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp;
+ if(!ap || (!ap->header.fixed && !ap->header.fun))
+#else
+ if(!ap || !ap->header.fun)
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ if(sp)
+ {
+ Shell_t *shp = sh_getinterp();
+ if(ap && ap->xp && !strmatch(sp,"+([0-9])"))
+ {
+ Namval_t *mp = nv_namptr(ap->xp,0);
+ nv_putval(mp, sp,0);
+ size = nv_getnum(mp);
+ }
+ else
+ size = (int)sh_arith(shp,(char*)sp);
+ }
+ if(size <0 && ap)
+ size += array_maxindex(np);
+ if(size >= ARRAY_MAX || (size < 0))
+ {
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np));
+ return(NIL(Namval_t*));
+ }
+ if(!ap || size>=ap->maxi)
+ {
+ if(size==0 && !(mode&ARRAY_FILL))
+ return(NIL(Namval_t*));
+ if(sh.subshell)
+ np = sh_assignok(np,1);
+ ap = array_grow(np, ap,size);
+ }
+ ap->header.nelem &= ~ARRAY_UNDEF;
+ ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE));
+#if 0
+ if(array_isbit(ap->bits,oldsize,ARRAY_CHILD))
+ mp = ap->val[oldsize].np;
+ if(size != oldsize && mp->nvalue.cp)
+ {
+ Namfun_t *nfp;
+ for(nfp=np->nvfun; nfp; nfp=nfp->next)
+ {
+ if(nfp->disc && nfp->disc->readf)
+ {
+ (*nfp->disc->readf)(mp,(Sfio_t*)0,0,nfp);
+ break;
+ }
+ }
+ }
+#endif
+ ap->cur = size;
+ if((mode&ARRAY_SCAN) && (ap->cur--,!nv_nextsub(np)))
+ np = 0;
+ if(mode&(ARRAY_FILL|ARRAY_ADD))
+ {
+ if(!(mode&ARRAY_ADD))
+ {
+ int n;
+ if(mode&ARRAY_SETSUB)
+ {
+ for(n=0; n <= ap->maxi; n++)
+ ap->val[n].cp = 0;
+ ap->header.nelem = 0;
+ }
+ for(n=0; n <= size; n++)
+ {
+ if(!ap->val[n].cp)
+ {
+ ap->val[n].cp = Empty;
+ if(!array_covered(np,ap))
+ ap->header.nelem++;
+ }
+ }
+ if(n=ap->maxi-ap->maxi)
+ memset(&ap->val[size],0,n*sizeof(union Value));
+ }
+ else if(!(sp=(char*)ap->val[size].cp) || sp==Empty)
+ {
+ if(sh.subshell)
+ np = sh_assignok(np,1);
+ if(ap->header.nelem&ARRAY_TREE)
+ {
+ char *cp;
+ Namval_t *mp;
+ if(!ap->header.table)
+ ap->header.table = dtopen(&_Nvdisc,Dtoset);
+ sfprintf(sh.strbuf,"%d",ap->cur);
+ cp = sfstruse(sh.strbuf);
+ mp = nv_search(cp, ap->header.table, NV_ADD);
+ mp->nvenv = (char*)np;
+ nv_arraychild(np,mp,0);
+ nv_setvtree(mp);
+ }
+ else
+ ap->val[size].cp = Empty;
+ if(!sp && !array_covered(np,ap))
+ ap->header.nelem++;
+ }
+ }
+ else if(!(mode&ARRAY_SCAN))
+ {
+ ap->header.nelem &= ~ARRAY_SCAN;
+ if(array_isbit(ap->bits,size,ARRAY_CHILD))
+ nv_putsub(ap->val[size].np,NIL(char*),ARRAY_UNDEF);
+ if(sp && !(mode&ARRAY_ADD) && !ap->val[size].cp)
+ np = 0;
+ }
+ return((Namval_t*)np);
+ }
+#if SHOPT_FIXEDARRAY
+ if(fp=(struct fixed_array*)ap->header.fixed)
+ {
+ if(!fp->data)
+ return(np);
+ if(mode&ARRAY_UNDEF)
+ {
+ fp->dim = 0;
+ fp->curi = 0;
+ for(size=fp->ndim;--size>=0;)
+ fp->cur[size] = 0;
+ ap->header.nelem &= ~ARRAY_MASK;
+ if(mode&ARRAY_FIXED)
+ {
+ mode &= ~ARRAY_UNDEF;
+ ap->header.nelem |= (ARRAY_FIXED|fp->nelem);
+ }
+ else
+ ap->header.nelem |= fp->max[0];
+ }
+ else if(mode&ARRAY_FIXED)
+ {
+ size = (mode&ARRAY_MASK)&~(ARRAY_FIXED);
+ fp->curi = size;
+ for(fp->dim=0;size>0 && fp->dim<fp->ndim; fp->dim++)
+ {
+ fp->cur[fp->dim] = size/fp->incr[fp->dim];
+ size -= fp->incr[fp->dim]*fp->cur[fp->dim];
+ }
+ while(fp->dim < fp->ndim)
+ fp->cur[fp->dim++] = 0;
+ fp->dim = ap->header.nelem;
+ ap->header.nelem |= ARRAY_FIXED;
+ }
+ else if(fp->dim< fp->ndim)
+ {
+ fp->curi += (size-fp->cur[fp->dim])*fp->incr[fp->dim];
+ fp->cur[fp->dim] = size;
+ }
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ ap->header.nelem &= ~ARRAY_UNDEF;
+ if(!(mode&ARRAY_FILL))
+ ap->header.nelem &= ~ARRAY_SCAN;
+ ap->header.nelem |= (mode&(ARRAY_SCAN|ARRAY_NOCHILD|ARRAY_UNDEF|ARRAY_NOSCOPE));
+#if SHOPT_FIXEDARRAY
+ if(fp)
+ return(np);
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if(sp)
+ {
+ if(mode&ARRAY_SETSUB)
+ {
+ (*ap->header.fun)(np, sp, NV_ASETSUB);
+ return(np);
+ }
+ (*ap->header.fun)(np, sp, (mode&ARRAY_ADD)?NV_AADD:0);
+ if(!(mode&(ARRAY_SCAN|ARRAY_ADD)) && !(*ap->header.fun)(np,NIL(char*),NV_ACURRENT))
+ np = 0;
+ }
+ else if(mode&ARRAY_SCAN)
+ (*ap->header.fun)(np,(char*)np,0);
+ else if(mode&ARRAY_UNDEF)
+ (*ap->header.fun)(np, "",0);
+ if((mode&ARRAY_SCAN) && !nv_nextsub(np))
+ np = 0;
+ return(np);
+}
+
+#if SHOPT_FIXEDARRAY
+int nv_arrfixed(Namval_t *np, Sfio_t *out, int flag, char *dim)
+{
+ Namarr_t *ap = nv_arrayptr(np);
+ struct fixed_array *fp = (struct fixed_array*)ap->fixed;
+ int n;
+ if(flag)
+ {
+ if(out)
+ {
+ for(n=0; n < fp->dim; n++)
+ sfprintf(out,"[%d]",fp->cur[n]);
+ }
+ if(dim)
+ *dim = fp->dim;
+ return(fp->curi);
+ }
+ if(out)
+ {
+ for(n=0; n < fp->ndim; n++)
+ sfprintf(out,"[%d]",fp->max[n]);
+ }
+ fp->dim = 0;
+ return(fp->curi);
+}
+
+static void array_fixed_setdata(Namval_t *np,Namarr_t* ap,struct fixed_array* fp)
+{
+ int n = ap->nelem;
+ ap->nelem = 1;
+ fp->size = fp->ptr?sizeof(void*):nv_datasize(np,0);
+ ap->nelem = n;
+ fp->data = (char*)calloc(fp->nelem,fp->size);
+ if(fp->ptr)
+ {
+ char **cp = (char**)fp->data;
+ for(n=fp->nelem; n-->0;)
+ *cp++ = Empty;
+ }
+}
+
+static int array_fixed_init(Namval_t *np, char *sub, char *cp)
+{
+ Shell_t *shp=sh_getinterp();
+ Namarr_t *ap;
+ struct fixed_array *fp;
+ int n=1,sz;
+ char *ep=cp;
+ while(*ep=='[')
+ {
+ ep = nv_endsubscript(np,ep,0);
+ n++;
+ }
+ if(*ep)
+ return(0);
+ sz = sizeof(struct fixed_array)+ 3*n*sizeof(int);
+ if(!(ap=newof(NIL(Namarr_t*),Namarr_t,1,sz)))
+ return(0);
+ ap->hdr.disc = &array_disc;
+ ap->hdr.dsize = sizeof(Namarr_t)+sz;
+ ap->hdr.nofree &= ~1;
+ fp = (struct fixed_array*)(ap+1);
+ ap->fixed = (void*)fp;
+ fp->ndim = n;
+ fp->max = (int*)(fp+1);
+ fp->incr = fp->max+n;
+ fp->cur = fp->incr+n;
+ fp->max[0] = (int)sh_arith(shp,(char*)sub);
+ for(n=1,ep=cp;*ep=='['; ep=cp)
+ {
+ cp = nv_endsubscript(np,ep,0);
+ cp[-1]=0;
+ fp->max[n++] = sz = (int)sh_arith(shp,(char*)ep+1);
+ if(sz<0)
+ {
+ free((void*)ap);
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np));
+ }
+ cp[-1] = ']';
+ }
+ nv_disc(np,(Namfun_t*)ap, NV_FIRST);
+ fp->ptr = !np->nvsize;
+ nv_onattr(np,NV_ARRAY|(fp->ptr?0:NV_NOFREE));
+ fp->incr[n=fp->ndim-1] = 1;
+ for(sz=1; --n>=0;)
+ sz = fp->incr[n] = sz*fp->max[n+1];
+ fp->nelem = sz*fp->max[0];
+ ap->nelem = fp->max[0];
+ return(1);
+}
+
+static char *array_fixed(Namval_t *np, char *sub, char *cp,int mode)
+{
+ Shell_t *shp=sh_getinterp();
+ Namarr_t *ap = nv_arrayptr(np);
+ struct fixed_array *fp = (struct fixed_array*)ap->fixed;
+ char *ep;
+ int size,n=0,sz;
+ if(!fp->data)
+ array_fixed_setdata(np,ap,fp);
+ ap->nelem &= ~ARRAY_UNDEF;
+ if(ap->nelem&ARRAY_FIXED)
+ {
+ ap->nelem &= ~ARRAY_FIXED;
+ n = fp->dim;
+ sz = fp->curi;
+ if(*sub==0)
+ goto skip;
+ }
+ else
+ fp->curi = 0;
+ size = (int)sh_arith(shp,(char*)sub);
+ fp->cur[n] = size;
+ if(size >= fp->max[n] || (size < 0))
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np));
+ *cp++ = ']';
+ sz = fp->curi + fp->cur[n]*fp->incr[n];
+ for(n++,ep=cp;*ep=='['; ep=cp,n++)
+ {
+ if(n >= fp->ndim)
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np));
+ cp = nv_endsubscript(np,ep,0);
+ cp[-1]=0;
+ size = (int)sh_arith(shp,(char*)ep+1);
+ if(size >= fp->max[n] || (size < 0))
+ errormsg(SH_DICT,ERROR_exit(1),e_subscript, nv_name(np));
+ fp->cur[n] = size;
+ cp[-1] = ']';
+ sz += fp->cur[n]*fp->incr[n];
+ }
+skip:
+ fp->dim = n;
+ ap->nelem &= ~ARRAY_MASK;
+ ap->nelem |= fp->max[n];
+ while(n < fp->ndim)
+ fp->cur[n++] = 0;
+ fp->curi = sz;
+ return(cp-1);
+}
+#endif /* SHOPT_FIXEDARRAY */
+
+/*
+ * process an array subscript for node <np> given the subscript <cp>
+ * returns pointer to character after the subscript
+ */
+char *nv_endsubscript(Namval_t *np, register char *cp, int mode)
+{
+ register int count=1, quoted=0, c;
+ register char *sp = cp+1;
+ /* first find matching ']' */
+ while(count>0 && (c= *++cp))
+ {
+ if(c=='\\' && (!(mode&NV_SUBQUOTE) || (c=cp[1])=='[' || c==']' || c=='\\' || c=='*' || c=='@'))
+ {
+ quoted=1;
+ cp++;
+ }
+ else if(c=='[')
+ count++;
+ else if(c==']')
+ count--;
+ }
+ *cp = 0;
+ if(quoted)
+ {
+ /* strip escape characters */
+ count = staktell();
+ stakwrite(sp,1+cp-sp);
+ sh_trim(sp=stakptr(count));
+ }
+ if(mode && np)
+ {
+ Namarr_t *ap = nv_arrayptr(np);
+ int scan = 0;
+#if SHOPT_FIXEDARRAY
+ if((mode&NV_FARRAY) && !nv_isarray(np))
+ {
+ if(array_fixed_init(np,sp,cp+1))
+ {
+ *cp++ = c;
+ return(strchr(cp,0));
+ }
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ if(ap)
+ scan = ap->nelem&ARRAY_SCAN;
+ if((mode&NV_ASSIGN) && (cp[1]=='=' || cp[1]=='+'))
+ mode |= NV_ADD;
+ else if(ap && cp[1]=='.' && (mode&NV_FARRAY))
+ mode |= NV_ADD;
+#if SHOPT_FIXEDARRAY
+ if(ap && ap->fixed)
+ cp = array_fixed(np,sp,cp,mode);
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ nv_putsub(np, sp, ((mode&NV_ADD)?ARRAY_ADD:0)|(cp[1]&&(mode&NV_ADD)?ARRAY_FILL:mode&ARRAY_FILL));
+ if(scan)
+ ap->nelem |= scan;
+ }
+ if(quoted)
+ stakseek(count);
+ *cp++ = c;
+ return(cp);
+}
+
+
+Namval_t *nv_opensub(Namval_t* np)
+{
+ register struct index_array *ap = (struct index_array*)nv_arrayptr(np);
+#if SHOPT_FIXEDARRAY
+ struct fixed_array *fp;
+#endif /* SHOPT_FIXEDARRAY */
+ if(ap)
+ {
+ if(is_associative(ap))
+ return((Namval_t*)((*ap->header.fun)(np,NIL(char*),NV_ACURRENT)));
+#if SHOPT_FIXEDARRAY
+ else if(!(fp=(struct fixed_array*)ap->header.fixed) && array_isbit(ap->bits,ap->cur,ARRAY_CHILD))
+#else
+ else if(array_isbit(ap->bits,ap->cur,ARRAY_CHILD))
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ return(ap->val[ap->cur].np);
+ }
+#if SHOPT_FIXEDARRAY
+ else if(fp)
+ {
+ int n = fp->dim;
+ if((fp->dim+1) < fp->ndim)
+ {
+ fp->dim++;
+ if(ap->header.nelem&ARRAY_SCAN)
+ {
+ while(++n < fp->ndim)
+ fp->cur[n] = 0;
+ fp->level++;
+ }
+ return(np);
+ }
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ }
+ return(NIL(Namval_t*));
+}
+
+char *nv_getsub(Namval_t* np)
+{
+ static char numbuff[NUMSIZE];
+ register struct index_array *ap;
+ register unsigned dot, n;
+ register char *cp = &numbuff[NUMSIZE];
+ if(!np || !(ap = (struct index_array*)nv_arrayptr(np)))
+ return(NIL(char*));
+ if(is_associative(ap))
+ return((char*)((*ap->header.fun)(np,NIL(char*),NV_ANAME)));
+ if(ap->xp)
+ {
+ np = nv_namptr(ap->xp,0);
+ np->nvalue.s = ap->cur;
+ return(nv_getval(np));
+ }
+ if((dot = ap->cur)==0)
+ *--cp = '0';
+ else while(n=dot)
+ {
+ dot /= 10;
+ *--cp = '0' + (n-10*dot);
+ }
+ return(cp);
+}
+
+/*
+ * If <np> is an indexed array node, the current subscript index
+ * returned, otherwise returns -1
+ */
+int nv_aindex(register Namval_t* np)
+{
+ Namarr_t *ap = nv_arrayptr(np);
+ if(!ap)
+ return(0);
+ else if(is_associative(ap))
+ return(-1);
+#if SHOPT_FIXEDARRAY
+ else if(ap->fixed)
+ return(-1);
+#endif /* SHOPT_FIXEDARRAY */
+ return(((struct index_array*)(ap))->cur&ARRAY_MASK);
+}
+
+int nv_arraynsub(register Namarr_t* ap)
+{
+ return(array_elem(ap));
+}
+
+int nv_aimax(register Namval_t* np)
+{
+ struct index_array *ap = (struct index_array*)nv_arrayptr(np);
+ int sub = -1;
+#if SHOPT_FIXEDARRAY
+ if(!ap || is_associative(&ap->header) || ap->header.fixed)
+#else
+ if(!ap || is_associative(&ap->header))
+#endif /* SHOPT_FIXEDARRAY */
+ return(-1);
+ sub = ap->maxi;
+ while(--sub>0 && ap->val[sub].cp==0);
+ return(sub);
+}
+
+/*
+ * This is the default implementation for associative arrays
+ */
+void *nv_associative(register Namval_t *np,const char *sp,int mode)
+{
+ register struct assoc_array *ap = (struct assoc_array*)nv_arrayptr(np);
+ register int type;
+ switch(mode)
+ {
+ case NV_AINIT:
+ if(ap = (struct assoc_array*)calloc(1,sizeof(struct assoc_array)))
+ {
+ ap->header.table = dtopen(&_Nvdisc,Dtoset);
+ ap->cur = 0;
+ ap->pos = 0;
+ ap->header.hdr.disc = &array_disc;
+ nv_disc(np,(Namfun_t*)ap, NV_FIRST);
+ ap->header.hdr.dsize = sizeof(struct assoc_array);
+ ap->header.hdr.nofree &= ~1;
+ }
+ return((void*)ap);
+ case NV_ADELETE:
+ if(ap->cur)
+ {
+ if(!ap->header.scope || (Dt_t*)ap->header.scope==ap->header.table || !nv_search(ap->cur->nvname,(Dt_t*)ap->header.scope,0))
+ ap->header.nelem--;
+ _nv_unset(ap->cur,NV_RDONLY);
+ nv_delete(ap->cur,ap->header.table,0);
+ ap->cur = 0;
+ }
+ return((void*)ap);
+ case NV_AFREE:
+ ap->pos = 0;
+ if(ap->header.scope)
+ {
+ ap->header.table = dtview(ap->header.table,(Dt_t*)0);
+ dtclose(ap->header.scope);
+ ap->header.scope = 0;
+ }
+ else
+ dtclose(ap->header.table);
+ return((void*)ap);
+ case NV_ANEXT:
+ if(!ap->pos)
+ {
+ if((ap->header.nelem&ARRAY_NOSCOPE) && ap->header.scope && dtvnext(ap->header.table))
+ {
+ ap->header.scope = dtvnext(ap->header.table);
+ ap->header.table->view = 0;
+ }
+ if(!(ap->pos=ap->cur))
+ ap->pos = (Namval_t*)dtfirst(ap->header.table);
+ }
+ else
+ ap->pos = ap->nextpos;
+ for(;ap->cur=ap->pos; ap->pos=ap->nextpos)
+ {
+ ap->nextpos = (Namval_t*)dtnext(ap->header.table,ap->pos);
+ if(!nv_isnull(ap->cur))
+ {
+ if((ap->header.nelem&ARRAY_NOCHILD) && nv_isattr(ap->cur,NV_CHILD))
+ continue;
+ return((void*)ap);
+ }
+ }
+ if((ap->header.nelem&ARRAY_NOSCOPE) && ap->header.scope && !dtvnext(ap->header.table))
+ {
+ ap->header.table->view = (Dt_t*)ap->header.scope;
+ ap->header.scope = ap->header.table;
+ }
+ return(NIL(void*));
+ case NV_ASETSUB:
+ ap->cur = (Namval_t*)sp;
+ return((void*)ap->cur);
+ case NV_ACURRENT:
+ if(ap->cur)
+ ap->cur->nvenv = (char*)np;
+ return((void*)ap->cur);
+ case NV_ANAME:
+ if(ap->cur)
+ {
+ Shell_t *shp = sh_getinterp();
+ if(!shp->instance && nv_isnull(ap->cur))
+ return(NIL(void*));
+ return((void*)ap->cur->nvname);
+ }
+ return(NIL(void*));
+ default:
+ if(sp)
+ {
+ Namval_t *mp=0;
+ ap->cur = 0;
+ if(sp==(char*)np)
+ return(0);
+ type = nv_isattr(np,NV_PUBLIC&~(NV_ARRAY|NV_CHILD|NV_MINIMAL));
+ if(mode)
+ mode = NV_ADD|HASH_NOSCOPE;
+ else if(ap->header.nelem&ARRAY_NOSCOPE)
+ mode = HASH_NOSCOPE;
+ if(*sp==0 && sh_isoption(SH_XTRACE) && (mode&NV_ADD))
+ errormsg(SH_DICT,ERROR_warn(0),"adding empty subscript");
+ if(sh.subshell && (mp=nv_search(sp,ap->header.table,0)) && nv_isnull(mp))
+ ap->cur = mp;
+ if((mp || (mp=nv_search(sp,ap->header.table,mode))) && nv_isnull(mp) && (mode&NV_ADD))
+ {
+ nv_onattr(mp,type);
+ mp->nvenv = (char*)np;
+ if((mode&NV_ADD) && nv_type(np))
+ nv_arraychild(np,mp,0);
+ if(sh.subshell)
+ np = sh_assignok(np,1);
+ if(!ap->header.scope || !nv_search(sp,dtvnext(ap->header.table),0))
+ ap->header.nelem++;
+ if(nv_isnull(mp))
+ {
+ if(ap->header.nelem&ARRAY_TREE)
+ nv_setvtree(mp);
+ mp->nvalue.cp = Empty;
+ }
+ }
+ else if(ap->header.nelem&ARRAY_SCAN)
+ {
+ Namval_t fake;
+ fake.nvname = (char*)sp;
+ ap->pos = mp = (Namval_t*)dtprev(ap->header.table,&fake);
+ ap->nextpos = (Namval_t*)dtnext(ap->header.table,mp);
+ }
+ else if(!mp && *sp && mode==0)
+ mp = nv_search(sp,ap->header.table,NV_ADD|HASH_NOSCOPE);
+ np = mp;
+ if(ap->pos && ap->pos==np)
+ ap->header.nelem |= ARRAY_SCAN;
+ else if(!(ap->header.nelem&ARRAY_SCAN))
+ ap->pos = 0;
+ ap->cur = np;
+ }
+ if(ap->cur)
+ return((void*)(&ap->cur->nvalue));
+ else
+ return((void*)(&ap->cur));
+ }
+}
+
+/*
+ * Assign values to an array
+ */
+void nv_setvec(register Namval_t *np,int append,register int argc,register char *argv[])
+{
+ int arg0=0;
+ struct index_array *ap=0,*aq;
+ if(nv_isarray(np))
+ {
+ ap = (struct index_array*)nv_arrayptr(np);
+ if(ap && is_associative(ap))
+ errormsg(SH_DICT,ERROR_exit(1),"cannot append index array to associative array %s",nv_name(np));
+ }
+ if(append)
+ {
+ if(ap)
+ {
+ if(!(aq = (struct index_array*)ap->header.scope))
+ aq = ap;
+ arg0 = ap->maxi;
+ while(--arg0>0 && ap->val[arg0].cp==0 && aq->val[arg0].cp==0);
+ arg0++;
+ }
+ else if(!nv_isnull(np))
+ arg0=1;
+ }
+ while(--argc >= 0)
+ {
+ nv_putsub(np,NIL(char*),(long)argc+arg0|ARRAY_FILL|ARRAY_ADD);
+ nv_putval(np,argv[argc],0);
+ }
+}
+
diff --git a/src/cmd/ksh93/sh/bash.c b/src/cmd/ksh93/sh/bash.c
new file mode 100644
index 0000000..fd2f3a1
--- /dev/null
+++ b/src/cmd/ksh93/sh/bash.c
@@ -0,0 +1,423 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * bash specific extensions
+ * originally provided by Karsten Fleischer
+ */
+
+#include "defs.h"
+#include "path.h"
+#include "io.h"
+#include "builtins.h"
+#include "name.h"
+
+#ifndef BASH_MAJOR
+# define BASH_MAJOR "1"
+# define BASH_MINOR "0"
+# define BASH_PATCH "0"
+# define BASH_BUILD "0"
+# define BASH_RELEASE "experimental"
+#endif
+#define BASH_VERSION BASH_MAJOR "." BASH_MINOR "." BASH_PATCH "(" BASH_BUILD ")-" BASH_RELEASE
+
+
+extern const char bash_pre_rc[];
+
+static char *login_files[4];
+
+const char sh_bash1[] =
+ "[B?Enable brace group expansion. This option is only availabe in bash "
+ "compatibility mode. In ksh mode, brace group expansion is always on.]"
+ "[P?Do not follow symbolic links, use physical directory structure "
+ "instead. Only available in bash compatibility mode.]";
+const char sh_bash2[] =
+"[O]:?[shopt_option?\ashopt_option\a is one of the shell options accepted by "
+ "the \bshopt\b builtin. If \ashopt_option\a is present, \b-O\b sets "
+ "the value of that option; \b+O\b unsets it. If \ashopt_option\a is "
+ "not supplied, the names and values of the shell options accepted by "
+ "\bshopt\b are printed on the standard output. If the invocation "
+ "option is \b+O\b, the output is displayed in a format that may be "
+ "reused as input. Only available if invoked as \bbash\b.]"
+"[01:init-file|rcfile]:[file?Execute commands from \afile\a instead of the "
+ "standard personal initialization file ~/.bashrc if the shell is "
+ "interactive. Only available if invoked as \bbash\b.]"
+"[02:editing?For option compatibility with \bbash\b only. Ignored.]"
+"[03:profile?Read either the system-wide startup file or any of the "
+ "personal initialization files. On by default for interactive "
+ "shells. Only available if invoked as \bbash\b.]"
+"[04:posix?If invoked as \bbash\b, turn on POSIX compatibility. \bBash\b in "
+ "POSIX mode is not the same as \bksh\b.]"
+"[05:version?Print version number and exit.]";
+
+const char sh_optshopt[] =
+"+[-1c?\n@(#)$Id: shopt (AT&T Research) 2003-02-13 $\n]"
+"[-author?Karsten Fleischer <K.Fleischer@omnium.de>]"
+USAGE_LICENSE
+"[+NAME?shopt - set/unset variables controlling optional shell behavior]"
+"[+DESCRIPTION?\bshopt\b sets or unsets variables controlling optional shell "
+ "behavior. With no options, or with the \b-p\b option, a list of all "
+ "settable options is displayed, with an indication of whether or not "
+ "each is set.]"
+"[p?Causes output to be displayed in a form that may be reused as input.]"
+"[s?Set each \aoptname\a.]"
+"[u?Unset each \aoptname\a.]"
+"[q?Suppress output (quiet mode). The return status indicates whether the "
+ "\aoptname\a is set or unset. If multiple \aoptname\a arguments are "
+ "given with \b-q\b, the return status is zero if all \aoptname\as are "
+ "enabled; non-zero otherwise.]"
+"[o?Restricts the values of \aoptname\a to be those defined for the \b-o\b "
+ "option to the set builtin.]"
+"[+?If either \b-s\b or \b-u\b is used with no \aoptname\a arguments, the "
+ "display is limited to those options which are set or unset.]"
+"[+?\bshopt\b supports all bash options. Some settings do not have any effect "
+ "or are are always on and cannot be changed.]"
+"[+?The value of \aoptname\a must be one of the following:]{"
+ "[+cdable_vars?If set, arguments to the \bcd\b command are "
+ "assumed to be names of variables whose values are to "
+ "be used if the usual \bcd\b proceeding fails.]"
+ "[+cdspell?Currently ignored.]"
+ "[+checkhash?Always on.]"
+ "[+checkwinsize?Currently ignored.]"
+ "[+cmdhist?Always on.]"
+ "[+dotglob?If set, include filenames beginning with a \b.\b "
+ "in the results of pathname expansion.]"
+ "[+execfail?Always on.]"
+ "[+expand_aliases?Always on.]"
+ "[+extglob?Enable extended pattern matching features.]"
+ "[+histappend?Always on.]"
+ "[+histreedit?If set and an edit mode is selected, the user "
+ "is given the opportunity to re-edit a failed history "
+ "substitution.]"
+ "[+histverify?If set and an edit mode is selected, the result "
+ "of a history substitution will not be executed "
+ "immediately but be placed in the edit buffer for "
+ "further modifications.]"
+ "[+hostcomplete?Currently ignored.]"
+ "[+huponexit?Currently ignored.]"
+ "[+interactive_comments?Always on.]"
+ "[+lithist?Always on.]"
+ "[+login_shell?This option is set if the shell is started as "
+ "a login shell. The value cannot be changed.]"
+ "[+mailwarn?Currently ignored.]"
+ "[+no_empty_cmd_completion?Always on.]"
+ "[+nocaseglob?Match filenames in a case-insensitive fashion "
+ "when performing filename expansion.]"
+ "[+nullglob?Allows filename patterns which match no files to "
+ "expand to a null string, rather than themselves.]"
+ "[+progcomp?Currently ignored.]"
+ "[+promptvars?Currently ignored.]"
+ "[+restricted_shell?This option is set if the shell is started "
+ "as a restricted shell. The value cannot be changed. "
+ "It is not reset during execution of startup files, "
+ "allowing the startup files to determine whether the "
+ "shell is restricted.]"
+ "[+shift_verbose?Currently ignored.]"
+ "[+sourcepath?If set, the \b.\b builtin uses the value of PATH "
+ "to find the directory containing the file supplied "
+ "as an argument.]"
+ "[+xpg_echo?If set, the \becho\b and \bprint\b builtins "
+ "expand backslash-escape sequences.]"
+"}"
+"\n"
+"\n[optname ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+?The return status when listing options is zero if all \aoptnames\a "
+ "are enabled, non-zero otherwise. When setting or unsetting options, "
+ "the return status is zero unless an \aoptname\a is not a valid shell "
+ "option.]"
+"}"
+
+"[+SEE ALSO?\bset\b(1)]"
+;
+
+/* GLOBIGNORE discipline. Turn on SH_DOTGLOB on set, turn off on unset. */
+
+static void put_globignore(register Namval_t* np, const char *val, int flags, Namfun_t *fp)
+{
+ if(val)
+ sh_onoption(SH_DOTGLOB);
+ else
+ sh_offoption(SH_DOTGLOB);
+
+ nv_putv(np,val,flags,fp);
+}
+
+const Namdisc_t SH_GLOBIGNORE_disc = { sizeof(Namfun_t), put_globignore };
+
+/* FUNCNAME discipline */
+
+struct funcname
+{
+ Namfun_t hdr;
+};
+
+static void put_funcname(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ /* bash silently returns with an error when FUNCNAME is set,
+ unsetting FUNCNAME is allowed */
+ if(val && !(flags&NV_RDONLY))
+ error_info.exit(1);
+
+ nv_putv(np,val,flags,fp);
+}
+
+const Namdisc_t SH_FUNCNAME_disc = { sizeof(struct funcname), put_funcname };
+
+#define SET_SET 1
+#define SET_UNSET 2
+#define SET_NOARGS 4
+
+/* shopt builtin */
+
+int b_shopt(int argc,register char *argv[],void *extra)
+{
+ Shell_t *shp = (Shell_t*)extra;
+ int n, f, ret=0;
+ Shopt_t newflags=shp->options, opt;
+ int verbose=PRINT_SHOPT|PRINT_ALL|PRINT_NO_HEADER|PRINT_VERBOSE;
+ int setflag=0, quietflag=0, oflag=0;
+ memset(&opt,0,sizeof(opt));
+#if SHOPT_RAWONLY
+ on_option(&newflags,SH_VIRAW);
+#endif
+ while((n = optget(argv,sh_optshopt)))
+ {
+ switch(n)
+ {
+ case 'p':
+ verbose&=~PRINT_VERBOSE;
+ break;
+ case 's':
+ case 'u':
+ setflag|=n=='s'?SET_SET:SET_UNSET;
+ if(setflag==(SET_SET|SET_UNSET))
+ {
+ errormsg(SH_DICT,ERROR_ERROR,"cannot set and unset options simultaneously");
+ error_info.errors++;
+ }
+ break;
+ case 'q':
+ quietflag=1;
+ break;
+ case 'o':
+ oflag=1;
+ verbose&=~PRINT_SHOPT;
+ break;
+ case ':':
+ errormsg(SH_DICT,2, "%s", opt_info.arg);
+ continue;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
+ return(-1);
+ }
+ }
+ if(error_info.errors)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
+ argc -= opt_info.index;
+ if(argc==0)
+ {
+ /* no args, -s => mask=current options, -u mask=~(current options)
+ else mask=all bits */
+ if(setflag&SET_SET)
+ opt=newflags;
+ else if(setflag&SET_UNSET)
+ for(n=0;n<4;n++)
+ opt.v[n]=~newflags.v[n];
+ else
+ memset(&opt,0xff,sizeof(opt));
+ setflag=SET_NOARGS;
+ }
+ while(argc>0)
+ {
+ f=1;
+ n=sh_lookopt(argv[opt_info.index],&f);
+ if(n<=0||(setflag
+ && (is_option(&opt,SH_INTERACTIVE)
+ || is_option(&opt,SH_RESTRICTED)
+ || is_option(&opt,SH_RESTRICTED2)
+ || is_option(&opt,SH_BASH)
+ || is_option(&opt,SH_LOGIN_SHELL)))
+ ||(oflag&&(n&SH_BASHOPT)))
+ {
+ errormsg(SH_DICT,ERROR_ERROR, e_option, argv[opt_info.index]);
+ error_info.errors++;
+ ret=1;
+ }
+ else if(f)
+ on_option(&opt,n&0xff);
+ else
+ off_option(&opt,n&0xff);
+ opt_info.index++;
+ argc--;
+ }
+ if(setflag&(SET_SET|SET_UNSET))
+ {
+ if(setflag&SET_SET)
+ {
+ if(sh_isoption(SH_INTERACTIVE))
+ off_option(&opt,SH_NOEXEC);
+ if(is_option(&opt,SH_VI)||is_option(&opt,SH_EMACS)||is_option(&opt,SH_GMACS))
+ {
+ off_option(&newflags,SH_VI);
+ off_option(&newflags,SH_EMACS);
+ off_option(&newflags,SH_GMACS);
+ }
+ for(n=0;n<4;n++)
+ newflags.v[n] |= opt.v[n];
+ }
+ else if(setflag&SET_UNSET)
+ for(n=0;n<4;n++)
+ newflags.v[n] &= ~opt.v[n];
+ sh_applyopts(shp,newflags);
+ shp->options = newflags;
+ if(is_option(&newflags,SH_XTRACE))
+ sh_trace(shp,argv,1);
+ }
+ else if(!(setflag&SET_NOARGS)) /* no -s,-u but args, ret=0 if opt&mask==mask */
+ {
+ for(n=0;n<4;n++)
+ ret+=((newflags.v[n]&opt.v[n])!=opt.v[n]);
+ }
+ if(!quietflag&&!(setflag&(SET_SET|SET_UNSET)))
+ sh_printopts(newflags,verbose,&opt);
+ return(ret);
+}
+
+/* mode = 0: init, called two times
+ before parsing shell args with SH_PREINIT state turned on
+ second time after sh_init() is through and with SH_PREINIT state turned off
+ mode > 1: re-init
+ mode < 0: shutdown
+*/
+
+void bash_init(Shell_t *shp,int mode)
+{
+ Sfio_t *iop;
+ Namval_t *np;
+ int n=0,xtrace,verbose;
+ if(mode>0)
+ goto reinit;
+ if(mode < 0)
+ {
+ /* termination code */
+ if(sh_isoption(SH_LOGIN_SHELL) && !sh_isoption(SH_POSIX))
+ sh_source(shp, NiL, sh_mactry(shp,(char*)e_bash_logout));
+ return;
+ }
+
+ if(sh_isstate(SH_PREINIT))
+ { /* pre-init stage */
+ if(sh_isoption(SH_RESTRICTED))
+ sh_onoption(SH_RESTRICTED2);
+ sh_onoption(SH_HISTORY2);
+ sh_onoption(SH_INTERACTIVE_COMM);
+ sh_onoption(SH_SOURCEPATH);
+ sh_onoption(SH_HISTAPPEND);
+ sh_onoption(SH_CMDHIST);
+ sh_onoption(SH_LITHIST);
+ sh_onoption(SH_NOEMPTYCMDCOMPL);
+ if(shp->login_sh==2)
+ sh_onoption(SH_LOGIN_SHELL);
+ if(strcmp(astconf("CONFORMANCE",0,0),"standard")==0)
+ sh_onoption(SH_POSIX);
+ if(strcmp(astconf("UNIVERSE",0,0),"att")==0)
+ sh_onoption(SH_XPG_ECHO);
+ else
+ sh_offoption(SH_XPG_ECHO);
+ if(strcmp(astconf("PATH_RESOLVE",0,0),"physical")==0)
+ sh_onoption(SH_PHYSICAL);
+ else
+ sh_offoption(SH_PHYSICAL);
+
+ /* add builtins */
+ sh_addbuiltin("shopt", b_shopt, &sh);
+
+ /* set up some variables needed for --version
+ * needs to go here because --version option is parsed before the init script.
+ */
+ if(np=nv_open("HOSTTYPE",shp->var_tree,0))
+ nv_putval(np, BASH_HOSTTYPE, NV_NOFREE);
+ if(np=nv_open("MACHTYPE",shp->var_tree,0))
+ nv_putval(np, BASH_MACHTYPE, NV_NOFREE);
+ if(np=nv_open("BASH_VERSION",shp->var_tree,0))
+ nv_putval(np, BASH_VERSION, NV_NOFREE);
+ if(np=nv_open("BASH_VERSINFO",shp->var_tree,0))
+ {
+ char *argv[7];
+ argv[0] = BASH_MAJOR;
+ argv[1] = BASH_MINOR;
+ argv[2] = BASH_PATCH;
+ argv[3] = BASH_BUILD;
+ argv[4] = BASH_RELEASE;
+ argv[5] = BASH_MACHTYPE;
+ argv[6] = 0;
+ nv_setvec(np, 0, 6, argv);
+ nv_onattr(np,NV_RDONLY);
+ }
+ return;
+ }
+
+ /* rest of init stage */
+
+ /* restrict BASH_ENV */
+ if(np=nv_open("BASH_ENV",shp->var_tree,0))
+ {
+ const Namdisc_t *dp = nv_discfun(NV_DCRESTRICT);
+ Namfun_t *fp = calloc(dp->dsize,1);
+ fp->disc = dp;
+ nv_disc(np, fp, 0);
+ }
+
+ /* open GLOBIGNORE node */
+ if(np=nv_open("GLOBIGNORE",shp->var_tree,0))
+ {
+ const Namdisc_t *dp = &SH_GLOBIGNORE_disc;
+ Namfun_t *fp = calloc(dp->dsize,1);
+ fp->disc = dp;
+ nv_disc(np, fp, 0);
+ }
+
+ /* set startup files */
+ n=0;
+ if(sh_isoption(SH_LOGIN_SHELL))
+ {
+ if(!sh_isoption(SH_POSIX))
+ {
+ login_files[n++] = (char*)e_bash_profile;
+ login_files[n++] = (char*)e_bash_login;
+ }
+ login_files[n++] = (char*)e_profile;
+ }
+ shp->login_files = login_files;
+reinit:
+ xtrace = sh_isoption(SH_XTRACE);
+ sh_offoption(SH_XTRACE);
+ verbose = sh_isoption(SH_VERBOSE);
+ sh_offoption(SH_VERBOSE);
+ if(np = nv_open("SHELLOPTS", shp->var_tree, NV_NOADD))
+ nv_offattr(np,NV_RDONLY);
+ iop = sfopen(NULL, bash_pre_rc, "s");
+ sh_eval(iop,0);
+ if(xtrace)
+ sh_offoption(SH_XTRACE);
+ if(verbose)
+ sh_offoption(SH_VERBOSE);
+}
diff --git a/src/cmd/ksh93/sh/defs.c b/src/cmd/ksh93/sh/defs.c
new file mode 100644
index 0000000..308ce22
--- /dev/null
+++ b/src/cmd/ksh93/sh/defs.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * Ksh - AT&T Labs
+ * Written by David Korn
+ * This file defines all the read/write shell global variables
+ */
+
+#include "defs.h"
+#include "jobs.h"
+#include "shlex.h"
+#include "edit.h"
+#include "timeout.h"
+
+Shell_t sh = {0};
+struct shared *shgd;
+#ifdef __IMPORT__
+ Shell_t *_imp__sh = &sh;
+#endif
+
+Dtdisc_t _Nvdisc =
+{
+ offsetof(Namval_t,nvname), -1 , 0, 0, 0, nv_compare
+};
+
+/* reserve room for writable state table */
+char *sh_lexstates[ST_NONE] = {0};
+
+struct jobs job = {0};
+int32_t sh_mailchk = 600;
+
diff --git a/src/cmd/ksh93/sh/deparse.c b/src/cmd/ksh93/sh/deparse.c
new file mode 100644
index 0000000..d7736a4
--- /dev/null
+++ b/src/cmd/ksh93/sh/deparse.c
@@ -0,0 +1,603 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * shell deparser
+ *
+ */
+
+#include "defs.h"
+#include "shnodes.h"
+#include "test.h"
+
+
+#define HUGE_INT (((unsigned)-1)>>1)
+#define BEGIN 0
+#define MIDDLE 1
+#define END 2
+#define PRE 1
+#define POST 2
+
+
+/* flags that can be specified with p_tree() */
+#define NO_NEWLINE 1
+#define NEED_BRACE 2
+#define NO_BRACKET 4
+
+static void p_comlist(const struct dolnod*,int);
+static void p_arg(const struct argnod*, int endchar, int opts);
+static void p_comarg(const struct comnod*);
+static void p_keyword(const char*,int);
+static void p_redirect(const struct ionod*);
+static void p_switch(const struct regnod*);
+static void here_body(const struct ionod*);
+static void p_tree(const Shnode_t*,int);
+
+static int level;
+static int begin_line;
+static int end_line;
+static char io_op[7];
+static char un_op[3] = "-?";
+static const struct ionod *here_doc;
+static Sfio_t *outfile;
+static const char *forinit = "";
+
+extern void sh_deparse(Sfio_t*, const Shnode_t*,int);
+
+void sh_deparse(Sfio_t *out, const Shnode_t *t,int tflags)
+{
+ outfile = out;
+ p_tree(t,tflags);
+}
+/*
+ * print script corresponding to shell tree <t>
+ */
+static void p_tree(register const Shnode_t *t,register int tflags)
+{
+ register char *cp;
+ int save = end_line;
+ int needbrace = (tflags&NEED_BRACE);
+ tflags &= ~NEED_BRACE;
+ if(tflags&NO_NEWLINE)
+ end_line = ' ';
+ else
+ end_line = '\n';
+ switch(t->tre.tretyp&COMMSK)
+ {
+ case TTIME:
+ if(t->tre.tretyp&COMSCAN)
+ p_keyword("!",BEGIN);
+ else
+ p_keyword("time",BEGIN);
+ if(t->par.partre)
+ p_tree(t->par.partre,tflags);
+ level--;
+ break;
+
+ case TCOM:
+ if(begin_line && level>0)
+ sfnputc(outfile,'\t',level);
+ begin_line = 0;
+ p_comarg((struct comnod*)t);
+ break;
+
+ case TSETIO:
+ if(t->tre.tretyp&FPCL)
+ tflags |= NEED_BRACE;
+ else
+ tflags = NO_NEWLINE|NEED_BRACE;
+ p_tree(t->fork.forktre,tflags);
+ p_redirect(t->fork.forkio);
+ break;
+
+ case TFORK:
+ if(needbrace)
+ tflags |= NEED_BRACE;
+ if(t->tre.tretyp&(FAMP|FCOOP))
+ {
+ tflags = NEED_BRACE|NO_NEWLINE;
+ end_line = ' ';
+ }
+ else if(t->fork.forkio)
+ tflags = NO_NEWLINE;
+ p_tree(t->fork.forktre,tflags);
+ if(t->fork.forkio)
+ p_redirect(t->fork.forkio);
+ if(t->tre.tretyp&FCOOP)
+ {
+ sfputr(outfile,"|&",'\n');
+ begin_line = 1;
+ }
+ else if(t->tre.tretyp&FAMP)
+ {
+ sfputr(outfile,"&",'\n');
+ begin_line = 1;
+ }
+ break;
+
+ case TIF:
+ p_keyword("if",BEGIN);
+ p_tree(t->if_.iftre,0);
+ p_keyword("then",MIDDLE);
+ p_tree(t->if_.thtre,0);
+ if(t->if_.eltre)
+ {
+ p_keyword("else",MIDDLE);
+ p_tree(t->if_.eltre,0);
+ }
+ p_keyword("fi",END);
+ break;
+
+ case TWH:
+ if(t->wh.whinc)
+ cp = "for";
+ else if(t->tre.tretyp&COMSCAN)
+ cp = "until";
+ else
+ cp = "while";
+ p_keyword(cp,BEGIN);
+ if(t->wh.whinc)
+ {
+ struct argnod *arg = (t->wh.whtre)->ar.arexpr;
+ sfprintf(outfile,"(( %s; ",forinit);
+ forinit = "";
+ sfputr(outfile,arg->argval,';');
+ arg = (t->wh.whinc)->arexpr;
+ sfprintf(outfile," %s))\n",arg->argval);
+ }
+ else
+ p_tree(t->wh.whtre,0);
+ t = t->wh.dotre;
+ goto dolist;
+
+ case TLST:
+ {
+ Shnode_t *tr = t->lst.lstrit;
+ if(tr->tre.tretyp==TWH && tr->wh.whinc && t->lst.lstlef->tre.tretyp==TARITH)
+ {
+ /* arithmetic for statement */
+ struct argnod *init = (t->lst.lstlef)->ar.arexpr;
+ forinit= init->argval;
+ p_tree(t->lst.lstrit,tflags);
+ break;
+ }
+ if(needbrace)
+ p_keyword("{",BEGIN);
+ p_tree(t->lst.lstlef,0);
+ if(needbrace)
+ tflags = 0;
+ p_tree(t->lst.lstrit,tflags);
+ if(needbrace)
+ p_keyword("}",END);
+ break;
+ }
+
+ case TAND:
+ cp = "&&";
+ goto andor;
+ case TORF:
+ cp = "||";
+ goto andor;
+ case TFIL:
+ cp = "|";
+ andor:
+ {
+ int bracket = 0;
+ if(t->tre.tretyp&TTEST)
+ {
+ tflags |= NO_NEWLINE;
+ if(!(tflags&NO_BRACKET))
+ {
+ p_keyword("[[",BEGIN);
+ tflags |= NO_BRACKET;
+ bracket=1;
+ }
+ }
+ p_tree(t->lst.lstlef,NEED_BRACE|NO_NEWLINE|(tflags&NO_BRACKET));
+ if(tflags&FALTPIPE)
+ {
+ Shnode_t *tt = t->lst.lstrit;
+ if(tt->tre.tretyp!=TFIL || !(tt->lst.lstlef->tre.tretyp&FALTPIPE))
+ {
+ sfputc(outfile,'\n');
+ return;
+ }
+ }
+ sfputr(outfile,cp,here_doc?'\n':' ');
+ if(here_doc)
+ {
+ here_body(here_doc);
+ here_doc = 0;
+ }
+ level++;
+ p_tree(t->lst.lstrit,tflags|NEED_BRACE);
+ if(bracket)
+ p_keyword("]]",END);
+ level--;
+ break;
+ }
+
+ case TPAR:
+ p_keyword("(",BEGIN);
+ p_tree(t->par.partre,0);
+ p_keyword(")",END);
+ break;
+
+ case TARITH:
+ {
+ register struct argnod *ap = t->ar.arexpr;
+ if(begin_line && level)
+ sfnputc(outfile,'\t',level);
+ sfprintf(outfile,"(( %s ))%c",ap->argval,end_line);
+ if(!(tflags&NO_NEWLINE))
+ begin_line=1;
+ break;
+ }
+
+ case TFOR:
+ cp = ((t->tre.tretyp&COMSCAN)?"select":"for");
+ p_keyword(cp,BEGIN);
+ sfputr(outfile,t->for_.fornam,' ');
+ if(t->for_.forlst)
+ {
+ sfputr(outfile,"in",' ');
+ tflags = end_line;
+ end_line = '\n';
+ p_comarg(t->for_.forlst);
+ end_line = tflags;
+ }
+ else
+ sfputc(outfile,'\n');
+ begin_line = 1;
+ t = t->for_.fortre;
+ dolist:
+ p_keyword("do",MIDDLE);
+ p_tree(t,0);
+ p_keyword("done",END);
+ break;
+
+ case TSW:
+ p_keyword("case",BEGIN);
+ p_arg(t->sw.swarg,' ',0);
+ if(t->sw.swlst)
+ {
+ begin_line = 1;
+ sfputr(outfile,"in",'\n');
+ tflags = end_line;
+ end_line = '\n';
+ p_switch(t->sw.swlst);
+ end_line = tflags;
+ }
+ p_keyword("esac",END);
+ break;
+
+ case TFUN:
+ if(t->tre.tretyp&FPOSIX)
+ {
+ sfprintf(outfile,"%s",t->funct.functnam);
+ p_keyword("()\n",BEGIN);
+ }
+ else
+ {
+ p_keyword("function",BEGIN);
+ tflags = (t->funct.functargs?' ':'\n');
+ sfputr(outfile,t->funct.functnam,tflags);
+ if(t->funct.functargs)
+ {
+ tflags = end_line;
+ end_line = '\n';
+ p_comarg(t->funct.functargs);
+ end_line = tflags;
+ }
+ }
+ begin_line = 1;
+ p_keyword("{\n",MIDDLE);
+ begin_line = 1;
+ p_tree(t->funct.functtre,0);
+ p_keyword("}",END);
+ break;
+ /* new test compound command */
+ case TTST:
+ if(!(tflags&NO_BRACKET))
+ p_keyword("[[",BEGIN);
+ if((t->tre.tretyp&TPAREN)==TPAREN)
+ {
+ p_keyword("(",BEGIN);
+ p_tree(t->lst.lstlef,NO_BRACKET|NO_NEWLINE);
+ p_keyword(")",END);
+ }
+ else
+ {
+ int flags = (t->tre.tretyp)>>TSHIFT;
+ if(t->tre.tretyp&TNEGATE)
+ sfputr(outfile,"!",' ');
+ if(t->tre.tretyp&TUNARY)
+ {
+ un_op[1] = flags;
+ sfputr(outfile,un_op,' ');
+ }
+ else
+ cp = ((char*)(shtab_testops+(flags&037)-1)->sh_name);
+ p_arg(&(t->lst.lstlef->arg),' ',0);
+ if(t->tre.tretyp&TBINARY)
+ {
+ sfputr(outfile,cp,' ');
+ p_arg(&(t->lst.lstrit->arg),' ',0);
+ }
+ }
+ if(!(tflags&NO_BRACKET))
+ p_keyword("]]",END);
+ }
+ while(begin_line && here_doc)
+ {
+ here_body(here_doc);
+ here_doc = 0;
+ }
+ end_line = save;
+ return;
+}
+
+/*
+ * print a keyword
+ * increment indent level for flag==BEGIN
+ * decrement indent level for flag==END
+ */
+static void p_keyword(const char *word,int flag)
+{
+ register int sep;
+ if(flag==END)
+ sep = end_line;
+ else if(*word=='[' || *word=='(')
+ sep = ' ';
+ else
+ sep = '\t';
+ if(flag!=BEGIN)
+ level--;
+ if(begin_line && level)
+ sfnputc(outfile,'\t',level);
+ sfputr(outfile,word,sep);
+ if(sep=='\n')
+ begin_line=1;
+ else
+ begin_line=0;
+ if(flag!=END)
+ level++;
+}
+
+static void p_arg(register const struct argnod *arg,register int endchar,int opts)
+{
+ register const char *cp;
+ register int flag;
+ do
+ {
+ if(!arg->argnxt.ap)
+ flag = endchar;
+ else if(opts&PRE)
+ {
+ /* case alternation lists in reverse order */
+ p_arg(arg->argnxt.ap,'|',opts);
+ flag = endchar;
+ }
+ else if(opts)
+ flag = ' ';
+ cp = arg->argval;
+ if(*cp==0 && (arg->argflag&ARG_EXP) && arg->argchn.ap)
+ {
+ int c = (arg->argflag&ARG_RAW)?'>':'<';
+ sfputc(outfile,c);
+ sfputc(outfile,'(');
+ p_tree((Shnode_t*)arg->argchn.ap,0);
+ sfputc(outfile,')');
+ }
+ else if(*cp==0 && opts==POST && arg->argchn.ap)
+ {
+ /* compound assignment */
+ struct fornod *fp=(struct fornod*)arg->argchn.ap;
+ sfprintf(outfile,"%s=(\n",fp->fornam);
+ sfnputc(outfile,'\t',++level);
+ p_tree(fp->fortre,0);
+ if(--level)
+ sfnputc(outfile,'\t',level);
+ sfputc(outfile,')');
+ }
+ else if((arg->argflag&ARG_RAW) && (cp[1] || (*cp!='[' && *cp!=']')))
+ cp = sh_fmtq(cp);
+ sfputr(outfile,cp,flag);
+ if(flag=='\n')
+ begin_line = 1;
+ arg = arg->argnxt.ap;
+ }
+ while((opts&POST) && arg);
+ return;
+}
+
+static void p_redirect(register const struct ionod *iop)
+{
+ register char *cp;
+ register int iof,iof2;
+ for(;iop;iop=iop->ionxt)
+ {
+ iof=iop->iofile;
+ cp = io_op;
+ if(iop->iovname)
+ {
+ sfwrite(outfile,"(;",2);
+ sfputr(outfile,iop->iovname,')');
+ cp++;
+ }
+ else
+ *cp = '0'+(iof&IOUFD);
+ if(iof&IOPUT)
+ {
+ if(*cp == '1' && !iop->iovname)
+ cp++;
+ io_op[1] = '>';
+ }
+ else
+ {
+ if(*cp == '0' && !iop->iovname)
+ cp++;
+ io_op[1] = '<';
+ }
+ io_op[2] = 0;
+ io_op[3] = 0;
+ if(iof&IOLSEEK)
+ {
+ io_op[1] = '#';
+ if(iof&IOARITH)
+ strcpy(&io_op[3]," ((");
+ }
+ else if(iof&IOMOV)
+ io_op[2] = '&';
+ else if(iof&(IORDW|IOAPP))
+ io_op[2] = '>';
+ else if(iof&IOCLOB)
+ io_op[2] = '|';
+ if(iop->iodelim)
+ {
+ /* here document */
+#ifdef xxx
+ iop->iolink = (char*)here_doc;
+#endif
+ here_doc = iop;
+ io_op[2] = '<';
+#ifdef future
+ if(iof&IOSTRIP)
+ io_op[3] = '-';
+#endif
+ }
+ sfputr(outfile,cp,' ');
+ if(iop->ionxt)
+ iof = ' ';
+ else
+ {
+ if((iof=end_line)=='\n')
+ begin_line = 1;
+ }
+ if((iof&IOLSEEK) && (iof&IOARITH))
+ iof2 = iof, iof = ' ';
+ if(iop->iodelim)
+ {
+ if(!(iop->iofile&IODOC))
+ sfwrite(outfile,"''",2);
+ sfputr(outfile,sh_fmtq(iop->iodelim),iof);
+ }
+ else if(iop->iofile&IORAW)
+ sfputr(outfile,sh_fmtq(iop->ioname),iof);
+ else
+ sfputr(outfile,iop->ioname,iof);
+ if((iof&IOLSEEK) && (iof&IOARITH))
+ sfputr(outfile, "))", iof2);
+ }
+ return;
+}
+
+static void p_comarg(register const struct comnod *com)
+{
+ register int flag = end_line;
+ if(com->comtyp&FAMP)
+ sfwrite(outfile,"& ",2);
+ if(com->comarg || com->comio)
+ flag = ' ';
+ if(com->comset)
+ p_arg(com->comset,flag,POST);
+ if(com->comarg)
+ {
+ if(!com->comio)
+ flag = end_line;
+ if(com->comtyp&COMSCAN)
+ p_arg(com->comarg,flag,POST);
+ else
+ p_comlist((struct dolnod*)com->comarg,flag);
+ }
+ if(com->comio)
+ p_redirect(com->comio);
+ return;
+}
+
+static void p_comlist(const struct dolnod *dol,int endchar)
+{
+ register char *cp, *const*argv;
+ register int flag = ' ', special;
+ argv = dol->dolval+ARG_SPARE;
+ cp = *argv;
+ special = (*cp=='[' && cp[1]==0);
+ do
+ {
+ if(cp)
+ argv++;
+ else
+ cp = "";
+ if(*argv==0)
+ {
+ if((flag=endchar)=='\n')
+ begin_line = 1;
+ special = (*cp==']' && cp[1]==0);
+ }
+ sfputr(outfile,special?cp:sh_fmtq(cp),flag);
+ special = 0;
+ }
+ while(cp = *argv);
+ return;
+}
+
+static void p_switch(register const struct regnod *reg)
+{
+ if(level>1)
+ sfnputc(outfile,'\t',level-1);
+ p_arg(reg->regptr,')',PRE);
+ begin_line = 0;
+ sfputc(outfile,'\t');
+ if(reg->regcom)
+ p_tree(reg->regcom,0);
+ level++;
+ if(reg->regflag)
+ p_keyword(";&",END);
+ else
+ p_keyword(";;",END);
+ if(reg->regnxt)
+ p_switch(reg->regnxt);
+ return;
+}
+
+/*
+ * output here documents
+ */
+static void here_body(register const struct ionod *iop)
+{
+ Sfio_t *infile;
+#ifdef xxx
+ if(iop->iolink)
+ here_body((struct inode*)iop->iolink);
+ iop->iolink = 0;
+#endif
+ if(iop->iofile&IOSTRG)
+ infile = sfnew((Sfio_t*)0,iop->ioname,iop->iosize,-1,SF_STRING|SF_READ);
+ else
+ sfseek(infile=sh.heredocs,iop->iooffset,SEEK_SET);
+ sfmove(infile,outfile,iop->iosize,-1);
+ if(iop->iofile&IOSTRG)
+ sfclose(infile);
+ sfputr(outfile,iop->iodelim,'\n');
+}
+
diff --git a/src/cmd/ksh93/sh/env.c b/src/cmd/ksh93/sh/env.c
new file mode 100644
index 0000000..717c8b8
--- /dev/null
+++ b/src/cmd/ksh93/sh/env.c
@@ -0,0 +1,255 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <cdt.h>
+
+#define env_change() (++ast.env_serial)
+
+typedef struct _venv_ Evar_t;
+struct _venv_
+{
+ union
+ {
+ Evar_t *next;
+ char *ptr;
+ } un;
+ Dtlink_t link;
+ int index;
+};
+
+typedef struct _env_
+{
+ Dt_t *dt;
+ Evar_t *freelist;
+ char **env;
+ int count;
+ int extra;
+ int max;
+ int flags;
+} Env_t;
+
+#define _BLD_env 1
+#include <env.h>
+
+#define ENV_VALID 2 /* set if env is valid */
+#define ENV_PMALLOC 1 /* set if Evar_t->un.ptr *s malloced */
+#define ENV_VMALLOC 2 /* set of Evar_t was malloced */
+#define ENV_BITS 3
+
+/*
+ * Compares the name portion of name=... only.
+ */
+static int compare(Dt_t *dt, Void_t* key1, Void_t* key2, Dtdisc_t* disc)
+{
+ register int c,d;
+ const unsigned char *s1=(unsigned const char*)key1;
+ const unsigned char *s2=(unsigned const char*)key2;
+ while((c= *s1++) && c!='=' && c==*s2)
+ s2++;
+ if(c=='=')
+ c = 0;
+ if((d=*s2)=='=')
+ d = 0;
+ return(c-d);
+}
+
+static Dtdisc_t env_disc =
+{
+ 0, -1,
+ sizeof(char*),
+ 0,
+ 0,
+ compare
+};
+
+/*
+ * return a pointer to the environment in sorted order
+ * NULL is returned if there if there is nospace
+ */
+char **env_get(Env_t* ep)
+{
+ register Evar_t *vp;
+ register int n=ep->extra;
+ if(ep->flags&ENV_VALID)
+ return(ep->env+n);
+ if(ep->count > ep->max)
+ {
+ if(ep->flags&ENV_MALLOCED)
+ free((void*)ep->env);
+ if(!(ep->env = (char**)malloc(sizeof(char*)*(ep->count+1))))
+ return(0);
+ ep->flags |= ENV_MALLOCED;
+ ep->max = ep->count;
+ }
+ for(vp=(Evar_t*)dtfirst(ep->dt);vp; vp=(Evar_t*)dtnext(ep->dt,vp))
+ {
+ vp->index = (n<<ENV_BITS) | (vp->index&((1<<ENV_BITS)-1));
+ ep->env[n++] = vp->un.ptr;
+ }
+ ep->env[n] = 0;
+ ep->flags |= ENV_VALID;
+ environ = ep->env+ep->extra;
+ return(ep->env+ep->extra);
+}
+
+/*
+ * add name=value pair given by <str> to <ep>
+ * if malloced is set, the variable will be freed when reassigned
+ * The environment list may become invalidated
+ * Returns 1 for success, 0 for failure
+ */
+int env_add(Env_t *ep, const char *str, int flags)
+{
+ Evar_t *vp = (Evar_t*)dtmatch(ep->dt,(void*)str);
+ if(vp && strcmp(str,vp->un.ptr)==0)
+ return(1);
+ if(flags&ENV_STRDUP)
+ str = strdup(str);
+ if(vp)
+ {
+ if(vp->index&ENV_PMALLOC)
+ free((void*)vp->un.ptr);
+ vp->un.ptr = (char*)str;
+ if(ep->env && (ep->flags&ENV_VALID))
+ ep->env[vp->index>>ENV_BITS] = vp->un.ptr;
+ }
+ else
+ {
+ ep->flags &= ~ENV_VALID;
+ if(vp = ep->freelist)
+ ep->freelist = vp->un.next;
+ else if(vp = newof((Evar_t*)0,Evar_t,2,0))
+ {
+ vp->index = ENV_VMALLOC;
+ ep->freelist = (vp+1);
+ ep->freelist->un.next = 0;
+ }
+ else
+ return(0);
+ vp->un.ptr = (void*)str;
+ if(!(vp=dtinsert(ep->dt,vp)))
+ return(0);
+ ep->count++;
+ }
+ if(flags)
+ vp->index |= ENV_PMALLOC;
+ else
+ vp->index &= ~ENV_PMALLOC;
+ env_change();
+ return(1);
+}
+
+/*
+ * delete name from <ep>
+ * The environment list may become invalidated
+ * Returns 1 for success, 0 for if name is not present
+ */
+int env_delete(Env_t *ep, const char *str)
+{
+ Evar_t *vp = (Evar_t*)dtmatch(ep->dt,(void*)str);
+ if(!vp)
+ return(0);
+ ep->flags &= ~ENV_VALID;
+ if(vp->index&ENV_PMALLOC)
+ free((void*)vp->un.ptr);
+ dtdelete(ep->dt,vp);
+ vp->un.next = ep->freelist;
+ ep->freelist = vp;
+ env_change();
+ return(1);
+}
+
+/*
+ * open up a structure to support environment variables
+ * initialize with environment give by <envp>
+ * If <extra> > 0, <extra> slots will be left at beginning of
+ * environment list when env_get() is involed.
+ * If <extra>==ENV_USABLE, then the original environ can be
+ * used and returned. Otherwise, a new one will be returned
+ */
+Env_t *env_open(char **envp, int extra)
+{
+ char **env;
+ Env_t *ep;
+ Evar_t *vp;
+ int n=2;
+ if(!(ep = newof((Env_t*)0,Env_t,1,0)))
+ return(0);
+ if(!(ep->dt = dtopen(&env_disc,Dtoset)))
+ return(0);
+ if(env=envp)
+ {
+ while(*env++);
+ n = (env+2)-envp;
+ }
+ if(extra==ENV_STABLE)
+ {
+ ep->env = envp;
+ ep->max = n-1;
+ }
+ else
+ ep->count = ep->extra = extra;
+ ep->freelist = vp = newof((Evar_t*)0,Evar_t,n,0);
+ vp->index = ENV_VMALLOC;
+ while(--n>0)
+ {
+ vp->un.next = (vp+1);
+ vp++;
+ }
+ vp->un.next = 0;
+ if(env)
+ {
+ for(env=envp; *env; env++)
+ env_add(ep,*env,0);
+ }
+ return(ep);
+}
+
+/*
+ * close <ep> and free up all space used by it
+ */
+void env_close(Env_t *ep)
+{
+ Evar_t *vp, *vpnext,*top;
+ if(ep->env && (ep->flags&ENV_MALLOCED))
+ free((void*)ep->env);
+ for(vp=(Evar_t*)dtfirst(ep->dt);vp; vp=vpnext)
+ {
+ vpnext = (Evar_t*)dtnext(ep->dt,vp);
+ env_delete(ep,vp->un.ptr);
+ }
+ for(top=0,vp = ep->freelist; vp; vp = vpnext)
+ {
+ vpnext = vp->un.next;
+ if(vp->index&ENV_VMALLOC)
+ {
+ vp->un.next = top;
+ top = vp;
+ }
+ }
+ for(vp=top; vp; vp = vpnext)
+ {
+ vpnext = vp->un.next;
+ free((void*)vp);
+ }
+ dtclose(ep->dt);
+}
diff --git a/src/cmd/ksh93/sh/expand.c b/src/cmd/ksh93/sh/expand.c
new file mode 100644
index 0000000..40c3dd1
--- /dev/null
+++ b/src/cmd/ksh93/sh/expand.c
@@ -0,0 +1,468 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * File name expansion
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#if KSHELL
+# include "defs.h"
+# include "variables.h"
+# include "test.h"
+#else
+# include <ast.h>
+# include <ctype.h>
+# include <setjmp.h>
+#endif /* KSHELL */
+#include <glob.h>
+#include <ls.h>
+#include <stak.h>
+#include <ast_dir.h>
+#include "io.h"
+#include "path.h"
+
+#if !SHOPT_BRACEPAT
+# define SHOPT_BRACEPAT 0
+#endif
+
+#if KSHELL
+# define argbegin argnxt.cp
+ static const char *sufstr;
+ static int suflen;
+ static int scantree(Dt_t*,const char*, struct argnod**);
+#else
+# define sh_sigcheck(sig) (0)
+# define sh_access access
+# define suflen 0
+#endif /* KSHELL */
+
+
+/*
+ * This routine builds a list of files that match a given pathname
+ * Uses external routine strgrpmatch() to match each component
+ * A leading . must match explicitly
+ *
+ */
+
+#ifndef GLOB_AUGMENTED
+# define GLOB_AUGMENTED 0
+#endif
+
+#define GLOB_RESCAN 1
+#define globptr() ((struct glob*)membase)
+
+static struct glob *membase;
+
+#if GLOB_VERSION >= 20010916L
+static char *nextdir(glob_t *gp, char *dir)
+{
+ Shell_t *shp = sh_getinterp();
+ Pathcomp_t *pp = (Pathcomp_t*)gp->gl_handle;
+ if(!dir)
+ pp = path_get(shp,"");
+ else
+ pp = pp->next;
+ gp->gl_handle = (void*)pp;
+ if(pp)
+ return(pp->name);
+ return(0);
+}
+#endif
+
+int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead)
+{
+ glob_t gdata;
+ register struct argnod *ap;
+ register glob_t *gp= &gdata;
+ register int flags,extra=0;
+#if SHOPT_BASH
+ register int off;
+ register char *sp, *cp, *cp2;
+#endif
+ sh_stats(STAT_GLOBS);
+ memset(gp,0,sizeof(gdata));
+ flags = GLOB_GROUP|GLOB_AUGMENTED|GLOB_NOCHECK|GLOB_NOSORT|GLOB_STACK|GLOB_LIST|GLOB_DISC;
+ if(sh_isoption(SH_MARKDIRS))
+ flags |= GLOB_MARK;
+ if(sh_isoption(SH_GLOBSTARS))
+ flags |= GLOB_STARSTAR;
+#if SHOPT_BASH
+#if 0
+ if(sh_isoption(SH_BASH) && !sh_isoption(SH_EXTGLOB))
+ flags &= ~GLOB_AUGMENTED;
+#endif
+ if(sh_isoption(SH_NULLGLOB))
+ flags &= ~GLOB_NOCHECK;
+ if(sh_isoption(SH_NOCASEGLOB))
+ flags |= GLOB_ICASE;
+#endif
+ if(sh_isstate(SH_COMPLETE))
+ {
+#if KSHELL
+ extra += scantree(shp->alias_tree,pattern,arghead);
+ extra += scantree(shp->fun_tree,pattern,arghead);
+# if GLOB_VERSION >= 20010916L
+ gp->gl_nextdir = nextdir;
+# endif
+#endif /* KSHELL */
+ flags |= GLOB_COMPLETE;
+ flags &= ~GLOB_NOCHECK;
+ }
+#if SHOPT_BASH
+ if(off = staktell())
+ sp = stakfreeze(0);
+ if(sh_isoption(SH_BASH))
+ {
+ /*
+ * For bash, FIGNORE is a colon separated list of suffixes to
+ * ignore when doing filename/command completion.
+ * GLOBIGNORE is similar to ksh FIGNORE, but colon separated
+ * instead of being an augmented shell pattern.
+ * Generate shell patterns out of those here.
+ */
+ if(sh_isstate(SH_FCOMPLETE))
+ cp=nv_getval(sh_scoped(shp,FIGNORENOD));
+ else
+ {
+ static Namval_t *GLOBIGNORENOD;
+ if(!GLOBIGNORENOD)
+ GLOBIGNORENOD = nv_open("GLOBIGNORE",shp->var_tree,0);
+ cp=nv_getval(sh_scoped(shp,GLOBIGNORENOD));
+ }
+ if(cp)
+ {
+ flags |= GLOB_AUGMENTED;
+ stakputs("@(");
+ if(!sh_isstate(SH_FCOMPLETE))
+ {
+ stakputs(cp);
+ for(cp=stakptr(off); *cp; cp++)
+ if(*cp == ':')
+ *cp='|';
+ }
+ else
+ {
+ cp2 = strtok(cp, ":");
+ if(!cp2)
+ cp2=cp;
+ do
+ {
+ stakputc('*');
+ stakputs(cp2);
+ if(cp2 = strtok(NULL, ":"))
+ {
+ *(cp2-1)=':';
+ stakputc('|');
+ }
+ } while(cp2);
+ }
+ stakputc(')');
+ gp->gl_fignore = stakfreeze(1);
+ }
+ else if(!sh_isstate(SH_FCOMPLETE) && sh_isoption(SH_DOTGLOB))
+ gp->gl_fignore = "";
+ }
+ else
+#endif
+ gp->gl_fignore = nv_getval(sh_scoped(shp,FIGNORENOD));
+ if(suflen)
+ gp->gl_suffix = sufstr;
+ gp->gl_intr = &shp->trapnote;
+ suflen = 0;
+ if(memcmp(pattern,"~(N",3)==0)
+ flags &= ~GLOB_NOCHECK;
+ glob(pattern, flags, 0, gp);
+#if SHOPT_BASH
+ if(off)
+ stakset(sp,off);
+ else
+ stakseek(0);
+#endif
+ sh_sigcheck(shp);
+ for(ap= (struct argnod*)gp->gl_list; ap; ap = ap->argnxt.ap)
+ {
+ ap->argchn.ap = ap->argnxt.ap;
+ if(!ap->argnxt.ap)
+ ap->argchn.ap = *arghead;
+ }
+ if(gp->gl_list)
+ *arghead = (struct argnod*)gp->gl_list;
+ return(gp->gl_pathc+extra);
+}
+
+#if KSHELL
+
+/*
+ * scan tree and add each name that matches the given pattern
+ */
+static int scantree(Dt_t *tree, const char *pattern, struct argnod **arghead)
+{
+ register Namval_t *np;
+ register struct argnod *ap;
+ register int nmatch=0;
+ register char *cp;
+ np = (Namval_t*)dtfirst(tree);
+ for(;np && !nv_isnull(np);(np = (Namval_t*)dtnext(tree,np)))
+ {
+ if(strmatch(cp=nv_name(np),pattern))
+ {
+ ap = (struct argnod*)stakseek(ARGVAL);
+ stakputs(cp);
+ ap = (struct argnod*)stakfreeze(1);
+ ap->argbegin = NIL(char*);
+ ap->argchn.ap = *arghead;
+ ap->argflag = ARG_RAW|ARG_MAKE;
+ *arghead = ap;
+ nmatch++;
+ }
+ }
+ return(nmatch);
+}
+
+/*
+ * file name completion
+ * generate the list of files found by adding an suffix to end of name
+ * The number of matches is returned
+ */
+
+int path_complete(Shell_t *shp,const char *name,register const char *suffix, struct argnod **arghead)
+{
+ sufstr = suffix;
+ suflen = strlen(suffix);
+ return(path_expand(shp,name,arghead));
+}
+
+#endif
+
+#if SHOPT_BRACEPAT
+
+static int checkfmt(Sfio_t* sp, void* vp, Sffmt_t* fp)
+{
+ return -1;
+}
+
+int path_generate(Shell_t *shp,struct argnod *todo, struct argnod **arghead)
+/*@
+ assume todo!=0;
+ return count satisfying count>=1;
+@*/
+{
+ register char *cp;
+ register int brace;
+ register struct argnod *ap;
+ struct argnod *top = 0;
+ struct argnod *apin;
+ char *pat, *rescan;
+ char *format;
+ char comma, range=0;
+ int first, last, incr, count = 0;
+ char tmp[32], end[1];
+ todo->argchn.ap = 0;
+again:
+ apin = ap = todo;
+ todo = ap->argchn.ap;
+ cp = ap->argval;
+ range = comma = brace = 0;
+ /* first search for {...,...} */
+ while(1) switch(*cp++)
+ {
+ case '{':
+ if(brace++==0)
+ pat = cp;
+ break;
+ case '}':
+ if(--brace>0)
+ break;
+ if(brace==0 && comma && *cp!='(')
+ goto endloop1;
+ comma = brace = 0;
+ break;
+ case '.':
+ if(brace==1 && *cp=='.')
+ {
+ char *endc;
+ incr = 1;
+ if(isdigit(*pat) || *pat=='+' || *pat=='-')
+ {
+ first = strtol(pat,&endc,0);
+ if(endc==(cp-1))
+ {
+ last = strtol(cp+1,&endc,0);
+ if(*endc=='.' && endc[1]=='.')
+ incr = strtol(endc+2,&endc,0);
+ else if(last<first)
+ incr = -1;
+ if(incr)
+ {
+ if(*endc=='%')
+ {
+ Sffmt_t fmt;
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.version = SFIO_VERSION;
+ fmt.form = endc;
+ fmt.extf = checkfmt;
+ sfprintf(sfstdout, "%!", &fmt);
+ if(!(fmt.flags&(SFFMT_LLONG|SFFMT_LDOUBLE)))
+ switch (fmt.fmt)
+ {
+ case 'c':
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ format = endc;
+ endc = fmt.form;
+ break;
+ }
+ }
+ else
+ format = "%d";
+ if(*endc=='}')
+ {
+ cp = endc+1;
+ range = 2;
+ goto endloop1;
+ }
+ }
+ }
+ }
+ else if((cp[2]=='}' || cp[2]=='.' && cp[3]=='.') && ((*pat>='a' && *pat<='z' && cp[1]>='a' && cp[1]<='z') || (*pat>='A' && *pat<='Z' && cp[1]>='A' && cp[1]<='Z')))
+ {
+ first = *pat;
+ last = cp[1];
+ cp += 2;
+ if(*cp=='.')
+ {
+ incr = strtol(cp+2,&endc,0);
+ cp = endc;
+ }
+ else if(first>last)
+ incr = -1;
+ if(incr && *cp=='}')
+ {
+ cp++;
+ range = 1;
+ goto endloop1;
+ }
+ }
+ cp++;
+ }
+ break;
+ case ',':
+ if(brace==1)
+ comma = 1;
+ break;
+ case '\\':
+ cp++;
+ break;
+ case 0:
+ /* insert on stack */
+ ap->argchn.ap = top;
+ top = ap;
+ if(todo)
+ goto again;
+ for(; ap; ap=apin)
+ {
+ apin = ap->argchn.ap;
+ if(!sh_isoption(SH_NOGLOB))
+ brace=path_expand(shp,ap->argval,arghead);
+ else
+ {
+ ap->argchn.ap = *arghead;
+ *arghead = ap;
+ brace=1;
+ }
+ if(brace)
+ {
+ count += brace;
+ (*arghead)->argflag |= ARG_MAKE;
+ }
+ }
+ return(count);
+ }
+endloop1:
+ rescan = cp;
+ cp = pat-1;
+ *cp = 0;
+ while(1)
+ {
+ brace = 0;
+ if(range)
+ {
+ if(range==1)
+ {
+ pat[0] = first;
+ cp = &pat[1];
+ }
+ else
+ {
+ *(rescan - 1) = 0;
+ sfsprintf(pat=tmp,sizeof(tmp),format,first);
+ *(rescan - 1) = '}';
+ *(cp = end) = 0;
+ }
+ if(incr*(first+incr) > last*incr)
+ *cp = '}';
+ else
+ first += incr;
+ }
+ /* generate each pattern and put on the todo list */
+ else while(1) switch(*++cp)
+ {
+ case '\\':
+ cp++;
+ break;
+ case '{':
+ brace++;
+ break;
+ case ',':
+ if(brace==0)
+ goto endloop2;
+ break;
+ case '}':
+ if(--brace<0)
+ goto endloop2;
+ }
+ endloop2:
+ brace = *cp;
+ *cp = 0;
+ sh_sigcheck(shp);
+ ap = (struct argnod*)stakseek(ARGVAL);
+ ap->argflag = ARG_RAW;
+ ap->argchn.ap = todo;
+ stakputs(apin->argval);
+ stakputs(pat);
+ stakputs(rescan);
+ todo = ap = (struct argnod*)stakfreeze(1);
+ if(brace == '}')
+ break;
+ if(!range)
+ pat = cp+1;
+ }
+ goto again;
+}
+
+#endif /* SHOPT_BRACEPAT */
diff --git a/src/cmd/ksh93/sh/fault.c b/src/cmd/ksh93/sh/fault.c
new file mode 100644
index 0000000..2d22e42
--- /dev/null
+++ b/src/cmd/ksh93/sh/fault.c
@@ -0,0 +1,672 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Fault handling routines
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <fcin.h>
+#include "io.h"
+#include "history.h"
+#include "shlex.h"
+#include "variables.h"
+#include "jobs.h"
+#include "path.h"
+#include "builtins.h"
+#include "ulimit.h"
+
+#define abortsig(sig) (sig==SIGABRT || sig==SIGBUS || sig==SIGILL || sig==SIGSEGV)
+
+static char indone;
+static int cursig = -1;
+
+#if !_std_malloc
+# include <vmalloc.h>
+#endif
+#if defined(VMFL) && (VMALLOC_VERSION>=20031205L)
+ /*
+ * This exception handler is called after vmalloc() unlocks the region
+ */
+ static int malloc_done(Vmalloc_t* vm, int type, Void_t* val, Vmdisc_t* dp)
+ {
+ dp->exceptf = 0;
+ sh_exit(SH_EXITSIG);
+ return(0);
+ }
+#endif
+
+/*
+ * Most signals caught or ignored by the shell come here
+*/
+void sh_fault(register int sig)
+{
+ register Shell_t *shp = sh_getinterp();
+ register int flag=0;
+ register char *trap;
+ register struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ int action=0;
+ /* reset handler */
+ if(!(sig&SH_TRAP))
+ signal(sig, sh_fault);
+ sig &= ~SH_TRAP;
+#ifdef SIGWINCH
+ if(sig==SIGWINCH)
+ {
+ int rows=0, cols=0;
+ int32_t v;
+ astwinsize(2,&rows,&cols);
+ if(v = cols)
+ nv_putval(COLUMNS, (char*)&v, NV_INT32|NV_RDONLY);
+ if(v = rows)
+ nv_putval(LINES, (char*)&v, NV_INT32|NV_RDONLY);
+ shp->winch++;
+ }
+#endif /* SIGWINCH */
+ trap = shp->st.trapcom[sig];
+ if(shp->savesig)
+ {
+ /* critical region, save and process later */
+ if(!(shp->sigflag[sig]&SH_SIGIGNORE))
+ shp->savesig = sig;
+ return;
+ }
+ if(sig==SIGALRM && shp->bltinfun==b_sleep)
+ {
+ if(trap && *trap)
+ {
+ shp->trapnote |= SH_SIGTRAP;
+ shp->sigflag[sig] |= SH_SIGTRAP;
+ }
+ return;
+ }
+ if(shp->subshell && trap && sig!=SIGINT && sig!=SIGQUIT && sig!=SIGWINCH && sig!=SIGCONT)
+ {
+ shp->exitval = SH_EXITSIG|sig;
+ sh_subfork();
+ shp->exitval = 0;
+ return;
+ }
+ /* handle ignored signals */
+ if(trap && *trap==0)
+ return;
+ flag = shp->sigflag[sig]&~SH_SIGOFF;
+ if(!trap)
+ {
+ if(sig==SIGINT && (shp->trapnote&SH_SIGIGNORE))
+ return;
+ if(flag&SH_SIGIGNORE)
+ {
+ if(shp->subshell)
+ shp->ignsig = sig;
+ sigrelease(sig);
+ return;
+ }
+ if(flag&SH_SIGDONE)
+ {
+ void *ptr=0;
+ if((flag&SH_SIGINTERACTIVE) && sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_FORKED) && ! shp->subshell)
+ {
+ /* check for TERM signal between fork/exec */
+ if(sig==SIGTERM && job.in_critical)
+ shp->trapnote |= SH_SIGTERM;
+ return;
+ }
+ shp->lastsig = sig;
+ sigrelease(sig);
+ if(pp->mode != SH_JMPSUB)
+ {
+ if(pp->mode < SH_JMPSUB)
+ pp->mode = shp->subshell?SH_JMPSUB:SH_JMPFUN;
+ else
+ pp->mode = SH_JMPEXIT;
+ }
+ if(shp->subshell)
+ sh_exit(SH_EXITSIG);
+ if(sig==SIGABRT || (abortsig(sig) && (ptr = malloc(1))))
+ {
+ if(ptr)
+ free(ptr);
+ sh_done(shp,sig);
+ }
+ /* mark signal and continue */
+ shp->trapnote |= SH_SIGSET;
+ if(sig <= shp->gd->sigmax)
+ shp->sigflag[sig] |= SH_SIGSET;
+#if defined(VMFL) && (VMALLOC_VERSION>=20031205L)
+ if(abortsig(sig))
+ {
+ /* abort inside malloc, process when malloc returns */
+ /* VMFL defined when using vmalloc() */
+ Vmdisc_t* dp = vmdisc(Vmregion,0);
+ if(dp)
+ dp->exceptf = malloc_done;
+ }
+#endif
+ return;
+ }
+ }
+ errno = 0;
+ if(pp->mode==SH_JMPCMD || (pp->mode==1 && shp->bltinfun) && !(flag&SH_SIGIGNORE))
+ shp->lastsig = sig;
+ if(trap)
+ {
+ /*
+ * propogate signal to foreground group
+ */
+ if(sig==SIGHUP && job.curpgid)
+ killpg(job.curpgid,SIGHUP);
+ flag = SH_SIGTRAP;
+ }
+ else
+ {
+ shp->lastsig = sig;
+ flag = SH_SIGSET;
+#ifdef SIGTSTP
+ if(sig==SIGTSTP)
+ {
+ shp->trapnote |= SH_SIGTSTP;
+ if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK))
+ {
+ sigrelease(sig);
+ sh_exit(SH_EXITSIG);
+ flag = 0;
+ }
+ }
+#endif /* SIGTSTP */
+ }
+#ifdef ERROR_NOTIFY
+ if((error_info.flags&ERROR_NOTIFY) && shp->bltinfun)
+ action = (*shp->bltinfun)(-sig,(char**)0,(void*)0);
+ if(action>0)
+ return;
+#endif
+ if(shp->bltinfun && shp->bltindata.notify)
+ {
+ shp->bltindata.sigset = 1;
+ return;
+ }
+ shp->trapnote |= flag;
+ if(sig <= shp->gd->sigmax)
+ shp->sigflag[sig] |= flag;
+ if(pp->mode==SH_JMPCMD && sh_isstate(SH_STOPOK))
+ {
+ if(action<0)
+ return;
+ sigrelease(sig);
+ sh_exit(SH_EXITSIG);
+ }
+}
+
+/*
+ * initialize signal handling
+ */
+void sh_siginit(void *ptr)
+{
+ Shell_t *shp = (Shell_t*)ptr;
+ register int sig, n;
+ register const struct shtable2 *tp = shtab_signals;
+ sig_begin();
+ /* find the largest signal number in the table */
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+ if ((n = SIGRTMIN) > 0 && (sig = SIGRTMAX) > n && sig < SH_TRAP)
+ {
+ shp->gd->sigruntime[SH_SIGRTMIN] = n;
+ shp->gd->sigruntime[SH_SIGRTMAX] = sig;
+ }
+#endif /* SIGRTMIN && SIGRTMAX */
+ n = SIGTERM;
+ while(*tp->sh_name)
+ {
+ sig = (tp->sh_number&((1<<SH_SIGBITS)-1));
+ if (!(sig-- & SH_TRAP))
+ {
+ if ((tp->sh_number>>SH_SIGBITS) & SH_SIGRUNTIME)
+ sig = shp->gd->sigruntime[sig];
+ if(sig>n && sig<SH_TRAP)
+ n = sig;
+ }
+ tp++;
+ }
+ shp->gd->sigmax = n++;
+ shp->st.trapcom = (char**)calloc(n,sizeof(char*));
+ shp->sigflag = (unsigned char*)calloc(n,1);
+ shp->gd->sigmsg = (char**)calloc(n,sizeof(char*));
+ for(tp=shtab_signals; sig=tp->sh_number; tp++)
+ {
+ n = (sig>>SH_SIGBITS);
+ if((sig &= ((1<<SH_SIGBITS)-1)) > (shp->gd->sigmax+1))
+ continue;
+ sig--;
+ if(n&SH_SIGRUNTIME)
+ sig = shp->gd->sigruntime[sig];
+ if(sig>=0)
+ {
+ shp->sigflag[sig] = n;
+ if(*tp->sh_name)
+ shp->gd->sigmsg[sig] = (char*)tp->sh_value;
+ }
+ }
+}
+
+/*
+ * Turn on trap handler for signal <sig>
+ */
+void sh_sigtrap(register int sig)
+{
+ register int flag;
+ void (*fun)(int);
+ sh.st.otrapcom = 0;
+ if(sig==0)
+ sh_sigdone();
+ else if(!((flag=sh.sigflag[sig])&(SH_SIGFAULT|SH_SIGOFF)))
+ {
+ /* don't set signal if already set or off by parent */
+ if((fun=signal(sig,sh_fault))==SIG_IGN)
+ {
+ signal(sig,SIG_IGN);
+ flag |= SH_SIGOFF;
+ }
+ else
+ {
+ flag |= SH_SIGFAULT;
+ if(sig==SIGALRM && fun!=SIG_DFL && fun!=sh_fault)
+ signal(sig,fun);
+ }
+ flag &= ~(SH_SIGSET|SH_SIGTRAP);
+ sh.sigflag[sig] = flag;
+ }
+}
+
+/*
+ * set signal handler so sh_done is called for all caught signals
+ */
+void sh_sigdone(void)
+{
+ register int flag, sig = shgd->sigmax;
+ sh.sigflag[0] |= SH_SIGFAULT;
+ for(sig=shgd->sigmax; sig>0; sig--)
+ {
+ flag = sh.sigflag[sig];
+ if((flag&(SH_SIGDONE|SH_SIGIGNORE|SH_SIGINTERACTIVE)) && !(flag&(SH_SIGFAULT|SH_SIGOFF)))
+ sh_sigtrap(sig);
+ }
+}
+
+/*
+ * Restore to default signals
+ * Free the trap strings if mode is non-zero
+ * If mode>1 then ignored traps cause signal to be ignored
+ */
+void sh_sigreset(register int mode)
+{
+ register char *trap;
+ register int flag, sig=sh.st.trapmax;
+ while(sig-- > 0)
+ {
+ if(trap=sh.st.trapcom[sig])
+ {
+ flag = sh.sigflag[sig]&~(SH_SIGTRAP|SH_SIGSET);
+ if(*trap)
+ {
+ if(mode)
+ free(trap);
+ sh.st.trapcom[sig] = 0;
+ }
+ else if(sig && mode>1)
+ {
+ if(sig!=SIGCHLD)
+ signal(sig,SIG_IGN);
+ flag &= ~SH_SIGFAULT;
+ flag |= SH_SIGOFF;
+ }
+ sh.sigflag[sig] = flag;
+ }
+ }
+ for(sig=SH_DEBUGTRAP-1;sig>=0;sig--)
+ {
+ if(trap=sh.st.trap[sig])
+ {
+ if(mode)
+ free(trap);
+ sh.st.trap[sig] = 0;
+ }
+
+ }
+ sh.st.trapcom[0] = 0;
+ if(mode)
+ sh.st.trapmax = 0;
+ sh.trapnote=0;
+}
+
+/*
+ * free up trap if set and restore signal handler if modified
+ */
+void sh_sigclear(register int sig)
+{
+ register int flag = sh.sigflag[sig];
+ register char *trap;
+ sh.st.otrapcom=0;
+ if(!(flag&SH_SIGFAULT))
+ return;
+ flag &= ~(SH_SIGTRAP|SH_SIGSET);
+ if(trap=sh.st.trapcom[sig])
+ {
+ if(!sh.subshell)
+ free(trap);
+ sh.st.trapcom[sig]=0;
+ }
+ sh.sigflag[sig] = flag;
+}
+
+/*
+ * check for traps
+ */
+
+void sh_chktrap(Shell_t* shp)
+{
+ register int sig=shp->st.trapmax;
+ register char *trap;
+ if(!(shp->trapnote&~SH_SIGIGNORE))
+ sig=0;
+ shp->trapnote &= ~SH_SIGTRAP;
+ /* execute errexit trap first */
+ if(sh_isstate(SH_ERREXIT) && shp->exitval)
+ {
+ int sav_trapnote = shp->trapnote;
+ shp->trapnote &= ~SH_SIGSET;
+ if(shp->st.trap[SH_ERRTRAP])
+ {
+ trap = shp->st.trap[SH_ERRTRAP];
+ shp->st.trap[SH_ERRTRAP] = 0;
+ sh_trap(trap,0);
+ shp->st.trap[SH_ERRTRAP] = trap;
+ }
+ shp->trapnote = sav_trapnote;
+ if(sh_isoption(SH_ERREXIT))
+ {
+ struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ pp->mode = SH_JMPEXIT;
+ sh_exit(shp->exitval);
+ }
+ }
+ if(shp->sigflag[SIGALRM]&SH_SIGALRM)
+ sh_timetraps(shp);
+#ifdef SHOPT_BGX
+ if((shp->sigflag[SIGCHLD]&SH_SIGTRAP) && shp->st.trapcom[SIGCHLD])
+ job_chldtrap(shp,shp->st.trapcom[SIGCHLD],1);
+#endif /* SHOPT_BGX */
+ while(--sig>=0)
+ {
+ if(sig==cursig)
+ continue;
+#ifdef SHOPT_BGX
+ if(sig==SIGCHLD)
+ continue;
+#endif /* SHOPT_BGX */
+ if(shp->sigflag[sig]&SH_SIGTRAP)
+ {
+ shp->sigflag[sig] &= ~SH_SIGTRAP;
+ if(trap=shp->st.trapcom[sig])
+ {
+ cursig = sig;
+ sh_trap(trap,0);
+ cursig = -1;
+ }
+ }
+ }
+}
+
+
+/*
+ * parse and execute the given trap string, stream or tree depending on mode
+ * mode==0 for string, mode==1 for stream, mode==2 for parse tree
+ */
+int sh_trap(const char *trap, int mode)
+{
+ Shell_t *shp = sh_getinterp();
+ int jmpval, savxit = shp->exitval;
+ int was_history = sh_isstate(SH_HISTORY);
+ int was_verbose = sh_isstate(SH_VERBOSE);
+ int staktop = staktell();
+ char *savptr = stakfreeze(0);
+ char ifstable[256];
+ struct checkpt buff;
+ Fcin_t savefc;
+ fcsave(&savefc);
+ memcpy(ifstable,shp->ifstable,sizeof(ifstable));
+ sh_offstate(SH_HISTORY);
+ sh_offstate(SH_VERBOSE);
+ shp->intrap++;
+ sh_pushcontext(shp,&buff,SH_JMPTRAP);
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval == 0)
+ {
+ if(mode==2)
+ sh_exec((Shnode_t*)trap,sh_isstate(SH_ERREXIT));
+ else
+ {
+ Sfio_t *sp;
+ if(mode)
+ sp = (Sfio_t*)trap;
+ else
+ sp = sfopen(NIL(Sfio_t*),trap,"s");
+ sh_eval(sp,0);
+ }
+ }
+ else if(indone)
+ {
+ if(jmpval==SH_JMPSCRIPT)
+ indone=0;
+ else
+ {
+ if(jmpval==SH_JMPEXIT)
+ savxit = shp->exitval;
+ jmpval=SH_JMPTRAP;
+ }
+ }
+ sh_popcontext(shp,&buff);
+ shp->intrap--;
+ sfsync(shp->outpool);
+ if(!shp->indebug && jmpval!=SH_JMPEXIT && jmpval!=SH_JMPFUN)
+ shp->exitval=savxit;
+ stakset(savptr,staktop);
+ fcrestore(&savefc);
+ memcpy(shp->ifstable,ifstable,sizeof(ifstable));
+ if(was_history)
+ sh_onstate(SH_HISTORY);
+ if(was_verbose)
+ sh_onstate(SH_VERBOSE);
+ exitset();
+ if(jmpval>SH_JMPTRAP && (((struct checkpt*)shp->jmpbuffer)->prev || ((struct checkpt*)shp->jmpbuffer)->mode==SH_JMPSCRIPT))
+ siglongjmp(*shp->jmplist,jmpval);
+ return(shp->exitval);
+}
+
+/*
+ * exit the current scope and jump to an earlier one based on pp->mode
+ */
+void sh_exit(register int xno)
+{
+ Shell_t *shp = sh_getinterp();
+ register struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ register int sig=0;
+ register Sfio_t* pool;
+ shp->exitval=xno;
+ if(xno==SH_EXITSIG)
+ shp->exitval |= (sig=shp->lastsig);
+ if(pp && pp->mode>1)
+ cursig = -1;
+#ifdef SIGTSTP
+ if(shp->trapnote&SH_SIGTSTP)
+ {
+ /* ^Z detected by the shell */
+ shp->trapnote = 0;
+ shp->sigflag[SIGTSTP] = 0;
+ if(!shp->subshell && sh_isstate(SH_MONITOR) && !sh_isstate(SH_STOPOK))
+ return;
+ if(sh_isstate(SH_TIMING))
+ return;
+ /* Handles ^Z for shell builtins, subshells, and functs */
+ shp->lastsig = 0;
+ sh_onstate(SH_MONITOR);
+ sh_offstate(SH_STOPOK);
+ shp->trapnote = 0;
+ if(!shp->subshell && (sig=sh_fork(shp,0,NIL(int*))))
+ {
+ job.curpgid = 0;
+ job.parent = (pid_t)-1;
+ job_wait(sig);
+ job.parent = 0;
+ shp->sigflag[SIGTSTP] = 0;
+ /* wait for child to stop */
+ shp->exitval = (SH_EXITSIG|SIGTSTP);
+ /* return to prompt mode */
+ pp->mode = SH_JMPERREXIT;
+ }
+ else
+ {
+ if(shp->subshell)
+ sh_subfork();
+ /* child process, put to sleep */
+ sh_offstate(SH_STOPOK);
+ sh_offstate(SH_MONITOR);
+ shp->sigflag[SIGTSTP] = 0;
+ /* stop child job */
+ killpg(job.curpgid,SIGTSTP);
+ /* child resumes */
+ job_clear();
+ shp->forked = 1;
+ shp->exitval = (xno&SH_EXITMASK);
+ return;
+ }
+ }
+#endif /* SIGTSTP */
+ /* unlock output pool */
+ sh_offstate(SH_NOTRACK);
+ if(!(pool=sfpool(NIL(Sfio_t*),shp->outpool,SF_WRITE)))
+ pool = shp->outpool; /* can't happen? */
+ sfclrlock(pool);
+#ifdef SIGPIPE
+ if(shp->lastsig==SIGPIPE)
+ sfpurge(pool);
+#endif /* SIGPIPE */
+ sfclrlock(sfstdin);
+ if(!pp)
+ sh_done(shp,sig);
+ shp->prefix = 0;
+#if SHOPT_TYPEDEF
+ shp->mktype = 0;
+#endif /* SHOPT_TYPEDEF*/
+ if(job.in_critical)
+ job_unlock();
+ if(pp->mode == SH_JMPSCRIPT && !pp->prev)
+ sh_done(shp,sig);
+ if(pp->mode)
+ siglongjmp(pp->buff,pp->mode);
+}
+
+static void array_notify(Namval_t *np, void *data)
+{
+ Namarr_t *ap = nv_arrayptr(np);
+ NOT_USED(data);
+ if(ap && ap->fun)
+ (*ap->fun)(np, 0, NV_AFREE);
+}
+
+/*
+ * This is the exit routine for the shell
+ */
+
+void sh_done(void *ptr, register int sig)
+{
+ Shell_t *shp = (Shell_t*)ptr;
+ register char *t;
+ register int savxit = shp->exitval;
+ shp->trapnote = 0;
+ indone=1;
+ if(sig)
+ savxit = SH_EXITSIG|sig;
+ if(shp->userinit)
+ (*shp->userinit)(shp, -1);
+ if(t=shp->st.trapcom[0])
+ {
+ shp->st.trapcom[0]=0; /*should free but not long */
+ shp->oldexit = savxit;
+ sh_trap(t,0);
+ savxit = shp->exitval;
+ }
+ else
+ {
+ /* avoid recursive call for set -e */
+ sh_offstate(SH_ERREXIT);
+ sh_chktrap(shp);
+ }
+ nv_scan(shp->var_tree,array_notify,(void*)0,NV_ARRAY,NV_ARRAY);
+ sh_freeup(shp);
+#if SHOPT_ACCT
+ sh_accend();
+#endif /* SHOPT_ACCT */
+#if SHOPT_VSH || SHOPT_ESH
+ if(mbwide()||sh_isoption(SH_EMACS)||sh_isoption(SH_VI)||sh_isoption(SH_GMACS))
+ tty_cooked(-1);
+#endif
+#ifdef JOBS
+ if((sh_isoption(SH_INTERACTIVE) && shp->login_sh) || (!sh_isoption(SH_INTERACTIVE) && (sig==SIGHUP)))
+ job_walk(sfstderr,job_terminate,SIGHUP,NIL(char**));
+#endif /* JOBS */
+ job_close(shp);
+ if(nv_search("VMTRACE", shp->var_tree,0))
+ strmatch((char*)0,(char*)0);
+ sfsync((Sfio_t*)sfstdin);
+ sfsync((Sfio_t*)shp->outpool);
+ sfsync((Sfio_t*)sfstdout);
+ if(savxit&SH_EXITSIG)
+ sig = savxit&SH_EXITMASK;
+ if(sig)
+ {
+ /* generate fault termination code */
+ if(RLIMIT_CORE!=RLIMIT_UNKNOWN)
+ {
+#ifdef _lib_getrlimit
+ struct rlimit rlp;
+ getrlimit(RLIMIT_CORE,&rlp);
+ rlp.rlim_cur = 0;
+ setrlimit(RLIMIT_CORE,&rlp);
+#else
+ vlimit(RLIMIT_CORE,0);
+#endif
+ }
+ signal(sig,SIG_DFL);
+ sigrelease(sig);
+ kill(getpid(),sig);
+ pause();
+ }
+#if SHOPT_KIA
+ if(sh_isoption(SH_NOEXEC))
+ kiaclose((Lex_t*)shp->lex_context);
+#endif /* SHOPT_KIA */
+ exit(savxit&SH_EXITMASK);
+}
+
diff --git a/src/cmd/ksh93/sh/fcin.c b/src/cmd/ksh93/sh/fcin.c
new file mode 100644
index 0000000..ea6ea6b
--- /dev/null
+++ b/src/cmd/ksh93/sh/fcin.c
@@ -0,0 +1,214 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Routines to implement fast character input
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <sfio.h>
+#include <error.h>
+#include <fcin.h>
+
+Fcin_t _Fcin = {0};
+
+/*
+ * open stream <f> for fast character input
+ */
+int fcfopen(register Sfio_t* f)
+{
+ register int n;
+ char *buff;
+ Fcin_t save;
+ errno = 0;
+ _Fcin.fcbuff = _Fcin.fcptr;
+ _Fcin._fcfile = f;
+ fcsave(&save);
+ if(!(buff=(char*)sfreserve(f,SF_UNBOUND,SF_LOCKR)))
+ {
+ fcrestore(&save);
+ _Fcin.fcchar = 0;
+ _Fcin.fcptr = _Fcin.fcbuff = &_Fcin.fcchar;
+ _Fcin.fclast = 0;
+ _Fcin._fcfile = (Sfio_t*)0;
+ return(EOF);
+ }
+ n = sfvalue(f);
+ fcrestore(&save);
+ sfread(f,buff,0);
+ _Fcin.fcoff = sftell(f);;
+ buff = (char*)sfreserve(f,SF_UNBOUND,SF_LOCKR);
+ _Fcin.fclast = (_Fcin.fcptr=_Fcin.fcbuff=(unsigned char*)buff)+n;
+ if(sffileno(f) >= 0)
+ *_Fcin.fclast = 0;
+ return(n);
+}
+
+
+/*
+ * With _Fcin.fcptr>_Fcin.fcbuff, the stream pointer is advanced and
+ * If _Fcin.fclast!=0, performs an sfreserve() for the next buffer.
+ * If a notify function has been set, it is called
+ * If last is non-zero, and the stream is a file, 0 is returned when
+ * the previous character is a 0 byte.
+ */
+int fcfill(void)
+{
+ register int n;
+ register Sfio_t *f;
+ register unsigned char *last=_Fcin.fclast, *ptr=_Fcin.fcptr;
+ if(!(f=fcfile()))
+ {
+ /* see whether pointer has passed null byte */
+ if(ptr>_Fcin.fcbuff && *--ptr==0)
+ _Fcin.fcptr=ptr;
+ else
+ _Fcin.fcoff = 0;
+ return(0);
+ }
+ if(last)
+ {
+ if( ptr<last && ptr>_Fcin.fcbuff && *(ptr-1)==0)
+ return(0);
+ if(_Fcin.fcchar)
+ *last = _Fcin.fcchar;
+ if(ptr > last)
+ _Fcin.fcptr = ptr = last;
+ }
+ if((n = ptr-_Fcin.fcbuff) && _Fcin.fcfun)
+ (*_Fcin.fcfun)(f,(const char*)_Fcin.fcbuff,n,_Fcin.context);
+ sfread(f, (char*)_Fcin.fcbuff, n);
+ _Fcin.fcoff +=n;
+ _Fcin._fcfile = 0;
+ if(!last)
+ return(0);
+ else if(fcfopen(f) < 0)
+ return(EOF);
+ return(*_Fcin.fcptr++);
+}
+
+/*
+ * Synchronize and close the current stream
+ */
+int fcclose(void)
+{
+ register unsigned char *ptr;
+ if(_Fcin.fclast==0)
+ return(0);
+ if((ptr=_Fcin.fcptr)>_Fcin.fcbuff && *(ptr-1)==0)
+ _Fcin.fcptr--;
+ if(_Fcin.fcchar)
+ *_Fcin.fclast = _Fcin.fcchar;
+ _Fcin.fclast = 0;
+ _Fcin.fcleft = 0;
+ return(fcfill());
+}
+
+/*
+ * Set the notify function that is called for each fcfill()
+ */
+void fcnotify(void (*fun)(Sfio_t*,const char*,int,void*),void* context)
+{
+ _Fcin.fcfun = fun;
+ _Fcin.context = context;
+}
+
+#ifdef __EXPORT__
+# define extern __EXPORT__
+#endif
+
+#undef fcsave
+extern void fcsave(Fcin_t *fp)
+{
+ *fp = _Fcin;
+}
+
+#undef fcrestore
+extern void fcrestore(Fcin_t *fp)
+{
+ _Fcin = *fp;
+}
+
+/* for testing purposes with small buffers */
+#if defined(IOBSIZE) && (IOBSIZE < 2*MB_LEN_MAX)
+# undef MB_LEN_MAX
+# define MB_LEN_MAX (IOBSIZE/2)
+#endif
+
+struct Extra
+{
+ unsigned char buff[2*MB_LEN_MAX];
+ unsigned char *next;
+};
+
+int _fcmbget(short *len)
+{
+ static struct Extra extra;
+ register int i, c, n;
+ if(_Fcin.fcleft)
+ {
+ if((c = mbsize(extra.next)) < 0)
+ c = 1;
+ if((_Fcin.fcleft -= c) <=0)
+ {
+ _Fcin.fcptr = (unsigned char*)fcfirst() - _Fcin.fcleft;
+ _Fcin.fcleft = 0;
+ }
+ *len = c;
+ if(c==1)
+ c = *extra.next++;
+ else if(c==0)
+ _Fcin.fcleft = 0;
+ else
+ c = mbchar(extra.next);
+ return(c);
+ }
+ switch(*len = mbsize(_Fcin.fcptr))
+ {
+ case -1:
+ if(_Fcin._fcfile && (n=(_Fcin.fclast-_Fcin.fcptr)) < MB_LEN_MAX)
+ {
+ memcpy(extra.buff, _Fcin.fcptr, n);
+ _Fcin.fcptr = _Fcin.fclast;
+ for(i=n; i < MB_LEN_MAX+n; i++)
+ {
+ if((extra.buff[i] = fcgetc(c))==0)
+ break;
+ }
+ _Fcin.fcleft = n;
+ extra.next = extra.buff;
+ return(fcmbget(len));
+ }
+ *len = 1;
+ /* fall through */
+ case 0:
+ case 1:
+ c=fcget();
+ break;
+ default:
+ c = mbchar(_Fcin.fcptr);
+ }
+ return(c);
+}
+
diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c
new file mode 100644
index 0000000..16e30df
--- /dev/null
+++ b/src/cmd/ksh93/sh/init.c
@@ -0,0 +1,2238 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ *
+ * Shell initialization
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <stak.h>
+#include <ccode.h>
+#include <pwd.h>
+#include <tmx.h>
+#include "variables.h"
+#include "path.h"
+#include "fault.h"
+#include "name.h"
+#include "edit.h"
+#include "jobs.h"
+#include "io.h"
+#include "shlex.h"
+#include "builtins.h"
+#include "FEATURE/time"
+#include "FEATURE/dynamic"
+#include "FEATURE/externs"
+#include "lexstates.h"
+#include "version.h"
+
+#if _hdr_wctype
+#include <ast_wchar.h>
+#include <wctype.h>
+#endif
+#if !_typ_wctrans_t
+#undef wctrans_t
+#define wctrans_t sh_wctrans_t
+typedef long wctrans_t;
+#endif
+#if !_lib_wctrans
+#undef wctrans
+#define wctrans sh_wctrans
+static wctrans_t wctrans(const char *name)
+{
+ if(strcmp(name,e_tolower)==0)
+ return(1);
+ else if(strcmp(name,e_toupper)==0)
+ return(2);
+ return(0);
+}
+#endif
+#if !_lib_towctrans
+#undef towctrans
+#define towctrans sh_towctrans
+static int towctrans(int c, wctrans_t t)
+{
+ if(t==1 && isupper(c))
+ c = tolower(c);
+ else if(t==2 && islower(c))
+ c = toupper(c);
+ return(c);
+}
+#endif
+
+char e_version[] = "\n@(#)$Id: Version "
+#if SHOPT_AUDIT
+#define ATTRS 1
+ "A"
+#endif
+#if SHOPT_BASH
+#define ATTRS 1
+ "B"
+#endif
+#if SHOPT_COSHELL
+#define ATTRS 1
+ "J"
+#else
+#if SHOPT_BGX
+#define ATTRS 1
+ "j"
+#endif
+#endif
+#if SHOPT_ACCT
+#define ATTRS 1
+ "L"
+#endif
+#if SHOPT_MULTIBYTE
+#define ATTRS 1
+ "M"
+#endif
+#if SHOPT_PFSH && _hdr_exec_attr
+#define ATTRS 1
+ "P"
+#endif
+#if SHOPT_REGRESS
+#define ATTRS 1
+ "R"
+#endif
+#if ATTRS
+ " "
+#endif
+ SH_RELEASE " $\0\n";
+
+#if SHOPT_BASH
+ extern void bash_init(Shell_t*,int);
+#endif
+
+#define RANDMASK 0x7fff
+
+#ifndef ARG_MAX
+# define ARG_MAX (1*1024*1024)
+#endif
+#ifndef CHILD_MAX
+# define CHILD_MAX (1*1024)
+#endif
+#ifndef CLK_TCK
+# define CLK_TCK 60
+#endif /* CLK_TCK */
+
+#ifndef environ
+ extern char **environ;
+#endif
+
+#undef getconf
+#define getconf(x) strtol(astconf(x,NiL,NiL),NiL,0)
+
+struct seconds
+{
+ Namfun_t hdr;
+ Shell_t *sh;
+};
+
+struct rand
+{
+ Namfun_t hdr;
+ Shell_t *sh;
+ int32_t rand_last;
+};
+
+struct ifs
+{
+ Namfun_t hdr;
+ Namval_t *ifsnp;
+};
+
+struct match
+{
+ Namfun_t hdr;
+ const char *v;
+ char *val;
+ char *rval[2];
+ int *match;
+ char node[NV_MINSZ+sizeof(char*)];
+ int first;
+ int vsize;
+ int nmatch;
+ int index;
+ int lastsub[2];
+};
+
+typedef struct _init_
+{
+ Shell_t *sh;
+#if SHOPT_FS_3D
+ Namfun_t VPATH_init;
+#endif /* SHOPT_FS_3D */
+ struct ifs IFS_init;
+ Namfun_t PATH_init;
+ Namfun_t FPATH_init;
+ Namfun_t CDPATH_init;
+ Namfun_t SHELL_init;
+ Namfun_t ENV_init;
+ Namfun_t VISUAL_init;
+ Namfun_t EDITOR_init;
+ Namfun_t HISTFILE_init;
+ Namfun_t HISTSIZE_init;
+ Namfun_t OPTINDEX_init;
+ struct seconds SECONDS_init;
+ struct rand RAND_init;
+ Namfun_t LINENO_init;
+ Namfun_t L_ARG_init;
+ Namfun_t SH_VERSION_init;
+ struct match SH_MATCH_init;
+ Namfun_t SH_MATH_init;
+#if SHOPT_COSHELL
+ Namfun_t SH_JOBPOOL_init;
+#endif /* SHOPT_COSHELL */
+#ifdef _hdr_locale
+ Namfun_t LC_TYPE_init;
+ Namfun_t LC_NUM_init;
+ Namfun_t LC_COLL_init;
+ Namfun_t LC_MSG_init;
+ Namfun_t LC_ALL_init;
+ Namfun_t LANG_init;
+#endif /* _hdr_locale */
+} Init_t;
+
+static Init_t *ip;
+static int lctype;
+static int nbltins;
+static void env_init(Shell_t*);
+static Init_t *nv_init(Shell_t*);
+static Dt_t *inittree(Shell_t*,const struct shtable2*);
+static int shlvl;
+
+#ifdef _WINIX
+# define EXE "?(.exe)"
+#else
+# define EXE
+#endif
+
+static int rand_shift;
+
+
+/*
+ * Invalidate all path name bindings
+ */
+static void rehash(register Namval_t *np,void *data)
+{
+ NOT_USED(data);
+ nv_onattr(np,NV_NOALIAS);
+}
+
+/*
+ * out of memory routine for stak routines
+ */
+static char *nospace(int unused)
+{
+ NOT_USED(unused);
+ errormsg(SH_DICT,ERROR_exit(3),e_nospace);
+ return(NIL(char*));
+}
+
+/* Trap for VISUAL and EDITOR variables */
+static void put_ed(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ register const char *cp, *name=nv_name(np);
+ register int newopt=0;
+ Shell_t *shp = nv_shell(np);
+ if(*name=='E' && nv_getval(sh_scoped(shp,VISINOD)))
+ goto done;
+ if(!(cp=val) && (*name=='E' || !(cp=nv_getval(sh_scoped(shp,EDITNOD)))))
+ goto done;
+ /* turn on vi or emacs option if editor name is either*/
+ cp = path_basename(cp);
+ if(strmatch(cp,"*[Vv][Ii]*"))
+ newopt=SH_VI;
+ else if(strmatch(cp,"*gmacs*"))
+ newopt=SH_GMACS;
+ else if(strmatch(cp,"*macs*"))
+ newopt=SH_EMACS;
+ if(newopt)
+ {
+ sh_offoption(SH_VI);
+ sh_offoption(SH_EMACS);
+ sh_offoption(SH_GMACS);
+ sh_onoption(newopt);
+ }
+done:
+ nv_putv(np, val, flags, fp);
+}
+
+/* Trap for HISTFILE and HISTSIZE variables */
+static void put_history(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ void *histopen = shp->gd->hist_ptr;
+ char *cp;
+ if(val && histopen)
+ {
+ if(np==HISTFILE && (cp=nv_getval(np)) && strcmp(val,cp)==0)
+ return;
+ if(np==HISTSIZE && sh_arith(shp,val)==nv_getnum(HISTSIZE))
+ return;
+ hist_close(shp->gd->hist_ptr);
+ }
+ nv_putv(np, val, flags, fp);
+ if(histopen)
+ {
+ if(val)
+ sh_histinit(shp);
+ else
+ hist_close(histopen);
+ }
+}
+
+/* Trap for OPTINDEX */
+static void put_optindex(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ shp->st.opterror = shp->st.optchar = 0;
+ nv_putv(np, val, flags, fp);
+ if(!val)
+ nv_disc(np,fp,NV_POP);
+}
+
+static Sfdouble_t nget_optindex(register Namval_t* np, Namfun_t *fp)
+{
+ return((Sfdouble_t)*np->nvalue.lp);
+}
+
+static Namfun_t *clone_optindex(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ Namfun_t *dp = (Namfun_t*)malloc(sizeof(Namfun_t));
+ memcpy((void*)dp,(void*)fp,sizeof(Namfun_t));
+ mp->nvalue.lp = np->nvalue.lp;
+ dp->nofree = 0;
+ return(dp);
+}
+
+
+/* Trap for restricted variables FPATH, PATH, SHELL, ENV */
+static void put_restricted(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ int path_scoped = 0, fpath_scoped=0;
+ Pathcomp_t *pp;
+ char *name = nv_name(np);
+ if(!(flags&NV_RDONLY) && sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np));
+ if(np==PATHNOD || (path_scoped=(strcmp(name,PATHNOD->nvname)==0)))
+ {
+ nv_scan(shp->track_tree,rehash,(void*)0,NV_TAGGED,NV_TAGGED);
+ if(path_scoped && !val)
+ val = PATHNOD->nvalue.cp;
+ }
+ if(val && !(flags&NV_RDONLY) && np->nvalue.cp && strcmp(val,np->nvalue.cp)==0)
+ return;
+ if(np==FPATHNOD || (fpath_scoped=(strcmp(name,FPATHNOD->nvname)==0)))
+ shp->pathlist = (void*)path_unsetfpath(shp);
+ nv_putv(np, val, flags, fp);
+ shp->universe = 0;
+ if(shp->pathlist)
+ {
+ val = np->nvalue.cp;
+ if(np==PATHNOD || path_scoped)
+ pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->pathlist,val,PATH_PATH);
+ else if(val && (np==FPATHNOD || fpath_scoped))
+ pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->pathlist,val,PATH_FPATH);
+ else
+ return;
+ if(shp->pathlist = (void*)pp)
+ pp->shp = shp;
+ if(!val && (flags&NV_NOSCOPE))
+ {
+ Namval_t *mp = dtsearch(shp->var_tree,np);
+ if(mp && (val=nv_getval(mp)))
+ nv_putval(mp,val,NV_RDONLY);
+ }
+#if 0
+sfprintf(sfstderr,"%d: name=%s val=%s\n",getpid(),name,val);
+path_dump((Pathcomp_t*)shp->pathlist);
+#endif
+ }
+}
+
+static void put_cdpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ Pathcomp_t *pp;
+ Shell_t *shp = nv_shell(np);
+ nv_putv(np, val, flags, fp);
+ if(!shp->cdpathlist)
+ return;
+ val = np->nvalue.cp;
+ pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->cdpathlist,val,PATH_CDPATH);
+ if(shp->cdpathlist = (void*)pp)
+ pp->shp = shp;
+}
+
+#ifdef _hdr_locale
+ /*
+ * This function needs to be modified to handle international
+ * error message translations
+ */
+#if ERROR_VERSION >= 20000101L
+ static char* msg_translate(const char* catalog, const char* message)
+ {
+ NOT_USED(catalog);
+ return((char*)message);
+ }
+#else
+ static char* msg_translate(const char* message, int type)
+ {
+ NOT_USED(type);
+ return((char*)message);
+ }
+#endif
+
+ /* Trap for LC_ALL, LC_CTYPE, LC_MESSAGES, LC_COLLATE and LANG */
+ static void put_lang(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+ {
+ Shell_t *shp = nv_shell(np);
+ int type;
+ char *name = nv_name(np);
+ if(name==(LCALLNOD)->nvname)
+ type = LC_ALL;
+ else if(name==(LCTYPENOD)->nvname)
+ type = LC_CTYPE;
+ else if(name==(LCMSGNOD)->nvname)
+ type = LC_MESSAGES;
+ else if(name==(LCCOLLNOD)->nvname)
+ type = LC_COLLATE;
+ else if(name==(LCNUMNOD)->nvname)
+ type = LC_NUMERIC;
+#ifdef LC_LANG
+ else if(name==(LANGNOD)->nvname)
+ type = LC_LANG;
+#else
+#define LC_LANG LC_ALL
+ else if(name==(LANGNOD)->nvname && (!(name=nv_getval(LCALLNOD)) || !*name))
+ type = LC_LANG;
+#endif
+ else
+ type= -1;
+ if(!sh_isstate(SH_INIT) && (type>=0 || type==LC_ALL || type==LC_LANG))
+ {
+ char* r;
+#ifdef AST_LC_setenv
+ ast.locale.set |= AST_LC_setenv;
+#endif
+ r = setlocale(type,val?val:"");
+#ifdef AST_LC_setenv
+ ast.locale.set ^= AST_LC_setenv;
+#endif
+ if(!r && val)
+ {
+ if(!sh_isstate(SH_INIT) || shp->login_sh==0)
+ errormsg(SH_DICT,0,e_badlocale,val);
+ return;
+ }
+ }
+ nv_putv(np, val, flags, fp);
+ if(CC_NATIVE!=CC_ASCII && (type==LC_ALL || type==LC_LANG || type==LC_CTYPE))
+ {
+ if(sh_lexstates[ST_BEGIN]!=sh_lexrstates[ST_BEGIN])
+ free((void*)sh_lexstates[ST_BEGIN]);
+ lctype++;
+ if(ast.locale.set&(1<<AST_LC_CTYPE))
+ {
+ register int c;
+ char *state[4];
+ sh_lexstates[ST_BEGIN] = state[0] = (char*)malloc(4*(1<<CHAR_BIT));
+ memcpy(state[0],sh_lexrstates[ST_BEGIN],(1<<CHAR_BIT));
+ sh_lexstates[ST_NAME] = state[1] = state[0] + (1<<CHAR_BIT);
+ memcpy(state[1],sh_lexrstates[ST_NAME],(1<<CHAR_BIT));
+ sh_lexstates[ST_DOL] = state[2] = state[1] + (1<<CHAR_BIT);
+ memcpy(state[2],sh_lexrstates[ST_DOL],(1<<CHAR_BIT));
+ sh_lexstates[ST_BRACE] = state[3] = state[2] + (1<<CHAR_BIT);
+ memcpy(state[3],sh_lexrstates[ST_BRACE],(1<<CHAR_BIT));
+ for(c=0; c<(1<<CHAR_BIT); c++)
+ {
+ if(state[0][c]!=S_REG)
+ continue;
+ if(state[2][c]!=S_ERR)
+ continue;
+ if(isblank(c))
+ {
+ state[0][c]=0;
+ state[1][c]=S_BREAK;
+ state[2][c]=S_BREAK;
+ continue;
+ }
+ if(!isalpha(c))
+ continue;
+ state[0][c]=S_NAME;
+ if(state[1][c]==S_REG)
+ state[1][c]=0;
+ state[2][c]=S_ALP;
+ if(state[3][c]==S_ERR)
+ state[3][c]=0;
+ }
+ }
+ else
+ {
+ sh_lexstates[ST_BEGIN]=(char*)sh_lexrstates[ST_BEGIN];
+ sh_lexstates[ST_NAME]=(char*)sh_lexrstates[ST_NAME];
+ sh_lexstates[ST_DOL]=(char*)sh_lexrstates[ST_DOL];
+ sh_lexstates[ST_BRACE]=(char*)sh_lexrstates[ST_BRACE];
+ }
+ }
+#if ERROR_VERSION < 20000101L
+ if(type==LC_ALL || type==LC_MESSAGES)
+ error_info.translate = msg_translate;
+#endif
+ }
+#endif /* _hdr_locale */
+
+/* Trap for IFS assignment and invalidates state table */
+static void put_ifs(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ register struct ifs *ip = (struct ifs*)fp;
+ ip->ifsnp = 0;
+ if(!val)
+ {
+ fp = nv_stack(np, NIL(Namfun_t*));
+ if(fp && !fp->nofree)
+ {
+ free((void*)fp);
+ fp = 0;
+ }
+ }
+ if(val != np->nvalue.cp)
+ nv_putv(np, val, flags, fp);
+ if(!val)
+ {
+ if(fp)
+ fp->next = np->nvfun;
+ np->nvfun = fp;
+ }
+}
+
+/*
+ * This is the lookup function for IFS
+ * It keeps the sh.ifstable up to date
+ */
+static char* get_ifs(register Namval_t* np, Namfun_t *fp)
+{
+ register struct ifs *ip = (struct ifs*)fp;
+ register char *cp, *value;
+ register int c,n;
+ register Shell_t *shp = nv_shell(np);
+ value = nv_getv(np,fp);
+ if(np!=ip->ifsnp)
+ {
+ ip->ifsnp = np;
+ memset(shp->ifstable,0,(1<<CHAR_BIT));
+ if(cp=value)
+ {
+#if SHOPT_MULTIBYTE
+ while(n=mbsize(cp),c= *(unsigned char*)cp)
+#else
+ while(c= *(unsigned char*)cp++)
+#endif /* SHOPT_MULTIBYTE */
+ {
+#if SHOPT_MULTIBYTE
+ cp++;
+ if(n>1)
+ {
+ cp += (n-1);
+ shp->ifstable[c] = S_MBYTE;
+ continue;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ n = S_DELIM;
+ if(c== *cp)
+ cp++;
+ else if(c=='\n')
+ n = S_NL;
+ else if(isspace(c))
+ n = S_SPACE;
+ shp->ifstable[c] = n;
+ }
+ }
+ else
+ {
+ shp->ifstable[' '] = shp->ifstable['\t'] = S_SPACE;
+ shp->ifstable['\n'] = S_NL;
+ }
+ }
+ return(value);
+}
+
+/*
+ * these functions are used to get and set the SECONDS variable
+ */
+#ifdef timeofday
+# define dtime(tp) ((double)((tp)->tv_sec)+1e-6*((double)((tp)->tv_usec)))
+# define tms timeval
+#else
+# define dtime(tp) (((double)times(tp))/shgd->lim.clk_tck)
+# define timeofday(a)
+#endif
+
+static void put_seconds(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ double d;
+ struct tms tp;
+ if(!val)
+ {
+ nv_putv(np, val, flags, fp);
+ fp = nv_stack(np, NIL(Namfun_t*));
+ if(fp && !fp->nofree)
+ free((void*)fp);
+ return;
+ }
+ if(!np->nvalue.dp)
+ {
+ nv_setsize(np,3);
+ nv_onattr(np,NV_DOUBLE);
+ np->nvalue.dp = new_of(double,0);
+ }
+ nv_putv(np, val, flags, fp);
+ d = *np->nvalue.dp;
+ timeofday(&tp);
+ *np->nvalue.dp = dtime(&tp)-d;
+}
+
+static char* get_seconds(register Namval_t* np, Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ register int places = nv_size(np);
+ struct tms tp;
+ double d, offset = (np->nvalue.dp?*np->nvalue.dp:0);
+ NOT_USED(fp);
+ timeofday(&tp);
+ d = dtime(&tp)- offset;
+ sfprintf(shp->strbuf,"%.*f",places,d);
+ return(sfstruse(shp->strbuf));
+}
+
+static Sfdouble_t nget_seconds(register Namval_t* np, Namfun_t *fp)
+{
+ struct tms tp;
+ double offset = (np->nvalue.dp?*np->nvalue.dp:0);
+ NOT_USED(fp);
+ timeofday(&tp);
+ return(dtime(&tp)- offset);
+}
+
+/*
+ * These three functions are used to get and set the RANDOM variable
+ */
+static void put_rand(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ struct rand *rp = (struct rand*)fp;
+ register long n;
+ if(!val)
+ {
+ fp = nv_stack(np, NIL(Namfun_t*));
+ if(fp && !fp->nofree)
+ free((void*)fp);
+ _nv_unset(np,0);
+ return;
+ }
+ if(flags&NV_INTEGER)
+ n = *(double*)val;
+ else
+ n = sh_arith(rp->sh,val);
+ srand((int)(n&RANDMASK));
+ rp->rand_last = -1;
+ if(!np->nvalue.lp)
+ np->nvalue.lp = &rp->rand_last;
+}
+
+/*
+ * get random number in range of 0 - 2**15
+ * never pick same number twice in a row
+ */
+static Sfdouble_t nget_rand(register Namval_t* np, Namfun_t *fp)
+{
+ register long cur, last= *np->nvalue.lp;
+ NOT_USED(fp);
+ do
+ cur = (rand()>>rand_shift)&RANDMASK;
+ while(cur==last);
+ *np->nvalue.lp = cur;
+ return((Sfdouble_t)cur);
+}
+
+static char* get_rand(register Namval_t* np, Namfun_t *fp)
+{
+ register long n = nget_rand(np,fp);
+ return(fmtbase(n, 10, 0));
+}
+
+/*
+ * These three routines are for LINENO
+ */
+static Sfdouble_t nget_lineno(Namval_t* np, Namfun_t *fp)
+{
+ double d=1;
+ if(error_info.line >0)
+ d = error_info.line;
+ else if(error_info.context && error_info.context->line>0)
+ d = error_info.context->line;
+ NOT_USED(np);
+ NOT_USED(fp);
+ return(d);
+}
+
+static void put_lineno(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ register long n;
+ Shell_t *shp = nv_shell(np);
+ if(!val)
+ {
+ fp = nv_stack(np, NIL(Namfun_t*));
+ if(fp && !fp->nofree)
+ free((void*)fp);
+ _nv_unset(np,0);
+ return;
+ }
+ if(flags&NV_INTEGER)
+ n = *(double*)val;
+ else
+ n = sh_arith(shp,val);
+ shp->st.firstline += nget_lineno(np,fp)+1-n;
+}
+
+static char* get_lineno(register Namval_t* np, Namfun_t *fp)
+{
+ register long n = nget_lineno(np,fp);
+ return(fmtbase(n, 10, 0));
+}
+
+static char* get_lastarg(Namval_t* np, Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ char *cp;
+ int pid;
+ if(sh_isstate(SH_INIT) && (cp=shp->lastarg) && *cp=='*' && (pid=strtol(cp+1,&cp,10)) && *cp=='*')
+ nv_putval(np,(pid==shp->gd->ppid?cp+1:0),0);
+ return(shp->lastarg);
+}
+
+static void put_lastarg(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ if(flags&NV_INTEGER)
+ {
+ sfprintf(shp->strbuf,"%.*g",12,*((double*)val));
+ val = sfstruse(shp->strbuf);
+ }
+ if(val)
+ val = strdup(val);
+ if(shp->lastarg && !nv_isattr(np,NV_NOFREE))
+ free((void*)shp->lastarg);
+ else
+ nv_offattr(np,NV_NOFREE);
+ shp->lastarg = (char*)val;
+ nv_offattr(np,NV_EXPORT);
+ np->nvenv = 0;
+}
+
+static int hasgetdisc(register Namfun_t *fp)
+{
+ while(fp && !fp->disc->getnum && !fp->disc->getval)
+ fp = fp->next;
+ return(fp!=0);
+}
+
+/*
+ * store the most recent value for use in .sh.match
+ * treat .sh.match as a two dimensional array
+ */
+void sh_setmatch(Shell_t *shp,const char *v, int vsize, int nmatch, int match[],int index)
+{
+ struct match *mp = &ip->SH_MATCH_init;
+ Namval_t *np = nv_namptr(mp->node,0);
+ register int i,n,x, savesub=shp->subshell;
+ Namarr_t *ap = nv_arrayptr(SH_MATCHNOD);
+ shp->subshell = 0;
+#ifndef SHOPT_2DMATCH
+ index = 0;
+#else
+ if(index==0)
+#endif /* SHOPT_2DMATCH */
+ {
+ if(ap->hdr.next != &mp->hdr)
+ {
+ free((void*)ap);
+ ap = nv_arrayptr(np);
+ SH_MATCHNOD->nvfun = &ap->hdr;
+ }
+ if(ap)
+ {
+ ap->nelem &= ~ARRAY_SCAN;
+ i = array_elem(ap);
+ ap->nelem++;
+ while(--i>= 0)
+ {
+ nv_putsub(SH_MATCHNOD, (char*)0,i);
+ _nv_unset(SH_MATCHNOD,NV_RDONLY);
+ }
+ ap->nelem--;
+ }
+ if(!nv_hasdisc(SH_MATCHNOD,mp->hdr.disc))
+ nv_disc(SH_MATCHNOD,&mp->hdr,NV_LAST);
+ if(nmatch)
+ nv_putsub(SH_MATCHNOD, NIL(char*), (nmatch-1)|ARRAY_FILL|ARRAY_SETSUB);
+ ap = nv_arrayptr(SH_MATCHNOD);
+ ap->nelem = mp->nmatch = nmatch;
+ mp->v = v;
+ mp->first = match[0];
+ }
+#ifdef SHOPT_2DMATCH
+ else
+ {
+ if(index==1)
+ {
+ np->nvalue.cp = Empty;
+ np->nvfun = SH_MATCHNOD->nvfun;
+ nv_onattr(np,NV_NOFREE|NV_ARRAY);
+ SH_MATCHNOD->nvfun = 0;
+ for(i=0; i < mp->nmatch; i++)
+ {
+ nv_putsub(SH_MATCHNOD, (char*)0, i);
+ nv_arraychild(SH_MATCHNOD, np,0);
+ }
+ if(ap = nv_arrayptr(SH_MATCHNOD))
+ ap->nelem = mp->nmatch;
+ }
+ ap = nv_arrayptr(np);
+ nv_putsub(np, NIL(char*), index|ARRAY_FILL|ARRAY_SETSUB);
+ }
+#endif /* SHOPT_2DMATCH */
+ shp->subshell = savesub;
+ index *= 2*mp->nmatch;
+ if(mp->nmatch)
+ {
+ for(n=mp->first+(mp->v-v),vsize=0,i=0; i < 2*nmatch; i++)
+ {
+ if(match[i]>=0 && (match[i] - n) > vsize)
+ vsize = match[i] -n;
+ }
+ i = (index+2*mp->nmatch)*sizeof(match[0]);
+ if((i+vsize) >= mp->vsize)
+ {
+ if(mp->vsize)
+ mp->match = (int*)realloc(mp->match,i+vsize+1);
+ else
+ mp->match = (int*)malloc(i+vsize+1);
+ mp->vsize = i+vsize+1;
+ }
+ mp->val = ((char*)mp->match)+i;
+ memcpy(mp->match+index,match,nmatch*2*sizeof(match[0]));
+ for(x=0,i=0; i < 2*nmatch; i++)
+ {
+ if(match[i]>=0)
+ mp->match[index+i] -= n;
+ else
+ x=1;
+
+ }
+ ap->nelem -= x;
+ while(i < 2*mp->nmatch)
+ mp->match[index+i++] = -1;
+ memcpy(mp->val,v+n,vsize);
+ mp->val[vsize] = 0;
+ mp->lastsub[0] = mp->lastsub[1] = -1;
+ }
+}
+
+#define array_scan(np) ((nv_arrayptr(np)->nelem&ARRAY_SCAN))
+
+static char* get_match(register Namval_t* np, Namfun_t *fp)
+{
+ struct match *mp = (struct match*)fp;
+ int sub,sub2=0,n,i =!mp->index;
+ char *val;
+ sub = nv_aindex(SH_MATCHNOD);
+ if(np!=SH_MATCHNOD)
+ sub2 = nv_aindex(np);
+ if(sub>=mp->nmatch)
+ return(0);
+ if(sub2>0)
+ sub += sub2*mp->nmatch;
+ if(sub==mp->lastsub[!i])
+ return(mp->rval[!i]);
+ else if(sub==mp->lastsub[i])
+ return(mp->rval[i]);
+ n = mp->match[2*sub+1]-mp->match[2*sub];
+ if(n<=0)
+ return(mp->match[2*sub]<0?Empty:"");
+ val = mp->val+mp->match[2*sub];
+ if(mp->val[mp->match[2*sub+1]]==0)
+ return(val);
+ mp->index = i;
+ if(mp->rval[i])
+ {
+ free((void*)mp->rval[i]);
+ mp->rval[i] = 0;
+ }
+ mp->rval[i] = (char*)malloc(n+1);
+ mp->lastsub[i] = sub;
+ memcpy(mp->rval[i],val,n);
+ mp->rval[i][n] = 0;
+ return(mp->rval[i]);
+}
+
+static const Namdisc_t SH_MATCH_disc = { sizeof(struct match), 0, get_match };
+
+static char* get_version(register Namval_t* np, Namfun_t *fp)
+{
+ return(nv_getv(np,fp));
+}
+
+static Sfdouble_t nget_version(register Namval_t* np, Namfun_t *fp)
+{
+ register const char *cp = e_version + strlen(e_version)-10;
+ register int c;
+ Sflong_t t = 0;
+ NOT_USED(fp);
+
+ while (c = *cp++)
+ if (c >= '0' && c <= '9')
+ {
+ t *= 10;
+ t += c - '0';
+ }
+ return((Sfdouble_t)t);
+}
+
+static const Namdisc_t SH_VERSION_disc = { 0, 0, get_version, nget_version };
+
+#if SHOPT_FS_3D
+ /*
+ * set or unset the mappings given a colon separated list of directories
+ */
+ static void vpath_set(char *str, int mode)
+ {
+ register char *lastp, *oldp=str, *newp=strchr(oldp,':');
+ if(!shgd->lim.fs3d)
+ return;
+ while(newp)
+ {
+ *newp++ = 0;
+ if(lastp=strchr(newp,':'))
+ *lastp = 0;
+ mount((mode?newp:""),oldp,FS3D_VIEW,0);
+ newp[-1] = ':';
+ oldp = newp;
+ newp=lastp;
+ }
+ }
+
+ /* catch vpath assignments */
+ static void put_vpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+ {
+ register char *cp;
+ if(cp = nv_getval(np))
+ vpath_set(cp,0);
+ if(val)
+ vpath_set((char*)val,1);
+ nv_putv(np,val,flags,fp);
+ }
+ static const Namdisc_t VPATH_disc = { 0, put_vpath };
+ static Namfun_t VPATH_init = { &VPATH_disc, 1 };
+#endif /* SHOPT_FS_3D */
+
+
+static const Namdisc_t IFS_disc = { sizeof(struct ifs), put_ifs, get_ifs };
+const Namdisc_t RESTRICTED_disc = { sizeof(Namfun_t), put_restricted };
+static const Namdisc_t CDPATH_disc = { sizeof(Namfun_t), put_cdpath };
+static const Namdisc_t EDITOR_disc = { sizeof(Namfun_t), put_ed };
+static const Namdisc_t HISTFILE_disc = { sizeof(Namfun_t), put_history };
+static const Namdisc_t OPTINDEX_disc = { sizeof(Namfun_t), put_optindex, 0, nget_optindex, 0, 0, clone_optindex };
+static const Namdisc_t SECONDS_disc = { sizeof(struct seconds), put_seconds, get_seconds, nget_seconds };
+static const Namdisc_t RAND_disc = { sizeof(struct rand), put_rand, get_rand, nget_rand };
+static const Namdisc_t LINENO_disc = { sizeof(Namfun_t), put_lineno, get_lineno, nget_lineno };
+static const Namdisc_t L_ARG_disc = { sizeof(Namfun_t), put_lastarg, get_lastarg };
+
+
+#define MAX_MATH_ARGS 3
+
+static char *name_math(Namval_t *np, Namfun_t *fp)
+{
+ Shell_t *shp = sh_getinterp();
+ sfprintf(shp->strbuf,".sh.math.%s",np->nvname);
+ return(sfstruse(shp->strbuf));
+}
+
+static const Namdisc_t math_child_disc =
+{
+ 0,0,0,0,0,0,0,
+ name_math
+};
+
+static Namfun_t math_child_fun =
+{
+ &math_child_disc, 1, 0, sizeof(Namfun_t)
+};
+
+static void math_init(Shell_t *shp)
+{
+ Namval_t *np;
+ char *name;
+ int i;
+ shp->mathnodes = (char*)calloc(1,MAX_MATH_ARGS*(NV_MINSZ+5));
+ name = shp->mathnodes+MAX_MATH_ARGS*NV_MINSZ;
+ for(i=0; i < MAX_MATH_ARGS; i++)
+ {
+ np = nv_namptr(shp->mathnodes,i);
+ np->nvfun = &math_child_fun;
+ memcpy(name,"arg",3);
+ name[3] = '1'+i;
+ np->nvname = name;
+ name+=5;
+ nv_onattr(np,NV_MINIMAL|NV_NOFREE|NV_LDOUBLE|NV_RDONLY);
+ }
+}
+
+static Namval_t *create_math(Namval_t *np,const char *name,int flag,Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ if(!name)
+ return(SH_MATHNOD);
+ if(name[0]!='a' || name[1]!='r' || name[2]!='g' || name[4] || !isdigit(name[3]) || (name[3]=='0' || (name[3]-'0')>MAX_MATH_ARGS))
+ return(0);
+ fp->last = (char*)&name[4];
+ return(nv_namptr(shp->mathnodes,name[3]-'1'));
+}
+
+static char* get_math(register Namval_t* np, Namfun_t *fp)
+{
+ Shell_t *shp = nv_shell(np);
+ Namval_t *mp,fake;
+ char *val;
+ int first=0;
+ fake.nvname = ".sh.math.";
+ mp = (Namval_t*)dtprev(shp->fun_tree,&fake);
+ while(mp=(Namval_t*)dtnext(shp->fun_tree,mp))
+ {
+ if(memcmp(mp->nvname,".sh.math.",9))
+ break;
+ if(first++)
+ sfputc(shp->strbuf,' ');
+ sfputr(shp->strbuf,mp->nvname+9,-1);
+ }
+ val = sfstruse(shp->strbuf);
+ return(val);
+
+}
+
+static char *setdisc_any(Namval_t *np, const char *event, Namval_t *action, Namfun_t *fp)
+{
+ Shell_t *shp=nv_shell(np);
+ Namval_t *mp,fake;
+ char *name;
+ int getname=0, off=staktell();
+ fake.nvname = nv_name(np);
+ if(!event)
+ {
+ if(!action)
+ {
+ mp = (Namval_t*)dtprev(shp->fun_tree,&fake);
+ return((char*)dtnext(shp->fun_tree,mp));
+ }
+ getname = 1;
+ }
+ stakputs(fake.nvname);
+ stakputc('.');
+ stakputs(event);
+ stakputc(0);
+ name = stakptr(off);
+ mp = nv_search(name, shp->fun_tree, action?NV_ADD:0);
+ stakseek(off);
+ if(getname)
+ return(mp?(char*)dtnext(shp->fun_tree,mp):0);
+ if(action==np)
+ action = mp;
+ return(action?(char*)action:"");
+}
+
+static const Namdisc_t SH_MATH_disc = { 0, 0, get_math, 0, setdisc_any, create_math, };
+
+#if SHOPT_COSHELL
+static const Namdisc_t SH_JOBPOOL_disc = { 0, 0, 0, 0, setdisc_any, 0, };
+#endif /* SHOPT_COSHELL */
+
+#if SHOPT_NAMESPACE
+ static char* get_nspace(Namval_t* np, Namfun_t *fp)
+ {
+ if(sh.namespace)
+ return(nv_name(sh.namespace));
+ return((char*)np->nvalue.cp);
+ }
+ static const Namdisc_t NSPACE_disc = { 0, 0, get_nspace };
+ static Namfun_t NSPACE_init = { &NSPACE_disc, 1};
+#endif /* SHOPT_NAMESPACE */
+
+#ifdef _hdr_locale
+ static const Namdisc_t LC_disc = { sizeof(Namfun_t), put_lang };
+#endif /* _hdr_locale */
+
+/*
+ * This function will get called whenever a configuration parameter changes
+ */
+static int newconf(const char *name, const char *path, const char *value)
+{
+ Shell_t *shp = sh_getinterp();
+ register char *arg;
+ if(!name)
+ setenviron(value);
+ else if(strcmp(name,"UNIVERSE")==0 && strcmp(astconf(name,0,0),value))
+ {
+ shp->universe = 0;
+ /* set directory in new universe */
+ if(*(arg = path_pwd(shp,0))=='/')
+ chdir(arg);
+ /* clear out old tracked alias */
+ stakseek(0);
+ stakputs(nv_getval(PATHNOD));
+ stakputc(0);
+ nv_putval(PATHNOD,stakseek(0),NV_RDONLY);
+ }
+ return(1);
+}
+
+#if (CC_NATIVE != CC_ASCII)
+ static void a2e(char *d, const char *s)
+ {
+ register const unsigned char *t;
+ register int i;
+ t = CCMAP(CC_ASCII, CC_NATIVE);
+ for(i=0; i<(1<<CHAR_BIT); i++)
+ d[t[i]] = s[i];
+ }
+
+ static void init_ebcdic(void)
+ {
+ int i;
+ char *cp = (char*)malloc(ST_NONE*(1<<CHAR_BIT));
+ for(i=0; i < ST_NONE; i++)
+ {
+ a2e(cp,sh_lexrstates[i]);
+ sh_lexstates[i] = cp;
+ cp += (1<<CHAR_BIT);
+ }
+ }
+#endif
+
+/*
+ * return SH_TYPE_* bitmask for path
+ * 0 for "not a shell"
+ */
+int sh_type(register const char *path)
+{
+ register const char* s;
+ register int t = 0;
+
+ if (s = (const char*)strrchr(path, '/'))
+ {
+ if (*path == '-')
+ t |= SH_TYPE_LOGIN;
+ s++;
+ }
+ else
+ s = path;
+ if (*s == '-')
+ {
+ s++;
+ t |= SH_TYPE_LOGIN;
+ }
+ for (;;)
+ {
+ if (!(t & (SH_TYPE_KSH|SH_TYPE_BASH)))
+ {
+ if (*s == 'k')
+ {
+ s++;
+ t |= SH_TYPE_KSH;
+ continue;
+ }
+#if SHOPT_BASH
+ if (*s == 'b' && *(s+1) == 'a')
+ {
+ s += 2;
+ t |= SH_TYPE_BASH;
+ continue;
+ }
+#endif
+ }
+ if (!(t & (SH_TYPE_PROFILE|SH_TYPE_RESTRICTED)))
+ {
+#if SHOPT_PFSH
+ if (*s == 'p' && *(s+1) == 'f')
+ {
+ s += 2;
+ t |= SH_TYPE_PROFILE;
+ continue;
+ }
+#endif
+ if (*s == 'r')
+ {
+ s++;
+ t |= SH_TYPE_RESTRICTED;
+ continue;
+ }
+ }
+ break;
+ }
+ if (*s++ == 's' && (*s == 'h' || *s == 'u'))
+ {
+ s++;
+ t |= SH_TYPE_SH;
+ if ((t & SH_TYPE_KSH) && *s == '9' && *(s+1) == '3')
+ s += 2;
+#if _WINIX
+ if (*s == '.' && *(s+1) == 'e' && *(s+2) == 'x' && *(s+3) == 'e')
+ s += 4;
+#endif
+ if (!isalnum(*s))
+ return t;
+ }
+ return t & ~(SH_TYPE_BASH|SH_TYPE_KSH|SH_TYPE_PROFILE|SH_TYPE_RESTRICTED);
+}
+
+
+static char *get_mode(Namval_t* np, Namfun_t* nfp)
+{
+ mode_t mode = nv_getn(np,nfp);
+ return(fmtperm(mode));
+}
+
+static void put_mode(Namval_t* np, const char* val, int flag, Namfun_t* nfp)
+{
+ if(val)
+ {
+ mode_t mode;
+ char *last=0;
+ if(flag&NV_INTEGER)
+ {
+ if(flag&NV_LONG)
+ mode = *(Sfdouble_t*)val;
+ else
+ mode = *(double*)val;
+ }
+ else
+ mode = strperm(val, &last,0);
+ if(*last)
+ errormsg(SH_DICT,ERROR_exit(1),"%s: invalid mode string",val);
+ nv_putv(np,(char*)&mode,NV_INTEGER,nfp);
+ }
+ else
+ nv_putv(np,val,flag,nfp);
+}
+
+static const Namdisc_t modedisc =
+{
+ 0,
+ put_mode,
+ get_mode,
+};
+
+
+/*
+ * initialize the shell
+ */
+Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit)
+{
+ static int beenhere;
+ Shell_t *shp;
+ register int n;
+ int type;
+ static char *login_files[3];
+ memfatal();
+ n = strlen(e_version);
+ if(e_version[n-1]=='$' && e_version[n-2]==' ')
+ e_version[n-2]=0;
+#if (CC_NATIVE == CC_ASCII)
+ memcpy(sh_lexstates,sh_lexrstates,ST_NONE*sizeof(char*));
+#else
+ init_ebcdic();
+#endif
+ if(!beenhere)
+ {
+ beenhere = 1;
+ shp = &sh;
+ shgd = newof(0,struct shared,1,0);
+ shgd->pid = getpid();
+ shgd->ppid = getppid();
+ shgd->userid=getuid();
+ shgd->euserid=geteuid();
+ shgd->groupid=getgid();
+ shgd->egroupid=getegid();
+ shgd->lim.clk_tck = getconf("CLK_TCK");
+ shgd->lim.arg_max = getconf("ARG_MAX");
+ shgd->lim.child_max = getconf("CHILD_MAX");
+ shgd->lim.ngroups_max = getconf("NGROUPS_MAX");
+ shgd->lim.posix_version = getconf("VERSION");
+ shgd->lim.posix_jobcontrol = getconf("JOB_CONTROL");
+ if(shgd->lim.arg_max <=0)
+ shgd->lim.arg_max = ARG_MAX;
+ if(shgd->lim.child_max <=0)
+ shgd->lim.child_max = CHILD_MAX;
+ if(shgd->lim.clk_tck <=0)
+ shgd->lim.clk_tck = CLK_TCK;
+#if SHOPT_FS_3D
+ if(fs3d(FS3D_TEST))
+ shgd->lim.fs3d = 1;
+#endif /* SHOPT_FS_3D */
+ shgd->ed_context = (void*)ed_open(shp);
+ error_info.exit = sh_exit;
+ error_info.id = path_basename(argv[0]);
+ }
+ else
+ shp = newof(0,Shell_t,1,0);
+ umask(shp->mask=umask(0));
+ shp->gd = shgd;
+ shp->mac_context = sh_macopen(shp);
+ shp->arg_context = sh_argopen(shp);
+ shp->lex_context = (void*)sh_lexopen(0,shp,1);
+ shp->strbuf = sfstropen();
+ shp->stk = stkstd;
+ sfsetbuf(shp->strbuf,(char*)0,64);
+ sh_onstate(SH_INIT);
+#if ERROR_VERSION >= 20000102L
+ error_info.catalog = e_dict;
+#endif
+#if SHOPT_REGRESS
+ {
+ Opt_t* nopt;
+ Opt_t* oopt;
+ char* a;
+ char** av = argv;
+ char* regress[3];
+
+ sh_regress_init(shp);
+ regress[0] = "__regress__";
+ regress[2] = 0;
+ /* NOTE: only shp is used by __regress__ at this point */
+ shp->bltindata.shp = shp;
+ while ((a = *++av) && a[0] == '-' && (a[1] == 'I' || a[1] == '-' && a[2] == 'r'))
+ {
+ if (a[1] == 'I')
+ {
+ if (a[2])
+ regress[1] = a + 2;
+ else if (!(regress[1] = *++av))
+ break;
+ }
+ else if (strncmp(a+2, "regress", 7))
+ break;
+ else if (a[9] == '=')
+ regress[1] = a + 10;
+ else if (!(regress[1] = *++av))
+ break;
+ nopt = optctx(0, 0);
+ oopt = optctx(nopt, 0);
+ b___regress__(2, regress, &shp->bltindata);
+ optctx(oopt, nopt);
+ }
+ }
+#endif
+ shp->cpipe[0] = -1;
+ shp->coutpipe = -1;
+ for(n=0;n < 10; n++)
+ {
+ /* don't use lower bits when rand() generates large numbers */
+ if(rand() > RANDMASK)
+ {
+ rand_shift = 3;
+ break;
+ }
+ }
+ sh_ioinit(shp);
+ /* initialize signal handling */
+ sh_siginit(shp);
+ stakinstall(NIL(Stak_t*),nospace);
+ /* set up memory for name-value pairs */
+ shp->init_context = nv_init(shp);
+ /* read the environment */
+ if(argc>0)
+ {
+ type = sh_type(*argv);
+ if(type&SH_TYPE_LOGIN)
+ shp->login_sh = 2;
+ }
+ env_init(shp);
+ if(!ENVNOD->nvalue.cp)
+ {
+ sfprintf(shp->strbuf,"%s/.kshrc",nv_getval(HOME));
+ nv_putval(ENVNOD,sfstruse(shp->strbuf),NV_RDONLY);
+ }
+ *SHLVL->nvalue.ip +=1;
+ nv_offattr(SHLVL,NV_IMPORT);
+#if SHOPT_SPAWN
+ {
+ /*
+ * try to find the pathname for this interpreter
+ * try using environment variable _ or argv[0]
+ */
+ char *cp=nv_getval(L_ARGNOD);
+ char buff[PATH_MAX+1];
+ shp->gd->shpath = 0;
+#if _AST_VERSION >= 20090202L
+ if((n = pathprog(NiL, buff, sizeof(buff))) > 0 && n <= sizeof(buff))
+ shp->gd->shpath = strdup(buff);
+#else
+ sfprintf(shp->strbuf,"/proc/%d/exe",getpid());
+ if((n=readlink(sfstruse(shp->strbuf),buff,sizeof(buff)-1))>0)
+ {
+ buff[n] = 0;
+ shp->gd->shpath = strdup(buff);
+ }
+#endif
+ else if((cp && (sh_type(cp)&SH_TYPE_SH)) || (argc>0 && strchr(cp= *argv,'/')))
+ {
+ if(*cp=='/')
+ shp->gd->shpath = strdup(cp);
+ else if(cp = nv_getval(PWDNOD))
+ {
+ int offset = staktell();
+ stakputs(cp);
+ stakputc('/');
+ stakputs(argv[0]);
+ pathcanon(stakptr(offset),PATH_DOTDOT);
+ shp->gd->shpath = strdup(stakptr(offset));
+ stakseek(offset);
+ }
+ }
+ }
+#endif
+ nv_putval(IFSNOD,(char*)e_sptbnl,NV_RDONLY);
+#if SHOPT_FS_3D
+ nv_stack(VPATHNOD, &VPATH_init);
+#endif /* SHOPT_FS_3D */
+ astconfdisc(newconf);
+#if SHOPT_TIMEOUT
+ shp->st.tmout = SHOPT_TIMEOUT;
+#endif /* SHOPT_TIMEOUT */
+ /* initialize jobs table */
+ job_clear();
+ if(argc>0)
+ {
+ /* check for restricted shell */
+ if(type&SH_TYPE_RESTRICTED)
+ sh_onoption(SH_RESTRICTED);
+#if SHOPT_PFSH
+ /* check for profile shell */
+ else if(type&SH_TYPE_PROFILE)
+ sh_onoption(SH_PFSH);
+#endif
+#if SHOPT_BASH
+ /* check for invocation as bash */
+ if(type&SH_TYPE_BASH)
+ {
+ shp>userinit = userinit = bash_init;
+ sh_onoption(SH_BASH);
+ sh_onstate(SH_PREINIT);
+ (*userinit)(shp, 0);
+ sh_offstate(SH_PREINIT);
+ }
+#endif
+ /* look for options */
+ /* shp->st.dolc is $# */
+ if((shp->st.dolc = sh_argopts(-argc,argv,shp)) < 0)
+ {
+ shp->exitval = 2;
+ sh_done(shp,0);
+ }
+ opt_info.disc = 0;
+ shp->st.dolv=argv+(argc-1)-shp->st.dolc;
+ shp->st.dolv[0] = argv[0];
+ if(shp->st.dolc < 1)
+ sh_onoption(SH_SFLAG);
+ if(!sh_isoption(SH_SFLAG))
+ {
+ shp->st.dolc--;
+ shp->st.dolv++;
+#if _WINIX
+ {
+ char* name;
+ name = shp->st.dolv[0];
+ if(name[1]==':' && (name[2]=='/' || name[2]=='\\'))
+ {
+#if _lib_pathposix
+ char* p;
+
+ if((n = pathposix(name, NIL(char*), 0)) > 0 && (p = (char*)malloc(++n)))
+ {
+ pathposix(name, p, n);
+ name = p;
+ }
+ else
+#endif
+ {
+ name[1] = name[0];
+ name[0] = name[2] = '/';
+ }
+ }
+ }
+#endif /* _WINIX */
+ }
+ if(beenhere==1)
+ {
+ struct lconv* lc;
+ shp->decomma = (lc=localeconv()) && lc->decimal_point && *lc->decimal_point==',';
+ beenhere = 2;
+ }
+ }
+#if SHOPT_PFSH
+ if (sh_isoption(SH_PFSH))
+ {
+ struct passwd *pw = getpwuid(shp->gd->userid);
+ if(pw)
+ shp->gd->user = strdup(pw->pw_name);
+
+ }
+#endif
+ /* set[ug]id scripts require the -p flag */
+ if(shp->gd->userid!=shp->gd->euserid || shp->gd->groupid!=shp->gd->egroupid)
+ {
+#ifdef SHOPT_P_SUID
+ /* require sh -p to run setuid and/or setgid */
+ if(!sh_isoption(SH_PRIVILEGED) && shp->gd->userid >= SHOPT_P_SUID)
+ {
+ setuid(shp->gd->euserid=shp->gd->userid);
+ setgid(shp->gd->egroupid=shp->gd->groupid);
+ }
+ else
+#endif /* SHOPT_P_SUID */
+ sh_onoption(SH_PRIVILEGED);
+#ifdef SHELLMAGIC
+ /* careful of #! setuid scripts with name beginning with - */
+ if(shp->login_sh && argv[1] && strcmp(argv[0],argv[1])==0)
+ errormsg(SH_DICT,ERROR_exit(1),e_prohibited);
+#endif /*SHELLMAGIC*/
+ }
+ else
+ sh_offoption(SH_PRIVILEGED);
+ /* shname for $0 in profiles and . scripts */
+ if(sh_isdevfd(argv[1]))
+ shp->shname = strdup(argv[0]);
+ else
+ shp->shname = strdup(shp->st.dolv[0]);
+ /*
+ * return here for shell script execution
+ * but not for parenthesis subshells
+ */
+ error_info.id = strdup(shp->st.dolv[0]); /* error_info.id is $0 */
+ shp->jmpbuffer = (void*)&shp->checkbase;
+ sh_pushcontext(shp,&shp->checkbase,SH_JMPSCRIPT);
+ shp->st.self = &shp->global;
+ shp->topscope = (Shscope_t*)shp->st.self;
+ sh_offstate(SH_INIT);
+ login_files[0] = (char*)e_profile;
+ login_files[1] = ".profile";
+ shp->gd->login_files = login_files;
+ shp->bltindata.version = SH_VERSION;
+ shp->bltindata.shp = shp;
+ shp->bltindata.shrun = sh_run;
+ shp->bltindata.shtrap = sh_trap;
+ shp->bltindata.shexit = sh_exit;
+ shp->bltindata.shbltin = sh_addbuiltin;
+#if _AST_VERSION >= 20080617L
+ shp->bltindata.shgetenv = sh_getenv;
+ shp->bltindata.shsetenv = sh_setenviron;
+ astintercept(&shp->bltindata,1);
+#endif
+#if 0
+#define NV_MKINTTYPE(x,y,z) nv_mkinttype(#x,sizeof(x),(x)-1<0,(y),(Namdisc_t*)z);
+ NV_MKINTTYPE(pid_t,"process id",0);
+ NV_MKINTTYPE(gid_t,"group id",0);
+ NV_MKINTTYPE(uid_t,"user id",0);
+ NV_MKINTTYPE(size_t,(const char*)0,0);
+ NV_MKINTTYPE(ssize_t,(const char*)0,0);
+ NV_MKINTTYPE(off_t,"offset in bytes",0);
+ NV_MKINTTYPE(ino_t,"\ai-\anode number",0);
+ NV_MKINTTYPE(mode_t,(const char*)0,&modedisc);
+ NV_MKINTTYPE(dev_t,"device id",0);
+ NV_MKINTTYPE(nlink_t,"hard link count",0);
+ NV_MKINTTYPE(blkcnt_t,"block count",0);
+ NV_MKINTTYPE(time_t,"seconds since the epoch",0);
+ nv_mkstat();
+#endif
+ if(shp->userinit=userinit)
+ (*userinit)(shp, 0);
+ return(shp);
+}
+
+Shell_t *sh_getinterp(void)
+{
+ return(&sh);
+}
+
+/*
+ * reinitialize before executing a script
+ */
+int sh_reinit(char *argv[])
+{
+ Shell_t *shp = sh_getinterp();
+ Shopt_t opt;
+ Namval_t *np,*npnext;
+ Dt_t *dp;
+ struct adata
+ {
+ Shell_t *sh;
+ void *extra[2];
+ } data;
+ for(np=dtfirst(shp->fun_tree);np;np=npnext)
+ {
+ if((dp=shp->fun_tree)->walk)
+ dp = dp->walk;
+ npnext = (Namval_t*)dtnext(shp->fun_tree,np);
+ if(np>= shgd->bltin_cmds && np < &shgd->bltin_cmds[nbltins])
+ continue;
+ if(is_abuiltin(np) && nv_isattr(np,NV_EXPORT))
+ continue;
+ if(*np->nvname=='/')
+ continue;
+ nv_delete(np,dp,NV_NOFREE);
+ }
+ dtclose(shp->alias_tree);
+ shp->alias_tree = inittree(shp,shtab_aliases);
+ shp->last_root = shp->var_tree;
+ shp->inuse_bits = 0;
+ if(shp->userinit)
+ (*shp->userinit)(shp, 1);
+ if(shp->heredocs)
+ {
+ sfclose(shp->heredocs);
+ shp->heredocs = 0;
+ }
+ /* remove locals */
+ sh_onstate(SH_INIT);
+ memset(&data,0,sizeof(data));
+ data.sh = shp;
+ nv_scan(shp->var_tree,sh_envnolocal,(void*)&data,NV_EXPORT,0);
+ nv_scan(shp->var_tree,sh_envnolocal,(void*)&data,NV_ARRAY,NV_ARRAY);
+ sh_offstate(SH_INIT);
+ memset(shp->st.trapcom,0,(shp->st.trapmax+1)*sizeof(char*));
+ memset((void*)&opt,0,sizeof(opt));
+#if SHOPT_NAMESPACE
+ if(shp->namespace)
+ {
+ dp=nv_dict(shp->namespace);
+ if(dp==shp->var_tree)
+ shp->var_tree = dtview(dp,0);
+ _nv_unset(shp->namespace,NV_RDONLY);
+ shp->namespace = 0;
+ }
+#endif /* SHOPT_NAMESPACE */
+ if(sh_isoption(SH_TRACKALL))
+ on_option(&opt,SH_TRACKALL);
+ if(sh_isoption(SH_EMACS))
+ on_option(&opt,SH_EMACS);
+ if(sh_isoption(SH_GMACS))
+ on_option(&opt,SH_GMACS);
+ if(sh_isoption(SH_VI))
+ on_option(&opt,SH_VI);
+ if(sh_isoption(SH_VIRAW))
+ on_option(&opt,SH_VIRAW);
+ shp->options = opt;
+ /* set up new args */
+ if(argv)
+ shp->arglist = sh_argcreate(argv);
+ if(shp->arglist)
+ sh_argreset(shp,shp->arglist,NIL(struct dolnod*));
+ shp->envlist=0;
+ shp->curenv = 0;
+ shp->shname = error_info.id = strdup(shp->st.dolv[0]);
+ sh_offstate(SH_FORKED);
+ shp->fn_depth = shp->dot_depth = 0;
+ sh_sigreset(0);
+ if(!(SHLVL->nvalue.ip))
+ {
+ shlvl = 0;
+ SHLVL->nvalue.ip = &shlvl;
+ nv_onattr(SHLVL,NV_INTEGER|NV_EXPORT|NV_NOFREE);
+ }
+ *SHLVL->nvalue.ip +=1;
+ nv_offattr(SHLVL,NV_IMPORT);
+ shp->st.filename = strdup(shp->lastarg);
+ nv_delete((Namval_t*)0, (Dt_t*)0, 0);
+ job.exitval = 0;
+ shp->inpipe = shp->outpipe = 0;
+ job_clear();
+ job.in_critical = 0;
+ return(1);
+}
+
+/*
+ * set when creating a local variable of this name
+ */
+Namfun_t *nv_cover(register Namval_t *np)
+{
+ if(np==IFSNOD || np==PATHNOD || np==SHELLNOD || np==FPATHNOD || np==CDPNOD || np==SECONDS || np==ENVNOD || np==LINENO)
+ return(np->nvfun);
+#ifdef _hdr_locale
+ if(np==LCALLNOD || np==LCTYPENOD || np==LCMSGNOD || np==LCCOLLNOD || np==LCNUMNOD || np==LANGNOD)
+ return(np->nvfun);
+#endif
+ return(0);
+}
+
+static const char *shdiscnames[] = { "tilde", 0};
+
+#ifdef SHOPT_STATS
+struct Stats
+{
+ Namfun_t hdr;
+ Shell_t *sh;
+ char *nodes;
+ int numnodes;
+ int current;
+};
+
+static Namval_t *next_stat(register Namval_t* np, Dt_t *root,Namfun_t *fp)
+{
+ struct Stats *sp = (struct Stats*)fp;
+ if(!root)
+ sp->current = 0;
+ else if(++sp->current>=sp->numnodes)
+ return(0);
+ return(nv_namptr(sp->nodes,sp->current));
+}
+
+static Namval_t *create_stat(Namval_t *np,const char *name,int flag,Namfun_t *fp)
+{
+ struct Stats *sp = (struct Stats*)fp;
+ register const char *cp=name;
+ register int i=0,n;
+ Namval_t *nq=0;
+ Shell_t *shp = sp->sh;
+ if(!name)
+ return(SH_STATS);
+ while((i=*cp++) && i != '=' && i != '+' && i!='[');
+ n = (cp-1) -name;
+ for(i=0; i < sp->numnodes; i++)
+ {
+ nq = nv_namptr(sp->nodes,i);
+ if((n==0||memcmp(name,nq->nvname,n)==0) && nq->nvname[n]==0)
+ goto found;
+ }
+ nq = 0;
+found:
+ if(nq)
+ {
+ fp->last = (char*)&name[n];
+ shp->last_table = SH_STATS;
+ }
+ else
+ errormsg(SH_DICT,ERROR_exit(1),e_notelem,n,name,nv_name(np));
+ return(nq);
+}
+
+static const Namdisc_t stat_disc =
+{
+ 0, 0, 0, 0, 0,
+ create_stat,
+ 0, 0,
+ next_stat
+};
+
+static char *name_stat(Namval_t *np, Namfun_t *fp)
+{
+ Shell_t *shp = sh_getinterp();
+ sfprintf(shp->strbuf,".sh.stats.%s",np->nvname);
+ return(sfstruse(shp->strbuf));
+}
+
+static const Namdisc_t stat_child_disc =
+{
+ 0,0,0,0,0,0,0,
+ name_stat
+};
+
+static Namfun_t stat_child_fun =
+{
+ &stat_child_disc, 1, 0, sizeof(Namfun_t)
+};
+
+static void stat_init(Shell_t *shp)
+{
+ int i,nstat = STAT_SUBSHELL+1;
+ struct Stats *sp = newof(0,struct Stats,1,nstat*NV_MINSZ);
+ Namval_t *np;
+ sp->numnodes = nstat;
+ sp->nodes = (char*)(sp+1);
+ shgd->stats = (int*)calloc(sizeof(int),nstat);
+ sp->sh = shp;
+ for(i=0; i < nstat; i++)
+ {
+ np = nv_namptr(sp->nodes,i);
+ np->nvfun = &stat_child_fun;
+ np->nvname = (char*)shtab_stats[i].sh_name;
+ nv_onattr(np,NV_RDONLY|NV_MINIMAL|NV_NOFREE|NV_INTEGER);
+ nv_setsize(np,10);
+ np->nvalue.ip = &shgd->stats[i];
+ }
+ sp->hdr.dsize = sizeof(struct Stats) + nstat*(sizeof(int)+NV_MINSZ);
+ sp->hdr.disc = &stat_disc;
+ nv_stack(SH_STATS,&sp->hdr);
+ sp->hdr.nofree = 1;
+ nv_setvtree(SH_STATS);
+}
+#else
+# define stat_init(x)
+#endif /* SHOPT_STATS */
+
+/*
+ * Initialize the shell name and alias table
+ */
+static Init_t *nv_init(Shell_t *shp)
+{
+ double d=0;
+ ip = newof(0,Init_t,1,0);
+ if(!ip)
+ return(0);
+ shp->nvfun.last = (char*)shp;
+ shp->nvfun.nofree = 1;
+ ip->sh = shp;
+ shp->var_base = shp->var_tree = inittree(shp,shtab_variables);
+ SHLVL->nvalue.ip = &shlvl;
+ ip->IFS_init.hdr.disc = &IFS_disc;
+ ip->PATH_init.disc = &RESTRICTED_disc;
+ ip->PATH_init.nofree = 1;
+ ip->FPATH_init.disc = &RESTRICTED_disc;
+ ip->FPATH_init.nofree = 1;
+ ip->CDPATH_init.disc = &CDPATH_disc;
+ ip->CDPATH_init.nofree = 1;
+ ip->SHELL_init.disc = &RESTRICTED_disc;
+ ip->SHELL_init.nofree = 1;
+ ip->ENV_init.disc = &RESTRICTED_disc;
+ ip->ENV_init.nofree = 1;
+ ip->VISUAL_init.disc = &EDITOR_disc;
+ ip->VISUAL_init.nofree = 1;
+ ip->EDITOR_init.disc = &EDITOR_disc;
+ ip->EDITOR_init.nofree = 1;
+ ip->HISTFILE_init.disc = &HISTFILE_disc;
+ ip->HISTFILE_init.nofree = 1;
+ ip->HISTSIZE_init.disc = &HISTFILE_disc;
+ ip->HISTSIZE_init.nofree = 1;
+ ip->OPTINDEX_init.disc = &OPTINDEX_disc;
+ ip->OPTINDEX_init.nofree = 1;
+ ip->SECONDS_init.hdr.disc = &SECONDS_disc;
+ ip->SECONDS_init.hdr.nofree = 1;
+ ip->RAND_init.hdr.disc = &RAND_disc;
+ ip->RAND_init.hdr.nofree = 1;
+ ip->RAND_init.sh = shp;
+ ip->SH_MATCH_init.hdr.disc = &SH_MATCH_disc;
+ ip->SH_MATCH_init.hdr.nofree = 1;
+ ip->SH_MATH_init.disc = &SH_MATH_disc;
+ ip->SH_MATH_init.nofree = 1;
+#if SHOPT_COSHELL
+ ip->SH_JOBPOOL_init.disc = &SH_JOBPOOL_disc;
+ ip->SH_JOBPOOL_init.nofree = 1;
+ nv_stack(SH_JOBPOOL, &ip->SH_JOBPOOL_init);
+#endif /* SHOPT_COSHELL */
+ ip->SH_VERSION_init.disc = &SH_VERSION_disc;
+ ip->SH_VERSION_init.nofree = 1;
+ ip->LINENO_init.disc = &LINENO_disc;
+ ip->LINENO_init.nofree = 1;
+ ip->L_ARG_init.disc = &L_ARG_disc;
+ ip->L_ARG_init.nofree = 1;
+#ifdef _hdr_locale
+ ip->LC_TYPE_init.disc = &LC_disc;
+ ip->LC_TYPE_init.nofree = 1;
+ ip->LC_NUM_init.disc = &LC_disc;
+ ip->LC_NUM_init.nofree = 1;
+ ip->LC_COLL_init.disc = &LC_disc;
+ ip->LC_COLL_init.nofree = 1;
+ ip->LC_MSG_init.disc = &LC_disc;
+ ip->LC_MSG_init.nofree = 1;
+ ip->LC_ALL_init.disc = &LC_disc;
+ ip->LC_ALL_init.nofree = 1;
+ ip->LANG_init.disc = &LC_disc;
+ ip->LANG_init.nofree = 1;
+#endif /* _hdr_locale */
+ nv_stack(IFSNOD, &ip->IFS_init.hdr);
+ ip->IFS_init.hdr.nofree = 1;
+ nv_stack(PATHNOD, &ip->PATH_init);
+ nv_stack(FPATHNOD, &ip->FPATH_init);
+ nv_stack(CDPNOD, &ip->CDPATH_init);
+ nv_stack(SHELLNOD, &ip->SHELL_init);
+ nv_stack(ENVNOD, &ip->ENV_init);
+ nv_stack(VISINOD, &ip->VISUAL_init);
+ nv_stack(EDITNOD, &ip->EDITOR_init);
+ nv_stack(HISTFILE, &ip->HISTFILE_init);
+ nv_stack(HISTSIZE, &ip->HISTSIZE_init);
+ nv_stack(OPTINDNOD, &ip->OPTINDEX_init);
+ nv_stack(SECONDS, &ip->SECONDS_init.hdr);
+ nv_stack(L_ARGNOD, &ip->L_ARG_init);
+ nv_putval(SECONDS, (char*)&d, NV_DOUBLE);
+ nv_stack(RANDNOD, &ip->RAND_init.hdr);
+ d = (shp->gd->pid&RANDMASK);
+ nv_putval(RANDNOD, (char*)&d, NV_DOUBLE);
+ nv_stack(LINENO, &ip->LINENO_init);
+ SH_MATCHNOD->nvfun = &ip->SH_MATCH_init.hdr;
+ nv_putsub(SH_MATCHNOD,(char*)0,10);
+ nv_stack(SH_MATHNOD, &ip->SH_MATH_init);
+ nv_stack(SH_VERSIONNOD, &ip->SH_VERSION_init);
+#ifdef _hdr_locale
+ nv_stack(LCTYPENOD, &ip->LC_TYPE_init);
+ nv_stack(LCALLNOD, &ip->LC_ALL_init);
+ nv_stack(LCMSGNOD, &ip->LC_MSG_init);
+ nv_stack(LCCOLLNOD, &ip->LC_COLL_init);
+ nv_stack(LCNUMNOD, &ip->LC_NUM_init);
+ nv_stack(LANGNOD, &ip->LANG_init);
+#endif /* _hdr_locale */
+ (PPIDNOD)->nvalue.lp = (&shp->gd->ppid);
+ (TMOUTNOD)->nvalue.lp = (&shp->st.tmout);
+ (MCHKNOD)->nvalue.lp = (&sh_mailchk);
+ (OPTINDNOD)->nvalue.lp = (&shp->st.optindex);
+ /* set up the seconds clock */
+ shp->alias_tree = inittree(shp,shtab_aliases);
+ shp->track_tree = dtopen(&_Nvdisc,Dtset);
+ shp->bltin_tree = inittree(shp,(const struct shtable2*)shtab_builtins);
+ shp->fun_tree = dtopen(&_Nvdisc,Dtoset);
+ dtview(shp->fun_tree,shp->bltin_tree);
+ nv_mount(DOTSHNOD, "type", shp->typedict=dtopen(&_Nvdisc,Dtoset));
+ nv_adddisc(DOTSHNOD, shdiscnames, (Namval_t**)0);
+ DOTSHNOD->nvalue.cp = Empty;
+ SH_LINENO->nvalue.ip = &shp->st.lineno;
+ VERSIONNOD->nvalue.nrp = newof(0,struct Namref,1,0);
+ VERSIONNOD->nvalue.nrp->np = SH_VERSIONNOD;
+ VERSIONNOD->nvalue.nrp->root = nv_dict(DOTSHNOD);
+ VERSIONNOD->nvalue.nrp->table = DOTSHNOD;
+ nv_onattr(VERSIONNOD,NV_REF);
+ math_init(shp);
+ if(!shgd->stats)
+ stat_init(shp);
+ return(ip);
+}
+
+/*
+ * initialize name-value pairs
+ */
+
+static Dt_t *inittree(Shell_t *shp,const struct shtable2 *name_vals)
+{
+ register Namval_t *np;
+ register const struct shtable2 *tp;
+ register unsigned n = 0;
+ register Dt_t *treep;
+ Dt_t *base_treep, *dict;
+ for(tp=name_vals;*tp->sh_name;tp++)
+ n++;
+ np = (Namval_t*)calloc(n,sizeof(Namval_t));
+ if(!shgd->bltin_nodes)
+ {
+ shgd->bltin_nodes = np;
+ shgd->bltin_nnodes = n;
+ }
+ else if(name_vals==(const struct shtable2*)shtab_builtins)
+ {
+ shgd->bltin_cmds = np;
+ nbltins = n;
+ }
+ base_treep = treep = dtopen(&_Nvdisc,Dtoset);
+ treep->user = (void*)shp;
+ for(tp=name_vals;*tp->sh_name;tp++,np++)
+ {
+ if((np->nvname = strrchr(tp->sh_name,'.')) && np->nvname!=((char*)tp->sh_name))
+ np->nvname++;
+ else
+ {
+ np->nvname = (char*)tp->sh_name;
+ treep = base_treep;
+ }
+ np->nvenv = 0;
+ if(name_vals==(const struct shtable2*)shtab_builtins)
+ np->nvalue.bfp = (Nambfp_f)((struct shtable3*)tp)->sh_value;
+ else
+ {
+ if(name_vals == shtab_variables)
+ np->nvfun = &shp->nvfun;
+ np->nvalue.cp = (char*)tp->sh_value;
+ }
+ nv_setattr(np,tp->sh_number);
+ if(nv_isattr(np,NV_TABLE))
+ nv_mount(np,(const char*)0,dict=dtopen(&_Nvdisc,Dtoset));
+ if(nv_isattr(np,NV_INTEGER))
+ nv_setsize(np,10);
+ else
+ nv_setsize(np,0);
+ dtinsert(treep,np);
+ if(nv_istable(np))
+ treep = dict;
+ }
+ return(treep);
+}
+
+/*
+ * read in the process environment and set up name-value pairs
+ * skip over items that are not name-value pairs
+ */
+
+static void env_init(Shell_t *shp)
+{
+ register char *cp;
+ register Namval_t *np,*mp;
+ register char **ep=environ;
+ char *dp,*next=0;
+ int nenv=0,k=0,size=0;
+ Namval_t *np0;
+#ifdef _ENV_H
+ shp->env = env_open(environ,3);
+ env_delete(shp->env,"_");
+#endif
+ if(!ep)
+ goto skip;
+ while(*ep++)
+ nenv++;
+ np = newof(0,Namval_t,nenv,0);
+ for(np0=np,ep=environ;cp= *ep; ep++)
+ {
+ dp = strchr(cp,'=');
+ if(!dp)
+ continue;
+ *dp++ = 0;
+ if(mp = dtmatch(shp->var_base,cp))
+ {
+ mp->nvenv = (char*)cp;
+ dp[-1] = '=';
+ }
+ else if(*cp=='A' && cp[1]=='_' && cp[2]=='_' && cp[3]=='z' && cp[4]==0)
+ {
+ dp[-1] = '=';
+ next = cp+4;
+ continue;
+ }
+ else
+ {
+ k++;
+ mp = np++;
+ mp->nvname = cp;
+ size += strlen(cp);
+ }
+ nv_onattr(mp,NV_IMPORT);
+ if(mp->nvfun || nv_isattr(mp,NV_INTEGER))
+ nv_putval(mp,dp,0);
+ else
+ {
+ mp->nvalue.cp = dp;
+ nv_onattr(mp,NV_NOFREE);
+ }
+ nv_onattr(mp,NV_EXPORT|NV_IMPORT);
+ }
+ np = (Namval_t*)realloc((void*)np0,k*sizeof(Namval_t));
+ dp = (char*)malloc(size+k);
+ while(k-->0)
+ {
+ size = strlen(np->nvname);
+ memcpy(dp,np->nvname,size+1);
+ np->nvname[size] = '=';
+ np->nvenv = np->nvname;
+ np->nvname = dp;
+ dp += size+1;
+ dtinsert(shp->var_base,np++);
+ }
+ while(cp=next)
+ {
+ if(next = strchr(++cp,'='))
+ *next = 0;
+ np = nv_search(cp+2,shp->var_tree,NV_ADD);
+ if(np!=SHLVL && nv_isattr(np,NV_IMPORT|NV_EXPORT))
+ {
+ int flag = *(unsigned char*)cp-' ';
+ int size = *(unsigned char*)(cp+1)-' ';
+ if((flag&NV_INTEGER) && size==0)
+ {
+ /* check for floating*/
+ char *val = nv_getval(np);
+ strtol(val,&dp,10);
+ if(*dp=='.' || *dp=='e' || *dp=='E')
+ {
+ char *lp;
+ flag |= NV_DOUBLE;
+ if(*dp=='.')
+ {
+ strtol(dp+1,&lp,10);
+ if(*lp)
+ dp = lp;
+ }
+ if(*dp && *dp!='.')
+ {
+ flag |= NV_EXPNOTE;
+ size = dp-val;
+ }
+ else
+ size = strlen(dp);
+ size--;
+ }
+ }
+ nv_newattr(np,flag|NV_IMPORT|NV_EXPORT,size);
+ if((flag&(NV_INTEGER|NV_UTOL|NV_LTOU))==(NV_UTOL|NV_LTOU))
+ nv_mapchar(np,(flag&NV_UTOL)?e_tolower:e_toupper);
+ }
+ else
+ cp += 2;
+ }
+skip:
+#ifdef _ENV_H
+ env_delete(shp->env,e_envmarker);
+#endif
+ if(nv_isnull(PWDNOD) || nv_isattr(PWDNOD,NV_TAGGED))
+ {
+ nv_offattr(PWDNOD,NV_TAGGED);
+ path_pwd(shp,0);
+ }
+ if((cp = nv_getval(SHELLNOD)) && (sh_type(cp)&SH_TYPE_RESTRICTED))
+ sh_onoption(SH_RESTRICTED); /* restricted shell */
+ return;
+}
+
+/*
+ * terminate shell and free up the space
+ */
+int sh_term(void)
+{
+ sfdisc(sfstdin,SF_POPDISC);
+ free((char*)sh.outbuff);
+ stakset(NIL(char*),0);
+ return(0);
+}
+
+/* function versions of these */
+
+#define DISABLE /* proto workaround */
+
+unsigned long sh_isoption DISABLE (int opt)
+{
+ return(sh_isoption(opt));
+}
+
+unsigned long sh_onoption DISABLE (int opt)
+{
+ return(sh_onoption(opt));
+}
+
+unsigned long sh_offoption DISABLE (int opt)
+{
+ return(sh_offoption(opt));
+}
+
+void sh_sigcheck DISABLE (void)
+{
+ Shell_t *shp = sh_getinterp();
+ sh_sigcheck(shp);
+}
+
+Dt_t* sh_bltin_tree DISABLE (void)
+{
+ return(sh.bltin_tree);
+}
+
+/*
+ * This code is for character mapped variables with wctrans()
+ */
+struct Mapchar
+{
+ Namfun_t hdr;
+ const char *name;
+ wctrans_t trans;
+ int lctype;
+};
+
+static void put_trans(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ struct Mapchar *mp = (struct Mapchar*)fp;
+ int c,offset = staktell(),off=offset;
+ if(val)
+ {
+ if(mp->lctype!=lctype)
+ {
+ mp->lctype = lctype;
+ mp->trans = wctrans(mp->name);
+ }
+ if(!mp->trans || (flags&NV_INTEGER))
+ goto skip;
+ while(c = mbchar(val))
+ {
+ c = towctrans(c,mp->trans);
+ stakseek(off+c);
+ stakseek(off);
+ c = mbconv(stakptr(off),c);
+ off += c;
+ stakseek(off);
+ }
+ stakputc(0);
+ val = stakptr(offset);
+ }
+ else
+ {
+ nv_putv(np,val,flags,fp);
+ nv_disc(np,fp,NV_POP);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ stakseek(offset);
+ return;
+ }
+skip:
+ nv_putv(np,val,flags,fp);
+ stakseek(offset);
+}
+
+static const Namdisc_t TRANS_disc = { sizeof(struct Mapchar), put_trans };
+
+Namfun_t *nv_mapchar(Namval_t *np,const char *name)
+{
+ wctrans_t trans = name?wctrans(name):0;
+ struct Mapchar *mp=0;
+ int n=0,low;
+ if(np)
+ mp = (struct Mapchar*)nv_hasdisc(np,&TRANS_disc);
+ if(!name)
+ return(mp?(Namfun_t*)mp->name:0);
+ if(!trans)
+ return(0);
+ if(!np)
+ return(((Namfun_t*)0)+1);
+ if((low=strcmp(name,e_tolower)) && strcmp(name,e_toupper))
+ n += strlen(name)+1;
+ if(mp)
+ {
+ if(strcmp(name,mp->name)==0)
+ return(&mp->hdr);
+ nv_disc(np,&mp->hdr,NV_POP);
+ if(!(mp->hdr.nofree&1))
+ free((void*)mp);
+ }
+ mp = newof(0,struct Mapchar,1,n);
+ mp->trans = trans;
+ mp->lctype = lctype;
+ if(low==0)
+ mp->name = e_tolower;
+ else if(n==0)
+ mp->name = e_toupper;
+ else
+ {
+ mp->name = (char*)(mp+1);
+ strcpy((char*)mp->name,name);
+ }
+ mp->hdr.disc = &TRANS_disc;
+ return(&mp->hdr);
+}
diff --git a/src/cmd/ksh93/sh/io.c b/src/cmd/ksh93/sh/io.c
new file mode 100644
index 0000000..9649f1f
--- /dev/null
+++ b/src/cmd/ksh93/sh/io.c
@@ -0,0 +1,2647 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Input/output file processing
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <fcin.h>
+#include <ls.h>
+#include <stdarg.h>
+#include <regex.h>
+#include "variables.h"
+#include "path.h"
+#include "io.h"
+#include "jobs.h"
+#include "shnodes.h"
+#include "history.h"
+#include "edit.h"
+#include "timeout.h"
+#include "FEATURE/externs"
+#include "FEATURE/dynamic"
+#include "FEATURE/poll"
+
+#ifdef FNDELAY
+# ifdef EAGAIN
+# if EAGAIN!=EWOULDBLOCK
+# undef EAGAIN
+# define EAGAIN EWOULDBLOCK
+# endif
+# else
+# define EAGAIN EWOULDBLOCK
+# endif /* EAGAIN */
+# ifndef O_NONBLOCK
+# define O_NONBLOCK FNDELAY
+# endif /* !O_NONBLOCK */
+#endif /* FNDELAY */
+
+#ifndef O_SERVICE
+# define O_SERVICE O_NOCTTY
+#endif
+
+#define RW_ALL (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)
+
+static void *timeout;
+static int (*fdnotify)(int,int);
+
+#if defined(_lib_socket) && defined(_sys_socket) && defined(_hdr_netinet_in)
+# include <sys/socket.h>
+# include <netdb.h>
+# include <netinet/in.h>
+# if !defined(htons) && !_lib_htons
+# define htons(x) (x)
+# endif
+# if !defined(htonl) && !_lib_htonl
+# define htonl(x) (x)
+# endif
+# if _pipe_socketpair && !_stream_peek
+# ifndef SHUT_RD
+# define SHUT_RD 0
+# endif
+# ifndef SHUT_WR
+# define SHUT_WR 1
+# endif
+# if _socketpair_shutdown_mode
+# define pipe(v) ((socketpair(AF_UNIX,SOCK_STREAM,0,v)<0||shutdown((v)[1],SHUT_RD)<0||fchmod((v)[1],S_IWUSR)<0||shutdown((v)[0],SHUT_WR)<0||fchmod((v)[0],S_IRUSR)<0)?(-1):0)
+# else
+# define pipe(v) ((socketpair(AF_UNIX,SOCK_STREAM,0,v)<0||shutdown((v)[1],SHUT_RD)<0||shutdown((v)[0],SHUT_WR)<0)?(-1):0)
+# endif
+# endif
+
+#if !_lib_getaddrinfo
+
+#undef EAI_SYSTEM
+
+#define EAI_SYSTEM 1
+
+#undef addrinfo
+#undef getaddrinfo
+#undef freeaddrinfo
+
+#define addrinfo local_addrinfo
+#define getaddrinfo local_getaddrinfo
+#define freeaddrinfo local_freeaddrinfo
+
+struct addrinfo
+{
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ socklen_t ai_addrlen;
+ struct sockaddr* ai_addr;
+ struct addrinfo* ai_next;
+};
+
+static int
+getaddrinfo(const char* node, const char* service, const struct addrinfo* hint, struct addrinfo **addr)
+{
+ unsigned long ip_addr = 0;
+ unsigned short ip_port = 0;
+ struct addrinfo* ap;
+ struct hostent* hp;
+ struct sockaddr_in* ip;
+ char* prot;
+ long n;
+
+ if (!(hp = gethostbyname(node)) || hp->h_addrtype!=AF_INET || hp->h_length>sizeof(struct in_addr))
+ {
+ errno = EADDRNOTAVAIL;
+ return EAI_SYSTEM;
+ }
+ ip_addr = (unsigned long)((struct in_addr*)hp->h_addr)->s_addr;
+ if ((n = strtol(service, &prot, 10)) > 0 && n <= USHRT_MAX && !*prot)
+ ip_port = htons((unsigned short)n);
+ else
+ {
+ struct servent* sp;
+ const char* protocol = 0;
+
+ if (hint)
+ switch (hint->ai_socktype)
+ {
+ case SOCK_STREAM:
+ switch (hint->ai_protocol)
+ {
+ case 0:
+ protocol = "tcp";
+ break;
+#ifdef IPPROTO_SCTP
+ case IPPROTO_SCTP:
+ protocol = "sctp";
+ break;
+#endif
+ }
+ break;
+ case SOCK_DGRAM:
+ protocol = "udp";
+ break;
+ }
+ if (!protocol)
+ {
+ errno = EPROTONOSUPPORT;
+ return 1;
+ }
+ if (sp = getservbyname(service, protocol))
+ ip_port = sp->s_port;
+ }
+ if (!ip_port)
+ {
+ errno = EADDRNOTAVAIL;
+ return EAI_SYSTEM;
+ }
+ if (!(ap = newof(0, struct addrinfo, 1, sizeof(struct sockaddr_in))))
+ return EAI_SYSTEM;
+ if (hint)
+ *ap = *hint;
+ ap->ai_family = hp->h_addrtype;
+ ap->ai_addrlen = sizeof(struct sockaddr_in);
+ ap->ai_addr = (struct sockaddr *)(ap+1);
+ ip = (struct sockaddr_in *)ap->ai_addr;
+ ip->sin_family = AF_INET;
+ ip->sin_port = ip_port;
+ ip->sin_addr.s_addr = ip_addr;
+ *addr = ap;
+ return 0;
+}
+
+static void
+freeaddrinfo(struct addrinfo* ap)
+{
+ if (ap)
+ free(ap);
+}
+
+#endif
+
+/*
+ * return <protocol>/<host>/<service> fd
+ * If called with flags==O_NONBLOCK return 1 if protocol is supported
+ */
+
+typedef int (*Inetintr_f)(struct addrinfo*, void*);
+
+static int
+inetopen(const char* path, int flags, Inetintr_f onintr, void* handle)
+{
+ register char* s;
+ register char* t;
+ int fd;
+ int oerrno;
+ struct addrinfo hint;
+ struct addrinfo* addr;
+ struct addrinfo* p;
+ int server = !!(flags&O_SERVICE);
+
+ memset(&hint, 0, sizeof(hint));
+ hint.ai_family = PF_UNSPEC;
+ switch (path[0])
+ {
+#ifdef IPPROTO_SCTP
+ case 's':
+ if (path[1]!='c' || path[2]!='t' || path[3]!='p' || path[4]!='/')
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_SCTP;
+ path += 5;
+ break;
+#endif
+ case 't':
+ if (path[1]!='c' || path[2]!='p' || path[3]!='/')
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ hint.ai_socktype = SOCK_STREAM;
+ path += 4;
+ break;
+ case 'u':
+ if (path[1]!='d' || path[2]!='p' || path[3]!='/')
+ {
+ errno = ENOTDIR;
+ return -1;
+ }
+ hint.ai_socktype = SOCK_DGRAM;
+ path += 4;
+ break;
+ default:
+ errno = ENOTDIR;
+ return -1;
+ }
+ if(flags==O_NONBLOCK)
+ return 1;
+ if (!(s = strdup(path)))
+ return -1;
+ if (t = strchr(s, '/'))
+ {
+ *t++ = 0;
+ if (streq(s, "local"))
+ s = strdup("localhost");
+ fd = getaddrinfo(s, t, &hint, &addr);
+ }
+ else
+ fd = -1;
+ free(s);
+ if (fd)
+ {
+ if (fd != EAI_SYSTEM)
+ errno = ENOTDIR;
+ return -1;
+ }
+ oerrno = errno;
+ errno = 0;
+ fd = -1;
+ for (p = addr; p; p = p->ai_next)
+ {
+ /*
+ * some api's don't take the hint
+ */
+
+ if (!p->ai_protocol)
+ p->ai_protocol = hint.ai_protocol;
+ if (!p->ai_socktype)
+ p->ai_socktype = hint.ai_socktype;
+ while ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) >= 0)
+ {
+ if (server && !bind(fd, p->ai_addr, p->ai_addrlen) && !listen(fd, 5) || !server && !connect(fd, p->ai_addr, p->ai_addrlen))
+ goto done;
+ close(fd);
+ fd = -1;
+ if (errno != EINTR || !onintr)
+ break;
+ if ((*onintr)(addr, handle))
+ goto done;
+ }
+ }
+ done:
+ freeaddrinfo(addr);
+ if (fd >= 0)
+ errno = oerrno;
+ return fd;
+}
+
+#else
+
+#undef O_SERVICE
+#undef SHOPT_COSHELL
+
+#endif
+
+struct fdsave
+{
+ int orig_fd; /* original file descriptor */
+ int save_fd; /* saved file descriptor */
+ int subshell; /* saved for subshell */
+ char *tname; /* name used with >; */
+};
+
+struct Iodisc
+{
+ Sfdisc_t disc;
+ Shell_t *sh;
+};
+
+static int subexcept(Sfio_t*, int, void*, Sfdisc_t*);
+static int eval_exceptf(Sfio_t*, int, void*, Sfdisc_t*);
+static int slowexcept(Sfio_t*, int, void*, Sfdisc_t*);
+static int pipeexcept(Sfio_t*, int, void*, Sfdisc_t*);
+static ssize_t piperead(Sfio_t*, void*, size_t, Sfdisc_t*);
+static ssize_t slowread(Sfio_t*, void*, size_t, Sfdisc_t*);
+static ssize_t subread(Sfio_t*, void*, size_t, Sfdisc_t*);
+static ssize_t tee_write(Sfio_t*,const void*,size_t,Sfdisc_t*);
+static int io_prompt(Shell_t*,Sfio_t*,int);
+static int io_heredoc(Shell_t*,register struct ionod*, const char*, int);
+static void sftrack(Sfio_t*,int,void*);
+static const Sfdisc_t eval_disc = { NULL, NULL, NULL, eval_exceptf, NULL};
+static Sfdisc_t tee_disc = {NULL,tee_write,NULL,NULL,NULL};
+static Sfio_t *subopen(Shell_t *,Sfio_t*, off_t, long);
+static const Sfdisc_t sub_disc = { subread, 0, 0, subexcept, 0 };
+
+struct subfile
+{
+ Sfdisc_t disc;
+ Sfio_t *oldsp;
+ off_t offset;
+ long size;
+ long left;
+};
+
+struct Eof
+{
+ Namfun_t hdr;
+ int fd;
+};
+
+static Sfdouble_t nget_cur_eof(register Namval_t* np, Namfun_t *fp)
+{
+ struct Eof *ep = (struct Eof*)fp;
+ Sfoff_t end, cur =lseek(ep->fd, (Sfoff_t)0, SEEK_CUR);
+ if(*np->nvname=='C')
+ return((Sfdouble_t)cur);
+ if(cur<0)
+ return((Sfdouble_t)-1);
+ end =lseek(ep->fd, (Sfoff_t)0, SEEK_END);
+ lseek(ep->fd, (Sfoff_t)0, SEEK_CUR);
+ return((Sfdouble_t)end);
+}
+
+static const Namdisc_t EOF_disc = { sizeof(struct Eof), 0, 0, nget_cur_eof};
+
+#define MATCH_BUFF (64*1024)
+struct Match
+{
+ Sfoff_t offset;
+ char *base;
+};
+
+static int matchf(void *handle, char *ptr, size_t size)
+{
+ struct Match *mp = (struct Match*)handle;
+ mp->offset += (ptr-mp->base);
+ return(1);
+}
+
+
+static struct fdsave *filemap;
+static short filemapsize;
+
+#define PSEUDOFD (SHRT_MAX)
+
+/* ======== input output and file copying ======== */
+
+int sh_iovalidfd(Shell_t *shp, int fd)
+{
+ Sfio_t **sftable = shp->sftable;
+ int max,n, **fdptrs = shp->fdptrs;
+ unsigned char *fdstatus = shp->fdstatus;
+ if(fd<0)
+ return(0);
+ if(fd < shp->gd->lim.open_max)
+ return(1);
+ max = strtol(astconf("OPEN_MAX",NiL,NiL),NiL,0);
+ if(fd >= max)
+ {
+ errno = EBADF;
+ return(0);
+ }
+ n = (fd+16)&~0xf;
+ if(n > max)
+ n = max;
+ max = shp->gd->lim.open_max;
+ shp->sftable = (Sfio_t**)calloc((n+1)*(sizeof(int*)+sizeof(Sfio_t*)+1),1);
+ if(max)
+ memcpy(shp->sftable,sftable,max*sizeof(Sfio_t*));
+ shp->fdptrs = (int**)(&shp->sftable[n]);
+ if(max)
+ memcpy(shp->fdptrs,fdptrs,max*sizeof(int*));
+ shp->fdstatus = (unsigned char*)(&shp->fdptrs[n]);
+ if(max)
+ memcpy(shp->fdstatus,fdstatus,max);
+ if(sftable)
+ free((void*)sftable);
+ shp->gd->lim.open_max = n;
+ return(1);
+}
+
+int sh_inuse(Shell_t *shp, int fd)
+{
+ return(fd < shp->gd->lim.open_max && shp->fdptrs[fd]);
+}
+
+void sh_ioinit(Shell_t *shp)
+{
+ filemapsize = 8;
+ filemap = (struct fdsave*)malloc(filemapsize*sizeof(struct fdsave));
+ sh_iovalidfd(shp,16);
+ shp->sftable[0] = sfstdin;
+ shp->sftable[1] = sfstdout;
+ shp->sftable[2] = sfstderr;
+ sfnotify(sftrack);
+ sh_iostream(shp,0);
+ sh_iostream(shp,1);
+ /* all write steams are in the same pool and share outbuff */
+ shp->outpool = sfopen(NIL(Sfio_t*),NIL(char*),"sw"); /* pool identifier */
+ shp->outbuff = (char*)malloc(IOBSIZE+4);
+ shp->errbuff = (char*)malloc(IOBSIZE/4);
+ sfsetbuf(sfstderr,shp->errbuff,IOBSIZE/4);
+ sfsetbuf(sfstdout,shp->outbuff,IOBSIZE);
+ sfpool(sfstdout,shp->outpool,SF_WRITE);
+ sfpool(sfstderr,shp->outpool,SF_WRITE);
+ sfset(sfstdout,SF_LINE,0);
+ sfset(sfstderr,SF_LINE,0);
+ sfset(sfstdin,SF_SHARE|SF_PUBLIC,1);
+}
+
+/*
+ * Handle output stream exceptions
+ */
+static int outexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle)
+{
+ Shell_t *shp = ((struct Iodisc*)handle)->sh;
+ static int active = 0;
+ if(type==SF_DPOP || type==SF_FINAL)
+ free((void*)handle);
+ else if(type==SF_WRITE && (*(ssize_t*)data)<0 && sffileno(iop)!=2)
+ switch (errno)
+ {
+ case EINTR:
+ case EPIPE:
+#ifdef ECONNRESET
+ case ECONNRESET:
+#endif
+#ifdef ESHUTDOWN
+ case ESHUTDOWN:
+#endif
+ break;
+ default:
+ if(!active)
+ {
+ int mode = ((struct checkpt*)shp->jmplist)->mode;
+ int save = errno;
+ active = 1;
+ ((struct checkpt*)shp->jmplist)->mode = 0;
+ sfpurge(iop);
+ sfpool(iop,NIL(Sfio_t*),SF_WRITE);
+ errno = save;
+ errormsg(SH_DICT,ERROR_system(1),e_badwrite,sffileno(iop));
+ active = 0;
+ ((struct checkpt*)shp->jmplist)->mode = mode;
+ sh_exit(1);
+ }
+ return(-1);
+ }
+ return(0);
+}
+
+/*
+ * create or initialize a stream corresponding to descriptor <fd>
+ * a buffer with room for a sentinal is allocated for a read stream.
+ * A discipline is inserted when read stream is a tty or a pipe
+ * For output streams, the buffer is set to sh.output and put into
+ * the sh.outpool synchronization pool
+ */
+Sfio_t *sh_iostream(Shell_t *shp, register int fd)
+{
+ register Sfio_t *iop;
+ register int status = sh_iocheckfd(shp,fd);
+ register int flags = SF_WRITE;
+ char *bp;
+ struct Iodisc *dp;
+ if(status==IOCLOSE)
+ {
+ switch(fd)
+ {
+ case 0:
+ return(sfstdin);
+ case 1:
+ return(sfstdout);
+ case 2:
+ return(sfstderr);
+ }
+ return(NIL(Sfio_t*));
+ }
+ if(status&IOREAD)
+ {
+ if(!(bp = (char *)malloc(IOBSIZE+1)))
+ return(NIL(Sfio_t*));
+ flags |= SF_READ;
+ if(!(status&IOWRITE))
+ flags &= ~SF_WRITE;
+ }
+ else
+ bp = shp->outbuff;
+ if(status&IODUP)
+ flags |= SF_SHARE|SF_PUBLIC;
+ if((iop = shp->sftable[fd]) && sffileno(iop)>=0)
+ {
+ if(status&IOTTY)
+ sfset(iop,SF_LINE|SF_WCWIDTH,1);
+ sfsetbuf(iop, bp, IOBSIZE);
+ }
+ else if(!(iop=sfnew((fd<=2?iop:0),bp,IOBSIZE,fd,flags)))
+ return(NIL(Sfio_t*));
+ dp = newof(0,struct Iodisc,1,0);
+ dp->sh = shp;
+ if(status&IOREAD)
+ {
+ sfset(iop,SF_MALLOC,1);
+ if(!(status&IOWRITE))
+ sfset(iop,SF_IOCHECK,1);
+ dp->disc.exceptf = slowexcept;
+ if(status&IOTTY)
+ dp->disc.readf = slowread;
+ else if(status&IONOSEEK)
+ {
+ dp->disc.readf = piperead;
+ sfset(iop, SF_IOINTR,1);
+ }
+ else
+ dp->disc.readf = 0;
+ dp->disc.seekf = 0;
+ dp->disc.writef = 0;
+ }
+ else
+ {
+ if((status&(IONOSEEK|IOTTY)) == IONOSEEK)
+ dp->disc.exceptf = pipeexcept;
+ else
+ dp->disc.exceptf = outexcept;
+ sfpool(iop,shp->outpool,SF_WRITE);
+ }
+ sfdisc(iop,&dp->disc);
+ shp->sftable[fd] = iop;
+ return(iop);
+}
+
+/*
+ * preserve the file descriptor or stream by moving it
+ */
+static void io_preserve(Shell_t* shp, register Sfio_t *sp, register int f2)
+{
+ register int fd;
+ if(sp)
+ fd = sfsetfd(sp,10);
+ else
+ fd = sh_fcntl(f2,F_DUPFD,10);
+ if(f2==shp->infd)
+ shp->infd = fd;
+ if(fd<0)
+ {
+ shp->toomany = 1;
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
+ errormsg(SH_DICT,ERROR_system(1),e_toomany);
+ }
+ if(f2 >= shp->gd->lim.open_max)
+ sh_iovalidfd(shp,f2);
+ if(shp->fdptrs[fd]=shp->fdptrs[f2])
+ {
+ if(f2==job.fd)
+ job.fd=fd;
+ *shp->fdptrs[fd] = fd;
+ shp->fdptrs[f2] = 0;
+ }
+ shp->sftable[fd] = sp;
+ shp->fdstatus[fd] = shp->fdstatus[f2];
+ if(fcntl(f2,F_GETFD,0)&1)
+ {
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fd] |= IOCLEX;
+ }
+ shp->sftable[f2] = 0;
+}
+
+/*
+ * Given a file descriptor <f1>, move it to a file descriptor number <f2>
+ * If <f2> is needed move it, otherwise it is closed first.
+ * The original stream <f1> is closed.
+ * The new file descriptor <f2> is returned;
+ */
+int sh_iorenumber(Shell_t *shp, register int f1,register int f2)
+{
+ register Sfio_t *sp = shp->sftable[f2];
+ if(f1!=f2)
+ {
+ /* see whether file descriptor is in use */
+ if(sh_inuse(shp,f2) || (f2>2 && sp))
+ {
+ if(!(shp->inuse_bits&(1<<f2)))
+ io_preserve(shp,sp,f2);
+ sp = 0;
+ }
+ else if(f2==0)
+ shp->st.ioset = 1;
+ sh_close(f2);
+ if(f2<=2 && sp)
+ {
+ register Sfio_t *spnew = sh_iostream(shp,f1);
+ shp->fdstatus[f2] = (shp->fdstatus[f1]&~IOCLEX);
+ sfsetfd(spnew,f2);
+ sfswap(spnew,sp);
+ sfset(sp,SF_SHARE|SF_PUBLIC,1);
+ }
+ else
+ {
+ shp->fdstatus[f2] = (shp->fdstatus[f1]&~IOCLEX);
+ if((f2 = sh_fcntl(f1,F_DUPFD, f2)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_file+4);
+ else if(f2 <= 2)
+ sh_iostream(shp,f2);
+ }
+ if(sp)
+ shp->sftable[f1] = 0;
+ if(shp->fdstatus[f1]!=IOCLOSE)
+ sh_close(f1);
+ }
+ else if(sp)
+ {
+ sfsetfd(sp,f2);
+ if(f2<=2)
+ sfset(sp,SF_SHARE|SF_PUBLIC,1);
+ }
+ if(f2>=shp->gd->lim.open_max)
+ sh_iovalidfd(shp,f2);
+ return(f2);
+}
+
+/*
+ * close a file descriptor and update stream table and attributes
+ */
+int sh_close(register int fd)
+{
+ Shell_t *shp = sh_getinterp();
+ register Sfio_t *sp;
+ register int r = 0;
+ if(fd<0)
+ return(-1);
+ if(fd >= shp->gd->lim.open_max)
+ sh_iovalidfd(shp,fd);
+ if(!(sp=shp->sftable[fd]) || sfclose(sp) < 0)
+ {
+ if(fdnotify)
+ (*fdnotify)(fd,SH_FDCLOSE);
+ r=close(fd);
+ }
+ if(fd>2)
+ shp->sftable[fd] = 0;
+ shp->fdstatus[fd] = IOCLOSE;
+ if(shp->fdptrs[fd])
+ *shp->fdptrs[fd] = -1;
+ shp->fdptrs[fd] = 0;
+ if(fd < 10)
+ shp->inuse_bits &= ~(1<<fd);
+ return(r);
+}
+
+#ifdef O_SERVICE
+
+static int
+onintr(struct addrinfo* addr, void* handle)
+{
+ Shell_t* sh = (Shell_t*)handle;
+
+ if (sh->trapnote&SH_SIGSET)
+ {
+ freeaddrinfo(addr);
+ sh_exit(SH_EXITSIG);
+ return -1;
+ }
+ if (sh->trapnote)
+ sh_chktrap(sh);
+ return 0;
+}
+
+#endif
+
+/*
+ * Mimic open(2) with checks for pseudo /dev/ files.
+ */
+int sh_open(register const char *path, int flags, ...)
+{
+ Shell_t *shp = sh_getinterp();
+ register int fd = -1;
+ mode_t mode;
+ char *e;
+ va_list ap;
+ va_start(ap, flags);
+ mode = (flags & O_CREAT) ? va_arg(ap, int) : 0;
+ va_end(ap);
+ errno = 0;
+ if(path==0)
+ {
+ errno = EFAULT;
+ return(-1);
+ }
+ if(*path==0)
+ {
+ errno = ENOENT;
+ return(-1);
+ }
+ if (path[0]=='/' && path[1]=='d' && path[2]=='e' && path[3]=='v' && path[4]=='/')
+ {
+ switch (path[5])
+ {
+ case 'f':
+ if (path[6]=='d' && path[7]=='/')
+ {
+ if(flags==O_NONBLOCK)
+ return(1);
+ fd = (int)strtol(path+8, &e, 10);
+ if (*e)
+ fd = -1;
+ }
+ break;
+ case 's':
+ if (path[6]=='t' && path[7]=='d')
+ switch (path[8])
+ {
+ case 'e':
+ if (path[9]=='r' && path[10]=='r' && !path[11])
+ fd = 2;
+ break;
+ case 'i':
+ if (path[9]=='n' && !path[10])
+ fd = 0;
+ break;
+ case 'o':
+ if (path[9]=='u' && path[10]=='t' && !path[11])
+ fd = 1;
+ break;
+ }
+ }
+#ifdef O_SERVICE
+ if (fd < 0)
+ {
+ if ((fd = inetopen(path+5, flags, onintr, shp)) < 0 && errno != ENOTDIR)
+ return -1;
+ if(flags==O_NONBLOCK)
+ return(fd>=0);
+ if (fd >= 0)
+ goto ok;
+ }
+ if(flags==O_NONBLOCK)
+ return(0);
+#endif
+ }
+ if (fd >= 0)
+ {
+ int nfd= -1;
+ if (flags & O_CREAT)
+ {
+ struct stat st;
+ if (stat(path,&st) >=0)
+ nfd = open(path,flags,st.st_mode);
+ }
+ else
+ nfd = open(path,flags);
+ if(nfd>=0)
+ {
+ fd = nfd;
+ goto ok;
+ }
+ if((mode=sh_iocheckfd(shp,fd))==IOCLOSE)
+ return(-1);
+ flags &= O_ACCMODE;
+ if(!(mode&IOWRITE) && ((flags==O_WRONLY) || (flags==O_RDWR)))
+ return(-1);
+ if(!(mode&IOREAD) && ((flags==O_RDONLY) || (flags==O_RDWR)))
+ return(-1);
+ if((fd=dup(fd))<0)
+ return(-1);
+ }
+ else
+ {
+#if SHOPT_REGRESS
+ char buf[PATH_MAX];
+ if(strncmp(path,"/etc/",5)==0)
+ {
+ sfsprintf(buf, sizeof(buf), "%s%s", sh_regress_etc(path, __LINE__, __FILE__), path+4);
+ path = buf;
+ }
+#endif
+ while((fd = open(path, flags, mode)) < 0)
+ if(errno!=EINTR || shp->trapnote)
+ return(-1);
+ }
+ ok:
+ flags &= O_ACCMODE;
+ if(flags==O_WRONLY)
+ mode = IOWRITE;
+ else if(flags==O_RDWR)
+ mode = (IOREAD|IOWRITE);
+ else
+ mode = IOREAD;
+ if(fd >= shp->gd->lim.open_max)
+ sh_iovalidfd(shp,fd);
+ shp->fdstatus[fd] = mode;
+ return(fd);
+}
+
+/*
+ * Open a file for reading
+ * On failure, print message.
+ */
+int sh_chkopen(register const char *name)
+{
+ register int fd = sh_open(name,O_RDONLY,0);
+ if(fd < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_open,name);
+ return(fd);
+}
+
+/*
+ * move open file descriptor to a number > 2
+ */
+int sh_iomovefd(register int fdold)
+{
+ Shell_t *shp = sh_getinterp();
+ register int fdnew;
+ if(fdold >= shp->gd->lim.open_max)
+ sh_iovalidfd(shp,fdold);
+ if(fdold<0 || fdold>2)
+ return(fdold);
+ fdnew = sh_iomovefd(dup(fdold));
+ shp->fdstatus[fdnew] = (shp->fdstatus[fdold]&~IOCLEX);
+ close(fdold);
+ shp->fdstatus[fdold] = IOCLOSE;
+ return(fdnew);
+}
+
+/*
+ * create a pipe and print message on failure
+ */
+int sh_pipe(register int pv[])
+{
+ Shell_t *shp = sh_getinterp();
+ int fd[2];
+ if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0)
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
+ pv[0] = sh_iomovefd(pv[0]);
+ pv[1] = sh_iomovefd(pv[1]);
+ shp->fdstatus[pv[0]] = IONOSEEK|IOREAD;
+ shp->fdstatus[pv[1]] = IONOSEEK|IOWRITE;
+ sh_subsavefd(pv[0]);
+ sh_subsavefd(pv[1]);
+ return(0);
+}
+
+#if SHOPT_COSHELL
+ int sh_coaccept(Shell_t *shp,int *pv,int out)
+ {
+ int fd = accept(pv[0],(struct sockaddr*)0,(socklen_t*)0);
+ sh_close(pv[0]);
+ pv[0] = -1;
+ if(fd<0)
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
+ if((pv[out]=sh_fcntl(fd,F_DUPFD,10)) >=10)
+ sh_close(fd);
+ else
+ pv[out] = sh_iomovefd(fd);
+ if(fcntl(pv[out],F_SETFD,FD_CLOEXEC) >=0)
+ shp->fdstatus[pv[out]] |= IOCLEX;
+ shp->fdstatus[pv[out]] = (out?IOWRITE:IOREAD);
+ shp->fdstatus[pv[out]] |= IONOSEEK;
+ sh_subsavefd(pv[out]);
+#if defined(SHUT_RD) && defined(SHUT_WR)
+ shutdown(pv[out],out?SHUT_RD:SHUT_WR);
+#endif
+ return(0);
+ }
+
+ int sh_copipe(Shell_t *shp, int *pv, int out)
+ {
+ int r,port=20000;
+ struct sockaddr_in sin;
+ socklen_t slen;
+ if ((pv[out] = socket (AF_INET, SOCK_STREAM, 0)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
+ do
+ {
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(++port);
+ sin.sin_addr.s_addr = INADDR_ANY;
+ slen = sizeof (sin);
+ }
+ while ((r=bind (pv[out], (struct sockaddr *) &sin, slen)) == -1 && errno==EADDRINUSE);
+ if(r<0 || listen(pv[out],5) <0)
+ {
+ close(pv[out]);
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
+ }
+ fcntl(pv[out],F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[pv[out]] |= IOCLEX;
+ pv[1-out] = -1;
+ pv[2] = port;
+ return(0);
+ }
+#endif /* SHOPT_COSHELL */
+
+static int pat_seek(void *handle, const char *str, size_t sz)
+{
+ char **bp = (char**)handle;
+ *bp = (char*)str;
+ return(-1);
+}
+
+static int pat_line(const regex_t* rp, const char *buff, register size_t n)
+{
+ register const char *cp=buff, *sp;
+ while(n>0)
+ {
+ for(sp=cp; n-->0 && *cp++ != '\n';);
+ if(regnexec(rp,sp,cp-sp, 0, (regmatch_t*)0, 0)==0)
+ return(sp-buff);
+ }
+ return(cp-buff);
+}
+
+static int io_patseek(Shell_t *shp, regex_t *rp, Sfio_t* sp, int flags)
+{
+ char *cp, *match;
+ int r, fd=sffileno(sp), close_exec = shp->fdstatus[fd]&IOCLEX;
+ int was_share,s=(PIPE_BUF>SF_BUFSIZE?SF_BUFSIZE:PIPE_BUF);
+ size_t n,m;
+ shp->fdstatus[sffileno(sp)] |= IOCLEX;
+ if(fd==0)
+ was_share = sfset(sp,SF_SHARE,1);
+ while((cp=sfreserve(sp, -s, SF_LOCKR)) || (cp=sfreserve(sp,SF_UNBOUND, SF_LOCKR)))
+ {
+ m = n = sfvalue(sp);
+ while(n>0 && cp[n-1]!='\n')
+ n--;
+ if(n)
+ m = n;
+ r = regrexec(rp,cp,m,0,(regmatch_t*)0, 0, '\n', (void*)&match, pat_seek);
+ if(r<0)
+ m = match-cp;
+ else if(r==2)
+ {
+ if((m = pat_line(rp,cp,m)) < n)
+ r = -1;
+ }
+ if(m && (flags&IOCOPY))
+ sfwrite(sfstdout,cp,m);
+ sfread(sp,cp,m);
+ if(r<0)
+ break;
+ }
+ if(!close_exec)
+ shp->fdstatus[sffileno(sp)] &= ~IOCLEX;
+ if(fd==0 && !(was_share&SF_SHARE))
+ sfset(sp, SF_SHARE,0);
+ return(0);
+}
+
+static Sfoff_t file_offset(Shell_t *shp, int fn, char *fname)
+{
+ Sfio_t *sp = shp->sftable[fn];
+ char *cp;
+ Sfoff_t off;
+ struct Eof endf;
+ Namval_t *mp = nv_open("EOF",shp->var_tree,0);
+ Namval_t *pp = nv_open("CUR",shp->var_tree,0);
+ memset(&endf,0,sizeof(struct Eof));
+ endf.fd = fn;
+ endf.hdr.disc = &EOF_disc;
+ endf.hdr.nofree = 1;
+ if(mp)
+ nv_stack(mp, &endf.hdr);
+ if(pp)
+ nv_stack(pp, &endf.hdr);
+ if(sp)
+ sfsync(sp);
+ off = sh_strnum(fname, &cp, 0);
+ if(mp)
+ nv_stack(mp, NiL);
+ if(pp)
+ nv_stack(pp, NiL);
+ return(*cp?(Sfoff_t)-1:off);
+}
+
+/*
+ * close a pipe
+ */
+void sh_pclose(register int pv[])
+{
+ if(pv[0]>=2)
+ sh_close(pv[0]);
+ if(pv[1]>=2)
+ sh_close(pv[1]);
+ pv[0] = pv[1] = -1;
+}
+
+static char *io_usename(char *name, int *perm, int fno, int mode)
+{
+ struct stat statb;
+ char *tname, *sp, *ep;
+ int fd;
+ if(mode==0)
+ {
+ if((fd = sh_open(name,O_RDONLY,0)) > 0)
+ {
+ if(fstat(fd,&statb) < 0)
+ return(0);
+ if(!S_ISREG(statb.st_mode))
+ return(0);
+ *perm = statb.st_mode&(RW_ALL|(S_IXUSR|S_IXGRP|S_IXOTH));
+ }
+ else if(fd < 0 && errno!=ENOENT)
+ return(0);
+ }
+ stakseek(1);
+ stakputs(name);
+ stakputc(0);
+ pathcanon(stakptr(1),PATH_PHYSICAL);
+ sp = ep = stakptr(1);
+ if(ep = strrchr(sp,'/'))
+ {
+ memmove(stakptr(0),sp,++ep-sp);
+ stakseek(ep-sp);
+ }
+ else
+ {
+ ep = sp;
+ stakseek(0);
+ }
+ stakputc('.');
+ sfprintf(stkstd,"%<#d_%d{;.tmp",getpid(),fno);
+ tname = stakfreeze(1);
+ switch(mode)
+ {
+ unlink(tname);
+ break;
+ case 1:
+ rename(tname,name);
+ break;
+ default:
+ unlink(tname);
+ break;
+ }
+ return(tname);
+}
+
+/*
+ * I/O redirection
+ * flag = 0 if files are to be restored
+ * flag = 2 if files are to be closed on exec
+ * flag = 3 when called from $( < ...), just open file and return
+ * flag = SH_SHOWME for trace only
+ */
+int sh_redirect(Shell_t *shp,struct ionod *iop, int flag)
+{
+ Sfoff_t off;
+ register char *fname;
+ register int fd, iof;
+ const char *message = e_open;
+ int o_mode; /* mode flag for open */
+ static char io_op[7]; /* used for -x trace info */
+ int trunc=0, clexec=0, fn, traceon;
+ int r, indx = shp->topfd, perm= -1;
+ char *tname=0, *after="", *trace = shp->st.trap[SH_DEBUGTRAP];
+ Namval_t *np=0;
+ int isstring = shp->subshell?(sfset(sfstdout,0,0)&SF_STRING):0;
+
+ if(flag==2)
+ clexec = 1;
+ if(iop)
+ traceon = sh_trace(shp,NIL(char**),0);
+ for(;iop;iop=iop->ionxt)
+ {
+ iof=iop->iofile;
+ fn = (iof&IOUFD);
+ if(fn==1 && shp->subshell && !shp->subshare && (flag==2 || isstring))
+ sh_subfork();
+ if(shp->redir0 && fn==0 && !(iof&IOMOV))
+ shp->redir0 = 2;
+ io_op[0] = '0'+(iof&IOUFD);
+ if(iof&IOPUT)
+ {
+ io_op[1] = '>';
+ o_mode = O_WRONLY|O_CREAT;
+ }
+ else
+ {
+ io_op[1] = '<';
+ o_mode = O_RDONLY|O_NONBLOCK;
+ }
+ io_op[2] = 0;
+ io_op[3] = 0;
+ io_op[4] = 0;
+ fname = iop->ioname;
+ if(!(iof&IORAW))
+ {
+ if(iof&IOLSEEK)
+ {
+ struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
+ memset(ap, 0, ARGVAL);
+ ap->argflag = ARG_MAC;
+ strcpy(ap->argval,iop->ioname);
+ fname=sh_macpat(shp,ap,(iof&IOARITH)?ARG_ARITH:ARG_EXP);
+ }
+ else if(iof&IOPROCSUB)
+ {
+ struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
+ memset(ap, 0, ARGVAL);
+ if(iof&IOPUT)
+ ap->argflag = ARG_RAW;
+ else if(shp->subshell)
+ sh_subtmpfile(shp);
+ ap->argchn.ap = (struct argnod*)fname;
+ ap = sh_argprocsub(shp,ap);
+ fname = ap->argval;
+ }
+ else
+ fname=sh_mactrim(shp,fname,(!sh_isoption(SH_NOGLOB)&&sh_isoption(SH_INTERACTIVE))?2:0);
+ }
+ errno=0;
+ np = 0;
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ if(!(iof&(IODOC|IOLSEEK|IOMOV)))
+ sh_coaddfile(shp,fname);
+ continue;
+ }
+#endif /* SHOPT_COSHELL */
+ if(iop->iovname)
+ {
+ np = nv_open(iop->iovname,shp->var_tree,NV_NOASSIGN|NV_VARNAME);
+ if(nv_isattr(np,NV_RDONLY))
+ errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
+ io_op[0] = '}';
+ if((iof&IOLSEEK) || ((iof&IOMOV) && *fname=='-'))
+ fn = nv_getnum(np);
+ }
+ if(fn>=shp->gd->lim.open_max && !sh_iovalidfd(shp,fn))
+ errormsg(SH_DICT,ERROR_system(1),e_file+4);
+ if(iof&IOLSEEK)
+ {
+ io_op[2] = '#';
+ if(iof&IOARITH)
+ {
+ strcpy(&io_op[3]," ((");
+ after = "))";
+ }
+ else if(iof&IOCOPY)
+ io_op[3] = '#';
+ goto traceit;
+ }
+ if(*fname || (iof&(IODOC|IOSTRG))==(IODOC|IOSTRG))
+ {
+ if(iof&IODOC)
+ {
+ if(traceon)
+ sfputr(sfstderr,io_op,'<');
+ fd = io_heredoc(shp,iop,fname,traceon);
+ if(traceon && (flag==SH_SHOWME))
+ sh_close(fd);
+ fname = 0;
+ }
+ else if(iof&IOMOV)
+ {
+ int dupfd,toclose= -1;
+ io_op[2] = '&';
+ if((fd=fname[0])>='0' && fd<='9')
+ {
+ char *number = fname;
+ dupfd = strtol(fname,&number,10);
+ if(*number=='-')
+ {
+ toclose = dupfd;
+ number++;
+ }
+ if(*number || dupfd > IOUFD)
+ {
+ message = e_file;
+ goto fail;
+ }
+ if(shp->subshell && dupfd==1)
+ {
+ if(sfset(sfstdout,0,0)&SF_STRING)
+ sh_subtmpfile(shp);
+ if(shp->comsub==1)
+ shp->subdup |= 1<<fn;
+ dupfd = sffileno(sfstdout);
+ }
+ else if(shp->sftable[dupfd])
+ sfsync(shp->sftable[dupfd]);
+ if(dupfd!=1 && fn < 10)
+ shp->subdup &= ~(1<<fn);
+ }
+ else if(fd=='-' && fname[1]==0)
+ {
+ fd= -1;
+ goto traceit;
+ }
+ else if(fd=='p' && fname[1]==0)
+ {
+ if(iof&IOPUT)
+ dupfd = shp->coutpipe;
+ else
+ dupfd = shp->cpipe[0];
+ if(flag)
+ toclose = dupfd;
+ }
+ else
+ {
+ message = e_file;
+ goto fail;
+ }
+ if(flag==SH_SHOWME)
+ goto traceit;
+ if((fd=sh_fcntl(dupfd,F_DUPFD,3))<0)
+ goto fail;
+ if(fd>= shp->gd->lim.open_max)
+ sh_iovalidfd(shp,fd);
+ sh_iocheckfd(shp,dupfd);
+ shp->fdstatus[fd] = (shp->fdstatus[dupfd]&~IOCLEX);
+ if(toclose<0 && shp->fdstatus[fd]&IOREAD)
+ shp->fdstatus[fd] |= IODUP;
+ else if(dupfd==shp->cpipe[0])
+ sh_pclose(shp->cpipe);
+ else if(toclose>=0)
+ {
+ if(flag==0)
+ sh_iosave(shp,toclose,indx,(char*)0); /* save file descriptor */
+ sh_close(toclose);
+ }
+ }
+ else if(iof&IORDW)
+ {
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
+ io_op[2] = '>';
+ o_mode = O_RDWR|O_CREAT;
+ if(iof&IOREWRITE)
+ trunc = io_op[2] = ';';
+ goto openit;
+ }
+ else if(!(iof&IOPUT))
+ {
+ if(flag==SH_SHOWME)
+ goto traceit;
+ fd=sh_chkopen(fname);
+ }
+ else if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
+ else
+ {
+ if(iof&IOAPP)
+ {
+ io_op[2] = '>';
+ o_mode |= O_APPEND;
+ }
+ else if((iof&IOREWRITE) && (flag==0 || flag==1 || sh_subsavefd(fn)))
+ {
+ io_op[2] = ';';
+ o_mode |= O_TRUNC;
+ if(tname = io_usename(fname,&perm,fn,0))
+ o_mode |= O_EXCL;
+ }
+ else
+ {
+ o_mode |= O_TRUNC;
+ if(iof&IOCLOB)
+ io_op[2] = '|';
+ else if(sh_isoption(SH_NOCLOBBER))
+ {
+ struct stat sb;
+ if(stat(fname,&sb)>=0)
+ {
+#if SHOPT_FS_3D
+ if(S_ISREG(sb.st_mode)&&
+ (!shp->gd->lim.fs3d || iview(&sb)==0))
+#else
+ if(S_ISREG(sb.st_mode))
+#endif /* SHOPT_FS_3D */
+ {
+ errno = EEXIST;
+ errormsg(SH_DICT,ERROR_system(1),e_exists,fname);
+ }
+ }
+ else
+ o_mode |= O_EXCL;
+ }
+ }
+ openit:
+ if(flag!=SH_SHOWME)
+ {
+ if((fd=sh_open(tname?tname:fname,o_mode,RW_ALL)) <0)
+ errormsg(SH_DICT,ERROR_system(1),((o_mode&O_CREAT)?e_create:e_open),fname);
+ if(perm>0)
+#if _lib_fchmod
+ fchmod(fd,perm);
+#else
+ chmod(tname,perm);
+#endif
+ }
+ }
+ traceit:
+ if(traceon && fname)
+ {
+ if(np)
+ sfprintf(sfstderr,"{%s",nv_name(np));
+ sfprintf(sfstderr,"%s %s%s%c",io_op,fname,after,iop->ionxt?' ':'\n');
+ }
+ if(flag==SH_SHOWME)
+ return(indx);
+ if(trace && fname)
+ {
+ char *argv[7], **av=argv;
+ av[3] = io_op;
+ av[4] = fname;
+ av[5] = 0;
+ av[6] = 0;
+ if(iof&IOARITH)
+ av[5] = after;
+ if(np)
+ {
+ av[0] = "{";
+ av[1] = nv_name(np);
+ av[2] = "}";
+ }
+ else
+ av +=3;
+ sh_debug(shp,trace,(char*)0,(char*)0,av,ARG_NOGLOB);
+ }
+ if(iof&IOLSEEK)
+ {
+ Sfio_t *sp = shp->sftable[fn];
+ r = shp->fdstatus[fn];
+ if(!(r&(IOSEEK|IONOSEEK)))
+ r = sh_iocheckfd(shp,fn);
+ sfsprintf(io_op,sizeof(io_op),"%d\0",fn);
+ if(r==IOCLOSE)
+ {
+ fname = io_op;
+ message = e_file;
+ goto fail;
+ }
+ if(iof&IOARITH)
+ {
+ if(r&IONOSEEK)
+ {
+ fname = io_op;
+ message = e_notseek;
+ goto fail;
+ }
+ message = e_badseek;
+ if((off = file_offset(shp,fn,fname))<0)
+ goto fail;
+ if(sp)
+ {
+ off=sfseek(sp, off, SEEK_SET);
+ sfsync(sp);
+ }
+ else
+ off=lseek(fn, off, SEEK_SET);
+ if(off<0)
+ r = -1;
+ }
+ else
+ {
+ regex_t *rp;
+ extern const char e_notimp[];
+ if(!(r&IOREAD))
+ {
+ message = e_noread;
+ goto fail;
+ }
+ if(!(rp = regcache(fname, REG_SHELL|REG_NOSUB|REG_NEWLINE|REG_AUGMENTED|REG_FIRST|REG_LEFT|REG_RIGHT, &r)))
+ {
+ message = e_badpattern;
+ goto fail;
+ }
+ if(!sp)
+ sp = sh_iostream(shp,fn);
+ r=io_patseek(shp,rp,sp,iof);
+ if(sp && flag==3)
+ {
+ /* close stream but not fn */
+ sfsetfd(sp,-1);
+ sfclose(sp);
+ }
+ }
+ if(r<0)
+ goto fail;
+ if(flag==3)
+ return(fn);
+ continue;
+ }
+ if(!np)
+ {
+ if(flag==0 || tname || (flag==1 && fn==1 && (shp->fdstatus[fn]&IONOSEEK) && shp->outpipepid && shp->outpipepid==getpid()))
+ {
+ if(fd==fn)
+ {
+ if((r=sh_fcntl(fd,F_DUPFD,10)) > 0)
+ {
+ fd = r;
+ sh_close(fn);
+ }
+ }
+ sh_iosave(shp,fn,indx,tname?fname:(trunc?Empty:0));
+ }
+ else if(sh_subsavefd(fn))
+ sh_iosave(shp,fn,indx|IOSUBSHELL,tname?fname:0);
+ }
+ if(fd<0)
+ {
+ if(sh_inuse(shp,fn) || (fn && fn==shp->infd))
+ {
+ if(fn>9 || !(shp->inuse_bits&(1<<fn)))
+ io_preserve(shp,shp->sftable[fn],fn);
+ }
+ sh_close(fn);
+ }
+ if(flag==3)
+ return(fd);
+ if(fd>=0)
+ {
+ if(np)
+ {
+ int32_t v;
+ fn = fd;
+ if(fd<10)
+ {
+ if((fn=fcntl(fd,F_DUPFD,10)) < 0)
+ goto fail;
+ if(fn>=shp->gd->lim.open_max && !sh_iovalidfd(shp,fn))
+ goto fail;
+ shp->fdstatus[fn] = shp->fdstatus[fd];
+ sh_close(fd);
+ fd = fn;
+ }
+ _nv_unset(np,0);
+ nv_onattr(np,NV_INT32);
+ v = fn;
+ nv_putval(np,(char*)&v, NV_INT32);
+ sh_iocheckfd(shp,fd);
+ }
+ else
+ {
+ fd = sh_iorenumber(shp,sh_iomovefd(fd),fn);
+ if(fn>2 && fn<10)
+ shp->inuse_bits |= (1<<fn);
+ }
+ }
+ if(fd >2 && clexec)
+ {
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fd] |= IOCLEX;
+ }
+ }
+ else
+ goto fail;
+ }
+ return(indx);
+fail:
+ errormsg(SH_DICT,ERROR_system(1),message,fname);
+ /* NOTREACHED */
+ return(0);
+}
+/*
+ * Create a tmp file for the here-document
+ */
+static int io_heredoc(Shell_t *shp,register struct ionod *iop, const char *name, int traceon)
+{
+ register Sfio_t *infile = 0, *outfile, *tmp;
+ register int fd;
+ Sfoff_t off;
+ if(!(iop->iofile&IOSTRG) && (!shp->heredocs || iop->iosize==0))
+ return(sh_open(e_devnull,O_RDONLY));
+ /* create an unnamed temporary file */
+ if(!(outfile=sftmp(0)))
+ errormsg(SH_DICT,ERROR_system(1),e_tmpcreate);
+ if(iop->iofile&IOSTRG)
+ {
+ if(traceon)
+ sfprintf(sfstderr,"< %s\n",name);
+ sfputr(outfile,name,'\n');
+ }
+ else
+ {
+ /*
+ * the locking is only needed in case & blocks process
+ * here-docs so this can be eliminted in some cases
+ */
+ struct flock lock;
+ int fno = sffileno(shp->heredocs);
+ if(fno>=0)
+ {
+ memset((void*)&lock,0,sizeof(lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ fcntl(fno,F_SETLKW,&lock);
+ lock.l_type = F_UNLCK;
+ }
+ off = sftell(shp->heredocs);
+ infile = subopen(shp,shp->heredocs,iop->iooffset,iop->iosize);
+ if(traceon)
+ {
+ char *cp = sh_fmtq(iop->iodelim);
+ fd = (*cp=='$' || *cp=='\'')?' ':'\\';
+ sfprintf(sfstderr," %c%s\n",fd,cp);
+ sfdisc(outfile,&tee_disc);
+ }
+ tmp = outfile;
+ if(fno>=0 && !(iop->iofile&IOQUOTE))
+ tmp = sftmp(iop->iosize<IOBSIZE?iop->iosize:0);
+ if(fno>=0 || (iop->iofile&IOQUOTE))
+ {
+ /* This is a quoted here-document, not expansion */
+ sfmove(infile,tmp,SF_UNBOUND,-1);
+ sfclose(infile);
+ if(sffileno(tmp)>0)
+ {
+ sfsetbuf(tmp,malloc(IOBSIZE+1),IOBSIZE);
+ sfset(tmp,SF_MALLOC,1);
+ }
+ sfseek(shp->heredocs,off,SEEK_SET);
+ if(fno>=0)
+ fcntl(fno,F_SETLK,&lock);
+ sfseek(tmp,(off_t)0,SEEK_SET);
+ infile = tmp;
+ }
+ if(!(iop->iofile&IOQUOTE))
+ {
+ char *lastpath = shp->lastpath;
+ sh_machere(shp,infile,outfile,iop->ioname);
+ shp->lastpath = lastpath;
+ if(infile)
+ sfclose(infile);
+ }
+ }
+ /* close stream outfile, but save file descriptor */
+ fd = sffileno(outfile);
+ sfsetfd(outfile,-1);
+ sfclose(outfile);
+ if(traceon && !(iop->iofile&IOSTRG))
+ sfputr(sfstderr,iop->ioname,'\n');
+ lseek(fd,(off_t)0,SEEK_SET);
+ shp->fdstatus[fd] = IOREAD;
+ return(fd);
+}
+
+/*
+ * This write discipline also writes the output on standard error
+ * This is used when tracing here-documents
+ */
+static ssize_t tee_write(Sfio_t *iop,const void *buff,size_t n,Sfdisc_t *unused)
+{
+ NOT_USED(unused);
+ sfwrite(sfstderr,buff,n);
+ return(write(sffileno(iop),buff,n));
+}
+
+/*
+ * copy file <origfd> into a save place
+ * The saved file is set close-on-exec
+ * if <origfd> < 0, then -origfd is saved, but not duped so that it
+ * will be closed with sh_iorestore.
+ */
+void sh_iosave(Shell_t *shp, register int origfd, int oldtop, char *name)
+{
+ register int savefd;
+ int flag = (oldtop&IOSUBSHELL);
+ oldtop &= ~IOSUBSHELL;
+ /* see if already saved, only save once */
+ for(savefd=shp->topfd; --savefd>=oldtop; )
+ {
+ if(filemap[savefd].orig_fd == origfd)
+ return;
+ }
+ /* make sure table is large enough */
+ if(shp->topfd >= filemapsize)
+ {
+ char *cp, *oldptr = (char*)filemap;
+ char *oldend = (char*)&filemap[filemapsize];
+ long moved;
+ filemapsize += 8;
+ if(!(filemap = (struct fdsave*)realloc(filemap,filemapsize*sizeof(struct fdsave))))
+ errormsg(SH_DICT,ERROR_exit(4),e_nospace);
+ if(moved = (char*)filemap - oldptr)
+ {
+ for(savefd=shp->gd->lim.open_max; --savefd>=0; )
+ {
+ cp = (char*)shp->fdptrs[savefd];
+ if(cp >= oldptr && cp < oldend)
+ shp->fdptrs[savefd] = (int*)(cp+moved);
+ }
+ }
+ }
+#if SHOPT_DEVFD
+ if(origfd <0)
+ {
+ savefd = origfd;
+ origfd = -origfd;
+ }
+ else
+#endif /* SHOPT_DEVFD */
+ {
+ if((savefd = sh_fcntl(origfd, F_DUPFD, 10)) < 0 && errno!=EBADF)
+ {
+ shp->toomany=1;
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
+ errormsg(SH_DICT,ERROR_system(1),e_toomany);
+ }
+ }
+ filemap[shp->topfd].tname = name;
+ filemap[shp->topfd].subshell = flag;
+ filemap[shp->topfd].orig_fd = origfd;
+ filemap[shp->topfd++].save_fd = savefd;
+ if(savefd >=0)
+ {
+ register Sfio_t* sp = shp->sftable[origfd];
+ /* make saved file close-on-exec */
+ sh_fcntl(savefd,F_SETFD,FD_CLOEXEC);
+ if(origfd==job.fd)
+ job.fd = savefd;
+ shp->fdstatus[savefd] = shp->fdstatus[origfd];
+ shp->fdptrs[savefd] = &filemap[shp->topfd-1].save_fd;
+ if(!(shp->sftable[savefd]=sp))
+ return;
+ sfsync(sp);
+ if(origfd <=2)
+ {
+ /* copy standard stream to new stream */
+ sp = sfswap(sp,NIL(Sfio_t*));
+ shp->sftable[savefd] = sp;
+ }
+ else
+ shp->sftable[origfd] = 0;
+ }
+}
+
+/*
+ * close all saved file descriptors
+ */
+void sh_iounsave(Shell_t* shp)
+{
+ register int fd, savefd, newfd;
+ for(newfd=fd=0; fd < shp->topfd; fd++)
+ {
+ if((savefd = filemap[fd].save_fd)< 0)
+ filemap[newfd++] = filemap[fd];
+ else
+ {
+ shp->sftable[savefd] = 0;
+ sh_close(savefd);
+ }
+ }
+ shp->topfd = newfd;
+}
+
+/*
+ * restore saved file descriptors from <last> on
+ */
+void sh_iorestore(Shell_t *shp, int last, int jmpval)
+{
+ register int origfd, savefd, fd;
+ int flag = (last&IOSUBSHELL);
+ last &= ~IOSUBSHELL;
+ for (fd = shp->topfd - 1; fd >= last; fd--)
+ {
+ if(!flag && filemap[fd].subshell)
+ continue;
+ if(jmpval==SH_JMPSCRIPT)
+ {
+ if ((savefd = filemap[fd].save_fd) >= 0)
+ {
+ shp->sftable[savefd] = 0;
+ sh_close(savefd);
+ }
+ continue;
+ }
+ origfd = filemap[fd].orig_fd;
+ if(origfd<0)
+ {
+ /* this should never happen */
+ savefd = filemap[fd].save_fd;
+ shp->sftable[savefd] = 0;
+ sh_close(savefd);
+ return;
+ }
+ if(filemap[fd].tname == Empty && shp->exitval==0)
+ ftruncate(origfd,lseek(origfd,0,SEEK_CUR));
+ else if(filemap[fd].tname)
+ io_usename(filemap[fd].tname,(int*)0,origfd,shp->exitval?2:1);
+ sh_close(origfd);
+ if ((savefd = filemap[fd].save_fd) >= 0)
+ {
+ sh_fcntl(savefd, F_DUPFD, origfd);
+ if(savefd==job.fd)
+ job.fd=origfd;
+ shp->fdstatus[origfd] = shp->fdstatus[savefd];
+ /* turn off close-on-exec if flag if necessary */
+ if(shp->fdstatus[origfd]&IOCLEX)
+ fcntl(origfd,F_SETFD,FD_CLOEXEC);
+ if(origfd<=2)
+ {
+ sfswap(shp->sftable[savefd],shp->sftable[origfd]);
+ if(origfd==0)
+ shp->st.ioset = 0;
+ }
+ else
+ shp->sftable[origfd] = shp->sftable[savefd];
+ shp->sftable[savefd] = 0;
+ sh_close(savefd);
+ }
+ else
+ shp->fdstatus[origfd] = IOCLOSE;
+ }
+ if(!flag)
+ {
+ /* keep file descriptors for subshell restore */
+ for (fd = last ; fd < shp->topfd; fd++)
+ {
+ if(filemap[fd].subshell)
+ filemap[last++] = filemap[fd];
+ }
+ }
+ if(last < shp->topfd)
+ shp->topfd = last;
+}
+
+/*
+ * returns access information on open file <fd>
+ * returns -1 for failure, 0 for success
+ * <mode> is the same as for access()
+ */
+int sh_ioaccess(int fd,register int mode)
+{
+ Shell_t *shp = sh_getinterp();
+ register int flags;
+ if(mode==X_OK)
+ return(-1);
+ if((flags=sh_iocheckfd(shp,fd))!=IOCLOSE)
+ {
+ if(mode==F_OK)
+ return(0);
+ if(mode==R_OK && (flags&IOREAD))
+ return(0);
+ if(mode==W_OK && (flags&IOWRITE))
+ return(0);
+ }
+ return(-1);
+}
+
+/*
+ * Handle interrupts for slow streams
+ */
+static int slowexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle)
+{
+ Shell_t *shp = ((struct Iodisc*)handle)->sh;
+ register int n,fno;
+ NOT_USED(handle);
+ if(type==SF_DPOP || type==SF_FINAL)
+ free((void*)handle);
+ if(type==SF_WRITE && errno==EPIPE)
+ {
+ sfpurge(iop);
+ return(-1);
+ }
+ if(type!=SF_READ)
+ return(0);
+ if((shp->trapnote&(SH_SIGSET|SH_SIGTRAP)) && errno!=EIO && errno!=ENXIO)
+ errno = EINTR;
+ fno = sffileno(iop);
+ if((n=sfvalue(iop))<=0)
+ {
+#ifndef FNDELAY
+# ifdef O_NDELAY
+ if(errno==0 && (n=fcntl(fno,F_GETFL,0))&O_NDELAY)
+ {
+ n &= ~O_NDELAY;
+ fcntl(fno, F_SETFL, n);
+ return(1);
+ }
+# endif /* O_NDELAY */
+#endif /* !FNDELAY */
+#ifdef O_NONBLOCK
+ if(errno==EAGAIN)
+ {
+ n = fcntl(fno,F_GETFL,0);
+ n &= ~O_NONBLOCK;
+ fcntl(fno, F_SETFL, n);
+ return(1);
+ }
+#endif /* O_NONBLOCK */
+ if(errno!=EINTR)
+ return(0);
+ else if(shp->bltinfun && (shp->trapnote&SH_SIGTRAP) && shp->lastsig)
+ return(-1);
+ n=1;
+ sh_onstate(SH_TTYWAIT);
+ }
+ else
+ n = 0;
+ if(shp->bltinfun && shp->bltindata.sigset)
+ return(-1);
+ errno = 0;
+ if(shp->trapnote&SH_SIGSET)
+ {
+ if(isatty(fno))
+ sfputc(sfstderr,'\n');
+ sh_exit(SH_EXITSIG);
+ }
+ if(shp->trapnote&SH_SIGTRAP)
+ sh_chktrap(shp);
+ return(n);
+}
+
+/*
+ * called when slowread times out
+ */
+static void time_grace(void *handle)
+{
+ Shell_t *shp = (Shell_t*)handle;
+ timeout = 0;
+ if(sh_isstate(SH_GRACE))
+ {
+ sh_offstate(SH_GRACE);
+ if(!sh_isstate(SH_INTERACTIVE))
+ return;
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPEXIT;
+ errormsg(SH_DICT,2,e_timeout);
+ shp->trapnote |= SH_SIGSET;
+ return;
+ }
+ errormsg(SH_DICT,0,e_timewarn);
+ sh_onstate(SH_GRACE);
+ sigrelease(SIGALRM);
+ shp->trapnote |= SH_SIGTRAP;
+}
+
+static ssize_t piperead(Sfio_t *iop,void *buff,register size_t size,Sfdisc_t *handle)
+{
+ Shell_t *shp = ((struct Iodisc*)handle)->sh;
+ int fd = sffileno(iop);
+ if(job.waitsafe && job.savesig)
+ {
+ job_lock();
+ job_unlock();
+ }
+ if(shp->trapnote)
+ {
+ errno = EINTR;
+ return(-1);
+ }
+ if(sh_isstate(SH_INTERACTIVE) && sffileno(iop)==0 && io_prompt(shp,iop,shp->nextprompt)<0 && errno==EIO)
+ return(0);
+ sh_onstate(SH_TTYWAIT);
+ if(!(shp->fdstatus[fd]&IOCLEX) && (sfset(iop,0,0)&SF_SHARE))
+ size = ed_read(shgd->ed_context, fd, (char*)buff, size,0);
+ else
+ size = sfrd(iop,buff,size,handle);
+ sh_offstate(SH_TTYWAIT);
+ return(size);
+}
+/*
+ * This is the read discipline that is applied to slow devices
+ * This routine takes care of prompting for input
+ */
+static ssize_t slowread(Sfio_t *iop,void *buff,register size_t size,Sfdisc_t *handle)
+{
+ Shell_t *shp = ((struct Iodisc*)handle)->sh;
+ int (*readf)(void*, int, char*, int, int);
+ int reedit=0, rsize;
+#if SHOPT_HISTEXPAND
+ char *xp=0;
+#endif
+# if SHOPT_ESH
+ if(sh_isoption(SH_EMACS) || sh_isoption(SH_GMACS))
+ readf = ed_emacsread;
+ else
+# endif /* SHOPT_ESH */
+# if SHOPT_VSH
+# if SHOPT_RAWONLY
+ if(sh_isoption(SH_VI) || ((SHOPT_RAWONLY-0) && mbwide()))
+# else
+ if(sh_isoption(SH_VI))
+# endif
+ readf = ed_viread;
+ else
+# endif /* SHOPT_VSH */
+ readf = ed_read;
+ if(shp->trapnote)
+ {
+ errno = EINTR;
+ return(-1);
+ }
+ while(1)
+ {
+ if(io_prompt(shp,iop,shp->nextprompt)<0 && errno==EIO)
+ return(0);
+ if(shp->timeout)
+ timeout = (void*)sh_timeradd(sh_isstate(SH_GRACE)?1000L*TGRACE:1000L*shp->timeout,0,time_grace,shp);
+ rsize = (*readf)(shgd->ed_context, sffileno(iop), (char*)buff, size, reedit);
+ if(timeout)
+ timerdel(timeout);
+ timeout=0;
+#if SHOPT_HISTEXPAND
+ if(rsize && *(char*)buff != '\n' && shp->nextprompt==1 && sh_isoption(SH_HISTEXPAND))
+ {
+ int r;
+ ((char*)buff)[rsize] = '\0';
+ if(xp)
+ {
+ free(xp);
+ xp = 0;
+ }
+ r = hist_expand(buff, &xp);
+ if((r & (HIST_EVENT|HIST_PRINT)) && !(r & HIST_ERROR) && xp)
+ {
+ strlcpy(buff, xp, size);
+ rsize = strlen(buff);
+ if(!sh_isoption(SH_HISTVERIFY) || readf==ed_read)
+ {
+ sfputr(sfstderr, xp, -1);
+ break;
+ }
+ reedit = rsize - 1;
+ continue;
+ }
+ if((r & HIST_ERROR) && sh_isoption(SH_HISTREEDIT))
+ {
+ reedit = rsize - 1;
+ continue;
+ }
+ if(r & (HIST_ERROR|HIST_PRINT))
+ {
+ *(char*)buff = '\n';
+ rsize = 1;
+ }
+ }
+#endif
+ break;
+ }
+ return(rsize);
+}
+
+/*
+ * check and return the attributes for a file descriptor
+ */
+
+int sh_iocheckfd(Shell_t *shp, register int fd)
+{
+ register int flags, n;
+ if((n=shp->fdstatus[fd])&IOCLOSE)
+ return(n);
+ if(!(n&(IOREAD|IOWRITE)))
+ {
+#ifdef F_GETFL
+ if((flags=fcntl(fd,F_GETFL,0)) < 0)
+ return(shp->fdstatus[fd]=IOCLOSE);
+ if((flags&O_ACCMODE)!=O_WRONLY)
+ n |= IOREAD;
+ if((flags&O_ACCMODE)!=O_RDONLY)
+ n |= IOWRITE;
+#else
+ struct stat statb;
+ if((flags = fstat(fd,&statb))< 0)
+ return(shp->fdstatus[fd]=IOCLOSE);
+ n |= (IOREAD|IOWRITE);
+ if(read(fd,"",0) < 0)
+ n &= ~IOREAD;
+#endif /* F_GETFL */
+ }
+ if(!(n&(IOSEEK|IONOSEEK)))
+ {
+ struct stat statb;
+ /* /dev/null check is a workaround for select bug */
+ static ino_t null_ino;
+ static dev_t null_dev;
+ if(null_ino==0 && stat(e_devnull,&statb) >=0)
+ {
+ null_ino = statb.st_ino;
+ null_dev = statb.st_dev;
+ }
+ if(tty_check(fd))
+ n |= IOTTY;
+ if(lseek(fd,NIL(off_t),SEEK_CUR)<0)
+ {
+ n |= IONOSEEK;
+#ifdef S_ISSOCK
+ if((fstat(fd,&statb)>=0) && S_ISSOCK(statb.st_mode))
+ {
+ n |= IOREAD|IOWRITE;
+# if _socketpair_shutdown_mode
+ if(!(statb.st_mode&S_IRUSR))
+ n &= ~IOREAD;
+ else if(!(statb.st_mode&S_IWUSR))
+ n &= ~IOWRITE;
+# endif
+ }
+#endif /* S_ISSOCK */
+ }
+ else if((fstat(fd,&statb)>=0) && (
+ S_ISFIFO(statb.st_mode) ||
+#ifdef S_ISSOCK
+ S_ISSOCK(statb.st_mode) ||
+#endif /* S_ISSOCK */
+ /* The following is for sockets on the sgi */
+ (statb.st_ino==0 && (statb.st_mode & ~(S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH|S_IXUSR|S_IXGRP|S_IXOTH|S_ISUID|S_ISGID))==0) ||
+ (S_ISCHR(statb.st_mode) && (statb.st_ino!=null_ino || statb.st_dev!=null_dev))
+ ))
+ n |= IONOSEEK;
+ else
+ n |= IOSEEK;
+ }
+ if(fd==0)
+ n &= ~IOWRITE;
+ else if(fd==1)
+ n &= ~IOREAD;
+ shp->fdstatus[fd] = n;
+ return(n);
+}
+
+/*
+ * Display prompt PS<flag> on standard error
+ */
+
+static int io_prompt(Shell_t *shp,Sfio_t *iop,register int flag)
+{
+ register char *cp;
+ char buff[1];
+ char *endprompt;
+ static short cmdno;
+ int sfflags;
+ if(flag<3 && !sh_isstate(SH_INTERACTIVE))
+ flag = 0;
+ if(flag==2 && sfpkrd(sffileno(iop),buff,1,'\n',0,1) >= 0)
+ flag = 0;
+ if(flag==0)
+ return(sfsync(sfstderr));
+ sfflags = sfset(sfstderr,SF_SHARE|SF_PUBLIC|SF_READ,0);
+ if(!(shp->prompt=(char*)sfreserve(sfstderr,0,0)))
+ shp->prompt = "";
+ switch(flag)
+ {
+ case 1:
+ {
+ register int c;
+#if defined(TIOCLBIC) && defined(LFLUSHO)
+ if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
+ {
+ /*
+ * re-enable output in case the user has
+ * disabled it. Not needed with edit mode
+ */
+ int mode = LFLUSHO;
+ ioctl(sffileno(sfstderr),TIOCLBIC,&mode);
+ }
+#endif /* TIOCLBIC */
+ cp = sh_mactry(shp,nv_getval(sh_scoped(shp,PS1NOD)));
+ for(;c= *cp;cp++)
+ {
+ if(c==HIST_CHAR)
+ {
+ /* look at next character */
+ c = *++cp;
+ /* print out line number if not !! */
+ if(c!= HIST_CHAR)
+ {
+ sfprintf(sfstderr,"%d", shp->gd->hist_ptr?(int)shp->gd->hist_ptr->histind:++cmdno);
+ }
+ if(c==0)
+ goto done;
+ }
+ sfputc(sfstderr,c);
+ }
+ goto done;
+ }
+ case 2:
+ cp = nv_getval(sh_scoped(shp,PS2NOD));
+ break;
+ case 3:
+ cp = nv_getval(sh_scoped(shp,PS3NOD));
+ break;
+ default:
+ goto done;
+ }
+ if(cp)
+ sfputr(sfstderr,cp,-1);
+done:
+ if(*shp->prompt && (endprompt=(char*)sfreserve(sfstderr,0,0)))
+ *endprompt = 0;
+ sfset(sfstderr,sfflags&SF_READ|SF_SHARE|SF_PUBLIC,1);
+ return(sfsync(sfstderr));
+}
+
+/*
+ * This discipline is inserted on write pipes to prevent SIGPIPE
+ * from causing an infinite loop
+ */
+static int pipeexcept(Sfio_t* iop, int mode, void *data, Sfdisc_t* handle)
+{
+ if(mode==SF_DPOP || mode==SF_FINAL)
+ free((void*)handle);
+ else if(mode==SF_WRITE && errno==EPIPE)
+ {
+ sfpurge(iop);
+ return(-1);
+ }
+ return(0);
+}
+
+/*
+ * keep track of each stream that is opened and closed
+ */
+static void sftrack(Sfio_t* sp, int flag, void* data)
+{
+ Shell_t *shp = sh_getinterp();
+ register int fd = sffileno(sp);
+ register struct checkpt *pp;
+ register int mode;
+ int newfd = integralof(data);
+ if(flag==SF_SETFD || flag==SF_CLOSING)
+ {
+ if(newfd<0)
+ flag = SF_CLOSING;
+ if(fdnotify)
+ (*fdnotify)(sffileno(sp),flag==SF_CLOSING?-1:newfd);
+ }
+#ifdef DEBUG
+ if(flag==SF_READ || flag==SF_WRITE)
+ {
+ char *z = fmtbase((long)getpid(),0,0);
+ write(ERRIO,z,strlen(z));
+ write(ERRIO,": ",2);
+ write(ERRIO,"attempt to ",11);
+ if(flag==SF_READ)
+ write(ERRIO,"read from",9);
+ else
+ write(ERRIO,"write to",8);
+ write(ERRIO," locked stream\n",15);
+ return;
+ }
+#endif
+ if(fd<0 || fd==PSEUDOFD || (fd>=shp->gd->lim.open_max && !sh_iovalidfd(shp,fd)))
+ return;
+ if(sh_isstate(SH_NOTRACK))
+ return;
+ mode = sfset(sp,0,0);
+ if(sp==shp->heredocs && fd < 10 && flag==SF_NEW)
+ {
+ fd = sfsetfd(sp,10);
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ }
+ if(fd < 3)
+ return;
+ if(flag==SF_NEW)
+ {
+ if(!shp->sftable[fd] && shp->fdstatus[fd]==IOCLOSE)
+ {
+ shp->sftable[fd] = sp;
+ flag = (mode&SF_WRITE)?IOWRITE:0;
+ if(mode&SF_READ)
+ flag |= IOREAD;
+ shp->fdstatus[fd] = flag;
+ sh_iostream(shp,fd);
+ }
+ if((pp=(struct checkpt*)shp->jmplist) && pp->mode==SH_JMPCMD)
+ {
+ struct openlist *item;
+ /*
+ * record open file descriptors so they can
+ * be closed in case a longjmp prevents
+ * built-ins from cleanup
+ */
+ item = new_of(struct openlist, 0);
+ item->strm = sp;
+ item->next = pp->olist;
+ pp->olist = item;
+ }
+ if(fdnotify)
+ (*fdnotify)(-1,sffileno(sp));
+ }
+ else if(flag==SF_CLOSING || (flag==SF_SETFD && newfd<=2))
+ {
+ shp->sftable[fd] = 0;
+ shp->fdstatus[fd]=IOCLOSE;
+ if(pp=(struct checkpt*)shp->jmplist)
+ {
+ struct openlist *item;
+ for(item=pp->olist; item; item=item->next)
+ {
+ if(item->strm == sp)
+ {
+ item->strm = 0;
+ break;
+ }
+ }
+ }
+ }
+}
+
+struct eval
+{
+ Sfdisc_t disc;
+ char **argv;
+ short slen;
+ char addspace;
+};
+
+/*
+ * Create a stream consisting of a space separated argv[] list
+ */
+
+Sfio_t *sh_sfeval(register char *argv[])
+{
+ register Sfio_t *iop;
+ register char *cp;
+ if(argv[1])
+ cp = "";
+ else
+ cp = argv[0];
+ iop = sfopen(NIL(Sfio_t*),(char*)cp,"s");
+ if(argv[1])
+ {
+ register struct eval *ep;
+ if(!(ep = new_of(struct eval,0)))
+ return(NIL(Sfio_t*));
+ ep->disc = eval_disc;
+ ep->argv = argv;
+ ep->slen = -1;
+ ep->addspace = 0;
+ sfdisc(iop,&ep->disc);
+ }
+ return(iop);
+}
+
+/*
+ * This code gets called whenever an end of string is found with eval
+ */
+
+static int eval_exceptf(Sfio_t *iop,int type, void *data, Sfdisc_t *handle)
+{
+ register struct eval *ep = (struct eval*)handle;
+ register char *cp;
+ register int len;
+
+ /* no more to do */
+ if(type!=SF_READ || !(cp = ep->argv[0]))
+ {
+ if(type==SF_CLOSING)
+ sfdisc(iop,SF_POPDISC);
+ else if(ep && (type==SF_DPOP || type==SF_FINAL))
+ free((void*)ep);
+ return(0);
+ }
+
+ if(!ep->addspace)
+ {
+ /* get the length of this string */
+ ep->slen = len = strlen(cp);
+ /* move to next string */
+ ep->argv++;
+ }
+ else /* insert space between arguments */
+ {
+ len = 1;
+ cp = " ";
+ }
+ /* insert the new string */
+ sfsetbuf(iop,cp,len);
+ ep->addspace = !ep->addspace;
+ return(1);
+}
+
+/*
+ * This routine returns a stream pointer to a segment of length <size> from
+ * the stream <sp> starting at offset <offset>
+ * The stream can be read with the normal stream operations
+ */
+
+static Sfio_t *subopen(Shell_t *shp,Sfio_t* sp, off_t offset, long size)
+{
+ register struct subfile *disp;
+ if(sfseek(sp,offset,SEEK_SET) <0)
+ return(NIL(Sfio_t*));
+ if(!(disp = (struct subfile*)malloc(sizeof(struct subfile)+IOBSIZE+1)))
+ return(NIL(Sfio_t*));
+ disp->disc = sub_disc;
+ disp->oldsp = sp;
+ disp->offset = offset;
+ disp->size = disp->left = size;
+ sp = sfnew(NIL(Sfio_t*),(char*)(disp+1),IOBSIZE,PSEUDOFD,SF_READ);
+ sfdisc(sp,&disp->disc);
+ return(sp);
+}
+
+/*
+ * read function for subfile discipline
+ */
+static ssize_t subread(Sfio_t* sp,void* buff,register size_t size,Sfdisc_t* handle)
+{
+ register struct subfile *disp = (struct subfile*)handle;
+ ssize_t n;
+ NOT_USED(sp);
+ sfseek(disp->oldsp,disp->offset,SEEK_SET);
+ if(disp->left == 0)
+ return(0);
+ if(size > disp->left)
+ size = disp->left;
+ disp->left -= size;
+ n = sfread(disp->oldsp,buff,size);
+ if(size>0)
+ disp->offset += size;
+ return(n);
+}
+
+/*
+ * exception handler for subfile discipline
+ */
+static int subexcept(Sfio_t* sp,register int mode, void *data, Sfdisc_t* handle)
+{
+ register struct subfile *disp = (struct subfile*)handle;
+ if(mode==SF_CLOSING)
+ {
+ sfdisc(sp,SF_POPDISC);
+ return(0);
+ }
+ else if(disp && (mode==SF_DPOP || mode==SF_FINAL))
+ {
+ free((void*)disp);
+ return(0);
+ }
+#ifdef SF_ATEXIT
+ else if (mode==SF_ATEXIT)
+ {
+ sfdisc(sp, SF_POPDISC);
+ return(0);
+ }
+#endif
+ else if(mode==SF_READ)
+ return(0);
+ return(-1);
+}
+
+#define NROW 15 /* number of rows before going to multi-columns */
+#define LBLSIZ 3 /* size of label field and interfield spacing */
+/*
+ * print a list of arguments in columns
+ */
+void sh_menu(Sfio_t *outfile,int argn,char *argv[])
+{
+ Shell_t *shp = sh_getinterp();
+ register int i,j;
+ register char **arg;
+ int nrow, ncol=1, ndigits=1;
+ int fldsize, wsize = ed_window();
+ char *cp = nv_getval(sh_scoped(shp,LINES));
+ nrow = (cp?1+2*((int)strtol(cp, (char**)0, 10)/3):NROW);
+ for(i=argn;i >= 10;i /= 10)
+ ndigits++;
+ if(argn < nrow)
+ {
+ nrow = argn;
+ goto skip;
+ }
+ i = 0;
+ for(arg=argv; *arg;arg++)
+ {
+ if((j=strlen(*arg)) > i)
+ i = j;
+ }
+ i += (ndigits+LBLSIZ);
+ if(i < wsize)
+ ncol = wsize/i;
+ if(argn > nrow*ncol)
+ {
+ nrow = 1 + (argn-1)/ncol;
+ }
+ else
+ {
+ ncol = 1 + (argn-1)/nrow;
+ nrow = 1 + (argn-1)/ncol;
+ }
+skip:
+ fldsize = (wsize/ncol)-(ndigits+LBLSIZ);
+ for(i=0;i<nrow;i++)
+ {
+ if(shp->trapnote&SH_SIGSET)
+ return;
+ j = i;
+ while(1)
+ {
+ arg = argv+j;
+ sfprintf(outfile,"%*d) %s",ndigits,j+1,*arg);
+ j += nrow;
+ if(j >= argn)
+ break;
+ sfnputc(outfile,' ',fldsize-strlen(*arg));
+ }
+ sfputc(outfile,'\n');
+ }
+}
+
+#undef read
+/*
+ * shell version of read() for user added builtins
+ */
+ssize_t sh_read(register int fd, void* buff, size_t n)
+{
+ Shell_t *shp = sh_getinterp();
+ register Sfio_t *sp;
+ if(sp=shp->sftable[fd])
+ return(sfread(sp,buff,n));
+ else
+ return(read(fd,buff,n));
+}
+
+#undef write
+/*
+ * shell version of write() for user added builtins
+ */
+ssize_t sh_write(register int fd, const void* buff, size_t n)
+{
+ Shell_t *shp = sh_getinterp();
+ register Sfio_t *sp;
+ if(sp=shp->sftable[fd])
+ return(sfwrite(sp,buff,n));
+ else
+ return(write(fd,buff,n));
+}
+
+#undef lseek
+/*
+ * shell version of lseek() for user added builtins
+ */
+off_t sh_seek(register int fd, off_t offset, int whence)
+{
+ Shell_t *shp = sh_getinterp();
+ register Sfio_t *sp;
+ if((sp=shp->sftable[fd]) && (sfset(sp,0,0)&(SF_READ|SF_WRITE)))
+ return(sfseek(sp,offset,whence));
+ else
+ return(lseek(fd,offset,whence));
+}
+
+#undef dup
+int sh_dup(register int old)
+{
+ Shell_t *shp = sh_getinterp();
+ register int fd = dup(old);
+ if(fd>=0)
+ {
+ if(shp->fdstatus[old] == IOCLOSE)
+ shp->fdstatus[old] = 0;
+ shp->fdstatus[fd] = (shp->fdstatus[old]&~IOCLEX);
+ if(fdnotify)
+ (*fdnotify)(old,fd);
+ }
+ return(fd);
+}
+
+#undef fcntl
+int sh_fcntl(register int fd, int op, ...)
+{
+ Shell_t *shp = sh_getinterp();
+ int newfd, arg;
+ va_list ap;
+ va_start(ap, op);
+ arg = va_arg(ap, int) ;
+ va_end(ap);
+ newfd = fcntl(fd,op,arg);
+ if(newfd>=0) switch(op)
+ {
+ case F_DUPFD:
+ if(shp->fdstatus[fd] == IOCLOSE)
+ shp->fdstatus[fd] = 0;
+ if(newfd>=shp->gd->lim.open_max)
+ sh_iovalidfd(shp,newfd);
+ shp->fdstatus[newfd] = (shp->fdstatus[fd]&~IOCLEX);
+ if(fdnotify)
+ (*fdnotify)(fd,newfd);
+ break;
+ case F_SETFD:
+ if(shp->fdstatus[fd] == IOCLOSE)
+ shp->fdstatus[fd] = 0;
+ if(arg&FD_CLOEXEC)
+ shp->fdstatus[fd] |= IOCLEX;
+ else
+ shp->fdstatus[fd] &= ~IOCLEX;
+ }
+ return(newfd);
+}
+
+#undef umask
+mode_t sh_umask(mode_t m)
+{
+ Shell_t *shp = sh_getinterp();
+ shp->mask = m;
+ return(umask(m));
+}
+
+/*
+ * give file descriptor <fd> and <mode>, return an iostream pointer
+ * <mode> must be SF_READ or SF_WRITE
+ * <fd> must be a non-negative number ofr SH_IOCOPROCESS or SH_IOHISTFILE.
+ * returns NULL on failure and may set errno.
+ */
+
+Sfio_t *sh_iogetiop(int fd, int mode)
+{
+ Shell_t *shp = sh_getinterp();
+ int n;
+ Sfio_t *iop=0;
+ if(mode!=SF_READ && mode!=SF_WRITE)
+ {
+ errno = EINVAL;
+ return(iop);
+ }
+ switch(fd)
+ {
+ case SH_IOHISTFILE:
+ if(!sh_histinit((void*)shp))
+ return(iop);
+ fd = sffileno(shp->gd->hist_ptr->histfp);
+ break;
+ case SH_IOCOPROCESS:
+ if(mode==SF_WRITE)
+ fd = shp->coutpipe;
+ else
+ fd = shp->cpipe[0];
+ break;
+ default:
+ if(fd<0 || !sh_iovalidfd(shp,fd))
+ fd = -1;
+ }
+ if(fd<0)
+ {
+ errno = EBADF;
+ return(iop);
+ }
+ if(!(n=shp->fdstatus[fd]))
+ n = sh_iocheckfd(shp,fd);
+ if(mode==SF_WRITE && !(n&IOWRITE))
+ return(iop);
+ if(mode==SF_READ && !(n&IOREAD))
+ return(iop);
+ if(!(iop = shp->sftable[fd]))
+ iop=sh_iostream(shp,fd);
+ return(iop);
+}
+
+typedef int (*Notify_f)(int,int);
+
+Notify_f sh_fdnotify(Notify_f notify)
+{
+ Notify_f old;
+ old = fdnotify;
+ fdnotify = notify;
+ return(old);
+}
+
+Sfio_t *sh_fd2sfio(int fd)
+{
+ Shell_t *shp = sh_getinterp();
+ register int status;
+ Sfio_t *sp = shp->sftable[fd];
+ if(!sp && (status = sh_iocheckfd(shp,fd))!=IOCLOSE)
+ {
+ register int flags=0;
+ if(status&IOREAD)
+ flags |= SF_READ;
+ if(status&IOWRITE)
+ flags |= SF_WRITE;
+ sp = sfnew(NULL, NULL, -1, fd,flags);
+ shp->sftable[fd] = sp;
+ }
+ return(sp);
+}
+
+Sfio_t *sh_pathopen(const char *cp)
+{
+ Shell_t *shp = sh_getinterp();
+ int n;
+#ifdef PATH_BFPATH
+ if((n=path_open(shp,cp,path_get(shp,cp))) < 0)
+ n = path_open(shp,cp,(Pathcomp_t*)0);
+#else
+ if((n=path_open(shp,cp,path_get(cp))) < 0)
+ n = path_open(shp,cp,"");
+#endif
+ if(n < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_open,cp);
+ return(sh_iostream(shp,n));
+}
+
+int sh_isdevfd(register const char *fd)
+{
+ if(!fd || memcmp(fd,"/dev/fd/",8) || fd[8]==0)
+ return(0);
+ for ( fd=&fd[8] ; *fd != '\0' ; fd++ )
+ {
+ if (*fd < '0' || *fd > '9')
+ return(0);
+ }
+ return(1);
+}
diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c
new file mode 100644
index 0000000..5dca257
--- /dev/null
+++ b/src/cmd/ksh93/sh/jobs.c
@@ -0,0 +1,2055 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Job control for UNIX Shell
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ * Written October, 1982
+ * Rewritten April, 1988
+ * Revised January, 1992
+ */
+
+#include "defs.h"
+#include <wait.h>
+#include "io.h"
+#include "jobs.h"
+#include "history.h"
+
+#if !defined(WCONTINUED) || !defined(WIFCONTINUED)
+# undef WCONTINUED
+# define WCONTINUED 0
+# undef WIFCONTINUED
+# define WIFCONTINUED(wstat) (0)
+#endif
+
+#define NJOB_SAVELIST 4
+
+/*
+ * temporary hack to get W* macros to work
+ */
+#undef wait
+#define wait ______wait
+/*
+ * This struct saves a link list of processes that have non-zero exit
+ * status, have had $! saved, but haven't been waited for
+ */
+struct jobsave
+{
+ struct jobsave *next;
+ pid_t pid;
+ unsigned short exitval;
+};
+
+static struct jobsave *job_savelist;
+static int njob_savelist;
+static struct process *pwfg;
+static int jobfork;
+
+pid_t pid_fromstring(char *str)
+{
+ pid_t pid;
+ char *last;
+ errno = 0;
+ if(sizeof(pid)==sizeof(Sflong_t))
+ pid = (pid_t)strtoll(str, &last, 10);
+ else
+ pid = (pid_t)strtol(str, &last, 10);
+ if(errno==ERANGE || *last)
+ errormsg(SH_DICT,ERROR_exit(1),"%s: invalid process id",str);
+ return(pid);
+}
+
+static void init_savelist(void)
+{
+ register struct jobsave *jp;
+ while(njob_savelist < NJOB_SAVELIST)
+ {
+ jp = newof(0,struct jobsave,1,0);
+ jp->next = job_savelist;
+ job_savelist = jp;
+ njob_savelist++;
+ }
+}
+
+struct back_save
+{
+ int count;
+ struct jobsave *list;
+ struct back_save *prev;
+};
+
+#define BYTE(n) (((n)+CHAR_BIT-1)/CHAR_BIT)
+#define MAXMSG 25
+#define SH_STOPSIG (SH_EXITSIG<<1)
+
+#ifdef VSUSP
+# ifndef CNSUSP
+# ifdef _POSIX_VDISABLE
+# define CNSUSP _POSIX_VDISABLE
+# else
+# define CNSUSP 0
+# endif /* _POSIX_VDISABLE */
+# endif /* CNSUSP */
+# ifndef CSWTCH
+# ifdef CSUSP
+# define CSWTCH CSUSP
+# else
+# define CSWTCH ('z'&037)
+# endif /* CSUSP */
+# endif /* CSWTCH */
+#endif /* VSUSP */
+
+/* Process states */
+#define P_EXITSAVE 01
+#define P_STOPPED 02
+#define P_NOTIFY 04
+#define P_SIGNALLED 010
+#define P_STTY 020
+#define P_DONE 040
+#define P_COREDUMP 0100
+#define P_DISOWN 0200
+#define P_FG 0400
+#ifdef SHOPT_BGX
+#define P_BG 01000
+#endif /* SHOPT_BGX */
+
+static int job_chksave(pid_t);
+static struct process *job_bypid(pid_t);
+static struct process *job_byjid(int);
+static char *job_sigmsg(int);
+static int job_alloc(void);
+static void job_free(int);
+static struct process *job_unpost(struct process*,int);
+static void job_unlink(struct process*);
+static void job_prmsg(struct process*);
+static struct process *freelist;
+static char beenhere;
+static char possible;
+static struct process dummy;
+static char by_number;
+static Sfio_t *outfile;
+static pid_t lastpid;
+static struct back_save bck;
+
+#ifdef JOBS
+ static void job_set(struct process*);
+ static void job_reset(struct process*);
+ static void job_waitsafe(int);
+ static struct process *job_byname(char*);
+ static struct process *job_bystring(char*);
+ static struct termios my_stty; /* terminal state for shell */
+ static char *job_string;
+#else
+ extern const char e_coredump[];
+#endif /* JOBS */
+
+#ifdef SIGTSTP
+ static void job_unstop(struct process*);
+ static void job_fgrp(struct process*, int);
+# ifndef _lib_tcgetpgrp
+# ifdef TIOCGPGRP
+ static int _i_;
+# define tcgetpgrp(a) (ioctl(a, TIOCGPGRP, &_i_)>=0?_i_:-1)
+# endif /* TIOCGPGRP */
+ int tcsetpgrp(int fd,pid_t pgrp)
+ {
+ int pgid = pgrp;
+# ifdef TIOCGPGRP
+ return(ioctl(fd, TIOCSPGRP, &pgid));
+# else
+ return(-1);
+# endif /* TIOCGPGRP */
+ }
+# endif /* _lib_tcgetpgrp */
+#else
+# define job_unstop(pw)
+# undef CNSUSP
+#endif /* SIGTSTP */
+
+#ifndef OTTYDISC
+# undef NTTYDISC
+#endif /* OTTYDISC */
+
+#ifdef JOBS
+
+typedef int (*Waitevent_f)(int,long,int);
+
+#ifdef SHOPT_BGX
+void job_chldtrap(Shell_t *shp, const char *trap, int unpost)
+{
+ register struct process *pw,*pwnext;
+ pid_t bckpid;
+ int oldexit,trapnote;
+ job_lock();
+ shp->sigflag[SIGCHLD] &= ~SH_SIGTRAP;
+ trapnote = shp->trapnote;
+ shp->trapnote = 0;
+ for(pw=job.pwlist;pw;pw=pwnext)
+ {
+ pwnext = pw->p_nxtjob;
+ if((pw->p_flag&(P_BG|P_DONE)) != (P_BG|P_DONE))
+ continue;
+ pw->p_flag &= ~P_BG;
+ bckpid = shp->bckpid;
+ oldexit = shp->savexit;
+ shp->bckpid = pw->p_pid;
+ shp->savexit = pw->p_exit;
+ if(pw->p_flag&P_SIGNALLED)
+ shp->savexit |= SH_EXITSIG;
+ sh_trap(trap,0);
+ if(pw->p_pid==bckpid && unpost)
+ job_unpost(pw,0);
+ shp->savexit = oldexit;
+ shp->bckpid = bckpid;
+ }
+ shp->trapnote = trapnote;
+ job_unlock();
+}
+#endif /* SHOPT_BGX */
+
+/*
+ * return next on link list of jobsave free list
+ */
+static struct jobsave *jobsave_create(pid_t pid)
+{
+ register struct jobsave *jp = job_savelist;
+ job_chksave(pid);
+ if(++bck.count > shgd->lim.child_max)
+ job_chksave(0);
+ if(jp)
+ {
+ njob_savelist--;
+ job_savelist = jp->next;
+ }
+ else
+ jp = newof(0,struct jobsave,1,0);
+ if(jp)
+ {
+ jp->pid = pid;
+ jp->next = bck.list;
+ bck.list = jp;
+ jp->exitval = 0;
+ }
+ return(jp);
+}
+
+#if SHOPT_COSHELL
+ pid_t sh_copid(struct cosh *csp)
+ {
+ return(COPID_BIT|(csp->id<<16)|csp->cojob->id);
+ }
+
+
+ char *sh_pid2str(Shell_t *shp,pid_t pid)
+ {
+ struct cosh *csp=0;
+ if(pid&COPID_BIT)
+ {
+ int id = (pid>>16) &0x3f;
+ for(csp=job.colist; csp; csp = csp->next)
+ {
+ if(csp->id == id)
+ break;
+ }
+ }
+ if(csp)
+ sfprintf(shp->strbuf,"%s.%d%c",csp->name,pid&0xff,0);
+ else
+ sfprintf(shp->strbuf,"%d%c",pid,0);
+ return(sfstruse(shp->strbuf));
+ }
+
+ int job_cowalk(int (*fun)(struct process*,int),int arg,char *name)
+ {
+ Shell_t *shp = sh_getinterp();
+ struct cosh *csp;
+ struct process *pw,*pwnext;
+ pid_t val;
+ int n,r=0;
+ char *cp = strchr(name,'.');
+ if(!cp)
+ n = strlen(name);
+ else
+ n = cp-name;
+ for(csp=(struct cosh*)job.colist;csp;csp=csp->next)
+ {
+ if(memcmp(name,csp->name,n)==0 && csp->name[n]==0)
+ break;
+ }
+ if(!csp)
+ errormsg(SH_DICT,ERROR_exit(1),e_jobusage,name);
+ if(cp)
+ {
+ n = pid_fromstring(cp+1);
+ val = (csp->id<<16)|n|COPID_BIT;
+ }
+ job_reap(SIGCHLD);
+ for(n=0,pw=job.pwlist; pw; pw=pwnext)
+ {
+ pwnext = pw->p_nxtjob;
+ if((cp && val==pw->p_pid) || (pw->p_cojob && pw->p_cojob->local==(void*)csp))
+ {
+ if(fun)
+ {
+ if(pw->p_flag&P_DONE)
+ continue;
+ r |= (*fun)(pw,arg);
+ }
+ else
+ job_wait(-pw->p_pid);
+ n++;
+ }
+ }
+ if(!n)
+ shp->exitval = fun?1:ERROR_NOENT;
+ else if(fun)
+ shp->exitval = r;
+ return(r);
+ }
+
+#endif /* SHOPT_COSHELL */
+
+/*
+ * Reap one job
+ * When called with sig==0, it does a blocking wait
+ */
+int job_reap(register int sig)
+{
+ Shell_t *shp = sh_getinterp();
+ register pid_t pid;
+ register struct process *pw;
+ struct process *px;
+ register int flags;
+ struct jobsave *jp;
+ int nochild=0, oerrno, wstat;
+ Waitevent_f waitevent = shp->gd->waitevent;
+ static int wcontinued = WCONTINUED;
+#if SHOPT_COSHELL
+ Cojob_t *cjp;
+ int cojobs;
+ long cotimeout = sig?0:-1;
+ for(pw=job.pwlist;pw;pw=pw->p_nxtjob)
+ {
+ if(pw->p_cojob && !(pw->p_flag&P_DONE))
+ break;
+ }
+ cojobs = (pw!=0);
+ pid = 0;
+#endif /* SHOPT_COSHELL */
+ if (vmbusy())
+ {
+ errormsg(SH_DICT,ERROR_warn(0),"vmbusy() inside job_reap() -- should not happen");
+ if (getenv("_AST_KSH_VMBUSY_ABORT"))
+ abort();
+ }
+#ifdef DEBUG
+ if(sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d signal=%d\n",__LINE__,getpid(),job.in_critical,sig) <=0)
+ write(2,"waitsafe\n",9);
+ sfsync(sfstderr);
+#endif /* DEBUG */
+ job.savesig = 0;
+ if(sig)
+ flags = WNOHANG|WUNTRACED|wcontinued;
+ else
+ flags = WUNTRACED|wcontinued;
+ shp->gd->waitevent = 0;
+ oerrno = errno;
+ while(1)
+ {
+ if(!(flags&WNOHANG) && !sh.intrap && job.pwlist)
+ {
+ sh_onstate(SH_TTYWAIT);
+ if(waitevent && (*waitevent)(-1,-1L,0))
+ flags |= WNOHANG;
+ }
+#if SHOPT_COSHELL
+ if(cojobs)
+ {
+ if(cjp = cowait(0,0,cotimeout))
+ {
+ struct cosh *csp;
+ csp = (struct cosh*)(cjp->coshell->data);
+ csp->cojob = cjp;
+ pid = sh_copid(csp);
+ if(cjp->status < 256)
+ wstat = cjp->status <<8;
+ else
+ wstat = cjp->status-256;
+ cotimeout = 0;
+ goto cojob;
+ }
+ else if(copending(0)==0)
+ cojobs = 0;
+ cotimeout = 0;
+ }
+#endif /* SHOPT_COSHELL */
+ pid = waitpid((pid_t)-1,&wstat,flags);
+ sh_offstate(SH_TTYWAIT);
+#if SHOPT_COSHELL
+ cojob:
+#endif /* SHOPT_COSHELL */
+
+ /*
+ * some systems (linux 2.6) may return EINVAL
+ * when there are no continued children
+ */
+
+ if (pid<0 && errno==EINVAL && (flags&WCONTINUED))
+ pid = waitpid((pid_t)-1,&wstat,flags&=~WCONTINUED);
+ sh_sigcheck(shp);
+ if(pid<0 && errno==EINTR && (sig||job.savesig))
+ {
+ errno = 0;
+ continue;
+ }
+ if(pid<=0)
+ break;
+ if(wstat==0)
+ job_chksave(pid);
+ flags |= WNOHANG;
+ job.waitsafe++;
+ jp = 0;
+ lastpid = pid;
+ if(!(pw=job_bypid(pid)))
+ {
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d unknown job pid=%d pw=%x\n",__LINE__,getpid(),job.in_critical,pid,pw);
+#endif /* DEBUG */
+ if (WIFCONTINUED(wstat) && wcontinued)
+ continue;
+ pw = &dummy;
+ pw->p_exit = 0;
+ pw->p_pgrp = 0;
+ pw->p_exitmin = 0;
+ if(job.toclear)
+ job_clear();
+ jp = jobsave_create(pid);
+ pw->p_flag = 0;
+ lastpid = pw->p_pid = pid;
+ px = 0;
+ if(jp && WIFSTOPPED(wstat))
+ {
+ jp->exitval = SH_STOPSIG;
+ continue;
+ }
+ }
+#ifdef SIGTSTP
+ else
+ px=job_byjid(pw->p_job);
+ if (WIFCONTINUED(wstat) && wcontinued)
+ pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED);
+ else if(WIFSTOPPED(wstat))
+ {
+ pw->p_flag |= (P_NOTIFY|P_SIGNALLED|P_STOPPED);
+ pw->p_exit = WSTOPSIG(wstat);
+ if(pw->p_pgrp && pw->p_pgrp==job.curpgid && sh_isstate(SH_STOPOK))
+ sh_fault(pw->p_exit);
+ if(px)
+ {
+ /* move to top of job list */
+ job_unlink(px);
+ px->p_nxtjob = job.pwlist;
+ job.pwlist = px;
+ }
+ continue;
+ }
+ else
+#endif /* SIGTSTP */
+ {
+ /* check for coprocess completion */
+ if(pid==shp->cpid)
+ {
+ sh_close(sh.coutpipe);
+ sh_close(sh.cpipe[1]);
+ sh.cpipe[1] = -1;
+ sh.coutpipe = -1;
+ }
+ else if(shp->subshell)
+ sh_subjobcheck(pid);
+
+ pw->p_flag &= ~(P_STOPPED|P_SIGNALLED);
+ if (WIFSIGNALED(wstat))
+ {
+ pw->p_flag |= (P_DONE|P_NOTIFY|P_SIGNALLED);
+ if (WTERMCORE(wstat))
+ pw->p_flag |= P_COREDUMP;
+ pw->p_exit = WTERMSIG(wstat);
+ /* if process in current jobs terminates from
+ * an interrupt, propogate to parent shell
+ */
+ if(pw->p_pgrp && pw->p_pgrp==job.curpgid && pw->p_exit==SIGINT && sh_isstate(SH_STOPOK))
+ {
+ pw->p_flag &= ~P_NOTIFY;
+ sh_offstate(SH_STOPOK);
+ sh_fault(SIGINT);
+ sh_onstate(SH_STOPOK);
+ }
+ }
+ else
+ {
+ pw->p_flag |= (P_DONE|P_NOTIFY);
+ pw->p_exit = pw->p_exitmin;
+ if(WEXITSTATUS(wstat) > pw->p_exitmin)
+ pw->p_exit = WEXITSTATUS(wstat);
+ }
+#ifdef SHOPT_BGX
+ if((pw->p_flag&P_DONE) && (pw->p_flag&P_BG))
+ {
+ job.numbjob--;
+ if(shp->st.trapcom[SIGCHLD])
+ {
+ shp->sigflag[SIGCHLD] |= SH_SIGTRAP;
+ if(sig==0)
+ job_chldtrap(shp,shp->st.trapcom[SIGCHLD],0);
+ else
+ shp->trapnote |= SH_SIGTRAP;
+ }
+ else
+ pw->p_flag &= ~P_BG;
+ }
+#endif /* SHOPT_BGX */
+ if(pw->p_pgrp==0)
+ pw->p_flag &= ~P_NOTIFY;
+ }
+ if(jp && pw== &dummy)
+ {
+ jp->exitval = pw->p_exit;
+ if(pw->p_flag&P_SIGNALLED)
+ jp->exitval |= SH_EXITSIG;
+ }
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d job %d with pid %d flags=%o complete with status=%x exit=%d\n",__LINE__,getpid(),job.in_critical,pw->p_job,pid,pw->p_flag,wstat,pw->p_exit);
+ sfsync(sfstderr);
+#endif /* DEBUG*/
+ /* only top-level process in job should have notify set */
+ if(px && pw != px)
+ pw->p_flag &= ~P_NOTIFY;
+ if(pid==pw->p_fgrp && pid==tcgetpgrp(JOBTTY))
+ {
+ px = job_byjid((int)pw->p_job);
+ for(; px && (px->p_flag&P_DONE); px=px->p_nxtproc);
+ if(!px)
+ tcsetpgrp(JOBTTY,job.mypid);
+ }
+#ifndef SHOPT_BGX
+ if(!shp->intrap && shp->st.trapcom[SIGCHLD] && pid>0 && (pwfg!=job_bypid(pid)))
+ {
+ shp->sigflag[SIGCHLD] |= SH_SIGTRAP;
+ shp->trapnote |= SH_SIGTRAP;
+ }
+#endif
+ }
+ if(errno==ECHILD)
+ {
+ errno = oerrno;
+#ifdef SHOPT_BGX
+ job.numbjob = 0;
+#endif /* SHOPT_BGX */
+ nochild = 1;
+ }
+ shp->gd->waitevent = waitevent;
+ if(sh_isoption(SH_NOTIFY) && sh_isstate(SH_TTYWAIT))
+ {
+ outfile = sfstderr;
+ job_list(pw,JOB_NFLAG|JOB_NLFLAG);
+ job_unpost(pw,1);
+ sfsync(sfstderr);
+ }
+ if(sig)
+ signal(sig, job_waitsafe);
+ return(nochild);
+}
+
+/*
+ * This is the SIGCLD interrupt routine
+ */
+static void job_waitsafe(int sig)
+{
+ if(job.in_critical || vmbusy())
+ {
+ job.savesig = sig;
+ job.waitsafe++;
+ }
+ else
+ job_reap(sig);
+}
+
+/*
+ * initialize job control if possible
+ * if lflag is set the switching driver message will not print
+ */
+void job_init(Shell_t *shp, int lflag)
+{
+ register int ntry=0;
+ job.fd = JOBTTY;
+ signal(SIGCHLD,job_waitsafe);
+# if defined(SIGCLD) && (SIGCLD!=SIGCHLD)
+ signal(SIGCLD,job_waitsafe);
+# endif
+ if(njob_savelist < NJOB_SAVELIST)
+ init_savelist();
+ if(!sh_isoption(SH_INTERACTIVE))
+ return;
+ /* use new line discipline when available */
+#ifdef NTTYDISC
+# ifdef FIOLOOKLD
+ if((job.linedisc = ioctl(JOBTTY, FIOLOOKLD, 0)) <0)
+# else
+ if(ioctl(JOBTTY,TIOCGETD,&job.linedisc) !=0)
+# endif /* FIOLOOKLD */
+ return;
+ if(job.linedisc!=NTTYDISC && job.linedisc!=OTTYDISC)
+ {
+ /* no job control when running with MPX */
+# if SHOPT_VSH
+ sh_onoption(SH_VIRAW);
+# endif /* SHOPT_VSH */
+ return;
+ }
+ if(job.linedisc==NTTYDISC)
+ job.linedisc = -1;
+#endif /* NTTYDISC */
+
+ job.mypgid = getpgrp();
+ /* some systems have job control, but not initialized */
+ if(job.mypgid<=0)
+ {
+ /* Get a controlling terminal and set process group */
+ /* This should have already been done by rlogin */
+ register int fd;
+ register char *ttynam;
+#ifndef SIGTSTP
+ setpgid(0,shp->gd->pid);
+#endif /*SIGTSTP */
+ if(job.mypgid<0 || !(ttynam=ttyname(JOBTTY)))
+ return;
+ close(JOBTTY);
+ if((fd = open(ttynam,O_RDWR)) <0)
+ return;
+ if(fd!=JOBTTY)
+ sh_iorenumber(shp,fd,JOBTTY);
+ job.mypgid = shp->gd->pid;
+#ifdef SIGTSTP
+ tcsetpgrp(JOBTTY,shp->gd->pid);
+ setpgid(0,shp->gd->pid);
+#endif /* SIGTSTP */
+ }
+#ifdef SIGTSTP
+ if(possible = (setpgid(0,job.mypgid)>=0) || errno==EPERM)
+ {
+ /* wait until we are in the foreground */
+ while((job.mytgid=tcgetpgrp(JOBTTY)) != job.mypgid)
+ {
+ if(job.mytgid == -1)
+ return;
+ /* Stop this shell until continued */
+ signal(SIGTTIN,SIG_DFL);
+ kill(shp->gd->pid,SIGTTIN);
+ /* resumes here after continue tries again */
+ if(ntry++ > IOMAXTRY)
+ {
+ errormsg(SH_DICT,0,e_no_start);
+ return;
+ }
+ }
+ }
+#endif /* SIGTTIN */
+
+#ifdef NTTYDISC
+ /* set the line discipline */
+ if(job.linedisc>=0)
+ {
+ int linedisc = NTTYDISC;
+# ifdef FIOPUSHLD
+ tty_get(JOBTTY,&my_stty);
+ if (ioctl(JOBTTY, FIOPOPLD, 0) < 0)
+ return;
+ if (ioctl(JOBTTY, FIOPUSHLD, &linedisc) < 0)
+ {
+ ioctl(JOBTTY, FIOPUSHLD, &job.linedisc);
+ return;
+ }
+ tty_set(JOBTTY,TCSANOW,&my_stty);
+# else
+ if(ioctl(JOBTTY,TIOCSETD,&linedisc) !=0)
+ return;
+# endif /* FIOPUSHLD */
+ if(lflag==0)
+ errormsg(SH_DICT,0,e_newtty);
+ else
+ job.linedisc = -1;
+ }
+#endif /* NTTYDISC */
+ if(!possible)
+ return;
+
+#ifdef SIGTSTP
+ /* make sure that we are a process group leader */
+ setpgid(0,shp->gd->pid);
+# if defined(SA_NOCLDSTOP) || defined(SA_NOCLDWAIT)
+# if !defined(SA_NOCLDSTOP)
+# define SA_NOCLDSTOP 0
+# endif
+# if !defined(SA_NOCLDWAIT)
+# define SA_NOCLDWAIT 0
+# endif
+ sigflag(SIGCHLD, SA_NOCLDSTOP|SA_NOCLDWAIT, 0);
+# endif /* SA_NOCLDSTOP || SA_NOCLDWAIT */
+ signal(SIGTTIN,SIG_IGN);
+ signal(SIGTTOU,SIG_IGN);
+ /* The shell now handles ^Z */
+ signal(SIGTSTP,sh_fault);
+ tcsetpgrp(JOBTTY,shp->gd->pid);
+# ifdef CNSUSP
+ /* set the switch character */
+ tty_get(JOBTTY,&my_stty);
+ job.suspend = (unsigned)my_stty.c_cc[VSUSP];
+ if(job.suspend == (unsigned char)CNSUSP)
+ {
+ my_stty.c_cc[VSUSP] = CSWTCH;
+ tty_set(JOBTTY,TCSAFLUSH,&my_stty);
+ }
+# endif /* CNSUSP */
+ sh_onoption(SH_MONITOR);
+ job.jobcontrol++;
+ job.mypid = shp->gd->pid;
+#endif /* SIGTSTP */
+ return;
+}
+
+
+/*
+ * see if there are any stopped jobs
+ * restore tty driver and pgrp
+ */
+int job_close(Shell_t* shp)
+{
+ register struct process *pw;
+ register int count = 0, running = 0;
+ if(possible && !job.jobcontrol)
+ return(0);
+ else if(!possible && (!sh_isstate(SH_MONITOR) || sh_isstate(SH_FORKED)))
+ return(0);
+ else if(getpid() != job.mypid)
+ return(0);
+ job_lock();
+ if(!tty_check(0))
+ beenhere++;
+ for(pw=job.pwlist;pw;pw=pw->p_nxtjob)
+ {
+ if(!(pw->p_flag&P_STOPPED))
+ {
+ if(!(pw->p_flag&P_DONE))
+ running++;
+ continue;
+ }
+ if(beenhere)
+ killpg(pw->p_pgrp,SIGTERM);
+ count++;
+ }
+ if(beenhere++ == 0 && job.pwlist)
+ {
+ if(count)
+ {
+ errormsg(SH_DICT,0,e_terminate);
+ return(-1);
+ }
+ else if(running && shp->login_sh)
+ {
+ errormsg(SH_DICT,0,e_jobsrunning);
+ return(-1);
+ }
+ }
+ job_unlock();
+# ifdef SIGTSTP
+ if(possible && setpgid(0,job.mypgid)>=0)
+ tcsetpgrp(job.fd,job.mypgid);
+# endif /* SIGTSTP */
+# ifdef NTTYDISC
+ if(job.linedisc>=0)
+ {
+ /* restore old line discipline */
+# ifdef FIOPUSHLD
+ tty_get(job.fd,&my_stty);
+ if (ioctl(job.fd, FIOPOPLD, 0) < 0)
+ return(0);
+ if (ioctl(job.fd, FIOPUSHLD, &job.linedisc) < 0)
+ {
+ job.linedisc = NTTYDISC;
+ ioctl(job.fd, FIOPUSHLD, &job.linedisc);
+ return(0);
+ }
+ tty_set(job.fd,TCSAFLUSH,&my_stty);
+# else
+ if(ioctl(job.fd,TIOCSETD,&job.linedisc) !=0)
+ return(0);
+# endif /* FIOPUSHLD */
+ errormsg(SH_DICT,0,e_oldtty);
+ }
+# endif /* NTTYDISC */
+# ifdef CNSUSP
+ if(possible && job.suspend==CNSUSP)
+ {
+ tty_get(job.fd,&my_stty);
+ my_stty.c_cc[VSUSP] = CNSUSP;
+ tty_set(job.fd,TCSAFLUSH,&my_stty);
+ }
+# endif /* CNSUSP */
+ job.jobcontrol = 0;
+ return(0);
+}
+
+static void job_set(register struct process *pw)
+{
+ Shell_t *shp = pw->p_shp;
+ /* save current terminal state */
+ tty_get(job.fd,&my_stty);
+ if(pw->p_flag&P_STTY)
+ {
+ /* restore terminal state for job */
+ tty_set(job.fd,TCSAFLUSH,&pw->p_stty);
+ }
+#ifdef SIGTSTP
+ if((pw->p_flag&P_STOPPED) || tcgetpgrp(job.fd) == shp->gd->pid)
+ tcsetpgrp(job.fd,pw->p_fgrp);
+ /* if job is stopped, resume it in the background */
+ job_unstop(pw);
+#endif /* SIGTSTP */
+}
+
+static void job_reset(register struct process *pw)
+{
+ /* save the terminal state for current job */
+#ifdef SIGTSTP
+ job_fgrp(pw,tcgetpgrp(job.fd));
+ if(tcsetpgrp(job.fd,job.mypid) !=0)
+ return;
+#endif /* SIGTSTP */
+ /* force the following tty_get() to do a tcgetattr() unless fg */
+ if(!(pw->p_flag&P_FG))
+ tty_set(-1, 0, NIL(struct termios*));
+ if(pw && (pw->p_flag&P_SIGNALLED) && pw->p_exit!=SIGHUP)
+ {
+ if(tty_get(job.fd,&pw->p_stty) == 0)
+ pw->p_flag |= P_STTY;
+ /* restore terminal state for job */
+ tty_set(job.fd,TCSAFLUSH,&my_stty);
+ }
+ beenhere = 0;
+}
+#endif /* JOBS */
+
+/*
+ * wait built-in command
+ */
+
+void job_bwait(char **jobs)
+{
+ register char *jp;
+ register struct process *pw;
+ register pid_t pid;
+ if(*jobs==0)
+ job_wait((pid_t)-1);
+ else while(jp = *jobs++)
+ {
+#ifdef JOBS
+ if(*jp == '%')
+ {
+ job_lock();
+ pw = job_bystring(jp);
+ job_unlock();
+ if(pw)
+ pid = pw->p_pid;
+ else
+ return;
+ }
+# if SHOPT_COSHELL
+ else if(isalpha(*jp))
+ {
+ job_cowalk(NULL,0,jp);
+ return;
+ }
+# endif /* SHOPT_COSHELL */
+ else
+#endif /* JOBS */
+ pid = pid_fromstring(jp);
+ job_wait(-pid);
+ }
+}
+
+#ifdef JOBS
+/*
+ * execute function <fun> for each job
+ */
+
+int job_walk(Sfio_t *file,int (*fun)(struct process*,int),int arg,char *joblist[])
+{
+ register struct process *pw;
+ register int r = 0;
+ register char *jobid, **jobs=joblist;
+ register struct process *px;
+ job_string = 0;
+ outfile = file;
+ by_number = 0;
+ job_lock();
+ pw = job.pwlist;
+#if SHOPT_COSHELL
+ job_waitsafe(SIGCHLD);
+#endif /* SHOPT_COSHELL */
+ if(jobs==0)
+ {
+ /* do all jobs */
+ for(;pw;pw=px)
+ {
+ px = pw->p_nxtjob;
+ if(pw->p_env != sh.jobenv)
+ continue;
+ if((*fun)(pw,arg))
+ r = 2;
+ }
+ }
+ else if(*jobs==0) /* current job */
+ {
+ /* skip over non-stop jobs */
+ while(pw && (pw->p_env!=sh.jobenv || pw->p_pgrp==0))
+ pw = pw->p_nxtjob;
+ if((*fun)(pw,arg))
+ r = 2;
+ }
+ else while(jobid = *jobs++)
+ {
+ job_string = jobid;
+ if(*jobid==0)
+ errormsg(SH_DICT,ERROR_exit(1),e_jobusage,job_string);
+#if SHOPT_COSHELL
+ if(isalpha(*jobid))
+ {
+ r = job_cowalk(fun,arg,jobid);
+ by_number = 0;
+ job_unlock();
+ return(r);
+ }
+#endif /* SHOPT_COSHELL */
+ if(*jobid == '%')
+ pw = job_bystring(jobid);
+ else
+ {
+ int pid = pid_fromstring(jobid);
+ if(!(pw = job_bypid(pid)))
+ {
+ pw = &dummy;
+ pw->p_shp = sh_getinterp();
+ pw->p_pid = pid;
+ pw->p_pgrp = pid;
+ }
+ by_number = 1;
+ }
+ if((*fun)(pw,arg))
+ r = 2;
+ by_number = 0;
+ }
+ job_unlock();
+ return(r);
+}
+
+/*
+ * send signal <sig> to background process group if not disowned
+ */
+int job_terminate(register struct process *pw,register int sig)
+{
+ if(pw->p_pgrp && !(pw->p_flag&P_DISOWN))
+ job_kill(pw,sig);
+ return(0);
+}
+
+/*
+ * list the given job
+ * flag JOB_LFLAG for long listing
+ * flag JOB_NFLAG for list only jobs marked for notification
+ * flag JOB_PFLAG for process id(s) only
+ */
+
+int job_list(struct process *pw,register int flag)
+{
+ Shell_t *shp = sh_getinterp();
+ register struct process *px = pw;
+ register int n;
+ register const char *msg;
+ register int msize;
+ if(!pw || pw->p_job<=0)
+ return(1);
+ if(pw->p_env != shp->jobenv)
+ return(0);
+ if((flag&JOB_NFLAG) && (!(px->p_flag&P_NOTIFY)||px->p_pgrp==0))
+ return(0);
+ if((flag&JOB_PFLAG))
+ {
+#if SHOPT_COSHELL
+ sfprintf(outfile,"%s\n",sh_pid2str(shp,px->p_pgrp?px->p_pgrp:px->p_pid));
+#else
+ sfprintf(outfile,"%d\n",px->p_pgrp?px->p_pgrp:px->p_pid);
+#endif /* SHOPT_COSHELL */
+ return(0);
+ }
+ if((px->p_flag&P_DONE) && job.waitall && !(flag&JOB_LFLAG))
+ return(0);
+ job_lock();
+ n = px->p_job;
+ if(px==job.pwlist)
+ msize = '+';
+ else if(px==job.pwlist->p_nxtjob)
+ msize = '-';
+ else
+ msize = ' ';
+ if(flag&JOB_NLFLAG)
+ sfputc(outfile,'\n');
+ sfprintf(outfile,"[%d] %c ",n, msize);
+ do
+ {
+ n = 0;
+ if(flag&JOB_LFLAG)
+#if SHOPT_COSHELL
+ sfprintf(outfile,"%s\t",sh_pid2str(shp,px->p_pid));
+#else
+ sfprintf(outfile,"%d\t",px->p_pid);
+#endif /* SHOPT_COSHELL */
+ if(px->p_flag&P_SIGNALLED)
+ msg = job_sigmsg((int)(px->p_exit));
+ else if(px->p_flag&P_NOTIFY)
+ {
+ msg = sh_translate(e_done);
+ n = px->p_exit;
+ }
+ else
+ msg = sh_translate(e_running);
+ px->p_flag &= ~P_NOTIFY;
+ sfputr(outfile,msg,-1);
+ msize = strlen(msg);
+ if(n)
+ {
+ sfprintf(outfile,"(%d)",(int)n);
+ msize += (3+(n>10)+(n>100));
+ }
+ if(px->p_flag&P_COREDUMP)
+ {
+ msg = sh_translate(e_coredump);
+ sfputr(outfile, msg, -1);
+ msize += strlen(msg);
+ }
+ sfnputc(outfile,' ',MAXMSG>msize?MAXMSG-msize:1);
+ if(flag&JOB_LFLAG)
+ px = px->p_nxtproc;
+ else
+ {
+ while(px=px->p_nxtproc)
+ px->p_flag &= ~P_NOTIFY;
+ px = 0;
+ }
+ if(!px)
+ hist_list(shgd->hist_ptr,outfile,pw->p_name,0,";");
+ else
+ sfputr(outfile, e_nlspace, -1);
+ }
+ while(px);
+ job_unlock();
+ return(0);
+}
+
+/*
+ * get the process group given the job number
+ * This routine returns the process group number or -1
+ */
+static struct process *job_bystring(register char *ajob)
+{
+ register struct process *pw=job.pwlist;
+ register int c;
+ if(*ajob++ != '%' || !pw)
+ return(NIL(struct process*));
+ c = *ajob;
+ if(isdigit(c))
+ pw = job_byjid((int)strtol(ajob, (char**)0, 10));
+ else if(c=='+' || c=='%')
+ ;
+ else if(c=='-')
+ {
+ if(pw)
+ pw = job.pwlist->p_nxtjob;
+ }
+ else
+ pw = job_byname(ajob);
+ if(pw && pw->p_flag)
+ return(pw);
+ return(NIL(struct process*));
+}
+
+/*
+ * Kill a job or process
+ */
+
+int job_kill(register struct process *pw,register int sig)
+{
+ Shell_t *shp = pw->p_shp;
+ register pid_t pid;
+ register int r;
+ const char *msg;
+#ifdef SIGTSTP
+ int stopsig = (sig==SIGSTOP||sig==SIGTSTP||sig==SIGTTIN||sig==SIGTTOU);
+#else
+# define stopsig 1
+#endif /* SIGTSTP */
+ job_lock();
+ errno = ECHILD;
+ if(pw==0)
+ goto error;
+ pid = pw->p_pid;
+#if SHOPT_COSHELL
+ if(pw->p_cojob)
+ r = cokill(pw->p_cojob->coshell,pw->p_cojob,sig);
+ else
+#endif /* SHOPT_COSHELL */
+ if(by_number)
+ {
+ if(pid==0 && job.jobcontrol)
+ r = job_walk(outfile, job_kill,sig, (char**)0);
+#ifdef SIGTSTP
+ if(sig==SIGSTOP && pid==shp->gd->pid && shp->gd->ppid==1)
+ {
+ /* can't stop login shell */
+ errno = EPERM;
+ r = -1;
+ }
+ else
+ {
+ if(pid>=0)
+ {
+ if((r = kill(pid,sig))>=0 && !stopsig)
+ {
+ if(pw->p_flag&P_STOPPED)
+ pw->p_flag &= ~(P_STOPPED|P_SIGNALLED);
+ if(sig)
+ kill(pid,SIGCONT);
+ }
+ }
+ else
+ {
+ if((r = killpg(-pid,sig))>=0 && !stopsig)
+ {
+ job_unstop(job_bypid(pw->p_pid));
+ if(sig)
+ killpg(-pid,SIGCONT);
+ }
+ }
+ }
+#else
+ if(pid>=0)
+ r = kill(pid,sig);
+ else
+ r = killpg(-pid,sig);
+#endif /* SIGTSTP */
+ }
+ else
+ {
+ if(pid = pw->p_pgrp)
+ {
+ r = killpg(pid,sig);
+#ifdef SIGTSTP
+ if(r>=0 && (sig==SIGHUP||sig==SIGTERM || sig==SIGCONT))
+ job_unstop(pw);
+#endif /* SIGTSTP */
+ if(r>=0)
+ sh_delay(.05);
+ }
+ while(pw && pw->p_pgrp==0 && (r=kill(pw->p_pid,sig))>=0)
+ {
+#ifdef SIGTSTP
+ if(sig==SIGHUP || sig==SIGTERM)
+ kill(pw->p_pid,SIGCONT);
+#endif /* SIGTSTP */
+ pw = pw->p_nxtproc;
+ }
+ }
+ if(r<0 && job_string)
+ {
+ error:
+ if(pw && by_number)
+ msg = sh_translate(e_no_proc);
+ else
+ msg = sh_translate(e_no_job);
+ if(errno == EPERM)
+ msg = sh_translate(e_access);
+ sfprintf(sfstderr,"kill: %s: %s\n",job_string, msg);
+ r = 2;
+ }
+ sh_delay(.001);
+ job_unlock();
+ return(r);
+}
+
+/*
+ * Get process structure from first letters of jobname
+ *
+ */
+
+static struct process *job_byname(char *name)
+{
+ register struct process *pw = job.pwlist;
+ register struct process *pz = 0;
+ register int *flag = 0;
+ register char *cp = name;
+ int offset;
+ if(!shgd->hist_ptr)
+ return(NIL(struct process*));
+ if(*cp=='?')
+ cp++,flag= &offset;
+ for(;pw;pw=pw->p_nxtjob)
+ {
+ if(hist_match(shgd->hist_ptr,pw->p_name,cp,flag)>=0)
+ {
+ if(pz)
+ errormsg(SH_DICT,ERROR_exit(1),e_jobusage,name-1);
+ pz = pw;
+ }
+ }
+ return(pz);
+}
+
+#else
+# define job_set(x)
+# define job_reset(x)
+#endif /* JOBS */
+
+
+
+/*
+ * Initialize the process posting array
+ */
+
+void job_clear(void)
+{
+ Shell_t *shp = sh_getinterp();
+ register struct process *pw, *px;
+ register struct process *pwnext;
+ register int j = BYTE(shp->gd->lim.child_max);
+ register struct jobsave *jp,*jpnext;
+ job_lock();
+ for(pw=job.pwlist; pw; pw=pwnext)
+ {
+ pwnext = pw->p_nxtjob;
+ while(px=pw)
+ {
+ pw = pw->p_nxtproc;
+ free((void*)px);
+ }
+ }
+ for(jp=bck.list; jp;jp=jpnext)
+ {
+ jpnext = jp->next;
+ free((void*)jp);
+ }
+ bck.list = 0;
+ if(njob_savelist < NJOB_SAVELIST)
+ init_savelist();
+ job.pwlist = NIL(struct process*);
+ job.numpost=0;
+#ifdef SHOPT_BGX
+ job.numbjob = 0;
+#endif /* SHOPT_BGX */
+ job.waitall = 0;
+ job.curpgid = 0;
+ job.toclear = 0;
+ if(!job.freejobs)
+ job.freejobs = (unsigned char*)malloc((unsigned)(j+1));
+ while(j >=0)
+ job.freejobs[j--] = 0;
+ job_unlock();
+}
+
+/*
+ * put the process <pid> on the process list and return the job number
+ * if non-zero, <join> is the process id of the job to join
+ */
+
+int job_post(Shell_t *shp,pid_t pid, pid_t join)
+{
+ register struct process *pw;
+ register History_t *hp = shp->gd->hist_ptr;
+#ifdef SHOPT_BGX
+ int val,bg=0;
+#else
+ int val;
+#endif
+ shp->jobenv = shp->curenv;
+ if(job.toclear)
+ {
+ job_clear();
+ return(0);
+ }
+ job_lock();
+#ifdef SHOPT_BGX
+ if(join==1)
+ {
+ join = 0;
+ bg = P_BG;
+ job.numbjob++;
+ }
+#endif /* SHOPT_BGX */
+ if(njob_savelist < NJOB_SAVELIST)
+ init_savelist();
+ if(pw = job_bypid(pid))
+ job_unpost(pw,0);
+ if(join)
+ {
+ if(pw=job_bypid(join))
+ val = pw->p_job;
+ else
+ val = job.curjobid;
+ /* if job to join is not first move it to front */
+ if(val && (pw=job_byjid(val)) != job.pwlist)
+ {
+ job_unlink(pw);
+ pw->p_nxtjob = job.pwlist;
+ job.pwlist = pw;
+ }
+ }
+ if(pw=freelist)
+ freelist = pw->p_nxtjob;
+ else
+ pw = new_of(struct process,0);
+ pw->p_flag = 0;
+ job.numpost++;
+ if(join && job.pwlist)
+ {
+ /* join existing current job */
+ pw->p_nxtjob = job.pwlist->p_nxtjob;
+ pw->p_nxtproc = job.pwlist;
+ pw->p_job = job.pwlist->p_job;
+ }
+ else
+ {
+ /* create a new job */
+ while((pw->p_job = job_alloc()) < 0)
+ job_wait((pid_t)1);
+ pw->p_nxtjob = job.pwlist;
+ pw->p_nxtproc = 0;
+ }
+ pw->p_exitval = job.exitval;
+#if SHOPT_COSHELL
+ pw->p_cojob = 0;
+ if(shp->coshell && (pid&COPID_BIT))
+ {
+ pw->p_cojob = ((struct cosh*)shp->coshell)->cojob;
+ job.curpgid = sh_isstate(SH_MONITOR)?pid:0;
+ }
+#endif /* SHOPT_COSHELL */
+ job.pwlist = pw;
+ pw->p_shp = shp;
+ pw->p_env = shp->curenv;
+ pw->p_pid = pid;
+ if(!shp->outpipe || shp->cpid==pid)
+ pw->p_flag = P_EXITSAVE;
+ pw->p_exitmin = shp->xargexit;
+ pw->p_exit = 0;
+ if(sh_isstate(SH_MONITOR))
+ {
+ if(killpg(job.curpgid,0)<0 && errno==ESRCH)
+ job.curpgid = pid;
+ pw->p_fgrp = job.curpgid;
+ }
+ else
+ pw->p_fgrp = 0;
+ pw->p_pgrp = pw->p_fgrp;
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: post pid=%d critical=%d job=%d pid=%d pgid=%d savesig=%d join=%d\n",__LINE__,getpid(),job.in_critical,pw->p_job,
+ pw->p_pid,pw->p_pgrp,job.savesig,join);
+ sfsync(sfstderr);
+#endif /* DEBUG */
+#ifdef JOBS
+ if(hp && !sh_isstate(SH_PROFILE))
+ pw->p_name=hist_tell(shgd->hist_ptr,(int)hp->histind-1);
+ else
+ pw->p_name = -1;
+#endif /* JOBS */
+ if ((val = job_chksave(pid))>=0 && !jobfork)
+ {
+ pw->p_exit = val;
+ if(pw->p_exit==SH_STOPSIG)
+ {
+ pw->p_flag |= (P_SIGNALLED|P_STOPPED);
+ pw->p_exit = 0;
+ }
+ else if(pw->p_exit >= SH_EXITSIG)
+ {
+ pw->p_flag |= P_DONE|P_SIGNALLED;
+ pw->p_exit &= SH_EXITMASK;
+ }
+ else
+ pw->p_flag |= (P_DONE|P_NOTIFY);
+ }
+#ifdef SHOPT_BGX
+ if(bg)
+ {
+ if(pw->p_flag&P_DONE)
+ job.numbjob--;
+ else
+ pw->p_flag |= P_BG;
+ }
+#endif /* SHOPT_BGX */
+ lastpid = 0;
+ job_unlock();
+ return(pw->p_job);
+}
+
+/*
+ * Returns a process structure give a process id
+ */
+
+static struct process *job_bypid(pid_t pid)
+{
+ register struct process *pw, *px;
+ for(pw=job.pwlist; pw; pw=pw->p_nxtjob)
+ for(px=pw; px; px=px->p_nxtproc)
+ {
+ if(px->p_pid==pid)
+ return(px);
+ }
+ return(NIL(struct process*));
+}
+
+/*
+ * return a pointer to a job given the job id
+ */
+
+static struct process *job_byjid(int jobid)
+{
+ register struct process *pw;
+ for(pw=job.pwlist;pw; pw = pw->p_nxtjob)
+ {
+ if(pw->p_job==jobid)
+ break;
+ }
+ return(pw);
+}
+
+/*
+ * print a signal message
+ */
+static void job_prmsg(register struct process *pw)
+{
+ if(pw->p_exit!=SIGINT && pw->p_exit!=SIGPIPE)
+ {
+ register const char *msg, *dump;
+ msg = job_sigmsg((int)(pw->p_exit));
+ msg = sh_translate(msg);
+ if(pw->p_flag&P_COREDUMP)
+ dump = sh_translate(e_coredump);
+ else
+ dump = "";
+ if(sh_isstate(SH_INTERACTIVE))
+ sfprintf(sfstderr,"%s%s\n",msg,dump);
+ else
+ errormsg(SH_DICT,2,"%d: %s%s",pw->p_pid,msg,dump);
+ }
+}
+
+/*
+ * Wait for process pid to complete
+ * If pid < -1, then wait can be interrupted, -pid is waited for (wait builtin)
+ * pid=0 to unpost all done processes
+ * pid=1 to wait for at least one process to complete
+ * pid=-1 to wait for all runing processes
+ */
+
+int job_wait(register pid_t pid)
+{
+ Shell_t *shp = sh_getinterp();
+ register struct process *pw=0,*px;
+ register int jobid = 0;
+ int nochild = 1;
+ char intr = 0;
+ if(pid < 0)
+ {
+ pid = -pid;
+ intr = 1;
+ }
+ job_lock();
+ if(pid==0)
+ {
+ if(!job.waitall || !job.curjobid || !(pw = job_byjid(job.curjobid)))
+ {
+ job_unlock();
+ goto done;
+ }
+ jobid = pw->p_job;
+ job.curjobid = 0;
+ if(!(pw->p_flag&(P_DONE|P_STOPPED)))
+ job_reap(job.savesig);
+ }
+ if(pid > 1)
+ {
+ if(pid==shp->spid)
+ shp->spid = 0;
+ if(!(pw=job_bypid(pid)))
+ {
+ /* check to see whether job status has been saved */
+ if((shp->exitval = job_chksave(pid)) < 0)
+ shp->exitval = ERROR_NOENT;
+ exitset();
+ job_unlock();
+ return(nochild);
+ }
+ else if(intr && pw->p_env!=shp->curenv)
+ {
+ shp->exitval = ERROR_NOENT;
+ job_unlock();
+ return(nochild);
+ }
+ jobid = pw->p_job;
+ if(!intr)
+ pw->p_flag &= ~P_EXITSAVE;
+ if(pw->p_pgrp && job.parent!= (pid_t)-1)
+ job_set(job_byjid(jobid));
+ }
+ pwfg = pw;
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d job=%d pid=%d\n",__LINE__,getpid(),job.in_critical,jobid,pid);
+ if(pw)
+ sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d flags=%o\n",__LINE__,getpid(),job.in_critical,pw->p_flag);
+#endif /* DEBUG*/
+ errno = 0;
+ if(shp->coutpipe>=0 && lastpid && shp->cpid==lastpid)
+ {
+ sh_close(shp->coutpipe);
+ sh_close(shp->cpipe[1]);
+ shp->cpipe[1] = shp->coutpipe = -1;
+ }
+ while(1)
+ {
+ if(job.waitsafe)
+ {
+ for(px=job.pwlist;px; px = px->p_nxtjob)
+ {
+ if(px!=pw && (px->p_flag&P_NOTIFY))
+ {
+ if(sh_isoption(SH_NOTIFY))
+ {
+ outfile = sfstderr;
+ job_list(px,JOB_NFLAG|JOB_NLFLAG);
+ sfsync(sfstderr);
+ }
+ else if(!sh_isoption(SH_INTERACTIVE) && (px->p_flag&P_SIGNALLED))
+ {
+ job_prmsg(px);
+ px->p_flag &= ~P_NOTIFY;
+ }
+ }
+ }
+ }
+ if(pw && (pw->p_flag&(P_DONE|P_STOPPED)))
+ {
+#ifdef SIGTSTP
+ if(pw->p_flag&P_STOPPED)
+ {
+ pw->p_flag |= P_EXITSAVE;
+ if(sh_isoption(SH_INTERACTIVE) && !sh_isstate(SH_FORKED))
+ {
+ if( pw->p_exit!=SIGTTIN && pw->p_exit!=SIGTTOU)
+ break;
+
+ killpg(pw->p_pgrp,SIGCONT);
+ }
+ else /* ignore stop when non-interactive */
+ pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED|P_EXITSAVE);
+ }
+ else
+#endif /* SIGTSTP */
+ {
+ if(pw->p_flag&P_SIGNALLED)
+ {
+ pw->p_flag &= ~P_NOTIFY;
+ job_prmsg(pw);
+ }
+ else if(pw->p_flag&P_DONE)
+ pw->p_flag &= ~P_NOTIFY;
+ if(pw->p_job==jobid)
+ {
+ px = job_byjid(jobid);
+ /* last process in job */
+ if(px!=pw)
+ px = 0;
+ if(px)
+ {
+ shp->exitval=px->p_exit;
+ if(px->p_flag&P_SIGNALLED)
+ shp->exitval |= SH_EXITSIG;
+ if(intr)
+ px->p_flag &= ~P_EXITSAVE;
+ }
+ }
+ px = job_unpost(pw,1);
+ if(!px || !job.waitall)
+ break;
+ pw = px;
+ continue;
+ }
+ }
+ sfsync(sfstderr);
+ job.waitsafe = 0;
+ nochild = job_reap(job.savesig);
+ if(job.waitsafe)
+ continue;
+ if(nochild)
+ break;
+ if(shp->sigflag[SIGALRM]&SH_SIGTRAP)
+ sh_timetraps(shp);
+ if((intr && shp->trapnote) || (pid==1 && !intr))
+ break;
+ }
+ if(intr && shp->trapnote)
+ shp->exitval = 1;
+ pwfg = 0;
+ job_unlock();
+ if(pid==1)
+ return(nochild);
+ exitset();
+ if(pid==0)
+ goto done;
+ if(pw->p_pgrp)
+ {
+ job_reset(pw);
+ /* propogate keyboard interrupts to parent */
+ if((pw->p_flag&P_SIGNALLED) && pw->p_exit==SIGINT && !(shp->sigflag[SIGINT]&SH_SIGOFF))
+ sh_fault(SIGINT);
+#ifdef SIGTSTP
+ else if((pw->p_flag&P_STOPPED) && pw->p_exit==SIGTSTP)
+ {
+ job.parent = 0;
+ sh_fault(SIGTSTP);
+ }
+#endif /* SIGTSTP */
+ }
+ else
+ {
+ if(pw->p_pid == tcgetpgrp(JOBTTY))
+ {
+ if(pw->p_pgrp==0)
+ pw->p_pgrp = pw->p_pid;
+ job_reset(pw);
+ }
+ tty_set(-1, 0, NIL(struct termios*));
+ }
+done:
+ if(!job.waitall && sh_isoption(SH_PIPEFAIL))
+ return(nochild);
+ if(!shp->intrap)
+ {
+ job_lock();
+ for(pw=job.pwlist; pw; pw=px)
+ {
+ px = pw->p_nxtjob;
+ job_unpost(pw,0);
+ }
+ job_unlock();
+ }
+ return(nochild);
+}
+
+/*
+ * move job to foreground if bgflag == 'f'
+ * move job to background if bgflag == 'b'
+ * disown job if bgflag == 'd'
+ */
+
+int job_switch(register struct process *pw,int bgflag)
+{
+ register const char *msg;
+ job_lock();
+ if(!pw || !(pw=job_byjid((int)pw->p_job)))
+ {
+ job_unlock();
+ return(1);
+ }
+ if(bgflag=='d')
+ {
+ for(; pw; pw=pw->p_nxtproc)
+ pw->p_flag |= P_DISOWN;
+ job_unlock();
+ return(0);
+ }
+#ifdef SIGTSTP
+ if(bgflag=='b')
+ {
+ sfprintf(outfile,"[%d]\t",(int)pw->p_job);
+ sh.bckpid = pw->p_pid;
+#ifdef SHOPT_BGX
+ pw->p_flag |= P_BG;
+#endif
+ msg = "&";
+ }
+ else
+ {
+ job_unlink(pw);
+ pw->p_nxtjob = job.pwlist;
+ job.pwlist = pw;
+ msg = "";
+ }
+ hist_list(shgd->hist_ptr,outfile,pw->p_name,'&',";");
+ sfputr(outfile,msg,'\n');
+ sfsync(outfile);
+ if(bgflag=='f')
+ {
+ if(!(pw=job_unpost(pw,1)))
+ {
+ job_unlock();
+ return(1);
+ }
+ job.waitall = 1;
+ pw->p_flag |= P_FG;
+#ifdef SHOPT_BGX
+ pw->p_flag &= ~P_BG;
+#endif
+ job_wait(pw->p_pid);
+ job.waitall = 0;
+ }
+ else if(pw->p_flag&P_STOPPED)
+ job_unstop(pw);
+#endif /* SIGTSTP */
+ job_unlock();
+ return(0);
+}
+
+
+#ifdef SIGTSTP
+/*
+ * Set the foreground group associated with a job
+ */
+
+static void job_fgrp(register struct process *pw, int newgrp)
+{
+ for(; pw; pw=pw->p_nxtproc)
+ pw->p_fgrp = newgrp;
+}
+
+/*
+ * turn off STOP state of a process group and send CONT signals
+ */
+
+static void job_unstop(register struct process *px)
+{
+ register struct process *pw;
+ register int num = 0;
+ for(pw=px ;pw ;pw=pw->p_nxtproc)
+ {
+ if(pw->p_flag&P_STOPPED)
+ {
+ num++;
+ pw->p_flag &= ~(P_STOPPED|P_SIGNALLED|P_NOTIFY);
+ }
+ }
+ if(num!=0)
+ {
+ if(px->p_fgrp != px->p_pgrp)
+ killpg(px->p_fgrp,SIGCONT);
+ killpg(px->p_pgrp,SIGCONT);
+ }
+}
+#endif /* SIGTSTP */
+
+/*
+ * remove a job from table
+ * If all the processes have not completed, unpost first non-completed process
+ * Otherwise the job is removed and job_unpost returns NULL.
+ * pwlist is reset if the first job is removed
+ * if <notify> is non-zero, then jobs with pending notifications are unposted
+ */
+
+static struct process *job_unpost(register struct process *pwtop,int notify)
+{
+ register struct process *pw;
+ /* make sure all processes are done */
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: drop pid=%d critical=%d pid=%d env=%d\n",__LINE__,getpid(),job.in_critical,pwtop->p_pid,pwtop->p_env);
+ sfsync(sfstderr);
+#endif /* DEBUG */
+ pwtop = pw = job_byjid((int)pwtop->p_job);
+#ifdef SHOPT_BGX
+ if(pw->p_flag&P_BG)
+ return(pw);
+#endif /* SHOPT_BGX */
+ for(; pw && (pw->p_flag&P_DONE)&&(notify||!(pw->p_flag&P_NOTIFY)||pw->p_env); pw=pw->p_nxtproc);
+ if(pw)
+ return(pw);
+ if(pwtop->p_job == job.curjobid)
+ return(0);
+ /* all processes complete, unpost job */
+ job_unlink(pwtop);
+ for(pw=pwtop; pw; pw=pw->p_nxtproc)
+ {
+ if(pw && pw->p_exitval)
+ *pw->p_exitval = pw->p_exit;
+ /* save the exit status for background jobs */
+ if((pw->p_flag&P_EXITSAVE) || pw->p_pid==sh.spid)
+ {
+ struct jobsave *jp;
+ /* save status for future wait */
+ if(jp = jobsave_create(pw->p_pid))
+ {
+ jp->exitval = pw->p_exit;
+ if(pw->p_flag&P_SIGNALLED)
+ jp->exitval |= SH_EXITSIG;
+ }
+ pw->p_flag &= ~P_EXITSAVE;
+ }
+ pw->p_flag &= ~P_DONE;
+ job.numpost--;
+ pw->p_nxtjob = freelist;
+ freelist = pw;
+ }
+ pwtop->p_pid = 0;
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: free pid=%d critical=%d job=%d\n",__LINE__,getpid(),job.in_critical,pwtop->p_job);
+ sfsync(sfstderr);
+#endif /* DEBUG */
+ job_free((int)pwtop->p_job);
+ return((struct process*)0);
+}
+
+/*
+ * unlink a job form the job list
+ */
+static void job_unlink(register struct process *pw)
+{
+ register struct process *px;
+ if(pw==job.pwlist)
+ {
+ job.pwlist = pw->p_nxtjob;
+ job.curpgid = 0;
+ return;
+ }
+ for(px=job.pwlist;px;px=px->p_nxtjob)
+ if(px->p_nxtjob == pw)
+ {
+ px->p_nxtjob = pw->p_nxtjob;
+ return;
+ }
+}
+
+/*
+ * get an unused job number
+ * freejobs is a bit vector, 0 is unused
+ */
+
+static int job_alloc(void)
+{
+ register int j=0;
+ register unsigned mask = 1;
+ register unsigned char *freeword;
+ register int jmax = BYTE(shgd->lim.child_max);
+ /* skip to first word with a free slot */
+ for(j=0;job.freejobs[j] == UCHAR_MAX; j++);
+ if(j >= jmax)
+ {
+ register struct process *pw;
+ for(j=1; j < shgd->lim.child_max; j++)
+ {
+ if((pw=job_byjid(j))&& !job_unpost(pw,0))
+ break;
+ }
+ j /= CHAR_BIT;
+ if(j >= jmax)
+ return(-1);
+ }
+ freeword = &job.freejobs[j];
+ j *= CHAR_BIT;
+ for(j++;mask&(*freeword);j++,mask <<=1);
+ *freeword |= mask;
+ return(j);
+}
+
+/*
+ * return a job number
+ */
+
+static void job_free(register int n)
+{
+ register int j = (--n)/CHAR_BIT;
+ register unsigned mask;
+ n -= j*CHAR_BIT;
+ mask = 1 << n;
+ job.freejobs[j] &= ~mask;
+}
+
+static char *job_sigmsg(int sig)
+{
+ static char signo[40];
+#ifdef apollo
+ /*
+ * This code handles the formatting for the apollo specific signal
+ * SIGAPOLLO.
+ */
+ extern char *apollo_error(void);
+
+ if ( sig == SIGAPOLLO )
+ return( apollo_error() );
+#endif /* apollo */
+ if(sig<=shgd->sigmax && shgd->sigmsg[sig])
+ return(shgd->sigmsg[sig]);
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+ if(sig>=sh.gd->sigruntime[SH_SIGRTMIN] && sig<=sh.gd->sigruntime[SH_SIGRTMAX])
+ {
+ static char sigrt[20];
+ if(sig>sh.gd->sigruntime[SH_SIGRTMIN]+(sh.gd->sigruntime[SH_SIGRTMAX]-sig<=sh.gd->sigruntime[SH_SIGRTMIN])/2)
+ sfsprintf(sigrt,sizeof(sigrt),"SIGRTMAX-%d",sh.gd->sigruntime[SH_SIGRTMAX]-sig);
+ else
+ sfsprintf(sigrt,sizeof(sigrt),"SIGRTMIN+%d",sig-sh.gd->sigruntime[SH_SIGRTMIN]);
+ return(sigrt);
+ }
+#endif
+ sfsprintf(signo,sizeof(signo),sh_translate(e_signo),sig);
+ return(signo);
+}
+
+/*
+ * see whether exit status has been saved and delete it
+ * if pid==0, then oldest saved process is deleted
+ * If pid is not found a -1 is returned.
+ */
+static int job_chksave(register pid_t pid)
+{
+ register struct jobsave *jp = bck.list, *jpold=0;
+ register int r= -1;
+ register int count=bck.count;
+ struct back_save *bp= &bck;
+again:
+ while(jp && count-->0)
+ {
+ if(jp->pid==pid)
+ break;
+ if(pid==0 && !jp->next)
+ break;
+ jpold = jp;
+ jp = jp->next;
+ }
+ if(!jp && pid && (bp=bp->prev))
+ {
+ count = bp->count;
+ jp = bp->list;
+ goto again;
+ }
+ if(jp)
+ {
+ r = 0;
+ if(pid)
+ r = jp->exitval;
+ if(jpold)
+ jpold->next = jp->next;
+ else
+ bp->list = jp->next;
+ bp->count--;
+ if(njob_savelist < NJOB_SAVELIST)
+ {
+ njob_savelist++;
+ jp->next = job_savelist;
+ job_savelist = jp;
+ }
+ else
+ free((void*)jp);
+ }
+ return(r);
+}
+
+void *job_subsave(void)
+{
+ struct back_save *bp = new_of(struct back_save,0);
+ job_lock();
+ *bp = bck;
+ bp->prev = bck.prev;
+ bck.count = 0;
+ bck.list = 0;
+ bck.prev = bp;
+ job_unlock();
+ return((void*)bp);
+}
+
+void job_subrestore(void* ptr)
+{
+ register struct jobsave *jp, *jpnext;
+ register struct back_save *bp = (struct back_save*)ptr;
+ register struct process *pw, *px, *pwnext;
+ struct jobsave *end=NULL;
+ job_lock();
+ for(jp=bck.list; jp; jp=jp->next)
+ {
+ if (!jp->next)
+ end = jp;
+ }
+ if(end)
+ end->next = bp->list;
+ else
+ bck.list = bp->list;
+ bck.count += bp->count;
+ bck.prev = bp->prev;
+ while(bck.count > shgd->lim.child_max)
+ job_chksave(0);
+ for(pw=job.pwlist; pw; pw=pwnext)
+ {
+ pwnext = pw->p_nxtjob;
+ if(pw->p_env != sh.curenv || pw->p_pid==sh.pipepid)
+ continue;
+ for(px=pw; px; px=px->p_nxtproc)
+ px->p_flag |= P_DONE;
+ job_unpost(pw,0);
+ }
+
+ free((void*)bp);
+ job_unlock();
+}
+
+int sh_waitsafe(void)
+{
+ return(job.waitsafe);
+}
+
+void job_fork(pid_t parent)
+{
+#ifdef DEBUG
+ sfprintf(sfstderr,"ksh: job line %4d: fork pid=%d critical=%d parent=%d\n",__LINE__,getpid(),job.in_critical,parent);
+#endif /* DEBUG */
+ switch (parent)
+ {
+ case -1:
+ job_lock();
+ jobfork++;
+ break;
+ case 0:
+ jobfork=0;
+ job_unlock();
+ job.waitsafe = 0;
+ job.in_critical = 0;
+ break;
+ default:
+ jobfork=0;
+ job_unlock();
+ break;
+ }
+}
+
diff --git a/src/cmd/ksh93/sh/lex.c b/src/cmd/ksh93/sh/lex.c
new file mode 100644
index 0000000..cbefd16
--- /dev/null
+++ b/src/cmd/ksh93/sh/lex.c
@@ -0,0 +1,2516 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * KornShell lexical analyzer
+ *
+ * Written by David Korn
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <stak.h>
+#include <fcin.h>
+#include <nval.h>
+#include "FEATURE/options"
+
+#if KSHELL
+# include "defs.h"
+#else
+# include <shell.h>
+# define nv_getval(np) ((np)->nvalue)
+ Shell_t sh = {1};
+#endif /* KSHELL */
+
+#include "argnod.h"
+#include "test.h"
+#include "lexstates.h"
+#include "io.h"
+
+#define TEST_RE 3
+#define SYNBAD 3 /* exit value for syntax errors */
+#define STACK_ARRAY 3 /* size of depth match stack growth */
+
+#if _lib_iswblank < 0 /* set in lexstates.h to enable this code */
+
+int
+local_iswblank(wchar_t wc)
+{
+ static int initialized;
+ static wctype_t wt;
+
+ if (!initialized)
+ {
+ initialized = 1;
+ wt = wctype("blank");
+ }
+ return(iswctype(wc, wt));
+}
+
+#endif
+
+/*
+ * This structure allows for arbitrary depth nesting of (...), {...}, [...]
+ */
+struct lexstate
+{
+ char incase; /* 1 for case pattern, 2 after case */
+ char intest; /* 1 inside [[...]] */
+ char testop1; /* 1 when unary test op legal */
+ char testop2; /* 1 when binary test op legal */
+ char reservok; /* >0 for reserved word legal */
+ char skipword; /* next word can't be reserved */
+ char last_quote; /* last multi-line quote character */
+ char nestedbrace; /* ${var op {...}} */
+};
+
+struct lexdata
+{
+ char nocopy;
+ char paren;
+ char dolparen;
+ char nest;
+ char docword;
+ char nested_tilde;
+ char *docend;
+ char noarg;
+ char balance;
+ char warn;
+ char message;
+ char arith;
+ char *first;
+ int level;
+ int lastc;
+ int lex_max;
+ int *lex_match;
+ int lex_state;
+ int docextra;
+#if SHOPT_KIA
+ off_t kiaoff;
+#endif
+};
+
+#define _SHLEX_PRIVATE \
+ struct lexdata lexd; \
+ struct lexstate lex;
+
+#include "shlex.h"
+
+
+#define pushlevel(lp,c,s) ((lp->lexd.level>=lp->lexd.lex_max?stack_grow(lp):1) &&\
+ ((lp->lexd.lex_match[lp->lexd.level++]=lp->lexd.lastc),\
+ lp->lexd.lastc=(((s)<<CHAR_BIT)|(c))))
+#define oldmode(lp) (lp->lexd.lastc>>CHAR_BIT)
+#define endchar(lp) (lp->lexd.lastc&0xff)
+#define setchar(lp,c) (lp->lexd.lastc = ((lp->lexd.lastc&~0xff)|(c)))
+#define poplevel(lp) (lp->lexd.lastc=lp->lexd.lex_match[--lp->lexd.level])
+
+static char *fmttoken(Lex_t*, int, char*);
+#ifdef SF_BUFCONST
+ static int alias_exceptf(Sfio_t*, int, void*, Sfdisc_t*);
+#else
+ static int alias_exceptf(Sfio_t*, int, Sfdisc_t*);
+#endif
+static void setupalias(Lex_t*,const char*, Namval_t*);
+static int comsub(Lex_t*,int);
+static void nested_here(Lex_t*);
+static int here_copy(Lex_t*, struct ionod*);
+static int stack_grow(Lex_t*);
+static const Sfdisc_t alias_disc = { NULL, NULL, NULL, alias_exceptf, NULL };
+
+#if SHOPT_KIA
+
+static void refvar(Lex_t *lp, int type)
+{
+ register Shell_t *shp = lp->sh;
+ register Stk_t *stkp = shp->stk;
+ off_t off = (fcseek(0)-(type+1))-(lp->lexd.first?lp->lexd.first:fcfirst());
+ unsigned long r;
+ if(lp->lexd.first)
+ {
+ off = (fcseek(0)-(type+1)) - lp->lexd.first;
+ r=kiaentity(lp,lp->lexd.first+lp->lexd.kiaoff+type,off-lp->lexd.kiaoff,'v',-1,-1,lp->current,'v',0,"");
+ }
+ else
+ {
+ int n,offset = stktell(stkp);
+ char *savptr,*begin;
+ off = offset + (fcseek(0)-(type+1)) - fcfirst();
+ if(lp->lexd.kiaoff < offset)
+ {
+ /* variable starts on stak, copy remainder */
+ if(off>offset)
+ sfwrite(stkp,fcfirst()+type,off-offset);
+ n = stktell(stkp)-lp->lexd.kiaoff;
+ begin = stkptr(stkp,lp->lexd.kiaoff);
+ }
+ else
+ {
+ /* variable in data buffer */
+ begin = fcfirst()+(type+lp->lexd.kiaoff-offset);
+ n = off-lp->lexd.kiaoff;
+ }
+ savptr = stkfreeze(stkp,0);
+ r=kiaentity(lp,begin,n,'v',-1,-1,lp->current,'v',0,"");
+ stkset(stkp,savptr,offset);
+ }
+ sfprintf(lp->kiatmp,"p;%..64d;v;%..64d;%d;%d;r;\n",lp->current,r,shp->inlineno,shp->inlineno);
+}
+#endif /* SHOPT_KIA */
+
+/*
+ * This routine gets called when reading across a buffer boundary
+ * If lexd.nocopy is off, then current token is saved on the stack
+ */
+static void lex_advance(Sfio_t *iop, const char *buff, register int size, void *context)
+{
+ register Lex_t *lp = (Lex_t*)context;
+ register Shell_t *shp = lp->sh;
+ register Sfio_t *log= shp->funlog;
+ Stk_t *stkp = shp->stk;
+#if KSHELL
+ /* write to history file and to stderr if necessary */
+ if(iop && !sfstacked(iop))
+ {
+ if(sh_isstate(SH_HISTORY) && shp->gd->hist_ptr)
+ log = shp->gd->hist_ptr->histfp;
+ sfwrite(log, (void*)buff, size);
+ if(sh_isstate(SH_VERBOSE))
+ sfwrite(sfstderr, buff, size);
+ }
+#endif
+ if(lp->lexd.nocopy)
+ return;
+ if(lp->lexd.dolparen && lp->lexd.docword && lp->lexd.docend)
+ {
+ int n = size - (lp->lexd.docend-(char*)buff);
+ sfwrite(shp->strbuf,lp->lexd.docend,n);
+ lp->lexd.docextra += n;
+ if(sffileno(iop)>=0)
+ lp->lexd.docend = sfsetbuf(iop,(Void_t*)iop,0);
+ else
+ lp->lexd.docend = fcfirst();
+ }
+ if(lp->lexd.first)
+ {
+ size -= (lp->lexd.first-(char*)buff);
+ buff = lp->lexd.first;
+ if(!lp->lexd.noarg)
+ lp->arg = (struct argnod*)stkseek(stkp,ARGVAL);
+#if SHOPT_KIA
+ lp->lexd.kiaoff += ARGVAL;
+#endif /* SHOPT_KIA */
+ }
+ if(size>0 && (lp->arg||lp->lexd.noarg))
+ {
+ sfwrite(stkp,buff,size);
+ lp->lexd.first = 0;
+ }
+}
+
+/*
+ * fill up another input buffer
+ * preserves lexical state
+ */
+static int lexfill(Lex_t *lp)
+{
+ register int c;
+ Lex_t savelex;
+ struct argnod *ap;
+ int aok,docextra;
+ savelex = *lp;
+ ap = lp->arg;
+ c = fcfill();
+ if(ap)
+ lp->arg = ap;
+ docextra = lp->lexd.docextra;
+ lp->lex = savelex.lex;
+ lp->lexd = savelex.lexd;
+ if(fcfile() || c)
+ lp->lexd.first = 0;
+ aok= lp->aliasok;
+ ap = lp->arg;
+ memcpy(lp, &savelex, offsetof(Lex_t,lexd));
+ lp->arg = ap;
+ lp->aliasok = aok;
+ if(lp->lexd.docword && docextra)
+ {
+ lp->lexd.docextra = docextra;
+ lp->lexd.docend = fcseek(0)-1;
+ }
+ return(c);
+}
+
+/*
+ * mode=1 for reinitialization
+ */
+Lex_t *sh_lexopen(Lex_t *lp, Shell_t *sp, int mode)
+{
+ if(!lp)
+ {
+ lp = (Lex_t*)newof(0,Lex_t,1,0);
+ lp->sh = sp;
+ }
+ fcnotify(lex_advance,lp);
+ lp->lex.intest = lp->lex.incase = lp->lex.skipword = lp->lexd.warn = 0;
+ lp->comp_assign = 0;
+ lp->lex.reservok = 1;
+ if(!sh_isoption(SH_DICTIONARY) && sh_isoption(SH_NOEXEC))
+ lp->lexd.warn=1;
+ if(!mode)
+ {
+ lp->lexd.noarg = lp->lexd.level= lp->lexd.dolparen = lp->lexd.balance = 0;
+ lp->lexd.nocopy = lp->lexd.docword = lp->lexd.nest = lp->lexd.paren = 0;
+ lp->lexd.lex_state = lp->lexd.lastc=0;
+ lp->lexd.docend = 0;
+ lp->lexd.nested_tilde = 0;
+ }
+ lp->comsub = 0;
+ return(lp);
+}
+
+#ifdef DBUG
+extern int lextoken(Lex_t*);
+int sh_lex(Lex_t *lp)
+{
+ Shell_t *shp = lp->sh;
+ register int flag;
+ char *quoted, *macro, *split, *expand;
+ char tokstr[3];
+ register int tok = lextoken(lp);
+ quoted = macro = split = expand = "";
+ if(tok==0 && (flag=lp->arg->argflag))
+ {
+ if(flag&ARG_MAC)
+ macro = "macro:";
+ if(flag&ARG_EXP)
+ expand = "expand:";
+ if(flag&ARG_QUOTED)
+ quoted = "quoted:";
+ }
+ sfprintf(sfstderr,"%d: line %d: %o:%s%s%s%s %s\n",getpid(),shp->inlineno,tok,quoted,
+ macro, split, expand, fmttoken(lp,tok,tokstr));
+ return(tok);
+}
+#define sh_lex lextoken
+#endif
+
+/*
+ * Get the next word and put it on the top of the stak
+ * A pointer to the current word is stored in lp->arg
+ * Returns the token type
+ */
+int sh_lex(Lex_t* lp)
+{
+ register Shell_t *shp = lp->sh;
+ register const char *state;
+ register int n, c, mode=ST_BEGIN, wordflags=0;
+ Stk_t *stkp = shp->stk;
+ int inlevel=lp->lexd.level, assignment=0, ingrave=0;
+ Sfio_t *sp;
+#if SHOPT_MULTIBYTE
+ LEN=1;
+#endif /* SHOPT_MULTIBYTE */
+ if(lp->lexd.paren)
+ {
+ lp->lexd.paren = 0;
+ return(lp->token=LPAREN);
+ }
+ if(lp->lex.incase)
+ lp->assignok = 0;
+ else
+ lp->assignok |= lp->lex.reservok;
+ if(lp->comp_assign==2)
+ lp->comp_assign = lp->lex.reservok = 0;
+ lp->lexd.arith = (lp->lexd.nest==1);
+ if(lp->lexd.nest)
+ {
+ pushlevel(lp,lp->lexd.nest,ST_NONE);
+ lp->lexd.nest = 0;
+ mode = lp->lexd.lex_state;
+ }
+ else if(lp->lexd.docword)
+ {
+ if(fcgetc(c)=='-' || c=='#')
+ {
+ lp->lexd.docword++;
+ lp->digits=(c=='#'?3:1);
+ }
+ else if(c=='<')
+ {
+ lp->digits=2;
+ lp->lexd.docword=0;
+ }
+ else if(c>0)
+ fcseek(-LEN);
+ }
+ if(!lp->lexd.dolparen)
+ {
+ lp->arg = 0;
+ if(mode!=ST_BEGIN)
+ lp->lexd.first = fcseek(0);
+ else
+ lp->lexd.first = 0;
+ }
+ lp->lastline = lp->sh->inlineno;
+ if(lp->noreserv)
+ lp->lex.reservok = 0;
+ while(1)
+ {
+ /* skip over characters in the current state */
+ state = sh_lexstates[mode];
+ while((n=STATE(state,c))==0);
+ switch(n)
+ {
+ case S_BREAK:
+ fcseek(-LEN);
+ goto breakloop;
+ case S_EOF:
+ sp = fcfile();
+ if((n=lexfill(lp)) > 0)
+ {
+ fcseek(-1);
+ continue;
+ }
+ /* check for zero byte in file */
+ if(n==0 && fcfile())
+ {
+ if(shp->readscript)
+ {
+ char *cp = error_info.id;
+ errno = ENOEXEC;
+ error_info.id = shp->readscript;
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,cp);
+ }
+ else
+ {
+ lp->token = -1;
+ sh_syntax(lp);
+ }
+ }
+ /* end-of-file */
+ if(mode==ST_BEGIN)
+ return(lp->token=EOFSYM);
+ if(mode >ST_NORM && lp->lexd.level>0)
+ {
+ switch(c=endchar(lp))
+ {
+ case '$':
+ if(mode==ST_LIT)
+ {
+ c = '\'';
+ break;
+ }
+ mode = oldmode(lp);
+ poplevel(lp);
+ continue;
+ case RBRACT:
+ c = LBRACT;
+ break;
+ case 1: /* for ((...)) */
+ case RPAREN:
+ c = LPAREN;
+ break;
+ default:
+ c = LBRACE;
+ break;
+ case '"': case '`': case '\'':
+ lp->lexd.balance = c;
+ break;
+ }
+ if(sp && !(sfset(sp,0,0)&SF_STRING))
+ {
+ lp->lasttok = c;
+ lp->token = EOFSYM;
+ sh_syntax(lp);
+ }
+ lp->lexd.balance = c;
+ }
+ goto breakloop;
+ case S_COM:
+ /* skip one or more comment line(s) */
+ lp->lex.reservok = !lp->lex.intest;
+ if((n=lp->lexd.nocopy) && lp->lexd.dolparen)
+ lp->lexd.nocopy--;
+ do
+ {
+ while(fcgetc(c)>0 && c!='\n');
+ if(c<=0 || lp->heredoc)
+ {
+ shp->inlineno++;
+ break;
+ }
+ while(shp->inlineno++,fcpeek(0)=='\n')
+ fcseek(1);
+ while(state[c=fcpeek(0)]==0)
+ fcseek(1);
+ }
+ while(c=='#');
+ lp->lexd.nocopy = n;
+ if(c<0)
+ return(lp->token=EOFSYM);
+ n = S_NLTOK;
+ shp->inlineno--;
+ /* FALL THRU */
+ case S_NLTOK:
+ /* check for here-document */
+ if(lp->heredoc)
+ {
+ if(!lp->lexd.dolparen)
+ lp->lexd.nocopy++;
+ c = shp->inlineno;
+ if(here_copy(lp,lp->heredoc)<=0 && lp->lasttok)
+ {
+ lp->lasttok = IODOCSYM;
+ lp->token = EOFSYM;
+ lp->lastline = c;
+ sh_syntax(lp);
+ }
+ if(!lp->lexd.dolparen)
+ lp->lexd.nocopy--;
+ lp->heredoc = 0;
+ }
+ lp->lex.reservok = !lp->lex.intest;
+ lp->lex.skipword = 0;
+ /* FALL THRU */
+ case S_NL:
+ /* skip over new-lines */
+ lp->lex.last_quote = 0;
+ while(shp->inlineno++,fcget()=='\n');
+ fcseek(-LEN);
+ if(n==S_NLTOK)
+ {
+ lp->comp_assign = 0;
+ return(lp->token='\n');
+ }
+ case S_BLNK:
+ if(lp->lex.incase<=TEST_RE)
+ continue;
+ /* implicit RPAREN for =~ test operator */
+ if(inlevel+1==lp->lexd.level)
+ {
+ if(lp->lex.intest)
+ fcseek(-LEN);
+ c = RPAREN;
+ goto do_pop;
+ }
+ continue;
+ case S_OP:
+ /* return operator token */
+ if(c=='<' || c=='>')
+ {
+ if(lp->lex.testop2)
+ lp->lex.testop2 = 0;
+ else
+ {
+ lp->digits = (c=='>');
+ lp->lex.skipword = 1;
+ lp->aliasok = lp->lex.reservok;
+ lp->lex.reservok = 0;
+ }
+ }
+ else
+ {
+ lp->lex.reservok = !lp->lex.intest;
+ if(c==RPAREN)
+ {
+ if(!lp->lexd.dolparen)
+ lp->lex.incase = 0;
+ return(lp->token=c);
+ }
+ lp->lex.testop1 = lp->lex.intest;
+ }
+ if(fcgetc(n)>0)
+ fcseek(-LEN);
+ if(state[n]==S_OP || n=='#')
+ {
+ if(n==c)
+ {
+ if(c=='<')
+ lp->lexd.docword=1;
+ else if(n==LPAREN)
+ {
+ if(lp->lex.intest)
+ return(c);
+ lp->lexd.nest=1;
+ lp->lastline = shp->inlineno;
+ lp->lexd.lex_state = ST_NESTED;
+ fcseek(1);
+ return(sh_lex(lp));
+ }
+ c |= SYMREP;
+ }
+ else if(c=='(' || c==')')
+ return(lp->token=c);
+ else if(c=='&')
+ {
+ if(!sh_isoption(SH_POSIX) && n=='>' && (sh_isoption(SH_BASH) || sh_isstate(SH_PROFILE)))
+ {
+ if(!sh_isoption(SH_BASH) && !lp->nonstandard)
+ {
+ lp->nonstandard = 1;
+ errormsg(SH_DICT,ERROR_warn(0),e_lexnonstandard,shp->inlineno);
+ }
+ lp->digits = -1;
+ c = '>';
+ }
+ else if(n=='|')
+ c |= SYMPIPE;
+ else
+ n = 0;
+ }
+ else if(n=='&')
+ c |= SYMAMP;
+ else if(c!='<' && c!='>')
+ n = 0;
+ else if(n==LPAREN)
+ {
+ c |= SYMLPAR;
+ lp->lex.reservok = 1;
+ lp->lex.skipword = 0;
+ }
+ else if(n=='|')
+ c |= SYMPIPE;
+ else if(c=='<' && n=='>')
+ {
+ lp->digits = 1;
+ c = IORDWRSYM;
+ fcgetc(n);
+ if(fcgetc(n)==';')
+ {
+ lp->token = c = IORDWRSYMT;
+ if(lp->inexec)
+ sh_syntax(lp);
+ }
+ else if(n>0)
+ fcseek(-LEN);
+ n= 0;
+ }
+ else if(n=='#' && (c=='<'||c=='>'))
+ c |= SYMSHARP;
+ else if(n==';' && c=='>')
+ {
+ c |= SYMSEMI;
+ if(lp->inexec)
+ {
+ lp->token = c;
+ sh_syntax(lp);
+ }
+ }
+ else
+ n = 0;
+ if(n)
+ {
+ fcseek(1);
+ lp->lex.incase = (c==BREAKCASESYM || c==FALLTHRUSYM);
+ }
+ else
+ {
+ if(lp->lexd.warn && (n=fcpeek(0))!=RPAREN && n!=' ' && n!='\t')
+ errormsg(SH_DICT,ERROR_warn(0),e_lexspace,shp->inlineno,c,n);
+ }
+ }
+ if(c==LPAREN && lp->comp_assign && !lp->lex.intest && !lp->lex.incase)
+ lp->comp_assign = 2;
+ else
+ lp->comp_assign = 0;
+ return(lp->token=c);
+ case S_ESC:
+ /* check for \<new-line> */
+ fcgetc(n);
+ c=2;
+#if SHOPT_CRNL
+ if(n=='\r')
+ {
+ if(fcgetc(n)=='\n')
+ c=3;
+ else
+ {
+ n='\r';
+ fcseek(-LEN);
+ }
+ }
+#endif /* SHOPT_CRNL */
+ if(n=='\n')
+ {
+ Sfio_t *sp;
+ struct argnod *ap;
+ shp->inlineno++;
+ /* synchronize */
+ if(!(sp=fcfile()))
+ state=fcseek(0);
+ fcclose();
+ ap = lp->arg;
+ if(sp)
+ fcfopen(sp);
+ else
+ fcsopen((char*)state);
+ /* remove \new-line */
+ n = stktell(stkp)-c;
+ stkseek(stkp,n);
+ lp->arg = ap;
+ if(n<=ARGVAL)
+ {
+ mode = 0;
+ lp->lexd.first = 0;
+ }
+ continue;
+ }
+ wordflags |= ARG_QUOTED;
+ if(mode==ST_DOL)
+ goto err;
+#ifndef STR_MAXIMAL
+ else if(mode==ST_NESTED && lp->lexd.warn &&
+ endchar(lp)==RBRACE &&
+ sh_lexstates[ST_DOL][n]==S_DIG
+ )
+ errormsg(SH_DICT,ERROR_warn(0),e_lexfuture,shp->inlineno,n);
+#endif /* STR_MAXIMAL */
+ break;
+ case S_NAME:
+ if(!lp->lex.skipword)
+ lp->lex.reservok *= 2;
+ /* FALL THRU */
+ case S_TILDE:
+ if(c=='~' && mode==ST_NESTED)
+ {
+ if(endchar(lp)==RBRACE)
+ {
+ lp->lexd.nested_tilde++;
+ goto tilde;
+ }
+ continue;
+ }
+ case S_RES:
+ if(!lp->lexd.dolparen)
+ lp->lexd.first = fcseek(0)-LEN;
+ else if(lp->lexd.docword)
+ lp->lexd.docend = fcseek(0)-LEN;
+ mode = ST_NAME;
+ if(c=='.')
+ fcseek(-LEN);
+ if(n!=S_TILDE)
+ continue;
+ tilde:
+ fcgetc(n);
+ if(n>0)
+ {
+ if(c=='~' && n==LPAREN)
+ {
+ if(lp->lexd.nested_tilde)
+ lp->lexd.nested_tilde++;
+ else if(lp->lex.incase)
+ lp->lex.incase = TEST_RE;
+ }
+ fcseek(-LEN);
+ if(lp->lexd.nested_tilde)
+ {
+ lp->lexd.nested_tilde--;
+ continue;
+ }
+ }
+ if(n==LPAREN)
+ goto epat;
+ wordflags = ARG_MAC;
+ mode = ST_NORM;
+ continue;
+ case S_REG:
+ if(mode==ST_BEGIN)
+ {
+ do_reg:
+ /* skip new-line joining */
+ if(c=='\\' && fcpeek(0)=='\n')
+ {
+ shp->inlineno++;
+ fcseek(1);
+ continue;
+ }
+ fcseek(-LEN);
+ if(!lp->lexd.dolparen)
+ lp->lexd.first = fcseek(0);
+ else if(lp->lexd.docword)
+ lp->lexd.docend = fcseek(0);
+ if(c=='[' && lp->assignok>=SH_ASSIGN)
+ {
+ mode = ST_NAME;
+ continue;
+ }
+ }
+ mode = ST_NORM;
+ continue;
+ case S_LIT:
+ if(oldmode(lp)==ST_NONE && !lp->lexd.noarg) /* in ((...)) */
+ {
+ if((c=fcpeek(0))==LPAREN || c==RPAREN || c=='$' || c==LBRACE || c==RBRACE || c=='[' || c==']')
+ {
+ if(fcpeek(1)=='\'')
+ fcseek(2);
+ }
+ continue;
+ }
+ wordflags |= ARG_QUOTED;
+ if(mode==ST_DOL)
+ {
+ if(endchar(lp)!='$')
+ goto err;
+ if(oldmode(lp)==ST_QUOTE) /* $' within "" or `` */
+ {
+ if(lp->lexd.warn)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexslash,shp->inlineno);
+ mode = ST_LIT;
+ }
+ }
+ if(mode!=ST_LIT)
+ {
+ if(lp->lexd.warn && lp->lex.last_quote && shp->inlineno > lp->lastline && fcpeek(-2)!='$')
+ errormsg(SH_DICT,ERROR_warn(0),e_lexlongquote,lp->lastline,lp->lex.last_quote);
+ lp->lex.last_quote = 0;
+ lp->lastline = shp->inlineno;
+ if(mode!=ST_DOL)
+ pushlevel(lp,'\'',mode);
+ mode = ST_LIT;
+ continue;
+ }
+ /* check for multi-line single-quoted string */
+ else if(shp->inlineno > lp->lastline)
+ lp->lex.last_quote = '\'';
+ mode = oldmode(lp);
+ poplevel(lp);
+ break;
+ case S_ESC2:
+ /* \ inside '' */
+ if(endchar(lp)=='$')
+ {
+ fcgetc(n);
+ if(n=='\n')
+ shp->inlineno++;
+ }
+ continue;
+ case S_GRAVE:
+ if(lp->lexd.warn && (mode!=ST_QUOTE || endchar(lp)!='`'))
+ errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete1,shp->inlineno);
+ wordflags |=(ARG_MAC|ARG_EXP);
+ if(mode==ST_QUOTE)
+ ingrave = !ingrave;
+ /* FALL THRU */
+ case S_QUOTE:
+ if(oldmode(lp)==ST_NONE && lp->lexd.arith) /* in ((...)) */
+ {
+ if(n!=S_GRAVE || fcpeek(0)=='\'')
+ continue;
+ }
+ if(n==S_QUOTE)
+ wordflags |=ARG_QUOTED;
+ if(mode!=ST_QUOTE)
+ {
+ if(c!='"' || mode!=ST_QNEST)
+ {
+ if(lp->lexd.warn && lp->lex.last_quote && shp->inlineno > lp->lastline)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexlongquote,lp->lastline,lp->lex.last_quote);
+ lp->lex.last_quote=0;
+ lp->lastline = shp->inlineno;
+ pushlevel(lp,c,mode);
+ }
+ ingrave ^= (c=='`');
+ mode = ST_QUOTE;
+ continue;
+ }
+ else if((n=endchar(lp))==c)
+ {
+ if(shp->inlineno > lp->lastline)
+ lp->lex.last_quote = c;
+ mode = oldmode(lp);
+ poplevel(lp);
+ }
+ else if(c=='"' && n==RBRACE)
+ mode = ST_QNEST;
+ break;
+ case S_DOL:
+ /* don't check syntax inside `` */
+ if(mode==ST_QUOTE && ingrave)
+ continue;
+#if SHOPT_KIA
+ if(lp->lexd.first)
+ lp->lexd.kiaoff = fcseek(0)-lp->lexd.first;
+ else
+ lp->lexd.kiaoff = stktell(stkp)+fcseek(0)-fcfirst();
+#endif /* SHOPT_KIA */
+ pushlevel(lp,'$',mode);
+ mode = ST_DOL;
+ continue;
+ case S_PAR:
+ do_comsub:
+ wordflags |= ARG_MAC;
+ mode = oldmode(lp);
+ poplevel(lp);
+ fcseek(-LEN);
+ wordflags |= comsub(lp,c);
+ continue;
+ case S_RBRA:
+ if((n=endchar(lp)) == '$')
+ goto err;
+ if(mode!=ST_QUOTE || n==RBRACE)
+ {
+ mode = oldmode(lp);
+ poplevel(lp);
+ }
+ break;
+ case S_EDOL:
+ /* end $identifier */
+#if SHOPT_KIA
+ if(lp->kiafile)
+ refvar(lp,0);
+#endif /* SHOPT_KIA */
+ if(lp->lexd.warn && c==LBRACT && !lp->lex.intest && !lp->lexd.arith && oldmode(lp)!= ST_NESTED)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexusebrace,shp->inlineno);
+ fcseek(-LEN);
+ mode = oldmode(lp);
+ poplevel(lp);
+ break;
+ case S_DOT:
+ /* make sure next character is alpha */
+ if(fcgetc(n)>0)
+ {
+ if(n=='.')
+ fcgetc(n);
+ if(n>0)
+ fcseek(-LEN);
+ }
+ if(isaletter(n) || n==LBRACT)
+ continue;
+ if(mode==ST_NAME)
+ {
+ if(n=='=')
+ continue;
+ break;
+ }
+ else if(n==RBRACE)
+ continue;
+ if(isastchar(n))
+ continue;
+ goto err;
+ case S_SPC1:
+ wordflags |= ARG_MAC;
+ if(endchar(lp)==RBRACE)
+ {
+ setchar(lp,c);
+ continue;
+ }
+ /* FALL THRU */
+ case S_ALP:
+ if(c=='.' && endchar(lp)=='$')
+ goto err;
+ case S_SPC2:
+ case S_DIG:
+ wordflags |= ARG_MAC;
+ switch(endchar(lp))
+ {
+ case '$':
+ if(n==S_ALP) /* $identifier */
+ mode = ST_DOLNAME;
+ else
+ {
+ mode = oldmode(lp);
+ poplevel(lp);
+ }
+ break;
+#if SHOPT_TYPEDEF
+ case '@':
+#endif /* SHOPT_TYPEDEF */
+ case '!':
+ if(n!=S_ALP)
+ goto dolerr;
+ case '#':
+ if(c=='#')
+ n = S_ALP;
+ case RBRACE:
+ if(n==S_ALP)
+ {
+ setchar(lp,RBRACE);
+ if(c=='.')
+ fcseek(-LEN);
+ mode = ST_BRACE;
+ }
+ else
+ {
+ if(fcgetc(c)>0)
+ fcseek(-LEN);
+ if(state[c]==S_ALP)
+ goto err;
+ if(n==S_DIG)
+ setchar(lp,'0');
+ else
+ setchar(lp,'!');
+ }
+ break;
+ case '0':
+ if(n==S_DIG)
+ break;
+ default:
+ goto dolerr;
+ }
+ break;
+ dolerr:
+ case S_ERR:
+ if((n=endchar(lp)) == '$')
+ goto err;
+ if(c=='*' || (n=sh_lexstates[ST_BRACE][c])!=S_MOD1 && n!=S_MOD2)
+ {
+ /* see whether inside `...` */
+ mode = oldmode(lp);
+ poplevel(lp);
+ if((n = endchar(lp)) != '`')
+ goto err;
+ pushlevel(lp,RBRACE,mode);
+ }
+ else
+ setchar(lp,RBRACE);
+ mode = ST_NESTED;
+ continue;
+ case S_MOD1:
+ if(oldmode(lp)==ST_QUOTE || oldmode(lp)==ST_NONE)
+ {
+ /* allow ' inside "${...}" */
+ if(c==':' && fcgetc(n)>0)
+ {
+ n = state[n];
+ fcseek(-LEN);
+ }
+ if(n==S_MOD1)
+ {
+ mode = ST_QUOTE;
+ continue;
+ }
+ }
+ /* FALL THRU */
+ case S_MOD2:
+#if SHOPT_KIA
+ if(lp->kiafile)
+ refvar(lp,1);
+#endif /* SHOPT_KIA */
+ if(c!=':' && fcgetc(n)>0)
+ {
+ if(n!=c)
+ c = 0;
+ if(!c || (fcgetc(n)>0))
+ {
+ fcseek(-LEN);
+ if(n==LPAREN)
+ {
+ if(c!='%')
+ {
+ lp->token = n;
+ sh_syntax(lp);
+ }
+ else if(lp->lexd.warn)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexquote,shp->inlineno,'%');
+ }
+ }
+ }
+ lp->lex.nestedbrace = 0;
+ mode = ST_NESTED;
+ continue;
+ case S_LBRA:
+ if((c=endchar(lp)) == '$')
+ {
+ if(fcgetc(c)>0)
+ fcseek(-LEN);
+ setchar(lp,RBRACE);
+ if(state[c]!=S_ERR && c!=RBRACE)
+ continue;
+ if((n=sh_lexstates[ST_BEGIN][c])==0 || n==S_OP || n==S_NLTOK)
+ {
+ c = LBRACE;
+ goto do_comsub;
+ }
+ }
+ err:
+ if(iswalpha(c))
+ continue;
+ n = endchar(lp);
+ mode = oldmode(lp);
+ poplevel(lp);
+ if(n!='$')
+ {
+ lp->token = c;
+ sh_syntax(lp);
+ }
+ else
+ {
+ if(lp->lexd.warn && c!='/' && sh_lexstates[ST_NORM][c]!=S_BREAK && (c!='"' || mode==ST_QUOTE))
+ errormsg(SH_DICT,ERROR_warn(0),e_lexslash,shp->inlineno);
+ else if(c=='"' && mode!=ST_QUOTE && !ingrave)
+ wordflags |= ARG_MESSAGE;
+ fcseek(-LEN);
+ }
+ continue;
+ case S_META:
+ if(lp->lexd.warn && endchar(lp)==RBRACE && !lp->lexd.nested_tilde)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexusequote,shp->inlineno,c);
+ continue;
+ case S_PUSH:
+ pushlevel(lp,RPAREN,mode);
+ mode = ST_NESTED;
+ continue;
+ case S_POP:
+ do_pop:
+ if(c==RBRACE && mode==ST_NESTED && lp->lex.nestedbrace)
+ {
+ lp->lex.nestedbrace--;
+ continue;
+ }
+ if(lp->lexd.level <= inlevel)
+ break;
+ if(lp->lexd.level==inlevel+1 && lp->lex.incase>=TEST_RE && !lp->lex.intest)
+ {
+ fcseek(-LEN);
+ goto breakloop;
+ }
+ n = endchar(lp);
+ if(c==RBRACT && !(n==RBRACT || n==RPAREN))
+ continue;
+ if((c==RBRACE||c==RPAREN) && n==RPAREN)
+ {
+ if(fcgetc(n)==LPAREN)
+ {
+ if(c!=RPAREN)
+ fcseek(-LEN);
+ continue;
+ }
+ if(n>0)
+ fcseek(-LEN);
+ n = RPAREN;
+ }
+ if(c==RBRACE)
+ lp->lexd.nested_tilde = 0;
+ if(c==';' && n!=';')
+ {
+ if(lp->lexd.warn && n==RBRACE)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexusequote,shp->inlineno,c);
+ continue;
+ }
+ if(mode==ST_QNEST)
+ {
+ if(lp->lexd.warn)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexescape,shp->inlineno,c);
+ continue;
+ }
+ mode = oldmode(lp);
+ poplevel(lp);
+ /* quotes in subscript need expansion */
+ if(mode==ST_NAME && (wordflags&ARG_QUOTED))
+ wordflags |= ARG_MAC;
+ /* check for ((...)) */
+ if(n==1 && c==RPAREN)
+ {
+ if(fcgetc(n)==RPAREN)
+ {
+ if(mode==ST_NONE && !lp->lexd.dolparen)
+ goto breakloop;
+ lp->lex.reservok = 1;
+ lp->lex.skipword = 0;
+ return(lp->token=EXPRSYM);
+ }
+ /* backward compatibility */
+ {
+ if(lp->lexd.warn)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexnested,shp->inlineno);
+ if(!(state=lp->lexd.first))
+ state = fcfirst();
+ else
+ {
+ n = state-fcseek(0);
+ fcseek(n);
+ }
+ lp->lexd.paren = 1;
+ }
+ return(lp->token=LPAREN);
+ }
+ if(mode==ST_NONE)
+ return(0);
+ if(c!=n)
+ {
+ lp->token = c;
+ sh_syntax(lp);
+ }
+ if(c==RBRACE && (mode==ST_NAME||mode==ST_NORM))
+ goto epat;
+ continue;
+ case S_EQ:
+ assignment = lp->assignok;
+ /* FALL THRU */
+ case S_COLON:
+ if(assignment)
+ {
+ if(fcgetc(c)=='~')
+ wordflags |= ARG_MAC;
+ else if(c!=LPAREN && assignment==SH_COMPASSIGN)
+ assignment = 0;
+ if(c!=EOF)
+ fcseek(-LEN);
+ }
+ break;
+ case S_LABEL:
+ if(lp->lex.reservok && !lp->lex.incase)
+ {
+ c = fcget();
+ fcseek(-LEN);
+ if(state[c]==S_BREAK)
+ {
+ assignment = -1;
+ goto breakloop;
+ }
+ }
+ break;
+ case S_BRACT:
+ /* check for possible subscript */
+ if((n=endchar(lp))==RBRACT || n==RPAREN ||
+ (mode==ST_BRACE) ||
+ (oldmode(lp)==ST_NONE) ||
+ (mode==ST_NAME && (lp->assignok||lp->lexd.level)))
+ {
+ if(mode==ST_NAME)
+ {
+ fcgetc(n);
+ if(n>0)
+ {
+ if(n==']')
+ errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1, shp->inlineno, "[]", "empty subscript");
+ fcseek(-LEN);
+ }
+ }
+ pushlevel(lp,RBRACT,mode);
+ wordflags |= ARG_QUOTED;
+ mode = ST_NESTED;
+ continue;
+ }
+ wordflags |= ARG_EXP;
+ break;
+ case S_BRACE:
+ {
+ int isfirst;
+ if(lp->lexd.dolparen)
+ {
+ if(mode==ST_BEGIN && (lp->lex.reservok||lp->comsub))
+ {
+ if(lp->comsub)
+ return(lp->token=c);
+ fcgetc(n);
+ if(n>0)
+ fcseek(-LEN);
+ else
+ n = '\n';
+ if(n==RBRACT || sh_lexstates[ST_NORM][n])
+ return(lp->token=c);
+ }
+ break;
+ }
+ else if(mode==ST_NESTED && endchar(lp)==RBRACE)
+ {
+ lp->lex.nestedbrace++;
+ continue;
+ }
+ else if(mode==ST_BEGIN)
+ {
+ if(lp->comsub && c==RBRACE)
+ return(lp->token=c);
+ goto do_reg;
+ }
+ isfirst = (lp->lexd.first&&fcseek(0)==lp->lexd.first+1);
+ fcgetc(n);
+ /* check for {} */
+ if(c==LBRACE && n==RBRACE)
+ break;
+ if(n>0)
+ fcseek(-LEN);
+ else if(lp->lex.reservok)
+ break;
+ /* check for reserved word { or } */
+ if(lp->lex.reservok && state[n]==S_BREAK && isfirst)
+ break;
+ if(sh_isoption(SH_BRACEEXPAND) && c==LBRACE && !assignment && state[n]!=S_BREAK
+ && !lp->lex.incase && !lp->lex.intest
+ && !lp->lex.skipword)
+ {
+ wordflags |= ARG_EXP;
+ }
+ if(c==RBRACE && n==LPAREN)
+ goto epat;
+ break;
+ }
+ case S_PAT:
+ wordflags |= ARG_EXP;
+ /* FALL THRU */
+ case S_EPAT:
+ epat:
+ if(fcgetc(n)==LPAREN && c!='[')
+ {
+ if(lp->lex.incase==TEST_RE)
+ {
+ lp->lex.incase++;
+ pushlevel(lp,RPAREN,ST_NORM);
+ mode = ST_NESTED;
+ }
+ wordflags |= ARG_EXP;
+ pushlevel(lp,RPAREN,mode);
+ mode = ST_NESTED;
+ continue;
+ }
+ if(lp->lexd.warn && c=='[' && n=='^')
+ errormsg(SH_DICT,ERROR_warn(0),e_lexcharclass,shp->inlineno);
+ if(n>0)
+ fcseek(-LEN);
+ if(n=='=' && c=='+' && mode==ST_NAME)
+ continue;
+ break;
+ }
+ lp->comp_assign = 0;
+ if(mode==ST_NAME)
+ mode = ST_NORM;
+ else if(mode==ST_NONE)
+ return(0);
+ }
+breakloop:
+ if(lp->lexd.nocopy)
+ {
+ lp->lexd.balance = 0;
+ return(0);
+ }
+ if(lp->lexd.dolparen)
+ {
+ lp->lexd.balance = 0;
+ if(lp->lexd.docword)
+ nested_here(lp);
+ lp->lexd.message = (wordflags&ARG_MESSAGE);
+ return(lp->token=0);
+ }
+ if(!(state=lp->lexd.first))
+ state = fcfirst();
+ n = fcseek(0)-(char*)state;
+ if(!lp->arg)
+ lp->arg = (struct argnod*)stkseek(stkp,ARGVAL);
+ if(n>0)
+ sfwrite(stkp,state,n);
+ /* add balancing character if necessary */
+ if(lp->lexd.balance)
+ {
+ sfputc(stkp,lp->lexd.balance);
+ lp->lexd.balance = 0;
+ }
+ sfputc(stkp,0);
+ stkseek(stkp,stktell(stkp)-1);
+ state = stkptr(stkp,ARGVAL);
+ n = stktell(stkp)-ARGVAL;
+ lp->lexd.first=0;
+ if(n==1)
+ {
+ /* check for numbered redirection */
+ n = state[0];
+ if((c=='<' || c=='>') && isadigit(n))
+ {
+ c = sh_lex(lp);
+ lp->digits = (n-'0');
+ return(c);
+ }
+ if(n==LBRACT)
+ c = 0;
+ else if(n==RBRACE && lp->comsub)
+ return(lp->token=n);
+ else if(n=='~')
+ c = ARG_MAC;
+ else
+ c = (wordflags&ARG_EXP);
+ n = 1;
+ }
+ else if(n>2 && state[0]=='{' && state[n-1]=='}' && !lp->lex.intest && !lp->lex.incase && (c=='<' || c== '>') && sh_isoption(SH_BRACEEXPAND))
+ {
+ if(!strchr(state,','))
+ {
+ stkseek(stkp,stktell(stkp)-1);
+ lp->arg = (struct argnod*)stkfreeze(stkp,1);
+ return(lp->token=IOVNAME);
+ }
+ c = wordflags;
+ }
+ else
+ c = wordflags;
+ if(assignment<0)
+ {
+ stkseek(stkp,stktell(stkp)-1);
+ lp->arg = (struct argnod*)stkfreeze(stkp,1);
+ lp->lex.reservok = 1;
+ return(lp->token=LABLSYM);
+ }
+ if(assignment || (lp->lex.intest&&!lp->lex.incase) || mode==ST_NONE)
+ c &= ~ARG_EXP;
+ if((c&ARG_EXP) && (c&ARG_QUOTED))
+ c |= ARG_MAC;
+ if(mode==ST_NONE)
+ {
+ /* eliminate trailing )) */
+ stkseek(stkp,stktell(stkp)-2);
+ }
+ if(c&ARG_MESSAGE)
+ {
+ if(sh_isoption(SH_DICTIONARY))
+ lp->arg = sh_endword(shp,2);
+ c |= ARG_MAC;
+ }
+ if(c==0 || (c&(ARG_MAC|ARG_EXP|ARG_MESSAGE)))
+ {
+ lp->arg = (struct argnod*)stkfreeze(stkp,1);
+ lp->arg->argflag = (c?c:ARG_RAW);
+ }
+ else if(mode==ST_NONE)
+ lp->arg = sh_endword(shp,-1);
+ else
+ lp->arg = sh_endword(shp,0);
+ state = lp->arg->argval;
+ lp->comp_assign = assignment;
+ if(assignment)
+ lp->arg->argflag |= ARG_ASSIGN;
+ else if(!lp->lex.skipword)
+ lp->assignok = 0;
+ lp->arg->argchn.cp = 0;
+ lp->arg->argnxt.ap = 0;
+ if(mode==ST_NONE)
+ return(lp->token=EXPRSYM);
+ if(lp->lex.intest)
+ {
+ if(lp->lex.testop1)
+ {
+ lp->lex.testop1 = 0;
+ if(n==2 && state[0]=='-' && state[2]==0 &&
+ strchr(test_opchars,state[1]))
+ {
+ if(lp->lexd.warn && state[1]=='a')
+ errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete2,shp->inlineno);
+ lp->digits = state[1];
+ lp->token = TESTUNOP;
+ }
+ else if(n==1 && state[0]=='!' && state[1]==0)
+ {
+ lp->lex.testop1 = 1;
+ lp->token = '!';
+ }
+ else
+ {
+ lp->lex.testop2 = 1;
+ lp->token = 0;
+ }
+ return(lp->token);
+ }
+ lp->lex.incase = 0;
+ c = sh_lookup(state,shtab_testops);
+ switch(c)
+ {
+ case TEST_END:
+ lp->lex.testop2 = lp->lex.intest = 0;
+ lp->lex.reservok = 1;
+ lp->token = ETESTSYM;
+ return(lp->token);
+
+ case TEST_SEQ:
+ if(lp->lexd.warn && state[1]==0)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete3,shp->inlineno);
+ /* FALL THRU */
+ default:
+ if(lp->lex.testop2)
+ {
+ if(lp->lexd.warn && (c&TEST_ARITH))
+ errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete4,shp->inlineno,state);
+ if(c&TEST_PATTERN)
+ lp->lex.incase = 1;
+ else if(c==TEST_REP)
+ lp->lex.incase = TEST_RE;
+ lp->lex.testop2 = 0;
+ lp->digits = c;
+ lp->token = TESTBINOP;
+ return(lp->token);
+ }
+
+ case TEST_OR: case TEST_AND:
+ case 0:
+ return(lp->token=0);
+ }
+ }
+ if(lp->lex.reservok /* && !lp->lex.incase*/ && n<=2)
+ {
+ /* check for {, }, ! */
+ c = state[0];
+ if(n==1 && (c=='{' || c=='}' || c=='!'))
+ {
+ if(lp->lexd.warn && c=='{' && lp->lex.incase==2)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete6,shp->inlineno);
+ if(lp->lex.incase==1 && c==RBRACE)
+ lp->lex.incase = 0;
+ return(lp->token=c);
+ }
+ else if(!lp->lex.incase && c==LBRACT && state[1]==LBRACT)
+ {
+ lp->lex.intest = lp->lex.testop1 = 1;
+ lp->lex.testop2 = lp->lex.reservok = 0;
+ return(lp->token=BTESTSYM);
+ }
+ }
+ c = 0;
+ if(!lp->lex.skipword)
+ {
+ if(n>1 && lp->lex.reservok==1 && mode==ST_NAME &&
+ (c=sh_lookup(state,shtab_reserved)))
+ {
+ if(lp->lex.incase)
+ {
+ if(lp->lex.incase >1)
+ lp->lex.incase = 1;
+ else if(c==ESACSYM)
+ lp->lex.incase = 0;
+ else
+ c = 0;
+ }
+ else if(c==FORSYM || c==CASESYM || c==SELECTSYM || c==FUNCTSYM || c==NSPACESYM)
+ {
+ lp->lex.skipword = 1;
+ lp->lex.incase = 2*(c==CASESYM);
+ }
+ else
+ lp->lex.skipword = 0;
+ if(c==INSYM)
+ lp->lex.reservok = 0;
+ else if(c==TIMESYM)
+ {
+ /* yech - POSIX requires time -p */
+ while(fcgetc(n)==' ' || n=='\t');
+ if(n>0)
+ fcseek(-LEN);
+ if(n=='-')
+ c=0;
+ }
+ return(lp->token=c);
+ }
+ if(!(wordflags&ARG_QUOTED) && (lp->lex.reservok||lp->aliasok))
+ {
+ /* check for aliases */
+ Namval_t* np;
+ if(!lp->lex.incase && !assignment && fcpeek(0)!=LPAREN &&
+ (np=nv_search(state,shp->alias_tree,HASH_SCOPE))
+ && !nv_isattr(np,NV_NOEXPAND)
+#if KSHELL
+ && (!sh_isstate(SH_NOALIAS) || nv_isattr(np,NV_NOFREE))
+#endif /* KSHELL */
+ && (state=nv_getval(np)))
+ {
+ setupalias(lp,state,np);
+ nv_onattr(np,NV_NOEXPAND);
+ lp->lex.reservok = 1;
+ lp->assignok |= lp->lex.reservok;
+ return(sh_lex(lp));
+ }
+ }
+ lp->lex.reservok = 0;
+ }
+ lp->lex.skipword = lp->lexd.docword = 0;
+ return(lp->token=c);
+}
+
+/*
+ * read to end of command substitution
+ */
+static int comsub(register Lex_t *lp, int endtok)
+{
+ register int n,c,count=1;
+ register int line=lp->sh->inlineno;
+ char *first,*cp=fcseek(0),word[5];
+ int off, messages=0, assignok=lp->assignok, csub;
+ struct lexstate save;
+ save = lp->lex;
+ csub = lp->comsub;
+ sh_lexopen(lp,lp->sh,1);
+ lp->lexd.dolparen++;
+ lp->lex.incase=0;
+ pushlevel(lp,0,0);
+ lp->comsub = (endtok==LBRACE);
+ if(first=lp->lexd.first)
+ off = cp-first;
+ else
+ off = cp-fcfirst();
+ if(off<0)
+ c=*cp, *cp=0;
+ n = sh_lex(lp);
+ if(off<0)
+ *cp = c;
+ if(n==endtok || off<0)
+ {
+ if(endtok==LPAREN && lp->lexd.paren)
+ {
+
+ if(first==lp->lexd.first)
+ {
+ n = cp+1-(char*)fcseek(0);
+ fcseek(n);
+ }
+ count++;
+ lp->lexd.paren = 0;
+ fcgetc(c);
+ }
+ while(1)
+ {
+ /* look for case and esac */
+ n=0;
+ while(1)
+ {
+ fcgetc(c);
+ /* skip leading white space */
+ if(n==0 && !sh_lexstates[ST_BEGIN][c])
+ continue;
+ if(n==4)
+ break;
+ if(sh_lexstates[ST_NAME][c])
+ goto skip;
+ word[n++] = c;
+ }
+ if(sh_lexstates[ST_NAME][c]==S_BREAK)
+ {
+ if(memcmp(word,"case",4)==0)
+ lp->lex.incase=1;
+ else if(memcmp(word,"esac",4)==0)
+ lp->lex.incase=0;
+ }
+ skip:
+ if(c && (c!='#' || n==0))
+ fcseek(-LEN);
+ if(c==RBRACE && lp->lex.incase)
+ lp->lex.incase=0;
+ c=sh_lex(lp);
+ switch(c)
+ {
+ case LBRACE:
+ if(endtok==LBRACE && !lp->lex.incase)
+ {
+ lp->comsub = 0;
+ count++;
+ }
+ break;
+ case RBRACE:
+ rbrace:
+ if(endtok==LBRACE && --count<=0)
+ goto done;
+ if(count==1)
+ lp->comsub = endtok==LBRACE;
+ break;
+ case IPROCSYM: case OPROCSYM:
+ case LPAREN:
+ if(endtok==LPAREN && !lp->lex.incase)
+ count++;
+ break;
+ case RPAREN:
+ if(lp->lex.incase)
+ lp->lex.incase=0;
+ else if(endtok==LPAREN && --count<=0)
+ goto done;
+ break;
+ case EOFSYM:
+ lp->lastline = line;
+ lp->lasttok = endtok;
+ sh_syntax(lp);
+ case IOSEEKSYM:
+ if(fcgetc(c)!='#' && c>0)
+ fcseek(-LEN);
+ break;
+ case IODOCSYM:
+ lp->lexd.docextra = 0;
+ sh_lex(lp);
+ break;
+ case 0:
+ lp->lex.reservok = 0;
+ messages |= lp->lexd.message;
+ break;
+ case ';':
+ do
+ fcgetc(c);
+ while(!sh_lexstates[ST_BEGIN][c]);
+ if(c==RBRACE && endtok==LBRACE)
+ goto rbrace;
+ if(c>0)
+ fcseek(-LEN);
+ /* fall through*/
+ default:
+ lp->lex.reservok = 1;
+ }
+ }
+ }
+done:
+ poplevel(lp);
+ lp->comsub = csub;
+ lp->lastline = line;
+ lp->lexd.dolparen--;
+ lp->lex = save;
+ lp->assignok = (endchar(lp)==RBRACT?assignok:0);
+ if(lp->heredoc)
+ errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax5,lp->sh->inlineno,lp->heredoc->ioname);
+ return(messages);
+}
+
+/*
+ * here-doc nested in $(...)
+ * allocate ionode with delimiter filled in without disturbing stak
+ */
+static void nested_here(register Lex_t *lp)
+{
+ register struct ionod *iop;
+ register int n=0,offset;
+ struct argnod *arg = lp->arg;
+ Stk_t *stkp = lp->sh->stk;
+ char *base;
+ if(offset=stktell(stkp))
+ base = stkfreeze(stkp,0);
+ if(lp->lexd.docend)
+ n = fcseek(0)-lp->lexd.docend;
+ iop = newof(0,struct ionod,1,lp->lexd.docextra+n+ARGVAL);
+ iop->iolst = lp->heredoc;
+ stkseek(stkp,ARGVAL);
+ if(lp->lexd.docextra)
+ {
+ sfseek(lp->sh->strbuf,(Sfoff_t)0, SEEK_SET);
+ sfmove(lp->sh->strbuf,stkp,lp->lexd.docextra,-1);
+ sfseek(lp->sh->strbuf,(Sfoff_t)0, SEEK_SET);
+ }
+ sfwrite(stkp,lp->lexd.docend,n);
+ lp->arg = sh_endword(lp->sh,0);
+ iop->ioname = (char*)(iop+1);
+ strcpy(iop->ioname,lp->arg->argval);
+ iop->iofile = (IODOC|IORAW);
+ if(lp->lexd.docword>1)
+ iop->iofile |= IOSTRIP;
+ lp->heredoc = iop;
+ lp->arg = arg;
+ lp->lexd.docword = 0;
+ if(offset)
+ stkset(stkp,base,offset);
+ else
+ stkseek(stkp,0);
+}
+
+/*
+ * skip to <close> character
+ * if <copy> is non,zero, then the characters are copied to the stack
+ * <state> is the initial lexical state
+ */
+void sh_lexskip(Lex_t *lp,int close, register int copy, int state)
+{
+ register char *cp;
+ lp->lexd.nest = close;
+ lp->lexd.lex_state = state;
+ lp->lexd.noarg = 1;
+ if(copy)
+ fcnotify(lex_advance,lp);
+ else
+ lp->lexd.nocopy++;
+ sh_lex(lp);
+ lp->lexd.noarg = 0;
+ if(copy)
+ {
+ fcnotify(0,lp);
+ if(!(cp=lp->lexd.first))
+ cp = fcfirst();
+ if((copy = fcseek(0)-cp) > 0)
+ sfwrite(lp->sh->stk,cp,copy);
+ }
+ else
+ lp->lexd.nocopy--;
+}
+
+#if SHOPT_CRNL
+ ssize_t _sfwrite(Sfio_t *sp, const Void_t *buff, size_t n)
+ {
+ const char *cp = (const char*)buff, *next=cp, *ep = cp + n;
+ int m=0,k;
+ while(next = (const char*)memchr(next,'\r',ep-next))
+ if(*++next=='\n')
+ {
+ if(k=next-cp-1)
+ {
+ if((k=sfwrite(sp,cp,k)) < 0)
+ return(m>0?m:-1);
+ m += k;
+ }
+ cp = next;
+ }
+ if((k=sfwrite(sp,cp,ep-cp)) < 0)
+ return(m>0?m:-1);
+ return(m+k);
+ }
+# define sfwrite _sfwrite
+#endif /* SHOPT_CRNL */
+
+/*
+ * read in here-document from script
+ * quoted here documents, and here-documents without special chars are
+ * noted with the IOQUOTE flag
+ * returns 1 for complete here-doc, 0 for EOF
+ */
+
+static int here_copy(Lex_t *lp,register struct ionod *iop)
+{
+ register const char *state;
+ register int c,n;
+ register char *bufp,*cp;
+ register Sfio_t *sp=lp->sh->heredocs, *funlog;
+ int stripcol=0,stripflg, nsave, special=0;
+ if(funlog=lp->sh->funlog)
+ {
+ if(fcfill()>0)
+ fcseek(-LEN);
+ lp->sh->funlog = 0;
+ }
+ if(iop->iolst)
+ here_copy(lp,iop->iolst);
+ iop->iooffset = sfseek(sp,(off_t)0,SEEK_END);
+ iop->iosize = 0;
+ iop->iodelim=iop->ioname;
+ /* check for and strip quoted characters in delimiter string */
+ if(stripflg=iop->iofile&IOSTRIP)
+ {
+ while(*iop->iodelim=='\t')
+ iop->iodelim++;
+ /* skip over leading tabs in document */
+ if(iop->iofile&IOLSEEK)
+ {
+ iop->iofile &= ~IOLSEEK;
+ while(fcgetc(c)=='\t' || c==' ')
+ {
+ if(c==' ')
+ stripcol++;
+ else
+ stripcol += 8 - stripcol%8;
+ }
+ }
+ else
+ while(fcgetc(c)=='\t');
+ if(c>0)
+ fcseek(-LEN);
+ }
+ if(iop->iofile&IOQUOTE)
+ state = sh_lexstates[ST_LIT];
+ else
+ state = sh_lexstates[ST_QUOTE];
+ bufp = fcseek(0);
+ n = S_NL;
+ while(1)
+ {
+ if(n!=S_NL)
+ {
+ /* skip over regular characters */
+#if SHOPT_MULTIBYTE
+ do
+ {
+ if(fcleft()< MB_LEN_MAX && mbsize(fcseek(0))<0)
+ {
+ n = S_EOF;
+ LEN = -fcleft();
+ break;
+ }
+ }
+#endif /* SHOPT_MULTIBYTE */
+
+ while((n=STATE(state,c))==0);
+ }
+ if(n==S_EOF || !(c=fcget()))
+ {
+ if(LEN < 0)
+ c = fclast()-bufp;
+ else
+ c= (fcseek(0)-1)-bufp;
+ if(!lp->lexd.dolparen && c)
+ {
+ if(n==S_ESC)
+ c--;
+ if(!lp->lexd.dolparen && (c=sfwrite(sp,bufp,c))>0)
+ iop->iosize += c;
+ }
+#if SHOPT_MULTIBYTE
+ if(LEN==0)
+ LEN=1;
+ if(LEN < 0)
+ {
+ n = LEN;
+ c = fcmbget(&LEN);
+ LEN += n;
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ c = lexfill(lp);
+ if(c<0)
+ break;
+ if(n==S_ESC)
+ {
+#if SHOPT_CRNL
+ if(c=='\r' && (c=fcget())!=NL)
+ fcseek(-LEN);
+#endif /* SHOPT_CRNL */
+ if(c==NL)
+ fcseek(1);
+ else if(!lp->lexd.dolparen)
+ {
+ iop->iosize++;
+ sfputc(sp,'\\');
+ }
+ }
+ bufp = fcseek(-LEN);
+ }
+ else
+ fcseek(-LEN);
+ switch(n)
+ {
+ case S_NL:
+ lp->sh->inlineno++;
+ if((stripcol && c==' ') || (stripflg && c=='\t'))
+ {
+ if(!lp->lexd.dolparen)
+ {
+ /* write out line */
+ n = fcseek(0)-bufp;
+ if((n=sfwrite(sp,bufp,n))>0)
+ iop->iosize += n;
+ }
+ /* skip over tabs */
+ if(stripcol)
+ {
+ int col=0;
+ do
+ {
+ fcgetc(c);
+ if(c==' ')
+ col++;
+ else
+ col += 8 - col%8;
+ if(col>stripcol)
+ break;
+ }
+ while (c==' ' || c=='\t');
+ }
+ else while(c=='\t')
+ fcgetc(c);
+ if(c<=0)
+ goto done;
+ bufp = fcseek(-LEN);
+ }
+ if(c!=iop->iodelim[0])
+ break;
+ cp = fcseek(0);
+ nsave = n = 0;
+ while(1)
+ {
+ if(!(c=fcget()))
+ {
+ if(!lp->lexd.dolparen && (c=cp-bufp))
+ {
+ if((c=sfwrite(sp,cp=bufp,c))>0)
+ iop->iosize+=c;
+ }
+ nsave = n;
+ if((c=lexfill(lp))<=0)
+ {
+ c = iop->iodelim[n]==0;
+ goto done;
+ }
+ }
+#if SHOPT_CRNL
+ if(c=='\r' && (c=fcget())!=NL)
+ {
+ if(c)
+ fcseek(-LEN);
+ c='\r';
+ }
+#endif /* SHOPT_CRNL */
+ if(c==NL)
+ lp->sh->inlineno++;
+ if(iop->iodelim[n]==0 && (c==NL||c==RPAREN))
+ {
+ if(!lp->lexd.dolparen && (n=cp-bufp))
+ {
+ if((n=sfwrite(sp,bufp,n))>0)
+ iop->iosize += n;
+ }
+ lp->sh->inlineno--;
+ if(c==RPAREN)
+ fcseek(-LEN);
+ goto done;
+ }
+ if(iop->iodelim[n++]!=c)
+ {
+ /*
+ * The match for delimiter failed.
+ * nsave>0 only when a buffer boundary
+ * was crossed while checking the
+ * delimiter
+ */
+ if(!lp->lexd.dolparen && nsave>0)
+ {
+ if((n=sfwrite(sp,iop->iodelim,nsave))>0)
+ iop->iosize += n;
+ bufp = fcfirst();
+ }
+ if(c==NL)
+ fcseek(-LEN);
+ break;
+ }
+ }
+ break;
+ case S_ESC:
+ n=1;
+#if SHOPT_CRNL
+ if(c=='\r')
+ {
+ fcseek(1);
+ if(c=fcget())
+ fcseek(-LEN);
+ if(c==NL)
+ n=2;
+ else
+ {
+ special++;
+ break;
+ }
+ }
+#endif /* SHOPT_CRNL */
+ if(c==NL)
+ {
+ /* new-line joining */
+ lp->sh->inlineno++;
+ if(!lp->lexd.dolparen && (n=(fcseek(0)-bufp)-n)>=0)
+ {
+ if(n && (n=sfwrite(sp,bufp,n))>0)
+ iop->iosize += n;
+ bufp = fcseek(0)+1;
+ }
+ }
+ else
+ special++;
+ fcget();
+ break;
+
+ case S_GRAVE:
+ case S_DOL:
+ special++;
+ break;
+ }
+ n=0;
+ }
+done:
+ lp->sh->funlog = funlog;
+ if(lp->lexd.dolparen)
+ free((void*)iop);
+ else if(!special)
+ iop->iofile |= IOQUOTE;
+ return(c);
+}
+
+/*
+ * generates string for given token
+ */
+static char *fmttoken(Lex_t *lp, register int sym, char *tok)
+{
+ int n=1;
+ if(sym < 0)
+ return((char*)sh_translate(e_lexzerobyte));
+ if(sym==0)
+ return(lp->arg?lp->arg->argval:"?");
+ if(lp->lex.intest && lp->arg && *lp->arg->argval)
+ return(lp->arg->argval);
+ if(sym&SYMRES)
+ {
+ register const Shtable_t *tp=shtab_reserved;
+ while(tp->sh_number && tp->sh_number!=sym)
+ tp++;
+ return((char*)tp->sh_name);
+ }
+ if(sym==EOFSYM)
+ return((char*)sh_translate(e_endoffile));
+ if(sym==NL)
+ return((char*)sh_translate(e_newline));
+ tok[0] = sym;
+ if(sym&SYMREP)
+ tok[n++] = sym;
+ else
+ {
+ switch(sym&SYMMASK)
+ {
+ case SYMAMP:
+ sym = '&';
+ break;
+ case SYMPIPE:
+ sym = '|';
+ break;
+ case SYMGT:
+ sym = '>';
+ break;
+ case SYMLPAR:
+ sym = LPAREN;
+ break;
+ case SYMSHARP:
+ sym = '#';
+ break;
+ case SYMSEMI:
+ if(tok[0]=='<')
+ tok[n++] = '>';
+ sym = ';';
+ break;
+ default:
+ sym = 0;
+ }
+ tok[n++] = sym;
+ }
+ tok[n] = 0;
+ return(tok);
+}
+
+/*
+ * print a bad syntax message
+ */
+
+void sh_syntax(Lex_t *lp)
+{
+ register Shell_t *shp = lp->sh;
+ register const char *cp = sh_translate(e_unexpected);
+ register char *tokstr;
+ register int tok = lp->token;
+ char tokbuf[3];
+ Sfio_t *sp;
+ if((tok==EOFSYM) && lp->lasttok)
+ {
+ tok = lp->lasttok;
+ cp = sh_translate(e_unmatched);
+ }
+ else
+ lp->lastline = shp->inlineno;
+ tokstr = fmttoken(lp,tok,tokbuf);
+ if((sp=fcfile()) || (shp->infd>=0 && (sp=shp->sftable[shp->infd])))
+ {
+ /* clear out any pending input */
+ register Sfio_t *top;
+ while(fcget()>0);
+ fcclose();
+ while(top=sfstack(sp,SF_POPSTACK))
+ sfclose(top);
+ }
+ else
+ fcclose();
+ shp->inlineno = lp->inlineno;
+ shp->st.firstline = lp->firstline;
+#if KSHELL
+ if(!sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_PROFILE))
+#else
+ if(shp->inlineno!=1)
+#endif
+ errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1,lp->lastline,tokstr,cp);
+ else
+ errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax2,tokstr,cp);
+}
+
+static char *stack_shift(Stk_t *stkp, register char *sp,char *dp)
+{
+ register char *ep;
+ register int offset = stktell(stkp);
+ register int left = offset-(sp-stkptr(stkp,0));
+ register int shift = (dp+1-sp);
+ offset += shift;
+ stkseek(stkp,offset);
+ sp = stkptr(stkp,offset);
+ ep = sp - shift;
+ while(left--)
+ *--sp = *--ep;
+ return(sp);
+}
+
+/*
+ * Assumes that current word is unfrozen on top of the stak
+ * If <mode> is zero, gets rid of quoting and consider argument as string
+ * and returns pointer to frozen arg
+ * If mode==1, just replace $"..." strings with international strings
+ * The result is left on the stak
+ * If mode==2, the each $"" string is printed on standard output
+ */
+struct argnod *sh_endword(Shell_t *shp,int mode)
+{
+ register const char *state = sh_lexstates[ST_NESTED];
+ register int n;
+ register char *sp,*dp;
+ register int inquote=0, inlit=0; /* set within quoted strings */
+ struct argnod* argp=0;
+ char *ep=0, *xp=0;
+ int bracket=0;
+ Stk_t *stkp=shp->stk;
+ sfputc(stkp,0);
+ sp = stkptr(stkp,ARGVAL);
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ {
+ do
+ {
+ int len;
+ switch(len = mbsize(sp))
+ {
+ case -1: /* illegal multi-byte char */
+ case 0:
+ case 1:
+ n=state[*sp++];
+ break;
+ default:
+ /*
+ * None of the state tables contain
+ * entries for multibyte characters,
+ * however, they should be treated
+ * the same as any other alph
+ * character. Therefore, we'll use
+ * the state of the 'a' character.
+ */
+ n=state['a'];
+ sp += len;
+ }
+ }
+ while(n == 0);
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ while((n=state[*sp++])==0);
+ dp = sp;
+ if(mode<0)
+ inquote = 1;
+ while(1)
+ {
+ switch(n)
+ {
+ case S_EOF:
+ stkseek(stkp,dp-stkptr(stkp,0));
+ if(mode<=0)
+ {
+ argp = (struct argnod*)stkfreeze(stkp,0);
+ argp->argflag = ARG_RAW|ARG_QUOTED;
+ }
+ return(argp);
+ case S_LIT:
+ if(!(inquote&1))
+ {
+ inlit = !inlit;
+ if(mode==0 || (mode<0 && bracket))
+ {
+ dp--;
+ if(ep)
+ {
+ *dp = 0;
+ stresc(ep);
+ dp = ep+ strlen(ep);
+ }
+ ep = 0;
+ }
+ }
+ break;
+ case S_QUOTE:
+ if(mode<0 && !bracket)
+ break;
+ if(!inlit)
+ {
+ if(mode<=0)
+ dp--;
+ inquote = inquote^1;
+ if(ep)
+ {
+ char *msg;
+ if(mode==2)
+ {
+ sfprintf(sfstdout,"%.*s\n",dp-ep,ep);
+ ep = 0;
+ break;
+ }
+ *--dp = 0;
+#if ERROR_VERSION >= 20000317L
+ msg = ERROR_translate(0,error_info.id,0,ep);
+#else
+# if ERROR_VERSION >= 20000101L
+ msg = ERROR_translate(error_info.id,ep);
+# else
+ msg = ERROR_translate(ep,2);
+# endif
+#endif
+ n = strlen(msg);
+ dp = ep+n;
+ if(sp-dp <= 1)
+ {
+ sp = stack_shift(stkp,sp,dp);
+ dp = sp-1;
+ ep = dp-n;
+ }
+ memmove(ep,msg,n);
+ *dp++ = '"';
+ }
+ ep = 0;
+ }
+ break;
+ case S_DOL: /* check for $'...' and $"..." */
+ if(inlit)
+ break;
+ if(*sp==LPAREN || *sp==LBRACE)
+ {
+ inquote <<= 1;
+ break;
+ }
+ if(inquote&1)
+ break;
+ if(*sp=='\'' || *sp=='"')
+ {
+ if(*sp=='"')
+ inquote |= 1;
+ else
+ inlit = 1;
+ sp++;
+ if((mode==0||(mode<0&&bracket)) || (inquote&1))
+ {
+ if(mode==2)
+ ep = dp++;
+ else if(mode==1)
+ (ep=dp)[-1] = '"';
+ else
+ ep = --dp;
+ }
+ }
+ break;
+ case S_ESC:
+#if SHOPT_CRNL
+ if(*sp=='\r' && sp[1]=='\n')
+ sp++;
+#endif /* SHOPT_CRNL */
+ if(inlit || mode>0)
+ {
+ if(mode<0)
+ {
+ if(dp>=sp)
+ {
+ sp = stack_shift(stkp,sp,dp+1);
+ dp = sp-2;
+ }
+ *dp++ = '\\';
+ }
+ if(ep)
+ *dp++ = *sp++;
+ break;
+ }
+ n = *sp;
+#if SHOPT_DOS
+ if(!(inquote&1) && sh_lexstates[ST_NORM][n]==0)
+ break;
+#endif /* SHOPT_DOS */
+ if(!(inquote&1) || (sh_lexstates[ST_QUOTE][n] && n!=RBRACE))
+ {
+ if(n=='\n')
+ dp--;
+ else
+ dp[-1] = n;
+ sp++;
+ }
+ break;
+ case S_POP:
+ if(sp[-1]!=RBRACT)
+ break;
+ if(!inlit && !(inquote&1))
+ {
+ inquote >>= 1;
+ if(xp)
+ dp = sh_checkid(xp,dp);
+ xp = 0;
+ if(--bracket<=0 && mode<0)
+ inquote = 1;
+ }
+ else if((inlit||inquote) && mode<0)
+ {
+ dp[-1] = '\\';
+ if(dp>=sp)
+ {
+ sp = stack_shift(stkp,sp,dp);
+ dp = sp-1;
+ }
+ *dp++ = ']';
+ }
+ break;
+ case S_BRACT:
+ if(dp[-2]=='.')
+ xp = dp;
+ if(mode<0)
+ {
+ if(inlit || (bracket&&inquote))
+ {
+ dp[-1] = '\\';
+ if(dp>=sp)
+ {
+ sp = stack_shift(stkp,sp,dp);
+ dp = sp-1;
+ }
+ *dp++ = '[';
+ }
+ else if(bracket++==0)
+ inquote = 0;
+ }
+ break;
+ }
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ {
+ do
+ {
+ int len;
+ switch(len = mbsize(sp))
+ {
+ case -1: /* illegal multi-byte char */
+ case 0:
+ case 1:
+ n=state[*dp++ = *sp++];
+ break;
+ default:
+ /*
+ * None of the state tables contain
+ * entries for multibyte characters,
+ * however, they should be treated
+ * the same as any other alph
+ * character. Therefore, we'll use
+ * the state of the 'a' character.
+ */
+ while(len--)
+ *dp++ = *sp++;
+ n=state['a'];
+ }
+ }
+ while(n == 0);
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ while((n=state[*dp++ = *sp++])==0);
+ }
+}
+
+struct alias
+{
+ Sfdisc_t disc;
+ Namval_t *np;
+ int nextc;
+ int line;
+ char buf[2];
+ Lex_t *lp;
+};
+
+/*
+ * This code gets called whenever an end of string is found with alias
+ */
+
+#ifndef SF_ATEXIT
+# define SF_ATEXIT 0
+#endif
+/*
+ * This code gets called whenever an end of string is found with alias
+ */
+#ifdef SF_BUFCONST
+static int alias_exceptf(Sfio_t *iop,int type,void *data, Sfdisc_t *handle)
+#else
+static int alias_exceptf(Sfio_t *iop,int type,Sfdisc_t *handle)
+#endif
+{
+ register struct alias *ap = (struct alias*)handle;
+ register Namval_t *np;
+ register Lex_t *lp;
+ if(type==0 || type==SF_ATEXIT || !ap)
+ return(0);
+ lp = ap->lp;
+ np = ap->np;
+ if(type!=SF_READ)
+ {
+ if(type==SF_CLOSING)
+ {
+ register Sfdisc_t *dp = sfdisc(iop,SF_POPDISC);
+ if(dp!=handle)
+ sfdisc(iop,dp);
+ }
+ else if(type==SF_FINAL)
+ free((void*)ap);
+ goto done;
+ }
+ if(ap->nextc)
+ {
+ /* if last character is a blank, then next work can be alias */
+ register int c = fcpeek(-1);
+ if(isblank(c))
+ lp->aliasok = 1;
+ *ap->buf = ap->nextc;
+ ap->nextc = 0;
+ sfsetbuf(iop,ap->buf,1);
+ return(1);
+ }
+done:
+ if(np)
+ nv_offattr(np,NV_NOEXPAND);
+ return(0);
+}
+
+
+static void setupalias(Lex_t *lp, const char *string,Namval_t *np)
+{
+ register Sfio_t *iop, *base;
+ struct alias *ap = (struct alias*)malloc(sizeof(struct alias));
+ ap->disc = alias_disc;
+ ap->lp = lp;
+ ap->buf[1] = 0;
+ if(ap->np = np)
+ {
+#if SHOPT_KIA
+ if(lp->kiafile)
+ {
+ unsigned long r;
+ r=kiaentity(lp,nv_name(np),-1,'p',0,0,lp->current,'a',0,"");
+ sfprintf(lp->kiatmp,"p;%..64d;p;%..64d;%d;%d;e;\n",lp->current,r,lp->sh->inlineno,lp->sh->inlineno);
+ }
+#endif /* SHOPT_KIA */
+ if((ap->nextc=fcget())==0)
+ ap->nextc = ' ';
+ }
+ else
+ ap->nextc = 0;
+ iop = sfopen(NIL(Sfio_t*),(char*)string,"s");
+ sfdisc(iop, &ap->disc);
+ lp->lexd.nocopy++;
+ if(!(base=fcfile()))
+ base = sfopen(NIL(Sfio_t*),fcseek(0),"s");
+ fcclose();
+ sfstack(base,iop);
+ fcfopen(base);
+ lp->lexd.nocopy--;
+}
+
+/*
+ * grow storage stack for nested constructs by STACK_ARRAY
+ */
+static int stack_grow(Lex_t *lp)
+{
+ lp->lexd.lex_max += STACK_ARRAY;
+ if(lp->lexd.lex_match)
+ lp->lexd.lex_match = (int*)realloc((char*)lp->lexd.lex_match,sizeof(int)*lp->lexd.lex_max);
+ else
+ lp->lexd.lex_match = (int*)malloc(sizeof(int)*STACK_ARRAY);
+ return(lp->lexd.lex_match!=0);
+}
+
diff --git a/src/cmd/ksh93/sh/macro.c b/src/cmd/ksh93/sh/macro.c
new file mode 100644
index 0000000..9adf5f5
--- /dev/null
+++ b/src/cmd/ksh93/sh/macro.c
@@ -0,0 +1,2814 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Shell macro expander
+ * expands ~
+ * expands ${...}
+ * expands $(...)
+ * expands $((...))
+ * expands `...`
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <fcin.h>
+#include <pwd.h>
+#include <ctype.h>
+#include "name.h"
+#include "variables.h"
+#include "shlex.h"
+#include "io.h"
+#include "jobs.h"
+#include "shnodes.h"
+#include "path.h"
+#include "national.h"
+#include "streval.h"
+
+#undef STR_GROUP
+#ifndef STR_GROUP
+# define STR_GROUP 0
+#endif
+
+#if SHOPT_MULTIBYTE
+# undef isascii
+# define isacii(c) ((c)<=UCHAR_MAX)
+#else
+# define mbchar(p) (*(unsigned char*)p++)
+#endif /* SHOPT_MULTIBYTE */
+
+#if _WINIX
+ static int Skip;
+#endif /*_WINIX */
+
+static int _c_;
+typedef struct _mac_
+{
+ Shell_t *shp; /* pointer to shell interpreter */
+ Sfio_t *sp; /* stream pointer for here-document */
+ struct argnod **arghead; /* address of head of argument list */
+ char *ifsp; /* pointer to IFS value */
+ int fields; /* number of fields */
+ short quoted; /* set when word has quotes */
+ unsigned char ifs; /* first char of IFS */
+ char atmode; /* when processing $@ */
+ char quote; /* set within double quoted contexts */
+ char lit; /* set within single quotes */
+ char split; /* set when word splittin is possible */
+ char pattern; /* set when file expansion follows */
+ char patfound; /* set if pattern character found */
+ char assign; /* set for assignments */
+ char arith; /* set for ((...)) */
+ char let; /* set when expanding let arguments */
+ char zeros; /* strip leading zeros when set */
+ char arrayok; /* $x[] ok for arrays */
+ char subcopy; /* set when copying subscript */
+ int dotdot; /* set for .. in subscript */
+ void *nvwalk; /* for name space walking*/
+} Mac_t;
+
+#undef ESCAPE
+#define ESCAPE '\\'
+#define isescchar(s) ((s)>S_QUOTE)
+#define isqescchar(s) ((s)>=S_QUOTE)
+#define isbracechar(c) ((c)==RBRACE || (_c_=sh_lexstates[ST_BRACE][c])==S_MOD1 ||_c_==S_MOD2)
+#define ltos(x) fmtbase((long)(x),0,0)
+
+/* type of macro expansions */
+#define M_BRACE 1 /* ${var} */
+#define M_TREE 2 /* ${var.} */
+#define M_SIZE 3 /* ${#var} */
+#define M_VNAME 4 /* ${!var} */
+#define M_SUBNAME 5 /* ${!var[sub]} */
+#define M_NAMESCAN 6 /* ${!var*} */
+#define M_NAMECOUNT 7 /* ${#var*} */
+#define M_TYPE 8 /* ${@var} */
+
+static int substring(const char*, const char*, int[], int);
+static void copyto(Mac_t*, int, int);
+static void comsubst(Mac_t*, Shnode_t*, int);
+static int varsub(Mac_t*);
+static void mac_copy(Mac_t*,const char*, int);
+static void tilde_expand2(Shell_t*,int);
+static char *sh_tilde(Shell_t*,const char*);
+static char *special(Shell_t *,int);
+static void endfield(Mac_t*,int);
+static void mac_error(Namval_t*);
+static char *mac_getstring(char*);
+static int charlen(const char*,int);
+#if SHOPT_MULTIBYTE
+ static char *lastchar(const char*,const char*);
+#endif /* SHOPT_MULTIBYTE */
+
+void *sh_macopen(Shell_t *shp)
+{
+ void *addr = newof(0,Mac_t,1,0);
+ Mac_t *mp = (Mac_t*)addr;
+ mp->shp = shp;
+ return(addr);
+}
+
+/*
+ * perform only parameter substitution and catch failures
+ */
+char *sh_mactry(Shell_t *shp,register char *string)
+{
+ if(string)
+ {
+ int jmp_val;
+ int savexit = shp->savexit;
+ struct checkpt buff;
+ sh_pushcontext(shp,&buff,SH_JMPSUB);
+ jmp_val = sigsetjmp(buff.buff,0);
+ if(jmp_val == 0)
+ string = sh_mactrim(shp,string,0);
+ sh_popcontext(shp,&buff);
+ shp->savexit = savexit;
+ return(string);
+ }
+ return("");
+}
+
+/*
+ * Perform parameter expansion, command substitution, and arithmetic
+ * expansion on <str>.
+ * If <mode> greater than 1 file expansion is performed if the result
+ * yields a single pathname.
+ * If <mode> negative, than expansion rules for assignment are applied.
+ */
+char *sh_mactrim(Shell_t *shp, char *str, register int mode)
+{
+ register Mac_t *mp = (Mac_t*)shp->mac_context;
+ Stk_t *stkp = shp->stk;
+ Mac_t savemac;
+ savemac = *mp;
+ stkseek(stkp,0);
+ mp->arith = (mode==3);
+ mp->let = 0;
+ shp->argaddr = 0;
+ mp->pattern = (mode==1||mode==2);
+ mp->patfound = 0;
+ mp->assign = 0;
+ if(mode<0)
+ mp->assign = -mode;
+ mp->quoted = mp->lit = mp->split = mp->quote = 0;
+ mp->sp = 0;
+ if(mp->ifsp=nv_getval(sh_scoped(shp,IFSNOD)))
+ mp->ifs = *mp->ifsp;
+ else
+ mp->ifs = ' ';
+ stkseek(stkp,0);
+ fcsopen(str);
+ copyto(mp,0,mp->arith);
+ str = stkfreeze(stkp,1);
+ if(mode==2)
+ {
+ /* expand only if unique */
+ struct argnod *arglist=0;
+ if((mode=path_expand(shp,str,&arglist))==1)
+ str = arglist->argval;
+ else if(mode>1)
+ errormsg(SH_DICT,ERROR_exit(1),e_ambiguous,str);
+ sh_trim(str);
+ }
+ *mp = savemac;
+ return(str);
+}
+
+/*
+ * Perform all the expansions on the argument <argp>
+ */
+int sh_macexpand(Shell_t* shp, register struct argnod *argp, struct argnod **arghead,int flag)
+{
+ register int flags = argp->argflag;
+ register char *str = argp->argval;
+ register Mac_t *mp = (Mac_t*)shp->mac_context;
+ char **saveargaddr = shp->argaddr;
+ Mac_t savemac;
+ Stk_t *stkp = shp->stk;
+ savemac = *mp;
+ mp->sp = 0;
+ if(mp->ifsp=nv_getval(sh_scoped(shp,IFSNOD)))
+ mp->ifs = *mp->ifsp;
+ else
+ mp->ifs = ' ';
+ if((flag&ARG_OPTIMIZE) && !shp->indebug && !(flags&ARG_MESSAGE))
+ shp->argaddr = (char**)&argp->argchn.ap;
+ else
+ shp->argaddr = 0;
+ mp->arghead = arghead;
+ mp->quoted = mp->lit = mp->quote = 0;
+ mp->arith = ((flag&ARG_ARITH)!=0);
+ mp->let = ((flag&ARG_LET)!=0);
+ mp->split = !(flag&ARG_ASSIGN);
+ mp->assign = !mp->split;
+ mp->pattern = mp->split && !(flag&ARG_NOGLOB) && !sh_isoption(SH_NOGLOB);
+ mp->arrayok = mp->arith || (flag&ARG_ARRAYOK);
+ str = argp->argval;
+ fcsopen(str);
+ mp->fields = 0;
+ mp->atmode = 0;
+ if(!arghead)
+ {
+ mp->split = 0;
+ mp->pattern = ((flag&ARG_EXP)!=0);
+ stkseek(stkp,0);
+ }
+ else
+ {
+ stkseek(stkp,ARGVAL);
+ *stkptr(stkp,ARGVAL-1) = 0;
+ }
+ mp->patfound = 0;
+ if(mp->pattern)
+ mp->arrayok = 0;
+ copyto(mp,0,mp->arith);
+ if(!arghead)
+ {
+ argp->argchn.cp = stkfreeze(stkp,1);
+ if(shp->argaddr)
+ argp->argflag |= ARG_MAKE;
+ }
+ else
+ {
+ endfield(mp,mp->quoted|mp->atmode);
+ flags = mp->fields;
+ if(flags==1 && shp->argaddr)
+ argp->argchn.ap = *arghead;
+ }
+ shp->argaddr = saveargaddr;
+ *mp = savemac;
+ return(flags);
+}
+
+/*
+ * Expand here document which is stored in <infile> or <string>
+ * The result is written to <outfile>
+ */
+void sh_machere(Shell_t *shp,Sfio_t *infile, Sfio_t *outfile, char *string)
+{
+ register int c,n;
+ register const char *state = sh_lexstates[ST_QUOTE];
+ register char *cp;
+ register Mac_t *mp = (Mac_t*)shp->mac_context;
+ Lex_t *lp = (Lex_t*)mp->shp->lex_context;
+ Fcin_t save;
+ Mac_t savemac;
+ Stk_t *stkp = shp->stk;
+ savemac = *mp;
+ stkseek(stkp,0);
+ shp->argaddr = 0;
+ mp->sp = outfile;
+ mp->split = mp->assign = mp->pattern = mp->patfound = mp->lit = mp->arith = mp->let = 0;
+ mp->quote = 1;
+ mp->ifsp = nv_getval(sh_scoped(shp,IFSNOD));
+ mp->ifs = ' ';
+ fcsave(&save);
+ if(infile)
+ fcfopen(infile);
+ else
+ fcsopen(string);
+ fcnotify(0,lp);
+ cp = fcseek(0);
+ while(1)
+ {
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ {
+ do
+ {
+ ssize_t len;
+ switch(len = mbsize(cp))
+ {
+ case -1: /* illegal multi-byte char */
+ case 0:
+ case 1:
+ n=state[*(unsigned char*)cp++];
+ break;
+ default:
+ /* use state of alpha character */
+ n=state['a'];
+ cp += len;
+ }
+ }
+ while(n == 0);
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ while((n=state[*(unsigned char*)cp++])==0);
+ if(n==S_NL || n==S_QUOTE || n==S_RBRA)
+ continue;
+ if(c=(cp-1)-fcseek(0))
+ sfwrite(outfile,fcseek(0),c);
+ cp = fcseek(c+1);
+ switch(n)
+ {
+ case S_EOF:
+ if((n=fcfill()) <=0)
+ {
+ /* ignore 0 byte when reading from file */
+ if(n==0 && fcfile())
+ continue;
+ fcrestore(&save);
+ *mp = savemac;
+ return;
+ }
+ cp = fcseek(-1);
+ continue;
+ case S_ESC:
+ fcgetc(c);
+ cp=fcseek(-1);
+ if(c>0)
+ cp++;
+ if(!isescchar(state[c]))
+ sfputc(outfile,ESCAPE);
+ continue;
+ case S_GRAVE:
+ comsubst(mp,(Shnode_t*)0,0);
+ break;
+ case S_DOL:
+ c = fcget();
+ if(c=='.')
+ goto regular;
+ again:
+ switch(n=sh_lexstates[ST_DOL][c])
+ {
+ case S_ALP: case S_SPC1: case S_SPC2:
+ case S_DIG: case S_LBRA:
+ {
+ Fcin_t save2;
+ int offset = stktell(stkp);
+ int offset2;
+ fcnotify(0,lp);
+ sfputc(stkp,c);
+ if(n==S_LBRA)
+ {
+ c = fcget();
+ fcseek(-1);
+ if(sh_lexstates[ST_NORM][c]==S_BREAK)
+ {
+ comsubst(mp,(Shnode_t*)0,2);
+ break;
+ }
+ sh_lexskip(lp,RBRACE,1,ST_BRACE);
+ }
+ else if(n==S_ALP)
+ {
+ while(fcgetc(c),isaname(c))
+ sfputc(stkp,c);
+ fcseek(-1);
+ }
+ sfputc(stkp,0);
+ offset2 = stktell(stkp);
+ fcsave(&save2);
+ fcsopen(stkptr(stkp,offset));
+ varsub(mp);
+ if(c=stktell(stkp)-offset2)
+ sfwrite(outfile,(char*)stkptr(stkp,offset2),c);
+ fcrestore(&save2);
+ stkseek(stkp,offset);
+ break;
+ }
+ case S_PAR:
+ comsubst(mp,(Shnode_t*)0,1);
+ break;
+ case S_EOF:
+ if((c=fcfill()) > 0)
+ goto again;
+ /* FALL THRU */
+ default:
+ regular:
+ sfputc(outfile,'$');
+ fcseek(-1);
+ break;
+ }
+ }
+ cp = fcseek(0);
+ }
+}
+
+/*
+ * expand argument but do not trim pattern characters
+ */
+char *sh_macpat(Shell_t *shp,register struct argnod *arg, int flags)
+{
+ register char *sp = arg->argval;
+ if((arg->argflag&ARG_RAW))
+ return(sp);
+ sh_stats(STAT_ARGEXPAND);
+ if(flags&ARG_OPTIMIZE)
+ arg->argchn.ap=0;
+ if(!(sp=arg->argchn.cp))
+ {
+ sh_macexpand(shp,arg,NIL(struct argnod**),flags|ARG_ARRAYOK);
+ sp = arg->argchn.cp;
+ if(!(flags&ARG_OPTIMIZE) || !(arg->argflag&ARG_MAKE))
+ arg->argchn.cp = 0;
+ arg->argflag &= ~ARG_MAKE;
+ }
+ else
+ sh_stats(STAT_ARGHITS);
+ return(sp);
+}
+
+/*
+ * Process the characters up to <endch> or end of input string
+ */
+static void copyto(register Mac_t *mp,int endch, int newquote)
+{
+ register int c,n;
+ register const char *state = sh_lexstates[ST_MACRO];
+ register char *cp,*first;
+ Lex_t *lp = (Lex_t*)mp->shp->lex_context;
+ int tilde = -1;
+ int oldquote = mp->quote;
+ int ansi_c = 0;
+ int paren = 0;
+ int ere = 0;
+ int brace = 0;
+ Sfio_t *sp = mp->sp;
+ Stk_t *stkp = mp->shp->stk;
+ char *resume = 0;
+ mp->sp = NIL(Sfio_t*);
+ mp->quote = newquote;
+ first = cp = fcseek(0);
+ if(!mp->quote && *cp=='~' && cp[1]!=LPAREN)
+ tilde = stktell(stkp);
+ /* handle // operator specially */
+ if(mp->pattern==2 && *cp=='/')
+ cp++;
+ while(1)
+ {
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ {
+ ssize_t len;
+ do
+ {
+ switch(len = mbsize(cp))
+ {
+ case -1: /* illegal multi-byte char */
+ case 0:
+ len = 1;
+ case 1:
+ n = state[*(unsigned char*)cp++];
+ break;
+ default:
+ /* treat as if alpha */
+ cp += len;
+ n=state['a'];
+ }
+ }
+ while(n == 0);
+ c = (cp-len) - first;
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ {
+ while((n=state[*(unsigned char*)cp++])==0);
+ c = (cp-1) - first;
+ }
+ switch(n)
+ {
+ case S_ESC:
+ if(ansi_c)
+ {
+ /* process ANSI-C escape character */
+ char *addr= --cp;
+ if(c)
+ sfwrite(stkp,first,c);
+ c = chresc(cp,&addr);
+ cp = addr;
+ first = fcseek(cp-first);
+#if SHOPT_MULTIBYTE
+ if(c > UCHAR_MAX && mbwide())
+ {
+ int i;
+ unsigned char mb[8];
+
+ n = mbconv((char*)mb, c);
+ for(i=0;i<n;i++)
+ sfputc(stkp,mb[i]);
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ sfputc(stkp,c);
+ if(c==ESCAPE && mp->pattern)
+ sfputc(stkp,ESCAPE);
+ break;
+ }
+ else if(sh_isoption(SH_BRACEEXPAND) && mp->pattern==4 && (*cp==',' || *cp==LBRACE || *cp==RBRACE || *cp=='.'))
+ break;
+ else if(mp->split && endch && !mp->quote && !mp->lit)
+ {
+ if(c)
+ mac_copy(mp,first,c);
+ cp = fcseek(c+2);
+ if(c= cp[-1])
+ {
+ sfputc(stkp,c);
+ if(c==ESCAPE)
+ sfputc(stkp,ESCAPE);
+ }
+ else
+ cp--;
+ first = cp;
+ break;
+ }
+ n = state[*(unsigned char*)cp];
+ if(n==S_ENDCH && *cp!=endch)
+ n = S_PAT;
+ if(mp->pattern)
+ {
+ /* preserve \digit for pattern matching */
+ /* also \alpha for extended patterns */
+ if(!mp->lit && !mp->quote)
+ {
+ int nc = *(unsigned char*)cp;
+ if((n==S_DIG || ((paren+ere) && (sh_lexstates[ST_DOL][nc]==S_ALP) || nc=='<' || nc=='>')))
+ break;
+ if(ere && mp->pattern==1 && strchr(".[()*+?{|^$&!",*cp))
+ break;
+ }
+ /* followed by file expansion */
+ if(!mp->lit && (n==S_ESC || (!mp->quote &&
+ (n==S_PAT||n==S_ENDCH||n==S_SLASH||n==S_BRACT||*cp=='-'))))
+ {
+ cp += (n!=S_EOF);
+ if(ere && n==S_ESC && *cp =='\\' && cp[1]=='$')
+ {
+ /* convert \\\$ into \$' */
+ sfwrite(stkp,first,c+1);
+ cp = first = fcseek(c+3);
+ }
+ break;
+ }
+ if(!(ere && *cp=='$') && (mp->lit || (mp->quote && !isqescchar(n) && n!=S_ENDCH)))
+ {
+ /* add \ for file expansion */
+ sfwrite(stkp,first,c+1);
+ first = fcseek(c);
+ break;
+ }
+ }
+ if(mp->lit)
+ break;
+ if(!mp->quote || isqescchar(n) || n==S_ENDCH)
+ {
+ /* eliminate \ */
+ if(c)
+ sfwrite(stkp,first,c);
+ /* check new-line joining */
+ first = fcseek(c+1);
+ }
+ cp += (n!=S_EOF);
+ break;
+ case S_GRAVE: case S_DOL:
+ if(mp->lit)
+ break;
+ if(c)
+ {
+ if(mp->split && !mp->quote && endch)
+ mac_copy(mp,first,c);
+ else
+ sfwrite(stkp,first,c);
+ }
+ first = fcseek(c+1);
+ c = mp->pattern;
+ if(n==S_GRAVE)
+ comsubst(mp,(Shnode_t*)0,0);
+ else if((n= *cp) == '"' && !mp->quote)
+ {
+ int off = stktell(stkp);
+ char *dp;
+ cp = first = fcseek(1);
+ mp->quote = 1;
+ if(!ERROR_translating())
+ break;
+ while(n=c, c= *++cp)
+ {
+ if(c=='\\' && n==c)
+ c = 0;
+ else if(c=='"' && n!='\\')
+ break;
+ }
+ n = cp-first;
+ sfwrite(stkp,first,n);
+ sfputc(stkp,0);
+ cp = stkptr(stkp,off);
+ dp = (char*)sh_translate(cp);
+ stkseek(stkp,off);
+ if(dp==cp)
+ {
+ cp = first;
+ break;
+ }
+ resume = fcseek(n);
+ fcclose();
+ fcsopen(dp);
+ cp = first = fcseek(0);
+ break;
+ }
+ else if(n==0 || !varsub(mp))
+ {
+ if(n=='\'' && !mp->quote)
+ ansi_c = 1;
+ else if(mp->quote || n!='"')
+ sfputc(stkp,'$');
+ }
+ cp = first = fcseek(0);
+ if(mp->quote && cp)
+ mp->pattern = c;
+ break;
+ case S_ENDCH:
+ if((mp->lit || cp[-1]!=endch || mp->quote!=newquote))
+ goto pattern;
+ if(endch==RBRACE && *cp==LPAREN && mp->pattern && brace)
+ goto pattern;
+ case S_EOF:
+ if(c)
+ {
+ if(mp->split && !mp->quote && !mp->lit && endch)
+ mac_copy(mp,first,c);
+ else
+ sfwrite(stkp,first,c);
+ }
+ if(n==S_EOF && resume)
+ {
+ fcclose();
+ fcsopen(resume);
+ resume = 0;
+ cp = first = fcseek(0);
+ continue;
+ }
+ c += (n!=S_EOF);
+ first = fcseek(c);
+ if(tilde>=0)
+ tilde_expand2(mp->shp,tilde);
+ goto done;
+ case S_QUOTE:
+ if(mp->lit || mp->arith)
+ break;
+ case S_LIT:
+ if(mp->arith)
+ {
+ if((*cp=='`' || *cp=='[') && cp[1]=='\'')
+ cp +=2;
+ break;
+ }
+ if(n==S_LIT && mp->quote)
+ break;
+ if(c)
+ {
+ if(mp->split && endch && !mp->quote && !mp->lit)
+ mac_copy(mp,first,c);
+ else
+ sfwrite(stkp,first,c);
+ }
+ first = fcseek(c+1);
+ if(n==S_LIT)
+ {
+ if(mp->quote)
+ continue;
+ if(mp->lit)
+ mp->lit = ansi_c = 0;
+ else
+ mp->lit = 1;
+ }
+ else
+ mp->quote = !mp->quote;
+ mp->quoted++;
+ break;
+ case S_BRACT:
+ if(mp->arith || (((mp->assign&1) || endch==RBRACT) &&
+ !(mp->quote || mp->lit)))
+ {
+ int offset=0,oldpat = mp->pattern;
+ int oldarith = mp->arith, oldsub=mp->subcopy;
+ sfwrite(stkp,first,++c);
+ if(mp->assign&1)
+ {
+ if(first[c-2]=='.')
+ offset = stktell(stkp);
+ if(isastchar(*cp) && cp[1]==']')
+ errormsg(SH_DICT,ERROR_exit(1),
+e_badsubscript,*cp);
+ }
+ first = fcseek(c);
+ mp->pattern = 4;
+ mp->arith = 0;
+ mp->subcopy = 0;
+ copyto(mp,RBRACT,0);
+ mp->subcopy = oldsub;
+ mp->arith = oldarith;
+ mp->pattern = oldpat;
+ sfputc(stkp,RBRACT);
+ if(offset)
+ {
+ cp = stkptr(stkp,stktell(stkp));
+ if(sh_checkid(stkptr(stkp,offset),cp)!=cp)
+ stkseek(stkp,stktell(stkp)-2);
+ }
+ cp = first = fcseek(0);
+ break;
+ }
+ case S_PAT:
+ if(mp->pattern && !(mp->quote || mp->lit))
+ {
+ mp->patfound = mp->pattern;
+ if((n=cp[-1])==LPAREN)
+ {
+ paren++;
+ if((cp-first)>1 && cp[-2]=='~')
+ {
+ char *p = cp;
+ while((c=mbchar(p)) && c!=RPAREN)
+ if(c=='A'||c=='E'||c=='K'||c=='P'||c=='X')
+ {
+ ere = 1;
+ break;
+ }
+ }
+ }
+ else if(n==RPAREN)
+ --paren;
+ }
+ goto pattern;
+ case S_COM:
+ if(mp->pattern==4 && (mp->quote || mp->lit))
+ {
+ if(c)
+ {
+ sfwrite(stkp,first,c);
+ first = fcseek(c);
+ }
+ sfputc(stkp,ESCAPE);
+ }
+ break;
+ case S_BRACE:
+ if(!(mp->quote || mp->lit))
+ {
+ mp->patfound = mp->split && sh_isoption(SH_BRACEEXPAND);
+ brace = 1;
+ }
+ pattern:
+ if(!mp->pattern || !(mp->quote || mp->lit))
+ {
+ /* mark beginning of {a,b} */
+ if(n==S_BRACE && endch==0 && mp->pattern)
+ mp->pattern=4;
+ if(n==S_SLASH && mp->pattern==2)
+ mp->pattern=3;
+ break;
+ }
+ if(mp->pattern==3)
+ break;
+ if(c)
+ sfwrite(stkp,first,c);
+ first = fcseek(c);
+ sfputc(stkp,ESCAPE);
+ break;
+ case S_EQ:
+ if(mp->assign==1)
+ {
+ if(*cp=='~' && !endch && !mp->quote && !mp->lit)
+ tilde = stktell(stkp)+(c+1);
+ mp->assign = 2;
+ }
+ break;
+ case S_SLASH:
+ case S_COLON:
+ if(tilde >=0)
+ {
+ if(c)
+ sfwrite(stkp,first,c);
+ first = fcseek(c);
+ tilde_expand2(mp->shp,tilde);
+#if _WINIX
+ if(Skip)
+ {
+ first = cp = fcseek(Skip);
+ Skip = 0;
+ }
+#endif /*_WINIX */
+ tilde = -1;
+ c=0;
+ }
+ if(n==S_COLON && mp->assign==2 && *cp=='~' && endch==0 && !mp->quote &&!mp->lit)
+ tilde = stktell(stkp)+(c+1);
+ else if(n==S_SLASH && mp->pattern==2)
+#if 0
+ goto pattern;
+#else
+ {
+ if(mp->quote || mp->lit)
+ goto pattern;
+ sfwrite(stkp,first,c+1);
+ first = fcseek(c+1);
+ c = stktell(stkp);
+ sh_lexskip(lp,RBRACE,0,ST_NESTED);
+ stkseek(stkp,c);
+ cp = fcseek(-1);
+ sfwrite(stkp,first,cp-first);
+ first=cp;
+ }
+#endif
+ break;
+ case S_DOT:
+ if(*cp=='.' && mp->subcopy==1)
+ {
+ sfwrite(stkp,first,c);
+ sfputc(stkp,0);
+ mp->dotdot = stktell(stkp);
+ cp = first = fcseek(c+2);
+ }
+ break;
+ }
+ }
+done:
+ mp->sp = sp;
+ mp->quote = oldquote;
+}
+
+/*
+ * copy <str> to stack performing sub-expression substitutions
+ */
+static void mac_substitute(Mac_t *mp, register char *cp,char *str,register int subexp[],int subsize)
+{
+ register int c,n;
+ register char *first=cp;
+ while(1)
+ {
+ while((c= *cp++) && c!=ESCAPE);
+ if(c==0)
+ break;
+ if((n= *cp++)=='\\' || n==RBRACE || (n>='0' && n<='9' && (n-='0')<subsize))
+ {
+ c = cp-first-2;
+ if(c)
+ mac_copy(mp,first,c);
+ first=cp;
+ if(n=='\\' || n==RBRACE)
+ {
+ first--;
+ continue;
+ }
+ if((c=subexp[2*n])>=0)
+ {
+ if((n=subexp[2*n+1]-c)>0)
+ mac_copy(mp,str+c,n);
+ }
+ }
+ else if(n==0)
+ break;
+ }
+ if(n=cp-first-1)
+ mac_copy(mp,first,n);
+}
+
+#if SHOPT_FILESCAN
+#define MAX_OFFSETS (sizeof(shp->offsets)/sizeof(shp->offsets[0]))
+#define MAX_ARGN (32*1024)
+
+/*
+ * compute the arguments $1 ... $n and $# from the current line as needed
+ * save line offsets in the offsets array.
+ */
+static char *getdolarg(Shell_t *shp, int n, int *size)
+{
+ register int c=S_DELIM, d=shp->ifstable['\\'];
+ register unsigned char *first,*last,*cp = (unsigned char*)shp->cur_line;
+ register int m=shp->offsets[0],delim=0;
+ if(m==0)
+ return(0);
+ if(m<0)
+ m = 0;
+ else if(n<=m)
+ m = n-1;
+ else
+ m--;
+ if(m >= MAX_OFFSETS-1)
+ m = MAX_OFFSETS-2;
+ cp += shp->offsets[m+1];
+ n -= m;
+ shp->ifstable['\\'] = 0;
+ shp->ifstable[0] = S_EOF;
+ while(1)
+ {
+ if(c==S_DELIM)
+ while(shp->ifstable[*cp++]==S_SPACE);
+ first = --cp;
+ if(++m < MAX_OFFSETS)
+ shp->offsets[m] = (first-(unsigned char*)shp->cur_line);
+ while((c=shp->ifstable[*cp++])==0);
+ last = cp-1;
+ if(c==S_SPACE)
+ while((c=shp->ifstable[*cp++])==S_SPACE);
+ if(--n==0 || c==S_EOF)
+ {
+ if(last==first && c==S_EOF && (!delim || (m>1)))
+ {
+ n++;
+ m--;
+ }
+ break;
+ }
+ delim = (c==S_DELIM);
+ }
+ shp->ifstable['\\'] = d;
+ if(m > shp->offsets[0])
+ shp->offsets[0] = m;
+ if(n)
+ first = last = 0;
+ if(size)
+ *size = last-first;
+ return((char*)first);
+}
+#endif /* SHOPT_FILESCAN */
+
+/*
+ * get the prefix after name reference resolution
+ */
+static char *prefix(Shell_t *shp, char *id)
+{
+ Namval_t *np;
+ register char *sub=0, *cp = strchr(id,'.');
+ if(cp)
+ {
+ *cp = 0;
+ np = nv_search(id, shp->var_tree,0);
+ *cp = '.';
+ if(isastchar(cp[1]))
+ cp[1] = 0;
+ if(np && nv_isref(np))
+ {
+ int n;
+ char *sp;
+ shp->argaddr = 0;
+ while(nv_isref(np) && np->nvalue.cp)
+ {
+ sub = nv_refsub(np);
+ np = nv_refnode(np);
+ if(sub)
+ nv_putsub(np,sub,0L);
+ }
+ id = (char*)malloc(strlen(cp)+1+(n=strlen(sp=nv_name(np)))+ (sub?strlen(sub)+3:1));
+ memcpy(id,sp,n);
+ if(sub)
+ {
+ id[n++] = '[';
+ strcpy(&id[n],sub);
+ n+= strlen(sub)+1;
+ id[n-1] = ']';
+ }
+ strcpy(&id[n],cp);
+ return(id);
+ }
+ }
+ return(strdup(id));
+}
+
+/*
+ * copy to ']' onto the stack and return offset to it
+ */
+static int subcopy(Mac_t *mp, int flag)
+{
+ int split = mp->split;
+ int xpattern = mp->pattern;
+ int loc = stktell(mp->shp->stk);
+ int xarith = mp->arith;
+ int arrayok = mp->arrayok;
+ mp->split = 0;
+ mp->arith = 0;
+ mp->pattern = flag?4:0;
+ mp->arrayok=1;
+ mp->subcopy++;
+ mp->dotdot = 0;
+ copyto(mp,RBRACT,0);
+ mp->subcopy = 0;
+ mp->pattern = xpattern;
+ mp->split = split;
+ mp->arith = xarith;
+ mp->arrayok = arrayok;
+ return(loc);
+}
+
+/*
+ * if name is a discipline function, run the function and put the results
+ * on the stack so that ${x.foo} behaves like ${ x.foo;}
+ */
+int sh_macfun(Shell_t *shp, const char *name, int offset)
+{
+ Namval_t *np, *nq;
+ np = nv_bfsearch(name,shp->fun_tree,&nq,(char**)0);
+ if(np)
+ {
+ /* treat ${x.foo} as ${x.foo;} */
+ union
+ {
+ struct comnod com;
+ Shnode_t node;
+ } t;
+ union
+ {
+ struct argnod arg;
+ struct dolnod dol;
+ char buff[sizeof(struct dolnod)+sizeof(char*)];
+ } d;
+ memset(&t,0,sizeof(t));
+ memset(&d,0,sizeof(d));
+ t.node.com.comarg = &d.arg;
+ t.node.com.comline = shp->inlineno;
+ d.dol.dolnum = 1;
+ d.dol.dolval[0] = strdup(name);
+ stkseek(shp->stk,offset);
+ comsubst((Mac_t*)shp->mac_context,&t.node,2);
+ free(d.dol.dolval[0]);
+ return(1);
+ }
+ return(0);
+}
+
+static int namecount(Mac_t *mp,const char *prefix)
+{
+ int count = 0;
+ mp->nvwalk = nv_diropen((Namval_t*)0,prefix);
+ while(nv_dirnext(mp->nvwalk))
+ count++;
+ nv_dirclose(mp->nvwalk);
+ return(count);
+}
+
+static char *nextname(Mac_t *mp,const char *prefix, int len)
+{
+ char *cp;
+ if(len==0)
+ {
+ mp->nvwalk = nv_diropen((Namval_t*)0,prefix);
+ return((char*)mp->nvwalk);
+ }
+ if(!(cp=nv_dirnext(mp->nvwalk)))
+ nv_dirclose(mp->nvwalk);
+ return(cp);
+}
+
+/*
+ * This routine handles $param, ${parm}, and ${param op word}
+ * The input stream is assumed to be a string
+ */
+static int varsub(Mac_t *mp)
+{
+ register int c;
+ register int type=0; /* M_xxx */
+ register char *v,*argp=0;
+ register Namval_t *np = NIL(Namval_t*);
+ register int dolg=0, mode=0;
+ Lex_t *lp = (Lex_t*)mp->shp->lex_context;
+ Namarr_t *ap=0;
+ int dolmax=0, vsize= -1, offset= -1, nulflg, replen=0, bysub=0;
+ char idbuff[3], *id = idbuff, *pattern=0, *repstr=0, *arrmax=0;
+ char *idx = 0;
+ int var=1,addsub=0,oldpat=mp->pattern,idnum=0,flag=0,d;
+ Stk_t *stkp = mp->shp->stk;
+retry1:
+ mp->zeros = 0;
+ idbuff[0] = 0;
+ idbuff[1] = 0;
+ c = fcmbget(&LEN);
+ switch(isascii(c)?sh_lexstates[ST_DOL][c]:S_ALP)
+ {
+ case S_RBRA:
+ if(type<M_SIZE)
+ goto nosub;
+ /* This code handles ${#} */
+ c = mode;
+ mode = type = 0;
+ /* FALL THRU */
+ case S_SPC1:
+ if(type==M_BRACE)
+ {
+ if(isaletter(mode=fcpeek(0)) || mode=='.')
+ {
+ if(c=='#')
+ type = M_SIZE;
+#ifdef SHOPT_TYPEDEF
+ else if(c=='@')
+ {
+ type = M_TYPE;
+ goto retry1;
+ }
+#endif /* SHOPT_TYPEDEF */
+ else
+ type = M_VNAME;
+ mode = c;
+ goto retry1;
+ }
+ else if(c=='#' && (isadigit(mode)||fcpeek(1)==RBRACE))
+ {
+ type = M_SIZE;
+ mode = c;
+ goto retry1;
+ }
+ }
+ /* FALL THRU */
+ case S_SPC2:
+ var = 0;
+ *id = c;
+ v = special(mp->shp,c);
+ if(isastchar(c))
+ {
+ mode = c;
+#if SHOPT_FILESCAN
+ if(mp->shp->cur_line)
+ {
+ v = getdolarg(mp->shp,1,(int*)0);
+ dolmax = MAX_ARGN;
+ }
+ else
+#endif /* SHOPT_FILESCAN */
+ dolmax = mp->shp->st.dolc+1;
+ mp->atmode = (v && mp->quoted && c=='@');
+ dolg = (v!=0);
+ }
+ break;
+ case S_LBRA:
+ if(type)
+ goto nosub;
+ type = M_BRACE;
+ goto retry1;
+ case S_PAR:
+ if(type)
+ goto nosub;
+ comsubst(mp,(Shnode_t*)0,1);
+ return(1);
+ case S_DIG:
+ var = 0;
+ c -= '0';
+ mp->shp->argaddr = 0;
+ if(type)
+ {
+ register int d;
+ while((d=fcget()),isadigit(d))
+ c = 10*c + (d-'0');
+ fcseek(-1);
+ }
+ idnum = c;
+ if(c==0)
+ v = special(mp->shp,c);
+#if SHOPT_FILESCAN
+ else if(mp->shp->cur_line)
+ {
+ mp->shp->used_pos = 1;
+ v = getdolarg(mp->shp,c,&vsize);
+ }
+#endif /* SHOPT_FILESCAN */
+ else if(c <= mp->shp->st.dolc)
+ {
+ mp->shp->used_pos = 1;
+ v = mp->shp->st.dolv[c];
+ }
+ else
+ v = 0;
+ break;
+ case S_ALP:
+ if(c=='.' && type==0)
+ goto nosub;
+ offset = stktell(stkp);
+ do
+ {
+ register int d;
+ np = 0;
+ do
+ {
+ if(LEN==1)
+ sfputc(stkp,c);
+ else
+ sfwrite(stkp,fcseek(0)-LEN,LEN);
+ }
+ while((d=c,(c=fcmbget(&LEN)),isaname(c))||type && c=='.');
+ while(c==LBRACT && (type||mp->arrayok))
+ {
+ mp->shp->argaddr=0;
+ if((c=fcmbget(&LEN),isastchar(c)) && fcpeek(0)==RBRACT && d!='.')
+ {
+ if(type==M_VNAME)
+ type = M_SUBNAME;
+ idbuff[0] = mode = c;
+ fcget();
+ c = fcmbget(&LEN);
+ if(c=='.' || c==LBRACT)
+ {
+ sfputc(stkp,LBRACT);
+ sfputc(stkp,mode);
+ sfputc(stkp,RBRACT);
+ }
+ else
+ flag = NV_ARRAY;
+ break;
+ }
+ else
+ {
+ fcseek(-LEN);
+ c = stktell(stkp);
+ if(d!='.')
+ sfputc(stkp,LBRACT);
+ v = stkptr(stkp,subcopy(mp,1));
+ if(type && mp->dotdot)
+ {
+ mode = '@';
+ v[-1] = 0;
+ if(type==M_VNAME)
+ type = M_SUBNAME;
+ else if(type==M_SIZE)
+ goto nosub;
+ }
+ else if(d!='.')
+ sfputc(stkp,RBRACT);
+ c = fcmbget(&LEN);
+ if(c==0 && type==M_VNAME)
+ type = M_SUBNAME;
+ }
+ }
+ }
+ while(type && c=='.');
+ if(type!=M_VNAME && c==RBRACE && type && fcpeek(-2)=='.')
+ {
+ /* ${x.} or ${x..} */
+ if(fcpeek(-3) == '.')
+ {
+ stkseek(stkp,stktell(stkp)-2);
+ nv_local = 1;
+ }
+ else
+ {
+ stkseek(stkp,stktell(stkp)-1);
+ type = M_TREE;
+ }
+ }
+ sfputc(stkp,0);
+ id=stkptr(stkp,offset);
+ if(isastchar(c) && type)
+ {
+ if(type==M_VNAME || type==M_SIZE)
+ {
+ idbuff[0] = mode = c;
+ if((d=fcpeek(0))==c)
+ idbuff[1] = fcget();
+ if(type==M_VNAME)
+ type = M_NAMESCAN;
+ else
+ type = M_NAMECOUNT;
+ break;
+ }
+ goto nosub;
+ }
+ flag |= NV_NOASSIGN|NV_VARNAME|NV_NOADD;
+ if(c=='=' || c=='?' || (c==':' && ((d=fcpeek(0))=='=' || d=='?')))
+ {
+ if(c=='=' || (c==':' && d=='='))
+ flag |= NV_ASSIGN;
+ flag &= ~NV_NOADD;
+ }
+#if SHOPT_FILESCAN
+ if(mp->shp->cur_line && *id=='R' && strcmp(id,"REPLY")==0)
+ {
+ mp->shp->argaddr=0;
+ np = REPLYNOD;
+ }
+ else
+#endif /* SHOPT_FILESCAN */
+ {
+ if(mp->shp->argaddr)
+ flag &= ~NV_NOADD;
+ np = nv_open(id,mp->shp->var_tree,flag|NV_NOFAIL);
+ if(!np)
+ {
+ sfprintf(mp->shp->strbuf,"%s%c",id,0);
+ id = sfstruse(mp->shp->strbuf);
+ }
+ }
+ if(isastchar(mode))
+ var = 0;
+ if((!np || nv_isnull(np)) && type==M_BRACE && c==RBRACE && !(flag&NV_ARRAY) && strchr(id,'.'))
+ {
+ if(sh_macfun(mp->shp,id,offset))
+ {
+ fcmbget(&LEN);
+ return(1);
+ }
+ }
+ if(np && (flag&NV_NOADD) && nv_isnull(np))
+ {
+ if(nv_isattr(np,NV_NOFREE))
+ nv_offattr(np,NV_NOFREE);
+#if SHOPT_FILESCAN
+ else if(np!=REPLYNOD || !mp->shp->cur_line)
+#else
+ else
+#endif /* SHOPT_FILESCAN */
+ np = 0;
+ }
+ ap = np?nv_arrayptr(np):0;
+ if(type)
+ {
+ if(mp->dotdot)
+ {
+ Namval_t *nq;
+#if SHOPT_FIXEDARRAY
+ if(ap && !ap->fixed && (nq=nv_opensub(np)))
+#else
+ if(ap && (nq=nv_opensub(np)))
+#endif /* SHOPT_FIXEDARRAY */
+ ap = nv_arrayptr(np=nq);
+ if(ap)
+ {
+ nv_putsub(np,v,ARRAY_SCAN);
+ v = stkptr(stkp,mp->dotdot);
+ dolmax =1;
+ if(array_assoc(ap))
+ arrmax = strdup(v);
+ else if((dolmax = (int)sh_arith(mp->shp,v))<0)
+ dolmax += array_maxindex(np);
+ if(type==M_SUBNAME)
+ bysub = 1;
+ }
+ else
+ {
+ if((int)sh_arith(mp->shp,v))
+ np = 0;
+ }
+ }
+ else if(ap && (isastchar(mode)||type==M_TREE) && !(ap->nelem&ARRAY_SCAN) && type!=M_SIZE)
+ nv_putsub(np,NIL(char*),ARRAY_SCAN);
+ if(!isbracechar(c))
+ goto nosub;
+ else
+ fcseek(-LEN);
+ }
+ else
+ fcseek(-1);
+ if(type<=1 && np && nv_isvtree(np) && mp->pattern==1 && !mp->split)
+ {
+ int cc=fcmbget(&LEN),peek=LEN;
+ if(type && cc=='}')
+ {
+ cc = fcmbget(&LEN);
+ peek++;
+ }
+ if(mp->quote && cc=='"')
+ {
+ cc = fcmbget(&LEN);
+ peek++;
+ }
+ fcseek(-peek);
+ if(cc==0)
+ mp->assign = 1;
+ }
+ if((type==M_VNAME||type==M_SUBNAME) && mp->shp->argaddr && strcmp(nv_name(np),id))
+ mp->shp->argaddr = 0;
+ c = (type>M_BRACE && isastchar(mode));
+ if(np && (type==M_TREE || !c || !ap))
+ {
+ char *savptr;
+ c = *((unsigned char*)stkptr(stkp,offset-1));
+ savptr = stkfreeze(stkp,0);
+ if(type==M_VNAME || (type==M_SUBNAME && ap))
+ {
+ type = M_BRACE;
+ v = nv_name(np);
+ if(ap && !mp->dotdot && !(ap->nelem&ARRAY_UNDEF))
+ addsub = 1;
+ }
+#ifdef SHOPT_TYPEDEF
+ else if(type==M_TYPE)
+ {
+ Namval_t *nq = nv_type(np);
+ type = M_BRACE;
+ if(nq)
+ nv_typename(nq,mp->shp->strbuf);
+ else
+ nv_attribute(np,mp->shp->strbuf,"typeset",1);
+ v = sfstruse(mp->shp->strbuf);
+ }
+#endif /* SHOPT_TYPEDEF */
+#if SHOPT_FILESCAN
+ else if(mp->shp->cur_line && np==REPLYNOD)
+ v = mp->shp->cur_line;
+#endif /* SHOPT_FILESCAN */
+ else if(type==M_TREE)
+ v = nv_getvtree(np,(Namfun_t*)0);
+ else
+ {
+ if(type && fcpeek(0)=='+')
+ {
+ if(ap)
+ v = nv_arrayisset(np,ap)?(char*)"x":0;
+ else
+ v = nv_isnull(np)?0:(char*)"x";
+ }
+ else
+ v = nv_getval(np);
+ mp->atmode = (v && mp->quoted && mode=='@');
+ /* special case --- ignore leading zeros */
+ if( (mp->arith||mp->let) && (np->nvfun || nv_isattr(np,(NV_LJUST|NV_RJUST|NV_ZFILL))) && !nv_isattr(np,NV_INTEGER) && (offset==0 || !isalnum(c)))
+ mp->zeros = 1;
+ }
+ if(savptr==stakptr(0))
+ stkseek(stkp,offset);
+ else
+ stkset(stkp,savptr,offset);
+ }
+ else
+ {
+ if(sh_isoption(SH_NOUNSET) && !isastchar(mode) && (type==M_VNAME || type==M_SIZE))
+ errormsg(SH_DICT,ERROR_exit(1),e_notset,id);
+ v = 0;
+ if(type==M_VNAME)
+ {
+ v = id;
+ type = M_BRACE;
+ }
+ else if(type==M_TYPE)
+ type = M_BRACE;
+ }
+ stkseek(stkp,offset);
+ if(ap)
+ {
+#if SHOPT_OPTIMIZE
+ if(mp->shp->argaddr)
+ nv_optimize(np);
+#endif
+ if(isastchar(mode) && array_elem(ap)> !c)
+ dolg = -1;
+ else
+ dolg = 0;
+ }
+ break;
+ case S_EOF:
+ fcseek(-1);
+ default:
+ goto nosub;
+ }
+ c = fcmbget(&LEN);
+ if(type>M_TREE)
+ {
+ if(c!=RBRACE)
+ mac_error(np);
+ if(type==M_NAMESCAN || type==M_NAMECOUNT)
+ {
+ mp->shp->last_root = mp->shp->var_tree;
+ id = idx = prefix(mp->shp,id);
+ stkseek(stkp,offset);
+ if(type==M_NAMECOUNT)
+ {
+ c = namecount(mp,id);
+ v = ltos(c);
+ }
+ else
+ {
+ dolmax = strlen(id);
+ dolg = -1;
+ nextname(mp,id,0);
+ v = nextname(mp,id,dolmax);
+ }
+ }
+ else if(type==M_SUBNAME)
+ {
+ if(dolg<0)
+ {
+ v = nv_getsub(np);
+ bysub=1;
+ }
+ else if(v)
+ {
+ if(!ap || isastchar(mode))
+ v = "0";
+ else
+ v = nv_getsub(np);
+ }
+ }
+ else
+ {
+ if(!isastchar(mode))
+ c = charlen(v,vsize);
+ else if(dolg>0)
+ {
+#if SHOPT_FILESCAN
+ if(mp->shp->cur_line)
+ {
+ getdolarg(mp->shp,MAX_ARGN,(int*)0);
+ c = mp->shp->offsets[0];
+ }
+ else
+#endif /* SHOPT_FILESCAN */
+ c = mp->shp->st.dolc;
+ }
+ else if(dolg<0)
+ c = array_elem(ap);
+ else
+ c = (v!=0);
+ dolg = dolmax = 0;
+ v = ltos(c);
+ }
+ c = RBRACE;
+ }
+ nulflg = 0;
+ if(type && c==':')
+ {
+ c = fcmbget(&LEN);
+ if(isascii(c) &&sh_lexstates[ST_BRACE][c]==S_MOD1 && c!='*' && c!= ':')
+ nulflg=1;
+ else if(c!='%' && c!='#')
+ {
+ fcseek(-LEN);
+ c = ':';
+ }
+ }
+ if(type)
+ {
+ if(!isbracechar(c))
+ {
+ if(!nulflg)
+ mac_error(np);
+ fcseek(-LEN);
+ c = ':';
+ }
+ if(c!=RBRACE)
+ {
+ int newops = (c=='#' || c == '%' || c=='/');
+ offset = stktell(stkp);
+ if(newops && sh_isoption(SH_NOUNSET) && *id && id!=idbuff && (!np || nv_isnull(np)))
+ errormsg(SH_DICT,ERROR_exit(1),e_notset,id);
+ if(c=='/' ||c==':' || ((!v || (nulflg && *v==0)) ^ (c=='+'||c=='#'||c=='%')))
+ {
+ int newquote = mp->quote;
+ int split = mp->split;
+ int quoted = mp->quoted;
+ int arith = mp->arith;
+ int zeros = mp->zeros;
+ int assign = mp->assign;
+ if(newops)
+ {
+ type = fcget();
+ if(type=='%' || type=='#')
+ {
+ int d = fcmbget(&LEN);
+ fcseek(-LEN);
+ if(d=='(')
+ type = 0;
+ }
+ fcseek(-1);
+ mp->pattern = 1+(c=='/');
+ mp->split = 0;
+ mp->quoted = 0;
+ mp->assign &= ~1;
+ mp->arith = mp->zeros = 0;
+ newquote = 0;
+ }
+ else if(c=='?' || c=='=')
+ mp->split = mp->pattern = 0;
+ copyto(mp,RBRACE,newquote);
+ if(!oldpat)
+ mp->patfound = 0;
+ mp->pattern = oldpat;
+ mp->split = split;
+ mp->quoted = quoted;
+ mp->arith = arith;
+ mp->zeros = zeros;
+ mp->assign = assign;
+ /* add null byte */
+ sfputc(stkp,0);
+ stkseek(stkp,stktell(stkp)-1);
+ }
+ else
+ {
+ sh_lexskip(lp,RBRACE,0,(!newops&&mp->quote)?ST_QUOTE:ST_NESTED);
+ stkseek(stkp,offset);
+ }
+ argp=stkptr(stkp,offset);
+ }
+ }
+ else
+ {
+ fcseek(-1);
+ c=0;
+ }
+ if(c==':') /* ${name:expr1[:expr2]} */
+ {
+ char *ptr;
+ type = (int)sh_strnum(argp,&ptr,1);
+ if(isastchar(mode))
+ {
+ if(id==idbuff) /* ${@} or ${*} */
+ {
+ if(type<0 && (type+= dolmax)<0)
+ type = 0;
+ if(type==0)
+ v = special(mp->shp,dolg=0);
+#if SHOPT_FILESCAN
+ else if(mp->shp->cur_line)
+ {
+ v = getdolarg(mp->shp,dolg=type,&vsize);
+ if(!v)
+ dolmax = type;
+ }
+#endif /* SHOPT_FILESCAN */
+ else if(type < dolmax)
+ v = mp->shp->st.dolv[dolg=type];
+ else
+ v = 0;
+ }
+ else if(ap)
+ {
+ if(type<0)
+ {
+ if(array_assoc(ap))
+ type = -type;
+ else
+ type += array_maxindex(np);
+ }
+ if(array_assoc(ap))
+ {
+ while(type-- >0 && (v=0,nv_nextsub(np)))
+ v = nv_getval(np);
+ }
+ else if(type > 0)
+ {
+ if(nv_putsub(np,NIL(char*),type|ARRAY_SCAN))
+ v = nv_getval(np);
+ else
+ v = 0;
+ }
+ }
+ else if(type>0)
+ v = 0;
+ if(!v)
+ mp->atmode = 0;
+ }
+ else if(v)
+ {
+ vsize = charlen(v,vsize);
+ if(type<0 && (type += vsize)<0)
+ type = 0;
+ if(vsize < type)
+ v = 0;
+#if SHOPT_MULTIBYTE
+ else if(mbwide())
+ {
+ mbinit();
+ for(c=type;c;c--)
+ mbchar(v);
+ c = ':';
+ }
+#endif /* SHOPT_MULTIBYTE */
+ else
+ v += type;
+ vsize = v?strlen(v):0;
+ }
+ if(*ptr==':')
+ {
+ if((type = (int)sh_strnum(ptr+1,&ptr,1)) <=0)
+ v = 0;
+ else if(isastchar(mode))
+ {
+ if(dolg>=0)
+ {
+ if(dolg+type < dolmax)
+ dolmax = dolg+type;
+ }
+ else
+ dolmax = type;
+ }
+ else if(type < vsize)
+ {
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ {
+ char *vp = v;
+ mbinit();
+ while(type-->0)
+ {
+ if((c=mbsize(vp))<1)
+ c = 1;
+ vp += c;
+ }
+ type = vp-v;
+ c = ':';
+ }
+#endif /* SHOPT_MULTIBYTE */
+ vsize = type;
+ }
+ else
+ vsize = v?strlen(v):0;
+ }
+ if(*ptr)
+ mac_error(np);
+ stkseek(stkp,offset);
+ argp = 0;
+ }
+ /* check for substring operations */
+ else if(c == '#' || c == '%' || c=='/')
+ {
+ if(c=='/')
+ {
+ if(type=='/' || type=='#' || type=='%')
+ {
+ c = type;
+ type = '/';
+ argp++;
+ }
+ else
+ type = 0;
+ }
+ else
+ {
+ if(type==c) /* ## or %% */
+ argp++;
+ else
+ type = 0;
+ }
+ pattern = strdup(argp);
+ if((type=='/' || c=='/') && (repstr = mac_getstring(pattern)))
+ {
+ Mac_t savemac;
+ char *first = fcseek(0);
+ int n = stktell(stkp);
+ savemac = *mp;
+ fcsopen(repstr);
+ mp->pattern = 3;
+ mp->split = 0;
+ copyto(mp,0,0);
+ sfputc(stkp,0);
+ repstr = strdup(stkptr(stkp,n));
+ replen = strlen(repstr);
+ stkseek(stkp,n);
+ *mp = savemac;
+ fcsopen(first);
+ }
+ if(v || c=='/' && offset>=0)
+ stkseek(stkp,offset);
+ }
+ /* check for quoted @ */
+ if(mode=='@' && mp->quote && !v && c!='-')
+ mp->quoted-=2;
+retry2:
+ if(v && (!nulflg || *v ) && c!='+')
+ {
+ register int d = (mode=='@'?' ':mp->ifs);
+ int match[2*(MATCH_MAX+1)], nmatch, nmatch_prev, vsize_last;
+ char *vlast;
+ while(1)
+ {
+ if(!v)
+ v= "";
+ if(c=='/' || c=='#' || c== '%')
+ {
+ int index = 0;
+ flag = (type || c=='/')?(STR_GROUP|STR_MAXIMAL):STR_GROUP;
+ if(c!='/')
+ flag |= STR_LEFT;
+ nmatch = 0;
+ while(1)
+ {
+ vsize = strlen(v);
+ nmatch_prev = nmatch;
+ if(c=='%')
+ nmatch=substring(v,pattern,match,flag&STR_MAXIMAL);
+ else
+ nmatch=strgrpmatch(v,pattern,match,elementsof(match)/2,flag);
+ if(nmatch && replen>0)
+ sh_setmatch(mp->shp,v,vsize,nmatch,match,index++);
+ if(nmatch)
+ {
+ vlast = v;
+ vsize_last = vsize;
+ vsize = match[0];
+ }
+ else if(c=='#')
+ vsize = 0;
+ if(vsize)
+ mac_copy(mp,v,vsize);
+ if(nmatch && replen>0 && (match[1] || !nmatch_prev))
+ mac_substitute(mp,repstr,v,match,nmatch);
+ if(nmatch==0)
+ v += vsize;
+ else
+ v += match[1];
+ if(*v && c=='/' && type)
+ {
+ /* avoid infinite loop */
+ if(nmatch && match[1]==0)
+ {
+ nmatch = 0;
+ mac_copy(mp,v,1);
+ v++;
+ }
+ continue;
+ }
+ vsize = -1;
+ break;
+ }
+ if(replen==0)
+ sh_setmatch(mp->shp,vlast,vsize_last,nmatch,match,index++);
+ }
+ if(vsize)
+ mac_copy(mp,v,vsize>0?vsize:strlen(v));
+ if(addsub)
+ {
+ mp->shp->instance++;
+ sfprintf(mp->shp->strbuf,"[%s]",nv_getsub(np));
+ mp->shp->instance--;
+ v = sfstruse(mp->shp->strbuf);
+ mac_copy(mp, v, strlen(v));
+ }
+ if(dolg==0 && dolmax==0)
+ break;
+ if(mp->dotdot)
+ {
+ if(nv_nextsub(np) == 0)
+ break;
+ if(bysub)
+ v = nv_getsub(np);
+ else
+ v = nv_getval(np);
+ if(array_assoc(ap))
+ {
+ if(strcmp(bysub?v:nv_getsub(np),arrmax)>0)
+ break;
+ }
+ else
+ {
+ if(nv_aindex(np) > dolmax)
+ break;
+ }
+ }
+ else if(dolg>=0)
+ {
+ if(++dolg >= dolmax)
+ break;
+#if SHOPT_FILESCAN
+ if(mp->shp->cur_line)
+ {
+ if(dolmax==MAX_ARGN && isastchar(mode))
+ break;
+ if(!(v=getdolarg(mp->shp,dolg,&vsize)))
+ {
+ dolmax = dolg;
+ break;
+ }
+ }
+ else
+#endif /* SHOPT_FILESCAN */
+ v = mp->shp->st.dolv[dolg];
+ }
+ else if(!np)
+ {
+ if(!(v = nextname(mp,id,dolmax)))
+ break;
+ }
+ else
+ {
+ if(dolmax && --dolmax <=0)
+ {
+ nv_putsub(np,NIL(char*),ARRAY_UNDEF);
+ break;
+ }
+ if(ap)
+ ap->nelem |= ARRAY_SCAN;
+ if(nv_nextsub(np) == 0)
+ break;
+ if(bysub)
+ v = nv_getsub(np);
+ else
+ v = nv_getval(np);
+ }
+ if(mp->split && (!mp->quote || mode=='@'))
+ {
+ if(!np)
+ mp->pattern = 0;
+ endfield(mp,mp->quoted);
+ mp->atmode = mode=='@';
+ mp->pattern = oldpat;
+ }
+ else if(d)
+ {
+ if(mp->sp)
+ sfputc(mp->sp,d);
+ else
+ sfputc(stkp,d);
+ }
+ }
+ if(arrmax)
+ free((void*)arrmax);
+ }
+ else if(argp)
+ {
+ if(c=='/' && replen>0 && pattern && strmatch("",pattern))
+ mac_substitute(mp,repstr,v,0,0);
+ if(c=='?')
+ {
+ if(np)
+ id = nv_name(np);
+ else if(idnum)
+ id = ltos(idnum);
+ if(*argp)
+ {
+ sfputc(stkp,0);
+ errormsg(SH_DICT,ERROR_exit(1),"%s: %s",id,argp);
+ }
+ else if(v)
+ errormsg(SH_DICT,ERROR_exit(1),e_nullset,id);
+ else
+ errormsg(SH_DICT,ERROR_exit(1),e_notset,id);
+ }
+ else if(c=='=')
+ {
+ if(np)
+ {
+ if(mp->shp->subshell)
+ np = sh_assignok(np,1);
+ nv_putval(np,argp,0);
+ v = nv_getval(np);
+ nulflg = 0;
+ stkseek(stkp,offset);
+ goto retry2;
+ }
+ else
+ mac_error(np);
+ }
+ }
+ else if(var && sh_isoption(SH_NOUNSET) && type<=M_TREE && (!np || nv_isnull(np) || (nv_isarray(np) && !np->nvalue.cp)))
+ {
+ if(np)
+ {
+ if(nv_isarray(np))
+ {
+ sfprintf(mp->shp->strbuf,"%s[%s]\0",nv_name(np),nv_getsub(np));
+ id = sfstruse(mp->shp->strbuf);
+ }
+ else
+ id = nv_name(np);
+ nv_close(np);
+ }
+ errormsg(SH_DICT,ERROR_exit(1),e_notset,id);
+ }
+ if(np)
+ nv_close(np);
+ if(pattern)
+ free(pattern);
+ if(repstr)
+ free(repstr);
+ if(idx)
+ free(idx);
+ return(1);
+nosub:
+ if(type==M_BRACE && sh_lexstates[ST_NORM][c]==S_BREAK)
+ {
+ fcseek(-1);
+ comsubst(mp,(Shnode_t*)0,2);
+ return(1);
+ }
+ if(type)
+ mac_error(np);
+ fcseek(-1);
+ nv_close(np);
+ return(0);
+}
+
+/*
+ * This routine handles command substitution
+ * <type> is 0 for older `...` version
+ */
+static void comsubst(Mac_t *mp,register Shnode_t* t, int type)
+{
+ Sfdouble_t num;
+ register int c;
+ register char *str;
+ Sfio_t *sp;
+ Stk_t *stkp = mp->shp->stk;
+ Fcin_t save;
+ struct slnod *saveslp = mp->shp->st.staklist;
+ struct _mac_ savemac;
+ int savtop = stktell(stkp);
+ char lastc=0, *savptr = stkfreeze(stkp,0);
+#if SHOPT_MULTIBYTE
+ wchar_t lastw=0;
+#endif /* SHOPT_MULTIBYTE */
+ int was_history = sh_isstate(SH_HISTORY);
+ int was_verbose = sh_isstate(SH_VERBOSE);
+ int was_interactive = sh_isstate(SH_INTERACTIVE);
+ int newlines,bufsize,nextnewlines;
+ Namval_t *np;
+ mp->shp->argaddr = 0;
+ savemac = *mp;
+ mp->shp->st.staklist=0;
+#ifdef SHOPT_COSHELL
+ if(mp->shp->inpool)
+ return;
+#endif /*SHOPT_COSHELL */
+ if(type)
+ {
+ sp = 0;
+ fcseek(-1);
+ if(!t)
+ t = sh_dolparen((Lex_t*)mp->shp->lex_context);
+ if(t && t->tre.tretyp==TARITH)
+ {
+ mp->shp->inarith = 1;
+ fcsave(&save);
+ if(t->ar.arcomp)
+ num = arith_exec(t->ar.arcomp);
+ else if((t->ar.arexpr->argflag&ARG_RAW))
+ num = sh_arith(mp->shp,t->ar.arexpr->argval);
+ else
+ num = sh_arith(mp->shp,sh_mactrim(mp->shp,t->ar.arexpr->argval,3));
+ mp->shp->inarith = 0;
+ out_offset:
+ stkset(stkp,savptr,savtop);
+ *mp = savemac;
+ if((Sflong_t)num!=num)
+ sfprintf(mp->shp->strbuf,"%.*Lg",LDBL_DIG,num);
+ else if(num)
+ sfprintf(mp->shp->strbuf,"%lld",(Sflong_t)num);
+ else
+ sfprintf(mp->shp->strbuf,"%Lg",num);
+ str = sfstruse(mp->shp->strbuf);
+ mac_copy(mp,str,strlen(str));
+ mp->shp->st.staklist = saveslp;
+ fcrestore(&save);
+ return;
+ }
+ }
+ else
+ {
+ while(fcgetc(c)!='`' && c)
+ {
+ if(c==ESCAPE)
+ {
+ fcgetc(c);
+ if(!(isescchar(sh_lexstates[ST_QUOTE][c]) ||
+ (c=='"' && mp->quote)))
+ sfputc(stkp,ESCAPE);
+ }
+ sfputc(stkp,c);
+ }
+ c = stktell(stkp);
+ str=stkfreeze(stkp,1);
+ /* disable verbose and don't save in history file */
+ sh_offstate(SH_HISTORY);
+ sh_offstate(SH_VERBOSE);
+ if(mp->sp)
+ sfsync(mp->sp); /* flush before executing command */
+ sp = sfnew(NIL(Sfio_t*),str,c,-1,SF_STRING|SF_READ);
+ c = mp->shp->inlineno;
+ mp->shp->inlineno = error_info.line+mp->shp->st.firstline;
+ t = (Shnode_t*)sh_parse(mp->shp, sp,SH_EOF|SH_NL);
+ mp->shp->inlineno = c;
+ type = 1;
+ }
+#if KSHELL
+ if(t)
+ {
+ fcsave(&save);
+ sfclose(sp);
+ if(t->tre.tretyp==0 && !t->com.comarg && !t->com.comset)
+ {
+ /* special case $(<file) and $(<#file) */
+ register int fd;
+ int r;
+ struct checkpt buff;
+ struct ionod *ip=0;
+ sh_pushcontext(mp->shp,&buff,SH_JMPIO);
+ if((ip=t->tre.treio) &&
+ ((ip->iofile&IOLSEEK) || !(ip->iofile&IOUFD)) &&
+ (r=sigsetjmp(buff.buff,0))==0)
+ fd = sh_redirect(mp->shp,ip,3);
+ else
+ fd = sh_chkopen(e_devnull);
+ sh_popcontext(mp->shp,&buff);
+ if(r==0 && ip && (ip->iofile&IOLSEEK))
+ {
+ if(sp=mp->shp->sftable[fd])
+ num = sftell(sp);
+ else
+ num = lseek(fd, (off_t)0, SEEK_CUR);
+ goto out_offset;
+ }
+ sp = sfnew(NIL(Sfio_t*),(char*)malloc(IOBSIZE+1),IOBSIZE,fd,SF_READ|SF_MALLOC);
+ type = 3;
+ }
+ else
+ sp = sh_subshell(mp->shp,t,sh_isstate(SH_ERREXIT),type);
+ fcrestore(&save);
+ }
+ else
+ sp = sfopen(NIL(Sfio_t*),"","sr");
+ sh_freeup(mp->shp);
+ mp->shp->st.staklist = saveslp;
+ if(was_history)
+ sh_onstate(SH_HISTORY);
+ if(was_verbose)
+ sh_onstate(SH_VERBOSE);
+#else
+ sp = sfpopen(NIL(Sfio_t*),str,"r");
+#endif
+ *mp = savemac;
+ np = sh_scoped(mp->shp,IFSNOD);
+ nv_putval(np,mp->ifsp,NV_RDONLY);
+ mp->ifsp = nv_getval(np);
+ stkset(stkp,savptr,savtop);
+ newlines = 0;
+ sfsetbuf(sp,(void*)sp,0);
+ bufsize = sfvalue(sp);
+ /* read command substitution output and put on stack or here-doc */
+ sfpool(sp, NIL(Sfio_t*), SF_WRITE);
+ sh_offstate(SH_INTERACTIVE);
+ while((str=(char*)sfreserve(sp,SF_UNBOUND,0)) && (c=bufsize=sfvalue(sp))>0)
+ {
+#if SHOPT_CRNL
+ /* eliminate <cr> */
+ register char *dp;
+ char *buff = str;
+ while(c>1 && (*str !='\r'|| str[1]!='\n'))
+ {
+ c--;
+ str++;
+ }
+ dp = str;
+ while(c>1)
+ {
+ str++;
+ c--;
+ while(c>1 && (*str!='\r' || str[1]!='\n'))
+ {
+ c--;
+ *dp++ = *str++;
+ }
+ }
+ if(c)
+ *dp++ = *str++;
+ str = buff;
+ c = dp-str;
+#endif /* SHOPT_CRNL */
+ /* delay appending trailing new-lines */
+ for(nextnewlines=0; c-->0 && str[c]=='\n'; nextnewlines++);
+ if(c < 0)
+ {
+ newlines += nextnewlines;
+ continue;
+ }
+ if(newlines >0)
+ {
+ if(mp->sp)
+ sfnputc(mp->sp,'\n',newlines);
+ else if(!mp->quote && mp->split && mp->shp->ifstable['\n'])
+ endfield(mp,0);
+ else
+ sfnputc(stkp,'\n',newlines);
+ }
+ else if(lastc)
+ {
+#if SHOPT_MULTIBYTE
+ if(lastw)
+ {
+ int n;
+ char mb[8];
+ n = mbconv(mb, lastw);
+ mac_copy(mp,mb,n);
+ lastw = 0;
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ mac_copy(mp,&lastc,1);
+ lastc = 0;
+ }
+ newlines = nextnewlines;
+ if(++c < bufsize)
+ str[c] = 0;
+ else
+ {
+ ssize_t len = 1;
+
+ /* can't write past buffer so save last character */
+#if SHOPT_MULTIBYTE
+ if ((len = mbsize(str))>1)
+ {
+ len = mb2wc(lastw,str,len);
+ if (len < 0)
+ {
+ lastw = 0;
+ len = 1;
+ }
+ }
+#endif /* SHOPT_MULTIBYTE */
+ c -= len;
+ lastc = str[c];
+ str[c] = 0;
+ }
+ mac_copy(mp,str,c);
+ }
+ if(was_interactive)
+ sh_onstate(SH_INTERACTIVE);
+ if(--newlines>0 && mp->shp->ifstable['\n']==S_DELIM)
+ {
+ if(mp->sp)
+ sfnputc(mp->sp,'\n',newlines);
+ else if(!mp->quote && mp->split)
+ while(newlines--)
+ endfield(mp,1);
+ else
+ sfnputc(stkp,'\n',newlines);
+ }
+ if(lastc)
+ {
+#if SHOPT_MULTIBYTE
+ if(lastw)
+ {
+ int n;
+ char mb[8];
+ n = mbconv(mb, lastw);
+ mac_copy(mp,mb,n);
+ lastw = 0;
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ mac_copy(mp,&lastc,1);
+ lastc = 0;
+ }
+ sfclose(sp);
+ return;
+}
+
+/*
+ * copy <str> onto the stack
+ */
+static void mac_copy(register Mac_t *mp,register const char *str, register int size)
+{
+ register char *state;
+ register const char *cp=str;
+ register int c,n,nopat,len;
+ Stk_t *stkp=mp->shp->stk;
+ int oldpat = mp->pattern;
+ nopat = (mp->quote||(mp->assign==1)||mp->arith);
+ if(mp->zeros)
+ {
+ /* prevent leading 0's from becomming octal constants */
+ while(size>1 && *str=='0')
+ str++,size--;
+ mp->zeros = 0;
+ cp = str;
+ }
+ if(mp->sp)
+ sfwrite(mp->sp,str,size);
+ else if(mp->pattern>=2 || (mp->pattern && nopat) || mp->assign==3)
+ {
+ state = sh_lexstates[ST_MACRO];
+ /* insert \ before file expansion characters */
+ while(size-->0)
+ {
+#if SHOPT_MULTIBYTE
+ if(mbwide() && (len=mbsize(cp))>1)
+ {
+ cp += len;
+ size -= (len-1);
+ continue;
+ }
+#endif
+ c = state[n= *(unsigned char*)cp++];
+ if(mp->assign==3 && mp->pattern!=4)
+ {
+ if(c==S_BRACT)
+ {
+ nopat = 0;
+ mp->pattern = 4;
+ }
+ continue;
+ }
+ if(nopat&&(c==S_PAT||c==S_ESC||c==S_BRACT||c==S_ENDCH) && mp->pattern!=3)
+ c=1;
+ else if(mp->pattern==4 && (c==S_ESC||c==S_BRACT||c==S_ENDCH || isastchar(n)))
+ {
+ if(c==S_ENDCH && oldpat!=4)
+ {
+ if(*cp==0 || *cp=='.' || *cp=='[')
+ {
+ mp->pattern = oldpat;
+ c=0;
+ }
+ else
+ c=1;
+ }
+ else
+ c=1;
+ }
+ else if(mp->pattern==2 && c==S_SLASH)
+ c=1;
+ else if(mp->pattern==3 && c==S_ESC && (state[*(unsigned char*)cp]==S_DIG||(*cp==ESCAPE)))
+ {
+ if(!(c=mp->quote))
+ cp++;
+ }
+ else
+ c=0;
+ if(c)
+ {
+ if(c = (cp-1) - str)
+ sfwrite(stkp,str,c);
+ sfputc(stkp,ESCAPE);
+ str = cp-1;
+ }
+ }
+ if(c = cp-str)
+ sfwrite(stkp,str,c);
+ }
+ else if(!mp->quote && mp->split && (mp->ifs||mp->pattern))
+ {
+ /* split words at ifs characters */
+ state = mp->shp->ifstable;
+ if(mp->pattern)
+ {
+ char *sp = "&|()";
+ while(c = *sp++)
+ {
+ if(state[c]==0)
+ state[c] = S_EPAT;
+ }
+ sp = "*?[{";
+ while(c = *sp++)
+ {
+ if(state[c]==0)
+ state[c] = S_PAT;
+ }
+ if(state[ESCAPE]==0)
+ state[ESCAPE] = S_ESC;
+ }
+ while(size-->0)
+ {
+ n=state[c= *(unsigned char*)cp++];
+#if SHOPT_MULTIBYTE
+ if(mbwide() && n!=S_MBYTE && (len=mbsize(cp-1))>1)
+ {
+ sfwrite(stkp,cp-1, len);
+ cp += --len;
+ size -= len;
+ continue;
+ }
+#endif
+ if(n==S_ESC || n==S_EPAT)
+ {
+ /* don't allow extended patterns in this case */
+ mp->patfound = mp->pattern;
+ sfputc(stkp,ESCAPE);
+ }
+ else if(n==S_PAT)
+ mp->patfound = mp->pattern;
+ else if(n && mp->ifs)
+ {
+#if SHOPT_MULTIBYTE
+ if(n==S_MBYTE)
+ {
+ if(sh_strchr(mp->ifsp,cp-1)<0)
+ continue;
+ n = mbsize(cp-1) - 1;
+ if(n==-2)
+ n = 0;
+ cp += n;
+ size -= n;
+ n= S_DELIM;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ if(n==S_SPACE || n==S_NL)
+ {
+ while(size>0 && ((n=state[c= *(unsigned char*)cp++])==S_SPACE||n==S_NL))
+ size--;
+#if SHOPT_MULTIBYTE
+ if(n==S_MBYTE && sh_strchr(mp->ifsp,cp-1)>=0)
+ {
+ n = mbsize(cp-1) - 1;
+ if(n==-2)
+ n = 0;
+ cp += n;
+ size -= n;
+ n=S_DELIM;
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ if(n==S_DELIM)
+ size--;
+ }
+ endfield(mp,n==S_DELIM||mp->quoted);
+ mp->patfound = 0;
+ if(n==S_DELIM)
+ while(size>0 && ((n=state[c= *(unsigned char*)cp++])==S_SPACE||n==S_NL))
+ size--;
+ if(size<=0)
+ break;
+ cp--;
+ continue;
+
+ }
+ sfputc(stkp,c);
+ }
+ if(mp->pattern)
+ {
+ cp = "&|()";
+ while(c = *cp++)
+ {
+ if(state[c]==S_EPAT)
+ state[c] = 0;
+ }
+ cp = "*?[{";
+ while(c = *cp++)
+ {
+ if(state[c]==S_PAT)
+ state[c] = 0;
+ }
+ if(mp->shp->ifstable[ESCAPE]==S_ESC)
+ mp->shp->ifstable[ESCAPE] = 0;
+ }
+ }
+ else
+ sfwrite(stkp,str,size);
+}
+
+/*
+ * Terminate field.
+ * If field is null count field if <split> is non-zero
+ * Do filename expansion of required
+ */
+static void endfield(register Mac_t *mp,int split)
+{
+ register struct argnod *argp;
+ register int count=0;
+ Stk_t *stkp = mp->shp->stk;
+ if(stktell(stkp) > ARGVAL || split)
+ {
+ argp = (struct argnod*)stkfreeze(stkp,1);
+ argp->argnxt.cp = 0;
+ argp->argflag = 0;
+ mp->atmode = 0;
+ if(mp->patfound)
+ {
+ mp->shp->argaddr = 0;
+#if SHOPT_BRACEPAT
+ count = path_generate(mp->shp,argp,mp->arghead);
+#else
+ count = path_expand(mp->shp,argp->argval,mp->arghead);
+#endif /* SHOPT_BRACEPAT */
+ if(count)
+ mp->fields += count;
+ else if(split) /* pattern is null string */
+ *argp->argval = 0;
+ else /* pattern expands to nothing */
+ count = -1;
+ }
+ if(count==0)
+ {
+ argp->argchn.ap = *mp->arghead;
+ *mp->arghead = argp;
+ mp->fields++;
+ }
+ if(count>=0)
+ {
+ (*mp->arghead)->argflag |= ARG_MAKE;
+ if(mp->assign || sh_isoption(SH_NOGLOB))
+ argp->argflag |= ARG_RAW|ARG_EXP;
+ }
+ stkseek(stkp,ARGVAL);
+ }
+ mp->quoted = mp->quote;
+}
+
+/*
+ * Finds the right substring of STRING using the expression PAT
+ * the longest substring is found when FLAG is set.
+ */
+static int substring(register const char *string,const char *pat,int match[], int flag)
+{
+ register const char *sp=string;
+ register int size,len,nmatch,n;
+ int smatch[2*(MATCH_MAX+1)];
+ if(flag)
+ {
+ if(n=strgrpmatch(sp,pat,smatch,elementsof(smatch)/2,STR_RIGHT|STR_MAXIMAL))
+ {
+ memcpy(match,smatch,n*2*sizeof(smatch[0]));
+ return(n);
+ }
+ return(0);
+ }
+ size = len = strlen(sp);
+ sp += size;
+ while(sp>=string)
+ {
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ sp = lastchar(string,sp);
+#endif /* SHOPT_MULTIBYTE */
+ if(n=strgrpmatch(sp,pat,smatch,elementsof(smatch)/2,STR_RIGHT|STR_LEFT|STR_MAXIMAL))
+ {
+ nmatch = n;
+ memcpy(match,smatch,n*2*sizeof(smatch[0]));
+ size = sp-string;
+ break;
+ }
+ sp--;
+ }
+ if(size==len)
+ return(0);
+ if(nmatch)
+ {
+ nmatch *=2;
+ while(--nmatch>=0)
+ match[nmatch] += size;
+ }
+ return(n);
+}
+
+#if SHOPT_MULTIBYTE
+ static char *lastchar(const char *string, const char *endstring)
+ {
+ register char *str = (char*)string;
+ register int c;
+ mbinit();
+ while(*str)
+ {
+ if((c=mbsize(str))<0)
+ c = 1;
+ if(str+c > endstring)
+ break;
+ str += c;
+ }
+ return(str);
+ }
+#endif /* SHOPT_MULTIBYTE */
+static int charlen(const char *string,int len)
+{
+ if(!string)
+ return(0);
+#if SHOPT_MULTIBYTE
+ if(mbwide())
+ {
+ register const char *str = string, *strmax=string+len;
+ register int n=0;
+ mbinit();
+ if(len>0)
+ {
+ while(str<strmax && mbchar(str))
+ n++;
+ }
+ else while(mbchar(str))
+ n++;
+ return(n);
+ }
+ else
+#endif /* SHOPT_MULTIBYTE */
+ {
+ if(len<0)
+ return(strlen(string));
+ return(len);
+ }
+}
+
+/*
+ * This is the default tilde discipline function
+ */
+static int sh_btilde(int argc, char *argv[], Shbltin_t *context)
+{
+ Shell_t *shp = context->shp;
+ char *cp = sh_tilde(shp,argv[1]);
+ NOT_USED(argc);
+ if(!cp)
+ cp = argv[1];
+ sfputr(sfstdout, cp, '\n');
+ return(0);
+}
+
+/*
+ * <offset> is byte offset for beginning of tilde string
+ */
+static void tilde_expand2(Shell_t *shp, register int offset)
+{
+ char shtilde[10], *av[3], *ptr=stkfreeze(shp->stk,1);
+ Sfio_t *iop, *save=sfstdout;
+ Namval_t *np;
+ static int beenhere=0;
+ strcpy(shtilde,".sh.tilde");
+ np = nv_open(shtilde,shp->fun_tree, NV_VARNAME|NV_NOARRAY|NV_NOASSIGN|NV_NOFAIL);
+ if(np && !beenhere)
+ {
+ beenhere = 1;
+ sh_addbuiltin(shtilde,sh_btilde,0);
+ nv_onattr(np,NV_EXPORT);
+ }
+ av[0] = ".sh.tilde";
+ av[1] = &ptr[offset];
+ av[2] = 0;
+ iop = sftmp((IOBSIZE>PATH_MAX?IOBSIZE:PATH_MAX)+1);
+ sfset(iop,SF_READ,0);
+ sfstdout = iop;
+ if(np)
+ sh_fun(np, (Namval_t*)0, av);
+ else
+ sh_btilde(2, av, &shp->bltindata);
+ sfstdout = save;
+ stkset(shp->stk,ptr, offset);
+ sfseek(iop,(Sfoff_t)0,SEEK_SET);
+ sfset(iop,SF_READ,1);
+ if(ptr = sfreserve(iop, SF_UNBOUND, -1))
+ {
+ Sfoff_t n = sfvalue(iop);
+ while(ptr[n-1]=='\n')
+ n--;
+ if(n==1 && fcpeek(0)=='/' && ptr[n-1])
+ n--;
+ if(n)
+ sfwrite(shp->stk,ptr,n);
+ }
+ else
+ sfputr(shp->stk,av[1],0);
+ sfclose(iop);
+}
+
+/*
+ * This routine is used to resolve ~ expansion.
+ * A ~ by itself is replaced with the users login directory.
+ * A ~- is replaced by the previous working directory in shell.
+ * A ~+ is replaced by the present working directory in shell.
+ * If ~name is replaced with login directory of name.
+ * If string doesn't start with ~ or ~... not found then 0 returned.
+ */
+
+static char *sh_tilde(Shell_t *shp,register const char *string)
+{
+ register char *cp;
+ register int c;
+ register struct passwd *pw;
+ register Namval_t *np=0;
+ static Dt_t *logins_tree;
+ if(*string++!='~')
+ return(NIL(char*));
+ if((c = *string)==0)
+ {
+ if(!(cp=nv_getval(sh_scoped(shp,HOME))))
+ cp = getlogin();
+ return(cp);
+ }
+ if((c=='-' || c=='+') && string[1]==0)
+ {
+ if(c=='+')
+ cp = nv_getval(sh_scoped(shp,PWDNOD));
+ else
+ cp = nv_getval(sh_scoped(shp,OLDPWDNOD));
+ return(cp);
+ }
+#if _WINIX
+ if(fcgetc(c)=='/')
+ {
+ char *str;
+ int n=0,offset=staktell();
+ stakputs(string);
+ do
+ {
+ stakputc(c);
+ n++;
+ }
+ while (fcgetc(c) && c!='/');
+ stakputc(0);
+ if(c)
+ fcseek(-1);
+ str = stakseek(offset);
+ Skip = n;
+ if(logins_tree && (np=nv_search(str,logins_tree,0)))
+ return(nv_getval(np));
+ if(pw = getpwnam(str))
+ {
+ string = str;
+ goto skip;
+ }
+ Skip = 0;
+ }
+#endif /* _WINIX */
+ if(logins_tree && (np=nv_search(string,logins_tree,0)))
+ return(nv_getval(np));
+ if(!(pw = getpwnam(string)))
+ return(NIL(char*));
+#if _WINIX
+skip:
+#endif /* _WINIX */
+ if(!logins_tree)
+ logins_tree = dtopen(&_Nvdisc,Dtbag);
+ if(np=nv_search(string,logins_tree,NV_ADD))
+ {
+ c = shp->subshell;
+ shp->subshell = 0;
+ nv_putval(np, pw->pw_dir,0);
+ shp->subshell = c;
+ }
+ return(pw->pw_dir);
+}
+
+/*
+ * return values for special macros
+ */
+static char *special(Shell_t *shp,register int c)
+{
+ if(c!='$')
+ shp->argaddr = 0;
+ switch(c)
+ {
+ case '@':
+ case '*':
+ return(shp->st.dolc>0?shp->st.dolv[1]:NIL(char*));
+ case '#':
+#if SHOPT_FILESCAN
+ if(shp->cur_line)
+ {
+ getdolarg(shp,MAX_ARGN,(int*)0);
+ return(ltos(shp->offsets[0]));
+ }
+#endif /* SHOPT_FILESCAN */
+ return(ltos(shp->st.dolc));
+ case '!':
+ if(shp->bckpid)
+#if SHOPT_COSHELL
+ return(sh_pid2str(shp,shp->bckpid));
+#else
+ return(ltos(shp->bckpid));
+#endif /* SHOPT_COSHELL */
+ break;
+ case '$':
+ if(nv_isnull(SH_DOLLARNOD))
+ return(ltos(shp->gd->pid));
+ return(nv_getval(SH_DOLLARNOD));
+ case '-':
+ return(sh_argdolminus(shp->arg_context));
+ case '?':
+ return(ltos(shp->savexit));
+ case 0:
+ if(sh_isstate(SH_PROFILE) || shp->fn_depth==0 || !shp->st.cmdname)
+ return(shp->shname);
+ else
+ return(shp->st.cmdname);
+ }
+ return(NIL(char*));
+}
+
+/*
+ * Handle macro expansion errors
+ */
+static void mac_error(Namval_t *np)
+{
+ if(np)
+ nv_close(np);
+ errormsg(SH_DICT,ERROR_exit(1),e_subst,fcfirst());
+}
+
+/*
+ * Given pattern/string, replace / with 0 and return pointer to string
+ * \ characters are stripped from string. The \ are stripped in the
+ * replacement string unless followed by a digit or \.
+ */
+static char *mac_getstring(char *pattern)
+{
+ register char *cp=pattern, *rep=0, *dp;
+ register int c;
+ while(c = *cp++)
+ {
+ if(c==ESCAPE && (!rep || (*cp && strchr("&|()[]*?",*cp))))
+ {
+ c = *cp++;
+ }
+ else if(!rep && c=='/')
+ {
+ cp[-1] = 0;
+ rep = dp = cp;
+ continue;
+ }
+ if(rep)
+ *dp++ = c;
+ }
+ if(rep)
+ *dp = 0;
+ return(rep);
+}
diff --git a/src/cmd/ksh93/sh/main.c b/src/cmd/ksh93/sh/main.c
new file mode 100644
index 0000000..85948a6
--- /dev/null
+++ b/src/cmd/ksh93/sh/main.c
@@ -0,0 +1,787 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Rewritten By David Korn
+ * AT&T Labs
+ *
+ */
+
+#include <ast.h>
+#include <sfio.h>
+#include <stak.h>
+#include <ls.h>
+#include <fcin.h>
+#include "defs.h"
+#include "variables.h"
+#include "path.h"
+#include "io.h"
+#include "jobs.h"
+#include "shlex.h"
+#include "shnodes.h"
+#include "history.h"
+#include "timeout.h"
+#include "FEATURE/time"
+#include "FEATURE/pstat"
+#include "FEATURE/execargs"
+#include "FEATURE/externs"
+#ifdef _hdr_nc
+# include <nc.h>
+#endif /* _hdr_nc */
+
+#define CMD_LENGTH 64
+
+/* These routines are referenced by this module */
+static void exfile(Shell_t*, Sfio_t*,int);
+static void chkmail(Shell_t *shp, char*);
+#if defined(_lib_fork) && !defined(_NEXT_SOURCE)
+ static void fixargs(char**,int);
+#else
+# define fixargs(a,b)
+#endif
+
+#ifndef environ
+ extern char **environ;
+#endif
+
+static struct stat lastmail;
+static time_t mailtime;
+static char beenhere = 0;
+
+#ifdef _lib_sigvec
+ void clearsigmask(register int sig)
+ {
+ struct sigvec vec;
+ if(sigvec(sig,NIL(struct sigvec*),&vec)>=0 && vec.sv_mask)
+ {
+ vec.sv_mask = 0;
+ sigvec(sig,&vec,NIL(struct sigvec*));
+ }
+ }
+#endif /* _lib_sigvec */
+
+#ifdef _lib_fts_notify
+# include <fts.h>
+ /* check for interrupts during tree walks */
+ static int fts_sigcheck(FTS* fp, FTSENT* ep, void* context)
+ {
+ Shell_t *shp = (Shell_t*)context;
+ NOT_USED(fp);
+ NOT_USED(ep);
+ if(shp->trapnote&SH_SIGSET)
+ {
+ errno = EINTR;
+ return(-1);
+ }
+ return(0);
+ }
+#endif /* _lib_fts_notify */
+
+#ifdef PATH_BFPATH
+#define PATHCOMP NIL(Pathcomp_t*)
+#else
+#define PATHCOMP ""
+#endif
+
+/*
+ * search for file and exfile() it if it exists
+ * 1 returned if file found, 0 otherwise
+ */
+
+int sh_source(Shell_t *shp, Sfio_t *iop, const char *file)
+{
+ char* oid;
+ char* nid;
+ int fd;
+
+ if (!file || !*file || (fd = path_open(shp,file, PATHCOMP)) < 0)
+ {
+ REGRESS(source, "sh_source", ("%s:ENOENT", file));
+ return 0;
+ }
+ oid = error_info.id;
+ nid = error_info.id = strdup(file);
+ shp->st.filename = path_fullname(shp,stakptr(PATH_OFFSET));
+ REGRESS(source, "sh_source", ("%s", file));
+ exfile(shp, iop, fd);
+ error_info.id = oid;
+ free(nid);
+ return 1;
+}
+
+#ifdef S_ISSOCK
+#define REMOTE(m) (S_ISSOCK(m)||!(m))
+#else
+#define REMOTE(m) !(m)
+#endif
+
+int sh_main(int ac, char *av[], Shinit_f userinit)
+{
+ register char *name;
+ register int fdin;
+ register Sfio_t *iop;
+ register Shell_t *shp;
+ struct stat statb;
+ int i, rshflag; /* set for restricted shell */
+ char *command;
+ free(malloc(64*1024));
+#ifdef _lib_sigvec
+ /* This is to clear mask that may be left on by rlogin */
+ clearsigmask(SIGALRM);
+ clearsigmask(SIGHUP);
+ clearsigmask(SIGCHLD);
+#endif /* _lib_sigvec */
+#ifdef _hdr_nc
+ _NutConf(_NC_SET_SUFFIXED_SEARCHING, 1);
+#endif /* _hdr_nc */
+ fixargs(av,0);
+ shp = sh_init(ac,av,userinit);
+ time(&mailtime);
+ if(rshflag=sh_isoption(SH_RESTRICTED))
+ sh_offoption(SH_RESTRICTED);
+#ifdef _lib_fts_notify
+ fts_notify(fts_sigcheck,(void*)shp);
+#endif /* _lib_fts_notify */
+ if(sigsetjmp(*((sigjmp_buf*)shp->jmpbuffer),0))
+ {
+ /* begin script execution here */
+ sh_reinit((char**)0);
+ shp->gd->pid = getpid();
+ shp->gd->ppid = getppid();
+ }
+ shp->fn_depth = shp->dot_depth = 0;
+ command = error_info.id;
+ /* set pidname '$$' */
+ srand(shp->gd->pid&0x7fff);
+ if(nv_isnull(PS4NOD))
+ nv_putval(PS4NOD,e_traceprompt,NV_RDONLY);
+ path_pwd(shp,1);
+ iop = (Sfio_t*)0;
+#if SHOPT_BRACEPAT
+ sh_onoption(SH_BRACEEXPAND);
+#endif
+ if((beenhere++)==0)
+ {
+ sh_onstate(SH_PROFILE);
+ ((Lex_t*)shp->lex_context)->nonstandard = 0;
+ if(shp->gd->ppid==1)
+ shp->login_sh++;
+ if(shp->login_sh >= 2)
+ sh_onoption(SH_LOGIN_SHELL);
+ /* decide whether shell is interactive */
+ if(!sh_isoption(SH_INTERACTIVE) && !sh_isoption(SH_TFLAG) && !sh_isoption(SH_CFLAG) &&
+ sh_isoption(SH_SFLAG) && tty_check(0) && tty_check(ERRIO))
+ sh_onoption(SH_INTERACTIVE);
+ if(sh_isoption(SH_INTERACTIVE))
+ {
+ sh_onoption(SH_BGNICE);
+ sh_onoption(SH_RC);
+ }
+ if(!sh_isoption(SH_RC) && (sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX)
+#if SHOPT_REMOTE
+ || !fstat(0, &statb) && REMOTE(statb.st_mode)
+#endif
+ ))
+ sh_onoption(SH_RC);
+ for(i=0; i<elementsof(shp->offoptions.v); i++)
+ shp->options.v[i] &= ~shp->offoptions.v[i];
+ if(sh_isoption(SH_INTERACTIVE))
+ {
+#ifdef SIGXCPU
+ signal(SIGXCPU,SIG_DFL);
+#endif /* SIGXCPU */
+#ifdef SIGXFSZ
+ signal(SIGXFSZ,SIG_DFL);
+#endif /* SIGXFSZ */
+ sh_onoption(SH_MONITOR);
+ }
+ job_init(shp,sh_isoption(SH_LOGIN_SHELL));
+ if(sh_isoption(SH_LOGIN_SHELL))
+ {
+ /* system profile */
+ sh_source(shp, iop, e_sysprofile);
+ if(!sh_isoption(SH_NOUSRPROFILE) && !sh_isoption(SH_PRIVILEGED))
+ {
+ char **files = shp->gd->login_files;
+ while ((name = *files++) && !sh_source(shp, iop, sh_mactry(shp,name)));
+ }
+ }
+ /* make sure PWD is set up correctly */
+ path_pwd(shp,1);
+ if(!sh_isoption(SH_NOEXEC))
+ {
+ if(!sh_isoption(SH_NOUSRPROFILE) && !sh_isoption(SH_PRIVILEGED) && sh_isoption(SH_RC))
+ {
+#if SHOPT_BASH
+ if(sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX))
+ {
+#if SHOPT_SYSRC
+ sh_source(shp, iop, e_bash_sysrc);
+#endif
+ sh_source(shp, iop, shp->gd->rcfile ? shp->gd->rcfile : sh_mactry(shp,(char*)e_bash_rc));
+ }
+ else
+#endif
+ {
+ if(name = sh_mactry(shp,nv_getval(ENVNOD)))
+ name = *name ? strdup(name) : (char*)0;
+#if SHOPT_SYSRC
+ if(!strmatch(name, "?(.)/./*"))
+ sh_source(shp, iop, e_sysrc);
+#endif
+ if(name)
+ {
+ sh_source(shp, iop, name);
+ free(name);
+ }
+ }
+ }
+ else if(sh_isoption(SH_INTERACTIVE) && sh_isoption(SH_PRIVILEGED))
+ sh_source(shp, iop, e_suidprofile);
+ }
+ shp->st.cmdname = error_info.id = command;
+ sh_offstate(SH_PROFILE);
+ if(rshflag)
+ sh_onoption(SH_RESTRICTED);
+ /* open input file if specified */
+ if(shp->comdiv)
+ {
+ shell_c:
+ iop = sfnew(NIL(Sfio_t*),shp->comdiv,strlen(shp->comdiv),0,SF_STRING|SF_READ);
+ }
+ else
+ {
+ name = error_info.id;
+ error_info.id = shp->shname;
+ if(sh_isoption(SH_SFLAG))
+ fdin = 0;
+ else
+ {
+ char *sp;
+ /* open stream should have been passed into shell */
+ if(strmatch(name,e_devfdNN))
+ {
+#if !_WINIX
+ char *cp;
+ int type;
+#endif
+ fdin = (int)strtol(name+8, (char**)0, 10);
+ if(fstat(fdin,&statb)<0)
+ errormsg(SH_DICT,ERROR_system(1),e_open,name);
+#if !_WINIX
+ /*
+ * try to undo effect of solaris 2.5+
+ * change for argv for setuid scripts
+ */
+ if(((type = sh_type(cp = av[0])) & SH_TYPE_SH) && (!(name = nv_getval(L_ARGNOD)) || !((type = sh_type(cp = name)) & SH_TYPE_SH)))
+ {
+ av[0] = (type & SH_TYPE_LOGIN) ? cp : path_basename(cp);
+ /* exec to change $0 for ps */
+ execv(pathshell(),av);
+ /* exec fails */
+ shp->st.dolv[0] = av[0];
+ fixargs(shp->st.dolv,1);
+ }
+#endif
+ name = av[0];
+ sh_offoption(SH_VERBOSE);
+ sh_offoption(SH_XTRACE);
+ }
+ else
+ {
+ int isdir = 0;
+ if((fdin=sh_open(name,O_RDONLY,0))>=0 &&(fstat(fdin,&statb)<0 || S_ISDIR(statb.st_mode)))
+ {
+ close(fdin);
+ isdir = 1;
+ fdin = -1;
+ }
+ else
+ shp->st.filename = path_fullname(shp,name);
+ sp = 0;
+ if(fdin < 0 && !strchr(name,'/'))
+ {
+#ifdef PATH_BFPATH
+ if(path_absolute(shp,name,NIL(Pathcomp_t*)))
+ sp = stakptr(PATH_OFFSET);
+#else
+ sp = path_absolute(shp,name,NIL(char*));
+#endif
+ if(sp)
+ {
+ if((fdin=sh_open(sp,O_RDONLY,0))>=0)
+ shp->st.filename = path_fullname(shp,sp);
+ }
+ }
+ if(fdin<0)
+ {
+ if(isdir)
+ errno = EISDIR;
+ error_info.id = av[0];
+ if(sp || errno!=ENOENT)
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_open,name);
+ /* try sh -c 'name "$@"' */
+ sh_onoption(SH_CFLAG);
+ shp->comdiv = (char*)malloc(strlen(name)+7);
+ name = strcopy(shp->comdiv,name);
+ if(shp->st.dolc)
+ strcopy(name," \"$@\"");
+ goto shell_c;
+ }
+ if(fdin==0)
+ fdin = sh_iomovefd(fdin);
+ }
+ shp->readscript = shp->shname;
+ }
+ error_info.id = name;
+ shp->comdiv--;
+#if SHOPT_ACCT
+ sh_accinit();
+ if(fdin != 0)
+ sh_accbegin(error_info.id);
+#endif /* SHOPT_ACCT */
+ }
+ }
+ else
+ {
+ fdin = shp->infd;
+ fixargs(shp->st.dolv,1);
+ }
+ if(sh_isoption(SH_INTERACTIVE))
+ sh_onstate(SH_INTERACTIVE);
+ nv_putval(IFSNOD,(char*)e_sptbnl,NV_RDONLY);
+ exfile(shp,iop,fdin);
+ sh_done(shp,0);
+ /* NOTREACHED */
+ return(0);
+}
+
+/*
+ * iop is not null when the input is a string
+ * fdin is the input file descriptor
+ */
+
+static void exfile(register Shell_t *shp, register Sfio_t *iop,register int fno)
+{
+ time_t curtime;
+ Shnode_t *t;
+ int maxtry=IOMAXTRY, tdone=0, execflags;
+ int states,jmpval;
+ struct checkpt buff;
+ sh_pushcontext(shp,&buff,SH_JMPERREXIT);
+ /* open input stream */
+ nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE);
+ if(!iop)
+ {
+ if(fno > 0)
+ {
+ int r;
+ if(fno < 10 && ((r=sh_fcntl(fno,F_DUPFD,10))>=10))
+ {
+ shp->fdstatus[r] = shp->fdstatus[fno];
+ sh_close(fno);
+ fno = r;
+ }
+ fcntl(fno,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fno] |= IOCLEX;
+ iop = sh_iostream((void*)shp,fno);
+ }
+ else
+ iop = sfstdin;
+ }
+ else
+ fno = -1;
+ shp->infd = fno;
+ if(sh_isstate(SH_INTERACTIVE))
+ {
+ if(nv_isnull(PS1NOD))
+ nv_putval(PS1NOD,(shp->gd->euserid?e_stdprompt:e_supprompt),NV_RDONLY);
+ sh_sigdone();
+ if(sh_histinit((void*)shp))
+ sh_onoption(SH_HISTORY);
+ }
+ else
+ {
+ if(!sh_isstate(SH_PROFILE))
+ {
+ buff.mode = SH_JMPEXIT;
+ sh_onoption(SH_TRACKALL);
+ sh_offoption(SH_MONITOR);
+ }
+ sh_offstate(SH_INTERACTIVE);
+ sh_offstate(SH_MONITOR);
+ sh_offstate(SH_HISTORY);
+ sh_offoption(SH_HISTORY);
+ }
+ states = sh_getstate();
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval)
+ {
+ Sfio_t *top;
+ sh_iorestore((void*)shp,0,jmpval);
+ hist_flush(shp->gd->hist_ptr);
+ sfsync(shp->outpool);
+ shp->st.execbrk = shp->st.breakcnt = 0;
+ /* check for return from profile or env file */
+ if(sh_isstate(SH_PROFILE) && (jmpval==SH_JMPFUN || jmpval==SH_JMPEXIT))
+ {
+ sh_setstate(states);
+ goto done;
+ }
+ if(!sh_isoption(SH_INTERACTIVE) || sh_isstate(SH_FORKED) || (jmpval > SH_JMPERREXIT && job_close(shp) >=0))
+ {
+ sh_offstate(SH_INTERACTIVE);
+ sh_offstate(SH_MONITOR);
+ goto done;
+ }
+ /* skip over remaining input */
+ if(top = fcfile())
+ {
+ while(fcget()>0);
+ fcclose();
+ while(top=sfstack(iop,SF_POPSTACK))
+ sfclose(top);
+ }
+ /* make sure that we own the terminal */
+#ifdef SIGTSTP
+ tcsetpgrp(job.fd,shp->gd->pid);
+#endif /* SIGTSTP */
+ }
+ /* error return here */
+ sfclrerr(iop);
+ sh_setstate(states);
+ shp->st.optindex = 1;
+ opt_info.offset = 0;
+ shp->st.loopcnt = 0;
+ shp->trapnote = 0;
+ shp->intrap = 0;
+ error_info.line = 1;
+ shp->inlineno = 1;
+ shp->binscript = 0;
+ if(sfeof(iop))
+ goto eof_or_error;
+ /* command loop */
+ while(1)
+ {
+ shp->nextprompt = 1;
+ sh_freeup(shp);
+ stakset(NIL(char*),0);
+ exitset();
+ sh_offstate(SH_STOPOK);
+ sh_offstate(SH_ERREXIT);
+ sh_offstate(SH_VERBOSE);
+ sh_offstate(SH_TIMING);
+ sh_offstate(SH_GRACE);
+ sh_offstate(SH_TTYWAIT);
+ if(sh_isoption(SH_VERBOSE))
+ sh_onstate(SH_VERBOSE);
+ sh_onstate(SH_ERREXIT);
+ /* -eim flags don't apply to profiles */
+ if(sh_isstate(SH_PROFILE))
+ {
+ sh_offstate(SH_INTERACTIVE);
+ sh_offstate(SH_ERREXIT);
+ sh_offstate(SH_MONITOR);
+ }
+ if(sh_isstate(SH_INTERACTIVE) && !tdone)
+ {
+ register char *mail;
+#ifdef JOBS
+ sh_offstate(SH_MONITOR);
+ if(sh_isoption(SH_MONITOR))
+ sh_onstate(SH_MONITOR);
+ if(job.pwlist)
+ {
+ job_walk(sfstderr,job_list,JOB_NFLAG,(char**)0);
+ job_wait((pid_t)0);
+ }
+#endif /* JOBS */
+ if((mail=nv_getval(MAILPNOD)) || (mail=nv_getval(MAILNOD)))
+ {
+ time(&curtime);
+ if ((curtime - mailtime) >= sh_mailchk)
+ {
+ chkmail(shp,mail);
+ mailtime = curtime;
+ }
+ }
+ if(shp->gd->hist_ptr)
+ hist_eof(shp->gd->hist_ptr);
+ /* sets timeout for command entry */
+ shp->timeout = shp->st.tmout;
+#if SHOPT_TIMEOUT
+ if(shp->timeout <= 0 || shp->timeout > SHOPT_TIMEOUT)
+ shp->timeout = SHOPT_TIMEOUT;
+#endif /* SHOPT_TIMEOUT */
+ shp->inlineno = 1;
+ error_info.line = 1;
+ shp->exitval = 0;
+ shp->trapnote = 0;
+ if(buff.mode == SH_JMPEXIT)
+ {
+ buff.mode = SH_JMPERREXIT;
+#ifdef DEBUG
+ errormsg(SH_DICT,ERROR_warn(0),"%d: mode changed to JMP_EXIT",getpid());
+#endif
+ }
+ }
+ errno = 0;
+ if(tdone || !sfreserve(iop,0,0))
+ {
+ eof_or_error:
+ if(sh_isstate(SH_INTERACTIVE) && !sferror(iop))
+ {
+ if(--maxtry>0 && sh_isoption(SH_IGNOREEOF) &&
+ !sferror(sfstderr) && (shp->fdstatus[fno]&IOTTY))
+ {
+ sfclrerr(iop);
+ errormsg(SH_DICT,0,e_logout);
+ continue;
+ }
+ else if(job_close(shp)<0)
+ continue;
+ }
+ if(errno==0 && sferror(iop) && --maxtry>0)
+ {
+ sfclrlock(iop);
+ sfclrerr(iop);
+ continue;
+ }
+ goto done;
+ }
+ maxtry = IOMAXTRY;
+ if(sh_isstate(SH_INTERACTIVE) && shp->gd->hist_ptr)
+ {
+ job_wait((pid_t)0);
+ hist_eof(shp->gd->hist_ptr);
+ sfsync(sfstderr);
+ }
+ if(sh_isoption(SH_HISTORY))
+ sh_onstate(SH_HISTORY);
+ job.waitall = job.curpgid = 0;
+ error_info.flags |= ERROR_INTERACTIVE;
+ t = (Shnode_t*)sh_parse(shp,iop,0);
+ if(!sh_isstate(SH_INTERACTIVE) && !sh_isoption(SH_CFLAG))
+ error_info.flags &= ~ERROR_INTERACTIVE;
+ shp->readscript = 0;
+ if(sh_isstate(SH_INTERACTIVE) && shp->gd->hist_ptr)
+ hist_flush(shp->gd->hist_ptr);
+ sh_offstate(SH_HISTORY);
+ if(t)
+ {
+ execflags = sh_state(SH_ERREXIT)|sh_state(SH_INTERACTIVE);
+ /* The last command may not have to fork */
+ if(!sh_isstate(SH_PROFILE) && sh_isoption(SH_CFLAG) &&
+ (fno<0 || !(shp->fdstatus[fno]&(IOTTY|IONOSEEK)))
+ && !sfreserve(iop,0,0))
+ {
+ execflags |= sh_state(SH_NOFORK);
+ }
+ shp->st.execbrk = 0;
+ sh_exec(t,execflags);
+ if(shp->forked)
+ {
+ sh_offstate(SH_INTERACTIVE);
+ goto done;
+ }
+ /* This is for sh -t */
+ if(sh_isoption(SH_TFLAG) && !sh_isstate(SH_PROFILE))
+ tdone++;
+ }
+ }
+done:
+ sh_popcontext(shp,&buff);
+ if(sh_isstate(SH_INTERACTIVE))
+ {
+ sfputc(sfstderr,'\n');
+ job_close(shp);
+ }
+ if(jmpval == SH_JMPSCRIPT)
+ siglongjmp(*shp->jmplist,jmpval);
+ else if(jmpval == SH_JMPEXIT)
+ sh_done(shp,0);
+ if(fno>0)
+ sh_close(fno);
+ if(shp->st.filename)
+ free((void*)shp->st.filename);
+ shp->st.filename = 0;
+}
+
+
+/* prints out messages if files in list have been modified since last call */
+static void chkmail(Shell_t *shp, char *files)
+{
+ register char *cp,*sp,*qp;
+ register char save;
+ struct argnod *arglist=0;
+ int offset = staktell();
+ char *savstak=stakptr(0);
+ struct stat statb;
+ if(*(cp=files) == 0)
+ return;
+ sp = cp;
+ do
+ {
+ /* skip to : or end of string saving first '?' */
+ for(qp=0;*sp && *sp != ':';sp++)
+ if((*sp == '?' || *sp=='%') && qp == 0)
+ qp = sp;
+ save = *sp;
+ *sp = 0;
+ /* change '?' to end-of-string */
+ if(qp)
+ *qp = 0;
+ do
+ {
+ /* see if time has been modified since last checked
+ * and the access time <= the modification time
+ */
+ if(stat(cp,&statb) >= 0 && statb.st_mtime >= mailtime
+ && statb.st_atime <= statb.st_mtime)
+ {
+ /* check for directory */
+ if(!arglist && S_ISDIR(statb.st_mode))
+ {
+ /* generate list of directory entries */
+ path_complete(shp,cp,"/*",&arglist);
+ }
+ else
+ {
+ /*
+ * If the file has shrunk,
+ * or if the size is zero
+ * then don't print anything
+ */
+ if(statb.st_size &&
+ ( statb.st_ino != lastmail.st_ino
+ || statb.st_dev != lastmail.st_dev
+ || statb.st_size > lastmail.st_size))
+ {
+ /* save and restore $_ */
+ char *save = shp->lastarg;
+ shp->lastarg = cp;
+ errormsg(SH_DICT,0,sh_mactry(shp,qp?qp+1:(char*)e_mailmsg));
+ shp->lastarg = save;
+ }
+ lastmail = statb;
+ break;
+ }
+ }
+ if(arglist)
+ {
+ cp = arglist->argval;
+ arglist = arglist->argchn.ap;
+ }
+ else
+ cp = 0;
+ }
+ while(cp);
+ if(qp)
+ *qp = '?';
+ *sp++ = save;
+ cp = sp;
+ }
+ while(save);
+ stakset(savstak,offset);
+}
+
+#undef EXECARGS
+#undef PSTAT
+#if defined(_hdr_execargs) && defined(pdp11)
+# include <execargs.h>
+# define EXECARGS 1
+#endif
+
+#if defined(_lib_pstat) && defined(_sys_pstat)
+# include <sys/pstat.h>
+# define PSTAT 1
+#endif
+
+#if defined(_lib_fork) && !defined(_NEXT_SOURCE)
+/*
+ * fix up command line for ps command
+ * mode is 0 for initialization
+ */
+static void fixargs(char **argv, int mode)
+{
+#if EXECARGS
+ *execargs=(char *)argv;
+#else
+ static char *buff;
+ static int command_len;
+ register char *cp;
+ int offset=0,size;
+# ifdef PSTAT
+ union pstun un;
+ if(mode==0)
+ {
+ struct pst_static st;
+ un.pst_static = &st;
+ if(pstat(PSTAT_STATIC, un, sizeof(struct pst_static), 1, 0)<0)
+ return;
+ command_len = st.command_length;
+ return;
+ }
+ stakseek(command_len+2);
+ buff = stakseek(0);
+# else
+ if(mode==0)
+ {
+ buff = argv[0];
+ while(cp = *argv++)
+ command_len += strlen(cp)+1;
+ if(environ && *environ==buff+command_len)
+ {
+ for(argv=environ; cp = *argv; cp++)
+ {
+ if(command_len > CMD_LENGTH)
+ {
+ command_len = CMD_LENGTH;
+ break;
+ }
+ *argv++ = strdup(cp);
+ command_len += strlen(cp)+1;
+ }
+ }
+ command_len -= 1;
+ return;
+ }
+# endif /* PSTAT */
+ if(command_len==0)
+ return;
+ while((cp = *argv++) && offset < command_len)
+ {
+ if(offset + (size=strlen(cp)) >= command_len)
+ size = command_len - offset;
+ memcpy(buff+offset,cp,size);
+ offset += size;
+ buff[offset++] = ' ';
+ }
+ buff[offset-1] = 0;
+# ifdef PSTAT
+ un.pst_command = stakptr(0);
+ pstat(PSTAT_SETCMD,un,0,0,0);
+# endif /* PSTAT */
+#endif /* EXECARGS */
+}
+#endif /* _lib_fork */
diff --git a/src/cmd/ksh93/sh/name.c b/src/cmd/ksh93/sh/name.c
new file mode 100644
index 0000000..77793f4
--- /dev/null
+++ b/src/cmd/ksh93/sh/name.c
@@ -0,0 +1,3684 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Labs
+ *
+ */
+
+#define putenv ___putenv
+
+#include "defs.h"
+#include "variables.h"
+#include "path.h"
+#include "lexstates.h"
+#include "timeout.h"
+#include "FEATURE/externs"
+#include "streval.h"
+
+#define NVCACHE 8 /* must be a power of 2 */
+#define Empty ((char*)(e_sptbnl+3))
+static char *savesub = 0;
+static char Null[1];
+static Namval_t NullNode;
+static Dt_t *Refdict;
+static Dtdisc_t _Refdisc =
+{
+ offsetof(struct Namref,np),sizeof(struct Namval_t*),sizeof(struct Namref)
+};
+
+#if !_lib_pathnative && _lib_uwin_path
+
+#define _lib_pathnative 1
+
+extern int uwin_path(const char*, char*, int);
+
+size_t
+pathnative(const char* path, char* buf, size_t siz)
+{
+ return uwin_path(path, buf, siz);
+}
+
+#endif /* _lib_pathnative */
+
+static void attstore(Namval_t*,void*);
+#ifndef _ENV_H
+ static void pushnam(Namval_t*,void*);
+ static char *staknam(Namval_t*, char*);
+#endif
+static void rightjust(char*, int, int);
+static char *lastdot(char*, int);
+
+struct adata
+{
+ Shell_t *sh;
+ Namval_t *tp;
+ char *mapname;
+ char **argnam;
+ int attsize;
+ char *attval;
+};
+
+#if SHOPT_TYPEDEF
+ struct sh_type
+ {
+ void *previous;
+ Namval_t **nodes;
+ Namval_t *rp;
+ short numnodes;
+ short maxnodes;
+ };
+#endif /*SHOPT_TYPEDEF */
+
+#if NVCACHE
+ struct Namcache
+ {
+ struct Cache_entry
+ {
+ Dt_t *root;
+ Dt_t *last_root;
+ char *name;
+ Namval_t *np;
+ Namval_t *last_table;
+ int flags;
+ short size;
+ short len;
+ } entries[NVCACHE];
+ short index;
+ short ok;
+ };
+ static struct Namcache nvcache;
+#endif
+
+char nv_local = 0;
+#ifndef _ENV_H
+static void(*nullscan)(Namval_t*,void*);
+#endif
+
+#if ( SFIO_VERSION <= 20010201L )
+# define _data data
+#endif
+
+#if !SHOPT_MULTIBYTE
+# define mbchar(p) (*(unsigned char*)p++)
+#endif /* SHOPT_MULTIBYTE */
+
+/* ======== name value pair routines ======== */
+
+#include "shnodes.h"
+#include "builtins.h"
+
+static char *getbuf(size_t len)
+{
+ static char *buf;
+ static size_t buflen;
+ if(buflen < len)
+ {
+ if(buflen==0)
+ buf = (char*)malloc(len);
+ else
+ buf = (char*)realloc(buf,len);
+ buflen = len;
+ }
+ return(buf);
+}
+
+#ifdef _ENV_H
+void sh_envput(Env_t* ep,Namval_t *np)
+{
+ int offset = staktell();
+ Namarr_t *ap = nv_arrayptr(np);
+ char *val;
+ if(ap)
+ {
+ if(ap->nelem&ARRAY_UNDEF)
+ nv_putsub(np,"0",0L);
+ else if(!(val=nv_getsub(np)) || strcmp(val,"0"))
+ return;
+ }
+ if(!(val = nv_getval(np)))
+ return;
+ stakputs(nv_name(np));
+ stakputc('=');
+ stakputs(val);
+ stakseek(offset);
+ env_add(ep,stakptr(offset),ENV_STRDUP);
+}
+#endif
+
+/*
+ * output variable name in format for re-input
+ */
+void nv_outname(Sfio_t *out, char *name, int len)
+{
+ const char *cp=name, *sp;
+ int c, offset = staktell();
+ while(sp= strchr(cp,'['))
+ {
+ if(len>0 && cp+len <= sp)
+ break;
+ sfwrite(out,cp,++sp-cp);
+ stakseek(offset);
+ while(c= *sp++)
+ {
+ if(c==']')
+ break;
+ else if(c=='\\')
+ {
+ if(*sp=='[' || *sp==']' || *sp=='\\')
+ c = *sp++;
+ }
+ stakputc(c);
+ }
+ stakputc(0);
+ sfputr(out,sh_fmtq(stakptr(offset)),-1);
+ if(len>0)
+ {
+ sfputc(out,']');
+ return;
+ }
+ cp = sp-1;
+ }
+ if(*cp)
+ {
+ if(len>0)
+ sfwrite(out,cp,len);
+ else
+ sfputr(out,cp,-1);
+ }
+ stakseek(offset);
+}
+
+#if SHOPT_TYPEDEF
+Namval_t *nv_addnode(Namval_t* np, int remove)
+{
+ Shell_t *shp = sh_getinterp();
+ register struct sh_type *sp = (struct sh_type*)shp->mktype;
+ register int i;
+ register char *name=0;
+ if(sp->numnodes==0 && !nv_isnull(np) && shp->last_table)
+ {
+ /* could be an redefine */
+ Dt_t *root = nv_dict(shp->last_table);
+ sp->rp = np;
+ nv_delete(np,root,NV_NOFREE);
+ np = nv_search(sp->rp->nvname,root,NV_ADD);
+ }
+ if(sp->numnodes && memcmp(np->nvname,NV_CLASS,sizeof(NV_CLASS)-1))
+ {
+ name = (sp->nodes[0])->nvname;
+ i = strlen(name);
+ if(memcmp(np->nvname,name,i))
+ return(np);
+ }
+ if(sp->rp && sp->numnodes)
+ {
+ /* check for a redefine */
+ if(name && np->nvname[i]=='.' && np->nvname[i+1]=='_' && np->nvname[i+2]==0)
+ sp->rp = 0;
+ else
+ {
+ Dt_t *root = nv_dict(shp->last_table);
+ nv_delete(sp->nodes[0],root,NV_NOFREE);
+ dtinsert(root,sp->rp);
+ errormsg(SH_DICT,ERROR_exit(1),e_redef,sp->nodes[0]->nvname);
+ }
+ }
+ for(i=0; i < sp->numnodes; i++)
+ {
+ if(np == sp->nodes[i])
+ {
+ if(remove)
+ {
+ while(++i < sp->numnodes)
+ sp->nodes[i-1] = sp->nodes[i];
+ sp->numnodes--;
+ }
+ return(np);
+ }
+ }
+ if(remove)
+ return(np);
+ if(sp->numnodes==sp->maxnodes)
+ {
+ sp->maxnodes += 20;
+ sp->nodes = (Namval_t**)realloc(sp->nodes,sizeof(Namval_t*)*sp->maxnodes);
+ }
+ sp->nodes[sp->numnodes++] = np;
+ return(np);
+}
+#endif /* SHOPT_TYPEDEF */
+
+/*
+ * given a list of assignments, determine <name> is on the list
+ returns a pointer to the argnod on the list or NULL
+ */
+struct argnod *nv_onlist(struct argnod *arg, const char *name)
+{
+ char *cp;
+ int len = strlen(name);
+ for(;arg; arg=arg->argnxt.ap)
+ {
+ if(*arg->argval==0 && arg->argchn.ap && !(arg->argflag&~(ARG_APPEND|ARG_QUOTED|ARG_MESSAGE)))
+ cp = ((struct fornod*)arg->argchn.ap)->fornam;
+ else
+ cp = arg->argval;
+ if(memcmp(cp,name,len)==0 && (cp[len]==0 || cp[len]=='='))
+ return(arg);
+ }
+ return(0);
+}
+
+/*
+ * Perform parameter assignment for a linked list of parameters
+ * <flags> contains attributes for the parameters
+ */
+void nv_setlist(register struct argnod *arg,register int flags, Namval_t *typ)
+{
+ Shell_t *shp = sh_getinterp();
+ register char *cp;
+ register Namval_t *np, *mp;
+ char *trap=shp->st.trap[SH_DEBUGTRAP];
+ char *prefix = shp->prefix;
+ int traceon = (sh_isoption(SH_XTRACE)!=0);
+ int array = (flags&(NV_ARRAY|NV_IARRAY));
+ Namarr_t *ap;
+ Namval_t node;
+ struct Namref nr;
+#if SHOPT_TYPEDEF
+ int maketype = flags&NV_TYPE;
+ struct sh_type shtp;
+ if(maketype)
+ {
+ shtp.previous = shp->mktype;
+ shp->mktype=(void*)&shtp;
+ shtp.numnodes=0;
+ shtp.maxnodes = 20;
+ shtp.rp = 0;
+ shtp.nodes =(Namval_t**)malloc(shtp.maxnodes*sizeof(Namval_t*));
+ }
+#endif /* SHOPT_TYPEDEF*/
+#if SHOPT_NAMESPACE
+ if(shp->namespace && nv_dict(shp->namespace)==shp->var_tree)
+ flags |= NV_NOSCOPE;
+#endif /* SHOPT_NAMESPACE */
+ flags &= ~(NV_TYPE|NV_ARRAY|NV_IARRAY);
+ if(sh_isoption(SH_ALLEXPORT))
+ flags |= NV_EXPORT;
+ if(shp->prefix)
+ {
+ flags &= ~(NV_IDENT|NV_EXPORT);
+ flags |= NV_VARNAME;
+ }
+ else
+ shp->prefix_root = shp->first_root = 0;
+ for(;arg; arg=arg->argnxt.ap)
+ {
+ shp->used_pos = 0;
+ if(arg->argflag&ARG_MAC)
+ {
+ shp->prefix = 0;
+ cp = sh_mactrim(shp,arg->argval,(flags&NV_NOREF)?-3:-1);
+ shp->prefix = prefix;
+ }
+ else
+ {
+ stakseek(0);
+ if(*arg->argval==0 && arg->argchn.ap && !(arg->argflag&~(ARG_APPEND|ARG_QUOTED|ARG_MESSAGE)))
+ {
+ int flag = (NV_VARNAME|NV_ARRAY|NV_ASSIGN);
+ int sub=0;
+ struct fornod *fp=(struct fornod*)arg->argchn.ap;
+ register Shnode_t *tp=fp->fortre;
+ flag |= (flags&(NV_NOSCOPE|NV_STATIC|NV_FARRAY));
+ if(arg->argflag&ARG_QUOTED)
+ cp = sh_mactrim(shp,fp->fornam,-1);
+ else
+ cp = fp->fornam;
+ error_info.line = fp->fortyp-shp->st.firstline;
+ if(!array && tp->tre.tretyp!=TLST && tp->com.comset && !tp->com.comarg && tp->com.comset->argval[0]==0 && tp->com.comset->argval[1]=='[')
+ array |= (tp->com.comset->argflag&ARG_MESSAGE)?NV_IARRAY:NV_ARRAY;
+ if(prefix && tp->com.comset && *cp=='[')
+ {
+ shp->prefix = 0;
+ np = nv_open(prefix,shp->last_root,flag);
+ shp->prefix = prefix;
+ if(np)
+ {
+ if(nv_isvtree(np) && !nv_isarray(np))
+ {
+ stakputc('.');
+ stakputs(cp);
+ cp = stakfreeze(1);
+ }
+ nv_close(np);
+ }
+ }
+ np = nv_open(cp,shp->var_tree,flag|NV_ASSIGN);
+ if(nv_isattr(np,NV_RDONLY) && np->nvfun && !(flags&NV_RDONLY))
+ errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
+ if(nv_isattr(np,NV_NOFREE) && nv_isnull(np))
+ nv_offattr(np,NV_NOFREE);
+ if(nv_istable(np))
+ _nv_unset(np,0);
+ if(typ && !array && (!shp->prefix || nv_isnull(np) || nv_isarray(np)))
+ {
+ if(!(nv_isnull(np)) && !nv_isarray(np))
+ _nv_unset(np,0);
+ nv_settype(np,typ,0);
+ }
+ if((flags&NV_STATIC) && !nv_isattr(np,NV_EXPORT) && !nv_isnull(np))
+#if SHOPT_TYPEDEF
+ goto check_type;
+#else
+ continue;
+#endif /* SHOPT_TYPEDEF */
+ ap=nv_arrayptr(np);
+#if SHOPT_FIXEDARRAY
+ if(ap && ap->fixed)
+ flags |= NV_FARRAY;
+#endif /* SHOPT_FIXEDARRAY */
+ if(array && (!ap || !ap->hdr.type))
+ {
+#if SHOPT_FIXEDARRAY
+ if(!(arg->argflag&ARG_APPEND) && (!ap || !ap->fixed))
+#else
+ if(!(arg->argflag&ARG_APPEND))
+#endif /* SHOPT_FIXEDARRAY */
+ _nv_unset(np,NV_EXPORT);
+ if(array&NV_ARRAY)
+ {
+ nv_setarray(np,nv_associative);
+ }
+ else
+ {
+ nv_onattr(np,NV_ARRAY);
+ }
+ }
+ if(array && tp->tre.tretyp!=TLST && !tp->com.comset && !tp->com.comarg)
+ {
+#if SHOPT_TYPEDEF
+ goto check_type;
+#else
+ continue;
+#endif /* SHOPT_TYPEDEF */
+ }
+ /* check for array assignment */
+ if(tp->tre.tretyp!=TLST && tp->com.comarg && !tp->com.comset && ((array&NV_IARRAY) || !((mp=tp->com.comnamp) && nv_isattr(mp,BLT_DCL))))
+ {
+ int argc;
+ Dt_t *last_root = shp->last_root;
+ char **argv = sh_argbuild(shp,&argc,&tp->com,0);
+ shp->last_root = last_root;
+#if SHOPT_TYPEDEF
+ if(shp->mktype && shp->dot_depth==0 && np==((struct sh_type*)shp->mktype)->nodes[0])
+ {
+ shp->mktype = 0;
+ errormsg(SH_DICT,ERROR_exit(1),"%s: not a known type name",argv[0]);
+ }
+#endif /* SHOPT_TYPEDEF */
+ if(!(arg->argflag&ARG_APPEND))
+ {
+#if SHOPT_FIXEDARRAY
+ if(!nv_isarray(np) || ((ap=nv_arrayptr(np)) && !ap->fixed && (ap->nelem&ARRAY_MASK)))
+#else
+ if(!nv_isarray(np) || ((ap=nv_arrayptr(np)) && (ap->nelem&ARRAY_MASK)))
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ if(ap)
+ ap->nelem |= ARRAY_UNDEF;
+ _nv_unset(np,0);
+ }
+ }
+ nv_setvec(np,(arg->argflag&ARG_APPEND),argc,argv);
+ if(traceon || trap)
+ {
+ int n = -1;
+ char *name = nv_name(np);
+ if(arg->argflag&ARG_APPEND)
+ n = '+';
+ if(trap)
+ sh_debug(shp,trap,name,(char*)0,argv,(arg->argflag&ARG_APPEND)|ARG_ASSIGN);
+ if(traceon)
+ {
+ sh_trace(shp,NIL(char**),0);
+ sfputr(sfstderr,name,n);
+ sfwrite(sfstderr,"=( ",3);
+ while(cp= *argv++)
+ sfputr(sfstderr,sh_fmtq(cp),' ');
+ sfwrite(sfstderr,")\n",2);
+ }
+ }
+#if SHOPT_TYPEDEF
+ goto check_type;
+#else
+ continue;
+#endif /* SHOPT_TYPEDEF */
+ }
+ if((tp->tre.tretyp&COMMSK)==TFUN)
+ goto skip;
+ if(tp->tre.tretyp==TLST || !tp->com.comset || tp->com.comset->argval[0]!='[')
+ {
+ if(tp->tre.tretyp!=TLST && !tp->com.comnamp && tp->com.comset && tp->com.comset->argval[0]==0 && tp->com.comset->argchn.ap)
+ {
+ if(prefix)
+ cp = stakcopy(nv_name(np));
+ shp->prefix = cp;
+ if(tp->com.comset->argval[1]=='[')
+ {
+ if((arg->argflag&ARG_APPEND) && (!nv_isarray(np) || (nv_aindex(np)>=0)))
+ _nv_unset(np,0);
+ if(!(array&NV_IARRAY) && !(tp->com.comset->argflag&ARG_MESSAGE))
+ nv_setarray(np,nv_associative);
+ }
+ nv_setlist(tp->com.comset,flags&~NV_STATIC,0);
+ shp->prefix = prefix;
+ if(tp->com.comset->argval[1]!='[')
+ nv_setvtree(np);
+ nv_close(np);
+#if SHOPT_TYPEDEF
+ goto check_type;
+#else
+ continue;
+#endif /* SHOPT_TYPEDEF */
+ }
+ if(*cp!='.' && *cp!='[' && strchr(cp,'['))
+ {
+ cp = stakcopy(nv_name(np));
+ nv_close(np);
+ if(!(arg->argflag&ARG_APPEND))
+ flag &= ~NV_ARRAY;
+ shp->prefix_root = shp->first_root;
+ np = nv_open(cp,shp->prefix_root?shp->prefix_root:shp->var_tree,flag);
+ }
+ if(arg->argflag&ARG_APPEND)
+ {
+ if(nv_isarray(np))
+ {
+ if((sub=nv_aimax(np)) < 0 && nv_arrayptr(np))
+ errormsg(SH_DICT,ERROR_exit(1),e_badappend,nv_name(np));
+ if(sub>=0)
+ sub++;
+ }
+ if(!nv_isnull(np) && np->nvalue.cp!=Empty && !nv_isvtree(np))
+ sub=1;
+ }
+ else if(((np->nvalue.cp && np->nvalue.cp!=Empty)||nv_isvtree(np)) && !nv_type(np))
+ _nv_unset(np,NV_EXPORT);
+ }
+ else
+ {
+ if(!(arg->argflag&ARG_APPEND))
+ _nv_unset(np,NV_EXPORT);
+ if(!sh_isoption(SH_BASH) && !(array&NV_IARRAY) && !nv_isarray(np))
+ nv_setarray(np,nv_associative);
+ }
+ skip:
+ if(sub>0)
+ {
+ sfprintf(stkstd,"%s[%d]",prefix?nv_name(np):cp,sub);
+ shp->prefix = stakfreeze(1);
+ nv_putsub(np,(char*)0,ARRAY_ADD|ARRAY_FILL|sub);
+ }
+ else if(prefix)
+ shp->prefix = stakcopy(nv_name(np));
+ else
+ shp->prefix = cp;
+ shp->last_table = 0;
+ if(shp->prefix)
+ {
+ if(*shp->prefix=='_' && shp->prefix[1]=='.' && nv_isref(L_ARGNOD))
+ {
+ sfprintf(stkstd,"%s%s",nv_name(L_ARGNOD->nvalue.nrp->np),shp->prefix+1);
+ shp->prefix = stkfreeze(stkstd,1);
+ }
+ memset(&nr,0,sizeof(nr));
+ memcpy(&node,L_ARGNOD,sizeof(node));
+ L_ARGNOD->nvalue.nrp = &nr;
+ nr.np = np;
+ nr.root = shp->last_root;
+ nr.table = shp->last_table;
+ L_ARGNOD->nvflag = NV_REF|NV_NOFREE;
+ L_ARGNOD->nvfun = 0;
+ }
+ sh_exec(tp,sh_isstate(SH_ERREXIT));
+#if SHOPT_TYPEDEF
+ if(shp->prefix)
+#endif
+ {
+ L_ARGNOD->nvalue.nrp = node.nvalue.nrp;
+ L_ARGNOD->nvflag = node.nvflag;
+ L_ARGNOD->nvfun = node.nvfun;
+ }
+ shp->prefix = prefix;
+ if(nv_isarray(np) && (mp=nv_opensub(np)))
+ np = mp;
+ while(tp->tre.tretyp==TLST)
+ {
+ if(!tp->lst.lstlef || !tp->lst.lstlef->tre.tretyp==TCOM || tp->lst.lstlef->com.comarg || tp->lst.lstlef->com.comset && tp->lst.lstlef->com.comset->argval[0]!='[')
+ break;
+ tp = tp->lst.lstrit;
+
+ }
+ if(!nv_isarray(np) && !typ && (tp->com.comarg || !tp->com.comset || tp->com.comset->argval[0]!='['))
+ {
+ nv_setvtree(np);
+ if(tp->com.comarg || tp->com.comset)
+ np->nvfun->dsize = 0;
+ }
+#if SHOPT_TYPEDEF
+ goto check_type;
+#else
+ continue;
+#endif /* SHOPT_TYPEDEF */
+ }
+ cp = arg->argval;
+ mp = 0;
+ }
+ np = nv_open(cp,shp->prefix_root?shp->prefix_root:shp->var_tree,flags);
+ if(!np->nvfun && (flags&NV_NOREF))
+ {
+ if(shp->used_pos)
+ nv_onattr(np,NV_PARAM);
+ else
+ nv_offattr(np,NV_PARAM);
+ }
+ if(traceon || trap)
+ {
+ register char *sp=cp;
+ char *name=nv_name(np);
+ char *sub=0;
+ int append = 0;
+ if(nv_isarray(np))
+ sub = savesub;
+ if(cp=lastdot(sp,'='))
+ {
+ if(cp[-1]=='+')
+ append = ARG_APPEND;
+ cp++;
+ }
+ if(traceon)
+ {
+ sh_trace(shp,NIL(char**),0);
+ nv_outname(sfstderr,name,-1);
+ if(sub)
+ sfprintf(sfstderr,"[%s]",sh_fmtq(sub));
+ if(cp)
+ {
+ if(append)
+ sfputc(sfstderr,'+');
+ sfprintf(sfstderr,"=%s\n",sh_fmtq(cp));
+ }
+ }
+ if(trap)
+ {
+ char *av[2];
+ av[0] = cp;
+ av[1] = 0;
+ sh_debug(shp,trap,name,sub,av,append);
+ }
+ }
+#if SHOPT_TYPEDEF
+ check_type:
+ if(maketype)
+ {
+ nv_open(shtp.nodes[0]->nvname,shp->var_tree,NV_ASSIGN|NV_VARNAME|NV_NOADD|NV_NOFAIL);
+ np = nv_mktype(shtp.nodes,shtp.numnodes);
+ free((void*)shtp.nodes);
+ shp->mktype = shtp.previous;
+ maketype = 0;
+ if(shp->namespace)
+ free(shp->prefix);
+ shp->prefix = 0;
+ if(nr.np == np)
+ {
+ L_ARGNOD->nvalue.nrp = node.nvalue.nrp;
+ L_ARGNOD->nvflag = node.nvflag;
+ L_ARGNOD->nvfun = node.nvfun;
+ }
+ }
+#endif /* SHOPT_TYPEDEF */
+ }
+}
+
+/*
+ * copy the subscript onto the stack
+ */
+static void stak_subscript(const char *sub, int last)
+{
+ register int c;
+ stakputc('[');
+ while(c= *sub++)
+ {
+ if(c=='[' || c==']' || c=='\\')
+ stakputc('\\');
+ stakputc(c);
+ }
+ stakputc(last);
+}
+
+/*
+ * construct a new name from a prefix and base name on the stack
+ */
+static char *copystack(const char *prefix, register const char *name, const char *sub)
+{
+ register int last=0,offset = staktell();
+ if(prefix)
+ {
+ stakputs(prefix);
+ if(*stakptr(staktell()-1)=='.')
+ stakseek(staktell()-1);
+ if(*name=='.' && name[1]=='[')
+ last = staktell()+2;
+ if(*name!='[' && *name!='.' && *name!='=' && *name!='+')
+ stakputc('.');
+ if(*name=='.' && (name[1]=='=' || name[1]==0))
+ stakputc('.');
+ }
+ if(last)
+ {
+ stakputs(name);
+ if(sh_checkid(stakptr(last),(char*)0))
+ stakseek(staktell()-2);
+ }
+ if(sub)
+ stak_subscript(sub,']');
+ if(!last)
+ stakputs(name);
+ stakputc(0);
+ return(stakptr(offset));
+}
+
+/*
+ * grow this stack string <name> by <n> bytes and move from cp-1 to end
+ * right by <n>. Returns beginning of string on the stack
+ */
+static char *stack_extend(const char *cname, char *cp, int n)
+{
+ register char *name = (char*)cname;
+ int offset = name - stakptr(0);
+ int m = cp-name;
+ stakseek(strlen(name)+n+1);
+ name = stakptr(offset);
+ cp = name + m;
+ m = strlen(cp)+1;
+ while(m-->0)
+ cp[n+m]=cp[m];
+ return((char*)name);
+}
+
+Namval_t *nv_create(const char *name, Dt_t *root, int flags, Namfun_t *dp)
+{
+ Shell_t *shp = sh_getinterp();
+ char *sub=0, *cp=(char*)name, *sp, *xp;
+ register int c;
+ register Namval_t *np=0, *nq=0;
+ Namfun_t *fp=0;
+ long mode, add=0;
+ int copy=0,isref,top=0,noscope=(flags&NV_NOSCOPE);
+ int nofree=0, level=0;
+#if SHOPT_FIXEDARRAY
+ Namarr_t *ap;
+#endif /* SHOPT_FIXEDARRAY */
+ if(root==shp->var_tree)
+ {
+ if(dtvnext(root))
+ top = 1;
+ else
+ flags &= ~NV_NOSCOPE;
+ }
+ if(!dp->disc)
+ copy = dp->nofree&1;
+ if(*cp=='.')
+ cp++;
+ while(1)
+ {
+ switch(c = *(unsigned char*)(sp = cp))
+ {
+ case '[':
+ if(flags&NV_NOARRAY)
+ {
+ dp->last = cp;
+ return(np);
+ }
+ cp = nv_endsubscript((Namval_t*)0,sp,0);
+ if(sp==name || sp[-1]=='.')
+ c = *(sp = cp);
+ goto skip;
+ case '.':
+ if(flags&NV_IDENT)
+ return(0);
+ if(root==shp->var_tree)
+ flags &= ~NV_EXPORT;
+ if(!copy && !(flags&NV_NOREF))
+ {
+ c = sp-name;
+ copy = cp-name;
+ dp->nofree |= 1;
+ name = copystack((const char*)0, name,(const char*)0);
+ cp = (char*)name+copy;
+ sp = (char*)name+c;
+ c = '.';
+ }
+ skip:
+ case '+':
+ case '=':
+ *sp = 0;
+ case 0:
+ isref = 0;
+ dp->last = cp;
+ mode = (c=='.' || (flags&NV_NOADD))?add:NV_ADD;
+ if(level++ || ((flags&NV_NOSCOPE) && c!='.'))
+ mode |= HASH_NOSCOPE;
+ np=0;
+ if(top)
+ {
+ struct Ufunction *rp;
+ if((rp=shp->st.real_fun) && !rp->sdict && (flags&NV_STATIC))
+ {
+ Dt_t *dp = dtview(shp->var_tree,(Dt_t*)0);
+ rp->sdict = dtopen(&_Nvdisc,Dtoset);
+ dtview(rp->sdict,dp);
+ dtview(shp->var_tree,rp->sdict);
+ }
+ if(np = nv_search(name,shp->var_tree,0))
+ {
+#if SHOPT_NAMESPACE
+ if(shp->var_tree->walk==shp->var_base || (shp->var_tree->walk!=shp->var_tree && shp->namespace && nv_dict(shp->namespace)==shp->var_tree->walk))
+#else
+ if(shp->var_tree->walk==shp->var_base)
+#endif /* SHOPT_NAMESPACE */
+ {
+#if SHOPT_NAMESPACE
+ if(!(nq = nv_search((char*)np,shp->var_base,HASH_BUCKET)))
+#endif /* SHOPT_NAMESPACE */
+ nq = np;
+ shp->last_root = shp->var_tree->walk;
+ if((flags&NV_NOSCOPE) && *cp!='.')
+ {
+ if(mode==0)
+ root = shp->var_tree->walk;
+ else
+ {
+ nv_delete(np,(Dt_t*)0,NV_NOFREE);
+ np = 0;
+ }
+ }
+ }
+ else
+ {
+ if(shp->var_tree->walk)
+ root = shp->var_tree->walk;
+ flags |= NV_NOSCOPE;
+ noscope = 1;
+ }
+ }
+ if(rp && rp->sdict && (flags&NV_STATIC))
+ {
+ root = rp->sdict;
+ if(np && shp->var_tree->walk==shp->var_tree)
+ {
+ _nv_unset(np,0);
+ nv_delete(np,shp->var_tree,0);
+ np = 0;
+ }
+ if(!np || shp->var_tree->walk!=root)
+ np = nv_search(name,root,HASH_NOSCOPE|NV_ADD);
+ }
+ }
+#if SHOPT_NAMESPACE
+ if(!np && !noscope && *name!='.' && shp->namespace && root==shp->var_tree)
+ root = nv_dict(shp->namespace);
+#endif /* SHOPT_NAMESPACE */
+ if(np || (np = nv_search(name,root,mode)))
+ {
+ isref = nv_isref(np);
+ shp->openmatch = 1;
+ if(top)
+ {
+ if(nq==np)
+ {
+ flags &= ~NV_NOSCOPE;
+ root = shp->last_root;
+ }
+ else if(nq)
+ {
+ if(nv_isnull(np) && c!='.' && (np->nvfun=nv_cover(nq)))
+ np->nvname = nq->nvname;
+ flags |= NV_NOSCOPE;
+ }
+ }
+ else if(add && nv_isnull(np) && c=='.' && cp[1]!='.')
+ nv_setvtree(np);
+#if SHOPT_NAMESPACE
+ if(shp->namespace && root==nv_dict(shp->namespace))
+ {
+ flags |= NV_NOSCOPE;
+ shp->last_table = shp->namespace;
+ }
+#endif /* SHOPT_NAMESPACE */
+ }
+ if(c)
+ *sp = c;
+ top = 0;
+ if(isref)
+ {
+#if SHOPT_FIXEDARRAY
+ int n=0,dim;
+#endif /* SHOPT_FIXEDARRAY */
+#if NVCACHE
+ nvcache.ok = 0;
+#endif
+ if(c=='.') /* don't optimize */
+ shp->argaddr = 0;
+ else if((flags&NV_NOREF) && (c!='[' && *cp!='.'))
+ {
+ if(c && !(flags&NV_NOADD))
+ nv_unref(np);
+ return(np);
+ }
+ while(nv_isref(np) && np->nvalue.cp)
+ {
+ root = nv_reftree(np);
+ shp->last_root = root;
+ shp->last_table = nv_reftable(np);
+ sub = nv_refsub(np);
+#if SHOPT_FIXEDARRAY
+ n = nv_refindex(np);
+ dim = nv_refdimen(np);
+#endif /* SHOPT_FIXEDARRAY */
+ np = nv_refnode(np);
+#if SHOPT_FIXEDARRAY
+ if(n)
+ {
+ ap = nv_arrayptr(np);
+ ap->nelem = dim;
+ nv_putsub(np,(char*)0,n);
+ }
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if(sub && c!='.')
+ nv_putsub(np,sub,0L);
+ flags |= NV_NOSCOPE;
+ noscope = 1;
+ }
+ shp->first_root = root;
+ if(nv_isref(np) && (c=='[' || c=='.' || !(flags&NV_ASSIGN)))
+ errormsg(SH_DICT,ERROR_exit(1),e_noref,nv_name(np));
+ if(sub && c==0)
+ {
+ if(flags&NV_ARRAY)
+ {
+ Namarr_t *ap = nv_arrayptr(np);
+ nq = nv_opensub(np);
+ if((flags&NV_ASSIGN) && (!nq || nv_isnull(nq)))
+ ap->nelem++;
+ if(!nq)
+ goto addsub;
+ }
+ return(np);
+ }
+ if(np==nq)
+ flags &= ~(noscope?0:NV_NOSCOPE);
+#if SHOPT_FIXEDARRAY
+ else if(c || n)
+#else
+ else if(c)
+#endif /* SHOPT_FIXEDARRAY */
+ {
+#if SHOPT_FIXEDARRAY
+ static char null[1] = "";
+#endif /* SHOPT_FIXEDARRAY */
+ c = (cp-sp);
+ copy = strlen(cp=nv_name(np));
+ dp->nofree |= 1;
+#if SHOPT_FIXEDARRAY
+ if(*sp==0)
+ name = cp;
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ name = copystack(cp,sp,sub);
+ sp = (char*)name + copy;
+ cp = sp+c;
+ c = *sp;
+ if(!noscope)
+ flags &= ~NV_NOSCOPE;
+#if SHOPT_FIXEDARRAY
+ if(c==0)
+ nv_endsubscript(np,null,NV_ADD);
+#endif /* SHOPT_FIXEDARRAY */
+ }
+ flags |= NV_NOREF;
+ if(nv_isnull(np) && !nv_isarray(np))
+ nofree = NV_NOFREE;
+ }
+ shp->last_root = root;
+ if(*cp && cp[1]=='.')
+ cp++;
+ if(c=='.' && (cp[1]==0 || cp[1]=='=' || cp[1]=='+'))
+ {
+ nv_local = 1;
+ if(np)
+ nv_onattr(np,nofree);
+ return(np);
+ }
+ if(cp[-1]=='.')
+ cp--;
+ do
+ {
+#if SHOPT_FIXEDARRAY
+ int fixed;
+#endif /* SHOPT_FIXEDARRAY */
+ if(!np)
+ {
+ if(!nq && *sp=='[' && *cp==0 && cp[-1]==']')
+ {
+ /*
+ * for backward compatibility
+ * evaluate subscript for
+ * possible side effects
+ */
+ cp[-1] = 0;
+ sh_arith(shp,sp+1);
+ cp[-1] = ']';
+ }
+ return(np);
+ }
+#if SHOPT_FIXEDARRAY
+ fixed = 0;
+ if((ap=nv_arrayptr(np)) && ap->fixed)
+ fixed = 1;
+#endif /* SHOPT_FIXEDARRAY */
+ if(c=='[' || (c=='.' && nv_isarray(np)))
+ {
+ int n = 0;
+ sub = 0;
+ mode &= ~HASH_NOSCOPE;
+ if(c=='[')
+ {
+#if SHOPT_FIXEDARRAY
+ Namarr_t *ap = nv_arrayptr(np);
+#endif /* SHOPT_FIXEDARRAY */
+#if 0
+ int scan = ap?(ap->nelem&ARRAY_SCAN):0;
+#endif
+ n = mode|nv_isarray(np);
+ if(!mode && (flags&NV_ARRAY) && ((c=sp[1])=='*' || c=='@') && sp[2]==']')
+ {
+ /* not implemented yet */
+ dp->last = cp;
+ return(np);
+ }
+#if SHOPT_FIXEDARRAY
+ if(fixed)
+ flags |= NV_FARRAY;
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if((n&NV_ADD)&&(flags&NV_ARRAY))
+ n |= ARRAY_FILL;
+ if(flags&NV_ASSIGN)
+ n |= NV_ADD;
+ cp = nv_endsubscript(np,sp,n|(flags&(NV_ASSIGN|NV_FARRAY)));
+#if SHOPT_FIXEDARRAY
+ flags &= ~NV_FARRAY;
+ if(fixed)
+ flags &= ~NV_ARRAY;
+
+#endif /* SHOPT_FIXEDARRAY */
+#if 0
+ if(scan)
+ nv_putsub(np,NIL(char*),ARRAY_SCAN);
+#endif
+ }
+ else
+ cp = sp;
+ if((c = *cp)=='.' || (c=='[' && nv_isarray(np)) || (n&ARRAY_FILL) || (flags&NV_ARRAY))
+
+ {
+ int m = cp-sp;
+ sub = m?nv_getsub(np):0;
+ if(!sub)
+ {
+ if(m && !(n&NV_ADD))
+ return(0);
+ sub = "0";
+ }
+ n = strlen(sub)+2;
+ if(!copy)
+ {
+ copy = cp-name;
+ dp->nofree |= 1;
+ name = copystack((const char*)0, name,(const char*)0);
+ cp = (char*)name+copy;
+ sp = cp-m;
+ }
+ if(n <= m)
+ {
+ if(n)
+ {
+ memcpy(sp+1,sub,n-2);
+ sp[n-1] = ']';
+ }
+ if(n < m)
+ {
+ char *dp = sp+n;
+ while(*dp++=*cp++);
+ cp = sp+n;
+ }
+ }
+ else
+ {
+ int r = n-m;
+ m = sp-name;
+ name = stack_extend(name, cp-1, r);
+ sp = (char*)name + m;
+ *sp = '[';
+ memcpy(sp+1,sub,n-2);
+ sp[n-1] = ']';
+ cp = sp+n;
+
+ }
+ }
+ else if(c==0 && mode && (n=nv_aindex(np))>0)
+ nv_putsub(np,(char*)0,n);
+#if SHOPT_FIXEDARRAY
+ else if(n==0 && !fixed && (c==0 || (c=='[' && !nv_isarray(np))))
+#else
+ else if(n==0 && (c==0 || (c=='[' && !nv_isarray(np))))
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ /* subscript must be 0*/
+ cp[-1] = 0;
+ n = sh_arith(shp,sp+1);
+ cp[-1] = ']';
+ if(n)
+ return(0);
+ if(c)
+ sp = cp;
+ }
+ dp->last = cp;
+ if(nv_isarray(np) && (c=='[' || c=='.' || (flags&NV_ARRAY)))
+ {
+ addsub:
+ sp = cp;
+ if(!(nq = nv_opensub(np)))
+ {
+ Namarr_t *ap = nv_arrayptr(np);
+ if(!sub && (flags&NV_NOADD))
+ return(0);
+ n = mode|((flags&NV_NOADD)?0:NV_ADD);
+ if(!ap && (n&NV_ADD))
+ {
+ nv_putsub(np,sub,ARRAY_FILL);
+ ap = nv_arrayptr(np);
+ }
+ if(n && ap && !ap->table)
+ ap->table = dtopen(&_Nvdisc,Dtoset);
+ if(ap && ap->table && (nq=nv_search(sub,ap->table,n)))
+ nq->nvenv = (char*)np;
+ if(nq && nv_isnull(nq))
+ nq = nv_arraychild(np,nq,c);
+ }
+ if(nq)
+ {
+ if(c=='.' && !nv_isvtree(nq))
+ {
+ if(flags&NV_NOADD)
+ return(0);
+ nv_setvtree(nq);
+ }
+ nv_onattr(np,nofree);
+ nofree = 0;
+ np = nq;
+ }
+ else if(memcmp(cp,"[0]",3))
+ return(nq);
+ else
+ {
+ /* ignore [0] */
+ dp->last = cp += 3;
+ c = *cp;
+ }
+ }
+ }
+#if SHOPT_FIXEDARRAY
+ else if(nv_isarray(np) && (!fixed || cp[-1]!=']'))
+#else
+ else if(nv_isarray(np))
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ if(c==0 && (flags&NV_MOVE))
+ return(np);
+ nv_putsub(np,NIL(char*),ARRAY_UNDEF);
+ }
+ nv_onattr(np,nofree);
+ nofree = 0;
+ if(c=='.' && (fp=np->nvfun))
+ {
+ for(; fp; fp=fp->next)
+ {
+ if(fp->disc && fp->disc->createf)
+ break;
+ }
+ if(fp)
+ {
+ if((nq = (*fp->disc->createf)(np,cp+1,flags,fp)) == np)
+ {
+ add = NV_ADD;
+ shp->last_table = 0;
+ break;
+ }
+ else if(np=nq)
+ {
+ if((c = *(sp=cp=dp->last=fp->last))==0)
+ {
+ if(nv_isarray(np) && sp[-1]!=']')
+ nv_putsub(np,NIL(char*),ARRAY_UNDEF);
+ return(np);
+ }
+ }
+ }
+ }
+ }
+ while(c=='[');
+ if(c!='.' || cp[1]=='.')
+ return(np);
+ cp++;
+ break;
+ default:
+ dp->last = cp;
+ if((c = mbchar(cp)) && !isaletter(c))
+ return(np);
+ while(xp=cp, c=mbchar(cp), isaname(c));
+ cp = xp;
+ }
+ }
+ return(np);
+}
+
+/*
+ * delete the node <np> from the dictionary <root> and clear from the cache
+ * if <root> is NULL, only the cache is cleared
+ * if flags does not contain NV_NOFREE, the node is freed
+ * if np==0 && !root && flags==0, delete the Refdict dictionary
+ */
+void nv_delete(Namval_t* np, Dt_t *root, int flags)
+{
+#if NVCACHE
+ register int c;
+ struct Cache_entry *xp;
+ for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c])
+ {
+ if(xp->np==np)
+ xp->root = 0;
+ }
+#endif
+ if(!np && !root && flags==0)
+ {
+ if(Refdict)
+ dtclose(Refdict);
+ Refdict = 0;
+ return;
+ }
+ if(root || !(flags&NV_NOFREE))
+ {
+ if(!(flags&NV_FUNCTION) && Refdict)
+ {
+ Namval_t **key = &np;
+ struct Namref *rp;
+ while(rp = (struct Namref*)dtmatch(Refdict,(void*)key))
+ {
+ if(rp->sub)
+ free(rp->sub);
+ rp->sub = 0;
+ rp = dtdelete(Refdict,(void*)rp);
+ rp->np = &NullNode;
+ }
+ }
+ }
+ if(root)
+ {
+ if(dtdelete(root,np))
+ {
+ if(!(flags&NV_NOFREE) && ((flags&NV_FUNCTION) || !nv_subsaved(np)))
+ free((void*)np);
+ }
+#if 0
+ else
+ {
+ sfprintf(sfstderr,"%s not deleted\n",nv_name(np));
+ sfsync(sfstderr);
+ }
+#endif
+ }
+}
+
+/*
+ * Put <arg> into associative memory.
+ * If <flags> & NV_ARRAY then follow array to next subscript
+ * If <flags> & NV_NOARRAY then subscript is not allowed
+ * If <flags> & NV_NOSCOPE then use the current scope only
+ * If <flags> & NV_ASSIGN then assignment is allowed
+ * If <flags> & NV_IDENT then name must be an identifier
+ * If <flags> & NV_VARNAME then name must be a valid variable name
+ * If <flags> & NV_NOADD then node will not be added if not found
+ * If <flags> & NV_NOREF then don't follow reference
+ * If <flags> & NV_NOFAIL then don't generate an error message on failure
+ * If <flags> & NV_STATIC then unset before an assignment
+ * If <flags> & NV_UNJUST then unset attributes before assignment
+ * SH_INIT is only set while initializing the environment
+ */
+Namval_t *nv_open(const char *name, Dt_t *root, int flags)
+{
+ Shell_t *shp = sh_getinterp();
+ register char *cp=(char*)name;
+ register int c;
+ register Namval_t *np=0;
+ Namfun_t fun;
+ int append=0;
+ const char *msg = e_varname;
+ char *fname = 0;
+ int offset = staktell();
+ Dt_t *funroot;
+#if NVCACHE
+ struct Cache_entry *xp;
+#endif
+
+ sh_stats(STAT_NVOPEN);
+ memset(&fun,0,sizeof(fun));
+ shp->openmatch = 0;
+ shp->last_table = 0;
+ if(!root)
+ root = shp->var_tree;
+ shp->last_root = root;
+ if(root==shp->fun_tree)
+ {
+ flags |= NV_NOREF;
+ msg = e_badfun;
+ if(strchr(name,'.'))
+ {
+ name = cp = copystack(0,name,(const char*)0);
+ fname = strrchr(cp,'.');
+ *fname = 0;
+ fun.nofree |= 1;
+ flags &= ~NV_IDENT;
+ funroot = root;
+ root = shp->var_tree;
+ }
+ }
+ else if(!(flags&(NV_IDENT|NV_VARNAME|NV_ASSIGN)))
+ {
+ long mode = ((flags&NV_NOADD)?0:NV_ADD);
+ if(flags&NV_NOSCOPE)
+ mode |= HASH_SCOPE|HASH_NOSCOPE;
+ np = nv_search(name,root,mode);
+ if(np && !(flags&NV_REF))
+ {
+ while(nv_isref(np))
+ {
+ shp->last_table = nv_reftable(np);
+ np = nv_refnode(np);
+ }
+ }
+ return(np);
+ }
+ else if(shp->prefix && (flags&NV_ASSIGN))
+ {
+ name = cp = copystack(shp->prefix,name,(const char*)0);
+ fun.nofree |= 1;
+ }
+ c = *(unsigned char*)cp;
+ if(root==shp->alias_tree)
+ {
+ msg = e_aliname;
+ while((c= *(unsigned char*)cp++) && (c!='=') && (c!='/') &&
+ (c>=0x200 || !(c=sh_lexstates[ST_NORM][c]) || c==S_EPAT || c==S_COLON));
+ if(shp->subshell && c=='=')
+ root = sh_subaliastree(1);
+ if(c= *--cp)
+ *cp = 0;
+ np = nv_search(name, root, (flags&NV_NOADD)?0:NV_ADD);
+ if(c)
+ *cp = c;
+ goto skip;
+ }
+ else if(flags&NV_IDENT)
+ msg = e_ident;
+ else if(c=='.')
+ {
+ c = *++cp;
+ flags |= NV_NOREF;
+ if(root==shp->var_tree)
+ root = shp->var_base;
+ shp->last_table = 0;
+ }
+ if(c= !isaletter(c))
+ goto skip;
+#if NVCACHE
+ for(c=0,xp=nvcache.entries ; c < NVCACHE; xp= &nvcache.entries[++c])
+ {
+ if(xp->root!=root)
+ continue;
+ if(*name==*xp->name && (flags&(NV_ARRAY|NV_NOSCOPE))==xp->flags && memcmp(xp->name,name,xp->len)==0 && (name[xp->len]==0 || name[xp->len]=='=' || name[xp->len]=='+'))
+ {
+ sh_stats(STAT_NVHITS);
+ np = xp->np;
+ cp = (char*)name+xp->len;
+ if(nv_isarray(np) && !(flags&NV_MOVE))
+ nv_putsub(np,NIL(char*),ARRAY_UNDEF);
+ shp->last_table = xp->last_table;
+ shp->last_root = xp->last_root;
+ goto nocache;
+ }
+ }
+ nvcache.ok = 1;
+#endif
+ np = nv_create(name, root, flags, &fun);
+ cp = fun.last;
+#if NVCACHE
+ if(np && nvcache.ok && cp[-1]!=']')
+ {
+ xp = &nvcache.entries[nvcache.index];
+ if(*cp)
+ {
+ char *sp = strchr(name,*cp);
+ if(!sp)
+ goto nocache;
+ xp->len = sp-name;
+ }
+ else
+ xp->len = strlen(name);
+ c = roundof(xp->len+1,32);
+ if(c > xp->size)
+ {
+ if(xp->size==0)
+ xp->name = malloc(c);
+ else
+ xp->name = realloc(xp->name,c);
+ xp->size = c;
+ }
+ memcpy(xp->name,name,xp->len);
+ xp->name[xp->len] = 0;
+ xp->root = root;
+ xp->np = np;
+ xp->last_table = shp->last_table;
+ xp->last_root = shp->last_root;
+ xp->flags = (flags&(NV_ARRAY|NV_NOSCOPE));
+ nvcache.index = (nvcache.index+1)&(NVCACHE-1);
+ }
+nocache:
+ nvcache.ok = 0;
+#endif
+ if(fname)
+ {
+ c = ((flags&NV_NOSCOPE)?HASH_NOSCOPE:0)|((flags&NV_NOADD)?0:NV_ADD);
+ *fname = '.';
+ np = nv_search(name, funroot, c);
+ *fname = 0;
+ }
+ else
+ {
+ if(*cp=='.' && cp[1]=='.')
+ {
+ append |= NV_NODISC;
+ cp+=2;
+ }
+ if(*cp=='+' && cp[1]=='=')
+ {
+ append |= NV_APPEND;
+ cp++;
+ }
+ }
+ c = *cp;
+skip:
+#if SHOPT_TYPEDEF
+ if(np && shp->mktype)
+ np = nv_addnode(np,0);
+#endif /* SHOPT_TYPEDEF */
+ if(c=='=' && np && (flags&NV_ASSIGN))
+ {
+ cp++;
+ if(sh_isstate(SH_INIT))
+ {
+ nv_putval(np, cp, NV_RDONLY);
+ if(np==PWDNOD)
+ nv_onattr(np,NV_TAGGED);
+ }
+ else
+ {
+ char *sub=0, *prefix= shp->prefix;
+ Namval_t *mp;
+ Namarr_t *ap;
+ int isref;
+ shp->prefix = 0;
+ if((flags&NV_STATIC) && !shp->mktype)
+ {
+ if(!nv_isnull(np))
+ {
+ shp->prefix = prefix;
+ return(np);
+ }
+ }
+ isref = nv_isref(np);
+#if SHOPT_FIXEDARRAY
+ if(sh_isoption(SH_XTRACE) && (ap=nv_arrayptr(np)) && !ap->fixed)
+#else
+ if(sh_isoption(SH_XTRACE) && nv_isarray(np))
+#endif /* SHOPT_FIXEDARRAY */
+ sub = nv_getsub(np);
+ c = msg==e_aliname? 0: (append | (flags&NV_EXPORT));
+ if(isref)
+ nv_offattr(np,NV_REF);
+ if(!append && (flags&NV_UNJUST))
+ {
+ nv_offattr(np,NV_LJUST|NV_RJUST|NV_ZFILL);
+ np->nvsize = 0;
+ }
+ if(flags&NV_MOVE)
+ {
+ if(ap=nv_arrayptr(np))
+ {
+ if(mp=nv_opensub(np))
+ np = mp;
+ else if(!array_assoc(ap) && (mp = nv_open(cp,shp->var_tree,NV_NOFAIL|NV_VARNAME|NV_NOARRAY|NV_NOASSIGN|NV_NOADD)) && nv_isvtree(np))
+ {
+ ap->nelem |= ARRAY_TREE;
+ nv_putsub(np,(char*)0,ARRAY_ADD|nv_aindex(np));
+ np = nv_opensub(np);
+ ap->nelem &= ~ARRAY_TREE;
+ ap->nelem -= 1;
+ }
+ }
+ _nv_unset(np,NV_EXPORT);
+ }
+ nv_putval(np, cp, c);
+ if(isref)
+ {
+ if(nv_search((char*)np,shp->var_base,HASH_BUCKET))
+ shp->last_root = shp->var_base;
+ nv_setref(np,(Dt_t*)0,NV_VARNAME);
+ }
+ savesub = sub;
+ shp->prefix = prefix;
+ }
+ nv_onattr(np, flags&NV_ATTRIBUTES);
+ }
+ else if(c)
+ {
+ if(flags&NV_NOFAIL)
+ return(0);
+ if(c=='.')
+ msg = e_noparent;
+ else if(c=='[')
+ msg = e_noarray;
+ errormsg(SH_DICT,ERROR_exit(1),msg,name);
+ }
+ if(fun.nofree&1)
+ stakseek(offset);
+ return(np);
+}
+
+#if SHOPT_MULTIBYTE
+ static int ja_size(char*, int, int);
+ static void ja_restore(void);
+ static char *savep;
+ static char savechars[8+1];
+#endif /* SHOPT_MULTIBYTE */
+
+/*
+ * put value <string> into name-value node <np>.
+ * If <np> is an array, then the element given by the
+ * current index is assigned to.
+ * If <flags> contains NV_RDONLY, readonly attribute is ignored
+ * If <flags> contains NV_INTEGER, string is a pointer to a number
+ * If <flags> contains NV_NOFREE, previous value is freed, and <string>
+ * becomes value of node and <flags> becomes attributes
+ */
+void nv_putval(register Namval_t *np, const char *string, int flags)
+{
+ Shell_t *shp = sh_getinterp();
+ register const char *sp=string;
+ register union Value *up;
+ register char *cp;
+ register int size = 0;
+ register int dot;
+ int was_local = nv_local;
+ union Value u;
+#if SHOPT_FIXEDARRAY
+ Namarr_t *ap;
+#endif /* SHOPT_FIXEDARRAY */
+ if(!(flags&NV_RDONLY) && nv_isattr (np, NV_RDONLY))
+ errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
+ /* The following could cause the shell to fork if assignment
+ * would cause a side effect
+ */
+ shp->argaddr = 0;
+ if(shp->subshell && !nv_local)
+ np = sh_assignok(np,1);
+ if(np->nvfun && np->nvfun->disc && !(flags&NV_NODISC) && !nv_isref(np))
+ {
+ /* This function contains disc */
+ if(!nv_local)
+ {
+ nv_local=1;
+ nv_putv(np,sp,flags,np->nvfun);
+ if(sp && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT)))
+ sh_envput(shp->env,np);
+ return;
+ }
+ /* called from disc, assign the actual value */
+ }
+ flags &= ~NV_NODISC;
+ nv_local=0;
+ if(flags&(NV_NOREF|NV_NOFREE))
+ {
+ if(np->nvalue.cp && np->nvalue.cp!=sp && !nv_isattr(np,NV_NOFREE))
+ free((void*)np->nvalue.cp);
+ np->nvalue.cp = (char*)sp;
+ nv_setattr(np,(flags&~NV_RDONLY)|NV_NOFREE);
+ return;
+ }
+ up= &np->nvalue;
+ if(nv_isattr(np,NV_INT16P) == NV_INT16)
+ {
+ if(!np->nvalue.up || !nv_isarray(np))
+ {
+ up = &u;
+ up->up = &np->nvalue;
+ }
+ }
+#if SHOPT_FIXEDARRAY
+ else if(np->nvalue.up && nv_isarray(np) && (ap=nv_arrayptr(np)) && !ap->fixed)
+#else
+ else if(np->nvalue.up && nv_isarray(np) && nv_arrayptr(np))
+#endif /* SHOPT_FIXEDARRAY */
+ up = np->nvalue.up;
+ if(up && up->cp==Empty)
+ up->cp = 0;
+ if(nv_isattr(np,NV_EXPORT))
+ nv_offattr(np,NV_IMPORT);
+ if(nv_isattr (np, NV_INTEGER))
+ {
+ if(nv_isattr(np, NV_DOUBLE) == NV_DOUBLE)
+ {
+ if(nv_isattr(np, NV_LONG) && sizeof(double)<sizeof(Sfdouble_t))
+ {
+ Sfdouble_t ld, old=0;
+ if(flags&NV_INTEGER)
+ {
+ if(flags&NV_LONG)
+ ld = *((Sfdouble_t*)sp);
+ else if(flags&NV_SHORT)
+ ld = *((float*)sp);
+ else
+ ld = *((double*)sp);
+ }
+ else
+ ld = sh_arith(shp,sp);
+ if(!up->ldp)
+ up->ldp = new_of(Sfdouble_t,0);
+ else if(flags&NV_APPEND)
+ old = *(up->ldp);
+ *(up->ldp) = old?ld+old:ld;
+ }
+ else
+ {
+ double d,od=0;
+ if(flags&NV_INTEGER)
+ {
+ if(flags&NV_LONG)
+ d = (double)(*(Sfdouble_t*)sp);
+ else if(flags&NV_SHORT)
+ d = (double)(*(float*)sp);
+ else
+ d = *(double*)sp;
+ }
+ else
+ d = sh_arith(shp,sp);
+ if(!up->dp)
+ up->dp = new_of(double,0);
+ else if(flags&NV_APPEND)
+ od = *(up->dp);
+ *(up->dp) = od?d+od:d;
+ }
+ }
+ else
+ {
+ if(nv_isattr(np, NV_LONG) && sizeof(int32_t)<sizeof(Sflong_t))
+ {
+ Sflong_t ll=0,oll=0;
+ if(flags&NV_INTEGER)
+ {
+ if((flags&NV_DOUBLE) == NV_DOUBLE)
+ {
+ if(flags&NV_LONG)
+ ll = *((Sfdouble_t*)sp);
+ else if(flags&NV_SHORT)
+ ll = *((float*)sp);
+ else
+ ll = *((double*)sp);
+ }
+ else if(nv_isattr(np,NV_UNSIGN))
+ {
+ if(flags&NV_LONG)
+ ll = *((Sfulong_t*)sp);
+ else if(flags&NV_SHORT)
+ ll = *((uint16_t*)sp);
+ else
+ ll = *((uint32_t*)sp);
+ }
+ else
+ {
+ if(flags&NV_LONG)
+ ll = *((Sflong_t*)sp);
+ else if(flags&NV_SHORT)
+ ll = *((uint16_t*)sp);
+ else
+ ll = *((uint32_t*)sp);
+ }
+ }
+ else if(sp)
+ ll = (Sflong_t)sh_arith(shp,sp);
+ if(!up->llp)
+ up->llp = new_of(Sflong_t,0);
+ else if(flags&NV_APPEND)
+ oll = *(up->llp);
+ *(up->llp) = ll+oll;
+ }
+ else
+ {
+ int32_t l=0,ol=0;
+ if(flags&NV_INTEGER)
+ {
+ if((flags&NV_DOUBLE) == NV_DOUBLE)
+ {
+ Sflong_t ll;
+ if(flags&NV_LONG)
+ ll = *((Sfdouble_t*)sp);
+ else if(flags&NV_SHORT)
+ ll = *((float*)sp);
+ else
+ ll = *((double*)sp);
+ l = (int32_t)ll;
+ }
+ else if(nv_isattr(np,NV_UNSIGN))
+ {
+ if(flags&NV_LONG)
+ l = *((Sfulong_t*)sp);
+ else if(flags&NV_SHORT)
+ l = *((uint16_t*)sp);
+ else
+ l = *(uint32_t*)sp;
+ }
+ else
+ {
+ if(flags&NV_LONG)
+ l = *((Sflong_t*)sp);
+ else if(flags&NV_SHORT)
+ l = *((int16_t*)sp);
+ else
+ l = *(int32_t*)sp;
+ }
+ }
+ else if(sp)
+ {
+ Sfdouble_t ld = sh_arith(shp,sp);
+ if(ld<0)
+ l = (int32_t)ld;
+ else
+ l = (uint32_t)ld;
+ }
+ if(nv_size(np) <= 1)
+ nv_setsize(np,10);
+ if(nv_isattr (np, NV_SHORT))
+ {
+ int16_t s=0;
+ if(flags&NV_APPEND)
+ s = *up->sp;
+ *(up->sp) = s+(int16_t)l;
+ nv_onattr(np,NV_NOFREE);
+ }
+ else
+ {
+ if(!up->lp)
+ up->lp = new_of(int32_t,0);
+ else if(flags&NV_APPEND)
+ ol = *(up->lp);
+ *(up->lp) = l+ol;
+ }
+ }
+ }
+ }
+ else
+ {
+ const char *tofree=0;
+ int offset,append;
+#if _lib_pathnative
+ char buff[PATH_MAX];
+#endif /* _lib_pathnative */
+ if(flags&NV_INTEGER)
+ {
+ if((flags&NV_DOUBLE)==NV_DOUBLE)
+ {
+ if(flags&NV_LONG)
+ sfprintf(shp->strbuf,"%.*Lg",LDBL_DIG,*((Sfdouble_t*)sp));
+ else
+ sfprintf(shp->strbuf,"%.*g",DBL_DIG,*((double*)sp));
+ }
+ else if(flags&NV_UNSIGN)
+ {
+ if(flags&NV_LONG)
+ sfprintf(shp->strbuf,"%I*lu",sizeof(Sfulong_t),*((Sfulong_t*)sp));
+ else
+ sfprintf(shp->strbuf,"%lu",(unsigned long)((flags&NV_SHORT)?*((uint16_t*)sp):*((uint32_t*)sp)));
+ }
+ else
+ {
+ if(flags&NV_LONG)
+ sfprintf(shp->strbuf,"%I*ld",sizeof(Sflong_t),*((Sflong_t*)sp));
+ else
+ sfprintf(shp->strbuf,"%ld",(long)((flags&NV_SHORT)?*((int16_t*)sp):*((int32_t*)sp)));
+ }
+ sp = sfstruse(shp->strbuf);
+ }
+ if(nv_isattr(np, NV_HOST|NV_INTEGER)==NV_HOST && sp)
+ {
+#ifdef _lib_pathnative
+ /*
+ * return the host file name given the UNIX name
+ */
+ pathnative(sp,buff,sizeof(buff));
+ if(buff[1]==':' && buff[2]=='/')
+ {
+ buff[2] = '\\';
+ if(*buff>='A' && *buff<='Z')
+ *buff += 'a'-'A';
+ }
+ sp = buff;
+#else
+ ;
+#endif /* _lib_pathnative */
+ }
+ else if((nv_isattr(np, NV_RJUST|NV_ZFILL|NV_LJUST)) && sp)
+ {
+ for(;*sp == ' '|| *sp=='\t';sp++);
+ if((nv_isattr(np,NV_ZFILL)) && (nv_isattr(np,NV_LJUST)))
+ for(;*sp=='0';sp++);
+ size = nv_size(np);
+#if SHOPT_MULTIBYTE
+ if(size)
+ size = ja_size((char*)sp,size,nv_isattr(np,NV_RJUST|NV_ZFILL));
+#endif /* SHOPT_MULTIBYTE */
+ }
+ if(!up->cp || *up->cp==0)
+ flags &= ~NV_APPEND;
+ if(!nv_isattr(np, NV_NOFREE))
+ {
+ /* delay free in case <sp> points into free region */
+ tofree = up->cp;
+ }
+ if(nv_isattr(np,NV_BINARY) && !(flags&NV_RAW))
+ tofree = 0;
+ if(nv_isattr(np,NV_LJUST|NV_RJUST) && nv_isattr(np,NV_LJUST|NV_RJUST)!=(NV_LJUST|NV_RJUST))
+ tofree = 0;
+ if (sp)
+ {
+ append=0;
+ dot = strlen(sp);
+#if (_AST_VERSION>=20030127L)
+ if(nv_isattr(np,NV_BINARY))
+ {
+ int oldsize = (flags&NV_APPEND)?nv_size(np):0;
+ if(flags&NV_RAW)
+ {
+ if(tofree)
+ {
+ free((void*)tofree);
+ nv_offattr(np,NV_NOFREE);
+ }
+ up->cp = sp;
+ return;
+ }
+ size = 0;
+ if(nv_isattr(np,NV_ZFILL))
+ size = nv_size(np);
+ if(size==0)
+ size = oldsize + (3*dot/4);
+ cp = (char*)malloc(size+1);
+ nv_offattr(np,NV_NOFREE);
+ if(oldsize)
+ memcpy((void*)cp,(void*)up->cp,oldsize);
+ up->cp = cp;
+ if(size <= oldsize)
+ return;
+ dot = base64decode(sp,dot, (void**)0, cp+oldsize, size-oldsize,(void**)0);
+ dot += oldsize;
+ if(!nv_isattr(np,NV_ZFILL) || nv_size(np)==0)
+ nv_setsize(np,dot);
+ else if(nv_isattr(np,NV_ZFILL) && (size>dot))
+ memset((void*)&cp[dot],0,size-dot);
+ return;
+ }
+ else
+#endif
+ {
+ if(size==0 && nv_isattr(np,NV_HOST)!=NV_HOST &&nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL))
+ nv_setsize(np,size=dot);
+ else if(size > dot)
+ dot = size;
+ else if(nv_isattr(np,NV_LJUST|NV_RJUST)==NV_LJUST && dot>size)
+ dot = size;
+ if(flags&NV_APPEND)
+ {
+ if(dot==0)
+ return;
+ append = strlen(up->cp);
+ if(!tofree || size)
+ {
+ offset = staktell();
+ stakputs(up->cp);
+ stakputs(sp);
+ stakputc(0);
+ sp = stakptr(offset);
+ dot += append;
+ append = 0;
+ }
+ else
+ {
+ flags &= ~NV_APPEND;
+ }
+ }
+ }
+ if(size==0 || tofree || dot || !(cp=(char*)up->cp))
+ {
+ if(dot==0 && !nv_isattr(np,NV_LJUST|NV_RJUST))
+ {
+ cp = Null;
+ nv_onattr(np,NV_NOFREE);
+ }
+ else
+ {
+ if(tofree && tofree!=Empty && tofree!=Null)
+ {
+ cp = (char*)realloc((void*)tofree,((unsigned)dot+append+8));
+ tofree = 0;
+ }
+ else
+ cp = (char*)malloc(((unsigned)dot+8));
+ cp[dot+append] = 0;
+ nv_offattr(np,NV_NOFREE);
+ }
+ }
+
+ }
+ else
+ cp = 0;
+ up->cp = cp;
+ if(sp)
+ {
+ int c = cp[dot+append];
+ memmove(cp+append,sp,dot);
+ cp[dot+append] = c;
+ if(nv_isattr(np, NV_RJUST) && nv_isattr(np, NV_ZFILL))
+ rightjust(cp,size,'0');
+ else if(nv_isattr(np, NV_LJUST|NV_RJUST)==NV_RJUST)
+ rightjust(cp,size,' ');
+ else if(nv_isattr(np, NV_LJUST|NV_RJUST)==NV_LJUST)
+ {
+ register char *dp;
+ dp = strlen (cp) + cp;
+ cp = cp+size;
+ for (; dp < cp; *dp++ = ' ');
+ }
+#if SHOPT_MULTIBYTE
+ /* restore original string */
+ if(savep)
+ ja_restore();
+#endif /* SHOPT_MULTIBYTE */
+ }
+ if(flags&NV_APPEND)
+ stakseek(offset);
+ if(tofree && tofree!=Empty && tofree!=Null)
+ free((void*)tofree);
+ }
+ if(!was_local && ((flags&NV_EXPORT) || nv_isattr(np,NV_EXPORT)))
+ sh_envput(shp->env,np);
+ return;
+}
+
+/*
+ *
+ * Right-justify <str> so that it contains no more than
+ * <size> characters. If <str> contains fewer than <size>
+ * characters, left-pad with <fill>. Trailing blanks
+ * in <str> will be ignored.
+ *
+ * If the leftmost digit in <str> is not a digit, <fill>
+ * will default to a blank.
+ */
+static void rightjust(char *str, int size, int fill)
+{
+ register int n;
+ register char *cp,*sp;
+ n = strlen(str);
+
+ /* ignore trailing blanks */
+ for(cp=str+n;n && *--cp == ' ';n--);
+ if (n == size)
+ return;
+ if(n > size)
+ {
+ *(str+n) = 0;
+ for (sp = str, cp = str+n-size; sp <= str+size; *sp++ = *cp++);
+ return;
+ }
+ else *(sp = str+size) = 0;
+ if (n == 0)
+ {
+ while (sp > str)
+ *--sp = ' ';
+ return;
+ }
+ while(n--)
+ {
+ sp--;
+ *sp = *cp--;
+ }
+ if(!isdigit(*str))
+ fill = ' ';
+ while(sp>str)
+ *--sp = fill;
+ return;
+}
+
+#if SHOPT_MULTIBYTE
+ /*
+ * handle left and right justified fields for multi-byte chars
+ * given physical size, return a logical size which reflects the
+ * screen width of multi-byte characters
+ * Multi-width characters replaced by spaces if they cross the boundary
+ * <type> is non-zero for right justified fields
+ */
+
+ static int ja_size(char *str,int size,int type)
+ {
+ register char *cp = str;
+ register int c, n=size;
+ register int outsize;
+ register char *oldcp=cp;
+ int oldn;
+ wchar_t w;
+ while(*cp)
+ {
+ oldn = n;
+ w = mbchar(cp);
+ outsize = mbwidth(w);
+ size -= outsize;
+ c = cp-oldcp;
+ n += (c-outsize);
+ oldcp = cp;
+ if(size<=0 && type==0)
+ break;
+ }
+ /* check for right justified fields that need truncating */
+ if(size <0)
+ {
+ if(type==0)
+ {
+ /* left justified and character crosses field boundary */
+ n = oldn;
+ /* save boundary char and replace with spaces */
+ size = c;
+ savechars[size] = 0;
+ while(size--)
+ {
+ savechars[size] = cp[size];
+ cp[size] = ' ';
+ }
+ savep = cp;
+ }
+ size = -size;
+ if(type)
+ n -= (ja_size(str,size,0)-size);
+ }
+ return(n);
+ }
+
+ static void ja_restore(void)
+ {
+ register char *cp = savechars;
+ while(*cp)
+ *savep++ = *cp++;
+ savep = 0;
+ }
+#endif /* SHOPT_MULTIBYTE */
+
+#ifndef _ENV_H
+static char *staknam(register Namval_t *np, char *value)
+{
+ register char *p,*q;
+ q = stakalloc(strlen(nv_name(np))+(value?strlen(value):0)+2);
+ p=strcopy(q,nv_name(np));
+ if(value)
+ {
+ *p++ = '=';
+ strcpy(p,value);
+ }
+ return(q);
+}
+#endif
+
+/*
+ * put the name and attribute into value of attributes variable
+ */
+#ifdef _ENV_H
+static void attstore(register Namval_t *np, void *data)
+{
+ register int flag, c = ' ';
+ NOT_USED(data);
+ if(!(nv_isattr(np,NV_EXPORT)))
+ return;
+ flag = nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER);
+ stakputc('=');
+ if((flag&NV_DOUBLE) == NV_DOUBLE)
+ {
+ /* export doubles as integers for ksh88 compatibility */
+ stakputc(c+NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE)));
+ }
+ else
+ {
+ stakputc(c+flag);
+ if(flag&NV_INTEGER)
+ c += nv_size(np);
+ }
+ stakputc(c);
+ stakputs(nv_name(np));
+}
+#else
+static void attstore(register Namval_t *np, void *data)
+{
+ register int flag = np->nvflag;
+ register struct adata *ap = (struct adata*)data;
+ ap->sh = sh_getinterp();
+ ap->tp = 0;
+ if(!(flag&NV_EXPORT) || (flag&NV_FUNCT))
+ return;
+ if((flag&(NV_UTOL|NV_LTOU|NV_INTEGER)) == (NV_UTOL|NV_LTOU))
+ {
+ data = (void*)nv_mapchar(np,0);
+ if(strcmp(data,e_tolower) && strcmp(data,e_toupper))
+ return;
+ }
+ flag &= (NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER);
+ *ap->attval++ = '=';
+ if((flag&NV_DOUBLE) == NV_DOUBLE)
+ {
+ /* export doubles as integers for ksh88 compatibility */
+ *ap->attval++ = ' '+ NV_INTEGER|(flag&~(NV_DOUBLE|NV_EXPNOTE));
+ *ap->attval = ' ';
+ }
+ else
+ {
+ *ap->attval++ = ' '+flag;
+ if(flag&NV_INTEGER)
+ *ap->attval = ' ' + nv_size(np);
+ else
+ *ap->attval = ' ';
+ }
+ ap->attval = strcopy(++ap->attval,nv_name(np));
+}
+#endif
+
+#ifndef _ENV_H
+static void pushnam(Namval_t *np, void *data)
+{
+ register char *value;
+ register struct adata *ap = (struct adata*)data;
+ ap->sh = sh_getinterp();
+ ap->tp = 0;
+ if(nv_isattr(np,NV_IMPORT) && np->nvenv)
+ *ap->argnam++ = np->nvenv;
+ else if(value=nv_getval(np))
+ *ap->argnam++ = staknam(np,value);
+ if(nv_isattr(np,NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER))
+ ap->attsize += (strlen(nv_name(np))+4);
+}
+#endif
+
+/*
+ * Generate the environment list for the child.
+ */
+
+#ifdef _ENV_H
+char **sh_envgen(void)
+{
+ Shell_t *shp = sh_getinterp();
+ int offset,tell;
+ register char **er;
+ env_delete(shp->env,"_");
+ er = env_get(shp->env);
+ offset = staktell();
+ stakputs(e_envmarker);
+ tell = staktell();
+ nv_scan(shp->var_tree, attstore,(void*)0,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER));
+ if(tell ==staktell())
+ stakseek(offset);
+ else
+ *--er = stakfreeze(1)+offset;
+ return(er);
+}
+#else
+char **sh_envgen(void)
+{
+ register char **er;
+ register int namec;
+ register char *cp;
+ struct adata data;
+ Shell_t *shp = sh_getinterp();
+ data.sh = shp;
+ data.tp = 0;
+ data.mapname = 0;
+ /* L_ARGNOD gets generated automatically as full path name of command */
+ nv_offattr(L_ARGNOD,NV_EXPORT);
+ data.attsize = 6;
+ namec = nv_scan(shp->var_tree,nullscan,(void*)0,NV_EXPORT,NV_EXPORT);
+ namec += shp->nenv;
+ er = (char**)stakalloc((namec+4)*sizeof(char*));
+ data.argnam = (er+=2) + shp->nenv;
+ if(shp->nenv)
+ memcpy((void*)er,environ,shp->nenv*sizeof(char*));
+ nv_scan(shp->var_tree, pushnam,&data,NV_EXPORT, NV_EXPORT);
+ *data.argnam = (char*)stakalloc(data.attsize);
+ cp = data.attval = strcopy(*data.argnam,e_envmarker);
+ nv_scan(shp->var_tree, attstore,&data,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER));
+ *data.attval = 0;
+ if(cp!=data.attval)
+ data.argnam++;
+ *data.argnam = 0;
+ return(er);
+}
+#endif
+
+struct scan
+{
+ void (*scanfn)(Namval_t*, void*);
+ int scanmask;
+ int scanflags;
+ int scancount;
+ void *scandata;
+};
+
+static int scanfilter(Dt_t *dict, void *arg, void *data)
+{
+ register Namval_t *np = (Namval_t*)arg;
+ register int k=np->nvflag;
+ register struct scan *sp = (struct scan*)data;
+ register struct adata *tp = (struct adata*)sp->scandata;
+ char *cp;
+ NOT_USED(dict);
+#if SHOPT_TYPEDEF
+ if(!is_abuiltin(np) && tp && tp->tp && nv_type(np)!=tp->tp)
+ return(0);
+#endif /*SHOPT_TYPEDEF */
+ if(sp->scanmask?(k&sp->scanmask)==sp->scanflags:(!sp->scanflags || (k&sp->scanflags)))
+ {
+ if(tp && tp->mapname)
+ {
+ if(sp->scanflags==NV_FUNCTION || sp->scanflags==(NV_NOFREE|NV_BINARY|NV_RAW))
+ {
+ int n = strlen(tp->mapname);
+ if(memcmp(np->nvname,tp->mapname,n) || np->nvname[n]!='.' || strchr(&np->nvname[n+1],'.'))
+ return(0);
+ }
+ else if((sp->scanflags==NV_UTOL||sp->scanflags==NV_LTOU) && (cp=(char*)nv_mapchar(np,0)) && strcmp(cp,tp->mapname))
+ return(0);
+ }
+ if(!np->nvalue.cp && !np->nvfun && !nv_isattr(np,~NV_DEFAULT))
+ return(0);
+ if(sp->scanfn)
+ {
+ if(nv_isarray(np))
+ nv_putsub(np,NIL(char*),0L);
+ (*sp->scanfn)(np,sp->scandata);
+ }
+ sp->scancount++;
+ }
+ return(0);
+}
+
+/*
+ * Walk through the name-value pairs
+ * if <mask> is non-zero, then only nodes with (nvflags&mask)==flags
+ * are visited
+ * If <mask> is zero, and <flags> non-zero, then nodes with one or
+ * more of <flags> is visited
+ * If <mask> and <flags> are zero, then all nodes are visted
+ */
+int nv_scan(Dt_t *root, void (*fn)(Namval_t*,void*), void *data,int mask, int flags)
+{
+ Dt_t *base=0;
+ struct scan sdata;
+ int (*hashfn)(Dt_t*, void*, void*);
+ sdata.scanmask = mask;
+ sdata.scanflags = flags&~NV_NOSCOPE;
+ sdata.scanfn = fn;
+ sdata.scancount = 0;
+ sdata.scandata = data;
+ hashfn = scanfilter;
+ if(flags&NV_NOSCOPE)
+ base = dtview((Dt_t*)root,0);
+ dtwalk(root, hashfn,&sdata);
+ if(base)
+ dtview((Dt_t*)root,base);
+ return(sdata.scancount);
+}
+
+/*
+ * create a new environment scope
+ */
+void sh_scope(Shell_t *shp, struct argnod *envlist, int fun)
+{
+ register Dt_t *newscope, *newroot=shp->var_base;
+ struct Ufunction *rp;
+#if SHOPT_NAMESPACE
+ if(shp->namespace)
+ {
+ newroot = nv_dict(shp->namespace);
+ dtview(newroot,(Dt_t*)shp->var_base);
+ }
+#endif /* SHOPT_NAMESPACE */
+ newscope = dtopen(&_Nvdisc,Dtoset);
+ if(envlist)
+ {
+ dtview(newscope,(Dt_t*)shp->var_tree);
+ shp->var_tree = newscope;
+ nv_setlist(envlist,NV_EXPORT|NV_NOSCOPE|NV_IDENT|NV_ASSIGN,0);
+ if(!fun)
+ return;
+ shp->var_tree = dtview(newscope,0);
+ }
+ if((rp=shp->st.real_fun) && rp->sdict)
+ {
+ dtview(rp->sdict,newroot);
+ newroot = rp->sdict;
+
+ }
+ dtview(newscope,(Dt_t*)newroot);
+ shp->var_tree = newscope;
+}
+
+/*
+ * Remove freeable local space associated with the nvalue field
+ * of nnod. This includes any strings representing the value(s) of the
+ * node, as well as its dope vector, if it is an array.
+ */
+
+void sh_envnolocal (register Namval_t *np, void *data)
+{
+ struct adata *tp = (struct adata*)data;
+ char *cp=0;
+ if(np==VERSIONNOD && nv_isref(np))
+ return;
+ if(np==L_ARGNOD)
+ return;
+ if(np == tp->sh->namespace)
+ return;
+ if(nv_isref(np))
+ nv_unref(np);
+ if(nv_isattr(np,NV_EXPORT) && nv_isarray(np))
+ {
+ nv_putsub(np,NIL(char*),0);
+ if(cp = nv_getval(np))
+ cp = strdup(cp);
+ }
+ if(nv_isattr(np,NV_EXPORT|NV_NOFREE))
+ {
+ if(nv_isref(np) && np!=VERSIONNOD)
+ {
+ nv_offattr(np,NV_NOFREE|NV_REF);
+ free((void*)np->nvalue.nrp);
+ np->nvalue.cp = 0;
+ }
+ if(!cp)
+ return;
+ }
+ if(nv_isarray(np))
+ nv_putsub(np,NIL(char*),ARRAY_UNDEF);
+ _nv_unset(np,NV_RDONLY);
+ nv_setattr(np,0);
+ if(cp)
+ {
+ nv_putval(np,cp,0);
+ free((void*)cp);
+ }
+}
+
+/*
+ * Currently this is a dummy, but someday will be needed
+ * for reference counting
+ */
+void nv_close(Namval_t *np)
+{
+ NOT_USED(np);
+}
+
+static void table_unset(Shell_t *shp, register Dt_t *root, int flags, Dt_t *oroot)
+{
+ register Namval_t *np,*nq, *npnext;
+ for(np=(Namval_t*)dtfirst(root);np;np=npnext)
+ {
+ if(nq=dtsearch(oroot,np))
+ {
+ if(nv_cover(nq))
+ {
+ int subshell = shp->subshell;
+ shp->subshell = 0;
+ if(nv_isattr(nq, NV_INTEGER))
+ {
+ Sfdouble_t d = nv_getnum(nq);
+ nv_putval(nq,(char*)&d,NV_LDOUBLE);
+ }
+ else if(shp->test&4)
+ nv_putval(nq, strdup(nv_getval(nq)), NV_RDONLY);
+ else
+ nv_putval(nq, nv_getval(nq), NV_RDONLY);
+ shp->subshell = subshell;
+ np->nvfun = 0;
+ }
+ if(nv_isattr(nq,NV_EXPORT))
+ sh_envput(shp->env,nq);
+ }
+ npnext = (Namval_t*)dtnext(root,np);
+ shp->last_root = root;
+ shp->last_table = 0;
+ if(nv_isvtree(np))
+ {
+ int len = strlen(np->nvname);
+ while((nq=npnext) && memcmp(np->nvname,nq->nvname,len)==0 && nq->nvname[len]=='.')
+
+ {
+ npnext = (Namval_t*)dtnext(root,nq);
+ _nv_unset(nq,flags);
+ nv_delete(nq,root,0);
+ }
+ }
+ _nv_unset(np,flags);
+ nv_delete(np,root,0);
+ }
+}
+
+/*
+ *
+ * Set the value of <np> to 0, and nullify any attributes
+ * that <np> may have had. Free any freeable space occupied
+ * by the value of <np>. If <np> denotes an array member, it
+ * will retain its attributes.
+ * <flags> can contain NV_RDONLY to override the readonly attribute
+ * being cleared.
+ * <flags> can contain NV_EXPORT to override preserve nvenv
+ */
+void _nv_unset(register Namval_t *np,int flags)
+{
+ Shell_t *shp = sh_getinterp();
+ register union Value *up;
+#if SHOPT_FIXEDARRAY
+ Namarr_t *ap;
+#endif /* SHOPT_FIXEDARRAY */
+ if(!(flags&NV_RDONLY) && nv_isattr (np,NV_RDONLY))
+ errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
+ if(is_afunction(np) && np->nvalue.ip)
+ {
+ register struct slnod *slp = (struct slnod*)(np->nvenv);
+ if(slp && !nv_isattr(np,NV_NOFREE))
+ {
+ struct Ufunction *rq,*rp = np->nvalue.rp;
+ /* free function definition */
+ register char *name=nv_name(np),*cp= strrchr(name,'.');
+ if(cp)
+ {
+ Namval_t *npv;
+ *cp = 0;
+ npv = nv_open(name,shp->var_tree,NV_NOARRAY|NV_VARNAME|NV_NOADD);
+ *cp++ = '.';
+ if(npv && npv!=shp->namespace)
+ nv_setdisc(npv,cp,NIL(Namval_t*),(Namfun_t*)npv);
+ }
+ if(rp->fname && shp->fpathdict && (rq = (struct Ufunction*)nv_search(rp->fname,shp->fpathdict,0)))
+ {
+ do
+ {
+ if(rq->np != np)
+ continue;
+ dtdelete(shp->fpathdict,rq);
+ break;
+ }
+ while(rq = (struct Ufunction*)dtnext(shp->fpathdict,rq));
+ }
+ if(rp->sdict)
+ {
+ Namval_t *mp, *nq;
+ for(mp=(Namval_t*)dtfirst(rp->sdict);mp;mp=nq)
+ {
+ nq = dtnext(rp->sdict,mp);
+ _nv_unset(mp,NV_RDONLY);
+ nv_delete(mp,rp->sdict,0);
+ }
+ dtclose(rp->sdict);
+ }
+ stakdelete(slp->slptr);
+ free((void*)np->nvalue.ip);
+ np->nvalue.ip = 0;
+ }
+ goto done;
+ }
+ if(shp->subshell)
+ np = sh_assignok(np,0);
+ nv_offattr(np,NV_NODISC);
+ if(np->nvfun && !nv_isref(np))
+ {
+ /* This function contains disc */
+ if(!nv_local)
+ {
+ nv_local=1;
+ nv_putv(np,NIL(char*),flags,np->nvfun);
+ nv_local=0;
+ return;
+ }
+ /* called from disc, assign the actual value */
+ nv_local=0;
+ }
+ if(nv_isattr(np,NV_INT16P) == NV_INT16)
+ {
+ np->nvalue.cp = nv_isarray(np)?Empty:0;
+ goto done;
+ }
+#if SHOPT_FIXEDARRAY
+ else if(np->nvalue.up && nv_isarray(np) && (ap=nv_arrayptr(np)) && !ap->fixed)
+#else
+ else if(np->nvalue.up && nv_isarray(np) && nv_arrayptr(np))
+#endif /* SHOPT_FIXEDARRAY */
+ up = np->nvalue.up;
+ else if(nv_isref(np) && !nv_isattr(np,NV_EXPORT|NV_MINIMAL) && np->nvalue.nrp)
+ {
+
+ if(np->nvalue.nrp->root)
+ dtdelete(Refdict,(void*)np->nvalue.nrp);
+ if(np->nvalue.nrp->sub)
+ free(np->nvalue.nrp->sub);
+ free((void*)np->nvalue.nrp);
+ np->nvalue.cp = 0;
+ up = 0;
+ }
+ else
+ up = &np->nvalue;
+ if(up && up->cp)
+ {
+ if(up->cp!=Empty && up->cp!=Null && !nv_isattr(np, NV_NOFREE))
+ free((void*)up->cp);
+ up->cp = 0;
+ }
+done:
+ if(!nv_isarray(np) || !nv_arrayptr(np))
+ {
+ nv_setsize(np,0);
+ if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(np,NV_EXPORT))
+ {
+ if(nv_isattr(np,NV_EXPORT) && !strchr(np->nvname,'['))
+ env_delete(shp->env,nv_name(np));
+ if(!(flags&NV_EXPORT) || nv_isattr(np,NV_IMPORT|NV_EXPORT)==(NV_IMPORT|NV_EXPORT))
+ np->nvenv = 0;
+ nv_setattr(np,0);
+ }
+ else
+ {
+ nv_setattr(np,NV_MINIMAL);
+ nv_delete(np,(Dt_t*)0,0);
+ }
+ }
+}
+
+/*
+ * return the node pointer in the highest level scope
+ */
+Namval_t *sh_scoped(Shell_t *shp, register Namval_t *np)
+{
+ if(!dtvnext(shp->var_tree))
+ return(np);
+ return(dtsearch(shp->var_tree,np));
+}
+
+#if 1
+/*
+ * return space separated list of names of variables in given tree
+ */
+static char *tableval(Dt_t *root)
+{
+ static Sfio_t *out;
+ register Namval_t *np;
+ register int first=1;
+ register Dt_t *base = dtview(root,0);
+ if(out)
+ sfseek(out,(Sfoff_t)0,SEEK_SET);
+ else
+ out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
+ for(np=(Namval_t*)dtfirst(root);np;np=(Namval_t*)dtnext(root,np))
+ {
+ if(!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE))
+ {
+ if(!first)
+ sfputc(out,' ');
+ else
+ first = 0;
+ sfputr(out,np->nvname,-1);
+ }
+ }
+ sfputc(out,0);
+ if(base)
+ dtview(root,base);
+ return((char*)out->_data);
+}
+#endif
+
+#if SHOPT_OPTIMIZE
+struct optimize
+{
+ Namfun_t hdr;
+ Shell_t *sh;
+ char **ptr;
+ struct optimize *next;
+ Namval_t *np;
+};
+
+static struct optimize *opt_free;
+
+static void optimize_clear(Namval_t* np, Namfun_t *fp)
+{
+ struct optimize *op = (struct optimize*)fp;
+ nv_stack(np,fp);
+ nv_stack(np,(Namfun_t*)0);
+ for(;op && op->np==np; op=op->next)
+ {
+ if(op->ptr)
+ {
+ *op->ptr = 0;
+ op->ptr = 0;
+ }
+ }
+}
+
+static void put_optimize(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ nv_putv(np,val,flags,fp);
+ optimize_clear(np,fp);
+}
+
+static Namfun_t *clone_optimize(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ return((Namfun_t*)0);
+}
+
+static const Namdisc_t optimize_disc = {sizeof(struct optimize),put_optimize,0,0,0,0,clone_optimize};
+
+void nv_optimize(Namval_t *np)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namfun_t *fp;
+ register struct optimize *op, *xp;
+ if(shp->argaddr)
+ {
+ if(np==SH_LINENO)
+ {
+ shp->argaddr = 0;
+ return;
+ }
+ for(fp=np->nvfun; fp; fp = fp->next)
+ {
+ if(fp->disc && (fp->disc->getnum || fp->disc->getval))
+ {
+ shp->argaddr = 0;
+ return;
+ }
+ if(fp->disc== &optimize_disc)
+ break;
+ }
+ if((xp= (struct optimize*)fp) && xp->ptr==shp->argaddr)
+ return;
+ if(op = opt_free)
+ opt_free = op->next;
+ else
+ op=(struct optimize*)calloc(1,sizeof(struct optimize));
+ op->ptr = shp->argaddr;
+ op->np = np;
+ if(xp)
+ {
+ op->hdr.disc = 0;
+ op->next = xp->next;
+ xp->next = op;
+ }
+ else
+ {
+ op->hdr.disc = &optimize_disc;
+ op->next = (struct optimize*)shp->optlist;
+ shp->optlist = (void*)op;
+ nv_stack(np,&op->hdr);
+ }
+ }
+}
+
+void sh_optclear(Shell_t *shp, void *old)
+{
+ register struct optimize *op,*opnext;
+ for(op=(struct optimize*)shp->optlist; op; op = opnext)
+ {
+ opnext = op->next;
+ if(op->ptr && op->hdr.disc)
+ {
+ nv_stack(op->np,&op->hdr);
+ nv_stack(op->np,(Namfun_t*)0);
+ }
+ op->next = opt_free;
+ opt_free = op;
+ }
+ shp->optlist = old;
+}
+
+#else
+# define optimize_clear(np,fp)
+#endif /* SHOPT_OPTIMIZE */
+
+/*
+ * Return a pointer to a character string that denotes the value
+ * of <np>. If <np> refers to an array, return a pointer to
+ * the value associated with the current index.
+ *
+ * If the value of <np> is an integer, the string returned will
+ * be overwritten by the next call to nv_getval.
+ *
+ * If <np> has no value, 0 is returned.
+ */
+
+char *nv_getval(register Namval_t *np)
+{
+ Shell_t *shp = sh_getinterp();
+ register union Value *up= &np->nvalue;
+ register int numeric;
+#if SHOPT_OPTIMIZE
+ if(!nv_local && shp->argaddr)
+ nv_optimize(np);
+#endif /* SHOPT_OPTIMIZE */
+ if((!np->nvfun || !np->nvfun->disc) && !nv_isattr(np,NV_ARRAY|NV_INTEGER|NV_FUNCT|NV_REF))
+ goto done;
+ if(nv_isref(np))
+ {
+ if(!np->nvalue.cp)
+ return(0);
+ shp->last_table = nv_reftable(np);
+ return(nv_name(nv_refnode(np)));
+ }
+ if(np->nvfun && np->nvfun->disc)
+ {
+ if(!nv_local)
+ {
+ nv_local=1;
+ return(nv_getv(np, np->nvfun));
+ }
+ nv_local=0;
+ }
+ numeric = ((nv_isattr (np, NV_INTEGER)) != 0);
+ if(numeric)
+ {
+ Sflong_t ll;
+ if(!up->cp)
+ return("0");
+ if(nv_isattr (np,NV_DOUBLE)==NV_DOUBLE)
+ {
+ Sfdouble_t ld;
+ double d;
+ char *format;
+ if(nv_isattr(np,NV_LONG))
+ {
+ ld = *up->ldp;
+ if(nv_isattr (np,NV_EXPNOTE))
+ format = "%.*Lg";
+ else if(nv_isattr (np,NV_HEXFLOAT))
+ format = "%.*La";
+ else
+ format = "%.*Lf";
+ sfprintf(shp->strbuf,format,nv_size(np),ld);
+ }
+ else
+ {
+ d = *up->dp;
+ if(nv_isattr (np,NV_EXPNOTE))
+ format = "%.*g";
+ else if(nv_isattr (np,NV_HEXFLOAT))
+ format = "%.*a";
+ else
+ format = "%.*f";
+ sfprintf(shp->strbuf,format,nv_size(np),d);
+ }
+ return(sfstruse(shp->strbuf));
+ }
+ else if(nv_isattr(np,NV_UNSIGN))
+ {
+ if(nv_isattr (np,NV_LONG))
+ ll = *(Sfulong_t*)up->llp;
+ else if(nv_isattr (np,NV_SHORT))
+ {
+ if(nv_isattr(np,NV_INT16P)==NV_INT16P)
+ ll = *(uint16_t*)(up->sp);
+ else
+ ll = (uint16_t)up->s;
+ }
+ else
+ ll = *(uint32_t*)(up->lp);
+ }
+ else if(nv_isattr (np,NV_LONG))
+ ll = *up->llp;
+ else if(nv_isattr (np,NV_SHORT))
+ {
+ if(nv_isattr(np,NV_INT16P)==NV_INT16P)
+ ll = *up->sp;
+ else
+ ll = up->s;
+ }
+ else
+ ll = *(up->lp);
+ if((numeric=nv_size(np))==10)
+ {
+ if(nv_isattr(np,NV_UNSIGN))
+ {
+ sfprintf(shp->strbuf,"%I*u",sizeof(ll),ll);
+ return(sfstruse(shp->strbuf));
+ }
+ numeric = 0;
+ }
+ return(fmtbase(ll,numeric, numeric&&numeric!=10));
+ }
+done:
+#if (_AST_VERSION>=20030127L)
+ /*
+ * if NV_RAW flag is on, return pointer to binary data
+ * otherwise, base64 encode the data and return this string
+ */
+ if(up->cp && nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW))
+ {
+ char *cp;
+ char *ep;
+ int size= nv_size(np), insize=(4*size)/3+size/45+8;
+ base64encode(up->cp, size, (void**)0, cp=getbuf(insize), insize, (void**)&ep);
+ *ep = 0;
+ return(cp);
+ }
+#endif
+ if(!nv_isattr(np,NV_LJUST|NV_RJUST) && (numeric=nv_size(np)) && up->cp && up->cp[numeric])
+ {
+ char *cp = getbuf(numeric+1);
+ memcpy(cp,up->cp,numeric);
+ cp[numeric]=0;
+ return(cp);
+ }
+ return ((char*)up->cp);
+}
+
+Sfdouble_t nv_getnum(register Namval_t *np)
+{
+ Shell_t *shp = sh_getinterp();
+ register union Value *up;
+ register Sfdouble_t r=0;
+ register char *str;
+#if SHOPT_OPTIMIZE
+ if(!nv_local && shp->argaddr)
+ nv_optimize(np);
+#endif /* SHOPT_OPTIMIZE */
+ if(nv_istable(np))
+ errormsg(SH_DICT,ERROR_exit(1),e_number,nv_name(np));
+ if(np->nvfun && np->nvfun->disc)
+ {
+ if(!nv_local)
+ {
+ nv_local=1;
+ return(nv_getn(np, np->nvfun));
+ }
+ nv_local=0;
+ }
+ if(nv_isref(np))
+ {
+ str = nv_refsub(np);
+ np = nv_refnode(np);
+ if(str)
+ nv_putsub(np,str,0L);
+ }
+ if(nv_isattr (np, NV_INTEGER))
+ {
+ up= &np->nvalue;
+ if(!up->lp || up->cp==Empty)
+ r = 0;
+ else if(nv_isattr(np, NV_DOUBLE)==NV_DOUBLE)
+ {
+ if(nv_isattr(np, NV_LONG))
+ r = *up->ldp;
+ else
+ r = *up->dp;
+ }
+ else if(nv_isattr(np, NV_UNSIGN))
+ {
+ if(nv_isattr(np, NV_LONG))
+ r = (Sflong_t)*((Sfulong_t*)up->llp);
+ else if(nv_isattr(np, NV_SHORT))
+ {
+ if(nv_isattr(np,NV_INT16P)==NV_INT16P)
+ r = (Sflong_t)(*(uint16_t*)up->sp);
+ else
+ r = (Sflong_t)((uint16_t)up->s);
+ }
+ else
+ r = *((uint32_t*)up->lp);
+ }
+ else
+ {
+ if(nv_isattr(np, NV_LONG))
+ r = *up->llp;
+ else if(nv_isattr(np, NV_SHORT))
+ {
+ if(nv_isattr(np,NV_INT16P)==NV_INT16P)
+ r = *up->sp;
+ else
+ r = up->s;
+ }
+ else
+ r = *up->lp;
+ }
+ }
+ else if((str=nv_getval(np)) && *str!=0)
+ {
+ if(nv_isattr(np,NV_LJUST|NV_RJUST) || (*str=='0' && !(str[1]=='x'||str[1]=='X')))
+ {
+ while(*str=='0')
+ str++;
+ }
+ r = sh_arith(shp,str);
+ }
+ return(r);
+}
+
+/*
+ * Give <np> the attributes <newatts,> and change its current
+ * value to conform to <newatts>. The <size> of left and right
+ * justified fields may be given.
+ */
+void nv_newattr (register Namval_t *np, unsigned newatts, int size)
+{
+ Shell_t *shp = sh_getinterp();
+ register char *sp;
+ register char *cp = 0;
+ register unsigned int n;
+ Namval_t *mp = 0;
+ Namarr_t *ap = 0;
+ int oldsize,oldatts,trans;
+ Namfun_t *fp= (newatts&NV_NODISC)?np->nvfun:0;
+ char *prefix = shp->prefix,*sub;
+ newatts &= ~NV_NODISC;
+
+ /* check for restrictions */
+ if(sh_isoption(SH_RESTRICTED) && ((sp=nv_name(np))==nv_name(PATHNOD) || sp==nv_name(SHELLNOD) || sp==nv_name(ENVNOD) || sp==nv_name(FPATHNOD)))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,nv_name(np));
+ /* handle attributes that do not change data separately */
+ n = np->nvflag;
+ trans = !(n&NV_INTEGER) && (n&(NV_LTOU|NV_UTOL));
+ if(newatts&NV_EXPORT)
+ nv_offattr(np,NV_IMPORT);
+ if(((n^newatts)&NV_EXPORT))
+ {
+ /* record changes to the environment */
+ if(n&NV_EXPORT)
+ env_delete(shp->env,nv_name(np));
+ else
+ sh_envput(shp->env,np);
+ }
+ oldsize = nv_size(np);
+ if((size==oldsize|| (n&NV_INTEGER)) && !trans && ((n^newatts)&~NV_NOCHANGE)==0)
+ {
+ if(size)
+ nv_setsize(np,size);
+ nv_offattr(np, ~NV_NOFREE);
+ nv_onattr(np, newatts);
+ return;
+ }
+ /* for an array, change all the elements */
+ if((ap=nv_arrayptr(np)) && ap->nelem>0)
+ nv_putsub(np,NIL(char*),ARRAY_SCAN);
+ oldsize = nv_size(np);
+ oldatts = np->nvflag;
+ if(fp)
+ np->nvfun = 0;
+ if(ap) /* add element to prevent array deletion */
+ {
+ ap->nelem++;
+#if SHOPT_FIXEDARRAY
+ if(ap->fixed)
+ {
+ nv_setsize(np,size);
+ np->nvflag &= NV_ARRAY;
+ np->nvflag |= newatts;
+ goto skip;
+ }
+#endif /* SHOPT_TYPEDEF */
+ }
+ do
+ {
+ nv_setsize(np,oldsize);
+ np->nvflag = oldatts;
+ if (sp = nv_getval(np))
+ {
+ if(nv_isattr(np,NV_ZFILL))
+ while(*sp=='0') sp++;
+ cp = (char*)malloc((n=strlen (sp)) + 8);
+ strcpy(cp, sp);
+ if(sp && (mp=nv_opensub(np)))
+ {
+ sub = nv_getsub(mp);
+ if(trans)
+ {
+ nv_disc(np, &ap->hdr,NV_POP);
+ nv_clone(np,mp,0);
+ nv_disc(np, &ap->hdr,NV_FIRST);
+ nv_offattr(mp,NV_ARRAY);
+ }
+ nv_newattr(mp,newatts&~NV_ARRAY,size);
+ }
+ if(!mp)
+ {
+ if(ap)
+ ap->nelem &= ~ARRAY_SCAN;
+ if(!trans)
+ _nv_unset(np,NV_RDONLY|NV_EXPORT);
+ if(ap)
+ ap->nelem |= ARRAY_SCAN;
+ }
+ if(size==0 && (newatts&NV_HOST)!=NV_HOST && (newatts&(NV_LJUST|NV_RJUST|NV_ZFILL)))
+ size = n;
+ }
+ else if(!trans)
+ _nv_unset(np,NV_EXPORT);
+ nv_setsize(np,size);
+ np->nvflag &= (NV_ARRAY|NV_NOFREE);
+ np->nvflag |= newatts;
+ if (cp)
+ {
+ if(!mp)
+ nv_putval (np, cp, NV_RDONLY);
+ free(cp);
+ }
+ }
+ while(ap && nv_nextsub(np));
+#if SHOPT_FIXEDARRAY
+skip:
+#endif /* SHOPT_TYPEDEF */
+ if(fp)
+ np->nvfun = fp;
+ if(ap)
+ ap->nelem--;
+ shp->prefix = prefix;
+ return;
+}
+
+static char *oldgetenv(const char *string)
+{
+ register char c0,c1;
+ register const char *cp, *sp;
+ register char **av = environ;
+ if(!string || (c0= *string)==0)
+ return(0);
+ if((c1=*++string)==0)
+ c1= '=';
+ while(cp = *av++)
+ {
+ if(cp[0]!=c0 || cp[1]!=c1)
+ continue;
+ sp = string;
+ while(*sp && *sp++ == *++cp);
+ if(*sp==0 && *++cp=='=')
+ return((char*)(cp+1));
+ }
+ return(0);
+}
+
+/*
+ * This version of getenv uses the hash storage to access environment values
+ */
+char *sh_getenv(const char *name)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namval_t *np;
+ if(!shp->var_tree)
+ {
+#if 0
+ if(name[0] == 'P' && name[1] == 'A' && name[2] == 'T' && name[3] == 'H' && name[4] == 0 || name[0] == 'L' && ((name[1] == 'C' || name[1] == 'D') && name[2] == '_' || name[1] == 'A' && name[1] == 'N') || name[0] == 'V' && name[1] == 'P' && name[2] == 'A' && name[3] == 'T' && name[4] == 'H' && name[5] == 0 || name[0] == '_' && name[1] == 'R' && name[2] == 'L' && name[3] == 'D' || name[0] == '_' && name[1] == 'A' && name[2] == 'S' && name[3] == 'T' && name[4] == '_')
+#endif
+ return(oldgetenv(name));
+ }
+ else if((np = nv_search(name,shp->var_tree,0)) && nv_isattr(np,NV_EXPORT))
+ return(nv_getval(np));
+ return(0);
+}
+
+#ifndef _NEXT_SOURCE
+/*
+ * Some dynamic linkers will make this file see the libc getenv(),
+ * so sh_getenv() is used for the astintercept() callback. Plain
+ * getenv() is provided for static links.
+ */
+char *getenv(const char *name)
+{
+ return sh_getenv(name);
+}
+#endif /* _NEXT_SOURCE */
+
+#undef putenv
+/*
+ * This version of putenv uses the hash storage to assign environment values
+ */
+int putenv(const char *name)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namval_t *np;
+ if(name)
+ {
+ np = nv_open(name,shp->var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN);
+ if(!strchr(name,'='))
+ _nv_unset(np,0);
+ }
+ return(0);
+}
+
+/*
+ * Override libast setenviron().
+ */
+char* sh_setenviron(const char *name)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namval_t *np;
+ if(name)
+ {
+ np = nv_open(name,shp->var_tree,NV_EXPORT|NV_IDENT|NV_NOARRAY|NV_ASSIGN);
+ if(strchr(name,'='))
+ return(nv_getval(np));
+ _nv_unset(np,0);
+ }
+ return("");
+}
+
+/*
+ * Same linker dance as with getenv() above.
+ */
+char* setenviron(const char *name)
+{
+ return sh_setenviron(name);
+}
+
+/*
+ * normalize <cp> and return pointer to subscript if any
+ * if <eq> is specified, return pointer to first = not in a subscript
+ */
+static char *lastdot(char *cp, int eq)
+{
+ register char *ep=0;
+ register int c;
+ if(eq)
+ cp++;
+ while(c= mbchar(cp))
+ {
+ if(c=='[')
+ {
+ if(*cp==']')
+ cp++;
+ else
+ cp = nv_endsubscript((Namval_t*)0,ep=cp,0);
+ }
+ else if(c=='.')
+ {
+ if(*cp=='[')
+ {
+ cp = nv_endsubscript((Namval_t*)0,ep=cp,0);
+ if((ep=sh_checkid(ep+1,cp)) < cp)
+ cp=strcpy(ep,cp);
+ }
+ ep = 0;
+ }
+ else if(eq && c == '=')
+ return(cp-1);
+ }
+ return(eq?0:ep);
+}
+
+int nv_rename(register Namval_t *np, int flags)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namval_t *mp=0,*nr=0;
+ register char *cp;
+ int r=0,arraynp=0,arraynr,index= -1;
+ Namval_t *last_table = shp->last_table;
+ Dt_t *last_root = shp->last_root;
+ Dt_t *hp = 0;
+ char *nvenv=0,*prefix=shp->prefix;
+ Namarr_t *ap,*aq=0;
+ if(nv_isattr(np,NV_PARAM) && shp->st.prevst)
+ {
+ if(!(hp=(Dt_t*)shp->st.prevst->save_tree))
+ hp = dtvnext(shp->var_tree);
+ }
+ if(!nv_isattr(np,NV_MINIMAL))
+ nvenv = np->nvenv;
+ if(nvenv || (cp = nv_name(np)) && nv_isarray(np) && cp[strlen(cp)-1] == ']')
+ arraynp = 1;
+ if(!(cp=nv_getval(np)))
+ {
+ if(flags&NV_MOVE)
+ errormsg(SH_DICT,ERROR_exit(1),e_varname,"");
+ return(0);
+ }
+ if(lastdot(cp,0) && nv_isattr(np,NV_MINIMAL))
+ errormsg(SH_DICT,ERROR_exit(1),e_varname,nv_name(np));
+ arraynr = cp[strlen(cp)-1] == ']';
+ if(nv_isarray(np) && !(mp=nv_opensub(np)))
+ index=nv_aindex(np);
+ shp->prefix = 0;
+ if(!hp)
+ hp = shp->var_tree;
+ if(!(nr = nv_open(cp, hp, flags|NV_ARRAY|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)))
+ {
+#if SHOPT_NAMESPACE
+ if(shp->namespace)
+ hp = nv_dict(shp->namespace);
+ else
+#endif /* SHOPT_NAMESPACE */
+ hp = shp->var_base;
+ }
+ else if(shp->last_root)
+ hp = shp->last_root;
+ if(!nr)
+ nr= nv_open(cp, hp, flags|NV_NOREF|((flags&NV_MOVE)?0:NV_NOFAIL));
+ shp->prefix = prefix;
+ if(!nr)
+ {
+ if(!nv_isvtree(np))
+ _nv_unset(np,0);
+ return(0);
+ }
+ if(!mp && index>=0 && nv_isvtree(nr))
+ {
+ sfprintf(shp->strbuf,"%s[%d]%c",nv_name(np),index,0);
+ /* create a virtual node */
+ if(mp = nv_open(sfstruse(shp->strbuf),shp->var_tree,NV_VARNAME|NV_ADD|NV_ARRAY))
+ {
+ if(ap = nv_arrayptr(np))
+ ap->nelem++;
+ mp->nvenv = nvenv = (void*)np;
+ }
+ }
+ if(mp)
+ {
+ nvenv = (char*)np;
+ np = mp;
+ }
+ if(nr==np)
+ {
+ if(index<0)
+ return(0);
+ if(cp = nv_getval(np))
+ cp = strdup(cp);
+ }
+ _nv_unset(np,NV_EXPORT);
+ if(nr==np)
+ {
+ nv_putsub(np,(char*)0, index);
+ nv_putval(np,cp,0);
+ free((void*)cp);
+ return(1);
+ }
+ shp->prev_table = shp->last_table;
+ shp->prev_root = shp->last_root;
+ shp->last_table = last_table;
+ shp->last_root = last_root;
+ if(flags&NV_MOVE)
+ {
+ if(arraynp && !nv_isattr(np,NV_MINIMAL) && (mp=(Namval_t*)np->nvenv) && (ap=nv_arrayptr(mp)))
+ ap->nelem++;
+ }
+ if(((aq=nv_arrayptr(nr)) && !arraynr) || nv_isvtree(nr))
+ {
+ if(ap=nv_arrayptr(np))
+ {
+ if(!ap->table)
+ ap->table = dtopen(&_Nvdisc,Dtoset);
+ if(ap->table)
+ mp = nv_search(nv_getsub(np),ap->table,NV_ADD);
+ nv_arraychild(np,mp,0);
+ nvenv = (void*)np;
+ }
+ else
+ mp = np;
+ nv_clone(nr,mp,(flags&NV_MOVE)|NV_COMVAR);
+ mp->nvenv = nvenv;
+ if(flags&NV_MOVE)
+ {
+ if(arraynr && !nv_isattr(nr,NV_MINIMAL) && (mp=(Namval_t*)nr->nvenv) && (ap=nv_arrayptr(mp)))
+ {
+ nv_putsub(mp,nr->nvname,0);
+ _nv_unset(mp,0);
+ }
+ nv_delete(nr,(Dt_t*)0,NV_NOFREE);
+ }
+ }
+ else
+ {
+ nv_putval(np,nv_getval(nr),0);
+ if(flags&NV_MOVE)
+ _nv_unset(nr,0);
+ }
+ return(1);
+}
+
+/*
+ * Create a reference node from <np> to $np in dictionary <hp>
+ */
+void nv_setref(register Namval_t *np, Dt_t *hp, int flags)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namval_t *nq=0, *nr=0;
+ register char *ep,*cp;
+ Dt_t *root = shp->last_root, *hpnext=0;
+ Namarr_t *ap=0;
+ int openmatch;
+ if(nv_isref(np))
+ return;
+ if(nv_isarray(np))
+ errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np));
+ if(!(cp=nv_getval(np)))
+ {
+ _nv_unset(np,0);
+ nv_onattr(np,NV_REF);
+ return;
+ }
+ if((ep = lastdot(cp,0)) && nv_isattr(np,NV_MINIMAL))
+ errormsg(SH_DICT,ERROR_exit(1),e_badref,nv_name(np));
+ if(hp)
+ hpnext = dtvnext(hp);
+ if((nr=nv_open(cp, hp?hp:shp->var_tree, flags|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)))
+ nq = nr;
+ else if(hpnext && dtvnext(hpnext)==shp->var_base && (nr=nv_open(cp,hpnext,flags|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)))
+ nq = nr;
+ else if((openmatch=shp->openmatch) && hpnext==shp->var_base && (nr=nv_open(cp,hpnext,flags|NV_NOSCOPE|NV_NOADD|NV_NOFAIL)))
+ nq = nr;
+ if(nq)
+ hp = shp->last_root;
+ else
+ hp = hp?(openmatch?hp:shp->var_base):shp->var_tree;
+ if(nr==np)
+ {
+ if(shp->namespace && nv_dict(shp->namespace)==hp)
+ errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np));
+ /* bind to earlier scope, or add to global scope */
+ if(!(hp=dtvnext(hp)) || (nq=nv_search((char*)np,hp,NV_ADD|HASH_BUCKET))==np)
+ errormsg(SH_DICT,ERROR_exit(1),e_selfref,nv_name(np));
+ if(nv_isarray(nq))
+ nv_putsub(nq,(char*)0,ARRAY_UNDEF);
+ }
+#if SHOPT_FIXEDARRAY
+ if(nq && ep && nv_isarray(nq) && !((ap=nv_arrayptr(nq)) && ap->fixed) && !nv_getsub(nq))
+#else
+ if(nq && ep && nv_isarray(nq) && !nv_getsub(nq))
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ if(!nv_arrayptr(nq))
+ {
+ nv_putsub(nq,"1",ARRAY_FILL);
+ _nv_unset(nq,NV_RDONLY);
+ }
+ nv_endsubscript(nq,ep-1,NV_ARRAY);
+ }
+ if(!nr)
+ {
+ shp->last_root = 0;
+ nr= nq = nv_open(cp, hp, flags);
+ if(shp->last_root)
+ hp = shp->last_root;
+ }
+ if(shp->last_root == shp->var_tree && root!=shp->var_tree)
+ {
+ _nv_unset(np,NV_RDONLY);
+ nv_onattr(np,NV_REF);
+ errormsg(SH_DICT,ERROR_exit(1),e_globalref,nv_name(np));
+ }
+ shp->instance = 1;
+ if(nq && !ep && (ap=nv_arrayptr(nq)) && !(ap->nelem&(ARRAY_UNDEF|ARRAY_SCAN)))
+ ep = nv_getsub(nq);
+#if SHOPT_FIXEDARRAY
+ if(ep && !(ap && ap->fixed))
+#else
+ if(ep)
+#endif /* SHOPT_FIXEDARRAY */
+ {
+ /* cause subscript evaluation and return result */
+ if(nv_isarray(nq))
+ ep = nv_getsub(nq);
+ else
+ {
+ int n;
+ ep[n=strlen(ep)-1] = 0;
+ nv_putsub(nr, ep, ARRAY_FILL);
+ ep[n] = ']';
+ if(nq = nv_opensub(nr))
+ ep = 0;
+ else
+ ep = nv_getsub(nq=nr);
+ }
+ }
+ shp->instance = 0;
+ shp->last_root = root;
+ _nv_unset(np,0);
+ nv_delete(np,(Dt_t*)0,0);
+ np->nvalue.nrp = newof(0,struct Namref,1,sizeof(Dtlink_t));
+ np->nvalue.nrp->np = nq;
+ np->nvalue.nrp->root = hp;
+ if(ep)
+ {
+#if SHOPT_FIXEDARRAY
+ if(ap && ap->fixed)
+ np->nvalue.nrp->curi = ARRAY_FIXED|nv_arrfixed(nq,(Sfio_t*)0,1,&np->nvalue.nrp->dim);
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ np->nvalue.nrp->sub = strdup(ep);
+ }
+ np->nvalue.nrp->table = shp->last_table;
+ nv_onattr(np,NV_REF|NV_NOFREE);
+ if(!Refdict)
+ {
+ NullNode.nvname = ".deleted";
+ NullNode.nvflag = NV_RDONLY;
+ Refdict = dtopen(&_Refdisc,Dtobag);
+ }
+ dtinsert(Refdict,np->nvalue.nrp);
+}
+
+/*
+ * get the scope corresponding to <index>
+ * whence uses the same values as lseeek()
+ */
+Shscope_t *sh_getscope(int index, int whence)
+{
+ Shell_t *shp = sh_getinterp();
+ register struct sh_scoped *sp, *topmost;
+ if(whence==SEEK_CUR)
+ sp = &shp->st;
+ else
+ {
+ if ((struct sh_scoped*)shp->topscope != shp->st.self)
+ topmost = (struct sh_scoped*)shp->topscope;
+ else
+ topmost = &(shp->st);
+ sp = topmost;
+ if(whence==SEEK_SET)
+ {
+ int n =0;
+ while(sp = sp->prevst)
+ n++;
+ index = n - index;
+ sp = topmost;
+ }
+ }
+ if(index < 0)
+ return((Shscope_t*)0);
+ while(index-- && (sp = sp->prevst));
+ return((Shscope_t*)sp);
+}
+
+/*
+ * make <scoped> the top scope and return previous scope
+ */
+Shscope_t *sh_setscope(Shscope_t *scope)
+{
+ Shell_t *shp = sh_getinterp();
+ Shscope_t *old = (Shscope_t*)shp->st.self;
+ *shp->st.self = shp->st;
+ shp->st = *((struct sh_scoped*)scope);
+ shp->var_tree = scope->var_tree;
+ SH_PATHNAMENOD->nvalue.cp = shp->st.filename;
+ SH_FUNNAMENOD->nvalue.cp = shp->st.funname;
+ return(old);
+}
+
+void sh_unscope(Shell_t *shp)
+{
+ register Dt_t *root = shp->var_tree;
+ register Dt_t *dp = dtview(root,(Dt_t*)0);
+ table_unset(shp,root,NV_RDONLY|NV_NOSCOPE,dp);
+ if(shp->st.real_fun && dp==shp->st.real_fun->sdict)
+ {
+ dp = dtview(dp,(Dt_t*)0);
+ shp->st.real_fun->sdict->view = dp;
+ }
+ shp->var_tree=dp;
+ dtclose(root);
+}
+
+/*
+ * The inverse of creating a reference node
+ */
+void nv_unref(register Namval_t *np)
+{
+ Namval_t *nq;
+ if(!nv_isref(np))
+ return;
+ nv_offattr(np,NV_NOFREE|NV_REF);
+ if(!np->nvalue.nrp)
+ return;
+ nq = nv_refnode(np);
+ if(Refdict)
+ {
+ if(np->nvalue.nrp->sub)
+ free(np->nvalue.nrp->sub);
+ dtdelete(Refdict,(void*)np->nvalue.nrp);
+ }
+ free((void*)np->nvalue.nrp);
+ np->nvalue.cp = strdup(nv_name(nq));
+#if SHOPT_OPTIMIZE
+ {
+ Namfun_t *fp;
+ for(fp=nq->nvfun; fp; fp = fp->next)
+ {
+ if(fp->disc== &optimize_disc)
+ {
+ optimize_clear(nq,fp);
+ return;
+ }
+ }
+ }
+#endif
+}
+
+/*
+ * These following are for binary compatibility with the old hash library
+ * They will be removed someday
+ */
+
+#if defined(__IMPORT__) && defined(__EXPORT__)
+# define extern __EXPORT__
+#endif
+
+#undef hashscope
+
+extern Dt_t *hashscope(Dt_t *root)
+{
+ return(dtvnext(root));
+}
+
+#undef hashfree
+
+extern Dt_t *hashfree(Dt_t *root)
+{
+ Dt_t *dp = dtvnext(root);
+ dtclose(root);
+ return(dp);
+}
+
+#undef hashname
+
+extern char *hashname(void *obj)
+{
+ Namval_t *np = (Namval_t*)obj;
+ return(np->nvname);
+}
+
+#undef hashlook
+
+extern void *hashlook(Dt_t *root, const char *name, int mode,int size)
+{
+ NOT_USED(size);
+ return((void*)nv_search(name,root,mode));
+}
+
+char *nv_name(register Namval_t *np)
+{
+ Shell_t *shp = sh_getinterp();
+ register Namval_t *table;
+ register Namfun_t *fp;
+#if SHOPT_FIXEDARRAY
+ Namarr_t *ap;
+#endif /* SHOPT_FIXEDARRAY */
+ char *cp;
+ if(is_abuiltin(np) || is_afunction(np))
+ {
+#if SHOPT_NAMESPACE
+ if(shp->namespace && is_afunction(np))
+ {
+ char *name = nv_name(shp->namespace);
+ int n = strlen(name);
+ if(memcmp(np->nvname,name,n)==0 && np->nvname[n]=='.')
+ return(np->nvname+n+1);
+ }
+#endif /* SHOPT_NAMESPACE */
+ return(np->nvname);
+ }
+#if SHOPT_FIXEDARRAY
+ ap = nv_arrayptr(np);
+#endif /* SHOPT_FIXEDARRAY */
+ if(!nv_isattr(np,NV_MINIMAL|NV_EXPORT) && np->nvenv)
+ {
+ Namval_t *nq= shp->last_table, *mp= (Namval_t*)np->nvenv;
+ if(np==shp->last_table)
+ shp->last_table = 0;
+ if(nv_isarray(mp))
+ sfprintf(shp->strbuf,"%s[%s]",nv_name(mp),np->nvname);
+ else
+ sfprintf(shp->strbuf,"%s.%s",nv_name(mp),np->nvname);
+ shp->last_table = nq;
+ return(sfstruse(shp->strbuf));
+ }
+ if(nv_istable(np))
+#if 1
+ shp->last_table = nv_parent(np);
+#else
+ shp->last_table = nv_create(np,0, NV_LAST,(Namfun_t*)0);
+#endif
+ else if(!nv_isref(np))
+ {
+ for(fp= np->nvfun ; fp; fp=fp->next)
+ if(fp->disc && fp->disc->namef)
+ {
+ if(np==shp->last_table)
+ shp->last_table = 0;
+ return((*fp->disc->namef)(np,fp));
+ }
+ }
+ if(!(table=shp->last_table) || *np->nvname=='.' || table==shp->namespace || np==table)
+ {
+#if SHOPT_FIXEDARRAY
+ if(!ap || !ap->fixed || (ap->nelem&ARRAY_UNDEF))
+ return(np->nvname);
+ table = 0;
+#else
+ return(np->nvname);
+#endif /* SHOPT_FIXEDARRAY */
+ }
+ if(table)
+ {
+ cp = nv_name(table);
+ sfprintf(shp->strbuf,"%s.%s",cp,np->nvname);
+ }
+ else
+ sfprintf(shp->strbuf,"%s",np->nvname);
+#if SHOPT_FIXEDARRAY
+ if(ap && ap->fixed)
+ nv_arrfixed(np,shp->strbuf,1,(char*)0);
+#endif /* SHOPT_FIXEDARRAY */
+ return(sfstruse(shp->strbuf));
+}
+
+Namval_t *nv_lastdict(void)
+{
+ Shell_t *shp = sh_getinterp();
+ return(shp->last_table);
+}
+
+#undef nv_context
+/*
+ * returns the data context for a builtin
+ */
+void *nv_context(Namval_t *np)
+{
+ return((void*)np->nvfun);
+}
+
+#define DISABLE /* proto workaround */
+
+int nv_isnull DISABLE (register Namval_t *np)
+{
+ return(nv_isnull(np));
+}
+
+#undef nv_setsize
+int nv_setsize(register Namval_t *np, int size)
+{
+ int oldsize = nv_size(np);
+ if(size>=0)
+ np->nvsize = size;
+ return(oldsize);
+}
+
+Shell_t *nv_shell(Namval_t *np)
+{
+ Namfun_t *fp;
+ for(fp=np->nvfun;fp;fp=fp->next)
+ {
+ if(!fp->disc)
+ return((Shell_t*)fp->last);
+ }
+ return(0);
+}
+
+#undef nv_unset
+
+void nv_unset(register Namval_t *np)
+{
+ _nv_unset(np,0);
+ return;
+}
diff --git a/src/cmd/ksh93/sh/nvdisc.c b/src/cmd/ksh93/sh/nvdisc.c
new file mode 100644
index 0000000..45a7edb
--- /dev/null
+++ b/src/cmd/ksh93/sh/nvdisc.c
@@ -0,0 +1,1468 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include "variables.h"
+#include "builtins.h"
+#include "path.h"
+
+static void assign(Namval_t*,const char*,int,Namfun_t*);
+
+int nv_compare(Dt_t* dict, Void_t *sp, Void_t *dp, Dtdisc_t *disc)
+{
+ if(sp==dp)
+ return(0);
+ return(strcmp((char*)sp,(char*)dp));
+}
+
+/*
+ * call the next getval function in the chain
+ */
+char *nv_getv(Namval_t *np, register Namfun_t *nfp)
+{
+ register Namfun_t *fp;
+ register char *cp;
+ if((fp = nfp) != NIL(Namfun_t*) && !nv_local)
+ fp = nfp = nfp->next;
+ nv_local=0;
+ for(; fp; fp=fp->next)
+ {
+ if(!fp->disc || (!fp->disc->getnum && !fp->disc->getval))
+ continue;
+ if(!nv_isattr(np,NV_NODISC) || fp==(Namfun_t*)nv_arrayptr(np))
+ break;
+ }
+ if(fp && fp->disc->getval)
+ cp = (*fp->disc->getval)(np,fp);
+ else if(fp && fp->disc->getnum)
+ {
+ sfprintf(sh.strbuf,"%.*Lg",12,(*fp->disc->getnum)(np,fp));
+ cp = sfstruse(sh.strbuf);
+ }
+ else
+ {
+ nv_local=1;
+ cp = nv_getval(np);
+ }
+ return(cp);
+}
+
+/*
+ * call the next getnum function in the chain
+ */
+Sfdouble_t nv_getn(Namval_t *np, register Namfun_t *nfp)
+{
+ register Namfun_t *fp;
+ register Sfdouble_t d=0;
+ Shell_t *shp = sh_getinterp();
+ char *str;
+ if((fp = nfp) != NIL(Namfun_t*) && !nv_local)
+ fp = nfp = nfp->next;
+ nv_local=0;
+ for(; fp; fp=fp->next)
+ {
+ if(!fp->disc || (!fp->disc->getnum && !fp->disc->getval))
+ continue;
+ if(!fp->disc->getnum && nv_isattr(np,NV_INTEGER))
+ continue;
+ if(!nv_isattr(np,NV_NODISC) || fp==(Namfun_t*)nv_arrayptr(np))
+ break;
+ }
+ if(fp && fp->disc && fp->disc->getnum)
+ d = (*fp->disc->getnum)(np,fp);
+ else if(nv_isattr(np,NV_INTEGER))
+ {
+ nv_local = 1;
+ d = nv_getnum(np);
+ }
+ else
+ {
+ if(fp && fp->disc && fp->disc->getval)
+ str = (*fp->disc->getval)(np,fp);
+ else
+ str = nv_getv(np,fp?fp:nfp);
+ if(str && *str)
+ {
+ if(nv_isattr(np,NV_LJUST|NV_RJUST) || (*str=='0' && !(str[1]=='x'||str[1]=='X')))
+ {
+ while(*str=='0')
+ str++;
+ }
+ d = sh_arith(shp,str);
+ }
+ }
+ return(d);
+}
+
+/*
+ * call the next assign function in the chain
+ */
+void nv_putv(Namval_t *np, const char *value, int flags, register Namfun_t *nfp)
+{
+ register Namfun_t *fp, *fpnext;
+ Namarr_t *ap;
+ if((fp=nfp) != NIL(Namfun_t*) && !nv_local)
+ fp = nfp = nfp->next;
+ nv_local=0;
+ if(flags&NV_NODISC)
+ fp = 0;
+ for(; fp; fp=fpnext)
+ {
+ fpnext = fp->next;
+ if(!fp->disc || !fp->disc->putval)
+ {
+ if(!value && (!(ap=nv_arrayptr(np)) || ap->nelem==0))
+ {
+ if(fp->disc || !(fp->nofree&1))
+ nv_disc(np,fp,NV_POP);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ }
+ continue;
+ }
+ if(!nv_isattr(np,NV_NODISC) || fp==(Namfun_t*)nv_arrayptr(np))
+ break;
+ }
+ if(!value && (flags&NV_TYPE) && fp && fp->disc->putval==assign)
+ fp = 0;
+ if(fp && fp->disc->putval)
+ (*fp->disc->putval)(np,value, flags, fp);
+ else
+ {
+ nv_local=1;
+ if(value)
+ nv_putval(np, value, flags);
+ else
+ _nv_unset(np, flags&(NV_RDONLY|NV_EXPORT));
+ }
+}
+
+#define LOOKUPS 0
+#define ASSIGN 1
+#define APPEND 2
+#define UNASSIGN 3
+#define LOOKUPN 4
+#define BLOCKED ((Namval_t*)&nv_local)
+
+struct vardisc
+{
+ Namfun_t fun;
+ Namval_t *disc[5];
+};
+
+struct blocked
+{
+ struct blocked *next;
+ Namval_t *np;
+ int flags;
+ void *sub;
+ int isub;
+};
+
+static struct blocked *blist;
+
+#define isblocked(bp,type) ((bp)->flags & (1<<(type)))
+#define block(bp,type) ((bp)->flags |= (1<<(type)))
+#define unblock(bp,type) ((bp)->flags &= ~(1<<(type)))
+
+/*
+ * returns pointer to blocking structure
+ */
+static struct blocked *block_info(Namval_t *np, struct blocked *pp)
+{
+ register struct blocked *bp;
+ void *sub=0;
+ int isub=0;
+ if(nv_isarray(np) && (isub=nv_aindex(np)) < 0)
+ sub = nv_associative(np,(const char*)0,NV_ACURRENT);
+ for(bp=blist ; bp; bp=bp->next)
+ {
+ if(bp->np==np && bp->sub==sub && bp->isub==isub)
+ return(bp);
+ }
+ if(pp)
+ {
+ pp->np = np;
+ pp->flags = 0;
+ pp->isub = isub;
+ pp->sub = sub;
+ pp->next = blist;
+ blist = pp;
+ }
+ return(pp);
+}
+
+static void block_done(struct blocked *bp)
+{
+ blist = bp = bp->next;
+ if(bp && (bp->isub>=0 || bp->sub))
+ nv_putsub(bp->np, bp->sub,(bp->isub<0?0:bp->isub)|ARRAY_SETSUB);
+}
+
+/*
+ * free discipline if no more discipline functions
+ */
+static void chktfree(register Namval_t *np, register struct vardisc *vp)
+{
+ register int n;
+ for(n=0; n< sizeof(vp->disc)/sizeof(*vp->disc); n++)
+ {
+ if(vp->disc[n])
+ break;
+ }
+ if(n>=sizeof(vp->disc)/sizeof(*vp->disc))
+ {
+ /* no disc left so pop */
+ Namfun_t *fp;
+ if((fp=nv_stack(np, NIL(Namfun_t*))) && !(fp->nofree&1))
+ free((void*)fp);
+ }
+}
+
+/*
+ * This function performs an assignment disc on the given node <np>
+ */
+static void assign(Namval_t *np,const char* val,int flags,Namfun_t *handle)
+{
+ int type = (flags&NV_APPEND)?APPEND:ASSIGN;
+ register struct vardisc *vp = (struct vardisc*)handle;
+ register Namval_t *nq = vp->disc[type];
+ struct blocked block, *bp = block_info(np, &block);
+ Namval_t node;
+ union Value *up = np->nvalue.up;
+#if SHOPT_TYPEDEF
+ Namval_t *tp, *nr;
+ if(val && (tp=nv_type(np)) && (nr=nv_open(val,sh.var_tree,NV_VARNAME|NV_ARRAY|NV_NOADD|NV_NOFAIL)) && tp==nv_type(nr))
+ {
+ char *sub = nv_getsub(np);
+ _nv_unset(np,0);
+ if(sub)
+ {
+ nv_putsub(np, sub, ARRAY_ADD);
+ nv_putval(np,nv_getval(nr), 0);
+ }
+ else
+ nv_clone(nr,np,0);
+ goto done;
+ }
+#endif /* SHOPT_TYPEDEF */
+ if(val || isblocked(bp,type))
+ {
+ if(!nq || isblocked(bp,type))
+ {
+ nv_putv(np,val,flags,handle);
+ goto done;
+ }
+ node = *SH_VALNOD;
+ if(!nv_isnull(SH_VALNOD))
+ {
+ nv_onattr(SH_VALNOD,NV_NOFREE);
+ _nv_unset(SH_VALNOD,0);
+ }
+ if(flags&NV_INTEGER)
+ nv_onattr(SH_VALNOD,(flags&(NV_LONG|NV_DOUBLE|NV_EXPNOTE|NV_HEXFLOAT|NV_SHORT)));
+ nv_putval(SH_VALNOD, val, (flags&NV_INTEGER)?flags:NV_NOFREE);
+ }
+ else
+ nq = vp->disc[type=UNASSIGN];
+ if(nq && !isblocked(bp,type))
+ {
+ int bflag=0;
+ block(bp,type);
+ if (type==APPEND && (bflag= !isblocked(bp,LOOKUPS)))
+ block(bp,LOOKUPS);
+ sh_fun(nq,np,(char**)0);
+ unblock(bp,type);
+ if(bflag)
+ unblock(bp,LOOKUPS);
+ if(!vp->disc[type])
+ chktfree(np,vp);
+ }
+ if(nv_isarray(np))
+ np->nvalue.up = up;
+ if(val)
+ {
+ register char *cp;
+ Sfdouble_t d;
+ if(nv_isnull(SH_VALNOD))
+ cp=0;
+ else if(flags&NV_INTEGER)
+ {
+ d = nv_getnum(SH_VALNOD);
+ cp = (char*)(&d);
+ flags |= (NV_LONG|NV_DOUBLE);
+ flags &= ~NV_SHORT;
+ }
+ else
+ cp = nv_getval(SH_VALNOD);
+ if(cp)
+ nv_putv(np,cp,flags|NV_RDONLY,handle);
+ _nv_unset(SH_VALNOD,0);
+ /* restore everything but the nvlink field */
+ memcpy(&SH_VALNOD->nvname, &node.nvname, sizeof(node)-sizeof(node.nvlink));
+ }
+ else if(sh_isstate(SH_INIT) || np==SH_FUNNAMENOD)
+ {
+ /* don't free functions during reinitialization */
+ nv_putv(np,val,flags,handle);
+ }
+ else if(!nq || !isblocked(bp,type))
+ {
+ Dt_t *root = sh_subfuntree(1);
+ int n;
+ Namarr_t *ap;
+ block(bp,type);
+ nv_disc(np,handle,NV_POP);
+ nv_putv(np, val, flags, handle);
+ if(sh.subshell)
+ goto done;
+ if(nv_isarray(np) && (ap=nv_arrayptr(np)) && ap->nelem>0)
+ goto done;
+ for(n=0; n < sizeof(vp->disc)/sizeof(*vp->disc); n++)
+ {
+ if((nq=vp->disc[n]) && !nv_isattr(nq,NV_NOFREE))
+ {
+ _nv_unset(nq,0);
+ dtdelete(root,nq);
+ }
+ }
+ unblock(bp,type);
+ if(!(handle->nofree&1))
+ free(handle);
+ }
+done:
+ if(bp== &block)
+ block_done(bp);
+}
+
+/*
+ * This function executes a lookup disc and then performs
+ * the lookup on the given node <np>
+ */
+static char* lookup(Namval_t *np, int type, Sfdouble_t *dp,Namfun_t *handle)
+{
+ register struct vardisc *vp = (struct vardisc*)handle;
+ struct blocked block, *bp = block_info(np, &block);
+ register Namval_t *nq = vp->disc[type];
+ register char *cp=0;
+ Namval_t node;
+ union Value *up = np->nvalue.up;
+ if(nq && !isblocked(bp,type))
+ {
+ node = *SH_VALNOD;
+ if(!nv_isnull(SH_VALNOD))
+ {
+ nv_onattr(SH_VALNOD,NV_NOFREE);
+ _nv_unset(SH_VALNOD,0);
+ }
+ if(type==LOOKUPN)
+ {
+ nv_onattr(SH_VALNOD,NV_DOUBLE|NV_INTEGER);
+ nv_setsize(SH_VALNOD,10);
+ }
+ block(bp,type);
+ sh_fun(nq,np,(char**)0);
+ unblock(bp,type);
+ if(!vp->disc[type])
+ chktfree(np,vp);
+ if(type==LOOKUPN)
+ {
+ cp = (char*)(SH_VALNOD->nvalue.cp);
+ *dp = nv_getnum(SH_VALNOD);
+ }
+ else if(cp = nv_getval(SH_VALNOD))
+ cp = stkcopy(stkstd,cp);
+ _nv_unset(SH_VALNOD,NV_RDONLY);
+ if(!nv_isnull(&node))
+ {
+ /* restore everything but the nvlink field */
+ memcpy(&SH_VALNOD->nvname, &node.nvname, sizeof(node)-sizeof(node.nvlink));
+ }
+ }
+ if(nv_isarray(np))
+ np->nvalue.up = up;
+ if(!cp)
+ {
+ if(type==LOOKUPS)
+ cp = nv_getv(np,handle);
+ else
+ *dp = nv_getn(np,handle);
+ }
+ if(bp== &block)
+ block_done(bp);
+ return(cp);
+}
+
+static char* lookups(Namval_t *np, Namfun_t *handle)
+{
+ return(lookup(np,LOOKUPS,(Sfdouble_t*)0,handle));
+}
+
+static Sfdouble_t lookupn(Namval_t *np, Namfun_t *handle)
+{
+ Sfdouble_t d;
+ lookup(np,LOOKUPN, &d ,handle);
+ return(d);
+}
+
+
+/*
+ * Set disc on given <event> to <action>
+ * If action==np, the current disc is returned
+ * A null return value indicates that no <event> is known for <np>
+ * If <event> is NULL, then return the event name after <action>
+ * If <event> is NULL, and <action> is NULL, return the first event
+ */
+char *nv_setdisc(register Namval_t* np,register const char *event,Namval_t *action,register Namfun_t *fp)
+{
+ register struct vardisc *vp = (struct vardisc*)np->nvfun;
+ register int type;
+ char *empty = "";
+ while(vp)
+ {
+ if(vp->fun.disc && (vp->fun.disc->setdisc || vp->fun.disc->putval == assign))
+ break;
+ vp = (struct vardisc*)vp->fun.next;
+ }
+ if(vp && !vp->fun.disc)
+ vp = 0;
+ if(np == (Namval_t*)fp)
+ {
+ register const char *name;
+ register int getname=0;
+ /* top level call, check for get/set */
+ if(!event)
+ {
+ if(!action)
+ return((char*)nv_discnames[0]);
+ getname=1;
+ event = (char*)action;
+ }
+ for(type=0; name=nv_discnames[type]; type++)
+ {
+ if(strcmp(event,name)==0)
+ break;
+ }
+ if(getname)
+ {
+ event = 0;
+ if(name && !(name = nv_discnames[++type]))
+ action = 0;
+ }
+ if(!name)
+ {
+ for(fp=(Namfun_t*)vp; fp; fp=fp->next)
+ {
+ if(fp->disc && fp->disc->setdisc)
+ return((*fp->disc->setdisc)(np,event,action,fp));
+ }
+ }
+ else if(getname)
+ return((char*)name);
+ }
+ if(!fp)
+ return(NIL(char*));
+ if(np != (Namval_t*)fp)
+ {
+ /* not the top level */
+ while(fp = fp->next)
+ {
+ if(fp->disc && fp->disc->setdisc)
+ return((*fp->disc->setdisc)(np,event,action,fp));
+ }
+ return(NIL(char*));
+ }
+ /* Handle GET/SET/APPEND/UNSET disc */
+ if(vp && vp->fun.disc->putval!=assign)
+ vp = 0;
+ if(!vp)
+ {
+ Namdisc_t *dp;
+ if(action==np)
+ return((char*)action);
+ if(!(vp = newof(NIL(struct vardisc*),struct vardisc,1,sizeof(Namdisc_t))))
+ return(0);
+ dp = (Namdisc_t*)(vp+1);
+ vp->fun.disc = dp;
+ memset(dp,0,sizeof(*dp));
+ dp->dsize = sizeof(struct vardisc);
+ dp->putval = assign;
+ if(nv_isarray(np) && !nv_arrayptr(np))
+ nv_putsub(np,(char*)0, 1);
+ nv_stack(np, (Namfun_t*)vp);
+ }
+ if(action==np)
+ {
+ action = vp->disc[type];
+ empty = 0;
+ }
+ else if(action)
+ {
+ Namdisc_t *dp = (Namdisc_t*)vp->fun.disc;
+ if(type==LOOKUPS)
+ dp->getval = lookups;
+ else if(type==LOOKUPN)
+ dp->getnum = lookupn;
+ vp->disc[type] = action;
+ }
+ else
+ {
+ struct blocked *bp;
+ action = vp->disc[type];
+ vp->disc[type] = 0;
+ if(!(bp=block_info(np,(struct blocked*)0)) || !isblocked(bp,UNASSIGN))
+ chktfree(np,vp);
+ }
+ return(action?(char*)action:empty);
+}
+
+/*
+ * Set disc on given <event> to <action>
+ * If action==np, the current disc is returned
+ * A null return value indicates that no <event> is known for <np>
+ * If <event> is NULL, then return the event name after <action>
+ * If <event> is NULL, and <action> is NULL, return the first event
+ */
+static char *setdisc(register Namval_t* np,register const char *event,Namval_t *action,register Namfun_t *fp)
+{
+ register Nambfun_t *vp = (Nambfun_t*)fp;
+ register int type,getname=0;
+ register const char *name;
+ const char **discnames = vp->bnames;
+ /* top level call, check for discipline match */
+ if(!event)
+ {
+ if(!action)
+ return((char*)discnames[0]);
+ getname=1;
+ event = (char*)action;
+ }
+ for(type=0; name=discnames[type]; type++)
+ {
+ if(strcmp(event,name)==0)
+ break;
+ }
+ if(getname)
+ {
+ event = 0;
+ if(name && !(name = discnames[++type]))
+ action = 0;
+ }
+ if(!name)
+ return(nv_setdisc(np,event,action,fp));
+ else if(getname)
+ return((char*)name);
+ /* Handle the disciplines */
+ if(action==np)
+ action = vp->bltins[type];
+ else if(action)
+ {
+ Namval_t *tp = nv_type(np);
+ if(tp && (np = (Namval_t*)vp->bltins[type]) && nv_isattr(np,NV_STATICF))
+ errormsg(SH_DICT,ERROR_exit(1),e_staticfun,name,tp->nvname);
+ vp->bltins[type] = action;
+ }
+ else
+ {
+ action = vp->bltins[type];
+ vp->bltins[type] = 0;
+ }
+ return(action?(char*)action:"");
+}
+
+static void putdisc(Namval_t* np, const char* val, int flag, Namfun_t* fp)
+{
+ nv_putv(np,val,flag,fp);
+ if(!val && !(flag&NV_NOFREE))
+ {
+ register Nambfun_t *vp = (Nambfun_t*)fp;
+ register int i;
+ for(i=0; vp->bnames[i]; i++)
+ {
+ register Namval_t *mp;
+ if((mp=vp->bltins[i]) && !nv_isattr(mp,NV_NOFREE))
+ {
+ if(is_abuiltin(mp))
+ {
+ if(mp->nvfun && !nv_isattr(mp,NV_NOFREE))
+ free((void*)mp->nvfun);
+ dtdelete(sh.bltin_tree,mp);
+ free((void*)mp);
+ }
+ }
+ }
+ nv_disc(np,fp,NV_POP);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+
+ }
+}
+
+static const Namdisc_t Nv_bdisc = { 0, putdisc, 0, 0, setdisc };
+
+Namfun_t *nv_clone_disc(register Namfun_t *fp, int flags)
+{
+ register Namfun_t *nfp;
+ register int size;
+ if(!fp->disc && !fp->next && (fp->nofree&1))
+ return(fp);
+ if(!(size=fp->dsize) && (!fp->disc || !(size=fp->disc->dsize)))
+ size = sizeof(Namfun_t);
+ if(!(nfp=newof(NIL(Namfun_t*),Namfun_t,1,size-sizeof(Namfun_t))))
+ return(0);
+ memcpy(nfp,fp,size);
+ nfp->nofree &= ~1;
+ nfp->nofree |= (flags&NV_RDONLY)?1:0;
+ return(nfp);
+}
+
+int nv_adddisc(Namval_t *np, const char **names, Namval_t **funs)
+{
+ register Nambfun_t *vp;
+ register int n=0;
+ register const char **av=names;
+ if(av)
+ {
+ while(*av++)
+ n++;
+ }
+ if(!(vp = newof(NIL(Nambfun_t*),Nambfun_t,1,n*sizeof(Namval_t*))))
+ return(0);
+ vp->fun.dsize = sizeof(Nambfun_t)+n*sizeof(Namval_t*);
+ vp->fun.nofree |= 2;
+ vp->num = n;
+ if(funs)
+ memcpy((void*)vp->bltins, (void*)funs,n*sizeof(Namval_t*));
+ else while(n>=0)
+ vp->bltins[n--] = 0;
+ vp->fun.disc = &Nv_bdisc;
+ vp->bnames = names;
+ nv_stack(np,&vp->fun);
+ return(1);
+}
+
+/*
+ * push, pop, clne, or reorder disciplines onto node <np>
+ * mode can be one of
+ * NV_FIRST: Move or push <fp> to top of the stack or delete top
+ * NV_LAST: Move or push <fp> to bottom of stack or delete last
+ * NV_POP: Delete <fp> from top of the stack
+ * NV_CLONE: Replace fp with a copy created my malloc() and return it
+ */
+Namfun_t *nv_disc(register Namval_t *np, register Namfun_t* fp, int mode)
+{
+ Namfun_t *lp, **lpp;
+ if(nv_isref(np))
+ return(0);
+ if(mode==NV_CLONE && !fp)
+ return(0);
+ if(fp)
+ {
+ fp->subshell = sh.subshell;
+ if((lp=np->nvfun)==fp)
+ {
+ if(mode==NV_CLONE)
+ {
+ lp = nv_clone_disc(fp,0);
+ return(np->nvfun=lp);
+ }
+ if(mode==NV_FIRST || mode==0)
+ return(fp);
+ np->nvfun = lp->next;
+ if(mode==NV_POP)
+ return(fp);
+ if(mode==NV_LAST && (lp->next==0 || lp->next->disc==0))
+ return(fp);
+ }
+ /* see if <fp> is on the list already */
+ lpp = &np->nvfun;
+ if(lp)
+ {
+ while(lp->next && lp->next->disc)
+ {
+ if(lp->next==fp)
+ {
+ if(mode==NV_LAST && fp->next==0)
+ return(fp);
+ if(mode==NV_CLONE)
+ {
+ fp = nv_clone_disc(fp,0);
+ lp->next = fp;
+ return(fp);
+ }
+ lp->next = fp->next;
+ if(mode==NV_POP)
+ return(fp);
+ if(mode!=NV_LAST)
+ break;
+ }
+ lp = lp->next;
+ }
+ if(mode==NV_LAST && lp->disc)
+ lpp = &lp->next;
+ }
+ if(mode==NV_POP)
+ return(0);
+ /* push */
+ nv_offattr(np,NV_NODISC);
+ if(mode==NV_LAST)
+ {
+ if(lp && !lp->disc)
+ fp->next = lp;
+ else
+ fp->next = 0;
+ }
+ else
+ {
+ if((fp->nofree&1) && *lpp)
+ fp = nv_clone_disc(fp,0);
+ fp->next = *lpp;
+ }
+ *lpp = fp;
+ }
+ else
+ {
+ if(mode==NV_FIRST)
+ return(np->nvfun);
+ else if(mode==NV_LAST)
+ for(lp=np->nvfun; lp; fp=lp,lp=lp->next);
+ else if(fp = np->nvfun)
+ np->nvfun = fp->next;
+ }
+ return(fp);
+}
+
+/*
+ * returns discipline pointer if discipline with specified functions
+ * is on the discipline stack
+ */
+Namfun_t *nv_hasdisc(Namval_t *np, const Namdisc_t *dp)
+{
+ register Namfun_t *fp;
+ for(fp=np->nvfun; fp; fp = fp->next)
+ {
+ if(fp->disc== dp)
+ return(fp);
+ }
+ return(0);
+}
+
+struct notify
+{
+ Namfun_t hdr;
+ char **ptr;
+};
+
+static void put_notify(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ struct notify *pp = (struct notify*)fp;
+ nv_putv(np,val,flags,fp);
+ nv_stack(np,fp);
+ nv_stack(np,(Namfun_t*)0);
+ *pp->ptr = 0;
+ if(!(fp->nofree&1))
+ free((void*)fp);
+}
+
+static const Namdisc_t notify_disc = { 0, put_notify };
+
+int nv_unsetnotify(Namval_t *np, char **addr)
+{
+ register Namfun_t *fp;
+ for(fp=np->nvfun;fp;fp=fp->next)
+ {
+ if(fp->disc->putval==put_notify && ((struct notify*)fp)->ptr==addr)
+ {
+ nv_stack(np,fp);
+ nv_stack(np,(Namfun_t*)0);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ return(1);
+ }
+ }
+ return(0);
+}
+
+int nv_setnotify(Namval_t *np, char **addr)
+{
+ struct notify *pp = newof(0,struct notify, 1,0);
+ if(!pp)
+ return(0);
+ pp->ptr = addr;
+ pp->hdr.disc = &notify_disc;
+ nv_stack(np,&pp->hdr);
+ return(1);
+}
+
+static void *newnode(const char *name)
+{
+ register int s;
+ register Namval_t *np = newof(0,Namval_t,1,s=strlen(name)+1);
+ if(np)
+ {
+ np->nvname = (char*)np+sizeof(Namval_t);
+ memcpy(np->nvname,name,s);
+ }
+ return((void*)np);
+}
+
+/*
+ * clone a numeric value
+ */
+static void *num_clone(register Namval_t *np, void *val)
+{
+ register int size;
+ void *nval;
+ if(!val)
+ return(0);
+ if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
+ {
+ if(nv_isattr(np,NV_LONG))
+ size = sizeof(Sfdouble_t);
+ else if(nv_isattr(np,NV_SHORT))
+ size = sizeof(float);
+ else
+ size = sizeof(double);
+ }
+ else
+ {
+ if(nv_isattr(np,NV_LONG))
+ size = sizeof(Sflong_t);
+ else if(nv_isattr(np,NV_SHORT))
+ {
+ if(nv_isattr(np,NV_INT16P)==NV_INT16P)
+ size = sizeof(short);
+ else
+ return((void*)np->nvalue.ip);
+ }
+ else
+ size = sizeof(int32_t);
+ }
+ if(!(nval = malloc(size)))
+ return(0);
+ memcpy(nval,val,size);
+ return(nval);
+}
+
+void clone_all_disc( Namval_t *np, Namval_t *mp, int flags)
+{
+ register Namfun_t *fp, **mfp = &mp->nvfun, *nfp, *fpnext;
+ for(fp=np->nvfun; fp;fp=fpnext)
+ {
+ fpnext = fp->next;
+ if(!fpnext && (flags&NV_COMVAR) && fp->disc && fp->disc->namef)
+ return;
+ if((fp->nofree&2) && (flags&NV_NODISC))
+ nfp = 0;
+ if(fp->disc && fp->disc->clonef)
+ nfp = (*fp->disc->clonef)(np,mp,flags,fp);
+ else if(flags&NV_MOVE)
+ nfp = fp;
+ else
+ nfp = nv_clone_disc(fp,flags);
+ if(!nfp)
+ continue;
+ nfp->next = 0;
+ *mfp = nfp;
+ mfp = &nfp->next;
+ }
+}
+
+/*
+ * clone <mp> from <np> flags can be one of the following
+ * NV_APPEND - append <np> onto <mp>
+ * NV_MOVE - move <np> to <mp>
+ * NV_NOFREE - mark the new node as nofree
+ * NV_NODISC - discplines with funs non-zero will not be copied
+ * NV_COMVAR - cloning a compound variable
+ */
+int nv_clone(Namval_t *np, Namval_t *mp, int flags)
+{
+ Namfun_t *fp, *fpnext;
+ const char *val = mp->nvalue.cp;
+ unsigned short flag = mp->nvflag;
+ unsigned short size = mp->nvsize;
+ for(fp=mp->nvfun; fp; fp=fpnext)
+ {
+ fpnext = fp->next;
+ if(!fpnext && (flags&NV_COMVAR) && fp->disc && fp->disc->namef)
+ break;
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ }
+ mp->nvfun = fp;
+ if(fp=np->nvfun)
+ {
+ if(nv_isattr(mp,NV_EXPORT|NV_MINIMAL) == (NV_EXPORT|NV_MINIMAL))
+ {
+ mp->nvenv = 0;
+ nv_offattr(mp,NV_MINIMAL);
+ }
+ if(!(flags&NV_COMVAR) && !nv_isattr(np,NV_MINIMAL) && np->nvenv && !(nv_isattr(mp,NV_MINIMAL)))
+ mp->nvenv = np->nvenv;
+ mp->nvflag &= NV_MINIMAL;
+ mp->nvflag |= np->nvflag&~(NV_ARRAY|NV_MINIMAL|NV_NOFREE);
+ flag = mp->nvflag;
+ clone_all_disc(np, mp, flags);
+ }
+ if(flags&NV_APPEND)
+ return(1);
+ if(mp->nvsize == size)
+ nv_setsize(mp,nv_size(np));
+ if(mp->nvflag == flag)
+ mp->nvflag = (np->nvflag&~(NV_MINIMAL))|(mp->nvflag&NV_MINIMAL);
+ if(nv_isattr(np,NV_EXPORT))
+ mp->nvflag |= (np->nvflag&NV_MINIMAL);
+ if(mp->nvalue.cp==val && !nv_isattr(np,NV_INTEGER))
+ {
+ if(np->nvalue.cp && np->nvalue.cp!=Empty && (flags&NV_COMVAR) && !(flags&NV_MOVE))
+ {
+ if(size)
+ mp->nvalue.cp = (char*)memdup(np->nvalue.cp,size);
+ else
+ mp->nvalue.cp = strdup(np->nvalue.cp);
+ nv_offattr(mp,NV_NOFREE);
+ }
+ else if((np->nvfun || !nv_isattr(np,NV_ARRAY)) && !(mp->nvalue.cp = np->nvalue.cp))
+ nv_offattr(mp,NV_NOFREE);
+ }
+ if(flags&NV_MOVE)
+ {
+ if(nv_isattr(np,NV_INTEGER))
+ mp->nvalue.ip = np->nvalue.ip;
+ np->nvfun = 0;
+ np->nvalue.cp = 0;
+ if(!nv_isattr(np,NV_MINIMAL) || nv_isattr(mp,NV_EXPORT))
+ {
+ mp->nvenv = np->nvenv;
+ np->nvflag = 0;
+ }
+ else
+ np->nvflag &= NV_MINIMAL;
+ nv_setsize(np,0);
+ return(1);
+ }
+ else if((flags&NV_ARRAY) && !nv_isattr(np,NV_MINIMAL))
+ mp->nvenv = np->nvenv;
+ if(nv_isattr(np,NV_INTEGER) && mp->nvalue.ip!=np->nvalue.ip && np->nvalue.cp!=Empty)
+ {
+ mp->nvalue.ip = (int*)num_clone(np,(void*)np->nvalue.ip);
+ nv_offattr(mp,NV_NOFREE);
+ }
+ else if((flags&NV_NOFREE) && !nv_arrayptr(np))
+ nv_onattr(np,NV_NOFREE);
+ return(1);
+}
+
+/*
+ * The following discipline is for copy-on-write semantics
+ */
+static char* clone_getv(Namval_t *np, Namfun_t *handle)
+{
+ return(np->nvalue.np?nv_getval(np->nvalue.np):0);
+}
+
+static Sfdouble_t clone_getn(Namval_t *np, Namfun_t *handle)
+{
+ return(np->nvalue.np?nv_getnum(np->nvalue.np):0);
+}
+
+static void clone_putv(Namval_t *np,const char* val,int flags,Namfun_t *handle)
+{
+ Namfun_t *dp = nv_stack(np,(Namfun_t*)0);
+ Namval_t *mp = np->nvalue.np;
+ if(!sh.subshell)
+ free((void*)dp);
+ if(val)
+ nv_clone(mp,np,NV_NOFREE);
+ np->nvalue.cp = 0;
+ nv_putval(np,val,flags);
+}
+
+static const Namdisc_t clone_disc =
+{
+ 0,
+ clone_putv,
+ clone_getv,
+ clone_getn
+};
+
+Namval_t *nv_mkclone(Namval_t *mp)
+{
+ Namval_t *np;
+ Namfun_t *dp;
+ np = newof(0,Namval_t,1,0);
+ np->nvflag = mp->nvflag;
+ np->nvsize = mp->nvsize;
+ np->nvname = mp->nvname;
+ np->nvalue.np = mp;
+ np->nvflag = mp->nvflag;
+ dp = newof(0,Namfun_t,1,0);
+ dp->disc = &clone_disc;
+ nv_stack(np,dp);
+ dtinsert(nv_dict(sh.namespace),np);
+ return(np);
+}
+
+Namval_t *nv_search(const char *name, Dt_t *root, int mode)
+{
+ register Namval_t *np;
+ register Dt_t *dp = 0;
+ if(mode&HASH_NOSCOPE)
+ dp = dtview(root,0);
+ if(mode&HASH_BUCKET)
+ {
+ Namval_t *mp = (void*)name;
+ if(!(np = dtsearch(root,mp)) && (mode&NV_ADD))
+ name = nv_name(mp);
+ }
+ else
+ {
+ if(*name=='.' && root==sh.var_tree && !dp)
+ root = sh.var_base;
+ np = dtmatch(root,(void*)name);
+ }
+#if SHOPT_COSHELL
+ if(sh.inpool)
+ mode |= HASH_NOSCOPE;
+#endif /* SHOPT_COSHELL */
+ if(!np && (mode&NV_ADD))
+ {
+ if(sh.namespace && !(mode&HASH_NOSCOPE) && root==sh.var_tree)
+ root = nv_dict(sh.namespace);
+ else if(!dp && !(mode&HASH_NOSCOPE))
+ {
+ register Dt_t *next;
+ while(next=dtvnext(root))
+ root = next;
+ }
+ np = (Namval_t*)dtinsert(root,newnode(name));
+ }
+ if(dp)
+ dtview(root,dp);
+ return(np);
+}
+
+/*
+ * finds function or builtin for given name and the discipline variable
+ * if var!=0 the variable pointer is returned and the built-in name
+ * is put onto the stack at the current offset.
+ * otherwise, a pointer to the builtin (variable or type) is returned
+ * and var contains the poiner to the variable
+ * if last==0 and first component of name is a reference, nv_bfsearch()
+ will return 0.
+ */
+Namval_t *nv_bfsearch(const char *name, Dt_t *root, Namval_t **var, char **last)
+{
+ Shell_t *shp = sh_getinterp();
+ int c,offset = staktell();
+ register char *sp, *cp=0;
+ Namval_t *np, *nq;
+ char *dname=0;
+ if(var)
+ *var = 0;
+ /* check for . in the name before = */
+ for(sp=(char*)name+1; *sp; sp++)
+ {
+ if(*sp=='=')
+ return(0);
+ if(*sp=='[')
+ {
+ while(*sp=='[')
+ {
+ sp = nv_endsubscript((Namval_t*)0,(char*)sp,0);
+ if(sp[-1]!=']')
+ return(0);
+ }
+ if(*sp==0)
+ break;
+ if(*sp!='.')
+ return(0);
+ cp = sp;
+ }
+ else if(*sp=='.')
+ cp = sp;
+ }
+ if(!cp)
+ return(var?nv_search(name,root,0):0);
+ stakputs(name);
+ stakputc(0);
+ dname = cp+1;
+ cp = stakptr(offset) + (cp-name);
+ if(last)
+ *last = cp;
+ c = *cp;
+ *cp = 0;
+ nq=nv_open(stakptr(offset),0,NV_VARNAME|NV_NOASSIGN|NV_NOADD|NV_NOFAIL);
+ *cp = c;
+ if(!nq)
+ {
+ np = 0;
+ goto done;
+ }
+ if(!var)
+ {
+ np = nq;
+ goto done;
+ }
+ *var = nq;
+ if(c=='[')
+ nv_endsubscript(nq, cp,NV_NOADD);
+ stakseek(offset);
+#if SHOPT_NAMESPACE
+ if(nv_istable(nq))
+ {
+ Namval_t *nsp = shp->namespace;
+ if(last==0)
+ return(nv_search(name,root,0));
+ shp->namespace = 0;
+ stakputs(nv_name(nq));
+ shp->namespace = nsp;
+ stakputs(dname-1);
+ stakputc(0);
+ np = nv_search(stakptr(offset),root,0);
+ stakseek(offset);
+ return(np);
+ }
+#endif /* SHOPT_NAMESPACE */
+ while(nv_isarray(nq) && !nv_isattr(nq,NV_MINIMAL|NV_EXPORT) && nq->nvenv && nv_isarray((Namval_t*)nq->nvenv))
+ nq = (Namval_t*)nq->nvenv;
+ return((Namval_t*)nv_setdisc(nq,dname,nq,(Namfun_t*)nq));
+done:
+ stakseek(offset);
+ return(np);
+}
+
+/*
+ * add or replace built-in version of command corresponding to <path>
+ * The <bltin> argument is a pointer to the built-in
+ * if <extra>==1, the built-in will be deleted
+ * Special builtins cannot be added or deleted return failure
+ * The return value for adding builtins is a pointer to the node or NULL on
+ * failure. For delete NULL means success and the node that cannot be
+ * deleted is returned on failure.
+ */
+Namval_t *sh_addbuiltin(const char *path, Shbltin_f bltin, void *extra)
+{
+ register const char *name = path_basename(path);
+ char *cp;
+ register Namval_t *np, *nq=0;
+ int offset=staktell();
+ if(name==path && bltin!=(Shbltin_f)SYSTYPESET->nvalue.bfp && (nq=nv_bfsearch(name,sh.bltin_tree,(Namval_t**)0,&cp)))
+ path = name = stakptr(offset);
+ if(np = nv_search(path,sh.bltin_tree,0))
+ {
+ /* exists without a path */
+ if(extra == (void*)1)
+ {
+ if(np->nvfun && !nv_isattr(np,NV_NOFREE))
+ free((void*)np->nvfun);
+ dtdelete(sh.bltin_tree,np);
+ return(0);
+ }
+ if(!bltin)
+ return(np);
+ }
+ else for(np=(Namval_t*)dtfirst(sh.bltin_tree);np;np=(Namval_t*)dtnext(sh.bltin_tree,np))
+ {
+ if(strcmp(name,path_basename(nv_name(np))))
+ continue;
+ /* exists probably with different path so delete it */
+ if(strcmp(path,nv_name(np)))
+ {
+ if(nv_isattr(np,BLT_SPC))
+ return(np);
+ if(!bltin)
+ bltin = (Shbltin_f)np->nvalue.bfp;
+ if(np->nvenv)
+ dtdelete(sh.bltin_tree,np);
+ if(extra == (void*)1)
+ return(0);
+ np = 0;
+ }
+ break;
+ }
+ if(!np && !(np = nv_search(path,sh.bltin_tree,bltin?NV_ADD:0)))
+ return(0);
+ if(nv_isattr(np,BLT_SPC))
+ {
+ if(extra)
+ np->nvfun = (Namfun_t*)extra;
+ return(np);
+ }
+ np->nvenv = 0;
+ np->nvfun = 0;
+ if(bltin)
+ {
+ np->nvalue.bfp = (Nambfp_f)bltin;
+ nv_onattr(np,NV_BLTIN|NV_NOFREE);
+ np->nvfun = (Namfun_t*)extra;
+ }
+ if(nq)
+ {
+ cp=nv_setdisc(nq,cp+1,np,(Namfun_t*)nq);
+ nv_close(nq);
+ if(!cp)
+ errormsg(SH_DICT,ERROR_exit(1),e_baddisc,name);
+ }
+ if(extra == (void*)1)
+ return(0);
+ return(np);
+}
+
+#undef nv_stack
+extern Namfun_t *nv_stack(register Namval_t *np, register Namfun_t* fp)
+{
+ return(nv_disc(np,fp,0));
+}
+
+struct table
+{
+ Namfun_t fun;
+ Namval_t *parent;
+ Shell_t *shp;
+ Dt_t *dict;
+};
+
+static Namval_t *next_table(register Namval_t* np, Dt_t *root,Namfun_t *fp)
+{
+ struct table *tp = (struct table *)fp;
+ if(root)
+ return((Namval_t*)dtnext(root,np));
+ else
+ return((Namval_t*)dtfirst(tp->dict));
+}
+
+static Namval_t *create_table(Namval_t *np,const char *name,int flags,Namfun_t *fp)
+{
+ struct table *tp = (struct table *)fp;
+ tp->shp->last_table = np;
+ return(nv_create(name, tp->dict, flags, fp));
+}
+
+static Namfun_t *clone_table(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ struct table *tp = (struct table*)fp;
+ struct table *ntp = (struct table*)nv_clone_disc(fp,0);
+ Dt_t *oroot=tp->dict,*nroot=dtopen(&_Nvdisc,Dtoset);
+ if(!nroot)
+ return(0);
+ memcpy((void*)ntp,(void*)fp,sizeof(struct table));
+ ntp->dict = nroot;
+ ntp->parent = nv_lastdict();
+ for(np=(Namval_t*)dtfirst(oroot);np;np=(Namval_t*)dtnext(oroot,np))
+ {
+ mp = (Namval_t*)dtinsert(nroot,newnode(np->nvname));
+ nv_clone(np,mp,flags);
+ }
+ return(&ntp->fun);
+}
+
+struct adata
+{
+ Shell_t *sh;
+ Namval_t *tp;
+ char *mapname;
+ char **argnam;
+ int attsize;
+ char *attval;
+};
+
+static void delete_fun(Namval_t *np, void *data)
+{
+ Shell_t *shp = ((struct adata*)data)->sh;
+ nv_delete(np,shp->fun_tree,NV_NOFREE);
+}
+
+static void put_table(register Namval_t* np, const char* val, int flags, Namfun_t* fp)
+{
+ register Dt_t *root = ((struct table*)fp)->dict;
+ register Namval_t *nq, *mp;
+ Namarr_t *ap;
+ struct adata data;
+ nv_putv(np,val,flags,fp);
+ if(val)
+ return;
+ if(nv_isarray(np) && (ap=nv_arrayptr(np)) && array_elem(ap))
+ return;
+ memset(&data,0,sizeof(data));
+ data.mapname = nv_name(np);
+ data.sh = ((struct table*)fp)->shp;
+ nv_scan(data.sh->fun_tree,delete_fun,(void*)&data,NV_FUNCTION,NV_FUNCTION|NV_NOSCOPE);
+ for(mp=(Namval_t*)dtfirst(root);mp;mp=nq)
+ {
+ _nv_unset(mp,flags);
+ nq = (Namval_t*)dtnext(root,mp);
+ dtdelete(root,mp);
+ free((void*)mp);
+ }
+ dtclose(root);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ np->nvfun = 0;
+}
+
+/*
+ * return space separated list of names of variables in given tree
+ */
+static char *get_table(Namval_t *np, Namfun_t *fp)
+{
+ register Dt_t *root = ((struct table*)fp)->dict;
+ static Sfio_t *out;
+ register int first=1;
+ register Dt_t *base = dtview(root,0);
+ if(out)
+ sfseek(out,(Sfoff_t)0,SEEK_SET);
+ else
+ out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
+ for(np=(Namval_t*)dtfirst(root);np;np=(Namval_t*)dtnext(root,np))
+ {
+ if(!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE))
+ {
+ if(!first)
+ sfputc(out,' ');
+ else
+ first = 0;
+ sfputr(out,np->nvname,-1);
+ }
+ }
+ sfputc(out,0);
+ if(base)
+ dtview(root,base);
+ return((char*)out->_data);
+}
+
+static const Namdisc_t table_disc =
+{
+ sizeof(struct table),
+ put_table,
+ get_table,
+ 0,
+ 0,
+ create_table,
+ clone_table,
+ 0,
+ next_table,
+};
+
+Namval_t *nv_parent(Namval_t *np)
+{
+ struct table *tp = (struct table *)nv_hasdisc(np,&table_disc);
+ if(tp)
+ return(tp->parent);
+ return(0);
+}
+
+Dt_t *nv_dict(Namval_t* np)
+{
+ Shell_t *shp=sh_getinterp();
+ struct table *tp = (struct table*)nv_hasdisc(np,&table_disc);
+ if(tp)
+ return(tp->dict);
+ np = shp->last_table;
+ while(np)
+ {
+ if(tp = (struct table*)nv_hasdisc(np,&table_disc))
+ return(tp->dict);
+#if 0
+ np = nv_create(np,(const char*)0, NV_FIRST, (Namfun_t*)0);
+#else
+ break;
+#endif
+ }
+ return(shp->var_tree);
+}
+
+int nv_istable(Namval_t *np)
+{
+ return(nv_hasdisc(np,&table_disc)!=0);
+}
+
+/*
+ * create a mountable name-value pair tree
+ */
+Namval_t *nv_mount(Namval_t *np, const char *name, Dt_t *dict)
+{
+ Namval_t *mp, *pp;
+ struct table *tp;
+ if(nv_hasdisc(np,&table_disc))
+ pp = np;
+ else
+ pp = nv_lastdict();
+ if(!(tp = newof((struct table*)0, struct table,1,0)))
+ return(0);
+ if(name)
+ {
+ Namfun_t *fp = pp->nvfun;
+ mp = (*fp->disc->createf)(pp,name,0,fp);
+ }
+ else
+ mp = np;
+ nv_offattr(mp,NV_TABLE);
+ if(!nv_isnull(mp))
+ _nv_unset(mp,NV_RDONLY);
+ tp->shp = sh_getinterp();
+ tp->dict = dict;
+ tp->parent = pp;
+ tp->fun.disc = &table_disc;
+ nv_disc(mp, &tp->fun, NV_FIRST);
+ return(mp);
+}
+
+const Namdisc_t *nv_discfun(int which)
+{
+ switch(which)
+ {
+ case NV_DCADD:
+ return(&Nv_bdisc);
+ case NV_DCRESTRICT:
+ return(&RESTRICTED_disc);
+ }
+ return(0);
+}
+
+int nv_hasget(Namval_t *np)
+{
+ register Namfun_t *fp;
+ for(fp=np->nvfun; fp; fp=fp->next)
+ {
+ if(!fp->disc || (!fp->disc->getnum && !fp->disc->getval))
+ continue;
+ return(1);
+ }
+ return(0);
+}
+
+#if SHOPT_NAMESPACE
+Namval_t *sh_fsearch(Shell_t *shp, const char *fname, int add)
+{
+ Stk_t *stkp = shp->stk;
+ int offset = stktell(stkp);
+ sfputr(stkp,nv_name(shp->namespace),'.');
+ sfputr(stkp,fname,0);
+ fname = stkptr(stkp,offset);
+ return(nv_search(fname,sh_subfuntree(add&NV_ADD),add));
+}
+#endif /* SHOPT_NAMESPACE */
diff --git a/src/cmd/ksh93/sh/nvtree.c b/src/cmd/ksh93/sh/nvtree.c
new file mode 100644
index 0000000..4cc3a52
--- /dev/null
+++ b/src/cmd/ksh93/sh/nvtree.c
@@ -0,0 +1,1161 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * code for tree nodes and name walking
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include "name.h"
+#include "argnod.h"
+#include "lexstates.h"
+
+struct nvdir
+{
+ Dt_t *root;
+ Namval_t *hp;
+ Namval_t *table;
+ Namval_t *otable;
+ Namval_t *(*nextnode)(Namval_t*,Dt_t*,Namfun_t*);
+ Namfun_t *fun;
+ struct nvdir *prev;
+ int len;
+ char *data;
+};
+
+static int Indent;
+char *nv_getvtree(Namval_t*, Namfun_t *);
+static void put_tree(Namval_t*, const char*, int,Namfun_t*);
+static char *walk_tree(Namval_t*, Namval_t*, int);
+
+static int read_tree(Namval_t* np, Sfio_t *iop, int n, Namfun_t *dp)
+{
+ Sfio_t *sp;
+ char *cp;
+ int c;
+ if(n>=0)
+ return(-1);
+ while((c = sfgetc(iop)) && isblank(c));
+ sfungetc(iop,c);
+ sfprintf(sh.strbuf,"%s=%c",nv_name(np),0);
+ cp = sfstruse(sh.strbuf);
+ sp = sfopen((Sfio_t*)0,cp,"s");
+ sfstack(iop,sp);
+ c=sh_eval(iop,SH_READEVAL);
+ return(c);
+}
+
+static Namval_t *create_tree(Namval_t *np,const char *name,int flag,Namfun_t *dp)
+{
+ register Namfun_t *fp=dp;
+ fp->dsize = 0;
+ while(fp=fp->next)
+ {
+ if(fp->disc && fp->disc->createf)
+ {
+ if(np=(*fp->disc->createf)(np,name,flag,fp))
+ dp->last = fp->last;
+ return(np);
+ }
+ }
+ return((flag&NV_NOADD)?0:np);
+}
+
+static Namfun_t *clone_tree(Namval_t *np, Namval_t *mp, int flags, Namfun_t *fp){
+ Namfun_t *dp;
+ if ((flags&NV_MOVE) && nv_type(np))
+ return(fp);
+ dp = nv_clone_disc(fp,flags);
+ if((flags&NV_COMVAR) && !(flags&NV_RAW))
+ {
+ walk_tree(np,mp,flags);
+ if((flags&NV_MOVE) && !(fp->nofree&1))
+ free((void*)fp);
+ }
+ return(dp);
+}
+
+static const Namdisc_t treedisc =
+{
+ 0,
+ put_tree,
+ nv_getvtree,
+ 0,
+ 0,
+ create_tree,
+ clone_tree
+ ,0,0,0,
+ read_tree
+};
+
+static char *nextdot(const char *str)
+{
+ register char *cp;
+ register int c;
+ if(*str=='.')
+ str++;
+ for(cp=(char*)str;c= *cp; cp++)
+ {
+ if(c=='[')
+ {
+ cp = nv_endsubscript((Namval_t*)0,(char*)cp,0);
+ return(*cp=='.'?cp:0);
+ }
+ if(c=='.')
+ return(cp);
+ }
+ return(0);
+}
+
+static Namfun_t *nextdisc(Namval_t *np)
+{
+ register Namfun_t *fp;
+ if(nv_isref(np))
+ return(0);
+ for(fp=np->nvfun;fp;fp=fp->next)
+ {
+ if(fp && fp->disc && fp->disc->nextf)
+ return(fp);
+ }
+ return(0);
+}
+
+void *nv_diropen(Namval_t *np,const char *name)
+{
+ char *next,*last;
+ int c,len=strlen(name);
+ struct nvdir *save, *dp = new_of(struct nvdir,len+1);
+ Namval_t *nq=0,fake;
+ Namfun_t *nfp=0;
+ if(!dp)
+ return(0);
+ memset((void*)dp, 0, sizeof(*dp));
+ dp->data = (char*)(dp+1);
+ if(name[len-1]=='*' || name[len-1]=='@')
+ len -= 1;
+ name = memcpy(dp->data,name,len);
+ dp->data[len] = 0;
+ dp->len = len;
+ dp->root = sh.last_root?sh.last_root:sh.var_tree;
+#if 1
+ while(1)
+ {
+ dp->table = sh.last_table;
+ sh.last_table = 0;
+ if(*(last=(char*)name)==0)
+ break;
+ if(!(next=nextdot(last)))
+ break;
+ *next = 0;
+ np = nv_open(name, dp->root, NV_NOFAIL);
+ *next = '.';
+ if(!np || !nv_istable(np))
+ break;
+ dp->root = nv_dict(np);
+ name = next+1;
+ }
+#else
+ dp->table = sh.last_table;
+ sh.last_table = 0;
+ last = dp->data;
+#endif
+ if(*name)
+ {
+ fake.nvname = (char*)name;
+ if(dp->hp = (Namval_t*)dtprev(dp->root,&fake))
+ {
+ char *cp = nv_name(dp->hp);
+ c = strlen(cp);
+ if(memcmp(name,cp,c) || name[c]!='[')
+ dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
+ else
+ {
+ np = dp->hp;
+ last = 0;
+ }
+ }
+ else
+ dp->hp = (Namval_t*)dtfirst(dp->root);
+ }
+ else
+ dp->hp = (Namval_t*)dtfirst(dp->root);
+ while(1)
+ {
+ if(!last)
+ next = 0;
+ else if(next= nextdot(last))
+ {
+ c = *next;
+ *next = 0;
+ }
+ if(!np)
+ {
+ if(nfp && nfp->disc && nfp->disc->createf)
+ {
+ np = (*nfp->disc->createf)(nq,last,0,nfp);
+ if(*nfp->last == '[')
+ {
+ nv_endsubscript(np,nfp->last,NV_NOADD);
+ if(nq = nv_opensub(np))
+ np = nq;
+ }
+ }
+ else
+ np = nv_search(last,dp->root,0);
+ }
+ if(next)
+ *next = c;
+ if(np==dp->hp && !next)
+ dp->hp = (Namval_t*)dtnext(dp->root,dp->hp);
+ if(np && ((nfp=nextdisc(np)) || nv_istable(np)))
+ {
+ if(!(save = new_of(struct nvdir,0)))
+ return(0);
+ *save = *dp;
+ dp->prev = save;
+ if(nv_istable(np))
+ dp->root = nv_dict(np);
+ else
+ dp->root = (Dt_t*)np;
+ if(nfp)
+ {
+ dp->nextnode = nfp->disc->nextf;
+ dp->table = np;
+ dp->otable = sh.last_table;
+ dp->fun = nfp;
+ dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp);
+ }
+ else
+ dp->nextnode = 0;
+ }
+ else
+ break;
+ if(!next || next[1]==0)
+ break;
+ last = next+1;
+ nq = np;
+ np = 0;
+ }
+ return((void*)dp);
+}
+
+
+static Namval_t *nextnode(struct nvdir *dp)
+{
+ if(dp->nextnode)
+ return((*dp->nextnode)(dp->hp,dp->root,dp->fun));
+ if(dp->len && memcmp(dp->data, dp->hp->nvname, dp->len))
+ return(0);
+ return((Namval_t*)dtnext(dp->root,dp->hp));
+}
+
+char *nv_dirnext(void *dir)
+{
+ register struct nvdir *save, *dp = (struct nvdir*)dir;
+ register Namval_t *np, *last_table;
+ register char *cp;
+ Namfun_t *nfp;
+ Namval_t *nq;
+ while(1)
+ {
+ while(np=dp->hp)
+ {
+#if 0
+ char *sptr;
+#endif
+ if(nv_isarray(np))
+ nv_putsub(np,(char*)0, ARRAY_UNDEF);
+ dp->hp = nextnode(dp);
+ if(nv_isnull(np) && !nv_isarray(np) && !nv_isattr(np,NV_INTEGER))
+ continue;
+ last_table = sh.last_table;
+#if 0
+ if(dp->table && dp->otable && !nv_isattr(dp->table,NV_MINIMAL))
+ {
+ sptr = dp->table->nvenv;
+ dp->table->nvenv = (char*)dp->otable;
+ }
+#endif
+ sh.last_table = dp->table;
+ cp = nv_name(np);
+#if 0
+ if(dp->table && dp->otable && !nv_isattr(dp->table,NV_MINIMAL))
+ dp->table->nvenv = sptr;
+#endif
+ if(dp->nextnode && !dp->hp && (nq = (Namval_t*)dp->table))
+ {
+ Namarr_t *ap = nv_arrayptr(nq);
+ if(ap && (ap->nelem&ARRAY_SCAN) && nv_nextsub(nq))
+ dp->hp = (*dp->nextnode)(np,(Dt_t*)0,dp->fun);
+ }
+ sh.last_table = last_table;
+ if(!dp->len || memcmp(cp,dp->data,dp->len)==0)
+ {
+ if((nfp=nextdisc(np)) && (nfp->disc->getval||nfp->disc->getnum) && nv_isvtree(np) && strcmp(cp,dp->data))
+ nfp = 0;
+ if(nfp || nv_istable(np))
+ {
+ Dt_t *root;
+ int len;
+ if(nv_istable(np))
+ root = nv_dict(np);
+ else
+ root = (Dt_t*)np;
+ /* check for recursive walk */
+ for(save=dp; save; save=save->prev)
+ {
+ if(save->root==root)
+ break;
+ }
+ if(save)
+ return(cp);
+ len = strlen(cp);
+ if(!(save = new_of(struct nvdir,len+1)))
+ return(0);
+ *save = *dp;
+ dp->prev = save;
+ dp->root = root;
+ dp->len = len-1;
+ dp->data = (char*)(save+1);
+ memcpy(dp->data,cp,len+1);
+ if(nfp && np->nvfun)
+ {
+#if 0
+ Namarr_t *ap = nv_arrayptr(np);
+ if(ap && (ap->nelem&ARRAY_UNDEF))
+ nv_putsub(np,(char*)0,ARRAY_SCAN);
+#endif
+ dp->nextnode = nfp->disc->nextf;
+ dp->otable = dp->table;
+ dp->table = np;
+ dp->fun = nfp;
+ dp->hp = (*dp->nextnode)(np,(Dt_t*)0,nfp);
+ }
+ else
+ dp->nextnode = 0;
+ }
+ return(cp);
+ }
+ }
+ if(!(save=dp->prev))
+ break;
+ *dp = *save;
+ free((void*)save);
+ }
+ return(0);
+}
+
+void nv_dirclose(void *dir)
+{
+ struct nvdir *dp = (struct nvdir*)dir;
+ if(dp->prev)
+ nv_dirclose((void*)dp->prev);
+ free(dir);
+}
+
+static void outtype(Namval_t *np, Namfun_t *fp, Sfio_t* out, const char *prefix)
+{
+ char *type=0;
+ Namval_t *tp = fp->type;
+ if(!tp && fp->disc && fp->disc->typef)
+ tp = (*fp->disc->typef)(np,fp);
+ for(fp=fp->next;fp;fp=fp->next)
+ {
+ if(fp->type || (fp->disc && fp->disc->typef &&(*fp->disc->typef)(np,fp)))
+ {
+ outtype(np,fp,out,prefix);
+ break;
+ }
+ }
+ if(prefix && *prefix=='t')
+ type = "-T";
+ else if(!prefix)
+ type = "type";
+ if(type)
+ {
+ char *cp=tp->nvname;
+ if(cp=strrchr(cp,'.'))
+ cp++;
+ else
+ cp = tp->nvname;
+ sfprintf(out,"%s %s ",type,cp);
+ }
+}
+
+/*
+ * print the attributes of name value pair give by <np>
+ */
+void nv_attribute(register Namval_t *np,Sfio_t *out,char *prefix,int noname)
+{
+ register const Shtable_t *tp;
+ register char *cp;
+ register unsigned val,mask,attr;
+ char *ip=0;
+ Namfun_t *fp=0;
+ Namval_t *typep=0;
+#if SHOPT_FIXEDARRAY
+ int fixed=0;
+#endif /* SHOPT_FIXEDARRAY */
+ for(fp=np->nvfun;fp;fp=fp->next)
+ {
+ if((typep=fp->type) || (fp->disc && fp->disc->typef && (typep=(*fp->disc->typef)(np,fp))))
+ break;
+ }
+ if(np==typep)
+ {
+
+ fp = 0;
+ typep = 0;
+ }
+ if(!fp && !nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)))
+ {
+ if(prefix && *prefix)
+ {
+ if(nv_isvtree(np))
+ sfprintf(out,"%s -C ",prefix);
+ else if((!np->nvalue.cp||np->nvalue.cp==Empty) && nv_isattr(np,~NV_NOFREE)==NV_MINIMAL && strcmp(np->nvname,"_"))
+ sfputr(out,prefix,' ');
+ }
+ return;
+ }
+
+ if ((attr=nv_isattr(np,~NV_NOFREE)) || fp)
+ {
+ if((attr&NV_NOPRINT|NV_INTEGER)==NV_NOPRINT)
+ attr &= ~NV_NOPRINT;
+ if(!attr && !fp)
+ return;
+ if(fp)
+ {
+ prefix = Empty;
+ attr &= NV_RDONLY|NV_ARRAY;
+ if(nv_isattr(np,NV_REF|NV_TAGGED)==(NV_REF|NV_TAGGED))
+ attr |= (NV_REF|NV_TAGGED);
+ if(typep)
+ {
+ char *cp = typep->nvname;
+ if(cp = strrchr(cp,'.'))
+ cp++;
+ else
+ cp = typep->nvname;
+ sfputr(out,cp,' ');
+ fp = 0;
+ }
+ }
+ else if(prefix && *prefix)
+ sfputr(out,prefix,' ');
+ for(tp = shtab_attributes; *tp->sh_name;tp++)
+ {
+ val = tp->sh_number;
+ mask = val;
+ if(fp && (val&NV_INTEGER))
+ break;
+ /*
+ * the following test is needed to prevent variables
+ * with E attribute from being given the F
+ * attribute as well
+ */
+ if(val==NV_DOUBLE && (attr&(NV_EXPNOTE|NV_HEXFLOAT)))
+ continue;
+ if(val&NV_INTEGER)
+ mask |= NV_DOUBLE;
+ else if(val&NV_HOST)
+ mask = NV_HOST;
+ if((attr&mask)==val)
+ {
+ if(val==NV_ARRAY)
+ {
+ Namarr_t *ap = nv_arrayptr(np);
+ char **xp=0;
+ if(ap && array_assoc(ap))
+ {
+ if(tp->sh_name[1]!='A')
+ continue;
+ }
+ else if(tp->sh_name[1]=='A')
+ continue;
+ if((ap && (ap->nelem&ARRAY_TREE)) || (!ap && nv_isattr(np,NV_NOFREE)))
+ {
+ if(prefix && *prefix)
+ sfwrite(out,"-C ",3);
+ }
+#if SHOPT_FIXEDARRAY
+ if(ap && ap->fixed)
+ fixed++;
+ else
+#endif /* SHOPT_FIXEDARRAY */
+ if(ap && !array_assoc(ap) && (xp=(char**)(ap+1)) && *xp)
+ ip = nv_namptr(*xp,0)->nvname;
+ }
+ if(val==NV_UTOL || val==NV_LTOU)
+ {
+ if((cp = (char*)nv_mapchar(np,0)) && strcmp(cp,tp->sh_name+2))
+ {
+ sfprintf(out,"-M %s ",cp);
+ continue;
+ }
+ }
+ if(prefix)
+ {
+ if(*tp->sh_name=='-')
+ sfprintf(out,"%.2s ",tp->sh_name);
+ if(ip)
+ {
+ sfprintf(out,"[%s] ",ip);
+ ip = 0;
+ }
+ }
+ else
+ sfputr(out,tp->sh_name+2,' ');
+ if ((val&(NV_LJUST|NV_RJUST|NV_ZFILL)) && !(val&NV_INTEGER) && val!=NV_HOST)
+ sfprintf(out,"%d ",nv_size(np));
+ if(val==(NV_REF|NV_TAGGED))
+ attr &= ~(NV_REF|NV_TAGGED);
+ }
+ if(val==NV_INTEGER && nv_isattr(np,NV_INTEGER))
+ {
+ if(nv_size(np) != 10)
+ {
+ if(nv_isattr(np, NV_DOUBLE)== NV_DOUBLE)
+ cp = "precision";
+ else
+ cp = "base";
+ if(!prefix)
+ sfputr(out,cp,' ');
+ sfprintf(out,"%d ",nv_size(np));
+ }
+ break;
+ }
+ }
+#if SHOPT_FIXEDARRAY
+ if(fixed)
+ {
+ sfprintf(out,"%s",nv_name(np));
+ nv_arrfixed(np,out,0,(char*)0);
+ sfputc(out,';');
+ }
+#endif /* SHOPT_FIXEDARRAY */
+ if(fp)
+ outtype(np,fp,out,prefix);
+ if(noname)
+ return;
+ sfputr(out,nv_name(np),'\n');
+ }
+}
+
+struct Walk
+{
+ Shell_t *shp;
+ Sfio_t *out;
+ Dt_t *root;
+ int noscope;
+ int indent;
+ int nofollow;
+ int array;
+ int flags;
+};
+
+void nv_outnode(Namval_t *np, Sfio_t* out, int indent, int special)
+{
+ char *fmtq,*ep,*xp;
+ Namval_t *mp;
+ Namarr_t *ap = nv_arrayptr(np);
+ int scan,tabs=0,c,more,associative = 0;
+ int saveI = Indent;
+ Indent = indent;
+ if(ap)
+ {
+ if(!(ap->nelem&ARRAY_SCAN))
+ nv_putsub(np,NIL(char*),ARRAY_SCAN);
+ sfputc(out,'(');
+ if(indent>=0)
+ {
+ sfputc(out,'\n');
+ tabs=1;
+ }
+ if(!(associative =(array_assoc(ap)!=0)))
+ {
+ if(array_elem(ap) < nv_aimax(np)+1)
+ associative=1;
+ }
+ }
+ mp = nv_opensub(np);
+ while(1)
+ {
+ if(mp && special && nv_isvtree(mp) && !nv_isarray(mp))
+ {
+ if(!nv_nextsub(np))
+ break;
+ mp = nv_opensub(np);
+ continue;
+ }
+ if(tabs)
+ sfnputc(out,'\t',Indent = ++indent);
+ tabs=0;
+ if(associative||special)
+ {
+ if(!(fmtq = nv_getsub(np)))
+ break;
+ sfprintf(out,"[%s]",sh_fmtq(fmtq));
+ sfputc(out,'=');
+ }
+ if(ap && !array_assoc(ap))
+ scan = ap->nelem&ARRAY_SCAN;
+ if(mp && nv_isarray(mp))
+ {
+ nv_outnode(mp, out, indent,0);
+ if(indent>0)
+ sfnputc(out,'\t',indent);
+ sfputc(out,')');
+ sfputc(out,indent>=0?'\n':' ');
+ if(ap && !array_assoc(ap))
+ ap->nelem |= scan;
+ more = nv_nextsub(np);
+ goto skip;
+ }
+ if(mp && nv_isvtree(mp))
+ {
+ if(indent<0)
+ nv_onattr(mp,NV_EXPORT);
+ nv_onattr(mp,NV_TABLE);
+ }
+ ep = nv_getval(mp?mp:np);
+ if(ep==Empty && !(ap && ap->fixed))
+ ep = 0;
+ xp = 0;
+ if(!ap && nv_isattr(np,NV_INTEGER|NV_LJUST)==NV_LJUST)
+ {
+ xp = ep+nv_size(np);
+ while(--xp>ep && *xp==' ');
+ if(xp>ep || *xp!=' ')
+ xp++;
+ if(xp < (ep+nv_size(np)))
+ *xp = 0;
+ else
+ xp = 0;
+ }
+ if(mp && nv_isvtree(mp))
+ fmtq = ep;
+ else if(!(fmtq = sh_fmtq(ep)))
+ fmtq = "";
+ else if(!associative && (ep=strchr(fmtq,'=')))
+ {
+ char *qp = strchr(fmtq,'\'');
+ if(!qp || qp>ep)
+ {
+ sfwrite(out,fmtq,ep-fmtq);
+ sfputc(out,'\\');
+ fmtq = ep;
+ }
+ }
+ if(ap && !array_assoc(ap))
+ ap->nelem |= scan;
+ more = nv_nextsub(np);
+ c = '\n';
+ if(indent<0)
+ {
+ c = indent < -1?-1:';';
+ if(ap)
+ c = more?' ':-1;
+ }
+ sfputr(out,fmtq,c);
+ if(xp)
+ *xp = ' ';
+ skip:
+ if(!more)
+ break;
+ mp = nv_opensub(np);
+ if(indent>0 && !(mp && special && nv_isvtree(mp)))
+ sfnputc(out,'\t',indent);
+ }
+ Indent = saveI;
+}
+
+static void outval(char *name, const char *vname, struct Walk *wp)
+{
+ register Namval_t *np, *nq, *last_table=wp->shp->last_table;
+ register Namfun_t *fp;
+ int isarray=0, special=0,mode=0;
+ if(*name!='.' || vname[strlen(vname)-1]==']')
+ mode = NV_ARRAY;
+ if(!(np=nv_open(vname,wp->root,mode|NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope)))
+ {
+ wp->shp->last_table = last_table;
+ return;
+ }
+ if(!wp->out)
+ wp->shp->last_table = last_table;
+ fp = nv_hasdisc(np,&treedisc);
+ if(*name=='.')
+ {
+ if(nv_isattr(np,NV_BINARY))
+ return;
+ if(fp && np->nvalue.cp && np->nvalue.cp!=Empty)
+ {
+ nv_local = 1;
+ fp = 0;
+ }
+ if(fp)
+ return;
+ if(nv_isarray(np))
+ return;
+ }
+ if(!special && fp && !nv_isarray(np))
+ {
+ Namfun_t *xp;
+ if(!wp->out)
+ {
+ fp = nv_stack(np,fp);
+ if(fp = nv_stack(np,NIL(Namfun_t*)))
+ free((void*)fp);
+ np->nvfun = 0;
+ return;
+ }
+ for(xp=fp->next; xp; xp = xp->next)
+ {
+ if(xp->disc && (xp->disc->getval || xp->disc->getnum))
+ break;
+ }
+ if(!xp)
+ return;
+ }
+ if(nv_isnull(np) && !nv_isarray(np) && !nv_isattr(np,NV_INTEGER))
+ return;
+ if(special || (nv_isarray(np) && nv_arrayptr(np)))
+ {
+ isarray=1;
+ if(array_elem(nv_arrayptr(np))==0)
+ isarray=2;
+ else
+ nq = nv_putsub(np,NIL(char*),ARRAY_SCAN|(wp->out?ARRAY_NOCHILD:0));
+ }
+ if(!wp->out)
+ {
+ _nv_unset(np,NV_RDONLY);
+ if(sh.subshell || (wp->flags!=NV_RDONLY) || nv_isattr(np,NV_MINIMAL|NV_NOFREE))
+ wp->root = 0;
+ nv_delete(np,wp->root,NV_NOFREE);
+ return;
+ }
+ if(isarray==1 && !nq)
+ {
+ sfputc(wp->out,'(');
+ if(wp->indent>=0)
+ sfputc(wp->out,'\n');
+ return;
+ }
+ if(isarray==0 && nv_isarray(np) && (nv_isnull(np)||np->nvalue.cp==Empty)) /* empty array */
+ isarray = 2;
+ special |= wp->nofollow;
+ if(!wp->array && wp->indent>0)
+ sfnputc(wp->out,'\t',wp->indent);
+ if(!special)
+ {
+ if(*name!='.')
+ nv_attribute(np,wp->out,"typeset",'=');
+ nv_outname(wp->out,name,-1);
+ if((np->nvalue.cp && np->nvalue.cp!=Empty) || nv_isattr(np,~(NV_MINIMAL|NV_NOFREE)) || nv_isvtree(np))
+ sfputc(wp->out,(isarray==2?(wp->indent>=0?'\n':';'):'='));
+ if(isarray==2)
+ return;
+ }
+ fp = np->nvfun;
+ if(*name=='.' && !isarray)
+ np->nvfun = 0;
+ nv_outnode(np, wp->out, wp->indent, special);
+ if(*name=='.' && !isarray)
+ np->nvfun = fp;
+ if(isarray && !special)
+ {
+ if(wp->indent>0)
+ {
+ sfnputc(wp->out,'\t',wp->indent);
+ sfwrite(wp->out,")\n",2);
+ }
+ else
+ sfwrite(wp->out,");",2);
+ }
+}
+
+/*
+ * format initialization list given a list of assignments <argp>
+ */
+static char **genvalue(char **argv, const char *prefix, int n, struct Walk *wp)
+{
+ register char *cp,*nextcp,*arg;
+ register Sfio_t *outfile = wp->out;
+ register int m,r,l;
+ if(n==0)
+ m = strlen(prefix);
+ else if(cp=nextdot(prefix))
+ m = cp-prefix;
+ else
+ m = strlen(prefix)-1;
+ m++;
+ if(outfile && !wp->array)
+ {
+ sfputc(outfile,'(');
+ if(wp->indent>=0)
+ {
+ wp->indent++;
+ sfputc(outfile,'\n');
+ }
+ }
+ for(; arg= *argv; argv++)
+ {
+ cp = arg + n;
+ if(n==0 && cp[m-1]!='.')
+ continue;
+ if(n && cp[m-1]==0)
+ break;
+ if(n==0 || strncmp(arg,prefix-n,m+n)==0)
+ {
+ cp +=m;
+ r = 0;
+ if(*cp=='.')
+ cp++,r++;
+ if(wp->indent < 0 && argv[1]==0)
+ wp->indent--;
+ if(nextcp=nextdot(cp))
+ {
+ if(outfile)
+ {
+ Namval_t *np,*tp;
+ *nextcp = 0;
+ np=nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL|wp->noscope);
+ if(!np || (nv_isarray(np) && (!(tp=nv_opensub(np)) || !nv_isvtree(tp))))
+ {
+ *nextcp = '.';
+ continue;
+ }
+ if(wp->indent>=0)
+ sfnputc(outfile,'\t',wp->indent);
+ if(*cp!='[' && (tp = nv_type(np)))
+ {
+ char *sp;
+ if(sp = strrchr(tp->nvname,'.'))
+ sp++;
+ else
+ sp = tp->nvname;
+ sfputr(outfile,sp,' ');
+ }
+ nv_outname(outfile,cp,nextcp-cp);
+ sfputc(outfile,'=');
+ *nextcp = '.';
+ }
+ else
+ {
+ outval(cp,arg,wp);
+ continue;
+ }
+ argv = genvalue(argv,cp,n+m+r,wp);
+ if(wp->indent>=0)
+ sfputc(outfile,'\n');
+ if(*argv)
+ continue;
+ break;
+ }
+ else if(outfile && !wp->nofollow && argv[1] && memcmp(arg,argv[1],l=strlen(arg))==0 && argv[1][l]=='[')
+ {
+ int k=1;
+ Namarr_t *ap=0;
+ Namval_t *np = nv_open(arg,wp->root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|wp->noscope);
+ if(!np)
+ continue;
+ if((wp->array = nv_isarray(np)) && (ap=nv_arrayptr(np)))
+ k = array_elem(ap);
+
+ if(wp->indent>0)
+ sfnputc(outfile,'\t',wp->indent);
+ nv_attribute(np,outfile,"typeset",1);
+ nv_close(np);
+ sfputr(outfile,arg+m+r+(n?n:0),(k?'=':'\n'));
+ if(!k)
+ {
+ wp->array=0;
+ continue;
+ }
+ wp->nofollow=1;
+ argv = genvalue(argv,cp,cp-arg ,wp);
+ sfputc(outfile,wp->indent<0?';':'\n');
+ }
+ else if(outfile && *cp=='[' && cp[-1]!='.')
+ {
+ /* skip multi-dimensional arrays */
+ if(*nv_endsubscript((Namval_t*)0,cp,0)=='[')
+ continue;
+ if(wp->indent>0)
+ sfnputc(outfile,'\t',wp->indent);
+ if(cp[-1]=='.')
+ cp--;
+ sfputr(outfile,cp,'=');
+ if(*cp=='.')
+ cp++;
+ argv = genvalue(++argv,cp,cp-arg ,wp);
+ sfputc(outfile,wp->indent>0?'\n':';');
+ }
+ else
+ {
+ outval(cp,arg,wp);
+ if(wp->array)
+ {
+ if(wp->indent>=0)
+ wp->indent++;
+ else
+ sfputc(outfile,' ');
+ wp->array = 0;
+ }
+ }
+ }
+ else
+ break;
+ wp->nofollow = 0;
+ }
+ wp->array = 0;
+ if(outfile)
+ {
+ int c = prefix[m-1];
+ cp = (char*)prefix;
+ if(c=='.')
+ cp[m-1] = 0;
+ outval(".",prefix-n,wp);
+ if(c=='.')
+ cp[m-1] = c;
+ if(wp->indent>0)
+ sfnputc(outfile,'\t',--wp->indent);
+ sfputc(outfile,')');
+ }
+ return(--argv);
+}
+
+/*
+ * walk the virtual tree and print or delete name-value pairs
+ */
+static char *walk_tree(register Namval_t *np, Namval_t *xp, int flags)
+{
+ static Sfio_t *out;
+ struct Walk walk;
+ Sfio_t *outfile;
+ Sfoff_t off = 0;
+ int len, savtop = staktell();
+ char *savptr = stakfreeze(0);
+ register struct argnod *ap=0;
+ struct argnod *arglist=0;
+ char *name,*cp, **argv;
+ char *subscript=0;
+ void *dir;
+ int n=0, noscope=(flags&NV_NOSCOPE);
+ Namarr_t *arp = nv_arrayptr(np);
+ Dt_t *save_tree = sh.var_tree;
+ Namval_t *mp=0;
+ Shell_t *shp = sh_getinterp();
+ char *xpname = xp?stakcopy(nv_name(xp)):0;
+ walk.shp = shp;
+ if(xp)
+ {
+ shp->last_root = shp->prev_root;
+ shp->last_table = shp->prev_table;
+ }
+ if(shp->last_table)
+ shp->last_root = nv_dict(shp->last_table);
+ if(shp->last_root)
+ shp->var_tree = shp->last_root;
+ stakputs(nv_name(np));
+ if(arp && !(arp->nelem&ARRAY_SCAN) && (subscript = nv_getsub(np)))
+ {
+ mp = nv_opensub(np);
+ stakputc('[');
+ stakputs(subscript);
+ stakputc(']');
+ stakputc('.');
+ }
+ else if(*stakptr(staktell()-1) == ']')
+ mp = np;
+ name = stakfreeze(1);
+ len = strlen(name);
+ shp->last_root = 0;
+ dir = nv_diropen(mp,name);
+ walk.root = shp->last_root?shp->last_root:shp->var_tree;
+ if(subscript)
+ name[strlen(name)-1] = 0;
+ while(cp = nv_dirnext(dir))
+ {
+ if(cp[len]!='.')
+ continue;
+ if(xp)
+ {
+ Dt_t *dp = shp->var_tree;
+ Namval_t *nq, *mq;
+ if(strlen(cp)<=len)
+ continue;
+ nq = nv_open(cp,walk.root,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_NOFAIL);
+ if(!nq && (flags&NV_MOVE))
+ nq = nv_search(cp,walk.root,NV_NOADD);
+ stakseek(0);
+ stakputs(xpname);
+ stakputs(cp+len);
+ stakputc(0);
+ shp->var_tree = save_tree;
+ mq = nv_open(stakptr(0),shp->prev_root,NV_VARNAME|NV_NOASSIGN|NV_NOFAIL);
+ shp->var_tree = dp;
+ if(nq && mq)
+ {
+ nv_clone(nq,mq,flags|NV_RAW);
+ if(flags&NV_MOVE)
+ nv_delete(nq,walk.root,0);
+ }
+ continue;
+ }
+ stakseek(ARGVAL);
+ stakputs(cp);
+ ap = (struct argnod*)stakfreeze(1);
+ ap->argflag = ARG_RAW;
+ ap->argchn.ap = arglist;
+ n++;
+ arglist = ap;
+ }
+ nv_dirclose(dir);
+ if(xp)
+ {
+ shp->var_tree = save_tree;
+ return((char*)0);
+ }
+ argv = (char**)stakalloc((n+1)*sizeof(char*));
+ argv += n;
+ *argv = 0;
+ for(; ap; ap=ap->argchn.ap)
+ *--argv = ap->argval;
+ if(flags&1)
+ outfile = 0;
+ else if(!(outfile=out))
+ outfile = out = sfnew((Sfio_t*)0,(char*)0,-1,-1,SF_WRITE|SF_STRING);
+ else if(flags&NV_TABLE)
+ off = sftell(outfile);
+ else
+ sfseek(outfile,0L,SEEK_SET);
+ walk.out = outfile;
+ walk.indent = (flags&NV_EXPORT)?-1:Indent;
+ walk.nofollow = 0;
+ walk.noscope = noscope;
+ walk.array = 0;
+ walk.flags = flags;
+ genvalue(argv,name,0,&walk);
+ stakset(savptr,savtop);
+ shp->var_tree = save_tree;
+ if(!outfile)
+ return((char*)0);
+ sfputc(out,0);
+ sfseek(out,off,SEEK_SET);
+ return((char*)out->_data+off);
+}
+
+Namfun_t *nv_isvtree(Namval_t *np)
+{
+ if(np)
+ return(nv_hasdisc(np,&treedisc));
+ return(0);
+}
+
+/*
+ * get discipline for compound initializations
+ */
+char *nv_getvtree(register Namval_t *np, Namfun_t *fp)
+{
+ int flags=0, dsize=fp?fp->dsize:0;
+ for(; fp && fp->next; fp=fp->next)
+ {
+ if(fp->next->disc && (fp->next->disc->getnum || fp->next->disc->getval))
+ return(nv_getv(np,fp));
+ }
+ if(nv_isattr(np,NV_BINARY) && !nv_isattr(np,NV_RAW))
+ return(nv_getv(np,fp));
+ if(nv_isattr(np,NV_ARRAY) && !nv_type(np) && nv_arraychild(np,(Namval_t*)0,0)==np)
+ return(nv_getv(np,fp));
+ if(flags = nv_isattr(np,NV_EXPORT))
+ nv_offattr(np,NV_EXPORT);
+ if(flags |= nv_isattr(np,NV_TABLE))
+ nv_offattr(np,NV_TABLE);
+ if(dsize && (flags&NV_EXPORT))
+ return("()");
+ return(walk_tree(np,(Namval_t*)0,flags));
+}
+
+/*
+ * put discipline for compound initializations
+ */
+static void put_tree(register Namval_t *np, const char *val, int flags,Namfun_t *fp)
+{
+ struct Namarray *ap;
+ int nleft = 0;
+ if(!val && !fp->next && nv_isattr(np,NV_NOFREE))
+ return;
+ if(!nv_isattr(np,(NV_INTEGER|NV_BINARY)))
+ {
+ Shell_t *shp = sh_getinterp();
+ Namval_t *last_table = shp->last_table;
+ Dt_t *last_root = shp->last_root;
+ Namval_t *mp = val?nv_open(val,shp->var_tree,NV_VARNAME|NV_NOADD|NV_NOASSIGN|NV_ARRAY|NV_NOFAIL):0;
+ if(mp && nv_isvtree(mp))
+ {
+ shp->prev_table = shp->last_table;
+ shp->prev_root = shp->last_root;
+ shp->last_table = last_table;
+ shp->last_root = last_root;
+ if(!(flags&NV_APPEND))
+ walk_tree(np,(Namval_t*)0,(flags&NV_NOSCOPE)|1);
+ nv_clone(mp,np,NV_COMVAR);
+ return;
+ }
+ walk_tree(np,(Namval_t*)0,(flags&NV_NOSCOPE)|1);
+ }
+ nv_putv(np, val, flags,fp);
+ if(val && nv_isattr(np,(NV_INTEGER|NV_BINARY)))
+ return;
+ if(ap= nv_arrayptr(np))
+ nleft = array_elem(ap);
+ if(nleft==0)
+ {
+ fp = nv_stack(np,fp);
+ if(fp = nv_stack(np,NIL(Namfun_t*)))
+ free((void*)fp);
+ }
+}
+
+/*
+ * Insert discipline to cause $x to print current tree
+ */
+void nv_setvtree(register Namval_t *np)
+{
+ register Namfun_t *nfp;
+ if(sh.subshell)
+ sh_assignok(np,1);
+ if(nv_hasdisc(np, &treedisc))
+ return;
+ nfp = newof(NIL(void*),Namfun_t,1,0);
+ nfp->disc = &treedisc;
+ nfp->dsize = sizeof(Namfun_t);
+ nv_stack(np, nfp);
+}
+
diff --git a/src/cmd/ksh93/sh/nvtype.c b/src/cmd/ksh93/sh/nvtype.c
new file mode 100644
index 0000000..3b7f34e
--- /dev/null
+++ b/src/cmd/ksh93/sh/nvtype.c
@@ -0,0 +1,1709 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ */
+#include "defs.h"
+#include "io.h"
+#include "variables.h"
+
+static const char sh_opttype[] =
+"[-1c?\n@(#)$Id: type (AT&T Labs Research) 2008-07-01 $\n]"
+USAGE_LICENSE
+"[+NAME?\f?\f - set the type of variables to \b\f?\f\b]"
+"[+DESCRIPTION?\b\f?\f\b sets the type on each of the variables specified "
+ "by \aname\a to \b\f?\f\b. If \b=\b\avalue\a is specified, "
+ "the variable \aname\a is set to \avalue\a before the variable "
+ "is converted to \b\f?\f\b.]"
+"[+?If no \aname\as are specified then the names and values of all "
+ "variables of this type are written to standard output.]"
+"[+?\b\f?\f\b is built-in to the shell as a declaration command so that "
+ "field splitting and pathname expansion are not performed on "
+ "the arguments. Tilde expansion occurs on \avalue\a.]"
+"[r?Enables readonly. Once enabled, the value cannot be changed or unset.]"
+"[a]:?[type?Indexed array. Each \aname\a will converted to an index "
+ "array of type \b\f?\f\b. If a variable already exists, the current "
+ "value will become index \b0\b. If \b[\b\atype\a\b]]\b is "
+ "specified, each subscript is interpreted as a value of enumeration "
+ "type \atype\a.]"
+"[A?Associative array. Each \aname\a will converted to an associate "
+ "array of type \b\f?\f\b. If a variable already exists, the current "
+ "value will become subscript \b0\b.]"
+"[h]:[string?Used within a type definition to provide a help string "
+ "for variable \aname\a. Otherwise, it is ignored.]"
+"[S?Used with a type definition to indicate that the variable is shared by "
+ "each instance of the type. When used inside a function defined "
+ "with the \bfunction\b reserved word, the specified variables "
+ "will have function static scope. Otherwise, the variable is "
+ "unset prior to processing the assignment list.]"
+"[+DETAILS]\ftypes\f"
+"\n"
+"\n[name[=value]...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+
+"[+SEE ALSO?\fother\f \breadonly\b(1), \btypeset\b(1)]"
+;
+
+typedef struct Namtype Namtype_t;
+typedef struct Namchld
+{
+ Namfun_t fun;
+ Namtype_t *ptype;
+ Namtype_t *ttype;
+} Namchld_t;
+
+struct Namtype
+{
+ Namfun_t fun;
+ Shell_t *sh;
+ Namval_t *np;
+ Namval_t *parent;
+ Namval_t *bp;
+ Namval_t *cp;
+#if SHOPT_NAMESPACE
+ Namval_t *nsp;
+#endif /* SHOPT_NAMESPACE */
+ char *nodes;
+ char *data;
+ Namchld_t childfun;
+ int numnodes;
+ char **names;
+ size_t dsize;
+ short strsize;
+ unsigned short ndisc;
+ unsigned short current;
+ unsigned short nref;
+};
+
+#if 0
+struct type
+{
+ Namtype_t hdr;
+ unsigned short ndisc;
+ unsigned short current;
+ unsigned short nref;
+};
+#endif
+
+typedef struct
+{
+ char _cSfdouble_t;
+ Sfdouble_t _dSfdouble_t;
+ char _cdouble;
+ double _ddouble;
+ char _cfloat;
+ float _dfloat;
+ char _cSflong_t;
+ Sflong_t _dSflong_t;
+ char _clong;
+ long _dlong;
+ char _cshort;
+ short _dshort;
+ char _cpointer;
+ char *_dpointer;
+} _Align_;
+
+#define alignof(t) ((char*)&((_Align_*)0)->_d##t-(char*)&((_Align_*)0)->_c##t)
+
+static void put_type(Namval_t*, const char*, int, Namfun_t*);
+static Namval_t* create_type(Namval_t*, const char*, int, Namfun_t*);
+static Namfun_t* clone_type(Namval_t*, Namval_t*, int, Namfun_t*);
+static Namval_t* next_type(Namval_t*, Dt_t*, Namfun_t*);
+
+static const Namdisc_t type_disc =
+{
+ sizeof(Namtype_t),
+ put_type,
+ 0,
+ 0,
+ 0,
+ create_type,
+ clone_type,
+ 0,
+ next_type,
+ 0,
+#if 0
+ read_type
+#endif
+};
+
+size_t nv_datasize(Namval_t *np, size_t *offset)
+{
+ size_t s=0, a=0;
+ if(nv_isattr(np,NV_INTEGER))
+ {
+ if(nv_isattr(np,NV_DOUBLE)==NV_DOUBLE)
+ {
+ if(nv_isattr(np, NV_LONG))
+ {
+ a = alignof(Sfdouble_t);
+ s = sizeof(Sfdouble_t);
+ }
+ else if(nv_isattr(np, NV_SHORT))
+ {
+ a = alignof(float);
+ s = sizeof(float);
+ }
+ else
+ {
+ a = alignof(double);
+ s = sizeof(double);
+ }
+ }
+ else
+ {
+ if(nv_isattr(np, NV_LONG))
+ {
+ a = alignof(Sflong_t);
+ s = sizeof(Sflong_t);
+ }
+ else if(nv_isattr(np, NV_SHORT))
+ {
+ a = alignof(short);
+ s = sizeof(short);
+ }
+ else
+ {
+ a = alignof(long);
+ s = sizeof(long);
+ }
+ }
+ }
+ else if(nv_isattr(np, NV_BINARY) || nv_isattr(np,NV_LJUST|NV_RJUST|NV_ZFILL))
+ s = nv_size(np);
+ else
+ {
+ a = alignof(pointer);
+ s = nv_size(np);
+ }
+ if(a>1 && offset)
+ *offset = a*((*offset +a-1)/a);
+ return(s);
+}
+
+static char *name_chtype(Namval_t *np, Namfun_t *fp)
+{
+ Namchld_t *pp = (Namchld_t*)fp;
+ char *cp, *sub;
+ Namval_t *tp = sh.last_table;
+ Namval_t *nq = pp->ptype->np;
+ Namarr_t *ap;
+ if(nv_isattr(np,NV_REF|NV_TAGGED)==(NV_REF|NV_TAGGED))
+ sh.last_table = 0;
+ cp = nv_name(nq);
+ if((ap = nv_arrayptr(nq)) && !(ap->nelem&ARRAY_UNDEF) && (sub= nv_getsub(nq)))
+ sfprintf(sh.strbuf,"%s[%s].%s",cp,sub,np->nvname);
+ else
+ sfprintf(sh.strbuf,"%s.%s",cp,np->nvname);
+#if SHOPT_FIXEDARRAY
+ if((ap=nv_arrayptr(np)) && ap->fixed)
+ nv_arrfixed(np,sh.strbuf,1,(char*)0);
+#endif /* SHOPT_FIXEDARRAY */
+ sh.last_table = tp;
+ return(sfstruse(sh.strbuf));
+}
+
+static void put_chtype(Namval_t* np, const char* val, int flag, Namfun_t* fp)
+{
+ if(!val && nv_isattr(np,NV_REF))
+ return;
+ nv_putv(np,val,flag,fp);
+ if(!val)
+ {
+ Namchld_t *pp = (Namchld_t*)fp;
+ size_t dsize=0,offset = (char*)np-(char*)pp->ptype;
+ Namval_t *mp = (Namval_t*)((char*)pp->ttype+offset);
+ dsize = nv_datasize(mp,&dsize);
+ if(mp->nvalue.cp >= pp->ttype->data && mp->nvalue.cp < (char*)pp+pp->ttype->fun.dsize)
+ {
+ np->nvalue.cp = pp->ptype->data + (mp->nvalue.cp-pp->ptype->data);
+ if(np->nvalue.cp!=mp->nvalue.cp)
+ memcpy((char*)np->nvalue.cp,mp->nvalue.cp,dsize);
+ }
+ else if(!nv_isarray(mp) && mp->nvalue.cp)
+ {
+ np->nvalue.cp = mp->nvalue.cp;
+ nv_onattr(np,NV_NOFREE);
+ }
+ np->nvsize = mp->nvsize;
+ np->nvflag = mp->nvflag&~NV_RDONLY;
+ }
+}
+
+static Namfun_t *clone_chtype(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ if(flags&NV_NODISC)
+ return(0);
+ return(nv_clone_disc(fp,flags));
+}
+
+static const Namdisc_t chtype_disc =
+{
+ sizeof(Namchld_t),
+ put_chtype,
+ 0,
+ 0,
+ 0,
+ 0,
+ clone_chtype,
+ name_chtype
+};
+
+static Namval_t *findref(void *nodes, int n)
+{
+ Namval_t *tp,*np = nv_namptr(nodes,n);
+ char *name = np->nvname;
+ int i=n, len= strrchr(name,'.')-name;
+ Namtype_t *pp;
+ while(--i>0)
+ {
+ np = nv_namptr(nodes,i);
+ if(np->nvname[len]==0)
+ {
+ tp = nv_type(np);
+ pp = (Namtype_t*)nv_hasdisc(tp,&type_disc);
+ return(nv_namptr(pp->nodes,n-i-1));
+ }
+ }
+ return(0);
+}
+
+static int fixnode(Namtype_t *dp, Namtype_t *pp, int i, struct Namref *nrp,int flag)
+{
+ Namval_t *nq = nv_namptr(dp->nodes,i);
+ Namfun_t *fp;
+ if(fp=nv_hasdisc(nq,&chtype_disc))
+ nv_disc(nq, fp, NV_POP);
+ if(nv_isattr(nq,NV_REF))
+ {
+ nq->nvalue.nrp = nrp++;
+ nv_setsize(nq,0);
+ if(strchr(nq->nvname,'.'))
+ nq->nvalue.nrp->np = findref(dp->nodes,i);
+ else
+ nq->nvalue.nrp->np = nv_namptr(pp->childfun.ttype->nodes,i);
+ nq->nvalue.nrp->root = sh.last_root;
+ nq->nvalue.nrp->table = pp->np;
+ nq ->nvflag = NV_REF|NV_NOFREE|NV_MINIMAL;
+ return(1);
+ }
+ if(nq->nvalue.cp || nq->nvfun)
+ {
+ const char *data = nq->nvalue.cp;
+ if(nq->nvfun)
+ {
+ Namval_t *np = nv_namptr(pp->nodes,i);
+ if(nv_isarray(nq))
+ nq->nvalue.cp = 0;
+ nq->nvfun = 0;
+ if(nv_isarray(nq) && ((flag&NV_IARRAY) || nv_type(np)))
+ clone_all_disc(np,nq,flag&~NV_TYPE);
+ else
+ clone_all_disc(np,nq,flag);
+ if(fp)
+ nv_disc(np, fp, NV_LAST);
+ }
+#if 0
+ if(nq->nvalue.cp >= pp->data && nq->nvalue.cp < (char*)pp +pp->fun.dsize)
+ nq->nvalue.cp = dp->data + (nq->nvalue.cp-pp->data);
+#else
+ if(data >= pp->data && data < (char*)pp +pp->fun.dsize)
+ nq->nvalue.cp = dp->data + (data-pp->data);
+#endif
+ else if(!nq->nvfun && pp->childfun.ttype!=pp->childfun.ptype)
+ {
+ Namval_t *nr = nv_namptr( pp->childfun.ttype->nodes,i);
+ if(nr->nvalue.cp!=nq->nvalue.cp)
+ {
+ if(i=nv_size(nq))
+ {
+ const char *cp = nq->nvalue.cp;
+ nq->nvalue.cp = (char*)malloc(i);
+ memcpy((char*)nq->nvalue.cp,cp,i);
+ }
+ else
+ nq->nvalue.cp = strdup(nq->nvalue.cp);
+ nv_offattr(nq,NV_NOFREE);
+ }
+ }
+ else if(nq->nvalue.cp==Empty)
+ nv_offattr(nq,NV_NOFREE);
+
+ }
+ if(fp)
+ nv_disc(nq, &dp->childfun.fun, NV_LAST);
+ return(0);
+}
+
+static Namfun_t *clone_type(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ Namtype_t *dp, *pp=(Namtype_t*)fp;
+ register int i;
+ register Namval_t *nq, *nr;
+ size_t size = fp->dsize;
+ int save, offset=staktell();
+ char *cp;
+ Dt_t *root = sh.last_root;
+ Namval_t *last_table = sh.last_table;
+ struct Namref *nrp = 0;
+ Namarr_t *ap;
+ if(flags&NV_MOVE)
+ {
+ pp->np = mp;
+ pp->childfun.ptype = pp;
+ return(fp);
+ }
+ if(flags&NV_TYPE)
+ return(nv_clone_disc(fp,flags));
+ if(size==0 && (!fp->disc || (size=fp->disc->dsize)==0))
+ size = sizeof(Namfun_t);
+ dp = (Namtype_t*)malloc(size+pp->nref*sizeof(struct Namref));
+ if(pp->nref)
+ {
+ nrp = (struct Namref*)((char*)dp + size);
+ memset((void*)nrp,0,pp->nref*sizeof(struct Namref));
+ }
+ memcpy((void*)dp,(void*)pp,size);
+#if 0
+ dp->parent = nv_lastdict();
+#else
+ dp->parent = mp;
+#endif
+ dp->fun.nofree = (flags&NV_RDONLY?1:0);
+ dp->np = mp;
+ dp->childfun.ptype = dp;
+#if 0
+ dp->childfun.ttype = (Namtype_t*)nv_hasdisc(dp->fun.type,&type_disc);
+#endif
+ dp->nodes = (char*)(dp+1);
+ dp->data = (char*)dp + (pp->data - (char*)pp);
+ for(i=dp->numnodes; --i >= 0; )
+ {
+ nq = nv_namptr(dp->nodes,i);
+ if(fixnode(dp,pp,i,nrp,NV_TYPE|(flags&NV_IARRAY)))
+ {
+ nrp++;
+ nq = nq->nvalue.nrp->np;
+ }
+ if(flags==(NV_NOFREE|NV_ARRAY))
+ continue;
+ if(nq->nvalue.cp || !nv_isvtree(nq) || nv_isattr(nq,NV_RDONLY))
+ {
+ /* see if default value has been overwritten */
+ if(!mp->nvname)
+ continue;
+ sh.last_table = last_table;
+ if(pp->strsize<0)
+ cp = nv_name(np);
+ else
+ cp = nv_name(mp);
+ stakputs(cp);
+ stakputc('.');
+ stakputs(nq->nvname);
+ stakputc(0);
+ root = nv_dict(mp);
+ save = fp->nofree;
+ fp->nofree = 1;
+ nr = nv_create(stakptr(offset),root,NV_VARNAME|NV_NOADD,fp);
+ fp->nofree = save;
+ stakseek(offset);
+ if(nr)
+ {
+ if(nv_isattr(nq,NV_RDONLY) && (nq->nvalue.cp || nv_isattr(nq,NV_INTEGER)))
+ errormsg(SH_DICT,ERROR_exit(1),e_readonly, nq->nvname);
+ if(nv_isref(nq))
+ nq = nv_refnode(nq);
+ if((size = nv_datasize(nr,(size_t*)0)) && size==nv_datasize(nq,(size_t*)0))
+ memcpy((char*)nq->nvalue.cp,nr->nvalue.cp,size);
+ else if(ap=nv_arrayptr(nr))
+ {
+ nv_putsub(nr,NIL(char*),ARRAY_SCAN|ARRAY_NOSCOPE);
+ do
+ {
+ if(array_assoc(ap))
+ cp = (char*)((*ap->fun)(nr,NIL(char*),NV_ANAME));
+ else
+ cp = nv_getsub(nr);
+ nv_putsub(nq,cp,ARRAY_ADD|ARRAY_NOSCOPE);
+ if(array_assoc(ap))
+ {
+ Namval_t *mp = (Namval_t*)((*ap->fun)(nr,NIL(char*),NV_ACURRENT));
+ Namval_t *mq = (Namval_t*)((*ap->fun)(nq,NIL(char*),NV_ACURRENT));
+ nv_clone(mp,mq,NV_MOVE);
+ ap->nelem--;
+ nv_delete(mp,ap->table,0);
+ }
+ else
+ {
+ cp = nv_getval(nr);
+ nv_putval(nq,cp,0);
+ }
+ }
+ while(nv_nextsub(nr));
+ }
+ else
+ nv_putval(nq,nv_getval(nr),NV_RDONLY);
+#if SHOPT_TYPEDEF
+ if(sh.mktype)
+ nv_addnode(nr,1);
+#endif /* SHOPT_TYPEDEF */
+ if(pp->strsize<0)
+ continue;
+ _nv_unset(nr,0);
+ if(!nv_isattr(nr,NV_MINIMAL))
+ nv_delete(nr,sh.last_root,0);
+ }
+ else if(nv_isattr(nq,NV_RDONLY) && !nq->nvalue.cp && !nv_isattr(nq,NV_INTEGER))
+ errormsg(SH_DICT,ERROR_exit(1),e_required,nq->nvname,nv_name(mp));
+ }
+ }
+ if(nv_isattr(mp,NV_BINARY))
+ mp->nvalue.cp = dp->data;
+ if(pp->strsize<0)
+ dp->strsize = -pp->strsize;
+ return(&dp->fun);
+}
+
+
+/*
+ * return Namval_t* corresponding to child <name> in <np>
+ */
+static Namval_t *create_type(Namval_t *np,const char *name,int flag,Namfun_t *fp)
+{
+ Namtype_t *dp = (Namtype_t*)fp;
+ register const char *cp=name;
+ register int i=0,n;
+ Namval_t *nq=0;
+ if(!name)
+ return(dp->parent);
+ while((n=*cp++) && n != '=' && n != '+' && n!='[');
+ n = (cp-1) -name;
+ if(dp->numnodes && dp->strsize<0)
+ {
+ char *base = (char*)np-sizeof(Dtlink_t);
+ int m=strlen(np->nvname);
+ while((nq=nv_namptr(base,++i)) && memcmp(nq->nvname,np->nvname,m)==0)
+ {
+ if(nq->nvname[m]=='.' && memcmp(name,&nq->nvname[m+1],n)==0 && nq->nvname[m+n+1]==0)
+ goto found;
+ }
+ nq = 0;
+ }
+ else for(i=0; i < dp->numnodes; i++)
+ {
+ nq = nv_namptr(dp->nodes,i);
+ if((n==0||memcmp(name,nq->nvname,n)==0) && nq->nvname[n]==0)
+ {
+ while(nv_isref(nq))
+ nq = nq->nvalue.nrp->np;
+ goto found;
+ }
+ }
+ nq = 0;
+found:
+ if(nq)
+ {
+ fp->last = (char*)&name[n];
+ sh.last_table = dp->parent;
+ }
+ else
+ {
+ if(name[n]!='=') for(i=0; i < dp->ndisc; i++)
+ {
+ if((memcmp(name,dp->names[i],n)==0) && dp->names[i][n]==0)
+ return(nq);
+ }
+ errormsg(SH_DICT,ERROR_exit(1),e_notelem,n,name,nv_name(np));
+ }
+ return(nq);
+}
+
+static void put_type(Namval_t* np, const char* val, int flag, Namfun_t* fp)
+{
+ Namval_t *nq;
+ if(val && (nq=nv_open(val,sh.var_tree,NV_VARNAME|NV_ARRAY|NV_NOADD|NV_NOFAIL)))
+ {
+ Namfun_t *pp;
+ if((pp=nv_hasdisc(nq,fp->disc)) && pp->type==fp->type)
+
+ {
+ if(!nq->nvenv)
+ flag |= NV_EXPORT;
+ _nv_unset(np, flag);
+ nv_clone(nq,np,NV_IARRAY);
+ return;
+ }
+ }
+ nv_putv(np,val,flag,fp);
+ if(!val)
+ {
+ Namtype_t *dp = (Namtype_t*)fp;
+ Namval_t *nq;
+ Namarr_t *ap;
+ int i;
+ if(nv_isarray(np) && (ap=nv_arrayptr(np)) && ap->nelem>0)
+ return;
+ for(i=0; i < dp->numnodes; i++)
+ {
+ nq = nv_namptr(dp->nodes,i);
+ if(ap=nv_arrayptr(nq))
+ ap->nelem |= ARRAY_UNDEF;
+ if(!nv_hasdisc(nq,&type_disc))
+ _nv_unset(nq,flag|NV_TYPE|nv_isattr(nq,NV_RDONLY));
+ }
+ nv_disc(np,fp,NV_POP);
+ if(!(fp->nofree&1))
+ free((void*)fp);
+ }
+}
+
+static Namval_t *next_type(register Namval_t* np, Dt_t *root,Namfun_t *fp)
+{
+ Namtype_t *dp = (Namtype_t*)fp;
+ if(!root)
+ {
+ Namarr_t *ap = nv_arrayptr(np);
+ if(ap && (ap->nelem&ARRAY_UNDEF))
+ nv_putsub(np,(char*)0,ARRAY_SCAN);
+ dp->current = 0;
+ }
+ else if(++dp->current>=dp->numnodes)
+ return(0);
+ return(nv_namptr(dp->nodes,dp->current));
+}
+
+static Namfun_t *clone_inttype(Namval_t* np, Namval_t *mp, int flags, Namfun_t *fp)
+{
+ Namfun_t *pp= (Namfun_t*)malloc(fp->dsize);
+ memcpy((void*)pp, (void*)fp, fp->dsize);
+ fp->nofree &= ~1;
+ if(nv_isattr(mp,NV_NOFREE) && mp->nvalue.cp)
+ memcpy((void*)mp->nvalue.cp,np->nvalue.cp, fp->dsize-sizeof(*fp));
+ else
+ mp->nvalue.cp = (char*)(fp+1);
+ if(!nv_isattr(mp,NV_MINIMAL))
+ mp->nvenv = 0;
+ nv_offattr(mp,NV_RDONLY);
+ return(pp);
+}
+
+static int typeinfo(Opt_t* op, Sfio_t *out, const char *str, Optdisc_t *fp)
+{
+ char *cp,**help,buffer[256];
+ Namtype_t *dp;
+ Namval_t *np,*nq,*tp;
+ int n, i, offset=staktell();
+ Sfio_t *sp;
+
+ np = *(Namval_t**)(fp+1);
+ stakputs(NV_CLASS);
+ stakputc('.');
+ stakputs(np->nvname);
+ stakputc(0);
+ np = nv_open(cp=stakptr(offset), sh.var_tree, NV_NOADD|NV_VARNAME);
+ stakseek(offset);
+ if(!np)
+ {
+ sfprintf(sfstderr,"%s: no such variable\n",cp);
+ return(-1);
+ }
+ if(!(dp=(Namtype_t*)nv_hasdisc(np,&type_disc)))
+ {
+ Namfun_t *fp;
+ for(fp=np->nvfun;fp;fp=fp->next)
+ {
+ if(fp->disc && fp->disc->clonef==clone_inttype)
+ break;
+ }
+ if(!fp)
+ {
+ sfprintf(sfstderr,"%s: not a type\n",np->nvname);
+ return(-1);
+ }
+ if(strcmp(str,"other")==0)
+ return(0);
+ tp = fp->type;
+ nv_offattr(np,NV_RDONLY);
+ fp->type = 0;
+ if(np->nvenv)
+ sfprintf(out,"[+?\b%s\b is a %s.]\n", tp->nvname, np->nvenv);
+ cp = (char*)out->_next;
+ sfprintf(out,"[+?\b%s\b is a %n ", tp->nvname, &i);
+ nv_attribute(np,out,(char*)0, 1);
+ if(cp[i+1]=='i')
+ cp[i-1]='n';
+ fp->type = tp;
+ nv_onattr(np,NV_RDONLY);
+ sfprintf(out," with default value \b%s\b.]",nv_getval(np));
+ return(0);
+ }
+ if(strcmp(str,"other")==0)
+ {
+ Nambfun_t *bp;
+ if(bp=(Nambfun_t*)nv_hasdisc(np,nv_discfun(NV_DCADD)))
+ {
+ for(i=0; i < bp->num; i++)
+ {
+ if(nv_isattr(bp->bltins[i],NV_OPTGET))
+ sfprintf(out,"\b%s.%s\b(3), ",np->nvname,bp->bnames[i]);
+ }
+ }
+ return(0);
+ }
+ help = &dp->names[dp->ndisc];
+ sp = sfnew((Sfio_t*)0,buffer,sizeof(buffer),-1,SF_STRING|SF_WRITE);
+ sfprintf(out,"[+?\b%s\b defines the following fields:]{\n",np->nvname);
+ for(i=0; i < dp->numnodes; i++)
+ {
+ nq = nv_namptr(dp->nodes,i);
+ if(tp=nv_type(nq))
+ {
+ Namfun_t *pp = nv_hasdisc(nq,&type_disc);
+ sfprintf(out,"\t[+%s?%s.\n",nq->nvname,tp->nvname);
+ n = strlen(nq->nvname);
+ while((cp=nv_namptr(dp->nodes,i+1)->nvname) && memcmp(cp,nq->nvname,n)==0 && cp[n]=='.')
+ i++;
+ }
+ else
+ {
+ sfseek(sp,(Sfoff_t)0, SEEK_SET);
+ nv_attribute(nq,sp,(char*)0,1);
+ cp = 0;
+ if(!nv_isattr(nq,NV_REF))
+ cp = sh_fmtq(nv_getval(nq));
+ sfputc(sp,0);
+ for(n=strlen(buffer); n>0 && buffer[n-1]==' '; n--);
+ buffer[n] = 0;
+ if(cp)
+ sfprintf(out,"\t[+%s?%s, default value is %s.\n",nq->nvname,*buffer?buffer:"string",cp);
+ else
+ sfprintf(out,"\t[+%s?%s.\n",nq->nvname,*buffer?buffer:"string");
+ }
+ if(help[i])
+ sfprintf(out," %s.",help[i]);
+ sfputc(out,']');
+ }
+ sfprintf(out,"}\n");
+ if(dp->ndisc>0)
+ {
+ stakseek(offset);
+ stakputs(NV_CLASS);
+ stakputc('.');
+ stakputs(np->nvname);
+ stakputc('.');
+ n = staktell();
+ sfprintf(out,"[+?\b%s\b defines the following discipline functions:]{\n",np->nvname);
+ for(i=0; i < dp->ndisc; i++)
+ {
+ stakputs(dp->names[i]);
+ stakputc(0);
+ cp = 0;
+ if((nq = nv_search(stakptr(offset),sh.fun_tree,0)) && nq->nvalue.cp)
+ cp = nq->nvalue.rp->help;
+ if(nq && nv_isattr(nq,NV_STATICF))
+ sfprintf(out,"\t[+%s?:static:%s]\n",dp->names[i],cp?cp:Empty);
+ else
+ sfprintf(out,"\t[+%s?%s]\n",dp->names[i],cp?cp:Empty);
+ if(cp)
+ sfputc(out,'.');
+ stakseek(n);
+ }
+ sfprintf(out,"}\n");
+ }
+ stakseek(offset);
+ sfclose(sp);
+ return(0);
+}
+
+static int std_disc(Namval_t *mp, Namtype_t *pp)
+{
+ register const char *sp, *cp = strrchr(mp->nvname,'.');
+ register const char **argv;
+ register int i;
+ Namval_t *np=0,*nq;
+ if(cp)
+ cp++;
+ else
+ cp = mp->nvname;
+ if(strcmp(cp,"create")==0)
+ {
+ if(pp)
+ pp->cp = mp;
+ return(0);
+ }
+ for(argv=nv_discnames; sp=*argv; argv++)
+ {
+ if(strcmp(cp,sp)==0)
+ {
+ if(!pp)
+ return(1);
+ goto found;
+ }
+ }
+ return(0);
+found:
+ if(memcmp(sp=mp->nvname,NV_CLASS,sizeof(NV_CLASS)-1)==0)
+ sp += sizeof(NV_CLASS);
+ sp += strlen(pp->fun.type->nvname)+1;
+ if(sp == cp)
+ np = pp->fun.type;
+ else for(i=1; i < pp->numnodes; i++)
+ {
+ nq = nv_namptr(pp->nodes,i);
+ if(memcmp(nq->nvname, sp, cp-sp-1)==0)
+ {
+ np = nq;
+ break;
+ }
+ }
+ if(np)
+ {
+ nv_onattr(mp,NV_NOFREE);
+ if(!nv_setdisc(np,cp, mp, (Namfun_t*)np))
+ sfprintf(sfstderr," nvsetdisc failed name=%s sp=%s cp=%s\n",np->nvname,sp,cp);
+ }
+ else
+ sfprintf(sfstderr,"can't set discipline %s cp=%s \n",sp,cp);
+ return(1);
+}
+
+
+void nv_addtype(Namval_t *np, const char *optstr, Optdisc_t *op, size_t optsz)
+{
+ Namdecl_t *cp = newof((Namdecl_t*)0,Namdecl_t,1,optsz);
+ Optdisc_t *dp = (Optdisc_t*)(cp+1);
+ Shell_t *shp = sh_getinterp();
+ Namval_t *mp,*bp;
+ char *name;
+ if(optstr)
+ cp->optstring = optstr;
+ else
+ cp->optstring = sh_opttype;
+ memcpy((void*)dp,(void*)op, optsz);
+ cp->optinfof = (void*)dp;
+ cp->tp = np;
+ mp = nv_search("typeset",shp->bltin_tree,0);
+ if(name=strrchr(np->nvname,'.'))
+ name++;
+ else
+ name = np->nvname;
+#if SHOPT_NAMESPACE
+ if(bp=(Namval_t*)shp->namespace)
+ {
+ Namtype_t *tp = (Namtype_t*)nv_hasdisc(np, &type_disc);
+ if(tp)
+ tp->nsp = bp;
+ if(!shp->strbuf2)
+ shp->strbuf2 = sfstropen();
+ sfprintf(shp->strbuf2,"%s.%s%c\n",nv_name(bp)+1,name,0);
+ name = sfstruse(shp->strbuf2);
+ }
+#endif /* SHOPT_NAMESPACE */
+ if((bp=nv_search(name,shp->fun_tree,NV_NOSCOPE)) && !bp->nvalue.ip)
+ nv_delete(bp,shp->fun_tree,0);
+ bp = sh_addbuiltin(name, (Shbltin_f)mp->nvalue.bfp, (void*)cp);
+ nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
+ nv_onattr(np, NV_RDONLY);
+}
+
+void nv_newtype(Namval_t *mp)
+{
+ struct {
+ Optdisc_t opt;
+ Namval_t *np;
+ } optdisc;
+ memset(&optdisc,0,sizeof(optdisc));
+ optdisc.opt.infof = typeinfo;
+ optdisc.np = mp;
+ nv_addtype(mp,sh_opttype, &optdisc.opt, sizeof(optdisc));
+}
+
+/*
+ * This function creates a type out of the <numnodes> nodes in the
+ * array <nodes>. The first node is the name for the type
+ */
+Namval_t *nv_mktype(Namval_t **nodes, int numnodes)
+{
+ Namval_t *mp=nodes[0], *bp=0, *np, *nq, **mnodes=nodes;
+ int i,j,k,m,n,nd=0,nref=0,iref=0,inherit=0;
+ int size=sizeof(NV_DATA), dsize=0, nnodes;
+ size_t offset=0;
+ char *name=0, *cp, *sp, **help;
+ Namtype_t *pp,*qp=0,*dp,*tp;
+ Dt_t *root = nv_dict(mp);
+ struct Namref *nrp = 0;
+ Namfun_t *fp;
+ m = strlen(mp->nvname)+1;
+ if(numnodes < 2)
+ {
+ cp = nodes[0]->nvname;
+ _nv_unset(nodes[0],NV_RDONLY);
+ errormsg(SH_DICT,ERROR_exit(1),e_badtypedef,cp);
+ }
+ for(nnodes=1,i=1; i <numnodes; i++)
+ {
+ np=nodes[i];
+ if(is_afunction(np))
+ {
+ if(!std_disc(np, (Namtype_t*)0))
+ {
+ size += strlen(np->nvname+m)+1;
+ if(memcmp(np->nvname,NV_CLASS,sizeof(NV_CLASS)-1)==0)
+ size -= sizeof(NV_CLASS);
+ nd++;
+ }
+ continue;
+ }
+ if(nv_isattr(np,NV_REF))
+ iref++;
+ if(np->nvenv)
+ size += strlen((char*)np->nvenv)+1;
+ if(strcmp(&np->nvname[m],NV_DATA)==0 && !nv_type(np))
+ continue;
+ if(qp)
+ { /* delete duplicates */
+ for(j=0; j < qp->numnodes;j++)
+ {
+ nq = nv_namptr(qp->nodes,j);
+ if(strcmp(nq->nvname,&np->nvname[m])==0)
+ break;
+ }
+ if(j < qp->numnodes)
+ continue;
+ }
+ nnodes++;
+ if(name && memcmp(&name[m],&np->nvname[m],n)==0 && np->nvname[m+n]=='.')
+ offset -= sizeof(char*);
+ dsize = nv_datasize(np,&offset);
+ if(!nv_isarray(np) && (dp=(Namtype_t*)nv_hasdisc(np, &type_disc)))
+ {
+ nnodes += dp->numnodes;
+ if((n=dp->strsize)<0)
+ n = -n;
+ iref = nref += dp->nref;
+ if(np->nvname[m]=='_' && np->nvname[m+1]==0 && (bp=nv_type(np)))
+ {
+ qp = dp;
+ nd = dp->ndisc;
+ nnodes = dp->numnodes;
+ offset = 0;
+ dsize = nv_size(np);
+ size += n;
+ }
+ else
+ size += n + dp->numnodes*(strlen(&np->nvname[m])+1);
+ n = strlen(np->nvname);
+ while((i+1) < numnodes && (cp=nodes[i+1]->nvname) && memcmp(cp,np->nvname,n)==0 && cp[n]=='.')
+ i++;
+ }
+ else if(nv_isattr(np,NV_REF))
+ nref++;
+ offset += (dsize?dsize:4);
+ size += (n=strlen(name=np->nvname)-m+1);
+ }
+ offset = roundof(offset,sizeof(char*));
+ nv_setsize(mp,offset);
+ if(nd)
+ nd++;
+ k = roundof(sizeof(Namtype_t),sizeof(Sfdouble_t)) - sizeof(Namtype_t);
+ pp = newof(NiL, Namtype_t, 1, nnodes*NV_MINSZ + offset + size + (nnodes+nd)*sizeof(char*) + iref*sizeof(struct Namref)+k);
+ pp->fun.dsize = sizeof(Namtype_t)+nnodes*NV_MINSZ +offset+k;
+ pp->fun.type = mp;
+ pp->parent = nv_lastdict();
+ pp->np = mp;
+ pp->bp = bp;
+ pp->childfun.fun.disc = &chtype_disc;
+ pp->childfun.fun.nofree = 1;
+ pp->childfun.ttype = pp;
+ pp->childfun.ptype = pp;
+ pp->fun.disc = &type_disc;
+ pp->nodes = (char*)(pp+1);
+ pp->numnodes = nnodes;
+ pp->data = pp->nodes + nnodes*NV_MINSZ +k;
+ pp->dsize = offset;
+ nrp = (struct Namref*)(pp->data+offset);
+ pp->names = (char**)(nrp+iref);
+ help = &pp->names[nd];
+ pp->strsize = size;
+ cp = (char*)&pp->names[nd+nnodes];
+ if(qp)
+ mnodes = newof(NiL, Namval_t*, nd+1, 0);
+ nd = 0;
+ nq = nv_namptr(pp->nodes,0);
+ nq->nvname = cp;
+ nv_onattr(nq,NV_MINIMAL);
+ cp = strcopy(cp,NV_DATA);
+ *cp++ = 0;
+ for(name=0, offset=0, k=i=1; i < numnodes; i++)
+ {
+ np=nodes[i];
+ if(is_afunction(np))
+ {
+ sp = np->nvname+m;
+ if(memcmp(np->nvname,NV_CLASS,sizeof(NV_CLASS)-1)==0)
+ sp += sizeof(NV_CLASS);
+ if(!std_disc(np, pp))
+ {
+ /* see if discipline already defined */
+ for(j=0; j< nd; j++)
+ {
+ if(strcmp(sp,pp->names[j])==0)
+ {
+ mnodes[j] = nodes[i];
+ break;
+ }
+ }
+ if(j>=nd)
+ {
+ pp->names[nd] = cp;
+ mnodes[nd++] = nodes[i];
+ cp = strcopy(cp,sp);
+ *cp++ = 0;
+ }
+ nv_onattr(mnodes[j],NV_NOFREE);
+ }
+ continue;
+ }
+ if(inherit)
+ {
+ for(j=0; j < k ; j++)
+ {
+ nq = nv_namptr(pp->nodes,j);
+ if(strcmp(nq->nvname,&np->nvname[m])==0)
+ break;
+ }
+ if(j < k)
+ {
+ sp = nv_getval(np);
+ if(nv_isvtree(np))
+ sfprintf(sfstderr,"initialization not implemented\n");
+ else if(sp)
+ nv_putval(nq,sp,0);
+ goto skip;
+ }
+ }
+ if(strcmp(&np->nvname[m],NV_DATA)==0 && !nv_type(np))
+ {
+ char *val=nv_getval(np);
+ nq = nv_namptr(pp->nodes,0);
+ nq->nvfun = 0;
+ nv_putval(nq,(val?val:0),nv_isattr(np,~(NV_IMPORT|NV_EXPORT|NV_ARRAY)));
+ nq->nvflag = np->nvflag|NV_NOFREE|NV_MINIMAL;
+ goto skip;
+ }
+ if(qp)
+ {
+ Nambfun_t *bp;
+ dp = (Namtype_t*)nv_hasdisc(nv_type(np), &type_disc);
+ memcpy(pp->nodes,dp->nodes,dp->numnodes*NV_MINSZ);
+ offset = nv_size(np);
+ memcpy(pp->data,dp->data,offset);
+ for(k=0;k < dp->numnodes; k++)
+ {
+ Namval_t *nr = nv_namptr(qp->nodes,k);
+ nq = nv_namptr(pp->nodes,k);
+ if(fixnode(pp,dp,k,nrp,0))
+ {
+ nrp++;
+ nq = nq->nvalue.nrp->np;
+ }
+ if(!nv_isattr(nr,NV_REF) && !nv_hasdisc(nr,&type_disc))
+ {
+ if(nr->nvsize)
+ memcpy((char*)nq->nvalue.cp,nr->nvalue.cp,size=nv_datasize(nr,(size_t*)0));
+ else
+ {
+ nq->nvalue.cp = nr->nvalue.cp;
+ nv_onattr(nq,NV_NOFREE);
+ }
+ }
+ }
+ if(bp=(Nambfun_t*)nv_hasdisc(np,nv_discfun(NV_DCADD)))
+ {
+ for(j=0; j < bp->num; j++)
+ {
+ pp->names[nd++] = (char*)bp->bnames[j];
+ mnodes[j] = bp->bltins[j];
+ }
+ }
+ qp = 0;
+ inherit=1;
+ goto skip;
+ }
+ nq = nv_namptr(pp->nodes,k);
+ if(np->nvenv)
+ {
+ /* need to save the string pointer */
+ nv_offattr(np,NV_EXPORT);
+ help[k] = cp;
+ cp = strcopy(cp,np->nvenv);
+ j = *help[k];
+ if(islower(j))
+ *help[k] = toupper(j);
+ *cp++ = 0;
+ np->nvenv = 0;
+ }
+ nq->nvname = cp;
+ if(name && memcmp(name,&np->nvname[m],n)==0 && np->nvname[m+n]=='.')
+ offset -= sizeof(char*);
+ dsize = nv_datasize(np,&offset);
+ cp = strcopy(name=cp, &np->nvname[m]);
+ n = cp-name;
+ *cp++ = 0;
+ nq->nvsize = np->nvsize;
+ nq->nvflag = (np->nvflag&~(NV_IMPORT|NV_EXPORT))|NV_NOFREE|NV_MINIMAL;
+ if(dp = (Namtype_t*)nv_hasdisc(np, &type_disc))
+ {
+ int r,kfirst=k;
+ char *cname = &np->nvname[m];
+ /*
+ * If field is a type, mark the type by setting
+ * strsize<0. This changes create_type()
+ */
+ clone_all_disc(np,nq,NV_RDONLY);
+ if(nv_isarray(np))
+ {
+ nv_disc(nq, &pp->childfun.fun, NV_LAST);
+ k++;
+ goto skip;
+ }
+ if(fp=nv_hasdisc(nq,&chtype_disc))
+ nv_disc(nq, &pp->childfun.fun, NV_LAST);
+ if(tp = (Namtype_t*)nv_hasdisc(nq, &type_disc))
+ tp->strsize = -tp->strsize;
+else sfprintf(sfstderr,"tp==NULL\n");
+ for(r=0; r < dp->numnodes; r++)
+ {
+ Namval_t *nr = nv_namptr(dp->nodes,r);
+ nq = nv_namptr(pp->nodes,++k);
+ nq->nvname = cp;
+ dsize = nv_datasize(nr,&offset);
+ nq->nvflag = nr->nvflag;
+ if(nr->nvalue.cp)
+ {
+ Namchld_t *xp = (Namchld_t*)nv_hasdisc(nr,&chtype_disc);
+ if(xp && nr->nvalue.cp >= xp->ptype->data && nr->nvalue.cp < xp->ptype->data+xp->ptype->fun.dsize)
+ {
+ nq->nvalue.cp = pp->data+offset;
+ memcpy((char*)nq->nvalue.cp,nr->nvalue.cp,dsize);
+ nv_onattr(nq,NV_NOFREE);
+ }
+ else
+ nq->nvalue.cp = strdup(nr->nvalue.cp);
+ nv_disc(nq, &pp->childfun.fun, NV_LAST);
+ }
+ nq->nvsize = nr->nvsize;
+ offset += dsize;
+ if(*cname!='_' || cname[1])
+ {
+ cp = strcopy(cp,cname);
+ *cp++ = '.';
+ }
+ cp = strcopy(cp,nr->nvname);
+ *cp++ = 0;
+ }
+ while((i+1) < numnodes && (cname=&nodes[i+1]->nvname[m]) && memcmp(cname,&np->nvname[m],n)==0 && cname[n]=='.')
+ {
+ int j=kfirst;
+ nv_unset(np);
+ nv_delete(np,root,0);
+ np = nodes[++i];
+ while(j < k)
+ {
+ nq = nv_namptr(pp->nodes,++j);
+ if(strcmp(nq->nvname,cname)==0)
+ {
+ sfprintf(sfstderr,"%s found at k=%d\n",nq->nvname,k);
+ if(nq->nvalue.cp>=pp->data && nq->nvalue.cp< (char*)pp->names)
+ memcpy((char*)nq->nvalue.cp,np->nvalue.cp,nv_datasize(np,0));
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ j = nv_isattr(np,NV_NOFREE);
+ nq->nvfun = np->nvfun;
+ np->nvfun = 0;
+ nv_disc(nq, &pp->childfun.fun, NV_LAST);
+ if(nq->nvfun)
+ {
+ for(fp=nq->nvfun; fp; fp = fp->next)
+ fp->nofree |= 1;
+ }
+ nq->nvalue.cp = np->nvalue.cp;
+ if(dsize && (np->nvalue.cp || !nv_isarray(np)))
+ {
+ nq->nvalue.cp = pp->data+offset;
+ sp = (char*)np->nvalue.cp;
+ if(nv_isattr(np,NV_INT16P) ==NV_INT16)
+ {
+ sp= (char*)&np->nvalue;
+ nv_onattr(nq,NV_INT16P);
+ j = 1;
+ }
+ if(sp)
+ memcpy((char*)nq->nvalue.cp,sp,dsize);
+ else if(nv_isattr(np,NV_LJUST|NV_RJUST))
+ memset((char*)nq->nvalue.cp,' ',dsize);
+ if(!j)
+ free((void*)np->nvalue.cp);
+ }
+ if(!nq->nvalue.cp && nq->nvfun== &pp->childfun.fun)
+ nq->nvalue.cp = Empty;
+ np->nvalue.cp = 0;
+#if 0
+ offset += dsize;
+#else
+ offset += (dsize?dsize:4);
+#endif
+ }
+ k++;
+ skip:
+ if(!nv_isnull(np))
+ _nv_unset(np,0);
+ nv_delete(np,root,0);
+ }
+ pp->ndisc = nd;
+ pp->nref = nref;
+ if(k>1)
+ {
+ nv_setsize(mp,offset);
+ mp->nvalue.cp = pp->data;
+ nv_onattr(mp,NV_NOFREE|NV_BINARY|NV_RAW);
+ }
+ else if(!mp->nvalue.cp)
+ mp->nvalue.cp = Empty;
+ nv_disc(mp, &pp->fun, NV_LAST);
+ if(nd>0)
+ {
+ pp->names[nd] = 0;
+ nv_adddisc(mp, (const char**)pp->names, mnodes);
+ }
+ if(mnodes!=nodes)
+ free((void*)mnodes);
+ nv_newtype(mp);
+ return(mp);
+}
+
+Namval_t *nv_mkinttype(char *name, size_t size, int sign, const char *help, Namdisc_t *ep)
+{
+ Namval_t *mp;
+ Namfun_t *fp;
+ Namdisc_t *dp;
+ int offset=staktell();
+ stakputs(NV_CLASS);
+ stakputc('.');
+ stakputs(name);
+ stakputc(0);
+ mp = nv_open(stakptr(offset), sh.var_tree, NV_VARNAME);
+ stakseek(offset);
+ offset = size + sizeof(Namdisc_t);
+ fp = newof(NiL, Namfun_t, 1, offset);
+ fp->type = mp;
+ fp->nofree |= 1;
+ fp->dsize = sizeof(Namfun_t)+size;
+ dp = (Namdisc_t*)(fp+1);
+ if(ep)
+ *dp = *ep;
+ dp->clonef = clone_inttype;
+ fp->disc = dp;
+ mp->nvalue.cp = (char*)(fp+1) + sizeof(Namdisc_t);
+ nv_setsize(mp,10);
+ mp->nvenv = (char*)help;
+ nv_onattr(mp,NV_NOFREE|NV_RDONLY|NV_INTEGER|NV_EXPORT);
+ if(size==16)
+ nv_onattr(mp,NV_INT16P);
+ else if(size==64)
+ nv_onattr(mp,NV_INT64);
+ if(!sign)
+ nv_onattr(mp,NV_UNSIGN);
+ nv_disc(mp, fp, NV_LAST);
+ nv_newtype(mp);
+ return(mp);
+}
+
+void nv_typename(Namval_t *tp, Sfio_t *out)
+{
+ char *v,*cp;
+ Namtype_t *dp;
+ cp = nv_name(tp);
+ if(v=strrchr(cp,'.'))
+ cp = v+1;
+ if((dp = (Namtype_t*)nv_hasdisc(tp,&type_disc)) && dp->bp)
+ {
+ nv_typename(dp->bp,out);
+ sfprintf(out,"%s.%s",sfstruse(out),cp);
+ }
+ else
+ sfputr(out,cp,-1);
+}
+
+Namval_t *nv_type(Namval_t *np)
+{
+ Namfun_t *fp;
+ if(nv_isattr(np,NV_BLTIN|BLT_DCL)==(NV_BLTIN|BLT_DCL))
+ {
+ Namdecl_t *ntp = (Namdecl_t*)nv_context(np);
+ return(ntp?ntp->tp:0);
+ }
+ for(fp=np->nvfun; fp; fp=fp->next)
+ {
+ if(fp->type)
+ return(fp->type);
+ if(fp->disc && fp->disc->typef && (np= (*fp->disc->typef)(np,fp)))
+ return(np);
+ }
+ return(0);
+}
+
+/*
+ * call any and all create functions
+ */
+static void type_init(Namval_t *np)
+{
+ int i;
+ Namtype_t *dp, *pp=(Namtype_t*)nv_hasdisc(np,&type_disc);
+ Namval_t *nq;
+ if(!pp)
+ return;
+ for(i=0; i < pp->numnodes; i++)
+ {
+ nq = nv_namptr(pp->nodes,i);
+ if((dp=(Namtype_t*)nv_hasdisc(nq,&type_disc)) && dp->cp)
+ sh_fun(dp->cp,nq, (char**)0);
+ }
+ if(pp->cp)
+ sh_fun(pp->cp, np, (char**)0);
+}
+
+/*
+ * This function turns variable <np> to the type <tp>
+ */
+int nv_settype(Namval_t* np, Namval_t *tp, int flags)
+{
+ int isnull = nv_isnull(np);
+ int rdonly = nv_isattr(np,NV_RDONLY);
+ char *val=0;
+ Namarr_t *ap=0;
+ Shell_t *shp = sh_getinterp();
+ int nelem=0,subshell=shp->subshell;
+#if SHOPT_TYPEDEF
+ Namval_t *tq;
+ if(nv_type(np)==tp)
+ return(0);
+ if(nv_isarray(np) && (tq=nv_type(np)))
+ {
+ if(tp==tq)
+ return(0);
+ errormsg(SH_DICT,ERROR_exit(1),e_redef,nv_name(np));
+ }
+ if((ap=nv_arrayptr(np)) && ap->nelem>0)
+ {
+ nv_putsub(np,NIL(char*),ARRAY_SCAN);
+ ap->hdr.type = tp;
+ do
+ {
+ nv_arraysettype(np, tp, nv_getsub(np),flags);
+ }
+ while(nv_nextsub(np));
+ }
+ else if(ap || nv_isarray(np))
+ {
+ flags &= ~NV_APPEND;
+ if(!ap)
+ {
+ if(subshell)
+ {
+ sh_assignok(np,1);
+ shp->subshell = 0;
+ }
+ nv_putsub(np,"0",ARRAY_FILL);
+ ap = nv_arrayptr(np);
+ nelem = 1;
+
+ }
+ }
+ else
+#endif /*SHOPT_TYPEDEF */
+ {
+ if(isnull)
+ flags &= ~NV_APPEND;
+ else if(!nv_isvtree(np))
+ {
+ val = strdup(nv_getval(np));
+ if(!(flags&NV_APPEND))
+ _nv_unset(np, NV_RDONLY);
+ }
+ if(!nv_clone(tp,np,flags|NV_NOFREE))
+ return(0);
+ }
+ if(ap)
+ {
+ int nofree;
+ nv_disc(np,&ap->hdr,NV_POP);
+ np->nvalue.up = 0;
+ nv_clone(tp,np,flags|NV_NOFREE);
+ if(np->nvalue.cp && np->nvalue.cp!=Empty && !nv_isattr(np,NV_NOFREE))
+ free((void*)np->nvalue.cp);
+ np->nvalue.up = 0;
+ nofree = ap->hdr.nofree;
+ ap->hdr.nofree = 0;
+ ap->hdr.type = tp;
+ nv_disc(np, &ap->hdr, NV_FIRST);
+ ap->hdr.nofree = nofree;
+ nv_onattr(np,NV_ARRAY);
+ if(nelem)
+ {
+ ap->nelem++;
+ nv_putsub(np,"0",0);
+ _nv_unset(np,NV_RDONLY|NV_TYPE);
+ ap->nelem--;
+ shp->subshell = subshell;
+ }
+ }
+ type_init(np);
+ if(!rdonly)
+ nv_offattr(np,NV_RDONLY);
+ if(val)
+ {
+ nv_putval(np,val,NV_RDONLY);
+ free((void*)val);
+ }
+ return(0);
+}
+
+#define S(x) #x
+#define FIELD(x,y) { S(y##x), S(x##_t), offsetof(struct stat,st_##y##x) }
+typedef struct _field_
+{
+ char *name;
+ char *type;
+ int offset;
+} Fields_t;
+
+Fields_t foo[]=
+{
+ FIELD(dev,),
+ FIELD(ino,),
+ FIELD(nlink,),
+ FIELD(mode,),
+ FIELD(uid,),
+ FIELD(gid,),
+ FIELD(size,),
+ FIELD(time,a),
+ FIELD(time,m),
+ FIELD(time,c),
+#if 0
+ FIELD(blksize,),
+ FIELD(blocks,),
+#endif
+ 0
+};
+
+
+Namval_t *nv_mkstruct(const char *name, int rsize, Fields_t *fields)
+{
+ Namval_t *mp, *nq, *nr, *tp;
+ Fields_t *fp;
+ Namtype_t *dp, *pp;
+ char *cp, *sp;
+ int nnodes=0, offset=staktell(), n, r, i, j;
+ size_t m, size=0;
+ stakputs(NV_CLASS);
+ stakputc('.');
+ r = staktell();
+ stakputs(name);
+ stakputc(0);
+ mp = nv_open(stakptr(offset), sh.var_tree, NV_VARNAME);
+ stakseek(r);
+
+ for(fp=fields; fp->name; fp++)
+ {
+ m = strlen(fp->name)+1;
+ size += m;
+ nnodes++;
+ if(memcmp(fp->type,"typeset",7))
+ {
+ stakputs(fp->type);
+ stakputc(0);
+ tp = nv_open(stakptr(offset), sh.var_tree, NV_VARNAME|NV_NOADD|NV_NOFAIL);
+ stakseek(r);
+ if(!tp)
+ errormsg(SH_DICT,ERROR_exit(1),e_unknowntype,strlen(fp->type),fp->type);
+ if(dp = (Namtype_t*)nv_hasdisc(tp,&type_disc))
+ {
+ nnodes += dp->numnodes;
+ if((i=dp->strsize) < 0)
+ i = -i;
+ size += i + dp->numnodes*m;
+ }
+ }
+ }
+ pp = newof(NiL,Namtype_t, 1, nnodes*NV_MINSZ + rsize + size);
+ pp->fun.dsize = sizeof(Namtype_t)+nnodes*NV_MINSZ +rsize;
+ pp->fun.type = mp;
+ pp->np = mp;
+ pp->childfun.fun.disc = &chtype_disc;
+ pp->childfun.fun.nofree = 1;
+ pp->childfun.ttype = pp;
+ pp->childfun.ptype = pp;
+ pp->fun.disc = &type_disc;
+ pp->nodes = (char*)(pp+1);
+ pp->numnodes = nnodes;
+ pp->strsize = size;
+ pp->data = pp->nodes + nnodes*NV_MINSZ;
+ cp = pp->data + rsize;
+ for(i=0,fp=fields; fp->name; fp++)
+ {
+ nq = nv_namptr(pp->nodes,i++);
+ nq->nvname = cp;
+ nq->nvalue.cp = pp->data + fp->offset;
+ nv_onattr(nq,NV_MINIMAL|NV_NOFREE);
+ m = strlen(fp->name)+1;
+ memcpy(cp, fp->name, m);
+ cp += m;
+ if(memcmp(fp->type,"typeset",7))
+ {
+ stakputs(fp->type);
+ stakputc(0);
+ tp = nv_open(stakptr(offset), sh.var_tree, NV_VARNAME);
+ stakseek(r);
+ clone_all_disc(tp,nq,NV_RDONLY);
+ nq->nvflag = tp->nvflag|NV_MINIMAL|NV_NOFREE;
+ nq->nvsize = tp->nvsize;
+ if(dp = (Namtype_t*)nv_hasdisc(nq,&type_disc))
+ dp->strsize = -dp->strsize;
+ if(dp = (Namtype_t*)nv_hasdisc(tp,&type_disc))
+ {
+ if(nv_hasdisc(nq,&chtype_disc))
+ nv_disc(nq, &pp->childfun.fun, NV_LAST);
+ sp = (char*)nq->nvalue.cp;
+ memcpy(sp, dp->data, nv_size(tp));
+ for(j=0; j < dp->numnodes; j++)
+ {
+ nr = nv_namptr(dp->nodes,j);
+ nq = nv_namptr(pp->nodes,i++);
+ nq->nvname = cp;
+ memcpy(cp,fp->name,m);
+ cp[m-1] = '.';
+ cp += m;
+ n = strlen(nr->nvname)+1;
+ memcpy(cp,nr->nvname,n);
+ cp += n;
+ if(nr->nvalue.cp>=dp->data && nr->nvalue.cp < (char*)pp + pp->fun.dsize)
+ {
+ nq->nvalue.cp = sp + (nr->nvalue.cp-dp->data);
+ }
+ nq->nvflag = nr->nvflag;
+ nq->nvsize = nr->nvsize;
+ }
+ }
+ }
+ else if(strmatch(fp->type+7,"*-*i*")==0)
+ {
+ nv_onattr(nq,NV_NOFREE|NV_RDONLY|NV_INTEGER);
+ if(strmatch(fp->type+7,"*-*s*")==0)
+ nv_onattr(nq,NV_INT16P);
+ else if(strmatch(fp->type+7,"*-*l*")==0)
+ nv_onattr(nq,NV_INT64);
+ if(strmatch(fp->type+7,"*-*u*")==0)
+ nv_onattr(nq,NV_UNSIGN);
+ }
+
+ }
+ stakseek(offset);
+ nv_onattr(mp,NV_RDONLY|NV_NOFREE|NV_BINARY);
+ nv_setsize(mp,rsize);
+ nv_disc(mp, &pp->fun, NV_LAST);
+ mp->nvalue.cp = pp->data;
+ nv_newtype(mp);
+ return(mp);
+}
+
+static void put_stat(Namval_t* np, const char* val, int flag, Namfun_t* nfp)
+{
+ if(val)
+ {
+ if(stat(val,(struct stat*)np->nvalue.cp)<0)
+ sfprintf(sfstderr,"stat of %s failed\n",val);
+ return;
+ }
+ nv_putv(np,val,flag,nfp);
+ nv_disc(np,nfp,NV_POP);
+ if(!(nfp->nofree&1))
+ free((void*)nfp);
+}
+
+static const Namdisc_t stat_disc =
+{
+ 0,
+ put_stat
+};
+
+
+void nv_mkstat(void)
+{
+ Namval_t *tp;
+ Namfun_t *fp;
+ tp = nv_mkstruct("stat_t", sizeof(struct stat), foo);
+ nv_offattr(tp,NV_RDONLY);
+ nv_setvtree(tp);
+ fp = newof(NiL,Namfun_t,1,0);
+ fp->type = tp;
+ fp->disc = &stat_disc;
+ nv_disc(tp,fp,NV_FIRST);
+ nv_putval(tp,e_devnull,0);
+ nv_onattr(tp,NV_RDONLY);
+}
+
+static void write_indent(Sfio_t *out,char *str,int n,int indent)
+{
+ register int c, first=1;
+ register char *cp = str;
+ while(n-- && (c = *str++))
+ {
+ if(c=='\n')
+ {
+ if(!first)
+ sfnputc(out,'\t',indent);
+ first = 0;
+ sfwrite(out,cp,str-cp);
+ cp = str;
+ }
+ }
+ if(cp > str)
+ {
+ sfnputc(out,'\t',indent);
+ sfwrite(out,cp,str-cp);
+ }
+}
+
+int sh_outtype(Shell_t *shp,Sfio_t *out)
+{
+ Namval_t node,*mp,*tp;
+ Dt_t *dp;
+ char *cp,*sp,*xp,nvtype[sizeof(NV_CLASS)];
+ Sfio_t *iop=0;
+ int n=0,indent = 0;
+ if(cp=shp->prefix)
+ {
+ indent=1;
+ while(*cp)
+ {
+ if(*cp++ =='.')
+ indent++;
+ }
+ n = cp-shp->prefix+1;
+ }
+ strcpy(nvtype,NV_CLASS);
+ if(!(mp = nv_open(nvtype, shp->var_base,NV_NOADD|NV_VARNAME)))
+ return(0);
+ memcpy(&node,L_ARGNOD,sizeof(node));
+ L_ARGNOD->nvfun = 0;
+ L_ARGNOD->nvalue.cp = 0;
+ dp = nv_dict(mp);
+ if(indent==0)
+ for(tp = (Namval_t*)dtfirst(dp); tp; tp = (Namval_t*)dtnext(dp,tp))
+ {
+ if(!nv_search(tp->nvname,shp->bltin_tree,0))
+ continue;
+ sfprintf(out,"typeset -T %s\n",tp->nvname);
+ }
+ for(tp = (Namval_t*)dtfirst(dp); tp; tp = (Namval_t*)dtnext(dp,tp))
+ {
+ if(nv_isnull(tp))
+ continue;
+ if(indent && (memcmp(tp->nvname,shp->prefix,n-1) || tp->nvname[n-1]!='.' || strchr(tp->nvname+n,'.')))
+ continue;
+ nv_settype(L_ARGNOD,tp,0);
+ if(indent)
+ sfnputc(out,'\t',indent);
+ sfprintf(out,"typeset -T %s=",tp->nvname+n);
+ shp->last_table = 0;
+ cp = nv_getval(L_ARGNOD);
+ if(indent)
+ write_indent(out,cp,strlen(cp)-1,indent);
+ else
+ sfprintf(out,"%.*s",strlen(cp)-1,cp);
+ _nv_unset(L_ARGNOD,NV_RDONLY);
+ for(sp=0; sp=nv_setdisc(tp,(char*)0,(Namval_t*)sp,(Namfun_t*)tp);)
+ {
+ mp = (Namval_t*)nv_setdisc(tp,sp,tp,(Namfun_t*)tp);
+ if(!mp || mp==tp)
+ continue;
+ if(cp=strrchr(mp->nvname,'.'))
+ cp++;
+ else
+ cp = mp->nvname;
+ if(indent)
+ sfnputc(out,'\t',indent);
+ if(nv_isattr(mp,NV_FPOSIX))
+ sfprintf(out,"\t%s()",cp);
+ else
+ sfprintf(out,"\tfunction %s",cp);
+ xp = 0;
+ if(mp->nvalue.ip && mp->nvalue.rp->hoffset>=0)
+ {
+ if(nv_isattr(mp,NV_FTMP))
+ iop = shp->heredocs;
+ else if(xp=mp->nvalue.rp->fname)
+ iop = sfopen(iop,xp,"r");
+ else if(shp->gd->hist_ptr)
+ iop = (shp->gd->hist_ptr)->histfp;
+ if(iop && sfseek(iop,(Sfoff_t)mp->nvalue.rp->hoffset,SEEK_SET)>=0)
+ sfmove(iop,out, nv_size(mp), -1);
+ else
+ sfputc(iop,'\n');
+ if(xp)
+ sfclose(iop);
+ if(nv_isattr(mp,NV_STATICF|NV_TAGGED))
+ {
+ if(indent)
+ sfnputc(out,'\t',indent);
+ sfwrite(out,"\ttypeset -f",11);
+ if(nv_isattr(mp,NV_STATICF))
+ sfputc(out,'S');
+ if(nv_isattr(mp,NV_TAGGED))
+ sfputc(out,'t');
+ if(mp->nvalue.rp->help)
+ sfprintf(out,"h '%s'",mp->nvalue.rp->help);
+ sfprintf(out," %s\n",cp);
+ }
+ iop = 0;
+ }
+ }
+ if(indent)
+ sfnputc(out,'\t',indent);
+ sfwrite(out,")\n",2);
+ }
+ dtdelete(shp->var_base,L_ARGNOD);
+ memcpy(L_ARGNOD,&node,sizeof(node));
+ dtinsert(shp->var_base,L_ARGNOD);
+ return(0);
+}
diff --git a/src/cmd/ksh93/sh/parse.c b/src/cmd/ksh93/sh/parse.c
new file mode 100644
index 0000000..6ef3ef9
--- /dev/null
+++ b/src/cmd/ksh93/sh/parse.c
@@ -0,0 +1,2082 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * UNIX shell
+ *
+ * S. R. Bourne
+ * Rewritten by David Korn
+ * AT&T Labs
+ *
+ * This is the parser for a shell language
+ */
+
+#if KSHELL
+#include "defs.h"
+#else
+#include <shell.h>
+#include <ctype.h>
+#endif
+#include <fcin.h>
+#include <error.h>
+#include "shlex.h"
+#include "history.h"
+#include "builtins.h"
+#include "test.h"
+#include "history.h"
+
+#define HERE_MEM SF_BUFSIZE /* size of here-docs kept in memory */
+
+#if CDT_VERSION < 20111111L
+#define hash nvlink.hl._hash
+#else
+#define hash nvlink.lh.__hash
+#endif
+
+/* These routines are local to this module */
+
+static Shnode_t *makeparent(Lex_t*, int, Shnode_t*);
+static Shnode_t *makelist(Lex_t*, int, Shnode_t*, Shnode_t*);
+static struct argnod *qscan(struct comnod*, int);
+static struct ionod *inout(Lex_t*,struct ionod*, int);
+static Shnode_t *sh_cmd(Lex_t*,int,int);
+static Shnode_t *term(Lex_t*,int);
+static Shnode_t *list(Lex_t*,int);
+static struct regnod *syncase(Lex_t*,int);
+static Shnode_t *item(Lex_t*,int);
+static Shnode_t *simple(Lex_t*,int, struct ionod*);
+static int skipnl(Lex_t*,int);
+static Shnode_t *test_expr(Lex_t*,int);
+static Shnode_t *test_and(Lex_t*);
+static Shnode_t *test_or(Lex_t*);
+static Shnode_t *test_primary(Lex_t*);
+
+#define sh_getlineno(lp) (lp->lastline)
+
+#ifndef NIL
+# define NIL(type) ((type)0)
+#endif /* NIL */
+#define CNTL(x) ((x)&037)
+
+
+#if !KSHELL
+static struct stdata
+{
+ struct slnod *staklist;
+ int cmdline;
+} st;
+#endif
+
+static int opt_get;
+static int loop_level;
+static struct argnod *label_list;
+static struct argnod *label_last;
+
+#define getnode(type) ((Shnode_t*)stakalloc(sizeof(struct type)))
+
+#if SHOPT_KIA
+#include "path.h"
+/*
+ * write out entities for each item in the list
+ * type=='V' for variable assignment lists
+ * Otherwise type is determined by the command */
+static unsigned long writedefs(Lex_t *lexp,struct argnod *arglist, int line, int type, struct argnod *cmd)
+{
+ register struct argnod *argp = arglist;
+ register char *cp;
+ register int n,eline;
+ int width=0;
+ unsigned long r=0;
+ static char atbuff[20];
+ int justify=0;
+ char *attribute = atbuff;
+ unsigned long parent=lexp->script;
+ if(type==0)
+ {
+ parent = lexp->current;
+ type = 'v';
+ switch(*argp->argval)
+ {
+ case 'a':
+ type='p';
+ justify = 'a';
+ break;
+ case 'e':
+ *attribute++ = 'x';
+ break;
+ case 'r':
+ *attribute++ = 'r';
+ break;
+ case 'l':
+ break;
+ }
+ while(argp = argp->argnxt.ap)
+ {
+ if((n= *(cp=argp->argval))!='-' && n!='+')
+ break;
+ if(cp[1]==n)
+ break;
+ while((n= *++cp))
+ {
+ if(isdigit(n))
+ width = 10*width + n-'0';
+ else if(n=='L' || n=='R' || n =='Z')
+ justify=n;
+ else
+ *attribute++ = n;
+ }
+ }
+ }
+ else if(cmd)
+ parent=kiaentity(lexp,sh_argstr(cmd),-1,'p',-1,-1,lexp->unknown,'b',0,"");
+ *attribute = 0;
+ while(argp)
+ {
+ if((cp=strchr(argp->argval,'='))||(cp=strchr(argp->argval,'?')))
+ n = cp-argp->argval;
+ else
+ n = strlen(argp->argval);
+ eline = lexp->sh->inlineno-(lexp->token==NL);
+ r=kiaentity(lexp,argp->argval,n,type,line,eline,parent,justify,width,atbuff);
+ sfprintf(lexp->kiatmp,"p;%..64d;v;%..64d;%d;%d;s;\n",lexp->current,r,line,eline);
+ argp = argp->argnxt.ap;
+ }
+ return(r);
+}
+#endif /* SHOPT_KIA */
+
+static void typeset_order(const char *str,int line)
+{
+ register int c,n=0;
+ unsigned const char *cp=(unsigned char*)str;
+ static unsigned char *table;
+ if(*cp!='+' && *cp!='-')
+ return;
+ if(!table)
+ {
+ table = calloc(1,256);
+ for(cp=(unsigned char*)"bflmnprstuxACHS";c = *cp; cp++)
+ table[c] = 1;
+ for(cp=(unsigned char*)"aiEFLRXhTZ";c = *cp; cp++)
+ table[c] = 2;
+ for(c='0'; c <='9'; c++)
+ table[c] = 3;
+ }
+ for(cp=(unsigned char*)str; c= *cp++; n=table[c])
+ {
+ if(table[c] < n)
+ errormsg(SH_DICT,ERROR_warn(0),e_lextypeset,line,str);
+ }
+}
+
+/*
+ * add type definitions when compiling with -n
+ */
+static void check_typedef(struct comnod *tp)
+{
+ char *cp=0;
+ if(tp->comtyp&COMSCAN)
+ {
+ struct argnod *ap = tp->comarg;
+ while(ap = ap->argnxt.ap)
+ {
+ if(!(ap->argflag&ARG_RAW) || memcmp(ap->argval,"--",2))
+ break;
+ if(sh_isoption(SH_NOEXEC))
+ typeset_order(ap->argval,tp->comline);
+ if(memcmp(ap->argval,"-T",2)==0)
+ {
+ if(ap->argval[2])
+ cp = ap->argval+2;
+ else if((ap->argnxt.ap)->argflag&ARG_RAW)
+ cp = (ap->argnxt.ap)->argval;
+ if(cp)
+ break;
+ }
+ }
+ }
+ else
+ {
+ struct dolnod *dp = (struct dolnod*)tp->comarg;
+ char **argv = dp->dolval + dp->dolbot+1;
+ while((cp= *argv++) && memcmp(cp,"--",2))
+ {
+ if(sh_isoption(SH_NOEXEC))
+ typeset_order(cp,tp->comline);
+ if(memcmp(cp,"-T",2)==0)
+ {
+ if(cp[2])
+ cp = cp+2;
+ else
+ cp = *argv;
+ break;
+ }
+ }
+ }
+ if(cp)
+ {
+ Namval_t *mp=(Namval_t*)tp->comnamp ,*bp;
+ bp = sh_addbuiltin(cp, (Shbltin_f)mp->nvalue.bfp, (void*)0);
+ nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
+ }
+}
+
+/*
+ * Make a parent node for fork() or io-redirection
+ */
+static Shnode_t *makeparent(Lex_t *lp, int flag, Shnode_t *child)
+{
+ register Shnode_t *par = getnode(forknod);
+ par->fork.forktyp = flag;
+ par->fork.forktre = child;
+ par->fork.forkio = 0;
+ par->fork.forkline = sh_getlineno(lp)-1;
+ return(par);
+}
+
+static int paramsub(const char *str)
+{
+ register int c,sub=0,lit=0;
+ while(c= *str++)
+ {
+ if(c=='$' && !lit)
+ {
+ if(*str=='(')
+ return(0);
+ if(sub)
+ continue;
+ if(*str=='{')
+ str++;
+ if(!isdigit(*str) && strchr("?#@*!$ ",*str)==0)
+ return(1);
+ }
+ else if(c=='`')
+ return(0);
+ else if(c=='[' && !lit)
+ sub++;
+ else if(c==']' && !lit)
+ sub--;
+ else if(c=='\'')
+ lit = !lit;
+ }
+ return(0);
+}
+
+static Shnode_t *getanode(Lex_t *lp, struct argnod *ap)
+{
+ register Shnode_t *t = getnode(arithnod);
+ t->ar.artyp = TARITH;
+ t->ar.arline = sh_getlineno(lp);
+ t->ar.arexpr = ap;
+ if(ap->argflag&ARG_RAW)
+ t->ar.arcomp = sh_arithcomp(lp->sh,ap->argval);
+ else
+ {
+ if(sh_isoption(SH_NOEXEC) && (ap->argflag&ARG_MAC) && paramsub(ap->argval))
+ errormsg(SH_DICT,ERROR_warn(0),e_lexwarnvar,lp->sh->inlineno);
+ t->ar.arcomp = 0;
+ }
+ return(t);
+}
+
+/*
+ * Make a node corresponding to a command list
+ */
+static Shnode_t *makelist(Lex_t *lexp, int type, Shnode_t *l, Shnode_t *r)
+{
+ register Shnode_t *t;
+ if(!l || !r)
+ sh_syntax(lexp);
+ else
+ {
+ if((type&COMMSK) == TTST)
+ t = getnode(tstnod);
+ else
+ t = getnode(lstnod);
+ t->lst.lsttyp = type;
+ t->lst.lstlef = l;
+ t->lst.lstrit = r;
+ }
+ return(t);
+}
+
+/*
+ * entry to shell parser
+ * Flag can be the union of SH_EOF|SH_NL
+ */
+
+void *sh_parse(Shell_t *shp, Sfio_t *iop, int flag)
+{
+ register Shnode_t *t;
+ Lex_t *lexp = (Lex_t*)shp->lex_context;
+ Fcin_t sav_input;
+ struct argnod *sav_arg = lexp->arg;
+ int sav_prompt = shp->nextprompt;
+ if(shp->binscript && (sffileno(iop)==shp->infd || (flag&SH_FUNEVAL)))
+ return((void*)sh_trestore(shp,iop));
+ fcsave(&sav_input);
+ shp->st.staklist = 0;
+ lexp->noreserv = 0;
+ lexp->heredoc = 0;
+ lexp->inlineno = shp->inlineno;
+ lexp->firstline = shp->st.firstline;
+ shp->nextprompt = 1;
+ loop_level = 0;
+ label_list = label_last = 0;
+ if(sh_isoption(SH_INTERACTIVE))
+ sh_onstate(SH_INTERACTIVE);
+ if(sh_isoption(SH_VERBOSE))
+ sh_onstate(SH_VERBOSE);
+ sh_lexopen(lexp,shp,0);
+ if(fcfopen(iop) < 0)
+ return(NIL(void*));
+ if(fcfile())
+ {
+ char *cp = fcfirst();
+ if( cp[0]==CNTL('k') && cp[1]==CNTL('s') && cp[2]==CNTL('h') && cp[3]==0)
+ {
+ int version;
+ fcseek(4);
+ fcgetc(version);
+ fcclose();
+ fcrestore(&sav_input);
+ lexp->arg = sav_arg;
+ if(version > 3)
+ errormsg(SH_DICT,ERROR_exit(1),e_lexversion);
+ if(sffileno(iop)==shp->infd || (flag&SH_FUNEVAL))
+ shp->binscript = 1;
+ sfgetc(iop);
+ t = sh_trestore(shp,iop);
+ if(flag&SH_NL)
+ {
+ Shnode_t *tt;
+ while(1)
+ {
+ if(!(tt = sh_trestore(shp,iop)))
+ break;
+ t =makelist(lexp,TLST, t, tt);
+ }
+ }
+ return((void*)t);
+ }
+ }
+ flag &= ~SH_FUNEVAL;
+ if((flag&SH_NL) && (shp->inlineno=error_info.line+shp->st.firstline)==0)
+ shp->inlineno=1;
+#if KSHELL
+ shp->nextprompt = 2;
+#endif
+ t = sh_cmd(lexp,(flag&SH_EOF)?EOFSYM:'\n',SH_SEMI|SH_EMPTY|(flag&SH_NL));
+ fcclose();
+ fcrestore(&sav_input);
+ lexp->arg = sav_arg;
+ /* unstack any completed alias expansions */
+ if((sfset(iop,0,0)&SF_STRING) && !sfreserve(iop,0,-1))
+ {
+ Sfio_t *sp = sfstack(iop,NULL);
+ if(sp)
+ sfclose(sp);
+ }
+ shp->nextprompt = sav_prompt;
+ if(flag&SH_NL)
+ {
+ shp->st.firstline = lexp->firstline;
+ shp->inlineno = lexp->inlineno;
+ }
+ stkseek(shp->stk,0);
+ return((void*)t);
+}
+
+/*
+ * This routine parses up the matching right parenthesis and returns
+ * the parse tree
+ */
+Shnode_t *sh_dolparen(Lex_t* lp)
+{
+ register Shnode_t *t=0;
+ Sfio_t *sp = fcfile();
+ int line = lp->sh->inlineno;
+ lp->sh->inlineno = error_info.line+lp->sh->st.firstline;
+ sh_lexopen(lp,lp->sh,1);
+ lp->comsub = 1;
+ switch(sh_lex(lp))
+ {
+ /* ((...)) arithmetic expression */
+ case EXPRSYM:
+ t = getanode(lp,lp->arg);
+ break;
+ case LPAREN:
+ t = sh_cmd(lp,RPAREN,SH_NL|SH_EMPTY);
+ break;
+ case LBRACE:
+ t = sh_cmd(lp,RBRACE,SH_NL|SH_EMPTY);
+ break;
+ }
+ lp->comsub = 0;
+ if(!sp && (sp=fcfile()))
+ {
+ /*
+ * This code handles the case where string has been converted
+ * to a file by an alias setup
+ */
+ register int c;
+ char *cp;
+ if(fcgetc(c) > 0)
+ fcseek(-1);
+ cp = fcseek(0);
+ fcclose();
+ fcsopen(cp);
+ sfclose(sp);
+ }
+ lp->sh->inlineno = line;
+ return(t);
+}
+
+/*
+ * remove temporary files and stacks
+ */
+
+void sh_freeup(Shell_t *shp)
+{
+ if(shp->st.staklist)
+ sh_funstaks(shp->st.staklist,-1);
+ shp->st.staklist = 0;
+}
+
+/*
+ * increase reference count for each stack in function list when flag>0
+ * decrease reference count for each stack in function list when flag<=0
+ * stack is freed when reference count is zero
+ */
+
+void sh_funstaks(register struct slnod *slp,int flag)
+{
+ register struct slnod *slpold;
+ while(slpold=slp)
+ {
+ if(slp->slchild)
+ sh_funstaks(slp->slchild,flag);
+ slp = slp->slnext;
+ if(flag<=0)
+ stakdelete(slpold->slptr);
+ else
+ staklink(slpold->slptr);
+ }
+}
+/*
+ * cmd
+ * empty
+ * list
+ * list & [ cmd ]
+ * list [ ; cmd ]
+ */
+
+static Shnode_t *sh_cmd(Lex_t *lexp, register int sym, int flag)
+{
+ register Shnode_t *left, *right;
+ register int type = FINT|FAMP;
+ if(sym==NL)
+ lexp->lasttok = 0;
+ left = list(lexp,flag);
+ if(lexp->token==NL)
+ {
+ if(flag&SH_NL)
+ lexp->token=';';
+ }
+ else if(!left && !(flag&SH_EMPTY))
+ sh_syntax(lexp);
+ switch(lexp->token)
+ {
+ case COOPSYM: /* set up a cooperating process */
+ type |= (FPIN|FPOU|FPCL|FCOOP);
+ /* FALL THRU */
+ case '&':
+ if(left)
+ {
+ /* (...)& -> {...;} & */
+ if(left->tre.tretyp==TPAR)
+ left = left->par.partre;
+ left = makeparent(lexp,TFORK|type, left);
+ }
+ /* FALL THRU */
+ case ';':
+ if(!left)
+ sh_syntax(lexp);
+ if(right=sh_cmd(lexp,sym,flag|SH_EMPTY))
+ left=makelist(lexp,TLST, left, right);
+ break;
+ case EOFSYM:
+ if(sym==NL)
+ break;
+ default:
+ if(sym && sym!=lexp->token)
+ {
+ if(sym!=ELSESYM || (lexp->token!=ELIFSYM && lexp->token!=FISYM))
+ sh_syntax(lexp);
+ }
+ }
+ return(left);
+}
+
+/*
+ * list
+ * term
+ * list && term
+ * list || term
+ * unfortunately, these are equal precedence
+ */
+static Shnode_t *list(Lex_t *lexp, register int flag)
+{
+ register Shnode_t *t = term(lexp,flag);
+ register int token;
+ while(t && ((token=lexp->token)==ANDFSYM || token==ORFSYM))
+ t = makelist(lexp,(token==ANDFSYM?TAND:TORF), t, term(lexp,SH_NL|SH_SEMI));
+ return(t);
+}
+
+/*
+ * term
+ * item
+ * item | term
+ */
+static Shnode_t *term(Lex_t *lexp,register int flag)
+{
+ register Shnode_t *t;
+ register int token;
+ if(flag&SH_NL)
+ token = skipnl(lexp,flag);
+ else
+ token = sh_lex(lexp);
+ /* check to see if pipeline is to be timed */
+ if(token==TIMESYM || token==NOTSYM)
+ {
+ t = getnode(parnod);
+ t->par.partyp=TTIME;
+ if(lexp->token==NOTSYM)
+ t->par.partyp |= COMSCAN;
+ t->par.partre = term(lexp,0);
+ }
+#if SHOPT_COSHELL
+ else if((t=item(lexp,SH_NL|SH_EMPTY|(flag&SH_SEMI))) && (lexp->token=='|' || lexp->token==PIPESYM2))
+#else
+ else if((t=item(lexp,SH_NL|SH_EMPTY|(flag&SH_SEMI))) && lexp->token=='|')
+#endif /* SHOPT_COSHELL */
+ {
+ register Shnode_t *tt;
+ int showme = t->tre.tretyp&FSHOWME;
+ t = makeparent(lexp,TFORK|FPOU,t);
+#if SHOPT_COSHELL
+ if(lexp->token==PIPESYM2)
+ t->tre.tretyp |= FALTPIPE;
+#endif /* SHOPT_COSHELL */
+ if(tt=term(lexp,SH_NL))
+ {
+ switch(tt->tre.tretyp&COMMSK)
+ {
+ case TFORK:
+ tt->tre.tretyp |= FPIN|FPCL;
+ break;
+ case TFIL:
+ tt->lst.lstlef->tre.tretyp |= FPIN|FPCL;
+ break;
+ default:
+ tt= makeparent(lexp,TSETIO|FPIN|FPCL,tt);
+ }
+ t=makelist(lexp,TFIL,t,tt);
+ t->tre.tretyp |= showme;
+ }
+ else if(lexp->token)
+ sh_syntax(lexp);
+ }
+ return(t);
+}
+
+/*
+ * case statement
+ */
+static struct regnod* syncase(Lex_t *lexp,register int esym)
+{
+ register int tok = skipnl(lexp,0);
+ register struct regnod *r;
+ if(tok==esym)
+ return(NIL(struct regnod*));
+ r = (struct regnod*)stakalloc(sizeof(struct regnod));
+ r->regptr=0;
+ r->regflag=0;
+ if(tok==LPAREN)
+ skipnl(lexp,0);
+ while(1)
+ {
+ if(!lexp->arg)
+ sh_syntax(lexp);
+ lexp->arg->argnxt.ap=r->regptr;
+ r->regptr = lexp->arg;
+ if((tok=sh_lex(lexp))==RPAREN)
+ break;
+ else if(tok=='|')
+ sh_lex(lexp);
+ else
+ sh_syntax(lexp);
+ }
+ r->regcom=sh_cmd(lexp,0,SH_NL|SH_EMPTY|SH_SEMI);
+ if((tok=lexp->token)==BREAKCASESYM)
+ r->regnxt=syncase(lexp,esym);
+ else if(tok==FALLTHRUSYM)
+ {
+ r->regflag++;
+ r->regnxt=syncase(lexp,esym);
+ }
+ else
+ {
+ if(tok!=esym && tok!=EOFSYM)
+ sh_syntax(lexp);
+ r->regnxt=0;
+ }
+ if(lexp->token==EOFSYM)
+ return(NIL(struct regnod*));
+ return(r);
+}
+
+/*
+ * This routine creates the parse tree for the arithmetic for
+ * When called, shlex.arg contains the string inside ((...))
+ * When the first argument is missing, a while node is returned
+ * Otherise a list containing an arithmetic command and a while
+ * is returned.
+ */
+static Shnode_t *arithfor(Lex_t *lexp,register Shnode_t *tf)
+{
+ register Shnode_t *t, *tw = tf;
+ register int offset;
+ register struct argnod *argp;
+ register int n;
+ Stk_t *stkp = lexp->sh->stk;
+ int argflag = lexp->arg->argflag;
+ /* save current input */
+ Fcin_t sav_input;
+ fcsave(&sav_input);
+ fcsopen(lexp->arg->argval);
+ /* split ((...)) into three expressions */
+ for(n=0; ; n++)
+ {
+ register int c;
+ argp = (struct argnod*)stkseek(stkp,ARGVAL);
+ argp->argnxt.ap = 0;
+ argp->argchn.cp = 0;
+ argp->argflag = argflag;
+ if(n==2)
+ break;
+ /* copy up to ; onto the stack */
+ sh_lexskip(lexp,';',1,ST_NESTED);
+ offset = stktell(stkp)-1;
+ if((c=fcpeek(-1))!=';')
+ break;
+ /* remove trailing white space */
+ while(offset>ARGVAL && ((c= *stkptr(stkp,offset-1)),isspace(c)))
+ offset--;
+ /* check for empty initialization expression */
+ if(offset==ARGVAL && n==0)
+ continue;
+ stkseek(stkp,offset);
+ /* check for empty condition and treat as while((1)) */
+ if(offset==ARGVAL)
+ sfputc(stkp,'1');
+ argp = (struct argnod*)stkfreeze(stkp,1);
+ t = getanode(lexp,argp);
+ if(n==0)
+ tf = makelist(lexp,TLST,t,tw);
+ else
+ tw->wh.whtre = t;
+ }
+ while((offset=fcpeek(0)) && isspace(offset))
+ fcseek(1);
+ stakputs(fcseek(0));
+ argp = (struct argnod*)stakfreeze(1);
+ fcrestore(&sav_input);
+ if(n<2)
+ {
+ lexp->token = RPAREN|SYMREP;
+ sh_syntax(lexp);
+ }
+ /* check whether the increment is present */
+ if(*argp->argval)
+ {
+ t = getanode(lexp,argp);
+ tw->wh.whinc = (struct arithnod*)t;
+ }
+ else
+ tw->wh.whinc = 0;
+ sh_lexopen(lexp, lexp->sh,1);
+ if((n=sh_lex(lexp))==NL)
+ n = skipnl(lexp,0);
+ else if(n==';')
+ n = sh_lex(lexp);
+ if(n!=DOSYM && n!=LBRACE)
+ sh_syntax(lexp);
+ tw->wh.dotre = sh_cmd(lexp,n==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI);
+ tw->wh.whtyp = TWH;
+ return(tf);
+
+}
+
+static Shnode_t *funct(Lex_t *lexp)
+{
+ Shell_t *shp = lexp->sh;
+ register Shnode_t *t;
+ register int flag;
+ struct slnod *volatile slp=0;
+ Stak_t *savstak;
+ Sfoff_t first, last;
+ struct functnod *volatile fp;
+ Sfio_t *iop;
+#if SHOPT_KIA
+ unsigned long current = lexp->current;
+#endif /* SHOPT_KIA */
+ int nargs=0,size=0,jmpval, saveloop=loop_level;
+ struct argnod *savelabel = label_last;
+ struct checkpt buff;
+ int save_optget = opt_get;
+ void *in_mktype = shp->mktype;
+ shp->mktype = 0;
+ opt_get = 0;
+ t = getnode(functnod);
+ t->funct.functline = shp->inlineno;
+ t->funct.functtyp=TFUN;
+ t->funct.functargs = 0;
+ if(!(flag = (lexp->token==FUNCTSYM)))
+ t->funct.functtyp |= FPOSIX;
+ else if(sh_lex(lexp))
+ sh_syntax(lexp);
+ if(!(iop=fcfile()))
+ {
+ iop = sfopen(NIL(Sfio_t*),fcseek(0),"s");
+ fcclose();
+ fcfopen(iop);
+ }
+ t->funct.functloc = first = fctell();
+ if(!shp->st.filename || sffileno(iop)<0)
+ {
+ if(fcfill() >= 0)
+ fcseek(-1);
+ if(sh_isstate(SH_HISTORY) && shp->gd->hist_ptr)
+ t->funct.functloc = sfseek(shp->gd->hist_ptr->histfp,(off_t)0,SEEK_CUR);
+ else
+ {
+ /* copy source to temporary file */
+ t->funct.functloc = 0;
+ if(lexp->sh->heredocs)
+ t->funct.functloc = sfseek(lexp->sh->heredocs,(Sfoff_t)0, SEEK_END);
+ else
+ lexp->sh->heredocs = sftmp(HERE_MEM);
+ lexp->sh->funlog = lexp->sh->heredocs;
+ t->funct.functtyp |= FPIN;
+ }
+ }
+ t->funct.functnam= (char*)lexp->arg->argval;
+#if SHOPT_KIA
+ if(lexp->kiafile)
+ lexp->current = kiaentity(lexp,t->funct.functnam,-1,'p',-1,-1,lexp->script,'p',0,"");
+#endif /* SHOPT_KIA */
+ if(flag)
+ {
+ lexp->token = sh_lex(lexp);
+#if SHOPT_BASH
+ if(lexp->token == LPAREN)
+ {
+ if((lexp->token = sh_lex(lexp)) == RPAREN)
+ t->funct.functtyp |= FPOSIX;
+ else
+ sh_syntax(lexp);
+ }
+#endif
+ }
+ if(t->funct.functtyp&FPOSIX)
+ skipnl(lexp,0);
+ else
+ {
+ if(lexp->token==0)
+ {
+ struct comnod *ac;
+ char *cp, **argv, **argv0;
+ int c;
+ t->funct.functargs = ac = (struct comnod*)simple(lexp,SH_NOIO|SH_FUNDEF,NIL(struct ionod*));
+ if(ac->comset || (ac->comtyp&COMSCAN))
+ errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax4,lexp->sh->inlineno);
+ argv0 = argv = ((struct dolnod*)ac->comarg)->dolval+ARG_SPARE;
+ while(cp= *argv++)
+ {
+ size += strlen(cp)+1;
+ if((c = mbchar(cp)) && isaletter(c))
+ while(c=mbchar(cp), isaname(c));
+ }
+ if(c)
+ errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax4,lexp->sh->inlineno);
+ nargs = argv-argv0;
+ size += sizeof(struct dolnod)+(nargs+ARG_SPARE)*sizeof(char*);
+ if(shp->shcomp && memcmp(".sh.math.",t->funct.functnam,9)==0)
+ {
+ Namval_t *np= nv_open(t->funct.functnam,shp->fun_tree,NV_ADD|NV_VARNAME);
+ np->nvalue.rp = new_of(struct Ufunction,shp->funload?sizeof(Dtlink_t):0);
+ memset((void*)np->nvalue.rp,0,sizeof(struct Ufunction));
+ np->nvalue.rp->argc = ((struct dolnod*)ac->comarg)->dolnum;
+ }
+ }
+ while(lexp->token==NL)
+ lexp->token = sh_lex(lexp);
+ }
+ if((flag && lexp->token!=LBRACE) || lexp->token==EOFSYM)
+ sh_syntax(lexp);
+ sh_pushcontext(shp,&buff,1);
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval == 0)
+ {
+ /* create a new stak frame to compile the command */
+ savstak = stakcreate(STAK_SMALL);
+ savstak = stakinstall(savstak, 0);
+ slp = (struct slnod*)stakalloc(sizeof(struct slnod)+sizeof(struct functnod));
+ slp->slchild = 0;
+ slp->slnext = shp->st.staklist;
+ shp->st.staklist = 0;
+ t->funct.functstak = (struct slnod*)slp;
+ /*
+ * store the pathname of function definition file on stack
+ * in name field of fake for node
+ */
+ fp = (struct functnod*)(slp+1);
+ fp->functtyp = TFUN|FAMP;
+ fp->functnam = 0;
+ fp->functline = t->funct.functline;
+ if(shp->st.filename)
+ fp->functnam = stakcopy(shp->st.filename);
+ loop_level = 0;
+ label_last = label_list;
+ if(size)
+ {
+ struct dolnod *dp = (struct dolnod*)stakalloc(size);
+ char *cp, *sp, **argv, **old = ((struct dolnod*)t->funct.functargs->comarg)->dolval+1;
+ argv = ((char**)(dp->dolval))+1;
+ dp->dolnum = ((struct dolnod*)t->funct.functargs->comarg)->dolnum;
+ t->funct.functargs->comarg = (struct argnod*)dp;
+ for(cp=(char*)&argv[nargs]; sp= *old++; cp++)
+ {
+ *argv++ = cp;
+ cp = strcopy(cp,sp);
+ }
+ *argv = 0;
+ }
+ if(!flag && lexp->token==0)
+ {
+ /* copy current word token to current stak frame */
+ struct argnod *ap;
+ flag = ARGVAL + strlen(lexp->arg->argval);
+ ap = (struct argnod*)stakalloc(flag);
+ memcpy(ap,lexp->arg,flag);
+ lexp->arg = ap;
+ }
+ t->funct.functtre = item(lexp,SH_NOIO);
+ }
+ else if(shp->shcomp)
+ exit(1);
+ sh_popcontext(shp,&buff);
+ loop_level = saveloop;
+ label_last = savelabel;
+ /* restore the old stack */
+ if(slp)
+ {
+ slp->slptr = stakinstall(savstak,0);
+ slp->slchild = shp->st.staklist;
+ }
+#if SHOPT_KIA
+ lexp->current = current;
+#endif /* SHOPT_KIA */
+ if(jmpval)
+ {
+ if(slp && slp->slptr)
+ {
+ shp->st.staklist = slp->slnext;
+ stakdelete(slp->slptr);
+ }
+ siglongjmp(*shp->jmplist,jmpval);
+ }
+ shp->st.staklist = (struct slnod*)slp;
+ last = fctell();
+ fp->functline = (last-first);
+ fp->functtre = t;
+ shp->mktype = in_mktype;
+ if(lexp->sh->funlog)
+ {
+ if(fcfill()>0)
+ fcseek(-1);
+ lexp->sh->funlog = 0;
+ }
+#if SHOPT_KIA
+ if(lexp->kiafile)
+ kiaentity(lexp,t->funct.functnam,-1,'p',t->funct.functline,shp->inlineno-1,lexp->current,'p',0,"");
+#endif /* SHOPT_KIA */
+ t->funct.functtyp |= opt_get;
+ opt_get = save_optget;
+ return(t);
+}
+
+/*
+ * Compound assignment
+ */
+static struct argnod *assign(Lex_t *lexp, register struct argnod *ap, int type)
+{
+ register int n;
+ register Shnode_t *t, **tp;
+ register struct comnod *ac;
+ Stk_t *stkp = lexp->sh->stk;
+ int array=0, index=0;
+ Namval_t *np;
+ n = strlen(ap->argval)-1;
+ if(ap->argval[n]!='=')
+ sh_syntax(lexp);
+ if(ap->argval[n-1]=='+')
+ {
+ ap->argval[n--]=0;
+ array = ARG_APPEND;
+ }
+ /* shift right */
+ while(n > 0)
+ {
+ ap->argval[n] = ap->argval[n-1];
+ n--;
+ }
+ *ap->argval=0;
+ t = getnode(fornod);
+ t->for_.fornam = (char*)(ap->argval+1);
+ t->for_.fortyp = sh_getlineno(lexp);
+ tp = &t->for_.fortre;
+ ap->argchn.ap = (struct argnod*)t;
+ ap->argflag &= ARG_QUOTED;
+ ap->argflag |= array;
+ lexp->assignok = SH_ASSIGN;
+ if(type==NV_ARRAY)
+ lexp->noreserv = 1;
+ else
+ lexp->aliasok = 1;
+ array= (type==NV_ARRAY)?SH_ARRAY:0;
+ if((n=skipnl(lexp,0))==RPAREN || n==LPAREN)
+ {
+ struct argnod *ar,*aq,**settail;
+ ac = (struct comnod*)getnode(comnod);
+ memset((void*)ac,0,sizeof(*ac));
+ comarray:
+ settail= &ac->comset;
+ ac->comline = sh_getlineno(lexp);
+ while(n==LPAREN)
+ {
+ ar = (struct argnod*)stkseek(stkp,ARGVAL);
+ ar->argflag= ARG_ASSIGN;
+ sfprintf(stkp,"[%d]=",index++);
+ if(aq=ac->comarg)
+ {
+ ac->comarg = aq->argnxt.ap;
+ sfprintf(stkp,"%s",aq->argval);
+ ar->argflag |= aq->argflag;
+ }
+ ar = (struct argnod*)stkfreeze(stkp,1);
+ ar->argnxt.ap = 0;
+ if(!aq)
+ ar = assign(lexp,ar,0);
+ ar->argflag |= ARG_MESSAGE;
+ *settail = ar;
+ settail = &(ar->argnxt.ap);
+ if(aq)
+ continue;
+ while((n = skipnl(lexp,0))==0)
+ {
+ ar = (struct argnod*)stkseek(stkp,ARGVAL);
+ ar->argflag= ARG_ASSIGN;
+ sfprintf(stkp,"[%d]=",index++);
+ stakputs(lexp->arg->argval);
+ ar = (struct argnod*)stkfreeze(stkp,1);
+ ar->argnxt.ap = 0;
+ ar->argflag = lexp->arg->argflag;
+ *settail = ar;
+ settail = &(ar->argnxt.ap);
+ }
+ }
+ }
+ else if(n && n!=FUNCTSYM)
+ sh_syntax(lexp);
+ else if(type!=NV_ARRAY && n!=FUNCTSYM && !(lexp->arg->argflag&ARG_ASSIGN) && !((np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && (nv_isattr(np,BLT_DCL)|| np==SYSDOT)))
+ {
+ array=SH_ARRAY;
+ if(fcgetc(n)==LPAREN)
+ {
+ int c;
+ if(fcgetc(c)==RPAREN)
+ {
+ lexp->token = SYMRES;
+ array = 0;
+ }
+ else
+ fcseek(-2);
+ }
+ else if(n>0)
+ fcseek(-1);
+ if(array && type==NV_TYPE)
+ {
+ struct argnod *arg = lexp->arg;
+ n = lexp->token;
+ if(path_search(lexp->sh,lexp->arg->argval,NIL(Pathcomp_t**),1) && (np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && nv_isattr(np,BLT_DCL))
+ {
+ lexp->token = n;
+ lexp->arg = arg;
+ array = 0;
+ }
+ else
+ sh_syntax(lexp);
+ }
+ }
+ lexp->noreserv = 0;
+ while(1)
+ {
+ if((n=lexp->token)==RPAREN)
+ break;
+ if(n==FUNCTSYM || n==SYMRES)
+ ac = (struct comnod*)funct(lexp);
+ else
+ ac = (struct comnod*)simple(lexp,SH_NOIO|SH_ASSIGN|array,NIL(struct ionod*));
+ if((n=lexp->token)==RPAREN)
+ break;
+ if(n!=NL && n!=';')
+ {
+ if(array && n==LPAREN)
+ goto comarray;
+ sh_syntax(lexp);
+ }
+ lexp->assignok = SH_ASSIGN;
+ if((n=skipnl(lexp,0)) || array)
+ {
+ if(n==RPAREN)
+ break;
+ if(array || n!=FUNCTSYM)
+ sh_syntax(lexp);
+ }
+ if((n!=FUNCTSYM) && !(lexp->arg->argflag&ARG_ASSIGN) && !((np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && (nv_isattr(np,BLT_DCL)||np==SYSDOT)))
+ {
+ struct argnod *arg = lexp->arg;
+ if(n!=0)
+ sh_syntax(lexp);
+ /* check for sys5 style function */
+ if(sh_lex(lexp)!=LPAREN || sh_lex(lexp)!=RPAREN)
+ {
+ lexp->arg = arg;
+ lexp->token = 0;
+ sh_syntax(lexp);
+ }
+ lexp->arg = arg;
+ lexp->token = SYMRES;
+ }
+ t = makelist(lexp,TLST,(Shnode_t*)ac,t);
+ *tp = t;
+ tp = &t->lst.lstrit;
+ }
+ *tp = (Shnode_t*)ac;
+ lexp->assignok = 0;
+ return(ap);
+}
+
+/*
+ * item
+ *
+ * ( cmd ) [ < in ] [ > out ]
+ * word word* [ < in ] [ > out ]
+ * if ... then ... else ... fi
+ * for ... while ... do ... done
+ * case ... in ... esac
+ * begin ... end
+ */
+
+static Shnode_t *item(Lex_t *lexp,int flag)
+{
+ register Shnode_t *t;
+ register struct ionod *io;
+ register int tok = (lexp->token&0xff);
+ int savwdval = lexp->lasttok;
+ int savline = lexp->lastline;
+ int showme=0, comsub;
+ if(!(flag&SH_NOIO) && (tok=='<' || tok=='>' || lexp->token==IOVNAME))
+ io=inout(lexp,NIL(struct ionod*),1);
+ else
+ io=0;
+ if((tok=lexp->token) && tok!=EOFSYM && tok!=FUNCTSYM)
+ {
+ lexp->lastline = sh_getlineno(lexp);
+ lexp->lasttok = lexp->token;
+ }
+ switch(tok)
+ {
+ /* [[ ... ]] test expression */
+ case BTESTSYM:
+ t = test_expr(lexp,ETESTSYM);
+ t->tre.tretyp &= ~TTEST;
+ break;
+ /* ((...)) arithmetic expression */
+ case EXPRSYM:
+ t = getanode(lexp,lexp->arg);
+ sh_lex(lexp);
+ goto done;
+
+ /* case statement */
+ case CASESYM:
+ {
+ int savetok = lexp->lasttok;
+ int saveline = lexp->lastline;
+ t = getnode(swnod);
+ if(sh_lex(lexp))
+ sh_syntax(lexp);
+ t->sw.swarg=lexp->arg;
+ t->sw.swtyp=TSW;
+ t->sw.swio = 0;
+ t->sw.swtyp |= FLINENO;
+ t->sw.swline = lexp->sh->inlineno;
+ if((tok=skipnl(lexp,0))!=INSYM && tok!=LBRACE)
+ sh_syntax(lexp);
+ if(!(t->sw.swlst=syncase(lexp,tok==INSYM?ESACSYM:RBRACE)) && lexp->token==EOFSYM)
+ {
+ lexp->lasttok = savetok;
+ lexp->lastline = saveline;
+ sh_syntax(lexp);
+ }
+ break;
+ }
+
+ /* if statement */
+ case IFSYM:
+ {
+ register Shnode_t *tt;
+ t = getnode(ifnod);
+ t->if_.iftyp=TIF;
+ t->if_.iftre=sh_cmd(lexp,THENSYM,SH_NL);
+ t->if_.thtre=sh_cmd(lexp,ELSESYM,SH_NL|SH_SEMI);
+ tok = lexp->token;
+ t->if_.eltre=(tok==ELSESYM?sh_cmd(lexp,FISYM,SH_NL|SH_SEMI):
+ (tok==ELIFSYM?(lexp->token=IFSYM, tt=item(lexp,SH_NOIO)):0));
+ if(tok==ELIFSYM)
+ {
+ if(!tt || tt->tre.tretyp!=TSETIO)
+ goto done;
+ t->if_.eltre = tt->fork.forktre;
+ tt->fork.forktre = t;
+ t = tt;
+ goto done;
+ }
+ break;
+ }
+
+ /* for and select statement */
+ case FORSYM:
+ case SELECTSYM:
+ {
+ t = getnode(fornod);
+ t->for_.fortyp=(lexp->token==FORSYM?TFOR:TSELECT);
+ t->for_.forlst=0;
+ t->for_.forline = lexp->sh->inlineno;
+ if(sh_lex(lexp))
+ {
+ if(lexp->token!=EXPRSYM || t->for_.fortyp!=TFOR)
+ sh_syntax(lexp);
+ /* arithmetic for */
+ t = arithfor(lexp,t);
+ break;
+ }
+ t->for_.fornam=(char*) lexp->arg->argval;
+ t->for_.fortyp |= FLINENO;
+#if SHOPT_KIA
+ if(lexp->kiafile)
+ writedefs(lexp,lexp->arg,lexp->sh->inlineno,'v',NIL(struct argnod*));
+#endif /* SHOPT_KIA */
+ while((tok=sh_lex(lexp))==NL);
+ if(tok==INSYM)
+ {
+ if(sh_lex(lexp))
+ {
+ if(lexp->token != NL && lexp->token !=';')
+ sh_syntax(lexp);
+ /* some Linux scripts assume this */
+ if(sh_isoption(SH_NOEXEC))
+ errormsg(SH_DICT,ERROR_warn(0),e_lexemptyfor,lexp->sh->inlineno-(lexp->token=='\n'));
+ t->for_.forlst = (struct comnod*)getnode(comnod);
+ (t->for_.forlst)->comarg = 0;
+ (t->for_.forlst)->comset = 0;
+ (t->for_.forlst)->comnamp = 0;
+ (t->for_.forlst)->comnamq = 0;
+ (t->for_.forlst)->comstate = 0;
+ (t->for_.forlst)->comio = 0;
+ (t->for_.forlst)->comtyp = 0;
+ }
+ else
+ t->for_.forlst=(struct comnod*)simple(lexp,SH_NOIO,NIL(struct ionod*));
+ if(lexp->token != NL && lexp->token !=';')
+ sh_syntax(lexp);
+ tok = skipnl(lexp,0);
+ }
+ /* 'for i;do cmd' is valid syntax */
+ else if(tok==';')
+ tok=sh_lex(lexp);
+ if(tok!=DOSYM && tok!=LBRACE)
+ sh_syntax(lexp);
+ loop_level++;
+ t->for_.fortre=sh_cmd(lexp,tok==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI);
+ if(--loop_level==0)
+ label_last = label_list;
+ break;
+ }
+
+ /* This is the code for parsing function definitions */
+ case FUNCTSYM:
+ return(funct(lexp));
+
+#if SHOPT_NAMESPACE
+ case NSPACESYM:
+ t = getnode(fornod);
+ t->for_.fortyp=TNSPACE;
+ t->for_.forlst=0;
+ if(sh_lex(lexp))
+ sh_syntax(lexp);
+ t->for_.fornam=(char*) lexp->arg->argval;
+ while((tok=sh_lex(lexp))==NL);
+ if(tok!=LBRACE)
+ sh_syntax(lexp);
+ t->for_.fortre = sh_cmd(lexp,RBRACE,SH_NL);
+ break;
+#endif /* SHOPT_NAMESPACE */
+
+ /* while and until */
+ case WHILESYM:
+ case UNTILSYM:
+ t = getnode(whnod);
+ t->wh.whtyp=(lexp->token==WHILESYM ? TWH : TUN);
+ loop_level++;
+ t->wh.whtre = sh_cmd(lexp,DOSYM,SH_NL);
+ t->wh.dotre = sh_cmd(lexp,DONESYM,SH_NL|SH_SEMI);
+ if(--loop_level==0)
+ label_last = label_list;
+ t->wh.whinc = 0;
+ break;
+
+ case LABLSYM:
+ {
+ register struct argnod *argp = label_list;
+ while(argp)
+ {
+ if(strcmp(argp->argval,lexp->arg->argval)==0)
+ errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax3,lexp->sh->inlineno,argp->argval);
+ argp = argp->argnxt.ap;
+ }
+ lexp->arg->argnxt.ap = label_list;
+ label_list = lexp->arg;
+ label_list->argchn.len = sh_getlineno(lexp);
+ label_list->argflag = loop_level;
+ skipnl(lexp,flag);
+ if(!(t = item(lexp,SH_NL)))
+ sh_syntax(lexp);
+ tok = (t->tre.tretyp&(COMSCAN|COMSCAN-1));
+ if(sh_isoption(SH_NOEXEC) && tok!=TWH && tok!=TUN && tok!=TFOR && tok!=TSELECT)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexlabignore,label_list->argchn.len,label_list->argval);
+ return(t);
+ }
+
+ /* command group with {...} */
+ case LBRACE:
+ comsub = lexp->comsub;
+ lexp->comsub = 0;
+ t = sh_cmd(lexp,RBRACE,SH_NL|SH_SEMI);
+ lexp->comsub = comsub;
+ break;
+
+ case LPAREN:
+ t = getnode(parnod);
+ t->par.partre=sh_cmd(lexp,RPAREN,SH_NL|SH_SEMI);
+ t->par.partyp=TPAR;
+ break;
+
+#if SHOPT_COSHELL
+ case '&':
+ if(tok=sh_lex(lexp))
+ {
+ if(tok!=NL)
+ sh_syntax(lexp);
+ t = getnode(comnod);
+ memset(t,0,sizeof(struct comnod));
+ t->com.comline = sh_getlineno(lexp);
+ }
+ else
+ t = (Shnode_t*)simple(lexp,SH_NOIO,NIL(struct ionod*));
+ t->com.comtyp |= FAMP;
+ if(lexp->token=='&' || lexp->token=='|')
+ sh_syntax(lexp);
+ return(t);
+ break;
+#endif /* SHOPT_COSHELL */
+ default:
+ if(io==0)
+ return(0);
+
+ case ';':
+ if(io==0)
+ {
+ if(!(flag&SH_SEMI))
+ return(0);
+ if(sh_lex(lexp)==';')
+ sh_syntax(lexp);
+ showme = FSHOWME;
+ }
+ /* simple command */
+ case 0:
+ t = (Shnode_t*)simple(lexp,flag,io);
+ if(t->com.comarg && lexp->intypeset)
+ check_typedef(&t->com);
+ lexp->intypeset = 0;
+ lexp->inexec = 0;
+ t->tre.tretyp |= showme;
+ return(t);
+ }
+ sh_lex(lexp);
+ if(io=inout(lexp,io,0))
+ {
+ if((tok=t->tre.tretyp&COMMSK) != TFORK)
+ tok = TSETIO;
+ t=makeparent(lexp,tok,t);
+ t->tre.treio=io;
+ }
+done:
+ lexp->lasttok = savwdval;
+ lexp->lastline = savline;
+ return(t);
+}
+
+static struct argnod *process_sub(Lex_t *lexp,int tok)
+{
+ struct argnod *argp;
+ Shnode_t *t;
+ int mode = (tok==OPROCSYM);
+ t = sh_cmd(lexp,RPAREN,SH_NL);
+ argp = (struct argnod*)stkalloc(lexp->sh->stk,sizeof(struct argnod));
+ *argp->argval = 0;
+ argp->argchn.ap = (struct argnod*)makeparent(lexp,mode?TFORK|FPIN|FAMP|FPCL:TFORK|FPOU,t);
+ argp->argflag = (ARG_EXP|mode);
+ return(argp);
+}
+
+
+/*
+ * This is for a simple command, for list, or compound assignment
+ */
+static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io)
+{
+ register struct comnod *t;
+ register struct argnod *argp;
+ register int tok;
+ Stk_t *stkp = lexp->sh->stk;
+ struct argnod **argtail;
+ struct argnod **settail;
+ int cmdarg=0;
+ int argno = 0;
+ int assignment = 0;
+ int key_on = (!(flag&SH_NOIO) && sh_isoption(SH_KEYWORD));
+ int associative=0;
+ if((argp=lexp->arg) && (argp->argflag&ARG_ASSIGN) && argp->argval[0]=='[')
+ {
+ flag |= SH_ARRAY;
+ associative = 1;
+ }
+ t = (struct comnod*)getnode(comnod);
+ t->comio=io; /*initial io chain*/
+ /* set command line number for error messages */
+ t->comline = sh_getlineno(lexp);
+ argtail = &(t->comarg);
+ t->comset = 0;
+ t->comnamp = 0;
+ t->comnamq = 0;
+ t->comstate = 0;
+ settail = &(t->comset);
+ while(lexp->token==0)
+ {
+ argp = lexp->arg;
+ if(*argp->argval==LBRACE && (flag&SH_FUNDEF) && argp->argval[1]==0)
+ {
+ lexp->token = LBRACE;
+ break;
+ }
+ if(associative && argp->argval[0]!='[')
+ sh_syntax(lexp);
+ /* check for assignment argument */
+ if((argp->argflag&ARG_ASSIGN) && assignment!=2)
+ {
+ *settail = argp;
+ settail = &(argp->argnxt.ap);
+ lexp->assignok = (flag&SH_ASSIGN)?SH_ASSIGN:1;
+ if(assignment)
+ {
+ struct argnod *ap=argp;
+ char *last, *cp;
+ if(assignment==1)
+ {
+ last = strchr(argp->argval,'=');
+ if(last && (last[-1]==']'|| (last[-1]=='+' && last[-2]==']')) && (cp=strchr(argp->argval,'[')) && (cp < last) && cp[-1]!='.')
+ last = cp;
+ stkseek(stkp,ARGVAL);
+ sfwrite(stkp,argp->argval,last-argp->argval);
+ ap=(struct argnod*)stkfreeze(stkp,1);
+ ap->argflag = ARG_RAW;
+ ap->argchn.ap = 0;
+ }
+ *argtail = ap;
+ argtail = &(ap->argnxt.ap);
+ if(argno>=0)
+ argno++;
+ }
+ else /* alias substitutions allowed */
+ lexp->aliasok = 1;
+ }
+ else
+ {
+ if(!(argp->argflag&ARG_RAW))
+ argno = -1;
+ if(argno>=0 && argno++==cmdarg && !(flag&SH_ARRAY) && *argp->argval!='/')
+ {
+ /* check for builtin command */
+ Namval_t *np=nv_bfsearch(argp->argval,lexp->sh->fun_tree, (Namval_t**)&t->comnamq,(char**)0);
+ if(cmdarg==0)
+ t->comnamp = (void*)np;
+ if(np && is_abuiltin(np))
+ {
+ if(nv_isattr(np,BLT_DCL))
+ {
+ assignment = 1+(*argp->argval=='a');
+ if(np==SYSTYPESET)
+ lexp->intypeset = 1;
+ key_on = 1;
+ }
+ else if(np==SYSCOMMAND)
+ cmdarg++;
+ else if(np==SYSEXEC)
+ lexp->inexec = 1;
+ else if(np->nvalue.bfp==(Nambfp_f)b_getopts)
+ opt_get |= FOPTGET;
+ }
+ }
+ *argtail = argp;
+ argtail = &(argp->argnxt.ap);
+ if(!(lexp->assignok=key_on) && !(flag&SH_NOIO) && sh_isoption(SH_NOEXEC))
+ lexp->assignok = SH_COMPASSIGN;
+ lexp->aliasok = 0;
+ }
+ retry:
+ tok = sh_lex(lexp);
+ if(tok==LABLSYM && (flag&SH_ASSIGN))
+ lexp->token = tok = 0;
+ if((tok==IPROCSYM || tok==OPROCSYM))
+ {
+ argp = process_sub(lexp,tok);
+ argno = -1;
+ *argtail = argp;
+ argtail = &(argp->argnxt.ap);
+ goto retry;
+ }
+ if(tok==LPAREN)
+ {
+ if(argp->argflag&ARG_ASSIGN)
+ {
+ int intypeset = lexp->intypeset;
+ int type = 0;
+ lexp->intypeset = 0;
+ if(t->comnamp==SYSTYPESET)
+ {
+ struct argnod *ap;
+ for(ap=t->comarg->argnxt.ap;ap;ap=ap->argnxt.ap)
+ {
+ if(*ap->argval!='-')
+ break;
+ if(strchr(ap->argval,'T'))
+ type = NV_TYPE;
+ else if(strchr(ap->argval,'a'))
+ type = NV_ARRAY;
+ else
+ continue;
+ break;
+ }
+ }
+ argp = assign(lexp,argp,type);
+ lexp->intypeset = intypeset;
+ if(associative)
+ lexp->assignok |= SH_ASSIGN;
+ goto retry;
+ }
+ else if(argno==1 && !t->comset)
+ {
+ /* SVR2 style function */
+ if(!(flag&SH_ARRAY) && sh_lex(lexp) == RPAREN)
+ {
+ lexp->arg = argp;
+ return(funct(lexp));
+ }
+ lexp->token = LPAREN;
+ }
+ }
+ else if(flag&SH_ASSIGN)
+ {
+ if(tok==RPAREN)
+ break;
+ else if(tok==NL && (flag&SH_ARRAY))
+ {
+ lexp->comp_assign = 2;
+ goto retry;
+ }
+
+ }
+ if(!(flag&SH_NOIO))
+ {
+ if(io)
+ {
+ while(io->ionxt)
+ io = io->ionxt;
+ io->ionxt = inout(lexp,(struct ionod*)0,0);
+ }
+ else
+ t->comio = io = inout(lexp,(struct ionod*)0,0);
+ }
+ }
+ *argtail = 0;
+ t->comtyp = TCOM;
+#if SHOPT_KIA
+ if(lexp->kiafile && !(flag&SH_NOIO))
+ {
+ register Namval_t *np=(Namval_t*)t->comnamp;
+ unsigned long r=0;
+ int line = t->comline;
+ argp = t->comarg;
+ if(np)
+ r = kiaentity(lexp,nv_name(np),-1,'p',-1,0,lexp->unknown,'b',0,"");
+ else if(argp)
+ r = kiaentity(lexp,sh_argstr(argp),-1,'p',-1,0,lexp->unknown,'c',0,"");
+ if(r>0)
+ sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;c;\n",lexp->current,r,line,line);
+ if(t->comset && argno==0)
+ writedefs(lexp,t->comset,line,'v',t->comarg);
+ else if(np && nv_isattr(np,BLT_DCL))
+ writedefs(lexp,argp,line,0,NIL(struct argnod*));
+ else if(argp && strcmp(argp->argval,"read")==0)
+ writedefs(lexp,argp,line,0,NIL(struct argnod*));
+#if 0
+ else if(argp && strcmp(argp->argval,"unset")==0)
+ writedefs(lexp,argp,line,'u',NIL(struct argnod*));
+#endif
+ else if(argp && *argp->argval=='.' && argp->argval[1]==0 && (argp=argp->argnxt.ap))
+ {
+ r = kiaentity(lexp,sh_argstr(argp),-1,'p',0,0,lexp->script,'d',0,"");
+ sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;d;\n",lexp->current,r,line,line);
+ }
+ }
+#endif /* SHOPT_KIA */
+ if(t->comnamp && (argp=t->comarg->argnxt.ap))
+ {
+ Namval_t *np=(Namval_t*)t->comnamp;
+ if((np==SYSBREAK || np==SYSCONT) && (argp->argflag&ARG_RAW) && !isdigit(*argp->argval))
+ {
+ register char *cp = argp->argval;
+ /* convert break/continue labels to numbers */
+ tok = 0;
+ for(argp=label_list;argp!=label_last;argp=argp->argnxt.ap)
+ {
+ if(strcmp(cp,argp->argval))
+ continue;
+ tok = loop_level-argp->argflag;
+ if(tok>=1)
+ {
+ argp = t->comarg->argnxt.ap;
+ if(tok>9)
+ {
+ argp->argval[1] = '0'+tok%10;
+ argp->argval[2] = 0;
+ tok /= 10;
+ }
+ else
+ argp->argval[1] = 0;
+ *argp->argval = '0'+tok;
+ }
+ break;
+ }
+ if(sh_isoption(SH_NOEXEC) && tok==0)
+ errormsg(SH_DICT,ERROR_warn(0),e_lexlabunknown,lexp->sh->inlineno-(lexp->token=='\n'),cp);
+ }
+ else if(sh_isoption(SH_NOEXEC) && np==SYSSET && ((tok= *argp->argval)=='-'||tok=='+') &&
+ (argp->argval[1]==0||strchr(argp->argval,'k')))
+ errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete5,lexp->sh->inlineno-(lexp->token=='\n'),argp->argval);
+ }
+ /* expand argument list if possible */
+ if(argno>0 && !(flag&SH_ARRAY))
+ t->comarg = qscan(t,argno);
+ else if(t->comarg)
+ t->comtyp |= COMSCAN;
+ lexp->aliasok = 0;
+ return((Shnode_t*)t);
+}
+
+/*
+ * skip past newlines but issue prompt if interactive
+ */
+static int skipnl(Lex_t *lexp,int flag)
+{
+ register int token;
+ while((token=sh_lex(lexp))==NL);
+ if(token==';' && !(flag&SH_SEMI))
+ sh_syntax(lexp);
+ return(token);
+}
+
+/*
+ * check for and process and i/o redirections
+ * if flag>0 then an alias can be in the next word
+ * if flag<0 only one redirection will be processed
+ */
+static struct ionod *inout(Lex_t *lexp,struct ionod *lastio,int flag)
+{
+ register int iof = lexp->digits, token=lexp->token;
+ register struct ionod *iop;
+ Stk_t *stkp = lexp->sh->stk;
+ char *iovname=0;
+ register int errout=0;
+ if(token==IOVNAME)
+ {
+ iovname=lexp->arg->argval+1;
+ token= sh_lex(lexp);
+ iof = 0;
+ }
+ switch(token&0xff)
+ {
+ case '<':
+ if(token==IODOCSYM)
+ iof |= (IODOC|IORAW);
+ else if(token==IOMOV0SYM)
+ iof |= IOMOV;
+ else if(token==IORDWRSYMT)
+ iof |= IORDW|IOREWRITE;
+ else if(token==IORDWRSYM)
+ iof |= IORDW;
+ else if((token&SYMSHARP) == SYMSHARP)
+ {
+ int n;
+ iof |= IOLSEEK;
+ if(fcgetc(n)=='#')
+ iof |= IOCOPY;
+ else if(n>0)
+ fcseek(-1);
+ }
+ break;
+
+ case '>':
+ if(iof<0)
+ {
+ errout = 1;
+ iof = 1;
+ }
+ iof |= IOPUT;
+ if(token==IOAPPSYM)
+ iof |= IOAPP;
+ else if(token==IOMOV1SYM)
+ iof |= IOMOV;
+ else if(token==IOCLOBSYM)
+ iof |= IOCLOB;
+ else if((token&SYMSHARP) == SYMSHARP)
+ iof |= IOLSEEK;
+ else if((token&SYMSEMI) == SYMSEMI)
+ iof |= IOREWRITE;
+ break;
+
+ default:
+ return(lastio);
+ }
+ lexp->digits=0;
+ iop=(struct ionod*) stkalloc(stkp,sizeof(struct ionod));
+ iop->iodelim = 0;
+ if(token=sh_lex(lexp))
+ {
+ if(token==RPAREN && (iof&IOLSEEK) && lexp->comsub)
+ {
+ lexp->arg = (struct argnod*)stkalloc(stkp,sizeof(struct argnod)+3);
+ strcpy(lexp->arg->argval,"CUR");
+ lexp->arg->argflag = ARG_RAW;
+ iof |= IOARITH;
+ fcseek(-1);
+ }
+ else if(token==EXPRSYM && (iof&IOLSEEK))
+ iof |= IOARITH;
+ else if(((token==IPROCSYM && !(iof&IOPUT)) || (token==OPROCSYM && (iof&IOPUT))) && !(iof&(IOLSEEK|IOREWRITE|IOMOV|IODOC)))
+ {
+ lexp->arg = process_sub(lexp,token);
+ iof |= IOPROCSUB;
+ }
+ else
+ sh_syntax(lexp);
+ }
+ if( (iof&IOPROCSUB) && !(iof&IOLSEEK))
+ iop->ioname= (char*)lexp->arg->argchn.ap;
+ else
+ iop->ioname=lexp->arg->argval;
+ iop->iovname = iovname;
+ if(iof&IODOC)
+ {
+ if(lexp->digits==2)
+ {
+ iof |= IOSTRG;
+ if(!(lexp->arg->argflag&ARG_RAW))
+ iof &= ~IORAW;
+ }
+ else
+ {
+ if(!lexp->sh->heredocs)
+ lexp->sh->heredocs = sftmp(HERE_MEM);
+ iop->iolst=lexp->heredoc;
+ lexp->heredoc=iop;
+ if(lexp->arg->argflag&ARG_QUOTED)
+ iof |= IOQUOTE;
+ if(lexp->digits==3)
+ iof |= IOLSEEK;
+ if(lexp->digits)
+ iof |= IOSTRIP;
+ }
+ }
+ else
+ {
+ iop->iolst = 0;
+ if(lexp->arg->argflag&ARG_RAW)
+ iof |= IORAW;
+ }
+ iop->iofile=iof;
+ if(flag>0)
+ /* allow alias substitutions and parameter assignments */
+ lexp->aliasok = lexp->assignok = 1;
+#if SHOPT_KIA
+ if(lexp->kiafile)
+ {
+ int n = lexp->sh->inlineno-(lexp->token=='\n');
+ if(!(iof&IOMOV))
+ {
+ unsigned long r=kiaentity(lexp,(iof&IORAW)?sh_fmtq(iop->ioname):iop->ioname,-1,'f',0,0,lexp->script,'f',0,"");
+ sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;%c;%d\n",lexp->current,r,n,n,(iof&IOPUT)?((iof&IOAPP)?'a':'w'):((iof&IODOC)?'h':'r'),iof&IOUFD);
+ }
+ }
+#endif /* SHOPT_KIA */
+ if(flag>=0)
+ {
+ struct ionod *ioq=iop;
+ sh_lex(lexp);
+ if(errout)
+ {
+ /* redirect standard output to standard error */
+ ioq = (struct ionod*)stkalloc(stkp,sizeof(struct ionod));
+ memset(ioq,0,sizeof(*ioq));
+ ioq->ioname = "1";
+ ioq->iolst = 0;
+ ioq->iodelim = 0;
+ ioq->iofile = IORAW|IOPUT|IOMOV|2;
+ iop->ionxt=ioq;
+ }
+ ioq->ionxt=inout(lexp,lastio,flag);
+ }
+ else
+ iop->ionxt=0;
+ return(iop);
+}
+
+/*
+ * convert argument chain to argument list when no special arguments
+ */
+
+static struct argnod *qscan(struct comnod *ac,int argn)
+{
+ register char **cp;
+ register struct argnod *ap;
+ register struct dolnod* dp;
+ register int special=0;
+ /* special hack for test -t compatibility */
+ if((Namval_t*)ac->comnamp==SYSTEST)
+ special = 2;
+ else if(*(ac->comarg->argval)=='[' && ac->comarg->argval[1]==0)
+ special = 3;
+ if(special)
+ {
+ ap = ac->comarg->argnxt.ap;
+ if(argn==(special+1) && ap->argval[1]==0 && *ap->argval=='!')
+ ap = ap->argnxt.ap;
+ else if(argn!=special)
+ special=0;
+ }
+ if(special)
+ {
+ const char *message;
+ if(strcmp(ap->argval,"-t"))
+ {
+ message = "line %d: Invariant test";
+ special=0;
+ }
+ else
+ {
+ message = "line %d: -t requires argument";
+ argn++;
+ }
+ if(sh_isoption(SH_NOEXEC))
+ errormsg(SH_DICT,ERROR_warn(0),message,ac->comline);
+ }
+ /* leave space for an extra argument at the front */
+ dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
+ cp = dp->dolval+ARG_SPARE;
+ dp->dolnum = argn;
+ dp->dolbot = ARG_SPARE;
+ ap = ac->comarg;
+ while(ap)
+ {
+ *cp++ = ap->argval;
+ ap = ap->argnxt.ap;
+ }
+ if(special==3)
+ {
+ cp[0] = cp[-1];
+ cp[-1] = "1";
+ cp++;
+ }
+ else if(special)
+ *cp++ = "1";
+ *cp = 0;
+ return((struct argnod*)dp);
+}
+
+static Shnode_t *test_expr(Lex_t *lp,int sym)
+{
+ register Shnode_t *t = test_or(lp);
+ if(lp->token!=sym)
+ sh_syntax(lp);
+ return(t);
+}
+
+static Shnode_t *test_or(Lex_t *lp)
+{
+ register Shnode_t *t = test_and(lp);
+ while(lp->token==ORFSYM)
+ t = makelist(lp,TORF|TTEST,t,test_and(lp));
+ return(t);
+}
+
+static Shnode_t *test_and(Lex_t *lp)
+{
+ register Shnode_t *t = test_primary(lp);
+ while(lp->token==ANDFSYM)
+ t = makelist(lp,TAND|TTEST,t,test_primary(lp));
+ return(t);
+}
+
+/*
+ * convert =~ into == ~(E)
+ */
+static void ere_match(void)
+{
+ Sfio_t *base, *iop = sfopen((Sfio_t*)0," ~(E)","s");
+ register int c;
+ while( fcgetc(c),(c==' ' || c=='\t'));
+ if(c)
+ fcseek(-1);
+ if(!(base=fcfile()))
+ base = sfopen(NIL(Sfio_t*),fcseek(0),"s");
+ fcclose();
+ sfstack(base,iop);
+ fcfopen(base);
+}
+
+static Shnode_t *test_primary(Lex_t *lexp)
+{
+ register struct argnod *arg;
+ register Shnode_t *t;
+ register int num,token;
+ token = skipnl(lexp,0);
+ num = lexp->digits;
+ switch(token)
+ {
+ case '(':
+ t = test_expr(lexp,')');
+ t = makelist(lexp,TTST|TTEST|TPAREN ,t, (Shnode_t*)pointerof(lexp->sh->inlineno));
+ break;
+ case '!':
+ if(!(t = test_primary(lexp)))
+ sh_syntax(lexp);
+ t->tre.tretyp |= TNEGATE;
+ return(t);
+ case TESTUNOP:
+ if(sh_lex(lexp))
+ sh_syntax(lexp);
+#if SHOPT_KIA
+ if(lexp->kiafile && !strchr("sntzoOG",num))
+ {
+ int line = lexp->sh->inlineno- (lexp->token==NL);
+ unsigned long r;
+ r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->script,'t',0,"");
+ sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
+ }
+#endif /* SHOPT_KIA */
+ t = makelist(lexp,TTST|TTEST|TUNARY|(num<<TSHIFT),
+ (Shnode_t*)lexp->arg,(Shnode_t*)lexp->arg);
+ t->tst.tstline = lexp->sh->inlineno;
+ break;
+ /* binary test operators */
+ case 0:
+ arg = lexp->arg;
+ if((token=sh_lex(lexp))==TESTBINOP)
+ {
+ num = lexp->digits;
+ if(num==TEST_REP)
+ {
+ ere_match();
+ num = TEST_PEQ;
+ }
+ }
+ else if(token=='<')
+ num = TEST_SLT;
+ else if(token=='>')
+ num = TEST_SGT;
+ else if(token==ANDFSYM||token==ORFSYM||token==ETESTSYM||token==RPAREN)
+ {
+ t = makelist(lexp,TTST|TTEST|TUNARY|('n'<<TSHIFT),
+ (Shnode_t*)arg,(Shnode_t*)arg);
+ t->tst.tstline = lexp->sh->inlineno;
+ return(t);
+ }
+ else
+ sh_syntax(lexp);
+#if SHOPT_KIA
+ if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT))
+ {
+ int line = lexp->sh->inlineno- (lexp->token==NL);
+ unsigned long r;
+ r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,"");
+ sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
+ }
+#endif /* SHOPT_KIA */
+ if(sh_lex(lexp))
+ sh_syntax(lexp);
+ if(num&TEST_PATTERN)
+ {
+ if(lexp->arg->argflag&(ARG_EXP|ARG_MAC))
+ num &= ~TEST_PATTERN;
+ }
+ t = getnode(tstnod);
+ t->lst.lsttyp = TTST|TTEST|TBINARY|(num<<TSHIFT);
+ t->lst.lstlef = (Shnode_t*)arg;
+ t->lst.lstrit = (Shnode_t*)lexp->arg;
+ t->tst.tstline = lexp->sh->inlineno;
+#if SHOPT_KIA
+ if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT))
+ {
+ int line = lexp->sh->inlineno-(lexp->token==NL);
+ unsigned long r;
+ r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,"");
+ sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
+ }
+#endif /* SHOPT_KIA */
+ break;
+ default:
+ return(0);
+ }
+ skipnl(lexp,0);
+ return(t);
+}
+
+#if SHOPT_KIA
+/*
+ * return an entity checksum
+ * The entity is created if it doesn't exist
+ */
+unsigned long kiaentity(Lex_t *lexp,const char *name,int len,int type,int first,int last,unsigned long parent, int pkind, int width, const char *attr)
+{
+ Stk_t *stkp = lexp->sh->stk;
+ Namval_t *np;
+ long offset = stktell(stkp);
+ sfputc(stkp,type);
+ if(len>0)
+ sfwrite(stkp,name,len);
+ else
+ {
+ if(type=='p')
+ sfputr(stkp,path_basename(name),0);
+ else
+ sfputr(stkp,name,0);
+ }
+ np = nv_search(stakptr(offset),lexp->entity_tree,NV_ADD);
+ stkseek(stkp,offset);
+ np->nvalue.i = pkind;
+ nv_setsize(np,width);
+ if(!nv_isattr(np,NV_TAGGED) && first>=0)
+ {
+ nv_onattr(np,NV_TAGGED);
+ if(!pkind)
+ pkind = '0';
+ if(len>0)
+ sfprintf(lexp->kiafile,"%..64d;%c;%.*s;%d;%d;%..64d;%..64d;%c;%d;%s\n",np->hash,type,len,name,first,last,parent,lexp->fscript,pkind,width,attr);
+ else
+ sfprintf(lexp->kiafile,"%..64d;%c;%s;%d;%d;%..64d;%..64d;%c;%d;%s\n",np->hash,type,name,first,last,parent,lexp->fscript,pkind,width,attr);
+ }
+ return(np->hash);
+}
+
+static void kia_add(register Namval_t *np, void *data)
+{
+ char *name = nv_name(np);
+ Lex_t *lp = (Lex_t*)data;
+ NOT_USED(data);
+ kiaentity(lp,name+1,-1,*name,0,-1,(*name=='p'?lp->unknown:lp->script),np->nvalue.i,nv_size(np),"");
+}
+
+int kiaclose(Lex_t *lexp)
+{
+ register off_t off1,off2;
+ register int n;
+ if(lexp->kiafile)
+ {
+ unsigned long r = kiaentity(lexp,lexp->scriptname,-1,'p',-1,lexp->sh->inlineno-1,0,'s',0,"");
+ kiaentity(lexp,lexp->scriptname,-1,'p',1,lexp->sh->inlineno-1,r,'s',0,"");
+ kiaentity(lexp,lexp->scriptname,-1,'f',1,lexp->sh->inlineno-1,r,'s',0,"");
+ nv_scan(lexp->entity_tree,kia_add,(void*)lexp,NV_TAGGED,0);
+ off1 = sfseek(lexp->kiafile,(off_t)0,SEEK_END);
+ sfseek(lexp->kiatmp,(off_t)0,SEEK_SET);
+ sfmove(lexp->kiatmp,lexp->kiafile,SF_UNBOUND,-1);
+ off2 = sfseek(lexp->kiafile,(off_t)0,SEEK_END);
+#ifdef SF_BUFCONST
+ if(off2==off1)
+ n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin));
+ else
+ n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nRELATIONSHIP;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin),(Sflong_t)off1,(size_t)(off2-off1));
+ if(off2 >= INT_MAX)
+ off2 = -(n+12);
+ sfprintf(lexp->kiafile,"%010.10lld;%010d\n",(Sflong_t)off2+10, n+12);
+#else
+ if(off2==off1)
+ n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin);
+ else
+ n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nRELATIONSHIP;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin,off1,off2-off1);
+ sfprintf(lexp->kiafile,"%010d;%010d\n",off2+10, n+12);
+#endif
+ }
+ return(sfclose(lexp->kiafile));
+}
+#endif /* SHOPT_KIA */
diff --git a/src/cmd/ksh93/sh/path.c b/src/cmd/ksh93/sh/path.c
new file mode 100644
index 0000000..28d61ae
--- /dev/null
+++ b/src/cmd/ksh93/sh/path.c
@@ -0,0 +1,1824 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <fcin.h>
+#include <ls.h>
+#include <nval.h>
+#include "variables.h"
+#include "path.h"
+#include "io.h"
+#include "jobs.h"
+#include "history.h"
+#include "test.h"
+#include "FEATURE/dynamic"
+#include "FEATURE/externs"
+#if SHOPT_PFSH
+# ifdef _hdr_exec_attr
+# include <exec_attr.h>
+# endif
+# if _lib_vfork
+# include <ast_vfork.h>
+# else
+# define vfork() fork()
+# endif
+#endif
+
+#define RW_ALL (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)
+#define LIBCMD "cmd"
+
+
+static int canexecute(Shell_t*,char*,int);
+static void funload(Shell_t*,int,const char*);
+static void exscript(Shell_t*,char*, char*[], char**);
+static int path_chkpaths(Shell_t*,Pathcomp_t*,Pathcomp_t*,Pathcomp_t*,int);
+static void path_checkdup(Shell_t *shp,register Pathcomp_t*);
+
+static const char *std_path;
+
+static int onstdpath(const char *name)
+{
+ register const char *cp = std_path, *sp;
+ if(cp)
+ while(*cp)
+ {
+ for(sp=name; *sp && (*cp == *sp); sp++,cp++);
+ if(*sp==0 && (*cp==0 || *cp==':'))
+ return(1);
+ while(*cp && *cp++!=':');
+ }
+ return(0);
+}
+
+#if SHOPT_PFSH
+int path_xattr(Shell_t *shp, const char *path, char *rpath)
+{
+ char resolvedpath[PATH_MAX + 1];
+ if (shp->gd->user && *shp->gd->user)
+ {
+ execattr_t *pf;
+ if(!rpath)
+ rpath = resolvedpath;
+ if (!realpath(path, resolvedpath))
+ return -1;
+ if(pf=getexecuser(shp->gd->user, KV_COMMAND, resolvedpath, GET_ONE))
+ {
+ if (!pf->attr || pf->attr->length == 0)
+ {
+ free_execattr(pf);
+ return(0);
+ }
+ free_execattr(pf);
+ return(1);
+ }
+ }
+ errno = ENOENT;
+ return(-1);
+}
+#endif /* SHOPT_PFSH */
+
+static pid_t path_pfexecve(Shell_t *shp,const char *path, char *argv[],char *const envp[],int spawn)
+{
+#if SHOPT_PFSH
+ char resolvedpath[PATH_MAX + 1];
+ pid_t pid;
+ if(spawn)
+ {
+ while((pid = vfork()) < 0)
+ _sh_fork(shp,pid, 0, (int*)0);
+ if(pid)
+ return(pid);
+ }
+ if(!sh_isoption(SH_PFSH))
+ return(execve(path, argv, envp));
+ /* Solaris implements realpath(3C) using the resolvepath(2) */
+ /* system call so we can save us to call access(2) first */
+
+ /* we can exec the command directly instead of via pfexec(1) if */
+ /* there is a matching entry without attributes in exec_attr(4) */
+ if(!path_xattr(shp,path,resolvedpath))
+ return(execve(path, argv, envp));
+ --argv;
+ argv[0] = argv[1];
+ argv[1] = resolvedpath;
+ return(execve("/usr/bin/pfexec", argv, envp));
+#else
+ return(execve(path, argv, envp));
+#endif
+}
+
+
+static pid_t _spawnveg(Shell_t *shp,const char *path, char* const argv[], char* const envp[], pid_t pgid)
+{
+ int waitsafe = job.waitsafe;
+ pid_t pid;
+ job_lock();
+ while(1)
+ {
+ sh_stats(STAT_SPAWN);
+ pid = spawnveg(path,argv,envp,pgid);
+ if(pid>=0 || errno!=EAGAIN)
+ break;
+ _sh_fork(shp,pid, 0, (int*)0);
+ }
+ job.waitsafe = waitsafe;
+ if(pid>0)
+ job_fork(pid);
+ else
+ job_unlock();
+ return(pid);
+}
+/*
+ * used with command -x to run the command in multiple passes
+ * spawn is non-zero when invoked via spawn
+ * the exitval is set to the maximum for each execution
+ */
+static pid_t path_xargs(Shell_t *shp,const char *path, char *argv[],char *const envp[], int spawn)
+{
+ register char *cp, **av, **xv;
+ char **avlast= &argv[shp->xargmax], **saveargs=0;
+ char *const *ev;
+ long size, left;
+ int nlast=1,n,exitval=0;
+ pid_t pid;
+ if(shp->xargmin < 0)
+ return((pid_t)-1);
+ size = shp->gd->lim.arg_max-1024;
+ for(ev=envp; cp= *ev; ev++)
+ size -= strlen(cp)-1;
+ for(av=argv; (cp= *av) && av< &argv[shp->xargmin]; av++)
+ size -= strlen(cp)-1;
+ for(av=avlast; cp= *av; av++,nlast++)
+ size -= strlen(cp)-1;
+ av = &argv[shp->xargmin];
+ if(!spawn)
+ job_clear();
+ shp->exitval = 0;
+ while(av<avlast)
+ {
+ for(xv=av,left=size; left>0 && av<avlast;)
+ left -= strlen(*av++)+1;
+ /* leave at least two for last */
+ if(left<0 && (avlast-av)<2)
+ av--;
+ if(xv==&argv[shp->xargmin])
+ {
+ n = nlast*sizeof(char*);
+ saveargs = (char**)malloc(n);
+ memcpy((void*)saveargs, (void*)av, n);
+ memcpy((void*)av,(void*)avlast,n);
+ }
+ else
+ {
+ for(n=shp->xargmin; xv < av; xv++)
+ argv[n++] = *xv;
+ for(xv=avlast; cp= *xv; xv++)
+ argv[n++] = cp;
+ argv[n] = 0;
+ }
+ if(saveargs || av<avlast || (exitval && !spawn))
+ {
+ if((pid=_spawnveg(shp,path,argv,envp,0)) < 0)
+ return(-1);
+ job_post(shp,pid,0);
+ job_wait(pid);
+ if(shp->exitval>exitval)
+ exitval = shp->exitval;
+ if(saveargs)
+ {
+ memcpy((void*)av,saveargs,n);
+ free((void*)saveargs);
+ saveargs = 0;
+ }
+ }
+ else if(spawn && !sh_isoption(SH_PFSH))
+ {
+ shp->xargexit = exitval;
+ if(saveargs)
+ free((void*)saveargs);
+ return(_spawnveg(shp,path,argv,envp,spawn>>1));
+ }
+ else
+ {
+ if(saveargs)
+ free((void*)saveargs);
+ return(path_pfexecve(shp,path,argv,envp,spawn));
+ }
+ }
+ if(!spawn)
+ exit(exitval);
+ return((pid_t)-1);
+}
+
+/*
+ * make sure PWD is set up correctly
+ * Return the present working directory
+ * Invokes getcwd() if flag==0 and if necessary
+ * Sets the PWD variable to this value
+ */
+char *path_pwd(Shell_t *shp,int flag)
+{
+ register char *cp;
+ register char *dfault = (char*)e_dot;
+ register int count = 0;
+ if(shp->pwd)
+ return((char*)shp->pwd);
+ while(1)
+ {
+ /* try from lowest to highest */
+ switch(count++)
+ {
+ case 0:
+ cp = nv_getval(PWDNOD);
+ break;
+ case 1:
+ cp = nv_getval(HOME);
+ break;
+ case 2:
+ cp = "/";
+ break;
+ case 3:
+ cp = (char*)e_crondir;
+ if(flag) /* skip next case when non-zero flag */
+ ++count;
+ break;
+ case 4:
+ {
+ if(cp=getcwd(NIL(char*),0))
+ {
+ nv_offattr(PWDNOD,NV_NOFREE);
+ _nv_unset(PWDNOD,0);
+ PWDNOD->nvalue.cp = cp;
+ goto skip;
+ }
+ break;
+ }
+ case 5:
+ return(dfault);
+ }
+ if(cp && *cp=='/' && test_inode(cp,e_dot))
+ break;
+ }
+ if(count>1)
+ {
+ nv_offattr(PWDNOD,NV_NOFREE);
+ nv_putval(PWDNOD,cp,NV_RDONLY);
+ }
+skip:
+ nv_onattr(PWDNOD,NV_NOFREE|NV_EXPORT);
+ shp->pwd = (char*)(PWDNOD->nvalue.cp);
+ return(cp);
+}
+
+static void free_bltin(Namval_t *np,void *data)
+{
+ register Pathcomp_t *pp= (Pathcomp_t*)data;
+ if(pp->flags&PATH_STD_DIR)
+ {
+ int offset=staktell();;
+ if(strcmp(pp->name,"/bin")==0 || memcmp(pp->name,np->nvname,pp->len) || np->nvname[pp->len]!='/')
+ return;
+ stakputs("/bin");
+ stakputs(np->nvname+pp->len+1);
+ stakputc(0);
+ sh_addbuiltin(stakptr(offset),(Shbltin_f)np->nvalue.bfp,NiL);
+ stakseek(offset);
+ return;
+ }
+ if((void*)np->nvenv==pp->bltin_lib)
+ nv_delete(np,sh_bltin_tree(),NV_NOFREE);
+}
+
+/*
+ * delete current Pathcomp_t structure
+ */
+void path_delete(Pathcomp_t *first)
+{
+ register Pathcomp_t *pp=first, *old=0, *ppnext;
+ while(pp)
+ {
+ ppnext = pp->next;
+ if(--pp->refcount<=0)
+ {
+ if(pp->lib)
+ free((void*)pp->lib);
+ if(pp->blib)
+ free((void*)pp->blib);
+ if(pp->bltin_lib || (pp->flags&PATH_STD_DIR))
+ {
+ nv_scan(sh_bltin_tree(),free_bltin,pp,0,0);
+#if SHOPT_DYNAMIC
+ if(pp->bltin_lib)
+ dlclose(pp->bltin_lib);
+#endif /* SHOPT_DYNAMIC */
+ }
+ free((void*)pp);
+ if(old)
+ old->next = ppnext;
+ }
+ else
+ old = pp;
+ pp = ppnext;
+ }
+}
+
+/*
+ * returns library variable from .paths
+ * The value might be returned on the stack overwriting path
+ */
+static char *path_lib(Shell_t *shp,Pathcomp_t *pp, char *path)
+{
+ register char *last = strrchr(path,'/');
+ register int r;
+ struct stat statb;
+ if(last)
+ *last = 0;
+ else
+ path = ".";
+ r = stat(path,&statb);
+ if(last)
+ *last = '/';
+ if(r>=0)
+ {
+ Pathcomp_t pcomp;
+ char save[8];
+ for( ;pp; pp=pp->next)
+ {
+ path_checkdup(shp,pp);
+ if(pp->ino==statb.st_ino && pp->dev==statb.st_dev && pp->mtime==statb.st_mtime)
+ return(pp->lib);
+ }
+ pcomp.len = 0;
+ if(last)
+ pcomp.len = last-path;
+ memcpy((void*)save, (void*)stakptr(PATH_OFFSET+pcomp.len),sizeof(save));
+ if(path_chkpaths(shp,(Pathcomp_t*)0,(Pathcomp_t*)0,&pcomp,PATH_OFFSET))
+ return(stakfreeze(1));
+ memcpy((void*)stakptr(PATH_OFFSET+pcomp.len),(void*)save,sizeof(save));
+ }
+ return(0);
+}
+
+#if 0
+void path_dump(register Pathcomp_t *pp)
+{
+ sfprintf(sfstderr,"dump\n");
+ while(pp)
+ {
+ sfprintf(sfstderr,"pp=%x dev=%d ino=%d len=%d flags=%o name=%.*s\n",
+ pp,pp->dev,pp->ino,pp->len,pp->flags,pp->len,pp->name);
+ pp = pp->next;
+ }
+}
+#endif
+
+/*
+ * check for duplicate directories on PATH
+ */
+static void path_checkdup(Shell_t *shp,register Pathcomp_t *pp)
+{
+ register char *name = pp->name;
+ register Pathcomp_t *oldpp,*first;
+ register int flag=0;
+ struct stat statb;
+ if(stat(name,&statb)<0 || !S_ISDIR(statb.st_mode))
+ {
+ pp->flags |= PATH_SKIP;
+ pp->dev = *name=='/';
+ return;
+ }
+ pp->mtime = statb.st_mtime;
+ pp->ino = statb.st_ino;
+ pp->dev = statb.st_dev;
+ if(*name=='/' && onstdpath(name))
+ flag = PATH_STD_DIR;
+ first = (pp->flags&PATH_CDPATH)?(Pathcomp_t*)shp->cdpathlist:path_get(shp,"");
+ for(oldpp=first; oldpp && oldpp!=pp; oldpp=oldpp->next)
+ {
+ if(pp->ino==oldpp->ino && pp->dev==oldpp->dev && pp->mtime==oldpp->mtime)
+ {
+ flag |= PATH_SKIP;
+ break;
+ }
+ }
+ pp->flags |= flag;
+ if(((pp->flags&(PATH_PATH|PATH_SKIP))==PATH_PATH))
+ {
+ int offset = staktell();
+ stakputs(name);
+ path_chkpaths(shp,first,0,pp,offset);
+ stakseek(offset);
+ }
+}
+
+/*
+ * write the next path to search on the current stack
+ * if last is given, all paths that come before <last> are skipped
+ * the next pathcomp is returned.
+ */
+Pathcomp_t *path_nextcomp(Shell_t *shp,register Pathcomp_t *pp, const char *name, Pathcomp_t *last)
+{
+ Pathcomp_t *ppnext;
+ stakseek(PATH_OFFSET);
+ if(*name=='/')
+ pp = 0;
+ else
+ {
+ for(;pp && pp!=last;pp=ppnext)
+ {
+ ppnext = pp->next;
+ if(!pp->dev && !pp->ino)
+ path_checkdup(shp,pp);
+ if(pp->flags&PATH_SKIP)
+ continue;
+ if(!last || *pp->name!='/')
+ break;
+ }
+ if(!pp) /* this should not happen */
+ pp = last;
+ }
+ if(pp && (pp->name[0]!='.' || pp->name[1]))
+ {
+ if(*pp->name!='/')
+ {
+ stakputs(path_pwd(shp,1));
+ if(*stakptr(staktell()-1)!='/')
+ stakputc('/');
+ }
+ stakwrite(pp->name,pp->len);
+ if(pp->name[pp->len-1]!='/')
+ stakputc('/');
+ }
+ stakputs(name);
+ stakputc(0);
+ while(pp && pp!=last && (pp=pp->next))
+ {
+ if(!(pp->flags&PATH_SKIP))
+ return(pp);
+ }
+ return((Pathcomp_t*)0);
+}
+
+static Pathcomp_t* defpath_init(Shell_t *shp)
+{
+ Pathcomp_t *pp = (void*)path_addpath(shp,(Pathcomp_t*)0,(std_path),PATH_PATH);
+ return(pp);
+}
+
+static void path_init(Shell_t *shp)
+{
+ const char *val;
+ Pathcomp_t *pp;
+ if(!std_path && !(std_path=astconf("PATH",NIL(char*),NIL(char*))))
+ std_path = e_defpath;
+ if(val=sh_scoped(shp,(PATHNOD))->nvalue.cp)
+ {
+ shp->pathlist = pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->pathlist,val,PATH_PATH);
+ }
+ else
+ {
+ if(!(pp=(Pathcomp_t*)shp->defpathlist))
+ pp = defpath_init(shp);
+ shp->pathlist = (void*)path_dup(pp);
+ }
+ if(val=sh_scoped(shp,(FPATHNOD))->nvalue.cp)
+ {
+ pp = (void*)path_addpath(shp,(Pathcomp_t*)shp->pathlist,val,PATH_FPATH);
+ }
+}
+
+/*
+ * returns that pathlist to search
+ */
+Pathcomp_t *path_get(register Shell_t *shp,register const char *name)
+{
+ register Pathcomp_t *pp=0;
+ if(*name && strchr(name,'/'))
+ return(0);
+ if(!sh_isstate(SH_DEFPATH))
+ {
+ if(!shp->pathlist)
+ path_init(shp);
+ pp = (Pathcomp_t*)shp->pathlist;
+ }
+ if(!pp && (!(sh_scoped(shp,PATHNOD)->nvalue.cp)) || sh_isstate(SH_DEFPATH))
+ {
+ if(!(pp=(Pathcomp_t*)shp->defpathlist))
+ pp = defpath_init(shp);
+ }
+ return(pp);
+}
+
+/*
+ * open file corresponding to name using path give by <pp>
+ */
+static int path_opentype(Shell_t *shp,const char *name, register Pathcomp_t *pp, int fun)
+{
+ register int fd= -1;
+ struct stat statb;
+ Pathcomp_t *oldpp;
+ if(!pp && !shp->pathlist)
+ path_init(shp);
+ if(!fun && strchr(name,'/'))
+ {
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,name);
+ }
+ do
+ {
+ pp = path_nextcomp(shp,oldpp=pp,name,0);
+ while(oldpp && (oldpp->flags&PATH_SKIP))
+ oldpp = oldpp->next;
+ if(fun && (!oldpp || !(oldpp->flags&PATH_FPATH)))
+ continue;
+ if((fd = sh_open(path_relative(shp,stakptr(PATH_OFFSET)),O_RDONLY,0)) >= 0)
+ {
+ if(fstat(fd,&statb)<0 || S_ISDIR(statb.st_mode))
+ {
+ errno = EISDIR;
+ sh_close(fd);
+ fd = -1;
+ }
+ }
+ }
+ while( fd<0 && pp);
+ if(fd>=0 && (fd = sh_iomovefd(fd)) > 0)
+ {
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fd] |= IOCLEX;
+ }
+ return(fd);
+}
+
+/*
+ * open file corresponding to name using path give by <pp>
+ */
+int path_open(Shell_t *shp,const char *name, register Pathcomp_t *pp)
+{
+ return(path_opentype(shp,name,pp,0));
+}
+
+/*
+ * given a pathname return the base name
+ */
+
+char *path_basename(register const char *name)
+{
+ register const char *start = name;
+ while (*name)
+ if ((*name++ == '/') && *name) /* don't trim trailing / */
+ start = name;
+ return ((char*)start);
+}
+
+char *path_fullname(Shell_t *shp,const char *name)
+{
+ int len=strlen(name)+1,dirlen=0;
+ char *path,*pwd;
+ if(*name!='/')
+ {
+ pwd = path_pwd(shp,1);
+ dirlen = strlen(pwd)+1;
+ }
+ path = (char*)malloc(len+dirlen);
+ if(dirlen)
+ {
+ memcpy((void*)path,(void*)pwd,dirlen);
+ path[dirlen-1] = '/';
+ }
+ memcpy((void*)&path[dirlen],(void*)name,len);
+ pathcanon(path,0);
+ return(path);
+}
+
+/*
+ * load functions from file <fno>
+ */
+static void funload(Shell_t *shp,int fno, const char *name)
+{
+ char *pname,*oldname=shp->st.filename, buff[IOBSIZE+1];
+ Namval_t *np;
+ struct Ufunction *rp,*rpfirst;
+ int savestates = sh_getstate(), oldload=shp->funload;
+ pname = path_fullname(shp,stakptr(PATH_OFFSET));
+ if(shp->fpathdict && (rp = dtmatch(shp->fpathdict,(void*)pname)))
+ {
+ Dt_t *funtree = sh_subfuntree(1);
+ while(1)
+ {
+ rpfirst = dtprev(shp->fpathdict,rp);
+ if(!rpfirst || strcmp(pname,rpfirst->fname))
+ break;
+ rp = rpfirst;
+ }
+ do
+ {
+ if((np = dtsearch(funtree,rp->np)) && is_afunction(np))
+ {
+ if(np->nvalue.rp)
+ np->nvalue.rp->fdict = 0;
+ nv_delete(np,funtree,NV_NOFREE);
+ }
+ dtinsert(funtree,rp->np);
+ rp->fdict = funtree;
+ }
+ while((rp=dtnext(shp->fpathdict,rp)) && strcmp(pname,rp->fname)==0);
+ sh_close(fno);
+ return;
+ }
+ sh_onstate(SH_NOLOG);
+ sh_onstate(SH_NOALIAS);
+ shp->readscript = (char*)name;
+ shp->st.filename = pname;
+ shp->funload = 1;
+ error_info.line = 0;
+ sh_eval(sfnew(NIL(Sfio_t*),buff,IOBSIZE,fno,SF_READ),SH_FUNEVAL);
+ sh_close(fno);
+ shp->readscript = 0;
+#if SHOPT_NAMESPACE
+ if(shp->namespace)
+ np = sh_fsearch(shp,name,0);
+ else
+#endif /* SHOPT_NAMESPACE */
+ np = nv_search(name,shp->fun_tree,0);
+ if(!np || !np->nvalue.ip)
+ pname = stakcopy(shp->st.filename);
+ else
+ pname = 0;
+ free((void*)shp->st.filename);
+ shp->funload = oldload;
+ shp->st.filename = oldname;
+ sh_setstate(savestates);
+ if(pname)
+ errormsg(SH_DICT,ERROR_exit(ERROR_NOEXEC),e_funload,name,pname);
+}
+
+/*
+ * do a path search and track alias if requested
+ * if flag is 0, or if name not found, then try autoloading function
+ * if flag==2 or 3, returns 1 if name found on FPATH
+ * if flag==3 no tracked alias will be set
+ * returns 1, if function was autoloaded.
+ * If oldpp is not NULL, it will contain a pointer to the path component
+ * where it was found.
+ */
+
+int path_search(Shell_t *shp,register const char *name,Pathcomp_t **oldpp, int flag)
+{
+ register Namval_t *np;
+ register int fno;
+ Pathcomp_t *pp=0;
+ if(name && strchr(name,'/'))
+ {
+ stakseek(PATH_OFFSET);
+ stakputs(name);
+ if(canexecute(shp,stakptr(PATH_OFFSET),0)<0)
+ {
+ *stakptr(PATH_OFFSET) = 0;
+ return(0);
+ }
+ if(*name=='/')
+ return(1);
+ stakseek(PATH_OFFSET);
+ stakputs(path_pwd(shp,1));
+ stakputc('/');
+ stakputs(name);
+ stakputc(0);
+ return(0);
+ }
+ if(sh_isstate(SH_DEFPATH))
+ {
+ if(!shp->defpathlist)
+ defpath_init(shp);
+ }
+ else if(!shp->pathlist)
+ path_init(shp);
+ if(flag)
+ {
+ if(!(flag&1) && (np=nv_search(name,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && (pp=(Pathcomp_t*)np->nvalue.cp))
+ {
+ stakseek(PATH_OFFSET);
+ path_nextcomp(shp,pp,name,pp);
+ if(oldpp)
+ *oldpp = pp;
+ stakputc(0);
+ return(0);
+ }
+ pp = path_absolute(shp,name,oldpp?*oldpp:NIL(Pathcomp_t*));
+ if(oldpp)
+ *oldpp = pp;
+ if(!pp && (np=nv_search(name,shp->fun_tree,0))&&np->nvalue.ip)
+ return(1);
+ if(!pp)
+ *stakptr(PATH_OFFSET) = 0;
+ }
+ if(flag==0 || !pp || (pp->flags&PATH_FPATH))
+ {
+ if(!pp)
+ pp=sh_isstate(SH_DEFPATH)?shp->defpathlist:shp->pathlist;
+ if(pp && strmatch(name,e_alphanum) && (fno=path_opentype(shp,name,pp,1))>=0)
+ {
+ if(flag==2)
+ {
+ sh_close(fno);
+ return(1);
+ }
+ funload(shp,fno,name);
+ return(1);
+ }
+ *stakptr(PATH_OFFSET) = 0;
+ return(0);
+ }
+ else if(pp && !sh_isstate(SH_DEFPATH) && *name!='/' && flag<3)
+ {
+ if(np=nv_search(name,shp->track_tree,NV_ADD))
+ path_alias(np,pp);
+ }
+ return(0);
+}
+
+/*
+ * do a path search and find the full pathname of file name
+ */
+Pathcomp_t *path_absolute(Shell_t *shp,register const char *name, Pathcomp_t *pp)
+{
+ register int f,isfun;
+ int noexec=0;
+ Pathcomp_t *oldpp;
+ Namval_t *np;
+ char *cp;
+ shp->path_err = ENOENT;
+ if(!pp && !(pp=path_get(shp,"")))
+ return(0);
+ shp->path_err = 0;
+ while(1)
+ {
+ sh_sigcheck(shp);
+ isfun = (pp->flags&PATH_FPATH);
+ if(oldpp=pp)
+ {
+ pp = path_nextcomp(shp,pp,name,0);
+ while(oldpp->flags&PATH_SKIP)
+ {
+ if(!(oldpp=oldpp->next))
+ {
+ shp->path_err = ENOENT;
+ return(0);
+ }
+ }
+ }
+
+ if(!isfun && !sh_isoption(SH_RESTRICTED))
+ {
+ if(*stakptr(PATH_OFFSET)=='/' && nv_search(stakptr(PATH_OFFSET),shp->bltin_tree,0))
+ return(oldpp);
+#if SHOPT_DYNAMIC
+ if(oldpp->blib)
+ {
+ Shbltin_f addr;
+ int n = staktell();
+ char *cp;
+ stakputs("b_");
+ stakputs(name);
+ stakputc(0);
+ if(!oldpp->bltin_lib)
+ {
+ if(cp = strrchr(oldpp->blib,'/'))
+ cp++;
+ else
+ cp = oldpp->blib;
+ if(!strcmp(cp,LIBCMD) && (addr=(Shbltin_f)dlllook((void*)0,stakptr(n))))
+ {
+ if((np = sh_addbuiltin(stakptr(PATH_OFFSET),addr,NiL)) && nv_isattr(np,NV_BLTINOPT))
+ return(oldpp);
+ }
+#ifdef SH_PLUGIN_VERSION
+ if (oldpp->bltin_lib = dllplugin(SH_ID, oldpp->blib, NiL, SH_PLUGIN_VERSION, NiL, RTLD_LAZY, NiL, 0))
+ sh_addlib(shp,oldpp->bltin_lib);
+#else
+#if (_AST_VERSION>=20040404)
+ if (oldpp->bltin_lib = dllplug(SH_ID, oldpp->blib, NiL, RTLD_LAZY, NiL, 0))
+#else
+ if (oldpp->bltin_lib = dllfind(oldpp->blib, NiL, RTLD_LAZY, NiL, 0))
+#endif
+ {
+ /*
+ * this detects the 2007-05-11 builtin context change and also
+ * the 2008-03-30 opt_info.num change that hit libcmd::b_head
+ */
+
+ if (libcmd && !dlllook(oldpp->bltin_lib, "b_pids"))
+ {
+ dlclose(oldpp->bltin_lib);
+ oldpp->bltin_lib = 0;
+ oldpp->blib = 0;
+ }
+ else
+ sh_addlib(shp,oldpp->bltin_lib);
+ }
+#endif
+ }
+ if(oldpp->bltin_lib &&
+ (addr=(Shbltin_f)dlllook(oldpp->bltin_lib,stakptr(n))) &&
+ (!(np = sh_addbuiltin(stakptr(PATH_OFFSET),NiL,NiL)) || np->nvalue.bfp!=(Nambfp_f)addr) &&
+ (np = sh_addbuiltin(stakptr(PATH_OFFSET),addr,NiL)))
+ {
+ np->nvenv = oldpp->bltin_lib;
+ return(oldpp);
+ }
+ }
+#endif /* SHOPT_DYNAMIC */
+ }
+ sh_stats(STAT_PATHS);
+ f = canexecute(shp,stakptr(PATH_OFFSET),isfun);
+ if(isfun && f>=0 && (cp = strrchr(name,'.')))
+ {
+ *cp = 0;
+ if(nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE))
+ f = -1;
+ *cp = '.';
+ }
+ if(isfun && f>=0)
+ {
+ nv_onattr(nv_open(name,sh_subfuntree(1),NV_NOARRAY|NV_IDENT|NV_NOSCOPE),NV_LTOU|NV_FUNCTION);
+ funload(shp,f,name);
+ close(f);
+ f = -1;
+ return(0);
+ }
+ else if(f>=0 && (oldpp->flags & PATH_STD_DIR))
+ {
+ int n = staktell();
+ stakputs("/bin/");
+ stakputs(name);
+ stakputc(0);
+ np = nv_search(stakptr(n),shp->bltin_tree,0);
+ stakseek(n);
+ if(np)
+ {
+ n = np->nvflag;
+ np = sh_addbuiltin(stakptr(PATH_OFFSET),(Shbltin_f)np->nvalue.bfp,nv_context(np));
+ np->nvflag = n;
+ }
+ }
+ if(!pp || f>=0)
+ break;
+ if(errno!=ENOENT)
+ noexec = errno;
+ }
+ if(f<0)
+ {
+ shp->path_err = (noexec?noexec:ENOENT);
+ return(0);
+ }
+ stakputc(0);
+ return(oldpp);
+}
+
+/*
+ * returns 0 if path can execute
+ * sets exec_err if file is found but can't be executable
+ */
+#undef S_IXALL
+#ifdef S_IXUSR
+# define S_IXALL (S_IXUSR|S_IXGRP|S_IXOTH)
+#else
+# ifdef S_IEXEC
+# define S_IXALL (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6))
+# else
+# define S_IXALL 0111
+# endif /*S_EXEC */
+#endif /* S_IXUSR */
+
+static int canexecute(Shell_t *shp,register char *path, int isfun)
+{
+ struct stat statb;
+ register int fd=0;
+ path = path_relative(shp,path);
+ if(isfun)
+ {
+ if((fd=open(path,O_RDONLY,0))<0 || fstat(fd,&statb)<0)
+ goto err;
+ }
+ else if(stat(path,&statb) < 0)
+ {
+#if _WINIX
+ /* check for .exe or .bat suffix */
+ char *cp;
+ if(errno==ENOENT && (!(cp=strrchr(path,'.')) || strlen(cp)>4 || strchr(cp,'/')))
+ {
+ int offset = staktell()-1;
+ stakseek(offset);
+ stakputs(".bat");
+ path = stakptr(PATH_OFFSET);
+ if(stat(path,&statb) < 0)
+ {
+ if(errno!=ENOENT)
+ goto err;
+ memcpy(stakptr(offset),".sh",4);
+ if(stat(path,&statb) < 0)
+ goto err;
+ }
+ }
+ else
+#endif /* _WINIX */
+ goto err;
+ }
+ errno = EPERM;
+ if(S_ISDIR(statb.st_mode))
+ errno = EISDIR;
+ else if((statb.st_mode&S_IXALL)==S_IXALL || sh_access(path,X_OK)>=0)
+ return(fd);
+ if(isfun && fd>=0)
+ sh_close(fd);
+err:
+ return(-1);
+}
+
+/*
+ * Return path relative to present working directory
+ */
+
+char *path_relative(Shell_t *shp,register const char* file)
+{
+ register const char *pwd;
+ register const char *fp = file;
+ /* can't relpath when shp->pwd not set */
+ if(!(pwd=shp->pwd))
+ return((char*)fp);
+ while(*pwd==*fp)
+ {
+ if(*pwd++==0)
+ return((char*)e_dot);
+ fp++;
+ }
+ if(*pwd==0 && *fp == '/')
+ {
+ while(*++fp=='/');
+ if(*fp)
+ return((char*)fp);
+ return((char*)e_dot);
+ }
+ return((char*)file);
+}
+
+void path_exec(Shell_t *shp,register const char *arg0,register char *argv[],struct argnod *local)
+{
+ char **envp;
+ const char *opath;
+ Pathcomp_t *libpath, *pp=0;
+ int slash=0;
+ nv_setlist(local,NV_EXPORT|NV_IDENT|NV_ASSIGN,0);
+ envp = sh_envgen();
+ if(strchr(arg0,'/'))
+ {
+ slash=1;
+ /* name containing / not allowed for restricted shell */
+ if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,arg0);
+ }
+ else
+ pp=path_get(shp,arg0);
+ shp->path_err= ENOENT;
+ sfsync(NIL(Sfio_t*));
+ timerdel(NIL(void*));
+ /* find first path that has a library component */
+ while(pp && (pp->flags&PATH_SKIP))
+ pp = pp->next;
+ if(pp || slash) do
+ {
+ sh_sigcheck(shp);
+ if(libpath=pp)
+ {
+ pp = path_nextcomp(shp,pp,arg0,0);
+ opath = stakfreeze(1)+PATH_OFFSET;
+ }
+ else
+ opath = arg0;
+ path_spawn(shp,opath,argv,envp,libpath,0);
+ while(pp && (pp->flags&PATH_FPATH))
+ pp = path_nextcomp(shp,pp,arg0,0);
+ }
+ while(pp);
+ /* force an exit */
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPEXIT;
+ if((errno=shp->path_err)==ENOENT)
+ errormsg(SH_DICT,ERROR_exit(ERROR_NOENT),e_found,arg0);
+ else
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,arg0);
+}
+
+pid_t path_spawn(Shell_t *shp,const char *opath,register char **argv, char **envp, Pathcomp_t *libpath, int spawn)
+{
+ register char *path;
+ char **xp=0, *xval, *libenv = (libpath?libpath->lib:0);
+ Namval_t* np;
+ char *s, *v;
+ int r, n, pidsize;
+ pid_t pid= -1;
+ /* leave room for inserting _= pathname in environment */
+ envp--;
+#if _lib_readlink
+ /* save original pathname */
+ stakseek(PATH_OFFSET);
+ pidsize = sfprintf(stkstd,"*%d*",spawn?getpid():getppid());
+ stakputs(opath);
+ opath = stakfreeze(1)+PATH_OFFSET+pidsize;
+ np=nv_search(argv[0],shp->track_tree,0);
+ while(libpath && !libpath->lib)
+ libpath=libpath->next;
+ if(libpath && (!np || nv_size(np)>0))
+ {
+ /* check for symlink and use symlink name */
+ char buff[PATH_MAX+1];
+ char save[PATH_MAX+1];
+ stakseek(PATH_OFFSET);
+ stakputs(opath);
+ path = stakptr(PATH_OFFSET);
+ while((n=readlink(path,buff,PATH_MAX))>0)
+ {
+ buff[n] = 0;
+ n = PATH_OFFSET;
+ r = 0;
+ if((v=strrchr(path,'/')) && *buff!='/')
+ {
+ if(buff[0]=='.' && buff[1]=='.' && (r = strlen(path) + 1) <= PATH_MAX)
+ memcpy(save, path, r);
+ else
+ r = 0;
+ n += (v+1-path);
+ }
+ stakseek(n);
+ stakputs(buff);
+ stakputc(0);
+ path = stakptr(PATH_OFFSET);
+ if(v && buff[0]=='.' && buff[1]=='.')
+ {
+ pathcanon(path, 0);
+ if(r && access(path,X_OK))
+ {
+ memcpy(path, save, r);
+ break;
+ }
+ }
+ if(libenv = path_lib(shp,libpath,path))
+ break;
+ }
+ stakseek(0);
+ }
+#endif
+ if(libenv && (v = strchr(libenv,'=')))
+ {
+ n = v - libenv;
+ *v = 0;
+ np = nv_open(libenv,shp->var_tree,0);
+ *v = '=';
+ s = nv_getval(np);
+ stakputs(libenv);
+ if(s)
+ {
+ stakputc(':');
+ stakputs(s);
+ }
+ v = stakfreeze(1);
+ r = 1;
+ xp = envp + 1;
+ while (s = *xp++)
+ {
+ if (strneq(s, v, n) && s[n] == '=')
+ {
+ xval = *--xp;
+ *xp = v;
+ r = 0;
+ break;
+ }
+ }
+ if (r)
+ {
+ *envp-- = v;
+ xp = 0;
+ }
+ }
+ if(!opath)
+ opath = stakptr(PATH_OFFSET);
+ envp[0] = (char*)opath-(PATH_OFFSET+pidsize);
+ envp[0][0] = '_';
+ envp[0][1] = '=';
+ sfsync(sfstderr);
+ sh_sigcheck(shp);
+ path = path_relative(shp,opath);
+#ifdef SHELLMAGIC
+ if(*path!='/' && path!=opath)
+ {
+ /*
+ * The following code because execv(foo,) and execv(./foo,)
+ * may not yield the same results
+ */
+ char *sp = (char*)malloc(strlen(path)+3);
+ sp[0] = '.';
+ sp[1] = '/';
+ strcpy(sp+2,path);
+ path = sp;
+ }
+#endif /* SHELLMAGIC */
+ if(spawn && !sh_isoption(SH_PFSH))
+ pid = _spawnveg(shp,opath, &argv[0],envp, spawn>>1);
+ else
+ pid = path_pfexecve(shp,opath, &argv[0] ,envp,spawn);
+ if(xp)
+ *xp = xval;
+#ifdef SHELLMAGIC
+ if(*path=='.' && path!=opath)
+ {
+ free(path);
+ path = path_relative(shp,opath);
+ }
+#endif /* SHELLMAGIC */
+ if(pid>0)
+ return(pid);
+retry:
+ switch(shp->path_err = errno)
+ {
+#ifdef apollo
+ /*
+ * On apollo's execve will fail with eacces when
+ * file has execute but not read permissions. So,
+ * for now we will pretend that EACCES and ENOEXEC
+ * mean the same thing.
+ */
+ case EACCES:
+#endif /* apollo */
+ case ENOEXEC:
+#if SHOPT_SUID_EXEC
+ case EPERM:
+ /* some systems return EPERM if setuid bit is on */
+#endif
+ errno = ENOEXEC;
+ if(spawn)
+ {
+#ifdef _lib_fork
+ if(shp->subshell)
+ return(-1);
+ do
+ {
+ if((pid=fork())>0)
+ return(pid);
+ }
+ while(_sh_fork(shp,pid,0,(int*)0) < 0);
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPEXIT;
+#else
+ return(-1);
+#endif
+ }
+ exscript(shp,path,argv,envp);
+#ifndef apollo
+ case EACCES:
+ {
+ struct stat statb;
+ if(stat(path,&statb)>=0)
+ {
+ if(S_ISDIR(statb.st_mode))
+ errno = EISDIR;
+#ifdef S_ISSOCK
+ if(S_ISSOCK(statb.st_mode))
+ exscript(shp,path,argv,envp);
+#endif
+ }
+ }
+ /* FALL THROUGH */
+#endif /* !apollo */
+#ifdef ENAMETOOLONG
+ case ENAMETOOLONG:
+#endif /* ENAMETOOLONG */
+#if !SHOPT_SUID_EXEC
+ case EPERM:
+#endif
+ shp->path_err = errno;
+ return(-1);
+ case ENOTDIR:
+ case ENOENT:
+ case EINTR:
+#ifdef EMLINK
+ case EMLINK:
+#endif /* EMLINK */
+ return(-1);
+ case E2BIG:
+ if(shp->xargmin)
+ {
+ pid = path_xargs(shp,opath, &argv[0] ,envp,spawn);
+ if(pid<0)
+ goto retry;
+ return(pid);
+ }
+ default:
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,path);
+ }
+ return 0;
+}
+
+/*
+ * File is executable but not machine code.
+ * Assume file is a Shell script and execute it.
+ */
+
+static void exscript(Shell_t *shp,register char *path,register char *argv[],char **envp)
+{
+ register Sfio_t *sp;
+ path = path_relative(shp,path);
+ shp->comdiv=0;
+ shp->bckpid = 0;
+ shp->coshell = 0;
+ shp->st.ioset=0;
+ /* clean up any cooperating processes */
+ if(shp->cpipe[0]>0)
+ sh_pclose(shp->cpipe);
+ if(shp->cpid && shp->outpipe)
+ sh_close(*shp->outpipe);
+ shp->cpid = 0;
+ if(sp=fcfile())
+ while(sfstack(sp,SF_POPSTACK));
+ job_clear();
+ if(shp->infd>0 && (shp->fdstatus[shp->infd]&IOCLEX))
+ sh_close(shp->infd);
+ sh_setstate(sh_state(SH_FORKED));
+ sfsync(sfstderr);
+#if SHOPT_SUID_EXEC && !SHOPT_PFSH
+ /* check if file cannot open for read or script is setuid/setgid */
+ {
+ static char name[] = "/tmp/euidXXXXXXXXXX";
+ register int n;
+ register uid_t euserid;
+ char *savet=0;
+ struct stat statb;
+ if((n=sh_open(path,O_RDONLY,0)) >= 0)
+ {
+ /* move <n> if n=0,1,2 */
+ n = sh_iomovefd(n);
+ if(fstat(n,&statb)>=0 && !(statb.st_mode&(S_ISUID|S_ISGID)))
+ goto openok;
+ sh_close(n);
+ }
+ if((euserid=geteuid()) != shp->gd->userid)
+ {
+ strncpy(name+9,fmtbase((long)getpid(),10,0),sizeof(name)-10);
+ /* create a suid open file with owner equal effective uid */
+ if((n=open(name,O_CREAT|O_TRUNC|O_WRONLY,S_ISUID|S_IXUSR)) < 0)
+ goto fail;
+ unlink(name);
+ /* make sure that file has right owner */
+ if(fstat(n,&statb)<0 || statb.st_uid != euserid)
+ goto fail;
+ if(n!=10)
+ {
+ sh_close(10);
+ fcntl(n, F_DUPFD, 10);
+ sh_close(n);
+ n=10;
+ }
+ }
+ savet = *--argv;
+ *argv = path;
+ path_pfexecve(shp,e_suidexec,argv,envp,0);
+ fail:
+ /*
+ * The following code is just for compatibility
+ */
+ if((n=open(path,O_RDONLY,0)) < 0)
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,path);
+ if(savet)
+ *argv++ = savet;
+ openok:
+ shp->infd = n;
+ }
+#else
+ if((shp->infd = sh_open(path,O_RDONLY,0)) < 0)
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,path);
+#endif
+ shp->infd = sh_iomovefd(shp->infd);
+#if SHOPT_ACCT
+ sh_accbegin(path) ; /* reset accounting */
+#endif /* SHOPT_ACCT */
+ shp->arglist = sh_argcreate(argv);
+ shp->lastarg = strdup(path);
+ /* save name of calling command */
+ shp->readscript = error_info.id;
+ /* close history file if name has changed */
+ if(shp->gd->hist_ptr && (path=nv_getval(HISTFILE)) && strcmp(path,shp->gd->hist_ptr->histname))
+ {
+ hist_close(shp->gd->hist_ptr);
+ (HISTCUR)->nvalue.lp = 0;
+ }
+ sh_offstate(SH_FORKED);
+ if(shp->sigflag[SIGCHLD]==SH_SIGOFF)
+ shp->sigflag[SIGCHLD] = SH_SIGFAULT;
+ siglongjmp(*shp->jmplist,SH_JMPSCRIPT);
+}
+
+#if SHOPT_ACCT
+# include <sys/acct.h>
+# include "FEATURE/time"
+
+ static struct acct sabuf;
+ static struct tms buffer;
+ static clock_t before;
+ static char *SHACCT; /* set to value of SHACCT environment variable */
+ static shaccton; /* non-zero causes accounting record to be written */
+ static int compress(time_t);
+ /*
+ * initialize accounting, i.e., see if SHACCT variable set
+ */
+ void sh_accinit(void)
+ {
+ SHACCT = getenv("SHACCT");
+ }
+ /*
+ * suspend accounting until turned on by sh_accbegin()
+ */
+ void sh_accsusp(void)
+ {
+ shaccton=0;
+#ifdef AEXPAND
+ sabuf.ac_flag |= AEXPND;
+#endif /* AEXPAND */
+ }
+
+ /*
+ * begin an accounting record by recording start time
+ */
+ void sh_accbegin(const char *cmdname)
+ {
+ if(SHACCT)
+ {
+ sabuf.ac_btime = time(NIL(time_t *));
+ before = times(&buffer);
+ sabuf.ac_uid = getuid();
+ sabuf.ac_gid = getgid();
+ strncpy(sabuf.ac_comm, (char*)path_basename(cmdname),
+ sizeof(sabuf.ac_comm));
+ shaccton = 1;
+ }
+ }
+ /*
+ * terminate an accounting record and append to accounting file
+ */
+ void sh_accend(void)
+ {
+ int fd;
+ clock_t after;
+
+ if(shaccton)
+ {
+ after = times(&buffer);
+ sabuf.ac_utime = compress(buffer.tms_utime + buffer.tms_cutime);
+ sabuf.ac_stime = compress(buffer.tms_stime + buffer.tms_cstime);
+ sabuf.ac_etime = compress( (time_t)(after-before));
+ fd = open( SHACCT , O_WRONLY | O_APPEND | O_CREAT,RW_ALL);
+ write(fd, (const char*)&sabuf, sizeof( sabuf ));
+ close( fd);
+ }
+ }
+
+ /*
+ * Produce a pseudo-floating point representation
+ * with 3 bits base-8 exponent, 13 bits fraction.
+ */
+ static int compress(register time_t t)
+ {
+ register int exp = 0, rund = 0;
+
+ while (t >= 8192)
+ {
+ exp++;
+ rund = t&04;
+ t >>= 3;
+ }
+ if (rund)
+ {
+ t++;
+ if (t >= 8192)
+ {
+ t >>= 3;
+ exp++;
+ }
+ }
+ return((exp<<13) + t);
+ }
+#endif /* SHOPT_ACCT */
+
+
+
+/*
+ * add a pathcomponent to the path search list and eliminate duplicates
+ * and non-existing absolute paths.
+ */
+static Pathcomp_t *path_addcomp(Shell_t *shp,Pathcomp_t *first, Pathcomp_t *old,const char *name, int flag)
+{
+ register Pathcomp_t *pp, *oldpp;
+ int len, offset=staktell();
+ if(!(flag&PATH_BFPATH))
+ {
+ register const char *cp = name;
+ while(*cp && *cp!=':')
+ stakputc(*cp++);
+ len = staktell()-offset;
+ stakputc(0);
+ stakseek(offset);
+ name = (const char*)stakptr(offset);
+ }
+ else
+ len = strlen(name);
+ for(pp=first; pp; pp=pp->next)
+ {
+ if(memcmp(name,pp->name,len)==0 && (pp->name[len]==':' || pp->name[len]==0))
+ {
+ pp->flags |= flag;
+ return(first);
+ }
+ }
+ for(pp=first, oldpp=0; pp; oldpp=pp, pp=pp->next);
+ pp = newof((Pathcomp_t*)0,Pathcomp_t,1,len+1);
+ pp->shp = shp;
+ pp->refcount = 1;
+ memcpy((char*)(pp+1),name,len+1);
+ pp->name = (char*)(pp+1);
+ pp->len = len;
+ if(oldpp)
+ oldpp->next = pp;
+ else
+ first = pp;
+ pp->flags = flag;
+ if(strcmp(name,SH_CMDLIB_DIR)==0)
+ {
+ pp->dev = 1;
+ pp->flags |= PATH_BUILTIN_LIB;
+ pp->blib = malloc(4);
+ strcpy(pp->blib,LIBCMD);
+ return(first);
+ }
+ if((old||shp->pathinit) && ((flag&(PATH_PATH|PATH_SKIP))==PATH_PATH))
+ path_chkpaths(shp,first,old,pp,offset);
+ return(first);
+}
+
+/*
+ * This function checks for the .paths file in directory in <pp>
+ * it assumes that the directory is on the stack at <offset>
+ */
+static int path_chkpaths(Shell_t *shp,Pathcomp_t *first, Pathcomp_t* old,Pathcomp_t *pp, int offset)
+{
+ struct stat statb;
+ int k,m,n,fd;
+ char *sp,*cp,*ep;
+ stakseek(offset+pp->len);
+ if(pp->len==1 && *stakptr(offset)=='/')
+ stakseek(offset);
+ stakputs("/.paths");
+ if((fd=open(stakptr(offset),O_RDONLY))>=0)
+ {
+ fstat(fd,&statb);
+ n = statb.st_size;
+ stakseek(offset+pp->len+n+2);
+ sp = stakptr(offset+pp->len);
+ *sp++ = '/';
+ n=read(fd,cp=sp,n);
+ sp[n] = 0;
+ close(fd);
+ for(ep=0; n--; cp++)
+ {
+ if(*cp=='=')
+ {
+ ep = cp+1;
+ continue;
+ }
+ else if(*cp!='\r' && *cp!='\n')
+ continue;
+ if(*sp=='#' || sp==cp)
+ {
+ sp = cp+1;
+ continue;
+ }
+ *cp = 0;
+ m = ep ? (ep-sp) : 0;
+ if(m==0 || m==6 && memcmp((void*)sp,(void*)"FPATH=",6)==0)
+ {
+ if(first)
+ {
+ char *ptr = stakptr(offset+pp->len+1);
+ if(ep)
+ strcpy(ptr,ep);
+ path_addcomp(shp,first,old,stakptr(offset),PATH_FPATH|PATH_BFPATH);
+ }
+ }
+ else if(m==12 && memcmp((void*)sp,(void*)"BUILTIN_LIB=",12)==0)
+ {
+ if(!(pp->flags & PATH_BUILTIN_LIB) || strchr(ep,'-'))
+ {
+ if ((pp->flags & (PATH_BUILTIN_LIB|PATH_STD_DIR)) == PATH_BUILTIN_LIB)
+ {
+ free(pp->blib);
+ pp->blib = 0;
+ }
+ pp->flags |= PATH_BUILTIN_LIB;
+ if (*ep == '.' && !*(ep + 1))
+ pp->flags |= PATH_STD_DIR;
+ else
+ {
+ k = strlen(ep)+1;
+ if (*ep != '/')
+ k += pp->len+1;
+ pp->blib = sp = malloc(k);
+ if (*ep != '/')
+ {
+ strcpy(pp->blib,pp->name);
+ sp += pp->len;
+ *sp++ = '/';
+ }
+ strcpy(sp,ep);
+ }
+ }
+ }
+ else if(m)
+ {
+ pp->lib = (char*)malloc(cp-sp+pp->len+2);
+ memcpy((void*)pp->lib,(void*)sp,m);
+ memcpy((void*)&pp->lib[m],stakptr(offset),pp->len);
+ pp->lib[k=m+pp->len] = '/';
+ strcpy((void*)&pp->lib[k+1],ep);
+ pathcanon(&pp->lib[m],0);
+ if(!first)
+ {
+ stakseek(0);
+ stakputs(pp->lib);
+ free((void*)pp->lib);
+ return(1);
+ }
+ }
+ sp = cp+1;
+ ep = 0;
+ }
+ }
+ return(0);
+}
+
+
+Pathcomp_t *path_addpath(Shell_t *shp,Pathcomp_t *first, register const char *path,int type)
+{
+ register const char *cp;
+ Pathcomp_t *old=0;
+ int offset = staktell();
+ char *savptr;
+
+ if(!path && type!=PATH_PATH)
+ return(first);
+ if(type!=PATH_FPATH)
+ {
+ old = first;
+ first = 0;
+ }
+ if(offset)
+ savptr = stakfreeze(0);
+ if(path) while(*(cp=path))
+ {
+ if(*cp==':')
+ {
+ if(type!=PATH_FPATH)
+ first = path_addcomp(shp,first,old,".",type);
+ while(*++path == ':');
+ }
+ else
+ {
+ int c;
+ while(*path && *path!=':')
+ path++;
+ c = *path++;
+ first = path_addcomp(shp,first,old,cp,type);
+ if(c==0)
+ break;
+ if(*path==0)
+ path--;
+ }
+ }
+ if(old)
+ {
+ if(!first && !path)
+ {
+ Pathcomp_t *pp = (Pathcomp_t*)shp->defpathlist;
+ if(!pp)
+ pp = defpath_init(shp);
+ first = path_dup(pp);
+ }
+ if(cp=(sh_scoped(shp,FPATHNOD))->nvalue.cp)
+ first = (void*)path_addpath(shp,(Pathcomp_t*)first,cp,PATH_FPATH);
+ path_delete(old);
+ }
+ if(offset)
+ stakset(savptr,offset);
+ else
+ stakseek(0);
+ return(first);
+}
+
+/*
+ * duplicate the path give by <first> by incremented reference counts
+ */
+Pathcomp_t *path_dup(Pathcomp_t *first)
+{
+ register Pathcomp_t *pp=first;
+ while(pp)
+ {
+ pp->refcount++;
+ pp = pp->next;
+ }
+ return(first);
+}
+
+/*
+ * called whenever the directory is changed
+ */
+void path_newdir(Shell_t *shp,Pathcomp_t *first)
+{
+ register Pathcomp_t *pp=first, *next, *pq;
+ struct stat statb;
+ for(pp=first; pp; pp=pp->next)
+ {
+ pp->flags &= ~PATH_SKIP;
+ if(*pp->name=='/')
+ continue;
+ /* delete .paths component */
+ if((next=pp->next) && (next->flags&PATH_BFPATH))
+ {
+ pp->next = next->next;
+ if(--next->refcount<=0)
+ free((void*)next);
+ }
+ if(stat(pp->name,&statb)<0 || !S_ISDIR(statb.st_mode))
+ {
+ pp->dev = 0;
+ pp->ino = 0;
+ continue;
+ }
+ pp->dev = statb.st_dev;
+ pp->ino = statb.st_ino;
+ pp->mtime = statb.st_mtime;
+ for(pq=first;pq!=pp;pq=pq->next)
+ {
+ if(pp->ino==pq->ino && pp->dev==pq->dev)
+ pp->flags |= PATH_SKIP;
+ }
+ for(pq=pp;pq=pq->next;)
+ {
+ if(pp->ino==pq->ino && pp->dev==pq->dev)
+ pq->flags |= PATH_SKIP;
+ }
+ if((pp->flags&(PATH_PATH|PATH_SKIP))==PATH_PATH)
+ {
+ /* try to insert .paths component */
+ int offset = staktell();
+ stakputs(pp->name);
+ stakseek(offset);
+ next = pp->next;
+ pp->next = 0;
+ path_chkpaths(shp,first,(Pathcomp_t*)0,pp,offset);
+ if(pp->next)
+ pp = pp->next;
+ pp->next = next;
+ }
+ }
+#if 0
+ path_dump(first);
+#endif
+}
+
+Pathcomp_t *path_unsetfpath(Shell_t *shp)
+{
+ Pathcomp_t *first = (Pathcomp_t*)shp->pathlist;
+ register Pathcomp_t *pp=first, *old=0;
+ if(shp->fpathdict)
+ {
+ struct Ufunction *rp, *rpnext;
+ for(rp=(struct Ufunction*)dtfirst(shp->fpathdict);rp;rp=rpnext)
+ {
+ rpnext = (struct Ufunction*)dtnext(shp->fpathdict,rp);
+ if(rp->fdict)
+ nv_delete(rp->np,rp->fdict,NV_NOFREE);
+ rp->fdict = 0;
+ }
+ }
+ while(pp)
+ {
+ if((pp->flags&PATH_FPATH) && !(pp->flags&PATH_BFPATH))
+ {
+ if(pp->flags&PATH_PATH)
+ pp->flags &= ~PATH_FPATH;
+ else
+ {
+ Pathcomp_t *ppsave=pp;
+ if(old)
+ old->next = pp->next;
+ else
+ first = pp->next;
+ pp = pp->next;
+ if(--ppsave->refcount<=0)
+ {
+ if(ppsave->lib)
+ free((void*)ppsave->lib);
+ free((void*)ppsave);
+ }
+ continue;
+ }
+
+ }
+ old = pp;
+ pp = pp->next;
+ }
+ return(first);
+}
+
+Pathcomp_t *path_dirfind(Pathcomp_t *first,const char *name,int c)
+{
+ register Pathcomp_t *pp=first;
+ while(pp)
+ {
+ if(memcmp(name,pp->name,pp->len)==0 && name[pp->len]==c)
+ return(pp);
+ pp = pp->next;
+ }
+ return(0);
+}
+
+/*
+ * get discipline for tracked alias
+ */
+static char *talias_get(Namval_t *np, Namfun_t *nvp)
+{
+ Pathcomp_t *pp = (Pathcomp_t*)np->nvalue.cp;
+ char *ptr;
+ if(!pp)
+ return(NULL);
+ path_nextcomp(pp->shp,pp,nv_name(np),pp);
+ ptr = stakfreeze(0);
+ return(ptr+PATH_OFFSET);
+}
+
+static void talias_put(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ if(!val && np->nvalue.cp)
+ {
+ Pathcomp_t *pp = (Pathcomp_t*)np->nvalue.cp;
+ if(--pp->refcount<=0)
+ free((void*)pp);
+ }
+ nv_putv(np,val,flags,fp);
+}
+
+static const Namdisc_t talias_disc = { 0, talias_put, talias_get };
+static Namfun_t talias_init = { &talias_disc, 1 };
+
+/*
+ * set tracked alias node <np> to value <pp>
+ */
+void path_alias(register Namval_t *np,register Pathcomp_t *pp)
+{
+ if(pp)
+ {
+ struct stat statb;
+ char *sp;
+ nv_offattr(np,NV_NOPRINT);
+ nv_stack(np,&talias_init);
+ np->nvalue.cp = (char*)pp;
+ pp->refcount++;
+ nv_setattr(np,NV_TAGGED|NV_NOFREE);
+ path_nextcomp(pp->shp,pp,nv_name(np),pp);
+ sp = stakptr(PATH_OFFSET);
+ if(sp && lstat(sp,&statb)>=0 && S_ISLNK(statb.st_mode))
+ nv_setsize(np,statb.st_size+1);
+ else
+ nv_setsize(np,0);
+ }
+ else
+ _nv_unset(np,0);
+}
+
diff --git a/src/cmd/ksh93/sh/pmain.c b/src/cmd/ksh93/sh/pmain.c
new file mode 100644
index 0000000..8742195
--- /dev/null
+++ b/src/cmd/ksh93/sh/pmain.c
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <shell.h>
+
+#include "FEATURE/externs"
+
+#if defined(__sun) && _sys_mman && _lib_memcntl && defined(MHA_MAPSIZE_STACK) && defined(MC_HAT_ADVISE)
+# undef VM_FLAGS /* solaris vs vmalloc.h symbol clash */
+# include <sys/mman.h>
+#else
+# undef _lib_memcntl
+#endif
+
+typedef int (*Shnote_f)(int, long, int);
+
+int main(int argc, char *argv[])
+{
+#if _lib_memcntl
+ /* advise larger stack size */
+ struct memcntl_mha mha;
+ mha.mha_cmd = MHA_MAPSIZE_STACK;
+ mha.mha_flags = 0;
+ mha.mha_pagesize = 64 * 1024;
+ (void)memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mha, 0, 0);
+#endif
+ return(sh_main(argc, argv, (Shinit_f)0));
+}
diff --git a/src/cmd/ksh93/sh/shcomp.c b/src/cmd/ksh93/sh/shcomp.c
new file mode 100644
index 0000000..184637b
--- /dev/null
+++ b/src/cmd/ksh93/sh/shcomp.c
@@ -0,0 +1,177 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * shell script to shell binary converter
+ *
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: shcomp (AT&T Research) 2003-03-02 $\n]"
+USAGE_LICENSE
+"[+NAME?shcomp - compile a shell script]"
+"[+DESCRIPTION?Unless \b-D\b is specified, \bshcomp\b takes a shell script, "
+ "\ainfile\a, and creates a binary format file, \aoutfile\a, that "
+ "\bksh\b can read and execute with the same effect as the original "
+ "script.]"
+"[+?Since aliases are processed as the script is read, alias definitions "
+ "whose value requires variable expansion will not work correctly.]"
+"[+?If \b-D\b is specified, all double quoted strings that are preceded by "
+ "\b$\b are output. These are the messages that need to be "
+ "translated to locale specific versions for internationalization.]"
+"[+?If \aoutfile\a is omitted, then the results will be written to "
+ "standard output. If \ainfile\a is also omitted, the shell script "
+ "will be read from standard input.]"
+"[D:dictionary?Generate a list of strings that need to be placed in a message "
+ "catalog for internationalization.]"
+"[n:noexec?Displays warning messages for obsolete or non-conforming "
+ "constructs.] "
+"[v:verbose?Displays input from \ainfile\a onto standard error as it "
+ "reads it.]"
+"\n"
+"\n[infile [outfile]]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bksh\b(1)]"
+;
+
+#include <shell.h>
+#include "defs.h"
+#include "shnodes.h"
+#include "sys/stat.h"
+
+#define CNTL(x) ((x)&037)
+#define VERSION 3
+static const char header[6] = { CNTL('k'),CNTL('s'),CNTL('h'),0,VERSION,0 };
+
+int main(int argc, char *argv[])
+{
+ Sfio_t *in, *out;
+ Shell_t *shp;
+ Namval_t *np;
+ Shnode_t *t;
+ char *cp;
+ int n, nflag=0, vflag=0, dflag=0;
+ error_info.id = argv[0];
+ while(n = optget(argv, usage )) switch(n)
+ {
+ case 'D':
+ dflag=1;
+ break;
+ case 'v':
+ vflag=1;
+ break;
+ case 'n':
+ nflag=1;
+ break;
+ case ':':
+ errormsg(SH_DICT,2,"%s",opt_info.arg);
+ break;
+ case '?':
+ errormsg(SH_DICT,ERROR_usage(2),"%s",opt_info.arg);
+ break;
+ }
+ shp = sh_init(argc,argv,(Shinit_f)0);
+ shp->shcomp = 1;
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if(error_info.errors || argc>2)
+ errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
+ if(cp= *argv)
+ {
+ argv++;
+ in = sh_pathopen(cp);
+ }
+ else
+ in = sfstdin;
+ if(cp= *argv)
+ {
+ struct stat statb;
+ if(!(out = sfopen((Sfio_t*)0,cp,"w")))
+ errormsg(SH_DICT,ERROR_system(1),"%s: cannot create",cp);
+ if(fstat(sffileno(out),&statb) >=0)
+ chmod(cp,(statb.st_mode&~S_IFMT)|S_IXUSR|S_IXGRP|S_IXOTH);
+ }
+ else
+ out = sfstdout;
+ if(dflag)
+ {
+ sh_onoption(SH_DICTIONARY);
+ sh_onoption(SH_NOEXEC);
+ }
+ if(nflag)
+ sh_onoption(SH_NOEXEC);
+ if(vflag)
+ sh_onoption(SH_VERBOSE);
+ if(!dflag)
+ sfwrite(out,header,sizeof(header));
+ shp->inlineno = 1;
+#if SHOPT_BRACEPAT
+ sh_onoption(SH_BRACEEXPAND);
+#endif
+ while(1)
+ {
+ stakset((char*)0,0);
+ if(t = (Shnode_t*)sh_parse(shp,in,0))
+ {
+ if((t->tre.tretyp&(COMMSK|COMSCAN))==0 && t->com.comnamp && strcmp(nv_name((Namval_t*)t->com.comnamp),"alias")==0)
+ sh_exec(t,0);
+ if(!dflag && sh_tdump(out,t) < 0)
+ errormsg(SH_DICT,ERROR_exit(1),"dump failed");
+ }
+ else if(sfeof(in))
+ break;
+ if(sferror(in))
+ errormsg(SH_DICT,ERROR_system(1),"I/O error");
+ if(t && ((t->tre.tretyp&COMMSK)==TCOM) && (np=t->com.comnamp) && (cp=nv_name(np)))
+ {
+ if(strcmp(cp,"exit")==0)
+ break;
+ /* check for exec of a command */
+ if(strcmp(cp,"exec")==0)
+ {
+ if(t->com.comtyp&COMSCAN)
+ {
+ if(t->com.comarg->argnxt.ap)
+ break;
+ }
+ else
+ {
+ struct dolnod *ap = (struct dolnod*)t->com.comarg;
+ if(ap->dolnum>1)
+ break;
+ }
+ }
+ }
+ }
+ /* copy any remaining input */
+ sfmove(in,out,SF_UNBOUND,-1);
+ if(in!=sfstdin)
+ sfclose(in);
+ if(out!=sfstdout)
+ sfclose(out);
+ return(0);
+}
diff --git a/src/cmd/ksh93/sh/streval.c b/src/cmd/ksh93/sh/streval.c
new file mode 100644
index 0000000..d13e0f8
--- /dev/null
+++ b/src/cmd/ksh93/sh/streval.c
@@ -0,0 +1,1023 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * D. G. Korn
+ * AT&T Labs
+ *
+ * arithmetic expression evaluator
+ *
+ * this version compiles the expression onto a stack
+ * and has a separate executor
+ */
+
+#include "streval.h"
+#include <ctype.h>
+#include <error.h>
+#include <stak.h>
+#include "FEATURE/externs"
+#include "defs.h" /* for sh.decomma */
+
+#ifndef ERROR_dictionary
+# define ERROR_dictionary(s) (s)
+#endif
+#ifndef SH_DICT
+# define SH_DICT "libshell"
+#endif
+
+#define MAXLEVEL 9
+#define SMALL_STACK 12
+
+/*
+ * The following are used with tokenbits() macro
+ */
+#define T_OP 0x3f /* mask for operator number */
+#define T_BINARY 0x40 /* binary operators */
+#define T_NOFLOAT 0x80 /* non floating point operator */
+#define A_LVALUE (2*MAXPREC+2)
+
+#define pow2size(x) ((x)<=2?2:(x)<=4?4:(x)<=8?8:(x)<=16?16:(x)<=32?32:64)
+#define round(x,size) (((x)+(size)-1)&~((size)-1))
+#define stakpush(v,val,type) ((((v)->offset=round(staktell(),pow2size(sizeof(type)))),\
+ stakseek((v)->offset+sizeof(type)), \
+ *((type*)stakptr((v)->offset)) = (val)),(v)->offset)
+#define roundptr(ep,cp,type) (((unsigned char*)(ep))+round(cp-((unsigned char*)(ep)),pow2size(sizeof(type))))
+
+static int level;
+
+struct vars /* vars stacked per invocation */
+{
+ Shell_t *shp;
+ const char *expr; /* current expression */
+ const char *nextchr; /* next char in current expression */
+ const char *errchr; /* next char after error */
+ const char *errstr; /* error string */
+ struct lval errmsg; /* error message text */
+ int offset; /* offset for pushchr macro */
+ int staksize; /* current stack size needed */
+ int stakmaxsize; /* maximum stack size needed */
+ unsigned char paren; /* parenthesis level */
+ char infun; /* incremented by comma inside function */
+ int emode;
+ Sfdouble_t (*convert)(const char**,struct lval*,int,Sfdouble_t);
+};
+
+typedef Sfdouble_t (*Math_f)(Sfdouble_t,...);
+typedef Sfdouble_t (*Math_1f_f)(Sfdouble_t);
+typedef int (*Math_1i_f)(Sfdouble_t);
+typedef Sfdouble_t (*Math_2f_f)(Sfdouble_t,Sfdouble_t);
+typedef Sfdouble_t (*Math_2f_i)(Sfdouble_t,int);
+typedef int (*Math_2i_f)(Sfdouble_t,Sfdouble_t);
+typedef Sfdouble_t (*Math_3f_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t);
+typedef int (*Math_3i_f)(Sfdouble_t,Sfdouble_t,Sfdouble_t);
+
+#define getchr(vp) (*(vp)->nextchr++)
+#define peekchr(vp) (*(vp)->nextchr)
+#define ungetchr(vp) ((vp)->nextchr--)
+
+#if ('a'==97) /* ASCII encodings */
+# define getop(c) (((c) >= sizeof(strval_states))? \
+ ((c)=='|'?A_OR:((c)=='^'?A_XOR:((c)=='~'?A_TILDE:A_REG))):\
+ strval_states[(c)])
+#else
+# define getop(c) (isdigit(c)?A_DIG:((c==' '||c=='\t'||c=='\n'||c=='"')?0: \
+ (c=='<'?A_LT:(c=='>'?A_GT:(c=='='?A_ASSIGN: \
+ (c=='+'?A_PLUS:(c=='-'?A_MINUS:(c=='*'?A_TIMES: \
+ (c=='/'?A_DIV:(c=='%'?A_MOD:(c==','?A_COMMA: \
+ (c=='&'?A_AND:(c=='!'?A_NOT:(c=='('?A_LPAR: \
+ (c==')'?A_RPAR:(c==0?A_EOF:(c==':'?A_COLON: \
+ (c=='?'?A_QUEST:(c=='|'?A_OR:(c=='^'?A_XOR: \
+ (c=='\''?A_LIT: \
+ (c=='.'?A_DOT:(c=='~'?A_TILDE:A_REG)))))))))))))))))))))))
+#endif
+
+#define seterror(v,msg) _seterror(v,ERROR_dictionary(msg))
+#define ERROR(vp,msg) return(seterror((vp),msg))
+
+/*
+ * set error message string and return(0)
+ */
+static int _seterror(struct vars *vp,const char *msg)
+{
+ if(!vp->errmsg.value)
+ vp->errmsg.value = (char*)msg;
+ vp->errchr = vp->nextchr;
+ vp->nextchr = "";
+ level = 0;
+ return(0);
+}
+
+
+static void arith_error(const char *message,const char *expr, int mode)
+{
+ level = 0;
+ mode = (mode&3)!=0;
+ errormsg(SH_DICT,ERROR_exit(mode),message,expr);
+}
+
+#if _ast_no_um2fm
+static Sfdouble_t U2F(Sfulong_t u)
+{
+ Sflong_t s = u;
+ Sfdouble_t f;
+
+ if (s >= 0)
+ return s;
+ s = u / 2;
+ f = s;
+ f *= 2;
+ if (u & 1)
+ f++;
+ return f;
+}
+#else
+#define U2F(x) x
+#endif
+
+Sfdouble_t arith_exec(Arith_t *ep)
+{
+ register Sfdouble_t num=0,*dp,*sp;
+ register unsigned char *cp = ep->code;
+ register int c,type=0;
+ register char *tp;
+ Sfdouble_t small_stack[SMALL_STACK+1],arg[9];
+ const char *ptr = "";
+ char *lastval=0;
+ int lastsub;
+ Math_f fun;
+ struct lval node;
+ Shell_t *shp = ep->shp;
+ node.shp = shp;
+ node.emode = ep->emode;
+ node.expr = ep->expr;
+ node.elen = ep->elen;
+ node.value = 0;
+ node.nosub = 0;
+ node.ptr = 0;
+ node.eflag = 0;
+ if(level++ >=MAXLEVEL)
+ {
+ arith_error(e_recursive,ep->expr,ep->emode);
+ return(0);
+ }
+ if(ep->staksize < SMALL_STACK)
+ sp = small_stack;
+ else
+ sp = (Sfdouble_t*)stakalloc(ep->staksize*(sizeof(Sfdouble_t)+1));
+ tp = (char*)(sp+ep->staksize);
+ tp--,sp--;
+ while(c = *cp++)
+ {
+ if(c&T_NOFLOAT)
+ {
+ if(type==1 || ((c&T_BINARY) && (c&T_OP)!=A_MOD && tp[-1]==1))
+ arith_error(e_incompatible,ep->expr,ep->emode);
+ }
+ switch(c&T_OP)
+ {
+ case A_JMP: case A_JMPZ: case A_JMPNZ:
+ c &= T_OP;
+ cp = roundptr(ep,cp,short);
+ if((c==A_JMPZ && num) || (c==A_JMPNZ &&!num))
+ cp += sizeof(short);
+ else
+ cp = (unsigned char*)ep + *((short*)cp);
+ continue;
+ case A_NOTNOT:
+ num = (num!=0);
+ type=0;
+ break;
+ case A_PLUSPLUS:
+ node.nosub = -1;
+ (*ep->fun)(&ptr,&node,ASSIGN,num+1);
+ break;
+ case A_MINUSMINUS:
+ node.nosub = -1;
+ (*ep->fun)(&ptr,&node,ASSIGN,num-1);
+ break;
+ case A_INCR:
+ num = num+1;
+ node.nosub = -1;
+ num = (*ep->fun)(&ptr,&node,ASSIGN,num);
+ break;
+ case A_DECR:
+ num = num-1;
+ node.nosub = -1;
+ num = (*ep->fun)(&ptr,&node,ASSIGN,num);
+ break;
+ case A_SWAP:
+ num = sp[-1];
+ sp[-1] = *sp;
+ type = tp[-1];
+ tp[-1] = *tp;
+ break;
+ case A_POP:
+ sp--;
+ continue;
+ case A_ASSIGNOP1:
+ node.emode |= ARITH_ASSIGNOP;
+ case A_PUSHV:
+ cp = roundptr(ep,cp,Sfdouble_t*);
+ dp = *((Sfdouble_t**)cp);
+ cp += sizeof(Sfdouble_t*);
+ c = *(short*)cp;
+ cp += sizeof(short);
+ lastval = node.value = (char*)dp;
+ if(node.flag = c)
+ lastval = 0;
+ node.isfloat=0;
+ node.level = level;
+ node.nosub = 0;
+ num = (*ep->fun)(&ptr,&node,VALUE,num);
+ if(node.emode&ARITH_ASSIGNOP)
+ {
+ lastsub = node.nosub;
+ node.nosub = 0;
+ node.emode &= ~ARITH_ASSIGNOP;
+ }
+ if(node.value != (char*)dp)
+ arith_error(node.value,ptr,ep->emode);
+ *++sp = num;
+ type = node.isfloat;
+ if(num > LDBL_ULLONG_MAX || num < LDBL_LLONG_MIN)
+ type = 1;
+ else
+ {
+ Sfdouble_t d=num;
+ if(num > LDBL_LLONG_MAX && num <= LDBL_ULLONG_MAX)
+ {
+ type = 2;
+ d -= LDBL_LLONG_MAX;
+ }
+ if((Sflong_t)d!=d)
+ type = 1;
+ }
+ *++tp = type;
+ c = 0;
+ break;
+ case A_ENUM:
+ node.eflag = 1;
+ continue;
+ case A_ASSIGNOP:
+ node.nosub = lastsub;
+ case A_STORE:
+ cp = roundptr(ep,cp,Sfdouble_t*);
+ dp = *((Sfdouble_t**)cp);
+ cp += sizeof(Sfdouble_t*);
+ c = *(short*)cp;
+ if(c<0)
+ c = 0;
+ cp += sizeof(short);
+ node.value = (char*)dp;
+ node.flag = c;
+ if(lastval)
+ node.eflag = 1;
+ node.ptr = 0;
+ num = (*ep->fun)(&ptr,&node,ASSIGN,num);
+ if(lastval && node.ptr)
+ {
+ Sfdouble_t r;
+ node.flag = 0;
+ node.value = lastval;
+ r = (*ep->fun)(&ptr,&node,VALUE,num);
+ if(r!=num)
+ {
+ node.flag=c;
+ node.value = (char*)dp;
+ num = (*ep->fun)(&ptr,&node,ASSIGN,r);
+ }
+
+ }
+ lastval = 0;
+ c=0;
+ break;
+ case A_PUSHF:
+ cp = roundptr(ep,cp,Math_f);
+ *++sp = (Sfdouble_t)(cp-ep->code);
+ cp += sizeof(Math_f);
+ *++tp = *cp++;
+ continue;
+ case A_PUSHN:
+ cp = roundptr(ep,cp,Sfdouble_t);
+ num = *((Sfdouble_t*)cp);
+ cp += sizeof(Sfdouble_t);
+ *++sp = num;
+ *++tp = type = *cp++;
+ break;
+ case A_NOT:
+ type=0;
+ num = !num;
+ break;
+ case A_UMINUS:
+ num = -num;
+ break;
+ case A_TILDE:
+ num = ~((Sflong_t)(num));
+ break;
+ case A_PLUS:
+ num += sp[-1];
+ break;
+ case A_MINUS:
+ num = sp[-1] - num;
+ break;
+ case A_TIMES:
+ num *= sp[-1];
+ break;
+ case A_POW:
+ num = pow(sp[-1],num);
+ break;
+ case A_MOD:
+ if(!(Sflong_t)num)
+ arith_error(e_divzero,ep->expr,ep->emode);
+ if(type==2 || tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) % (Sfulong_t)(num));
+ else
+ num = (Sflong_t)(sp[-1]) % (Sflong_t)(num);
+ break;
+ case A_DIV:
+ if(type==1 || tp[-1]==1)
+ {
+ num = sp[-1]/num;
+ type = 1;
+ }
+ else if((Sfulong_t)(num)==0)
+ arith_error(e_divzero,ep->expr,ep->emode);
+ else if(type==2 || tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) / (Sfulong_t)(num));
+ else
+ num = (Sflong_t)(sp[-1]) / (Sflong_t)(num);
+ break;
+ case A_LSHIFT:
+ if(tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) << (long)(num));
+ else
+ num = (Sflong_t)(sp[-1]) << (long)(num);
+ break;
+ case A_RSHIFT:
+ if(tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) >> (long)(num));
+ else
+ num = (Sflong_t)(sp[-1]) >> (long)(num);
+ break;
+ case A_XOR:
+ if(type==2 || tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) ^ (Sfulong_t)(num));
+ else
+ num = (Sflong_t)(sp[-1]) ^ (Sflong_t)(num);
+ break;
+ case A_OR:
+ if(type==2 || tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) | (Sfulong_t)(num));
+ else
+ num = (Sflong_t)(sp[-1]) | (Sflong_t)(num);
+ break;
+ case A_AND:
+ if(type==2 || tp[-1]==2)
+ num = U2F((Sfulong_t)(sp[-1]) & (Sfulong_t)(num));
+ else
+ num = (Sflong_t)(sp[-1]) & (Sflong_t)(num);
+ break;
+ case A_EQ:
+ num = (sp[-1]==num);
+ type=0;
+ break;
+ case A_NEQ:
+ num = (sp[-1]!=num);
+ type=0;
+ break;
+ case A_LE:
+ num = (sp[-1]<=num);
+ type=0;
+ break;
+ case A_GE:
+ num = (sp[-1]>=num);
+ type=0;
+ break;
+ case A_GT:
+ num = (sp[-1]>num);
+ type=0;
+ break;
+ case A_LT:
+ num = (sp[-1]<num);
+ type=0;
+ break;
+ case A_CALL1F:
+ sp--,tp--;
+ fun = *((Math_f*)(ep->code+(int)(*sp)));
+ type = *tp;
+ if(c&T_BINARY)
+ {
+ c &= ~T_BINARY;
+ arg[0] = num;
+ arg[1] = 0;
+ num = sh_mathfun(shp,(void*)fun,1,arg);
+ break;
+ }
+ num = (*((Math_1f_f)fun))(num);
+ break;
+ case A_CALL1I:
+ sp--,tp--;
+ fun = *((Math_f*)(ep->code+(int)(*sp)));
+ type = *tp;
+ num = (*((Math_1i_f)fun))(num);
+ break;
+ case A_CALL2F:
+ sp-=2,tp-=2;
+ fun = *((Math_f*)(ep->code+(int)(*sp)));
+ type = *tp;
+ if(c&T_BINARY)
+ {
+ c &= ~T_BINARY;
+ arg[0] = sp[1];
+ arg[1] = num;
+ arg[2] = 0;
+ num = sh_mathfun(shp,(void*)fun,2,arg);
+ break;
+ }
+ if(c&T_NOFLOAT)
+ num = (*((Math_2f_i)fun))(sp[1],(int)num);
+ else
+ num = (*((Math_2f_f)fun))(sp[1],num);
+ break;
+ case A_CALL2I:
+ sp-=2,tp-=2;
+ fun = *((Math_f*)(ep->code+(int)(*sp)));
+ type = *tp;
+ num = (*((Math_2i_f)fun))(sp[1],num);
+ break;
+ case A_CALL3F:
+ sp-=3,tp-=3;
+ fun = *((Math_f*)(ep->code+(int)(*sp)));
+ type = *tp;
+ if(c&T_BINARY)
+ {
+ c &= ~T_BINARY;
+ arg[0] = sp[1];
+ arg[1] = sp[2];
+ arg[2] = num;
+ arg[3] = 0;
+ num = sh_mathfun(shp,(void*)fun,3,arg);
+ break;
+ }
+ num = (*((Math_3f_f)fun))(sp[1],sp[2],num);
+ break;
+ }
+ if(c)
+ lastval = 0;
+ if(c&T_BINARY)
+ {
+ node.ptr = 0;
+ sp--,tp--;
+ type |= (*tp!=0);
+ }
+ *sp = num;
+ *tp = type;
+ }
+ if(level>0)
+ level--;
+ return(num);
+}
+
+/*
+ * This returns operator tokens or A_REG or A_NUM
+ */
+static int gettok(register struct vars *vp)
+{
+ register int c,op;
+ vp->errchr = vp->nextchr;
+ while(1)
+ {
+ c = getchr(vp);
+ switch(op=getop(c))
+ {
+ case 0:
+ vp->errchr = vp->nextchr;
+ continue;
+ case A_EOF:
+ vp->nextchr--;
+ break;
+ case A_COMMA:
+ if(vp->shp->decomma && (c=peekchr(vp))>='0' && c<='9')
+ {
+ op = A_DIG;
+ goto keep;
+ }
+ break;
+ case A_DOT:
+ if((c=peekchr(vp))>='0' && c<='9')
+ op = A_DIG;
+ else
+ op = A_REG;
+ /*FALL THRU*/
+ case A_DIG: case A_REG: case A_LIT:
+ keep:
+ ungetchr(vp);
+ break;
+ case A_QUEST:
+ if(peekchr(vp)==':')
+ {
+ getchr(vp);
+ op = A_QCOLON;
+ }
+ break;
+ case A_LT: case A_GT:
+ if(peekchr(vp)==c)
+ {
+ getchr(vp);
+ op -= 2;
+ break;
+ }
+ /* FALL THRU */
+ case A_NOT: case A_COLON:
+ c = '=';
+ /* FALL THRU */
+ case A_ASSIGN:
+ case A_TIMES:
+ case A_PLUS: case A_MINUS:
+ case A_OR: case A_AND:
+ if(peekchr(vp)==c)
+ {
+ getchr(vp);
+ op--;
+ }
+ }
+ return(op);
+ }
+}
+
+/*
+ * evaluate a subexpression with precedence
+ */
+
+static int expr(register struct vars *vp,register int precedence)
+{
+ register int c, op;
+ int invalid,wasop=0;
+ struct lval lvalue,assignop;
+ const char *pos;
+ Sfdouble_t d;
+
+ lvalue.value = 0;
+ lvalue.nargs = 0;
+ lvalue.fun = 0;
+ lvalue.shp = vp->shp;
+again:
+ op = gettok(vp);
+ c = 2*MAXPREC+1;
+ switch(op)
+ {
+ case A_PLUS:
+ goto again;
+ case A_EOF:
+ if(precedence>2)
+ ERROR(vp,e_moretokens);
+ return(1);
+ case A_MINUS:
+ op = A_UMINUS;
+ goto common;
+ case A_NOT:
+ goto common;
+ case A_MINUSMINUS:
+ c = A_LVALUE;
+ op = A_DECR|T_NOFLOAT;
+ goto common;
+ case A_PLUSPLUS:
+ c = A_LVALUE;
+ op = A_INCR|T_NOFLOAT;
+ /* FALL THRU */
+ case A_TILDE:
+ op |= T_NOFLOAT;
+ common:
+ if(!expr(vp,c))
+ return(0);
+ stakputc(op);
+ break;
+ default:
+ vp->nextchr = vp->errchr;
+ wasop = 1;
+ }
+ invalid = wasop;
+ while(1)
+ {
+ assignop.value = 0;
+ op = gettok(vp);
+ if(op==A_DIG || op==A_REG || op==A_LIT)
+ {
+ if(!wasop)
+ ERROR(vp,e_synbad);
+ goto number;
+ }
+ if(wasop++ && op!=A_LPAR)
+ ERROR(vp,e_synbad);
+ /* check for assignment operation */
+ if(peekchr(vp)== '=' && !(strval_precedence[op]&NOASSIGN))
+ {
+ if((!lvalue.value || precedence > 3))
+ ERROR(vp,e_notlvalue);
+ if(precedence==3)
+ precedence = 2;
+ assignop = lvalue;
+ getchr(vp);
+ c = 3;
+ }
+ else
+ {
+ c = (strval_precedence[op]&PRECMASK);
+ if(c==MAXPREC || op==A_POW)
+ c++;
+ c *= 2;
+ }
+ /* from here on c is the new precedence level */
+ if(lvalue.value && (op!=A_ASSIGN))
+ {
+ if(vp->staksize++>=vp->stakmaxsize)
+ vp->stakmaxsize = vp->staksize;
+ if(op==A_EQ || op==A_NEQ)
+ stakputc(A_ENUM);
+ stakputc(assignop.value?A_ASSIGNOP1:A_PUSHV);
+ stakpush(vp,lvalue.value,char*);
+ if(lvalue.flag<0)
+ lvalue.flag = 0;
+ stakpush(vp,lvalue.flag,short);
+ if(vp->nextchr==0)
+ ERROR(vp,e_badnum);
+ if(!(strval_precedence[op]&SEQPOINT))
+ lvalue.value = 0;
+ invalid = 0;
+ }
+ else if(precedence==A_LVALUE)
+ ERROR(vp,e_notlvalue);
+ if(invalid && op>A_ASSIGN)
+ ERROR(vp,e_synbad);
+ if(precedence >= c)
+ goto done;
+ if(strval_precedence[op]&RASSOC)
+ c--;
+ if((c < (2*MAXPREC+1)) && !(strval_precedence[op]&SEQPOINT))
+ {
+ wasop = 0;
+ if(!expr(vp,c))
+ return(0);
+ }
+ switch(op)
+ {
+ case A_RPAR:
+ if(!vp->paren)
+ ERROR(vp,e_paren);
+ if(invalid)
+ ERROR(vp,e_synbad);
+ goto done;
+
+ case A_COMMA:
+ wasop = 0;
+ if(vp->infun)
+ vp->infun++;
+ else
+ {
+ stakputc(A_POP);
+ vp->staksize--;
+ }
+ if(!expr(vp,c))
+ {
+ stakseek(staktell()-1);
+ return(0);
+ }
+ lvalue.value = 0;
+ break;
+
+ case A_LPAR:
+ {
+ int infun = vp->infun;
+ int userfun=0;
+ Sfdouble_t (*fun)(Sfdouble_t,...);
+ int nargs = lvalue.nargs;
+ if(nargs<0)
+ nargs = -nargs;
+ fun = lvalue.fun;
+ lvalue.fun = 0;
+ if(fun)
+ {
+ if(vp->staksize++>=vp->stakmaxsize)
+ vp->stakmaxsize = vp->staksize;
+ vp->infun=1;
+ if((int)lvalue.nargs<0)
+ userfun = T_BINARY;
+ else if((int)lvalue.nargs&040)
+ userfun = T_NOFLOAT;
+ stakputc(A_PUSHF);
+ stakpush(vp,fun,Math_f);
+ stakputc(1);
+ }
+ else
+ vp->infun = 0;
+ if(!invalid)
+ ERROR(vp,e_synbad);
+ vp->paren++;
+ if(!expr(vp,1))
+ return(0);
+ vp->paren--;
+ if(fun)
+ {
+ int x= (nargs&010)?2:-1;
+ nargs &= 7;
+ if(vp->infun != nargs)
+ ERROR(vp,e_argcount);
+ if((vp->staksize+=nargs)>=vp->stakmaxsize)
+ vp->stakmaxsize = vp->staksize+nargs;
+ stakputc(A_CALL1F+userfun+nargs+x);
+ vp->staksize -= nargs;
+ }
+ vp->infun = infun;
+ if (gettok(vp) != A_RPAR)
+ ERROR(vp,e_paren);
+ wasop = 0;
+ break;
+ }
+
+ case A_PLUSPLUS:
+ case A_MINUSMINUS:
+ wasop=0;
+ op |= T_NOFLOAT;
+ case A_ASSIGN:
+ if(!lvalue.value)
+ ERROR(vp,e_notlvalue);
+ if(op==A_ASSIGN)
+ {
+ stakputc(A_STORE);
+ stakpush(vp,lvalue.value,char*);
+ stakpush(vp,lvalue.flag,short);
+ vp->staksize--;
+ }
+ else
+ stakputc(op);
+ lvalue.value = 0;
+ break;
+
+ case A_QUEST:
+ {
+ int offset1,offset2;
+ stakputc(A_JMPZ);
+ offset1 = stakpush(vp,0,short);
+ stakputc(A_POP);
+ if(!expr(vp,1))
+ return(0);
+ if(gettok(vp)!=A_COLON)
+ ERROR(vp,e_questcolon);
+ stakputc(A_JMP);
+ offset2 = stakpush(vp,0,short);
+ *((short*)stakptr(offset1)) = staktell();
+ stakputc(A_POP);
+ if(!expr(vp,3))
+ return(0);
+ *((short*)stakptr(offset2)) = staktell();
+ lvalue.value = 0;
+ wasop = 0;
+ break;
+ }
+
+ case A_COLON:
+ ERROR(vp,e_badcolon);
+ break;
+
+ case A_QCOLON:
+ case A_ANDAND:
+ case A_OROR:
+ {
+ int offset;
+ if(op==A_ANDAND)
+ op = A_JMPZ;
+ else
+ op = A_JMPNZ;
+ stakputc(op);
+ offset = stakpush(vp,0,short);
+ stakputc(A_POP);
+ if(!expr(vp,c))
+ return(0);
+ *((short*)stakptr(offset)) = staktell();
+ if(op!=A_QCOLON)
+ stakputc(A_NOTNOT);
+ lvalue.value = 0;
+ wasop=0;
+ break;
+ }
+ case A_AND: case A_OR: case A_XOR: case A_LSHIFT:
+ case A_RSHIFT: case A_MOD:
+ op |= T_NOFLOAT;
+ /* FALL THRU */
+ case A_PLUS: case A_MINUS: case A_TIMES: case A_DIV:
+ case A_EQ: case A_NEQ: case A_LT: case A_LE:
+ case A_GT: case A_GE: case A_POW:
+ stakputc(op|T_BINARY);
+ vp->staksize--;
+ break;
+ case A_NOT: case A_TILDE:
+ default:
+ ERROR(vp,e_synbad);
+ number:
+ wasop = 0;
+ if(*vp->nextchr=='L' && vp->nextchr[1]=='\'')
+ {
+ vp->nextchr++;
+ op = A_LIT;
+ }
+ pos = vp->nextchr;
+ lvalue.isfloat = 0;
+ lvalue.expr = vp->expr;
+ lvalue.emode = vp->emode;
+ if(op==A_LIT)
+ {
+ /* character constants */
+ if(pos[1]=='\\' && pos[2]=='\'' && pos[3]!='\'')
+ {
+ d = '\\';
+ vp->nextchr +=2;
+ }
+ else
+ d = chresc(pos+1,(char**)&vp->nextchr);
+ /* posix allows the trailing ' to be optional */
+ if(*vp->nextchr=='\'')
+ vp->nextchr++;
+ }
+ else
+ d = (*vp->convert)(&vp->nextchr, &lvalue, LOOKUP, 0);
+ if (vp->nextchr == pos)
+ {
+ if(vp->errmsg.value = lvalue.value)
+ vp->errstr = pos;
+ ERROR(vp,op==A_LIT?e_charconst:e_synbad);
+ }
+ if(op==A_DIG || op==A_LIT)
+ {
+ stakputc(A_PUSHN);
+ if(vp->staksize++>=vp->stakmaxsize)
+ vp->stakmaxsize = vp->staksize;
+ stakpush(vp,d,Sfdouble_t);
+ stakputc(lvalue.isfloat);
+ }
+
+ /* check for function call */
+ if(lvalue.fun)
+ continue;
+ break;
+ }
+ invalid = 0;
+ if(assignop.value)
+ {
+ if(vp->staksize++>=vp->stakmaxsize)
+ vp->stakmaxsize = vp->staksize;
+ if(assignop.flag<0)
+ assignop.flag = 0;
+ stakputc(c&1?A_ASSIGNOP:A_STORE);
+ stakpush(vp,assignop.value,char*);
+ stakpush(vp,assignop.flag,short);
+ }
+ }
+ done:
+ vp->nextchr = vp->errchr;
+ return(1);
+}
+
+Arith_t *arith_compile(Shell_t *shp,const char *string,char **last,Sfdouble_t(*fun)(const char**,struct lval*,int,Sfdouble_t),int emode)
+{
+ struct vars cur;
+ register Arith_t *ep;
+ int offset;
+ memset((void*)&cur,0,sizeof(cur));
+ cur.shp = shp;
+ cur.expr = cur.nextchr = string;
+ cur.convert = fun;
+ cur.emode = emode;
+ cur.errmsg.value = 0;
+ cur.errmsg.emode = emode;
+ stakseek(sizeof(Arith_t));
+ if(!expr(&cur,0) && cur.errmsg.value)
+ {
+ if(cur.errstr)
+ string = cur.errstr;
+ if((*fun)( &string , &cur.errmsg, MESSAGE, 0) < 0)
+ {
+ stakseek(0);
+ *last = (char*)Empty;
+ return(0);
+ }
+ cur.nextchr = cur.errchr;
+ }
+ stakputc(0);
+ offset = staktell();
+ ep = (Arith_t*)stakfreeze(0);
+ ep->shp = shp;
+ ep->expr = string;
+ ep->elen = strlen(string);
+ ep->code = (unsigned char*)(ep+1);
+ ep->fun = fun;
+ ep->emode = emode;
+ ep->size = offset - sizeof(Arith_t);
+ ep->staksize = cur.stakmaxsize+1;
+ if(last)
+ *last = (char*)(cur.nextchr);
+ return(ep);
+}
+
+/*
+ * evaluate an integer arithmetic expression in s
+ *
+ * (Sfdouble_t)(*convert)(char** end, struct lval* string, int type, Sfdouble_t value)
+ * is a user supplied conversion routine that is called when unknown
+ * chars are encountered.
+ * *end points to the part to be converted and must be adjusted by convert to
+ * point to the next non-converted character; if typ is MESSAGE then string
+ * points to an error message string
+ *
+ * NOTE: (*convert)() may call strval()
+ */
+
+Sfdouble_t strval(Shell_t *shp,const char *s,char **end,Sfdouble_t(*conv)(const char**,struct lval*,int,Sfdouble_t),int emode)
+{
+ Arith_t *ep;
+ Sfdouble_t d;
+ char *sp=0;
+ int offset;
+ if(offset=staktell())
+ sp = stakfreeze(1);
+ ep = arith_compile(shp,s,end,conv,emode);
+ ep->emode = emode;
+ d = arith_exec(ep);
+ stakset(sp?sp:(char*)ep,offset);
+ return(d);
+}
+
+#if _mem_name__exception
+#undef _mem_name_exception
+#define _mem_name_exception 1
+#undef exception
+#define exception _exception
+#undef matherr
+#endif
+
+#if _mem_name_exception
+
+#undef error
+
+#if _BLD_shell && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#ifndef DOMAIN
+#define DOMAIN _DOMAIN
+#endif
+#ifndef OVERFLOW
+#define OVERFLOW _OVERFLOW
+#endif
+#ifndef SING
+#define SING _SING
+#endif
+
+ extern int matherr(struct exception *ep)
+ {
+ const char *message;
+ switch(ep->type)
+ {
+#ifdef DOMAIN
+ case DOMAIN:
+ message = ERROR_dictionary(e_domain);
+ break;
+#endif
+#ifdef OVERFLOW
+ case OVERFLOW:
+ message = ERROR_dictionary(e_overflow);
+ break;
+#endif
+#ifdef SING
+ case SING:
+ message = ERROR_dictionary(e_singularity);
+ break;
+#endif
+ default:
+ return(1);
+ }
+ level=0;
+ errormsg(SH_DICT,ERROR_exit(1),message,ep->name);
+ return(0);
+ }
+
+#undef extern
+
+#endif /* _mem_name_exception */
diff --git a/src/cmd/ksh93/sh/string.c b/src/cmd/ksh93/sh/string.c
new file mode 100644
index 0000000..2765e8d
--- /dev/null
+++ b/src/cmd/ksh93/sh/string.c
@@ -0,0 +1,730 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * string processing routines for Korn shell
+ *
+ */
+
+#include <ast.h>
+#include <ast_wchar.h>
+#include "defs.h"
+#include <stak.h>
+#include <ccode.h>
+#include "shtable.h"
+#include "lexstates.h"
+#include "national.h"
+
+#if _hdr_wctype
+# include <wctype.h>
+#endif
+
+#if !_lib_iswprint && !defined(iswprint)
+# define iswprint(c) (((c)&~0377) || isprint(c))
+#endif
+
+
+/*
+ * Table lookup routine
+ * <table> is searched for string <sp> and corresponding value is returned
+ * This is only used for small tables and is used to save non-sharable memory
+ */
+
+const Shtable_t *sh_locate(register const char *sp,const Shtable_t *table,int size)
+{
+ register int first;
+ register const Shtable_t *tp;
+ register int c;
+ static const Shtable_t empty = {0,0};
+ if(sp==0 || (first= *sp)==0)
+ return(&empty);
+ tp=table;
+ while((c= *tp->sh_name) && (CC_NATIVE!=CC_ASCII || c <= first))
+ {
+ if(first == c && strcmp(sp,tp->sh_name)==0)
+ return(tp);
+ tp = (Shtable_t*)((char*)tp+size);
+ }
+ return(&empty);
+}
+
+/*
+ * shtab_options lookup routine
+ */
+
+#define sep(c) ((c)=='-'||(c)=='_')
+
+int sh_lookopt(register const char *sp, int *invert)
+{
+ register int first;
+ register const Shtable_t *tp;
+ register int c;
+ register const char *s, *t, *sw, *tw;
+ int amb;
+ int hit;
+ int inv;
+ int no;
+ if(sp==0)
+ return(0);
+ if(*sp=='n' && *(sp+1)=='o' && (*(sp+2)!='t' || *(sp+3)!='i'))
+ {
+ sp+=2;
+ if(sep(*sp))
+ sp++;
+ *invert = !*invert;
+ }
+ if((first= *sp)==0)
+ return(0);
+ tp=shtab_options;
+ amb=hit=0;
+ for(;;)
+ {
+ t=tp->sh_name;
+ if(no = *t=='n' && *(t+1)=='o' && *(t+2)!='t')
+ t+=2;
+ if(!(c= *t))
+ break;
+ if(first == c)
+ {
+ if(strcmp(sp,t)==0)
+ {
+ *invert ^= no;
+ return(tp->sh_number);
+ }
+ s=sw=sp;
+ tw=t;
+ for(;;)
+ {
+ if(!*s || *s=='=')
+ {
+ if (*s == '=' && !strtol(s+1, NiL, 0))
+ no = !no;
+ if (!*t)
+ {
+ *invert ^= no;
+ return(tp->sh_number);
+ }
+ if (hit || amb)
+ {
+ hit = 0;
+ amb = 1;
+ }
+ else
+ {
+ hit = tp->sh_number;
+ inv = no;
+ }
+ break;
+ }
+ else if(!*t)
+ break;
+ else if(sep(*s))
+ sw = ++s;
+ else if(sep(*t))
+ tw = ++t;
+ else if(*s==*t)
+ {
+ s++;
+ t++;
+ }
+ else if(s==sw && t==tw)
+ break;
+ else
+ {
+ if(t!=tw)
+ {
+ while(*t && !sep(*t))
+ t++;
+ if(!*t)
+ break;
+ tw = ++t;
+ }
+ while (s>sw && *s!=*t)
+ s--;
+ }
+ }
+ }
+ tp = (Shtable_t*)((char*)tp+sizeof(*shtab_options));
+ }
+ if(hit)
+ *invert ^= inv;
+ return(hit);
+}
+
+/*
+ * look for the substring <oldsp> in <string> and replace with <newsp>
+ * The new string is put on top of the stack
+ */
+char *sh_substitute(const char *string,const char *oldsp,char *newsp)
+/*@
+ assume string!=NULL && oldsp!=NULL && newsp!=NULL;
+ return x satisfying x==NULL ||
+ strlen(x)==(strlen(in string)+strlen(in newsp)-strlen(in oldsp));
+@*/
+{
+ register const char *sp = string;
+ register const char *cp;
+ const char *savesp = 0;
+ stakseek(0);
+ if(*sp==0)
+ return((char*)0);
+ if(*(cp=oldsp) == 0)
+ goto found;
+#if SHOPT_MULTIBYTE
+ mbinit();
+#endif /* SHOPT_MULTIBYTE */
+ do
+ {
+ /* skip to first character which matches start of oldsp */
+ while(*sp && (savesp==sp || *sp != *cp))
+ {
+#if SHOPT_MULTIBYTE
+ /* skip a whole character at a time */
+ int c = mbsize(sp);
+ if(c < 0)
+ sp++;
+ while(c-- > 0)
+#endif /* SHOPT_MULTIBYTE */
+ stakputc(*sp++);
+ }
+ if(*sp == 0)
+ return((char*)0);
+ savesp = sp;
+ for(;*cp;cp++)
+ {
+ if(*cp != *sp++)
+ break;
+ }
+ if(*cp==0)
+ /* match found */
+ goto found;
+ sp = savesp;
+ cp = oldsp;
+ }
+ while(*sp);
+ return((char*)0);
+
+found:
+ /* copy new */
+ stakputs(newsp);
+ /* copy rest of string */
+ stakputs(sp);
+ return(stakfreeze(1));
+}
+
+/*
+ * TRIM(sp)
+ * Remove escape characters from characters in <sp> and eliminate quoted nulls.
+ */
+
+void sh_trim(register char *sp)
+/*@
+ assume sp!=NULL;
+ promise strlen(in sp) <= in strlen(sp);
+@*/
+{
+ register char *dp;
+ register int c;
+ if(sp)
+ {
+ dp = sp;
+ while(c= *sp)
+ {
+#if SHOPT_MULTIBYTE
+ int len;
+ if(mbwide() && (len=mbsize(sp))>1)
+ {
+ memmove(dp, sp, len);
+ dp += len;
+ sp += len;
+ continue;
+ }
+#endif /* SHOPT_MULTIBYTE */
+ sp++;
+ if(c == '\\')
+ c = *sp++;
+ if(c)
+ *dp++ = c;
+ }
+ *dp = 0;
+ }
+}
+
+/*
+ * copy <str1> to <str2> changing upper case to lower case
+ * <str2> must be big enough to hold <str1>
+ * <str1> and <str2> may point to the same place.
+ */
+
+void sh_utol(register char const *str1,register char *str2)
+/*@
+ assume str1!=0 && str2!=0
+ return x satisfying strlen(in str1)==strlen(in str2);
+@*/
+{
+ register int c;
+ for(; c= *((unsigned char*)str1); str1++,str2++)
+ {
+ if(isupper(c))
+ *str2 = tolower(c);
+ else
+ *str2 = c;
+ }
+ *str2 = 0;
+}
+
+/*
+ * format string as a csv field
+ */
+static char *sh_fmtcsv(const char *string)
+{
+ register const char *cp = string, *op;
+ register int c;
+ int offset;
+ if(!cp)
+ return((char*)0);
+ offset = staktell();
+ while((c=mbchar(cp)),isaname(c));
+ if(c==0)
+ return((char*)string);
+ stakputc('"');
+ stakwrite(string,cp-string);
+ if(c=='"')
+ stakputc('"');
+ string = cp;
+ while(c=mbchar(cp))
+ {
+ if(c=='"')
+ {
+ stakwrite(string,cp-string);
+ string = cp;
+ stakputc('"');
+ }
+ }
+ if(--cp>string)
+ stakwrite(string,cp-string);
+ stakputc('"');
+ stakputc(0);
+ return(stakptr(offset));
+}
+
+/*
+ * print <str> quoting chars so that it can be read by the shell
+ * puts null terminated result on stack, but doesn't freeze it
+ */
+char *sh_fmtq(const char *string)
+{
+ register const char *cp = string, *op;
+ register int c, state;
+ int offset;
+ if(!cp)
+ return((char*)0);
+ offset = staktell();
+ state = ((c= mbchar(cp))==0);
+ if(isaletter(c))
+ {
+ while((c=mbchar(cp)),isaname(c));
+ if(c==0)
+ return((char*)string);
+ if(c=='=')
+ {
+ if(*cp==0)
+ return((char*)string);
+ if(*cp=='=')
+ cp++;
+ c = cp - string;
+ stakwrite(string,c);
+ string = cp;
+ c = mbchar(cp);
+ }
+ }
+ if(c==0 || c=='#' || c=='~')
+ state = 1;
+ for(;c;c= mbchar(cp))
+ {
+#if SHOPT_MULTIBYTE
+ if(c=='\'' || !iswprint(c))
+#else
+ if(c=='\'' || !isprint(c))
+#endif /* SHOPT_MULTIBYTE */
+ state = 2;
+ else if(c==']' || c=='=' || (c!=':' && c<=0x7f && (c=sh_lexstates[ST_NORM][c]) && c!=S_EPAT))
+ state |=1;
+ }
+ if(state<2)
+ {
+ if(state==1)
+ stakputc('\'');
+ if(c = --cp - string)
+ stakwrite(string,c);
+ if(state==1)
+ stakputc('\'');
+ }
+ else
+ {
+ stakwrite("$'",2);
+ cp = string;
+#if SHOPT_MULTIBYTE
+ while(op = cp, c= mbchar(cp))
+#else
+ while(op = cp, c= *(unsigned char*)cp++)
+#endif
+ {
+ state=1;
+ switch(c)
+ {
+ case ('a'==97?'\033':39):
+ c = 'E';
+ break;
+ case '\n':
+ c = 'n';
+ break;
+ case '\r':
+ c = 'r';
+ break;
+ case '\t':
+ c = 't';
+ break;
+ case '\f':
+ c = 'f';
+ break;
+ case '\b':
+ c = 'b';
+ break;
+ case '\a':
+ c = 'a';
+ break;
+ case '\\': case '\'':
+ break;
+ default:
+#if SHOPT_MULTIBYTE
+ if(!iswprint(c))
+ {
+ while(op<cp)
+ sfprintf(staksp,"\\%.3o",*(unsigned char*)op++);
+ continue;
+ }
+#else
+ if(!isprint(c))
+ {
+ sfprintf(staksp,"\\%.3o",c);
+ continue;
+ }
+#endif
+ state=0;
+ break;
+ }
+ if(state)
+ {
+ stakputc('\\');
+ stakputc(c);
+ }
+ else
+ stakwrite(op, cp-op);
+ }
+ stakputc('\'');
+ }
+ stakputc(0);
+ return(stakptr(offset));
+}
+
+/*
+ * print <str> quoting chars so that it can be read by the shell
+ * puts null terminated result on stack, but doesn't freeze it
+ * single!=0 limits quoting to '...'
+ * fold>0 prints raw newlines and inserts appropriately
+ * escaped newlines every (fold-x) chars
+ */
+char *sh_fmtqf(const char *string, int single, int fold)
+{
+ register const char *cp = string;
+ register const char *bp;
+ register const char *vp;
+ register int c;
+ register int n;
+ register int q;
+ register int a;
+ int offset;
+
+ if (--fold < 8)
+ fold = 0;
+ if(single)
+ return sh_fmtcsv(cp);
+ if (!cp || !*cp || !fold || fold && strlen(string) < fold)
+ return sh_fmtq(cp);
+ offset = staktell();
+ single = single ? 1 : 3;
+ c = mbchar(string);
+ a = isaletter(c) ? '=' : 0;
+ vp = cp + 1;
+ do
+ {
+ q = 0;
+ n = fold;
+ bp = cp;
+ while ((!n || n-- > 0) && (c = mbchar(cp)))
+ {
+ if (a && !isaname(c))
+ a = 0;
+#if SHOPT_MULTIBYTE
+ if (c >= 0x200)
+ continue;
+ if (c == '\'' || !iswprint(c))
+#else
+ if (c == '\'' || !isprint(c))
+#endif /* SHOPT_MULTIBYTE */
+ {
+ q = single;
+ break;
+ }
+ if (c == '\n')
+ q = 1;
+ else if (c == a)
+ {
+ stakwrite(bp, cp - bp);
+ bp = cp;
+ vp = cp + 1;
+ a = 0;
+ }
+ else if ((c == '#' || c == '~') && cp == vp || c == ']' || c != ':' && (c = sh_lexstates[ST_NORM][c]) && c != S_EPAT)
+ q = 1;
+ }
+ if (q & 2)
+ {
+ stakputc('$');
+ stakputc('\'');
+ cp = bp;
+ n = fold - 3;
+ q = 1;
+ while (c = mbchar(cp))
+ {
+ switch (c)
+ {
+ case ('a'==97?'\033':39):
+ c = 'E';
+ break;
+ case '\n':
+ q = 0;
+ n = fold - 1;
+ break;
+ case '\r':
+ c = 'r';
+ break;
+ case '\t':
+ c = 't';
+ break;
+ case '\f':
+ c = 'f';
+ break;
+ case '\b':
+ c = 'b';
+ break;
+ case '\a':
+ c = 'a';
+ break;
+ case '\\':
+ if (*cp == 'n')
+ {
+ c = '\n';
+ q = 0;
+ n = fold - 1;
+ break;
+ }
+ case '\'':
+ break;
+ default:
+#if SHOPT_MULTIBYTE
+ if(!iswprint(c))
+#else
+ if(!isprint(c))
+#endif
+ {
+ if ((n -= 4) <= 0)
+ {
+ stakwrite("'\\\n$'", 5);
+ n = fold - 7;
+ }
+ sfprintf(staksp, "\\%03o", c);
+ continue;
+ }
+ q = 0;
+ break;
+ }
+ if ((n -= q + 1) <= 0)
+ {
+ if (!q)
+ {
+ stakputc('\'');
+ cp = bp;
+ break;
+ }
+ stakwrite("'\\\n$'", 5);
+ n = fold - 5;
+ }
+ if (q)
+ stakputc('\\');
+ else
+ q = 1;
+ stakputc(c);
+ bp = cp;
+ }
+ if (!c)
+ stakputc('\'');
+ }
+ else if (q & 1)
+ {
+ stakputc('\'');
+ cp = bp;
+ n = fold ? (fold - 2) : 0;
+ while (c = mbchar(cp))
+ {
+ if (c == '\n')
+ n = fold - 1;
+ else if (n && --n <= 0)
+ {
+ n = fold - 2;
+ stakwrite(bp, --cp - bp);
+ bp = cp;
+ stakwrite("'\\\n'", 4);
+ }
+ else if (n == 1 && *cp == '\'')
+ {
+ n = fold - 5;
+ stakwrite(bp, --cp - bp);
+ bp = cp;
+ stakwrite("'\\\n\\''", 6);
+ }
+ else if (c == '\'')
+ {
+ stakwrite(bp, cp - bp - 1);
+ bp = cp;
+ if (n && (n -= 4) <= 0)
+ {
+ n = fold - 5;
+ stakwrite("'\\\n\\''", 6);
+ }
+ else
+ stakwrite("'\\''", 4);
+ }
+ }
+ stakwrite(bp, cp - bp - 1);
+ stakputc('\'');
+ }
+ else if (n = fold)
+ {
+ cp = bp;
+ while (c = mbchar(cp))
+ {
+ if (--n <= 0)
+ {
+ n = fold;
+ stakwrite(bp, --cp - bp);
+ bp = cp;
+ stakwrite("\\\n", 2);
+ }
+ }
+ stakwrite(bp, cp - bp - 1);
+ }
+ else
+ stakwrite(bp, cp - bp);
+ if (c)
+ {
+ stakputc('\\');
+ stakputc('\n');
+ }
+ } while (c);
+ stakputc(0);
+ return(stakptr(offset));
+}
+
+#if SHOPT_MULTIBYTE
+ int sh_strchr(const char *string, register const char *dp)
+ {
+ wchar_t c, d;
+ register const char *cp=string;
+ mbinit();
+ d = mbchar(dp);
+ mbinit();
+ while(c = mbchar(cp))
+ {
+ if(c==d)
+ return(cp-string);
+ }
+ if(d==0)
+ return(cp-string);
+ return(-1);
+ }
+#endif /* SHOPT_MULTIBYTE */
+
+const char *_sh_translate(const char *message)
+{
+#if ERROR_VERSION >= 20000317L
+ return(ERROR_translate(0,0,e_dict,message));
+#else
+#if ERROR_VERSION >= 20000101L
+ return(ERROR_translate(e_dict,message));
+#else
+ return(ERROR_translate(message,1));
+#endif
+#endif
+}
+
+/*
+ * change '['identifier']' to identifier
+ * character before <str> must be a '['
+ * returns pointer to last character
+ */
+char *sh_checkid(char *str, char *last)
+{
+ register unsigned char *cp = (unsigned char*)str;
+ register unsigned char *v = cp;
+ register int c;
+ if(c=mbchar(cp),isaletter(c))
+ while(c=mbchar(cp),isaname(c));
+ if(c==']' && (!last || ((char*)cp==last)))
+ {
+ /* eliminate [ and ] */
+ while(v < cp)
+ {
+ v[-1] = *v;
+ v++;
+ }
+ if(last)
+ last -=2;
+ else
+ {
+ while(*v)
+ {
+ v[-2] = *v;
+ v++;
+ }
+ v[-2] = 0;
+ last = (char*)v;
+ }
+ }
+ return(last);
+}
+
+#if _AST_VERSION <= 20000317L
+char *fmtident(const char *string)
+{
+ return((char*)string);
+}
+#endif
diff --git a/src/cmd/ksh93/sh/subshell.c b/src/cmd/ksh93/sh/subshell.c
new file mode 100644
index 0000000..c7c022b
--- /dev/null
+++ b/src/cmd/ksh93/sh/subshell.c
@@ -0,0 +1,780 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Create and manage subshells avoiding forks when possible
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <ls.h>
+#include "io.h"
+#include "fault.h"
+#include "shnodes.h"
+#include "shlex.h"
+#include "jobs.h"
+#include "variables.h"
+#include "path.h"
+
+#ifndef PIPE_BUF
+# define PIPE_BUF 512
+#endif
+
+/*
+ * Note that the following structure must be the same
+ * size as the Dtlink_t structure
+ */
+struct Link
+{
+ struct Link *next;
+ Namval_t *child;
+ Dt_t *dict;
+ Namval_t *node;
+};
+
+/*
+ * The following structure is used for command substitution and (...)
+ */
+static struct subshell
+{
+ Shell_t *shp; /* shell interpreter */
+ struct subshell *prev; /* previous subshell data */
+ struct subshell *pipe; /* subshell where output goes to pipe on fork */
+ Dt_t *var; /* variable table at time of subshell */
+ struct Link *svar; /* save shell variable table */
+ Dt_t *sfun; /* function scope for subshell */
+ Dt_t *salias;/* alias scope for subshell */
+ Pathcomp_t *pathlist; /* for PATH variable */
+#if (ERROR_VERSION >= 20030214L)
+ struct Error_context_s *errcontext;
+#else
+ struct errorcontext *errcontext;
+#endif
+ Shopt_t options;/* save shell options */
+ pid_t subpid; /* child process id */
+ Sfio_t* saveout;/*saved standard output */
+ char *pwd; /* present working directory */
+ const char *shpwd; /* saved pointer to sh.pwd */
+ void *jobs; /* save job info */
+ mode_t mask; /* saved umask */
+ short tmpfd; /* saved tmp file descriptor */
+ short pipefd; /* read fd if pipe is created */
+ char jobcontrol;
+ char monitor;
+ unsigned char fdstatus;
+ int fdsaved; /* bit make for saved files */
+ int sig; /* signal for $$ */
+ pid_t bckpid;
+ pid_t cpid;
+ int coutpipe;
+ int cpipe;
+ int nofork;
+ int subdup;
+ char subshare;
+ char comsub;
+#if SHOPT_COSHELL
+ void *coshell;
+#endif /* SHOPT_COSHELL */
+} *subshell_data;
+
+static int subenv;
+
+
+/*
+ * This routine will turn the sftmp() file into a real /tmp file or pipe
+ * if the /tmp file create fails
+ */
+void sh_subtmpfile(Shell_t *shp)
+{
+ if(sfset(sfstdout,0,0)&SF_STRING)
+ {
+ register int fd;
+ register struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ register struct subshell *sp = subshell_data->pipe;
+ /* save file descriptor 1 if open */
+ if((sp->tmpfd = fd = fcntl(1,F_DUPFD,10)) >= 0)
+ {
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fd] = shp->fdstatus[1]|IOCLEX;
+ close(1);
+ }
+ else if(errno!=EBADF)
+ errormsg(SH_DICT,ERROR_system(1),e_toomany);
+ /* popping a discipline forces a /tmp file create */
+ sfdisc(sfstdout,SF_POPDISC);
+ if((fd=sffileno(sfstdout))<0)
+ {
+ /* unable to create the /tmp file so use a pipe */
+ int fds[3];
+ Sfoff_t off;
+ fds[2] = 0;
+ sh_pipe(fds);
+ sp->pipefd = fds[0];
+ sh_fcntl(sp->pipefd,F_SETFD,FD_CLOEXEC);
+ /* write the data to the pipe */
+ if(off = sftell(sfstdout))
+ write(fds[1],sfsetbuf(sfstdout,(Void_t*)sfstdout,0),(size_t)off);
+ sfclose(sfstdout);
+ if((sh_fcntl(fds[1],F_DUPFD, 1)) != 1)
+ errormsg(SH_DICT,ERROR_system(1),e_file+4);
+ sh_close(fds[1]);
+ }
+ else
+ {
+ shp->fdstatus[fd] = IOREAD|IOWRITE;
+ sfsync(sfstdout);
+ if(fd==1)
+ fcntl(1,F_SETFD,0);
+ else
+ {
+ sfsetfd(sfstdout,1);
+ shp->fdstatus[1] = shp->fdstatus[fd];
+ shp->fdstatus[fd] = IOCLOSE;
+ }
+ }
+ sh_iostream(shp,1);
+ sfset(sfstdout,SF_SHARE|SF_PUBLIC,1);
+ sfpool(sfstdout,shp->outpool,SF_WRITE);
+ if(pp && pp->olist && pp->olist->strm == sfstdout)
+ pp->olist->strm = 0;
+ }
+}
+
+
+/*
+ * This routine creates a temp file if necessary and creates a subshell.
+ * The parent routine longjmps back to sh_subshell()
+ * The child continues possibly with its standard output replaced by temp file
+ */
+void sh_subfork(void)
+{
+ register struct subshell *sp = subshell_data;
+ Shell_t *shp = sp->shp;
+ int curenv = shp->curenv;
+ pid_t pid;
+ char *trap = shp->st.trapcom[0];
+ if(trap)
+ trap = strdup(trap);
+ /* see whether inside $(...) */
+ if(sp->pipe)
+ sh_subtmpfile(shp);
+ shp->curenv = 0;
+ shp->savesig = -1;
+ if(pid = sh_fork(shp,FSHOWME,NIL(int*)))
+ {
+ shp->curenv = curenv;
+ /* this is the parent part of the fork */
+ if(sp->subpid==0)
+ sp->subpid = pid;
+ if(trap)
+ free((void*)trap);
+ siglongjmp(*shp->jmplist,SH_JMPSUB);
+ }
+ else
+ {
+ /* this is the child part of the fork */
+ /* setting subpid to 1 causes subshell to exit when reached */
+ sh_onstate(SH_FORKED);
+ sh_onstate(SH_NOLOG);
+ sh_offoption(SH_MONITOR);
+ sh_offstate(SH_MONITOR);
+ subshell_data = 0;
+ shp->subshell = 0;
+ shp->comsub = 0;
+ SH_SUBSHELLNOD->nvalue.s = 0;
+ sp->subpid=0;
+ shp->st.trapcom[0] = trap;
+ shp->savesig = 0;
+ }
+}
+
+int nv_subsaved(register Namval_t *np)
+{
+ register struct subshell *sp;
+ register struct Link *lp;
+ for(sp = (struct subshell*)subshell_data; sp; sp=sp->prev)
+ {
+ for(lp=sp->svar; lp; lp = lp->next)
+ {
+ if(lp->node==np)
+ return(1);
+ }
+ }
+ return(0);
+}
+
+/*
+ * This routine will make a copy of the given node in the
+ * layer created by the most recent subshell_fork if the
+ * node hasn't already been copied
+ */
+Namval_t *sh_assignok(register Namval_t *np,int add)
+{
+ register Namval_t *mp;
+ register struct Link *lp;
+ register struct subshell *sp = (struct subshell*)subshell_data;
+ Shell_t *shp = sp->shp;
+ Dt_t *dp= shp->var_tree;
+ Namval_t *mpnext;
+ Namarr_t *ap;
+ int save;
+ /* don't bother with this */
+ if(!sp->shpwd || np==SH_LEVELNOD || np==L_ARGNOD || np==SH_SUBSCRNOD || np==SH_NAMENOD)
+ return(np);
+ /* don't bother to save if in newer scope */
+ if(sp->var!=shp->var_tree && sp->var!=shp->var_base && shp->last_root==shp->var_tree)
+ return(np);
+ if((ap=nv_arrayptr(np)) && (mp=nv_opensub(np)))
+ {
+ shp->last_root = ap->table;
+ sh_assignok(mp,add);
+ if(!add || array_assoc(ap))
+ return(np);
+ }
+ for(lp=sp->svar; lp;lp = lp->next)
+ {
+ if(lp->node==np)
+ return(np);
+ }
+ /* first two pointers use linkage from np */
+ lp = (struct Link*)malloc(sizeof(*np)+2*sizeof(void*));
+ memset(lp,0, sizeof(*mp)+2*sizeof(void*));
+ lp->node = np;
+ if(!add && nv_isvtree(np))
+ {
+ Namval_t fake;
+ Dt_t *walk, *root=shp->var_tree;
+ char *name = nv_name(np);
+ int len = strlen(name);
+ fake.nvname = name;
+ mpnext = dtnext(root,&fake);
+ dp = root->walk?root->walk:root;
+ while(mp=mpnext)
+ {
+ walk = root->walk?root->walk:root;
+ mpnext = dtnext(root,mp);
+ if(memcmp(name,mp->nvname,len) || mp->nvname[len]!='.')
+ break;
+ nv_delete(mp,walk,NV_NOFREE);
+ *((Namval_t**)mp) = lp->child;
+ lp->child = mp;
+
+ }
+ }
+ lp->dict = dp;
+ mp = (Namval_t*)&lp->dict;
+ lp->next = subshell_data->svar;
+ subshell_data->svar = lp;
+ save = shp->subshell;
+ shp->subshell = 0;
+ mp->nvname = np->nvname;
+ if(nv_isattr(np,NV_NOFREE))
+ nv_onattr(mp,NV_IDENT);
+ nv_clone(np,mp,(add?(nv_isnull(np)?0:NV_NOFREE)|NV_ARRAY:NV_MOVE));
+ shp->subshell = save;
+ return(np);
+}
+
+/*
+ * restore the variables
+ */
+static void nv_restore(struct subshell *sp)
+{
+ register struct Link *lp, *lq;
+ register Namval_t *mp, *np;
+ const char *save = sp->shpwd;
+ Namval_t *mpnext;
+ int flags,nofree;
+ sp->shpwd = 0; /* make sure sh_assignok doesn't save with nv_unset() */
+ for(lp=sp->svar; lp; lp=lq)
+ {
+ np = (Namval_t*)&lp->dict;
+ lq = lp->next;
+ mp = lp->node;
+ if(!mp->nvname)
+ continue;
+ flags = 0;
+ if(nv_isattr(mp,NV_MINIMAL) && !nv_isattr(np,NV_EXPORT))
+ flags |= NV_MINIMAL;
+ if(nv_isarray(mp))
+ nv_putsub(mp,NIL(char*),ARRAY_SCAN);
+ nofree = mp->nvfun?mp->nvfun->nofree:0;
+ _nv_unset(mp,NV_RDONLY|NV_CLONE);
+ if(nv_isarray(np))
+ {
+ nv_clone(np,mp,NV_MOVE);
+ goto skip;
+ }
+ nv_setsize(mp,nv_size(np));
+ if(!(flags&NV_MINIMAL))
+ mp->nvenv = np->nvenv;
+ if(!nofree)
+ mp->nvfun = np->nvfun;
+ if(nv_isattr(np,NV_IDENT))
+ {
+ nv_offattr(np,NV_IDENT);
+ flags |= NV_NOFREE;
+ }
+ mp->nvflag = np->nvflag|(flags&NV_MINIMAL);
+ if(nv_cover(mp))
+ nv_putval(mp, nv_getval(np),np->nvflag|NV_NOFREE);
+ else
+ mp->nvalue.cp = np->nvalue.cp;
+ if(nofree && np->nvfun && !np->nvfun->nofree)
+ free((char*)np->nvfun);
+ np->nvfun = 0;
+ if(nv_isattr(mp,NV_EXPORT))
+ {
+ char *name = nv_name(mp);
+ sh_envput(sp->shp->env,mp);
+ if(*name=='_' && strcmp(name,"_AST_FEATURES")==0)
+ astconf(NiL, NiL, NiL);
+ }
+ else if(nv_isattr(np,NV_EXPORT))
+ env_delete(sp->shp->env,nv_name(mp));
+ nv_onattr(mp,flags);
+ skip:
+ for(mp=lp->child; mp; mp=mpnext)
+ {
+ mpnext = *((Namval_t**)mp);
+ dtinsert(lp->dict,mp);
+ }
+ free((void*)lp);
+ sp->svar = lq;
+ }
+ sp->shpwd=save;
+}
+
+/*
+ * return pointer to alias tree
+ * create new one if in a subshell and one doesn't exist and create is non-zero
+ */
+Dt_t *sh_subaliastree(int create)
+{
+ register struct subshell *sp = subshell_data;
+ if(!sp || sp->shp->curenv==0)
+ return(sh.alias_tree);
+ if(!sp->salias && create)
+ {
+ sp->salias = dtopen(&_Nvdisc,Dtoset);
+ dtview(sp->salias,sp->shp->alias_tree);
+ sp->shp->alias_tree = sp->salias;
+ }
+ return(sp->salias);
+}
+
+/*
+ * return pointer to function tree
+ * create new one if in a subshell and one doesn't exist and create is non-zero
+ */
+Dt_t *sh_subfuntree(int create)
+{
+ register struct subshell *sp = subshell_data;
+ if(!sp || sp->shp->curenv==0)
+ return(sh.fun_tree);
+ if(!sp->sfun && create)
+ {
+ sp->sfun = dtopen(&_Nvdisc,Dtoset);
+ dtview(sp->sfun,sp->shp->fun_tree);
+ sp->shp->fun_tree = sp->sfun;
+ }
+ return(sp->shp->fun_tree);
+}
+
+static void table_unset(register Dt_t *root,int fun)
+{
+ register Namval_t *np,*nq;
+ int flag;
+ for(np=(Namval_t*)dtfirst(root);np;np=nq)
+ {
+ nq = (Namval_t*)dtnext(root,np);
+ flag=0;
+ if(fun && np->nvalue.rp && np->nvalue.rp->fname && *np->nvalue.rp->fname=='/')
+ {
+ np->nvalue.rp->fdict = 0;
+ flag = NV_NOFREE;
+ }
+ else
+ _nv_unset(np,NV_RDONLY);
+ nv_delete(np,root,flag|NV_FUNCTION);
+ }
+}
+
+int sh_subsavefd(register int fd)
+{
+ register struct subshell *sp = subshell_data;
+ register int old=0;
+ if(sp)
+ {
+ old = !(sp->fdsaved&(1<<(fd-1)));
+ sp->fdsaved |= (1<<(fd-1));
+ }
+ return(old);
+}
+
+void sh_subjobcheck(pid_t pid)
+{
+ register struct subshell *sp = subshell_data;
+ while(sp)
+ {
+ if(sp->cpid==pid)
+ {
+ sh_close(sp->coutpipe);
+ sh_close(sp->cpipe);
+ sp->coutpipe = sp->cpipe = -1;
+ return;
+ }
+ sp = sp->prev;
+ }
+}
+
+/*
+ * Run command tree <t> in a virtual sub-shell
+ * If comsub is not null, then output will be placed in temp file (or buffer)
+ * If comsub is not null, the return value will be a stream consisting of
+ * output of command <t>. Otherwise, NULL will be returned.
+ */
+
+Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, int flags, int comsub)
+{
+ struct subshell sub_data;
+ register struct subshell *sp = &sub_data;
+ int jmpval,nsig=0,duped=0;
+ int savecurenv = shp->curenv;
+ int savejobpgid = job.curpgid;
+ int *saveexitval = job.exitval;
+ int16_t subshell;
+ char *savsig;
+ Sfio_t *iop=0;
+ struct checkpt buff;
+ struct sh_scoped savst;
+ struct dolnod *argsav=0;
+ int argcnt;
+ memset((char*)sp, 0, sizeof(*sp));
+ sfsync(shp->outpool);
+ sh_sigcheck(shp);
+ shp->savesig = -1;
+ if(argsav = sh_arguse(shp))
+ argcnt = argsav->dolrefcnt;
+ if(shp->curenv==0)
+ {
+ subshell_data=0;
+ subenv = 0;
+ }
+ shp->curenv = ++subenv;
+ savst = shp->st;
+ sh_pushcontext(shp,&buff,SH_JMPSUB);
+ subshell = shp->subshell+1;
+ SH_SUBSHELLNOD->nvalue.s = subshell;
+ shp->subshell = subshell;
+ sp->prev = subshell_data;
+ sp->shp = shp;
+ sp->sig = 0;
+ subshell_data = sp;
+ sp->errcontext = &buff.err;
+ sp->var = shp->var_tree;
+ sp->options = shp->options;
+ sp->jobs = job_subsave();
+ sp->subdup = shp->subdup;
+#if SHOPT_COSHELL
+ sp->coshell = shp->coshell;
+ shp->coshell = 0;
+#endif /* SHOPT_COSHELL */
+ /* make sure initialization has occurred */
+ if(!shp->pathlist)
+ {
+ shp->pathinit = 1;
+ path_get(shp,".");
+ shp->pathinit = 0;
+ }
+ sp->pathlist = path_dup((Pathcomp_t*)shp->pathlist);
+ if(!shp->pwd)
+ path_pwd(shp,0);
+ sp->bckpid = shp->bckpid;
+ if(comsub)
+ sh_stats(STAT_COMSUB);
+ else
+ job.curpgid = 0;
+ sp->subshare = shp->subshare;
+ sp->comsub = shp->comsub;
+ shp->subshare = comsub==2 || (comsub==1 && sh_isoption(SH_SUBSHARE));
+ if(comsub)
+ shp->comsub = comsub;
+ if(!comsub || !shp->subshare)
+ {
+ sp->shpwd = shp->pwd;
+ sp->pwd = (shp->pwd?strdup(shp->pwd):0);
+ sp->mask = shp->mask;
+ sh_stats(STAT_SUBSHELL);
+ /* save trap table */
+ shp->st.otrapcom = 0;
+ if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
+ {
+ nsig += sizeof(char*);
+ memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
+ /* this nonsense needed for $(trap) */
+ shp->st.otrapcom = (char**)savsig;
+ }
+ sp->cpid = shp->cpid;
+ sp->coutpipe = shp->coutpipe;
+ sp->cpipe = shp->cpipe[1];
+ shp->cpid = 0;
+ sh_sigreset(0);
+ }
+ jmpval = sigsetjmp(buff.buff,0);
+ if(jmpval==0)
+ {
+ if(comsub)
+ {
+ /* disable job control */
+ shp->spid = 0;
+ sp->jobcontrol = job.jobcontrol;
+ sp->monitor = (sh_isstate(SH_MONITOR)!=0);
+ job.jobcontrol=0;
+ sh_offstate(SH_MONITOR);
+ sp->pipe = sp;
+ /* save sfstdout and status */
+ sp->saveout = sfswap(sfstdout,NIL(Sfio_t*));
+ sp->fdstatus = shp->fdstatus[1];
+ sp->tmpfd = -1;
+ sp->pipefd = -1;
+ /* use sftmp() file for standard output */
+ if(!(iop = sftmp(PIPE_BUF)))
+ {
+ sfswap(sp->saveout,sfstdout);
+ errormsg(SH_DICT,ERROR_system(1),e_tmpcreate);
+ }
+ sfswap(iop,sfstdout);
+ sfset(sfstdout,SF_READ,0);
+ shp->fdstatus[1] = IOWRITE;
+ if(!(sp->nofork = sh_state(SH_NOFORK)))
+ sh_onstate(SH_NOFORK);
+ flags |= sh_state(SH_NOFORK);
+ }
+ else if(sp->prev)
+ {
+ sp->pipe = sp->prev->pipe;
+ flags &= ~sh_state(SH_NOFORK);
+ }
+ if(shp->savesig < 0)
+ {
+ shp->savesig = 0;
+ sh_exec(t,flags);
+ }
+ }
+ if(comsub!=2 && jmpval!=SH_JMPSUB && shp->st.trapcom[0] && shp->subshell)
+ {
+ /* trap on EXIT not handled by child */
+ char *trap=shp->st.trapcom[0];
+ shp->st.trapcom[0] = 0; /* prevent recursion */
+ shp->oldexit = shp->exitval;
+ sh_trap(trap,0);
+ free(trap);
+ }
+ sh_popcontext(shp,&buff);
+ if(shp->subshell==0) /* must be child process */
+ {
+ subshell_data = sp->prev;
+ if(jmpval==SH_JMPSCRIPT)
+ siglongjmp(*shp->jmplist,jmpval);
+ shp->exitval &= SH_EXITMASK;
+ sh_done(shp,0);
+ }
+ if(!shp->savesig)
+ shp->savesig = -1;
+ if(comsub)
+ {
+ /* re-enable job control */
+ if(!sp->nofork)
+ sh_offstate(SH_NOFORK);
+ job.jobcontrol = sp->jobcontrol;
+ if(sp->monitor)
+ sh_onstate(SH_MONITOR);
+ if(sp->pipefd>=0)
+ {
+ /* sftmp() file has been returned into pipe */
+ iop = sh_iostream(shp,sp->pipefd);
+ sfclose(sfstdout);
+ }
+ else
+ {
+ /* move tmp file to iop and restore sfstdout */
+ iop = sfswap(sfstdout,NIL(Sfio_t*));
+ if(!iop)
+ {
+ /* maybe locked try again */
+ sfclrlock(sfstdout);
+ iop = sfswap(sfstdout,NIL(Sfio_t*));
+ }
+ if(iop && sffileno(iop)==1)
+ {
+ int fd=sfsetfd(iop,3);
+ if(fd<0)
+ {
+ shp->toomany = 1;
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
+ errormsg(SH_DICT,ERROR_system(1),e_toomany);
+ }
+ if(fd >= shp->gd->lim.open_max)
+ sh_iovalidfd(shp,fd);
+ shp->sftable[fd] = iop;
+ fcntl(fd,F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[fd] = (shp->fdstatus[1]|IOCLEX);
+ shp->fdstatus[1] = IOCLOSE;
+ }
+ sfset(iop,SF_READ,1);
+ }
+ sfswap(sp->saveout,sfstdout);
+ /* check if standard output was preserved */
+ if(sp->tmpfd>=0)
+ {
+ close(1);
+ if (fcntl(sp->tmpfd,F_DUPFD,1) != 1)
+ duped++;
+ sh_close(sp->tmpfd);
+ }
+ shp->fdstatus[1] = sp->fdstatus;
+ }
+ path_delete((Pathcomp_t*)shp->pathlist);
+ shp->pathlist = (void*)sp->pathlist;
+ job_subrestore(sp->jobs);
+ shp->jobenv = savecurenv;
+ job.curpgid = savejobpgid;
+ job.exitval = saveexitval;
+ shp->bckpid = sp->bckpid;
+ if(sp->shpwd) /* restore environment if saved */
+ {
+ int n;
+ shp->options = sp->options;
+ nv_restore(sp);
+ if(sp->salias)
+ {
+ shp->alias_tree = dtview(sp->salias,0);
+ table_unset(sp->salias,0);
+ dtclose(sp->salias);
+ }
+ if(sp->sfun)
+ {
+ shp->fun_tree = dtview(sp->sfun,0);
+ table_unset(sp->sfun,1);
+ dtclose(sp->sfun);
+ }
+ n = shp->st.trapmax-savst.trapmax;
+ sh_sigreset(1);
+ if(n>0)
+ memset(&shp->st.trapcom[savst.trapmax],0,n*sizeof(char*));
+ shp->st = savst;
+ shp->curenv = savecurenv;
+ if(nsig)
+ {
+ memcpy((char*)&shp->st.trapcom[0],savsig,nsig);
+ free((void*)savsig);
+ }
+ shp->options = sp->options;
+ if(!shp->pwd || strcmp(sp->pwd,shp->pwd))
+ {
+ /* restore PWDNOD */
+ Namval_t *pwdnod = sh_scoped(shp,PWDNOD);
+ if(shp->pwd)
+ {
+ chdir(shp->pwd=sp->pwd);
+ path_newdir(shp,shp->pathlist);
+ }
+ if(nv_isattr(pwdnod,NV_NOFREE))
+ pwdnod->nvalue.cp = (const char*)sp->pwd;
+ }
+ else if(sp->shpwd != shp->pwd)
+ {
+ shp->pwd = sp->pwd;
+ if(PWDNOD->nvalue.cp==sp->shpwd)
+ PWDNOD->nvalue.cp = sp->pwd;
+ }
+ else
+ free((void*)sp->pwd);
+ if(sp->mask!=shp->mask)
+ umask(shp->mask=sp->mask);
+ if(shp->coutpipe!=sp->coutpipe)
+ {
+ sh_close(shp->coutpipe);
+ sh_close(shp->cpipe[1]);
+ }
+ shp->cpid = sp->cpid;
+ shp->cpipe[1] = sp->cpipe;
+ shp->coutpipe = sp->coutpipe;
+ }
+ shp->subshare = sp->subshare;
+ shp->comsub = sp->comsub;
+ shp->subdup = sp->subdup;
+#if SHOPT_COSHELL
+ shp->coshell = sp->coshell;
+#endif /* SHOPT_COSHELL */
+ if(shp->subshell)
+ SH_SUBSHELLNOD->nvalue.s = --shp->subshell;
+ subshell = shp->subshell;
+ subshell_data = sp->prev;
+ if(!argsav || argsav->dolrefcnt==argcnt)
+ sh_argfree(shp,argsav,0);
+ if(shp->topfd != buff.topfd)
+ sh_iorestore(shp,buff.topfd|IOSUBSHELL,jmpval);
+ if(sp->sig)
+ {
+ if(sp->prev)
+ sp->prev->sig = sp->sig;
+ else
+ {
+ sh_fault(sp->sig);
+ sh_chktrap(shp);
+ }
+ }
+ sh_sigcheck(shp);
+ shp->trapnote = 0;
+ nsig = shp->savesig;
+ shp->savesig = 0;
+ if(nsig>0)
+ sh_fault(nsig);
+ if(sp->subpid)
+ job_wait(sp->subpid);
+ if(comsub && iop && sp->pipefd<0)
+ sfseek(iop,(off_t)0,SEEK_SET);
+ if(shp->trapnote)
+ sh_chktrap(shp);
+ if(shp->exitval > SH_EXITSIG)
+ {
+ int sig = shp->exitval&SH_EXITMASK;
+ if(sig==SIGINT || sig== SIGQUIT)
+ sh_fault(sig);
+ }
+ if(duped)
+ {
+ ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
+ shp->toomany = 1;
+ errormsg(SH_DICT,ERROR_system(1),e_redirect);
+ }
+ if(shp->ignsig)
+ sh_fault(shp->ignsig);
+ if(jmpval==SH_JMPSUB && shp->lastsig)
+ sh_fault(shp->lastsig);
+ if(jmpval && shp->toomany)
+ siglongjmp(*shp->jmplist,jmpval);
+ return(iop);
+}
diff --git a/src/cmd/ksh93/sh/suid_exec.c b/src/cmd/ksh93/sh/suid_exec.c
new file mode 100644
index 0000000..a635b63
--- /dev/null
+++ b/src/cmd/ksh93/sh/suid_exec.c
@@ -0,0 +1,509 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * This is a program to execute 'execute only' and suid/sgid shell scripts.
+ * This program must be owned by root and must have the set uid bit set.
+ * It must not have the set group id bit set. This program must be installed
+ * where the define parameter THISPROG indicates to work correctly on system V
+ *
+ * Written by David Korn
+ * AT&T Labs
+ * Enhanced by Rob Stampfli
+ */
+
+/* The file name of the script to execute is argv[0]
+ * Argv[1] is the program name
+ * The basic idea is to open the script as standard input, set the effective
+ * user and group id correctly, and then exec the shell.
+ * The complicated part is getting the effective uid of the caller and
+ * setting the effective uid/gid. The program which execs this program
+ * may pass file descriptor FDIN as an open file with mode SPECIAL if
+ * the effective user id is not the real user id. The effective
+ * user id for authentication purposes will be the owner of this
+ * open file. On systems without the setreuid() call, e[ug]id is set
+ * by copying this program to a /tmp/file, making it a suid and/or sgid
+ * program, and then execing this program.
+ * A forked version of this program waits until it can unlink the /tmp
+ * file and then exits. Actually, we fork() twice so the parent can
+ * wait for the child to complete. A pipe is used to guarantee that we
+ * do not remove the /tmp file too soon.
+ */
+
+#include <ast.h>
+#include "FEATURE/externs"
+#include <ls.h>
+#include <sig.h>
+#include <error.h>
+#include <sys/wait.h>
+#include "version.h"
+
+#define SPECIAL 04100 /* setuid execute only by owner */
+#define FDIN 10 /* must be same as /dev/fd below */
+#undef FDSYNC
+#define FDSYNC 11 /* used on sys5 to synchronize cleanup */
+#define FDVERIFY 12 /* used to validate /tmp process */
+#undef BLKSIZE
+#define BLKSIZE sizeof(char*)*1024
+#define THISPROG "/etc/suid_exec"
+#define DEFSHELL "/bin/sh"
+
+static void error_exit(const char*);
+static int in_dir(const char*, const char*);
+static int endsh(const char*);
+#ifndef _lib_setregid
+# undef _lib_setreuid
+#endif
+#ifndef _lib_setreuid
+ static void setids(int,uid_t,gid_t);
+ static int mycopy(int, int);
+ static void maketemp(char*);
+#else
+ static void setids(int,int,int);
+#endif /* _lib_setreuid */
+
+static const char version[] = "\n@(#)$Id: suid_exec "SH_RELEASE" $\n";
+static const char badopen[] = "cannot open";
+static const char badexec[] = "cannot exec";
+static const char devfd[] = "/dev/fd/10"; /* must match FDIN above */
+static char tmpname[] = "/tmp/SUIDXXXXXX";
+static char **arglist;
+
+static char *shell;
+static char *command;
+static uid_t ruserid;
+static uid_t euserid;
+static gid_t rgroupid;
+static gid_t egroupid;
+static struct stat statb;
+
+int main(int argc,char *argv[])
+{
+ register int m,n;
+ register char *p;
+ struct stat statx;
+ int mode;
+ uid_t effuid;
+ gid_t effgid;
+ NOT_USED(argc);
+ arglist = argv;
+ if((command = argv[1]) == 0)
+ error_exit(badexec);
+ ruserid = getuid();
+ euserid = geteuid();
+ rgroupid = getgid();
+ egroupid = getegid();
+ p = argv[0];
+#ifndef _lib_setreuid
+ maketemp(tmpname);
+ if(strcmp(p,tmpname)==0)
+ {
+ /* At this point, the presumption is that we are the
+ * version of THISPROG copied into /tmp, with the owner,
+ * group, and setuid/gid bits correctly set. This copy of
+ * the program is executable by anyone, so we must be careful
+ * not to allow just any invocation of it to succeed, since
+ * it is setuid/gid. Validate the proper execution by
+ * examining the FDVERIFY file descriptor -- if it is owned
+ * by root and is mode SPECIAL, then this is proof that it was
+ * passed by a program with superuser privileges -- hence we
+ * can presume legitimacy. Otherwise, bail out, as we suspect
+ * an impostor.
+ */
+ if(fstat(FDVERIFY,&statb) < 0 || statb.st_uid != 0 ||
+ (statb.st_mode & ~S_IFMT) != SPECIAL || close(FDVERIFY)<0)
+ error_exit(badexec);
+ /* This enables the grandchild to clean up /tmp file */
+ close(FDSYNC);
+ /* Make sure that this is a valid invocation of the clone.
+ * Perhaps unnecessary, given FDVERIFY, but what the heck...
+ */
+ if(stat(tmpname,&statb) < 0 || statb.st_nlink != 1 ||
+ !S_ISREG(statb.st_mode))
+ error_exit(badexec);
+ if(ruserid != euserid &&
+ ((statb.st_mode & S_ISUID) == 0 || statb.st_uid != euserid))
+ error_exit(badexec);
+ goto exec;
+ }
+ /* Make sure that this is the real setuid program, not the clone.
+ * It is possible by clever hacking to get past this point in the
+ * clone, but it doesn't do the hacker any good that I can see.
+ */
+ if(euserid)
+ error_exit(badexec);
+#endif /* _lib_setreuid */
+ /* Open the script for reading first and then validate it. This
+ * prevents someone from pulling a switcheroo while we are validating.
+ */
+ n = open(p,0);
+ if(n == FDIN)
+ {
+ n = dup(n);
+ close(FDIN);
+ }
+ if(n < 0)
+ error_exit(badopen);
+ /* validate execution rights to this script */
+ if(fstat(FDIN,&statb) < 0 || (statb.st_mode & ~S_IFMT) != SPECIAL)
+ euserid = ruserid;
+ else
+ euserid = statb.st_uid;
+ /* do it the easy way if you can */
+ if(euserid == ruserid && egroupid == rgroupid)
+ {
+ if(access(p,X_OK) < 0)
+ error_exit(badexec);
+ }
+ else
+ {
+ /* have to check access on each component */
+ while(*p++)
+ {
+ if(*p == '/' || *p == 0)
+ {
+ m = *p;
+ *p = 0;
+ if(eaccess(argv[0],X_OK) < 0)
+ error_exit(badexec);
+ *p = m;
+ }
+ }
+ p = argv[0];
+ }
+ if(fstat(n, &statb) < 0 || !S_ISREG(statb.st_mode))
+ error_exit(badopen);
+ if(stat(p, &statx) < 0 ||
+ statb.st_ino != statx.st_ino || statb.st_dev != statx.st_dev)
+ error_exit(badexec);
+ if(stat(THISPROG, &statx) < 0 ||
+ (statb.st_ino == statx.st_ino && statb.st_dev == statx.st_dev))
+ error_exit(badexec);
+ close(FDIN);
+ if(fcntl(n,F_DUPFD,FDIN) != FDIN)
+ error_exit(badexec);
+ close(n);
+
+ /* compute the desired new effective user and group id */
+ effuid = euserid;
+ effgid = egroupid;
+ mode = 0;
+ if(statb.st_mode & S_ISUID)
+ effuid = statb.st_uid;
+ if(statb.st_mode & S_ISGID)
+ effgid = statb.st_gid;
+
+ /* see if group needs setting */
+ if(effgid != egroupid)
+ if(effgid != rgroupid || setgid(rgroupid) < 0)
+ mode = S_ISGID;
+
+ /* now see if the uid needs setting */
+ if(mode)
+ {
+ if(effuid != ruserid)
+ mode |= S_ISUID;
+ }
+ else if(effuid)
+ {
+ if(effuid != ruserid || setuid(ruserid) < 0)
+ mode = S_ISUID;
+ }
+
+ if(mode)
+ setids(mode, effuid, effgid);
+#ifndef _lib_setreuid
+exec:
+#endif /* _lib_setreuid */
+ /* only use SHELL if file is in trusted directory and ends in sh */
+ shell = getenv("SHELL");
+ if(shell == 0 || !endsh(shell) || (
+ !in_dir("/bin",shell) &&
+ !in_dir("/usr/bin",shell) &&
+ !in_dir("/usr/lbin",shell) &&
+ !in_dir("/usr/local/bin",shell)))
+ shell = DEFSHELL;
+ argv[0] = command;
+ argv[1] = (char*)devfd;
+ execv(shell,argv);
+ error_exit(badexec);
+}
+
+/*
+ * return true of shell ends in sh of ksh
+ */
+
+static int endsh(register const char *shell)
+{
+ while(*shell)
+ shell++;
+ if(*--shell != 'h' || *--shell != 's')
+ return(0);
+ if(*--shell=='/')
+ return(1);
+ if(*shell=='k' && *--shell=='/')
+ return(1);
+ return(0);
+}
+
+
+/*
+ * return true of shell is in <dir> directory
+ */
+
+static int in_dir(register const char *dir,register const char *shell)
+{
+ while(*dir)
+ {
+ if(*dir++ != *shell++)
+ return(0);
+ }
+ /* return true if next character is a '/' */
+ return(*shell=='/');
+}
+
+static void error_exit(const char *message)
+{
+ sfprintf(sfstdout,"%s: %s\n",command,message);
+ exit(126);
+}
+
+
+/*
+ * This version of access checks against effective uid and effective gid
+ */
+
+int eaccess(register const char *name, register int mode)
+{
+ struct stat statb;
+ if (stat(name, &statb) == 0)
+ {
+ if(euserid == 0)
+ {
+ if(!S_ISREG(statb.st_mode) || mode != 1)
+ return(0);
+ /* root needs execute permission for someone */
+ mode = (S_IXUSR|S_IXGRP|S_IXOTH);
+ }
+ else if(euserid == statb.st_uid)
+ mode <<= 6;
+ else if(egroupid == statb.st_gid)
+ mode <<= 3;
+#ifdef _lib_getgroups
+ /* on some systems you can be in several groups */
+ else
+ {
+ static int maxgroups;
+ gid_t *groups=0;
+ register int n;
+ if(maxgroups==0)
+ {
+ /* first time */
+ if((maxgroups=getgroups(0,groups)) < 0)
+ {
+ /* pre-POSIX system */
+ maxgroups=NGROUPS_MAX;
+ }
+ }
+ groups = (gid_t*)malloc((maxgroups+1)*sizeof(gid_t));
+ n = getgroups(maxgroups,groups);
+ while(--n >= 0)
+ {
+ if(groups[n] == statb.st_gid)
+ {
+ mode <<= 3;
+ break;
+ }
+ }
+ }
+#endif /* _lib_getgroups */
+ if(statb.st_mode & mode)
+ return(0);
+ }
+ return(-1);
+}
+
+#ifdef _lib_setreuid
+static void setids(int mode,int owner,int group)
+{
+ if(mode & S_ISGID)
+ setregid(rgroupid,group);
+
+ /* set effective uid even if S_ISUID is not set. This is because
+ * we are *really* executing EUID root at this point. Even if S_ISUID
+ * is not set, the value for owner that is passsed should be correct.
+ */
+ setreuid(ruserid,owner);
+}
+
+#else
+/*
+ * This version of setids creats a /tmp file and copies itself into it.
+ * The "clone" file is made executable with appropriate suid/sgid bits.
+ * Finally, the clone is exec'ed. This file is unlinked by a grandchild
+ * of this program, who waits around until the text is free.
+ */
+
+static void setids(int mode,uid_t owner,gid_t group)
+{
+ register int n,m;
+ int pv[2];
+
+ /*
+ * Create a token to pass to the new program for validation.
+ * This token can only be procured by someone running with an
+ * effective userid of root, and hence gives the clone a way to
+ * certify that it was really invoked by THISPROG. Someone who
+ * is already root could spoof us, but why would they want to?
+ *
+ * Since we are root here, we must be careful: What if someone
+ * linked a valuable file to tmpname?
+ */
+ unlink(tmpname); /* should normally fail */
+#ifdef O_EXCL
+ if((n = open(tmpname, O_WRONLY | O_CREAT | O_EXCL, SPECIAL)) < 0 ||
+ unlink(tmpname) < 0)
+#else
+ if((n = open(tmpname, O_WRONLY | O_CREAT ,SPECIAL)) < 0 || unlink(tmpname) < 0)
+#endif
+ error_exit(badexec);
+ if(n != FDVERIFY)
+ {
+ close(FDVERIFY);
+ if(fcntl(n,F_DUPFD,FDVERIFY) != FDVERIFY)
+ error_exit(badexec);
+ }
+ mode |= S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6);
+ /* create a pipe for synchronization */
+ if(pipe(pv) < 0)
+ error_exit(badexec);
+ if((n=fork()) == 0)
+ { /* child */
+ close(FDVERIFY);
+ close(pv[1]);
+ if((n=fork()) == 0)
+ { /* grandchild -- cleans up clone file */
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGTERM, SIG_IGN);
+ read(pv[0],pv,1); /* wait for clone to close pipe */
+ while(unlink(tmpname) < 0 && errno == ETXTBSY)
+ sleep(1);
+ exit(0);
+ }
+ else if(n == -1)
+ exit(1);
+ else
+ {
+ /* Create a set[ug]id file that will become the clone.
+ * To make this atomic, without need for chown(), the
+ * child takes on desired user and group. The only
+ * downsize of this that I can see is that it may
+ * screw up some per- * user accounting.
+ */
+ if((m = open(THISPROG, O_RDONLY)) < 0)
+ exit(1);
+ if((mode & S_ISGID) && setgid(group) < 0)
+ exit(1);
+ if((mode & S_ISUID) && owner && setuid(owner) < 0)
+ exit(1);
+#ifdef O_EXCL
+ if((n = open(tmpname,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, mode)) < 0)
+#else
+ unlink(tmpname);
+ if((n = open(tmpname,O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0)
+#endif /* O_EXCL */
+ exit(1);
+ /* populate the clone */
+ m = mycopy(m,n);
+ if(chmod(tmpname,mode) <0)
+ exit(1);
+ exit(m);
+ }
+ }
+ else if(n == -1)
+ error_exit(badexec);
+ else
+ {
+ arglist[0] = (char*)tmpname;
+ close(pv[0]);
+ /* move write end of pipe into FDSYNC */
+ if(pv[1] != FDSYNC)
+ {
+ close(FDSYNC);
+ if(fcntl(pv[1],F_DUPFD,FDSYNC) != FDSYNC)
+ error_exit(badexec);
+ }
+ /* wait for child to die */
+ while((m = wait(0)) != n)
+ if(m == -1 && errno != EINTR)
+ break;
+ /* Kill any setuid status at this point. That way, if the
+ * clone is not setuid, we won't exec it as root. Also, don't
+ * neglect to consider that someone could have switched the
+ * clone file on us.
+ */
+ if(setuid(ruserid) < 0)
+ error_exit(badexec);
+ execv(tmpname,arglist);
+ error_exit(badexec);
+ }
+}
+
+/*
+ * create a unique name into the <template>
+ */
+
+static void maketemp(char *template)
+{
+ register char *cp = template;
+ register pid_t n = getpid();
+ /* skip to end of string */
+ while(*++cp);
+ /* convert process id to string */
+ while(n > 0)
+ {
+ *--cp = (n%10) + '0';
+ n /= 10;
+ }
+
+}
+
+/*
+ * copy THISPROG into the open file number <fdo> and close <fdo>
+ */
+
+static int mycopy(int fdi, int fdo)
+{
+ char buffer[BLKSIZE];
+ register int n;
+
+ while((n = read(fdi,buffer,BLKSIZE)) > 0)
+ if(write(fdo,buffer,n) != n)
+ break;
+ close(fdi);
+ close(fdo);
+ return n;
+}
+
+#endif /* _lib_setreuid */
+
+
diff --git a/src/cmd/ksh93/sh/tdump.c b/src/cmd/ksh93/sh/tdump.c
new file mode 100644
index 0000000..d3d82d8
--- /dev/null
+++ b/src/cmd/ksh93/sh/tdump.c
@@ -0,0 +1,262 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * shell parse tree dump
+ *
+ */
+
+#include "defs.h"
+#include "shnodes.h"
+#include "path.h"
+#include "io.h"
+#include <ccode.h>
+
+static int p_comlist(const struct dolnod*);
+static int p_arg(const struct argnod*);
+static int p_comarg(const struct comnod*);
+static int p_redirect(const struct ionod*);
+static int p_switch(const struct regnod*);
+static int p_tree(const Shnode_t*);
+static int p_string(const char*);
+
+static Sfio_t *outfile;
+
+int sh_tdump(Sfio_t *out, const Shnode_t *t)
+{
+ outfile = out;
+ return(p_tree(t));
+}
+
+/*
+ * convert to ASCII to write and back again if needed
+ */
+static int outstring(Sfio_t *out, const char *string, int n)
+{
+ int r;
+ char *cp = (char*)string;
+ ccmaps(cp, n, CC_NATIVE, CC_ASCII);
+ r = sfwrite(out,cp,n);
+ ccmaps(cp, n, CC_ASCII, CC_NATIVE);
+ return(r);
+}
+
+/*
+ * print script corresponding to shell tree <t>
+ */
+static int p_tree(register const Shnode_t *t)
+{
+ if(!t)
+ return(sfputl(outfile,-1));
+ if(sfputl(outfile,t->tre.tretyp)<0)
+ return(-1);
+ switch(t->tre.tretyp&COMMSK)
+ {
+ case TTIME:
+ case TPAR:
+ return(p_tree(t->par.partre));
+ case TCOM:
+ return(p_comarg((struct comnod*)t));
+ case TSETIO:
+ case TFORK:
+ if(sfputu(outfile,t->fork.forkline)<0)
+ return(-1);
+ if(p_tree(t->fork.forktre)<0)
+ return(-1);
+ return(p_redirect(t->fork.forkio));
+ case TIF:
+ if(p_tree(t->if_.iftre)<0)
+ return(-1);
+ if(p_tree(t->if_.thtre)<0)
+ return(-1);
+ return(p_tree(t->if_.eltre));
+ case TWH:
+ if(t->wh.whinc)
+ {
+ if(p_tree((Shnode_t*)(t->wh.whinc))<0)
+ return(-1);
+ }
+ else
+ {
+ if(sfputl(outfile,-1)<0)
+ return(-1);
+ }
+ if(p_tree(t->wh.whtre)<0)
+ return(-1);
+ return(p_tree(t->wh.dotre));
+ case TLST:
+ case TAND:
+ case TORF:
+ case TFIL:
+ if(p_tree(t->lst.lstlef)<0)
+ return(-1);
+ return(p_tree(t->lst.lstrit));
+ case TARITH:
+ if(sfputu(outfile,t->ar.arline)<0)
+ return(-1);
+ return(p_arg(t->ar.arexpr));
+ case TFOR:
+ if(sfputu(outfile,t->for_.forline)<0)
+ return(-1);
+ if(p_tree(t->for_.fortre)<0)
+ return(-1);
+ if(p_string(t->for_.fornam)<0)
+ return(-1);
+ return(p_tree((Shnode_t*)t->for_.forlst));
+ case TSW:
+ if(sfputu(outfile,t->sw.swline)<0)
+ return(-1);
+ if(p_arg(t->sw.swarg)<0)
+ return(-1);
+ return(p_switch(t->sw.swlst));
+ case TFUN:
+ if(sfputu(outfile,t->funct.functline)<0)
+ return(-1);
+ if(p_string(t->funct.functnam)<0)
+ return(-1);
+ if(p_tree(t->funct.functtre)<0)
+ return(-1);
+ return(p_tree((Shnode_t*)t->funct.functargs));
+ case TTST:
+ if(sfputu(outfile,t->tst.tstline)<0)
+ return(-1);
+ if((t->tre.tretyp&TPAREN)==TPAREN)
+ return(p_tree(t->lst.lstlef));
+ else
+ {
+ if(p_arg(&(t->lst.lstlef->arg))<0)
+ return(-1);
+ if((t->tre.tretyp&TBINARY))
+ return(p_arg(&(t->lst.lstrit->arg)));
+ return(0);
+ }
+ }
+ return(-1);
+}
+
+static int p_arg(register const struct argnod *arg)
+{
+ register int n;
+ struct fornod *fp;
+ while(arg)
+ {
+ if((n = strlen(arg->argval)) || (arg->argflag&~(ARG_APPEND|ARG_MESSAGE|ARG_QUOTED)))
+ fp=0;
+ else
+ {
+ fp=(struct fornod*)arg->argchn.ap;
+ n = strlen(fp->fornam)+1;
+ }
+ sfputu(outfile,n+1);
+ if(fp)
+ {
+ sfputc(outfile,0);
+ outstring(outfile,fp->fornam,n-1);
+ }
+ else
+ outstring(outfile,arg->argval,n);
+ sfputc(outfile,arg->argflag);
+ if(fp)
+ {
+ sfputu(outfile,fp->fortyp);
+ p_tree(fp->fortre);
+ }
+ else if(n==0 && (arg->argflag&ARG_EXP) && arg->argchn.ap)
+ p_tree((Shnode_t*)arg->argchn.ap);
+ arg = arg->argnxt.ap;
+ }
+ return(sfputu(outfile,0));
+}
+
+static int p_redirect(register const struct ionod *iop)
+{
+ while(iop)
+ {
+ if(iop->iovname)
+ sfputl(outfile,iop->iofile|IOVNM);
+ else
+ sfputl(outfile,iop->iofile);
+ p_string(iop->ioname);
+ if(iop->iodelim)
+ {
+ p_string(iop->iodelim);
+ sfputl(outfile,iop->iosize);
+ sfseek(sh.heredocs,iop->iooffset,SEEK_SET);
+ sfmove(sh.heredocs,outfile, iop->iosize,-1);
+ }
+ else
+ sfputu(outfile,0);
+ if(iop->iovname)
+ p_string(iop->iovname);
+ iop = iop->ionxt;
+ }
+ return(sfputl(outfile,-1));
+}
+
+static int p_comarg(register const struct comnod *com)
+{
+ p_redirect(com->comio);
+ p_arg(com->comset);
+ if(!com->comarg)
+ sfputl(outfile,-1);
+ else if(com->comtyp&COMSCAN)
+ p_arg(com->comarg);
+ else
+ p_comlist((struct dolnod*)com->comarg);
+ return(sfputu(outfile,com->comline));
+}
+
+static int p_comlist(const struct dolnod *dol)
+{
+ register char *cp, *const*argv;
+ register int n;
+ argv = dol->dolval+ARG_SPARE;
+ while(cp = *argv)
+ argv++;
+ n = argv - (dol->dolval+1);
+ sfputl(outfile,n);
+ argv = dol->dolval+ARG_SPARE;
+ while(cp = *argv++)
+ p_string(cp);
+ return(sfputu(outfile,0));
+}
+
+static int p_switch(register const struct regnod *reg)
+{
+ while(reg)
+ {
+ sfputl(outfile,reg->regflag);
+ p_arg(reg->regptr);
+ p_tree(reg->regcom);
+ reg = reg->regnxt;
+ }
+ return(sfputl(outfile,-1));
+}
+
+static int p_string(register const char *string)
+{
+ register size_t n=strlen(string);
+ if(sfputu(outfile,n+1)<0)
+ return(-1);
+ return(outstring(outfile,string,n));
+}
diff --git a/src/cmd/ksh93/sh/timers.c b/src/cmd/ksh93/sh/timers.c
new file mode 100644
index 0000000..d9ace52
--- /dev/null
+++ b/src/cmd/ksh93/sh/timers.c
@@ -0,0 +1,248 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <sig.h>
+#include <error.h>
+#include "fault.h"
+#include "defs.h"
+#include "FEATURE/sigfeatures"
+#include "FEATURE/time"
+
+typedef struct _timer
+{
+ double wakeup;
+ double incr;
+ struct _timer *next;
+ void (*action)(void*);
+ void *handle;
+} Timer_t;
+
+#define IN_ADDTIMEOUT 1
+#define IN_SIGALRM 2
+#define DEFER_SIGALRM 4
+#define SIGALRM_CALL 8
+
+static Timer_t *tptop, *tpmin, *tpfree;
+static char time_state;
+
+static double getnow(void)
+{
+ register double now;
+#ifdef timeofday
+ struct timeval tp;
+ timeofday(&tp);
+ now = tp.tv_sec + 1.e-6*tp.tv_usec;
+
+#else
+ now = (double)time((time_t*)0);
+#endif /* timeofday */
+ return(now+.001);
+}
+
+/*
+ * set an alarm for <t> seconds
+ */
+static double setalarm(register double t)
+{
+#if defined(_lib_setitimer) && defined(ITIMER_REAL)
+ struct itimerval tnew, told;
+ tnew.it_value.tv_sec = t;
+ tnew.it_value.tv_usec = 1.e6*(t- (double)tnew.it_value.tv_sec);
+ if(t && tnew.it_value.tv_sec==0 && tnew.it_value.tv_usec<1000)
+ tnew.it_value.tv_usec = 1000;
+ tnew.it_interval.tv_sec = 0;
+ tnew.it_interval.tv_usec = 0;
+ if(setitimer(ITIMER_REAL,&tnew,&told) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_alarm);
+ t = told.it_value.tv_sec + 1.e-6*told.it_value.tv_usec;
+#else
+ unsigned seconds = (unsigned)t;
+ if(t && seconds<1)
+ seconds=1;
+ t = (double)alarm(seconds);
+#endif
+ return(t);
+}
+
+/* signal handler for alarm call */
+static void sigalrm(int sig)
+{
+ register Timer_t *tp, *tplast, *tpold, *tpnext;
+ double now;
+ static double left;
+ NOT_USED(sig);
+ left = 0;
+ if(time_state&SIGALRM_CALL)
+ time_state &= ~SIGALRM_CALL;
+ else if(alarm(0))
+ sh_fault(SIGALRM|SH_TRAP);
+ if(time_state)
+ {
+ if(time_state&IN_ADDTIMEOUT)
+ time_state |= DEFER_SIGALRM;
+ errno = EINTR;
+ return;
+ }
+ time_state |= IN_SIGALRM;
+ sigrelease(SIGALRM);
+ while(1)
+ {
+ now = getnow();
+ tpold = tpmin = 0;
+ for(tplast=0,tp=tptop; tp; tp=tpnext)
+ {
+ tpnext = tp->next;
+ if(tp->action)
+ {
+ if(tp->wakeup <=now)
+ {
+ if(!tpold || tpold->wakeup>tp->wakeup)
+ tpold = tp;
+ }
+ else
+ {
+ if(!tpmin || tpmin->wakeup>tp->wakeup)
+ tpmin=tp;
+ }
+ tplast = tp;
+ }
+ else
+ {
+ if(tplast)
+ tplast->next = tp->next;
+ else
+ tptop = tp->next;
+ tp->next = tpfree;
+ tpfree = tp;
+ }
+ }
+ if((tp=tpold) && tp->incr)
+ {
+ while((tp->wakeup += tp->incr) <= now);
+ if(!tpmin || tpmin->wakeup>tp->wakeup)
+ tpmin=tp;
+ }
+ if(tpmin && (left==0 || (tp && tpmin->wakeup < (now+left))))
+ {
+ if(left==0)
+ signal(SIGALRM,sigalrm);
+ left = setalarm(tpmin->wakeup-now);
+ if(left && (now+left) < tpmin->wakeup)
+ setalarm(left);
+ else
+ left=tpmin->wakeup-now;
+ }
+ if(tp)
+ {
+ void (*action)(void*);
+ action = tp->action;
+ if(!tp->incr)
+ tp->action = 0;
+ errno = EINTR;
+ time_state &= ~IN_SIGALRM;
+ (*action)(tp->handle);
+ time_state |= IN_SIGALRM;
+ }
+ else
+ break;
+ }
+ if(!tpmin)
+ signal(SIGALRM,(sh.sigflag[SIGALRM]&SH_SIGFAULT)?sh_fault:SIG_DFL);
+ time_state &= ~IN_SIGALRM;
+ errno = EINTR;
+}
+
+static void oldalrm(void *handle)
+{
+ Handler_t fn = *(Handler_t*)handle;
+ free(handle);
+ (*fn)(SIGALRM);
+}
+
+void *sh_timeradd(unsigned long msec,int flags,void (*action)(void*),void *handle)
+{
+ register Timer_t *tp;
+ double t;
+ Handler_t fn;
+ t = ((double)msec)/1000.;
+ if(t<=0 || !action)
+ return((void*)0);
+ if(tp=tpfree)
+ tpfree = tp->next;
+ else if(!(tp=(Timer_t*)malloc(sizeof(Timer_t))))
+ return((void*)0);
+ tp->wakeup = getnow() + t;
+ tp->incr = (flags?t:0);
+ tp->action = action;
+ tp->handle = handle;
+ time_state |= IN_ADDTIMEOUT;
+ tp->next = tptop;
+ tptop = tp;
+ if(!tpmin || tp->wakeup < tpmin->wakeup)
+ {
+ tpmin = tp;
+ fn = (Handler_t)signal(SIGALRM,sigalrm);
+ if((t= setalarm(t))>0 && fn && fn!=(Handler_t)sigalrm)
+ {
+ Handler_t *hp = (Handler_t*)malloc(sizeof(Handler_t));
+ if(hp)
+ {
+ *hp = fn;
+ sh_timeradd((long)(1000*t), 0, oldalrm, (void*)hp);
+ }
+ }
+ tp = tptop;
+ }
+ else if(tpmin && !tpmin->action)
+ time_state |= DEFER_SIGALRM;
+ time_state &= ~IN_ADDTIMEOUT;
+ if(time_state&DEFER_SIGALRM)
+ {
+ time_state=SIGALRM_CALL;
+ sigalrm(SIGALRM);
+ if(tp!=tptop)
+ tp=0;
+ }
+ return((void*)tp);
+}
+
+/*
+ * delete timer <tp>. If <tp> is NULL, all timers are deleted
+ */
+void timerdel(void *handle)
+{
+ register Timer_t *tp = (Timer_t*)handle;
+ if(tp)
+ tp->action = 0;
+ else
+ {
+ for(tp=tptop; tp; tp=tp->next)
+ tp->action = 0;
+ if(tpmin)
+ {
+ tpmin = 0;
+ setalarm((double)0);
+ }
+ signal(SIGALRM,(sh.sigflag[SIGALRM]&SH_SIGFAULT)?sh_fault:SIG_DFL);
+ }
+}
+
diff --git a/src/cmd/ksh93/sh/trestore.c b/src/cmd/ksh93/sh/trestore.c
new file mode 100644
index 0000000..c209b73
--- /dev/null
+++ b/src/cmd/ksh93/sh/trestore.c
@@ -0,0 +1,353 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * shell intermediate code reader
+ *
+ */
+
+#include "defs.h"
+#include "shnodes.h"
+#include "path.h"
+#include "io.h"
+#include <ccode.h>
+
+static struct dolnod *r_comlist(Shell_t*);
+static struct argnod *r_arg(Shell_t*);
+static struct ionod *r_redirect(Shell_t*);
+static struct regnod *r_switch(Shell_t*);
+static Shnode_t *r_tree(Shell_t*);
+static char *r_string(Stk_t*);
+static void r_comarg(Shell_t*,struct comnod*);
+
+static Sfio_t *infile;
+
+#define getnode(s,type) ((Shnode_t*)stkalloc((s),sizeof(struct type)))
+
+Shnode_t *sh_trestore(Shell_t *shp,Sfio_t *in)
+{
+ Shnode_t *t;
+ infile = in;
+ t = r_tree(shp);
+ return(t);
+}
+/*
+ * read in a shell tree
+ */
+static Shnode_t *r_tree(Shell_t *shp)
+{
+ long l = sfgetl(infile);
+ register int type;
+ register Shnode_t *t=0;
+ if(l<0)
+ return(t);
+ type = l;
+ switch(type&COMMSK)
+ {
+ case TTIME:
+ case TPAR:
+ t = getnode(shp->stk,parnod);
+ t->par.partre = r_tree(shp);
+ break;
+ case TCOM:
+ t = getnode(shp->stk,comnod);
+ t->tre.tretyp = type;
+ r_comarg(shp,(struct comnod*)t);
+ break;
+ case TSETIO:
+ case TFORK:
+ t = getnode(shp->stk,forknod);
+ t->fork.forkline = sfgetu(infile);
+ t->fork.forktre = r_tree(shp);
+ t->fork.forkio = r_redirect(shp);
+ break;
+ case TIF:
+ t = getnode(shp->stk,ifnod);
+ t->if_.iftre = r_tree(shp);
+ t->if_.thtre = r_tree(shp);
+ t->if_.eltre = r_tree(shp);
+ break;
+ case TWH:
+ t = getnode(shp->stk,whnod);
+ t->wh.whinc = (struct arithnod*)r_tree(shp);
+ t->wh.whtre = r_tree(shp);
+ t->wh.dotre = r_tree(shp);
+ break;
+ case TLST:
+ case TAND:
+ case TORF:
+ case TFIL:
+ t = getnode(shp->stk,lstnod);
+ t->lst.lstlef = r_tree(shp);
+ t->lst.lstrit = r_tree(shp);
+ break;
+ case TARITH:
+ t = getnode(shp->stk,arithnod);
+ t->ar.arline = sfgetu(infile);
+ t->ar.arexpr = r_arg(shp);
+ t->ar.arcomp = 0;
+ if((t->ar.arexpr)->argflag&ARG_RAW)
+ t->ar.arcomp = sh_arithcomp(shp,(t->ar.arexpr)->argval);
+ break;
+ case TFOR:
+ t = getnode(shp->stk,fornod);
+ t->for_.forline = 0;
+ if(type&FLINENO)
+ t->for_.forline = sfgetu(infile);
+ t->for_.fortre = r_tree(shp);
+ t->for_.fornam = r_string(shp->stk);
+ t->for_.forlst = (struct comnod*)r_tree(shp);
+ break;
+ case TSW:
+ t = getnode(shp->stk,swnod);
+ t->sw.swline = 0;
+ if(type&FLINENO)
+ t->sw.swline = sfgetu(infile);
+ t->sw.swarg = r_arg(shp);
+ if(type&COMSCAN)
+ t->sw.swio = r_redirect(shp);
+ else
+ t->sw.swio = 0;
+ t->sw.swlst = r_switch(shp);
+ break;
+ case TFUN:
+ {
+ Stak_t *savstak;
+ struct slnod *slp;
+ struct functnod *fp;
+ t = getnode(shp->stk,functnod);
+ t->funct.functloc = -1;
+ t->funct.functline = sfgetu(infile);
+ t->funct.functnam = r_string(shp->stk);
+ savstak = stakcreate(STAK_SMALL);
+ savstak = stakinstall(savstak, 0);
+ slp = (struct slnod*)stkalloc(shp->stk,sizeof(struct slnod)+sizeof(struct functnod));
+ slp->slchild = 0;
+ slp->slnext = shp->st.staklist;
+ shp->st.staklist = 0;
+ fp = (struct functnod*)(slp+1);
+ memset(fp, 0, sizeof(*fp));
+ fp->functtyp = TFUN|FAMP;
+ if(shp->st.filename)
+ fp->functnam = stkcopy(shp->stk,shp->st.filename);
+ t->funct.functtre = r_tree(shp);
+ t->funct.functstak = slp;
+ t->funct.functargs = (struct comnod*)r_tree(shp);
+ slp->slptr = stakinstall(savstak,0);
+ slp->slchild = shp->st.staklist;
+ break;
+ }
+ case TTST:
+ t = getnode(shp->stk,tstnod);
+ t->tst.tstline = sfgetu(infile);
+ if((type&TPAREN)==TPAREN)
+ t->lst.lstlef = r_tree(shp);
+ else
+ {
+ t->lst.lstlef = (Shnode_t*)r_arg(shp);
+ if((type&TBINARY))
+ t->lst.lstrit = (Shnode_t*)r_arg(shp);
+ }
+ }
+ if(t)
+ t->tre.tretyp = type;
+ return(t);
+}
+
+static struct argnod *r_arg(Shell_t *shp)
+{
+ register struct argnod *ap=0, *apold, *aptop=0;
+ register long l;
+ Stk_t *stkp=shp->stk;
+ while((l=sfgetu(infile))>0)
+ {
+ ap = (struct argnod*)stkseek(stkp,(unsigned)l+ARGVAL);
+ if(!aptop)
+ aptop = ap;
+ else
+ apold->argnxt.ap = ap;
+ if(--l > 0)
+ {
+ sfread(infile,ap->argval,(size_t)l);
+ ccmaps(ap->argval, l, CC_ASCII, CC_NATIVE);
+ }
+ ap->argval[l] = 0;
+ ap->argchn.cp = 0;
+ ap->argflag = sfgetc(infile);
+#if 0
+ if((ap->argflag&ARG_MESSAGE) && *ap->argval)
+ {
+ /* replace international messages */
+ sh_endword(shp,1);
+ ap->argflag &= ~ARG_MESSAGE;
+ if(!(ap->argflag&(ARG_MAC|ARG_EXP)))
+ ap = sh_endword(shp,0);
+ else
+ {
+ ap = (struct argnod*)stkfreeze(stkp,0);
+ if(ap->argflag==0)
+ ap->argflag = ARG_RAW;
+ }
+ }
+ else
+#endif
+ ap = (struct argnod*)stkfreeze(stkp,0);
+ if(*ap->argval==0 && (ap->argflag&ARG_EXP))
+ ap->argchn.ap = (struct argnod*)r_tree(shp);
+ else if(*ap->argval==0 && (ap->argflag&~(ARG_APPEND|ARG_MESSAGE|ARG_QUOTED))==0)
+ {
+ struct fornod *fp = (struct fornod*)getnode(shp->stk,fornod);
+ fp->fortyp = sfgetu(infile);
+ fp->fortre = r_tree(shp);
+ fp->fornam = ap->argval+1;
+ ap->argchn.ap = (struct argnod*)fp;
+ }
+ apold = ap;
+ }
+ if(ap)
+ ap->argnxt.ap = 0;
+ return(aptop);
+}
+
+static struct ionod *r_redirect(Shell_t* shp)
+{
+ register long l;
+ register struct ionod *iop=0, *iopold, *ioptop=0;
+ while((l=sfgetl(infile))>=0)
+ {
+ iop = (struct ionod*)getnode(shp->stk,ionod);
+ if(!ioptop)
+ ioptop = iop;
+ else
+ iopold->ionxt = iop;
+ iop->iofile = l;
+ iop->ioname = r_string(shp->stk);
+ if(iop->iodelim = r_string(shp->stk))
+ {
+ iop->iosize = sfgetl(infile);
+ if(shp->heredocs)
+ iop->iooffset = sfseek(shp->heredocs,(off_t)0,SEEK_END);
+ else
+ {
+ shp->heredocs = sftmp(512);
+ iop->iooffset = 0;
+ }
+ sfmove(infile,shp->heredocs, iop->iosize, -1);
+ }
+ iopold = iop;
+ if(iop->iofile&IOVNM)
+ iop->iovname = r_string(shp->stk);
+ else
+ iop->iovname = 0;
+ iop->iofile &= ~IOVNM;
+ }
+ if(iop)
+ iop->ionxt = 0;
+ return(ioptop);
+}
+
+static void r_comarg(Shell_t *shp,struct comnod *com)
+{
+ char *cmdname=0;
+ com->comio = r_redirect(shp);
+ com->comset = r_arg(shp);
+ com->comstate = 0;
+ if(com->comtyp&COMSCAN)
+ {
+ com->comarg = r_arg(shp);
+ if(com->comarg->argflag==ARG_RAW)
+ cmdname = com->comarg->argval;
+ }
+ else if(com->comarg = (struct argnod*)r_comlist(shp))
+ cmdname = ((struct dolnod*)(com->comarg))->dolval[ARG_SPARE];
+ com->comline = sfgetu(infile);
+ com->comnamq = 0;
+ if(cmdname)
+ {
+ char *cp;
+ com->comnamp = (void*)nv_search(cmdname,shp->fun_tree,0);
+ if(com->comnamp && (cp =strrchr(cmdname+1,'.')))
+ {
+ *cp = 0;
+ com->comnamp = (void*)nv_open(cmdname,shp->var_tree,NV_VARNAME|NV_NOADD|NV_NOARRAY);
+ *cp = '.';
+ }
+ }
+ else
+ com->comnamp = 0;
+}
+
+static struct dolnod *r_comlist(Shell_t *shp)
+{
+ register struct dolnod *dol=0;
+ register long l;
+ register char **argv;
+ if((l=sfgetl(infile))>0)
+ {
+ dol = (struct dolnod*)stkalloc(shp->stk,sizeof(struct dolnod) + sizeof(char*)*(l+ARG_SPARE));
+ dol->dolnum = l;
+ dol->dolbot = ARG_SPARE;
+ argv = dol->dolval+ARG_SPARE;
+ while(*argv++ = r_string(shp->stk));
+ }
+ return(dol);
+}
+
+static struct regnod *r_switch(Shell_t *shp)
+{
+ register long l;
+ struct regnod *reg=0,*regold,*regtop=0;
+ while((l=sfgetl(infile))>=0)
+ {
+ reg = (struct regnod*)getnode(shp->stk,regnod);
+ if(!regtop)
+ regtop = reg;
+ else
+ regold->regnxt = reg;
+ reg->regflag = l;
+ reg->regptr = r_arg(shp);
+ reg->regcom = r_tree(shp);
+ regold = reg;
+ }
+ if(reg)
+ reg->regnxt = 0;
+ return(regtop);
+}
+
+static char *r_string(Stk_t *stkp)
+{
+ register Sfio_t *in = infile;
+ register unsigned long l = sfgetu(in);
+ register char *ptr;
+ if(l == 0)
+ return(NIL(char*));
+ ptr = stkalloc(stkp,(unsigned)l);
+ if(--l > 0)
+ {
+ if(sfread(in,ptr,(size_t)l)!=(size_t)l)
+ return(NIL(char*));
+ ccmaps(ptr, l, CC_ASCII, CC_NATIVE);
+ }
+ ptr[l] = 0;
+ return(ptr);
+}
diff --git a/src/cmd/ksh93/sh/waitevent.c b/src/cmd/ksh93/sh/waitevent.c
new file mode 100644
index 0000000..e868116
--- /dev/null
+++ b/src/cmd/ksh93/sh/waitevent.c
@@ -0,0 +1,54 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "defs.h"
+/*
+ * This installs a hook to allow the processing of events when
+ * the shell is waiting for input and when the shell is
+ * waiting for job completion.
+ * The previous waitevent hook function is returned
+ */
+
+
+void *sh_waitnotify(int(*newevent)(int,long,int))
+{
+ int (*old)(int,long,int);
+ old = shgd->waitevent;
+ shgd->waitevent = newevent;
+ return((void*)old);
+}
+
+#if __OBSOLETE__ < 20080101
+/*
+ * this used to be a private symbol
+ * retain the old name for a bit for a smooth transition
+ */
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern void *_sh_waitnotify(int(*newevent)(int,long,int))
+{
+ return sh_waitnotify(newevent);
+}
+
+#endif
diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c
new file mode 100644
index 0000000..28ad1e1
--- /dev/null
+++ b/src/cmd/ksh93/sh/xec.c
@@ -0,0 +1,3991 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * UNIX shell parse tree executer
+ *
+ * David Korn
+ * AT&T Labs
+ *
+ */
+
+#include "defs.h"
+#include <fcin.h>
+#include "variables.h"
+#include "path.h"
+#include "name.h"
+#include "io.h"
+#include "shnodes.h"
+#include "jobs.h"
+#include "test.h"
+#include "builtins.h"
+#include "FEATURE/time"
+#include "FEATURE/externs"
+#include "FEATURE/locale"
+#include "streval.h"
+
+#if !_std_malloc
+# include <vmalloc.h>
+#endif
+
+#if _lib_vfork
+# include <ast_vfork.h>
+#else
+# define vfork() fork()
+#endif
+
+#define SH_NTFORK SH_TIMING
+#define NV_BLTPFSH NV_ARRAY
+
+#if _lib_nice
+ extern int nice(int);
+#endif /* _lib_nice */
+#if !_lib_spawnveg
+# define spawnveg(a,b,c,d) spawnve(a,b,c)
+#endif /* !_lib_spawnveg */
+#if SHOPT_SPAWN
+ static pid_t sh_ntfork(Shell_t*,const Shnode_t*,char*[],int*,int);
+#endif /* SHOPT_SPAWN */
+
+static void sh_funct(Shell_t *,Namval_t*, int, char*[], struct argnod*,int);
+static int trim_eq(const char*, const char*);
+static void coproc_init(Shell_t*, int pipes[]);
+
+static void *timeout;
+static char pipejob;
+static char nopost;
+static int restorefd;
+
+struct funenv
+{
+ Namval_t *node;
+ struct argnod *env;
+ Namval_t **nref;
+};
+
+/* ======== command execution ========*/
+
+#if !SHOPT_DEVFD
+ static void fifo_check(void *handle)
+ {
+ Shell_t *shp = (Shell_t*)handle;
+ pid_t pid = getppid();
+ if(pid==1)
+ {
+ unlink(shp->fifo);
+ sh_done(shp,0);
+ }
+ }
+#endif /* !SHOPT_DEVFD */
+
+/*
+ * The following two functions allow command substituion for non-builtins
+ * to use a pipe and to wait for the pipe to close before restoring to a
+ * temp file.
+ */
+static int subpipe[3] = {-1};
+static int subdup,tsetio,usepipe;
+static void iousepipe(Shell_t *shp)
+{
+ int i;
+ usepipe++;
+ fcntl(subpipe[0],F_SETFD,FD_CLOEXEC);
+ subpipe[2] = fcntl(1,F_DUPFD,10);
+ fcntl(subpipe[2],F_SETFD,FD_CLOEXEC);
+ shp->fdstatus[subpipe[2]] = shp->fdstatus[1];
+ close(1);
+ fcntl(subpipe[1],F_DUPFD,1);
+ shp->fdstatus[1] = shp->fdstatus[subpipe[1]];
+ sh_close(subpipe[1]);
+ if(subdup=shp->subdup) for(i=0; i < 10; i++)
+ {
+ if(subdup&(1<<i))
+ {
+ sh_close(i);
+ fcntl(1,F_DUPFD,i);
+ shp->fdstatus[i] = shp->fdstatus[1];
+ }
+ }
+}
+
+static void iounpipe(Shell_t *shp)
+{
+ int n;
+ char buff[SF_BUFSIZE];
+ usepipe = 0;
+ close(1);
+ fcntl(subpipe[2], F_DUPFD, 1);
+ shp->fdstatus[1] = shp->fdstatus[subpipe[2]];
+ if(subdup) for(n=0; n < 10; n++)
+ {
+ if(subdup&(1<<n))
+ {
+ sh_close(n);
+ fcntl(1, F_DUPFD, n);
+ shp->fdstatus[n] = shp->fdstatus[1];
+ }
+ }
+ shp->subdup = 0;
+ sh_close(subpipe[2]);
+ while((n = read(subpipe[0],buff,sizeof(buff)))!=0)
+ {
+ if(n>0)
+ sfwrite(sfstdout,buff,n);
+ else if(errno!=EINTR)
+ break;
+ }
+ sh_close(subpipe[0]);
+ subpipe[0] = -1;
+ tsetio = 0;
+}
+
+/*
+ * print time <t> in h:m:s format with precision <p>
+ */
+static void l_time(Sfio_t *outfile,register clock_t t,int p)
+{
+ register int min, sec, frac;
+ register int hr;
+ if(p)
+ {
+ frac = t%shgd->lim.clk_tck;
+ frac = (frac*100)/shgd->lim.clk_tck;
+ }
+ t /= shgd->lim.clk_tck;
+ sec = t%60;
+ t /= 60;
+ min = t%60;
+ if(hr=t/60)
+ sfprintf(outfile,"%dh",hr);
+ if(p)
+ sfprintf(outfile,"%dm%d%c%0*ds",min,sec,GETDECIMAL(0),p,frac);
+ else
+ sfprintf(outfile,"%dm%ds",min,sec);
+}
+
+static int p_time(Shell_t *shp, Sfio_t *out, const char *format, clock_t *tm)
+{
+ int c,p,l,n,offset = staktell();
+ const char *first;
+ double d;
+ Stk_t *stkp = shp->stk;
+ for(first=format ; c= *format; format++)
+ {
+ if(c!='%')
+ continue;
+ sfwrite(stkp, first, format-first);
+ n = l = 0;
+ p = 3;
+ if((c= *++format) == '%')
+ {
+ first = format;
+ continue;
+ }
+ if(c>='0' && c <='9')
+ {
+ p = (c>'3')?3:(c-'0');
+ c = *++format;
+ }
+ else if(c=='P')
+ {
+ if(d=tm[0])
+ d = 100.*(((double)(tm[1]+tm[2]))/d);
+ p = 2;
+ goto skip;
+ }
+ if(c=='l')
+ {
+ l = 1;
+ c = *++format;
+ }
+ if(c=='U')
+ n = 1;
+ else if(c=='S')
+ n = 2;
+ else if(c!='R')
+ {
+ stkseek(stkp,offset);
+ errormsg(SH_DICT,ERROR_exit(0),e_badtformat,c);
+ return(0);
+ }
+ d = (double)tm[n]/shp->gd->lim.clk_tck;
+ skip:
+ if(l)
+ l_time(stkp, tm[n], p);
+ else
+ sfprintf(stkp,"%.*f",p, d);
+ first = format+1;
+ }
+ if(format>first)
+ sfwrite(stkp,first, format-first);
+ sfputc(stkp,'\n');
+ n = stktell(stkp)-offset;
+ sfwrite(out,stkptr(stkp,offset),n);
+ stkseek(stkp,offset);
+ return(n);
+}
+
+#if SHOPT_OPTIMIZE
+/*
+ * clear argument pointers that point into the stack
+ */
+static int p_arg(struct argnod*,int);
+static int p_switch(struct regnod*);
+static int p_comarg(register struct comnod *com)
+{
+ Namval_t *np=com->comnamp;
+ int n = p_arg(com->comset,ARG_ASSIGN);
+ if(com->comarg && (com->comtyp&COMSCAN))
+ n+= p_arg(com->comarg,0);
+ if(com->comstate && np)
+ {
+ /* call builtin to cleanup state */
+ Shbltin_t *bp = &sh.bltindata;
+ void *save_ptr = bp->ptr;
+ void *save_data = bp->data;
+ bp->bnode = np;
+ bp->vnode = com->comnamq;
+ bp->ptr = nv_context(np);
+ bp->data = com->comstate;
+ bp->flags = SH_END_OPTIM;
+ ((Shbltin_f)funptr(np))(0,(char**)0, bp);
+ bp->ptr = save_ptr;
+ bp->data = save_data;
+ }
+ com->comstate = 0;
+ if(com->comarg && !np)
+ n++;
+ return(n);
+}
+
+extern void sh_optclear(Shell_t*, void*);
+
+static int sh_tclear(register Shnode_t *t)
+{
+ int n=0;
+ if(!t)
+ return(0);
+ switch(t->tre.tretyp&COMMSK)
+ {
+ case TTIME:
+ case TPAR:
+ return(sh_tclear(t->par.partre));
+ case TCOM:
+ return(p_comarg((struct comnod*)t));
+ case TSETIO:
+ case TFORK:
+ return(sh_tclear(t->fork.forktre));
+ case TIF:
+ n=sh_tclear(t->if_.iftre);
+ n+=sh_tclear(t->if_.thtre);
+ n+=sh_tclear(t->if_.eltre);
+ return(n);
+ case TWH:
+ if(t->wh.whinc)
+ n=sh_tclear((Shnode_t*)(t->wh.whinc));
+ n+=sh_tclear(t->wh.whtre);
+ n+=sh_tclear(t->wh.dotre);
+ return(n);
+ case TLST:
+ case TAND:
+ case TORF:
+ case TFIL:
+ n=sh_tclear(t->lst.lstlef);
+ return(n+sh_tclear(t->lst.lstrit));
+ case TARITH:
+ return(p_arg(t->ar.arexpr,ARG_ARITH));
+ case TFOR:
+ n=sh_tclear(t->for_.fortre);
+ return(n+sh_tclear((Shnode_t*)t->for_.forlst));
+ case TSW:
+ n=p_arg(t->sw.swarg,0);
+ return(n+p_switch(t->sw.swlst));
+ case TFUN:
+ n=sh_tclear(t->funct.functtre);
+ return(n+sh_tclear((Shnode_t*)t->funct.functargs));
+ case TTST:
+ if((t->tre.tretyp&TPAREN)==TPAREN)
+ return(sh_tclear(t->lst.lstlef));
+ else
+ {
+ n=p_arg(&(t->lst.lstlef->arg),0);
+ if(t->tre.tretyp&TBINARY)
+ n+=p_arg(&(t->lst.lstrit->arg),0);
+ }
+ }
+ return(n);
+}
+
+static int p_arg(register struct argnod *arg,int flag)
+{
+ while(arg)
+ {
+ if(strlen(arg->argval) || (arg->argflag==ARG_RAW))
+ arg->argchn.ap = 0;
+ else if(flag==0)
+ sh_tclear((Shnode_t*)arg->argchn.ap);
+ else
+ sh_tclear(((struct fornod*)arg->argchn.ap)->fortre);
+ arg = arg->argnxt.ap;
+ }
+ return(0);
+}
+
+static int p_switch(register struct regnod *reg)
+{
+ int n=0;
+ while(reg)
+ {
+ n+=p_arg(reg->regptr,0);
+ n+=sh_tclear(reg->regcom);
+ reg = reg->regnxt;
+ }
+ return(n);
+}
+# define OPTIMIZE_FLAG (ARG_OPTIMIZE)
+# define OPTIMIZE (flags&OPTIMIZE_FLAG)
+#else
+# define OPTIMIZE_FLAG (0)
+# define OPTIMIZE (0)
+# define sh_tclear(x)
+#endif /* SHOPT_OPTIMIZE */
+
+static void out_pattern(Sfio_t *iop, register const char *cp, int n)
+{
+ register int c;
+ do
+ {
+ switch(c= *cp)
+ {
+ case 0:
+ if(n<0)
+ return;
+ c = n;
+ break;
+ case '\n':
+ sfputr(iop,"$'\\n",'\'');
+ continue;
+ case '\\':
+ if (!(c = *++cp))
+ c = '\\';
+ /*FALLTHROUGH*/
+ case ' ':
+ case '<': case '>': case ';':
+ case '$': case '`': case '\t':
+ sfputc(iop,'\\');
+ break;
+ }
+ sfputc(iop,c);
+ }
+ while(*cp++);
+}
+
+static void out_string(Sfio_t *iop, register const char *cp, int c, int quoted)
+{
+ if(quoted)
+ {
+ int n = stktell(stkstd);
+ cp = sh_fmtq(cp);
+ if(iop==stkstd && cp==stkptr(stkstd,n))
+ {
+ *stkptr(stkstd,stktell(stkstd)-1) = c;
+ return;
+ }
+ }
+ sfputr(iop,cp,c);
+}
+
+struct Level
+{
+ Namfun_t hdr;
+ short maxlevel;
+};
+
+/*
+ * this is for a debugger but it hasn't been tested yet
+ * if a debug script sets .sh.level it should set up the scope
+ * as if you were executing in that level
+ */
+static void put_level(Namval_t* np,const char *val,int flags,Namfun_t *fp)
+{
+ Shscope_t *sp;
+ struct Level *lp = (struct Level*)fp;
+ int16_t level, oldlevel = (int16_t)nv_getnum(np);
+ nv_putv(np,val,flags,fp);
+ if(!val)
+ {
+ fp = nv_stack(np, NIL(Namfun_t*));
+ if(fp && !fp->nofree)
+ free((void*)fp);
+ return;
+ }
+ level = nv_getnum(np);
+ if(level<0 || level > lp->maxlevel)
+ {
+ nv_putv(np, (char*)&oldlevel, NV_INT16, fp);
+ /* perhaps this should be an error */
+ return;
+ }
+ if(level==oldlevel)
+ return;
+ if(sp = sh_getscope(level,SEEK_SET))
+ {
+ sh_setscope(sp);
+ error_info.id = sp->cmdname;
+
+ }
+}
+
+static const Namdisc_t level_disc = { sizeof(struct Level), put_level };
+
+static struct Level *init_level(Shell_t *shp,int level)
+{
+ struct Level *lp = newof(NiL,struct Level,1,0);
+ lp->maxlevel = level;
+ _nv_unset(SH_LEVELNOD,0);
+ nv_onattr(SH_LEVELNOD,NV_INT16|NV_NOFREE);
+ shp->last_root = nv_dict(DOTSHNOD);
+ nv_putval(SH_LEVELNOD,(char*)&lp->maxlevel,NV_INT16);
+ lp->hdr.disc = &level_disc;
+ nv_disc(SH_LEVELNOD,&lp->hdr,NV_FIRST);
+ return(lp);
+}
+
+/*
+ * write the current command on the stack and make it available as .sh.command
+ */
+int sh_debug(Shell_t *shp, const char *trap, const char *name, const char *subscript, char *const argv[], int flags)
+{
+ Stk_t *stkp=shp->stk;
+ struct sh_scoped savst;
+ Namval_t *np = SH_COMMANDNOD;
+ char *sav = stkptr(stkp,0);
+ int n=4, offset=stktell(stkp);
+ const char *cp = "+=( ";
+ Sfio_t *iop = stkstd;
+ short level;
+ if(shp->indebug)
+ return(0);
+ shp->indebug = 1;
+ if(name)
+ {
+ sfputr(iop,name,-1);
+ if(subscript)
+ {
+ sfputc(iop,'[');
+ out_string(iop,subscript,']',1);
+ }
+ if(!(flags&ARG_APPEND))
+ cp+=1, n-=1;
+ if(!(flags&ARG_ASSIGN))
+ n -= 2;
+ sfwrite(iop,cp,n);
+ }
+ if(*argv && !(flags&ARG_RAW))
+ out_string(iop, *argv++,' ', 0);
+ n = (flags&ARG_ARITH);
+ while(cp = *argv++)
+ {
+ if((flags&ARG_EXP) && argv[1]==0)
+ out_pattern(iop, cp,' ');
+ else
+ out_string(iop, cp,' ',n?0: (flags&(ARG_RAW|ARG_NOGLOB))||*argv);
+ }
+ if(flags&ARG_ASSIGN)
+ sfputc(iop,')');
+ else if(iop==stkstd)
+ *stkptr(stkp,stktell(stkp)-1) = 0;
+ np->nvalue.cp = stkfreeze(stkp,1);
+ /* now setup .sh.level variable */
+ shp->st.lineno = error_info.line;
+ level = shp->fn_depth+shp->dot_depth;
+ shp->last_root = nv_dict(DOTSHNOD);
+ if(!SH_LEVELNOD->nvfun || !SH_LEVELNOD->nvfun->disc || nv_isattr(SH_LEVELNOD,NV_INT16|NV_NOFREE)!=(NV_INT16|NV_NOFREE))
+ init_level(shp,level);
+ else
+ nv_putval(SH_LEVELNOD,(char*)&level,NV_INT16);
+ savst = shp->st;
+ shp->st.trap[SH_DEBUGTRAP] = 0;
+ n = sh_trap(trap,0);
+ np->nvalue.cp = 0;
+ shp->indebug = 0;
+ if(shp->st.cmdname)
+ error_info.id = shp->st.cmdname;
+ nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
+ nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
+ shp->st = savst;
+ if(sav != stkptr(stkp,0))
+ stkset(stkp,sav,0);
+ else
+ stkseek(stkp,offset);
+ return(n);
+}
+
+/*
+ * Given stream <iop> compile and execute
+ */
+int sh_eval(register Sfio_t *iop, int mode)
+{
+ register Shnode_t *t;
+ Shell_t *shp = sh_getinterp();
+ struct slnod *saveslp = shp->st.staklist;
+ int jmpval;
+ struct checkpt *pp = (struct checkpt*)shp->jmplist;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ static Sfio_t *io_save;
+ volatile int traceon=0, lineno=0;
+ int binscript=shp->binscript;
+ char comsub = shp->comsub;
+ io_save = iop; /* preserve correct value across longjmp */
+ shp->binscript = 0;
+ shp->comsub = 0;
+#define SH_TOPFUN 0x8000 /* this is a temporary tksh hack */
+ if (mode & SH_TOPFUN)
+ {
+ mode ^= SH_TOPFUN;
+ shp->fn_reset = 1;
+ }
+ sh_pushcontext(shp,buffp,SH_JMPEVAL);
+ buffp->olist = pp->olist;
+ jmpval = sigsetjmp(buffp->buff,0);
+ while(jmpval==0)
+ {
+ if(mode&SH_READEVAL)
+ {
+ lineno = shp->inlineno;
+ if(traceon=sh_isoption(SH_XTRACE))
+ sh_offoption(SH_XTRACE);
+ }
+ t = (Shnode_t*)sh_parse(shp,iop,(mode&(SH_READEVAL|SH_FUNEVAL))?mode&SH_FUNEVAL:SH_NL);
+ if(!(mode&SH_FUNEVAL) || !sfreserve(iop,0,0))
+ {
+ if(!(mode&SH_READEVAL))
+ sfclose(iop);
+ io_save = 0;
+ mode &= ~SH_FUNEVAL;
+ }
+ mode &= ~SH_READEVAL;
+ if(!sh_isoption(SH_VERBOSE))
+ sh_offstate(SH_VERBOSE);
+ if((mode&~SH_FUNEVAL) && shp->gd->hist_ptr)
+ {
+ hist_flush(shp->gd->hist_ptr);
+ mode = sh_state(SH_INTERACTIVE);
+ }
+ sh_exec(t,sh_isstate(SH_ERREXIT)|sh_isstate(SH_NOFORK)|(mode&~SH_FUNEVAL));
+ if(!(mode&SH_FUNEVAL))
+ break;
+ }
+ sh_popcontext(shp,buffp);
+ shp->binscript = binscript;
+ shp->comsub = comsub;
+ if(traceon)
+ sh_onoption(SH_XTRACE);
+ if(lineno)
+ shp->inlineno = lineno;
+ if(io_save)
+ sfclose(io_save);
+ sh_freeup(shp);
+ shp->st.staklist = saveslp;
+ shp->fn_reset = 0;
+ if(jmpval>SH_JMPEVAL)
+ siglongjmp(*shp->jmplist,jmpval);
+ return(shp->exitval);
+}
+
+/*
+ * returns 1 when option -<c> is specified
+ */
+static int checkopt(char *argv[], int c)
+{
+ char *cp;
+ while(cp = *++argv)
+ {
+ if(*cp=='+')
+ continue;
+ if(*cp!='-' || cp[1]=='-')
+ break;
+ if(strchr(++cp,c))
+ return(1);
+ if(*cp=='h' && cp[1]==0 && *++argv==0)
+ break;
+ }
+ return(0);
+}
+
+static void free_list(struct openlist *olist)
+{
+ struct openlist *item,*next;
+ for(item=olist;item;item=next)
+ {
+ next = item->next;
+ free((void*)item);
+ }
+}
+
+/*
+ * set ${.sh.name} and ${.sh.subscript}
+ * set _ to reference for ${.sh.name}[$.sh.subscript]
+ */
+static int set_instance(Shell_t *shp,Namval_t *nq, Namval_t *node, struct Namref *nr)
+{
+ char *sp=0,*cp;
+ Namarr_t *ap;
+ Namval_t *np;
+ if(!nv_isattr(nq,NV_MINIMAL|NV_EXPORT|NV_ARRAY) && (np=(Namval_t*)nq->nvenv) && nv_isarray(np))
+ nq = np;
+ cp = nv_name(nq);
+ memset(nr,0,sizeof(*nr));
+ nr->np = nq;
+ nr->root = shp->var_tree;
+ nr->table = shp->last_table;
+#if SHOPT_NAMESPACE
+ if(!nr->table && shp->namespace)
+ nr->table = shp->namespace;
+#endif /* SHOPT_NAMESPACE */
+ shp->instance = 1;
+ if((ap=nv_arrayptr(nq)) && (sp = nv_getsub(nq)))
+ sp = strdup(sp);
+ shp->instance = 0;
+ if(shp->var_tree!=shp->var_base && !nv_search((char*)nq,nr->root,HASH_BUCKET|HASH_NOSCOPE))
+ {
+#if SHOPT_NAMESPACE
+ nr->root = shp->namespace?nv_dict(shp->namespace):shp->var_base;
+#else
+ nr->root = shp->var_base;
+#endif /* SHOPT_NAMESPACE */
+ }
+ nv_putval(SH_NAMENOD, cp, NV_NOFREE);
+ memcpy(node,L_ARGNOD,sizeof(*node));
+ L_ARGNOD->nvalue.nrp = nr;
+ L_ARGNOD->nvflag = NV_REF|NV_NOFREE;
+ L_ARGNOD->nvfun = 0;
+ L_ARGNOD->nvenv = 0;
+ if(sp)
+ {
+ nv_putval(SH_SUBSCRNOD,nr->sub=sp,NV_NOFREE);
+ return(ap->nelem&ARRAY_SCAN);
+ }
+ return(0);
+}
+
+static void unset_instance(Namval_t *nq, Namval_t *node, struct Namref *nr,long mode)
+{
+ L_ARGNOD->nvalue.nrp = node->nvalue.nrp;
+ L_ARGNOD->nvflag = node->nvflag;
+ L_ARGNOD->nvfun = node->nvfun;
+ if(nr->sub)
+ {
+ nv_putsub(nr->np, nr->sub, mode);
+ free((void*)nr->sub);
+ }
+ _nv_unset(SH_NAMENOD,0);
+ _nv_unset(SH_SUBSCRNOD,0);
+}
+
+#if SHOPT_COSHELL
+uintmax_t coused;
+/*
+ * print out function definition
+ */
+static void print_fun(register Namval_t* np, void *data)
+{
+ register char *format;
+ NOT_USED(data);
+ if(!is_afunction(np) || !np->nvalue.ip)
+ return;
+ if(nv_isattr(np,NV_FPOSIX))
+ format="%s()\n{ ";
+ else
+ format="function %s\n{ ";
+ sfprintf(sfstdout,format,nv_name(np));
+ sh_deparse(sfstdout,(Shnode_t*)(nv_funtree(np)),0);
+ sfwrite(sfstdout,"}\n",2);
+}
+
+static void *sh_coinit(Shell_t *shp,char **argv)
+{
+ struct cosh *csp = job.colist;
+ const char *name = argv?argv[0]:0;
+ int id, open=1;
+ if(!name)
+ return(0);
+ if(*name=='-')
+ {
+ name++;
+ open=0;
+ }
+ nv_open(name,shp->var_tree,NV_IDENT|NV_NOADD);
+ while(csp)
+ {
+ if(strcmp(name,csp->name)==0)
+ {
+ if(open)
+ {
+ coattr(csp->coshell,argv[1]);
+ return((void*)csp);
+ }
+ coclose(csp->coshell);
+ return(0);
+ }
+ csp = csp->next;
+ }
+ if(!open)
+ errormsg(SH_DICT,ERROR_exit(1),"%s: unknown namespace",name);
+ environ[0][2]=0;
+ csp = newof(0,struct cosh,1,strlen(name)+1);
+ if(!(csp->coshell = coopen(NULL,CO_SHELL|CO_SILENT,argv[1])))
+ {
+ free((void*)csp);
+ errormsg(SH_DICT,ERROR_exit(1),"%s: unable to create namespace",name);
+ }
+ csp->coshell->data = (void*)csp;
+ csp->name = (char*)(csp+1);
+ strcpy(csp->name,name);
+ for(id=0; coused&(1<<id); id++);
+ coused |= (1<<id);
+ csp->id = id;
+ csp->next = job.colist;
+ job.colist = csp;
+ return((void*)csp);
+}
+
+int sh_coaddfile(Shell_t *shp, char *name)
+{
+ Namval_t *np = dtmatch(shp->inpool,name);
+ if(!np)
+ {
+ np = (Namval_t*)stakalloc(sizeof(Dtlink_t)+sizeof(char*));
+ np->nvname = name;
+ (Namval_t*)dtinsert(shp->inpool,np);
+ shp->poolfiles++;
+ return(1);
+ }
+ return(0);
+}
+
+static int sh_coexec(Shell_t *shp,const Shnode_t *t, int filt)
+{
+ struct cosh *csp = ((struct cosh*)shp->coshell);
+ Cojob_t *cjp;
+ char *str,*trap,host[PATH_MAX];
+ int lineno,sig,trace = sh_isoption(SH_XTRACE);
+ int verbose = sh_isoption(SH_VERBOSE);
+ sh_offoption(SH_XTRACE);
+ sh_offoption(SH_VERBOSE);
+ if(!shp->strbuf2)
+ shp->strbuf2 = sfstropen();
+ sfswap(shp->strbuf2,sfstdout);
+ sh_trap("typeset -p\nprint cd \"$PWD\"\nprint .sh.dollar=$$\nprint umask $(umask)",0);
+ for(sig=shp->st.trapmax;--sig>0;)
+ {
+ if((trap=shp->st.trapcom[sig]) && *trap==0)
+ sfprintf(sfstdout,"trap '' %d\n",sig);
+ }
+ if(t->tre.tretyp==TFIL)
+ lineno = ((struct forknod*)t->lst.lstlef)->forkline;
+ else
+ lineno = t->fork.forkline;
+ if(filt)
+ {
+ if(gethostname(host,sizeof(host)) < 0)
+ errormsg(SH_DICT,ERROR_system(1),e_pipe);
+ if(shp->inpipe[2]>=20000)
+ sfprintf(sfstdout,"command exec < /dev/tcp/%s/%d || print -u2 'cannot create pipe'\n",host,shp->inpipe[2]);
+ sfprintf(sfstdout,"command exec > /dev/tcp/%s/%d || print -u2 'cannot create pipe'\n",host,shp->outpipe[2]);
+ if(filt==3)
+ t = t->fork.forktre;
+ }
+ else
+ t = t->fork.forktre;
+ nv_scan(shp->fun_tree, print_fun, (void*)0,0, 0);
+ if(1)
+ {
+ Dt_t *top = shp->var_tree;
+ sh_scope(shp,(struct argnod*)0,0);
+ shp->inpool = dtopen(&_Nvdisc,Dtset);
+ sh_exec(t,filt==1||filt==2?SH_NOFORK:0);
+ if(shp->poolfiles)
+ {
+ Namval_t *np;
+ sfprintf(sfstdout,"[[ ${.sh} == *pool* ]] && .sh.pool.files=(\n");
+ for(np=(Namval_t*)dtfirst(shp->inpool);np;np=(Namval_t*)dtnext(shp->inpool,np))
+ {
+ sfprintf(sfstdout,"\t%s\n",sh_fmtq(np->nvname));
+ }
+ sfputr(sfstdout,")",'\n');
+ ;
+ }
+ dtclose(shp->inpool);
+ shp->inpool = 0;
+ shp->poolfiles = 0;
+ sh_unscope(shp);
+ shp->var_tree = top;
+ }
+ sfprintf(sfstdout,"typeset -f .sh.pool.init && .sh.pool.init\n");
+ sfprintf(sfstdout,"LINENO=%d\n",lineno);
+ if(trace)
+ sh_onoption(SH_XTRACE);
+ if(verbose)
+ sh_onoption(SH_VERBOSE);
+ sh_trap("set +o",0);
+ sh_deparse(sfstdout,t,filt==1||filt==2?FALTPIPE:0);
+ sfputc(sfstdout,0);
+ sfswap(shp->strbuf2,sfstdout);
+ str = sfstruse(shp->strbuf2);
+ if(cjp=coexec(csp->coshell,str,0,NULL,NULL,NULL))
+ {
+ csp->cojob = cjp;
+ cjp->local = shp->coshell;
+ if(filt)
+ {
+ if(filt>1)
+ sh_coaccept(shp,shp->inpipe,1);
+ sh_coaccept(shp,shp->outpipe,0);
+ if(filt > 2)
+ {
+ shp->coutpipe = shp->inpipe[1];
+ shp->fdptrs[shp->coutpipe] = &shp->coutpipe;
+ }
+ }
+ return(sh_copid(csp));
+ }
+ return(-1);
+}
+#endif /*SHOPT_COSHELL*/
+
+int sh_exec(register const Shnode_t *t, int flags)
+{
+ register Shell_t *shp = sh_getinterp();
+ Stk_t *stkp = shp->stk;
+ sh_sigcheck(shp);
+ if(t && !shp->st.execbrk && !sh_isoption(SH_NOEXEC))
+ {
+ register int type = flags;
+ register char *com0 = 0;
+ int errorflg = (type&sh_state(SH_ERREXIT))|OPTIMIZE;
+ int execflg = (type&sh_state(SH_NOFORK));
+ int execflg2 = (type&sh_state(SH_FORKED));
+ int mainloop = (type&sh_state(SH_INTERACTIVE));
+#if SHOPT_AMP || SHOPT_SPAWN
+ int ntflag = (type&sh_state(SH_NTFORK));
+#else
+ int ntflag = 0;
+#endif
+ int topfd = shp->topfd;
+ char *sav=stkptr(stkp,0);
+ char *cp=0, **com=0, *comn;
+ int argn;
+ int skipexitset = 0;
+ int was_interactive = 0;
+ int was_errexit = sh_isstate(SH_ERREXIT);
+ int was_monitor = sh_isstate(SH_MONITOR);
+ int echeck = 0;
+ if(flags&sh_state(SH_INTERACTIVE))
+ {
+ if(pipejob==2)
+ job_unlock();
+ pipejob = 0;
+ job.curpgid = 0;
+ job.curjobid = 0;
+ flags &= ~sh_state(SH_INTERACTIVE);
+ }
+ sh_offstate(SH_ERREXIT);
+ sh_offstate(SH_DEFPATH);
+ if(was_errexit&flags)
+ sh_onstate(SH_ERREXIT);
+ if(was_monitor&flags)
+ sh_onstate(SH_MONITOR);
+ type = t->tre.tretyp;
+ if(!shp->intrap)
+ shp->oldexit=shp->exitval;
+ shp->exitval=0;
+ shp->lastsig = 0;
+ shp->lastpath = 0;
+ switch(type&COMMSK)
+ {
+ case TCOM:
+ {
+ register struct argnod *argp;
+ char *trap;
+ Namval_t *np, *nq, *last_table;
+ struct ionod *io;
+ int command=0, flgs=NV_ASSIGN;
+ shp->bltindata.invariant = type>>(COMBITS+2);
+ type &= (COMMSK|COMSCAN);
+ sh_stats(STAT_SCMDS);
+ error_info.line = t->com.comline-shp->st.firstline;
+ com = sh_argbuild(shp,&argn,&(t->com),OPTIMIZE);
+ echeck = 1;
+ if(t->tre.tretyp&COMSCAN)
+ {
+ argp = t->com.comarg;
+ if(argp && *com && !(argp->argflag&ARG_RAW))
+ sh_sigcheck(shp);
+ }
+ np = (Namval_t*)(t->com.comnamp);
+ nq = (Namval_t*)(t->com.comnamq);
+ com0 = com[0];
+ shp->xargexit = 0;
+ while(np==SYSCOMMAND)
+ {
+ register int n = b_command(0,com,&shp->bltindata);
+ if(n==0)
+ break;
+ command += n;
+ np = 0;
+ if(!(com0= *(com+=n)))
+ break;
+ np = nv_bfsearch(com0, shp->bltin_tree, &nq, &cp);
+ }
+ if(shp->xargexit)
+ {
+ shp->xargmin -= command;
+ shp->xargmax -= command;
+ }
+ else
+ shp->xargmin = 0;
+ argn -= command;
+#if SHOPT_COSHELL
+ if(argn && shp->inpool)
+ {
+ if(io=t->tre.treio)
+ sh_redirect(shp,io,0);
+ if(!np || !is_abuiltin(np) || *np->nvname=='/' || np==SYSCD)
+ {
+ char **argv, *cp;
+ for(argv=com+1; cp= *argv; argv++)
+ {
+ if(cp && *cp && *cp!='-')
+ sh_coaddfile(shp,*argv);
+ }
+ break;
+ }
+ if(np->nvalue.bfp!=SYSTYPESET->nvalue.bfp)
+ break;
+ }
+ if(t->tre.tretyp&FAMP)
+ {
+ shp->coshell = sh_coinit(shp,com);
+ com0 = 0;
+ break;
+ }
+#endif /* SHOPT_COSHELL */
+ if(np && is_abuiltin(np))
+ {
+ if(!command)
+ {
+ Namval_t *mp;
+#if SHOPT_NAMESPACE
+ if(shp->namespace && (mp=sh_fsearch(shp,np->nvname,0)))
+ np = mp;
+ else
+#endif /* SHOPT_NAMESPACE */
+ np = dtsearch(shp->fun_tree,np);
+ }
+#if SHOPT_PFSH
+ if(sh_isoption(SH_PFSH) && nv_isattr(np,NV_BLTINOPT) && !nv_isattr(np,NV_BLTPFSH))
+ {
+ if(path_xattr(shp,np->nvname,(char*)0))
+ {
+ dtdelete(shp->bltin_tree,np);
+ np = 0;
+ }
+ else
+ nv_onattr(np,NV_BLTPFSH);
+
+ }
+#endif /* SHOPT_PFSH */
+ }
+ if(com0)
+ {
+ if(!np && !strchr(com0,'/'))
+ {
+ Dt_t *root = command?shp->bltin_tree:shp->fun_tree;
+ np = nv_bfsearch(com0, root, &nq, &cp);
+#if SHOPT_NAMESPACE
+ if(shp->namespace && !nq && !cp)
+ np = sh_fsearch(shp,com0,0);
+#endif /* SHOPT_NAMESPACE */
+ }
+ comn = com[argn-1];
+ }
+ io = t->tre.treio;
+ if(shp->envlist = argp = t->com.comset)
+ {
+ if(argn==0 || (np && nv_isattr(np,(BLT_DCL|BLT_SPC))))
+ {
+ Namval_t *tp=0;
+ if(argn)
+ {
+ if(checkopt(com,'A'))
+ flgs |= NV_ARRAY;
+ else if(checkopt(com,'a'))
+ flgs |= NV_IARRAY;
+ }
+#if SHOPT_BASH
+ if(np==SYSLOCAL)
+ {
+ if(!nv_getval(SH_FUNNAMENOD))
+ errormsg(SH_DICT,ERROR_exit(1),"%s: can only be used in a function",com0);
+ if(!shp->st.var_local)
+ {
+ sh_scope(shp,(struct argnod*)0,0);
+ shp->st.var_local = shp->var_tree;
+ }
+
+ }
+#endif /* SHOPT_BASH */
+ if(np==SYSTYPESET || (np && np->nvalue.bfp==SYSTYPESET->nvalue.bfp))
+ {
+ if(np!=SYSTYPESET)
+ {
+ shp->typeinit = np;
+ tp = nv_type(np);
+ }
+ if(checkopt(com,'C'))
+ flgs |= NV_COMVAR;
+ if(checkopt(com,'S'))
+ flgs |= NV_STATIC;
+ if(checkopt(com,'m'))
+ flgs |= NV_MOVE;
+ if(checkopt(com,'n'))
+ flgs |= NV_NOREF;
+ else if(!shp->typeinit && (checkopt(com,'L') || checkopt(com,'R') || checkopt(com,'Z')))
+ flgs |= NV_UNJUST;
+#if SHOPT_TYPEDEF
+ else if(argn>=3 && checkopt(com,'T'))
+ {
+# if SHOPT_NAMESPACE
+ if(shp->namespace)
+ {
+ if(!shp->strbuf2)
+ shp->strbuf2 = sfstropen();
+ sfprintf(shp->strbuf2,"%s%s%c",NV_CLASS,nv_name(shp->namespace),0);
+ shp->prefix = strdup(sfstruse(shp->strbuf2));
+ nv_open(shp->prefix,shp->var_base,NV_VARNAME);
+ }
+ else
+# endif /* SHOPT_NAMESPACE */
+ shp->prefix = NV_CLASS;
+ flgs |= NV_TYPE;
+
+ }
+#endif /* SHOPT_TYPEDEF */
+ if((shp->fn_depth && !shp->prefix) || np==SYSLOCAL)
+ flgs |= NV_NOSCOPE;
+ }
+ else if(np==SYSEXPORT)
+ flgs |= NV_EXPORT;
+ if(flgs&(NV_EXPORT|NV_NOREF))
+ flgs |= NV_IDENT;
+ else
+ flgs |= NV_VARNAME;
+#if 0
+ if(OPTIMIZE)
+ flgs |= NV_TAGGED;
+#endif
+ nv_setlist(argp,flgs,tp);
+ if(np==shp->typeinit)
+ shp->typeinit = 0;
+ shp->envlist = argp;
+ argp = NULL;
+ }
+ }
+ last_table = shp->last_table;
+ shp->last_table = 0;
+ if((io||argn))
+ {
+ Shbltin_t *bp=0;
+ static char *argv[1];
+ int tflags = 1;
+ if(np && nv_isattr(np,BLT_DCL))
+ tflags |= 2;
+ if(argn==0)
+ {
+ /* fake 'true' built-in */
+ np = SYSTRUE;
+ *argv = nv_name(np);
+ com = argv;
+ }
+ /* set +x doesn't echo */
+ else if((t->tre.tretyp&FSHOWME) && sh_isoption(SH_SHOWME))
+ {
+ int ison = sh_isoption(SH_XTRACE);
+ if(!ison)
+ sh_onoption(SH_XTRACE);
+ sh_trace(shp,com-command,tflags);
+ if(io)
+ sh_redirect(shp,io,SH_SHOWME);
+ if(!ison)
+ sh_offoption(SH_XTRACE);
+ break;
+ }
+ else if((np!=SYSSET) && sh_isoption(SH_XTRACE))
+ sh_trace(shp,com-command,tflags);
+ if(trap=shp->st.trap[SH_DEBUGTRAP])
+ {
+ int n = sh_debug(shp,trap,(char*)0,(char*)0, com, ARG_RAW);
+ if(n==255 && shp->fn_depth+shp->dot_depth)
+ {
+ np = SYSRETURN;
+ argn = 1;
+ com[0] = np->nvname;
+ com[1] = 0;
+ io = 0;
+ argp = 0;
+ }
+ else if(n==2)
+ break;
+ }
+ if(io)
+ sfsync(shp->outpool);
+ shp->lastpath = 0;
+ if(!np && !strchr(com0,'/'))
+ {
+ if(path_search(shp,com0,NIL(Pathcomp_t**),1))
+ {
+ error_info.line = t->com.comline-shp->st.firstline;
+#if SHOPT_NAMESPACE
+ if(!shp->namespace || !(np=sh_fsearch(shp,com0,0)))
+#endif /* SHOPT_NAMESPACE */
+ np=nv_search(com0,shp->fun_tree,0);
+ if(!np || !np->nvalue.ip)
+ {
+ Namval_t *mp=nv_search(com0,shp->bltin_tree,0);
+ if(mp)
+ np = mp;
+ }
+ }
+ else
+ {
+ if((np=nv_search(com0,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
+ np=nv_search(nv_getval(np),shp->bltin_tree,0);
+ else
+ np = 0;
+ }
+ }
+ if(np && pipejob==2)
+ {
+ job_unlock();
+ pipejob = 1;
+ }
+ /* check for builtins */
+ if(np && is_abuiltin(np))
+ {
+ volatile int scope=0, share=0;
+ volatile void *save_ptr;
+ volatile void *save_data;
+ int jmpval, save_prompt;
+ int was_nofork = execflg?sh_isstate(SH_NOFORK):0;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ unsigned long was_vi=0, was_emacs=0, was_gmacs=0;
+ struct stat statb;
+ bp = &shp->bltindata;
+ save_ptr = bp->ptr;
+ save_data = bp->data;
+ memset(&statb, 0, sizeof(struct stat));
+ if(strchr(nv_name(np),'/'))
+ {
+ /*
+ * disable editors for built-in
+ * versions of commands on PATH
+ */
+ was_vi = sh_isoption(SH_VI);
+ was_emacs = sh_isoption(SH_EMACS);
+ was_gmacs = sh_isoption(SH_GMACS);
+ sh_offoption(SH_VI);
+ sh_offoption(SH_EMACS);
+ sh_offoption(SH_GMACS);
+ }
+ if(execflg)
+ sh_onstate(SH_NOFORK);
+ sh_pushcontext(shp,buffp,SH_JMPCMD);
+ jmpval = sigsetjmp(buffp->buff,1);
+ if(jmpval == 0)
+ {
+ if(!(nv_isattr(np,BLT_ENV)))
+ error_info.flags |= ERROR_SILENT;
+ errorpush(&buffp->err,0);
+ if(io)
+ {
+ struct openlist *item;
+ if(np==SYSLOGIN)
+ type=1;
+ else if(np==SYSEXEC)
+ type=1+!com[1];
+ else
+ type = (execflg && !shp->subshell && !shp->st.trapcom[0]);
+ shp->redir0 = 1;
+ sh_redirect(shp,io,type);
+ for(item=buffp->olist;item;item=item->next)
+ item->strm=0;
+ }
+ if(!(nv_isattr(np,BLT_ENV)))
+ {
+ if(bp->nosfio)
+ {
+ if(!shp->pwd)
+ path_pwd(shp,0);
+ if(shp->pwd)
+ stat(".",&statb);
+ }
+ sfsync(NULL);
+ share = sfset(sfstdin,SF_SHARE,0);
+ sh_onstate(SH_STOPOK);
+ sfpool(sfstderr,NIL(Sfio_t*),SF_WRITE);
+ sfset(sfstderr,SF_LINE,1);
+ save_prompt = shp->nextprompt;
+ shp->nextprompt = 0;
+ }
+ if(argp)
+ {
+ scope++;
+ sh_scope(shp,argp,0);
+ }
+ opt_info.index = opt_info.offset = 0;
+ opt_info.disc = 0;
+ error_info.id = *com;
+ if(argn)
+ shp->exitval = 0;
+ shp->bltinfun = (Shbltin_f)funptr(np);
+ bp->bnode = np;
+ bp->vnode = nq;
+ bp->ptr = nv_context(np);
+ bp->data = t->com.comstate;
+ bp->sigset = 0;
+ bp->notify = 0;
+ bp->flags = (OPTIMIZE!=0);
+ if(shp->subshell && nv_isattr(np,BLT_NOSFIO))
+ sh_subtmpfile(shp);
+ if(execflg && !shp->subshell &&
+ !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && shp->fn_depth==0 && !nv_isattr(np,BLT_ENV))
+ {
+ /* do close-on-exec */
+ int fd;
+ for(fd=0; fd < shp->gd->lim.open_max; fd++)
+ if((shp->fdstatus[fd]&IOCLEX)&&fd!=shp->infd)
+ sh_close(fd);
+ }
+ if(argn)
+ shp->exitval = (*shp->bltinfun)(argn,com,(void*)bp);
+ if(error_info.flags&ERROR_INTERACTIVE)
+ tty_check(ERRIO);
+ ((Shnode_t*)t)->com.comstate = shp->bltindata.data;
+ bp->data = (void*)save_data;
+ if(sh.exitval && errno==EINTR && shp->lastsig)
+ sh.exitval = SH_EXITSIG|shp->lastsig;
+ else if(!nv_isattr(np,BLT_EXIT) && shp->exitval!=SH_RUNPROG)
+ shp->exitval &= SH_EXITMASK;
+ }
+ else
+ {
+ struct openlist *item;
+ for(item=buffp->olist;item;item=item->next)
+ {
+ if(item->strm)
+ {
+ sfclrlock(item->strm);
+ if(shp->gd->hist_ptr && item->strm == shp->gd->hist_ptr->histfp)
+ hist_close(shp->gd->hist_ptr);
+ else
+ sfclose(item->strm);
+ }
+ }
+ if(shp->bltinfun && (error_info.flags&ERROR_NOTIFY))
+ (*shp->bltinfun)(-2,com,(void*)bp);
+ /* failure on special built-ins fatal */
+ if(jmpval<=SH_JMPCMD && (!nv_isattr(np,BLT_SPC) || command))
+ jmpval=0;
+ }
+ if(bp)
+ {
+ bp->bnode = 0;
+ if( bp->ptr!= nv_context(np))
+ np->nvfun = (Namfun_t*)bp->ptr;
+ }
+ if(execflg && !was_nofork)
+ sh_offstate(SH_NOFORK);
+ if(!(nv_isattr(np,BLT_ENV)))
+ {
+ if(bp->nosfio && shp->pwd)
+ {
+ struct stat stata;
+ stat(".",&stata);
+ /* restore directory changed */
+ if(statb.st_ino!=stata.st_ino || statb.st_dev!=stata.st_dev)
+ chdir(shp->pwd);
+ }
+ sh_offstate(SH_STOPOK);
+ if(share&SF_SHARE)
+ sfset(sfstdin,SF_PUBLIC|SF_SHARE,1);
+ sfset(sfstderr,SF_LINE,0);
+ sfpool(sfstderr,shp->outpool,SF_WRITE);
+ sfpool(sfstdin,NIL(Sfio_t*),SF_WRITE);
+ shp->nextprompt = save_prompt;
+ }
+ sh_popcontext(shp,buffp);
+ errorpop(&buffp->err);
+ error_info.flags &= ~(ERROR_SILENT|ERROR_NOTIFY);
+ shp->bltinfun = 0;
+ if(buffp->olist)
+ free_list(buffp->olist);
+ if(was_vi)
+ sh_onoption(SH_VI);
+ else if(was_emacs)
+ sh_onoption(SH_EMACS);
+ else if(was_gmacs)
+ sh_onoption(SH_GMACS);
+ if(scope)
+ sh_unscope(shp);
+ bp->ptr = (void*)save_ptr;
+ bp->data = (void*)save_data;
+ /* don't restore for subshell exec */
+ if((shp->topfd>topfd) && !(shp->subshell && np==SYSEXEC))
+ sh_iorestore(shp,topfd,jmpval);
+
+ shp->redir0 = 0;
+ if(jmpval)
+ siglongjmp(*shp->jmplist,jmpval);
+#if 0
+ if(flgs&NV_STATIC)
+ ((Shnode_t*)t)->com.comset = 0;
+#endif
+ if(shp->exitval >=0)
+ goto setexit;
+ np = 0;
+ type=0;
+ }
+ /* check for functions */
+ if(!command && np && nv_isattr(np,NV_FUNCTION))
+ {
+ volatile int indx;
+ int jmpval=0;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+#if SHOPT_NAMESPACE
+ Namval_t node,*namespace=shp->namespace;
+#else
+ Namval_t node;
+#endif /* SHOPT_NAMESPACE */
+ struct Namref nr;
+ long mode;
+ register struct slnod *slp;
+ if(!np->nvalue.ip)
+ {
+ indx = path_search(shp,com0,NIL(Pathcomp_t**),0);
+ if(indx==1)
+ {
+#if SHOPT_NAMESPACE
+ if(shp->namespace)
+ np = sh_fsearch(shp,com0,0);
+ else
+#endif /* SHOPT_NAMESPACE */
+ np = nv_search(com0,shp->fun_tree,HASH_NOSCOPE);
+ }
+
+ if(!np->nvalue.ip)
+ {
+ if(indx==1)
+ {
+ errormsg(SH_DICT,ERROR_exit(0),e_defined,com0);
+ shp->exitval = ERROR_NOEXEC;
+ }
+ else
+ {
+ errormsg(SH_DICT,ERROR_exit(0),e_found,"function");
+ shp->exitval = ERROR_NOENT;
+ }
+ goto setexit;
+ }
+ }
+ /* increase refcnt for unset */
+ slp = (struct slnod*)np->nvenv;
+ sh_funstaks(slp->slchild,1);
+ staklink(slp->slptr);
+ if(nq)
+ {
+ Namval_t *mp=0;
+ if(nv_isattr(np,NV_STATICF) && (mp=nv_type(nq)))
+ nq = mp;
+ shp->last_table = last_table;
+ mode = set_instance(shp,nq,&node,&nr);
+ }
+ if(io)
+ {
+ indx = shp->topfd;
+ sh_pushcontext(shp,buffp,SH_JMPCMD);
+ jmpval = sigsetjmp(buffp->buff,0);
+ }
+ if(jmpval == 0)
+ {
+ if(io)
+ indx = sh_redirect(shp,io,execflg);
+#if SHOPT_NAMESPACE
+ if(nq && nv_istable(nq))
+ shp->namespace = nq;
+#endif /* SHOPT_NAMESPACE */
+ sh_funct(shp,np,argn,com,t->com.comset,(flags&~OPTIMIZE_FLAG));
+ }
+#if SHOPT_NAMESPACE
+ shp->namespace = namespace;
+#endif /* SHOPT_NAMESPACE */
+ if(io)
+ {
+ if(buffp->olist)
+ free_list(buffp->olist);
+ sh_popcontext(shp,buffp);
+ sh_iorestore(shp,indx,jmpval);
+ }
+ if(nq)
+ unset_instance(nq,&node,&nr,mode);
+ sh_funstaks(slp->slchild,-1);
+ stakdelete(slp->slptr);
+ if(jmpval > SH_JMPFUN)
+ siglongjmp(*shp->jmplist,jmpval);
+ goto setexit;
+ }
+ }
+ else if(!io)
+ {
+ setexit:
+ exitset();
+ break;
+ }
+ }
+ case TFORK:
+ {
+ register pid_t parent;
+ int no_fork,jobid;
+ int pipes[3];
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ sh_exec(t->fork.forktre,0);
+ break;
+ }
+#endif /* SHOPT_COSHELL */
+ if(shp->subshell)
+ {
+ sh_subtmpfile(shp);
+ if(!usepipe)
+ {
+ subpipe[0] = -1;
+ if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK) && sh_pipe(subpipe)>=0)
+ iousepipe(shp);
+ }
+ if((type&(FAMP|TFORK))==(FAMP|TFORK))
+ sh_subfork();
+ }
+ no_fork = !ntflag && !(type&(FAMP|FPOU)) &&
+ !(shp->st.trapcom[SIGINT] && *shp->st.trapcom[SIGINT]) &&
+ !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] &&
+ ((struct checkpt*)shp->jmplist)->mode!=SH_JMPEVAL &&
+ (execflg2 || (execflg &&
+ !shp->subshell && shp->fn_depth==0 &&
+ !(pipejob && sh_isoption(SH_PIPEFAIL))
+ ));
+ if(sh_isstate(SH_PROFILE) || shp->dot_depth)
+ {
+ /* disable foreground job monitor */
+ if(!(type&FAMP))
+ sh_offstate(SH_MONITOR);
+#if SHOPT_DEVFD
+ else if(!(type&FINT))
+ sh_offstate(SH_MONITOR);
+#endif /* SHOPT_DEVFD */
+ }
+ if(no_fork)
+ job.parent=parent=0;
+ else
+ {
+#ifdef SHOPT_BGX
+ int maxjob;
+ if(((type&(FAMP|FINT)) == (FAMP|FINT)) && (maxjob=nv_getnum(JOBMAXNOD))>0)
+ {
+ while(job.numbjob >= maxjob)
+ {
+ job_lock();
+ job_reap(0);
+ job_unlock();
+ }
+ }
+#endif /* SHOPT_BGX */
+ nv_getval(RANDNOD);
+ restorefd = shp->topfd;
+ if(type&FCOOP)
+ {
+ pipes[2] = 0;
+#if SHOPT_COSHELL
+ if(shp->coshell)
+ {
+ if(shp->cpipe[0]<0 || shp->cpipe[1] < 0)
+ {
+ sh_copipe(shp,shp->outpipe=shp->cpipe,0);
+ shp->fdptrs[shp->cpipe[0]] = shp->cpipe;
+ }
+ sh_copipe(shp,shp->inpipe=pipes,0);
+ parent = sh_coexec(shp,t,3);
+ shp->cpid = parent;
+ jobid = job_post(shp,parent,0);
+ goto skip;
+ }
+#endif /* SHOPT_COSHELL */
+ coproc_init(shp,pipes);
+ }
+#if SHOPT_COSHELL
+ if((type&(FAMP|FINT)) == (FAMP|FINT))
+ {
+ if(shp->coshell)
+ {
+ parent = sh_coexec(shp,t,0);
+ jobid = job_post(shp,parent,0);
+ goto skip;
+ }
+ }
+#endif /* SHOPT_COSHELL */
+#if SHOPT_AMP
+ if((type&(FAMP|FINT)) == (FAMP|FINT))
+ parent = sh_ntfork(shp,t,com,&jobid,ntflag);
+ else
+ parent = sh_fork(shp,type,&jobid);
+ if(parent<0)
+ {
+ if(shp->comsub==1 && subpipe[0]>=0)
+ iounpipe(shp);
+ break;
+ }
+#else
+#if SHOPT_SPAWN
+# ifdef _lib_fork
+ if(com)
+ parent = sh_ntfork(shp,t,com,&jobid,ntflag);
+ else
+ parent = sh_fork(shp,type,&jobid);
+# else
+ if((parent = sh_ntfork(shp,t,com,&jobid,ntflag))<=0)
+ break;
+# endif /* _lib_fork */
+ if(parent<0)
+ {
+ if(shp->comsub==1 && subpipe[0]>=0)
+ iounpipe(shp);
+ break;
+ }
+#else
+ parent = sh_fork(shp,type,&jobid);
+#endif /* SHOPT_SPAWN */
+#endif
+ }
+#if SHOPT_COSHELL
+ skip:
+#endif /* SHOPT_COSHELL */
+ if(job.parent=parent)
+ /* This is the parent branch of fork
+ * It may or may not wait for the child
+ */
+ {
+ if(pipejob==2)
+ {
+ pipejob = 1;
+ job_unlock();
+ }
+ if(type&FPCL)
+ sh_close(shp->inpipe[0]);
+ if(type&(FCOOP|FAMP))
+ shp->bckpid = parent;
+ else if(!(type&(FAMP|FPOU)))
+ {
+ if(!sh_isoption(SH_MONITOR))
+ {
+ if(!(shp->sigflag[SIGINT]&(SH_SIGFAULT|SH_SIGOFF)))
+ sh_sigtrap(SIGINT);
+ shp->trapnote |= SH_SIGIGNORE;
+ }
+ if(shp->pipepid)
+ shp->pipepid = parent;
+ else
+ job_wait(parent);
+ if(shp->topfd > topfd)
+ sh_iorestore(shp,topfd,sh.exitval);
+ if(usepipe && tsetio && subdup)
+ iounpipe(shp);
+ if(!sh_isoption(SH_MONITOR))
+ {
+ shp->trapnote &= ~SH_SIGIGNORE;
+ if(shp->exitval == (SH_EXITSIG|SIGINT))
+ sh_fault(SIGINT);
+ }
+ }
+ if(type&FAMP)
+ {
+ if(sh_isstate(SH_PROFILE) || sh_isstate(SH_INTERACTIVE))
+ {
+ /* print job number */
+#ifdef JOBS
+# if SHOPT_COSHELL
+ sfprintf(sfstderr,"[%d]\t%s\n",jobid,sh_pid2str(shp,parent));
+# else
+ sfprintf(sfstderr,"[%d]\t%d\n",jobid,parent);
+# endif /* SHOPT_COSHELL */
+#else
+ sfprintf(sfstderr,"%d\n",parent);
+#endif /* JOBS */
+ }
+ }
+ break;
+ }
+ else
+ /*
+ * this is the FORKED branch (child) of execute
+ */
+ {
+ volatile int jmpval;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ struct ionod *iop;
+ int rewrite=0;
+ if(no_fork)
+ sh_sigreset(2);
+ sh_pushcontext(shp,buffp,SH_JMPEXIT);
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval)
+ goto done;
+ if((type&FINT) && !sh_isstate(SH_MONITOR))
+ {
+ /* default std input for & */
+ signal(SIGINT,SIG_IGN);
+ signal(SIGQUIT,SIG_IGN);
+ if(!shp->st.ioset)
+ {
+ if(sh_close(0)>=0)
+ sh_chkopen(e_devnull);
+ }
+ }
+ sh_offstate(SH_MONITOR);
+ /* pipe in or out */
+#ifdef _lib_nice
+ if((type&FAMP) && sh_isoption(SH_BGNICE))
+ nice(4);
+#endif /* _lib_nice */
+#if !SHOPT_DEVFD
+ if(shp->fifo && (type&(FPIN|FPOU)))
+ {
+ int fn,fd = (type&FPIN)?0:1;
+ void *fifo_timer=sh_timeradd(500,1,fifo_check,(void*)shp);
+ fn = sh_open(shp->fifo,fd?O_WRONLY:O_RDONLY);
+ timerdel(fifo_timer);
+ sh_iorenumber(shp,fn,fd);
+ sh_close(fn);
+ sh_delay(.001);
+ unlink(shp->fifo);
+ free(shp->fifo);
+ shp->fifo = 0;
+ type &= ~(FPIN|FPOU);
+ }
+#endif /* !SHOPT_DEVFD */
+ if(type&FPIN)
+ {
+#if SHOPT_COSHELL
+ if(shp->inpipe[2]>20000)
+ sh_coaccept(shp,shp->inpipe,0);
+#endif /* SHOPT_COSHELL */
+ sh_iorenumber(shp,shp->inpipe[0],0);
+ if(!(type&FPOU) || (type&FCOOP))
+ sh_close(shp->inpipe[1]);
+ }
+ if(type&FPOU)
+ {
+#if SHOPT_COSHELL
+ if(shp->outpipe[2]>20000)
+ sh_coaccept(shp,shp->outpipe,1);
+#endif /* SHOPT_COSHELL */
+ sh_iorenumber(shp,shp->outpipe[1],1);
+ sh_pclose(shp->outpipe);
+ }
+ if((type&COMMSK)!=TCOM)
+ error_info.line = t->fork.forkline-shp->st.firstline;
+ if(shp->topfd)
+ sh_iounsave(shp);
+ topfd = shp->topfd;
+ if(com0 && (iop=t->tre.treio))
+ {
+ for(;iop;iop=iop->ionxt)
+ {
+ if(iop->iofile&IOREWRITE)
+ rewrite = 1;
+ }
+ }
+ sh_redirect(shp,t->tre.treio,1);
+ if(rewrite)
+ {
+ job_lock();
+ while((parent = vfork()) < 0)
+ _sh_fork(shp,parent, 0, (int*)0);
+ if(parent)
+ {
+ job_post(shp,parent,0);
+ job_wait(parent);
+ sh_iorestore(shp,topfd,SH_JMPCMD);
+ sh_done(shp,(shp->exitval&SH_EXITSIG)?(shp->exitval&SH_EXITMASK):0);
+
+ }
+ job_unlock();
+ }
+ if((type&COMMSK)!=TCOM)
+ {
+ /* don't clear job table for out
+ pipes so that jobs comand can
+ be used in a pipeline
+ */
+ if(!no_fork && !(type&FPOU))
+ job_clear();
+ sh_exec(t->fork.forktre,flags|sh_state(SH_NOFORK)|sh_state(SH_FORKED));
+ }
+ else if(com0)
+ {
+ sh_offoption(SH_ERREXIT);
+ sh_freeup(shp);
+ path_exec(shp,com0,com,t->com.comset);
+ }
+ done:
+ sh_popcontext(shp,buffp);
+ if(jmpval>SH_JMPEXIT)
+ siglongjmp(*shp->jmplist,jmpval);
+ sh_done(shp,0);
+ }
+ }
+
+ case TSETIO:
+ {
+ /*
+ * don't create a new process, just
+ * save and restore io-streams
+ */
+ pid_t pid;
+ int jmpval, waitall;
+ int simple = (t->fork.forktre->tre.tretyp&COMMSK)==TCOM;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ sh_redirect(shp,t->fork.forkio,0);
+ sh_exec(t->fork.forktre,0);
+ break;
+ }
+#endif /*SHOPT_COSHELL */
+ if(shp->subshell)
+ execflg = 0;
+ sh_pushcontext(shp,buffp,SH_JMPIO);
+ if(type&FPIN)
+ {
+ was_interactive = sh_isstate(SH_INTERACTIVE);
+ sh_offstate(SH_INTERACTIVE);
+ sh_iosave(shp,0,shp->topfd,(char*)0);
+ shp->pipepid = simple;
+ sh_iorenumber(shp,shp->inpipe[0],0);
+ /*
+ * if read end of pipe is a simple command
+ * treat as non-sharable to improve performance
+ */
+ if(simple)
+ sfset(sfstdin,SF_PUBLIC|SF_SHARE,0);
+ waitall = job.waitall;
+ job.waitall = 0;
+ pid = job.parent;
+ }
+ else
+ error_info.line = t->fork.forkline-shp->st.firstline;
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval==0)
+ {
+ if(shp->comsub==1)
+ tsetio = 1;
+ sh_redirect(shp,t->fork.forkio,execflg);
+ (t->fork.forktre)->tre.tretyp |= t->tre.tretyp&FSHOWME;
+ sh_exec(t->fork.forktre,flags&~simple);
+ }
+ else
+ sfsync(shp->outpool);
+ sh_popcontext(shp,buffp);
+ sh_iorestore(shp,buffp->topfd,jmpval);
+ if(buffp->olist)
+ free_list(buffp->olist);
+ if(type&FPIN)
+ {
+ job.waitall = waitall;
+ type = shp->exitval;
+ if(!(type&SH_EXITSIG))
+ {
+ /* wait for remainder of pipline */
+ if(shp->pipepid>1)
+ {
+ job_wait(shp->pipepid);
+ type = shp->exitval;
+ }
+ else
+ job_wait(waitall?pid:0);
+ if(type || !sh_isoption(SH_PIPEFAIL))
+ shp->exitval = type;
+ }
+ if(shp->comsub==1 && subpipe[0]>=0)
+ iounpipe(shp);
+ shp->pipepid = 0;
+ shp->st.ioset = 0;
+ if(simple && was_errexit)
+ {
+ echeck = 1;
+ sh_onstate(SH_ERREXIT);
+ }
+ }
+ if(jmpval>SH_JMPIO)
+ siglongjmp(*shp->jmplist,jmpval);
+ break;
+ }
+
+ case TPAR:
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ sh_exec(t->par.partre,0);
+ break;
+ }
+#endif /* SHOPT_COSHELL */
+ echeck = 1;
+ flags &= ~OPTIMIZE_FLAG;
+ if(!shp->subshell && !shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && (flags&sh_state(SH_NOFORK)))
+ {
+ char *savsig;
+ int nsig,jmpval;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ shp->st.otrapcom = 0;
+ if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
+ {
+ nsig += sizeof(char*);
+ memcpy(savsig=malloc(nsig),(char*)&shp->st.trapcom[0],nsig);
+ shp->st.otrapcom = (char**)savsig;
+ }
+ sh_sigreset(0);
+ sh_pushcontext(shp,buffp,SH_JMPEXIT);
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval==0)
+ sh_exec(t->par.partre,flags);
+ sh_popcontext(shp,buffp);
+ if(jmpval > SH_JMPEXIT)
+ siglongjmp(*shp->jmplist,jmpval);
+ if(shp->exitval > 256)
+ shp->exitval -= 128;
+ sh_done(shp,0);
+ }
+ else if(((type=t->par.partre->tre.tretyp)&FAMP) && ((type&COMMSK)==TFORK))
+ {
+ pid_t pid;
+ sfsync(NIL(Sfio_t*));
+ while((pid=fork())< 0)
+ _sh_fork(shp,pid,0,0);
+ if(pid==0)
+ {
+ sh_exec(t->par.partre,flags);
+ shp->st.trapcom[0]=0;
+ sh_done(shp,0);
+ }
+ }
+ else
+ sh_subshell(shp,t->par.partre,flags,0);
+ break;
+
+ case TFIL:
+ {
+ /*
+ * This code sets up a pipe.
+ * All elements of the pipe are started by the parent.
+ * The last element executes in current environment
+ */
+ int pvo[3]; /* old pipe for multi-stage */
+ int pvn[3]; /* current set up pipe */
+ int savepipe = pipejob;
+ int showme = t->tre.tretyp&FSHOWME;
+ int n,waitall,savewaitall=job.waitall;
+ int savejobid = job.curjobid;
+ int *exitval=0,*saveexitval = job.exitval;
+ pid_t savepgid = job.curpgid;
+#if SHOPT_COSHELL
+ int copipe=0;
+ Shnode_t *tt;
+#endif /* SHOPT_COSHELL */
+ job.exitval = 0;
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ do
+ {
+ sh_exec(t->lst.lstlef, 0);
+ t = t->lst.lstrit;
+ if(flags && (t->tre.tretyp!=TFIL || !(t->lst.lstlef->tre.tretyp&FALTPIPE)))
+ goto coskip1;
+ }
+ while(t->tre.tretyp==TFIL);
+ sh_exec(t,0);
+ coskip1:
+ break;
+ }
+ pvo[2] = pvn[2] = 0;
+#endif /* SHOPT_COSHELL */
+ job.curjobid = 0;
+ if(shp->subshell)
+ {
+ sh_subtmpfile(shp);
+ if(!usepipe)
+ {
+ subpipe[0] = -1;
+ if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK) && sh_pipe(subpipe)>=0)
+ iousepipe(shp);
+ }
+ }
+ shp->inpipe = pvo;
+ shp->outpipe = pvn;
+ pvo[1] = -1;
+ if(sh_isoption(SH_PIPEFAIL))
+ {
+ const Shnode_t* tn=t;
+ job.waitall = 2;
+ job.curpgid = 0;
+ while((tn=tn->lst.lstrit) && tn->tre.tretyp==TFIL)
+ job.waitall++;
+ exitval = job.exitval = (int*)stakalloc(job.waitall*sizeof(int));
+ memset(exitval,0,job.waitall*sizeof(int));
+ }
+ else
+ job.waitall |= !pipejob && sh_isstate(SH_MONITOR);
+ job_lock();
+ do
+ {
+ /* create the pipe */
+#if SHOPT_COSHELL
+ tt = t->lst.lstrit;
+ if(shp->coshell && !showme)
+ {
+ if(t->lst.lstlef->tre.tretyp&FALTPIPE)
+ {
+ sh_copipe(shp,pvn,0);
+ type = sh_coexec(shp,t,1+copipe);
+ pvn[1] = -1;
+ pipejob=1;
+ if(type>0)
+ {
+ job_post(shp,type,0);
+ type = 0;
+ }
+ copipe = 1;
+ pvo[0] = pvn[0];
+ while(tt->tre.tretyp==TFIL && tt->lst.lstlef->tre.tretyp&FALTPIPE)
+ tt = tt->lst.lstrit;
+ t = tt;
+ continue;
+ }
+ else if(tt->tre.tretyp==TFIL && tt->lst.lstlef->tre.tretyp&FALTPIPE)
+ {
+ sh_copipe(shp,pvn,0);
+ pvo[2] = pvn[2];
+ copipe = 0;
+ goto coskip2;
+ }
+ }
+#endif /* SHOPT_COSHELL */
+ sh_pipe(pvn);
+#if SHOPT_COSHELL
+ pvn[2] = 0;
+ coskip2:
+#endif /* SHOPT_COSHELL */
+ /* execute out part of pipe no wait */
+ (t->lst.lstlef)->tre.tretyp |= showme;
+ type = sh_exec(t->lst.lstlef, errorflg);
+ /* close out-part of pipe */
+ sh_close(pvn[1]);
+ pipejob=1;
+ /* save the pipe stream-ids */
+ pvo[0] = pvn[0];
+ /* pipeline all in one process group */
+ t = t->lst.lstrit;
+ }
+ /* repeat until end of pipeline */
+ while(!type && t->tre.tretyp==TFIL);
+ shp->inpipe = pvn;
+ shp->outpipe = 0;
+ pipejob = 2;
+ waitall = job.waitall;
+ job.waitall = 0;
+ if(type == 0)
+ {
+ /*
+ * execute last element of pipeline
+ * in the current process
+ */
+ ((Shnode_t*)t)->tre.tretyp |= showme;
+ sh_exec(t,flags);
+ }
+ else
+ /* execution failure, close pipe */
+ sh_pclose(pvn);
+ if(pipejob==2)
+ job_unlock();
+ pipejob = savepipe;
+ n = shp->exitval;
+ if(job.waitall = waitall)
+ {
+ if(sh_isstate(SH_MONITOR))
+ job_wait(0);
+ else
+ {
+ shp->intrap++;
+ job_wait(0);
+ shp->intrap--;
+ }
+ }
+ if(n==0 && exitval)
+ {
+ while(exitval <= --job.exitval)
+ {
+ if(*job.exitval)
+ {
+ n = *job.exitval;
+ break;
+ }
+ }
+ }
+ shp->exitval = n;
+#ifdef SIGTSTP
+ if(!pipejob && sh_isstate(SH_MONITOR))
+ tcsetpgrp(JOBTTY,shp->gd->pid);
+#endif /*SIGTSTP */
+ job.curpgid = savepgid;
+ job.exitval = saveexitval;
+ job.waitall = savewaitall;
+ job.curjobid = savejobid;
+ break;
+ }
+
+ case TLST:
+ {
+ /* a list of commands are executed here */
+ do
+ {
+ sh_exec(t->lst.lstlef,errorflg|OPTIMIZE);
+ t = t->lst.lstrit;
+ }
+ while(t->tre.tretyp == TLST);
+ sh_exec(t,flags);
+ break;
+ }
+
+ case TAND:
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ andor:
+ sh_exec(t->lst.lstlef,0);
+ sh_exec(t->lst.lstrit,0);
+ break;
+ }
+#endif /* SHOPT_COSHELL */
+ if(type&TTEST)
+ skipexitset++;
+ if(sh_exec(t->lst.lstlef,OPTIMIZE)==0)
+ sh_exec(t->lst.lstrit,flags);
+ break;
+
+ case TORF:
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ goto andor;
+#endif /* SHOPT_COSHELL */
+ if(type&TTEST)
+ skipexitset++;
+ if(sh_exec(t->lst.lstlef,OPTIMIZE)!=0)
+ sh_exec(t->lst.lstrit,flags);
+ break;
+
+ case TFOR: /* for and select */
+ {
+ register char **args;
+ register int nargs;
+ register Namval_t *np;
+ int flag = errorflg|OPTIMIZE_FLAG;
+ struct dolnod *argsav=0;
+ struct comnod *tp;
+ char *cp, *trap, *nullptr = 0;
+ int nameref, refresh=1;
+ char *av[5];
+#if SHOPT_COSHELL
+ int poolfiles;
+#endif /* SHOPT_COSHELL */
+#if SHOPT_OPTIMIZE
+ int jmpval = ((struct checkpt*)shp->jmplist)->mode;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ void *optlist = shp->optlist;
+ shp->optlist = 0;
+ sh_tclear(t->for_.fortre);
+ sh_pushcontext(shp,buffp,jmpval);
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval)
+ goto endfor;
+#endif /* SHOPT_OPTIMIZE */
+ error_info.line = t->for_.forline-shp->st.firstline;
+ if(!(tp=t->for_.forlst))
+ {
+ args=shp->st.dolv+1;
+ nargs = shp->st.dolc;
+ argsav=sh_arguse(shp);
+ }
+ else
+ {
+ args=sh_argbuild(shp,&argn,tp,0);
+ nargs = argn;
+ }
+ np = nv_open(t->for_.fornam, shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOREF);
+ nameref = nv_isref(np)!=0;
+ shp->st.loopcnt++;
+ cp = *args;
+ while(cp && shp->st.execbrk==0)
+ {
+ if(t->tre.tretyp&COMSCAN)
+ {
+ char *val;
+ int save_prompt;
+ /* reuse register */
+ if(refresh)
+ {
+ sh_menu(sfstderr,nargs,args);
+ refresh = 0;
+ }
+ save_prompt = shp->nextprompt;
+ shp->nextprompt = 3;
+ shp->timeout = 0;
+ shp->exitval=sh_readline(shp,&nullptr,0,1,1000*shp->st.tmout);
+ shp->nextprompt = save_prompt;
+ if(shp->exitval||sfeof(sfstdin)||sferror(sfstdin))
+ {
+ shp->exitval = 1;
+ break;
+ }
+ if(!(val=nv_getval(sh_scoped(shp,REPLYNOD))))
+ continue;
+ else
+ {
+ if(*(cp=val) == 0)
+ {
+ refresh++;
+ goto check;
+ }
+ while(type = *cp++)
+ if(type < '0' && type > '9')
+ break;
+ if(type!=0)
+ type = nargs;
+ else
+ type = (int)strtol(val, (char**)0, 10)-1;
+ if(type<0 || type >= nargs)
+ cp = "";
+ else
+ cp = args[type];
+ }
+ }
+ if(nameref)
+ nv_offattr(np,NV_REF);
+ else if(nv_isattr(np, NV_ARRAY))
+ nv_putsub(np,NIL(char*),0L);
+ nv_putval(np,cp,0);
+ if(nameref)
+ nv_setref(np,(Dt_t*)0,NV_VARNAME);
+ if(trap=shp->st.trap[SH_DEBUGTRAP])
+ {
+ av[0] = (t->tre.tretyp&COMSCAN)?"select":"for";
+ av[1] = t->for_.fornam;
+ av[2] = "in";
+ av[3] = cp;
+ av[4] = 0;
+ sh_debug(shp,trap,(char*)0,(char*)0,av,0);
+ }
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ poolfiles = shp->poolfiles;
+ sh_exec(t->for_.fortre,0);
+ if(poolfiles==shp->poolfiles)
+ break;
+ }
+#endif /* SHOPT_COSHELL */
+ sh_exec(t->for_.fortre,flag);
+ flag &= ~OPTIMIZE_FLAG;
+ if(t->tre.tretyp&COMSCAN)
+ {
+ if((cp=nv_getval(sh_scoped(shp,REPLYNOD))) && *cp==0)
+ refresh++;
+ }
+ else
+ cp = *++args;
+ check:
+ if(shp->st.breakcnt<0)
+ shp->st.execbrk = (++shp->st.breakcnt !=0);
+ }
+#if SHOPT_OPTIMIZE
+ endfor:
+ sh_popcontext(shp,buffp);
+ sh_tclear(t->for_.fortre);
+ sh_optclear(shp,optlist);
+ if(jmpval)
+ siglongjmp(*shp->jmplist,jmpval);
+#endif /*SHOPT_OPTIMIZE */
+ if(shp->st.breakcnt>0)
+ shp->st.execbrk = (--shp->st.breakcnt !=0);
+ shp->st.loopcnt--;
+ sh_argfree(shp,argsav,0);
+ nv_close(np);
+ break;
+ }
+
+ case TWH: /* while and until */
+ {
+ volatile int r=0;
+ int first = OPTIMIZE_FLAG;
+ Shnode_t *tt = t->wh.whtre;
+#if SHOPT_FILESCAN
+ Sfio_t *iop=0;
+ int savein,fd;
+#endif /*SHOPT_FILESCAN*/
+#if SHOPT_OPTIMIZE
+ int jmpval = ((struct checkpt*)shp->jmplist)->mode;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ void *optlist = shp->optlist;
+#endif /* SHOPT_OPTIMIZE */
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ int poolfiles;
+# if SHOPT_FILESCAN
+ if(type==TWH && tt->tre.tretyp==TCOM && !tt->com.comarg && tt->com.comio)
+ {
+ sh_redirect(shp,tt->com.comio,0);
+ break;
+ }
+# endif /* SHOPT_FILESCAN */
+ sh_exec(tt,0);
+ do
+ {
+ if((sh_exec(tt,0)==0)!=(type==TWH))
+ break;
+ poolfiles = shp->poolfiles;
+ sh_exec(t->wh.dotre,0);
+ if(t->wh.whinc)
+ sh_exec((Shnode_t*)t->wh.whinc,0);
+ }
+ while(poolfiles != shp->poolfiles);
+ break;
+ }
+#endif /*SHOPT_COSHELL */
+#if SHOPT_OPTIMIZE
+ shp->optlist = 0;
+ sh_tclear(t->wh.whtre);
+ sh_tclear(t->wh.dotre);
+ sh_pushcontext(shp,buffp,jmpval);
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval)
+ goto endwhile;
+#endif /* SHOPT_OPTIMIZE */
+#if SHOPT_FILESCAN
+ if(type==TWH && tt->tre.tretyp==TCOM && !tt->com.comarg && tt->com.comio)
+ {
+ fd = sh_redirect(shp,tt->com.comio,3);
+ savein = dup(0);
+ if(fd==0)
+ fd = savein;
+ iop = sfnew(NULL,NULL,SF_UNBOUND,fd,SF_READ);
+ close(0);
+ open(e_devnull,O_RDONLY);
+ shp->offsets[0] = -1;
+ shp->offsets[1] = 0;
+ if(tt->com.comset)
+ nv_setlist(tt->com.comset,NV_IDENT|NV_ASSIGN,0);
+ }
+#endif /*SHOPT_FILESCAN */
+ shp->st.loopcnt++;
+ while(shp->st.execbrk==0)
+ {
+#if SHOPT_FILESCAN
+ if(iop)
+ {
+ if(!(shp->cur_line=sfgetr(iop,'\n',SF_STRING)))
+ break;
+ }
+ else
+#endif /*SHOPT_FILESCAN */
+ if((sh_exec(tt,first)==0)!=(type==TWH))
+ break;
+ r = sh_exec(t->wh.dotre,first|errorflg);
+ if(shp->st.breakcnt<0)
+ shp->st.execbrk = (++shp->st.breakcnt !=0);
+ /* This is for the arithmetic for */
+ if(shp->st.execbrk==0 && t->wh.whinc)
+ sh_exec((Shnode_t*)t->wh.whinc,first);
+ first = 0;
+ errorflg &= ~OPTIMIZE_FLAG;
+#if SHOPT_FILESCAN
+ shp->offsets[0] = -1;
+ shp->offsets[1] = 0;
+#endif /*SHOPT_FILESCAN */
+ }
+#if SHOPT_OPTIMIZE
+ endwhile:
+ sh_popcontext(shp,buffp);
+ sh_tclear(t->wh.whtre);
+ sh_tclear(t->wh.dotre);
+ sh_optclear(shp,optlist);
+ if(jmpval)
+ siglongjmp(*shp->jmplist,jmpval);
+#endif /*SHOPT_OPTIMIZE */
+ if(shp->st.breakcnt>0)
+ shp->st.execbrk = (--shp->st.breakcnt !=0);
+ shp->st.loopcnt--;
+ shp->exitval= r;
+#if SHOPT_FILESCAN
+ if(iop)
+ {
+ sfclose(iop);
+ close(0);
+ dup(savein);
+ shp->cur_line = 0;
+ }
+#endif /*SHOPT_FILESCAN */
+ break;
+ }
+ case TARITH: /* (( expression )) */
+ {
+ register char *trap;
+ char *arg[4];
+ error_info.line = t->ar.arline-shp->st.firstline;
+ arg[0] = "((";
+ if(!(t->ar.arexpr->argflag&ARG_RAW))
+ arg[1] = sh_macpat(shp,t->ar.arexpr,OPTIMIZE|ARG_ARITH);
+ else
+ arg[1] = t->ar.arexpr->argval;
+ arg[2] = "))";
+ arg[3] = 0;
+ if(trap=shp->st.trap[SH_DEBUGTRAP])
+ sh_debug(shp,trap,(char*)0, (char*)0, arg, ARG_ARITH);
+ if(sh_isoption(SH_XTRACE))
+ {
+ sh_trace(shp,NIL(char**),0);
+ sfprintf(sfstderr,"((%s))\n",arg[1]);
+ }
+ if(t->ar.arcomp)
+ shp->exitval = !arith_exec((Arith_t*)t->ar.arcomp);
+ else
+ shp->exitval = !sh_arith(shp,arg[1]);
+ break;
+ }
+
+ case TIF:
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ sh_exec(t->if_.thtre,0);
+ if(t->if_.eltre)
+ sh_exec(t->if_.eltre, 0);
+ break;
+ }
+#endif /*SHOPT_COSHELL */
+ if(sh_exec(t->if_.iftre,OPTIMIZE)==0)
+ sh_exec(t->if_.thtre,flags);
+ else if(t->if_.eltre)
+ sh_exec(t->if_.eltre, flags);
+ else
+ shp->exitval=0; /* force zero exit for if-then-fi */
+ break;
+
+ case TSW:
+ {
+ Shnode_t *tt = (Shnode_t*)t;
+ char *trap, *r = sh_macpat(shp,tt->sw.swarg,OPTIMIZE);
+ error_info.line = t->sw.swline-shp->st.firstline;
+ t= (Shnode_t*)(tt->sw.swlst);
+ if(trap=shp->st.trap[SH_DEBUGTRAP])
+ {
+ char *av[4];
+ av[0] = "case";
+ av[1] = r;
+ av[2] = "in";
+ av[3] = 0;
+ sh_debug(shp,trap, (char*)0, (char*)0, av, 0);
+ }
+ while(t)
+ {
+ register struct argnod *rex=(struct argnod*)t->reg.regptr;
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ sh_exec(t->reg.regcom,0);
+ continue;
+ }
+#endif /*SHOPT_COSHELL */
+ while(rex)
+ {
+ register char *s;
+ if(rex->argflag&ARG_MAC)
+ {
+ s = sh_macpat(shp,rex,OPTIMIZE|ARG_EXP);
+ while(*s=='\\' && s[1]==0)
+ s+=2;
+ }
+ else
+ s = rex->argval;
+ type = (rex->argflag&ARG_RAW);
+ if((type && strcmp(r,s)==0) ||
+ (!type && (strmatch(r,s)
+ || trim_eq(r,s))))
+ {
+ do sh_exec(t->reg.regcom,(t->reg.regflag?(flags&sh_state(SH_ERREXIT)):flags));
+ while(t->reg.regflag &&
+ (t=(Shnode_t*)t->reg.regnxt));
+ t=0;
+ break;
+ }
+ else
+ rex=rex->argnxt.ap;
+ }
+ if(t)
+ t=(Shnode_t*)t->reg.regnxt;
+ }
+ break;
+ }
+
+ case TTIME:
+ {
+ /* time the command */
+ struct tms before,after;
+ const char *format = e_timeformat;
+ clock_t at, tm[3];
+#ifdef timeofday
+ struct timeval tb,ta;
+#else
+ clock_t bt;
+#endif /* timeofday */
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ if(t->par.partre)
+ sh_exec(t->par.partre,0);
+ break;
+ }
+#endif /*SHOPT_COSHELL */
+ if(type!=TTIME)
+ {
+ sh_exec(t->par.partre,OPTIMIZE);
+ shp->exitval = !shp->exitval;
+ break;
+ }
+ if(t->par.partre)
+ {
+ long timer_on;
+ if(shp->subshell && shp->comsub==1)
+ sh_subfork();
+ timer_on = sh_isstate(SH_TIMING);
+#ifdef timeofday
+ timeofday(&tb);
+ times(&before);
+#else
+ bt = times(&before);
+#endif /* timeofday */
+ job.waitall = 1;
+ sh_onstate(SH_TIMING);
+ sh_exec(t->par.partre,OPTIMIZE);
+ if(!timer_on)
+ sh_offstate(SH_TIMING);
+ job.waitall = 0;
+ }
+ else
+ {
+#ifndef timeofday
+ bt = 0;
+#endif /* timeofday */
+ before.tms_utime = before.tms_cutime = 0;
+ before.tms_stime = before.tms_cstime = 0;
+ }
+#ifdef timeofday
+ times(&after);
+ timeofday(&ta);
+ at = shp->gd->lim.clk_tck*(ta.tv_sec-tb.tv_sec);
+ at += ((shp->gd->lim.clk_tck*(((1000000L/2)/shp->gd->lim.clk_tck)+(ta.tv_usec-tb.tv_usec)))/1000000L);
+#else
+ at = times(&after) - bt;
+#endif /* timeofday */
+ tm[0] = at;
+ if(t->par.partre)
+ {
+ Namval_t *np = nv_open("TIMEFORMAT",shp->var_tree,NV_NOADD);
+ if(np)
+ {
+ format = nv_getval(np);
+ nv_close(np);
+ }
+ if(!format)
+ format = e_timeformat;
+ }
+ else
+ format = strchr(format+1,'\n')+1;
+ tm[1] = after.tms_utime - before.tms_utime;
+ tm[1] += after.tms_cutime - before.tms_cutime;
+ tm[2] = after.tms_stime - before.tms_stime;
+ tm[2] += after.tms_cstime - before.tms_cstime;
+ if(format && *format)
+ p_time(shp,sfstderr,sh_translate(format),tm);
+ break;
+ }
+ case TFUN:
+ {
+ register Namval_t *np=0;
+ register struct slnod *slp;
+ register char *fname = ((struct functnod*)t)->functnam;
+ register char *cp = strrchr(fname,'.');
+ register Namval_t *npv=0,*mp;
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ {
+ sh_exec(t->funct.functtre,0);
+ break;
+ }
+#endif /* SHOPT_COSHELL */
+#if SHOPT_NAMESPACE
+ if(t->tre.tretyp==TNSPACE)
+ {
+ Dt_t *root,*oldroot, *bot=0;
+ Namval_t *oldnspace = shp->namespace;
+ int offset = stktell(stkp);
+ long optindex = shp->st.optindex;
+ int flags=NV_NOASSIGN|NV_NOARRAY|NV_VARNAME;
+ if(cp)
+ errormsg(SH_DICT,ERROR_exit(1),e_ident,fname);
+ if(!shp->namespace)
+ sfputc(stkp,'.');
+ else
+ flags |= NV_NOSCOPE;
+ sfputr(stkp,fname,0);
+ np = nv_open(stkptr(stkp,offset),shp->var_tree,flags);
+ offset = stktell(stkp);
+ shp->namespace = np;
+ if(nv_istable(np))
+ root = nv_dict(np);
+ else
+ {
+ root = dtopen(&_Nvdisc,Dtoset);
+ nv_mount(np, (char*)0, root);
+ np->nvalue.cp = Empty;
+ shp->st.optindex = 1;
+ }
+ if(oldnspace && dtvnext(dtvnext(shp->var_tree)))
+ bot = dtview(shp->var_tree,0);
+ else if(dtvnext(shp->var_tree))
+ bot = dtview(shp->var_tree,0);
+ oldroot = shp->var_tree;
+ dtview(root,shp->var_base);
+ shp->var_tree = root;
+ if(bot)
+ dtview(shp->var_tree,bot);
+ sh_exec(t->for_.fortre,flags|sh_state(SH_ERREXIT));
+ if(dtvnext(shp->var_tree))
+ bot = dtview(shp->var_tree,0);
+ shp->var_tree = oldroot;
+ if(bot)
+ dtview(shp->var_tree,bot);
+ shp->namespace = oldnspace;
+ shp->st.optindex = optindex;
+ break;
+ }
+#endif /* SHOPT_NAMESPACE */
+ /* look for discipline functions */
+ error_info.line = t->funct.functline-shp->st.firstline;
+ /* Function names cannot be special builtin */
+ if(cp || shp->prefix)
+ {
+ int offset = stktell(stkp);
+ if(shp->prefix)
+ {
+ cp = shp->prefix;
+ shp->prefix = 0;
+ npv = nv_open(cp,shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
+ shp->prefix = cp;
+ cp = fname;
+ }
+ else
+ {
+ sfwrite(stkp,fname,cp++-fname);
+ sfputc(stkp,0);
+ npv = nv_open(stkptr(stkp,offset),shp->var_tree,NV_NOASSIGN|NV_NOARRAY|NV_VARNAME);
+ }
+ offset = stktell(stkp);
+ sfprintf(stkp,"%s.%s%c",nv_name(npv),cp,0);
+ fname = stkptr(stkp,offset);
+ }
+ else if((mp=nv_search(fname,shp->bltin_tree,0)) && nv_isattr(mp,BLT_SPC))
+ errormsg(SH_DICT,ERROR_exit(1),e_badfun,fname);
+#if SHOPT_NAMESPACE
+ if(shp->namespace && !shp->prefix && *fname!='.')
+ np = sh_fsearch(shp,fname,NV_ADD|HASH_NOSCOPE);
+ if(!np)
+#endif /* SHOPT_NAMESPACE */
+ np = nv_open(fname,sh_subfuntree(1),NV_NOASSIGN|NV_NOARRAY|NV_VARNAME|NV_NOSCOPE);
+ if(npv)
+ {
+ if(!shp->mktype)
+ cp = nv_setdisc(npv,cp,np,(Namfun_t*)npv);
+ if(!cp)
+ errormsg(SH_DICT,ERROR_exit(1),e_baddisc,fname);
+ }
+ if(np->nvalue.rp)
+ {
+ struct Ufunction *rp = np->nvalue.rp;
+ slp = (struct slnod*)np->nvenv;
+ sh_funstaks(slp->slchild,-1);
+ stakdelete(slp->slptr);
+ if(shp->funload)
+ {
+ free((void*)np->nvalue.rp);
+ np->nvalue.rp = 0;
+ }
+ if(rp->sdict)
+ {
+ Namval_t *mp, *nq;
+ shp->last_root = rp->sdict;
+ for(mp=(Namval_t*)dtfirst(rp->sdict);mp;mp=nq)
+ {
+ nq = dtnext(rp->sdict,mp);
+ _nv_unset(mp,NV_RDONLY);
+ nv_delete(mp,rp->sdict,0);
+ }
+ dtclose(rp->sdict);
+ rp->sdict = 0;
+ }
+ }
+ if(!np->nvalue.rp)
+ {
+ np->nvalue.rp = new_of(struct Ufunction,shp->funload?sizeof(Dtlink_t):0);
+ memset((void*)np->nvalue.rp,0,sizeof(struct Ufunction));
+ }
+ if(t->funct.functstak)
+ {
+ static Dtdisc_t _Rpdisc =
+ {
+ offsetof(struct Ufunction,fname), -1, sizeof(struct Ufunction)
+ };
+ struct functnod *fp;
+ struct comnod *ac = t->funct.functargs;
+ slp = t->funct.functstak;
+ sh_funstaks(slp->slchild,1);
+ staklink(slp->slptr);
+ np->nvenv = (char*)slp;
+ nv_funtree(np) = (int*)(t->funct.functtre);
+ np->nvalue.rp->hoffset = t->funct.functloc;
+ np->nvalue.rp->lineno = t->funct.functline;
+ np->nvalue.rp->nspace = shp->namespace;
+ np->nvalue.rp->fname = 0;
+ np->nvalue.rp->argv = ac?((struct dolnod*)ac->comarg)->dolval+1:0;
+ np->nvalue.rp->argc = ac?((struct dolnod*)ac->comarg)->dolnum:0;
+ np->nvalue.rp->fdict = shp->fun_tree;
+ fp = (struct functnod*)(slp+1);
+ if(fp->functtyp==(TFUN|FAMP))
+ np->nvalue.rp->fname = fp->functnam;
+ nv_setsize(np,fp->functline);
+ nv_offattr(np,NV_FPOSIX);
+ if(shp->funload)
+ {
+ struct Ufunction *rp = np->nvalue.rp;
+ rp->np = np;
+ if(!shp->fpathdict)
+ shp->fpathdict = dtopen(&_Rpdisc,Dtobag);
+ if(shp->fpathdict)
+ dtinsert(shp->fpathdict,rp);
+ }
+ }
+ else
+ _nv_unset(np,0);
+ if(type&FPOSIX)
+ nv_onattr(np,NV_FUNCTION|NV_FPOSIX);
+ else
+ nv_onattr(np,NV_FUNCTION);
+ if(type&FPIN)
+ nv_onattr(np,NV_FTMP);
+ if(type&FOPTGET)
+ nv_onattr(np,NV_OPTGET);
+ break;
+ }
+
+ /* new test compound command */
+ case TTST:
+ {
+ register int n;
+ register char *left;
+ int negate = (type&TNEGATE)!=0;
+#if SHOPT_COSHELL
+ if(shp->inpool)
+ break;
+#endif /* SHOPT_COSHELL */
+ if(type&TTEST)
+ skipexitset++;
+ error_info.line = t->tst.tstline-shp->st.firstline;
+ echeck = 1;
+ if((type&TPAREN)==TPAREN)
+ {
+ sh_exec(t->lst.lstlef,OPTIMIZE);
+ n = !shp->exitval;
+ }
+ else
+ {
+ register int traceon=0;
+ register char *right;
+ register char *trap;
+ char *argv[6];
+ n = type>>TSHIFT;
+ left = sh_macpat(shp,&(t->lst.lstlef->arg),OPTIMIZE);
+ if(type&TBINARY)
+ right = sh_macpat(shp,&(t->lst.lstrit->arg),((n==TEST_PEQ||n==TEST_PNE)?ARG_EXP:0)|OPTIMIZE);
+ if(trap=shp->st.trap[SH_DEBUGTRAP])
+ argv[0] = (type&TNEGATE)?((char*)e_tstbegin):"[[";
+ if(sh_isoption(SH_XTRACE))
+ {
+ traceon = sh_trace(shp,NIL(char**),0);
+ sfwrite(sfstderr,e_tstbegin,(type&TNEGATE?5:3));
+ }
+ if(type&TUNARY)
+ {
+ if(traceon)
+ sfprintf(sfstderr,"-%c %s",n,sh_fmtq(left));
+ if(trap)
+ {
+ char unop[3];
+ unop[0] = '-';
+ unop[1] = n;
+ unop[2] = 0;
+ argv[1] = unop;
+ argv[2] = left;
+ argv[3] = "]]";
+ argv[4] = 0;
+ sh_debug(shp,trap,(char*)0,(char*)0,argv, 0);
+ }
+ n = test_unop(shp,n,left);
+ }
+ else if(type&TBINARY)
+ {
+ char *op;
+ int pattern = 0;
+ if(trap || traceon)
+ op = (char*)(shtab_testops+(n&037)-1)->sh_name;
+ type >>= TSHIFT;
+ if(type==TEST_PEQ || type==TEST_PNE)
+ pattern=ARG_EXP;
+ if(trap)
+ {
+ argv[1] = left;
+ argv[2] = op;
+ argv[3] = right;
+ argv[4] = "]]";
+ argv[5] = 0;
+ sh_debug(shp,trap,(char*)0,(char*)0,argv, pattern);
+ }
+ n = test_binop(shp,n,left,right);
+ if(traceon)
+ {
+ sfprintf(sfstderr,"%s %s ",sh_fmtq(left),op);
+ if(pattern)
+ out_pattern(sfstderr,right,-1);
+ else
+ sfputr(sfstderr,sh_fmtq(right),-1);
+ }
+ }
+ if(traceon)
+ sfwrite(sfstderr,e_tstend,4);
+ }
+ shp->exitval = ((!n)^negate);
+ if(!skipexitset)
+ exitset();
+ break;
+ }
+ }
+ if(shp->trapnote || (shp->exitval && sh_isstate(SH_ERREXIT)) &&
+ t && echeck)
+ sh_chktrap(shp);
+ /* set $_ */
+ if(mainloop && com0)
+ {
+ /* store last argument here if it fits */
+ static char lastarg[32];
+ if(sh_isstate(SH_FORKED))
+ sh_done(shp,0);
+ if(shp->lastarg!= lastarg && shp->lastarg)
+ free(shp->lastarg);
+ if(strlen(comn) < sizeof(lastarg))
+ {
+ nv_onattr(L_ARGNOD,NV_NOFREE);
+ shp->lastarg = strcpy(lastarg,comn);
+ }
+ else
+ {
+ nv_offattr(L_ARGNOD,NV_NOFREE);
+ shp->lastarg = strdup(comn);
+ }
+ }
+ if(!skipexitset)
+ exitset();
+#if SHOPT_COSHELL
+ if(!shp->inpool && !(OPTIMIZE))
+#else
+ if(!(OPTIMIZE))
+#endif /* SHOPT_COSHELL */
+ {
+ if(sav != stkptr(stkp,0))
+ stkset(stkp,sav,0);
+ else if(stktell(stkp))
+ stkseek(stkp,0);
+ }
+ if(shp->trapnote&SH_SIGSET)
+ sh_exit(SH_EXITSIG|shp->lastsig);
+ if(was_interactive)
+ sh_onstate(SH_INTERACTIVE);
+ if(was_monitor && sh_isoption(SH_MONITOR))
+ sh_onstate(SH_MONITOR);
+ if(was_errexit)
+ sh_onstate(SH_ERREXIT);
+ }
+ return(shp->exitval);
+}
+
+int sh_run(int argn, char *argv[])
+{
+ Shell_t *shp = sh_getinterp();
+ register struct dolnod *dp;
+ register struct comnod *t = (struct comnod*)stakalloc(sizeof(struct comnod));
+ int savtop = staktell();
+ char *savptr = stakfreeze(0);
+ Opt_t *op, *np = optctx(0, 0);
+ Shbltin_t bltindata;
+ bltindata = shp->bltindata;
+ op = optctx(np, 0);
+ memset(t, 0, sizeof(struct comnod));
+ dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
+ dp->dolnum = argn;
+ dp->dolbot = ARG_SPARE;
+ memcpy(dp->dolval+ARG_SPARE, argv, (argn+1)*sizeof(char*));
+ t->comarg = (struct argnod*)dp;
+ if(!strchr(argv[0],'/'))
+ t->comnamp = (void*)nv_bfsearch(argv[0],shp->fun_tree,(Namval_t**)&t->comnamq,(char**)0);
+ argn=sh_exec((Shnode_t*)t,sh_isstate(SH_ERREXIT));
+ optctx(op,np);
+ shp->bltindata = bltindata;
+ if(savptr!=stakptr(0))
+ stakset(savptr,savtop);
+ else
+ stakseek(savtop);
+ return(argn);
+}
+
+/*
+ * test for equality with second argument trimmed
+ * returns 1 if r == trim(s) otherwise 0
+ */
+
+static int trim_eq(register const char *r,register const char *s)
+{
+ register char c;
+ while(c = *s++)
+ {
+ if(c=='\\')
+ c = *s++;
+ if(c && c != *r++)
+ return(0);
+ }
+ return(*r==0);
+}
+
+/*
+ * print out the command line if set -x is on
+ */
+
+int sh_trace(Shell_t *shp,register char *argv[], register int nl)
+{
+ register char *cp;
+ register int bracket = 0;
+ int decl = (nl&2);
+ nl &= ~2;
+ if(sh_isoption(SH_XTRACE))
+ {
+ /* make this trace atomic */
+ sfset(sfstderr,SF_SHARE|SF_PUBLIC,0);
+ if(!(cp=nv_getval(sh_scoped(shp,PS4NOD))))
+ cp = "+ ";
+ else
+ {
+ sh_offoption(SH_XTRACE);
+ cp = sh_mactry(shp,cp);
+ sh_onoption(SH_XTRACE);
+ }
+ if(*cp)
+ sfputr(sfstderr,cp,-1);
+ if(argv)
+ {
+ char *argv0 = *argv;
+ nl = (nl?'\n':-1);
+ /* don't quote [ and [[ */
+ if(*(cp=argv[0])=='[' && (!cp[1] || !cp[2]&&cp[1]=='['))
+ {
+ sfputr(sfstderr,cp,*++argv?' ':nl);
+ bracket = 1;
+ }
+ while(cp = *argv++)
+ {
+ if(bracket==0 || *argv || *cp!=']')
+ cp = sh_fmtq(cp);
+ if(decl && shp->prefix && cp!=argv0 && *cp!='-')
+ {
+ if(*cp=='.' && cp[1]==0)
+ cp = shp->prefix;
+ else
+ sfputr(sfstderr,shp->prefix,'.');
+ }
+ sfputr(sfstderr,cp,*argv?' ':nl);
+ }
+ sfset(sfstderr,SF_SHARE|SF_PUBLIC,1);
+ }
+ return(1);
+ }
+ return(0);
+}
+
+/*
+ * This routine creates a subshell by calling fork() or vfork()
+ * If ((flags&COMASK)==TCOM), then vfork() is permitted
+ * If fork fails, the shell sleeps for exponentially longer periods
+ * and tries again until a limit is reached.
+ * SH_FORKLIM is the max period between forks - power of 2 usually.
+ * Currently shell tries after 2,4,8,16, and 32 seconds and then quits
+ * Failures cause the routine to error exit.
+ * Parent links to here-documents are removed by the child
+ * Traps are reset by the child
+ * The process-id of the child is returned to the parent, 0 to the child.
+ */
+
+static void timed_out(void *handle)
+{
+ NOT_USED(handle);
+ timeout = 0;
+}
+
+
+/*
+ * called by parent and child after fork by sh_fork()
+ */
+pid_t _sh_fork(Shell_t *shp,register pid_t parent,int flags,int *jobid)
+{
+ static long forkcnt = 1000L;
+ pid_t curpgid = job.curpgid;
+ pid_t postid = (flags&FAMP)?0:curpgid;
+ int sig,nochild;
+ if(parent<0)
+ {
+ sh_sigcheck(shp);
+ if((forkcnt *= 2) > 1000L*SH_FORKLIM)
+ {
+ forkcnt=1000L;
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_nofork);
+ }
+ timeout = (void*)sh_timeradd(forkcnt, 0, timed_out, NIL(void*));
+ nochild = job_wait((pid_t)1);
+ if(timeout)
+ {
+ if(nochild)
+ pause();
+ else if(forkcnt>1000L)
+ forkcnt /= 2;
+ timerdel(timeout);
+ timeout = 0;
+ }
+ return(-1);
+ }
+ forkcnt = 1000L;
+ if(parent)
+ {
+ int myjob,waitall=job.waitall;
+ shp->gd->nforks++;
+ if(job.toclear)
+ job_clear();
+ job.waitall = waitall;
+#ifdef JOBS
+ /* first process defines process group */
+ if(sh_isstate(SH_MONITOR))
+ {
+ /*
+ * errno==EPERM means that an earlier processes
+ * completed. Make parent the job group id.
+ */
+ if(postid==0)
+ job.curpgid = parent;
+ if(job.jobcontrol || (flags&FAMP))
+ {
+ if(setpgid(parent,job.curpgid)<0 && errno==EPERM)
+ setpgid(parent,parent);
+ }
+ }
+#endif /* JOBS */
+ if(!sh_isstate(SH_MONITOR) && job.waitall && postid==0)
+ job.curpgid = parent;
+ if(flags&FCOOP)
+ shp->cpid = parent;
+ if(!postid && job.curjobid && (flags&FPOU))
+ postid = job.curpgid;
+#ifdef SHOPT_BGX
+ if(!postid && (flags&(FAMP|FINT)) == (FAMP|FINT))
+ postid = 1;
+ myjob = job_post(shp,parent,postid);
+ if(postid==1)
+ postid = 0;
+#else
+ myjob = job_post(shp,parent,postid);
+#endif /* SHOPT_BGX */
+ if(job.waitall && (flags&FPOU))
+ {
+ if(!job.curjobid)
+ job.curjobid = myjob;
+ if(job.exitval)
+ job.exitval++;
+ }
+ if(flags&FAMP)
+ job.curpgid = curpgid;
+ if(jobid)
+ *jobid = myjob;
+ if(shp->comsub==1 && subpipe[0]>=0)
+ {
+ if(!tsetio || !subdup)
+ {
+ if(shp->topfd > restorefd)
+ sh_iorestore(shp,restorefd,sh.exitval);
+ iounpipe(shp);
+ }
+ }
+ return(parent);
+ }
+#if !_std_malloc
+ vmtrace(-1);
+#endif
+ shp->outpipepid = ((flags&FPOU)?getpid():0);
+ /* This is the child process */
+ if(shp->trapnote&SH_SIGTERM)
+ sh_exit(SH_EXITSIG|SIGTERM);
+ shp->gd->nforks=0;
+ timerdel(NIL(void*));
+#ifdef JOBS
+ if(!job.jobcontrol && !(flags&FAMP))
+ sh_offstate(SH_MONITOR);
+ if(sh_isstate(SH_MONITOR))
+ {
+ parent = getpid();
+ if(postid==0)
+ job.curpgid = parent;
+ while(setpgid(0,job.curpgid)<0 && job.curpgid!=parent)
+ job.curpgid = parent;
+# ifdef SIGTSTP
+ if(job.curpgid==parent && !(flags&FAMP))
+ tcsetpgrp(job.fd,job.curpgid);
+# endif /* SIGTSTP */
+ }
+# ifdef SIGTSTP
+ if(job.jobcontrol)
+ {
+ signal(SIGTTIN,SIG_DFL);
+ signal(SIGTTOU,SIG_DFL);
+ signal(SIGTSTP,SIG_DFL);
+ }
+# endif /* SIGTSTP */
+ job.jobcontrol = 0;
+#endif /* JOBS */
+ job.toclear = 1;
+ shp->login_sh = 0;
+ sh_offoption(SH_LOGIN_SHELL);
+ sh_onstate(SH_FORKED);
+ sh_onstate(SH_NOLOG);
+ if (shp->fn_reset)
+ shp->fn_depth = shp->fn_reset = 0;
+#if SHOPT_ACCT
+ sh_accsusp();
+#endif /* SHOPT_ACCT */
+ /* Reset remaining signals to parent */
+ /* except for those `lost' by trap */
+ if(!(flags&FSHOWME))
+ sh_sigreset(2);
+ shp->subshell = 0;
+ shp->comsub = 0;
+ shp->spid = 0;
+ if((flags&FAMP) && shp->coutpipe>1)
+ sh_close(shp->coutpipe);
+ sig = shp->savesig;
+ shp->savesig = 0;
+ if(sig>0)
+ sh_fault(sig);
+ sh_sigcheck(shp);
+ usepipe=0;
+ return(0);
+}
+
+pid_t sh_fork(Shell_t *shp,int flags, int *jobid)
+{
+ register pid_t parent;
+ register int sig;
+ if(!shp->pathlist)
+ path_get(shp,"");
+ sfsync(NIL(Sfio_t*));
+ shp->trapnote &= ~SH_SIGTERM;
+ job_fork(-1);
+ shp->savesig = -1;
+ while(_sh_fork(shp,parent=fork(),flags,jobid) < 0);
+ sh_stats(STAT_FORKS);
+ if(!shp->subshell)
+ {
+ sig = shp->savesig;
+ shp->savesig = 0;
+ if(sig>0)
+ sh_fault(sig);
+ }
+ job_fork(parent);
+ return(parent);
+}
+
+struct Tdata
+{
+ Shell_t *sh;
+ Namval_t *tp;
+ void *extra[2];
+};
+
+/*
+ * add exports from previous scope to the new scope
+ */
+static void local_exports(register Namval_t *np, void *data)
+{
+ Shell_t *shp = ((struct Tdata*)data)->sh;
+ register Namval_t *mp;
+ register char *cp;
+ if(nv_isarray(np))
+ nv_putsub(np,NIL(char*),0);
+ if((cp = nv_getval(np)) && (mp = nv_search(nv_name(np), shp->var_tree, NV_ADD|HASH_NOSCOPE)) && nv_isnull(mp))
+ nv_putval(mp, cp, 0);
+}
+
+/*
+ * This routine executes .sh.math functions from within ((...)))
+*/
+Sfdouble_t sh_mathfun(Shell_t *shp,void *fp, int nargs, Sfdouble_t *arg)
+{
+ Sfdouble_t d;
+ Namval_t node,*mp,*np, *nref[9], **nr=nref;
+ char *argv[2];
+ struct funenv funenv;
+ int i;
+ np = (Namval_t*)fp;
+ funenv.node = np;
+ funenv.nref = nref;
+ funenv.env = 0;
+ memcpy(&node,SH_VALNOD,sizeof(node));
+ SH_VALNOD->nvfun = 0;
+ SH_VALNOD->nvenv = 0;
+ SH_VALNOD->nvflag = NV_LDOUBLE|NV_NOFREE;
+ SH_VALNOD->nvalue.ldp = 0;
+ for(i=0; i < nargs; i++)
+ {
+ *nr++ = mp = nv_namptr(shp->mathnodes,i);
+ mp->nvalue.ldp = arg++;
+ }
+ *nr = 0;
+ SH_VALNOD->nvalue.ldp = &d;
+ argv[0] = np->nvname;
+ argv[1] = 0;
+ sh_funscope(1,argv,0,&funenv,0);
+ while(mp= *nr++)
+ mp->nvalue.ldp = 0;
+ SH_VALNOD->nvfun = node.nvfun;
+ SH_VALNOD->nvflag = node.nvflag;
+ SH_VALNOD->nvenv = node.nvenv;
+ SH_VALNOD->nvalue.ldp = node.nvalue.ldp;
+ return(d);
+}
+
+/*
+ * This routine is used to execute the given function <fun> in a new scope
+ * If <fun> is NULL, then arg points to a structure containing a pointer
+ * to a function that will be executed in the current environment.
+ */
+int sh_funscope(int argn, char *argv[],int(*fun)(void*),void *arg,int execflg)
+{
+ register char *trap;
+ register int nsig;
+ register Shell_t *shp = sh_getinterp();
+ struct dolnod *argsav=0,*saveargfor;
+ struct sh_scoped savst, *prevscope = shp->st.self;
+ struct argnod *envlist=0;
+ int jmpval;
+ volatile int r = 0;
+ int n;
+ char *savstak;
+ struct funenv *fp = 0;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ Namval_t *nspace = shp->namespace;
+ Dt_t *last_root = shp->last_root;
+ Shopt_t options;
+#if SHOPT_NAMESPACE
+ Namval_t *np;
+#endif /* SHOPT_NAMESPACE */
+ options = shp->options;
+ if(shp->fn_depth==0)
+ shp->glob_options = shp->options;
+ else
+ shp->options = shp->glob_options;
+#if 0
+ shp->st.lineno = error_info.line;
+#endif
+ *prevscope = shp->st;
+ sh_offoption(SH_ERREXIT);
+ shp->st.prevst = prevscope;
+ shp->st.self = &savst;
+ shp->topscope = (Shscope_t*)shp->st.self;
+ shp->st.opterror = shp->st.optchar = 0;
+ shp->st.optindex = 1;
+ shp->st.loopcnt = 0;
+ if(!fun)
+ {
+ fp = (struct funenv*)arg;
+ shp->st.real_fun = (fp->node)->nvalue.rp;
+ envlist = fp->env;
+ }
+ prevscope->save_tree = shp->var_tree;
+ n = dtvnext(prevscope->save_tree)!= (shp->namespace?shp->var_base:0);
+#if SHOPT_NAMESPACE
+ if(n && fp && (np=(fp->node)->nvalue.rp->nspace) && np!=shp->namespace)
+ shp->namespace = np;
+#endif /* SHOPT_NAMESPACE */
+ sh_scope(shp,envlist,1);
+ if(n)
+ {
+ struct Tdata tdata;
+ memset(&tdata,0,sizeof(tdata));
+ tdata.sh = shp;
+ /* eliminate parent scope */
+ nv_scan(prevscope->save_tree, local_exports,&tdata, NV_EXPORT, NV_EXPORT|NV_NOSCOPE);
+ }
+ shp->st.save_tree = shp->var_tree;
+ if(!fun)
+ {
+ if(nv_isattr(fp->node,NV_TAGGED))
+ sh_onoption(SH_XTRACE);
+ else
+ sh_offoption(SH_XTRACE);
+ }
+ shp->st.cmdname = argv[0];
+ /* save trap table */
+ if((nsig=shp->st.trapmax*sizeof(char*))>0 || shp->st.trapcom[0])
+ {
+ nsig += sizeof(char*);
+ memcpy(savstak=stakalloc(nsig),(char*)&shp->st.trapcom[0],nsig);
+ }
+ sh_sigreset(0);
+ argsav = sh_argnew(shp,argv,&saveargfor);
+ sh_pushcontext(shp,buffp,SH_JMPFUN);
+ errorpush(&buffp->err,0);
+ error_info.id = argv[0];
+ shp->st.var_local = shp->var_tree;
+ if(!fun)
+ {
+ shp->st.filename = fp->node->nvalue.rp->fname;
+ shp->st.funname = nv_name(fp->node);
+ shp->last_root = nv_dict(DOTSHNOD);
+ nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
+ nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
+ }
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval == 0)
+ {
+ if(shp->fn_depth++ > MAXDEPTH)
+ {
+ shp->toomany = 1;
+ siglongjmp(*shp->jmplist,SH_JMPERRFN);
+ }
+ else if(fun)
+ r= (*fun)(arg);
+ else
+ {
+ char **arg = shp->st.real_fun->argv;
+ Namval_t *np, *nq, **nref;
+ if(nref=fp->nref)
+ {
+ shp->last_root = 0;
+ for(r=0; arg[r]; r++)
+ {
+ np = nv_search(arg[r],shp->var_tree,HASH_NOSCOPE|NV_ADD);
+ if(np && (nq=*nref++))
+ {
+ np->nvalue.nrp = newof(0,struct Namref,1,0);
+ np->nvalue.nrp->np = nq;
+ nv_onattr(np,NV_REF|NV_NOFREE);
+ }
+ }
+ }
+ sh_exec((Shnode_t*)(nv_funtree((fp->node))),execflg|SH_ERREXIT);
+ r = shp->exitval;
+ }
+ }
+ if(--shp->fn_depth==1 && jmpval==SH_JMPERRFN)
+ errormsg(SH_DICT,ERROR_exit(1),e_toodeep,argv[0]);
+ sh_popcontext(shp,buffp);
+ if (shp->st.self != &savst)
+ shp->var_tree = (Dt_t*)savst.save_tree;
+ sh_unscope(shp);
+ shp->namespace = nspace;
+ shp->var_tree = (Dt_t*)prevscope->save_tree;
+ if(shp->topscope != (Shscope_t*)shp->st.self)
+ sh_setscope(shp->topscope);
+ sh_argreset(shp,argsav,saveargfor);
+ trap = shp->st.trapcom[0];
+ shp->st.trapcom[0] = 0;
+ sh_sigreset(1);
+ if (shp->st.self != &savst)
+ *shp->st.self = shp->st;
+ shp->st = *prevscope;
+ shp->topscope = (Shscope_t*)prevscope;
+ nv_getval(sh_scoped(shp,IFSNOD));
+ if(nsig)
+ memcpy((char*)&shp->st.trapcom[0],savstak,nsig);
+ shp->trapnote=0;
+ if(nsig)
+ stakset(savstak,0);
+ shp->options = options;
+ shp->last_root = last_root;
+ if(jmpval == SH_JMPSUB)
+ siglongjmp(*shp->jmplist,jmpval);
+ if(trap)
+ {
+ sh_trap(trap,0);
+ free(trap);
+ }
+ if(jmpval)
+ r=shp->exitval;
+ if(r>SH_EXITSIG && ((r&SH_EXITMASK)==SIGINT || ((r&SH_EXITMASK)==SIGQUIT)))
+ sh_fault(r&SH_EXITMASK);
+ if(jmpval > SH_JMPFUN)
+ {
+ sh_chktrap(shp);
+ siglongjmp(*shp->jmplist,jmpval);
+ }
+ return(r);
+}
+
+static void sh_funct(Shell_t *shp,Namval_t *np,int argn, char *argv[],struct argnod *envlist,int execflg)
+{
+ struct funenv fun;
+ char *fname = nv_getval(SH_FUNNAMENOD);
+ struct Level *lp =(struct Level*)(SH_LEVELNOD->nvfun);
+ int level, pipepid=shp->pipepid, comsub=shp->comsub;
+ shp->comsub = 0;
+ shp->pipepid = 0;
+ sh_stats(STAT_FUNCT);
+ if(!lp->hdr.disc)
+ lp = init_level(shp,0);
+ if((struct sh_scoped*)shp->topscope != shp->st.self)
+ sh_setscope(shp->topscope);
+ level = lp->maxlevel = shp->dot_depth + shp->fn_depth+1;
+ SH_LEVELNOD->nvalue.s = lp->maxlevel;
+ shp->st.lineno = error_info.line;
+ if(nv_isattr(np,NV_FPOSIX))
+ {
+ char *save;
+ int loopcnt = shp->st.loopcnt;
+ shp->posix_fun = np;
+ save = argv[-1];
+ argv[-1] = 0;
+ shp->st.funname = nv_name(np);
+ shp->last_root = nv_dict(DOTSHNOD);
+ nv_putval(SH_FUNNAMENOD, nv_name(np),NV_NOFREE);
+ opt_info.index = opt_info.offset = 0;
+ error_info.errors = 0;
+ shp->st.loopcnt = 0;
+ b_dot_cmd(argn+1,argv-1,&shp->bltindata);
+ shp->st.loopcnt = loopcnt;
+ argv[-1] = save;
+ }
+ else
+ {
+ fun.env = envlist;
+ fun.node = np;
+ fun.nref = 0;
+ sh_funscope(argn,argv,0,&fun,execflg);
+ }
+ if(level-- != nv_getnum(SH_LEVELNOD))
+ {
+ Shscope_t *sp = sh_getscope(0,SEEK_END);
+ sh_setscope(sp);
+ }
+ lp->maxlevel = level;
+ SH_LEVELNOD->nvalue.s = lp->maxlevel;
+ shp->last_root = nv_dict(DOTSHNOD);
+ shp->comsub = comsub;
+#if 0
+ nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
+#else
+ nv_putval(SH_FUNNAMENOD,fname,NV_NOFREE);
+#endif
+ nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
+ shp->pipepid = pipepid;
+}
+
+/*
+ * external interface to execute a function without arguments
+ * <np> is the function node
+ * If <nq> is not-null, then sh.name and sh.subscript will be set
+ */
+int sh_fun(Namval_t *np, Namval_t *nq, char *argv[])
+{
+ Shell_t *shp = sh_getinterp();
+ register int offset;
+ register char *base;
+ Namval_t node;
+ struct Namref nr;
+ long mode;
+ char *prefix = shp->prefix;
+ int n=0;
+ char *av[3];
+ Fcin_t save;
+ fcsave(&save);
+ if((offset=staktell())>0)
+ base=stakfreeze(0);
+ shp->prefix = 0;
+ if(!argv)
+ {
+ argv = av+1;
+ argv[1]=0;
+ }
+ argv[0] = nv_name(np);
+ while(argv[n])
+ n++;
+ if(nq)
+ mode = set_instance(shp,nq,&node, &nr);
+ if(is_abuiltin(np))
+ {
+ int jmpval;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ Shbltin_t *bp = &shp->bltindata;
+ sh_pushcontext(shp,buffp,SH_JMPCMD);
+ jmpval = sigsetjmp(buffp->buff,1);
+ if(jmpval == 0)
+ {
+ bp->bnode = np;
+ bp->ptr = nv_context(np);
+ errorpush(&buffp->err,0);
+ error_info.id = argv[0];
+ opt_info.index = opt_info.offset = 0;
+ opt_info.disc = 0;
+ shp->exitval = 0;
+ shp->exitval = ((Shbltin_f)funptr(np))(n,argv,bp);
+ }
+ sh_popcontext(shp,buffp);
+ if(jmpval>SH_JMPCMD)
+ siglongjmp(*shp->jmplist,jmpval);
+ }
+ else
+ sh_funct(shp,np,n,argv,(struct argnod*)0,sh_isstate(SH_ERREXIT));
+ if(nq)
+ unset_instance(nq, &node, &nr, mode);
+ fcrestore(&save);
+ if(offset>0)
+ stakset(base,offset);
+ shp->prefix = prefix;
+ return(shp->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
+ */
+static void coproc_init(Shell_t *shp, int pipes[])
+{
+ int outfd;
+ if(shp->coutpipe>=0 && shp->cpid)
+ errormsg(SH_DICT,ERROR_exit(1),e_pexists);
+ shp->cpid = 0;
+ if(shp->cpipe[0]<=0 || shp->cpipe[1]<=0)
+ {
+ /* first co-process */
+ sh_pclose(shp->cpipe);
+ sh_pipe(shp->cpipe);
+ if((outfd=shp->cpipe[1]) < 10)
+ {
+ int fd=fcntl(shp->cpipe[1],F_DUPFD,10);
+ if(fd>=10)
+ {
+ shp->fdstatus[fd] = (shp->fdstatus[outfd]&~IOCLEX);
+ close(outfd);
+ shp->fdstatus[outfd] = IOCLOSE;
+ shp->cpipe[1] = fd;
+ }
+ }
+ if(fcntl(*shp->cpipe,F_SETFD,FD_CLOEXEC)>=0)
+ shp->fdstatus[shp->cpipe[0]] |= IOCLEX;
+ shp->fdptrs[shp->cpipe[0]] = shp->cpipe;
+
+ if(fcntl(shp->cpipe[1],F_SETFD,FD_CLOEXEC) >=0)
+ shp->fdstatus[shp->cpipe[1]] |= IOCLEX;
+ }
+ shp->outpipe = shp->cpipe;
+ sh_pipe(shp->inpipe=pipes);
+ shp->coutpipe = shp->inpipe[1];
+ shp->fdptrs[shp->coutpipe] = &shp->coutpipe;
+ if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0)
+ shp->fdstatus[shp->outpipe[0]] |= IOCLEX;
+}
+
+#if SHOPT_SPAWN
+
+
+#if SHOPT_AMP || !defined(_lib_fork)
+
+/*
+ * create a shell script consisting of t->fork.forktre and execute it
+ */
+static int run_subshell(Shell_t *shp,const Shnode_t *t,pid_t grp)
+{
+ static const char prolog[] = "(print $(typeset +A);set; typeset -p; print .sh.dollar=$$;set +o)";
+ register int i, fd, trace = sh_isoption(SH_XTRACE);
+ int pin,pout;
+ pid_t pid;
+ char *arglist[3], *envlist[2], devfd[12], *cp;
+ Sfio_t *sp = sftmp(0);
+ envlist[0] = "_=" SH_ID;
+ envlist[1] = 0;
+ arglist[0] = error_info.id?error_info.id:shp->shname;
+ if(*arglist[0]=='-')
+ arglist[0]++;
+ arglist[1] = devfd;
+ strncpy(devfd,e_devfdNN,sizeof(devfd));
+ arglist[2] = 0;
+ sfstack(sfstdout,sp);
+ if(trace)
+ sh_offoption(SH_XTRACE);
+ sfwrite(sfstdout,"typeset -A -- ",14);
+ sh_trap(prolog,0);
+ nv_scan(shp->fun_tree, print_fun, (void*)0,0, 0);
+ if(shp->st.dolc>0)
+ {
+ /* pass the positional parameters */
+ char **argv = shp->st.dolv+1;
+ sfwrite(sfstdout,"set --",6);
+ while(*argv)
+ sfprintf(sfstdout," %s",sh_fmtq(*argv++));
+ sfputc(sfstdout,'\n');
+ }
+ pin = (shp->inpipe?shp->inpipe[1]:0);
+ pout = (shp->outpipe?shp->outpipe[0]:0);
+ for(i=3; i < 10; i++)
+ {
+ if(shp->fdstatus[i]&IOCLEX && i!=pin && i!=pout)
+ {
+ sfprintf(sfstdout,"exec %d<&%d\n",i,i);
+ fcntl(i,F_SETFD,0);
+ }
+ }
+ sfprintf(sfstdout,"LINENO=%d\n",t->fork.forkline);
+ if(trace)
+ {
+ sfwrite(sfstdout,"set -x\n",7);
+ sh_onoption(SH_XTRACE);
+ }
+ sfstack(sfstdout,NIL(Sfio_t*));
+ sh_deparse(sp,t->fork.forktre,0);
+ sfseek(sp,(Sfoff_t)0,SEEK_SET);
+ fd = sh_dup(sffileno(sp));
+ cp = devfd+8;
+ if(fd>9)
+ *cp++ = '0' + (fd/10);
+ *cp++ = '0' + fd%10;
+ *cp = 0;
+ sfclose(sp);
+ sfsync(NIL(Sfio_t*));
+ if(!shp->gd->shpath)
+ shp->gd->shpath = pathshell();
+ pid = spawnveg(shp->shpath,arglist,envlist,grp);
+ close(fd);
+ for(i=3; i < 10; i++)
+ {
+ if(shp->fdstatus[i]&IOCLEX && i!=pin && i!=pout)
+ fcntl(i,F_SETFD,FD_CLOEXEC);
+ }
+ if(pid <=0)
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,arglist[0]);
+ return(pid);
+}
+#endif /* !_lib_fork */
+
+static void sigreset(Shell_t *shp,int mode)
+{
+ register char *trap;
+ register int sig=shp->st.trapmax;
+ while(sig-- > 0)
+ {
+ if(sig==SIGCHLD)
+ continue;
+ if((trap=shp->st.trapcom[sig]) && *trap==0)
+ signal(sig,mode?sh_fault:SIG_IGN);
+ }
+}
+
+/*
+ * A combined fork/exec for systems with slow or non-existent fork()
+ */
+static pid_t sh_ntfork(Shell_t *shp,const Shnode_t *t,char *argv[],int *jobid,int flag)
+{
+ static pid_t spawnpid;
+ static int savetype;
+ static int savejobid;
+ struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
+ int otype=0, jmpval,jobfork=0;
+ volatile int jobwasset=0, scope=0, sigwasset=0;
+ char **arge, *path;
+ volatile pid_t grp = 0;
+ Pathcomp_t *pp;
+ if(flag)
+ {
+ otype = savetype;
+ savetype=0;
+ }
+# if SHOPT_AMP || !defined(_lib_fork)
+ if(!argv)
+ {
+ register Shnode_t *tchild = t->fork.forktre;
+ int optimize=0;
+ otype = t->tre.tretyp;
+ savetype = otype;
+ spawnpid = 0;
+# ifndef _lib_fork
+ if((tchild->tre.tretyp&COMMSK)==TCOM)
+ {
+ Namval_t *np = (Namval_t*)(tchild->com.comnamp);
+ if(np)
+ {
+ path = nv_name(np);
+ if(!nv_isattr(np,BLT_ENV))
+ np=0;
+ else if(strcmp(path,"echo")==0 || memcmp(path,"print",5)==0)
+ np=0;
+ }
+ else if(!tchild->com.comarg)
+ optimize=1;
+ else if(tchild->com.comtyp&COMSCAN)
+ {
+ if(tchild->com.comarg->argflag&ARG_RAW)
+ path = tchild->com.comarg->argval;
+ else
+ path = 0;
+ }
+ else
+ path = ((struct dolnod*)tchild->com.comarg)->dolval[ARG_SPARE];
+ if(!np && path && !nv_search(path,shp->fun_tree,0))
+ optimize=1;
+ }
+# endif
+ sh_pushcontext(shp,buffp,SH_JMPIO);
+ jmpval = sigsetjmp(buffp->buff,0);
+ {
+ if((otype&FINT) && !sh_isstate(SH_MONITOR))
+ {
+ signal(SIGQUIT,SIG_IGN);
+ signal(SIGINT,SIG_IGN);
+ if(!shp->st.ioset)
+ {
+ sh_iosave(shp,0,buffp->topfd,(char*)0);
+ sh_iorenumber(shp,sh_chkopen(e_devnull),0);
+ }
+ }
+ if(otype&FPIN)
+ {
+ int fd = shp->inpipe[1];
+ sh_iosave(shp,0,buffp->topfd,(char*)0);
+ sh_iorenumber(shp,shp->inpipe[0],0);
+ if(fd>=0 && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(fd,F_SETFD,FD_CLOEXEC)>=0)
+ shp->fdstatus[fd] |= IOCLEX;
+ }
+ if(otype&FPOU)
+ {
+#if SHOPT_COSHELL
+ if(shp->outpipe[2] > 20000)
+ sh_coaccept(shp,shp->outpipe,1);
+#endif /* SHOPT_COSHELL */
+ sh_iosave(shp,1,buffp->topfd,(char*)0);
+ sh_iorenumber(shp,sh_dup(shp->outpipe[1]),1);
+ if(fcntl(shp->outpipe[0],F_SETFD,FD_CLOEXEC)>=0)
+ shp->fdstatus[shp->outpipe[0]] |= IOCLEX;
+ }
+
+ if(t->fork.forkio)
+ sh_redirect(shp,t->fork.forkio,0);
+ if(optimize==0)
+ {
+#ifdef SIGTSTP
+ if(job.jobcontrol)
+ {
+ signal(SIGTTIN,SIG_DFL);
+ signal(SIGTTOU,SIG_DFL);
+ }
+#endif /* SIGTSTP */
+#ifdef JOBS
+ if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
+ {
+ if((otype&FAMP) || job.curpgid==0)
+ grp = 1;
+ else
+ grp = job.curpgid;
+ }
+#endif /* JOBS */
+ spawnpid = run_subshell(shp,t,grp);
+ }
+ else
+ {
+ sh_exec(tchild,SH_NTFORK);
+ if(jobid)
+ *jobid = savejobid;
+ }
+ }
+ sh_popcontext(shp,buffp);
+ if((otype&FINT) && !sh_isstate(SH_MONITOR))
+ {
+ signal(SIGQUIT,sh_fault);
+ signal(SIGINT,sh_fault);
+ }
+ if((otype&FPIN) && (!(otype&FPOU) || (otype&FCOOP)) && fcntl(shp->inpipe[1],F_SETFD,FD_CLOEXEC)>=0)
+ shp->fdstatus[shp->inpipe[1]] &= ~IOCLEX;
+ if(t->fork.forkio || otype)
+ sh_iorestore(shp,buffp->topfd,jmpval);
+ if(optimize==0)
+ {
+#ifdef SIGTSTP
+ if(job.jobcontrol)
+ {
+ signal(SIGTTIN,SIG_IGN);
+ signal(SIGTTOU,SIG_IGN);
+ }
+#endif /* SIGTSTP */
+ if(spawnpid>0)
+ _sh_fork(shp,spawnpid,otype,jobid);
+ if(grp>0 && !(otype&FAMP))
+ {
+ while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
+ job.curpgid = spawnpid;
+ }
+ }
+ savetype=0;
+ if(jmpval>SH_JMPIO)
+ siglongjmp(*shp->jmplist,jmpval);
+ if(spawnpid<0 && (otype&FCOOP))
+ {
+ sh_close(shp->coutpipe);
+ sh_close(shp->cpipe[1]);
+ shp->cpipe[1] = -1;
+ shp->coutpipe = -1;
+ }
+ shp->exitval = 0;
+ return(spawnpid);
+ }
+# endif /* !_lib_fork */
+ sh_pushcontext(shp,buffp,SH_JMPCMD);
+ errorpush(&buffp->err,ERROR_SILENT);
+ jmpval = sigsetjmp(buffp->buff,0);
+ if(jmpval == 0)
+ {
+ if((otype&FINT) && !sh_isstate(SH_MONITOR))
+ {
+ signal(SIGQUIT,SIG_IGN);
+ signal(SIGINT,SIG_IGN);
+ }
+ spawnpid = -1;
+ if(t->com.comio)
+ sh_redirect(shp,t->com.comio,0);
+ error_info.id = *argv;
+ if(t->com.comset)
+ {
+ scope++;
+ sh_scope(shp,t->com.comset,0);
+ }
+ if(!strchr(path=argv[0],'/'))
+ {
+ Namval_t *np;
+ if((np=nv_search(path,shp->track_tree,0)) && !nv_isattr(np,NV_NOALIAS) && np->nvalue.cp)
+ path = nv_getval(np);
+ else if(path_absolute(shp,path,NIL(Pathcomp_t*)))
+ {
+ path = stkptr(shp->stk,PATH_OFFSET);
+ stkfreeze(shp->stk,0);
+ }
+ else
+ {
+ pp=path_get(shp,path);
+ while(pp)
+ {
+ if(pp->len==1 && *pp->name=='.')
+ break;
+ pp = pp->next;
+ }
+ if(!pp)
+ path = 0;
+ }
+ }
+ else if(sh_isoption(SH_RESTRICTED))
+ errormsg(SH_DICT,ERROR_exit(1),e_restricted,path);
+ if(!path)
+ {
+ spawnpid = -1;
+ goto fail;
+ }
+ arge = sh_envgen();
+ shp->exitval = 0;
+#ifdef SIGTSTP
+ if(job.jobcontrol)
+ {
+ signal(SIGTTIN,SIG_DFL);
+ signal(SIGTTOU,SIG_DFL);
+ jobwasset++;
+ }
+#endif /* SIGTSTP */
+#ifdef JOBS
+ if(sh_isstate(SH_MONITOR) && (job.jobcontrol || (otype&FAMP)))
+ {
+ if((otype&FAMP) || job.curpgid==0)
+ grp = 1;
+ else
+ grp = job.curpgid;
+ }
+#endif /* JOBS */
+
+ sfsync(NIL(Sfio_t*));
+ sigreset(shp,0); /* set signals to ignore */
+ sigwasset++;
+ /* find first path that has a library component */
+ for(pp=path_get(shp,argv[0]); pp && !pp->lib ; pp=pp->next);
+ job_fork(-1);
+ jobfork = 1;
+ spawnpid = path_spawn(shp,path,argv,arge,pp,(grp<<1)|1);
+ if(spawnpid < 0 && errno==ENOEXEC)
+ {
+ char *devfd;
+ int fd = open(path,O_RDONLY);
+ argv[-1] = argv[0];
+ argv[0] = path;
+ if(fd>=0)
+ {
+ struct stat statb;
+ sfprintf(shp->strbuf,"/dev/fd/%d",fd);
+ if(stat(devfd=sfstruse(shp->strbuf),&statb)>=0)
+ argv[0] = devfd;
+ }
+ if(!shp->gd->shpath)
+ shp->gd->shpath = pathshell();
+ spawnpid = path_spawn(shp,shp->gd->shpath,&argv[-1],arge,pp,(grp<<1)|1);
+ if(fd>=0)
+ close(fd);
+ argv[0] = argv[-1];
+ }
+ fail:
+ if(jobfork && spawnpid<0)
+ job_fork(0);
+ if(spawnpid < 0) switch(errno=shp->path_err)
+ {
+ case ENOENT:
+ errormsg(SH_DICT,ERROR_system(ERROR_NOENT),e_found+4);
+ default:
+ errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec+4);
+ }
+ }
+ else
+ exitset();
+ sh_popcontext(shp,buffp);
+ if(buffp->olist)
+ free_list(buffp->olist);
+#ifdef SIGTSTP
+ if(jobwasset)
+ {
+ signal(SIGTTIN,SIG_IGN);
+ signal(SIGTTOU,SIG_IGN);
+ }
+#endif /* SIGTSTP */
+ if(sigwasset)
+ sigreset(shp,1); /* restore ignored signals */
+ if(scope)
+ {
+ sh_unscope(shp);
+ if(jmpval==SH_JMPSCRIPT)
+ nv_setlist(t->com.comset,NV_EXPORT|NV_IDENT|NV_ASSIGN,0);
+ }
+ if(t->com.comio && (jmpval || spawnpid<=0))
+ sh_iorestore(shp,buffp->topfd,jmpval);
+ if(jmpval>SH_JMPCMD)
+ siglongjmp(*shp->jmplist,jmpval);
+ if(spawnpid>0)
+ {
+ _sh_fork(shp,spawnpid,otype,jobid);
+ job_fork(spawnpid);
+#ifdef JOBS
+ if(grp==1)
+ job.curpgid = spawnpid;
+# ifdef SIGTSTP
+ if(grp>0 && !(otype&FAMP))
+ {
+ while(tcsetpgrp(job.fd,job.curpgid)<0 && job.curpgid!=spawnpid)
+ job.curpgid = spawnpid;
+ }
+# endif /* SIGTSTP */
+#endif /* JOBS */
+ savejobid = *jobid;
+ if(otype)
+ return(0);
+ }
+ return(spawnpid);
+}
+
+# ifdef _was_lib_fork
+# define _lib_fork 1
+# endif
+# ifndef _lib_fork
+ pid_t fork(void)
+ {
+ errormsg(SH_DICT,ERROR_exit(3),e_notimp,"fork");
+ return(-1);
+ }
+# endif /* _lib_fork */
+#endif /* SHOPT_SPAWN */
diff --git a/src/cmd/ksh93/shell.3 b/src/cmd/ksh93/shell.3
new file mode 100644
index 0000000..8a27482
--- /dev/null
+++ b/src/cmd/ksh93/shell.3
@@ -0,0 +1,414 @@
+.fp 5 CW
+.TH SHELL 3 "28 Feb 2003" AST
+.SH NAME
+\fBshell\fR \- a \f5ksh\fP library interface
+.SH SYNOPSIS
+.ta .8i 1.6i 2.4i 3.2i 4.0i 4.8i 5.6i
+.SS "HEADERS/LIBRARIES"
+.nf
+.ft 5
+#include <shell.h>
+libshell.a -lshell
+.ft R
+.fi
+.SS "DATA TYPES"
+.nf
+.ft 5
+Shell_t;
+Shopt_t;
+Shscope_t;
+Shbltin_t;
+Shbltin_f;
+Shinit_f;
+Shwait_f;
+.ft R
+.fi
+.SS "FUNCTIONS"
+.nf
+.ft 5
+int sh_main(int \fIargc\fP, char *\fIargv\fP[], Sh_init \fIfn\fP);
+Shell_t *sh_init(int \fIargc\fP, char *\fIargv\fP[]);
+Shell_t *sh_getinterp(void);
+
+Namval_t *sh_addbuiltin(const char *\fIname\fP,Sh_bltin_f \fIfn\fP,void *\fIarg\fP);
+
+unsigned int sh_isoption(int \fIoption\fP);
+unsigned int sh_onoption(int \fIoption\fP);
+unsigned int sh_offoption(int \fIoption\fP);
+
+void *sh_parse(Shell_t *\fIshp\fP, Sfio_t *\fIsp\fP, int \fIflags\fP);
+int sh_trap(const char *\fIstring\fP, int \fImode\fP);
+int sh_run(int \fIargc\fP, char *\fIargv\fP[]);
+int sh_eval(Sfio_t *\fIsp\fP,int \fImode\fP);
+int sh_fun(Namval_t *\fIfunnode\fP, Namval_t *\fIvarnode\fP, char *\fIargv\fP[]);
+int sh_funscope(int \fIargc\fP,char *\fIargv\fP[],int(*\fIfn\fP)(void*),void *\fIarg\fP,int \fIflags\fP);
+Shscope_t *sh_getscope(int \fIindex\fP,int \fIwhence\fP);
+Shscope_t *sh_setscope(Shscope_t *\fIscope\fP);
+
+int (*sh_fdnotify(int(*\fIfn\fP)(int,int)))(int,int);
+char *sh_fmtq(const char *\fIstring\fP);
+void *sh_waitnotify(Shwait_f \fIfn\fP);
+void sh_delay(double \fIsec\fP);
+Sfio_t *sh_iogetiop(int \fIfd\fP, int \fImode\fP);
+int sh_sigcheck(void);
+.ft R
+.fi
+.SH DESCRIPTION
+The \fIShell\fP library is a set of functions used for
+writing extensions to \f5ksh\fP or writing commands
+that embed shell command processing.
+The include file \f5<shell.h>\fP contains the type definitions,
+function prototypes and symbolic constants defined by
+this interface. It also defines replacement definitions for
+the standard library functions
+\f5access()\fP,
+\f5close()\fP,
+\f5dup()\fP,
+\f5exit()\fP,
+\f5fcntl()\fP,
+\f5lseek()\fP,
+\f5open()\fP,
+\f5pipe()\fP,
+\f5read()\fP,
+and
+\f5write()\fP
+that must be used
+with all code
+intended to be compiled as built-in commands.
+.P
+The \f5<shell.h>\fP header includes \f5<ast.h>\fP which
+in turn includes the standard include files, \f5<stddef.h>\fP,
+\f5<stdlib.h>\fP, \f5<stdarg.h>\fP, \f5<limits.h>\fP,
+\f5<stdio.h>\fP, \f5<string.h>\fP, \f5<unistd.h>\fP,
+\f5<sys/types.h>\fP, \f5<fcntl.h>\fP, and \f5<locale.h>\fP.
+The \f5<shell.h>\fP header also includes the headers
+\f5<cdt.h>\fP,
+\f5<cmd.h>\fP,
+\f5<sfio.h>\fP,
+\f5<nval.h>\fP,
+\f5<stk.h>\fP,
+and \f5<error.h>\fP
+so that in most cases, programs only require the single
+header \f5<shell.h>\fP.
+.PP
+Programs can use this library in one of the following ways:
+.PD 0
+.TP
+.B 1
+To write builtin commands and/or other code that will be loaded
+into the shell by loading dynamic libraries
+at run time using the \f5builtin\fP(1) command.
+In this case the shell will look for a function named \f5lib_init\fP
+in your library and, if found, will execute this function with
+two arguments. The first
+argument will be an \f5int\fP with value \f50\fP when the library is loaded.
+The second argument will contain a pointer to a structure of type
+\f5Shbltin_t\fP.
+In addition, for each argument named on the \f5builtin\fP
+command line, it will look for a function named \f5b_\fP\fIname\fP\f5()\fP
+in your library and will \fIname\fP as a built-in.
+.TP
+.B 2
+To build separate a separate command that uses the shell as a
+library at compile or run time.
+In this case the \f5sh_init()\fP function must be called to
+initialize this library before any other commands in this library
+are invoked.
+The arguments \fIargc\fP and \fIargv\fP are the number
+of arguments and the vector of arguments as supplied by the shell.
+It returns a pointer the \f5Shell_t\fP.
+.TP
+.B 3
+To build a new version of \f5ksh\fP with extended capabilities,
+for example \f5tksh\fP(1).
+In this case, the user writes a \f5main()\fP function that
+calls \f5sh_main()\fP with the \fIargc\fP and \fIargv\fP arguments
+from \f5main\fP and pointer to function, \fIfn\fP as a third
+argument.. The function \fIfn\fP will
+be invoked with argument \f50\fP after \f5ksh\fP has done initialization,
+but before \f5ksh\fP has processed any start up files or executed
+any commands. The function \fIfn\fP
+will be invoked with an argument of \f51\fP before \f5ksh\fP
+begins to execute a script that has been invoked by name
+since \f5ksh\fP cleans up memory and long jumps back to
+the beginning of the shell in this case.
+The function \fIfn\fP will be called with argument \f5-1\fP before
+the shell exits.
+.PD
+.PP
+The \f5Shell_t\fP structure contains the following fields:
+.nf
+.ft 5
+ Shopt_t \fIoptions\fP; \fR/* set -o options */\fP
+ Dt_t *\fIvar_tree\fP; \fR/* shell variable dictionary */\fP
+ Dt_t *\fIfun_tree\fP; \fR/* shell function dictionary */\fP
+ Dt_t *\fIalias_tree\fP; \fR/* shell alias dictionary */\fP
+ Dt_t *\fIbltin_tree\fP; \fR/* shell built-in dictionary */\fP
+ Shscope_t *\fItopscope\fP; \fR/* pointer to top-level scope */\fP
+ char *\fIinfile_name\fP; \fR/* path name of current input file*/\fP
+ int \fIinlineno\fP; \fR/* line number of current input file*/\fP
+ int \fIexitval\fP; \fR/* most recent exit value*/\fP
+.ft R
+.fi
+This structure is returned by \f5sh_init()\fP but can also be retrieved
+by a call to \f5sh_getinterp()\fP.
+.PP
+All built-in commands to the shell are invoked with
+three arguments. The first two arguments give the
+number of arguments and the argument list
+and uses the same conventions as the \f5main()\fP function
+of a program. The third argument is a pointer to a structure
+of type \f5Shbltin_t\fP. This structure contains \f5shp\fP which is a pointer
+to the shell interpreter, and \f5ptr\fP which is a pointer that
+can be associated with each built-in.
+The \f5sh_addbuiltin()\fP function is used to add, replace or delete
+built-in commands.
+It takes the name of the built-in, \fIname\fP, a pointer
+to the function that implements the built-in, \fIfn\fP, and
+a pointer that will be passed to the function in the \f5ptr\fP field when
+it is invoked.
+If, \fIfn\fP is non-\f5NULL\fP the built-in command
+is added or replaced. Otherwise, \f5sh_addbuiltin()\fP will
+return a pointer to the built-in if it exists or \f5NULL\fP otherwise.
+If \fIarg\fP is \f5(void*)1\fP the built-in will be deleted.
+The \fIname\fP argument can be in the format of a pathname.
+It cannot be the name of any of the special built-in commands.
+If \fIname\fP contains a \f5/\fP, the built-in is the basename of
+the pathname and the built-in will only be executed
+if the given pathname is encountered when performing
+a path search.
+When adding or replacing a built-in,
+\f5sh_addbuiltin()\fP function returns a pointer to
+the name-value pair corresponding to the built-in on success and \f5NULL\fP
+if it is unable to add or replace the built-in.
+When deleting a built-in, \f5NULL\fP is returned on success or
+if not found, and the name-value pair pointer is returned if the built-in
+cannot be deleted.
+.PP
+The functions \f5sh_onoption()\fP, \f5sh_offoption()\fP, \f5sh_isoption()\fP
+are used to set, unset, and test for shell options respectively.
+The \fIoption\fP argument can be any one of the following:
+.IP
+\f5SH_ALLEXPORT\fP:
+The \f5NV_EXPORT\fP attribute is given to each variable whose
+name is an identifier when a value is assigned.
+.IP
+\f5SH_BGNICE\fP:
+Each background process is run at a lower priority.
+.IP
+\f5SH_ERREXIT\fP:
+Causes a non-interactive shell to exit when a command,
+other than a conditional command, returns non-zero.
+.IP
+\f5SH_EMACS\fP:
+The emacs editing mode.
+.IP
+\f5SH_GMACS\fP:
+Same as the emacs editing mode except for the behavior of CONTROL-T.
+.IP
+\f5SH_HISTORY\fP:
+Indicates that the history file has been created and that
+commands can be logged.
+.IP
+\f5SH_IGNOREEOF\fP:
+Do not treat end-of-file as exit.
+.IP
+\f5SH_INTERACTIVE\fP:
+.IP
+Set for interactive shells.
+Do not set or unset this option.
+\f5SH_MARKDIRS\fP:
+A \fB/\fP is added to the end of each directory generated by pathname
+expansion.
+.IP
+\f5SH_MONITOR\fP:
+Indicates that the monitor option is enabled for job control.
+.IP
+\f5SH_NOCLOBBER\fP:
+The \fB>\fP redirection will fail if the file exists. Each file
+created with \fB>\fP will have the \f5O_EXCL\fP bit set as described
+in \f5<fcntl.h>\fP
+.IP
+\f5SH_NOGLOB\fP:
+Do not perform pathname expansion.
+.IP
+\f5SH_NOLOG\fP:
+Do not save function definitions in the history file.
+.IP
+\f5SH_NOTIFY\fP:
+Cause a message to be generated as soon as each background job completes.
+.IP
+\f5SH_NOUNSET\fP:
+Cause the shell to fail with an error of an unset variable is
+referenced.
+.IP
+\f5SH_PRIVILEGED\fP:
+.IP
+\f5SH_VERBOSE\fP:
+Cause each line to be echoed as it is read by the parser.
+.IP
+\f5SH_XTRACE\fP:
+Cause each command to be displayed after all expansions, but
+before execution.
+.IP
+\f5SH_VI\fP:
+The vi edit mode.
+.IP
+\f5SH_VIRAW\fP:
+Read character at a time rather than line at a time when
+in vi edit mode.
+.IP
+.PP
+The \f5sh_trap()\fP function can be used to compile and execute
+a string or file.
+A value of \f50\fP for \fImode\fP indicates that \fIname\fP
+refers to a string. A value of \f51\fP for \fImode\fP
+indicates that \fIname\fP is an \f5Sfio_t*\fP to an open stream.
+A value of \f52\fP for \fImode\fP indicates that \fIname\fP
+points to a parse tree that has been returned by \f5sh_parse()\fP.
+The complete file associated with the string or file
+is compiled and then executed so that aliases defined
+within the string or file will not take effect until
+the next command is executed.
+.PP
+The \f5sh_run()\fP function will run the command given by
+by the argument list \fIargv\fP containing \fIargc\fP elements.
+If \fIargv\fP\f5[0]\fP does not contain a \f5/\fP, it will
+be checked to see if it is a built-in or function before
+performing a path search.
+.PP
+The \f5sh_eval()\fP function executes a string or file
+stream \fIsp\fP.
+If \fImode\fP is non-zero and the history file has
+been created, the stream defined by \fIsp\fP
+will be appended to the history file as a command.
+.PP
+The \f5sh_parse()\fP function takes a pointer to the
+shell interpreter \fIshp\fP, a pointer to a string or file stream
+\fIsp\fP, and compilation flags, and returns a pointer
+to a parse tree of the compiled stream. This pointer can
+be used in subsequent calls to \f5sh_trap()\fP.
+The compilation flags can be zero or more of the following:
+.IP
+\f5SH_NL\fP:
+Treat new-lines as \fB;\fP.
+.IP
+\f5SH_EOF\fP:
+An end of file causes syntax error. By default it will
+be treated as a new-line.
+.PP
+\f5ksh\fP executes each function defined with the \f5function\fP
+reserved word in a separate scope. The \f5Shscope_t\fP type
+provides an interface to some of the information that
+is available on each scope. The structure contains
+the following public members:
+.nf
+ \f5Sh_scope_t *par_scope;\fP
+ \f5int argc;\fP
+ \f5char **argv;\fP
+ \f5char *cmdname;\fP
+ \f5Dt_t *var_tree;\fP
+.fi
+The \f5sh_getscope()\fP function can be used to the the
+scope information associated with existing scope.
+Scopes are numbered from \f50\fP for the global scope
+up to the current scope level. The \fIwhence\fP
+argument uses the symbolic constants associated with \f5lseek()\fP
+to indicate whether the \f5Iscope\fP argument is absolute,
+relative to the current scope, or relative to the topmost scope.
+The\f5sh_setscope()\fP function can be used to make a
+a known scope the current scope. It returns a pointer to the
+old current scope.
+.PP
+The \f5sh_funscope()\fP function can be used to run a function
+in a new scope. The arguments \fIargc\fP and \fIargv\fP
+are the number of arguments and the list of arguments
+respectively. If \fIfn\fP is non-\f5NULL\fP, then
+this function is invoked with \fIargc\fP, \fIargv\fP, and \fIarg\fP
+as arguments.
+.PP
+The \f5sh_fun()\fP function can be called within a
+discipline function or built-in extension to execute a
+discipline function script.
+The argument \fIfunnode\fP is a pointer to the shell function
+or built-in to execute.
+The argument \fIvarnode\fP is a pointer to the name
+value pair that has defined this discipline.
+The array \fIargv\fP is a \f5NULL\fP terminated list of
+arguments that are passed to the function.
+.PP
+By default, \f5ksh\fP only records but does not act
+on signals when running a built-in command.
+If a built-in takes a substantial amount of time
+to execute, then it should check for interrupts
+periodically by calling \f5sh_sigcheck()\fP.
+If a signal is pending, \f5sh_sigcheck()\fP will exit
+the function you are calling and return to the point
+where the most recent built-in was invoked, or where
+\f5sh_eval()\fP or \f5sh_trap()\fP was called.
+.PP
+The \f5sh_delay()\fP function is used to cause the
+shell to sleep for a period of time defined by \fIsec\fP.
+.PP
+The \f5sh_fmtq()\fP function can be used to convert a string
+into a string that is quoted so that it can be reinput
+to the shell. The quoted string returned by \f5sh_fmtq\fP
+may be returned on the current stack, so that it
+must be saved or copied.
+.PP
+The \f5sh_fdnotify()\fP function causes the function \fIfn\fP
+to be called whenever the shell duplicates or closes a file.
+It is provided for extensions that need to keep track of
+file descriptors that could be changed by shell commands.
+The function \fIfn\fP is called with two arguments.
+The first argument is the original file descriptor. The
+second argument is the new file descriptor for duplicating
+files, and \f5SH_FDCLOSE\fP when a file has been closed.
+The previously installed \f5sh_fdnotify()\fP function pointer
+is returned.
+.PP
+The \f5sh_waitnotify()\fP function causes the function \fIfn\fP
+to be called whenever the shell is waiting for input from
+a slow device or waiting for a process to complete.
+This function can process events and run shell commands
+until there is input, the timer is reached or a signal arises.
+It is called with three arguments. The first is the file
+descriptor from which the shell trying to read or \f5\-1\fP
+if the shell is waiting for a process to complete.
+The second is a timeout in milliseconds.
+A value of \f5\-1\fP for the timeout means that
+no timeout should be set.
+The third argument is 0 for input file descriptors
+and 1 for output file descriptor.
+The function needs to return a value \f5>0\fP if there
+is input on the file descriptor, and a value \f5<0\fP
+if the timeout is reached or a signal has occurred.
+A value of \f50\fP indicates
+that the function has returned without processing and that the shell
+should wait for input or process completion.
+The previous installed \f5sh_waitnotify()\fP function pointer is returned.
+.PP
+The \f5sh_iogetiop()\fP function returns a pointer to the
+Sfio stream corresponding to file descriptor number \fIfd\fP
+and the given mode \fImode\fP. The mode can be either
+\f5SF_READ\fP or \f5SF_WRITE\fP.
+The \fIfd\fP argument can the number of an open file descriptor or
+one of the following symbolic constants:
+.IP
+\f5SH_IOCOPROCESS\fP:
+The stream corresponding to the most recent co-process.
+.IP
+\f5SH_IOHISTFILE\fP:
+The stream corresponding to the history file.
+If no stream exists corresponding to \fIfd\fP or the stream
+can not be accessed in the specified mode, \f5NULL\fP is returned.
+.SH SEE ALSO
+builtin(1)
+cdt(3)
+error(3)
+nval(3)
+sfio(3)
+stk(3)
+tksh(1)
+.SH AUTHOR
+David G. Korn (dgk@research.att.com).
diff --git a/src/cmd/ksh93/tests/alias.sh b/src/cmd/ksh93/tests/alias.sh
new file mode 100755
index 0000000..5a75fa3
--- /dev/null
+++ b/src/cmd/ksh93/tests/alias.sh
@@ -0,0 +1,102 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+alias foo='print hello'
+if [[ $(foo) != hello ]]
+then err_exit 'foo, where foo is alias for "print hello" failed'
+fi
+if [[ $(foo world) != 'hello world' ]]
+then err_exit 'foo world, where foo is alias for "print hello" failed'
+fi
+alias foo='print hello '
+alias bar=world
+if [[ $(foo bar) != 'hello world' ]]
+then err_exit 'foo bar, where foo is alias for "print hello " failed'
+fi
+if [[ $(foo \bar) != 'hello bar' ]]
+then err_exit 'foo \bar, where foo is alias for "print hello " failed'
+fi
+alias bar='foo world'
+if [[ $(bar) != 'hello world' ]]
+then err_exit 'bar, where bar is alias for "foo world" failed'
+fi
+if [[ $(alias bar) != "bar='foo world'" ]]
+then err_exit 'alias bar, where bar is alias for "foo world" failed'
+fi
+unalias foo || err_exit "unalias foo failed"
+alias foo 2> /dev/null && err_exit "alias for non-existent alias foo returns true"
+unset bar
+alias bar="print foo$bar"
+bar=bar
+if [[ $(bar) != foo ]]
+then err_exit 'alias bar, where bar is alias for "print foo$bar" failed'
+fi
+unset bar
+alias bar='print hello'
+if [[ $bar != '' ]]
+then err_exit 'alias bar cause variable bar to be set'
+fi
+alias !!=print
+if [[ $(!! hello 2>/dev/null) != hello ]]
+then err_exit 'alias for !!=print not working'
+fi
+alias foo=echo
+if [[ $(print "$(foo bar)" ) != bar ]]
+then err_exit 'alias in command substitution not working'
+fi
+( unalias foo)
+if [[ $(foo bar 2> /dev/null) != bar ]]
+then err_exit 'alias not working after unalias in subshell'
+fi
+builtin -d rm 2> /dev/null
+if whence rm > /dev/null
+then [[ ! $(alias -t | grep rm= ) ]] && err_exit 'tracked alias not set'
+ PATH=$PATH
+ [[ $(alias -t | grep rm= ) ]] && err_exit 'tracked alias not cleared'
+fi
+if hash -r 2>/dev/null && [[ ! $(hash) ]]
+then PATH=$tmp:/bin:/usr/bin
+ for i in foo -foo --
+ do print ':' > $tmp/$i
+ chmod +x $tmp/$i
+ hash -r -- $i 2>/dev/null || err_exit "hash -r -- $i failed"
+ [[ $(hash) == $i=$tmp/$i ]] || err_exit "hash -r -- $i failed, expected $i=$tmp/$i, got $(hash)"
+ done
+else err_exit 'hash -r failed'
+fi
+( alias :pr=print) 2> /dev/null || err_exit 'alias beginning with : fails'
+( alias p:r=print) 2> /dev/null || err_exit 'alias with : in name fails'
+
+unalias no_such_alias && err_exit 'unalias should return non-zero for unknown alias'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/append.sh b/src/cmd/ksh93/tests/append.sh
new file mode 100755
index 0000000..80a7f25
--- /dev/null
+++ b/src/cmd/ksh93/tests/append.sh
@@ -0,0 +1,86 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+{
+x=abc
+x+=def ;} 2> /dev/null
+if [[ $x != abcdef ]]
+then err_exit 'abc+def != abcdef'
+fi
+integer i=3
+{ i+=4;} 2> /dev/null
+if (( i != 7 ))
+then err_exit '3+4!=7'
+fi
+iarray=( one two three )
+{ iarray+= (four five six) ;} 2> /dev/null
+if [[ ${iarray[@]} != 'one two three four five six' ]]
+then err_exit 'index array append fails'
+fi
+unset iarray
+iarray=one
+{ iarray+= (four five six) ;} 2> /dev/null
+if [[ ${iarray[@]} != 'one four five six' ]]
+then err_exit 'index array append to scalar fails'
+fi
+typeset -A aarray
+aarray=( [1]=1 [3]=4 [xyz]=xyz )
+aarray+=( [2]=2 [3]=3 [foo]=bar )
+if [[ ${aarray[3]} != 3 ]]
+then err_exit 'associative array append fails'
+fi
+if [[ ${#aarray[@]} != 5 ]]
+then err_exit 'number of elements of associative array append fails'
+fi
+point=(x=1 y=2)
+point+=( y=3 z=4)
+if [[ ${point.y} != 3 ]]
+then err_exit 'compound append fails'
+fi
+if [[ ${point.x} != 1 ]]
+then err_exit 'compound append to compound variable unsets existing variables'
+fi
+unset foo
+foo=one
+foo+=(two)
+if [[ ${foo[@]} != 'one two' ]]
+then err_exit 'array append to non array variable fails'
+fi
+unset foo
+foo[0]=(x=3)
+foo+=(x=4)
+[[ ${foo[1].x} == 4 ]] || err_exit 'compound append to index array not working'
+[[ ${foo[0].x} == 3 ]] || err_exit 'compound append to index array unsets existing variables'
+
+unset foo
+foo=a
+foo+=''
+[[ $foo == 'a' ]] || err_exit 'appending an empty string not working'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/arith.sh b/src/cmd/ksh93/tests/arith.sh
new file mode 100755
index 0000000..4d48ac2
--- /dev/null
+++ b/src/cmd/ksh93/tests/arith.sh
@@ -0,0 +1,737 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+trap '' FPE # NOTE: osf.alpha requires this (no ieee math)
+
+integer x=1 y=2 z=3
+if (( 2+2 != 4 ))
+then err_exit 2+2!=4
+fi
+if ((x+y!=z))
+then err_exit x+y!=z
+fi
+if (($x+$y!=$z))
+then err_exit $x+$y!=$z
+fi
+if (((x|y)!=z))
+then err_exit "(x|y)!=z"
+fi
+if ((y >= z))
+then err_exit "y>=z"
+fi
+if ((y+3 != z+2))
+then err_exit "y+3!=z+2"
+fi
+if ((y<<2 != 1<<3))
+then err_exit "y<<2!=1<<3"
+fi
+if ((133%10 != 3))
+then err_exit "133%10!=3"
+ if (( 2.5 != 2.5 ))
+ then err_exit 2.5!=2.5
+ fi
+fi
+d=0
+((d || 1)) || err_exit 'd=0; ((d||1))'
+if (( d++!=0))
+then err_exit "d++!=0"
+fi
+if (( --d!=0))
+then err_exit "--d!=0"
+fi
+if (( (d++,6)!=6 && d!=1))
+then err_exit '(d++,6)!=6 && d!=1'
+fi
+d=0
+if (( (1?2+1:3*4+d++)!=3 || d!=0))
+then err_exit '(1?2+1:3*4+d++) !=3'
+fi
+for ((i=0; i < 20; i++))
+do :
+done
+if (( i != 20))
+then err_exit 'for (( expr)) failed'
+fi
+for ((i=0; i < 20; i++)); do : ; done
+if (( i != 20))
+then err_exit 'for (( expr));... failed'
+fi
+for ((i=0; i < 20; i++)) do : ; done
+if (( i != 20))
+then err_exit 'for (( expr))... failed'
+fi
+if (( (i?0:1) ))
+then err_exit '(( (i?0:1) )) failed'
+fi
+if (( (1 || 1 && 0) != 1 ))
+then err_exit '( (1 || 1 && 0) != 1) failed'
+fi
+if (( (_=1)+(_x=0)-_ ))
+then err_exit '(_=1)+(_x=0)-_ failed'
+fi
+if (( (3^6) != 5))
+then err_exit '((3^6) != 5) failed'
+fi
+integer x=1
+if (( (x=-x) != -1 ))
+then err_exit '(x=-x) != -1 failed'
+fi
+i=2
+if (( 1$(($i))3 != 123 ))
+then err_exit ' 1$(($i))3 failed'
+fi
+((pi=4*atan(1.)))
+point=(
+ float x
+ float y
+)
+(( point.x = cos(pi/6), point.y = sin(pi/6) ))
+if (( point.x*point.x + point.y*point.y > 1.01 ))
+then err_exit 'cos*cos +sin*sin > 1.01'
+fi
+if (( point.x*point.x + point.y*point.y < .99 ))
+then err_exit 'cos*cos +sin*sin < .99'
+fi
+if [[ $((y=x=1.5)) != 1 ]]
+then err_exit 'typecast not working in arithmetic evaluation'
+fi
+typeset -E x=1.5
+( ((x++)) ) 2>/dev/null
+if [[ $? == 0 ]]
+then err_exit 'postincrement of floating point allowed'
+fi
+( ((++x)) ) 2>/dev/null
+if [[ $? == 0 ]]
+then err_exit 'preincrement of floating point allowed'
+fi
+x=1.5
+( ((x%1.1)) ) 2>/dev/null
+if [[ $? == 0 ]]
+then err_exit 'floating point allowed with % operator'
+fi
+x=.125
+if [[ $(( 4 * x/2 )) != 0.25 ]]
+then err_exit '(( 4 * x/2 )) is not 0.25, with x=.125'
+fi
+if [[ $(( pow(2,3) )) != 8 ]]
+then err_exit '$(( pow(2,3) )) != 8'
+fi
+( [[ $(( pow(2,(3)) )) == 8 ]] ) 2> /dev/null
+if (( $? ))
+then err_exit '$(( pow(2,(3)) )) != 8'
+fi
+unset x
+integer x=1; integer x=1
+if [[ $x != 1 ]]
+then err_exit 'two consecutive integer x=1 not working'
+fi
+unset z
+{ z=$(typeset -RZ2 z2; (( z2 = 8 )); print $z2) ;} 2>/dev/null
+if [[ $z != "08" ]]
+then err_exit "typeset -RZ2 leading 0 decimal not working [z=$z]"
+fi
+{ z=$(typeset -RZ3 z3; (( z3 = 8 )); print $z3) ;} 2>/dev/null
+if [[ $z != "008" ]]
+then err_exit "typeset -RZ3 leading 0 decimal not working [z=$z]"
+fi
+unset z
+typeset -Z3 z=010
+(( z=z+1))
+if [[ $z != 011 ]]
+then err_exit "leading 0's in -Z not treated as decimal"
+fi
+unset x
+integer x=0
+if [[ $((x+=1)) != 1 ]] || ((x!=1))
+then err_exit "+= not working"
+ x=1
+fi
+x=1
+if [[ $((x*=5)) != 5 ]] || ((x!=5))
+then err_exit "*= not working"
+ x=5
+fi
+if [[ $((x%=4)) != 1 ]] || ((x!=1))
+then err_exit "%= not working"
+ x=1
+fi
+if [[ $((x|=6)) != 7 ]] || ((x!=7))
+then err_exit "|= not working"
+ x=7
+fi
+if [[ $((x&=5)) != 5 ]] || ((x!=5))
+then err_exit "&= not working"
+ x=5
+fi
+function newscope
+{
+ float x=1.5
+ (( x += 1 ))
+ print -r -- $x
+}
+if [[ $(newscope) != 2.5 ]]
+then err_exit "arithmetic using wrong scope"
+fi
+unset x
+integer y[3]=9 y[4]=2 i=3
+(( x = y[3] + y[4] ))
+if [[ $x != 11 ]]
+then err_exit "constant index array arithmetic failure"
+fi
+(( x = $empty y[3] + y[4] ))
+if [[ $x != 11 ]]
+then err_exit "empty constant index array arithmetic failure"
+fi
+(( x = y[i] + y[i+1] ))
+if [[ $x != 11 ]]
+then err_exit "variable subscript index array arithmetic failure"
+fi
+integer a[5]=3 a[2]=4
+(( x = y[a[5]] + y[a[2]] ))
+if [[ $x != 11 ]]
+then err_exit "nested subscript index array arithmetic failure"
+fi
+unset y
+typeset -Ai y
+y[three]=9 y[four]=2
+three=four
+four=three
+(( x = y[three] + y[four] ))
+if [[ $x != 11 ]]
+then err_exit "constant associative array arithmetic failure"
+fi
+(( x = y[$three] + y[$four] ))
+if [[ $x != 11 ]]
+then err_exit "variable subscript associative array arithmetic failure"
+fi
+$SHELL -nc '((a = 1))' 2> /dev/null || err_exit "sh -n fails with arithmetic"
+$SHELL -nc '((a.b++))' 2> /dev/null || err_exit "sh -n fails with arithmetic2"
+unset z
+float z=7.5
+if { (( z%2 != 1));} 2> /dev/null
+then err_exit '% not working on floating point'
+fi
+chr=(a ' ' '=' '\r' '\n' '\\' '\"' '$' "\\'" '[' ']' '(' ')' '<' '\xab' '\040' '`' '{' '}' '*' '\E')
+if (('a' == 97))
+then val=(97 32 61 13 10 92 34 36 39 91 93 40 41 60 171 32 96 123 125 42 27)
+else val=(129 64 126 13 21 224 127 91 125 173 189 77 93 76 171 32 121 192 208 92 39 21)
+fi
+q=0
+for ((i=0; i < ${#chr[@]}; i++))
+do if (( '${chr[i]}' != ${val[i]} ))
+ then err_exit "(( '${chr[i]}' != ${val[i]} ))"
+ fi
+ if [[ $(( '${chr[i]}' )) != ${val[i]} ]]
+ then err_exit "(( '${chr[i]}' )) != ${val[i]}"
+ fi
+ if [[ $(( L'${chr[i]}' )) != ${val[i]} ]]
+ then err_exit "(( '${chr[i]}' )) != ${val[i]}"
+ fi
+ if eval '((' "'${chr[i]}'" != ${val[i]} '))'
+ then err_exit "eval (( '${chr[i]}' != ${val[i]} ))"
+ fi
+ if eval '((' "'${chr[i]}'" != ${val[i]} ' + $q ))'
+ then err_exit "eval (( '${chr[i]}' != ${val[i]} ))"
+ fi
+done
+unset x
+typeset -ui x=4294967293
+[[ $x != 4294967293 ]] && err_exit "unsigned integers not working"
+x=32767
+x=x+1
+[[ $x != 32768 ]] && err_exit "unsigned integer addition not working"
+unset x
+float x=99999999999999999999999999
+if (( x < 1e20 ))
+then err_exit 'large integer constants not working'
+fi
+unset x y
+function foobar
+{
+ nameref x=$1
+ (( x +=1 ))
+ print $x
+}
+x=0 y=4
+if [[ $(foobar y) != 5 ]]
+then err_exit 'name references in arithmetic statements in functions broken'
+fi
+if (( 2**3 != pow(2,3) ))
+then err_exit '2**3 not working'
+fi
+if (( 2**3*2 != pow(2,3)*2 ))
+then err_exit '2**3*2 not working'
+fi
+if (( 4**3**2 != pow(4,pow(3,2)) ))
+then err_exit '4**3**2 not working'
+fi
+if (( (4**3)**2 != pow(pow(4,3),2) ))
+then err_exit '(4**3)**2 not working'
+fi
+typeset -Z3 x=11
+typeset -i x
+if (( x != 11 ))
+then err_exit '-Z3 not treated as decimal'
+fi
+unset x
+typeset -ui x=-1
+(( x >= 0 )) || err_exit 'unsigned integer not working'
+(( $x >= 0 )) || err_exit 'unsigned integer not working as $x'
+unset x
+typeset -ui42 x=50
+if [[ $x != 42#18 ]]
+then err_exit 'display of unsigned integers in non-decimal bases wrong'
+fi
+$SHELL -c 'i=0;(( ofiles[i] != -1 && (ofiles[i] < mins || mins == -1) ));exit 0' 2> /dev/null || err_exit 'lexical error with arithemtic expression'
+$SHELL -c '(( +1 == 1))' 2> /dev/null || err_exit 'unary + not working'
+typeset -E20 val=123.01234567890
+[[ $val == 123.0123456789 ]] || err_exit "rounding error val=$val"
+if [[ $(print x$((10))=foo) != x10=foo ]]
+then err_exit 'parsing error with x$((10))=foo'
+fi
+$SHELL -c 'typeset x$((10))=foo' 2> /dev/null || err_exit 'typeset x$((10)) parse error'
+unset x
+x=$(( exp(log(2.0)) ))
+(( x > 1.999 && x < 2.001 )) || err_exit 'composite functions not working'
+unset x y n
+typeset -Z8 x=0 y=0
+integer n
+for (( n=0; n < 20; n++ ))
+do let "x = $x+1"
+ (( y = $y+1 ))
+done
+(( x == n )) || err_exit 'let with zero filled fields not working'
+(( y == n )) || err_exit '((...)) with zero filled fields not working'
+typeset -RZ3 x=10
+[[ $(($x)) == 10 && $((1$x)) == 1010 ]] || err_exit 'zero filled fields not preserving leading zeros'
+unset y
+[[ $(let y=$x;print $y) == 10 && $(let y=1$x;print $y) == 1010 ]] || err_exit 'zero filled fields not preserving leading zeros with let'
+unset i ip ipx
+typeset -i hex=( 172 30 18 1)
+typeset -ui ip=0 ipx=0
+integer i
+for ((i=0; i < 4; i++))
+do (( ip = (ip<<8) | hex[i]))
+done
+for ((i=0; i < 4; i++))
+do (( ipx = ip % 256 ))
+ (( ip /= 256 ))
+ (( ipx != hex[3-i] )) && err_exit "hex digit $((3-i)) not correct"
+done
+unset x
+x=010
+(( x == 10 )) || err_exit 'leading zeros in x treated as octal arithmetic with $((x))'
+(( $x == 8 )) || err_exit 'leading zeros not treated as octal arithmetic with $x'
+unset x
+typeset -Z x=010
+(( x == 10 )) || err_exit 'leading zeros not ignored for arithmetic'
+(( $x == 10 )) || err_exit 'leading zeros not ignored for arithmetic with $x'
+typeset -i i=x
+(( i == 10 )) || err_exit 'leading zeros not ignored for arithmetic assignment'
+(( ${x:0:1} == 0 )) || err_exit 'leading zero should not be stripped for x:a:b'
+c010=3
+(( c$x == 3 )) || err_exit 'leading zero with variable should not be stripped'
+[[ $( ($SHELL -c '((++1))' 2>&1) 2>/dev/null ) == *++1:* ]] || err_exit "((++1)) not generating error message"
+i=2
+(( "22" == 22 )) || err_exit "double quoted constants fail"
+(( "2$i" == 22 )) || err_exit "double quoted variables fail"
+(( "18+$i+2" == 22 )) || err_exit "double quoted expressions fail"
+# 04-04-28 bug fix
+unset i; typeset -i i=01-2
+(( i == -1 )) || err_exit "01-2 is not -1"
+
+cat > $tmp/script <<-\!
+tests=$*
+typeset -A blop
+function blop.get
+{
+ .sh.value=777
+}
+function mkobj
+{
+ nameref obj=$1
+ obj=()
+ [[ $tests == *1* ]] && {
+ (( obj.foo = 1 ))
+ (( obj.bar = 2 ))
+ (( obj.baz = obj.foo + obj.bar )) # ok
+ echo $obj
+ }
+ [[ $tests == *2* ]] && {
+ (( obj.faz = faz = obj.foo + obj.bar )) # ok
+ echo $obj
+ }
+ [[ $tests == *3* ]] && {
+ # case 3, 'active' variable involved, w/ intermediate variable
+ (( obj.foz = foz = ${blop[1]} )) # coredump
+ echo $obj
+ }
+ [[ $tests == *4* ]] && {
+ # case 4, 'active' variable, in two steps
+ (( foz = ${blop[1]} )) # ok
+ (( obj.foz = foz )) # ok
+ echo $obj
+ }
+ [[ $tests == *5* ]] && {
+ # case 5, 'active' variable involved, w/o intermediate variable
+ (( obj.fuz = ${blop[1]} )) # coredump
+ echo $obj
+ }
+ [[ $tests == *6* ]] && {
+ echo $(( obj.baz = obj.foo + obj.bar )) # coredump
+ }
+ [[ $tests == *7* ]] && {
+ echo $(( obj.foo + obj.bar )) # coredump
+ }
+}
+mkobj bla
+!
+chmod +x $tmp/script
+[[ $($tmp/script 1) != '( bar=2 baz=3 foo=1 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 2) != '( faz=0 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 3) != '( foz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 4) != '( foz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 5) != '( fuz=777 )' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 6) != '0' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+[[ $($tmp/script 7) != '0' ]] 2>/dev/null && err_exit 'compound var arithmetic failed'
+unset foo
+typeset -F1 foo=123456789.19
+[[ $foo == 123456789.2 ]] || err_exit 'typeset -F1 not working correctly'
+
+# divide by zero
+
+for expr in '1/(1/2)' '8%(1/2)' '8%(1.0/2)'
+do [[ $( ( $SHELL -c "( (($expr)) ) || print ok" ) 2>/dev/null ) == ok ]] || err_exit "divide by zero not trapped: $expr"
+done
+
+for expr in '1/(1.0/2)' '1/(1/2.0)'
+do [[ $( ( $SHELL -c "( print -r -- \$(($expr)) )" ) 2>/dev/null ) == 2 ]] || err_exit "invalid value for: $expr"
+done
+[[ $((5||0)) == 1 ]] || err_exit '$((5||0))'" == $((5||0)) should be 1"
+$SHELL -c 'integer x=3 y=2; (( (y += x += 2) == 7 && x==5))' 2> /dev/null || err_exit '((y += x += 2)) not working'
+$SHELL -c 'b=0; [[ $((b?a=1:b=9)) == 9 ]]' 2> /dev/null || err_exit 'b?a=1:b=9 not working'
+unset x
+(( x = 4*atan(1.0) ))
+[[ $x == "$((x))" ]] || err_exit '$x !- $((x)) when x is pi'
+$SHELL -c "[[ ${x//./} == {14,100}(\d) ]]" 2> /dev/null || err_exit 'pi has less than 14 significant places'
+if (( Inf+1 == Inf ))
+then set \
+ Inf inf \
+ -Inf -inf \
+ Nan nan \
+ -Nan -nan \
+ 1.0/0.0 inf
+ while (( $# >= 2 ))
+ do x=$(printf "%g\n" $(($1)))
+ [[ $x == $2 ]] || err_exit "printf '%g\\n' \$(($1)) failed -- expected $2, got $x"
+ x=$(printf "%g\n" $1)
+ [[ $x == $2 ]] || err_exit "printf '%g\\n' $1 failed -- expected $2, got $x"
+ x=$(printf -- $(($1)))
+ [[ $x == $2 ]] || err_exit "print -- \$(($1)) failed -- expected $2, got $x"
+ shift 2
+ done
+ (( 1.0/0.0 == Inf )) || err_exit '1.0/0.0 != Inf'
+ [[ $(print -- $((0.0/0.0))) == ?(-)nan ]] || err_exit '0.0/0.0 != NaN'
+ (( Inf*Inf == Inf )) || err_exit 'Inf*Inf != Inf'
+ (( NaN != NaN )) || err_exit 'NaN == NaN'
+ (( -5*Inf == -Inf )) || err_exit '-5*Inf != -Inf'
+ [[ $(print -- $((sqrt(-1.0)))) == ?(-)nan ]]|| err_exit 'sqrt(-1.0) != NaN'
+ (( pow(1.0,Inf) == 1.0 )) || err_exit 'pow(1.0,Inf) != 1.0'
+ (( pow(Inf,0.0) == 1.0 )) || err_exit 'pow(Inf,0.0) != 1.0'
+ [[ $(print -- $((NaN/Inf))) == ?(-)nan ]] || err_exit 'NaN/Inf != NaN'
+ (( 4.0/Inf == 0.0 )) || err_exit '4.0/Inf != 0.0'
+else err_exit 'Inf and NaN not working'
+fi
+unset x y n r
+n=14.555
+float x=$n y
+y=$(printf "%a" x)
+r=$y
+[[ $r == $n ]] || err_exit "output of printf %a not self preserving -- expected $x, got $y"
+unset x y r
+x=-0
+y=$(printf "%g %g %g %g %g %g\n" -0. -0 $((-0)) x $x $((x)))
+r="-0 -0 -0 -0 -0 -0"
+[[ $y == "$r" ]] || err_exit "-0 vs -0.0 inconsistency -- expected '$r', got '$y'"
+$SHELL -c '(( x=));:' 2> /dev/null && err_exit '((x=)) should be an error'
+$SHELL -c '(( x+=));:' 2> /dev/null && err_exit '((x+=)) should be an error'
+$SHELL -c '(( x=+));:' 2> /dev/null && err_exit '((x=+)) should be an error'
+$SHELL -c 'x=();x.arr[0]=(z=3); ((x.arr[0].z=2))' 2> /dev/null || err_exit '(((x.arr[0].z=2)) should not be an error'
+
+float t
+typeset a b r
+v="-0.0 0.0 +0.0 -1.0 1.0 +1.0"
+for a in $v
+do for b in $v
+ do (( r = copysign(a,b) ))
+ (( t = copysign(a,b) ))
+ [[ $r == $t ]] || err_exit $(printf "float t=copysign(%3.1f,%3.1f) => %3.1f -- expected %3.1f\n" a b t r)
+ done
+done
+
+typeset -l y y_ascii
+(( y=sin(90) ))
+y_ascii=$y
+(( y == y_ascii )) || err_exit "no match,\n\t$(printf "%a\n" y)\n!=\n\t$(printf "%a\n" y_ascii)"
+
+( $SHELL <<- \EOF
+ p=5
+ t[p]=6
+ while (( t[p] != 0 )) ; do
+ ((
+ p+=1 ,
+ t[p]+=2 ,
+ p+=3 ,
+ t[p]+=5 ,
+ p+=1 ,
+ t[p]+=2 ,
+ p+=1 ,
+ t[p]+=1 ,
+ p-=6 ,
+ t[p]-=1
+ ))
+ :
+ done
+EOF) 2> /dev/null || err_exit 'error with comma expression'
+
+N=(89551 89557)
+i=0 j=1
+[[ $(printf "%d" N[j]-N[i]) == 6 ]] || err_exit 'printf %d N[i]-N[j] failed'
+[[ $((N[j]-N[i])) == 6 ]] || err_exit '$((N[j]-N[i])) incorrect'
+
+unset a x
+x=0
+((a[++x]++))
+(( x==1)) || err_exit '((a[++x]++)) should only increment x once'
+(( a[1]==1)) || err_exit 'a[1] not incremented'
+unset a
+x=0
+((a[x++]++))
+(( x==1)) || err_exit '((a[x++]++)) should only increment x once'
+(( a[0]==1)) || err_exit 'a[0] not incremented'
+unset a
+x=0
+((a[x+=2]+=1))
+(( x==2)) || err_exit '((a[x+=2]++)) should result in x==2'
+(( a[2]==1)) || err_exit 'a[0] not 1'
+
+unset a i
+typeset -a a
+i=1
+(( a[i]=1 ))
+(( a[0] == 0 )) || err_exit 'a[0] not 0'
+(( a[1] == 1 )) || err_exit 'a[1] not 1'
+
+unset a
+typeset -i a
+for ((i=0;i<1000;i++))
+do ((a[RANDOM%2]++))
+done
+(( (a[0]+a[1])==1000)) || err_exit '(a[0]+a[1])!=1000'
+
+(( 4.**3/10 == 6.4 )) || err_exit '4.**3/10!=6.4'
+(( (.5+3)/7 == .5 )) || err_exit '(.5+3)/7!==.5'
+
+function .sh.math.mysin x
+{
+ ((.sh.value = x - x**3/6. + x**5/120.-x**7/5040. + x**9/362880.))
+}
+
+(( abs(sin(.5)-mysin(.5)) < 1e-6 )) || err_exit 'mysin() not close to sin()'
+
+$SHELL 2> /dev/null <<- \EOF || err_exit "arithmetic functions defined and referenced in compound command not working"
+{
+ function .sh.math.mysin x
+ {
+ ((.sh.value = x-x**3/6. + x**5/120.-x**7/5040. + x**9/362880.))
+ }
+ (( abs(sin(.5)-mysin(.5)) < 1e-6 ))
+ exit 0
+}
+EOF
+
+
+
+function .sh.math.max x y z
+{
+ .sh.value=x
+ (( y > x )) && .sh.value=y
+ (( z > .sh.value )) && .sh.value=z
+}
+(( max(max(3,8,5),7,5)==8)) || err_exit 'max(max(3,8,5),7,5)!=8'
+(( max(max(3,8,5),7,9)==9)) || err_exit 'max(max(3,8,9),7,5)!=9'
+(( max(6,max(3,9,5),7)==9 )) || err_exit 'max(6,max(3,8,5),7)!=9'
+(( max(6,7, max(3,8,5))==8 )) || err_exit 'max(6,7,max(3,8,5))!=8'
+
+enum color_t=(red green blue yellow)
+color_t shirt pants=blue
+(( pants == blue )) || err_exit 'pants should be blue'
+(( shirt == red )) || err_exit 'pants should be red'
+(( shirt != green )) || err_exit 'shirt should not be green'
+(( pants != shirt )) || err_exit 'pants should be the same as shirt'
+(( pants = yellow ))
+(( pants == yellow )) || err_exit 'pants should be yellow'
+
+unset z
+integer -a z=( [1]=90 )
+function x
+{
+ nameref nz=$1
+ float x y
+ float x=$((log10(nz))) y=$((log10($nz)))
+ (( abs(x-y) < 1e-10 )) || err_exit '$nz and nz differs in arithmetic expression when nz is reference to array instance'
+}
+x z[1]
+
+unset x
+float x
+x=$( ($SHELL -c 'print -- $(( asinh(acosh(atanh(sin(cos(tan(atan(acos(asin(tanh(cosh(sinh(asinh(acosh(atanh(sin(cos(tan(atan(acos(asin(tanh(cosh(sinh(.5)))))))))))))))))))))))) )) ';:) 2> /dev/null)
+(( abs(x-.5) < 1.e-10 )) || err_exit 'bug in composite function evaluation'
+
+unset x
+typeset -X x=16
+{ (( $x == 16 )) ;} 2> /dev/null || err_exit 'expansions of hexfloat not working in arithmetic expansions'
+
+unset foo
+function foobar
+{
+ (( foo = 8))
+}
+typeset -i foo
+foobar
+(( foo == 8 )) || err_exit 'arithmetic assignment binding to the wrong scope'
+
+(( tgamma(4)/12 )) || err_exit 'floating point attribute for functions not preserved'
+
+unset F
+function f
+{
+ ((F=1))
+}
+f
+[[ $F == 1 ]] || err_exit 'scoping bug with arithmetic expression'
+
+F=1
+function f
+{
+ typeset F
+ ((F=2))
+}
+[[ $F == 1 ]] || err_exit 'scoping bug2 with arithmetic expression'
+
+unset play foo x z
+typeset -A play
+x=foo
+play[$x]=(x=2)
+for ((i=0; i < 2; i++))
+do (( play[$x].y , z++ ))
+done
+(( z==2 )) || err_exit 'unset compound array variable error with for loop optimization'
+
+[[ $($SHELL 2> /dev/null -c 'print -- $(( ldexp(1, 4) ))' ) == 16 ]] || err_exit 'function ldexp not implement or not working correctly'
+
+
+$SHELL 2> /dev/null -c 'str="0x1.df768ed398ee1e01329a130627ae0000p-1";typeset -l -E x;((x=str))' || err_exit '((x=var)) fails for hexfloat with var begining with 0x1.nnn'
+
+x=(3 6 12)
+(( x[2] /= x[0]))
+(( x[2] == 4 )) || err_exit '(( x[2] /= x[0])) fails for index array'
+
+x=([0]=3 [1]=6 [2]=12)
+(( x[2] /= x[0]))
+(( x[2] == 4 )) || err_exit '(( x[2] /= x[0])) fails for associative array'
+
+got=$($SHELL 2> /dev/null -c 'compound -a x;compound -a x[0].y; integer -a x[0].y[0].z; (( x[0].y[0].z[2]=3 )); typeset -p x')
+exp='typeset -C -a x=((typeset -C -a y=( [0]=(typeset -a -l -i z=([2]=3);));))'
+[[ $got == "$exp" ]] || err_exit '(( x[0].y[0].z[2]=3 )) not working'
+
+unset x
+let x=010
+[[ $x == 10 ]] || err_exit 'let treating 010 as octal'
+set -o letoctal
+let x=010
+[[ $x == 8 ]] || err_exit 'let not treating 010 as octal with letoctal on'
+
+float z=0
+integer aa=2 a=1
+typeset -A A
+A[a]=(typeset -A AA)
+A[a].AA[aa]=1
+(( z= A[a].AA[aa]++ ))
+(( z == 1 )) || err_exit "z should be 1 but is $z for associative array of
+associative array arithmetic"
+[[ ${A[a].AA[aa]} == 2 ]] || err_exit '${A[a].AA[aa]} should be 2 after ++ operation for associative array of associative array arithmetic'
+unset A[a]
+
+A[a]=(typeset -a AA)
+A[a].AA[aa]=1
+(( z += A[a].AA[aa++]++ ))
+(( z == 2 )) || err_exit "z should be 2 but is $z for associative array of
+index array arithmetic"
+(( aa == 3 )) || err_exit "subscript aa should be 3 but is $aa after ++"
+[[ ${A[a].AA[aa-1]} == 2 ]] || err_exit '${A[a].AA[aa]} should be 2 after ++ operation for ssociative array of index array arithmetic'
+unset A
+
+typeset -a A
+A[a]=(typeset -A AA)
+A[a].AA[aa]=1
+(( z += A[a].AA[aa]++ ))
+(( z == 3 )) || err_exit "z should be 3 but is $z for index array of
+associative array arithmetic"
+[[ ${A[a].AA[aa]} == 2 ]] || err_exit '${A[a].AA[aa]} should be 2 after ++ operation for index array of associative array arithmetic'
+unset A[a]
+
+A[a]=(typeset -a AA)
+A[a].AA[aa]=1
+(( z += A[a++].AA[aa++]++ ))
+(( z == 4 )) || err_exit "z should be 4 but is $z for index array of
+index array arithmetic"
+[[ ${A[a-1].AA[aa-1]} == 2 ]] || err_exit '${A[a].AA[aa]} should be 2 after ++ operation for index array of index array arithmetic'
+(( aa == 4 )) || err_exit "subscript aa should be 4 but is $aa after ++"
+(( a == 2 )) || err_exit "subscript a should be 2 but is $a after ++"
+unset A
+
+unset r x
+integer x
+r=020
+(($r == 16)) || err_exit 'leading 0 not treated as octal inside ((...))'
+x=$(($r))
+(( x == 16 )) || err_exit 'leading 0 not treated as octal inside $((...))'
+x=$r
+((x == 20 )) || err_exit 'leading 0 should not be treated as octal outside ((...))'
+print -- -020 | read x
+((x == -20)) || err_exit 'numbers with leading -0 should not be treated as octal outside ((...))'
+print -- -8#20 | read x
+((x == -16)) || err_exit 'numbers with leading -8# should be treated as octal'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/arrays.sh b/src/cmd/ksh93/tests/arrays.sh
new file mode 100755
index 0000000..8aec386
--- /dev/null
+++ b/src/cmd/ksh93/tests/arrays.sh
@@ -0,0 +1,588 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function fun
+{
+ integer i
+ unset xxx
+ for i in 0 1
+ do xxx[$i]=$i
+ done
+}
+
+set -A x zero one two three four 'five six'
+if [[ $x != zero ]]
+then err_exit '$x is not element 0'
+fi
+if [[ ${x[0]} != zero ]]
+then err_exit '${x[0] is not element 0'
+fi
+if (( ${#x[0]} != 4 ))
+then err_exit "length of ${x[0]} is not 4"
+fi
+if (( ${#x[@]} != 6 ))
+then err_exit 'number of elements of x is not 6'
+fi
+if [[ ${x[2]} != two ]]
+then err_exit ' element two is not 2'
+fi
+if [[ ${x[@]:2:1} != two ]]
+then err_exit ' ${x[@]:2:1} is not two'
+fi
+set -A y -- ${x[*]}
+if [[ $y != zero ]]
+then err_exit '$x is not element 0'
+fi
+if [[ ${y[0]} != zero ]]
+then err_exit '${y[0] is not element 0'
+fi
+if (( ${#y[@]} != 7 ))
+then err_exit 'number of elements of y is not 7'
+fi
+if [[ ${y[2]} != two ]]
+then err_exit ' element two is not 2'
+fi
+set +A y nine ten
+if [[ ${y[2]} != two ]]
+then err_exit ' element two is not 2'
+fi
+if [[ ${y[0]} != nine ]]
+then err_exit '${y[0] is not nine'
+fi
+unset y[4]
+if (( ${#y[@]} != 6 ))
+then err_exit 'number of elements of y is not 6'
+fi
+if (( ${#y[4]} != 0 ))
+then err_exit 'string length of unset element is not 0'
+fi
+unset foo
+if (( ${#foo[@]} != 0 ))
+then err_exit 'number of elements of unset variable foo is not 0'
+fi
+foo=''
+if (( ${#foo[0]} != 0 ))
+then err_exit 'string length of null element is not 0'
+fi
+if (( ${#foo[@]} != 1 ))
+then err_exit 'number of elements of null variable foo is not 1'
+fi
+unset foo
+foo[0]=foo
+foo[3]=bar
+unset foo[0]
+unset foo[3]
+if (( ${#foo[@]} != 0 ))
+then err_exit 'number of elements of left in variable foo is not 0'
+fi
+unset foo
+foo[3]=bar
+foo[0]=foo
+unset foo[3]
+unset foo[0]
+if (( ${#foo[@]} != 0 ))
+then err_exit 'number of elements of left in variable foo again is not 0'
+fi
+fun
+if (( ${#xxx[@]} != 2 ))
+then err_exit 'number of elements of left in variable xxx is not 2'
+fi
+fun
+if (( ${#xxx[@]} != 2 ))
+then err_exit 'number of elements of left in variable xxx again is not 2'
+fi
+set -A foo -- "${x[@]}"
+if (( ${#foo[@]} != 6 ))
+then err_exit 'number of elements of foo is not 6'
+fi
+if (( ${#PWD[@]} != 1 ))
+then err_exit 'number of elements of PWD is not 1'
+fi
+unset x
+x[2]=foo x[4]=bar
+if (( ${#x[@]} != 2 ))
+then err_exit 'number of elements of x is not 2'
+fi
+s[1]=1 c[1]=foo
+if [[ ${c[s[1]]} != foo ]]
+then err_exit 'c[1]=foo s[1]=1; ${c[s[1]]} != foo'
+fi
+unset s
+typeset -Ai s
+y=* z=[
+s[$y]=1
+s[$z]=2
+if (( ${#s[@]} != 2 ))
+then err_exit 'number of elements of is not 2'
+fi
+(( s[$z] = s[$z] + ${s[$y]} ))
+if [[ ${s[$z]} != 3 ]]
+then err_exit '[[ ${s[$z]} != 3 ]]'
+fi
+if (( s[$z] != 3 ))
+then err_exit '(( s[$z] != 3 ))'
+fi
+(( s[$y] = s[$y] + ${s[$z]} ))
+if [[ ${s[$y]} != 4 ]]
+then err_exit '[[ ${s[$y]} != 4 ]]'
+fi
+if (( s[$y] != 4 ))
+then err_exit '(( s[$y] != 4 ))'
+fi
+set -A y 2 4 6
+typeset -i y
+z=${y[@]}
+typeset -R12 y
+typeset -i y
+if [[ ${y[@]} != "$z" ]]
+then err_exit 'error in array conversion from int to R12'
+fi
+if (( ${#y[@]} != 3 ))
+then err_exit 'error in count of array conversion from int to R12'
+fi
+unset abcdefg
+: ${abcdefg[1]}
+set | grep '^abcdefg$' >/dev/null && err_exit 'empty array variable in set list'
+unset x y
+x=1
+typeset -i y[$x]=4
+if [[ ${y[1]} != 4 ]]
+then err_exit 'arithmetic expressions in typeset not working'
+fi
+unset foo
+typeset foo=bar
+typeset -A foo
+if [[ ${foo[0]} != bar ]]
+then err_exit 'initial value not preserved when typecast to associative'
+fi
+unset foo
+foo=(one two)
+typeset -A foo
+foo[two]=3
+if [[ ${#foo[*]} != 3 ]]
+then err_exit 'conversion of indexed to associative array failed'
+fi
+set a b c d e f g h i j k l m
+if [[ ${#} != 13 ]]
+then err_exit '${#} not 13'
+fi
+unset xxx
+xxx=foo
+if [[ ${!xxx[@]} != 0 ]]
+then err_exit '${!xxx[@]} for scalar not 0'
+fi
+if [[ ${11} != k ]]
+then err_exit '${11} not working'
+fi
+if [[ ${@:4:1} != d ]]
+then err_exit '${@:4:1} not working'
+fi
+foovar1=abc
+foovar2=def
+if [[ ${!foovar@} != +(foovar[[:alnum:]]?([ ])) ]]
+then err_exit '${!foovar@} does not expand correctly'
+fi
+if [[ ${!foovar1} != foovar1 ]]
+then err_exit '${!foovar1} != foovar1'
+fi
+unset xxx
+: ${xxx[3]}
+if [[ ${!xxx[@]} ]]
+then err_exit '${!xxx[@]} should be null'
+fi
+integer i=0
+{
+ set -x
+ xxx[++i]=1
+ set +x
+} 2> /dev/null
+if (( i != 1))
+then err_exit 'execution trace side effects with array subscripts'
+fi
+unset list
+: $(set -A list foo bar)
+if (( ${#list[@]} != 0))
+then err_exit '$(set -A list ...) leaves side effects'
+fi
+unset list
+list= (foo bar bam)
+( set -A list one two three four)
+if [[ ${list[1]} != bar ]]
+then err_exit 'array not restored after subshell'
+fi
+XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin
+xpath=( $( IFS=: ; echo $XPATH ) )
+if [[ $(print -r "${xpath[@]##*/}") != 'bin bin ucb bin . sbin sbin' ]]
+then err_exit '${xpath[@]##*/} not applied to each element'
+fi
+foo=( zero one '' three four '' six)
+integer n=-1
+if [[ ${foo[@]:n} != six ]]
+then err_exit 'array offset of -1 not working'
+fi
+if [[ ${foo[@]: -3:1} != four ]]
+then err_exit 'array offset of -3:1 not working'
+fi
+$SHELL -c 'x=(if then else fi)' 2> /dev/null || err_exit 'reserved words in x=() assignment not working'
+unset foo
+foo=one
+foo=( $foo two)
+if [[ ${#foo[@]} != 2 ]]
+then err_exit 'array getting unset before right hand side evaluation'
+fi
+foo=(143 3643 38732)
+export foo
+typeset -i foo
+if [[ $($SHELL -c 'print $foo') != 143 ]]
+then err_exit 'exporting indexed array not exporting 0-th element'
+fi
+( $SHELL -c '
+ unset foo
+ typeset -A foo=([0]=143 [1]=3643 [2]=38732)
+ export foo
+ typeset -i foo
+ [[ $($SHELL -c "print $foo") == 143 ]]'
+) 2> /dev/null ||
+ err_exit 'exporting associative array not exporting 0-th element'
+unset foo
+typeset -A foo
+foo[$((10))]=ok 2> /dev/null || err_exit 'arithmetic expression as subscript not working'
+unset foo
+typeset -A foo
+integer foo=0
+[[ $foo == 0 ]] || err_exit 'zero element of associative array not being set'
+unset foo
+typeset -A foo=( [two]=1)
+for i in one three four five
+do : ${foo[$i]}
+done
+if [[ ${!foo[@]} != two ]]
+then err_exit 'error in subscript names'
+fi
+unset x
+x=( 1 2 3)
+(x[1]=8)
+[[ ${x[1]} == 2 ]] || err_exit 'index array produce side effects in subshells'
+x=( 1 2 3)
+(
+ x+=(8)
+ [[ ${#x[@]} == 4 ]] || err_exit 'index array append in subshell error'
+)
+[[ ${#x[@]} == 3 ]] || err_exit 'index array append in subshell effects parent'
+x=( [one]=1 [two]=2 [three]=3)
+(x[two]=8)
+[[ ${x[two]} == 2 ]] || err_exit 'associative array produce side effects in subshells'
+unset x
+x=( [one]=1 [two]=2 [three]=3)
+(
+ x+=( [four]=4 )
+ [[ ${#x[@]} == 4 ]] || err_exit 'associative array append in subshell error'
+)
+[[ ${#x[@]} == 3 ]] || err_exit 'associative array append in subshell effects parent'
+unset x
+integer i
+for ((i=0; i < 40; i++))
+do x[i]=$i
+done
+[[ ${#x[@]} == 40 ]] || err_exit 'index arrays loosing values'
+[[ $( ($SHELL -c 'typeset -A var; (IFS=: ; set -A var a:b:c ;print ${var[@]});:' )2>/dev/null) == 'a b c' ]] || err_exit 'change associative to index failed'
+unset foo
+[[ $(foo=good
+for ((i=0; i < 2; i++))
+do [[ ${foo[i]} ]] && print ok
+done) == ok ]] || err_exit 'invalid optimization for subscripted variables'
+(
+x=([foo]=bar)
+set +A x bam
+) 2> /dev/null && err_exit 'set +A with associative array should be an error'
+unset bam foo
+foo=0
+typeset -A bam
+unset bam[foo]
+bam[foo]=value
+[[ $bam == value ]] && err_exit 'unset associative array element error'
+: only first element of an array can be exported
+unset bam
+print 'print ${var[0]} ${var[1]}' > $tmp/script
+chmod +x $tmp/script
+[[ $($SHELL -c "var=(foo bar);export var;$tmp/script") == foo ]] || err_exit 'export array not exporting just first element'
+
+unset foo
+set --allexport
+foo=one
+foo[1]=two
+foo[0]=three
+[[ $foo == three ]] || err_exit '--allexport not working with arrays'
+set --noallexport
+unset foo
+
+cat > $tmp/script <<- \!
+ typeset -A foo
+ print foo${foo[abc]}
+!
+[[ $($SHELL -c "typeset -A foo;$tmp/script") == foo ]] 2> /dev/null || err_exit 'empty associative arrays not being cleared correctly before scripts'
+[[ $($SHELL -c "typeset -A foo;foo[abc]=abc;$tmp/script") == foo ]] 2> /dev/null || err_exit 'associative arrays not being cleared correctly before scripts'
+unset foo
+foo=(one two)
+[[ ${foo[@]:1} == two ]] || err_exit '${foo[@]:1} == two'
+[[ ! ${foo[@]:2} ]] || err_exit '${foo[@]:2} not null'
+unset foo
+foo=one
+[[ ! ${foo[@]:1} ]] || err_exit '${foo[@]:1} not null'
+function EMPTY
+{
+ typeset i
+ typeset -n ARRAY=$1
+ for i in ${!ARRAY[@]}
+ do unset ARRAY[$i]
+ done
+}
+unset foo
+typeset -A foo
+foo[bar]=bam
+foo[x]=y
+EMPTY foo
+[[ $(typeset | grep foo$) == *associative* ]] || err_exit 'array lost associative attribute'
+[[ ! ${foo[@]} ]] || err_exit 'array not empty'
+[[ ! ${!foo[@]} ]] || err_exit 'array names not empty'
+unset foo
+foo=bar
+set -- "${foo[@]:1}"
+(( $# == 0 )) || err_exit '${foo[@]:1} should not have any values'
+unset bar
+exp=4
+: ${_foo[bar=4]}
+(( bar == 4 )) || err_exit "subscript of unset variable not evaluated -- expected '4', got '$got'"
+unset bar
+: ${_foo[bar=$exp]}
+(( bar == $exp )) || err_exit "subscript of unset variable not evaluated -- expected '$exp', got '$got'"
+unset foo bar
+foo[5]=4
+bar[4]=3
+bar[0]=foo
+foo[0]=bam
+foo[4]=5
+[[ ${!foo[2+2]} == 'foo[4]' ]] || err_exit '${!var[sub]} should be var[sub]'
+[[ ${bar[${foo[5]}]} == 3 ]] || err_exit 'array subscript cannot be an array instance'
+[[ $bar[4] == 3 ]] || err_exit '$bar[x] != ${bar[x]} inside [[ ]]'
+(( $bar[4] == 3 )) || err_exit '$bar[x] != ${bar[x]} inside (( ))'
+[[ $bar[$foo[5]] == 3 ]] || err_exit '$bar[foo[x]] != ${bar[foo[x]]} inside [[ ]]'
+(( $bar[$foo[5]] == 3 )) || err_exit '$bar[foo[x]] != ${bar[foo[x]]} inside (( ))'
+x=$bar[4]
+[[ $x == 4 ]] && err_exit '$bar[4] should not be an array in an assignment'
+x=${bar[$foo[5]]}
+(( $x == 3 )) || err_exit '${bar[$foo[sub]]} not working'
+[[ $($SHELL <<- \++EOF+++
+ typeset -i test_variable=0
+ typeset -A test_array
+ test_array[1]=100
+ read test_array[2] <<-!
+ 2
+ !
+ read test_array[3] <<-!
+ 3
+ !
+ test_array[3]=4
+ print "val=${test_array[3]}"
+++EOF+++
+) == val=4 ]] 2> /dev/null || err_exit 'after reading array[j] and assign array[j] fails'
+[[ $($SHELL <<- \+++EOF+++
+ pastebin=( typeset -a form)
+ pastebin.form+=( name="name" data="clueless" )
+ print -r -- ${pastebin.form[0].name}
++++EOF+++
+) == name ]] 2> /dev/null || err_exit 'indexed array in compound variable not working'
+unset foo bar
+: ${foo[bar=2]}
+[[ $bar == 2 ]] || err_exit 'subscript not evaluated for unset variable'
+unset foo bar
+bar=1
+typeset -a foo=([1]=ok [2]=no)
+[[ $foo[bar] == ok ]] || err_exit 'typeset -a not working for simple assignment'
+unset foo
+typeset -a foo=([1]=(x=ok) [2]=(x=no))
+[[ $(typeset | grep 'foo$') == *index* ]] || err_exit 'typeset -a not creating an indexed array'
+foo+=([5]=good)
+[[ $(typeset | grep 'foo$') == *index* ]] || err_exit 'append to indexed array not preserving array type'
+unset foo
+typeset -A foo=([1]=ok [2]=no)
+[[ $foo[bar] == ok ]] && err_exit 'typeset -A not working for simple assignment'
+unset foo
+typeset -A foo=([1]=(x=ok) [2]=(x=no))
+[[ ${foo[bar].x} == ok ]] && err_exit 'typeset -A not working for compound assignment'
+[[ $($SHELL -c 'typeset -a foo;typeset | grep "foo$"' 2> /dev/null) == *index* ]] || err_exit 'typeset fails for indexed array with no elements'
+xxxxx=(one)
+[[ $(typeset | grep xxxxx$) == *'indexed array'* ]] || err_exit 'array of one element not an indexed array'
+unset foo
+foo[1]=(x=3 y=4)
+{ [[ ${!foo[1].*} == 'foo[1].x foo[1].y' ]] ;} 2> /dev/null || err_exit '${!foo[sub].*} not expanding correctly'
+unset x
+x=( typeset -a foo=( [0]="a" [1]="b" [2]="c" ))
+[[ ${@x.foo} == 'typeset -a'* ]] || err_exit 'x.foo is not an indexed array'
+x=( typeset -A foo=( [0]="a" [1]="b" [2]="c" ))
+[[ ${@x.foo} == 'typeset -A'* ]] || err_exit 'x.foo is not an associative array'
+$SHELL -c $'x=(foo\n\tbar\nbam\n)' 2> /dev/null || err_exit 'compound array assignment with new-lines not working'
+$SHELL -c $'x=(foo\n\tbar:\nbam\n)' 2> /dev/null || err_exit 'compound array assignment with labels not working'
+$SHELL -c $'x=(foo\n\tdone\nbam\n)' 2> /dev/null || err_exit 'compound array assignment with reserved words not working'
+[[ $($SHELL -c 'typeset -A A; print $(( A[foo].bar ))' 2> /dev/null) == 0 ]] || err_exit 'unset variable not evaluating to 0'
+unset a
+typeset -A a
+a[a].z=1
+a[z].z=2
+unset a[a]
+[[ ${!a[@]} == z ]] || err_exit '"unset a[a]" unsets entire array'
+unset a
+a=([x]=1 [y]=2 [z]=(foo=3 bar=4))
+eval "b=$(printf "%B\n" a)"
+eval "c=$(printf "%#B\n" a)"
+[[ ${a[*]} == "${b[*]}" ]] || err_exit 'printf %B not preserving values for arrays'
+[[ ${a[*]} == "${c[*]}" ]] || err_exit 'printf %#B not preserving values for arrays'
+unset a
+a=(zero one two three four)
+a[6]=six
+[[ ${a[-1]} == six ]] || err_exit 'a[-1] should be six'
+[[ ${a[-3]} == four ]] || err_exit 'a[-3] should be four'
+[[ ${a[-3..-1]} == 'four six' ]] || err_exit "a[-3,-1] should be 'four six'"
+
+FILTER=(typeset scope)
+FILTER[0].scope=include
+FILTER[1].scope=exclude
+[[ ${#FILTER[@]} == 2 ]] || err_exit "FILTER array should have two elements not ${#FILTER[@]}"
+
+unset x
+function x.get
+{
+ print sub=${.sh.subscript}
+}
+x[2]=
+z=$(: ${x[1]} )
+[[ $z == sub=1 ]] || err_exit 'get function not invoked for index array'
+
+unset x
+typeset -A x
+function x.get
+{
+ print sub=${.sh.subscript}
+}
+x[2]=
+z=$(: ${x[1]} )
+[[ $z == sub=1 ]] || err_exit 'get function not invoked for associative array'
+
+unset y
+i=1
+a=(11 22)
+typeset -m y=a[i]
+[[ $y == 22 ]] || err_exit 'typeset -m for index array not working'
+[[ ${a[i]} || ${a[0]} != 11 ]] && err_exit 'typeset -m for index array not deleting element'
+
+unset y
+a=([0]=11 [1]=22)
+typeset -m y=a[$i]
+[[ $y == 22 ]] || err_exit 'typeset -m for associative array not working'
+[[ ${a[$i]} || ${a[0]} != 11 ]] && err_exit 'typeset -m for associative array not deleting element'
+unset x a j
+
+typeset -a a=( [0]="aa" [1]="bb" [2]="cc" )
+typeset -m 'j=a[0]'
+typeset -m 'a[0]=a[1]'
+typeset -m 'a[1]=j'
+[[ ${a[@]} == 'bb aa cc' ]] || err_exit 'moving index array elements not working'
+unset a j
+
+typeset -A a=( [0]="aa" [1]="bb" [2]="cc" )
+typeset -m 'j=a[0]'
+typeset -m 'a[0]=a[1]'
+typeset -m 'a[1]=j'
+[[ ${a[@]} == 'bb aa cc' ]] || err_exit 'moving associative array elements not working'
+unset a j
+
+z=(a b c)
+unset x
+typeset -m x[1]=z
+[[ ${x[1][@]} == 'a b c' ]] || err_exit 'moving indexed array to index array element not working'
+
+unset x z
+z=([0]=a [1]=b [2]=c)
+typeset -m x[1]=z
+[[ ${x[1][@]} == 'a b c' ]] || err_exit 'moving associative array to index array element not working'
+
+{
+typeset -a arr=(
+ float
+)
+} 2> /dev/null
+[[ ${arr[0]} == float ]] || err_exit 'typeset -a should not expand alias for float'
+unset arr
+
+{
+typeset -r -a arr=(
+ float
+)
+} 2> /dev/null
+[[ ${arr[0]} == float ]] || err_exit 'typeset -r -a should not expand alias for float'
+{
+typeset -a arr2=(
+ typeset +r
+)
+} 2> /dev/null
+[[ ${arr2[0]} == typeset ]] || err_exit 'typeset -a should not process declarations'
+unset arr2
+
+$SHELL 2> /dev/null -c $'typeset -a arr=(\nfor)' || err_exit 'typeset -a should allow reserved words as first argument'
+
+$SHELL 2> /dev/null -c $'typeset -r -a arr=(\nfor)' || err_exit 'typeset -r -a should allow reserved words as first argument'
+
+typeset arr2[6]
+[[ ${#arr2[@]} == 0 ]] || err_exit 'declartion "typeset array[6]" should not show any elements'
+
+arr2[1]=def
+[[ ${arr2[1]} == def ]] || err_exit 'declaration "typeset array[6]" causes arrays causes wrong side effects'
+
+unset foo
+typeset foo[7]
+[[ ${#foo[@]} == 0 ]] || err_exit 'typeset foo[7] should not have one element'
+
+a=123 $SHELL 2> /dev/null -c 'integer a[5]=3 a[2]=4; unset a;x=0; ((a[++x]++));:' || err_exit 'unsetting array variable leaves side effect'
+
+unset foo
+foo=(aa bb cc)
+foo=( ${foo[@]:1} )
+[[ ${foo[@]} == 'bb cc' ]] || err_exit "indexed array assignment using parts of array for values gives wrong result of ${foo[@]}"
+
+unset foo
+foo=([xx]=aa [yy]=bb [zz]=cc)
+foo=( ${foo[yy]} ${foo[zz]} )
+[[ ${foo[@]} == 'bb cc' ]] || err_exit "associative array assignment using parts of array for values gives wrong result of ${foo[@]}"
+
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/arrays2.sh b/src/cmd/ksh93/tests/arrays2.sh
new file mode 100755
index 0000000..70de3b0
--- /dev/null
+++ b/src/cmd/ksh93/tests/arrays2.sh
@@ -0,0 +1,212 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+for ((i=0; i < 4; i++ ))
+do for ((j=0; j < 5; j++ ))
+ do a[i][j]=$i$j
+ done
+done
+for ((i=0; i < 4; i++ ))
+do for ((j=0; j < 5; j++ ))
+ do [[ ${a[i][j]} == "$i$j" ]] || err_exit "\${a[$i][$j]} != $i$j"
+ done
+done
+for ((i=0; i < 4; i++ ))
+do j=0;for k in ${a[i][@]}
+ do [[ $k == "$i$j" ]] || err_exit "\${a[i][@]} != $i$j"
+ (( j++ ))
+ done
+done
+unset a
+a=(
+ ( 00 01 02 03 04 )
+ ( 10 11 12 13 14 15)
+ ( 20 21 22 23 24 )
+ ( 30 31 32 33 34 )
+)
+
+function check
+{
+ nameref a=$1
+ nameref b=a[2]
+ typeset c=$1
+ integer i j
+ for ((i=0; i < 4; i++ ))
+ do for ((j=0; j < 5; j++ ))
+ do [[ ${a[$i][$j]} == "$i$j" ]] || err_exit "\${$c[$i][$j]} != $i$j"
+ done
+ done
+ (( ${#a[@]} == 4 )) || err_exit "\${#$c[@]} not 4"
+ (( ${#a[0][@]} == 5 )) || err_exit "\${#$c[0][@]} not 5"
+ (( ${#a[1][@]} == 6 )) || err_exit "\${#$c[1][@]} not 6"
+ set -s -- ${!a[@]}
+ [[ ${@} == '0 1 2 3' ]] || err_exit "\${!$c[@]} not 0 1 2 3"
+ set -s -- ${!a[0][@]}
+ [[ ${@} == '0 1 2 3 4' ]] || err_exit "\${!$c[0][@]} not 0 1 2 3 4"
+ set -s -- ${!a[1][@]}
+ [[ ${@} == '0 1 2 3 4 5' ]] || err_exit "\${!$c[1][@]} not 0 1 2 3 4 5"
+ [[ $a == 00 ]] || err_exit "\$$c is not 00"
+ [[ ${a[0]} == 00 ]] || err_exit "\${$a[0]} is not 00"
+ [[ ${a[0][0]} == 00 ]] || err_exit "${a[0][0]} is not 00"
+ [[ ${a[0][0][0]} == 00 ]] || err_exit "\${$c[0][0][0]} is not 00"
+ [[ ${a[0][0][1]} == '' ]] || err_exit "\${$c[0][0][1]} is not empty"
+ [[ ${b[3]} == 23 ]] || err_exit "${!b}[3] not = 23"
+}
+
+check a
+
+unset a
+typeset -A a
+for ((i=0; i < 4; i++ ))
+do for ((j=0; j < 5; j++ ))
+ do a[$i][j]=$i$j
+ done
+done
+for ((i=0; i < 4; i++ ))
+do for ((j=0; j < 5; j++ ))
+ do [[ ${a[$i][j]} == "$i$j" ]] || err_exit "\${a[$i][$j]} == $i$j"
+ done
+done
+a[1][5]=15
+b=(
+ [0]=( 00 01 02 03 04 )
+ [1]=( 10 11 12 13 14 15)
+ [2]=( 20 21 22 23 24 )
+ [3]=( 30 31 32 33 34 )
+)
+check b
+[[ ${a[1][@]} == "${b[1][@]}" ]] || err_exit "a[1] not equal to b[1]"
+c=(
+ [0]=( [0]=00 [1]=01 [2]=02 [3]=03 [4]=04 )
+ [1]=( [0]=10 [1]=11 [2]=12 [3]=13 [4]=14 [5]=15)
+ [2]=( [0]=20 [1]=21 [2]=22 [3]=23 [4]=24 )
+ [3]=( [0]=30 [1]=31 [2]=32 [3]=33 [4]=34 )
+)
+check c
+typeset -A d
+d[0]=( [0]=00 [1]=01 [2]=02 [3]=03 [4]=04 )
+d[1]=( [0]=10 [1]=11 [2]=12 [3]=13 [4]=14 [5]=15)
+d[2]=( [0]=20 [1]=21 [2]=22 [3]=23 [4]=24 )
+d[3]=( [0]=30 [1]=31 [2]=32 [3]=33 [4]=34 )
+check d
+unset a b c d
+[[ ${a-set} ]] || err_exit "a is set after unset"
+[[ ${b-set} ]] || err_exit "b is set after unset"
+[[ ${c-set} ]] || err_exit "c is set after unset"
+[[ ${d-set} ]] || err_exit "c is set after unset"
+
+$SHELL 2> /dev/null <<\+++ || err_exit 'input of 3 dimensional array not working'
+typeset x=(
+ ( (g G) (h H) (i I) )
+ ( (d D) (e E) (f F) )
+ ( (a A) (b B) (c C) )
+)
+[[ ${x[0][0][0]} == g ]] || err_exit '${x[0][0][0]} == G'
+[[ ${x[1][1][0]} == e ]] || err_exit '${x[1][1][0]} == e'
+[[ ${x[1][1][1]} == E ]] || err_exit '${x[2][2][1]} == C'
+[[ ${x[0][2][1]} == I ]] || err_exit '${x[0][2][1]} == I'
++++
+
+typeset -a -si x=( [0]=(1 2 3) [1]=(4 5 6) [2]=(7 8 9) )
+[[ ${x[1][1]} == 5 ]] || err_exit 'changing two dimensional indexed array to short integer failed'
+unset x
+typeset -A -si x=( [0]=(1 2 3) [1]=(4 5 6) [2]=(7 8 9) )
+[[ ${x[1][2]} == 6 ]] || err_exit 'changing two dimensional associative array to short integer failed'
+
+unset ar x y
+integer -a ar
+integer i x y
+for (( i=0 ; i < 100 ; i++ ))
+do (( ar[y][x++]=i ))
+ (( x > 9 )) && (( y++ , x=0 ))
+done
+[[ ${#ar[0][*]} == 10 ]] || err_exit "\${#ar[0][*]} is '${#ar[0][*]}', should be 10"
+[[ ${#ar[*]} == 10 ]] || err_exit "\${#ar[*]} is '${#ar[*]}', should be 10"
+[[ ${ar[5][5]} == 55 ]] || err_exit "ar[5][5] is '${ar[5][5]}', should be 55"
+
+unset ar
+integer -a ar
+x=0 y=0
+for (( i=0 ; i < 81 ; i++ ))
+do nameref ar_y=ar[$y]
+ (( ar_y[x++]=i ))
+ (( x > 8 )) && (( y++ , x=0 ))
+ typeset +n ar_y
+done
+[[ ${#ar[0][*]} == 9 ]] || err_exit "\${#ar[0][*]} is '${#ar[0][*]}', should be 9"
+[[ ${#ar[*]} == 9 ]] || err_exit "\${#ar[*]} is '${#ar[*]}', should be 9"
+[[ ${ar[4][4]} == 40 ]] || err_exit "ar[4][4] is '${ar[4][4]}', should be 40"
+
+$SHELL 2> /dev/null -c 'compound c;float -a c.ar;(( c.ar[2][3][3] = 5))' || 'multi-dimensional arrays in arithemtic expressions not working'
+
+expected='typeset -a -l -E c.ar=([2]=([3]=([3]=5) ) )'
+unset c
+float c.ar
+c.ar[2][3][3]=5
+[[ $(typeset -p c.ar) == "$expected" ]] || err_exit "c.ar[2][3][3]=5;typeset -c c.ar expands to $(typeset -p c.ar)"
+
+unset values
+float -a values=( [1][3]=90 [1][4]=89 )
+function fx
+{
+ nameref arg=$1
+ [[ ${arg[0..5]} == '90 89' ]] || err_exit '${arg[0..5]} not correct where arg is a nameref to values[1]'
+}
+fx values[1]
+
+function test_short_integer
+{
+ compound out=( typeset stdout stderr ; integer res )
+ compound -r -a tests=(
+ ( cmd='integer -s -r -a x=( 1 2 3 ) ; print "${x[2]}"' stdoutpattern='3' )
+ ( cmd='integer -s -r -A x=( [0]=1 [1]=2 [2]=3 ) ; print "${x[2]}"' stdoutpattern='3' )
+ # 2D integer arrays: the following two tests crash for both "integer -s" and "integer"
+ ( cmd='integer -r -a x=( [0]=( [0]=1 [1]=2 [2]=3 ) [1]=( [0]=4 [1]=5 [2]=6 ) [2]=( [0]=7 [1]=8 [2]=9 ) ) ; print "${x[1][1]}"' stdoutpattern='5' )
+ ( cmd='integer -s -r -a x=( [0]=( [0]=1 [1]=2 [2]=3 ) [1]=( [0]=4 [1]=5 [2]=6 ) [2]=( [0]=7 [1]=8 [2]=9 ) ) ; print "${x[1][1]}"' stdoutpattern='5' )
+ )
+ typeset testname
+ integer i
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ nameref tst=tests[i]
+ testname="${0}/${i}"
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -o errexit -c "${tst.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" == ${tst.stdoutpattern} ]] || err_exit "${testname}: Expected stdout to match $(printf '%q\n' "${tst.stdoutpattern}"), got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "${testname}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ (( out.res == 0 )) || err_exit "${testname}: Unexpected exit code ${out.res}"
+ done
+
+ return 0
+}
+# run tests
+test_short_integer
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/attributes.sh b/src/cmd/ksh93/tests/attributes.sh
new file mode 100755
index 0000000..9deca59
--- /dev/null
+++ b/src/cmd/ksh93/tests/attributes.sh
@@ -0,0 +1,418 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+r=readonly u=Uppercase l=Lowercase i=22 i8=10 L=abc L5=def uL5=abcdef xi=20
+x=export t=tagged H=hostname LZ5=026 RZ5=026 Z5=123 lR5=ABcdef R5=def n=l
+for option in u l i i8 L L5 LZ5 RZ5 Z5 r x H t R5 uL5 lR5 xi n
+do typeset -$option $option
+done
+(r=newval) 2> /dev/null && err_exit readonly attribute fails
+i=i+5
+if ((i != 27))
+then err_exit integer attributes fails
+fi
+if [[ $i8 != 8#12 ]]
+then err_exit integer base 8 fails
+fi
+if [[ $u != UPPERCASE ]]
+then err_exit uppercase fails
+fi
+if [[ $l != lowercase ]]
+then err_exit lowercase fails
+fi
+if [[ $n != lowercase ]]
+then err_exit reference variables fail
+fi
+if [[ t=tagged != $(typeset -t) ]]
+then err_exit tagged fails
+fi
+if [[ t != $(typeset +t) ]]
+then err_exit tagged fails
+fi
+if [[ $Z5 != 00123 ]]
+then err_exit zerofill fails
+fi
+if [[ $RZ5 != 00026 ]]
+then err_exit right zerofill fails
+fi
+L=12345
+if [[ $L != 123 ]]
+then err_exit leftjust fails
+fi
+if [[ $L5 != "def " ]]
+then err_exit leftjust fails
+fi
+if [[ $uL5 != ABCDE ]]
+then err_exit leftjust uppercase fails
+fi
+if [[ $lR5 != bcdef ]]
+then err_exit rightjust fails
+fi
+if [[ $R5 != " def" ]]
+then err_exit rightjust fails
+fi
+if [[ $($SHELL -c 'echo $x') != export ]]
+then err_exit export fails
+fi
+if [[ $($SHELL -c 'xi=xi+4;echo $xi') != 24 ]]
+then err_exit export attributes fails
+fi
+x=$(foo=abc $SHELL <<!
+ foo=bar
+ $SHELL -c 'print \$foo'
+!
+)
+if [[ $x != bar ]]
+then err_exit 'environment variables require re-export'
+fi
+(typeset + ) > /dev/null 2>&1 || err_exit 'typeset + not working'
+(typeset -L-5 buf="A" 2>/dev/null)
+if [[ $? == 0 ]]
+then err_exit 'typeset allows negative field for left/right adjust'
+fi
+a=b
+readonly $a=foo
+if [[ $b != foo ]]
+then err_exit 'readonly $a=b not working'
+fi
+if [[ $(export | grep '^PATH=') != PATH=* ]]
+then err_exit 'export not working'
+fi
+picture=(
+ bitmap=/fruit
+ size=(typeset -E x=2.5)
+)
+string="$(print $picture)"
+if [[ "${string}" != *'size=( typeset -E'* ]]
+then err_exit 'print of compound exponential variable not working'
+fi
+sz=(typeset -E y=2.2)
+string="$(print $sz)"
+if [[ "${sz}" == *'typeset -E -F'* ]]
+then err_exit 'print of exponential shows both -E and -F attributes'
+fi
+print 'typeset -i m=48/4+1;print -- $m' > $tmp/script
+chmod +x $tmp/script
+typeset -Z2 m
+if [[ $($tmp/script) != 13 ]]
+then err_exit 'attributes not cleared for script execution'
+fi
+print 'print VAR=$VAR' > $tmp/script
+typeset -L70 VAR=var
+$tmp/script > $tmp/script.1
+[[ $(< $tmp/script.1) == VAR= ]] || err_exit 'typeset -L should not be inherited'
+typeset -Z LAST=00
+unset -f foo
+function foo
+{
+ if [[ $1 ]]
+ then LAST=$1
+ else ((LAST++))
+ fi
+}
+foo 1
+if (( ${#LAST} != 2 ))
+then err_exit 'LAST!=2'
+fi
+foo
+if (( ${#LAST} != 2 ))
+then err_exit 'LAST!=2'
+fi
+[[ $(set | grep LAST) == LAST=02 ]] || err_exit "LAST not correct in set list"
+set -a
+unset foo
+foo=bar
+if [[ $(export | grep ^foo=) != 'foo=bar' ]]
+then err_exit 'all export not working'
+fi
+unset foo
+read foo <<!
+bar
+!
+if [[ $(export | grep ^foo=) != 'foo=bar' ]]
+then err_exit 'all export not working with read'
+fi
+if [[ $(typeset | grep PS2) == PS2 ]]
+then err_exit 'typeset without arguments outputs names without attributes'
+fi
+unset a z q x
+w1=hello
+w2=world
+t1="$w1 $w2"
+if (( 'a' == 97 ))
+then b1=aGVsbG8gd29ybGQ=
+ b2=aGVsbG8gd29ybGRoZWxsbyB3b3JsZA==
+else b1=iIWTk5ZAppaZk4Q=
+ b2=iIWTk5ZAppaZk4SIhZOTlkCmlpmThA==
+fi
+z=$b1
+typeset -b x=$b1
+[[ $x == "$z" ]] || print -u2 'binary variable not expanding correctly'
+[[ $(printf "%B" x) == $t1 ]] || err_exit 'typeset -b not working'
+typeset -b -Z5 a=$b1
+[[ $(printf "%B" a) == $w1 ]] || err_exit 'typeset -b -Z5 not working'
+typeset -b q=$x$x
+[[ $q == $b2 ]] || err_exit 'typeset -b not working with concatination'
+[[ $(printf "%B" q) == $t1$t1 ]] || err_exit 'typeset -b concatination not working'
+x+=$b1
+[[ $x == $b2 ]] || err_exit 'typeset -b not working with append'
+[[ $(printf "%B" x) == $t1$t1 ]] || err_exit 'typeset -b append not working'
+typeset -b -Z20 z=$b1
+(( $(printf "%B" z | wc -c) == 20 )) || err_exit 'typeset -b -Z20 not storing 20 bytes'
+{
+ typeset -b v1 v2
+ read -N11 v1
+ read -N22 v2
+} << !
+hello worldhello worldhello world
+!
+[[ $v1 == "$b1" ]] || err_exit "v1=$v1 should be $b1"
+[[ $v2 == "$x" ]] || err_exit "v1=$v2 should be $x"
+if env '!=1' >/dev/null 2>&1
+then [[ $(env '!=1' $SHELL -c 'echo ok' 2>/dev/null) == ok ]] || err_exit 'malformed environment terminates shell'
+fi
+unset var
+typeset -b var
+printf '12%Z34' | read -r -N 5 var
+[[ $var == MTIAMzQ= ]] || err_exit 'binary files with zeros not working'
+unset var
+if command typeset -usi var=0xfffff 2> /dev/null
+then (( $var == 0xffff )) || err_exit 'unsigned short integers not working'
+else err_exit 'typeset -usi cannot be used for unsigned short'
+fi
+[[ $($SHELL -c 'unset foo;typeset -Z2 foo; print ${foo:-3}' 2> /dev/null) == 3 ]] || err_exit '${foo:-3} not 3 when typeset -Z2 field undefined'
+[[ $($SHELL -c 'unset foo;typeset -Z2 foo; print ${foo:=3}' 2> /dev/null) == 03 ]] || err_exit '${foo:=-3} not 3 when typeset -Z2 foo undefined'
+unset foo bar
+unset -f fun
+function fun
+{
+ export foo=hello
+ typeset -x bar=world
+ [[ $foo == hello ]] || err_exit 'export scoping problem in function'
+}
+fun
+[[ $(export | grep foo) == 'foo=hello' ]] || err_exit 'export not working in functions'
+[[ $(export | grep bar) ]] && err_exit 'typeset -x not local'
+[[ $($SHELL -c 'typeset -r IFS=;print -r $(pwd)' 2> /dev/null) == "$(pwd)" ]] || err_exit 'readonly IFS causes command substitution to fail'
+fred[66]=88
+[[ $(typeset -pa) == *fred* ]] || err_exit 'typeset -pa not working'
+unset x y z
+typeset -LZ3 x=abcd y z=00abcd
+y=03
+[[ $y == "3 " ]] || err_exit '-LZ3 not working for value 03'
+[[ $x == "abc" ]] || err_exit '-LZ3 not working for value abcd'
+[[ $x == "abc" ]] || err_exit '-LZ3 not working for value 00abcd'
+unset x z
+set +a
+[[ $(typeset -p z) ]] && err_exit "typeset -p for z undefined failed"
+unset z
+x='typeset -i z=45'
+eval "$x"
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%=*}" ]] || err_exit "typeset +p for '$x' failed"
+unset z
+x='typeset -a z=(a b c)'
+eval "$x"
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%=*}" ]] || err_exit "typeset +p for '$x' failed"
+unset z
+x='typeset -C z=(
+ foo=bar
+ xxx=bam
+)'
+eval "$x"
+x=${x//$'\t'}
+x=${x//$'(\n'/'('}
+x=${x//$'\n'/';'}
+x=${x%';)'}')'
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%%=*}" ]] || err_exit "typeset +p for '$x' failed"
+unset z
+x='typeset -A z=([bar]=bam [xyz]=bar)'
+eval "$x"
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%%=*}" ]] || err_exit "typeset +p for '$x' failed"
+unset z
+foo=abc
+x='typeset -n z=foo'
+eval "$x"
+[[ $(typeset -p z) == "$x" ]] || err_exit "typeset -p for '$x' failed"
+[[ $(typeset +p z) == "${x%%=*}" ]] || err_exit "typeset +p for '$x' failed"
+typeset +n z
+unset foo z
+typeset -T Pt_t=(
+ float x=1 y=2
+)
+Pt_t z
+x=${z//$'\t'}
+x=${x//$'(\n'/'('}
+x=${x//$'\n'/';'}
+x=${x%';)'}')'
+[[ $(typeset -p z) == "Pt_t z=$x" ]] || err_exit "typeset -p for type failed"
+[[ $(typeset +p z) == "Pt_t z" ]] || err_exit "typeset +p for type failed"
+unset z
+function foo
+{
+ typeset -p bar
+}
+bar=xxx
+[[ $(foo) == bar=xxx ]] || err_exit 'typeset -p not working inside a function'
+unset foo
+typeset -L5 foo
+[[ $(typeset -p foo) == 'typeset -L 5 foo' ]] || err_exit 'typeset -p not working for variables with attributes but without a value'
+{ $SHELL <<- EOF
+ typeset -L3 foo=aaa
+ typeset -L6 foo=bbbbbb
+ [[ \$foo == bbbbbb ]]
+EOF
+} || err_exit 'typeset -L should not preserve old attributes'
+{ $SHELL <<- EOF
+ typeset -R3 foo=aaa
+ typeset -R6 foo=bbbbbb
+ [[ \$foo == bbbbbb ]]
+EOF
+} 2> /dev/null || err_exit 'typeset -R should not preserve old attributes'
+
+expected='YWJjZGVmZ2hpag=='
+unset foo
+typeset -b -Z10 foo
+read foo <<< 'abcdefghijklmnop'
+[[ $foo == "$expected" ]] || err_exit 'read foo, where foo is "typeset -b -Z10" not working'
+unset foo
+typeset -b -Z10 foo
+read -N10 foo <<< 'abcdefghijklmnop'
+[[ $foo == "$expected" ]] || err_exit 'read -N10 foo, where foo is "typeset -b -Z10" not working'
+unset foo
+typeset -b -A foo
+read -N10 foo[4] <<< 'abcdefghijklmnop'
+[[ ${foo[4]} == "$expected" ]] || err_exit 'read -N10 foo, where foo is "typeset -b -A" foo not working'
+unset foo
+typeset -b -a foo
+read -N10 foo[4] <<< 'abcdefghijklmnop'
+[[ ${foo[4]} == "$expected" ]] || err_exit 'read -N10 foo, where foo is "typeset -b -a" foo not working'
+[[ $(printf %B foo[4]) == abcdefghij ]] || err_exit 'printf %B for binary associative array element not working'
+[[ $(printf %B foo[4]) == abcdefghij ]] || err_exit 'printf %B for binary indexed array element not working'
+unset foo
+
+$SHELL 2> /dev/null -c 'export foo=(bar=3)' && err_exit 'compound variables cannot be exported'
+
+$SHELL -c 'builtin date' >/dev/null 2>&1 &&
+{
+
+# check env var changes against a builtin that uses the env var
+
+SEC=1234252800
+ETZ=EST5EDT
+EDT=03
+PTZ=PST8PDT
+PDT=00
+
+CMD="date -f%H \\#$SEC"
+
+export TZ=$ETZ
+
+set -- \
+ "$EDT $PDT $EDT" "" "TZ=$PTZ" "" \
+ "$EDT $PDT $EDT" "" "TZ=$PTZ" "TZ=$ETZ" \
+ "$EDT $PDT $EDT" "TZ=$ETZ" "TZ=$PTZ" "TZ=$ETZ" \
+ "$PDT $EDT $PDT" "TZ=$PTZ" "" "TZ=$PTZ" \
+ "$PDT $EDT $PDT" "TZ=$PTZ" "TZ=$ETZ" "TZ=$PTZ" \
+ "$EDT $PDT $EDT" "foo=bar" "TZ=$PTZ" "TZ=$ETZ" \
+
+while (( $# >= 4 ))
+do exp=$1
+ got=$(print $($SHELL -c "builtin date; $2 $CMD; $3 $CMD; $4 $CMD"))
+ [[ $got == $exp ]] || err_exit "[ '$2' '$3' '$4' ] env sequence failed -- expected '$exp', got '$got'"
+ shift 4
+done
+
+}
+
+unset v
+typeset -H v=/dev/null
+[[ $v == *nul* ]] || err_exit 'typeset -H for /dev/null not working'
+
+unset x
+(typeset +C x) 2> /dev/null && err_exit 'typeset +C should be an error'
+(typeset +A x) 2> /dev/null && err_exit 'typeset +A should be an error'
+(typeset +a x) 2> /dev/null && err_exit 'typeset +a should be an error'
+
+unset x
+{
+x=$($SHELL -c 'integer -s x=5;print -r -- $x')
+} 2> /dev/null
+[[ $x == 5 ]] || err_exit 'integer -s not working'
+
+[[ $(typeset -l) == *namespace*.sh* ]] && err_exit 'typeset -l should not contain namespace .sh'
+
+unset got
+typeset -u got
+exp=100
+((got=$exp))
+[[ $got == $exp ]] || err_exit "typeset -l fails on numeric value -- expected '$exp', got '$got'"
+
+unset s
+typeset -a -u s=( hello world chicken )
+[[ ${s[2]} == CHICKEN ]] || err_exit 'typeset -u not working with indexed arrays'
+unset s
+typeset -A -u s=( [1]=hello [0]=world [2]=chicken )
+[[ ${s[2]} == CHICKEN ]] || err_exit 'typeset -u not working with associative arrays'
+expected=$'(\n\t[0]=WORLD\n\t[1]=HELLO\n\t[2]=CHICKEN\n)'
+[[ $(print -v s) == "$expected" ]] || err_exit 'typeset -u for associative array does not display correctly'
+
+unset s
+if command typeset -M totitle s 2> /dev/null
+then [[ $(typeset +p s) == 'typeset -M totitle s' ]] || err_exit 'typeset -M totitle does not display correctly with typeset -p'
+fi
+
+{ $SHELL <<- \EOF
+ compound -a a1
+ for ((i=1 ; i < 100 ; i++ ))
+ do [[ "$( typeset + a1[$i] )" == '' ]] && a1[$i].text='hello'
+ done
+ [[ ${a1[70].text} == hello ]]
+EOF
+} 2> /dev/null
+(( $? )) && err_exit 'typeset + a[i] not working'
+
+typeset groupDB="" userDB=""
+typeset -l -L1 DBPick=""
+[[ -n "$groupDB" ]] && err_exit 'typeset -l -L1 causes unwanted side effect'
+
+HISTFILE=foo
+typeset -u PS1='hello --- '
+HISTFILE=foo
+[[ $HISTFILE == foo ]] || err_exit 'typeset -u PS1 affects HISTFILE'
+
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/basic.sh b/src/cmd/ksh93/tests/basic.sh
new file mode 100755
index 0000000..2941543
--- /dev/null
+++ b/src/cmd/ksh93/tests/basic.sh
@@ -0,0 +1,513 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+# test basic file operations like redirection, pipes, file expansion
+set -- \
+ go+r 0000 \
+ go-r 0044 \
+ ug=r 0330 \
+ go+w 0000 \
+ go-w 0022 \
+ ug=w 0550 \
+ go+x 0000 \
+ go-x 0011 \
+ ug=x 0660 \
+ go-rx 0055 \
+ uo-wx 0303 \
+ ug-rw 0660 \
+ o= 0007
+while (( $# >= 2 ))
+do umask 0
+ umask $1
+ g=$(umask)
+ [[ $g == $2 ]] || err_exit "umask 0; umask $1 failed -- expected $2, got $g"
+ shift 2
+done
+umask u=rwx,go=rx || err_exit "umask u=rws,go=rx failed"
+if [[ $(umask -S) != u=rwx,g=rx,o=rx ]]
+then err_exit 'umask -S incorrect'
+fi
+pwd=$PWD
+[[ $SHELL != /* ]] && SHELL=$pwd/$SHELL
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+um=$(umask -S)
+( umask 0777; > foobar )
+rm -f foobar
+> foobar
+[[ -r foobar ]] || err_exit 'umask not being restored after subshell'
+umask "$um"
+rm -f foobar
+# optimizer bug test
+> foobar
+for i in 1 2
+do print foobar*
+ rm -f foobar
+done > out
+if [[ "$(<out)" != "foobar"$'\n'"foobar*" ]]
+then print -u2 "optimizer bug with file expansion"
+fi
+rm -f out foobar
+mkdir dir
+if [[ $(print */) != dir/ ]]
+then err_exit 'file expansion with trailing / not working'
+fi
+if [[ $(print *) != dir ]]
+then err_exit 'file expansion with single file not working'
+fi
+print hi > .foo
+if [[ $(print *) != dir ]]
+then err_exit 'file expansion leading . not working'
+fi
+date > dat1 || err_exit "date > dat1 failed"
+test -r dat1 || err_exit "dat1 is not readable"
+x=dat1
+cat <$x > dat2 || err_exit "cat < $x > dat2 failed"
+cat dat1 dat2 | cat | cat | cat > dat3 || err_exit "cat pipe failed"
+cat > dat4 <<!
+$(date)
+!
+cat dat1 dat2 | cat | cat | cat > dat5 &
+wait $!
+set -- dat*
+if (( $# != 5 ))
+then err_exit "dat* matches only $# files"
+fi
+if (command > foo\\abc) 2> /dev/null
+then set -- foo*
+ if [[ $1 != 'foo\abc' ]]
+ then err_exit 'foo* does not match foo\abc'
+ fi
+fi
+if ( : > TT* && : > TTfoo ) 2>/dev/null
+then set -- TT*
+ if (( $# < 2 ))
+ then err_exit 'TT* not expanding when file TT* exists'
+ fi
+fi
+cd ~- || err_exit "cd back failed"
+cat > $tmp/script <<- !
+ #! $SHELL
+ print -r -- \$0
+!
+chmod 755 $tmp/script
+if [[ $($tmp/script) != "$tmp/script" ]]
+then err_exit '$0 not correct for #! script'
+fi
+bar=foo
+eval foo=\$bar
+if [[ $foo != foo ]]
+then err_exit 'eval foo=\$bar not working'
+fi
+bar='foo=foo\ bar'
+eval $bar
+if [[ $foo != 'foo bar' ]]
+then err_exit 'eval foo=\$bar, with bar="foo\ bar" not working'
+fi
+cd /tmp
+cd ../../tmp || err_exit "cd ../../tmp failed"
+if [[ $PWD != /tmp ]]
+then err_exit 'cd ../../tmp is not /tmp'
+fi
+( sleep 2; cat <<!
+foobar
+!
+) | cat > $tmp/foobar &
+wait $!
+foobar=$( < $tmp/foobar)
+if [[ $foobar != foobar ]]
+then err_exit "$foobar is not foobar"
+fi
+{
+ print foo
+ /bin/echo bar
+ print bam
+} > $tmp/foobar
+if [[ $( < $tmp/foobar) != $'foo\nbar\nbam' ]]
+then err_exit "output file pointer not shared correctly"
+fi
+cat > $tmp/foobar <<\!
+ print foo
+ /bin/echo bar
+ print bam
+!
+chmod +x $tmp/foobar
+if [[ $($tmp/foobar) != $'foo\nbar\nbam' ]]
+then err_exit "script not working"
+fi
+if [[ $($tmp/foobar | /bin/cat) != $'foo\nbar\nbam' ]]
+then err_exit "script | cat not working"
+fi
+if [[ $( $tmp/foobar) != $'foo\nbar\nbam' ]]
+then err_exit "output file pointer not shared correctly"
+fi
+rm -f $tmp/foobar
+x=$( (print foo) ; (print bar) )
+if [[ $x != $'foo\nbar' ]]
+then err_exit " ( (print foo);(print bar ) failed"
+fi
+x=$( (/bin/echo foo) ; (print bar) )
+if [[ $x != $'foo\nbar' ]]
+then err_exit " ( (/bin/echo);(print bar ) failed"
+fi
+x=$( (/bin/echo foo) ; (/bin/echo bar) )
+if [[ $x != $'foo\nbar' ]]
+then err_exit " ( (/bin/echo);(/bin/echo bar ) failed"
+fi
+cat > $tmp/script <<\!
+if [[ -p /dev/fd/0 ]]
+then builtin cat
+ cat - > /dev/null
+ [[ -p /dev/fd/0 ]] && print ok
+else print no
+fi
+!
+chmod +x $tmp/script
+case $( (print) | $tmp/script;:) in
+ok) ;;
+no) err_exit "[[ -p /dev/fd/0 ]] fails for standard input pipe" ;;
+*) err_exit "builtin replaces standard input pipe" ;;
+esac
+print 'print $0' > $tmp/script
+print ". $tmp/script" > $tmp/scriptx
+chmod +x $tmp/scriptx
+if [[ $($tmp/scriptx) != $tmp/scriptx ]]
+then err_exit '$0 not correct for . script'
+fi
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+print ./b > ./a; print ./c > b; print ./d > c; print ./e > d; print "echo \"hello there\"" > e
+chmod 755 a b c d e
+x=$(./a)
+if [[ $x != "hello there" ]]
+then err_exit "nested scripts failed"
+fi
+x=$( (./a) | cat)
+if [[ $x != "hello there" ]]
+then err_exit "scripts in subshells fail"
+fi
+cd ~- || err_exit "cd back failed"
+x=$( (/bin/echo foo) 2> /dev/null )
+if [[ $x != foo ]]
+then err_exit "subshell in command substitution fails"
+fi
+exec 9>& 1
+exec 1>&-
+x=$(print hello)
+if [[ $x != hello ]]
+then err_exit "command subsitution with stdout closed failed"
+fi
+exec >& 9
+cd $pwd
+x=$(cat <<\! | $SHELL
+/bin/echo | /bin/cat
+/bin/echo hello
+!
+)
+if [[ $x != $'\n'hello ]]
+then err_exit "$SHELL not working when standard input is a pipe"
+fi
+x=$( (/bin/echo hello) 2> /dev/null )
+if [[ $x != hello ]]
+then err_exit "subshell in command substitution with 1 closed fails"
+fi
+cat > $tmp/script <<- \!
+read line 2> /dev/null
+print done
+!
+if [[ $($SHELL $tmp/script <&-) != done ]]
+then err_exit "executing script with 0 closed fails"
+fi
+trap '' INT
+cat > $tmp/script <<- \!
+trap 'print bad' INT
+kill -s INT $$
+print good
+!
+chmod +x $tmp/script
+if [[ $($SHELL $tmp/script) != good ]]
+then err_exit "traps ignored by parent not ignored"
+fi
+trap - INT
+cat > $tmp/script <<- \!
+read line
+/bin/cat
+!
+if [[ $($SHELL $tmp/script <<!
+one
+two
+!
+) != two ]]
+then err_exit "standard input not positioned correctly"
+fi
+word=$(print $'foo\nbar' | { read line; /bin/cat;})
+if [[ $word != bar ]]
+then err_exit "pipe to { read line; /bin/cat;} not working"
+fi
+word=$(print $'foo\nbar' | ( read line; /bin/cat) )
+if [[ $word != bar ]]
+then err_exit "pipe to ( read line; /bin/cat) not working"
+fi
+if [[ $(print x{a,b}y) != 'xay xby' ]]
+then err_exit 'brace expansion not working'
+fi
+if [[ $(for i in foo bar
+ do ( tgz=$(print $i)
+ print $tgz)
+ done) != $'foo\nbar' ]]
+then err_exit 'for loop subshell optimizer bug'
+fi
+unset a1
+optbug()
+{
+ set -A a1 foo bar bam
+ integer i
+ for ((i=0; i < 3; i++))
+ do
+ (( ${#a1[@]} < 2 )) && return 0
+ set -- "${a1[@]}"
+ shift
+ set -A a1 -- "$@"
+ done
+ return 1
+}
+optbug || err_exit 'array size optimzation bug'
+wait # not running --pipefail which would interfere with subsequent tests
+: $(jobs -p) # required to clear jobs for next jobs -p (interactive side effect)
+sleep 20 &
+pids=$!
+if [[ $(jobs -p) != $! ]]
+then err_exit 'jobs -p not reporting a background job'
+fi
+sleep 20 &
+pids="$pids $!"
+foo()
+{
+ set -- $(jobs -p)
+ (( $# == 2 )) || err_exit "$# jobs not reported -- 2 expected"
+}
+foo
+kill $pids
+
+[[ $( (trap 'print alarm' ALRM; sleep 4) & sleep 2; kill -ALRM $!; sleep 2; wait) == alarm ]] || err_exit 'ALRM signal not working'
+[[ $($SHELL -c 'trap "" HUP; $SHELL -c "(sleep 2;kill -HUP $$)& sleep 4;print done"') != done ]] && err_exit 'ignored traps not being ignored'
+[[ $($SHELL -c 'o=foobar; for x in foo bar; do (o=save);print $o;done' 2> /dev/null ) == $'foobar\nfoobar' ]] || err_exit 'for loop optimization subshell bug'
+command exec 3<> /dev/null
+if cat /dev/fd/3 >/dev/null 2>&1 || whence mkfifo > /dev/null
+then [[ $($SHELL -c 'cat <(print foo)' 2> /dev/null) == foo ]] || err_exit 'process substitution not working'
+ [[ $($SHELL -c $'tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!!
+ line0
+ line1
+ line2
+ !!!
+ wait
+ cat '$tmp/scriptx 2> /dev/null) == line1 ]] || err_exit '>() process substitution fails'
+ > $tmp/scriptx
+ [[ $($SHELL -c $'
+ for i in 1
+ do tee >(grep \'1$\' > '$tmp/scriptx$') > /dev/null <<- \!!!
+ line0
+ line1
+ line2
+ !!!
+ done
+ wait
+ cat '$tmp/scriptx 2>> /dev/null) == line1 ]] || err_exit '>() process substitution fails in for loop'
+ [[ $({ $SHELL -c 'cat <(for i in x y z; do print $i; done)';} 2> /dev/null) == $'x\ny\nz' ]] ||
+ err_exit 'process substitution of compound commands not working'
+fi
+[[ $($SHELL -r 'command -p :' 2>&1) == *restricted* ]] || err_exit 'command -p not restricted'
+print cat > $tmp/scriptx
+chmod +x $tmp/scriptx
+[[ $($SHELL -c "print foo | $tmp/scriptx ;:" 2> /dev/null ) == foo ]] || err_exit 'piping into script fails'
+[[ $($SHELL -c 'X=1;print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 1 ]] || err_exit 'x=1;${x:=$(..."...")} failure'
+[[ $($SHELL -c 'print -r -- ${X:=$(expr "a(0)" : '"'a*(\([^)]\))')}'" 2> /dev/null) == 0 ]] || err_exit '${x:=$(..."...")} failure'
+if cat /dev/fd/3 >/dev/null 2>&1 || whence mkfifo > /dev/null
+then [[ $(cat <(print hello) ) == hello ]] || err_exit "process substitution not working outside for or while loop"
+ $SHELL -c '[[ $(for i in 1;do cat <(print hello);done ) == hello ]]' 2> /dev/null|| err_exit "process substitution not working in for or while loop"
+fi
+exec 3> /dev/null
+print 'print foo "$@"' > $tmp/scriptx
+[[ $( print "($tmp/scriptx bar)" | $SHELL 2>/dev/null) == 'foo bar' ]] || err_exit 'script pipe to shell fails'
+print "#! $SHELL" > $tmp/scriptx
+print 'print -- $0' >> $tmp/scriptx
+chmod +x $tmp/scriptx
+[[ $($tmp/scriptx) == $tmp/scriptx ]] || err_exit "\$0 is $0 instead of $tmp/scriptx"
+cat > $tmp/scriptx <<- \EOF
+ myfilter() { x=$(print ok | cat); print -r -- $SECONDS;}
+ set -o pipefail
+ sleep 3 | myfilter
+EOF
+(( $($SHELL $tmp/scriptx) > 2.0 )) && err_exit 'command substitution causes pipefail option to hang'
+exec 3<&-
+( typeset -r foo=bar) 2> /dev/null || err_exit 'readonly variables set in a subshell cannot unset'
+$SHELL -c 'x=${ print hello;}; [[ $x == hello ]]' 2> /dev/null || err_exit '${ command;} not supported'
+$SHELL 2> /dev/null <<- \EOF || err_exit 'multiline ${...} command substitution not supported'
+ x=${
+ print hello
+ }
+ [[ $x == hello ]]
+EOF
+$SHELL 2> /dev/null <<- \EOF || err_exit '${...} command substitution with side effects not supported '
+ y=bye
+ x=${
+ y=hello
+ print hello
+ }
+ [[ $y == $x ]]
+EOF
+$SHELL 2> /dev/null <<- \EOF || err_exit 'nested ${...} command substitution not supported'
+ x=${
+ print ${ print hello;} $(print world)
+ }
+ [[ $x == 'hello world' ]]
+EOF
+$SHELL 2> /dev/null <<- \EOF || err_exit 'terminating } is not a reserved word with ${ command }'
+ x=${ { print -n } ; print -n hello ; } ; print ' world' }
+ [[ $x == '}hello world' ]]
+EOF
+$SHELL 2> /dev/null <<- \EOF || err_exit '${ command;}xxx not working'
+ f()
+ {
+ print foo
+ }
+ [[ ${ f;}bar == foobar ]]
+EOF
+
+unset foo
+[[ ! ${foo[@]} ]] || err_exit '${foo[@]} is not empty when foo is unset'
+[[ ! ${foo[3]} ]] || err_exit '${foo[3]} is not empty when foo is unset'
+[[ $(print "[${ print foo }]") == '[foo]' ]] || err_exit '${...} not working when } is followed by ]'
+[[ $(print "${ print "[${ print foo }]" }") == '[foo]' ]] || err_exit 'nested ${...} not working when } is followed by ]'
+unset foo
+foo=$(false) > /dev/null && err_exit 'failed command substitution with redirection not returning false'
+expected=foreback
+got=$(print -n fore; (sleep 2;print back)&)
+[[ $got == $expected ]] || err_exit "command substitution background process output error -- got '$got', expected '$expected'"
+
+binfalse=$(whence -p false)
+for false in false $binfalse
+do x=$($false) && err_exit "x=\$($false) should fail"
+ $($false) && err_exit "\$($false) should fail"
+ $($false) > /dev/null && err_exit "\$($false) > /dev/null should fail"
+done
+if env x-a=y >/dev/null 2>&1
+then [[ $(env 'x-a=y' $SHELL -c 'env | grep x-a') == *x-a=y* ]] || err_exit 'invalid environment variables not preserved'
+fi
+float s=SECONDS
+sleep=$(whence -p sleep)
+for i in 1 2
+do print $i
+done | while read sec; do ( $sleep $sec; $sleep $sec) done
+(( (SECONDS-s) < 4)) && err_exit '"command | while read...done" finishing too fast'
+s=SECONDS
+set -o pipefail
+for ((i=0; i < 30; i++))
+do print hello
+ sleep .1
+done | $sleep 1
+(( (SECONDS-s) < 2 )) || err_exit 'early termination not causing broken pipe'
+[[ $({ trap 'print trap' 0; print -n | $(whence -p cat); } & wait $!) == trap ]] || err_exit 'trap on exit not getting triggered'
+var=$({ trap 'print trap' ERR; print -n | $binfalse; } & wait $!)
+[[ $var == trap ]] || err_exit 'trap on ERR not getting triggered'
+
+exp=
+got=$(
+ function fun
+ {
+ $binfalse && echo FAILED
+ }
+ : works if this line deleted : |
+ fun
+ : works if this line deleted :
+)
+[[ $got == $exp ]] || err_exit "pipe to function with conditional fails -- expected '$exp', got '$got'"
+got=$(
+ : works if this line deleted : |
+ { $binfalse && echo FAILED; }
+ : works if this line deleted :
+)
+[[ $got == $exp ]] || err_exit "pipe to { ... } with conditional fails -- expected '$exp', got '$got'"
+
+got=$(
+ : works if this line deleted : |
+ ( $binfalse && echo FAILED )
+ : works if this line deleted :
+)
+[[ $got == $exp ]] || err_exit "pipe to ( ... ) with conditional fails -- expected '$exp', got '$got'"
+
+( $SHELL -c 'trap : DEBUG; x=( $foo); exit 0') 2> /dev/null || err_exit 'trap DEBUG fails'
+
+bintrue=$(whence -p true)
+set -o pipefail
+float start=$SECONDS end
+for ((i=0; i < 2; i++))
+do print foo
+ sleep 1.5
+done | { read; $bintrue; end=$SECONDS ;}
+(( (SECONDS-start) < 1 )) && err_exit "pipefail not waiting for pipe to finish"
+set +o pipefail
+(( (SECONDS-end) > 2 )) && err_exit "pipefail causing $bintrue to wait for other end of pipe"
+
+
+{ env A__z=C+SHLVL $SHELL -c : ;} 2> /dev/null || err_exit "SHLVL with wrong attribute fails"
+
+if [[ $bintrue ]]
+then float t0=SECONDS
+ { time sleep 1.5 | $bintrue ;} 2> /dev/null
+ (( (SECONDS-t0) < 1 )) && err_exit 'time not waiting for pipeline to complete'
+fi
+
+cat > $tmp/foo.sh <<- \EOF
+ eval "cat > /dev/null < /dev/null"
+ sleep 1
+EOF
+float sec=SECONDS
+. $tmp/foo.sh | cat > /dev/null
+(( (SECONDS-sec) < .7 )) && err_exit '. script does not restore output redirection with eval'
+
+file=$tmp/foobar
+builtin cat
+for ((n=0; n < 1000; n++))
+do
+ > $file
+ { sleep .001;echo $? >$file;} | cat > /dev/null
+ if [[ ! -s $file ]]
+ then err_exit 'output from pipe is lost with pipe to builtin'
+ break;
+ fi
+done
+
+$SHELL -c 'kill -0 123456789123456789123456789' 2> /dev/null && err_exit 'kill not catching process id overflows'
+
+[[ $($SHELL -c '{ cd..; print ok;}' 2> /dev/null) == ok ]] || err_exit 'command name ending in .. causes shell to abort'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/bracket.sh b/src/cmd/ksh93/tests/bracket.sh
new file mode 100755
index 0000000..cfe4055
--- /dev/null
+++ b/src/cmd/ksh93/tests/bracket.sh
@@ -0,0 +1,340 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+null=''
+if [[ ! -z $null ]]
+then err_exit "-z: null string should be of zero length"
+fi
+file=$tmp/original
+newer_file=$tmp/newer
+if [[ -z $file ]]
+then err_exit "-z: $file string should not be of zero length"
+fi
+if [[ -a $file ]]
+then err_exit "-a: $file shouldn't exist"
+fi
+if [[ -e $file ]]
+then err_exit "-e: $file shouldn't exist"
+fi
+> $file
+if [[ ! -a $file ]]
+then err_exit "-a: $file should exist"
+fi
+if [[ ! -e $file ]]
+then err_exit "-e: $file should exist"
+fi
+chmod 777 $file
+if [[ ! -r $file ]]
+then err_exit "-r: $file should be readable"
+fi
+if [[ ! -w $file ]]
+then err_exit "-w: $file should be writable"
+fi
+if [[ ! -w $file ]]
+then err_exit "-x: $file should be executable"
+fi
+if [[ ! -w $file || ! -r $file ]]
+then err_exit "-rw: $file should be readable/writable"
+fi
+if [[ -s $file ]]
+then err_exit "-s: $file should be of zero size"
+fi
+if [[ ! -f $file ]]
+then err_exit "-f: $file should be an ordinary file"
+fi
+if [[ -d $file ]]
+then err_exit "-f: $file should not be a directory file"
+fi
+if [[ ! -d . ]]
+then err_exit "-d: . should not be a directory file"
+fi
+if [[ -f /dev/null ]]
+then err_exit "-f: /dev/null should not be an ordinary file"
+fi
+chmod 000 $file
+if [[ -r $file ]]
+then err_exit "-r: $file should not be readable"
+fi
+if [[ ! -O $file ]]
+then err_exit "-r: $file should be owned by me"
+fi
+if [[ -w $file ]]
+then err_exit "-w: $file should not be writable"
+fi
+if [[ -w $file ]]
+then err_exit "-x: $file should not be executable"
+fi
+if [[ -w $file || -r $file ]]
+then err_exit "-rw: $file should not be readable/writable"
+fi
+if [[ -z x && -z x || ! -z x ]]
+then :
+else err_exit " wrong precedence"
+fi
+if [[ -z x && (-z x || ! -z x) ]]
+then err_exit " () grouping not working"
+fi
+if [[ foo < bar ]]
+then err_exit "foo comes before bar"
+fi
+[[ . -ef $(pwd) ]] || err_exit ". is not $PWD"
+set -o allexport
+[[ -o allexport ]] || err_exit '-o: did not set allexport option'
+if [[ -n $null ]]
+then err_exit "'$null' has non-zero length"
+fi
+if [[ ! -r /dev/fd/0 ]]
+then err_exit "/dev/fd/0 not open for reading"
+fi
+if [[ ! -w /dev/fd/2 ]]
+then err_exit "/dev/fd/2 not open for writing"
+fi
+sleep 1
+> $newer_file
+if [[ ! $file -ot $newer_file ]]
+then err_exit "$file should be older than $newer_file"
+fi
+if [[ $file -nt $newer_file ]]
+then err_exit "$newer_file should be newer than $file"
+fi
+if [[ $file != $tmp/* ]]
+then err_exit "$file should match $tmp/*"
+fi
+if [[ $file == $tmp'/*' ]]
+then err_exit "$file should not equal $tmp'/*'"
+fi
+[[ ! ( ! -z $null && ! -z x) ]] || err_exit "negation and grouping"
+[[ -z '' || -z '' || -z '' ]] || err_exit "three ors not working"
+[[ -z '' && -z '' && -z '' ]] || err_exit "three ors not working"
+(exit 8)
+if [[ $? -ne 8 || $? -ne 8 ]]
+then err_exit 'value $? within [[...]]'
+fi
+x='(x'
+if [[ '(x' != '('* ]]
+then err_exit " '(x' does not match '('* within [[...]]"
+fi
+if [[ '(x' != "("* ]]
+then err_exit ' "(x" does not match "("* within [[...]]'
+fi
+if [[ '(x' != \(* ]]
+then err_exit ' "(x" does not match \(* within [[...]]'
+fi
+if [[ 'x(' != *'(' ]]
+then err_exit " 'x(' does not match '('* within [[...]]"
+fi
+if [[ 'x&' != *'&' ]]
+then err_exit " 'x&' does not match '&'* within [[...]]"
+fi
+if [[ 'xy' == *'*' ]]
+then err_exit " 'xy' matches *'*' within [[...]]"
+fi
+if [[ 3 > 4 ]]
+then err_exit '3 < 4'
+fi
+if [[ 4 < 3 ]]
+then err_exit '3 > 4'
+fi
+if [[ 3x > 4x ]]
+then err_exit '3x < 4x'
+fi
+x='@(bin|dev|?)'
+cd /
+if [[ $(print $x) != "$x" ]]
+then err_exit 'extended pattern matching on command arguments'
+fi
+if [[ dev != $x ]]
+then err_exit 'extended pattern matching not working on variables'
+fi
+if [[ -u $SHELL ]]
+then err_exit "setuid on $SHELL"
+fi
+if [[ -g $SHELL ]]
+then err_exit "setgid on $SHELL"
+fi
+test -d . -a '(' ! -f . ')' || err_exit 'test not working'
+if [[ '!' != ! ]]
+then err_exit 'quoting unary operator not working'
+fi
+test \( -n x \) -o \( -n y \) 2> /dev/null || err_exit 'test ( -n x ) -o ( -n y) not working'
+test \( -n x \) -o -n y 2> /dev/null || err_exit 'test ( -n x ) -o -n y not working'
+chmod 600 $file
+exec 4> $file
+print -u4 foobar
+if [[ ! -s $file ]]
+then err_exit "-s: $file should be non-zero"
+fi
+exec 4>&-
+if [[ 011 -ne 11 ]]
+then err_exit "leading zeros in arithmetic compares not ignored"
+fi
+{
+ set -x
+ [[ foo > bar ]]
+} 2> /dev/null || { set +x; err_exit "foo<bar with -x enabled" ;}
+set +x
+(
+ eval "[[ (a) ]]"
+) 2> /dev/null || err_exit "[[ (a) ]] not working"
+> $file
+chmod 4755 "$file"
+if test -u $file && test ! -u $file
+then err_exit "test ! -u suidfile not working"
+fi
+for i in '(' ')' '[' ']'
+do [[ $i == $i ]] || err_exit "[[ $i != $i ]]"
+done
+(
+ [[ aaaa == {4}(a) ]] || err_exit 'aaaa != {4}(a)'
+ [[ aaaa == {2,5}(a) ]] || err_exit 'aaaa != {2,4}(a)'
+ [[ abcdcdabcd == {3,6}(ab|cd) ]] || err_exit 'abcdcdabcd == {3,4}(ab|cd)'
+ [[ abcdcdabcde == {5}(ab|cd)e ]] || err_exit 'abcdcdabcd == {5}(ab|cd)e'
+) || err_exit 'errors with {..}(...) patterns'
+[[ D290.2003.02.16.temp == D290.+(2003.02.16).temp* ]] || err_exit 'pattern match bug with +(...)'
+rm -rf $file
+{
+[[ -N $file ]] && err_exit 'test -N $tmp/*: st_mtime>st_atime after creat'
+sleep 2
+print 'hello world'
+[[ -N $file ]] || err_exit 'test -N $tmp/*: st_mtime<=st_atime after write'
+sleep 2
+read
+[[ -N $file ]] && err_exit 'test -N $tmp/*: st_mtime>st_atime after read'
+} > $file < $file
+if rm -rf "$file" && ln -s / "$file"
+then [[ -L "$file" ]] || err_exit '-L not working'
+ [[ -L "$file"/ ]] && err_exit '-L with file/ not working'
+fi
+$SHELL -c 't=1234567890; [[ $t == @({10}(\d)) ]]' 2> /dev/null || err_exit ' @({10}(\d)) pattern not working'
+$SHELL -c '[[ att_ == ~(E)(att|cus)_.* ]]' 2> /dev/null || err_exit ' ~(E)(att|cus)_* pattern not working'
+$SHELL -c '[[ att_ =~ (att|cus)_.* ]]' 2> /dev/null || err_exit ' =~ ere not working'
+$SHELL -c '[[ abc =~ a(b)c ]]' 2> /dev/null || err_exit '[[ abc =~ a(b)c ]] fails'
+$SHELL -xc '[[ abc =~ \babc\b ]]' 2> /dev/null || err_exit '[[ abc =~ \babc\b ]] fails'
+[[ abc == ~(E)\babc\b ]] || err_exit '\b not preserved for ere when not in ()'
+[[ abc == ~(iEi)\babc\b ]] || err_exit '\b not preserved for ~(iEi) when not in ()'
+
+e=$($SHELL -c '[ -z "" -a -z "" ]' 2>&1)
+[[ $e ]] && err_exit "[ ... ] compatibility check failed -- $e"
+i=hell
+[[ hell0 == $i[0] ]] || err_exit 'pattern $i[0] interpreded as array ref'
+test '(' = ')' && err_exit '"test ( = )" should not be true'
+[[ $($SHELL -c 'case F in ~(Eilr)[a-z0-9#]) print ok;;esac' 2> /dev/null) == ok ]] || err_exit '~(Eilr) not working in case command'
+[[ $($SHELL -c "case Q in ~(Fi)q | \$'\E') print ok;;esac" 2> /dev/null) == ok ]] || err_exit '~(Fi)q | \E not working in case command'
+
+for l in C en_US.ISO8859-15
+do [[ $($SHELL -c "LC_COLLATE=$l" 2>&1) ]] && continue
+ export LC_COLLATE=$l
+ set -- \
+ 'A' 0 1 1 0 1 1 1 0 0 1 0 0 \
+ 'Z' 0 1 1 0 1 1 1 0 0 1 0 0 \
+ '/' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '.' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '_' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '-' 1 1 1 1 1 1 0 0 0 0 0 0 \
+ '%' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '@' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '!' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ '^' 0 0 0 0 0 0 1 1 1 1 1 1 \
+ # retain this line #
+ while (( $# >= 13 ))
+ do c=$1
+ shift
+ for p in \
+ '[![.-.]]' \
+ '[![.-.][:upper:]]' \
+ '[![.-.]A-Z]' \
+ '[!-]' \
+ '[!-[:upper:]]' \
+ '[!-A-Z]' \
+ '[[.-.]]' \
+ '[[.-.][:upper:]]' \
+ '[[.-.]A-Z]' \
+ '[-]' \
+ '[-[:upper:]]' \
+ '[-A-Z]' \
+ # retain this line #
+ do e=$1
+ shift
+ [[ $c == $p ]]
+ g=$?
+ [[ $g == $e ]] || err_exit "[[ '$c' == $p ]] for LC_COLLATE=$l failed -- expected $e, got $g"
+ done
+ done
+done
+integer n
+if ( : < /dev/tty ) 2>/dev/null && exec {n}< /dev/tty
+then [[ -t $n ]] || err_exit "[[ -t n ]] fails when n > 9"
+fi
+foo=([1]=a [2]=b [3]=c)
+[[ -v foo[1] ]] || err_exit 'foo[1] should be set'
+[[ ${foo[1]+x} ]] || err_exit '${foo[1]+x} should be x'
+[[ ${foo[@]+x} ]] || err_exit '${foo[@]+x} should be x'
+unset foo[1]
+[[ -v foo[1] ]] && err_exit 'foo[1] should not be set'
+[[ ${foo[1]+x} ]] && err_exit '${foo[1]+x} should be empty'
+bar=(a b c)
+[[ -v bar[1] ]] || err_exit 'bar[1] should be set'
+[[ ${bar[1]+x} ]] || err_exit '${foo[1]+x} should be x'
+unset bar[1]
+[[ ${bar[1]+x} ]] && err_exit '${foo[1]+x} should be empty'
+[[ -v bar ]] || err_exit 'bar should be set'
+[[ -v bar[1] ]] && err_exit 'bar[1] should not be set'
+integer z=( 1 2 4)
+[[ -v z[1] ]] || err_exit 'z[1] should be set'
+unset z[1]
+[[ -v z[1] ]] && err_exit 'z[1] should not be set'
+typeset -si y=( 1 2 4)
+[[ -v y[6] ]] && err_exit 'y[6] should not be set'
+[[ -v y[1] ]] || err_exit 'y[1] should be set'
+unset y[1]
+[[ -v y[1] ]] && err_exit 'y[1] should not be set'
+x=abc
+[[ -v x[0] ]] || err_exit 'x[0] should be set'
+[[ ${x[0]+x} ]] || err_exit print '${x[0]+x} should be x'
+[[ -v x[3] ]] && err_exit 'x[3] should not be set'
+[[ ${x[3]+x} ]] && err_exit '${x[0]+x} should be Empty'
+unset x
+[[ ${x[@]+x} ]] && err_exit '${x[@]+x} should be Empty'
+unset x y z foo bar
+
+{ x=$($SHELL -c '[[ (( $# -eq 0 )) ]] && print ok') 2> /dev/null;}
+[[ $x == ok ]] || err_exit '((...)) inside [[...]] not treated as nested ()'
+
+[[ -e /dev/fd/ ]] || err_exit '/dev/fd/ does not exits'
+[[ -e /dev/tcp/ ]] || err_exit '/dev/tcp/ does not exist'
+[[ -e /dev/udp/ ]] || err_exit '/dev/udp/ does not exist'
+[[ -e /dev/xxx/ ]] && err_exit '/dev/xxx/ exists'
+
+$SHELL 2> /dev/null -c '[[(-n foo)]]' || err_exit '[[(-n foo)]] should not require space in front of ('
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/builtins.sh b/src/cmd/ksh93/tests/builtins.sh
new file mode 100755
index 0000000..6346aff
--- /dev/null
+++ b/src/cmd/ksh93/tests/builtins.sh
@@ -0,0 +1,562 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+# test shell builtin commands
+builtin getconf
+: ${foo=bar} || err_exit ": failed"
+[[ $foo == bar ]] || err_exit ": side effects failed"
+set -- - foobar
+[[ $# == 2 && $1 == - && $2 == foobar ]] || err_exit "set -- - foobar failed"
+set -- -x foobar
+[[ $# == 2 && $1 == -x && $2 == foobar ]] || err_exit "set -- -x foobar failed"
+getopts :x: foo || err_exit "getopts :x: returns false"
+[[ $foo == x && $OPTARG == foobar ]] || err_exit "getopts :x: failed"
+OPTIND=1
+getopts :r:s var -r
+if [[ $var != : || $OPTARG != r ]]
+then err_exit "'getopts :r:s var -r' not working"
+fi
+OPTIND=1
+getopts :d#u OPT -d 16177
+if [[ $OPT != d || $OPTARG != 16177 ]]
+then err_exit "'getopts :d#u OPT=d OPTARG=16177' failed -- OPT=$OPT OPTARG=$OPTARG"
+fi
+OPTIND=1
+while getopts 'ab' option -a -b
+do [[ $OPTIND == $((OPTIND)) ]] || err_exit "OPTIND optimization bug"
+done
+
+USAGE=$'[-][S:server?Operate on the specified \asubservice\a:]:[subservice:=pmserver]
+ {
+ [p:pmserver]
+ [r:repserver]
+ [11:notifyd]
+ }'
+set pmser p rep r notifyd -11
+while (( $# > 1 ))
+do OPTIND=1
+ getopts "$USAGE" OPT -S $1
+ [[ $OPT == S && $OPTARG == $2 ]] || err_exit "OPT=$OPT OPTARG=$OPTARG -- expected OPT=S OPTARG=$2"
+ shift 2
+done
+
+false ${foo=bar} && err_exit "false failed"
+read <<!
+hello world
+!
+[[ $REPLY == 'hello world' ]] || err_exit "read builtin failed"
+print x:y | IFS=: read a b
+if [[ $a != x ]]
+then err_exit "IFS=: read ... not working"
+fi
+read <<!
+hello \
+world
+!
+[[ $REPLY == 'hello world' ]] || err_exit "read continuation failed"
+read -d x <<!
+hello worldxfoobar
+!
+[[ $REPLY == 'hello world' ]] || err_exit "read builtin failed"
+read <<\!
+hello \
+ world \
+
+!
+[[ $REPLY == 'hello world' ]] || err_exit "read continuation2 failed"
+print "one\ntwo" | { read line
+ print $line | /bin/cat > /dev/null
+ read line
+}
+read <<\!
+\
+a\
+\
+\
+b
+!
+if [[ $REPLY != ab ]]
+then err_exit "read multiple continuation failed"
+fi
+if [[ $line != two ]]
+then err_exit "read from pipeline failed"
+fi
+line=two
+read line < /dev/null
+if [[ $line != "" ]]
+then err_exit "read from /dev/null failed"
+fi
+if [[ $(print -R -) != - ]]
+then err_exit "print -R not working correctly"
+fi
+if [[ $(print -- -) != - ]]
+then err_exit "print -- not working correctly"
+fi
+print -f "hello%nbar\n" size > /dev/null
+if (( size != 5 ))
+then err_exit "%n format of printf not working"
+fi
+print -n -u2 2>&1-
+[[ -w /dev/fd/1 ]] || err_exit "2<&1- with built-ins has side effects"
+x=$0
+if [[ $(eval 'print $0') != $x ]]
+then err_exit '$0 not correct for eval'
+fi
+$SHELL -c 'read x <<< hello' 2> /dev/null || err_exit 'syntax <<< not recognized'
+($SHELL -c 'read x[1] <<< hello') 2> /dev/null || err_exit 'read x[1] not working'
+unset x
+readonly x
+set -- $(readonly)
+if [[ " $@ " != *" x "* ]]
+then err_exit 'unset readonly variables are not displayed'
+fi
+if [[ $( for i in foo bar
+ do print $i
+ continue 10
+ done
+ ) != $'foo\nbar' ]]
+then err_exit 'continue breaks out of loop'
+fi
+(continue bad 2>/dev/null && err_exit 'continue bad should return an error')
+(break bad 2>/dev/null && err_exit 'break bad should return an error')
+(continue 0 2>/dev/null && err_exit 'continue 0 should return an error')
+(break 0 2>/dev/null && err_exit 'break 0 should return an error')
+breakfun() { break;}
+continuefun() { continue;}
+for fun in break continue
+do if [[ $( for i in foo
+ do ${fun}fun
+ print $i
+ done
+ ) != foo ]]
+ then err_exit "$fun call in ${fun}fun breaks out of for loop"
+ fi
+done
+if [[ $(print -f "%b" "\a\n\v\b\r\f\E\03\\oo") != $'\a\n\v\b\r\f\E\03\\oo' ]]
+then err_exit 'print -f "%b" not working'
+fi
+if [[ $(print -f "%P" "[^x].*b\$") != '*[!x]*b' ]]
+then err_exit 'print -f "%P" not working'
+fi
+if [[ $(abc: for i in foo bar;do print $i;break abc;done) != foo ]]
+then err_exit 'break labels not working'
+fi
+if [[ $(command -v if) != if ]]
+then err_exit 'command -v not working'
+fi
+read -r var <<\!
+
+!
+if [[ $var != "" ]]
+then err_exit "read -r of blank line not working"
+fi
+mkdir -p $tmp/a/b/c 2>/dev/null || err_exit "mkdir -p failed"
+$SHELL -c "cd $tmp/a/b; cd c" 2>/dev/null || err_exit "initial script relative cd fails"
+
+trap 'print TERM' TERM
+exp=$'trap -- \'print TERM\' TERM\ntrap -- \'cd /; rm -rf '$tmp$'\' EXIT'
+got=$(trap)
+[[ $got == $exp ]] || err_exit "\$(trap) failed -- expected \"$exp\", got \"$got\""
+exp='print TERM'
+got=$(trap -p TERM)
+[[ $got == $exp ]] || err_exit "\$(trap -p TERM) failed -- expected \"$exp\", got \"$got\""
+
+[[ $($SHELL -c 'trap "print ok" SIGTERM; kill -s SIGTERM $$' 2> /dev/null) == ok ]] || err_exit 'SIGTERM not recognized'
+[[ $($SHELL -c 'trap "print ok" sigterm; kill -s sigterm $$' 2> /dev/null) == ok ]] || err_exit 'SIGTERM not recognized'
+[[ $($SHELL -c '( trap "" TERM);kill $$;print bad' == bad) ]] 2> /dev/null && err_exit 'trap ignored in subshell causes it to be ignored by parent'
+${SHELL} -c 'kill -1 -$$' 2> /dev/null
+[[ $(kill -l $?) == HUP ]] || err_exit 'kill -1 -pid not working'
+${SHELL} -c 'kill -1 -$$' 2> /dev/null
+[[ $(kill -l $?) == HUP ]] || err_exit 'kill -n1 -pid not working'
+${SHELL} -c 'kill -s HUP -$$' 2> /dev/null
+[[ $(kill -l $?) == HUP ]] || err_exit 'kill -HUP -pid not working'
+n=123
+typeset -A base
+base[o]=8#
+base[x]=16#
+base[X]=16#
+for i in d i o u x X
+do if (( $(( ${base[$i]}$(printf "%$i" $n) )) != n ))
+ then err_exit "printf %$i not working"
+ fi
+done
+if [[ $( trap 'print done' EXIT) != done ]]
+then err_exit 'trap on EXIT not working'
+fi
+if [[ $( trap 'print done' EXIT; trap - EXIT) == done ]]
+then err_exit 'trap on EXIT not being cleared'
+fi
+if [[ $(LC_MESSAGES=C type test) != 'test is a shell builtin' ]]
+then err_exit 'whence -v test not a builtin'
+fi
+builtin -d test
+if [[ $(type test) == *builtin* ]]
+then err_exit 'whence -v test after builtin -d incorrect'
+fi
+typeset -Z3 percent=$(printf '%o\n' "'%'")
+forrmat=\\${percent}s
+if [[ $(printf "$forrmat") != %s ]]
+then err_exit "printf $forrmat not working"
+fi
+if (( $(printf 'x\0y' | wc -c) != 3 ))
+then err_exit 'printf \0 not working'
+fi
+if [[ $(printf "%bx%s\n" 'f\to\cbar') != $'f\to' ]]
+then err_exit 'printf %bx%s\n not working'
+fi
+alpha=abcdefghijklmnop
+if [[ $(printf "%10.*s\n" 5 $alpha) != ' abcde' ]]
+then err_exit 'printf %10.%s\n not working'
+fi
+float x2=.0000625
+if [[ $(printf "%10.5E\n" x2) != 6.25000E-05 ]]
+then err_exit 'printf "%10.5E" not normalizing correctly'
+fi
+x2=.000000001
+if [[ $(printf "%g\n" x2 2>/dev/null) != 1e-09 ]]
+then err_exit 'printf "%g" not working correctly'
+fi
+#FIXME#($SHELL read -s foobar <<\!
+#FIXME#testing
+#FIXME#!
+#FIXME#) 2> /dev/null || err_exit ksh read -s var fails
+if [[ $(printf +3 2>/dev/null) != +3 ]]
+then err_exit 'printf is not processing formats beginning with + correctly'
+fi
+if printf "%d %d\n" 123bad 78 >/dev/null 2>/dev/null
+then err_exit "printf not exiting non-zero with conversion errors"
+fi
+if [[ $(trap --version 2> /dev/null;print done) != done ]]
+then err_exit 'trap builtin terminating after --version'
+fi
+if [[ $(set --version 2> /dev/null;print done) != done ]]
+then err_exit 'set builtin terminating after --veresion'
+fi
+unset -f foobar
+function foobar
+{
+ print 'hello world'
+}
+OPTIND=1
+if [[ $(getopts $'[+?X\ffoobar\fX]' v --man 2>&1) != *'Xhello world'X* ]]
+then err_exit '\f...\f not working in getopts usage strings'
+fi
+if [[ $(printf '%H\n' $'<>"& \'\tabc') != '&lt;&gt;&quot;&amp;&nbsp;&apos;&#9;abc' ]]
+then err_exit 'printf %H not working'
+fi
+if [[ $( printf 'foo://ab_c%#H\n' $'<>"& \'\tabc') != 'foo://ab_c%3C%3E%22%26%20%27%09abc' ]]
+then err_exit 'printf %#H not working'
+fi
+if [[ $(printf '%R %R %R %R\n' 'a.b' '*.c' '^' '!(*.*)') != '^a\.b$ \.c$ ^\^$ ^(.*\..*)!$' ]]
+then err_exit 'printf %R not working'
+fi
+if [[ $(printf '%..:c\n' abc) != a:b:c ]]
+then err_exit "printf '%..:c' not working"
+fi
+if [[ $(printf '%..*c\n' : abc) != a:b:c ]]
+then err_exit "printf '%..*c' not working"
+fi
+if [[ $(printf '%..:s\n' abc def ) != abc:def ]]
+then err_exit "printf '%..:s' not working"
+fi
+if [[ $(printf '%..*s\n' : abc def) != abc:def ]]
+then err_exit "printf '%..*s' not working"
+fi
+[[ $(printf '%q\n') == '' ]] || err_exit 'printf "%q" with missing arguments'
+# we won't get hit by the one second boundary twice, right?
+[[ $(printf '%T\n' now) == "$(date)" ]] ||
+[[ $(printf '%T\n' now) == "$(date)" ]] ||
+err_exit 'printf "%T" now'
+behead()
+{
+ read line
+ left=$(cat)
+}
+print $'line1\nline2' | behead
+if [[ $left != line2 ]]
+then err_exit "read reading ahead on a pipe"
+fi
+read -n1 y <<!
+abc
+!
+exp=a
+if [[ $y != $exp ]]
+then err_exit "read -n1 failed -- expected '$exp', got '$y'"
+fi
+print -n $'{ read -r line;print $line;}\nhello' > $tmp/script
+chmod 755 $tmp/script
+if [[ $($SHELL < $tmp/script) != hello ]]
+then err_exit 'read of incomplete line not working correctly'
+fi
+set -f
+set -- *
+if [[ $1 != '*' ]]
+then err_exit 'set -f not working'
+fi
+unset pid1 pid2
+false &
+pid1=$!
+pid2=$(
+ wait $pid1
+ (( $? == 127 )) || err_exit "job known to subshell"
+ print $!
+)
+wait $pid1
+(( $? == 1 )) || err_exit "wait not saving exit value"
+wait $pid2
+(( $? == 127 )) || err_exit "subshell job known to parent"
+env=
+v=$(getconf LIBPATH)
+for v in ${v//,/ }
+do v=${v#*:}
+ v=${v%%:*}
+ eval [[ \$$v ]] && env="$env $v=\"\$$v\""
+done
+if [[ $(foo=bar; eval foo=\$foo $env exec -c \$SHELL -c \'print \$foo\') != bar ]]
+then err_exit '"name=value exec -c ..." not working'
+fi
+$SHELL -c 'OPTIND=-1000000; getopts a opt -a' 2> /dev/null
+[[ $? == 1 ]] || err_exit 'getopts with negative OPTIND not working'
+getopts 'n#num' opt -n 3
+[[ $OPTARG == 3 ]] || err_exit 'getopts with numerical arguments failed'
+if [[ $($SHELL -c $'printf \'%2$s %1$s\n\' world hello') != 'hello world' ]]
+then err_exit 'printf %2$s %1$s not working'
+fi
+val=$(( 'C' ))
+set -- \
+ "'C" $val 0 \
+ "'C'" $val 0 \
+ '"C' $val 0 \
+ '"C"' $val 0 \
+ "'CX" $val 1 \
+ "'CX'" $val 1 \
+ "'C'X" $val 1 \
+ '"CX' $val 1 \
+ '"CX"' $val 1 \
+ '"C"X' $val 1
+while (( $# >= 3 ))
+do arg=$1 val=$2 code=$3
+ shift 3
+ for fmt in '%d' '%g'
+ do out=$(printf "$fmt" "$arg" 2>/dev/null)
+ err=$(printf "$fmt" "$arg" 2>&1 >/dev/null)
+ printf "$fmt" "$arg" >/dev/null 2>&1
+ ret=$?
+ [[ $out == $val ]] || err_exit "printf $fmt $arg failed -- expected '$val', got '$out'"
+ if (( $code ))
+ then [[ $err ]] || err_exit "printf $fmt $arg failed, error message expected"
+ else [[ $err ]] && err_exit "$err: printf $fmt $arg failed, error message not expected -- got '$err'"
+ fi
+ (( $ret == $code )) || err_exit "printf $fmt $arg failed -- expected exit code $code, got $ret"
+ done
+done
+((n=0))
+((n++)); ARGC[$n]=1 ARGV[$n]=""
+((n++)); ARGC[$n]=2 ARGV[$n]="-a"
+((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2"
+((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x"
+((n++)); ARGC[$n]=4 ARGV[$n]="-a -v 2 x y"
+for ((i=1; i<=n; i++))
+do set -- ${ARGV[$i]}
+ OPTIND=0
+ while getopts -a tst "av:" OPT
+ do :
+ done
+ if [[ $OPTIND != ${ARGC[$i]} ]]
+ then err_exit "\$OPTIND after getopts loop incorrect -- expected ${ARGC[$i]}, got $OPTIND"
+ fi
+done
+options=ab:c
+optarg=foo
+set -- -a -b $optarg -c bar
+while getopts $options opt
+do case $opt in
+ a|c) [[ $OPTARG ]] && err_exit "getopts $options \$OPTARG for flag $opt failed, expected \"\", got \"$OPTARG\"" ;;
+ b) [[ $OPTARG == $optarg ]] || err_exit "getopts $options \$OPTARG failed -- \"$optarg\" expected, got \"$OPTARG\"" ;;
+ *) err_exit "getopts $options failed -- got flag $opt" ;;
+ esac
+done
+
+[[ $($SHELL 2> /dev/null -c 'readonly foo; getopts a: foo -a blah; echo foo') == foo ]] || err_exit 'getopts with readonly variable causes script to abort'
+
+unset a
+{ read -N3 a; read -N1 b;} <<!
+abcdefg
+!
+exp=abc
+[[ $a == $exp ]] || err_exit "read -N3 here-document failed -- expected '$exp', got '$a'"
+exp=d
+[[ $b == $exp ]] || err_exit "read -N1 here-document failed -- expected '$exp', got '$b'"
+read -n3 a <<!
+abcdefg
+!
+exp=abc
+[[ $a == $exp ]] || err_exit "read -n3 here-document failed -- expected '$exp', got '$a'"
+#(print -n a;sleep 1; print -n bcde) | { read -N3 a; read -N1 b;}
+#[[ $a == $exp ]] || err_exit "read -N3 from pipe failed -- expected '$exp', got '$a'"
+#exp=d
+#[[ $b == $exp ]] || err_exit "read -N1 from pipe failed -- expected '$exp', got '$b'"
+#(print -n a;sleep 1; print -n bcde) | read -n3 a
+#exp=a
+#[[ $a == $exp ]] || err_exit "read -n3 from pipe failed -- expected '$exp', got '$a'"
+#rm -f $tmp/fifo
+#if mkfifo $tmp/fifo 2> /dev/null
+#then (print -n a; sleep 1;print -n bcde) > $tmp/fifo &
+# {
+# read -u5 -n3 -t2 a || err_exit 'read -n3 from fifo timedout'
+# read -u5 -n1 -t2 b || err_exit 'read -n1 from fifo timedout'
+# } 5< $tmp/fifo
+# exp=a
+# [[ $a == $exp ]] || err_exit "read -n3 from fifo failed -- expected '$exp', got '$a'"
+# rm -f $tmp/fifo
+# mkfifo $tmp/fifo 2> /dev/null
+# (print -n a; sleep 1;print -n bcde) > $tmp/fifo &
+# {
+# read -u5 -N3 -t2 a || err_exit 'read -N3 from fifo timed out'
+# read -u5 -N1 -t2 b || err_exit 'read -N1 from fifo timedout'
+# } 5< $tmp/fifo
+# exp=abc
+# [[ $a == $exp ]] || err_exit "read -N3 from fifo failed -- expected '$exp', got '$a'"
+# exp=d
+# [[ $b == $exp ]] || err_exit "read -N1 from fifo failed -- expected '$exp', got '$b'"
+#fi
+#rm -f $tmp/fifo
+
+function longline
+{
+ integer i
+ for((i=0; i < $1; i++))
+ do print argument$i
+ done
+}
+# test command -x option
+integer sum=0 n=10000
+if ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1
+then for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) 2> /dev/null)
+ do ((sum += $i))
+ done
+ (( sum == n )) || err_exit "command -x processed only $sum arguments"
+ command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1
+ [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x'
+fi
+# test command -x option with extra arguments
+integer sum=0 n=10000
+if ! ${SHELL:-ksh} -c 'print $#' count $(longline $n) > /dev/null 2>&1
+then for i in $(command command -x ${SHELL:-ksh} -c 'print $#;[[ $1 != argument0 ]]' count $(longline $n) one two three) #2> /dev/null)
+ do ((sum += $i))
+ done
+ (( sum > n )) || err_exit "command -x processed only $sum arguments"
+ (( (sum-n)%3==0 )) || err_exit "command -x processed only $sum arguments"
+ (( sum == n+3)) && err_exit "command -x processed only $sum arguments"
+ command -p command -x ${SHELL:-ksh} -c 'print $#;[[ $1 == argument0 ]]' count $(longline $n) > /dev/null 2>&1
+ [[ $? != 1 ]] && err_exit 'incorrect exit status for command -x'
+fi
+# test for debug trap
+[[ $(typeset -i i=0
+ trap 'print $i' DEBUG
+ while (( i <2))
+ do (( i++))
+ done) == $'0\n0\n1\n1\n2' ]] || err_exit "DEBUG trap not working"
+getconf UNIVERSE - ucb
+[[ $($SHELL -c 'echo -3') == -3 ]] || err_exit "echo -3 not working in ucb universe"
+typeset -F3 start_x=SECONDS total_t delay=0.02
+typeset reps=50 leeway=5
+#sleep $(( 2 * leeway * reps * delay )) |
+#for (( i=0 ; i < reps ; i++ ))
+#do read -N1 -t $delay
+#done
+#(( total_t = SECONDS - start_x ))
+#if (( total_t > leeway * reps * delay ))
+#then err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too long"
+#elif (( total_t < reps * delay ))
+#then err_exit "read -t in pipe taking $total_t secs - $(( reps * delay )) minimum - too fast"
+#fi
+#$SHELL -c 'sleep $(printf "%a" .95)' 2> /dev/null || err_exit "sleep doesn't except %a format constants"
+#$SHELL -c 'test \( ! -e \)' 2> /dev/null ; [[ $? == 1 ]] || err_exit 'test \( ! -e \) not working'
+[[ $(ulimit) == "$(ulimit -fS)" ]] || err_exit 'ulimit is not the same as ulimit -fS'
+tmpfile=$tmp/file.2
+print $'\nprint -r -- "${.sh.file} ${LINENO} ${.sh.lineno}"' > $tmpfile
+[[ $( . "$tmpfile") == "$tmpfile 2 1" ]] || err_exit 'dot command not working'
+print -r -- "'xxx" > $tmpfile
+[[ $($SHELL -c ". $tmpfile"$'\n print ok' 2> /dev/null) == ok ]] || err_exit 'syntax error in dot command affects next command'
+
+#float sec=$SECONDS del=4
+#exec 3>&2 2>/dev/null
+#$SHELL -c "( sleep 1; kill -ALRM \$\$ ) & sleep $del" 2> /dev/null
+#exitval=$?
+#(( sec = SECONDS - sec ))
+#exec 2>&3-
+#(( exitval )) && err_exit "sleep doesn't exit 0 with ALRM interupt"
+#(( sec > (del - 1) )) || err_exit "ALRM signal causes sleep to terminate prematurely -- expected 3 sec, got $sec"
+typeset -r z=3
+y=5
+for i in 123 z %x a.b.c
+do ( unset $i) 2>/dev/null && err_exit "unset $i should fail"
+done
+a=()
+for i in y y y[8] t[abc] y.d a.b a
+do unset $i || print -u2 "err_exit unset $i should not fail"
+done
+[[ $($SHELL -c 'y=3; unset 123 y;print $?$y') == 1 ]] 2> /dev/null || err_exit 'y is not getting unset with unset 123 y'
+[[ $($SHELL -c 'trap foo TERM; (trap;(trap) )') == 'trap -- foo TERM' ]] || err_exit 'traps not getting reset when subshell is last process'
+
+n=$(printf "%b" 'a\0b\0c' | wc -c)
+(( n == 5 )) || err_exit '\0 not working with %b format with printf'
+
+t=$(ulimit -t)
+[[ $($SHELL -c 'ulimit -v 15000 2>/dev/null; ulimit -t') == "$t" ]] || err_exit 'ulimit -v changes ulimit -t'
+
+$SHELL 2> /dev/null -c 'cd ""' && err_exit 'cd "" not producing an error'
+[[ $($SHELL 2> /dev/null -c 'cd "";print hi') != hi ]] && err_exit 'cd "" should not terminate script'
+
+bincat=$(whence -p cat)
+builtin cat
+out=$tmp/seq.out
+seq 11 >$out
+cmp -s <(print -- "$($bincat<( $bincat $out ) )") <(print -- "$(cat <( cat $out ) )") || err_exit "builtin cat differs from $bincat"
+
+[[ $($SHELL -c '{ printf %R "["; print ok;}' 2> /dev/null) == ok ]] || err_exit $'\'printf %R "["\' causes shell to abort'
+
+v=$( $SHELL -c $'
+ trap \'print "usr1"\' USR1
+ trap exit USR2
+ sleep 1 && {
+ kill -USR1 $$ && sleep 1
+ kill -0 $$ 2>/dev/null && kill -USR2 $$
+ } &
+ sleep 2 | read
+ echo done
+' ) 2> /dev/null
+[[ $v == $'usr1\ndone' ]] || err_exit 'read not terminating when receiving USR1 signal'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/case.sh b/src/cmd/ksh93/tests/case.sh
new file mode 100755
index 0000000..7fe01ea
--- /dev/null
+++ b/src/cmd/ksh93/tests/case.sh
@@ -0,0 +1,85 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+bar=foo2
+bam=foo[3]
+for i in foo1 foo2 foo3 foo4 foo5 foo6
+do foo=0
+ case $i in
+ foo1) foo=1;;
+ $bar) foo=2;;
+ $bam) foo=3;;
+ foo[4]) foo=4;;
+ ${bar%?}5)
+ foo=5;;
+ "${bar%?}6")
+ foo=6;;
+ esac
+ if [[ $i != foo$foo ]]
+ then err_exit "$i not matching correct pattern"
+ fi
+done
+f="[ksh92]"
+case $f in
+\[*\]) ;;
+*) err_exit "$f does not match \[*\]";;
+esac
+
+if [[ $($SHELL -c '
+ x=$(case abc {
+ abc) { print yes;};;
+ *) print no;;
+ }
+ )
+ print -r -- "$x"' 2> /dev/null) != yes ]]
+then err_exit 'case abc {...} not working'
+fi
+[[ $($SHELL -c 'case a in
+a) print -n a > /dev/null ;&
+b) print b;;
+esac') != b ]] && err_exit 'bug in ;& at end of script'
+[[ $(VMDEBUG=1 $SHELL -c '
+ tmp=foo
+ for i in a b
+ do case $i in
+ a) : tmp=$tmp tmp.h=$tmp.h;;
+ b) ( tmp=bar )
+ for j in a
+ do print -r -- $tmp.h
+ done
+ ;;
+ esac
+ done
+') == foo.h ]] || err_exit "optimizer bug"
+
+x=$($SHELL -ec 'case a in a) echo 1; false; echo 2 ;& b) echo 3;; esac')
+[[ $x == 1 ]] || err_exit 'set -e ignored on case fail through'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/comvar.sh b/src/cmd/ksh93/tests/comvar.sh
new file mode 100755
index 0000000..e08f972
--- /dev/null
+++ b/src/cmd/ksh93/tests/comvar.sh
@@ -0,0 +1,689 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+#test for compound variables
+Command=${0##*/}
+integer Errors=0
+Point=(
+ float x=1. y=0.
+)
+eval p="$Point"
+if (( (p.x*p.x + p.y*p.y) > 1.01 ))
+then err_exit 'compound variable not working'
+fi
+nameref foo=p
+if [[ ${foo.x} != ${Point.x} ]]
+then err_exit 'reference to compound object not working'
+fi
+unset foo
+rec=(
+ name='Joe Blow'
+ born=(
+ month=jan
+ integer day=16
+ year=1980
+ )
+)
+eval newrec="$rec"
+if [[ ${newrec.name} != "${rec.name}" ]]
+then err_exit 'copying a compound object not working'
+fi
+if (( newrec.born.day != 16 ))
+then err_exit 'copying integer field of compound object not working'
+fi
+p_t=(
+ integer z=0
+ typeset -A tokens
+)
+unset x
+typeset -A x
+x=( [foo]=bar )
+if [[ ${x[@]} != bar ]]
+then err_exit 'compound assignemnt of associative arrays not working'
+fi
+unset -n foo x
+unset foo x
+foo=( x=3)
+nameref x=foo
+if [[ ${!x.@} != foo.x ]]
+then err_exit 'name references not expanded on prefix matching'
+fi
+unset x
+unset -n x
+(
+ x=()
+ x.foo.bar=7
+ [[ ${x.foo.bar} == 7 ]] || err_exit '[[ ${x.foo.bar} != 7 ]]'
+ (( x.foo.bar == 7 ))|| err_exit '(( x.foo.bar != 7 ))'
+ [[ ${x.foo} == *bar=7* ]] || err_exit '[[ ${x.foo} != *bar=7* ]]'
+)
+foo=(integer x=3)
+if [[ ${foo} != *x=3* ]]
+then err_exit "compound variable with integer subvariable not working"
+fi
+$SHELL -c $'x=(foo=bar)\n[[ x == x ]]' 2> /dev/null ||
+ err_exit '[[ ... ]] not working after compound assignment'
+unset foo
+[[ ${!foo.@} ]] && err_exit 'unset compound variable leaves subvariables'
+suitable=(
+ label="Table Viewer"
+ langs="ksh"
+ uselang=ksh
+ launch=no
+ groups="default"
+ default=(
+ label="Table Viewer Preferences"
+ entrylist=" \
+ vieworigin viewsize viewcolor viewfontname viewfontsize \
+ showheader header showfooter footer showtitle title showlegends \
+ class_td_lg1_style class_tr_tr1_style \
+ class_th_th1_style class_td_td1_style \
+ fields fieldorder \
+ "
+ entries=(
+ vieworigin=(
+ type=coord var=vieworigin val="0 0" label="Window Position"
+ )
+ viewsize=(
+ type=coord var=viewsize val="400 400" label="Window Size"
+ )
+ viewcolor=(
+ type=2colors var=viewcolor val="gray black"
+ label="Window Colors"
+ )
+ viewfontname=(
+ type=fontname var=viewfontname val="Times-Roman"
+ label="Window Font Name"
+ )
+ viewfontsize=(
+ type=fontsize var=viewfontsize val=14 label="Window Font Size"
+ )
+
+ showheader=(
+ type=yesno var=showheader val=no label="Show Header"
+ )
+ header=(
+ type=text var=header val="" label="Header"
+ )
+
+ showfooter=(
+ type=yesno var=showfooter val=no label="Show Footer"
+ )
+ footer=(
+ type=text var=footer val="" label="Footer"
+ )
+
+ showtitle=(
+ type=yesno var=showtitle val=yes label="Show Title"
+ )
+ title=(
+ type=text var=title val="SWIFTUI - Table View" label="Title"
+ )
+
+ showlegends=(
+ type=yesno var=showlegends val=yes label="Show Legends"
+ )
+
+ class_td_lg1_style=(
+ type=style var=class_td_lg1_style
+ val="color: black; font-family: Times-Roman; font-size: 14pt"
+ label="Legend 1 Style"
+ )
+
+ class_tr_tr1_style=(
+ type=style var=class_tr_tr1_style val="background: black"
+ label="Table Row 1 Style"
+ )
+
+ class_th_th1_style=(
+ type=style var=class_th_th1_style
+ val="color: black; font-family: Times-Roman; font-size: 14pt; text-align: left"
+ label="Table Header 1 Style"
+ )
+
+ class_td_td1_style=(
+ type=style var=class_td_td1_style
+ val="color: black; font-family: Times-Roman; font-size: 14pt; text-align: left"
+ label="Table Cell 1 Style"
+ )
+
+ fields=(
+ type=text var=fields val= label="List of Fields"
+ )
+ fieldorder=(
+ type=text var=fieldorder val= label="Order of Fields"
+ )
+ )
+ )
+)
+[[ "${suitable}" == *entrylist=* ]] || err_exit 'compound variable expansion omitting fields'
+foo=( bar=foo barbar=bar)
+[[ $foo == *bar=foo* ]] || err_exit 'no prefix elements in compound variable output'
+function localvar
+{
+ typeset point=(typeset -i x=3 y=4)
+ (( (point.x*point.x + point.y*point.y) == 25 )) || err_exit "local compound variable not working"
+}
+point=(integer x=6 y=8)
+localvar
+ (( (point.x*point.x + point.y*point.y) == 100 )) || err_exit "global compound variable not preserved"
+[[ $($SHELL -c 'foo=();foo.[x]=(y z); print ${foo.x[@]}') == 'y z' ]] 2> /dev/null || err_exit 'foo=( [x]=(y z) not working'
+function staticvar
+{
+ if [[ $1 ]]
+ then print -r -- "$point"
+ return
+ fi
+ typeset -S point=(typeset -i x=3 y=4)
+ (( (point.x*point.x + point.y*point.y) == 25 )) || err_exit "local compound variable not working"
+ point.y=5
+ point.z=foobar
+}
+staticvar
+ (( (point.x*point.x + point.y*point.y) == 100 )) || err_exit "global compound variable not preserved"
+[[ $(staticvar x) == $'(\n\ttypeset -i x=3\n\ttypeset -i y=5\n\tz=foobar\n)' ]] || err_exit 'static variables in function not working'
+integer x=3
+( typeset -S x=+++)2> /dev/null || err_exit "typeset -S doesn't unset first"
+
+unset z
+( [[ ${z.foo.bar:-abc} == abc ]] 2> /dev/null) || err_exit ':- not working with compound variables'
+stack=()
+typeset -a stack.items=([0]=foo [1]=bar)
+[[ ${stack.items[0]} == foo ]] || err_exit 'typeset -a variable not expanding correctly'
+$SHELL -c 'typeset -a info=( [1]=( passwd=( since=2005-07-20) ))' || err_exit 'problem with embedded index array in compound variable'
+x=(foo=([1]=(y=([2]=(z=4)))))
+[[ $x == *'.y'=* ]] && err_exit 'expansion with bogus leading . in name'
+unset z
+z=1
+function foo
+{
+ z=3
+ [[ ${a.z} == 3 ]] && err_exit "\${a.z} should not be 3"
+ print hi
+}
+a=( b=$(foo) )
+[[ ${a.z} == 3 ]] && err_exit 'a.z should not be set to 3'
+function a.b.get
+{
+ .sh.value=foo
+}
+{ b=( b1=${a.b} ) ;} 2> /dev/null
+[[ ${b.b1} == foo ]] || err_exit '${b.b1} should be foo'
+function dcl1
+{
+ eval 'a=1
+ function a.set
+ { print ${.sh.name}=${.sh.value}; }'
+}
+function dcl2
+{
+ eval 'b=(typeset x=0; typeset y=0 )
+ function b.x.set
+ { print ${.sh.name}=${.sh.value}; }'
+}
+dcl1
+[[ ${ a=123;} == 'a=123' ]] || err_exit 'should be a=123'
+dcl2
+[[ ${ b.x=456;} == 'b.x=456' ]] || err_exit 'should be b.x=456'
+eval 'b=(typeset x=0; typeset y=0 )
+function b.x.set
+{ print ${.sh.name}=${.sh.value}; }' > /dev/null
+[[ ${ b.x=789;} == 'b.x=789' ]] || err_exit 'should be b.x=789'
+unset a b
+function func
+{
+ typeset X
+ X=( bar=2 )
+}
+
+X=( foo=1 )
+func
+[[ $X == $'(\n\tfoo=1\n)' ]] || err_exit 'scoping problem with compound variables'
+unset foo
+typeset -A foo=([a]=aa;[b]=bb;[c]=cc)
+[[ ${foo[c]} == cc ]] || err_exit 'associative array assignment with; not working'
+[[ $({ $SHELL -c 'x=(); typeset -a x.foo; x.foo=bar; print -r -- "$x"' ;} 2> /dev/null) == $'(\n\ttypeset -a foo=bar\n)' ]] || err_exit 'indexed array in compound variable with only element 0 defined fails'
+unset foo
+foo=(typeset -a bar)
+[[ $foo == *'typeset -a bar'* ]] || err_exit 'array attribute -a not preserved in compound variable'
+unset s
+typeset -A s=( [foo]=(y=2 z=3) [bar]=(y=4 z=5))
+[[ ${s[@]} == *z=*z=* ]] || err_exit 'missing elements in compound associative array'
+unset nodes
+typeset -A nodes
+nodes[0]+=( integer x=5)
+[[ ${nodes[0].x} == 5 ]] || err_exit '${nodes[0].x} should be 5'
+unset foo
+typeset -C foo
+foo.bar=abc
+[[ $foo == $'(\n\tbar=abc\n)' ]] || err_exit 'typeset -C not working for foo'
+typeset -C foo=(bar=def)
+[[ $foo == $'(\n\tbar=def\n)' ]] || err_exit 'typeset -C not working when initialized'
+foo=(
+ hello=ok
+ yes=( bam=2 yes=4)
+ typeset -A array=([one]=one [two]=2)
+ last=me
+)
+eval foo2="$foo"
+foo2.hello=notok foo2.yes.yex=no foo2.extra=yes.
+typeset -C bar bam
+{
+ read -Cu3 bar
+ read -Cu3 bam
+ read -ru3
+} 3<<- ++++
+ "$foo"
+ "$foo2"
+ last line
+++++
+[[ $? == 0 ]] || err_exit ' read -C failed'
+[[ $bar == "$foo" ]] || err_exit '$foo != $bar'
+[[ $bam == "$foo2" ]] || err_exit '$foo2 != $bmr'
+[[ $REPLY == 'last line' ]] || err_exit "\$REPLY=$REPLY should be 'last line"
+typeset x=( typeset -a foo=( [1][3]=hello [9][2]="world" ) )
+eval y="(typeset -a foo=$(printf "%B\n" x.foo) )"
+[[ $x == "$y" ]] || err_exit '$x.foo != $y.foo with %B'
+eval y="(typeset -a foo=$(printf "%#B\n" x.foo) )"
+[[ $x == "$y" ]] || err_exit '$x.foo != $y.foo with %#B'
+eval y="$(printf "%B\n" x)"
+[[ $x == "$y" ]] || err_exit '$x != $y with %B'
+eval y="$(printf "%#B\n" x)"
+[[ $x == "$y" ]] || err_exit '$x != $y with %#B'
+y=$(set | grep ^x=) 2> /dev/null
+eval "${y/#x/y}"
+[[ $x == "$y" ]] || err_exit '$x != $y with set | grep'
+unset x y z
+x=( float x=0 y=1; z=([foo]=abc [bar]=def))
+typeset -C y=x
+[[ $x == "$y" ]] || err_exit '$x != $y with typeset -C'
+unset y
+y=()
+y=x
+[[ $x == "$y" ]] || err_exit '$x != $y when x=y and x and y are -C '
+function foobar
+{
+ typeset -C z
+ z=x
+ [[ $x == "$z" ]] || err_exit '$x != $z when x=z and x and z are -C '
+ y=z
+}
+[[ $x == "$y" ]] || err_exit '$x != $y when x=y -C copied in a function '
+z=(foo=abc)
+y+=z
+[[ $y == *foo=abc* ]] || err_exit 'z not appended to y'
+unset y.foo
+[[ $x == "$y" ]] || err_exit '$x != $y when y.foo deleted'
+unset x y
+x=( foo=(z=abc d=ghi) bar=abc; typeset -A r=([x]=3 [y]=4))
+unset x
+x=()
+[[ $x == $'(\n)' ]] || err_exit 'unset compound variable is not empty'
+
+unset z
+z=()
+z.foo=( [one]=hello [two]=(x=3 y=4) [three]=hi)
+z.bar[0]=hello
+z.bar[2]=world
+z.bar[1]=(x=4 y=5)
+exp='(
+ typeset -a bar=(
+ [0]=hello
+ [2]=world
+ [1]=(
+ x=4
+ y=5
+ )
+ )
+ typeset -A foo=(
+ [one]=hello
+ [three]=hi
+ [two]=(
+ x=3
+ y=4
+ )
+ )
+)'
+got=$z
+[[ $got == "$exp" ]] || {
+ exp=$(printf %q "$exp")
+ got=$(printf %q "$got")
+ err_exit "compound indexed array pretty print failed -- expected $exp, got $got"
+}
+
+typeset -A record
+record[a]=(
+ typeset -a x=(
+ [1]=(
+ X=1
+ )
+ )
+)
+exp=$'(\n\ttypeset -a x=(\n\t\t[1]=(\n\t\t\tX=1\n\t\t)\n\t)\n)'
+got=${record[a]}
+[[ $got == "$exp" ]] || {
+ exp=$(printf %q "$exp")
+ got=$(printf %q "$got")
+ err_exit "compound indexed array pretty print failed -- expected $exp, got $got"
+}
+
+unset r
+r=(
+ typeset -a x=(
+ [1]=(
+ X=1
+ )
+ )
+)
+exp=$'(\n\ttypeset -a x=(\n\t\t[1]=(\n\t\t\tX=1\n\t\t)\n\t)\n)'
+got=$r
+[[ $got == "$exp" ]] || {
+ exp=$(printf %q "$exp")
+ got=$(printf %q "$got")
+ err_exit "compound indexed array pretty print failed -- expected $exp, got $got"
+}
+
+# array of compund variables
+typeset -C data=(
+ typeset -a samples
+)
+data.samples+=(
+ type1="greeting1"
+ timestamp1="now1"
+ command1="grrrr1"
+)
+data.samples+=(
+ type2="greeting2"
+ timestamp2="now2"
+ command2="grrrr2"
+)
+
+[[ $data == %(()) ]] || err_exit "unbalanced parenthesis with compound variable containing array of compound variables"
+typeset -C -A hello=( [foo]=bar)
+[[ $(typeset -p hello) == 'typeset -C -A hello=([foo]=bar)' ]] || err_exit 'typeset -A -C with intial assignment not working'
+# this caused a core dump before ksh93t+
+[[ $($SHELL -c 'foo=(x=3 y=4);function bar { typeset z=4;: $z;};bar;print ${!foo.@}') == 'foo.x foo.y' ]] 2> /dev/null || err_exit '${!foo.@} after function not working'
+
+function foo
+{
+ typeset tmp
+ read -C tmp
+ read -C tmp
+}
+foo 2> /dev/null <<- \EOF || err_exit 'deleting compound variable in function failed'
+ (
+ typeset -A myarray3=(
+ [a]=( foo=bar)
+ [b]=( foo=bar)
+ [c d]=( foo=bar)
+ [e]=( foo=bar)
+ [f]=( foo=bar)
+ [g]=( foo=bar)
+ [h]=( foo=bar)
+ [i]=( foo=bar)
+ [j]=( foo=bar)
+ )
+ )
+ hello
+EOF
+
+typeset -C -a mica01
+mica01[4]=( a_string="foo bar" )
+typeset -C more_content=(
+ some_stuff="hello"
+)
+mica01[4]+=more_content
+expected=$'typeset -C -a mica01=([4]=(a_string=\'foo bar\';some_stuff=hello))'
+[[ $(typeset -p mica01) == "$expected" ]] || err_exit 'appened to indexed array compound variable not working'
+
+unset x
+compound x=( integer x ; )
+[[ ! -v x.x ]] && err_exit 'x.x should be set'
+expected=$'(\n\ttypeset -l -i x=0\n)'
+[[ $(print -v x) == "$expected" ]] || err_exit "'print -v x' should be $expected"
+
+typeset -C -A hello19=(
+ [19]=(
+ one="xone 19"
+ two="xtwo 19"
+ )
+ [23]=(
+ one="xone 23"
+ two="xtwo 23"
+ )
+)
+expected="typeset -C -A hello19=([19]=(one='xone 19';two='xtwo 19') [23]=(one='xone 23';two='xtwo 23'))"
+[[ $(typeset -p hello19) == "$expected" ]] || print -u2 'typeset -p hello19 incorrect'
+expected=$'(\n\tone=\'xone 19\'\n\ttwo=\'xtwo 19\'\n) (\n\tone=\'xone 23\'\n\ttwo=\'xtwo 23\'\n)'
+[[ ${hello19[@]} == "$expected" ]] || print -u2 '${hello19[@]} incorrect'
+
+typeset -C -A foo1=( abc="alphabet" ) foo2=( abc="alphabet" )
+function add_one
+{
+ nameref left_op=$1
+ typeset -C info
+ info.hello="world"
+ nameref x=info
+ left_op+=x
+}
+nameref node1="foo1[1234]"
+add_one "node1"
+add_one "foo2[1234]"
+[[ "${foo1[1234]}" == "${foo2[1234]}" ]] || err_exit "test failed\n$(diff -u <( print -r -- "${foo1[1234]}") <(print -r -- "${foo2[1234]}"))."
+
+typeset -C tree
+function f1
+{
+ nameref tr=$1
+ typeset -A tr.subtree
+ typeset -C node
+ node.one="hello"
+ node.two="world"
+
+ # move local note into the array
+ typeset -m tr.subtree["a_node"]=node
+}
+f1 tree
+expected=$'(\n\ttypeset -A subtree=(\n\t\t[a_node]=(\n\t\t\tone=hello\n\t\t\ttwo=world\n\t\t)\n\t)\n)'
+[[ $tree == "$expected" ]] || err_exit 'move of compound local variable to global variable not working'
+
+typeset -C -A array
+float array[12].amount=2.9
+expected='typeset -C -A array=([12]=(typeset -l -E amount=2.9))'
+[[ $(typeset -p array) == "$expected" ]] || err_exit 'typeset with compound variable with compound variable array not working'
+
+typeset -T foo_t=(
+ function diff
+ {
+ print 1.0
+ return 0
+ }
+)
+foo_t sw
+compound output=(
+ integer one=1
+ float mydiff=sw.diff
+ float end=.314
+)
+[[ $output == *end=* ]] || err_exit "The field 'name' end is missing"
+
+compound cpv1=( integer f=2 )
+compound x=(
+ integer a=1
+ compound b=cpv1
+)
+[[ $x == *f=2* ]] || err_exit "The field b containg 'f=2' is missing"
+
+unset x
+compound x=(
+ compound -a nodes=(
+ [4]=( )
+ )
+)
+expected='typeset -C x=(typeset -C -a nodes=([4]=());)'
+[[ $(typeset -p x) == "$expected" ]] || err_exit 'typeset -p with nested compound index array not working'
+
+unset v
+compound v=(
+ integer -A ar=(
+ [aa]=4 [bb]=9
+ )
+)
+expected='typeset -C v=(typeset -A -l -i ar=([aa]=4 [bb]=9);)'
+[[ $(typeset -p v) == "$expected" ]] || err_exit 'attributes for associative arrays embedded in compound variables not working'
+
+unset x
+compound -a x
+x[1]=( a=1 b=2 )
+[[ $(print -v x[1]) == "${x[1]}" ]] || err_exit 'print -v x[1] not working for index array of compound variables'
+
+unset x
+z='typeset -a x=(hello (x=12;y=5) world)'
+{ eval "$z" ;} 2> /dev/null
+[[ $(typeset -p x) == "$z" ]] || err_exit "compound assignment '$z' not working"
+
+expected='typeset -C -A l=([4]=(typeset -a ar=(1 2 3);b=1))'
+typeset -A -C l
+printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4]
+[[ $(typeset -p l) == "$expected" ]] || err_exit 'read -C for associative array of compound variables not working'
+
+unset x
+compound x=( z="a=b c")
+exp=$'typeset -C x=(z=a\\=\'b c\')'
+got=$(typeset -p x)
+[[ $got == "$exp" ]] || err_exit "typeset -p failed -- expected '$exp', got '$got'"
+
+x=(typeset -C -a y;float z=2)
+got=$(print -C x)
+expected='(typeset -C -a y;typeset -l -E z=2)'
+[[ $expected == "$got" ]] || err_exit "print -C x exects '$expected' got '$got'"
+
+unset vx vy
+compound vx=(
+ compound -a va=(
+ [3][17]=(
+ integer -A ar=( [aa]=4 [bb]=9 )
+ )
+ )
+)
+eval "vy=$(print -C vx)"
+[[ $vx == "$vy" ]] || err_exit 'print -C with multi-dimensional array not working'
+eval "vy=$(print -v vx)"
+[[ $vx == "$vy" ]] || err_exit 'print -v with multi-dimensional array not working'
+
+unset x
+typeset -C -A x=( [0]=(a=1) [1]=(b=2) )
+expected=$'(\n\t[0]=(\n\t\ta=1\n\t)\n\t[1]=(\n\t\tb=2\n\t)\n)'
+[[ $(print -v x) == "$expected" ]] || err_exit 'print -v not formatting correctly'
+
+compound -a x=( [0]=(a=1) [1]=(b=2) )
+typeset -m "z=x[1]"
+[[ $(typeset -p z 2>/dev/null) == 'typeset -C z=(b=2)' ]] || err_exit 'typeset -m not working with commpound -a variable'
+
+unset x z
+compound -A x=( [0]=(a=1) [1]=(b=2) )
+typeset -m "z=x[1]"
+[[ $(typeset -p z 2>/dev/null) == 'typeset -C z=(b=2)' ]] || err_exit 'typeset -m not working with commpound -a variable'
+typeset -m "x[1]=x[0]"
+typeset -m "x[0]=z"
+exp='([0]=(b=2) [1]=(a=1))'
+[[ $(print -C x) == "$exp" ]] || err_exit 'typeset -m not working for associative arrays'
+
+unset z r
+z=(a b c)
+r=(x=3 y=4)
+typeset -m z[1]=r
+exp='typeset -a z=(a (x=3;y=4) c)'
+[[ $(typeset -p z) == "$exp" ]] || err_exit 'moving compound variable into indexed array fails'
+
+unset c
+compound c
+compound -a c.a=( [1]=( aa=1 ) )
+compound -a c.b=( [2]=( bb=2 ) )
+typeset -m "c.b[9]=c.a[1]"
+exp='typeset -C c=(typeset -C -a a;typeset -C -a b=( [2]=(bb=2;)[9]=(aa=1));)'
+[[ $(typeset -p c) == "$exp" ]] || err_exit 'moving compound indexed array element to another index fails'
+
+unset c
+compound c
+compound -a c.a=( [1]=( aa=1 ) )
+compound -A c.b=( [2]=( bb=2 ) )
+typeset -m "c.b[9]=c.a[1]"
+exp='typeset -C c=(typeset -C -a a;typeset -C -A b=( [2]=(bb=2;)[9]=(aa=1));)'
+[[ $(typeset -p c) == "$exp" ]] || err_exit 'moving compound indexed array element to a compound associative array element fails'
+
+zzz=(
+ foo=(
+ bar=4
+ )
+)
+[[ $(set | grep "^zzz\.") ]] && err_exit 'set displays compound variables incorrectly'
+
+typeset -A stats
+stats[1]=(a=1 b=2)
+stats[2]=(a=1 b=2)
+stats[1]=(c=3 d=4)
+(( ${#stats[@]} == 2 )) || err_exit "stats[1] should contain 2 element not ${#stats[@]}"
+
+integer i=1
+foo[i++]=(x=3 y=4)
+[[ ${foo[1].x} == 3 ]] || err_exit "\${foo[1].x} should be 3"
+[[ ${foo[1].y} == 4 ]] || err_exit "\${foo[1].y} should be 4"
+
+# ${!x.} caused core dump in ks93u and earlier
+{ $SHELL -c 'compound x=(y=1); : ${!x.}' ; ((!$?));} || err_exit '${!x.} not working'
+
+$SHELL -c 'typeset -A a=([b]=c)' 2> /dev/null || err_exit 'typeset -A a=([b]=c) fails'
+
+compound -a a
+compound c=( name="container1" )
+a[4]=c
+[[ ${a[4]} == $'(\n\tname=container1\n)' ]] || err_exit 'assignment of compound variable to compound array element not working'
+
+unset c
+compound c
+compound -a c.board
+for ((i=2; i < 4; i++))
+do c.board[1][$i]=(foo=bar)
+done
+exp=$'(\n\ttypeset -C -a board=(\n\t\t[1]=(\n\t\t\t[2]=(\n\t\t\t\tfoo=bar\n\t\t\t)\n\t\t\t[3]=(\n\t\t\t\tfoo=bar\n\t\t\t)\n\t\t)\n\t)\n)'
+[[ "$(print -v c)" == "$exp" ]] || err_exit 'compound variable assignment to two dimensional array not working'
+
+unset zz
+zz=()
+zz.[foo]=abc
+zz.[2]=def
+exp='typeset -C zz=([2]=def;foo=abc)'
+[[ $(typeset -p zz) == "$exp" ]] || err_exit 'expansion of compound variables with non-identifiers not working'
+(
+ typeset -i zz.[3]=123
+ exec 2>& 3-
+ exp='typeset -C zz=([2]=def;typeset -i [3]=123;foo=abc)'
+ [[ $(typeset -p zz) == "$exp" ]] || err_exit 'expansion of compound variables with non-identifiers not working in subshells'
+) 3>&2 2> /dev/null || err_exit 'syntax errors expansion of compound variables with non-identifiers'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/comvario.sh b/src/cmd/ksh93/tests/comvario.sh
new file mode 100644
index 0000000..8ed803a
--- /dev/null
+++ b/src/cmd/ksh93/tests/comvario.sh
@@ -0,0 +1,686 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Roland Mainz <roland.mainz@nrubsig.org> #
+# #
+########################################################################
+
+# test setup
+function err_exit
+{
+ print -u2 -n '\t'
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+# "nounset" disabled for now
+#set -o nounset
+Command=${0##*/}
+integer Errors=0 HAVE_signbit=0
+
+if typeset -f .sh.math.signbit >/dev/null && (( signbit(-NaN) ))
+then HAVE_signbit=1
+else print -u2 "$0: warning: -lm does not support signbit(-NaN)"
+fi
+
+compound bracketstat=(
+ integer bopen=0
+ integer bclose=0
+)
+
+function count_brackets
+{
+ typeset x="$1"
+ typeset c
+
+ integer i
+ (( bracketstat.bopen=0 , bracketstat.bclose=0 ))
+
+ for (( i=0 ; i < ${#x} ; i++ )) ; do
+ c="${x:i:1}"
+ [[ "$c" == '(' ]] && (( bracketstat.bopen++ ))
+ [[ "$c" == ')' ]] && (( bracketstat.bclose++ ))
+ done
+
+ (( bracketstat.bopen != bracketstat.bclose )) && return 1
+
+ return 0
+}
+
+# compound variable "cat" nr.1, using $ print "%B\n" ... #
+function cpvcat1
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do printf '%B\n' tmp ; done
+ return 0
+}
+
+# compound variable "cat" nr.2, using $ print "%#B\n" ... #
+function cpvcat2
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do printf '%#B\n' tmp ; done
+ return 0
+}
+
+# compound variable "cat" nr.3, using $ print -C ... #
+function cpvcat3
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do print -C tmp ; done
+ return 0
+}
+
+# compound variable "cat" nr.4, using $ print -v ... #
+function cpvcat4
+{
+ set -o errexit
+ compound tmp
+
+ while read -C tmp ; do print -v tmp ; done
+ return 0
+}
+
+typeset s
+
+# Test 1:
+# Check whether "read -C" leaves the file pointer at the next line
+# (and does not read beyond that point).
+# Data layout is:
+# -- snip --
+# <compound var>
+# hello
+# -- snip --
+# (additionally we test some extra stuff like bracket count)
+s=${
+ compound x=(
+ a=1 b=2
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 )
+ typeset -A myarray3=(
+ [a]=(
+ float m1=0.5
+ float m2=0.6
+ foo="hello"
+ )
+ [b]=(
+ foo="bar"
+ )
+ ["c d"]=(
+ integer at=90
+ )
+ [e]=(
+ compound nested_cpv=(
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset str=$'a \'string'
+ )
+ )
+ [f]=(
+ typeset g="f"
+ )
+ [a_nan]=(
+ float my_nan=-nan
+ )
+ [a_hexfloat]=(
+ typeset -X my_hexfloat=1.1
+ )
+ )
+ )
+
+ {
+ printf "%B\n" x
+ print "hello"
+ } | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | {
+ read -C y
+ read s
+ }
+ print "x${s}x"
+} || err_exit "test returned exit code $?"
+
+[[ "${s}" == "xhellox" ]] || err_exit "Expected 'xhellox', got ${s}"
+count_brackets "$y" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v y)" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C y)" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+
+# cleanup
+unset x y || err_exit "unset failed"
+[[ "$x" == '' ]] || err_exit "cleanup failed for x"
+[[ "$y" == '' ]] || err_exit "cleanup failed for y"
+
+
+# Test 2:
+# Same as test 1 except one more compound var following the "hello"
+# line.
+# Data layout is:
+# -- snip --
+# <compound var>
+# hello
+# <compound var>
+# -- snip --
+s=${
+ compound x=(
+ a=1 b=2
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 )
+ compound -A myarray3=(
+ [a]=(
+ float m1=0.5
+ float m2=0.6
+ foo="hello"
+ )
+ [b]=(
+ foo="bar"
+ )
+ ["c d"]=(
+ integer at=90
+ )
+ [e]=(
+ compound nested_cpv=(
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset str=$'a \'string'
+ )
+ )
+ [f]=(
+ typeset g="f"
+ )
+ [a_nan]=(
+ float my_nan=-nan
+ )
+ [a_hexfloat]=(
+ typeset -X my_hexfloat=1.1
+ )
+ )
+ )
+
+ {
+ printf "%B\n" x
+ print "hello"
+ printf "%B\n" x
+ } | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | {
+ read -C y1
+ read s
+ read -C y2
+ }
+
+ print "x${s}x"
+} || err_exit "test returned exit code $?"
+
+[[ "${s}" == "xhellox" ]] || err_exit "Expected 'xhellox', got ${s}."
+[[ "${y1.myarray3[b].foo}" == "bar" ]] || err_exit "y1.myarray3[b].foo != bar"
+[[ "${y2.myarray3[b].foo}" == "bar" ]] || err_exit "y2.myarray3[b].foo != bar"
+[[ "$y1" != "" ]] || err_exit "y1 is empty"
+[[ "$y2" != "" ]] || err_exit "y2 is empty"
+(( ${#y1.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in y1.myarray3[e].nested_cpv, got ${#y1.myarray3[e].nested_cpv[@]}"
+(( ${#y2.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in y2.myarray3[e].nested_cpv, got ${#y2.myarray3[e].nested_cpv[@]}"
+(( isnan(y1.myarray3[a_nan].my_nan) )) || err_exit "y1.myarray3[a_nan].my_nan not a NaN"
+(( isnan(y2.myarray3[a_nan].my_nan) )) || err_exit "y2.myarray3[a_nan].my_nan not a NaN"
+if (( HAVE_signbit ))
+then (( signbit(y1.myarray3[a_nan].my_nan) )) || err_exit "y1.myarray3[a_nan].my_nan not negative"
+ (( signbit(y2.myarray3[a_nan].my_nan) )) || err_exit "y2.myarray3[a_nan].my_nan not negative"
+fi
+count_brackets "$y1" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v y1)" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C y1)" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$y2" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v y2)" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C y2)" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+[[ "$y1" == "$y2" ]] || err_exit "Expected $(printf "%q\n" "${y1}") == $(printf "%q\n" "${y2}")."
+[[ "$x" == "$y1" ]] || err_exit "Expected $(printf "%q\n" "${x}") == $(printf "%q\n" "${y}")."
+
+# cleanup
+unset x y1 y2 || err_exit "unset failed"
+[[ "$x" == '' ]] || err_exit "cleanup failed for x"
+[[ "$y1" == '' ]] || err_exit "cleanup failed for y1"
+[[ "$y2" == '' ]] || err_exit "cleanup failed for y2"
+
+
+# Test 3: Test compound variable copy operator vs. "read -C"
+compound x=(
+ a=1 b=2
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 )
+ compound -A myarray3=(
+ [a]=(
+ float m1=0.5
+ float m2=0.6
+ foo="hello"
+ )
+ [b]=(
+ foo="bar"
+ )
+ ["c d"]=(
+ integer at=90
+ )
+ [e]=(
+ compound nested_cpv=(
+ typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 )
+ typeset str=$'a \'string'
+ )
+ )
+ [f]=(
+ typeset g="f"
+ )
+ [a_nan]=(
+ float my_nan=-nan
+ )
+ [a_hexfloat]=(
+ typeset -X my_hexfloat=1.1
+ )
+ )
+)
+
+compound x_copy=x || err_exit "x_copy copy failed"
+[[ "${x_copy}" != "" ]] || err_exit "x_copy should not be empty"
+count_brackets "${x_copy}" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v x_copy)" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C x_copy)" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+
+compound nested_cpv_copy
+
+nested_cpv_copy=x.myarray3[e].nested_cpv || err_exit "x.myarray3[e].nested_cpv copy failed"
+(( ${#nested_cpv_copy.myarray[@]} == 10 )) || err_exit "Expected 10 elements in nested_cpv_copy.myarray, got ${#nested_cpv_copy.myarray[@]}"
+
+# unset branch "x.myarray3[e].nested_cpv" of the variable tree "x" ...
+unset x.myarray3[e].nested_cpv || err_exit "unset x.myarray3[e].nested_cpv failed"
+[[ "${x.myarray3[e].nested_cpv}" == "" ]] || err_exit "x.myarray3[e].nested_cpv still has a value"
+
+# ... and restore it from the saved copy
+printf "%B\n" nested_cpv_copy | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | read -C x.myarray3[e].nested_cpv || err_exit "read failed"
+
+# compare copy of the original tree and the modified one
+[[ "${x}" == "${x_copy}" ]] || err_exit "x != x_copy"
+count_brackets "${x}" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -v x)" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+count_brackets "$(print -C x)" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
+(( ${#x.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in x.myarray3[e].nested_cpv, got ${#x.myarray3[e].nested_cpv[@]}"
+(( isnan(x.myarray3[a_nan].my_nan) )) || err_exit "x.myarray3[a_nan].my_nan not a NaN"
+if (( HAVE_signbit ))
+then (( signbit(x.myarray3[a_nan].my_nan) )) || err_exit "x.myarray3[a_nan].my_nan not negative"
+fi
+
+# cleanup
+unset x x_copy nested_cpv_copy || err_exit "unset failed"
+
+
+# Test 4: Test "read -C" failure for missing bracket at the end
+typeset s
+s=$($SHELL -c 'compound myvar ; print "( unfinished=1" | read -C myvar 2>'/dev/null' || print "error $?"') || err_exit 'shell failed'
+[[ "$s" == 'error 3' ]] || err_exit "compound_read: expected error 3, got ${s}"
+
+
+# Test 5: Test "read -C" failure for missing bracket at the beginning
+typeset s
+s=$($SHELL -c 'compound myvar ; print " unfinished=1 )" | read -C myvar 2>'/dev/null' || print "error $?"') || err_exit 'shell failed'
+[[ "$s" == 'error 3' ]] || err_exit "compound_read: expected error 3, got ${s}"
+
+
+# test6: Derived from the test2 for CR #6944386
+# ("compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -C v prints trash")
+# which caused compound variables to be corrupted like this:
+# -- snip --
+# ksh93 -c 'compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -v v'
+# (
+# typeset -A -l -i ar=(
+# [aa]=$'\004'
+# [bb]=$'\t'
+# )
+# )
+# -- snip --
+
+function test6
+{
+ compound out=( typeset stdout stderr ; integer res )
+ compound val
+ integer testid
+
+ compound -r -a tests=(
+ # subtests1:
+ ( cmd='compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -C v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='ar' )
+ ( cmd='compound v=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -C v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='ar' )
+ ( cmd='compound v=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -C v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='ar' )
+ ( cmd='compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -v v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='ar' )
+ ( cmd='compound v=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -v v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='ar' )
+ ( cmd='compound v=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; print -v v' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='ar' )
+
+ # subtests2: Same as subtests1 but variable "v" is inside "vx"
+ ( cmd='compound vx=( compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='v.ar' )
+ ( cmd='compound vx=( compound v=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='v.ar' )
+
+ # subtests3: Same as subtests1 but variable "va" is an indexed array
+ ( cmd='compound vx=( compound -a va=( [3]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3].ar' )
+ ( cmd='compound vx=( compound -a va=( [3]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[3].ar' )
+
+ # subtests4: Same as subtests1 but variable "va" is an 2d indexed array
+ ( cmd='compound vx=( compound -a va=( [3][17]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[3][17].ar' )
+ ( cmd='compound vx=( compound -a va=( [3][17]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[3][17].ar' )
+
+ # subtests5: Same as subtests1 but variable "va" is an associative array
+ ( cmd='compound vx=( compound -A va=( [l]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -C vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( integer -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( float -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=9.*)&(.*\\[aa\\]=4.*)' arrefname='va[l].ar' )
+ ( cmd='compound vx=( compound -A va=( [l]=( typeset -A ar=( [aa]=4 [bb]=9 ) ; ) ; ) ; ) ; print -v vx' stdoutpattern=$'~(Alr)(.*\\[bb\\]=["\']*9.*)&(.*\\[aa\\]=["\']*4.*)' arrefname='va[l].ar' )
+ )
+
+ for testid in "${!tests[@]}" ; do
+ nameref test=tests[testid]
+ typeset testname="test2/${testid}"
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -c "${test.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ (( out.res == 0 )) || err_exit "${testname}: Test shell returned with exit code ${out.res}"
+ [[ "${out.stdout}" == ${test.stdoutpattern} ]] || err_exit "${testname}: Expected match for ${test.stdoutpattern}, got $(printf "%q\n" "${out.stdout}")"
+ [[ "${out.stderr}" == "" ]] || err_exit "${testname}: Expected empty stderr, got $(printf "%q\n" "${out.stderr}")"
+
+ read -C val <<<"${out.stdout}" || err_exit "${testname}: read -C val failed with exit code $?"
+ nameref ar="val.${test.arrefname}"
+ (( ar[aa] == 4 )) || err_exit "${testname}: Expected ar[aa] == 4, got ${ar[aa]}"
+ (( ar[bb] == 9 )) || err_exit "${testname}: Expected ar[bb] == 9, got ${ar[bb]}"
+ done
+
+ return 0
+}
+
+test6
+
+function test_3D_array_read_C
+{
+ compound out=( typeset stdout stderr ; integer res )
+ integer i
+ typeset -r -a tests=(
+ # ast-ksh.2010-03-09 will print "ksh93[1]: read: line 4: 0[0]: invalid variable name" for 3D arrays passed to read -C
+ 'compound c=( typeset -a x ) ; for (( i=0 ; i < 3 ; i++ )) ; do for (( j=0 ; j < 3 ; j++ )) ; do for (( k=0 ; k < 3 ; k++ )) ; do c.x[i][j][k]="$i$j$k" ; done; done; done ; unset c.x[2][0][1] ; print -v c | read -C dummy'
+
+ # same test, 4D, fails with 'ksh[1]: read: line 4: 0: invalid variable name'
+ 'compound c=( typeset -a x ) ; for (( i=0 ; i < 3 ; i++ )) ; do for (( j=0 ; j < 3 ; j++ )) ; do for (( k=0 ; k < 3 ; k++ )) ; do for (( l=0 ; l < 3 ; l++ )) ; do c.x[i][j][k][l]="$i$j$k$l" ; done; done; done ; done ; unset c.x[2][0][1][2] ; print -v c | read -C dummy'
+ )
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${tests[i]}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" == '' ]] || err_exit "$0/${i}: Expected empty stdout, got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "$0/${i}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ done
+
+ return 0
+}
+
+
+function test_access_2Darray_in_type_in_compound
+{
+ compound out=( typeset stdout stderr ; integer res )
+ integer i
+ typeset -r -a tests=(
+ # ast-ksh.2010-03-09 will print 'ksh: line 1: l.c.x[i][j]=: no parent'
+ 'typeset -T c_t=(typeset -a x) ; compound l=( c_t c ) ; for ((i=0;i<3;i++));do for ((j=0;j<3;j++));do l.c.x[i][j]="" ; done; done; print -v l | read -C dummy'
+ )
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${tests[i]}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" == '' ]] || err_exit "$0/${i}: Expected empty stdout, got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "$0/${i}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ done
+
+ return 0
+}
+
+function test_read_type_crash
+{
+ compound out=( typeset stdout stderr ; integer res )
+ typeset -r test='
+typeset -T field_t=(
+ typeset -a f
+
+ function reset
+ {
+ integer i j
+
+ for (( i=0 ; i < 3 ; i++ )) ; do
+ for (( j=0 ; j < 3 ; j++ )) ; do
+ _.f[i][j]=""
+ done
+ done
+ return 0
+ }
+
+ function enumerate_empty_fields
+ {
+ integer i j
+
+ for (( i=0 ; i < 3 ; i++ )) ; do
+ for (( j=0 ; j < 3 ; j++ )) ; do
+ [[ "${_.f[i][j]}" == "" ]] && printf "[%d][%d]\n" i j
+ done
+ done
+ return 0
+ }
+
+ function setf
+ {
+ _.f[$1][$2]="$3"
+ }
+)
+
+set -o nounset
+
+compound c1=( field_t x )
+
+c1.x.reset
+
+print -v c1 | read -C c2
+print -v c2
+'
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${test}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" != '' ]] || err_exit "$0: Expected nonempty stdout."
+ [[ "${out.stderr}" == '' ]] || err_exit "$0: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+
+ if [[ -f 'core' && -x '/usr/bin/pstack' ]] ; then
+ pstack 'core'
+ rm 'core'
+ fi
+
+ return 0
+}
+
+
+function test_read_C_into_array
+{
+ compound out=( typeset stdout stderr ; integer res )
+ # fixme:
+ # - The tests should cover 3D and 5D indexed arrays and namerefs to sub-dimensions of a 5D indexed array
+ compound -r -a tests=(
+ ( cmd=' typeset -a -C l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4] ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd=' typeset -a -C l ; nameref l4=l[4] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+
+ ( cmd=' typeset -a -C l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4][6] ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' ) )
+ ( cmd=' typeset -a -C l ; nameref l4=l[4][6] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' ) )
+
+ ( cmd=' typeset -a -C l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4][6][9][11][15] ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' '~(X)(.+\[9\].+)&(.+\[11\].+)&(.+\[15\].+)' ) )
+ ( cmd=' typeset -a -C l ; nameref l4=l[4][6][9][11][15] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' '~(X)(.+\[9\].+)&(.+\[11\].+)&(.+\[15\].+)' ) )
+
+ ( cmd=' typeset -A -C l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4] ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd=' typeset -A -C l ; nameref l4=l[4] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v l' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd='compound c ; typeset -a -C c.l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C c.l[4] ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd='compound c ; typeset -a -C c.l ; nameref l4=c.l[4] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+
+ ( cmd='compound c ; typeset -a -C c.l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C c.l[4][6] ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' ) )
+ ( cmd='compound c ; typeset -a -C c.l ; nameref l4=c.l[4][6] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' ) )
+
+ ( cmd='compound c ; typeset -a -C c.l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C c.l[4][6][9][11][15] ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' '~(X)(.+\[9\].+)&(.+\[11\].+)&(.+\[15\].+)' ) )
+ ( cmd='compound c ; typeset -a -C c.l ; nameref l4=c.[4][6][9][11][15] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)&(.+\[6\].+)' '~(X)(.+\[9\].+)&(.+\[11\].+)&(.+\[15\].+)' ) )
+
+ ( cmd='compound c ; typeset -A -C c.l ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C c.l[4] ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ ( cmd='compound c ; typeset -A -C c.l ; nameref l4=c.l[4] ; printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4 ; print -v c' typeset -a stdoutpattern=( '~(X)(.+b=1.+)&(.+\[4\].+)' ) )
+ )
+ typeset cmd
+ typeset pat
+ integer i
+
+ compound -a test_variants
+
+ # build list of variations of the tests above
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ nameref tst=tests[i]
+
+ # plain test
+ cmd="${tst.cmd}"
+ test_variants+=( testname="${0}/${i}/plain" cmd="$cmd" typeset -a stdoutpattern=( "${tst.stdoutpattern[@]}" ) )
+
+ # test with "read -C" in a function
+ cmd="${tst.cmd/~(E)read[[:space:]]+-C[[:space:]]+([[:alnum:]]+)[[:space:]]+\;/{ function rf { nameref val=\$1 \; read -C val \; } \; rf \1 \; } \; }"
+ test_variants+=( testname="${0}/${i}/read_in_function" cmd="$cmd" typeset -a stdoutpattern=( "${tst.stdoutpattern[@]}" ) )
+
+ # test with "read -C" in a nested function
+ cmd="${tst.cmd/~(E)read[[:space:]]+-C[[:space:]]+([[:alnum:]]+)[[:space:]]+\;/{ function rf2 { nameref val=\$1 \; read -C val \; } \; function rf { nameref val=\$1 \; rf2 val \; } \; rf \1 \; } \; }"
+ test_variants+=( testname="${0}/${i}/read_in_nested_function" cmd="$cmd" typeset -a stdoutpattern=( "${tst.stdoutpattern[@]}" ) )
+
+ # test with "read -C" in a nested function with target variable
+ # being a function-local variable of function "main"
+ cmd='function rf2 { nameref val=$1 ; read -C val ; } ; function rf { nameref val=$1 ; rf2 val ; } ; function main { '
+ cmd+="${tst.cmd/~(E)read[[:space:]]+-C[[:space:]]+([[:alnum:]]+)[[:space:]]+\;/rf \1 \; }"
+ cmd+=' ; } ; main'
+ test_variants+=( testname="${0}/${i}/read_into_localvar_in_nested_function" cmd="$cmd" typeset -a stdoutpattern=( "${tst.stdoutpattern[@]}" ) )
+ done
+
+ # run test variants
+ for (( i=0 ; i < ${#test_variants[@]} ; i++ )) ; do
+ nameref tv=test_variants[i]
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -o errexit -c "${tv.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ for pat in "${tv.stdoutpattern[@]}" ; do
+ [[ "${out.stdout}" == ${pat} ]] || err_exit "${tv.testname}: Expected stdout of $(printf '%q\n' "${tv.cmd}") to match $(printf '%q\n' "${pat}"), got $(printf '%q\n' "${out.stdout}")"
+ done
+ [[ "${out.stderr}" == '' ]] || err_exit "${tv.testname}: Expected empty stderr for $(printf '%q\n' "${tv.cmd}"), got $(printf '%q\n' "${out.stderr}")"
+ (( out.res == 0 )) || err_exit "${tv.testname}: Unexpected exit code ${out.res} for $(printf '%q\n' "${tv.cmd}")"
+ done
+
+ return 0
+}
+
+
+# This test checks whether reading a compound variable value with
+# "read -C var" which contains special shell keywords or aliases
+# like "functions", "alias", "!" etc. in a string array causes the
+# shell to produce errors like this:
+# -- snip --
+# $ ksh93 -c 'print "( compound -A a1=( [4]=( typeset -a x=( alias ) ) ) ;
+# compound -A a2=( [4]=( typeset -a x=( ! ! ! alias ) ) ) )" | read -C c ; print -v c' 1>/dev/null
+# ksh93[1]: alias: c.a1[4].x: compound assignment requires sub-variable name
+# -- snip --
+# A 2nd issue indirectly tested here was that simple indexed string array
+# declarations in a function with the same special keywords did not work
+# either.
+# This happened in ast-ksh.2010-11-12 or older.
+function test_read_C_special_shell_keywords
+{
+ typeset -r -a testcmdpatterns=(
+ # this was the original testcase
+ 'print "( compound -A a1=( [4]=( typeset -a x=( %keyword% ) ) ) ; compound -A a2=( [4]=( typeset -a x=( ! ! ! alias ) ) ) )" | read -C c ; print "X${c.a1[4].x[0]}X"'
+ # same as above but uses indexed arrays instead of associative arrays
+ 'print "( compound -a a1=( [4]=( typeset -a x=( %keyword% ) ) ) ; compound -a a2=( [4]=( typeset -a x=( ! ! ! alias ) ) ) )" | read -C c ; print "X${c.a1[4].x[0]}X"'
+ # same as first testcase but uses a blank in the array index value
+ $'print "( compound -A a1=( [\'hello world\']=( typeset -a x=( %keyword% ) ) ) ; compound -A a2=( [\'hello world\']=( typeset -a x=( ! ! ! alias ) ) ) )" | read -C c ; print "X${c.a1[\'hello world\'].x[0]}X"'
+ )
+ typeset -r -a shell_special_words=(
+ 'alias'
+ 'compound'
+ 'function'
+ 'functions'
+ 'integer'
+ 'local'
+ 'namespace'
+ 'typeset'
+ 'SECONDS'
+ '.sh.version'
+ '!'
+ )
+ integer spwi # shell_special_words index
+ integer tcpi # testcmdpatterns index
+ typeset testcmd
+ typeset testname
+ typeset shkeyword
+ compound out=( typeset stdout stderr ; integer res )
+
+ for (( tcpi=0 ; tcpi < ${#testcmdpatterns[@]} ; tcpi++ )) ; do
+ for (( spwi=0 ; spwi < ${#shell_special_words[@]} ; spwi++ )) ; do
+ shkeyword=${shell_special_words[spwi]}
+ testcmd="${testcmdpatterns[tcpi]//%keyword%/${shkeyword}}"
+ testname="${0}/${tcpi}/${spwi}/"
+
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -o errexit -c "${testcmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ [[ "${out.stdout}" == "X${shkeyword}X" ]] || err_exit "${testname}: Expected stdout to match $(printf '%q\n' "X${shkeyword}X"), got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "${testname}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ (( out.res == 0 )) || err_exit "${testname}: Unexpected exit code ${out.res}"
+ done
+ done
+
+ return 0
+}
+
+
+test_3D_array_read_C
+test_access_2Darray_in_type_in_compound
+test_read_type_crash
+test_read_C_into_array
+test_read_C_special_shell_keywords
+
+
+# tests done
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/coprocess.sh b/src/cmd/ksh93/tests/coprocess.sh
new file mode 100755
index 0000000..749f691
--- /dev/null
+++ b/src/cmd/ksh93/tests/coprocess.sh
@@ -0,0 +1,360 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+# test the behavior of co-processes
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+if [[ -d /cygdrive ]]
+then err_exit cygwin detected - coprocess tests disabled - enable at the risk of wedging your system
+ exit $((Errors))
+fi
+
+bintrue=$(whence -p true)
+
+function ping # id
+{
+ integer x=0
+ while ((x++ < 5))
+ do read -r
+ print -r "$1 $REPLY"
+ done
+}
+
+cat |&
+print -p "hello"
+read -p line
+[[ $line == hello ]] || err_exit 'coprocessing fails'
+exec 5>&p 6<&p
+print -u5 'hello again' || err_exit 'write on u5 fails'
+read -u6 line
+[[ $line == 'hello again' ]] || err_exit 'coprocess after moving fds fails'
+exec 5<&- 6<&-
+wait $!
+
+ping three |&
+exec 3>&p
+ping four |&
+exec 4>&p
+ping pipe |&
+
+integer count
+for i in three four pipe four pipe four three pipe pipe three pipe
+do case $i in
+ three) to=-u3;;
+ four) to=-u4;;
+ pipe) to=-p;;
+ esac
+ (( count++ ))
+ print $to $i $count
+done
+
+while ((count > 0))
+do (( count-- ))
+ read -p
+ set -- $REPLY
+ if [[ $1 != $2 ]]
+ then err_exit "$1 does not match $2"
+ fi
+ case $1 in
+ three) ;;
+ four) ;;
+ pipe) ;;
+ *) err_exit "unknown message +|$REPLY|+" ;;
+ esac
+done
+kill $(jobs -p) 2>/dev/null
+
+file=$tmp/regress
+cat > $file <<\!
+/bin/cat |&
+!
+chmod +x $file
+sleep 10 |&
+$file 2> /dev/null || err_exit "parent coprocess prevents script coprocess"
+exec 5<&p 6>&p
+exec 5<&- 6>&-
+kill $(jobs -p) 2>/dev/null
+
+${SHELL-ksh} |&
+cop=$!
+exp=Done
+print -p $'print hello | cat\nprint '$exp
+read -t 5 -p
+read -t 5 -p
+got=$REPLY
+if [[ $got != $exp ]]
+then err_exit "${SHELL-ksh} coprocess io failed -- got '$got', expected '$exp'"
+fi
+exec 5<&p 6>&p
+exec 5<&- 6>&-
+{ sleep 4; kill $cop; } 2>/dev/null &
+spy=$!
+if wait $cop 2>/dev/null
+then kill $spy 2>/dev/null
+else err_exit "coprocess hung after 'exec 5<&p 6>&p; exec 5<&- 6>&-'"
+fi
+wait
+
+{
+echo line1 | grep 'line2'
+echo line2 | grep 'line1'
+} |&
+SECONDS=0 count=0
+while read -p -t 10 line
+do ((count++))
+done
+if (( SECONDS > 8 ))
+then err_exit "read -p hanging (SECONDS=$SECONDS count=$count)"
+fi
+wait $!
+
+( sleep 3 |& sleep 1 && kill $!; sleep 1; sleep 3 |& sleep 1 && kill $! ) ||
+ err_exit "coprocess cleanup not working correctly"
+{ : |& } 2>/dev/null ||
+ err_exit "subshell coprocess lingers in parent"
+wait $!
+
+unset N r e
+integer N=5
+e=12345
+(
+ integer i
+ for ((i = 1; i <= N; i++))
+ do print $i |&
+ read -p r
+ print -n $r
+ wait $!
+ done
+ print
+) 2>/dev/null | read -t 10 r
+[[ $r == $e ]] || err_exit "coprocess timing bug -- expected $e, got '$r'"
+r=
+(
+ integer i
+ for ((i = 1; i <= N; i++))
+ do print $i |&
+ sleep 0.01
+ r=$r$(cat <&p)
+ wait $!
+ done
+ print $r
+) 2>/dev/null | read -t 10 r
+[[ $r == $e ]] || err_exit "coprocess command substitution bug -- expected $e, got '$r'"
+
+(
+ /bin/cat |&
+ sleep 0.01
+ exec 6>&p
+ print -u6 ok
+ exec 6>&-
+ sleep 2
+ kill $! 2> /dev/null
+) && err_exit 'coprocess with subshell would hang'
+for sig in IOT ABRT
+do if ( trap - $sig ) 2> /dev/null
+ then if [[ $( { sig=$sig $SHELL 2> /dev/null <<- '++EOF++'
+ cat |&
+ pid=$!
+ trap "print TRAP" $sig
+ (
+ sleep 2
+ kill -$sig $$
+ sleep 2
+ kill -$sig $$
+ kill $pid
+ sleep 2
+ kill $$
+ ) &
+ while read -p || (($? > 256))
+ do :
+ done
+ ++EOF++
+ } ) != $'TRAP\nTRAP' ]] 2> /dev/null
+ then err_exit 'traps when reading from coprocess not working'
+ fi
+ break
+ fi
+done
+
+trap 'sleep_pid=; kill $pid; err_exit "coprocess 1 hung"' TERM
+{ sleep 5; kill $$; } &
+sleep_pid=$!
+builtin cat
+cat |&
+pid=$!
+exec 5<&p 6>&p
+exp=hi
+print -u6 $exp; read -u5
+[[ $REPLY == "$exp" ]] || err_exit "REPLY failed -- expected '$exp', got '$REPLY'"
+exec 6>&-
+wait $pid
+trap - TERM
+[[ $sleep_pid ]] && kill $sleep_pid
+
+trap 'sleep_pid=; kill $pid; err_exit "coprocess 2 hung"' TERM
+{ sleep 5; kill $$; } &
+sleep_pid=$!
+cat |&
+pid=$!
+print foo >&p 2> /dev/null || err_exit 'first write of foo to coprocess failed'
+print foo >&p 2> /dev/null || err_exit 'second write of foo to coprocess failed'
+kill $pid
+wait $pid 2> /dev/null
+trap - TERM
+[[ $sleep_pid ]] && kill $sleep_pid
+
+trap 'sleep_pid=; kill $pid; err_exit "coprocess 3 hung"' TERM
+{ sleep 5; kill $$; } &
+sleep_pid=$!
+cat |&
+pid=$!
+print -p foo
+print -p bar
+read <&p || err_exit 'first read from coprocess failed'
+[[ $REPLY == foo ]] || err_exit "first REPLY is $REPLY not foo"
+read <&p || err_exit 'second read from coprocess failed'
+[[ $REPLY == bar ]] || err_exit "second REPLY is $REPLY not bar"
+kill $pid
+wait $pid 2> /dev/null
+trap - TERM
+[[ $sleep_pid ]] && kill $sleep_pid
+
+exp=ksh
+got=$(print -r $'#00315
+COATTRIBUTES=\'label=make \'
+# @(#)$Id: libcoshell (AT&T Research) 2008-04-28 $
+_COSHELL_msgfd=5
+{ { (eval \'function fun { trap \":\" 0; return 1; }; trap \"exit 0\" 0; fun; exit 1\') && PATH= print -u$_COSHELL_msgfd ksh; } || { times && echo bsh >&$_COSHELL_msgfd; } || { echo osh >&$_COSHELL_msgfd; }; } >/dev/null 2>&1' | $SHELL 5>&1)
+[[ $got == $exp ]] || err_exit "coshell(3) identification sequence failed -- expected '$exp', got '$got'"
+
+function cop
+{
+ read
+ print ok
+}
+
+exp=ok
+
+cop |&
+pid=$!
+if print -p yo 2>/dev/null
+then read -p got
+else got='no coprocess'
+fi
+[[ $got == $exp ]] || err_exit "main coprocess main query failed -- expected $exp, got '$got'"
+kill $pid 2>/dev/null
+wait
+
+cop |&
+pid=$!
+(
+if print -p yo 2>/dev/null
+then read -p got
+else got='no coprocess'
+fi
+[[ $got == $exp ]] || err_exit "main coprocess subshell query failed -- expected $exp, got '$got'"
+)
+kill $pid 2>/dev/null
+wait
+
+exp='no coprocess'
+
+(
+cop |&
+print $! > $tmp/pid
+)
+pid=$(<$tmp/pid)
+if print -p yo 2>/dev/null
+then read -p got
+else got=$exp
+fi
+[[ $got == $exp ]] || err_exit "subshell coprocess main query failed -- expected $exp, got '$got'"
+kill $pid 2>/dev/null
+wait
+
+(
+cop |&
+print $! > $tmp/pid
+)
+pid=$(<$tmp/pid)
+(
+if print -p yo 2>/dev/null
+then read -p got
+else got=$exp
+fi
+[[ $got == $exp ]] || err_exit "subshell coprocess subshell query failed -- expected $exp, got '$got'"
+kill $pid 2>/dev/null
+wait
+)
+
+function mypipe
+{
+ read; read
+ print -r -- "$REPLY"
+}
+
+mypipe |&
+print -p "hello"
+z="$( $bintrue $($bintrue) )"
+{ print -p "world";} 2> /dev/null
+read -p
+[[ $REPLY == world ]] || err_exit "expected 'world' got '$REPLY'"
+kill $pid 2>/dev/null
+wait
+
+
+function cop
+{
+ read
+ print ok
+}
+exp=ok
+cop |&
+pid=$!
+(
+if print -p yo 2>/dev/null
+then read -p got
+else got='no coprocess'
+fi
+[[ $got == $exp ]] || err_exit "main coprocess subshell query failed -- expected $exp, got '$got'"
+)
+kill $pid 2>/dev/null
+wait
+
+tee=$(whence -p tee)
+ls -l |&
+pid=$!
+$tee -a /dev/null <&p > /dev/null
+wait $pid
+x=$?
+[[ $x == 0 ]] || err_exit "coprocess exitval should be 0, not $x"
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/cubetype.sh b/src/cmd/ksh93/tests/cubetype.sh
new file mode 100755
index 0000000..dbe4e8b
--- /dev/null
+++ b/src/cmd/ksh93/tests/cubetype.sh
@@ -0,0 +1,213 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+integer n=2
+
+typeset -T Box_t=(
+ float -h 'height in inches' x=2
+ float -h 'width in inches' y=4
+ comvar=(top=8 bottom=9)
+ integer -S count=0
+ items=(foo bar)
+ colors=([wall]=blue [floor]=red)
+ typeset name=unknown
+ typeset -L6 status=INIT
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y)))
+ (( _.count++))
+ }
+ typeset -fh 'distance from the origin' len
+ depth()
+ {
+ print 0
+ }
+ float x=3
+)
+
+for ((i=0; i < n; i++))
+do
+Box_t b=(name=box1)
+exp=3 got=${b.x}
+[[ "$got" == "$exp" ]] || err_exit "\${b.x} incorrect for iteration $i -- expected $exp, got '$got'"
+exp=5 got=$(( b.len ))
+(( got == exp )) || err_exit "b.len incorrect for iteration $i -- expected $exp, got '$got = sqrt(${b.x}*${b.x}+${b.y}*${b.y})'"
+exp=5 got=${b.len}
+[[ "$got" == "$exp" ]] || err_exit "\${b.len} incorrect for iteration $i -- expected $exp, got '$got = sqrt(${b.x}*${b.x}+${b.y}*${b.y})'"
+exp=box1 got=${b.name}
+[[ "$got" == "${exp}" ]] || err_exit "\${b.name} incorrect for iteration $i -- expected $exp, got '$got'"
+exp=2 got=$(( b.count ))
+(( got == exp )) || err_exit "b.count incorrect for iteration $i -- expected $exp, got '$got'"
+exp=2 got=${b.count}
+[[ "$got" == "$exp" ]] || err_exit "\${b.ccount} incorrect for iteration $i -- expected $exp, got '$got'"
+b.colors[wall]=green
+b.colors[door]=white
+exp=3 got=${#b.colors[@]}
+[[ "$got" == "$exp" ]] || err_exit "\${#b.colors[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+b.comvar.bottom=11
+b.items[1]=bam
+b.items[2]=extra
+exp=3 got=${#b.items[@]}
+[[ ${#b.items[@]} == 3 ]] || err_exit "\${#b.items[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+Box_t bb=b
+bb.colors[desk]=orange
+exp=4 got=${#b.colors[@]}
+[[ ${#bb.colors[@]} == 4 ]] || err_exit "\${#bb.colors[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+unset b.colors
+exp=2 got=${#b.colors[@]}
+[[ ${#b.colors[@]} == 2 ]] || err_exit "\${#b.colors[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+unset b.items
+exp=2 got=${#b.items[@]}
+[[ ${#b.items[@]} == 2 ]] || err_exit "\${#b.items[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+unset bb.colors
+exp=2 got=${#bb.colors[@]}
+[[ ${#bb.colors[@]} == 2 ]] || err_exit "\${#bb.colors[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+unset bb.items
+exp=2 got=${#bb.items[@]}
+[[ ${#bb.items[@]} == 2 ]] || err_exit "\${#bb.items[@]} incorrect for iteration $i -- expected $exp, got '$got'"
+[[ $b == "$bb" ]] || err_exit "\$b='$b' != \$bb='$bb'"
+b.count=0
+unset b bb
+done
+
+typeset -T Cube_t=(
+ Box_t _=(y=5)
+ float z=1
+ depth()
+ {
+ print -r -- $((_.z))
+ }
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y + _.z*_.z)))
+ (( _.count++))
+ }
+ float x=8
+ fun()
+ {
+ print 'hello world'
+ }
+)
+
+
+for ((i=0; i < n; i++))
+do
+Box_t b=(name=box2)
+[[ ${b.name} == box2 ]] || err_exit "\${b.name} incorrect -- expected box2, got '${b.name}'"
+(( b.len == 5 )) || err_exit "b.len incorrect for box2 -- expected 5, got '$(( b.len ))'"
+(( b.count == 1 )) || err_exit "b.count incorrect -- expected 1, got '$(( b.count ))'"
+Cube_t c=(name=cube1)
+[[ $c == $'(\n\ttypeset -l -E x=8\n\ttypeset -l -E y=5\n\tcomvar=(\n\t\ttop=8\n\t\tbottom=9\n\t)\n\ttypeset -S -l -i count=1\n\ttypeset -a items=(\n\t\tfoo\n\t\tbar\n\t)\n\ttypeset -A colors=(\n\t\t[floor]=red\n\t\t[wall]=blue\n\t)\n\tname=cube1\n\ttypeset -L 6 status=INIT\n\ttypeset -l -E z=1\n)' ]] || err_exit '$c not correct'
+[[ ${c.x} == 8 ]] || err_exit '${c.x} != 8'
+[[ ${c.depth} == 1 ]] || err_exit '${c.depth} != 1'
+[[ ${c.name} == cube1 ]] || err_exit '${c.name} != cube1 '
+[[ $(c.fun) == 'hello world' ]] || err_exit '$(c.fun) != "hello world"'
+[[ ${c.fun} == 'hello world' ]] || err_exit '${c.fun} != "hello world"'
+(( abs(c.len - sqrt(90)) < 1e-10 )) || err_exit 'c.len != sqrt(90)'
+(( c.count == 2 )) || err_exit 'c.count != 2'
+(( c.count == b.count )) || err_exit 'c.count != b.count'
+c.count=0
+Cube_t d=c
+[[ $d == "$c" ]] || err_exit '$d != $c'
+eval "Cube_t zzz=$c"
+[[ $zzz == "$c" ]] || err_exit '$zzz != $c'
+Cube_t zzz=c
+[[ $zzz == "$c" ]] || err_exit '$zzz != $c without eval'
+xxx=$(typeset -p c)
+eval "${xxx/c=/ccc=}"
+[[ $ccc == "$c" ]] || err_exit '$ccc != $c'
+unset b c d zzz xxx ccc
+done
+for ((i=0; i < n; i++))
+do
+Cube_t cc
+cc[2]=(x=2 y=3 name=two colors+=([table]=white) items+=(pencil) z=6)
+[[ ${cc[0].x} == 8 ]] || err_exit 'cc[0].x !=8'
+[[ ${cc[2].y} == 3 ]] || err_exit '${cc[2].y} != 3'
+(( cc[2].y == 3 )) || err_exit '(( cc[2].y != 3))'
+[[ ${cc[2].colors[table]} == white ]] || err_exit '${cc[2].colors[table]} != white'
+[[ ${cc[2].items[2]} == pencil ]] || err_exit '${cc[2].items[2]} != pencil'
+(( cc[2].len == 7 )) || err_exit '(( cc[2].len != 7 ))'
+[[ $(cc[2].len) == 7 ]] || err_exit '$(cc[2].len) != 7 ))'
+[[ ${cc[2].len} == 7 ]] || err_exit '${cc[2].len} != 7 ))'
+(( cc[2].count == 2 )) || err_exit 'cc[2].count != 2'
+unset cc[2].x cc[2].y cc[2].z
+(( cc[2].len == cc[0].len )) || err_exit 'cc[2].len != cc[0].len'
+(( cc[2].len == cc.len )) || err_exit 'cc[2].len != cc.len'
+(( cc[2].count == 6 )) || err_exit 'cc[2].count != 6'
+unset cc[2].name cc[2].colors cc[2].items
+[[ $cc == "${cc[2]}" ]] || err_exit '$cc != ${cc[2]}'
+cc.count=0
+unset cc
+Cube_t -A cc
+cc[two]=(x=2 y=3 name=two colors+=([table]=white) items+=(pencil) z=6)
+Cube_t cc[one]
+[[ ${#cc[@]} == 2 ]] || err_exit '${#cc[@]} != 2'
+[[ ${cc[two].y} == 3 ]] || err_exit '${cc[two].y} != 3'
+(( cc[two].y == 3 )) || err_exit '(( cc[two].y != 3))'
+[[ ${cc[two].colors[table]} == white ]] || err_exit '${cc[two].colors[table]} != white'
+[[ ${cc[two].items[2]} == pencil ]] || err_exit '${cc[two].items[2]} != pencil'
+(( cc[two].len == 7 )) || err_exit '(( cc[two].len != 7 ))'
+[[ $(cc[two].len) == 7 ]] || err_exit '$(cc[two].len) != 7 ))'
+[[ ${cc[two].len} == 7 ]] || err_exit '${cc[two].len} != 7 ))'
+(( cc[two].count == 2 )) || err_exit 'cc[two].count != 2'
+unset cc[two].x cc[two].y cc[two].z
+(( cc[two].len == cc[one].len )) || err_exit 'cc[two].len != cc[one].len'
+(( cc[two].count == 4 )) || err_exit 'cc[two].count != 4'
+unset cc[two].name unset cc[two].colors cc[two].items
+[[ ${cc[one]} == "${cc[two]}" ]] || err_exit '${cc[one]} != ${cc[two]}'
+cc[two].count=0
+unset cc
+Cube_t cc=(
+ [one]=
+ [two]=(x=2 y=3 name=two colors+=([table]=white) z=6)
+)
+[[ ${#cc[@]} == 2 ]] || err_exit '${#cc[@]} != 2'
+[[ ${cc[two].y} == 3 ]] || err_exit '${cc[two].y} != 3'
+(( cc[two].y == 3 )) || err_exit '(( cc[two].y != 3))'
+[[ ${cc[two].colors[table]} == white ]] || err_exit '${cc[two].colors[table]} != white'
+(( cc[two].len == 7 )) || err_exit '(( cc[two].len != 7 ))'
+[[ $(cc[two].len) == 7 ]] || err_exit '$(cc[two].len) != 7 ))'
+[[ ${cc[two].len} == 7 ]] || err_exit '${cc[two].len} != 7 ))'
+(( cc[two].count == 2 )) || err_exit 'cc[two].count != 2'
+unset cc[two].x cc[two].y cc[two].z
+(( cc[two].len == cc[one].len )) || err_exit 'cc[two].len != cc[one].len'
+(( cc[two].count == 4 )) || err_exit 'cc[two].count != 4'
+cc[three]=cc[two]
+[[ ${cc[two]} == "${cc[three]}" ]] || err_exit "\${cc[two]}='${cc[two]}' != \${cc[three]}='${cc[three]}'"
+[[ $cc[two] == "${cc[three]}" ]] || err_exit "\$cc[two]='${cc[two]}' != \${cc[three]}='${cc[three]}'"
+exp=3
+got=${#cc[@]}
+[[ $got == $exp ]] || err_exit "\${#cc[@]} failed -- expected '$exp', got '$got'"
+unset cc[two].name unset cc[two].colors
+cc[two].count=0
+unset cc
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/enum.sh b/src/cmd/ksh93/tests/enum.sh
new file mode 100755
index 0000000..134a0a3
--- /dev/null
+++ b/src/cmd/ksh93/tests/enum.sh
@@ -0,0 +1,68 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+enum Color_t=(red green blue orange yellow)
+enum -i Sex_t=(Male Female)
+for ((i=0; i < 1000; i++))
+do
+Color_t x
+[[ $x == red ]] || err_exit 'Color_t does not default to red'
+x=orange
+[[ $x == orange ]] || err_exit '$x should be orange'
+( x=violet) 2> /dev/null && err_exit 'x=violet should fail'
+x[2]=green
+[[ ${x[2]} == green ]] || err_exit '${x[2]} should be green'
+(( x[2] == 1 )) || err_exit '((x[2]!=1))'
+[[ $((x[2])) == 1 ]] || err_exit '$((x[2]))!=1'
+[[ $x == orange ]] || err_exit '$x is no longer orange'
+Color_t -A y
+y[foo]=yellow
+[[ ${y[foo]} == yellow ]] || err_exit '${y[foo]} != yellow'
+(( y[foo] == 4 )) || err_exit '(( y[foo] != 4))'
+unset y
+typeset -a [Color_t] z
+z[green]=xyz
+[[ ${z[green]} == xyz ]] || err_exit '${z[green]} should be xyz'
+[[ ${z[1]} == xyz ]] || err_exit '${z[1]} should be xyz'
+z[orange]=bam
+[[ ${!z[@]} == 'green orange' ]] || err_exit '${!z[@]} == "green orange"'
+unset x
+Sex_t x
+[[ $x == Male ]] || err_exit 'Sex_t not defaulting to Male'
+x=female
+[[ $x == Female ]] || err_exit 'Sex_t not case sensitive'
+unset x y z
+done
+(
+typeset -T X_t=( typeset name=aha )
+typeset -a[X_t] arr
+) 2> /dev/null
+[[ $? == 1 ]] || err_exit 'typeset -a[X_t] should generate an error message when X-t is not an enumeriation type'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/exit.sh b/src/cmd/ksh93/tests/exit.sh
new file mode 100755
index 0000000..d2b91b7
--- /dev/null
+++ b/src/cmd/ksh93/tests/exit.sh
@@ -0,0 +1,80 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function abspath
+{
+ base=$(basename $SHELL)
+ cd ${SHELL%/$base}
+ newdir=$(pwd)
+ cd ~-
+ print $newdir/$base
+}
+#test for proper exit of shell
+builtin getconf
+ABSHELL=$(abspath)
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+print exit 0 >.profile
+${ABSHELL} <<!
+HOME=$PWD \
+PATH=$PATH \
+SHELL=$ABSSHELL \
+$(
+ v=$(getconf LIBPATH)
+ for v in ${v//,/ }
+ do v=${v#*:}
+ v=${v%%:*}
+ eval [[ \$$v ]] && eval print -n \" \"\$v=\"\$$v\"
+ done
+) \
+exec -c -a -ksh ${ABSHELL} -c "exit 1" 1>/dev/null 2>&1
+!
+status=$(echo $?)
+if [[ -o noprivileged && $status != 0 ]]
+then err_exit 'exit in .profile is ignored'
+elif [[ -o privileged && $status == 0 ]]
+then err_exit 'privileged .profile not ignored'
+fi
+if [[ $(trap 'code=$?; echo $code; trap 0; exit $code' 0; exit 123) != 123 ]]
+then err_exit 'exit not setting $?'
+fi
+cat > run.sh <<- "EOF"
+ trap 'code=$?; echo $code; trap 0; exit $code' 0
+ ( trap 0; exit 123 )
+EOF
+if [[ $($SHELL ./run.sh) != 123 ]]
+then err_exit 'subshell trap on exit overwrites parent trap'
+fi
+cd ~- || err_exit "cd back failed"
+$SHELL -c 'builtin -f cmd getconf; getconf --"?-version"; exit 0' >/dev/null 2>&1 || err_exit 'ksh plugin exit failed -- was ksh built with CCFLAGS+=$(CC.EXPORT.DYNAMIC)?'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/expand.sh b/src/cmd/ksh93/tests/expand.sh
new file mode 100755
index 0000000..2547be8
--- /dev/null
+++ b/src/cmd/ksh93/tests/expand.sh
@@ -0,0 +1,126 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$Line]: "$@"
+ ((Errors++))
+}
+
+integer Errors=0
+Command=${0##*/}
+
+# {...} expansion tests -- ignore if not supported
+
+[[ $(print a{0,1}z) == "a0z a1z" ]] || exit 0
+
+integer Line=$LINENO+1
+set -- \
+ 'ff{c,b,a}' 'ffc ffb ffa' \
+ 'f{d,e,f}g' 'fdg feg ffg' \
+ '{l,n,m}xyz' 'lxyz nxyz mxyz' \
+ '{abc\,def}' '{abc,def}' \
+ '{"abc,def"}' '{abc,def}' \
+ "{'abc,def'}" '{abc,def}' \
+ '{abc}' '{abc}' \
+ '\{a,b,c,d,e}' '{a,b,c,d,e}' \
+ '{x,y,\{a,b,c}}' 'x} y} {a} b} c}' \
+ '{x\,y,\{abc\},trie}' 'x,y {abc} trie' \
+ '/usr/{ucb/{ex,edit},lib/{ex,how_ex}}' '/usr/ucb/ex /usr/ucb/edit /usr/lib/ex /usr/lib/how_ex' \
+ 'XXXX\{a,b,c\}' 'XXXX{a,b,c}' \
+ '{}' '{}' \
+ '{ }' '{ }' \
+ '}' '}' \
+ '{' '{' \
+ 'abcd{efgh' 'abcd{efgh' \
+ 'foo {1,2} bar' 'foo 1 2 bar' \
+ '`print -r -- foo {1,2} bar`' 'foo 1 2 bar' \
+ '$(print -r -- foo {1,2} bar)' 'foo 1 2 bar' \
+ '{1..10}' '1 2 3 4 5 6 7 8 9 10' \
+ '{0..10,braces}' '0..10 braces' \
+ '{{0..10},braces}' '0 1 2 3 4 5 6 7 8 9 10 braces' \
+ 'x{{0..10},braces}y' 'x0y x1y x2y x3y x4y x5y x6y x7y x8y x9y x10y xbracesy' \
+ '{3..3}' '3' \
+ 'x{3..3}y' 'x3y' \
+ '{10..1}' '10 9 8 7 6 5 4 3 2 1' \
+ '{10..1}y' '10y 9y 8y 7y 6y 5y 4y 3y 2y 1y' \
+ 'x{10..1}y' 'x10y x9y x8y x7y x6y x5y x4y x3y x2y x1y' \
+ '{a..f}' 'a b c d e f' \
+ '{f..a}' 'f e d c b a' \
+ '{a..A}' '{a..A}' \
+ '{A..a}' '{A..a}' \
+ '{f..f}' 'f' \
+ '{1..f}' '{1..f}' \
+ '{f..1}' '{f..1}' \
+ '0{1..9} {10..20}' '01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20' \
+ '{-1..-10}' '-1 -2 -3 -4 -5 -6 -7 -8 -9 -10' \
+ '{-19..0}' '-19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0' \
+ '{0..10}' '0 1 2 3 4 5 6 7 8 9 10' \
+ '{0..10..1}' '0 1 2 3 4 5 6 7 8 9 10' \
+ '{0..10..2}' '0 2 4 6 8 10' \
+ '{0..10..3}' '0 3 6 9' \
+ '{0..10..0}' '{0..10..0}' \
+ '{0..10..-1}' '0' \
+ '{10..0}' '10 9 8 7 6 5 4 3 2 1 0' \
+ '{10..0..-1}' '10 9 8 7 6 5 4 3 2 1 0' \
+ '{10..0..-2}' '10 8 6 4 2 0' \
+ '{10..0..-3}' '10 7 4 1' \
+ '{10..0..0}' '{10..0..0}' \
+ '{10..0..1}' '10' \
+ '{a..z..2}' 'a c e g i k m o q s u w y' \
+ '{y..b..-3}' 'y v s p m j g d' \
+ '{0..0x1000..0x200}' '0 512 1024 1536 2048 2560 3072 3584 4096' \
+ '{a,b}{0..2}{z,y}' 'a0z a0y a1z a1y a2z a2y b0z b0y b1z b1y b2z b2y' \
+ '{0..0100..8%03o}' '000 010 020 030 040 050 060 070 100' \
+ '{0..0100..040%020o}' '00000000000000000000 00000000000000000040 00000000000000000100' \
+ '{0..7%03..2u}' '000 001 010 011 100 101 110 111' \
+ '{0..10%llu}' '{0..10%llu}' \
+ '{0..10%s}' '{0..10%s}' \
+ '{0..10%dl}' '{0..10%dl}' \
+ '{a,b}{0..3%02..2u}{y,z}' 'a00y a00z a01y a01z a10y a10z a11y a11z b00y b00z b01y b01z b10y b10z b11y b11z' \
+
+while (($#>1))
+do ((Line++))
+ pattern=$1
+ shift
+ expected=$1
+ shift
+ got=$(eval print -r -- "$pattern")
+ [[ $got == $expected ]] || err_exit "'$pattern' failed -- expected '$expected' got '$got'"
+ #print -r -- " '$pattern' '$got' \\"
+done
+
+# ~(N) no expand glob pattern option
+set -- ~(N)/dev/null
+[[ $# == 1 && $1 == /dev/null ]] || err_exit "~(N)/dev/null not matching /dev/null"
+set -- ~(N)/dev/non_existant_file
+[[ $# == 0 ]] || err_exit "~(N)/dev/nonexistant not empty"
+set -- ""~(N)/dev/non_existant_file
+[[ $# == 1 && ! $1 ]] || err_exit '""~(N)/dev/nonexistant not null argument'
+set -- ~(N)/dev/non_existant_file""
+[[ $# == 1 && ! $1 ]] || err_exit '~(N)/dev/nonexistent"" not null argument'
+for i in ~(N)/dev/non_existent_file
+do err_exit "~(N)/dev/non_existent_file in for loop is $i"
+done
+for i in ""~(N)/dev/non_existent_file
+do [[ ! $i ]] || err_exit '""~(N)/dev/non_existent_file not null'
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/functions.sh b/src/cmd/ksh93/tests/functions.sh
new file mode 100755
index 0000000..fcf3755
--- /dev/null
+++ b/src/cmd/ksh93/tests/functions.sh
@@ -0,0 +1,1157 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+integer Errors=0
+Command=${0##*/}
+
+ulimit -c 0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+integer foo=33
+bar=bye
+# check for global variables and $0
+function foobar
+{
+ case $1 in
+ 1) print -r - "$foo" "$bar";;
+ 2) print -r - "$0";;
+ 3) typeset foo=foo
+ integer bar=10
+ print -r - "$foo" "$bar";;
+ 4) trap 'foo=36' EXIT
+ typeset foo=20;;
+ esac
+}
+function print
+{
+ command print hi
+}
+if [[ $(print) != hi ]]
+then err_exit "command print not working inside print function"
+fi
+unset -f print
+
+if [[ $(foobar 1) != '33 bye' ]]
+then err_exit 'global variables not correct'
+fi
+
+if [[ $(foobar 2) != 'foobar' ]]
+then err_exit '$0 not correct'
+fi
+
+if [[ $(bar=foo foobar 1) != '33 foo' ]]
+then err_exit 'environment override not correct'
+fi
+if [[ $bar == foo ]]
+then err_exit 'scoping error'
+fi
+
+if [[ $(foobar 3) != 'foo 10' ]]
+then err_exit non-local variables
+fi
+
+foobar 4
+if [[ $foo != 36 ]]
+then err_exit EXIT trap in wrong scope
+fi
+unset -f foobar || err_exit "cannot unset function foobar"
+typeset -f foobar>/dev/null && err_exit "typeset -f has incorrect exit status"
+
+function foobar
+{
+ (return 0)
+}
+> $tmp/test1
+{
+foobar
+if [ -r $tmp/test1 ]
+then rm -r $tmp/test1
+else err_exit 'return within subshell inside function error'
+fi
+}
+abc() print hi
+if [[ $(abc) != hi ]]
+then err_exit 'abc() print hi not working'
+fi
+( unset -f abc )
+if [[ $(abc 2>/dev/null) != hi ]]
+then err_exit 'abc() print hi not working after subshell unset'
+fi
+(
+ function f
+ {
+ exit 1
+ }
+ f
+ err_exit 'exit from function not working'
+)
+unset -f foo
+function foo
+{
+ x=2
+ (
+ x=3
+ cd $tmp
+ print bar
+ )
+ if [[ $x != 2 ]]
+ then err_exit 'value of x not restored after subshell inside function'
+ fi
+}
+x=1
+dir=$PWD
+if [[ $(foo) != bar ]]
+then err_exit 'cd inside nested subshell not working'
+fi
+if [[ $PWD != "$dir" ]]
+then err_exit 'cd inside nested subshell changes $PWD'
+fi
+fun() /bin/echo hello
+if [[ $(fun) != hello ]]
+then err_exit one line functions not working
+fi
+cat > $tmp/script <<-\!
+ print -r -- "$1"
+!
+chmod +x $tmp/script
+function passargs
+{
+ $tmp/script "$@"
+}
+if [[ $(passargs one) != one ]]
+then err_exit 'passing args from functions to scripts not working'
+fi
+cat > $tmp/script <<-\!
+ trap 'exit 0' EXIT
+ function foo
+ {
+ /tmp > /dev/null 2>&1
+ }
+ foo
+!
+if ! $tmp/script
+then err_exit 'exit trap incorrectly triggered'
+fi
+if ! $SHELL -c $tmp/script
+then err_exit 'exit trap incorrectly triggered when invoked with -c'
+fi
+$SHELL -c "trap 'rm $tmp/script' EXIT"
+if [[ -f $tmp/script ]]
+then err_exit 'exit trap not triggered when invoked with -c'
+fi
+cat > $tmp/script <<- \EOF
+ foobar()
+ {
+ return
+ }
+ shift
+ foobar
+ print -r -- "$1"
+EOF
+chmod +x $tmp/script
+if [[ $( $SHELL $tmp/script arg1 arg2) != arg2 ]]
+then err_exit 'arguments not restored by posix functions'
+fi
+function foo
+{
+ print hello
+}
+(
+ function foo
+ {
+ print bar
+ }
+ if [[ $(foo) != bar ]]
+ then err_exit 'function definitions inside subshells not working'
+ fi
+)
+if [[ $(foo) != hello ]]
+then err_exit 'function definitions inside subshells not restored'
+fi
+unset -f foo bar
+function bar
+{
+ print "$y"
+}
+
+function foo
+{
+ typeset x=3
+ y=$x bar
+}
+x=1
+if [[ $(foo) != 3 ]]
+then err_exit 'variable assignment list not using parent scope'
+fi
+unset -f foobar
+cat > $tmp/foobar <<!
+function foobar
+{
+ print foo
+}
+!
+chmod +x $tmp/foobar
+FPATH=$tmp
+autoload foobar
+if [[ $(foobar 2>/dev/null) != foo ]]
+then err_exit 'autoload not working'
+fi
+unset -f foobar
+function foobar
+{
+ typeset -r x=3
+ return 0
+}
+( foobar ) 2> /dev/null || err_exit "cannot unset readonly variable in function"
+if $SHELL -n 2> /dev/null <<-!
+ abc()
+ !
+then err_exit 'abc() without a function body is not a syntax error'
+fi
+function winpath
+{
+ usage='q pathname ...'
+ typeset var format=s
+ while getopts "$usage" var
+ do case $var in
+ q) format=q;;
+ esac
+ done
+ print done
+}
+if [[ $( (winpath --man 2>/dev/null); print ok) != ok ]]
+then err_exit 'getopts --man in functions not working'
+fi
+if [[ $( (winpath -z 2>/dev/null); print ok) != ok ]]
+then err_exit 'getopts with bad option in functions not working'
+fi
+unset -f x
+function x
+{
+ print "$@"
+}
+typeset -ft x
+if [[ $(x x=y 2>/dev/null) != x=y ]]
+then err_exit 'name=value pair args not passed to traced functions'
+fi
+function bad
+{
+ false
+}
+trap 'val=false' ERR
+val=true
+bad
+if [[ $val != false ]]
+then err_exit 'set -e not working for functions'
+fi
+function bad
+{
+ false
+ return 0
+}
+val=true
+bad
+if [[ $val != true ]]
+then err_exit 'set -e not disabled for functions'
+fi
+bad()
+{
+ false
+ return 0
+}
+val=true
+bad
+if [[ $val != false ]]
+then err_exit 'set -e not inherited for posix functions'
+fi
+trap - ERR
+
+function myexport
+{
+ nameref var=$1
+ if (( $# > 1 ))
+ then export $1=$2
+ fi
+ if (( $# > 2 ))
+ then print $(myexport "$1" "$3" )
+ return
+ fi
+ typeset val
+ val=$(export | grep "^$1=")
+ print ${val#"$1="}
+}
+export dgk=base
+val=$(myexport dgk fun)
+if [[ $val != fun ]]
+then err_exit "export inside function not working -- expected 'fun', got '$val'"
+fi
+val=$(export | sed -e '/^dgk=/!d' -e 's/^dgk=//')
+if [[ $val != base ]]
+then err_exit "export not restored after function call -- expected 'base', got '$val'"
+fi
+val=$(myexport dgk fun fun2)
+if [[ $val != fun2 ]]
+then err_exit "export inside function not working with recursive function -- expected 'fun2', got '$val'"
+fi
+val=$(export | sed -e '/^dgk=/!d' -e 's/^dgk=//')
+if [[ $val != base ]]
+then err_exit "export not restored after recursive function call -- expected 'base', got '$val'"
+fi
+val=$(dgk=try3 myexport dgk)
+if [[ $val != try3 ]]
+then err_exit "name=value not added to export list with function call -- expected 'try3', got '$val'"
+fi
+val=$(export | sed -e '/^dgk=/!d' -e 's/^dgk=//')
+if [[ $val != base ]]
+then err_exit "export not restored name=value function call -- expected 'base', got '$val'"
+fi
+unset zzz
+val=$(myexport zzz fun)
+if [[ $val != fun ]]
+then err_exit "export inside function not working -- expected 'fun', got '$val'"
+fi
+val=$(export | sed -e '/^zzz=/!d' -e 's/^zzz=//')
+if [[ $val ]]
+then err_exit "unset varaible exported after function call -- expected '', got '$val'"
+fi
+
+unset zzz
+typeset -u zzz
+function foo
+{
+ zzz=abc
+ print $zzz
+}
+if [[ $(foo)$(foo) != ABCABC ]]
+then err_exit 'attributes on unset variables not saved/restored'
+fi
+function xpd {
+ typeset i j=$1
+ for i
+ do print i=$i j=$j
+ [[ $i == a ]] && xpd b
+ done
+ }
+if [[ $(xpd a c) != $'i=a j=a\ni=b j=b\ni=c j=a' ]]
+then err_exit 'for loop function optimization error'
+fi
+
+typeset -A visited
+integer level=0
+function closure
+{
+ (( $# > 5 )) && return 1
+ ((level < 2)) && ((level++))
+ typeset tmp r=0
+ visited[$1]=1
+
+ for tmp in $level _$level
+ do
+ [[ ${visited[$tmp]} == 1 ]] && continue
+ closure $tmp $* || r=1
+ done
+ return $r
+}
+closure 0 || err_exit -u2 'for loop function optimization bug2'
+dir=$tmp/dir
+mkdir $dir
+cd $dir || { err_exit "cd $dir failed"; exit 1; }
+
+(
+ function a {
+ print a
+ }
+ function b {
+ print 1
+ a
+ print 2
+ } > /dev/null
+ typeset -ft a b
+ PS4=X
+ b
+) > file 2>&1
+[[ $(<file) == *'Xprint 2'* ]] || err_exit 'function trace disabled by function call'
+rm -f file
+
+print 'false' > try
+chmod +x try
+cat > tst <<- EOF
+ function ignore
+ {
+ ./try
+ return 0
+ }
+ trap "print error; exit 1" ERR
+ ignore
+EOF
+if [[ $($SHELL < tst) == error ]]
+then err_exit 'ERR trap not cleared'
+fi
+FPATH=$dir
+print ': This does nothing' > foobar
+chmod +x foobar
+unset -f foobar
+{ foobar; } 2>/dev/null
+got=$?
+exp=126
+if [[ $got != $exp ]]
+then err_exit "function file without function definition processes wrong error -- expected '$exp', got '$got'"
+fi
+print 'set a b c' > dotscript
+[[ $(PATH=$PATH: $SHELL -c '. dotscript;print $#') == 3 ]] || err_exit 'positional parameters not preserved with . script without arguments'
+cd ~- || err_exit "cd back failed"
+function errcheck
+{
+ trap 'print ERR; return 1' ERR
+ false
+ print ok
+}
+err=$(errcheck)
+[[ $err == ERR ]] || err_exit 'trap on ERR not working in a function'
+x="$(
+ function foobar
+ {
+ print ok
+ }
+ typeset -f foobar
+)"
+eval "$x" || err_exit 'typeset -f generates syntax error'
+[[ $(foobar) != ok ]] && err_exit 'typeset -f not generating function'
+unset -f a b c
+a()
+{
+ b
+ b
+ print ${.sh.fun}
+}
+b() { : ;}
+[[ $(a) == a ]] || err_exit '.sh.fun not set correctly in a function'
+print $'a(){\ndate\n}' | $SHELL 2> /dev/null || err_exit 'parser error in a(){;date;}'
+cat > $tmp/data1 << '++EOF'
+ 1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 3 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 4 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 8 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 12 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 13 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 14 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 15 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 16 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 17 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 18 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 19 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ 20 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+++EOF
+cat > $tmp/script << '++EOF'
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+f()
+{
+cat <<\M
+++EOF
+cat $tmp/data1 >> $tmp/script
+printf 'M\n}\n\nf\n\n' >> $tmp/script
+$SHELL -c $tmp/script > $tmp/data2
+cmp -s $tmp/data[12] || err_exit 'error with long functions'
+v=1
+function f
+{
+ typeset i
+ for i in 0 1
+ do typeset v
+ v=$i
+ [[ $v == $i ]] || return 1
+ done
+}
+f || err_exit "typeset optimization bug"
+function f
+{
+ print -r -- "$foo$bar"
+}
+function g
+{
+ print -r -- $(bar=bam f)
+}
+unset foo bar
+[[ $(foo=hello g) == hellobam ]] || err_exit 'function exports not passed on'
+[[ $(bar=hello g) == bam ]] || err_exit 'function exports not overridden'
+unset -f foo
+function foo
+{
+ typeset line=$1
+ set +n
+ while [[ $line ]]
+ do if [[ ! $varname ]]
+ then varname=${line%% *}
+ line=${line##"$varname"?( )}
+ [[ $line ]] && continue
+ else print ok
+ return
+ fi
+ varname=
+ done
+}
+[[ $(foo 'NUMBERED RECORDSIZE') == ok ]] || err_exit 'optimization error with undefined variable'
+unset x
+x=$(
+ set -e
+ integer count=0
+ function err_f
+ {
+ if ((count++==3))
+ then print failed
+ else false
+ fi
+ }
+ trap 'err_f' ERR
+ false
+)
+[[ $x == failed ]] && err_exit 'ERR trap executed multiple times'
+export environment
+typeset global
+function f
+{
+ typeset i t local
+
+ for i
+ do case $i in
+ [-+]*) set "$@"
+ continue
+ ;;
+ local) local=f
+ t=$(typeset +f $local)
+ ;;
+ global) global=f
+ t=$(typeset +f $global)
+ ;;
+ environment)
+ environment=f
+ t=$(typeset +f $environment)
+ ;;
+ literal)t=$(typeset +f f)
+ ;;
+ positional)
+ set -- f
+ t=$(typeset +f $1)
+ ;;
+ esac
+ [[ $t ]] || err_exit "typeset +f \$$i failed"
+ done
+}
+f local global environment literal positional
+$SHELL -c '
+ print exit 0 > '$tmp'/script
+ chmod +x '$tmp'/script
+ unset var
+ var=( ident=1 )
+ function fun
+ {
+ PATH='$tmp' script
+ }
+ fun
+' || err_exit "compound variable cleanup before script exec failed"
+( $SHELL << \++EOF++
+function main
+{
+ typeset key
+ typeset -A entry
+ entry[a]=( value=aaa )
+}
+main
+++EOF++
+) 2> /dev/null || err_exit 'function main fails'
+optind=$OPTIND
+sub()
+{
+ (
+ OPTIND=1
+ while getopts :abc OPTION "$@"
+ do print OPTIND=$OPTIND
+ done
+ )
+}
+[[ $(sub -a) == OPTIND=2 ]] || err_exit 'OPTIND should be 2'
+[[ $(sub -a) == OPTIND=2 ]] || err_exit 'OPTIND should be 2 again'
+[[ $OPTIND == "$optind" ]] || err_exit 'OPTIND should be 1'
+
+function bar
+{
+ [[ -o nounset ]] && err_exit 'nounset option should not be inherited'
+}
+function foo
+{
+ set -o nounset
+ bar
+}
+set +o nounset
+foo
+function red
+{
+ integer -S d=0
+ printf 'red_one %d\n' d
+ (( d++ ))
+ return 0
+}
+[[ ${ red } != 'red_one 0' ]] && err_exit 'expected red_one 0'
+[[ ${ red } != 'red_one 1' ]] && err_exit 'expected red_one 1'
+xyz=$0
+function traceback
+{
+ integer .level=.sh.level
+ while((--.level>=0))
+ do
+ ((.sh.level = .level))
+ [[ $xyz == "$0" ]] || err_exit "\$xyz=$xyz does not match $0 on level ${.level}"
+ [[ ${.sh.lineno} == "$1" ]] || err_exit "\${.sh.lineno}=${.sh.lineno} does not match $1 on level ${.level}"
+ done
+}
+
+function foo
+{
+ typeset xyz=foo
+ set -- $((LINENO+1))
+ bar $LINENO "$1"
+}
+
+function bar
+{
+ typeset xyz=bar
+ set -- $((LINENO+2))
+ trap 'traceback $LINENO' DEBUG
+ : $LINENO "$1"
+}
+
+set -- $((LINENO+1))
+foo $LINENO
+function .sh.fun.set
+{
+ print -r -- "${.sh.value}"
+}
+function abc
+{
+ :
+}
+def()
+{
+ :
+}
+[[ $(abc) == abc ]] || err_exit '.sh.fun.set not capturing function name'
+[[ $(def) == def ]] || err_exit '.sh.fun.set not capturing name()'
+unset -f .sh.fun.set
+
+# tests for debug functions
+basefile=${.sh.file}
+integer baseline
+cat > $tmp/debug << \+++
+ : line 1
+
+ : line 3
++++
+# Print one line in a call stack
+function _Dbg_print_frame
+{
+ typeset -i pos=$1
+ typeset fn=$2
+ typeset filename="$3"
+ typeset -i line=$4
+ typeset arg=$5
+ shift 5
+ if ((pos==0))
+ then [[ $filename == "$basefile" ]] || err_exit "filename for level 0 is $filename not $basename"
+ [[ $arg == DEBUG ]] && ((baseline++))
+ [[ $line == "$baseline" ]] || err_exit "line number for level 0 is $line not $baseline"
+ elif ((pos==1))
+ then [[ $filename == "$tmp/debug" ]] || err_exit "filename for level 1 is $filename not $tmp/debug"
+ [[ $* == 'foo bar' ]] || err_exit "args are '$*', not 'foo bar'"
+ [[ $line == $arg ]] || err_exit "line number for level 1 is $line not $arg"
+ else err_exit "level should be 0 or 1 but is $pos"
+ fi
+}
+
+function _Dbg_debug_trap_handler
+{
+
+ integer .level=.sh.level .max=.sh.level-1
+ while((--.level>=0))
+ do
+ ((.sh.level = .level))
+ _Dbg_print_frame "${.level}" "$0" "${.sh.file}" "${.sh.lineno}" "${.sh.command##* }" "$@"
+ done
+}
+
+((baseline=LINENO+2))
+trap '_Dbg_debug_trap_handler' DEBUG
+. $tmp/debug foo bar
+trap '' DEBUG
+
+caller() {
+ integer .level=.sh.level .max=.sh.level-1
+ while((--.level>=0))
+ do
+ ((.sh.level = .level))
+ print -r -- "${.sh.lineno}"
+ done
+}
+bar() { caller;}
+set -- $(bar)
+[[ $1 == $2 ]] && err_exit ".sh.inline optimization bug"
+( $SHELL -c ' function foo { typeset x=$1;print $1;};z=();z=($(foo bar)) ') 2> /dev/null || err_exit 'using a function to set an array in a command sub fails'
+
+{
+got=$(
+s=$(ulimit -s)
+if [[ $s == +([[:digit:]]) ]] && (( s < 16384 ))
+then ulimit -s 16384 2>/dev/null
+fi
+$SHELL << \+++
+f()
+{
+ if (($1>1))
+ then x=$(f $(($1-1))) || exit 1
+ fi
+ return 0
+}
+f 257 && print ok
++++
+)
+} 2>/dev/null
+[[ $got == ok ]] || err_exit 'cannot handle comsub depth > 256 in function'
+
+tmp1=$tmp/job.1
+tmp2=$tmp/job.2
+cat > $tmp1 << +++
+#! $SHELL
+print \$\$
++++
+chmod +x $tmp1
+function foo
+{
+ typeset pid
+ $tmp1 > $tmp2 & pid=$!
+ wait $!
+ [[ $(< $tmp2) == $pid ]] || err_exit 'wrong pid for & job in function'
+}
+foo
+# make sure compiled functions work
+[[ $(tmp=$tmp $SHELL <<- \++++
+ cat > $tmp/functions <<- \EOF
+ function bar
+ {
+ print foo
+ }
+ function foobar
+ {
+ bar
+ }
+ EOF
+ ${SHCOMP:-${SHELL%/*}/shcomp} $tmp/functions > $tmp/foobar
+ rm -f "$tmp/functions"
+ chmod +x $tmp/foobar
+ rm $tmp/!(dir|foobar)
+ FPATH=$tmp
+ PATH=$FPATH:$PATH
+ foobar
+++++
+) == foo ]] > /dev/null || err_exit 'functions compiled with shcomp not working'
+# tests for compiled . scripts
+print $'print hello\nprint world' > $tmp/foo
+${SHCOMP:-${SHELL%/*}/shcomp} $tmp/foo > $tmp/foo.sh
+val=$(. $tmp/foo.sh)
+[[ $val == $'hello\nworld' ]] || err_exit "processing compiled dot files not working correctly val=$val"
+# test for functions in shell having side effects.
+unset -f foo foobar bar
+cd "$tmp"
+FPATH=$PWD
+PATH=$FPATH:$PATH
+cat > foo <<- \EOF
+ function bar
+ {
+ print foobar
+ }
+ function foo
+ {
+ bar
+ }
+EOF
+chmod +x foo
+: $(foo)
+[[ $(typeset +f) == *foo* ]] && err_exit 'function in subshell leaving side effect of function foo'
+unset -f foo bar
+: $(foo)
+[[ $(typeset +f) == *foo* ]] && err_exit 'function in subshell leaving side effects of function foo after reload'
+[[ $(typeset +f) == *bar* ]] && err_exit 'function in subshell leaving side effects of function bar after reload'
+
+unset -f foo
+typeset -A bar
+function foo
+{
+ typeset -i bar[$1].x
+ bar[$1].x=5
+}
+foo sub
+[[ ${!bar[@]} == sub ]] || err_exit 'scoping problem with compound array variables'
+
+function A
+{
+ trap "> /dev/null;print TRAP A" EXIT
+ # (( stderr )) && print >&2
+}
+
+function B
+{
+ trap "> /dev/null;print TRAP B" EXIT
+ A
+}
+
+x=$(B)
+[[ $x == $'TRAP A\nTRAP B' ]] || err_exit "trap from functions in subshells fails got" $x
+
+function foo
+{
+ typeset bar=abc
+ unset bar
+# [[ $bar == bam ]] || err_exit 'unsetting local variable does not expose global variable'
+ [[ $bar ]] && err_exit 'unsetting local variable exposes global variable'
+}
+bar=bam
+foo
+
+sleep=$(whence -p sleep)
+function gosleep
+{
+ $sleep 4
+}
+x=$(
+ (sleep 2; pid=; ps | grep sleep | read pid extra; [[ $pid ]] && kill -- $pid) &
+ gosleep 2> /dev/null
+ print ok
+)
+[[ $x == ok ]] || err_exit 'TERM signal sent to last process of function kills the script'
+
+# verify that $0 does not change with functions defined as fun()
+func1()
+{
+ [[ $0 == "$dol0" ]] || err_exit "\$0 changed in func1() to $0"
+}
+function func2
+{
+ [[ $0 == func2 ]] || err_exit "\$0 changed in func2() to $0"
+ dol0=func2
+ func1
+}
+func2
+
+{ $SHELL <<- \EOF
+ function foo
+ {
+ typeset rc=0
+ unset -f foo
+ return $rc;
+ }
+ foo
+EOF
+} 2> /dev/null || err_exit 'problem with unset -f foo within function foo'
+
+val=$($SHELL 2> /dev/null <<- \EOF
+ .sh.fun.set() { set -x; }
+ function f1 { print -n ${.sh.fun}; set -o | grep xtrace;}
+ function f2 { print -n ${.sh.fun}; set -o | grep xtrace;}
+ f1
+ set -o | grep xtrace
+ f2
+EOF)
+[[ $val == f1xtrace*on*off*f2xtrace*on* ]] || err_exit "'.sh.fun.set() { set -x; }' not tracing all functions"
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/glob.sh b/src/cmd/ksh93/tests/glob.sh
new file mode 100755
index 0000000..5b7930e
--- /dev/null
+++ b/src/cmd/ksh93/tests/glob.sh
@@ -0,0 +1,374 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -r $'\t'"${Command}[$1] ${@:2}"
+ ((Errors++))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer aware=0 contrary=0 Errors=0 ignorant=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function test_glob
+{
+ typeset lineno expected drop arg got sep op val add del
+ lineno=$1
+ shift
+ if [[ $1 == --* ]]
+ then del=${1#--}
+ shift
+ fi
+ if [[ $1 == ++* ]]
+ then add=${1#++}
+ shift
+ fi
+ expected=$1
+ shift
+ if (( contrary ))
+ then if [[ $expected == "<Beware> "* ]]
+ then expected=${expected#"<Beware> "}
+ expected="$expected <Beware>"
+ fi
+ if [[ $expected == *"<aXb> <abd>"* ]]
+ then expected=${expected/"<aXb> <abd>"/"<abd> <aXb>"}
+ fi
+ fi
+ for arg
+ do got="$got$sep<$arg>"
+ sep=" "
+ done
+ if (( ignorant && aware ))
+ then if [[ $del ]]
+ then got="<$del> $got"
+ fi
+ if [[ $add ]]
+ then expected="<$add> $expected"
+ fi
+ fi
+ if [[ $got != "$expected" ]]
+ then 'err_exit' $lineno "glob -- expected '$expected', got '$got'"
+ fi
+}
+alias test_glob='test_glob $LINENO'
+
+function test_case
+{
+ typeset lineno expected subject pattern got
+ lineno=$1 expected=$2 subject=$3 pattern=$4
+ eval "
+ case $subject in
+ $pattern) got='<match>' ;;
+ *) got='<nomatch>' ;;
+ esac
+ "
+ if [[ $got != "$expected" ]]
+ then 'err_exit' $lineno "case $subject in $pattern) -- expected '$expected', got '$got'"
+ fi
+}
+alias test_case='test_case $LINENO'
+
+unset undefined
+
+cd $tmp || { err_exit "cd $tmp failed"; exit 1; }
+
+export LC_COLLATE=C
+touch B b
+set -- *
+case $* in
+'b B') contrary=1 ;;
+b|B) ignorant=1 ;;
+esac
+set -- $(LC_ALL=C /bin/sh -c 'echo [a-c]')
+case $* in
+B) aware=1 ;;
+esac
+rm -rf *
+
+touch a b c d abc abd abe bb bcd ca cb dd de Beware
+mkdir bdir
+
+test_glob '<a> <abc> <abd> <abe> <X*>' a* X*
+test_glob '<a> <abc> <abd> <abe>' \a*
+
+if ( set --nullglob ) 2>/dev/null
+then
+ set --nullglob
+
+ test_glob '<a> <abc> <abd> <abe>' a* X*
+
+ set --nonullglob
+fi
+
+if ( set --failglob ) 2>/dev/null
+then
+ set --failglob
+ mkdir tmp
+ touch tmp/l1 tmp/l2 tmp/l3
+
+ test_glob '' tmp/l[12] tmp/*4 tmp/*3
+ test_glob '' tmp/l[12] tmp/*4 tmp/*3
+
+ rm -r tmp
+ set --nofailglob
+fi
+
+test_glob '<bdir/>' b*/
+test_glob '<*>' \*
+test_glob '<a*>' 'a*'
+test_glob '<a*>' a\*
+test_glob '<c> <ca> <cb> <a*> <*q*>' c* a\* *q*
+test_glob '<**>' "*"*
+test_glob '<**>' \**
+test_glob '<\.\./*/>' "\.\./*/"
+test_glob '<s/\..*//>' 's/\..*//'
+test_glob '</^root:/{s/^[!:]*:[!:]*:\([!:]*\).*$/\1/>' "/^root:/{s/^[!:]*:[!:]*:\([!:]*\).*"'$'"/\1/"
+test_glob '<abc> <abd> <abe> <bb> <cb>' [a-c]b*
+test_glob ++Beware '<abd> <abe> <bb> <bcd> <bdir> <ca> <cb> <dd> <de>' [a-y]*[!c]
+test_glob '<abd> <abe>' a*[!c]
+
+touch a-b aXb
+
+test_glob '<a-b> <aXb>' a[X-]b
+
+touch .x .y
+
+test_glob --Beware '<Beware> <d> <dd> <de>' [!a-c]*
+
+if mkdir a\*b 2>/dev/null
+then
+ touch a\*b/ooo
+
+ test_glob '<a*b/ooo>' a\*b/*
+ test_glob '<a*b/ooo>' a\*?/*
+ test_case '<match>' '!7' '*\!*'
+ test_case '<match>' 'r.*' '*.\*'
+ test_glob '<abc>' a[b]c
+ test_glob '<abc>' a["b"]c
+ test_glob '<abc>' a[\b]c
+ test_glob '<abc>' a?c
+ test_case '<match>' 'abc' 'a"b"c'
+ test_case '<match>' 'abc' 'a*c'
+ test_case '<nomatch>' 'abc' '"a?c"'
+ test_case '<nomatch>' 'abc' 'a\*c'
+ test_case '<nomatch>' 'abc' 'a\[b]c'
+ test_case '<match>' '"$undefined"' '""'
+ test_case '<match>' 'abc' 'a["\b"]c'
+
+ rm -rf mkdir a\*b
+fi
+
+mkdir man
+mkdir man/man1
+touch man/man1/sh.1
+
+test_glob '<man/man1/sh.1>' */man*/sh.*
+test_glob '<man/man1/sh.1>' $(echo */man*/sh.*)
+test_glob '<man/man1/sh.1>' "$(echo */man*/sh.*)"
+
+test_case '<match>' 'abc' 'a***c'
+test_case '<match>' 'abc' 'a*****?c'
+test_case '<match>' 'abc' '?*****??'
+test_case '<match>' 'abc' '*****??'
+test_case '<match>' 'abc' '*****??c'
+test_case '<match>' 'abc' '?*****?c'
+test_case '<match>' 'abc' '?***?****c'
+test_case '<match>' 'abc' '?***?****?'
+test_case '<match>' 'abc' '?***?****'
+test_case '<match>' 'abc' '*******c'
+test_case '<match>' 'abc' '*******?'
+test_case '<match>' 'abcdecdhjk' 'a*cd**?**??k'
+test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??k'
+test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??k***'
+test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??***k'
+test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??***k**'
+test_case '<match>' 'abcdecdhjk' 'a****c**?**??*****'
+test_case '<match>' "'-'" '[-abc]'
+test_case '<match>' "'-'" '[abc-]'
+test_case '<match>' "'\\'" '\\'
+test_case '<match>' "'\\'" '[\\]'
+test_case '<match>' "'\\'" "'\\'"
+test_case '<match>' "'['" '[[]'
+test_case '<match>' '[' '[[]'
+test_case '<match>' "'['" '['
+test_case '<match>' '[' '['
+test_case '<match>' "'[abc'" "'['*"
+test_case '<nomatch>' "'[abc'" '[*'
+test_case '<match>' '[abc' "'['*"
+test_case '<nomatch>' '[abc' '[*'
+test_case '<match>' 'abd' "a[b/c]d"
+test_case '<match>' 'a/d' "a[b/c]d"
+test_case '<match>' 'acd' "a[b/c]d"
+test_case '<match>' "']'" '[]]'
+test_case '<match>' "'-'" '[]-]'
+test_case '<match>' 'p' '[a-\z]'
+test_case '<match>' '"/tmp"' '[/\\]*'
+test_case '<nomatch>' 'abc' '??**********?****?'
+test_case '<nomatch>' 'abc' '??**********?****c'
+test_case '<nomatch>' 'abc' '?************c****?****'
+test_case '<nomatch>' 'abc' '*c*?**'
+test_case '<nomatch>' 'abc' 'a*****c*?**'
+test_case '<nomatch>' 'abc' 'a********???*******'
+test_case '<nomatch>' "'a'" '[]'
+test_case '<nomatch>' 'a' '[]'
+test_case '<nomatch>' "'['" '[abc'
+test_case '<nomatch>' '[' '[abc'
+
+test_glob ++Beware '<b> <bb> <bcd> <bdir>' b*
+test_glob '<Beware> <b> <bb> <bcd> <bdir>' [bB]*
+
+if ( set --nocaseglob ) 2>/dev/null
+then
+ set --nocaseglob
+
+ test_glob '<Beware> <b> <bb> <bcd> <bdir>' b*
+ test_glob '<Beware> <b> <bb> <bcd> <bdir>' [b]*
+ test_glob '<Beware> <b> <bb> <bcd> <bdir>' [bB]*
+
+ set --nonocaseglob
+fi
+
+if ( set -f ) 2>/dev/null
+then
+ set -f
+
+ test_glob '<*>' *
+
+ set +f
+fi
+
+if ( set --noglob ) 2>/dev/null
+then
+ set --noglob
+
+ test_glob '<*>' *
+
+ set --glob
+fi
+
+FIGNORE='@(.*|*)'
+test_glob '<*>' *
+
+FIGNORE='@(.*|*c|*e|?)'
+test_glob '<a-b> <aXb> <abd> <bb> <bcd> <bdir> <ca> <cb> <dd> <man>' *
+
+FIGNORE='@(.*|*b|*d|?)'
+test_glob '<Beware> <abc> <abe> <bdir> <ca> <de> <man>' *
+
+FIGNORE=
+test_glob '<man/man1/sh.1>' */man*/sh.*
+
+unset FIGNORE
+test_glob '<bb> <ca> <cb> <dd> <de>' ??
+test_glob '<man/man1/sh.1>' */man*/sh.*
+
+GLOBIGNORE='.*:*'
+set -- *
+if [[ $1 == '*' ]]
+then
+ GLOBIGNORE='.*:*c:*e:?'
+ test_glob '<>' *
+
+ GLOBIGNORE='.*:*b:*d:?'
+ test_glob '<>' *
+
+ unset GLOBIGNORE
+ test_glob '<>' *
+ test_glob '<man/man1/sh.1>' */man*/sh.*
+
+ GLOBIGNORE=
+ test_glob '<man/man1/sh.1>' */man*/sh.*
+fi
+unset GLOBIGNORE
+
+function test_sub
+{
+ x='${subject'$2'}'
+ eval g=$x
+ if [[ "$g" != "$3" ]]
+ then 'err_exit' $1 subject="'$subject' $x failed, expected '$3', got '$g'"
+ fi
+}
+alias test_sub='test_sub $LINENO'
+
+set --noglob --nobraceexpand
+
+subject='A regular expressions test'
+
+test_sub '/e/#' 'A r#gular expressions test'
+test_sub '//e/#' 'A r#gular #xpr#ssions t#st'
+test_sub '/[^e]/#' '# regular expressions test'
+test_sub '//[^e]/#' '###e######e###e########e##'
+test_sub '/+(e)/#' 'A r#gular expressions test'
+test_sub '//+(e)/#' 'A r#gular #xpr#ssions t#st'
+test_sub '/@-(e)/#' 'A r#gular expressions test'
+test_sub '//@-(e)/#' 'A r#gular #xpr#ssions t#st'
+test_sub '/?(e)/#' '#A regular expressions test'
+test_sub '//?(e)/#' '#A# #r#g#u#l#a#r# #x#p#r#s#s#i#o#n#s# #t#s#t#'
+test_sub '/*(e)/#' '#A regular expressions test'
+test_sub '//*(e)/#' '#A# #r#g#u#l#a#r# #x#p#r#s#s#i#o#n#s# #t#s#t#'
+test_sub '//@(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//@-(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//+(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//+-(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//@(+(e))/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//@(+-(e))/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
+test_sub '//-(e)/#' 'A regular expressions test'
+test_sub '//--(e)/#' 'A regular expressions test'
+test_sub '//?(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//{0,1}(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//*(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//{0,}(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//@(?(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//@({0,1}(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//@(*(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '//@({0,}(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
+test_sub '/?-(e)/#' '#A regular expressions test'
+test_sub '/@(?-(e))/[\1]' '[]A regular expressions test'
+test_sub '/!(e)/#' '#'
+test_sub '//!(e)/#' '#'
+test_sub '/@(!(e))/[\1]' '[A regular expressions test]'
+test_sub '//@(!(e))/[\1]' '[A regular expressions test]'
+
+subject='e'
+
+test_sub '/!(e)/#' '#e'
+test_sub '//!(e)/#' '#e#'
+test_sub '/!(e)/[\1]' '[]e'
+test_sub '//!(e)/[\1]' '[]e[]'
+test_sub '/@(!(e))/[\1]' '[]e'
+test_sub '//@(!(e))/[\1]' '[]e[]'
+
+subject='a'
+
+test_sub '/@(!(a))/[\1]' '[]a'
+test_sub '//@(!(a))/[\1]' '[]a[]'
+
+subject='aha'
+
+test_sub '/@(!(a))/[\1]' '[aha]'
+test_sub '//@(!(a))/[\1]' '[aha]'
+test_sub '/@(!(aha))/[\1]' '[ah]a'
+test_sub '//@(!(aha))/[\1]' '[ah][a]'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/grep.sh b/src/cmd/ksh93/tests/grep.sh
new file mode 100755
index 0000000..480f823
--- /dev/null
+++ b/src/cmd/ksh93/tests/grep.sh
@@ -0,0 +1,105 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function grep
+{
+ #
+ # SHELL VERSION OF GREP
+ #
+ vflag= xflag= cflag= lflag= nflag=
+ set -f
+ while ((1)) # look for grep options
+ do case "$1" in
+ -v*) vflag=1;;
+ -x*) xflag=1;;
+ -c*) cflag=1;;
+ -l*) lflag=1;;
+ -n*) nflag=1;;
+ -b*) print 'b option not supported';;
+ -e*) shift;expr="$1";;
+ -f*) shift;expr=$(< $1);;
+ -*) print $0: 'unknown flag';return 2;;
+ *)
+ if test "$expr" = ''
+ then expr="$1";shift
+ fi
+ test "$xflag" || expr="*${expr}*"
+ break;;
+ esac
+ shift # next argument
+ done
+ noprint=$vflag$cflag$lflag # don't print if these flags are set
+ integer n=0 c=0 tc=0 nargs=$# # initialize counters
+ for i in "$@" # go thru the files
+ do if ((nargs<=1))
+ then fname=''
+ else fname="$i":
+ fi
+ test "$i" && exec 0< $i # open file if necessary
+ while read -r line # read in a line
+ do let n=n+1
+ case "$line" in
+ $expr) # line matches pattern
+ test "$noprint" || print -r -- "$fname${nflag:+$n:}$line"
+ let c=c+1 ;;
+ *) # not a match
+ if test "$vflag"
+ then print -r -- "$fname${nflag:+$n:}$line"
+ fi;;
+ esac
+ done
+ if test "$lflag" && ((c))
+ then print -r -- "$i"
+ fi
+ let tc=tc+c n=0 c=0
+ done
+ test "$cflag" && print $tc # print count if cflag is set
+ let tc # set the return value
+}
+
+cat > $tmp/grep <<\!
+this is a food bar test
+to see how many lines find both foo and bar.
+Some line contain foo only,
+and some lines contain bar only.
+However, many lines contain both foo and also bar.
+A line containing foobar should also be counted.
+There should be six lines with foo and bar.
+There are only two line with out foo but with bar.
+!
+
+if (( $(grep -c 'foo*bar' $tmp/grep ) != 6))
+then err_exit
+fi
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/heredoc.sh b/src/cmd/ksh93/tests/heredoc.sh
new file mode 100755
index 0000000..a8d8a72
--- /dev/null
+++ b/src/cmd/ksh93/tests/heredoc.sh
@@ -0,0 +1,496 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+f=$tmp/here1
+g=$tmp/here2
+cat > $f <<!
+hello world
+!
+if [[ $(<$f) != 'hello world' ]]
+then err_exit "'hello world' here doc not working"
+fi
+cat > $g <<\!
+hello world
+!
+cmp $f $g 2> /dev/null || err_exit "'hello world' quoted here doc not working"
+cat > $g <<- !
+ hello world
+!
+cmp $f $g 2> /dev/null || err_exit "'hello world' tabbed here doc not working"
+cat > $g <<- \!
+ hello world
+!
+cmp $f $g 2> /dev/null || err_exit "'hello world' quoted tabbed here doc not working"
+x=hello
+cat > $g <<!
+$x world
+!
+cmp $f $g 2> /dev/null || err_exit "'$x world' here doc not working"
+cat > $g <<!
+$(print hello) world
+!
+cmp $f $g 2> /dev/null || err_exit "'$(print hello) world' here doc not working"
+cat > $f <<\!!
+!@#$%%^^&*()_+~"::~;'`<>?/.,{}[]
+!!
+if [[ $(<$f) != '!@#$%%^^&*()_+~"::~;'\''`<>?/.,{}[]' ]]
+then err_exit "'hello world' here doc not working"
+fi
+cat > $g <<!!
+!@#\$%%^^&*()_+~"::~;'\`<>?/.,{}[]
+!!
+cmp $f $g 2> /dev/null || err_exit "unquoted here doc not working"
+exec 3<<!
+ foo
+!
+if [[ $(<&3) != ' foo' ]]
+then err_exit "leading tabs stripped with <<!"
+fi
+$SHELL -c "
+eval `echo 'cat <<x'` "|| err_exit "eval `echo 'cat <<x'` core dumps"
+cat > /dev/null <<EOF # comments should not cause core dumps
+abc
+EOF
+cat >$g << :
+:
+:
+cmp /dev/null $g 2> /dev/null || err_exit "empty here doc not working"
+x=$(print $( cat <<HUP
+hello
+HUP
+)
+)
+if [[ $x != hello ]]
+then err_exit "here doc inside command sub not working"
+fi
+y=$(cat <<!
+${x:+${x}}
+!
+)
+if [[ $y != "${x:+${x}}" ]]
+then err_exit '${x:+${x}} not working in here document'
+fi
+$SHELL -c '
+x=0
+while (( x < 100 ))
+do ((x = x+1))
+ cat << EOF
+EOF
+done
+' 2> /dev/null || err_exit '100 empty here docs fails'
+{
+ print 'builtin -d cat
+ cat <<- EOF'
+ for ((i=0; i < 100; i++))
+ do print XXXXXXXXXXXXXXXXXXXX
+ done
+ print ' XXX$(date)XXXX
+ EOF'
+} > $f
+chmod +x "$f"
+$SHELL "$f" > /dev/null || err_exit "large here-doc with command substitution fails"
+x=$(/bin/cat <<!
+$0
+!
+)
+[[ "$x" == "$0" ]] || err_exit '$0 not correct inside here documents'
+$SHELL -c 'x=$(
+cat << EOF
+EOF)' 2> /dev/null || err_exit 'here-doc cannot be terminated by )'
+if [[ $( IFS=:;cat <<-!
+ $IFS$(print hi)$IFS
+ !) != :hi: ]]
+then err_exit '$IFS unset by command substitution in here docs'
+fi
+if x=$($SHELL -c 'cat <<< "hello world"' 2> /dev/null)
+then [[ $x == 'hello world' ]] || err_exit '<<< documents not working'
+ x=$($SHELL -c 'v="hello world";cat <<< $v' 2> /dev/null)
+ [[ $x == 'hello world' ]] || err_exit '<<< documents with $x not working'
+ x=$($SHELL -c 'v="hello world";cat <<< "$v"' 2> /dev/null)
+ [[ $x == 'hello world' ]] || err_exit '<<< documents with $x not working'
+else err_exit '<<< syntax not supported'
+fi
+if [[ $(cat << EOF #testing
+#abc
+abc
+EOF) != $'#abc\nabc' ]]
+then err_exit 'comments not preserved in here-documents'
+fi
+cat > "$f" <<- '!!!!'
+ builtin cat
+ : << EOF
+ $PWD
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ EOF
+ command exec 3>&- 4>&- 5>&- 6>&- 7>&- 8>&- 9>&-
+ x=abc
+ cat << EOF
+ $x
+ EOF
+!!!!
+chmod 755 "$f"
+if [[ $($SHELL "$f") != abc ]]
+then err_exit 'here document descritor was closed'
+fi
+cat > "$f" <<- '!!!!'
+ exec 0<&-
+ foobar()
+ {
+ /bin/cat <<- !
+ foobar
+ !
+ }
+ : << EOF
+ $PWD
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ EOF
+ print -r -- "$(foobar)"
+!!!!
+if [[ $($SHELL "$f") != foobar ]]
+then err_exit 'here document with stdin closed failed'
+fi
+printf $'cat <<# \\!!!\n\thello\n\t\tworld\n!!!' > $f
+[[ $($SHELL "$f") == $'hello\n\tworld' ]] || err_exit "<<# not working for quoted here documents"
+printf $'w=world;cat <<# !!!\n\thello\n\t\t$w\n!!!' > $f
+[[ $($SHELL "$f") == $'hello\n\tworld' ]] || err_exit "<<# not working for non-quoted here documents"
+[[ $( $SHELL <<- \++++
+ S=( typeset a )
+ function S.a.get
+ {
+ .sh.value=$__a
+ }
+ __a=1234
+ cat <<-EOF
+ ${S.a}
+ EOF
+++++
+) == 1234 ]] 2> /dev/null || err_exit 'here document with get discipline failed'
+[[ $($SHELL -c 'g(){ print ok;}; cat <<- EOF
+ ${ g;}
+ EOF
+ ' 2> /dev/null) == ok ]] || err_exit '${ command;} not working in heredoc'
+script=$f
+{
+for ((i=0; i < 406; i++))
+do print ': 23456789012345678'
+done
+print : 123456789123
+cat <<- \EOF
+eval "$(
+ { cat ; } <<MARKER
+ print hello
+ MARKER
+)"
+EOF
+} > $script
+chmod +x $script
+[[ $($SHELL $script) == hello ]] 2> /dev/null || err_exit 'heredoc embeded in command substitution fails at buffer boundary'
+
+got=$( cat << EOF
+\
+abc
+EOF)
+[[ $got == abc ]] || err_exit 'line continuation at start of buffer not working'
+
+tmpfile1=$tmp/file1
+tmpfile2=$tmp/file2
+function gendata
+{
+ typeset -RZ3 i
+ for ((i=0; i < 500; i++))
+ do print -r -- "=====================This is line $i============="
+ done
+}
+
+cat > $tmpfile1 <<- +++
+ function foobar
+ {
+ cat << XXX
+ $(gendata)
+ XXX
+ }
+ cat > $tmpfile2 <<- EOF
+ \$(foobar)
+ $(gendata)
+EOF
++++
+chmod +x $tmpfile1
+$SHELL $tmpfile1
+set -- $(wc < $tmpfile2)
+(( $1 == 1000 )) || err_exit "heredoc $1 lines, should be 1000 lines"
+(( $2 == 4000 )) || err_exit "heredoc $2 words, should be 4000 words"
+
+# comment with here document looses line number count
+integer line=$((LINENO+5))
+function tst
+{
+ [[ $1 == $2 ]] || echo expected $1, got $2
+}
+tst $line $LINENO <<"!" # this comment affects LINENO #
+1
+!
+(( (line+=3) == LINENO )) || err_exit "line number=$LINENO should be $line"
+
+[[ $($SHELL -c 'wc -c <<< ""' 2> /dev/null) == *1 ]] || err_exit '<<< with empty string not working'
+
+mkdir $tmp/functions
+cat > $tmp/functions/t2 <<\!!!
+function t2
+{
+cat <<EOF | sed 's/1234567890/qwertyuiopasdfghj/'
+${1}
+EOF
+}
+!!!
+
+FPATH=$tmp/functions
+foo=${
+cat <<EOF
+1 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111111
+111111111111111111111111111111111111111111111111111111111111 1
+
+2 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222222
+222222222222222222222222222222222222222222222222222222222222 2
+
+3 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333333
+333333333333333333333333333333333333333333333333333333333333 3
+
+4 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444444
+444444444444444444444444444444444444444444444444444444444444 4
+
+5 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555555
+555555555555555555555555555555555555555555555555555555555555 5
+
+6 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666666
+666666666666666666666666666666666666666666666666666666666666 6
+
+7 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777777
+777777777777777777777777777777777777777777777777777777777777 7
+
+8 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888888
+888888888888888888888888888888888888888888888888888888888888 8
+
+9 34567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999 9
+
+10 4567890 $(t2 1234567890 ) 0123456789012345678901234567890123
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+101010101010101010101010101010101010101010101010101010101010103
+1010101010101010101010101010101010101010101010101010101010 END
+
+EOF
+}
+[[ ${#foo} == 10238 ]] || err_exit 'large here docs containing command subs of dynamically loaded functions fails'
+
+{
+ print $'FOO=1\nBAR=foobarbaz'
+ print -- 'cat <<#EOF'
+ integer i
+ for ((i=0; i < 50000; i++))
+ do print -r -- ' $(($FOO + 1))'
+ print -r -- ' $BAR meep'
+ done
+ print EOF
+} > $f
+$SHELL $f > $g
+[[ $(grep meep $g | grep -v foobar) != '' ]] && err_exit 'here-doc loosing $var expansions on boundaries in rare cases'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/io.sh b/src/cmd/ksh93/tests/io.sh
new file mode 100755
index 0000000..bed0fd4
--- /dev/null
+++ b/src/cmd/ksh93/tests/io.sh
@@ -0,0 +1,484 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+unset HISTFILE
+
+function fun
+{
+ while command exec 3>&1
+ do break
+ done 2> /dev/null
+ print -u3 good
+}
+print 'read -r a; print -r -u$1 -- "$a"' > $tmp/mycat
+chmod 755 $tmp/mycat
+for ((i=3; i < 10; i++))
+do
+ eval "a=\$(print foo | $tmp/mycat" $i $i'>&1 > /dev/null |cat)' 2> /dev/null
+ [[ $a == foo ]] || err_exit "bad file descriptor $i in comsub script"
+done
+exec 3> /dev/null
+[[ $(fun) == good ]] || err_exit 'file 3 closed before subshell completes'
+exec 3>&-
+cd $tmp || { err_exit "cd $tmp failed"; exit ; }
+print foo > file1
+print bar >> file1
+if [[ $(<file1) != $'foo\nbar' ]]
+then err_exit 'append (>>) not working'
+fi
+set -o noclobber
+exec 3<> file1
+read -u3 line
+exp=foo
+if [[ $line != $exp ]]
+then err_exit "read on <> fd failed -- expected '$exp', got '$line'"
+fi
+if ( 4> file1 ) 2> /dev/null
+then err_exit 'noclobber not causing exclusive open'
+fi
+set +o noclobber
+
+FDFS=(
+ ( dir=/proc/self/fd semantics='open' )
+ ( dir=/proc/$$/fd semantics='open' )
+ ( dir=/dev/fd semantics='open|dup' )
+ ( dir=/dev/fd semantics='dup' )
+)
+for ((fdfs=0; fdfs<${#FDFS[@]}-1; fdfs++))
+do [[ -e ${FDFS[fdfs].dir} ]] && { command : > ${FDFS[fdfs].dir}/1; } 2>/dev/null >&2 && break
+done
+
+exec 3<> file1
+if command exec 4< ${FDFS[fdfs].dir}/3
+then read -u3 got
+ read -u4 got
+ exp='foo|bar'
+ case $got in
+ foo) semantics='open' ;;
+ bar) semantics='dup' ;;
+ *) semantics='failed' ;;
+ esac
+ [[ $semantics == @(${FDFS[fdfs].semantics}) ]] || err_exit "'4< ${FDFS[fdfs].dir}/3' $semantics semantics instead of ${FDFS[fdfs].semantics} -- expected '$exp', got '$got'"
+fi
+
+# 2004-11-25 ancient /dev/fd/N redirection bug fix
+got=$(
+ {
+ print -n 1
+ print -n 2 > ${FDFS[fdfs].dir}/2
+ print -n 3
+ print -n 4 > ${FDFS[fdfs].dir}/2
+ } 2>&1
+)
+exp='1234|4'
+case $got in
+1234) semantics='dup' ;;
+4) semantics='open' ;;
+*) semantics='failed' ;;
+esac
+[[ $semantics == @(${FDFS[fdfs].semantics}) ]] || err_exit "${FDFS[fdfs].dir}/N $semantics semantics instead of ${FDFS[fdfs].semantics} -- expected '$exp', got '$got'"
+
+cat > close0 <<\!
+exec 0<&-
+echo $(./close1)
+!
+print "echo abc" > close1
+chmod +x close0 close1
+x=$(./close0)
+if [[ $x != "abc" ]]
+then err_exit "picked up file descriptor zero for opening script file"
+fi
+cat > close0 <<\!
+ for ((i=0; i < 1100; i++))
+ do exec 4< /dev/null
+ read -u4
+ done
+ exit 0
+!
+./close0 2> /dev/null || err_exit "multiple exec 4< /dev/null can fail"
+$SHELL -c '
+ trap "rm -f in out" EXIT
+ for ((i = 0; i < 1000; i++))
+ do print -r -- "This is a test"
+ done > in
+ > out
+ exec 1<> out
+ builtin cat
+ print -r -- "$(<in)"
+ cmp -s in out' 2> /dev/null
+[[ $? == 0 ]] || err_exit 'builtin cat truncates files'
+cat >| script <<-\!
+print hello
+( exec 3<&- 4<&-)
+exec 3<&- 4<&-
+print world
+!
+chmod +x script
+[[ $( $SHELL ./script) == $'hello\nworld' ]] || err_exit 'closing 3 & 4 causes script to fail'
+cd ~- || err_exit "cd back failed"
+( exec > '' ) 2> /dev/null && err_exit '> "" does not fail'
+unset x
+( exec > ${x} ) 2> /dev/null && err_exit '> $x, where x null does not fail'
+exec <<!
+foo
+bar
+!
+( exec 0< /dev/null)
+read line
+if [[ $line != foo ]]
+then err_exit 'file descriptor not restored after exec in subshell'
+fi
+exec 3>&- 4>&-
+[[ $( {
+ read -r line; print -r -- "$line"
+ (
+ read -r line; print -r -- "$line"
+ ) & wait
+ while read -r line
+ do print -r -- "$line"
+ done
+ } << !
+line 1
+line 2
+line 3
+!) == $'line 1\nline 2\nline 3' ]] || err_exit 'read error with subshells'
+# 2004-05-11 bug fix
+cat > $tmp/1 <<- ++EOF++
+ script=$tmp/2
+ trap "rm -f \$script" EXIT
+ exec 9> \$script
+ for ((i=3; i<9; i++))
+ do eval "while read -u\$i; do : ; done \$i</dev/null"
+ print -u9 "exec \$i< /dev/null"
+ done
+ for ((i=0; i < 60; i++))
+ do print -u9 -f "%.80c\n" ' '
+ done
+ print -u9 'print ok'
+ exec 9<&-
+ chmod +x \$script
+ \$script
+++EOF++
+chmod +x $tmp/1
+[[ $($SHELL $tmp/1) == ok ]] || err_exit "parent i/o causes child script to fail"
+# 2004-12-20 redirection loss bug fix
+cat > $tmp/1 <<- \++EOF++
+ function a
+ {
+ trap 'print ok' EXIT
+ : > /dev/null
+ }
+ a
+++EOF++
+chmod +x $tmp/1
+[[ $($tmp/1) == ok ]] || err_exit "trap on EXIT loses last command redirection"
+print > /dev/null {n}> $tmp/1
+[[ ! -s $tmp/1 ]] && newio=1
+if [[ $newio && $(print hello | while read -u$n; do print $REPLY; done {n}<&0) != hello ]]
+then err_exit "{n}<&0 not working with for loop"
+fi
+[[ $({ read -r; read -u3 3<&0; print -- "$REPLY" ;} <<!
+hello
+world
+!) == world ]] || err_exit 'I/O not synchronized with <&'
+x="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNSPQRSTUVWXYZ1234567890"
+for ((i=0; i < 62; i++))
+do printf "%.39c\n" ${x:i:1}
+done > $tmp/seek
+if command exec 3<> $tmp/seek
+then (( $(3<#) == 0 )) || err_exit "not at position 0"
+ (( $(3<# ((EOF))) == 40*62 )) || err_exit "not at end-of-file"
+ command exec 3<# ((40*8)) || err_exit "absolute seek fails"
+ read -u3
+ [[ $REPLY == +(i) ]] || err_exit "expected iiii..., got $REPLY"
+ [[ $(3<#) == $(3<# ((CUR)) ) ]] || err_exit '$(3<#)!=$(3<#((CUR)))'
+ command exec 3<# ((CUR+80))
+ read -u3
+ [[ $REPLY == {39}(l) ]] || err_exit "expected lll..., got $REPLY"
+ command exec 3<# ((EOF-80))
+ read -u3
+ [[ $REPLY == +(9) ]] || err_exit "expected 999..., got $REPLY"
+ command exec 3># ((80))
+ print -u3 -f "%.39c\n" @
+ command exec 3># ((80))
+ read -u3
+ [[ $REPLY == +(@) ]] || err_exit "expected @@@..., got $REPLY"
+ read -u3
+ [[ $REPLY == +(d) ]] || err_exit "expected ddd..., got $REPLY"
+ command exec 3># ((EOF))
+ print -u3 -f "%.39c\n" ^
+ (( $(3<# ((CUR-0))) == 40*63 )) || err_exit "not at extended end-of-file"
+ command exec 3<# ((40*62))
+ read -u3
+ [[ $REPLY == +(^) ]] || err_exit "expected ddd..., got $REPLY"
+ command exec 3<# ((0))
+ command exec 3<# *jjjj*
+ read -u3
+ [[ $REPLY == {39}(j) ]] || err_exit "<# pattern failed"
+ [[ $(command exec 3<## *llll*) == {39}(k) ]] || err_exit "<## pattern not saving standard output"
+ read -u3
+ [[ $REPLY == {39}(l) ]] || err_exit "<## pattern failed to position"
+ command exec 3<# *abc*
+ read -u3 && err_exit "not found pattern not positioning at eof"
+ cat $tmp/seek | read -r <# *WWW*
+ [[ $REPLY == *WWWWW* ]] || err_exit '<# not working for pipes'
+ { < $tmp/seek <# ((2358336120)) ;} 2> /dev/null || err_exit 'long seek not working'
+else err_exit "$tmp/seek: cannot open for reading"
+fi
+command exec 3<&- || 'cannot close 3'
+for ((i=0; i < 62; i++))
+do printf "%.39c\n" ${x:i:1}
+done > $tmp/seek
+if command exec {n}<> $tmp/seek
+then { command exec {n}<#((EOF)) ;} 2> /dev/null || err_exit '{n}<# not working'
+ if $SHELL -c '{n}</dev/null' 2> /dev/null
+ then (( $({n}<#) == 40*62)) || err_exit '$({n}<#) not working'
+ else err_exit 'not able to parse {n}</dev/null'
+ fi
+fi
+$SHELL -ic '
+{
+ print -u2 || exit 2
+ print -u3 || exit 3
+ print -u4 || exit 4
+ print -u5 || exit 5
+ print -u6 || exit 6
+ print -u7 || exit 7
+ print -u8 || exit 8
+ print -u9 || exit 9
+} 3> /dev/null 4> /dev/null 5> /dev/null 6> /dev/null 7> /dev/null 8> /dev/null 9> /dev/null' > /dev/null 2>&1
+exitval=$?
+(( exitval )) && err_exit "print to unit $exitval failed"
+$SHELL -c "{ > $tmp/1 ; date;} >&- 2> /dev/null" > $tmp/2
+[[ -s $tmp/1 || -s $tmp/2 ]] && err_exit 'commands with standard output closed produce output'
+$SHELL -c "$SHELL -c ': 3>&1' 1>&- 2>/dev/null" && err_exit 'closed standard output not passed to subshell'
+[[ $(cat <<- \EOF | $SHELL
+ do_it_all()
+ {
+ dd 2>/dev/null # not a ksh93 buildin
+ return $?
+ }
+ do_it_all ; exit $?
+ hello world
+EOF) == 'hello world' ]] || err_exit 'invalid readahead on stdin'
+$SHELL -c 'exec 3>; /dev/null' 2> /dev/null && err_exit '>; with exec should be an error'
+$SHELL -c ': 3>; /dev/null' 2> /dev/null || err_exit '>; not working with at all'
+print hello > $tmp/1
+if ! $SHELL -c "false >; $tmp/1" 2> /dev/null
+then [[ $(<$tmp/1) == hello ]] || err_exit '>; not preserving file on failure'
+fi
+if ! $SHELL -c "sed -e 's/hello/hello world/' $tmp/1" >; $tmp/1 2> /dev/null
+then [[ $(<$tmp/1) == 'hello world' ]] || err_exit '>; not updating file on success'
+fi
+
+$SHELL -c 'exec 3<>; /dev/null' 2> /dev/null && err_exit '<>; with exec should be an error'
+$SHELL -c ': 3<>; /dev/null' 2> /dev/null || err_exit '<>; not working with at all'
+print $'hello\nworld' > $tmp/1
+if ! $SHELL -c "false <>; $tmp/1" 2> /dev/null
+then [[ $(<$tmp/1) == $'hello\nworld' ]] || err_exit '<>; not preserving file on failure'
+fi
+if ! $SHELL -c "head -1 $tmp/1" <>; $tmp/1 2> /dev/null
+then [[ $(<$tmp/1) == hello ]] || err_exit '<>; not truncating file on success of head'
+fi
+print $'hello\nworld' > $tmp/1
+if ! $SHELL -c head < $tmp/1 <#((6)) <>; $tmp/1 2> /dev/null
+then [[ $(<$tmp/1) == world ]] || err_exit '<>; not truncating file on success of behead'
+fi
+
+unset y
+read -n1 y <<!
+abc
+!
+if [[ $y != a ]]
+then err_exit 'read -n1 not working'
+fi
+unset a
+{ read -N3 a; read -N1 b;} <<!
+abcdefg
+!
+[[ $a == abc ]] || err_exit 'read -N3 here-document not working'
+[[ $b == d ]] || err_exit 'read -N1 here-document not working'
+read -n3 a <<!
+abcdefg
+!
+[[ $a == abc ]] || err_exit 'read -n3 here-document not working'
+(print -n a; sleep 1; print -n bcde) | { read -N3 a; read -N1 b;}
+[[ $a == abc ]] || err_exit 'read -N3 from pipe not working'
+[[ $b == d ]] || err_exit 'read -N1 from pipe not working'
+(print -n a; sleep 1; print -n bcde) |read -n3 a
+[[ $a == a ]] || err_exit 'read -n3 from pipe not working'
+if mkfifo $tmp/fifo 2> /dev/null
+then (print -n a; sleep 2; print -n bcde) > $tmp/fifo &
+ {
+ read -u5 -n3 -t3 a || err_exit 'read -n3 from fifo timed out'
+ read -u5 -n1 -t3 b || err_exit 'read -n1 from fifo timed out'
+ } 5< $tmp/fifo
+ exp=a
+ got=$a
+ [[ $got == "$exp" ]] || err_exit "read -n3 from fifo failed -- expected '$exp', got '$got'"
+ exp=b
+ got=$b
+ [[ $got == "$exp" ]] || err_exit "read -n1 from fifo failed -- expected '$exp', got '$got'"
+ rm -f $tmp/fifo
+ wait
+ mkfifo $tmp/fifo 2> /dev/null
+ (print -n a; sleep 2; print -n bcde) > $tmp/fifo &
+ {
+ read -u5 -N3 -t3 a || err_exit 'read -N3 from fifo timed out'
+ read -u5 -N1 -t3 b || err_exit 'read -N1 from fifo timed out'
+ } 5< $tmp/fifo
+ exp=abc
+ got=$a
+ [[ $got == "$exp" ]] || err_exit "read -N3 from fifo failed -- expected '$exp', got '$got'"
+ exp=d
+ got=$b
+ [[ $got == "$exp" ]] || err_exit "read -N1 from fifo failed -- expected '$exp', got '$got'"
+ wait
+fi
+(
+ print -n 'prompt1: '
+ sleep .1
+ print line2
+ sleep .1
+ print -n 'prompt2: '
+ sleep .1
+) | {
+ read -t2 -n 1000 line1
+ read -t2 -n 1000 line2
+ read -t2 -n 1000 line3
+ read -t2 -n 1000 line4
+}
+[[ $? == 0 ]] && err_exit 'should have timed out'
+[[ $line1 == 'prompt1: ' ]] || err_exit "line1 should be 'prompt1: '"
+[[ $line2 == line2 ]] || err_exit "line2 should be line2"
+[[ $line3 == 'prompt2: ' ]] || err_exit "line3 should be 'prompt2: '"
+[[ ! $line4 ]] || err_exit "line4 should be empty"
+
+if $SHELL -c "export LC_ALL=C.UTF-8; c=$'\342\202\254'; [[ \${#c} == 1 ]]" 2>/dev/null
+then lc_utf8=C.UTF-8
+else lc_utf8=''
+fi
+
+typeset -a e o=(-n2 -N2)
+integer i
+set -- \
+ 'a' 'bcd' 'a bcd' 'ab cd' \
+ 'ab' 'cd' 'ab cd' 'ab cd' \
+ 'abc' 'd' 'ab cd' 'ab cd' \
+ 'abcd' '' 'ab cd' 'ab cd'
+while (( $# >= 3 ))
+do a=$1
+ b=$2
+ e[0]=$3
+ e[1]=$4
+ shift 4
+ for ((i = 0; i < 2; i++))
+ do for lc_all in C $lc_utf8
+ do g=$(LC_ALL=$lc_all $SHELL -c "{ print -n '$a'; sleep 0.2; print -n '$b'; sleep 0.2; } | { read ${o[i]} a; print -n \$a; read a; print -n \ \$a; }")
+ [[ $g == "${e[i]}" ]] || err_exit "LC_ALL=$lc_all read ${o[i]} from pipe '$a $b' failed -- expected '${e[i]}', got '$g'"
+ done
+ done
+done
+
+if [[ $lc_utf8 ]]
+then export LC_ALL=$lc_utf8
+ typeset -a c=( '' 'A' $'\303\274' $'\342\202\254' )
+ integer i w
+ typeset o
+ if (( ${#c[2]} == 1 && ${#c[3]} == 1 ))
+ then for i in 1 2 3
+ do for o in n N
+ do for w in 1 2 3
+ do print -nr "${c[w]}" | read -${o}${i} g
+ if [[ $o == N ]] && (( i > 1 ))
+ then e=''
+ else e=${c[w]}
+ fi
+ [[ $g == "$e" ]] || err_exit "read -${o}${i} failed for '${c[w]}' -- expected '$e', got '$g'"
+ done
+ done
+ done
+ fi
+fi
+
+exec 3<&2
+file=$tmp/file
+redirect 5>$file 2>&5
+print -u5 -f 'This is a test\n'
+print -u2 OK
+exec 2<&3
+exp=$'This is a test\nOK'
+got=$(< $file)
+[[ $got == $exp ]] || err_exit "output garbled when stderr is duped -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+print 'hello world' > $file
+1<>; $file 1># ((5))
+(( $(wc -c < $file) == 5 )) || err_exit "$file was not truncate to 5 bytes"
+
+$SHELL -c "PS4=':2:'
+ exec 1> $tmp/21.out 2> $tmp/22.out
+ set -x
+ printf ':1:A:'
+ print \$(:)
+ print :1:Z:" 1> $tmp/11.out 2> $tmp/12.out
+[[ -s $tmp/11.out ]] && err_exit "standard output leaked past redirection"
+[[ -s $tmp/12.out ]] && err_exit "standard error leaked past redirection"
+exp=$':1:A:\n:1:Z:'
+got=$(<$tmp/21.out)
+[[ $exp == "$got" ]] || err_exit "standard output garbled -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+exp=$':2:printf :1:A:\n:2::\n:2:print\n:2:print :1:Z:'
+got=$(<$tmp/22.out)
+[[ $exp == "$got" ]] || err_exit "standard error garbled -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+
+tmp=$tmp $SHELL 2> /dev/null -c 'exec 3<&1 ; exec 1<&- ; exec > $tmp/outfile;print foobar' || err_exit 'exec 1<&- causes failure'
+[[ $(<$tmp/outfile) == foobar ]] || err_exit 'outfile does not contain foobar'
+
+print hello there world > $tmp/foobar
+sed -e 's/there //' $tmp/foobar >; $tmp/foobar
+[[ $(<$tmp/foobar) == 'hello world' ]] || err_exit '>; redirection not working on simple command'
+print hello there world > $tmp/foobar
+{ sed -e 's/there //' $tmp/foobar;print done;} >; $tmp/foobar
+[[ $(<$tmp/foobar) == $'hello world\ndone' ]] || err_exit '>; redirection not working for compound command'
+print hello there world > $tmp/foobar
+$SHELL -c "sed -e 's/there //' $tmp/foobar >; $tmp/foobar"
+[[ $(<$tmp/foobar) == 'hello world' ]] || err_exit '>; redirection not working with -c on a simple command'
+
+rm -f "$tmp/junk"
+for (( i=1; i < 50; i++ ))
+do out=$(/bin/ls "$tmp/junk" 2>/dev/null)
+ if (( $? == 0 ))
+ then err_exit 'wrong error code with redirection'
+ break
+ fi
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/leaks.sh b/src/cmd/ksh93/tests/leaks.sh
new file mode 100755
index 0000000..8d89b05
--- /dev/null
+++ b/src/cmd/ksh93/tests/leaks.sh
@@ -0,0 +1,68 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+builtin vmstate 2>/dev/null || exit 0
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+# test for variable reset leak #
+
+function test_reset
+{
+ integer i n=$1
+
+ for ((i = 0; i < n; i++))
+ do u=$i
+ done
+}
+
+n=1000
+
+# one round to get to steady state -- sensitive to -x
+
+test_reset $n
+a=0$(vmstate --format='+%(size)u')
+b=0$(vmstate --format='+%(size)u')
+
+test_reset $n
+a=0$(vmstate --format='+%(size)u')
+test_reset $n
+b=0$(vmstate --format='+%(size)u')
+
+if (( b > a ))
+then err_exit "variable value reset memory leak -- $((b-a)) bytes after $n iterations"
+fi
+
+# buffer boundary tests
+
+for exp in 65535 65536
+do got=$($SHELL -c 'x=$(printf "%.*c" '$exp' x); print ${#x}' 2>&1)
+ [[ $got == $exp ]] || err_exit "large command substitution failed -- expected $exp, got $got"
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/locale.sh b/src/cmd/ksh93/tests/locale.sh
new file mode 100755
index 0000000..60209dc
--- /dev/null
+++ b/src/cmd/ksh93/tests/locale.sh
@@ -0,0 +1,319 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+unset LANG ${!LC_*}
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+cd $tmp || exit
+
+a=$($SHELL -c '/' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
+b=$($SHELL -c '(LC_ALL=debug / 2>/dev/null); /' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
+[[ "$b" == "$a" ]] || err_exit "locale not restored after subshell -- expected '$a', got '$b'"
+b=$($SHELL -c '(LC_ALL=debug; / 2>/dev/null); /' 2>&1 | sed -e "s,.*: *,," -e "s, *\[.*,,")
+[[ "$b" == "$a" ]] || err_exit "locale not restored after subshell -- expected '$a', got '$b'"
+
+# test shift-jis \x81\x40 ... \x81\x7E encodings
+# (shift char followed by 7 bit ascii)
+
+typeset -i16 chr
+for locale in $(PATH=/bin:/usr/bin locale -a 2>/dev/null | grep -i jis)
+do export LC_ALL=$locale
+ for ((chr=0x40; chr<=0x7E; chr++))
+ do c=${chr#16#}
+ for s in \\x81\\x$c \\x$c
+ do b="$(printf "$s")"
+ eval n=\$\'$s\'
+ [[ $b == "$n" ]] || err_exit "LC_ALL=$locale printf difference for \"$s\" -- expected '$n', got '$b'"
+ u=$(print -- $b)
+ q=$(print -- "$b")
+ [[ $u == "$q" ]] || err_exit "LC_ALL=$locale quoted print difference for \"$s\" -- $b => '$u' vs \"$b\" => '$q'"
+ done
+ done
+done
+
+# this locale is supported by ast on all platforms
+# EU for { decimal_point="," thousands_sep="." }
+
+locale=C_EU.UTF-8
+
+export LC_ALL=C
+
+# test multibyte value/trace format -- $'\303\274' is UTF-8 u-umlaut
+
+c=$(LC_ALL=C $SHELL -c "printf $':%2s:\n' $'\303\274'")
+u=$(LC_ALL=$locale $SHELL -c "printf $':%2s:\n' $'\303\274'" 2>/dev/null)
+if [[ "$c" != "$u" ]]
+then LC_ALL=$locale
+ x=$'+2+ typeset item.text\
++3+ item.text=\303\274\
++4+ print -- \303\274\
+\303\274\
++5+ eval $\'arr[0]=(\\n\\ttext=\\303\\274\\n)\'
++2+ arr[0].text=ü\
++6+ print -- \303\274\
+ü\
++7+ eval txt=$\'(\\n\\ttext=\\303\\274\\n)\'
++2+ txt.text=\303\274\
++8+ print -- \'(\' text=$\'\\303\\274\' \')\'\
+( text=\303\274 )'
+ u=$(LC_ALL=$locale PS4='+$LINENO+ ' $SHELL -x -c "
+ item=(typeset text)
+ item.text=$'\303\274'
+ print -- \"\${item.text}\"
+ eval \"arr[0]=\$item\"
+ print -- \"\${arr[0].text}\"
+ eval \"txt=\${arr[0]}\"
+ print -- \$txt
+ " 2>&1)
+ [[ "$u" == "$x" ]] || err_exit LC_ALL=$locale multibyte value/trace format failed
+
+ x=$'00fc\n20ac'
+ u=$(LC_ALL=$locale $SHELL -c $'printf "%04x\n" \$\'\"\303\274\"\' \$\'\"\xE2\x82\xAC\"\'')
+ [[ $u == $x ]] || err_exit LC_ALL=$locale multibyte %04x printf format failed
+fi
+
+if (( $($SHELL -c $'export LC_ALL='$locale$'; print -r "\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254" | wc -m' 2>/dev/null) == 10 ))
+then LC_ALL=$locale $SHELL -c b1=$'"\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254"; [[ ${b1:4:1} == w ]]' || err_exit 'multibyte ${var:offset:len} not working correctly'
+fi
+
+#$SHELL -c 'export LANG='$locale'; printf "\u[20ac]\u[20ac]" > $tmp/two_euro_chars.txt'
+printf $'\342\202\254\342\202\254' > $tmp/two_euro_chars.txt
+exp="6 2 6"
+set -- $($SHELL -c "
+ unset LC_CTYPE
+ export LANG=$locale
+ export LC_ALL=C
+ command wc -C < $tmp/two_euro_chars.txt
+ unset LC_ALL
+ command wc -C < $tmp/two_euro_chars.txt
+ export LC_ALL=C
+ command wc -C < $tmp/two_euro_chars.txt
+")
+got=$*
+[[ $got == $exp ]] || err_exit "command wc LC_ALL default failed -- expected '$exp', got '$got'"
+set -- $($SHELL -c "
+ if builtin wc 2>/dev/null || builtin -f cmd wc 2>/dev/null
+ then unset LC_CTYPE
+ export LANG=$locale
+ export LC_ALL=C
+ wc -C < $tmp/two_euro_chars.txt
+ unset LC_ALL
+ wc -C < $tmp/two_euro_chars.txt
+ export LC_ALL=C
+ wc -C < $tmp/two_euro_chars.txt
+ fi
+")
+got=$*
+[[ $got == $exp ]] || err_exit "builtin wc LC_ALL default failed -- expected '$exp', got '$got'"
+
+# multibyte char straddling buffer boundary
+
+{
+ unset i
+ integer i
+ for ((i = 0; i < 163; i++))
+ do print "#234567890123456789012345678901234567890123456789"
+ done
+ printf $'%-.*c\n' 15 '#'
+ for ((i = 0; i < 2; i++))
+ do print $': "\xe5\xae\x9f\xe8\xa1\x8c\xe6\xa9\x9f\xe8\x83\xbd\xe3\x82\x92\xe8\xa1\xa8\xe7\xa4\xba\xe3\x81\x97\xe3\x81\xbe\xe3\x81\x99\xe3\x80\x82" :'
+ done
+} > ko.dat
+
+LC_ALL=$locale $SHELL < ko.dat 2> /dev/null || err_exit "script with multibyte char straddling buffer boundary fails"
+
+# exp LC_ALL LC_NUMERIC LANG
+set -- \
+ 2,5 $locale C '' \
+ 2.5 C $locale '' \
+ 2,5 $locale '' C \
+ 2,5 '' $locale C \
+ 2.5 C '' $locale \
+ 2.5 '' C $locale \
+
+unset a b c
+unset LC_ALL LC_NUMERIC LANG
+integer a b c
+while (( $# >= 4 ))
+do exp=$1
+ unset H V
+ typeset -A H
+ typeset -a V
+ [[ $2 ]] && V[0]="export LC_ALL=$2;"
+ [[ $3 ]] && V[1]="export LC_NUMERIC=$3;"
+ [[ $4 ]] && V[2]="export LANG=$4;"
+ for ((a = 0; a < 3; a++))
+ do for ((b = 0; b < 3; b++))
+ do if (( b != a ))
+ then for ((c = 0; c < 3; c++))
+ do if (( c != a && c != b ))
+ then T=${V[$a]}${V[$b]}${V[$c]}
+ if [[ ! ${H[$T]} ]]
+ then H[$T]=1
+ got=$($SHELL -c "${T}print \$(( $exp ))" 2>&1)
+ [[ $got == $exp ]] || err_exit "${T} sequence failed -- expected '$exp', got '$got'"
+ fi
+ fi
+ done
+ fi
+ done
+ done
+ shift 4
+done
+
+# setocale(LC_ALL,"") after setlocale() initialization
+
+printf 'f1\357\274\240f2\n' > input1
+printf 't2\357\274\240f1\n' > input2
+printf '\357\274\240\n' > delim
+print "export LC_ALL=$locale
+join -j1 1 -j2 2 -o 1.1 -t \$(cat delim) input1 input2 > out" > script
+$SHELL -c 'unset LANG ${!LC_*}; $SHELL ./script' ||
+err_exit "join test script failed -- exit code $?"
+exp="f1"
+got="$(<out)"
+[[ $got == "$exp" ]] || err_exit "LC_ALL test script failed -- expected '$exp', got '$got'"
+
+# multibyte identifiers
+
+exp=OK
+got=$(LC_ALL=C.UTF-8 $SHELL -c $'\u[5929]=OK; print ${\u[5929]}' 2>&1)
+[[ $got == "$exp" ]] || err_exit "multibyte variable definition/expansion failed -- expected '$exp', got '$got'"
+got=$(LC_ALL=C.UTF-8 $SHELL -c $'function \u[5929]\n{\nprint OK;\n}; \u[5929]' 2>&1)
+[[ $got == "$exp" ]] || err_exit "multibyte ksh function definition/execution failed -- expected '$exp', got '$got'"
+got=$(LC_ALL=C.UTF-8 $SHELL -c $'\u[5929]()\n{\nprint OK;\n}; \u[5929]' 2>&1)
+[[ $got == "$exp" ]] || err_exit "multibyte posix function definition/execution failed -- expected '$exp', got '$got'"
+
+# this locale is supported by ast on all platforms
+# mainly used to debug multibyte and message translation code
+# however wctype is not supported but that's ok for these tests
+
+locale=debug
+
+if [[ "$(LC_ALL=$locale $SHELL <<- \+EOF+
+ x=a<1z>b<2yx>c
+ print ${#x}
+ +EOF+)" != 5
+ ]]
+then err_exit '${#x} not working with multibyte locales'
+fi
+
+dir=_not_found_
+exp=2
+for cmd in \
+ "cd $dir; export LC_ALL=debug; cd $dir" \
+ "cd $dir; LC_ALL=debug cd $dir" \
+
+do got=$($SHELL -c "$cmd" 2>&1 | sort -u | wc -l)
+ (( ${got:-0} == $exp )) || err_exit "'$cmd' sequence failed -- error message not localized"
+done
+exp=121
+for lc in LANG LC_MESSAGES LC_ALL
+do for cmd in "($lc=$locale;cd $dir)" "$lc=$locale;cd $dir;unset $lc" "function tst { typeset $lc=$locale;cd $dir; }; tst"
+ do tst="$lc=C;cd $dir;$cmd;cd $dir;:"
+ $SHELL -c "unset LANG \${!LC_*}; $SHELL -c '$tst'" > out 2>&1 ||
+ err_exit "'$tst' failed -- exit status $?"
+ integer id=0
+ unset msg
+ typeset -A msg
+ got=
+ while read -r line
+ do line=${line##*:}
+ if [[ ! ${msg[$line]} ]]
+ then msg[$line]=$((++id))
+ fi
+ got+=${msg[$line]}
+ done < out
+ [[ $got == $exp ]] || err_exit "'$tst' failed -- expected '$exp', got '$got'"
+ done
+done
+
+exp=123
+got=$(LC_ALL=debug $SHELL -c "a<2A@>z=$exp; print \$a<2A@>z")
+[[ $got == $exp ]] || err_exit "multibyte debug locale \$a<2A@>z failed -- expected '$exp', got '$got'"
+
+unset LC_ALL LC_MESSAGES
+export LANG=debug
+function message
+{
+ print -r $"An error occurred."
+}
+exp=$'(libshell,3,46)\nAn error occurred.\n(libshell,3,46)'
+alt=$'(debug,message,libshell,An error occurred.)\nAn error occurred.\n(debug,message,libshell,An error occurred.)'
+got=$(message; LANG=C message; message)
+[[ $got == "$exp" || $got == "$alt" ]] || {
+ EXP=$(printf %q "$exp")
+ ALT=$(printf %q "$alt")
+ GOT=$(printf %q "$got")
+ err_exit "LANG change not seen by function -- expected $EXP or $ALT, got $GOT"
+}
+
+a_thing=fish
+got=$(print -r aa$"\\ahello \" /\\${a_thing}/\\"zz)
+exp='aa(debug,'$Command',libshell,\ahello " /\fish/\)zz'
+[[ $got == "$exp" ]] || err_exit "$\"...\" containing expansions fails: expected $exp, got $got"
+
+exp='(debug,'$Command',libshell,This is a string\n)'
+typeset got=$"This is a string\n"
+[[ $got == "$exp" ]] || err_exit "$\"...\" in assignment expansion fails: expected $exp got $got"
+
+unset LANG
+
+LC_ALL=C
+x=$"hello"
+[[ $x == hello ]] || err_exit 'assignment of message strings not working'
+
+# tests for multibyte characteer at buffer boundary
+{
+ print 'cat << \\EOF'
+ for ((i=1; i < 164; i++))
+ do print 123456789+123456789+123456789+123456789+123456789
+ done
+ print $'next character is multibyte<2b|>c<3d|\>foo'
+ for ((i=1; i < 10; i++))
+ do print 123456789+123456789+123456789+123456789+123456789
+ done
+ print EOF
+} > script$$.1
+chmod +x script$$.1
+x=$( LC_ALL=debug $SHELL ./script$$.1)
+[[ ${#x} == 8641 ]] || err_exit 'here doc contains wrong number of chars with multibyte locale'
+[[ $x == *$'next character is multibyte<2b|>c<3d|\>foo'* ]] || err_exit "here_doc doesn't contain line with multibyte chars"
+
+
+x=$(LC_ALL=debug $SHELL -c 'x="a<2b|>c";print -r -- ${#x}')
+(( x == 3 )) || err_exit 'character length of multibyte character should be 3'
+x=$(LC_ALL=debug $SHELL -c 'typeset -R10 x="a<2b|>c";print -r -- "${x}"')
+[[ $x == ' a<2b|>c' ]] || err_exit 'typeset -R10 should begin with three spaces'
+x=$(LC_ALL=debug $SHELL -c 'typeset -L10 x="a<2b|>c";print -r -- "${x}"')
+[[ $x == 'a<2b|>c ' ]] || err_exit 'typeset -L10 should end in three spaces'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/math.sh b/src/cmd/ksh93/tests/math.sh
new file mode 100644
index 0000000..59884f5
--- /dev/null
+++ b/src/cmd/ksh93/tests/math.sh
@@ -0,0 +1,202 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors < 127 && Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+set -o nounset
+
+typeset tmp
+
+# create temporary test directory
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+cd $tmp || exit
+
+function test_arithmetric_expression_accesss_array_element_through_nameref
+{
+ compound out=( typeset stdout stderr ; integer res )
+ compound -r -a tests=(
+ (
+ cmd='@@TYPE@@ -a @@VAR@@ ; @@VAR@@[1]=90 ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@=( [1]=90 ) ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@ ; @@VAR@@[1][3]=90 ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1][3]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@=( [1][3]=90 ) ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1][3]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@ ; @@VAR@@[1][3][5]=90 ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1][3][5]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@=( [1][3][5]=90 ) ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1][3][5]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -a @@VAR@@ ; @@VAR@@[1][3][5]=90 ; function x { nameref nz=${1}[$2][$3][$4] ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@ 1 3 5' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -A @@VAR@@ ; @@VAR@@[1]=90 ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1]' ; stdoutpattern=' 90==90'
+ )
+ (
+ cmd='@@TYPE@@ -A @@VAR@@=( [1]=90 ) ; function x { nameref nz=$1 ; print " $(( round(nz) ))==$(( round($nz) ))" ; } ; x @@VAR@@[1]' ; stdoutpattern=' 90==90'
+ )
+ )
+
+ typeset testname
+ integer i
+ typeset mode
+ typeset cmd
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ # fixme: This list should include "typeset -lX" and "typeset -X" but ast-ksh.2010-03-09 fails like this:
+ # 'typeset -X -a z ; z[1][3]=90 ; function x { nameref nz=$1 ; print " $(( nz ))==$(( $nz ))" ; } ; x z[1][3]'
+ # + typeset -X -a z
+ # + z[1][3]=90
+ # + x 'z[1][3]'
+ # /home/test001/bin/ksh[1]: x: line 1: x1.68000000000000000000000000000000p: no parent
+ for ty in \
+ 'typeset' \
+ 'integer' \
+ 'float' \
+ 'typeset -i' \
+ 'typeset -si' \
+ 'typeset -li' \
+ 'typeset -E' \
+ 'typeset -F' \
+ 'typeset -X' \
+ 'typeset -lE' \
+ 'typeset -lX' \
+ 'typeset -lF' ; do
+ for mode in \
+ 'plain' \
+ 'in_compound' \
+ 'in_indexed_compound_array' \
+ 'in_2d_indexed_compound_array' \
+ 'in_4d_indexed_compound_array' \
+ 'in_associative_compound_array' \
+ 'in_compound_nameref' \
+ 'in_indexed_compound_array_nameref' \
+ 'in_2d_indexed_compound_array_nameref' \
+ 'in_4d_indexed_compound_array_nameref' \
+ 'in_associative_compound_array_nameref' \
+ ; do
+ nameref tst=tests[i]
+
+ cmd="${tst.cmd//@@TYPE@@/${ty}}"
+
+ case "${mode}" in
+ 'plain')
+ cmd="${cmd//@@VAR@@/z}"
+ ;;
+
+ 'in_compound')
+ cmd="compound c ; ${cmd//@@VAR@@/c.z}"
+ ;;
+ 'in_indexed_compound_array')
+ cmd="compound -a c ; ${cmd//@@VAR@@/c[11].z}"
+ ;;
+ 'in_2d_indexed_compound_array')
+ cmd="compound -a c ; ${cmd//@@VAR@@/c[17][19].z}"
+ ;;
+ 'in_4d_indexed_compound_array')
+ cmd="compound -a c ; ${cmd//@@VAR@@/c[17][19][23][27].z}"
+ ;;
+ 'in_associative_compound_array')
+ cmd="compound -A c ; ${cmd//@@VAR@@/c[info].z}"
+ ;;
+
+ 'in_compound_nameref')
+ cmd="compound c ; nameref ncr=c.z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ 'in_indexed_compound_array_nameref')
+ cmd="compound -a c ; nameref ncr=c[11].z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ 'in_2d_indexed_compound_array_nameref')
+ cmd="compound -a c ; nameref ncr=c[17][19].z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ 'in_4d_indexed_compound_array_nameref')
+ cmd="compound -a c ; nameref ncr=c[17][19][23][27].z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ 'in_associative_compound_array_nameref')
+ cmd="compound -A c ; nameref ncr=c[info].z ; ${cmd//@@VAR@@/ncr}"
+ ;;
+ *)
+ err_exit "Unexpected mode ${mode}"
+ ;;
+ esac
+
+ testname="${0}/${cmd}"
+#set -x
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -o errexit -c "${cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+#set +x
+
+ [[ "${out.stdout}" == ${tst.stdoutpattern} ]] || err_exit "${testname}: Expected stdout to match $(printf '%q\n' "${tst.stdoutpattern}"), got $(printf '%q\n' "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "${testname}: Expected empty stderr, got $(printf '%q\n' "${out.stderr}")"
+ (( out.res == 0 )) || err_exit "${testname}: Unexpected exit code ${out.res}"
+ done
+ done
+ done
+
+ return 0
+}
+
+function test_has_iszero
+{
+ typeset str
+ integer i
+
+ typeset -r -a tests=(
+ '(( iszero(0) )) && print "OK"'
+ '(( iszero(0.) )) && print "OK"'
+ '(( iszero(-0) )) && print "OK"'
+ '(( iszero(-0.) )) && print "OK"'
+ 'float n=0. ; (( iszero(n) )) && print "OK"'
+ 'float n=+0. ; (( iszero(n) )) && print "OK"'
+ 'float n=-0. ; (( iszero(n) )) && print "OK"'
+ 'float n=1. ; (( iszero(n) )) || print "OK"'
+ 'float n=1. ; (( iszero(n-1.) )) && print "OK"'
+ 'float n=-1. ; (( iszero(n+1.) )) && print "OK"'
+ )
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ str="$( ${SHELL} -o errexit -c "${tests[i]}" 2>&1 )" || err_exit "test $i: returned non-zero exit code $?"
+ [[ "${str}" == 'OK' ]] || err_exit "test $i: expected 'OK', got '${str}'"
+ done
+
+ return 0
+}
+
+# run tests
+test_arithmetric_expression_accesss_array_element_through_nameref
+test_has_iszero
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/nameref.sh b/src/cmd/ksh93/tests/nameref.sh
new file mode 100755
index 0000000..7eb0b21
--- /dev/null
+++ b/src/cmd/ksh93/tests/nameref.sh
@@ -0,0 +1,658 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+function checkref
+{
+ nameref foo=$1 bar=$2
+ if [[ $foo != $bar ]]
+ then err_exit "foo=$foo != bar=$bar"
+ fi
+ foo=hello
+ if [[ $foo != $bar ]]
+ then err_exit "foo=$foo != bar=$bar"
+ fi
+ foo.child=child
+ if [[ ${foo.child} != ${bar.child} ]]
+ then err_exit "foo.child=${foo.child} != bar=${bar.child}"
+ fi
+}
+
+name=first
+checkref name name
+name.child=second
+checkref name name
+.foo=top
+.foo.bar=next
+checkref .foo.bar .foo.bar
+if [[ ${.foo.bar} != hello ]]
+then err_exit ".foo.bar=${.foo.bar} != hello"
+fi
+if [[ ${.foo.bar.child} != child ]]
+then err_exit ".foo.bar.child=${.foo.bar.child} != child"
+fi
+function func1
+{
+ nameref color=$1
+ func2 color
+}
+
+function func2
+{
+ nameref color=$1
+ set -s -- ${!color[@]}
+ print -r -- "$@"
+}
+
+typeset -A color
+color[apple]=red
+color[grape]=purple
+color[banana]=yellow
+if [[ $(func1 color) != 'apple banana grape' ]]
+then err_exit "nameref or nameref not working"
+fi
+nameref x=.foo.bar
+if [[ ${!x} != .foo.bar ]]
+then err_exit "${!x} not working"
+fi
+typeset +n x $(typeset +n)
+unset x
+nameref x=.foo.bar
+function x.set
+{
+ [[ ${.sh.value} ]] && print hello
+}
+if [[ $(.foo.bar.set) != $(x.set) ]]
+then err_exit "function references not working"
+fi
+if [[ $(typeset +n) != x ]]
+then err_exit "typeset +n doesn't list names of reference variables"
+fi
+if [[ $(typeset -n) != x=.foo.bar ]]
+then err_exit "typeset +n doesn't list values of reference variables"
+fi
+file=$tmp/test
+typeset +n foo bar 2> /dev/null
+unset foo bar
+export bar=foo
+nameref foo=bar
+if [[ $foo != foo ]]
+then err_exit "value of nameref foo != $foo"
+fi
+cat > $file <<\!
+print -r -- $foo
+!
+chmod +x "$file"
+y=$( $file)
+if [[ $y != '' ]]
+then err_exit "reference variable not cleared"
+fi
+{
+ command nameref xx=yy
+ command nameref yy=xx
+} 2> /dev/null && err_exit "self reference not detected"
+typeset +n foo bar
+unset foo bar
+set foo
+nameref bar=$1
+foo=hello
+if [[ $bar != hello ]]
+then err_exit 'nameref of positional paramters outside of function not working'
+fi
+unset foo bar
+bar=123
+function foobar
+{
+ typeset -n foo=bar
+ typeset -n foo=bar
+}
+foobar 2> /dev/null || err_exit 'nameref not unsetting previous reference'
+(
+ nameref short=verylong
+ short=( A=a B=b )
+ if [[ ${verylong.A} != a ]]
+ then err_exit 'nameref short to longname compound assignment error'
+ fi
+) 2> /dev/null|| err_exit 'nameref short to longname compound assignment error'
+unset x
+if [[ $(var1=1 var2=2
+ for i in var1 var2
+ do nameref x=$i
+ print $x
+ done) != $'1\n2' ]]
+then err_exit 'for loop nameref optimization error'
+fi
+if [[ $(typeset -A var1 var2
+ var1[sub1]=1 var2[sub2]=1
+ for i in var1 var2
+ do
+ typeset -n array=$i
+ print ${!array[*]}
+ done) != $'sub1\nsub2' ]]
+then err_exit 'for loop nameref optimization test2 error'
+fi
+
+unset -n x foo bar
+if [[ $(nameref x=foo;for x in foo bar;do print ${!x};done) != $'foo\nbar' ]]
+then err_exit 'for loop optimization with namerefs not working'
+fi
+if [[ $(
+ p=(x=(r=3) y=(r=4))
+ for i in x y
+ do nameref x=p.$i
+ print ${x.r}
+ done
+) != $'3\n4' ]]
+then err_exit 'nameref optimization error'
+fi
+[[ $(
+unset x y var
+var=(foo=bar)
+for i in y var
+do typeset -n x=$i
+ if [[ ${!x.@} ]]
+ then print ok
+ fi
+ typeset +n x
+done) != ok ]] && err_exit 'invalid for loop optimization of name references'
+function setval # name value
+{
+ nameref arg=$1
+ nameref var=arg.bar
+ var=$2
+}
+foo=( integer bar=0)
+setval foo 5
+(( foo.bar == 5)) || err_exit 'nested nameref not working'
+function selfref
+{
+ typeset -n ps=$1
+ print -r -- "${ps}"
+}
+ps=(a=1 b=2)
+[[ $(selfref ps) == *a=1* ]] || err_exit 'local nameref cannot reference global variable of the same name'
+function subref
+{
+ typeset -n foo=$1
+ print -r -- ${foo.a}
+}
+[[ $(subref ps) == 1 ]] || err_exit 'local nameref cannot reference global variable child'
+
+function local
+{
+ typeset ps=(typeset -i a=3 b=4)
+ [[ $(subref ps) == 3 ]] || err_exit 'local nameref cannot reference caller compound variable'
+}
+local
+unset -f local
+function local
+{
+ qs=(integer a=3; integer b=4)
+}
+local 2> /dev/null || err_exit 'function local has non-zero exit status'
+[[ ${qs.a} == 3 ]] || err_exit 'function cannot set compound global variable'
+unset fun i
+foo=(x=hi)
+function fun
+{
+ nameref i=$1
+ print -r -- "${i.x}"
+}
+i=foo
+[[ $(fun $i) == hi ]] || err_exit 'nameref for compound variable with in function name of caller fails'
+unset -n foo bar
+typeset -A foo
+foo[x.y]=(x=3 y=4)
+nameref bar=foo[x.y]
+[[ ${bar.x} == 3 ]] || err_exit 'nameref to subscript containing . fails'
+[[ ${!bar} == 'foo[x.y]' ]] || err_exit '${!var} not correct for nameref to an array instance'
+typeset +n bar
+nameref bar=foo
+[[ ${!bar} == foo ]] || err_exit '${!var} not correct for nameref to array variable'
+$SHELL -c 'function bar { nameref x=foo[++];};typeset -A foo;bar' 2> /dev/null ||err_exit 'nameref of associative array tries to evaluate subscript'
+i=$($SHELL -c 'nameref foo=bar; bar[2]=(x=3 y=4); nameref x=foo[2].y;print -r -- $x' 2> /dev/null)
+[[ $i == 4 ]] || err_exit 'creating reference from subscripted variable whose name is a reference failed'
+[[ $($SHELL 2> /dev/null <<- '+++EOF'
+ function bar
+ {
+ nameref x=$1
+ print -r -- "$x"
+ }
+ function foo
+ {
+ typeset var=( foo=hello)
+ bar var
+ }
+ foo
++++EOF
+) == *foo=hello* ]] || err_exit 'unable to display compound variable from name reference of local variable'
+#set -x
+for c in '=' '[' ']' '\' "'" '"' '<' '=' '('
+do [[ $($SHELL 2> /dev/null <<- ++EOF++
+ i=\\$c;typeset -A a; a[\$i]=foo;typeset -n x=a[\$i]; print "\$x"
+ ++EOF++
+) != foo ]] && err_exit 'nameref x=a[$c] '"not working for c=$c"
+done
+for c in '=' '[' ']' '\' "'" '"' '<' '=' '('
+do [[ $($SHELL 2> /dev/null <<- ++EOF++
+ i=\\$c;typeset -A a; a[\$i]=foo;b=a[\$i];typeset -n x=\$b; print "\$x"
+ ++EOF++
+) != foo ]] && err_exit 'nameref x=$b with b=a[$c] '"not working for c=$c"
+done
+
+unset -n foo x
+unset foo x
+typeset -A foo
+nameref x=foo[xyz]
+foo[xyz]=ok
+[[ $x == ok ]] || err_exit 'nameref to unset subscript not working'
+function function2
+{
+ nameref v=$1
+ v.x=19 v.y=20
+}
+function function1
+{
+ typeset compound_var=()
+ function2 compound_var
+ printf "x=%d, y=%d\n" compound_var.x compound_var.y
+}
+x="$(function1)"
+[[ "$x" != 'x=19, y=20' ]] && err_exit "expected 'x=19, y=20', got '${x}'"
+typeset +n bar
+unset foo bar
+[[ $(function a
+{
+ for i in foo bar
+ do typeset -n v=$i
+ print $v
+ done | cat
+}
+foo=1 bar=2;a) == $'1\n2' ]] 2> /dev/null || err_exit 'nameref in pipeline broken'
+function a
+{
+ typeset -n v=vars.data._1
+ print "${v.a} ${v.b}"
+}
+vars=(data=())
+vars.data._1.a=a.1
+vars.data._1.b=b.1
+[[ $(a) == 'a.1 b.1' ]] || err_exit 'nameref choosing wrong scope -- '
+typeset +n bam zip foo
+unset bam zip foo
+typeset -A foo
+foo[2]=bar
+typeset -n bam=foo[2]
+typeset -n zip=bam
+[[ $zip == bar ]] || err_exit 'nameref to another nameref to array element fails'
+[[ -R zip ]] || err_exit '[[ -R zip ]] should detect that zip is a reference'
+[[ -R bam ]] || err_exit '[[ -R bam ]] should detect that bam is a reference'
+[[ -R zip ]] || err_exit '[[ -v zip ]] should detect that zip is set'
+[[ -v bam ]] || err_exit '[[ -v bam ]] should detect that bam is set'
+[[ -R 123 ]] && err_exit '[[ -R 123 ]] should detect that 123 is not a reference'
+[[ -v 123 ]] && err_exit '[[ -v 123 ]] should detect that 123 is not set'
+
+unset ref x
+typeset -n ref
+x=3
+function foobar
+{
+ typeset xxx=3
+ ref=xxx
+ return 0
+}
+foobar 2> /dev/null && err_exit 'invalid reference should cause foobar to fail'
+[[ -v ref ]] && err_exit '$ref should be unset'
+ref=x
+[[ $ref == 3 ]] || err_exit "\$ref is $ref, it should be 3"
+function foobar
+{
+ typeset fvar=()
+ typeset -n ref=fvar.foo
+ ref=ok
+ print -r $ref
+}
+[[ $(foobar) == ok ]] 2> /dev/null || err_exit 'nameref in function not creating variable in proper scope'
+function foobar
+{
+ nameref doc=docs
+ nameref bar=doc.num
+ [[ $bar == 2 ]] || err_exit 'nameref scoping error'
+}
+
+docs=(num=2)
+foobar
+
+typeset +n x y
+unset x y
+typeset -A x
+x[a]=(b=c)
+typeset -n y=x[a]
+[[ ${!y.@} == 'x[a].b' ]] || err_exit 'reference to array element not expanded with ${!y.@}'
+
+typeset +n v
+v=()
+k=a.b.c/d
+command typeset -n n=v.${k//['./']/_} 2> /dev/null || err_exit 'patterns with quotes not handled correctly with name reference assignment'
+
+typeset _n sp
+nameref sp=addrsp
+sp[14]=( size=1 )
+[[ -v sp[19] ]] && err_exit '[[ -v sp[19] ]] where sp is a nameref should not be set'
+
+function fun2
+{
+ nameref var=$1
+ var.foo=bar
+}
+
+function fun1
+{
+ compound -S container
+ fun2 container
+ [[ $container == *foo=bar* ]] || err_exit 'name references to static compound variables in parent scope not working'
+}
+fun1
+
+function fun2
+{
+ nameref var=$1
+ var.foo=bar
+}
+
+typeset -T container_t=(
+ typeset foo
+)
+
+function fun1
+{
+ container_t -S container
+ fun2 container
+ [[ $container == *foo=bar* ]] || err_exit 'name references to static type variables in parent scope not working'
+}
+fun1
+
+function fun2
+{
+ nameref var=$1
+ nameref node=var.foo
+ node=bar
+}
+function fun3
+{
+ fun2 container #2> /dev/null
+}
+compound container
+fun3
+[[ $container == *foo=bar* ]] || err_exit 'name reference to a name reference variable in a function not working'
+
+typeset -A x=( [a]=1 )
+nameref c=x[h]
+[[ -v x[h] ]] && err_exit 'creating reference to non-existant associative array element causes element to get added'
+
+unset a
+function x
+{
+ nameref a=a
+ (( $# > 0 )) && typeset -A a
+ a[a b]=${1-99} # this was cauing a syntax on the second call
+}
+x 7
+x 2> /dev/null
+[[ ${a[a b]} == 99 ]] || err_exit 'nameref not handling subscript correctly'
+
+nameref sizes=baz
+typeset -A -i sizes
+sizes[bar]=1
+[[ ${sizes[*]} == 1 ]] || err_exit 'adding -Ai attribute to name referenced variable not working'
+
+$SHELL 2> /dev/null -c 'nameref foo=bar; typeset -A foo; (( (x=foo[a])==0 ))' || err_exit 'references inside arithmetic expressions not working'
+:
+
+unset ar z
+integer -a ar
+nameref z=ar[0]
+(( z[2]=3))
+[[ ${ar[0][2]} == 3 ]] || err_exit "\${ar[0][2]} is '${ar[0][2]}' but should be 3"
+(( ar[0][2] == 3 )) || err_exit "ar[0][2] is '${ar[0][2]}' but should be 3"
+
+unset c x
+typeset +n c x
+compound c=( typeset -a x )
+nameref x=c.x
+x[4]=1
+[[ ${ typeset -p c.x ;} == *-C* ]] && err_exit 'c.x should not have -C attributes'
+
+{ $SHELL 2> /dev/null <<- \EOF
+ typeset -T xxx_t=(
+ float x=1 y=2
+ typeset name=abc
+ )
+ xxx_t x
+ nameref r=x.y
+ [[ $r == 2 ]] || exit 1
+ unset x
+ [[ ${!r} == .deleted ]] || exit 2
+EOF
+} 2> /dev/null #|| print -u2 bad
+exitval=$?
+if [[ $(kill -l $exitval) == SEGV ]]
+then print -u2 'name reference to unset type instance causes segmentation violation'
+else if((exitval))
+ then print -u2 'name reference to unset type instance not redirected to .deleted'
+ fi
+fi
+
+typeset +n nr
+unset c nr
+compound c
+compound -A c.a
+nameref nr=c.a[hello]
+[[ ${!nr} == "c.a[hello]" ]] || err_exit 'name reference nr to unset associative array instance does not expand ${!nr} correctly.'
+
+typeset +n nr
+compound -a c.b
+nameref nr=c.b[2]
+[[ ${!nr} == "c.b[2]" ]] || err_exit 'name reference nr to unset indexed array instance does not expand ${!nr} correctly.'
+
+typeset +n a b
+unset a b
+typeset -n a=ls[0] b=ls[1]
+read line << \!
+3 4
+!
+set -A ls -- $line
+[[ $a == 3 ]] || err_exit 'name reference to ls[0] when ls is not an array fails'
+
+$SHELL 2> /dev/null <<-\EOF || err_exit 'nameref to array element fails'
+ set -o errexit
+ function bf {
+ nameref treename=$1
+ nodepath="treename" ;
+ nameref x="$nodepath"
+ compound -A x.nodes
+ nameref node=treename.nodes[4]
+ node=()
+ typeset +p node.elements
+ }
+ compound c
+ bf c
+EOF
+
+function add_compound
+{
+ nameref arr=$1
+ arr[34]+=( float val=1.1 )
+}
+compound -a rootcpv
+nameref mycpv=rootcpv[4][8][16][32][64]
+compound -a mycpv.myindexedcompoundarray
+add_compound mycpv.myindexedcompoundarray
+(( mycpv.myindexedcompoundarray[34].val == 1.1 )) || err_exit 'nameref scoping error'
+
+function add_file_to_tree
+{
+ nameref node=$1
+ compound -A node.elements
+ node.elements[/]=(filepath=foobar)
+}
+function main
+{
+ compound filetree
+ add_file_to_tree filetree
+}
+main 2> /dev/null
+[[ $? == 0 ]] || err_exit 'nameref binding to calling function compound variable failed'
+
+unset l
+typeset -a -C l
+printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l[4][6]
+exp=$(print -v l)
+unset l
+typeset -a -C l
+nameref l4=l[4]
+printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l4[6]
+[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l4=l[4] not working'
+unset l
+typeset -a -C l
+nameref l46=l[4][6]
+printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | read -C l46
+[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l46=l[4][6] not working'
+
+exp=$'(\n\t[4]=(\n\t\ttypeset -a ar=(\n\t\t\t1\n\t\t\t2\n\t\t)\n\t\tb=1\n\t)\n)'
+unset l
+typeset +n l4
+typeset -a -C l
+nameref l4=l[4]
+printf "( typeset -a ar=( 1\n2\n) b=1 )\n" | read -C l4
+[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l4=l[4] not working with indexed array read'
+
+unset l
+typeset +n l4
+typeset -A -C l
+nameref l4=l[4]
+printf "( typeset -a ar=( 1\n2\n) b=1 )\n" | read -C l4
+[[ $(print -v l) == "$exp" ]] || err_exit 'nameref l4=l[4] not working with associative array read'
+
+exp=$'(\n\t[9]=(\n\t\tfish=4\n\t)\n)'
+function add_eval
+{
+ nameref pos=$1
+ source /dev/stdin <<<"$2"
+ typeset -m pos=addvar
+}
+function do_local_plain
+{
+ compound -A local_tree
+ add_eval local_tree[9].fish "typeset -i addvar=4"
+ [[ $(print -v local_tree) == "$exp" ]] || err_exit 'do_local_plain failed'
+}
+function do_global_throughnameref
+{
+ nameref tr=global_tree
+ add_eval tr[9].fish "typeset -i addvar=4"
+ [[ $(print -v tr) == "$exp" ]] || err_exit 'do_global_throughnameref failed'
+}
+function do_local_throughnameref
+{
+ compound -A local_tree
+ nameref tr=local_tree
+ add_eval tr[9].fish "typeset -i addvar=4"
+ [[ $(print -v tr) == "$exp" ]] || err_exit 'do_local_throughnameref failed'
+}
+compound -A global_tree
+do_global_throughnameref
+do_local_throughnameref
+do_local_plain
+
+unset ar
+compound -a ar
+function read_c
+{
+ nameref v=$1
+ read -C v
+}
+print "( typeset -i x=36 ) " | read_c ar[5][9][2]
+exp=$'(\n\t[5]=(\n\t\t[9]=(\n\t\t\t[2]=(\n\t\t\t\ttypeset -i x=36\n\t\t\t)\n\t\t)\n\t)\n)'
+[[ $(print -v ar) == "$exp" ]] || err_exit 'read into nameref of global array instance from within a function fails'
+
+function read_c
+{
+ nameref v=$1
+ read -C v
+}
+function main
+{
+ compound -a ar
+ nameref nar=ar
+ print "( typeset -i x=36 ) " | read_c nar[5][9][2]
+ exp=$'(\n\t[5]=(\n\t\t[9]=(\n\t\t\t[2]=(\n\t\t\t\ttypeset -i x=36\n\t\t\t)\n\t\t)\n\t)\n)'
+ [[ $(print -v nar) == "$exp" ]] || err_exit 'read from a nameref variable from calling scope fails'
+}
+main
+
+function rf2
+{
+ nameref val=$1
+ read -C val
+}
+function rf
+{
+ nameref val=$1
+ rf2 val
+}
+function main
+{
+ compound c
+ typeset -A -C c.l
+ nameref l4=c.l[4]
+ printf "( typeset -a ar=( 1\n2\n3\n) b=1 )\n" | rf l4
+ exp=$'(\n\ttypeset -C -A l=(\n\t\t[4]=(\n\t\t\ttypeset -a ar=(\n\t\t\t\t1\n\t\t\t\t2\n\t\t\t\t3\n\t\t\t)\n\t\t\tb=1\n\t\t)\n\t)\n)'
+ [[ $(print -v c) == "$exp" ]] || err_exit 'read -C with nameref to array element fails'
+}
+main
+
+# bug reported by ek
+cfg=( alarms=(type=3))
+function a
+{
+ typeset -n y=$1
+ print -- ${y.type}
+}
+function b
+{
+ a $1
+}
+[[ $(a cfg.alarms) == 3 ]] || err_exit "nameref scoping error in function"
+[[ $(b cfg.alarms) == 3 ]] || err_exit "nameref scoping error in nested function"
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/options.sh b/src/cmd/ksh93/tests/options.sh
new file mode 100755
index 0000000..c5b4c2e
--- /dev/null
+++ b/src/cmd/ksh93/tests/options.sh
@@ -0,0 +1,544 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+unset HISTFILE
+export LC_ALL=C ENV=
+
+ulimit -c 0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+if [[ $( ${SHELL-ksh} -s hello<<-\!
+ print $1
+ !
+ ) != hello ]]
+then err_exit "${SHELL-ksh} -s not working"
+fi
+x=$(
+ set -e
+ false && print bad
+ print good
+)
+if [[ $x != good ]]
+then err_exit 'sh -e not working'
+fi
+[[ $($SHELL -D -c 'print hi; print $"hello"') == '"hello"' ]] || err_exit 'ksh -D not working'
+
+env=$tmp/.env
+print $'(print -u1 aha) &>/dev/null\n(print -u2 aha) &>/dev/null' > $env
+rc=$tmp/.kshrc
+print $'PS1=""\nfunction env_hit\n{\n\tprint OK\n}' > $rc
+
+export ENV=/.$env
+if [[ ! -o privileged ]]
+then
+ got=$($SHELL -E -c : 2>/dev/null)
+ if [[ $g ]]
+ then
+ got=$(printf %q "$got")
+ err_exit "\$ENV file &>/dev/null does not redirect stdout -- expected '', got $got"
+ fi
+ got=$($SHELL -E -c : 2>&1 >/dev/null)
+ if [[ $got != *nonstandard* || $got == *$'\n'* ]]
+ then
+ got=$(printf %q "$got")
+ err_exit "\$ENV file &>/dev/null does not redirect stderr -- expected one diagnostic line, got $got"
+ fi
+fi
+
+export ENV=/.$rc
+if [[ -o privileged ]]
+then
+ [[ $(print env_hit | $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'privileged nointeractive shell reads $ENV file'
+ [[ $(print env_hit | $SHELL -E 2>&1) == "OK" ]] &&
+ err_exit 'privileged -E reads $ENV file'
+ [[ $(print env_hit | $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit 'privileged +E reads $ENV file'
+ [[ $(print env_hit | $SHELL --rc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --rc reads $ENV file'
+ [[ $(print env_hit | $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --norc reads $ENV file'
+else
+ [[ $(print env_hit | $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'nointeractive shell reads $ENV file'
+ [[ $(print env_hit | $SHELL -E 2>&1) == "OK" ]] ||
+ err_exit '-E ignores $ENV file'
+ [[ $(print env_hit | $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit '+E reads $ENV file'
+ [[ $(print env_hit | $SHELL --rc 2>&1) == "OK" ]] ||
+ err_exit '--rc ignores $ENV file'
+ [[ $(print env_hit | $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit '--norc reads $ENV file'
+ [[ $(print env_hit | $SHELL -i 2>&1) == "OK" ]] ||
+ err_exit '-i ignores $ENV file'
+fi
+
+export ENV=
+if [[ -o privileged ]]
+then
+ [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'privileged nointeractive shell reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] &&
+ err_exit 'privileged -E ignores empty $ENV'
+ [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit 'privileged +E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --rc ignores empty $ENV'
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --norc reads $HOME/.kshrc file'
+else
+ [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'nointeractive shell reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] &&
+ err_exit '-E ignores empty $ENV'
+ [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit '+E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] &&
+ err_exit '--rc ignores empty $ENV'
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit '--norc reads $HOME/.kshrc file'
+fi
+
+unset ENV
+if [[ -o privileged ]]
+then
+ [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'privileged nointeractive shell reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] &&
+ err_exit 'privileged -E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit 'privileged +E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --rc reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit 'privileged --norc reads $HOME/.kshrc file'
+else
+ [[ $(print env_hit | HOME=$tmp $SHELL 2>&1) == "OK" ]] &&
+ err_exit 'nointeractive shell reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL -E 2>&1) == "OK" ]] ||
+ err_exit '-E ignores $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL +E 2>&1) == "OK" ]] &&
+ err_exit '+E reads $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --rc 2>&1) == "OK" ]] ||
+ err_exit '--rc ignores $HOME/.kshrc file'
+ [[ $(print env_hit | HOME=$tmp $SHELL --norc 2>&1) == "OK" ]] &&
+ err_exit '--norc reads $HOME/.kshrc file'
+fi
+
+rm -rf $tmp/.kshrc
+
+if command set -G 2> /dev/null
+then cd $tmp
+ mkdir bar foo
+ > bar.c > bam.c
+ > bar/foo.c > bar/bam.c
+ > foo/bam.c
+ set -- **.c
+ expected='bam.c bar.c'
+ [[ $* == $expected ]] ||
+ err_exit "-G **.c failed -- expected '$expected', got '$*'"
+ set -- **
+ expected='bam.c bar bar.c bar/bam.c bar/foo.c foo foo/bam.c'
+ [[ $* == $expected ]] ||
+ err_exit "-G ** failed -- expected '$expected', got '$*'"
+ set -- **/*.c
+ expected='bam.c bar.c bar/bam.c bar/foo.c foo/bam.c'
+ [[ $* == $expected ]] ||
+ err_exit "-G **/*.c failed -- expected '$expected', got '$*'"
+ set -- **/bam.c
+ expected='bam.c bar/bam.c foo/bam.c'
+ [[ $* == $expected ]] ||
+ err_exit "-G **/bam.c failed -- expected '$expected', got '$*'"
+ cd ~-
+fi
+
+cd $tmp
+t="<$$>.profile.<$$>"
+echo "echo '$t'" > .profile
+cp $SHELL ./-ksh
+if [[ -o privileged ]]
+then
+ [[ $(HOME=$PWD $SHELL -l </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged -l reads .profile'
+ [[ $(HOME=$PWD $SHELL --login </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged --login reads .profile'
+ [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged --login-shell reads .profile'
+ [[ $(HOME=$PWD $SHELL --login_shell </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged --login_shell reads .profile'
+ [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged exec -a -ksh ksh reads .profile'
+ [[ $(HOME=$PWD ./-ksh -i </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged ./-ksh reads .profile'
+ [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>&1) == *$t* ]] &&
+ err_exit 'privileged ./-ksh -p reads .profile'
+else
+ [[ $(HOME=$PWD $SHELL -l </dev/null 2>&1) == *$t* ]] ||
+ err_exit '-l ignores .profile'
+ [[ $(HOME=$PWD $SHELL --login </dev/null 2>&1) == *$t* ]] ||
+ err_exit '--login ignores .profile'
+ [[ $(HOME=$PWD $SHELL --login-shell </dev/null 2>&1) == *$t* ]] ||
+ err_exit '--login-shell ignores .profile'
+ [[ $(HOME=$PWD $SHELL --login_shell </dev/null 2>&1) == *$t* ]] ||
+ err_exit '--login_shell ignores .profile'
+ [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>/dev/null) == *$t* ]] ||
+ err_exit 'exec -a -ksh ksh 2>/dev/null ignores .profile'
+ [[ $(HOME=$PWD exec -a -ksh $SHELL </dev/null 2>&1) == *$t* ]] ||
+ err_exit 'exec -a -ksh ksh 2>&1 ignores .profile'
+ [[ $(HOME=$PWD ./-ksh -i </dev/null 2>&1) == *$t* ]] ||
+ err_exit './-ksh ignores .profile'
+ [[ $(HOME=$PWD ./-ksh -ip </dev/null 2>&1) == *$t* ]] &&
+ err_exit './-ksh -p does not ignore .profile'
+fi
+cd ~-
+rm -rf $tmp/.profile
+
+# { exec interactive login_shell restricted xtrace } in the following test
+
+for opt in \
+ allexport all-export all_export \
+ bgnice bg-nice bg_nice \
+ clobber emacs \
+ errexit err-exit err_exit \
+ glob \
+ globstar glob-star glob_star \
+ gmacs \
+ ignoreeof ignore-eof ignore_eof \
+ keyword log markdirs monitor notify \
+ pipefail pipe-fail pipe_fail \
+ trackall track-all track_all \
+ unset verbose vi \
+ viraw vi-raw vi_raw
+do old=$opt
+ if [[ ! -o $opt ]]
+ then old=no$opt
+ fi
+
+ set --$opt || err_exit "set --$opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ [[ -o no$opt ]] && err_exit "[[ -o no$opt ]] failed"
+ [[ -o no-$opt ]] && err_exit "[[ -o no-$opt ]] failed"
+ [[ -o no_$opt ]] && err_exit "[[ -o no_$opt ]] failed"
+ [[ -o ?$opt ]] || err_exit "[[ -o ?$opt ]] failed"
+ [[ -o ?no$opt ]] || err_exit "[[ -o ?no$opt ]] failed"
+ [[ -o ?no-$opt ]] || err_exit "[[ -o ?no-$opt ]] failed"
+ [[ -o ?no_$opt ]] || err_exit "[[ -o ?no_$opt ]] failed"
+
+ set --no$opt || err_exit "set --no$opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed"
+
+ set --no-$opt || err_exit "set --no-$opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed"
+
+ set --no_$opt || err_exit "set --no_$opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ [[ -o $opt ]] && err_exit "[[ -o $opt ]] failed"
+
+ set -o $opt || err_exit "set -o $opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ set -o $opt=1 || err_exit "set -o $opt=1 failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ set -o no$opt=0 || err_exit "set -o no$opt=0 failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ set --$opt=1 || err_exit "set --$opt=1 failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+ set --no$opt=0 || err_exit "set --no$opt=0 failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+
+ set -o no$opt || err_exit "set -o no$opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ set -o $opt=0 || err_exit "set -o $opt=0 failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ set -o no$opt=1 || err_exit "set -o no$opt=1 failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ set --$opt=0 || err_exit "set --$opt=0 failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+ set --no$opt=1 || err_exit "set --no$opt=1 failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+
+ set -o no-$opt || err_exit "set -o no-$opt failed"
+ [[ -o no-$opt ]] || err_exit "[[ -o no-$opt ]] failed"
+
+ set -o no_$opt || err_exit "set -o no_$opt failed"
+ [[ -o no_$opt ]] || err_exit "[[ -o no_$opt ]] failed"
+
+ set +o $opt || err_exit "set +o $opt failed"
+ [[ -o no$opt ]] || err_exit "[[ -o no$opt ]] failed"
+
+ set +o no$opt || err_exit "set +o no$opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+
+ set +o no-$opt || err_exit "set +o no-$opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+
+ set +o no_$opt || err_exit "set +o no_$opt failed"
+ [[ -o $opt ]] || err_exit "[[ -o $opt ]] failed"
+
+ set --$old
+done
+
+for opt in \
+ exec interactive login_shell login-shell logi privileged \
+ rc restricted xtrace
+do [[ -o $opt ]]
+ y=$?
+ [[ -o no$opt ]]
+ n=$?
+ case $y$n in
+ 10|01) ;;
+ *) err_exit "[[ -o $opt ]] == [[ -o no$opt ]]" ;;
+ esac
+done
+
+for opt in \
+ foo foo-bar foo_bar
+do if [[ -o ?$opt ]]
+ then err_exit "[[ -o ?$opt ]] should fail"
+ fi
+ if [[ -o ?no$opt ]]
+ then err_exit "[[ -o ?no$opt ]] should fail"
+ fi
+done
+
+[[ $(set +o) == $(set --state) ]] || err_exit "set --state different from set +o"
+set -- $(set --state)
+[[ $1 == set && $2 == --default ]] || err_exit "set --state failed -- expected 'set --default *', got '$1 $2 *'"
+shift
+restore=$*
+shift
+off=
+for opt
+do case $opt in
+ --not*) opt=${opt/--/--no} ;;
+ --no*) opt=${opt/--no/--} ;;
+ --*) opt=${opt/--/--no} ;;
+ esac
+ off="$off $opt"
+done
+set $off
+state=$(set --state)
+default=$(set --default --state)
+[[ $state == $default ]] || err_exit "set --state for default options failed: expected '$default', got '$state'"
+set $restore
+state=$(set --state)
+[[ $state == "set $restore" ]] || err_exit "set --state after restore failed: expected 'set $restore', got '$state'"
+
+typeset -a pipeline
+pipeline=(
+ ( nopipefail=0 pipefail=1 command='false|true|true' )
+ ( nopipefail=0 pipefail=1 command='true|false|true' )
+ ( nopipefail=1 pipefail=1 command='true|true|false' )
+ ( nopipefail=1 pipefail=1 command='false|false|false' )
+ ( nopipefail=0 pipefail=0 command='true|true|true' )
+ ( nopipefail=0 pipefail=0 command='print hi|(sleep 1;/bin/cat)>/dev/null' )
+)
+set --nopipefail
+for ((i = 0; i < ${#pipeline[@]}; i++ ))
+do eval ${pipeline[i].command}
+ status=$?
+ expected=${pipeline[i].nopipefail}
+ [[ $status == $expected ]] ||
+ err_exit "--nopipefail '${pipeline[i].command}' exit status $status -- expected $expected"
+done
+ftt=0
+set --pipefail
+for ((i = 0; i < ${#pipeline[@]}; i++ ))
+do eval ${pipeline[i].command}
+ status=$?
+ expected=${pipeline[i].pipefail}
+ if [[ $status != $expected ]]
+ then err_exit "--pipefail '${pipeline[i].command}' exit status $status -- expected $expected"
+ (( i == 0 )) && ftt=1
+ fi
+done
+if (( ! ftt ))
+then exp=10
+ got=$(for((n=1;n<exp;n++))do $SHELL --pipefail -c '(sleep 0.1;false)|true|true' && break; done; print $n)
+ [[ $got == $exp ]] || err_exit "--pipefail -c '(sleep 0.1;false)|true|true' fails with exit status 0 (after $got/$exp iterations)"
+fi
+
+echo=$(whence -p echo)
+for ((i=0; i < 20; i++))
+do if ! x=$(true | $echo 123)
+ then err_exit 'command substitution with wrong exit status with pipefai'
+ break
+ fi
+done
+(
+ set -o pipefail
+ false | true
+ (( $? )) || err_exit 'pipe not failing in subshell with pipefail'
+) | wc >/dev/null
+$SHELL -c 'set -o pipefail; false | $(whence -p true);' && err_exit 'pipefail not returning failure with sh -c'
+exp='1212 or 1221'
+got=$(
+ set --pipefail
+ pipe() { date | cat > /dev/null ;}
+ print $'1\n2' |
+ while read i
+ do if pipe $tmp
+ then { print -n $i; sleep 2; print -n $i; } &
+ fi
+ done
+ wait
+)
+[[ $got == @((12|21)(12|21)) ]] || err_exit "& job delayed by --pipefail, expected '$exp', got '$got'"
+$SHELL -c '[[ $- == *c* ]]' || err_exit 'option c not in $-'
+> $tmp/.profile
+for i in i l r s D E a b e f h k n t u v x B C G H
+do HOME=$tmp ENV= $SHELL -$i >/dev/null 2>&1 <<- ++EOF++ || err_exit "option $i not in \$-"
+ [[ \$- == *$i* ]] || exit 1
+ ++EOF++
+done
+letters=ilrabefhknuvxBCGE
+integer j=0
+for i in interactive login restricted allexport notify errexit \
+ noglob trackall keyword noexec nounset verbose xtrace braceexpand \
+ noclobber globstar rc
+do HOME=$tmp ENV= $SHELL -o $i >/dev/null 2>&1 <<- ++EOF++ || err_exit "option $i not equivalent to ${letters:j:1}"
+ [[ \$- == *${letters:j:1}* ]] || exit 1
+ ++EOF++
+ ((j++))
+done
+
+export ENV= PS1="(:$$:)"
+histfile=$tmp/history
+exp=$(HISTFILE=$histfile $SHELL -c $'function foo\n{\ncat\n}\ntype foo')
+for var in HISTSIZE HISTFILE
+do got=$( ( HISTFILE=$histfile $SHELL +E -ic $'unset '$var$'\nfunction foo\n{\ncat\n}\ntype foo\nexit' ) 2>&1 )
+ got=${got##*"$PS1"}
+ [[ $got == "$exp" ]] || err_exit "function definition inside (...) with $var unset fails -- got '$got', expected '$exp'"
+ got=$( { HISTFILE=$histfile $SHELL +E -ic $'unset '$var$'\nfunction foo\n{\ncat\n}\ntype foo\nexit' ;} 2>&1 )
+ got=${got##*"$PS1"}
+ [[ $got == "$exp" ]] || err_exit "function definition inside {...;} with $var unset fails -- got '$got', expected '$exp'"
+done
+( unset HISTFILE; $SHELL -ic "HISTFILE=$histfile" 2>/dev/null ) || err_exit "setting HISTFILE when not in environment fails"
+
+# the next tests loop on all combinations of
+# { SUB PAR CMD ADD }
+
+SUB=(
+ ( BEG='$( ' END=' )' )
+ ( BEG='${ ' END='; }' )
+)
+PAR=(
+ ( BEG='( ' END=' )' )
+ ( BEG='{ ' END='; }' )
+)
+CMD=( command-kill script-kill )
+ADD=( '' '; :' )
+
+cd $tmp
+print $'#!'$SHELL$'\nkill -KILL $$' > command-kill
+print $'kill -KILL $$' > script-kill
+chmod +x command-kill script-kill
+export PATH=.:$PATH
+exp='Killed'
+for ((S=0; S<${#SUB[@]}; S++))
+do for ((P=0; P<${#PAR[@]}; P++))
+ do for ((C=0; C<${#CMD[@]}; C++))
+ do for ((A=0; A<${#ADD[@]}; A++))
+ do cmd="${SUB[S].BEG}${PAR[P].BEG}${CMD[C]}${PAR[P].END} 2>&1${ADD[A]}${SUB[S].END}"
+ eval got="$cmd"
+ got=${got##*': '}
+ got=${got%%'('*}
+ [[ $got == "$exp" ]] || err_exit "$cmd failed -- got '$got', expected '$exp'"
+ done
+ done
+ done
+done
+
+$SHELL 2> /dev/null -c '{; true ;}' || err_exit 'leading ; causes syntax error in brace group'
+$SHELL 2> /dev/null -c '(; true ;)' || err_exit 'leading ; causes syntax error in parenthesis group'
+
+print 'for ((i = 0; i < ${1:-10000}; i++ )); do printf "%.*c\n" 15 x; done' > pipefail
+chmod +x pipefail
+$SHELL --pipefail -c './pipefail 10000 | sed 1q' >/dev/null 2>&1 &
+tst=$!
+{ sleep 4; kill $tst; } 2>/dev/null &
+spy=$!
+wait $tst 2>/dev/null
+status=$?
+if [[ $status == 0 || $(kill -l $status) == PIPE ]]
+then kill $spy 2>/dev/null
+else err_exit "pipefail pipeline bypasses SIGPIPE and hangs"
+fi
+wait
+
+[[ $($SHELL -uc '[[ "${d1.u[z asd].revents}" ]]' 2>&1) == *'d1.u[z asd].revents'* ]] || err_exit 'name of unset parameter not in error message'
+
+[[ $($SHELL 2> /dev/null -xc $'set --showme\nprint 1\n; print 2') == 1 ]] || err_exit 'showme option with xtrace not working correctly'
+
+$SHELL -uc 'var=foo;unset var;: ${var%foo}' >/dev/null 2>&1 && err_exit '${var%foo} should fail with set -u'
+$SHELL -uc 'var=foo;unset var;: ${!var}' >/dev/null 2>&1 && err_exit '${!var} should fail with set -u'
+$SHELL -uc 'var=foo;unset var;: ${#var}' >/dev/null 2>&1 && err_exit '${#var} should fail with set -u'
+$SHELL -uc 'var=foo;unset var;: ${var-OK}' >/dev/null 2>&1 || err_exit '${var-OK} should not fail with set -u'
+$SHELL -uc 'var=foo;nset var;: ${var:-OK}' >/dev/null 2>&1 || err_exit '${var:-OK} should not fail with set -u'
+
+z=$($SHELL 2>&1 -uc 'print ${X23456789012345}')
+[[ $z == *X23456789012345:* ]] || err_exit "error message garbled with set -u got $z"
+
+# pipe hang bug fixed 2011-03-15
+float start=SECONDS toolong=3
+( $SHELL <<-EOF
+ set -o pipefail
+ (sleep $toolong;kill \$\$> /dev/null) &
+ cat $SHELL | for ((i=0; i < 5; i++))
+ do
+ date | wc > /dev/null
+ $SHELL -c 'read -N1'
+ done
+EOF
+) 2> /dev/null
+(( (SECONDS-start) > (toolong-0.5) )) && err_exit "pipefail causes script to hang"
+
+# showme with arithmetic for loops
+$SHELL -n -c $'for((;1;))\ndo ; nothing\ndone' 2>/dev/null || err_exit 'showme commands give syntax error inside arithmetic for loops'
+
+#set -x
+float t1=SECONDS
+set -o pipefail
+print | while read
+do if { date | true;} ; true
+ then sleep 2 &
+ fi
+done
+(( (SECONDS-t1) > .5 )) && err_exit 'pipefail should not wait for background processes'
+
+# process source files from profiles as profile files
+print '. ./dotfile' > envfile
+print $'alias print=:\nprint foobar' > dotfile
+[[ $(ENV=$PWD/envfile $SHELL -i -c : 2>/dev/null) == foobar ]] && err_exit 'files source from profile does not process aliases correctly'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/path.sh b/src/cmd/ksh93/tests/path.sh
new file mode 100755
index 0000000..3fd16e9
--- /dev/null
+++ b/src/cmd/ksh93/tests/path.sh
@@ -0,0 +1,375 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+cd $tmp || exit
+type /xxxxxx > out1 2> out2
+[[ -s out1 ]] && err_exit 'type should not write on stdout for not found case'
+[[ -s out2 ]] || err_exit 'type should write on stderr for not found case'
+mkdir dir1 dir2
+cat > dir1/foobar << '+++'
+foobar() { print foobar1;}
+function dir1 { print dir1;}
++++
+cat > dir2/foobar << '+++'
+foobar() { print foobar2;}
+function dir2 { print dir2;}
++++
+chmod +x dir[12]/foobar
+p=$PATH
+FPATH=$PWD/dir1
+PATH=$FPATH:$p
+[[ $( foobar) == foobar1 ]] || err_exit 'foobar should output foobar1'
+FPATH=$PWD/dir2
+PATH=$FPATH:$p
+[[ $(foobar) == foobar2 ]] || err_exit 'foobar should output foobar2'
+FPATH=$PWD/dir1
+PATH=$FPATH:$p
+[[ $(foobar) == foobar1 ]] || err_exit 'foobar should output foobar1 again'
+FPATH=$PWD/dir2
+PATH=$FPATH:$p
+[[ ${ foobar;} == foobar2 ]] || err_exit 'foobar should output foobar2 with ${}'
+[[ ${ dir2;} == dir2 ]] || err_exit 'should be dir2'
+[[ ${ dir1;} == dir1 ]] 2> /dev/null && err_exit 'should not be be dir1'
+FPATH=$PWD/dir1
+PATH=$FPATH:$p
+[[ ${ foobar;} == foobar1 ]] || err_exit 'foobar should output foobar1 with ${}'
+[[ ${ dir1;} == dir1 ]] || err_exit 'should be dir1'
+[[ ${ dir2;} == dir2 ]] 2> /dev/null && err_exit 'should not be be dir2'
+FPATH=$PWD/dir2
+PATH=$FPATH:$p
+[[ ${ foobar;} == foobar2 ]] || err_exit 'foobar should output foobar2 with ${} again'
+PATH=$p
+(PATH="/bin")
+[[ $($SHELL -c 'print -r -- "$PATH"') == "$PATH" ]] || err_exit 'export PATH lost in subshell'
+cat > bug1 <<- EOF
+ print print ok > $tmp/ok
+ /bin/chmod 755 $tmp/ok
+ function a
+ {
+ typeset -x PATH=$tmp
+ ok
+ }
+ path=\$PATH
+ unset PATH
+ a
+ PATH=\$path
+}
+EOF
+[[ $($SHELL ./bug1 2>/dev/null) == ok ]] || err_exit "PATH in function not working"
+cat > bug1 <<- \EOF
+ function lock_unlock
+ {
+ typeset PATH=/usr/bin
+ typeset -x PATH=''
+ }
+
+ PATH=/usr/bin
+ : $(PATH=/usr/bin getconf PATH)
+ typeset -ft lock_unlock
+ lock_unlock
+EOF
+($SHELL ./bug1) 2> /dev/null || err_exit "path_delete bug"
+mkdir tdir
+if $SHELL tdir > /dev/null 2>&1
+then err_exit 'not an error to run ksh on a directory'
+fi
+
+print 'print hi' > ls
+if [[ $($SHELL ls 2> /dev/null) != hi ]]
+then err_exit "$SHELL name not executing version in current directory"
+fi
+if [[ $(ls -d . 2>/dev/null) == . && $(PATH=/bin:/usr/bin:$PATH ls -d . 2>/dev/null) != . ]]
+then err_exit 'PATH export in command substitution not working'
+fi
+pwd=$PWD
+# get rid of leading and trailing : and trailing :.
+PATH=${PATH%.}
+PATH=${PATH%:}
+PATH=${PATH#.}
+PATH=${PATH#:}
+path=$PATH
+var=$(whence date)
+dir=$(basename "$var")
+for i in 1 2 3 4 5 6 7 8 9 0
+do if ! whence notfound$i 2> /dev/null
+ then cmd=notfound$i
+ break
+ fi
+done
+print 'print hello' > date
+chmod +x date
+print 'print notfound' > $cmd
+chmod +x "$cmd"
+> foo
+chmod 755 foo
+for PATH in $path :$path $path: .:$path $path: $path:. $PWD::$path $PWD:.:$path $path:$PWD $path:.:$PWD
+do
+# print path=$PATH $(whence date)
+# print path=$PATH $(whence "$cmd")
+ date
+ "$cmd"
+done > /dev/null 2>&1
+builtin -d date 2> /dev/null
+if [[ $(PATH=:/usr/bin; date) != 'hello' ]]
+then err_exit "leading : in path not working"
+fi
+(
+ PATH=$PWD:
+ builtin chmod
+ print 'print cannot execute' > noexec
+ chmod 644 noexec
+ if [[ ! -x noexec ]]
+ then noexec > /dev/null 2>&1
+ else exit 126
+ fi
+)
+status=$?
+[[ $status == 126 ]] || err_exit "exit status of non-executable is $status -- 126 expected"
+builtin -d rm 2> /dev/null
+chmod=$(whence chmod)
+rm=$(whence rm)
+d=$(dirname "$rm")
+
+chmod=$(whence chmod)
+
+for cmd in date foo
+do exp="$cmd found"
+ print print $exp > $cmd
+ $chmod +x $cmd
+ got=$($SHELL -c "unset FPATH; PATH=/dev/null; $cmd" 2>&1)
+ [[ $got == $exp ]] && err_exit "$cmd as last command should not find ./$cmd with PATH=/dev/null"
+ got=$($SHELL -c "unset FPATH; PATH=/dev/null; $cmd" 2>&1)
+ [[ $got == $exp ]] && err_exit "$cmd should not find ./$cmd with PATH=/dev/null"
+ exp=$PWD/./$cmd
+ got=$(unset FPATH; PATH=/dev/null; whence ./$cmd)
+ [[ $got == $exp ]] || err_exit "whence $cmd should find ./$cmd with PATH=/dev/null"
+ exp=$PWD/$cmd
+ got=$(unset FPATH; PATH=/dev/null; whence $PWD/$cmd)
+ [[ $got == $exp ]] || err_exit "whence \$PWD/$cmd should find ./$cmd with PATH=/dev/null"
+done
+
+exp=''
+got=$($SHELL -c "unset FPATH; PATH=/dev/null; whence ./notfound" 2>&1)
+[[ $got == $exp ]] || err_exit "whence ./$cmd failed -- expected '$exp', got '$got'"
+got=$($SHELL -c "unset FPATH; PATH=/dev/null; whence $PWD/notfound" 2>&1)
+[[ $got == $exp ]] || err_exit "whence \$PWD/$cmd failed -- expected '$exp', got '$got'"
+
+unset FPATH
+PATH=/dev/null
+for cmd in date foo
+do exp="$cmd found"
+ print print $exp > $cmd
+ $chmod +x $cmd
+ got=$($cmd 2>&1)
+ [[ $got == $exp ]] && err_exit "$cmd as last command should not find ./$cmd with PATH=/dev/null"
+ got=$($cmd 2>&1; :)
+ [[ $got == $exp ]] && err_exit "$cmd should not find ./$cmd with PATH=/dev/null"
+ exp=$PWD/./$cmd
+ got=$(whence ./$cmd)
+ [[ $got == $exp ]] || err_exit "whence ./$cmd should find ./$cmd with PATH=/dev/null"
+ exp=$PWD/$cmd
+ got=$(whence $PWD/$cmd)
+ [[ $got == $exp ]] || err_exit "whence \$PWD/$cmd should find ./$cmd with PATH=/dev/null"
+done
+exp=''
+got=$(whence ./notfound)
+[[ $got == $exp ]] || err_exit "whence ./$cmd failed -- expected '$exp', got '$got'"
+got=$(whence $PWD/notfound)
+[[ $got == $exp ]] || err_exit "whence \$PWD/$cmd failed -- expected '$exp', got '$got'"
+
+PATH=$d:
+cp "$rm" kshrm
+if [[ $(whence kshrm) != $PWD/kshrm ]]
+then err_exit 'trailing : in pathname not working'
+fi
+cp "$rm" rm
+PATH=:$d
+if [[ $(whence rm) != $PWD/rm ]]
+then err_exit 'leading : in pathname not working'
+fi
+PATH=$d: whence rm > /dev/null
+if [[ $(whence rm) != $PWD/rm ]]
+then err_exit 'pathname not restored after scoping'
+fi
+mkdir bin
+print 'print ok' > bin/tst
+chmod +x bin/tst
+if [[ $(PATH=$PWD/bin tst 2>/dev/null) != ok ]]
+then err_exit '(PATH=$PWD/bin foo) does not find $PWD/bin/foo'
+fi
+cd /
+if whence ls > /dev/null
+then PATH=
+ if [[ $(whence rm) ]]
+ then err_exit 'setting PATH to Null not working'
+ fi
+ unset PATH
+ if [[ $(whence rm) != /*rm ]]
+ then err_exit 'unsetting path not working'
+ fi
+fi
+PATH=/dev:$tmp
+x=$(whence rm)
+typeset foo=$(PATH=/xyz:/abc :)
+y=$(whence rm)
+[[ $x != "$y" ]] && err_exit 'PATH not restored after command substitution'
+whence getconf > /dev/null && err_exit 'getconf should not be found'
+builtin /bin/getconf
+PATH=/bin
+PATH=$(getconf PATH)
+x=$(whence ls)
+PATH=.:$PWD:${x%/ls}
+[[ $(whence ls) == "$x" ]] || err_exit 'PATH search bug when .:$PWD in path'
+PATH=$PWD:.:${x%/ls}
+[[ $(whence ls) == "$x" ]] || err_exit 'PATH search bug when :$PWD:. in path'
+cd "${x%/ls}"
+[[ $(whence ls) == /* ]] || err_exit 'whence not generating absolute pathname'
+status=$($SHELL -c $'trap \'print $?\' EXIT;/xxx/a/b/c/d/e 2> /dev/null')
+[[ $status == 127 ]] || err_exit "not found command exit status $status -- expected 127"
+status=$($SHELL -c $'trap \'print $?\' EXIT;/dev/null 2> /dev/null')
+[[ $status == 126 ]] || err_exit "non executable command exit status $status -- expected 126"
+status=$($SHELL -c $'trap \'print $?\' ERR;/xxx/a/b/c/d/e 2> /dev/null')
+[[ $status == 127 ]] || err_exit "not found command with ERR trap exit status $status -- expected 127"
+status=$($SHELL -c $'trap \'print $?\' ERR;/dev/null 2> /dev/null')
+[[ $status == 126 ]] || err_exit "non executable command ERR trap exit status $status -- expected 126"
+
+# universe via PATH
+
+builtin getconf
+getconf UNIVERSE - att # override sticky default 'UNIVERSE = foo'
+
+[[ $(PATH=/usr/ucb/bin:/usr/bin echo -n ucb) == 'ucb' ]] || err_exit "ucb universe echo ignores -n option"
+[[ $(PATH=/usr/xpg/bin:/usr/bin echo -n att) == '-n att' ]] || err_exit "att universe echo does not ignore -n option"
+
+PATH=$path
+
+scr=$tmp/script
+exp=126
+
+: > $scr
+chmod a=x $scr
+{ got=$($scr; print $?); } 2>/dev/null
+[[ "$got" == "$exp" ]] || err_exit "unreadable empty script should fail -- expected $exp, got $got"
+{ got=$(command $scr; print $?); } 2>/dev/null
+[[ "$got" == "$exp" ]] || err_exit "command of unreadable empty script should fail -- expected $exp, got $got"
+[[ "$(:; $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "unreadable empty script in [[ ... ]] should fail -- expected $exp"
+[[ "$(:; command $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "command unreadable empty script in [[ ... ]] should fail -- expected $exp"
+got=$($SHELL -c "$scr; print \$?" 2>/dev/null)
+[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of unreadable empty script should fail -- expected $exp, got" $got
+got=$($SHELL -c "command $scr; print \$?" 2>/dev/null)
+[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of command of unreadable empty script should fail -- expected $exp, got" $got
+
+rm -f $scr
+print : > $scr
+chmod a=x $scr
+{ got=$($scr; print $?); } 2>/dev/null
+[[ "$got" == "$exp" ]] || err_exit "unreadable non-empty script should fail -- expected $exp, got $got"
+{ got=$(command $scr; print $?); } 2>/dev/null
+[[ "$got" == "$exp" ]] || err_exit "command of unreadable non-empty script should fail -- expected $exp, got $got"
+[[ "$(:; $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "unreadable non-empty script in [[ ... ]] should fail -- expected $exp"
+[[ "$(:; command $scr; print $?)" == "$exp" ]] 2>/dev/null || err_exit "command unreadable non-empty script in [[ ... ]] should fail -- expected $exp"
+got=$($SHELL -c "$scr; print \$?" 2>/dev/null)
+[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of unreadable non-empty script should fail -- expected $exp, got" $got
+got=$($SHELL -c "command $scr; print \$?" 2>/dev/null)
+[[ "$got" == "$exp" ]] || err_exit "\$SHELL -c of command of unreadable non-empty script should fail -- expected $exp, got" $got
+
+# whence -a bug fix
+cd "$tmp"
+ifs=$IFS
+IFS=$'\n'
+PATH=$PATH:
+> ls
+chmod +x ls
+ok=
+for i in $(whence -a ls)
+do if [[ $i == *"$PWD/ls" ]]
+ then ok=1
+ break;
+ fi
+done
+[[ $ok ]] || err_exit 'whence -a not finding all executables'
+rm -f ls
+PATH=${PATH%:}
+
+#whence -p bug fix
+function foo
+{
+ :
+}
+[[ $(whence -p foo) == foo ]] && err_exit 'whence -p foo should not find function foo'
+
+# whence -q bug fix
+$SHELL -c 'whence -q cat' & pid=$!
+sleep 3
+kill $! 2> /dev/null && err_exit 'whence -q appears to be hung'
+
+FPATH=$PWD
+print 'function foobar { :;}' > foobar
+autoload foobar;
+exec {m}< /dev/null
+for ((i=0; i < 25; i++))
+do ( foobar )
+done
+exec {m}<& -
+exec {n}< /dev/null
+(( n > m )) && err_exit 'autoload function in subshell leaves file open'
+
+# whence -a bug fix
+rmdir=rmdir
+if mkdir "$rmdir"
+then rm=${ whence rm;}
+ cp "$rm" "$rmdir"
+ { PATH=:${rm%/rm} $SHELL -c "cd \"$rmdir\";whence -a rm";} > /dev/null 2>&1
+ exitval=$?
+ (( exitval==0 )) || err_exit "whence -a has exitval $exitval"
+fi
+
+[[ ! -d bin ]] && mkdir bin
+[[ ! -d fun ]] && mkdir fun
+print 'FPATH=../fun' > bin/.paths
+cat <<- \EOF > fun/myfun
+ function myfun
+ {
+ print myfun
+ }
+EOF
+x=$(FPATH= PATH=$PWD/bin $SHELL -c ': $(whence less);myfun') 2> /dev/null
+[[ $x == myfun ]] || err_exit 'function myfun not found'
+
+cp $(whence -p echo) user_to_group_relationship.hdr.query
+FPATH=/foobar:
+PATH=$FPATH:$PATH:.
+[[ $(user_to_group_relationship.hdr.query foobar) == foobar ]] 2> /dev/null || err_exit 'Cannot execute command with . in name when PATH and FPATH end in :.'
+
+exit $((Errors<125?Errors:125))
+
diff --git a/src/cmd/ksh93/tests/pointtype.sh b/src/cmd/ksh93/tests/pointtype.sh
new file mode 100755
index 0000000..b0a5333
--- /dev/null
+++ b/src/cmd/ksh93/tests/pointtype.sh
@@ -0,0 +1,138 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+typeset -T Pt_t=(
+ float x=1
+ float y=0
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y)))
+ }
+)
+
+for ((i=0; i < 100; i++))
+do
+Pt_t p
+[[ ${p.x} == 1 ]] || err_exit '${p[x]} is not 1'
+(( p.x == 1 )) || err_ext 'p[x] is not 1'
+[[ $(p.len) == 1 ]] || err_exit '$(p.len) != 1'
+[[ ${p.len} == 1 ]] || err_exit '${p.len} != 1'
+(( p.len == 1 )) || err_exit '((p.len != 1))'
+Pt_t q=(y=2)
+(( q.x == 1 )) || err_exit 'q.x is not 1'
+(( (q.len - sqrt(5)) < 10e-10 )) || err_exit 'q.len != sqrt(5)'
+q.len()
+{
+ print -r $((abs(_.x)+abs(_.y) ))
+}
+(( q.len == 3 )) || err_exit 'q.len is not 3'
+p=q
+[[ ${p.y} == 2 ]] || err_exit '${p[y]} is not 2'
+[[ ${@p} == Pt_t ]] || err_exit 'type of p is not Pt_t'
+[[ ${@q} == Pt_t ]] || err_exit 'type of q is not Pt_t'
+(( p.len == 3 )) || err_exit 'p.len is not 3'
+unset p q
+Pt_t pp=( ( x=3 y=4) ( x=5 y=12) (y=2) )
+(( pp[0].len == 5 )) || err_exit 'pp[0].len != 5'
+(( pp[1].len == 13 )) || err_exit 'pp[0].len != 12'
+(( (pp[2].len - sqrt(5)) < 10e-10 )) || err_exit 'pp[2].len != sqrt(5)'
+[[ ${pp[1]} == $'(\n\ttypeset -l -E x=5\n\ttypeset -l -E y=12\n)' ]] || err_exit '${pp[1] is not correct'
+[[ ${!pp[@]} == '0 1 2' ]] || err_exit '${pp[@] != "0 1 2"'
+pp+=( x=6 y=8)
+(( pp[3].len == 10 )) || err_exit 'pp[3].len != 10'
+[[ ${!pp[@]} == '0 1 2 3' ]] || err_exit '${pp[@] != "0 1 2 3"'
+pp[4]=pp[1]
+[[ ${pp[4]} == $'(\n\ttypeset -l -E x=5\n\ttypeset -l -E y=12\n)' ]] || err_exit '${pp[4] is not correct'
+unset pp
+Pt_t pp=( [one]=( x=3 y=4) [two]=( x=5 y=12) [three]=(y=2) )
+(( pp[one].len == 5 )) || err_exit 'pp[one].len != 5'
+(( pp[two].len == 13 )) || err_exit 'pp[two].len != 12'
+[[ ${pp[two]} == $'(\n\ttypeset -l -E x=5\n\ttypeset -l -E y=12\n)' ]] || err_exit '${pp[two] is not correct'
+[[ ${!pp[@]} == 'one three two' ]] || err_exit '${pp[@] != "one three two"'
+[[ ${@pp[1]} == Pt_t ]] || err_exit 'type of pp[1] is not Pt_t'
+unset pp
+done
+# redefinition of point
+typeset -T Pt_t=(
+ Pt_t _=(x=3 y=6)
+ float z=2
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y + _.z*_.z)))
+ }
+)
+Pt_t p
+[[ ${p.y} == 6 ]] || err_exit '${p.y} != 6'
+(( p.len == 7 )) || err_exit '((p.len !=7))'
+
+z=()
+Pt_t -a z.p
+z.p[1]=(y=2)
+z.p[2]=(y=5)
+z.p[3]=(x=6 y=4)
+eval y="$z"
+[[ $y == "$z" ]] || err_exit 'expansion of indexed array of types is incorrect'
+eval "$(typeset -p y)"
+[[ $y == "$z" ]] || err_exit 'typeset -p z for indexed array of types is incorrect'
+unset z y
+z=()
+Pt_t -A z.p
+z.p[1]=(y=2)
+z.p[2]=(y=5)
+z.p[3]=(x=6 y=4)
+eval y="$z"
+[[ $y == "$z" ]] || err_exit 'expansion of associative array of types is incorrect'
+eval "$(typeset -p y)"
+[[ $y == "$z" ]] || err_exit 'typeset -p z for associative of types is incorrect'
+unset z y
+
+typeset -T A_t=(
+ Pt_t -a b
+)
+typeset -T B_t=(
+ Pt_t -A b
+)
+A_t r
+r.b[1]=(y=2)
+r.b[2]=(y=5)
+eval s="$r"
+[[ $r == "$s" ]] || err_exit 'expansion of type containing index array of types is incorrect'
+eval "$(typeset -p s)"
+[[ $y == "$z" ]] || err_exit 'typeset -p z for type containing index of types is incorrect'
+unset r s
+B_t r
+r.b[1]=(y=2)
+r.b[2]=(y=5)
+eval s="$r"
+[[ $r == "$s" ]] || err_exit 'expansion of type containing index array of types is incorrect'
+eval "$(typeset -p s)"
+[[ $y == "$z" ]] || err_exit 'typeset -p z for type containing index of types is incorrect'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/pty.sh b/src/cmd/ksh93/tests/pty.sh
new file mode 100755
index 0000000..71eaef5
--- /dev/null
+++ b/src/cmd/ksh93/tests/pty.sh
@@ -0,0 +1,442 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+: : generated by mkptytests from "posix-sh-*-c.pty" : :
+
+# the trickiest part of the tests is avoiding typeahead
+# in the pty dialogue
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+
+alias err_exit='err_exit $lineno'
+
+Command=${0##*/}
+integer Errors=0 lineno=1
+
+whence -q pty || { lineno=$LINENO; err_exit "pty command not found -- tests skipped"; exit 0; }
+
+bintrue=$(whence -p true)
+
+x=$( $SHELL <<- \EOF
+ trap 'exit 0' EXIT
+ bintrue=$(whence -p true)
+ set -o monitor
+ {
+ eval $'set -o vi\npty $bintrue'
+ } < /dev/null & pid=$!
+ #sleep 1
+ jobs
+ kill $$
+ EOF
+)
+[[ $x == *Stop* ]] && err_exit 'monitor mode enabled incorrectly causes job to stop'
+
+if [[ -o xtrace ]]
+then debug=--debug=1
+else debug=
+fi
+
+function tst
+{
+ integer lineno=$1 offset
+ typeset text
+
+ pty $debug --dialogue --messages='/dev/fd/1' $SHELL |
+ while read -r text
+ do if [[ $text == *debug* ]]
+ then print -u2 -r -- "$text"
+ else offset=${text/*: line +([[:digit:]]):*/\1}
+ err_exit "${text/: line $offset:/: line $(( lineno + offset)):}"
+ fi
+ done
+}
+
+export PS1=':test-!: ' PS2='> ' PS4=': ' ENV= EXINIT= HISTFILE= TERM=dumb VISUAL=vi LC_ALL=C
+
+if ! pty $bintrue < /dev/null
+then err_exit pty command hangs on $bintrue -- tests skipped
+ exit 0
+fi
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 026(C)
+
+# If the User Portability Utilities Option is supported: When the
+# POSIX locale is specified and a background job is suspended by a
+# SIGTSTP signal then the <state> field in the output message is set to
+# Stopped, Suspended, Stopped(SIGTSTP) or Suspended(SIGTSTP).
+
+I ^\r?\n$
+p :test-1:
+w sleep 60 &
+u [[:digit:]]\r?\n$
+s 100
+p :test-2:
+w kill -TSTP $!
+u (Stopped|Suspended)
+p :test-3:
+w kill -KILL $!
+w wait
+u (Killed|Done)
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 028(C)
+
+# If the User Portability Utilities Option is supported: When the
+# POSIX locale is specified and a background job is suspended by a
+# SIGTTIN signal then the <state> field in the output message is set to
+# Stopped(SIGTTIN) or Suspended(SIGTTIN).
+
+I ^\r?\n$
+p :test-1:
+w sleep 60 &
+u [[:digit:]]\r?\n$
+s 100
+p :test-2:
+w kill -TTIN $!
+u (Stopped|Suspended) \(SIGTTIN\)
+p :test-3:
+w kill -KILL $!
+w wait
+u (Killed|Done)
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 029(C)
+
+# If the User Portability Utilities Option is supported: When the
+# POSIX locale is specified and a background job is suspended by a
+# SIGTTOU signal then the <state> field in the output message is set to
+# Stopped(SIGTTOU) or Suspended(SIGTTOU).
+
+I ^\r?\n$
+p :test-1:
+w sleep 60 &
+u [[:digit:]]\r?\n$
+s 100
+p :test-2:
+w kill -TTOU $!
+u (Stopped|Suspended) \(SIGTTOU\)
+p :test-3:
+w kill -KILL $!
+w wait
+u (Killed|Done)
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 091(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode an entered
+# character other than <newline>, erase, interrupt, kill, control-V,
+# control-W, backslash \ (followed by erase or kill), end-of-file and
+# <ESC> is inserted in the current command line.
+
+c echo h
+c ell
+w o
+u ^hello\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 093(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: After termination of a previous
+# command, sh is entered in insert mode.
+
+w echo hello
+u ^hello\r?\n$
+c echo goo
+c dby
+w e
+u ^goodbye\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 094(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode an <ESC>
+# switches sh into command mode.
+
+c echo he\E
+s 400
+w allo
+u ^hello\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 096(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in command mode the
+# interrupt character causes sh to terminate command line editing on
+# the current command line, re-issue the prompt on the next line of the
+# terminal and to reset the command history so that the command that
+# was interrupted is not entered in the history.
+
+I ^\r?\n$
+p :test-1:
+w echo first
+p :test-2:
+w stty intr ^C
+p :test-3:
+c echo bad\E
+s 400
+c \cC
+w echo scrambled
+p :test-4:
+w history
+u echo first
+r stty intr \^C
+r echo
+r history
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 097(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode a <newline>
+# causes the current command line to be executed.
+
+c echo ok\n
+u ^ok\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 099(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode the interrupt
+# character causes sh to terminate command line editing on the current
+# command line, re-issue the prompt on the next line of the terminal
+# and to reset the command history so that the command that was
+# interrupted is not entered in the history.
+
+I ^\r?\n$
+p :test-1:
+w echo first
+u ^first
+p :test-2:
+w stty intr ^C
+r
+p :test-3:
+c echo bad\cC
+w echo last
+p :test-4:
+w history
+u echo first
+r stty intr \^C
+r echo last
+r history
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 100(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode the kill
+# character clears all the characters from the input line.
+
+p :test-1:
+w stty kill ^X
+p :test-2:
+c echo bad\cX
+w echo ok
+u ^ok\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 101(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode a control-V
+# causes the next character to be inserted even in the case that the
+# character is a special insert mode character.
+# Testing Requirements: The assertion must be tested with at least the
+# following set of characters: <newline>, erase, interrupt, kill,
+# control-V, control-W, end-of-file, backslash \ (followed by erase or
+# kill) and <ESC>.
+
+d 10
+p :test-1:
+w stty erase ^H intr ^C kill ^X
+p :test-2:
+w echo erase=:\cV\cH:
+u ^erase=:\r?\n$
+p :test-3:
+w echo kill=:\cV\cX:
+u ^kill=:\cX:\r?\n$
+p :test-4:
+w echo control-V=:\cV\cV:
+u ^control-V=:\cV:\r?\n$
+p :test-5:
+w echo control-W:\cV\cW:
+u ^control-W:\cW:\r?\n$
+p :test-6:
+w echo EOF=:\cV\cD:
+u ^EOF=:\004:\r?\n$
+p :test-7:
+w echo backslash-erase=:\\\cH:
+u ^backslash-erase=:\r?\n$
+p :test-8:
+w echo backslash-kill=:\\\cX:
+u ^backslash-kill=:\cX:\r?\n$
+p :test-9:
+w echo ESC=:\cV\E:
+u ^ESC=:\E:\r?\n$
+p :test-10:
+w echo interrupt=:\cV\cC:
+u ^interrupt=:\cC:\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 104(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in insert mode an
+# end-of-file at the beginning of an input line is interpreted as the
+# end of input.
+
+p :test-1:
+w trap 'echo done >&2' EXIT
+p :test-2:
+s 100
+c \cD
+u ^done\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 111(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in command mode, # inserts
+# the character # at the beginning of the command line and causes the
+# line to be treated as a comment and the line is entered in the
+# command history.
+
+p :test-1:
+c echo save\E
+s 400
+c #
+p :test-2:
+w history
+u #echo save
+r history
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 137(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in command mode, then v
+# invokes the vi editor to edit the current command line in a temporary
+# file. When the editor exits, the commands in the temporary file are
+# executed.
+
+p :test-1:
+c echo hello\E
+s 400
+c v
+u /tmp/
+c A world\E
+s 400
+w :wq
+u ^hello world\r?\n$
+!
+
+# err_exit #
+tst $LINENO <<"!"
+L POSIX sh 251(C)
+
+# If the User Portability Utilities Option is supported and shell
+# command line editing is supported: When in command mode, then the
+# command N repeats the most recent / or ? command, reversing the
+# direction of the search.
+
+p :test-1:
+w echo repeat-1
+u ^repeat-1\r?\n$
+p :test-2:
+w echo repeat-2
+u ^repeat-2\r?\n$
+p :test-3:
+s 100
+c \E
+s 400
+w /rep
+u echo repeat-2
+c n
+r echo repeat-1
+c N
+r echo repeat-2
+w dd
+p :test-3:
+w echo repeat-3
+u ^repeat-3\r?\n$
+p :test-4:
+s 100
+c \E
+s 400
+w ?rep
+r echo repeat-2
+c N
+r echo repeat-1
+c n
+r echo repeat-2
+c n
+r echo repeat-3
+!
+
+# err_exit #
+whence -q less &&
+TERM=vt100 tst $LINENO <<"!"
+L process/terminal group exercise
+
+w m=yes; while true; do echo $m-$m; done | less
+u :$|:\E|lines
+c \cZ
+r Stopped
+w fg
+u yes-yes
+!
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/quoting.sh b/src/cmd/ksh93/tests/quoting.sh
new file mode 100755
index 0000000..01aae0d
--- /dev/null
+++ b/src/cmd/ksh93/tests/quoting.sh
@@ -0,0 +1,369 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+if [[ 'hi there' != "hi there" ]]
+then err_exit "single quotes not the same as double quotes"
+fi
+x='hi there'
+if [[ $x != 'hi there' ]]
+then err_exit "$x not the same as 'hi there'"
+fi
+if [[ $x != "hi there" ]]
+then err_exit "$x not the same as \"hi there \""
+fi
+if [[ \a\b\c\*\|\"\ \\ != 'abc*|" \' ]]
+then err_exit " \\ differs from '' "
+fi
+if [[ "ab\'\"\$(" != 'ab\'\''"$(' ]]
+then err_exit " \"\" differs from '' "
+fi
+if [[ $(print -r - 'abc*|" \') != 'abc*|" \' ]]
+then err_exit "\$(print -r - '') differs from ''"
+fi
+if [[ $(print -r - "abc*|\" \\") != 'abc*|" \' ]]
+then err_exit "\$(print -r - '') differs from ''"
+fi
+if [[ "$(print -r - 'abc*|" \')" != 'abc*|" \' ]]
+then err_exit "\"\$(print -r - '')\" differs from ''"
+fi
+if [[ "$(print -r - "abc*|\" \\")" != 'abc*|" \' ]]
+then err_exit "\"\$(print -r - "")\" differs from ''"
+fi
+if [[ $(print -r - $(print -r - 'abc*|" \')) != 'abc*|" \' ]]
+then err_exit "nested \$(print -r - '') differs from ''"
+fi
+if [[ "$(print -r - $(print -r - 'abc*|" \'))" != 'abc*|" \' ]]
+then err_exit "\"nested \$(print -r - '')\" differs from ''"
+fi
+if [[ $(print -r - "$(print -r - 'abc*|" \')") != 'abc*|" \' ]]
+then err_exit "nested \"\$(print -r - '')\" differs from ''"
+fi
+unset x
+if [[ ${x-$(print -r - "abc*|\" \\")} != 'abc*|" \' ]]
+then err_exit "\${x-\$(print -r - '')} differs from ''"
+fi
+if [[ ${x-$(print -r - "a}c*|\" \\")} != 'a}c*|" \' ]]
+then err_exit "\${x-\$(print -r - '}')} differs from ''"
+fi
+x=$((echo foo)|(cat))
+if [[ $x != foo ]]
+then err_exit "((cmd)|(cmd)) failed"
+fi
+x=$(print -r -- "\"$HOME\"")
+if [[ $x != '"'$HOME'"' ]]
+then err_exit "nested double quotes failed"
+fi
+unset z
+: ${z="a{b}c"}
+if [[ $z != 'a{b}c' ]]
+then err_exit '${z="a{b}c"} not correct'
+fi
+unset z
+: "${z="a{b}c"}"
+if [[ $z != 'a{b}c' ]]
+then err_exit '"${z="a{b}c"}" not correct'
+fi
+if [[ $(print -r -- "a\*b") != 'a\*b' ]]
+then err_exit '$(print -r -- "a\*b") differs from a\*b'
+fi
+unset x
+if [[ $(print -r -- "a\*b$x") != 'a\*b' ]]
+then err_exit '$(print -r -- "a\*b$x") differs from a\*b'
+fi
+x=hello
+set -- ${x+foo bar bam}
+if (( $# !=3 ))
+then err_exit '${x+foo bar bam} does not yield three arguments'
+fi
+set -- ${x+foo "bar bam"}
+if (( $# !=2 ))
+then err_exit '${x+foo "bar bam"} does not yield two arguments'
+fi
+set -- ${x+foo 'bar bam'}
+if (( $# !=2 ))
+then err_exit '${x+foo '\''bar bam'\''} does not yield two arguments'
+fi
+set -- ${x+foo $x bam}
+if (( $# !=3 ))
+then err_exit '${x+foo $x bam} does not yield three arguments'
+fi
+set -- ${x+foo "$x" bam}
+if (( $# !=3 ))
+then err_exit '${x+foo "$x" bam} does not yield three arguments'
+fi
+set -- ${x+"foo $x bam"}
+if (( $# !=1 ))
+then err_exit '${x+"foo $x bam"} does not yield one argument'
+fi
+set -- "${x+foo $x bam}"
+if (( $# !=1 ))
+then err_exit '"${x+foo $x bam}" does not yield one argument'
+fi
+set -- ${x+foo "$x "bam}
+if (( $# !=2 ))
+then err_exit '${x+foo "$x "bam} does not yield two arguments'
+fi
+x="ab$'cd"
+if [[ $x != 'ab$'"'cd" ]]
+then err_exit '$'"' inside double quotes not working"
+fi
+x=`print 'ab$'`
+if [[ $x != 'ab$' ]]
+then err_exit '$'"' inside `` quotes not working"
+fi
+unset a
+x=$(print -r -- "'\
+\
+")
+if [[ $x != "'" ]]
+then err_exit 'line continuation in double strings not working'
+fi
+x=$(print -r -- "'\
+$a\
+")
+if [[ $x != "'" ]]
+then err_exit 'line continuation in expanded double strings not working'
+fi
+x='\*'
+if [[ $(print -r -- $x) != '\*' ]]
+then err_exit 'x="\\*";$x != \*'
+fi
+x=' hello world '
+set -- $x
+if (( $# != 2 ))
+then err_exit 'field splitting error'
+fi
+x=$(print -r -- '1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890 \
+1234567890123456789012345678901234567890123456789012345678901234567890')
+if (( ${#x} != (15*73-3) ))
+then err_exit "length of x, ${#x}, is incorrect should be $((15*73-3))"
+fi
+x='$hi'
+if [[ $x\$ != '$hi$' ]]
+then err_exit ' $x\$, with x=$hi, does not expand to $hi$'
+fi
+if [[ $x$ != '$hi$' ]]
+then err_exit ' $x$, with x=$hi, does not expand to $hi$'
+fi
+set -- $(/bin/echo foo;sleep 1;/bin/echo bar)
+if [[ $# != 2 ]]
+then err_exit 'word splitting after command substitution not working'
+fi
+unset q
+if [[ "${q:+'}q${q:+'}" != q ]]
+then err_exit 'expansion of "{q:+'\''}" not correct when q unset'
+fi
+q=1
+if [[ "${q:+'}q${q:+'}" != "'q'" ]]
+then err_exit 'expansion of "{q:+'\''}" not correct when q set'
+fi
+x=$'x\' #y'
+if [[ $x != "x' #y" ]]
+then err_exit "$'x\' #y'" not working
+fi
+x=$q$'x\' #y'
+if [[ $x != "1x' #y" ]]
+then err_exit "$q$'x\' #y'" not working
+fi
+IFS=,
+x='a,b\,c,d'
+set -- $x
+if [[ $2 != 'b\' ]]
+then err_exit "field splitting of $x with IFS=$IFS not working"
+fi
+foo=bar
+bar=$(print -r -- ${foo+\\n\ })
+if [[ $bar != '\n ' ]]
+then err_exit '${foo+\\n\ } expansion error'
+fi
+unset bar
+bar=$(print -r -- ${foo+\\n\ $bar})
+if [[ $bar != '\n ' ]]
+then err_exit '${foo+\\n\ $bar} expansion error with bar unset'
+fi
+x='\\(..\\)|&\|\|\\&\\|'
+if [[ $(print -r -- $x) != "$x" ]]
+then err_exit '$x, where x=\\(..\\)|&\|\|\\&\\| not working'
+fi
+x='\\('
+if [[ $(print -r -- a${x}b) != a"${x}"b ]]
+then err_exit 'a${x}b, where x=\\( not working'
+fi
+x=
+if [[ $(print -r -- $x'\\1') != '\\1' ]]
+then err_exit 'backreference inside single quotes broken'
+fi
+set -- ''
+set -- "$@"
+if (( $# != 1 ))
+then err_exit '"$@" not preserving nulls'
+fi
+x=
+if [[ $(print -r s"!\2${x}\1\a!") != 's!\2\1\a!' ]]
+then err_exit 'print -r s"!\2${x}\1\a!" not equal s!\2\1\a!'
+fi
+if [[ $(print -r $'foo\n\n\n') != foo ]]
+then err_exit 'trailing newlines on comsubstitution not removed'
+fi
+unset x
+if [[ ${x:='//'} != '//' ]]
+then err_exit '${x:='//'} != "//"'
+fi
+if [[ $(print -r "\"hi$\"") != '"hi$"' ]]
+then err_exit '$\ not correct inside ""'
+fi
+unset x
+if [[ "${x-a\}b}" != 'a}b' ]]
+then err_exit '"${x-a\}b}" != "a}b"'
+fi
+if [[ "\}\]$x\*\{\[\\" != '\}\]\*\{\[\' ]]
+then err_exit '"\}\]$x\*\{\[\\" != "\}\]\*\{\[\"'
+fi
+foo=yes
+if [[ $(print -r -- {\$foo}) != '{$foo}' ]]
+then err_exit '{\$foo}' not expanded correctly
+fi
+[[ foo == $(
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+###########################################################
+print foo) ]] || err_exit "command subsitution with long comments broken"
+subject='some/other/words'
+re='@(?*)/@(?*)/@(?*)'
+[[ ${subject/${re}/\3} != words ]] && err_exit 'string replacement with \3 not working'
+[[ ${subject/${re}/'\3'} != '\3' ]] && err_exit 'string replacement with '"'\3'"' not working'
+[[ ${subject/${re}/"\\3"} != '\3' ]] && err_exit 'string replacement with "\\3" not working'
+[[ ${subject/${re}/"\3"} != '\3' ]] && err_exit 'string replacement with "\3" not working'
+string='\3'
+[[ ${subject/${re}/${string}} != words ]] && err_exit 'string replacement with $string not working with string=\3'
+[[ $(print -r "${subject/${re}/${string}}") != words ]] && err_exit 'string replacement with $string not working with string=\3 using print'
+[[ ${subject/${re}/"${string}"} != '\3' ]] && err_exit 'string replacement with "$string" not working with string=\3'
+[[ $(print -r "${subject/${re}/"${string}"}") != '\3' ]] && err_exit 'string replacement with "$string" not working with string=\3 using print'
+string='\\3'
+[[ ${subject/${re}/${string}} != '\3' ]] && err_exit 'string replacement with $string not working with string=\\3'
+[[ ${subject/${re}/"${string}"} != '\\3' ]] && err_exit 'string replacement with "$string" not working with string=\\3'
+[[ ${subject/${re}/\4} != '\4' ]] && err_exit 'string replacement with \4 not working'
+[[ ${subject/${re}/'\4'} != '\4' ]] && err_exit 'string replacement with '\4' not working'
+string='\4'
+[[ ${subject/${re}/${string}} != '\4' ]] && err_exit 'string replacement with $string not working with string=\4'
+[[ ${subject/${re}/"${string}"} != '\4' ]] && err_exit 'string replacement with "$string" not working with string=\4'
+string='&foo'
+[[ ${subject/${re}/${string}} != '&foo' ]] && err_exit 'string replacement with $string not working with string=&foo'
+[[ ${subject/${re}/"${string}"} != '&foo' ]] && err_exit 'string replacement with "$string" not working with string=&foo'
+{
+x=x
+x=${x:-`id | sed 's/^[^(]*(\([^)]*\)).*/\1/'`}
+} 2> /dev/null || err_exit 'skipping over `` failed'
+[[ $x == x ]] || err_exit 'assignment ${x:=`...`} failed'
+[[ $($SHELL -c 'print a[') == 'a[' ]] || err_exit "unbalanced '[' in command arg fails"
+$SHELL -c $'false && (( `wc -l /dev/null | nawk \'{print $1}\'` > 2 )) && true;:' 2> /dev/null || err_exit 'syntax error with ` in arithmetic expression'
+{ $SHELL -c '(( 1`: "{ }"` ))' ;} 2> /dev/null || err_exit 'problem with ` inside (())'
+varname=foobarx
+x=`print '"\$'${varname}'"'`
+[[ $x == '"$foobarx"' ]] || err_exit $'\\$\' not handled correctly inside ``'
+
+copy1=5 copynum=1
+foo="`eval echo "$"{copy$copynum"-0}"`"
+[[ $foo == "$copy1" ]] || err_exit '$"..." not being ignored inside ``'
+
+[[ $($SHELL -c 'set -- ${1+"$@"}; print $#' cmd '') == 1 ]] || err_exit '${1+"$@"} with one empty argument fails'
+[[ $($SHELL -c 'set -- ${1+"$@"}; print $#' cmd foo '') == 2 ]] || err_exit '${1+"$@"} with one non-empty and on empty argument fails'
+[[ $($SHELL -c 'set -- ${1+"$@"}; print $#' cmd "" '') == 2 ]] || err_exit '${1+"$@"} with two empty arguments fails'
+[[ $($SHELL -c 'set -- ${1+"$@"}; print $#' cmd "" '' '') == 3 ]] || err_exit '${1+"$@"} with three empty arguments fails'
+[[ $($SHELL -c 'set -- "$@"; print $#' cmd '') == 1 ]] || err_exit '"$@" with one empty argument fails'
+[[ $($SHELL -c 'set -- "${@:2}"; print $#' cmd '') == 0 ]] || err_exit '"$@" with one empty argument fails'
+[[ $($SHELL -c 'set -- "$@"; print $#' cmd foo '') == 2 ]] || err_exit '"$@" with one non-empty and on empty argument fails'
+[[ $($SHELL -c 'set -- "$@"; print $#' cmd "" '') == 2 ]] || err_exit '"$@" with two empty arguments fails'
+[[ $($SHELL -c 'set -- "$@"; print $#' cmd "" '' '') == 3 ]] || err_exit '"$@" with three empty arguments fails'
+args=('')
+set -- "${args[@]}"
+[[ $# == 1 ]] || err_exit '"${args[@]}"} with one empty argument fails'
+set -- ${1+"${args[@]}"}
+[[ $# == 1 ]] || err_exit '${1+"${args[@]}"} with one empty argument fails'
+args=(foo '')
+set -- "${args[@]}"
+[[ $# == 2 ]] || err_exit '"${args[@]}"} with one non-empty and one empty argument fails'
+set -- ${1+"${args[@]}"}
+[[ $# == 2 ]] || err_exit '${1+"${args[@]}"} with one non-empty and one empty argument fails'
+
+unset ARGS
+set --
+ARGS=("$@")
+set -- "${ARGS[@]}"
+(( $# )) && err_exit 'set -- "${ARGS[@]}" for empty array should not produce arguments'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/quoting2.sh b/src/cmd/ksh93/tests/quoting2.sh
new file mode 100755
index 0000000..bc7380d
--- /dev/null
+++ b/src/cmd/ksh93/tests/quoting2.sh
@@ -0,0 +1,215 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+set -o noglob
+if [[ 'hi there' != "hi there" ]]
+then err_exit "single quotes not the same as double quotes"
+fi
+x='hi there'
+if [[ $x != 'hi there' ]]
+then err_exit "$x not the same as 'hi there'"
+fi
+if [[ $x != "hi there" ]]
+then err_exit "$x not the same as \"hi there \""
+fi
+if [[ \a\b\c\*\|\"\ \\ != 'abc*|" \' ]]
+then err_exit " \\ differs from '' "
+fi
+if [[ "ab\'\"\$(" != 'ab\'\''"$(' ]]
+then err_exit " \"\" differs from '' "
+fi
+if [[ $(print -r - 'abc*|" \') != 'abc*|" \' ]]
+then err_exit "\$(print -r - '') differs from ''"
+fi
+if [[ $(print -r - "abc*|\" \\") != 'abc*|" \' ]]
+then err_exit "\$(print -r - '') differs from ''"
+fi
+if [[ "$(print -r - 'abc*|" \')" != 'abc*|" \' ]]
+then err_exit "\"\$(print -r - '')\" differs from ''"
+fi
+if [[ "$(print -r - "abc*|\" \\")" != 'abc*|" \' ]]
+then err_exit "\"\$(print -r - "")\" differs from ''"
+fi
+if [[ $(print -r - "$(print -r - 'abc*|" \')") != 'abc*|" \' ]]
+then err_exit "nested \$(print -r - '') differs from ''"
+fi
+if [[ "$(print -r - $(print -r - 'abc*|" \'))" != 'abc*|" \' ]]
+then err_exit "\"nested \$(print -r - '')\" differs from ''"
+fi
+if [[ $(print -r - "$(print -r - 'abc*|" \')") != 'abc*|" \' ]]
+then err_exit "nested \"\$(print -r - '')\" differs from ''"
+fi
+unset x
+if [[ ${x-$(print -r - "abc*|\" \\")} != 'abc*|" \' ]]
+then err_exit "\${x-\$(print -r - '')} differs from ''"
+fi
+if [[ ${x-$(print -r - "a}c*|\" \\")} != 'a}c*|" \' ]]
+then err_exit "\${x-\$(print -r - '}')} differs from ''"
+fi
+x=$((echo foo)|(cat))
+if [[ $x != foo ]]
+then err_exit "((cmd)|(cmd)) failed"
+fi
+x=$(print -r -- "\"$HOME\"")
+if [[ $x != '"'$HOME'"' ]]
+then err_exit "nested double quotes failed"
+fi
+unset z
+: ${z="a{b}c"}
+if [[ $z != 'a{b}c' ]]
+then err_exit '${z="a{b}c"} not correct'
+fi
+unset z
+: "${z="a{b}c"}"
+if [[ $z != 'a{b}c' ]]
+then err_exit '"${z="a{b}c"}" not correct'
+fi
+if [[ $(print -r -- "a\*b") != 'a\*b' ]]
+then err_exit '$(print -r -- "a\*b") differs from a\*b'
+fi
+unset x
+if [[ $(print -r -- "a\*b$x") != 'a\*b' ]]
+then err_exit '$(print -r -- "a\*b$x") differs from a\*b'
+fi
+x=hello
+set -- ${x+foo bar bam}
+if (( $# !=3 ))
+then err_exit '${x+foo bar bam} does not yield three arguments'
+fi
+set -- ${x+foo "bar bam"}
+if (( $# !=2 ))
+then err_exit '${x+foo "bar bam"} does not yield two arguments'
+fi
+set -- ${x+foo 'bar bam'}
+if (( $# !=2 ))
+then err_exit '${x+foo '\''bar bam'\''} does not yield two arguments'
+fi
+set -- ${x+foo $x bam}
+if (( $# !=3 ))
+then err_exit '${x+foo $x bam} does not yield three arguments'
+fi
+set -- ${x+foo "$x" bam}
+if (( $# !=3 ))
+then err_exit '${x+foo "$x" bam} does not yield three arguments'
+fi
+set -- ${x+"foo $x bam"}
+if (( $# !=1 ))
+then err_exit '${x+"foo $x bam"} does not yield one argument'
+fi
+set -- "${x+foo $x bam}"
+if (( $# !=1 ))
+then err_exit '"${x+foo $x bam}" does not yield one argument'
+fi
+set -- ${x+foo "$x "bam}
+if (( $# !=2 ))
+then err_exit '${x+foo "$x "bam} does not yield two arguments'
+fi
+x="ab$'cd"
+if [[ $x != 'ab$'"'cd" ]]
+then err_exit '$'"' inside double quotes not working"
+fi
+x=`print 'ab$'`
+if [[ $x != 'ab$' ]]
+then err_exit '$'"' inside `` quotes not working"
+fi
+unset a
+x=$(print -r -- "'\
+\
+")
+if [[ $x != "'" ]]
+then err_exit 'line continuation in double strings not working'
+fi
+x=$(print -r -- "'\
+$a\
+")
+if [[ $x != "'" ]]
+then err_exit 'line continuation in expanded double strings not working'
+fi
+x='\*'
+if [[ $(print -r -- $x) != '\*' ]]
+then err_exit 'x="\\*";$x != \*'
+fi
+if [[ $(print -r -- "\}" ) != '\}' ]]
+then err_exit '(print -r -- "\}"' not working
+fi
+if [[ $(print -r -- "\{" ) != '\{' ]]
+then err_exit 'print -r -- "\{"' not working
+fi
+# The following caused a syntax error on earlier versions
+foo=foo x=-
+if [[ `eval print \\${foo$x}` != foo* ]]
+then err_exit '`eval print \\${foo$x}`' not working
+fi
+if [[ "`eval print \\${foo$x}`" != foo* ]]
+then err_exit '"`eval print \\${foo$x}`"' not working
+fi
+if ( [[ $() != '' ]] )
+then err_exit '$() not working'
+fi
+x=a:b:c
+set -- $( IFS=:; print $x)
+if (( $# != 3))
+then err_exit 'IFS not working correctly with command substitution'
+fi
+$SHELL -n 2> /dev/null << \! || err_exit '$(...) bug with ( in comment'
+y=$(
+ # ( this line is a bug fix
+ print hi
+)
+!
+x=
+for j in glob noglob
+do for i in 'a\*b' 'a\ b' 'a\bc' 'a\*b' 'a\"b'
+ do eval [[ '$('print -r -- \'$i\'\$x')' != "'$i'" ]] && err_exit "quoting of $i\$x with $j enabled failed"
+ eval [[ '$('print -r -- \'$i\'\${x%*}')' != "'$i'" ]] && err_exit "quoting of $i\${x%*} with $j enabled failed"
+ if [[ $j == noglob ]]
+ then eval [[ '$('print -r -- \'$i\'\${x:-*}')' != "'$i''*'" ]] && err_exit "quoting of $i\${x:-*} with $j enabled failed"
+ fi
+ done
+ set -f
+done
+foo=foo
+[[ "$" == '$' ]] || err_exit '"$" != $'
+[[ "${foo}$" == 'foo$' ]] || err_exit 'foo=foo;"${foo}$" != foo$'
+[[ "${foo}${foo}$" == 'foofoo$' ]] || err_exit 'foo=foo;"${foo}${foo}$" != foofoo$'
+foo='$ '
+[[ "$foo" == ~(Elr)(\\\$|#)\ ]] || err_exit $'\'$ \' not matching RE \\\\\\$|#\''
+[[ "$foo" == ~(Elr)('\$'|#)\ ]] || err_exit $'\'$ \' not matching RE \'\\$\'|#\''
+foo='# '
+[[ "$foo" == ~(Elr)(\\\$|#)\ ]] || err_exit $'\'# \' not matching RE \\'\$|#\''
+[[ "$foo" == ~(Elr)('\$'|#)\ ]] || err_exit $'\'# \' not matching RE \'\\$\'|#\''
+[[ '\$' == '\$'* ]] || err_exit $'\'\\$\' not matching \'\\$\'*'
+[[ a+a == ~(E)a\+a ]] || err_exit '~(E)a\+a not matching a+a'
+[[ a+a =~ a\+a ]] || err_exit 'RE a\+a not matching a+a'
+
+exp='ac'
+got=$'a\0b'c
+[[ $got == "$exp" ]] || err_exit "\$'a\\0b'c expansion failed -- expected '$exp', got '$got'"
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/readcsv.sh b/src/cmd/ksh93/tests/readcsv.sh
new file mode 100644
index 0000000..9dd6d9c
--- /dev/null
+++ b/src/cmd/ksh93/tests/readcsv.sh
@@ -0,0 +1,65 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+tmp1=$tmp/tmp1.csv
+tmp2=$tmp/tmp2.csv
+cat > $tmp1 <<- \EOF
+ CAT,"CVE CCODE","NECA OCN",ST,LATA,AP,"New InterState
+ Orig","New Inter""""State
+ Term","New IntraState
+ Orig","New IntraState
+ Term"
+ CLEC,XXXX,AAAA,RB,ABC,comp," 0.2 "," 0.4 "," 0.6 "," 0.8 "
+ CLEC,YYYY,QQQQ,SX,123,mmmm," 0.3 "," 0.5 "," 0.7 "," 0.9 "
+EOF
+integer count=0 nfields
+IFS=${2-,}
+typeset -a arr
+while read -A -S arr
+do ((nfields=${#arr[@]}))
+ if ((++count==1))
+ then ((nfields==10)) || err_exit 'first record should contain 10 fields'
+ [[ ${arr[7]} == $'New Inter""State\nTerm' ]] || err_exit $'7th field of record 1 should contain New Inter""State\nTerm'
+ fi
+ for ((i=0; i < nfields;i++))
+ do delim=$IFS
+ if ((i == nfields-1))
+ then delim=$'\r\n'
+ fi
+ printf "%#q%s" "${arr[i]}" "$delim"
+ done
+done < $tmp1 > $tmp2
+diff "$tmp1" "$tmp2" >/dev/null 2>&1 || err_exit "files $tmp1 and $tmp2 differ"
+
+exit $((Errors<125?Errors:125))
+
diff --git a/src/cmd/ksh93/tests/recttype.sh b/src/cmd/ksh93/tests/recttype.sh
new file mode 100755
index 0000000..9f41d92
--- /dev/null
+++ b/src/cmd/ksh93/tests/recttype.sh
@@ -0,0 +1,70 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+typeset -T Pt_t=(
+ float x=1
+ float y=0
+ len()
+ {
+ print -r $((sqrt(_.x*_.x + _.y*_.y)))
+ }
+)
+
+typeset -T Rect_t=(
+ Pt_t ll=(x=0 y=0)
+ Pt_t ur=(x=1 y=1)
+ area()
+ {
+ print -r $(( abs((_.ur.x-_.ll.x)*(_.ur.y-_.ll.y)) ))
+ }
+)
+
+for ((i=0; i < 100; i++))
+do
+Rect_t r
+[[ ${r.area} == 1 ]] || err_exit '${r.area} != 1'
+Rect_t s=(
+ Pt_t ur=(x=9 y=9)
+ Pt_t ll=(x=7 y=7)
+)
+[[ ${s.ur.x} == 9 ]] || err_exit ' ${s.ur.x} != 9'
+(( s.ur.x == 9 ))|| err_exit ' ((s.ur.x)) != 9'
+[[ ${s.ll.y} == 7 ]] || err_exit '${s.ll.y} != 7'
+(( s.area == 4 )) || err_exit 'area of s should be 4'
+[[ ${s.area} == 4 ]] || err_exit '${s.area} != 4'
+unset r s
+done
+Rect_t -A r
+r[one]=(ur=(x=4 y=4))
+(( r[one].area == 16 )) || err_exit 'area of r[one] should be 16'
+[[ ${r[one].area} == 16 ]] || err_exit '${r[one].area} should be 16'
+unset r
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/restricted.sh b/src/cmd/ksh93/tests/restricted.sh
new file mode 100755
index 0000000..5699105
--- /dev/null
+++ b/src/cmd/ksh93/tests/restricted.sh
@@ -0,0 +1,83 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+# test restricted shell
+pwd=$PWD
+case $SHELL in
+/*) ;;
+*/*) SHELL=$pwd/$SHELL;;
+*) SHELL=$(whence "$SHELL");;
+esac
+function check_restricted
+{
+ rm -f out
+ LC_MESSAGES=C rksh -c "$@" 2> out > /dev/null
+ grep restricted out > /dev/null 2>&1
+}
+
+[[ $SHELL != /* ]] && SHELL=$pwd/$SHELL
+cd $tmp || err_exit "cd $tmp failed"
+ln -s $SHELL rksh
+PATH=$PWD:$PATH
+rksh -c '[[ -o restricted ]]' || err_exit 'restricted option not set'
+[[ $(rksh -c 'print hello') == hello ]] || err_exit 'unable to run print'
+check_restricted /bin/echo || err_exit '/bin/echo not resticted'
+check_restricted ./echo || err_exit './echo not resticted'
+check_restricted 'SHELL=ksh' || err_exit 'SHELL asignment not resticted'
+check_restricted 'PATH=/bin' || err_exit 'PATH asignment not resticted'
+check_restricted 'FPATH=/bin' || err_exit 'FPATH asignment not resticted'
+check_restricted 'ENV=/bin' || err_exit 'ENV asignment not resticted'
+check_restricted 'print > file' || err_exit '> file not restricted'
+> empty
+check_restricted 'print <> empty' || err_exit '<> file not restricted'
+print 'echo hello' > script
+chmod +x ./script
+! check_restricted script || err_exit 'script without builtins should run in restricted mode'
+check_restricted ./script || err_exit 'script with / in name should not run in restricted mode'
+print '/bin/echo hello' > script
+! check_restricted script || err_exit 'script with pathnames should run in restricted mode'
+print 'echo hello> file' > script
+! check_restricted script || err_exit 'script with output redirection should run in restricted mode'
+print 'PATH=/bin' > script
+! check_restricted script || err_exit 'script with PATH assignment should run in restricted mode'
+cat > script <<!
+#! $SHELL
+print hello
+!
+! check_restricted 'script;:' || err_exit 'script with #! pathname should run in restricted mode'
+! check_restricted 'script' || err_exit 'script with #! pathname should run in restricted mode even if last command in script'
+for i in PATH ENV FPATH
+do check_restricted "function foo { typeset $i=foobar;};foo" || err_exit "$i can be changed in function by using typeset"
+done
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/return.sh b/src/cmd/ksh93/tests/return.sh
new file mode 100755
index 0000000..8c243f5
--- /dev/null
+++ b/src/cmd/ksh93/tests/return.sh
@@ -0,0 +1,183 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+# test the behavior of return and exit with functions
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+unset HISTFILE
+
+foo=NOVAL bar=NOVAL
+file=$tmp/test
+function foo
+{
+ typeset foo=NOEXIT
+ trap "foo=EXIT;rm -f $file" EXIT
+ > $file
+ if (( $1 == 0 ))
+ then return $2
+ elif (( $1 == 1 ))
+ then exit $2
+ else bar "$@"
+ fi
+}
+
+function bar
+{
+ typeset bar=NOEXIT
+ trap 'bar=EXIT' EXIT
+ if (( $1 == 2 ))
+ then return $2
+ elif (( $1 == 3 ))
+ then exit $2
+ fi
+}
+
+function funcheck
+{
+ [[ $foo == EXIT ]] || err_exit "foo "$@" : exit trap not set"
+ if [[ -f $file ]]
+ then rm -r $file
+ err_exit "foo $@: doesn't remove $file"
+ fi
+ foo=NOVAL bar=NOVAL
+}
+
+(exit 0) || err_exit "exit 0 is not zero"
+(return 0) || err_exit "return 0 is not zero"
+(exit) || err_exit "default exit value is not zero"
+(return) || err_exit "default return value is not zero"
+(exit 35)
+ret=$?
+if (( $ret != 35 ))
+then err_exit "exit 35 is $ret not 35"
+fi
+(return 35)
+ret=$?
+if (( $ret != 35 ))
+then err_exit "return 35 is $ret not 35"
+fi
+
+foo 0 0 || err_exit "foo 0 0: incorrect return"
+funcheck 0 0
+foo 0 3
+ret=$?
+if (( $ret != 3 ))
+then err_exit "foo 0 3: return is $ret not 3"
+fi
+funcheck 0 3
+foo 2 0 || err_exit "foo 2 0: incorrect return"
+[[ $bar == EXIT ]] || err_exit "foo 2 0: bar exit trap not set"
+funcheck 2 0
+foo 2 3
+ret=$?
+if (( $ret != 3 ))
+then err_exit "foo 2 3: return is $ret not 3"
+fi
+[[ $bar == EXIT ]] || err_exit "foo 2 3: bar exit trap not set"
+funcheck 2 3
+(foo 3 3)
+ret=$?
+if (( $ret != 3 ))
+then err_exit "foo 3 3: return is $ret not 3"
+fi
+foo=EXIT
+funcheck 3 3
+cat > $file <<!
+return 3
+exit 4
+!
+( . $file )
+ret=$?
+if (( $ret != 3 ))
+then err_exit "return in dot script is $ret should be 3"
+fi
+chmod 755 $file
+( $file )
+ret=$?
+if (( $ret != 3 ))
+then err_exit "return in script is $ret should be 3"
+fi
+cat > $file <<!
+: line 1
+# next line should fail and cause an exit
+: > /
+exit 4
+!
+( . $file ; exit 5 ) 2> /dev/null
+ret=$?
+if (( $ret != 1 ))
+then err_exit "error in dot script is $ret should be 1"
+fi
+( $file; exit 5 ) 2> /dev/null
+ret=$?
+if (( $ret != 5 ))
+then err_exit "error in script is $ret should be 5"
+fi
+cat > $file <<\!
+print -r -- "$0"
+!
+x=$( . $file)
+if [[ $x != $0 ]]
+then err_exit "\$0 in a dot script is $x. Should be $0"
+fi
+x=$($SHELL -i --norc 2> /dev/null <<\!
+typeset -i x=1/0
+print hello
+!
+)
+if [[ $x != hello ]]
+then err_exit "interactive shell terminates with error in bltin"
+fi
+x=$( set -e
+ false
+ print bad
+ )
+if [[ $x != '' ]]
+then err_exit "set -e doesn't terminate script on error"
+fi
+x=$( set -e
+ trap 'exit 0' EXIT
+ false
+ print bad
+ )
+if (( $? != 0 ))
+then err_exit "exit 0 in trap should doesn't set exit value to 0"
+fi
+$SHELL <<\!
+trap 'exit 8' EXIT
+exit 1
+!
+if (( $? != 8 ))
+then err_exit "exit 8 in trap should set exit value to 8"
+fi
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/select.sh b/src/cmd/ksh93/tests/select.sh
new file mode 100755
index 0000000..07d0bde
--- /dev/null
+++ b/src/cmd/ksh93/tests/select.sh
@@ -0,0 +1,67 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+PS3='ABC '
+
+cat > $tmp/1 <<\!
+1) foo
+2) bar
+3) bam
+!
+
+select i in foo bar bam
+do case $i in
+ foo) break;;
+ *) err_exit "select 1 not working"
+ break;;
+ esac
+done 2> /dev/null <<!
+1
+!
+
+unset i
+select i in foo bar bam
+do case $i in
+ foo) err_exit "select foo not working" 2>&3
+ break;;
+ *) if [[ $REPLY != foo ]]
+ then err_exit "select REPLY not correct" 2>&3
+ fi
+ ( set -u; : $i ) || err_exit "select: i not set to null" 2>&3
+ break;;
+ esac
+done 3>&2 2> $tmp/2 <<!
+foo
+!
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/shtests b/src/cmd/ksh93/tests/shtests
new file mode 100755
index 0000000..5815aab
--- /dev/null
+++ b/src/cmd/ksh93/tests/shtests
@@ -0,0 +1,235 @@
+: ksh regression test harness :
+
+USAGE_LICENSE="[-author?David Korn <dgk@research.att.com>][-author?Glenn Fowler <gsf@research.att.com>][-copyright?Copyright (c) 2000-2011 AT&T Intellectual Property][-license?http://www.opensource.org/licenses/cpl1.0.txt]"
+
+command=shtests
+
+setslocale='*@(locale).sh'
+timesensitive='*@(options|sigchld|subshell).sh'
+
+USAGE=$'
+[-s8?
+@(#)$Id: shtests (AT&T Research) 2011-08-08 $
+]
+'$USAGE_LICENSE$'
+[+NAME?shtests - ksh regression test harness]
+[+DESCRIPTION?\bshtests\b is the \bksh\b(1) regression test harness for
+ \b$SHELL\b or \bksh\b if \bSHELL\b is not defined and exported. If
+ none of the \b--posix --utf8 --compile\b options are specified then
+ all three are enabled.]
+[+INPUT FILES?\bshtests\b regression test files are shell scripts that
+ run in an environment controlled by \bshtests\b. An identification
+ message is printed before and after each test on the standard output.
+ The default environment settings are:]
+ {
+ [+unset LANG]
+ [+unset LC_ALL]
+ [+LC_NUMERIC=C?\b.\b radix point assumed by all test scripts.]
+ [+VMALLOC_OPTIONS=abort?\bvmalloc\b(1) arena checking enabled
+ with \babort(2)\b on error.]
+ }
+[c:compile?Run test scripts using \bshcomp\b(1).]
+[d:debug?Enable \bshtests\b execution trace.]
+[l:locale?Disable \b--utf8\b and run the \b--posix\b and \b--compile\b
+ tests, if enabled, in the locale of the caller. This may cause invalid
+ regressions, especially for locales where \b.\b is not the radix
+ point.]
+[p:posix?Run the test scripts in the posix/C locale.]
+[t!:time?Include the current date/time in the test identification
+ messages.]
+[u:utf8?Run the test scripts in the ast-specific C.UTF-8 locale.]
+[v!:vmalloc_options?Run tests with \bVMALLOC_OPTIONS=abort\b. Test
+ script names matching \b'$timesensitive$'\b are run with
+ \bVMALLOC_OPTIONS\b unset.]
+[x:trace?Enable script execution trace.]
+
+[ test.sh ... ] [ name=value ... ]
+
+[+SEE ALSO?\bksh\b(1), \bregress\b(1), \brt\b(1)]
+'
+
+function usage
+{
+ OPTIND=0
+ getopts -a $command "$USAGE" OPT '--??long'
+ exit 2
+}
+
+unset DISPLAY ENV FIGNORE HISTFILE
+trap + PIPE # unadvertized -- set SIGPIPE to SIG_DFL #
+
+integer compile=0 debug=0 locale=0 posix=0 time=1 utf8=0
+typeset vmalloc_options=abort trace=
+vmalloc_options= #XXX# until multi-region vmalloc trace fixed #XXX#
+
+while getopts -a $command "$USAGE" OPT
+do case $OPT in
+ c) if (( $OPTARG ))
+ then compile=2
+ else compile=0
+ fi
+ ;;
+ d) debug=$OPTARG
+ ;;
+ l) locale=$OPTARG
+ ;;
+ p) posix=$OPTARG
+ ;;
+ t) time=$OPTARG
+ ;;
+ u) utf8=$OPTARG
+ ;;
+ v) if (( OPTARG ))
+ then vmalloc_options=abort
+ else vmalloc_options=
+ fi
+ ;;
+ x) trace=-x
+ ;;
+ *) usage
+ ;;
+ esac
+done
+shift $OPTIND-1
+
+if (( debug )) || [[ $trace ]]
+then export PS4=':$LINENO: '
+ if (( debug ))
+ then set -x
+ fi
+fi
+
+while [[ $1 == *=* ]]
+do eval export "$1"
+ shift
+done
+
+if (( !compile && !posix && !utf8 ))
+then compile=1
+ posix=1
+ utf8=1
+fi
+if (( locale ))
+then utf8=0
+ if [[ $LC_ALL ]]
+ then export LANG=$LC_ALL
+ fi
+else unset LANG LC_ALL
+ export LC_NUMERIC=C
+fi
+if [[ $VMALLOC_OPTIONS ]]
+then vmalloc_options=$VMALLOC_OPTIONS
+else VMALLOC_OPTIONS=$vmalloc_options
+fi
+[[ $VMALLOC_OPTIONS ]] || timesensitive=.
+export PATH PWD SHCOMP SHELL VMALLOC_OPTIONS
+PWD=$(pwd)
+SHELL=${SHELL-ksh}
+case $0 in
+/*) d=$(dirname $0);;
+*/*) d=$PWD/$(dirname $0);;
+*) d=$PWD;;
+esac
+case $SHELL in
+/*) ;;
+*/*) SHELL=$d/$SHELL;;
+*) SHELL=$(whence $SHELL);;
+esac
+PATH=/bin:/usr/bin
+if [[ -d /usr/ucb ]]
+then PATH=$PATH:/usr/ucb
+fi
+PATH=$PATH:$d
+if [[ $INSTALLROOT && -r $INSTALLROOT/bin/.paths ]]
+then PATH=$INSTALLROOT/bin:$PATH
+fi
+if [[ ${SHELL%/*} != $INSTALLROOT/bin ]]
+then PATH=${SHELL%/*}:$PATH
+fi
+if [[ ! $SHCOMP ]]
+then s=${SHELL:##*sh}
+ s=${SHELL:%/*}/shcomp$s
+ if [[ -x $s ]]
+ then SHCOMP=$s
+ elif [[ -x ${s%-g} ]]
+ then SHCOMP=${s%-g}
+ else SHCOMP=shcomp
+ fi
+fi
+if (( compile ))
+then if whence $SHCOMP > /dev/null
+ then tmp=$(mktemp -dt) || { echo mktemp -dt failed >&2; exit 1; }
+ trap "cd /; rm -rf $tmp" EXIT
+ elif (( compile > 1 ))
+ then echo $0: --compile: $SHCOMP not found >&2
+ exit 1
+ else compile=0
+ fi
+fi
+typeset -A tests
+for i in ${*-*.sh}
+do if [[ ! -r $i ]]
+ then echo $0: $i: not found >&2
+ continue
+ fi
+ t=$(grep -c err_exit $i)
+ if (( t > 2 ))
+ then (( t = t - 2 ))
+ fi
+ tests[$i]=$t
+ T=test
+ if (( t != 1 ))
+ then T=${T}s
+ fi
+ u=${i##*/}
+ u=${u%.sh}
+ if [[ $i == $timesensitive ]]
+ then VMALLOC_OPTIONS=
+ fi
+ if (( posix || utf8 ))
+ then locales=
+ (( posix )) && locales+=" ${LANG:-C}"
+ [[ $utf8 == 0 || $i == $setslocale ]] || locales+=" C.UTF-8"
+ for lang in $locales
+ do o=$u
+ if [[ $lang == C ]]
+ then lang=
+ else o="$o($lang)"
+ lang=LANG=$lang
+ fi
+ echo test $o begins ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"}
+ E=error
+ if eval $lang \$SHELL \$trace \$i
+ then echo test $o passed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} "[ $t $T 0 ${E}s ]"
+ else e=$?
+ if (( e != 1 ))
+ then E=${E}s
+ fi
+ echo test $o failed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T $e $E ]"
+ fi
+ done
+ fi
+ if (( compile ))
+ then c=$tmp/shcomp-$u.ksh
+ o="$u(shcomp)"
+ echo test $o begins ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"}
+ E=error
+ if $SHCOMP $i > $c
+ then if $SHELL $trace $c
+ then echo test $o passed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} "[ $t $T 0 ${E}s ]"
+ else e=$?
+ if (( e != 1 ))
+ then E=${E}s
+ fi
+ echo test $o failed ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T $e $E ]"
+ fi
+ else e=$?
+ t=1
+ T=test
+ echo test $o failed to compile ${time:+"at $(date +%Y-%m-%d+%H:%M:%S)"} with exit code $e "[ $t $T 1 $E ]"
+ fi
+ if [[ $i == $timesensitive ]]
+ then VMALLOC_OPTIONS=$vmalloc_options
+ fi
+ fi
+done
diff --git a/src/cmd/ksh93/tests/sigchld.sh b/src/cmd/ksh93/tests/sigchld.sh
new file mode 100755
index 0000000..d4dcee6
--- /dev/null
+++ b/src/cmd/ksh93/tests/sigchld.sh
@@ -0,0 +1,160 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+float DELAY=${1:-0.2}
+integer FOREGROUND=10 BACKGROUND=2 Errors=0
+
+s=$($SHELL -c '
+integer i foreground=0 background=0
+float delay='$DELAY' d=0 s=0
+
+set --errexit
+
+trap "(( background++ ))" CHLD
+
+(( d = delay ))
+for ((i = 0; i < '$BACKGROUND'; i++))
+do sleep $d &
+ (( d *= 4 ))
+ (( s += d ))
+done
+for ((i = 0; i < '$FOREGROUND'; i++))
+do (( foreground++ ))
+ sleep $delay
+ (( s -= delay ))
+ $SHELL -c : > /dev/null # foreground does not generate SIGCHLD
+done
+if (( (s += delay) < 1 ))
+then (( s = 1 ))
+fi
+sleep $s
+wait
+print foreground=$foreground background=$background
+') || err_exit "test loop failed"
+
+eval $s
+
+(( foreground == FOREGROUND )) || err_exit "expected '$FOREGROUND foreground' -- got '$foreground' (DELAY=$DELAY)"
+(( background == BACKGROUND )) || err_exit "expected '$BACKGROUND background' -- got '$background' (DELAY=$DELAY)"
+
+set --noerrexit
+
+if [[ ${.sh.version} == Version?*([[:upper:]])J* ]]
+then
+
+ jobmax=4
+ got=$($SHELL -c '
+ JOBMAX='$jobmax' JOBCOUNT=$(('$jobmax'*2))
+ integer running=0 maxrunning=0
+ trap "((running--))" CHLD
+ for ((i=0; i<JOBCOUNT; i++))
+ do sleep 1 &
+ if ((++running > maxrunning))
+ then ((maxrunning=running))
+ fi
+ done
+ wait
+ print running=$running maxrunning=$maxrunning
+ ')
+ exp='running=0 maxrunning='$jobmax
+ [[ $got == $exp ]] || err_exit "SIGCHLD trap queueing failed -- expected '$exp', got '$got'"
+
+ got=$($SHELL -c '
+ typeset -A proc
+
+ trap "
+ print \${proc[\$!].name} \${proc[\$!].status} \$?
+ unset proc[\$!]
+ " CHLD
+
+ { sleep 3; print a; exit 1; } &
+ proc[$!]=( name=a status=1 )
+
+ { sleep 2; print b; exit 2; } &
+ proc[$!]=( name=b status=2 )
+
+ { sleep 1; print c; exit 3; } &
+ proc[$!]=( name=c status=3 )
+
+ while (( ${#proc[@]} ))
+ do sleep -s
+ done
+ ')
+ exp='c\nc 3 3\nb\nb 2 2\na\na 1 1'
+ [[ $got == $exp ]] || err_exit "SIGCHLD trap queueing failed -- expected $(printf %q "$exp"), got $(printf %q "$got")"
+
+fi
+
+{
+got=$( ( sleep 1;print $'\n') | $SHELL -c 'function handler { : ;}
+ trap handler CHLD; sleep .3 & IFS= read; print good')
+} 2> /dev/null
+[[ $got == good ]] || err_exit 'SIGCLD handler effects read behavior'
+
+set -- $(
+ (
+ $SHELL -xc $'
+ trap \'wait $!; print $! $?\' CHLD
+ { sleep 0.1; exit 9; } &
+ print $!
+ sleep 0.5
+ '
+ ) 2>/dev/null; print $?
+)
+if (( $# != 4 ))
+then err_exit "CHLD trap failed -- expected 4 args, got $#"
+elif (( $4 != 0 ))
+then err_exit "CHLD trap failed -- exit code $4"
+elif (( $1 != $2 ))
+then err_exit "child pid mismatch -- got '$1' != '$2'"
+elif (( $3 != 9 ))
+then err_exit "child status mismatch -- expected '9', got '$3'"
+fi
+
+trap '' CHLD
+integer d
+for ((d=0; d < 2000; d++))
+do if print foo | grep bar
+ then break
+ fi
+done
+(( d==2000 )) || err_exit "trap '' CHLD causes side effects d=$d"
+trap - CHLD
+
+tmp=$(mktemp -dt)
+trap 'rm -rf $tmp' EXIT
+x=$($SHELL 2> /dev/null -ic '/bin/notfound; sleep .5 & sleep 1;jobs')
+[[ $x == *Done* ]] || err_exit 'SIGCHLD blocked after notfound'
+x=$($SHELL 2> /dev/null -ic 'kill -0 12345678901234567876; sleep .5 & sleep 1;jobs')
+[[ $x == *Done* ]] || err_exit 'SIGCHLD blocked after error message'
+print 'set -o monitor;sleep .5 & sleep 1;jobs' > $tmp/foobar
+chmod +x $tmp/foobar
+x=$($SHELL -c "echo | $tmp/foobar")
+[[ $x == *Done* ]] || err_exit 'SIGCHLD blocked for script at end of pipeline'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/signal.sh b/src/cmd/ksh93/tests/signal.sh
new file mode 100755
index 0000000..c6e150b
--- /dev/null
+++ b/src/cmd/ksh93/tests/signal.sh
@@ -0,0 +1,435 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors++ ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+cd $tmp || err_exit "cd $tmp failed"
+
+unset n s t
+typeset -A SIG
+for s in $(kill -l)
+do if ! n=$(kill -l $s 2>/dev/null)
+ then err_exit "'kill -l $s' failed"
+ elif ! t=$(kill -l $n 2>/dev/null)
+ then err_exit "'kill -l $n' failed"
+ elif [[ $s == ?(SIG)$t ]]
+ then SIG[${s#SIG}]=1
+ elif ! m=$(kill -l $t 2>/dev/null)
+ then err_exit "'kill -l $t' failed"
+ elif [[ $m != $n ]]
+ then err_exit "'kill -l $s' => $n, 'kill -l $n' => $t, kill -l $t => $m -- expected $n"
+ fi
+done
+
+(
+ set --pipefail
+ {
+ $SHELL 2> out2 <<- \EOF
+ g=false
+ trap 'print -u2 PIPED; $g && exit 0;g=true' PIPE
+ while :
+ do print hello
+ done
+ EOF
+ } | head > /dev/null
+ (( $? == 0)) || err_exit "SIGPIPE with wrong error code $?"
+ [[ $(<out2) == $'PIPED\nPIPED' ]] || err_exit 'SIGPIPE output on standard error is not correct'
+) &
+cop=$!
+{ sleep 4; kill $cop; } 2>/dev/null &
+spy=$!
+if wait $cop 2>/dev/null
+then kill $spy 2>/dev/null
+else err_exit "pipe with --pipefail PIPE trap hangs"
+fi
+wait
+rm -f out2
+
+[[ $( trap 'print -n got_child' SIGCHLD
+ sleep 2 &
+ for ((i=0; i < 4; i++))
+ do sleep .75
+ print -n $i
+ done) == 01got_child23 ]] || err_exit 'SIGCHLD not working'
+
+# begin standalone SIGINT test generation
+
+cat > tst <<'!'
+# shell trap tests
+#
+# tst control script that calls tst-1, must be run by ksh
+# tst-1 calls tst-2
+# tst-2 calls tst-3
+# tst-3 defaults or handles and discards/propagates SIGINT
+#
+# initial -v option lists script entry and SIGINT delivery
+#
+# three test options
+#
+# d call next script directly, otherwise via $SHELL -c
+# t trap, echo, and kill self on SIGINT, otherwise x or SIGINT default if no x
+# x trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit, otherwise SIGINT default
+# z trap, echo on SIGINT, and tst-3 exit 0, tst-2 exit 0, otherwise SIGINT default
+#
+# Usage: tst [-v] [-options] shell-to-test ...
+
+# "trap + sig" is an unadvertized extension for this test
+# if run from nmake SIGINT is set to SIG_IGN
+# this call sets it back to SIG_DFL
+# semantics w.r.t. function scope must be worked out before
+# making it public
+trap + INT
+
+set -o monitor
+
+function gen
+{
+ typeset o t x d
+ for x in - x z
+ do case $x in
+ [$1]) for t in - t
+ do case $t in
+ [$1]) for d in - d
+ do case $d in
+ [$1]) o="$o $x$t$d"
+ esac
+ done
+ esac
+ done
+ esac
+ done
+ echo '' $o
+}
+
+case $1 in
+-v) v=v; shift ;;
+-*v*) v=v ;;
+*) v= ;;
+esac
+case $1 in
+*' '*) o=$1; shift ;;
+-*) o=$(gen $1); shift ;;
+*) o=$(gen -txd) ;;
+esac
+case $# in
+0) set ksh bash ksh88 pdksh ash zsh ;;
+esac
+for f in $o
+do case $# in
+ 1) ;;
+ *) echo ;;
+ esac
+ for sh
+ do if $sh -c 'exit 0' > /dev/null 2>&1
+ then case $# in
+ 1) printf '%3s ' "$f" ;;
+ *) printf '%16s %3s ' "$sh" "$f" ;;
+ esac
+ $sh tst-1 $v$f $sh > tst.out &
+ wait
+ echo $(cat tst.out)
+ fi
+ done
+done
+case $# in
+1) ;;
+*) echo ;;
+esac
+!
+cat > tst-1 <<'!'
+exec 2>/dev/null
+case $1 in
+*v*) echo 1-main ;;
+esac
+{
+ sleep 2
+ case $1 in
+ *v*) echo "SIGINT" ;;
+ esac
+ kill -s INT 0
+} &
+case $1 in
+*t*) trap '
+ echo 1-intr
+ trap - INT
+ # omitting the self kill exposes shells that deliver
+ # the SIGINT trap but exit 0 for -xt
+ # kill -s INT $$
+ ' INT
+ ;;
+esac
+case $1 in
+*d*) tst-2 $1 $2; status=$? ;;
+*) $2 -c "tst-2 $1 $2"; status=$? ;;
+esac
+printf '1-%04d\n' $status
+sleep 2
+!
+cat > tst-2 <<'!'
+case $1 in
+*z*) trap '
+ echo 2-intr
+ exit 0
+ ' INT
+ ;;
+*x*) trap '
+ echo 2-intr
+ exit
+ ' INT
+ ;;
+*t*) trap '
+ echo 2-intr
+ trap - INT
+ kill -s INT $$
+ ' INT
+ ;;
+esac
+case $1 in
+*v*) echo 2-main ;;
+esac
+case $1 in
+*d*) tst-3 $1 $2; status=$? ;;
+*) $2 -c "tst-3 $1 $2"; status=$? ;;
+esac
+printf '2-%04d\n' $status
+!
+cat > tst-3 <<'!'
+case $1 in
+*[xz]*) trap '
+ sleep 2
+ echo 3-intr
+ exit 0
+ ' INT
+ ;;
+*) trap '
+ sleep 2
+ echo 3-intr
+ trap - INT
+ kill -s INT $$
+ ' INT
+ ;;
+esac
+case $1 in
+*v*) echo 3-main ;;
+esac
+sleep 5
+printf '3-%04d\n' $?
+!
+chmod +x tst tst-?
+
+# end standalone test generation
+
+export PATH=$PATH:
+typeset -A expected
+expected[---]="3-intr"
+expected[--d]="3-intr"
+expected[-t-]="3-intr 2-intr 1-intr 1-0258"
+expected[-td]="3-intr 2-intr 1-intr 1-0258"
+expected[x--]="3-intr 2-intr 1-0000"
+expected[x-d]="3-intr 2-intr 1-0000"
+expected[xt-]="3-intr 2-intr 1-intr 1-0000"
+expected[xtd]="3-intr 2-intr 1-intr 1-0000"
+expected[z--]="3-intr 2-intr 1-0000"
+expected[z-d]="3-intr 2-intr 1-0000"
+expected[zt-]="3-intr 2-intr 1-intr 1-0000"
+expected[ztd]="3-intr 2-intr 1-intr 1-0000"
+
+tst $SHELL > tst.got
+
+while read ops out
+do [[ $out == ${expected[$ops]} ]] || err_exit "interrupt $ops test failed -- expected '${expected[$ops]}', got '$out'"
+done < tst.got
+
+if [[ ${SIG[USR1]} ]]
+then float s=$SECONDS
+ [[ $(LC_ALL=C $SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell ignoring signal does not send signal to parent'
+ (( (SECONDS-s) < 4 )) && err_exit 'parent does not wait for child to complete before handling signal'
+ ((s = SECONDS))
+ [[ $(LC_ALL=C $SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "exit" USR1 ; exec kill -USR1 $$ & sleep 5); print done') == SIGUSR1 ]] || err_exit 'subshell catching signal does not send signal to parent'
+ (( SECONDS-s < 4 )) && err_exit 'parent completes early'
+fi
+
+yes=$(whence -p yes)
+if [[ $yes ]]
+then for exp in TERM VTALRM PIPE
+ do if [[ ${SIG[$exp]} ]]
+ then {
+ $SHELL <<- EOF
+ foo() { return 0; }
+ trap foo EXIT
+ { sleep 2; kill -$exp \$\$; sleep 3; kill -0 \$\$ && kill -KILL \$\$; } &
+ $yes |
+ while read yes
+ do (/bin/date; sleep .1)
+ done > /dev/null
+ EOF
+ } 2>> /dev/null
+ got=$(kill -l $?)
+ [[ $exp == $got ]] || err_exit "kill -$exp \$\$ failed, required termination by signal '$got'"
+ fi
+ done
+fi
+
+SECONDS=0
+$SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; (sleep 5); print finished' > $tmp/sig
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+$SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; sleep 5; print finished' > $tmp/sig
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+{ $SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; (sleep 5); print finished' > $tmp/sig ;} 2> /dev/null
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+{ $SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; sleep 5; print finished' > $tmp/sig ;} 2> /dev/null
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+x=$(<$tmp/sig)
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+x=$($SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; (sleep 5); print finished')
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+SECONDS=0
+x=$($SHELL 2> /dev/null -c 'sleep 2 && kill $$ & trap "print done; exit 3" EXIT; sleep 5; print finished')
+e=$?
+[[ $e == 3 ]] || err_exit "exit status failed -- expected 3, got $e"
+[[ $x == done ]] || err_exit "output failed -- expected 'done', got '$x'"
+(( SECONDS > 3.5 )) && err_exit "took $SECONDS seconds, expected around 2"
+
+trap '' SIGBUS
+[[ $($SHELL -c 'trap date SIGBUS; trap -p SIGBUS') ]] && err_exit 'SIGBUS should not have a trap'
+trap -- - SIGBUS
+
+{
+ x=$(
+ $SHELL <<- \++EOF
+ timeout()
+ {
+ trap 'trap - TERM; return' TERM
+ ( sleep $1; kill -TERM $$ ) >/dev/null 2>&1 &
+ sleep 3
+ }
+ timeout 1
+ print ok
+++EOF
+ )
+} 2> /dev/null
+[[ $x == ok ]] || err_exit 'return without arguments in trap not preserving exit status'
+
+x=$(
+ $SHELL <<- \++EOF
+ set -o pipefail
+ foobar()
+ {
+ for ((i=0; i < 10000; i++))
+ do print abcdefghijklmnopqrstuvwxyz
+ done | head > /dev/null
+ }
+ foobar
+ print ok
+ ++EOF
+)
+[[ $x == ok ]] || err_exit 'SIGPIPE exit status causes PIPE signal to be propogaged'
+
+x=$(
+ $SHELL <<- \EOF
+ trap "print GNAW" URG
+ print 1
+ ( sleep 1 ; kill -URG $$ ; sleep 1 ; print S1 ; )
+ print 2
+EOF
+)
+[[ $x == $'1\nS1\nGNAW\n2' ]] || err_exit 'signal ignored in subshell not propagated to parent'
+
+if [[ ${SIG[RTMIN]} ]]
+then {
+ $SHELL <<- \EOF
+ trap : RTMIN
+ for ((i=0 ; i < 3 ; i++))
+ do sleep 1
+ kill -RTMIN $$ 2> /dev/null
+ done &
+ wait
+ EOF
+ } 2> /dev/null
+ [[ $? == 0 ]] && err_exit 'wait interrupted by caught signal should have non-zero exit status'
+ {
+ $SHELL <<- \EOF
+ for ((i=0 ; i < 3 ; i++))
+ do sleep 1
+ kill -RTMIN $$ 2> /dev/null
+ done &
+ wait
+ EOF
+ } 2> /dev/null
+ [[ $(kill -l $?) == RTMIN ]] || err_exit 'wait interrupted by signal not caught should exit with the value of that signal+256'
+fi
+
+function b
+{
+ sleep 3
+ endb=1
+}
+
+function a
+{
+ trap 'print int' TERM
+ b
+ enda=1
+}
+
+{ /bin/sleep 1;kill -s TERM $$;}&
+unset enda endb
+a
+[[ $endb ]] && err_exit 'TERM signal did not kill function b'
+[[ $enda == 1 ]] || err_exit 'TERM signal killed function a'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/statics.sh b/src/cmd/ksh93/tests/statics.sh
new file mode 100755
index 0000000..7e67279
--- /dev/null
+++ b/src/cmd/ksh93/tests/statics.sh
@@ -0,0 +1,690 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# Written by Roland Mainz <roland.mainz@nrubsig.org>
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors < 127 && Errors++ ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+set -o nounset
+Command=${0##*/}
+integer Errors=0
+
+
+
+typeset -T test_t=(
+ typeset name
+ typeset cmd
+ typeset expected_output
+)
+
+function testfunc
+{
+ integer line_number=$1
+ typeset cmd="$2"
+ typeset expected_output="$3"
+ typeset output
+
+ output="$($SHELL -c "${cmd}" 2>&1 )"
+
+ [[ "${output}" == "${expected_output}" ]] || err_exit ${line_number} "${output} != ${expected_output}"
+}
+
+# test1: basic tests
+function test1
+{
+ # string
+ testfunc ${LINENO} '(function l { typeset -S x ; x+="#" ; $1 && print "$x" ; } ; l false ; l false ; l true)' "###"
+ testfunc ${LINENO} 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false ; l false ; l true' ">###"
+ testfunc ${LINENO} 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false ; (l false) ; l true' ">##"
+ testfunc ${LINENO} 'function l { typeset -S x=">" ; x+="#" ; $1 && print "$x" ; } ; l false; ( ulimit -c 0 ; l false) ; l true' ">##"
+
+ # integer
+ # (normal)
+ testfunc ${LINENO} '(function l { integer -S x ; x+=1 ; $1 && print "$x" ; } ; l false ; l false ; l true )' "3"
+ testfunc ${LINENO} '(function l { integer -S x ; x+=1 ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "2"
+ # (int)
+ testfunc ${LINENO} '(function l { typeset -S -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; l false ; l true )' "3"
+ testfunc ${LINENO} '(function l { typeset -S -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "2"
+ # (short)
+ testfunc ${LINENO} '(function l { typeset -S -s -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; l false ; l true )' "3"
+ testfunc ${LINENO} '(function l { typeset -S -s -i x ; x+=1 ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "2"
+
+ # float
+ testfunc ${LINENO} '(function l { float -S x=0.5 ; (( x+=.5 )) ; $1 && print "$x" ; } ; l false ; l false ; l true )' "2"
+ testfunc ${LINENO} '(function l { float -S x=0.5 ; (( x+=.5 )) ; $1 && print "$x" ; } ; l false ; (l false) ; l true )' "1.5"
+
+ return 0
+}
+
+# test2: test the more complex datatypes
+function test2
+{
+ compound out=( typeset stdout stderr ; integer res )
+ integer i
+
+ test_t -r -a tests=(
+ (
+ name='compound'
+ cmd=$'
+ function l
+ {
+ compound -S s=(
+ integer a=1
+ integer b=2
+ )
+
+ (( s.a++, s.b++ ))
+
+ $1 && printf "a=%d, b=%d\n" s.a s.b
+ }
+ (l false ; l false ; l true ; printf ";")
+ (l false ; l false ; l true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+ (
+ name='compound_nameref'
+ cmd=$'
+ function l_n
+ {
+ nameref sn=$2
+ (( sn.a++, sn.b++ ))
+
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function l
+ {
+ compound -S s=( a=1 b=2 )
+ l_n $1 s
+ }
+ (l false ; l false ; l true ; printf ";")
+ (l false ; l false ; l true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='type'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+ function l
+ {
+ ab_t -S s
+
+ s.increment
+
+ $1 && printf "a=%d, b=%d\n" s.a s.b
+ }
+ (l false ; l false ; l true ; printf ";")
+ (l false ; l false ; l true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='type_nameref'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+ function l_n
+ {
+ nameref sn=$2
+
+ sn.increment
+
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function l
+ {
+ ab_t -S s
+ l_n $1 s
+ }
+ (l false ; l false ; l true ; printf ";")
+ (l false ; l false ; l true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='indexed_string_array_appendelement'
+ cmd=$'
+ function ar
+ {
+ typeset -a -S s=( "hello" )
+
+ s+=( "an element" )
+
+ $1 && { printf "%s" "${s[@]}" ; printf "\n" ; }
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;'
+ )
+
+ (
+ name='indexed_string_array_nameref_appendelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+ sn+=( "an element" )
+
+ $1 && { printf "%s" "${sn[@]}" ; printf "\n" ; }
+ }
+ function ar
+ {
+ typeset -a -S s=( "hello" )
+ ar_n $1 s
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;'
+ )
+
+ (
+ name='associative_string_array_appendelement'
+ cmd=$'
+ function ar
+ {
+ typeset -A -S s=( [0]="hello" )
+
+ s[$(( ${#s[@]} + 1))]="an element"
+
+ $1 && { printf "%s" "${s[@]}" ; printf "\n" ; }
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;'
+ )
+
+ (
+ name='associative_string_array_nameref_appendelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ sn[$(( ${#sn[@]} + 1))]="an element"
+
+ $1 && { printf "%s" "${sn[@]}" ; printf "\n" ; }
+ }
+ function ar
+ {
+ typeset -A -S s=( [0]="hello" )
+ ar_n $1 s
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'helloan elementan elementan element\n;helloan elementan elementan element\n;'
+ )
+
+ (
+ name='indexed_compound_array_editelement'
+ cmd=$'
+ function ar
+ {
+ compound -S -a s=(
+ [5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ (( s[5].a++, s[5].b++ ))
+ $1 && printf "a=%d, b=%d\n" s[5].a s[5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='indexed_compound_array_nameref_editelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ (( sn.a++, sn.b++ ))
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ compound -S -a s=(
+ [5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ ar_n $1 s[5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='2d_indexed_compound_array_editelement'
+ cmd=$'
+ function ar
+ {
+ compound -S -a s=(
+ [8][5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ (( s[8][5].a++, s[8][5].b++ ))
+ $1 && printf "a=%d, b=%d\n" s[8][5].a s[8][5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='2d_indexed_compound_array_nameref_editelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ (( sn.a++, sn.b++ ))
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ compound -S -a s=(
+ [8][5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ ar_n $1 s[8][5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+ (
+ name='4d_indexed_compound_array_editelement'
+ cmd=$'
+ function ar
+ {
+ compound -S -a s=(
+ [8][5][0][9]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ (( s[8][5][0][9].a++, s[8][5][0][9].b++ ))
+ $1 && printf "a=%d, b=%d\n" s[8][5][0][9].a s[8][5][0][9].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='4d_indexed_compound_array_nameref_editelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ (( sn.a++, sn.b++ ))
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ compound -S -a s=(
+ [8][5][0][9]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ ar_n $1 s[8][5][0][9]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='associative_compound_array_editelement'
+ cmd=$'
+ function ar
+ {
+ compound -S -A s=(
+ [5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ (( s[5].a++, s[5].b++ ))
+ $1 && printf "a=%d, b=%d\n" s[5].a s[5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='associative_compound_array_nameref_editelement'
+ cmd=$'
+ function ar_n
+ {
+ nameref sn=$2
+
+ (( sn.a++, sn.b++ ))
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ compound -S -A s=(
+ [5]=(
+ integer a=1
+ integer b=2
+ )
+ )
+
+ ar_n $1 s[5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='indexed_type_array_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ?
+
+ s[5].increment
+ $1 && printf "a=%d, b=%d\n" s[5].a s[5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='indexed_type_array_nameref_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar_n
+ {
+ nameref sn=$2
+
+ sn.increment
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ?
+
+ ar_n $1 s[5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='2d_indexed_type_array_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[9][5] ]] || s[9][5]=( ) # how do I init an array of types ?
+
+ s[9][5].increment
+ $1 && printf "a=%d, b=%d\n" s[9][5].a s[9][5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='2d_indexed_type_array_nameref_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar_n
+ {
+ nameref sn=$2
+
+ sn.increment
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[9][5] ]] || s[9][5]=( ) # how do I init an array of types ?
+
+ ar_n $1 s[9][5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='associative_type_array_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar
+ {
+ ab_t -S -A s
+ [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ?
+
+ s[5].increment
+ $1 && printf "a=%d, b=%d\n" s[5].a s[5].b
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ (
+ name='associative_type_array_nameref_editelement'
+ cmd=$'
+ typeset -T ab_t=(
+ integer a=1
+ integer b=2
+
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+
+ function ar_n
+ {
+ nameref sn=$2
+
+ sn.increment
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ ab_t -S -A s
+ [[ -v s[5] ]] || s[5]=( ) # how do I init an array of types ?
+
+ ar_n $1 s[5]
+ }
+ (ar false ; ar false ; ar true ; printf ";")
+ (ar false ; ar false ; ar true ; printf ";")
+ '
+ expected_output=$'a=4, b=5\n;a=4, b=5\n;'
+ )
+
+ )
+
+ for (( i=0 ; i < ${#tests[@]} ; i++ )) ; do
+ nameref currtest=tests[i]
+
+#print -u2 -- "${currtest.cmd}"
+ out.stderr="${ { out.stdout="${ ${SHELL} -o nounset -c "${currtest.cmd}" ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
+
+ (( out.res == 0 )) || err_exit "${currtest.name}: Test shell returned with exit code ${out.res}"
+ [[ "${out.stdout}" == "${currtest.expected_output}" ]] || err_exit "${currtest.name}: Expected stdout == $(printf "%q\n" "${currtest.expected_output}"), got $(printf "%q\n" "${out.stdout}")"
+ [[ "${out.stderr}" == '' ]] || err_exit "${currtest.name}: Expected empty stderr, got $(printf "%q\n" "${out.stderr}")"
+ done
+
+ return 0
+}
+
+# run tests
+test1
+test2
+
+
+# Test visibilty of "global" vs. "static" variables. if we have a "static" variable in a
+# function and "unset" it we should see a global variable with the same
+# name, right ?
+integer hx=5
+function test_hx_scope
+{
+ integer -S hx=9
+ $2 && unset hx
+ $1 && printf 'hx=%d\n' hx
+}
+test_hx_scope false false
+test_hx_scope false false
+# first test the "unset" call in a $(...) subshell...
+[[ "$( test_hx_scope true true )" == 'hx=5' ]] || err_exit "can't see global variable hx after unsetting static variable hx"
+# ... end then test whether the value has changed.
+[[ "${ test_hx_scope true false ;}" == 'hx=9' ]] || err_exit "hx variable somehow changed"
+
+out=$(function fun2
+{
+ nameref sn=$1
+ (( sn.a++, sn.b++ ))
+ $2 && printf "a=%d, b=%d\n" sn.a sn.b
+}
+function fun1
+{
+ compound -S s=( a=0 b=0 )
+ fun2 s $1
+}
+(fun1 false ; fun1 false ; fun1 true)
+(fun1 false ; fun1 false ; fun1 true)
+)
+[[ $out == $'a=3, b=3\na=3, b=3' ]] || err_exit 'static variables in functions with initializers not working'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/subshell.sh b/src/cmd/ksh93/tests/subshell.sh
new file mode 100755
index 0000000..819811a
--- /dev/null
+++ b/src/cmd/ksh93/tests/subshell.sh
@@ -0,0 +1,582 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u$Error_fd -n "\t"
+ print -u$Error_fd -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0 Error_fd=2
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+bincat=$(PATH=$(getconf PATH) whence -p cat)
+
+z=()
+z.foo=( [one]=hello [two]=(x=3 y=4) [three]=hi)
+z.bar[0]=hello
+z.bar[2]=world
+z.bar[1]=(x=4 y=5)
+val='(
+ typeset -a bar=(
+ [0]=hello
+ [2]=world
+ [1]=(
+ x=4
+ y=5
+ )
+ )
+ typeset -A foo=(
+ [one]=hello
+ [three]=hi
+ [two]=(
+ x=3
+ y=4
+ )
+ )
+)'
+[[ $z == "$val" ]] || err_exit 'compound variable with mixed arrays not working'
+z.bar[1]=yesyes
+[[ ${z.bar[1]} == yesyes ]] || err_exit 'reassign of index array compound variable fails'
+z.bar[1]=(x=12 y=5)
+[[ ${z.bar[1]} == $'(\n\tx=12\n\ty=5\n)' ]] || err_exit 'reassign array simple to compound variable fails'
+eval val="$z"
+(
+ z.foo[three]=good
+ [[ ${z.foo[three]} == good ]] || err_exit 'associative array assignment in subshell not working'
+)
+[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment'
+eval val="$z"
+(
+ z.foo[two]=ok
+ [[ ${z.foo[two]} == ok ]] || err_exit 'associative array assignment to compound variable in subshell not working'
+ z.bar[1]=yes
+ [[ ${z.bar[1]} == yes ]] || err_exit 'index array assignment to compound variable in subshell not working'
+)
+[[ $z == "$val" ]] || err_exit 'compound variable changes after associative array assignment'
+
+x=(
+ foo=( qqq=abc rrr=def)
+ bar=( zzz=no rst=fed)
+)
+eval val="$x"
+(
+ unset x.foo
+ [[ ${x.foo.qqq} ]] && err_exit 'x.foo.qqq should be unset'
+ x.foo=good
+ [[ ${x.foo} == good ]] || err_exit 'x.foo should be good'
+)
+[[ $x == "$val" ]] || err_exit 'compound variable changes after unset leaves'
+unset l
+(
+ l=( a=1 b="BE" )
+)
+[[ ${l+foo} != foo ]] || err_exit 'l should be unset'
+
+Error_fd=9
+eval "exec $Error_fd>&2 2>/dev/null"
+
+TEST_notfound=notfound
+while whence $TEST_notfound >/dev/null 2>&1
+do TEST_notfound=notfound-$RANDOM
+done
+
+
+integer BS=1024 nb=64 ss=60 bs no
+for bs in $BS 1
+do $SHELL -c '
+ {
+ sleep '$ss'
+ kill -KILL $$
+ } &
+ set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs')
+ print ${#1}
+ kill $!
+ ' > $tmp/sub 2>/dev/null
+ no=$(<$tmp/sub)
+ (( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs -- expected $((BS*nb)), got ${no:-0}"
+done
+# this time with redirection on the trailing command
+for bs in $BS 1
+do $SHELL -c '
+ {
+ sleep 2
+ sleep '$ss'
+ kill -KILL $$
+ } &
+ set -- $(printf %.'$(($BS*$nb))'c x | dd bs='$bs' 2>/dev/null)
+ print ${#1}
+ kill $!
+ ' > $tmp/sub 2>/dev/null
+ no=$(<$tmp/sub)
+ (( no == (BS * nb) )) || err_exit "shell hangs on command substitution output size >= $BS*$nb with write size $bs and trailing redirection -- expected $((BS*nb)), got ${no:-0}"
+done
+
+# exercise command substitutuion trailing newline logic w.r.t. pipe vs. tmp file io
+
+set -- \
+ 'post-line print' \
+ '$TEST_unset; ($TEST_fork; print 1); print' \
+ 1 \
+ 'pre-line print' \
+ '$TEST_unset; ($TEST_fork; print); print 1' \
+ $'\n1' \
+ 'multiple pre-line print' \
+ '$TEST_unset; ($TEST_fork; print); print; ($TEST_fork; print 1); print' \
+ $'\n\n1' \
+ 'multiple post-line print' \
+ '$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print); print' \
+ 1 \
+ 'intermediate print' \
+ '$TEST_unset; ($TEST_fork; print 1); print; ($TEST_fork; print 2); print' \
+ $'1\n\n2' \
+ 'simple variable' \
+ '$TEST_unset; ($TEST_fork; l=2; print "$l"); print $l' \
+ 2 \
+ 'compound variable' \
+ '$TEST_unset; ($TEST_fork; l=(a=2 b="BE"); print "$l"); print $l' \
+ $'(\n\ta=2\n\tb=BE\n)' \
+
+export TEST_fork TEST_unset
+
+while (( $# >= 3 ))
+do txt=$1
+ cmd=$2
+ exp=$3
+ shift 3
+ for TEST_unset in '' 'unset var'
+ do for TEST_fork in '' 'ulimit -c 0'
+ do for TEST_shell in "eval" "$SHELL -c"
+ do if ! got=$($TEST_shell "$cmd")
+ then err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt print failed"
+ elif [[ "$got" != "$exp" ]]
+ then EXP=$(printf %q "$exp")
+ GOT=$(printf %q "$got")
+ err_exit "${TEST_shell/*-c/\$SHELL -c} ${TEST_unset:+unset }${TEST_fork:+fork }$txt command substitution failed -- expected $EXP, got $GOT"
+ fi
+ done
+ done
+ done
+done
+
+r=$( ($SHELL -c '
+ {
+ sleep 32
+ kill -KILL $$
+ } &
+ for v in $(set | sed "s/=.*//")
+ do command unset $v
+ done
+ typeset -Z5 I
+ for ((I = 0; I < 1024; I++))
+ do eval A$I=1234567890
+ done
+ a=$(set 2>&1)
+ print ok
+ kill -KILL $!
+') 2>/dev/null)
+[[ $r == ok ]] || err_exit "large subshell command substitution hangs"
+
+for TEST_command in '' $TEST_notfound
+do for TEST_exec in '' 'exec'
+ do for TEST_fork in '' 'ulimit -c 0;'
+ do for TEST_redirect in '' '>/dev/null'
+ do for TEST_substitute in '' ': $'
+ do
+
+ TEST_test="$TEST_substitute($TEST_fork $TEST_exec $TEST_command $TEST_redirect)"
+ [[ $TEST_test == '('*([[:space:]])')' ]] && continue
+ r=$($SHELL -c '
+ {
+ sleep 2
+ kill -KILL $$
+ } &
+ '"$TEST_test"'
+ kill $!
+ print ok
+ ')
+ [[ $r == ok ]] || err_exit "shell hangs on $TEST_test"
+
+ done
+ done
+ done
+ done
+done
+
+$SHELL -c '( autoload xxxxx);print -n' || err_exit 'autoloaded functions in subshells can cause failure'
+foo=$($SHELL <<- ++EOF++
+ (trap 'print bar' EXIT;print -n foo)
+ ++EOF++
+)
+[[ $foo == foobar ]] || err_exit 'trap on exit when last commands is subshell is not triggered'
+
+err=$(
+ $SHELL 2>&1 <<- \EOF
+ date=$(whence -p date)
+ function foo
+ {
+ x=$( $date > /dev/null 2>&1 ;:)
+ }
+ # consume almost all fds to push the test to the fd limit #
+ integer max=$(ulimit --nofile)
+ (( max -= 6 ))
+ for ((i=20; i < max; i++))
+ do exec {i}>&1
+ done
+ for ((i=0; i < 20; i++))
+ do y=$(foo)
+ done
+ EOF
+) || {
+ err=${err%%$'\n'*}
+ err=${err#*:}
+ err=${err##[[:space:]]}
+ err_exit "nested command substitution with redirections failed -- $err"
+}
+
+exp=0
+$SHELL -c $'
+ function foobar
+ {
+ print "hello world"
+ }
+ [[ $(getopts \'[+?X\ffoobar\fX]\' v --man 2>&1) == *"Xhello worldX"* ]]
+ exit '$exp$'
+'
+got=$?
+[[ $got == $exp ]] || err_exit "getopts --man runtime callout with nonzero exit terminates shell -- expected '$exp', got '$got'"
+exp=ok
+got=$($SHELL -c $'
+ function foobar
+ {
+ print "hello world"
+ }
+ [[ $(getopts \'[+?X\ffoobar\fX]\' v --man 2>&1) == *"Xhello worldX"* ]]
+ print '$exp$'
+')
+[[ $got == $exp ]] || err_exit "getopts --man runtime callout with nonzero exit terminates shell -- expected '$exp', got '$got'"
+
+# command substitution variations #
+set -- \
+ '$(' ')' \
+ '${ ' '; }' \
+ '$(ulimit -c 0; ' ')' \
+ '$( (' ') )' \
+ '${ (' '); }' \
+ '`' '`' \
+ '`(' ')`' \
+ '`ulimit -c 0; ' '`' \
+ # end of table #
+exp=ok
+testcase[1]='
+ if %sexpr "NOMATCH" : ".*Z" >/dev/null%s
+ then print error
+ else print ok
+ fi
+ exit %s
+'
+testcase[2]='
+ function bar
+ {
+ pipeout=%1$sprintf Ok | tr O o%2$s
+ print $pipeout
+ return 0
+ }
+ foo=%1$sbar%2$s || foo="exit status $?"
+ print $foo
+ exit %3$s
+'
+while (( $# >= 2 ))
+do for ((TEST=1; TEST<=${#testcase[@]}; TEST++))
+ do body=${testcase[TEST]}
+ for code in 0 2
+ do got=${ printf "$body" "$1" "$2" "$code" | $SHELL 2>&1 }
+ status=$?
+ if (( status != code ))
+ then err_exit "test $TEST '$1...$2 exit $code' failed -- exit status $status, expected $code"
+ elif [[ $got != $exp ]]
+ then err_exit "test $TEST '$1...$2 exit $code' failed -- got '$got', expected '$exp'"
+ fi
+ done
+ done
+ shift 2
+done
+
+# the next tests loop on all combinations of
+# { SUB CAT INS TST APP } X { file-sizes }
+# where the file size starts at 1Ki and doubles up to and including 1Mi
+#
+# the tests and timeouts are done in async subshells to prevent
+# the test harness from hanging
+
+SUB=(
+ ( BEG='$( ' END=' )' )
+ ( BEG='${ ' END='; }' )
+)
+CAT=( cat $bincat )
+INS=( "" "builtin cat; " "builtin -d cat $bincat; " ": > /dev/null; " )
+APP=( "" "; :" )
+TST=(
+ ( CMD='print foo | $cat' EXP=3 )
+ ( CMD='$cat < $tmp/lin' )
+ ( CMD='cat $tmp/lin | $cat' )
+ ( CMD='read v < $tmp/buf; print $v' LIM=4*1024 )
+ ( CMD='cat $tmp/buf | read v; print $v' LIM=4*1024 )
+)
+
+if cat /dev/fd/3 3</dev/null >/dev/null 2>&1 || whence mkfifo > /dev/null
+then T=${#TST[@]}
+ TST[T].CMD='$cat <(print foo)'
+ TST[T].EXP=3
+fi
+
+# prime the two data files to 512 bytes each
+# $tmp/lin has newlines every 16 bytes and $tmp/buf has no newlines
+# the outer loop doubles the file size at top
+
+buf=$'1234567890abcdef'
+lin=$'\n1234567890abcde'
+for ((i=0; i<5; i++))
+do buf=$buf$buf
+ lin=$lin$lin
+done
+print -n "$buf" > $tmp/buf
+print -n "$lin" > $tmp/lin
+
+unset SKIP
+for ((n=1024; n<=1024*1024; n*=2))
+do cat $tmp/buf $tmp/buf > $tmp/tmp
+ mv $tmp/tmp $tmp/buf
+ cat $tmp/lin $tmp/lin > $tmp/tmp
+ mv $tmp/tmp $tmp/lin
+ for ((S=0; S<${#SUB[@]}; S++))
+ do for ((C=0; C<${#CAT[@]}; C++))
+ do cat=${CAT[C]}
+ for ((I=0; I<${#INS[@]}; I++))
+ do for ((A=0; A<${#APP[@]}; A++))
+ do for ((T=0; T<${#TST[@]}; T++))
+ do #undent...#
+
+ if [[ ! ${SKIP[S][C][I][A][T]} ]]
+ then eval "{ x=${SUB[S].BEG}${INS[I]}${TST[T].CMD}${APP[A]}${SUB[S].END}; print \${#x}; } >\$tmp/out &"
+ m=$!
+ { sleep 4; kill -9 $m; } &
+ k=$!
+ wait $m
+ h=$?
+ kill -9 $k
+ wait $k
+ got=$(<$tmp/out)
+ if [[ ! $got ]] && (( h ))
+ then got=HUNG
+ fi
+ if [[ ${TST[T].EXP} ]]
+ then exp=${TST[T].EXP}
+ else exp=$n
+ fi
+ if [[ $got != $exp ]]
+ then # on failure skip similar tests on larger files sizes #
+ SKIP[S][C][I][A][T]=1
+ siz=$(printf $'%#i' $exp)
+ cmd=${TST[T].CMD//\$cat/$cat}
+ cmd=${cmd//\$tmp\/buf/$siz.buf}
+ cmd=${cmd//\$tmp\/lin/$siz.lin}
+ err_exit "'x=${SUB[S].BEG}${INS[I]}${cmd}${APP[A]}${SUB[S].END} && print \${#x}' failed -- expected '$exp', got '$got'"
+ elif [[ ${TST[T].EXP} ]] || (( TST[T].LIM >= n ))
+ then SKIP[S][C][I][A][T]=1
+ fi
+ fi
+
+ #...indent#
+ done
+ done
+ done
+ done
+ done
+done
+
+# specifics -- there's more?
+
+{
+ cmd='{ exec 5>/dev/null; print "$(eval ls -d . 2>&1 1>&5)"; } >$tmp/out &'
+ eval $cmd
+ m=$!
+ { sleep 4; kill -9 $m; } &
+ k=$!
+ wait $m
+ h=$?
+ kill -9 $k
+ wait $k
+ got=$(<$tmp/out)
+} 2>/dev/null
+exp=''
+if [[ ! $got ]] && (( h ))
+then got=HUNG
+fi
+if [[ $got != $exp ]]
+then err_exit "eval '$cmd' failed -- expected '$exp', got '$got'"
+fi
+
+float t1=$SECONDS
+sleep=$(whence -p sleep)
+if [[ $sleep ]]
+then
+ $SHELL -c "( $sleep 5 </dev/null >/dev/null 2>&1 & );exit 0" | cat
+ (( (SECONDS-t1) > 4 )) && err_exit '/bin/sleep& in subshell hanging'
+ ((t1=SECONDS))
+fi
+$SHELL -c '( sleep 5 </dev/null >/dev/null 2>&1 & );exit 0' | cat
+(( (SECONDS-t1) > 4 )) && err_exit 'sleep& in subshell hanging'
+
+exp=HOME=$HOME
+( HOME=/bin/sh )
+got=$(env | grep ^HOME=)
+[[ $got == "$exp" ]] || err_exit "( HOME=/bin/sh ) cleanup failed -- expected '$exp', got '$got'"
+
+cmd='echo $((case x in x)echo ok;esac);:)'
+exp=ok
+got=$($SHELL -c "$cmd" 2>&1)
+[[ $got == "$exp" ]] || err_exit "'$cmd' failed -- expected '$exp', got '$got'"
+
+cmd='eval "for i in 1 2; do eval /bin/echo x; done"'
+exp=$'x\nx'
+got=$($SHELL -c "$cmd")
+if [[ $got != "$exp" ]]
+then EXP=$(printf %q "$exp")
+ GOT=$(printf %q "$got")
+ err_exit "'$cmd' failed -- expected $EXP, got $GOT"
+fi
+
+(
+$SHELL -c 'sleep 20 & pid=$!; { x=$( ( seq 60000 ) );kill -9 $pid;}&;wait $pid'
+) 2> /dev/null
+(( $? )) || err_exit 'nested command substitution with large output hangs'
+
+(.sh.foo=foobar)
+[[ ${.sh.foo} == foobar ]] && err_exit '.sh subvariables in subshells remain set'
+[[ $($SHELL -c 'print 1 | : "$(/bin/cat <(/bin/cat))"') ]] && err_exit 'process substitution not working correctly in subshells'
+
+# config hang bug
+integer i
+for ((i=1; i < 1000; i++))
+do typeset foo$i=$i
+done
+{
+ : $( (ac_space=' '; set | grep ac_space) 2>&1)
+} < /dev/null | cat > /dev/null &
+sleep 1.5
+if kill -KILL $! 2> /dev/null
+then err_exit 'process timed out with hung comsub'
+fi
+wait $! 2> /dev/null
+(( $? > 128 )) && err_exit 'incorrect exit status with comsub'
+
+$SHELL 2> /dev/null -c '[[ ${ print foo },${ print bar } == foo,bar ]]' || err_exit '${ print foo },${ print bar } not working'
+$SHELL 2> /dev/null -c '[[ ${ print foo; },${ print bar } == foo,bar ]]' || err_exit '${ print foo; },${ print bar } not working'
+
+src=$'true 2>&1\n: $(true | true)\n: $(true | true)\n: $(true | true)\n'$(whence -p true)
+exp=ok
+got=$( $SHELL -c "(eval '$src'); echo $exp" )
+[[ $got == "$exp" ]] || err_exit 'subshell eval of pipeline clobbers stdout'
+
+x=$( { time $SHELL -c date >| /dev/null;} 2>&1)
+[[ $x == *real*user*sys* ]] || err_exit 'time { ...;} 2>&1 in $(...) fails'
+
+x=$($SHELL -c '( function fx { export X=123; } ; fx; ); echo $X')
+[[ $x == 123 ]] && err_exit 'global variables set from with functions inside a
+subshell can leave side effects in parent shell'
+
+date=$(whence -p date)
+err() { return $1; }
+( err 12 ) & pid=$!
+: $( $date)
+wait $pid
+[[ $? == 12 ]] || err_exit 'exit status from subshells not being preserved'
+
+if cat /dev/fd/3 3</dev/null >/dev/null 2>&1 || whence mkfifo > /dev/null
+then x="$(sed 's/^/Hello /' <(print "Fred" | sort))"
+ [[ $x == 'Hello Fred' ]] || err_exit "process substitution of pipeline in command substitution not working"
+fi
+
+{
+$SHELL <<- \EOF
+ function foo
+ {
+ integer i
+ print -u2 foobar
+ for ((i=0; i < 8000; i++))
+ do print abcdefghijk
+ done
+ print -u2 done
+ }
+ out=$(eval "foo | cat" 2>&1)
+ (( ${#out} == 96011 )) || err_exit "\${#out} is ${#out} should be 96011"
+EOF
+} & pid=$!
+$SHELL -c "{ sleep 2 && kill $pid ;}" 2> /dev/null
+(( $? == 0 )) && err_exit 'process has hung'
+
+{
+x=$( $SHELL <<- \EOF
+ function func1 { typeset IFS; : $(func2); print END ;}
+ function func2 { IFS="BAR"; }
+ func1
+ func1
+EOF
+)
+} 2> /dev/null
+[[ $x == $'END\nEND' ]] || err_exit 'bug in save/restore of IFS in subshell'
+
+true=$(whence -p true)
+date=$(whence -p date)
+tmpf=$tmp/foo
+function fun1
+{
+ $true
+ cd - >/dev/null 2>&1
+ print -u2 -- "$($date) SUCCESS"
+}
+
+print -n $(fun1 2> $tmpf)
+[[ $(< $tmpf) == *SUCCESS ]] || err_exit 'standard error output lost with command substitution'
+
+
+tmpfile=$tmp/foo
+cat > $tmpfile <<-\EOF
+ $SHELL -c 'function g { IFS= ;};function f { typeset IFS;(g);: $V;};f;f'
+ EOF
+$SHELL 2> /dev/null "$tmpfile" || err_exit 'IFS in subshell causes core dump'
+
+unset i
+if [[ -d /dev/fd ]]
+then integer i
+ for ((i=11; i < 29; i++))
+ do if ! [[ -r /dev/fd/$i || -w /dev/fd/$i ]]
+ then a=$($SHELL -c "[[ -r /dev/fd/$i || -w /dev/fd/$i ]]")
+ (( $? )) || err_exit "file descriptor $i not close on exec"
+ fi
+ done
+fi
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/substring.sh b/src/cmd/ksh93/tests/substring.sh
new file mode 100755
index 0000000..e79447f
--- /dev/null
+++ b/src/cmd/ksh93/tests/substring.sh
@@ -0,0 +1,628 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0 j=4
+base=/home/dgk/foo//bar
+string1=$base/abcabcabc
+if [[ ${string1:0} != "$string1" ]]
+then err_exit "string1:0"
+fi
+if [[ ${string1: -1} != "c" ]]
+then err_exit "string1: -1"
+fi
+if [[ ${string1:0:1000} != "$string1" ]]
+then err_exit "string1:0"
+fi
+if [[ ${string1:1} != "${string1#?}" ]]
+then err_exit "string1:1"
+fi
+if [[ ${string1:1:4} != home ]]
+then err_exit "string1:1:4"
+fi
+if [[ ${string1: -5:4} != bcab ]]
+then err_exit "string1: -5:4"
+fi
+if [[ ${string1:1:j} != home ]]
+then err_exit "string1:1:j"
+fi
+if [[ ${string1:(j?1:0):j} != home ]]
+then err_exit "string1:(j?1:0):j"
+fi
+if [[ ${string1%*zzz*} != "$string1" ]]
+then err_exit "string1%*zzz*"
+fi
+if [[ ${string1%%*zzz*} != "$string1" ]]
+then err_exit "string1%%*zzz*"
+fi
+if [[ ${string1#*zzz*} != "$string1" ]]
+then err_exit "string1#*zzz*"
+fi
+if [[ ${string1##*zzz*} != "$string1" ]]
+then err_exit "string1##*zzz*"
+fi
+if [[ ${string1%+(abc)} != "$base/abcabc" ]]
+then err_exit "string1%+(abc)"
+fi
+if [[ ${string1%%+(abc)} != "$base/" ]]
+then err_exit "string1%%+(abc)"
+fi
+if [[ ${string1%/*} != "$base" ]]
+then err_exit "string1%/*"
+fi
+if [[ "${string1%/*}" != "$base" ]]
+then err_exit '"string1%/*"'
+fi
+if [[ ${string1%"/*"} != "$string1" ]]
+then err_exit 'string1%"/*"'
+fi
+if [[ ${string1%%/*} != "" ]]
+then err_exit "string1%%/*"
+fi
+if [[ ${string1#*/bar} != /abcabcabc ]]
+then err_exit "string1#*bar"
+fi
+if [[ ${string1##*/bar} != /abcabcabc ]]
+then err_exit "string1#*bar"
+fi
+if [[ "${string1#@(*/bar|*/foo)}" != //bar/abcabcabc ]]
+then err_exit "string1#@(*/bar|*/foo)"
+fi
+if [[ ${string1##@(*/bar|*/foo)} != /abcabcabc ]]
+then err_exit "string1##@(*/bar|*/foo)"
+fi
+if [[ ${string1##*/@(bar|foo)} != /abcabcabc ]]
+then err_exit "string1##*/@(bar|foo)"
+fi
+foo=abc
+if [[ ${foo#a[b*} != abc ]]
+then err_exit "abc#a[b*} != abc"
+fi
+if [[ ${foo//[0-9]/bar} != abc ]]
+then err_exit '${foo//[0-9]/bar} not expanding correctly'
+fi
+foo='(abc)'
+if [[ ${foo#'('} != 'abc)' ]]
+then err_exit "(abc)#( != abc)"
+fi
+if [[ ${foo%')'} != '(abc' ]]
+then err_exit "(abc)%) != (abc"
+fi
+foo=a123b456c
+if [[ ${foo/[0-9]?/""} != a3b456c ]]
+then err_exit '${foo/[0-9]?/""} not expanding correctly'
+fi
+if [[ ${foo//[0-9]/""} != abc ]]
+then err_exit '${foo//[0-9]/""} not expanding correctly'
+fi
+if [[ ${foo/#a/b} != b123b456c ]]
+then err_exit '${foo/#a/b} not expanding correctly'
+fi
+if [[ ${foo/#?/b} != b123b456c ]]
+then err_exit '${foo/#?/b} not expanding correctly'
+fi
+if [[ ${foo/%c/b} != a123b456b ]]
+then err_exit '${foo/%c/b} not expanding correctly'
+fi
+if [[ ${foo/%?/b} != a123b456b ]]
+then err_exit '${foo/%?/b} not expanding correctly'
+fi
+while read -r pattern string expected
+do if (( expected ))
+ then if [[ $string != $pattern ]]
+ then err_exit "$pattern does not match $string"
+ fi
+ if [[ ${string##$pattern} != "" ]]
+ then err_exit "\${$string##$pattern} not null"
+ fi
+ if [ "${string##$pattern}" != '' ]
+ then err_exit "\"\${$string##$pattern}\" not null"
+ fi
+ if [[ ${string/$pattern} != "" ]]
+ then err_exit "\${$string/$pattern} not null"
+ fi
+ else if [[ $string == $pattern ]]
+ then err_exit "$pattern matches $string"
+ fi
+ fi
+done <<- \EOF
+ +(a)*+(a) aabca 1
+ !(*.o) foo.o 0
+ !(*.o) foo.c 1
+EOF
+xx=a/b/c/d/e
+yy=${xx#*/}
+if [[ $yy != b/c/d/e ]]
+then err_exit '${xx#*/} != a/b/c/d/e when xx=a/b/c/d/e'
+fi
+if [[ ${xx//\//\\} != 'a\b\c\d\e' ]]
+then err_exit '${xx//\//\\} not working'
+fi
+x=[123]def
+if [[ "${x//\[@(*)\]/\{\1\}}" != {123}def ]]
+then err_exit 'closing brace escape not working'
+fi
+xx=%28text%29
+if [[ ${xx//%28/abc\)} != 'abc)text%29' ]]
+then err_exit '${xx//%28/abc\)} not working'
+fi
+xx='a:b'
+str='(){}[]*?|&^%$#@l'
+for ((i=0 ; i < ${#str}; i++))
+do [[ $(eval print -r -- \"\${xx//:/\\${str:i:1}}\") == "a${str:i:1}b" ]] || err_exit "substitution of \\${str:i:1}} failed"
+ [[ $(eval print -rn -- \"\${xx//:/\'${str:i:1}\'}\") == "a${str:i:1}b" ]] || err_exit "substitution of '${str:i:1}' failed"
+ [[ $(eval print -r -- \"\${xx//:/\"${str:i:1}\"}\") == "a${str:i:1}b" ]] || err_exit "substitution of \"${str:i:1}\" failed"
+done
+[[ ${xx//:/\\n} == 'a\nb' ]] || err_exit "substituion of \\\\n failed"
+[[ ${xx//:/'\n'} == 'a\nb' ]] || err_exit "substituion of '\\n' failed"
+[[ ${xx//:/"\n"} == 'a\nb' ]] || err_exit "substituion of \"\\n\" failed"
+[[ ${xx//:/$'\n'} == $'a\nb' ]] || err_exit "substituion of \$'\\n' failed"
+unset foo
+foo=one/two/three
+if [[ ${foo//'/'/_} != one_two_three ]]
+then err_exit 'single quoting / in replacements failed'
+fi
+if [[ ${foo//"/"/_} != one_two_three ]]
+then err_exit 'double quoting / in replacements failed'
+fi
+if [[ ${foo//\//_} != one_two_three ]]
+then err_exit 'escaping / in replacements failed'
+fi
+function myexport
+{
+ nameref var=$1
+ if (( $# > 1 ))
+ then export $1=$2
+ fi
+ if (( $# > 2 ))
+ then print $(myexport "$1" "$3" )
+ return
+ fi
+ typeset val
+ val=$(export | grep "^$1=")
+ print ${val#"$1="}
+
+}
+export dgk=base
+if [[ $(myexport dgk fun) != fun ]]
+then err_exit 'export inside function not working'
+fi
+val=$(export | grep "^dgk=")
+if [[ ${val#dgk=} != base ]]
+then err_exit 'export not restored after function call'
+fi
+if [[ $(myexport dgk fun fun2) != fun2 ]]
+then err_exit 'export inside function not working with recursive function'
+fi
+val=$(export | grep "^dgk=")
+if [[ ${val#dgk=} != base ]]
+then err_exit 'export not restored after recursive function call'
+fi
+if [[ $(dgk=try3 myexport dgk) != try3 ]]
+then err_exit 'name=value not added to export list with function call'
+fi
+val=$(export | grep "^dgk=")
+if [[ ${val#dgk=} != base ]]
+then err_exit 'export not restored name=value function call'
+fi
+unset zzz
+if [[ $(myexport zzz fun) != fun ]]
+then err_exit 'export inside function not working for zzz'
+fi
+if [[ $(export | grep "zzz=") ]]
+then err_exit 'zzz exported after function call'
+fi
+set -- foo/bar bam/yes last/file/done
+if [[ ${@/*\/@(*)/\1} != 'bar yes done' ]]
+then err_exit '\1 not working with $@'
+fi
+var=(foo/bar bam/yes last/file/done)
+if [[ ${var[@]/*\/@(*)/\1} != 'bar yes done' ]]
+then err_exit '\1 not working with ${var[@]}'
+fi
+var='abc_d2ef.462abc %%'
+if [[ ${var/+(\w)/Q} != 'Q.462abc %%' ]]
+then err_exit '${var/+(\w)/Q} not workding'
+fi
+if [[ ${var//+(\w)/Q} != 'Q.Q %%' ]]
+then err_exit '${var//+(\w)/Q} not workding'
+fi
+if [[ ${var//+(\S)/Q} != 'Q Q' ]]
+then err_exit '${var//+(\S)/Q} not workding'
+fi
+var=$($SHELL -c 'v=/vin:/usr/vin r=vin; : ${v//vin/${r//v/b}};typeset -p .sh.match') 2> /dev/null
+[[ $var == 'typeset -a .sh.match=((vin vin) )' ]] || err_exit '.sh.match not correct when replacement pattern contains a substring match'
+foo='foo+bar+'
+[[ $(print -r -- ${foo//+/'|'}) != 'foo|bar|' ]] && err_exit "\${foobar//+/'|'}"
+[[ $(print -r -- ${foo//+/"|"}) != 'foo|bar|' ]] && err_exit '${foobar//+/"|"}'
+[[ $(print -r -- "${foo//+/'|'}") != 'foo|bar|' ]] && err_exit '"${foobar//+/'"'|'"'}"'
+[[ $(print -r -- "${foo//+/"|"}") != 'foo|bar|' ]] && err_exit '"${foobar//+/"|"}"'
+unset x
+x=abcedfg
+: ${x%@(d)f@(g)}
+[[ ${.sh.match[0]} == dfg ]] || err_exit '.sh.match[0] not dfg'
+[[ ${.sh.match[1]} == d ]] || err_exit '.sh.match[1] not d'
+[[ ${.sh.match[2]} == g ]] || err_exit '.sh.match[2] not g'
+x=abcedddfg
+: ${x%%+(d)f@(g)}
+[[ ${.sh.match[1]} == ddd ]] || err_exit '.sh.match[1] not ddd'
+unset a b
+a='\[abc @(*) def\]'
+b='[abc 123 def]'
+[[ ${b//$a/\1} == 123 ]] || err_exit "\${var/pattern} not working with \[ in pattern"
+unset foo
+foo='(win32.i386) '
+[[ ${foo/'('/'(x11-'} == '(x11-win32.i386) ' ]] || err_exit "\${var/pattern} not working with ' in pattern"
+$SHELL -c $'v=\'$(hello)\'; [[ ${v//\'$(\'/-I\'$(\'} == -I"$v" ]]' 2> /dev/null || err_exit "\${var/pattern} not working with \$( as pattern"
+unset X
+$SHELL -c '[[ ! ${X[@]:0:300} ]]' 2> /dev/null || err_exit '${X[@]:0:300} with X undefined fails'
+$SHELL -c '[[ ${@:0:300} == "$0" ]]' 2> /dev/null || err_exit '${@:0:300} with no arguments fails'
+i=20030704
+[[ ${i#{6}(?)} == 04 ]] || err_exit '${i#{6}(?)} not working'
+[[ ${i#{6,6}(?)} == 04 ]] || err_exit '${i#{6,6}(?)} not working'
+LC_ALL=posix
+i=" ."
+[[ $(printf "<%s>\n" ${i#' '}) == '<.>' ]] || err_exit 'printf "<%s>\n" ${i#' '} failed'
+unset x
+x=foo
+[[ "${x%o}(1)" == "fo(1)" ]] || err_exit 'print ${}() treated as pattern'
+unset i pattern string
+string=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz
+integer i
+for((i=0; i < ${#string}; i++))
+do pattern+='@(?)'
+done
+[[ $(string=$string $SHELL -c ": \${string/$pattern/}; print \${.sh.match[26]}") == Z ]] || err_exit -u2 'sh.match[26] not Z'
+: ${string/$pattern/}
+(( ${#.sh.match[@]} == 53 )) || err_exit '.sh.match has wrong number of elements'
+[[ ${.sh.match[@]:2:4} == 'B C D E' ]] || err_exit '${.sh.match[@]:2:4} incorrect'
+
+D=$';' E=$'\\\\' Q=$'"' S=$'\'' M='nested pattern substitution failed'
+
+x='-(-)-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-(-)-)-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-(-()-)-'
+[[ ${x/*%(())*/\1} == '()' ]] || err_exit $M
+x='-(-\)-)-'
+[[ ${x/*%(())*/\1} == '(-\)' ]] || err_exit $M
+x='-(-\\)-)-'
+[[ ${x/*%(())*/\1} == '(-\\)' ]] || err_exit $M
+x='-(-(-)-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-(-(-)-)-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-(-[-]-)-'
+[[ ${x/*%(()[])*/\1} == '(-[-]-)' ]] || err_exit $M
+x='-[-(-)-]-'
+[[ ${x/*%(()[])*/\1} == '(-)' ]] || err_exit $M
+x='-(-[-)-]-'
+[[ ${x/*%(()[])*/\1} == '-(-[-)-]-' ]] || err_exit $M
+x='-(-[-]-)-'
+[[ ${x/*%([]())*/\1} == '[-]' ]] || err_exit $M
+x='-[-(-)-]-'
+[[ ${x/*%([]())*/\1} == '[-(-)-]' ]] || err_exit $M
+x='-(-[-)-]-'
+[[ ${x/*%([]())*/\1} == '-(-[-)-]-' ]] || err_exit $M
+
+x='-((-))-'
+[[ ${x/*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(-g)*%(())*/\1} == '((-))-' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(-g:*)*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(+g)*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(+g:*)*%(())*/\1} == '(-)' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/*(?)*%(())*(?)*/:\1:\2:\3:} == ':-(:(-):)-:' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(-g)*(?)*%(())*(?)*/:\1:\2:\3:} == '::((-))::-' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(-g:*(?))*%(())*(?)*/:\1:\2:\3:} == '::(-):)-:' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(+g)*(?)*%(())*(?)*/:\1:\2:\3:} == ':-(:(-):)-:' ]] || err_exit $M
+x='-((-))-'
+[[ ${x/~(+g:*(?))*%(())*(?)*/:\1:\2:\3:} == ':-(:(-):)-:' ]] || err_exit $M
+x='call(a+b,x/(c/d),(0));'
+[[ ${x/+([[:alnum:]])*([[:space:]])@(*%(()))*/:\1:\2:\3:} == ':call::(a+b,x/(c/d),(0)):' ]] || err_exit $M
+
+x='-(-;-)-'
+[[ ${x/*%(()D${D})*/\1} == '-(-;-)-' ]] || err_exit $M
+x='-(-);-'
+[[ ${x/*%(()D${D})*/\1} == '(-)' ]] || err_exit $M
+x='-(-)\;-'
+[[ ${x/*%(()D${D})*/\1} == '(-)' ]] || err_exit $M
+x='-(-\;-)-'
+[[ ${x/*%(()D${D}E${E})*/\1} == '(-\;-)' ]] || err_exit $M
+x='-(-)\;-'
+[[ ${x/*%(()D${D}E${E})*/\1} == '(-)' ]] || err_exit $M
+x='-(-(-)\;-)-'
+[[ ${x/*%(()D${D}E${E})*/\1} == '(-)' ]] || err_exit $M
+
+x='-(-")"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-")"-)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-\")"-)' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-\")\"-)' ]] || err_exit $M
+x=$'-(-\\\'")\\\'-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'(-\\\'")\\\'-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"\'-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\')\\\'\'-)-'
+[[ ${x/*%(()Q${S}Q${Q})*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M
+x=$'-(-\'")\'-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'(-\'")\'-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"\'-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\')\\\'\'-)-'
+[[ ${x/*%(()L${S}Q${Q})*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M
+x='-(-")"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-")"-)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-\")"-)' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()Q${Q})*/\1} == '(-\")\"-)' ]] || err_exit $M
+
+x='-(-\)-)-'
+[[ ${x/*%(()E${E})*/\1} == '(-\)-)' ]] || err_exit $M
+x='-(-\\)-)-'
+[[ ${x/*%(()E${E})*/\1} == '(-\\)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()E${E}Q${Q})*/\1} == '(-\")' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()E${E}Q${Q})*/\1} == '(-\")' ]] || err_exit $M
+x=$'-(-\'")"-)-'
+[[ ${x/*%(()E${E}Q${S}Q${Q})*/\1} == $'-(-\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()E${E}Q${S}Q${Q})*/\1} == $'(-\\\'")"-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()E${E}Q${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'(-\\\'")"-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\\"\')\\\'\\"-)-'
+[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'(-\\"\')\\\'\\"-)' ]] || err_exit $M
+x=$'-(-\\"\')\\\'\\"\'-)-'
+[[ ${x/*%(()E${E}L${S}Q${Q})*/\1} == $'-(-\\"\')\\\'\\"\'-)-' ]] || err_exit $M
+
+x='-(-;-)-'
+[[ ${x/*%(()D\;)*/\1} == '-(-;-)-' ]] || err_exit $M
+x='-(-);-'
+[[ ${x/*%(()D\;)*/\1} == '(-)' ]] || err_exit $M
+x='-(-)\;-'
+[[ ${x/*%(()D\;)*/\1} == '(-)' ]] || err_exit $M
+x='-(-\;-)-'
+[[ ${x/*%(()D\;E\\)*/\1} == '(-\;-)' ]] || err_exit $M
+x='-(-);-'
+[[ ${x/*%(()D\;E\\)*/\1} == '(-)' ]] || err_exit $M
+x='-(-)\;-'
+[[ ${x/*%(()D\;E\\)*/\1} == '(-)' ]] || err_exit $M
+x='-(-(-)\;-)-'
+[[ ${x/*%(()D\;E\\)*/\1} == '(-)' ]] || err_exit $M
+
+x='-(-")"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-")"-)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-\")"-)' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-\")\"-)' ]] || err_exit $M
+x=$'-(-\\\'")\\\'-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'(-\\\'")\\\'-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"\'-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\')\\\'\'-)-'
+[[ ${x/*%(()Q\'Q\")*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M
+x=$'-(-\'")\'-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'(-\'")\'-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'-(-\\\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"\'-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'(-\\\'")"\'-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\')\\\'\'-)-'
+[[ ${x/*%(()L\'Q\")*/\1} == $'-(-\')\\\'\'-)-' ]] || err_exit $M
+x='-(-")"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-")"-)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-\")"-)' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()Q\")*/\1} == '(-\")\"-)' ]] || err_exit $M
+
+x='-(-\)-)-'
+[[ ${x/*%(()E\\)*/\1} == '(-\)-)' ]] || err_exit $M
+x='-(-\\)-)-'
+[[ ${x/*%(()E\\)*/\1} == '(-\\)' ]] || err_exit $M
+x='-(-\")"-)-'
+[[ ${x/*%(()E\\Q\")*/\1} == '(-\")' ]] || err_exit $M
+x='-(-\")\"-)-'
+[[ ${x/*%(()E\\Q\")*/\1} == '(-\")' ]] || err_exit $M
+x=$'-(-\'")"-)-'
+[[ ${x/*%(()E\\Q\'Q\")*/\1} == $'-(-\'")"-)-' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()E\\Q\'Q\")*/\1} == $'(-\\\'")"-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()E\\Q\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\\\'")"-)-'
+[[ ${x/*%(()E\\L\'Q\")*/\1} == $'(-\\\'")"-)' ]] || err_exit $M
+x=$'-(-\\"\')\'\\"-)-'
+[[ ${x/*%(()E\\L\'Q\")*/\1} == $'(-\\"\')\'\\"-)' ]] || err_exit $M
+x=$'-(-\\"\')\\\'\\"-)-'
+[[ ${x/*%(()E\\L\'Q\")*/\1} == $'(-\\"\')\\\'\\"-)' ]] || err_exit $M
+x=$'-(-\\"\')\\\'\\"\'-)-'
+[[ ${x/*%(()E\\L\'Q\")*/\1} == $'-(-\\"\')\\\'\\"\'-)-' ]] || err_exit $M
+
+pattern=00
+var=100
+[[ $( print $(( ${var%%00} )) ) == 1 ]] || err_exit "arithmetic with embeddded patterns fails"
+[[ $( print $(( ${var%%$pattern} )) ) == 1 ]] || err_exit "arithmetic with embeddded pattern variables fails"
+if [[ ax == @(a)* ]] && [[ ${.sh.match[1]:0:${#.sh.match[1]}} != a ]]
+then err_exit '${.sh.match[1]:1:${#.sh.match[1]}} not expanding correctly'
+fi
+
+string='foo(d:\nt\box\something)bar'
+expected='d:\nt\box\something'
+[[ ${string/*\(+([!\)])\)*/\1} == "$expected" ]] || err_exit "substring expansion failed '${string/*\(+([!\)])\)*/\1}' returned -- '$expected' expected"
+if [[ $($SHELL -c $'export LC_ALL=C.UTF-8; print -r "\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254" | wc -m' 2>/dev/null) == 10 ]]
+then LC_ALL=C.UTF-8 $SHELL -c b1=$'"\342\202\254\342\202\254\342\202\254\342\202\254w\342\202\254\342\202\254\342\202\254\342\202\254"; [[ ${b1:4:1} == w ]]' || err_exit 'multibyte ${var:offset:len} not working correctly'
+fi
+{ $SHELL -c 'unset x;[[ ${SHELL:$x} == $SHELL ]]';} 2> /dev/null || err_exit '${var:$x} fails when x is not set'
+{ $SHELL -c 'x=;[[ ${SHELL:$x} == $SHELL ]]';} 2> /dev/null || err_exit '${var:$x} fails when x is null'
+
+# subject mode pattern result #
+set -- \
+ 'a$z' 'E' '[$]|#' 'a($)z' \
+ 'a#z' 'E' '[$]|#' 'a(#)z' \
+ 'a$z' 'Elr' '[$]|#' 'a$z' \
+ 'a#z' 'Elr' '[$]|#' 'a#z' \
+ 'a$' 'E' '[$]|#' 'a($)' \
+ 'a#' 'E' '[$]|#' 'a(#)' \
+ 'a$' 'Elr' '[$]|#' 'a$' \
+ 'a#' 'Elr' '[$]|#' 'a#' \
+ '$z' 'E' '[$]|#' '($)z' \
+ '#z' 'E' '[$]|#' '(#)z' \
+ '$z' 'Elr' '[$]|#' '$z' \
+ '#z' 'Elr' '[$]|#' '#z' \
+ '$' 'E' '[$]|#' '($)' \
+ '#' 'E' '[$]|#' '(#)' \
+ '$' 'Elr' '[$]|#' '($)' \
+ '#' 'Elr' '[$]|#' '(#)' \
+ 'a$z' 'E' '\$|#' 'a$z()' \
+ 'a$z' 'E' '\\$|#' 'a$z' \
+ 'a$z' 'E' '\\\$|#' 'a($)z' \
+ 'a#z' 'E' '\\\$|#' 'a(#)z' \
+ 'a$z' 'Elr' '\\\$|#' 'a$z' \
+ 'a#z' 'Elr' '\\\$|#' 'a#z' \
+ 'a$' 'E' '\\\$|#' 'a($)' \
+ 'a#' 'E' '\\\$|#' 'a(#)' \
+ 'a$' 'Elr' '\\\$|#' 'a$' \
+ 'a#' 'Elr' '\\\$|#' 'a#' \
+ '$z' 'E' '\\\$|#' '($)z' \
+ '#z' 'E' '\\\$|#' '(#)z' \
+ '$z' 'Elr' '\\\$|#' '$z' \
+ '#z' 'Elr' '\\\$|#' '#z' \
+ '$' 'E' '\\\$|#' '($)' \
+ '#' 'E' '\\\$|#' '(#)' \
+ '$' 'Elr' '\\\$|#' '($)' \
+ '#' 'Elr' '\\\$|#' '(#)' \
+# do not delete this line #
+unset i o
+while (( $# >= 4 ))
+do i=$1
+ eval o="\${i/~($2)$3/\\(\\0\\)}"
+ if [[ "$o" != "$4" ]]
+ then err_exit "i='$1'; \${i/~($2)$3/\\(\\0\\)} failed -- expected '$4', got '$o'"
+ fi
+ eval o="\${i/~($2)($3)/\\(\\1\\)}"
+ if [[ "$o" != "$4" ]]
+ then err_exit "i='$1'; \${i/~($2)($3)/\\(\\1\\)} failed -- expected '$4', got '$o'"
+ fi
+ shift 4
+done
+
+#multibyte locale tests
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:0:1}" == a || err_exit ${x:0:1} should be a'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1:1}" == "<2b|>" || err_exit ${x:1:1} should be <2b|>'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:3:1}" == "<3d|\\>" || err_exit ${x:3:1} should be <3d|\>'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:4:1}" == e || err_exit ${x:4:1} should bee'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1}" == "<2b|>c<3d|\\>e" || print -u2 ${x:1}" should be <2b|>c<3d|\>e'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x: -1:1}" == e || err_exit ${x: -1:1} should be e'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x: -2:1}" == "<3d|\\>" || err_exit ${x: -2:1} == <3d|\>'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1:3}" == "<2b|>c<3d|\\>" || err_exit ${x:1:3} should be <2b|>c<3d|\>'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x:1:20}" == "<2b|>c<3d|\\>e" || err_exit ${x:1:20} should be <2b|>c<3d|\>e'
+x='a<2b|>c<3d|\>e' LC_ALL=debug $SHELL -c 'test "${x#??}" == "c<3d|\\>e" || err_exit "${x#??} should be c<3d|\>e'
+
+x='a one and a two'
+[[ "${x//~(E)\<.\>/}" == ' one and two' ]] || err_exit "\< and \> not working in with ere's"
+
+{
+$SHELL -c 'typeset x="123" ; integer i=100 ; print -n "${x:i:5}"'
+} 2> /dev/null || err_exit '${x:i:j} fails when i > strlen(x)'
+
+got=$($SHELL -c 'A=""; B="B"; for I in ${A[@]} ${B[@]}; do echo "\"$I\""; done')
+[[ $got == $'"B"' ]] || err_exit '"\"$I\"" fails when $I is empty string'
+
+A='|'
+[[ $A == $A ]] || err_exit 'With A="|", [[ $A == $A ]] does not match'
+
+x="111 222 333 444 555 666"
+[[ $x == ~(E)(...).(...).(...) ]]
+[[ -v .sh.match[0] ]] || err_exit '[[ -v .sh.match[0] ]] should be true'
+[[ -v .sh.match[3] ]] || err_exit '[[ -v .sh.match[3] ]] should be true'
+[[ -v .sh.match[4] ]] && err_exit '[[ -v .sh.match[4] ]] should be false'
+[[ ${#.sh.match[@]} == 4 ]] || err_exit "\${#.sh.match[@]} should be 4, not ${#.sh.match[@]}"
+
+x="foo bar"
+dummy=${x/~(E)(*)/}
+[[ ${ print -v .sh.match;} ]] && err_exit 'print -v should show .sh.match empty when there are no matches'
+
+if $SHELL -c 'set 1 2 3 4 5 6 7 8 9 10 11 12; : ${##[0-9]}' 2>/dev/null
+then set 1 2 3 4 5 6 7 8 9 10 11 12
+ [[ ${##[0-9]} == 2 ]] || err_exit '${##[0-9]} should be 2 with $#==12'
+ [[ ${###[0-9]} == 2 ]] || err_exit '${###[0-9]} should be 2 with $#==12'
+ [[ ${#%[0-9]} == 1 ]] || err_exit '${#%[0-9]} should be 1 with $#==12'
+ [[ ${#%%[0-9]} == 1 ]] || err_exit '${#%%[0-9]} should be 1 with $#==12'
+else err_exit '${##[0-9]} give syntax error'
+fi
+
+{
+ $SHELL -c 'x="a123 456 789z"; : ${x//{3}(\d)/ }' &
+ sleep .5; kill $!; wait $!
+} 2> /dev/null || err_exit $'tokenizer can\'t handle ${var op {..} }'
+
+
+function foo
+{
+ typeset x="123 456 789 abc"
+ typeset dummy="${x/~(E-g)([[:digit:]][[:digit:]])((X)|([[:digit:]]))([[:blank:]])/_}"
+ exp=$'(\n\t[0]=\'123 \'\n\t[1]=12\n\t[2]=3\n\t[4]=3\n\t[5]=\' \'\n)'
+ [[ $(print -v .sh.match) == "$exp" ]] || err_exit '.sh.match not correct with alternations'
+}
+foo
+
+x="a 1 b"
+d=${x/~(E)(([[:digit:]])[[:space:]]*|([[:alpha:]]))/X}
+[[ $(print -v .sh.match) == $'(\n\t[0]=a\n\t[1]=a\n\t[3]=a\n)' ]] || err_exit '.sh.match not sparse'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/tilde.sh b/src/cmd/ksh93/tests/tilde.sh
new file mode 100755
index 0000000..b044723
--- /dev/null
+++ b/src/cmd/ksh93/tests/tilde.sh
@@ -0,0 +1,101 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2012 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r $Command: "$@"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+if $SHELL -c '[[ ~root == /* ]]'
+then x=$(print -r -- ~root)
+ [[ $x == ~root ]] || err_exit '~user expanded in subshell prevent ~user from working'
+fi
+
+function home # id
+{
+ typeset IFS=: pwd=/etc/passwd
+ set -o noglob
+ if [[ -f $pwd ]] && grep -c "^$1:" $pwd > /dev/null
+ then set -- $(grep "^$1:" $pwd)
+ print -r -- "$6"
+ else print .
+ fi
+}
+
+OLDPWD=/bin
+if [[ ~ != $HOME ]]
+then err_exit '~' not $HOME
+fi
+x=~
+if [[ $x != $HOME ]]
+then err_exit x=~ not $HOME
+fi
+x=x:~
+if [[ $x != x:$HOME ]]
+then err_exit x=x:~ not x:$HOME
+fi
+if [[ ~+ != $PWD ]]
+then err_exit '~' not $PWD
+fi
+x=~+
+if [[ $x != $PWD ]]
+then err_exit x=~+ not $PWD
+fi
+if [[ ~- != $OLDPWD ]]
+then err_exit '~' not $PWD
+fi
+x=~-
+if [[ $x != $OLDPWD ]]
+then err_exit x=~- not $OLDPWD
+fi
+for u in root Administrator
+do h=$(home $u)
+ if [[ $h != . ]]
+ then [[ ~$u -ef $h ]] || err_exit "~$u not $h"
+ x=~$u
+ [[ $x -ef $h ]] || x="~$u not $h"
+ break
+ fi
+done
+x=~g.r.emlin
+if [[ $x != '~g.r.emlin' ]]
+then err_exit "x=~g.r.emlin failed -- expected '~g.r.emlin', got '$x'"
+fi
+x=~:~
+if [[ $x != "$HOME:$HOME" ]]
+then err_exit "x=~:~ failed, expected '$HOME:$HOME', got '$x'"
+fi
+HOME=/
+[[ ~ == / ]] || err_exit '~ should be /'
+[[ ~/foo == /foo ]] || err_exit '~/foo should be /foo when ~==/'
+print $'print ~+\n[[ $1 ]] && $0' > $tmp/tilde
+chmod +x $tmp/tilde
+nl=$'\n'
+[[ $($tmp/tilde foo) == "$PWD$nl$PWD" ]] 2> /dev/null || err_exit 'tilde fails inside a script run by name'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/timetype.sh b/src/cmd/ksh93/tests/timetype.sh
new file mode 100755
index 0000000..16453c4
--- /dev/null
+++ b/src/cmd/ksh93/tests/timetype.sh
@@ -0,0 +1,81 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+typeset -T Time_t=(
+ integer .=-1
+ _='%F+%H:%M'
+ get()
+ {
+ if (( _ < 0 ))
+ then .sh.value=${ printf "%(${_._})T" now ;}
+ else .sh.value=${ printf "%(${_._})T" "#$((_))" ;}
+ fi
+ }
+ set()
+ {
+ .sh.value=${ printf "%(%#)T" "${.sh.value}";}
+ }
+)
+
+d=$(printf "%(%F+%H:%M)T" now)
+integer s=$(printf "%(%#)T" "$d")
+Time_t t=$d
+[[ $t == "$d" ]] || err_exit "printf %T != Time_t -- expected '$d', got '$t'"
+(( t == s )) || err_exit "numeric Time_t failed -- expected '$s', got '$t'"
+t._='%#'
+[[ $t == $s ]] || err_exit "t._='%#' failed -- expected '$s', got '$t'"
+unset t
+Time_t tt=(yesterday today tomorrow)
+tt[3]=2pm
+[[ ${!tt[@]} == '0 1 2 3' ]] || err_exit "indexed array subscript names failed -- expected '0 1 2 3', got '${!tt[@]}'"
+[[ ${tt[0]} == *+00:00 ]] || err_exit "tt[0] failed -- expected 00:00, got '${tt[0]##*+}'"
+[[ ${tt[1]} == *+00:00 ]] || err_exit "tt[1] failed -- expected 00:00, got '${tt[1]##*+}'"
+[[ ${tt[2]} == *+00:00 ]] || err_exit "tt[2] failed -- expected 00:00, got '${tt[2]##*+}'"
+[[ ${tt[3]} == *+14:00 ]] || err_exit "tt[3] failed -- expected 14:00, got '${tt[3]##*+}'"
+unset tt
+Time_t tt=('2008-08-11+00:00:00,yesterday' '2008-08-11+00:00:00,today' '2008-08-11+00:00:00,tomorrow')
+tt[3]=9am
+tt[4]=5pm
+(( (tt[1] - tt[0]) == 24*3600 )) || err_exit "today-yesterday='$((tt[1] - tt[0]))' != 1 day"
+(( (tt[2] - tt[1]) == 24*3600 )) || err_exit "tomorrow-today='$((tt[2] - tt[1]))' != 1 day"
+(( (tt[4] - tt[3]) == 8*3600 )) || err_exit "9am..5pm='$((tt[4] - tt[3]))' != 8 hours"
+unset tt
+Time_t tt=([yesterday]='2008-08-11+00:00:00,yesterday' [today]='2008-08-11+00:00:00,today' [tomorrow]='2008-08-11+00:00:00,tomorrow')
+tt[2pm]='2008-08-11+00:00:00,2pm'
+[[ ${tt[yesterday]} == *+00:00 ]] || err_exit "tt[yesterday] failed -- expected 00:00, got '${tt[yesterday]##*+}'"
+[[ ${tt[today]} == *+00:00 ]] || err_exit "tt[today] failed -- expected 00:00, got '${tt[today]##*+}'"
+[[ ${tt[tomorrow]} == *+00:00 ]] || err_exit "tt[tomorrow] failed -- expected 00:00, got '${tt[tomorrow]##*+}'"
+[[ ${tt[2pm]} == *+14:00 ]] || err_exit "tt[2pm] failed -- expected 14:00, got '${tt[2pm]##*+}'"
+(( (tt[today] - tt[yesterday] ) == 24*3600 )) || err_exit "tt[today]-tt[yesterday] failed -- expected 24*3600, got $(((tt[today]-tt[yesterday])/3600.0))*3600"
+(( (tt[tomorrow] - tt[today] ) == 24*3600 )) || err_exit "tt[tomorrow]-tt[today] failed -- expected 24*3600, got $(((tt[tomorrow]-tt[today])/3600.0))*3600"
+(( (tt[2pm] - tt[today] ) == 14*3600 )) || err_exit "tt[2pm]-tt[today] failed -- expected 14*3600, got $(((tt[2pm]-tt[today])/3600.0))*3600"
+unset tt
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/treemove.sh b/src/cmd/ksh93/tests/treemove.sh
new file mode 100755
index 0000000..8e293c0
--- /dev/null
+++ b/src/cmd/ksh93/tests/treemove.sh
@@ -0,0 +1,163 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This test checks whether "typeset -m" correctly moves local variables
+# into a global variable tree.
+#
+# This was reported as CR #XXXXXXXX ("XXXX"):
+# -- snip --
+#XXXX
+# -- snip --
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+integer Errors=0
+
+## test start
+typeset -C tree1 tree2
+
+# add node to tree which uses "typeset -m" to move a local variable
+# into tree1.subtree["a_node"]
+function f1
+{
+ nameref tr=$1
+ typeset -A tr.subtree
+ typeset -C node
+ node.one="hello"
+ node.two="world"
+ # move local note into the array
+false
+ typeset -m tr.subtree["a_node"]=node
+ return 0
+}
+
+# Alternative version which uses "nameref" instead of "typeset -m"
+function f2
+{
+ nameref tr=$1
+ typeset -A tr.subtree
+ nameref node=tr.subtree["a_node"]
+ node.one="hello"
+ node.two="world"
+ return 0
+}
+
+f1 tree1
+f2 tree2
+
+[[ "${tree1.subtree["a_node"].one}" == "hello" ]] || err_exit "expected tree1.subtree[\"a_node\"].one == 'hello', got ${tree1.subtree["a_node"].one}"
+[[ "${tree1.subtree["a_node"].two}" == "world" ]] || err_exit "expected tree1.subtree[\"a_node\"].two == 'world', got ${tree1.subtree["a_node"].two}"
+[[ "${tree1}" == "${tree2}" ]] || err_exit "tree1 and tree2 differ:$'\n'"
+
+unset c
+compound c
+typeset -C -a c.ar
+c.ar[4]=( a4=1 )
+typeset -m "c.ar[5]=c.ar[4]"
+exp=$'(\n\ttypeset -C -a ar=(\n\t\t[5]=(\n\t\t\ta4=1\n\t\t)\n\t)\n)'
+[[ $(print -v c) == "$exp" ]] || err_exit 'typeset -m "c.ar[5]=c.ar[4]" not working'
+
+typeset -T x_t=( hello=world )
+function m
+{
+ compound c
+ compound -a c.x
+ x_t c.x[4][5][8].field
+ x_t x
+ typeset -m c.x[4][6][9].field=x
+ exp=$'(\n\ttypeset -C -a x=(\n\t\t[4]=(\n\t\t\t[5]=(\n\t\t\t\t[8]=(\n\t\t\t\t\tx_t field=(\n\t\t\t\t\t\thello=world\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t)\n\t\t\t[6]=(\n\t\t\t\t[9]=(\n\t\t\t\t\tx_t field=(\n\t\t\t\t\t\thello=world\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t)\n\t\t)\n\t)\n)'
+ [[ $(print -v c) == "$exp" ]] || err_exit "typeset -m c.x[4][6][9].field=x where x is a type is not working"
+}
+m
+
+function moveme
+{
+ nameref src=$2 dest=$1
+ typeset -m dest=src
+}
+function main
+{
+ compound a=( aa=1 )
+ compound -a ar
+ moveme ar[4] a 2> /dev/null || err_exit 'function moveme fails'
+ exp=$'(\n\t[4]=(\n\t\taa=1\n\t)\n)'
+ [[ $(print -v ar) == "$exp" ]] || err_exit 'typeset -m dest=src where dest and src are name references fails'
+}
+main
+
+
+{
+$SHELL <<- \EOF
+ function main
+ {
+ compound c=(
+ compound -a board
+ )
+ for ((i=0 ; i < 2 ; i++ )) ; do
+ compound el=(typeset id='pawn')
+ typeset -m "c.board[1][i]=el"
+ done
+ exp=$'(\n\ttypeset -C -a board=(\n\t\t[1]=(\n\t\t\t(\n\t\t\t\tid=pawn\n\t\t\t)\n\t\t\t(\n\t\t\t\tid=pawn\n\t\t\t)\n\t\t)\n\t)\n)'
+ [[ $(print -v c) == "$exp" ]] || exit 1
+ }
+ main
+EOF
+} 2> /dev/null
+if ((exitval=$?))
+then if [[ $(kill -l $exitval) == SEGV ]]
+ then err_exit 'typeset -m "c.board[1][i]=el" core dumps'
+ else err_exit 'typeset -m "c.board[1][i]=el" gives wrong value'
+ fi
+fi
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/types.sh b/src/cmd/ksh93/tests/types.sh
new file mode 100755
index 0000000..e8f82e1
--- /dev/null
+++ b/src/cmd/ksh93/tests/types.sh
@@ -0,0 +1,632 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+integer n=2
+
+typeset -T Type_t=(
+ typeset name=foobar
+ typeset x=(hi=ok bar=yes)
+ typeset y=(xa=xx xq=89)
+ typeset -A aa=([one]=abc [two]=def)
+ typeset -a ia=(abc def)
+ typeset -i z=5
+)
+for ((i=0; i < 10; i++))
+do
+ Type_t r s
+ [[ $r == "$s" ]] || err_exit 'r is not equal to s'
+ typeset -C x=r.x
+ y=(xa=bb xq=cc)
+ y2=xyz
+ z2=xyz
+ typeset -C z=y
+ [[ $y == "$z" ]] || err_exit 'y is not equal to z'
+ typeset -C s.y=z
+ [[ $y == "${s.y}" ]] || err_exit 'y is not equal to s.y'
+ .sh.q=$y
+ typeset -C www=.sh.q
+ [[ $www == "$z" ]] || err_exit 'www is not equal to z'
+ typeset -C s.x=r.x
+ [[ ${s.x} == "${r.x}" ]] || err_exit 's.x is not equal to r.x'
+
+ function foo
+ {
+ nameref x=$1 y=$2
+ typeset z=$x
+ y=$x
+ [[ $x == "$y" ]] || err_exit "x is not equal to y with ${!x}"
+ }
+ foo r.y y
+ [[ $y == "${r.y}" ]] || err_exit 'y is not equal to r.y'
+ typeset -C y=z
+ foo y r.y
+ [[ $y == "${r.y}" ]] || err_exit 'y is not equal to r.y again'
+ typeset -C y=z
+ (
+ q=${z}
+ [[ $q == "$z" ]] || err_exit 'q is not equal to z'
+ z=abc
+ )
+ [[ $z == "$y" ]] || err_exit 'value of z not preserved after subshell'
+ unset z y r s x z2 y2 www .sh.q
+done
+typeset -T Frame_t=( typeset file lineno )
+Frame_t frame
+[[ $(typeset -p frame) == 'Frame_t frame=(typeset file;typeset lineno)' ]] || err_exit 'empty fields in type not displayed'
+x=( typeset -a arr=([2]=abc [4]=(x=1 y=def));zz=abc)
+typeset -C y=x
+[[ "$x" == "$y" ]] || print -u2 'y is not equal to x'
+Type_t z=(y=(xa=bb xq=cc))
+typeset -A arr=([foo]=one [bar]=2)
+typeset -A brr=([foo]=one [bar]=2)
+[[ "${arr[@]}" == "${brr[@]}" ]] || err_exit 'arr is not brr'
+for ((i=0; i < 1; i++))
+do typeset -m zzz=x
+ [[ $zzz == "$y" ]] || err_exit 'zzz is not equal to y'
+ typeset -m x=zzz
+ [[ $x == "$y" ]] || err_exit 'x is not equal to y'
+ Type_t t=(y=(xa=bb xq=cc))
+ typeset -m r=t
+ [[ $r == "$z" ]] || err_exit 'r is not equal to z'
+ typeset -m t=r
+ [[ $t == "$z" ]] || err_exit 't is not equal to z'
+ typeset -m crr=arr
+ [[ "${crr[@]}" == "${brr[@]}" ]] || err_exit 'crr is not brr'
+ typeset -m arr=crr
+ [[ "${arr[@]}" == "${brr[@]}" ]] || err_exit 'brr is not arr'
+done
+typeset -m brr[foo]=brr[bar]
+[[ ${brr[foo]} == 2 ]] || err_exit 'move an associative array element fails'
+[[ ${brr[bar]} ]] && err_exit 'brr[bar] should be unset after move'
+unset x y zzz
+x=(a b c)
+typeset -m x[1]=x[2]
+[[ ${x[1]} == c ]] || err_exit 'move an indexed array element fails'
+[[ ${x[2]} ]] && err_exit 'x[2] should be unset after move'
+cat > $tmp/types <<- \+++
+ typeset -T Pt_t=(float x=1. y=0.)
+ Pt_t p=(y=2)
+ print -r -- ${p.y}
++++
+expected=2
+got=$(. $tmp/types) 2>/dev/null
+[[ "$got" == "$expected" ]] || err_exit "typedefs in dot script failed -- expected '$expected', got '$got'"
+typeset -T X_t=(
+ typeset x=foo y=bar
+ typeset s=${_.x}
+ create()
+ {
+ _.y=bam
+ }
+)
+X_t x
+[[ ${x.x} == foo ]] || err_exit 'x.x should be foo'
+[[ ${x.y} == bam ]] || err_exit 'x.y should be bam'
+[[ ${x.s} == ${x.x} ]] || err_exit 'x.s should be x.x'
+typeset -T Y_t=( X_t r )
+Y_t z
+[[ ${z.r.x} == foo ]] || err_exit 'z.r.x should be foo'
+[[ ${z.r.y} == bam ]] || err_exit 'z.r.y should be bam'
+[[ ${z.r.s} == ${z.r.x} ]] || err_exit 'z.r.s should be z.r.x'
+
+unset xx yy
+typeset -T xx=(typeset yy=zz)
+xx=yy
+{ typeset -T xx=(typeset yy=zz) ;} 2>/dev/null && err_exit 'type redefinition should fail'
+$SHELL 2> /dev/null <<- +++ || err_exit 'typedef with only f(){} fails'
+ typeset -T X_t=(
+ f()
+ {
+ print ok
+ }
+ )
++++
+$SHELL 2> /dev/null <<- +++ || err_exit 'unable to redefine f discipline function'
+ typeset -T X_t=(
+ x=1
+ f()
+ {
+ print ok
+ }
+ )
+ X_t z=(
+ function f
+ {
+ print override f
+ }
+ )
++++
+$SHELL 2> /dev/null <<- +++ && err_exit 'invalid discipline name should be an error'
+ typeset -T X_t=(
+ x=1
+ f()
+ {
+ print ok
+ }
+ )
+ X_t z=(
+ function g
+ {
+ print override f
+ }
+ )
++++
+# compound variables containing type variables
+Type_t r
+var=(
+ typeset x=foobar
+ Type_t r
+ integer z=5
+)
+[[ ${var.r} == "$r" ]] || err_exit 'var.r != r'
+(( var.z == 5)) || err_exit 'var.z !=5'
+[[ "$var" == *x=foobar* ]] || err_exit '$var does not contain x=foobar'
+
+typeset -T A_t=(
+ typeset x=aha
+ typeset b=${_.x}
+)
+unset x
+A_t x
+expected=aha
+got=${x.b}
+[[ "$got" == "$expected" ]] || err_exit "type '_' reference failed -- expected '$expected', got '$got'"
+
+typeset -T Tst_t=(
+ function f
+ {
+ A_t a
+ print ${ _.g ${a.x}; }
+ }
+ function g
+ {
+ print foo
+ }
+)
+Tst_t tst
+expected=foo
+got=${ tst.f;}
+[[ "$got" == "$expected" ]] || err_exit "_.g where g is a function in type discipline method failed -- expected '$expected', got '$got'"
+
+typeset -T B_t=(
+ integer -a arr
+ function f
+ {
+ (( _.arr[0] = 0 ))
+ (( _.arr[1] = 1 ))
+ print ${_.arr[*]}
+ }
+)
+unset x
+B_t x
+expected='0 1'
+got=${ x.f;}
+[[ "$got" == "$expected" ]] || err_exit "array assignment of subscripts in type discipline arithmetic failed -- expected '$expected', got '$got'"
+
+typeset -T Fileinfo_t=(
+ size=-1
+ typeset -a text=()
+ integer mtime=-1
+)
+Fileinfo_t -A _Dbg_filenames
+Fileinfo_t finfo
+function bar
+{
+ finfo.text=(line1 line2 line3)
+ finfo.size=${#finfo.text[@]}
+ _Dbg_filenames[foo]=finfo
+}
+bar
+
+expected='Fileinfo_t -A _Dbg_filenames=([foo]=(size=3;typeset -a text=(line1 line2 line3);typeset -l -i mtime=-1))'
+got=$(typeset -p _Dbg_filenames)
+[[ "$got" == "$expected" ]] || {
+ got=$(printf %q "$got")
+ err_exit "copy to associative array of types in function failed -- expected '$expected', got $got"
+}
+
+$SHELL > /dev/null <<- '+++++' || err_exit 'passing _ as nameref arg not working'
+ function f1
+ {
+ typeset -n v=$1
+ print -r -- "$v"
+ }
+ typeset -T A_t=(
+ typeset blah=xxx
+ function f { f1 _ ;}
+ )
+ A_t a
+ [[ ${ a.f ./t1;} == "$a" ]]
++++++
+expected='A_t b.a=(name=one)'
+[[ $( $SHELL << \+++
+ typeset -T A_t=(
+ typeset name=aha
+ )
+ typeset -T B_t=(
+ typeset arr
+ A_t a
+ f()
+ {
+ _.a=(name=one)
+ typeset -p _.a
+ }
+ )
+ B_t b
+ b.f
++++
+) == "$expected" ]] 2> /dev/null || err_exit '_.a=(name=one) not expanding correctly'
+expected='A_t x=(name=xxx)'
+[[ $( $SHELL << \+++
+ typeset -T A_t=(
+ typeset name
+ )
+ A_t x=(name="xxx")
+ typeset -p x
++++
+) == "$expected" ]] || err_exit 'empty field in definition does not expand correctly'
+
+typeset -T Foo_t=(
+ integer x=3
+ integer y=4
+ len() { print -r -- $(( sqrt(_.x**2 + _.y**2))) ;}
+)
+Foo_t foo
+[[ ${foo.len} == 5 ]] || err_exit "discipline function len not working"
+
+typeset -T benchmark_t=(
+ integer num_iterations
+)
+function do_benchmarks
+{
+ nameref tst=b
+ integer num_iterations
+ (( num_iterations= int(tst.num_iterations * 1.0) ))
+ printf "%d\n" num_iterations
+}
+benchmark_t b=(num_iterations=5)
+[[ $(do_benchmarks) == 5 ]] || err_exit 'scoping of nameref of type variables in arithmetic expressions not working'
+
+function cat_content
+{
+ cat <<- EOF
+ (
+ foo_t -a foolist=(
+ ( val=3 )
+ ( val=4 )
+ ( val=5 )
+ )
+ )
+ EOF
+ return 0
+}
+typeset -T foo_t=(
+ integer val=-1
+ function print
+ {
+ print -- ${_.val}
+ }
+)
+function do_something
+{
+ nameref li=$1 # "li" may be an index or associative array
+ li[2].print
+}
+cat_content | read -C x
+[[ $(do_something x.foolist) == 5 ]] || err_exit 'subscripts not honored for arrays of type with disciplines'
+
+typeset -T benchcmd_t=(
+ float x=1
+ float y=2
+)
+unset x
+compound x=(
+ float o
+ benchcmd_t -a m
+ integer h
+)
+expected=$'(\n\ttypeset -l -i h=0\n\tbenchcmd_t -a m\n\ttypeset -l -E o=0\n)'
+[[ $x == "$expected" ]] || err_exit 'compound variable with array of types with no elements not working'
+
+expected=$'Std_file_t db.file[/etc/profile]=(action=preserve;typeset -A sum=([8242e663d6f7bb4c5427a0e58e2925f3]=1);)'
+{
+ got=$($SHELL <<- \EOF
+ MAGIC='stdinstall (at&t research) 2009-08-25'
+ typeset -T Std_file_t=(
+ typeset action
+ typeset -A sum
+ )
+ typeset -T Std_t=(
+ typeset magic=$MAGIC
+ Std_file_t -A file
+ )
+ Std_t db=(magic='stdinstall (at&t research) 2009-08-25';Std_file_t -A file=( [/./home/gsf/.env.sh]=(action=preserve;typeset -A sum=([9b67ab407d01a52b3e73e3945b9a3ee0]=1);)[/etc/profile]=(action=preserve;typeset -A sum=([8242e663d6f7bb4c5427a0e58e2925f3]=1);)[/home/gsf/.profile]=(action=preserve;typeset -A sum=([3ce23137335219672bf2865d003a098e]=1);));)
+ typeset -p db.file[/etc/profile]
+ EOF)
+} 2> /dev/null
+[[ $got == "$expected" ]] || err_exit 'types with arrays of types as members fails'
+
+typeset -T x_t=(
+ integer dummy
+ function set
+ {
+ [[ ${.sh.name} == v ]] || err_exit "name=${.sh.name} should be v"
+ [[ ${.sh.subscript} == 4 ]] || err_exit "subscript=${.sh.subscript} should be 4"
+ [[ ${.sh.value} == hello ]] || err_exit "value=${.sh.value} should be hello"
+ }
+)
+x_t -a v
+v[4]="hello"
+
+typeset -T oset=(
+ typeset -A s
+)
+oset foo bar
+: ${foo.s[a]:=foobar}
+: ${bar.s[d]:=foobar}
+[[ ${bar.s[a]} == foobar ]] && err_exit '${var:=val} for types assigns to type instead of type instance'
+
+typeset -T olist=(
+ typeset -a l
+)
+olist foo
+foo.l[1]=x
+[[ ${!foo.l[*]} == *0* ]] && '0-th elment of foo.l should not be set'
+
+typeset -T oset2=( typeset -A foo )
+oset2 bar
+: ${bar.foo[a]}
+bar.foo[a]=b
+[[ ${#bar.foo[*]} == 1 ]] || err_exit "bar.foo should have 1 element not ${#bar.foo[*]}"
+[[ ${bar.foo[*]} == b ]] || err_exit "bar.foo[*] should be 'b' not ${bar.foo[*]}"
+[[ ${bar.foo[a]} == b ]] || err_exit "bar.foo[a] should be 'b' not ${bar.foo[*]}"
+
+{ x=$( $SHELL 2> /dev/null << \++EOF++
+ typeset -T ab_t=(
+ integer a=1 b=2
+ function increment
+ {
+ (( _.a++, _.b++ ))
+ }
+ )
+ function ar_n
+ {
+ nameref sn=$2
+ sn.increment
+ $1 && printf "a=%d, b=%d\n" sn.a sn.b
+ }
+ function ar
+ {
+ ab_t -S -a s
+ [[ -v s[5] ]] || s[5]=( )
+ ar_n $1 s[5]
+ }
+ x=$(ar false ; ar false ; ar true ; printf ";")
+ y=$(ar false ; ar false ; ar true ; printf ";")
+ print -r -- "\"$x\"" == "\"$y\""
+++EOF++
+) ;} 2> /dev/null
+[[ $x == *a=4*b=5* ]] || err_exit 'static types in a function not working'
+{ eval "[[ $x ]]";} 2> /dev/null || err_exit 'arrays of types leaving side effects in subshells'
+
+typeset -T y_t=(
+ typeset dummy
+ function print_b
+ {
+ print "B"
+ }
+)
+y_t a b=(
+ function print_b
+ {
+ print "1"
+ }
+)
+[[ $(a.print_b) == B ]] || err_exit 'default discipline not working'
+[[ $(b.print_b) == 1 ]] || err_exit 'discipline override not working'
+
+$SHELL 2> /dev/null -c 'true || { typeset -T Type_t=(typeset name=foo);
+ Type_t z=(name=bar) ;}' || err_exit 'unable to parse type command until typeset -T executes'
+
+cd "$tmp"
+FPATH=$PWD
+PATH=$PWD:$PATH
+cat > A_t <<- \EOF
+ typeset -T A_t=(
+ B_t b
+ )
+EOF
+cat > B_t <<- \EOF
+ typeset -T B_t=(
+ integer n=5
+ )
+EOF
+
+unset n
+if n=$(FPATH=$PWD PATH=$PWD:$PATH $SHELL 2> /dev/null -c 'A_t a; print ${a.b.n}')
+then (( n==5 )) || err_exit 'dynamic loading of types gives wrong result'
+else err_exit 'unable to load types dynamically'
+fi
+
+# check that typeset -T reproduces a type.
+if $SHELL > /dev/null 2>&1 -c 'typeset -T'
+then $SHELL > junk1 <<- \+++EOF
+ typeset -T foo_t=(
+ integer x=3 y=4
+ float z=1.2
+ len()
+ {
+ ((.sh.value=sqrt(_.x**2 + _.y**2) ))
+ }
+ function count
+ {
+ print z=$z
+ }
+ )
+ typeset -T
+ print 'typeset -T'
+ +++EOF
+ $SHELL -c '. ./junk1;print "typeset -T"' > junk2
+ diff junk[12] > /dev/null || err_exit 'typeset -T not idempotent'
+ $SHELL -c '. ./junk1;print "typeset +f"' > junk2
+ [[ -s junk2 ]] || err_exit 'non-discipline-method functions found'
+else
+ err_exit 'typeset -T not supported'
+fi
+
+[[ $($SHELL -c 'typeset -T x=( typeset -a h ) ; x j; print -v j.h') ]] && err_exit 'type with indexed array without elements inserts element 0'
+
+[[ $($SHELL -c 'typeset -T x=( integer -a s ) ; compound c ; x c.i ; c.i.s[4]=666 ; print -v c') == *'[0]'* ]] && err_exit 'type with indexed array with non-zero element inserts element 0'
+
+
+{ $SHELL -c '(sleep 3;kill $$)& typeset -T x=( typeset -a s );compound c;x c.i;c.i.s[7][5][3]=hello;x c.j=c.i;[[ ${c.i} == "${c.j}" ]]';} 2> /dev/null
+exitval=$?
+if [[ $(kill -l $exitval) == TERM ]]
+then err_exit 'clone of multi-dimensional array timed out'
+elif ((exitval))
+then err_exit "c.i and c.j are not the same multi-dimensional array"
+fi
+
+typeset -T foobar_t=(
+ float x=1 y=0
+ slen()
+ {
+ print -r -- $((sqrt(_.x**2 + _.y**2)))
+ }
+ typeset -fS slen
+ len()
+ {
+ print -r -- $((sqrt(_.x**2 + _.y**2)))
+ }
+)
+unset z
+foobar_t z=(x=3 y=4)
+(( z.len == 5 )) || err_exit 'z.len should be 5'
+(( z.slen == 1 )) || err_exit 'z.slen should be 1'
+(( .sh.type.foobar_t.slen == 1 )) || err_exit '.sh.type.foobar_t.slen should be 1'
+(( .sh.type.foobar_t.len == 1 )) || err_exit '.sh.type.foobar_t.len should be 1'
+
+typeset -T z_t=( typeset -a ce )
+z_t x1
+x1.ce[3][4]=45
+compound c
+z_t -a c.x2
+c.x2[9]=x1
+got=$(typeset +p "c.x2[9].ce")
+exp='typeset -a c.x2[9].ce'
+[[ $got == "$exp" ]] || err_exit "typeset +p 'c.x2[9].ce' failed -- expected '$exp', got '$got'"
+
+unset b
+typeset -T a_t=(
+ typeset a="hello"
+)
+typeset -T b_t=(
+ a_t b
+)
+compound b
+compound -a b.ca
+b_t b.ca[4].b
+exp='typeset -C b=(typeset -C -a ca=( [4]=(b_t b=(a_t b=(a=hello))));)'
+got=$(typeset -p b)
+[[ $got == "$exp" ]] || err_exit 'typeset -p of nested type not correct'
+
+typeset -T u_t=(
+ integer dummy
+ unset()
+ {
+ print unset
+ }
+)
+unset z
+u_t -a x | read z
+[[ $z == unset ]] && err_exit 'unset discipline called on type creation'
+
+{ z=$($SHELL 2> /dev/null 'typeset -T foo; typeset -T') ;} 2> /dev/null
+[[ $z == 'typeset -T foo' ]] || err_exit '"typeset -T foo; typeset -T" failed'
+
+{ z=$($SHELL 2> /dev/null 'typeset -T foo=bar; typeset -T') ;} 2> /dev/null
+[[ $z ]] && err_exit '"typeset -T foo=bar" should not creates type foo'
+
+{
+$SHELL << \EOF
+ typeset -T board_t=(
+ compound -a board_y
+ function binsert
+ {
+ nameref figure=$1
+ integer y=$2 x=$3
+ typeset -m "_.board_y[y].board_x[x].field=figure"
+ }
+ )
+ function main
+ {
+ compound c=(
+ board_t b
+ )
+ for ((i=0 ; i < 2 ; i++ )) ; do
+ compound p=( hello=world )
+ c.b.binsert p 1 $i
+ done
+ exp='typeset -C c=(board_t b=(typeset -a board_y=( [1]=(typeset -a board_x=( [0]=(field=(hello=world;))[1]=(field=(hello=world)));));))'
+ [[ $(typeset -p c) == "$exp" ]] || exit 1
+ }
+ main
+EOF
+} 2> /dev/null
+if (( exitval=$?))
+then if [[ $(kill -l $exitval) == SEGV ]]
+ then err_exit 'typeset -m in type discipline causes exception'
+ else err_exit 'typeset -m in type discipline gives wrong value'
+ fi
+fi
+
+typeset -T pawn_t=(
+ print_debug()
+ {
+ print 'PAWN'
+ }
+)
+function main
+{
+ compound c=(
+ compound -a board
+ )
+
+ for ((i=2 ; i < 8 ; i++ )) ; do
+ pawn_t c.board[1][$i]
+ done
+
+}
+main 2> /dev/null && err_exit 'type assignment to compound array instance should generate an error'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh
new file mode 100755
index 0000000..be7c308
--- /dev/null
+++ b/src/cmd/ksh93/tests/variables.sh
@@ -0,0 +1,665 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ let Errors+=1
+}
+alias err_exit='err_exit $LINENO'
+
+Command=${0##*/}
+integer Errors=0
+
+tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
+trap "cd /; rm -rf $tmp" EXIT
+
+[[ ${.sh.version} == "$KSH_VERSION" ]] || err_exit '.sh.version != KSH_VERSION'
+unset ss
+[[ ${@ss} ]] && err_exit '${@ss} should be empty string when ss is unset'
+[[ ${!ss} == ss ]] || err_exit '${!ss} should be ss when ss is unset'
+[[ ${#ss} == 0 ]] || err_exit '${#ss} should be 0 when ss is unset'
+# RANDOM
+if (( RANDOM==RANDOM || $RANDOM==$RANDOM ))
+then err_exit RANDOM variable not working
+fi
+# SECONDS
+sleep 3
+if (( SECONDS < 2 ))
+then err_exit SECONDS variable not working
+fi
+# _
+set abc def
+if [[ $_ != def ]]
+then err_exit _ variable not working
+fi
+# ERRNO
+#set abc def
+#rm -f foobar#
+#ERRNO=
+#2> /dev/null < foobar#
+#if (( ERRNO == 0 ))
+#then err_exit ERRNO variable not working
+#fi
+# PWD
+if [[ ! $PWD -ef . ]]
+then err_exit PWD variable failed, not equivalent to .
+fi
+# PPID
+exp=$$
+got=${ $SHELL -c 'print $PPID'; }
+if [[ ${ $SHELL -c 'print $PPID'; } != $$ ]]
+then err_exit "PPID variable failed -- expected '$exp', got '$got'"
+fi
+# OLDPWD
+old=$PWD
+cd /
+if [[ $OLDPWD != $old ]]
+then err_exit "OLDPWD variable failed -- expected '$old', got '$OLDPWD'"
+fi
+cd $old || err_exit cd failed
+# REPLY
+read <<-!
+ foobar
+ !
+if [[ $REPLY != foobar ]]
+then err_exit REPLY variable not working
+fi
+integer save=$LINENO
+# LINENO
+LINENO=10
+#
+# These lines intentionally left blank
+#
+if (( LINENO != 13))
+then err_exit LINENO variable not working
+fi
+LINENO=save+10
+IFS=:
+x=a::b::c
+if [[ $x != a::b::c ]]
+then err_exit "word splitting on constants"
+fi
+set -- $x
+if [[ $# != 5 ]]
+then err_exit ":: doesn't separate null arguments "
+fi
+set x
+if x$1=0 2> /dev/null
+then err_exit "x\$1=value treated as an assignment"
+fi
+# check for attributes across subshells
+typeset -i x=3
+y=1/0
+if ( typeset x=y ) 2> /dev/null
+then err_exit "attributes not passed to subshells"
+fi
+unset x
+function x.set
+{
+ nameref foo=${.sh.name}.save
+ foo=${.sh.value}
+ .sh.value=$0
+}
+x=bar
+if [[ $x != x.set ]]
+then err_exit 'x.set does not override assignment'
+fi
+x.get()
+{
+ nameref foo=${.sh.name}.save
+ .sh.value=$foo
+}
+
+if [[ $x != bar ]]
+then err_exit 'x.get does not work correctly'
+fi
+typeset +n foo
+unset foo
+foo=bar
+(
+ unset foo
+ set +u
+ if [[ $foo != '' ]]
+ then err_exit '$foo not null after unset in subsehll'
+ fi
+)
+if [[ $foo != bar ]]
+then err_exit 'unset foo in subshell produces side effect '
+fi
+unset foo
+if [[ $( { : ${foo?hi there} ; } 2>&1) != *'hi there' ]]
+then err_exit '${foo?hi there} with foo unset does not print hi there on 2'
+fi
+x=$0
+set foobar
+if [[ ${@:0} != "$x foobar" ]]
+then err_exit '${@:0} not expanding correctly'
+fi
+set --
+if [[ ${*:0:1} != "$0" ]]
+then err_exit '${@:0} not expanding correctly'
+fi
+ACCESS=0
+function COUNT.set
+{
+ (( ACCESS++ ))
+}
+COUNT=0
+(( COUNT++ ))
+if (( COUNT != 1 || ACCESS!=2 ))
+then err_exit " set discipline failure COUNT=$COUNT ACCESS=$ACCESS"
+fi
+LANG=C > /dev/null 2>&1
+if [[ $LANG != C ]]
+then err_exit "C locale not working"
+fi
+unset RANDOM
+unset -n foo
+foo=junk
+function foo.get
+{
+ .sh.value=stuff
+ unset -f foo.get
+}
+if [[ $foo != stuff ]]
+then err_exit "foo.get discipline not working"
+fi
+if [[ $foo != junk ]]
+then err_exit "foo.get discipline not working after unset"
+fi
+# special variables
+set -- 1 2 3 4 5 6 7 8 9 10
+sleep 1000 &
+if [[ $(print -r -- ${#10}) != 2 ]]
+then err_exit '${#10}, where ${10}=10 not working'
+fi
+for i in @ '*' ! '#' - '?' '$'
+do false
+ eval foo='$'$i bar='$'{$i}
+ if [[ ${foo} != "${bar}" ]]
+ then err_exit "\$$i not equal to \${$i}"
+ fi
+ command eval bar='$'{$i%?} 2> /dev/null || err_exit "\${$i%?} gives syntax error"
+ if [[ $i != [@*] && ${foo%?} != "$bar" ]]
+ then err_exit "\${$i%?} not correct"
+ fi
+ command eval bar='$'{$i#?} 2> /dev/null || err_exit "\${$i#?} gives syntax error"
+ if [[ $i != [@*] && ${foo#?} != "$bar" ]]
+ then err_exit "\${$i#?} not correct"
+ fi
+ command eval foo='$'{$i} bar='$'{#$i} || err_exit "\${#$i} gives synta
+x error"
+ if [[ $i != @([@*]) && ${#foo} != "$bar" ]]
+ then err_exit "\${#$i} not correct"
+ fi
+done
+kill $!
+unset x
+CDPATH=/
+x=$(cd ${tmp#/})
+if [[ $x != $tmp ]]
+then err_exit 'CDPATH does not display new directory'
+fi
+CDPATH=/:
+x=$(cd ${tmp%/*}; cd ${tmp##*/})
+if [[ $x ]]
+then err_exit 'CDPATH displays new directory when not used'
+fi
+x=$(cd ${tmp#/})
+if [[ $x != $tmp ]]
+then err_exit "CDPATH ${tmp#/} does not display new directory"
+fi
+TMOUT=100
+(TMOUT=20)
+if (( TMOUT !=100 ))
+then err_exit 'setting TMOUT in subshell affects parent'
+fi
+unset y
+function setdisc # var
+{
+ eval function $1.get'
+ {
+ .sh.value=good
+ }
+ '
+}
+y=bad
+setdisc y
+if [[ $y != good ]]
+then err_exit 'setdisc function not working'
+fi
+integer x=$LINENO
+: $'\
+'
+if (( LINENO != x+3 ))
+then err_exit '\<newline> gets linenumber count wrong'
+fi
+set --
+set -- "${@-}"
+if (( $# !=1 ))
+then err_exit '"${@-}" not expanding to null string'
+fi
+for i in : % + / 3b '**' '***' '@@' '{' '[' '}' !! '*a' '$foo'
+do (eval : \${"$i"} 2> /dev/null) && err_exit "\${$i} not an syntax error"
+done
+unset IFS
+( IFS=' ' ; read -r a b c <<-!
+ x y z
+ !
+ if [[ $b ]]
+ then err_exit 'IFS=" " not causing adjacent space to be null string'
+ fi
+)
+read -r a b c <<-!
+x y z
+!
+if [[ $b != y ]]
+then err_exit 'IFS not restored after subshell'
+fi
+
+# The next part generates 3428 IFS set/read tests.
+
+unset IFS x
+function split
+{
+ i=$1 s=$2 r=$3
+ IFS=': '
+ set -- $i
+ IFS=' '
+ g="[$#]"
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ g="$g($1)"
+ shift
+ done
+ case "$g" in
+ "$s") ;;
+ *) err_exit "IFS=': '; set -- '$i'; expected '$s' got '$g'" ;;
+ esac
+ print "$i" | IFS=": " read arg rem; g="($arg)($rem)"
+ case "$g" in
+ "$r") ;;
+ *) err_exit "IFS=': '; read '$i'; expected '$r' got '$g'" ;;
+ esac
+}
+for str in \
+ '-' \
+ 'a' \
+ '- -' \
+ '- a' \
+ 'a -' \
+ 'a b' \
+ '- - -' \
+ '- - a' \
+ '- a -' \
+ '- a b' \
+ 'a - -' \
+ 'a - b' \
+ 'a b -' \
+ 'a b c'
+do
+ IFS=' '
+ set x $str
+ shift
+ case $# in
+ 0) continue ;;
+ esac
+ f1=$1
+ case $f1 in
+ '-') f1='' ;;
+ esac
+ shift
+ case $# in
+ 0) for d0 in '' ' '
+ do
+ for d1 in '' ' ' ':' ' :' ': ' ' : '
+ do
+ case $f1$d1 in
+ '') split "$d0$f1$d1" "[0]" "()()" ;;
+ ' ') ;;
+ *) split "$d0$f1$d1" "[1]($f1)" "($f1)()" ;;
+ esac
+ done
+ done
+ continue
+ ;;
+ esac
+ f2=$1
+ case $f2 in
+ '-') f2='' ;;
+ esac
+ shift
+ case $# in
+ 0) for d0 in '' ' '
+ do
+ for d1 in ' ' ':' ' :' ': ' ' : '
+ do
+ case ' ' in
+ $f1$d1|$d1$f2) continue ;;
+ esac
+ for d2 in '' ' ' ':' ' :' ': ' ' : '
+ do
+ case $f2$d2 in
+ '') split "$d0$f1$d1$f2$d2" "[1]($f1)" "($f1)()" ;;
+ ' ') ;;
+ *) split "$d0$f1$d1$f2$d2" "[2]($f1)($f2)" "($f1)($f2)" ;;
+ esac
+ done
+ done
+ done
+ continue
+ ;;
+ esac
+ f3=$1
+ case $f3 in
+ '-') f3='' ;;
+ esac
+ shift
+ case $# in
+ 0) for d0 in '' ' '
+ do
+ for d1 in ':' ' :' ': ' ' : '
+ do
+ case ' ' in
+ $f1$d1|$d1$f2) continue ;;
+ esac
+ for d2 in ' ' ':' ' :' ': ' ' : '
+ do
+ case $f2$d2 in
+ ' ') continue ;;
+ esac
+ case ' ' in
+ $f2$d2|$d2$f3) continue ;;
+ esac
+ for d3 in '' ' ' ':' ' :' ': ' ' : '
+ do
+ case $f3$d3 in
+ '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;;
+ ' ') ;;
+ *) x=$f2$d2$f3$d3
+ x=${x#' '}
+ x=${x%' '}
+ split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)"
+ ;;
+ esac
+ done
+ done
+ done
+ done
+ continue
+ ;;
+ esac
+done
+unset IFS
+
+if [[ $( (print ${12345:?}) 2>&1) != *12345* ]]
+then err_exit 'incorrect error message with ${12345?}'
+fi
+unset foobar
+if [[ $( (print ${foobar:?}) 2>&1) != *foobar* ]]
+then err_exit 'incorrect error message with ${foobar?}'
+fi
+unset bar
+if [[ $( (print ${bar:?bam}) 2>&1) != *bar*bam* ]]
+then err_exit 'incorrect error message with ${foobar?}'
+fi
+{ $SHELL -c '
+function foo
+{
+ typeset SECONDS=0
+ sleep 1.5
+ print $SECONDS
+
+}
+x=$(foo)
+(( x >1 && x < 2 ))
+'
+} 2> /dev/null || err_exit 'SECONDS not working in function'
+cat > $tmp/script <<-\!
+ posixfun()
+ {
+ unset x
+ nameref x=$1
+ print -r -- "$x"
+ }
+ function fun
+ {
+ nameref x=$1
+ print -r -- "$x"
+ }
+ if [[ $1 ]]
+ then file=${.sh.file}
+ else print -r -- "${.sh.file}"
+ fi
+!
+chmod +x $tmp/script
+. $tmp/script 1
+[[ $file == $tmp/script ]] || err_exit ".sh.file not working for dot scripts"
+[[ $($SHELL $tmp/script) == $tmp/script ]] || err_exit ".sh.file not working for scripts"
+[[ $(posixfun .sh.file) == $tmp/script ]] || err_exit ".sh.file not working for posix functions"
+[[ $(fun .sh.file) == $tmp/script ]] || err_exit ".sh.file not working for functions"
+[[ $(posixfun .sh.fun) == posixfun ]] || err_exit ".sh.fun not working for posix functions"
+[[ $(fun .sh.fun) == fun ]] || err_exit ".sh.fun not working for functions"
+[[ $(posixfun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for posix functions"
+[[ $(fun .sh.subshell) == 1 ]] || err_exit ".sh.subshell not working for functions"
+(
+ [[ $(posixfun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for posix functions in subshells"
+ [[ $(fun .sh.subshell) == 2 ]] || err_exit ".sh.subshell not working for functions in subshells"
+ (( .sh.subshell == 1 )) || err_exit ".sh.subshell not working in a subshell"
+)
+TIMEFORMAT='this is a test'
+[[ $({ { time :;} 2>&1;}) == "$TIMEFORMAT" ]] || err_exit 'TIMEFORMAT not working'
+: ${.sh.version}
+[[ $(alias integer) == *.sh.* ]] && err_exit '.sh. prefixed to alias name'
+: ${.sh.version}
+[[ $(whence rm) == *.sh.* ]] && err_exit '.sh. prefixed to tracked alias name'
+: ${.sh.version}
+[[ $(cd /bin;env | grep PWD=) == *.sh.* ]] && err_exit '.sh. prefixed to PWD'
+# unset discipline bug fix
+dave=dave
+function dave.unset
+{
+ unset dave
+}
+unset dave
+[[ $(typeset +f) == *dave.* ]] && err_exit 'unset discipline not removed'
+
+print 'print ${VAR}' > $tmp/script
+unset VAR
+VAR=new $tmp/script > $tmp/out
+got=$(<$tmp/out)
+[[ $got == new ]] || err_exit "previously unset environment variable not passed to script, expected 'new', got '$got'"
+[[ ! $VAR ]] || err_exit "previously unset environment variable set after script, expected '', got '$VAR'"
+unset VAR
+VAR=old
+VAR=new $tmp/script > $tmp/out
+got=$(<$tmp/out)
+[[ $got == new ]] || err_exit "environment variable covering local variable not passed to script, expected 'new', got '$got'"
+[[ $VAR == old ]] || err_exit "previously set local variable changed after script, expected 'old', got '$VAR'"
+unset VAR
+export VAR=old
+VAR=new $tmp/script > $tmp/out
+got=$(<$tmp/out)
+[[ $got == new ]] || err_exit "environment variable covering environment variable not passed to script, expected 'new', got '$got'"
+[[ $VAR == old ]] || err_exit "previously set environment variable changed after script, expected 'old', got '$VAR'"
+
+(
+ unset dave
+ function dave.append
+ {
+ .sh.value+=$dave
+ dave=
+ }
+ dave=foo; dave+=bar
+ [[ $dave == barfoo ]] || exit 2
+) 2> /dev/null
+case $? in
+0) ;;
+1) err_exit 'append discipline not implemented';;
+*) err_exit 'append discipline not working';;
+esac
+.sh.foobar=hello
+{
+ function .sh.foobar.get
+ {
+ .sh.value=world
+ }
+} 2> /dev/null || err_exit "cannot add get discipline to .sh.foobar"
+[[ ${.sh.foobar} == world ]] || err_exit 'get discipline for .sh.foobar not working'
+x='a|b'
+IFS='|'
+set -- $x
+[[ $2 == b ]] || err_exit '$2 should be b after set'
+exec 3>&2 2> /dev/null
+set -x
+( IFS= ) 2> /dev/null
+set +x
+exec 2>&3-
+set -- $x
+[[ $2 == b ]] || err_exit '$2 should be b after subshell'
+: & pid=$!
+( : & )
+[[ $pid == $! ]] || err_exit '$! value not preserved across subshells'
+unset foo
+typeset -A foo
+function foo.set
+{
+ case ${.sh.subscript} in
+ bar) if ((.sh.value > 1 ))
+ then .sh.value=5
+ foo[barrier_hit]=yes
+ fi
+ ;;
+ barrier_hit)
+ if [[ ${.sh.value} == yes ]]
+ then foo[barrier_not_hit]=no
+ else foo[barrier_not_hit]=yes
+ fi
+ ;;
+ esac
+}
+foo[barrier_hit]=no
+foo[bar]=1
+(( foo[bar] == 1 )) || err_exit 'foo[bar] should be 1'
+[[ ${foo[barrier_hit]} == no ]] || err_exit 'foo[barrier_hit] should be no'
+[[ ${foo[barrier_not_hit]} == yes ]] || err_exit 'foo[barrier_not_hit] should be yes'
+foo[barrier_hit]=no
+foo[bar]=2
+(( foo[bar] == 5 )) || err_exit 'foo[bar] should be 5'
+[[ ${foo[barrier_hit]} == yes ]] || err_exit 'foo[barrier_hit] should be yes'
+[[ ${foo[barrier_not_hit]} == no ]] || err_exit 'foo[barrier_not_hit] should be no'
+unset x
+typeset -i x
+function x.set
+{
+ typeset sub=${.sh.subscript}
+ (( sub > 0 )) && (( x[sub-1]= x[sub-1] + .sh.value ))
+}
+x[0]=0 x[1]=1 x[2]=2 x[3]=3
+[[ ${x[@]} == '12 8 5 3' ]] || err_exit 'set discipline for indexed array not working correctly'
+float seconds
+((SECONDS=3*4))
+seconds=SECONDS
+(( seconds < 12 || seconds > 12.1 )) && err_exit "SECONDS is $seconds and should be close to 12"
+unset a
+function a.set
+{
+ print -r -- "${.sh.name}=${.sh.value}"
+}
+[[ $(a=1) == a=1 ]] || err_exit 'set discipline not working in subshell assignment'
+[[ $(a=1 :) == a=1 ]] || err_exit 'set discipline not working in subshell command'
+
+[[ ${.sh.subshell} == 0 ]] || err_exit '${.sh.subshell} should be 0'
+(
+ [[ ${.sh.subshell} == 1 ]] || err_exit '${.sh.subshell} should be 1'
+ (
+ [[ ${.sh.subshell} == 2 ]] || err_exit '${.sh.subshell} should be 2'
+ )
+)
+
+set -- {1..32768}
+(( $# == 32768 )) || err_exit "\$# failed -- expected 32768, got $#"
+set --
+
+unset r v x
+path=$PATH
+x=foo
+for v in EDITOR VISUAL OPTIND CDPATH FPATH PATH ENV LINENO RANDOM SECONDS _
+do nameref r=$v
+ unset $v
+ if ( $SHELL -c "unset $v; : \$$v" ) 2>/dev/null
+ then [[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'"
+ r=$x
+ [[ $r == $x ]] || err_exit "$v=$x failed -- expected '$x', got '$r'"
+ else err_exit "unset $v; : \$$v failed"
+ fi
+done
+
+x=x
+for v in LC_ALL LC_CTYPE LC_MESSAGES LC_COLLATE LC_NUMERIC
+do nameref r=$v
+ unset $v
+ [[ $r ]] && err_exit "unset $v failed -- expected '', got '$r'"
+ d=$($SHELL -c "$v=$x" 2>&1)
+ [[ $d ]] || err_exit "$v=$x failed -- expected locale diagnostic"
+ { g=$( r=$x; print -- $r ); } 2>/dev/null
+ [[ $g == '' ]] || err_exit "$v=$x failed -- expected '', got '$g'"
+ { g=$( r=C; r=$x; print -- $r ); } 2>/dev/null
+ [[ $g == 'C' ]] || err_exit "$v=C; $v=$x failed -- expected 'C', got '$g'"
+done
+PATH=$path
+
+cd $tmp
+
+print print -n zzz > zzz
+chmod +x zzz
+exp='aaazzz'
+got=$($SHELL -c 'unset SHLVL; print -n aaa; ./zzz' 2>&1) >/dev/null 2>&1
+[[ $got == "$exp" ]] || err_exit "unset SHLVL causes script failure -- expected '$exp', got '$got'"
+
+mkdir glean
+for cmd in date ok
+do exp="$cmd ok"
+ rm -f $cmd
+ print print $exp > glean/$cmd
+ chmod +x glean/$cmd
+ got=$(CDPATH=:.. $SHELL -c "PATH=:/bin:/usr/bin; date > /dev/null; cd glean && ./$cmd" 2>&1)
+ [[ $got == "$exp" ]] || err_exit "cd with CDPATH after PATH change failed -- expected '$exp', got '$got'"
+done
+
+v=LC_CTYPE
+unset $v
+[[ -v $v ]] && err_exit "unset $v; [[ -v $v ]] failed"
+eval $v=C
+[[ -v $v ]] || err_exit "$v=C; [[ -v $v ]] failed"
+
+cmd='set --nounset; unset foo; : ${!foo*}'
+$SHELL -c "$cmd" 2>/dev/null || err_exit "'$cmd' exit status $?, expected 0"
+
+SHLVL=1
+level=$($SHELL -c $'$SHELL -c \'print -r "$SHLVL"\'')
+[[ $level == 3 ]] || err_exit "SHLVL should be 3 not $level"
+
+[[ $($SHELL -c '{ x=1; : ${x.};print ok;}' 2> /dev/null) == ok ]] || err_exit '${x.} where x is a simple variable causes shell to abort'
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/vartree1.sh b/src/cmd/ksh93/tests/vartree1.sh
new file mode 100755
index 0000000..d558dc6
--- /dev/null
+++ b/src/cmd/ksh93/tests/vartree1.sh
@@ -0,0 +1,215 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# variable tree test #001
+# Propose of this test is whether ksh93 handles global variable trees
+# and function-local variable trees the same way, including "nameref"
+# and "unset" handling.
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+function build_tree
+{
+#set -o errexit -o xtrace
+ typeset index
+ typeset s
+ typeset i
+ typeset dummy
+ typeset a b c d e f
+
+ nameref dest_tree="$1" # destination tree
+ nameref srcdata="$2" # source data
+ typeset tree_mode="$3" # mode to define the type of leads
+
+ typeset -A dest_tree.l1
+
+ for index in "${!srcdata.hashnodes[@]}" ; do
+ nameref node=srcdata.hashnodes["${index}"]
+
+ for i in "${node.xlfd[@]}" ; do
+ IFS='-' read dummy a b c d e f <<<"$i"
+
+ if [[ "$a" == "" ]] ; then
+ a="$dummy"
+ fi
+
+ [[ "$a" == "" ]] && a='-'
+ [[ "$b" == "" ]] && b='-'
+ [[ "$c" == "" ]] && c='-'
+
+ if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
+ #if ! (unset dest_tree.l1["$a"]) ; then
+ typeset -A dest_tree.l1["$a"].l2
+ fi
+
+ if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then
+ #if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3
+ fi
+
+ if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries
+ fi
+
+ #dest_tree.l1["$a"].l2["$b"].l3["$c"].entries+=( "$index" )
+ typeset new_index
+ if [[ "${tree_mode}" == "leaf_name" ]] ; then
+ new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 ))
+ else
+ new_index="${node.name}"
+
+ # skip if the leaf node already exists
+ if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then
+ continue
+ fi
+ fi
+
+ add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}"
+ done
+ done
+
+ return 0
+}
+
+function add_tree_leaf
+{
+ nameref tree_leafnode="$1"
+ nameref data_node=srcdata.hashnodes["$2"]
+ typeset add_mode="$3"
+
+ case "${add_mode}" in
+ "leaf_name")
+ tree_leafnode="${data_node.name}"
+ return 0
+ ;;
+ "leaf_compound")
+ tree_leafnode=(
+ typeset name="${data_node.name}"
+ typeset -a filenames=( "${data_node.filenames[@]}" )
+ typeset -a comments=( "${data_node.comments[@]}" )
+ typeset -a xlfd=( "${data_node.xlfd[@]}" )
+ )
+ return 0
+ ;;
+ *)
+ print -u2 -f "ERROR: Unknown mode %s in add_tree_leaf\n" "${add_mode}"
+ return 1
+ ;;
+ esac
+
+ # not reached
+ return 1
+}
+
+# "mysrcdata_local" and "mysrcdata_global" must be identical
+typeset mysrcdata_global=(
+ typeset -A hashnodes=(
+ [abcd]=(
+ name='abcd'
+ typeset -a xlfd=(
+ '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific'
+ )
+ typeset -a comments=(
+ 'comment 1'
+ 'comment 2'
+ 'comment 3'
+ )
+ typeset -a filenames=(
+ '/home/foo/abcd_1'
+ '/home/foo/abcd_2'
+ '/home/foo/abcd_3'
+ )
+ )
+ )
+)
+
+mytree_global=()
+
+function main
+{
+ # "mysrcdata_local" and "mysrcdata_global" must be identical
+ typeset mysrcdata_local=(
+ typeset -A hashnodes=(
+ [abcd]=(
+ name='abcd'
+ typeset -a xlfd=(
+ '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific'
+ )
+ typeset -a comments=(
+ 'comment 1'
+ 'comment 2'
+ 'comment 3'
+ )
+ typeset -a filenames=(
+ '/home/foo/abcd_1'
+ '/home/foo/abcd_2'
+ '/home/foo/abcd_3'
+ )
+ )
+ )
+ )
+
+ # build tree using global tree variables
+ build_tree mytree_global mysrcdata_global leaf_compound || \
+ err_exit 'build_tree mytree_global mysrcdata_global leaf_compound returned an error'
+
+ (( $(print -r -- "${mytree_global}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global' too small"
+
+ # build tree using local tree variables
+ mytree_local=()
+ build_tree mytree_local mysrcdata_local leaf_compound || \
+ err_exit 'build_tree mytree_local mysrcdata_local leaf_compound returned an error'
+
+ (( $(print -r -- "${mytree_local}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local' too small"
+
+ # Compare trees
+ if [[ "${mytree_global}" != "${mytree_local}" ]] ; then
+ err_exit "compound trees 'mytree_local' and 'mytree_global' not identical"
+ fi
+
+ unset 'mytree_global.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ err_exit "variable 'mytree_global.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
+ [[ "${mytree_global}" != "${mytree_local}" ]] || err_exit "mytree_global and mytree_local should differ"
+
+ unset 'mytree_local.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ err_exit "variable 'mytree_local.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
+ # Compare trees (after "unset")
+ if [[ "${mytree_global}" != "${mytree_local}" ]] ; then
+ err_exit "compound trees 'mytree_local' and 'mytree_global' not identical after unset"
+ fi
+}
+
+main
+
+exit $((Errors<125?Errors:125))
diff --git a/src/cmd/ksh93/tests/vartree2.sh b/src/cmd/ksh93/tests/vartree2.sh
new file mode 100755
index 0000000..e3e4cff
--- /dev/null
+++ b/src/cmd/ksh93/tests/vartree2.sh
@@ -0,0 +1,335 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1982-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# David Korn <dgk@research.att.com> #
+# #
+########################################################################
+#
+# variable tree test #002
+# Propose of this test is whether ksh93 handles global variable trees
+# and function-local variable trees the same way, including "nameref"
+# and "unset" handling.
+#
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+# "built_tree1" and "built_tree2" are identical except the way how they test
+# whether a variable exists:
+# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable
+# as non-zero length content
+# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell
+function build_tree1
+{
+#set -o errexit -o xtrace
+ typeset index
+ typeset s
+ typeset i
+ typeset dummy
+ typeset a b c d e f
+
+ nameref dest_tree="$1" # destination tree
+ nameref srcdata="$2" # source data
+ typeset tree_mode="$3" # mode to define the type of leads
+
+ typeset -A dest_tree.l1
+
+ for index in "${!srcdata.hashnodes[@]}" ; do
+ nameref node=srcdata.hashnodes["${index}"]
+
+ for i in "${node.xlfd[@]}" ; do
+ IFS='-' read dummy a b c d e f <<<"$i"
+
+ if [[ "$a" == "" ]] ; then
+ a="$dummy"
+ fi
+
+ [[ "$a" == "" ]] && a='-'
+ [[ "$b" == "" ]] && b='-'
+ [[ "$c" == "" ]] && c='-'
+
+ if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
+ #if ! (unset dest_tree.l1["$a"]) ; then
+ typeset -A dest_tree.l1["$a"].l2
+ fi
+
+ if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then
+ #if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3
+ fi
+
+ if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries
+ fi
+
+ typeset new_index
+ if [[ "${tree_mode}" == "leaf_name" ]] ; then
+ new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 ))
+ else
+ new_index="${node.name}"
+
+ # skip if the leaf node already exists
+ if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then
+ continue
+ fi
+ fi
+
+ add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}"
+ done
+ done
+
+ return 0
+}
+
+# "built_tree1" and "built_tree2" are identical except the way how they test
+# whether a variable exists:
+# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable
+# as non-zero length content
+# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell
+function build_tree2
+{
+#set -o errexit -o xtrace
+ typeset index
+ typeset s
+ typeset i
+ typeset dummy
+ typeset a b c d e f
+
+ nameref dest_tree="$1" # destination tree
+ nameref srcdata="$2" # source data
+ typeset tree_mode="$3" # mode to define the type of leads
+
+ typeset -A dest_tree.l1
+
+ for index in "${!srcdata.hashnodes[@]}" ; do
+ nameref node=srcdata.hashnodes["${index}"]
+
+ for i in "${node.xlfd[@]}" ; do
+ IFS='-' read dummy a b c d e f <<<"$i"
+
+ if [[ "$a" == "" ]] ; then
+ a="$dummy"
+ fi
+
+ [[ "$a" == "" ]] && a='-'
+ [[ "$b" == "" ]] && b='-'
+ [[ "$c" == "" ]] && c='-'
+
+ #if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then
+ if ! (unset dest_tree.l1["$a"]) ; then
+ typeset -A dest_tree.l1["$a"].l2
+ fi
+
+ #if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then
+ if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3
+ fi
+
+ if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then
+ typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries
+ fi
+
+ typeset new_index
+ if [[ "${tree_mode}" == "leaf_name" ]] ; then
+ new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 ))
+ else
+ new_index="${node.name}"
+
+ # skip if the leaf node already exists
+ if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then
+ continue
+ fi
+ fi
+
+ add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}"
+ done
+ done
+
+ return 0
+}
+
+
+function add_tree_leaf
+{
+ nameref tree_leafnode="$1"
+ nameref data_node=srcdata.hashnodes["$2"]
+ typeset add_mode="$3"
+
+ case "${add_mode}" in
+ "leaf_name")
+ tree_leafnode="${data_node.name}"
+ return 0
+ ;;
+ "leaf_compound")
+ tree_leafnode=(
+ typeset name="${data_node.name}"
+ typeset -a filenames=( "${data_node.filenames[@]}" )
+ typeset -a comments=( "${data_node.comments[@]}" )
+ typeset -a xlfd=( "${data_node.xlfd[@]}" )
+ )
+ return 0
+ ;;
+ *)
+ print -u2 -f "ERROR: Unknown mode %s in add_tree_leaf\n" "${add_mode}"
+ return 1
+ ;;
+ esac
+
+ # not reached
+ return 1
+}
+
+# "mysrcdata_local" and "mysrcdata_global" must be identical
+typeset mysrcdata_global=(
+ typeset -A hashnodes=(
+ [abcd]=(
+ name='abcd'
+ typeset -a xlfd=(
+ '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific'
+ )
+ typeset -a comments=(
+ 'comment 1'
+ 'comment 2'
+ 'comment 3'
+ )
+ typeset -a filenames=(
+ '/home/foo/abcd_1'
+ '/home/foo/abcd_2'
+ '/home/foo/abcd_3'
+ )
+ )
+ )
+)
+
+mytree_global1=()
+mytree_global2=()
+
+function main
+{
+ # "mysrcdata_local" and "mysrcdata_global" must be identical
+ typeset mysrcdata_local=(
+ typeset -A hashnodes=(
+ [abcd]=(
+ name='abcd'
+ typeset -a xlfd=(
+ '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific'
+ '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific'
+ )
+ typeset -a comments=(
+ 'comment 1'
+ 'comment 2'
+ 'comment 3'
+ )
+ typeset -a filenames=(
+ '/home/foo/abcd_1'
+ '/home/foo/abcd_2'
+ '/home/foo/abcd_3'
+ )
+ )
+ )
+ )
+
+ #### Build tree using global tree variables
+ build_tree1 mytree_global1 mysrcdata_global leaf_compound || \
+ err_exit 'build_tree1 mytree_global1 mysrcdata_global leaf_compound returned an error'
+ (( $(print -r -- "${mytree_global1}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global1' too small"
+
+ build_tree2 mytree_global2 mysrcdata_global leaf_compound || \
+ err_exit 'build_tree2 mytree_global2 mysrcdata_global leaf_compound returned an error'
+ (( $(print -r -- "${mytree_global2}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global2' too small"
+
+
+ #### build tree using local tree variables
+ mytree_local1=()
+ mytree_local2=()
+
+ build_tree1 mytree_local1 mysrcdata_local leaf_compound || \
+ err_exit 'build_tree1 mytree_local1 mysrcdata_local leaf_compound returned an error'
+ (( $(print -r -- "${mytree_local1}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local1' too small"
+
+ build_tree2 mytree_local2 mysrcdata_local leaf_compound || \
+ err_exit 'build_tree2 mytree_local2 mysrcdata_local leaf_compound returned an error'
+ (( $(print -r -- "${mytree_local2}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local2' too small"
+
+
+ #### Compare treess
+ if [[ "${mytree_global1}" != "${mytree_local1}" ]] ; then
+ err_exit "compound trees 'mytree_global1' and 'mytree_local1' not identical"
+ fi
+
+ if [[ "${mytree_global1}" != "${mytree_global2}" ]] ; then
+ err_exit "compound trees 'mytree_global1' and 'mytree_global2' not identical"
+ fi
+
+ if [[ "${mytree_local1}" != "${mytree_local2}" ]] ; then
+ err_exit "compound trees 'mytree_local1' and 'mytree_local2' not identical"
+ fi
+
+
+ #### test "unset" in a subshell
+ ( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \
+ err_exit "try 1: variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found"
+ ( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \
+ err_exit "try 2: variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found"
+
+ # remove parent node (array element) and then check whether the child is gone, too:
+ (
+ unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]'
+ [[ -v 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'} ]]
+ ) && err_exit "global: parent node removed (array element), child still exists"
+ (
+ unset 'mytree_local1.l1[urw].l2[itc zapfdingbats]'
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
+ ) && err_exit "local: parent node removed (array element), child still exists"
+
+ # remove parent node (array variable) and then check whether the child is gone, too:
+ (
+ unset 'mytree_local1.l1[urw].l2'
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
+ ) && err_exit "global: parent node removed (array variable), child still exists"
+ (
+ unset 'mytree_local1.l1[urw].l2'
+ [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]]
+ ) && err_exit "local: parent node removed (array variable), child still exists"
+
+
+ #### test "unset" and compare trees
+ unset 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ err_exit "variable 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
+ [[ "${mytree_global1}" != "${mytree_local1}" ]] || err_exit "mytree_global1 and mytree_local1 should differ"
+
+ unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ||
+ err_exit "variable 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found"
+
+ # Compare trees (after "unset")
+ if [[ "${mytree_global1}" != "${mytree_local1}" ]] ; then
+ err_exit "compound trees 'mytree_local1' and 'mytree_global1' not identical after unset"
+ fi
+}
+
+main
+
+exit $((Errors<125?Errors:125))
diff --git a/src/lib/Makefile b/src/lib/Makefile
new file mode 100644
index 0000000..a046f68
--- /dev/null
+++ b/src/lib/Makefile
@@ -0,0 +1 @@
+:MAKE:
diff --git a/src/lib/Mamfile b/src/lib/Mamfile
new file mode 100644
index 0000000..7b439a5
--- /dev/null
+++ b/src/lib/Mamfile
@@ -0,0 +1,7 @@
+info mam static
+note component level :MAKE: equivalent
+make install
+make all
+exec - ${MAMAKE} -r '*' ${MAMAKEARGS}
+done all virtual
+done install virtual
diff --git a/src/lib/libast/Makefile b/src/lib/libast/Makefile
new file mode 100644
index 0000000..8dd819a
--- /dev/null
+++ b/src/lib/libast/Makefile
@@ -0,0 +1,442 @@
+/*
+ * ast library
+ */
+
+:PACKAGE: ast
+
+LICENSE = since=1985,author=gsf+dgk+kpv
+
+ID = ast
+
+HOSTTYPE == "$(CC.HOSTTYPE)"
+
+CCFLAGS = $(CC.SUFFIX.DEBUG:+$(CC.DEBUG)) $(CC.OPTIMIZE) $(CC.DLL)
+
+IFFEFLAGS = -v -X ast -X std
+
+.SOURCE : aso cdt comp dir disc hash man misc obsolete path port preroot \
+ regex sfio stdio string tm uwin vec vmalloc
+
+.SOURCE.h : include comp std cdt vmalloc
+
+CP = $(STDCP|"cp")
+
+PARANOID ==
+CONF_LIBPREFIX == "$(CC.PREFIX.DYNAMIC|CC.PREFIX.SHARED)"
+CONF_LIBSUFFIX == "$(CC.SUFFIX.DYNAMIC|CC.SUFFIX.SHARED)"
+DEBUG ==
+__OBSOLETE__ == $("6 months ago":@F=%(%Y0101)T)
+
+HEADERSRC = ast.h ast_dir.h ast_getopt.h ast_std.h \
+ ast_namval.h ast_windows.h \
+ ccode.h cdt.h cdtlib.h cmdarg.h debug.h dt.h error.h find.h ftw.h \
+ ftwalk.h fts.h fs3d.h getopt.h glob.h hash.h hashkey.h hashpart.h \
+ ip6.h lc.h ls.h magic.h mc.h mime.h mnt.h modecanon.h modex.h \
+ namval.h option.h proc.h re_comp.h recfmt.h regex.h regexp.h \
+ sfio.h sfio_s.h sfio_t.h sfdisc.h shcmd.h \
+ stack.h stak.h stk.h swap.h tar.h times.h tm.h tok.h \
+ usage.h vdb.h vecargs.h vmalloc.h wait.h wordexp.h \
+ bytesex.h endian.h fnmatch.h magicid.h fnv.h aso.h \
+ $(HEADERSTD)
+
+HEADERGEN = align.h preroot.h sig.h tmx.h tv.h \
+ $(ID)_api.h $(ID)_botch.h $(ID)_ccode.h $(ID)_fcntl.h $(ID)_float.h \
+ $(ID)_fs.h $(ID)_lib.h $(ID)_map.h $(ID)_mmap.h $(ID)_mode.h $(ID)_ndbm.h \
+ $(ID)_param.h $(ID)_sys.h $(ID)_time.h $(ID)_time.h $(ID)_tty.h \
+ $(ID)_vfork.h $(ID)_wait.h $(ID)_limits.h $(ID)_standards.h $(ID)_sizeof.h \
+ $(HEADERSTD:/^/$(ID)_/)
+
+HEADEREXP = $(ID)_common.h
+
+HEADEROPT = fmtmsg.h libgen.h syslog.h
+
+HEADERSTD = dirent.h iconv.h nl_types.h stdio.h wchar.h wctype.h
+
+$(ID) 5.4 :LIBRARY: README RELEASE \
+ LIBAST.3 aso.3 ast.3 astsa.3 cdt.3 chr.3 compat.3 error.3 \
+ find.3 fmt.3 fmtls.3 fs3d.3 ftwalk.3 getcwd.3 hash.3 iblocks.3 \
+ int.3 ip6.3 magic.3 mem.3 mime.3 modecanon.3 optget.3 path.3 \
+ preroot.3 proc.3 re.3 regex.3 setenviron.3 sfdisc.3 sfio.3 \
+ sig.3 spawnveg.3 stak.3 stk.3 strcopy.3 strdup.3 strelapsed.3 \
+ strerror.3 stresc.3 streval.3 strgid.3 strmatch.3 stropt.3 \
+ strperm.3 strsignal.3 strsort.3 strtape.3 strton.3 struid.3 \
+ swap.3 tab.3 tm.3 tmx.3 tok.3 touch.3 tv.3 vecargs.3 vmalloc.3 \
+ $(HEADERSRC) \
+ state.c transition.c \
+ dirlib.h opendir.c readdir.c rewinddir.c seekdir.c telldir.c \
+ getcwd.c fastfind.c \
+ hashlib.h hashalloc.c hashdump.c hashfree.c hashlast.c \
+ hashlook.c hashscan.c hashsize.c hashview.c hashwalk.c \
+ memhash.c memsum.c strhash.c strkey.c strsum.c \
+ stracmp.c strnacmp.c \
+ ccmap.c ccmapid.c ccnative.c \
+ chresc.c chrtoi.c streval.c strexpr.c strmatch.c strcopy.c \
+ modelib.h modei.c modex.c strmode.c \
+ strlcat.c strlcpy.c strlook.c strncopy.c strsearch.c strpsearch.c \
+ stresc.c stropt.c strtape.c strpcmp.c strnpcmp.c strvcmp.c strnvcmp.c \
+ tok.c tokline.c tokscan.c \
+ pathaccess.c pathcat.c pathcanon.c pathcheck.c pathpath.c \
+ pathexists.c pathfind.c pathkey.c pathprobe.c pathrepl.c \
+ pathnative.c pathposix.c pathtemp.c pathtmp.c pathstat.c \
+ pathgetlink.c pathsetlink.c pathbin.c pathshell.c pathcd.c \
+ pathprog.c \
+ fs3d.c ftwalk.c ftwflags.c fts.c \
+ astintercept.c conformance.c getenv.c setenviron.c \
+ optget.c optjoin.c optesc.c optctx.c strsort.c struniq.c \
+ magic.c mime.c mimetype.c signal.c sigflag.c systrace.c \
+ error.c errorf.c errormsg.c errorx.c \
+ localeconv.c setlocale.c translate.c \
+ catopen.c iconv.c lc.c lctab.c mc.c \
+ base64.c recfmt.c recstr.c reclen.c fmtrec.c \
+ fmtbase.c fmtbuf.c fmtclock.c fmtdev.c fmtelapsed.c fmterror.c \
+ fmtesc.c fmtfmt.c fmtfs.c fmtident.c fmtint.c fmtip4.c fmtip6.c fmtls.c \
+ fmtmatch.c fmtmode.c fmtnum.c fmtperm.c fmtre.c fmttime.c fmtuid.c \
+ fmtgid.c fmtsignal.c fmtscale.c fmttmx.c fmttv.c fmtversion.c \
+ strelapsed.c strperm.c struid.c strgid.c \
+ strtoip4.c strtoip6.c stack.c stk.c \
+ swapget.c swapmem.c swapop.c swapput.c \
+ sigdata.c sigcrit.c sigunblock.c \
+ proclib.h procopen.c procclose.c procrun.c procfree.c \
+ tmdate.c tmequiv.c tmfix.c tmfmt.c tmform.c tmgoff.c tminit.c \
+ tmleap.c tmlex.c tmlocale.c tmmake.c tmpoff.c tmscan.c \
+ tmsleep.c tmtime.c tmtype.c tmweek.c tmword.c tmzone.c \
+ tmxdate.c tmxduration.c tmxfmt.c tmxgettime.c tmxleap.c tmxmake.c \
+ tmxscan.c tmxsettime.c tmxsleep.c tmxtime.c tmxtouch.c \
+ tvcmp.c tvgettime.c tvsettime.c tvsleep.c tvtouch.c \
+ cmdarg.c vecargs.c vecfile.c vecfree.c vecload.c vecstring.c \
+ univlib.h univdata.c touch.c mnt.c debug.c \
+ memccpy.c memchr.c memcmp.c memcpy.c memdup.c memmove.c memset.c \
+ mkdir.c mkfifo.c mknod.c rmdir.c remove.c rename.c link.c unlink.c \
+ strdup.c strchr.c strrchr.c strstr.c \
+ strtod.c strtold.c \
+ strtol.c strtoll.c strtoul.c strtoull.c strton.c strtonll.c \
+ strntod.c strntold.c strnton.c strntonll.c \
+ strntol.c strntoll.c strntoul.c strntoull.c \
+ strcasecmp.c strncasecmp.c strerror.c \
+ mktemp.c tmpnam.c fsync.c \
+ execlp.c execve.c execvp.c execvpe.c spawnveg.c \
+ vfork.c killpg.c \
+ hsearch.c tsearch.c \
+ getlogin.c putenv.c setenv.c unsetenv.c \
+ lstat.c statvfs.c \
+ eaccess.c gross.c gross_sgi.h omitted.c \
+ fakelink.h readlink.c symlink.c \
+ getpgrp.c setpgid.c setsid.c waitpid.c \
+ creat64.c fcntl.c open.c \
+ atexit.c getdents.c getwd.c dup2.c errno.c \
+ getpreroot.c ispreroot.c realopen.c setpreroot.c \
+ getgroups.c mount.c system.c iblocks.c \
+ modedata.c tmdata.c \
+ memfatal.c sfkeyprintf.c \
+ sfdcdio.c sfdcdos.c sfdcfilter.c sfdcseekable.c \
+ sfdcslow.c sfdcsubstr.c sfdctee.c sfdcunion.c \
+ sfdcmore.c sfdcprefix.c \
+ wc.c wc2utf8.c \
+ /* standards */ \
+ basename.c closelog.c dirname.c fmtmsglib.c fnmatch.c ftw.c \
+ getdate.c getsubopt.c glob.c nftw.c openlog.c re_comp.c \
+ resolvepath.c realpath.c regcmp.c regexp.c setlogmask.c strftime.c \
+ strptime.c swab.c syslog.c sysloglib.h tempnam.c \
+ wordexp.c mktime.c \
+ /* regex */ \
+ reglib.h regalloc.c regclass.c regcoll.c regcomp.c regcache.c \
+ regdecomp.c regerror.c regexec.c regfatal.c reginit.c regnexec.c \
+ regsubcomp.c regsubexec.c regsub.c regrecord.c regrexec.c regstat.c \
+ /* cdt */ \
+ dthdr.h dtclose.c dtdisc.c dthash.c dtlist.c dtmethod.c \
+ dtopen.c dtstrhash.c dttree.c dtview.c dtwalk.c \
+ dtnew.c dtcomp.c \
+ /* sfio */ \
+ sfhdr.h sfdchdr.h \
+ sfclose.c sfclrlock.c sfdisc.c sfdlen.c sfexcept.c \
+ sfgetl.c sfgetu.c sfcvt.c sfecvt.c sffcvt.c \
+ sfextern.c sffilbuf.c sfflsbuf.c sfprints.c sfgetd.c \
+ sfgetr.c sfllen.c sfmode.c sfmove.c sfnew.c \
+ sfpkrd.c sfnotify.c sfnputc.c sfopen.c sfpeek.c sfpoll.c \
+ sfpool.c sfpopen.c sfprintf.c sfputd.c sfputl.c sfputr.c \
+ sfputu.c sfrd.c sfread.c sfreserve.c sfscanf.c sfseek.c sfset.c \
+ sfsetbuf.c sfsetfd.c sfsize.c sfsk.c sfstack.c sfstrtod.c sfsync.c \
+ sfswap.c sftable.c sftell.c sftmp.c sfungetc.c sfvprintf.c \
+ sfvscanf.c sfwr.c sfwrite.c sfpurge.c sfraise.c sfwalk.c \
+ sfgetm.c sfmutex.c sfputm.c sfresize.c \
+ _sfclrerr.c _sfeof.c _sferror.c _sffileno.c \
+ _sfopen.c _sfstacked.c _sfvalue.c \
+ _sfgetc.c _sfgetl.c _sfgetl2.c _sfgetu.c _sfgetu2.c \
+ _sfdlen.c _sfllen.c _sfslen.c _sfulen.c \
+ _sfputc.c _sfputd.c _sfputl.c _sfputm.c _sfputu.c \
+ /* stdio */ \
+ clearerr.c fclose.c fdopen.c feof.c ferror.c fflush.c \
+ fgetc.c fgetpos.c fgets.c fileno.c fopen.c fprintf.c \
+ fpurge.c fputc.c fputs.c fread.c freopen.c fscanf.c \
+ fseek.c fseeko.c fsetpos.c ftell.c ftello.c fwrite.c \
+ flockfile.c ftrylockfile.c funlockfile.c \
+ getc.c getchar.c getw.c pclose.c popen.c printf.c \
+ putc.c putchar.c puts.c putw.c rewind.c scanf.c \
+ setbuf.c setbuffer.c setlinebuf.c setvbuf.c \
+ snprintf.c sprintf.c sscanf.c \
+ asprintf.c vasprintf.c \
+ stdio/tmpfile.c ungetc.c vfprintf.c vfscanf.c vprintf.c \
+ vscanf.c vsnprintf.c vsprintf.c vsscanf.c \
+ _doprnt.c _doscan.c _filbuf.c _flsbuf.c _stdfun.c \
+ _stdopen.c _stdprintf.c _stdscanf.c _stdsprnt.c \
+ _stdvbuf.c _stdvsnprnt.c _stdvsprnt.c _stdvsscn.c \
+ /* wchar stdio */ \
+ fgetwc.c fwprintf.c putwchar.c vfwscanf.c wprintf.c \
+ fgetws.c fwscanf.c swprintf.c vswprintf.c wscanf.c \
+ fputwc.c getwc.c swscanf.c vswscanf.c \
+ fputws.c getwchar.c ungetwc.c vwprintf.c \
+ fwide.c putwc.c vfwprintf.c vwscanf.c \
+ /* stdio extensions */ \
+ stdio_c99.c fcloseall.c fmemopen.c getdelim.c getline.c \
+ /* math */ \
+ frexp.c frexpl.c \
+ /* ast */ \
+ astcopy.c astconf.c astdynamic.c astlicense.c astquery.c astwinsize.c \
+ conftab.c \
+ $(CC.LD.STATIC) aststatic.c getopt.c getoptl.c $(CC.LD.DYNAMIC) \
+ /* aso */ \
+ aso.c asolock.c asometh.c asorelax.c aso-sem.c aso-fcntl.c \
+ /* vmalloc */ \
+ vmalloc.h vmhdr.h vmbest.c vmclear.c vmclose.c vmdcheap.c vmdebug.c \
+ vmdisc.c vmexit.c vmlast.c vmopen.c vmpool.c vmprivate.c vmprofile.c \
+ vmregion.c vmsegment.c vmset.c vmstat.c vmstrdup.c vmtrace.c vmwalk.c \
+ vmmopen.c malloc.c vmgetmem.c \
+ /* uwin */ \
+ mathimpl.h rlib.h \
+ a64l.c acosh.c asinh.c atanh.c cbrt.c crypt.c erf.c \
+ err.c exp.c exp__E.c expm1.c gamma.c getpass.c lgamma.c log.c log1p.c \
+ log__L.c rand48.c random.c rcmd.c rint.c support.c \
+ /* obsolete */ \
+ sfstrtmp.c spawn.c \
+ -liconv -lw /* these should be pulled in by -lc */
+
+/*
+ * man is stdio.h problematic
+ * the std/stdio.h => ast_stdio.h runaround should
+ * get to a steady state
+ *
+ * also, -D_BLD_ast must be explicit for the uwin bootstrap
+ */
+
+.MAKEINIT : .AST.INIT
+.AST.INIT : .MAKE
+ CCFLAGS += -D_BLD_ast
+
+parameter (_BLD_ast)
+virtual ast/stdio.h
+
+ :NOPROTECT: sfprintf.c sfvprintf.c sfscanf.c sfvscanf.c
+
+ :NOOPTIMIZE: spawnveg.c
+"ibm.risc" :NOOPTIMIZE: regcomp.c
+"linux.i386-64*":NOOPTIMIZE: sfset.c
+"sol?.*" :NOOPTIMIZE: sfrd.c sfvprintf.c tmxfmt.c
+"win32*" :NOOPTIMIZE: fastfind.c mc.c
+
+/*
+ * NOTE: sun4 runtime link botches ro data so advertised sig_info is rw
+ */
+
+:READONLY: conftab.c lctab.c modedata.c /*sftable.c*/ \
+ /*sigdata.c*/ tmdata.c univdata.c
+
+:: atmain.C \
+ stdgets.c stdprintf.c stdscanf.c stdvbuf.c stdsprnt.c \
+ stdvsprnt.c stdvsnprnt.c stdvsscn.c stdopen.c \
+ astsa
+
+if "$(PWD:B)" != "cc-*"
+
+$(INCLUDEDIR) :INSTALLPROTO: $(HEADEREXP) $(HEADERSRC) $(HEADERGEN)
+
+:INSTALLDIR: conf
+
+conf :: conf.sh
+
+conflim.h conftab.h conftab.c :JOINT: conf conf.tab
+ $(*:O=1:P=A) $(IFFEFLAGS:V:N=-v) $(*:O>1) $(CC) $(CCFLAGS:VP:N!=-D_BLD_*|$\(*\)) /* 2007-07-01: $(CCFLAGS:VPX:N!=-D_BLD_*) */
+
+$(HEADERGEN) :COPY: FEATURE/$$(<:B:/$(ID)_//)
+
+ast_namval.h :COPY: namval.h
+
+lcgen : lcgen.c
+ $(CC.NATIVE|CC) -o $(<) $(*)
+
+lc.h lctab.c :JOINT: lcgen lc.tab
+ $(*:O=1:C,^[^/],./&,) $(tmp).1 $(tmp).2 < $(*:O=2) # :P=E: in 2006
+ $(PROTO) -p $(PROTOFLAGS) $(tmp).1 $(PROTOINSTALL) > $(tmp).3
+ $(RM) -f $(tmp).1
+ if $(CMP) -s $(tmp).3 $(<:O=1)
+ then $(RM) $(tmp).3
+ else $(MV) $(tmp).3 $(<:O=1)
+ fi
+ if $(CMP) -s $(tmp).2 $(<:O=2)
+ then $(RM) $(tmp).2
+ else $(MV) $(tmp).2 $(<:O=2)
+ fi
+
+$(LIBDIR)/file/magic :INSTALL: magic.tab
+
+:INSTALL: $(HEADEROPT:D=$(INCLUDEDIR):B:S)
+
+$(HEADEROPT:D=$(INCLUDEDIR):B:S) : $$(<:B:S) ast_lib.h
+ case $(CC.HOSTTYPE) in
+ win32.*)$(PROTO) -p $(PROTOFLAGS) $(*:O=1) $(PROTOINSTALL) > 1.$(tmp).x
+ if $(CMP) -s $(<) 1.$(tmp).x
+ then $(RM) -f 1.$(tmp).x
+ else $(MV) 1.$(tmp).x $(<)
+ fi
+ ;;
+ *) $(SILENT) $(GREP) -l 'define[ ][ ]*_[hl][di][rb]_$(<:B)' $(*:O>1) > /dev/null || {
+ $(PROTO) -p $(PROTOFLAGS) $(*:O=1) $(PROTOINSTALL) > 1.$(tmp).x
+ if $(CMP) -s $(<) 1.$(tmp).x
+ then $(RM) -f 1.$(tmp).x
+ else $(MV) 1.$(tmp).x $(<)
+ fi
+ }
+ ;;
+ esac
+
+/* a few headers are problematic */
+
+$(INCLUDEDIR)/prototyped.h :INSTALL: $(INCLUDEDIR)
+ echo "#include <../prototyped.h>" > 1.$(tmp).x
+ if $(CMP) -s $(<) 1.$(tmp).x
+ then $(RM) -f 1.$(tmp).x
+ else $(MV) 1.$(tmp).x $(<)
+ fi
+
+/*
+ * FEATURE/common for iffe probes, <ast_common.h> for ast source
+ * *but* <ast_common.h> may get pulled in by intercepted headers
+ * so both must be built very early
+ */
+
+$(ID)_common.h : .SCAN.IGNORE FEATURE/common
+ $(SED) '/define _def_map_ast/d' < $(*) > 1.$(tmp).x
+ if $(CMP) -s $(<) 1.$(tmp).x
+ then $(RM) -f 1.$(tmp).x
+ else $(MV) 1.$(tmp).x $(<)
+ fi
+
+FEATURE/common : .SCAN.IGNORE
+
+/*
+ * more stdio.h complications ...
+ * prepare for compilation by generating these headers first;
+ * this helps mam by catching headers that might be indirectly
+ * included on other systems
+ */
+
+.check.hdr : .IGNORE .VIRTUAL \
+ FEATURE/standards - FEATURE/lib - FEATURE/common - \
+ FEATURE/param - FEATURE/aso - \
+ ast_map.h - ast_limits.h - ast_stdio.h ast_nl_types.h - \
+ ast_wchar.h ast_wctype.h
+ : clean up obsolete headers :
+ $(RM) -rf $(HEADERSTD) ast_hdr.h ast_types.h ast_unistd.h iffeio.h \
+ $(INCLUDEDIR)/limits.h $(INCLUDEDIR)/unistd.h \
+ $(PACKAGEROOT)/src/lib/libast/std/limits.h
+
+ast.req : .check.hdr .check.lib
+
+else
+
+ast.req : .check.lib
+
+end
+
+/*
+ * some systems move -lc routines to -lm
+ * see astmath.c for details
+ */
+
+.check.lib : .AFTER astmath.exe FEATURE/aso
+ $(SED) -e '/^#define _REQ_/!d' -e 's/#define _REQ_\([a-z0-9_]*\).*/ -l\1/' $(*:N=FEATURE/*) >> $(<<)
+ if test -f astmath.exe
+ then touch $(<<)
+ else echo ' -lm' >> $(<<)
+ fi
+
+astmath.exe : .DONTCARE astmath.c
+ X=1
+ for N in 1 2 3 4 5 6 8
+ do if $(CC) -DN=$N -DIS $(CCFLAGS) -o $(*:N=*.c:B:S=.exe) $(*) 2>/dev/null
+ then : implicit math function N=$N :
+ elif $(CC) -DN=$N -DIS $(CCFLAGS) -o $(*:N=*.c:B:S=.exe) $(*) -lm 2>/dev/null
+ then : math function N=$N requires -lm :
+ X=0
+ break
+ fi
+ done
+ case $X in
+ 0) $(RM) -f $(*:N=*.c:B:S=.exe) ;;
+ *) touch $(*:N=*.c:B:S=.exe) ;;
+ esac
+ $(RM) -f $(*:N=*.c:B:S=$(CC.SUFFIX.OBJECT))
+
+/*
+ * atmain.C is the only C++ and only for a few systems
+ */
+
+atmain.o : atmain.C
+ ignore $(CC) -c $(CCFLAGS) $(*)
+ if test ! -f $(<)
+ then $(CP) $(*) $(*:B:S=.cpp)
+ ignore $(CC) -c $(CCFLAGS) $(*:B:S=.cpp)
+ if test ! -f $(<)
+ then $(CP) $(*) $(*:B:S=.c)
+ $(CC) -c $(CCFLAGS) $(*:B:S=.c)
+ fi
+ fi
+
+/* astsa is a standalone subset of ast for imbedded applications */
+
+PAXFILTER = ;*.[ch];$(PROTO) $(PROTOFLAGS) -c "" -p
+
+ast_sa.h : .DONTCARE
+
+astsa.tgz : $$("astsa/astsa.manifest":T=F:T=I:/[[:space:]][[:space:]]*/ /G:C,^,astsa/,)
+ $(PAX) $(PAXFLAGS) -wf $(<) -x $(<:/.*\.//) -s ',.*/,,' -A $(PAXFILTER:@Q) $(*)
+
+/* libmini.a is a bootstrap dll for uwin cc -D_BLD_ast that exports part of ast */
+
+MINI = mini
+
+:: $(MINI).sym
+
+if CC.HOSTTYPE == "win32*"
+
+DLL = $(ID)$(VERSION:/[^0-9]//G)
+
+$(MINI) : $(MINI)$$(CC.SUFFIX.SHARED)
+
+$(MINI)$$(CC.SUFFIX.SHARED) : $(MINI).sym $(ID)
+ $(RM) -rf $(MINI).tmp
+ mkdir $(MINI).tmp
+ {
+ echo LIBRARY $(DLL:F=%(upper)s)
+ echo
+ echo SECTIONS
+ echo .data READ WRITE
+ echo
+ echo EXPORTS
+ cat $(*:N=*.sym)
+ } > $(MINI).tmp/$(DLL)$(CC.SUFFIX.LD:O=1)
+ cd $(MINI).tmp
+ $(LD) $(CCFLAGS:N=-[gG]*) $(CC.SHARED) -o $(DLL) $(DLL)$(CC.SUFFIX.LD:O=1) $(*$(ID).so/$(DLL)$(CC.SUFFIX.DYNAMIC):C,^[^-],../&,)
+ cd ..
+ $(MV) $(MINI).tmp/$(DLL)$(CC.SUFFIX.SHARED) $(<)
+ $(RM) -rf $(MINI).tmp
+
+end
+
+:MSGKEY: misc/magic.tab
+ $(SED) \
+ -e '/^#/d' \
+ -e '/[^ ]* *[^ ]* *[^ ]* *./!d' \
+ -e 's,^[^ ]* *[^ ]* *[^ ]* *\(.[^ ]*\).*$,\1,' \
+ -e 's,[\\"],\\&,g' \
+ -e 's,.*,"&",' \
+ $(*)
diff --git a/src/lib/libast/Mamfile b/src/lib/libast/Mamfile
new file mode 100644
index 0000000..0c0290c
--- /dev/null
+++ b/src/lib/libast/Mamfile
@@ -0,0 +1,7356 @@
+info mam static 00000 1994-07-17 make (AT&T Research) 5.7 2012-02-29
+setv INSTALLROOT ../../..
+setv PACKAGEROOT ../../../../..
+setv AR ${mam_cc_AR} ${mam_cc_AR_ARFLAGS}
+setv ARFLAGS rc
+setv AS as
+setv ASFLAGS
+setv CC cc
+setv mam_cc_FLAGS ${mam_cc_DLL} -D_BLD_ast
+setv CCFLAGS ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${mam_cc_OPTIMIZE}?}
+setv CCLDFLAGS ${-strip-symbols?1?${mam_cc_LD_STRIP}??}
+setv COTEMP $$
+setv CPIO cpio
+setv CPIOFLAGS
+setv CPP "${CC} -E"
+setv F77 f77
+setv HOSTCC ${CC}
+setv IGNORE
+setv LD ld
+setv LDFLAGS
+setv LEX lex
+setv LEXFLAGS
+setv LPR lpr
+setv LPRFLAGS
+setv M4FLAGS
+setv NMAKE nmake
+setv NMAKEFLAGS
+setv PR pr
+setv PRFLAGS
+setv SHELL /bin/sh
+setv SILENT
+setv TAR tar
+setv YACC yacc
+setv YACCFLAGS -d
+make ${PACKAGEROOT}/lib/package/ast.lic
+done ${PACKAGEROOT}/lib/package/ast.lic
+make install
+make ast
+make libast.a archive
+make ast.req
+make FEATURE/standards
+meta FEATURE/standards features/%>FEATURE/% features/standards standards
+make features/standards
+done features/standards
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/standards
+done FEATURE/standards generated
+make FEATURE/lib
+meta FEATURE/lib features/%>FEATURE/% features/lib lib
+make features/lib
+done features/lib
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/lib
+done FEATURE/lib generated
+make FEATURE/common
+meta FEATURE/common features/%>FEATURE/% features/common common
+make features/common
+done features/common
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/common
+done FEATURE/common generated
+make FEATURE/param
+meta FEATURE/param features/%.sh>FEATURE/% features/param.sh param
+make features/param.sh
+done features/param.sh
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/param.sh
+make std/endian.h implicit
+make std/bytesex.h implicit
+make ast_common.h implicit
+prev FEATURE/common
+exec - sed '/define _def_map_ast/d' < FEATURE/common > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ast_common.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ast_common.h
+exec - fi
+make ast_map.h implicit
+make FEATURE/map
+meta FEATURE/map features/%.c>FEATURE/% features/map.c map
+make features/map.c
+make FEATURE/api implicit
+meta FEATURE/api features/%>FEATURE/% features/api api
+make features/api
+done features/api
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/api
+done FEATURE/api generated
+make FEATURE/eaccess implicit
+meta FEATURE/eaccess features/%>FEATURE/% features/eaccess eaccess
+make features/eaccess
+done features/eaccess
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/eaccess
+done FEATURE/eaccess generated
+make FEATURE/vmalloc implicit
+meta FEATURE/vmalloc features/%>FEATURE/% features/vmalloc vmalloc
+make features/vmalloc
+done features/vmalloc
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/vmalloc
+make FEATURE/mmap implicit
+meta FEATURE/mmap features/%>FEATURE/% features/mmap mmap
+make features/mmap
+done features/mmap
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/mmap
+done FEATURE/mmap dontcare generated
+done FEATURE/vmalloc generated
+make FEATURE/options implicit
+meta FEATURE/options features/%>FEATURE/% features/options options
+make features/options
+done features/options
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/options
+done FEATURE/options generated
+prev FEATURE/mmap implicit
+prev FEATURE/lib implicit
+done features/map.c
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. ${LDFLAGS} ' run features/map.c
+done FEATURE/map generated
+exec - cmp 2>/dev/null -s FEATURE/map ast_map.h || { rm -f ast_map.h; silent test -d . || mkdir .; ${STDCP} FEATURE/map ast_map.h; }
+done ast_map.h dontcare generated
+done ast_common.h dontcare generated
+done std/bytesex.h dontcare
+done std/endian.h dontcare
+done FEATURE/param generated
+make FEATURE/aso
+meta FEATURE/aso features/%>FEATURE/% features/aso aso
+make features/aso
+done features/aso
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/aso
+done FEATURE/aso generated
+prev ast_map.h
+make ast_limits.h
+make FEATURE/limits
+meta FEATURE/limits features/%.c>FEATURE/% features/limits.c limits
+make features/limits.c
+make conflim.h implicit
+make conf
+make comp/conf.sh
+done comp/conf.sh
+meta conf %.sh>% comp/conf.sh conf
+prev comp/conf.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : conf contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n comp/conf.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 29 in
+exec - 0) ${STDCP} comp/conf.sh conf
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < comp/conf.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - comp/conf.sh <<'!'
+exec - HOSTTYPE="${mam_cc_HOSTTYPE}"
+exec - !
+exec - } > conf
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - comp/conf.sh > conf <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec - HOSTTYPE="${mam_cc_HOSTTYPE}"
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w conf -a -x conf || chmod u+w,+x conf
+done conf generated
+make comp/conf.tab
+done comp/conf.tab
+exec - ${INSTALLROOT}/src/lib/libast/conf -v comp/conf.tab ${CC} ${mam_cc_FLAGS} ${CCFLAGS}
+make joint.conflim.h joint
+prev conflim.h
+make conftab.h
+done conftab.h generated
+make conftab.c
+done conftab.c generated
+done joint.conflim.h generated virtual
+done conflim.h generated
+prev FEATURE/param implicit
+make comp/getopt.h implicit
+make include/ast_getopt.h implicit
+done include/ast_getopt.h dontcare
+done comp/getopt.h dontcare
+prev FEATURE/common implicit
+prev FEATURE/lib implicit
+prev FEATURE/standards implicit
+done features/limits.c
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd ${LDFLAGS} ' run features/limits.c
+done FEATURE/limits generated
+exec - cmp 2>/dev/null -s FEATURE/limits ast_limits.h || { rm -f ast_limits.h; silent test -d . || mkdir .; ${STDCP} FEATURE/limits ast_limits.h; }
+done ast_limits.h generated
+make ast_stdio.h
+make FEATURE/stdio
+meta FEATURE/stdio features/%>FEATURE/% features/stdio stdio
+make features/stdio
+done features/stdio
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/stdio
+make include/sfio_s.h implicit
+done include/sfio_s.h dontcare
+make include/ast_std.h implicit
+make include/regex.h implicit
+make ast_wchar.h implicit
+make FEATURE/wchar
+meta FEATURE/wchar features/%>FEATURE/% features/wchar wchar
+make features/wchar
+prev ast_common.h implicit
+done features/wchar
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/wchar
+make std/wctype.h implicit
+make ast_wctype.h implicit
+make FEATURE/wctype
+meta FEATURE/wctype features/%>FEATURE/% features/wctype wctype
+make features/wctype
+done features/wctype
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/wctype
+prev std/endian.h implicit
+done FEATURE/wctype generated
+exec - cmp 2>/dev/null -s FEATURE/wctype ast_wctype.h || { rm -f ast_wctype.h; silent test -d . || mkdir .; ${STDCP} FEATURE/wctype ast_wctype.h; }
+done ast_wctype.h dontcare generated
+done std/wctype.h dontcare
+make std/stdio.h implicit
+prev ast_stdio.h implicit
+done std/stdio.h dontcare
+prev std/stdio.h implicit
+prev ast_common.h implicit
+done FEATURE/wchar generated
+exec - cmp 2>/dev/null -s FEATURE/wchar ast_wchar.h || { rm -f ast_wchar.h; silent test -d . || mkdir .; ${STDCP} FEATURE/wchar ast_wchar.h; }
+prev std/stdio.h implicit
+prev ast_common.h implicit
+done ast_wchar.h dontcare generated
+prev ast_common.h implicit
+done include/regex.h dontcare
+prev comp/getopt.h implicit
+prev ast_map.h implicit
+make ast_botch.h implicit
+make FEATURE/botch
+meta FEATURE/botch features/%.c>FEATURE/% features/botch.c botch
+make features/botch.c
+make FEATURE/sys implicit
+meta FEATURE/sys features/%>FEATURE/% features/sys sys
+make features/sys
+done features/sys
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/sys
+prev std/endian.h implicit
+prev std/endian.h implicit
+done FEATURE/sys generated
+prev FEATURE/lib implicit
+done features/botch.c
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd ${LDFLAGS} ' run features/botch.c
+done FEATURE/botch generated
+exec - cmp 2>/dev/null -s FEATURE/botch ast_botch.h || { rm -f ast_botch.h; silent test -d . || mkdir .; ${STDCP} FEATURE/botch ast_botch.h; }
+done ast_botch.h dontcare generated
+prev ast_limits.h implicit
+make ast_fcntl.h implicit
+make FEATURE/fcntl
+meta FEATURE/fcntl features/%.c>FEATURE/% features/fcntl.c fcntl
+make features/fcntl.c
+make FEATURE/tty implicit
+meta FEATURE/tty features/%>FEATURE/% features/tty tty
+make features/tty
+done features/tty
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/tty
+done FEATURE/tty generated
+make FEATURE/fs implicit
+meta FEATURE/fs features/%>FEATURE/% features/fs fs
+make features/fs
+done features/fs
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/fs
+done FEATURE/fs generated
+prev FEATURE/lib implicit
+done features/fcntl.c
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd ${LDFLAGS} ' run features/fcntl.c
+make ast_fs.h implicit
+prev FEATURE/fs
+exec - cmp 2>/dev/null -s FEATURE/fs ast_fs.h || { rm -f ast_fs.h; silent test -d . || mkdir .; ${STDCP} FEATURE/fs ast_fs.h; }
+done ast_fs.h dontcare generated
+done FEATURE/fcntl generated
+exec - cmp 2>/dev/null -s FEATURE/fcntl ast_fcntl.h || { rm -f ast_fcntl.h; silent test -d . || mkdir .; ${STDCP} FEATURE/fcntl ast_fcntl.h; }
+prev ast_fs.h implicit
+done ast_fcntl.h dontcare generated
+prev include/ast_getopt.h implicit
+make ast_sys.h implicit
+prev FEATURE/sys
+exec - cmp 2>/dev/null -s FEATURE/sys ast_sys.h || { rm -f ast_sys.h; silent test -d . || mkdir .; ${STDCP} FEATURE/sys ast_sys.h; }
+done ast_sys.h dontcare generated
+make ast_lib.h implicit
+prev FEATURE/lib
+exec - cmp 2>/dev/null -s FEATURE/lib ast_lib.h || { rm -f ast_lib.h; silent test -d . || mkdir .; ${STDCP} FEATURE/lib ast_lib.h; }
+done ast_lib.h dontcare generated
+prev ast_common.h implicit
+done include/ast_std.h dontcare
+done FEATURE/stdio generated
+exec - cmp 2>/dev/null -s FEATURE/stdio ast_stdio.h || { rm -f ast_stdio.h; silent test -d . || mkdir .; ${STDCP} FEATURE/stdio ast_stdio.h; }
+prev include/sfio_s.h implicit
+prev include/ast_std.h implicit
+done ast_stdio.h dontcare generated
+make ast_nl_types.h
+make FEATURE/nl_types
+meta FEATURE/nl_types features/%>FEATURE/% features/nl_types nl_types
+make features/nl_types
+done features/nl_types
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/nl_types
+done FEATURE/nl_types generated
+exec - cmp 2>/dev/null -s FEATURE/nl_types ast_nl_types.h || { rm -f ast_nl_types.h; silent test -d . || mkdir .; ${STDCP} FEATURE/nl_types ast_nl_types.h; }
+done ast_nl_types.h generated
+prev ast_wchar.h
+prev ast_wctype.h
+exec - : clean up obsolete headers :
+exec - rm -rf dirent.h iconv.h nl_types.h stdio.h wchar.h wctype.h ast_hdr.h ast_types.h ast_unistd.h iffeio.h \
+exec - ${INSTALLROOT}/include/ast/limits.h ${INSTALLROOT}/include/ast/unistd.h \
+exec - ${PACKAGEROOT}/src/lib/libast/std/limits.h
+exec - set -
+exec - echo 'int main(){return 0;}' > 1.${COTEMP}.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -c 1.${COTEMP}.c &&
+exec - x=`${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l'*' 2>&1 | sed -e 's/[][()+@?]/#/g' || :` &&
+exec - {
+exec - case "" in
+exec - *?) echo " " ;;
+exec - esac
+exec - for i in ast iconv w
+exec - do case $i in
+exec - "ast"|ast)
+exec - ;;
+exec - *) if test -f ${INSTALLROOT}/lib/lib/$i
+exec - then y=`cat ${INSTALLROOT}/lib/lib/$i`
+exec - case $y in
+exec - *-?*) echo "" $y ;;
+exec - esac
+exec - continue
+exec - elif test ! -f ${INSTALLROOT}/lib/lib$i.a
+exec - then case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) continue ;;
+exec - esac
+exec - ;;
+exec - esac
+exec - fi
+exec - ;;
+exec - esac
+exec - echo " -l$i"
+exec - done
+exec - } > ast.req
+exec - rm -f 1.${COTEMP}.*
+make astmath.exe
+make port/astmath.c
+prev std/endian.h implicit
+prev std/endian.h implicit
+done port/astmath.c
+exec - X=1
+exec - for N in 1 2 3 4 5 6 8
+exec - do if ${CC} -DN=$N -DIS ${mam_cc_FLAGS} ${CCFLAGS} -I. -Istd -o astmath.exe port/astmath.c 2>/dev/null
+exec - then : implicit math function N=$N :
+exec - elif ${CC} -DN=$N -DIS ${mam_cc_FLAGS} ${CCFLAGS} -I. -Istd -o astmath.exe port/astmath.c -lm 2>/dev/null
+exec - then : math function N=$N requires -lm :
+exec - X=0
+exec - break
+exec - fi
+exec - done
+exec - case $X in
+exec - 0) rm -f astmath.exe ;;
+exec - *) touch astmath.exe ;;
+exec - esac
+exec - rm -f astmath
+done astmath.exe dontcare generated
+prev FEATURE/aso
+exec - sed -e '/^#define _REQ_/!d' -e 's/#define _REQ_\([a-z0-9_]*\).*/ -l\1/' FEATURE/aso >> ast.req
+exec - if test -f astmath.exe
+exec - then touch ast.req
+exec - else echo ' -lm' >> ast.req
+exec - fi
+done ast.req generated
+make state.o
+make misc/state.c
+make include/ast.h implicit
+make ast_api.h implicit
+prev FEATURE/api
+exec - cmp 2>/dev/null -s FEATURE/api ast_api.h || { rm -f ast_api.h; silent test -d . || mkdir .; ${STDCP} FEATURE/api ast_api.h; }
+done ast_api.h dontcare generated
+make include/vmalloc.h implicit
+prev ast_common.h implicit
+prev include/ast_std.h implicit
+done include/vmalloc.h dontcare
+make include/sfio.h implicit
+prev include/sfio_s.h implicit
+prev ast_common.h implicit
+prev include/ast_std.h implicit
+done include/sfio.h dontcare
+prev include/ast_std.h implicit
+done include/ast.h
+done misc/state.c
+meta state.o %.c>%.o misc/state.c state
+prev misc/state.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/state.c
+done state.o generated
+make transition.o
+make comp/transition.c
+prev include/ast.h implicit
+done comp/transition.c
+meta transition.o %.c>%.o comp/transition.c transition
+prev comp/transition.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/transition.c
+done transition.o generated
+make opendir.o
+make dir/opendir.c
+make dir/dirlib.h implicit
+make dir/dirstd.h implicit
+done dir/dirstd.h dontcare
+make direntry.h implicit
+done direntry.h dontcare virtual
+make ast_param.h implicit
+prev FEATURE/param
+exec - cmp 2>/dev/null -s FEATURE/param ast_param.h || { rm -f ast_param.h; silent test -d . || mkdir .; ${STDCP} FEATURE/param ast_param.h; }
+done ast_param.h dontcare generated
+make std/dirent.h implicit
+make ast_dirent.h implicit
+make FEATURE/dirent
+meta FEATURE/dirent features/%>FEATURE/% features/dirent dirent
+make features/dirent
+done features/dirent
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/dirent
+prev include/ast_std.h implicit
+done FEATURE/dirent generated
+exec - cmp 2>/dev/null -s FEATURE/dirent ast_dirent.h || { rm -f ast_dirent.h; silent test -d . || mkdir .; ${STDCP} FEATURE/dirent ast_dirent.h; }
+prev include/ast_std.h implicit
+done ast_dirent.h dontcare generated
+done std/dirent.h dontcare
+make ndir.h implicit
+done ndir.h dontcare virtual
+prev std/dirent.h implicit
+make include/ls.h implicit
+make ast_mode.h implicit
+make FEATURE/mode
+meta FEATURE/mode features/%.c>FEATURE/% features/mode.c mode
+make features/mode.c
+make include/modecanon.h implicit
+done include/modecanon.h
+prev FEATURE/param implicit
+done features/mode.c
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -Istd ${LDFLAGS} ' run features/mode.c
+done FEATURE/mode generated
+exec - cmp 2>/dev/null -s FEATURE/mode ast_mode.h || { rm -f ast_mode.h; silent test -d . || mkdir .; ${STDCP} FEATURE/mode ast_mode.h; }
+done ast_mode.h dontcare generated
+prev ast_fs.h implicit
+prev include/ast_std.h implicit
+done include/ls.h dontcare
+prev include/ast.h implicit
+done dir/dirlib.h
+done dir/opendir.c
+meta opendir.o %.c>%.o dir/opendir.c opendir
+prev dir/opendir.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idir -Iinclude -Istd -D_PACKAGE_ast -c dir/opendir.c
+done opendir.o generated
+make readdir.o
+make dir/readdir.c
+prev dir/dirlib.h implicit
+done dir/readdir.c
+meta readdir.o %.c>%.o dir/readdir.c readdir
+prev dir/readdir.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idir -Iinclude -Istd -D_PACKAGE_ast -c dir/readdir.c
+done readdir.o generated
+make rewinddir.o
+make dir/rewinddir.c
+prev dir/dirlib.h implicit
+done dir/rewinddir.c
+meta rewinddir.o %.c>%.o dir/rewinddir.c rewinddir
+prev dir/rewinddir.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idir -Iinclude -Istd -D_PACKAGE_ast -c dir/rewinddir.c
+done rewinddir.o generated
+make seekdir.o
+make dir/seekdir.c
+prev dir/dirlib.h implicit
+done dir/seekdir.c
+meta seekdir.o %.c>%.o dir/seekdir.c seekdir
+prev dir/seekdir.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idir -Iinclude -Istd -D_PACKAGE_ast -c dir/seekdir.c
+done seekdir.o generated
+make telldir.o
+make dir/telldir.c
+prev dir/dirlib.h implicit
+done dir/telldir.c
+meta telldir.o %.c>%.o dir/telldir.c telldir
+prev dir/telldir.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idir -Iinclude -Istd -D_PACKAGE_ast -c dir/telldir.c
+done telldir.o generated
+make getcwd.o
+make misc/getcwd.c
+make include/fs3d.h implicit
+prev ast_fs.h implicit
+done include/fs3d.h dontcare
+make include/ast_dir.h implicit
+prev std/dirent.h implicit
+prev dir/dirlib.h implicit
+prev ast_lib.h implicit
+done include/ast_dir.h dontcare
+make include/error.h implicit
+make include/option.h implicit
+prev include/ast.h implicit
+done include/option.h dontcare
+prev include/ast.h implicit
+done include/error.h dontcare
+make FEATURE/syscall implicit
+meta FEATURE/syscall features/%>FEATURE/% features/syscall syscall
+make features/syscall
+done features/syscall
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/syscall
+done FEATURE/syscall dontcare generated
+prev include/ast.h implicit
+done misc/getcwd.c
+meta getcwd.o %.c>%.o misc/getcwd.c getcwd
+prev misc/getcwd.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idir -Iinclude -Istd -D_PACKAGE_ast -c misc/getcwd.c
+done getcwd.o generated
+make fastfind.o
+make misc/fastfind.c
+make misc/findlib.h implicit
+make include/find.h implicit
+done include/find.h dontcare
+prev include/vmalloc.h implicit
+prev include/regex.h implicit
+prev include/ls.h implicit
+prev include/error.h implicit
+prev std/endian.h implicit
+make include/cdt.h implicit
+prev ast_common.h implicit
+prev include/ast_std.h implicit
+done include/cdt.h dontcare
+prev include/ast.h implicit
+done misc/findlib.h
+done misc/fastfind.c
+meta fastfind.o %.c>%.o misc/fastfind.c fastfind
+prev misc/fastfind.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/fastfind.c
+done fastfind.o generated
+make hashalloc.o
+make hash/hashalloc.c
+make hash/hashlib.h implicit
+make include/hash.h implicit
+make include/hashpart.h implicit
+done include/hashpart.h dontcare
+done include/hash.h dontcare
+prev include/ast.h implicit
+done hash/hashlib.h
+done hash/hashalloc.c
+meta hashalloc.o %.c>%.o hash/hashalloc.c hashalloc
+prev hash/hashalloc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/hashalloc.c
+done hashalloc.o generated
+make hashdump.o
+make hash/hashdump.c
+prev hash/hashlib.h implicit
+done hash/hashdump.c
+meta hashdump.o %.c>%.o hash/hashdump.c hashdump
+prev hash/hashdump.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/hashdump.c
+done hashdump.o generated
+make hashfree.o
+make hash/hashfree.c
+prev hash/hashlib.h implicit
+done hash/hashfree.c
+meta hashfree.o %.c>%.o hash/hashfree.c hashfree
+prev hash/hashfree.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/hashfree.c
+done hashfree.o generated
+make hashlast.o
+make hash/hashlast.c
+prev hash/hashlib.h implicit
+done hash/hashlast.c
+meta hashlast.o %.c>%.o hash/hashlast.c hashlast
+prev hash/hashlast.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/hashlast.c
+done hashlast.o generated
+make hashlook.o
+make hash/hashlook.c
+prev hash/hashlib.h implicit
+done hash/hashlook.c
+meta hashlook.o %.c>%.o hash/hashlook.c hashlook
+prev hash/hashlook.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/hashlook.c
+done hashlook.o generated
+make hashscan.o
+make hash/hashscan.c
+prev hash/hashlib.h implicit
+done hash/hashscan.c
+meta hashscan.o %.c>%.o hash/hashscan.c hashscan
+prev hash/hashscan.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/hashscan.c
+done hashscan.o generated
+make hashsize.o
+make hash/hashsize.c
+prev hash/hashlib.h implicit
+done hash/hashsize.c
+meta hashsize.o %.c>%.o hash/hashsize.c hashsize
+prev hash/hashsize.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/hashsize.c
+done hashsize.o generated
+make hashview.o
+make hash/hashview.c
+prev hash/hashlib.h implicit
+done hash/hashview.c
+meta hashview.o %.c>%.o hash/hashview.c hashview
+prev hash/hashview.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/hashview.c
+done hashview.o generated
+make hashwalk.o
+make hash/hashwalk.c
+prev hash/hashlib.h implicit
+done hash/hashwalk.c
+meta hashwalk.o %.c>%.o hash/hashwalk.c hashwalk
+prev hash/hashwalk.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/hashwalk.c
+done hashwalk.o generated
+make memhash.o
+make hash/memhash.c
+prev hash/hashlib.h implicit
+done hash/memhash.c
+meta memhash.o %.c>%.o hash/memhash.c memhash
+prev hash/memhash.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/memhash.c
+done memhash.o generated
+make memsum.o
+make hash/memsum.c
+prev hash/hashlib.h implicit
+done hash/memsum.c
+meta memsum.o %.c>%.o hash/memsum.c memsum
+prev hash/memsum.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/memsum.c
+done memsum.o generated
+make strhash.o
+make hash/strhash.c
+prev hash/hashlib.h implicit
+done hash/strhash.c
+meta strhash.o %.c>%.o hash/strhash.c strhash
+prev hash/strhash.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/strhash.c
+done strhash.o generated
+make strkey.o
+make hash/strkey.c
+make include/hashkey.h implicit
+done include/hashkey.h
+prev include/ast.h implicit
+done hash/strkey.c
+meta strkey.o %.c>%.o hash/strkey.c strkey
+prev hash/strkey.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c hash/strkey.c
+done strkey.o generated
+make strsum.o
+make hash/strsum.c
+prev hash/hashlib.h implicit
+done hash/strsum.c
+meta strsum.o %.c>%.o hash/strsum.c strsum
+prev hash/strsum.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ihash -Iinclude -Istd -D_PACKAGE_ast -c hash/strsum.c
+done strsum.o generated
+make stracmp.o
+make string/stracmp.c
+make include/ccode.h implicit
+make ast_ccode.h implicit
+make FEATURE/ccode
+meta FEATURE/ccode features/%>FEATURE/% features/ccode ccode
+make features/ccode
+done features/ccode
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/ccode
+done FEATURE/ccode generated
+exec - cmp 2>/dev/null -s FEATURE/ccode ast_ccode.h || { rm -f ast_ccode.h; silent test -d . || mkdir .; ${STDCP} FEATURE/ccode ast_ccode.h; }
+done ast_ccode.h dontcare generated
+prev ast_common.h implicit
+done include/ccode.h
+prev include/ast.h implicit
+done string/stracmp.c
+meta stracmp.o %.c>%.o string/stracmp.c stracmp
+prev string/stracmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/stracmp.c
+done stracmp.o generated
+make strnacmp.o
+make string/strnacmp.c
+prev include/ccode.h implicit
+prev include/ast.h implicit
+done string/strnacmp.c
+meta strnacmp.o %.c>%.o string/strnacmp.c strnacmp
+prev string/strnacmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strnacmp.c
+done strnacmp.o generated
+make ccmap.o
+make string/ccmap.c
+prev include/ccode.h implicit
+prev include/ast.h implicit
+done string/ccmap.c
+meta ccmap.o %.c>%.o string/ccmap.c ccmap
+prev string/ccmap.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/ccmap.c
+done ccmap.o generated
+make ccmapid.o
+make string/ccmapid.c
+prev include/ccode.h implicit
+prev include/ast.h implicit
+done string/ccmapid.c
+meta ccmapid.o %.c>%.o string/ccmapid.c ccmapid
+prev string/ccmapid.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/ccmapid.c
+done ccmapid.o generated
+make ccnative.o
+make string/ccnative.c
+prev include/ccode.h implicit
+prev include/ast.h implicit
+done string/ccnative.c
+meta ccnative.o %.c>%.o string/ccnative.c ccnative
+prev string/ccnative.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/ccnative.c
+done ccnative.o generated
+make chresc.o
+make string/chresc.c
+prev include/regex.h implicit
+prev include/ccode.h implicit
+prev include/ast.h implicit
+done string/chresc.c
+meta chresc.o %.c>%.o string/chresc.c chresc
+prev string/chresc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/chresc.c
+done chresc.o generated
+make chrtoi.o
+make string/chrtoi.c
+prev include/ast.h implicit
+done string/chrtoi.c
+meta chrtoi.o %.c>%.o string/chrtoi.c chrtoi
+prev string/chrtoi.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/chrtoi.c
+done chrtoi.o generated
+make streval.o
+make string/streval.c
+prev include/ast.h implicit
+done string/streval.c
+meta streval.o %.c>%.o string/streval.c streval
+prev string/streval.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/streval.c
+done streval.o generated
+make strexpr.o
+make string/strexpr.c
+prev include/ast.h implicit
+done string/strexpr.c
+meta strexpr.o %.c>%.o string/strexpr.c strexpr
+prev string/strexpr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strexpr.c
+done strexpr.o generated
+make strmatch.o
+make string/strmatch.c
+prev include/regex.h implicit
+prev include/ast.h implicit
+done string/strmatch.c
+meta strmatch.o %.c>%.o string/strmatch.c strmatch
+prev string/strmatch.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strmatch.c
+done strmatch.o generated
+make strcopy.o
+make string/strcopy.c
+prev include/ast.h implicit
+done string/strcopy.c
+meta strcopy.o %.c>%.o string/strcopy.c strcopy
+prev string/strcopy.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strcopy.c
+done strcopy.o generated
+make modei.o
+make string/modei.c
+make string/modelib.h implicit
+make include/modex.h implicit
+prev include/modecanon.h implicit
+prev ast_fs.h implicit
+done include/modex.h dontcare
+prev include/ls.h implicit
+prev include/ast.h implicit
+done string/modelib.h
+done string/modei.c
+meta modei.o %.c>%.o string/modei.c modei
+prev string/modei.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Istring -Iinclude -Istd -D_PACKAGE_ast -c string/modei.c
+done modei.o generated
+make modex.o
+make string/modex.c
+prev string/modelib.h implicit
+done string/modex.c
+meta modex.o %.c>%.o string/modex.c modex
+prev string/modex.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Istring -Iinclude -Istd -D_PACKAGE_ast -c string/modex.c
+done modex.o generated
+make strmode.o
+make string/strmode.c
+prev string/modelib.h implicit
+done string/strmode.c
+meta strmode.o %.c>%.o string/strmode.c strmode
+prev string/strmode.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Istring -Iinclude -Istd -D_PACKAGE_ast -c string/strmode.c
+done strmode.o generated
+make strlcat.o
+make string/strlcat.c
+prev ast_map.h implicit
+prev include/ast.h implicit
+done string/strlcat.c
+meta strlcat.o %.c>%.o string/strlcat.c strlcat
+prev string/strlcat.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strlcat.c
+done strlcat.o generated
+make strlcpy.o
+make string/strlcpy.c
+prev ast_map.h implicit
+prev include/ast.h implicit
+done string/strlcpy.c
+meta strlcpy.o %.c>%.o string/strlcpy.c strlcpy
+prev string/strlcpy.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strlcpy.c
+done strlcpy.o generated
+make strlook.o
+make string/strlook.c
+prev include/ast.h implicit
+done string/strlook.c
+meta strlook.o %.c>%.o string/strlook.c strlook
+prev string/strlook.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strlook.c
+done strlook.o generated
+make strncopy.o
+make string/strncopy.c
+prev include/ast.h implicit
+done string/strncopy.c
+meta strncopy.o %.c>%.o string/strncopy.c strncopy
+prev string/strncopy.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strncopy.c
+done strncopy.o generated
+make strsearch.o
+make string/strsearch.c
+prev include/ast.h implicit
+done string/strsearch.c
+meta strsearch.o %.c>%.o string/strsearch.c strsearch
+prev string/strsearch.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strsearch.c
+done strsearch.o generated
+make strpsearch.o
+make string/strpsearch.c
+prev include/ccode.h implicit
+prev include/ast.h implicit
+done string/strpsearch.c
+meta strpsearch.o %.c>%.o string/strpsearch.c strpsearch
+prev string/strpsearch.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strpsearch.c
+done strpsearch.o generated
+make stresc.o
+make string/stresc.c
+prev include/ast.h implicit
+done string/stresc.c
+meta stresc.o %.c>%.o string/stresc.c stresc
+prev string/stresc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/stresc.c
+done stresc.o generated
+make stropt.o
+make string/stropt.c
+prev include/ast.h implicit
+done string/stropt.c
+meta stropt.o %.c>%.o string/stropt.c stropt
+prev string/stropt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/stropt.c
+done stropt.o generated
+make strtape.o
+make string/strtape.c
+prev include/ast.h implicit
+done string/strtape.c
+meta strtape.o %.c>%.o string/strtape.c strtape
+prev string/strtape.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strtape.c
+done strtape.o generated
+make strpcmp.o
+make string/strpcmp.c
+prev include/ast.h implicit
+done string/strpcmp.c
+meta strpcmp.o %.c>%.o string/strpcmp.c strpcmp
+prev string/strpcmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strpcmp.c
+done strpcmp.o generated
+make strnpcmp.o
+make string/strnpcmp.c
+prev include/ast.h implicit
+done string/strnpcmp.c
+meta strnpcmp.o %.c>%.o string/strnpcmp.c strnpcmp
+prev string/strnpcmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strnpcmp.c
+done strnpcmp.o generated
+make strvcmp.o
+make string/strvcmp.c
+prev include/ast.h implicit
+done string/strvcmp.c
+meta strvcmp.o %.c>%.o string/strvcmp.c strvcmp
+prev string/strvcmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strvcmp.c
+done strvcmp.o generated
+make strnvcmp.o
+make string/strnvcmp.c
+prev include/ast.h implicit
+done string/strnvcmp.c
+meta strnvcmp.o %.c>%.o string/strnvcmp.c strnvcmp
+prev string/strnvcmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strnvcmp.c
+done strnvcmp.o generated
+make tok.o
+make string/tok.c
+make include/tok.h implicit
+prev include/ast.h implicit
+done include/tok.h
+prev include/ast.h implicit
+done string/tok.c
+meta tok.o %.c>%.o string/tok.c tok
+prev string/tok.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/tok.c
+done tok.o generated
+make tokline.o
+make string/tokline.c
+prev include/tok.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+done string/tokline.c
+meta tokline.o %.c>%.o string/tokline.c tokline
+prev string/tokline.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/tokline.c
+done tokline.o generated
+make tokscan.o
+make string/tokscan.c
+prev include/tok.h implicit
+prev include/ast.h implicit
+done string/tokscan.c
+meta tokscan.o %.c>%.o string/tokscan.c tokscan
+prev string/tokscan.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/tokscan.c
+done tokscan.o generated
+make pathaccess.o
+make path/pathaccess.c
+prev ast_api.h implicit
+prev include/ast.h implicit
+done path/pathaccess.c
+meta pathaccess.o %.c>%.o path/pathaccess.c pathaccess
+prev path/pathaccess.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathaccess.c
+done pathaccess.o generated
+make pathcat.o
+make path/pathcat.c
+prev ast_api.h implicit
+prev include/ast.h implicit
+done path/pathcat.c
+meta pathcat.o %.c>%.o path/pathcat.c pathcat
+prev path/pathcat.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathcat.c
+done pathcat.o generated
+make pathcanon.o
+make path/pathcanon.c
+prev ast_api.h implicit
+prev include/error.h implicit
+prev include/fs3d.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done path/pathcanon.c
+meta pathcanon.o %.c>%.o path/pathcanon.c pathcanon
+prev path/pathcanon.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathcanon.c
+done pathcanon.o generated
+make pathcheck.o
+make path/pathcheck.c
+make include/times.h implicit
+make ast_time.h implicit
+make FEATURE/time
+meta FEATURE/time features/%>FEATURE/% features/time time
+make features/time
+done features/time
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/time
+done FEATURE/time generated
+exec - cmp 2>/dev/null -s FEATURE/time ast_time.h || { rm -f ast_time.h; silent test -d . || mkdir .; ${STDCP} FEATURE/time ast_time.h; }
+done ast_time.h dontcare generated
+prev include/ast.h implicit
+done include/times.h
+prev include/error.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done path/pathcheck.c
+meta pathcheck.o %.c>%.o path/pathcheck.c pathcheck
+prev path/pathcheck.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathcheck.c
+done pathcheck.o generated
+make pathpath.o
+make path/pathpath.c
+prev ast_api.h implicit
+prev include/ast.h implicit
+done path/pathpath.c
+meta pathpath.o %.c>%.o path/pathpath.c pathpath
+prev path/pathpath.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathpath.c
+done pathpath.o generated
+make pathexists.o
+make path/pathexists.c
+prev include/error.h implicit
+prev include/ls.h implicit
+make port/lclib.h implicit
+make lc.h implicit
+make lcgen
+make port/lcgen.c
+prev std/stdio.h implicit
+done port/lcgen.c
+exec - ${CC} -o lcgen port/lcgen.c
+done lcgen generated
+make port/lc.tab
+done port/lc.tab
+exec - ./lcgen ${COTEMP}.1 ${COTEMP}.2 < port/lc.tab
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ${COTEMP}.1 > ${COTEMP}.3
+exec - rm -f ${COTEMP}.1
+exec - if cmp 2>/dev/null -s ${COTEMP}.3 lc.h
+exec - then rm ${COTEMP}.3
+exec - else mv ${COTEMP}.3 lc.h
+exec - fi
+exec - if cmp 2>/dev/null -s ${COTEMP}.2 lctab.c
+exec - then rm ${COTEMP}.2
+exec - else mv ${COTEMP}.2 lctab.c
+exec - fi
+prev include/ast.h implicit
+make ${INSTALLROOT}/include/prototyped.h implicit
+done ${INSTALLROOT}/include/prototyped.h dontcare
+make joint.lc.h joint
+prev lc.h
+make lctab.c
+done lctab.c generated
+done joint.lc.h generated virtual
+done lc.h dontcare generated
+prev include/error.h implicit
+prev include/ast.h implicit
+done port/lclib.h
+done path/pathexists.c
+meta pathexists.o %.c>%.o path/pathexists.c pathexists
+prev path/pathexists.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c path/pathexists.c
+done pathexists.o generated
+make pathfind.o
+make path/pathfind.c
+prev include/ls.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+done path/pathfind.c
+meta pathfind.o %.c>%.o path/pathfind.c pathfind
+prev path/pathfind.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathfind.c
+done pathfind.o generated
+make pathkey.o
+make path/pathkey.c
+prev ast_api.h implicit
+prev include/ls.h implicit
+make preroot.h implicit
+make FEATURE/preroot
+meta FEATURE/preroot features/%.sh>FEATURE/% features/preroot.sh preroot
+make features/preroot.sh
+done features/preroot.sh
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/preroot.sh
+done FEATURE/preroot generated
+exec - cmp 2>/dev/null -s FEATURE/preroot preroot.h || { rm -f preroot.h; silent test -d . || mkdir .; ${STDCP} FEATURE/preroot preroot.h; }
+done preroot.h generated
+prev include/fs3d.h implicit
+prev include/ast.h implicit
+done path/pathkey.c
+meta pathkey.o %.c>%.o path/pathkey.c pathkey
+prev path/pathkey.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathkey.c
+done pathkey.o generated
+make pathprobe.o
+make path/pathprobe.c
+prev ast_api.h implicit
+make include/proc.h implicit
+prev include/ast.h implicit
+done include/proc.h
+prev include/ls.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+done path/pathprobe.c
+meta pathprobe.o %.c>%.o path/pathprobe.c pathprobe
+prev path/pathprobe.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -DHOSTTYPE=\""${mam_cc_HOSTTYPE}"\" -D_PACKAGE_ast -c path/pathprobe.c
+done pathprobe.o generated
+make pathrepl.o
+make path/pathrepl.c
+prev ast_api.h implicit
+prev include/ast.h implicit
+done path/pathrepl.c
+meta pathrepl.o %.c>%.o path/pathrepl.c pathrepl
+prev path/pathrepl.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathrepl.c
+done pathrepl.o generated
+make pathnative.o
+make path/pathnative.c
+prev include/ast.h implicit
+done path/pathnative.c
+meta pathnative.o %.c>%.o path/pathnative.c pathnative
+prev path/pathnative.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathnative.c
+done pathnative.o generated
+make pathposix.o
+make path/pathposix.c
+make uwin.h implicit
+done uwin.h dontcare virtual
+prev include/ast.h implicit
+done path/pathposix.c
+meta pathposix.o %.c>%.o path/pathposix.c pathposix
+prev path/pathposix.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathposix.c
+done pathposix.o generated
+make pathtemp.o
+make path/pathtemp.c
+make include/tm.h implicit
+prev include/times.h implicit
+prev include/ast.h implicit
+done include/tm.h
+make tv.h implicit
+make FEATURE/tv
+meta FEATURE/tv features/%>FEATURE/% features/tv tv
+make features/tv
+done features/tv
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/tv
+prev include/ast.h implicit
+done FEATURE/tv generated
+exec - cmp 2>/dev/null -s FEATURE/tv tv.h || { rm -f tv.h; silent test -d . || mkdir .; ${STDCP} FEATURE/tv tv.h; }
+prev include/ast.h implicit
+done tv.h generated
+prev include/ls.h implicit
+prev include/ast.h implicit
+done path/pathtemp.c
+meta pathtemp.o %.c>%.o path/pathtemp.c pathtemp
+prev path/pathtemp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathtemp.c
+done pathtemp.o generated
+make pathtmp.o
+make path/pathtmp.c
+prev std/stdio.h implicit
+prev include/ast.h implicit
+done path/pathtmp.c
+meta pathtmp.o %.c>%.o path/pathtmp.c pathtmp
+prev path/pathtmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathtmp.c
+done pathtmp.o generated
+make pathstat.o
+make path/pathstat.c
+prev include/error.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done path/pathstat.c
+meta pathstat.o %.c>%.o path/pathstat.c pathstat
+prev path/pathstat.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathstat.c
+done pathstat.o generated
+make pathgetlink.o
+make path/pathgetlink.c
+make misc/univlib.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done misc/univlib.h
+done path/pathgetlink.c
+meta pathgetlink.o %.c>%.o path/pathgetlink.c pathgetlink
+prev path/pathgetlink.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c path/pathgetlink.c
+done pathgetlink.o generated
+make pathsetlink.o
+make path/pathsetlink.c
+prev misc/univlib.h implicit
+done path/pathsetlink.c
+meta pathsetlink.o %.c>%.o path/pathsetlink.c pathsetlink
+prev path/pathsetlink.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c path/pathsetlink.c
+done pathsetlink.o generated
+make pathbin.o
+make path/pathbin.c
+prev include/ast.h implicit
+done path/pathbin.c
+meta pathbin.o %.c>%.o path/pathbin.c pathbin
+prev path/pathbin.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathbin.c
+done pathbin.o generated
+make pathshell.o
+make path/pathshell.c
+prev include/ast.h implicit
+done path/pathshell.c
+meta pathshell.o %.c>%.o path/pathshell.c pathshell
+prev path/pathshell.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathshell.c
+done pathshell.o generated
+make pathcd.o
+make path/pathcd.c
+make include/stk.h implicit
+prev include/sfio.h implicit
+done include/stk.h
+prev include/error.h implicit
+prev include/ast.h implicit
+done path/pathcd.c
+meta pathcd.o %.c>%.o path/pathcd.c pathcd
+prev path/pathcd.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathcd.c
+done pathcd.o generated
+make pathprog.o
+make path/pathprog.c
+make FEATURE/prog implicit
+meta FEATURE/prog features/%>FEATURE/% features/prog prog
+make features/prog
+done features/prog
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/prog
+done FEATURE/prog generated
+make include/ast_windows.h implicit
+make windows.h implicit
+done windows.h dontcare virtual
+done include/ast_windows.h dontcare
+prev include/ast.h implicit
+done path/pathprog.c
+meta pathprog.o %.c>%.o path/pathprog.c pathprog
+prev path/pathprog.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c path/pathprog.c
+done pathprog.o generated
+make fs3d.o
+make misc/fs3d.c
+prev include/fs3d.h implicit
+prev include/ast.h implicit
+done misc/fs3d.c
+meta fs3d.o %.c>%.o misc/fs3d.c fs3d
+prev misc/fs3d.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/fs3d.c
+done fs3d.o generated
+make ftwalk.o
+make misc/ftwalk.c
+make include/ftwalk.h implicit
+make include/fts.h implicit
+prev ast_mode.h implicit
+prev ast_fs.h implicit
+prev include/ast_std.h implicit
+done include/fts.h dontcare
+done include/ftwalk.h
+prev include/ast.h implicit
+done misc/ftwalk.c
+meta ftwalk.o %.c>%.o misc/ftwalk.c ftwalk
+prev misc/ftwalk.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/ftwalk.c
+done ftwalk.o generated
+make ftwflags.o
+make misc/ftwflags.c
+prev include/ftwalk.h implicit
+prev include/ast.h implicit
+done misc/ftwflags.c
+meta ftwflags.o %.c>%.o misc/ftwflags.c ftwflags
+prev misc/ftwflags.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/ftwflags.c
+done ftwflags.o generated
+make fts.o
+make misc/fts.c
+prev include/fts.h implicit
+prev include/ls.h implicit
+prev include/fs3d.h implicit
+prev include/error.h implicit
+prev include/ast_dir.h implicit
+prev include/ast.h implicit
+done misc/fts.c
+meta fts.o %.c>%.o misc/fts.c fts
+prev misc/fts.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idir -Iinclude -Istd -D__OBSOLETE__=20110101 -D_PACKAGE_ast -c misc/fts.c
+done fts.o generated
+make astintercept.o
+make misc/astintercept.c
+make misc/intercepts.h implicit
+make include/shcmd.h implicit
+done include/shcmd.h dontcare
+prev include/ast.h implicit
+done misc/intercepts.h
+done misc/astintercept.c
+meta astintercept.o %.c>%.o misc/astintercept.c astintercept
+prev misc/astintercept.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/astintercept.c
+done astintercept.o generated
+make conformance.o
+make misc/conformance.c
+prev include/ast.h implicit
+done misc/conformance.c
+meta conformance.o %.c>%.o misc/conformance.c conformance
+prev misc/conformance.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/conformance.c
+done conformance.o generated
+make getenv.o
+make misc/getenv.c
+prev windows.h implicit
+prev misc/intercepts.h implicit
+done misc/getenv.c
+meta getenv.o %.c>%.o misc/getenv.c getenv
+prev misc/getenv.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/getenv.c
+done getenv.o generated
+make setenviron.o
+make misc/setenviron.c
+prev include/fs3d.h implicit
+prev misc/intercepts.h implicit
+done misc/setenviron.c
+meta setenviron.o %.c>%.o misc/setenviron.c setenviron
+prev misc/setenviron.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/setenviron.c
+done setenviron.o generated
+make optget.o
+make misc/optget.c
+prev include/ccode.h implicit
+make include/debug.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+done include/debug.h
+make misc/optlib.h implicit
+prev include/error.h implicit
+prev include/cdt.h implicit
+prev include/ast.h implicit
+done misc/optlib.h
+done misc/optget.c
+meta optget.o %.c>%.o misc/optget.c optget
+prev misc/optget.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/optget.c
+done optget.o generated
+make optjoin.o
+make misc/optjoin.c
+prev misc/optlib.h implicit
+done misc/optjoin.c
+meta optjoin.o %.c>%.o misc/optjoin.c optjoin
+prev misc/optjoin.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/optjoin.c
+done optjoin.o generated
+make optesc.o
+make misc/optesc.c
+prev misc/optlib.h implicit
+done misc/optesc.c
+meta optesc.o %.c>%.o misc/optesc.c optesc
+prev misc/optesc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/optesc.c
+done optesc.o generated
+make optctx.o
+make misc/optctx.c
+prev misc/optlib.h implicit
+done misc/optctx.c
+meta optctx.o %.c>%.o misc/optctx.c optctx
+prev misc/optctx.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/optctx.c
+done optctx.o generated
+make strsort.o
+make string/strsort.c
+prev include/ast.h implicit
+done string/strsort.c
+meta strsort.o %.c>%.o string/strsort.c strsort
+prev string/strsort.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strsort.c
+done strsort.o generated
+make struniq.o
+make string/struniq.c
+prev include/ast.h implicit
+done string/struniq.c
+meta struniq.o %.c>%.o string/struniq.c struniq
+prev string/struniq.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/struniq.c
+done struniq.o generated
+make magic.o
+make misc/magic.c
+make include/magic.h implicit
+prev include/ls.h implicit
+prev include/sfio.h implicit
+done include/magic.h
+make include/swap.h implicit
+prev ast_common.h implicit
+done include/swap.h
+prev include/regex.h implicit
+prev include/error.h implicit
+prev include/modex.h implicit
+make include/dt.h implicit
+prev include/vmalloc.h implicit
+prev include/cdt.h implicit
+done include/dt.h
+prev include/ccode.h implicit
+prev include/ast.h implicit
+done misc/magic.c
+meta magic.o %.c>%.o misc/magic.c magic
+prev misc/magic.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/magic.c
+done magic.o generated
+make mime.o
+make misc/mime.c
+make misc/mimelib.h implicit
+make include/mime.h implicit
+prev include/ls.h implicit
+prev include/sfio.h implicit
+done include/mime.h dontcare
+prev include/tok.h implicit
+prev include/magic.h implicit
+prev include/cdt.h implicit
+prev include/ast.h implicit
+done misc/mimelib.h
+done misc/mime.c
+meta mime.o %.c>%.o misc/mime.c mime
+prev misc/mime.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/mime.c
+done mime.o generated
+make mimetype.o
+make misc/mimetype.c
+prev misc/mimelib.h implicit
+done misc/mimetype.c
+meta mimetype.o %.c>%.o misc/mimetype.c mimetype
+prev misc/mimetype.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/mimetype.c
+done mimetype.o generated
+make signal.o
+make misc/signal.c
+prev ast_map.h implicit
+make sig.h implicit
+make FEATURE/sig
+meta FEATURE/sig features/%.sh>FEATURE/% features/sig.sh sig
+make features/sig.sh
+done features/sig.sh
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/sig.sh
+done FEATURE/sig generated
+exec - cmp 2>/dev/null -s FEATURE/sig sig.h || { rm -f sig.h; silent test -d . || mkdir .; ${STDCP} FEATURE/sig sig.h; }
+done sig.h generated
+prev include/ast.h implicit
+done misc/signal.c
+meta signal.o %.c>%.o misc/signal.c signal
+prev misc/signal.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/signal.c
+done signal.o generated
+make sigflag.o
+make comp/sigflag.c
+prev sig.h implicit
+prev include/ast.h implicit
+done comp/sigflag.c
+meta sigflag.o %.c>%.o comp/sigflag.c sigflag
+prev comp/sigflag.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/sigflag.c
+done sigflag.o generated
+make systrace.o
+make misc/systrace.c
+prev include/debug.h implicit
+prev include/proc.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+done misc/systrace.c
+meta systrace.o %.c>%.o misc/systrace.c systrace
+prev misc/systrace.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/systrace.c
+done systrace.o generated
+make error.o
+make misc/error.c
+prev include/regex.h implicit
+prev include/times.h implicit
+prev include/stk.h implicit
+prev sig.h implicit
+make include/namval.h implicit
+done include/namval.h
+prev include/ccode.h implicit
+prev port/lclib.h implicit
+done misc/error.c
+meta error.o %.c>%.o misc/error.c error
+prev misc/error.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Iinclude -Istd -I${INSTALLROOT}/include -DERROR_CATALOG=\""libast"\" -D_PACKAGE_ast -c misc/error.c
+done error.o generated
+make errorf.o
+make misc/errorf.c
+prev include/error.h implicit
+done misc/errorf.c
+meta errorf.o %.c>%.o misc/errorf.c errorf
+prev misc/errorf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/errorf.c
+done errorf.o generated
+make errormsg.o
+make misc/errormsg.c
+prev include/error.h implicit
+done misc/errormsg.c
+meta errormsg.o %.c>%.o misc/errormsg.c errormsg
+prev misc/errormsg.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/errormsg.c
+done errormsg.o generated
+make errorx.o
+make misc/errorx.c
+prev port/lclib.h implicit
+done misc/errorx.c
+meta errorx.o %.c>%.o misc/errorx.c errorx
+prev misc/errorx.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c misc/errorx.c
+done errorx.o generated
+make localeconv.o
+make comp/localeconv.c
+prev port/lclib.h implicit
+done comp/localeconv.c
+meta localeconv.o %.c>%.o comp/localeconv.c localeconv
+prev comp/localeconv.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c comp/localeconv.c
+done localeconv.o generated
+make setlocale.o
+make comp/setlocale.c
+prev include/ast_windows.h implicit
+prev std/wctype.h implicit
+prev include/namval.h implicit
+make include/mc.h implicit
+prev include/ast.h implicit
+done include/mc.h
+prev ast_wchar.h implicit
+prev port/lclib.h implicit
+make ast_standards.h implicit
+prev FEATURE/standards
+exec - cmp 2>/dev/null -s FEATURE/standards ast_standards.h || { rm -f ast_standards.h; silent test -d . || mkdir .; ${STDCP} FEATURE/standards ast_standards.h; }
+done ast_standards.h generated
+done comp/setlocale.c
+meta setlocale.o %.c>%.o comp/setlocale.c setlocale
+prev comp/setlocale.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c comp/setlocale.c
+done setlocale.o generated
+make translate.o
+make misc/translate.c
+make std/nl_types.h implicit
+prev ast_nl_types.h implicit
+done std/nl_types.h
+prev include/mc.h implicit
+prev include/error.h implicit
+prev include/cdt.h implicit
+prev port/lclib.h implicit
+done misc/translate.c
+meta translate.o %.c>%.o misc/translate.c translate
+prev misc/translate.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c misc/translate.c
+done translate.o generated
+make catopen.o
+make comp/catopen.c
+make std/iconv.h implicit
+make ast_iconv.h implicit
+make FEATURE/iconv
+meta FEATURE/iconv features/%>FEATURE/% features/iconv iconv
+make features/iconv
+done features/iconv
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/iconv
+prev include/ccode.h implicit
+prev ast_common.h implicit
+done FEATURE/iconv generated
+exec - cmp 2>/dev/null -s FEATURE/iconv ast_iconv.h || { rm -f ast_iconv.h; silent test -d . || mkdir .; ${STDCP} FEATURE/iconv ast_iconv.h; }
+prev include/ccode.h implicit
+prev ast_common.h implicit
+done ast_iconv.h generated
+done std/iconv.h
+prev std/nl_types.h implicit
+prev include/mc.h implicit
+prev include/ast.h implicit
+done comp/catopen.c
+meta catopen.o %.c>%.o comp/catopen.c catopen
+prev comp/catopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/catopen.c
+done catopen.o generated
+make iconv.o
+make comp/iconv.c
+prev include/ast_windows.h implicit
+prev port/lclib.h implicit
+prev std/iconv.h implicit
+prev include/ccode.h implicit
+prev std/dirent.h implicit
+prev include/ast.h implicit
+done comp/iconv.c
+meta iconv.o %.c>%.o comp/iconv.c iconv
+prev comp/iconv.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c comp/iconv.c
+done iconv.o generated
+make lc.o
+make port/lc.c
+make FEATURE/locale implicit
+meta FEATURE/locale features/%>FEATURE/% features/locale locale
+make features/locale
+done features/locale
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/locale
+done FEATURE/locale generated
+make port/lclang.h implicit
+prev include/ast_windows.h implicit
+done port/lclang.h
+prev port/lclib.h implicit
+done port/lc.c
+meta lc.o %.c>%.o port/lc.c lc
+prev port/lc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c port/lc.c
+done lc.o generated
+make lctab.o
+make lctab.c
+prev port/lclang.h implicit
+prev port/lclib.h implicit
+done lctab.c
+meta lctab.o %.c>%.o lctab.c lctab
+prev lctab.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c lctab.c
+done lctab.o generated
+make mc.o
+make port/mc.c
+prev std/nl_types.h implicit
+prev include/mc.h implicit
+prev include/error.h implicit
+prev include/vmalloc.h implicit
+prev std/iconv.h implicit
+prev port/lclib.h implicit
+make sfio/sfhdr.h implicit
+prev port/lclib.h implicit
+make vfork.h implicit
+done vfork.h dontcare virtual
+make std/wchar.h implicit
+prev ast_wchar.h implicit
+done std/wchar.h dontcare
+make FEATURE/float implicit
+meta FEATURE/float features/%>FEATURE/% features/float float
+make features/float
+make FEATURE/isoc99 implicit
+meta FEATURE/isoc99 features/%>FEATURE/% features/isoc99 isoc99
+make features/isoc99
+done features/isoc99
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/isoc99
+done FEATURE/isoc99 generated
+done features/float
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/float
+prev ast_common.h implicit
+done FEATURE/float dontcare generated
+make mman.h implicit
+done mman.h dontcare virtual
+make filio.h implicit
+done filio.h dontcare virtual
+make stat.h implicit
+done stat.h dontcare virtual
+prev include/ls.h implicit
+make ast_tty.h implicit
+prev FEATURE/tty
+exec - cmp 2>/dev/null -s FEATURE/tty ast_tty.h || { rm -f ast_tty.h; silent test -d . || mkdir .; ${STDCP} FEATURE/tty ast_tty.h; }
+done ast_tty.h dontcare generated
+prev ast_time.h implicit
+prev include/ast.h implicit
+make sfio/vthread.h implicit
+prev windows.h implicit
+prev std/endian.h implicit
+prev ast_common.h implicit
+done sfio/vthread.h dontcare
+make include/sfio_t.h implicit
+prev include/sfio.h implicit
+done include/sfio_t.h dontcare
+prev FEATURE/common implicit
+prev FEATURE/mmap implicit
+make FEATURE/sfio implicit
+meta FEATURE/sfio features/%>FEATURE/% features/sfio sfio
+make features/sfio
+done features/sfio
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/sfio
+done FEATURE/sfio dontcare generated
+done sfio/sfhdr.h
+done port/mc.c
+meta mc.o %.c>%.o port/mc.c mc
+prev port/mc.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${DEBUG+-DDEBUG=${DEBUG}} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c port/mc.c
+done mc.o generated
+make base64.o
+make string/base64.c
+prev include/ast.h implicit
+done string/base64.c
+meta base64.o %.c>%.o string/base64.c base64
+prev string/base64.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/base64.c
+done base64.o generated
+make recfmt.o
+make misc/recfmt.c
+make include/recfmt.h implicit
+prev include/ast.h implicit
+done include/recfmt.h
+done misc/recfmt.c
+meta recfmt.o %.c>%.o misc/recfmt.c recfmt
+prev misc/recfmt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/recfmt.c
+done recfmt.o generated
+make recstr.o
+make misc/recstr.c
+prev include/recfmt.h implicit
+done misc/recstr.c
+meta recstr.o %.c>%.o misc/recstr.c recstr
+prev misc/recstr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/recstr.c
+done recstr.o generated
+make reclen.o
+make misc/reclen.c
+prev include/recfmt.h implicit
+done misc/reclen.c
+meta reclen.o %.c>%.o misc/reclen.c reclen
+prev misc/reclen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/reclen.c
+done reclen.o generated
+make fmtrec.o
+make misc/fmtrec.c
+prev include/recfmt.h implicit
+done misc/fmtrec.c
+meta fmtrec.o %.c>%.o misc/fmtrec.c fmtrec
+prev misc/fmtrec.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/fmtrec.c
+done fmtrec.o generated
+make fmtbase.o
+make string/fmtbase.c
+prev include/ast.h implicit
+done string/fmtbase.c
+meta fmtbase.o %.c>%.o string/fmtbase.c fmtbase
+prev string/fmtbase.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D__OBSOLETE__=20110101 -D_PACKAGE_ast -c string/fmtbase.c
+done fmtbase.o generated
+make fmtbuf.o
+make string/fmtbuf.c
+prev include/ast.h implicit
+done string/fmtbuf.c
+meta fmtbuf.o %.c>%.o string/fmtbuf.c fmtbuf
+prev string/fmtbuf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtbuf.c
+done fmtbuf.o generated
+make fmtclock.o
+make string/fmtclock.c
+prev include/tm.h implicit
+prev include/ast.h implicit
+done string/fmtclock.c
+meta fmtclock.o %.c>%.o string/fmtclock.c fmtclock
+prev string/fmtclock.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtclock.c
+done fmtclock.o generated
+make fmtdev.o
+make string/fmtdev.c
+prev include/ls.h implicit
+prev include/ast.h implicit
+done string/fmtdev.c
+meta fmtdev.o %.c>%.o string/fmtdev.c fmtdev
+prev string/fmtdev.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtdev.c
+done fmtdev.o generated
+make fmtelapsed.o
+make string/fmtelapsed.c
+prev include/ast.h implicit
+done string/fmtelapsed.c
+meta fmtelapsed.o %.c>%.o string/fmtelapsed.c fmtelapsed
+prev string/fmtelapsed.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtelapsed.c
+done fmtelapsed.o generated
+make fmterror.o
+make string/fmterror.c
+prev include/ast.h implicit
+done string/fmterror.c
+meta fmterror.o %.c>%.o string/fmterror.c fmterror
+prev string/fmterror.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmterror.c
+done fmterror.o generated
+make fmtesc.o
+make string/fmtesc.c
+prev std/wctype.h implicit
+prev std/wchar.h implicit
+prev include/ccode.h implicit
+prev include/ast.h implicit
+done string/fmtesc.c
+meta fmtesc.o %.c>%.o string/fmtesc.c fmtesc
+prev string/fmtesc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtesc.c
+done fmtesc.o generated
+make fmtfmt.o
+make string/fmtfmt.c
+prev include/ast.h implicit
+done string/fmtfmt.c
+meta fmtfmt.o %.c>%.o string/fmtfmt.c fmtfmt
+prev string/fmtfmt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtfmt.c
+done fmtfmt.o generated
+make fmtfs.o
+make string/fmtfs.c
+prev include/cdt.h implicit
+prev FEATURE/fs implicit
+make include/mnt.h implicit
+done include/mnt.h
+prev include/ls.h implicit
+prev include/ast.h implicit
+done string/fmtfs.c
+meta fmtfs.o %.c>%.o string/fmtfs.c fmtfs
+prev string/fmtfs.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtfs.c
+done fmtfs.o generated
+make fmtident.o
+make string/fmtident.c
+prev include/ast.h implicit
+done string/fmtident.c
+meta fmtident.o %.c>%.o string/fmtident.c fmtident
+prev string/fmtident.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtident.c
+done fmtident.o generated
+make fmtint.o
+make string/fmtint.c
+prev include/ast.h implicit
+done string/fmtint.c
+meta fmtint.o %.c>%.o string/fmtint.c fmtint
+prev string/fmtint.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtint.c
+done fmtint.o generated
+make fmtip4.o
+make string/fmtip4.c
+prev include/ast.h implicit
+done string/fmtip4.c
+meta fmtip4.o %.c>%.o string/fmtip4.c fmtip4
+prev string/fmtip4.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtip4.c
+done fmtip4.o generated
+make fmtip6.o
+make string/fmtip6.c
+make include/ip6.h implicit
+done include/ip6.h
+prev include/ast.h implicit
+done string/fmtip6.c
+meta fmtip6.o %.c>%.o string/fmtip6.c fmtip6
+prev string/fmtip6.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtip6.c
+done fmtip6.o generated
+make fmtls.o
+make string/fmtls.c
+prev include/tm.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done string/fmtls.c
+meta fmtls.o %.c>%.o string/fmtls.c fmtls
+prev string/fmtls.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtls.c
+done fmtls.o generated
+make fmtmatch.o
+make string/fmtmatch.c
+prev include/ast.h implicit
+done string/fmtmatch.c
+meta fmtmatch.o %.c>%.o string/fmtmatch.c fmtmatch
+prev string/fmtmatch.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtmatch.c
+done fmtmatch.o generated
+make fmtmode.o
+make string/fmtmode.c
+prev string/modelib.h implicit
+done string/fmtmode.c
+meta fmtmode.o %.c>%.o string/fmtmode.c fmtmode
+prev string/fmtmode.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Istring -Iinclude -Istd -D_PACKAGE_ast -c string/fmtmode.c
+done fmtmode.o generated
+make fmtnum.o
+make string/fmtnum.c
+prev include/ast.h implicit
+done string/fmtnum.c
+meta fmtnum.o %.c>%.o string/fmtnum.c fmtnum
+prev string/fmtnum.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtnum.c
+done fmtnum.o generated
+make fmtperm.o
+make string/fmtperm.c
+prev include/ls.h implicit
+prev include/ast.h implicit
+done string/fmtperm.c
+meta fmtperm.o %.c>%.o string/fmtperm.c fmtperm
+prev string/fmtperm.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtperm.c
+done fmtperm.o generated
+make fmtre.o
+make string/fmtre.c
+prev include/ast.h implicit
+done string/fmtre.c
+meta fmtre.o %.c>%.o string/fmtre.c fmtre
+prev string/fmtre.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtre.c
+done fmtre.o generated
+make fmttime.o
+make string/fmttime.c
+prev include/tm.h implicit
+done string/fmttime.c
+meta fmttime.o %.c>%.o string/fmttime.c fmttime
+prev string/fmttime.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmttime.c
+done fmttime.o generated
+make fmtuid.o
+make string/fmtuid.c
+prev std/stdio.h implicit
+prev include/cdt.h implicit
+prev include/ast.h implicit
+done string/fmtuid.c
+meta fmtuid.o %.c>%.o string/fmtuid.c fmtuid
+prev string/fmtuid.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtuid.c
+done fmtuid.o generated
+make fmtgid.o
+make string/fmtgid.c
+prev std/stdio.h implicit
+prev include/cdt.h implicit
+prev include/ast.h implicit
+done string/fmtgid.c
+meta fmtgid.o %.c>%.o string/fmtgid.c fmtgid
+prev string/fmtgid.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtgid.c
+done fmtgid.o generated
+make fmtsignal.o
+make string/fmtsignal.c
+prev sig.h implicit
+prev include/ast.h implicit
+done string/fmtsignal.c
+meta fmtsignal.o %.c>%.o string/fmtsignal.c fmtsignal
+prev string/fmtsignal.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtsignal.c
+done fmtsignal.o generated
+make fmtscale.o
+make string/fmtscale.c
+prev port/lclib.h implicit
+prev include/ast.h implicit
+done string/fmtscale.c
+meta fmtscale.o %.c>%.o string/fmtscale.c fmtscale
+prev string/fmtscale.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c string/fmtscale.c
+done fmtscale.o generated
+make fmttmx.o
+make string/fmttmx.c
+prev tv.h implicit
+make tmx.h implicit
+make FEATURE/tmx
+meta FEATURE/tmx features/%>FEATURE/% features/tmx tmx
+make features/tmx
+prev FEATURE/common implicit
+done features/tmx
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/tmx
+prev tv.h implicit
+prev include/tm.h implicit
+done FEATURE/tmx generated
+exec - cmp 2>/dev/null -s FEATURE/tmx tmx.h || { rm -f tmx.h; silent test -d . || mkdir .; ${STDCP} FEATURE/tmx tmx.h; }
+prev tv.h implicit
+prev include/tm.h implicit
+done tmx.h generated
+done string/fmttmx.c
+meta fmttmx.o %.c>%.o string/fmttmx.c fmttmx
+prev string/fmttmx.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmttmx.c
+done fmttmx.o generated
+make fmttv.o
+make string/fmttv.c
+prev include/tm.h implicit
+prev tv.h implicit
+done string/fmttv.c
+meta fmttv.o %.c>%.o string/fmttv.c fmttv
+prev string/fmttv.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmttv.c
+done fmttv.o generated
+make fmtversion.o
+make string/fmtversion.c
+prev include/ast.h implicit
+done string/fmtversion.c
+meta fmtversion.o %.c>%.o string/fmtversion.c fmtversion
+prev string/fmtversion.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/fmtversion.c
+done fmtversion.o generated
+make strelapsed.o
+make string/strelapsed.c
+prev include/ast.h implicit
+done string/strelapsed.c
+meta strelapsed.o %.c>%.o string/strelapsed.c strelapsed
+prev string/strelapsed.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strelapsed.c
+done strelapsed.o generated
+make strperm.o
+make string/strperm.c
+prev include/modex.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done string/strperm.c
+meta strperm.o %.c>%.o string/strperm.c strperm
+prev string/strperm.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strperm.c
+done strperm.o generated
+make struid.o
+make string/struid.c
+prev include/cdt.h implicit
+prev include/ast.h implicit
+done string/struid.c
+meta struid.o %.c>%.o string/struid.c struid
+prev string/struid.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/struid.c
+done struid.o generated
+make strgid.o
+make string/strgid.c
+prev include/cdt.h implicit
+prev include/ast.h implicit
+done string/strgid.c
+meta strgid.o %.c>%.o string/strgid.c strgid
+prev string/strgid.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strgid.c
+done strgid.o generated
+make strtoip4.o
+make string/strtoip4.c
+prev include/ast.h implicit
+done string/strtoip4.c
+meta strtoip4.o %.c>%.o string/strtoip4.c strtoip4
+prev string/strtoip4.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strtoip4.c
+done strtoip4.o generated
+make strtoip6.o
+make string/strtoip6.c
+prev include/ip6.h implicit
+prev include/ast.h implicit
+done string/strtoip6.c
+meta strtoip6.o %.c>%.o string/strtoip6.c strtoip6
+prev string/strtoip6.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strtoip6.c
+done strtoip6.o generated
+make stack.o
+make misc/stack.c
+make include/stack.h implicit
+done include/stack.h
+prev include/ast.h implicit
+done misc/stack.c
+meta stack.o %.c>%.o misc/stack.c stack
+prev misc/stack.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/stack.c
+done stack.o generated
+make stk.o
+make misc/stk.c
+prev include/stk.h implicit
+make align.h implicit
+make FEATURE/align
+meta FEATURE/align features/%.c>FEATURE/% features/align.c align
+make features/align.c
+prev FEATURE/common implicit
+done features/align.c
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. ${LDFLAGS} ' run features/align.c
+done FEATURE/align generated
+exec - cmp 2>/dev/null -s FEATURE/align align.h || { rm -f align.h; silent test -d . || mkdir .; ${STDCP} FEATURE/align align.h; }
+done align.h generated
+prev include/ast.h implicit
+prev include/sfio_t.h implicit
+done misc/stk.c
+meta stk.o %.c>%.o misc/stk.c stk
+prev misc/stk.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/stk.c
+done stk.o generated
+make swapget.o
+make string/swapget.c
+prev include/swap.h implicit
+prev include/ast.h implicit
+done string/swapget.c
+meta swapget.o %.c>%.o string/swapget.c swapget
+prev string/swapget.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/swapget.c
+done swapget.o generated
+make swapmem.o
+make string/swapmem.c
+prev include/swap.h implicit
+prev include/ast.h implicit
+done string/swapmem.c
+meta swapmem.o %.c>%.o string/swapmem.c swapmem
+prev string/swapmem.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/swapmem.c
+done swapmem.o generated
+make swapop.o
+make string/swapop.c
+prev include/swap.h implicit
+prev include/ast.h implicit
+done string/swapop.c
+meta swapop.o %.c>%.o string/swapop.c swapop
+prev string/swapop.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/swapop.c
+done swapop.o generated
+make swapput.o
+make string/swapput.c
+prev include/swap.h implicit
+prev include/ast.h implicit
+done string/swapput.c
+meta swapput.o %.c>%.o string/swapput.c swapput
+prev string/swapput.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/swapput.c
+done swapput.o generated
+make sigdata.o
+make misc/sigdata.c
+make FEATURE/signal implicit
+meta FEATURE/signal features/%.c>FEATURE/% features/signal.c signal
+make features/signal.c
+make FEATURE/siglist implicit
+meta FEATURE/siglist features/%>FEATURE/% features/siglist siglist
+make features/siglist
+done features/siglist
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/siglist
+done FEATURE/siglist generated
+prev FEATURE/standards implicit
+done features/signal.c
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. ${LDFLAGS} ' run features/signal.c
+done FEATURE/signal generated
+prev sig.h implicit
+prev include/ast.h implicit
+done misc/sigdata.c
+meta sigdata.o %.c>%.o misc/sigdata.c sigdata
+prev misc/sigdata.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/sigdata.c
+done sigdata.o generated
+make sigcrit.o
+make misc/sigcrit.c
+prev sig.h implicit
+prev include/ast.h implicit
+done misc/sigcrit.c
+meta sigcrit.o %.c>%.o misc/sigcrit.c sigcrit
+prev misc/sigcrit.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/sigcrit.c
+done sigcrit.o generated
+make sigunblock.o
+make comp/sigunblock.c
+prev sig.h implicit
+prev include/ast.h implicit
+done comp/sigunblock.c
+meta sigunblock.o %.c>%.o comp/sigunblock.c sigunblock
+prev comp/sigunblock.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/sigunblock.c
+done sigunblock.o generated
+make procopen.o
+make misc/procopen.c
+prev include/namval.h implicit
+prev ast_tty.h implicit
+prev include/ls.h implicit
+make misc/proclib.h implicit
+prev include/proc.h implicit
+make include/wait.h implicit
+make ast_wait.h implicit
+make FEATURE/wait
+meta FEATURE/wait features/%>FEATURE/% features/wait wait
+make features/wait
+done features/wait
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/wait
+done FEATURE/wait generated
+exec - cmp 2>/dev/null -s FEATURE/wait ast_wait.h || { rm -f ast_wait.h; silent test -d . || mkdir .; ${STDCP} FEATURE/wait ast_wait.h; }
+done ast_wait.h dontcare generated
+prev include/ast.h implicit
+done include/wait.h dontcare
+prev sig.h implicit
+prev include/ast.h implicit
+done misc/proclib.h
+done misc/procopen.c
+meta procopen.o %.c>%.o misc/procopen.c procopen
+prev misc/procopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/procopen.c
+done procopen.o generated
+make procclose.o
+make misc/procclose.c
+prev misc/proclib.h implicit
+done misc/procclose.c
+meta procclose.o %.c>%.o misc/procclose.c procclose
+prev misc/procclose.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/procclose.c
+done procclose.o generated
+make procrun.o
+make misc/procrun.c
+prev misc/proclib.h implicit
+done misc/procrun.c
+meta procrun.o %.c>%.o misc/procrun.c procrun
+prev misc/procrun.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D__OBSOLETE__=20110101 -D_PACKAGE_ast -c misc/procrun.c
+done procrun.o generated
+make procfree.o
+make misc/procfree.c
+prev misc/proclib.h implicit
+done misc/procfree.c
+meta procfree.o %.c>%.o misc/procfree.c procfree
+prev misc/procfree.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/procfree.c
+done procfree.o generated
+make tmdate.o
+make tm/tmdate.c
+prev tmx.h implicit
+done tm/tmdate.c
+meta tmdate.o %.c>%.o tm/tmdate.c tmdate
+prev tm/tmdate.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmdate.c
+done tmdate.o generated
+make tmequiv.o
+make tm/tmequiv.c
+prev include/tm.h implicit
+done tm/tmequiv.c
+meta tmequiv.o %.c>%.o tm/tmequiv.c tmequiv
+prev tm/tmequiv.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmequiv.c
+done tmequiv.o generated
+make tmfix.o
+make tm/tmfix.c
+prev tmx.h implicit
+prev include/ast.h implicit
+done tm/tmfix.c
+meta tmfix.o %.c>%.o tm/tmfix.c tmfix
+prev tm/tmfix.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmfix.c
+done tmfix.o generated
+make tmfmt.o
+make tm/tmfmt.c
+prev tmx.h implicit
+done tm/tmfmt.c
+meta tmfmt.o %.c>%.o tm/tmfmt.c tmfmt
+prev tm/tmfmt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmfmt.c
+done tmfmt.o generated
+make tmform.o
+make tm/tmform.c
+prev include/tm.h implicit
+prev include/ast.h implicit
+done tm/tmform.c
+meta tmform.o %.c>%.o tm/tmform.c tmform
+prev tm/tmform.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmform.c
+done tmform.o generated
+make tmgoff.o
+make tm/tmgoff.c
+prev include/tm.h implicit
+prev include/ast.h implicit
+done tm/tmgoff.c
+meta tmgoff.o %.c>%.o tm/tmgoff.c tmgoff
+prev tm/tmgoff.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmgoff.c
+done tmgoff.o generated
+make tminit.o
+make tm/tminit.c
+make FEATURE/tmlib implicit
+meta FEATURE/tmlib features/%>FEATURE/% features/tmlib tmlib
+make features/tmlib
+done features/tmlib
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/tmlib
+done FEATURE/tmlib generated
+prev include/namval.h implicit
+prev include/tm.h implicit
+done tm/tminit.c
+meta tminit.o %.c>%.o tm/tminit.c tminit
+prev tm/tminit.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tminit.c
+done tminit.o generated
+make tmleap.o
+make tm/tmleap.c
+prev tmx.h implicit
+done tm/tmleap.c
+meta tmleap.o %.c>%.o tm/tmleap.c tmleap
+prev tm/tmleap.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmleap.c
+done tmleap.o generated
+make tmlex.o
+make tm/tmlex.c
+prev include/tm.h implicit
+prev include/ast.h implicit
+done tm/tmlex.c
+meta tmlex.o %.c>%.o tm/tmlex.c tmlex
+prev tm/tmlex.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmlex.c
+done tmlex.o generated
+make tmlocale.o
+make tm/tmlocale.c
+prev std/nl_types.h implicit
+prev std/nl_types.h implicit
+prev include/ast_windows.h implicit
+prev port/lclib.h implicit
+prev ast_nl_types.h implicit
+prev include/tm.h implicit
+prev include/mc.h implicit
+prev std/iconv.h implicit
+prev include/cdt.h implicit
+prev include/ast.h implicit
+done tm/tmlocale.c
+meta tmlocale.o %.c>%.o tm/tmlocale.c tmlocale
+prev tm/tmlocale.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c tm/tmlocale.c
+done tmlocale.o generated
+make tmmake.o
+make tm/tmmake.c
+prev tmx.h implicit
+done tm/tmmake.c
+meta tmmake.o %.c>%.o tm/tmmake.c tmmake
+prev tm/tmmake.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmmake.c
+done tmmake.o generated
+make tmpoff.o
+make tm/tmpoff.c
+prev include/tm.h implicit
+prev include/ast.h implicit
+done tm/tmpoff.c
+meta tmpoff.o %.c>%.o tm/tmpoff.c tmpoff
+prev tm/tmpoff.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmpoff.c
+done tmpoff.o generated
+make tmscan.o
+make tm/tmscan.c
+prev tmx.h implicit
+done tm/tmscan.c
+meta tmscan.o %.c>%.o tm/tmscan.c tmscan
+prev tm/tmscan.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmscan.c
+done tmscan.o generated
+make tmsleep.o
+make tm/tmsleep.c
+prev tv.h implicit
+prev include/tm.h implicit
+prev include/ast.h implicit
+done tm/tmsleep.c
+meta tmsleep.o %.c>%.o tm/tmsleep.c tmsleep
+prev tm/tmsleep.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmsleep.c
+done tmsleep.o generated
+make tmtime.o
+make tm/tmtime.c
+prev tmx.h implicit
+done tm/tmtime.c
+meta tmtime.o %.c>%.o tm/tmtime.c tmtime
+prev tm/tmtime.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmtime.c
+done tmtime.o generated
+make tmtype.o
+make tm/tmtype.c
+prev include/tm.h implicit
+prev include/ast.h implicit
+done tm/tmtype.c
+meta tmtype.o %.c>%.o tm/tmtype.c tmtype
+prev tm/tmtype.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmtype.c
+done tmtype.o generated
+make tmweek.o
+make tm/tmweek.c
+prev tmx.h implicit
+done tm/tmweek.c
+meta tmweek.o %.c>%.o tm/tmweek.c tmweek
+prev tm/tmweek.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmweek.c
+done tmweek.o generated
+make tmword.o
+make tm/tmword.c
+prev include/tm.h implicit
+prev include/ast.h implicit
+done tm/tmword.c
+meta tmword.o %.c>%.o tm/tmword.c tmword
+prev tm/tmword.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmword.c
+done tmword.o generated
+make tmzone.o
+make tm/tmzone.c
+prev include/tm.h implicit
+prev include/ast.h implicit
+done tm/tmzone.c
+meta tmzone.o %.c>%.o tm/tmzone.c tmzone
+prev tm/tmzone.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmzone.c
+done tmzone.o generated
+make tmxdate.o
+make tm/tmxdate.c
+prev include/debug.h implicit
+prev tmx.h implicit
+done tm/tmxdate.c
+meta tmxdate.o %.c>%.o tm/tmxdate.c tmxdate
+prev tm/tmxdate.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmxdate.c
+done tmxdate.o generated
+make tmxduration.o
+make tm/tmxduration.c
+prev tmx.h implicit
+done tm/tmxduration.c
+meta tmxduration.o %.c>%.o tm/tmxduration.c tmxduration
+prev tm/tmxduration.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmxduration.c
+done tmxduration.o generated
+make tmxfmt.o
+make tm/tmxfmt.c
+prev tmx.h implicit
+done tm/tmxfmt.c
+meta tmxfmt.o %.c>%.o tm/tmxfmt.c tmxfmt
+prev tm/tmxfmt.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmxfmt.c
+done tmxfmt.o generated
+make tmxgettime.o
+make tm/tmxgettime.c
+prev tv.h implicit
+prev tmx.h implicit
+done tm/tmxgettime.c
+meta tmxgettime.o %.c>%.o tm/tmxgettime.c tmxgettime
+prev tm/tmxgettime.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmxgettime.c
+done tmxgettime.o generated
+make tmxleap.o
+make tm/tmxleap.c
+prev tmx.h implicit
+done tm/tmxleap.c
+meta tmxleap.o %.c>%.o tm/tmxleap.c tmxleap
+prev tm/tmxleap.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmxleap.c
+done tmxleap.o generated
+make tmxmake.o
+make tm/tmxmake.c
+prev FEATURE/tmlib implicit
+prev tmx.h implicit
+done tm/tmxmake.c
+meta tmxmake.o %.c>%.o tm/tmxmake.c tmxmake
+prev tm/tmxmake.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmxmake.c
+done tmxmake.o generated
+make tmxscan.o
+make tm/tmxscan.c
+prev tmx.h implicit
+done tm/tmxscan.c
+meta tmxscan.o %.c>%.o tm/tmxscan.c tmxscan
+prev tm/tmxscan.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmxscan.c
+done tmxscan.o generated
+make tmxsettime.o
+make tm/tmxsettime.c
+prev tv.h implicit
+prev tmx.h implicit
+done tm/tmxsettime.c
+meta tmxsettime.o %.c>%.o tm/tmxsettime.c tmxsettime
+prev tm/tmxsettime.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmxsettime.c
+done tmxsettime.o generated
+make tmxsleep.o
+make tm/tmxsleep.c
+prev tv.h implicit
+prev tmx.h implicit
+done tm/tmxsleep.c
+meta tmxsleep.o %.c>%.o tm/tmxsleep.c tmxsleep
+prev tm/tmxsleep.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmxsleep.c
+done tmxsleep.o generated
+make tmxtime.o
+make tm/tmxtime.c
+prev FEATURE/tmlib implicit
+prev tmx.h implicit
+done tm/tmxtime.c
+meta tmxtime.o %.c>%.o tm/tmxtime.c tmxtime
+prev tm/tmxtime.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmxtime.c
+done tmxtime.o generated
+make tmxtouch.o
+make tm/tmxtouch.c
+prev tv.h implicit
+prev tmx.h implicit
+done tm/tmxtouch.c
+meta tmxtouch.o %.c>%.o tm/tmxtouch.c tmxtouch
+prev tm/tmxtouch.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmxtouch.c
+done tmxtouch.o generated
+make tvcmp.o
+make tm/tvcmp.c
+prev tv.h implicit
+done tm/tvcmp.c
+meta tvcmp.o %.c>%.o tm/tvcmp.c tvcmp
+prev tm/tvcmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tvcmp.c
+done tvcmp.o generated
+make tvgettime.o
+make tm/tvgettime.c
+make FEATURE/tvlib implicit
+meta FEATURE/tvlib features/%>FEATURE/% features/tvlib tvlib
+make features/tvlib
+done features/tvlib
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/tvlib
+done FEATURE/tvlib generated
+prev include/tm.h implicit
+prev tv.h implicit
+done tm/tvgettime.c
+meta tvgettime.o %.c>%.o tm/tvgettime.c tvgettime
+prev tm/tvgettime.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tvgettime.c
+done tvgettime.o generated
+make tvsettime.o
+make tm/tvsettime.c
+prev FEATURE/tvlib implicit
+prev include/tm.h implicit
+prev tv.h implicit
+done tm/tvsettime.c
+meta tvsettime.o %.c>%.o tm/tvsettime.c tvsettime
+prev tm/tvsettime.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tvsettime.c
+done tvsettime.o generated
+make tvsleep.o
+make tm/tvsleep.c
+prev FEATURE/tvlib implicit
+prev include/tm.h implicit
+prev tv.h implicit
+done tm/tvsleep.c
+meta tvsleep.o %.c>%.o tm/tvsleep.c tvsleep
+prev tm/tvsleep.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tvsleep.c
+done tvsleep.o generated
+make tvtouch.o
+make tm/tvtouch.c
+prev FEATURE/tvlib implicit
+prev include/error.h implicit
+prev include/times.h implicit
+prev tv.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done tm/tvtouch.c
+meta tvtouch.o %.c>%.o tm/tvtouch.c tvtouch
+prev tm/tvtouch.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tvtouch.c
+done tvtouch.o generated
+make cmdarg.o
+make misc/cmdarg.c
+prev include/proc.h implicit
+prev ast_api.h implicit
+make include/cmdarg.h implicit
+prev include/error.h implicit
+done include/cmdarg.h
+prev include/ast.h implicit
+done misc/cmdarg.c
+meta cmdarg.o %.c>%.o misc/cmdarg.c cmdarg
+prev misc/cmdarg.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/cmdarg.c
+done cmdarg.o generated
+make vecargs.o
+make vec/vecargs.c
+make include/vecargs.h implicit
+done include/vecargs.h
+prev include/ast.h implicit
+done vec/vecargs.c
+meta vecargs.o %.c>%.o vec/vecargs.c vecargs
+prev vec/vecargs.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c vec/vecargs.c
+done vecargs.o generated
+make vecfile.o
+make vec/vecfile.c
+prev include/vecargs.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done vec/vecfile.c
+meta vecfile.o %.c>%.o vec/vecfile.c vecfile
+prev vec/vecfile.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c vec/vecfile.c
+done vecfile.o generated
+make vecfree.o
+make vec/vecfree.c
+prev include/vecargs.h implicit
+prev include/ast.h implicit
+done vec/vecfree.c
+meta vecfree.o %.c>%.o vec/vecfree.c vecfree
+prev vec/vecfree.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c vec/vecfree.c
+done vecfree.o generated
+make vecload.o
+make vec/vecload.c
+prev include/vecargs.h implicit
+prev include/ast.h implicit
+done vec/vecload.c
+meta vecload.o %.c>%.o vec/vecload.c vecload
+prev vec/vecload.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c vec/vecload.c
+done vecload.o generated
+make vecstring.o
+make vec/vecstring.c
+prev include/vecargs.h implicit
+prev include/ast.h implicit
+done vec/vecstring.c
+meta vecstring.o %.c>%.o vec/vecstring.c vecstring
+prev vec/vecstring.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c vec/vecstring.c
+done vecstring.o generated
+make univdata.o
+make misc/univdata.c
+prev misc/univlib.h implicit
+done misc/univdata.c
+meta univdata.o %.c>%.o misc/univdata.c univdata
+prev misc/univdata.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D_PACKAGE_ast -c misc/univdata.c
+done univdata.o generated
+make touch.o
+make port/touch.c
+prev tv.h implicit
+prev include/times.h implicit
+prev include/ast.h implicit
+done port/touch.c
+meta touch.o %.c>%.o port/touch.c touch
+prev port/touch.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c port/touch.c
+done touch.o generated
+make mnt.o
+make port/mnt.c
+make mnttab.h implicit
+done mnttab.h dontcare virtual
+prev std/stdio.h implicit
+prev std/stdio.h implicit
+prev include/ast_windows.h implicit
+prev include/ls.h implicit
+prev include/mnt.h implicit
+prev include/ast.h implicit
+done port/mnt.c
+meta mnt.o %.c>%.o port/mnt.c mnt
+prev port/mnt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c port/mnt.c
+done mnt.o generated
+make debug.o
+make misc/debug.c
+prev include/times.h implicit
+prev include/debug.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+done misc/debug.c
+meta debug.o %.c>%.o misc/debug.c debug
+prev misc/debug.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c misc/debug.c
+done debug.o generated
+make memccpy.o
+make comp/memccpy.c
+prev include/ast.h implicit
+done comp/memccpy.c
+meta memccpy.o %.c>%.o comp/memccpy.c memccpy
+prev comp/memccpy.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/memccpy.c
+done memccpy.o generated
+make memchr.o
+make comp/memchr.c
+prev include/ast.h implicit
+done comp/memchr.c
+meta memchr.o %.c>%.o comp/memchr.c memchr
+prev comp/memchr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/memchr.c
+done memchr.o generated
+make memcmp.o
+make comp/memcmp.c
+prev include/ast.h implicit
+done comp/memcmp.c
+meta memcmp.o %.c>%.o comp/memcmp.c memcmp
+prev comp/memcmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/memcmp.c
+done memcmp.o generated
+make memcpy.o
+make comp/memcpy.c
+prev include/ast.h implicit
+done comp/memcpy.c
+meta memcpy.o %.c>%.o comp/memcpy.c memcpy
+prev comp/memcpy.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/memcpy.c
+done memcpy.o generated
+make memdup.o
+make string/memdup.c
+prev include/ast.h implicit
+done string/memdup.c
+meta memdup.o %.c>%.o string/memdup.c memdup
+prev string/memdup.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/memdup.c
+done memdup.o generated
+make memmove.o
+make comp/memmove.c
+prev include/ast.h implicit
+done comp/memmove.c
+meta memmove.o %.c>%.o comp/memmove.c memmove
+prev comp/memmove.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/memmove.c
+done memmove.o generated
+make memset.o
+make comp/memset.c
+prev include/ast.h implicit
+done comp/memset.c
+meta memset.o %.c>%.o comp/memset.c memset
+prev comp/memset.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/memset.c
+done memset.o generated
+make mkdir.o
+make comp/mkdir.c
+prev include/error.h implicit
+prev include/wait.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done comp/mkdir.c
+meta mkdir.o %.c>%.o comp/mkdir.c mkdir
+prev comp/mkdir.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/mkdir.c
+done mkdir.o generated
+make mkfifo.o
+make comp/mkfifo.c
+prev include/error.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done comp/mkfifo.c
+meta mkfifo.o %.c>%.o comp/mkfifo.c mkfifo
+prev comp/mkfifo.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/mkfifo.c
+done mkfifo.o generated
+make mknod.o
+make comp/mknod.c
+prev include/error.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done comp/mknod.c
+meta mknod.o %.c>%.o comp/mknod.c mknod
+prev comp/mknod.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/mknod.c
+done mknod.o generated
+make rmdir.o
+make comp/rmdir.c
+prev include/error.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done comp/rmdir.c
+meta rmdir.o %.c>%.o comp/rmdir.c rmdir
+prev comp/rmdir.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/rmdir.c
+done rmdir.o generated
+make remove.o
+make comp/remove.c
+prev ast_map.h implicit
+prev include/ast.h implicit
+done comp/remove.c
+meta remove.o %.c>%.o comp/remove.c remove
+prev comp/remove.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/remove.c
+done remove.o generated
+make rename.o
+make comp/rename.c
+prev include/proc.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/rename.c
+meta rename.o %.c>%.o comp/rename.c rename
+prev comp/rename.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/rename.c
+done rename.o generated
+make link.o
+make comp/link.c
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/link.c
+meta link.o %.c>%.o comp/link.c link
+prev comp/link.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/link.c
+done link.o generated
+make unlink.o
+make comp/unlink.c
+prev include/ast.h implicit
+done comp/unlink.c
+meta unlink.o %.c>%.o comp/unlink.c unlink
+prev comp/unlink.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/unlink.c
+done unlink.o generated
+make strdup.o
+make string/strdup.c
+prev include/ast.h implicit
+done string/strdup.c
+meta strdup.o %.c>%.o string/strdup.c strdup
+prev string/strdup.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/strdup.c
+done strdup.o generated
+make strchr.o
+make comp/strchr.c
+prev include/ast.h implicit
+done comp/strchr.c
+meta strchr.o %.c>%.o comp/strchr.c strchr
+prev comp/strchr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/strchr.c
+done strchr.o generated
+make strrchr.o
+make comp/strrchr.c
+prev include/ast.h implicit
+done comp/strrchr.c
+meta strrchr.o %.c>%.o comp/strrchr.c strrchr
+prev comp/strrchr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/strrchr.c
+done strrchr.o generated
+make strstr.o
+make comp/strstr.c
+prev include/ast.h implicit
+done comp/strstr.c
+meta strstr.o %.c>%.o comp/strstr.c strstr
+prev comp/strstr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/strstr.c
+done strstr.o generated
+make strtod.o
+make comp/strtod.c
+make sfio/sfstrtof.h implicit
+prev FEATURE/float implicit
+prev sfio/sfhdr.h implicit
+done sfio/sfstrtof.h
+prev include/ast.h implicit
+done comp/strtod.c
+meta strtod.o %.c>%.o comp/strtod.c strtod
+prev comp/strtod.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c comp/strtod.c
+done strtod.o generated
+make strtold.o
+make comp/strtold.c
+prev sfio/sfstrtof.h implicit
+prev ast_sys.h implicit
+prev ast_lib.h implicit
+prev ast_common.h implicit
+done comp/strtold.c
+meta strtold.o %.c>%.o comp/strtold.c strtold
+prev comp/strtold.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c comp/strtold.c
+done strtold.o generated
+make strtol.o
+make comp/strtol.c
+make string/strtoi.h implicit
+prev sfio/sfhdr.h implicit
+prev include/ast.h implicit
+done string/strtoi.h dontcare
+done comp/strtol.c
+meta strtol.o %.c>%.o comp/strtol.c strtol
+prev comp/strtol.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istring -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c comp/strtol.c
+done strtol.o generated
+make strtoll.o
+make comp/strtoll.c
+prev string/strtoi.h implicit
+prev ast_map.h implicit
+prev include/ast.h implicit
+done comp/strtoll.c
+meta strtoll.o %.c>%.o comp/strtoll.c strtoll
+prev comp/strtoll.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istring -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c comp/strtoll.c
+done strtoll.o generated
+make strtoul.o
+make comp/strtoul.c
+prev string/strtoi.h implicit
+done comp/strtoul.c
+meta strtoul.o %.c>%.o comp/strtoul.c strtoul
+prev comp/strtoul.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istring -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c comp/strtoul.c
+done strtoul.o generated
+make strtoull.o
+make comp/strtoull.c
+prev string/strtoi.h implicit
+prev ast_map.h implicit
+prev include/ast.h implicit
+done comp/strtoull.c
+meta strtoull.o %.c>%.o comp/strtoull.c strtoull
+prev comp/strtoull.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istring -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c comp/strtoull.c
+done strtoull.o generated
+make strton.o
+make string/strton.c
+prev string/strtoi.h implicit
+done string/strton.c
+meta strton.o %.c>%.o string/strton.c strton
+prev string/strton.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istring -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c string/strton.c
+done strton.o generated
+make strtonll.o
+make string/strtonll.c
+prev string/strtoi.h implicit
+done string/strtonll.c
+meta strtonll.o %.c>%.o string/strtonll.c strtonll
+prev string/strtonll.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istring -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c string/strtonll.c
+done strtonll.o generated
+make strntod.o
+make string/strntod.c
+prev sfio/sfstrtof.h implicit
+prev include/ast.h implicit
+done string/strntod.c
+meta strntod.o %.c>%.o string/strntod.c strntod
+prev string/strntod.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c string/strntod.c
+done strntod.o generated
+make strntold.o
+make string/strntold.c
+prev sfio/sfstrtof.h implicit
+prev include/ast.h implicit
+done string/strntold.c
+meta strntold.o %.c>%.o string/strntold.c strntold
+prev string/strntold.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c string/strntold.c
+done strntold.o generated
+make strnton.o
+make string/strnton.c
+prev string/strtoi.h implicit
+done string/strnton.c
+meta strnton.o %.c>%.o string/strnton.c strnton
+prev string/strnton.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istring -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c string/strnton.c
+done strnton.o generated
+make strntonll.o
+make string/strntonll.c
+prev string/strtoi.h implicit
+done string/strntonll.c
+meta strntonll.o %.c>%.o string/strntonll.c strntonll
+prev string/strntonll.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istring -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c string/strntonll.c
+done strntonll.o generated
+make strntol.o
+make string/strntol.c
+prev string/strtoi.h implicit
+done string/strntol.c
+meta strntol.o %.c>%.o string/strntol.c strntol
+prev string/strntol.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istring -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c string/strntol.c
+done strntol.o generated
+make strntoll.o
+make string/strntoll.c
+prev string/strtoi.h implicit
+done string/strntoll.c
+meta strntoll.o %.c>%.o string/strntoll.c strntoll
+prev string/strntoll.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istring -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c string/strntoll.c
+done strntoll.o generated
+make strntoul.o
+make string/strntoul.c
+prev string/strtoi.h implicit
+done string/strntoul.c
+meta strntoul.o %.c>%.o string/strntoul.c strntoul
+prev string/strntoul.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istring -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c string/strntoul.c
+done strntoul.o generated
+make strntoull.o
+make string/strntoull.c
+prev string/strtoi.h implicit
+done string/strntoull.c
+meta strntoull.o %.c>%.o string/strntoull.c strntoull
+prev string/strntoull.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istring -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c string/strntoull.c
+done strntoull.o generated
+make strcasecmp.o
+make comp/strcasecmp.c
+prev include/ast.h implicit
+done comp/strcasecmp.c
+meta strcasecmp.o %.c>%.o comp/strcasecmp.c strcasecmp
+prev comp/strcasecmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/strcasecmp.c
+done strcasecmp.o generated
+make strncasecmp.o
+make comp/strncasecmp.c
+prev include/ast.h implicit
+done comp/strncasecmp.c
+meta strncasecmp.o %.c>%.o comp/strncasecmp.c strncasecmp
+prev comp/strncasecmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/strncasecmp.c
+done strncasecmp.o generated
+make strerror.o
+make string/strerror.c
+make FEATURE/errno implicit
+meta FEATURE/errno features/%>FEATURE/% features/errno errno
+make features/errno
+done features/errno
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/errno
+done FEATURE/errno generated
+prev port/lclib.h implicit
+done string/strerror.c
+meta strerror.o %.c>%.o string/strerror.c strerror
+prev string/strerror.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c string/strerror.c
+done strerror.o generated
+make mktemp.o
+make comp/mktemp.c
+prev ast_map.h implicit
+prev std/stdio.h implicit
+prev include/ast.h implicit
+done comp/mktemp.c
+meta mktemp.o %.c>%.o comp/mktemp.c mktemp
+prev comp/mktemp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/mktemp.c
+done mktemp.o generated
+make tmpnam.o
+make comp/tmpnam.c
+prev ast_map.h implicit
+prev std/stdio.h implicit
+prev include/ast.h implicit
+done comp/tmpnam.c
+meta tmpnam.o %.c>%.o comp/tmpnam.c tmpnam
+prev comp/tmpnam.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/tmpnam.c
+done tmpnam.o generated
+make fsync.o
+make comp/fsync.c
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/fsync.c
+meta fsync.o %.c>%.o comp/fsync.c fsync
+prev comp/fsync.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/fsync.c
+done fsync.o generated
+make execlp.o
+make comp/execlp.c
+prev include/ast.h implicit
+prev ast_lib.h implicit
+done comp/execlp.c
+meta execlp.o %.c>%.o comp/execlp.c execlp
+prev comp/execlp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/execlp.c
+done execlp.o generated
+make execve.o
+make comp/execve.c
+prev include/error.h implicit
+prev include/wait.h implicit
+prev sig.h implicit
+prev include/ast.h implicit
+done comp/execve.c
+meta execve.o %.c>%.o comp/execve.c execve
+prev comp/execve.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/execve.c
+done execve.o generated
+make execvp.o
+make comp/execvp.c
+prev include/ast.h implicit
+prev ast_lib.h implicit
+done comp/execvp.c
+meta execvp.o %.c>%.o comp/execvp.c execvp
+prev comp/execvp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/execvp.c
+done execvp.o generated
+make execvpe.o
+make comp/execvpe.c
+prev include/ast.h implicit
+prev ast_lib.h implicit
+done comp/execvpe.c
+meta execvpe.o %.c>%.o comp/execvpe.c execvpe
+prev comp/execvpe.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/execvpe.c
+done execvpe.o generated
+make spawnveg.o
+make comp/spawnveg.c
+make ast_vfork.h implicit
+make FEATURE/vfork
+meta FEATURE/vfork features/%>FEATURE/% features/vfork vfork
+make features/vfork
+done features/vfork
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/vfork
+done FEATURE/vfork generated
+exec - cmp 2>/dev/null -s FEATURE/vfork ast_vfork.h || { rm -f ast_vfork.h; silent test -d . || mkdir .; ${STDCP} FEATURE/vfork ast_vfork.h; }
+done ast_vfork.h dontcare generated
+prev ast_tty.h implicit
+prev sig.h implicit
+make process.h implicit
+done process.h dontcare virtual
+prev include/wait.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/spawnveg.c
+meta spawnveg.o %.c>%.o comp/spawnveg.c spawnveg
+prev comp/spawnveg.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/spawnveg.c
+done spawnveg.o generated
+make vfork.o
+make comp/vfork.c
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/vfork.c
+meta vfork.o %.c>%.o comp/vfork.c vfork
+prev comp/vfork.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/vfork.c
+done vfork.o generated
+make killpg.o
+make comp/killpg.c
+prev sig.h implicit
+prev include/ast.h implicit
+done comp/killpg.c
+meta killpg.o %.c>%.o comp/killpg.c killpg
+prev comp/killpg.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/killpg.c
+done killpg.o generated
+make hsearch.o
+make comp/hsearch.c
+make cdt/dthdr.h implicit
+make cdt/cdtlib.h implicit
+prev include/debug.h implicit
+make include/aso.h implicit
+prev ast_common.h implicit
+done include/aso.h dontcare
+prev include/cdt.h implicit
+make ${INSTALLROOT}/include/ast/dlldefs.h implicit
+done ${INSTALLROOT}/include/ast/dlldefs.h dontcare
+prev include/ast.h implicit
+done cdt/cdtlib.h dontcare
+done cdt/dthdr.h dontcare
+prev include/ast.h implicit
+done comp/hsearch.c
+meta hsearch.o %.c>%.o comp/hsearch.c hsearch
+prev comp/hsearch.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c comp/hsearch.c
+done hsearch.o generated
+make tsearch.o
+make comp/tsearch.c
+prev cdt/dthdr.h implicit
+prev include/ast.h implicit
+done comp/tsearch.c
+meta tsearch.o %.c>%.o comp/tsearch.c tsearch
+prev comp/tsearch.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c comp/tsearch.c
+done tsearch.o generated
+make getlogin.o
+make comp/getlogin.c
+prev include/ast.h implicit
+done comp/getlogin.c
+meta getlogin.o %.c>%.o comp/getlogin.c getlogin
+prev comp/getlogin.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/getlogin.c
+done getlogin.o generated
+make putenv.o
+make comp/putenv.c
+prev ast_map.h implicit
+prev include/ast.h implicit
+done comp/putenv.c
+meta putenv.o %.c>%.o comp/putenv.c putenv
+prev comp/putenv.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/putenv.c
+done putenv.o generated
+make setenv.o
+make comp/setenv.c
+prev ast_map.h implicit
+prev include/ast.h implicit
+done comp/setenv.c
+meta setenv.o %.c>%.o comp/setenv.c setenv
+prev comp/setenv.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/setenv.c
+done setenv.o generated
+make unsetenv.o
+make comp/unsetenv.c
+prev ast_map.h implicit
+prev include/ast.h implicit
+done comp/unsetenv.c
+meta unsetenv.o %.c>%.o comp/unsetenv.c unsetenv
+prev comp/unsetenv.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/unsetenv.c
+done unsetenv.o generated
+make lstat.o
+make comp/lstat.c
+prev include/ls.h implicit
+prev include/ast.h implicit
+done comp/lstat.c
+meta lstat.o %.c>%.o comp/lstat.c lstat
+prev comp/lstat.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/lstat.c
+done lstat.o generated
+make statvfs.o
+make comp/statvfs.c
+prev include/error.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done comp/statvfs.c
+meta statvfs.o %.c>%.o comp/statvfs.c statvfs
+prev comp/statvfs.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/statvfs.c
+done statvfs.o generated
+make eaccess.o
+make comp/eaccess.c
+prev FEATURE/eaccess implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done comp/eaccess.c
+meta eaccess.o %.c>%.o comp/eaccess.c eaccess
+prev comp/eaccess.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/eaccess.c
+done eaccess.o generated
+make gross.o
+make comp/gross.c
+make comp/gross_sgi.h implicit
+make locale_attr.h implicit
+done locale_attr.h dontcare virtual
+done comp/gross_sgi.h dontcare
+make FEATURE/hack implicit
+meta FEATURE/hack features/%>FEATURE/% features/hack hack
+make features/hack
+done features/hack
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/hack
+done FEATURE/hack generated
+prev include/ls.h implicit
+prev include/ast.h implicit
+done comp/gross.c
+meta gross.o %.c>%.o comp/gross.c gross
+prev comp/gross.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/gross.c
+done gross.o generated
+make omitted.o
+make comp/omitted.c
+prev process.h implicit
+prev include/ast_windows.h implicit
+prev include/ls.h implicit
+make FEATURE/omitted implicit
+meta FEATURE/omitted features/%>FEATURE/% features/omitted omitted
+make features/omitted
+done features/omitted
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/omitted
+done FEATURE/omitted generated
+prev include/tm.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/omitted.c
+meta omitted.o %.c>%.o comp/omitted.c omitted
+prev comp/omitted.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/omitted.c
+done omitted.o generated
+make readlink.o
+make comp/readlink.c
+prev include/error.h implicit
+make comp/fakelink.h implicit
+done comp/fakelink.h dontcare
+prev include/ast.h implicit
+done comp/readlink.c
+meta readlink.o %.c>%.o comp/readlink.c readlink
+prev comp/readlink.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/readlink.c
+done readlink.o generated
+make symlink.o
+make comp/symlink.c
+prev include/error.h implicit
+prev comp/fakelink.h implicit
+prev include/ast.h implicit
+done comp/symlink.c
+meta symlink.o %.c>%.o comp/symlink.c symlink
+prev comp/symlink.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/symlink.c
+done symlink.o generated
+make getpgrp.o
+make comp/getpgrp.c
+prev include/ast_std.h implicit
+done comp/getpgrp.c
+meta getpgrp.o %.c>%.o comp/getpgrp.c getpgrp
+prev comp/getpgrp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c comp/getpgrp.c
+done getpgrp.o generated
+make setpgid.o
+make comp/setpgid.c
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/setpgid.c
+meta setpgid.o %.c>%.o comp/setpgid.c setpgid
+prev comp/setpgid.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/setpgid.c
+done setpgid.o generated
+make setsid.o
+make comp/setsid.c
+prev include/error.h implicit
+prev ast_tty.h implicit
+prev include/ast.h implicit
+done comp/setsid.c
+meta setsid.o %.c>%.o comp/setsid.c setsid
+prev comp/setsid.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/setsid.c
+done setsid.o generated
+make waitpid.o
+make comp/waitpid.c
+prev include/error.h implicit
+prev sig.h implicit
+prev include/wait.h implicit
+prev include/ast.h implicit
+done comp/waitpid.c
+meta waitpid.o %.c>%.o comp/waitpid.c waitpid
+prev comp/waitpid.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/waitpid.c
+done waitpid.o generated
+make creat64.o
+make comp/creat64.c
+prev include/ast.h implicit
+done comp/creat64.c
+meta creat64.o %.c>%.o comp/creat64.c creat64
+prev comp/creat64.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/creat64.c
+done creat64.o generated
+make fcntl.o
+make comp/fcntl.c
+prev include/error.h implicit
+prev ast_tty.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done comp/fcntl.c
+meta fcntl.o %.c>%.o comp/fcntl.c fcntl
+prev comp/fcntl.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/fcntl.c
+done fcntl.o generated
+make open.o
+make comp/open.c
+prev ast_tty.h implicit
+prev include/error.h implicit
+prev include/ls.h implicit
+prev include/ast.h implicit
+done comp/open.c
+meta open.o %.c>%.o comp/open.c open
+prev comp/open.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/open.c
+done open.o generated
+make atexit.o
+make comp/atexit.c
+prev include/ast.h implicit
+done comp/atexit.c
+meta atexit.o %.c>%.o comp/atexit.c atexit
+prev comp/atexit.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/atexit.c
+done atexit.o generated
+make getdents.o
+make dir/getdents.c
+prev dir/dirlib.h implicit
+done dir/getdents.c
+meta getdents.o %.c>%.o dir/getdents.c getdents
+prev dir/getdents.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idir -Iinclude -Istd -D_PACKAGE_ast -c dir/getdents.c
+done getdents.o generated
+make getwd.o
+make comp/getwd.c
+prev include/ast.h implicit
+done comp/getwd.c
+meta getwd.o %.c>%.o comp/getwd.c getwd
+prev comp/getwd.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/getwd.c
+done getwd.o generated
+make dup2.o
+make comp/dup2.c
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/dup2.c
+meta dup2.o %.c>%.o comp/dup2.c dup2
+prev comp/dup2.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/dup2.c
+done dup2.o generated
+make errno.o
+make comp/errno.c
+prev include/ast.h implicit
+done comp/errno.c
+meta errno.o %.c>%.o comp/errno.c errno
+prev comp/errno.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/errno.c
+done errno.o generated
+make getpreroot.o
+make preroot/getpreroot.c
+prev std/stdio.h implicit
+prev include/error.h implicit
+prev include/ls.h implicit
+prev include/ast_dir.h implicit
+prev preroot.h implicit
+prev include/ast.h implicit
+done preroot/getpreroot.c
+meta getpreroot.o %.c>%.o preroot/getpreroot.c getpreroot
+prev preroot/getpreroot.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idir -Iinclude -Istd -D_PACKAGE_ast -c preroot/getpreroot.c
+done getpreroot.o generated
+make ispreroot.o
+make preroot/ispreroot.c
+prev include/ls.h implicit
+prev preroot.h implicit
+prev include/ast.h implicit
+done preroot/ispreroot.c
+meta ispreroot.o %.c>%.o preroot/ispreroot.c ispreroot
+prev preroot/ispreroot.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c preroot/ispreroot.c
+done ispreroot.o generated
+make realopen.o
+make preroot/realopen.c
+prev preroot.h implicit
+prev include/ast.h implicit
+done preroot/realopen.c
+meta realopen.o %.c>%.o preroot/realopen.c realopen
+prev preroot/realopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c preroot/realopen.c
+done realopen.o generated
+make setpreroot.o
+make preroot/setpreroot.c
+prev include/option.h implicit
+prev preroot.h implicit
+prev include/ast.h implicit
+done preroot/setpreroot.c
+meta setpreroot.o %.c>%.o preroot/setpreroot.c setpreroot
+prev preroot/setpreroot.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c preroot/setpreroot.c
+done setpreroot.o generated
+make getgroups.o
+make comp/getgroups.c
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/getgroups.c
+meta getgroups.o %.c>%.o comp/getgroups.c getgroups
+prev comp/getgroups.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/getgroups.c
+done getgroups.o generated
+make mount.o
+make comp/mount.c
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/mount.c
+meta mount.o %.c>%.o comp/mount.c mount
+prev comp/mount.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/mount.c
+done mount.o generated
+make system.o
+make comp/system.c
+prev ast_map.h implicit
+prev include/proc.h implicit
+prev include/ast.h implicit
+done comp/system.c
+meta system.o %.c>%.o comp/system.c system
+prev comp/system.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/system.c
+done system.o generated
+make iblocks.o
+make port/iblocks.c
+prev include/ls.h implicit
+prev ast_param.h implicit
+prev include/ast.h implicit
+done port/iblocks.c
+meta iblocks.o %.c>%.o port/iblocks.c iblocks
+prev port/iblocks.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c port/iblocks.c
+done iblocks.o generated
+make modedata.o
+make string/modedata.c
+prev string/modelib.h implicit
+done string/modedata.c
+meta modedata.o %.c>%.o string/modedata.c modedata
+prev string/modedata.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Istring -Iinclude -Istd -D_PACKAGE_ast -c string/modedata.c
+done modedata.o generated
+make tmdata.o
+make tm/tmdata.c
+prev include/tm.h implicit
+prev include/ast.h implicit
+done tm/tmdata.c
+meta tmdata.o %.c>%.o tm/tmdata.c tmdata
+prev tm/tmdata.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c tm/tmdata.c
+done tmdata.o generated
+make memfatal.o
+make disc/memfatal.c
+prev FEATURE/vmalloc implicit
+prev include/vmalloc.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+done disc/memfatal.c
+meta memfatal.o %.c>%.o disc/memfatal.c memfatal
+prev disc/memfatal.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c disc/memfatal.c
+done memfatal.o generated
+make sfkeyprintf.o
+make disc/sfkeyprintf.c
+prev ast_api.h implicit
+prev include/regex.h implicit
+make include/sfdisc.h implicit
+prev include/ast.h implicit
+done include/sfdisc.h
+prev include/ccode.h implicit
+prev include/ast.h implicit
+done disc/sfkeyprintf.c
+meta sfkeyprintf.o %.c>%.o disc/sfkeyprintf.c sfkeyprintf
+prev disc/sfkeyprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c disc/sfkeyprintf.c
+done sfkeyprintf.o generated
+make sfdcdio.o
+make disc/sfdcdio.c
+make disc/sfdchdr.h implicit
+prev include/sfdisc.h implicit
+prev sfio/sfhdr.h implicit
+done disc/sfdchdr.h
+done disc/sfdcdio.c
+meta sfdcdio.o %.c>%.o disc/sfdcdio.c sfdcdio
+prev disc/sfdcdio.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idisc -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c disc/sfdcdio.c
+done sfdcdio.o generated
+make sfdcdos.o
+make disc/sfdcdos.c
+prev disc/sfdchdr.h implicit
+done disc/sfdcdos.c
+meta sfdcdos.o %.c>%.o disc/sfdcdos.c sfdcdos
+prev disc/sfdcdos.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idisc -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c disc/sfdcdos.c
+done sfdcdos.o generated
+make sfdcfilter.o
+make disc/sfdcfilter.c
+prev disc/sfdchdr.h implicit
+done disc/sfdcfilter.c
+meta sfdcfilter.o %.c>%.o disc/sfdcfilter.c sfdcfilter
+prev disc/sfdcfilter.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idisc -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c disc/sfdcfilter.c
+done sfdcfilter.o generated
+make sfdcseekable.o
+make disc/sfdcseekable.c
+prev disc/sfdchdr.h implicit
+done disc/sfdcseekable.c
+meta sfdcseekable.o %.c>%.o disc/sfdcseekable.c sfdcseekable
+prev disc/sfdcseekable.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idisc -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c disc/sfdcseekable.c
+done sfdcseekable.o generated
+make sfdcslow.o
+make disc/sfdcslow.c
+prev disc/sfdchdr.h implicit
+done disc/sfdcslow.c
+meta sfdcslow.o %.c>%.o disc/sfdcslow.c sfdcslow
+prev disc/sfdcslow.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idisc -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c disc/sfdcslow.c
+done sfdcslow.o generated
+make sfdcsubstr.o
+make disc/sfdcsubstr.c
+prev disc/sfdchdr.h implicit
+done disc/sfdcsubstr.c
+meta sfdcsubstr.o %.c>%.o disc/sfdcsubstr.c sfdcsubstr
+prev disc/sfdcsubstr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idisc -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c disc/sfdcsubstr.c
+done sfdcsubstr.o generated
+make sfdctee.o
+make disc/sfdctee.c
+prev disc/sfdchdr.h implicit
+done disc/sfdctee.c
+meta sfdctee.o %.c>%.o disc/sfdctee.c sfdctee
+prev disc/sfdctee.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idisc -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c disc/sfdctee.c
+done sfdctee.o generated
+make sfdcunion.o
+make disc/sfdcunion.c
+prev disc/sfdchdr.h implicit
+done disc/sfdcunion.c
+meta sfdcunion.o %.c>%.o disc/sfdcunion.c sfdcunion
+prev disc/sfdcunion.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idisc -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c disc/sfdcunion.c
+done sfdcunion.o generated
+make sfdcmore.o
+make disc/sfdcmore.c
+prev ast_tty.h implicit
+prev disc/sfdchdr.h implicit
+done disc/sfdcmore.c
+meta sfdcmore.o %.c>%.o disc/sfdcmore.c sfdcmore
+prev disc/sfdcmore.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idisc -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c disc/sfdcmore.c
+done sfdcmore.o generated
+make sfdcprefix.o
+make disc/sfdcprefix.c
+prev disc/sfdchdr.h implicit
+done disc/sfdcprefix.c
+meta sfdcprefix.o %.c>%.o disc/sfdcprefix.c sfdcprefix
+prev disc/sfdcprefix.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idisc -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c disc/sfdcprefix.c
+done sfdcprefix.o generated
+make wc.o
+make comp/wc.c
+prev std/wchar.h implicit
+prev include/ast.h implicit
+done comp/wc.c
+meta wc.o %.c>%.o comp/wc.c wc
+prev comp/wc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/wc.c
+done wc.o generated
+make wc2utf8.o
+make string/wc2utf8.c
+prev include/ast.h implicit
+done string/wc2utf8.c
+meta wc2utf8.o %.c>%.o string/wc2utf8.c wc2utf8
+prev string/wc2utf8.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c string/wc2utf8.c
+done wc2utf8.o generated
+make basename.o
+make comp/basename.c
+prev include/ast_std.h implicit
+done comp/basename.c
+meta basename.o %.c>%.o comp/basename.c basename
+prev comp/basename.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c comp/basename.c
+done basename.o generated
+make closelog.o
+make comp/closelog.c
+make comp/sysloglib.h implicit
+make comp/syslog.h implicit
+make ast_namval.h implicit
+prev include/namval.h
+exec - cmp 2>/dev/null -s include/namval.h ast_namval.h || { rm -f ast_namval.h; silent test -d . || mkdir .; ${STDCP} include/namval.h ast_namval.h; }
+done ast_namval.h dontcare generated
+done comp/syslog.h dontcare
+done comp/sysloglib.h dontcare
+prev include/ast.h implicit
+done comp/closelog.c
+meta closelog.o %.c>%.o comp/closelog.c closelog
+prev comp/closelog.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/closelog.c
+done closelog.o generated
+make dirname.o
+make comp/dirname.c
+prev include/ast_std.h implicit
+done comp/dirname.c
+meta dirname.o %.c>%.o comp/dirname.c dirname
+prev comp/dirname.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c comp/dirname.c
+done dirname.o generated
+make fmtmsglib.o
+make comp/fmtmsglib.c
+make comp/fmtmsg.h implicit
+done comp/fmtmsg.h dontcare
+prev include/ast.h implicit
+done comp/fmtmsglib.c
+meta fmtmsglib.o %.c>%.o comp/fmtmsglib.c fmtmsglib
+prev comp/fmtmsglib.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/fmtmsglib.c
+done fmtmsglib.o generated
+make fnmatch.o
+make comp/fnmatch.c
+make comp/fnmatch.h implicit
+prev ast_common.h implicit
+done comp/fnmatch.h
+prev include/regex.h implicit
+prev include/ast.h implicit
+prev ast_lib.h implicit
+done comp/fnmatch.c
+meta fnmatch.o %.c>%.o comp/fnmatch.c fnmatch
+prev comp/fnmatch.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/fnmatch.c
+done fnmatch.o generated
+make ftw.o
+make comp/ftw.c
+make comp/ftw.h implicit
+prev include/ftwalk.h implicit
+done comp/ftw.h
+prev include/ast.h implicit
+done comp/ftw.c
+meta ftw.o %.c>%.o comp/ftw.c ftw
+prev comp/ftw.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/ftw.c
+done ftw.o generated
+make getdate.o
+make comp/getdate.c
+prev ast_map.h implicit
+prev include/tm.h implicit
+prev include/ast.h implicit
+done comp/getdate.c
+meta getdate.o %.c>%.o comp/getdate.c getdate
+prev comp/getdate.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/getdate.c
+done getdate.o generated
+make getsubopt.o
+make comp/getsubopt.c
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/getsubopt.c
+meta getsubopt.o %.c>%.o comp/getsubopt.c getsubopt
+prev comp/getsubopt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/getsubopt.c
+done getsubopt.o generated
+make glob.o
+make misc/glob.c
+make include/glob.h implicit
+done include/glob.h
+prev include/regex.h implicit
+prev include/error.h implicit
+prev include/ast_dir.h implicit
+make include/stak.h implicit
+prev include/stk.h implicit
+done include/stak.h
+prev include/ls.h implicit
+prev include/ast.h implicit
+done misc/glob.c
+meta glob.o %.c>%.o misc/glob.c glob
+prev misc/glob.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Idir -Iinclude -Istd -D_PACKAGE_ast -c misc/glob.c
+done glob.o generated
+make nftw.o
+make comp/nftw.c
+prev comp/ftw.h implicit
+prev include/ast.h implicit
+done comp/nftw.c
+meta nftw.o %.c>%.o comp/nftw.c nftw
+prev comp/nftw.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/nftw.c
+done nftw.o generated
+make openlog.o
+make comp/openlog.c
+prev comp/sysloglib.h implicit
+prev include/ast.h implicit
+done comp/openlog.c
+meta openlog.o %.c>%.o comp/openlog.c openlog
+prev comp/openlog.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/openlog.c
+done openlog.o generated
+make re_comp.o
+make comp/re_comp.c
+prev include/regex.h implicit
+make comp/re_comp.h implicit
+done comp/re_comp.h
+prev include/ast.h implicit
+done comp/re_comp.c
+meta re_comp.o %.c>%.o comp/re_comp.c re_comp
+prev comp/re_comp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/re_comp.c
+done re_comp.o generated
+make resolvepath.o
+make comp/resolvepath.c
+prev ast_api.h implicit
+prev ast_map.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/resolvepath.c
+meta resolvepath.o %.c>%.o comp/resolvepath.c resolvepath
+prev comp/resolvepath.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/resolvepath.c
+done resolvepath.o generated
+make realpath.o
+make comp/realpath.c
+prev ast_map.h implicit
+prev include/ast.h implicit
+done comp/realpath.c
+meta realpath.o %.c>%.o comp/realpath.c realpath
+prev comp/realpath.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/realpath.c
+done realpath.o generated
+make regcmp.o
+make comp/regcmp.c
+prev align.h implicit
+prev include/regex.h implicit
+make comp/libgen.h implicit
+done comp/libgen.h
+prev include/ast.h implicit
+done comp/regcmp.c
+meta regcmp.o %.c>%.o comp/regcmp.c regcmp
+prev comp/regcmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/regcmp.c
+done regcmp.o generated
+make regexp.o
+make comp/regexp.c
+prev align.h implicit
+prev include/regex.h implicit
+make comp/regexp.h implicit
+done comp/regexp.h
+prev include/ast.h implicit
+done comp/regexp.c
+meta regexp.o %.c>%.o comp/regexp.c regexp
+prev comp/regexp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/regexp.c
+done regexp.o generated
+make setlogmask.o
+make comp/setlogmask.c
+prev comp/sysloglib.h implicit
+prev include/ast.h implicit
+done comp/setlogmask.c
+meta setlogmask.o %.c>%.o comp/setlogmask.c setlogmask
+prev comp/setlogmask.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/setlogmask.c
+done setlogmask.o generated
+make strftime.o
+make comp/strftime.c
+prev ast_map.h implicit
+prev include/tm.h implicit
+prev include/ast.h implicit
+done comp/strftime.c
+meta strftime.o %.c>%.o comp/strftime.c strftime
+prev comp/strftime.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/strftime.c
+done strftime.o generated
+make strptime.o
+make comp/strptime.c
+prev ast_map.h implicit
+prev tmx.h implicit
+prev include/ast.h implicit
+done comp/strptime.c
+meta strptime.o %.c>%.o comp/strptime.c strptime
+prev comp/strptime.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/strptime.c
+done strptime.o generated
+make swab.o
+make comp/swab.c
+prev include/swap.h implicit
+prev include/ast.h implicit
+done comp/swab.c
+meta swab.o %.c>%.o comp/swab.c swab
+prev comp/swab.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/swab.c
+done swab.o generated
+make syslog.o
+make comp/syslog.c
+prev std/endian.h implicit
+prev include/ls.h implicit
+prev include/tm.h implicit
+prev include/error.h implicit
+prev comp/sysloglib.h implicit
+prev include/ast.h implicit
+done comp/syslog.c
+meta syslog.o %.c>%.o comp/syslog.c syslog
+prev comp/syslog.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/syslog.c
+done syslog.o generated
+make tempnam.o
+make comp/tempnam.c
+prev std/stdio.h implicit
+prev include/ast.h implicit
+prev include/ast_std.h implicit
+done comp/tempnam.c
+meta tempnam.o %.c>%.o comp/tempnam.c tempnam
+prev comp/tempnam.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/tempnam.c
+done tempnam.o generated
+make wordexp.o
+make comp/wordexp.c
+prev include/stak.h implicit
+make comp/wordexp.h implicit
+prev ast_common.h implicit
+done comp/wordexp.h
+prev include/ast.h implicit
+done comp/wordexp.c
+meta wordexp.o %.c>%.o comp/wordexp.c wordexp
+prev comp/wordexp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/wordexp.c
+done wordexp.o generated
+make mktime.o
+make comp/mktime.c
+prev ast_map.h implicit
+prev include/tm.h implicit
+prev include/ast.h implicit
+done comp/mktime.c
+meta mktime.o %.c>%.o comp/mktime.c mktime
+prev comp/mktime.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/mktime.c
+done mktime.o generated
+make regalloc.o
+make regex/regalloc.c
+make regex/reglib.h implicit
+prev std/wctype.h implicit
+prev std/wchar.h implicit
+prev std/stdio.h implicit
+prev include/regex.h implicit
+prev include/stk.h implicit
+prev include/cdt.h implicit
+prev include/ast.h implicit
+done regex/reglib.h
+done regex/regalloc.c
+meta regalloc.o %.c>%.o regex/regalloc.c regalloc
+prev regex/regalloc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regalloc.c
+done regalloc.o generated
+make regclass.o
+make regex/regclass.c
+prev regex/reglib.h implicit
+done regex/regclass.c
+meta regclass.o %.c>%.o regex/regclass.c regclass
+prev regex/regclass.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regclass.c
+done regclass.o generated
+make regcoll.o
+make regex/regcoll.c
+prev regex/reglib.h implicit
+done regex/regcoll.c
+meta regcoll.o %.c>%.o regex/regcoll.c regcoll
+prev regex/regcoll.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regcoll.c
+done regcoll.o generated
+make regcomp.o
+make regex/regcomp.c
+prev port/lclib.h implicit
+prev regex/reglib.h implicit
+done regex/regcomp.c
+meta regcomp.o %.c>%.o regex/regcomp.c regcomp
+prev regex/regcomp.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} -I. -Icomp -Iport -Iregex -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c regex/regcomp.c
+done regcomp.o generated
+make regcache.o
+make regex/regcache.c
+prev include/regex.h implicit
+prev include/ast.h implicit
+done regex/regcache.c
+meta regcache.o %.c>%.o regex/regcache.c regcache
+prev regex/regcache.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c regex/regcache.c
+done regcache.o generated
+make regdecomp.o
+make regex/regdecomp.c
+prev regex/reglib.h implicit
+done regex/regdecomp.c
+meta regdecomp.o %.c>%.o regex/regdecomp.c regdecomp
+prev regex/regdecomp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regdecomp.c
+done regdecomp.o generated
+make regerror.o
+make regex/regerror.c
+prev regex/reglib.h implicit
+done regex/regerror.c
+meta regerror.o %.c>%.o regex/regerror.c regerror
+prev regex/regerror.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regerror.c
+done regerror.o generated
+make regexec.o
+make regex/regexec.c
+prev regex/reglib.h implicit
+done regex/regexec.c
+meta regexec.o %.c>%.o regex/regexec.c regexec
+prev regex/regexec.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regexec.c
+done regexec.o generated
+make regfatal.o
+make regex/regfatal.c
+prev include/error.h implicit
+prev regex/reglib.h implicit
+done regex/regfatal.c
+meta regfatal.o %.c>%.o regex/regfatal.c regfatal
+prev regex/regfatal.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regfatal.c
+done regfatal.o generated
+make reginit.o
+make regex/reginit.c
+prev include/ccode.h implicit
+prev regex/reglib.h implicit
+done regex/reginit.c
+meta reginit.o %.c>%.o regex/reginit.c reginit
+prev regex/reginit.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/reginit.c
+done reginit.o generated
+make regnexec.o
+make regex/regnexec.c
+prev regex/reglib.h implicit
+done regex/regnexec.c
+meta regnexec.o %.c>%.o regex/regnexec.c regnexec
+prev regex/regnexec.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regnexec.c
+done regnexec.o generated
+make regsubcomp.o
+make regex/regsubcomp.c
+prev regex/reglib.h implicit
+done regex/regsubcomp.c
+meta regsubcomp.o %.c>%.o regex/regsubcomp.c regsubcomp
+prev regex/regsubcomp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regsubcomp.c
+done regsubcomp.o generated
+make regsubexec.o
+make regex/regsubexec.c
+prev regex/reglib.h implicit
+done regex/regsubexec.c
+meta regsubexec.o %.c>%.o regex/regsubexec.c regsubexec
+prev regex/regsubexec.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regsubexec.c
+done regsubexec.o generated
+make regsub.o
+make regex/regsub.c
+prev regex/reglib.h implicit
+done regex/regsub.c
+meta regsub.o %.c>%.o regex/regsub.c regsub
+prev regex/regsub.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regsub.c
+done regsub.o generated
+make regrecord.o
+make regex/regrecord.c
+prev regex/reglib.h implicit
+done regex/regrecord.c
+meta regrecord.o %.c>%.o regex/regrecord.c regrecord
+prev regex/regrecord.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regrecord.c
+done regrecord.o generated
+make regrexec.o
+make regex/regrexec.c
+prev regex/reglib.h implicit
+done regex/regrexec.c
+meta regrexec.o %.c>%.o regex/regrexec.c regrexec
+prev regex/regrexec.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regrexec.c
+done regrexec.o generated
+make regstat.o
+make regex/regstat.c
+prev regex/reglib.h implicit
+done regex/regstat.c
+meta regstat.o %.c>%.o regex/regstat.c regstat
+prev regex/regstat.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iregex -Iinclude -Istd -D_PACKAGE_ast -c regex/regstat.c
+done regstat.o generated
+make dtclose.o
+make cdt/dtclose.c
+prev cdt/dthdr.h implicit
+done cdt/dtclose.c
+meta dtclose.o %.c>%.o cdt/dtclose.c dtclose
+prev cdt/dtclose.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dtclose.c
+done dtclose.o generated
+make dtdisc.o
+make cdt/dtdisc.c
+prev cdt/dthdr.h implicit
+done cdt/dtdisc.c
+meta dtdisc.o %.c>%.o cdt/dtdisc.c dtdisc
+prev cdt/dtdisc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dtdisc.c
+done dtdisc.o generated
+make dthash.o
+make cdt/dthash.c
+prev cdt/dthdr.h implicit
+done cdt/dthash.c
+meta dthash.o %.c>%.o cdt/dthash.c dthash
+prev cdt/dthash.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dthash.c
+done dthash.o generated
+make dtlist.o
+make cdt/dtlist.c
+prev cdt/dthdr.h implicit
+done cdt/dtlist.c
+meta dtlist.o %.c>%.o cdt/dtlist.c dtlist
+prev cdt/dtlist.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dtlist.c
+done dtlist.o generated
+make dtmethod.o
+make cdt/dtmethod.c
+prev cdt/dthdr.h implicit
+done cdt/dtmethod.c
+meta dtmethod.o %.c>%.o cdt/dtmethod.c dtmethod
+prev cdt/dtmethod.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dtmethod.c
+done dtmethod.o generated
+make dtopen.o
+make cdt/dtopen.c
+prev cdt/dthdr.h implicit
+done cdt/dtopen.c
+meta dtopen.o %.c>%.o cdt/dtopen.c dtopen
+prev cdt/dtopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dtopen.c
+done dtopen.o generated
+make dtstrhash.o
+make cdt/dtstrhash.c
+prev cdt/dthdr.h implicit
+done cdt/dtstrhash.c
+meta dtstrhash.o %.c>%.o cdt/dtstrhash.c dtstrhash
+prev cdt/dtstrhash.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dtstrhash.c
+done dtstrhash.o generated
+make dttree.o
+make cdt/dttree.c
+prev cdt/dthdr.h implicit
+done cdt/dttree.c
+meta dttree.o %.c>%.o cdt/dttree.c dttree
+prev cdt/dttree.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dttree.c
+done dttree.o generated
+make dtview.o
+make cdt/dtview.c
+prev cdt/dthdr.h implicit
+done cdt/dtview.c
+meta dtview.o %.c>%.o cdt/dtview.c dtview
+prev cdt/dtview.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dtview.c
+done dtview.o generated
+make dtwalk.o
+make cdt/dtwalk.c
+prev cdt/dthdr.h implicit
+done cdt/dtwalk.c
+meta dtwalk.o %.c>%.o cdt/dtwalk.c dtwalk
+prev cdt/dtwalk.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icdt -Icomp -Iinclude -Istd -I${INSTALLROOT}/include/ast -D_PACKAGE_ast -c cdt/dtwalk.c
+done dtwalk.o generated
+make dtnew.o
+make cdt/dtnew.c
+prev include/dt.h implicit
+done cdt/dtnew.c
+meta dtnew.o %.c>%.o cdt/dtnew.c dtnew
+prev cdt/dtnew.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c cdt/dtnew.c
+done dtnew.o generated
+make dtcomp.o
+make cdt/dtcomp.c
+prev include/cdt.h implicit
+done cdt/dtcomp.c
+meta dtcomp.o %.c>%.o cdt/dtcomp.c dtcomp
+prev cdt/dtcomp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c cdt/dtcomp.c
+done dtcomp.o generated
+make sfclose.o
+make sfio/sfclose.c
+prev sfio/sfhdr.h implicit
+done sfio/sfclose.c
+meta sfclose.o %.c>%.o sfio/sfclose.c sfclose
+prev sfio/sfclose.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfclose.c
+done sfclose.o generated
+make sfclrlock.o
+make sfio/sfclrlock.c
+prev sfio/sfhdr.h implicit
+done sfio/sfclrlock.c
+meta sfclrlock.o %.c>%.o sfio/sfclrlock.c sfclrlock
+prev sfio/sfclrlock.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfclrlock.c
+done sfclrlock.o generated
+make sfdisc.o
+make sfio/sfdisc.c
+prev sfio/sfhdr.h implicit
+done sfio/sfdisc.c
+meta sfdisc.o %.c>%.o sfio/sfdisc.c sfdisc
+prev sfio/sfdisc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfdisc.c
+done sfdisc.o generated
+make sfdlen.o
+make sfio/sfdlen.c
+prev sfio/sfhdr.h implicit
+done sfio/sfdlen.c
+meta sfdlen.o %.c>%.o sfio/sfdlen.c sfdlen
+prev sfio/sfdlen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfdlen.c
+done sfdlen.o generated
+make sfexcept.o
+make sfio/sfexcept.c
+prev sfio/sfhdr.h implicit
+done sfio/sfexcept.c
+meta sfexcept.o %.c>%.o sfio/sfexcept.c sfexcept
+prev sfio/sfexcept.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfexcept.c
+done sfexcept.o generated
+make sfgetl.o
+make sfio/sfgetl.c
+prev sfio/sfhdr.h implicit
+done sfio/sfgetl.c
+meta sfgetl.o %.c>%.o sfio/sfgetl.c sfgetl
+prev sfio/sfgetl.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfgetl.c
+done sfgetl.o generated
+make sfgetu.o
+make sfio/sfgetu.c
+prev sfio/sfhdr.h implicit
+done sfio/sfgetu.c
+meta sfgetu.o %.c>%.o sfio/sfgetu.c sfgetu
+prev sfio/sfgetu.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfgetu.c
+done sfgetu.o generated
+make sfcvt.o
+make sfio/sfcvt.c
+prev sfio/sfhdr.h implicit
+prev FEATURE/isoc99 implicit
+done sfio/sfcvt.c
+meta sfcvt.o %.c>%.o sfio/sfcvt.c sfcvt
+prev sfio/sfcvt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfcvt.c
+done sfcvt.o generated
+make sfecvt.o
+make sfio/sfecvt.c
+prev sfio/sfhdr.h implicit
+done sfio/sfecvt.c
+meta sfecvt.o %.c>%.o sfio/sfecvt.c sfecvt
+prev sfio/sfecvt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfecvt.c
+done sfecvt.o generated
+make sffcvt.o
+make sfio/sffcvt.c
+prev sfio/sfhdr.h implicit
+done sfio/sffcvt.c
+meta sffcvt.o %.c>%.o sfio/sffcvt.c sffcvt
+prev sfio/sffcvt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sffcvt.c
+done sffcvt.o generated
+make sfextern.o
+make sfio/sfextern.c
+prev sfio/sfhdr.h implicit
+done sfio/sfextern.c
+meta sfextern.o %.c>%.o sfio/sfextern.c sfextern
+prev sfio/sfextern.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfextern.c
+done sfextern.o generated
+make sffilbuf.o
+make sfio/sffilbuf.c
+prev sfio/sfhdr.h implicit
+done sfio/sffilbuf.c
+meta sffilbuf.o %.c>%.o sfio/sffilbuf.c sffilbuf
+prev sfio/sffilbuf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sffilbuf.c
+done sffilbuf.o generated
+make sfflsbuf.o
+make sfio/sfflsbuf.c
+prev sfio/sfhdr.h implicit
+done sfio/sfflsbuf.c
+meta sfflsbuf.o %.c>%.o sfio/sfflsbuf.c sfflsbuf
+prev sfio/sfflsbuf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfflsbuf.c
+done sfflsbuf.o generated
+make sfprints.o
+make sfio/sfprints.c
+prev sfio/sfhdr.h implicit
+done sfio/sfprints.c
+meta sfprints.o %.c>%.o sfio/sfprints.c sfprints
+prev sfio/sfprints.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfprints.c
+done sfprints.o generated
+make sfgetd.o
+make sfio/sfgetd.c
+prev sfio/sfhdr.h implicit
+done sfio/sfgetd.c
+meta sfgetd.o %.c>%.o sfio/sfgetd.c sfgetd
+prev sfio/sfgetd.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfgetd.c
+done sfgetd.o generated
+make sfgetr.o
+make sfio/sfgetr.c
+prev sfio/sfhdr.h implicit
+done sfio/sfgetr.c
+meta sfgetr.o %.c>%.o sfio/sfgetr.c sfgetr
+prev sfio/sfgetr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfgetr.c
+done sfgetr.o generated
+make sfllen.o
+make sfio/sfllen.c
+prev sfio/sfhdr.h implicit
+done sfio/sfllen.c
+meta sfllen.o %.c>%.o sfio/sfllen.c sfllen
+prev sfio/sfllen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfllen.c
+done sfllen.o generated
+make sfmode.o
+make sfio/sfmode.c
+prev include/wait.h implicit
+prev sig.h implicit
+prev sfio/sfhdr.h implicit
+done sfio/sfmode.c
+meta sfmode.o %.c>%.o sfio/sfmode.c sfmode
+prev sfio/sfmode.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfmode.c
+done sfmode.o generated
+make sfmove.o
+make sfio/sfmove.c
+prev sfio/sfhdr.h implicit
+done sfio/sfmove.c
+meta sfmove.o %.c>%.o sfio/sfmove.c sfmove
+prev sfio/sfmove.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfmove.c
+done sfmove.o generated
+make sfnew.o
+make sfio/sfnew.c
+prev sfio/sfhdr.h implicit
+done sfio/sfnew.c
+meta sfnew.o %.c>%.o sfio/sfnew.c sfnew
+prev sfio/sfnew.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfnew.c
+done sfnew.o generated
+make sfpkrd.o
+make sfio/sfpkrd.c
+prev sfio/sfhdr.h implicit
+done sfio/sfpkrd.c
+meta sfpkrd.o %.c>%.o sfio/sfpkrd.c sfpkrd
+prev sfio/sfpkrd.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfpkrd.c
+done sfpkrd.o generated
+make sfnotify.o
+make sfio/sfnotify.c
+prev sfio/sfhdr.h implicit
+done sfio/sfnotify.c
+meta sfnotify.o %.c>%.o sfio/sfnotify.c sfnotify
+prev sfio/sfnotify.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfnotify.c
+done sfnotify.o generated
+make sfnputc.o
+make sfio/sfnputc.c
+prev sfio/sfhdr.h implicit
+done sfio/sfnputc.c
+meta sfnputc.o %.c>%.o sfio/sfnputc.c sfnputc
+prev sfio/sfnputc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfnputc.c
+done sfnputc.o generated
+make sfopen.o
+make sfio/sfopen.c
+prev sfio/sfhdr.h implicit
+done sfio/sfopen.c
+meta sfopen.o %.c>%.o sfio/sfopen.c sfopen
+prev sfio/sfopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfopen.c
+done sfopen.o generated
+make sfpeek.o
+make sfio/sfpeek.c
+prev sfio/sfhdr.h implicit
+done sfio/sfpeek.c
+meta sfpeek.o %.c>%.o sfio/sfpeek.c sfpeek
+prev sfio/sfpeek.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfpeek.c
+done sfpeek.o generated
+make sfpoll.o
+make sfio/sfpoll.c
+prev sfio/sfhdr.h implicit
+done sfio/sfpoll.c
+meta sfpoll.o %.c>%.o sfio/sfpoll.c sfpoll
+prev sfio/sfpoll.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfpoll.c
+done sfpoll.o generated
+make sfpool.o
+make sfio/sfpool.c
+prev sfio/sfhdr.h implicit
+done sfio/sfpool.c
+meta sfpool.o %.c>%.o sfio/sfpool.c sfpool
+prev sfio/sfpool.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfpool.c
+done sfpool.o generated
+make sfpopen.o
+make sfio/sfpopen.c
+prev include/proc.h implicit
+prev sfio/sfhdr.h implicit
+done sfio/sfpopen.c
+meta sfpopen.o %.c>%.o sfio/sfpopen.c sfpopen
+prev sfio/sfpopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfpopen.c
+done sfpopen.o generated
+make sfprintf.o
+make sfio/sfprintf.c
+prev sfio/sfhdr.h implicit
+done sfio/sfprintf.c
+meta sfprintf.o %.c>%.o sfio/sfprintf.c sfprintf
+prev sfio/sfprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS.FORCE} ${mam_cc_NOPROTECT} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfprintf.c
+done sfprintf.o generated
+make sfputd.o
+make sfio/sfputd.c
+prev sfio/sfhdr.h implicit
+done sfio/sfputd.c
+meta sfputd.o %.c>%.o sfio/sfputd.c sfputd
+prev sfio/sfputd.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfputd.c
+done sfputd.o generated
+make sfputl.o
+make sfio/sfputl.c
+prev sfio/sfhdr.h implicit
+done sfio/sfputl.c
+meta sfputl.o %.c>%.o sfio/sfputl.c sfputl
+prev sfio/sfputl.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfputl.c
+done sfputl.o generated
+make sfputr.o
+make sfio/sfputr.c
+prev sfio/sfhdr.h implicit
+done sfio/sfputr.c
+meta sfputr.o %.c>%.o sfio/sfputr.c sfputr
+prev sfio/sfputr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfputr.c
+done sfputr.o generated
+make sfputu.o
+make sfio/sfputu.c
+prev sfio/sfhdr.h implicit
+done sfio/sfputu.c
+meta sfputu.o %.c>%.o sfio/sfputu.c sfputu
+prev sfio/sfputu.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfputu.c
+done sfputu.o generated
+make sfrd.o
+make sfio/sfrd.c
+prev sfio/sfhdr.h implicit
+done sfio/sfrd.c
+meta sfrd.o %.c>%.o sfio/sfrd.c sfrd
+prev sfio/sfrd.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${DEBUG+-DDEBUG=${DEBUG}} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfrd.c
+done sfrd.o generated
+make sfread.o
+make sfio/sfread.c
+prev sfio/sfhdr.h implicit
+done sfio/sfread.c
+meta sfread.o %.c>%.o sfio/sfread.c sfread
+prev sfio/sfread.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfread.c
+done sfread.o generated
+make sfreserve.o
+make sfio/sfreserve.c
+prev sfio/sfhdr.h implicit
+done sfio/sfreserve.c
+meta sfreserve.o %.c>%.o sfio/sfreserve.c sfreserve
+prev sfio/sfreserve.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfreserve.c
+done sfreserve.o generated
+make sfscanf.o
+make sfio/sfscanf.c
+prev sfio/sfhdr.h implicit
+done sfio/sfscanf.c
+meta sfscanf.o %.c>%.o sfio/sfscanf.c sfscanf
+prev sfio/sfscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS.FORCE} ${mam_cc_NOPROTECT} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfscanf.c
+done sfscanf.o generated
+make sfseek.o
+make sfio/sfseek.c
+prev sfio/sfhdr.h implicit
+done sfio/sfseek.c
+meta sfseek.o %.c>%.o sfio/sfseek.c sfseek
+prev sfio/sfseek.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfseek.c
+done sfseek.o generated
+make sfset.o
+make sfio/sfset.c
+prev sfio/sfhdr.h implicit
+done sfio/sfset.c
+meta sfset.o %.c>%.o sfio/sfset.c sfset
+prev sfio/sfset.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${DEBUG+-DDEBUG=${DEBUG}} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfset.c
+done sfset.o generated
+make sfsetbuf.o
+make sfio/sfsetbuf.c
+prev sfio/sfhdr.h implicit
+done sfio/sfsetbuf.c
+meta sfsetbuf.o %.c>%.o sfio/sfsetbuf.c sfsetbuf
+prev sfio/sfsetbuf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfsetbuf.c
+done sfsetbuf.o generated
+make sfsetfd.o
+make sfio/sfsetfd.c
+prev sfio/sfhdr.h implicit
+done sfio/sfsetfd.c
+meta sfsetfd.o %.c>%.o sfio/sfsetfd.c sfsetfd
+prev sfio/sfsetfd.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfsetfd.c
+done sfsetfd.o generated
+make sfsize.o
+make sfio/sfsize.c
+prev sfio/sfhdr.h implicit
+done sfio/sfsize.c
+meta sfsize.o %.c>%.o sfio/sfsize.c sfsize
+prev sfio/sfsize.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfsize.c
+done sfsize.o generated
+make sfsk.o
+make sfio/sfsk.c
+prev sfio/sfhdr.h implicit
+done sfio/sfsk.c
+meta sfsk.o %.c>%.o sfio/sfsk.c sfsk
+prev sfio/sfsk.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfsk.c
+done sfsk.o generated
+make sfstack.o
+make sfio/sfstack.c
+prev sfio/sfhdr.h implicit
+done sfio/sfstack.c
+meta sfstack.o %.c>%.o sfio/sfstack.c sfstack
+prev sfio/sfstack.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfstack.c
+done sfstack.o generated
+make sfstrtod.o
+make sfio/sfstrtod.c
+prev sfio/sfhdr.h implicit
+done sfio/sfstrtod.c
+meta sfstrtod.o %.c>%.o sfio/sfstrtod.c sfstrtod
+prev sfio/sfstrtod.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfstrtod.c
+done sfstrtod.o generated
+make sfsync.o
+make sfio/sfsync.c
+prev sfio/sfhdr.h implicit
+done sfio/sfsync.c
+meta sfsync.o %.c>%.o sfio/sfsync.c sfsync
+prev sfio/sfsync.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfsync.c
+done sfsync.o generated
+make sfswap.o
+make sfio/sfswap.c
+prev sfio/sfhdr.h implicit
+done sfio/sfswap.c
+meta sfswap.o %.c>%.o sfio/sfswap.c sfswap
+prev sfio/sfswap.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfswap.c
+done sfswap.o generated
+make sftable.o
+make sfio/sftable.c
+make FEATURE/sfinit implicit
+meta FEATURE/sfinit features/%.c>FEATURE/% features/sfinit.c sfinit
+make features/sfinit.c
+prev FEATURE/float implicit
+prev FEATURE/common implicit
+done features/sfinit.c
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Istd ${LDFLAGS} ' run features/sfinit.c
+done FEATURE/sfinit generated
+prev FEATURE/float implicit
+prev sfio/sfhdr.h implicit
+done sfio/sftable.c
+meta sftable.o %.c>%.o sfio/sftable.c sftable
+prev sfio/sftable.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sftable.c
+done sftable.o generated
+make sftell.o
+make sfio/sftell.c
+prev sfio/sfhdr.h implicit
+done sfio/sftell.c
+meta sftell.o %.c>%.o sfio/sftell.c sftell
+prev sfio/sftell.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sftell.c
+done sftell.o generated
+make sftmp.o
+make sfio/sftmp.c
+prev sfio/sfhdr.h implicit
+done sfio/sftmp.c
+meta sftmp.o %.c>%.o sfio/sftmp.c sftmp
+prev sfio/sftmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sftmp.c
+done sftmp.o generated
+make sfungetc.o
+make sfio/sfungetc.c
+prev sfio/sfhdr.h implicit
+done sfio/sfungetc.c
+meta sfungetc.o %.c>%.o sfio/sfungetc.c sfungetc
+prev sfio/sfungetc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfungetc.c
+done sfungetc.o generated
+make sfvprintf.o
+make sfio/sfvprintf.c
+prev include/ccode.h implicit
+prev sfio/sfhdr.h implicit
+done sfio/sfvprintf.c
+meta sfvprintf.o %.c>%.o sfio/sfvprintf.c sfvprintf
+prev sfio/sfvprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} ${mam_cc_NOPROTECT} ${DEBUG+-DDEBUG=${DEBUG}} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfvprintf.c
+done sfvprintf.o generated
+make sfvscanf.o
+make sfio/sfvscanf.c
+prev sfio/sfstrtof.h implicit
+prev sfio/sfhdr.h implicit
+done sfio/sfvscanf.c
+meta sfvscanf.o %.c>%.o sfio/sfvscanf.c sfvscanf
+prev sfio/sfvscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS.FORCE} ${mam_cc_NOPROTECT} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfvscanf.c
+done sfvscanf.o generated
+make sfwr.o
+make sfio/sfwr.c
+prev sfio/sfhdr.h implicit
+done sfio/sfwr.c
+meta sfwr.o %.c>%.o sfio/sfwr.c sfwr
+prev sfio/sfwr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfwr.c
+done sfwr.o generated
+make sfwrite.o
+make sfio/sfwrite.c
+prev sfio/sfhdr.h implicit
+done sfio/sfwrite.c
+meta sfwrite.o %.c>%.o sfio/sfwrite.c sfwrite
+prev sfio/sfwrite.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfwrite.c
+done sfwrite.o generated
+make sfpurge.o
+make sfio/sfpurge.c
+prev sfio/sfhdr.h implicit
+done sfio/sfpurge.c
+meta sfpurge.o %.c>%.o sfio/sfpurge.c sfpurge
+prev sfio/sfpurge.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfpurge.c
+done sfpurge.o generated
+make sfraise.o
+make sfio/sfraise.c
+prev sfio/sfhdr.h implicit
+done sfio/sfraise.c
+meta sfraise.o %.c>%.o sfio/sfraise.c sfraise
+prev sfio/sfraise.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfraise.c
+done sfraise.o generated
+make sfwalk.o
+make sfio/sfwalk.c
+prev sfio/sfhdr.h implicit
+done sfio/sfwalk.c
+meta sfwalk.o %.c>%.o sfio/sfwalk.c sfwalk
+prev sfio/sfwalk.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfwalk.c
+done sfwalk.o generated
+make sfgetm.o
+make sfio/sfgetm.c
+prev sfio/sfhdr.h implicit
+done sfio/sfgetm.c
+meta sfgetm.o %.c>%.o sfio/sfgetm.c sfgetm
+prev sfio/sfgetm.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfgetm.c
+done sfgetm.o generated
+make sfmutex.o
+make sfio/sfmutex.c
+prev sfio/sfhdr.h implicit
+done sfio/sfmutex.c
+meta sfmutex.o %.c>%.o sfio/sfmutex.c sfmutex
+prev sfio/sfmutex.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfmutex.c
+done sfmutex.o generated
+make sfputm.o
+make sfio/sfputm.c
+prev sfio/sfhdr.h implicit
+done sfio/sfputm.c
+meta sfputm.o %.c>%.o sfio/sfputm.c sfputm
+prev sfio/sfputm.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfputm.c
+done sfputm.o generated
+make sfresize.o
+make sfio/sfresize.c
+prev sfio/sfhdr.h implicit
+done sfio/sfresize.c
+meta sfresize.o %.c>%.o sfio/sfresize.c sfresize
+prev sfio/sfresize.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/sfresize.c
+done sfresize.o generated
+make _sfclrerr.o
+make sfio/_sfclrerr.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfclrerr.c
+meta _sfclrerr.o %.c>%.o sfio/_sfclrerr.c _sfclrerr
+prev sfio/_sfclrerr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfclrerr.c
+done _sfclrerr.o generated
+make _sfeof.o
+make sfio/_sfeof.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfeof.c
+meta _sfeof.o %.c>%.o sfio/_sfeof.c _sfeof
+prev sfio/_sfeof.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfeof.c
+done _sfeof.o generated
+make _sferror.o
+make sfio/_sferror.c
+prev sfio/sfhdr.h implicit
+done sfio/_sferror.c
+meta _sferror.o %.c>%.o sfio/_sferror.c _sferror
+prev sfio/_sferror.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sferror.c
+done _sferror.o generated
+make _sffileno.o
+make sfio/_sffileno.c
+prev sfio/sfhdr.h implicit
+done sfio/_sffileno.c
+meta _sffileno.o %.c>%.o sfio/_sffileno.c _sffileno
+prev sfio/_sffileno.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sffileno.c
+done _sffileno.o generated
+make _sfopen.o
+make sfio/_sfopen.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfopen.c
+meta _sfopen.o %.c>%.o sfio/_sfopen.c _sfopen
+prev sfio/_sfopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfopen.c
+done _sfopen.o generated
+make _sfstacked.o
+make sfio/_sfstacked.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfstacked.c
+meta _sfstacked.o %.c>%.o sfio/_sfstacked.c _sfstacked
+prev sfio/_sfstacked.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfstacked.c
+done _sfstacked.o generated
+make _sfvalue.o
+make sfio/_sfvalue.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfvalue.c
+meta _sfvalue.o %.c>%.o sfio/_sfvalue.c _sfvalue
+prev sfio/_sfvalue.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfvalue.c
+done _sfvalue.o generated
+make _sfgetc.o
+make sfio/_sfgetc.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfgetc.c
+meta _sfgetc.o %.c>%.o sfio/_sfgetc.c _sfgetc
+prev sfio/_sfgetc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfgetc.c
+done _sfgetc.o generated
+make _sfgetl.o
+make sfio/_sfgetl.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfgetl.c
+meta _sfgetl.o %.c>%.o sfio/_sfgetl.c _sfgetl
+prev sfio/_sfgetl.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfgetl.c
+done _sfgetl.o generated
+make _sfgetl2.o
+make sfio/_sfgetl2.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfgetl2.c
+meta _sfgetl2.o %.c>%.o sfio/_sfgetl2.c _sfgetl2
+prev sfio/_sfgetl2.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfgetl2.c
+done _sfgetl2.o generated
+make _sfgetu.o
+make sfio/_sfgetu.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfgetu.c
+meta _sfgetu.o %.c>%.o sfio/_sfgetu.c _sfgetu
+prev sfio/_sfgetu.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfgetu.c
+done _sfgetu.o generated
+make _sfgetu2.o
+make sfio/_sfgetu2.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfgetu2.c
+meta _sfgetu2.o %.c>%.o sfio/_sfgetu2.c _sfgetu2
+prev sfio/_sfgetu2.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfgetu2.c
+done _sfgetu2.o generated
+make _sfdlen.o
+make sfio/_sfdlen.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfdlen.c
+meta _sfdlen.o %.c>%.o sfio/_sfdlen.c _sfdlen
+prev sfio/_sfdlen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfdlen.c
+done _sfdlen.o generated
+make _sfllen.o
+make sfio/_sfllen.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfllen.c
+meta _sfllen.o %.c>%.o sfio/_sfllen.c _sfllen
+prev sfio/_sfllen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfllen.c
+done _sfllen.o generated
+make _sfslen.o
+make sfio/_sfslen.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfslen.c
+meta _sfslen.o %.c>%.o sfio/_sfslen.c _sfslen
+prev sfio/_sfslen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfslen.c
+done _sfslen.o generated
+make _sfulen.o
+make sfio/_sfulen.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfulen.c
+meta _sfulen.o %.c>%.o sfio/_sfulen.c _sfulen
+prev sfio/_sfulen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfulen.c
+done _sfulen.o generated
+make _sfputc.o
+make sfio/_sfputc.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfputc.c
+meta _sfputc.o %.c>%.o sfio/_sfputc.c _sfputc
+prev sfio/_sfputc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfputc.c
+done _sfputc.o generated
+make _sfputd.o
+make sfio/_sfputd.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfputd.c
+meta _sfputd.o %.c>%.o sfio/_sfputd.c _sfputd
+prev sfio/_sfputd.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfputd.c
+done _sfputd.o generated
+make _sfputl.o
+make sfio/_sfputl.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfputl.c
+meta _sfputl.o %.c>%.o sfio/_sfputl.c _sfputl
+prev sfio/_sfputl.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfputl.c
+done _sfputl.o generated
+make _sfputm.o
+make sfio/_sfputm.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfputm.c
+meta _sfputm.o %.c>%.o sfio/_sfputm.c _sfputm
+prev sfio/_sfputm.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfputm.c
+done _sfputm.o generated
+make _sfputu.o
+make sfio/_sfputu.c
+prev sfio/sfhdr.h implicit
+done sfio/_sfputu.c
+meta _sfputu.o %.c>%.o sfio/_sfputu.c _sfputu
+prev sfio/_sfputu.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c sfio/_sfputu.c
+done _sfputu.o generated
+make clearerr.o
+make stdio/clearerr.c
+make stdio/stdhdr.h implicit
+prev std/stdio.h implicit
+prev sfio/sfhdr.h implicit
+done stdio/stdhdr.h
+done stdio/clearerr.c
+meta clearerr.o %.c>%.o stdio/clearerr.c clearerr
+prev stdio/clearerr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/clearerr.c
+done clearerr.o generated
+make fclose.o
+make stdio/fclose.c
+prev stdio/stdhdr.h implicit
+done stdio/fclose.c
+meta fclose.o %.c>%.o stdio/fclose.c fclose
+prev stdio/fclose.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fclose.c
+done fclose.o generated
+make fdopen.o
+make stdio/fdopen.c
+prev stdio/stdhdr.h implicit
+done stdio/fdopen.c
+meta fdopen.o %.c>%.o stdio/fdopen.c fdopen
+prev stdio/fdopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fdopen.c
+done fdopen.o generated
+make feof.o
+make stdio/feof.c
+prev stdio/stdhdr.h implicit
+done stdio/feof.c
+meta feof.o %.c>%.o stdio/feof.c feof
+prev stdio/feof.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/feof.c
+done feof.o generated
+make ferror.o
+make stdio/ferror.c
+prev stdio/stdhdr.h implicit
+done stdio/ferror.c
+meta ferror.o %.c>%.o stdio/ferror.c ferror
+prev stdio/ferror.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/ferror.c
+done ferror.o generated
+make fflush.o
+make stdio/fflush.c
+prev stdio/stdhdr.h implicit
+done stdio/fflush.c
+meta fflush.o %.c>%.o stdio/fflush.c fflush
+prev stdio/fflush.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fflush.c
+done fflush.o generated
+make fgetc.o
+make stdio/fgetc.c
+prev stdio/stdhdr.h implicit
+done stdio/fgetc.c
+meta fgetc.o %.c>%.o stdio/fgetc.c fgetc
+prev stdio/fgetc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fgetc.c
+done fgetc.o generated
+make fgetpos.o
+make stdio/fgetpos.c
+prev stdio/stdhdr.h implicit
+done stdio/fgetpos.c
+meta fgetpos.o %.c>%.o stdio/fgetpos.c fgetpos
+prev stdio/fgetpos.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fgetpos.c
+done fgetpos.o generated
+make fgets.o
+make stdio/fgets.c
+prev stdio/stdhdr.h implicit
+done stdio/fgets.c
+meta fgets.o %.c>%.o stdio/fgets.c fgets
+prev stdio/fgets.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fgets.c
+done fgets.o generated
+make fileno.o
+make stdio/fileno.c
+prev stdio/stdhdr.h implicit
+done stdio/fileno.c
+meta fileno.o %.c>%.o stdio/fileno.c fileno
+prev stdio/fileno.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fileno.c
+done fileno.o generated
+make fopen.o
+make stdio/fopen.c
+prev stdio/stdhdr.h implicit
+done stdio/fopen.c
+meta fopen.o %.c>%.o stdio/fopen.c fopen
+prev stdio/fopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fopen.c
+done fopen.o generated
+make fprintf.o
+make stdio/fprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/fprintf.c
+meta fprintf.o %.c>%.o stdio/fprintf.c fprintf
+prev stdio/fprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fprintf.c
+done fprintf.o generated
+make fpurge.o
+make stdio/fpurge.c
+prev stdio/stdhdr.h implicit
+done stdio/fpurge.c
+meta fpurge.o %.c>%.o stdio/fpurge.c fpurge
+prev stdio/fpurge.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fpurge.c
+done fpurge.o generated
+make fputc.o
+make stdio/fputc.c
+prev stdio/stdhdr.h implicit
+done stdio/fputc.c
+meta fputc.o %.c>%.o stdio/fputc.c fputc
+prev stdio/fputc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fputc.c
+done fputc.o generated
+make fputs.o
+make stdio/fputs.c
+prev stdio/stdhdr.h implicit
+done stdio/fputs.c
+meta fputs.o %.c>%.o stdio/fputs.c fputs
+prev stdio/fputs.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fputs.c
+done fputs.o generated
+make fread.o
+make stdio/fread.c
+prev stdio/stdhdr.h implicit
+done stdio/fread.c
+meta fread.o %.c>%.o stdio/fread.c fread
+prev stdio/fread.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fread.c
+done fread.o generated
+make freopen.o
+make stdio/freopen.c
+prev stdio/stdhdr.h implicit
+done stdio/freopen.c
+meta freopen.o %.c>%.o stdio/freopen.c freopen
+prev stdio/freopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/freopen.c
+done freopen.o generated
+make fscanf.o
+make stdio/fscanf.c
+prev stdio/stdhdr.h implicit
+done stdio/fscanf.c
+meta fscanf.o %.c>%.o stdio/fscanf.c fscanf
+prev stdio/fscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fscanf.c
+done fscanf.o generated
+make fseek.o
+make stdio/fseek.c
+prev stdio/stdhdr.h implicit
+done stdio/fseek.c
+meta fseek.o %.c>%.o stdio/fseek.c fseek
+prev stdio/fseek.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fseek.c
+done fseek.o generated
+make fseeko.o
+make stdio/fseeko.c
+prev stdio/stdhdr.h implicit
+done stdio/fseeko.c
+meta fseeko.o %.c>%.o stdio/fseeko.c fseeko
+prev stdio/fseeko.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fseeko.c
+done fseeko.o generated
+make fsetpos.o
+make stdio/fsetpos.c
+prev stdio/stdhdr.h implicit
+done stdio/fsetpos.c
+meta fsetpos.o %.c>%.o stdio/fsetpos.c fsetpos
+prev stdio/fsetpos.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fsetpos.c
+done fsetpos.o generated
+make ftell.o
+make stdio/ftell.c
+prev stdio/stdhdr.h implicit
+done stdio/ftell.c
+meta ftell.o %.c>%.o stdio/ftell.c ftell
+prev stdio/ftell.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/ftell.c
+done ftell.o generated
+make ftello.o
+make stdio/ftello.c
+prev stdio/stdhdr.h implicit
+done stdio/ftello.c
+meta ftello.o %.c>%.o stdio/ftello.c ftello
+prev stdio/ftello.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/ftello.c
+done ftello.o generated
+make fwrite.o
+make stdio/fwrite.c
+prev stdio/stdhdr.h implicit
+done stdio/fwrite.c
+meta fwrite.o %.c>%.o stdio/fwrite.c fwrite
+prev stdio/fwrite.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fwrite.c
+done fwrite.o generated
+make flockfile.o
+make stdio/flockfile.c
+prev stdio/stdhdr.h implicit
+done stdio/flockfile.c
+meta flockfile.o %.c>%.o stdio/flockfile.c flockfile
+prev stdio/flockfile.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/flockfile.c
+done flockfile.o generated
+make ftrylockfile.o
+make stdio/ftrylockfile.c
+prev stdio/stdhdr.h implicit
+done stdio/ftrylockfile.c
+meta ftrylockfile.o %.c>%.o stdio/ftrylockfile.c ftrylockfile
+prev stdio/ftrylockfile.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/ftrylockfile.c
+done ftrylockfile.o generated
+make funlockfile.o
+make stdio/funlockfile.c
+prev stdio/stdhdr.h implicit
+done stdio/funlockfile.c
+meta funlockfile.o %.c>%.o stdio/funlockfile.c funlockfile
+prev stdio/funlockfile.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/funlockfile.c
+done funlockfile.o generated
+make getc.o
+make stdio/getc.c
+prev stdio/stdhdr.h implicit
+done stdio/getc.c
+meta getc.o %.c>%.o stdio/getc.c getc
+prev stdio/getc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/getc.c
+done getc.o generated
+make getchar.o
+make stdio/getchar.c
+prev stdio/stdhdr.h implicit
+done stdio/getchar.c
+meta getchar.o %.c>%.o stdio/getchar.c getchar
+prev stdio/getchar.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/getchar.c
+done getchar.o generated
+make getw.o
+make stdio/getw.c
+prev stdio/stdhdr.h implicit
+done stdio/getw.c
+meta getw.o %.c>%.o stdio/getw.c getw
+prev stdio/getw.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/getw.c
+done getw.o generated
+make pclose.o
+make stdio/pclose.c
+prev stdio/stdhdr.h implicit
+done stdio/pclose.c
+meta pclose.o %.c>%.o stdio/pclose.c pclose
+prev stdio/pclose.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/pclose.c
+done pclose.o generated
+make popen.o
+make stdio/popen.c
+prev stdio/stdhdr.h implicit
+done stdio/popen.c
+meta popen.o %.c>%.o stdio/popen.c popen
+prev stdio/popen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/popen.c
+done popen.o generated
+make printf.o
+make stdio/printf.c
+prev stdio/stdhdr.h implicit
+done stdio/printf.c
+meta printf.o %.c>%.o stdio/printf.c printf
+prev stdio/printf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/printf.c
+done printf.o generated
+make putc.o
+make stdio/putc.c
+prev stdio/stdhdr.h implicit
+done stdio/putc.c
+meta putc.o %.c>%.o stdio/putc.c putc
+prev stdio/putc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/putc.c
+done putc.o generated
+make putchar.o
+make stdio/putchar.c
+prev stdio/stdhdr.h implicit
+done stdio/putchar.c
+meta putchar.o %.c>%.o stdio/putchar.c putchar
+prev stdio/putchar.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/putchar.c
+done putchar.o generated
+make puts.o
+make stdio/puts.c
+prev stdio/stdhdr.h implicit
+done stdio/puts.c
+meta puts.o %.c>%.o stdio/puts.c puts
+prev stdio/puts.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/puts.c
+done puts.o generated
+make putw.o
+make stdio/putw.c
+prev stdio/stdhdr.h implicit
+done stdio/putw.c
+meta putw.o %.c>%.o stdio/putw.c putw
+prev stdio/putw.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/putw.c
+done putw.o generated
+make rewind.o
+make stdio/rewind.c
+prev stdio/stdhdr.h implicit
+done stdio/rewind.c
+meta rewind.o %.c>%.o stdio/rewind.c rewind
+prev stdio/rewind.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/rewind.c
+done rewind.o generated
+make scanf.o
+make stdio/scanf.c
+prev stdio/stdhdr.h implicit
+done stdio/scanf.c
+meta scanf.o %.c>%.o stdio/scanf.c scanf
+prev stdio/scanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/scanf.c
+done scanf.o generated
+make setbuf.o
+make stdio/setbuf.c
+prev stdio/stdhdr.h implicit
+done stdio/setbuf.c
+meta setbuf.o %.c>%.o stdio/setbuf.c setbuf
+prev stdio/setbuf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/setbuf.c
+done setbuf.o generated
+make setbuffer.o
+make stdio/setbuffer.c
+prev stdio/stdhdr.h implicit
+done stdio/setbuffer.c
+meta setbuffer.o %.c>%.o stdio/setbuffer.c setbuffer
+prev stdio/setbuffer.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/setbuffer.c
+done setbuffer.o generated
+make setlinebuf.o
+make stdio/setlinebuf.c
+prev stdio/stdhdr.h implicit
+done stdio/setlinebuf.c
+meta setlinebuf.o %.c>%.o stdio/setlinebuf.c setlinebuf
+prev stdio/setlinebuf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/setlinebuf.c
+done setlinebuf.o generated
+make setvbuf.o
+make stdio/setvbuf.c
+prev stdio/stdhdr.h implicit
+done stdio/setvbuf.c
+meta setvbuf.o %.c>%.o stdio/setvbuf.c setvbuf
+prev stdio/setvbuf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/setvbuf.c
+done setvbuf.o generated
+make snprintf.o
+make stdio/snprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/snprintf.c
+meta snprintf.o %.c>%.o stdio/snprintf.c snprintf
+prev stdio/snprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/snprintf.c
+done snprintf.o generated
+make sprintf.o
+make stdio/sprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/sprintf.c
+meta sprintf.o %.c>%.o stdio/sprintf.c sprintf
+prev stdio/sprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/sprintf.c
+done sprintf.o generated
+make sscanf.o
+make stdio/sscanf.c
+prev stdio/stdhdr.h implicit
+done stdio/sscanf.c
+meta sscanf.o %.c>%.o stdio/sscanf.c sscanf
+prev stdio/sscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/sscanf.c
+done sscanf.o generated
+make asprintf.o
+make stdio/asprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/asprintf.c
+meta asprintf.o %.c>%.o stdio/asprintf.c asprintf
+prev stdio/asprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/asprintf.c
+done asprintf.o generated
+make vasprintf.o
+make stdio/vasprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/vasprintf.c
+meta vasprintf.o %.c>%.o stdio/vasprintf.c vasprintf
+prev stdio/vasprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vasprintf.c
+done vasprintf.o generated
+make tmpfile.o
+make stdio/tmpfile.c
+prev stdio/stdhdr.h implicit
+done stdio/tmpfile.c
+meta tmpfile.o %.c>%.o stdio/tmpfile.c tmpfile
+prev stdio/tmpfile.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/tmpfile.c
+done tmpfile.o generated
+make ungetc.o
+make stdio/ungetc.c
+prev stdio/stdhdr.h implicit
+done stdio/ungetc.c
+meta ungetc.o %.c>%.o stdio/ungetc.c ungetc
+prev stdio/ungetc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/ungetc.c
+done ungetc.o generated
+make vfprintf.o
+make stdio/vfprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/vfprintf.c
+meta vfprintf.o %.c>%.o stdio/vfprintf.c vfprintf
+prev stdio/vfprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vfprintf.c
+done vfprintf.o generated
+make vfscanf.o
+make stdio/vfscanf.c
+prev stdio/stdhdr.h implicit
+done stdio/vfscanf.c
+meta vfscanf.o %.c>%.o stdio/vfscanf.c vfscanf
+prev stdio/vfscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vfscanf.c
+done vfscanf.o generated
+make vprintf.o
+make stdio/vprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/vprintf.c
+meta vprintf.o %.c>%.o stdio/vprintf.c vprintf
+prev stdio/vprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vprintf.c
+done vprintf.o generated
+make vscanf.o
+make stdio/vscanf.c
+prev stdio/stdhdr.h implicit
+done stdio/vscanf.c
+meta vscanf.o %.c>%.o stdio/vscanf.c vscanf
+prev stdio/vscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vscanf.c
+done vscanf.o generated
+make vsnprintf.o
+make stdio/vsnprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/vsnprintf.c
+meta vsnprintf.o %.c>%.o stdio/vsnprintf.c vsnprintf
+prev stdio/vsnprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vsnprintf.c
+done vsnprintf.o generated
+make vsprintf.o
+make stdio/vsprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/vsprintf.c
+meta vsprintf.o %.c>%.o stdio/vsprintf.c vsprintf
+prev stdio/vsprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vsprintf.c
+done vsprintf.o generated
+make vsscanf.o
+make stdio/vsscanf.c
+prev stdio/stdhdr.h implicit
+done stdio/vsscanf.c
+meta vsscanf.o %.c>%.o stdio/vsscanf.c vsscanf
+prev stdio/vsscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vsscanf.c
+done vsscanf.o generated
+make _doprnt.o
+make stdio/_doprnt.c
+prev stdio/stdhdr.h implicit
+done stdio/_doprnt.c
+meta _doprnt.o %.c>%.o stdio/_doprnt.c _doprnt
+prev stdio/_doprnt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_doprnt.c
+done _doprnt.o generated
+make _doscan.o
+make stdio/_doscan.c
+prev stdio/stdhdr.h implicit
+done stdio/_doscan.c
+meta _doscan.o %.c>%.o stdio/_doscan.c _doscan
+prev stdio/_doscan.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_doscan.c
+done _doscan.o generated
+make _filbuf.o
+make stdio/_filbuf.c
+prev stdio/stdhdr.h implicit
+done stdio/_filbuf.c
+meta _filbuf.o %.c>%.o stdio/_filbuf.c _filbuf
+prev stdio/_filbuf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_filbuf.c
+done _filbuf.o generated
+make _flsbuf.o
+make stdio/_flsbuf.c
+prev stdio/stdhdr.h implicit
+done stdio/_flsbuf.c
+meta _flsbuf.o %.c>%.o stdio/_flsbuf.c _flsbuf
+prev stdio/_flsbuf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_flsbuf.c
+done _flsbuf.o generated
+make _stdfun.o
+make stdio/_stdfun.c
+prev stdio/stdhdr.h implicit
+make FEATURE/uwin implicit
+meta FEATURE/uwin features/%>FEATURE/% features/uwin uwin
+make features/uwin
+done features/uwin
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/uwin
+done FEATURE/uwin dontcare generated
+prev uwin.h implicit
+prev include/ast_windows.h implicit
+prev include/ast.h implicit
+done stdio/_stdfun.c
+meta _stdfun.o %.c>%.o stdio/_stdfun.c _stdfun
+prev stdio/_stdfun.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_stdfun.c
+done _stdfun.o generated
+make _stdopen.o
+make stdio/_stdopen.c
+prev stdio/stdhdr.h implicit
+done stdio/_stdopen.c
+meta _stdopen.o %.c>%.o stdio/_stdopen.c _stdopen
+prev stdio/_stdopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_stdopen.c
+done _stdopen.o generated
+make _stdprintf.o
+make stdio/_stdprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/_stdprintf.c
+meta _stdprintf.o %.c>%.o stdio/_stdprintf.c _stdprintf
+prev stdio/_stdprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_stdprintf.c
+done _stdprintf.o generated
+make _stdscanf.o
+make stdio/_stdscanf.c
+prev stdio/stdhdr.h implicit
+done stdio/_stdscanf.c
+meta _stdscanf.o %.c>%.o stdio/_stdscanf.c _stdscanf
+prev stdio/_stdscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_stdscanf.c
+done _stdscanf.o generated
+make _stdsprnt.o
+make stdio/_stdsprnt.c
+prev stdio/stdhdr.h implicit
+done stdio/_stdsprnt.c
+meta _stdsprnt.o %.c>%.o stdio/_stdsprnt.c _stdsprnt
+prev stdio/_stdsprnt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_stdsprnt.c
+done _stdsprnt.o generated
+make _stdvbuf.o
+make stdio/_stdvbuf.c
+prev stdio/stdhdr.h implicit
+done stdio/_stdvbuf.c
+meta _stdvbuf.o %.c>%.o stdio/_stdvbuf.c _stdvbuf
+prev stdio/_stdvbuf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_stdvbuf.c
+done _stdvbuf.o generated
+make _stdvsnprnt.o
+make stdio/_stdvsnprnt.c
+prev stdio/stdhdr.h implicit
+done stdio/_stdvsnprnt.c
+meta _stdvsnprnt.o %.c>%.o stdio/_stdvsnprnt.c _stdvsnprnt
+prev stdio/_stdvsnprnt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_stdvsnprnt.c
+done _stdvsnprnt.o generated
+make _stdvsprnt.o
+make stdio/_stdvsprnt.c
+prev stdio/stdhdr.h implicit
+done stdio/_stdvsprnt.c
+meta _stdvsprnt.o %.c>%.o stdio/_stdvsprnt.c _stdvsprnt
+prev stdio/_stdvsprnt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_stdvsprnt.c
+done _stdvsprnt.o generated
+make _stdvsscn.o
+make stdio/_stdvsscn.c
+prev stdio/stdhdr.h implicit
+done stdio/_stdvsscn.c
+meta _stdvsscn.o %.c>%.o stdio/_stdvsscn.c _stdvsscn
+prev stdio/_stdvsscn.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/_stdvsscn.c
+done _stdvsscn.o generated
+make fgetwc.o
+make stdio/fgetwc.c
+prev stdio/stdhdr.h implicit
+done stdio/fgetwc.c
+meta fgetwc.o %.c>%.o stdio/fgetwc.c fgetwc
+prev stdio/fgetwc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fgetwc.c
+done fgetwc.o generated
+make fwprintf.o
+make stdio/fwprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/fwprintf.c
+meta fwprintf.o %.c>%.o stdio/fwprintf.c fwprintf
+prev stdio/fwprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fwprintf.c
+done fwprintf.o generated
+make putwchar.o
+make stdio/putwchar.c
+prev ast_wchar.h implicit
+prev stdio/stdhdr.h implicit
+done stdio/putwchar.c
+meta putwchar.o %.c>%.o stdio/putwchar.c putwchar
+prev stdio/putwchar.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/putwchar.c
+done putwchar.o generated
+make vfwscanf.o
+make stdio/vfwscanf.c
+prev stdio/stdhdr.h implicit
+done stdio/vfwscanf.c
+meta vfwscanf.o %.c>%.o stdio/vfwscanf.c vfwscanf
+prev stdio/vfwscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vfwscanf.c
+done vfwscanf.o generated
+make wprintf.o
+make stdio/wprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/wprintf.c
+meta wprintf.o %.c>%.o stdio/wprintf.c wprintf
+prev stdio/wprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/wprintf.c
+done wprintf.o generated
+make fgetws.o
+make stdio/fgetws.c
+prev stdio/stdhdr.h implicit
+done stdio/fgetws.c
+meta fgetws.o %.c>%.o stdio/fgetws.c fgetws
+prev stdio/fgetws.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fgetws.c
+done fgetws.o generated
+make fwscanf.o
+make stdio/fwscanf.c
+prev stdio/stdhdr.h implicit
+done stdio/fwscanf.c
+meta fwscanf.o %.c>%.o stdio/fwscanf.c fwscanf
+prev stdio/fwscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fwscanf.c
+done fwscanf.o generated
+make swprintf.o
+make stdio/swprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/swprintf.c
+meta swprintf.o %.c>%.o stdio/swprintf.c swprintf
+prev stdio/swprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/swprintf.c
+done swprintf.o generated
+make vswprintf.o
+make stdio/vswprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/vswprintf.c
+meta vswprintf.o %.c>%.o stdio/vswprintf.c vswprintf
+prev stdio/vswprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vswprintf.c
+done vswprintf.o generated
+make wscanf.o
+make stdio/wscanf.c
+prev stdio/stdhdr.h implicit
+done stdio/wscanf.c
+meta wscanf.o %.c>%.o stdio/wscanf.c wscanf
+prev stdio/wscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/wscanf.c
+done wscanf.o generated
+make fputwc.o
+make stdio/fputwc.c
+prev stdio/stdhdr.h implicit
+done stdio/fputwc.c
+meta fputwc.o %.c>%.o stdio/fputwc.c fputwc
+prev stdio/fputwc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fputwc.c
+done fputwc.o generated
+make getwc.o
+make stdio/getwc.c
+prev ast_wchar.h implicit
+prev stdio/stdhdr.h implicit
+done stdio/getwc.c
+meta getwc.o %.c>%.o stdio/getwc.c getwc
+prev stdio/getwc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/getwc.c
+done getwc.o generated
+make swscanf.o
+make stdio/swscanf.c
+prev stdio/stdhdr.h implicit
+done stdio/swscanf.c
+meta swscanf.o %.c>%.o stdio/swscanf.c swscanf
+prev stdio/swscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/swscanf.c
+done swscanf.o generated
+make vswscanf.o
+make stdio/vswscanf.c
+prev stdio/stdhdr.h implicit
+done stdio/vswscanf.c
+meta vswscanf.o %.c>%.o stdio/vswscanf.c vswscanf
+prev stdio/vswscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vswscanf.c
+done vswscanf.o generated
+make fputws.o
+make stdio/fputws.c
+prev stdio/stdhdr.h implicit
+done stdio/fputws.c
+meta fputws.o %.c>%.o stdio/fputws.c fputws
+prev stdio/fputws.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fputws.c
+done fputws.o generated
+make getwchar.o
+make stdio/getwchar.c
+prev ast_wchar.h implicit
+prev stdio/stdhdr.h implicit
+done stdio/getwchar.c
+meta getwchar.o %.c>%.o stdio/getwchar.c getwchar
+prev stdio/getwchar.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/getwchar.c
+done getwchar.o generated
+make ungetwc.o
+make stdio/ungetwc.c
+prev stdio/stdhdr.h implicit
+done stdio/ungetwc.c
+meta ungetwc.o %.c>%.o stdio/ungetwc.c ungetwc
+prev stdio/ungetwc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/ungetwc.c
+done ungetwc.o generated
+make vwprintf.o
+make stdio/vwprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/vwprintf.c
+meta vwprintf.o %.c>%.o stdio/vwprintf.c vwprintf
+prev stdio/vwprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vwprintf.c
+done vwprintf.o generated
+make fwide.o
+make stdio/fwide.c
+prev stdio/stdhdr.h implicit
+done stdio/fwide.c
+meta fwide.o %.c>%.o stdio/fwide.c fwide
+prev stdio/fwide.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fwide.c
+done fwide.o generated
+make putwc.o
+make stdio/putwc.c
+prev ast_wchar.h implicit
+prev stdio/stdhdr.h implicit
+done stdio/putwc.c
+meta putwc.o %.c>%.o stdio/putwc.c putwc
+prev stdio/putwc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/putwc.c
+done putwc.o generated
+make vfwprintf.o
+make stdio/vfwprintf.c
+prev stdio/stdhdr.h implicit
+done stdio/vfwprintf.c
+meta vfwprintf.o %.c>%.o stdio/vfwprintf.c vfwprintf
+prev stdio/vfwprintf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vfwprintf.c
+done vfwprintf.o generated
+make vwscanf.o
+make stdio/vwscanf.c
+prev stdio/stdhdr.h implicit
+done stdio/vwscanf.c
+meta vwscanf.o %.c>%.o stdio/vwscanf.c vwscanf
+prev stdio/vwscanf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/vwscanf.c
+done vwscanf.o generated
+make stdio_c99.o
+make stdio/stdio_c99.c
+prev stdio/stdhdr.h implicit
+done stdio/stdio_c99.c
+meta stdio_c99.o %.c>%.o stdio/stdio_c99.c stdio_c99
+prev stdio/stdio_c99.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/stdio_c99.c
+done stdio_c99.o generated
+make fcloseall.o
+make stdio/fcloseall.c
+prev stdio/stdhdr.h implicit
+done stdio/fcloseall.c
+meta fcloseall.o %.c>%.o stdio/fcloseall.c fcloseall
+prev stdio/fcloseall.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fcloseall.c
+done fcloseall.o generated
+make fmemopen.o
+make stdio/fmemopen.c
+prev stdio/stdhdr.h implicit
+done stdio/fmemopen.c
+meta fmemopen.o %.c>%.o stdio/fmemopen.c fmemopen
+prev stdio/fmemopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/fmemopen.c
+done fmemopen.o generated
+make getdelim.o
+make stdio/getdelim.c
+prev stdio/stdhdr.h implicit
+done stdio/getdelim.c
+meta getdelim.o %.c>%.o stdio/getdelim.c getdelim
+prev stdio/getdelim.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/getdelim.c
+done getdelim.o generated
+make getline.o
+make stdio/getline.c
+prev stdio/stdhdr.h implicit
+done stdio/getline.c
+meta getline.o %.c>%.o stdio/getline.c getline
+prev stdio/getline.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Istdio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c stdio/getline.c
+done getline.o generated
+make frexp.o
+make comp/frexp.c
+prev FEATURE/float implicit
+prev include/ast.h implicit
+done comp/frexp.c
+meta frexp.o %.c>%.o comp/frexp.c frexp
+prev comp/frexp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/frexp.c
+done frexp.o generated
+make frexpl.o
+make comp/frexpl.c
+prev FEATURE/float implicit
+prev include/ast.h implicit
+done comp/frexpl.c
+meta frexpl.o %.c>%.o comp/frexpl.c frexpl
+prev comp/frexpl.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/frexpl.c
+done frexpl.o generated
+make astcopy.o
+make port/astcopy.c
+prev include/ls.h implicit
+make ast_mmap.h implicit
+prev FEATURE/mmap
+exec - cmp 2>/dev/null -s FEATURE/mmap ast_mmap.h || { rm -f ast_mmap.h; silent test -d . || mkdir .; ${STDCP} FEATURE/mmap ast_mmap.h; }
+done ast_mmap.h generated
+prev include/ast.h implicit
+done port/astcopy.c
+meta astcopy.o %.c>%.o port/astcopy.c astcopy
+prev port/astcopy.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c port/astcopy.c
+done astcopy.o generated
+make astconf.o
+make port/astconf.c
+make FEATURE/libpath implicit
+meta FEATURE/libpath features/%.sh>FEATURE/% features/libpath.sh libpath
+make features/libpath.sh
+done features/libpath.sh
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/libpath.sh
+done FEATURE/libpath generated
+make conftab.h implicit
+done conftab.h
+prev include/ls.h implicit
+prev include/proc.h implicit
+prev include/regex.h implicit
+prev include/fs3d.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+prev misc/univlib.h implicit
+done port/astconf.c
+meta astconf.o %.c>%.o port/astconf.c astconf
+prev port/astconf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Imisc -Iinclude -Istd -D__OBSOLETE__=20110101 -DCONF_LIBSUFFIX=\""${mam_cc_SUFFIX_DYNAMIC-${mam_cc_SUFFIX_SHARED}}"\" -DCONF_LIBPREFIX=\""${mam_cc_PREFIX_DYNAMIC-${mam_cc_PREFIX_SHARED}}"\" -DHOSTTYPE=\""${mam_cc_HOSTTYPE}"\" -D_PACKAGE_ast -c port/astconf.c
+done astconf.o generated
+make astdynamic.o
+make port/astdynamic.c
+prev sfio/sfhdr.h implicit
+prev include/ast_windows.h implicit
+prev include/ast.h implicit
+prev include/sfio_t.h implicit
+done port/astdynamic.c
+meta astdynamic.o %.c>%.o port/astdynamic.c astdynamic
+prev port/astdynamic.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iport -Isfio -Iinclude -Istd -I${INSTALLROOT}/include -D_PACKAGE_ast -c port/astdynamic.c
+done astdynamic.o generated
+make astlicense.o
+make port/astlicense.c
+prev include/ast.h implicit
+done port/astlicense.c
+meta astlicense.o %.c>%.o port/astlicense.c astlicense
+prev port/astlicense.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c port/astlicense.c
+done astlicense.o generated
+make astquery.o
+make port/astquery.c
+prev include/error.h implicit
+prev include/ast.h implicit
+done port/astquery.c
+meta astquery.o %.c>%.o port/astquery.c astquery
+prev port/astquery.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c port/astquery.c
+done astquery.o generated
+make astwinsize.o
+make port/astwinsize.c
+make jioctl.h implicit
+done jioctl.h dontcare virtual
+prev ast_tty.h implicit
+prev include/ast.h implicit
+done port/astwinsize.c
+meta astwinsize.o %.c>%.o port/astwinsize.c astwinsize
+prev port/astwinsize.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c port/astwinsize.c
+done astwinsize.o generated
+make conftab.o
+make conftab.c
+prev conftab.h implicit
+prev FEATURE/param implicit
+prev FEATURE/common implicit
+prev FEATURE/standards implicit
+done conftab.c
+meta conftab.o %.c>%.o conftab.c conftab
+prev conftab.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c conftab.c
+done conftab.o generated
+make aststatic.o
+make port/aststatic.c
+prev include/ast.h implicit
+done port/aststatic.c
+meta aststatic.o %.c>%.o port/aststatic.c aststatic
+prev port/aststatic.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c port/aststatic.c
+done aststatic.o generated
+make getopt.o
+make comp/getopt.c
+prev include/option.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+done comp/getopt.c
+meta getopt.o %.c>%.o comp/getopt.c getopt
+prev comp/getopt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/getopt.c
+done getopt.o generated
+make getoptl.o
+make comp/getoptl.c
+prev comp/getopt.h implicit
+prev include/option.h implicit
+prev include/error.h implicit
+prev include/ast_getopt.h implicit
+prev include/ast.h implicit
+done comp/getoptl.c
+meta getoptl.o %.c>%.o comp/getoptl.c getoptl
+prev comp/getoptl.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c comp/getoptl.c
+done getoptl.o generated
+make aso.o
+make aso/aso.c
+prev std/stdio.h implicit
+make aso/asohdr.h implicit
+prev include/aso.h implicit
+prev FEATURE/aso implicit
+make include/fnv.h implicit
+prev ast_common.h implicit
+done include/fnv.h dontcare
+prev include/error.h implicit
+prev include/ast.h implicit
+done aso/asohdr.h
+done aso/aso.c
+meta aso.o %.c>%.o aso/aso.c aso
+prev aso/aso.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iaso -Icomp -Iinclude -Istd -D_PACKAGE_ast -c aso/aso.c
+done aso.o generated
+make asolock.o
+make aso/asolock.c
+prev aso/asohdr.h implicit
+done aso/asolock.c
+meta asolock.o %.c>%.o aso/asolock.c asolock
+prev aso/asolock.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iaso -Icomp -Iinclude -Istd -D_PACKAGE_ast -c aso/asolock.c
+done asolock.o generated
+make asometh.o
+make aso/asometh.c
+prev aso/asohdr.h implicit
+done aso/asometh.c
+meta asometh.o %.c>%.o aso/asometh.c asometh
+prev aso/asometh.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iaso -Icomp -Iinclude -Istd -D_PACKAGE_ast -c aso/asometh.c
+done asometh.o generated
+make asorelax.o
+make aso/asorelax.c
+prev tv.h implicit
+prev aso/asohdr.h implicit
+done aso/asorelax.c
+meta asorelax.o %.c>%.o aso/asorelax.c asorelax
+prev aso/asorelax.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iaso -Icomp -Iinclude -Istd -D_PACKAGE_ast -c aso/asorelax.c
+done asorelax.o generated
+make aso-sem.o
+make aso/aso-sem.c
+prev aso/asohdr.h implicit
+done aso/aso-sem.c
+meta aso-sem.o %.c>%.o aso/aso-sem.c aso-sem
+prev aso/aso-sem.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iaso -Icomp -Iinclude -Istd -D_PACKAGE_ast -c aso/aso-sem.c
+done aso-sem.o generated
+make aso-fcntl.o
+make aso/aso-fcntl.c
+prev aso/asohdr.h implicit
+done aso/aso-fcntl.c
+meta aso-fcntl.o %.c>%.o aso/aso-fcntl.c aso-fcntl
+prev aso/aso-fcntl.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iaso -Icomp -Iinclude -Istd -D_PACKAGE_ast -c aso/aso-fcntl.c
+done aso-fcntl.o generated
+make vmbest.o
+make vmalloc/vmbest.c
+prev windows.h implicit
+prev include/ast_windows.h implicit
+make vmalloc/vmhdr.h implicit
+prev include/vmalloc.h implicit
+prev include/ast_windows.h implicit
+prev include/aso.h implicit
+prev FEATURE/vmalloc implicit
+prev ast_common.h implicit
+prev include/ast.h implicit
+done vmalloc/vmhdr.h dontcare
+done vmalloc/vmbest.c
+meta vmbest.o %.c>%.o vmalloc/vmbest.c vmbest
+prev vmalloc/vmbest.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmbest.c
+done vmbest.o generated
+make vmclear.o
+make vmalloc/vmclear.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmclear.c
+meta vmclear.o %.c>%.o vmalloc/vmclear.c vmclear
+prev vmalloc/vmclear.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmclear.c
+done vmclear.o generated
+make vmclose.o
+make vmalloc/vmclose.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmclose.c
+meta vmclose.o %.c>%.o vmalloc/vmclose.c vmclose
+prev vmalloc/vmclose.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmclose.c
+done vmclose.o generated
+make vmdcheap.o
+make vmalloc/vmdcheap.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmdcheap.c
+meta vmdcheap.o %.c>%.o vmalloc/vmdcheap.c vmdcheap
+prev vmalloc/vmdcheap.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmdcheap.c
+done vmdcheap.o generated
+make vmdebug.o
+make vmalloc/vmdebug.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmdebug.c
+meta vmdebug.o %.c>%.o vmalloc/vmdebug.c vmdebug
+prev vmalloc/vmdebug.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmdebug.c
+done vmdebug.o generated
+make vmdisc.o
+make vmalloc/vmdisc.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmdisc.c
+meta vmdisc.o %.c>%.o vmalloc/vmdisc.c vmdisc
+prev vmalloc/vmdisc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmdisc.c
+done vmdisc.o generated
+make vmexit.o
+make vmalloc/vmexit.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmexit.c
+meta vmexit.o %.c>%.o vmalloc/vmexit.c vmexit
+prev vmalloc/vmexit.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmexit.c
+done vmexit.o generated
+make vmlast.o
+make vmalloc/vmlast.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmlast.c
+meta vmlast.o %.c>%.o vmalloc/vmlast.c vmlast
+prev vmalloc/vmlast.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmlast.c
+done vmlast.o generated
+make vmopen.o
+make vmalloc/vmopen.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmopen.c
+meta vmopen.o %.c>%.o vmalloc/vmopen.c vmopen
+prev vmalloc/vmopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmopen.c
+done vmopen.o generated
+make vmpool.o
+make vmalloc/vmpool.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmpool.c
+meta vmpool.o %.c>%.o vmalloc/vmpool.c vmpool
+prev vmalloc/vmpool.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmpool.c
+done vmpool.o generated
+make vmprivate.o
+make vmalloc/vmprivate.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmprivate.c
+meta vmprivate.o %.c>%.o vmalloc/vmprivate.c vmprivate
+prev vmalloc/vmprivate.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmprivate.c
+done vmprivate.o generated
+make vmprofile.o
+make vmalloc/vmprofile.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmprofile.c
+meta vmprofile.o %.c>%.o vmalloc/vmprofile.c vmprofile
+prev vmalloc/vmprofile.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmprofile.c
+done vmprofile.o generated
+make vmregion.o
+make vmalloc/vmregion.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmregion.c
+meta vmregion.o %.c>%.o vmalloc/vmregion.c vmregion
+prev vmalloc/vmregion.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmregion.c
+done vmregion.o generated
+make vmsegment.o
+make vmalloc/vmsegment.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmsegment.c
+meta vmsegment.o %.c>%.o vmalloc/vmsegment.c vmsegment
+prev vmalloc/vmsegment.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmsegment.c
+done vmsegment.o generated
+make vmset.o
+make vmalloc/vmset.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmset.c
+meta vmset.o %.c>%.o vmalloc/vmset.c vmset
+prev vmalloc/vmset.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmset.c
+done vmset.o generated
+make vmstat.o
+make vmalloc/vmstat.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmstat.c
+meta vmstat.o %.c>%.o vmalloc/vmstat.c vmstat
+prev vmalloc/vmstat.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmstat.c
+done vmstat.o generated
+make vmstrdup.o
+make vmalloc/vmstrdup.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmstrdup.c
+meta vmstrdup.o %.c>%.o vmalloc/vmstrdup.c vmstrdup
+prev vmalloc/vmstrdup.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmstrdup.c
+done vmstrdup.o generated
+make vmtrace.o
+make vmalloc/vmtrace.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmtrace.c
+meta vmtrace.o %.c>%.o vmalloc/vmtrace.c vmtrace
+prev vmalloc/vmtrace.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmtrace.c
+done vmtrace.o generated
+make vmwalk.o
+make vmalloc/vmwalk.c
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmwalk.c
+meta vmwalk.o %.c>%.o vmalloc/vmwalk.c vmwalk
+prev vmalloc/vmwalk.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmwalk.c
+done vmwalk.o generated
+make vmmopen.o
+make vmalloc/vmmopen.c
+prev std/stdio.h implicit
+prev vmalloc/vmhdr.h implicit
+done vmalloc/vmmopen.c
+meta vmmopen.o %.c>%.o vmalloc/vmmopen.c vmmopen
+prev vmalloc/vmmopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmmopen.c
+done vmmopen.o generated
+make malloc.o
+make vmalloc/malloc.c
+prev include/ast_windows.h implicit
+prev vmalloc/vmhdr.h implicit
+done vmalloc/malloc.c
+meta malloc.o %.c>%.o vmalloc/malloc.c malloc
+prev vmalloc/malloc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Ivmalloc -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/malloc.c
+done malloc.o generated
+make vmgetmem.o
+make vmalloc/vmgetmem.c
+prev include/vmalloc.h implicit
+done vmalloc/vmgetmem.c
+meta vmgetmem.o %.c>%.o vmalloc/vmgetmem.c vmgetmem
+prev vmalloc/vmgetmem.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c vmalloc/vmgetmem.c
+done vmgetmem.o generated
+make a64l.o
+make uwin/a64l.c
+prev FEATURE/uwin implicit
+done uwin/a64l.c
+meta a64l.o %.c>%.o uwin/a64l.c a64l
+prev uwin/a64l.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Istd -c uwin/a64l.c
+done a64l.o generated
+make acosh.o
+make uwin/acosh.c
+make uwin/mathimpl.h implicit
+done uwin/mathimpl.h dontcare
+prev FEATURE/uwin implicit
+done uwin/acosh.c
+meta acosh.o %.c>%.o uwin/acosh.c acosh
+prev uwin/acosh.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/acosh.c
+done acosh.o generated
+make asinh.o
+make uwin/asinh.c
+prev uwin/mathimpl.h implicit
+prev FEATURE/uwin implicit
+done uwin/asinh.c
+meta asinh.o %.c>%.o uwin/asinh.c asinh
+prev uwin/asinh.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/asinh.c
+done asinh.o generated
+make atanh.o
+make uwin/atanh.c
+prev uwin/mathimpl.h implicit
+prev FEATURE/uwin implicit
+done uwin/atanh.c
+meta atanh.o %.c>%.o uwin/atanh.c atanh
+prev uwin/atanh.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/atanh.c
+done atanh.o generated
+make cbrt.o
+make uwin/cbrt.c
+prev uwin/mathimpl.h implicit
+prev FEATURE/uwin implicit
+done uwin/cbrt.c
+meta cbrt.o %.c>%.o uwin/cbrt.c cbrt
+prev uwin/cbrt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/cbrt.c
+done cbrt.o generated
+make crypt.o
+make uwin/crypt.c
+prev std/stdio.h implicit
+prev FEATURE/uwin implicit
+done uwin/crypt.c
+meta crypt.o %.c>%.o uwin/crypt.c crypt
+prev uwin/crypt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c uwin/crypt.c
+done crypt.o generated
+make erf.o
+make uwin/erf.c
+prev uwin/mathimpl.h implicit
+make ieee_libm.h implicit
+done ieee_libm.h dontcare virtual
+prev FEATURE/uwin implicit
+done uwin/erf.c
+meta erf.o %.c>%.o uwin/erf.c erf
+prev uwin/erf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/erf.c
+done erf.o generated
+make err.o
+make uwin/err.c
+prev windows.h implicit
+prev include/error.h implicit
+prev include/ast.h implicit
+prev FEATURE/uwin implicit
+done uwin/err.c
+meta err.o %.c>%.o uwin/err.c err
+prev uwin/err.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c uwin/err.c
+done err.o generated
+make exp.o
+make uwin/exp.c
+prev uwin/mathimpl.h implicit
+prev FEATURE/uwin implicit
+done uwin/exp.c
+meta exp.o %.c>%.o uwin/exp.c exp
+prev uwin/exp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/exp.c
+done exp.o generated
+make exp__E.o
+make uwin/exp__E.c
+prev uwin/mathimpl.h implicit
+prev FEATURE/uwin implicit
+done uwin/exp__E.c
+meta exp__E.o %.c>%.o uwin/exp__E.c exp__E
+prev uwin/exp__E.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/exp__E.c
+done exp__E.o generated
+make expm1.o
+make uwin/expm1.c
+prev uwin/mathimpl.h implicit
+prev FEATURE/uwin implicit
+done uwin/expm1.c
+meta expm1.o %.c>%.o uwin/expm1.c expm1
+prev uwin/expm1.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/expm1.c
+done expm1.o generated
+make gamma.o
+make uwin/gamma.c
+prev uwin/mathimpl.h implicit
+prev FEATURE/uwin implicit
+done uwin/gamma.c
+meta gamma.o %.c>%.o uwin/gamma.c gamma
+prev uwin/gamma.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/gamma.c
+done gamma.o generated
+make getpass.o
+make uwin/getpass.c
+prev include/ast.h implicit
+prev FEATURE/uwin implicit
+done uwin/getpass.c
+meta getpass.o %.c>%.o uwin/getpass.c getpass
+prev uwin/getpass.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c uwin/getpass.c
+done getpass.o generated
+make lgamma.o
+make uwin/lgamma.c
+prev uwin/mathimpl.h implicit
+prev FEATURE/uwin implicit
+done uwin/lgamma.c
+meta lgamma.o %.c>%.o uwin/lgamma.c lgamma
+prev uwin/lgamma.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/lgamma.c
+done lgamma.o generated
+make log.o
+make uwin/log.c
+prev uwin/mathimpl.h implicit
+prev FEATURE/uwin implicit
+done uwin/log.c
+meta log.o %.c>%.o uwin/log.c log
+prev uwin/log.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/log.c
+done log.o generated
+make log1p.o
+make uwin/log1p.c
+prev uwin/mathimpl.h implicit
+prev FEATURE/uwin implicit
+done uwin/log1p.c
+meta log1p.o %.c>%.o uwin/log1p.c log1p
+prev uwin/log1p.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/log1p.c
+done log1p.o generated
+make log__L.o
+make uwin/log__L.c
+prev uwin/mathimpl.h implicit
+prev FEATURE/uwin implicit
+done uwin/log__L.c
+meta log__L.o %.c>%.o uwin/log__L.c log__L
+prev uwin/log__L.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/log__L.c
+done log__L.o generated
+make rand48.o
+make uwin/rand48.c
+prev FEATURE/uwin implicit
+done uwin/rand48.c
+meta rand48.o %.c>%.o uwin/rand48.c rand48
+prev uwin/rand48.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Istd -c uwin/rand48.c
+done rand48.o generated
+make random.o
+make uwin/random.c
+prev FEATURE/uwin implicit
+done uwin/random.c
+meta random.o %.c>%.o uwin/random.c random
+prev uwin/random.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Istd -c uwin/random.c
+done random.o generated
+make rcmd.o
+make uwin/rcmd.c
+prev std/nl_types.h implicit
+make uwin/rlib.h implicit
+prev std/endian.h implicit
+prev std/stdio.h implicit
+prev std/stdio.h implicit
+prev include/ast_std.h implicit
+done uwin/rlib.h dontcare
+prev FEATURE/uwin implicit
+done uwin/rcmd.c
+meta rcmd.o %.c>%.o uwin/rcmd.c rcmd
+prev uwin/rcmd.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iuwin -Iinclude -Istd -c uwin/rcmd.c
+done rcmd.o generated
+make rint.o
+make uwin/rint.c
+prev FEATURE/uwin implicit
+done uwin/rint.c
+meta rint.o %.c>%.o uwin/rint.c rint
+prev uwin/rint.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Istd -c uwin/rint.c
+done rint.o generated
+make support.o
+make uwin/support.c
+prev uwin/mathimpl.h implicit
+prev FEATURE/uwin implicit
+done uwin/support.c
+meta support.o %.c>%.o uwin/support.c support
+prev uwin/support.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iuwin -Istd -c uwin/support.c
+done support.o generated
+make sfstrtmp.o
+make disc/sfstrtmp.c
+prev include/ast.h implicit
+prev include/sfio_t.h implicit
+done disc/sfstrtmp.c
+meta sfstrtmp.o %.c>%.o disc/sfstrtmp.c sfstrtmp
+prev disc/sfstrtmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D__OBSOLETE__=20110101 -D_PACKAGE_ast -c disc/sfstrtmp.c
+done sfstrtmp.o generated
+make spawn.o
+make obsolete/spawn.c
+prev include/error.h implicit
+prev include/ast.h implicit
+prev ast_lib.h implicit
+done obsolete/spawn.c
+meta spawn.o %.c>%.o obsolete/spawn.c spawn
+prev obsolete/spawn.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -D_PACKAGE_ast -c obsolete/spawn.c
+done spawn.o generated
+exec - ${AR} rc libast.a state.o transition.o opendir.o readdir.o rewinddir.o seekdir.o telldir.o getcwd.o fastfind.o hashalloc.o hashdump.o hashfree.o hashlast.o hashlook.o hashscan.o hashsize.o hashview.o hashwalk.o memhash.o memsum.o strhash.o strkey.o strsum.o stracmp.o strnacmp.o ccmap.o ccmapid.o ccnative.o chresc.o chrtoi.o
+exec - ${AR} rc libast.a streval.o strexpr.o strmatch.o strcopy.o modei.o modex.o strmode.o strlcat.o strlcpy.o strlook.o strncopy.o strsearch.o strpsearch.o stresc.o stropt.o strtape.o strpcmp.o strnpcmp.o strvcmp.o strnvcmp.o tok.o tokline.o tokscan.o pathaccess.o pathcat.o pathcanon.o pathcheck.o pathpath.o pathexists.o pathfind.o pathkey.o pathprobe.o pathrepl.o pathnative.o pathposix.o pathtemp.o pathtmp.o pathstat.o pathgetlink.o pathsetlink.o pathbin.o pathshell.o pathcd.o pathprog.o fs3d.o ftwalk.o ftwflags.o fts.o astintercept.o conformance.o getenv.o setenviron.o optget.o optjoin.o optesc.o optctx.o strsort.o struniq.o magic.o mime.o mimetype.o signal.o sigflag.o systrace.o error.o errorf.o errormsg.o errorx.o localeconv.o setlocale.o translate.o catopen.o iconv.o lc.o lctab.o mc.o base64.o recfmt.o recstr.o reclen.o fmtrec.o fmtbase.o fmtbuf.o fmtclock.o fmtdev.o fmtelapsed.o fmterror.o fmtesc.o fmtfmt.o fmtfs.o fmtident.o fmtint.o fmtip4.o fmtip6.o fmtls.o fmtmatch.o fmtmode.o fmtnum.o fmtperm.o fmtre.o fmttime.o
+exec - ${AR} rc libast.a fmtuid.o fmtgid.o fmtsignal.o fmtscale.o fmttmx.o fmttv.o fmtversion.o strelapsed.o strperm.o struid.o strgid.o strtoip4.o strtoip6.o stack.o stk.o swapget.o swapmem.o swapop.o swapput.o sigdata.o sigcrit.o sigunblock.o procopen.o procclose.o procrun.o procfree.o tmdate.o tmequiv.o tmfix.o tmfmt.o tmform.o tmgoff.o tminit.o tmleap.o tmlex.o tmlocale.o tmmake.o tmpoff.o tmscan.o tmsleep.o tmtime.o tmtype.o tmweek.o tmword.o tmzone.o tmxdate.o tmxduration.o tmxfmt.o tmxgettime.o tmxleap.o tmxmake.o tmxscan.o tmxsettime.o tmxsleep.o tmxtime.o tmxtouch.o tvcmp.o tvgettime.o tvsettime.o tvsleep.o tvtouch.o cmdarg.o vecargs.o vecfile.o vecfree.o vecload.o vecstring.o univdata.o touch.o mnt.o debug.o memccpy.o memchr.o memcmp.o memcpy.o memdup.o memmove.o memset.o mkdir.o mkfifo.o mknod.o rmdir.o remove.o rename.o link.o unlink.o strdup.o strchr.o strrchr.o strstr.o strtod.o strtold.o strtol.o strtoll.o strtoul.o strtoull.o strton.o strtonll.o strntod.o strntold.o strnton.o
+exec - ${AR} rc libast.a strntonll.o strntol.o strntoll.o strntoul.o strntoull.o strcasecmp.o strncasecmp.o strerror.o mktemp.o tmpnam.o fsync.o execlp.o execve.o execvp.o execvpe.o spawnveg.o vfork.o killpg.o hsearch.o tsearch.o getlogin.o putenv.o setenv.o unsetenv.o lstat.o statvfs.o eaccess.o gross.o omitted.o readlink.o symlink.o getpgrp.o setpgid.o setsid.o waitpid.o creat64.o fcntl.o open.o atexit.o getdents.o getwd.o dup2.o errno.o getpreroot.o ispreroot.o realopen.o setpreroot.o getgroups.o mount.o system.o iblocks.o modedata.o tmdata.o memfatal.o sfkeyprintf.o sfdcdio.o sfdcdos.o sfdcfilter.o sfdcseekable.o sfdcslow.o sfdcsubstr.o sfdctee.o sfdcunion.o sfdcmore.o sfdcprefix.o wc.o wc2utf8.o basename.o closelog.o dirname.o fmtmsglib.o fnmatch.o ftw.o getdate.o getsubopt.o glob.o nftw.o openlog.o re_comp.o resolvepath.o realpath.o regcmp.o regexp.o setlogmask.o strftime.o strptime.o swab.o syslog.o tempnam.o wordexp.o mktime.o regalloc.o regclass.o regcoll.o regcomp.o regcache.o regdecomp.o regerror.o regexec.o regfatal.o reginit.o
+exec - ${AR} rc libast.a regnexec.o regsubcomp.o regsubexec.o regsub.o regrecord.o regrexec.o regstat.o dtclose.o dtdisc.o dthash.o dtlist.o dtmethod.o dtopen.o dtstrhash.o dttree.o dtview.o dtwalk.o dtnew.o dtcomp.o sfclose.o sfclrlock.o sfdisc.o sfdlen.o sfexcept.o sfgetl.o sfgetu.o sfcvt.o sfecvt.o sffcvt.o sfextern.o sffilbuf.o sfflsbuf.o sfprints.o sfgetd.o sfgetr.o sfllen.o sfmode.o sfmove.o sfnew.o sfpkrd.o sfnotify.o sfnputc.o sfopen.o sfpeek.o sfpoll.o sfpool.o sfpopen.o sfprintf.o sfputd.o sfputl.o sfputr.o sfputu.o sfrd.o sfread.o sfreserve.o sfscanf.o sfseek.o sfset.o sfsetbuf.o sfsetfd.o sfsize.o sfsk.o sfstack.o sfstrtod.o sfsync.o sfswap.o sftable.o sftell.o sftmp.o sfungetc.o sfvprintf.o sfvscanf.o sfwr.o sfwrite.o sfpurge.o sfraise.o sfwalk.o sfgetm.o sfmutex.o sfputm.o sfresize.o _sfclrerr.o _sfeof.o _sferror.o _sffileno.o _sfopen.o _sfstacked.o _sfvalue.o _sfgetc.o _sfgetl.o _sfgetl2.o _sfgetu.o _sfgetu2.o _sfdlen.o _sfllen.o _sfslen.o _sfulen.o _sfputc.o _sfputd.o _sfputl.o _sfputm.o
+exec - ${AR} rc libast.a _sfputu.o clearerr.o fclose.o fdopen.o feof.o ferror.o fflush.o fgetc.o fgetpos.o fgets.o fileno.o fopen.o fprintf.o fpurge.o fputc.o fputs.o fread.o freopen.o fscanf.o fseek.o fseeko.o fsetpos.o ftell.o ftello.o fwrite.o flockfile.o ftrylockfile.o funlockfile.o getc.o getchar.o getw.o pclose.o popen.o printf.o putc.o putchar.o puts.o putw.o rewind.o scanf.o setbuf.o setbuffer.o setlinebuf.o setvbuf.o snprintf.o sprintf.o sscanf.o asprintf.o vasprintf.o tmpfile.o ungetc.o vfprintf.o vfscanf.o vprintf.o vscanf.o vsnprintf.o vsprintf.o vsscanf.o _doprnt.o _doscan.o _filbuf.o _flsbuf.o _stdfun.o _stdopen.o _stdprintf.o _stdscanf.o _stdsprnt.o _stdvbuf.o _stdvsnprnt.o _stdvsprnt.o _stdvsscn.o fgetwc.o fwprintf.o putwchar.o vfwscanf.o wprintf.o fgetws.o fwscanf.o swprintf.o vswprintf.o wscanf.o fputwc.o getwc.o swscanf.o vswscanf.o fputws.o getwchar.o ungetwc.o vwprintf.o fwide.o putwc.o vfwprintf.o vwscanf.o stdio_c99.o fcloseall.o fmemopen.o getdelim.o getline.o frexp.o frexpl.o astcopy.o
+exec - ${AR} rc libast.a astconf.o astdynamic.o astlicense.o astquery.o astwinsize.o conftab.o aststatic.o getopt.o getoptl.o aso.o asolock.o asometh.o asorelax.o aso-sem.o aso-fcntl.o vmbest.o vmclear.o vmclose.o vmdcheap.o vmdebug.o vmdisc.o vmexit.o vmlast.o vmopen.o vmpool.o vmprivate.o vmprofile.o vmregion.o vmsegment.o vmset.o vmstat.o vmstrdup.o vmtrace.o vmwalk.o vmmopen.o malloc.o vmgetmem.o a64l.o acosh.o asinh.o atanh.o cbrt.o crypt.o erf.o err.o exp.o exp__E.o expm1.o gamma.o getpass.o lgamma.o log.o log1p.o log__L.o rand48.o random.o rcmd.o rint.o support.o sfstrtmp.o spawn.o
+exec - (ranlib libast.a) >/dev/null 2>&1 || true
+done libast.a generated
+done ast virtual
+prev libast.a archive
+make ${INSTALLROOT}/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib
+exec - then mkdir -p ${INSTALLROOT}/lib
+exec - fi
+done ${INSTALLROOT}/lib generated
+make ${INSTALLROOT}/lib/libast.a archive
+prev ${INSTALLROOT}/lib
+prev libast.a archive
+exec - test '' = 'libast.a' || ${STDCMP} 2>/dev/null -s libast.a ${INSTALLROOT}/lib/libast.a || { ${STDMV} ${INSTALLROOT}/lib/libast.a ${INSTALLROOT}/lib/libast.a.old 2>/dev/null || true; ${STDCP} libast.a ${INSTALLROOT}/lib/libast.a ;}
+exec - (ranlib ${INSTALLROOT}/lib/libast.a) >/dev/null 2>&1 || true
+done ${INSTALLROOT}/lib/libast.a generated
+make ${INSTALLROOT}/man/man3
+exec - if silent test ! -d ${INSTALLROOT}/man/man3
+exec - then mkdir -p ${INSTALLROOT}/man/man3
+exec - fi
+done ${INSTALLROOT}/man/man3 generated
+make ${INSTALLROOT}/man/man3/LIBAST.3
+prev ${INSTALLROOT}/man/man3
+make man/LIBAST.3
+done man/LIBAST.3
+exec - test '' = 'man/LIBAST.3' || ${STDCMP} 2>/dev/null -s man/LIBAST.3 ${INSTALLROOT}/man/man3/LIBAST.3 || { ${STDMV} ${INSTALLROOT}/man/man3/LIBAST.3 ${INSTALLROOT}/man/man3/LIBAST.3.old 2>/dev/null || true; ${STDCP} man/LIBAST.3 ${INSTALLROOT}/man/man3/LIBAST.3 ;}
+done ${INSTALLROOT}/man/man3/LIBAST.3 generated
+make ${INSTALLROOT}/man/man3/aso.3
+make man/aso.3
+done man/aso.3
+exec - test '' = 'man/aso.3' || ${STDCMP} 2>/dev/null -s man/aso.3 ${INSTALLROOT}/man/man3/aso.3 || { ${STDMV} ${INSTALLROOT}/man/man3/aso.3 ${INSTALLROOT}/man/man3/aso.3.old 2>/dev/null || true; ${STDCP} man/aso.3 ${INSTALLROOT}/man/man3/aso.3 ;}
+done ${INSTALLROOT}/man/man3/aso.3 generated
+make ${INSTALLROOT}/man/man3/ast.3
+make man/ast.3
+done man/ast.3
+exec - test '' = 'man/ast.3' || ${STDCMP} 2>/dev/null -s man/ast.3 ${INSTALLROOT}/man/man3/ast.3 || { ${STDMV} ${INSTALLROOT}/man/man3/ast.3 ${INSTALLROOT}/man/man3/ast.3.old 2>/dev/null || true; ${STDCP} man/ast.3 ${INSTALLROOT}/man/man3/ast.3 ;}
+done ${INSTALLROOT}/man/man3/ast.3 generated
+make ${INSTALLROOT}/man/man3/astsa.3
+make man/astsa.3
+done man/astsa.3
+exec - test '' = 'man/astsa.3' || ${STDCMP} 2>/dev/null -s man/astsa.3 ${INSTALLROOT}/man/man3/astsa.3 || { ${STDMV} ${INSTALLROOT}/man/man3/astsa.3 ${INSTALLROOT}/man/man3/astsa.3.old 2>/dev/null || true; ${STDCP} man/astsa.3 ${INSTALLROOT}/man/man3/astsa.3 ;}
+done ${INSTALLROOT}/man/man3/astsa.3 generated
+make ${INSTALLROOT}/man/man3/cdt.3
+make man/cdt.3
+done man/cdt.3
+exec - test '' = 'man/cdt.3' || ${STDCMP} 2>/dev/null -s man/cdt.3 ${INSTALLROOT}/man/man3/cdt.3 || { ${STDMV} ${INSTALLROOT}/man/man3/cdt.3 ${INSTALLROOT}/man/man3/cdt.3.old 2>/dev/null || true; ${STDCP} man/cdt.3 ${INSTALLROOT}/man/man3/cdt.3 ;}
+done ${INSTALLROOT}/man/man3/cdt.3 generated
+make ${INSTALLROOT}/man/man3/chr.3
+make man/chr.3
+done man/chr.3
+exec - test '' = 'man/chr.3' || ${STDCMP} 2>/dev/null -s man/chr.3 ${INSTALLROOT}/man/man3/chr.3 || { ${STDMV} ${INSTALLROOT}/man/man3/chr.3 ${INSTALLROOT}/man/man3/chr.3.old 2>/dev/null || true; ${STDCP} man/chr.3 ${INSTALLROOT}/man/man3/chr.3 ;}
+done ${INSTALLROOT}/man/man3/chr.3 generated
+make ${INSTALLROOT}/man/man3/compat.3
+make man/compat.3
+done man/compat.3
+exec - test '' = 'man/compat.3' || ${STDCMP} 2>/dev/null -s man/compat.3 ${INSTALLROOT}/man/man3/compat.3 || { ${STDMV} ${INSTALLROOT}/man/man3/compat.3 ${INSTALLROOT}/man/man3/compat.3.old 2>/dev/null || true; ${STDCP} man/compat.3 ${INSTALLROOT}/man/man3/compat.3 ;}
+done ${INSTALLROOT}/man/man3/compat.3 generated
+make ${INSTALLROOT}/man/man3/error.3
+make man/error.3
+done man/error.3
+exec - test '' = 'man/error.3' || ${STDCMP} 2>/dev/null -s man/error.3 ${INSTALLROOT}/man/man3/error.3 || { ${STDMV} ${INSTALLROOT}/man/man3/error.3 ${INSTALLROOT}/man/man3/error.3.old 2>/dev/null || true; ${STDCP} man/error.3 ${INSTALLROOT}/man/man3/error.3 ;}
+done ${INSTALLROOT}/man/man3/error.3 generated
+make ${INSTALLROOT}/man/man3/find.3
+make man/find.3
+done man/find.3
+exec - test '' = 'man/find.3' || ${STDCMP} 2>/dev/null -s man/find.3 ${INSTALLROOT}/man/man3/find.3 || { ${STDMV} ${INSTALLROOT}/man/man3/find.3 ${INSTALLROOT}/man/man3/find.3.old 2>/dev/null || true; ${STDCP} man/find.3 ${INSTALLROOT}/man/man3/find.3 ;}
+done ${INSTALLROOT}/man/man3/find.3 generated
+make ${INSTALLROOT}/man/man3/fmt.3
+make man/fmt.3
+done man/fmt.3
+exec - test '' = 'man/fmt.3' || ${STDCMP} 2>/dev/null -s man/fmt.3 ${INSTALLROOT}/man/man3/fmt.3 || { ${STDMV} ${INSTALLROOT}/man/man3/fmt.3 ${INSTALLROOT}/man/man3/fmt.3.old 2>/dev/null || true; ${STDCP} man/fmt.3 ${INSTALLROOT}/man/man3/fmt.3 ;}
+done ${INSTALLROOT}/man/man3/fmt.3 generated
+make ${INSTALLROOT}/man/man3/fmtls.3
+make man/fmtls.3
+done man/fmtls.3
+exec - test '' = 'man/fmtls.3' || ${STDCMP} 2>/dev/null -s man/fmtls.3 ${INSTALLROOT}/man/man3/fmtls.3 || { ${STDMV} ${INSTALLROOT}/man/man3/fmtls.3 ${INSTALLROOT}/man/man3/fmtls.3.old 2>/dev/null || true; ${STDCP} man/fmtls.3 ${INSTALLROOT}/man/man3/fmtls.3 ;}
+done ${INSTALLROOT}/man/man3/fmtls.3 generated
+make ${INSTALLROOT}/man/man3/fs3d.3
+make man/fs3d.3
+done man/fs3d.3
+exec - test '' = 'man/fs3d.3' || ${STDCMP} 2>/dev/null -s man/fs3d.3 ${INSTALLROOT}/man/man3/fs3d.3 || { ${STDMV} ${INSTALLROOT}/man/man3/fs3d.3 ${INSTALLROOT}/man/man3/fs3d.3.old 2>/dev/null || true; ${STDCP} man/fs3d.3 ${INSTALLROOT}/man/man3/fs3d.3 ;}
+done ${INSTALLROOT}/man/man3/fs3d.3 generated
+make ${INSTALLROOT}/man/man3/ftwalk.3
+make man/ftwalk.3
+done man/ftwalk.3
+exec - test '' = 'man/ftwalk.3' || ${STDCMP} 2>/dev/null -s man/ftwalk.3 ${INSTALLROOT}/man/man3/ftwalk.3 || { ${STDMV} ${INSTALLROOT}/man/man3/ftwalk.3 ${INSTALLROOT}/man/man3/ftwalk.3.old 2>/dev/null || true; ${STDCP} man/ftwalk.3 ${INSTALLROOT}/man/man3/ftwalk.3 ;}
+done ${INSTALLROOT}/man/man3/ftwalk.3 generated
+make ${INSTALLROOT}/man/man3/getcwd.3
+make man/getcwd.3
+done man/getcwd.3
+exec - test '' = 'man/getcwd.3' || ${STDCMP} 2>/dev/null -s man/getcwd.3 ${INSTALLROOT}/man/man3/getcwd.3 || { ${STDMV} ${INSTALLROOT}/man/man3/getcwd.3 ${INSTALLROOT}/man/man3/getcwd.3.old 2>/dev/null || true; ${STDCP} man/getcwd.3 ${INSTALLROOT}/man/man3/getcwd.3 ;}
+done ${INSTALLROOT}/man/man3/getcwd.3 generated
+make ${INSTALLROOT}/man/man3/hash.3
+make man/hash.3
+done man/hash.3
+exec - test '' = 'man/hash.3' || ${STDCMP} 2>/dev/null -s man/hash.3 ${INSTALLROOT}/man/man3/hash.3 || { ${STDMV} ${INSTALLROOT}/man/man3/hash.3 ${INSTALLROOT}/man/man3/hash.3.old 2>/dev/null || true; ${STDCP} man/hash.3 ${INSTALLROOT}/man/man3/hash.3 ;}
+done ${INSTALLROOT}/man/man3/hash.3 generated
+make ${INSTALLROOT}/man/man3/iblocks.3
+make man/iblocks.3
+done man/iblocks.3
+exec - test '' = 'man/iblocks.3' || ${STDCMP} 2>/dev/null -s man/iblocks.3 ${INSTALLROOT}/man/man3/iblocks.3 || { ${STDMV} ${INSTALLROOT}/man/man3/iblocks.3 ${INSTALLROOT}/man/man3/iblocks.3.old 2>/dev/null || true; ${STDCP} man/iblocks.3 ${INSTALLROOT}/man/man3/iblocks.3 ;}
+done ${INSTALLROOT}/man/man3/iblocks.3 generated
+make ${INSTALLROOT}/man/man3/int.3
+make man/int.3
+done man/int.3
+exec - test '' = 'man/int.3' || ${STDCMP} 2>/dev/null -s man/int.3 ${INSTALLROOT}/man/man3/int.3 || { ${STDMV} ${INSTALLROOT}/man/man3/int.3 ${INSTALLROOT}/man/man3/int.3.old 2>/dev/null || true; ${STDCP} man/int.3 ${INSTALLROOT}/man/man3/int.3 ;}
+done ${INSTALLROOT}/man/man3/int.3 generated
+make ${INSTALLROOT}/man/man3/ip6.3
+make man/ip6.3
+done man/ip6.3
+exec - test '' = 'man/ip6.3' || ${STDCMP} 2>/dev/null -s man/ip6.3 ${INSTALLROOT}/man/man3/ip6.3 || { ${STDMV} ${INSTALLROOT}/man/man3/ip6.3 ${INSTALLROOT}/man/man3/ip6.3.old 2>/dev/null || true; ${STDCP} man/ip6.3 ${INSTALLROOT}/man/man3/ip6.3 ;}
+done ${INSTALLROOT}/man/man3/ip6.3 generated
+make ${INSTALLROOT}/man/man3/magic.3
+make man/magic.3
+done man/magic.3
+exec - test '' = 'man/magic.3' || ${STDCMP} 2>/dev/null -s man/magic.3 ${INSTALLROOT}/man/man3/magic.3 || { ${STDMV} ${INSTALLROOT}/man/man3/magic.3 ${INSTALLROOT}/man/man3/magic.3.old 2>/dev/null || true; ${STDCP} man/magic.3 ${INSTALLROOT}/man/man3/magic.3 ;}
+done ${INSTALLROOT}/man/man3/magic.3 generated
+make ${INSTALLROOT}/man/man3/mem.3
+make man/mem.3
+done man/mem.3
+exec - test '' = 'man/mem.3' || ${STDCMP} 2>/dev/null -s man/mem.3 ${INSTALLROOT}/man/man3/mem.3 || { ${STDMV} ${INSTALLROOT}/man/man3/mem.3 ${INSTALLROOT}/man/man3/mem.3.old 2>/dev/null || true; ${STDCP} man/mem.3 ${INSTALLROOT}/man/man3/mem.3 ;}
+done ${INSTALLROOT}/man/man3/mem.3 generated
+make ${INSTALLROOT}/man/man3/mime.3
+make man/mime.3
+done man/mime.3
+exec - test '' = 'man/mime.3' || ${STDCMP} 2>/dev/null -s man/mime.3 ${INSTALLROOT}/man/man3/mime.3 || { ${STDMV} ${INSTALLROOT}/man/man3/mime.3 ${INSTALLROOT}/man/man3/mime.3.old 2>/dev/null || true; ${STDCP} man/mime.3 ${INSTALLROOT}/man/man3/mime.3 ;}
+done ${INSTALLROOT}/man/man3/mime.3 generated
+make ${INSTALLROOT}/man/man3/modecanon.3
+make man/modecanon.3
+done man/modecanon.3
+exec - test '' = 'man/modecanon.3' || ${STDCMP} 2>/dev/null -s man/modecanon.3 ${INSTALLROOT}/man/man3/modecanon.3 || { ${STDMV} ${INSTALLROOT}/man/man3/modecanon.3 ${INSTALLROOT}/man/man3/modecanon.3.old 2>/dev/null || true; ${STDCP} man/modecanon.3 ${INSTALLROOT}/man/man3/modecanon.3 ;}
+done ${INSTALLROOT}/man/man3/modecanon.3 generated
+make ${INSTALLROOT}/man/man3/optget.3
+make man/optget.3
+done man/optget.3
+exec - test '' = 'man/optget.3' || ${STDCMP} 2>/dev/null -s man/optget.3 ${INSTALLROOT}/man/man3/optget.3 || { ${STDMV} ${INSTALLROOT}/man/man3/optget.3 ${INSTALLROOT}/man/man3/optget.3.old 2>/dev/null || true; ${STDCP} man/optget.3 ${INSTALLROOT}/man/man3/optget.3 ;}
+done ${INSTALLROOT}/man/man3/optget.3 generated
+make ${INSTALLROOT}/man/man3/path.3
+make man/path.3
+done man/path.3
+exec - test '' = 'man/path.3' || ${STDCMP} 2>/dev/null -s man/path.3 ${INSTALLROOT}/man/man3/path.3 || { ${STDMV} ${INSTALLROOT}/man/man3/path.3 ${INSTALLROOT}/man/man3/path.3.old 2>/dev/null || true; ${STDCP} man/path.3 ${INSTALLROOT}/man/man3/path.3 ;}
+done ${INSTALLROOT}/man/man3/path.3 generated
+make ${INSTALLROOT}/man/man3/preroot.3
+make man/preroot.3
+done man/preroot.3
+exec - test '' = 'man/preroot.3' || ${STDCMP} 2>/dev/null -s man/preroot.3 ${INSTALLROOT}/man/man3/preroot.3 || { ${STDMV} ${INSTALLROOT}/man/man3/preroot.3 ${INSTALLROOT}/man/man3/preroot.3.old 2>/dev/null || true; ${STDCP} man/preroot.3 ${INSTALLROOT}/man/man3/preroot.3 ;}
+done ${INSTALLROOT}/man/man3/preroot.3 generated
+make ${INSTALLROOT}/man/man3/proc.3
+make man/proc.3
+done man/proc.3
+exec - test '' = 'man/proc.3' || ${STDCMP} 2>/dev/null -s man/proc.3 ${INSTALLROOT}/man/man3/proc.3 || { ${STDMV} ${INSTALLROOT}/man/man3/proc.3 ${INSTALLROOT}/man/man3/proc.3.old 2>/dev/null || true; ${STDCP} man/proc.3 ${INSTALLROOT}/man/man3/proc.3 ;}
+done ${INSTALLROOT}/man/man3/proc.3 generated
+make ${INSTALLROOT}/man/man3/re.3
+make man/re.3
+done man/re.3
+exec - test '' = 'man/re.3' || ${STDCMP} 2>/dev/null -s man/re.3 ${INSTALLROOT}/man/man3/re.3 || { ${STDMV} ${INSTALLROOT}/man/man3/re.3 ${INSTALLROOT}/man/man3/re.3.old 2>/dev/null || true; ${STDCP} man/re.3 ${INSTALLROOT}/man/man3/re.3 ;}
+done ${INSTALLROOT}/man/man3/re.3 generated
+make ${INSTALLROOT}/man/man3/regex.3
+make man/regex.3
+done man/regex.3
+exec - test '' = 'man/regex.3' || ${STDCMP} 2>/dev/null -s man/regex.3 ${INSTALLROOT}/man/man3/regex.3 || { ${STDMV} ${INSTALLROOT}/man/man3/regex.3 ${INSTALLROOT}/man/man3/regex.3.old 2>/dev/null || true; ${STDCP} man/regex.3 ${INSTALLROOT}/man/man3/regex.3 ;}
+done ${INSTALLROOT}/man/man3/regex.3 generated
+make ${INSTALLROOT}/man/man3/setenviron.3
+make man/setenviron.3
+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
+exec - test '' = 'man/sfio.3' || ${STDCMP} 2>/dev/null -s man/sfio.3 ${INSTALLROOT}/man/man3/sfio.3 || { ${STDMV} ${INSTALLROOT}/man/man3/sfio.3 ${INSTALLROOT}/man/man3/sfio.3.old 2>/dev/null || true; ${STDCP} man/sfio.3 ${INSTALLROOT}/man/man3/sfio.3 ;}
+done ${INSTALLROOT}/man/man3/sfio.3 generated
+make ${INSTALLROOT}/man/man3/sig.3
+make man/sig.3
+done man/sig.3
+exec - test '' = 'man/sig.3' || ${STDCMP} 2>/dev/null -s man/sig.3 ${INSTALLROOT}/man/man3/sig.3 || { ${STDMV} ${INSTALLROOT}/man/man3/sig.3 ${INSTALLROOT}/man/man3/sig.3.old 2>/dev/null || true; ${STDCP} man/sig.3 ${INSTALLROOT}/man/man3/sig.3 ;}
+done ${INSTALLROOT}/man/man3/sig.3 generated
+make ${INSTALLROOT}/man/man3/spawnveg.3
+make man/spawnveg.3
+done man/spawnveg.3
+exec - test '' = 'man/spawnveg.3' || ${STDCMP} 2>/dev/null -s man/spawnveg.3 ${INSTALLROOT}/man/man3/spawnveg.3 || { ${STDMV} ${INSTALLROOT}/man/man3/spawnveg.3 ${INSTALLROOT}/man/man3/spawnveg.3.old 2>/dev/null || true; ${STDCP} man/spawnveg.3 ${INSTALLROOT}/man/man3/spawnveg.3 ;}
+done ${INSTALLROOT}/man/man3/spawnveg.3 generated
+make ${INSTALLROOT}/man/man3/stak.3
+make man/stak.3
+done man/stak.3
+exec - test '' = 'man/stak.3' || ${STDCMP} 2>/dev/null -s man/stak.3 ${INSTALLROOT}/man/man3/stak.3 || { ${STDMV} ${INSTALLROOT}/man/man3/stak.3 ${INSTALLROOT}/man/man3/stak.3.old 2>/dev/null || true; ${STDCP} man/stak.3 ${INSTALLROOT}/man/man3/stak.3 ;}
+done ${INSTALLROOT}/man/man3/stak.3 generated
+make ${INSTALLROOT}/man/man3/stk.3
+make man/stk.3
+done man/stk.3
+exec - test '' = 'man/stk.3' || ${STDCMP} 2>/dev/null -s man/stk.3 ${INSTALLROOT}/man/man3/stk.3 || { ${STDMV} ${INSTALLROOT}/man/man3/stk.3 ${INSTALLROOT}/man/man3/stk.3.old 2>/dev/null || true; ${STDCP} man/stk.3 ${INSTALLROOT}/man/man3/stk.3 ;}
+done ${INSTALLROOT}/man/man3/stk.3 generated
+make ${INSTALLROOT}/man/man3/strcopy.3
+make man/strcopy.3
+done man/strcopy.3
+exec - test '' = 'man/strcopy.3' || ${STDCMP} 2>/dev/null -s man/strcopy.3 ${INSTALLROOT}/man/man3/strcopy.3 || { ${STDMV} ${INSTALLROOT}/man/man3/strcopy.3 ${INSTALLROOT}/man/man3/strcopy.3.old 2>/dev/null || true; ${STDCP} man/strcopy.3 ${INSTALLROOT}/man/man3/strcopy.3 ;}
+done ${INSTALLROOT}/man/man3/strcopy.3 generated
+make ${INSTALLROOT}/man/man3/strdup.3
+make man/strdup.3
+done man/strdup.3
+exec - test '' = 'man/strdup.3' || ${STDCMP} 2>/dev/null -s man/strdup.3 ${INSTALLROOT}/man/man3/strdup.3 || { ${STDMV} ${INSTALLROOT}/man/man3/strdup.3 ${INSTALLROOT}/man/man3/strdup.3.old 2>/dev/null || true; ${STDCP} man/strdup.3 ${INSTALLROOT}/man/man3/strdup.3 ;}
+done ${INSTALLROOT}/man/man3/strdup.3 generated
+make ${INSTALLROOT}/man/man3/strelapsed.3
+make man/strelapsed.3
+done man/strelapsed.3
+exec - test '' = 'man/strelapsed.3' || ${STDCMP} 2>/dev/null -s man/strelapsed.3 ${INSTALLROOT}/man/man3/strelapsed.3 || { ${STDMV} ${INSTALLROOT}/man/man3/strelapsed.3 ${INSTALLROOT}/man/man3/strelapsed.3.old 2>/dev/null || true; ${STDCP} man/strelapsed.3 ${INSTALLROOT}/man/man3/strelapsed.3 ;}
+done ${INSTALLROOT}/man/man3/strelapsed.3 generated
+make ${INSTALLROOT}/man/man3/strerror.3
+make man/strerror.3
+done man/strerror.3
+exec - test '' = 'man/strerror.3' || ${STDCMP} 2>/dev/null -s man/strerror.3 ${INSTALLROOT}/man/man3/strerror.3 || { ${STDMV} ${INSTALLROOT}/man/man3/strerror.3 ${INSTALLROOT}/man/man3/strerror.3.old 2>/dev/null || true; ${STDCP} man/strerror.3 ${INSTALLROOT}/man/man3/strerror.3 ;}
+done ${INSTALLROOT}/man/man3/strerror.3 generated
+make ${INSTALLROOT}/man/man3/stresc.3
+make man/stresc.3
+done man/stresc.3
+exec - test '' = 'man/stresc.3' || ${STDCMP} 2>/dev/null -s man/stresc.3 ${INSTALLROOT}/man/man3/stresc.3 || { ${STDMV} ${INSTALLROOT}/man/man3/stresc.3 ${INSTALLROOT}/man/man3/stresc.3.old 2>/dev/null || true; ${STDCP} man/stresc.3 ${INSTALLROOT}/man/man3/stresc.3 ;}
+done ${INSTALLROOT}/man/man3/stresc.3 generated
+make ${INSTALLROOT}/man/man3/streval.3
+make man/streval.3
+done man/streval.3
+exec - test '' = 'man/streval.3' || ${STDCMP} 2>/dev/null -s man/streval.3 ${INSTALLROOT}/man/man3/streval.3 || { ${STDMV} ${INSTALLROOT}/man/man3/streval.3 ${INSTALLROOT}/man/man3/streval.3.old 2>/dev/null || true; ${STDCP} man/streval.3 ${INSTALLROOT}/man/man3/streval.3 ;}
+done ${INSTALLROOT}/man/man3/streval.3 generated
+make ${INSTALLROOT}/man/man3/strgid.3
+make man/strgid.3
+done man/strgid.3
+exec - test '' = 'man/strgid.3' || ${STDCMP} 2>/dev/null -s man/strgid.3 ${INSTALLROOT}/man/man3/strgid.3 || { ${STDMV} ${INSTALLROOT}/man/man3/strgid.3 ${INSTALLROOT}/man/man3/strgid.3.old 2>/dev/null || true; ${STDCP} man/strgid.3 ${INSTALLROOT}/man/man3/strgid.3 ;}
+done ${INSTALLROOT}/man/man3/strgid.3 generated
+make ${INSTALLROOT}/man/man3/strmatch.3
+make man/strmatch.3
+done man/strmatch.3
+exec - test '' = 'man/strmatch.3' || ${STDCMP} 2>/dev/null -s man/strmatch.3 ${INSTALLROOT}/man/man3/strmatch.3 || { ${STDMV} ${INSTALLROOT}/man/man3/strmatch.3 ${INSTALLROOT}/man/man3/strmatch.3.old 2>/dev/null || true; ${STDCP} man/strmatch.3 ${INSTALLROOT}/man/man3/strmatch.3 ;}
+done ${INSTALLROOT}/man/man3/strmatch.3 generated
+make ${INSTALLROOT}/man/man3/stropt.3
+make man/stropt.3
+done man/stropt.3
+exec - test '' = 'man/stropt.3' || ${STDCMP} 2>/dev/null -s man/stropt.3 ${INSTALLROOT}/man/man3/stropt.3 || { ${STDMV} ${INSTALLROOT}/man/man3/stropt.3 ${INSTALLROOT}/man/man3/stropt.3.old 2>/dev/null || true; ${STDCP} man/stropt.3 ${INSTALLROOT}/man/man3/stropt.3 ;}
+done ${INSTALLROOT}/man/man3/stropt.3 generated
+make ${INSTALLROOT}/man/man3/strperm.3
+make man/strperm.3
+done man/strperm.3
+exec - test '' = 'man/strperm.3' || ${STDCMP} 2>/dev/null -s man/strperm.3 ${INSTALLROOT}/man/man3/strperm.3 || { ${STDMV} ${INSTALLROOT}/man/man3/strperm.3 ${INSTALLROOT}/man/man3/strperm.3.old 2>/dev/null || true; ${STDCP} man/strperm.3 ${INSTALLROOT}/man/man3/strperm.3 ;}
+done ${INSTALLROOT}/man/man3/strperm.3 generated
+make ${INSTALLROOT}/man/man3/strsignal.3
+make man/strsignal.3
+done man/strsignal.3
+exec - test '' = 'man/strsignal.3' || ${STDCMP} 2>/dev/null -s man/strsignal.3 ${INSTALLROOT}/man/man3/strsignal.3 || { ${STDMV} ${INSTALLROOT}/man/man3/strsignal.3 ${INSTALLROOT}/man/man3/strsignal.3.old 2>/dev/null || true; ${STDCP} man/strsignal.3 ${INSTALLROOT}/man/man3/strsignal.3 ;}
+done ${INSTALLROOT}/man/man3/strsignal.3 generated
+make ${INSTALLROOT}/man/man3/strsort.3
+make man/strsort.3
+done man/strsort.3
+exec - test '' = 'man/strsort.3' || ${STDCMP} 2>/dev/null -s man/strsort.3 ${INSTALLROOT}/man/man3/strsort.3 || { ${STDMV} ${INSTALLROOT}/man/man3/strsort.3 ${INSTALLROOT}/man/man3/strsort.3.old 2>/dev/null || true; ${STDCP} man/strsort.3 ${INSTALLROOT}/man/man3/strsort.3 ;}
+done ${INSTALLROOT}/man/man3/strsort.3 generated
+make ${INSTALLROOT}/man/man3/strtape.3
+make man/strtape.3
+done man/strtape.3
+exec - test '' = 'man/strtape.3' || ${STDCMP} 2>/dev/null -s man/strtape.3 ${INSTALLROOT}/man/man3/strtape.3 || { ${STDMV} ${INSTALLROOT}/man/man3/strtape.3 ${INSTALLROOT}/man/man3/strtape.3.old 2>/dev/null || true; ${STDCP} man/strtape.3 ${INSTALLROOT}/man/man3/strtape.3 ;}
+done ${INSTALLROOT}/man/man3/strtape.3 generated
+make ${INSTALLROOT}/man/man3/strton.3
+make man/strton.3
+done man/strton.3
+exec - test '' = 'man/strton.3' || ${STDCMP} 2>/dev/null -s man/strton.3 ${INSTALLROOT}/man/man3/strton.3 || { ${STDMV} ${INSTALLROOT}/man/man3/strton.3 ${INSTALLROOT}/man/man3/strton.3.old 2>/dev/null || true; ${STDCP} man/strton.3 ${INSTALLROOT}/man/man3/strton.3 ;}
+done ${INSTALLROOT}/man/man3/strton.3 generated
+make ${INSTALLROOT}/man/man3/struid.3
+make man/struid.3
+done man/struid.3
+exec - test '' = 'man/struid.3' || ${STDCMP} 2>/dev/null -s man/struid.3 ${INSTALLROOT}/man/man3/struid.3 || { ${STDMV} ${INSTALLROOT}/man/man3/struid.3 ${INSTALLROOT}/man/man3/struid.3.old 2>/dev/null || true; ${STDCP} man/struid.3 ${INSTALLROOT}/man/man3/struid.3 ;}
+done ${INSTALLROOT}/man/man3/struid.3 generated
+make ${INSTALLROOT}/man/man3/swap.3
+make man/swap.3
+done man/swap.3
+exec - test '' = 'man/swap.3' || ${STDCMP} 2>/dev/null -s man/swap.3 ${INSTALLROOT}/man/man3/swap.3 || { ${STDMV} ${INSTALLROOT}/man/man3/swap.3 ${INSTALLROOT}/man/man3/swap.3.old 2>/dev/null || true; ${STDCP} man/swap.3 ${INSTALLROOT}/man/man3/swap.3 ;}
+done ${INSTALLROOT}/man/man3/swap.3 generated
+make ${INSTALLROOT}/man/man3/tab.3
+make man/tab.3
+done man/tab.3
+exec - test '' = 'man/tab.3' || ${STDCMP} 2>/dev/null -s man/tab.3 ${INSTALLROOT}/man/man3/tab.3 || { ${STDMV} ${INSTALLROOT}/man/man3/tab.3 ${INSTALLROOT}/man/man3/tab.3.old 2>/dev/null || true; ${STDCP} man/tab.3 ${INSTALLROOT}/man/man3/tab.3 ;}
+done ${INSTALLROOT}/man/man3/tab.3 generated
+make ${INSTALLROOT}/man/man3/tm.3
+make man/tm.3
+done man/tm.3
+exec - test '' = 'man/tm.3' || ${STDCMP} 2>/dev/null -s man/tm.3 ${INSTALLROOT}/man/man3/tm.3 || { ${STDMV} ${INSTALLROOT}/man/man3/tm.3 ${INSTALLROOT}/man/man3/tm.3.old 2>/dev/null || true; ${STDCP} man/tm.3 ${INSTALLROOT}/man/man3/tm.3 ;}
+done ${INSTALLROOT}/man/man3/tm.3 generated
+make ${INSTALLROOT}/man/man3/tmx.3
+make man/tmx.3
+done man/tmx.3
+exec - test '' = 'man/tmx.3' || ${STDCMP} 2>/dev/null -s man/tmx.3 ${INSTALLROOT}/man/man3/tmx.3 || { ${STDMV} ${INSTALLROOT}/man/man3/tmx.3 ${INSTALLROOT}/man/man3/tmx.3.old 2>/dev/null || true; ${STDCP} man/tmx.3 ${INSTALLROOT}/man/man3/tmx.3 ;}
+done ${INSTALLROOT}/man/man3/tmx.3 generated
+make ${INSTALLROOT}/man/man3/tok.3
+make man/tok.3
+done man/tok.3
+exec - test '' = 'man/tok.3' || ${STDCMP} 2>/dev/null -s man/tok.3 ${INSTALLROOT}/man/man3/tok.3 || { ${STDMV} ${INSTALLROOT}/man/man3/tok.3 ${INSTALLROOT}/man/man3/tok.3.old 2>/dev/null || true; ${STDCP} man/tok.3 ${INSTALLROOT}/man/man3/tok.3 ;}
+done ${INSTALLROOT}/man/man3/tok.3 generated
+make ${INSTALLROOT}/man/man3/touch.3
+make man/touch.3
+done man/touch.3
+exec - test '' = 'man/touch.3' || ${STDCMP} 2>/dev/null -s man/touch.3 ${INSTALLROOT}/man/man3/touch.3 || { ${STDMV} ${INSTALLROOT}/man/man3/touch.3 ${INSTALLROOT}/man/man3/touch.3.old 2>/dev/null || true; ${STDCP} man/touch.3 ${INSTALLROOT}/man/man3/touch.3 ;}
+done ${INSTALLROOT}/man/man3/touch.3 generated
+make ${INSTALLROOT}/man/man3/tv.3
+make man/tv.3
+done man/tv.3
+exec - test '' = 'man/tv.3' || ${STDCMP} 2>/dev/null -s man/tv.3 ${INSTALLROOT}/man/man3/tv.3 || { ${STDMV} ${INSTALLROOT}/man/man3/tv.3 ${INSTALLROOT}/man/man3/tv.3.old 2>/dev/null || true; ${STDCP} man/tv.3 ${INSTALLROOT}/man/man3/tv.3 ;}
+done ${INSTALLROOT}/man/man3/tv.3 generated
+make ${INSTALLROOT}/man/man3/vecargs.3
+make man/vecargs.3
+done man/vecargs.3
+exec - test '' = 'man/vecargs.3' || ${STDCMP} 2>/dev/null -s man/vecargs.3 ${INSTALLROOT}/man/man3/vecargs.3 || { ${STDMV} ${INSTALLROOT}/man/man3/vecargs.3 ${INSTALLROOT}/man/man3/vecargs.3.old 2>/dev/null || true; ${STDCP} man/vecargs.3 ${INSTALLROOT}/man/man3/vecargs.3 ;}
+done ${INSTALLROOT}/man/man3/vecargs.3 generated
+make ${INSTALLROOT}/man/man3/vmalloc.3
+make man/vmalloc.3
+done man/vmalloc.3
+exec - test '' = 'man/vmalloc.3' || ${STDCMP} 2>/dev/null -s man/vmalloc.3 ${INSTALLROOT}/man/man3/vmalloc.3 || { ${STDMV} ${INSTALLROOT}/man/man3/vmalloc.3 ${INSTALLROOT}/man/man3/vmalloc.3.old 2>/dev/null || true; ${STDCP} man/vmalloc.3 ${INSTALLROOT}/man/man3/vmalloc.3 ;}
+done ${INSTALLROOT}/man/man3/vmalloc.3 generated
+make ${INSTALLROOT}/lib/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib/lib
+exec - then mkdir -p ${INSTALLROOT}/lib/lib
+exec - fi
+done ${INSTALLROOT}/lib/lib generated
+make ${INSTALLROOT}/lib/lib/ast
+prev ${INSTALLROOT}/lib/lib
+prev ast.req
+exec - test '' = 'ast.req' || ${STDCMP} 2>/dev/null -s ast.req ${INSTALLROOT}/lib/lib/ast || { ${STDMV} ${INSTALLROOT}/lib/lib/ast ${INSTALLROOT}/lib/lib/ast.old 2>/dev/null || true; ${STDCP} ast.req ${INSTALLROOT}/lib/lib/ast ;}
+done ${INSTALLROOT}/lib/lib/ast generated
+make ${INSTALLROOT}/include/ast
+exec - if silent test ! -d ${INSTALLROOT}/include/ast
+exec - then mkdir -p ${INSTALLROOT}/include/ast
+exec - fi
+done ${INSTALLROOT}/include/ast generated
+make ${INSTALLROOT}/include/ast/ast_common.h
+prev ${INSTALLROOT}/include/ast
+prev ast_common.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_common.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_common.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_common.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_common.h generated
+make ${INSTALLROOT}/include/ast/ast.h
+prev include/ast.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/ast.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast.h generated
+make ${INSTALLROOT}/include/ast/ast_dir.h
+prev include/ast_dir.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/ast_dir.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_dir.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_dir.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_dir.h generated
+make ${INSTALLROOT}/include/ast/ast_getopt.h
+prev include/ast_getopt.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/ast_getopt.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_getopt.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_getopt.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_getopt.h generated
+make ${INSTALLROOT}/include/ast/ast_std.h
+prev include/ast_std.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/ast_std.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_std.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_std.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_std.h generated
+make ${INSTALLROOT}/include/ast/ast_namval.h
+prev ast_namval.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_namval.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_namval.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_namval.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_namval.h generated
+make ${INSTALLROOT}/include/ast/ast_windows.h
+prev include/ast_windows.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/ast_windows.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_windows.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_windows.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_windows.h generated
+make ${INSTALLROOT}/include/ast/ccode.h
+prev include/ccode.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/ccode.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ccode.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ccode.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ccode.h generated
+make ${INSTALLROOT}/include/ast/cdt.h
+prev include/cdt.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/cdt.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/cdt.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/cdt.h
+exec - fi
+done ${INSTALLROOT}/include/ast/cdt.h generated
+make ${INSTALLROOT}/include/ast/cdtlib.h
+prev cdt/cdtlib.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' cdt/cdtlib.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/cdtlib.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/cdtlib.h
+exec - fi
+done ${INSTALLROOT}/include/ast/cdtlib.h generated
+make ${INSTALLROOT}/include/ast/cmdarg.h
+prev include/cmdarg.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/cmdarg.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/cmdarg.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/cmdarg.h
+exec - fi
+done ${INSTALLROOT}/include/ast/cmdarg.h generated
+make ${INSTALLROOT}/include/ast/debug.h
+prev include/debug.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/debug.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/debug.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/debug.h
+exec - fi
+done ${INSTALLROOT}/include/ast/debug.h generated
+make ${INSTALLROOT}/include/ast/dt.h
+prev include/dt.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/dt.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/dt.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/dt.h
+exec - fi
+done ${INSTALLROOT}/include/ast/dt.h generated
+make ${INSTALLROOT}/include/ast/error.h
+prev include/error.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/error.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/error.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/error.h
+exec - fi
+done ${INSTALLROOT}/include/ast/error.h generated
+make ${INSTALLROOT}/include/ast/find.h
+prev include/find.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/find.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/find.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/find.h
+exec - fi
+done ${INSTALLROOT}/include/ast/find.h generated
+make ${INSTALLROOT}/include/ast/ftw.h
+prev comp/ftw.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' comp/ftw.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ftw.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ftw.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ftw.h generated
+make ${INSTALLROOT}/include/ast/ftwalk.h
+prev include/ftwalk.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/ftwalk.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ftwalk.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ftwalk.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ftwalk.h generated
+make ${INSTALLROOT}/include/ast/fts.h
+prev include/fts.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/fts.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/fts.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/fts.h
+exec - fi
+done ${INSTALLROOT}/include/ast/fts.h generated
+make ${INSTALLROOT}/include/ast/fs3d.h
+prev include/fs3d.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/fs3d.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/fs3d.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/fs3d.h
+exec - fi
+done ${INSTALLROOT}/include/ast/fs3d.h generated
+make ${INSTALLROOT}/include/ast/getopt.h
+prev comp/getopt.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' comp/getopt.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/getopt.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/getopt.h
+exec - fi
+done ${INSTALLROOT}/include/ast/getopt.h generated
+make ${INSTALLROOT}/include/ast/glob.h
+prev include/glob.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/glob.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/glob.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/glob.h
+exec - fi
+done ${INSTALLROOT}/include/ast/glob.h generated
+make ${INSTALLROOT}/include/ast/hash.h
+prev include/hash.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/hash.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/hash.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/hash.h
+exec - fi
+done ${INSTALLROOT}/include/ast/hash.h generated
+make ${INSTALLROOT}/include/ast/hashkey.h
+prev include/hashkey.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/hashkey.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/hashkey.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/hashkey.h
+exec - fi
+done ${INSTALLROOT}/include/ast/hashkey.h generated
+make ${INSTALLROOT}/include/ast/hashpart.h
+prev include/hashpart.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/hashpart.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/hashpart.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/hashpart.h
+exec - fi
+done ${INSTALLROOT}/include/ast/hashpart.h generated
+make ${INSTALLROOT}/include/ast/ip6.h
+prev include/ip6.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/ip6.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ip6.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ip6.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ip6.h generated
+make ${INSTALLROOT}/include/ast/lc.h
+prev lc.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' lc.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/lc.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/lc.h
+exec - fi
+done ${INSTALLROOT}/include/ast/lc.h generated
+make ${INSTALLROOT}/include/ast/ls.h
+prev include/ls.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/ls.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ls.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ls.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ls.h generated
+make ${INSTALLROOT}/include/ast/magic.h
+prev include/magic.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/magic.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/magic.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/magic.h
+exec - fi
+done ${INSTALLROOT}/include/ast/magic.h generated
+make ${INSTALLROOT}/include/ast/mc.h
+prev include/mc.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/mc.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/mc.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/mc.h
+exec - fi
+done ${INSTALLROOT}/include/ast/mc.h generated
+make ${INSTALLROOT}/include/ast/mime.h
+prev include/mime.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/mime.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/mime.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/mime.h
+exec - fi
+done ${INSTALLROOT}/include/ast/mime.h generated
+make ${INSTALLROOT}/include/ast/mnt.h
+prev include/mnt.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/mnt.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/mnt.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/mnt.h
+exec - fi
+done ${INSTALLROOT}/include/ast/mnt.h generated
+make ${INSTALLROOT}/include/ast/modecanon.h
+prev include/modecanon.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/modecanon.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/modecanon.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/modecanon.h
+exec - fi
+done ${INSTALLROOT}/include/ast/modecanon.h generated
+make ${INSTALLROOT}/include/ast/modex.h
+prev include/modex.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/modex.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/modex.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/modex.h
+exec - fi
+done ${INSTALLROOT}/include/ast/modex.h generated
+make ${INSTALLROOT}/include/ast/namval.h
+prev include/namval.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/namval.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/namval.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/namval.h
+exec - fi
+done ${INSTALLROOT}/include/ast/namval.h generated
+make ${INSTALLROOT}/include/ast/option.h
+prev include/option.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/option.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/option.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/option.h
+exec - fi
+done ${INSTALLROOT}/include/ast/option.h generated
+make ${INSTALLROOT}/include/ast/proc.h
+prev include/proc.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/proc.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/proc.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/proc.h
+exec - fi
+done ${INSTALLROOT}/include/ast/proc.h generated
+make ${INSTALLROOT}/include/ast/re_comp.h
+prev comp/re_comp.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' comp/re_comp.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/re_comp.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/re_comp.h
+exec - fi
+done ${INSTALLROOT}/include/ast/re_comp.h generated
+make ${INSTALLROOT}/include/ast/recfmt.h
+prev include/recfmt.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/recfmt.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/recfmt.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/recfmt.h
+exec - fi
+done ${INSTALLROOT}/include/ast/recfmt.h generated
+make ${INSTALLROOT}/include/ast/regex.h
+prev include/regex.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/regex.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/regex.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/regex.h
+exec - fi
+done ${INSTALLROOT}/include/ast/regex.h generated
+make ${INSTALLROOT}/include/ast/regexp.h
+prev comp/regexp.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' comp/regexp.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/regexp.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/regexp.h
+exec - fi
+done ${INSTALLROOT}/include/ast/regexp.h generated
+make ${INSTALLROOT}/include/ast/sfio.h
+prev include/sfio.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/sfio.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/sfio.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/sfio.h
+exec - fi
+done ${INSTALLROOT}/include/ast/sfio.h generated
+make ${INSTALLROOT}/include/ast/sfio_s.h
+prev include/sfio_s.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/sfio_s.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/sfio_s.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/sfio_s.h
+exec - fi
+done ${INSTALLROOT}/include/ast/sfio_s.h generated
+make ${INSTALLROOT}/include/ast/sfio_t.h
+prev include/sfio_t.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/sfio_t.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/sfio_t.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/sfio_t.h
+exec - fi
+done ${INSTALLROOT}/include/ast/sfio_t.h generated
+make ${INSTALLROOT}/include/ast/sfdisc.h
+prev include/sfdisc.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/sfdisc.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/sfdisc.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/sfdisc.h
+exec - fi
+done ${INSTALLROOT}/include/ast/sfdisc.h generated
+make ${INSTALLROOT}/include/ast/shcmd.h
+prev include/shcmd.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/shcmd.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/shcmd.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/shcmd.h
+exec - fi
+done ${INSTALLROOT}/include/ast/shcmd.h generated
+make ${INSTALLROOT}/include/ast/stack.h
+prev include/stack.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/stack.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/stack.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/stack.h
+exec - fi
+done ${INSTALLROOT}/include/ast/stack.h generated
+make ${INSTALLROOT}/include/ast/stak.h
+prev include/stak.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/stak.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/stak.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/stak.h
+exec - fi
+done ${INSTALLROOT}/include/ast/stak.h generated
+make ${INSTALLROOT}/include/ast/stk.h
+prev include/stk.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/stk.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/stk.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/stk.h
+exec - fi
+done ${INSTALLROOT}/include/ast/stk.h generated
+make ${INSTALLROOT}/include/ast/swap.h
+prev include/swap.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/swap.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/swap.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/swap.h
+exec - fi
+done ${INSTALLROOT}/include/ast/swap.h generated
+make ${INSTALLROOT}/include/ast/tar.h
+make include/tar.h
+done include/tar.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/tar.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/tar.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/tar.h
+exec - fi
+done ${INSTALLROOT}/include/ast/tar.h generated
+make ${INSTALLROOT}/include/ast/times.h
+prev include/times.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/times.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/times.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/times.h
+exec - fi
+done ${INSTALLROOT}/include/ast/times.h generated
+make ${INSTALLROOT}/include/ast/tm.h
+prev include/tm.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/tm.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/tm.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/tm.h
+exec - fi
+done ${INSTALLROOT}/include/ast/tm.h generated
+make ${INSTALLROOT}/include/ast/tok.h
+prev include/tok.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/tok.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/tok.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/tok.h
+exec - fi
+done ${INSTALLROOT}/include/ast/tok.h generated
+make ${INSTALLROOT}/include/ast/usage.h
+make include/usage.h
+done include/usage.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/usage.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/usage.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/usage.h
+exec - fi
+done ${INSTALLROOT}/include/ast/usage.h generated
+make ${INSTALLROOT}/include/ast/vdb.h
+make include/vdb.h
+done include/vdb.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/vdb.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/vdb.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/vdb.h
+exec - fi
+done ${INSTALLROOT}/include/ast/vdb.h generated
+make ${INSTALLROOT}/include/ast/vecargs.h
+prev include/vecargs.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/vecargs.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/vecargs.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/vecargs.h
+exec - fi
+done ${INSTALLROOT}/include/ast/vecargs.h generated
+make ${INSTALLROOT}/include/ast/vmalloc.h
+prev include/vmalloc.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/vmalloc.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/vmalloc.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/vmalloc.h
+exec - fi
+done ${INSTALLROOT}/include/ast/vmalloc.h generated
+make ${INSTALLROOT}/include/ast/wait.h
+prev include/wait.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/wait.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/wait.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/wait.h
+exec - fi
+done ${INSTALLROOT}/include/ast/wait.h generated
+make ${INSTALLROOT}/include/ast/wordexp.h
+prev comp/wordexp.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' comp/wordexp.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/wordexp.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/wordexp.h
+exec - fi
+done ${INSTALLROOT}/include/ast/wordexp.h generated
+make ${INSTALLROOT}/include/ast/bytesex.h
+prev std/bytesex.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' std/bytesex.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/bytesex.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/bytesex.h
+exec - fi
+done ${INSTALLROOT}/include/ast/bytesex.h generated
+make ${INSTALLROOT}/include/ast/endian.h
+prev std/endian.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' std/endian.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/endian.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/endian.h
+exec - fi
+done ${INSTALLROOT}/include/ast/endian.h generated
+make ${INSTALLROOT}/include/ast/fnmatch.h
+prev comp/fnmatch.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' comp/fnmatch.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/fnmatch.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/fnmatch.h
+exec - fi
+done ${INSTALLROOT}/include/ast/fnmatch.h generated
+make ${INSTALLROOT}/include/ast/magicid.h
+make include/magicid.h
+prev ast_common.h implicit
+done include/magicid.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/magicid.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/magicid.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/magicid.h
+exec - fi
+done ${INSTALLROOT}/include/ast/magicid.h generated
+make ${INSTALLROOT}/include/ast/fnv.h
+prev include/fnv.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/fnv.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/fnv.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/fnv.h
+exec - fi
+done ${INSTALLROOT}/include/ast/fnv.h generated
+make ${INSTALLROOT}/include/ast/aso.h
+prev include/aso.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' include/aso.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/aso.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/aso.h
+exec - fi
+done ${INSTALLROOT}/include/ast/aso.h generated
+make ${INSTALLROOT}/include/ast/dirent.h
+prev std/dirent.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' std/dirent.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/dirent.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/dirent.h
+exec - fi
+done ${INSTALLROOT}/include/ast/dirent.h generated
+make ${INSTALLROOT}/include/ast/iconv.h
+prev std/iconv.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' std/iconv.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/iconv.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/iconv.h
+exec - fi
+done ${INSTALLROOT}/include/ast/iconv.h generated
+make ${INSTALLROOT}/include/ast/nl_types.h
+prev std/nl_types.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' std/nl_types.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/nl_types.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/nl_types.h
+exec - fi
+done ${INSTALLROOT}/include/ast/nl_types.h generated
+make ${INSTALLROOT}/include/ast/stdio.h
+prev std/stdio.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' std/stdio.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/stdio.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/stdio.h
+exec - fi
+done ${INSTALLROOT}/include/ast/stdio.h generated
+make ${INSTALLROOT}/include/ast/wchar.h
+prev std/wchar.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' std/wchar.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/wchar.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/wchar.h
+exec - fi
+done ${INSTALLROOT}/include/ast/wchar.h generated
+make ${INSTALLROOT}/include/ast/wctype.h
+prev std/wctype.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' std/wctype.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/wctype.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/wctype.h
+exec - fi
+done ${INSTALLROOT}/include/ast/wctype.h generated
+make ${INSTALLROOT}/include/ast/align.h
+prev align.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' align.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/align.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/align.h
+exec - fi
+done ${INSTALLROOT}/include/ast/align.h generated
+make ${INSTALLROOT}/include/ast/preroot.h
+prev preroot.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' preroot.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/preroot.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/preroot.h
+exec - fi
+done ${INSTALLROOT}/include/ast/preroot.h generated
+make ${INSTALLROOT}/include/ast/sig.h
+prev sig.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' sig.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/sig.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/sig.h
+exec - fi
+done ${INSTALLROOT}/include/ast/sig.h generated
+make ${INSTALLROOT}/include/ast/tmx.h
+prev tmx.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' tmx.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/tmx.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/tmx.h
+exec - fi
+done ${INSTALLROOT}/include/ast/tmx.h generated
+make ${INSTALLROOT}/include/ast/tv.h
+prev tv.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' tv.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/tv.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/tv.h
+exec - fi
+done ${INSTALLROOT}/include/ast/tv.h generated
+make ${INSTALLROOT}/include/ast/ast_api.h
+prev ast_api.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_api.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_api.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_api.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_api.h generated
+make ${INSTALLROOT}/include/ast/ast_botch.h
+prev ast_botch.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_botch.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_botch.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_botch.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_botch.h generated
+make ${INSTALLROOT}/include/ast/ast_ccode.h
+prev ast_ccode.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_ccode.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_ccode.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_ccode.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_ccode.h generated
+make ${INSTALLROOT}/include/ast/ast_fcntl.h
+prev ast_fcntl.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_fcntl.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_fcntl.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_fcntl.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_fcntl.h generated
+make ${INSTALLROOT}/include/ast/ast_float.h
+make ast_float.h
+prev FEATURE/float
+exec - cmp 2>/dev/null -s FEATURE/float ast_float.h || { rm -f ast_float.h; silent test -d . || mkdir .; ${STDCP} FEATURE/float ast_float.h; }
+prev ast_common.h implicit
+done ast_float.h generated
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_float.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_float.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_float.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_float.h generated
+make ${INSTALLROOT}/include/ast/ast_fs.h
+prev ast_fs.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_fs.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_fs.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_fs.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_fs.h generated
+make ${INSTALLROOT}/include/ast/ast_lib.h
+prev ast_lib.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_lib.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_lib.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_lib.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_lib.h generated
+make ${INSTALLROOT}/include/ast/ast_map.h
+prev ast_map.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_map.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_map.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_map.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_map.h generated
+make ${INSTALLROOT}/include/ast/ast_mmap.h
+prev ast_mmap.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_mmap.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_mmap.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_mmap.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_mmap.h generated
+make ${INSTALLROOT}/include/ast/ast_mode.h
+prev ast_mode.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_mode.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_mode.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_mode.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_mode.h generated
+make ${INSTALLROOT}/include/ast/ast_ndbm.h
+make ast_ndbm.h
+make FEATURE/ndbm
+meta FEATURE/ndbm features/%>FEATURE/% features/ndbm ndbm
+make features/ndbm
+done features/ndbm
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/ndbm
+prev std/stdio.h implicit
+done FEATURE/ndbm generated
+exec - cmp 2>/dev/null -s FEATURE/ndbm ast_ndbm.h || { rm -f ast_ndbm.h; silent test -d . || mkdir .; ${STDCP} FEATURE/ndbm ast_ndbm.h; }
+done ast_ndbm.h generated
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_ndbm.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_ndbm.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_ndbm.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_ndbm.h generated
+make ${INSTALLROOT}/include/ast/ast_param.h
+prev ast_param.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_param.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_param.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_param.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_param.h generated
+make ${INSTALLROOT}/include/ast/ast_sys.h
+prev ast_sys.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_sys.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_sys.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_sys.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_sys.h generated
+make ${INSTALLROOT}/include/ast/ast_time.h
+prev ast_time.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_time.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_time.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_time.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_time.h generated
+make ${INSTALLROOT}/include/ast/ast_tty.h
+prev ast_tty.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_tty.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_tty.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_tty.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_tty.h generated
+make ${INSTALLROOT}/include/ast/ast_vfork.h
+prev ast_vfork.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_vfork.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_vfork.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_vfork.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_vfork.h generated
+make ${INSTALLROOT}/include/ast/ast_wait.h
+prev ast_wait.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_wait.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_wait.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_wait.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_wait.h generated
+make ${INSTALLROOT}/include/ast/ast_limits.h
+prev ast_limits.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_limits.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_limits.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_limits.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_limits.h generated
+make ${INSTALLROOT}/include/ast/ast_standards.h
+prev ast_standards.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_standards.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_standards.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_standards.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_standards.h generated
+make ${INSTALLROOT}/include/ast/ast_sizeof.h
+make ast_sizeof.h
+make FEATURE/sizeof
+meta FEATURE/sizeof features/%>FEATURE/% features/sizeof sizeof
+make features/sizeof
+done features/sizeof
+exec - iffe -v -X ast -X std -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' run features/sizeof
+done FEATURE/sizeof generated
+exec - cmp 2>/dev/null -s FEATURE/sizeof ast_sizeof.h || { rm -f ast_sizeof.h; silent test -d . || mkdir .; ${STDCP} FEATURE/sizeof ast_sizeof.h; }
+done ast_sizeof.h generated
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_sizeof.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_sizeof.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_sizeof.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_sizeof.h generated
+make ${INSTALLROOT}/include/ast/ast_dirent.h
+prev ast_dirent.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_dirent.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_dirent.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_dirent.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_dirent.h generated
+make ${INSTALLROOT}/include/ast/ast_iconv.h
+prev ast_iconv.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_iconv.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_iconv.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_iconv.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_iconv.h generated
+make ${INSTALLROOT}/include/ast/ast_nl_types.h
+prev ast_nl_types.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_nl_types.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_nl_types.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_nl_types.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_nl_types.h generated
+make ${INSTALLROOT}/include/ast/ast_stdio.h
+prev ast_stdio.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_stdio.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_stdio.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_stdio.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_stdio.h generated
+make ${INSTALLROOT}/include/ast/ast_wchar.h
+prev ast_wchar.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_wchar.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_wchar.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_wchar.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_wchar.h generated
+make ${INSTALLROOT}/include/ast/ast_wctype.h
+prev ast_wctype.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' ast_wctype.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/ast_wctype.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/ast_wctype.h
+exec - fi
+done ${INSTALLROOT}/include/ast/ast_wctype.h generated
+make ${INSTALLROOT}/lib/file
+exec - if silent test ! -d ${INSTALLROOT}/lib/file
+exec - then mkdir -p ${INSTALLROOT}/lib/file
+exec - fi
+done ${INSTALLROOT}/lib/file generated
+make ${INSTALLROOT}/lib/file/magic
+prev ${INSTALLROOT}/lib/file
+make misc/magic.tab
+done misc/magic.tab
+exec - test '' = 'misc/magic.tab' || ${STDCMP} 2>/dev/null -s misc/magic.tab ${INSTALLROOT}/lib/file/magic || { ${STDMV} ${INSTALLROOT}/lib/file/magic ${INSTALLROOT}/lib/file/magic.old 2>/dev/null || true; ${STDCP} misc/magic.tab ${INSTALLROOT}/lib/file/magic ;}
+done ${INSTALLROOT}/lib/file/magic generated
+make ${INSTALLROOT}/include/ast/fmtmsg.h
+prev comp/fmtmsg.h
+prev ast_lib.h
+exec - case ${mam_cc_HOSTTYPE} in
+exec - win32.*)proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' comp/fmtmsg.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/fmtmsg.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/fmtmsg.h
+exec - fi
+exec - ;;
+exec - *) silent grep -l 'define[ ][ ]*_[hl][di][rb]_fmtmsg' ast_lib.h > /dev/null || {
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' comp/fmtmsg.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/fmtmsg.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/fmtmsg.h
+exec - fi
+exec - }
+exec - ;;
+exec - esac
+prev ${INSTALLROOT}/include/prototyped.h implicit
+done ${INSTALLROOT}/include/ast/fmtmsg.h generated
+make ${INSTALLROOT}/include/ast/libgen.h
+prev comp/libgen.h
+prev ast_lib.h
+exec - case ${mam_cc_HOSTTYPE} in
+exec - win32.*)proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' comp/libgen.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/libgen.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/libgen.h
+exec - fi
+exec - ;;
+exec - *) silent grep -l 'define[ ][ ]*_[hl][di][rb]_libgen' ast_lib.h > /dev/null || {
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' comp/libgen.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/libgen.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/libgen.h
+exec - fi
+exec - }
+exec - ;;
+exec - esac
+prev ${INSTALLROOT}/include/prototyped.h implicit
+done ${INSTALLROOT}/include/ast/libgen.h generated
+make ${INSTALLROOT}/include/ast/syslog.h
+prev comp/syslog.h
+prev ast_lib.h
+exec - case ${mam_cc_HOSTTYPE} in
+exec - win32.*)proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' comp/syslog.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/syslog.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/syslog.h
+exec - fi
+exec - ;;
+exec - *) silent grep -l 'define[ ][ ]*_[hl][di][rb]_syslog' ast_lib.h > /dev/null || {
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1985,author=gsf+dgk+kpv' comp/syslog.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/syslog.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/syslog.h
+exec - fi
+exec - }
+exec - ;;
+exec - esac
+prev ast_namval.h implicit
+prev ${INSTALLROOT}/include/prototyped.h implicit
+done ${INSTALLROOT}/include/ast/syslog.h generated
+make ${INSTALLROOT}/include/ast/prototyped.h
+prev ${INSTALLROOT}/include/ast
+exec - echo "#include <../prototyped.h>" > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${INSTALLROOT}/include/ast/prototyped.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${INSTALLROOT}/include/ast/prototyped.h
+exec - fi
+done ${INSTALLROOT}/include/ast/prototyped.h generated
+done install virtual
+make test
+done test dontcare virtual
diff --git a/src/lib/libast/README b/src/lib/libast/README
new file mode 100644
index 0000000..cc0cf82
--- /dev/null
+++ b/src/lib/libast/README
@@ -0,0 +1,95 @@
+The advanced software technology department has been collecting useful C
+routines in a single library called libast. libast is used by nmake, the
+nmake cpp (which is mainly based on another library (libpp)), CIA
+(C information abstractor from Robin Chen), and a collection of other
+/bin and /usr/bin commands that benefit from concentrating functionality
+in libast.
+
+More detail is available in the man pages. libast contains:
+
+ (1) routines to support a generic environment for
+ a variety of UNIX operating system variants
+
+ (2) routines that update standard libc routines
+
+ (3) routines shared between several commands
+
+If you already have nmake 2.0 or newer installed then use
+`nmake install' from this directory, otherwise use
+ship/shipin from the root of the distribution directory tree.
+
+Some of the routines not found in section 3:
+
+hash: generic, scoped hash table support
+
+ hashalloc create a hash table or push new scope
+ hashdump debug dump of one or all hash tables
+ hashfree free a hashalloc()'d table
+ hashlook low level name lookup
+ hashscan entry generator for scoped table scan
+ hashsize explicitly change table size (usually automatic)
+ hashwalk apply function to each table entry
+ memhash return hash code for n-char chunk of memory
+ strhash return hash code for null terminated string
+
+include/ast: libast support headers
+
+ align.h compile time type alignmnent support
+ dirent.h POSIX directory(3) interface definitions
+ error.h error() interface definitions
+ ftw.h ftwalk() interface definitions
+ hash.h hash*() interface definitions
+ ls.h strls() interface definitions
+ re.h re*() interface definitions
+ tar.h POSIX ustar format interface definitions
+ tm.h tm*() interface definitions
+
+misc:
+
+ cmdargs apply a sequence of cmd line option parsers
+ cmdopen like popen() but stdin and stdout are specified
+ cvtatoe convert ASCII to EBCDIC
+ cvtetoa convert EBCDIC to ASCII
+ error output generic error and trace messages
+ ftwalk an ftw(3) that works -- used in new tw(1)
+ getcwd uses $PWD if ok, doesn't use /bin/pwd
+ getshell return full path of shell for cmdopen()
+ ooptget optget() for obsolete ar(1) and tar(1) options
+ optget YA getopt(3) but no argc or error message output
+ pathaccess find file with specific acces on list of dirs
+ pathcanon canonicalize path name in place
+ pathcmd return full path name of executable using $PATH
+ pathroot determine `related root' directory for command
+ perror uses strerror()
+ readargs append each line of file to argv[0]
+
+re: egrep(1) and ed(1) style re's from V9
+ (not the good awk(1) algorithm)
+
+ recomp compile re pattern
+ reerror report re*() errors
+ reexec match string using compiled re
+ resub ed(1) style substitute using last reexec()
+
+string:
+
+ chresc return next char in string converting \ sequences
+ ctoi convert char constant string to int
+ strcopy like strcpy(3) but returns end of destination
+ strdup malloc(3) and strcpy(3) smashed together
+ strerror return error message string given errno
+ stresc convert \ sequences in string in place
+ streval evaluate C expression in string
+ strls ls -l format support
+ strmatch Korn shell file pattern match
+ strmode return ls -l style output given st.st_mode
+ strsignal return signal id string given SIG* number
+ strtape convert generic tape unit to /dev/* file
+ token generate space separated tokens in string
+
+tm: time conversion support
+
+ tmdate convert date string to time_t
+ tmform format time_t to date string
+ tmmake return current time_t
+ tmtime convert struct tm to time_t
diff --git a/src/lib/libast/RELEASE b/src/lib/libast/RELEASE
new file mode 100644
index 0000000..cb9fb68
--- /dev/null
+++ b/src/lib/libast/RELEASE
@@ -0,0 +1,1769 @@
+12-03-10 misc/optget.c: HELP_index for "PLUGIN" too
+12-02-29 include/shcmd.h: PLUGIN_VERSION 20111111 for cdt disc/meth change
+12-02-29 comp/spawnveg.c: fix sigcritical() to include waitpid() for internal child
+12-02-29 malloc.c: make __malloc_hook initialization thread safe
+12-02-24 comp/iconv.c: fix winix UTF-8 vs UCS-2 over-conversion
+12-02-24 astsa/*.h: clean up header guards
+12-02-24 astsa/astsa.omk: clean up standalone old make makefile interactions
+12-02-21 misc/cmdarg.c: fix bug that set argv[0]
+12-02-10 sfvprintf.c: fix 1 byte too long buffer access
+12-02-07 malloc.c/features/vmalloc: add gnu __malloc_hook tests
+12-02-06 vmmopen.c: fix ALIGN vs sys/param.h macro conflict
+12-02-02 astlicense.c: add license.component for component-specific licenses
+12-01-31 spawnveg.c: fix transient bug that made invalid setpgid() call
+12-01-27 pathpath.c: fix buffer size math when internal allocation requested
+12-01-24 malloc.c: fix _vmkeep() bug that did not return previous state
+12-01-23 malloc.c: add VMALLOC_OPTIONS=break to try sbrk() block allocator first
+12-01-21 astlicense.c: option style only overrides default license.type
+12-01-18 malloc.c: disable multiple regions for tracing or !vmbest or ASO_SIGNAL
+12-01-12 sfpkrd.c: add __sun I_PEEK+rsh runtime workaround
+12-01-10 shcmd.h: void* => Shbltin_t*
+12-01-10 tmxdate.c: handle { n>=1000 } TM_PARTS
+11-12-21 plug up some meory links -- thanks mhlavink
+11-12-21 vmprivate.c: enclose VM_NONMEM exception in CLRLOCK(vm,0) ... SETLOCK(vm,0)
+11-12-13 aso: in -lposix for uwin, not -last -- just like vmalloc
+11-12-13 sfpoll.c: all streams SF_IOINTR => don't ignore EINTR
+11-12-13 sfdcslow.c: set SF_IOINTR
+11-12-09 malloc.c: add _vmkeep() for setlocale() intercept _SYS_setlocale_free_OK
+11-12-04 sfio: _Sfmaxr=0 (unlimited) by default; use ulimit -M|-d or SFIO_OPTIONS
+11-12-01 aso: sync to new api
+11-11-11 optget.c: move .TH to the top for --nroff to get our macros first
+11-11-11 aso,cdt,vmalloc: resync with kpv
+11-11-11 cdt: preserve bits and Dt_link_t for CDT_VERSION < 20111111
+11-10-24 sfvprintf.c: %.-ns truncate from left to n chars
+11-10-21 sfvprintf.c: fix %0s (no width) core dump
+11-10-10 aso: add _WIN32 support
+11-09-26 vmalloc: sync with kpv
+11-08-29 features/{dirent,wchar,wctype}: eliminate #include with no header
+11-08-25 #pragma prototyped tweaks -- sun4 is dead, long live sun4
+11-08-25 ftwalk.c: FTS_SLNONE => FTW_SL
+11-08-11 features/wchar: fix #include _nxt_wchar for K&R C
+11-08-04 optget.c: tweak --html rendering
+11-07-24 mime.c: add %(default)[st] default if arg == ""
+11-07-21 setlocale.c: fix debug locale to treat "<<" as two single byte chars
+11-06-14 spawnveg.c: pgid -1: new session -2: setpgrp()&&tcsetpgid()
+11-06-14 pathprog.c: add darwin _NSGetExecutablePath
+11-05-14 features/common,features/align.c: { _X86_ _X64_ } conditionals for generic uwin
+11-05-13 tm/tminit.c: tweak tzname[] prototype
+11-05-09 astlicense.c: add ". file" parent-relative include and depth 4 input stack
+11-05-05 cmdarg: update to cmdopen_20110505 api
+11-05-03 sfio/sfclose.c: make sure close() errors propagate to sfclose() return value
+11-04-20 port/astlicense.c: add { id name } keys
+11-04-15 fmtdev.c: fix to work for non-{blk,chr} special
+11-04-12 stk: change size args to size_t and stseek() offset to ssize_t
+11-04-12 sfio: sync with kpv to optimize large SF_STRING sfputr() buffer allocation
+11-03-28 misc/fts.c: fix FTS_SLNONE logic to set it when it should!
+11-03-17 misc/stk.c: fixed bug that could delete an active stack frame
+11-03-10 sfio/sfvprintf.c: add %0<width>s to preserve <width> trailing chars in string arg
+11-03-09 misc/magic.c: add %d...%s where if %d==1 then %s=="" else %s=="s"
+11-03-09 misc/magic.tab: add windows ico
+11-02-08 misc/stk.c: change STK_FSIZE to (1024*sizeof(char*)) for 64 bit normalization
+11-02-02 sfio/sfmode.c: don't call sfsetbuf() on unbuffered stream to make it unbuffered
+11-02-02 features/wchar: handle hp.ia64 va_list interactions
+11-02-02 comp/omitted.c: fix mismatch between stat() vs _stat()
+11-01-31 std/wctype,features/wctype: add to handle <wchar.h> interactions
+11-01-28 add -lw for ancient sunos
+11-01-28 include/magic.h,misc/magic.c: add MAGIC_ALL
+11-01-27 tm/tmxfmt.c,tmpoff.c: %_z for SHH:MM
+11-01-25 features/wchar: change <wctype.h> <wchar.h> ordering
+10-12-24 sfstrtof.h: fix thousand grouping bug that did not check last group
+10-12-21 pathkey.c: add win32 { /32 /64 } preroot to hash
+10-12-09 pathprog.c: handle intermediate path != '* and fix invalid pathpath() call
+10-12-01 astconf.c: fix look.standard undefined variable reference
+10-12-01 sfset.c: SF_LINE|SF_WCWIDTH => no need for sfsetbuf() to call isatty()
+10-12-01 sfsetbuf.c: cache /dev/null <dev,ino> to cut down /dev/null stat()'s
+10-12-01 optget.c: delay dictionary initialization until needed
+10-11-30 malloc.c: drop { VMDEBUG VMETHOD VMPROFILE VMTRACE } env checks
+10-11-30 port/astconf.c: eliminate esaccess() calls for OP_universe checks
+10-11-24 regcomp.c: [[=]=]] must at least match itself in non-C locales
+10-11-23 glob.h,glob.c: add GLOB_GROUP => REG_SHELL_GROUP
+10-11-20 glob.c: handle mode switches across /
+10-11-19 regcomp.c: REG_SHELL => REG_CLASS_ESCAPE
+10-11-16 vmalloc.h: add VMFL tracing to vmstrdup()
+10-11-16 ast.h: simplify VMDEBUG _BLD_DEBUG and VMFL logic
+10-11-12 tm/tmlocale.c: ast TM_* extensions default to C locale
+10-11-10 regex/regnexec.c,vmalloc/vmstat.c: eliminate strict-aliasing puns
+10-10-20 misc/translate.c: change debug translation to drop " in (a,b,c,"d")
+10-10-10 misc/glob.c: drop ancient D_FILENO(d)!=0 test and trust readdir()
+10-10-06 misc/translate.c: fix "debug" locale logic
+10-10-04 misc/magic.c: fix magic() skip check to honor the continuation
+10-10-04 regex/regcoll.c: add wchar_t* args to regcollate(), drop ucs name lookup
+10-09-28 comp/setlocale.c: add utf8_wctomb()
+10-09-28 string/chresc.c,regex/regcoll.c: fix \S[.X.] (\C[.X.] never worked!)
+10-09-24 string/chresc.c: \Cc for control c, \S[.X.] for collating symbol X
+10-09-24 string/chresc.c: { \cc \e } deprecated
+10-09-22 regex/regcomp.c: fix off-by-one collation class allocation bug
+10-09-20 regex/regclass.c: fix CTYPES off-by-one bug
+10-09-14 comp/conf.sh: const int conf_elements, prefix_elements;
+10-09-08 add features/sizeof => ast_sizeof.h
+10-08-31 comp/getopt[l].c: export functions for dlls
+10-08-25 port/lc.c: add features/locale check for canonical UTF-8 spelling
+10-08-20 include/ast.h: add export plugin_version() prototype
+10-08-20 comp/conf.tab: add SF_BUFSIZE
+10-08-11 misc/conformance.c: conformance(0,0) => "standard"
+10-08-11 misc/conformance.c: check ast_env_serial for dynamic astconf() changes
+10-08-11 port/lcgen.c: remember to fudge Table_t.count for synthesized entries
+10-08-04 include/ast.h,comp/setlocale.c: add { debug C.UTF-8 } mbalpha() mbwidth()
+10-08-02 misc/translate.c: add NLSPATH message cache check
+10-07-29 string/fmtint.c: fix nasty bug that rendered "1000" as "1"
+10-07-27 setlocale,lsgen,localeconv: handle C vs C_EU decimal thousands sep
+10-07-26 misc/optget.c: fix interaction with nested plugin/builtin calls
+10-06-29 string/strtoi.h: strton() multiplier 1 => power of two suffix
+10-06-28 features/wchar: handle systems that require __va_list => va_list
+10-06-28 comp/conf.tab: another PID_MAX tweak -- default to 99999 for most
+10-06-28 port/astconf.c: lone "CONFORMANCE = standard" => all defaults standard
+10-06-25 misc/optget.c: avoid sfprints() call during initialization
+10-06-01 features/api, ast_api.h: formalized forwards/backwards api compatibility
+10-06-01 _AST_API=20100601: add size_t args for all path*() output buffers
+10-06-01 comp/setlocale.c: handle C.UTF-8 test locale
+10-06-01 include/mc.h: add size_t to mcfind() for result buffer (internal api)
+10-06-01 use strlcpy() instead of strncpy()
+10-05-28 include/ast_version.h: add AST_PLUGIN_VERSION for dllplugin()
+10-05-28 include/shcmd.h: add SH_PLUGIN_VERSION for dllplugin()
+10-05-28 misc/conformance.c: add conformance(3)
+10-05-28 misc/optget.c: add [(id1|id2)...] conformance("id1|id2",0) conditionals
+10-05-25 include/sfhdr.h: adjust SF_NMAP according to _ptr_bits
+10-05-25 include/shcmd.h: add sh_builtin() macro for lib_init() table initialization
+10-05-21 misc/optget.c: --html \bfoo::bar([[:digit:]][[:upper:]]*) => foo-bar.html
+10-05-15 include/proc.h,misc/procopen.c: add PROC_ORPHAN
+10-05-09 misc/optget.c: add --???MAN[section] --???SECTION
+10-05-07 sfio,stdio: fix all snprintf() variants to handle buf==0 and/or n==0
+10-05-04 string/fmtesc.c: add mb iswsoace() and iswcntrl() quoting checks
+10-05-03 fix LC_MESSAGES catalog lookup bugs, check for $set==3, accept $set==1
+10-04-30 string/chresc.c: add chrexp() for FMT_EXP_*
+10-04-30 string/stresc.c: add strexp() for FMT_EXP_*
+10-04-30 string/chresc.c: fix \uXXXXY bug that consumed Y
+10-04-22 misc/optget.c: check for html entities in <A name="...">
+10-04-22 misc/getcwd.c: add features/syscall check for SYSGETCWD() { linux solaris }
+10-04-22 string/stresc.c: wide chars absent locale guidance default to UTF-8
+10-04-12 port/mnt.c: favor bsd getfsstat() over getmntinfo()
+10-04-11 string/strtoi.h: k (1000) and ki (1024) now differentiated
+10-04-10 misc/recstr.c: fix 'd[delimiter]' parse
+10-04-08 include/vmalloc.h,vmalloc/vmstat.c: add Vmstat_t.mode region mode bits
+10-04-05 misc/fts.c: drop 1997-01-07 fts_open()=0 is one file and stat() fails
+10-04-05 misc/optget.c,optlib.h: add Optpass_t.release for --nroff .TH
+10-04-02 misc/optget.c: fix $'[-n?\n...]' --version bug
+10-04-02 regex/regcomp.c: ~(X) => REG_EXTENDED|REG_AUGMENTED, ~(PU) instead of ~(U)
+10-03-24 misc/procopen.c: add PROC_FD_CTTY(fd)
+10-03-24 path/pathtemp.c: fix pointer => int casts
+10-03-15 regex/regcache.c: fix 1 byte buffer overflow (didn't count trailing \0)
+10-03-08 features/tvlib: fix utimensat probe to include all macros/structs
+10-03-07 features/lib: change stream_peek to test pipes only
+10-03-07 string/strelapsed.c: fix next char return overrun
+10-03-06 tm/tvtouch.c: use runtime fallback if utimensat() fails with ENOSYS
+10-03-05 path/pathtemp.c: add pfx /seed for regression testing
+10-03-04 vmalloc/vmwalk.c: add user supplied handle arg
+10-03-04 path/pathtemp.c: properly handle mktemp()-style *+(X) templates
+10-03-03 include/ast_getopt.h: remove NULL guard - _AST_GETOPT_H now handles it
+10-02-24 comp/getopt.h: fix ast_std.h interactions
+10-02-24 vmalloc/malloc.c: empty { VMALLOC_OPTION VMDEBUG ... } => no debug!
+10-02-02 string/base64.c: fix corner case output buffer overflow
+10-02-02 features/fs: sys/mnttab.h requires stdio.h on some systems!!
+10-02-01 misc/optget.c: uppercase --html heading -- doh
+10-01-29 misc/optget.c: [+NAME?...] overrides error_info.id for >= STYLE_man
+10-01-25 vmalloc/vmprivate.c: fix seg ptr initialization bug (24 years old!!)
+10-01-20 misc/optget.c: handle nested {...} rendering
+10-01-20 misc/state.c: add ast.version for runtime api version
+10-01-20 port/astconf.c: "_AST_VERSION" now returns ast.version
+10-01-20 include/ast_std.h: add ast.version for runtime api version
+10-01-19 astlicense.c: add epl
+10-01-01 vmalloc: VMALLOC_OPTIONS env var for all runtime options
+10-01-01 include: change some <ast.h> refs to less intrusive <ast_*.h>
+10-01-01 setlocale.c,translate.c,fmterror.c: AST_LC_internal retains prev state
+10-01-01 comp/setlocale.c: AST_LC_setenv defers to LC_ALL (for sh)
+10-01-01 ast_std.h: add { AST_LC_internal AST_LC_setenv }
+09-12-24 comp/setlocale.c: fix setlocale(LC_ALL,"") when already initialized
+09-12-17 misc/optget.c: handle mixed solaris usage="x:f:(in)yo:(out)"
+09-12-11 regex/regcomp.c: posix semantics for [z-a]
+09-12-11 regex/regcomp.c: fix BRE/ERE ^^ logic
+09-12-11 regex/regcomp.c: fix regcomb() for REG_LEFT|REG_RIGHT
+09-12-11 regex/regcomp.c: bm complete=0 if REX_END
+09-12-11 comp/sigflag.c: add with npt check in features/sig.sh
+09-12-11 tm/tminit.c: fix _tzset_environ logic
+09-12-09 tm/tmlocale.c: include "ast_nl_types.h" to pull nl_langinfo in!
+09-12-04 features/options: add "opt map-libc" check
+09-12-03 tm/tmxdate.c: fix 'next month final day' for dec -> jan
+09-11-21 misc/magic.tab: add gimp XCF
+09-11-20 vmalloc/vmtrace.c: add pid to assertion disgnostics
+09-11-11 regex.h,regcomp.c: add REG_CLASS_ESCAPE, \ inside [...] literal by default
+09-11-03 regex/regcache.c: change to variable length pattern strings
+09-10-28 include/error.h: fix ERROR_translate() arg parens
+09-10-26 port/lcgen.c,comp/setlocale.c: handle LANG init after LC_* already defined
+09-10-05 _sfopen.c: add but ignore 'F' flags for stdio compatibility
+09-09-28 fts.h,ftwalk.h,fts.c: promote { namelen pathlen level } to (s)size_t
+09-09-28 locales: add AST_LC_LANG for $LANG
+09-09-28 setlocale.c: fix logic for dynamic { LANG LC_ALL LC_* } changes
+09-09-17 include/sfio.h,sfio/sfwalk.c: add sfwalk()
+09-09-09 sfio/sfputr.c: add SIGPIPE hang fix
+09-08-24 sfio/sfreserve.c: fix SF_UNBOUND logic with pushed streams
+09-08-18 include/ast_std.h,ast.h: add ast.mb_sync to sync mbchar() after error
+09-08-17 comp/setlocale.c: add AST_LC_utf8 and { utf8_mbtowc() utf8_mblen() }
+09-08-11 comp/setlocale.c: treat "en"/"en_US" AST_LC_MESSAGES as "C"/"POSIX"
+09-08-10 vmalloc/vmhdr.h: add user-defined _AST_PAGESIZE and computed VMHEAPINCR
+09-08-09 comp/conf.tab: add NPROCESSORS_MAX
+09-07-29 astlicense.c: fix first name=value logic error
+09-07-22 string/fmtip6.c: don't drop trailing 0 in 44::1:0:0
+09-06-30 port/astconf.c: standard PATH_RESOLVE is "physical" (not "metaphysical")
+09-06-19 vmalloc: sync with kpv
+09-06-19 include/shcmd.h: add sh_context(p) cast
+09-06-11 misc/magic.tab: differentiate pc 386 32/64 bit dll/exe/obj
+09-06-06 port/astconf.c: fix look->name null pointer reference
+09-06-05 port/astconf.c: fix 'UNIVERSE = value' synthesize logic
+09-05-25 tm/tmxduration.c: add
+09-05-08 comp/syslog.c: add _UWIN /var/log/syslog preference
+09-05-01 comp/setlocale.c: fix _UWIN intercepts to return NiL on unknown locales
+09-04-27 sfio/sfpool.c: fix bug that did not return pool on delete
+09-04-22 include/regex.h,regex/regcomp.c: add REG_REGEXP <regexp.h> compatibility
+09-04-15 tm/tmxdate.c: handle "4th thursday in november"
+09-03-31 string/strvcmp.c,string/strnvcmp.c: add version strcmp(3)
+09-03-31 string/strpcmp.c,string/strnpcmp.c: add path prefix strcmp(3)
+09-03-29 misc/optget.c: clean up num = number casts
+09-03-04 tm/tmxmake.c: add tmxtm() with zone override
+09-03-03 tm/tmxfmt.c: add %(...)<c>, specifically %(...)z for output zone
+09-02-22 tm/tmxdate.c: add iso P... durations
+09-02-02 path/pathprog.c: add
+09-02-02 misc/opthdr.h,optget.c: fix flags mixup, handle old '-' as option
+09-02-02 sfio/sfprints.c: fix sfvaprints() return value to not count trailing '\0'
+09-02-02 misc/cmdarg.c: handle !defined(ARG_MAX)
+09-02-02 port/astconf.c: fix UNIVERSE overwrite of null[] value!
+09-01-31 features/sys: drop header sys/localedef.h
+09-01-28 include/fs3d.h,misc/fs3d.c: mount() => fs3d_mount() for diff std prototypes
+09-01-14 misc/fts_open.c: delay top list reorder until first fts_read()
+09-01-14 include/ls.h: LS_W_INUMBER => 9 to accomodate large st_ino
+09-01-14 misc/optget.c: expand STYLE_usage input text
+09-01-09 features/uwin,stdio/_stdfun.c: iffe for _p__iob and __p__iob
+09-01-09 misc/magic.tab: add ISO filesystem image entries
+09-01-07 string/strtoi.c: strtol() etc. do not consume [lLuU] suffix -- thanks jkf
+09-01-07 sfio/sfstrtof.h: strtod() etc. do not consume [fFlL] suffix -- thanks jkf
+09-01-05 string/strlcat.c: fix logic to match docs (not that easy)
+08-12-30 tm/tmxdate.c,include/tm.h: add TM_WORK { "workday" "working" "work" }
+08-12-28 sfio/sfcvt.c: fix 'a' format rounding
+08-12-21 tm/tmdata.c: add 2008-12-31+23:59:60-0000 leap second event
+08-12-19 tm/tmxdate.c: check for dates near the epoch rolling back to the future
+08-12-19 tm/tmxfmt.c: change %s for now==0 to be the epoch
+08-12-07 include/ast_std.h,misc/getenv.c: no _ast_getenv for uwin ast54 compatibility
+08-12-07 tm/tmxfmt.c: add %[_][EO]K for [space pad] [full|long] iso
+08-12-07 sfio/sfvscanf.c: fix ok[] short by one allocation
+08-12-07 comp/setlocale.c: fix off by one composite initialition loop test
+08-12-07 path/pathkey.c: fix off by one loop test
+08-12-04 vmalloc/vmbest.c: catch sbrk() wraparound
+08-12-04 comp/spawnveg.c: clean up attrs on failure too
+08-11-04 regex/regcomp.c: fix locale [!-...] and [^-...] re-initialization
+08-11-04 stdio: add flockfile.c ftrylockfile.c funlockfile.c
+08-10-24 port/astconf.c: handle multiple/trailing '/' in universe initialization
+08-09-10 misc/magic.c: handle old vcodex() indices
+08-09-10 sfio/sfvprintf.c: drop SF_WCWIDTH, use %Lc or %Ls instead
+08-09-05 Makefile: ibm.risc joins the :NOOPTIMIZE: crowd
+08-09-04 regex/regnexec.c: fix nested delimiter match beyond end of subject
+08-08-20 misc/fts.c: fix st_nlink stat() optimization logic
+08-08-19 sfio/sfpkrd.c: workaround macosx recv(PEEK) data consumption on non-socket
+08-08-19 strn?tol?d: handle long double with smaller exponent range than double
+08-08-18 sfio/sfcvt.c: eliminate excessive multiplies and integral overprecision
+08-08-11 tm/tmxfmt.c: handle %10N and %010N
+08-08-06 include/shcmd.h: add 'int invariant;' for builtin invariant arg count
+08-08-05 features/ndbm: favor sleepycat ndbm compatibility
+08-07-21 include/glob.h,misc/glob.c: GLOB_STARSTAR only forces lstat on chdir
+08-07-17 sfio: sync with kpv
+08-07-17 misc/optget.c: call astwinsize() each time terminal width required
+08-07-16 sfio/sfvscanf.c: fix %% to skip leading space per posix
+08-07-16 vmalloc/vmbest.c: add VMCHECK=m, VM_mmap to favor mmap() alloc
+08-07-16 features/stdio,stdio/f(read|write).c: size_t return value!! ouch
+08-06-24 tm/tmxfmt.c: fix %z to handle tm_isdst -- doh
+08-06-24 misc/astintercept.c,misc/getenv.c: split from misc/setenviron.c
+08-06-17 misc/setenviron.c: add { astintercept() getenv() }
+08-06-09 tm/tmlocale.c: use _DATE_FMT if defined for TM_DEFAULT
+08-06-06 misc/optget.c: handle sub-component about details
+08-06-04 misc/optget.c: fix [-n?\n...\n] version parse
+08-06-04 include/debug.h,misc/debug.c: merge with kpvdebug.h
+08-06-02 features/ndbm: add to tame dbmlib.iffe replication
+08-06-01 comp/resolvepath.c,realpath.c: fix resolvepath() return value type
+08-05-22 tm/tmxdate.c: fix a few ordinal/last/this/next bugs
+08-05-18 string/fmtre.c: fix omitted stack var initialization bug
+08-05-14 regex/regcomp.c,regcoll.c: fix UTF-8 collation sequence logic
+08-05-11 tm/tmxfmt.c: :NOOPTIMIZE:, otherwise %Q/../../ fails
+08-05-01 tm/tmxdate.c: mon 1..12 => mon[13] -- doh
+08-04-30 misc/glob.c,reegex/regcomp.c: ~(R) => ~(O) to avoid pcre clash
+08-04-24 port/astconf.c: 'name = value' does assignment without system init
+08-04-15 port/astconf.c: SC#N treated like 'SC(N)'
+08-04-14 misc/optget.c: clean up nroff output
+08-04-01 port/astconf.c: add RELEASE => /proc/version fallback
+08-03-30 misc/optget.c: [-n]... to enable -number & +number options
+08-03-06 misc/optget.c: ---* and +++* are now operands
+08-03-06 misc/errorx.c: fix old error_info.translate workaround
+08-02-05 regex/regcomp.c: allow REG_SHELL {,n}... => {0,n}...
+08-02-27 misc/stk.c: top element during allocation relocated to top
+08-02-18 include/ip6.h,string/strtoip6.c,fmtip6.c: add ipv6 addr support
+08-02-14 regex/regsubexec.c: fix null match (tricky)
+08-02-14 regex/regsubcomp.c: fix SRE to match ksh
+08-02-11 comp/spawnveg.c: return proper errno on [v]fork() failure
+08-02-11 tm/tmxdate.c,tmdata.c: handle more ISO 8601:2000 forms
+08-02-02 regex/reglib.h: add REGMULTIREF to REG_COMP
+08-02-02 string/strmatch.c: fix str="" pat="" sub values
+08-01-31 comp/conf.sh,conf.tab: handle /bin/sh \ in read data, redir subshell
+08-01-18 misc/magic.tab: amd-x68, 64-bit => x86-64
+08-01-18 string/strnton.c,strntonll.c: add
+07-12-10 string/strelapsed.c: "0" is a valid elapsed time!
+07-12-02 sfio/sfreserve.c: preserve SF_SHARE sfrd() via sfreserve(f,0,0)
+07-11-21 comp/setlocale.c: add sjis_mbtowc() to work around [\~] translation
+07-11-15 features/signal.c: RT(1) .. RT(MAX-1) => RTMIN+1 .. RTMAX-1
+07-11-14 features/float: favor sscanf() due to gnu strto[l]d() nan bugs
+07-10-31 regex/regcomp.c: fix REX_COLL_CLASS node allocation size
+07-10-31 sfio/sfcvt.c: use signbit() if available
+07-10-31 features/isoc99: _ISOC99_SOURCE tests
+07-10-31 port/astmath.c: add -DN=8 for signbit()
+07-10-31 sfio/sfstrtod.h: don't forget about -0.0
+07-10-26 features/map.c: add { optopt optarg optind opterr }
+07-10-26 features/stdio: add _filbuf => _ast__filbuf
+07-10-26 comp/getsubopt.c: fix #undef that interfered with <ast_map.h>
+07-10-26 regex/regcomp.c: fix bug that missed ')' in ~(F)...
+07-10-12 port/astconf.c: fix CONF_ALLOC 16 bit overflow
+07-10-12 misc/fts.c: fix fts_close() to free the handle -- doh
+07-10-11 comp/setlocale.c: second and subsequent setlocale(*,"") reverts to previous
+07-10-11 path/pathprobe.c: add vfs ST_NOSUID check
+07-10-10 comp/conf.tab: add a few more xpg6 deferrals
+07-09-28 astsa: update to share with mainline src via _PACKAGE_astsa
+07-09-25 sfio/sfgetr.c: no limit on string stream line size
+07-09-25 sfio/sfextern.c: increase _Sfmaxr to 256*1024
+07-09-18 misc/procopen.c: tighten up SIGCHLD logic between parent/child
+07-09-18 misc/signal.c: unblock SIG_DFL after setting handler, sig<0 => don't unblock
+07-09-13 misc/fs3d.c: no $LD_PRELOAD => no 3d and avoids invalid mount(2) call
+07-09-11 vmalloc: vmstat(0,0)==1 => region in use, drop VM_primary|VM_secondary
+07-09-05 misc/recstr.c: handle [lL] gobbled by strtol() -- ouch
+07-08-17 path/pathprobe.c: handle '\r' in VERSION string
+07-07-17 regex/regcache.c: regcache(0,n,0) extends cache to size n (no shrinking)
+07-07-16 tm/tmdata.c: add 2005-12-31, drop 1999-12-31 (where did that come from?)
+07-05-21 tm/tmxfmt.c,tmxscan.c: %F => %L (TM_DEFAULT); %F => %Y-%m-%d
+07-05-15 sfio/sfvprintf.c: %h? and SFFMT_SHORT => raw bytes
+07-05-09 features/signal.c,features/siglist: use kill -l & strsignal()
+07-04-25 misc/optctx.c: add for opt_info switching
+07-04-24 misc/cmdarg.c,include/cmdarg.h: add CMD_CHECKED, CMD_SILENT
+07-04-24 misc/procopen.c,include/proc.h: add PROC_CHECK
+07-04-24 misc/procrun.c: add flags arg (current use PROC_ARGMOD)
+07-04-24 misc/cmdarg.c,include/cmdarg.h: move from src/cmd/tw
+07-04-20 port/(lclang.h|lc.c|mc.c|lclib.h|lcgen.c): separate lctab.c
+07-04-20 comp/conf.sh: defer to systems without 'grep -q' -- sigh
+07-04-20 comp/conf.sh: probe for LL integer constant initializer suffix
+07-04-20 include/syslog.h: <namval.h> => <ast_namval.h> for win32
+07-04-20 ast_namval.h: add as copy of include/namval.h for win32
+07-04-19 comp/conf.tab: fix SVID SI entries to probe SI_* (not _SI_*)
+07-04-13 tm/tmxdate.c,tm/tmzone.c: handle [-+]0000 UTC zone offset
+07-04-11 sfio/sfvprintf.c: add %F, propagate SFFMT_UPPER
+07-04-11 sfio/sfcvt.c: handle SFFMT_UPPER => nan/inf vs. NAN/INF
+07-04-02 comp/conf.tab,comp/conf.sh: add C/POSIX <stdint.h> symbols
+07-03-28 misc/optget.c: fix l10n --?-
+07-03-25 features/common: fix { ast_std.h ast_map.h stdint.h } logic
+07-03-21 error.h: move from error_info to (*_error_data_)
+07-03-21 misc/error.c: add errorctx() for error_info switching
+07-03-21 option.h: move from opt_info to (*_opt_data_)
+07-03-19 regex/regdecomp.c: fix REX_ONECHAR escapes and add REX_KMP
+07-03-11 tm/tmxscan.c,regex/regnexec.c: fix strict-alias transgressions
+07-02-27 comp/conf.sh: handle native getconf invalid numeric values
+07-02-21 comp/conf.sh,comp/conf.tab: handle SSIZE_MAX vs _POSIX_SSIZE_MAX
+07-02-20 sfio/sfvprintf.c: handle SF_WCWIDTH justification
+07-02-14 features/common: cover <stdint.h>, move to int_(bits)_t
+07-02-14 include/int.h: drop
+07-02-14 include/sfio.h: add SF_WCWIDTH
+07-02-12 comp/conf.sh: fix CONF_LIMIT bug that missed ULONG_MAX etc.
+07-02-12 comp/conf.tab: *LONGLONG* => *LLONG* to match posix
+07-02-12 features/float: *LONGLONG* => *LLONG* to match posix
+07-02-12 port/astconf.c: handle CONF_LIMITS_DEF with no deferral
+07-02-12 stdio/vasprintf.c: add trailing '\0' -- doh
+07-02-04 string/fmtelapsed.c: fix naive multi month/year logic
+07-02-02 misc/optget.c: add --??posix for getopts(1)/getopt(3)
+07-01-26 string/chresc.c: use mbchar()
+07-01-26 misc/optget.c: handle "o:-:" usage for old-style long options
+07-01-22 sfio/sfdisc.c,sfpool.c: handle push on streams with pending peek
+07-01-22 include/sfio.h: mv Sfieee_t to sfio/sfhdr.h
+07-01-17 tm/tmxfmt.c: fix terminating nil logic which clobbered size-1
+07-01-11 misc/stk.c: a 2 day marathon bug fix (can we release now dr ek?)
+07-01-05 comp/spawnveg.c: posix_spawnattr_setflags(POSIX_SPAWN_SETPGROUP)
+07-01-05 misc/error.c: fix multibyte vs. printable logic
+07-01-01 comp/conf.sh: LC_ALL=C
+06-12-26 tm/tmxdate.c: handle nn*.nnnn* == sec.ns
+06-12-20 features/libpath.sh: generalize sol.* LIBPATH patterns
+06-12-18 comp/setlocale.c: include ast_standards.h and ast_wchar.h !
+06-12-12 string/strperm.c: octal modes are absolute!
+06-12-11 comp/conf.tab: always defer ARG_MAX
+06-12-07 Makefile: fix conftab.c generation CCFLAGS to match build - doh
+06-12-04 sfio/sfcvt.c: fix (int) vs. (long) cast mismatches
+06-12-01 comp/conf.tab: add changes to cover solaris { bin xpg4 xpg6 }
+06-12-01 regex/reginit.c: adjust { SRE KRE } escaped (){}*? inside [...]
+06-12-01 sfio/sfcvt.c: add signbit/copysign tests
+06-11-22 comp/spawnveg.c: fix _real_vfork logic to work with 3d
+06-11-20 features/common: bias _ast_int8_t "long long" before "__int64"
+06-11-20 string/strperm.c: fix X to work with all ops (not just +)
+06-11-15 astconf.c,conf.tab: add CONF_DEFER_* for variable constants
+06-11-11 port/astconf.c: validate path arg w.r.t. underlying calls
+06-11-11 comp/conf.sh: fix S CONF_STANDARD bug, add D to defer to native
+06-11-11 comp/conf.tab: add D to defer to native
+06-11-01 include/vmalloc.h: avoid VM_FLAGS sys/v*.h clash
+06-11-01 include/ast.h: add FMT_PARAM for fmtquote()
+06-10-31 disc/sfdcseekable.c: add SFSK_DISCARD for seekable window control
+06-10-31 comp/spawnveg.c,features/lib: handle posix_spawn exit status 127
+06-10-30 features/lib: fix posix_spawn() fork() prototype conflicts
+06-10-30 string/fmtscale.c: fix 1024 rounding bugs
+06-10-27 disc/sfkeyprintf.c: handle 'i' (=='d') -- oops
+06-10-26 sfio/sfvprintf.c: %#d => fmtscale(1000), %#i => fmtscale(1024)
+06-10-26 features/map.c: _map_libc cleanup
+06-10-26 features/fcntl: add to the circle of trust
+06-10-26 features/sys: add <sys/socket.h> socklen_t
+06-10-26 include/regex.h: handle include before <ast_map.h>
+06-10-25 astconf "SHELL" => "SH" to avoid _POSIX_SHELL conflict
+06-10-25 comp/conf.*: drop no-op duplicate conftab.c entries
+06-10-18 string/fmtscale.c: 1000: n[.]n[n](kMGTPE), 1024: n[.]n[n](KMGTPE)i
+06-10-11 ast_std.h: now implies <sys/stat.h> (did on most before anyway)
+06-10-11 strtoi.h: ignore sign for 0, validate scale shift
+06-10-11 strdup.c,vmstrdup.c: handle 0 arg
+06-10-11 add sfstruse()/sfstropen() error checks
+06-10-10 misc/procopen.c: envv==environ => don't modify environ
+06-10-10 misc/procclose.c: return valid exit(1) status
+06-10-06 port/astconf.c,comp/conf.sh,comp/conf.tab: play nice with getconf(1)
+06-10-01 comp/conf.tab: SHELL default checks { _CS_PATH } X { ksh ksh93 sh }
+06-10-01 comp/conf.sh: export CONF_getconf to shell actions
+06-10-01 comp/putenv.c: always enable setenv() for procopen()
+06-10-01 misc/procopen.c: use pathshell() or astconf("SHELL",0,0) if PARANOID
+06-10-01 path/pathshell.c: localize the shell path patterns and accept ksh93
+06-09-28 Makefile: avoid ast <stdio.h> vix iffe -X ast -- doh
+06-09-27 regex/regdecomp.c: add
+06-09-26 regex/regcomp.c: handle KRE ~(...)<invalid-kre>
+06-09-25 reorganize to avoid native header intercepts
+06-09-15 uwin/crypt.c: _UWIN only!
+06-09-14 Makefile: tweak the ast_common.h bootstrap again (finally?)
+06-09-14 misc/optget.c: noncommercial => OPT_proprietary
+06-09-12 string/strelapsed.c: fix multi-char qualifier parse
+06-09-12 string/strtoi.h: drop [cClLqQwW] multipliers
+06-09-11 misc/optget.c: add numeric arg validity check
+06-09-07 misc/optget.c,tm/tmfix.c: fix uninitialzed var refs
+06-09-05 path/pathprobe.c: add version header verification
+06-08-01 Makefile: handle iffe vs FEATURE/common vs ast_common.h
+06-08-31 Makefile: add ast_map.h to the bootstrap list
+06-08-30 misc/glob.c: fix ~(E)re bug that stripped ~(E) before regcomp
+06-08-30 include/ast.h: add { integralof(x) pointerof(x) }
+06-08-27 string/strelapsed.c: fix off-by-one (too little) parse bug
+06-08-25 misc/optget.c: 0*<n>.* numeric option args => <n>.*
+06-08-22 misc/glob.c: handle ~(...) pattern options
+06-08-16 string/strelapsed.c: fix off-by-one (too far) parse bug
+06-08-16 regex/regcomp.c: accept but ignore ~(N)
+06-08-14 features/libpath.sh: add solaris LD_LIBRARY_PATH_64 check
+06-08-05 sfio/sfpool.c: pool SF_READ|SF_WRITE loop fix
+06-08-02 misc/fts.c: fix FTS_NOSTAT optimization to check for ..
+06-07-28 include/glob.h: add gl_extra for user globlist_t expansion
+06-07-27 features/common: #include "ast_map.h"
+06-07-26 comp/fnmatch.[ch]: allow <ast_map.h> to map fnmatch()
+06-07-22 cdt: snarf from kpv
+06-07-17 string/strperm.c: perm==-1 skips umask(1)
+06-07-17 sfio/sfvprintf.c: handle format invalid mb seq
+06-07-17 regex/regcomp.c: inline REG_SHELL => anchored, otherwise not
+06-07-17 regex/regcomp.c: inline B|G:basic E:REG_EXTENDED F|L:REG_LITERAL
+06-07-17 regex/regcomp.c: inline l:REG_LEFT r:REG_RIGHT
+06-07-17 regex/regcomp.c: inline a:REG_LEFT|REG_RIGHT p:~REG_LENIENT
+06-07-17 string/chresc.c: add \Uxxxxxxxx
+06-07-17 sfio/sfstrtof.h: ignore thousands sep after decimal
+06-07-17 string/tokline.c: splice() => spliceline() for bsd
+06-06-27 features/float,sfio/sfcvt.c: fix Nan logic
+06-06-27 port/astmath.c: fix long double isnan() test
+06-06-27 features/map.c: _map_libc for std => _ast_std
+06-06-25 string/strperm.c: handle posix = w.r.t. umask
+06-06-19 port/mnt.c,features/fs: handle netbsd getmntent api change
+06-06-18 regex/regstat.c: add REG_LITERAL check
+06-06-11 cdt/dtview.c: update from kpv
+06-05-31 sfio/sfhdr.h: fix _SFOPEN() typo
+06-05-09 comp/conf.sh: add native getconf -a names to the mix
+06-04-28 misc/optget.c: add solaris long option name compatibility
+06-03-09 string/strmatch.c: add REG_ADVANCE => REG_* flags
+06-02-14 comp/iconv.c: fix uwin iconv_list() /reg/ generator
+06-02-10 port/astconf.c: relax standard prefix filter
+06-02-08 sfrd.c,sfsync.c: lock logic bug fix
+06-02-01 port/astlicense.c: add { parent incorporation }
+06-01-26 port/astconf.c: fix { LIBPREFIX LIBSUFFIX } length
+06-01-06 features/lib: change _UNIV_DEFAULT probe to use cross{...}
+06-01-04 misc/stk.c: fix n**2 realloc behavior
+06-01-01 include/sfio.h: export { _Sfi _Sfmaxr }
+05-12-13 string/chresc.c: handle \C-X => control-X, \M- => ESC
+05-11-22 regex/regcache.c: add, convert string/strmatch.c to regcache()
+05-10-06 string/ccmap.c: update ebcdic-u to be idempotent
+05-09-28 vmalloc: snarf from kpv; fixes large block brk() thrashing
+05-09-26 misc/magic.c,misc/magic.tab: handle latest vcodex header
+05-09-12 misc/optget.c: reset opt_info.offset on error
+ string/strtoi.h: strton() '.' multiplier only if m>1
+ string/fmtesc.c: add unadvertized FMT_PARM for FMT_SHELL
+05-09-09 string/fmtesc.c: fix FMT_SHELL logic w.r.t. [$`]
+05-08-11 string/strerror.c: fix { sys_errlist sys_nerr } prototypes
+05-08-03 sfio: snarf sfvaprints sfaprints
+05-07-21 port/astconf.c: retain most recent synthesized lookup
+05-07-20 sfio/sfsetbuf.c: default file io size now 64K on all systems
+05-07-17 ccmap*: add microfocus cobol EBCDIC_U
+05-06-29 regex/regcomp.c: fix the A & B inline flag logic
+05-06-15 include/recfmt.h: add fs format flag to fmtrec()
+05-06-14 error.c: add ERROR_OPTIONS { break count match }
+05-06-07 features/stdio: drop FEATURE/limits to fix bootstrap circular dep
+05-06-02 features/*,Makefile: drop vestigel iffeio.h bootstrap workaround
+05-05-31 string/fmtbuf.c: unlock (spin) before each return -- doh
+05-05-30 sfio/sfpkrd.c: work around macos 10.4 recv(MSG_PEEK) bug
+05-05-27 regex: add REX_NEST (?%[S.][T.][OT])
+ magic.tab: ammend bsd db magic
+05-05-23 regex: REX_NEST (?%[D.][E.][L.][Q.][oc]...)
+05-05-21 regex: state.fold[] is now locale specific -- doh
+05-05-19 regex: add REX_NEST (?%\\()<>[]""...) %(...) nested match
+05-05-15 recfmt.h: add recstr() reclen() fmtrec()
+05-05-13 optget.c: allow boolean options to take numeric values
+05-05-12 recfmt.c: add to recfmt.h, adjust Recfmt_t encodings
+05-04-30 sfio: add sfmaxr(), default 64K
+05-04-22 comp/omitted.c: fix magic() logic for files < 512 bytes
+05-04-20 cdt: snarf update from kpv; void* Dt_t.user added
+ misc/error.c: library => ERROR_LIBRARY
+05-04-19 regex/regcomp.c: handle REG_SHELL [^...] == [!...]
+05-04-11 tm/tmxscan.c: handle yyy.mm.dd[-+.]hh.mm.ss.nnnnnn
+05-04-07 regex/regnexec.c: fix out of bounds boundary check -- ouch
+ features/align.c: add jmp_buf to the alignment mix (ia64)
+ vmalloc/vmhdr.h: add jmp_buf to the alignment mix (ia64)
+05-03-31 misc/optget.c: fix option { - _ } separator matching
+05-03-30 misc/glob.c: eliminate superfluous GLOB_NOMATCH stat() calls
+05-03-24 port/astwinsize.c: include <sys/ioctl.h> if possible
+05-03-23 string/ccmap.c: add ebcdic-m mvs cobol table
+05-03-11 comp/omitted.c: handle utime[s](const,const)
+ comp/conf.tab: fix linux PID_MAX probe
+05-03-10 comp/setlocale.c: LC_* value "" => unset -- doh
+ misc/optget.c: reorder _PACKAGE_astsa code for msgcc
+05-03-08 misc/optget.c: delete leading space in STYLE_nroff output
+05-03-07 sfio/sfhdr.h: drop extern _sfdscan -- clashes with sfvscanf.c static
+05-03-01 tm/tminit.c: add tmlocaltime() for tzset() getenv() override workaround
+05-02-20 features/tvlib: tmsettimeofday only for systems that have settimeofday
+ features/float: fix mvs.s390 NaN tests
+05-02-18 tm/tmxmake.c: fix <0 west of GMT bug that warped to 1800's -- wow
+05-02-11 port/mnt.c: handle lynxos MOUNTED=/etc/fstab
+05-02-08 features/float,sfio.h,sfcvt.c,sftable.c: add INF and fix NAN
+05-02-04 features/lib: add _std_strtol (for lynxos)
+ include/ast_std.h: add _std_strtol tests
+ comp/strtod.c: #define S2F_function strtod
+ misc/signal.c: fix ancient bsd SV_INTERRUPT vs. SV_ABORT clash
+05-01-11 sfio/sfmove.c: try to seek(fr) when fw==0
+ comp/omitted.c: intercept utimes() too
+ comp/omitted.c: add DOSPATHVARS env var path value conversions
+ features/tvlib,tm/tvtouch.c: check for utimets()
+ misc/optget.c: handle '-' or '_' option word separators
+ sfio/_sfopen.c: allow stream mode changes after initialization
+ sfio: sync with kpv: SF_SYNCED fix for ksh input loss bug
+05-01-09 tm/tmxfmt.c: fix %6N for n<100000000
+05-01-08 regex/regcomp.c: conj() => con() to avoid C99 clash
+05-01-05 tm/*: fix { %U %V %W } logic -- my head hurts
+04-12-30 tm/tmxtime.c: fix tm_isdst<0 loop
+04-12-23 vmalloc/vmbest.c: fix vmresize bug that didn't 0 new data
+04-12-19 misc/optget.c: broaden - long option match
+04-12-09 string/strtoi.h: fix terabyte 't' suffix math
+ string/strmatch.c: flush cache on locale change
+04-12-01 tm/tmsleep.c: add
+ tv.h,tv*.c,tv.3: move from pax
+ tmx.h,tmx*.c,tmx.3: add high resolution tm(3) counterparts
+ features/lib: add *another* sgi linux.ia64 memccpy bug check
+04-10-31 Makefile: __OBSOLETE__ now computed <6 months ago year>0101
+ ccode.h,ccmapid.c: add ccmaplist(Ccmap_t*) iterator
+ option.h,optesc.c: add 3rd arg, 1 => quote '?' too
+ misc/magic.c: fix bug that terminated `string \0a' at \0
+ misc/magic.c: handle vcodex() via decompose()
+ misc/magic.tab: add vcodex magic
+ features/stdio: handle _LARGEFILE64_SOURCE -- oops
+ stdio/(fseek|ftell|fseeko|fsetpos|fgetpos|ftello).c: oops^2
+04-10-28 string/swapop.c: size==-4 => size=4 and extend op=3 to op=7
+ tm/tmfix.c: fix tm_mon<0 logic
+04-10-22 tm/tmdate.c: handle 'final day feb 2004'
+ port/astlicense.c: add query=all|id|${...}${...}
+ port/astlicense.c: "free" => "mit"
+ comp/omitted.c: revert to the open source license
+ string/stropt.c: drop siz==0 => tab is hash table
+ include/sfio.h: incorporate <sfstr.h>
+ include/sfstr.h: drop
+ disc/sfstrtmp.c: drop -- use sfstrbuf()
+04-10-20 misc/magic.tab: update tar magic
+04-10-18 ufc-crypt.h,crypt_util.c: drop GPL code
+ crypt.c: add BSD code
+ pathpath.c: disable { $0 $_ $PWD } related root search
+04-10-01 normalize ident stamps
+ port/astlicense.c: add type=cpl -- yeah
+04-09-25 string/swapop.c: return op < size -- duh
+04-09-23 comp/spawnveg.c: :NOOPTIMIZE: -- volatile sometimes ignored
+04-09-21 comp/spawnveg.c: exec_errno_ptr is volatile -- duh
+04-09-14 tm/tmscan.c: add %| alternation and %& => tmdate()
+04-09-08 misc/optget.c: add :!value: omitted optional arg value
+ misc/optget.c: fix --noNAME ambiguous option logic
+04-08-26 string/strperm.c: add who^mode to propagate least restrictive up
+ astmath.c: add { frexpl ldexpl } checks for ast.req
+ port/astlicense.c: ignore first option if non-assignment
+ include/ast_dir.h: move d_fileno map before struct defs -- duh
+04-08-24 vmalloc/vmbest.c: add {VM_region} VMCHECK=+r for region segment checks
+ misc/recfmt.c,include/recfmt.h: add
+04-08-23 vmalloc/vmbest.c: add {VM_primary VM_secondary} VMCHECK=-s for primary
+ features/common: punt to <stdarg.h> for unknown va_list
+04-08-11 vmalloc: sync _UWIN libposix hooks
+04-07-27 features/common,features/limits.c: ULL suffix for unsigned _ast_int8_t
+04-07-22 include/ast.h,comp/eaccess.c: add eaccess() for effective access()
+04-07-19 comp/open.c,sfio/_sfopen.c: { O_RDONLY O_WRONLY O_RDWR } are values
+04-06-28 misc/error.c: check level after error_info.auxilliary
+04-06-24 string/strmatch.c: strgrpmatch() match[] now variable size array
+04-06-17 features/common: change _DLL null define to (the standard ast) 1
+04-06-11 misc/optget.c: allow optional [-|+|--|++] optstr() option prefix
+ misc/optget.c: reset optstr() state on 0 return
+ misc/optget.c: text()=>textout() linux.ppc symbol hijack workaround
+04-05-31 sfio/sfreserve.c: no side buffer if user buffer is large enough
+04-05-27 string/fmtbuf.c: handle one concurrent buf > sizeof(buf)
+04-05-24 regcomp.c: fix no-advance initialization
+04-05-05 conf.tab,conf.sh: update to align with standards
+ magic.tab: ms suffix update
+04-05-04 port/lcgen.c: fix territory initialization
+04-04-15 tm/tmdate.c,include/tm.h: fix specific and ordinal days
+04-04-08 astconf: retain { HOSTTYPE LIBPATH LIBPREFIX LIBSUFFIX } strict vals
+04-04-07 vmalloc/vmbest.c: fix alpha tiny block bug
+ vmalloc/malloc.c: re-enable on alpha
+04-03-30 tm/tminit.c: GMT => UCT only if tz.daylight not defined
+04-03-25 vmalloc/malloc.c: _AST_std_malloc=1 for __alpha
+ path/pathprobe.c: per-user probe dir => $HOME/.probe/$HOSTTYPE
+04-03-23 regex/reglib.h: fix isw*() redefines
+04-03-17 features/stdio: no __FILE override for __CYGWIN_ (sys/reent.h clash)
+ sfio/sfhdr.h,sfio/sfsetbuf.c: lower sfmove() default buf size 4x
+04-02-29 comp/omitted.c: move env trace after PATH fixup
+ comp/omitted.c: cygwin spawn _P_DETACH => _P_NOWAIT+setpgid(pid,0)
+ misc/optget.c: fix html mailto: match
+ port/astlicense.c: add type=test for fixed 2001 date
+ features/float: check local NaNQ first
+ vmalloc/vmhdr.h: fix _vmextern_ vm_truncate return type
+ misc/magic.tab: add elf s390 index=22
+04-02-26 vmalloc: VMCHECK a:assertions c:arena-check w:warn-instead-of-abort
+ sfio/sfvscanf.c: fix extf arg selection
+04-02-24 features/dirent: set nodefine to avoid ast_std.h _typ_off64_t undef
+ disc/sfkeyprintf.c: only case pattern must be ()[] balanced
+04-02-14 include/sfio_t.h: add SF_DCDOWN, SFDCNEXT(), SFDCPREV()
+04-02-13 string/strmatch.c: fix bug that didn't save one-time sub[] size
+ vmalloc: -g: export VMCHECK=1 enable malloc/free checks
+ vmalloc: -g: free(0) to check and disable malloc/free checks
+ vmalloc: -g: free(1) to check and enable malloc/free checks
+04-02-11 Makefile: add :P=A: to conf and lcgen exec for cross-compile
+ regex: use MBSIZE() instead of mbsize() to grab 1 char on err
+ vmalloc/vmbest.c: updated to do more comprehensive DEBUG tests
+04-02-04 sfio/sfraise.c: add sfraise(0,a,b) to iterate over all streams
+04-02-01 vmalloc/vmbest.c: _BLD_DEBUG free(0) checks the arena
+04-01-31 features/vmalloc: fix typo that missed _mmap_zero
+04-01-23 string/strerror.c: handle real strerror() return value overwrite
+04-01-11 path/pathpath.c: fix size vs. sizeof(buf) typo
+03-12-22 misc/magic.tab: dos EXE tweaks
+03-12-05 vmalloc: sync with kpv, adding exceptf announcements
+03-12-04 port/astlicense.c: fix expand() loop sentinel bug
+03-12-02 include/ast.h: mbchar() advances by 1 on mbtowc() error
+ misc/fts.c: increase MINNAME to 32
+03-11-21 vmalloc/vmbest.c: export VMCHECK=1 to enable $(CC.DEBUG) vmcheck()
+ vmalloc/vmbest.c: export VMCHECK=2 to disable KPVCOMPACT
+ misc/magic.c: add { cobol copybook pl1 } and suffix preference
+03-11-12 features/stdio: drop cuserid,getopt for SUSV3
+03-11-11 vmalloc/*: merge kpv update -- this should stomp the compaction bug
+03-10-23 comp/iconv.c: fix sfreserve lock fallback
+03-10-20 sfio/_sfopen.c: add to allow user sfopen() intercept
+03-10-17 regnexec.c: fix exec time REG_LEFT, \x.... => wctomb()
+03-10-12 string/strtoi.h: fix strton '.' overconsumption
+03-10-12 comp/iconv.c: identity is always (iconv_t)0
+03-10-09 string/fmtesc.c: fix FMT_SHELL to check for all shell magic chars
+03-10-01 port/astlicense.c: unknown authors copied verbatim (instead of ignored)
+03-09-30 string/chresc.c: handle \u..., \x... consumes all trailing hex digits
+ string/stresc.c: \u... and \x... > UCHAR_MAX => wctomb()
+03-09-29 fnv.h: add
+03-09-23 modedata.c: table is for external modes, so no arch specific hacks
+ optget.c: fix option prefix match translation bug
+ optget.c: add `<length> <name>=<value>\n' to optstr()
+ features/lib: add memcmp() test for sgi optimzation bug
+03-09-22 regex.h,regcomp.c: add regncomp()
+ regclass.c: fix for loop dangling ; in regaddclass()
+03-09-20 sftable.c,sfvprintf.c: fix SFFMT_CHAR handling to match extf api
+03-09-19 sfmode.c: update release to kpv's
+03-09-17 regcomp.c: add pedantic backref error checks
+03-09-16 regnexec.c: exec time REG_LEFT => don't advance past initial position
+ regclass.c: add regaddclass() for user defined [:class:]
+ regexec.h: REG_VERSION_N2X, add redisc_t {re_map} ccode map
+ regstat.c: add regstat_t
+03-09-11 optget.c: --n:=v sets opt_info.assign=':', opt_info.number enabled
+03-09-09 disc/sfkeyprintf.c: *pn on lookup is arg separator; lookup "" arg too
+03-09-05 optget.c: [f:l*?] preserves user long name past '*' in opt_info.name[]
+03-09-03 sfstr.h: add sfstrpend() for #pending bytes in read buffer
+03-08-25 regex: add REG_FIRST, optimize bm
+ features/lib: _AST_no_spawnveg==1 falls back to fork/exec
+03-08-22 features/stdio,stdio/asprintf.c,stdio/vasprintf.c: add
+03-08-21 path/pathnative.c,path/pathposix.c: interix updates
+ features/botched: add cygwin _stat => _stat64
+03-08-15 include/ast.h: map out bsd strmode()
+ features/common: add interix _ast_intmax_t workarounds
+ misc/fs3d.c: 3d mount test now uses "" instead of NiL (or cygwin dumps)
+03-08-11 string/fmtesc.c: fix optional quoting checks
+ tm/tmdate.c: fix > 1 year of seconds arithmetic
+ tm/tmfix.c: fix leap year adjustments
+03-08-01 features/lib: beef up sock_peek test for interix
+03-07-29 features/float: add -lm to frexp... test
+ Makefile: fix -lm astmath test sense
+03-07-26 features/mem.c: favor _mem_sbrk over _mem_mmap_*
+03-07-22 vmalloc/vmbest.c: fall back to sbrk() if mmap() fails
+ features/mem.c: _mem_sbrk means sbrk() and brk() work
+03-07-17 regex/regcomp.c: fix bug that treated KRE X{n,m} like {n,m}(X)
+ misc/magic.c: check MAGIC_VERBOSE for all load() messages
+03-07-14 misc/optget.c: handle [...]{[...]\f...\f...}
+03-06-21 misc/sigcrit.c: block SIGCHLD if _lib_sigprocmask || _lib_sigsetmask
+ comp/spawnveg.c,sfio/sfmode.c: use sigcritical() SIG_REG_* macros
+ comp/spawnveg.c: drop ENOEXEC logic
+ vmalloc/*: snarf kpv KPVCOMPACT() fix
+ vmalloc/vmbest.c: export VMCHECK=2 to disable KPVCOMPACT (just in case)
+ string/strdup.c: drop __strdup() etc. intercepts -- malloc gets it
+ features/mem: define _mem_method and _mem_* possible values
+ vmalloc/malloc.c: _AST_mem_method==_mem_* to force mem get method
+ sfio/sfputr.c: __ia64 memccpy is bogus -- how many tries do they get?
+ path/pathshell.c: verify abs path and access(path,X_OK) -- duh
+ vmalloc/vmhdr.h: add private _Vmessage() for non-sfio ASSERT()
+ port/astconf.c: fix bug that always returned the minmax value
+03-06-11 comp/*.c: reorder macro hding for mvs.390 and <ast_map.h>
+ features/vmalloc: add _lib_brk and _lib_sbrk verification
+ include/ast_std.h,etc.: add _map_malloc for malloc => _ast_malloc
+ comp/conf.sh: fix SI_* and *_SI_* macro redefs
+ ast.h: VMDEBUG or _BLD_DEBUG enable <vmalloc.h> and VMFL tracing
+ vmalloc/vmtrace.c: _PACKAGE_ast __FUNCTION__ is a string
+ vmalloc/vmtrace.c: set trace file fd FD_CLOEXEC
+ vmalloc/vmbest.c: set /dev/zero mmap fd FD_CLOEXEC
+ features/mmap: fix ancient read() vs. mmap() time arithmetic typo
+ vmalloc/malloc.c: _AST_std_malloc==1 to force standard malloc
+03-06-09 comp/omitted.c: add _imp__FUNCTION sybols for __CYGWIN__ static link
+ vmalloc/vmbest.c: handle systems with sbrk() but no brk()
+03-06-04 port/astconf.c: drop non-standard diagnostics
+03-06-03 comp/conf.sh: rework symbol collision logic
+03-05-30 conf.tab,conf.sh,astconf.c: add <sys/systeminfo.h> sysinfo() SI_*
+03-05-29 ccode.h: rework for extensibility, drop obsolete mematoe(), memetoa()
+03-05-28 regex/*: recode to use isw*() directly when needed, is*() otherwise
+03-05-27 features/vmalloc: fix _std_malloc test
+03-05-25 misc/optget.c: fix optstr() ???* internal options
+03-05-24 misc/optget.c: fix (ancient) argv null dereference
+03-05-23 comp/getcwd.c: don't intercept on _WINIX -- unreliable st_ino
+03-05-22 sfio/sfsprintf.c: n<0 => don't append '\0'
+03-05-18 misc/fts.c: re-stat FTS_DP to update nlink/times
+ misc/fts.c: add FTSENT.stack to eliminate getlist() recursion
+ regex/ucs_names.h: use "..." catenation to placate some cc's
+03-05-11 string/strtoi.h: handle "-" "+" "0x" "11#"
+03-05-09 vmalloc/vmbest.c: large memory allocation tweaks
+03-05-06 misc/optget.c: fix getopt_long() prefix==1 bug that missed short flags
+03-04-27 comp/system.c: handle <ast_map.h>
+03-04-24 vmalloc/vmmopen.c: drop dup <unistd.h>
+03-04-21 tm/tmdate.c: fix next hour/min logic
+03-04-15 vmalloc/malloc.c: intercept __malloc() along with __libc_malloc()
+ string/strdup.c: intercept __strdup() along with __libc_strdup()
+ features/mmap: consolidate from features/(lib|sfio|vmalloc)
+ add _NO_MMAP==1 to disable all mmap()/munmap() calls
+ path/pathposix.c: add
+03-04-14 comp/setlocale.c: fix debug_mbtowc() return value for *s==0 || n < 1
+ comp/iconv.c: fix error return errno values
+03-04-11 misc/stk.c: fix stkgrow() realloc bug
+03-04-05 string/tok.c: support readonly single token input strings
+ disc/sfdcdio.c: fix F_DIOINFO and FDIRECT #ifdef's
+ include/ast_std.h: allow _LARGEFILE64_SOURCE on __hppa
+ features/common: fix `tst _foo_' => `tst foo_' typo
+ features/float: fix `tst _foo_' => `tst foo_' typo
+ features/float: add FLTMAX_(UINTMAX_MAX,INTMAX_MAX,INTMAX_MIN)
+ comp/omitted.c: fix pathconf => _pathconf => _ast_pathconf loop
+03-04-03 features/float: add _ast_no_um2fm: no usinged intmax => floatmax cast
+ vmalloc/vmbest.c: add getenv("VMCHECK") to initialize Vmcheck
+03-03-28 include/ast_dir.h: add D_TYPE; { D_FILENO D_TYPE } must be #ifdef'd
+ misc/fts.c|getcwd.c|glob.c,preroot/getpreroot.c: add D_FILENO #ifdef's
+ Makefile: make sure _BLD_ast is defined for all compiles
+03-03-27 ast_vfork.h: generate from features/vfork to pick up headers/pragmas
+03-03-25 comp/omitted.c: drop free() of live environ
+ path/pathshell.c: allow trailing .exe -- pox on that
+ string/strtoi.h: fix bug leading 3 digits before thousands sep bug
+ string/(fmt|str)[gu]id.c: we know root when we see it
+03-03-24 misc/optget.c: handle : and ? in := default value
+03-03-21 ast_std.h: drop all spawn*() but spawnveg()
+ obsolete/spawn.c: add for dropped spawn*()
+ features/lib: _use_spawnveg if spawnveg() is a win over fork()/exec()
+ features/lib: drop NutForkExecve() and _map_spawnve
+ features/lib: fix memccpy test to clean up /tmp droppings
+ comp/spawnveg.c: call posix_spawn() if implemented
+ comp/omitted.c: add spawnve() intercept
+ comp/getoptl.c: set getopt_long() optind even if no options
+ tm/tmfmt.c: add %Q<delim>recent<delim>distant<delim>
+ misc/optget.c: fix trailing '*' for option and option args
+ sfio/sfmode.c: getenv("_AST_SFIO_OPTIONS") [,]SF_LINE[,] for fd {0,1,2}
+ vmalloc/*: kpv sync for uwin build independent of libast
+03-03-18 port/astconf.c: switch to dynamic string values (saves 7K data/bss)
+ string/strmatch.c: switch to dynamic regex cache (saves 3K data/bss)
+ regex/regcoll.c,ucs_names.h: initialize rw tables from smaller ro data
+ features/lib: add vfork test for passing SIG_IGN across exec
+ features/lib: add spawn test for passing SIG_IGN across spawn
+03-03-17 comp/omitted.c: unlink() renames to .deleted dir in case file open
+ sfio/sfpopen.c: handle mode "" for spawn with no pipe
+ features/float,comp/frexp.c,comp/frexpl.c: add pow2() table alternative
+03-03-12 features/lib: fix linux.ia64 memccpy() tests -- now its their turn
+ features/vmalloc: fix /dev/zero test
+ features/align: _ast_intmax_t and _ast_fltmax_t join the union
+ misc/stk.c: fix struct frame size to align data
+ disc/sfdcdos.c: change sfslen() => sfvalue(f)
+03-03-10 misc/optget.c: handle [f\f:x:lll\f?ddd]
+03-03-07 port/astconf.c: uninitialized CONFORMANCE + POSIXLY_CORRECT => standard
+03-03-05 comp/omitted.c: make sure at least /bin is in PATH to find cygwin dlls
+03-03-02 path/pathshell.c: write access to /bin is effectively root
+03-02-28 features/float: add (FLT|DBL|LDBL)_U?(LONG|LONGLONG|INTMAX)_(MIN|MAX)
+03-02-25 features/lib: change vfork() test to use _exit() instead of exit()
+03-02-23 include/error.h: update ERROR_VERSION for error_info.number space
+03-02-22 comp/conf.sh: wrap ksh check in eval to avoid premature exit
+03-02-21 misc/fts.c: verify chdir(..) to avoid malicious dir rename()
+03-02-19 string/strtoip4.c: isspace() instead of ' '||'\t'
+03-02-17 regex/regcomp.c: fix stats.l REX_REP logic that botched REX_BM
+03-02-13 string/base64.c: handle catenated encodings
+03-02-11 features/libpath.sh: change LIBPATH to <dir>[:<env>[:<pat>]][,...]
+03-02-07 path/pathfind.c: allow "/dev/null" to be PATH_REGULAR
+03-02-06 include/ast.h,fmtquote.c: add FMT_ALWAYS|FMT_ESCAPED|FMT_SHELL|FMT_WIDE
+03-02-05 tm/tmdate.c,tm/tmword.c,string/strelapsed.c: '_' treated like ' '
+03-02-01 string/strelapsed.c: handle ps style [day-][hour:]min:sec
+03-01-31 port/astlicense.c: fix author=* match
+03-01-30 include/tm.h: add tmisleapyear() macro
+03-01-29 comp/getopt.h,comp/getoptl.c: add gnu getopt_long(), getopt_long_only()
+ include/ast_getopt.h: for non-gnu part of comp/getopt.h
+ include/ast_std.h: include <ast_getopt.h> instead of <getopt.h>
+03-01-28 ast.h,string/base64.c: add base64encode() and base64decode()
+ path/pathfind.c: verify S_ISREG()
+03-01-24 path/pathexists.c: fix abs dir bug and deal with case ignorance
+03-01-23 path/pathpath.c: honor PATH_ABSOLUTE for the easy case too
+03-01-22 path/pathprobe.c: fix search to find both the probe script and command
+03-01-17 misc/magic.tab: application/zip => appplication/(gzip|pzip|zip)
+03-01-14 misc/optget.c: change href="" to href="."
+03-01-10 include/ast_std.h: strtold() import hackery for static __CYGWIN__
+03-01-03 include/regex.h,regex/regcomp.h: add REG_SHELL_GROUP
+ include/ast.h,string/strmatch.c: add STR_GROUP for REG_SHELL_GROUP
+02-12-15 include/error.h: errorcontext => Error_context_s (compatible til 2004)
+02-12-06 misc/sigdata.c: add NoF(sigdadata) -- why nmake was uninterruptable!
+02-12-03 comp/omitted.c,features/omitted: handle cygwin alarm() return botch
+02-11-27 misc/swapop.c: op=3,size=4 => op=7
+ string/strlcat.c,strlcpy.c: fix uwin decl clash
+02-11-26 sfio/sfvprintf.c: fix sfsprintf() '\0' termination bug
+02-11-22 misc/glob.c: move static struniq() to libast extern
+ string/fmtversion.c,include/ast.h: add fmtversion
+02-11-18 string/strncopy.c: add
+ misc/magic.tab: list size for magicid.h magic
+02-11-14 sfio/sfvprintf.c: add %#c for C escapes
+ include/error.h: add ERROR_NOTIFY context flag for builtin commands
+02-11-11 string/strtoi.h: add S2I_size for strnto*() size_t 2nd arg
+ sfio/sfstrtof.h: add S2I_size for strnto*() size_t 2nd arg
+ comp/putenv.c: add setenv() and unsetenv() wrappers for setenviron()
+02-10-31 path/pathfind.c: add dir of including file to the pathinclude() list
+ misc/optesc.c: add
+02-10-30 string/strtoip4.c: set next char pointer even on error
+02-10-29 comp/resolvepath.c: add (size_t version of realpath())
+ misc/mime.c: fix mimehead() to ignore null content values
+02-10-28 misc/glob.c: add GLOB_STARSTAR for /**/ and GLOB_NOTDIR optimization
+02-10-27 string/struniq.c: add
+02-10-23 features/common: fix off-by-one loop check
+02-10-18 include/ast_std.h: avoid off_t,ftruncate,lseek,truncate redefinitions
+02-10-17 misc/mime.c: handle type/* match, fix bogus header parse
+02-10-04 sfio/sfstrtof.h: S2F_static <0:export =0:private >0:static
+02-10-02 features/common: don't define _WIN32; define _WINIX => unix on windows
+ features/tty: finally stomp the bsd _POSIX_VDISABLE redefinition
+ misc/fastfind.c: add more specific findwrite() error messages
+ comp/omitted.c: fix cygwin utime() to update st_ctime
+ comp/strtol.c,strtoul.c: __CYGWIN__ static link workaround XXX
+ string/fmtls.c,fmttime.c: tmform() => tmfmt()
+02-09-22 port/astconf.c: return values in fmtbuf() buffer instead of stack
+ port/mnt.c: don't set MNT_REMOTE for win32 ?:\* paths
+ sfio/sfvscanf.c: _sfdscan() is library global (not static)
+02-09-21 path/pathkey.c: add tool arg for mamake compatible hash
+ features/fcntl.c: handle iffe _hdr_lcl_* => _lcl_* change
+02-09-15 comp/conf.sh: fix enum vs. macro test
+ cdt: kpv sync
+02-09-11 ast.h,features/common: move _WIN32 macro init to features/common
+ features/common: enable __EXTERN__ and __DEFINE__ for _WIN32&!_UWIN
+ features/float: add -lm to _ast_*_nan_init tests
+ vmalloc: kpv sync with vmresizef => vmgetmem
+ features/iconv: must have both <iconv.h> and iconv_open()!
+ features/vmalloc: alloca test must compile *and* link
+ sfio/sfvscanf.c,sfstrtof.h: add flag arg to char get, fix NaN loop
+02-09-10 vmalloc/vmhdr.h: enable getpagesize() and sbrk() prototypes
+ features/fcntl.c: enable mmap64() prototype
+ include/ast_windows.h: windows.h wrapper with ast namespace workarounds
+02-09-07 misc/mime.c: fix quoted value parse bug that ate the whole line
+02-09-05 features/vmalloc: add free() to _std_malloc test
+ include/ast.h: NoF(x) now defines _DATA_x for !_BLD_DLL too
+ tm/tmlocale.c: { C POSIX en } == unix dadgummit
+02-08-29 path/pathfind.c: initialize Dir_t.next=0
+02-08-28 uwin/rint.c: update
+ features/libpath.sh: "bin" is now the default value
+02-08-22 vmtrace.h: add for debugging
+02-08-20 misc/magic.c: convert to use <cdt.h>
+ vmalloc/vmresizef.c: add for generic discipline resizef default
+ string/strelapsed.c: allow long time component names
+02-08-19 misc/optget.c: add `.fp 5 CW' to --nroff output
+ string/(fmtfs|fmtuid|fmtgid|strgid|struid).c: convert to use <cdt.h>
+ include/dt.h,cdt/dtnew.c: add for dtopen() in specific vm region
+02-08-13 comp/omitted.c: fix bzero logic for e.g. unixware.i386
+ include/ast.h: add fmtbase->fmtbasell; swap in 2003-09-01
+02-08-12 regex/regnexec.c: fix REG_MINIMAL REX_DOT mb bug
+02-08-08 features/iconv: <ast_common.h> instead of <sys/types.h> <ast_common.h>
+02-08-07 regex/regcomp.c: recognize anchors in BRE subexpressions
+02-08-06 comp/iconv.c: handle win32 cpNNNN == windows-NNNN aliases
+02-08-05 cdt/*: sync with kpv src
+02-08-02 features/iconv: include sys/types.h for ast_types.h
+02-08-01 misc/magic.c: magic file "." names the default
+ misc/magic.c: handle addr type (from irix string)
+ features/lib: move malloc tests to features/vmalloc
+ features/vmalloc: snarf tests from features/lib
+ vmalloc/*: sync with kpv src
+ comp/libc.c: dropped -- __libc_* intercepts moved to vmalloc/malloc.c
+02-07-30 features/lib: handle __libc_malloc() in _std_malloc test
+ vmalloc/malloc.c: add gnu pvalloc()
+ features/vmalloc: fix alloca check
+02-07-29 features/limits.c: handle netbsd guards
+02-07-27 sfio/sfpoll.c: handle rw pipes
+02-07-25 features/iconv: include ast_types.h for size_t in ast_iconv.h
+02-07-18 apply LARGEFILE64 header prototype clash patches
+ misc/optget.c: __EXTERN__ _opt_info_ instead of opt_info
+02-07-17 ast_std.h: memzero() now defaults to memset() instead of bzero()
+02-07-16 ast_std.h: add ast.env_serial
+ misc/setenviron.c: increment ast.env_serial
+ include/tm.h: tmset() now calls tminit() directly
+ tm/tminit.c: check ast.env_serial for env change
+ tm/tmfix.c: speed up for large values of tm_mday
+02-07-15 comp/fnmatch.c: fix memory leak caused by missing regfree()
+ comp/strstr.c: fix broken interpretation and implementation
+ comp/iconv.c: intercept (but no-op) null to and from buffer pointers
+02-06-27 ast_std.h: map _sysconf => _ast_sysconf for sun
+02-06-26 cdt,sfio,vmalloc: kpv sync -- is this ever easy?
+02-06-24 sfio: kpv sync, vfwscanf(),fputw() fix (wcslen(x)*sizeof(wchar_t)!!)
+ misc/fts.c: fix symlink chdir() optimzation bug
+02-06-11 sfio/sfwrite.c: string to file fix
+ Makefile: __OBSOLETE__==20020101
+02-06-01 regex/regcomp.c: REG_DELIMITED now consumes the delimiter
+02-05-31 regex/reglib.h,regcomp.c,regnexec.c: null subexpression fixes
+02-05-24 misc/fts.c: disable dir link counts in 3d
+ misc/magic.c: fix "*(mkfile)" sh pattern to "*@(mkfile)"
+02-05-20 regex.h,regex/regsubcomp.c,regex/regsubexec.c: add
+ regex/regsub.c: deprecate
+02-05-16 tm/tmfix.c: fix '60+n min/sec ago' bug for n min/sec after the hour
+02-05-14 regex/regsub.c: fix (^|x) null match early termination bug
+02-05-13 dir/dirlib.h: drop errant extern==__EXPORT__
+ features/uwin: add uwin lib tests
+ uwin/*.c: check features/uwin for stubs
+ features/float: add nan representation generation
+ sfio/sftable.h: used _ast_*_nan_init for huge values
+02-05-09 misc/fts.c: fix virtual top to force ``child'' stat()
+ features/common: define va_copy() only if not in <stdarg.h>
+02-05-01 string/strtoip4.c: cisco inverted quad mask must have 4 parts
+02-04-30 misc/magic.tab: fix pzip version check
+02-04-19 string/strtoip4.c: handle cisco inverted quad mask n.n.n.n/i.i.i.i
+02-04-18 misc/fts.c: add chdir() verification stat() optimizations
+ path/pathkey.c: check PROBE_ATTRIBUTES for list of vars
+02-04-12 port/astlicense.c: type=open tweak, fix author list spacing
+02-04-11 regex/regcomp.c: check for pattern number overflow
+02-04-05 tm/tmfmt.c: add %u
+02-04-04 sfkeyprintf.c: fix %c numeric value
+ path/pathpath.c: check plain path first -- duh
+02-04-03 misc/fts.c: fix (FTS_PHYSICAL|FTS_NOSTAT) stat optimizations
+ ftwalk.c: only clear FTW_DELAY if FTW_CHILDREN
+ ftwalk.h: add FTW_NSOK for FTW_DELAY
+02-03-29 ast.h: drop strerror() prototype -- already in <ast_std.h>
+ features/stdio: check for _SFIO_H redundant _Sfstd* declarations
+02-03-26 misc/glob.c: fix GLOB_LIST gl_flags values
+02-03-24 port/mnt.c: update bsd fstype name and mount option logic
+02-03-23 Makefile: add ast_wchar.h to the .check.hdr list (for mamake)
+02-03-17 features/stdio: hack around g++ 3.* clashes
+ Makefile: add ast_nl_types.h to the .check.hdr list (for mamake)
+ string/strtoip4.c: fix validity check bug that only checked last part
+02-03-14 misc/optget.c: fix --keys to not expand inline \f...\f
+02-03-12 port/astlicense.c: add type=free
+ path/pathaccess.c: sibling ".." search ignores relative dirs
+ sfio/sfvscanf.c: sfstrtof get() must return 0 on eof
+02-03-11 path/pathexists.c: check path by pairs checking {ENOTDIR,ENOENT}
+02-02-14 features/float: copy local min/max macros to avoid printf roundoff
+ features/wchar: include <ast_common.h>, not <ast_std.h>
+ misc/magic.c: match[]=>matches[] to fix K&R match() macro conflict
+ include/vmalloc.h: include <stdlib.h> for !_PACKAGE_ast
+ uwin/mini.sym: add sprintf (now required by features/common)
+ regex/regnexec.c: truncate wide chars for <ctype.h> functions
+ Makefile: fix MAM ast_common.h sequencing bug by making it first
+ cdt/dthash.c: fix DT_DELETE memory leak (DT_DETACH typo)
+ cdt/dthash.c: fix DT_DELETE double free (dt->data->here typo)
+ regex/regcomp.c: fix recomb() to reject RE with backref
+ features/iffeio: explicitly generate stdio.lcl
+ stdio: add {fcloseall,f(get|put)s_unlocked,fmemopen,getdelim,getline}
+ tmmake,tmtime: allow negative time_t if native localtime/gmtime do
+ tmdate: allow years before 1969
+ fmtfmt: add
+ include/ast.h: add { PATH_TOUCH_CREATE PATH_TOUCH_VERBATIM }
+ Makefile: add std/*.h for std header iffe overrides
+ comp/iconv.c: fix non-C win32 sfreserve() loop
+02-02-11 features/common: separate long long / long double tests
+ features/common: verify printf handles long long / long double
+02-02-02 include/ast_std.h,sfio/sfhdr.h: drop _hdr_locale tests -- always on now
+ include/ast_std.h: trust _UWIN <unistd.h>
+02-01-31 port/mnt.c: add aix options field
+02-01-30 comp/strstr.c: add for ancient s5
+ stdio/_flsbuf.c: only on systems that transfer to native (e.g., uwin)
+ string/strtoi.h: cat min/max error return values
+02-01-28 features/tty: add cf[gs]et[io]speed macros for <termio.h>
+ comp/rename.c: punt to (ancient) /usr/lib/mv_dir on EISDIR
+02-01-24 sigcrit.c: fix SIGCLD!=SIGCHLD interrupt loop
+ sfvprintf.c: convert fast io macros to functions for uts.390 cc
+ string/strtoi.h: drop #pragma prototyped for standalone sfio
+ sfdcsubstr.c: rename from sfdcsubstream.c for 14 char fs
+02-01-22 execlp,execvp,execvpe,spawnlp,spawnvp,spawnvpe: fix __EXPORT__
+ spawnlp,spawnve,spawnvp,spawnvpe: handle ms mode arg -- barf
+ sftable.c: ifdef hacks for _WIN32&_ALPHA_ fp exception
+ _stdfun.c: add _UWIN&_ALPHA_ iob map
+02-01-18 sfio/sfstrtof.h: drop #pragma prototyped for standalone sfio
+02-01-17 features/hdr: don't include <stddef.h> after it doesn't check out!
+02-01-16 misc/magic.c: add version type for YYYYMMDD or [a.][b.]c.d
+ misc/magic.c: recode mime %s parse -- sensible and no buffer overflow
+02-01-15 misc/magic.tab,magicid.h: add generic binary magic number and header
+02-01-12 tm/tmlocale.c: override win32 default date for {C,POSIX,en} locales
+ comp/omitted.c: fix cygwin workaround logic bugs
+02-01-09 stdio/fseeko.c,ftello.c: add from UNIX98
+02-01-08 comp/conf.sh: use $cc instead of cc
+02-01-07 string/strlcat.c,string/strlcpy.c: add bsd api
+01-12-18 comp/conf.tab: fix LFS_CFLAGS default for sun _CS_LFS_CFLAGS botch
+ features/common: add hdr stdarg test
+ tm/tmdate.c: handle YYYY/MM/DD
+01-12-10 misc/magic.tab: add generic 0x00010203 binary magic
+01-12-03 path/pathprobe.c: return HOME relative path if readonly/non-suid fs
+01-11-30 misc/optget.c: add simple cache for repeat offenders (like ksh read)
+ sfio/sfhdr.h: preserve errno across SFMMSEQON-SFMMSEQOFF
+01-11-29 magic.tab: fix GIF version number listing
+01-11-28 string/fmtbase.c: p!=0 => base always included in output
+01-11-26 misc/fts.c: empty path is an error
+01-11-14 misc/optget.c: fix --?+SECTION queries to include paragraphs
+01-11-20 regex/regnexec.c: fix REG_MINIMAL character class match bug
+01-11-19 features/lib: retain _lib_confstr for all solaris releases
+01-11-16 comp/setlocale.c: fix !_lib_setlocale typo
+01-10-31 regex/ucs_names.h: add string catenation to keep line length low
+ misc/fastfind.c: handle gnu slocate db read
+ misc/optget.c: add --?+SECTION queries
+ comp/fnmatch.h: add FNM_NOSYS
+01-10-30 tm/tmdate.c: fix cron specs when both wday and mday are specified
+01-10-20 misc/glob.c: fix bug that called \ trim() twice on same path
+ misc/glob.c: fix \ trim() bug that restored / to wrong position
+ string/fmtre.c: fix { ^ . $ } translations
+ misc/optget.c: use original string if translation fails -- duh
+ sfio/sfhdr.h: assume <errno.h> assigns proper atttibutes to errno
+ comp/regcmp.c: __ia64 workaround fixed by proper CC.DLL probe
+ comp/getdate.c: __ia64 workaround fixed by proper CC.DLL probe
+ features/lib: add lib getdate
+01-10-18 features/lib: check for strtod static link collision
+ features/float: add another signed cast for old bsd cc
+ features/wchar: add <stdlib.h> <stdio.h> before <wchar.h> for old bsd
+01-10-17 sfio/sfcvt.c: limit max precision to { FLT_DIG DBL_DIG LDBL_DIG }
+ sfio/sfcvt.c: fix %[aA] format to always have leading 0[xX]1.
+ sfio/sfvprintf.c: handle %C %lc %S %ls for wchar_t args
+ sfio/sfvscanf.c: handle %C %lc %S %ls for wchar_t args
+ string/fmtmode.c: fix bug that omitted trailing '\0'
+01-10-12 misc/optget.c: . => \&. for --??nroff
+ comp/wc.c: fix mbstate_t initialization typo
+ features/float: fix max integer / float loop termiation
+ features/float: fix LDBL_UINTMAX_MAX typo that did DBL_UINTMAX_MAX
+01-10-11 include/sfio.h: fix _Sfstd* import/export
+ features/common: fix _UWIN __DYNAMIC__() definition
+01-10-06 features/fcntl.c: { O_BINARY O_TEXT } default to 0
+ features/omitted: add for comp/omitted.c
+ sfio/sfopen.c: O_BINARY default for _WIN32&&!_UWIN
+01-10-05 misc/glob.c: fix `\(x/*' GLOB_NOMATCH bug that returned `(x'
+ misc/optget.c: fix localization lookup that didn't drop doubled : ? ]
+01-10-04 comp/setlocale.c: handle sizeof(wchar_t)!=4 in debug locale
+ comp/conf.sh: handle sytems where _SC_* is both an enum and a macro
+01-09-25 astconf: add LIBPREFIX
+01-09-20 features/common: add __DYNAMIC__() for dll externs
+01-09-19 cdt: kpv update
+ mb*() macros: update for ksh conversion, extend debug locale
+01-09-16 tm/tmlocale.c: add compiled in defaults for C locale
+ misc/glob.c: add gl_nextdir callback for GLOB_COMPLETE
+01-08-14 clarify _WIN32 vs. _UWIN vs. __CYGWIN__
+ tminit: fix standard & daylight initialization
+01-09-11 pathnative.c: add for native fs representation
+ regex.h: fix regerror_t prototype
+01-09-04 regex/regnexec.c: fix REG_ICASE for multi-char collating elements
+ tm/tmlocale.c: fix old ascii LC_TIME load
+ locale*: add new LC_* categories
+ comp/omitted.c: add CYGWIN workarounds
+ features/lib: add CYGWIN workarounds
+01-08-11 features/common: some compilers have long long but no LL constants!
+ features/lib: add mmap64 implementation test (for linux.s390)
+ regex/regcomp.c: fix \ in [...] parse
+ setlocale: retain user locale spelling in setlocale() return value
+ features/limits.c: don't include ./limits.h -- duh
+ fmtesc: don't escape multibyte chars
+ tm/tmlocale.c: fix native C locale default
+01-08-08 features/float: some compilers (msdev) forget long long vs. double
+01-07-31 misc/optget.c: handle suboptions
+01-07-27 cdt.h: add DTDISC()
+01-07-17 iffeio.h: move to include for stdio bootstrap iffe workarounds
+01-06-25 regex: perl extensions added and tested
+01-06-21 misc/error: add ERROR_OPTIONS=prefix=string for message processing
+01-06-15 string/chresc: only 2 hex digits max for \xxx
+ regex/regsub: handle REG_SHELL ~(nnn) rhs backrefs
+01-06-11 regex: handle embedded \0 in pattern and subject string
+ regex: add (?nnn) for backrefs > 9
+ comp/fnmatch: add FNM_LEADING_DIR for gnu compatibility
+ features/float: _ast_flt_unsigned_max_t for bsd.i386 omission
+01-06-06 misc/optget.c: add o option for old ps,ar,tar with optional leading -
+ regex/regcomp.c: REG_LENIENT|REG_DELIMITED \<newline> => <newline>
+ regex/regcomp.c: REG_LENIENT \000 => NUL
+01-06-04 features/dirent: replace Makefile hack with iffe semi-hack
+ regex/regnexec.c: negation must also check REG_SHELL_DOT
+01-06-03 sprintf.c: change buf size from SF_BUFSIZE to INT_MAX
+01-05-31 glob: fix gl_fignore to ignore leading . by default
+ features/lib: add botch_d_ino_dirent64 for linux botch
+01-05-25 port/lc.tab: add a few missing language_territory's
+01-05-23 string/chresc: \C[.collation-element.]
+ fmtmatch,fmtre: update for <regex.h> syntax extensions
+01-05-21 regex: add perl extensions, unicode names for collation elements
+01-05-11 string/chresc: \e == \E == escape, \cX == control X, \x{..} == \x..
+01-05-09 path/pathtemp.c: pathtemp(0,0,0,"/private",0) for mode S_IRUSR|S_IWUSR
+ port/touch.c: handle utime(2) EPERM to fix bug that truncated
+ regex: change REG_MINIMAL to avoid negation -- much faster now
+01-05-08 *.h: add some off_t macro guards for suse linux
+01-05-03 regcomp.c: optimize ((x)!)* to ((x)!)
+ wchar: add <wchar.h> and stdio wchar routines
+01-05-02 feaures/wchar: add <wchar.h> intercept, add stdio wchar functions
+01-05-01 string/strtoi.h: signed strtoi accepts qualified unsigned constants
+01-04-30 comp/setlocale.c: fix code that relied on 2 simultaneous getenv()'s
+ tm/tmlocale.c: check for UTF-8 encoded LC_TIME files
+ misc/magic.tab: add utf-8 and utf-16 U+FEFF magic
+01-04-26 features/common: some cc's have _ast_int8_t but not LL constants
+01-04-24 features/lib: add _std_strtod for mac os X
+01-04-23 ccode: add CC_sub for ms embedded EOF char on ebcdic -- no joke
+01-04-20 iconv: handle ebcdic<=>utf
+ mc.h,mc.c: add mcindex()
+ ast_std.h: add AST_MESSAGE_SET
+01-04-18 features/libpath.sh: fix mvs probe
+ *: sundry mvs fixes
+ glob: fix GLOB_NOCHECK to avoid stat() and properly trim patterns
+01-04-01 strtod,strtold: add
+ strtol,strtoul,strtoll,strtoull,strton,strtonl: handle locale & ERANGE
+ sfvprintf,sfvscanf: handle locale decimal_point,thousands_sep
+ sfvprintf,sfvscanf: handle %a,%A
+ setlocale: add LC_NUMERIC decimal_point,thousands_sep init
+ ast_std.h: __OPTIMIZE_SIZE__==1 to disable non-std __GNUC__ inlines
+ pathexists: path cache to cut down pathpath() access(2) calls
+ features/stdio: __FILE_TAG == _sfio_s for solaris
+01-03-23 iconv: fix iconv_move buffer boundary bug that stopped at 1 block
+01-03-19 glob: add GLOB_AUGMENTED
+ regex: REG_SHELL syntax error implies REG_LITERAL match
+ strto[ln][ll]: add overflow checks
+01-03-17 locale: reimplemented to provide canonical locale namespace
+ locale: add LC_ALL=local for local system user default
+ tm.h: TM_*_3 => TM_*_ABBREV
+ tmfmt: handle standard E and O format modifiers
+ tmlocale: consult nl_langinfo() if defined
+ fmtquote("\"",1) => shell quote
+01-03-08 regex: handle multibyte chars and collation classes
+ strmatch,strgrpmatch: now a wrapper on regex
+ ast_std.h: add mb*() multibyte and collation support
+ sfvscanf: handle locale decimal and thousand
+ proc*,system: handle ignored SIGCHLD
+ sfkeyprintf: handle %*C
+01-03-06 locale: add locale data cache for efficient multiple locale switching
+ optget: fix LC_MESSAGES!=C --man bug
+01-03-01 Makefile: HEADEROPT is not optional for win32.*
+ comp/syslog.h: comply with the de factos
+ optget(): fix \f...\f stack bug that referenced data after pop
+01-02-27 *locale*: a batch of fixes for native LC_MESSAGE&LC_TIME hooks
+01-02-22 pathprobe: reprobe test now checks probe.ini too
+ sfio_s.h: advertize public Sfio_t members with _ prefix
+ sfio.h,features/stdio: add <sfio_s.h> reference
+ sfhdr.h: map <sfio_s.h> _foo to foo
+ sfio.h: SF_APPEND=>SF_APPENDWR, SF_CLOSE=>SF_CLOSING
+01-02-14 comp/conf.sh: probe <unistd.h> for _(CS|PC|SC)_* getconf symbols
+ stdio/*: update for uwin stdio.dll binary compatibility
+ sfread: finally fixed premature pipe read EOF bug
+ fmtscale: format tenths for number > 0 && number < 10
+01-02-09 _sfmode(),_sftype(),_Sfextern: UWIN binary stdio compatibility exports
+01-02-08 sfgetm,sfputm,_sfputm: fix max clash with k&r max() macro
+ setlocale: undef valid for sun4 k&r valid() macro
+01-02-07 catopen.c: don't do native catopen for the debug locale
+01-02-06 sfraise.c: add SF_FINAL check to avoid (posibly) freed disciplines
+01-01-01 features/common: fix uwin __DEFINE__
+ sftable: initialize decimal and thousand
+ magic.tab: add corel wordperfect document
+ syslog: add LOG_LEVEL, add '\n' only if needed
+ include/tm.h: #undef daylight for _WIN32
+ sfio.h: add _SF_APPEND and _SF_CLOSE for native namespace incursion
+ ast_std.h: add AST_LC_multibyte for MB_CUR_MAX>1
+ setlocale: set AST_LC_multibyte
+ strmatch: check AST_LC_multibyte
+ features/limits.c: add _BITS_POSIX1_LIM_H guard for linux
+ features/libpath.sh: fix for aix LIBPATH
+ procopen,procclose: block SIGCHLD if PROC_FOREGROUND (e.g., system(3))
+ optget.c: add enumerated option argument values
+ optget.c: add <!--INTERNAL--> for private --html
+ optget.c: fix memory leak that hit shell builtins hard
+ sfio: drop sfread small chunk logic
+00-12-25 mnt.c: handle " and ' quoting for fstab
+ sftmp.c: let pathtemp() open the fd O_EXCL
+00-12-15 conf.sh: add -v for verbose trace
+ features/(limits|unistd).c: no FEATURE/types because of _POSIX_SOURCE
+ features/time: add default for CLOCKS_PER_SEC
+ features/lib: std_malloc now handles NeXT
+00-12-13 strton: recognize qualifier only if preceded by a digit
+ features/lib: change return in vfork() test to exit() for linux sparc
+ fmtquote: fix $'...' quote logic
+00-12-11 tmdate: fix cron format bug that mishandled months
+00-12-01 optget: handle $Id: ... $ in --?-version
+ features/fcntl.c: fix _STDPP_ mmap munmap
+00-11-27 magic: drop dup sfclose() in load()
+ optget: handle error_info.id==0
+00-11-22 features/stdio: add _FILEDEFED for sol9.sun4
+ strton,stronll: handle [u|U][l|L][ll|LL] qualifiers
+00-10-31 tmdate: add TM_DATESTYLE and mmddHHMM[cc]yy
+ astlicense.c: #include <hashkey.h> MAM workaround
+ astlicense.c: check for non-empty CONTRIBUTORS
+00-10-26 features/stdio: add _FILE and __FILE for gnu
+ misc/stk.c: fix stack pointer check off-by-one (dgk does it too!)
+00-10-23 syslog.h: sync with bsd values
+00-10-18 _STUB_* now functions instead of common symbols
+ all extern data declared with definition to eliminate common symbols
+ fastfind: add mac/bsd /var/db/locate.database
+00-10-17 features/lib: add apple osX (darwin.ppc) workarounds
+00-10-12 add: fmtbuf(), fmtclock(), fmtip4(), strtoip4()
+ fmt*() now use fmtbuf() for tmp fmt buf allocation
+00-10-05 regex: add REG_DISCIPLINE and regdisc_t for alloc/error disc
+00-09-29 features/lib: pipe_rw==0 for sgi: boot rw == bin incompatibility
+00-09-21 astlicense: handle \' and \" in license values
+00-09-20 sfwrite: fix write() error in sfprintf() loop
+00-08-11 hdr,vmhdr.h: check/hide { getpagesize sbrk } prototypes
+ astlicense: add noncommercial
+00-07-31 fflush: don't seek on pipes
+ sfresize: add
+ setlocale: fix bad newof() call
+00-06-01 strmatch: initialize match.current.beg[0] to avoid dump at line 670
+ sfio/stdio: a few more errno tweaks
+ astquery: sfstdin/sfstderr by default
+00-05-26 sfmode: errno=EBADF for invalid stream use
+00-05-22 rewind: fix for xopen test
+00-05-18 mcfind: returns absolute path
+00-05-16 optget: --keys must catch \f...\f too
+ translate,mc: errno cleanup
+00-05-09 magic: add netbsd binary magic
+ fts: PATH_RESOLVE!=logical => FTS_SEEDOTDIR
+ ftwflags: call fts_flags()
+ astconf: astconf(0,0,0) re-syncs with _AST_FEATURES
+00-05-08 optget: --usage & --keys for last -catalog group only
+00-05-02 iconv.c: add; use codes[] in ccmapid() and ccmapname(); "" for native
+00-05-01 pathtmp: copy env values (libshell or putenv may change)
+00-04-01 optget: drop bar from [-foo?bar] for --??keys
+ sfvscanf: add %X -- duh
+ features/common: fix va_listval() for power pc
+ findopen: fix FIND_GENERATE codes file search
+ magic: add ERROR_translate() and msgcat.key
+ tmlocale: add for LC_TIME locale info
+ tmlex: check tm_info.format and tm_data.format
+ tmfix: fix for tm_wday special case (via nl_langinfo on LC_TIME fields)
+ strftime: fix for nl_langinfo special case
+ ast_std.h: provide LC_* defauls if not defined
+ sfnew: check ${_AST_sfio_bufsize} -- don't tell kpv
+ catopen,nl_types.h: add intercept to mc* routines
+ magic.tab: add ast message catalog
+ strerror: add _ast_strerror intercept with ERROR_translate("errno")
+ fmtquote: escapes >0177 only if (flags&2)
+00-03-17 feof: stdio macro functions only for _UWIN
+ optget: proper ERROR_translate() calls
+ astgetconf: add for thread safe error message control
+ astlicense: fix type=special but with non-null notice
+ errorx: add for ERROR_translate() support
+ ERROR_translate: add locale id args for alternate dictionary
+ option.h: move _OPT_PRIVATE_ to pointer to avoid dll size mismatch
+ ftwalk: fix FTW_CHILDREN bug that hit top level non-dirs twice
+ translate.c: default error_info.translate
+ astconf: fix dup loop thrash that never returns, add _AST_VERSION
+00-03-10 ast_std.h: do _LARGEFILE_SOURCE initialization before std headers
+ fmtquote: handle $'...' quotes
+00-03-07 optget: fix numeric option support test
+ sfkeyprintf: add %q for '...' quoting with ansi escapes
+00-03-06 features/stdio: fix _sfflsbuf prototype (dingold@gte.net)
+00-02-14 pathtmp: fix pid cache bug that sometimes repeated after ~10 attempts
+ optget: "..." attribute quote
+ pathfind: eliminate *: prefix in lib, not type
+ proc: PROC_FOREGROUND for system(3) semantics (wait status return)
+ pathtmp: fix mktemp() logic
+ fts: fix FTS_NOSEEDOTDIR bug that botched ./* in top list
+ include/ast/prototyped.h includes include/prototyped.h
+ pathpath: fix strdup(0) bug
+ optget: --html <foo@bar> => ...mailto:foo@bar...
+ sscanf: fix sfsscanf => sfvsscanf typo
+ magic.tab: strengthen tar recognition
+00-02-08 conf.sh: fix ifdef for systems that think sysconf(FOO) is const
+00-02-04 glob: fix globlist_t.gl_flags
+00-02-02 vm*: add NoF() for data only files
+00-01-27 fts: fix top level .==.. statp bug (thanks to dr. ek)
+00-01-25 conf.tab: fix LFS*_*LAGS typo
+00-01-24 astlicense: handle type=verbose, license.notice, author=*
+00-01-11 pathprobe: generate info for first probe script on PATH - duh
+ ast.h: add NoF(x) for files that define no functions
+ tmpfile: fix implementation
+ global change for string ERROR_translate() dictionary names
+ optget: fix new way but no long names off by one
+ optget: handle [--dictionary?name]
+99-11-19 comp/conf.sh: `expr length XXX` is not universal
+ drop sfstdio; stdio via functions everywhere
+ drop Makefile conditionals (and follow our own advice for once)
+ sfio: new stream after atexit() bug fix
+ tm: Tm_zone_t.daylight=0 for standard time within zone
+ stdio: fopen => _ast_fopen: only way short of binary compatibility
+ Makefile: atmain.C falls back to atmain.c
+ optget: add --keys, s<section> option
+ stdio: _UWIN check for foreign stdio
+99-11-11 astlicense: add
+99-10-31 glob: fix regexec pattern; add PATH_ATTRIBUTES case check
+ pathpath: path==0 means malloc space
+99-10-22 tmfmt: %C=2-digit-century, %k=date(1), %y=2-digit-year-in-century
+99-10-18 fastfind: expanded default db lookup
+99-08-11 magic: fix off by one registry malloc
+ features/fs: add __RENAME checks for stat familiy (netbsd)
+ features/fs: major()/minor() fixes for s5
+ features/libpath.sh: netbsd fix -- ld.so not in std places
+ misc/fastfind: fix codes path generation bug
+ optget: beef up --?* description, fix <TR>...</TR> nesting
+ pathprobe: check for override (writable key file) first
+ features/time: int tmtimeofday(struct timeval*);
+ optget: fix opt_info.num, even if opt_info.arg!=0
+ fts: FTS_PHYSICAL => FTS_SEEDOTDIR, add FTS_CHOP
+ fastfind: init dir tab with logical and physical name
+ glob: add gnu GLOB_ALTDIRFUNC
+99-07-17 sfio: kpv update and sfhdr.h sync!
+99-06-24 stdio: fix fflush() to ignore sfseek(0) return value
+99-06-23 magic: '\r' is text not control to placate m$
+99-06-08 stdio: fix fseek,ftell semantics
+ uwin stdio: fflush() => _doflsh() to avoid __cplusplus clash
+ getopt: call liberror() to avoid error() conflict
+ tmfmt,tmscan: %N zone type (nation code), %z zone minutes west offset
+ tmfmt: - no pad _ space pad 0 leading 0 pad
+99-05-28 magic: fix 'x' == '*' for any number, magic.tab tweaks
+ features/lib: verify that stat64 really works
+99-05-21 tm*: add TM_WINDOW==69 for consistent century windowing guard year
+99-05-18 tmtime: add century leap year calc anticipating unsigned time_t
+99-05-17 sfkeyprintf: handle %o and %x!!
+99-05-09 pathprobe: $HOME/.probe if not suid and st_uid!=geteuid()
+99-04-28 magic,magic.tab: add registry()
+99-04-24 regcomp: fix ksh pattern +! parse
+ regfatalpat: add
+ optget: make : ? ] double escape consistent in all contexts
+99-04-01 features: drop iffeio.h and stdio.h when only printf() used
+ regex: fix stats() .l and .k count
+ fmtquote: added; most general fmtesc() form
+99-03-22 fmtesc.c,ast.h: add fmtnesq()
+ optget: --?x works for -x option flag
+99-03-17 features/limits.c: workaround solaris __EXTENSIONS__ _timespec bug
+ workaround limits.h circular prereq with ignore stdio.h
+ sfvprintf: %04e left-pad zero fixed
+99-03-03 fts: uncle already: add FTS_SEEDOTDIR to retain leading ./
+ regex: REG_MULTIPLE, BM for fixed string alternation
+ optget: embedded `-' optional in long options, prefix={0,1,2}
+99-02-14 fastfind: fix dir format bug that emitted wrong paths
+ astconf: fix redef off by one bug
+99-02-11 pathcanon(): don't cache astconf("PATH_LEADING_SLASHES", NiL, NiL)
+99-01-23 optget: move <old_opt.h> back into <option.h>, no open-close
+ optget: add "[index:long-name:description]" for --long-name
+ comp/gross: add weak __libc_attr for irix < 6.5 compatibility
+ features/limits.c: tweak the guards again
+99-01-11 fastfind: handle old format count byte order
+ magic.tab: fix elf to use real phdr offset
+ magic.c,magic.tab: fix | to act like switch/case
+ comp/fross.c,features/hack: for gross hacks
+ features/stdio: avoid sfio namespace pollution
+98-12-25 tmdate: yyyy.mm.dd
+ pathprobe: fix procrun() cmd path bug
+ fmtesq: add
+ features/common: win32.alpha va_list
+ magic: add pc alpha object
+98-11-11 strmatch: add STR_ICASE
+ pathprobe: punt to $HOME/.probe/<key+HOSTTYPE> if not S_ISUID
+ tmzone,tmdate: handle +-minutes, nn/MMM/yyyy
+ stropt: fix nested quote pop
+ tmfmt: add %K => %Y-%m-%d/%H:%M:%S
+ sfio/stdio: fix fseek() SF_PUBLIC omissions
+ fmtesc: catch '\\' (duh)
+ vmalloc: vmbest round bug fix
+98-11-01 fts.c: no pathcanon() if (fts_flags & FTS_PHYSICAL)
+98-10-01 features/stdio prototype fixes
+ optget: strton() instead of strtol() for #
+98-09-22 regcomp: add REG_DELIMITED and REG_ESCAPE delimited re support
+98-09-15 fix _LARGEFILE64_SOURCE stuff
+ ast_std.h: provide mmap() prototype
+98-08-11 fix sfpopen() to ignore SIGPIPE by ignoresig() for sfio but not stdio
+ fix procopen() to ignore SIGPIPE by ignoresig() for PROC_IGNORE
+ sfio sfpopen/popen update
+ magic.src: fix ustar entry
+98-07-17 fix ftwalk() short by one malloc()
+ add fts_notify()
+98-06-25 sfdcmore,sfdcprefix: add
+98-06-19 tokscan: add %f %g
+98-06-01 disc/sf*.c: memset(0) after disc malloc()
+98-05-11 strelapsed: y==Y
+ fts: pathcanon() top list
+98-04-01 error: error_info.time for all msgs, just after cmd id
+ error: no sfsync(sfstdin)
+ sfio: sfpool, Sffmt_t update
+ magic.tab: sgi core dumps -- why aren't these elf?
+ stropt: (v+n) for unknown option is option value if n!=0
+ procopen: fix setsid() for spawnveg() only
+98-03-19 malloc: add realloc foreign region check
+ sfdisc.h: rename to match kpv disciplines
+ fastfind: fix strcasecmp/strcmp directory prefix mixup
+98-03-17 features/fcntl.c,pathtmp,sftmp: add O_TEMPORARY
+98-03-01 pathcanon: fix PATH_LEADING_SLASHES to stat() both slashes
+ pathcanon: add PATH_VERIFIED
+ tmdate: add skip[] to expand separator char set
+ fastfind: FIND_OLD for old 7 bit db, FIND_TYPE for new 8 bit typed db
+ fastfind: default generates gnu LOCATE02 8 bit db
+ magic: handle %s in mime description
+ cdt: kpv update
+ sfio: kpv update
+ stdio: fpos64_t fseek64(), ftell64(), fgetpos64(), fsetpos64()
+ stdio: fseek() => sfseek(SF_PUBLIC) to avoid locking
+ fts: initialize parent stat[bp] from top level *after* statf done
+ astmath: add -lm requirement test
+ *: Astlong_t => _ast_*_t
+ regex: simplify regcollate() (from doug)
+ tmtime: preserve Tm_t*tm when calling tminit()
+ astconf: add readonly PATH_ATTRIBUTES=[cirw]
+98-02-14 fastfind: add FIND_ICASE to ignore case
+ tmdate,tmgoff: handle (+|-)hh[[:]mm[[:]ss]] absolute timezone
+ tmdate: `<n> <part>' now assumes `next <n> <part>' instead of `this'
+ tmfix: fix leap year bug that forgot to add 1900
+ proc: add PROC_ZOMBIE
+98-02-06 strmatch() char class range bug fix
+ regex char class range bug fix
+98-01-23 _WIN32: changed the #if logic again to accomodate _GNUC_
+ mnt: grab the mount options too
+ ast_std.h: hide getopt,getsubopt from stdlib.h
+ features/limits.c: add gnu guard macros to avoid limits.h recursion
+ features/mode.c: include "limits.h" instead of "FEATURE/limits.lcl"
+98-01-11 sfio.h: use Astlong_t, move Sfio_t Sfdisc_t typedef to top for stdio.h
+ sfhdr.h: #undef SETLOCAL for hpux
+ sfvprintf,sfvscanf: %I*x for sizeof(int_arg)
+ handle ftruncate64 and truncate64
+ dtopen.c: __hppa dll needs Dtset Dtlist Dttree refs here
+97-12-18 fmtnum: add
+97-12-11 magic: handle sgi 64 bit core dumps
+97-12-07 pathtmp: add override for TMPPATH,TMPDIR and cycling
+97-11-11 tm: handle 0 return from gmtime(),localtime() (dos negative time_t)
+ features/stdio: fix fflush() macro to do physical sync
+97-10-31 astconf PATH_RESOLVE is logical if 3d&&!std, metaphysical otherwise
+ magic: fix #! mime bug
+ tm: tmtime() now calls tmfix() and adjusts tm_isdst too=>mtime() works
+97-10-11 dllfind,dlfcn: move to separate -ldll so -last can link static, duh
+ Makefile,state.c: move forced header generation state.c => Makefile
+ sfio: update including SF_WHOLE
+97-10-01 sfdostext: add \r\n => \n sfio discipline
+ stropt: NiL table => p=name for all name=value
+97-08-11 pathtmp: check pid to note forks
+ procopen: FD_CLOEXEC rfd && wfd
+ fts: fts_close() after fts_children() with no fts_read() now works
+97-07-17 error: sfsync(sfstdin,sfstdout,sfstderr) instead of sfsync(NiL)
+ _sfcvinit: add sfio internal interface to base conversion tables
+ strton: use _Sfcv* base conversion tables instead of sfsscanf()
+ sfvscanf: use _Sfcv* base conversion tables
+ mime: x- permutations now matched if exact fails
+ mime: original- stripped from content-* headers
+ tmdate: add yyyy-jjj, yyyy-mm-dd
+ dllfind: add
+ ccmapid: fix buf copy loop limit
+ ccmapname,ccmapcpy: add
+ sfstrtmp: add
+97-05-09 streval: fix up casts for pseudo-ansi cc
+ features/types: use _ast_int_8 vars to verify support
+ string/modedata: check for mvs.390 S_IFMT
+ include/ast(_std).h: add #define __FILE_typedef
+ magic: add ccode text check
+ include/ftwalk.h: FTW_PATH=>FTS_NOCHDIR to avoid FTS_AGAIN (duh)
+ fts: clear status for FTS_AGAIN (fixes rm -r bug)
+ mnt: add mvs openedition w_getmntent()
+ sfhdr: _hdr_float && <float.h> for correct MAXDOUBLE
+ vmalloc/vmbest: if _std_malloc then use malloc()/free() not sbrk()
+ remove: check _std_remove
+ procopen: handle pio[{0,1}]=={0,1}
+ setenviron,features/uinstd: test for mvs.390 dll environ hacks
+96-12-25 <sfio_p.h> -> <ast_common.h>
+ __EXTERN__(type,object)
+ __DEFINE__(type,object,value)
+ magic: check strings in !CC_NATIVE code set too
+ system: cmd==0 means check for shell access (xopen)
+ sfhdr.h: fix sfrsrv prototype
+ add __libc_malloc etc for gnu/linux
+ astconf(NiL,path,name) == astconf(name,path,NiL) + no liberror
+ fts_open: if toplist() stat fails return 0
+ ftwalk: handle fts_open()==0 via one phony userf() call
+ sfmode: S_ISFIFO default is SF_SHARE=0
+ features/lib: _WIN32 _lib_vfork=1 by default
+ unsigned<0 comparison and other fixes via sgi.mips4 cc
+ stk.c: use <align.h> ALIGN_BOUND for stkalloc()
+ features/lib,vfork: uwin fix
+ ast_std.h: fix strto[u]ll prototypes with features/types _ast_int_8
+ getsubopt: add for xopen 4.2 compatibility
+ drop function __IMPORT__
+ magic: more magic
+ change #define FILE from Sfio_t to struct _sfio_s
+ state.c: add generated includes that may be hit by std for MAM
+ bytesex: forgot about sizeof(long)=>7; could we fix the name too?
+ vmalloc.h: fix vmnewof() definition
+ sfio.h,stdio.h,ast_common.h: pollution cleanup
+ magic.c: add | op for switch
+ Makefile: stdio.h was on both HEADERSRC and HEADERGEN -- don't do that
+ drop pp:notice to get <sfio.h> ... <ast.h> to work
+ regex: add [[:<:]]==\< and [[:>:]]==\> for bsd compat
+ mime.c: ignore X-* headers while scanning for Content-*
+ magic.c: check for negative indirect offsets
+ magic.tab: fix dos entry that generated negative indirect offsets
+ vmalloc.h: add vmstrdup() prototype
+ hash.h: add hashgetbucket() macro
+ magic.c: MAGIFILE is now a : file list
+ mnt.c: another 4.4 bsd fix -- users must include <sys/crap.h>
+ common: fix _WIN32 chicken&egg with va_copy
+ sfio: forgot to set f->val along with _Sfi in sfexcept()
+ Makefile: add mini target for uwin libmini.a
+ sfcvt.c: workaround for flaky long double optimizers
+ features/common: fix to work with va_list==void*
+ regexec.c: fix REG_STARTEND subexpression offsets
+ strmatch.c: don't forget <wctype.h>
+ regrexec.c: fix REG_INVERT end boundary bug that missed last record
+ astconf.c: notify(0,0,"a=b") called for each setenviron("a=b")
+ pathcanon.c: check astconf(PATH_LEADING_SLASHES) to preserve //*
+96-11-28 _LARGEFILE64_SOURCE by default if possible: NOTE: assumes xopen
+ regerror: fix for xopen
+ getopt: fix for xopen
+ magic: add ciao virtual database
+ astconf: posix/strict/xopen implies "standard" conformance
+ fs3d.h: hide mount prototype
+ ast_std.h,mnt.c,features/fs: ncr port tweaks
+96-10-31 version 5.0
+ add strtoll() strtoull()
+ sfkeyprintf: upgrade to int_max args
+ ast.h: add ssizeof() to work around unsigned botch
+ conf.sh: add shell actions to conf.tab
+ _DLL*: drop for _BLD_<lib> + __EXPORT__ + __IMPORT__
+ sfio,cdt,vmalloc: kpv update
+96-10-11 <ccode.h>: add character code map support
+ procclose: return shell style exit status
+ features/fs: pun statvfs.f_basetype to statvfs.f_reserved7 for mvs
+ uwin: add subdir for uwin additions
+ ast_std.h: swab() is from <stdlib.h>
+ sfio.h: <ast_std.h> if _PACKAGE_ast
+ magic.tab: add mips[1-4], 64-bit
+ port tweaks for sol.sun4 and sun4
+96-09-06 strerror: add
+ fmterror: uses strerror
+ str*search: use sfiso646() order
+ strpsearch: add
+ magic: add Magic_t.mime mime type return for magictype()
+ mime.h: add
+ strton: use sfsscanf()
+ strperm: factor in umask() if no who
+ pathtmp: add TMPPATH check
+ libevent: add
+ magic: add discipline to magicopen()
+ mime: add discipline to mimeopen()
+96-08-31 regex: fix BM fail table generator
+96-08-11 mntread: fix mnt.type for SCO variant
+ conf.tab: add SCO KERNEL_* sysconf() vars
+ fastfind: add findwrite(), fix findread() FF_OFF omission
+ ftwalk: reimplement on top of fts
+ fnmatch,re_comp,regexp: reimplement on top of regex
+ basename,dirname,fmtmsg,fts,ftw,getdate,getsubopt,glob: add
+ hsearch,nftw,realpath,strftime,strptime,swab,tempnam: add
+ tsearch,wordexp: add
+ getcwd: cache last path for easy test
+96-07-17 error: sfsync(NiL) ... write ... sfsync(sfstderr)
+ astconf: handle readonly *(DEV|DIR) vars
+96-04-01 swapop: fix stupid return value bug
+ features/int.c: fix int_swap generation bug
+ regnexec,regrexec: fix unsigned underflow init error
+ ls.h: fix iblocks() to be in units of LS_BLOCKSIZE
+96-02-29 magic: space before function is definition with no call
+ hash: drop hash_info from public interface
+ hash: OBSOLETE hashlast()
+ hash: add Hash_root_t.Hash_last_t to public interface
+ add strsearch() and strnsearch() to complement strlook()
+ add hashkey.h for keyword->long hash
+ pathpath: pathpath(0,0,"",0) disables $0 $_ $PWD relative search
+ sfio: sfstrtod+sfhdr update
+ regex: fix REG_LENIENT to map BRE \[+?|] to ERE [+?|]
+ change _std_malloc iffe test so it doesn't hang on alpha
+ sfhdr.h: features/sfio generates _lib_cvt instead of _i386_cvt
+ ast_hdr.h: add va_copy(a,b) to copy va_list b to a
+ getopt: fix stupid getopt() -> optget() bug
+ sfvprintf: %h? now downcasts
+ regex: handle strto?l() errno in regcomp()
+ sfstrtod: _Sfstrtod_already_defined -> _STUB_sfstrtod
+ ast_std.h: hide valloc() and ignore <strings.h>
+ sfkeyprintf: pass phony va_list for '2'
+ regex: change HIT var type from int to size_t in special()
+ ast.h: add EXIT_STATUS(x) to convert wait() status to sh exit status
+96-02-14 regex: add _ to \<...\> isalnum test
+ regex: fix BM inner loop breakout
+ features/types: size_t is signed on some systems! => _ast_size_t
+ sfio: sfrd discipline peek optimization
+ vmalloc: vmalloc.h malloc family macro upgrade
+ tokopen: fix newline bug for non-restore open
+ sfio: no inline for gcc until it emits for -g too
+96-02-12 sfio: internal upgrade
+96-02-09 regex: Boyer-Moore boundary fix
+ vmalloc: snarf latest
+96-02-06 regex: add regrecord() and regrexec() for Boyer-Moore record filtering
+ regex: rearrange regnexec() args to match buffer,count arg style
+96-01-31 stk: add STK_NULL to stk.h and stk.c
+ regex: privatize regex.h and fix min re length computation
+ workaround lazy strdup() implementations in features/lib _std_malloc
+ fix stkclose() to free(stream) -- purify missed because of sfio links
+ unused var cleanup
+ port/mnt.c must include <ls.h> to get <ast_fs.h>
+ add SF_FINAL to sfio and stk
+ sfio reads now on natural block boundaries
+ add #!!! <level> <message> !!! to tokline()
+ add REX_BM pre-filter to regcomp/regnexec
+96-01-22 add regcomp env.paren overflow checks
+96-01-11 add Doug McIlroy's regex (converted to C from C++ by gsf)
+ AT&T Research now
+ sfgetr optimization
+ regex buglets
+96-01-05 tweak magic.tab for win32
+95-12-25 add !(...) -> (...)! to fmtre()
+ nt tweaks -- functions with no header proto must be defined extern
+95-11-24 version 4.1
+ add mnt.h mntopen mntread mntclose
+ convert fmtfs to mnt.h
+ add RE_LEFTANCHOR and RE_RIGHTANCHOR
+ gcc inlines must also have global library function instantiation!
+ add hashview()
+ fix strtape() internal buffer flow
+ fix mntread() fs/dir transposition for uts mnttab
+95-10-31 change features/unistd.c includes to break limits-param cycle
+ add cdt from kpv
+ sfio snarf from kpv
+ add [ht]search for _WIN32
+95-10-11 clarify PARANOID pathcheck() warning
+ fix procopen() LIB_SPAWN environ bug with setenviron() cache
+ fix setenviron() bug that forgot to reset environ if == 0
+ add %Z '\0' output format to sfkeyprintf()
+ sfio snarf for sfvprintf fix
+ allow multiple hashscan() with scope caveat
+ add comp/fakelink.h to synthesize a few symlink text patterns
+ add !<xxx> magic to misc/magic.tab
+ add FTW_TOP to inhibit recursion (for ftw side effects on top level)
+ add memfatal() common malloc fatal exception message
+ add dos \r\n test to misc/magic.c/cklang()
+ sftmp() O_EXCL+random to avoid collisions
+ pathtemp() uses sftmp() randomizing
+ features/fs uses SF_APPENDWR
+ sftmp() uses pathtemp() -- don't worry, its not circular
+ a few more _WIN32 compatibility additions
+ realloc fixed to use VM_RSCOPY|VM_RSMOVE instead of obsolete 1
+ add hashlook(tab, oldname, HASH_RENAME, newname)
+ a few more tweaks to satisfy port warnings
+ add _SFIO_INLINE_PRIVATE to provide real function too
+ fix <dirent.h> installation test
+ oops object / shared library compat with _sfgetl2 _sfgetu2
+95-09-11 add getopt() compatibility
+ add fstat,lstat,mknod,stat fixes for _x versions in sys/stat.h
+ add getconf CONFORMANCE - posix for things that aren't ast default
+ sfio_t.h: #ifndef _SFIO_H #include "sfio.h" #endif
+ snarf vmalloc from kpv
+95-08-11 fix malloc bug in magic
+ update linux and bsd 386 magic entries
+ error_info.auxilliary returns new level, |=ERROR_OUTPUT if msg done
+ drop fnmatch from strmatch for sparc (solaris) until it collates
+95-07-17 fix port/astconf universe initialization
+ fix misc/optget opt_info.nopt initialization
+ drop tmset() TZ=... because it only worked when TZ=... was ignored
+95-05-09 mongo <ast.h> namespace cleanup
+ drop > 2 year old obsolete interfaces
+ sfvprintf.c fix for (char:8 short:16 int:32 long:64) architectures
+ TMP_MAX back into conf.tab
+ pathbin() and pathshell() now use astconf()
+ fix pathtemp() to not cache getenv("TMPDIR")
+ fix ftwalk() metaphysical to handle non-dirs too
+ initialize *_info = { 0 }; for ancient ld semantics (NeXT)
+ fix magic() to do vmfree()
+ astconf(X_OK) must prefix lines with "getconf"
+ use <wchar.h> and wctype in strmatch() if available
+ _lib_utime_now checks utime(path,0)
+ _lib_poll_notimer checks poll(x,0,timeout)
+ add another _lib_utime_now check to port/touch.c
+ fix dd_buf cast in dir/opendir.c
+ split getconf.h into conftab.h and conftab.c for :READONLY:
+ use mbtowc() only if MB_LEN_MAX>1
+ sfio char* -> Void_t* cleanup
+ handle old syntax in misc/magic.c
+ sigdata.c holds readonly signal strings
+ pathcheck() does AT&T checks for tools matching PARANOID - yuk
+ unused var cleanup
+ deprecate hash_info in favor of hashlast()
+ fix bad conf.sh ksh integer interactions
+ dll cleanup
+ magic.c falls back to malloc for now
+ add environ to <ast.h> -- C library global data syms are *RESERVED*
+ sfhdr.h memccpy(1,2,3,size_t) prototype
+95-04-01 version 4.0
+ convert to vmalloc
+ allow sigcritical() nesting mismatch to work around vfork() bug
+ add strexpr() primitive for streval() with user handle (like ftwalk)
+ add <magic.h> and magic.c file command magic interface
+ update magic mail message entry
+ fix keyprintf() invisible char count nesting bug
+ add sfstrnew(SF_READ|SF_WRITE) for alternate sfstropen() modes
+ sfstrnew(SF_READ) but reading requires sfseek(), sfreserve()
+ add conf.tab and conf.sh to nail C/POSIX limits/unistd macros
+ add getconf() string interface to *conf*
+ _DLL_INTERMEDIATE_DATA for systems that require indirect globals
+ _DLL for building shared libraries with _DLL_INTERMEDIATE_DATA
+ vecfile() restricted to S_ISREG()
+ add spawnveg() for job control
+ convert procopen() PROC_PGRP(id) to spawnveg()
+ fmterror() returns error text given errno (strerror() does same)
+ fmtsignal() returns signal text given errno (strsignal() does same)
+ {sig_name,sig_text,SIG_MAX} -> sig_info.{name,text,sigmax}
+ liberror("",...) omits [%s library] prefix
+ update features/signal.c table
+ add vmdisc() and change vmnewof() to use vmresize()
+ fix conf.sh to allow refs to previously defined limits
+ fix undefined entries in getconf()
+ magic data in magic.tab
+ fix stropt() pointer cast
+ vmalloc() exception handler replaces nomalloc()
+ merge sigdata.c into fmtsignal.c -- sun link needs function w/ data!
+ sftmp() bug fix
+ drop local <unistd.h> even with _POSIX_SOURCE
+ fix vmstrdup() macro arg miscount
+ fix conf.sh to handle enum'd symbolic constants in unistd.h
+ drop malloc() et.al. prototypes from vmalloc.h
+ fix sfvprintf() %d argument reference
+ add OSF/1 AES symbol(s) to conf.tab
+ determine standards prefix from conf.tab
+ add _CS_SHELL to conf.tab
+ getpath() default is confstr(_CS_PATH)
+ getshell() default is confstr(_CS_SHELL)
+ unify keyprintf user function args (should have learned by now!)
+ add quad type to magic
+ add astfeature() to unify universe style dynamic features
+ add ftwflags() to determine FTW_* flags from astfeature()
+95-03-11 fix stropt() to not modify its *const* arg
+ handle "'\ quotes and chresc() in stropt() values
+ , treated like :space: between stropt() options
+ fix procopen() fd dup to ignore self-dups
+ add library id[] to misc/state.c
+ add ftwalk(FTW_METAPHYSICAL) for posix -H
+ sfvprintf() now handles balanced () in %()
+ add tmfmt() with buffer size check to replace tmform()
+ add fmttime() calling tmfmt() to fit fmt*() mold
+ add <keyprintf.h> and keyprintf() to support %(...)? in commands
+ add Hash_table_t for size==0 in stropt()
+ add EXTTYPE extended header to tar.h
+95-02-14 sfmove() buffer size overflow fix
+ add _SFSTDIO_H to sfio.h
+ rename setenv() to setenviron() -- posix finally decided
+ rename <option.h> opt_* to opt_info.*
+ update features/unistd.c for _SC_* and _PC_* posix additions
+95-01-19 (char*)uchar cast in fmtesc()
+ fix hash bucket memory leak in hashlook() [via John Mocenigo]
+ update strings/strtape()
+ fix optget()/optjoin() to handle leading +
+ add ALIGN_ prefix to <align.h> identifiers
+95-01-11 change tm/*.c tmset(0) to tmset(tm_info.zone) to keep user setting
+ fix tmform() %Z null pointer dereference
+95-01-01 add this RELEASE file
+ fix strperm() to properly handle "644 file"
+ fix tokline() to return last '\0' terminated line in string
+ fix tokscan() to properly handle \\n splice
+ add fmtesc() to complement stresc()
+ add LS_NUMBER to fmtls()
+ drop spurious optusage() ' '
diff --git a/src/lib/libast/aso/aso-fcntl.c b/src/lib/libast/aso/aso-fcntl.c
new file mode 100644
index 0000000..7f3f6d9
--- /dev/null
+++ b/src/lib/libast/aso/aso-fcntl.c
@@ -0,0 +1,188 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "asohdr.h"
+
+#if defined(_UWIN) && defined(_BLD_ast) || !_aso_fcntl
+
+NoN(aso_meth_fcntl)
+
+#else
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+typedef struct APL_s
+{
+ int fd;
+ size_t size;
+ char path[1];
+} APL_t;
+
+static void*
+aso_init_fcntl(void* data, const char* details)
+{
+ APL_t* apl = (APL_t*)data;
+ char* path;
+ char* opt;
+ size_t size;
+ size_t references;
+ int n;
+ int fd;
+ int drop;
+ int perm;
+ struct flock lock;
+ char buf[PATH_MAX];
+ char tmp[64];
+
+ if (apl)
+ {
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = apl->size;
+ lock.l_len = sizeof(references);
+ if (fcntl(apl->fd, F_SETLKW, &lock) >= 0)
+ {
+ if (lseek(apl->fd, apl->size, SEEK_SET) != apl->size)
+ references = 0;
+ else if (read(apl->fd, &references, sizeof(references)) != sizeof(references))
+ references = 0;
+ else if (references > 0)
+ {
+ references--;
+ if (lseek(apl->fd, apl->size, SEEK_SET) != apl->size)
+ references = 0;
+ else if (write(apl->fd, &references, sizeof(references)) != sizeof(references))
+ references = 0;
+ }
+ lock.l_type = F_UNLCK;
+ fcntl(apl->fd, F_SETLK, &lock);
+ if (!references)
+ remove(apl->path);
+ }
+ close(apl->fd);
+ free(apl);
+ return 0;
+ }
+ fd = -1;
+ perm = S_IRUSR|S_IWUSR;
+ drop = 0;
+ size = 32 * 1024 - sizeof(references);
+ if (path = (char*)details)
+ while (opt = strchr(path, ','))
+ {
+ if (strneq(path, "perm=", 5))
+ {
+ if ((n = opt - (path + 5)) >= sizeof(tmp))
+ n = sizeof(tmp) - 1;
+ memcpy(tmp, path + 5, n);
+ tmp[n] = 0;
+ perm = strperm(tmp, NiL, perm);
+ }
+ else if (strneq(path, "size=", 5))
+ {
+ size = strtoul(path + 5, NiL, 0);
+ if (size <= sizeof(references))
+ goto bad;
+ size -= sizeof(references);
+ }
+ path = opt + 1;
+ }
+ if (!path || !*path)
+ {
+ if (!(path = pathtemp(buf, sizeof(buf), NiL, "aso", &fd)))
+ return 0;
+ drop = 1;
+ }
+ if (!(apl = newof(0, APL_t, 1, strlen(path))))
+ goto bad;
+ if (fd >= 0 || (fd = open(path, O_RDWR)) < 0 && (fd = open(path, O_CREAT|O_RDWR, perm)) >= 0)
+ {
+ if (lseek(fd, size, SEEK_SET) != size)
+ goto bad;
+ references = 1;
+ if (write(fd, &references, sizeof(references)) != sizeof(references))
+ goto bad;
+ }
+ else
+ {
+ if ((size = lseek(fd, 0, SEEK_END)) <= sizeof(references))
+ goto bad;
+ size -= sizeof(references);
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = sizeof(references);
+ if (fcntl(fd, F_SETLKW, &lock) < 0)
+ goto bad;
+ if (lseek(fd, size, SEEK_SET) != size)
+ goto bad;
+ if (read(fd, &references, sizeof(references)) != sizeof(references))
+ goto bad;
+ references++;
+ if (lseek(fd, size, SEEK_SET) != size)
+ goto bad;
+ if (write(fd, &references, sizeof(references)) != sizeof(references))
+ goto bad;
+ lock.l_type = F_UNLCK;
+ fcntl(fd, F_SETLK, &lock);
+ }
+ apl->fd = fd;
+ apl->size = size;
+ strcpy(apl->path, path);
+ return apl;
+ bad:
+ if (apl)
+ free(apl);
+ if (fd >= 0)
+ close(fd);
+ if (drop)
+ remove(path);
+ return 0;
+}
+
+static ssize_t
+aso_lock_fcntl(void* data, ssize_t k, void volatile* p)
+{
+ APL_t* apl = (APL_t*)data;
+ struct flock lock;
+
+ if (!apl)
+ return -1;
+ if (k > 0)
+ lock.l_type = F_UNLCK;
+ else
+ {
+ lock.l_type = F_WRLCK;
+ k = HASH(p, apl->size) + 1;
+ }
+ lock.l_whence = SEEK_SET;
+ lock.l_start = k - 1;
+ lock.l_len = 1;
+ return fcntl(apl->fd, F_SETLKW, &lock) < 0 ? -1 : k;
+}
+
+Asometh_t _aso_meth_fcntl = { "fcntl", ASO_PROCESS, aso_init_fcntl, aso_lock_fcntl };
+
+#endif
diff --git a/src/lib/libast/aso/aso-sem.c b/src/lib/libast/aso/aso-sem.c
new file mode 100644
index 0000000..5ed9b72
--- /dev/null
+++ b/src/lib/libast/aso/aso-sem.c
@@ -0,0 +1,193 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "asohdr.h"
+
+#if defined(_UWIN) && defined(_BLD_ast) || !_aso_semaphore
+
+NoN(aso_meth_semaphore)
+
+#else
+
+#include <sys/stat.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+#define SPIN 1000000
+
+typedef union Semun_u
+{
+ int val;
+ struct semid_ds* ds;
+ unsigned short* array;
+} Semun_t;
+
+typedef struct APL_s
+{
+ int id;
+ size_t size;
+} APL_t;
+
+static void*
+aso_init_semaphore(void* data, const char* details)
+{
+ APL_t* apl = (APL_t*)data;
+ char* path;
+ char* opt;
+ size_t size;
+ size_t n;
+ int key;
+ int id;
+ int perm;
+ struct sembuf sem;
+ char tmp[64];
+
+ if (apl)
+ {
+ /*
+ * semaphore 0 is the reference count
+ * the id is dropped on last reference
+ */
+
+ sem.sem_num = 0;
+ sem.sem_op = -1;
+ sem.sem_flg = IPC_NOWAIT;
+ semop(apl->id, &sem, 1);
+ sem.sem_op = 0;
+ if (!semop(apl->id, &sem, 1))
+ semctl(apl->id, 0, IPC_RMID);
+ free(apl);
+ return 0;
+ }
+ perm = S_IRUSR|S_IWUSR;
+ size = 128;
+ if (path = (char*)details)
+ while (opt = strchr(path, ','))
+ {
+ if (strneq(path, "perm=", 5))
+ {
+ if ((n = opt - (path + 5)) >= sizeof(tmp))
+ n = sizeof(tmp) - 1;
+ memcpy(tmp, path + 5, n);
+ tmp[n] = 0;
+ perm = strperm(tmp, NiL, perm);
+ }
+ else if (strneq(path, "size=", 5))
+ {
+ size = strtoul(path + 5, NiL, 0);
+ if (size <= 1)
+ return 0;
+ }
+ path = opt + 1;
+ }
+ key = (!path || !*path || streq(path, "private")) ? IPC_PRIVATE : (strsum(path, 0) & 0x7fff);
+ for (;;)
+ {
+ if ((id = semget(key, size, IPC_CREAT|IPC_EXCL|perm)) >= 0)
+ {
+ /*
+ * initialize all semaphores to 0
+ * this also sets the semaphore 0 ref count
+ */
+
+ sem.sem_op = 1;
+ sem.sem_flg = 0;
+ for (sem.sem_num = 0; sem.sem_num < size; sem.sem_num++)
+ if (semop(id, &sem, 1) < 0)
+ {
+ (void)semctl(id, 0, IPC_RMID);
+ return 0;
+ }
+ break;
+ }
+ else if (errno == EINVAL && size > 3)
+ size /= 2;
+ else if (errno != EEXIST)
+ return 0;
+ else if ((id = semget(key, size, perm)) >= 0)
+ {
+ struct semid_ds ds;
+ Semun_t arg;
+ unsigned int k;
+
+ /*
+ * make sure all semaphores have been activated
+ */
+
+ arg.ds = &ds;
+ for (k = 0; k < SPIN; ASOLOOP(k))
+ {
+ if (semctl(id, size-1, IPC_STAT, arg) < 0)
+ return 0;
+ if (ds.sem_otime)
+ break;
+ }
+ if (k > SPIN)
+ return 0;
+
+ /*
+ * bump the ref count
+ */
+
+ sem.sem_num = 0;
+ sem.sem_op = 1;
+ sem.sem_flg = 0;
+ if (semop(id, &sem, 1) < 0)
+ return 0;
+ break;
+ }
+ else if (errno == EINVAL && size > 3)
+ size /= 2;
+ else
+ return 0;
+ }
+ if (!(apl = newof(0, APL_t, 1, 0)))
+ return 0;
+ apl->id = id;
+ apl->size = size - 1;
+ return apl;
+}
+
+static ssize_t
+aso_lock_semaphore(void* data, ssize_t k, void volatile* p)
+{
+ APL_t* apl = (APL_t*)data;
+ struct sembuf sem;
+
+ if (!apl)
+ return -1;
+ if (k > 0)
+ sem.sem_op = 1;
+ else
+ {
+ sem.sem_op = -1;
+ k = HASH(p, apl->size) + 1;
+ }
+ sem.sem_num = k;
+ sem.sem_flg = 0;
+ return semop(apl->id, &sem, 1) < 0 ? -1 : k;
+}
+
+Asometh_t _aso_meth_semaphore = { "semaphore", ASO_PROCESS|ASO_THREAD, aso_init_semaphore, aso_lock_semaphore };
+
+#endif
diff --git a/src/lib/libast/aso/aso.c b/src/lib/libast/aso/aso.c
new file mode 100644
index 0000000..6ad4f31
--- /dev/null
+++ b/src/lib/libast/aso/aso.c
@@ -0,0 +1,866 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "asohdr.h"
+
+#if defined(_UWIN) && defined(_BLD_ast)
+
+NoN(aso)
+
+#else
+
+/*
+ * ast atomic scalar operations
+ * AT&T Research
+ *
+ * cas { 8 16 32 [64] } subset snarfed from the work by
+ * Adam Edgar and Kiem-Phong Vo 2010-10-10
+ *
+ * lock methods and emulations by
+ * Glenn Fowler 2011-11-11
+ *
+ * hopefully stable by 2012-12-12
+ */
+
+#if !_PACKAGE_ast
+
+#if _UWIN
+
+extern ssize_t sfsprintf(char*, size_t, const char*, ...);
+
+#else
+
+#include <stdio.h>
+
+#define sfsprintf snprintf
+
+#endif
+
+#endif
+
+#if defined(_aso_casptr) && (defined(_aso_cas32) || defined(_aso_cas64))
+#define ASO_METHOD (&_aso_meth_intrinsic)
+#define ASO_LOCKF 0
+#else
+#define ASO_METHOD (&_aso_meth_signal)
+#define ASO_LOCKF _aso_lock_signal
+#endif
+
+typedef union
+{
+ uint8_t c[2];
+ uint16_t i;
+} U16_8_t;
+
+typedef union
+{
+ uint8_t c[4];
+ uint32_t i;
+} U32_8_t;
+
+typedef union
+{
+ uint16_t c[2];
+ uint32_t i;
+} U32_16_t;
+
+#ifdef _ast_int8_t
+
+typedef union
+{
+ uint8_t c[8];
+ uint64_t i;
+} U64_8_t;
+
+typedef union
+{
+ uint16_t c[4];
+ uint64_t i;
+} U64_16_t;
+
+typedef union
+{
+ uint32_t c[2];
+ uint64_t i;
+} U64_32_t;
+
+#endif
+
+typedef struct State_s
+{
+ Asometh_t* meth;
+ Asolock_f lockf;
+ Asoerror_f errorf;
+ uintmax_t hung;
+ unsigned int hung2;
+ void* data;
+ pid_t pid;
+} State_t;
+
+static unsigned int _aso_data_signal;
+
+static ssize_t
+_aso_lock_signal(void* data, ssize_t k, void volatile* p)
+{
+ if (k >= 0)
+ {
+ _aso_data_signal--;
+ return 0;
+ }
+ while (_aso_data_signal++)
+ _aso_data_signal--;
+ return 1;
+}
+
+static Asometh_t _aso_meth_signal = { "signal", ASO_SIGNAL, 0, _aso_lock_signal };
+extern Asometh_t _aso_meth_semaphore;
+extern Asometh_t _aso_meth_fcntl;
+static Asometh_t _aso_meth_intrinsic = { "intrinsic", ASO_INTRINSIC|ASO_PROCESS|ASO_THREAD|ASO_SIGNAL, 0, 0 };
+
+static Asometh_t* method[] =
+{
+ &_aso_meth_signal,
+#if defined(_ast_int8_t) && defined(_aso_cas64) || !defined(_ast_int8_t) && defined(_aso_cas32)
+ &_aso_meth_intrinsic,
+#endif
+#if _aso_semaphore
+ &_aso_meth_semaphore,
+#endif
+#if _aso_fcntl
+ &_aso_meth_fcntl,
+#endif
+};
+
+static State_t state =
+{
+ ASO_METHOD, ASO_LOCKF
+};
+
+static int
+asoerror(int type, const char* format, const char* a, const char* b, long n)
+{
+ char buf[128];
+
+ if (b)
+ sfsprintf(buf, sizeof(buf), format, a, b, n);
+ else if (a)
+ sfsprintf(buf, sizeof(buf), format, a, n);
+ else
+ sfsprintf(buf, sizeof(buf), format, n);
+ return state.errorf(type, buf);
+}
+
+/*
+ * if type!=0 return lock method for type with name details
+ * else if name!=0 return lock method matching <name>[,<details>]
+ * else return the current lock method
+ * 0 returned on error
+ *
+ * the user visible asometh() calls this function
+ * it allows, e.g., for -ltaso to provide an asometh() intercept
+ * that prepend its ASO_THREAD methods ahead of the _asometh() methods
+ */
+
+Asometh_t*
+_asometh(int type, void* data)
+{
+ size_t n;
+ int i;
+ char* e;
+ Asometh_t* meth;
+ char* name;
+
+ if (type == ASO_NEXT)
+ {
+ if (!(meth = (Asometh_t*)data))
+ return method[0];
+ for (i = 0; i < elementsof(method) - 1; i++)
+ if (meth == method[i])
+ return method[i+1];
+ return 0;
+ }
+ if (type)
+ {
+ for (i = 0; i < elementsof(method); i++)
+ if (method[i]->type & type)
+ {
+ method[i]->details = (char*)data;
+ return method[i];
+ }
+ return 0;
+ }
+ if (!(name = (char*)data))
+ return state.meth;
+ n = (e = strchr(name, ',')) ? (e - name) : strlen(name);
+ for (i = 0; i < elementsof(method); i++)
+ if (strncmp(name, method[i]->name, n) == 0)
+ {
+ if (e)
+ method[i]->details = e + 1;
+ return method[i];
+ }
+ return 0;
+}
+
+/*
+ * clean up lock method on exit
+ */
+
+static void
+asoexit(void)
+{
+ if (state.meth && state.meth->initf && state.data && state.pid == getpid())
+ {
+ state.lockf = ASO_METHOD->lockf;
+ state.meth->initf(state.data, 0);
+ state.data = 0;
+ }
+}
+
+/*
+ * initialize lock method
+ */
+
+int
+asoinit(const char* details, Asometh_t* meth, Asodisc_t* disc)
+{
+ void* data;
+
+ if (disc)
+ {
+ state.errorf = disc->errorf;
+ state.hung2 = disc->hung;
+ state.hung = 1;
+ state.hung <<= state.hung2;
+ state.hung--;
+ }
+ if (!meth)
+ return 0;
+ if (!meth->lockf && !(meth->type & ASO_INTRINSIC))
+ {
+ if (state.errorf)
+ asoerror(ASO_EMETHOD, "%s method has no lock function", meth->name, 0, 0);
+ return -1;
+ }
+ state.lockf = ASO_METHOD->lockf;
+ if (state.meth && state.meth->initf && state.data)
+ {
+ state.meth->initf(state.data, 0);
+ state.data = 0;
+ }
+ if (!meth->initf)
+ data = 0;
+ else if (!(data = meth->initf(0, details ? details : meth->details)))
+ {
+ state.meth = ASO_METHOD;
+ if (state.errorf)
+ asoerror(ASO_EMETHOD, "%s method initialization failed -- reverting to the %s method", meth->name, state.meth->name, 0);
+ return -1;
+ }
+ state.meth = meth;
+ state.data = data;
+ state.lockf = meth->lockf;
+ if (!state.pid)
+ {
+ state.pid = getpid();
+ atexit(asoexit);
+ }
+ return 0;
+}
+
+/*
+ * loop check for hung spin locks
+ * and periodic relinquishing of the processor
+ */
+
+int
+asoloop(uintmax_t rep)
+{
+ if (state.hung && !(rep & state.hung) && state.errorf)
+ return asoerror(ASO_EHUNG, "spin lock possibly hung after 2^%u attempts", 0, 0, state.hung2);
+ return (rep & ASO_RELAX) ? 0 : asorelax(1);
+}
+
+/*
+ * error checking state.lockf() call
+ */
+
+static ssize_t
+lock(void* data, ssize_t k, void volatile* p)
+{
+ ssize_t r;
+
+ if ((r = state.lockf(data, k, p)) < 0 && state.errorf)
+ asoerror(ASO_EMETHOD, "%s method lock failed", state.meth->name, 0, 0);
+ return r;
+}
+
+/*
+ * sync and return "current" value
+ */
+
+uint8_t
+asoget8(uint8_t volatile* p)
+{
+ int o;
+
+ do
+ {
+ o = *p;
+ } while (asocas8(p, o, o) != o);
+ return o;
+}
+
+uint16_t
+asoget16(uint16_t volatile* p)
+{
+ int o;
+
+ do
+ {
+ o = *p;
+ } while (asocas16(p, o, o) != o);
+ return o;
+}
+
+uint32_t
+asoget32(uint32_t volatile* p)
+{
+ uint32_t o;
+
+ do
+ {
+ o = *p;
+ } while (asocas32(p, o, o) != o);
+ return o;
+}
+
+#ifdef _ast_int8_t
+
+uint64_t
+asoget64(uint64_t volatile* p)
+{
+ uint64_t o;
+
+ do
+ {
+ o = *p;
+ } while (asocas64(p, o, o) != o);
+ return o;
+}
+
+#endif
+
+void*
+asogetptr(void volatile* p)
+{
+ void* o;
+
+ do
+ {
+ o = *(void* volatile*)p;
+ } while (asocasptr(p, o, o) != o);
+ return o;
+}
+
+/*
+ * increment and return old value
+ */
+
+uint8_t
+asoinc8(uint8_t volatile* p)
+{
+ ssize_t k;
+ int o;
+
+#if defined(_aso_inc8)
+ if (!state.lockf)
+ return _aso_inc8(p);
+#else
+ if (!state.lockf)
+ {
+ do
+ {
+ o = *p;
+ } while (asocas8(p, o, o + 1) != o);
+ return o;
+ }
+#endif
+ k = lock(state.data, 0, p);
+ o = (*p)++;
+ lock(state.data, k, p);
+ return o;
+}
+
+uint16_t
+asoinc16(uint16_t volatile* p)
+{
+ ssize_t k;
+ int o;
+
+#if defined(_aso_inc16)
+ if (!state.lockf)
+ return _aso_inc16(p);
+#else
+ if (!state.lockf)
+ {
+ do
+ {
+ o = *p;
+ } while (asocas16(p, o, o + 1) != o);
+ return o;
+ }
+#endif
+ k = lock(state.data, 0, p);
+ o = (*p)++;
+ lock(state.data, k, p);
+ return o;
+}
+
+uint32_t
+asoinc32(uint32_t volatile* p)
+{
+ ssize_t k;
+ int o;
+
+#if defined(_aso_inc32)
+ if (!state.lockf)
+ return _aso_inc32(p);
+#else
+ if (!state.lockf)
+ {
+ do
+ {
+ o = *p;
+ } while (asocas32(p, o, o + 1) != o);
+ return o;
+ }
+#endif
+ k = lock(state.data, 0, p);
+ o = (*p)++;
+ lock(state.data, k, p);
+ return o;
+}
+
+#ifdef _ast_int8_t
+
+uint64_t
+asoinc64(uint64_t volatile* p)
+{
+ ssize_t k;
+ uint64_t o;
+
+#if defined(_aso_inc64)
+ if (!state.lockf)
+ return _aso_inc64(p);
+#else
+ if (!state.lockf)
+ {
+ do
+ {
+ o = *p;
+ } while (asocas64(p, o, o + 1) != o);
+ return o;
+ }
+#endif
+ k = lock(state.data, 0, p);
+ o = (*p)++;
+ lock(state.data, k, p);
+ return o;
+}
+
+#endif
+
+/*
+ * decrement and return old value
+ */
+
+uint8_t
+asodec8(uint8_t volatile* p)
+{
+ ssize_t k;
+ int o;
+
+#if defined(_aso_dec8)
+ if (!state.lockf)
+ return _aso_dec8(p);
+#else
+ if (!state.lockf)
+ {
+ do
+ {
+ o = *p;
+ } while (asocas8(p, o, o - 1) != o);
+ return o;
+ }
+#endif
+ k = lock(state.data, 0, p);
+ o = (*p)--;
+ lock(state.data, k, p);
+ return o;
+}
+
+uint16_t
+asodec16(uint16_t volatile* p)
+{
+ ssize_t k;
+ int o;
+
+#if defined(_aso_dec16)
+ if (!state.lockf)
+ return _aso_dec16(p);
+#else
+ if (!state.lockf)
+ {
+ do
+ {
+ o = *p;
+ } while (asocas16(p, o, o - 1) != o);
+ return o;
+ }
+#endif
+ k = lock(state.data, 0, p);
+ o = (*p)--;
+ lock(state.data, k, p);
+ return o;
+}
+
+uint32_t
+asodec32(uint32_t volatile* p)
+{
+ ssize_t k;
+ int o;
+
+#if defined(_aso_dec32)
+ if (!state.lockf)
+ return _aso_dec32(p);
+#else
+ if (!state.lockf)
+ {
+ do
+ {
+ o = *p;
+ } while (asocas32(p, o, o - 1) != o);
+ return o;
+ }
+#endif
+ k = lock(state.data, 0, p);
+ o = (*p)--;
+ lock(state.data, k, p);
+ return o;
+}
+
+#ifdef _ast_int8_t
+
+uint64_t
+asodec64(uint64_t volatile* p)
+{
+ ssize_t k;
+ uint64_t o;
+
+#if defined(_aso_dec64)
+ if (!state.lockf)
+ return _aso_dec64(p);
+#else
+ if (!state.lockf)
+ {
+ do
+ {
+ o = *p;
+ } while (asocas64(p, o, o - 1) != o);
+ return o;
+ }
+#endif
+ k = lock(state.data, 0, p);
+ o = (*p)--;
+ lock(state.data, k, p);
+ return o;
+}
+
+#endif
+
+/*
+ * { 8 16 32 [64] } compare with old, swap with new if same, and return old value
+ */
+
+uint8_t
+asocas8(uint8_t volatile* p, int o, int n)
+{
+ ssize_t k;
+
+#if defined(_aso_cas8)
+ if (!state.lockf)
+ return _aso_cas8(p, o, n);
+#elif defined(_aso_cas16)
+ if (!state.lockf)
+ {
+ U16_8_t u;
+ U16_8_t v;
+ U16_8_t* a;
+ int s;
+ int i;
+
+ s = (int)(integralof(p) & (sizeof(u.i) - 1));
+ a = (U16_8_t*)((char*)0 + (integralof(p) & ~(sizeof(u.i) - 1)));
+ for (;;)
+ {
+ u.i = a->i;
+ u.c[s] = o;
+ v.i = u.i;
+ v.c[s] = n;
+ if (_aso_cas16(&a->i, u.i, v.i) == u.i)
+ break;
+ for (i = 0;; i++)
+ if (i >= elementsof(u.c))
+ return a->c[s];
+ else if (i != s && u.c[i] != a->c[i])
+ break;
+ }
+ return o;
+ }
+#elif defined(_aso_cas32)
+ if (!state.lockf)
+ {
+ U32_8_t u;
+ U32_8_t v;
+ U32_8_t* a;
+ int s;
+ int i;
+
+ s = (int)(integralof(p) & (sizeof(u.i) - 1));
+ a = (U32_8_t*)((char*)0 + (integralof(p) & ~(sizeof(u.i) - 1)));
+ for (;;)
+ {
+ u.i = a->i;
+ u.c[s] = o;
+ v.i = u.i;
+ v.c[s] = n;
+ if (_aso_cas32(&a->i, u.i, v.i) == u.i)
+ break;
+ for (i = 0;; i++)
+ if (i >= elementsof(u.c))
+ return a->c[s];
+ else if (i != s && u.c[i] != a->c[i])
+ break;
+ }
+ return o;
+ }
+#elif defined(_aso_cas64)
+ if (!state.lockf)
+ {
+ U64_8_t u;
+ U64_8_t v;
+ U64_8_t* a;
+ int s;
+ int i;
+
+ s = (int)(integralof(p) & (sizeof(u.i) - 1));
+ a = (U64_8_t*)((char*)0 + (integralof(p) & ~(sizeof(u.i) - 1)));
+ for (;;)
+ {
+ u.i = a->i;
+ u.c[s] = o;
+ v.i = u.i;
+ v.c[s] = n;
+ if (_aso_cas64(&a->i, u.i, v.i) == u.i)
+ break;
+ for (i = 0;; i++)
+ if (i >= elementsof(u.c))
+ return a->c[s];
+ else if (i != s && u.c[i] != a->c[i])
+ break;
+ }
+ return o;
+ }
+#endif
+ k = lock(state.data, 0, p);
+ if (*p == o)
+ *p = n;
+ else
+ o = *p;
+ lock(state.data, k, p);
+ return o;
+}
+
+uint16_t
+asocas16(uint16_t volatile* p, uint16_t o, uint16_t n)
+{
+ ssize_t k;
+
+#if defined(_aso_cas16)
+ if (!state.lockf)
+ return _aso_cas16(p, o, n);
+#elif defined(_aso_cas32)
+ if (!state.lockf)
+ {
+ U32_16_t u;
+ U32_16_t v;
+ U32_16_t* a;
+ int s;
+ int i;
+
+ s = (int)(integralof(p) & (sizeof(u.i) - 1)) / 2;
+ a = (U32_16_t*)((char*)0 + (integralof(p) & ~(sizeof(u.i) - 1)));
+ for (;;)
+ {
+ u.i = a->i;
+ u.c[s] = o;
+ v.i = u.i;
+ v.c[s] = n;
+ if (_aso_cas32(&a->i, u.i, v.i) == u.i)
+ break;
+ for (i = 0;; i++)
+ if (i >= elementsof(u.c))
+ return a->c[s];
+ else if (i != s && u.c[i] != a->c[i])
+ break;
+ }
+ return o;
+ }
+#elif defined(_aso_cas64)
+ if (!state.lockf)
+ {
+ U64_16_t u;
+ U64_16_t v;
+ U64_16_t* a;
+ int s;
+ int i;
+
+ s = (int)(integralof(p) & (sizeof(u.i) - 1)) / 2;
+ a = (U64_16_t*)((char*)0 + (integralof(p) & ~(sizeof(u.i) - 1)));
+ for (;;)
+ {
+ u.i = a->i;
+ u.c[s] = o;
+ v.i = u.i;
+ v.c[s] = n;
+ if (_aso_cas64(&a->i, u.i, v.i) == u.i)
+ break;
+ for (i = 0;; i++)
+ if (i >= elementsof(u.c))
+ return a->c[s];
+ else if (i != s && u.c[i] != a->c[i])
+ break;
+ }
+ return o;
+ }
+#endif
+ k = lock(state.data, 0, p);
+ if (*p == o)
+ *p = n;
+ else
+ o = *p;
+ lock(state.data, k, p);
+ return o;
+}
+
+uint32_t
+asocas32(uint32_t volatile* p, uint32_t o, uint32_t n)
+{
+ ssize_t k;
+
+#if defined(_aso_cas32)
+ if (!state.lockf)
+ return _aso_cas32(p, o, n);
+#elif defined(_aso_cas64)
+ if (!state.lockf)
+ {
+ U64_32_t u;
+ U64_32_t v;
+ U64_32_t* a;
+ int s;
+ int i;
+
+ s = (int)(integralof(p) & (sizeof(u.i) - 1)) / 4;
+ a = (U64_32_t*)((char*)0 + (integralof(p) & ~(sizeof(u.i) - 1)));
+ for (;;)
+ {
+ u.i = a->i;
+ u.c[s] = o;
+ v.i = u.i;
+ v.c[s] = n;
+ if (_aso_cas64(&a->i, u.i, v.i) == u.i)
+ break;
+ for (i = 0;; i++)
+ if (i >= elementsof(u.c))
+ return a->c[s];
+ else if (i != s && u.c[i] != a->c[i])
+ break;
+ }
+ return o;
+ }
+#endif
+ k = lock(state.data, 0, p);
+ if (*p == o)
+ *p = n;
+ else
+ o = *p;
+ lock(state.data, k, p);
+ return o;
+}
+
+#ifdef _ast_int8_t
+
+uint64_t
+asocas64(uint64_t volatile* p, uint64_t o, uint64_t n)
+{
+ ssize_t k;
+
+#if defined(_aso_cas64)
+ if (!state.lockf)
+ return _aso_cas64(p, o, n);
+#endif
+ k = lock(state.data, 0, p);
+ if (*p == o)
+ *p = n;
+ else
+ o = *p;
+ lock(state.data, k, p);
+ return o;
+}
+
+#endif
+
+/*
+ * compare with old, swap with new if same, and return old value
+ */
+
+void*
+asocasptr(void volatile* p, void* o, void* n)
+{
+ ssize_t k;
+
+#if defined(_aso_casptr)
+ if (!state.lockf)
+ return _aso_casptr((void**)p, o, n);
+#endif
+ k = lock(state.data, 0, p);
+ if (*(void* volatile*)p == o)
+ *(void* volatile*)p = n;
+ else
+ o = *(void* volatile*)p;
+ lock(state.data, k, p);
+ return o;
+}
+
+#endif
diff --git a/src/lib/libast/aso/asohdr.h b/src/lib/libast/aso/asohdr.h
new file mode 100644
index 0000000..80bb3bf
--- /dev/null
+++ b/src/lib/libast/aso/asohdr.h
@@ -0,0 +1,71 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _ASOHDR_H
+#define _ASOHDR_H 1
+
+#if _PACKAGE_ast
+
+#include <ast.h>
+#include <error.h>
+#include <fnv.h>
+
+#else
+
+#include <errno.h>
+
+#ifndef elementsof
+#define elementsof(x) (sizeof(x)/sizeof(x[0]))
+#endif
+#ifndef integralof
+#define integralof(x) (((char*)(x))-((char*)0))
+#endif
+#ifndef FNV_MULT
+#define FNV_MULT 0x01000193L
+#endif
+#ifndef NiL
+#define NiL ((void*)0)
+#endif
+#ifndef NoN
+#if defined(__STDC__) || defined(__STDPP__)
+#define NoN(x) void _STUB_ ## x () {}
+#else
+#define NoN(x) void _STUB_/**/x () {}
+#endif
+#if !defined(_STUB_)
+#define _STUB_
+#endif
+#endif
+
+#endif
+
+#include "FEATURE/aso"
+
+#if _UWIN
+#undef _aso_fcntl
+#undef _aso_semaphore
+#endif
+
+#include "aso.h"
+
+#define HASH(p,z) ((integralof(p)*FNV_MULT)%(z))
+
+#endif
diff --git a/src/lib/libast/aso/asolock.c b/src/lib/libast/aso/asolock.c
new file mode 100644
index 0000000..60c7dba
--- /dev/null
+++ b/src/lib/libast/aso/asolock.c
@@ -0,0 +1,55 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "asohdr.h"
+
+#if defined(_UWIN) && defined(_BLD_ast)
+
+NoN(asolock)
+
+#else
+
+int
+asolock(unsigned int volatile* lock, unsigned int key, int type)
+{
+ unsigned int k;
+
+ if (key)
+ switch (type)
+ {
+ case ASO_UNLOCK:
+ return *lock == 0 ? 0 : asocasint(lock, key, 0) == key ? 0 : -1;
+ case ASO_TRYLOCK:
+ return *lock == key ? 0 : asocasint(lock, 0, key) == 0 ? 0 : -1;
+ case ASO_LOCK:
+ if (*lock == key)
+ return 0;
+ /*FALLTHROUGH*/
+ case ASO_SPINLOCK:
+ for (k = 0; asocasint(lock, 0, key) != 0; ASOLOOP(k));
+ return 0;
+ }
+ return -1;
+}
+
+#endif
diff --git a/src/lib/libast/aso/asometh.c b/src/lib/libast/aso/asometh.c
new file mode 100644
index 0000000..e97bbab
--- /dev/null
+++ b/src/lib/libast/aso/asometh.c
@@ -0,0 +1,43 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "asohdr.h"
+
+#if defined(_UWIN) && defined(_BLD_ast)
+
+NoN(asometh)
+
+#else
+
+/*
+ * this is the default user visible asometh()
+ * -ltaso intercepts asometh() to prepend ASO_THREAD methods
+ */
+
+Asometh_t*
+asometh(int type, void* data)
+{
+ return _asometh(type, data);
+}
+
+#endif
diff --git a/src/lib/libast/aso/asorelax.c b/src/lib/libast/aso/asorelax.c
new file mode 100644
index 0000000..9716380
--- /dev/null
+++ b/src/lib/libast/aso/asorelax.c
@@ -0,0 +1,56 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "asohdr.h"
+
+#if defined(_UWIN) && defined(_BLD_ast)
+
+NoN(asorelax)
+
+#else
+
+#if _PACKAGE_ast
+#include <tv.h>
+#else
+#include <time.h>
+#endif
+
+int
+asorelax(long nsec)
+{
+#if _PACKAGE_ast
+ Tv_t tv;
+
+ tv.tv_sec = 0;
+ tv.tv_nsec = nsec;
+ return tvsleep(&tv, 0);
+#else
+ struct timespec ts;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = nsec;
+ return nanosleep(&ts, 0);
+#endif
+}
+
+#endif
diff --git a/src/lib/libast/astsa/README-astsa b/src/lib/libast/astsa/README-astsa
new file mode 100644
index 0000000..0935f7e
--- /dev/null
+++ b/src/lib/libast/astsa/README-astsa
@@ -0,0 +1,15 @@
+astsa implements a small subset of the ast library for other ast
+standalone commands and libraries using X/Open interfaces.
+
+To get better performance and functionality, consider using any of
+the full-featured ast-* packages at
+
+ http://www.research.att.com/sw/download/
+
+astsa.omk is an old make makefile that builds the headers and objects
+and defines these variables for use in other makefiles
+
+ ASTSA_OPTIMIZE ``-O'' by default
+
+The astsa files may be combined in a single directory with other ast
+standalone packages.
diff --git a/src/lib/libast/astsa/aso.c b/src/lib/libast/astsa/aso.c
new file mode 100644
index 0000000..3b2226d
--- /dev/null
+++ b/src/lib/libast/astsa/aso.c
@@ -0,0 +1,56 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <aso.h>
+
+int
+asolock(unsigned int volatile* lock, unsigned int key, int type)
+{
+ unsigned int k;
+
+ if (key)
+ switch (type)
+ {
+ case ASO_UNLOCK:
+ if (*lock != 0)
+ {
+ if (*lock != key)
+ return -1;
+ *lock = 0;
+ }
+ return 0;
+ case ASO_TRYLOCK:
+ if (*lock != key)
+ {
+ if (*lock != 0)
+ return -1;
+ *lock = key;
+ }
+ return 0;
+ case ASO_LOCK:
+ case ASO_SPINLOCK:
+ *lock = key;
+ return 0;
+ }
+ return -1;
+}
diff --git a/src/lib/libast/astsa/aso.h b/src/lib/libast/astsa/aso.h
new file mode 100644
index 0000000..9c5d2c2
--- /dev/null
+++ b/src/lib/libast/astsa/aso.h
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _ASO_H
+#define _ASO_H 1
+
+#define ASO_UNLOCK 0 /* unlock if key matches */
+#define ASO_TRYLOCK 1 /* matched key means successful attempt */
+#define ASO_LOCK 2 /* matched key first, then spin-lock */
+#define ASO_SPINLOCK 3 /* no matching of key before locking */
+
+extern int asolock(unsigned int volatile*, unsigned int, int);
+
+#endif
diff --git a/src/lib/libast/astsa/ast.c b/src/lib/libast/astsa/ast.c
new file mode 100644
index 0000000..6428ebf
--- /dev/null
+++ b/src/lib/libast/astsa/ast.c
@@ -0,0 +1,85 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * standalone mini ast+sfio implementation
+ */
+
+#include <ast.h>
+
+#define CHUNK 1024
+
+_Ast_info_t ast;
+
+int
+astwinsize(int fd, int* lines, int* columns)
+{
+ if (lines)
+ *lines = 24;
+ if (columns)
+ *columns = 80;
+ return 0;
+}
+
+char*
+sfgetr(Sfio_t* sp, int c, int z)
+{
+ register char* s;
+ register char* e;
+
+ static char* buf;
+ static unsigned long siz;
+
+ if (!buf)
+ {
+ siz = CHUNK;
+ if (!(buf = newof(0, char, siz, 0)))
+ return 0;
+ }
+ if (z < 0)
+ return *buf ? buf : (char*)0;
+ s = buf;
+ e = s + siz;
+ for (;;)
+ {
+ if (s >= e)
+ {
+ siz += CHUNK;
+ if (!(buf = newof(buf, char, siz, 0)))
+ return 0;
+ s = buf + (siz - CHUNK);
+ e = s + siz;
+ }
+ if ((c = sfgetc(sp)) == EOF)
+ {
+ *s = 0;
+ return 0;
+ }
+ if (c == '\n')
+ {
+ *s = z ? 0 : c;
+ break;
+ }
+ *s++ = c;
+ }
+ return buf;
+}
diff --git a/src/lib/libast/astsa/ast.h b/src/lib/libast/astsa/ast.h
new file mode 100644
index 0000000..f25f6a5
--- /dev/null
+++ b/src/lib/libast/astsa/ast.h
@@ -0,0 +1,156 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * standalone mini ast+sfio interface
+ */
+
+#ifndef _AST_H
+#define _AST_H 1
+
+#include <ast_sa.h>
+#include <ast_common.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#define FMT_EXP_CHAR 0x020 /* expand single byte chars */
+#define FMT_EXP_LINE 0x040 /* expand \n and \r */
+#define FMT_EXP_WIDE 0x080 /* expand \u \U \x wide chars */
+#define FMT_EXP_NOCR 0x100 /* skip \r */
+#define FMT_EXP_NONL 0x200 /* skip \n */
+
+#define STR_MAXIMAL 01 /* maximal match */
+#define STR_LEFT 02 /* implicit left anchor */
+#define STR_RIGHT 04 /* implicit right anchor */
+#define STR_ICASE 010 /* ignore case */
+#define STR_GROUP 020 /* (|&) inside [@|&](...) only */
+
+typedef int (*Error_f)(void*, void*, int, ...);
+
+typedef struct
+{
+
+ char* id;
+
+ struct
+ {
+ unsigned int serial;
+ unsigned int set;
+ } locale;
+
+ long tmp_long;
+ size_t tmp_size;
+ short tmp_short;
+ char tmp_char;
+ wchar_t tmp_wchar;
+
+ int (*collate)(const char*, const char*);
+
+ int tmp_int;
+ void* tmp_pointer;
+
+ int mb_cur_max;
+ int (*mb_len)(const char*, size_t);
+ int (*mb_towc)(wchar_t*, const char*, size_t);
+ size_t (*mb_xfrm)(char*, const char*, size_t);
+ int (*mb_width)(wchar_t);
+ int (*mb_conv)(char*, wchar_t);
+
+ unsigned int env_serial;
+
+ char pad[944];
+
+} _Ast_info_t;
+
+#define ast _ast_info_
+
+#define elementsof(x) (sizeof(x)/sizeof(x[0]))
+#define integralof(x) (((char*)(x))-((char*)0))
+#define newof(p,t,n,x) ((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)calloc(1,sizeof(t)*(n)+(x)))
+#define oldof(p,t,n,x) ((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)malloc(sizeof(t)*(n)+(x)))
+#define pointerof(x) ((void*)((char*)0+(x)))
+#define roundof(x,y) (((x)+(y)-1)&~((y)-1))
+
+#ifndef offsetof
+#define offsetof(type,member) ((unsigned long)&(((type*)0)->member))
+#endif
+
+#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
+#define NiL 0
+#define NoP(x) (void)(x)
+#else
+#define NiL ((char*)0)
+#define NoP(x) (&x,1)
+#endif
+
+#define conformance(a,b) "ast"
+#define fmtident(s) ((char*)(s)+10)
+#define mbchar(s) (*s++)
+#define setlocale(a,b)
+
+#define streq(a,b) (*(a)==*(b)&&!strcmp(a,b))
+#define strneq(a,b,n) (*(a)==*(b)&&!strncmp(a,b,n))
+#define strton(s,t,b,f) strtol(s,t,0)
+#define strtonll(s,t,b,f) strtoll(s,t,0)
+
+#define Sfio_t FILE
+
+#define sfstdin stdin
+#define sfstdout stdout
+#define sfstderr stderr
+
+#define sfclose(f) fclose(f)
+#define sffileno(f) fileno(f)
+#define sfgetc(f) fgetc(f)
+#define sfopen(f,n,m) fopen(n,m)
+#define sfputc(f,c) fputc(c,f)
+#define sfread(f,b,n) fread(b,n,1,f)
+#define sfseek(f,p,w) fseek(f,p,w)
+#define sfset(f,v,n)
+#define sfsync(f) fflush(f)
+#define sfwrite(f,b,n) fwrite(b,n,1,f)
+
+#define sfprintf fprintf
+#define sfsprintf snprintf
+#define sfvprintf vfprintf
+
+#define sfscanf fscanf
+
+#define sfgetr _sf_getr
+
+#include <sfstr.h>
+
+extern _Ast_info_t ast;
+
+extern int astwinsize(int, int*, int*);
+extern int chresc(const char*, char**);
+extern char* fmtbuf(size_t);
+extern char* fmtip4(uint32_t, int);
+extern char* sfgetr(Sfio_t*, int, int);
+extern char* strcopy(char*, const char*);
+extern int strmatch(const char*, const char*);
+extern int strtoip4(const char*, char**, uint32_t*, unsigned char*);
+
+#endif
diff --git a/src/lib/libast/astsa/ast_common.h b/src/lib/libast/astsa/ast_common.h
new file mode 100644
index 0000000..55573d6
--- /dev/null
+++ b/src/lib/libast/astsa/ast_common.h
@@ -0,0 +1,49 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _AST_COMMON_H
+#define _AST_COMMON_H 1
+
+#include <ast_sa.h>
+#include <sys/types.h>
+
+#define Void_t void
+#define _ARG_(x) x
+#define _BEGIN_EXTERNS_
+#define _END_EXTERNS_
+#define __STD_C 1
+
+#if _hdr_stdint
+#include <stdint.h>
+#else
+#include <inttypes.h>
+#endif
+
+#if _hdr_unistd
+#include <unistd.h>
+#endif
+
+#define _typ_int32_t 1
+#ifdef _ast_int8_t
+#define _typ_int64_t 1
+#endif
+
+#endif
diff --git a/src/lib/libast/astsa/astsa.manifest b/src/lib/libast/astsa/astsa.manifest
new file mode 100644
index 0000000..03785fa
--- /dev/null
+++ b/src/lib/libast/astsa/astsa.manifest
@@ -0,0 +1,50 @@
+../../../../include/prototyped.h
+../cdt/cdtlib.h
+../cdt/dtclose.c
+../cdt/dtdisc.c
+../cdt/dthash.c
+../cdt/dthdr.h
+../cdt/dtlist.c
+../cdt/dtmethod.c
+../cdt/dtnew.c
+../cdt/dtopen.c
+../cdt/dtstrhash.c
+../cdt/dttree.c
+../cdt/dtview.c
+../cdt/dtwalk.c
+../include/cdt.h
+../include/hashkey.h
+../include/hashpart.h
+../include/ip6.h
+../include/magicid.h
+../misc/optget.c
+../misc/optlib.h
+../string/chresc.c
+../string/fmtbuf.c
+../string/fmtip4.c
+../string/fmtip6.c
+../string/strcopy.c
+../string/strtoip4.c
+../string/strtoip6.c
+README-astsa
+aso.c
+aso.h
+ast.c
+ast.h
+ast_common.h
+astsa.manifest
+astsa.mm
+astsa.omk
+ccode.h
+debug.h
+error.c
+error.h
+mkast_sa
+option.h
+sfstr.c
+sfstr.h
+strdup.c
+strmatch.c
+times.h
+vmalloc.c
+vmalloc.h
diff --git a/src/lib/libast/astsa/astsa.mm b/src/lib/libast/astsa/astsa.mm
new file mode 100644
index 0000000..eca64c0
--- /dev/null
+++ b/src/lib/libast/astsa/astsa.mm
@@ -0,0 +1,33 @@
+.xx title="astsa"
+.MT 4
+.TL
+
+.H 1 "astsa"
+.B astsa
+implements a small subset of the
+.B ast
+library for other
+.B ast
+standalone commands and libraries using X/Open interfaces.
+.P
+To get better performance and functionality, consider using any of
+the full-featured ast-* packages at
+.DS
+.xx link="http://www.research.att.com/sw/download/"
+.DE
+.P
+astsa.omk is an old make makefile that builds the headers and objects
+and defines these variables for use in other makefiles
+.VL 12
+.LI
+.B ASTSA_GEN
+point -I to these
+.LI
+.B ASTSA_HDRS
+point -I to these
+.LI
+.B AST_OBJS
+link against these
+.LE
+The astsa files may be combined in a single directory with other ast
+standalone packages.
diff --git a/src/lib/libast/astsa/astsa.omk b/src/lib/libast/astsa/astsa.omk
new file mode 100644
index 0000000..92d7882
--- /dev/null
+++ b/src/lib/libast/astsa/astsa.omk
@@ -0,0 +1,82 @@
+#
+# standalone mini libast old make makefile
+#
+
+CC = cc
+CFLAGS = $(ASTSA_CFLAGS)
+
+ASTSA_OPTIMIZE = -O
+ASTSA_CFLAGS = $(ASTSA_OPTIMIZE) -D_PACKAGE_astsa -I.
+
+ASTSA_GEN = \
+ ast_sa.h
+
+ASTSA_BLD = \
+ dthdr.h
+
+ASTSA_HDRS = \
+ ast.h \
+ ast_common.h \
+ ccode.h \
+ cdt.h \
+ debug.h \
+ error.h \
+ hashkey.h \
+ hashpart.h \
+ ip6.h \
+ magicid.h \
+ option.h \
+ optlib.h \
+ prototyped.h \
+ sfstr.h \
+ times.h \
+ vmalloc.h
+
+ASTSA_SRCS = \
+ aso.c \
+ ast.c \
+ chresc.c \
+ error.c \
+ fmtbuf.c \
+ fmtip4.c \
+ fmtip6.c \
+ optget.c \
+ sfstr.c \
+ strcopy.c \
+ strdup.c \
+ strmatch.c \
+ strtoip4.c \
+ strtoip6.c \
+ vmalloc.c \
+ dtclose.c \
+ dtdisc.c \
+ dthash.c \
+ dtlist.c \
+ dtmethod.c \
+ dtnew.c \
+ dtopen.c \
+ dtstrhash.c \
+ dttree.c \
+ dtview.c \
+ dtwalk.c
+
+ASTSA_MANIFEST = \
+ README astsa.omk mkast_sa \
+ $(ASTSA_BLD) $(ASTSA_HDRS) $(ASTSA_SRCS)
+
+astsa : ast_sa.h libastsa.a
+
+libastsa.a : aso.o ast.o chresc.o error.o fmtbuf.o fmtip4.o fmtip6.o optget.o \
+ sfstr.o strcopy.o strdup.o strmatch.o strtoip4.o strtoip6.o \
+ vmalloc.o \
+ dtclose.o dtdisc.o dthash.o dtlist.o dtmethod.o \
+ dtopen.o dtstrhash.o dttree.o dtview.o dtwalk.o
+ ar cr libastsa.a $?
+
+ast_sa.h : mkast_sa
+ ./mkast_sa $(CC) $(CFLAGS) > ast_sa.h
+
+clean :
+ rm -f ast_sa.h *.o *.a
+
+clobber : clean
diff --git a/src/lib/libast/astsa/ccode.h b/src/lib/libast/astsa/ccode.h
new file mode 100644
index 0000000..493e462
--- /dev/null
+++ b/src/lib/libast/astsa/ccode.h
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _CCODE_H
+#define _CCODE_H 1
+
+#define CC_bel '\a'
+#define CC_esc '\033'
+#define CC_vt '\v'
+
+#define CC_ASCII 0
+#define CC_NATIVE CC_ASCII
+
+#define ccmapc(c,f,t) (c)
+
+#endif
diff --git a/src/lib/libast/astsa/debug.h b/src/lib/libast/astsa/debug.h
new file mode 100644
index 0000000..7b93f4b
--- /dev/null
+++ b/src/lib/libast/astsa/debug.h
@@ -0,0 +1,29 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _DEBUG_H
+#define _DEBUG_H 1
+
+#define DEBUG_ASSERT(x)
+
+#define message(p)
+
+#endif
diff --git a/src/lib/libast/astsa/error.c b/src/lib/libast/astsa/error.c
new file mode 100644
index 0000000..84b7728
--- /dev/null
+++ b/src/lib/libast/astsa/error.c
@@ -0,0 +1,103 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * standalone mini error implementation
+ */
+
+#include <ast.h>
+#include <error.h>
+
+Error_info_t error_info;
+
+void
+errorv(const char* id, int level, va_list ap)
+{
+ char* a;
+ char* s;
+ int flags;
+
+ if (level < 0)
+ flags = 0;
+ else
+ {
+ flags = level & ~ERROR_LEVEL;
+ level &= ERROR_LEVEL;
+ }
+ a = va_arg(ap, char*);
+ if (level && ((s = error_info.id) || (s = (char*)id)))
+ {
+ if (!(flags & ERROR_USAGE))
+ sfprintf(sfstderr, "%s: ", s);
+ else if (strcmp(a, "%s"))
+ sfprintf(sfstderr, "Usage: %s ", s);
+ }
+ if (flags & ERROR_USAGE)
+ /*nop*/;
+ else if (level < 0)
+ sfprintf(sfstderr, "debug%d: ", level);
+ else if (level)
+ {
+ if (level == ERROR_WARNING)
+ {
+ sfprintf(sfstderr, "warning: ");
+ error_info.warnings++;
+ }
+ else
+ {
+ error_info.errors++;
+ if (level == ERROR_PANIC)
+ sfprintf(sfstderr, "panic: ");
+ }
+ if (error_info.line)
+ {
+ if (error_info.file && *error_info.file)
+ sfprintf(sfstderr, "\"%s\", ", error_info.file);
+ sfprintf(sfstderr, "line %d: ", error_info.line);
+ }
+ }
+ sfvprintf(sfstderr, a, ap);
+ sfprintf(sfstderr, "\n");
+ if (level >= ERROR_FATAL)
+ exit(level - ERROR_FATAL + 1);
+}
+
+void
+error(int level, ...)
+{
+ va_list ap;
+
+ va_start(ap, level);
+ errorv(NiL, level, ap);
+ va_end(ap);
+}
+
+int
+errorf(void* handle, void* discipline, int level, ...)
+{
+ va_list ap;
+
+ va_start(ap, level);
+ errorv((discipline && handle) ? *((char**)handle) : (char*)handle, level, ap);
+ va_end(ap);
+ return 0;
+}
diff --git a/src/lib/libast/astsa/error.h b/src/lib/libast/astsa/error.h
new file mode 100644
index 0000000..a95809f
--- /dev/null
+++ b/src/lib/libast/astsa/error.h
@@ -0,0 +1,66 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * standalone mini error interface
+ */
+
+#ifndef _ERROR_H
+#define _ERROR_H 1
+
+#include <option.h>
+#include <stdarg.h>
+
+typedef struct Error_info_s
+{
+ int errors;
+ int line;
+ int warnings;
+ char* catalog;
+ char* file;
+ char* id;
+} Error_info_t;
+
+#define ERROR_catalog(s) s
+
+#define ERROR_INFO 0 /* info message -- no err_id */
+#define ERROR_WARNING 1 /* warning message */
+#define ERROR_ERROR 2 /* error message -- no err_exit */
+#define ERROR_FATAL 3 /* error message with err_exit */
+#define ERROR_PANIC ERROR_LEVEL /* panic message with err_exit */
+
+#define ERROR_LEVEL 0x00ff /* level portion of status */
+#define ERROR_SYSTEM 0x0100 /* report system errno message */
+#define ERROR_USAGE 0x0800 /* usage message */
+
+#define error_info _err_info
+#define error _err_msg
+#define errorv _err_msgv
+
+extern Error_info_t error_info;
+
+#define errorx(l,x,c,m) (char*)m
+
+extern void error(int, ...);
+extern int errorf(void*, void*, int, ...);
+extern void errorv(const char*, int, va_list);
+
+#endif
diff --git a/src/lib/libast/astsa/hashkey.h b/src/lib/libast/astsa/hashkey.h
new file mode 100644
index 0000000..7f02842
--- /dev/null
+++ b/src/lib/libast/astsa/hashkey.h
@@ -0,0 +1,61 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * 1-6 char lower-case keyword -> long hash
+ * digit args passed as HASHKEYN('2')
+ */
+
+#ifndef _HASHKEY_H
+#define _HASHKEY_H 1
+
+#define HASHKEYMAX 6
+#define HASHKEYBIT 5
+#define HASHKEYOFF ('a'-1)
+#define HASHKEYPART(h,c) (((h)<<HASHKEYBIT)+HASHKEY1(c))
+
+#define HASHKEYN(n) ((n)-'0'+'z'+1)
+
+#define HASHKEY1(c1) ((c1)-HASHKEYOFF)
+#define HASHKEY2(c1,c2) HASHKEYPART(HASHKEY1(c1),c2)
+#define HASHKEY3(c1,c2,c3) HASHKEYPART(HASHKEY2(c1,c2),c3)
+#define HASHKEY4(c1,c2,c3,c4) HASHKEYPART(HASHKEY3(c1,c2,c3),c4)
+#define HASHKEY5(c1,c2,c3,c4,c5) HASHKEYPART(HASHKEY4(c1,c2,c3,c4),c5)
+#define HASHKEY6(c1,c2,c3,c4,c5,c6) HASHKEYPART(HASHKEY5(c1,c2,c3,c4,c5),c6)
+
+#define HASHNKEY1(n,c1) HASHKEY2((n)+HASHKEYOFF,c1)
+#define HASHNKEY2(n,c2,c1) HASHKEY3((n)+HASHKEYOFF,c2,c1)
+#define HASHNKEY3(n,c3,c2,c1) HASHKEY4((n)+HASHKEYOFF,c3,c2,c1)
+#define HASHNKEY4(n,c4,c3,c2,c1) HASHKEY5((n)+'a',c4,c3,c2,c1)
+#define HASHNKEY5(n,c5,c4,c3,c2,c1) HASHKEY6((n)+'a',c5,c4,c3,c2,c1)
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern long strkey(const char*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/astsa/mkast_sa b/src/lib/libast/astsa/mkast_sa
new file mode 100755
index 0000000..df448f2
--- /dev/null
+++ b/src/lib/libast/astsa/mkast_sa
@@ -0,0 +1,150 @@
+: generate ast_sa.h
+case $# in
+0) set cc ;;
+esac
+cat > _ast_.c <<'!'
+ #define _BYTESEX_H
+
+ #include <stdio.h>
+ #include <sys/types.h>
+
+ #if N == 0
+ #define _ast_int8_t long
+ #define _ast_int8_str "long"
+ #endif
+ #if N == 1
+ #define _ast_int8_t long long
+ #define _ast_int8_str "long long"
+ #endif
+ #if N == 2
+ #define _ast_int8_t __int64_t
+ #define _ast_int8_str "__int64_t"
+ #endif
+ #if N == 3
+ #define _ast_int8_t _int64_t
+ #define _ast_int8_str "_int64_t"
+ #endif
+ #if N == 4
+ #define _ast_int8_t int64_t
+ #define _ast_int8_str "int64_t"
+ #endif
+ #if N == 5
+ #define _ast_int8_t __int64
+ #define _ast_int8_str "__int64"
+ #endif
+ #if N == 6
+ #define _ast_int8_t _int64
+ #define _ast_int8_str "_int64"
+ #endif
+ #if N == 7
+ #define _ast_int8_t int64
+ #define _ast_int8_str "int64"
+ #endif
+
+ #define elementsof(x) (sizeof(x)/sizeof(x[0]))
+
+ static char i_char = 1;
+ static short i_short = 1;
+ static int i_int = 1;
+ static long i_long = 1;
+ #ifdef _ast_int8_t
+ static _ast_int8_t i_long_long = 1;
+ #endif
+
+ static struct
+ {
+ char* name;
+ int size;
+ char* swap;
+ } int_type[] =
+ {
+ "char", sizeof(char), (char*)&i_char,
+ "short", sizeof(short), (char*)&i_short,
+ "int", sizeof(int), (char*)&i_int,
+ "long", sizeof(long), (char*)&i_long,
+ #ifdef _ast_int8_t
+ _ast_int8_str, sizeof(_ast_int8_t), (char*)&i_long_long,
+ #endif
+ };
+
+ static struct
+ {
+ char* name;
+ int size;
+ } flt_type[] =
+ {
+ "float", sizeof(float),
+ "double", sizeof(double),
+ #ifdef _typ_long_double
+ "long double", sizeof(long double),
+ #endif
+ };
+
+ static int int_size[] = { 1, 2, 4, 8 };
+
+ main()
+ {
+ register int t;
+ register int s;
+ register int m = 1;
+ register int b = 1;
+ register int w = 0;
+
+ #ifdef _ast_int8_t
+ if (int_type[elementsof(int_type)-1].size <= 4)
+ return 1;
+ #endif
+ for (s = 0; s < elementsof(int_size); s++)
+ {
+ for (t = 0; t < elementsof(int_type) && int_type[t].size < int_size[s]; t++);
+ if (t < elementsof(int_type))
+ {
+ m = int_size[s];
+ printf("#define _ast_int%d_t %s\n", m, int_type[t].name);
+ if (m > 1)
+ {
+ if (*int_type[t].swap)
+ w |= b;
+ b <<= 1;
+ }
+ }
+ }
+ printf("#define _ast_intmax_t _ast_int%d_t\n", m);
+ if (m == sizeof(long))
+ printf("#define _ast_intmax_long 1\n");
+ printf("#define _ast_intswap %d\n", w);
+ printf("\n");
+ for (t = 0; t < elementsof(flt_type); t++)
+ {
+ while (t < elementsof(flt_type) && flt_type[t].size == flt_type[t + 1].size)
+ t++;
+ m = flt_type[t].size;
+ printf("#define _ast_flt%d_t %s\n", flt_type[t].size, flt_type[t].name);
+ }
+ printf("#define _ast_fltmax_t _ast_flt%d_t\n", m);
+ if (m == sizeof(double))
+ printf("#define _ast_fltmax_double 1\n");
+ return 0;
+ }
+!
+echo "#ifndef _AST_SA_H"
+echo "#define _AST_SA_H 1"
+echo
+for i in '' -DN=0 -DN=1 -DN=2 -DN=3 -DN=4 -DN=5 -DN=6 -DN=7 -DN=8
+do "$@" $i -o _ast_.exe _ast_.c 2> /dev/null &&
+ ./_ast_.exe &&
+ break
+done
+echo '#include <stdint.h>' > _ast_.c
+if "$@" -E _ast_.c > /dev/null 2>&1
+then echo "#define _hdr_stdint 1"
+fi
+echo '#include <unistd.h>' > _ast_.c
+if "$@" -E _ast_.c > /dev/null 2>&1
+then echo "#define _hdr_unistd 1"
+fi
+rm -f _ast_.c _ast_.exe
+echo "#define __DEFINE__(T,obj,val) T obj = val"
+echo "#define __EXTERN__(T,obj) extern T obj"
+echo
+echo "#endif"
diff --git a/src/lib/libast/astsa/option.h b/src/lib/libast/astsa/option.h
new file mode 100644
index 0000000..aa66920
--- /dev/null
+++ b/src/lib/libast/astsa/option.h
@@ -0,0 +1,106 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * command line option parse interface
+ */
+
+#ifndef _OPTION_H
+#define _OPTION_H 1
+
+#include <ast.h>
+
+#define OPT_VERSION 20000401L
+
+#define opt_info _opt_info_
+
+#define OPT_USER (1L<<16) /* first user flag bit */
+
+struct Opt_s;
+struct Optdisc_s;
+
+typedef int (*Optinfo_f)(struct Opt_s*, Sfio_t*, const char*, struct Optdisc_s*);
+
+typedef struct Optdisc_s
+{
+ unsigned long version; /* OPT_VERSION */
+ unsigned long flags; /* OPT_* flags */
+ char* catalog; /* error catalog id */
+ Optinfo_f infof; /* runtime info function */
+} Optdisc_t;
+
+/* NOTE: Opt_t member order fixed by a previous binary release */
+
+#ifndef _OPT_PRIVATE_
+#define _OPT_PRIVATE_ void* _opt_private;
+#endif
+
+typedef struct Opt_s
+{
+ int again; /* see optjoin() */
+ char* arg; /* {:,#} string argument */
+ char** argv; /* most recent argv */
+ int index; /* argv index */
+ char* msg; /* error/usage message buffer */
+ long num; /* # numeric argument */
+ int offset; /* char offset in argv[index] */
+ char option[8]; /* current flag {-,+} + option */
+ char name[64]; /* current long name or flag */
+ Optdisc_t* disc; /* user discipline */
+ intmax_t number; /* # numeric argument */
+ unsigned char assignment; /* option arg assigment op */
+ unsigned char pads[sizeof(void*)-1];
+ _OPT_PRIVATE_
+} Opt_t;
+
+#define optinit(d,f) (memset(d,0,sizeof(*(d))),(d)->version=OPT_VERSION,(d)->infof=(f),opt_info.disc=(d))
+
+#if _BLD_ast && defined(__EXPORT__)
+#define __PUBLIC_DATA__ __EXPORT__
+#else
+#if !_BLD_ast && defined(__IMPORT__)
+#define __PUBLIC_DATA__ __IMPORT__
+#else
+#define __PUBLIC_DATA__
+#endif
+#endif
+
+extern __PUBLIC_DATA__ Opt_t opt_info;
+
+#undef __PUBLIC_DATA__
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int optget(char**, const char*);
+extern int optjoin(char**, ...);
+extern char* opthelp(const char*, const char*);
+extern char* optusage(const char*);
+extern int optstr(const char*, const char*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/astsa/optlib.h b/src/lib/libast/astsa/optlib.h
new file mode 100644
index 0000000..8e09734
--- /dev/null
+++ b/src/lib/libast/astsa/optlib.h
@@ -0,0 +1,105 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * command line option parser and usage formatter private definitions
+ */
+
+#ifndef _OPTLIB_H
+#define _OPTLIB_H 1
+
+#include <ast.h>
+#include <cdt.h>
+
+#define OPT_cache 0x01
+#define OPT_functions 0x02
+#define OPT_ignore 0x04
+#define OPT_long 0x08
+#define OPT_old 0x10
+#define OPT_plus 0x20
+#define OPT_proprietary 0x40
+
+#define OPT_cache_flag 0x01
+#define OPT_cache_invert 0x02
+#define OPT_cache_numeric 0x04
+#define OPT_cache_optional 0x08
+#define OPT_cache_string 0x10
+
+#define OPT_CACHE 128
+#define OPT_FLAGS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+
+struct Optdisc_s;
+
+typedef struct Optpass_s
+{
+ char* opts;
+ char* oopts;
+ char* catalog;
+ unsigned char version;
+ unsigned char prefix;
+ unsigned char flags;
+ unsigned char section;
+} Optpass_t;
+
+typedef struct Optcache_s
+{
+ struct Optcache_s* next;
+ Optpass_t pass;
+ int caching;
+ unsigned char flags[sizeof(OPT_FLAGS)];
+} Optcache_t;
+
+typedef struct Optstate_s
+{
+ Sfio_t* mp; /* opt_info.msg string stream */
+ Sfio_t* vp; /* translation string stream */
+ Sfio_t* xp; /* translation string stream */
+ Sfio_t* cp; /* compatibility string stream */
+ Optpass_t pass[8]; /* optjoin() list */
+ char* argv[2]; /* initial argv copy */
+ char* strv[3]; /* optstr() argv */
+ char* str; /* optstr() string */
+ Sfio_t* strp; /* optstr() stream */
+ int force; /* force this style */
+ int pindex; /* prev index for backup */
+ int poffset; /* prev offset for backup */
+ int npass; /* # optjoin() passes */
+ int join; /* optjoin() pass # */
+ int plus; /* + ok */
+ int style; /* default opthelp() style */
+ int width; /* format line width */
+ int flags; /* display flags */
+ int emphasis; /* ansi term emphasis ok */
+ Dtdisc_t msgdisc; /* msgdict discipline */
+ Dt_t* msgdict; /* default ast.id catalog msgs */
+ Optcache_t* cache; /* OPT_cache cache */
+} Optstate_t;
+
+#define _OPT_PRIVATE_ \
+ char pad[2*sizeof(void*)]; \
+ Optstate_t* state;
+
+#include <error.h>
+
+#endif
diff --git a/src/lib/libast/astsa/sfstr.c b/src/lib/libast/astsa/sfstr.c
new file mode 100644
index 0000000..7fc0be3
--- /dev/null
+++ b/src/lib/libast/astsa/sfstr.c
@@ -0,0 +1,246 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include <ast.h>
+#include <stdarg.h>
+
+#define STR (8*1024)
+
+#define VALID(p,f) ((p=(Sfstr_t*)f)>=&strs[0]&&p<&strs[elementsof(strs)])
+
+static Sfstr_t strs[64];
+
+static int
+extend(Sfstr_t* p, int n)
+{
+ int o;
+
+ if (n < STR)
+ n = STR;
+ n += p->end - p->beg;
+ o = p->nxt - p->beg;
+ if (!(p->beg = realloc(p->beg, n)))
+ return -1;
+ p->nxt = p->beg + o;
+ p->end = p->beg + n;
+ return 0;
+}
+
+int
+sfclose(Sfio_t* f)
+{
+ Sfstr_t* p;
+ int r;
+
+ if (VALID(p, f))
+ {
+ p->nxt = 0;
+ r = 0;
+ }
+ else
+ r = fclose(f);
+ return r;
+}
+
+int
+sfprintf(Sfio_t* f, const char* fmt, ...)
+{
+ Sfstr_t* p;
+ char* s;
+ va_list ap;
+ int r;
+
+ static char buf[STR];
+
+ va_start(ap, fmt);
+ if (!VALID(p, f))
+ r = vfprintf(f, fmt, ap);
+ else if ((r = vsnprintf(buf, sizeof(buf), fmt, ap)) > 0)
+ r = sfwrite(f, buf, r);
+ va_end(ap);
+ return r;
+}
+
+char*
+sfprints(const char* fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ static char buf[STR];
+
+ va_start(ap, fmt);
+ r = vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ return r > 0 ? buf : (char*)0;
+}
+
+int
+sfputc(Sfio_t* f, int c)
+{
+ Sfstr_t* p;
+ int r;
+
+ if (VALID(p, f))
+ {
+ if (p->nxt >= p->end && extend(p, 1))
+ return -1;
+ *p->nxt++ = c;
+ r = 1;
+ }
+ else
+ r = fputc(c, f);
+ return r;
+}
+
+int
+sfputr(Sfio_t* f, const char* buf, int sep)
+{
+ Sfstr_t* p;
+ int r;
+ int n;
+
+ n = strlen(buf);
+ if (VALID(p, f))
+ {
+ r = n + (sep >= 0);
+ if (r > (p->end - p->nxt) && extend(p, r))
+ return -1;
+ memcpy(p->nxt, buf, n);
+ p->nxt += n;
+ if (sep >= 0)
+ *p->nxt++ = sep;
+ }
+ else
+ {
+ r = fwrite(buf, 1, n, f);
+ if (sep >= 0 && fputc(sep, f) != EOF)
+ r++;
+ }
+ return r;
+}
+
+char*
+sfstrbase(Sfio_t* f)
+{
+ Sfstr_t* p;
+
+ if (VALID(p, f))
+ return p->beg;
+ return 0;
+}
+
+Sfio_t*
+sfstropen(void)
+{
+ Sfstr_t* p;
+
+ for (p = &strs[0]; p < &strs[elementsof(strs)]; p++)
+ if (!p->nxt)
+ {
+ if (!p->beg)
+ {
+ if (!(p->beg = malloc(STR)))
+ break;
+ p->end = p->beg + STR;
+ }
+ p->nxt = p->beg;
+ return (Sfio_t*)p;
+ }
+ return 0;
+}
+
+#define _sf_strseek(f,p,m) \
+ ( (m) == SEEK_SET ? \
+ (((p) < 0 || (p) > ((f)->end - (f)->beg)) ? (char*)0 : \
+ (char*)((f)->nxt = (f)->beg+(p)) ) \
+ : (m) == SEEK_CUR ? \
+ ((f)->nxt += (p), \
+ (((f)->nxt < (f)->beg || (f)->nxt > (f)->end) ? \
+ ((f)->nxt -= (p), (char*)0) : (char*)(f)->nxt ) ) \
+ : (m) == SEEK_END ? \
+ ( ((p) > 0 || (((f)->end - (f)->beg) + (p)) < 0) ? (char*)0 : \
+ (char*)((f)->nxt = (f)->end+(p)) ) \
+ : (char*)0 \
+ )
+
+char*
+sfstrseek(Sfio_t* f, int n, int w)
+{
+ Sfstr_t* p;
+
+ if (VALID(p, f))
+ return _sf_strseek(p, n, w);
+ return 0;
+}
+
+char*
+sfstrset(Sfio_t* f, int n)
+{
+ Sfstr_t* p;
+
+ if (VALID(p, f) && n >= 0 && n < (p->nxt - p->beg))
+ return p->nxt = p->beg + n;
+ return 0;
+}
+
+int
+sfstrtell(Sfio_t* f)
+{
+ Sfstr_t* p;
+ int r;
+
+ if (VALID(p, f) && p->nxt)
+ r = p->nxt - p->beg;
+ else
+ r = -1;
+ return r;
+}
+
+char*
+sfstruse(Sfio_t* f)
+{
+ Sfstr_t* p;
+
+ if (VALID(p, f) && (p->nxt < p->end || !extend(p, 1)))
+ {
+ *p->nxt = 0;
+ return p->nxt = p->beg;
+ }
+ return 0;
+}
+
+int
+sfwrite(Sfio_t* f, void* buf, int n)
+{
+ Sfstr_t* p;
+
+ if (VALID(p, f))
+ {
+ if (n > (p->end - p->nxt) && extend(p, n))
+ return -1;
+ memcpy(p->nxt, buf, n);
+ p->nxt += n;
+ }
+ else
+ n = fwrite(buf, 1, n, f);
+ return n;
+}
diff --git a/src/lib/libast/astsa/sfstr.h b/src/lib/libast/astsa/sfstr.h
new file mode 100644
index 0000000..4fe21f5
--- /dev/null
+++ b/src/lib/libast/astsa/sfstr.h
@@ -0,0 +1,60 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _SFSTR_H
+#define _SFSTR_H 1
+
+#include <ast.h>
+
+typedef struct Sfstr_s
+{
+ char* beg;
+ char* nxt;
+ char* end;
+} Sfstr_t;
+
+#undef sfclose
+#undef sfprintf
+#undef sfprints
+#undef sfputc
+#undef sfputr
+#undef sfstrbase
+#undef sfstropen
+#undef sfstrseek
+#undef sfstrset
+#undef sfstrtell
+#undef sfstruse
+#undef sfwrite
+
+extern int sfclose(Sfio_t*);
+extern int sfprintf(Sfio_t*, const char*, ...);
+extern char* sfprints(const char*, ...);
+extern int sfputc(Sfio_t*, int);
+extern int sfputr(Sfio_t*, const char*, int);
+extern char* sfstrbase(Sfio_t*);
+extern Sfio_t* sfstropen(void);
+extern char* sfstrseek(Sfio_t*, int, int);
+extern char* sfstrset(Sfio_t*, int);
+extern int sfstrtell(Sfio_t*);
+extern char* sfstruse(Sfio_t*);
+extern int sfwrite(Sfio_t*, void*, int);
+
+#endif
diff --git a/src/lib/libast/astsa/strdup.c b/src/lib/libast/astsa/strdup.c
new file mode 100644
index 0000000..a4de874
--- /dev/null
+++ b/src/lib/libast/astsa/strdup.c
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+/*
+ * return a copy of s using malloc
+ */
+
+char*
+strdup(register const char* s)
+{
+ register char* t;
+ register int n;
+
+ return (s && (t = newof(0, char, n = strlen(s) + 1, 0))) ? (char*)memcpy(t, s, n) : (char*)0;
+}
diff --git a/src/lib/libast/astsa/strmatch.c b/src/lib/libast/astsa/strmatch.c
new file mode 100644
index 0000000..f6a9ff3
--- /dev/null
+++ b/src/lib/libast/astsa/strmatch.c
@@ -0,0 +1,597 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * D. G. Korn
+ * G. S. Fowler
+ * AT&T Research
+ *
+ * match shell file patterns -- derived from Bourne and Korn shell gmatch()
+ *
+ * sh pattern egrep RE description
+ * ---------- -------- -----------
+ * * .* 0 or more chars
+ * ? . any single char
+ * [.] [.] char class
+ * [!.] [^.] negated char class
+ * [[:.:]] [[:.:]] ctype class
+ * [[=.=]] [[=.=]] equivalence class
+ * [[...]] [[...]] collation element
+ * *(.) (.)* 0 or more of
+ * +(.) (.)+ 1 or more of
+ * ?(.) (.)? 0 or 1 of
+ * (.) (.) 1 of
+ * @(.) (.) 1 of
+ * a|b a|b a or b
+ * \# () subgroup back reference [1-9]
+ * a&b a and b
+ * !(.) none of
+ *
+ * \ used to escape metacharacters
+ *
+ * *, ?, (, |, &, ), [, \ must be \'d outside of [...]
+ * only ] must be \'d inside [...]
+ *
+ * BUG: unbalanced ) terminates top level pattern
+ */
+
+#include <ast.h>
+#include <ctype.h>
+#include <hashkey.h>
+
+#ifndef isblank
+#define isblank(x) ((x)==' '||(x)=='\t')
+#endif
+
+#ifndef isgraph
+#define isgraph(x) (isprint(x)&&!isblank(x))
+#endif
+
+#define MAXGROUP 10
+
+typedef struct
+{
+ char* beg[MAXGROUP];
+ char* end[MAXGROUP];
+ char* next_s;
+ short groups;
+} Group_t;
+
+typedef struct
+{
+ Group_t current;
+ Group_t best;
+ char* last_s;
+ char* next_p;
+} Match_t;
+
+#define mbgetchar(p) (*p++)
+
+#ifndef isxdigit
+#define isxdigit(c) ((c)>='0'&&(c)<='9'||(c)>='a'&&(c)<='f'||(c)>='A'&&(c)<='F')
+#endif
+
+#define getsource(s,e) (((s)>=(e))?0:mbgetchar(s))
+
+#define COLL_MAX 3
+
+/*
+ * gobble chars up to <sub> or ) keeping track of (...) and [...]
+ * sub must be one of { '|', '&', 0 }
+ * 0 returned if s runs out
+ */
+
+static char*
+gobble(Match_t* mp, register char* s, register int sub, int* g, int clear)
+{
+ register int p = 0;
+ register char* b = 0;
+ int c = 0;
+ int n;
+
+ for (;;)
+ switch (mbgetchar(s))
+ {
+ case '\\':
+ if (mbgetchar(s))
+ break;
+ /*FALLTHROUGH*/
+ case 0:
+ return 0;
+ case '[':
+ if (!b)
+ {
+ if (*s == '!')
+ mbgetchar(s);
+ b = s;
+ }
+ else if (*s == '.' || *s == '=' || *s == ':')
+ c = *s;
+ break;
+ case ']':
+ if (b)
+ {
+ if (*(s - 2) == c)
+ c = 0;
+ else if (b != (s - 1))
+ b = 0;
+ }
+ break;
+ case '(':
+ if (!b)
+ {
+ p++;
+ n = (*g)++;
+ if (clear)
+ {
+ if (!sub)
+ n++;
+ if (n < MAXGROUP)
+ mp->current.beg[n] = mp->current.end[n] = 0;
+ }
+ }
+ break;
+ case ')':
+ if (!b && p-- <= 0)
+ return sub ? 0 : s;
+ break;
+ case '|':
+ if (!b && !p && sub == '|')
+ return s;
+ break;
+ }
+}
+
+static int grpmatch(Match_t*, int, char*, register char*, char*, int);
+
+/*
+ * match a single pattern
+ * e is the end (0) of the substring in s
+ * r marks the start of a repeated subgroup pattern
+ */
+
+static int
+onematch(Match_t* mp, int g, char* s, char* p, char* e, char* r, int flags)
+{
+ register int pc;
+ register int sc;
+ register int n;
+ register int icase;
+ char* olds;
+ char* oldp;
+
+ icase = flags & STR_ICASE;
+ do
+ {
+ olds = s;
+ sc = getsource(s, e);
+ if (icase && isupper(sc))
+ sc = tolower(sc);
+ oldp = p;
+ switch (pc = mbgetchar(p))
+ {
+ case '(':
+ case '*':
+ case '?':
+ case '+':
+ case '@':
+ case '!':
+ if (pc == '(' || *p == '(')
+ {
+ char* subp;
+ int oldg;
+
+ s = olds;
+ subp = p + (pc != '(');
+ oldg = g;
+ n = ++g;
+ if (g < MAXGROUP && (!r || g > mp->current.groups))
+ mp->current.beg[g] = mp->current.end[g] = 0;
+ if (!(p = gobble(mp, subp, 0, &g, !r)))
+ return 0;
+ if (pc == '*' || pc == '?' || pc == '+' && oldp == r)
+ {
+ if (onematch(mp, g, s, p, e, NiL, flags))
+ return 1;
+ if (!sc || !getsource(s, e))
+ {
+ mp->current.groups = oldg;
+ return 0;
+ }
+ }
+ if (pc == '*' || pc == '+')
+ {
+ p = oldp;
+ sc = n - 1;
+ }
+ else
+ sc = g;
+ pc = (pc != '!');
+ do
+ {
+ if (grpmatch(mp, n, olds, subp, s, flags) == pc)
+ {
+ if (n < MAXGROUP)
+ {
+ if (!mp->current.beg[n] || mp->current.beg[n] > olds)
+ mp->current.beg[n] = olds;
+ if (s > mp->current.end[n])
+ mp->current.end[n] = s;
+ }
+ if (onematch(mp, sc, s, p, e, oldp, flags))
+ {
+ if (p == oldp && n < MAXGROUP)
+ {
+ if (!mp->current.beg[n] || mp->current.beg[n] > olds)
+ mp->current.beg[n] = olds;
+ if (s > mp->current.end[n])
+ mp->current.end[n] = s;
+ }
+ return 1;
+ }
+ }
+ } while (s < e && mbgetchar(s));
+ mp->current.groups = oldg;
+ return 0;
+ }
+ else if (pc == '*')
+ {
+ /*
+ * several stars are the same as one
+ */
+
+ while (*p == '*' && *(p + 1) != '(')
+ p++;
+ oldp = p;
+ switch (pc = mbgetchar(p))
+ {
+ case '@':
+ case '!':
+ case '+':
+ n = *p == '(';
+ break;
+ case '(':
+ case '[':
+ case '?':
+ case '*':
+ n = 1;
+ break;
+ case 0:
+ case '|':
+ case '&':
+ case ')':
+ mp->current.next_s = (flags & STR_MAXIMAL) ? e : olds;
+ mp->next_p = oldp;
+ mp->current.groups = g;
+ if (!pc && (!mp->best.next_s || (flags & STR_MAXIMAL) && mp->current.next_s > mp->best.next_s || !(flags & STR_MAXIMAL) && mp->current.next_s < mp->best.next_s))
+ mp->best = mp->current;
+ return 1;
+ case '\\':
+ if (!(pc = mbgetchar(p)))
+ return 0;
+ if (pc >= '0' && pc <= '9')
+ {
+ n = pc - '0';
+ if (n <= g && mp->current.beg[n])
+ pc = *mp->current.beg[n];
+ }
+ /*FALLTHROUGH*/
+ default:
+ if (icase && isupper(pc))
+ pc = tolower(pc);
+ n = 0;
+ break;
+ }
+ p = oldp;
+ for (;;)
+ {
+ if ((n || pc == sc) && onematch(mp, g, olds, p, e, NiL, flags))
+ return 1;
+ if (!sc)
+ return 0;
+ olds = s;
+ sc = getsource(s, e);
+ if ((flags & STR_ICASE) && isupper(sc))
+ sc = tolower(sc);
+ }
+ }
+ else if (pc != '?' && pc != sc)
+ return 0;
+ break;
+ case 0:
+ if (!(flags & STR_MAXIMAL))
+ sc = 0;
+ /*FALLTHROUGH*/
+ case '|':
+ case '&':
+ case ')':
+ if (!sc)
+ {
+ mp->current.next_s = olds;
+ mp->next_p = oldp;
+ mp->current.groups = g;
+ }
+ if (!pc && (!mp->best.next_s || (flags & STR_MAXIMAL) && olds > mp->best.next_s || !(flags & STR_MAXIMAL) && olds < mp->best.next_s))
+ {
+ mp->best = mp->current;
+ mp->best.next_s = olds;
+ mp->best.groups = g;
+ }
+ return !sc;
+ case '[':
+ {
+ /*UNDENT...*/
+
+ int invert;
+ int x;
+ int ok = 0;
+ char* range;
+
+ if (!sc)
+ return 0;
+ range = 0;
+ n = 0;
+ if (invert = *p == '!')
+ p++;
+ for (;;)
+ {
+ oldp = p;
+ if (!(pc = mbgetchar(p)))
+ return 0;
+ else if (pc == '[' && (*p == ':' || *p == '=' || *p == '.'))
+ {
+ x = 0;
+ n = mbgetchar(p);
+ oldp = p;
+ for (;;)
+ {
+ if (!(pc = mbgetchar(p)))
+ return 0;
+ if (pc == n && *p == ']')
+ break;
+ x++;
+ }
+ mbgetchar(p);
+ if (ok)
+ /*NOP*/;
+ else if (n == ':')
+ {
+ switch (HASHNKEY5(x, oldp[0], oldp[1], oldp[2], oldp[3], oldp[4]))
+ {
+ case HASHNKEY5(5,'a','l','n','u','m'):
+ if (isalnum(sc))
+ ok = 1;
+ break;
+ case HASHNKEY5(5,'a','l','p','h','a'):
+ if (isalpha(sc))
+ ok = 1;
+ break;
+ case HASHNKEY5(5,'b','l','a','n','k'):
+ if (isblank(sc))
+ ok = 1;
+ break;
+ case HASHNKEY5(5,'c','n','t','r','l'):
+ if (iscntrl(sc))
+ ok = 1;
+ break;
+ case HASHNKEY5(5,'d','i','g','i','t'):
+ if (isdigit(sc))
+ ok = 1;
+ break;
+ case HASHNKEY5(5,'g','r','a','p','h'):
+ if (isgraph(sc))
+ ok = 1;
+ break;
+ case HASHNKEY5(5,'l','o','w','e','r'):
+ if (islower(sc))
+ ok = 1;
+ break;
+ case HASHNKEY5(5,'p','r','i','n','t'):
+ if (isprint(sc))
+ ok = 1;
+ break;
+ case HASHNKEY5(5,'p','u','n','c','t'):
+ if (ispunct(sc))
+ ok = 1;
+ break;
+ case HASHNKEY5(5,'s','p','a','c','e'):
+ if (isspace(sc))
+ ok = 1;
+ break;
+ case HASHNKEY5(5,'u','p','p','e','r'):
+ if (icase ? islower(sc) : isupper(sc))
+ ok = 1;
+ break;
+ case HASHNKEY5(6,'x','d','i','g','i'):
+ if (oldp[5] == 't' && isxdigit(sc))
+ ok = 1;
+ break;
+ }
+ }
+ else if (range)
+ goto getrange;
+ else if (*p == '-' && *(p + 1) != ']')
+ {
+ mbgetchar(p);
+ range = oldp;
+ }
+ else if (isalpha(*oldp) && isalpha(*olds) && tolower(*oldp) == tolower(*olds) || sc == mbgetchar(oldp))
+ ok = 1;
+ n = 1;
+ }
+ else if (pc == ']' && n)
+ {
+ if (ok != invert)
+ break;
+ return 0;
+ }
+ else if (pc == '\\' && (oldp = p, !(pc = mbgetchar(p))))
+ return 0;
+ else if (ok)
+ /*NOP*/;
+ else if (range)
+ {
+ getrange:
+ if (icase && isupper(pc))
+ pc = tolower(pc);
+ x = mbgetchar(range);
+ if (icase && isupper(x))
+ x = tolower(x);
+ if (sc == x || sc == pc || sc > x && sc < pc)
+ ok = 1;
+ if (*p == '-' && *(p + 1) != ']')
+ {
+ mbgetchar(p);
+ range = oldp;
+ }
+ else
+ range = 0;
+ n = 1;
+ }
+ else if (*p == '-' && *(p + 1) != ']')
+ {
+ mbgetchar(p);
+ range = oldp;
+ n = 1;
+ }
+ else
+ {
+ if (icase && isupper(pc))
+ pc = tolower(pc);
+ if (sc == pc)
+ ok = 1;
+ n = pc;
+ }
+ }
+
+ /*...INDENT*/
+ }
+ break;
+ case '\\':
+ if (!(pc = mbgetchar(p)))
+ return 0;
+ if (pc >= '0' && pc <= '9')
+ {
+ n = pc - '0';
+ if (n <= g && (oldp = mp->current.beg[n]))
+ {
+ while (oldp < mp->current.end[n])
+ if (!*olds || *olds++ != *oldp++)
+ return 0;
+ s = olds;
+ break;
+ }
+ }
+ /*FALLTHROUGH*/
+ default:
+ if (icase && isupper(pc))
+ pc = tolower(pc);
+ if (pc != sc)
+ return 0;
+ break;
+ }
+ } while (sc);
+ return 0;
+}
+
+/*
+ * match any pattern in a group
+ * | and & subgroups are parsed here
+ */
+
+static int
+grpmatch(Match_t* mp, int g, char* s, register char* p, char* e, int flags)
+{
+ register char* a;
+
+ do
+ {
+ for (a = p; onematch(mp, g, s, a, e, NiL, flags); a++)
+ if (*(a = mp->next_p) != '&')
+ return 1;
+ } while (p = gobble(mp, p, '|', &g, 1));
+ return 0;
+}
+
+/*
+ * subgroup match
+ * 0 returned if no match
+ * otherwise number of subgroups matched returned
+ * match group begin offsets are even elements of sub
+ * match group end offsets are odd elements of sub
+ * the matched string is from s+sub[0] up to but not
+ * including s+sub[1]
+ */
+
+int
+strgrpmatch(const char* b, const char* p, int* sub, int n, int flags)
+{
+ register int i;
+ register char* s;
+ char* e;
+ Match_t match;
+
+ s = (char*)b;
+ match.last_s = e = s + strlen(s);
+ for (;;)
+ {
+ match.best.next_s = 0;
+ match.current.groups = 0;
+ if ((i = grpmatch(&match, 0, s, (char*)p, e, flags)) || match.best.next_s)
+ {
+ if (!i)
+ match.current = match.best;
+ match.current.groups++;
+ match.current.end[0] = match.current.next_s;
+ break;
+ }
+ if ((flags & STR_LEFT) || s >= e)
+ return 0;
+ s++;
+ }
+ if ((flags & STR_RIGHT) && match.current.next_s != e)
+ return 0;
+ if (!sub)
+ return 1;
+ match.current.beg[0] = s;
+ s = (char*)b;
+ if (n > match.current.groups)
+ n = match.current.groups;
+ for (i = 0; i < n; i++)
+ {
+ sub[i * 2] = match.current.end[i] ? match.current.beg[i] - s : 0;
+ sub[i * 2 + 1] = match.current.end[i] ? match.current.end[i] - s : 0;
+ }
+ return n;
+}
+
+/*
+ * compare the string s with the shell pattern p
+ * returns 1 for match 0 otherwise
+ */
+
+int
+strmatch(const char* s, const char* p)
+{
+ return strgrpmatch(s, p, NiL, 0, STR_MAXIMAL|STR_LEFT|STR_RIGHT);
+}
diff --git a/src/lib/libast/astsa/times.h b/src/lib/libast/astsa/times.h
new file mode 100644
index 0000000..7b916f7
--- /dev/null
+++ b/src/lib/libast/astsa/times.h
@@ -0,0 +1,27 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _TIMES_H
+#define _TIMES_H 1
+
+#include <sys/times.h>
+
+#endif
diff --git a/src/lib/libast/astsa/vmalloc.c b/src/lib/libast/astsa/vmalloc.c
new file mode 100644
index 0000000..3195b13
--- /dev/null
+++ b/src/lib/libast/astsa/vmalloc.c
@@ -0,0 +1,102 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * standalone mini vmalloc implementation
+ * no resize, no free, no disciplines, no methods
+ */
+
+#include <ast.h>
+#include <vmalloc.h>
+
+Vmalloc_t* Vmregion;
+
+Vmalloc_t*
+_vm_open(void)
+{
+ Vmalloc_t* vp;
+
+ if (vp = newof(0, Vmalloc_t, 1, 0))
+ {
+ vp->current = &vp->base;
+ vp->data = vp->current->data;
+ vp->size = sizeof(vp->current->data);
+ }
+ return vp;
+}
+
+int
+_vm_close(register Vmalloc_t* vp)
+{
+ register Vmchunk_t* cp;
+ register Vmchunk_t* np;
+
+ if (!vp)
+ return -1;
+ np = vp->base.next;
+ while (cp = np)
+ {
+ np = cp->next;
+ free(cp);
+ }
+ free(vp);
+ return 0;
+}
+
+void*
+_vm_resize(register Vmalloc_t* vp, void* o, unsigned long size)
+{
+ char* p;
+ unsigned long n;
+ unsigned long z;
+
+ z = vp->last;
+ vp->last = size;
+ if (o && size < z)
+ return o;
+ if ((o ? (size - z) : size) > vp->size)
+ {
+ n = (size > sizeof(vp->current->data)) ? (size - sizeof(vp->current->data)) : 0;
+ if (!(vp->current->next = newof(0, Vmchunk_t, 1, n)))
+ return 0;
+ vp->current = vp->current->next;
+ vp->data = vp->current->data;
+ vp->size = n ? 0 : sizeof(vp->current->data);
+ if (o)
+ {
+ memcpy(vp->data, o, z);
+ o = (void*)vp->data;
+ }
+ }
+ else if (o)
+ size -= z;
+ p = vp->data;
+ size = roundof(size, VM_ALIGN);
+ if (size >= vp->size)
+ vp->size = 0;
+ else
+ {
+ vp->size -= size;
+ vp->data += size;
+ }
+ return p;
+}
diff --git a/src/lib/libast/astsa/vmalloc.h b/src/lib/libast/astsa/vmalloc.h
new file mode 100644
index 0000000..e3d2e5b
--- /dev/null
+++ b/src/lib/libast/astsa/vmalloc.h
@@ -0,0 +1,61 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * standalone mini vmalloc interface
+ */
+
+#ifndef _VMALLOC_H
+#define _VMALLOC_H 1
+
+#define vmalloc(v,n) _vm_resize(v,(void*)0,n)
+#define vmalign(v,n,a) _vm_resize(v,(void*)0,n)
+#define vmclose(v) _vm_close(v)
+#define vmfree(v,p)
+#define vmnewof(v,o,t,n,x) (t*)_vm_resize(v,(void*)o,sizeof(t)*(n)+(x))
+#define vmopen(a,b,c) _vm_open()
+
+#define VM_CHUNK (32*1024)
+#define VM_ALIGN 16
+
+typedef struct Vmchunk_s
+{
+ struct Vmchunk_s* next;
+ char align[VM_ALIGN - sizeof(struct Vmchunk_s*)];
+ char data[VM_CHUNK - VM_ALIGN];
+} Vmchunk_t;
+
+typedef struct Vmalloc_s
+{
+ Vmchunk_t base;
+ Vmchunk_t* current;
+ char* data;
+ long size;
+ long last;
+} Vmalloc_t;
+
+extern Vmalloc_t* Vmregion;
+
+extern int _vm_close(Vmalloc_t*);
+extern Vmalloc_t* _vm_open(void);
+extern void* _vm_resize(Vmalloc_t*, void*, unsigned long);
+
+#endif
diff --git a/src/lib/libast/cdt/cdtlib.h b/src/lib/libast/cdt/cdtlib.h
new file mode 100644
index 0000000..1972dd2
--- /dev/null
+++ b/src/lib/libast/cdt/cdtlib.h
@@ -0,0 +1,183 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _CDTLIB_H
+#define _CDTLIB_H 1
+
+/* cdt library/method implementation header
+** this header is exported to the method libraries
+** Written by Kiem-Phong Vo (5/25/96)
+*/
+
+#if _PACKAGE_ast
+#include <ast.h>
+#if !_BLD_cdt
+#include <dlldefs.h>
+#endif
+#endif
+
+#include <cdt.h>
+#include <unistd.h>
+#include <aso.h>
+
+#include "debug.h"
+
+/* short-hand notations */
+#define NIL(t) ((t)0)
+#define reg register
+
+/* min #bits for a hash table. (1<<this) is table size */
+#define DT_HTABLE 10
+
+/* convenient types */
+#if !defined(uint)
+#define uint unsigned int
+#endif
+#if !defined(uchar)
+#define uchar unsigned char
+#endif
+
+/* This struct holds private method data created on DT_OPEN */
+struct _dtdata_s
+{ unsigned int lock; /* general dictionary lock */
+ Dtuser_t user; /* application's data */
+ unsigned int type; /* method type, control flags */
+ ssize_t size; /* number of objects */
+ Dt_t dict; /* when DT_INDATA is requested */
+};
+
+/* this structure holds the plugin information */
+typedef struct _dtlib_s
+{
+ char* name; /* short name */
+ char* description; /* short description */
+ char* release; /* release info */
+ char* prefix; /* name prefix */
+ Dtmethod_t** methods; /* method list */
+} Dtlib_t;
+
+#if _BLD_cdt
+
+#if defined(__STDC__)
+#define CDTLIB(m) __DEFINE__(Dtmethod_t*,m,&_##m);
+#else
+#define CDTLIB(m) __DEFINE__(Dtmethod_t*,m,&_/**/m);
+#endif
+
+#else
+
+#if defined(__STDC__)
+#define CDTLIB(m) \
+ void* cdt_lib(const char* name, Dtdisc_t* disc, const char* type) \
+ { \
+ int i; \
+ int n; \
+ if (!type) \
+ return &cdt_lib_##m; \
+ n = strlen(cdt_lib_##m.prefix); \
+ if (!strncmp(type, cdt_lib_##m.prefix, n)) \
+ type += n; \
+ for (i = 0; cdt_lib_##m.methods[i]; i++) \
+ if (!strcmp(type, cdt_lib_##m.methods[i]->name + n)) \
+ return cdt_lib_##m.methods[i]; \
+ return 0; \
+ } \
+ unsigned long plugin_version(void) { return CDT_PLUGIN_VERSION; }
+#else
+#define CDTLIB(m) \
+ void* cdt_lib(name, disc, type) const char* name; Dtdisc_t* disc; const char* type; \
+ { \
+ int i; \
+ int n; \
+ if (!type) \
+ return &cdt_lib_/**/m; \
+ n = strlen(cdt_lib_/**/m.prefix); \
+ if (!strncmp(type, cdt_lib_/**/m.prefix, n)) \
+ type += n; \
+ for (i = 0; cdt_lib_/**/m.methods[i]; i++) \
+ if (!strcmp(type, cdt_lib_/**/m.methods[i]->name + n)) \
+ return cdt_lib_/**/m.methods[i]; \
+ return 0; \
+ } \
+ unsigned long plugin_version() { return CDT_PLUGIN_VERSION; }
+#endif
+
+#endif /* _BLD_cdt */
+
+/* these macros lock/unlock dictionaries. DTRETURN substitutes for "return" */
+#define DTSETLOCK(dt) (((dt)->data->type&DT_SHARE) ? asolock(&(dt)->data->lock,1,ASO_SPINLOCK) : 0 )
+#define DTCLRLOCK(dt) (((dt)->data->type&DT_SHARE) ? asolock(&(dt)->data->lock,1,ASO_UNLOCK) : 0 )
+#define DTRETURN(ob,rv) do { (ob) = (rv); goto dt_return; } while(0)
+#define DTERROR(dt, mesg) (!((dt)->disc && (dt)->disc->eventf) ? 0 : \
+ (*(dt)->disc->eventf)((dt),DT_ERROR,(Void_t*)(mesg),(dt)->disc) )
+
+/* announce completion of an operation of type (ty) on some object (ob) in dictionary (dt) */
+#define DTANNOUNCE(dt,ob,ty) ( ((ob) && ((ty)&DT_TOANNOUNCE) && ((dt)->data->type&DT_ANNOUNCE) && \
+ (dt)->disc && (dt)->disc->eventf ) ? \
+ (*(dt)->disc->eventf)((dt), DT_ANNOUNCE|(ty), (ob), (dt)->disc) : 0 )
+
+/* map bits for upward compabitibility */
+#define DTTYPE(dt,ty) ((dt)->typef ? (*(dt)->typef)((dt), (ty)) : (ty) )
+
+/* short-hands for fields in Dtlink_t.
+** note that __hash is used as a hash value
+** or as the position in the parent table.
+*/
+#define _left lh.__left
+#define _hash lh.__hash
+#define _ppos lh.__hash
+
+#define _rght rh.__rght
+#define _ptbl rh.__ptbl
+
+/* tree rotation/linking functions */
+#define rrotate(x,y) ((x)->_left = (y)->_rght, (y)->_rght = (x))
+#define lrotate(x,y) ((x)->_rght = (y)->_left, (y)->_left = (x))
+#define rlink(r,x) ((r) = (r)->_left = (x) )
+#define llink(l,x) ((l) = (l)->_rght = (x) )
+
+#define RROTATE(x,y) (rrotate(x,y), (x) = (y))
+#define LROTATE(x,y) (lrotate(x,y), (x) = (y))
+#define RRSHIFT(x,t) ((t) = (x)->_left->_left, (x)->_left->_left = (t)->_rght, \
+ (t)->_rght = (x), (x) = (t) )
+#define LLSHIFT(x,t) ((t) = (x)->_rght->_rght, (x)->_rght->_rght = (t)->_left, \
+ (t)->_left = (x), (x) = (t) )
+
+_BEGIN_EXTERNS_
+
+#if _BLD_cdt && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern Dtlink_t* _dtmake _ARG_((Dt_t*, Void_t*, int));
+extern void _dtfree _ARG_((Dt_t*, Dtlink_t*, int));
+extern int _dtlock _ARG_((Dt_t*, int));
+
+#undef extern
+
+#if !_PACKAGE_ast
+extern Void_t* malloc _ARG_((size_t));
+extern Void_t* realloc _ARG_((Void_t*, size_t));
+extern void free _ARG_((Void_t*));
+#endif
+_END_EXTERNS_
+
+#endif /* _CDTLIB_H */
diff --git a/src/lib/libast/cdt/dtclose.c b/src/lib/libast/cdt/dtclose.c
new file mode 100644
index 0000000..45bca76
--- /dev/null
+++ b/src/lib/libast/cdt/dtclose.c
@@ -0,0 +1,66 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Close a dictionary
+**
+** Written by Kiem-Phong Vo (11/15/2010)
+*/
+#if __STD_C
+int dtclose(Dt_t* dt)
+#else
+int dtclose(dt)
+Dt_t* dt;
+#endif
+{
+ int ev, type;
+ Dt_t pdt;
+ Dtdisc_t *disc = dt->disc;
+
+ if(!dt || dt->nview > 0 ) /* can't close if being viewed */
+ return -1;
+
+ if(disc && disc->eventf) /* announce closing event */
+ ev = (*disc->eventf)(dt, DT_CLOSE, (Void_t*)1, disc);
+ else ev = 0;
+ if(ev < 0) /* cannot close */
+ return -1;
+
+ if(dt->view) /* turn off viewing at this point */
+ dtview(dt,NIL(Dt_t*));
+
+ type = dt->data->type; /* save before memory is freed */
+ memcpy(&pdt, dt, sizeof(Dt_t));
+
+ if(ev == 0 ) /* release all allocated data */
+ { (void)(*(dt->meth->searchf))(dt,NIL(Void_t*),DT_CLEAR);
+ (void)(*dt->meth->eventf)(dt, DT_CLOSE, (Void_t*)0);
+ /**/DEBUG_ASSERT(!dt->data);
+ }
+ if(!(type&DT_INDATA) )
+ (void)free(dt);
+
+ if(disc && disc->eventf) /* announce end of closing activities */
+ (void)(*disc->eventf)(&pdt, DT_ENDCLOSE, (Void_t*)0, disc);
+
+ return 0;
+}
diff --git a/src/lib/libast/cdt/dtcomp.c b/src/lib/libast/cdt/dtcomp.c
new file mode 100644
index 0000000..5308c70
--- /dev/null
+++ b/src/lib/libast/cdt/dtcomp.c
@@ -0,0 +1,60 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * backwards binary compatibility
+ */
+
+#include <cdt.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#undef dtflatten
+extern Dtlink_t* dtflatten(Dt_t* d)
+{
+ return (Dtlink_t*)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_FLATTEN);
+}
+
+#undef dtextract
+extern Dtlink_t* dtextract(Dt_t* d)
+{
+ return (Dtlink_t*)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_EXTRACT);
+}
+
+#undef dtrestore
+extern Dtlink_t* dtrestore(Dt_t* d, Void_t* l)
+{
+ return (Dtlink_t*)(*(_DT(d)->searchf))((d),(l),DT_RESTORE);
+}
+
+#undef dtsize
+extern ssize_t dtsize(Dt_t* d)
+{
+ return (ssize_t)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_STAT);
+}
+
+#undef dtstat
+extern ssize_t dtstat(Dt_t* d)
+{
+ return (ssize_t)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_STAT);
+}
diff --git a/src/lib/libast/cdt/dtdisc.c b/src/lib/libast/cdt/dtdisc.c
new file mode 100644
index 0000000..166aa7c
--- /dev/null
+++ b/src/lib/libast/cdt/dtdisc.c
@@ -0,0 +1,91 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Change discipline.
+** dt : dictionary
+** disc : discipline
+**
+** Written by Kiem-Phong Vo (5/26/96)
+*/
+
+#if __STD_C
+static Void_t* dtmemory(Dt_t* dt, Void_t* addr, size_t size, Dtdisc_t* disc)
+#else
+static Void_t* dtmemory(dt, addr, size, disc)
+Dt_t* dt; /* dictionary */
+Void_t* addr; /* address to be manipulate */
+size_t size; /* size to obtain */
+Dtdisc_t* disc; /* discipline */
+#endif
+{
+ if(addr)
+ { if(size == 0)
+ { free(addr);
+ return NIL(Void_t*);
+ }
+ else return realloc(addr,size);
+ }
+ else return size > 0 ? malloc(size) : NIL(Void_t*);
+}
+
+#if __STD_C
+Dtdisc_t* dtdisc(Dt_t* dt, Dtdisc_t* disc, int type)
+#else
+Dtdisc_t* dtdisc(dt,disc,type)
+Dt_t* dt;
+Dtdisc_t* disc;
+int type;
+#endif
+{
+ Dtsearch_f searchf;
+ Dtdisc_t *old;
+ Dtlink_t *list;
+
+ if(!(old = dt->disc) ) /* initialization call from dtopen() */
+ { dt->disc = disc;
+ if(!(dt->memoryf = disc->memoryf) )
+ dt->memoryf = dtmemory;
+ return disc;
+ }
+
+ if(!disc) /* only want to know current discipline */
+ return old;
+
+ searchf = dt->meth->searchf;
+
+ if(old->eventf && (*old->eventf)(dt,DT_DISC,(Void_t*)disc,old) < 0)
+ return NIL(Dtdisc_t*);
+
+ if((type & (DT_SAMEHASH|DT_SAMECMP)) != (DT_SAMEHASH|DT_SAMECMP) )
+ list = dtextract(dt); /* grab the list of objects if any */
+ else list = NIL(Dtlink_t*);
+
+ dt->disc = disc;
+ if(!(dt->memoryf = disc->memoryf) )
+ dt->memoryf = dtmemory;
+
+ if(list ) /* reinsert extracted objects (with new discipline) */
+ dtrestore(dt, list);
+
+ return old;
+}
diff --git a/src/lib/libast/cdt/dthash.c b/src/lib/libast/cdt/dthash.c
new file mode 100644
index 0000000..984b2a5
--- /dev/null
+++ b/src/lib/libast/cdt/dthash.c
@@ -0,0 +1,431 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Hash table with chaining for collisions.
+**
+** Written by Kiem-Phong Vo (05/25/96)
+*/
+
+/* these bits should be outside the scope of DT_METHODS */
+#define H_FIXED 0100000 /* table size is fixed */
+#define H_FLATTEN 0200000 /* table was flattened */
+
+#define HLOAD(n) (n) /* load one-to-one */
+
+/* internal data structure for hash table with chaining */
+typedef struct _dthash_s
+{ Dtdata_t data;
+ int type;
+ Dtlink_t* here; /* fingered object */
+ Dtlink_t** htbl; /* hash table slots */
+ ssize_t tblz; /* size of hash table */
+} Dthash_t;
+
+/* make/resize hash table */
+static int htable(Dt_t* dt)
+{
+ Dtlink_t **htbl, **t, **endt, *l, *next;
+ ssize_t n, k;
+ Dtdisc_t *disc = dt->disc;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ if((n = hash->tblz) > 0 && (hash->type&H_FIXED) )
+ return 0; /* fixed size table */
+
+ if(n == 0 && disc && disc->eventf) /* let user have input */
+ { if((*disc->eventf)(dt, DT_HASHSIZE, &n, disc) > 0 )
+ { if(n < 0) /* fix table size */
+ { hash->type |= H_FIXED;
+ n = -n;
+ }
+ }
+ }
+
+ /* table size should be a power of 2 */
+ n = n < HLOAD(hash->data.size) ? HLOAD(hash->data.size) : n;
+ for(k = (1<<DT_HTABLE); k < n; )
+ k *= 2;
+ if((n = k) <= hash->tblz)
+ return 0;
+
+ /* allocate new table */
+ if(!(htbl = (Dtlink_t**)(*dt->memoryf)(dt, 0, n*sizeof(Dtlink_t*), disc)) )
+ { DTERROR(dt, "Error in allocating an extended hash table");
+ return -1;
+ }
+ memset(htbl, 0, n*sizeof(Dtlink_t*));
+
+ /* move objects into new table */
+ for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
+ { for(l = *t; l; l = next)
+ { next = l->_rght;
+ l->_rght = htbl[k = l->_hash&(n-1)];
+ htbl[k] = l;
+ }
+ }
+
+ if(hash->htbl) /* free old table and set new table */
+ (void)(*dt->memoryf)(dt, hash->htbl, 0, disc);
+ hash->htbl = htbl;
+ hash->tblz = n;
+
+ return 0;
+}
+
+static Void_t* hclear(Dt_t* dt)
+{
+ Dtlink_t **t, **endt, *l, *next;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ hash->here = NIL(Dtlink_t*);
+ hash->data.size = 0;
+
+ for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
+ { for(l = *t; l; l = next)
+ { next = l->_rght;
+ _dtfree(dt, l, DT_DELETE);
+ }
+ *t = NIL(Dtlink_t*);
+ }
+
+ return NIL(Void_t*);
+}
+
+static Void_t* hfirst(Dt_t* dt)
+{
+ Dtlink_t **t, **endt, *l;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
+ { if(!(l = *t) )
+ continue;
+ hash->here = l;
+ return _DTOBJ(dt->disc, l);
+ }
+
+ return NIL(Void_t*);
+}
+
+static Void_t* hnext(Dt_t* dt, Dtlink_t* l)
+{
+ Dtlink_t **t, **endt, *next;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ if((next = l->_rght) )
+ { hash->here = next;
+ return _DTOBJ(dt->disc, next);
+ }
+ else
+ { t = hash->htbl + (l->_hash & (hash->tblz-1)) + 1;
+ endt = hash->htbl + hash->tblz;
+ for(; t < endt; ++t)
+ { if(!(l = *t) )
+ continue;
+ hash->here = l;
+ return _DTOBJ(dt->disc, l);
+ }
+ return NIL(Void_t*);
+ }
+}
+
+static Void_t* hflatten(Dt_t* dt, int type)
+{
+ Dtlink_t **t, **endt, *head, *tail, *l;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ if(type == DT_FLATTEN || type == DT_EXTRACT)
+ { head = tail = NIL(Dtlink_t*);
+ for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
+ { for(l = *t; l; l = l->_rght)
+ { if(tail)
+ tail = (tail->_rght = l);
+ else head = tail = l;
+
+ *t = type == DT_FLATTEN ? tail : NIL(Dtlink_t*);
+ }
+ }
+
+ if(type == DT_FLATTEN)
+ { hash->here = head;
+ hash->type |= H_FLATTEN;
+ }
+ else hash->data.size = 0;
+
+ return (Void_t*)head;
+ }
+ else /* restoring a previous flattened list */
+ { head = hash->here;
+ for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
+ { if(*t == NIL(Dtlink_t*))
+ continue;
+
+ /* find the tail of the list for this slot */
+ for(l = head; l && l != *t; l = l->_rght)
+ ;
+ if(!l) /* something is seriously wrong */
+ return NIL(Void_t*);
+
+ *t = head; /* head of list for this slot */
+ head = l->_rght; /* head of next list */
+ l->_rght = NIL(Dtlink_t*);
+ }
+
+ hash->here = NIL(Dtlink_t*);
+ hash->type &= ~H_FLATTEN;
+
+ return NIL(Void_t*);
+ }
+}
+
+static Void_t* hlist(Dt_t* dt, Dtlink_t* list, int type)
+{
+ Void_t *obj;
+ Dtlink_t *l, *next;
+ Dtdisc_t *disc = dt->disc;
+
+ if(type&DT_FLATTEN)
+ return hflatten(dt, DT_FLATTEN);
+ else if(type&DT_EXTRACT)
+ return hflatten(dt, DT_EXTRACT);
+ else /* if(type&DT_RESTORE) */
+ { dt->data->size = 0;
+ for(l = list; l; l = next)
+ { next = l->_rght;
+ obj = _DTOBJ(disc,l);
+ if((*dt->meth->searchf)(dt, (Void_t*)l, DT_RELINK) == obj)
+ dt->data->size += 1;
+ }
+ return (Void_t*)list;
+ }
+}
+
+static Void_t* hstat(Dt_t* dt, Dtstat_t* st)
+{
+ ssize_t n;
+ Dtlink_t **t, **endt, *l;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ if(st)
+ { memset(st, 0, sizeof(Dtstat_t));
+ st->meth = dt->meth->type;
+ st->size = hash->data.size;
+ st->space = sizeof(Dthash_t) + hash->tblz*sizeof(Dtlink_t*) +
+ (dt->disc->link >= 0 ? 0 : hash->data.size*sizeof(Dthold_t));
+
+ for(endt = (t = hash->htbl) + hash->tblz; t < endt; ++t)
+ { for(n = 0, l = *t; l; l = l->_rght)
+ n += 1;
+ st->mlev = n > st->mlev ? n : st->mlev;
+ if(n < DT_MAXSIZE) /* if chain length is small */
+ { st->msize = n > st->msize ? n : st->msize;
+ st->lsize[n] += n;
+ }
+ }
+ }
+
+ return (Void_t*)hash->data.size;
+}
+
+#if __STD_C
+static Void_t* dthashchain(Dt_t* dt, Void_t* obj, int type)
+#else
+static Void_t* dthashchain(dt,obj,type)
+Dt_t* dt;
+Void_t* obj;
+int type;
+#endif
+{
+ Dtlink_t *lnk, *pp, *ll, *p, *l, **tbl;
+ Void_t *key, *k, *o;
+ uint hsh;
+ Dtdisc_t *disc = dt->disc;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+
+ type = DTTYPE(dt,type); /* map type for upward compatibility */
+ if(!(type&DT_OPERATIONS) )
+ return NIL(Void_t*);
+
+ DTSETLOCK(dt);
+
+ if(!hash->htbl && htable(dt) < 0 ) /* initialize hash table */
+ DTRETURN(obj, NIL(Void_t*));
+
+ if(hash->type&H_FLATTEN) /* restore flattened list */
+ hflatten(dt, 0);
+
+ if(type&(DT_FIRST|DT_LAST|DT_CLEAR|DT_EXTRACT|DT_RESTORE|DT_FLATTEN|DT_STAT) )
+ { if(type&(DT_FIRST|DT_LAST) )
+ DTRETURN(obj, hfirst(dt));
+ else if(type&DT_CLEAR)
+ DTRETURN(obj, hclear(dt));
+ else if(type&DT_STAT)
+ DTRETURN(obj, hstat(dt, (Dtstat_t*)obj));
+ else /*if(type&(DT_EXTRACT|DT_RESTORE|DT_FLATTEN))*/
+ DTRETURN(obj, hlist(dt, (Dtlink_t*)obj, type));
+ }
+
+ lnk = hash->here; /* fingered object */
+ hash->here = NIL(Dtlink_t*);
+
+ if(lnk && obj == _DTOBJ(disc,lnk))
+ { if(type&DT_SEARCH)
+ DTRETURN(obj, obj);
+ else if(type&(DT_NEXT|DT_PREV) )
+ DTRETURN(obj, hnext(dt,lnk));
+ }
+
+ if(type&DT_RELINK)
+ { lnk = (Dtlink_t*)obj;
+ obj = _DTOBJ(disc,lnk);
+ key = _DTKEY(disc,obj);
+ }
+ else
+ { lnk = NIL(Dtlink_t*);
+ if((type&DT_MATCH) )
+ { key = obj;
+ obj = NIL(Void_t*);
+ }
+ else key = _DTKEY(disc,obj);
+ }
+ hsh = _DTHSH(dt,key,disc);
+
+ tbl = hash->htbl + (hsh & (hash->tblz-1));
+ pp = ll = NIL(Dtlink_t*);
+ for(p = NIL(Dtlink_t*), l = *tbl; l; p = l, l = l->_rght)
+ { if(hsh == l->_hash)
+ { o = _DTOBJ(disc,l); k = _DTKEY(disc,o);
+ if(_DTCMP(dt, key, k, disc) != 0 )
+ continue;
+ else if((type&(DT_REMOVE|DT_NEXT|DT_PREV)) && o != obj )
+ { if(type&(DT_NEXT|DT_PREV) )
+ { pp = p; ll = l; }
+ continue;
+ }
+ else break;
+ }
+ }
+ if(l) /* found an object, use it */
+ { pp = p; ll = l; }
+
+ if(ll) /* found object */
+ { if(type&(DT_SEARCH|DT_MATCH|DT_ATLEAST|DT_ATMOST) )
+ { hash->here = ll;
+ DTRETURN(obj, _DTOBJ(disc,ll));
+ }
+ else if(type & (DT_NEXT|DT_PREV) )
+ DTRETURN(obj, hnext(dt, ll));
+ else if(type & (DT_DELETE|DT_DETACH|DT_REMOVE) )
+ { hash->data.size -= 1;
+ if(pp)
+ pp->_rght = ll->_rght;
+ else *tbl = ll->_rght;
+ _dtfree(dt, ll, type);
+ DTRETURN(obj, _DTOBJ(disc,ll));
+ }
+ else
+ { /**/DEBUG_ASSERT(type&(DT_INSERT|DT_ATTACH|DT_APPEND|DT_RELINK));
+ if(!(dt->meth->type&DT_BAG) )
+ { if(type&(DT_INSERT|DT_APPEND|DT_ATTACH) )
+ type |= DT_SEARCH; /* for announcement */
+ else if(lnk && (type&DT_RELINK) )
+ _dtfree(dt, lnk, DT_DELETE);
+ DTRETURN(obj, _DTOBJ(disc,ll));
+ }
+ else goto do_insert;
+ }
+ }
+ else /* no matching object */
+ { if(!(type&(DT_INSERT|DT_APPEND|DT_ATTACH|DT_RELINK)) )
+ DTRETURN(obj, NIL(Void_t*));
+
+ do_insert: /* inserting a new object */
+ if(hash->tblz < HLOAD(hash->data.size) )
+ { htable(dt); /* resize table */
+ tbl = hash->htbl + (hsh & (hash->tblz-1));
+ }
+
+ if(!lnk) /* inserting a new object */
+ { if(!(lnk = _dtmake(dt, obj, type)) )
+ DTRETURN(obj, NIL(Void_t*));
+ hash->data.size += 1;
+ }
+
+ lnk->_hash = hsh; /* memoize the hash value */
+ lnk->_rght = *tbl; *tbl = lnk;
+
+ hash->here = lnk;
+ DTRETURN(obj, _DTOBJ(disc,lnk));
+ }
+
+dt_return:
+ DTANNOUNCE(dt, obj, type);
+ DTCLRLOCK(dt);
+ return obj;
+}
+
+static int hashevent(Dt_t* dt, int event, Void_t* arg)
+{
+ Dtlink_t *list;
+ Dthash_t *hash = (Dthash_t*)dt->data;
+ int rv = -1;
+
+ if(event == DT_OPEN)
+ { if(hash)
+ return 0;
+ if(!(hash = (Dthash_t*)(*dt->memoryf)(dt, 0, sizeof(Dthash_t), dt->disc)) )
+ { DTERROR(dt, "Error in allocating a hash table with chaining");
+ return -1;
+ }
+ memset(hash, 0, sizeof(Dthash_t));
+ dt->data = (Dtdata_t*)hash;
+ return 1;
+ }
+ else if(event == DT_CLOSE)
+ { if(!hash)
+ return 0;
+ if(hash->data.size > 0 )
+ (void)hclear(dt);
+ if(hash->htbl)
+ (void)(*dt->memoryf)(dt, hash->htbl, 0, dt->disc);
+ (void)(*dt->memoryf)(dt, hash, 0, dt->disc);
+ dt->data = NIL(Dtdata_t*);
+ return 0;
+ }
+ else return 0;
+}
+
+static Dtmethod_t _Dtset = { dthashchain, DT_SET, hashevent, "Dtset" };
+static Dtmethod_t _Dtbag = { dthashchain, DT_BAG, hashevent, "Dtbag" };
+__DEFINE__(Dtmethod_t*,Dtset,&_Dtset);
+__DEFINE__(Dtmethod_t*,Dtbag,&_Dtbag);
+
+/* backwards compatibility */
+#undef Dthash
+#if defined(__EXPORT__)
+__EXPORT__
+#endif
+__DEFINE__(Dtmethod_t*,Dthash,&_Dtset);
+
+#ifdef NoF
+NoF(dthashchain)
+#endif
diff --git a/src/lib/libast/cdt/dthdr.h b/src/lib/libast/cdt/dthdr.h
new file mode 100644
index 0000000..d24ae0d
--- /dev/null
+++ b/src/lib/libast/cdt/dthdr.h
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _DTHDR_H
+#define _DTHDR_H 1
+
+#ifndef _BLD_cdt
+#define _BLD_cdt 1
+#endif
+
+/* Internal definitions for libcdt.
+** Written by Kiem-Phong Vo (5/25/96)
+*/
+
+#undef _DTTRACE
+
+#include <cdtlib.h>
+
+#endif /* _DTHDR_H */
diff --git a/src/lib/libast/cdt/dtlist.c b/src/lib/libast/cdt/dtlist.c
new file mode 100644
index 0000000..af0dfd1
--- /dev/null
+++ b/src/lib/libast/cdt/dtlist.c
@@ -0,0 +1,387 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* List, Deque, Stack, Queue.
+**
+** Written by Kiem-Phong Vo (05/25/96)
+*/
+
+typedef struct _dtlist_s
+{ Dtdata_t data;
+ Dtlink_t* link; /* list of objects */
+ Dtlink_t* here; /* finger to searched objects */
+} Dtlist_t;
+
+#ifdef DEBUG
+int dtlistprint(Dt_t* dt, Dtlink_t* here, char* (*objprintf)(Void_t*) )
+{
+ int k;
+ char *obj, *endb, buf[1024];
+ Dtdisc_t *disc = dt->disc;
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ if(!here && !(here = list->link) )
+ return -1;
+
+ for(; here; here = here->_rght)
+ { endb = buf; /* indentation */
+ *endb++ = '(';
+ obj = (*objprintf)(_DTOBJ(disc, here));
+ k = strlen(obj); memcpy(endb, obj, k); endb += k;
+ *endb++ = ')';
+ *endb++ = '\n';
+ write(2, buf, endb-buf);
+ }
+
+ return 0;
+}
+#endif
+
+/* terminal objects: DT_FIRST|DT_LAST */
+#if __STD_C
+Void_t* lfirstlast(Dt_t* dt, int type)
+#else
+Void_t* lfirstlast(dt, type)
+Dt_t* dt;
+int type;
+#endif
+{
+ Dtlink_t *lnk;
+ Dtdisc_t *disc = dt->disc;
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ if((lnk = list->link) )
+ { if(type&DT_LAST)
+ lnk = lnk->_left;
+ list->here = lnk; /* finger points to this */
+ }
+
+ return lnk ? _DTOBJ(disc,lnk) : NIL(Void_t*);
+}
+
+/* DT_CLEAR */
+#if __STD_C
+Void_t* lclear(Dt_t* dt)
+#else
+Void_t* lclear(dt)
+Dt_t* dt;
+#endif
+{
+ Dtlink_t *lnk, *next;
+ Dtdisc_t *disc = dt->disc;
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ lnk = list->link;
+ list->link = list->here = NIL(Dtlink_t*);
+ list->data.size = 0;
+
+ if(disc->freef || disc->link < 0)
+ { for(; lnk; lnk = next)
+ { next = lnk->_rght;
+ _dtfree(dt, lnk, DT_DELETE);
+ }
+ }
+
+ return NIL(Void_t*);
+}
+
+/* DT_FLATTEN|DT_EXTRACT|DT_RESTORE */
+#if __STD_C
+Void_t* llist(Dt_t* dt, Dtlink_t* lnk, int type)
+#else
+Void_t* llist(dt, lnk, type)
+Dt_t* dt;
+Dtlink_t* lnk;
+int type;
+#endif
+{
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ if(type&(DT_FLATTEN|DT_EXTRACT) )
+ { if(lnk) /* error on calling */
+ return NIL(Void_t*);
+
+ lnk = list->link;
+ if(type&DT_EXTRACT)
+ { list->link = NIL(Dtlink_t*);
+ dt->data->size = 0;
+ }
+ }
+ else /* if(type&DT_RESTORE) */
+ { if(list->link != NIL(Dtlink_t*))
+ return NIL(Void_t*);
+
+ list->link = lnk;
+
+ dt->data->size = 0;
+ for(; lnk; lnk = lnk->_rght)
+ dt->data->size += 1;
+ }
+
+ return (Void_t*)lnk;
+}
+
+#if __STD_C
+static Void_t* liststat(Dt_t* dt, Dtstat_t* st)
+#else
+static Void_t* liststat(dt, st)
+Dt_t* dt;
+Dtstat_t* st;
+#endif
+{
+ ssize_t size;
+ Dtlink_t *lnk;
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ if(st)
+ { memset(st, 0, sizeof(Dtstat_t));
+ st->meth = dt->meth->type;
+ st->size = dt->data->size;
+ st->space = sizeof(Dtlist_t) + (dt->disc->link >= 0 ? 0 : dt->data->size*sizeof(Dthold_t));
+ }
+
+ return (Void_t*)dt->data->size;
+}
+
+#if __STD_C
+static Void_t* dtlist(Dt_t* dt, Void_t* obj, int type)
+#else
+static Void_t* dtlist(dt, obj, type)
+Dt_t* dt;
+Void_t* obj;
+int type;
+#endif
+{
+ Dtlink_t *r, *t, *h;
+ Void_t *key, *o, *k;
+ Dtdisc_t *disc = dt->disc;
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ type = DTTYPE(dt,type); /* map type for upward compatibility */
+ if(!(type&DT_OPERATIONS) )
+ return NIL(Void_t*);
+
+ DTSETLOCK(dt);
+
+ if(type&(DT_FIRST|DT_LAST) )
+ DTRETURN(obj, lfirstlast(dt, type));
+ else if(type&(DT_EXTRACT|DT_RESTORE|DT_FLATTEN) )
+ DTRETURN(obj, llist(dt, (Dtlink_t*)obj, type));
+ else if(type&DT_CLEAR)
+ DTRETURN(obj, lclear(dt));
+ else if(type&DT_STAT )
+ DTRETURN(obj, liststat(dt, (Dtstat_t*)obj));
+
+ h = list->here; /* save finger to last search object */
+ list->here = NIL(Dtlink_t*);
+
+ if(!obj)
+ { if((type&(DT_DELETE|DT_DETACH|DT_REMOVE)) && (dt->meth->type&(DT_STACK|DT_QUEUE)) )
+ if((r = list->link) ) /* special case for destack or dequeue */
+ goto dt_delete;
+ DTRETURN(obj, NIL(Void_t*)); /* error, needing non-void object */
+ }
+
+ if(type&DT_RELINK) /* relink object after some processing */
+ { r = (Dtlink_t*)obj;
+ goto do_insert;
+ }
+ else if(type&(DT_INSERT|DT_APPEND|DT_ATTACH))
+ { if(!(r = _dtmake(dt, obj, type)) )
+ DTRETURN(obj, NIL(Void_t*));
+ dt->data->size += 1;
+
+ do_insert:
+ if(dt->meth->type&DT_DEQUE)
+ { if(type&DT_APPEND)
+ goto dt_queue; /* append at end */
+ else goto dt_stack; /* insert at top */
+ }
+ else if(dt->meth->type&DT_LIST)
+ { if(type&DT_APPEND)
+ { if(!h || !h->_rght)
+ goto dt_queue;
+ r->_rght = h->_rght;
+ r->_rght->_left = r;
+ r->_left = h;
+ r->_left->_rght = r;
+ }
+ else
+ { if(!h || h == list->link )
+ goto dt_stack;
+ r->_left = h->_left;
+ r->_left->_rght = r;
+ r->_rght = h;
+ r->_rght->_left = r;
+ }
+ }
+ else if(dt->meth->type&DT_STACK)
+ { dt_stack:
+ r->_rght = t = list->link;
+ if(t)
+ { r->_left = t->_left;
+ t->_left = r;
+ }
+ else r->_left = r;
+ list->link = r;
+ }
+ else /* if(dt->meth->type&DT_QUEUE) */
+ { dt_queue:
+ if((t = list->link) )
+ { t->_left->_rght = r;
+ r->_left = t->_left;
+ t->_left = r;
+ }
+ else
+ { list->link = r;
+ r->_left = r;
+ }
+ r->_rght = NIL(Dtlink_t*);
+ }
+
+ list->here = r;
+ DTRETURN(obj, _DTOBJ(disc,r));
+ }
+
+ /* define key to match */
+ if(type&DT_MATCH)
+ { key = obj;
+ obj = NIL(Void_t*);
+ }
+ else key = _DTKEY(disc, obj);
+
+ /* try to find a matching object */
+ if(h && _DTOBJ(disc,h) == obj && (type & (DT_SEARCH|DT_NEXT|DT_PREV)) )
+ r = h; /* match at the finger, no search needed */
+ else /* linear search through the list */
+ { h = NIL(Dtlink_t*); /* track first/last obj with same key */
+ for(r = list->link; r; r = r->_rght)
+ { o = _DTOBJ(disc,r); k = _DTKEY(disc,o);
+ if(_DTCMP(dt, key, k, disc) != 0)
+ continue;
+ else if(type & (DT_REMOVE|DT_NEXT|DT_PREV) )
+ { if(o == obj) /* got exact object, done */
+ break;
+ else if(type&DT_NEXT) /* track last object */
+ h = r;
+ else if(type&DT_PREV) /* track first object */
+ h = h ? h : r;
+ else continue;
+ }
+ else if(type & DT_ATLEAST )
+ h = r; /* track last object */
+ else break;
+ }
+ r = h ? h : r;
+ }
+ if(!r)
+ DTRETURN(obj, NIL(Void_t*));
+
+ if(type&(DT_DELETE|DT_DETACH|DT_REMOVE))
+ { dt_delete:
+ if(r->_rght)
+ r->_rght->_left = r->_left;
+ if(r == (t = list->link) )
+ { list->link = r->_rght;
+ if((h = list->link) )
+ h->_left = t->_left;
+ }
+ else
+ { r->_left->_rght = r->_rght;
+ if(r == t->_left)
+ t->_left = r->_left;
+ }
+
+ list->here = r == list->here ? r->_rght : NIL(Dtlink_t*);
+
+ obj = _DTOBJ(disc,r);
+ _dtfree(dt, r, type);
+ dt->data->size -= 1;
+
+ DTRETURN(obj, obj);
+ }
+
+ if(type&DT_NEXT)
+ r = r->_rght;
+ else if(type&DT_PREV)
+ r = r == list->link ? NIL(Dtlink_t*) : r->_left;
+ /* else: if(type&(DT_SEARCH|DT_MATCH|DT_ATLEAST|DT_ATMOST)) */
+
+ list->here = r;
+ if(r)
+ DTRETURN(obj, _DTOBJ(disc,r));
+ else DTRETURN(obj, NIL(Void_t*));
+
+dt_return:
+ DTANNOUNCE(dt,obj,type);
+ DTCLRLOCK(dt);
+ return obj;
+}
+
+#if __STD_C
+static int listevent(Dt_t* dt, int event, Void_t* arg)
+#else
+static int listevent(dt, event, arg)
+Dt_t* dt;
+int event;
+Void_t* arg;
+#endif
+{
+ Dtlist_t *list = (Dtlist_t*)dt->data;
+
+ if(event == DT_OPEN)
+ { if(list) /* already initialized */
+ return 0;
+ if(!(list = (Dtlist_t*)(*dt->memoryf)(dt, 0, sizeof(Dtlist_t), dt->disc)) )
+ { DTERROR(dt, "Error in allocating a list data structure");
+ return -1;
+ }
+ memset(list, 0, sizeof(Dtlist_t));
+ dt->data = (Dtdata_t*)list;
+ return 1;
+ }
+ else if(event == DT_CLOSE)
+ { if(!list) /* already closed */
+ return 0;
+ if(list->link) /* remove all items */
+ (void)lclear(dt);
+ (void)(*dt->memoryf)(dt, (Void_t*)list, 0, dt->disc);
+ dt->data = NIL(Dtdata_t*);
+ return 0;
+ }
+ else return 0;
+}
+
+static Dtmethod_t _Dtlist = { dtlist, DT_LIST, listevent, "Dtlist" };
+static Dtmethod_t _Dtdeque = { dtlist, DT_DEQUE, listevent, "Dtdeque" };
+static Dtmethod_t _Dtstack = { dtlist, DT_STACK, listevent, "Dtstack" };
+static Dtmethod_t _Dtqueue = { dtlist, DT_QUEUE, listevent, "Dtqueue" };
+
+__DEFINE__(Dtmethod_t*,Dtlist,&_Dtlist);
+__DEFINE__(Dtmethod_t*,Dtdeque,&_Dtdeque);
+__DEFINE__(Dtmethod_t*,Dtstack,&_Dtstack);
+__DEFINE__(Dtmethod_t*,Dtqueue,&_Dtqueue);
+
+#ifdef NoF
+NoF(dtlist)
+#endif
diff --git a/src/lib/libast/cdt/dtmethod.c b/src/lib/libast/cdt/dtmethod.c
new file mode 100644
index 0000000..56a1d25
--- /dev/null
+++ b/src/lib/libast/cdt/dtmethod.c
@@ -0,0 +1,107 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Change search method.
+**
+** Written by Kiem-Phong Vo (05/25/96)
+*/
+
+#if __STD_C
+Dtmethod_t* dtmethod(Dt_t* dt, Dtmethod_t* meth)
+#else
+Dtmethod_t* dtmethod(dt, meth)
+Dt_t* dt;
+Dtmethod_t* meth;
+#endif
+{
+ Dtlink_t *list;
+ Dtdisc_t *disc = dt->disc;
+ Dtmethod_t *oldmt = dt->meth;
+ Dtdata_t *newdt, *olddt = dt->data;
+
+ if(!meth || meth == oldmt)
+ return oldmt;
+
+ /* ask discipline if switching to new method is ok */
+ if(disc->eventf && (*disc->eventf)(dt,DT_METH,(Void_t*)meth,disc) < 0)
+ return NIL(Dtmethod_t*);
+
+ list = dtextract(dt); /* extract elements out of dictionary */
+
+ /* try to create internal structure for new method */
+ if(dt->searchf == oldmt->searchf) /* ie, not viewpathing */
+ dt->searchf = meth->searchf;
+ dt->meth = meth;
+ dt->data = NIL(Dtdata_t*);
+ if((*dt->meth->eventf)(dt, DT_OPEN, NIL(Void_t*)) < 0 )
+ newdt = NIL(Dtdata_t*);
+ else newdt = dt->data;
+
+ /* see what need to be done to data of the old method */
+ if(dt->searchf == meth->searchf)
+ dt->searchf = oldmt->searchf;
+ dt->meth = oldmt;
+ dt->data = olddt;
+ if(newdt) /* switch was successful, remove old data */
+ { (void)(*dt->meth->eventf)(dt, DT_CLOSE, NIL(Void_t*));
+
+ if(dt->searchf == oldmt->searchf)
+ dt->searchf = meth->searchf;
+ dt->meth = meth;
+ dt->data = newdt;
+ dtrestore(dt, list);
+ return oldmt;
+ }
+ else /* switch failed, restore dictionary to previous states */
+ { dtrestore(dt, list);
+ return NIL(Dtmethod_t*);
+ }
+}
+
+/* customize certain actions in a container data structure */
+int dtcustomize(Dt_t* dt, int type, int action)
+{
+ int done = 0;
+
+ if((type&DT_SHARE) &&
+ (!dt->meth->eventf || (*dt->meth->eventf)(dt, DT_SHARE, (Void_t*)((long)action)) >= 0) )
+ { if(action <= 0 )
+ dt->data->type &= ~DT_SHARE;
+ else dt->data->type |= DT_SHARE;
+ done |= DT_SHARE;
+ }
+
+ if((type&DT_ANNOUNCE) &&
+ (!dt->meth->eventf || (*dt->meth->eventf)(dt, DT_ANNOUNCE, (Void_t*)((long)action)) >= 0) )
+ { if(action <= 0 )
+ dt->data->type &= ~DT_ANNOUNCE;
+ else dt->data->type |= DT_ANNOUNCE;
+ done |= DT_ANNOUNCE;
+ }
+
+ if((type&DT_OPTIMIZE) &&
+ (!dt->meth->eventf || (*dt->meth->eventf)(dt, DT_OPTIMIZE, (Void_t*)((long)action)) >= 0) )
+ done |= DT_OPTIMIZE;
+
+ return done;
+}
diff --git a/src/lib/libast/cdt/dtnew.c b/src/lib/libast/cdt/dtnew.c
new file mode 100644
index 0000000..5e1bb70
--- /dev/null
+++ b/src/lib/libast/cdt/dtnew.c
@@ -0,0 +1,81 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * dtopen() with handle placed in specific vm region
+ */
+
+#include <dt.h>
+
+typedef struct Dc_s
+{
+ Dtdisc_t ndisc;
+ Dtdisc_t* odisc;
+ Vmalloc_t* vm;
+} Dc_t;
+
+static int
+eventf(Dt_t* dt, int op, void* data, Dtdisc_t* disc)
+{
+ Dc_t* dc = (Dc_t*)disc;
+ int r;
+
+ if (dc->odisc->eventf && (r = (*dc->odisc->eventf)(dt, op, data, dc->odisc)))
+ return r;
+ return op == DT_ENDOPEN ? 1 : 0;
+}
+
+static void*
+memoryf(Dt_t* dt, void* addr, size_t size, Dtdisc_t* disc)
+{
+ return vmresize(((Dc_t*)disc)->vm, addr, size, VM_RSMOVE);
+}
+
+/*
+ * open a dictionary using disc->memoryf if set or vm otherwise
+ */
+
+Dt_t*
+_dtnew(Vmalloc_t* vm, Dtdisc_t* disc, Dtmethod_t* meth, unsigned long version)
+{
+ Dt_t* dt;
+ Dc_t dc;
+
+ dc.odisc = disc;
+ dc.ndisc = *disc;
+ dc.ndisc.eventf = eventf;
+ if (!dc.ndisc.memoryf)
+ dc.ndisc.memoryf = memoryf;
+ dc.vm = vm;
+ if (dt = _dtopen(&dc.ndisc, meth, version))
+ dtdisc(dt, disc, DT_SAMECMP|DT_SAMEHASH);
+ return dt;
+}
+
+#undef dtnew
+
+Dt_t*
+dtnew(Vmalloc_t* vm, Dtdisc_t* disc, Dtmethod_t* meth)
+{
+ return _dtnew(vm, disc, meth, 20050420L);
+}
diff --git a/src/lib/libast/cdt/dtopen.c b/src/lib/libast/cdt/dtopen.c
new file mode 100644
index 0000000..6411969
--- /dev/null
+++ b/src/lib/libast/cdt/dtopen.c
@@ -0,0 +1,177 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+static char* Version = "\n@(#)$Id: cdt (AT&T Labs - Research) 2011-11-11 $\0\n";
+
+/* Make a new dictionary
+**
+** Written by Kiem-Phong Vo (5/25/96)
+*/
+
+/* map operation bits from the 2005 version to the current version */
+static int _dttype2005(Dt_t* dt, int type)
+{
+ if (type == DT_DELETE && (dt->meth->type&(DT_OBAG|DT_BAG)))
+ type = DT_REMOVE;
+ return type;
+}
+
+#if __STD_C
+Dt_t* _dtopen(Dtdisc_t* disc, Dtmethod_t* meth, unsigned long version)
+#else
+Dt_t* _dtopen(disc, meth, version)
+Dtdisc_t* disc;
+Dtmethod_t* meth;
+unsigned long version;
+#endif
+{
+ Dtdata_t *data;
+ Dt_t *dt, pdt;
+ int ev, type;
+
+ if(!disc || !meth)
+ return NIL(Dt_t*);
+
+ dt = NIL(Dt_t*);
+ data = NIL(Dtdata_t*);
+ type = meth->type;
+
+ memset(&pdt, 0, sizeof(Dt_t));
+ pdt.searchf = meth->searchf;
+ pdt.meth = meth;
+ dtdisc(&pdt,disc,0); /* note that this sets pdt.memoryf */
+
+ if(disc->eventf)
+ { if((ev = (*disc->eventf)(&pdt,DT_OPEN,(Void_t*)(&data),disc)) < 0)
+ return NIL(Dt_t*); /* something bad happened */
+ else if(ev > 0)
+ { if(data) /* shared data are being restored */
+ { if((data->type & DT_METHODS) != meth->type)
+ { DTERROR(&pdt, "Error in matching methods to restore dictionary");
+ return NIL(Dt_t*);
+ }
+ pdt.data = data;
+ }
+ }
+ else
+ { if(data) /* dt should be allocated with dt->data */
+ type |= DT_INDATA;
+ }
+ }
+
+ if(!pdt.data) /* allocate method-specific data */
+ if((*meth->eventf)(&pdt, DT_OPEN, NIL(Void_t*)) < 0 || !pdt.data )
+ return NIL(Dt_t*);
+ pdt.data->type |= type;
+
+ /* now allocate/initialize the actual dictionary structure */
+ if(pdt.data->type&DT_INDATA)
+ dt = &pdt.data->dict;
+ else if(!(dt = (Dt_t*) malloc(sizeof(Dt_t))) )
+ { (void)(*meth->eventf)(&pdt, DT_CLOSE, NIL(Void_t*));
+ DTERROR(&pdt, "Error in allocating a new dictionary");
+ return NIL(Dt_t*);
+ }
+
+ *dt = pdt;
+
+ dt->user = &dt->data->user; /* space allocated for application usage */
+
+ if(disc->eventf) /* signal opening is done */
+ (void)(*disc->eventf)(dt, DT_ENDOPEN, (Void_t*)0, disc);
+
+ /* set mapping of operation bits between versions as needed */
+ if(version < 20111111L)
+ dt->typef = _dttype2005;
+
+ return dt;
+}
+
+#undef dtopen /* deal with binary upward compatibility for op bits */
+#if __STD_C
+Dt_t* dtopen(Dtdisc_t* disc, Dtmethod_t* meth)
+#else
+Dt_t* dtopen(disc, meth)
+Dtdisc_t* disc;
+Dtmethod_t* meth;
+#endif
+{
+ return _dtopen(disc, meth, 20050420L);
+}
+
+/* below are private functions used across CDT modules */
+Dtlink_t* _dtmake(Dt_t* dt, Void_t* obj, int type)
+{
+ Dthold_t *h;
+ Dtdisc_t *disc = dt->disc;
+
+ /* if obj is a prototype, make a real one */
+ if(!(type&DT_ATTACH) && disc->makef && !(obj = (*disc->makef)(dt, obj, disc)) )
+ return NIL(Dtlink_t*);
+
+ if(disc->link >= 0) /* holder is embedded in obj itself */
+ return _DTLNK(disc, obj);
+
+ /* create a holder to hold obj */
+ if((h = (Dthold_t*)(dt->memoryf)(dt, NIL(Void_t*), sizeof(Dthold_t), disc)) )
+ h->obj = obj;
+ else
+ { DTERROR(dt, "Error in allocating an object holder");
+ if(!(type&DT_ATTACH) && disc->makef && disc->freef)
+ (void)(*disc->freef)(dt, obj, disc); /* free just-made obj */
+ }
+
+ return (Dtlink_t*)h;
+}
+
+void _dtfree(Dt_t* dt, Dtlink_t* l, int type)
+{
+ Dtdisc_t *disc = dt->disc;
+
+ if(!(type&DT_DETACH) && disc->freef) /* free object */
+ (void)(*disc->freef)(dt, _DTOBJ(disc,l), disc);
+
+ if(disc->link < 0) /* free holder */
+ (void)(*dt->memoryf)(dt, (Void_t*)l, 0, disc);
+}
+
+int dtuserlock(Dt_t* dt, unsigned int key, int type)
+{
+ if(type > 0)
+ return asolock(&dt->data->user.lock, key, ASO_LOCK);
+ else if(type < 0)
+ return asolock(&dt->data->user.lock, key, ASO_UNLOCK);
+ else return asolock(&dt->data->user.lock, key, ASO_TRYLOCK);
+}
+
+Void_t* dtuserdata(Dt_t* dt, Void_t* data, unsigned int key)
+{
+ if(key == 0)
+ return dt->data->user.data;
+ else if(dtuserlock(dt, key, 1) < 0 )
+ return NIL(Void_t*);
+ else
+ { dt->data->user.data = data;
+ dtuserlock(dt, key, -1);
+ return data;
+ }
+}
diff --git a/src/lib/libast/cdt/dtstrhash.c b/src/lib/libast/cdt/dtstrhash.c
new file mode 100644
index 0000000..7eaac89
--- /dev/null
+++ b/src/lib/libast/cdt/dtstrhash.c
@@ -0,0 +1,61 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Hashing a string into an unsigned integer.
+** The basic method is to continuingly accumulate bytes and multiply
+** with some given prime. The length n of the string is added last.
+** The recurrent equation is like this:
+** h[k] = (h[k-1] + bytes)*prime for 0 <= k < n
+** h[n] = (h[n-1] + n)*prime
+** The prime is chosen to have a good distribution of 1-bits so that
+** the multiplication will distribute the bits in the accumulator well.
+** The below code accumulates 2 bytes at a time for speed.
+**
+** Written by Kiem-Phong Vo (02/28/03)
+*/
+
+#if __STD_C
+uint dtstrhash(uint h, Void_t* args, ssize_t n)
+#else
+uint dtstrhash(h,args,n)
+reg uint h;
+Void_t* args;
+ssize_t n;
+#endif
+{
+ unsigned char *s = (unsigned char*)args;
+
+ if(n <= 0)
+ { for(; *s != 0; s += s[1] ? 2 : 1)
+ h = (h + (s[0]<<8) + s[1])*DT_PRIME;
+ n = s - (unsigned char*)args;
+ }
+ else
+ { unsigned char* ends;
+ for(ends = s+n-1; s < ends; s += 2)
+ h = (h + (s[0]<<8) + s[1])*DT_PRIME;
+ if(s <= ends)
+ h = (h + (s[0]<<8))*DT_PRIME;
+ }
+ return (h+n)*DT_PRIME;
+}
diff --git a/src/lib/libast/cdt/dttree.c b/src/lib/libast/cdt/dttree.c
new file mode 100644
index 0000000..2dd31d3
--- /dev/null
+++ b/src/lib/libast/cdt/dttree.c
@@ -0,0 +1,696 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Ordered set/multiset
+** dt: dictionary being searched
+** obj: the object to look for.
+** type: search type.
+**
+** Written by Kiem-Phong Vo (5/25/96)
+*/
+
+typedef struct _dttree_s
+{ Dtdata_t data;
+ Dtlink_t* root; /* tree root */
+} Dttree_t;
+
+#ifdef CDT_DEBUG
+int dttreeprint(Dt_t* dt, Dtlink_t* here, int lev, char* (*objprintf)(Void_t*) )
+{
+ int k, rv;
+ char *obj, *endb, buf[1024];
+ Dtdisc_t *disc = dt->disc;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ if(!here && !(here = tree->root) )
+ return -1;
+
+ endb = buf; /* indentation */
+ for(k = 0; k < lev; ++k)
+ { *endb++ = ' '; *endb++ = ' '; }
+
+ *endb++ = '(';
+ obj = (*objprintf)(_DTOBJ(disc, here));
+ k = strlen(obj); memcpy(endb, obj, k); endb += k;
+ *endb++ = ')';
+ *endb++ = ':';
+ *endb++ = ' ';
+
+ *endb++ = '<';
+ if(here->_left)
+ obj = (*objprintf)(_DTOBJ(disc,here->_left));
+ else obj = "NIL";
+ k = strlen(obj); memcpy(endb, obj, k); endb += k;
+ *endb++ = '>';
+ *endb++ = ' ';
+
+ *endb++ = '<';
+ if(here->_rght)
+ obj = (*objprintf)(_DTOBJ(disc,here->_rght));
+ else obj = "NIL";
+ k = strlen(obj); memcpy(endb, obj, k); endb += k;
+ *endb++ = '>';
+ *endb++ = '\n';
+ write(2, buf, endb-buf);
+
+ if(here->_left)
+ dttreeprint(dt, here->_left, lev+1, objprintf);
+ if(here->_rght)
+ dttreeprint(dt, here->_rght, lev+1, objprintf);
+
+ return 0;
+}
+#endif
+
+/* terminal object: DT_FIRST|DT_LAST */
+#if __STD_C
+Void_t* tfirstlast(Dt_t* dt, int type)
+#else
+Void_t* tfirstlast(dt, type)
+Dt_t* dt;
+int type;
+#endif
+{
+ Dtlink_t *t, *root;
+ Dtdisc_t *disc = dt->disc;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ if(!(root = tree->root) )
+ return NIL(Void_t*);
+
+ if(type&DT_LAST)
+ { while((t = root->_rght) )
+ LROTATE(root,t);
+ }
+ else /* type&DT_FIRST */
+ { while((t = root->_left) )
+ RROTATE(root,t);
+ }
+ tree->root = root;
+
+ return _DTOBJ(disc, root);
+}
+
+/* DT_CLEAR */
+#if __STD_C
+static Void_t* tclear(Dt_t* dt)
+#else
+static Void_t* tclear(dt)
+Dt_t* dt;
+#endif
+{
+ Dtlink_t *root, *t;
+ Dtdisc_t *disc = dt->disc;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ root = tree->root;
+ tree->root = NIL(Dtlink_t*);
+ tree->data.size = 0;
+
+ if(root && (disc->link < 0 || disc->freef) )
+ { do
+ { while((t = root->_left) )
+ RROTATE(root,t);
+ t = root->_rght;
+ _dtfree(dt, root, DT_DELETE);
+ } while((root = t) );
+ }
+
+ return NIL(Void_t*);
+}
+
+#if __STD_C
+static Void_t* tlist(Dt_t* dt, Dtlink_t* list, int type)
+#else
+static Void_t* tlist(dt, list, type)
+Dt_t* dt;
+Dtlink_t* list;
+int type;
+#endif
+{
+ Void_t *obj;
+ Dtlink_t *last, *r, *t;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+ Dtdisc_t *disc = dt->disc;
+
+ if(type&(DT_FLATTEN|DT_EXTRACT) )
+ { if((list = tree->root) )
+ { while((t = list->_left) ) /* make smallest object root */
+ RROTATE(list, t);
+ for(r = (last = list)->_rght; r; r = (last = r)->_rght)
+ { while((t = r->_left) ) /* no left children */
+ RROTATE(r,t);
+ last->_rght = r;
+ }
+ }
+
+ if(type&DT_FLATTEN)
+ tree->root = list;
+ else
+ { tree->root = NIL(Dtlink_t*);
+ dt->data->size = 0;
+ }
+ }
+ else /* if(type&DT_RESTORE) */
+ { dt->data->size = 0;
+ for(r = list; r; r = t)
+ { t = r->_rght;
+ obj = _DTOBJ(disc,r);
+ if((*dt->meth->searchf)(dt, (Void_t*)r, DT_RELINK) == obj )
+ dt->data->size += 1;
+ }
+ }
+
+ return (Void_t*)list;
+}
+
+#if __STD_C /* compute tree depth and number of nodes */
+static ssize_t tsize(Dtlink_t* root, ssize_t lev, Dtstat_t* st)
+#else
+static ssize_t tsize(root, lev, st)
+Dtlink_t* root;
+ssize_t lev;
+Dtstat_t* st;
+#endif
+{
+ ssize_t size, z;
+
+ if(!root) /* nothing to do */
+ return 0;
+
+ if(lev >= DT_MAXRECURSE) /* avoid blowing the stack */
+ return -1;
+
+ if(st)
+ { st->mlev = lev > st->mlev ? lev : st->mlev;
+ if(lev < DT_MAXSIZE)
+ { st->msize = lev > st->msize ? lev : st->msize;
+ st->lsize[lev] += 1; /* count #objects per level */
+ }
+ }
+
+ size = 1;
+
+ if((z = tsize(root->_left, lev+1, st)) < 0)
+ return -1;
+ else size += z;
+
+ if((z = tsize(root->_rght, lev+1, st)) < 0)
+ return -1;
+ else size += z;
+
+ return size;
+}
+
+#if __STD_C
+static Void_t* tstat(Dt_t* dt, Dtstat_t* st)
+#else
+static Void_t* tstat(dt, st)
+Dt_t* dt;
+Dtstat_t* st;
+#endif
+{
+ ssize_t size;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ if(!st)
+ return (Void_t*)dt->data->size;
+ else
+ { memset(st, 0, sizeof(Dtstat_t));
+ size = tsize(tree->root, 0, st);
+ /**/DEBUG_ASSERT((dt->data->type&DT_SHARE) || size == dt->data->size);
+ st->meth = dt->meth->type;
+ st->size = size;
+ st->space = sizeof(Dttree_t) + (dt->disc->link >= 0 ? 0 : size*sizeof(Dthold_t));
+ return (Void_t*)size;
+ }
+}
+
+#if __STD_C /* make a list into a balanced tree */
+static Dtlink_t* tbalance(Dtlink_t* list, ssize_t size)
+#else
+static Dtlink_t* tbalance(list, size)
+Dtlink_t* list;
+ssize_t size;
+#endif
+{
+ ssize_t n;
+ Dtlink_t *l, *mid;
+
+ if(size <= 2)
+ return list;
+
+ for(l = list, n = size/2 - 1; n > 0; n -= 1)
+ l = l->_rght;
+
+ mid = l->_rght; l->_rght = NIL(Dtlink_t*);
+ mid->_left = tbalance(list, (n = size/2) );
+ mid->_rght = tbalance(mid->_rght, size - (n + 1));
+ return mid;
+}
+
+static void toptimize(Dt_t* dt)
+{
+ ssize_t size;
+ Dtlink_t *l, *list;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ if((list = (Dtlink_t*)tlist(dt, NIL(Void_t*), DT_FLATTEN)) )
+ { for(size = 0, l = list; l; l = l->_rght)
+ size += 1;
+ tree->root = tbalance(list, size);
+ }
+}
+
+static Dtlink_t* troot(Dt_t* dt, Dtlink_t* list, Dtlink_t* link, Void_t* obj, int type)
+{
+ Dtlink_t *root, *last, *t, *r, *l;
+ Void_t *key, *o, *k;
+ Dtdisc_t *disc = dt->disc;
+
+ key = _DTKEY(disc, obj); /* key of object */
+
+ if(type&(DT_ATMOST|DT_ATLEAST) ) /* find the left-most or right-most element */
+ { list->_left = link->_rght;
+ list->_rght = link->_left;
+ if(type&DT_ATMOST)
+ { while((l = list->_left) )
+ { while((r = l->_rght) ) /* get the max elt of left subtree */
+ LROTATE(l,r);
+ list->_left = l;
+
+ o = _DTOBJ(disc,l); k = _DTKEY(disc,o);
+ if(_DTCMP(dt, key, k, disc) != 0 )
+ break;
+ else RROTATE(list,l);
+ }
+ }
+ else
+ { while((r = list->_rght) )
+ { while((l = r->_left) ) /* get the min elt of right subtree */
+ RROTATE(r,l);
+ list->_rght = r;
+
+ o = _DTOBJ(disc,r); k = _DTKEY(disc,o);
+ if(_DTCMP(dt, key, k, disc) != 0 )
+ break;
+ else LROTATE(list,r);
+ }
+ }
+ link->_rght = list->_left;
+ link->_left = list->_rght;
+ return list;
+ }
+
+ last = list; list->_left = list->_rght = NIL(Dtlink_t*);
+ root = NIL(Dtlink_t*);
+
+ while(!root && (t = link->_rght) ) /* link->_rght is the left subtree <= obj */
+ { while((r = t->_rght) ) /* make t the maximum element */
+ LROTATE(t,r);
+
+ o = _DTOBJ(disc,t); k = _DTKEY(disc,o);
+ if(_DTCMP(dt, key, k, disc) != 0 )
+ { link->_rght = t; /* no more of this group in subtree */
+ break;
+ }
+ else if((type & (DT_REMOVE|DT_NEXT|DT_PREV)) && o == obj)
+ { link->_rght = t->_left; /* found the exact object */
+ root = t;
+ }
+ else /* add t to equal list in an order-preserving manner */
+ { link->_rght = t->_left;
+ t->_left = t->_rght = NIL(Dtlink_t*);
+ if(type&DT_NEXT )
+ { last->_left = t; last = t; }
+ else { t->_rght = list; list = t; }
+ }
+ }
+
+ while(!root && (t = link->_left) ) /* link->_left is the right subtree >= obj */
+ { while((l = t->_left) ) /* make t the minimum element */
+ RROTATE(t,l);
+
+ o = _DTOBJ(disc,t); k = _DTKEY(disc,o);
+ if(_DTCMP(dt, key, k, disc) != 0 )
+ { link->_left = t; /* no more of this group in subtree */
+ break;
+ }
+ else if((type & (DT_REMOVE|DT_NEXT|DT_PREV)) && o == obj)
+ { link->_left = t->_rght; /* found the exact object */
+ root = t;
+ }
+ else /* add t to equal list in an order-preserving manner */
+ { link->_left = t->_rght;
+ t->_left = t->_rght = NIL(Dtlink_t*);
+ if(type&DT_NEXT )
+ { t->_left = list; list = t; }
+ else { last->_rght = t; last = t; }
+ }
+ }
+
+ if(!root) /* always set a non-trivial root */
+ { root = list;
+ if(type&DT_NEXT)
+ list = list->_left;
+ else list = list->_rght;
+ }
+
+ if(list) /* add the rest of the equal-list to the proper subtree */
+ { if(type&DT_NEXT)
+ { last->_left = link->_rght;
+ link->_rght = list;
+ }
+ else
+ { last->_rght = link->_left;
+ link->_left = list;
+ }
+ }
+
+ return root;
+}
+
+#if __STD_C
+static Void_t* dttree(Dt_t* dt, Void_t* obj, int type)
+#else
+static Void_t* dttree(dt,obj,type)
+Dt_t* dt;
+Void_t* obj;
+int type;
+#endif
+{
+ int cmp;
+ Void_t *o, *k, *key;
+ Dtlink_t *root, *t, *l, *r, *me, link;
+ Dtdisc_t *disc = dt->disc;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ type = DTTYPE(dt, type); /* map type for upward compatibility */
+ if(!(type&DT_OPERATIONS) )
+ return NIL(Void_t*);
+
+ DTSETLOCK(dt);
+
+ if(type&(DT_FIRST|DT_LAST) )
+ DTRETURN(obj, tfirstlast(dt, type));
+ else if(type&(DT_EXTRACT|DT_RESTORE|DT_FLATTEN))
+ DTRETURN(obj, tlist(dt, (Dtlink_t*)obj, type));
+ else if(type&DT_CLEAR)
+ DTRETURN(obj, tclear(dt));
+ else if(type&DT_STAT)
+ { toptimize(dt); /* balance tree to avoid deep recursion */
+ DTRETURN(obj, tstat(dt, (Dtstat_t*)obj));
+ }
+
+ if(!obj) /* from here on, an object prototype is required */
+ DTRETURN(obj, NIL(Void_t*));
+
+ if(type&DT_RELINK) /* relinking objects after some processing */
+ { me = (Dtlink_t*)obj;
+ obj = _DTOBJ(disc,me);
+ key = _DTKEY(disc,obj);
+ }
+ else
+ { me = NIL(Dtlink_t*);
+ if(type&DT_MATCH) /* no prototype object given, just the key */
+ { key = obj;
+ obj = NIL(Void_t*);
+ }
+ else key = _DTKEY(disc,obj); /* get key from prototype object */
+ }
+
+ memset(&link, 0, sizeof(link));
+ l = r = &link; /* link._rght(_left) will be LEFT(RIGHT) tree after splaying */
+ if((root = tree->root) && _DTOBJ(disc,root) != obj) /* splay-search for a matching object */
+ { while(1)
+ { o = _DTOBJ(disc,root); k = _DTKEY(disc,o);
+ if((cmp = _DTCMP(dt,key,k,disc)) == 0)
+ break;
+ else if(cmp < 0)
+ { if((t = root->_left) )
+ { o = _DTOBJ(disc,t); k = _DTKEY(disc,o);
+ if((cmp = _DTCMP(dt,key,k,disc)) < 0)
+ { rrotate(root,t);
+ rlink(r,t);
+ if(!(root = t->_left) )
+ break;
+ }
+ else if(cmp == 0)
+ { rlink(r,root);
+ root = t;
+ break;
+ }
+ else /* if(cmp > 0) */
+ { llink(l,t);
+ rlink(r,root);
+ if(!(root = t->_rght) )
+ break;
+ }
+ }
+ else
+ { rlink(r,root);
+ root = NIL(Dtlink_t*);
+ break;
+ }
+ }
+ else /* if(cmp > 0) */
+ { if((t = root->_rght) )
+ { o = _DTOBJ(disc,t); k = _DTKEY(disc,o);
+ if((cmp = _DTCMP(dt,key,k,disc)) > 0)
+ { lrotate(root,t);
+ llink(l,t);
+ if(!(root = t->_rght) )
+ break;
+ }
+ else if(cmp == 0)
+ { llink(l,root);
+ root = t;
+ break;
+ }
+ else /* if(cmp < 0) */
+ { rlink(r,t);
+ llink(l,root);
+ if(!(root = t->_left) )
+ break;
+ }
+ }
+ else
+ { llink(l,root);
+ root = NIL(Dtlink_t*);
+ break;
+ }
+ }
+ }
+ }
+ l->_rght = root ? root->_left : NIL(Dtlink_t*);
+ r->_left = root ? root->_rght : NIL(Dtlink_t*);
+
+ if(root)
+ { if(dt->meth->type&DT_OBAG ) /* may need to reset root to the right object */
+ { if((type&(DT_ATLEAST|DT_ATMOST)) ||
+ ((type&(DT_NEXT|DT_PREV|DT_REMOVE)) && _DTOBJ(disc,root) != obj) )
+ root = troot(dt, root, &link, obj, type);
+ }
+
+ if(type&(DT_SEARCH|DT_MATCH|DT_ATMOST|DT_ATLEAST))
+ { has_root: /* reconstitute the tree */
+ root->_left = link._rght;
+ root->_rght = link._left;
+ tree->root = root;
+ DTRETURN(obj, _DTOBJ(disc,root));
+ }
+ else if(type&DT_NEXT)
+ { root->_left = link._rght;
+ root->_rght = NIL(Dtlink_t*);
+ link._rght = root;
+ dt_next:
+ if((root = link._left) )
+ { while((t = root->_left) )
+ RROTATE(root,t);
+ link._left = root->_rght;
+ goto has_root;
+ }
+ else goto no_root;
+ }
+ else if(type&DT_PREV)
+ { root->_rght = link._left;
+ root->_left = NIL(Dtlink_t*);
+ link._left = root;
+ dt_prev:
+ if((root = link._rght) )
+ { while((t = root->_rght) )
+ LROTATE(root,t);
+ link._rght = root->_left;
+ goto has_root;
+ }
+ else goto no_root;
+ }
+ else if(type&DT_REMOVE) /* remove a particular element in the tree */
+ { if(_DTOBJ(disc,root) == obj)
+ goto dt_delete;
+ else
+ { root->_left = link._rght;
+ root->_rght = link._left;
+ tree->root = root;
+ DTRETURN(obj, NIL(Void_t*));
+ }
+ }
+ else if(type&(DT_DELETE|DT_DETACH))
+ { dt_delete: /* remove an object from the dictionary */
+ obj = _DTOBJ(disc,root);
+ _dtfree(dt, root, type);
+ dt->data->size -= 1;
+ goto no_root;
+ }
+ else if(type&(DT_INSERT|DT_APPEND|DT_ATTACH))
+ { if(dt->meth->type&DT_OSET)
+ { type |= DT_SEARCH; /* for announcement */
+ goto has_root;
+ }
+ else
+ { root->_left = NIL(Dtlink_t*);
+ root->_rght = link._left;
+ link._left = root;
+ goto dt_insert;
+ }
+ }
+ else if(type&DT_RELINK) /* a duplicate */
+ { if(dt->meth->type&DT_OSET)
+ _dtfree(dt, me, DT_DELETE);
+ else
+ { me->_left = NIL(Dtlink_t*);
+ me->_rght = link._left;
+ link._left = me;
+ }
+ goto has_root;
+ }
+ }
+ else /* no matching object, tree has been split to LEFT&RIGHT subtrees */
+ { if(type&(DT_SEARCH|DT_MATCH))
+ { no_root:
+ if(!(l = link._rght) ) /* no LEFT subtree */
+ tree->root = link._left; /* tree is RIGHT tree */
+ else
+ { while((t = l->_rght) ) /* maximize root of LEFT tree */
+ { if(t->_rght)
+ LLSHIFT(l,t);
+ else LROTATE(l,t);
+ }
+ l->_rght = link._left; /* hook RIGHT tree to LEFT root */
+ tree->root = l; /* LEFT tree is now the entire tree */
+ }
+
+ if(type&(DT_DELETE|DT_DETACH|DT_REMOVE))
+ DTRETURN(obj, obj);
+ else DTRETURN(obj, NIL(Void_t*));
+ }
+ else if(type&(DT_NEXT|DT_ATLEAST) )
+ goto dt_next;
+ else if(type&(DT_PREV|DT_ATMOST) )
+ goto dt_prev;
+ else if(type&(DT_DELETE|DT_DETACH|DT_REMOVE))
+ { obj = NIL(Void_t*);
+ goto no_root;
+ }
+ else if(type&(DT_INSERT|DT_APPEND|DT_ATTACH))
+ { dt_insert:
+ if(!(root = _dtmake(dt, obj, type)) )
+ { obj = NIL(Void_t*);
+ goto no_root;
+ }
+ else
+ { dt->data->size += 1;
+ goto has_root;
+ }
+ }
+ else if(type&DT_RELINK)
+ { root = me;
+ goto has_root;
+ }
+ }
+ DTRETURN(obj, NIL(Void_t*));
+
+dt_return:
+ DTANNOUNCE(dt,obj,type);
+ DTCLRLOCK(dt);
+ return obj;
+}
+
+static int treeevent(Dt_t* dt, int event, Void_t* arg)
+{
+ Dtlink_t *l, *list;
+ ssize_t size;
+ Dttree_t *tree = (Dttree_t*)dt->data;
+
+ if(event == DT_OPEN)
+ { if(tree) /* already initialized */
+ return 0;
+ if(!(tree = (Dttree_t*)(*dt->memoryf)(dt, 0, sizeof(Dttree_t), dt->disc)) )
+ { DTERROR(dt, "Error in allocating a tree data structure");
+ return -1;
+ }
+ memset(tree, 0, sizeof(Dttree_t));
+ dt->data = (Dtdata_t*)tree;
+ return 1;
+ }
+ else if(event == DT_CLOSE)
+ { if(!tree)
+ return 0;
+ if(tree->root)
+ (void)tclear(dt);
+ (void)(*dt->memoryf)(dt, (Void_t*)tree, 0, dt->disc);
+ dt->data = NIL(Dtdata_t*);
+ return 0;
+ }
+ else if(event == DT_OPTIMIZE) /* balance the search tree */
+ { toptimize(dt);
+ return 0;
+ }
+ else return 0;
+}
+
+#if _UWIN
+
+Void_t* dtfinger(Dt_t* dt)
+{
+ return (dt && dt->meth && (dt->meth->type & DT_ORDERED)) ? (Void_t*)((Dttree_t*)dt->data)->root : NIL(Void_t*);
+}
+
+#endif
+
+/* make this method available */
+static Dtmethod_t _Dtoset = { dttree, DT_OSET, treeevent, "Dtoset" };
+static Dtmethod_t _Dtobag = { dttree, DT_OBAG, treeevent, "Dtobag" };
+__DEFINE__(Dtmethod_t*,Dtoset,&_Dtoset);
+__DEFINE__(Dtmethod_t*,Dtobag,&_Dtobag);
+
+/* backwards compatibility */
+#undef Dttree
+#if defined(__EXPORT__)
+__EXPORT__
+#endif
+__DEFINE__(Dtmethod_t*,Dttree,&_Dtoset);
+
+#ifdef NoF
+NoF(dttree)
+#endif
diff --git a/src/lib/libast/cdt/dtview.c b/src/lib/libast/cdt/dtview.c
new file mode 100644
index 0000000..94f4a54
--- /dev/null
+++ b/src/lib/libast/cdt/dtview.c
@@ -0,0 +1,157 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Set a view path from dict to view.
+**
+** Written by Kiem-Phong Vo (5/25/96)
+*/
+
+/* these operations must be done without viewpathing */
+#define DT_NOVIEWPATH (DT_INSERT|DT_APPEND|DT_DELETE|\
+ DT_ATTACH|DT_DETACH|DT_RELINK|DT_CLEAR| \
+ DT_FLATTEN|DT_EXTRACT|DT_RESTORE|DT_STAT)
+
+#if __STD_C
+static Void_t* dtvsearch(Dt_t* dt, reg Void_t* obj, reg int type)
+#else
+static Void_t* dtvsearch(dt,obj,type)
+Dt_t* dt;
+reg Void_t* obj;
+reg int type;
+#endif
+{
+ int cmp;
+ Dt_t *d, *p;
+ Void_t *o, *n, *oky, *nky;
+
+ if(type&DT_NOVIEWPATH)
+ return (*(dt->meth->searchf))(dt,obj,type);
+
+ o = NIL(Void_t*);
+
+ /* these ops look for the first appearance of an object of the right type */
+ if((type & (DT_MATCH|DT_SEARCH)) ||
+ ((type & (DT_FIRST|DT_LAST|DT_ATLEAST|DT_ATMOST)) && !(dt->meth->type&DT_ORDERED) ) )
+ { for(d = dt; d; d = d->view)
+ if((o = (*(d->meth->searchf))(d,obj,type)) )
+ break;
+ dt->walk = d;
+ return o;
+ }
+
+ if(dt->meth->type & DT_ORDERED) /* ordered sets/bags */
+ { if(!(type & (DT_FIRST|DT_LAST|DT_NEXT|DT_PREV|DT_ATLEAST|DT_ATMOST)) )
+ return NIL(Void_t*);
+
+ /* find the min/max element that satisfies the op requirement */
+ n = nky = NIL(Void_t*); p = NIL(Dt_t*);
+ for(d = dt; d; d = d->view)
+ { if(!(o = (*d->meth->searchf)(d, obj, type)) )
+ continue;
+ oky = _DTKEY(d->disc,o);
+
+ if(n) /* get the right one among all dictionaries */
+ { cmp = _DTCMP(d,oky,nky,d->disc);
+ if(((type & (DT_NEXT|DT_FIRST|DT_ATLEAST)) && cmp < 0) ||
+ ((type & (DT_PREV|DT_LAST|DT_ATMOST)) && cmp > 0) )
+ goto b_est;
+ }
+ else
+ { b_est: /* current best element to fit op requirement */
+ p = d;
+ n = o;
+ nky = oky;
+ }
+ }
+
+ dt->walk = p;
+ return n;
+ }
+
+ /* unordered collections */
+ if(!(type&(DT_NEXT|DT_PREV)) )
+ return NIL(Void_t*);
+
+ if(!dt->walk )
+ { for(d = dt; d; d = d->view)
+ if((o = (*(d->meth->searchf))(d, obj, DT_SEARCH)) )
+ break;
+ dt->walk = d;
+ if(!(obj = o) )
+ return NIL(Void_t*);
+ }
+
+ for(d = dt->walk, obj = (*d->meth->searchf)(d, obj, type);; )
+ { while(obj) /* keep moving until finding an uncovered object */
+ { for(p = dt; ; p = p->view)
+ { if(p == d) /* adjacent object is uncovered */
+ return obj;
+ if((*(p->meth->searchf))(p, obj, DT_SEARCH) )
+ break;
+ }
+ obj = (*d->meth->searchf)(d, obj, type);
+ }
+
+ if(!(d = dt->walk = d->view) ) /* move on to next dictionary */
+ return NIL(Void_t*);
+ else if(type&DT_NEXT)
+ obj = (*(d->meth->searchf))(d,NIL(Void_t*),DT_FIRST);
+ else obj = (*(d->meth->searchf))(d,NIL(Void_t*),DT_LAST);
+ }
+}
+
+#if __STD_C
+Dt_t* dtview(reg Dt_t* dt, reg Dt_t* view)
+#else
+Dt_t* dtview(dt,view)
+reg Dt_t* dt;
+reg Dt_t* view;
+#endif
+{
+ reg Dt_t* d;
+
+ if(view && view->meth != dt->meth) /* must use the same method */
+ return NIL(Dt_t*);
+
+ /* make sure there won't be a cycle */
+ for(d = view; d; d = d->view)
+ if(d == dt)
+ return NIL(Dt_t*);
+
+ /* no more viewing lower dictionary */
+ if((d = dt->view) )
+ d->nview -= 1;
+ dt->view = dt->walk = NIL(Dt_t*);
+
+ if(!view)
+ { dt->searchf = dt->meth->searchf;
+ return d;
+ }
+
+ /* ok */
+ dt->view = view;
+ dt->searchf = dtvsearch;
+ view->nview += 1;
+
+ return view;
+}
diff --git a/src/lib/libast/cdt/dtwalk.c b/src/lib/libast/cdt/dtwalk.c
new file mode 100644
index 0000000..05c706c
--- /dev/null
+++ b/src/lib/libast/cdt/dtwalk.c
@@ -0,0 +1,53 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "dthdr.h"
+
+/* Walk a dictionary and all dictionaries viewed through it.
+** userf: user function
+**
+** Written by Kiem-Phong Vo (5/25/96)
+*/
+
+#if __STD_C
+int dtwalk(Dt_t* dt, int (*userf)(Dt_t*, Void_t*, Void_t*), Void_t* data)
+#else
+int dtwalk(dt,userf,data)
+Dt_t* dt;
+int(* userf)();
+Void_t* data;
+#endif
+{
+ Void_t *obj, *next;
+ Dt_t *walk;
+ int rv;
+
+ for(obj = dtfirst(dt); obj; )
+ { if(!(walk = dt->walk) )
+ walk = dt;
+ next = dtnext(dt,obj);
+ if((rv = (*userf)(walk, obj, data )) < 0)
+ return rv;
+ obj = next;
+ }
+
+ return 0;
+}
diff --git a/src/lib/libast/comp/atexit.c b/src/lib/libast/comp/atexit.c
new file mode 100644
index 0000000..d0df2d5
--- /dev/null
+++ b/src/lib/libast/comp/atexit.c
@@ -0,0 +1,115 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * ANSI C atexit()
+ * arrange for func to be called LIFO on exit()
+ */
+
+#include <ast.h>
+
+#if _lib_atexit
+
+NoN(atexit)
+
+#else
+
+#if _lib_onexit || _lib_on_exit
+
+#if !_lib_onexit
+#define onexit on_exit
+#endif
+
+extern int onexit(void(*)(void));
+
+int
+atexit(void (*func)(void))
+{
+ return(onexit(func));
+}
+
+#else
+
+struct list
+{
+ struct list* next;
+ void (*func)(void);
+};
+
+static struct list* funclist;
+
+extern void _exit(int);
+
+int
+atexit(void (*func)(void))
+{
+ register struct list* p;
+
+ if (!(p = newof(0, struct list, 1, 0))) return(-1);
+ p->func = func;
+ p->next = funclist;
+ funclist = p;
+ return(0);
+}
+
+void
+_ast_atexit(void)
+{
+ register struct list* p;
+
+ while (p = funclist)
+ {
+ funclist = p->next;
+ (*p->func)();
+ }
+}
+
+#if _std_cleanup
+
+#if _lib__cleanup
+extern void _cleanup(void);
+#endif
+
+void
+exit(int code)
+{
+ _ast_atexit();
+#if _lib__cleanup
+ _cleanup();
+#endif
+ _exit(code);
+}
+
+#else
+
+void
+_cleanup(void)
+{
+ _ast_atexit();
+}
+
+#endif
+
+#endif
+
+#endif
diff --git a/src/lib/libast/comp/basename.c b/src/lib/libast/comp/basename.c
new file mode 100644
index 0000000..912f8d6
--- /dev/null
+++ b/src/lib/libast/comp/basename.c
@@ -0,0 +1,55 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * basename(3) implementation
+ */
+
+#include <ast_std.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char *basename(register char *pathname)
+{
+ register char *first, *last;
+ for(first=last=pathname; *last; last++);
+ /* back over trailing '/' */
+ if(last>first)
+ while(*--last=='/' && last > first);
+ if(last==first && *last=='/')
+ {
+ /* all '/' or "" */
+ if(*first=='/')
+ if(*++last=='/') /* keep leading // */
+ last++;
+ }
+ else
+ {
+ for(first=last++;first>pathname && *first!='/';first--);
+ if(*first=='/')
+ first++;
+ }
+ *last = 0;
+ return(first);
+}
diff --git a/src/lib/libast/comp/catopen.c b/src/lib/libast/comp/catopen.c
new file mode 100644
index 0000000..7bace39
--- /dev/null
+++ b/src/lib/libast/comp/catopen.c
@@ -0,0 +1,182 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * catopen intercept
+ * the ast catalogs are checked first
+ * the ast mc* and native cat* routines do all the work
+ * catalogs found by mcfind() are converted from utf to ucs
+ *
+ * nl_catd is cast to void*
+ * this is either an Mc_t* (Mc_t.set != 0)
+ * or a Cc_t* where Cc_t.cat is the native nl_catd
+ */
+
+#include <ast.h>
+#include <mc.h>
+#include <nl_types.h>
+#include <iconv.h>
+
+#ifndef DEBUG_trace
+#define DEBUG_trace 0
+#endif
+#if DEBUG_trace
+#undef setlocale
+#endif
+
+#if _lib_catopen
+
+#undef nl_catd
+#undef catopen
+#undef catgets
+#undef catclose
+
+typedef struct
+{
+ Mcset_t* set;
+ nl_catd cat;
+ iconv_t cvt;
+ Sfio_t* tmp;
+} Cc_t;
+
+#else
+
+#define _ast_nl_catd nl_catd
+#define _ast_catopen catopen
+#define _ast_catgets catgets
+#define _ast_catclose catclose
+
+#endif
+
+_ast_nl_catd
+_ast_catopen(const char* name, int flag)
+{
+ Mc_t* mc;
+ char* s;
+ Sfio_t* ip;
+ char path[PATH_MAX];
+
+ /*
+ * first try the ast catalogs
+ */
+
+#if DEBUG_trace
+sfprintf(sfstderr, "AHA#%d:%s %s LC_MESSAGES=%s:%s\n", __LINE__, __FILE__, name, _ast_setlocale(LC_MESSAGES, 0), setlocale(LC_MESSAGES, 0));
+#endif
+ if ((s = mcfind(NiL, name, LC_MESSAGES, flag, path, sizeof(path))) && (ip = sfopen(NiL, s, "r")))
+ {
+#if DEBUG_trace
+sfprintf(sfstderr, "AHA#%d:%s %s\n", __LINE__, __FILE__, s);
+#endif
+ mc = mcopen(ip);
+ sfclose(ip);
+ if (mc)
+ return (_ast_nl_catd)mc;
+ }
+#if _lib_catopen
+ if (strcmp(setlocale(LC_MESSAGES, NiL), "debug"))
+ {
+ Cc_t* cc;
+ nl_catd d;
+
+ /*
+ * now the native catalogs
+ */
+
+ if (s && (d = catopen(s, flag)) != (nl_catd)(-1) || !(s = 0) && (d = catopen(name, flag)) != (nl_catd)(-1))
+ {
+ if (!(cc = newof(0, Cc_t, 1, 0)))
+ {
+ catclose(d);
+ return (_ast_nl_catd)(-1);
+ }
+ cc->cat = d;
+ if ((s || *name == '/') && (ast.locale.set & (1<<AST_LC_MESSAGES)))
+ {
+ if ((cc->cvt = iconv_open("", "utf")) == (iconv_t)(-1) || !(cc->tmp = sfstropen()))
+ {
+ catclose(d);
+ free(cc);
+ return (_ast_nl_catd)(-1);
+ }
+ }
+ else
+ cc->cvt = (iconv_t)(-1);
+#if DEBUG_trace
+sfprintf(sfstderr, "AHA#%d:%s %s %s native %p\n", __LINE__, __FILE__, s, name, cc->cat);
+#endif
+ return (_ast_nl_catd)cc;
+ }
+ }
+#endif
+
+ /*
+ * loser
+ */
+
+ return (_ast_nl_catd)(-1);
+}
+
+char*
+_ast_catgets(_ast_nl_catd cat, int set, int num, const char* msg)
+{
+ if (cat == (_ast_nl_catd)(-1))
+ return (char*)msg;
+#if _lib_catopen
+ if (!((Cc_t*)cat)->set)
+ {
+ char* s;
+ size_t n;
+
+ msg = (char*)catgets(((Cc_t*)cat)->cat, set, num, msg);
+ if (((Cc_t*)cat)->cvt != (iconv_t)(-1))
+ {
+ s = (char*)msg;
+ n = strlen(s);
+ iconv_write(((Cc_t*)cat)->cvt, ((Cc_t*)cat)->tmp, &s, &n, NiL);
+ if (s = sfstruse(((Cc_t*)cat)->tmp))
+ return s;
+ }
+ return (char*)msg;
+ }
+#endif
+ return mcget((Mc_t*)cat, set, num, msg);
+}
+
+int
+_ast_catclose(_ast_nl_catd cat)
+{
+ if (cat == (_ast_nl_catd)(-1))
+ return -1;
+#if _lib_catopen
+ if (!((Cc_t*)cat)->set)
+ {
+ if (((Cc_t*)cat)->cvt != (iconv_t)(-1))
+ iconv_close(((Cc_t*)cat)->cvt);
+ if (((Cc_t*)cat)->tmp)
+ sfclose(((Cc_t*)cat)->tmp);
+ return catclose(((Cc_t*)cat)->cat);
+ }
+#endif
+ return mcclose((Mc_t*)cat);
+}
diff --git a/src/lib/libast/comp/closelog.c b/src/lib/libast/comp/closelog.c
new file mode 100644
index 0000000..b8c848a
--- /dev/null
+++ b/src/lib/libast/comp/closelog.c
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * closelog implementation
+ */
+
+#include <ast.h>
+
+#if _lib_syslog
+
+NoN(closelog)
+
+#else
+
+#include "sysloglib.h"
+
+void
+closelog(void)
+{
+ if (log.fd >= 0)
+ {
+ close(log.fd);
+ log.fd = -1;
+ }
+ log.facility = 0;
+ log.flags = 0;
+ log.mask = ~0;
+ log.attempt = 0;
+}
+
+#endif
diff --git a/src/lib/libast/comp/conf.sh b/src/lib/libast/comp/conf.sh
new file mode 100644
index 0000000..aaf3f3a
--- /dev/null
+++ b/src/lib/libast/comp/conf.sh
@@ -0,0 +1,1635 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1985-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# David Korn <dgk@research.att.com> #
+# Phong Vo <kpv@research.att.com> #
+# #
+########################################################################
+: generate getconf and limits info
+#
+# @(#)conf.sh (AT&T Research) 2011-08-26
+#
+# this script generates these files from the table file in the first arg
+# the remaining args are the C compiler name and flags
+#
+# conflim.h supplemental limits.h definitions
+# conftab.h readonly string table definitions
+# conftab.c readonly string table data
+#
+# you may think it should be simpler
+# but you shall be confused anyway
+#
+
+case $-:$BASH_VERSION in
+*x*:[0123456789]*) : bash set -x is broken :; set +ex ;;
+esac
+
+LC_ALL=C
+export LC_ALL
+
+command=conf
+
+shell=`eval 'x=123&&integer n=\${#x}\${x#1?}&&((n==330/(10)))&&echo ksh' 2>/dev/null`
+
+append=0
+debug=
+extra=0
+keep_call='*'
+keep_name='*'
+trace=
+verbose=0
+while :
+do case $1 in
+ -a) append=1 ;;
+ -c*) keep_call=${1#-?} ;;
+ -d*) debug=$1 ;;
+ -l) extra=1 ;;
+ -n*) keep_name=${1#-?} ;;
+ -t) trace=1 ;;
+ -v) verbose=1 ;;
+ -*) echo "Usage: $command [-a] [-ccall-pattern] [-dN] [-l] [-nname_pattern] [-t] [-v] conf.tab" >&2; exit 2 ;;
+ *) break ;;
+ esac
+ shift
+done
+head='#include "FEATURE/standards"
+#include "FEATURE/common"'
+tail='#include "FEATURE/param"'
+generated="/* : : generated by $command from $1 : : */"
+hdr=
+ifs=${IFS-'
+ '}
+nl='
+'
+sp=' '
+ob='{'
+cb='}'
+sym=[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*
+tmp=conf.tmp
+case $verbose:$debug$trace in
+1:?*) echo "$command: debug=$debug trace=$trace keep_call=$keep_call keep_name=$keep_name" >&2 ;;
+esac
+case $trace in
+1) PS4='+$LINENO+ '; set -x ;;
+esac
+
+case $# in
+0) case $extra in
+ 0) echo "$command: table argument expected" >&2
+ exit 1
+ ;;
+ esac
+ tab=/dev/null
+ ;;
+*) tab=$1
+ shift
+ if test ! -f $tab
+ then echo "$command: $tab: cannot read" >&2
+ exit 1
+ fi
+ ;;
+esac
+case $# in
+0) cc=cc ;;
+*) cc=$* ;;
+esac
+
+rm -f $tmp.*
+case $debug in
+'') trap "code=\$?; rm -f $tmp.*; exit \$code" 0 1 2 ;;
+esac
+
+# determine the intmax_t printf format
+
+cat > $tmp.c <<!
+${head}
+int
+main()
+{
+#if _ast_intmax_long
+ return 1;
+#else
+ return 0;
+#endif
+}
+!
+if $cc -o $tmp.exe $tmp.c >/dev/null 2>&1 && ./$tmp.exe
+then LL_format='ll'
+else LL_format='l'
+fi
+
+# determine the intmax_t constant suffix
+
+cat > $tmp.c <<!
+${head}
+int
+main()
+{
+#if _ast_intmax_long
+ return 1;
+#else
+ _ast_intmax_t s = 0x7fffffffffffffffLL;
+ unsigned _ast_intmax_t u = 0xffffffffffffffffLL;
+
+ return 0;
+#endif
+}
+!
+if $cc -o $tmp.exe $tmp.c >/dev/null 2>&1
+then if ./$tmp.exe
+ then LL_suffix='LL'
+ else LL_suffix='L'
+ fi
+else LL_suffix=''
+fi
+
+cat > $tmp.c <<!
+${head}
+int
+main()
+{
+ unsigned int u = 1U;
+ unsigned int ul = 1UL;
+
+ return 0;
+}
+!
+if $cc -o $tmp.exe $tmp.c >/dev/null 2>&1
+then U_suffix='U'
+else U_suffix=''
+fi
+
+# set up the names and keys
+
+keys=
+standards=
+
+case $append$extra in
+00) case $verbose in
+ 1) echo "$command: read $tab" >&2 ;;
+ esac
+ exec < $tab
+ while :
+ do IFS=""
+ read line
+ eof=$?
+ IFS=$ifs
+ case $eof in
+ 0) ;;
+ *) break ;;
+ esac
+ case $line in
+ ""|\#*) ;;
+ *) set x $line
+ shift; name=$1
+ shift; standard=$1
+ shift; call=$1
+ shift; section=$1
+ shift; flags=$1
+ alternates=
+ define=
+ values=
+ script=
+ headers=
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ ":") shift
+ eval script='$'script_$1
+ break
+ ;;
+ *"{") case $1 in
+ "sh{") script="# $name" ;;
+ *) script= ;;
+ esac
+ shift
+ args="$*"
+ IFS=""
+ while read line
+ do case $line in
+ "}") break ;;
+ esac
+ script=$script$nl$line
+ done
+ IFS=$ifs
+ break
+ ;;
+ *.h) case $shell in
+ ksh) f=${1%.h} ;;
+ *) f=`echo $1 | sed 's,\.h$,,'` ;;
+ esac
+ case " $hdr " in
+ *" $f "*)
+ headers=$headers$nl#include$sp'<'$1'>'
+ ;;
+ *" -$f- "*)
+ ;;
+ *) if iffe -n - hdr $f | grep _hdr_$f >/dev/null
+ then hdr="$hdr $f"
+ headers=$headers$nl#include$sp'<'$1'>'
+ else hdr="$hdr -$f-"
+ fi
+ ;;
+ esac
+ ;;
+ *) values=$values$sp$1
+ case $1 in
+ $sym) echo "$1" >> $tmp.v ;;
+ esac
+ ;;
+ esac
+ done
+ case " $standards " in
+ *" $standard "*)
+ ;;
+ *) standards="$standards $standard"
+ ;;
+ esac
+ case $name:$flags in
+ *:*S*) ;;
+ VERSION)flags="${flags}S" ;;
+ esac
+ case $name in
+ *VERSION*)key=${standard}${section} ;;
+ *) key= ;;
+ esac
+ case $key in
+ ''|*_) key=${key}${name} ;;
+ *) key=${key}_${name} ;;
+ esac
+ eval sys='$'CONF_call_${key}
+ case $sys in
+ ?*) call=$sys ;;
+ esac
+ case $call in
+ SI) sys=CS ;;
+ *) sys=$call ;;
+ esac
+ key=${sys}_${key}
+ keys="$keys$nl$key"
+ eval CONF_name_${key}='$'name
+ eval CONF_standard_${key}='$'standard
+ eval CONF_call_${key}='$'call
+ eval CONF_section_${key}='$'section
+ eval CONF_flags_${key}='$'flags
+ eval CONF_define_${key}='$'define
+ eval CONF_values_${key}='$'values
+ eval CONF_script_${key}='$'script
+ eval CONF_args_${key}='$'args
+ eval CONF_headers_${key}='$'headers
+ eval CONF_keys_${name}=\"'$'CONF_keys_${name} '$'key\"
+ ;;
+ esac
+ done
+ ;;
+esac
+case $debug in
+-d1) for key in $keys
+ do eval name=\"'$'CONF_name_$key\"
+ case $name in
+ ?*) eval standard=\"'$'CONF_standard_$key\"
+ eval call=\"'$'CONF_call_$key\"
+ eval section=\"'$'CONF_section_$key\"
+ eval flags=\"'$'CONF_flags_$key\"
+ eval define=\"'$'CONF_define_$key\"
+ eval values=\"'$'CONF_values_$key\"
+ eval script=\"'$'CONF_script_$key\"
+ eval args=\"'$'CONF_args_$key\"
+ eval headers=\"'$'CONF_headers_$key\"
+ printf "%29s %35s %8s %2s %1d %5s %s$nl" "$name" "$key" "$standard" "$call" "$section" "$flags" "$define${values:+$sp=$values}${headers:+$sp$headers$nl}${script:+$sp$ob$script$nl$cb}"
+ ;;
+ esac
+ done
+ exit
+ ;;
+esac
+
+systeminfo='
+#if !defined(SYS_NMLEN)
+#define SYS_NMLEN 9
+#endif
+#include <sys/systeminfo.h>'
+echo "$systeminfo" > $tmp.c
+$cc -E $tmp.c >/dev/null 2>&1 || systeminfo=
+
+# check for native getconf(1)
+
+CONF_getconf=
+CONF_getconf_a=
+for d in /usr/bin /bin /usr/sbin /sbin
+do if test -x $d/getconf
+ then case `$d/getconf --?-version 2>&1` in
+ *"AT&T"*"Research"*)
+ : presumably an implementation also configured from conf.tab
+ ;;
+ *) CONF_getconf=$d/getconf
+ if $CONF_getconf -a >/dev/null 2>&1
+ then CONF_getconf_a=-a
+ fi
+ ;;
+ esac
+ break
+ fi
+done
+export CONF_getconf CONF_getconf_a
+
+case $verbose in
+1) echo "$command: check ${CONF_getconf:+$CONF_getconf(1),}confstr(2),pathconf(2),sysconf(2),sysinfo(2) configuration names" >&2 ;;
+esac
+{
+ echo "#include <unistd.h>$systeminfo
+int i = 0;" > $tmp.c
+ $cc -E $tmp.c
+} |
+sed \
+ -e '/^#[^0123456789]*1[ ]*".*".*/!d' \
+ -e 's/^#[^0123456789]*1[ ]*"\(.*\)".*/\1/' |
+sort -u > $tmp.f
+{
+sed \
+ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]/ /g' \
+ -e 's/[ ][ ]*/\n/g' \
+ `cat $tmp.f` 2>/dev/null |
+ egrep '^(SI|_(CS|PC|SC|SI))_.'
+ case $CONF_getconf_a in
+ ?*) $CONF_getconf $CONF_getconf_a | sed 's,[=: ].*,,'
+ ;;
+ *) case $CONF_getconf in
+ ?*) for v in `strings $CONF_getconf | grep '^[ABCDEFGHIJKLMNOPQRSTUVWXYZ_][ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*$'`
+ do if $CONF_getconf $v >/dev/null
+ then echo $v
+ fi
+ done
+ ;;
+ esac
+ ;;
+ esac 2>/dev/null
+} |
+egrep -v '^_[ABCDEFGHIJKLMNOPQRSTUVWXYZ]+_(COUNT|LAST|N|STR)$' |
+sort -u > $tmp.g
+{
+ grep '^_' $tmp.g
+ grep '^[^_]' $tmp.g
+} > $tmp.t
+mv $tmp.t $tmp.g
+case $debug in
+-d2) exit ;;
+esac
+
+HOST=`package | sed -e 's,[0123456789.].*,,' | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+case $HOST in
+'') HOST=SYSTEM ;;
+esac
+
+exec < $tmp.g
+
+while read line
+do flags=F
+ section=
+ underscore=
+ define=$line
+ IFS=_
+ set $line
+ IFS=$ifs
+ case $1 in
+ '') case $# in
+ 0) continue ;;
+ esac
+ shift
+ ;;
+ esac
+ case $1 in
+ CS|PC|SC|SI)
+ call=$1
+ shift
+ standard=$1
+ ;;
+ *) flags=${flags}R
+ standard=$1
+ while :
+ do case $# in
+ 0) continue 2 ;;
+ esac
+ shift
+ case $1 in
+ CS|PC|SC|SI)
+ call=$1
+ shift
+ break
+ ;;
+ O|o|OLD|old)
+ continue 2
+ ;;
+ esac
+ standard=${standard}_$1
+ done
+ ;;
+ esac
+ case $1 in
+ SET) continue ;;
+ esac
+ case $standard in
+ _*) standard=`echo $standard | sed 's,^_*,,'` ;;
+ esac
+ case " $standards " in
+ *" $standard "*)
+ ;;
+ *) case $standard in
+ [0123456789]*)
+ section=$standard
+ standard=POSIX
+ ;;
+ *[0123456789])
+ eval `echo $standard | sed 's,\(.*\)\([0123456789]*\),standard=\1 section=\2,'`
+ ;;
+ esac
+ ;;
+ esac
+ case $flags in
+ *R*) case $call in
+ SI) ;;
+ *) underscore=U ;;
+ esac
+ ;;
+ *) case " $standards " in
+ " C ") shift
+ ;;
+ *" $standard "*)
+ case $call in
+ SI) ;;
+ *) flags=${flags}P
+ underscore=U
+ ;;
+ esac
+ shift
+ ;;
+ *) standard=
+ ;;
+ esac
+ ;;
+ esac
+ case $standard in
+ '') standard=$HOST
+ case $call in
+ SI) ;;
+ *) underscore=U ;;
+ esac
+ case $call in
+ CS|PC|SC)
+ case $define in
+ _${call}_*)
+ standard=POSIX
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ part=$section
+ case $section in
+ '') section=1
+ case $standard in
+ POSIX|XOPEN) part=$section ;;
+ esac
+ ;;
+ esac
+ name=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ case $name in
+ '') name=$1 ;;
+ *) name=${name}_$1 ;;
+ esac
+ shift
+ done
+ case $name in
+ '') ;;
+ CONFORMANCE|FS_3D|HOSTTYPE|LIBPATH|LIBPREFIX|LIBSUFFIX|PATH_ATTRIBUTES|PATH_RESOLVE|UNIVERSE)
+ ;;
+ *) values=
+ script=
+ args=
+ headers=
+ case $name in
+ V[123456789]_*|V[123456789][0123456789]_*) underscore=VW ;;
+ esac
+ case $call in
+ CS|SI) key=CS ;;
+ *) key=$call ;;
+ esac
+ case $name in
+ *VERSION*)key=${key}_${standard}${part} ;;
+ esac
+ key=${key}_${name}
+ eval x='$'CONF_keys_$name
+ case $x in
+ '') eval x='$'CONF_name_$key
+ case $x in
+ '') case $call in
+ SI) flags=O$flags ;;
+ esac
+ case $underscore in
+ ?*) flags=${flags}${underscore} ;;
+ esac
+ old=QQ
+ case $name in
+ *VERSION*)old=${old}_${standard}${part} ;;
+ esac
+ old=${old}_${name}
+ eval x='$'CONF_name_$old
+ case $x in
+ ?*) eval CONF_name_$old=
+ eval flags='$'flags'$'CONF_flags_$old
+ eval values='$'CONF_values_$old
+ eval script='$'CONF_script_$old
+ eval args='$'CONF_args_$old
+ eval headers='$'CONF_headers_$old
+ ;;
+ esac
+ keys="$keys$nl$key"
+ eval CONF_name_${key}='$'name
+ eval CONF_standard_${key}='$'standard
+ eval CONF_call_${key}='$'call
+ eval CONF_section_${key}='$'section
+ eval CONF_flags_${key}=d'$'flags
+ eval CONF_define_${key}='$'define
+ eval CONF_values_${key}='$'values
+ eval CONF_script_${key}='$'script
+ eval CONF_args_${key}='$'args
+ eval CONF_headers_${key}='$'headers
+ ;;
+ *) eval x='$'CONF_define_$key
+ case $x in
+ ?*) case $call in
+ CS) eval x='$'CONF_call_$key
+ case $x in
+ SI) ;;
+ *) define= ;;
+ esac
+ ;;
+ *) define=
+ ;;
+ esac
+ ;;
+ esac
+ case $define in
+ ?*) eval CONF_define_${key}='$'define
+ eval CONF_call_${key}='$'call
+ eval x='$'CONF_call_${key}
+ case $x in
+ QQ) ;;
+ *) case $flags in
+ *R*) flags=R ;;
+ *) flags= ;;
+ esac
+ ;;
+ esac
+ case $call in
+ SI) flags=O$flags ;;
+ esac
+ eval CONF_flags_${key}=d'$'flags'$'CONF_flags_${key}
+ ;;
+ esac
+ old=QQ
+ case $name in
+ *VERSION*)old=${old}_${standard}${part} ;;
+ esac
+ old=${old}_${name}
+ eval CONF_name_$old=
+ esac
+ ;;
+ *) for key in $x
+ do eval x='$'CONF_call_${key}
+ case $x in
+ XX) eval CONF_call_${key}=QQ
+ eval CONF_flags_${key}=S'$'CONF_flags_${key}
+ ;;
+ esac
+ done
+ esac
+ ;;
+ esac
+done
+
+# sort keys by name
+
+keys=`for key in $keys
+do eval echo '$'CONF_name_$key '$'key
+done | sort -u | sed 's,.* ,,'`
+case $debug in
+-d3) for key in $keys
+ do eval name=\"'$'CONF_name_$key\"
+ case $name in
+ ?*) eval standard=\"'$'CONF_standard_$key\"
+ eval call=\"'$'CONF_call_$key\"
+ eval section=\"'$'CONF_section_$key\"
+ eval flags=\"'$'CONF_flags_$key\"
+ eval define=\"'$'CONF_define_$key\"
+ eval values=\"'$'CONF_values_$key\"
+ eval script=\"'$'CONF_script_$key\"
+ eval headers=\"'$'CONF_headers_$key\"
+ printf "%29s %35s %8s %2s %1d %5s %s$nl" "$name" "$key" "$standard" "$call" "$section" "$flags" "$define${values:+$sp=$values}${headers:+$sp$headers$nl}${script:+$sp$ob$script$nl$cb}"
+ ;;
+ esac
+ done
+ exit
+ ;;
+esac
+
+# mark the dups CONF_PREFIXED
+
+prev_key=
+prev_name=
+for key in $keys
+do eval name=\"'$'CONF_name_$key\"
+ case $name in
+ '') continue
+ ;;
+ $prev_name)
+ eval p='$'CONF_flags_${prev_key}
+ eval c='$'CONF_flags_${key}
+ case $p:$c in
+ *L*:*L*);;
+ *L*:*) c=L${c} ;;
+ *:*L*) p=L${p} ;;
+ *) p=P$p c=P$c ;;
+ esac
+ eval CONF_flags_${prev_key}=$p
+ eval CONF_flags_${key}=$c
+ ;;
+ esac
+ prev_name=$name
+ prev_key=$key
+done
+
+# collect all the macros/enums
+
+for key in $keys
+do eval name=\"'$'CONF_name_$key\"
+ case $name in
+ '') continue ;;
+ $keep_name) ;;
+ *) continue ;;
+ esac
+ eval call=\"'$'CONF_call_$key\"
+ case $call in
+ $keep_call) ;;
+ *) continue ;;
+ esac
+ eval standard=\"'$'CONF_standard_$key\"
+ eval section=\"'$'CONF_section_$key\"
+ eval flags=\"'$'CONF_flags_$key\"
+ eval define=\"'$'CONF_define_$key\"
+ eval values=\"'$'CONF_values_$key\"
+ eval script=\"'$'CONF_script_$key\"
+ eval args=\"'$'CONF_args_$key\"
+ eval headers=\"'$'CONF_headers_$key\"
+ conf_name=$name
+ case $call in
+ QQ) call=XX
+ for c in SC PC CS
+ do case $flags in
+ *S*) case $section in
+ 1) eval x='$'CONF_call_${c}_${standard}_${name} ;;
+ *) eval x='$'CONF_call_${c}_${standard}${section}_${name} ;;
+ esac
+ ;;
+ *) eval x='$'CONF_call_${c}_${name}
+ ;;
+ esac
+ case $x in
+ ?*) call=$x
+ break
+ ;;
+ esac
+ done
+ case $call in
+ XX) for c in SC PC CS
+ do echo "_${c}_${name}"
+ case $flags in
+ *S*) case $section in
+ 1) echo "_${c}_${standard}_${name}" ;;
+ *) echo "_${c}_${standard}${section}_${name}" ;;
+ esac
+ ;;
+ esac
+ done
+ ;;
+ esac
+ ;;
+ esac
+ case $call in
+ CS|PC|SC|SI|XX)
+ ;;
+ *) echo "$command: $name: $call: invalid call" >&2
+ exit 1
+ ;;
+ esac
+ case $flags in
+ *[ABEGHIJQTYZabcefghijklmnopqrstuvwxyz_123456789]*)
+ echo "$command: $name: $flags: invalid flag(s)" >&2
+ exit 1
+ ;;
+ esac
+ case $section in
+ [01]) ;;
+ *) case $flags in
+ *N*) ;;
+ *) name=${section}_${name} ;;
+ esac
+ standard=${standard}${section}
+ ;;
+ esac
+ case $call in
+ XX) ;;
+ *) case $flags in
+ *d*) conf_op=${define} ;;
+ *O*) conf_op=${call}_${name} ;;
+ *R*) conf_op=_${standard}_${call}_${name} ;;
+ *S*) conf_op=_${call}_${standard}_${name} ;;
+ *) conf_op=_${call}_${name} ;;
+ esac
+ echo "${conf_op}"
+ ;;
+ esac
+ case $standard:$flags in
+ C:*) ;;
+ *:*L*) echo "${conf_name}"
+ echo "_${standard}_${conf_name}"
+ ;;
+ *:*M*) case $section in
+ 1) echo "_${standard}_${conf_name}" ;;
+ *) echo "_${standard}${section}_${conf_name}" ;;
+ esac
+ ;;
+ esac
+done > $tmp.q
+sort -u < $tmp.q > $tmp.t
+mv $tmp.t $tmp.q
+sort -u < $tmp.v > $tmp.t
+mv $tmp.t $tmp.v
+case $debug in
+-d4) exit ;;
+esac
+
+# test all the macros in a few batches (some compilers have an error limit)
+
+defined() # list-file
+{
+ : > $tmp.p
+ while :
+ do {
+ cat <<!
+${head}
+#include <sys/types.h>
+#include <limits.h>
+#include <unistd.h>$systeminfo$headers
+${tail}
+#undef conf
+unsigned int conf[] = {
+!
+ sed 's/$/,/' $1
+ echo "};"
+ } > $tmp.c
+ [ -f $tmp.1.c ] || cp $tmp.c $tmp.1.c
+ if $cc -c $tmp.c > $tmp.e 2>&1
+ then break
+ fi
+ [ -f $tmp.1.e ] || cp $tmp.e $tmp.1.e
+ snl='\
+'
+ sed "s/[^_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789][^_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]*/${snl}/g" $tmp.e |
+ grep '^[_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz][_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789]*$' |
+ sort -u > $tmp.n
+ cmp -s $tmp.n $tmp.p && break
+ fgrep -x -v -f $tmp.n $1 > $tmp.y
+ mv $tmp.y $1
+ mv $tmp.n $tmp.p
+ done
+ {
+ cat <<!
+${head}
+#include <sys/types.h>
+#include <limits.h>
+#include <unistd.h>$systeminfo$headers
+${tail}
+#undef conf
+!
+ sed 's/.*/conf "&" = &/' $1
+ } > $tmp.c
+ $cc -E $tmp.c 2>/dev/null |
+ sed -e '/conf[ ]*".*"[ ]*=[ ]*/!d' -e '/[_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789][ ]*(/!d' -e 's/.*"\(.*\)".*/\1/' > $tmp.n
+ if test -s $tmp.n
+ then fgrep -x -v -f $tmp.n $1 > $tmp.y
+ mv $tmp.y $1
+ fi
+}
+
+case $verbose in
+1) echo "$command: check macros/enums as static initializers" >&2 ;;
+esac
+defined $tmp.q
+defined $tmp.v
+case $debug in
+-d5) exit ;;
+esac
+
+# mark the constant macros/enums
+
+exec < $tmp.q
+while read line
+do eval CONF_const_${line}=1
+done
+exec < $tmp.v
+while read line
+do eval CONF_const_${line}=1
+done
+
+# mark the string literal values
+
+{
+ cat <<!
+${head}
+#include <sys/types.h>
+#include <limits.h>
+#include <unistd.h>$systeminfo$headers
+${tail}
+#undef conf
+!
+ sed 's/.*/conf "&" = &/' $tmp.q
+} > $tmp.c
+$cc -E $tmp.c 2>/dev/null |
+sed -e '/conf[ ]*".*"[ ]*=[ ]*"/!d' -e 's/.*"\([^"]*\)".*/\1/' > $tmp.e
+exec < $tmp.e
+while read line
+do eval CONF_string_${line}=1
+done
+
+# walk through the table
+
+case $shell in
+ksh) integer len name_max ;;
+esac
+name_max=1
+export tmp name standard call cc
+
+exec > $tmp.t
+for key in $keys
+do eval name=\"'$'CONF_name_$key\"
+ case $name in
+ '') continue ;;
+ $keep_name) ;;
+ *) continue ;;
+ esac
+ eval call=\"'$'CONF_call_$key\"
+ case $call in
+ $keep_call) ;;
+ *) continue ;;
+ esac
+ eval standard=\"'$'CONF_standard_$key\"
+ eval section=\"'$'CONF_section_$key\"
+ eval flags=\"'$'CONF_flags_$key\"
+ eval define=\"'$'CONF_define_$key\"
+ eval values=\"'$'CONF_values_$key\"
+ eval script=\"'$'CONF_script_$key\"
+ eval args=\"'$'CONF_args_$key\"
+ eval headers=\"'$'CONF_headers_$key\"
+ conf_name=$name
+ case $call in
+ QQ) call=XX
+ for c in SC PC CS
+ do case $flags in
+ *S*) case $section in
+ 1) eval x='$'CONF_call_${c}_${standard}_${name} ;;
+ *) eval x='$'CONF_call_${c}_${standard}${section}_${name} ;;
+ esac
+ ;;
+ *) eval x='$'CONF_call_${c}_${name}
+ ;;
+ esac
+ case $x in
+ ?*) call=$x
+ break
+ ;;
+ esac
+ done
+ case $call in
+ XX) for c in SC PC CS
+ do case $flags in
+ *S*) case $section in
+ 1) eval x='$'CONF_const__${c}_${standard}_${name} ;;
+ *) eval x='$'CONF_const__${c}_${standard}${section}_${name} ;;
+ esac
+ ;;
+ *) eval x='$'CONF_const__${c}_${name}
+ ;;
+ esac
+ case $x in
+ 1) call=$c
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+ case $call in
+ XX) case $standard in
+ C) standard=POSIX ;;
+ esac
+ case $flags in
+ *L*) flags=lFU ;;
+ *) flags=FU ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case " $standards " in
+ *" $standard "*)
+ ;;
+ *) standards="$standards $standard"
+ ;;
+ esac
+ conf_standard=CONF_${standard}
+ case $call in
+ CS) conf_call=CONF_confstr
+ ;;
+ PC) conf_call=CONF_pathconf
+ ;;
+ SC) conf_call=CONF_sysconf
+ ;;
+ SI) conf_call=CONF_sysinfo
+ ;;
+ XX) conf_call=CONF_nop
+ ;;
+ esac
+ conf_op=-1
+ for s in _${call}_${standard}${section}_${name} _${call}_${standard}_${name} _${call}_${section}_${name} _${call}_${name} ${call}_${name}
+ do eval x='$'CONF_const_${s}
+ case $x in
+ 1) conf_op=${s}
+ break
+ ;;
+ esac
+ done
+ conf_section=$section
+ conf_flags=0
+ case $flags in
+ *C*) conf_flags="${conf_flags}|CONF_DEFER_CALL" ;;
+ esac
+ case $flags in
+ *D*) conf_flags="${conf_flags}|CONF_DEFER_MM" ;;
+ esac
+ case $flags in
+ *F*) conf_flags="${conf_flags}|CONF_FEATURE" ;;
+ esac
+ case $flags in
+ *L*) conf_flags="${conf_flags}|CONF_LIMIT" ;;
+ esac
+ case $flags in
+ *M*) conf_flags="${conf_flags}|CONF_MINMAX" ;;
+ esac
+ case $flags in
+ *N*) conf_flags="${conf_flags}|CONF_NOSECTION" ;;
+ esac
+ case $flags in
+ *P*) conf_flags="${conf_flags}|CONF_PREFIXED" ;;
+ esac
+ case $flags in
+ *S*) conf_flags="${conf_flags}|CONF_STANDARD" ;;
+ esac
+ case $flags in
+ *U*) conf_flags="${conf_flags}|CONF_UNDERSCORE" ;;
+ esac
+ case $flags in
+ *V*) conf_flags="${conf_flags}|CONF_NOUNDERSCORE" ;;
+ esac
+ case $flags in
+ *W*) conf_flags="${conf_flags}|CONF_PREFIX_ONLY" ;;
+ esac
+ case $debug in
+ ?*) case $standard in
+ ????) sep=" " ;;
+ ???) sep=" " ;;
+ ??) sep=" " ;;
+ ?) sep=" " ;;
+ *) sep="" ;;
+ esac
+ echo "$command: test: $sep$standard $call $name" >&2
+ ;;
+ esac
+ case $call in
+ CS|SI) conf_flags="${conf_flags}|CONF_STRING"
+ string=1
+ ;;
+ *) eval string='$'CONF_string_${key}
+ ;;
+ esac
+ conf_limit=0
+ case $flags in
+ *[Ll]*) d=
+ case ${conf_name} in
+ LONG_MAX|SSIZE_MAX)
+ x=
+ ;;
+ *) eval x='$'CONF_const_${conf_name}
+ ;;
+ esac
+ case $x in
+ '') for s in ${values}
+ do case $s in
+ $sym) eval x='$'CONF_const_${s}
+ case $x in
+ 1) eval a='$'CONF_const_${standard}_${s}
+ case $a in
+ $x) x= ;;
+ *) x=$s ;;
+ esac
+ break
+ ;;
+ esac
+ ;;
+ [0123456789]*|[-+][0123456789]*)
+ d=$s
+ break
+ ;;
+ esac
+ done
+ case ${x:+1}:$flags:$conf_op in
+ :*:-1|:*X*:*)
+ case $verbose in
+ 1) echo "$command: probe for ${conf_name} <limits.h> value" >&2 ;;
+ esac
+ x=
+ case $CONF_getconf in
+ ?*) if $CONF_getconf $conf_name > $tmp.x 2>/dev/null
+ then x=`cat $tmp.x`
+ case $x in
+ undefined) x= ;;
+ esac
+ fi
+ ;;
+ esac
+ case ${x:+1} in
+ '') case $script in
+ '#'*) echo "$script" > $tmp.sh
+ chmod +x $tmp.sh
+ x=`./$tmp.sh 2>/dev/null`
+ ;;
+ '') case $conf_name in
+ SIZE_*|U*|*_MAX)
+ f="%${LL_format}u"
+ t="unsigned _ast_intmax_t"
+ ;;
+ *) f="%${LL_format}d"
+ t="_ast_intmax_t"
+ ;;
+ esac
+ cat > $tmp.c <<!
+${head}
+#include <stdio.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <unistd.h>$systeminfo$headers
+${tail}
+int
+main()
+{
+ printf("$f\n", ($t)$conf_name);
+ return 0;
+}
+!
+ ;;
+ *) cat > $tmp.c <<!
+${head}
+#include <stdio.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <unistd.h>$systeminfo$headers
+${tail}
+${script}
+!
+ ;;
+ esac
+ case $args in
+ '') set "" ;;
+ *) eval set '""' '"'$args'"'; shift ;;
+ esac
+ for a
+ do case $script in
+ '#'*) ./$tmp.sh $a > $tmp.x 2>/dev/null
+ x=$?
+ ;;
+ *) $cc $a -o $tmp.exe $tmp.c >/dev/null 2>&1 && ./$tmp.exe > $tmp.x 2>/dev/null
+ x=$?
+ ;;
+ esac
+ case $x in
+ 0) x=`cat $tmp.x`
+ case $x in
+ "-") x=$a ;;
+ esac
+ break
+ ;;
+ *) x=
+ ;;
+ esac
+ done
+ ;;
+ esac
+ case $x in
+ '') x=$d ;;
+ esac
+ ;;
+ esac
+ case ${x:+1}:$flags:$conf_op in
+ 1:*:-1|1:*X*:*)
+ conf_limit=$x
+ case $flags in
+ *L*) ;;
+ *) conf_flags="${conf_flags}|CONF_LIMIT" ;;
+ esac
+ conf_flags="${conf_flags}|CONF_LIMIT_DEF"
+ case $string:$x in
+ 1:*) cat >> $tmp.l <<!
+printf("#ifndef ${conf_name}\n");
+printf("#define ${conf_name} \"${x}\"\n");
+printf("#endif\n");
+!
+ ;;
+ *:U*) cat >> $tmp.l <<!
+printf("#ifndef ${conf_name}\n");
+printf("#ifndef ${x}\n");
+printf("#define ${x} %lu\n", ${x});
+printf("#endif\n");
+printf("#define ${conf_name} ${x}\n");
+printf("#endif\n");
+!
+ ;;
+ *:$sym) cat >> $tmp.l <<!
+printf("#ifndef ${conf_name}\n");
+printf("#ifndef ${x}\n");
+printf("#define ${x} %ld\n", ${x});
+printf("#endif\n");
+printf("#define ${conf_name} ${x}\n");
+printf("#endif\n");
+!
+ ;;
+ *) cat >> $tmp.l <<!
+printf("#ifndef ${conf_name}\n");
+printf("#define ${conf_name} ${x}\n");
+printf("#endif\n");
+!
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $section in
+ [01]) ;;
+ *) case $flags in
+ *N*) ;;
+ *) name=${section}_${name} ;;
+ esac
+ standard=${standard}${section}
+ ;;
+ esac
+ conf_minmax=0
+ case $call:$standard:$flags in
+ *:C:*M*)for s in _${standard}_${conf_name} ${values}
+ do case $s in
+ $sym) ;;
+ *) conf_minmax=$s
+ conf_flags="${conf_flags}|CONF_MINMAX_DEF"
+ break
+ ;;
+ esac
+ done
+ ;;
+ *:C:*) ;;
+ [CPSX][CSX]:*:*[FM]*)
+ x=
+ for s in _${standard}_${conf_name} ${values}
+ do case $s in
+ $sym) eval x='$'CONF_const_${s} ;;
+ *) x=1 ;;
+ esac
+ case $x in
+ 1) conf_minmax=$s
+ case $flags in
+ *M*) conf_flags="${conf_flags}|CONF_MINMAX_DEF" ;;
+ esac
+ case $conf_minmax in
+ [-+0123456789]*) x= ;;
+ esac
+ break
+ ;;
+ esac
+ done
+ case ${x:+1}:${script:+1} in
+ :1) case $verbose in
+ 1) echo "$command: probe for _${standard}_${conf_name} minmax value" >&2 ;;
+ esac
+ case $CONF_getconf in
+ ?*) if $CONF_getconf _${standard}_${conf_name} > $tmp.x 2>/dev/null
+ then x=`cat $tmp.x`
+ case $x in
+ undefined) x= ;;
+ esac
+ fi
+ ;;
+ esac
+ case $x in
+ '') case $script in
+ '#'*) echo "$script" > $tmp.sh
+ chmod +x $tmp.sh
+ x=`./$tmp.sh 2>/dev/null`
+ ;;
+ *) cat > $tmp.c <<!
+${head}
+#include <sys/types.h>
+#include <limits.h>
+#include <unistd.h>$systeminfo$headers
+${tail}
+${script}
+!
+ ;;
+ esac
+ case $args in
+ '') set "" ;;
+ *) eval set '""' "$args"; shift ;;
+ esac
+ for a
+ do case $script in
+ '#'*) ./$tmp.sh $a > $tmp.x 2>/dev/null
+ x=$?
+ ;;
+ *) $cc $a -o $tmp.exe $tmp.c >/dev/null 2>&1 && ./$tmp.exe > $tmp.x 2>/dev/null
+ x=$?
+ ;;
+ esac
+ case $x in
+ 0) x=`cat $tmp.x`
+ case $x in
+ "-") x=$a ;;
+ esac
+ break
+ ;;
+ *) x=
+ ;;
+ esac
+ done
+ ;;
+ esac
+ case $x in
+ ?*) conf_minmax=$x
+ case $flags in
+ *M*) case "|$conf_flags|" in
+ *'|CONF_MINMAX_DEF|'*)
+ ;;
+ *) conf_flags="${conf_flags}|CONF_MINMAX_DEF"
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ case $string in
+ 1) conf_limit="{ 0, $conf_limit }" conf_minmax="{ 0, $conf_minmax }"
+ ;;
+ *) case $conf_limit in
+ 0[xX]*|-*|+*|[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*)
+ ;;
+ *[!0123456789abcdefABCDEF]*)
+ conf_limit=0
+ ;;
+ *[!0123456789]*)
+ conf_limit=0x$conf_limit
+ ;;
+ esac
+ case $conf_minmax in
+ 0[xX]*|-*|+*|[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_]*)
+ ;;
+ *[!0123456789abcdefABCDEF]*)
+ conf_minmax=0
+ ;;
+ *[!0123456789]*)
+ conf_minmax=0x$conf_minmax
+ ;;
+ esac
+ case $conf_limit in
+ ?*[-+]*|*['()']*)
+ ;;
+ *[lLuU])
+ case $LL_suffix in
+ ??) case $conf_limit in
+ *[!lL][lL]|*[!lL][lL][uU])
+ conf_limit=${conf_limit}L
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ -*[2468])
+ case $shell in
+ ksh) p=${conf_limit%?}
+ s=${conf_limit#$p}
+ ((s=s-1))
+ ;;
+ *) eval `echo '' $conf_limit | sed 's/ *\(.*\)\(.\) */p=\1 s=\2/'`
+ s=`expr $s - 1`
+ ;;
+ esac
+ conf_limit=${p}${s}${LL_suffix}-1${LL_suffix}
+ ;;
+ 0[xX]*[abcdefABCDEF])
+ conf_limit=${conf_limit}${LL_suffix}
+ ;;
+ -*[0123456789])
+ conf_limit=${conf_limit}${LL_suffix}
+ ;;
+ *[0123456789])
+ conf_limit=${conf_limit}${U_suffix}${LL_suffix}
+ ;;
+ esac
+ case $conf_minmax in
+ ?*[-+]*|*['()']*)
+ ;;
+ *[lLuU])
+ case $LL_suffix in
+ ??) case $conf_minmax in
+ *[!lL][lL]|*[!lL][lL][uU])
+ conf_minmax=${conf_minmax}L
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ -*[2468])
+ case $shell in
+ ksh) p=${conf_minmax%?}
+ s=${conf_minmax#$p}
+ ((s=s-1))
+ ;;
+ *) eval `echo '' $conf_minmax | sed 's/ *\(.*\)\(.\) */p=\1 s=\2/'`
+ s=`expr $s - 1`
+ ;;
+ esac
+ conf_minmax=${p}${s}${LL_suffix}-1${LL_suffix}
+ ;;
+ 0[xX]*[abcdefABCDEF])
+ conf_minmax=${conf_minmax}${LL_suffix}
+ ;;
+ -*[0123456789])
+ conf_minmax=${conf_minmax}${LL_suffix}
+ ;;
+ *[0123456789])
+ conf_minmax=${conf_minmax}${U_suffix}${LL_suffix}
+ ;;
+ esac
+ conf_limit="{ $conf_limit, 0 }" conf_minmax="{ $conf_minmax, 0 }"
+ ;;
+ esac
+ case $conf_flags in
+ '0|'*) case $shell in
+ ksh) conf_flags=${conf_flags#0?} ;;
+ *) conf_flags=`echo "$conf_flags" | sed 's/^0.//'` ;;
+ esac
+ ;;
+ esac
+ echo "{ \"$conf_name\", $conf_limit, $conf_minmax, $conf_flags, $conf_standard, $conf_section, $conf_call, $conf_op },"
+ case $shell in
+ ksh) len=${#conf_name}
+ if ((len>=name_max))
+ then ((name_max=len+1))
+ fi
+ ;;
+ *) len=`echo ${conf_name} | wc -c`
+ if expr \( $len - 1 \) \>= ${name_max} >/dev/null
+ then name_max=$len
+ fi
+ ;;
+ esac
+done
+exec > /dev/null
+case $debug in
+-d6) exit ;;
+esac
+
+# conf string table
+
+base=conftab
+case $verbose in
+1) echo "$command: generate ${base}.h string table header" >&2 ;;
+esac
+case $shell in
+ksh) ((name_max=name_max+3)); ((name_max=name_max/4*4)) ;; # bsd /bin/sh !
+*) name_max=`expr \( $name_max + 3 \) / 4 \* 4` ;;
+esac
+{
+cat <<!
+#ifndef _CONFTAB_H
+#define _CONFTAB_H
+$systeminfo
+
+${generated}
+
+#if !defined(const) && !defined(__STDC__) && !defined(__cplusplus) && !defined(c_plusplus)
+#define const
+#endif
+
+#define conf _ast_conf_data
+#define conf_elements _ast_conf_ndata
+
+#define prefix _ast_conf_prefix
+#define prefix_elements _ast_conf_nprefix
+
+#define CONF_nop 0
+#define CONF_confstr 1
+#define CONF_pathconf 2
+#define CONF_sysconf 3
+#define CONF_sysinfo 4
+
+!
+index=0
+for standard in $standards
+do echo "#define CONF_${standard} ${index}"
+ case $shell in
+ ksh) ((index=index+1)) ;;
+ *) index=`expr ${index} + 1` ;;
+ esac
+done
+echo "#define CONF_call ${index}"
+case $CONF_getconf in
+?*) echo
+ echo "#define _pth_getconf \"$CONF_getconf\""
+ case $CONF_getconf_a in
+ ?*) echo "#define _pth_getconf_a \"$CONF_getconf_a\"" ;;
+ esac
+ ;;
+esac
+cat <<!
+
+#define CONF_DEFER_CALL 0x0001
+#define CONF_DEFER_MM 0x0002
+#define CONF_FEATURE 0x0004
+#define CONF_LIMIT 0x0008
+#define CONF_LIMIT_DEF 0x0010
+#define CONF_MINMAX 0x0020
+#define CONF_MINMAX_DEF 0x0040
+#define CONF_NOSECTION 0x0080
+#define CONF_NOUNDERSCORE 0x0100
+#define CONF_PREFIX_ONLY 0x0200
+#define CONF_PREFIXED 0x0400
+#define CONF_STANDARD 0x0800
+#define CONF_STRING 0x1000
+#define CONF_UNDERSCORE 0x2000
+#define CONF_USER 0x4000
+
+struct Conf_s; typedef struct Conf_s Conf_t;
+
+typedef struct Value_s
+{
+ intmax_t number;
+ const char* string;
+} Value_t;
+
+struct Conf_s
+{
+ const char name[${name_max}];
+ Value_t limit;
+ Value_t minmax;
+ unsigned int flags;
+ short standard;
+ short section;
+ short call;
+ short op;
+};
+
+typedef struct Prefix_s
+{
+ const char name[16];
+ short length;
+ short standard;
+ short call;
+} Prefix_t;
+
+extern const Conf_t conf[];
+extern const int conf_elements;
+
+extern const Prefix_t prefix[];
+extern const int prefix_elements;
+
+#endif
+!
+} > $tmp.2
+case $debug in
+-d7) echo $command: $tmp.2 ${base}.h ;;
+*) cmp -s $tmp.2 ${base}.h 2>/dev/null || mv $tmp.2 ${base}.h ;;
+esac
+
+case $verbose in
+1) echo "$command: generate ${base}.c string table" >&2 ;;
+esac
+{
+cat <<!
+${head}
+#include <sys/types.h>
+#include <limits.h>
+#include <unistd.h>$systeminfo$headers
+${tail}
+#include "${base}.h"
+
+${generated}
+
+/*
+ * prefix strings -- the first few are indexed by Conf_t.standard
+ */
+
+const Prefix_t prefix[] =
+{
+!
+for standard in $standards
+do case $shell in
+ ksh) len=${#standard} ;;
+ *) len=`echo ${standard} | wc -c`; len=`expr $len - 1` ;;
+ esac
+ echo " \"${standard}\", ${len}, CONF_${standard}, -1,"
+done
+cat <<!
+ "XX", 2, CONF_POSIX, CONF_nop,
+ "CS", 2, CONF_POSIX, CONF_confstr,
+ "PC", 2, CONF_POSIX, CONF_pathconf,
+ "SC", 2, CONF_POSIX, CONF_sysconf,
+ "SI", 2, CONF_SVID, CONF_sysinfo,
+};
+
+const int prefix_elements = (int)sizeof(prefix) / (int)sizeof(prefix[0]);
+
+/*
+ * conf strings sorted in ascending order
+ */
+
+const Conf_t conf[] =
+{
+!
+cat $tmp.t
+cat <<!
+};
+
+const int conf_elements = (int)sizeof(conf) / (int)sizeof(conf[0]);
+!
+} > $tmp.4
+case $debug in
+-d7) echo $command: $tmp.4 ${base}.c ;;
+*) cmp -s $tmp.4 ${base}.c 2>/dev/null || mv $tmp.4 ${base}.c ;;
+esac
+
+# limits.h generation code
+
+base=conflim
+case $verbose in
+1) echo "$command: generate ${base}.h supplemental <limits.h> values" >&2 ;;
+esac
+{
+cat <<!
+${generated}
+
+/*
+ * supplemental <limits.h> values
+ */
+
+!
+test -f $tmp.l && cat $tmp.l
+} > $tmp.5
+case $debug in
+-d7) echo $command: $tmp.5 ${base}.h ;;
+*) cmp -s $tmp.5 ${base}.h 2>/dev/null || mv $tmp.5 ${base}.h ;;
+esac
+exit 0
diff --git a/src/lib/libast/comp/conf.tab b/src/lib/libast/comp/conf.tab
new file mode 100644
index 0000000..2dc05e0
--- /dev/null
+++ b/src/lib/libast/comp/conf.tab
@@ -0,0 +1,601 @@
+#
+# posix { getconf limits } macro table
+#
+# @(#)conf.tab (AT&T Research) 2010-06-28
+#
+# name standard section call flags [ header ... ] [ value ... ]
+#
+# name: sans prefix
+# standard: AST, C, POSIX, SVID, XOPEN, <vendor> { SCO, SGI, SUN, ... }
+# section: section number in standard
+# call: CS=confstr PC=pathconf SC=sysconf SI=sysinfo QQ=query XX=none
+# flags: 0 no flags
+# C defer call to native getconf(1)
+# D defer minmax to native getconf(1)
+# F unistd.h feature
+# L limits.h constant
+# M has _<standard><section>_<name> minmax value
+# N _<call>_<name>
+# O use original name and definition
+# R _<standard>_<call>_<section>_<name>
+# S _<call>_<standard><section>_<name>
+# U <standard><section>_<name> prefixed by underscore
+# V _ prefix not allowed
+# W standard required
+# X define even if native is dynamic (ast special)
+#
+# default names if <section> <= 1
+#
+# _<call>_<name>
+# <standard>_<name>
+#
+# default names if <section> > 1
+#
+# _<call>_<section>_<name>
+# <standard><section>_<name>
+#
+# the [NSU] flags modify the default names
+#
+
+ABI_AIO_XFER_MAX C QQ 1 L
+ABI_ASYNCHRONOUS_IO C QQ 1 L
+ABI_ASYNC_IO C QQ 1 L
+ADVISORY_INFO POSIX SC 1 FUW
+AIO_LISTIO_MAX POSIX SC 1 LMU 2
+AIO_MAX POSIX SC 1 LMU 1
+AIO_PRIO_DELTA_MAX POSIX SC 1 LMU
+ALLOC_SIZE_MIN POSIX PC 1 LUVW
+ARCHITECTURE SVID SI 1 O
+ARG_MAX POSIX SC 1 CDLMUX NCARGS 4096
+ASYNCHRONOUS_IO POSIX SC 1 CDFUW
+ASYNC_IO POSIX PC 1 FUW
+ATEXIT_MAX XOPEN SC 1 LMU 32
+AUDIT C QQ 1 L
+AVAIL_PROCESSORS C QQ 1 L
+AVPHYS_PAGES SUN SC 1 0
+BARRIERS POSIX SC 1 FUW
+BC_BASE_MAX POSIX SC 2 LMN 99
+BC_DIM_MAX POSIX SC 2 LMN 2048
+BC_SCALE_MAX POSIX SC 2 LMN 99
+BC_STRING_MAX POSIX SC 2 LMN 1000
+BUSTYPES SVID SI 1 O
+CHARCLASS_NAME_MAX XOPEN XX 1 L 14
+CHAR_BIT C XX 1 L 8
+CHAR_MAX C XX 1 L
+CHAR_MIN C XX 1 L
+CHAR_TERM POSIX SC 2 FUW
+CHILD_MAX POSIX SC 1 CDLMUX 6 cc{
+ #if _lib_fork
+ #define child() fork()
+ #else
+ #ifdef _map_spawnve
+ #define spawnve _map_spawnve
+ #endif
+ extern int spawnve(const char*, char* const[], char* const[]);
+ static char* cmd[] = { "/bin/echo", 0 };
+ #define child() spawnve(cmd[0],cmd,(char**)0)
+ #endif
+ int main()
+ {
+ int i;
+ int n;
+ for (i = 3; i < 512 && (n = child()) >= 0; i++)
+ if (!n) _exit(0);
+ while (wait((int*)0) > 0);
+ for (n = 8; n < i; n <<= 1);
+ printf("%d", n);
+ return 0;
+ }
+}
+CHOWN_RESTRICTED POSIX PC 1 FUW
+CKPT POSIX SC 1 FU
+CLK_TCK POSIX SC 1 L HZ 60
+CLOCKRES_MIN POSIX SC 1 MUW 1
+CLOCKS_PER_SEC C QQ 1 L
+CLOCK_SELECTION POSIX SC 1 FUVW
+COLL_WEIGHTS_MAX POSIX SC 2 DLMN 2
+CPUTIME POSIX SC 1 FUW
+CPU_KEYBITS1 C QQ 1 L
+CPU_VERSION C QQ 1 L
+CRYPT XOPEN SC 1 FSUW
+C_BIND POSIX SC 2 CFU
+C_DEV POSIX SC 2 CFU
+C_VERSION POSIX SC 2 CDFU
+DATAKEYS_MAX C QQ 1 0
+DELAYTIMER_MAX POSIX SC 1 LMU 32
+ENH_I18N XOPEN SC 1 FSUW
+EQUIV_CLASS_MAX C QQ 1 L
+EXEC_INTERPRETER_LENGTH C QQ 1 L
+EXPR_NEST_MAX POSIX SC 2 LMN 32
+FCHR_MAX SVID SC 1 LMU LONG_MAX 2147483647
+FILESIZEBITS POSIX PC 1 LMU (8*sizeof(off_t)) 32
+FILE_LOCKING POSIX SC 1 FU
+FORT_DEV POSIX SC 2 CFUW
+FORT_RUN POSIX SC 2 CFUW
+FSYNC POSIX SC 1 CDFUW _lib_fsync
+GETGR_R_SIZE_MAX C QQ 1 L
+GETPW_R_SIZE_MAX C QQ 1 L
+HOSTID C QQ 1 L
+HOSTNAME SVID SI 1 O
+HOST_NAME_MAX POSIX SC 1 LMU 255
+HW_PROVIDER SVID SI 1 O
+HW_SERIAL C QQ 1 L
+ILP32_OFF32 XBS5 SC 1 FU
+ILP32_OFF32_CFLAGS XBS5 CS 1 FU
+ILP32_OFF32_LDFLAGS XBS5 CS 1 FU
+ILP32_OFF32_LIBS XBS5 CS 1 FU
+ILP32_OFF32_LINTFLAGS XBS5 CS 1 FU
+ILP32_OFFBIG XBS5 SC 1 FU
+ILP32_OFFBIG_CFLAGS XBS5 CS 1 FU
+ILP32_OFFBIG_LDFLAGS XBS5 CS 1 FU
+ILP32_OFFBIG_LIBS XBS5 CS 1 FU
+ILP32_OFFBIG_LINTFLAGS XBS5 CS 1 FU
+INITTAB_NAME SVID SI 1 O
+INT_MAX C XX 1 L 32767
+INT_MIN C XX 1 L -32767
+IOV_MAX XOPEN SC 1 LMU 16
+IO_TYPE C QQ 1 L
+IPV6 POSIX SC 1 FUW
+IP_SECOPTS C QQ 1 L
+JOB_CONTROL POSIX SC 1 FUW cc{
+ #include "FEATURE/wait"
+ #if _ok_wif
+ int main()
+ {
+ printf("1");
+ return 0;
+ }
+ #endif
+}
+KERNEL_CLIST SCO SC 1 0
+KERNEL_CLIST_MAX SCO SC 1 0
+KERNEL_DISK SCO SC 1 0
+KERNEL_DISK_MAX SCO SC 1 0
+KERNEL_DMABUF SCO SC 1 0
+KERNEL_DMABUF_MAX SCO SC 1 0
+KERNEL_FILE SCO SC 1 0
+KERNEL_FILE_MAX SCO SC 1 0
+KERNEL_FLCKREC SCO SC 1 0
+KERNEL_FLCKREC_MAX SCO SC 1 0
+KERNEL_INODE SCO SC 1 0
+KERNEL_INODE_MAX SCO SC 1 0
+KERNEL_MOUNT SCO SC 1 0
+KERNEL_MOUNT_MAX SCO SC 1 0
+KERNEL_PINODE SCO SC 1 0
+KERNEL_PINODE_MAX SCO SC 1 0
+KERNEL_PROC SCO SC 1 0
+KERNEL_PROC_MAX SCO SC 1 0
+KERNEL_REGION SCO SC 1 0
+KERNEL_REGION_MAX SCO SC 1 0
+KERNEL_S5INODE SCO SC 1 0
+KERNEL_S5INODE_MAX SCO SC 1 0
+KERNEL_STAMP SVID SI 1 O
+KERN_POINTERS C QQ 1 L
+KERN_SIM C QQ 1 L
+LEGACY XOPEN SC 1 FU
+LFS_CFLAGS POSIX CS 1 MU cc{ -D_LARGEFILE_SOURCE "-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" -D_LARGEFILE64_SOURCE -64
+ #include <sys/types.h>
+ int
+ main()
+ {
+ if (sizeof(off_t) >= sizeof(off_64_t))
+ {
+ printf("-");
+ return 0;
+ }
+ return 1;
+ }
+}
+LFS64_CFLAGS POSIX CS 1 MU : LFS_CFLAGS
+LFS64_LDFLAGS POSIX CS 1 MU : LFS_CFLAGS
+LFS64_LIBS POSIX CS 1 MU
+LFS64_LINTFLAGS POSIX CS 1 MU : LFS_CFLAGS
+LFS_LDFLAGS POSIX CS 1 MU : LFS_CFLAGS
+LFS_LIBS POSIX CS 1 MU
+LFS_LINTFLAGS POSIX CS 1 MU : LFS_CFLAGS
+LINE_MAX POSIX SC 2 LMN 2048
+LINK_MAX POSIX PC 1 LMU MAXLINK SHRT_MAX 8
+LLONG_MAX C XX 1 L
+LLONG_MIN C XX 1 L
+LOCALEDEF POSIX SC 1 FUW
+LOCALEDEF POSIX SC 2 CFUW
+LOGIN_NAME_MAX POSIX SC 1 LMU
+LOGNAME_MAX SVID SC 1 MU 8
+LONG_BIT XOPEN XX 1 L (8*sizeof(long)) 32
+LONG_MAX C XX 1 L 2147483647
+LONG_MIN C XX 1 L -2147483647
+LP64_OFF64 XBS5 SC 1 FU
+LP64_OFF64_CFLAGS XBS5 CS 1 FU
+LP64_OFF64_LDFLAGS XBS5 CS 1 FU
+LP64_OFF64_LIBS XBS5 CS 1 FU
+LP64_OFF64_LINTFLAGS XBS5 CS 1 FU
+LPBIG_OFFBIG XBS5 SC 1 FU
+LPBIG_OFFBIG_CFLAGS XBS5 CS 1 FU
+LPBIG_OFFBIG_LDFLAGS XBS5 CS 1 FU
+LPBIG_OFFBIG_LIBS XBS5 CS 1 FU
+LPBIG_OFFBIG_LINTFLAGS XBS5 CS 1 FU
+MACHINE SVID SI 1 O
+MAPPED_FILES POSIX SC 1 CDFUW _lib_mmap
+MAX_CANON POSIX PC 1 LMU CANBSIZ 255
+MAX_INPUT POSIX PC 1 LMU MAX_CANON 255
+MB_LEN_MAX C XX 1 L 1
+MCAS_OFFSET C QQ 1 L
+MEMLOCK POSIX SC 1 CDFUW
+MEMLOCK_RANGE POSIX SC 1 CDFUW
+MEMORY_PROTECTION POSIX SC 1 CDFUW
+MESSAGE_PASSING POSIX SC 1 CDFUW
+MMAP_FIXED_ALIGNMENT C QQ 1 L _AST_PAGESIZE
+MONOTONIC_CLOCK POSIX SC 1 FUW
+MQ_OPEN_MAX POSIX SC 1 LMU 8
+MQ_PRIO_MAX POSIX SC 1 LMU 32
+MSEM_LOCKID C QQ 1 L
+MULTI_PROCESS POSIX SC 1 FU
+NACLS_MAX SVID SC 1 0
+NAME_MAX POSIX PC 1 LMU 14 cc{
+ int main()
+ {
+ #ifdef MAXNAMLEN
+ printf("%d", MAXNAMLEN);
+ #else
+ #if !defined(remove) && (!_lib_remove || _lib_unlink)
+ #define remove unlink
+ #endif
+ int i;
+ int n;
+ int v;
+ char name[256];
+ for (i = 0; i < sizeof(name); i++)
+ name[i] = 'F';
+ name[8] = '.';
+ name[sizeof(name) - 1] = 0;
+ if ((n = creat(name, 0666)) >= 0)
+ {
+ close(n);
+ for (v = 12; v < sizeof(name); v++)
+ {
+ name[v] = 0;
+ if (remove(name) >= 0) break;
+ name[v] = 'F';
+ }
+ }
+ else for (v = 12; v < sizeof(name); v++)
+ {
+ name[v] = 0;
+ if ((n = creat(name, 0666)) >= 0)
+ {
+ close(n);
+ remove(name);
+ name[v] = 'F';
+ }
+ else
+ {
+ v--;
+ break;
+ }
+ }
+ printf("%d", v);
+ return 0;
+ }
+ #endif
+}
+NGROUPS_MAX POSIX SC 1 CDLMU 8 cc{
+ #if _lib_getgroups
+ int main()
+ {
+ int n;
+ gid_t g;
+ if ((n = getgroups(0, &g)) < 0)
+ #if defined(NGROUPS) && (NGROUPS-0) > 0
+ n = NGROUPS;
+ #else
+ return 1;
+ #endif
+ printf("%d", n);
+ return 0;
+ }
+ #endif
+}
+NL_ARGMAX XOPEN XX 1 L 9
+NL_LANGMAX XOPEN XX 1 L 14
+NL_MAX C QQ 1 L
+NL_MSGMAX XOPEN XX 1 L 32767
+NL_NMAX XOPEN XX 1 L 1
+NL_SETMAX XOPEN XX 1 L 255
+NL_SPECMAX C QQ 1 L
+NL_TEXTMAX XOPEN XX 1 L LINE_MAX
+NO_TRUNC POSIX PC 1 FUW
+NPROCESSORS_CONF SVID SC 1 0
+NPROCESSORS_MAX SVID SC 1 0
+NPROCESSORS_ONLN SVID SC 1 0
+NPROC_CONF C QQ 1 L
+NPROC_ONLN C QQ 1 L
+NSS_BUFLEN_GROUP C QQ 1 L
+NSS_BUFLEN_PASSWD C QQ 1 L
+NUM_PROCESSORS C QQ 1 L
+NZERO XOPEN XX 1 L 20
+OPEN_MAX POSIX SC 1 CDLMUX 16 cc{
+ #if _lib_getdtablesize
+ extern int getdtablesize(void);
+ int main()
+ {
+ printf("%d", getdtablesize());
+ return 0;
+ }
+ #else
+ int main()
+ {
+ int i;
+ int n;
+ int v;
+ n = 0;
+ v = 2;
+ while ((i = dup(0)) >= 0)
+ {
+ if (!n) n = i;
+ if (i > v) v = i;
+ }
+ while (n <= v) close(n++);
+ printf("%d", v);
+ return 0;
+ }
+ #endif
+}
+OPEN_MAX_CEIL AST XX 1 L OPEN_MAX
+OSREL_MAJ C QQ 1 L
+OSREL_MIN C QQ 1 L
+OSREL_PATCH C QQ 1 L
+OS_BASE SVID SI 1 O
+OS_PROVIDER SVID SI 1 O
+OS_VERSION AES SC 1 FSU
+PAGESIZE POSIX SC 1 MU PAGESIZE PAGE_SIZE 4096 cc{
+ int main()
+ {
+ #if _WIN32
+ printf("%ld", 64*1024L);
+ return 0;
+ #else
+ #if _lib_getpagesize
+ #if _npt_getpagesize
+ extern size_t getpagesize(void);
+ #endif
+ printf("%d", getpagesize());
+ return 0;
+ #endif
+ #else
+ return 1;
+ #endif
+ }
+}
+PAGE_SIZE POSIX SC 1 MU _AST_PAGESIZE
+PASS_MAX SVID SC 1 CDLMU 8
+PATH POSIX CS 1 CMU "/bin:/usr/bin"
+PATH_MAX POSIX PC 1 CDLMUX MAXPATHLEN 1024
+PBS POSIX SC 2 FUW
+PBS_ACCOUNTING POSIX SC 2 FUW
+PBS_CHECKPOINT POSIX SC 2 FUW
+PBS_LOCATE POSIX SC 2 FUW
+PBS_MESSAGE POSIX SC 2 FUW
+PBS_TRACK POSIX SC 2 FUW
+PHYS_PAGES SUN SC 1 0
+PID_MAX SVID SC 1 LMU 30000 cc{
+ int main()
+ {
+ long v;
+ int fd;
+ int n;
+ char buf[1024];
+#ifdef PID_MAX
+ v = PID_MAX;
+#else
+ v = 99999;
+#endif
+ if ((fd = open("/proc/sys/kernel/pid_max", 0)) >= 0 && (n = read(fd, buf, sizeof(buf)-1)) > 1)
+ {
+ buf[n] = 0;
+ v = strtol(buf, (char**)0, 0);
+ }
+ else
+ {
+#ifdef __sgi
+ v = 0x7fffffff;
+#endif
+ }
+ printf("%ld", v);
+ return 0;
+ }
+}
+PII POSIX SC 1 FU
+PII_INTERNET POSIX SC 1 FU
+PII_INTERNET_DGRAM POSIX SC 1 FU
+PII_INTERNET_STREAM POSIX SC 1 FU
+PII_OSI POSIX SC 1 FU
+PII_OSI_CLTS POSIX SC 1 FU
+PII_OSI_COTS POSIX SC 1 FU
+PII_OSI_M POSIX SC 1 FU
+PII_SOCKET POSIX SC 1 FU
+PII_XTI POSIX SC 1 FU
+PIPE_BUF POSIX PC 1 LMU 512
+POLL POSIX SC 1 FU
+PRIORITIZED_IO POSIX SC 1 FUW
+PRIORITY_SCHEDULING POSIX SC 1 CDFUW
+PRIO_IO POSIX PC 1 FUW
+PROC_RSRC_MGR C QQ 1 L
+PTHREAD_DESTRUCTOR_ITERATIONS C QQ 1 L
+PTHREAD_KEYS_MAX C QQ 1 L
+PTHREAD_STACK_MIN C QQ 1 L
+PTHREAD_THREADS_MAX C QQ 1 L
+PTRDIFF_MAX C XX 1 LMU stdint.h 65535
+PTRDIFF_MIN C XX 1 LMU stdint.h -65535
+RAW_SOCKETS POSIX SC 1 FUW
+READER_WRITER_LOCKS POSIX SC 1 FUW
+REALTIME XOPEN SC 1 FU
+REALTIME_SIGNALS POSIX SC 1 CDFUW
+REALTIME_THREADS XOPEN SC 1 FU
+REC_INCR_XFER_SIZE POSIX PC 1 LVW
+REC_MAX_XFER_SIZE POSIX PC 1 LVW
+REC_MIN_XFER_SIZE POSIX PC 1 LVW
+REC_XFER_ALIGN POSIX PC 1 LVW
+REENTRANT_FUNCTIONS POSIX SC 1 FU
+REGEXP POSIX SC 1 FUW
+REGEX_VERSION POSIX SC 1 F 20030916
+RELEASE AST XX 1 L
+RESOURCE_LIMITS POSIX SC 1 FU
+RE_DUP_MAX POSIX SC 2 LMN 255
+RTSIG_MAX POSIX SC 1 LMU 8
+SAVED_IDS POSIX SC 1 FUW cc{
+ #if _lib_setuid && !_lib_setreuid
+ int main()
+ {
+ printf("1");
+ return 0;
+ }
+ #endif
+}
+SCHAR_MAX C XX 1 L 127
+SCHAR_MIN C XX 1 L -127
+SECURITY_CLASS C QQ 1 L
+SELECT POSIX SC 1 FU
+SEMAPHORES POSIX SC 1 CDFUW
+SEM_NSEMS_MAX POSIX SC 1 LMU 256
+SEM_VALUE_MAX POSIX SC 1 LMU 32767
+SF_BUFSIZE AST XX 1 MUX sh{
+ sed -e '/[ ]*#[ ]*define[ ][ ]*SF_BUFSIZE[ ]/!d' -e 's/^[^0-9]*//' -e 's/[^0-9]*$//' $PACKAGEROOT/src/lib/libast/include/sfio.h
+}
+SH AST CS 1 MU sh{
+ ifs=$IFS
+ IFS=:
+ set '' `$CONF_getconf PATH 2>/dev/null` /bin /usr/bin /sbin /usr/sbin
+ shift
+ path=$*
+ IFS=$ifs
+ for s in ksh ksh93 sh
+ do for d in $path
+ do if test -x $d/$s
+ then case $s in
+ ksh) case `$d/$s '--?-author' 2>&1` in
+ *'David Korn'*) ;;
+ *) continue ;;
+ esac
+ ;;
+ esac
+ echo '"'$d/$s'"'
+ exit
+ fi
+ done
+ done
+ echo '"/bin/sh"'
+}
+SHARED_MEMORY_OBJECTS POSIX SC 1 CDFUW
+SHELL POSIX SC 1 FUVW
+SHM XOPEN SC 1 FSUW
+SHRT_MAX C XX 1 L 32767
+SHRT_MIN C XX 1 L -32767
+SIG_ATOMIC_MAX C XX 1 L signal.h
+SIG_ATOMIC_MIN C XX 1 L signal.h
+SIGQUEUE_MAX POSIX SC 1 LMU 32
+SIGQUEUE_MAX POSIX SC 1 LMU 32
+SIGRT_MAX SVID SC 1 0
+SIGRT_MIN SVID SC 1 0
+SIZE_MAX C XX 1 LMX stdint.h UINT_MAX 65535
+SLVM_MAXNODES C QQ 1 L
+SOCK_MAXBUF C QQ 1 0
+SOFTPOWER C QQ 1 L
+SPAWN POSIX SC 1 FUW
+SPIN_LOCKS POSIX SC 1 FUW
+SPORADIC_SERVER POSIX SC 1 FUW
+SRPC_DOMAIN C QQ 1 0
+SS_REPL_MAX POSIX SC 1 FUW
+SSIZE_MAX POSIX XX 1 LMUX INT_MAX 32767
+STD_BLK SVID SC 1 LMU 1024
+STREAM_MAX POSIX SC 1 LMU OPEN_MAX 8
+STREAMS XOPEN SC 1 FSUW
+SW_DEV POSIX SC 2 CFUW
+SYMLINK_MAX POSIX PC 1 LMU 255 cc{
+ int main()
+ {
+ printf("%d", PATH_MAX-1);
+ return 0;
+ }
+}
+SYMLINKS POSIX PC 2 FUW
+SYMLOOP_MAX POSIX SC 1 LMU 8
+SYNCHRONIZED_IO POSIX SC 1 CDFUW
+SYNC_IO POSIX PC 1 FUW
+SYSNAME SVID SI 1 O
+SYSPID_MAX SVID SC 1 LMU 2
+THREADS POSIX SC 1 CDFUW
+THREADS_PRIO_CEILING POSIX SC 1 FUW
+THREADS_PRIO_INHERIT POSIX SC 1 FUW
+THREAD_ATTR_STACKADDR POSIX SC 1 CDFUW
+THREAD_ATTR_STACKSIZE POSIX SC 1 CDFUW
+THREAD_CPUTIME POSIX SC 1 FUW
+THREAD_DESTRUCTOR_ITERATIONS POSIX SC 1 LMUW PTHREAD_DESTRUCTOR_ITERATIONS 4
+THREAD_KEYS_MAX POSIX SC 1 LMUW PTHREAD_KEYS_MAX 128
+THREAD_PRIORITY_SCHEDULING POSIX SC 1 CDFUW
+THREAD_PRIO_INHERIT POSIX SC 1 CDFUW
+THREAD_PRIO_PROTECT POSIX SC 1 CDFUW
+THREAD_PROCESS_SHARED POSIX SC 1 CDFUW
+THREAD_SAFE_FUNCTIONS POSIX SC 1 CDFUW
+THREAD_SPORADIC_SERVER POSIX SC 1 FUW
+THREAD_STACK_MIN POSIX SC 1 LUW PTHREAD_STACK_MIN
+THREAD_THREADS_MAX POSIX SC 1 LMUW PTHREAD_THREADS_MAX 64
+TIMEOUTS POSIX SC 1 FUW
+TIMERS POSIX SC 1 CDFUW
+TIMER_MAX POSIX SC 1 LMU 32
+TMP AST CS 1 MU "/tmp"
+TMP_MAX C SC 1 LMU 10000
+TRACE POSIX SC 1 FUW
+TRACE_EVENT_FILTER POSIX SC 1 FUW
+TRACE_EVENT_NAME_MAX POSIX SC 1 FUVW
+TRACE_INHERIT POSIX SC 1 FUW
+TRACE_LOG POSIX SC 1 FUW
+TRACE_NAME_MAX POSIX SC 1 FUVW
+TRACE_SYS_MAX POSIX SC 1 FUVW
+TRACE_USER_EVENT_MAX POSIX SC 1 FUVW
+TTY_NAME_MAX POSIX SC 1 LMU 9
+TYPED_MEMORY_OBJECTS POSIX SC 1 FUW
+TZNAME_MAX POSIX SC 1 CDLMU 6
+T_IOV_MAX C QQ 1 0
+UCHAR_MAX C XX 1 L 255
+UCHAR_MIN C XX 1 L
+UID_MAX SVID SC 1 LMU 60002
+UINT_MAX C XX 1 L 65535
+UIO_MAXIOV C QQ 1 0
+ULLONG_MAX C XX 1 L
+ULONG_MAX C XX 1 L 4294967295
+UNIX XOPEN SC 1 FSUW
+UPE POSIX SC 2 CFUW
+USER_LIMIT SVID SI 1 O
+USHRT_MAX C XX 1 L 65535
+V6_ILP32_OFF32 POSIX SC 1 W
+V6_ILP32_OFFBIG POSIX SC 1 W
+V6_LP64_OFF64 POSIX SC 1 W
+V6_LPBIG_OFFBIG POSIX SC 1 W
+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 SVID SI 1 S
+VERSION XPG SC 3 DFSU
+VERSION XPG SC 4 DFSU
+VERSION_88 C XX 1 L
+VERSION_88 POSIX SC 1 FSU
+VERSION_90 C XX 1 L
+VERSION_90 POSIX SC 1 FSU
+VERSION_93 C XX 1 L
+VERSION_93 POSIX SC 1 FSU
+WCHAR_MAX C XX 1 L stddef.h
+WCHAR_MIN C XX 1 L stddef.h
+WINT_MIN C XX 1 L wchar.h
+WINT_MAX C XX 1 L wchar.h
+WORD_BIT XOPEN XX 1 L (8*sizeof(int))
+XCU_VERSION XOPEN SC 1 CDFSU
+XPG2 XOPEN XX 1 FU
+XPG3 XOPEN XX 1 FU
+XPG4 XOPEN XX 1 FU
+
+# vendor prefixes
+
+VERSION GNU XX 1 S
+VERSION TRUSTEDBSD XX 1 S
diff --git a/src/lib/libast/comp/creat64.c b/src/lib/libast/comp/creat64.c
new file mode 100644
index 0000000..7917f2f
--- /dev/null
+++ b/src/lib/libast/comp/creat64.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if defined(_lib_creat64) || !defined(_lib_open64)
+
+NoN(creat64)
+
+#else
+
+int
+creat64(const char* path, mode_t mode)
+{
+ return open64(path, O_WRONLY|O_CREAT|O_TRUNC, mode);
+}
+
+#endif
diff --git a/src/lib/libast/comp/dirname.c b/src/lib/libast/comp/dirname.c
new file mode 100644
index 0000000..b03d734
--- /dev/null
+++ b/src/lib/libast/comp/dirname.c
@@ -0,0 +1,61 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * dirname(3) implementation
+ */
+
+#include <ast_std.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char *dirname(register char *pathname)
+{
+ register char *last;
+ /* go to end of path */
+ for(last=pathname; *last; last++);
+ /* back over trailing '/' */
+ while(last>pathname && *--last=='/');
+ /* back over non-slash chars */
+ for(;last>pathname && *last!='/';last--);
+ if(last==pathname)
+ {
+ /* all '/' or "" */
+ if(*last!='/')
+ *last = '.';
+ /* preserve // */
+ else if(last[1]=='/')
+ last++;
+ }
+ else
+ {
+ /* back over trailing '/' */
+ for(;*last=='/' && last > pathname; last--);
+ /* preserve // */
+ if(last==pathname && *pathname=='/' && pathname[1]=='/')
+ last++;
+ }
+ *(last + 1) = 0;
+ return(pathname);
+}
diff --git a/src/lib/libast/comp/dup2.c b/src/lib/libast/comp/dup2.c
new file mode 100644
index 0000000..6999972
--- /dev/null
+++ b/src/lib/libast/comp/dup2.c
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_dup2
+
+NoN(dup2)
+
+#else
+
+#include <error.h>
+
+int
+dup2(int d1, int d2)
+{
+ int save_errno;
+
+ if (d1 == d2) return(d1);
+ save_errno = errno;
+ close(d2);
+ errno = save_errno;
+ return(fcntl(d1, F_DUPFD, d2));
+}
+
+#endif
diff --git a/src/lib/libast/comp/eaccess.c b/src/lib/libast/comp/eaccess.c
new file mode 100644
index 0000000..1fe44a7
--- /dev/null
+++ b/src/lib/libast/comp/eaccess.c
@@ -0,0 +1,139 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * access() euid/egid implementation
+ */
+
+#include <ast.h>
+#include <errno.h>
+#include <ls.h>
+
+#include "FEATURE/eaccess"
+
+#if _lib_eaccess
+
+NoN(eaccess)
+
+#else
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+eaccess(const char* path, register int flags)
+{
+#ifdef EFF_ONLY_OK
+ return access(path, flags|EFF_ONLY_OK);
+#else
+#if _lib_euidaccess
+ return euidaccess(path, flags);
+#else
+ register int mode;
+ struct stat st;
+
+ static int init;
+ static uid_t ruid;
+ static uid_t euid;
+ static gid_t rgid;
+ static gid_t egid;
+
+ if (!init)
+ {
+ ruid = getuid();
+ euid = geteuid();
+ rgid = getgid();
+ egid = getegid();
+ init = (ruid == euid && rgid == egid) ? 1 : -1;
+ }
+ if (init > 0 || flags == F_OK)
+ return access(path, flags);
+ if (stat(path, &st))
+ return -1;
+ mode = 0;
+ if (euid == 0)
+ {
+ if (!S_ISREG(st.st_mode) || !(flags & X_OK) || (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
+ return 0;
+ goto nope;
+ }
+ else if (euid == st.st_uid)
+ {
+ if (flags & R_OK)
+ mode |= S_IRUSR;
+ if (flags & W_OK)
+ mode |= S_IWUSR;
+ if (flags & X_OK)
+ mode |= S_IXUSR;
+ }
+ else if (egid == st.st_gid)
+ {
+#if _lib_getgroups
+ setgroup:
+#endif
+ if (flags & R_OK)
+ mode |= S_IRGRP;
+ if (flags & W_OK)
+ mode |= S_IWGRP;
+ if (flags & X_OK)
+ mode |= S_IXGRP;
+ }
+ else
+ {
+#if _lib_getgroups
+ register int n;
+
+ static int ngroups = -2;
+ static gid_t* groups;
+
+ if (ngroups == -2)
+ {
+ if ((ngroups = getgroups(0, (gid_t*)0)) <= 0)
+ ngroups = NGROUPS_MAX;
+ if (!(groups = newof(0, gid_t, ngroups + 1, 0)))
+ ngroups = -1;
+ else
+ ngroups = getgroups(ngroups, groups);
+ }
+ n = ngroups;
+ while (--n >= 0)
+ if (groups[n] == st.st_gid)
+ goto setgroup;
+#endif
+ if (flags & R_OK)
+ mode |= S_IROTH;
+ if (flags & W_OK)
+ mode |= S_IWOTH;
+ if (flags & X_OK)
+ mode |= S_IXOTH;
+ }
+ if ((st.st_mode & mode) == mode)
+ return 0;
+ nope:
+ errno = EACCES;
+ return -1;
+#endif
+#endif
+}
+
+#endif
diff --git a/src/lib/libast/comp/errno.c b/src/lib/libast/comp/errno.c
new file mode 100644
index 0000000..374a720
--- /dev/null
+++ b/src/lib/libast/comp/errno.c
@@ -0,0 +1,40 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _tst_errno
+
+NoN(errno)
+
+#else
+
+/*
+ * this avoids multiple definitions with some libc's
+ * that define both an ast library supplied routine and
+ * errno in the same .o
+ */
+
+int errno;
+
+#endif
diff --git a/src/lib/libast/comp/execlp.c b/src/lib/libast/comp/execlp.c
new file mode 100644
index 0000000..42de6ef
--- /dev/null
+++ b/src/lib/libast/comp/execlp.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast_lib.h>
+
+#if _lib_execlp
+
+#include <ast.h>
+
+NoN(execlp)
+
+#else
+
+#if defined(__EXPORT__)
+__EXPORT__ int execlp(const char*, const char*, ...);
+#endif
+
+#include <ast.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+execlp(const char* name, const char* arg, ...)
+{
+ return execvp(name, (char *const*)&arg);
+}
+
+#endif
diff --git a/src/lib/libast/comp/execve.c b/src/lib/libast/comp/execve.c
new file mode 100644
index 0000000..9d7e2ff
--- /dev/null
+++ b/src/lib/libast/comp/execve.c
@@ -0,0 +1,70 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_execve
+
+NoN(execve)
+
+#else
+
+#include <sig.h>
+#include <wait.h>
+#include <error.h>
+
+static pid_t childpid;
+
+static void
+execsig(int sig)
+{
+ kill(childpid, sig);
+ signal(sig, execsig);
+}
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+execve(const char* path, char* const argv[], char* const arge[])
+{
+ int status;
+
+ if ((childpid = spawnve(path, argv, arge)) < 0)
+ return(-1);
+ for (status = 0; status < 64; status++)
+ signal(status, execsig);
+ while (waitpid(childpid, &status, 0) == -1)
+ if (errno != EINTR) return(-1);
+ if (WIFSIGNALED(status))
+ {
+ signal(WTERMSIG(status), SIG_DFL);
+ kill(getpid(), WTERMSIG(status));
+ pause();
+ }
+ else status = WEXITSTATUS(status);
+ exit(status);
+}
+
+#endif
diff --git a/src/lib/libast/comp/execvp.c b/src/lib/libast/comp/execvp.c
new file mode 100644
index 0000000..1e34172
--- /dev/null
+++ b/src/lib/libast/comp/execvp.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast_lib.h>
+
+#if _lib_execvp
+
+#include <ast.h>
+
+NoN(execvp)
+
+#else
+
+#if defined(__EXPORT__)
+__EXPORT__ int execvp(const char*, char* const[]);
+#endif
+
+#include <ast.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+execvp(const char* name, char* const argv[])
+{
+ return execvpe(name, argv, environ);
+}
+
+#endif
diff --git a/src/lib/libast/comp/execvpe.c b/src/lib/libast/comp/execvpe.c
new file mode 100644
index 0000000..c711c50
--- /dev/null
+++ b/src/lib/libast/comp/execvpe.c
@@ -0,0 +1,78 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast_lib.h>
+
+#if _lib_execvpe
+
+#include <ast.h>
+
+NoN(execvpe)
+
+#else
+
+#if defined(__EXPORT__)
+__EXPORT__ int execvpe(const char*, char* const[], char* const[]);
+#endif
+
+#include <ast.h>
+#include <errno.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+execvpe(const char* name, char* const argv[], char* const envv[])
+{
+ register const char* path = name;
+ char buffer[PATH_MAX];
+
+ if (*path != '/' && !(path = pathpath(name, NULL, PATH_REGULAR|PATH_EXECUTE, buffer, sizeof(buffer))))
+ path = name;
+ execve(path, argv, envv);
+ if (errno == ENOEXEC)
+ {
+ register char** newargv;
+ register char** ov;
+ register char** nv;
+
+ for (ov = (char**)argv; *ov++;);
+ if (newargv = newof(0, char*, ov + 1 - (char**)argv, 0))
+ {
+ nv = newargv;
+ *nv++ = "sh";
+ *nv++ = (char*)path;
+ ov = (char**)argv;
+ while (*nv++ = *++ov);
+ path = pathshell();
+ execve(path, newargv, envv);
+ free(newargv);
+ }
+ else
+ errno = ENOMEM;
+ }
+ return -1;
+}
+
+#endif
diff --git a/src/lib/libast/comp/fakelink.h b/src/lib/libast/comp/fakelink.h
new file mode 100644
index 0000000..5683541
--- /dev/null
+++ b/src/lib/libast/comp/fakelink.h
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Bell Laboratories
+ *
+ * fake symbolic link private interface
+ */
+
+#ifndef _FAKELINK_H
+#define _FAKELINK_H
+
+#define FAKELINK_MAGIC "!<symlink>"
+
+#endif
diff --git a/src/lib/libast/comp/fcntl.c b/src/lib/libast/comp/fcntl.c
new file mode 100644
index 0000000..70adfee
--- /dev/null
+++ b/src/lib/libast/comp/fcntl.c
@@ -0,0 +1,98 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * -last fcntl
+ */
+
+#include <ast.h>
+
+#ifndef fcntl
+
+NoN(fcntl)
+
+#else
+
+#include <ls.h>
+#include <ast_tty.h>
+#include <error.h>
+
+#if F_SETFD >= _ast_F_LOCAL
+#if _sys_filio
+#include <sys/filio.h>
+#endif
+#endif
+
+#if _lib_fcntl
+#undef fcntl
+extern int fcntl(int, int, ...);
+#endif
+
+int
+_ast_fcntl(int fd, int op, ...)
+{
+ int n;
+ int save_errno;
+ struct stat st;
+ va_list ap;
+
+ save_errno = errno;
+ va_start(ap, op);
+ if (op >= _ast_F_LOCAL) switch (op)
+ {
+#if F_DUPFD >= _ast_F_LOCAL
+ case F_DUPFD:
+ n = va_arg(ap, int);
+ op = dup2(fd, n);
+ break;
+#endif
+#if F_GETFL >= _ast_F_LOCAL
+ case F_GETFL:
+ op = fstat(fd, &st);
+ break;
+#endif
+#if F_SETFD >= _ast_F_LOCAL && defined(FIOCLEX)
+ case F_SETFD:
+ n = va_arg(ap, int);
+ op = ioctl(fd, n == FD_CLOEXEC ? FIOCLEX : FIONCLEX, 0);
+ break;
+#endif
+ default:
+ errno = EINVAL;
+ op = -1;
+ break;
+ }
+ else
+#if _lib_fcntl
+ op = fcntl(fd, op, va_arg(ap, int));
+#else
+ {
+ errno = EINVAL;
+ op = -1;
+ }
+#endif
+ va_end(ap);
+ return(op);
+}
+
+#endif
diff --git a/src/lib/libast/comp/fmtmsg.h b/src/lib/libast/comp/fmtmsg.h
new file mode 100644
index 0000000..9360c41
--- /dev/null
+++ b/src/lib/libast/comp/fmtmsg.h
@@ -0,0 +1,141 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * fmtmsg interface definitions
+ */
+
+#ifndef _FMTMSG_H
+#define _FMTMSG_H
+
+#define MM_VERB_ENV "MSGVERB" /* keyword filter env var */
+#define MM_SEVERITY_ENV "SEV_LEVEL" /* alternate severity env var */
+
+/* max component length */
+
+#define MM_LABEL_1_MAX 10 /* label field 1 length */
+#define MM_LABEL_2_MAX 14 /* label field 2 length */
+
+/* classification type */
+
+#define MM_HARD 0x00000001L /* hardware */
+#define MM_SOFT 0x00000002L /* software */
+#define MM_FIRM 0x00000004L /* firmware */
+
+/* classification source */
+
+#define MM_APPL 0x00000010L /* application */
+#define MM_UTIL 0x00000020L /* utility */
+#define MM_OPSYS 0x00000040L /* kernel */
+
+/* classification display */
+
+#define MM_PRINT 0x00000100L /* stderr */
+#define MM_CONSOLE 0x00000200L /* console */
+
+/* classification status */
+
+#define MM_RECOVER 0x00001000L /* recoverable */
+#define MM_NRECOV 0x00002000L /* non-recoverable */
+
+/* severity */
+
+#define MM_NOSEV 0x0 /* no severity */
+#define MM_HALT 0x1 /* severe fault */
+#define MM_ERROR 0x2 /* fault */
+#define MM_WARNING 0x4 /* could be a problem */
+#define MM_INFO 0x8 /* not an error (noise?) */
+
+/* fmtmsg return value */
+
+#define MM_OK 0 /* succeeded */
+#define MM_NOTOK 3 /* failed completely */
+#define MM_NOMSG 1 /* stderr message failed */
+#define MM_NOCON 2 /* console message failed */
+
+/* null argument values -- 0 just doesn't get any respect */
+
+#define MM_NULLLBL (char*)0 /* label */
+#define MM_NULLSEV 0 /* severity */
+#define MM_NULLMC 0L /* class */
+#define MM_NULLTXT (char*)0 /* text */
+#define MM_NULLACT (char*)0 /* action */
+#define MM_NULLTAG (char*)0 /* tag */
+
+#ifdef MM_TABLES
+
+/* encoding support */
+
+typedef struct
+{
+ const char* name;
+ const char* display;
+ unsigned int value;
+} MM_table_t;
+
+#define mm_class _mm_class
+#define mm_severity _mm_severity()
+#define mm_verb _mm_verb
+
+#define MM_all 0xff
+#define MM_action 0x01
+#define MM_class 0x02
+#define MM_label 0x04
+#define MM_severity 0x08
+#define MM_source 0x10
+#define MM_status 0x20
+#define MM_tag 0x40
+#define MM_text 0x80
+
+#define MM_default (MM_action|MM_label|MM_severity|MM_tag|MM_text)
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+#if !_BLD_ast && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern const MM_table_t mm_class[];
+extern const MM_table_t mm_verb[];
+
+#undef extern
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern const MM_table_t* mm_severity;
+
+#undef extern
+
+#endif
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int fmtmsg(long, const char*, int, const char*, const char*, const char*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/comp/fmtmsglib.c b/src/lib/libast/comp/fmtmsglib.c
new file mode 100644
index 0000000..3484223
--- /dev/null
+++ b/src/lib/libast/comp/fmtmsglib.c
@@ -0,0 +1,335 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * fmtmsg implementation
+ */
+
+#include <ast.h>
+
+#if _lib_fmtmsg
+
+NoN(fmtmsg)
+
+#else
+
+#define MM_TABLES
+
+#include <fmtmsg.h>
+
+#define INIT_VERB 0x1
+#define INIT_CONSOLE 0x2
+
+static struct
+{
+ int console;
+ unsigned int init;
+ unsigned int mask;
+} mm;
+
+const MM_table_t mm_class[] =
+{
+ "null", 0, 0,
+ "hard", "HARDWARE", MM_HARD,
+ "soft", "SOFTWARE", MM_SOFT,
+ "firm", "FIRMWARE", MM_FIRM,
+ "appl", "APPLICATION", MM_APPL,
+ "util", "UTILITY", MM_UTIL,
+ "opsys", "KERNEL", MM_OPSYS,
+ "print", 0, MM_PRINT,
+ "console", 0, MM_CONSOLE,
+ "recov", "RECOVERABLE", MM_RECOVER,
+ "nrecov", "PANIC", MM_NRECOV,
+ 0, 0, 0
+};
+
+static const MM_table_t mm_severity_init[] =
+{
+ "nosev", 0, MM_NOSEV,
+ "halt", "HALT", MM_HALT,
+ "error", "ERROR", MM_ERROR,
+ "warn", "WARNING", MM_WARNING,
+ "info", "INFO", MM_INFO,
+ 0, 0, 0
+};
+
+const MM_table_t mm_verb[] =
+{
+ "all", 0, MM_all,
+ "action", 0, MM_action,
+ "class", 0, MM_class,
+ "default", 0, MM_default,
+ "label", 0, MM_label,
+ "severity", 0, MM_severity,
+ "source", 0, MM_source,
+ "tag", 0, MM_tag,
+ "text", 0, MM_text,
+ 0, 0, 0
+};
+
+const MM_table_t*
+_mm_severity(void)
+{
+ static MM_table_t* severity;
+
+ if (!severity)
+ {
+ register char* s;
+ register MM_table_t* p;
+ register int n;
+ register int c;
+ char* e;
+ MM_table_t* q;
+
+ n = 0;
+ if ((s = getenv(MM_SEVERITY_ENV)) && *s)
+ {
+ e = s;
+ c = 0;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ break;
+ case ',':
+ if (++c > 2)
+ {
+ n = 0;
+ break;
+ }
+ continue;
+ case ':':
+ if (c != 2)
+ {
+ n = 0;
+ break;
+ }
+ c = 0;
+ n++;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ if (c == 2)
+ n++;
+ else n = 0;
+ if (n)
+ {
+ for (p = (MM_table_t*)mm_severity_init; p->name; p++);
+ n += p - (MM_table_t*)mm_severity_init + 1;
+ if (severity = newof(0, MM_table_t, n, s - e))
+ {
+ s = (char*)severity + n * sizeof(MM_table_t);
+ strcpy(s, e);
+ p = severity;
+ for (q = (MM_table_t*)mm_severity_init; q->name; q++)
+ *p++ = *q;
+ p->name = s;
+ c = 0;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ break;
+ case ',':
+ switch (c++)
+ {
+ case 0:
+ *(s - 1) = 0;
+ p->value = strtol(s, NiL, 0);
+ break;
+ case 1:
+ p->display = s;
+ break;
+ }
+ continue;
+ case ':':
+ c = 0;
+ *(s - 1) = 0;
+ (++p)->name = s;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ }
+ }
+ }
+ if (!severity)
+ severity = (MM_table_t*)mm_severity_init;
+ }
+ return (const MM_table_t*)severity;
+}
+
+static char*
+display(register const MM_table_t* tab, int value, int mask)
+{
+ while (tab->name)
+ {
+ if (value == tab->value || mask && (value & tab->value))
+ return (char*)tab->display;
+ tab++;
+ }
+ return 0;
+}
+
+int
+fmtmsg(long classification, const char* label, int severity, const char* text, const char* action, const char* tag)
+{
+ register int c;
+ register char* s;
+ register char* t;
+ register MM_table_t* p;
+ int n;
+ int m;
+ int r;
+ int fd;
+ unsigned int mask;
+ Sfio_t* sp;
+ char lab[MM_LABEL_1_MAX + MM_LABEL_2_MAX + 3];
+
+ if (!mm.init)
+ {
+ mm.init = INIT_VERB;
+ if (!(s = getenv(MM_VERB_ENV)))
+ mm.mask = MM_default;
+ else for (;;)
+ {
+ if (t = strchr(s, ':'))
+ *t = 0;
+ if (!(p = (MM_table_t*)strlook(mm_verb, sizeof(MM_table_t), s)))
+ {
+ mm.mask = MM_default;
+ if (t)
+ *t = ':';
+ break;
+ }
+ mm.mask |= p->value;
+ if (!t)
+ break;
+ *t++ = ':';
+ s = t;
+ }
+ }
+ if (!(classification & (MM_CONSOLE|MM_PRINT)))
+ return 0;
+ if (!(sp = sfstropen()))
+ return MM_NOTOK;
+ r = 0;
+ if (s = (char*)label)
+ {
+ if (t = strchr(s, ':'))
+ {
+ if ((n = t - s) > MM_LABEL_1_MAX)
+ n = MM_LABEL_1_MAX;
+ sfprintf(sp, "%*.*s:", n, n, s);
+ s = ++t;
+ if ((n = strlen(t)) > MM_LABEL_2_MAX)
+ n = MM_LABEL_2_MAX;
+ sfprintf(sp, "%*.*s", n, n, s);
+ }
+ else
+ {
+ if ((n = strlen(t)) > MM_LABEL_1_MAX)
+ n = MM_LABEL_1_MAX;
+ sfprintf(sp, "%*.*s", n, n, s);
+ }
+ if (!(s = sfstruse(sp)))
+ {
+ sfstrclose(sp);
+ return MM_NOTOK;
+ }
+ strcpy(lab, s);
+ }
+ for (;;)
+ {
+ if (classification & MM_CONSOLE)
+ {
+ classification &= ~MM_CONSOLE;
+ if (!(mm.init & INIT_CONSOLE))
+ mm.console = open("/dev/console", O_WRONLY|O_APPEND|O_NOCTTY);
+ if (mm.console < 0)
+ {
+ r |= MM_NOCON;
+ continue;
+ }
+ c = MM_NOCON;
+ fd = mm.console;
+ mask = MM_all;
+ }
+ else if (classification & MM_PRINT)
+ {
+ classification &= ~MM_PRINT;
+ c = MM_NOMSG;
+ fd = 2;
+ mask = mm.mask;
+ }
+ else break;
+ if ((mask & MM_label) && label)
+ sfprintf(sp, "%s: ", lab);
+ if ((mask & MM_severity) && (s = display(mm_severity, severity, 0)))
+ sfprintf(sp, "%s: ", s);
+ n = sfstrtell(sp);
+ if ((mask & MM_text) && text)
+ sfprintf(sp, "%s\n", text);
+ else sfputc(sp, '\n');
+ if ((mask & MM_action) && action || (mask & MM_tag) && (label || tag))
+ {
+ if (fd != mm.console && (n -= 8) > 0)
+ sfprintf(sp, "%*.*s", n, n, "");
+ sfprintf(sp, "TO FIX:");
+ if ((mask & MM_action) && action)
+ sfprintf(sp, " %s", action);
+ if ((mask & MM_tag) && (label || tag))
+ {
+ sfprintf(sp, " ");
+ if (!tag || label && !strchr(tag, ':'))
+ sfprintf(sp, "%s%s", lab, tag ? ":" : "");
+ if (tag)
+ sfprintf(sp, "%s", tag);
+ }
+ if (mask & (MM_class|MM_source|MM_status))
+ {
+ sfputc(sp, ' ');
+ if ((mask & MM_source) && (m = classification & (MM_APPL|MM_UTIL|MM_OPSYS)) && (s = display(mm_class, m, 1)))
+ sfprintf(sp, " %s", s);
+ if ((mask & MM_class) && (m = classification & (MM_HARD|MM_SOFT|MM_FIRM)) && (s = display(mm_class, m, 1)))
+ sfprintf(sp, " %s", s);
+ if ((mask & MM_status) && (m = classification & (MM_RECOVER|MM_NRECOV)) && (s = display(mm_class, m, 1)))
+ sfprintf(sp, " %s", s);
+ }
+ sfputc(sp, '\n');
+ }
+ n = sfstrtell(sp);
+ if (!(s = sfstruse(sp)) || write(fd, s, n) != n)
+ r |= c;
+ }
+ sfstrclose(sp);
+ return r;
+}
+
+#endif
diff --git a/src/lib/libast/comp/fnmatch.c b/src/lib/libast/comp/fnmatch.c
new file mode 100644
index 0000000..6c31998
--- /dev/null
+++ b/src/lib/libast/comp/fnmatch.c
@@ -0,0 +1,79 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * fnmatch implementation
+ */
+
+#include <ast_lib.h>
+
+#include <ast.h>
+#include <regex.h>
+#include <fnmatch.h>
+
+typedef struct
+{
+ int fnm; /* fnmatch flag */
+ int reg; /* regex flag */
+} Map_t;
+
+static const Map_t map[] =
+{
+ FNM_AUGMENTED, REG_AUGMENTED,
+ FNM_ICASE, REG_ICASE,
+ FNM_NOESCAPE, REG_SHELL_ESCAPED,
+ FNM_PATHNAME, REG_SHELL_PATH,
+ FNM_PERIOD, REG_SHELL_DOT,
+};
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+fnmatch(const char* pattern, const char* subject, register int flags)
+{
+ register int reflags = REG_SHELL|REG_LEFT;
+ register const Map_t* mp;
+ regex_t re;
+ regmatch_t match;
+
+ for (mp = map; mp < &map[elementsof(map)]; mp++)
+ if (flags & mp->fnm)
+ reflags |= mp->reg;
+ if (flags & FNM_LEADING_DIR)
+ {
+ if (!(reflags = regcomp(&re, pattern, reflags)))
+ {
+ reflags = regexec(&re, subject, 1, &match, 0);
+ regfree(&re);
+ if (!reflags && (reflags = subject[match.rm_eo]))
+ reflags = reflags == '/' ? 0 : FNM_NOMATCH;
+ }
+ }
+ else if (!(reflags = regcomp(&re, pattern, reflags|REG_RIGHT)))
+ {
+ reflags = regexec(&re, subject, 0, NiL, 0);
+ regfree(&re);
+ }
+ return reflags;
+}
diff --git a/src/lib/libast/comp/fnmatch.h b/src/lib/libast/comp/fnmatch.h
new file mode 100644
index 0000000..945e645
--- /dev/null
+++ b/src/lib/libast/comp/fnmatch.h
@@ -0,0 +1,61 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * posix fnmatch interface definitions
+ */
+
+#ifndef _FNMATCH_H
+#define _FNMATCH_H
+
+#include <ast_common.h>
+
+/* fnmatch flags */
+
+#define FNM_NOESCAPE 0x0001 /* \ is literal */
+#define FNM_PATHNAME 0x0002 /* explicit match for / */
+#define FNM_PERIOD 0x0004 /* explicit match for leading . */
+#define FNM_NOSYS 0x0010 /* not implemented */
+
+/* nonstandard fnmatch() flags */
+
+#define FNM_AUGMENTED 0x0008 /* enable ! & ( | ) */
+#define FNM_ICASE 0x0020 /* ignore case in match */
+#define FNM_LEADING_DIR 0x0040 /* match up to implicit / */
+
+#define FNM_CASEFOLD FNM_ICASE /* gnu/bsd compatibility */
+#define FNM_IGNORECASE FNM_ICASE /* gnu/bsd compatibility */
+#define FNM_FILE_NAME FNM_PATHNAME /* gnu compatibility */
+
+/* fnmatch error codes -- other non-zero values from <regex.h> */
+
+#define FNM_NOMATCH 1 /* == REG_NOMATCH */
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int fnmatch(const char*, const char*, int);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/comp/frexp.c b/src/lib/libast/comp/frexp.c
new file mode 100644
index 0000000..02cd50f
--- /dev/null
+++ b/src/lib/libast/comp/frexp.c
@@ -0,0 +1,153 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * frexp/ldexp implementation
+ */
+
+#include <ast.h>
+
+#include "FEATURE/float"
+
+#if _lib_frexp && _lib_ldexp
+
+NoN(frexp)
+
+#else
+
+#if defined(_ast_dbl_exp_index) && defined(_ast_dbl_exp_shift)
+
+#define INIT() _ast_dbl_exp_t _pow_
+#define pow2(i) (_pow_.f=1,_pow_.e[_ast_dbl_exp_index]+=((i)<<_ast_dbl_exp_shift),_pow_.f)
+
+#else
+
+static double pow2tab[DBL_MAX_EXP + 1];
+
+static int
+init(void)
+{
+ register int x;
+ double g;
+
+ g = 1;
+ for (x = 0; x < elementsof(pow2tab); x++)
+ {
+ pow2tab[x] = g;
+ g *= 2;
+ }
+ return 0;
+}
+
+#define INIT() (pow2tab[0]?0:init())
+
+#define pow2(i) pow2tab[i]
+
+#endif
+
+#if !_lib_frexp
+
+extern double
+frexp(double f, int* p)
+{
+ register int k;
+ register int x;
+ double g;
+
+ INIT();
+
+ /*
+ * normalize
+ */
+
+ x = k = DBL_MAX_EXP / 2;
+ if (f < 1)
+ {
+ g = 1.0L / f;
+ for (;;)
+ {
+ k = (k + 1) / 2;
+ if (g < pow2(x))
+ x -= k;
+ else if (k == 1 && g < pow2(x+1))
+ break;
+ else
+ x += k;
+ }
+ if (g == pow2(x))
+ x--;
+ x = -x;
+ }
+ else if (f > 1)
+ {
+ for (;;)
+ {
+ k = (k + 1) / 2;
+ if (f > pow2(x))
+ x += k;
+ else if (k == 1 && f > pow2(x-1))
+ break;
+ else
+ x -= k;
+ }
+ if (f == pow2(x))
+ x++;
+ }
+ else
+ x = 1;
+ *p = x;
+
+ /*
+ * shift
+ */
+
+ x = -x;
+ if (x < 0)
+ f /= pow2(-x);
+ else if (x < DBL_MAX_EXP)
+ f *= pow2(x);
+ else
+ f = (f * pow2(DBL_MAX_EXP - 1)) * pow2(x - (DBL_MAX_EXP - 1));
+ return f;
+}
+
+#endif
+
+#if !_lib_ldexp
+
+extern double
+ldexp(double f, register int x)
+{
+ INIT();
+ if (x < 0)
+ f /= pow2(-x);
+ else if (x < DBL_MAX_EXP)
+ f *= pow2(x);
+ else
+ f = (f * pow2(DBL_MAX_EXP - 1)) * pow2(x - (DBL_MAX_EXP - 1));
+ return f;
+}
+
+#endif
+
+#endif
diff --git a/src/lib/libast/comp/frexpl.c b/src/lib/libast/comp/frexpl.c
new file mode 100644
index 0000000..5d90ad9
--- /dev/null
+++ b/src/lib/libast/comp/frexpl.c
@@ -0,0 +1,161 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * frexpl/ldexpl implementation
+ */
+
+#include <ast.h>
+
+#include "FEATURE/float"
+
+#if _lib_frexpl && _lib_ldexpl
+
+NoN(frexpl)
+
+#else
+
+#ifndef LDBL_MAX_EXP
+#define LDBL_MAX_EXP DBL_MAX_EXP
+#endif
+
+#if defined(_ast_fltmax_exp_index) && defined(_ast_fltmax_exp_shift)
+
+#define INIT() _ast_fltmax_exp_t _pow_
+#define pow2(i) (_pow_.f=1,_pow_.e[_ast_fltmax_exp_index]+=((i)<<_ast_fltmax_exp_shift),_pow_.f)
+
+#else
+
+static _ast_fltmax_t pow2tab[LDBL_MAX_EXP + 1];
+
+static int
+init(void)
+{
+ register int x;
+ _ast_fltmax_t g;
+
+ g = 1;
+ for (x = 0; x < elementsof(pow2tab); x++)
+ {
+ pow2tab[x] = g;
+ g *= 2;
+ }
+ return 0;
+}
+
+#define INIT() (pow2tab[0]?0:init())
+
+#define pow2(i) (pow2tab[i])
+
+#endif
+
+#if !_lib_frexpl
+
+#undef frexpl
+
+extern _ast_fltmax_t
+frexpl(_ast_fltmax_t f, int* p)
+{
+ register int k;
+ register int x;
+ _ast_fltmax_t g;
+
+ INIT();
+
+ /*
+ * normalize
+ */
+
+ x = k = LDBL_MAX_EXP / 2;
+ if (f < 1)
+ {
+ g = 1.0L / f;
+ for (;;)
+ {
+ k = (k + 1) / 2;
+ if (g < pow2(x))
+ x -= k;
+ else if (k == 1 && g < pow2(x+1))
+ break;
+ else
+ x += k;
+ }
+ if (g == pow2(x))
+ x--;
+ x = -x;
+ }
+ else if (f > 1)
+ {
+ for (;;)
+ {
+ k = (k + 1) / 2;
+ if (f > pow2(x))
+ x += k;
+ else if (k == 1 && f > pow2(x-1))
+ break;
+ else
+ x -= k;
+ }
+ if (f == pow2(x))
+ x++;
+ }
+ else
+ x = 1;
+ *p = x;
+
+ /*
+ * shift
+ */
+
+ x = -x;
+ if (x < 0)
+ f /= pow2(-x);
+ else if (x < LDBL_MAX_EXP)
+ f *= pow2(x);
+ else
+ f = (f * pow2(LDBL_MAX_EXP - 1)) * pow2(x - (LDBL_MAX_EXP - 1));
+ return f;
+}
+
+#endif
+
+#if !_lib_ldexpl
+
+#undef ldexpl
+
+extern _ast_fltmax_t
+ldexpl(_ast_fltmax_t f, register int x)
+{
+ INIT();
+ if (x < 0)
+ f /= pow2(-x);
+ else if (x < LDBL_MAX_EXP)
+ f *= pow2(x);
+ else
+ f = (f * pow2(LDBL_MAX_EXP - 1)) * pow2(x - (LDBL_MAX_EXP - 1));
+ return f;
+}
+
+#endif
+
+#endif
diff --git a/src/lib/libast/comp/fsync.c b/src/lib/libast/comp/fsync.c
new file mode 100644
index 0000000..4223fa0
--- /dev/null
+++ b/src/lib/libast/comp/fsync.c
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_fsync
+
+NoN(fsync)
+
+#else
+
+#include <error.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+int
+fsync(int fd)
+{
+ NoP(fd);
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif
diff --git a/src/lib/libast/comp/ftw.c b/src/lib/libast/comp/ftw.c
new file mode 100644
index 0000000..4722628
--- /dev/null
+++ b/src/lib/libast/comp/ftw.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * ftw implementation
+ */
+
+#include <ast.h>
+#include <ftw.h>
+
+static int (*ftw_userf)(const char*, const struct stat*, int);
+
+static int
+ftw_user(Ftw_t* ftw)
+{
+ register int n = ftw->info;
+
+ if (n & (FTW_C|FTW_NX))
+ n = FTW_DNR;
+ else if (n & FTW_SL)
+ n = FTW_NS;
+ return (*ftw_userf)(ftw->path, &ftw->statb, n);
+}
+
+int
+ftw(const char* path, int(*userf)(const char*, const struct stat*, int), int depth)
+{
+ NoP(depth);
+ ftw_userf = userf;
+ return ftwalk(path, ftw_user, FTW_DOT, NiL);
+}
diff --git a/src/lib/libast/comp/ftw.h b/src/lib/libast/comp/ftw.h
new file mode 100644
index 0000000..a61f548
--- /dev/null
+++ b/src/lib/libast/comp/ftw.h
@@ -0,0 +1,60 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * ftw,nftw over ftwalk
+ */
+
+#ifndef _FTW_H
+#define _FTW_H
+
+#define FTW FTWALK
+#include <ftwalk.h>
+#undef FTW
+
+#define FTW_SLN (FTW_SL|FTW_NR)
+
+#define FTW_PHYS (FTW_PHYSICAL)
+#define FTW_CHDIR (FTW_DOT)
+#define FTW_DEPTH (FTW_POST)
+#define FTW_OPEN (0)
+
+struct FTW
+{
+ int quit;
+ int base;
+ int level;
+};
+
+#define FTW_SKD FTW_SKIP
+#define FTW_PRUNE FTW_SKIP
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int ftw(const char*, int(*)(const char*, const struct stat*, int), int);
+extern int nftw(const char*, int(*)(const char*, const struct stat*, int, struct FTW*), int, int);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/comp/getdate.c b/src/lib/libast/comp/getdate.c
new file mode 100644
index 0000000..455c5fb
--- /dev/null
+++ b/src/lib/libast/comp/getdate.c
@@ -0,0 +1,83 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * getdate implementation
+ */
+
+#define getdate ______getdate
+
+#include <ast.h>
+#include <tm.h>
+
+#undef getdate
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#undef _lib_getdate /* we can pass X/Open */
+
+#if _lib_getdate
+
+NoN(getdate)
+
+#else
+
+#ifndef getdate_err
+__DEFINE__(int, getdate_err, 0);
+#endif
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern struct tm*
+getdate(const char* s)
+{
+ char* e;
+ char* f;
+ time_t t;
+ Tm_t* tm;
+
+ static struct tm ts;
+
+ t = tmscan(s, &e, NiL, &f, NiL, TM_PEDANTIC);
+ if (*e || *f)
+ {
+ /* of course we all know what 7 means */
+ getdate_err = 7;
+ return 0;
+ }
+ tm = tmmake(&t);
+ ts.tm_sec = tm->tm_sec;
+ ts.tm_min = tm->tm_min;
+ ts.tm_hour = tm->tm_hour;
+ ts.tm_mday = tm->tm_mday;
+ ts.tm_mon = tm->tm_mon;
+ ts.tm_year = tm->tm_year;
+ ts.tm_wday = tm->tm_wday;
+ ts.tm_yday = tm->tm_yday;
+ ts.tm_isdst = tm->tm_isdst;
+ return &ts;
+}
+
+#endif
diff --git a/src/lib/libast/comp/getgroups.c b/src/lib/libast/comp/getgroups.c
new file mode 100644
index 0000000..8b90bf0
--- /dev/null
+++ b/src/lib/libast/comp/getgroups.c
@@ -0,0 +1,78 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if !defined(getgroups) && defined(_lib_getgroups)
+
+NoN(getgroups)
+
+#else
+
+#include <error.h>
+
+#if defined(getgroups)
+#undef getgroups
+#define ast_getgroups _ast_getgroups
+#define botched 1
+extern int getgroups(int, int*);
+#else
+#define ast_getgroups getgroups
+#endif
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+ast_getgroups(int len, gid_t* set)
+{
+#if botched
+#if NGROUPS_MAX < 1
+#undef NGROUPS_MAX
+#define NGROUPS_MAX 1
+#endif
+ register int i;
+ int big[NGROUPS_MAX];
+#else
+#undef NGROUPS_MAX
+#define NGROUPS_MAX 1
+#endif
+ if (!len) return(NGROUPS_MAX);
+ if (len < 0 || !set)
+ {
+ errno = EINVAL;
+ return(-1);
+ }
+#if botched
+ len = getgroups(len > NGROUPS_MAX ? NGROUPS_MAX : len, big);
+ for (i = 0; i < len; i++)
+ set[i] = big[i];
+ return(len);
+#else
+ *set = getgid();
+ return(1);
+#endif
+}
+
+#endif
diff --git a/src/lib/libast/comp/getlogin.c b/src/lib/libast/comp/getlogin.c
new file mode 100644
index 0000000..7611dbb
--- /dev/null
+++ b/src/lib/libast/comp/getlogin.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_getlogin
+
+NoN(getlogin)
+
+#else
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char*
+getlogin(void)
+{
+ return fmtuid(getuid());
+}
+
+#endif
diff --git a/src/lib/libast/comp/getopt.c b/src/lib/libast/comp/getopt.c
new file mode 100644
index 0000000..c5c6f19
--- /dev/null
+++ b/src/lib/libast/comp/getopt.c
@@ -0,0 +1,78 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#undef _lib_getopt /* we can satisfy the api */
+
+#if _lib_getopt
+
+NoN(getopt)
+
+#else
+
+#undef _BLD_ast /* enable ast imports since we're user static */
+
+#include <error.h>
+#include <option.h>
+
+int opterr = 1;
+int optind = 1;
+int optopt = 0;
+char* optarg = 0;
+
+static int lastoptind;
+
+extern int
+getopt(int argc, char* const* argv, const char* optstring)
+{
+ int n;
+
+ NoP(argc);
+ opt_info.index = (optind > 1 || optind == lastoptind) ? optind : 0;
+ if (opt_info.index >= argc)
+ return -1;
+ switch (n = optget((char**)argv, optstring))
+ {
+ case ':':
+ n = '?';
+ /*FALLTHROUGH*/
+ case '?':
+ if (opterr && (!optstring || *optstring != ':'))
+ {
+ if (!error_info.id)
+ error_info.id = argv[0];
+ errormsg(NiL, 2, opt_info.arg);
+ }
+ optopt = opt_info.option[1];
+ break;
+ case 0:
+ n = -1;
+ break;
+ }
+ optarg = opt_info.arg;
+ lastoptind = optind = opt_info.index;
+ return n;
+}
+
+#endif
diff --git a/src/lib/libast/comp/getopt.h b/src/lib/libast/comp/getopt.h
new file mode 100644
index 0000000..110ce39
--- /dev/null
+++ b/src/lib/libast/comp/getopt.h
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * gnu getopt interface
+ */
+
+#ifndef _GETOPT_H
+#ifdef _AST_STD_I
+#define _GETOPT_H -1
+#else
+#define _GETOPT_H 1
+
+#include <ast_getopt.h>
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+struct option
+{
+ const char* name;
+ int has_arg;
+ int* flag;
+ int val;
+};
+
+extern int getopt_long(int, char* const*, const char*, const struct option*, int*);
+extern int getopt_long_only(int, char* const*, const char*, const struct option*, int*);
+
+#endif
+#endif
diff --git a/src/lib/libast/comp/getoptl.c b/src/lib/libast/comp/getoptl.c
new file mode 100644
index 0000000..edfa4f1
--- /dev/null
+++ b/src/lib/libast/comp/getoptl.c
@@ -0,0 +1,151 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <ast_getopt.h>
+
+#undef _BLD_ast /* enable ast imports since we're user static */
+
+#include <error.h>
+#include <option.h>
+#include <getopt.h>
+#include <ctype.h>
+
+static const char* lastoptstring;
+static const struct option* lastlongopts;
+static char* usage;
+static Sfio_t* up;
+
+static int lastoptind;
+
+static int
+golly(int argc, char* const* argv, const char* optstring, const struct option* longopts, int* longindex, int flags)
+{
+ register char* s;
+ register const struct option* o;
+ register int c;
+ char* t;
+
+ if (!up || optstring != lastoptstring || longopts != lastlongopts)
+ {
+ if (!up && !(up = sfstropen()) || !(t = strdup(optstring)))
+ return -1;
+ sfprintf(up, "[-1p%d]", flags);
+ for (o = longopts; o->name; o++)
+ {
+ if (o->flag || o->val <= 0 || o->val > UCHAR_MAX || !isalnum(o->val))
+ sfprintf(up, "\n[%d:%s]", UCHAR_MAX + 1 + (o - longopts), o->name);
+ else
+ {
+ sfprintf(up, "\n[%c:%s]", o->val, o->name);
+ if (s = strchr(t, o->val))
+ {
+ *s++ = ' ';
+ if (*s == ':')
+ {
+ *s++ = ' ';
+ if (*s == ':')
+ *s = ' ';
+ }
+ }
+ }
+ if (o->has_arg)
+ {
+ sfputc(up, ':');
+ if (o->has_arg == optional_argument)
+ sfputc(up, '?');
+ sfprintf(up, "[string]");
+ }
+ }
+ s = t;
+ while (c = *s++)
+ if (c != ' ')
+ {
+ sfprintf(up, "\n[%c]", c);
+ if (*s == ':')
+ {
+ sfputc(up, *s);
+ if (*++s == ':')
+ {
+ sfputc(up, '?');
+ s++;
+ }
+ sfputc(up, '[');
+ sfputc(up, ']');
+ }
+ }
+ sfputc(up, '\n');
+ free(t);
+ if (!(usage = sfstruse(up)))
+ return -1;
+ lastoptstring = optstring;
+ lastlongopts = longopts;
+ }
+ opt_info.index = (optind > 1 || optind == lastoptind) ? optind : 0;
+ if (opt_info.index >= argc || !(c = optget((char**)argv, usage)))
+ {
+ sfstrclose(up);
+ up = 0;
+ c = -1;
+ }
+ else
+ {
+ if (c == ':' || c == '?')
+ {
+ if (opterr && (!optstring || *optstring != ':'))
+ {
+ if (!error_info.id)
+ error_info.id = argv[0];
+ errormsg(NiL, c == '?' ? (ERROR_USAGE|4) : 2, "%s", opt_info.arg);
+ }
+ optopt = opt_info.option[1];
+ c = '?';
+ }
+ optarg = opt_info.arg;
+ if (c < 0)
+ {
+ o = longopts - c - UCHAR_MAX - 1;
+ if (o->flag)
+ {
+ *o->flag = o->val;
+ c = 0;
+ }
+ else
+ c = o->val;
+ }
+ }
+ lastoptind = optind = opt_info.index;
+ return c;
+}
+
+extern int
+getopt_long(int argc, char* const* argv, const char* optstring, const struct option* longopts, int* longindex)
+{
+ return golly(argc, argv, optstring, longopts, longindex, 2);
+}
+
+extern int
+getopt_long_only(int argc, char* const* argv, const char* optstring, const struct option* longopts, int* longindex)
+{
+ return golly(argc, argv, optstring, longopts, longindex, 1);
+}
diff --git a/src/lib/libast/comp/getpgrp.c b/src/lib/libast/comp/getpgrp.c
new file mode 100644
index 0000000..b38ad8a
--- /dev/null
+++ b/src/lib/libast/comp/getpgrp.c
@@ -0,0 +1,47 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#define getpgrp ______getpgrp
+
+#include <ast_std.h>
+
+#undef getpgrp
+
+/*
+ * bsd int getpgrp(int);
+ * s5 int getpgrp(void);
+ * posix pid_t getpgrp(void);
+ * user SOL
+ */
+
+extern int getpgrp(int);
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+_ast_getpgrp(void)
+{
+ return getpgrp(0);
+}
diff --git a/src/lib/libast/comp/getsubopt.c b/src/lib/libast/comp/getsubopt.c
new file mode 100644
index 0000000..9d7162c
--- /dev/null
+++ b/src/lib/libast/comp/getsubopt.c
@@ -0,0 +1,84 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Xopen 4.2 compatibility
+ */
+
+#include <ast.h>
+
+#undef _lib_getsubopt /* we can satisfy the api */
+
+#if _lib_getsubopt
+
+NoN(getsubopt)
+
+#else
+
+#undef _BLD_ast /* enable ast imports since we're user static */
+
+#include <error.h>
+
+extern int
+getsubopt(register char** op, char* const* tp, char** vp)
+{
+ register char* b;
+ register char* s;
+ register char* v;
+
+ if (*(b = *op))
+ {
+ v = 0;
+ s = b;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ s--;
+ break;
+ case ',':
+ *(s - 1) = 0;
+ break;
+ case '=':
+ if (!v)
+ {
+ *(s - 1) = 0;
+ v = s;
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ *op = s;
+ *vp = v;
+ for (op = (char**)tp; *op; op++)
+ if (streq(b, *op))
+ return op - (char**)tp;
+ }
+ *vp = b;
+ return -1;
+}
+
+#endif
diff --git a/src/lib/libast/comp/getwd.c b/src/lib/libast/comp/getwd.c
new file mode 100644
index 0000000..e600155
--- /dev/null
+++ b/src/lib/libast/comp/getwd.c
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * getwd() using getcwd()
+ *
+ * some getwd()'s are incredible
+ */
+
+#include <ast.h>
+
+char*
+getwd(char* path)
+{
+ if (getcwd(path, PATH_MAX)) return(path);
+ strcpy(path, "getwd: error in . or ..");
+ return(0);
+}
diff --git a/src/lib/libast/comp/gross.c b/src/lib/libast/comp/gross.c
new file mode 100644
index 0000000..cf5be0d
--- /dev/null
+++ b/src/lib/libast/comp/gross.c
@@ -0,0 +1,99 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * porting hacks here
+ */
+
+#include <ast.h>
+#include <ls.h>
+
+#include "FEATURE/hack"
+
+void _STUB_gross(){}
+
+#if _lcl_xstat
+
+extern int fstat(int fd, struct stat* st)
+{
+#if _lib___fxstat
+ return __fxstat(_STAT_VER, fd, st);
+#else
+ return _fxstat(_STAT_VER, fd, st);
+#endif
+}
+
+extern int lstat(const char* path, struct stat* st)
+{
+#if _lib___lxstat
+ return __lxstat(_STAT_VER, path, st);
+#else
+ return _lxstat(_STAT_VER, path, st);
+#endif
+}
+
+extern int stat(const char* path, struct stat* st)
+{
+#if _lib___xstat
+ return __xstat(_STAT_VER, path, st);
+#else
+ return _xstat(_STAT_VER, path, st);
+#endif
+}
+
+#endif
+
+#if _lcl_xstat64
+
+extern int fstat64(int fd, struct stat64* st)
+{
+#if _lib___fxstat64
+ return __fxstat64(_STAT_VER, fd, st);
+#else
+ return _fxstat64(_STAT_VER, fd, st);
+#endif
+}
+
+extern int lstat64(const char* path, struct stat64* st)
+{
+#if _lib___lxstat64
+ return __lxstat64(_STAT_VER, path, st);
+#else
+ return _lxstat64(_STAT_VER, path, st);
+#endif
+}
+
+extern int stat64(const char* path, struct stat64* st)
+{
+#if _lib___xstat64
+ return __xstat64(_STAT_VER, path, st);
+#else
+ return _xstat64(_STAT_VER, path, st);
+#endif
+}
+
+#endif
+
+#if __sgi && _hdr_locale_attr
+
+#include "gross_sgi.h"
+
+#endif
diff --git a/src/lib/libast/comp/gross_sgi.h b/src/lib/libast/comp/gross_sgi.h
new file mode 100644
index 0000000..7469789
--- /dev/null
+++ b/src/lib/libast/comp/gross_sgi.h
@@ -0,0 +1,188 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if __sgi && _hdr_locale_attr
+
+/*
+ * irix 6.5 introduced __libc_attr referenced by
+ * ctype and locale macros; this hack lets
+ * 6.5 a.outs run on irix < 6.5
+ *
+ * NOTE: this hack also freezes the US locale
+ */
+
+#include <locale_attr.h>
+
+static __ctype_t _ast_ctype_tbl =
+{
+ {
+ 0x00000000, 0x00000020, 0x00000020, 0x00000020,
+ 0x00000020, 0x00000020, 0x00000020, 0x00000020,
+ 0x00000020, 0x00000020, 0x80000028, 0x00000028,
+ 0x00000028, 0x00000028, 0x00000028, 0x00000020,
+ 0x00000020, 0x00000020, 0x00000020, 0x00000020,
+ 0x00000020, 0x00000020, 0x00000020, 0x00000020,
+ 0x00000020, 0x00000020, 0x00000020, 0x00000020,
+ 0x00000020, 0x00000020, 0x00000020, 0x00000020,
+ 0x00000020, 0x80008008, 0x00000010, 0x00000010,
+ 0x00000010, 0x00000010, 0x00000010, 0x00000010,
+ 0x00000010, 0x00000010, 0x00000010, 0x00000010,
+ 0x00000010, 0x00000010, 0x00000010, 0x00000010,
+ 0x00000010, 0x00000084, 0x00000084, 0x00000084,
+ 0x00000084, 0x00000084, 0x00000084, 0x00000084,
+ 0x00000084, 0x00000084, 0x00000084, 0x00000010,
+ 0x00000010, 0x00000010, 0x00000010, 0x00000010,
+ 0x00000010, 0x00000010, 0x00000081, 0x00000081,
+ 0x00000081, 0x00000081, 0x00000081, 0x00000081,
+ 0x00000001, 0x00000001, 0x00000001, 0x00000001,
+ 0x00000001, 0x00000001, 0x00000001, 0x00000001,
+ 0x00000001, 0x00000001, 0x00000001, 0x00000001,
+ 0x00000001, 0x00000001, 0x00000001, 0x00000001,
+ 0x00000001, 0x00000001, 0x00000001, 0x00000001,
+ 0x00000010, 0x00000010, 0x00000010, 0x00000010,
+ 0x00000010, 0x00000010, 0x00000082, 0x00000082,
+ 0x00000082, 0x00000082, 0x00000082, 0x00000082,
+ 0x00000002, 0x00000002, 0x00000002, 0x00000002,
+ 0x00000002, 0x00000002, 0x00000002, 0x00000002,
+ 0x00000002, 0x00000002, 0x00000002, 0x00000002,
+ 0x00000002, 0x00000002, 0x00000002, 0x00000002,
+ 0x00000002, 0x00000002, 0x00000002, 0x00000002,
+ 0x00000010, 0x00000010, 0x00000010, 0x00000010,
+ 0x00000020, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000,
+ },
+ {
+ -1, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110,
+ 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150,
+ 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190,
+ 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, 206,
+ 207, 208, 209, 210, 211, 212, 213, 214,
+ 215, 216, 217, 218, 219, 220, 221, 222,
+ 223, 224, 225, 226, 227, 228, 229, 230,
+ 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251, 252, 253, 254,
+ 255,
+ },
+ {
+ -1, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78,
+ 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150,
+ 151, 152, 153, 154, 155, 156, 157, 158,
+ 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174,
+ 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190,
+ 191, 192, 193, 194, 195, 196, 197, 198,
+ 199, 200, 201, 202, 203, 204, 205, 206,
+ 207, 208, 209, 210, 211, 212, 213, 214,
+ 215, 216, 217, 218, 219, 220, 221, 222,
+ 223, 224, 225, 226, 227, 228, 229, 230,
+ 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246,
+ 247, 248, 249, 250, 251, 252, 253, 254,
+ 255,
+ },
+ {
+ 000, 000, 000, 000, 000, 000, 000,
+ },
+};
+
+extern __attr_t ___libc_attr =
+{
+ &_ast_ctype_tbl,
+ { 0 },
+ { 0 },
+ { 1 },
+};
+
+#pragma weak __libc_attr = ___libc_attr
+
+#endif
diff --git a/src/lib/libast/comp/hsearch.c b/src/lib/libast/comp/hsearch.c
new file mode 100644
index 0000000..43953e4
--- /dev/null
+++ b/src/lib/libast/comp/hsearch.c
@@ -0,0 +1,138 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * hsearch() for systems that have <search.h> but no hsearch()
+ * why would such a system provide the interface but not the
+ * implementation? that's what happens when one slimes their
+ * way through standards compliance
+ *
+ * NOTE: please excuse the crude feature test
+ */
+
+#if !_UWIN
+
+void _STUB_hsearch(){}
+
+#else
+
+#if _PACKAGE_ast
+#include <ast.h>
+#endif
+
+#define hcreate ______hcreate
+#define hdestroy ______hdestroy
+#define hsearch ______hsearch
+
+#include <search.h>
+
+#undef hcreate
+#undef hdestroy
+#undef hsearch
+
+#include "dthdr.h"
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+/* POSIX hsearch library based on libdt
+** Written by Kiem-Phong Vo (AT&T Research, 07/19/95)
+*/
+
+/* type of objects in hash table */
+typedef struct _hash_s
+{ Dtlink_t link;
+ ENTRY item;
+} Hash_t;
+
+/* object delete function */
+#if __STD_C
+static void hashfree(Dt_t* dt, Void_t* obj, Dtdisc_t* disc)
+#else
+static void hashfree(dt, obj, disc)
+Dt_t* dt;
+Void_t* obj;
+Dtdisc_t* disc;
+#endif
+{
+ free(((Hash_t*)obj)->item.key);
+ free(obj);
+}
+
+static Dt_t* Hashtab; /* object dictionary */
+static Dtdisc_t Hashdisc = /* discipline */
+{ sizeof(Dtlink_t), -1,
+ 0,
+ NIL(Dtmake_f), hashfree,
+ NIL(Dtcompar_f), /* always use strcmp */
+ NIL(Dthash_f),
+ NIL(Dtmemory_f),
+ NIL(Dtevent_f)
+};
+
+extern
+#if __STD_C
+int hcreate(size_t nel)
+#else
+int hcreate(nel)
+size_t nel;
+#endif
+{
+ if(Hashtab) /* already opened */
+ return 0;
+
+ if(!(Hashtab = dtopen(&Hashdisc,Dtset)) )
+ return 0;
+
+ return 1;
+}
+
+extern void hdestroy()
+{ if(Hashtab)
+ dtclose(Hashtab);
+ Hashtab = NIL(Dt_t*);
+}
+
+extern
+#if __STD_C
+ENTRY* hsearch(ENTRY item, ACTION action)
+#else
+ENTRY* hsearch(item, action)
+ENTRY item;
+ACTION action;
+#endif
+{
+ reg Hash_t* o;
+
+ if(!Hashtab)
+ return NIL(ENTRY*);
+
+ if(!(o = (Hash_t*)dtmatch(Hashtab,item.key)) && action == ENTER &&
+ (o = (Hash_t*)malloc(sizeof(Hash_t)) ) )
+ { o->item = item;
+ o = (Hash_t*)dtinsert(Hashtab,o);
+ }
+
+ return o ? &(o->item) : NIL(ENTRY*);
+}
+
+#endif
diff --git a/src/lib/libast/comp/iconv.c b/src/lib/libast/comp/iconv.c
new file mode 100644
index 0000000..ba24988
--- /dev/null
+++ b/src/lib/libast/comp/iconv.c
@@ -0,0 +1,1599 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * iconv intercept
+ * minimally provides { utf*<=>bin ascii<=>ebcdic* }
+ */
+
+#include <ast.h>
+#include <dirent.h>
+
+#define DEBUG_TRACE 0
+#define _ICONV_LIST_PRIVATE_
+
+#include <ccode.h>
+#include <ctype.h>
+#include <iconv.h>
+
+#include "lclib.h"
+
+#if !_lib_iconv_open
+
+#define _ast_iconv_t iconv_t
+#define _ast_iconv_f iconv_f
+#define _ast_iconv_list_t iconv_list_t
+#define _ast_iconv_open iconv_open
+#define _ast_iconv iconv
+#define _ast_iconv_close iconv_close
+#define _ast_iconv_list iconv_list
+#define _ast_iconv_move iconv_move
+#define _ast_iconv_name iconv_name
+#define _ast_iconv_write iconv_write
+
+#endif
+
+#ifndef E2BIG
+#define E2BIG ENOMEM
+#endif
+#ifndef EILSEQ
+#define EILSEQ EIO
+#endif
+
+#define RETURN(e,n,fn) \
+ if (*fn && !e) e = E2BIG; \
+ if (e) { errno = e; return (size_t)(-1); } \
+ return n;
+
+typedef struct Map_s
+{
+ char* name;
+ const unsigned char* map;
+ _ast_iconv_f fun;
+ int index;
+} Map_t;
+
+typedef struct Conv_s
+{
+ iconv_t cvt;
+ char* buf;
+ size_t size;
+ Map_t from;
+ Map_t to;
+} Conv_t;
+
+static Conv_t* freelist[4];
+static int freeindex;
+
+static const char name_local[] = "local";
+static const char name_native[] = "native";
+
+static const _ast_iconv_list_t codes[] =
+{
+ {
+ "utf",
+ "un|unicode|utf",
+ "multibyte 8-bit unicode",
+ "UTF-%s",
+ "8",
+ CC_UTF,
+ },
+
+ {
+ "ume",
+ "um|ume|utf?(-)7",
+ "multibyte 7-bit unicode",
+ "UTF-7",
+ 0,
+ CC_UME,
+ },
+
+ {
+ "euc",
+ "(big|euc)*",
+ "euc family",
+ 0,
+ 0,
+ CC_ICONV,
+ },
+
+ {
+ "dos",
+ "dos?(-)?(855)",
+ "dos code page",
+ "DOS855",
+ 0,
+ CC_ICONV,
+ },
+
+ {
+ "ucs",
+ "ucs?(-)?(2)?(be)|utf-16?(be)",
+ "unicode runes",
+ "UCS-%s",
+ "2",
+ CC_UCS,
+ },
+
+ {
+ "ucs-le",
+ "ucs?(-)?(2)le|utf-16le",
+ "little endian unicode runes",
+ "UCS-%sLE",
+ "2",
+ CC_SCU,
+ },
+
+ { 0 },
+};
+
+#if _UWIN
+
+#include <ast_windows.h>
+
+#ifndef CP_UCS2
+#define CP_UCS2 0x0000
+#endif
+
+static char _win_maps[] = "/reg/local_machine/SOFTWARE/Classes/MIME/Database/Charset";
+
+/*
+ * return the codeset index given its name or alias
+ * the map is in the what? oh, the registry
+ */
+
+static int
+_win_codeset(const char* name)
+{
+ register char* s;
+ char* e;
+ int n;
+ Sfio_t* sp;
+ char aka[128];
+ char tmp[128];
+
+#if DEBUG_TRACE
+error(DEBUG_TRACE, "AHA#%d _win_codeset name=%s", __LINE__, name);
+#endif
+ if (name == name_native)
+ return CP_ACP;
+ if (!strcasecmp(name, "utf") || !strcasecmp(name, "utf8") || !strcasecmp(name, "utf-8"))
+ return CP_UTF8;
+ if (!strcasecmp(name, "ucs") || !strcasecmp(name, "ucs2") || !strcasecmp(name, "ucs-2"))
+ return CP_UCS2;
+ if (name[0] == '0' && name[1] == 'x' && (n = strtol(name, &e, 0)) > 0 && !*e)
+ return n;
+ for (;;)
+ {
+ sfsprintf(tmp, sizeof(tmp), "%s/%s", _win_maps, name);
+ if (!(sp = sfopen(0, tmp, "r")))
+ {
+ s = (char*)name;
+ if ((s[0] == 'c' || s[0] == 'C') && (s[1] == 'p' || s[1] == 'P'))
+ s += 2;
+ if (!isdigit(s[0]))
+ break;
+ sfsprintf(tmp, sizeof(tmp), "%s/windows-%s", _win_maps, s);
+ if (!(sp = sfopen(0, tmp, "r")))
+ break;
+ }
+ for (;;)
+ {
+ if (!(s = sfgetr(sp, '\n', 0)))
+ {
+ sfclose(sp);
+ return -1;
+ }
+ if (!strncasecmp(s, "AliasForCharSet=", 16))
+ {
+ n = sfvalue(sp) - 17;
+ s += 16;
+ if (n >= sizeof(aka))
+ n = sizeof(aka) - 1;
+ memcpy(aka, s, n);
+ aka[n] = 0;
+ sfclose(sp);
+ name = (const char*)aka;
+ break;
+ }
+ if (!strncasecmp(s, "CodePage=", 9))
+ {
+ s += 9;
+ n = strtol(s, 0, 0);
+ sfclose(sp);
+ return n;
+ }
+ }
+ }
+ return -1;
+}
+
+/*
+ * get and check the codeset indices
+ */
+
+static _ast_iconv_t
+_win_iconv_open(register Conv_t* cc, const char* t, const char* f)
+{
+#if DEBUG_TRACE
+error(DEBUG_TRACE, "AHA#%d _win_iconv_open f=%s t=%s\n", __LINE__, f, t);
+#endif
+ if ((cc->from.index = _win_codeset(f)) < 0)
+ return (_ast_iconv_t)(-1);
+ if ((cc->to.index = _win_codeset(t)) < 0)
+ return (_ast_iconv_t)(-1);
+#if DEBUG_TRACE
+error(DEBUG_TRACE, "AHA#%d _win_iconv_open f=0x%04x t=0x%04x\n", __LINE__, cc->from.index, cc->to.index);
+#endif
+ return (_ast_iconv_t)cc;
+}
+
+/*
+ * even though the indices already check out
+ * they could still be rejected
+ */
+
+static size_t
+_win_iconv(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
+{
+ Conv_t* cc = (Conv_t*)cd;
+ size_t un;
+ size_t tz;
+ size_t fz;
+ size_t bz;
+ size_t pz;
+ size_t oz;
+ LPWSTR ub;
+
+#if DEBUG_TRACE
+error(DEBUG_TRACE, "AHA#%d _win_iconv from=0x%04x to=0x%04x\n", __LINE__, cc->from.index, cc->to.index);
+#endif
+ if (cc->from.index == cc->to.index || cc->from.index != CP_UCS2 && cc->to.index == 0)
+ {
+ /*
+ * easy
+ */
+
+ fz = tz = (*fn < *tn) ? *fn : *tn;
+ memcpy(*tb, *fb, fz);
+ }
+ else
+ {
+ ub = 0;
+ un = *fn;
+
+ /*
+ * from => ucs-2
+ */
+
+ if (cc->to.index == CP_UCS2)
+ {
+ if ((tz = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)*fn, (LPWSTR)*tb, *tn)) && tz <= *tn)
+ {
+ fz = *fn;
+ tz *= sizeof(WCHAR);
+ }
+ else
+ {
+ /*
+ * target too small
+ * binary search on input size to make it fit
+ */
+
+ oz = 0;
+ pz = *fn / 2;
+ fz = *fn - pz;
+ for (;;)
+ {
+ while (!(tz = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)fz, (LPWSTR)*tb, 0)))
+ if (++fz >= *fn)
+ goto nope;
+ tz *= sizeof(WCHAR);
+ if (tz == *tn)
+ break;
+ if (!(pz /= 2))
+ {
+ if (!(fz = oz))
+ goto nope;
+ break;
+ }
+ if (tz > *tn)
+ fz -= pz;
+ else
+ {
+ oz = fz;
+ fz += pz;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (cc->from.index == CP_UCS2)
+ {
+ un = *fn / sizeof(WCHAR);
+ ub = (LPWSTR)*fb;
+ }
+ else if (!(un = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)*fn, (LPWSTR)*tb, 0)))
+ goto nope;
+ else if (!(ub = (LPWSTR)malloc(un * sizeof(WCHAR))))
+ goto nope;
+ else if (!(un = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)*fn, (LPWSTR)ub, un)))
+ goto nope;
+
+ /*
+ * ucs-2 => to
+ */
+
+ if (tz = WideCharToMultiByte(cc->to.index, 0, (LPCWSTR)ub, un, *tb, *tn, 0, 0))
+ fz = *fn;
+ else
+ {
+ /*
+ * target too small
+ * binary search on input size to make it fit
+ */
+
+ oz = 0;
+ pz = *fn / 2;
+ bz = *fn - pz;
+ for (;;)
+ {
+ while (!(fz = MultiByteToWideChar(cc->from.index, 0, (LPCSTR)*fb, (int)bz, (LPWSTR)ub, un)))
+ if (++bz > *fn)
+ goto nope;
+ if (!(tz = WideCharToMultiByte(cc->to.index, 0, (LPCWSTR)ub, fz, *tb, 0, 0, 0)))
+ goto nope;
+ if (tz == *tn)
+ break;
+ if (!(pz /= 2))
+ {
+ if (!(fz = oz))
+ goto nope;
+ break;
+ }
+ if (tz > *tn)
+ bz -= pz;
+ else
+ {
+ oz = bz;
+ bz += pz;
+ }
+ }
+ if (!(tz = WideCharToMultiByte(cc->to.index, 0, (LPCWSTR)ub, fz, *tb, tz, 0, 0)))
+ goto nope;
+#if DEBUG_TRACE
+error(DEBUG_TRACE, "AHA#%d _win_iconv *fn=%u fz=%u[%u] *tn=%u tz=%u\n", __LINE__, *fn, fz, fz * sizeof(WCHAR), *tn, tz);
+#endif
+#if 0
+ fz *= sizeof(WCHAR);
+#endif
+ }
+ if (ub != (LPWSTR)*fb)
+ free(ub);
+ }
+ }
+ *fb += fz;
+ *fn -= fz;
+ *tb += tz;
+ *tn -= tz;
+ return fz;
+ nope:
+ if (ub && ub != (LPWSTR)*fb)
+ free(ub);
+ errno = EINVAL;
+ return (size_t)(-1);
+}
+
+#endif
+
+/*
+ * return canonical character code set name for m
+ * if b!=0 then canonical name placed in b of size n
+ * <ccode.h> index returned
+ */
+
+int
+_ast_iconv_name(register const char* m, register char* b, size_t n)
+{
+ register const _ast_iconv_list_t* cp;
+ const _ast_iconv_list_t* bp;
+ register int c;
+ register char* e;
+ int sub[2];
+ char buf[16];
+#if DEBUG_TRACE
+ char* o;
+#endif
+
+ if (!b)
+ {
+ b = buf;
+ n = sizeof(buf);
+ }
+#if DEBUG_TRACE
+ o = b;
+#endif
+ e = b + n - 1;
+ bp = 0;
+ n = 0;
+ cp = ccmaplist(NiL);
+#if DEBUG_TRACE
+if (error_info.trace < DEBUG_TRACE) sfprintf(sfstderr, "%s: debug-%d: AHA%d _ast_iconv_name m=\"%s\"\n", error_info.id, error_info.trace, __LINE__, m);
+#endif
+ for (;;)
+ {
+#if DEBUG_TRACE
+if (error_info.trace < DEBUG_TRACE) sfprintf(sfstderr, "%s: debug-%d: AHA%d _ast_iconv_name n=%d bp=%p cp=%p ccode=%d name=\"%s\"\n", error_info.id, error_info.trace, __LINE__, n, bp, cp, cp->ccode, cp->name);
+#endif
+ if (strgrpmatch(m, cp->match, sub, elementsof(sub) / 2, STR_MAXIMAL|STR_LEFT|STR_ICASE))
+ {
+ if (!(c = m[sub[1]]))
+ {
+ bp = cp;
+ break;
+ }
+ if (sub[1] > n && !isalpha(c))
+ {
+ bp = cp;
+ n = sub[1];
+ }
+ }
+ if (cp->ccode < 0)
+ {
+ if (!(++cp)->name)
+ break;
+ }
+ else if (!(cp = (const _ast_iconv_list_t*)ccmaplist((_ast_iconv_list_t*)cp)))
+ cp = codes;
+ }
+ if (cp = bp)
+ {
+ if (cp->canon)
+ {
+ if (cp->index)
+ {
+ for (m += sub[1]; *m && !isalnum(*m); m++);
+ if (!isdigit(*m))
+ m = cp->index;
+ }
+ else
+ m = "1";
+ b += sfsprintf(b, e - b, cp->canon, m);
+ }
+ else if (cp->ccode == CC_NATIVE)
+ {
+ if ((locales[AST_LC_CTYPE]->flags & LC_default) || !locales[AST_LC_CTYPE]->charset || !(m = locales[AST_LC_CTYPE]->charset->code) || streq(m, "iso8859-1"))
+ switch (CC_NATIVE)
+ {
+ case CC_EBCDIC:
+ m = (const char*)"EBCDIC";
+ break;
+ case CC_EBCDIC_I:
+ m = (const char*)"EBCDIC-I";
+ break;
+ case CC_EBCDIC_O:
+ m = (const char*)"EBCDIC-O";
+ break;
+ default:
+ m = (const char*)"ISO-8859-1";
+ break;
+ }
+ b += sfsprintf(b, e - b, "%s", m);
+ }
+ *b = 0;
+#if DEBUG_TRACE
+if (error_info.trace < DEBUG_TRACE) sfprintf(sfstderr, "%s: debug-%d: AHA%d _ast_iconv_name ccode=%d canon=\"%s\"\n", error_info.id, error_info.trace, __LINE__, cp->ccode, o);
+#endif
+ return cp->ccode;
+ }
+ while (b < e && (c = *m++))
+ {
+ if (islower(c))
+ c = toupper(c);
+ *b++ = c;
+ }
+ *b = 0;
+#if DEBUG_TRACE
+if (error_info.trace < DEBUG_TRACE) sfprintf(sfstderr, "%s: debug-%d: AHA%d _ast_iconv_name ccode=%d canon=\"%s\"\n", error_info.id, error_info.trace, __LINE__, CC_ICONV, o);
+#endif
+ return CC_ICONV;
+}
+
+/*
+ * convert utf-8 to bin
+ */
+
+static size_t
+utf2bin(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
+{
+ register unsigned char* f;
+ register unsigned char* fe;
+ register unsigned char* t;
+ register unsigned char* te;
+ register unsigned char* p;
+ register int c;
+ register int w;
+ size_t n;
+ int e;
+
+ e = 0;
+ f = (unsigned char*)(*fb);
+ fe = f + (*fn);
+ t = (unsigned char*)(*tb);
+ te = t + (*tn);
+ while (t < te && f < fe)
+ {
+ p = f;
+ c = *f++;
+ if (c & 0x80)
+ {
+ if (!(c & 0x40))
+ {
+ f = p;
+ e = EILSEQ;
+ break;
+ }
+ if (c & 0x20)
+ {
+ w = (c & 0x0F) << 12;
+ if (f >= fe)
+ {
+ f = p;
+ e = EINVAL;
+ break;
+ }
+ c = *f++;
+ if (c & 0x40)
+ {
+ f = p;
+ e = EILSEQ;
+ break;
+ }
+ w |= (c & 0x3F) << 6;
+ }
+ else
+ w = (c & 0x1F) << 6;
+ if (f >= fe)
+ {
+ f = p;
+ e = EINVAL;
+ break;
+ }
+ c = *f++;
+ w |= (c & 0x3F);
+ }
+ else
+ w = c;
+ *t++ = w;
+ }
+ *fn -= (char*)f - (*fb);
+ *fb = (char*)f;
+ *tn -= (n = (char*)t - (*tb));
+ *tb = (char*)t;
+ RETURN(e, n, fn);
+}
+
+/*
+ * convert bin to utf-8
+ */
+
+static size_t
+bin2utf(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
+{
+ register unsigned char* f;
+ register unsigned char* fe;
+ register unsigned char* t;
+ register unsigned char* te;
+ register int c;
+ wchar_t w;
+ size_t n;
+ int e;
+
+ e = 0;
+ f = (unsigned char*)(*fb);
+ fe = f + (*fn);
+ t = (unsigned char*)(*tb);
+ te = t + (*tn);
+ while (f < fe && t < te)
+ {
+ if (!mbwide())
+ {
+ c = 1;
+ w = *f;
+ }
+ else if ((c = (*_ast_info.mb_towc)(&w, (char*)f, fe - f)) < 0)
+ {
+ e = EINVAL;
+ break;
+ }
+ else if (!c)
+ c = 1;
+ if (!(w & ~0x7F))
+ *t++ = w;
+ else
+ {
+ if (!(w & ~0x7FF))
+ {
+ if (t >= (te - 2))
+ {
+ e = E2BIG;
+ break;
+ }
+ *t++ = 0xC0 + (w >> 6);
+ }
+ else if (!(w & ~0xffff))
+ {
+ if (t >= (te - 3))
+ {
+ e = E2BIG;
+ break;
+ }
+ *t++ = 0xE0 + (w >> 12);
+ *t++ = 0x80 + ((w >> 6 ) & 0x3F);
+ }
+ else
+ {
+ e = EILSEQ;
+ break;
+ }
+ *t++ = 0x80 + (w & 0x3F);
+ }
+ f += c;
+ }
+ *fn -= (n = (char*)f - (*fb));
+ *fb = (char*)f;
+ *tn -= (char*)t - (*tb);
+ *tb = (char*)t;
+ RETURN(e, n, fn);
+}
+
+static const unsigned char ume_D[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'(),-./:?!\"#$%&*;<=>@[]^_`{|} \t\n";
+
+static const unsigned char ume_M[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static unsigned char ume_d[UCHAR_MAX+1];
+
+static unsigned char ume_m[UCHAR_MAX+1];
+
+#define NOE 0xFF
+#define UMEINIT() (ume_d[ume_D[0]]?0:umeinit())
+
+/*
+ * initialize the ume tables
+ */
+
+static int
+umeinit(void)
+{
+ register const unsigned char* s;
+ register int i;
+ register int c;
+
+ if (!ume_d[ume_D[0]])
+ {
+ s = ume_D;
+ while (c = *s++)
+ ume_d[c] = 1;
+ memset(ume_m, NOE, sizeof(ume_m));
+ for (i = 0; c = ume_M[i]; i++)
+ ume_m[c] = i;
+ }
+ return 0;
+}
+
+/*
+ * convert utf-7 to bin
+ */
+
+static size_t
+ume2bin(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
+{
+ register unsigned char* f;
+ register unsigned char* fe;
+ register unsigned char* t;
+ register unsigned char* te;
+ register unsigned char* p;
+ register int s;
+ register int c;
+ register int w;
+ size_t n;
+ int e;
+
+ e = 0;
+ UMEINIT();
+ f = (unsigned char*)(*fb);
+ fe = f + (*fn);
+ t = (unsigned char*)(*tb);
+ te = t + (*tn);
+ s = 0;
+ while (f < fe && t < te)
+ {
+ p = f;
+ c = *f++;
+ if (s)
+ {
+ if (c == '-' && s > 1)
+ s = 0;
+ else if ((w = ume_m[c]) == NOE)
+ {
+ s = 0;
+ *t++ = c;
+ }
+ else if (f >= (fe - 2))
+ {
+ f = p;
+ e = EINVAL;
+ break;
+ }
+ else
+ {
+ s = 2;
+ w = (w << 6) | ume_m[*f++];
+ w = (w << 6) | ume_m[*f++];
+ if (!(w & ~0xFF))
+ *t++ = w;
+ else if (t >= (te - 1))
+ {
+ f = p;
+ e = E2BIG;
+ break;
+ }
+ else
+ {
+ *t++ = (w >> 8) & 0xFF;
+ *t++ = w & 0xFF;
+ }
+ }
+ }
+ else if (c == '+')
+ s = 1;
+ else
+ *t++ = c;
+ }
+ *fn -= (char*)f - (*fb);
+ *fb = (char*)f;
+ *tn -= (n = (char*)t - (*tb));
+ *tb = (char*)t;
+ RETURN(e, n, fn);
+}
+
+/*
+ * convert bin to utf-7
+ */
+
+static size_t
+bin2ume(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
+{
+ register unsigned char* f;
+ register unsigned char* fe;
+ register unsigned char* t;
+ register unsigned char* te;
+ register int c;
+ register int s;
+ wchar_t w;
+ size_t n;
+ int e;
+
+ e = 0;
+ UMEINIT();
+ f = (unsigned char*)(*fb);
+ fe = f + (*fn);
+ t = (unsigned char*)(*tb);
+ te = t + (*tn);
+ s = 0;
+ while (f < fe && t < (te - s))
+ {
+ if (!mbwide())
+ {
+ c = 1;
+ w = *f;
+ }
+ else if ((c = (*_ast_info.mb_towc)(&w, (char*)f, fe - f)) < 0)
+ {
+ e = EINVAL;
+ break;
+ }
+ else if (!c)
+ c = 1;
+ if (!(w & ~0x7F) && ume_d[w])
+ {
+ if (s)
+ {
+ s = 0;
+ *t++ = '-';
+ }
+ *t++ = w;
+ }
+ else if (t >= (te - (4 + s)))
+ {
+ e = E2BIG;
+ break;
+ }
+ else
+ {
+ if (!s)
+ {
+ s = 1;
+ *t++ = '+';
+ }
+ *t++ = ume_M[(w >> 12) & 0x3F];
+ *t++ = ume_M[(w >> 6) & 0x3F];
+ *t++ = ume_M[w & 0x3F];
+ }
+ f += c;
+ }
+ if (s)
+ *t++ = '-';
+ *fn -= (n = (char*)f - (*fb));
+ *fb = (char*)f;
+ *tn -= (char*)t - (*tb);
+ *tb = (char*)t;
+ RETURN(e, n, fn);
+}
+
+/*
+ * convert ucs-2 to bin with no byte swap
+ */
+
+static size_t
+ucs2bin(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
+{
+ register unsigned char* f;
+ register unsigned char* fe;
+ register unsigned char* t;
+ register unsigned char* te;
+ register int w;
+ size_t n;
+ int e;
+
+ e = 0;
+ f = (unsigned char*)(*fb);
+ fe = f + (*fn);
+ t = (unsigned char*)(*tb);
+ te = t + (*tn);
+ while (f < (fe - 1) && t < te)
+ {
+ w = *f++;
+ w = (w << 8) | *f++;
+ if (!(w & ~0xFF))
+ *t++ = w;
+ else if (t >= (te - 1))
+ {
+ f -= 2;
+ e = E2BIG;
+ break;
+ }
+ else
+ {
+ *t++ = (w >> 8) & 0xFF;
+ *t++ = w & 0xFF;
+ }
+ }
+ *fn -= (char*)f - (*fb);
+ *fb = (char*)f;
+ *tn -= (n = (char*)t - (*tb));
+ *tb = (char*)t;
+ RETURN(e, n, fn);
+}
+
+/*
+ * convert bin to ucs-2 with no byte swap
+ */
+
+static size_t
+bin2ucs(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
+{
+ register unsigned char* f;
+ register unsigned char* fe;
+ register unsigned char* t;
+ register unsigned char* te;
+ register int c;
+ wchar_t w;
+ size_t n;
+ int e;
+
+ e = 0;
+ f = (unsigned char*)(*fb);
+ fe = f + (*fn);
+ t = (unsigned char*)(*tb);
+ te = t + (*tn);
+ while (f < fe && t < (te - 1))
+ {
+ if (!mbwide())
+ {
+ c = 1;
+ w = *f;
+ }
+ if ((c = (*_ast_info.mb_towc)(&w, (char*)f, fe - f)) < 0)
+ {
+ e = EINVAL;
+ break;
+ }
+ else if (!c)
+ c = 1;
+ *t++ = (w >> 8) & 0xFF;
+ *t++ = w & 0xFF;
+ f += c;
+ }
+ *fn -= (n = (char*)f - (*fb));
+ *fb = (char*)f;
+ *tn -= (char*)t - (*tb);
+ *tb = (char*)t;
+ RETURN(e, n, fn);
+}
+
+/*
+ * convert ucs-2 to bin with byte swap
+ */
+
+static size_t
+scu2bin(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
+{
+ register unsigned char* f;
+ register unsigned char* fe;
+ register unsigned char* t;
+ register unsigned char* te;
+ register int w;
+ size_t n;
+ int e;
+
+ e = 0;
+ f = (unsigned char*)(*fb);
+ fe = f + (*fn);
+ t = (unsigned char*)(*tb);
+ te = t + (*tn);
+ while (f < (fe - 1) && t < te)
+ {
+ w = *f++;
+ w = w | (*f++ << 8);
+ if (!(w & ~0xFF))
+ *t++ = w;
+ else if (t >= (te - 1))
+ {
+ f -= 2;
+ e = E2BIG;
+ break;
+ }
+ else
+ {
+ *t++ = (w >> 8) & 0xFF;
+ *t++ = w & 0xFF;
+ }
+ }
+ *fn -= (char*)f - (*fb);
+ *fb = (char*)f;
+ *tn -= (n = (char*)t - (*tb));
+ *tb = (char*)t;
+ RETURN(e, n, fn);
+}
+
+/*
+ * convert bin to ucs-2 with byte swap
+ */
+
+static size_t
+bin2scu(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
+{
+ register unsigned char* f;
+ register unsigned char* fe;
+ register unsigned char* t;
+ register unsigned char* te;
+ register int c;
+ wchar_t w;
+ size_t n;
+ int e;
+
+ e = 0;
+ f = (unsigned char*)(*fb);
+ fe = f + (*fn);
+ t = (unsigned char*)(*tb);
+ te = t + (*tn);
+ while (f < fe && t < (te - 1))
+ {
+ if (!mbwide())
+ {
+ c = 1;
+ w = *f;
+ }
+ else if ((c = (*_ast_info.mb_towc)(&w, (char*)f, fe - f)) < 0)
+ {
+ e = EINVAL;
+ break;
+ }
+ else if (!c)
+ c = 1;
+ *t++ = w & 0xFF;
+ *t++ = (w >> 8) & 0xFF;
+ f += c;
+ }
+ *fn -= (n = (char*)f - (*fb));
+ *fb = (char*)f;
+ *tn -= (char*)t - (*tb);
+ *tb = (char*)t;
+ RETURN(e, n, fn);
+}
+
+/*
+ * open a character code conversion map from f to t
+ */
+
+_ast_iconv_t
+_ast_iconv_open(const char* t, const char* f)
+{
+ register Conv_t* cc;
+ int fc;
+ int tc;
+ int i;
+
+ char fr[64];
+ char to[64];
+
+#if DEBUG_TRACE
+error(DEBUG_TRACE, "AHA#%d _ast_iconv_open f=%s t=%s\n", __LINE__, f, t);
+#endif
+ if (!t || !*t || *t == '-' && !*(t + 1) || !strcasecmp(t, name_local) || !strcasecmp(t, name_native))
+ t = name_native;
+ if (!f || !*f || *f == '-' && !*(f + 1) || !strcasecmp(t, name_local) || !strcasecmp(f, name_native))
+ f = name_native;
+
+ /*
+ * the ast identify is always (iconv_t)(0)
+ */
+
+ if (t == f)
+ return (iconv_t)(0);
+ fc = _ast_iconv_name(f, fr, sizeof(fr));
+ tc = _ast_iconv_name(t, to, sizeof(to));
+#if DEBUG_TRACE
+error(DEBUG_TRACE, "AHA#%d _ast_iconv_open f=%s:%s:%d t=%s:%s:%d\n", __LINE__, f, fr, fc, t, to, tc);
+#endif
+ if (fc != CC_ICONV && fc == tc || streq(fr, to))
+ return (iconv_t)(0);
+
+ /*
+ * first check the free list
+ */
+
+ for (i = 0; i < elementsof(freelist); i++)
+ if ((cc = freelist[i]) && streq(to, cc->to.name) && streq(fr, cc->from.name))
+ {
+ freelist[i] = 0;
+#if _lib_iconv_open
+ /*
+ * reset the shift state if any
+ */
+
+ if (cc->cvt != (iconv_t)(-1))
+ iconv(cc->cvt, NiL, NiL, NiL, NiL);
+#endif
+ return cc;
+ }
+
+ /*
+ * allocate a new one
+ */
+
+ if (!(cc = newof(0, Conv_t, 1, strlen(to) + strlen(fr) + 2)))
+ return (iconv_t)(-1);
+ cc->to.name = (char*)(cc + 1);
+ cc->from.name = strcopy(cc->to.name, to) + 1;
+ strcpy(cc->from.name, fr);
+ cc->cvt = (iconv_t)(-1);
+
+ /*
+ * 8 bit maps are the easiest
+ */
+
+ if (fc >= 0 && tc >= 0)
+ cc->from.map = ccmap(fc, tc);
+#if _lib_iconv_open
+ else if ((cc->cvt = iconv_open(t, f)) != (iconv_t)(-1) || (cc->cvt = iconv_open(to, fr)) != (iconv_t)(-1))
+ cc->from.fun = (_ast_iconv_f)iconv;
+#endif
+#if _UWIN
+ else if ((cc->cvt = _win_iconv_open(cc, t, f)) != (_ast_iconv_t)(-1) || (cc->cvt = _win_iconv_open(cc, to, fr)) != (_ast_iconv_t)(-1))
+ cc->from.fun = (_ast_iconv_f)_win_iconv;
+#endif
+ else
+ {
+ switch (fc)
+ {
+ case CC_UTF:
+ cc->from.fun = utf2bin;
+ break;
+ case CC_UME:
+ cc->from.fun = ume2bin;
+ break;
+ case CC_UCS:
+ cc->from.fun = ucs2bin;
+ break;
+ case CC_SCU:
+ cc->from.fun = scu2bin;
+ break;
+ case CC_ASCII:
+ break;
+ default:
+ if (fc < 0)
+ goto nope;
+ cc->from.map = ccmap(fc, CC_ASCII);
+ break;
+ }
+ switch (tc)
+ {
+ case CC_UTF:
+ cc->to.fun = bin2utf;
+ break;
+ case CC_UME:
+ cc->to.fun = bin2ume;
+ break;
+ case CC_UCS:
+ cc->to.fun = bin2ucs;
+ break;
+ case CC_SCU:
+ cc->to.fun = bin2scu;
+ break;
+ case CC_ASCII:
+ break;
+ default:
+ if (tc < 0)
+ goto nope;
+ cc->to.map = ccmap(CC_ASCII, tc);
+ break;
+ }
+ }
+ return (iconv_t)cc;
+ nope:
+ return (iconv_t)(-1);
+}
+
+/*
+ * close a character code conversion map
+ */
+
+int
+_ast_iconv_close(_ast_iconv_t cd)
+{
+ Conv_t* cc;
+ Conv_t* oc;
+ int i;
+ int r = 0;
+
+ if (cd == (_ast_iconv_t)(-1))
+ return -1;
+ if (!(cc = (Conv_t*)cd))
+ return 0;
+
+ /*
+ * add to the free list
+ */
+
+ i = freeindex;
+ for (;;)
+ {
+ if (++ i >= elementsof(freelist))
+ i = 0;
+ if (!freelist[i])
+ break;
+ if (i == freeindex)
+ {
+ if (++ i >= elementsof(freelist))
+ i = 0;
+
+ /*
+ * close the oldest
+ */
+
+ if (oc = freelist[i])
+ {
+#if _lib_iconv_open
+ if (oc->cvt != (iconv_t)(-1))
+ r = iconv_close(oc->cvt);
+#endif
+ if (oc->buf)
+ free(oc->buf);
+ free(oc);
+ }
+ break;
+ }
+ }
+ freelist[freeindex = i] = cc;
+ return r;
+}
+
+/*
+ * copy *fb size *fn to *tb size *tn
+ * fb,fn tb,tn updated on return
+ */
+
+size_t
+_ast_iconv(_ast_iconv_t cd, char** fb, size_t* fn, char** tb, size_t* tn)
+{
+ Conv_t* cc = (Conv_t*)cd;
+ register unsigned char* f;
+ register unsigned char* t;
+ register unsigned char* e;
+ register const unsigned char* m;
+ register size_t n;
+ char* b;
+ char* tfb;
+ size_t tfn;
+ size_t i;
+
+ if (!fb || !*fb)
+ {
+ /* TODO: reset to the initial state */
+ if (!tb || !*tb)
+ return 0;
+ /* TODO: write the initial state shift sequence */
+ return 0;
+ }
+ n = *tn;
+ if (cc)
+ {
+ if (cc->from.fun)
+ {
+ if (cc->to.fun)
+ {
+ if (!cc->buf && !(cc->buf = oldof(0, char, cc->size = SF_BUFSIZE, 0)))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ b = cc->buf;
+ i = cc->size;
+ tfb = *fb;
+ tfn = *fn;
+ if ((*cc->from.fun)(cc->cvt, &tfb, &tfn, &b, &i) == (size_t)(-1))
+ return -1;
+ tfn = b - cc->buf;
+ tfb = cc->buf;
+ n = (*cc->to.fun)(cc->cvt, &tfb, &tfn, tb, tn);
+ i = tfb - cc->buf;
+ *fb += i;
+ *fn -= i;
+ return n;
+ }
+ if ((*cc->from.fun)(cc->cvt, fb, fn, tb, tn) == (size_t)(-1))
+ return -1;
+ n -= *tn;
+ if (m = cc->to.map)
+ {
+ e = (unsigned char*)(*tb);
+ for (t = e - n; t < e; t++)
+ *t = m[*t];
+ }
+ return n;
+ }
+ else if (cc->to.fun)
+ {
+ if (!(m = cc->from.map))
+ return (*cc->to.fun)(cc->cvt, fb, fn, tb, tn);
+ if (!cc->buf && !(cc->buf = oldof(0, char, cc->size = SF_BUFSIZE, 0)))
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ if ((n = *fn) > cc->size)
+ n = cc->size;
+ f = (unsigned char*)(*fb);
+ e = f + n;
+ t = (unsigned char*)(b = cc->buf);
+ while (f < e)
+ *t++ = m[*f++];
+ n = (*cc->to.fun)(cc->cvt, &b, fn, tb, tn);
+ *fb += b - cc->buf;
+ return n;
+ }
+ }
+ if (n > *fn)
+ n = *fn;
+ if (cc && (m = cc->from.map))
+ {
+ f = (unsigned char*)(*fb);
+ e = f + n;
+ t = (unsigned char*)(*tb);
+ while (f < e)
+ *t++ = m[*f++];
+ }
+ else
+ memcpy(*tb, *fb, n);
+ *fb += n;
+ *fn -= n;
+ *tb += n;
+ *tn -= n;
+ return n;
+}
+
+#define OK ((size_t)-1)
+
+/*
+ * write *fb size *fn to op
+ * fb,fn updated on return
+ * total bytes written to op returned
+ */
+
+ssize_t
+_ast_iconv_write(_ast_iconv_t cd, Sfio_t* op, char** fb, size_t* fn, Iconv_disc_t* disc)
+{
+ char* fo = *fb;
+ char* tb;
+ char* ts;
+ size_t* e;
+ size_t tn;
+ size_t r;
+ int ok;
+ Iconv_disc_t compat;
+
+ /*
+ * the old api had optional size_t* instead of Iconv_disc_t*
+ */
+
+ if (!disc || disc->version < 20110101L || disc->version >= 30000101L)
+ {
+ e = (size_t*)disc;
+ disc = &compat;
+ iconv_init(disc, 0);
+ }
+ else
+ e = 0;
+ r = 0;
+ tn = 0;
+ ok = 1;
+ while (ok && *fn > 0)
+ {
+ if (!(tb = (char*)sfreserve(op, -(tn + 1), SF_WRITE|SF_LOCKR)) || !(tn = sfvalue(op)))
+ {
+ if (!r)
+ r = -1;
+ break;
+ }
+ ts = tb;
+#if DEBUG_TRACE
+error(DEBUG_TRACE, "AHA#%d iconv_write ts=%p tn=%d", __LINE__, ts, tn);
+ for (;;)
+#else
+ while (*fn > 0 && _ast_iconv(cd, fb, fn, &ts, &tn) == (size_t)(-1))
+#endif
+ {
+#if DEBUG_TRACE
+ ssize_t _r;
+error(DEBUG_TRACE, "AHA#%d iconv_write %d => %d `%-.*s'", __LINE__, *fn, tn, *fn, *fb);
+ _r = _ast_iconv(cd, fb, fn, &ts, &tn);
+error(DEBUG_TRACE, "AHA#%d iconv_write %d => %d [%d]", __LINE__, *fn, tn, _r);
+ if (_r != (size_t)(-1) || !fn)
+ break;
+#endif
+ switch (errno)
+ {
+ case E2BIG:
+ break;
+ case EINVAL:
+ if (disc->errorf)
+ (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "incomplete multibyte sequence at offset %I*u", sizeof(fo), *fb - fo);
+ goto bad;
+ default:
+ if (disc->errorf)
+ (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "invalid multibyte sequence at offset %I*u", sizeof(fo), *fb - fo);
+ bad:
+ disc->errors++;
+ if (!(disc->flags & ICONV_FATAL))
+ {
+ if (!(disc->flags & ICONV_OMIT) && tn > 0)
+ {
+ *ts++ = (disc->fill >= 0) ? disc->fill : **fb;
+ tn--;
+ }
+ (*fb)++;
+ (*fn)--;
+ continue;
+ }
+ ok = 0;
+ break;
+ }
+ break;
+ }
+#if DEBUG_TRACE
+error(DEBUG_TRACE, "AHA#%d iconv_write %d", __LINE__, ts - tb);
+#endif
+ sfwrite(op, tb, ts - tb);
+ r += ts - tb;
+ }
+ if (e)
+ *e = disc->errors;
+ return r;
+}
+
+/*
+ * move n bytes from ip to op
+ */
+
+ssize_t
+_ast_iconv_move(_ast_iconv_t cd, Sfio_t* ip, Sfio_t* op, size_t n, Iconv_disc_t* disc)
+{
+ char* fb;
+ char* fs;
+ char* tb;
+ char* ts;
+ size_t* e;
+ size_t fe;
+ size_t fn;
+ size_t fo;
+ size_t ft;
+ size_t tn;
+ size_t i;
+ ssize_t r = 0;
+ int ok = 1;
+ int locked;
+ Iconv_disc_t compat;
+
+ /*
+ * the old api had optional size_t* instead of Iconv_disc_t*
+ */
+
+ if (!disc || disc->version < 20110101L || disc->version >= 30000101L)
+ {
+ e = (size_t*)disc;
+ disc = &compat;
+ iconv_init(disc, 0);
+ }
+ else
+ e = 0;
+ tb = 0;
+ fe = OK;
+ ft = 0;
+ fn = n;
+ do
+ {
+ if (n != SF_UNBOUND)
+ n = -((ssize_t)(n & (((size_t)(~0))>>1)));
+ if ((!(fb = (char*)sfreserve(ip, n, locked = SF_LOCKR)) || !(fo = sfvalue(ip))) &&
+ (!(fb = (char*)sfreserve(ip, n, locked = 0)) || !(fo = sfvalue(ip))))
+ break;
+ fs = fb;
+ fn = fo;
+ if (!(tb = (char*)sfreserve(op, SF_UNBOUND, SF_WRITE|SF_LOCKR)))
+ {
+ if (!r)
+ r = -1;
+ break;
+ }
+ ts = tb;
+ tn = sfvalue(op);
+ while (fn > 0 && _ast_iconv(cd, &fs, &fn, &ts, &tn) == (size_t)(-1))
+ {
+ switch (errno)
+ {
+ case E2BIG:
+ break;
+ case EINVAL:
+ if (fe == ft + (fo - fn))
+ {
+ fe = OK;
+ if (disc->errorf)
+ (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "incomplete multibyte sequence at offset %I*u", sizeof(ft), ft + (fo - fn));
+ goto bad;
+ }
+ fe = ft;
+ break;
+ default:
+ if (disc->errorf)
+ (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "invalid multibyte sequence at offset %I*u", sizeof(ft), ft + (fo - fn));
+ bad:
+ disc->errors++;
+ if (!(disc->flags & ICONV_FATAL))
+ {
+ if (!(disc->flags & ICONV_OMIT) && tn > 0)
+ {
+ *ts++ = (disc->fill >= 0) ? disc->fill : *fs;
+ tn--;
+ }
+ fs++;
+ fn--;
+ continue;
+ }
+ ok = 0;
+ break;
+ }
+ break;
+ }
+ sfwrite(op, tb, ts - tb);
+ r += ts - tb;
+ ts = tb;
+ if (locked)
+ sfread(ip, fb, fs - fb);
+ else
+ for (i = fn; --i >= (fs - fb);)
+ sfungetc(ip, fb[i]);
+ if (n != SF_UNBOUND)
+ {
+ if (n <= (fs - fb))
+ break;
+ n -= fs - fb;
+ }
+ ft += (fs - fb);
+ if (fn == fo)
+ fn++;
+ } while (ok);
+ if (fb && locked)
+ sfread(ip, fb, 0);
+ if (tb)
+ {
+ sfwrite(op, tb, 0);
+ if (ts > tb)
+ {
+ sfwrite(op, tb, ts - tb);
+ r += ts - tb;
+ }
+ }
+ if (e)
+ *e = disc->errors;
+ return r;
+}
+
+/*
+ * iconv_list_t iterator
+ * call with arg 0 to start
+ * prev return value is current arg
+ */
+
+_ast_iconv_list_t*
+_ast_iconv_list(_ast_iconv_list_t* cp)
+{
+#if _UWIN
+ struct dirent* ent;
+
+ if (!cp)
+ {
+ if (!(cp = newof(0, _ast_iconv_list_t, 1, 0)))
+ return ccmaplist(NiL);
+ if (!(cp->data = opendir(_win_maps)))
+ {
+ free(cp);
+ return ccmaplist(NiL);
+ }
+ }
+ if (cp->data)
+ {
+ if (ent = readdir((DIR*)cp->data))
+ {
+ cp->name = cp->match = cp->desc = (const char*)ent->d_name;
+ return cp;
+ }
+ closedir((DIR*)cp->data);
+ free(cp);
+ return ccmaplist(NiL);
+ }
+#else
+ if (!cp)
+ return ccmaplist(NiL);
+#endif
+ if (cp->ccode >= 0)
+ return (cp = ccmaplist(cp)) ? cp : (_ast_iconv_list_t*)codes;
+ return (++cp)->name ? cp : (_ast_iconv_list_t*)0;
+}
diff --git a/src/lib/libast/comp/killpg.c b/src/lib/libast/comp/killpg.c
new file mode 100644
index 0000000..725a1f9
--- /dev/null
+++ b/src/lib/libast/comp/killpg.c
@@ -0,0 +1,40 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_killpg
+
+NoN(killpg)
+
+#else
+
+#include <sig.h>
+
+int
+killpg(pid_t g, int s)
+{
+ return(kill(-g, s));
+}
+
+#endif
diff --git a/src/lib/libast/comp/libgen.h b/src/lib/libast/comp/libgen.h
new file mode 100644
index 0000000..a2bb92a
--- /dev/null
+++ b/src/lib/libast/comp/libgen.h
@@ -0,0 +1,52 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * libgen interface definitions
+ */
+
+#ifndef _LIBGEN_H
+#define _LIBGEN_H
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+#if !_BLD_ast && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern char* __loc1;
+
+#undef extern
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char* regcmp(const char*, ...);
+extern char* regex(const char*, const char*, ...);
+extern char* basename(char*);
+extern char* dirname(char*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/comp/link.c b/src/lib/libast/comp/link.c
new file mode 100644
index 0000000..571806f
--- /dev/null
+++ b/src/lib/libast/comp/link.c
@@ -0,0 +1,47 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_link
+
+NoN(link)
+
+#else
+
+#include <error.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+int
+link(const char* from, const char* to)
+{
+ NoP(from);
+ NoP(to);
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif
diff --git a/src/lib/libast/comp/localeconv.c b/src/lib/libast/comp/localeconv.c
new file mode 100644
index 0000000..8cdc841
--- /dev/null
+++ b/src/lib/libast/comp/localeconv.c
@@ -0,0 +1,100 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * localeconv() intercept
+ */
+
+#include "lclib.h"
+
+#undef localeconv
+
+static char null[] = "";
+
+static struct lconv debug_lconv =
+{
+ ",",
+ ".",
+ &null[0],
+ &null[0],
+ &null[0],
+ &null[0],
+ &null[0],
+ &null[0],
+ &null[0],
+ &null[0],
+ CHAR_MAX,
+ CHAR_MAX,
+ CHAR_MAX,
+ CHAR_MAX,
+ CHAR_MAX,
+ CHAR_MAX,
+ CHAR_MAX,
+ CHAR_MAX,
+};
+
+static struct lconv default_lconv =
+{
+ ".",
+ &null[0],
+ &null[0],
+ &null[0],
+ &null[0],
+ &null[0],
+ &null[0],
+ &null[0],
+ &null[0],
+ &null[0],
+ CHAR_MAX,
+ CHAR_MAX,
+ CHAR_MAX,
+ CHAR_MAX,
+ CHAR_MAX,
+ CHAR_MAX,
+ CHAR_MAX,
+ CHAR_MAX,
+};
+
+#if !_lib_localeconv
+
+struct lconv*
+localeconv(void)
+{
+ return &default_lconv;
+}
+
+#endif
+
+/*
+ * localeconv() intercept
+ */
+
+struct lconv*
+_ast_localeconv(void)
+{
+ if ((locales[AST_LC_MONETARY]->flags | locales[AST_LC_NUMERIC]->flags) & LC_debug)
+ return &debug_lconv;
+ if ((locales[AST_LC_NUMERIC]->flags & (LC_default|LC_local)) == LC_local)
+ return locales[AST_LC_NUMERIC]->territory == &lc_territories[0] ? &default_lconv : &debug_lconv;
+ return localeconv();
+}
diff --git a/src/lib/libast/comp/lstat.c b/src/lib/libast/comp/lstat.c
new file mode 100644
index 0000000..7531215
--- /dev/null
+++ b/src/lib/libast/comp/lstat.c
@@ -0,0 +1,39 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <ls.h>
+
+#if _lib_lstat
+
+NoN(lstat)
+
+#else
+
+int
+lstat(const char* path, struct stat* st)
+{
+ return(stat(path, st));
+}
+
+#endif
diff --git a/src/lib/libast/comp/memccpy.c b/src/lib/libast/comp/memccpy.c
new file mode 100644
index 0000000..c973a2d
--- /dev/null
+++ b/src/lib/libast/comp/memccpy.c
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_memccpy && !_UWIN
+
+NoN(memccpy)
+
+#else
+
+/*
+ * Copy s2 to s1, stopping if character c is copied. Copy no more than n bytes.
+ * Return a pointer to the byte after character c in the copy,
+ * or 0 if c is not found in the first n bytes.
+ */
+
+void*
+memccpy(void* as1, const void* as2, register int c, size_t n)
+{
+ register char* s1 = (char*)as1;
+ register const char* s2 = (char*)as2;
+ register const char* ep = s2 + n;
+
+ while (s2 < ep)
+ if ((*s1++ = *s2++) == c)
+ return(s1);
+ return(0);
+}
+
+#endif
diff --git a/src/lib/libast/comp/memchr.c b/src/lib/libast/comp/memchr.c
new file mode 100644
index 0000000..d294059
--- /dev/null
+++ b/src/lib/libast/comp/memchr.c
@@ -0,0 +1,49 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_memchr
+
+NoN(memchr)
+
+#else
+
+/*
+ * Return the ptr in sp at which the character c appears;
+ * 0 if not found in n chars; don't stop at \0.
+ */
+
+void*
+memchr(const void* asp, register int c, size_t n)
+{
+ register const char* sp = (char*)asp;
+ register const char* ep = sp + n;
+
+ while (sp < ep)
+ if (*sp++ == c)
+ return(--sp);
+ return(0);
+}
+
+#endif
diff --git a/src/lib/libast/comp/memcmp.c b/src/lib/libast/comp/memcmp.c
new file mode 100644
index 0000000..b74540c
--- /dev/null
+++ b/src/lib/libast/comp/memcmp.c
@@ -0,0 +1,45 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_memcmp
+
+NoN(memcmp)
+
+#else
+
+int
+memcmp(const void* ab1, const void* ab2, size_t n)
+{
+ register const unsigned char* b1 = (const unsigned char*)ab1;
+ register const unsigned char* b2 = (const unsigned char*)ab2;
+ register const unsigned char* e = b1 + n;
+
+ while (b1 < e)
+ if (*b1++ != *b2++)
+ return(*--b1 - *--b2);
+ return(0);
+}
+
+#endif
diff --git a/src/lib/libast/comp/memcpy.c b/src/lib/libast/comp/memcpy.c
new file mode 100644
index 0000000..25fa0b7
--- /dev/null
+++ b/src/lib/libast/comp/memcpy.c
@@ -0,0 +1,60 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_memcpy
+
+NoN(memcpy)
+
+#else
+
+#undef memcpy
+
+#if _lib_bcopy
+
+extern void bcopy(void*, void*, size_t);
+
+void*
+memcpy(void* s1, void* s2, size_t n)
+{
+ bcopy(s2, s1, n);
+ return(s1);
+}
+
+#else
+
+void*
+memcpy(void* as1, const void* as2, register size_t n)
+{
+ register char* s1 = (char*)as1;
+ register const char* s2 = (const char*)as2;
+
+ while (n-- > 0)
+ *s1++ = *s2++;
+ return(as1);
+}
+
+#endif
+
+#endif
diff --git a/src/lib/libast/comp/memmove.c b/src/lib/libast/comp/memmove.c
new file mode 100644
index 0000000..9d5ba59
--- /dev/null
+++ b/src/lib/libast/comp/memmove.c
@@ -0,0 +1,53 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_memmove
+
+NoN(memmove)
+
+#else
+
+void*
+memmove(void* to, const void* from, register size_t n)
+{
+ register char* out = (char*)to;
+ register char* in = (char*)from;
+
+ if (n <= 0) /* works if size_t is signed or not */
+ ;
+ else if (in + n <= out || out + n <= in)
+ return(memcpy(to, from, n)); /* hope it's fast*/
+ else if (out < in)
+ do *out++ = *in++; while (--n > 0);
+ else
+ {
+ out += n;
+ in += n;
+ do *--out = *--in; while(--n > 0);
+ }
+ return(to);
+}
+
+#endif
diff --git a/src/lib/libast/comp/memset.c b/src/lib/libast/comp/memset.c
new file mode 100644
index 0000000..359d157
--- /dev/null
+++ b/src/lib/libast/comp/memset.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_memset
+
+NoN(memset)
+
+#else
+
+void*
+memset(void* asp, register int c, register size_t n)
+{
+ register char* sp = (char*)asp;
+
+ while (n-- > 0)
+ *sp++ = c;
+ return(asp);
+}
+
+#endif
diff --git a/src/lib/libast/comp/mkdir.c b/src/lib/libast/comp/mkdir.c
new file mode 100644
index 0000000..37e8e51
--- /dev/null
+++ b/src/lib/libast/comp/mkdir.c
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_mkdir
+
+NoN(mkdir)
+
+#else
+
+#include <ls.h>
+#include <wait.h>
+#include <error.h>
+
+int
+mkdir(const char* path, mode_t mode)
+{
+ register int n;
+ char* av[3];
+
+ static char* cmd[] = { "/bin/mkdir", "/usr/5bin/mkdir", 0 };
+
+
+ n = errno;
+ if (!access(path, F_OK))
+ {
+ errno = EEXIST;
+ return(-1);
+ }
+ if (errno != ENOENT) return(-1);
+ errno = n;
+ av[0] = "mkdir";
+ av[1] = path;
+ av[2] = 0;
+ for (n = 0; n < elementsof(cmd); n++)
+ if (procclose(procopen(cmd[n], av, NiL, NiL, 0)) != -1)
+ break;
+ return(chmod(path, mode));
+}
+
+#endif
diff --git a/src/lib/libast/comp/mkfifo.c b/src/lib/libast/comp/mkfifo.c
new file mode 100644
index 0000000..e4b26a4
--- /dev/null
+++ b/src/lib/libast/comp/mkfifo.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_mkfifo
+
+NoN(mkfifo)
+
+#else
+
+#include <ls.h>
+#include <error.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+int
+mkfifo(const char* path, mode_t mode)
+{
+#ifdef S_IFIFO
+ return mknod(path, S_IFIFO|(mode & ~S_IFMT), 0);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+#endif
diff --git a/src/lib/libast/comp/mknod.c b/src/lib/libast/comp/mknod.c
new file mode 100644
index 0000000..8172a13
--- /dev/null
+++ b/src/lib/libast/comp/mknod.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <ls.h>
+
+#if _lib_mknod
+
+NoN(mknod)
+
+#else
+
+#include <error.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+int
+mknod(const char* path, mode_t mode, dev_t dev)
+{
+ if (S_ISFIFO(mode))
+ return mkfifo(path, mode);
+ if (S_ISDIR(mode))
+ return mkdir(path, mode);
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif
diff --git a/src/lib/libast/comp/mktemp.c b/src/lib/libast/comp/mktemp.c
new file mode 100644
index 0000000..c29dc90
--- /dev/null
+++ b/src/lib/libast/comp/mktemp.c
@@ -0,0 +1,85 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * mktemp,mkstemp implementation
+ */
+
+#define mktemp ______mktemp
+#define mkstemp ______mkstemp
+
+#include <ast.h>
+#include <stdio.h>
+
+#undef mktemp
+#undef mkstemp
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+static char*
+temp(char* buf, int* fdp)
+{
+ char* s;
+ char* d;
+ int n;
+ size_t len;
+
+ len = strlen(buf);
+ if (s = strrchr(buf, '/'))
+ {
+ *s++ = 0;
+ d = buf;
+ }
+ else
+ {
+ s = buf;
+ d = "";
+ }
+ if ((n = strlen(s)) < 6 || strcmp(s + n - 6, "XXXXXX"))
+ *buf = 0;
+ else
+ {
+ *(s + n - 6) = 0;
+ if (!pathtemp(buf, len, d, s, fdp))
+ *buf = 0;
+ }
+ return buf;
+}
+
+extern char*
+mktemp(char* buf)
+{
+ return temp(buf, NiL);
+}
+
+extern int
+mkstemp(char* buf)
+{
+ int fd;
+
+ return *temp(buf, &fd) ? fd : -1;
+}
diff --git a/src/lib/libast/comp/mktime.c b/src/lib/libast/comp/mktime.c
new file mode 100644
index 0000000..c39ca40
--- /dev/null
+++ b/src/lib/libast/comp/mktime.c
@@ -0,0 +1,77 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * mktime implementation
+ */
+
+#define mktime ______mktime
+
+#include <ast.h>
+#include <tm.h>
+
+#undef mktime
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#undef _lib_mktime /* we can pass X/Open */
+
+#if _lib_mktime
+
+NoN(mktime)
+
+#else
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern time_t
+mktime(struct tm* ts)
+{
+ time_t t;
+ Tm_t tm;
+
+ tm.tm_sec = ts->tm_sec;
+ tm.tm_min = ts->tm_min;
+ tm.tm_hour = ts->tm_hour;
+ tm.tm_mday = ts->tm_mday;
+ tm.tm_mon = ts->tm_mon;
+ tm.tm_year = ts->tm_year;
+ tm.tm_wday = ts->tm_wday;
+ tm.tm_yday = ts->tm_yday;
+ tm.tm_isdst = ts->tm_isdst;
+ t = tmtime(&tm, TM_LOCALZONE);
+ ts->tm_sec = tm.tm_sec;
+ ts->tm_min = tm.tm_min;
+ ts->tm_hour = tm.tm_hour;
+ ts->tm_mday = tm.tm_mday;
+ ts->tm_mon = tm.tm_mon;
+ ts->tm_year = tm.tm_year;
+ ts->tm_wday = tm.tm_wday;
+ ts->tm_yday = tm.tm_yday;
+ ts->tm_isdst = tm.tm_isdst;
+ return t;
+}
+
+#endif
diff --git a/src/lib/libast/comp/mount.c b/src/lib/libast/comp/mount.c
new file mode 100644
index 0000000..eaf27e5
--- /dev/null
+++ b/src/lib/libast/comp/mount.c
@@ -0,0 +1,49 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_mount
+
+NoN(mount)
+
+#else
+
+#include <error.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+int
+mount(const char* a, char* b, int c, void* d)
+{
+ NoP(a);
+ NoP(b);
+ NoP(c);
+ NoP(d);
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif
diff --git a/src/lib/libast/comp/nftw.c b/src/lib/libast/comp/nftw.c
new file mode 100644
index 0000000..6c8c97a
--- /dev/null
+++ b/src/lib/libast/comp/nftw.c
@@ -0,0 +1,61 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * nftw implementation
+ */
+
+#include <ast.h>
+#include <ftw.h>
+
+static int nftw_flags;
+static int (*nftw_userf)(const char*, const struct stat*, int, struct FTW*);
+
+static int
+nftw_user(Ftw_t* ftw)
+{
+ register int n = ftw->info;
+ struct FTW nftw;
+ struct stat st;
+
+ if (n & (FTW_C|FTW_NX))
+ n = FTW_DNR;
+ else if ((n & FTW_SL) && (!(nftw_flags & FTW_PHYSICAL) || stat(ftw->path, &st)))
+ n = FTW_SLN;
+ nftw.base = ftw->pathlen - ftw->namelen;
+ nftw.level = ftw->level;
+ nftw.quit = 0;
+ n = (*nftw_userf)(ftw->path, &ftw->statb, n, &nftw);
+ ftw->status = nftw.quit;
+ return n;
+}
+
+int
+nftw(const char* path, int(*userf)(const char*, const struct stat*, int, struct FTW*), int depth, int flags)
+{
+ NoP(depth);
+ nftw_userf = userf;
+ if (flags & FTW_CHDIR) flags &= ~FTW_DOT;
+ else flags |= FTW_DOT;
+ nftw_flags = flags;
+ return ftwalk(path, nftw_user, flags, NiL);
+}
diff --git a/src/lib/libast/comp/omitted.c b/src/lib/libast/comp/omitted.c
new file mode 100644
index 0000000..b517965
--- /dev/null
+++ b/src/lib/libast/comp/omitted.c
@@ -0,0 +1,1152 @@
+#pragma prototyped noticed
+
+/*
+ * workarounds to bring the native interface close to posix and x/open
+ */
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide utime utimes
+#else
+#define utime ______utime
+#define utimes ______utimes
+#endif
+
+#include <ast.h>
+#include <error.h>
+#include <tm.h>
+
+#include "FEATURE/omitted"
+
+#undef OMITTED
+
+#if _win32_botch
+
+#define OMITTED 1
+
+#include <ls.h>
+#include <utime.h>
+
+#if __CYGWIN__
+#include <ast_windows.h>
+#if _win32_botch_execve || _lib_spawn_mode
+#define CONVERT 1
+#endif
+#endif
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide utime utimes
+#else
+#undef utime
+#undef utimes
+#endif
+
+#ifndef MAX_PATH
+#define MAX_PATH PATH_MAX
+#endif
+
+/*
+ * these workarounds assume each system call foo() has a _foo() entry
+ * which is true for __CYGWIN__ and __EMX__ (both gnu based)
+ *
+ * the workarounds handle:
+ *
+ * (1) .exe suffix inconsistencies
+ * (2) /bin/sh reference in execve() and spawnve()
+ * (3) bogus getpagesize() return values
+ * (4) a fork() bug that screws up shell fork()+script
+ *
+ * NOTE: Not all workarounds can be handled by unix syscall intercepts.
+ * In particular, { ksh nmake } have workarounds for case-ignorant
+ * filesystems and { libast } has workarounds for win32 locale info.
+ */
+
+#undef _pathconf
+#undef pathconf
+#undef stat
+
+extern int _access(const char*, int);
+extern unsigned int _alarm(unsigned int);
+extern int _chmod(const char*, mode_t);
+extern int _close(int);
+extern pid_t _execve(const char*, char* const*, char* const*);
+extern uid_t _getuid(void);
+extern int _link(const char*, const char*);
+extern int _open(const char*, int, ...);
+extern long _pathconf(const char*, int);
+extern ssize_t _read(int, void*, size_t);
+extern int _rename(const char*, const char*);
+extern pid_t _spawnve(int, const char*, char* const*, char* const*);
+extern int _stat(const char*, struct stat*);
+extern int _unlink(const char*);
+extern int _utime(const char*, const struct utimbuf*);
+extern int _utimes(const char*, const struct timeval*);
+extern ssize_t _write(int, const void*, size_t);
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#if _win32_botch_access
+#define sysaccess _access
+#else
+#define sysaccess access
+#endif
+#if _win32_botch_alarm
+#define sysalarm _alarm
+#else
+#define sysalarm alarm
+#endif
+#if _win32_botch_chmod
+#define syschmod _chmod
+#else
+#define syschmod chmod
+#endif
+#if _win32_botch_copy
+#define sysclose _close
+#else
+#define sysclose close
+#endif
+#if _win32_botch_execve || _lib_spawn_mode
+#define sysexecve _execve
+#else
+#define sysexecve execve
+#endif
+#if CONVERT
+#define sysgetuid _getuid
+#else
+#define sysgetuid getuid
+#endif
+#if _win32_botch_link
+#define syslink _link
+#else
+#define syslink link
+#endif
+#if _win32_botch_open || _win32_botch_copy
+#define sysopen _open
+#else
+#define sysopen open
+#endif
+#if _win32_botch_pathconf
+#define syspathconf _pathconf
+#else
+#define syspathconf pathconf
+#endif
+#define sysread _read
+#if _win32_botch_rename
+#define sysrename _rename
+#else
+#define sysrename rename
+#endif
+#if _lib_spawn_mode
+#define sysspawnve _spawnve
+#else
+#define sysspawnve spawnve
+#endif
+#if _win32_botch_stat
+#define sysstat _stat
+#else
+#define sysstat stat
+#endif
+#if _win32_botch_truncate
+#define systruncate _truncate
+#else
+#define systruncate truncate
+#endif
+#if _win32_botch_unlink
+#define sysunlink _unlink
+#else
+#define sysunlink unlink
+#endif
+#if _win32_botch_utime
+#define sysutime _utime
+#define sysutimes _utimes
+#else
+#define sysutime utime
+#define sysutimes utimes
+#endif
+#if _win32_botch_copy
+#define syswrite _write
+#else
+#define syswrite write
+#endif
+
+static char*
+suffix(register const char* path)
+{
+ register const char* s = path + strlen(path);
+ register int c;
+
+ while (s > path)
+ if ((c = *--s) == '.')
+ return (char*)s + 1;
+ else if (c == '/' || c == '\\')
+ break;
+ return 0;
+}
+
+static int
+execrate(const char* path, char* buf, int size, int physical)
+{
+ char* s;
+ int n;
+ int oerrno;
+
+ if (suffix(path))
+ return 0;
+ oerrno = errno;
+ if (physical || strlen(path) >= size || !(s = pathcanon(strcpy(buf, path), size, PATH_PHYSICAL|PATH_DOTDOT|PATH_EXISTS)))
+ snprintf(buf, size, "%s.exe", path);
+ else if (!suffix(buf) && ((buf + size) - s) >= 4)
+ strcpy(s, ".exe");
+ errno = oerrno;
+ return 1;
+}
+
+/*
+ * return 0 if path is magic, -1 otherwise
+ * ux!=0 set to 1 if path is unix executable
+ * ux!=0 also retains errno for -1 return
+ */
+
+static int
+magic(const char* path, int* ux)
+{
+ int fd;
+ int r;
+ int n;
+ int m;
+ int oerrno;
+#if CONVERT
+ unsigned char buf[512];
+#else
+ unsigned char buf[2];
+#endif
+
+ oerrno = errno;
+ if ((fd = sysopen(path, O_RDONLY, 0)) >= 0)
+ {
+#if CONVERT
+ if (ux)
+ n = sizeof(buf);
+ else
+#endif
+ n = 2;
+ r = (m = sysread(fd, buf, n)) >= 2 && (buf[1] == 0x5a && (buf[0] == 0x4c || buf[0] == 0x4d) || ux && buf[0] == '#' && buf[1] == '!' && (*ux = 1) && !(ux = 0)) ? 0 : -1;
+ sysclose(fd);
+ if (ux)
+ {
+ if (r)
+ oerrno = ENOEXEC;
+ else if (m > 61 && (n = buf[60] | (buf[61]<<8) + 92) < (m - 1))
+ *ux = (buf[n] | (buf[n+1]<<8)) == 3;
+ else
+ *ux = 0;
+ }
+ }
+ else if (!ux)
+ r = -1;
+ else if (errno == ENOENT)
+ {
+ oerrno = errno;
+ r = -1;
+ }
+ else
+ {
+ r = 0;
+ *ux = 0;
+ }
+ errno = oerrno;
+ return r;
+}
+
+#if _win32_botch_access
+
+extern int
+access(const char* path, int op)
+{
+ int r;
+ int oerrno;
+ char buf[PATH_MAX];
+
+ oerrno = errno;
+ if ((r = sysaccess(path, op)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
+ {
+ errno = oerrno;
+ r = sysaccess(buf, op);
+ }
+ return r;
+}
+
+#endif
+
+#if _win32_botch_alarm
+
+extern unsigned int
+alarm(unsigned int s)
+{
+ unsigned int n;
+ unsigned int r;
+
+ static unsigned int a;
+
+ n = (unsigned int)time(NiL);
+ if (a <= n)
+ r = 0;
+ else
+ r = a - n;
+ a = n + s - 1;
+ (void)sysalarm(s);
+ return r;
+}
+
+#endif
+
+#if _win32_botch_chmod
+
+extern int
+chmod(const char* path, mode_t mode)
+{
+ int r;
+ int oerrno;
+ char buf[PATH_MAX];
+
+ if ((r = syschmod(path, mode)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
+ {
+ errno = oerrno;
+ return syschmod(buf, mode);
+ }
+ if (!(r = syschmod(path, mode)) &&
+ (mode & (S_IXUSR|S_IXGRP|S_IXOTH)) &&
+ !suffix(path) &&
+ (strlen(path) + 4) < sizeof(buf))
+ {
+ oerrno = errno;
+ if (!magic(path, NiL))
+ {
+ snprintf(buf, sizeof(buf), "%s.exe", path);
+ sysrename(path, buf);
+ }
+ errno = oerrno;
+ }
+ return r;
+}
+
+#endif
+
+#if _win32_botch_execve || _lib_spawn_mode
+
+#if _lib_spawn_mode
+
+/*
+ * can anyone get const prototype args straight?
+ */
+
+#define execve ______execve
+#define spawnve ______spawnve
+
+#include <process.h>
+
+#undef execve
+#undef spawnve
+
+#endif
+
+#if CONVERT
+
+/*
+ * this intercept converts dos env vars to unix
+ * we'd rather intercept main but can't twist cc to do it
+ * getuid() gets ksh to do the right thing and
+ * that's our main concern
+ *
+ * DOSPATHVARS='a b c' convert { a b c }
+ */
+
+static int convertinit;
+
+/*
+ * convertvars[0] names the list of env var names
+ * convertvars[i] are not converted
+ */
+
+static const char* convertvars[] = { "DOSPATHVARS", "PATH" };
+
+static int
+convert(register const char* d, const char* s)
+{
+ register const char* t;
+ register const char* v;
+ int i;
+
+ for (i = 0; i < elementsof(convertvars); i++)
+ {
+ for (v = convertvars[i], t = s; *t && *t == *v; t++, v++);
+ if (*t == '=' && *v == 0)
+ return 0;
+ }
+ for (;;)
+ {
+ while (*d == ' ' || *d == '\t')
+ d++;
+ if (!*d)
+ break;
+ for (t = s; *t && *t == *d; d++, t++);
+ if (*t == '=' && (*d == ' ' || *d == '\t' || *d == 0))
+ return t - s + 1;
+ while (*d && *d != ' ' && *d != '\t')
+ d++;
+ }
+ return 0;
+}
+
+uid_t
+getuid(void)
+{
+ register char* d;
+ register char* s;
+ register char* t;
+ register char** e;
+ int n;
+ int m;
+
+ if (!convertinit++ && (d = getenv(convertvars[0])))
+ for (e = environ; s = *e; e++)
+ if ((n = convert(d, s)) && (m = cygwin_win32_to_posix_path_list_buf_size(s + n)) > 0)
+ {
+ if (!(t = malloc(n + m + 1)))
+ break;
+ *e = t;
+ memcpy(t, s, n);
+ cygwin_win32_to_posix_path_list(s + n, t + n);
+ }
+ return sysgetuid();
+}
+
+#endif
+
+#ifndef _P_OVERLAY
+#define _P_OVERLAY (-1)
+#endif
+
+#define DEBUG 1
+
+static pid_t
+runve(int mode, const char* path, char* const* argv, char* const* envv)
+{
+ register char* s;
+ register char** p;
+ register char** v;
+
+ void* m1;
+ void* m2;
+ pid_t pid;
+ int oerrno;
+ int ux;
+ int n;
+#if defined(_P_DETACH) && defined(_P_NOWAIT)
+ int pgrp;
+#endif
+#if CONVERT
+ char* d;
+ char* t;
+ int m;
+#endif
+ struct stat st;
+ char buf[PATH_MAX];
+ char tmp[PATH_MAX];
+
+#if DEBUG
+ static int trace;
+#endif
+
+#if defined(_P_DETACH) && defined(_P_NOWAIT)
+ if (mode == _P_DETACH)
+ {
+ /*
+ * 2004-02-29 cygwin _P_DETACH is useless:
+ * spawn*() returns 0 instead of the spawned pid
+ * spawned { pgid sid } are the same as the parent
+ */
+
+ mode = _P_NOWAIT;
+ pgrp = 1;
+ }
+ else
+ pgrp = 0;
+#endif
+ if (!envv)
+ envv = (char* const*)environ;
+ m1 = m2 = 0;
+ oerrno = errno;
+#if DEBUG
+ if (!trace)
+ trace = (s = getenv("_AST_exec_trace")) ? *s : 'n';
+#endif
+ if (execrate(path, buf, sizeof(buf), 0))
+ {
+ if (!sysstat(buf, &st))
+ path = (const char*)buf;
+ else
+ errno = oerrno;
+ }
+ if (path != (const char*)buf && sysstat(path, &st))
+ return -1;
+ if (!S_ISREG(st.st_mode) || !(st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
+ {
+ errno = EACCES;
+ return -1;
+ }
+ if (magic(path, &ux))
+ {
+#if _CYGWIN_fork_works
+ errno = ENOEXEC;
+ return -1;
+#else
+ ux = 1;
+ p = (char**)argv;
+ while (*p++);
+ if (!(v = (char**)malloc((p - (char**)argv + 2) * sizeof(char*))))
+ {
+ errno = EAGAIN;
+ return -1;
+ }
+ m1 = v;
+ p = v;
+ *p++ = (char*)path;
+ *p++ = (char*)path;
+ path = (const char*)pathshell();
+ if (*argv)
+ argv++;
+ while (*p++ = (char*)*argv++);
+ argv = (char* const*)v;
+#endif
+ }
+
+ /*
+ * the win32 dll search order is
+ * (1) the directory of path
+ * (2) .
+ * (3) /c/(WINNT|WINDOWS)/system32 /c/(WINNT|WINDOWS)
+ * (4) the directories on $PATH
+ * there are no cygwin dlls in (3), so if (1) and (2) fail
+ * to produce the required dlls its up to (4)
+ *
+ * the standard allows PATH to be anything once the path
+ * to an executable is determined; this code ensures that PATH
+ * contains /bin so that at least the cygwin dll, required
+ * by all cygwin executables, will be found
+ */
+
+ if (p = (char**)envv)
+ {
+ n = 1;
+ while (s = *p++)
+ if (strneq(s, "PATH=", 5))
+ {
+ s += 5;
+ do
+ {
+ s = pathcat(s, ':', NiL, "", tmp, sizeof(tmp));
+ if (streq(tmp, "/usr/bin/") || streq(tmp, "/bin/"))
+ {
+ n = 0;
+ break;
+ }
+ } while (s);
+ if (n)
+ {
+ n = 0;
+ snprintf(tmp, sizeof(tmp), "%s:/bin", *(p - 1));
+ *(p - 1) = tmp;
+ }
+ break;
+ }
+ if (n)
+ {
+ n = p - (char**)envv + 1;
+ p = (char**)envv;
+ if (v = (char**)malloc(n * sizeof(char*)))
+ {
+ m2 = v;
+ envv = (char* const*)v;
+ *v++ = strcpy(tmp, "PATH=/bin");
+ while (*v++ = *p++);
+ }
+ }
+#if CONVERT
+ if (!ux && (d = getenv(convertvars[0])))
+ for (p = (char**)envv; s = *p; p++)
+ if ((n = convert(d, s)) && (m = cygwin_posix_to_win32_path_list_buf_size(s + n)) > 0)
+ {
+ if (!(t = malloc(n + m + 1)))
+ break;
+ *p = t;
+ memcpy(t, s, n);
+ cygwin_posix_to_win32_path_list(s + n, t + n);
+ }
+#endif
+ }
+
+#if DEBUG
+ if (trace == 'a' || trace == 'e')
+ {
+ sfprintf(sfstderr, "%s %s [", mode == _P_OVERLAY ? "_execve" : "_spawnve", path);
+ for (n = 0; argv[n]; n++)
+ sfprintf(sfstderr, " '%s'", argv[n]);
+ if (trace == 'e')
+ {
+ sfprintf(sfstderr, " ] [");
+ for (n = 0; envv[n]; n++)
+ sfprintf(sfstderr, " '%s'", envv[n]);
+ }
+ sfprintf(sfstderr, " ]\n");
+ sfsync(sfstderr);
+ }
+#endif
+#if _lib_spawn_mode
+ if (mode != _P_OVERLAY)
+ {
+ pid = sysspawnve(mode, path, argv, envv);
+#if defined(_P_DETACH) && defined(_P_NOWAIT)
+ if (pid > 0 && pgrp)
+ setpgid(pid, 0);
+#endif
+ }
+ else
+#endif
+ {
+#if defined(_P_DETACH) && defined(_P_NOWAIT)
+ if (pgrp)
+ setpgid(0, 0);
+#endif
+ pid = sysexecve(path, argv, envv);
+ }
+ if (m1)
+ free(m1);
+ if (m2)
+ free(m2);
+ return pid;
+}
+
+#if _win32_botch_execve
+
+extern pid_t
+execve(const char* path, char* const* argv, char* const* envv)
+{
+ return runve(_P_OVERLAY, path, argv, envv);
+}
+
+#endif
+
+#if _lib_spawn_mode
+
+extern pid_t
+spawnve(int mode, const char* path, char* const* argv, char* const* envv)
+{
+ return runve(mode, path, argv, envv);
+}
+
+#endif
+
+#endif
+
+#if _win32_botch_getpagesize
+
+extern size_t
+getpagesize(void)
+{
+ return 64 * 1024;
+}
+
+#endif
+
+#if _win32_botch_link
+
+extern int
+link(const char* fp, const char* tp)
+{
+ int r;
+ int oerrno;
+ char fb[PATH_MAX];
+ char tb[PATH_MAX];
+
+ oerrno = errno;
+ if ((r = syslink(fp, tp)) && errno == ENOENT && execrate(fp, fb, sizeof(fb), 1))
+ {
+ if (execrate(tp, tb, sizeof(tb), 1))
+ tp = tb;
+ errno = oerrno;
+ r = syslink(fb, tp);
+ }
+ return r;
+}
+
+#endif
+
+#if _win32_botch_open || _win32_botch_copy
+
+#if _win32_botch_copy
+
+/*
+ * this should intercept the important cases
+ * dup*() and exec*() fd's will not be intercepted
+ */
+
+typedef struct Exe_test_s
+{
+ int test;
+ ino_t ino;
+ char path[PATH_MAX];
+} Exe_test_t;
+
+static Exe_test_t* exe[16];
+
+extern int
+close(int fd)
+{
+ int r;
+ int oerrno;
+ struct stat st;
+ char buf[PATH_MAX];
+
+ if (fd >= 0 && fd < elementsof(exe) && exe[fd])
+ {
+ r = exe[fd]->test;
+ exe[fd]->test = 0;
+ if (r > 0 && !fstat(fd, &st) && st.st_ino == exe[fd]->ino)
+ {
+ if (r = sysclose(fd))
+ return r;
+ oerrno = errno;
+ if (!stat(exe[fd]->path, &st) && st.st_ino == exe[fd]->ino)
+ {
+ snprintf(buf, sizeof(buf), "%s.exe", exe[fd]->path);
+ sysrename(exe[fd]->path, buf);
+ }
+ errno = oerrno;
+ return 0;
+ }
+ }
+ return sysclose(fd);
+}
+
+extern ssize_t
+write(int fd, const void* buf, size_t n)
+{
+ if (fd >= 0 && fd < elementsof(exe) && exe[fd] && exe[fd]->test < 0)
+ exe[fd]->test = n >= 2 && ((unsigned char*)buf)[1] == 0x5a && (((unsigned char*)buf)[0] == 0x4c || ((unsigned char*)buf)[0] == 0x4d) && !lseek(fd, (off_t)0, SEEK_CUR);
+ return syswrite(fd, buf, n);
+}
+
+#endif
+
+extern int
+open(const char* path, int flags, ...)
+{
+ int fd;
+ int mode;
+ int oerrno;
+ char buf[PATH_MAX];
+#if _win32_botch_copy
+ struct stat st;
+#endif
+ va_list ap;
+
+ va_start(ap, flags);
+ mode = (flags & O_CREAT) ? va_arg(ap, int) : 0;
+ oerrno = errno;
+ fd = sysopen(path, flags, mode);
+#if _win32_botch_open
+ if (fd < 0 && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
+ {
+ errno = oerrno;
+ fd = sysopen(buf, flags, mode);
+ }
+#endif
+#if _win32_botch_copy
+ if (fd >= 0 && fd < elementsof(exe) && strlen(path) < PATH_MAX &&
+ (flags & (O_CREAT|O_TRUNC)) == (O_CREAT|O_TRUNC) && (mode & 0111))
+ {
+ if (!suffix(path) && !fstat(fd, &st) && (exe[fd] || (exe[fd] = (Exe_test_t*)malloc(sizeof(Exe_test_t)))))
+ {
+ exe[fd]->test = -1;
+ exe[fd]->ino = st.st_ino;
+ strcpy(exe[fd]->path, path);
+ }
+ errno = oerrno;
+ }
+#endif
+ va_end(ap);
+ return fd;
+}
+
+#endif
+
+#if _win32_botch_pathconf
+
+extern long
+pathconf(const char* path, int op)
+{
+ if (sysaccess(path, F_OK))
+ return -1;
+ return syspathconf(path, op);
+}
+
+#endif
+
+#if _win32_botch_rename
+
+extern int
+rename(const char* fp, const char* tp)
+{
+ int r;
+ int oerrno;
+ char fb[PATH_MAX];
+ char tb[PATH_MAX];
+
+ oerrno = errno;
+ if ((r = sysrename(fp, tp)) && errno == ENOENT && execrate(fp, fb, sizeof(fb), 1))
+ {
+ if (execrate(tp, tb, sizeof(tb), 1))
+ tp = tb;
+ errno = oerrno;
+ r = sysrename(fb, tp);
+ }
+ return r;
+}
+
+#endif
+
+#if _win32_botch_stat
+
+extern int
+stat(const char* path, struct stat* st)
+{
+ int r;
+ int oerrno;
+ char buf[PATH_MAX];
+
+ oerrno = errno;
+ if ((r = sysstat(path, st)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
+ {
+ errno = oerrno;
+ r = sysstat(buf, st);
+ }
+ return r;
+}
+
+#endif
+
+#if _win32_botch_truncate
+
+extern int
+truncate(const char* path, off_t offset)
+{
+ int r;
+ int oerrno;
+ char buf[PATH_MAX];
+
+ oerrno = errno;
+ if ((r = systruncate(path, offset)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
+ {
+ errno = oerrno;
+ r = systruncate(buf, offset);
+ }
+ return r;
+}
+
+#endif
+
+#if _win32_botch_unlink
+
+extern int
+unlink(const char* path)
+{
+ int r;
+ int drive;
+ int mask;
+ int suffix;
+ int stop;
+ int oerrno;
+ unsigned long base;
+ char buf[PATH_MAX];
+ char tmp[MAX_PATH];
+
+#define DELETED_DIR_1 7
+#define DELETED_DIR_2 16
+
+ static char deleted[] = "%c:\\temp\\.deleted\\%08x.%03x";
+
+ static int count = 0;
+
+#if __CYGWIN__
+
+ DWORD fattr = FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE;
+ DWORD share = FILE_SHARE_DELETE;
+ HANDLE hp;
+ struct stat st;
+ char nat[MAX_PATH];
+
+ oerrno = errno;
+ if (lstat(path, &st) || !S_ISREG(st.st_mode))
+ goto try_unlink;
+ cygwin_conv_to_full_win32_path(path, nat);
+ if (!strncasecmp(nat + 1, ":\\temp\\", 7))
+ goto try_unlink;
+ drive = nat[0];
+ path = (const char*)nat;
+ for (;;)
+ {
+ hp = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ if (hp != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(hp);
+ errno = oerrno;
+ return 0;
+ }
+ if (GetLastError() != ERROR_FILE_NOT_FOUND)
+ break;
+ if (path == (const char*)buf || !execrate(path, buf, sizeof(buf), 1))
+ {
+ errno = ENOENT;
+ return -1;
+ }
+ path = (const char*)buf;
+ }
+#else
+ if (sysaccess(path, 0))
+#if _win32_botch_access
+ {
+ if (errno != ENOENT || !execrate(path, buf, sizeof(buf), 1) || sysaccess(buf, 0))
+ return -1;
+ path = (const char*)buf;
+ }
+#else
+ return -1;
+#endif
+ drive = 'C':
+#endif
+
+ /*
+ * rename to a `deleted' path just in case the file is open
+ * otherwise directory readers may choke on phantom entries
+ */
+
+ base = ((getuid() & 0xffff) << 16) | (time(NiL) & 0xffff);
+ suffix = (getpid() & 0xfff) + count++;
+ snprintf(tmp, sizeof(tmp), deleted, drive, base, suffix);
+ if (!sysrename(path, tmp))
+ {
+ path = (const char*)tmp;
+ goto try_delete;
+ }
+ if (errno != ENOTDIR && errno != ENOENT)
+ goto try_unlink;
+ tmp[DELETED_DIR_2] = 0;
+ if (sysaccess(tmp, 0))
+ {
+ mask = umask(0);
+ tmp[DELETED_DIR_1] = 0;
+ if (sysaccess(tmp, 0) && mkdir(tmp, S_IRWXU|S_IRWXG|S_IRWXO))
+ {
+ umask(mask);
+ goto try_unlink;
+ }
+ tmp[DELETED_DIR_1] = '\\';
+ r = mkdir(tmp, S_IRWXU|S_IRWXG|S_IRWXO);
+ umask(mask);
+ if (r)
+ goto try_unlink;
+ errno = 0;
+ }
+ tmp[DELETED_DIR_2] = '\\';
+ if (!errno && !sysrename(path, tmp))
+ {
+ path = (const char*)tmp;
+ goto try_delete;
+ }
+#if !__CYGWIN__
+ if (errno == ENOENT)
+ {
+#if !_win32_botch_access
+ if (execrate(path, buf, sizeof(buf), 1) && !sysrename(buf, tmp))
+ path = (const char*)tmp;
+#endif
+ goto try_unlink;
+ }
+#endif
+ stop = suffix;
+ do
+ {
+ snprintf(tmp, sizeof(tmp), deleted, drive, base, suffix);
+ if (!sysrename(path, tmp))
+ {
+ path = (const char*)tmp;
+ goto try_delete;
+ }
+ if (++suffix > 0xfff)
+ suffix = 0;
+ } while (suffix != stop);
+ try_delete:
+#if __CYGWIN__
+ hp = CreateFile(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ if (hp != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(hp);
+ errno = oerrno;
+ return 0;
+ }
+#endif
+ try_unlink:
+ errno = oerrno;
+ return sysunlink(path);
+}
+
+#endif
+
+#if _win32_botch_utime
+
+#if __CYGWIN__
+
+/*
+ * cygwin refuses to set st_ctime for some operations
+ * this rejects that refusal
+ */
+
+static void
+ctime_now(const char* path)
+{
+ HANDLE hp;
+ SYSTEMTIME st;
+ FILETIME ct;
+ WIN32_FIND_DATA ff;
+ struct stat fs;
+ int oerrno;
+ char tmp[MAX_PATH];
+
+ if (sysstat(path, &fs) || (fs.st_mode & S_IWUSR) || syschmod(path, (fs.st_mode | S_IWUSR) & S_IPERM))
+ fs.st_mode = 0;
+ cygwin_conv_to_win32_path(path, tmp);
+ hp = CreateFile(tmp, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hp && hp != INVALID_HANDLE_VALUE)
+ {
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &ct);
+ SetFileTime(hp, &ct, 0, 0);
+ CloseHandle(hp);
+ }
+ if (fs.st_mode)
+ syschmod(path, fs.st_mode & S_IPERM);
+ errno = oerrno;
+}
+
+#else
+
+#define ctime_now(p)
+
+#endif
+
+extern int
+utimes(const char* path, const struct timeval* ut)
+{
+ int r;
+ int oerrno;
+ char buf[PATH_MAX];
+
+ oerrno = errno;
+ if ((r = sysutimes(path, ut)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
+ {
+ errno = oerrno;
+ r = sysutimes(path = buf, ut);
+ }
+ if (!r)
+ ctime_now(path);
+ return r;
+}
+
+extern int
+utime(const char* path, const struct utimbuf* ut)
+{
+ int r;
+ int oerrno;
+ char buf[PATH_MAX];
+
+ oerrno = errno;
+ if ((r = sysutime(path, ut)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
+ {
+ errno = oerrno;
+ r = sysutime(path = buf, ut);
+ }
+ if (!r)
+ ctime_now(path);
+ return r;
+}
+
+#endif
+
+#endif
+
+/*
+ * some systems (sun) miss a few functions required by their
+ * own bsd-like macros
+ */
+
+#if !_lib_bzero || defined(bzero)
+
+#undef bzero
+
+void
+bzero(void* b, size_t n)
+{
+ memset(b, 0, n);
+}
+
+#endif
+
+#if !_lib_getpagesize || defined(getpagesize)
+
+#ifndef OMITTED
+#define OMITTED 1
+#endif
+
+#undef getpagesize
+
+#ifdef _SC_PAGESIZE
+#undef _AST_PAGESIZE
+#define _AST_PAGESIZE (int)sysconf(_SC_PAGESIZE)
+#else
+#ifndef _AST_PAGESIZE
+#define _AST_PAGESIZE 4096
+#endif
+#endif
+
+int
+getpagesize()
+{
+ return _AST_PAGESIZE;
+}
+
+#endif
+
+#if __CYGWIN__ && defined(__IMPORT__) && defined(__EXPORT__)
+
+#ifndef OMITTED
+#define OMITTED 1
+#endif
+
+/*
+ * a few _imp__FUNCTION symbols are needed to avoid
+ * static link multiple definitions
+ */
+
+#ifndef strtod
+__EXPORT__ double (*_imp__strtod)(const char*, char**) = strtod;
+#endif
+
+#endif
+
+#ifndef OMITTED
+
+NoN(omitted)
+
+#endif
diff --git a/src/lib/libast/comp/open.c b/src/lib/libast/comp/open.c
new file mode 100644
index 0000000..6e2530f
--- /dev/null
+++ b/src/lib/libast/comp/open.c
@@ -0,0 +1,119 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * -last 3 arg open
+ */
+
+#include <ast.h>
+
+#if !defined(open) || !defined(_ast_O_LOCAL)
+
+NoN(open)
+
+#else
+
+#undef open
+
+extern int open(const char*, int, ...);
+
+#include <ls.h>
+#include <error.h>
+
+#ifdef O_NOCTTY
+#include <ast_tty.h>
+#endif
+
+int
+_ast_open(const char* path, int op, ...)
+{
+ int fd;
+ int mode;
+ int save_errno;
+ struct stat st;
+ va_list ap;
+
+ save_errno = errno;
+ va_start(ap, op);
+ mode = (op & O_CREAT) ? va_arg(ap, int) : S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
+ va_end(ap);
+ if (op & ~(_ast_O_LOCAL-1))
+ {
+ if (!(op & O_CREAT))
+ op &= ~O_EXCL;
+ for (;;)
+ {
+ if (op & O_TRUNC)
+ {
+ if ((op & O_EXCL) && !access(path, F_OK))
+ {
+ errno = EEXIST;
+ return(-1);
+ }
+ if ((fd = creat(path, (op & O_EXCL) ? 0 : mode)) < 0)
+ return(-1);
+ if (op & O_EXCL)
+ {
+ if (fstat(fd, &st) || (st.st_mode & S_IPERM))
+ {
+ errno = EEXIST;
+ close(fd);
+ return(-1);
+ }
+#if _lib_fchmod
+ if (mode && fchmod(fd, mode))
+#else
+ if (mode && chmod(path, mode))
+#endif
+ errno = save_errno;
+ }
+ if ((op & O_ACCMODE) == O_RDWR)
+ {
+ close(fd);
+ op &= ~(O_CREAT|O_TRUNC);
+ continue;
+ }
+ }
+ else if ((fd = open(path, op & (_ast_O_LOCAL-1), mode)) < 0)
+ {
+ if (op & O_CREAT)
+ {
+ op |= O_TRUNC;
+ continue;
+ }
+ return(-1);
+ }
+ else if ((op & O_APPEND) && lseek(fd, 0L, SEEK_END) == -1L)
+ errno = save_errno;
+#if O_NOCTTY
+ if ((op & O_NOCTTY) && ioctl(fd, TIOCNOTTY, 0))
+ errno = save_errno;
+#endif
+ break;
+ }
+ }
+ else fd = open(path, op, mode);
+ return(fd);
+}
+
+#endif
diff --git a/src/lib/libast/comp/openlog.c b/src/lib/libast/comp/openlog.c
new file mode 100644
index 0000000..518d441
--- /dev/null
+++ b/src/lib/libast/comp/openlog.c
@@ -0,0 +1,58 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * openlog implementation
+ */
+
+#include <ast.h>
+
+#if _lib_syslog
+
+NoN(openlog)
+
+#else
+
+#include "sysloglib.h"
+
+void
+openlog(const char* ident, int flags, int facility)
+{
+ int n;
+
+ if (ident)
+ {
+ n = strlen(ident);
+ if (n >= sizeof(log.ident))
+ n = sizeof(log.ident) - 1;
+ memcpy(log.ident, ident, n);
+ log.ident[n] = 0;
+ }
+ else
+ log.ident[0] = 0;
+ log.facility = facility;
+ log.flags = flags;
+ if (!(log.flags & LOG_ODELAY))
+ sendlog(NiL);
+}
+
+#endif
diff --git a/src/lib/libast/comp/putenv.c b/src/lib/libast/comp/putenv.c
new file mode 100644
index 0000000..72b0f61
--- /dev/null
+++ b/src/lib/libast/comp/putenv.c
@@ -0,0 +1,53 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#define putenv ______putenv
+
+#if _UWIN
+#define _STDLIB_H_ 1
+#endif
+
+#include <ast.h>
+
+#undef putenv
+
+#if _lib_putenv
+
+NoN(putenv)
+
+#else
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+putenv(const char* s)
+{
+ return setenviron(s) ? 0 : -1;
+}
+
+#endif
diff --git a/src/lib/libast/comp/re_comp.c b/src/lib/libast/comp/re_comp.c
new file mode 100644
index 0000000..ad31f24
--- /dev/null
+++ b/src/lib/libast/comp/re_comp.c
@@ -0,0 +1,81 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * re_comp implementation
+ */
+
+#include <ast.h>
+#include <re_comp.h>
+#include <regex.h>
+
+#undef error
+#undef valid
+
+static struct
+{
+ char error[64];
+ regex_t re;
+ int valid;
+} state;
+
+char*
+re_comp(const char* pattern)
+{
+ register int r;
+
+ if (!pattern || !*pattern)
+ {
+ if (state.valid)
+ return 0;
+ r = REG_BADPAT;
+ }
+ else
+ {
+ if (state.valid)
+ {
+ state.valid = 0;
+ regfree(&state.re);
+ }
+ if (!(r = regcomp(&state.re, pattern, REG_LENIENT|REG_NOSUB|REG_NULL)))
+ {
+ state.valid = 1;
+ return 0;
+ }
+ }
+ regerror(r, &state.re, state.error, sizeof(state.error));
+ return state.error;
+}
+
+int
+re_exec(const char* subject)
+{
+ if (state.valid && subject)
+ switch (regexec(&state.re, subject, 0, NiL, 0))
+ {
+ case 0:
+ return 1;
+ case REG_NOMATCH:
+ return 0;
+ }
+ return -1;
+}
diff --git a/src/lib/libast/comp/re_comp.h b/src/lib/libast/comp/re_comp.h
new file mode 100644
index 0000000..616fb4c
--- /dev/null
+++ b/src/lib/libast/comp/re_comp.h
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * re_comp interface definitions
+ *
+ * OBSOLETE: use <regex.h>
+ */
+
+#ifndef _RE_COMP_H
+#define _RE_COMP_H
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char* re_comp(const char*);
+extern int re_exec(const char*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/comp/readlink.c b/src/lib/libast/comp/readlink.c
new file mode 100644
index 0000000..df2129e
--- /dev/null
+++ b/src/lib/libast/comp/readlink.c
@@ -0,0 +1,61 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_readlink
+
+NoN(readlink)
+
+#else
+
+#include "fakelink.h"
+
+#include <error.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+int
+readlink(const char* path, char* buf, int siz)
+{
+ int fd;
+ int n;
+
+ if (siz > sizeof(FAKELINK_MAGIC))
+ {
+ if ((fd = open(path, O_RDONLY)) < 0)
+ return -1;
+ if (read(fd, buf, sizeof(FAKELINK_MAGIC)) == sizeof(FAKELINK_MAGIC) && !strcmp(buf, FAKELINK_MAGIC) && (n = read(fd, buf, siz)) > 0 && !buf[n - 1])
+ {
+ close(fd);
+ return n;
+ }
+ close(fd);
+ }
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif
diff --git a/src/lib/libast/comp/realpath.c b/src/lib/libast/comp/realpath.c
new file mode 100644
index 0000000..54c8703
--- /dev/null
+++ b/src/lib/libast/comp/realpath.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * realpath implementation
+ */
+
+#define realpath ______realpath
+#define resolvepath ______resolvepath
+
+#include <ast.h>
+
+#undef realpath
+#undef resolvepath
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+extern int resolvepath(const char*, char*, size_t);
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char*
+realpath(const char* file, char* path)
+{
+ return resolvepath(file, path, PATH_MAX) > 0 ? path : (char*)0;
+}
diff --git a/src/lib/libast/comp/regcmp.c b/src/lib/libast/comp/regcmp.c
new file mode 100644
index 0000000..ddf5498
--- /dev/null
+++ b/src/lib/libast/comp/regcmp.c
@@ -0,0 +1,224 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * regcmp implementation
+ */
+
+#include <ast.h>
+#include <libgen.h>
+#include <regex.h>
+#include <align.h>
+
+#define INC (2*1024)
+#define TOT (16*1024)
+#define SUB 10
+
+typedef struct
+{
+ char* cur;
+ regex_t re;
+ unsigned char sub[SUB];
+ int nsub;
+ size_t size;
+ char buf[ALIGN_BOUND2];
+} Regex_t;
+
+__DEFINE__(char*, __loc1, 0);
+
+static void*
+block(void* handle, void* data, size_t size)
+{
+ register Regex_t* re = (Regex_t*)handle;
+
+ if (data || (size = roundof(size, ALIGN_BOUND2)) > (re->buf + re->size - re->cur))
+ return 0;
+ data = (void*)re->cur;
+ re->cur += size;
+ return data;
+}
+
+char*
+regcmp(const char* pattern, ...)
+{
+ register char* s;
+ register Regex_t* re;
+ register size_t n;
+ register int c;
+ register int p;
+ int b;
+ int e;
+ int i;
+ int j;
+ int nsub;
+ register Sfio_t* sp;
+ unsigned char paren[128];
+ unsigned char sub[SUB];
+ va_list ap;
+
+ va_start(ap, pattern);
+ if (pattern || !*pattern || !(sp = sfstropen()))
+ e = 1;
+ else
+ {
+ e = 0;
+ memset(paren, 0, sizeof(paren));
+ n = 0;
+ p = -1;
+ b = 0;
+ nsub = 0;
+ s = (char*)pattern;
+ do
+ {
+ while (c = *s++)
+ {
+ if (c == '\\')
+ {
+ sfputc(sp, c);
+ if (!(c = *s++))
+ break;
+ }
+ else if (b)
+ {
+ if (c == ']')
+ b = 0;
+ }
+ else if (c == '[')
+ {
+ b = 1;
+ if (*s == '^')
+ {
+ sfputc(sp, c);
+ c = *s++;
+ }
+ if (*s == ']')
+ {
+ sfputc(sp, c);
+ c = *s++;
+ }
+ }
+ else if (c == '(')
+ {
+ /*
+ * someone explain in one sentence why
+ * a cast is needed to make this work
+ */
+
+ if (p < (int)(elementsof(paren) - 1))
+ p++;
+ paren[p] = ++n;
+ }
+ else if (c == ')' && p >= 0)
+ {
+ for (i = p; i > 0; i--)
+ if (paren[i])
+ break;
+ if (*s == '$' && (j = *(s + 1)) >= '0' && j <= '9')
+ {
+ s += 2;
+ j -= '0';
+ if (nsub <= j)
+ {
+ if (!nsub)
+ memset(sub, 0, sizeof(sub));
+ nsub = j + 1;
+ }
+ sub[j] = paren[i] + 1;
+ }
+ paren[i] = 0;
+ }
+ sfputc(sp, c);
+ }
+ } while (s = va_arg(ap, char*));
+ }
+ va_end(ap);
+ if (e)
+ return 0;
+ if (!(s = sfstruse(sp)))
+ {
+ sfstrclose(sp);
+ return 0;
+ }
+ re = 0;
+ n = 0;
+ do
+ {
+ if ((n += INC) > TOT || !(re = newof(re, Regex_t, 0, n)))
+ {
+ if (re)
+ free(re);
+ sfstrclose(sp);
+ return 0;
+ }
+ re->cur = re->buf;
+ re->size = n + ALIGN_BOUND2 - sizeof(Regex_t);
+ regalloc(re, block, REG_NOFREE);
+ c = regcomp(&re->re, s, REG_EXTENDED|REG_LENIENT|REG_NULL);
+ regalloc(NiL, NiL, 0);
+ } while (c == REG_ESPACE);
+ sfstrclose(sp);
+ if (c)
+ {
+ free(re);
+ return 0;
+ }
+ if (re->nsub = nsub)
+ memcpy(re->sub, sub, (nsub + 1) * sizeof(sub[0]));
+ return (char*)re;
+}
+
+char*
+regex(const char* handle, const char* subject, ...)
+{
+ register Regex_t* re;
+ register int n;
+ register int i;
+ register int k;
+ char* sub[SUB + 1];
+ regmatch_t match[SUB + 1];
+ va_list ap;
+
+ va_start(ap, subject);
+ if (!(re = (Regex_t*)handle) || !subject)
+ k = 1;
+ else
+ {
+ k = 0;
+ for (n = 0; n < re->nsub; n++)
+ sub[n] = va_arg(ap, char*);
+ }
+ va_end(ap);
+ if (k)
+ return 0;
+ if (regexec(&re->re, subject, SUB + 1, match, 0))
+ return 0;
+ for (n = 0; n < re->nsub; n++)
+ if (i = re->sub[n])
+ {
+ i--;
+ k = match[i].rm_eo - match[i].rm_so;
+ strlcpy(sub[n], subject + match[i].rm_so, k);
+ *(sub[n] + k) = 0;
+ }
+ __loc1 = (char*)subject + match[0].rm_so;
+ return (char*)subject + match[0].rm_eo;
+}
diff --git a/src/lib/libast/comp/regexp.c b/src/lib/libast/comp/regexp.c
new file mode 100644
index 0000000..d2e33a4
--- /dev/null
+++ b/src/lib/libast/comp/regexp.c
@@ -0,0 +1,123 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * <regexp.h> library support
+ */
+
+#define _REGEXP_DECLARE
+
+#include <ast.h>
+#include <regexp.h>
+#include <regex.h>
+#include <align.h>
+
+typedef struct
+{
+ regex_t re;
+ char* buf;
+ char* cur;
+ unsigned int size;
+} Env_t;
+
+static void*
+block(void* handle, void* data, size_t size)
+{
+ register Env_t* env = (Env_t*)handle;
+
+ if (data || (size = roundof(size, ALIGN_BOUND2)) > (env->buf + env->size - env->cur))
+ return 0;
+ data = (void*)env->cur;
+ env->cur += size;
+ return data;
+}
+
+int
+_re_comp(regexp_t* re, const char* pattern, char* handle, unsigned int size)
+{
+ register Env_t* env = (Env_t*)handle;
+ register int n;
+
+ if (size <= sizeof(Env_t))
+ return 50;
+ env->buf = env->cur = (char*)env + sizeof(Env_t);
+ env->size = size - sizeof(Env_t);
+ regalloc(env, block, REG_NOFREE);
+ n = regcomp(&env->re, pattern, REG_LENIENT|REG_NULL);
+ switch (n)
+ {
+ case 0:
+ break;
+ case REG_ERANGE:
+ n = 11;
+ break;
+ case REG_BADBR:
+ n = 16;
+ break;
+ case REG_ESUBREG:
+ n = 25;
+ break;
+ case REG_EPAREN:
+ n = 42;
+ break;
+ case REG_EBRACK:
+ n = 49;
+ break;
+ default:
+ n = 50;
+ break;
+ }
+ re->re_nbra = env->re.re_nsub;
+ return n;
+}
+
+int
+_re_exec(regexp_t* re, const char* subject, const char* handle, int anchor)
+{
+ register Env_t* env = (Env_t*)handle;
+ register int n;
+ regmatch_t match[elementsof(re->re_braslist)+1];
+
+ if (regexec(&env->re, subject, elementsof(match), match, 0) || anchor && match[0].rm_so)
+ return 0;
+ re->re_loc1 = (char*)subject + match[0].rm_so;
+ re->re_loc2 = (char*)subject + match[0].rm_eo;
+ for (n = 1; n <= env->re.re_nsub; n++)
+ {
+ re->re_braslist[n-1] = (char*)subject + match[n].rm_so;
+ re->re_braelist[n-1] = (char*)subject + match[n].rm_eo;
+ }
+ return 1;
+}
+
+char*
+_re_putc(int c)
+{
+ static Sfio_t* sp;
+
+ if (!sp && !(sp = sfstropen()))
+ return 0;
+ if (!c)
+ return sfstruse(sp);
+ sfputc(sp, c);
+ return 0;
+}
diff --git a/src/lib/libast/comp/regexp.h b/src/lib/libast/comp/regexp.h
new file mode 100644
index 0000000..93b7185
--- /dev/null
+++ b/src/lib/libast/comp/regexp.h
@@ -0,0 +1,129 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * regexp interface and partial implementation
+ * what a novel approach
+ * don't do it again
+ *
+ * OBSOLETE: use <regex.h>
+ */
+
+#ifndef _REGEXP_H
+#define _REGEXP_H
+
+#define NBRA 9
+
+typedef struct
+{
+ char* re_braslist[NBRA];
+ char* re_braelist[NBRA];
+ char* re_loc1;
+ char* re_loc2;
+ char* re_locs;
+ int re_circf;
+ int re_nbra;
+ int re_nodelim;
+ int re_sed;
+} regexp_t;
+
+#define braslist _re_info.re_braslist
+#define braelist _re_info.re_braelist
+#define circf _re_info.re_circf
+#define loc1 _re_info.re_loc1
+#define loc2 _re_info.re_loc2
+#define locs _re_info.re_locs
+#define nbra _re_info.re_nbra
+#define nodelim _re_info.re_nodelim
+#define sed _re_info.re_sed
+
+#define advance(a,b) _re_exec(&_re_info,a,b,1)
+#define compile(a,b,c,d) _re_read(&_re_info,a,b,c,d)
+#define step(a,b) _re_exec(&_re_info,a,b,0)
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int _re_comp(regexp_t*, const char*, char*, unsigned int);
+extern int _re_exec(regexp_t*, const char*, const char*, int);
+extern char* _re_putc(int);
+extern char* _re_read(regexp_t*, const char*, char*, const char*, int);
+
+#undef extern
+
+#ifndef _REGEXP_DECLARE
+
+regexp_t _re_info;
+
+char*
+_re_read(register regexp_t* re, const char* instring, char* ep, const char* endbuf, int seof)
+{
+ register int c;
+
+ static const char* prev;
+
+#ifdef INIT
+ INIT;
+#endif
+
+ re->re_nodelim = 0;
+ if ((c = GETC()) == seof || c == '\n' || c == -1 || c == 0)
+ {
+ if (c != seof)
+ {
+ UNGETC(c);
+ re->re_nodelim = 1;
+ }
+ if (!re->re_sed && !prev)
+ { ERROR(41); }
+ RETURN((char*)endbuf);
+ }
+ UNGETC(c);
+ prev = 0;
+ for (;;)
+ {
+ if ((c = GETC()) == seof || c == '\n' || c == -1 || c == 0)
+ {
+ if (re->re_sed)
+ { ERROR(36); }
+ UNGETC(c);
+ re->re_nodelim = 1;
+ break;
+ }
+ if (c == '\\')
+ {
+ _re_putc(c);
+ if ((c = GETC()) == seof || c == '\n' || c == -1 || c == 0)
+ { ERROR(36); }
+ }
+ _re_putc(c);
+ }
+ if (c = _re_comp(re, _re_putc(0), ep, (char*)endbuf - ep))
+ { ERROR(c); }
+ prev = endbuf;
+ RETURN((char*)prev);
+}
+
+#endif
+
+#endif
diff --git a/src/lib/libast/comp/remove.c b/src/lib/libast/comp/remove.c
new file mode 100644
index 0000000..32a8e32
--- /dev/null
+++ b/src/lib/libast/comp/remove.c
@@ -0,0 +1,49 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#define remove ______remove
+
+#include <ast.h>
+
+#undef remove
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#if _std_remove || !_lib_unlink
+
+NoN(remove)
+
+#else
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+remove(const char* path)
+{
+ return unlink(path);
+}
+
+#endif
diff --git a/src/lib/libast/comp/rename.c b/src/lib/libast/comp/rename.c
new file mode 100644
index 0000000..2ab3770
--- /dev/null
+++ b/src/lib/libast/comp/rename.c
@@ -0,0 +1,98 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_rename
+
+NoN(rename)
+
+#else
+
+#include <error.h>
+#include <proc.h>
+
+#ifdef EPERM
+
+static int
+mvdir(const char* from, const char* to)
+{
+ char* argv[4];
+ int oerrno;
+
+ static const char mvdir[] = "/usr/lib/mv_dir";
+
+ oerrno = errno;
+ if (!eaccess(mvdir, X_OK))
+ {
+ argv[0] = mvdir;
+ argv[1] = from;
+ argv[2] = to;
+ argv[3] = 0;
+ if (!procrun(argv[0], argv, 0))
+ {
+ errno = oerrno;
+ return 0;
+ }
+ }
+ errno = EPERM;
+ return -1;
+}
+
+#endif
+
+int
+rename(const char* from, const char* to)
+{
+ int oerrno;
+ int ooerrno;
+
+ ooerrno = errno;
+ while (link(from, to))
+ {
+#ifdef EPERM
+ if (errno == EPERM)
+ {
+ errno = ooerrno;
+ return mvdir(from, to);
+ }
+#endif
+ oerrno = errno;
+ if (unlink(to))
+ {
+#ifdef EPERM
+ if (errno == EPERM)
+ {
+ errno = ooerrno;
+ return mvdir(from, to);
+ }
+#endif
+ errno = oerrno;
+ return -1;
+ }
+ }
+ errno = ooerrno;
+ return unlink(from);
+}
+
+#endif
diff --git a/src/lib/libast/comp/resolvepath.c b/src/lib/libast/comp/resolvepath.c
new file mode 100644
index 0000000..a5cc4c9
--- /dev/null
+++ b/src/lib/libast/comp/resolvepath.c
@@ -0,0 +1,72 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * resolvepath implementation
+ */
+
+#define resolvepath ______resolvepath
+
+#include <ast.h>
+#include <error.h>
+
+#undef resolvepath
+
+#undef _def_map_ast
+#include <ast_map.h>
+#undef _AST_API_H
+#include <ast_api.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+resolvepath(const char* file, char* path, size_t size)
+{
+ register char* s;
+ register int n;
+ register int r;
+
+ r = *file != '/';
+ n = strlen(file) + r + 1;
+ if (n >= size)
+ {
+#ifdef ENAMETOOLONG
+ errno = ENAMETOOLONG;
+#else
+ errno = ENOMEM;
+#endif
+ return 0;
+ }
+ if (!r)
+ s = path;
+ else if (!getcwd(path, size - n))
+ return 0;
+ else
+ {
+ s = path + strlen(path);
+ *s++ = '/';
+ }
+ strlcpy(s, file, size - (s - path));
+ return (s = pathcanon(path, size, PATH_PHYSICAL|PATH_DOTDOT|PATH_EXISTS)) ? (s - path) : -1;
+}
diff --git a/src/lib/libast/comp/rmdir.c b/src/lib/libast/comp/rmdir.c
new file mode 100644
index 0000000..9b3270d
--- /dev/null
+++ b/src/lib/libast/comp/rmdir.c
@@ -0,0 +1,66 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_rmdir
+
+NoN(rmdir)
+
+#else
+
+#include <ls.h>
+#include <error.h>
+
+int
+rmdir(const char* path)
+{
+ register int n;
+ struct stat st;
+ char* av[3];
+
+ static char* cmd[] = { "/bin/rmdir", "/usr/5bin/rmdir", 0 };
+
+ if (stat(path, &st) < 0) return(-1);
+ if (!S_ISDIR(st.st_mode))
+ {
+ errno = ENOTDIR;
+ return(-1);
+ }
+ av[0] = "rmdir";
+ av[1] = path;
+ av[2] = 0;
+ for (n = 0; n < elementsof(cmd); n++)
+ if (procclose(procopen(cmd[n], av, NiL, NiL, 0)) != -1)
+ break;
+ n = errno;
+ if (access(path, F_OK) < 0)
+ {
+ errno = n;
+ return(0);
+ }
+ errno = EPERM;
+ return(-1);
+}
+
+#endif
diff --git a/src/lib/libast/comp/setenv.c b/src/lib/libast/comp/setenv.c
new file mode 100644
index 0000000..c2e3d65
--- /dev/null
+++ b/src/lib/libast/comp/setenv.c
@@ -0,0 +1,58 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#define setenv ______setenv
+
+#include <ast.h>
+
+#undef setenv
+#undef _lib_setenv /* procopen() calls setenv() */
+
+#if _lib_setenv
+
+NoN(setenv)
+
+#else
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+setenv(const char* name, const char* value, int overwrite)
+{
+ char* s;
+
+ if (overwrite || !getenv(name))
+ {
+ if (!(s = sfprints("%s=%s", name, value)) || !(s = strdup(s)))
+ return -1;
+ return setenviron(s) ? 0 : -1;
+ }
+ return 0;
+}
+
+#endif
diff --git a/src/lib/libast/comp/setlocale.c b/src/lib/libast/comp/setlocale.c
new file mode 100644
index 0000000..b2bc760
--- /dev/null
+++ b/src/lib/libast/comp/setlocale.c
@@ -0,0 +1,2865 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * setlocale() intercept
+ * maintains a bitmask of non-default categories
+ * and a permanent locale namespace for pointer comparison
+ * and persistent private data for locale related functions
+ */
+
+#include <ast_standards.h>
+
+#include "lclib.h"
+
+#include <ast_wchar.h>
+#include <ctype.h>
+#include <mc.h>
+#include <namval.h>
+
+#if ( _lib_wcwidth || _lib_wctomb ) && _hdr_wctype
+#include <wctype.h>
+#endif
+
+#if _lib_wcwidth
+#undef wcwidth
+#else
+#define wcwidth 0
+#endif
+
+#if _lib_wctomb
+#undef wctomb
+#else
+#define wctomb 0
+#endif
+
+#ifdef mblen
+#undef mblen
+extern int mblen(const char*, size_t);
+#endif
+
+#undef mbtowc
+#undef setlocale
+#undef strcmp
+#undef strcoll
+#undef strxfrm
+#undef valid
+
+#ifndef AST_LC_CANONICAL
+#define AST_LC_CANONICAL LC_abbreviated
+#endif
+
+static void
+header(void)
+{
+ static int done = 0;
+
+ if (!done)
+ {
+ done = 1;
+ sfprintf(sfstderr, "locale %17s %16s %16s %16s %s\n", "CATEGORY", "AST", "SYSTEM", "PREVIOUS", "ATTRIBUTES");
+ }
+}
+
+#if _UWIN
+
+#include <ast_windows.h>
+
+#undef _lib_setlocale
+#define _lib_setlocale 1
+
+#define setlocale(c,l) native_setlocale(c,l)
+
+extern char* uwin_setlocale(int, const char*);
+
+/*
+ * convert locale to native locale name in buf
+ */
+
+static char*
+native_locale(const char* locale, char* buf, size_t siz)
+{
+ Lc_t* lc;
+ const Lc_attribute_list_t* ap;
+ int i;
+ unsigned long lcid;
+ unsigned long lang;
+ unsigned long ctry;
+ char lbuf[128];
+ char cbuf[128];
+
+ if (locale && *locale)
+ {
+ if (!(lc = lcmake(locale)))
+ return 0;
+ lang = lc->language->index;
+ ctry = 0;
+ for (ap = lc->attributes; ap; ap = ap->next)
+ if (ctry = ap->attribute->index)
+ break;
+ if (!ctry)
+ {
+ for (i = 0; i < elementsof(lc->territory->languages); i++)
+ if (lc->territory->languages[i] == lc->language)
+ {
+ ctry = lc->territory->indices[i];
+ break;
+ }
+ if (!ctry)
+ {
+ if (!lang)
+ return 0;
+ ctry = SUBLANG_DEFAULT;
+ }
+ }
+ lcid = MAKELCID(MAKELANGID(lang, ctry), SORT_DEFAULT);
+ }
+ else
+ lcid = GetUserDefaultLCID();
+ if (GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, lbuf, sizeof(lbuf)) <= 0 ||
+ GetLocaleInfo(lcid, LOCALE_SENGCOUNTRY, cbuf, sizeof(cbuf)) <= 0)
+ return 0;
+ if (lc->charset->ms)
+ sfsprintf(buf, siz, "%s_%s.%s", lbuf, cbuf, lc->charset->ms);
+ else
+ sfsprintf(buf, siz, "%s_%s", lbuf, cbuf);
+ return buf;
+}
+
+/*
+ * locale!=0 here
+ */
+
+static char*
+native_setlocale(int category, const char* locale)
+{
+ char* usr;
+ char* sys;
+ char buf[256];
+
+ if (!(usr = native_locale(locale, buf, sizeof(buf))))
+ return 0;
+
+ /*
+ * win32 doesn't have LC_MESSAGES
+ */
+
+ if (category == LC_MESSAGES)
+ return (char*)locale;
+ sys = uwin_setlocale(category, usr);
+ if (ast.locale.set & AST_LC_debug)
+ sfprintf(sfstderr, "locale uwin %17s %-24s %-24s\n", lc_categories[lcindex(category, 0)].name, usr, sys);
+ return sys;
+}
+
+#else
+
+#define native_locale(a,b,c) ((char*)0)
+
+#endif
+
+/*
+ * LC_COLLATE and LC_CTYPE native support
+ */
+
+#if !_lib_mbtowc || MB_LEN_MAX <= 1
+#define mblen 0
+#define mbtowc 0
+#endif
+
+#if !_lib_strcoll
+#define strcoll 0
+#endif
+
+#if !_lib_strxfrm
+#define strxfrm 0
+#endif
+
+/*
+ * LC_COLLATE and LC_CTYPE debug support
+ *
+ * mutibyte debug encoding
+ *
+ * DL0 [ '0' .. '4' ] c1 ... c4 DR0
+ * DL1 [ '0' .. '4' ] c1 ... c4 DR1
+ *
+ * with these ligatures
+ *
+ * ch CH sst SST
+ *
+ * and private collation order
+ *
+ * wide character display width is the low order 3 bits
+ * wctomb() uses DL1...DR1
+ */
+
+#define DEBUG_MB_CUR_MAX 7
+
+#if DEBUG_MB_CUR_MAX < MB_LEN_MAX
+#undef DEBUG_MB_CUR_MAX
+#define DEBUG_MB_CUR_MAX MB_LEN_MAX
+#endif
+
+#define DL0 '<'
+#define DL1 0xab /* 8-bit mini << on xterm */
+#define DR0 '>'
+#define DR1 0xbb /* 8-bit mini >> on xterm */
+
+#define DB ((int)sizeof(wchar_t)*8-1)
+#define DC 7 /* wchar_t embedded char bits */
+#define DX (DB/DC) /* wchar_t max embedded chars */
+#define DZ (DB-DX*DC+1) /* wchar_t embedded size bits */
+#define DD 3 /* # mb delimiter chars <n...> */
+
+static unsigned char debug_order[] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 99, 100, 101, 102, 98, 103, 104, 105,
+ 106, 107, 108, 43, 109, 44, 42, 110,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 111, 112, 113, 114, 115, 116,
+ 117, 71, 72, 73, 74, 75, 76, 77,
+ 78, 79, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 118, 119, 120, 121, 97,
+ 122, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255,
+};
+
+static int
+debug_mbtowc(register wchar_t* p, register const char* s, size_t n)
+{
+ register const char* q;
+ register const char* r;
+ register int w;
+ register int dr;
+ wchar_t c;
+
+ if (n < 1)
+ return -1;
+ if (!s || !*s)
+ return 0;
+ switch (((unsigned char*)s)[0])
+ {
+ case DL0:
+ dr = DR0;
+ break;
+ case DL1:
+ dr = DR1;
+ break;
+ default:
+ single:
+ if (p)
+ *p = ((unsigned char*)s)[0] & ((1<<DC)-1);
+ return 1;
+ }
+ if (n < 2)
+ return -1;
+ if ((w = ((unsigned char*)s)[1]) < '0' || w > ('0' + DX))
+ goto single;
+ if ((w -= '0' - DD) > n)
+ return -1;
+ r = s + w - 1;
+ q = s += 2;
+ while (q < r && *q)
+ q++;
+ if (q != r || *((unsigned char*)q) != dr)
+ return -1;
+ if (p)
+ {
+ c = 1;
+ while (--q >= s)
+ {
+ c <<= DC;
+ c |= *((unsigned char*)q);
+ }
+ c <<= DZ;
+ c |= (w - DD);
+ *p = c;
+ }
+ return w;
+}
+
+static int
+debug_wctomb(char* s, wchar_t c)
+{
+ int w;
+ int i;
+ int k;
+
+ w = 0;
+ if (c >= 0 && c <= UCHAR_MAX)
+ {
+ w++;
+ if (s)
+ *s = c;
+ }
+ else if ((i = c & ((1<<DZ)-1)) > DX)
+ return -1;
+ else
+ {
+ w++;
+ if (s)
+ *s++ = DL0;
+ c >>= DZ;
+ w++;
+ if (s)
+ *s++ = i + '0';
+ while (i--)
+ {
+ w++;
+ if (s)
+ *s++ = (k = c & ((1<<DC)-1)) ? k : '?';
+ c >>= DC;
+ }
+ w++;
+ if (s)
+ *s++ = DR0;
+ }
+ return w;
+}
+
+static int
+debug_mblen(const char* s, size_t n)
+{
+ return debug_mbtowc(NiL, s, n);
+}
+
+static int
+debug_wcwidth(wchar_t c)
+{
+ if (c >= 0 && c <= UCHAR_MAX)
+ return 1;
+ if ((c &= ((1<<DZ)-1)) > DX)
+ return -1;
+ return c + DD;
+}
+
+static int
+debug_alpha(wchar_t c)
+{
+ return isalpha((c >> DZ) & ((1<<DC)-1));
+}
+
+static size_t
+debug_strxfrm(register char* t, register const char* s, size_t n)
+{
+ register const char* q;
+ register const char* r;
+ register char* e;
+ char* o;
+ register size_t z;
+ register int w;
+
+ o = t;
+ z = 0;
+ if (e = t)
+ e += n;
+ while (s[0])
+ {
+ if ((((unsigned char*)s)[0] == DL0 || ((unsigned char*)s)[0] == DL1) && (w = s[1]) >= '0' && w <= ('0' + DC))
+ {
+ w -= '0';
+ q = s + 2;
+ r = q + w;
+ while (q < r && *q)
+ q++;
+ if (*((unsigned char*)q) == DR0 || *((unsigned char*)q) == DR1)
+ {
+ if (t)
+ {
+ for (q = s + 2; q < r; q++)
+ if (t < e)
+ *t++ = debug_order[*q];
+ while (w++ < DX)
+ if (t < e)
+ *t++ = 1;
+ }
+ s = r + 1;
+ z += DX;
+ continue;
+ }
+ }
+ if ((s[0] == 'c' || s[0] == 'C') && (s[1] == 'h' || s[1] == 'H'))
+ {
+ if (t)
+ {
+ if (t < e)
+ *t++ = debug_order[s[0]];
+ if (t < e)
+ *t++ = debug_order[s[1]];
+ if (t < e)
+ *t++ = 1;
+ if (t < e)
+ *t++ = 1;
+ }
+ s += 2;
+ z += DX;
+ continue;
+ }
+ if ((s[0] == 's' || s[0] == 'S') && (s[1] == 's' || s[1] == 'S') && (s[2] == 't' || s[2] == 'T'))
+ {
+ if (t)
+ {
+ if (t < e)
+ *t++ = debug_order[s[0]];
+ if (t < e)
+ *t++ = debug_order[s[1]];
+ if (t < e)
+ *t++ = debug_order[s[2]];
+ if (t < e)
+ *t++ = 1;
+ }
+ s += 3;
+ z += DX;
+ continue;
+ }
+ if (t)
+ {
+ if (t < e)
+ *t++ = debug_order[s[0]];
+ if (t < e)
+ *t++ = 1;
+ if (t < e)
+ *t++ = 1;
+ if (t < e)
+ *t++ = 1;
+ }
+ s++;
+ z += DX;
+ }
+ if (!t)
+ return z;
+ if (t < e)
+ *t = 0;
+ return t - o;
+}
+
+static int
+debug_strcoll(const char* a, const char* b)
+{
+ char ab[1024];
+ char bb[1024];
+
+ debug_strxfrm(ab, a, sizeof(ab) - 1);
+ ab[sizeof(ab)-1] = 0;
+ debug_strxfrm(bb, b, sizeof(bb) - 1);
+ bb[sizeof(bb)-1] = 0;
+ return strcmp(ab, bb);
+}
+
+/*
+ * default locale
+ */
+
+static int
+default_wcwidth(wchar_t w)
+{
+ return w >= 0 && w <= 255 && !iscntrl(w) ? 1 : -1;
+}
+
+/*
+ * called when LC_COLLATE initialized or changes
+ */
+
+static int
+set_collate(Lc_category_t* cp)
+{
+ if (locales[cp->internal]->flags & LC_debug)
+ {
+ ast.collate = debug_strcoll;
+ ast.mb_xfrm = debug_strxfrm;
+ }
+ else if (locales[cp->internal]->flags & LC_default)
+ {
+ ast.collate = strcmp;
+ ast.mb_xfrm = 0;
+ }
+ else
+ {
+ ast.collate = strcoll;
+ ast.mb_xfrm = strxfrm;
+ }
+ return 0;
+}
+
+/*
+ * workaround the interesting sjis that translates unshifted 7 bit ascii!
+ */
+
+#if _hdr_wchar && _typ_mbstate_t && _lib_mbrtowc
+
+#define mb_state_zero ((mbstate_t*)&ast.pad[sizeof(ast.pad)-2*sizeof(mbstate_t)])
+#define mb_state ((mbstate_t*)&ast.pad[sizeof(ast.pad)-sizeof(mbstate_t)])
+
+static int
+sjis_mbtowc(register wchar_t* p, register const char* s, size_t n)
+{
+ if (n && p && s && (*s == '\\' || *s == '~') && !memcmp(mb_state, mb_state_zero, sizeof(mbstate_t)))
+ {
+ *p = *s;
+ return 1;
+ }
+ return mbrtowc(p, s, n, mb_state);
+}
+
+#endif
+
+#if 0
+
+#define utf8_wctomb wctomb
+
+#else
+
+static int
+utf8_wctomb(char* u, wchar_t w)
+{
+ if (!u)
+ return 0;
+ if (w >= (1<<11))
+ {
+ *u++ = 0xe0|(w>>12);
+ *u++ = 0x80|((w>>6)&0x3f);
+ *u++ = 0x80|(w&0x3f);
+ return 3;
+ }
+ if (w >= (1<<7))
+ {
+ *u++ = 0xc0|(w>>6);
+ *u++ = 0x80|(w&0x3f);
+ return 2;
+ }
+ *u++ = w;
+ return 1;
+}
+
+#endif
+
+static const uint32_t utf8mask[] =
+{
+ 0x00000000,
+ 0x00000000,
+ 0xffffff80,
+ 0xfffff800,
+ 0xffff0000,
+ 0xffe00000,
+ 0xfc000000,
+};
+
+static const signed char utf8tab[256] =
+{
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6,-1,-1,
+};
+
+static int
+utf8_mbtowc(wchar_t* wp, const char* str, size_t n)
+{
+ register unsigned char* sp = (unsigned char*)str;
+ register int m;
+ register int i;
+ register int c;
+ register wchar_t w = 0;
+
+ if (!sp || !n)
+ return 0;
+ if ((m = utf8tab[*sp]) > 0)
+ {
+ if (m > n)
+ return -1;
+ if (wp)
+ {
+ if (m == 1)
+ {
+ *wp = *sp;
+ return 1;
+ }
+ w = *sp & ((1<<(8-m))-1);
+ for (i = m - 1; i > 0; i--)
+ {
+ c = *++sp;
+ if ((c&0xc0) != 0x80)
+ goto invalid;
+ w = (w<<6) | (c&0x3f);
+ }
+ if (!(utf8mask[m] & w) || w >= 0xd800 && (w <= 0xdfff || w >= 0xfffe && w <= 0xffff))
+ goto invalid;
+ *wp = w;
+ }
+ return m;
+ }
+ if (!*sp)
+ return 0;
+ invalid:
+#ifdef EILSEQ
+ errno = EILSEQ;
+#endif
+ ast.mb_sync = (const char*)sp - str;
+ return -1;
+}
+
+static int
+utf8_mblen(const char* str, size_t n)
+{
+ wchar_t w;
+
+ return utf8_mbtowc(&w, str, n);
+}
+
+static const unsigned char utf8_wcw[] =
+{
+ 0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xd5,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x5d,0x55,0x55,0x55,0x55,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xf5,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xd5,0xff,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xf5,0xdf,0xdf,
+ 0xff,0x55,0xd5,0x5d,0x55,0x55,0x55,0x55,0x75,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0xd5,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xd5,0xff,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x15,0xc0,0x50,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0xd5,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xf5,0xf5,0xff,
+ 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x57,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0xd5,0x57,0x55,0x57,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0xd7,0xff,0x03,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x30,0x10,
+ 0x41,0xfc,0xff,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0xd5,0xff,0x55,0xfd,0xff,0xff,
+ 0xff,0xff,0xff,0xfd,0xff,0xff,0x7f,0x7f,0x57,0x55,0x55,0x55,0x55,0x55,0xd5,0xff,
+ 0x55,0x55,0x15,0x00,0x00,0xf0,0xff,0xff,0x55,0x55,0x55,0x55,0x54,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x05,0x00,0x00,0x00,0x14,0x04,0xf0,0x55,0x55,0x55,0xd5,
+ 0x55,0x55,0x55,0x35,0x51,0x55,0x55,0x55,0x55,0x55,0x55,0xfd,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x05,0x00,0x00,0xf4,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x43,0x57,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xf5,0x54,
+ 0x01,0x00,0x54,0xf1,0x01,0xfc,0x55,0x55,0x05,0x55,0x55,0x55,0xfd,0xff,0xff,0xff,
+ 0x53,0x57,0x55,0x7d,0x7d,0x55,0x55,0x55,0x55,0x55,0x5d,0x55,0xdd,0x5f,0xf5,0x5c,
+ 0x01,0x7c,0x7d,0xf1,0xff,0x7f,0xff,0x75,0x05,0x5f,0x55,0x55,0x55,0x55,0xd5,0xff,
+ 0xcf,0x57,0xd5,0x7f,0x7d,0x55,0x55,0x55,0x55,0x55,0x5d,0x55,0x5d,0xd7,0xf5,0x5c,
+ 0xc1,0x3f,0x3c,0xf0,0xff,0xff,0x57,0xdd,0xff,0x5f,0x55,0x55,0x50,0xfd,0xff,0xff,
+ 0x43,0x57,0x55,0x77,0x75,0x55,0x55,0x55,0x55,0x55,0x5d,0x55,0x5d,0x57,0xf5,0x54,
+ 0x01,0x30,0x74,0xf1,0xfd,0xff,0xff,0xff,0xfd,0x5f,0x55,0x55,0xff,0xff,0xff,0xff,
+ 0x53,0x57,0x55,0x7d,0x7d,0x55,0x55,0x55,0x55,0x55,0x5d,0x55,0x5d,0x5f,0xf5,0x14,
+ 0x01,0x7f,0x7d,0xf1,0xff,0x4f,0xff,0x75,0xf5,0x5f,0x55,0x55,0xfd,0xff,0xff,0xff,
+ 0x4f,0x57,0xd5,0x5f,0x5d,0xf5,0xd7,0x5d,0x7f,0xfd,0xd5,0x5f,0x55,0x75,0xf5,0x5f,
+ 0xd4,0x5f,0x5d,0xf1,0xff,0x7f,0xff,0xff,0xff,0x7f,0x55,0x55,0xd5,0xff,0xff,0xff,
+ 0x57,0x57,0x55,0x5d,0x5d,0x55,0x55,0x55,0x55,0x55,0x5d,0x55,0x55,0x57,0xf5,0x0f,
+ 0x54,0x0d,0x0c,0xf0,0xff,0xc3,0xff,0xff,0xf5,0x5f,0x55,0x55,0xff,0xff,0xff,0xff,
+ 0x5f,0x57,0x55,0x5d,0x5d,0x55,0x55,0x55,0x55,0x55,0x5d,0x55,0x55,0x57,0xf5,0x1f,
+ 0x55,0x4d,0x5d,0xf0,0xff,0xd7,0xff,0xdf,0xf5,0x5f,0x55,0x55,0xff,0xff,0xff,0xff,
+ 0x5f,0x57,0x55,0x5d,0x5d,0x55,0x55,0x55,0x55,0x55,0x5d,0x55,0x55,0x55,0xf5,0x5f,
+ 0x01,0x5f,0x5d,0xf1,0xff,0x7f,0xff,0xff,0xf5,0x5f,0x55,0x55,0xff,0xff,0xff,0xff,
+ 0x5f,0x57,0x55,0x55,0x55,0xd5,0x5f,0x55,0x55,0x55,0x55,0x55,0x75,0x55,0x55,0xf7,
+ 0x55,0xd5,0xcf,0x7f,0x05,0xcc,0x55,0x55,0xff,0xff,0xff,0xff,0x5f,0xfd,0xff,0xff,
+ 0x57,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x51,0x00,0xc0,0x7f,
+ 0x55,0x15,0x00,0x40,0x55,0x55,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xd7,0x7d,0xdd,0xf7,0xff,0x55,0x57,0x55,0x57,0x77,0x5f,0x57,0x51,0x00,0x30,0xf4,
+ 0x55,0xdd,0x00,0xf0,0x55,0x55,0xf5,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x50,0x55,0x55,0x55,0x55,0x55,0x55,0x11,0x51,0x55,
+ 0x55,0x55,0x57,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xd5,0xff,0x03,0x00,0x00,0x40,
+ 0x00,0x04,0x55,0xff,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,
+ 0x55,0x45,0x55,0x7d,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x75,0x55,0xd7,0x01,0xc4,0x0f,0xf1,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0xf5,0xff,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x7d,0xff,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xfa,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,
+ 0x55,0xd5,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0xd5,0x5d,0xf5,0x55,0xd5,0x5d,0xf5,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0xd5,0x5d,0xf5,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xd5,0x5d,0xf5,0x55,0xd5,
+ 0x5d,0xf5,0x55,0xd5,0x55,0xd5,0x55,0x55,0x55,0x55,0x55,0xd5,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0xd5,0x5d,0xf5,0x55,0xd5,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0xd5,0x55,0x55,0x55,0x55,0xd5,0xff,0x57,0x55,0x55,0x55,0x55,0x55,0x55,0xfd,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xfd,0xff,0xff,
+ 0x57,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xd5,0xff,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xfd,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xfd,0xff,0xff,0xff,
+ 0x55,0x55,0x55,0x5d,0x05,0xfc,0xff,0xff,0x55,0x55,0x55,0x55,0x05,0xd4,0xff,0xff,
+ 0x55,0x55,0x55,0x55,0x05,0xff,0xff,0xff,0x55,0x55,0x55,0x5d,0x0d,0xff,0xff,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x15,0x00,0x50,
+ 0x55,0x45,0x01,0x00,0x00,0x55,0x55,0xfd,0x55,0x55,0xf5,0xff,0xff,0xff,0xff,0xff,
+ 0x55,0x55,0x15,0xc0,0x55,0x55,0xf5,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xff,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xf1,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xf5,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0xf5,0x55,0xf5,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0xf5,0x55,0xf5,0x55,0x55,0x77,0x77,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xf5,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x5d,0x55,0x55,
+ 0x55,0x5d,0x55,0x55,0x55,0x5f,0x55,0x57,0x55,0x55,0x55,0x55,0x5f,0x5d,0x55,0xd5,
+ 0x55,0x55,0x15,0x00,0x55,0x55,0x55,0x55,0x55,0x55,0x0f,0x40,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0xd5,0x7f,0xff,0x7f,0x00,0xff,0x0f,0x00,0xf5,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0xd5,0xff,0xff,0xff,0xff,0x55,0x55,0x55,0x55,0xf5,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0xff,0xff,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xd5,0x57,
+ 0x55,0x55,0x55,0xff,0x7f,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0xff,0xff,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x69,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0xd5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xd5,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x55,0x55,0xd5,0xff,0xff,0xff,0xff,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xd5,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x5f,0x57,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xf5,
+ 0x55,0x55,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x57,0x5d,0xf5,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x57,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x77,0xd5,0xdf,0x55,0xd5,0x57,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0xfd,0x55,0x55,0x55,0x55,0x55,0x55,0x57,0x55,0x55,0xd5,
+ 0xff,0xff,0xff,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xff,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xba,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xff,0xff,0xff,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xaa,0xaa,0xaa,0xff,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0x0a,0x00,0xaa,0xaa,0xaa,0x6a,
+ 0xab,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xea,0x83,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xff,0xab,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xfe,0xab,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xea,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xfe,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xff,0xff,0xff,0xab,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xbf,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xff,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xea,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xea,0xbf,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xfa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xea,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xfa,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xfe,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xea,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x00,0x00,0x00,0x00,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xfa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xea,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x55,0xd5,0xff,0xff,0x7f,0x55,0xff,0x47,0x55,0x55,0x55,0x55,0x55,0xd5,0x55,0xdd,
+ 0x75,0x5d,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xf5,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0xff,0xff,0xff,0xff,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x5f,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0x55,0x55,0xfd,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xea,0xab,0xaa,0xea,0xaa,0xaa,0xaa,0xaa,0xea,0xaa,0xff,0x55,0x5d,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x3d,
+ 0xab,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
+ 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0x56,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
+ 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xd5,
+ 0x5f,0x55,0x5f,0x55,0x5f,0x55,0x5f,0xfd,0xaa,0xea,0x55,0xd5,0xff,0xff,0x03,0xf5
+};
+
+static int
+utf8_wcwidth(wchar_t c)
+{
+ int n;
+
+ return (n = (utf8_wcw[(c >> 2) & 0x3fff] >> ((c & 0x3) << 1)) & 0x3) == 3 ? -1 : n;
+}
+
+static const unsigned char utf8_wam[] =
+{
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,0xfe,0xff,0xff,0x07,
+ 0x00,0x00,0x00,0x00,0x00,0x04,0x20,0x04,0xff,0xff,0x7f,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xfd,0xff,0x0f,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x3f,0xff,0xf9,0x03,0x00,0x03,0x00,0x1f,0x40,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
+ 0x40,0xd7,0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x3f,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x03,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x3f,0x03,
+ 0xff,0xff,0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x7f,0x02,0xfe,0xff,0xff,0xff,
+ 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x07,0x07,0x00,
+ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,0xff,0x07,0x00,0x00,0xff,0xc3,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2f,0x00,0x60,0x00,0xff,0x1f,
+ 0x00,0x00,0xfd,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0x3f,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x23,0x00,0x00,0x01,0xff,0xc3,0xff,0x00,0x00,
+ 0xe0,0x9f,0xf9,0xff,0xff,0xfd,0xc5,0x03,0x00,0x00,0x00,0xb0,0xc3,0xff,0x03,0x00,
+ 0xe0,0x87,0xf9,0xff,0xff,0xfd,0x6d,0x03,0x00,0x00,0x00,0x5e,0xc0,0xff,0x1c,0x00,
+ 0xe0,0xaf,0xfb,0xff,0xff,0xfd,0xed,0x23,0x00,0x00,0x01,0x00,0xc1,0xff,0x00,0x00,
+ 0xe0,0x9f,0xf9,0xff,0xff,0xfd,0xcd,0x23,0x00,0x00,0x00,0xb0,0xc3,0xff,0x00,0x00,
+ 0xe8,0xc7,0x3d,0xd6,0x18,0xc7,0xbf,0x03,0x00,0x00,0x00,0x00,0x80,0xff,0x00,0x00,
+ 0xe0,0xdf,0xfd,0xff,0xff,0xfd,0xef,0x03,0x00,0x00,0x00,0x00,0xc3,0xff,0x00,0x00,
+ 0xe0,0xdf,0xfd,0xff,0xff,0xfd,0xef,0x03,0x00,0x00,0x00,0x40,0xc3,0xff,0x00,0x00,
+ 0xe0,0xdf,0xfd,0xff,0xff,0xfd,0xff,0x03,0x00,0x00,0x00,0x00,0xc3,0xff,0x00,0x00,
+ 0xe0,0xff,0x7f,0xfc,0xff,0xff,0xfb,0x2f,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xfe,0xff,0xff,0xff,0xff,0x7f,0xff,0x07,0xbf,0x7f,0xff,0x03,0x00,0x00,0x00,0x00,
+ 0x96,0x25,0xf0,0xfe,0xae,0xec,0x0d,0x20,0x5f,0x00,0xff,0x33,0x00,0x00,0x00,0x00,
+ 0x01,0x00,0x00,0x00,0xff,0x03,0x00,0x00,0xff,0xfe,0xff,0xff,0xff,0x07,0x00,0x00,
+ 0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xfb,0x06,0x00,0x00,0xff,0x03,0x3f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,0x01,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x83,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,
+ 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x3d,0x7f,0x3d,0xff,0xff,0xff,0xff,
+ 0x7f,0x3d,0xff,0xff,0xff,0x7f,0x3d,0x7f,0x3d,0x7f,0x7f,0xff,0xff,0x7f,0xff,0xff,
+ 0xff,0x7f,0x3d,0x7f,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0x07,0x00,0xfe,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0x00,
+ 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x9f,0x7f,0x00,
+ 0xfe,0xff,0xff,0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc7,0x01,0x00,
+ 0xff,0xdf,0x03,0x00,0xff,0xff,0x03,0x00,0xff,0xff,0x03,0x00,0xff,0xdf,0x01,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x80,0x10,0xff,0x03,0x00,0x00,
+ 0x00,0x00,0xff,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,
+ 0xff,0xff,0x3f,0x3f,0xff,0xff,0xff,0xff,0x3f,0x3f,0xff,0xaa,0xff,0xff,0xff,0x3f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0x5f,0xdc,0x1f,0xcf,0x0f,0xff,0x1f,0xdc,0x1f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x80,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x84,0xfc,0x2f,0x3e,0x50,0xbf,0xfb,0xe3,0xe0,0x03,0x00,0x00,0xff,0xff,0xff,0xff,
+ 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe0,0x00,0x00,0x00,0xfe,0x03,0x3e,0x1f,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0xe0,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf7,
+ 0xe0,0xff,0xff,0xff,0xff,0x1f,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x7f,0x00,0xf8,0xa0,0xff,0xfd,0x7f,0x5f,0xdb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x0f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdf,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+ 0x00,0x00,0xff,0x03,0xfe,0xff,0xff,0x07,0xfe,0xff,0xff,0x07,0xc0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xfc,0xfc,0xfc,0x1c,0x00,0x00,0x00,0x00
+};
+
+static int
+utf8_alpha(wchar_t c)
+{
+ return !!(utf8_wam[(c >> 3) & 0x1fff] & (1 << (c & 0x7)));
+}
+
+#if !_hdr_wchar || !_lib_wctype || !_lib_iswctype
+#undef iswalpha
+#define iswalpha default_iswalpha
+static int
+iswalpha(wchar_t c)
+{
+ return c <= 0x7f ? isalpha(c) : 0;
+}
+#endif
+
+typedef int (*Isw_f)(wchar_t);
+
+/*
+ * called when LC_CTYPE initialized or changes
+ */
+
+static int
+set_ctype(Lc_category_t* cp)
+{
+ ast.mb_sync = 0;
+ ast.mb_alpha = (Isw_f)iswalpha;
+#if AHA
+ if ((ast.locale.set & (AST_LC_debug|AST_LC_setlocale)) && !(ast.locale.set & AST_LC_internal))
+ sfprintf(sfstderr, "locale setf %17s %16s\n", cp->name, locales[cp->internal]->name);
+#endif
+ if (locales[cp->internal]->flags & LC_debug)
+ {
+ ast.mb_cur_max = DEBUG_MB_CUR_MAX;
+ ast.mb_len = debug_mblen;
+ ast.mb_towc = debug_mbtowc;
+ ast.mb_width = debug_wcwidth;
+ ast.mb_conv = debug_wctomb;
+ ast.mb_alpha = debug_alpha;
+ }
+ else if ((locales[cp->internal]->flags & LC_utf8) && !(ast.locale.set & AST_LC_test))
+ {
+ ast.mb_cur_max = 6;
+ ast.mb_len = utf8_mblen;
+ ast.mb_towc = utf8_mbtowc;
+ if ((locales[cp->internal]->flags & LC_local) || !(ast.mb_width = wcwidth))
+ ast.mb_width = utf8_wcwidth;
+ ast.mb_conv = utf8_wctomb;
+ ast.mb_alpha = utf8_alpha;
+ }
+ else if ((locales[cp->internal]->flags & LC_default) || (ast.mb_cur_max = MB_CUR_MAX) <= 1 || !(ast.mb_len = mblen) || !(ast.mb_towc = mbtowc))
+ {
+ ast.mb_cur_max = 1;
+ ast.mb_len = 0;
+ ast.mb_towc = 0;
+ ast.mb_width = default_wcwidth;
+ ast.mb_conv = 0;
+ }
+ else
+ {
+ if (!(ast.mb_width = wcwidth))
+ ast.mb_width = default_wcwidth;
+ ast.mb_conv = wctomb;
+#ifdef mb_state
+ {
+ /*
+ * check for sjis that translates unshifted 7 bit ascii!
+ */
+
+ char* s;
+ char buf[2];
+
+ mbinit();
+ buf[1] = 0;
+ *(s = buf) = '\\';
+ if (mbchar(s) != buf[0])
+ {
+ memcpy(mb_state, mb_state_zero, sizeof(mbstate_t));
+ ast.mb_towc = sjis_mbtowc;
+ }
+ }
+#endif
+ }
+ return 0;
+}
+
+/*
+ * called when LC_NUMERIC initialized or changes
+ */
+
+static int
+set_numeric(Lc_category_t* cp)
+{
+ register int category = cp->internal;
+ struct lconv* lp;
+ Lc_numeric_t* dp;
+
+ static Lc_numeric_t default_numeric = { '.', -1 };
+ static Lc_numeric_t eu_numeric = { ',', '.' };
+ static Lc_numeric_t us_numeric = { '.', ',' };
+
+#if AHA
+ if ((ast.locale.set & (AST_LC_debug|AST_LC_setlocale)) && !(ast.locale.set & AST_LC_internal))
+ sfprintf(sfstderr, "locale setf %17s %16s\n", cp->name, locales[cp->internal]->name);
+#endif
+ if (!LCINFO(category)->data)
+ {
+ if (locales[cp->internal]->flags & LC_local)
+ dp = locales[cp->internal]->territory == &lc_territories[0] ? &default_numeric : *locales[cp->internal]->territory->code == 'e' ? &eu_numeric : &us_numeric;
+ else if ((lp = localeconv()) && (dp = newof(0, Lc_numeric_t, 1, 0)))
+ {
+ dp->decimal = lp->decimal_point && *lp->decimal_point ? *(unsigned char*)lp->decimal_point : '.';
+ dp->thousand = lp->thousands_sep && *lp->thousands_sep ? *(unsigned char*)lp->thousands_sep : -1;
+ }
+ else
+ dp = &default_numeric;
+ LCINFO(category)->data = (void*)dp;
+ }
+ return 0;
+}
+
+/*
+ * this table is indexed by AST_LC_[A-Z]*
+ */
+
+Lc_category_t lc_categories[] =
+{
+{ "LC_ALL", LC_ALL, AST_LC_ALL, 0 },
+{ "LC_COLLATE", LC_COLLATE, AST_LC_COLLATE, set_collate },
+{ "LC_CTYPE", LC_CTYPE, AST_LC_CTYPE, set_ctype },
+{ "LC_MESSAGES", LC_MESSAGES, AST_LC_MESSAGES, 0 },
+{ "LC_MONETARY", LC_MONETARY, AST_LC_MONETARY, 0 },
+{ "LC_NUMERIC", LC_NUMERIC, AST_LC_NUMERIC, set_numeric },
+{ "LC_TIME", LC_TIME, AST_LC_TIME, 0 },
+{ "LC_IDENTIFICATION",LC_IDENTIFICATION,AST_LC_IDENTIFICATION,0 },
+{ "LC_ADDRESS", LC_ADDRESS, AST_LC_ADDRESS, 0 },
+{ "LC_NAME", LC_NAME, AST_LC_NAME, 0 },
+{ "LC_TELEPHONE", LC_TELEPHONE, AST_LC_TELEPHONE, 0 },
+{ "LC_XLITERATE", LC_XLITERATE, AST_LC_XLITERATE, 0 },
+{ "LC_MEASUREMENT", LC_MEASUREMENT, AST_LC_MEASUREMENT, 0 },
+{ "LC_PAPER", LC_PAPER, AST_LC_PAPER, 0 },
+};
+
+static Lc_t* lang;
+static Lc_t* lc_all;
+
+typedef struct Unamval_s
+{
+ char* name;
+ unsigned int value;
+} Unamval_t;
+
+static const Unamval_t options[] =
+{
+ "debug", AST_LC_debug,
+ "find", AST_LC_find,
+ "setlocale", AST_LC_setlocale,
+ "test", AST_LC_test,
+ "translate", AST_LC_translate,
+ 0, 0
+};
+
+/*
+ * called by stropt() to set options
+ */
+
+static int
+setopt(void* a, const void* p, int n, const char* v)
+{
+ if (p)
+ {
+ if (n)
+ ast.locale.set |= ((Unamval_t*)p)->value;
+ else
+ ast.locale.set &= ~((Unamval_t*)p)->value;
+ }
+ return 0;
+}
+
+#if !_lib_setlocale
+
+#define setlocale(c,l) default_setlocale(c,l)
+
+static char*
+default_setlocale(int category, const char* locale)
+{
+ Lc_t* lc;
+
+ if (locale)
+ {
+ if (!(lc = lcmake(locale)) || !(lc->flags & LC_default))
+ return 0;
+ locales[0]->flags &= ~lc->flags;
+ locales[1]->flags &= ~lc->flags;
+ return lc->name;
+ }
+ return (locales[1]->flags & (1<<category)) ? locales[1]->name : locales[0]->name;
+}
+
+#endif
+
+#if !_UWIN
+
+/*
+ * workaround for systems that shall not be named (solaris,freebsd)
+ * the call free() with addresses that look like the came from the stack
+ */
+
+extern int _vmkeep(int);
+
+static char*
+_sys_setlocale(int category, const char* locale)
+{
+ char* r;
+ int k;
+
+ k = _vmkeep(1);
+ r = setlocale(category, locale);
+ (void)_vmkeep(k);
+ return r;
+}
+
+#define setlocale(a,b) _sys_setlocale(a,b)
+
+#endif
+
+/*
+ * set a single AST_LC_* locale category
+ * the caller must validate category
+ * lc==0 restores the previous state
+ */
+
+static char*
+single(int category, Lc_t* lc, unsigned int flags)
+{
+ const char* sys;
+ int i;
+
+#if AHA
+ if ((ast.locale.set & (AST_LC_debug|AST_LC_setlocale)) && !(ast.locale.set & AST_LC_internal))
+ sfprintf(sfstderr, "locale single %16s %16s flags %04x\n", lc_categories[category].name, lc ? lc->name : 0, flags);
+#endif
+ if (flags & (LC_setenv|LC_setlocale))
+ {
+ if (!(ast.locale.set & AST_LC_internal))
+ lc_categories[category].prev = lc;
+ if ((flags & LC_setenv) && lc_all && locales[category])
+ {
+ if (lc_categories[category].setf)
+ (*lc_categories[category].setf)(&lc_categories[category]);
+ return (char*)locales[category]->name;
+ }
+ }
+ if (!lc && (!(lc_categories[category].flags & LC_setlocale) || !(lc = lc_categories[category].prev)) && !(lc = lc_all) && !(lc = lc_categories[category].prev) && !(lc = lang))
+ lc = lcmake(NiL);
+ sys = 0;
+ if (locales[category] != lc)
+ {
+ if (lc_categories[category].external == -lc_categories[category].internal)
+ {
+ for (i = 1; i < AST_LC_COUNT; i++)
+ if (locales[i] == lc)
+ {
+ sys = (char*)lc->name;
+ break;
+ }
+ }
+ else if (lc->flags & (LC_debug|LC_local))
+ sys = setlocale(lc_categories[category].external, lcmake(NiL)->name);
+ else if (!(sys = setlocale(lc_categories[category].external, lc->name)) &&
+ (streq(lc->name, lc->code) || !(sys = setlocale(lc_categories[category].external, lc->code))) &&
+ !streq(lc->code, lc->language->code))
+ sys = setlocale(lc_categories[category].external, lc->language->code);
+ if (sys)
+ lc->flags |= LC_checked;
+ else
+ {
+ /*
+ * check for local override
+ * currently this means an LC_MESSAGES dir exists
+ */
+
+ if (!(lc->flags & LC_checked))
+ {
+ char path[PATH_MAX];
+
+ if (mcfind(lc->code, NiL, LC_MESSAGES, 0, path, sizeof(path)))
+ lc->flags |= LC_local;
+ lc->flags |= LC_checked;
+ }
+ if (!(lc->flags & LC_local))
+ return 0;
+ if (lc_categories[category].external != -lc_categories[category].internal)
+ setlocale(lc_categories[category].external, lcmake(NiL)->name);
+ }
+ locales[category] = lc;
+ if (lc_categories[category].setf && (*lc_categories[category].setf)(&lc_categories[category]))
+ {
+ locales[category] = lc_categories[category].prev;
+ return 0;
+ }
+ if ((lc->flags & LC_default) || category == AST_LC_MESSAGES && lc->name[0] == 'e' && lc->name[1] == 'n' && (lc->name[2] == 0 || lc->name[2] == '_' && lc->name[3] == 'U'))
+ ast.locale.set &= ~(1<<category);
+ else
+ ast.locale.set |= (1<<category);
+
+ }
+ else if (lc_categories[category].flags ^ flags)
+ {
+ lc_categories[category].flags &= ~(LC_setenv|LC_setlocale);
+ lc_categories[category].flags |= flags;
+ }
+ else
+ {
+ if (lc_categories[category].setf)
+ (*lc_categories[category].setf)(&lc_categories[category]);
+ return (char*)lc->name;
+ }
+ if ((ast.locale.set & (AST_LC_debug|AST_LC_setlocale)) && !(ast.locale.set & AST_LC_internal))
+ {
+ header();
+ sfprintf(sfstderr, "locale set %17s %16s %16s %16s", lc_categories[category].name, lc->name, sys, lc_categories[category].prev ? lc_categories[category].prev->name : NiL);
+ if (category == AST_LC_CTYPE)
+ sfprintf(sfstderr, " MB_CUR_MAX=%d%s%s%s%s%s"
+ , ast.mb_cur_max
+ , ast.mb_len == debug_mblen ? " debug_mblen" : ast.mb_len == utf8_mblen ? " utf8_mblen" : ast.mb_len == mblen ? " mblen" : ""
+ , ast.mb_towc == debug_mbtowc ? " debug_mbtowc" : ast.mb_towc == utf8_mbtowc ? " utf8_mbtowc" : ast.mb_towc == mbtowc ? " mbtowc"
+#ifdef mb_state
+ : ast.mb_towc == sjis_mbtowc ? " sjis_mbtowc"
+#endif
+ : ""
+ , ast.mb_width == debug_wcwidth ? " debug_wcwidth" : ast.mb_width == utf8_wcwidth ? " utf8_wcwidth" : ast.mb_width == wcwidth ? " wcwidth" : ast.mb_width == default_wcwidth ? " default_wcwidth" : ""
+ , ast.mb_conv == debug_wctomb ? " debug_wctomb" : ast.mb_conv == utf8_wctomb ? " utf8_wctomb" : ast.mb_conv == wctomb ? " wctomb" : ""
+ , ast.mb_alpha == debug_alpha ? " debug_alpha" : ast.mb_alpha == utf8_alpha ? " utf8_alpha" : ast.mb_alpha == (Isw_f)iswalpha ? " iswalpha" : ""
+ );
+ else if (category == AST_LC_NUMERIC)
+ {
+ Lc_numeric_t* dp = (Lc_numeric_t*)LCINFO(category)->data;
+
+ sfprintf(sfstderr, " decimal='%c' thousands='%c'", dp->decimal, dp->thousand >= 0 ? dp->thousand : 'X');
+ }
+ if ((locales[category]->flags | lc_categories[category].flags) & LC_default)
+ sfprintf(sfstderr, " default");
+ if ((locales[category]->flags | lc_categories[category].flags) & LC_local)
+ sfprintf(sfstderr, " local");
+ if ((locales[category]->flags | lc_categories[category].flags) & LC_setlocale)
+ sfprintf(sfstderr, " setlocale");
+ if ((locales[category]->flags | lc_categories[category].flags) & LC_setenv)
+ sfprintf(sfstderr, " setenv");
+ sfprintf(sfstderr, "\n");
+ }
+ return (char*)lc->name;
+}
+
+/*
+ * set composite AST_LC_ALL locale categories
+ * return <0:composite-error 0:not-composite >0:composite-ok
+ */
+
+static int
+composite(register const char* s, int initialize)
+{
+ register const char* t;
+ register int i;
+ register int j;
+ register int k;
+ int n;
+ int m;
+ const char* w;
+ Lc_t* p;
+ int cat[AST_LC_COUNT];
+ int stk[AST_LC_COUNT];
+ char buf[PATH_MAX / 2];
+
+ k = n = 0;
+ while (s[0] == 'L' && s[1] == 'C' && s[2] == '_')
+ {
+ n++;
+ j = 0;
+ w = s;
+ for (i = 1; i < AST_LC_COUNT; i++)
+ {
+ s = w;
+ t = lc_categories[i].name;
+ while (*t && *s++ == *t++);
+ if (!*t && *s++ == '=')
+ {
+ cat[j++] = i;
+ if (s[0] != 'L' || s[1] != 'C' || s[2] != '_')
+ break;
+ w = s;
+ i = -1;
+ }
+ }
+ for (s = w; *s && *s != '='; s++);
+ if (!*s)
+ {
+ for (i = 0; i < k; i++)
+ single(stk[i], NiL, 0);
+ return -1;
+ }
+ w = ++s;
+ for (;;)
+ {
+ if (!*s)
+ {
+ p = lcmake(w);
+ break;
+ }
+ else if (*s++ == ';')
+ {
+ if ((m = s - w - 1) >= sizeof(buf))
+ m = sizeof(buf) - 1;
+ memcpy(buf, w, m);
+ buf[m] = 0;
+ p = lcmake(buf);
+ break;
+ }
+ }
+ for (i = 0; i < j; i++)
+ if (!initialize)
+ {
+ if (!single(cat[i], p, 0))
+ {
+ for (i = 0; i < k; i++)
+ single(stk[i], NiL, 0);
+ return -1;
+ }
+ stk[k++] = cat[i];
+ }
+ else if (!lc_categories[cat[i]].prev && !(ast.locale.set & AST_LC_internal))
+ lc_categories[cat[i]].prev = p;
+ }
+ while (s[0] == '/' && s[1] && n < (AST_LC_COUNT - 1))
+ {
+ n++;
+ for (w = ++s; *s && *s != '/'; s++);
+ if (!*s)
+ p = lcmake(w);
+ else
+ {
+ if ((j = s - w - 1) >= sizeof(buf))
+ j = sizeof(buf) - 1;
+ memcpy(buf, w, j);
+ buf[j] = 0;
+ p = lcmake(buf);
+ }
+ if (!initialize)
+ {
+ if (!single(n, p, 0))
+ {
+ for (i = 1; i < n; i++)
+ single(i, NiL, 0);
+ return -1;
+ }
+ }
+ else if (!lc_categories[n].prev && !(ast.locale.set & AST_LC_internal))
+ lc_categories[n].prev = p;
+ }
+ return n;
+}
+
+/*
+ * setlocale() intercept
+ *
+ * locale:
+ * 0 query
+ * "" initialize from environment (if LC_ALL)
+ * "" AST_LC_setenv: value unset (defer to LANG)
+ * "*" AST_LC_setenv: value set (defer to LC_ALL)
+ * * set (override LC_ALL)
+ */
+
+char*
+_ast_setlocale(int category, const char* locale)
+{
+ register char* s;
+ register int i;
+ register int j;
+ int k;
+ int f;
+ Lc_t* p;
+ int cat[AST_LC_COUNT];
+
+ static Sfio_t* sp;
+ static int initialized;
+ static const char local[] = "local";
+
+ if ((category = lcindex(category, 0)) < 0)
+ return 0;
+ if (!locale)
+ {
+ /*
+ * return the current state
+ */
+
+ compose:
+ if (category != AST_LC_ALL && category != AST_LC_LANG)
+ return (char*)locales[category]->name;
+ if (!sp && !(sp = sfstropen()))
+ return 0;
+ for (i = 1; i < AST_LC_COUNT; i++)
+ cat[i] = -1;
+ for (i = 1, k = 0; i < AST_LC_COUNT; i++)
+ if (cat[i] < 0)
+ {
+ k++;
+ cat[i] = i;
+ for (j = i + 1; j < AST_LC_COUNT; j++)
+ if (locales[j] == locales[i])
+ cat[j] = i;
+ }
+ if (k == 1)
+ return (char*)locales[1]->name;
+ for (i = 1; i < AST_LC_COUNT; i++)
+ if (cat[i] >= 0 && !(locales[i]->flags & LC_default))
+ {
+ if (sfstrtell(sp))
+ sfprintf(sp, ";");
+ for (j = i, k = cat[i]; j < AST_LC_COUNT; j++)
+ if (cat[j] == k)
+ {
+ cat[j] = -1;
+ sfprintf(sp, "%s=", lc_categories[j].name);
+ }
+ sfprintf(sp, "%s", locales[i]->name);
+ }
+ if (!sfstrtell(sp))
+ return (char*)locales[0]->name;
+ return sfstruse(sp);
+ }
+ if (!ast.locale.serial++)
+ {
+ stropt(getenv("LC_OPTIONS"), options, sizeof(*options), setopt, NiL);
+ initialized = 0;
+ }
+ if ((ast.locale.set & (AST_LC_debug|AST_LC_setlocale)) && !(ast.locale.set & AST_LC_internal))
+ {
+ header();
+ sfprintf(sfstderr, "locale user %17s %16s %16s %16s%s%s\n", category == AST_LC_LANG ? "LANG" : lc_categories[category].name, locale && !*locale ? "''" : locale, "", "", initialized ? "" : " initial", (ast.locale.set & AST_LC_setenv) ? " setenv" : "");
+ }
+ if (ast.locale.set & AST_LC_setenv)
+ {
+ f = LC_setenv;
+ p = *locale ? lcmake(locale) : (Lc_t*)0;
+ }
+ else if (*locale)
+ {
+ f = LC_setlocale;
+ p = lcmake(locale);
+ }
+ else if (category == AST_LC_ALL)
+ {
+ if (!initialized)
+ {
+ char* u;
+ char tmp[256];
+
+ /*
+ * initialize from the environment
+ * precedence determined by X/Open
+ */
+
+ u = 0;
+ if ((s = getenv("LANG")) && *s)
+ {
+ if (streq(s, local) && (u || (u = native_locale(locale, tmp, sizeof(tmp)))))
+ s = u;
+ lang = lcmake(s);
+ }
+ else
+ lang = 0;
+ if ((s = getenv("LC_ALL")) && *s)
+ {
+ if (streq(s, local) && (u || (u = native_locale(locale, tmp, sizeof(tmp)))))
+ s = u;
+ lc_all = lcmake(s);
+ }
+ else
+ lc_all = 0;
+ for (i = 1; i < AST_LC_COUNT; i++)
+ if (lc_categories[i].flags & LC_setlocale)
+ /* explicitly set by setlocale() */;
+ else if ((s = getenv(lc_categories[i].name)) && *s)
+ {
+ if (streq(s, local) && (u || (u = native_locale(locale, tmp, sizeof(tmp)))))
+ s = u;
+ lc_categories[i].prev = lcmake(s);
+ }
+ else
+ lc_categories[i].prev = 0;
+ for (i = 1; i < AST_LC_COUNT; i++)
+ if (!single(i, lc_all && !(lc_categories[i].flags & LC_setlocale) ? lc_all : lc_categories[i].prev, 0))
+ {
+ while (i--)
+ single(i, NiL, 0);
+ return 0;
+ }
+ if (ast.locale.set & AST_LC_debug)
+ for (i = 1; i < AST_LC_COUNT; i++)
+ sfprintf(sfstderr, "locale env %17s %16s %16s %16s\n", lc_categories[i].name, locales[i]->name, "", lc_categories[i].prev ? lc_categories[i].prev->name : (char*)0);
+ initialized = 1;
+ }
+ goto compose;
+ }
+ else if (category == AST_LC_LANG || !(p = lc_categories[category].prev))
+ {
+ f = 0;
+ p = lcmake("C");
+ }
+ else
+ f = 0;
+ if (category == AST_LC_LANG)
+ {
+ if (lang != p)
+ {
+ lang = p;
+ if (!lc_all)
+ for (i = 1; i < AST_LC_COUNT; i++)
+ if (!single(i, lc_categories[i].prev, 0))
+ {
+ while (i--)
+ single(i, NiL, 0);
+ return 0;
+ }
+ }
+ }
+ else if (category != AST_LC_ALL)
+ {
+ if (f || !lc_all)
+ return single(category, p, f);
+ if (p && !(ast.locale.set & AST_LC_internal))
+ lc_categories[category].prev = p;
+ return (char*)locales[category]->name;
+ }
+ else if (composite(locale, 0) < 0)
+ return 0;
+ else if (lc_all != p)
+ {
+ lc_all = p;
+ for (i = 1; i < AST_LC_COUNT; i++)
+ if (!single(i, lc_all && !(lc_categories[i].flags & LC_setlocale) ? lc_all : lc_categories[i].prev, 0))
+ {
+ while (i--)
+ single(i, NiL, 0);
+ return 0;
+ }
+ }
+ goto compose;
+}
diff --git a/src/lib/libast/comp/setlogmask.c b/src/lib/libast/comp/setlogmask.c
new file mode 100644
index 0000000..f1851a7
--- /dev/null
+++ b/src/lib/libast/comp/setlogmask.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * syslog implementation
+ */
+
+#include <ast.h>
+
+#if _lib_syslog
+
+NoN(setlogmask)
+
+#else
+
+#include "sysloglib.h"
+
+int
+setlogmask(int mask)
+{
+ int old_mask;
+
+ old_mask = log.mask;
+ if (mask)
+ log.mask = mask;
+ return old_mask;
+}
+
+#endif
diff --git a/src/lib/libast/comp/setpgid.c b/src/lib/libast/comp/setpgid.c
new file mode 100644
index 0000000..c966919
--- /dev/null
+++ b/src/lib/libast/comp/setpgid.c
@@ -0,0 +1,80 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_setpgid
+
+NoN(setpgid)
+
+#else
+
+#include <error.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+#if _lib_setpgrp2
+#define setpgrp setpgrp2
+#else
+#if _lib_BSDsetpgrp
+#define _lib_setpgrp2 1
+#define setpgrp BSDsetpgrp
+#else
+#if _lib_wait3
+#define _lib_setpgrp2 1
+#endif
+#endif
+#endif
+
+#if _lib_setpgrp2
+extern int setpgrp(int, int);
+#else
+extern int setpgrp(void);
+#endif
+
+/*
+ * set process group id
+ */
+
+int
+setpgid(pid_t pid, pid_t pgid)
+{
+#if _lib_setpgrp2
+ return(setpgrp(pid, pgid));
+#else
+#if _lib_setpgrp
+ int caller = getpid();
+
+ if ((pid == 0 || pid == caller) && (pgid == 0 || pgid == caller))
+ return(setpgrp());
+ errno = EINVAL;
+#else
+ errno = ENOSYS;
+#endif
+ return(-1);
+#endif
+}
+
+#endif
diff --git a/src/lib/libast/comp/setsid.c b/src/lib/libast/comp/setsid.c
new file mode 100644
index 0000000..10544bb
--- /dev/null
+++ b/src/lib/libast/comp/setsid.c
@@ -0,0 +1,90 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_setsid
+
+NoN(setsid)
+
+#else
+
+#include <ast_tty.h>
+#include <error.h>
+
+/*
+ * become new process group leader and drop control tty
+ */
+
+pid_t
+setsid(void)
+{
+ int pg;
+#ifdef TIOCNOTTY
+ int fd;
+#endif
+
+ /*
+ * become a new process group leader
+ */
+
+ if ((pg = getpid()) == getpgrp())
+ {
+ errno = EPERM;
+ return(-1);
+ }
+ setpgid(pg, pg);
+#ifdef TIOCNOTTY
+
+ /*
+ * drop the control tty
+ */
+
+ if ((fd = open("/dev/tty", O_RDONLY)) >= 0)
+ {
+ ioctl(fd, TIOCNOTTY, 0);
+ close(fd);
+ }
+#else
+
+ /*
+ * second child in s5 to avoid reacquiring the control tty
+ */
+
+#if _lib_fork && HUH920711 /* some s5's botch this */
+ switch (fork())
+ {
+ case -1:
+ exit(1);
+ case 0:
+ break;
+ default:
+ exit(0);
+ }
+#endif
+
+#endif
+ return(pg);
+}
+
+#endif
diff --git a/src/lib/libast/comp/sigflag.c b/src/lib/libast/comp/sigflag.c
new file mode 100644
index 0000000..05ea22b
--- /dev/null
+++ b/src/lib/libast/comp/sigflag.c
@@ -0,0 +1,52 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_sigflag
+
+NoN(sigflag)
+
+#else
+
+#include <sig.h>
+
+int
+sigflag(int sig, int flags, int set)
+{
+#if _lib_sigaction
+ struct sigaction sa;
+
+ if (sigaction(sig, NiL, &sa))
+ return -1;
+ if (set)
+ sa.sa_flags |= flags;
+ else
+ sa.sa_flags &= ~flags;
+ return sigaction(sig, &sa, NiL);
+#else
+ return -1;
+#endif
+}
+
+#endif
diff --git a/src/lib/libast/comp/sigunblock.c b/src/lib/libast/comp/sigunblock.c
new file mode 100644
index 0000000..dfcb28b
--- /dev/null
+++ b/src/lib/libast/comp/sigunblock.c
@@ -0,0 +1,63 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_sigunblock
+
+NoN(sigunblock)
+
+#else
+
+#include <sig.h>
+
+#ifndef SIG_UNBLOCK
+#undef _lib_sigprocmask
+#endif
+
+int
+sigunblock(int s)
+{
+#if _lib_sigprocmask
+ int op;
+ sigset_t mask;
+
+ sigemptyset(&mask);
+ if (s)
+ {
+ sigaddset(&mask, s);
+ op = SIG_UNBLOCK;
+ }
+ else op = SIG_SETMASK;
+ return(sigprocmask(op, &mask, NiL));
+#else
+#if _lib_sigsetmask
+ return(sigsetmask(s ? (sigsetmask(0L) & ~sigmask(s)) : 0L));
+#else
+ NoP(s);
+ return(0);
+#endif
+#endif
+}
+
+#endif
diff --git a/src/lib/libast/comp/spawnveg.c b/src/lib/libast/comp/spawnveg.c
new file mode 100644
index 0000000..6117e3a
--- /dev/null
+++ b/src/lib/libast/comp/spawnveg.c
@@ -0,0 +1,296 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * spawnveg -- spawnve with process group or session control
+ *
+ * pgid <0 setsid() [session group leader]
+ * 0 nothing [retain session and process group]
+ * 1 setpgid(0,0) [process group leader]
+ * >1 setpgid(0,pgid) [join process group]
+ */
+
+#include <ast.h>
+
+#if _lib_spawnveg
+
+NoN(spawnveg)
+
+#else
+
+#if _lib_posix_spawn > 1 /* reports underlying exec() errors */
+
+#include <spawn.h>
+#include <error.h>
+#include <wait.h>
+
+pid_t
+spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
+{
+ int err;
+ pid_t pid;
+ posix_spawnattr_t attr;
+
+ if (err = posix_spawnattr_init(&attr))
+ goto nope;
+ if (pgid)
+ {
+ if (pgid <= 1)
+ pgid = 0;
+ if (err = posix_spawnattr_setpgroup(&attr, pgid))
+ goto bad;
+ if (err = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP))
+ goto bad;
+ }
+ if (err = posix_spawn(&pid, path, NiL, &attr, argv, envv ? envv : environ))
+ goto bad;
+ posix_spawnattr_destroy(&attr);
+#if _lib_posix_spawn < 2
+ if (waitpid(pid, &err, WNOHANG|WNOWAIT) == pid && EXIT_STATUS(err) == 127)
+ {
+ while (waitpid(pid, NiL, 0) == -1 && errno == EINTR);
+ if (!access(path, X_OK))
+ errno = ENOEXEC;
+ pid = -1;
+ }
+#endif
+ return pid;
+ bad:
+ posix_spawnattr_destroy(&attr);
+ nope:
+ errno = err;
+ return -1;
+}
+
+#else
+
+#if _lib_spawn_mode
+
+#include <process.h>
+
+#ifndef P_NOWAIT
+#define P_NOWAIT _P_NOWAIT
+#endif
+#ifndef P_DETACH
+#define P_DETACH _P_DETACH
+#endif
+
+pid_t
+spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
+{
+ return spawnve(pgid ? P_DETACH : P_NOWAIT, path, argv, envv ? envv : environ);
+}
+
+#else
+
+#if _lib_spawn && _hdr_spawn && _mem_pgroup_inheritance
+
+#include <spawn.h>
+
+/*
+ * open-edition/mvs/zos fork+exec+(setpgid)
+ */
+
+pid_t
+spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
+{
+ struct inheritance inherit;
+
+ inherit.flags = 0;
+ if (pgid)
+ {
+ inherit.flags |= SPAWN_SETGROUP;
+ inherit.pgroup = (pgid > 1) ? pgid : SPAWN_NEWPGROUP;
+ }
+ return spawn(path, 0, (int*)0, &inherit, (const char**)argv, (const char**)envv);
+}
+
+#else
+
+#include <error.h>
+#include <wait.h>
+#include <sig.h>
+#include <ast_tty.h>
+#include <ast_vfork.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+#if _lib_spawnve && _hdr_process
+#include <process.h>
+#if defined(P_NOWAIT) || defined(_P_NOWAIT)
+#undef _lib_spawnve
+#endif
+#endif
+
+#if !_lib_vfork
+#undef _real_vfork
+#endif
+
+/*
+ * fork+exec+(setsid|setpgid)
+ */
+
+pid_t
+spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
+{
+#if _lib_fork || _lib_vfork
+ int n;
+ int m;
+ pid_t pid;
+ pid_t rid;
+#if _real_vfork
+ volatile int exec_errno;
+ volatile int* volatile exec_errno_ptr;
+#else
+ int err[2];
+#endif
+#endif
+
+#if 0
+ if (access(path, X_OK))
+ return -1;
+#endif
+ if (!envv)
+ envv = environ;
+#if _lib_spawnve
+#if _lib_fork || _lib_vfork
+ if (!pgid)
+#endif
+ return spawnve(path, argv, envv);
+#endif
+#if _lib_fork || _lib_vfork
+ n = errno;
+#if _real_vfork
+ exec_errno = 0;
+ exec_errno_ptr = &exec_errno;
+#else
+ if (pipe(err) < 0)
+ err[0] = -1;
+ else
+ {
+ fcntl(err[0], F_SETFD, FD_CLOEXEC);
+ fcntl(err[1], F_SETFD, FD_CLOEXEC);
+ }
+#endif
+ sigcritical(SIG_REG_EXEC|SIG_REG_PROC);
+#if _lib_vfork
+ pid = vfork();
+#else
+ pid = fork();
+#endif
+ if (pid == -1)
+ n = errno;
+ else if (!pid)
+ {
+ sigcritical(0);
+ if (pgid == -1)
+ setsid();
+ else if (pgid)
+ {
+ m = 0;
+ if (pgid == 1 || pgid == -2 && (m = 1))
+ pgid = getpid();
+ if (setpgid(0, pgid) < 0 && errno == EPERM)
+ setpgid(pgid, 0);
+#if _lib_tcgetpgrp
+ if (m)
+ tcsetpgrp(2, pgid);
+#else
+#ifdef TIOCSPGRP
+ if (m)
+ ioctl(2, TIOCSPGRP, &pgid);
+#endif
+#endif
+ }
+ execve(path, argv, envv);
+#if _real_vfork
+ *exec_errno_ptr = errno;
+#else
+ if (err[0] != -1)
+ {
+ m = errno;
+ write(err[1], &m, sizeof(m));
+ }
+#endif
+ _exit(errno == ENOENT ? EXIT_NOTFOUND : EXIT_NOEXEC);
+ }
+ rid = pid;
+#if _real_vfork
+ if (pid != -1 && (m = *exec_errno_ptr))
+ {
+ while (waitpid(pid, NiL, 0) == -1 && errno == EINTR);
+ rid = pid = -1;
+ n = m;
+ }
+#else
+ if (err[0] != -1)
+ {
+ close(err[1]);
+ if (pid != -1)
+ {
+ m = 0;
+ while (read(err[0], &m, sizeof(m)) == -1)
+ if (errno != EINTR)
+ {
+ m = errno;
+ break;
+ }
+ if (m)
+ {
+ while (waitpid(pid, &n, 0) && errno == EINTR);
+ rid = pid = -1;
+ n = m;
+ }
+ }
+ close(err[0]);
+ }
+#endif
+ sigcritical(0);
+ if (pid != -1 && pgid > 0)
+ {
+ /*
+ * parent and child are in a race here
+ */
+
+ if (pgid == 1)
+ pgid = pid;
+ if (setpgid(pid, pgid) < 0 && pid != pgid && errno == EPERM)
+ setpgid(pid, pid);
+ }
+ errno = n;
+ return rid;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+#endif
+
+#endif
+
+#endif
+
+#endif
diff --git a/src/lib/libast/comp/statvfs.c b/src/lib/libast/comp/statvfs.c
new file mode 100644
index 0000000..b9bbf68
--- /dev/null
+++ b/src/lib/libast/comp/statvfs.c
@@ -0,0 +1,163 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <ls.h>
+
+#if _lib_statvfs
+
+NoN(statvfs)
+
+#else
+
+#include <error.h>
+
+#define HUH (-1)
+
+#if _lib_statfs && _mem_f_files_statfs && ( _sys_statfs || _sys_vfs || _sys_mount )
+
+#if _sys_statfs
+#include <sys/statfs.h>
+#else
+#if _sys_vfs
+#include <sys/vfs.h>
+#else
+#if _sys_mount
+#if _lib_getmntinfo
+#include <sys/param.h> /* expect some macro redefinitions here */
+#endif
+#include <sys/mount.h>
+#endif
+#endif
+#endif
+
+#if _lib_statfs4
+#define FSTATFS(a,b) fstatfs(a,b,sizeof(struct statfs),0)
+#define STATFS(a,b) statfs(a,b,sizeof(struct statfs),0)
+#else
+#define FSTATFS(a,b) fstatfs(a,b)
+#define STATFS(a,b) statfs(a,b)
+#endif
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+static void
+us2v(register struct statfs* ufs, register struct stat* st, register struct statvfs* vfs)
+{
+ memset(vfs, 0, sizeof(*vfs));
+ vfs->f_bsize = vfs->f_frsize = ufs->f_bsize;
+ vfs->f_blocks = ufs->f_blocks;
+ vfs->f_bfree = ufs->f_bfree;
+ vfs->f_bavail =
+#if _mem_f_bavail_statfs
+ ufs->f_bavail;
+#else
+ ufs->f_bfree;
+#endif
+ vfs->f_files = ufs->f_files;
+ vfs->f_ffree = ufs->f_ffree;
+ vfs->f_favail = (ufs->f_ffree > 10) ? (ufs->f_ffree - 10) : 0;
+ vfs->f_fsid = st->st_dev;
+ strlcpy(vfs->f_basetype, FS_default, sizeof(vfs->f_basetype) - 1);
+ vfs->f_namemax = 14;
+ strlcpy(vfs->f_fstr, vfs->f_basetype, sizeof(vfs->f_fstr) - 1);
+}
+
+extern int
+fstatvfs(int fd, struct statvfs* vfs)
+{
+ struct statfs ufs;
+ struct stat st;
+
+ if (FSTATFS(fd, &ufs) || fstat(fd, &st))
+ return(-1);
+ us2v(&ufs, &st, vfs);
+ return(0);
+}
+
+extern int
+statvfs(const char* path, struct statvfs* vfs)
+{
+ struct statfs ufs;
+ struct stat st;
+
+ if (STATFS(path, &ufs) || stat(path, &st))
+ return(-1);
+ us2v(&ufs, &st, vfs);
+ return(0);
+}
+
+#else
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+static void
+s2v(register struct stat* st, register struct statvfs* vfs)
+{
+ memset(vfs, 0, sizeof(*vfs));
+ vfs->f_bsize = vfs->f_frsize =
+#if _mem_st_blksize_stat
+ st->st_blksize;
+#else
+ 512;
+#endif
+ vfs->f_blocks = HUH;
+ vfs->f_bfree = HUH;
+ vfs->f_files = HUH;
+ vfs->f_ffree = HUH;
+ vfs->f_favail = HUH;
+ vfs->f_fsid = st->st_dev;
+ strlcpy(vfs->f_basetype, FS_default, sizeof(vfs->f_basetype));
+ vfs->f_namemax = 14;
+ strlcpy(vfs->f_fstr, vfs->f_basetype, sizeof(vfs->f_fstr));
+}
+
+extern int
+fstatvfs(int fd, struct statvfs* vfs)
+{
+ struct stat st;
+
+ if (fstat(fd, &st))
+ return(-1);
+ s2v(&st, vfs);
+ return(0);
+}
+
+extern int
+statvfs(const char* path, struct statvfs* vfs)
+{
+ struct stat st;
+
+ if (stat(path, &st))
+ return(-1);
+ s2v(&st, vfs);
+ return(0);
+}
+
+#endif
+
+#endif
diff --git a/src/lib/libast/comp/strcasecmp.c b/src/lib/libast/comp/strcasecmp.c
new file mode 100644
index 0000000..0ea1869
--- /dev/null
+++ b/src/lib/libast/comp/strcasecmp.c
@@ -0,0 +1,58 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_strcasecmp
+
+NoN(strcasecmp)
+
+#else
+
+#include <ctype.h>
+
+#undef strcasecmp
+
+int
+strcasecmp(register const char* a, register const char* b)
+{
+ register int ac;
+ register int bc;
+ register int d;
+
+ for (;;)
+ {
+ ac = *a++;
+ if (isupper(ac))
+ ac = tolower(ac);
+ bc = *b++;
+ if (isupper(bc))
+ bc = tolower(bc);
+ if (d = ac - bc)
+ return d;
+ if (!ac)
+ return 0;
+ }
+}
+
+#endif
diff --git a/src/lib/libast/comp/strchr.c b/src/lib/libast/comp/strchr.c
new file mode 100644
index 0000000..7b556c5
--- /dev/null
+++ b/src/lib/libast/comp/strchr.c
@@ -0,0 +1,57 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_strchr
+
+NoN(strchr)
+
+#else
+
+#undef strchr
+
+#if _lib_index
+
+#undef index
+
+extern char* index(const char*, int);
+
+char*
+strchr(const char* s, int c)
+{
+ return(index(s, c));
+}
+
+#else
+
+char*
+strchr(register const char* s, register int c)
+{
+ do if (*s == c) return((char*)s); while(*s++);
+ return(0);
+}
+
+#endif
+
+#endif
diff --git a/src/lib/libast/comp/strftime.c b/src/lib/libast/comp/strftime.c
new file mode 100644
index 0000000..5c8d5bd
--- /dev/null
+++ b/src/lib/libast/comp/strftime.c
@@ -0,0 +1,104 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * strftime implementation
+ */
+
+#define strftime ______strftime
+
+#include <ast.h>
+#include <tm.h>
+
+#undef strftime
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#undef _lib_strftime /* we can pass X/Open */
+
+#if _lib_strftime
+
+NoN(strftime)
+
+#else
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern size_t
+strftime(char* buf, size_t len, const char* format, const struct tm* tm)
+{
+ register char* s;
+ time_t t;
+ Tm_t tl;
+
+ memset(&tl, 0, sizeof(tl));
+
+ /*
+ * nl_langinfo() may call strftime() with bogus tm except for
+ * one value -- what a way to go
+ */
+
+ if (tm->tm_sec < 0 || tm->tm_sec > 60 ||
+ tm->tm_min < 0 || tm->tm_min > 59 ||
+ tm->tm_hour < 0 || tm->tm_hour > 23 ||
+ tm->tm_wday < 0 || tm->tm_wday > 6 ||
+ tm->tm_mday < 1 || tm->tm_mday > 31 ||
+ tm->tm_mon < 0 || tm->tm_mon > 11 ||
+ tm->tm_year < 0 || tm->tm_year > (2138 - 1900))
+ {
+ if (tm->tm_sec >= 0 && tm->tm_sec <= 60)
+ tl.tm_sec = tm->tm_sec;
+ if (tm->tm_min >= 0 && tm->tm_min <= 59)
+ tl.tm_min = tm->tm_min;
+ if (tm->tm_hour >= 0 && tm->tm_hour <= 23)
+ tl.tm_hour = tm->tm_hour;
+ if (tm->tm_wday >= 0 && tm->tm_wday <= 6)
+ tl.tm_wday = tm->tm_wday;
+ if (tm->tm_mday >= 0 && tm->tm_mday <= 31)
+ tl.tm_mday = tm->tm_mday;
+ if (tm->tm_mon >= 0 && tm->tm_mon <= 11)
+ tl.tm_mon = tm->tm_mon;
+ if (tm->tm_year >= 0 && tm->tm_year <= (2138 - 1900))
+ tl.tm_year = tm->tm_year;
+ }
+ else
+ {
+ tl.tm_sec = tm->tm_sec;
+ tl.tm_min = tm->tm_min;
+ tl.tm_hour = tm->tm_hour;
+ tl.tm_mday = tm->tm_mday;
+ tl.tm_mon = tm->tm_mon;
+ tl.tm_year = tm->tm_year;
+ tl.tm_wday = tm->tm_wday;
+ tl.tm_yday = tm->tm_yday;
+ tl.tm_isdst = tm->tm_isdst;
+ }
+ t = tmtime(&tl, TM_LOCALZONE);
+ if (!(s = tmfmt(buf, len, format, &t)))
+ return 0;
+ return s - buf;
+}
+
+#endif
diff --git a/src/lib/libast/comp/strncasecmp.c b/src/lib/libast/comp/strncasecmp.c
new file mode 100644
index 0000000..c312526
--- /dev/null
+++ b/src/lib/libast/comp/strncasecmp.c
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_strncasecmp
+
+NoN(strncasecmp)
+
+#else
+
+#include <ctype.h>
+
+#undef strncasecmp
+
+int
+strncasecmp(register const char* a, register const char* b, size_t n)
+{
+ register const char* e;
+ register int ac;
+ register int bc;
+ register int d;
+
+ e = a + n;
+ for (;;)
+ {
+ if (a >= e)
+ return 0;
+ ac = *a++;
+ if (isupper(ac))
+ ac = tolower(ac);
+ bc = *b++;
+ if (isupper(bc))
+ bc = tolower(bc);
+ if (d = ac - bc)
+ return d;
+ if (!ac)
+ return 0;
+ }
+}
+
+#endif
diff --git a/src/lib/libast/comp/strptime.c b/src/lib/libast/comp/strptime.c
new file mode 100644
index 0000000..981c98b
--- /dev/null
+++ b/src/lib/libast/comp/strptime.c
@@ -0,0 +1,82 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * strptime implementation
+ */
+
+#define strptime ______strptime
+
+#include <ast.h>
+#include <tmx.h>
+
+#undef strptime
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#if _lib_strptime
+
+NoN(strptime)
+
+#else
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char*
+strptime(const char* s, const char* format, struct tm* ts)
+{
+ char* e;
+ char* f;
+ time_t t;
+ Tm_t tm;
+
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_sec = ts->tm_sec;
+ tm.tm_min = ts->tm_min;
+ tm.tm_hour = ts->tm_hour;
+ tm.tm_mday = ts->tm_mday;
+ tm.tm_mon = ts->tm_mon;
+ tm.tm_year = ts->tm_year;
+ tm.tm_wday = ts->tm_wday;
+ tm.tm_yday = ts->tm_yday;
+ tm.tm_isdst = ts->tm_isdst;
+ t = tmtime(&tm, TM_LOCALZONE);
+ t = tmscan(s, &e, format, &f, &t, 0);
+ if (e == (char*)s || *f)
+ return 0;
+ tmxtm(&tm, tmxclock(&t), NiL);
+ ts->tm_sec = tm.tm_sec;
+ ts->tm_min = tm.tm_min;
+ ts->tm_hour = tm.tm_hour;
+ ts->tm_mday = tm.tm_mday;
+ ts->tm_mon = tm.tm_mon;
+ ts->tm_year = tm.tm_year;
+ ts->tm_wday = tm.tm_wday;
+ ts->tm_yday = tm.tm_yday;
+ ts->tm_isdst = tm.tm_isdst;
+ return e;
+}
+
+#endif
diff --git a/src/lib/libast/comp/strrchr.c b/src/lib/libast/comp/strrchr.c
new file mode 100644
index 0000000..4e192ce
--- /dev/null
+++ b/src/lib/libast/comp/strrchr.c
@@ -0,0 +1,60 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_strrchr
+
+NoN(strrchr)
+
+#else
+
+#undef strrchr
+
+#if _lib_rindex
+
+#undef rindex
+
+extern char* rindex(const char*, int);
+
+char*
+strrchr(const char* s, int c)
+{
+ return(rindex(s, c));
+}
+
+#else
+
+char*
+strrchr(register const char* s, register int c)
+{
+ register const char* r;
+
+ r = 0;
+ do if (*s == c) r = s; while(*s++);
+ return((char*)r);
+}
+
+#endif
+
+#endif
diff --git a/src/lib/libast/comp/strstr.c b/src/lib/libast/comp/strstr.c
new file mode 100644
index 0000000..aa50058
--- /dev/null
+++ b/src/lib/libast/comp/strstr.c
@@ -0,0 +1,76 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide strstr
+#else
+#define strstr ______strstr
+#endif
+
+#include <ast.h>
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide strstr
+#else
+#undef strstr
+#endif
+
+#if _lib_strstr
+
+NoN(strstr)
+
+#else
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char*
+strstr(register const char* s1, register const char* s2)
+{
+ register int c1;
+ register int c2;
+ register const char* t1;
+ register const char* t2;
+
+ if (s2)
+ {
+ if (!*s2)
+ return (char*)s1;
+ c2 = *s2++;
+ while (c1 = *s1++)
+ if (c1 == c2)
+ {
+ t1 = s1;
+ t2 = s2;
+ do
+ {
+ if (!*t2)
+ return (char*)s1 - 1;
+ } while (*t1++ == *t2++);
+ }
+ }
+ return 0;
+}
+
+#endif
diff --git a/src/lib/libast/comp/strtod.c b/src/lib/libast/comp/strtod.c
new file mode 100644
index 0000000..f0fb9af
--- /dev/null
+++ b/src/lib/libast/comp/strtod.c
@@ -0,0 +1,31 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strtod() implementation
+ */
+
+#include <ast.h>
+
+#define S2F_function strtod
+#define S2F_type 1
+
+#include "sfstrtof.h"
diff --git a/src/lib/libast/comp/strtol.c b/src/lib/libast/comp/strtol.c
new file mode 100644
index 0000000..de0367f
--- /dev/null
+++ b/src/lib/libast/comp/strtol.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strtol() implementation
+ */
+
+#if ! __CYGWIN__ /* 1.3.* static link conflict -- no iffe for this yet */
+
+#define S2I_function strtol
+#define S2I_number long
+#define S2I_unumber unsigned long
+
+#include "strtoi.h"
+
+#endif
diff --git a/src/lib/libast/comp/strtold.c b/src/lib/libast/comp/strtold.c
new file mode 100644
index 0000000..8f8c5b5
--- /dev/null
+++ b/src/lib/libast/comp/strtold.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strtold() implementation
+ */
+
+#define S2F_function strtold
+#define S2F_type 2
+
+/*
+ * ast strtold() => strtod() when double == long double
+ */
+
+#define _AST_STD_H 1
+
+#include <ast_common.h>
+
+#if _ast_fltmax_double
+#define strtold ______strtold
+#endif
+
+#include <ast_lib.h>
+#include <ast_sys.h>
+
+#if _ast_fltmax_double
+#undef strtold
+#endif
+
+#undef _AST_STD_H
+
+#include "sfstrtof.h"
diff --git a/src/lib/libast/comp/strtoll.c b/src/lib/libast/comp/strtoll.c
new file mode 100644
index 0000000..b5cf852
--- /dev/null
+++ b/src/lib/libast/comp/strtoll.c
@@ -0,0 +1,44 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strtoll() implementation
+ */
+
+#define strtoll ______strtoll
+
+#include <ast.h>
+
+#undef strtoll
+
+#if !_UWIN
+
+#undef _def_map_ast
+
+#include <ast_map.h>
+
+#endif
+
+#define S2I_function strtoll
+#define S2I_number intmax_t
+#define S2I_unumber uintmax_t
+
+#include "strtoi.h"
diff --git a/src/lib/libast/comp/strtoul.c b/src/lib/libast/comp/strtoul.c
new file mode 100644
index 0000000..82d964a
--- /dev/null
+++ b/src/lib/libast/comp/strtoul.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strtoul() implementation
+ */
+
+#if ! __CYGWIN__ /* 1.3.* static link conflict -- no iffe for this yet */
+
+#define S2I_function strtoul
+#define S2I_number long
+#define S2I_unumber unsigned long
+#define S2I_unsigned 1
+
+#include "strtoi.h"
+
+#endif
diff --git a/src/lib/libast/comp/strtoull.c b/src/lib/libast/comp/strtoull.c
new file mode 100644
index 0000000..bc197f6
--- /dev/null
+++ b/src/lib/libast/comp/strtoull.c
@@ -0,0 +1,45 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strtoull() implementation
+ */
+
+#define strtoull ______strtoull
+
+#include <ast.h>
+
+#undef strtoull
+
+#if !_UWIN
+
+#undef _def_map_ast
+
+#include <ast_map.h>
+
+#endif
+
+#define S2I_function strtoull
+#define S2I_number intmax_t
+#define S2I_unumber uintmax_t
+#define S2I_unsigned 1
+
+#include "strtoi.h"
diff --git a/src/lib/libast/comp/swab.c b/src/lib/libast/comp/swab.c
new file mode 100644
index 0000000..4bc905d
--- /dev/null
+++ b/src/lib/libast/comp/swab.c
@@ -0,0 +1,60 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * swab implementation
+ */
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide swab
+#else
+#define swab ______swab
+#endif
+
+#include <ast.h>
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide swab
+#else
+#undef swab
+#endif
+
+#if _lib_swab
+
+NoN(swab)
+
+#else
+
+#include <swap.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern void
+swab(const void* src, void* dst, ssize_t n)
+{
+ if (n > 1)
+ swapmem(1, src, dst, n & ~1);
+}
+
+#endif
diff --git a/src/lib/libast/comp/symlink.c b/src/lib/libast/comp/symlink.c
new file mode 100644
index 0000000..b0a5787
--- /dev/null
+++ b/src/lib/libast/comp/symlink.c
@@ -0,0 +1,59 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_symlink
+
+NoN(symlink)
+
+#else
+
+#include "fakelink.h"
+
+#include <error.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+int
+symlink(const char* a, char* b)
+{
+ if (*a == '/' && (*(a + 1) == 'd' || *(a + 1) == 'p' || *(a + 1) == 'n') && (!strncmp(a, "/dev/tcp/", 9) || !strncmp(a, "/dev/udp/", 9) || !strncmp(a, "/proc/", 6) || !strncmp(a, "/n/", 3)))
+ {
+ int n;
+ int fd;
+
+ if ((fd = open(b, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
+ return -1;
+ n = strlen(a) + 1;
+ n = (write(fd, FAKELINK_MAGIC, sizeof(FAKELINK_MAGIC)) != sizeof(FAKELINK_MAGIC) || write(fd, a, n) != n) ? -1 : 0;
+ close(fd);
+ return n;
+ }
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif
diff --git a/src/lib/libast/comp/syslog.c b/src/lib/libast/comp/syslog.c
new file mode 100644
index 0000000..08554e1
--- /dev/null
+++ b/src/lib/libast/comp/syslog.c
@@ -0,0 +1,367 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * syslog implementation
+ */
+
+#include <ast.h>
+
+#if _lib_syslog
+
+NoN(syslog)
+
+#else
+
+#define LOG_TABLES
+
+#include "sysloglib.h"
+
+#include <error.h>
+#include <tm.h>
+
+Syslog_state_t log = { LOG_USER, -1, 0, ~0 };
+
+static const Namval_t attempt[] =
+{
+#if _UWIN
+ "/var/log/syslog", 0,
+#endif
+ "/dev/log", 0,
+ "var/log/syslog", 0,
+ "lib/syslog/log", 0,
+ "/dev/console", LOG_CONS,
+};
+
+const Namval_t log_facility[] =
+{
+ "default", 0,
+ "user", LOG_USER,
+ "kernel", LOG_KERN,
+ "mail", LOG_MAIL,
+ "daemon", LOG_DAEMON,
+ "security", LOG_AUTH,
+ "syslog", LOG_SYSLOG,
+ "lpr", LOG_LPR,
+ "news", LOG_NEWS,
+ "uucp", LOG_UUCP,
+ "cron", LOG_CRON,
+ "audit", LOG_AUDIT,
+ "logalert", LOG_LFMT,
+#ifdef LOG_SYSTEM2
+ "system2", LOG_SYSTEM2,
+#endif
+#ifdef LOG_SYSTEM1
+ "system1", LOG_SYSTEM1,
+#endif
+#ifdef LOG_SYSTEM0
+ "system0", LOG_SYSTEM0,
+#endif
+ 0, 0
+};
+
+const Namval_t log_severity[] =
+{
+ "panic", LOG_EMERG,
+ "alert", LOG_ALERT,
+ "critical", LOG_CRIT,
+ "error", LOG_ERR,
+ "warning", LOG_WARNING,
+ "notice", LOG_NOTICE,
+ "info", LOG_INFO,
+ "debug", LOG_DEBUG,
+ 0, 0
+};
+
+#if _UWIN
+
+/*
+ * open /dev/(fdp|tcp|udp)/HOST/SERVICE for read
+ */
+
+#include <ctype.h>
+#include <ls.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netdb.h>
+#include <netinet/in.h>
+
+#if !defined(htons) && !_lib_htons
+# define htons(x) (x)
+#endif
+#if !defined(htonl) && !_lib_htonl
+# define htonl(x) (x)
+#endif
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK 0x7f000001L
+#endif
+
+/*
+ * convert s to sockaddr_in
+ * -1 returned on error
+ */
+
+static int
+str2inet(register char* s, char* prot, struct sockaddr_in* addr)
+{
+ register int c;
+ register int v;
+ register int n = 0;
+ unsigned long a = 0;
+ unsigned short p = 0;
+
+ if (!memcmp(s, "local/", 6))
+ {
+ a = INADDR_LOOPBACK;
+ n = 4;
+ s += 6;
+ }
+ else if (!isdigit(*s))
+ {
+ struct hostent* hp;
+ char* e = strchr(s, '/');
+
+ if (!(e = strchr(s, '/')))
+ return -1;
+ *e = 0;
+ hp = gethostbyname(s);
+ *e = '/';
+ if (!hp || hp->h_addrtype != AF_INET || hp->h_length > sizeof(struct in_addr))
+ return -1;
+ a = (unsigned long)((struct in_addr*)hp->h_addr)->s_addr;
+ n = 6;
+ s = e + 1;
+ }
+ for (;;)
+ {
+ v = 0;
+ while ((c = *s++) >= '0' && c <= '9')
+ v = v * 10 + c - '0';
+ if (++n <= 4)
+ a = (a << 8) | (v & 0xff);
+ else
+ {
+ if (n <= 5)
+ a = htonl(a);
+ if (c)
+ {
+ struct servent* sp;
+
+ if (!(sp = getservbyname(s - 1, prot)))
+ return -1;
+ p = sp->s_port;
+ }
+ else
+ p = htons(v);
+ break;
+ }
+ if (c != '.' && c != '/')
+ return -1;
+ }
+ memset((char*)addr, 0, sizeof(*addr));
+ addr->sin_family = AF_INET;
+ addr->sin_addr.s_addr = a;
+ addr->sin_port = p;
+ return 0;
+}
+
+/*
+ * call this after open fails to see if path is a socket
+ */
+
+int
+sockopen(const char* path)
+{
+ int fd;
+ struct sockaddr_in addr;
+ char buf[PATH_MAX];
+
+ if (pathgetlink(path, buf, sizeof(buf)) <= 0)
+ {
+ if (strlen(path) >= sizeof(buf))
+ return -1;
+ strcpy(buf, path);
+ }
+#if LOCAL
+ {
+ int ul;
+ struct sockaddr_un ua;
+ struct stat st;
+
+ if ((ul = strlen(buf)) < sizeof(ua.sun_path) && !stat(buf, &st) && S_ISSOCK(st.st_mode))
+ {
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ return -1;
+ ua.sun_family = AF_UNIX;
+ strcpy(ua.sun_path, buf);
+ ul += sizeof(ua.sun_family) + 1;
+ if (!connect(fd, (struct sockaddr*)&ua, ul))
+ return fd;
+ close(fd);
+ return -1;
+ }
+ }
+#endif
+ if (!strmatch(buf, "/dev/(tcp|udp)/*/*"))
+ return -1;
+ buf[8] = 0;
+ if (str2inet(buf + 9, buf + 5, &addr))
+ return -1;
+ if ((fd = socket(AF_INET, buf[5] == 't' ? SOCK_STREAM : SOCK_DGRAM, 0)) < 0)
+ return -1;
+ if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)))
+ {
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+#else
+
+int
+sockopen(const char* path)
+{
+ return -1;
+}
+
+#endif
+
+void
+sendlog(const char* msg)
+{
+ register char* s;
+ register Namval_t* p;
+ register int n;
+
+ n = msg ? strlen(msg) : 0;
+ for (;;)
+ {
+ if (log.fd < 0)
+ {
+ char buf[PATH_MAX];
+
+ if (log.attempt >= elementsof(attempt))
+ break;
+ p = (Namval_t*)&attempt[log.attempt++];
+ if (p->value && !(p->value & log.flags))
+ continue;
+ if (*(s = p->name) != '/' && !(s = pathpath(buf, s, "", PATH_REGULAR|PATH_READ, sizeof(buf))))
+ continue;
+ if ((log.fd = open(s, O_WRONLY|O_APPEND|O_NOCTTY)) < 0 && (log.fd = sockopen(s)) < 0)
+ continue;
+ fcntl(log.fd, F_SETFD, FD_CLOEXEC);
+ }
+ if (!n || write(log.fd, msg, n) > 0)
+ break;
+ close(log.fd);
+ log.fd = -1;
+ }
+ if (n && (log.flags & LOG_PERROR))
+ write(2, msg, n);
+}
+
+static int
+extend(Sfio_t* sp, void* vp, Sffmt_t* dp)
+{
+ if (dp->fmt == 'm')
+ {
+ dp->flags |= SFFMT_VALUE;
+ dp->fmt = 's';
+ dp->size = -1;
+ *((char**)vp) = fmterror(errno);
+ }
+ return 0;
+}
+
+void
+vsyslog(int priority, const char* format, va_list ap)
+{
+ register int c;
+ register char* s;
+ Sfio_t* sp;
+ Sffmt_t fmt;
+ char buf[16];
+
+ if (!LOG_FACILITY(priority))
+ priority |= log.facility;
+ if (!(priority & log.mask))
+ return;
+ if (sp = sfstropen())
+ {
+ sfputr(sp, fmttime("%b %d %H:%M:%S", time(NiL)), -1);
+ if (log.flags & LOG_LEVEL)
+ {
+ if ((c = LOG_SEVERITY(priority)) < elementsof(log_severity))
+ s = (char*)log_severity[c].name;
+ else
+ sfsprintf(s = buf, sizeof(buf), "debug%d", c);
+ sfprintf(sp, " %-8s ", s);
+ if ((c = LOG_FACILITY(priority)) < elementsof(log_facility))
+ s = (char*)log_facility[c].name;
+ else
+ sfsprintf(s = buf, sizeof(buf), "local%d", c);
+ sfprintf(sp, " %-8s ", s);
+ }
+#if _lib_gethostname
+ if (!*log.host && gethostname(log.host, sizeof(log.host)-1))
+ strcpy(log.host, "localhost");
+ sfprintf(sp, " %s", log.host);
+#endif
+ if (*log.ident)
+ sfprintf(sp, " %s", log.ident);
+ if (log.flags & LOG_PID)
+ {
+ if (!*log.ident)
+ sfprintf(sp, " ");
+ sfprintf(sp, "[%d]", getpid());
+ }
+ if (format)
+ {
+ sfprintf(sp, ": ");
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.version = SFIO_VERSION;
+ fmt.form = (char*)format;
+ fmt.extf = extend;
+ va_copy(fmt.args, ap);
+ sfprintf(sp, "%!", &fmt);
+ }
+ if ((s = sfstrseek(sp, 0, SEEK_CUR)) && *(s - 1) != '\n')
+ sfputc(sp, '\n');
+ if (s = sfstruse(sp))
+ sendlog(s);
+ sfstrclose(sp);
+ }
+}
+
+void
+syslog(int priority, const char* format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vsyslog(priority, format, ap);
+ va_end(ap);
+}
+
+#endif
diff --git a/src/lib/libast/comp/syslog.h b/src/lib/libast/comp/syslog.h
new file mode 100644
index 0000000..4856034
--- /dev/null
+++ b/src/lib/libast/comp/syslog.h
@@ -0,0 +1,132 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * posix syslog interface definitions
+ */
+
+#ifndef _SYSLOG_H
+#define _SYSLOG_H
+
+#include <stdarg.h>
+
+#define LOG_PRIBITS 3 /* priority bits */
+#define LOG_FACBITS 7 /* facility bits */
+
+#define LOG_PRIMASK ((1<<LOG_PRIBITS)-1)
+#define LOG_FACMASK (((1<<LOG_FACBITS)-1)<<LOG_PRIBITS)
+
+#define LOG_PRI(p) ((p)&((1<<LOG_PRIBITS)-1))
+#define LOG_FAC(p) (((p)>>LOG_PRIBITS)&((1<<LOG_FACBITS)-1))
+
+#define LOG_MAKEPRI(f,p) (((f)<<LOG_PRIBITS)|(p))
+
+/* syslog priority severity levels */
+
+#define LOG_EMERG 0 /* panic condition */
+#define LOG_ALERT 1 /* should be corrected immediately */
+#define LOG_CRIT 2 /* critical condition */
+#define LOG_ERR 3 /* error condition */
+#define LOG_WARNING 4 /* warning condition */
+#define LOG_NOTICE 5 /* no error but may need intervention */
+#define LOG_INFO 6 /* informational message */
+#define LOG_DEBUG 7 /* debug message */
+
+/* setlogmask masks */
+
+#define LOG_MASK(s) (1<<(s)) /* individual severity s */
+#define LOG_UPTO(s) ((1<<((s)+1))-1)/* up to and including s */
+
+/* syslog facilities */
+
+#define LOG_KERN (0<<LOG_PRIBITS) /* kernel */
+#define LOG_USER (1<<LOG_PRIBITS) /* user process -- default */
+#define LOG_MAIL (2<<LOG_PRIBITS) /* mail */
+#define LOG_DAEMON (3<<LOG_PRIBITS) /* daemon */
+#define LOG_AUTH (4<<LOG_PRIBITS) /* security/authorization */
+#define LOG_SYSLOG (5<<LOG_PRIBITS) /* syslog internal */
+#define LOG_LPR (6<<LOG_PRIBITS) /* line printer */
+#define LOG_NEWS (7<<LOG_PRIBITS) /* network news */
+#define LOG_UUCP (8<<LOG_PRIBITS) /* uucp */
+#define LOG_CRON (9<<LOG_PRIBITS) /* cron */
+#define LOG_AUDIT (13<<LOG_PRIBITS) /* audit daemon */
+#define LOG_LFMT (14<<LOG_PRIBITS) /* logalert */
+#define LOG_LOCAL0 (16<<LOG_PRIBITS) /* reserved for local use */
+#define LOG_LOCAL1 (17<<LOG_PRIBITS) /* reserved for local use */
+#define LOG_LOCAL2 (18<<LOG_PRIBITS) /* reserved for local use */
+#define LOG_LOCAL3 (19<<LOG_PRIBITS) /* reserved for local use */
+#define LOG_LOCAL4 (20<<LOG_PRIBITS) /* reserved for local use */
+#define LOG_LOCAL5 (21<<LOG_PRIBITS) /* reserved for local use */
+#define LOG_LOCAL6 (22<<LOG_PRIBITS) /* reserved for local use */
+#define LOG_LOCAL7 (23<<LOG_PRIBITS) /* reserved for local use */
+
+#define LOG_NFACILITIES 24
+
+/* openlog flags */
+
+#define LOG_PID 0x01 /* log the pid with each message */
+#define LOG_CONS 0x02 /* log to console if errors in sending */
+#define LOG_NDELAY 0x08 /* open right now */
+#define LOG_ODELAY 0x04 /* delay open until syslog() is called */
+#define LOG_NOWAIT 0x10 /* don't wait() for any child processes */
+#define LOG_PERROR 0x20 /* log to stderr too */
+#define LOG_LEVEL 0x40 /* tag messages with facility/level */
+
+#ifdef LOG_TABLES
+
+/* encoding support */
+
+#include <ast_namval.h>
+
+#define log_facility _log_facility
+#define log_severity _log_severity
+
+#define LOG_FACILITY(p) LOG_FAC(p) /* get facility index from pri */
+#define LOG_SEVERITY(p) LOG_PRI(p) /* get severity from pri */
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+#if !_BLD_ast && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern const Namval_t log_facility[];
+extern const Namval_t log_severity[];
+
+#undef extern
+
+#endif
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern void closelog(void);
+extern void openlog(const char*, int, int);
+extern int setlogmask(int);
+extern void syslog(int, const char*, ...);
+extern void vsyslog(int, const char*, va_list);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/comp/sysloglib.h b/src/lib/libast/comp/sysloglib.h
new file mode 100644
index 0000000..5a894c4
--- /dev/null
+++ b/src/lib/libast/comp/sysloglib.h
@@ -0,0 +1,54 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * posix syslog implementation definitions
+ */
+
+#ifndef _SYSLOGLIB_H
+#define _SYSLOGLIB_H
+
+#include <syslog.h>
+
+#define log _log_info_
+#define sendlog _log_send_
+
+/*
+ * NOTE: syslog() has a static initializer for Syslog_state_t log
+ */
+
+typedef struct
+{
+ int facility; /* openlog facility */
+ int fd; /* log to this fd */
+ int flags; /* openlog flags */
+ unsigned int mask; /* setlogmask mask */
+ int attempt; /* logfile attempt state */
+ char ident[64]; /* openlog ident */
+ char host[64]; /* openlog host name */
+} Syslog_state_t;
+
+extern Syslog_state_t log;
+
+extern void sendlog(const char*);
+
+#endif
diff --git a/src/lib/libast/comp/system.c b/src/lib/libast/comp/system.c
new file mode 100644
index 0000000..c0a3aa3
--- /dev/null
+++ b/src/lib/libast/comp/system.c
@@ -0,0 +1,55 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * ast library system(3)
+ */
+
+#define system ______system
+
+#define _STDLIB_H_ 1 /* uwin workaround */
+
+#include <ast.h>
+#include <proc.h>
+
+#undef system
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+system(const char* cmd)
+{
+ char* sh[4];
+
+ if (!cmd)
+ return !eaccess(pathshell(), X_OK);
+ sh[0] = "sh";
+ sh[1] = "-c";
+ sh[2] = (char*)cmd;
+ sh[3] = 0;
+ return procrun(NiL, sh, 0);
+}
diff --git a/src/lib/libast/comp/tempnam.c b/src/lib/libast/comp/tempnam.c
new file mode 100644
index 0000000..3cf375c
--- /dev/null
+++ b/src/lib/libast/comp/tempnam.c
@@ -0,0 +1,58 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * tempnam implementation
+ */
+
+#include <ast_std.h>
+
+#ifdef tempnam
+#define _def_tempnam 1
+#else
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide tempnam
+#else
+#define tempnam ______tempnam
+#endif
+#endif
+
+#include <ast.h>
+#include <stdio.h>
+
+#if !_def_tempnam
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide tempnam
+#else
+#undef tempnam
+#endif
+#endif
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char*
+tempnam(const char* dir, const char* pfx)
+{
+ return pathtmp(NiL, dir, pfx, NiL);
+}
diff --git a/src/lib/libast/comp/tmpnam.c b/src/lib/libast/comp/tmpnam.c
new file mode 100644
index 0000000..543ccdb
--- /dev/null
+++ b/src/lib/libast/comp/tmpnam.c
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * tmpnam implementation
+ */
+
+#define tmpnam ______tmpnam
+
+#include <ast.h>
+#include <stdio.h>
+
+#undef tmpnam
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#ifndef L_tmpnam
+#define L_tmpnam 25
+#endif
+
+extern char*
+tmpnam(char* s)
+{
+ static char buf[L_tmpnam];
+
+ return pathtemp(s ? s : buf, L_tmpnam, NiL, "tn", NiL);
+}
diff --git a/src/lib/libast/comp/transition.c b/src/lib/libast/comp/transition.c
new file mode 100644
index 0000000..ba65370
--- /dev/null
+++ b/src/lib/libast/comp/transition.c
@@ -0,0 +1,86 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * transient code to aid transition between releases
+ */
+
+#include <ast.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#define STUB 1
+
+/*
+ * 2006-09-28
+ *
+ * on some systems the _std_strtol iffe changed (due to a faulty
+ * test prototype) and the cause programs dynamically linked to
+ * an updated -last to fail at runtime with missing _ast_strtol etc.
+ */
+
+#if !_std_strtol
+
+#ifndef strtol
+#undef STUB
+extern long
+_ast_strtol(const char* a, char** b, int c)
+{
+ return strtol(a, b, c);
+}
+#endif
+
+#ifndef strtoul
+#undef STUB
+extern unsigned long
+_ast_strtoul(const char* a, char** b, int c)
+{
+ return strtoul(a, b, c);
+}
+#endif
+
+#ifndef strtoll
+#undef STUB
+extern intmax_t
+_ast_strtoll(const char* a, char** b, int c)
+{
+ return strtoll(a, b, c);
+}
+#endif
+
+#ifndef strtoull
+#undef STUB
+extern uintmax_t
+_ast_strtoull(const char* a, char** b, int c)
+{
+ return strtoull(a, b, c);
+}
+#endif
+
+#endif
+
+#if STUB
+NoN(transition)
+#endif
diff --git a/src/lib/libast/comp/tsearch.c b/src/lib/libast/comp/tsearch.c
new file mode 100644
index 0000000..486f082
--- /dev/null
+++ b/src/lib/libast/comp/tsearch.c
@@ -0,0 +1,240 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * tsearch() for systems that have <search.h> but no tsearch()
+ * why would such a system provide the interface but not the
+ * implementation? that's what happens when one slimes their
+ * way through standards compliance
+ *
+ * NOTE: please excuse the crude feature test
+ */
+
+#if !_UWIN
+
+void _STUB_tsearch(){}
+
+#else
+
+#if _PACKAGE_ast
+#include <ast.h>
+#endif
+
+#define tdelete ______tdelete
+#define tfind ______tfind
+#define tsearch ______tsearch
+#define twalk ______twalk
+
+#include <search.h>
+
+#undef tdelete
+#undef tfind
+#undef tsearch
+#undef twalk
+
+#include "dthdr.h"
+
+extern Void_t* dtfinger(Dt_t*);
+
+/* POSIX tsearch library based on libcdt
+** Written by Kiem-Phong Vo (AT&T Research, 07/19/95)
+*/
+
+typedef struct _tree_s
+{ Dtlink_t link;
+ Void_t* key;
+} Tree_t;
+
+typedef struct _treedisc_s
+{ Dtdisc_t disc;
+ int(* comparf)_ARG_((const Void_t*, const Void_t*));
+} Treedisc_t;
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+/* compare function */
+#if __STD_C
+static int treecompare(Dt_t* dt, char* one, char* two, Dtdisc_t* disc)
+#else
+static int treecompare(dt, one, two, disc)
+Dt_t* dt;
+char* one;
+char* two;
+Dtdisc_t* disc;
+#endif
+{
+ return (*((Treedisc_t*)disc)->comparf)((Void_t*)one,(Void_t*)two);
+}
+
+static Treedisc_t Treedisc =
+{ { sizeof(Dtlink_t), -1, /* object is key */
+ 0,
+ NIL(Dtmake_f), NIL(Dtfree_f),
+ treecompare,
+ NIL(Dthash_f),
+ NIL(Dtmemory_f),
+ NIL(Dtevent_f)
+ },
+ 0
+};
+
+extern
+#if __STD_C
+Void_t* tsearch(const Void_t* key, Void_t** rootp,
+ int(*comparf)(const Void_t*,const Void_t*) )
+#else
+Void_t* tsearch(key, rootp, comparf)
+Void_t* key;
+Void_t** rootp;
+int(* comparf)();
+#endif
+{
+ reg Dt_t* dt;
+ reg Tree_t* o;
+
+ if(!rootp ||
+ (!(dt = *((Dt_t**)rootp)) && !(dt = dtopen((Dtdisc_t*)(&Treedisc),Dtoset))) )
+ return NIL(Void_t*);
+
+ /* dangerous to set comparf on each call but that's tsearch */
+ Treedisc.comparf = comparf;
+
+ if(!(o = (Tree_t*)dtmatch(dt,key)) )
+ { if(!(o = (Tree_t*)malloc(sizeof(Tree_t))) )
+ return NIL(Void_t*);
+ o->key = (Void_t*)key;
+ dtinsert(dt,o);
+ }
+
+ if(o)
+ *rootp = (Void_t*)dt;
+ else if(*rootp == NIL(Void_t*) )
+ dtclose(dt);
+
+ return (Void_t*)(&o->key);
+}
+
+extern
+#if __STD_C
+Void_t* tfind(const Void_t* key, Void_t*const* rootp,
+ int(*comparf)(const Void_t*, const Void_t*) )
+#else
+Void_t* tfind(key, rootp, comparf)
+Void_t* key;
+Void_t** rootp;
+int(* comparf)();
+#endif
+{
+ reg Dt_t* dt;
+ reg Tree_t* o;
+
+ if(!rootp || !(dt = *((Dt_t**)rootp)) )
+ return NIL(Void_t*);
+ Treedisc.comparf = comparf;
+
+ return (o = (Tree_t*)dtmatch(dt,key)) ? (Void_t*)(&o->key) : NIL(Void_t*);
+}
+
+/* the original tdelete() specifies that it will return the parent pointer
+** in the tree if there is one. Since we are using a splay tree, a deleted
+** node is always rotated to the root first. So this implementation always
+** returns the key of the new root.
+*/
+extern
+#if __STD_C
+Void_t* tdelete(const Void_t* key, Void_t** rootp,
+ int(*comparf)(const Void_t*, const Void_t*) )
+#else
+Void_t* tdelete(key, rootp, comparf)
+Void_t* key;
+Void_t** rootp;
+int(* comparf)();
+#endif
+{
+ reg Dt_t* dt;
+ reg Tree_t* o;
+ Tree_t obj;
+
+ if(!rootp || !(dt = *((Dt_t**)rootp)) )
+ return NIL(Void_t*);
+
+ Treedisc.comparf = comparf;
+
+ obj.key = (Void_t*)key;
+ dtdelete(dt,&obj);
+
+ if(!(o = dtfinger(dt)) )
+ { dtclose(dt);
+ *rootp = NIL(Void_t*);
+ }
+
+ return o ? (Void_t*)(&o->key) : NIL(Void_t*);
+}
+
+/* the below routine assumes a particular layout of Dtlink_t.
+** If this ever gets changed, this routine should be redone.
+*/
+#define lchild link.lh.__left
+#define rchild link.rh.__rght
+
+#if __STD_C
+static void _twalk(Tree_t* obj, void(*action)(const Void_t*,VISIT,int), int level)
+#else
+static void _twalk(obj,action,level)
+Tree_t* obj;
+void(* action)();
+int level;
+#endif
+{ if(!obj->lchild && !obj->rchild)
+ (*action)((Void_t*)obj,leaf,level);
+ else
+ { (*action)((Void_t*)obj,preorder,level);
+ if(obj->lchild)
+ _twalk((Tree_t*)obj->lchild,action,level+1);
+ (*action)((Void_t*)obj,postorder,level);
+ if(obj->rchild)
+ _twalk((Tree_t*)obj->rchild,action,level+1);
+ (*action)((Void_t*)obj,endorder,level);
+ }
+}
+
+/* the original twalk allows specifying arbitrary node to start traversal.
+** Since our root is a dictionary structure, the search here will start
+** at whichever node happens to be current root.
+*/
+extern
+#if __STD_C
+void twalk(const Void_t* root, void(*action)(const Void_t*,VISIT,int) )
+#else
+void twalk(root, action)
+Void_t* root;
+void(* action)();
+#endif
+{
+ reg Tree_t* o;
+
+ if(root && (o = (Tree_t*)dtfinger((Dt_t*)root)) )
+ _twalk(o,action,0);
+}
+
+#endif
diff --git a/src/lib/libast/comp/unlink.c b/src/lib/libast/comp/unlink.c
new file mode 100644
index 0000000..5450848
--- /dev/null
+++ b/src/lib/libast/comp/unlink.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_unlink
+
+NoN(unlink)
+
+#else
+
+int
+unlink(const char* path)
+{
+ return(remove(path));
+}
+
+#endif
diff --git a/src/lib/libast/comp/unsetenv.c b/src/lib/libast/comp/unsetenv.c
new file mode 100644
index 0000000..867892a
--- /dev/null
+++ b/src/lib/libast/comp/unsetenv.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#define unsetenv ______unsetenv
+
+#include <ast.h>
+
+#undef unsetenv
+
+#if _lib_unsetenv
+
+NoN(unsetenv)
+
+#else
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern void
+unsetenv(const char *name)
+{
+ if (!strchr(name, '='))
+ setenviron(name);
+}
+
+#endif
diff --git a/src/lib/libast/comp/vfork.c b/src/lib/libast/comp/vfork.c
new file mode 100644
index 0000000..dfe2fd6
--- /dev/null
+++ b/src/lib/libast/comp/vfork.c
@@ -0,0 +1,55 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_vfork
+
+NoN(vfork)
+
+#else
+
+#include <error.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+#undef vfork
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern pid_t
+vfork(void)
+{
+#if _lib_fork
+ return(fork());
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+#endif
diff --git a/src/lib/libast/comp/waitpid.c b/src/lib/libast/comp/waitpid.c
new file mode 100644
index 0000000..2995b19
--- /dev/null
+++ b/src/lib/libast/comp/waitpid.c
@@ -0,0 +1,199 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * POSIX waitpid()
+ *
+ * pid < -1 WUNTRACED may not be fully supported
+ * process group specifics ignored by non-{waitpid,wait4}
+ */
+
+#include <ast.h>
+#include <wait.h>
+
+#if _lib_waitpid
+
+NoN(waitpid)
+
+#else
+
+#if _lib_wait4
+
+struct rusage;
+
+extern int wait4(int, int*, int, struct rusage*);
+
+pid_t
+waitpid(pid_t pid, int* status, int flags)
+{
+ return(wait4(pid, status, flags, NiL));
+}
+
+#else
+
+#undef SIGCLD
+
+#if _lib_wait3
+
+extern int wait3(int*, int, struct rusage*);
+
+#else
+
+#if _lib_wait2
+
+#define wait3(s,f,u) wait2(s,f)
+
+extern int wait2(int*, int);
+
+#else
+
+#include <sig.h>
+
+#define wait3(s,f,u) wait(s)
+
+static int caught;
+
+static void
+catch(sig)
+int sig;
+{
+ NoP(sig);
+ caught = 1;
+}
+
+#endif
+
+#endif
+
+#include <error.h>
+
+struct zombie
+{
+ struct zombie* next;
+ int status;
+ pid_t pid;
+};
+
+pid_t
+waitpid(pid_t pid, int* status, int flags)
+{
+ register struct zombie* zp;
+ register struct zombie* pp;
+ register int p;
+ int s;
+#if !_lib_wait2 && !_lib_wait3
+#if !defined(SIGCLD)
+ int n;
+ int oerrno;
+#endif
+ Sig_handler_t handler;
+#endif
+
+ static struct zombie* zombies;
+
+ pp = 0;
+ zp = zombies;
+ while (zp)
+ {
+ if (zp->pid >= 0 && (zp->pid == pid || pid <= 0))
+ {
+ if (pp) pp->next = zp->next;
+ else zombies = zp->next;
+ if (status) *status = zp->status;
+ pid = zp->pid;
+ free(zp);
+ return(pid);
+ }
+ }
+ if (pid > 0 && kill(pid, 0) < 0) return(-1);
+ for (;;)
+ {
+#if !_lib_wait2 && !_lib_wait3
+#if !defined(SIGCLD)
+ oerrno = errno;
+#endif
+ if (flags & WNOHANG)
+ {
+ caught = 0;
+#if defined(SIGCLD)
+ handler = signal(SIGCLD, catch);
+ if (!caught)
+ {
+ signal(SIGCLD, handler);
+ return(0);
+ }
+#else
+#if defined(SIGALRM)
+ handler = signal(SIGALRM, catch);
+ n = alarm(1);
+#endif
+#endif
+ }
+#endif
+ p = wait3(&s, flags, NiL);
+#if !_lib_wait3
+#if !_lib_wait2
+#if defined(SIGCLD)
+ if (flags & WNOHANG) signal(SIGCLD, handler);
+#else
+#if defined(SIGALRM)
+ if (flags & WNOHANG)
+ {
+ if (n == 0 && !caught || n == 1) alarm(n);
+ else if (n > 1) alarm(n - caught);
+ signal(SIGALRM, handler);
+ }
+ if (p == -1 && errno == EINTR)
+ {
+ errno = oerrno;
+ p = 0;
+ s = 0;
+ }
+#endif
+#endif
+#else
+ if (p == -1 && errno == EINVAL && (flags & ~WNOHANG))
+ p = wait3(&s, flags & WNOHANG, NiL);
+#endif
+#endif
+ if (p <= 0)
+ {
+ if (p == 0 && status) *status = s;
+ return(p);
+ }
+ if (pid <= 0 || p == pid)
+ {
+ if (status) *status = s;
+ return(p);
+ }
+ if (!(zp = newof(0, struct zombie, 1, 0))) return(-1);
+ zp->pid = p;
+ zp->status = s;
+ zp->next = zombies;
+ zombies = zp;
+ }
+ /*NOTREACHED*/
+}
+
+#endif
+
+#endif
diff --git a/src/lib/libast/comp/wc.c b/src/lib/libast/comp/wc.c
new file mode 100644
index 0000000..521b55a
--- /dev/null
+++ b/src/lib/libast/comp/wc.c
@@ -0,0 +1,139 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * NOTE: mbs* and wcs* are provided to avoid link errors only
+ */
+
+#include <ast.h>
+#include <wchar.h>
+
+#define STUB 1
+
+#if !_lib_mbtowc
+#undef STUB
+size_t
+mbtowc(wchar_t* t, const char* s, size_t n)
+{
+ if (t && n > 0)
+ *t = *s;
+ return 1;
+}
+#endif
+
+#if !_lib_mbrtowc
+#undef STUB
+size_t
+mbrtowc(wchar_t* t, const char* s, size_t n, mbstate_t* q)
+{
+#if _lib_mbtowc
+#undef STUB
+ memset(q, 0, sizeof(*q));
+ return mbtowc(t, s, n);
+#else
+ *q = 0;
+ if (t && n > 0)
+ *t = *s;
+ return 1;
+#endif
+}
+#endif
+
+#if !_lib_mbstowcs
+#undef STUB
+size_t
+mbstowcs(wchar_t* t, const char* s, size_t n)
+{
+ register wchar_t* p = t;
+ register wchar_t* e = t + n;
+ register unsigned char* u = (unsigned char*)s;
+
+ if (t)
+ while (p < e && (*p++ = *u++));
+ else
+ while (p++, *u++);
+ return p - t;
+}
+#endif
+
+#if !_lib_wctomb
+#undef STUB
+int
+wctomb(char* s, wchar_t c)
+{
+ if (s)
+ *s = c;
+ return 1;
+}
+#endif
+
+#if !_lib_wcrtomb
+#undef STUB
+size_t
+wcrtomb(char* s, wchar_t c, mbstate_t* q)
+{
+#if _lib_wctomb
+#undef STUB
+ memset(q, 0, sizeof(*q));
+ return wctomb(s, c);
+#else
+ if (s)
+ *s = c;
+ *q = 0;
+ return 1;
+#endif
+}
+#endif
+
+#if !_lib_wcslen
+#undef STUB
+size_t
+wcslen(const wchar_t* s)
+{
+ register const wchar_t* p = s;
+
+ while (*p)
+ p++;
+ return p - s;
+}
+#endif
+
+#if !_lib_wcstombs
+#undef STUB
+size_t
+wcstombs(char* t, register const wchar_t* s, size_t n)
+{
+ register char* p = t;
+ register char* e = t + n;
+
+ if (t)
+ while (p < e && (*p++ = *s++));
+ else
+ while (p++, *s++);
+ return p - t;
+}
+#endif
+
+#if STUB
+NoN(wc)
+#endif
diff --git a/src/lib/libast/comp/wordexp.c b/src/lib/libast/comp/wordexp.c
new file mode 100644
index 0000000..33016dc
--- /dev/null
+++ b/src/lib/libast/comp/wordexp.c
@@ -0,0 +1,217 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * POSIX 1003.2 wordexp implementation
+ */
+
+#include <ast.h>
+#include <wordexp.h>
+#include <stak.h>
+
+struct list
+{
+ struct list *next;
+};
+
+/*
+ * elimnates shell quoting as inserted with sh_fmtq
+ * result relaces <string>
+ * length of resulting string is returned.
+ */
+static int sh_unquote(char* string)
+{
+ register char *sp=string, *dp;
+ register int c;
+ while((c= *sp) && c!='\'')
+ sp++;
+ if(c==0)
+ return(sp-string);
+ if((dp=sp) > string && sp[-1]=='$')
+ {
+ register int n=stresc(sp+1);
+ /* copy all but trailing ' */
+ while(--n>0)
+ *dp++ = *++sp;
+ }
+ else
+ {
+ while((c= *++sp) && c!='\'')
+ *dp++ = c;
+ }
+ *dp=0;
+ return(dp-string);
+}
+
+int wordexp(const char *string, wordexp_t *wdarg, register int flags)
+{
+ register Sfio_t *iop;
+ register char *cp=(char*)string;
+ register int c,quoted=0,literal=0,ac=0;
+ int offset;
+ char *savebase,**av;
+ if(offset=staktell())
+ savebase = stakfreeze(0);
+ if(flags&WRDE_REUSE)
+ wordfree(wdarg);
+ else if(!(flags&WRDE_APPEND))
+ {
+ wdarg->we_wordv = 0;
+ wdarg->we_wordc = 0;
+ }
+ if(flags&WRDE_UNDEF)
+ stakwrite("set -u\n",7);
+ if(!(flags&WRDE_SHOWERR))
+ stakwrite("exec 2> /dev/null\n",18);
+ stakwrite("print -f \"%q\\n\" ",16);
+ if(*cp=='#')
+ stakputc('\\');
+ while(c = *cp++)
+ {
+ if(c=='\'' && !quoted)
+ literal = !literal;
+ else if(!literal)
+ {
+ if(c=='\\' && (!quoted || strchr("\\\"`\n$",c)))
+ {
+ stakputc('\\');
+ if(c= *cp)
+ cp++;
+ else
+ c = '\\';
+ }
+ else if(c=='"')
+ quoted = !quoted;
+ else if(c=='`' || (c=='$' && *cp=='('))
+ {
+ if(flags&WRDE_NOCMD)
+ {
+ c=WRDE_CMDSUB;
+ goto err;
+ }
+ /* only the shell can parse the rest */
+ stakputs(cp-1);
+ break;
+ }
+ else if(!quoted && strchr("|&\n;<>"+ac,c))
+ {
+ c=WRDE_BADCHAR;
+ goto err;
+ }
+ else if(c=='(') /* allow | and & inside pattern */
+ ac=2;
+ }
+ stakputc(c);
+ }
+ stakputc(0);
+ if(!(iop = sfpopen((Sfio_t*)0,stakptr(0),"r")))
+ {
+ c = WRDE_NOSHELL;
+ goto err;
+ }
+ stakseek(0);
+ ac = 0;
+ while((c=sfgetc(iop)) != EOF)
+ {
+ if(c=='\'')
+ quoted = ! quoted;
+ else if(!quoted && (c==' ' || c=='\n'))
+ {
+ ac++;
+ c = 0;
+ }
+ stakputc(c);
+ }
+ if(c=sfclose(iop))
+ {
+ if(c==3 || !(flags&WRDE_UNDEF))
+ c=WRDE_SYNTAX;
+ else
+ c=WRDE_BADVAL;
+ goto err;
+ }
+ c = ac+2;
+ if(flags&WRDE_DOOFFS)
+ c += wdarg->we_offs;
+ if(flags&WRDE_APPEND)
+ av = (char**)realloc((void*)&wdarg->we_wordv[-1], (wdarg->we_wordc+c)*sizeof(char*));
+ else if(av = (char**)malloc(c*sizeof(char*)))
+ {
+ if(flags&WRDE_DOOFFS)
+ memset((void*)av,0,(wdarg->we_offs+1)*sizeof(char*));
+ else
+ av[0] = 0;
+ }
+ if(!av)
+ return(WRDE_NOSPACE);
+ c = staktell();
+ if(!(cp = (char*)malloc(sizeof(char*)+c)))
+ {
+ c=WRDE_NOSPACE;
+ goto err;
+ }
+ ((struct list*)cp)->next = (struct list*)(*av);
+ *av++ = (char*)cp;
+ cp += sizeof(char*);
+ wdarg->we_wordv = av;
+ if(flags&WRDE_APPEND)
+ av += wdarg->we_wordc;
+ wdarg->we_wordc += ac;
+ if(flags&WRDE_DOOFFS)
+ av += wdarg->we_offs;
+ memcpy((void*)cp,stakptr(offset),c);
+ while(ac-- > 0)
+ {
+ *av++ = cp;
+ sh_unquote(cp);
+ while(c= *cp++);
+ }
+ *av = 0;
+ c=0;
+err:
+ if(offset)
+ stakset(savebase,offset);
+ else
+ stakseek(0);
+ return(c);
+}
+
+/*
+ * free fields in <wdarg>
+ */
+int wordfree(register wordexp_t *wdarg)
+{
+ struct list *arg, *argnext;
+ if(wdarg->we_wordv)
+ {
+ argnext = (struct list*)wdarg->we_wordv[-1];
+ while(arg=argnext)
+ {
+ argnext = arg->next;
+ free((void*)arg);
+ }
+ free((void*)&wdarg->we_wordv[-1]);
+ wdarg->we_wordv = 0;
+ }
+ wdarg->we_wordc=0;
+ return(0);
+}
diff --git a/src/lib/libast/comp/wordexp.h b/src/lib/libast/comp/wordexp.h
new file mode 100644
index 0000000..69a1bb4
--- /dev/null
+++ b/src/lib/libast/comp/wordexp.h
@@ -0,0 +1,63 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * posix wordexp interface definitions
+ */
+
+#ifndef _WORDEXP_H
+#define _WORDEXP_H
+
+#include <ast_common.h>
+
+#define WRDE_APPEND 01
+#define WRDE_DOOFFS 02
+#define WRDE_NOCMD 04
+#define WRDE_NOSYS 0100
+#define WRDE_REUSE 010
+#define WRDE_SHOWERR 020
+#define WRDE_UNDEF 040
+
+#define WRDE_BADCHAR 1
+#define WRDE_BADVAL 2
+#define WRDE_CMDSUB 3
+#define WRDE_NOSPACE 4
+#define WRDE_SYNTAX 5
+#define WRDE_NOSHELL 6
+
+typedef struct _wdarg
+{
+ size_t we_wordc;
+ char **we_wordv;
+ size_t we_offs;
+} wordexp_t;
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int wordexp(const char*, wordexp_t*, int);
+extern int wordfree(wordexp_t*);
+
+#undef extern
+
+#endif /* _WORDEXP_H */
diff --git a/src/lib/libast/dir/dirlib.h b/src/lib/libast/dir/dirlib.h
new file mode 100644
index 0000000..509ed0c
--- /dev/null
+++ b/src/lib/libast/dir/dirlib.h
@@ -0,0 +1,174 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Research
+ *
+ * directory stream access library private definitions
+ * library routines should include this file rather than <dirent.h>
+ */
+
+#ifndef _DIRLIB_H
+#define _DIRLIB_H
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide getdents getdirentries
+#else
+#undef getdents
+#define getdents ______getdents
+#undef getdirentries
+#define getdirentries ______getdirentries
+#endif
+
+#include <ast.h>
+#include <errno.h>
+
+#if _lib_opendir && ( _hdr_dirent || _hdr_ndir || _sys_dir )
+
+#define _dir_ok 1
+
+#include <ls.h>
+
+#ifndef _DIRENT_H
+#if _hdr_dirent
+#if _typ_off64_t
+#undef off_t
+#endif
+#include <dirent.h>
+#if _typ_off64_t
+#define off_t off64_t
+#endif
+#else
+#if _hdr_ndir
+#include <ndir.h>
+#else
+#include <sys/dir.h>
+#endif
+#ifndef dirent
+#define dirent direct
+#endif
+#endif
+#endif
+
+#define DIRdirent dirent
+
+#else
+
+#define dirent DIRdirent
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide DIR closedir opendir readdir seekdir telldir
+#else
+#undef DIR
+#define DIR ______DIR
+#undef closedir
+#define closedir ______closedir
+#undef opendir
+#define opendir ______opendir
+#undef readdir
+#define readdir ______readdir
+#undef seekdir
+#define seekdir ______seekdir
+#undef telldir
+#define telldir ______telldir
+#endif
+
+#include <ast_param.h>
+
+#include <ls.h>
+#include <limits.h>
+
+#ifndef _DIRENT_H
+#if _hdr_dirent
+#if _typ_off64_t
+#undef off_t
+#endif
+#include <dirent.h>
+#if _typ_off64_t
+#define off_t off64_t
+#endif
+#else
+#if _hdr_direntry
+#include <direntry.h>
+#else
+#include <sys/dir.h>
+#endif
+#endif
+#endif
+
+#undef dirent
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide DIR closedir opendir readdir seekdir telldir
+#else
+#undef DIR
+#undef closedir
+#undef opendir
+#undef readdir
+#undef seekdir
+#undef telldir
+#endif
+
+#define _DIR_PRIVATE_ \
+ int dd_loc; /* offset in block */ \
+ int dd_size; /* valid data in block */ \
+ char* dd_buf; /* directory block */
+
+#ifdef _BLD_3d
+#define DIR DIRDIR
+#endif
+#undef _DIRENT_H
+#include "dirstd.h"
+#ifndef _DIRENT_H
+#define _DIRENT_H 1
+#endif
+#ifdef _BLD_3d
+#undef DIR
+#endif
+
+#ifndef DIRBLKSIZ
+#ifdef DIRBLK
+#define DIRBLKSIZ DIRBLK
+#else
+#ifdef DIRBUF
+#define DIRBLKSIZ DIRBUF
+#else
+#define DIRBLKSIZ 8192
+#endif
+#endif
+#endif
+
+#endif
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide getdents getdirentries
+#else
+#undef getdents
+#undef getdirentries
+#endif
+
+#ifndef errno
+extern int errno;
+#endif
+
+extern ssize_t getdents(int, void*, size_t);
+
+#endif
diff --git a/src/lib/libast/dir/dirstd.h b/src/lib/libast/dir/dirstd.h
new file mode 100644
index 0000000..79dc6ea
--- /dev/null
+++ b/src/lib/libast/dir/dirstd.h
@@ -0,0 +1,63 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Bell Laboratories
+ *
+ * <dirent.h> for systems with no opendir()
+ */
+
+#ifndef _DIRENT_H
+#define _DIRENT_H
+
+typedef struct
+{
+ int dd_fd; /* file descriptor */
+#ifdef _DIR_PRIVATE_
+ _DIR_PRIVATE_
+#endif
+} DIR;
+
+struct dirent
+{
+ long d_fileno; /* entry serial number */
+ int d_reclen; /* entry length */
+ int d_namlen; /* entry name length */
+ char d_name[1]; /* entry name */
+};
+
+#ifndef _BLD_3d
+
+#ifdef rewinddir
+#undef rewinddir
+#define rewinddir(p) seekdir(p,0L)
+#endif
+
+extern DIR* opendir(const char*);
+extern void closedir(DIR*);
+extern struct dirent* readdir(DIR*);
+extern void seekdir(DIR*, long);
+extern long telldir(DIR*);
+
+#endif
+
+#endif
diff --git a/src/lib/libast/dir/getdents.c b/src/lib/libast/dir/getdents.c
new file mode 100644
index 0000000..22228cd
--- /dev/null
+++ b/src/lib/libast/dir/getdents.c
@@ -0,0 +1,166 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "dirlib.h"
+
+#if _dir_ok || _lib_getdents
+
+NoN(getdents)
+
+#else
+
+/*
+ * getdents
+ *
+ * read directory entries into directory block
+ *
+ * NOTE: directory entries must fit within DIRBLKSIZ boundaries
+ */
+
+#ifndef MAXNAMLEN
+#define MAXNAMLEN 255
+#endif
+
+#if _lib_dirread
+extern int dirread(int, char*, int);
+#endif
+#if _lib_getdirentries
+extern int getdirentries(int, char*, int, long*);
+#endif
+
+ssize_t
+getdents(int fd, void* buf, size_t siz)
+{
+ struct stat st;
+
+ if (siz < DIRBLKSIZ)
+ {
+ errno = EINVAL;
+ return(-1);
+ }
+ if (fstat(fd, &st)) return(-1);
+ if (!S_ISDIR(st.st_mode))
+ {
+#ifdef ENOTDIR
+ errno = ENOTDIR;
+#else
+ errno = EBADF;
+#endif
+ return(-1);
+ }
+#if _lib_getdirentries
+ {
+ long off;
+ return(getdirentries(fd, buf, siz, &off));
+ }
+#else
+#if _lib_dirread
+ {
+ register char* sp; /* system */
+ register struct dirent* up; /* user */
+ char* u;
+ int n;
+ int m;
+ int i;
+
+ m = (siz * 6) / 10;
+ m = roundof(m, 8);
+ sp = (char*)buf + siz - m - 1;
+ if (!(n = dirread(fd, sp, m))) return(0);
+ if (n > 0)
+ {
+ up = (struct dirent*)buf;
+ sp[n] = 0;
+ while (sp < (char*)buf + siz - m + n)
+ {
+ i = 0;
+ while (*sp >= '0' && *sp <= '9')
+ i = 10 * i + *sp++ - '0';
+ while (*sp && *sp != '\t') sp++;
+ if (*sp++)
+ {
+ up->d_fileno = i;
+ u = up->d_name;
+ while ((*u = *sp++) && u < up->d_name + MAXNAMLEN) u++;
+ *u = 0;
+ up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - up->d_name) + 1;
+ up->d_reclen = roundof(up->d_reclen, 8);
+ up = (struct dirent*)((char*)up + up->d_reclen);
+ }
+ }
+ return((char*)up - (char*)buf);
+ }
+ }
+#else
+#if _mem_d_reclen_direct
+ return(read(fd, buf, siz));
+#else
+ {
+
+#define MAXREC roundof(sizeof(*up)-sizeof(up->d_name)+sizeof(sp->d_name)+1,8)
+
+ register struct direct* sp; /* system */
+ register struct dirent* up; /* user */
+ register char* s;
+ register char* u;
+ int n;
+ int m;
+ char tmp[sizeof(sp->d_name) + 1];
+
+ /*
+ * we assume sizeof(struct dirent) > sizeof(struct direct)
+ */
+
+ up = (struct dirent*)buf;
+ n = (siz / MAXREC) * sizeof(struct direct);
+ if ((!(m = n & ~511) || m < MAXREC) && (!(m = n & ~255) || m < MAXREC)) m = n;
+ do
+ {
+ if ((n = read(fd, (char*)buf + siz - m, m)) <= 0) break;
+ sp = (struct direct*)((char*)buf + siz - m);
+ while (sp < (struct direct*)((char*)buf + siz - m + n))
+ {
+ if (sp->d_ino)
+ {
+ up->d_fileno = sp->d_ino;
+ s = sp->d_name;
+ u = tmp;
+ while (s < sp->d_name + sizeof(sp->d_name) && *s)
+ *u++ = *s++;
+ *u = 0;
+ strcpy(up->d_name, tmp);
+ up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - tmp) + 1;
+ up->d_reclen = roundof(up->d_reclen, 8);
+ up = (struct dirent*)((char*)up + up->d_reclen);
+ }
+ sp++;
+ }
+ } while (up == (struct dirent*)buf);
+ return((char*)up - (char*)buf);
+ }
+#endif
+#endif
+#endif
+}
+
+#endif
diff --git a/src/lib/libast/dir/opendir.c b/src/lib/libast/dir/opendir.c
new file mode 100644
index 0000000..bb9177e
--- /dev/null
+++ b/src/lib/libast/dir/opendir.c
@@ -0,0 +1,95 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * opendir, closedir
+ *
+ * open|close directory stream
+ *
+ * POSIX compatible directory stream access routines:
+ *
+ * #include <sys/types.h>
+ * #include <dirent.h>
+ *
+ * NOTE: readdir() returns a pointer to struct dirent
+ */
+
+#include "dirlib.h"
+
+#if _dir_ok
+
+NoN(opendir)
+
+#else
+
+static const char id_dir[] = "\n@(#)$Id: directory (AT&T Research) 1993-04-01 $\0\n";
+
+static DIR* freedirp; /* always keep one dirp */
+
+DIR*
+opendir(register const char* path)
+{
+ register DIR* dirp = 0;
+ register int fd;
+ struct stat st;
+
+ if ((fd = open(path, O_RDONLY)) < 0) return(0);
+ if (fstat(fd, &st) < 0 ||
+ !S_ISDIR(st.st_mode) && (errno = ENOTDIR) ||
+ fcntl(fd, F_SETFD, FD_CLOEXEC) ||
+ !(dirp = freedirp ? freedirp :
+#if defined(_DIR_PRIVATE_) || _ptr_dd_buf
+ newof(0, DIR, 1, DIRBLKSIZ)
+#else
+ newof(0, DIR, 1, 0)
+#endif
+ ))
+ {
+ close(fd);
+ if (dirp)
+ {
+ if (!freedirp) freedirp = dirp;
+ else free(dirp);
+ }
+ return(0);
+ }
+ freedirp = 0;
+ dirp->dd_fd = fd;
+ dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
+#if defined(_DIR_PRIVATE_) || _ptr_dd_buf
+ dirp->dd_buf = (void*)((char*)dirp + sizeof(DIR));
+#endif
+ return(dirp);
+}
+
+void
+closedir(register DIR* dirp)
+{
+ if (dirp)
+ {
+ close(dirp->dd_fd);
+ if (!freedirp) freedirp = dirp;
+ else free(dirp);
+ }
+}
+
+#endif
diff --git a/src/lib/libast/dir/readdir.c b/src/lib/libast/dir/readdir.c
new file mode 100644
index 0000000..1c595b7
--- /dev/null
+++ b/src/lib/libast/dir/readdir.c
@@ -0,0 +1,61 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * readdir
+ *
+ * read from directory stream
+ *
+ * NOTE: directory entries must fit within DIRBLKSIZ boundaries
+ */
+
+#include "dirlib.h"
+
+#if _dir_ok
+
+NoN(readdir)
+
+#else
+
+struct dirent*
+readdir(register DIR* dirp)
+{
+ register struct dirent* dp;
+
+ for (;;)
+ {
+ if (dirp->dd_loc >= dirp->dd_size)
+ {
+ if (dirp->dd_size < 0) return(0);
+ dirp->dd_loc = 0;
+ if ((dirp->dd_size = getdents(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
+ return(0);
+ }
+ dp = (struct dirent*)((char*)dirp->dd_buf + dirp->dd_loc);
+ if (dp->d_reclen <= 0) return(0);
+ dirp->dd_loc += dp->d_reclen;
+ if (dp->d_fileno) return(dp);
+ }
+ /*NOTREACHED*/
+}
+
+#endif
diff --git a/src/lib/libast/dir/rewinddir.c b/src/lib/libast/dir/rewinddir.c
new file mode 100644
index 0000000..244690a
--- /dev/null
+++ b/src/lib/libast/dir/rewinddir.c
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * rewinddir
+ *
+ * rewind directory stream
+ * provided for POSIX compatibility
+ */
+
+#include "dirlib.h"
+
+#if _dir_ok && ( defined(rewinddir) || _lib_rewinddir )
+
+NoN(rewinddir)
+
+#else
+
+#undef rewinddir
+
+void
+rewinddir(DIR* dirp)
+{
+ seekdir(dirp, 0L);
+}
+
+#endif
diff --git a/src/lib/libast/dir/seekdir.c b/src/lib/libast/dir/seekdir.c
new file mode 100644
index 0000000..8113584
--- /dev/null
+++ b/src/lib/libast/dir/seekdir.c
@@ -0,0 +1,56 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * seekdir
+ *
+ * seek on directory stream
+ * this is not optimal because there aren't portable
+ * semantics for directory seeks
+ */
+
+#include "dirlib.h"
+
+#if _dir_ok
+
+NoN(seekdir)
+
+#else
+
+void
+seekdir(register DIR* dirp, long loc)
+{
+ off_t base; /* file location of block */
+ off_t offset; /* offset within block */
+
+ if (telldir(dirp) != loc)
+ {
+ lseek(dirp->dd_fd, 0L, SEEK_SET);
+ dirp->dd_loc = dirp->dd_size = 0;
+ while (telldir(dirp) != loc)
+ if (!readdir(dirp))
+ break; /* "can't happen" */
+ }
+}
+
+#endif
diff --git a/src/lib/libast/dir/telldir.c b/src/lib/libast/dir/telldir.c
new file mode 100644
index 0000000..611d9e7
--- /dev/null
+++ b/src/lib/libast/dir/telldir.c
@@ -0,0 +1,43 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * telldir
+ *
+ * get directory stream pointer offset for seekdir()
+ */
+
+#include "dirlib.h"
+
+#if _dir_ok
+
+NoN(telldir)
+
+#else
+
+long
+telldir(DIR* dirp)
+{
+ return(lseek(dirp->dd_fd, 0L, SEEK_CUR) + (long)dirp->dd_loc);
+}
+
+#endif
diff --git a/src/lib/libast/disc/memfatal.c b/src/lib/libast/disc/memfatal.c
new file mode 100644
index 0000000..9016d36
--- /dev/null
+++ b/src/lib/libast/disc/memfatal.c
@@ -0,0 +1,82 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * install error message handler for fatal malloc exceptions
+ */
+
+#include <ast.h>
+#include <error.h>
+#include <vmalloc.h>
+
+#include "FEATURE/vmalloc"
+
+#if _std_malloc
+
+void
+memfatal(void)
+{
+}
+
+#else
+
+/*
+ * print message and fail on VM_BADADDR,VM_NOMEM
+ */
+
+static int
+nomalloc(Vmalloc_t* region, int type, void* obj, Vmdisc_t* disc)
+{
+ Vmstat_t st;
+
+ NoP(disc);
+ switch (type)
+ {
+#ifdef VM_BADADDR
+ case VM_BADADDR:
+ error(ERROR_SYSTEM|3, "invalid pointer %p passed to free or realloc", obj);
+ return(-1);
+#endif
+ case VM_NOMEM:
+ vmstat(region, &st);
+ error(ERROR_SYSTEM|3, "storage allocator out of space on %lu byte request ( region %lu segments %lu busy %lu:%lu:%lu free %lu:%lu:%lu )", (size_t)obj, st.extent, st.n_seg, st.n_busy, st.s_busy, st.m_busy, st.n_free, st.s_free, st.m_free);
+ return(-1);
+ }
+ return(0);
+}
+
+/*
+ * initialize the malloc exception handler
+ */
+
+void
+memfatal(void)
+{
+ Vmdisc_t* disc;
+
+ malloc(0);
+ if (disc = vmdisc(Vmregion, NiL))
+ disc->exceptf = nomalloc;
+}
+
+#endif
diff --git a/src/lib/libast/disc/sfdcdio.c b/src/lib/libast/disc/sfdcdio.c
new file mode 100644
index 0000000..e8277f1
--- /dev/null
+++ b/src/lib/libast/disc/sfdcdio.c
@@ -0,0 +1,229 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfdchdr.h"
+
+/* Discipline to turn on direct IO capability.
+** This currently only works for XFS on SGI's.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998.
+*/
+
+#ifndef FDIRECT
+#undef F_FIOINFO
+#endif
+
+typedef struct _direct_s
+{ Sfdisc_t disc; /* Sfio discipline */
+ int cntl; /* file control flags */
+#ifdef F_DIOINFO
+ struct dioattr dio; /* direct IO params */
+#endif
+} Direct_t;
+
+/* convert a pointer to an int */
+#define P2I(p) (Sfulong_t)((char*)(p) - (char*)0)
+
+#if __STD_C
+static ssize_t diordwr(Sfio_t* f, Void_t* buf, size_t n, Direct_t* di, int type)
+#else
+static ssize_t diordwr(f, buf, n, di, type)
+Sfio_t* f;
+Void_t* buf;
+size_t n;
+Direct_t* di;
+int type;
+#endif
+{
+ size_t rw, done;
+ ssize_t rv;
+
+ done = 0; /* amount processed by direct IO */
+ rv = 0;
+
+#ifdef F_DIOINFO
+ if((P2I(buf)%di->dio.d_mem) == 0 &&
+ (f->here%di->dio.d_miniosz) == 0 && n >= di->dio.d_miniosz )
+ { /* direct IO ok, make sure we're in the right mode */
+ if(!(di->cntl & FDIRECT) )
+ { di->cntl |= FDIRECT;
+ (void)fcntl(f->file, F_SETFL, di->cntl);
+ }
+
+ for(rw = (n/di->dio.d_miniosz)*di->dio.d_miniosz;; )
+ { size_t io;
+
+ if((io = rw) > di->dio.d_maxiosz )
+ io = di->dio.d_maxiosz;
+ if(type == SF_READ)
+ rv = read(f->file,buf,io);
+ else rv = write(f->file,buf,io);
+
+ if(rv > 0)
+ { rw -= rv; done += rv;
+ buf = (Void_t*)((char*)buf + rv);
+ }
+
+ if(rv < io || rw < di->dio.d_miniosz)
+ break;
+ }
+ }
+
+ if(done < n && (di->cntl & FDIRECT) )
+ { /* turn off directIO for remaining IO operation */
+ di->cntl &= ~FDIRECT;
+ (void)fcntl(f->file, F_SETFL, di->cntl);
+ }
+#endif /*F_DIOINFO*/
+
+ if((rw = n-done) > 0 &&
+ (rv = type == SF_READ ? read(f->file,buf,rw) : write(f->file,buf,rw)) > 0 )
+ done += rv;
+
+ return done ? done : rv;
+}
+
+#if __STD_C
+static ssize_t dioread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+static ssize_t dioread(f, buf, n, disc)
+Sfio_t* f;
+Void_t* buf;
+size_t n;
+Sfdisc_t* disc;
+#endif
+{
+ return diordwr(f, buf, n, (Direct_t*)disc, SF_READ);
+}
+
+#if __STD_C
+static ssize_t diowrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+static ssize_t diowrite(f, buf, n, disc)
+Sfio_t* f;
+Void_t* buf;
+size_t n;
+Sfdisc_t* disc;
+#endif
+{
+ return diordwr(f, (Void_t*)buf, n, (Direct_t*)disc, SF_WRITE);
+}
+
+#if __STD_C
+static int dioexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
+#else
+static int dioexcept(f,type,data,disc)
+Sfio_t* f;
+int type;
+Void_t* data;
+Sfdisc_t* disc;
+#endif
+{
+ Direct_t* di = (Direct_t*)disc;
+
+ if(type == SF_FINAL || type == SF_DPOP)
+ {
+#ifdef F_DIOINFO
+ if(di->cntl&FDIRECT)
+ { di->cntl &= ~FDIRECT;
+ (void)fcntl(f->file,F_SETFL,di->cntl);
+ }
+#endif
+ free(disc);
+ }
+
+ return 0;
+}
+
+#if __STD_C
+int sfdcdio(Sfio_t* f, size_t bufsize)
+#else
+int sfdcdio(f, bufsize)
+Sfio_t* f;
+size_t bufsize;
+#endif
+{
+#ifndef F_DIOINFO
+ return -1;
+#else
+ int cntl;
+ struct dioattr dio;
+ Void_t* buf;
+ Direct_t* di;
+
+ if(f->extent < 0 || (f->flags&SF_STRING))
+ return -1;
+
+ if((cntl = fcntl(f->file,F_GETFL,0)) < 0)
+ return -1;
+
+ if(!(cntl&FDIRECT) )
+ { cntl |= FDIRECT;
+ if(fcntl(f->file,F_SETFL,cntl) < 0)
+ return -1;
+ }
+
+ if(fcntl(f->file,F_DIOINFO,&dio) < 0)
+ goto no_direct;
+
+ if(bufsize > 0)
+ bufsize = (bufsize/dio.d_miniosz)*dio.d_miniosz;
+ if(bufsize <= 0)
+ bufsize = dio.d_miniosz*64;
+ if(bufsize > dio.d_maxiosz)
+ bufsize = dio.d_maxiosz;
+
+ if(!(di = (Direct_t*)malloc(sizeof(Direct_t))) )
+ goto no_direct;
+
+ if(!(buf = (Void_t*)memalign(dio.d_mem,bufsize)) )
+ { free(di);
+ goto no_direct;
+ }
+
+ sfsetbuf(f,buf,bufsize);
+ if(sfsetbuf(f,buf,0) == buf)
+ sfset(f,SF_MALLOC,1);
+ else
+ { free(buf);
+ free(di);
+ goto no_direct;
+ }
+
+ di->disc.readf = dioread;
+ di->disc.writef = diowrite;
+ di->disc.seekf = NIL(Sfseek_f);
+ di->disc.exceptf = dioexcept;
+ di->cntl = cntl;
+ di->dio = dio;
+
+ if(sfdisc(f,(Sfdisc_t*)di) != (Sfdisc_t*)di)
+ { free(di);
+ no_direct:
+ cntl &= ~FDIRECT;
+ (void)fcntl(f->file,F_SETFL,cntl);
+ return -1;
+ }
+
+ return 0;
+
+#endif /*F_DIOINFO*/
+}
diff --git a/src/lib/libast/disc/sfdcdos.c b/src/lib/libast/disc/sfdcdos.c
new file mode 100644
index 0000000..15b7865
--- /dev/null
+++ b/src/lib/libast/disc/sfdcdos.c
@@ -0,0 +1,416 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfdchdr.h"
+
+/* Discipline to turn \r\n into \n.
+** This is useful to deal with DOS text files.
+**
+** Written by David Korn (03/18/1998).
+*/
+
+#define MINMAP 8
+#define CHUNK 1024
+
+struct map
+{
+ Sfoff_t logical;
+ Sfoff_t physical;
+};
+
+typedef struct _dosdisc
+{
+ Sfdisc_t disc;
+ struct map *maptable;
+ int mapsize;
+ int maptop;
+ Sfoff_t lhere;
+ Sfoff_t llast;
+ Sfoff_t lmax;
+ Sfoff_t pmax;
+ Sfoff_t phere;
+ Sfoff_t plast;
+ Sfoff_t begin;
+ int skip;
+ void *buff;
+ char last;
+ char extra;
+ int bsize;
+} Dosdisc_t;
+
+#if __STD_C
+static void addmapping(register Dosdisc_t *dp)
+#else
+static void addmapping(dp)
+register Dosdisc_t *dp;
+#endif
+{
+ register int n;
+ if((n=dp->maptop++)>=dp->mapsize)
+ {
+ dp->mapsize *= 2;
+ if(!(dp->maptable=(struct map*)realloc((void*)dp->maptable,(dp->mapsize+1)*sizeof(struct map))))
+ {
+ dp->maptop--;
+ dp->mapsize *= 2;
+ return;
+ }
+ }
+ dp->maptable[n].physical = dp->phere;
+ dp->maptable[n].logical = dp->lhere;
+ dp->maptable[dp->maptop].logical=0;
+}
+
+#if __STD_C
+static struct map *getmapping(Dosdisc_t *dp, Sfoff_t offset, register int whence)
+#else
+static struct map *getmapping(dp, offset, whence)
+Dosdisc_t *dp;
+Sfoff_t offset;
+register int whence;
+#endif
+{
+ register struct map *mp;
+ static struct map dummy;
+ if(offset <= dp->begin)
+ {
+ dummy.logical = dummy.physical = offset;
+ return(&dummy);
+ }
+ if(!(mp=dp->maptable))
+ {
+ dummy.logical = dp->begin;
+ dummy.physical = dummy.logical+1;
+ return(&dummy);
+ }
+ while((++mp)->logical && (whence==SEEK_CUR?mp->physical:mp->logical) <= offset);
+ return(mp-1);
+}
+
+#if __STD_C
+static ssize_t dos_read(Sfio_t *iop, void *buff, size_t size, Sfdisc_t* disc)
+#else
+static ssize_t dos_read(iop, buff, size, disc)
+Sfio_t *iop;
+void *buff;
+size_t size;
+Sfdisc_t* disc;
+#endif
+{
+ register Dosdisc_t *dp = (Dosdisc_t*)disc;
+ register char *cp = (char*)buff, *first, *cpmax;
+ register int n, count, m;
+ if(dp->extra)
+ {
+ dp->extra=0;
+ *cp = dp->last;
+ return(1);
+ }
+ while(1)
+ {
+ if((n = sfrd(iop,buff,size,disc)) <= 0)
+ return(n);
+ dp->plast=dp->phere;
+ dp->phere +=n;
+ dp->llast = dp->lhere;
+ cpmax = cp+n-1;
+ if(dp->last=='\r' && *cp!='\n')
+ {
+ /* should insert a '\r' */ ;
+ }
+ dp->last = *cpmax;
+ if(n>1)
+ break;
+ if(dp->last!='\r')
+ {
+ dp->lhere++;
+ return(1);
+ }
+ }
+ if(dp->last=='\r')
+ n--;
+ else if(dp->last!='\n' || cpmax[-1]!='\r')
+ *cpmax = '\r';
+ dp->lhere += n;
+ while(1)
+ {
+ while(*cp++ != '\r');
+ if(cp > cpmax || *cp=='\n')
+ break;
+ }
+ dp->skip = cp-1 - (char*)buff;
+ /* if not \r\n in buffer, just return */
+ if((count = cpmax+1-cp) <=0)
+ {
+ *cpmax = dp->last;
+ if(!dp->maptable)
+ dp->begin +=n;
+ dp->skip++;
+ count=0;
+ goto done;
+ }
+ if(!dp->maptable)
+ {
+ dp->begin += cp - (char*)buff-1;
+ if(dp->maptable=(struct map*)malloc((MINMAP+1)*sizeof(struct map)))
+ {
+ dp->mapsize = MINMAP;
+ dp->maptable[0].logical= dp->begin;
+ dp->maptable[0].physical = dp->maptable[0].logical+1;
+ dp->maptable[1].logical=0;
+ dp->maptop = 1;
+ }
+ }
+ /* save original discipline inside buffer */
+ if(count>dp->bsize)
+ {
+ if(dp->bsize==0)
+ dp->buff = malloc(count);
+ else
+ dp->buff = realloc(dp->buff,count);
+ dp->bsize = count;
+ if(!dp->buff)
+ return(-1);
+ }
+ memcpy(dp->buff, cp, count);
+ count=1;
+ while(1)
+ {
+ first=cp;
+ if(cp==cpmax)
+ cp++;
+ else
+ while(*cp++ != '\r');
+ if(cp<=cpmax && *cp!='\n')
+ continue;
+ if((m=(cp-first)-1) >0)
+ memcpy(first-count, first, m);
+ if(cp > cpmax)
+ break;
+ count++;
+ }
+ cpmax[-count] = dp->last;
+ dp->lhere -= count;
+done:
+ if(dp->lhere>dp->lmax)
+ {
+ dp->lmax = dp->lhere;
+ dp->pmax = dp->phere;
+ if(dp->maptable && dp->lmax > dp->maptable[dp->maptop-1].logical+CHUNK)
+ addmapping(dp);
+ }
+ return(n-count);
+}
+
+/*
+ * returns the current offset
+ * <offset> must be in the current buffer
+ * if <whence> is SEEK_CUR, physical offset converted to logical offset
+ * otherwise, logical offset is converted to physical offset
+ */
+#if __STD_C
+static Sfoff_t cur_offset(Dosdisc_t *dp, Sfoff_t offset,Sfio_t *iop,register int whence)
+#else
+static Sfoff_t cur_offset(dp, offset, iop, whence)
+Dosdisc_t *dp;
+Sfoff_t offset;
+Sfio_t *iop;
+register int whence;
+#endif
+{
+ register Sfoff_t n,m=0;
+ register char *cp;
+
+ if(whence==SEEK_CUR)
+ {
+ whence= -1;
+ n = offset - dp->plast;
+ iop->next = iop->data + n;
+ offset = dp->llast;
+ }
+ else
+ {
+ whence = 1;
+ n = offset - dp->llast;
+ offset = dp->plast;
+ }
+ offset +=n;
+ if((n -= dp->skip) > 0)
+ {
+ m=whence;
+ cp = (char*)dp->buff;
+ while(n--)
+ {
+ if(*cp++=='\r' && *cp=='\n')
+ {
+ m += whence;
+ if(whence>0)
+ n++;
+ }
+ }
+ }
+ if(whence<0)
+ iop->next += m;
+ return(offset+m);
+}
+
+#if __STD_C
+static Sfoff_t dos_seek(Sfio_t *iop, Sfoff_t offset, register int whence, Sfdisc_t* disc)
+#else
+static Sfoff_t dos_seek(iop, offset, whence, disc)
+Sfio_t *iop;
+Sfoff_t offset;
+register int whence;
+Sfdisc_t* disc;
+#endif
+{
+ register Dosdisc_t *dp = (Dosdisc_t*)disc;
+ struct map dummy, *mp=0;
+ Sfoff_t physical;
+ register int n,size;
+retry:
+ switch(whence)
+ {
+ case SEEK_CUR:
+ offset = sfsk(iop, (Sfoff_t)0,SEEK_CUR,disc);
+ if(offset<=dp->begin)
+ return(offset);
+ /* check for seek outside buffer */
+ if(offset==dp->phere)
+ return(dp->lhere);
+ else if(offset==dp->plast)
+ return(dp->llast);
+ else if(offset<dp->plast || offset>dp->phere)
+ mp = getmapping(dp,offset,whence);
+ break;
+ case SEEK_SET:
+ /* check for seek outside buffer */
+ if(offset<dp->llast || offset > dp->lhere)
+ mp = getmapping(dp,offset,whence);
+ break;
+ case SEEK_END:
+ if(!dp->maptable)
+ return(sfsk(iop,offset,SEEK_END,disc));
+ mp = &dummy;
+ mp->physical = dp->plast;
+ mp->logical = dp->llast;
+ break;
+ }
+ if(sfsetbuf(iop,(char*)iop,0))
+ size = sfvalue(iop);
+ else
+ size = iop->endb-iop->data;
+ if(mp)
+ {
+ sfsk(iop,mp->physical,SEEK_SET,disc);
+ dp->phere = mp->physical;
+ dp->lhere = mp->logical;
+ if((*disc->readf)(iop,iop->data,size,disc)<0)
+ return(-1);
+ }
+ while(1)
+ {
+ if(whence==SEEK_CUR && dp->phere>=offset)
+ break;
+ if(whence==SEEK_SET && dp->lhere>=offset)
+ break;
+ n=(*disc->readf)(iop,iop->data,size,disc);
+ if(n < 0)
+ return(-1);
+ if(n==0)
+ {
+ if(whence==SEEK_END && offset<0)
+ {
+ offset = dp->lhere;
+ whence=SEEK_SET;
+ goto retry;
+ }
+ break;
+ }
+ }
+ if(whence==SEEK_END)
+ offset += dp->lhere;
+ else
+ {
+ physical = cur_offset(dp,offset,iop,whence);
+ if(whence==SEEK_SET)
+ {
+ sfsk(iop, physical ,SEEK_SET,disc);
+ dp->phere = physical;
+ dp->lhere = offset;
+ }
+ else
+ offset = physical;
+ }
+ return(offset);
+}
+
+#if __STD_C
+static int dos_except(Sfio_t *iop, int type, void *arg, Sfdisc_t *disc)
+#else
+static int dos_except(iop, type, arg, disc)
+Sfio_t *iop;
+int type;
+void *arg;
+Sfdisc_t *disc;
+#endif
+{
+ register Dosdisc_t *dp = (Dosdisc_t*)disc;
+ if(type==SF_DPOP || type==SF_FINAL)
+ {
+ if(dp->bsize>0)
+ free((void*)dp->buff);
+ if(dp->mapsize)
+ free((void*)dp->maptable);
+ free((void*)disc);
+ }
+ return(0);
+}
+
+#if __STD_C
+int sfdcdos(Sfio_t *f)
+#else
+int sfdcdos(f)
+Sfio_t *f;
+#endif
+{
+ Dosdisc_t *dos;
+
+ /* this is a readonly discipline */
+ if(sfset(f,0,0)&SF_WRITE)
+ return(-1);
+
+ if(!(dos = (Dosdisc_t*)malloc(sizeof(Dosdisc_t))) )
+ return -1;
+ memset(dos,'\0',sizeof(Dosdisc_t));
+
+ dos->disc.readf = dos_read;
+ dos->disc.writef = NIL(Sfwrite_f);
+ dos->disc.seekf = dos_seek;
+ dos->disc.exceptf = dos_except;
+
+ if(sfdisc(f,(Sfdisc_t*)dos) != (Sfdisc_t*)dos)
+ { free(dos);
+ return -1;
+ }
+
+ return(0);
+}
diff --git a/src/lib/libast/disc/sfdcfilter.c b/src/lib/libast/disc/sfdcfilter.c
new file mode 100644
index 0000000..16a2219
--- /dev/null
+++ b/src/lib/libast/disc/sfdcfilter.c
@@ -0,0 +1,186 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfdchdr.h"
+
+/* Discipline to invoke UNIX processes as data filters.
+** These processes must be able to fit in pipelines.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998.
+*/
+
+typedef struct _filter_s
+{ Sfdisc_t disc; /* discipline structure */
+ Sfio_t* filter; /* the filter stream */
+ char* next; /* data unwritten */
+ char* endb; /* end of data */
+ char raw[4096]; /* raw data buffer */
+} Filter_t;
+
+/* read data from the filter */
+#if __STD_C
+static ssize_t filterread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+static ssize_t filterread(f, buf, n, disc)
+Sfio_t* f; /* stream reading from */
+Void_t* buf; /* buffer to read into */
+size_t n; /* number of bytes requested */
+Sfdisc_t* disc; /* discipline */
+#endif
+{
+ Filter_t* fi;
+ ssize_t r, w;
+
+ fi = (Filter_t*)disc;
+ for(;;)
+ {
+ /* get some raw data to stuff down the pipe */
+ if(fi->next && fi->next >= fi->endb )
+ { if((r = sfrd(f,fi->raw,sizeof(fi->raw),disc)) > 0)
+ { fi->next = fi->raw;
+ fi->endb = fi->raw+r;
+ }
+ else
+ { /* eof, close write end of pipes */
+ sfset(fi->filter,SF_READ,0);
+ close(sffileno(fi->filter));
+ sfset(fi->filter,SF_READ,1);
+ fi->next = fi->endb = NIL(char*);
+ }
+ }
+
+ if(fi->next && (w = fi->endb - fi->next) > 0 )
+ { /* see if pipe is ready for write */
+ sfset(fi->filter, SF_READ, 0);
+ r = sfpoll(&fi->filter, 1, 1);
+ sfset(fi->filter, SF_READ, 1);
+
+ if(r == 1) /* non-blocking write */
+ { errno = 0;
+ if((w = sfwr(fi->filter, fi->next, w, 0)) > 0)
+ fi->next += w;
+ else if(errno != EAGAIN)
+ return 0;
+ }
+ }
+
+ /* see if pipe is ready for read */
+ sfset(fi->filter, SF_WRITE, 0);
+ w = sfpoll(&fi->filter, 1, fi->next ? 1 : -1);
+ sfset(fi->filter, SF_WRITE, 1);
+
+ if(!fi->next || w == 1) /* non-blocking read */
+ { errno = 0;
+ if((r = sfrd(fi->filter, buf, n, 0)) > 0)
+ return r;
+ if(errno != EAGAIN)
+ return 0;
+ }
+ }
+}
+
+#if __STD_C
+static ssize_t filterwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+static ssize_t filterwrite(f, buf, n, disc)
+Sfio_t* f; /* stream writing to */
+Void_t* buf; /* buffer to write into */
+size_t n; /* number of bytes requested */
+Sfdisc_t* disc; /* discipline */
+#endif
+{
+ return -1;
+}
+
+/* for the duration of this discipline, the stream is unseekable */
+#if __STD_C
+static Sfoff_t filterseek(Sfio_t* f, Sfoff_t addr, int offset, Sfdisc_t* disc)
+#else
+static Sfoff_t filterseek(f, addr, offset, disc)
+Sfio_t* f;
+Sfoff_t addr;
+int offset;
+Sfdisc_t* disc;
+#endif
+{ f = NIL(Sfio_t*);
+ addr = 0;
+ offset = 0;
+ disc = NIL(Sfdisc_t*);
+ return (Sfoff_t)(-1);
+}
+
+/* on close, remove the discipline */
+#if __STD_C
+static int filterexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
+#else
+static int filterexcept(f,type,data,disc)
+Sfio_t* f;
+int type;
+Void_t* data;
+Sfdisc_t* disc;
+#endif
+{
+ if(type == SF_FINAL || type == SF_DPOP)
+ { sfclose(((Filter_t*)disc)->filter);
+ free(disc);
+ }
+
+ return 0;
+}
+
+#if __STD_C
+int sfdcfilter(Sfio_t* f, const char* cmd)
+#else
+int sfdcfilter(f, cmd)
+Sfio_t* f; /* stream to filter data */
+char* cmd; /* program to run as a filter */
+#endif
+{
+ reg Filter_t* fi;
+ reg Sfio_t* filter;
+
+ /* open filter for read&write */
+ if(!(filter = sfpopen(NIL(Sfio_t*),cmd,"r+")) )
+ return -1;
+
+ /* unbuffered stream */
+ sfsetbuf(filter,NIL(Void_t*),0);
+
+ if(!(fi = (Filter_t*)malloc(sizeof(Filter_t))) )
+ { sfclose(filter);
+ return -1;
+ }
+
+ fi->disc.readf = filterread;
+ fi->disc.writef = filterwrite;
+ fi->disc.seekf = filterseek;
+ fi->disc.exceptf = filterexcept;
+ fi->filter = filter;
+ fi->next = fi->endb = fi->raw;
+
+ if(sfdisc(f,(Sfdisc_t*)fi) != (Sfdisc_t*)fi)
+ { sfclose(filter);
+ free(fi);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/lib/libast/disc/sfdchdr.h b/src/lib/libast/disc/sfdchdr.h
new file mode 100644
index 0000000..7e5bbca
--- /dev/null
+++ b/src/lib/libast/disc/sfdchdr.h
@@ -0,0 +1,28 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * common header for discipline functions
+ */
+
+#include "sfhdr.h"
+
+#include <sfdisc.h>
diff --git a/src/lib/libast/disc/sfdcmore.c b/src/lib/libast/disc/sfdcmore.c
new file mode 100644
index 0000000..900b55d
--- /dev/null
+++ b/src/lib/libast/disc/sfdcmore.c
@@ -0,0 +1,369 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfdchdr.h"
+
+#if _PACKAGE_ast
+#include <ast_tty.h>
+#include <signal.h>
+#endif
+
+/*
+ * a simple but fast more style pager discipline
+ * if on sfstdout then sfstdin ops reset the page state
+ *
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * @(#)$Id: sfdcmore (AT&T Research) 1998-06-25 $
+ */
+
+typedef struct
+{
+ Sfdisc_t disc; /* sfio discipline */
+ Sfio_t* input; /* tied with this input stream */
+ Sfio_t* error; /* tied with this error stream */
+ int rows; /* max rows */
+ int cols; /* max cols */
+ int row; /* current row */
+ int col; /* current col */
+ int match; /* match length, 0 if none */
+ char pattern[128]; /* match pattern */
+ char prompt[1]; /* prompt string */
+} More_t;
+
+/*
+ * more read
+ * we assume line-at-a-time input
+ */
+
+#if __STD_C
+static ssize_t moreread(Sfio_t* f, void* buf, size_t n, Sfdisc_t* dp)
+#else
+static ssize_t moreread(f, buf, n, dp)
+Sfio_t* f;
+void* buf;
+size_t n;
+Sfdisc_t* dp;
+#endif
+{
+ register More_t* more = (More_t*)dp;
+
+ more->match = 0;
+ more->row = 2;
+ more->col = 1;
+ return sfrd(f, buf, n, dp);
+}
+
+/*
+ * output label on wfd and return next char on rfd with no echo
+ * return < -1 is -(signal + 1)
+ */
+
+#if __STD_C
+static int ttyquery(Sfio_t* rp, Sfio_t* wp, const char* label, Sfdisc_t* dp)
+#else
+static int ttyquery(rp, wp, label, dp)
+Sfio_t* rp;
+Sfio_t* wp;
+char* label;
+Sfdisc_t* dp;
+#endif
+{
+ register int r;
+ int n;
+
+#ifdef TCSADRAIN
+ unsigned char c;
+ struct termios old;
+ struct termios tty;
+ int rfd = sffileno(rp);
+ int wfd = sffileno(rp);
+
+ if (!label)
+ n = 0;
+ else if (n = strlen(label))
+ write(wfd, label, n);
+ tcgetattr(rfd, &old);
+ tty = old;
+ tty.c_cc[VTIME] = 0;
+ tty.c_cc[VMIN] = 1;
+ tty.c_lflag &= ~(ICANON|ECHO|ECHOK|ISIG);
+ tcsetattr(rfd, TCSADRAIN, &tty);
+ if ((r = read(rfd, &c, 1)) == 1)
+ {
+ if (c == old.c_cc[VEOF])
+ r = -1;
+ else if (c == old.c_cc[VINTR])
+ r = -(SIGINT + 1);
+ else if (c == old.c_cc[VQUIT])
+ r = -(SIGQUIT + 1);
+ else if (c == '\r')
+ r = '\n';
+ else
+ r = c;
+ }
+ tcsetattr(rfd, TCSADRAIN, &old);
+ if (n)
+ {
+ write(wfd, "\r", 1);
+ while (n-- > 0)
+ write(wfd, " ", 1);
+ write(wfd, "\r", 1);
+ }
+#else
+ register char* s;
+
+ if (label && (n = strlen(label)))
+ sfwr(wp, label, n, dp);
+ r = (s = sfgetr(rp, '\n', 0)) ? *s : -1;
+#endif
+ return r;
+}
+
+/*
+ * more write
+ */
+
+#if __STD_C
+static ssize_t morewrite(Sfio_t* f, const Void_t* buf, register size_t n, Sfdisc_t* dp)
+#else
+static ssize_t morewrite(f, buf, n, dp)
+Sfio_t* f;
+Void_t* buf;
+register size_t n;
+Sfdisc_t* dp;
+#endif
+{
+ register More_t* more = (More_t*)dp;
+ register char* b;
+ register char* s;
+ register char* e;
+ register ssize_t w;
+ register int r;
+
+ if (!more->row)
+ return n;
+ if (!more->col)
+ return sfwr(f, buf, n, dp);
+ w = 0;
+ b = (char*)buf;
+ s = b;
+ e = s + n;
+ if (more->match)
+ {
+ match:
+ for (r = more->pattern[0];; s++)
+ {
+ if (s >= e)
+ return n;
+ if (*s == '\n')
+ b = s + 1;
+ else if (*s == r && (e - s) >= more->match && !strncmp(s, more->pattern, more->match))
+ break;
+ }
+ s = b;
+ w += b - (char*)buf;
+ more->match = 0;
+ }
+ while (s < e)
+ {
+ switch (*s++)
+ {
+ case '\t':
+ more->col = ((more->col + 8) & ~7) - 1;
+ /*FALLTHROUGH*/
+ default:
+ if (++more->col <= more->cols || s < e && *s == '\n')
+ continue;
+ /*FALLTHROUGH*/
+ case '\n':
+ more->col = 1;
+ if (++more->row < more->rows)
+ continue;
+ break;
+ case '\b':
+ if (more->col > 1)
+ more->col--;
+ continue;
+ case '\r':
+ more->col = 1;
+ continue;
+ }
+ w += sfwr(f, b, s - b, dp);
+ b = s;
+ r = ttyquery(sfstdin, f, more->prompt, dp);
+ if (r == '/' || r == 'n')
+ {
+ if (r == '/')
+ {
+ sfwr(f, "/", 1, dp);
+ if ((s = sfgetr(sfstdin, '\n', 1)) && (n = sfvalue(sfstdin) - 1) > 0)
+ {
+ if (n >= sizeof(more->pattern))
+ n = sizeof(more->pattern) - 1;
+ memcpy(more->pattern, s, n);
+ more->pattern[n] = 0;
+ }
+ }
+ if (more->match = strlen(more->pattern))
+ {
+ more->row = 1;
+ more->col = 1;
+ goto match;
+ }
+ }
+ switch (r)
+ {
+ case '\n':
+ case '\r':
+ more->row--;
+ more->col = 1;
+ break;
+ case ' ':
+ more->row = 2;
+ more->col = 1;
+ break;
+ default:
+ more->row = 0;
+ return n;
+ }
+ }
+ if (s > b)
+ w += sfwr(f, b, s - b, dp);
+ return w;
+}
+
+/*
+ * remove the discipline on close
+ */
+
+#if __STD_C
+static int moreexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* dp)
+#else
+static int moreexcept(f, type, data, dp)
+Sfio_t* f;
+int type;
+Void_t* data;
+Sfdisc_t* dp;
+#endif
+{
+ register More_t* more = (More_t*)dp;
+
+ if (type == SF_FINAL || type == SF_DPOP)
+ {
+ if (f = more->input)
+ {
+ more->input = 0;
+ sfdisc(f, SF_POPDISC);
+ }
+ else if (f = more->error)
+ {
+ more->error = 0;
+ sfdisc(f, SF_POPDISC);
+ }
+ else
+ free(dp);
+ }
+ else if (type == SF_SYNC)
+ {
+ more->match = 0;
+ more->row = 1;
+ more->col = 1;
+ }
+ return 0;
+}
+
+/*
+ * push the more discipline on f
+ * if prompt==0 then a default ansi prompt is used
+ * if rows==0 or cols==0 then they are deterimined from the tty
+ * if f==sfstdout then input on sfstdin also resets the state
+ */
+
+#if __STD_C
+int sfdcmore(Sfio_t* f, const char* prompt, int rows, int cols)
+#else
+int sfdcmore(f, prompt, rows, cols)
+Sfio_t* f;
+char* prompt;
+int rows;
+int cols;
+#endif
+{
+ register More_t* more;
+ size_t n;
+
+ /*
+ * this is a writeonly discipline for interactive io
+ */
+
+ if (!(sfset(f, 0, 0) & SF_WRITE) || !isatty(sffileno(sfstdin)) || !isatty(sffileno(sfstdout)))
+ return -1;
+ if (!prompt)
+ prompt = "\033[7m More\033[m";
+ n = strlen(prompt) + 1;
+ if (!(more = (More_t*)malloc(sizeof(More_t) + n)))
+ return -1;
+ memset(more, 0, sizeof(*more));
+
+ more->disc.readf = moreread;
+ more->disc.writef = morewrite;
+ more->disc.exceptf = moreexcept;
+ memcpy(more->prompt, prompt, n);
+ if (!rows || !cols)
+ {
+#if _PACKAGE_ast
+ astwinsize(sffileno(sfstdin), &rows, &cols);
+#endif
+ if (!rows)
+ rows = 24;
+ if (!cols)
+ cols = 80;
+ }
+ more->rows = rows;
+ more->cols = cols;
+ more->row = 1;
+ more->col = 1;
+
+ if (sfdisc(f, &more->disc) != &more->disc)
+ {
+ free(more);
+ return -1;
+ }
+ if (f == sfstdout)
+ {
+ if (sfdisc(sfstdin, &more->disc) != &more->disc)
+ {
+ sfdisc(f, SF_POPDISC);
+ return -1;
+ }
+ more->input = sfstdin;
+ if (sfdisc(sfstderr, &more->disc) != &more->disc)
+ {
+ sfdisc(f, SF_POPDISC);
+ return -1;
+ }
+ more->error = sfstdin;
+ }
+
+ return 0;
+}
diff --git a/src/lib/libast/disc/sfdcprefix.c b/src/lib/libast/disc/sfdcprefix.c
new file mode 100644
index 0000000..29f3fd4
--- /dev/null
+++ b/src/lib/libast/disc/sfdcprefix.c
@@ -0,0 +1,153 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfdchdr.h"
+
+/*
+ * a discipline that prepends a prefix string to each output line
+ *
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * @(#)$Id: sfdcprefix (AT&T Research) 1998-06-25 $
+ */
+
+typedef struct
+{
+ Sfdisc_t disc; /* sfio discipline */
+ size_t length; /* prefix length */
+ size_t empty; /* empty line prefix length */
+ int skip; /* this line already prefixed */
+ char prefix[1]; /* prefix string */
+} Prefix_t;
+
+/*
+ * prefix write
+ */
+
+#if __STD_C
+static ssize_t pfxwrite(Sfio_t* f, const Void_t* buf, register size_t n, Sfdisc_t* dp)
+#else
+static ssize_t pfxwrite(f, buf, n, dp)
+Sfio_t* f;
+Void_t* buf;
+register size_t n;
+Sfdisc_t* dp;
+#endif
+{
+ register Prefix_t* pfx = (Prefix_t*)dp;
+ register char* b;
+ register char* s;
+ register char* e;
+ register char* t;
+ register ssize_t w;
+ int skip;
+
+ skip = 0;
+ w = 0;
+ b = (char*)buf;
+ s = b;
+ e = s + n;
+ do
+ {
+ if (!(t = memchr(s, '\n', e - s)))
+ {
+ skip = 1;
+ t = e - 1;
+ }
+ n = t - s + 1;
+ if (pfx->skip)
+ pfx->skip = 0;
+ else
+ sfwr(f, pfx->prefix, n > 1 ? pfx->length : pfx->empty, dp);
+ w += sfwr(f, s, n, dp);
+ if ((s = t + 1) >= e)
+ return w;
+ } while ((s = t + 1) < e);
+ pfx->skip = skip;
+ return w;
+
+}
+
+/*
+ * remove the discipline on close
+ */
+
+#if __STD_C
+static int pfxexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* dp)
+#else
+static int pfxexcept(f, type, data, dp)
+Sfio_t* f;
+int type;
+Void_t* data;
+Sfdisc_t* dp;
+#endif
+{
+ if (type == SF_FINAL || type == SF_DPOP)
+ free(dp);
+ return 0;
+}
+
+/*
+ * push the prefix discipline on f
+ */
+
+#if __STD_C
+int sfdcprefix(Sfio_t* f, const char* prefix)
+#else
+int sfdcprefix(f, prefix)
+Sfio_t* f;
+char* prefix;
+#endif
+{
+ register Prefix_t* pfx;
+ register char* s;
+ size_t n;
+
+ /*
+ * this is a writeonly discipline
+ */
+
+ if (!prefix || !(n = strlen(prefix)) || !(sfset(f, 0, 0) & SF_WRITE))
+ return -1;
+ if (!(pfx = (Prefix_t*)malloc(sizeof(Prefix_t) + n)))
+ return -1;
+ memset(pfx, 0, sizeof(*pfx));
+
+ pfx->disc.writef = pfxwrite;
+ pfx->disc.exceptf = pfxexcept;
+ pfx->length = n;
+ memcpy(pfx->prefix, prefix, n);
+ s = (char*)prefix + n;
+ while (--s > (char*)prefix && (*s == ' ' || *s == '\t'));
+ n = s - (char*)prefix;
+ if (*s != ' ' || *s != '\t')
+ n++;
+ pfx->empty = n;
+
+ if (sfdisc(f, &pfx->disc) != &pfx->disc)
+ {
+ free(pfx);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/lib/libast/disc/sfdcseekable.c b/src/lib/libast/disc/sfdcseekable.c
new file mode 100644
index 0000000..23c5b93
--- /dev/null
+++ b/src/lib/libast/disc/sfdcseekable.c
@@ -0,0 +1,227 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfdchdr.h"
+
+/* Discipline to make an unseekable read stream seekable
+**
+** sfraise(f,SFSK_DISCARD,0) discards previous seek data
+** but seeks from current offset on still allowed
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998.
+*/
+
+typedef struct _skable_s
+{ Sfdisc_t disc; /* sfio discipline */
+ Sfio_t* shadow; /* to shadow data */
+ Sfoff_t discard;/* sfseek(f,-1,SEEK_SET) discarded data */
+ Sfoff_t extent; /* shadow extent */
+ int eof; /* if eof has been reached */
+} Seek_t;
+
+#if __STD_C
+static ssize_t skwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+static ssize_t skwrite(f, buf, n, disc)
+Sfio_t* f; /* stream involved */
+Void_t* buf; /* buffer to read into */
+size_t n; /* number of bytes to read */
+Sfdisc_t* disc; /* discipline */
+#endif
+{
+ return (ssize_t)(-1);
+}
+
+#if __STD_C
+static ssize_t skread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+static ssize_t skread(f, buf, n, disc)
+Sfio_t* f; /* stream involved */
+Void_t* buf; /* buffer to read into */
+size_t n; /* number of bytes to read */
+Sfdisc_t* disc; /* discipline */
+#endif
+{
+ Seek_t* sk;
+ Sfio_t* sf;
+ Sfoff_t addr;
+ ssize_t r, w, p;
+
+ sk = (Seek_t*)disc;
+ sf = sk->shadow;
+ if(sk->eof)
+ return sfread(sf,buf,n);
+
+ addr = sfseek(sf,(Sfoff_t)0,SEEK_CUR);
+
+ if(addr+n <= sk->extent)
+ return sfread(sf,buf,n);
+
+ if((r = (ssize_t)(sk->extent-addr)) > 0)
+ { if((w = sfread(sf,buf,r)) != r)
+ return w;
+ buf = (char*)buf + r;
+ n -= r;
+ }
+
+ /* do a raw read */
+ if((w = sfrd(f,buf,n,disc)) <= 0)
+ { sk->eof = 1;
+ w = 0;
+ }
+ else
+ {
+ if((p = sfwrite(sf,buf,w)) != w)
+ sk->eof = 1;
+ if(p > 0)
+ sk->extent += p;
+ }
+
+ return r+w;
+}
+
+#if __STD_C
+static Sfoff_t skseek(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc)
+#else
+static Sfoff_t skseek(f, addr, type, disc)
+Sfio_t* f;
+Sfoff_t addr;
+int type;
+Sfdisc_t* disc;
+#endif
+{
+ Seek_t* sk;
+ Sfio_t* sf;
+ char buf[SF_BUFSIZE];
+ ssize_t r, w;
+
+ sk = (Seek_t*)disc;
+ sf = sk->shadow;
+
+ switch (type)
+ {
+ case SEEK_SET:
+ addr -= sk->discard;
+ break;
+ case SEEK_CUR:
+ addr += sftell(sf);
+ break;
+ case SEEK_END:
+ addr += sk->extent;
+ break;
+ default:
+ return -1;
+ }
+
+ if(addr < 0)
+ return (Sfoff_t)(-1);
+ else if(addr > sk->extent)
+ { if(sk->eof)
+ return (Sfoff_t)(-1);
+
+ /* read enough to reach the seek point */
+ while(addr > sk->extent)
+ { if(addr > sk->extent+sizeof(buf) )
+ w = sizeof(buf);
+ else w = (int)(addr-sk->extent);
+ if((r = sfrd(f,buf,w,disc)) <= 0)
+ w = r-1;
+ else if((w = sfwrite(sf,buf,r)) > 0)
+ sk->extent += w;
+ if(w != r)
+ { sk->eof = 1;
+ break;
+ }
+ }
+
+ if(addr > sk->extent)
+ return (Sfoff_t)(-1);
+ }
+
+ return sfseek(sf,addr,SEEK_SET) + sk->discard;
+}
+
+/* on close, remove the discipline */
+#if __STD_C
+static int skexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
+#else
+static int skexcept(f,type,data,disc)
+Sfio_t* f;
+int type;
+Void_t* data;
+Sfdisc_t* disc;
+#endif
+{
+ Seek_t* sk;
+
+ sk = (Seek_t*)disc;
+
+ switch (type)
+ {
+ case SF_FINAL:
+ case SF_DPOP:
+ sfclose(sk->shadow);
+ free(disc);
+ break;
+ case SFSK_DISCARD:
+ sk->eof = 0;
+ sk->discard += sk->extent;
+ sk->extent = 0;
+ sfseek(sk->shadow,(Sfoff_t)0,SEEK_SET);
+ break;
+ }
+ return 0;
+}
+
+#if __STD_C
+int sfdcseekable(Sfio_t* f)
+#else
+int sfdcseekable(f)
+Sfio_t* f;
+#endif
+{
+ reg Seek_t* sk;
+
+ /* see if already seekable */
+ if(sfseek(f,(Sfoff_t)0,SEEK_CUR) >= 0)
+ return 0;
+
+ if(!(sk = (Seek_t*)malloc(sizeof(Seek_t))) )
+ return -1;
+ memset(sk, 0, sizeof(*sk));
+
+ sk->disc.readf = skread;
+ sk->disc.writef = skwrite;
+ sk->disc.seekf = skseek;
+ sk->disc.exceptf = skexcept;
+ sk->shadow = sftmp(SF_BUFSIZE);
+ sk->discard = 0;
+ sk->extent = 0;
+ sk->eof = 0;
+
+ if(sfdisc(f, (Sfdisc_t*)sk) != (Sfdisc_t*)sk)
+ { sfclose(sk->shadow);
+ free(sk);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/lib/libast/disc/sfdcslow.c b/src/lib/libast/disc/sfdcslow.c
new file mode 100644
index 0000000..e75f438
--- /dev/null
+++ b/src/lib/libast/disc/sfdcslow.c
@@ -0,0 +1,84 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfdchdr.h"
+
+/* Make a stream op return immediately on interrupts.
+** This is useful on slow streams (hence the name).
+**
+** Written by Glenn Fowler (03/18/1998).
+*/
+
+#if __STD_C
+static int slowexcept(Sfio_t* f, int type, Void_t* v, Sfdisc_t* disc)
+#else
+static int slowexcept(f, type, v, disc)
+Sfio_t* f;
+int type;
+Void_t* v;
+Sfdisc_t* disc;
+#endif
+{
+ NOTUSED(f);
+ NOTUSED(v);
+ NOTUSED(disc);
+
+ switch (type)
+ {
+ case SF_FINAL:
+ case SF_DPOP:
+ free(disc);
+ break;
+ case SF_READ:
+ case SF_WRITE:
+ if (errno == EINTR)
+ return(-1);
+ break;
+ }
+
+ return(0);
+}
+
+#if __STD_C
+int sfdcslow(Sfio_t* f)
+#else
+int sfdcslow(f)
+Sfio_t* f;
+#endif
+{
+ Sfdisc_t* disc;
+
+ if(!(disc = (Sfdisc_t*)malloc(sizeof(Sfdisc_t))) )
+ return(-1);
+
+ disc->readf = NIL(Sfread_f);
+ disc->writef = NIL(Sfwrite_f);
+ disc->seekf = NIL(Sfseek_f);
+ disc->exceptf = slowexcept;
+
+ if(sfdisc(f,disc) != disc)
+ { free(disc);
+ return(-1);
+ }
+ sfset(f,SF_IOINTR,1);
+
+ return(0);
+}
diff --git a/src/lib/libast/disc/sfdcsubstr.c b/src/lib/libast/disc/sfdcsubstr.c
new file mode 100644
index 0000000..c0fae9b
--- /dev/null
+++ b/src/lib/libast/disc/sfdcsubstr.c
@@ -0,0 +1,217 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfdchdr.h"
+
+
+/* Discipline to treat a contiguous segment of a stream as a stream
+** in its own right. The hard part in all this is to allow multiple
+** segments of the stream to be used as substreams at the same time.
+**
+** Written by David G. Korn and Kiem-Phong Vo (03/18/1998)
+*/
+
+typedef struct _subfile_s
+{
+ Sfdisc_t disc; /* sfio discipline */
+ Sfio_t* parent; /* parent stream */
+ Sfoff_t offset; /* starting offset */
+ Sfoff_t extent; /* size wanted */
+ Sfoff_t here; /* current seek location */
+} Subfile_t;
+
+#if __STD_C
+static ssize_t streamio(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc, int type)
+#else
+static ssize_t streamio(f, buf, n, disc, type)
+Sfio_t* f;
+Void_t* buf;
+size_t n;
+Sfdisc_t* disc;
+int type;
+#endif
+{
+ reg Subfile_t *su;
+ reg Sfoff_t here, parent;
+ reg ssize_t io;
+
+ su = (Subfile_t*)disc;
+
+ /* read just what we need */
+ if(su->extent >= 0 && (ssize_t)n > (io = (ssize_t)(su->extent - su->here)) )
+ n = io;
+ if(n <= 0)
+ return n;
+
+ /* save current location in parent stream */
+ parent = sfsk(f,(Sfoff_t)0,SEEK_CUR,disc);
+
+ /* read data */
+ here = su->here + su->offset;
+ if(sfsk(f,here,SEEK_SET,disc) != here)
+ io = 0;
+ else
+ { if(type == SF_WRITE)
+ io = sfwr(f,buf,n,disc);
+ else io = sfrd(f,buf,n,disc);
+ if(io > 0)
+ su->here += io;
+ }
+
+ /* restore parent current position */
+ sfsk(f,parent,SEEK_SET,disc);
+
+ return io;
+}
+
+#if __STD_C
+static ssize_t streamwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+static ssize_t streamwrite(f, buf, n, disc)
+Sfio_t* f;
+Void_t* buf;
+size_t n;
+Sfdisc_t* disc;
+#endif
+{
+ return streamio(f,(Void_t*)buf,n,disc,SF_WRITE);
+}
+
+#if __STD_C
+static ssize_t streamread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+static ssize_t streamread(f, buf, n, disc)
+Sfio_t* f;
+Void_t* buf;
+size_t n;
+Sfdisc_t* disc;
+#endif
+{
+ return streamio(f,buf,n,disc,SF_READ);
+}
+
+#if __STD_C
+static Sfoff_t streamseek(Sfio_t* f, Sfoff_t pos, int type, Sfdisc_t* disc)
+#else
+static Sfoff_t streamseek(f, pos, type, disc)
+Sfio_t* f;
+Sfoff_t pos;
+int type;
+Sfdisc_t* disc;
+#endif
+{
+ reg Subfile_t* su;
+ reg Sfoff_t here, parent;
+
+ su = (Subfile_t*)disc;
+
+ switch(type)
+ {
+ case SEEK_SET:
+ here = 0;
+ break;
+ case SEEK_CUR:
+ here = su->here;
+ break;
+ case SEEK_END:
+ if(su->extent >= 0)
+ here = su->extent;
+ else
+ { parent = sfsk(f,(Sfoff_t)0,SEEK_CUR,disc);
+ if((here = sfsk(f,(Sfoff_t)0,SEEK_END,disc)) < 0)
+ return -1;
+ else here -= su->offset;
+ sfsk(f,parent,SEEK_SET,disc);
+ }
+ break;
+ default:
+ return -1;
+ }
+
+ pos += here;
+ if(pos < 0 || (su->extent >= 0 && pos >= su->extent))
+ return -1;
+
+ return (su->here = pos);
+}
+
+#if __STD_C
+static int streamexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
+#else
+static int streamexcept(f, type, data, disc)
+Sfio_t* f;
+int type;
+Void_t* data;
+Sfdisc_t* disc;
+#endif
+{
+ if(type == SF_FINAL || type == SF_DPOP)
+ free(disc);
+ return 0;
+}
+
+#if __STD_C
+Sfio_t* sfdcsubstream(Sfio_t* f, Sfio_t* parent, Sfoff_t offset, Sfoff_t extent)
+#else
+Sfio_t* sfdcsubstream(f, parent, offset, extent)
+Sfio_t* f; /* stream */
+Sfio_t* parent; /* parent stream */
+Sfoff_t offset; /* offset in f */
+Sfoff_t extent; /* desired size */
+#endif
+{
+ reg Sfio_t* sp;
+ reg Subfile_t* su;
+ reg Sfoff_t here;
+
+ /* establish that we can seek to offset */
+ if((here = sfseek(parent,(Sfoff_t)0,SEEK_CUR)) < 0 || sfseek(parent,offset,SEEK_SET) < 0)
+ return 0;
+ else sfseek(parent,here,SEEK_SET);
+ sfpurge(parent);
+
+ if (!(sp = f) && !(sp = sfnew(NIL(Sfio_t*), NIL(Void_t*), (size_t)SF_UNBOUND, dup(sffileno(parent)), parent->flags)))
+ return 0;
+
+ if(!(su = (Subfile_t*)malloc(sizeof(Subfile_t))))
+ { if(sp != f)
+ sfclose(sp);
+ return 0;
+ }
+ memset(su, 0, sizeof(*su));
+
+ su->disc.readf = streamread;
+ su->disc.writef = streamwrite;
+ su->disc.seekf = streamseek;
+ su->disc.exceptf = streamexcept;
+ su->parent = parent;
+ su->offset = offset;
+ su->extent = extent;
+
+ if(sfdisc(sp, (Sfdisc_t*)su) != (Sfdisc_t*)su)
+ { free(su);
+ if(sp != f)
+ sfclose(sp);
+ return 0;
+ }
+
+ return sp;
+}
diff --git a/src/lib/libast/disc/sfdctee.c b/src/lib/libast/disc/sfdctee.c
new file mode 100644
index 0000000..66bf71e
--- /dev/null
+++ b/src/lib/libast/disc/sfdctee.c
@@ -0,0 +1,102 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfdchdr.h"
+
+/* A discipline to tee the output to a stream to another stream.
+** This is similar to what the "tee" program does. As implemented
+** this discipline only works with file streams.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998.
+*/
+
+/* the discipline structure for tee-ing */
+typedef struct _tee_s
+{ Sfdisc_t disc; /* the sfio discipline structure */
+ Sfio_t* tee; /* the stream to tee to */
+ int status; /* if tee stream is still ok */
+} Tee_t;
+
+/* write to the teed stream. */
+#if __STD_C
+static ssize_t teewrite(Sfio_t* f, const Void_t* buf, size_t size, Sfdisc_t* disc)
+#else
+static ssize_t teewrite(f,buf,size,disc)
+Sfio_t* f; /* the stream being written to */
+Void_t* buf; /* the buffer of data being output */
+size_t size; /* the data size */
+Sfdisc_t* disc; /* the tee discipline */
+#endif
+{
+ reg Tee_t* te = (Tee_t*)disc;
+
+ /* tee data if still ok */
+ if(te->status == 0 && sfwrite(te->tee,buf,size) != (ssize_t)size)
+ te->status = -1;
+
+ /* do the actual write */
+ return sfwr(f,buf,size,disc);
+}
+
+/* on close, remove the discipline */
+#if __STD_C
+static int teeexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
+#else
+static int teeexcept(f,type,data,disc)
+Sfio_t* f;
+int type;
+Void_t* data;
+Sfdisc_t* disc;
+#endif
+{
+ if(type == SF_FINAL || type == SF_DPOP)
+ free(disc);
+
+ return 0;
+}
+
+#if __STD_C
+int sfdctee(Sfio_t* f, Sfio_t* tee)
+#else
+int sfdctee(f, tee)
+Sfio_t* f; /* stream to tee from */
+Sfio_t* tee; /* stream to tee to */
+#endif
+{
+ reg Tee_t* te;
+
+ if(!(te = (Tee_t*)malloc(sizeof(Tee_t))) )
+ return -1;
+
+ te->disc.readf = NIL(Sfread_f);
+ te->disc.seekf = NIL(Sfseek_f);
+ te->disc.writef = teewrite;
+ te->disc.exceptf = teeexcept;
+ te->tee = tee;
+ te->status = 0;
+
+ if(sfdisc(f,(Sfdisc_t*)te) != (Sfdisc_t*)te)
+ { free(te);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/lib/libast/disc/sfdcunion.c b/src/lib/libast/disc/sfdcunion.c
new file mode 100644
index 0000000..1f45909
--- /dev/null
+++ b/src/lib/libast/disc/sfdcunion.c
@@ -0,0 +1,203 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfdchdr.h"
+
+
+/* Make a sequence of streams act like a single stream.
+** This is for reading only.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998.
+*/
+
+#define UNSEEKABLE 1
+
+typedef struct _file_s
+{ Sfio_t* f; /* the stream */
+ Sfoff_t lower; /* its lowest end */
+} File_t;
+
+typedef struct _union_s
+{
+ Sfdisc_t disc; /* discipline structure */
+ short type; /* type of streams */
+ short c; /* current stream */
+ short n; /* number of streams */
+ Sfoff_t here; /* current location */
+ File_t f[1]; /* array of streams */
+} Union_t;
+
+#if __STD_C
+static ssize_t unwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+static ssize_t unwrite(f, buf, n, disc)
+Sfio_t* f; /* stream involved */
+Void_t* buf; /* buffer to read into */
+size_t n; /* number of bytes to read */
+Sfdisc_t* disc; /* discipline */
+#endif
+{
+ return -1;
+}
+
+#if __STD_C
+static ssize_t unread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+static ssize_t unread(f, buf, n, disc)
+Sfio_t* f; /* stream involved */
+Void_t* buf; /* buffer to read into */
+size_t n; /* number of bytes to read */
+Sfdisc_t* disc; /* discipline */
+#endif
+{
+ reg Union_t* un;
+ reg ssize_t r, m;
+
+ un = (Union_t*)disc;
+ m = n;
+ f = un->f[un->c].f;
+ while(1)
+ { if((r = sfread(f,buf,m)) < 0 || (r == 0 && un->c == un->n-1) )
+ break;
+
+ m -= r;
+ un->here += r;
+
+ if(m == 0)
+ break;
+
+ buf = (char*)buf + r;
+ if(sfeof(f) && un->c < un->n-1)
+ f = un->f[un->c += 1].f;
+ }
+ return n-m;
+}
+
+#if __STD_C
+static Sfoff_t unseek(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc)
+#else
+static Sfoff_t unseek(f, addr, type, disc)
+Sfio_t* f;
+Sfoff_t addr;
+int type;
+Sfdisc_t* disc;
+#endif
+{
+ reg Union_t* un;
+ reg int i;
+ reg Sfoff_t extent, s;
+
+ un = (Union_t*)disc;
+ if(un->type&UNSEEKABLE)
+ return -1L;
+
+ if(type == 2)
+ { extent = 0;
+ for(i = 0; i < un->n; ++i)
+ extent += (sfsize(un->f[i].f) - un->f[i].lower);
+ addr += extent;
+ }
+ else if(type == 1)
+ addr += un->here;
+
+ if(addr < 0)
+ return -1;
+
+ /* find the stream where the addr could be in */
+ extent = 0;
+ for(i = 0; i < un->n-1; ++i)
+ { s = sfsize(un->f[i].f) - un->f[i].lower;
+ if(addr < extent + s)
+ break;
+ extent += s;
+ }
+
+ s = (addr-extent) + un->f[i].lower;
+ if(sfseek(un->f[i].f,s,0) != s)
+ return -1;
+
+ un->c = i;
+ un->here = addr;
+
+ for(i += 1; i < un->n; ++i)
+ sfseek(un->f[i].f,un->f[i].lower,0);
+
+ return addr;
+}
+
+/* on close, remove the discipline */
+#if __STD_C
+static int unexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
+#else
+static int unexcept(f,type,data,disc)
+Sfio_t* f;
+int type;
+Void_t* data;
+Sfdisc_t* disc;
+#endif
+{
+ if(type == SF_FINAL || type == SF_DPOP)
+ free(disc);
+
+ return 0;
+}
+
+#if __STD_C
+int sfdcunion(Sfio_t* f, Sfio_t** array, int n)
+#else
+int sfdcunion(f, array, n)
+Sfio_t* f;
+Sfio_t** array;
+int n;
+#endif
+{
+ reg Union_t* un;
+ reg int i;
+
+ if(n <= 0)
+ return -1;
+
+ if(!(un = (Union_t*)malloc(sizeof(Union_t)+(n-1)*sizeof(File_t))) )
+ return -1;
+ memset(un, 0, sizeof(*un));
+
+ un->disc.readf = unread;
+ un->disc.writef = unwrite;
+ un->disc.seekf = unseek;
+ un->disc.exceptf = unexcept;
+ un->n = n;
+
+ for(i = 0; i < n; ++i)
+ { un->f[i].f = array[i];
+ if(!(un->type&UNSEEKABLE))
+ { un->f[i].lower = sfseek(array[i],(Sfoff_t)0,1);
+ if(un->f[i].lower < 0)
+ un->type |= UNSEEKABLE;
+ }
+ }
+
+ if(sfdisc(f,(Sfdisc_t*)un) != (Sfdisc_t*)un)
+ { free(un);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/lib/libast/disc/sfkeyprintf.c b/src/lib/libast/disc/sfkeyprintf.c
new file mode 100644
index 0000000..c63fe37
--- /dev/null
+++ b/src/lib/libast/disc/sfkeyprintf.c
@@ -0,0 +1,392 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * keyword printf support
+ */
+
+#define _AST_API_H 1
+
+#include <ast.h>
+#include <ccode.h>
+#include <ctype.h>
+#include <sfdisc.h>
+#include <regex.h>
+
+#define FMT_case 1
+#define FMT_edit 2
+
+typedef struct
+{
+ Sffmt_t fmt;
+ void* handle;
+ Sf_key_lookup_t lookup;
+ Sf_key_convert_t convert;
+ Sfio_t* tmp[2];
+ regex_t red[2];
+ regex_t* re[2];
+ int invisible;
+ int level;
+ int version;
+} Fmt_t;
+
+typedef struct
+{
+ char* next;
+ int delimiter;
+ int first;
+} Field_t;
+
+typedef union
+{
+ char** p;
+ char* s;
+ Sflong_t q;
+ long l;
+ int i;
+ short h;
+ char c;
+} Value_t;
+
+#define initfield(f,s) ((f)->first = (f)->delimiter = *((f)->next = (s)))
+
+static char*
+getfield(register Field_t* f, int restore)
+{
+ register char* s;
+ register int n;
+ register int c;
+ register int lp;
+ register int rp;
+ char* b;
+
+ if (!f->delimiter)
+ return 0;
+ s = f->next;
+ if (f->first)
+ f->first = 0;
+ else if (restore)
+ *s = f->delimiter;
+ b = ++s;
+ lp = rp = n = 0;
+ for (;;)
+ {
+ if (!(c = *s++))
+ {
+ f->delimiter = 0;
+ break;
+ }
+ else if (c == CC_esc || c == '\\')
+ {
+ if (*s)
+ s++;
+ }
+ else if (c == lp)
+ n++;
+ else if (c == rp)
+ n--;
+ else if (n <= 0)
+ {
+ if (c == '(' && restore)
+ {
+ lp = '(';
+ rp = ')';
+ n = 1;
+ }
+ else if (c == '[' && restore)
+ {
+ lp = '[';
+ rp = ']';
+ n = 1;
+ }
+ else if (c == f->delimiter)
+ {
+ *(f->next = --s) = 0;
+ break;
+ }
+ }
+ }
+ return b;
+}
+
+/*
+ * sfio %! extension function
+ */
+
+static int
+getfmt(Sfio_t* sp, void* vp, Sffmt_t* dp)
+{
+ register Fmt_t* fp = (Fmt_t*)dp;
+ Value_t* value = (Value_t*)vp;
+ register char* v;
+ char* t;
+ char* b;
+ char* a = 0;
+ char* s = 0;
+ Sflong_t n = 0;
+ int h = 0;
+ int i = 0;
+ int x = 0;
+ int d;
+ Field_t f;
+ regmatch_t match[10];
+
+ fp->level++;
+ if (fp->fmt.t_str && fp->fmt.n_str > 0 && (v = fmtbuf(fp->fmt.n_str + 1)))
+ {
+ memcpy(v, fp->fmt.t_str, fp->fmt.n_str);
+ v[fp->fmt.n_str] = 0;
+ b = v;
+ for (;;)
+ {
+ switch (*v++)
+ {
+ case 0:
+ break;
+ case '(':
+ h++;
+ continue;
+ case ')':
+ h--;
+ continue;
+ case '=':
+ case ':':
+ case ',':
+ if (h <= 0)
+ {
+ a = v;
+ break;
+ }
+ continue;
+ default:
+ continue;
+ }
+ if (i = *--v)
+ {
+ *v = 0;
+ if (i == ':' && fp->fmt.fmt == 's' && strlen(a) > 4 && !isalnum(*(a + 4)))
+ {
+ d = *(a + 4);
+ *(a + 4) = 0;
+ if (streq(a, "case"))
+ x = FMT_case;
+ else if (streq(a, "edit"))
+ x = FMT_edit;
+ *(a + 4) = d;
+ if (x)
+ a = 0;
+ }
+ }
+ break;
+ }
+ n = i;
+ t = fp->fmt.t_str;
+ fp->fmt.t_str = b;
+ h = (*fp->lookup)(fp->handle, &fp->fmt, a, &s, &n);
+ fp->fmt.t_str = t;
+ if (i)
+ *v++ = i;
+ }
+ else
+ {
+ h = (*fp->lookup)(fp->handle, &fp->fmt, a, &s, &n);
+ v = 0;
+ }
+ fp->fmt.flags |= SFFMT_VALUE;
+ switch (fp->fmt.fmt)
+ {
+ case 'c':
+ value->c = s ? *s : n;
+ break;
+ case 'd':
+ case 'i':
+ fp->fmt.size = sizeof(Sflong_t);
+ value->q = (Sflong_t)(s ? strtoll(s, NiL, 0) : n);
+ break;
+ case 'o':
+ case 'u':
+ case 'x':
+ fp->fmt.size = sizeof(Sflong_t);
+ value->q = s ? (Sflong_t)strtoull(s, NiL, 0) : n;
+ break;
+ case 'p':
+ if (s)
+ n = strtoll(s, NiL, 0);
+ value->p = pointerof(n);
+ break;
+ case 'q':
+ if (s)
+ {
+ fp->fmt.fmt = 's';
+ value->s = fmtquote(s, "$'", "'", strlen(s), 0);
+ }
+ else
+ {
+ fp->fmt.fmt = 'd';
+ value->q = n;
+ }
+ break;
+ case 's':
+ if (!s && (!h || !fp->tmp[1] && !(fp->tmp[1] = sfstropen()) || sfprintf(fp->tmp[1], "%I*d", sizeof(n), n) <= 0 || !(s = sfstruse(fp->tmp[1]))))
+ s = "";
+ if (x)
+ {
+ h = 0;
+ d = initfield(&f, v + 4);
+ switch (x)
+ {
+ case FMT_case:
+ while ((a = getfield(&f, 1)) && (v = getfield(&f, 0)))
+ {
+ if (strmatch(s, a))
+ {
+ Fmt_t fmt;
+
+ fmt = *fp;
+ fmt.fmt.form = v;
+ for (h = 0; h < elementsof(fmt.tmp); h++)
+ fmt.tmp[h] = 0;
+ if (!fp->tmp[0] && !(fp->tmp[0] = sfstropen()) || sfprintf(fp->tmp[0], "%!", &fmt) <= 0 || !(s = sfstruse(fp->tmp[0])))
+ s = "";
+ *(v - 1) = d;
+ if (f.delimiter)
+ *f.next = d;
+ for (h = 0; h < elementsof(fmt.tmp); h++)
+ if (fmt.tmp[h])
+ sfclose(fmt.tmp[h]);
+ h = 1;
+ break;
+ }
+ *(v - 1) = d;
+ }
+ break;
+ case FMT_edit:
+ for (x = 0; *f.next; x ^= 1)
+ {
+ if (fp->re[x])
+ regfree(fp->re[x]);
+ else
+ fp->re[x] = &fp->red[x];
+ if (regcomp(fp->re[x], f.next, REG_DELIMITED|REG_NULL))
+ break;
+ f.next += fp->re[x]->re_npat;
+ if (regsubcomp(fp->re[x], f.next, NiL, 0, 0))
+ break;
+ f.next += fp->re[x]->re_npat;
+ if (!regexec(fp->re[x], s, elementsof(match), match, 0) && !regsubexec(fp->re[x], s, elementsof(match), match))
+ {
+ s = fp->re[x]->re_sub->re_buf;
+ if (fp->re[x]->re_sub->re_flags & REG_SUB_STOP)
+ break;
+ }
+ }
+ h = 1;
+ break;
+ }
+ if (!h)
+ s = "";
+ }
+ value->s = s;
+ if (fp->level == 1)
+ while ((s = strchr(s, CC_esc)) && *(s + 1) == '[')
+ do fp->invisible++; while (*s && !islower(*s++));
+ break;
+ case 'Z':
+ fp->fmt.fmt = 'c';
+ value->c = 0;
+ break;
+ case '\n':
+ value->s = "\n";
+ break;
+ case '.':
+ value->i = n;
+ break;
+ default:
+ if ((!fp->convert || !(value->s = (*fp->convert)(fp->handle, &fp->fmt, a, s, n))) && (!fp->tmp[0] && !(fp->tmp[0] = sfstropen()) || sfprintf(fp->tmp[0], "%%%c", fp->fmt.fmt) <= 0 || !(value->s = sfstruse(fp->tmp[0]))))
+ value->s = "";
+ break;
+ }
+ fp->level--;
+ return 0;
+}
+
+/*
+ * this is the original interface
+ */
+
+int
+sfkeyprintf(Sfio_t* sp, void* handle, const char* format, Sf_key_lookup_t lookup, Sf_key_convert_t convert)
+{
+ register int i;
+ int r;
+ Fmt_t fmt;
+
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.fmt.version = SFIO_VERSION;
+ fmt.fmt.form = (char*)format;
+ fmt.fmt.extf = getfmt;
+ fmt.handle = handle;
+ fmt.lookup = lookup;
+ fmt.convert = convert;
+ r = sfprintf(sp, "%!", &fmt) - fmt.invisible;
+ for (i = 0; i < elementsof(fmt.tmp); i++)
+ if (fmt.tmp[i])
+ sfclose(fmt.tmp[i]);
+ for (i = 0; i < elementsof(fmt.re); i++)
+ if (fmt.re[i])
+ regfree(fmt.re[i]);
+ return r;
+}
+
+#undef _AST_API_H
+
+#include <ast_api.h>
+
+/*
+ * Sffmt_t* callback args
+ */
+
+int
+sfkeyprintf_20000308(Sfio_t* sp, void* handle, const char* format, Sf_key_lookup_t lookup, Sf_key_convert_t convert)
+{
+ register int i;
+ int r;
+ Fmt_t fmt;
+
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.version = 20030909;
+ fmt.fmt.version = SFIO_VERSION;
+ fmt.fmt.form = (char*)format;
+ fmt.fmt.extf = getfmt;
+ fmt.handle = handle;
+ fmt.lookup = lookup;
+ fmt.convert = convert;
+ r = sfprintf(sp, "%!", &fmt) - fmt.invisible;
+ for (i = 0; i < elementsof(fmt.tmp); i++)
+ if (fmt.tmp[i])
+ sfclose(fmt.tmp[i]);
+ return r;
+}
diff --git a/src/lib/libast/disc/sfstrtmp.c b/src/lib/libast/disc/sfstrtmp.c
new file mode 100644
index 0000000..beed91b
--- /dev/null
+++ b/src/lib/libast/disc/sfstrtmp.c
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * sfio tmp string buffer support
+ */
+
+#include <sfio_t.h>
+#include <ast.h>
+
+#if __OBSOLETE__ >= 20070101 /* sfstr* macros now use sfsetbuf() */
+
+NoN(sfstrtmp)
+
+#else
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+/*
+ * replace buffer in string stream f for either SF_READ or SF_WRITE
+ */
+
+extern int
+sfstrtmp(register Sfio_t* f, int mode, void* buf, size_t siz)
+{
+ if (!(f->_flags & SF_STRING))
+ return -1;
+ if (f->_flags & SF_MALLOC)
+ free(f->_data);
+ f->_flags &= ~(SF_ERROR|SF_MALLOC);
+ f->mode = mode;
+ f->_next = f->_data = (unsigned char*)buf;
+ f->_endw = f->_endr = f->_endb = f->_data + siz;
+ f->_size = siz;
+ return 0;
+}
+
+#endif
diff --git a/src/lib/libast/features/align.c b/src/lib/libast/features/align.c
new file mode 100644
index 0000000..e2c97c8
--- /dev/null
+++ b/src/lib/libast/features/align.c
@@ -0,0 +1,188 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * generate align features
+ *
+ * NOTE: two's complement binary integral representation assumed
+ */
+
+#include "FEATURE/common"
+
+#include <setjmp.h>
+
+union _u_
+{
+ long u1;
+ char* u2;
+ double u3;
+ char u4[1024];
+ intmax_t u5;
+ uintmax_t u6;
+ _ast_fltmax_t u7;
+ void* u8;
+ char* (*u9)();
+ jmp_buf u10;
+};
+
+struct _s_
+{
+ char s1;
+ union _u_ s2;
+};
+
+#define roundof(x,y) (((x)+((y)-1))&~((y)-1))
+
+static union _u_ u;
+static union _u_ v;
+
+int
+main()
+{
+ register int i;
+ register int j;
+ register int k;
+
+ int align0;
+ int align1;
+ int align2;
+ unsigned long bit1;
+ unsigned long bit2;
+ unsigned long bits0;
+ unsigned long bits1;
+ unsigned long bits2;
+
+ u.u2 = u.u4;
+ v.u2 = u.u2 + 1;
+ bit1 = u.u1 ^ v.u1;
+ v.u2 = u.u2 + 2;
+ bit2 = u.u1 ^ v.u1;
+ align0 = sizeof(struct _s_) - sizeof(union _u_);
+ bits0 = 0;
+ k = 0;
+ for (j = 0; j < align0; j++)
+ {
+ u.u2 = u.u4 + j;
+ bits1 = 0;
+ for (i = 0; i < align0; i++)
+ {
+ v.u2 = u.u2 + i;
+ bits1 |= u.u1 ^ v.u1;
+ }
+ if (!bits0 || bits1 < bits0)
+ {
+ bits0 = bits1;
+ k = j;
+ }
+ }
+ align1 = roundof(align0, 2);
+ u.u2 = u.u4 + k;
+ for (bits1 = bits0; i < align1; i++)
+ {
+ v.u2 = u.u2 + i;
+ bits1 |= u.u1 ^ v.u1;
+ }
+ align2 = roundof(align0, 4);
+ for (bits2 = bits1; i < align2; i++)
+ {
+ v.u2 = u.u2 + i;
+ bits2 |= u.u1 ^ v.u1;
+ }
+ printf("\n");
+ printf("#define ALIGN_CHUNK %d\n", sizeof(char*) >= 4 ? 8192 : 1024);
+ printf("#define ALIGN_INTEGRAL uintptr_t\n");
+ printf("#define ALIGN_INTEGER(x) ((char*)(x)-(char*)0)\n");
+ printf("#define ALIGN_POINTER(x) ((char*)(x))\n");
+ if (bits2 == (align2 - 1))
+ printf("#define ALIGN_ROUND(x,y) ALIGN_POINTER(ALIGN_INTEGER((x)+(y)-1)&~((y)-1))\n");
+ else
+ printf("#define ALIGN_ROUND(x,y) ALIGN_POINTER(ALIGN_INTEGER(ALIGN_ALIGN(x)+(((y)+%d)/%d)-1)&~((((y)+%d)/%d)-1))\n", align0, align0, align0, align0);
+ printf("\n");
+ if (align0 == align2)
+ {
+ printf("#define ALIGN_BOUND ALIGN_BOUND2\n");
+ printf("#define ALIGN_ALIGN(x) ALIGN_ALIGN2(x)\n");
+ printf("#define ALIGN_TRUNC(x) ALIGN_TRUNC2(x)\n");
+ }
+ else if (align0 == align1)
+ {
+ printf("#define ALIGN_BOUND ALIGN_BOUND1\n");
+ printf("#define ALIGN_ALIGN(x) ALIGN_ALIGN1(x)\n");
+ printf("#define ALIGN_TRUNC(x) ALIGN_TRUNC1(x)\n");
+ }
+ else
+ {
+ printf("#define ALIGN_BOUND 1\n");
+ printf("#define ALIGN_ALIGN(x) ALIGN_POINTER(x)\n");
+ printf("#define ALIGN_TRUNC(x) ALIGN_POINTER(x)\n");
+ }
+ printf("\n");
+ printf("#define ALIGN_BIT1 0x%lx\n", bit1);
+ if (align1 == align2)
+ {
+ printf("#define ALIGN_BOUND1 ALIGN_BOUND2\n");
+ printf("#define ALIGN_ALIGN1(x) ALIGN_ALIGN2(x)\n");
+ printf("#define ALIGN_TRUNC1(x) ALIGN_TRUNC2(x)\n");
+ }
+ else
+ {
+ printf("#define ALIGN_BOUND1 %d\n", align1);
+ printf("#define ALIGN_ALIGN1(x) ALIGN_TRUNC1((x)+%d)\n", align1 - 1);
+ printf("#define ALIGN_TRUNC1(x) ALIGN_POINTER(ALIGN_INTEGER((x)+%d)&0x%lx)\n", align1 - 1, ~(bits0|bits1));
+ }
+#if _X86_ || _X64_
+ printf("#if _X64_\n");
+ printf("#define ALIGN_CLRBIT1(x) ALIGN_POINTER(ALIGN_INTEGER(x)&0xfffffffffffffffeULL)\n");
+ printf("#else\n");
+ printf("#define ALIGN_CLRBIT1(x) ALIGN_POINTER(ALIGN_INTEGER(x)&0xfffffffe)\n");
+ printf("#endif\n");
+#else
+ printf("#define ALIGN_CLRBIT1(x) ALIGN_POINTER(ALIGN_INTEGER(x)&0x%lx)\n", ~bit1);
+#endif
+ printf("#define ALIGN_SETBIT1(x) ALIGN_POINTER(ALIGN_INTEGER(x)|0x%lx)\n", bit1);
+ printf("#define ALIGN_TSTBIT1(x) ALIGN_POINTER(ALIGN_INTEGER(x)&0x%lx)\n", bit1);
+ printf("\n");
+ printf("#define ALIGN_BIT2 0x%lx\n", bit2);
+#if _X86_ || _X64_
+ printf("#if _X64_\n");
+ printf("#define ALIGN_BOUND2 16\n");
+ printf("#define ALIGN_ALIGN2(x) ALIGN_TRUNC2((x)+15)\n");
+ printf("#define ALIGN_TRUNC2(x) ALIGN_POINTER(ALIGN_INTEGER(x)&0xfffffffffffffffeULL)\n");
+ printf("#else\n");
+ printf("#define ALIGN_BOUND2 8\n");
+ printf("#define ALIGN_ALIGN2(x) ALIGN_TRUNC2((x)+7)\n");
+ printf("#define ALIGN_TRUNC2(x) ALIGN_POINTER(ALIGN_INTEGER(x)&0xfffffff8)\n");
+ printf("#endif\n");
+#else
+ printf("#define ALIGN_BOUND2 %d\n", align2);
+ printf("#define ALIGN_ALIGN2(x) ALIGN_TRUNC2((x)+%d)\n", align2 - 1);
+ printf("#define ALIGN_TRUNC2(x) ALIGN_POINTER(ALIGN_INTEGER(x)&0x%lx)\n", ~(bits0|bits1|bits2));
+#endif
+ printf("#define ALIGN_CLRBIT2(x) ALIGN_POINTER(ALIGN_INTEGER(x)&0x%lx)\n", ~bit2);
+ printf("#define ALIGN_SETBIT2(x) ALIGN_POINTER(ALIGN_INTEGER(x)|0x%lx)\n", bit2);
+ printf("#define ALIGN_TSTBIT2(x) ALIGN_POINTER(ALIGN_INTEGER(x)&0x%lx)\n", bit2);
+ printf("\n");
+ return 0;
+}
diff --git a/src/lib/libast/features/api b/src/lib/libast/features/api
new file mode 100644
index 0000000..acfcd71
--- /dev/null
+++ b/src/lib/libast/features/api
@@ -0,0 +1,11 @@
+iff AST_API
+
+ver ast 20110505
+
+api ast 20110505 cmdopen
+
+api ast 20100601 pathaccess pathcanon pathcat pathkey pathpath pathprobe pathrepl
+
+api ast 20000308 sfkeyprintf
+
+print #define _AST_VERSION AST_VERSION /* pre-20100601 compatibility */
diff --git a/src/lib/libast/features/aso b/src/lib/libast/features/aso
new file mode 100644
index 0000000..2b7f01a
--- /dev/null
+++ b/src/lib/libast/features/aso
@@ -0,0 +1,671 @@
+# ast atomic scalar operations feature tests
+
+if aso note{ gcc 4.1+ 64 bit memory atomic operations model }end link{
+ #include "FEATURE/common"
+ int main()
+ {
+ uint64_t i = 0;
+ return __sync_fetch_and_add(&i,7);
+ }
+ }end && {
+ #define _aso_cas8(p,o,n) __sync_val_compare_and_swap(p,o,n)
+ #define _aso_inc8(p) __sync_fetch_and_add(p,1)
+ #define _aso_dec8(p) __sync_fetch_and_sub(p,1)
+ #define _aso_cas16(p,o,n) __sync_val_compare_and_swap(p,o,n)
+ #define _aso_inc16(p) __sync_fetch_and_add(p,1)
+ #define _aso_dec16(p) __sync_fetch_and_sub(p,1)
+ #define _aso_cas32(p,o,n) __sync_val_compare_and_swap(p,o,n)
+ #define _aso_inc32(p) __sync_fetch_and_add(p,1)
+ #define _aso_dec32(p) __sync_fetch_and_sub(p,1)
+ #define _aso_cas64(p,o,n) __sync_val_compare_and_swap(p,o,n)
+ #define _aso_inc64(p) __sync_fetch_and_add(p,1)
+ #define _aso_dec64(p) __sync_fetch_and_sub(p,1)
+ #if _ast_sizeof_pointer == 8
+ #define _aso_casptr(p,o,n) ((void*)__sync_val_compare_and_swap(p,(uint64_t)o,(uint64_t)n))
+ #else
+ #define _aso_casptr(p,o,n) ((void*)__sync_val_compare_and_swap(p,(uint32_t)o,(uint32_t)n))
+ #endif
+ }
+elif aso note{ gcc 4.1+ 32 bit memory atomic operations model }end link{
+ #include "FEATURE/common"
+ int main()
+ {
+ uint32_t i = 0;
+ return __sync_fetch_and_add(&i,7);
+ }
+ }end && {
+ #define _aso_cas8(p,o,n) __sync_val_compare_and_swap(p,o,n)
+ #define _aso_inc8(p) __sync_fetch_and_add(p,1)
+ #define _aso_dec8(p) __sync_fetch_and_sub(p,1)
+ #define _aso_cas16(p,o,n) __sync_val_compare_and_swap(p,o,n)
+ #define _aso_inc16(p) __sync_fetch_and_add(p,1)
+ #define _aso_dec16(p) __sync_fetch_and_sub(p,1)
+ #define _aso_cas32(p,o,n) __sync_val_compare_and_swap(p,o,n)
+ #define _aso_inc32(p) __sync_fetch_and_add(p,1)
+ #define _aso_dec32(p) __sync_fetch_and_sub(p,1)
+ #define _aso_casptr(p,o,n) ((void*)__sync_val_compare_and_swap(p,(uint32_t)o,(uint32_t)n))
+ }
+elif aso note{ <atomic.h> atomic_cas_64 }end link{
+ #include "FEATURE/common"
+ #include <atomic.h>
+ int main()
+ {
+ uint64_t i = 0;
+ uint32_t j = 1;
+ return atomic_cas_64(&i, 0, 1) != 0 || atomic_add_32_nv(&j, 1) != 1;
+ }
+ }end && {
+ #include <atomic.h>
+ #define _aso_cas8(p,o,n) atomic_cas_8(p,o,n)
+ #define _aso_inc8(p) (atomic_add_8_nv(p,1)-1)
+ #define _aso_dec8(p) (atomic_add_8_nv(p,-1)+1)
+ #define _aso_cas16(p,o,n) atomic_cas_16(p,o,n)
+ #define _aso_inc16(p) (atomic_add_16_nv(p,1)-1)
+ #define _aso_dec16(p) (atomic_add_16_nv(p,-1)+1)
+ #define _aso_cas32(p,o,n) atomic_cas_32(p,o,n)
+ #define _aso_inc32(p) (atomic_add_32_nv(p,1)-1)
+ #define _aso_dec32(p) (atomic_add_32_nv(p,-1)+1)
+ #define _aso_cas64(p,o,n) atomic_cas_64(p,o,n)
+ #define _aso_inc64(p) (atomic_add_64_nv(p,1)-1)
+ #define _aso_dec64(p) (atomic_add_64_nv(p,-1)+1)
+ #if _ast_sizeof_pointer == 8
+ #define _aso_casptr(p,o,n) ((void*)atomic_cas_64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
+ #else
+ #define _aso_casptr(p,o,n) ((void*)atomic_cas_32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
+ #endif
+ }
+elif aso note{ <atomic.h> atomic_cas_32 }end link{
+ #include "FEATURE/common"
+ #include <atomic.h>
+ int main()
+ {
+ uint32_t i = 0;
+ return atomic_cas_32(&i, 0, 1) != 0 || (atomic_add_32_nv(&i, 1) - 1) != 1;
+ }
+ }end && {
+ #include <atomic.h>
+ #define _aso_cas8(p,o,n) atomic_cas_8(p,o,n)
+ #define _aso_inc8(p) (atomic_add_8_nv(p,1)-1)
+ #define _aso_dec8(p) (atomic_add_8_nv(p,-1)+1)
+ #define _aso_cas16(p,o,n) atomic_cas_16(p,o,n)
+ #define _aso_inc16(p) (atomic_add_16_nv(p,1)-1)
+ #define _aso_dec16(p) (atomic_add_16_nv(p,-1)+1)
+ #define _aso_cas32(p,o,n) atomic_cas_32(p,o,n)
+ #define _aso_inc32(p) (atomic_add_32_nv(p,1)-1)
+ #define _aso_dec32(p) (atomic_add_32_nv(p,-1)+1)
+ #define _aso_casptr(p,o,n) ((void*)atomic_cas_32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
+ }
+elif aso -latomic note{ <atomic.h> atomic_cas_64 with -latomic }end link{
+ #include "FEATURE/common"
+ #include <atomic.h>
+ int main()
+ {
+ uint64_t i = 0;
+ uint32_t j = 1;
+ return atomic_cas_64(&i, 0, 1) != 0 || (atomic_add_32_nv(&j, 1) - 1) != 1;
+ }
+ }end && {
+ #include <atomic.h>
+ #define _REQ_atomic
+ #define _aso_cas8(p,o,n) atomic_cas_8(p,o,n)
+ #define _aso_inc8(p) (atomic_add_8_nv(p,1)-1)
+ #define _aso_dec8(p) (atomic_add_8_nv(p,-1)+1)
+ #define _aso_cas16(p,o,n) atomic_cas_16(p,o,n)
+ #define _aso_inc16(p) (atomic_add_16_nv(p,1)-1)
+ #define _aso_dec16(p) (atomic_add_16_nv(p,-1)+1)
+ #define _aso_cas32(p,o,n) atomic_cas_32(p,o,n)
+ #define _aso_inc32(p) (atomic_add_32_nv(p,1)-1)
+ #define _aso_dec32(p) (atomic_add_32_nv(p,-1)+1)
+ #define _aso_cas64(p,o,n) atomic_cas_64(p,o,n)
+ #define _aso_inc64(p) (atomic_add_64_nv(p,1)-1)
+ #define _aso_dec64(p) (atomic_add_64_nv(p,-1)+1)
+ #if _ast_sizeof_pointer == 8
+ #define _aso_casptr(p,o,n) ((void*)atomic_cas_64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
+ #else
+ #define _aso_casptr(p,o,n) ((void*)atomic_cas_32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
+ #endif
+ }
+elif aso note{ <atomic.h> atomic_cas_32 with -latomic }end link{
+ #include "FEATURE/common"
+ #include <atomic.h>
+ int main()
+ {
+ uint32_t i = 0;
+ return atomic_cas_32(&i, 0, 1) != 0 || (atomic_add_32_nv(&i, 1) - 1) != 1;
+ }
+ }end && {
+ #include <atomic.h>
+ #define _REQ_atomic
+ #define _aso_cas8(p,o,n) atomic_cas_8(p,o,n)
+ #define _aso_inc8(p) (atomic_add_8_nv(p,1)-1)
+ #define _aso_dec8(p) (atomic_add_8_nv(p,-1)+1)
+ #define _aso_cas16(p,o,n) atomic_cas_16(p,o,n)
+ #define _aso_inc16(p) (atomic_add_16_nv(p,1)-1)
+ #define _aso_dec16(p) (atomic_add_16_nv(p,-1)+1)
+ #define _aso_cas32(p,o,n) atomic_cas_32(p,o,n)
+ #define _aso_inc32(p) (atomic_add_32_nv(p,1)-1)
+ #define _aso_dec32(p) (atomic_add_32_nv(p,-1)+1)
+ #define _aso_casptr(p,o,n) ((void*)atomic_cas_32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
+ }
+elif aso note{ <atomic.h> cas64 }end link{
+ #include "FEATURE/common"
+ #include <atomic.h>
+ int main()
+ {
+ uint64_t i = 0;
+ uint32_t j = 1;
+ return cas64(&i, 0, 1) != 0 || (atomic_add_32_nv(&j, 1) - 1) != 1;
+ }
+ }end && {
+ #include <atomic.h>
+ #define _aso_cas8(p,o,n) cas8(p,o,n)
+ #define _aso_inc8(p) (atomic_add_8_nv(p,1)-1)
+ #define _aso_dec8(p) (atomic_add_8_nv(p,-1)+1)
+ #define _aso_cas16(p,o,n) cas16(p,o,n)
+ #define _aso_inc16(p) (atomic_add_16_nv(p,1)-1)
+ #define _aso_dec16(p) (atomic_add_16_nv(p,-1)+1)
+ #define _aso_cas32(p,o,n) cas32(p,o,n)
+ #define _aso_inc32(p) (atomic_add_32_nv(p,1)-1)
+ #define _aso_dec32(p) (atomic_add_32_nv(p,-1)+1)
+ #define _aso_cas64(p,o,n) cas64(p,o,n)
+ #define _aso_inc64(p) (atomic_add_64_nv(p,1)-1)
+ #define _aso_dec64(p) (atomic_add_64_nv(p,-1)+1)
+ #if _ast_sizeof_pointer == 8
+ #define _aso_casptr(p,o,n) ((void*)cas64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
+ #else
+ #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
+ #endif
+ }
+elif aso note{ <atomic.h> just cas64 }end link{
+ #include "FEATURE/common"
+ #include <atomic.h>
+ int main()
+ {
+ uint64_t i = 0;
+ uint32_t j = 1;
+ uint16_t k = 1;
+ uint8_t l = 1;
+ return cas64(&i, 0, 1) != 0 || cas32(&j, 0, 1) != 0 || cas16(&k, 0, 1) != 0 || cas8(&l, 0, 1) != 0;
+ }
+ }end && {
+ #include <atomic.h>
+ #define _aso_cas8(p,o,n) cas8(p,o,n)
+ #define _aso_cas16(p,o,n) cas16(p,o,n)
+ #define _aso_cas32(p,o,n) cas32(p,o,n)
+ #define _aso_cas64(p,o,n) cas64(p,o,n)
+ #if _ast_sizeof_pointer == 8
+ #define _aso_casptr(p,o,n) ((void*)cas64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
+ #else
+ #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
+ #endif
+ }
+elif aso note{ <atomic.h> cas32 }end link{
+ #include "FEATURE/common"
+ #include <atomic.h>
+ int main()
+ {
+ uint32_t i = 0;
+ return cas32(&i, 0, 1) != 0 || (atomic_add_32_nv(&i, 1) - 1) != 1;
+ }
+ }end && {
+ #include <atomic.h>
+ #define _aso_cas8(p,o,n) cas8(p,o,n)
+ #define _aso_inc8(p) (atomic_add_8_nv(p,1)-1)
+ #define _aso_dec8(p) (atomic_add_8_nv(p,-1)+1)
+ #define _aso_cas16(p,o,n) cas16(p,o,n)
+ #define _aso_inc16(p) (atomic_add_16_nv(p,1)-1)
+ #define _aso_dec16(p) (atomic_add_16_nv(p,-1)+1)
+ #define _aso_cas32(p,o,n) cas32(p,o,n)
+ #define _aso_inc32(p) (atomic_add_32_nv(p,1)-1)
+ #define _aso_dec32(p) (atomic_add_32_nv(p,-1)+1)
+ #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
+ }
+elif aso note{ <atomic.h> just cas32 }end link{
+ #include "FEATURE/common"
+ #include <atomic.h>
+ int main()
+ {
+ uint32_t j = 1;
+ uint16_t k = 1;
+ uint8_t l = 1;
+ return cas32(&j, 0, 1) != 0 || cas16(&k, 0, 1) != 0 || cas8(&l, 0, 1) != 0;
+ }
+ }end && {
+ #include <atomic.h>
+ #define _aso_cas8(p,o,n) cas8(p,o,n)
+ #define _aso_cas16(p,o,n) cas16(p,o,n)
+ #define _aso_cas32(p,o,n) cas32(p,o,n)
+ #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
+ }
+elif aso note{ winix Interlocked }end link{
+ #include <windows.h>
+ int main()
+ {
+ LONG i = 0;
+ LONGLONG j = 0;
+ return InterlockedCompareExchange(&i, 1, 0) != 0 ||
+ InterlockedIncrement(&i) != 1 ||
+ InterlockedDecrement(&i) != 2;
+ }
+ }end && {
+ #include <ast_windows.h>
+ #define _aso_cas32(p,o,n) InterlockedCompareExchange((LONG volatile*)p,n,o)
+ #define _aso_inc32(p) (InterlockedIncrement((LONG volatile*)p)-1)
+ #define _aso_dec32(p) (InterlockedDecrement((LONG volatile*)p)+1)
+ #if _X64
+ #define _aso_cas64(p,o,n) InterlockedCompareExchange64((LONGLONG volatile*)p,n,o)
+ #define _aso_inc64(p) (InterlockedIncrement64((LONGLONG volatile*)p)-1)
+ #define _aso_dec64(p) (InterlockedDecrement64((LONGLONG volatile*)p)+1)
+ #define _aso_casptr(p,o,n) ((void*)InterlockedCompareExchange64((LONGLONG volatile*)p,(LONGLONG)n,(LONGLONG)o))
+ #else
+ #if _BLD_posix
+ #include "dl.h"
+ typedef struct LL_s
+ {
+ LONG a;
+ LONG b;
+ } LL_t;
+ typedef union
+ {
+ LONGLONG i;
+ LL_t ll;
+ } LL_u;
+
+ #define _aso_cas64(p,o,n) _aso_InterlockedCompareExchange64((LONGLONG volatile*)p,n,o)
+ static LONGLONG _aso_InterlockedCompareExchange64_init(LONGLONG volatile*, LONGLONG, LONGLONG);
+ typedef LONGLONG (*_aso_InterlockedCompareExchange64_f)(LONGLONG volatile*, LONGLONG, LONGLONG);
+ static _aso_InterlockedCompareExchange64_f _aso_InterlockedCompareExchange64 = _aso_InterlockedCompareExchange64_init;
+ static LONGLONG _aso_InterlockedCompareExchange64_32(LONGLONG volatile* p, LONGLONG o, LONGLONG n)
+ {
+ LL_t* lp = (LL_t*)p;
+ LL_t* op = (LL_t*)&o;
+ LL_t* np = (LL_t*)&n;
+ LONGLONG r;
+
+ r = *p;
+ if (_aso_cas32(&lp->a, op->a, np->a) == op->a)
+ {
+ if (_aso_cas32(&lp->b, op->b, np->b) == op->b)
+ return o;
+ _aso_cas32(&lp->a, np->a, op->a);
+ }
+ return r;
+ }
+ static LONGLONG _aso_InterlockedCompareExchange64_init(LONGLONG volatile* p, LONGLONG o, LONGLONG n)
+ {
+ if (!(_aso_InterlockedCompareExchange64 = (_aso_InterlockedCompareExchange64_f)getsymbol(MODULE_kernel, "InterlockedCompareExchange64")))
+ _aso_InterlockedCompareExchange64 = _aso_InterlockedCompareExchange64_32;
+ return _aso_InterlockedCompareExchange64(p, o, n);
+ }
+
+ #define _aso_inc64(p) (_aso_InterlockedIncrement64((LONGLONG volatile*)p)-1)
+ typedef LONGLONG (*_aso_InterlockedIncrement64_f)(LONGLONG volatile*);
+ static LONGLONG _aso_InterlockedIncrement64_init(LONGLONG volatile*);
+ static _aso_InterlockedIncrement64_f _aso_InterlockedIncrement64 = _aso_InterlockedIncrement64_init;
+ static LONGLONG _aso_InterlockedIncrement64_32(LONGLONG volatile* p)
+ {
+ LONGLONG o;
+
+ do
+ {
+ o = *p;
+ } while (_aso_InterlockedCompareExchange64_32(p, o, o + 1) != o);
+ return o;
+ }
+ static LONGLONG _aso_InterlockedIncrement64_init(LONGLONG volatile* p)
+ {
+ if (!(_aso_InterlockedIncrement64 = (_aso_InterlockedIncrement64_f)getsymbol(MODULE_kernel, "InterlockedIncrement64")))
+ _aso_InterlockedIncrement64 = _aso_InterlockedIncrement64_32;
+ return _aso_InterlockedIncrement64(p);
+ }
+
+ #define _aso_dec64(p) (_aso_InterlockedDecrement64((LONGLONG volatile*)p)+1)
+ typedef LONGLONG (*_aso_InterlockedDecrement64_f)(LONGLONG volatile*);
+ static LONGLONG _aso_InterlockedDecrement64_init(LONGLONG volatile*);
+ static _aso_InterlockedDecrement64_f _aso_InterlockedDecrement64 = _aso_InterlockedDecrement64_init;
+ static LONGLONG _aso_InterlockedDecrement64_32(LONGLONG volatile* p)
+ {
+ LONGLONG o;
+
+ do
+ {
+ o = *p;
+ } while (_aso_InterlockedCompareExchange64_32(p, o, o - 1) != o);
+ return o;
+ }
+ static LONGLONG _aso_InterlockedDecrement64_init(LONGLONG volatile* p)
+ {
+ if (!(_aso_InterlockedDecrement64 = (_aso_InterlockedDecrement64_f)getsymbol(MODULE_kernel, "InterlockedDecrement64")))
+ _aso_InterlockedDecrement64 = _aso_InterlockedDecrement64_32;
+ return _aso_InterlockedDecrement64(p);
+ }
+ #endif
+ #define _aso_casptr(p,o,n) ((void*)InterlockedCompareExchange((LONG volatile*)p,(LONG)n,(LONG)o))
+ #endif
+ }
+elif aso note{ aix fetch and add }end link{
+ #include <sys/atomic_op.h>
+ int main()
+ {
+ int i = 0;
+ return fetch_and_add((atomic_p)&i,1);
+ }
+ }end && {
+ #include <sys/atomic_op.h>
+ #define _aso_incint(p) fetch_and_add((atomic_p)p,1)
+ #define _aso_decint(p) fetch_and_add((atomic_p)p,-1)
+ #define _aso_casint(p,o,n) (compare_and_swap((atomic_p)p,(int*)&o,(int)n) ? o : *p)
+ #if _ast_sizeof_pointer == 8
+ #define _aso_casptr(p,o,n) (compare_and_swaplp((atomic_l)p,(long*)&o,(long)n) ? o : *(void**)p)
+ #else
+ #define _aso_casptr(p,o,n) (compare_and_swap((atomic_p)p,(int*)&o,(int)n) ? o : *(void**)p)
+ #endif
+ }
+elif aso note{ mips compare and swap }end link{
+ int main()
+ {
+ int i = 1;
+ return __compare_and_swap(&i, 0, 1) != 1;
+ }
+ }end && {
+ #define _aso_cas32(p,o,n) (__compare_and_swap(p,o,n) ? o : *p)
+ #define _aso_casptr(p,o,n) (__compare_and_swap((long*)p,(long)o,(long)n) ? o : *(void**)p)
+ }
+elif aso note{ i386|i386-64 asm compare and swap }end link{
+ #include "FEATURE/common"
+
+ static uint32_t
+ cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
+ {
+ uint32_t r;
+
+ __asm__ __volatile__ (
+ "lock ; cmpxchg %3,%4"
+ : "=a"(r), "=m"(*p)
+ : "0"(o), "q"(n), "m"(*p)
+ : "memory", "cc"
+ );
+ return r;
+ }
+
+ #if _ast_sizeof_pointer == 8
+
+ static uint64_t
+ cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
+ {
+ uint64_t r;
+
+ __asm__ __volatile__ (
+ "lock ; cmpxchg %3,%4"
+ : "=a"(r), "=m"(*p)
+ : "0"(o), "q"(n), "m"(*p)
+ : "memory", "cc"
+ );
+ return r;
+ }
+
+ #else
+
+ #define cas64(p,o,n) (*(p))
+
+ #endif
+
+ int main()
+ {
+ uint32_t i = 0;
+ uint64_t j = 0;
+ return cas32(&i, 0, 1) || cas64(&j, 0, 1);
+ }
+ }end && {
+ static uint32_t
+ cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
+ {
+ uint32_t r;
+
+ __asm__ __volatile__ (
+ "lock ; cmpxchg %3,%4"
+ : "=a"(r), "=m"(*p)
+ : "0"(o), "q"(n), "m"(*p)
+ : "memory", "cc"
+ );
+ return r;
+ }
+
+ #if _ast_sizeof_pointer == 8
+
+ static uint64_t
+ cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
+ {
+ uint64_t r;
+
+ __asm__ __volatile__ (
+ "lock ; cmpxchg %3,%4"
+ : "=a"(r), "=m"(*p)
+ : "0"(o), "q"(n), "m"(*p)
+ : "memory", "cc"
+ );
+ return r;
+ }
+
+ #endif
+
+ #define _aso_cas32(p,o,n) cas32(p,o,n)
+ #if _ast_sizeof_pointer == 8
+ #define _aso_cas64(p,o,n) cas64(p,o,n)
+ #define _aso_casptr(p,o,n) ((void*)cas64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
+ #else
+ #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
+ #endif
+ }
+elif aso note{ ia64 asm compare and swap }end link{
+ #include "FEATURE/common"
+
+ static uint32_t
+ cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
+ {
+ uint32_t r;
+
+ __asm__ __volatile__ (
+ "zxt4 %3=%3 ;; mov ar.ccv=%3 ;; cmpxchg4.acq %0=%1,%2,ar.ccv"
+ : "=r"(r), "+S"(*p)
+ : "r"(n), "r"(o) : "memory"
+ );
+ return r;
+ }
+
+ static uint64_t
+ cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
+ {
+ uint64_t r;
+
+ __asm__ __volatile__ (
+ "mov ar.ccv=%3 ;; cmpxchg8.acq %0=%1,%2,ar.ccv"
+ : "=r"(r), "+S"(*p)
+ : "r"(n), "r"(o) : "memory"
+ );
+ return r;
+ }
+
+ int main()
+ {
+ uint32_t i = 0;
+ uint64_t j = 0;
+ return cas32(&i, 0, 1) || cas64(&j, 0, 1);
+ }
+ }end && {
+ static uint32_t
+ cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
+ {
+ uint32_t r;
+
+ __asm__ __volatile__ (
+ "zxt4 %3=%3 ;; mov ar.ccv=%3 ;; cmpxchg4.acq %0=%1,%2,ar.ccv"
+ : "=r"(r), "+S"(*p)
+ : "r"(n), "r"(o) : "memory"
+ );
+ return r;
+ }
+
+ static uint64_t
+ cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
+ {
+ uint64_t r;
+
+ __asm__ __volatile__ (
+ "mov ar.ccv=%3 ;; cmpxchg8.acq %0=%1,%2,ar.ccv"
+ : "=r"(r), "+S"(*p)
+ : "r"(n), "r"(o) : "memory"
+ );
+ return r;
+ }
+
+ #define _aso_cas32(p,o,n) cas32(p,o,n)
+ #define _aso_cas64(p,o,n) cas64(p,o,n)
+ #if _ast_sizeof_pointer == 8
+ #define _aso_casptr(p,o,n) ((void*)cas64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
+ #else
+ #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
+ #endif
+ }
+elif aso note{ ppc asm compare and swap }end link{
+ #include "FEATURE/common"
+
+ static uint32_t
+ cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
+ {
+ int r;
+
+ __asm__ __volatile__ (
+ "0: lwarx %0,0,%1 ;"
+ " xor. %0,%3,%0;"
+ " bne 1f;"
+ " stwcx. %2,0,%1;"
+ " bne- 0b;"
+ "1:"
+ : "=&r"(r)
+ : "r"(p), "r"(n), "r"(o)
+ : "cr0", "memory"
+ );
+ __asm__ __volatile__ ("isync" : : : "memory");
+ return r ? *p : o;
+ }
+
+ static uint64_t
+ cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
+ {
+ long r;
+
+ __asm__ __volatile__ (
+ "0: ldarx %0,0,%1 ;"
+ " xor. %0,%3,%0;"
+ " bne 1f;"
+ " stdcx. %2,0,%1;"
+ " bne- 0b;"
+ "1:"
+ : "=&r"(r)
+ : "r"(p), "r"(n), "r"(o)
+ : "cr0", "memory"
+ );
+ __asm__ __volatile__ ("isync" : : : "memory");
+ return r ? *p : o;
+ }
+
+ int main()
+ {
+ uint32_t i = 0;
+ uint64_t j = 0;
+ return cas32(&i, 0, 1) || cas64(&j, 0, 1);
+ }
+ }end && {
+ static uint32_t
+ cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
+ {
+ int r;
+
+ __asm__ __volatile__ (
+ "0: lwarx %0,0,%1 ;"
+ " xor. %0,%3,%0;"
+ " bne 1f;"
+ " stwcx. %2,0,%1;"
+ " bne- 0b;"
+ "1:"
+ : "=&r"(r)
+ : "r"(p), "r"(n), "r"(o)
+ : "cr0", "memory"
+ );
+ __asm__ __volatile__ ("isync" : : : "memory");
+ return r ? *p : o;
+ }
+
+ static uint64_t
+ cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
+ {
+ long r;
+
+ __asm__ __volatile__ (
+ "0: ldarx %0,0,%1 ;"
+ " xor. %0,%3,%0;"
+ " bne 1f;"
+ " stdcx. %2,0,%1;"
+ " bne- 0b;"
+ "1:"
+ : "=&r"(r)
+ : "r"(p), "r"(n), "r"(o)
+ : "cr0", "memory"
+ );
+ __asm__ __volatile__ ("isync" : : : "memory");
+ return r ? *p : o;
+ }
+
+ #define _aso_cas32(p,o,n) cas32(p,o,n)
+ #define _aso_cas64(p,o,n) cas64(p,o,n)
+ #if _ast_sizeof_pointer == 8
+ #define _aso_casptr(p,o,n) ((void*)cas64((uint64_t*)p,(uint64_t)o,(uint64_t)n))
+ #else
+ #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,(uint32_t)o,(uint32_t)n))
+ #endif
+ }
+endif
+
+aso fcntl note{ fcntl(F_SETLCK[W]) work }end link{
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+
+ int main()
+ {
+ struct flock lock;
+
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 1;
+ return fcntl(1, F_SETLKW, &lock) < 0;
+ }
+}end
+
+aso semaphore note{ semget semop semctl work }end link{
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/ipc.h>
+ #include <sys/sem.h>
+
+ int main()
+ {
+ int id;
+ struct sembuf sem;
+
+ if ((id = semget(IPC_PRIVATE, 16, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR)) < 0)
+ return 1;
+ sem.sem_num = 0;
+ sem.sem_op = 1;
+ sem.sem_flg = 0;
+ if (semop(id, &sem, 1) < 0)
+ return 1;
+ if (semctl(id, 0, IPC_RMID) < 0)
+ return 1;
+ return 0;
+ }
+}end
diff --git a/src/lib/libast/features/botch.c b/src/lib/libast/features/botch.c
new file mode 100644
index 0000000..d30547d
--- /dev/null
+++ b/src/lib/libast/features/botch.c
@@ -0,0 +1,72 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * generate ast traps for botched standard prototypes
+ */
+
+#include <sys/types.h>
+
+#include "FEATURE/lib"
+#include "FEATURE/sys"
+
+#if _lib_getgroups
+extern int getgroups(int, gid_t*);
+#endif
+
+int
+main()
+{
+#if _lib_getgroups
+ if (sizeof(int) > sizeof(gid_t))
+ {
+ int n;
+ int i;
+ int r;
+ gid_t groups[32 * sizeof(int) / sizeof(gid_t)];
+
+ r = sizeof(int) / sizeof(gid_t);
+ if ((n = getgroups((sizeof(groups) / sizeof(groups[0])) / r, groups)) > 0)
+ for (i = 1; i <= n; i++)
+ {
+ groups[i] = ((gid_t)0);
+ if (getgroups(i, groups) != i)
+ goto botched;
+ if (groups[i] != ((gid_t)0))
+ goto botched;
+ groups[i] = ((gid_t)-1);
+ if (getgroups(i, groups) != i)
+ goto botched;
+ if (groups[i] != ((gid_t)-1))
+ goto botched;
+ }
+ }
+ return 0;
+ botched:
+ printf("#undef getgroups\n");
+ printf("#define getgroups _ast_getgroups /* implementation botches gid_t* arg */\n");
+#endif
+ return 0;
+}
diff --git a/src/lib/libast/features/ccode b/src/lib/libast/features/ccode
new file mode 100644
index 0000000..0175763
--- /dev/null
+++ b/src/lib/libast/features/ccode
@@ -0,0 +1,81 @@
+tst output{
+ int main()
+ {
+ printf("\n");
+ printf("#define CC_ASCII 1 /* ISO-8859-1 */\n");
+ printf("#define CC_EBCDIC_E 2 /* Xopen dd(1) EBCDIC */\n");
+ printf("#define CC_EBCDIC_I 3 /* Xopen dd(1) IBM */\n");
+ printf("#define CC_EBCDIC_O 4 /* IBM-1047 mvs OpenEdition */\n");
+ printf("#define CC_EBCDIC_S 5 /* Siemens posix-bc */\n");
+ printf("#define CC_EBCDIC_H 6 /* IBM-37 AS/400 */\n");
+ printf("#define CC_EBCDIC_M 7 /* IBM mvs cobol */\n");
+ printf("#define CC_EBCDIC_U 8 /* microfocus cobol */\n");
+ printf("\n");
+ printf("#define CC_MAPS 8 /* number of code maps */\n");
+ printf("\n");
+ printf("#define CC_EBCDIC CC_EBCDIC_E\n");
+ printf("#define CC_EBCDIC1 CC_EBCDIC_E\n");
+ printf("#define CC_EBCDIC2 CC_EBCDIC_I\n");
+ printf("#define CC_EBCDIC3 CC_EBCDIC_O\n");
+ printf("\n");
+ switch ('~')
+ {
+ case 0137:
+ printf("#define CC_NATIVE CC_EBCDIC_E /* native character code */\n");
+ break;
+ case 0176:
+ printf("#define CC_NATIVE CC_ASCII /* native character code */\n");
+ break;
+ case 0241:
+ switch ('\n')
+ {
+ case 0025:
+ printf("#define CC_NATIVE CC_EBCDIC_O /* native character code */\n");
+ break;
+ default:
+ switch ('[')
+ {
+ case 0272:
+ printf("#define CC_NATIVE CC_EBCDIC_H /* native character code */\n");
+ break;
+ default:
+ printf("#define CC_NATIVE CC_EBCDIC_I /* native character code */\n");
+ break;
+ }
+ break;
+ }
+ break;
+ case 0377:
+ printf("#define CC_NATIVE CC_EBCDIC_S /* native character code */\n");
+ break;
+ default:
+ switch ('A')
+ {
+ case 0301:
+ printf("#define CC_NATIVE CC_EBCDIC_O /* native character code */\n");
+ break;
+ default:
+ printf("#define CC_NATIVE CC_ASCII /* native character code */\n");
+ break;
+ }
+ break;
+ }
+ if ('A' == 0101)
+ {
+ printf("#define CC_ALIEN CC_EBCDIC /* alien character code */\n\n");
+ printf("#define CC_bel 0007 /* bel character */\n");
+ printf("#define CC_esc 0033 /* esc character */\n");
+ printf("#define CC_sub 0032 /* sub character */\n");
+ printf("#define CC_vt 0013 /* vt character */\n");
+ }
+ else
+ {
+ printf("#define CC_ALIEN CC_ASCII /* alien character code */\n\n");
+ printf("#define CC_bel 0057 /* bel character */\n");
+ printf("#define CC_esc 0047 /* esc character */\n");
+ printf("#define CC_sub 0077 /* sub character */\n");
+ printf("#define CC_vt 0013 /* vt character */\n");
+ }
+ return 0;
+ }
+}end
diff --git a/src/lib/libast/features/common b/src/lib/libast/features/common
new file mode 100644
index 0000000..500ce87
--- /dev/null
+++ b/src/lib/libast/features/common
@@ -0,0 +1,624 @@
+iff AST_COMMON
+hdr pthread,stdarg,stddef,stdint,inttypes,types,unistd
+sys types
+typ long.double,size_t,ssize_t
+typ __va_list stdio.h
+
+mac SF_APPEND,SF_CLOSE sys/stat.h sys/socket.h
+
+dll import note{ Microsoft import/export nonsense }end execute{
+ __declspec(dllimport) int foo;
+ int main() { return foo == 5 ? 0 : 1; }
+ int bar = 5;
+ int* _imp__foo = &bar;
+}end
+
+std proto note{ standard C prototypes ok }end compile{
+ extern int foo(int, int);
+ bar() { foo(1, 1); }
+}end
+
+tst ptr_void note{ standard C void* ok }end compile{
+ extern void* foo();
+ void* bar() { return foo(); }
+}end
+
+cat{
+ /* disable non-standard linux/gnu inlines */
+ #ifdef __GNUC__
+ # undef __OPTIMIZE_SIZE__
+ # define __OPTIMIZE_SIZE__ 1
+ #endif
+
+ /* __STD_C indicates that the language is ANSI-C or C++ */
+ #if !defined(__STD_C) && __STDC__
+ # define __STD_C 1
+ #endif
+ #if !defined(__STD_C) && (__cplusplus || c_plusplus)
+ # define __STD_C 1
+ #endif
+ #if !defined(__STD_C) && _std_proto
+ # define __STD_C 1
+ #endif
+ #if !defined(__STD_C)
+ # define __STD_C 0
+ #endif
+
+ /* extern symbols must be protected against C++ name mangling */
+ #ifndef _BEGIN_EXTERNS_
+ # if __cplusplus || c_plusplus
+ # define _BEGIN_EXTERNS_ extern "C" {
+ # define _END_EXTERNS_ }
+ # else
+ # define _BEGIN_EXTERNS_
+ # define _END_EXTERNS_
+ # endif
+ #endif
+
+ /* _ARG_ simplifies function prototyping among flavors of C */
+ #ifndef _ARG_
+ # if __STD_C
+ # define _ARG_(x) x
+ # else
+ # define _ARG_(x) ()
+ # endif
+ #endif
+
+ /* _NIL_ simplifies defining nil pointers to a given type */
+ #ifndef _NIL_
+ # define _NIL_(x) ((x)0)
+ #endif
+
+ /* __INLINE__, if defined, is the inline keyword */
+ #if !defined(__INLINE__) && defined(__cplusplus)
+ # define __INLINE__ inline
+ #endif
+ #if !defined(__INLINE__) && defined(_WIN32) && !defined(__GNUC__)
+ # define __INLINE__ __inline
+ #endif
+
+ /* Void_t is defined so that Void_t* can address any type */
+ #ifndef Void_t
+ # if __STD_C
+ # define Void_t void
+ # else
+ # define Void_t char
+ # endif
+ #endif
+
+ /* windows variants and veneers */
+ #if !defined(_WINIX) && (_UWIN || __CYGWIN__ || __EMX__)
+ # define _WINIX 1
+ #endif
+
+ /* dynamic linked library external scope handling */
+ #ifdef __DYNAMIC__
+ # undef __DYNAMIC__
+ # ifndef _DLL
+ # define _DLL 1
+ # endif
+ #endif
+ #if _dll_import
+ # if _BLD_STATIC && !_BLD_DLL
+ # undef _DLL
+ # else
+ # if !_UWIN && !defined(_DLL)
+ # define _DLL 1
+ # endif
+ # endif
+ # if !defined(__EXPORT__) && _BLD_DLL
+ # define __EXPORT__ __declspec(dllexport)
+ # endif
+ # if !defined(__IMPORT__) && ( _BLD_DLL || defined(_DLL) )
+ # define __IMPORT__ __declspec(dllimport)
+ # endif
+ # if _BLD_DLL && _UWIN
+ # define __DYNAMIC__(v) (_ast_getdll()->_ast_ ## v)
+ # endif
+ #endif
+ #if !defined(_astimport)
+ # if defined(__IMPORT__) && defined(_DLL)
+ # define _astimport __IMPORT__
+ # else
+ # define _astimport extern
+ # endif
+ #endif
+ #if _dll_import && ( !_BLD_DLL || _WINIX && !_UWIN )
+ # ifdef __STDC__
+ # define __EXTERN__(T,obj) extern T obj; T* _imp__ ## obj = &obj
+ # define __DEFINE__(T,obj,val) T obj = val; T* _imp__ ## obj = &obj
+ # else
+ # define __EXTERN__(T,obj) extern T obj; T* _imp__/**/obj = &obj
+ # define __DEFINE__(T,obj,val) T obj = val; T* _imp__/**/obj = &obj
+ # endif
+ #else
+ # define __EXTERN__(T,obj) extern T obj
+ # define __DEFINE__(T,obj,val) T obj = val
+ #endif
+}end
+
+if tst - note{ <stdarg.h>+<wchar.h> works }end compile{
+ /*<NOSTDIO>*/
+ #include <stdarg.h>
+ #include <wchar.h>
+ }end
+elif tst - note{ explicit <sys/va_list.h> before <stdarg.h>+<wchar.h> }end compile{
+ /*<NOSTDIO>*/
+ #include <sys/va_list.h>
+ #include <stdarg.h>
+ #include <wchar.h>
+ }end {
+ #include <sys/va_list.h>
+ }
+endif
+
+tst ast_LL note{ LL numeric suffix supported }end compile{
+ int i = 1LL;
+ unsigned int u = 1ULL; /* NOTE: some compilers choke on 1LLU */
+}end
+
+tst - -DN=1 - -DN=2 - -DN=3 - -DN=4 - -DN=5 - -DN=6 - -DN=7 - -DN=8 - -DN=0 output{
+ #define _BYTESEX_H
+
+ #include <string.h>
+ #include <sys/types.h>
+
+ #if _STD_
+ #if N == 1
+ #define _ast_int8_t long
+ #define _ast_int8_str "long"
+ #endif
+ #if N == 2
+ #define _ast_int8_t long long
+ #define _ast_int8_str "long long"
+ #endif
+ #if N == 3
+ #define _ast_int8_t __int64
+ #define _ast_int8_str "__int64"
+ #endif
+ #if N == 4
+ #define _ast_int8_t __int64_t
+ #define _ast_int8_str "__int64_t"
+ #endif
+ #if N == 5
+ #define _ast_int8_t _int64_t
+ #define _ast_int8_str "_int64_t"
+ #endif
+ #if N == 6
+ #define _ast_int8_t int64_t
+ #define _ast_int8_str "int64_t"
+ #endif
+ #if N == 7
+ #define _ast_int8_t _int64
+ #define _ast_int8_str "_int64"
+ #endif
+ #if N == 8
+ #define _ast_int8_t int64
+ #define _ast_int8_str "int64"
+ #endif
+ #endif
+
+ #define elementsof(x) (sizeof(x)/sizeof(x[0]))
+
+ static char i_char = 1;
+ static short i_short = 1;
+ static int i_int = 1;
+ static long i_long = 1L;
+ #ifdef _ast_int8_t
+ #if _ast_LL
+ static _ast_int8_t i_long_long = 1LL;
+ static unsigned _ast_int8_t u_long_long = 18446744073709551615ULL;
+ #else
+ static _ast_int8_t i_long_long = 1;
+ static unsigned _ast_int8_t u_long_long = 18446744073709551615;
+ #endif
+ #endif
+
+ static struct
+ {
+ char* name;
+ int size;
+ char* swap;
+ } int_type[] =
+ {
+ "char", sizeof(char), (char*)&i_char,
+ "short", sizeof(short), (char*)&i_short,
+ "int", sizeof(int), (char*)&i_int,
+ "long", sizeof(long), (char*)&i_long,
+ #ifdef _ast_int8_t
+ _ast_int8_str, sizeof(_ast_int8_t), (char*)&i_long_long,
+ #endif
+ };
+
+ static int int_size[] = { 1, 2, 4, 8 };
+
+ int
+ main()
+ {
+ register int t;
+ register int s;
+ register int m = 1;
+ register int b = 1;
+ register int w = 0;
+
+ #ifdef _ast_int8_t
+ unsigned _ast_int8_t p;
+ char buf[64];
+
+ if (int_type[elementsof(int_type)-1].size <= 4)
+ return 1;
+ p = 0x12345678;
+ p <<= 32;
+ p |= 0x9abcdef0;
+ sprintf(buf, "0x%016llx", p);
+ if (strcmp(buf, "0x123456789abcdef0"))
+ return 1;
+ #endif
+ for (s = 0; s < elementsof(int_size); s++)
+ {
+ for (t = 0; t < elementsof(int_type) && int_type[t].size < int_size[s]; t++);
+ if (t < elementsof(int_type))
+ {
+ m = int_size[s];
+ #if __INTERIX
+ if (m == 8)
+ {
+ printf("#ifdef _MSC_VER\n");
+ printf("#define _ast_int8_t __int64\n");
+ printf("#else\n");
+ printf("#define _ast_int8_t long long\n");
+ printf("#endif\n");
+ }
+ else
+ #endif
+ printf("#define _ast_int%d_t %s\n", m, int_type[t].name);
+ if (m > 1)
+ {
+ if (*int_type[t].swap)
+ w |= b;
+ b <<= 1;
+ }
+ }
+ }
+ printf("#define _ast_intmax_t _ast_int%d_t\n", m);
+ if (m == sizeof(long))
+ printf("#define _ast_intmax_long 1\n");
+ printf("#define _ast_intswap %d\n", w);
+ printf("\n");
+ return 0;
+ }
+}end
+
+tst - output{
+ #include <string.h>
+ #include <sys/types.h>
+
+ #if _X86_ || _X64_
+ #define COND 1
+ #define CONDNAME "_X64_"
+ #else
+ #define COND 0
+ #endif
+
+ #define elementsof(x) (sizeof(x)/sizeof(x[0]))
+
+ static struct
+ {
+ char* name;
+ int size;
+ int cond;
+ } types[] =
+ {
+ "short", sizeof(short), 0,
+ "int", sizeof(int), 0,
+ "long", sizeof(long), 0,
+ "size_t", sizeof(size_t), 0,
+ "pointer", sizeof(void*), COND * 4,
+ "float", sizeof(float), 0,
+ "double", sizeof(double), 0,
+ #ifdef _typ_long_double
+ "long_double", sizeof(long double), 0,
+ #endif
+ };
+
+ int
+ main()
+ {
+ register int t;
+
+ for (t = 0; t < elementsof(types); t++)
+ #if COND
+ if (types[t].cond)
+ {
+ printf("#if %s\n", CONDNAME);
+ printf("#define _ast_sizeof_%s%s %d /* sizeof(%s) */\n", types[t].name, strlen(types[t].name) < 4 ? "\t" : "", types[t].cond * 2, types[t].name);
+ printf("#else\n");
+ printf("#define _ast_sizeof_%s%s %d /* sizeof(%s) */\n", types[t].name, strlen(types[t].name) < 4 ? "\t" : "", types[t].cond, types[t].name);
+ printf("#endif\n");
+ }
+ else
+ #endif
+ printf("#define _ast_sizeof_%s%s %d /* sizeof(%s) */\n", types[t].name, strlen(types[t].name) < 4 ? "\t" : "", types[t].size, types[t].name);
+ printf("\n");
+ return 0;
+ }
+}end
+
+tst - -DN=1 - -DN=0 output{
+ #define _BYTESEX_H
+
+ #include <string.h>
+ #include <sys/types.h>
+
+ #if !N || !_STD_
+ #undef _typ_long_double
+ #endif
+
+ #define elementsof(x) (sizeof(x)/sizeof(x[0]))
+
+ static struct
+ {
+ char* name;
+ int size;
+ } flt_type[] =
+ {
+ "float", sizeof(float),
+ "double", sizeof(double),
+ #ifdef _typ_long_double
+ "long double", sizeof(long double),
+ #endif
+ };
+
+ int
+ main()
+ {
+ register int t;
+ register int m = 1;
+
+ #ifdef _typ_long_double
+ long double p;
+ char buf[64];
+
+ if (flt_type[elementsof(flt_type)-1].size <= sizeof(double))
+ return 1;
+ p = 1.12345E-55;
+ sprintf(buf, "%1.5LE", p);
+ if (strcmp(buf, "1.12345E-55"))
+ return 1;
+ #endif
+ for (t = 0; t < elementsof(flt_type); t++)
+ {
+ while (t < (elementsof(flt_type) - 1) && flt_type[t].size == flt_type[t + 1].size)
+ t++;
+ m = flt_type[t].size;
+ printf("#define _ast_flt%d_t %s\n", flt_type[t].size, flt_type[t].name);
+ }
+ printf("#define _ast_fltmax_t _ast_flt%d_t\n", m);
+ if (m == sizeof(double))
+ printf("#define _ast_fltmax_double 1\n");
+ return 0;
+ }
+}end
+
+typ int8_t stdint.h inttypes.h no{
+ #undef _typ_int8_t
+ #define _typ_int8_t 1
+ typedef _ast_int1_t int8_t;
+}end
+typ uint8_t stdint.h inttypes.h no{
+ #undef _typ_uint8_t
+ #define _typ_uint8_t 1
+ typedef unsigned _ast_int1_t uint8_t;
+}end
+typ int16_t stdint.h inttypes.h no{
+ #undef _typ_int16_t
+ #define _typ_int16_t 1
+ typedef _ast_int2_t int16_t;
+}end
+typ uint16_t stdint.h inttypes.h no{
+ #undef _typ_uint16_t
+ #define _typ_uint16_t 1
+ typedef unsigned _ast_int2_t uint16_t;
+}end
+typ int32_t stdint.h inttypes.h no{
+ #undef _typ_int32_t
+ #define _typ_int32_t 1
+ typedef _ast_int4_t int32_t;
+}end
+typ uint32_t stdint.h inttypes.h no{
+ #undef _typ_uint32_t
+ #define _typ_uint32_t 1
+ typedef unsigned _ast_int4_t uint32_t;
+}end
+typ int64_t stdint.h inttypes.h no{
+ #ifdef _ast_int8_t
+ #undef _typ_int64_t
+ #define _typ_int64_t 1
+ typedef _ast_int8_t int64_t;
+ #endif
+}end
+typ uint64_t stdint.h inttypes.h no{
+ #ifdef _ast_int8_t
+ #undef _typ_uint64_t
+ #define _typ_uint64_t 1
+ typedef unsigned _ast_int8_t uint64_t;
+ #endif
+}end
+typ intmax_t stdint.h inttypes.h no{
+ #undef _typ_intmax_t
+ #define _typ_intmax_t 1
+ typedef _ast_intmax_t intmax_t;
+}end
+typ uintmax_t stdint.h inttypes.h no{
+ #undef _typ_uintmax_t
+ #define _typ_uintmax_t 1
+ typedef unsigned _ast_intmax_t uintmax_t;
+}end
+typ uintptr_t stdint.h inttypes.h no{
+ #undef _typ_uintptr_t
+ #define _typ_uintptr_t 1
+ #if _ast_sizeof_pointer == 8 && defined(_ast_int8_t)
+ typedef unsigned _ast_int8_t uintptr_t;
+ #else
+ typedef unsigned _ast_int4_t uintptr_t;
+ #endif
+}end
+
+tst - -DTRY=1 - -DTRY=1 -Dvoid=char - -DTRY=2 - -DTRY=3 - -DTRY=4 output{
+ #if _STD_ && _hdr_stdarg
+ #include <stdarg.h>
+ static void
+ varyfunny(int* p, ...)
+ {
+ va_list ap;
+ va_start(ap, p);
+ #if TRY == 1
+ *p = *ap++ != 0;
+ #endif /*TRY == 1*/
+ #if TRY == 2
+ *p = *ap != 0;
+ #endif /*TRY == 2*/
+ #if TRY == 3
+ *p = ap++ != 0;
+ #endif /*TRY == 3*/
+ va_end(ap);
+ }
+ #else
+ #include <varargs.h>
+ static void
+ varyfunny(va_alist)
+ va_dcl
+ {
+ va_list ap;
+ int* p;
+ va_start(ap);
+ p = va_arg(ap, int*);
+ #if TRY == 1
+ *p = *ap++ != 0;
+ #endif /*TRY == 1*/
+ #if TRY == 2
+ *p = *ap != 0;
+ #endif /*TRY == 2*/
+ #if TRY == 3
+ *p = ap++ != 0;
+ #endif /*TRY == 3*/
+ va_end(ap);
+ }
+ #endif
+ int
+ main()
+ {
+ int r;
+
+ printf("\n#ifndef va_listref\n");
+ printf("#ifndef va_start\n");
+ printf("#if __STD_C\n");
+ printf("#include <stdarg.h>\n");
+ printf("#else\n");
+ printf("#include <varargs.h>\n");
+ printf("#endif\n");
+ printf("#endif\n");
+ #if TRY == 4
+ printf("#define va_listref(p) (&(p))\t");
+ printf("/* pass va_list to varargs function */\n");
+ printf("#define va_listval(p) (*(p))\t");
+ printf("/* retrieve va_list from va_arg(ap,va_listarg) */\n");
+ printf("#define va_listarg va_list*\t");
+ printf("/* va_arg() va_list type */\n");
+ #else
+ varyfunny(&r);
+ printf("#define va_listref(p) (p)\t");
+ printf("/* pass va_list to varargs function */\n");
+ if (sizeof(va_list) > sizeof(void*))
+ printf("#define va_listval(p) (*(p))\t");
+ else
+ printf("#define va_listval(p) (p)\t");
+ printf("/* retrieve va_list from va_arg(ap,va_listarg) */\n");
+ #if TRY == 2
+ printf("#define va_listarg va_list*\t");
+ #else
+ printf("#define va_listarg va_list\t");
+ #endif /*TRY == 2*/
+ printf("/* va_arg() va_list type */\n");
+ #endif /*TRY == 4*/
+
+ #if _UWIN
+ printf("#ifndef va_copy\n");
+ printf("#define va_copy(to,fr) ((to)=(fr))\t");
+ printf("/* copy va_list fr -> to */\n");
+ printf("#endif\n");
+ #else
+ #if !defined(va_copy)
+ #if defined(__va_copy)
+ printf("#ifndef va_copy\n");
+ printf("#define va_copy(to,fr) __va_copy(to,fr)\t");
+ printf("/* copy va_list fr -> to */\n");
+ printf("#endif\n");
+ #else
+ #if TRY == 2
+ printf("#ifndef va_copy\n");
+ printf("#define va_copy(to,fr) memcpy(to,fr,sizeof(va_list))\t");
+ printf("/* copy va_list fr -> to */\n");
+ printf("#endif\n");
+ #else
+ printf("#ifndef va_copy\n");
+ printf("#define va_copy(to,fr) ((to)=(fr))\t");
+ printf("/* copy va_list fr -> to */\n");
+ printf("#endif\n");
+ #endif
+ #endif
+ #endif
+ #endif
+
+ printf("#endif\n");
+ return 0;
+ }
+}end
+
+cat{
+ #ifndef _AST_STD_H
+ # if __STD_C && _hdr_stddef
+ # include <stddef.h>
+ # endif
+ # if _sys_types
+ # include <sys/types.h>
+ # endif
+ # if _hdr_stdint
+ # include <stdint.h>
+ # else
+ # if _hdr_inttypes
+ # include <inttypes.h>
+ # endif
+ # endif
+ #endif
+ #if !_typ_size_t
+ # define _typ_size_t 1
+ typedef int size_t;
+ #endif
+ #if !_typ_ssize_t
+ # define _typ_ssize_t 1
+ typedef int ssize_t;
+ #endif
+ #ifndef _AST_STD_H
+ # define _def_map_ast 1
+ # if !_def_map_ast
+ # include <ast_map.h>
+ # endif
+ #endif
+}end
+
+run{
+ grep __NO_INCLUDE_WARN__ /usr/include/stat.h >/dev/null 2>&1 &&
+ grep '<name.h>' /usr/include/sys/stat.h >/dev/null 2>&1 &&
+ grep __name_h /usr/include/name.h >/dev/null 2>&1 &&
+ cat <<!
+ /* disable ${HOSTTYPE} <sys/foo.h> vs. <foo.h> clash warnings */
+ #ifndef __NO_INCLUDE_WARN__
+ #define __NO_INCLUDE_WARN__ 1
+ #endif
+ /* disable ${HOSTTYPE} <sys/stat.h> <name.h> hijack */
+ #ifndef __name_h
+ #define __name_h 1
+ #endif
+ !
+}end
diff --git a/src/lib/libast/features/dirent b/src/lib/libast/features/dirent
new file mode 100644
index 0000000..a36d35a
--- /dev/null
+++ b/src/lib/libast/features/dirent
@@ -0,0 +1,275 @@
+set prototyped
+
+set nodefine
+lib stat64 -D_LARGEFILE64_SOURCE
+typ off64_t -D_LARGEFILE64_SOURCE
+set define
+
+lib opendir
+hdr dirent,ndir
+sys dir
+nxt dirent
+
+tst botch_d_ino_dirent64 -D_LARGEFILE64_SOURCE note{ dirent64.d_ino vs. readdir64 mismatch }end compile{
+ #if !__arm__
+ )
+ #endif
+ #include <dirent.h>
+ int
+ main()
+ {
+ struct dirent64 ent;
+ char aha[5-((int)sizeof(ent.d_ino))];
+ return sizeof(aha);
+ }
+}end
+
+if ( ! _lib_opendir ) {
+ /*
+ * <dirent.h> for systems with no opendir()
+ */
+
+ #ifndef _DIRENT_H
+ #define _DIRENT_H
+
+ typedef struct
+ {
+ int dd_fd; /* file descriptor */
+ #ifdef _DIR_PRIVATE_
+ _DIR_PRIVATE_
+ #endif
+ } DIR;
+
+ struct dirent
+ {
+ long d_fileno; /* entry serial number */
+ int d_reclen; /* entry length */
+ int d_namlen; /* entry name length */
+ char d_name[1]; /* entry name */
+ };
+
+ #ifndef _DIR_PRIVATE_
+
+ #ifdef rewinddir
+ #undef rewinddir
+ #define rewinddir(p) seekdir(p,0L)
+ #endif
+
+ extern DIR* opendir(const char*);
+ extern void closedir(DIR*);
+ extern struct dirent* readdir(DIR*);
+ extern void seekdir(DIR*, long);
+ extern long telldir(DIR*);
+
+ #endif
+
+ #endif
+}
+elif ( _nxt_dirent && _lib_stat64 && _typ_off64_t && _botch_d_ino_dirent64 ) pass{
+cat <<!
+ /*
+ * <dirent.h> for [fl]stat64 and off64_t with sizeof(ino64_t)==4
+ */
+
+ #ifndef _AST_STD_H
+
+ #include ${_nxt_dirent-_nxt_dirent} /* the native <dirent.h> */
+
+ #else
+
+ #ifndef _DIR64_H
+ #define _DIR64_H
+
+ #include <ast_std.h>
+
+ #if _typ_off64_t
+ #undef off_t
+ #endif
+
+ #undef __ino64_t
+ #define __ino64_t int64_t
+
+ #include ${_nxt_dirent-_nxt_dirent} /* the native <dirent.h> */
+
+ #undef __ino64_t
+ #define __ino64_t __ino64_t
+
+ #if _typ_off64_t
+ #define off_t off64_t
+ #endif
+
+ #if _lib_readdir64 && _typ_struct_dirent64
+ #ifndef dirent
+ #define dirent dirent64
+ #endif
+ #ifndef readdir
+ #define readdir readdir64
+ #endif
+ #endif
+
+ #endif
+
+ #endif
+!
+}end
+elif ( _nxt_dirent && _lib_stat64 && _typ_off64_t ) pass{
+cat <<!
+ /*
+ * <dirent.h> for [fl]stat64 and off64_t
+ */
+
+ #ifndef _AST_STD_H
+
+ #include ${_nxt_dirent-_nxt_dirent} /* the native <dirent.h> */
+
+ #else
+
+ #ifndef _DIR64_H
+ #define _DIR64_H
+
+ #include <ast_std.h>
+
+ #if _typ_off64_t
+ #undef off_t
+ #endif
+
+ #include ${_nxt_dirent-_nxt_dirent} /* the native <dirent.h> */
+
+ #if _typ_off64_t
+ #define off_t off64_t
+ #endif
+
+ #if _lib_readdir64 && _typ_struct_dirent64
+ #ifndef dirent
+ #define dirent dirent64
+ #endif
+ #ifndef readdir
+ #define readdir readdir64
+ #endif
+ #endif
+
+ #endif
+
+ #endif
+!
+}end
+elif ( _nxt_dirent && _hdr_dirent ) pass{
+cat <<!
+ /*
+ * <dirent.h> for systems with ok <dirent.h>
+ */
+
+ #ifndef _DIRENT_H
+
+ #include ${_nxt_dirent-_nxt_dirent} /* the native <dirent.h> */
+
+ #ifndef _DIRENT_H
+ #define _DIRENT_H
+ #endif
+
+ #endif
+!
+}end
+elif ( _hdr_ndir ) {
+ /*
+ * <dirent.h> for systems with opendir() and <ndir.h>
+ */
+
+ #ifndef _DIRENT_H
+ #define _DIRENT_H
+
+ #if defined(__STDPP__directive) && defined(__STDPP__hide)
+ __STDPP__directive pragma pp:hide closedir opendir readdir seekdir telldir
+ #else
+ #define closedir ______closedir
+ #define opendir ______opendir
+ #define readdir ______readdir
+ #define seekdir ______seekdir
+ #define telldir ______telldir
+ #endif
+
+ #include <ndir.h>
+
+ #if defined(__STDPP__directive) && defined(__STDPP__hide)
+ __STDPP__directive pragma pp:nohide closedir opendir readdir seekdir telldir
+ #else
+ #undef closedir
+ #undef opendir
+ #undef readdir
+ #undef seekdir
+ #undef telldir
+ #endif
+
+ #ifndef dirent
+ #define dirent direct
+ #endif
+
+ #if !defined(d_fileno) && !defined(d_ino)
+ #define d_fileno d_ino
+ #endif
+
+ #ifdef rewinddir
+ #undef rewinddir
+ #define rewinddir(p) seekdir(p,0L)
+ #endif
+
+ extern DIR* opendir(const char*);
+ extern void closedir(DIR*);
+ extern struct dirent* readdir(DIR*);
+ extern void seekdir(DIR*, long);
+ extern long telldir(DIR*);
+
+ #endif
+}
+elif ( _sys_dir ) {
+ /*
+ * <dirent.h> for systems with opendir() and no <ndir.h>
+ */
+
+ #ifndef _DIRENT_H
+ #define _DIRENT_H
+
+ #if defined(__STDPP__directive) && defined(__STDPP__hide)
+ __STDPP__directive pragma pp:hide closedir opendir readdir seekdir telldir
+ #else
+ #define closedir ______closedir
+ #define opendir ______opendir
+ #define readdir ______readdir
+ #define seekdir ______seekdir
+ #define telldir ______telldir
+ #endif
+
+ #include <sys/dir.h>
+
+ #if defined(__STDPP__directive) && defined(__STDPP__hide)
+ __STDPP__directive pragma pp:nohide closedir opendir readdir seekdir telldir
+ #else
+ #undef closedir
+ #undef opendir
+ #undef readdir
+ #undef seekdir
+ #undef telldir
+ #endif
+
+ #ifndef dirent
+ #define dirent direct
+ #endif
+
+ #if !defined(d_fileno) && !defined(d_ino)
+ #define d_fileno d_ino
+ #endif
+
+ #ifdef rewinddir
+ #undef rewinddir
+ #define rewinddir(p) seekdir(p,0L)
+ #endif
+
+ extern DIR* opendir(const char*);
+ extern void closedir(DIR*);
+ extern struct dirent* readdir(DIR*);
+ extern void seekdir(DIR*, long);
+ extern long telldir(DIR*);
+
+ #endif
+}
+endif
diff --git a/src/lib/libast/features/eaccess b/src/lib/libast/features/eaccess
new file mode 100644
index 0000000..bf9710a
--- /dev/null
+++ b/src/lib/libast/features/eaccess
@@ -0,0 +1,11 @@
+lib eaccess,euidaccess
+macro{
+ #include <sys/types.h>
+ #include <unistd.h>
+ #ifdef EFF_ONLY_OK
+ <<"#define EFF_ONLY_OK">> EFF_ONLY_OK
+ #endif
+ #ifdef EX_OK
+ <<"#define EX_OK">> EX_OK
+ #endif
+}end
diff --git a/src/lib/libast/features/errno b/src/lib/libast/features/errno
new file mode 100644
index 0000000..271fe6d
--- /dev/null
+++ b/src/lib/libast/features/errno
@@ -0,0 +1,31 @@
+tst dat_sys_nerr note{ sys_nerr in default libs }end compile{
+ extern int sys_nerr;
+ int f()
+ {
+ return sys_nerr > 0;
+ }
+}end
+
+tst def_errno_sys_nerr note{ sys_nerr declared in errno.h }end compile{
+ #include <errno.h>
+ int f()
+ {
+ return sys_nerr > 0;
+ }
+}end
+
+tst dat_sys_errlist note{ sys_errlist in default libs }end compile{
+ extern char* sys_errlist[];
+ int f()
+ {
+ return *sys_errlist[1] != 0;
+ }
+}end
+
+tst def_errno_sys_errlist note{ sys_errlist declared in errno.h }end compile{
+ #include <errno.h>
+ int f()
+ {
+ return *sys_errlist[1] != 0;
+ }
+}end
diff --git a/src/lib/libast/features/fcntl.c b/src/lib/libast/features/fcntl.c
new file mode 100644
index 0000000..0868f06
--- /dev/null
+++ b/src/lib/libast/features/fcntl.c
@@ -0,0 +1,360 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * generate POSIX fcntl.h
+ */
+
+#include <sys/types.h>
+
+#include "FEATURE/lib"
+
+#define getdtablesize ______getdtablesize
+#define getpagesize ______getpagesize
+#define ioctl ______ioctl
+
+#if _typ_off64_t
+#undef off_t
+#ifdef __STDC__
+#define off_t off_t
+#endif
+#endif
+
+#if _hdr_fcntl
+#include <fcntl.h>
+#endif
+#if _hdr_unistd
+#include <unistd.h>
+#endif
+
+#include <sys/stat.h>
+
+#include "FEATURE/fs"
+
+#undef getdtablesize
+#undef getpagesize
+#undef ioctl
+
+#include "FEATURE/tty"
+
+#if _typ_off64_t
+#undef off_t
+#define off_t off64_t
+#endif
+
+int
+main()
+{
+ int f_local = 0;
+ int f_lck = 0;
+ int o_local = 2;
+
+ printf("#pragma prototyped\n");
+ printf("\n");
+ printf("#if _typ_off64_t\n");
+ printf("#undef off_t\n");
+ printf("#ifdef __STDC__\n");
+ printf("#define off_t off_t\n");
+ printf("#endif\n");
+ printf("#endif\n");
+ printf("\n");
+ printf("#include <ast_fs.h>\n");
+ printf("\n");
+ printf("#if _typ_off64_t\n");
+ printf("#undef off_t\n");
+ printf("#ifdef __STDC__\n");
+ printf("#define off_t off_t\n");
+ printf("#endif\n");
+ printf("#endif\n");
+ printf("\n");
+ printf("#include <fcntl.h>\n");
+#if _hdr_mman
+ printf("#include <mman.h>\n");
+#else
+#if _sys_mman
+ printf("#include <sys/mman.h>\n");
+#endif
+#endif
+ printf("\n");
+#ifndef FD_CLOEXEC
+ printf("#define FD_CLOEXEC 1\n");
+ printf("\n");
+#endif
+
+#ifndef F_DUPFD
+#define NEED_F 1
+#else
+ if (F_DUPFD > f_local) f_local = F_DUPFD;
+#endif
+#ifndef F_GETFD
+#define NEED_F 1
+#else
+ if (F_GETFD > f_local) f_local = F_GETFD;
+#endif
+#ifndef F_GETFL
+#define NEED_F 1
+#else
+ if (F_GETFL > f_local) f_local = F_GETFL;
+#endif
+#ifndef F_GETLK
+#define NEED_F 1
+#else
+ if (F_GETLK > f_local) f_local = F_GETLK;
+#endif
+#ifndef F_RDLCK
+#define NEED_F 1
+#define NEED_LCK 1
+#else
+ if (F_RDLCK > f_lck) f_lck = F_RDLCK;
+#endif
+#ifndef F_SETFD
+#define NEED_F 1
+#else
+ if (F_SETFD > f_local) f_local = F_SETFD;
+#endif
+#ifndef F_SETFL
+#define NEED_F 1
+#else
+ if (F_SETFL > f_local) f_local = F_SETFL;
+#endif
+#ifndef F_SETLK
+#define NEED_F 1
+#else
+ if (F_SETLK > f_local) f_local = F_SETLK;
+#endif
+#ifndef F_SETLKW
+#define NEED_F 1
+#else
+ if (F_SETLKW > f_local) f_local = F_SETLKW;
+#endif
+#ifndef F_UNLCK
+#define NEED_F 1
+#define NEED_LCK 1
+#else
+ if (F_UNLCK > f_lck) f_lck = F_UNLCK;
+#endif
+#ifndef F_WRLCK
+#define NEED_F 1
+#define NEED_LCK 1
+#else
+ if (F_WRLCK > f_lck) f_lck = F_WRLCK;
+#endif
+
+#if NEED_F
+ printf("#define fcntl _ast_fcntl\n");
+#if _lib_fcntl
+ printf("#define _lib_fcntl 1\n");
+#endif
+ printf("#define _ast_F_LOCAL %d\n", f_local + 1);
+#ifndef F_DUPFD
+ printf("#define F_DUPFD %d\n", ++f_local);
+#endif
+#ifndef F_GETFD
+ printf("#define F_GETFD %d\n", ++f_local);
+#endif
+#ifndef F_GETFL
+ printf("#define F_GETFL %d\n", ++f_local);
+#endif
+#ifndef F_GETLK
+ printf("#define F_GETLK %d\n", ++f_local);
+#endif
+#ifndef F_SETFD
+ printf("#define F_SETFD %d\n", ++f_local);
+#endif
+#ifndef F_SETFL
+ printf("#define F_SETFL %d\n", ++f_local);
+#endif
+#ifndef F_SETLK
+ printf("#define F_SETLK %d\n", ++f_local);
+#endif
+#ifndef F_SETLKW
+ printf("#define F_SETLKW %d\n", ++f_local);
+#endif
+#if NEED_LCK
+ printf("\n");
+#ifndef F_RDLCK
+ printf("#define F_RDLCK %d\n", f_lck++);
+#endif
+#ifndef F_WRLCK
+ printf("#define F_WRLCK %d\n", f_lck++);
+#endif
+#ifndef F_UNLCK
+ printf("#define F_UNLCK %d\n", f_lck++);
+#endif
+#endif
+ printf("\n");
+ if (f_lck == 3)
+ {
+ printf("struct flock\n");
+ printf("{\n");
+ printf(" short l_type;\n");
+ printf(" short l_whence;\n");
+ printf(" off_t l_start;\n");
+ printf(" off_t l_len;\n");
+ printf(" short l_pid;\n");
+ printf("};\n");
+ printf("\n");
+ }
+ printf("\n");
+#endif
+
+#ifndef O_APPEND
+#define NEED_O 1
+#else
+ if (O_APPEND > o_local) o_local = O_APPEND;
+#endif
+#ifndef O_CREAT
+#define NEED_O 1
+#else
+ if (O_CREAT > o_local) o_local = O_CREAT;
+#endif
+#ifndef O_EXCL
+#define NEED_O 1
+#else
+ if (O_EXCL > o_local) o_local = O_EXCL;
+#endif
+#ifndef O_NOCTTY
+#ifdef TIOCNOTTY
+#define NEED_O 1
+#endif
+#else
+ if (O_NOCTTY > o_local) o_local = O_NOCTTY;
+#endif
+#ifndef O_NONBLOCK
+#ifndef O_NDELAY
+#define NEED_O 1
+#endif
+#else
+ if (O_NONBLOCK > o_local) o_local = O_NONBLOCK;
+#endif
+#ifndef O_RDONLY
+#define NEED_O 1
+#endif
+#ifndef O_RDWR
+#define NEED_O 1
+#endif
+#ifndef O_TRUNC
+#define NEED_O 1
+#else
+ if (O_TRUNC > o_local) o_local = O_TRUNC;
+#endif
+#ifndef O_WRONLY
+#define NEED_O 1
+#endif
+
+#if NEED_O
+ printf("#define open _ast_open\n");
+ printf("#define _ast_O_LOCAL 0%o\n", o_local<<1);
+#ifndef O_RDONLY
+ printf("#define O_RDONLY 0\n");
+#endif
+#ifndef O_WRONLY
+ printf("#define O_WRONLY 1\n");
+#endif
+#ifndef O_RDWR
+ printf("#define O_RDWR 2\n");
+#endif
+#ifndef O_APPEND
+ printf("#define O_APPEND 0%o\n", o_local <<= 1);
+#endif
+#ifndef O_CREAT
+ printf("#define O_CREAT 0%o\n", o_local <<= 1);
+#endif
+#ifndef O_EXCL
+ printf("#define O_EXCL 0%o\n", o_local <<= 1);
+#endif
+#ifndef O_NOCTTY
+#ifdef TIOCNOTTY
+ printf("#define O_NOCTTY 0%o\n", o_local <<= 1);
+#endif
+#endif
+#ifndef O_NONBLOCK
+#ifndef O_NDELAY
+ printf("#define O_NONBLOCK 0%o\n", o_local <<= 1);
+#endif
+#endif
+#ifndef O_TRUNC
+ printf("#define O_TRUNC 0%o\n", o_local <<= 1);
+#endif
+#endif
+#ifndef O_ACCMODE
+ printf("#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)\n");
+#endif
+#ifndef O_NOCTTY
+#ifndef TIOCNOTTY
+ printf("#define O_NOCTTY 0\n");
+#endif
+#endif
+#ifndef O_NONBLOCK
+#ifdef O_NDELAY
+ printf("#define O_NONBLOCK O_NDELAY\n");
+#endif
+#endif
+#ifndef O_BINARY
+ printf("#define O_BINARY 0\n");
+#endif
+#ifndef O_TEMPORARY
+ printf("#define O_TEMPORARY 0\n");
+#endif
+#ifndef O_TEXT
+ printf("#define O_TEXT 0\n");
+#endif
+#if NEED_F || NEED_O
+ printf("\n");
+#if NEED_F
+ printf("extern int fcntl(int, int, ...);\n");
+#endif
+#if NEED_O
+ printf("extern int open(const char*, int, ...);\n");
+#endif
+#endif
+ printf("\n");
+ printf("#include <ast_fs.h>\n");
+ printf("#if _typ_off64_t\n");
+ printf("#undef off_t\n");
+ printf("#define off_t off64_t\n");
+ printf("#endif\n");
+ printf("#if _lib_fstat64\n");
+ printf("#define fstat fstat64\n");
+ printf("#endif\n");
+ printf("#if _lib_lstat64\n");
+ printf("#define lstat lstat64\n");
+ printf("#endif\n");
+ printf("#if _lib_stat64\n");
+ printf("#define stat stat64\n");
+ printf("#endif\n");
+ printf("#if _lib_creat64\n");
+ printf("#define creat creat64\n");
+ printf("#endif\n");
+ printf("#if _lib_mmap64\n");
+ printf("#define mmap mmap64\n");
+ printf("#endif\n");
+ printf("#if _lib_open64\n");
+ printf("#undef open\n");
+ printf("#define open open64\n");
+ printf("#endif\n");
+
+ return 0;
+}
diff --git a/src/lib/libast/features/float b/src/lib/libast/features/float
new file mode 100644
index 0000000..de27bb2
--- /dev/null
+++ b/src/lib/libast/features/float
@@ -0,0 +1,1191 @@
+set prototyped
+set nooptimize
+set stdio FEATURE/isoc99
+hdr float,limits,math,values
+lib fpclassify,frexp,frexpl,ldexp,ldexpl,finite,finitel,isinf,isinfl,isnan,isnanl,signbit,copysign,copysignl FEATURE/isoc99 math.h -lm
+
+tst ast_no_um2fm note{ no unsigned intmax => floatmax cast }end nolink{
+ #include "FEATURE/common"
+ int
+ main()
+ {
+ _ast_fltmax_t f = 0;
+ unsigned _ast_intmax_t i = 0;
+ f = i;
+ i = f;
+ return f == i;
+ }
+}end
+
+tst ast_mpy_overflow_fpe note{ fpe on mpy overflow }end noexecute{
+ int
+ main()
+ {
+ float f;
+ float p;
+ int i;
+
+ i = 0;
+ p = f = 1.0;
+ do
+ {
+ p = f;
+ f *= 2.0;
+ } while (f != p && ++i < 1024);
+ return 0;
+ }
+}end
+
+tst ast_div_underflow_fpe note{ fpe on div underflow }end noexecute{
+ int
+ main()
+ {
+ float f;
+ float p;
+ int i;
+
+ i = 0;
+ p = f = 1.0;
+ do
+ {
+ p = f;
+ f /= 2.0;
+ } while (f != p && ++i < 1024);
+ return 0;
+ }
+}end
+
+macro{
+ #if _hdr_float
+ #include <float.h>
+ #endif
+ #if _hdr_limits
+ #include <limits.h>
+ #endif
+ #if _hdr_math
+ #include <math.h>
+ #endif
+ #if _hdr_values
+ #include <values.h>
+ #endif
+
+ #if !defined(FLT_MIN_EXP) && defined(FMINEXP)
+ #define FLT_MIN_EXP FMINEXP
+ #endif
+ #if !defined(FLT_MIN) && defined(MINFLOAT)
+ #define FLT_MIN MINFLOAT
+ #endif
+ #if !defined(FLT_MAX_EXP) && defined(FMAXEXP)
+ #define FLT_MAX_EXP FMAXEXP
+ #endif
+ #if !defined(FLT_MAX) && defined(MAXFLOAT)
+ #define FLT_MAX MAXFLOAT
+ #endif
+
+ #if !defined(DBL_MIN_EXP) && defined(DMINEXP)
+ #define DBL_MIN_EXP DMINEXP
+ #endif
+ #if !defined(DBL_MIN) && defined(MINDOUBLE)
+ #define DBL_MIN MINDOUBLE
+ #endif
+ #if !defined(DBL_MAX_EXP) && defined(DMAXEXP)
+ #define DBL_MAX_EXP DMAXEXP
+ #endif
+ #if !defined(DBL_MAX) && defined(MAXDOUBLE)
+ #define DBL_MAX MAXDOUBLE
+ #endif
+
+ <<"#include <ast_common.h>">>
+ #if _hdr_float
+ <<"#include <float.h>">>
+ #endif
+ #if _hdr_math
+ <<"#include <math.h>">>
+ #endif
+ #ifdef FLT_DIG
+ <<"#ifndef FLT_DIG">>
+ <<"#define FLT_DIG">> FLT_DIG
+ <<"#endif">>
+ #endif
+ #ifdef FLT_MAX
+ <<"#ifndef FLT_MAX">>
+ <<"#define FLT_MAX">> FLT_MAX
+ <<"#endif">>
+ #endif
+ #ifdef FLT_MAX_10_EXP
+ <<"#ifndef FLT_MAX_10_EXP">>
+ <<"#define FLT_MAX_10_EXP">> FLT_MAX_10_EXP
+ <<"#endif">>
+ #endif
+ #ifdef FLT_MAX_EXP
+ <<"#ifndef FLT_MAX_EXP">>
+ <<"#define FLT_MAX_EXP">> FLT_MAX_EXP
+ <<"#endif">>
+ #endif
+ #ifdef FLT_MIN
+ <<"#ifndef FLT_MIN">>
+ <<"#define FLT_MIN">> FLT_MIN
+ <<"#endif">>
+ #endif
+ #ifdef FLT_MIN_10_EXP
+ <<"#ifndef FLT_MIN_10_EXP">>
+ <<"#define FLT_MIN_10_EXP">> FLT_MIN_10_EXP
+ <<"#endif">>
+ #endif
+ #ifdef FLT_MIN_EXP
+ <<"#ifndef FLT_MIN_EXP">>
+ <<"#define FLT_MIN_EXP">> FLT_MIN_EXP
+ <<"#endif">>
+ #endif
+
+ #ifdef DBL_DIG
+ <<"#ifndef DBL_DIG">>
+ <<"#define DBL_DIG">> DBL_DIG
+ <<"#endif">>
+ #endif
+ #ifdef DBL_MAX
+ <<"#ifndef DBL_MAX">>
+ <<"#define DBL_MAX">> DBL_MAX
+ <<"#endif">>
+ #endif
+ #ifdef DBL_MAX_10_EXP
+ <<"#ifndef DBL_MAX_10_EXP">>
+ <<"#define DBL_MAX_10_EXP">> DBL_MAX_10_EXP
+ <<"#endif">>
+ #endif
+ #ifdef DBL_MAX_EXP
+ <<"#ifndef DBL_MAX_EXP">>
+ <<"#define DBL_MAX_EXP">> DBL_MAX_EXP
+ <<"#endif">>
+ #endif
+ #ifdef DBL_MIN
+ <<"#ifndef DBL_MIN">>
+ <<"#define DBL_MIN">> DBL_MIN
+ <<"#endif">>
+ #endif
+ #ifdef DBL_MIN_10_EXP
+ <<"#ifndef DBL_MIN_10_EXP">>
+ <<"#define DBL_MIN_10_EXP">> DBL_MIN_10_EXP
+ <<"#endif">>
+ #endif
+ #ifdef DBL_MIN_EXP
+ <<"#ifndef DBL_MIN_EXP">>
+ <<"#define DBL_MIN_EXP">> DBL_MIN_EXP
+ <<"#endif">>
+ #endif
+
+ #ifdef LDBL_DIG
+ <<"#ifndef LDBL_DIG">>
+ <<"#define LDBL_DIG">> LDBL_DIG
+ <<"#endif">>
+ #endif
+ #ifdef LDBL_MAX
+ <<"#ifndef LDBL_MAX">>
+ <<"#define LDBL_MAX">> LDBL_MAX
+ <<"#endif">>
+ #endif
+ #ifdef LDBL_MAX_10_EXP
+ <<"#ifndef LDBL_MAX_10_EXP">>
+ <<"#define LDBL_MAX_10_EXP">> LDBL_MAX_10_EXP
+ <<"#endif">>
+ #endif
+ #ifdef LDBL_MAX_EXP
+ <<"#ifndef LDBL_MAX_EXP">>
+ <<"#define LDBL_MAX_EXP">> LDBL_MAX_EXP
+ <<"#endif">>
+ #endif
+ #ifdef LDBL_MIN
+ <<"#ifndef LDBL_MIN">>
+ <<"#define LDBL_MIN">> LDBL_MIN
+ <<"#endif">>
+ #endif
+ #ifdef LDBL_MIN_10_EXP
+ <<"#ifndef LDBL_MIN_10_EXP">>
+ <<"#define LDBL_MIN_10_EXP">> LDBL_MIN_10_EXP
+ <<"#endif">>
+ #endif
+ #ifdef LDBL_MIN_EXP
+ <<"#ifndef LDBL_MIN_EXP">>
+ <<"#define LDBL_MIN_EXP">> LDBL_MIN_EXP
+ <<"#endif">>
+ #endif
+}end
+
+tst - note{ missing floating point limits }end output{
+ #include "FEATURE/common"
+ #include <stdio.h>
+ #if _hdr_float
+ #include <float.h>
+ #endif
+ #if _hdr_limits
+ #include <limits.h>
+ #endif
+ #if _hdr_math
+ #include <math.h>
+ #endif
+ #if _hdr_values
+ #include <values.h>
+ #endif
+ #include <signal.h>
+ #ifdef SIGFPE
+ static int caught = 0;
+ #if _STD_
+ static void catch(int sig)
+ #else
+ static void catch(sig) int sig;
+ #endif
+ {
+ signal(sig, SIG_IGN);
+ caught++;
+ }
+ #endif
+ int
+ main()
+ {
+ register int i;
+ register int s;
+ float f;
+ float pf;
+ float mf;
+ float xf;
+ double d;
+ double pd;
+ double md;
+ char* fp;
+ #if _ast_fltmax_double
+ char* fs = "";
+ char* ds = "";
+ #else
+ _ast_fltmax_t l;
+ _ast_fltmax_t pl;
+ _ast_fltmax_t ml;
+ char* fs = "F";
+ char* ds = "";
+ char* ls = "L";
+ #endif
+ unsigned long u;
+ unsigned _ast_intmax_t w;
+ unsigned _ast_intmax_t pw;
+ unsigned _ast_intmax_t x;
+ unsigned short us;
+ unsigned int ui;
+ unsigned long ul;
+ unsigned _ast_intmax_t uq;
+
+ #ifdef SIGFPE
+ signal(SIGFPE, catch);
+ #endif
+ printf("\n");
+ printf("\n");
+ us = 0;
+ us = ~us;
+ i = 0;
+ while (us /= 10)
+ i++;
+ printf("#define USHRT_DIG %d\n", i);
+ ui = 0;
+ ui = ~ui;
+ i = 0;
+ while (ui /= 10)
+ i++;
+ printf("#define UINT_DIG %d\n", i);
+ ul = 0;
+ ul = ~ul;
+ i = 0;
+ while (ul /= 10)
+ i++;
+ printf("#define ULONG_DIG %d\n", i);
+ if (sizeof(uq) > sizeof(ul))
+ {
+ uq = 0;
+ uq = ~uq;
+ i = 0;
+ while (uq /= 10)
+ i++;
+ printf("#define ULLONG_DIG %d\n", i);
+ printf("#define UINTMAX_DIG ULLONG_DIG\n");
+ }
+ else
+ printf("#define UINTMAX_DIG ULONG_DIG\n");
+ printf("\n");
+ w = 1;
+ do
+ {
+ pw = w;
+ w *= 2;
+ f = (_ast_intmax_t)w;
+ x = (_ast_intmax_t)f;
+ } while (w > pw && w == x);
+ w = (pw - 1) + pw;
+ u = ~0;
+ if (u > w)
+ u = w;
+ printf("#define FLT_ULONG_MAX %lu.0F\n", u);
+ if (sizeof(w) > sizeof(u))
+ {
+ printf("#define FLT_ULLONG_MAX %llu.0F\n", w);
+ printf("#define FLT_UINTMAX_MAX FLT_ULLONG_MAX\n");
+ }
+ else
+ {
+ printf("#define FLT_ULLONG_MAX FLT_ULONG_MAX\n");
+ printf("#define FLT_UINTMAX_MAX FLT_ULONG_MAX\n");
+ }
+ u /= 2;
+ w /= 2;
+ printf("#define FLT_LONG_MAX %lu.0F\n", u);
+ if (sizeof(w) > sizeof(u))
+ {
+ printf("#define FLT_LLONG_MAX %llu.0F\n", w);
+ printf("#define FLT_INTMAX_MAX FLT_LLONG_MAX\n");
+ }
+ else
+ {
+ printf("#define FLT_LLONG_MAX FLT_LONG_MAX\n");
+ printf("#define FLT_INTMAX_MAX FLT_LONG_MAX\n");
+ }
+ u++;
+ w++;
+ printf("#define FLT_LONG_MIN (-%lu.0F)\n", u);
+ if (sizeof(w) > sizeof(u))
+ {
+ printf("#define FLT_LLONG_MIN (-%llu.0F)\n", w);
+ printf("#define FLT_INTMAX_MIN FLT_LLONG_MIN\n");
+ }
+ else
+ {
+ printf("#define FLT_LLONG_MIN FLT_LONG_MIN\n");
+ printf("#define FLT_INTMAX_MIN FLT_LONG_MIN\n");
+ }
+ #ifdef FLT_DIG
+ s = FLT_DIG;
+ #else
+ f = pf = 1.0;
+ s = -1;
+ do
+ {
+ s++;
+ f *= 10.0;
+ } while (f != (f + pf));
+ #endif
+ #if defined(FLT_MIN) && defined(FLT_MIN_EXP)
+ i = FLT_MIN_EXP;
+ mf = FLT_MIN;
+ #else
+ i = 3;
+ f = pf = 1.0;
+ do
+ {
+ i--;
+ mf = pf;
+ pf = f;
+ f /= 2.0;
+ } while (f < pf);
+ #ifdef FLT_MIN_EXP
+ i = FLT_MIN_EXP;
+ #endif
+ #ifdef FLT_MIN
+ mf = FLT_MIN;
+ #endif
+ #endif
+ #ifndef FLT_DIG
+ printf("#ifndef FLT_DIG\n");
+ printf("#define FLT_DIG %d\n", s);
+ printf("#endif\n");
+ #endif
+ #ifndef FLT_MIN
+ printf("#ifndef FLT_MIN\n");
+ printf("#define FLT_MIN %.*E%s\n", s + 1, mf, fs);
+ printf("#endif\n");
+ #endif
+ #ifndef FLT_MIN_EXP
+ printf("#ifndef FLT_MIN_EXP\n");
+ printf("#define FLT_MIN_EXP (%d)\n", i);
+ printf("#endif\n");
+ #endif
+
+ #if defined(FLT_MAX) && defined(FLT_MAX_EXP)
+ i = FLT_MAX_EXP;
+ f = FLT_MAX;
+ #else
+ i = -1;
+ f = pf = 1.0;
+ do
+ {
+ i++;
+ mf = pf;
+ pf = f;
+ f *= 2.0;
+ } while (f > pf);
+ #ifdef FLT_MAX_EXP
+ i = FLT_MAX_EXP;
+ #endif
+ #ifdef FLT_MAX
+ f = FLT_MAX;
+ #endif
+ #endif
+ #ifdef FLT_MAX_EXP
+ i = FLT_MAX_EXP;
+ #else
+ f = 1;
+ do
+ {
+ f *= 2.0;
+ } while (mf == (mf + f));
+ f = (mf - f) * 2.0 + f;
+ #endif
+ xf = f;
+ #ifndef FLT_MAX
+ printf("#ifndef FLT_MAX\n");
+ printf("#define FLT_MAX %.*E%s\n", s + 1, f, fs);
+ printf("#endif\n");
+ #endif
+ #ifndef FLT_MAX_EXP
+ printf("#ifndef FLT_MAX_EXP\n");
+ printf("#define FLT_MAX_EXP %d\n", i);
+ printf("#endif\n");
+ #endif
+
+ #ifdef FLT_MIN_10_EXP
+ i = FLT_MIN_10_EXP;
+ #else
+ i = 2;
+ f = 1.0;
+ do
+ {
+ i--;
+ pf = f;
+ f /= 10.0;
+ } while (f < pf);
+ #endif
+ #ifndef FLT_MIN_10_EXP
+ printf("#ifndef FLT_MIN_10_EXP\n");
+ printf("#define FLT_MIN_10_EXP (%d)\n", i);
+ printf("#endif\n");
+ #endif
+
+ #ifdef FLT_MAX_10_EXP
+ i = FLT_MAX_10_EXP;
+ #else
+ i = -2;
+ f = 1.0;
+ do
+ {
+ i++;
+ pf = f;
+ f *= 10.0;
+ } while (f > pf);
+ #endif
+ #ifndef FLT_MAX_10_EXP
+ printf("#ifndef FLT_MAX_10_EXP\n");
+ printf("#define FLT_MAX_10_EXP %d\n", i);
+ printf("#endif\n");
+ #endif
+
+ printf("\n");
+ w = 1;
+ do
+ {
+ pw = w;
+ w *= 2;
+ d = (_ast_intmax_t)w;
+ x = (_ast_intmax_t)d;
+ } while (w > pw && w == x);
+ w = (pw - 1) + pw;
+ u = ~0;
+ if (u > w)
+ u = w;
+ printf("#define DBL_ULONG_MAX %lu.0\n", u);
+ if (sizeof(w) > sizeof(u))
+ {
+ printf("#define DBL_ULLONG_MAX %llu.0\n", w);
+ printf("#define DBL_UINTMAX_MAX DBL_ULLONG_MAX\n");
+ }
+ else
+ {
+ printf("#define DBL_ULLONG_MAX DBL_ULONG_MAX\n");
+ printf("#define DBL_UINTMAX_MAX DBL_ULONG_MAX\n");
+ }
+ u /= 2;
+ w /= 2;
+ printf("#define DBL_LONG_MAX %lu.0\n", u);
+ if (sizeof(w) > sizeof(u))
+ {
+ printf("#define DBL_LLONG_MAX %llu.0\n", w);
+ printf("#define DBL_INTMAX_MAX DBL_LLONG_MAX\n");
+ }
+ else
+ {
+ printf("#define DBL_LLONG_MAX DBL_LONG_MAX\n");
+ printf("#define DBL_INTMAX_MAX DBL_LONG_MAX\n");
+ }
+ u++;
+ w++;
+ printf("#define DBL_LONG_MIN (-%lu.0)\n", u);
+ if (sizeof(w) > sizeof(u))
+ {
+ printf("#define DBL_LLONG_MIN (-%llu.0)\n", w);
+ printf("#define DBL_INTMAX_MIN DBL_LLONG_MIN\n");
+ }
+ else
+ {
+ printf("#define DBL_LLONG_MIN DBL_LONG_MIN\n");
+ printf("#define DBL_INTMAX_MIN DBL_LONG_MIN\n");
+ }
+ #ifdef DBL_DIG
+ s = DBL_DIG;
+ #else
+ d = pd = 1.0;
+ s = -1;
+ do
+ {
+ s++;
+ d *= 10.0;
+ } while (d != (d + pd));
+ #endif
+ #if defined(DBL_MIN) && defined(DBL_MIN_EXP)
+ i = DBL_MIN_EXP;
+ md = DBL_MIN;
+ #else
+ i = 3;
+ d = pd = 1.0;
+ do
+ {
+ i--;
+ md = pd;
+ pd = d;
+ d /= 2.0;
+ } while (d < pd);
+ #ifdef DBL_MIN_EXP
+ i = DBL_MIN_EXP;
+ #endif
+ #ifdef DBL_MIN
+ md = DBL_MIN;
+ #endif
+ #endif
+ #ifndef DBL_DIG
+ printf("#ifndef DBL_DIG\n");
+ printf("#define DBL_DIG %d\n", s);
+ printf("#endif\n");
+ #endif
+ #ifndef DBL_MIN
+ printf("#ifndef DBL_MIN\n");
+ printf("#define DBL_MIN %.*E%s\n", s + 1, md, ds);
+ printf("#endif\n");
+ #endif
+ #ifndef DBL_MIN_EXP
+ printf("#ifndef DBL_MIN_EXP\n");
+ printf("#define DBL_MIN_EXP (%d)\n", i);
+ printf("#endif\n");
+ #endif
+
+ #if defined(DBL_MAX) && defined(DBL_MAX_EXP)
+ i = DBL_MAX_EXP;
+ d = DBL_MAX;
+ #else
+ i = -1;
+ d = pd = 1.0;
+ do
+ {
+ i++;
+ md = pd;
+ pd = d;
+ d *= 2.0;
+ } while (d > pd);
+ d = 1.0;
+ do
+ {
+ d *= 2.0;
+ } while (md == (md + d));
+ d = (md - d) * 2.0 + d;
+ #ifdef DBL_MAX_EXP
+ i = DBL_MAX_EXP;
+ #endif
+ #ifdef DBL_MAX
+ d = DBL_MAX;
+ #endif
+ #endif
+ #ifndef DBL_MAX
+ printf("#ifndef DBL_MAX\n");
+ printf("#define DBL_MAX %.*E%s\n", s + 1, d, ds);
+ printf("#endif\n");
+ #endif
+ #ifndef DBL_MAX_EXP
+ printf("#ifndef DBL_MAX_EXP\n");
+ printf("#define DBL_MAX_EXP %d\n", i);
+ printf("#endif\n");
+ #endif
+
+ #ifdef DBL_MIN_10_EXP
+ i = DBL_MIN_10_EXP;
+ #else
+ i = 2;
+ d = 1.0;
+ do
+ {
+ i--;
+ pd = d;
+ d /= 10.0;
+ } while (d < pd);
+ #endif
+ #ifndef DBL_MIN_10_EXP
+ printf("#ifndef DBL_MIN_10_EXP\n");
+ printf("#define DBL_MIN_10_EXP (%d)\n", i);
+ printf("#endif\n");
+ #endif
+
+ #ifdef DBL_MAX_10_EXP
+ i = DBL_MAX_10_EXP;
+ #else
+ i = -2;
+ d = 1.0;
+ do
+ {
+ i++;
+ pd = d;
+ d *= 10.0;
+ } while (d > pd);
+ #endif
+ #ifndef DBL_MAX_10_EXP
+ printf("#ifndef DBL_MAX_10_EXP\n");
+ printf("#define DBL_MAX_10_EXP %d\n", i);
+ printf("#endif\n");
+ #endif
+
+ #if !_ast_fltmax_double
+ printf("\n");
+ w = 1;
+ do
+ {
+ pw = w;
+ w *= 2;
+ l = (_ast_intmax_t)w;
+ x = (_ast_intmax_t)l;
+ } while (w > pw && w == x);
+ w = (pw - 1) + pw;
+ u = ~0;
+ if (u > w)
+ u = w;
+ printf("#define LDBL_ULONG_MAX %lu.0L\n", u);
+ if (sizeof(w) > sizeof(u))
+ {
+ printf("#define LDBL_ULLONG_MAX %llu.0L\n", w);
+ printf("#define LDBL_UINTMAX_MAX LDBL_ULLONG_MAX\n");
+ }
+ else
+ {
+ printf("#define LDBL_ULLONG_MAX LDBL_ULONG_MAX\n");
+ printf("#define LDBL_UINTMAX_MAX LDBL_ULONG_MAX\n");
+ }
+ u /= 2;
+ w /= 2;
+ printf("#define LDBL_LONG_MAX %lu.0L\n", u);
+ if (sizeof(w) > sizeof(u))
+ {
+ printf("#define LDBL_LLONG_MAX %llu.0L\n", w);
+ printf("#define LDBL_INTMAX_MAX LDBL_LLONG_MAX\n");
+ }
+ else
+ {
+ printf("#define LDBL_LLONG_MAX LDBL_LONG_MAX\n");
+ printf("#define LDBL_INTMAX_MAX LDBL_LONG_MAX\n");
+ }
+ u++;
+ w++;
+ printf("#define LDBL_LONG_MIN (-%lu.0L)\n", u);
+ if (sizeof(w) > sizeof(u))
+ {
+ printf("#define LDBL_LLONG_MIN (-%llu.0L)\n", w);
+ printf("#define LDBL_INTMAX_MIN LDBL_LLONG_MIN\n");
+ }
+ else
+ {
+ printf("#define LDBL_LLONG_MIN LDBL_LONG_MIN\n");
+ printf("#define LDBL_INTMAX_MIN LDBL_LONG_MIN\n");
+ }
+ #ifdef LDBL_DIG
+ s = LDBL_DIG;
+ #else
+ l = pl = 1.0L;
+ s = -1;
+ do
+ {
+ s++;
+ l *= 10.0L;
+ } while (l != (l + pl));
+ #endif
+ #if defined(LDBL_MIN) && defined(LDBL_MIN_EXP)
+ i = LDBL_MIN_EXP;
+ ml = LDBL_MIN;
+ #else
+ i = 3;
+ l = pl = 1.0L;
+ do
+ {
+ i--;
+ ml = pl;
+ pl = l;
+ l /= 2.0L;
+ } while (l < pl);
+ #ifdef LDBL_MIN_EXP
+ i = LDBL_MIN_EXP;
+ #endif
+ #ifdef LDBL_MIN
+ ml = LDBL_MIN;
+ #endif
+ #endif
+ #ifndef LDBL_DIG
+ printf("#ifndef LDBL_DIG\n");
+ printf("#define LDBL_DIG %d\n", s);
+ printf("#endif\n");
+ #endif
+ #ifndef LDBL_MIN
+ printf("#ifndef LDBL_MIN\n");
+ printf("#define LDBL_MIN %.*LE%s\n", s + 1, ml, ls);
+ printf("#endif\n");
+ #endif
+ #ifndef LDBL_MIN_EXP
+ printf("#ifndef LDBL_MIN_EXP\n");
+ printf("#define LDBL_MIN_EXP (%d)\n", i);
+ printf("#endif\n");
+ #endif
+
+ #if defined(LDBL_MAX) && defined(LDBL_MAX_EXP)
+ i = LDBL_MAX_EXP;
+ l = LDBL_MAX;
+ #else
+ i = -1;
+ l = pl = 1.0L;
+ do
+ {
+ i++;
+ ml = pl;
+ pl = l;
+ l *= 2.0L;
+ } while (l > pl);
+ l = 1.0L;
+ do
+ {
+ l *= 2.0L;
+ } while (ml == (ml + l));
+ l = (ml - l) * 2.0L + l;
+ #ifdef LDBL_MAX_EXP
+ i = LDBL_MAX_EXP;
+ #endif
+ #ifdef LDBL_MAX
+ l = LDBL_MAX;
+ #endif
+ #endif
+ #ifndef LDBL_MAX
+ printf("#ifndef LDBL_MAX\n");
+ printf("#define LDBL_MAX %.*LE%s\n", s + 1, l, ls);
+ printf("#endif\n");
+ #endif
+ #ifndef LDBL_MAX_EXP
+ printf("#ifndef LDBL_MAX_EXP\n");
+ printf("#define LDBL_MAX_EXP %d\n", i);
+ printf("#endif\n");
+ #endif
+
+ #ifdef LDBL_MIN_10_EXP
+ i = LDBL_MIN_10_EXP;
+ #else
+ i = 2;
+ l = 1.0L;
+ do
+ {
+ i--;
+ pl = l;
+ l /= 10.0L;
+ } while (l < pl);
+ #endif
+ #ifndef LDBL_MIN_10_EXP
+ printf("#ifndef LDBL_MIN_10_EXP\n");
+ printf("#define LDBL_MIN_10_EXP (%d)\n", i);
+ printf("#endif\n");
+ #endif
+
+ #ifdef LDBL_MAX_10_EXP
+ i = LDBL_MAX_10_EXP;
+ #else
+ i = -2;
+ l = 1.0L;
+ do
+ {
+ i++;
+ pl = l;
+ l *= 10.0L;
+ } while (l > pl);
+ #endif
+ #ifndef LDBL_MAX_10_EXP
+ printf("#ifndef LDBL_MAX_10_EXP\n");
+ printf("#define LDBL_MAX_10_EXP %d\n", i);
+ printf("#endif\n");
+ #endif
+ fp = "LDBL";
+ #else
+ fp = "DBL";
+ #endif
+
+ printf("\n");
+ printf("#define FLTMAX_UINTMAX_MAX %s_UINTMAX_MAX\n", fp);
+ printf("#define FLTMAX_INTMAX_MAX %s_INTMAX_MAX\n", fp);
+ printf("#define FLTMAX_INTMAX_MIN %s_INTMAX_MIN\n", fp);
+
+ #ifdef SIGFPE
+ if (!caught)
+ {
+ #if !__MVS__
+ f = xf;
+ f *= 2;
+ if (!f)
+ #endif
+ caught = 1;
+ }
+ if (caught)
+ printf("\n#define _ast_fltsig %d\n", SIGFPE);
+ #endif
+
+ printf("\n");
+ #if !_lib_frexp
+ printf("extern double frexp(double, int*);\n");
+ #endif
+ #if !_lib_frexpl
+ printf("extern _ast_fltmax_t frexpl(_ast_fltmax_t, int*);\n");
+ #endif
+ #if !_lib_ldexp
+ printf("extern double ldexp(double, int);\n");
+ #endif
+ #if !_lib_ldexpl
+ printf("extern _ast_fltmax_t ldexpl(_ast_fltmax_t, int);\n");
+ #endif
+
+ return 0;
+ }
+}end
+
+tst - note{ double exponent bitfoolery }end output{
+ #include "FEATURE/common"
+ #include <stdio.h>
+ typedef union _dbl_exp_u
+ {
+ unsigned _ast_int4_t e[sizeof(double) / 4];
+ double f;
+ } _ast_dbl_exp_t;
+ int
+ main()
+ {
+ int i;
+ int j;
+ unsigned _ast_int4_t e;
+ _ast_dbl_exp_t a;
+ _ast_dbl_exp_t b;
+ a.f = 1;
+ b.f = 2;
+ for (i = 0; i < sizeof(a.e) / sizeof(a.e[0]); i++)
+ if (e = a.e[i] ^ b.e[i])
+ {
+ for (j = i + 1; j < sizeof(a.e) / sizeof(a.e[0]); j++)
+ if (a.e[j] ^ b.e[j])
+ return 0;
+ printf("typedef union _ast_dbl_exp_u\n{\n\tuint32_t\t\te[sizeof(double)/4];\n\tdouble\t\t\tf;\n} _ast_dbl_exp_t;\n\n");
+ printf("#define _ast_dbl_exp_index %d\n", i);
+ for (i = 0; !(e & 1); e >>= 1, i++);
+ printf("#define _ast_dbl_exp_shift %d\n\n", i);
+ return 0;
+ }
+ return 0;
+ }
+}end
+
+tst - note{ long double exponent bitfoolery }end output{
+ #include "FEATURE/common"
+ #include <stdio.h>
+ typedef union _ast_fltmax_exp_u
+ {
+ unsigned _ast_int4_t e[sizeof(_ast_fltmax_t) / 4];
+ _ast_fltmax_t f;
+ } _ast_fltmax_exp_t;
+ int
+ main()
+ {
+ int i;
+ int j;
+ unsigned _ast_int4_t e;
+ _ast_fltmax_exp_t a;
+ _ast_fltmax_exp_t b;
+ a.f = 1;
+ b.f = 2;
+ for (i = 0; i < sizeof(a.e) / sizeof(a.e[0]); i++)
+ if (e = a.e[i] ^ b.e[i])
+ {
+ for (j = i + 1; j < sizeof(a.e) / sizeof(a.e[0]); j++)
+ if (a.e[j] ^ b.e[j])
+ return 0;
+ printf("typedef union _fltmax_exp_u\n{\n\tuint32_t\t\te[sizeof(_ast_fltmax_t)/4];\n\t_ast_fltmax_t\t\tf;\n} _ast_fltmax_exp_t;\n\n");
+ printf("#define _ast_fltmax_exp_index\t%d\n", i);
+ for (i = 0; !(e & 1); e >>= 1, i++);
+ printf("#define _ast_fltmax_exp_shift\t%d\n\n", i);
+ return 0;
+ }
+ return 0;
+ }
+}end
+
+tst - -DN=1 - -DN=2 note{ _ast_fltmax_t maximum integral type }end output{
+ #include <stdio.h>
+ int
+ main()
+ {
+ #if N == 1
+ unsigned long long m;
+ long double f = 123.456;
+
+ m = f;
+ if (!m || f == m)
+ return 1;
+ printf("#define _ast_flt_unsigned_max_t unsigned long long\n");
+ #else
+ printf("#define _ast_flt_unsigned_max_t unsigned long\n");
+ #endif
+ return 0;
+ }
+}end
+
+tst - -DSCAN=1 - -lm -DSTRTO=1 - -DMAC=1 - -DDIV=1 - -DEXP=1 - -DADD=1 - -DMPY=1 note{ INF and NAN memory representations }end output{
+ #if MAC
+ #define _AIX_COMPATIBILITY 1
+ #define _FP_MODE_VARIABLE 1
+ #endif
+ #include "FEATURE/common"
+ #include <stdio.h>
+ #include <sys/types.h>
+ #include <signal.h>
+ #if _hdr_float
+ #include <float.h>
+ #endif
+ #if _hdr_limits
+ #include <limits.h>
+ #endif
+ #if _hdr_math
+ #include <math.h>
+ #endif
+ #if _hdr_values
+ #include <values.h>
+ #endif
+ #if STRTO && _hdr_stdlib
+ #include <stdlib.h>
+ #endif
+ #if !defined(FLT_MAX) && defined(MAXFLOAT)
+ #define FLT_MAX MAXFLOAT
+ #endif
+ #if !defined(DBL_MAX) && defined(MAXDOUBLE)
+ #define DBL_MAX MAXDOUBLE
+ #endif
+ #if _ast_fltmax_double
+ #undef LDBL_MAX
+ #endif
+ static void
+ #if _STD_
+ list(const char* typ, const char* var, void* val, int siz)
+ #else
+ list(typ, var, val, siz)
+ char* typ;
+ char* var;
+ void* val;
+ int siz;
+ #endif
+ {
+ register unsigned char* u = (unsigned char*)val;
+ register unsigned char* e = u + siz;
+
+ printf("#define _ast_%s_%s_init\t0x%02x", typ, var, *u);
+ while (++u < e)
+ printf(",0x%02x", *u);
+ printf("\n");
+ }
+ int
+ main()
+ {
+ #if SCAN || STRTO
+ #undef NAN
+ #define NAN "NaN"
+ #undef INF
+ #define INF "INF"
+ {
+ float f;
+
+ #if SCAN
+ if (sscanf(NAN, "%g", &f) != 1)
+ return 1;
+ #else
+ f = atof(NAN);
+ #endif
+ list("flt", "nan", &f, sizeof(f));
+ #if SCAN
+ if (sscanf(INF, "%g", &f) != 1)
+ return 1;
+ #else
+ f = atof(INF);
+ #endif
+ list("flt", "inf", &f, sizeof(f));
+ }
+ {
+ double f;
+ #if STRTO
+ char* e;
+ #endif
+
+ #if SCAN
+ if (sscanf(NAN, "%lg", &f) != 1)
+ return 1;
+ #else
+ f = strtod(NAN, &e);
+ if (*e)
+ return 1;
+ #endif
+ list("dbl", "nan", &f, sizeof(f));
+ #if SCAN
+ if (sscanf(INF, "%lg", &f) != 1)
+ return 1;
+ #else
+ f = strtod(INF, &e);
+ if (*e)
+ return 1;
+ #endif
+ list("dbl", "inf", &f, sizeof(f));
+ }
+ #ifdef LDBL_MAX
+ {
+ long double f;
+ #if STRTO
+ char* e;
+ #endif
+
+ #if SCAN
+ if (sscanf(NAN, "%Lg", &f) != 1)
+ return 1;
+ #else
+ f = strtold(NAN, &e);
+ if (*e)
+ return 1;
+ #endif
+ list("ldbl", "nan", &f, sizeof(f));
+ #if SCAN
+ if (sscanf(INF, "%Lg", &f) != 1)
+ return 1;
+ #else
+ f = strtold(INF, &e);
+ if (*e)
+ return 1;
+ #endif
+ list("ldbl", "inf", &f, sizeof(f));
+ }
+ #endif
+ #else
+ #ifdef SIGFPE
+ signal(SIGFPE, SIG_IGN);
+ #endif
+ #ifdef FLT_MAX
+ {
+ float f = FLT_MAX;
+ #if DIV
+ float z = 0;
+
+ f = 0.0 / z;
+ if (!f)
+ return 1;
+ list("flt", "nan", &f, sizeof(f));
+ f = 1.0 / z;
+ list("flt", "inf", &f, sizeof(f));
+ #else
+ #if ADD
+ f += f;
+ #endif
+ #if EXP
+ f = exp(f);
+ #endif
+ #if MPY
+ f *= 2;
+ #endif
+ #if MAC
+ f = FLT_QNAN;
+ #endif
+ list("flt", "nan", &f, sizeof(f));
+ #if MAC
+ f = FLT_INFINITY;
+ #endif
+ list("flt", "inf", &f, sizeof(f));
+ #endif
+ }
+ #endif
+ #ifdef DBL_MAX
+ {
+ double f = DBL_MAX;
+ #if DIV
+ double z = 0;
+
+ f = 0.0 / z;
+ if (!f)
+ return 1;
+ list("dbl", "nan", &f, sizeof(f));
+ f = 1.0 / z;
+ list("dbl", "inf", &f, sizeof(f));
+ #else
+ #if ADD
+ f += f;
+ #endif
+ #if EXP
+ f = exp(f);
+ #endif
+ #if MPY
+ f *= 2;
+ #endif
+ #if MAC
+ f = DBL_QNAN;
+ #endif
+ list("dbl", "nan", &f, sizeof(f));
+ #if MAC
+ f = DBL_INFINITY;
+ #endif
+ list("dbl", "inf", &f, sizeof(f));
+ #endif
+ }
+ #endif
+ #ifdef LDBL_MAX
+ {
+ long double f = LDBL_MAX;
+ #if DIV
+ long double z = 0;
+
+ f = 0.0 / z;
+ if (!f)
+ return 1;
+ list("ldbl", "nan", &f, sizeof(f));
+ f = 1.0 / z;
+ list("ldbl", "inf", &f, sizeof(f));
+ #else
+ #if ADD
+ f += f;
+ #endif
+ #if EXP
+ f = exp(f);
+ #endif
+ #if MPY
+ f *= 2;
+ #endif
+ #if MAC
+ f = LDBL_QNAN;
+ #endif
+ list("ldbl", "nan", &f, sizeof(f));
+ #if MAC
+ f = LDBL_INFINITY;
+ #endif
+ list("ldbl", "inf", &f, sizeof(f));
+ #endif
+ }
+ #endif
+ #endif
+ return 0;
+ }
+}end
diff --git a/src/lib/libast/features/fs b/src/lib/libast/features/fs
new file mode 100644
index 0000000..3caeedb
--- /dev/null
+++ b/src/lib/libast/features/fs
@@ -0,0 +1,251 @@
+set prototyped
+lib _fxstat,__fxstat,_lxstat,__lxstat,_xmknod,__xmknod,_xstat,__xstat,lstat,mknod,sync sys/types.h sys/stat.h
+lib _fxstat64,__fxstat64,_lxstat64,__lxstat64,_xstat64,__xstat64 -D_LARGEFILE64_SOURCE sys/types.h sys/stat.h
+mac fstat,lstat,stat,mknod sys/types.h sys/stat.h
+
+lcl xstat -D_LARGEFILE64_SOURCE link{
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ struct stat64 { int xxx; }; /* disable if stat64 available */
+ #if _STD_
+ extern int stat(const char* path, struct stat* st)
+ #else
+ int stat(path, st)
+ char* path;
+ struct stat* st;
+ #endif
+ {
+ #if _lib___xstat
+ return __xstat(_STAT_VER, path, st);
+ #else
+ return _xstat(_STAT_VER, path, st);
+ #endif
+ }
+ int
+ main()
+ {
+ struct stat st;
+ return stat(".",&st) < 0;
+ }
+}end
+
+lcl xstat64 -D_LARGEFILE64_SOURCE link{
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #if _STD_
+ extern int stat64(const char* path, struct stat64* st)
+ #else
+ int stat64(path, st)
+ char* path;
+ #endif
+ {
+ #if _lib___xstat64
+ return __xstat64(_STAT_VER, path, st);
+ #else
+ return _xstat64(_STAT_VER, path, st);
+ #endif
+ }
+ int
+ main()
+ {
+ struct stat64 st;
+ return stat64(".",&st) < 0;
+ }
+}end
+
+header sys/stat.h
+header sys/mkdev.h
+
+extern chmod int (const char*, mode_t)
+extern fstat int (int, struct stat*)
+extern lstat int (const char*, struct stat*)
+extern mkdir int (const char*, mode_t)
+extern mkfifo int (const char*, mode_t)
+extern mknod int (const char*, mode_t, dev_t)
+extern stat int (const char*, struct stat*)
+
+define FS_default "ufs"
+
+macro{
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #ifndef major
+ #include <sys/param.h>
+ #ifndef major
+ #include <sys/sysmacros.h>
+ #endif
+ <<"#if defined(__STDPP__directive) && defined(__STDPP__initial)">>
+ <<"__STDPP__directive pragma pp:initial">>
+ <<"#endif">>
+ <<"#ifndef major">>
+ #ifdef major
+ <<"#define major(x)">> major((x))
+ #else
+ #ifndef L_BITSMAJOR
+ #define L_BITSMAJOR 8
+ #endif
+ #ifndef L_BITSMINOR
+ #define L_BITSMINOR 8
+ #endif
+ #ifndef L_MAXMAJ
+ #define L_MAXMAJ ((1<<L_BITSMAJOR)-1)
+ #endif
+ #ifndef L_MAXMIN
+ #define L_MAXMIN ((1<<L_BITSMINOR)-1)
+ #endif
+ <<"#define major(x)">> ((int)(((unsigned)(x)>>L_BITSMINOR)&L_MAXMAJ))
+ #endif
+ <<"#endif">>
+ <<"#ifndef minor">>
+ #ifdef minor
+ <<"#define minor(x)">> minor((x))
+ #else
+ <<"#define minor(x)">> ((int)((x)&L_MAXMIN))
+ #endif
+ <<"#endif">>
+ <<"#ifndef makedev">>
+ #ifdef makedev
+ <<"#define makedev(x,y)">> makedev((x),(y))
+ #else
+ <<"#define makedev(x,y)">> ((dev_t)((((x)&0377)<<8)|((y)&0377)))
+ #endif
+ <<"#endif">>
+ #endif
+ <<"#if defined(__STDPP__directive) && defined(__STDPP__initial)">>
+ <<"__STDPP__directive pragma pp:noinitial">>
+ <<"#endif">>
+}end fail{
+ cat <<!
+ #ifndef major
+ #define major(x) ((int)(((unsigned)(x)>>8)&0377))
+ #endif
+ #ifndef minor
+ #define minor(x) ((int)((x)&0377))
+ #endif
+ #ifndef makedev
+ #define makedev(x,y) ((dev_t)((((x)&0377)<<8)|((y)&0377)))
+ #endif
+ !
+}end
+
+hdr mntent,mnttab stdio.h
+sys mntent,mnttab stdio.h
+sys fs_types,mount,statfs,statvfs,vfs,vmount sys/param.h sys/ucred.h
+
+mem mnttab.mt_dev,mnttab.mt_filsys,mnttab.mt_fstyp sys/types.h mnttab.h
+mem mntent.mnt_opts,w_mntent.mnt_opts,mnttab.mnt_opts sys/types.h stdio.h mntent.h sys/mntent.h
+mem mntent.mnt_opts,mnttab.mnt_opts stdio.h sys/types.h mnttab.h sys/mnttab.h
+mem stat.st_blocks,stat.st_blksize,stat.st_rdev sys/types.h sys/stat.h
+mem statfs.f_files,statfs.f_bavail sys/types.h - sys/statfs.h - sys/vfs.h - sys/param.h sys/mount.h
+mem statvfs.f_basetype,statvfs.f_frsize sys/types.h sys/statvfs.h
+
+ary f_reserved7 sys/types.h sys/statvfs.h note{ statvfs.f_reserved7 can double for statvfs.f_basetype }end compile{
+ int f(vp)struct statvfs* vp;{return vp->f_reserved7[0] = 1;}
+}end
+
+lib getfsstat,getmntent,getmntinfo,mntctl,mntopen,mntread,mntclose,setmntent
+lib w_getmntent
+lib statfs,statvfs
+
+lib statfs4 sys/types.h - sys/statfs.h - sys/vfs.h - sys/mount.h compile{
+ int f()
+ {
+ struct statfs fs;
+ return statfs("/",&fs,sizeof(fs),0);
+ }
+}end
+
+lib getmntinfo_statvfs note{ getmntinfo uses statvfs -- since when? }end compile{
+ #include <sys/types.h>
+ #include <sys/mount.h>
+ int
+ gmi(struct statvfs* fs)
+ {
+ fs->f_flag = 0;
+ return getmntinfo(fs, 0);
+ }
+}end
+
+lib getfsstat_statvfs note{ getfsstat uses statvfs -- just in case it is confused like getmntinfo }end compile{
+ #include <sys/types.h>
+ #include <sys/mount.h>
+ int
+ gfs(struct statvfs* fs)
+ {
+ fs->f_flag = 0;
+ return getfsstat(fs, sizeof(struct statvfs), MNT_WAIT);
+ }
+}end
+
+cat{
+ #if _sys_statvfs
+ #include <sys/statvfs.h>
+ #if !_mem_statvfs_f_basetype
+ #if _ary_f_reserved7
+ #define f_basetype f_reserved7
+ #endif
+ #endif
+ #else
+ #define _mem_f_basetype_statvfs 1
+ #define _mem_f_frsize_statvfs 1
+ struct statvfs
+ {
+ unsigned long f_bsize; /* fundamental file system block size */
+ unsigned long f_frsize; /* fragment size */
+ unsigned long f_blocks; /* total # of blocks of f_frsize on fs */
+ unsigned long f_bfree; /* total # of free blocks of f_frsize */
+ unsigned long f_bavail; /* # of free blocks avail to non-superuser */
+ unsigned long f_files; /* total # of file nodes (inodes) */
+ unsigned long f_ffree; /* total # of free file nodes */
+ unsigned long f_favail; /* # of free nodes avail to non-superuser */
+ unsigned long f_fsid; /* file system id (dev for now) */
+ char f_basetype[16]; /* target fs type name, null-terminated */
+ unsigned long f_flag; /* bit-mask of flags */
+ unsigned long f_namemax; /* maximum file name length */
+ char f_fstr[32]; /* filesystem-specific string */
+ unsigned long f_filler[16]; /* reserved for future expansion */
+ };
+ extern int fstatvfs(int, struct statvfs*);
+ extern int statvfs(const char*, struct statvfs*);
+ #endif
+ #if _typ_off64_t
+ #undef off_t
+ #define off_t off64_t
+ #endif
+ #if _lib_statvfs64 && !defined(statvfs)
+ #define statvfs statvfs64
+ #if !defined(__USE_LARGEFILE64)
+ extern int statvfs64(const char*, struct statvfs64*);
+ #endif
+ #endif
+ #if _lib_fstatvfs64 && !defined(fstatvfs)
+ #define fstatvfs fstatvfs64
+ #if !defined(__USE_LARGEFILE64)
+ extern int fstatvfs64(int, struct statvfs64*);
+ #endif
+ #endif
+}end
+
+str st_fstype sys/types.h sys/stat.h note{ stat.st_fstype is a string }end compile{
+ int f(st)struct stat* st;{return st->st_fstype[0];}
+}end
+
+int st_fstype sys/types.h sys/stat.h note{ stat.st_fstype is an int }end compile{
+ int f(st)struct stat* st;{return st->st_fstype = 1;}
+}end
+
+int st_spare1 sys/types.h sys/stat.h note{ stat.st_spare1 is an int }end compile{
+ int f(st)struct stat* st;{return st->st_spare1 = 1;}
+}end
+
+ary st_spare4 sys/types.h sys/stat.h note{ stat.st_spare4 is an array }end compile{
+ int f(st)struct stat* st;{return st->st_spare4[0] = 1;}
+}end
+
+ary st_extra sys/types.h sys/stat.h note{ stat.st_extra is an array }end compile{
+ int f(st)struct stat* st;{return st->st_extra[0] = 1;}
+}end
+
+ary st_pad4 sys/types.h sys/stat.h note{ stat.st_pad4 is an array }end compile{
+ int f(st)struct stat* st;{return st->st_pad4[0] = 1;}
+}end
diff --git a/src/lib/libast/features/hack b/src/lib/libast/features/hack
new file mode 100644
index 0000000..2be7af9
--- /dev/null
+++ b/src/lib/libast/features/hack
@@ -0,0 +1 @@
+hdr locale_attr
diff --git a/src/lib/libast/features/iconv b/src/lib/libast/features/iconv
new file mode 100644
index 0000000..92fd62f
--- /dev/null
+++ b/src/lib/libast/features/iconv
@@ -0,0 +1,116 @@
+set prototyped
+hdr iconv
+lib iconv_open,iconv_close,iconv iconv.h -liconv
+nxt iconv
+
+tst output{
+ #if !_lib_iconv_open
+ #define _undef_hdr_iconv 1
+ #undef _hdr_iconv
+ #endif
+ #if !_hdr_iconv
+ #define _undef_lib_iconv_open 1
+ #undef _lib_iconv_open
+ #endif
+ #if _hdr_iconv
+ #include <sys/types.h>
+ #include <iconv.h>
+ #endif
+
+ int
+ main()
+ {
+ char* lib;
+
+ printf("#include <ast_common.h>\n");
+ printf("#include <ccode.h>\n");
+ #if _undef_hdr_iconv
+ printf("#undef _hdr_iconv\n");
+ #endif
+ #if _undef_lib_iconv_open
+ printf("#undef _lib_iconv_open\n");
+ #endif
+ #if _hdr_iconv && defined(_nxt_iconv_str)
+ printf("#include <%s> /* the native iconv.h */\n", _nxt_iconv_str);
+ #endif
+ printf("\n");
+ printf("#define ICONV_VERSION 20110111L\n");
+ printf("\n");
+ printf("#define ICONV_FATAL 0x02\n");
+ printf("#define ICONV_OMIT 0x04\n");
+ printf("\n");
+ printf("#define CC_ICONV (-1)\n");
+ printf("#define CC_UCS (-2)\n");
+ printf("#define CC_SCU (-3)\n");
+ printf("#define CC_UTF (-4)\n");
+ printf("#define CC_UME (-5)\n");
+ printf("\n");
+ #if _lib_iconv_open
+ lib = "_ast_";
+ printf("#ifndef _ICONV_LIST_PRIVATE_\n");
+ printf("#undef iconv_t\n");
+ printf("#define iconv_t %siconv_t\n", lib);
+ printf("#undef iconv_f\n");
+ printf("#define iconv_f %siconv_f\n", lib);
+ printf("#undef iconv_list_t\n");
+ printf("#define iconv_list_t %siconv_list_t\n", lib);
+ printf("#undef iconv_open\n");
+ printf("#define iconv_open %siconv_open\n", lib);
+ printf("#undef iconv\n");
+ printf("#define iconv %siconv\n", lib);
+ printf("#undef iconv_close\n");
+ printf("#define iconv_close %siconv_close\n", lib);
+ printf("#undef iconv_list\n");
+ printf("#define iconv_list %siconv_list\n", lib);
+ printf("#undef iconv_move\n");
+ printf("#define iconv_move %siconv_move\n", lib);
+ printf("#undef iconv_name\n");
+ printf("#define iconv_name %siconv_name\n", lib);
+ printf("#undef iconv_write\n");
+ printf("#define iconv_write %siconv_write\n", lib);
+ printf("#endif\n");
+ #else
+ lib = "";
+ #endif
+ printf("\n");
+ printf("typedef int (*Iconv_error_f)(void*, void*, int, ...);\n");
+ printf("\n");
+ printf("typedef struct Iconv_disc_s\n");
+ printf("{\n");
+ printf(" uint32_t version;\n");
+ printf(" Iconv_error_f errorf;\n");
+ printf(" size_t errors;\n");
+ printf(" uint32_t flags;\n");
+ printf(" int fill;\n");
+ printf("} Iconv_disc_t;\n");
+ printf("\n");
+ printf("typedef Ccmap_t %siconv_list_t;\n", lib);
+ printf("typedef void* %siconv_t;\n", lib);
+ printf("typedef size_t (*%siconv_f)(%siconv_t, char**, size_t*, char**, size_t*);\n", lib, lib);
+ printf("\n");
+ printf("#define iconv_init(d,e) (memset(d,0,sizeof(*(d))),(d)->version=ICONV_VERSION,(d)->errorf=(Iconv_error_f)(e),(d)->fill=(-1))\n");
+ printf("\n");
+ printf("#if _BLD_ast && defined(__EXPORT__)\n");
+ printf("#define extern __EXPORT__\n");
+ printf("#endif\n");
+ printf("\n");
+ printf("extern %siconv_t %siconv_open(const char*, const char*);\n", lib, lib);
+ printf("extern size_t %siconv(%siconv_t, char**, size_t*, char**, size_t*);\n", lib, lib);
+ printf("extern int %siconv_close(%siconv_t);\n", lib, lib);
+ printf("extern %siconv_list_t* %siconv_list(%siconv_list_t*);\n", lib, lib, lib);
+ printf("extern int %siconv_name(const char*, char*, size_t);\n", lib);
+ printf("#if _SFIO_H\n");
+ printf("extern ssize_t %siconv_move(%siconv_t, Sfio_t*, Sfio_t*, size_t, Iconv_disc_t*);\n", lib, lib);
+ printf("extern ssize_t %siconv_write(%siconv_t, Sfio_t*, char**, size_t*, Iconv_disc_t*);\n", lib, lib);
+ printf("#else\n");
+ printf("#if _SFSTDIO_H\n");
+ printf("extern ssize_t %siconv_move(%siconv_t, FILE*, FILE*, size_t, Iconv_disc_t*);\n", lib, lib);
+ printf("extern ssize_t %siconv_write(%siconv_t, FILE*, char**, size_t*, Iconv_disc_t*);\n", lib, lib);
+ printf("#endif\n");
+ printf("#endif\n");
+ printf("\n");
+ printf("#undef extern\n");
+ printf("\n");
+ return 0;
+ }
+}end
diff --git a/src/lib/libast/features/isoc99 b/src/lib/libast/features/isoc99
new file mode 100644
index 0000000..e85c9f5
--- /dev/null
+++ b/src/lib/libast/features/isoc99
@@ -0,0 +1,13 @@
+if tst -D_ISOC99_SOURCE -lm note{ _ISOC99_SOURCE plays nice }end link{
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <math.h>
+ int main() { return signbit(-0.0); }
+ }end {
+ #ifndef _ISOC99_SOURCE
+ #define _ISOC99_SOURCE 1
+ #endif
+ }
+endif
diff --git a/src/lib/libast/features/lib b/src/lib/libast/features/lib
new file mode 100644
index 0000000..763c91d
--- /dev/null
+++ b/src/lib/libast/features/lib
@@ -0,0 +1,664 @@
+ref -D_def_map_ast=1
+
+cmd universe
+
+hdr dirent,direntry,filio,fmtmsg,fnmatch,jioctl,libgen,limits
+hdr locale,ndir,nl_types,process,spawn,syslog,utime,vfork
+hdr wchar note{ <wchar.h> and isw*() really work }end execute{
+ #include <wchar.h>
+ int
+ main()
+ {
+ wchar_t w = 'a';
+ return iswalnum(w) == 0;
+ }
+}end
+hdr wctype wchar.h
+
+dat _tzname,tzname
+
+lib BSDsetpgrp
+lib _cleanup
+lib atexit,bcopy,bzero,catclose,catgets,catopen,confstr,dirread,dup2
+lib execlp,execve,execvp,execvpe
+lib fchmod,fcntl,fmtmsg,fnmatch,fork,fsync
+lib getconf,getdents,getdirentries,getdtablesize,getdate
+lib getgroups,gethostname,getlogin,getpagesize,getrlimit,getuniverse
+lib getopt,getsubopt,getopt_long,getopt_long_only
+lib glob,index,iswblank,iswctype,killpg,link,localeconv,madvise
+lib mbtowc,mbrtowc,memalign,memchr,memcpy,memdup,memmove,memset
+lib mkdir,mkfifo,mktemp,mktime
+lib mount,on_exit,onexit,opendir,pathconf
+lib readlink,remove,rename,rewinddir,rindex,rmdir,setlocale
+lib setpgid,setpgrp,setpgrp2,setreuid,setsid,setuid,sigaction
+lib sigprocmask,sigsetmask,sigunblock,sigvec,socketpair
+lib spawn,spawnve,spawnveg
+lib strchr,strcoll,strdup,strerror,strcasecmp,strncasecmp,strrchr,strstr
+lib strmode,strxfrm,strftime,swab,symlink,sysconf,sysinfo,syslog
+lib telldir,tmpnam,tzset,universe,unlink,utime,wctype
+lib ftruncate,truncate
+lib creat64,fstat64,fstatvfs64,ftruncate64 -D_LARGEFILE64_SOURCE
+lib lseek64,lstat64 -D_LARGEFILE64_SOURCE
+lib open64,readdir64,stat64,statvfs64,truncate64 -D_LARGEFILE64_SOURCE
+
+lib,npt strtod,strtold,strtol,strtoll,strtoul,strtoull stdlib.h
+lib,npt sigflag signal.h
+
+mem direct.d_reclen sys/types.h sys/dir.h
+mem dirent.d_fileno,dirent.d_ino,dirent.d_namlen,dirent.d_off,dirent.d_reclen,dirent.d_type sys/types.h dirent.h
+mem DIR sys/types.h - dirent.h - sys/dir.h
+mem DIR.dd_fd sys/types.h - dirent.h - sys/dir.h
+mem inheritance.pgroup spawn.h
+
+sys dir,filio,jioctl,localedef,ptem,resource
+sys socket,stream,systeminfo,universe,vfork
+
+typ off64_t -D_LARGEFILE64_SOURCE
+typ struct.dirent64 -D_LARGEFILE64_SOURCE dirent.h
+
+tst tst_errno note{ errno can be assigned }end link{
+ _BEGIN_EXTERNS_
+ #define error ______error
+ #define strerror ______strerror
+ #include <errno.h>
+ #undef error
+ #undef strerror
+ #ifndef errno
+ extern int errno;
+ #endif
+ error() { }
+ strerror() { }
+ _END_EXTERNS_
+ int main() { errno = 0; error(); strerror(); return 0; }
+}end
+
+tst lib_poll_fd_1 note{ fd is first arg to poll() }end execute{
+ #include <poll.h>
+ _BEGIN_EXTERNS_
+ extern int pipe _ARG_((int*));
+ _END_EXTERNS_
+ int
+ main()
+ { int rw[2];
+ struct pollfd fd;
+ if (pipe(rw) < 0) return 1;
+ fd.fd = rw[0];
+ fd.events = POLLIN;
+ fd.revents = 0;
+ if (poll(&fd, 1, 0) < 0 || fd.revents != 0) return 1;
+ if (write(rw[1], "x", 1) != 1) return 1;
+ if (poll(&fd, 1, 0) < 0 || fd.revents == 0) return 1;
+ return 0;
+ }
+}end
+
+tst lib_poll_fd_2 note{ fd is second arg to poll() }end execute{
+ #include <poll.h>
+ _BEGIN_EXTERNS_
+ extern int pipe _ARG_((int*));
+ _END_EXTERNS_
+ int
+ main()
+ { int rw[2];
+ struct pollfd fd;
+ if (pipe(rw) < 0) return 1;
+ fd.fd = rw[0];
+ fd.events = POLLIN;
+ fd.revents = 0;
+ return poll(1, &fd, 0) < 0;
+ if (poll(1, &fd, 0) < 0 || fd.revents != 0) return 1;
+ if (write(rw[1], "x", 1) != 1) return 1;
+ if (poll(1, &fd, 0) < 0 || fd.revents == 0) return 1;
+ return 0;
+ }
+}end
+
+exp _lib_poll _lib_poll_fd_1||_lib_poll_fd_2
+
+tst lib_poll_notimer note{ poll with no fds ignores timeout }end execute{
+ #include <sys/types.h>
+ #include <poll.h>
+ _BEGIN_EXTERNS_
+ extern time_t time _ARG_((time_t*));
+ _END_EXTERNS_
+ #define TIMEOUT 4
+ int
+ main()
+ {
+ unsigned long start;
+ unsigned long finish;
+ struct pollfd fd;
+ start = time((time_t*)0);
+ if (poll(&fd, 0, TIMEOUT * 1000) < 0)
+ return 0;
+ finish = time((time_t*)0);
+ return (finish - start) > (TIMEOUT / 2);
+ }
+}end
+
+tst lib_select note{ select() has standard 5 arg interface }end link{
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <sys/socket.h>
+ int
+ main()
+ { struct timeval tmb;
+ fd_set rd;
+ FD_ZERO(&rd);
+ FD_SET(0,&rd);
+ tmb.tv_sec = 0;
+ tmb.tv_usec = 0;
+ select(1,&rd,(fd_set*)0,(fd_set*)0,&tmb);
+ return 0;
+ }
+}end
+
+tst pipe_rw note{ full duplex pipes }end execute{
+ _BEGIN_EXTERNS_
+ extern int pipe _ARG_((int*));
+ extern int read _ARG_((int, void*, int));
+ extern int strcmp _ARG_((const char*, const char*));
+ extern int write _ARG_((int, void*, int));
+ _END_EXTERNS_
+ int
+ main()
+ {
+ #if defined(__sgi) || defined(_sgi) || defined(sgi)
+ /* boot tuneable pipes force one way for bin compatibility */
+ return 1;
+ #else
+ static char test[] = "test\n";
+ int io[2];
+ char buf[sizeof(test)];
+ if (pipe(io)) return 1;
+ if (write(io[1], test, sizeof(test)) != sizeof(test)) return 1;
+ if (read(io[0], buf, sizeof(test)) != sizeof(test)) return 1;
+ if (strcmp(test, buf)) return 1;
+ if (write(io[0], test, sizeof(test)) != sizeof(test)) return 1;
+ if (read(io[1], buf, sizeof(test)) != sizeof(test)) return 1;
+ if (strcmp(test, buf)) return 1;
+ return 0;
+ #endif
+ }
+}end
+
+tst lib_vfork unistd.h stdlib.h vfork.h note{ vfork exists and it works }end execute{
+ #include <signal.h>
+ int
+ main(argc, argv)
+ int argc;
+ char** argv;
+ {
+ int status;
+ char* cmd[3];
+ if (argv[1])
+ _exit(signal(SIGHUP, SIG_DFL) != SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
+ switch (vfork())
+ {
+ case -1:
+ _exit(1);
+ case 0:
+ cmd[0] = argv[0];
+ cmd[1] = "test";
+ cmd[2] = 0;
+ execv(cmd[0], cmd);
+ _exit(2);
+ }
+ status = 1;
+ _exit(wait(&status) < 0 || status != 0);
+ }
+}end
+
+tst real_vfork note{ vfork child shares data with parent }end execute{
+ _BEGIN_EXTERNS_
+ extern int _exit _ARG_((int));
+ extern int vfork _ARG_((void));
+ _END_EXTERNS_
+ int code;
+ int
+ main()
+ {
+ code = 1;
+ if (!vfork())
+ code = 0;
+ _exit(code);
+ }
+}end
+
+tst lib_posix_spawn unistd.h stdlib.h spawn.h -Dfork=______fork note{ posix_spawn exists and it works and its worth using }end status{
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/wait.h>
+ #include <spawn.h>
+ #include <signal.h>
+ #include <fcntl.h>
+ #include <string.h>
+ #undef fork
+ /* if it uses fork() why bother? */
+ pid_t fork _ARG_((void)) { return -1; }
+ pid_t _fork _ARG_((void)) { return -1; }
+ pid_t __fork _ARG_((void)) { return -1; }
+ int
+ main(argc, argv)
+ int argc;
+ char** argv;
+ {
+ char* s;
+ pid_t pid;
+ posix_spawnattr_t attr;
+ int n;
+ int status;
+ char* cmd[3];
+ char tmp[1024];
+ if (argv[1])
+ _exit(signal(SIGHUP, SIG_DFL) != SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
+ if (posix_spawnattr_init(&attr))
+ _exit(0);
+ if (posix_spawnattr_setpgroup(&attr, 0))
+ _exit(0);
+ if (posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP))
+ _exit(0);
+ /* first try an a.out and verify that SIGHUP is ignored */
+ cmd[0] = argv[0];
+ cmd[1] = "test";
+ cmd[2] = 0;
+ if (posix_spawn(&pid, cmd[0], 0, &attr, cmd, 0))
+ _exit(0);
+ status = 1;
+ if (wait(&status) < 0 || status != 0)
+ _exit(0);
+ /* passing ENOEXEC to the shell is bogus */
+ n = strlen(cmd[0]);
+ if (n >= (sizeof(tmp) - 3))
+ _exit(0);
+ strcpy(tmp, cmd[0]);
+ tmp[n] = '.';
+ tmp[n+1] = 's';
+ tmp[n+2] = 'h';
+ tmp[n+3] = 0;
+ if (close(open(tmp, O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO)) < 0 || chmod(tmp, S_IRWXU|S_IRWXG|S_IRWXO) < 0)
+ _exit(0);
+ cmd[0] = tmp;
+ n = 0;
+ pid = -1;
+ if (posix_spawn(&pid, cmd[0], 0, &attr, cmd, 0))
+ n = 2;
+ else
+ {
+ n = pid != -1 && waitpid(pid, &status, WNOHANG|WNOWAIT) == pid && ((status>>8)&0x7f) == 127;
+ wait(&status);
+ }
+ _exit(n);
+ }
+}end
+
+tst lib_spawn_mode unistd.h stdlib.h note{ first spawn arg is mode and it works }end execute{
+ #include <signal.h>
+ #include <process.h>
+ #ifndef P_NOWAIT
+ #define P_NOWAIT _P_NOWAIT
+ #endif
+ int
+ main(argc, argv)
+ int argc;
+ char** argv;
+ {
+ int status;
+ char* cmd[3];
+ if (argv[1])
+ _exit(signal(SIGHUP, SIG_DFL) != SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
+ cmd[0] = argv[0];
+ cmd[1] = "test";
+ cmd[2] = 0;
+ if (spawnv(P_NOWAIT, cmd[0], cmd) < 0)
+ _exit(1);
+ status = 1;
+ _exit(wait(&status) < 0 || status != 0);
+ }
+}end
+
+tst stream_peek note{ ioctl(I_PEEK) works on pipe() }end execute{
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <stropts.h>
+ int
+ main()
+ { struct strpeek peek;
+ int fds[2];
+ char ctlbuf[32];
+ char databuf[32];
+ peek.flags = 0;
+ peek.ctlbuf.maxlen = peek.ctlbuf.len = sizeof(ctlbuf);
+ peek.ctlbuf.buf = ctlbuf;
+ peek.databuf.maxlen = peek.databuf.len = sizeof(databuf);
+ peek.databuf.buf = databuf;
+ pipe(fds);
+ return ioctl(fds[0],I_PEEK,&peek) < 0;
+ }
+}end
+
+tst socket_peek note{ recv(MSG_PEEK) works on socketpair() }end execute{
+ #include <unistd.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ int
+ main()
+ {
+ int i;
+ int fds[2];
+ char buf[128];
+
+ static char msg[] = "abcd";
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
+ return 1;
+ if (write(fds[1], msg, sizeof(msg)) != sizeof(msg))
+ return 1;
+ if (recv(fds[0], buf, sizeof(buf), MSG_PEEK) != sizeof(msg))
+ return 1;
+ for (i = 0; i < sizeof(msg); i++)
+ if (buf[i] != msg[i])
+ return 1;
+ if (read(fds[0], buf, sizeof(msg)) != sizeof(msg))
+ return 1;
+ for (i = 0; i < sizeof(msg); i++)
+ if (buf[i] != msg[i])
+ return 1;
+ return 0;
+ }
+}end
+
+tst lib_memcmp string.h note{ standard memcmp interface that works }end execute{
+ /* sgi again -- we're sick of being their regression test */
+ #define L 8
+ char a[L] = { '0' };
+ char b[L] = { '1' };
+ int
+ main()
+ {
+ return memcmp(a, b, L) >= 0;
+ }
+}end
+
+tst lib_memccpy string.h unistd.h stdlib.h fcntl.h signal.h sys/types.h sys/stat.h sys/mman.h fcntl.h note{ standard memccpy interface that works }end execute{
+ #if _STD_
+ static void gotcha(int sig)
+ #else
+ static int gotcha(sig) int sig;
+ #endif
+ {
+ exit(1);
+ }
+ #ifdef MAP_PRIVATE
+ static const char x[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxN";
+ #if _STD_
+ static int indict_sgi_ia64_4Q_2004(int n)
+ #else
+ static int indict_sgi_ia64_4Q_2004(n) int n;
+ #endif
+ {
+ char* b;
+ char* s;
+ char* e;
+ char* t;
+ long m;
+ int d;
+ char u[1024];
+
+ static char p[32] = {'/','t','m','p','/','m','m'};
+
+ for (d = 7; d < 13; d++)
+ p[d] = 'X';
+ p[d] = 0;
+ if ((d = mkstemp(p)) < 0)
+ return 1;
+ remove(p);
+ for (m = 0; m < n; m++)
+ if (write(d, x, sizeof(x)-1) != sizeof(x)-1)
+ {
+ close(d);
+ return 1;
+ }
+ if (lseek(d, (off_t)0, SEEK_SET))
+ {
+ close(d);
+ return 1;
+ }
+ m = n * (sizeof(x)-1);
+ if (!(b = mmap((void*)0, m, PROT_READ|PROT_WRITE, MAP_PRIVATE, d, (off_t)0)))
+ {
+ close(d);
+ return 1;
+ }
+ for (e = (s = b) + m; s < e && (t = memccpy(u, s, 'N', (e-s) > sizeof(u) ? sizeof(u) : (e-s))); s += (t-u))
+ if ((t-u) != (sizeof(x)-1) || memcmp(u, s, t-u))
+ {
+ close(d);
+ return 1;
+ }
+ if (s < e)
+ {
+ close(d);
+ return 1;
+ }
+ close(d);
+ return 0;
+ }
+ #endif
+
+ int
+ main ()
+ {
+ char buf[1024];
+ #ifdef MAP_PRIVATE
+ char* srcbuf;
+ char* dstbuf;
+ int fd;
+ size_t siz;
+ int i;
+ #endif
+
+ #if defined(__ia64) || defined(__ia64__) || defined(__itanium__)
+ /*
+ * 0 faith that the itanium coders will ever get this right
+ * prove me wrong
+ */
+
+ return 1;
+ #endif
+
+ /*
+ * early mac osx failed here -- fixed 3Q 2001
+ */
+
+ if (memccpy(buf, "abc", 0, sizeof(buf)) != (buf + 4))
+ return 1;
+ #ifdef MAP_PRIVATE
+ siz = 64 * 1024;
+ if (!(dstbuf = malloc(2 * siz)))
+ return 0;
+ if ((fd = open("/dev/zero", O_RDWR)) < 0)
+ return 0;
+ if (!(srcbuf = (char*)mmap(NULL, siz, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0)))
+ return 0;
+ if (!mmap(srcbuf + siz, siz, PROT_NONE, MAP_PRIVATE, fd, 0))
+ return 0;
+ for (i = 0; i < siz; i++)
+ srcbuf[i] = 'x';
+ srcbuf[siz - 1] = 0;
+ alarm(10);
+ signal(SIGSEGV, gotcha);
+ signal(SIGBUS, gotcha);
+ signal(SIGALRM, gotcha);
+ /*
+ * sgi ia64 dumps here as of 3Q 2001
+ * bug acknowleged 1Q 2003
+ */
+ memccpy(dstbuf, srcbuf, 0, siz + 10);
+ alarm(0);
+ if (strcmp(srcbuf, dstbuf))
+ return 1;
+ if (indict_sgi_ia64_4Q_2004(1))
+ return 1;
+ if (indict_sgi_ia64_4Q_2004(257))
+ return 1;
+ #endif
+ return 0;
+ }
+}end
+
+tst lib_utime_now note{ utime works with 0 time vector }end execute{
+ #include <sys/types.h>
+ _BEGIN_EXTERNS_
+ extern int utime _ARG_((const char*, void*));
+ _END_EXTERNS_
+ int
+ main()
+ {
+ return utime(".", (void*)0) == -1;
+ }
+}end
+
+tst cross{
+ u=att
+ case `/bin/cat -s /dev/null/foo 2>&1` in
+ '') ;;
+ *) case `/bin/echo '\\t'` in
+ '\t') u=ucb ;;
+ esac
+ ;;
+ esac
+ echo "#define _UNIV_DEFAULT \"$u\" /* default universe name */"
+}end
+
+std cleanup note{ stuck with standard _cleanup }end noexecute{
+ _BEGIN_EXTERNS_
+ extern void exit _ARG_((int));
+ extern void _exit _ARG_((int));
+ extern void _cleanup();
+ void _cleanup() { _exit(0); }
+ _END_EXTERNS_
+ int main() { printf("cleanup\n"); exit(1); }
+}end
+
+std remove note{ stuck with standard remove() }end nostatic{
+ _BEGIN_EXTERNS_
+ extern int unlink _ARG_((const char*));
+ _END_EXTERNS_
+ #if _STD_
+ int remove(const char* path) { return 0; }
+ #else
+ int remove(path) char* path; { return 0; }
+ #endif
+ int main() { return unlink("foo"); }
+}end
+
+std signal note{ stuck with standard signal }end nolink{
+ _BEGIN_EXTERNS_
+ extern int abort();
+ int signal() { return 0; }
+ _END_EXTERNS_
+ int main() { signal(); abort(); return 0; }
+}end
+
+std strcoll note{ standard strcoll works }end execute{
+ #include <string.h>
+ #define S "hello world"
+ int
+ main()
+ {
+ char s[] = S;
+ char t[] = S;
+ return strcoll(s, t) || strcmp(s, t);
+ }
+}end
+
+std strtod stdlib.h note{ stuck with standard strtod }end nostatic{
+ _BEGIN_EXTERNS_
+ #if _STD_
+ double strtod(const char* s, char** e) { return 0.0; }
+ #else
+ double strtod(s, e) char* s; char** e; { return 0.0; }
+ #endif
+ _END_EXTERNS_
+ int main() { printf(""); return strtod("1",0) != 0; }
+}end
+
+std strtold stdlib.h note{ stuck with standard strtold }end nostatic{
+ _BEGIN_EXTERNS_
+ #if _STD_
+ long double strtold(const char* s, char** e) { return 0.0; }
+ #else
+ long double strtold(s, e) char* s; char** e; { return 0.0; }
+ #endif
+ _END_EXTERNS_
+ int main() { printf(""); return strtold("1",0) != 0; }
+}end
+
+std strtol note{ stuck with standard strtol }end nostatic{
+ _BEGIN_EXTERNS_
+ #if _STD_
+ extern long atol(const char*);
+ long strtol(const char* s, char** e, int b) { return 0; }
+ #else
+ extern long atol();
+ long strtol(s, e, b) char* s; char** e; int b; { return 0; }
+ #endif
+ _END_EXTERNS_
+ int main() { printf(""); return (atol("1") + strtol("1",(char**)0,0)) != 0; }
+}end
+
+tst - output{
+ int
+ main()
+ {
+ #if _UWIN
+ printf("\n");
+ printf("/* override some uwin feature tests */\n");
+ printf("#undef _lib_execlp\n");
+ printf("#undef _lib_execvp\n");
+ printf("#undef _lib_execvpe\n");
+ printf("#undef _lib_fork\n");
+ printf("#undef _std_string\n");
+ printf("#define _std_string 1\n");
+ printf("#undef _stream_peek\n");
+ printf("\n");
+ #endif
+
+ #if _lib_spawnveg || _lib_posix_spawn || _lib_spawn_mode || _lib_spawn && _hdr_spawn && _mem_pgroup_inheritance || _lib_vfork && _real_vfork
+ printf("#if !_AST_no_spawnveg\n");
+ printf("#define _use_spawnveg 1\n");
+ printf("#endif\n");
+ printf("\n");
+ #endif
+
+ return 0;
+ }
+
+}end
+
+tst no64 -D_LARGEFILE64_SOURCE note{ largefile 64 broken }end execute{
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ int
+ main()
+ {
+ struct stat64 st;
+ return !stat64(".", &st) && st.st_mode && st.st_mtime;
+ }
+}end pass{
+ echo "/* can we at least agree that a successful return means success? */"
+ echo "#undef _lib_creat64"
+ echo "#undef _lib_fstat64"
+ echo "#undef _lib_fstatvfs64"
+ echo "#undef _lib_ftruncate64"
+ echo "#undef _lib_lseek64"
+ echo "#undef _lib_lstat64"
+ echo "#undef _lib_mmap64"
+ echo "#undef _lib_stat64"
+ echo "#undef _lib_statvfs64"
+ echo "#undef _lib_truncate64"
+}end
diff --git a/src/lib/libast/features/libpath.sh b/src/lib/libast/features/libpath.sh
new file mode 100644
index 0000000..b3809fd
--- /dev/null
+++ b/src/lib/libast/features/libpath.sh
@@ -0,0 +1,73 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1985-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# David Korn <dgk@research.att.com> #
+# Phong Vo <kpv@research.att.com> #
+# #
+########################################################################
+ok=0
+for i in \
+ -x /lib/ld.so /lib/ld-*.so /usr/lib/ld.so /lib/rld \
+ -f /usr/shlib/libc.so /shlib/libc.so /usr/lib/libc.so \
+ -r /usr/shlib/libc.so /shlib/libc.so
+do case $i in
+ -*) op=$i; continue ;;
+ esac
+ if test $op $i
+ then ok=1
+ break
+ fi
+ set x $i.[0-9]*
+ if test $op $2
+ then ok=1
+ break
+ fi
+done
+if test "0" != "$ok"
+then libpath=lib:LD_LIBRARY_PATH
+ case `package` in
+ sgi.*) if test -d /lib32
+ then libpath="lib32:LD_LIBRARYN32_PATH:sgi.mips3|sgi.*-n32,$libpath"
+ fi
+ if test -d /lib64
+ then libpath="lib64:LD_LIBRARY64_PATH:sgi.mips[4-9]|sgi.*-64,$libpath"
+ fi
+ ;;
+ sol*.*) if test -d /lib/32
+ then libpath="lib/32:LD_LIBRARY_PATH_32,$libpath"
+ fi
+ if test -d /lib/64
+ then libpath="lib/64:LD_LIBRARY_PATH_64:sol.*64*,$libpath"
+ fi
+ ;;
+ esac
+elif test -x /lib/dld.sl
+then libpath=lib:SHLIB_PATH
+elif test -x /usr/lib/dyld
+then libpath=lib:DYLD_LIBRARY_PATH
+else case `package` in
+ ibm.*|mvs.*)
+ libpath=lib:LIBPATH
+ ;;
+ *) libpath=
+ ;;
+ esac
+fi
+case $libpath in
+'') libpath=bin ;;
+esac
+echo "#define CONF_LIBPATH \"$libpath\""
diff --git a/src/lib/libast/features/limits.c b/src/lib/libast/features/limits.c
new file mode 100644
index 0000000..c6e82df
--- /dev/null
+++ b/src/lib/libast/features/limits.c
@@ -0,0 +1,339 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * generate limits features
+ *
+ * FOPEN_MAX POSIX says ANSI defines it but it's not in ANSI
+ *
+ * NOTE: two's complement binary integral representation assumed
+ */
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide getpagesize getdtablesize
+#else
+#define getpagesize ______getpagesize
+#define getdtablesize ______getdtablesize
+#endif
+
+/*
+ * we'd like as many symbols as possible defined
+ * the standards push the vendors the other way
+ * but don't provide guard that lets everything through
+ * so each vendor adds their own guard
+ * many now include something like <standards.h> to
+ * get it straight in one place -- <sys/types.h> should
+ * kick that in
+ */
+
+#include "FEATURE/standards"
+#include "FEATURE/lib"
+
+#ifdef __sun
+#define _timespec timespec
+#endif
+
+#include <sys/types.h>
+
+#undef _SGIAPI
+#define _SGIAPI 1
+
+#if _hdr_limits
+#include <limits.h>
+#endif
+
+#undef _SGIAPI
+#define _SGIAPI 0
+
+#include "FEATURE/lib"
+#include "FEATURE/common"
+
+#if _hdr_unistd
+#include <unistd.h>
+#endif
+
+#include "FEATURE/param"
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide getpagesize getdtablesize
+#else
+#undef getpagesize
+#undef getdtablesize
+#endif
+
+int main()
+{
+ char c;
+ unsigned char uc;
+ unsigned short us;
+ unsigned int ui;
+ unsigned long ul;
+ unsigned long val;
+#if _typ_uint64_t
+ uint64_t ull;
+ uint64_t vll;
+#endif
+
+ /*
+ * <limits.h> with *constant* valued macros
+ */
+
+ printf("\n");
+#ifndef CHAR_BIT
+ uc = 0;
+ uc = ~uc;
+ val = 1;
+ while (uc >>= 1) val++;
+ printf("#define CHAR_BIT %lu\n", val);
+#endif
+#ifndef MB_LEN_MAX
+ val = 1;
+ printf("#define MB_LEN_MAX %lu\n", val);
+#endif
+
+ c = 0;
+ c = ~c;
+ uc = 0;
+ uc = ~uc;
+ us = 0;
+ us = ~us;
+ ui = 0;
+ ui = ~ui;
+ ul = 0;
+ ul = ~ul;
+#if _typ_uint64_t
+ ull = 0;
+ ull = ~ull;
+#endif
+
+#ifndef UCHAR_MAX
+ val = uc;
+ printf("#if defined(__STDC__)\n");
+ printf("#define UCHAR_MAX %luU\n", val);
+ printf("#else\n");
+ printf("#define UCHAR_MAX %lu\n", val);
+ printf("#endif\n");
+#endif
+
+#ifndef SCHAR_MIN
+ val = (unsigned char)(uc >> 1) + 1;
+ printf("#define SCHAR_MIN (-%lu)\n", val);
+#endif
+
+#ifndef SCHAR_MAX
+ val = (unsigned char)(uc >> 1);
+ printf("#define SCHAR_MAX %lu\n", val);
+#endif
+
+ if (c < 0)
+ {
+#ifndef CHAR_MIN
+ printf("#define CHAR_MIN SCHAR_MIN\n");
+#endif
+
+#ifndef CHAR_MAX
+ printf("#define CHAR_MAX SCHAR_MAX\n");
+#endif
+ }
+ else
+ {
+#ifndef CHAR_MIN
+ printf("#define CHAR_MIN 0\n");
+#endif
+
+#ifndef CHAR_MAX
+ printf("#define CHAR_MAX UCHAR_MAX\n");
+#endif
+ }
+
+#ifndef USHRT_MAX
+ val = us;
+ printf("#if defined(__STDC__)\n");
+ printf("#define USHRT_MAX %luU\n", val);
+ printf("#else\n");
+ printf("#define USHRT_MAX %lu\n", val);
+ printf("#endif\n");
+#endif
+
+#ifndef SHRT_MIN
+ val = (unsigned short)(us >> 1) + 1;
+ printf("#define SHRT_MIN (-%lu)\n", val);
+#endif
+
+#ifndef SHRT_MAX
+ val = (unsigned short)(us >> 1);
+ printf("#define SHRT_MAX %lu\n", val);
+#endif
+
+ if (ui == us)
+ {
+#ifndef UINT_MAX
+ printf("#define UINT_MAX USHRT_MAX\n");
+#endif
+
+#ifndef INT_MIN
+ printf("#define INT_MIN SHRT_MIN\n");
+#endif
+
+#ifndef INT_MAX
+ printf("#define INT_MAX SHRT_MAX\n");
+#endif
+ }
+ else
+ {
+#ifndef UINT_MAX
+ val = ui;
+ printf("#if defined(__STDC__)\n");
+ printf("#define UINT_MAX %luU\n", val);
+ printf("#else\n");
+ printf("#define UINT_MAX %lu\n", val);
+ printf("#endif\n");
+#endif
+
+#ifndef INT_MIN
+ val = (unsigned int)(ui >> 1) + 1;
+ if (ui == ul) printf("#define INT_MIN (-%lu-1)\n", val - 1);
+ else printf("#define INT_MIN (-%lu)\n", val);
+#endif
+
+#ifndef INT_MAX
+ val = (unsigned int)(ui >> 1);
+ printf("#define INT_MAX %lu\n", val);
+#endif
+ }
+
+ if (ul == ui)
+ {
+#ifndef ULONG_MAX
+ printf("#define ULONG_MAX UINT_MAX\n");
+#endif
+
+#ifndef LONG_MIN
+ printf("#define LONG_MIN INT_MIN\n");
+#endif
+
+#ifndef LONG_MAX
+ printf("#define LONG_MAX INT_MAX\n");
+#endif
+ }
+ else
+ {
+#ifndef ULONG_MAX
+ val = ul;
+ printf("#if defined(__STDC__)\n");
+ printf("#define ULONG_MAX %luLU\n", val);
+ printf("#else\n");
+ printf("#define ULONG_MAX %lu\n", val);
+ printf("#endif\n");
+#endif
+
+#ifndef LONG_MIN
+ val = (unsigned long)(ul >> 1) + 1;
+ printf("#define LONG_MIN (-%luL-1L)\n", val - 1);
+#endif
+
+#ifndef LONG_MAX
+ val = (unsigned long)(ul >> 1);
+ printf("#define LONG_MAX %luL\n", val);
+#endif
+ }
+
+#if _typ_uint64_t && !_ast_intmax_long
+ if (ull == ul)
+ {
+#ifndef ULLONG_MAX
+ printf("#define ULLONG_MAX ULONG_MAX\n");
+#endif
+
+#ifndef LLONG_MIN
+ printf("#define LLONG_MIN LONG_MIN\n");
+#endif
+
+#ifndef LLONG_MAX
+ printf("#define LLONG_MAX LONG_MAX\n");
+#endif
+ }
+ else
+ {
+#ifndef ULLONG_MAX
+ vll = ull;
+ printf("#ifndef ULLONG_MAX\n");
+ printf("#if defined(__STDC__) && _ast_LL\n");
+ printf("#define ULLONG_MAX %lluULL\n", vll);
+ printf("#else\n");
+ printf("#define ULLONG_MAX %llu\n", vll);
+ printf("#endif\n");
+ printf("#endif\n");
+#endif
+
+#ifndef LLONG_MIN
+ vll = (uint64_t)(ull >> 1) + 1;
+ printf("#ifndef LLONG_MIN\n");
+ printf("#if defined(__STDC__) && _ast_LL\n");
+ printf("#define LLONG_MIN (-%lluLL-1LL)\n", vll - 1);
+ printf("#else\n");
+ printf("#define LLONG_MIN (-%llu-1)\n", vll - 1);
+ printf("#endif\n");
+ printf("#endif\n");
+#endif
+
+#ifndef LLONG_MAX
+ vll = (uint64_t)(ull >> 1);
+ printf("#ifndef LLONG_MAX\n");
+ printf("#if defined(__STDC__) && _ast_LL\n");
+ printf("#define LLONG_MAX %lluLL\n", vll);
+ printf("#else\n");
+ printf("#define LLONG_MAX %llu\n", vll);
+ printf("#endif\n");
+ printf("#endif\n");
+#endif
+ }
+#endif
+
+ printf("\n");
+#ifdef _UWIN
+ printf("#ifdef _UWIN\n");
+ printf("#ifndef DBL_DIG\n");
+ printf("#define DBL_DIG 15\n");
+ printf("#endif\n");
+ printf("#ifndef DBL_MAX\n");
+ printf("#define DBL_MAX 1.7976931348623158e+308\n");
+ printf("#endif\n");
+ printf("#ifndef FLT_DIG\n");
+ printf("#define FLT_DIG 6\n");
+ printf("#endif\n");
+ printf("#ifndef FLT_MAX\n");
+ printf("#define FLT_MAX 3.402823466e+38F\n");
+ printf("#endif\n");
+ printf("#endif\n");
+ printf("\n");
+#endif
+
+#include "conflim.h"
+
+ printf("\n");
+
+ return 0;
+}
diff --git a/src/lib/libast/features/locale b/src/lib/libast/features/locale
new file mode 100644
index 0000000..ffd1988
--- /dev/null
+++ b/src/lib/libast/features/locale
@@ -0,0 +1,28 @@
+tst - note{ canonical UTF-8 name }end run{
+ ifs=$IFS
+ str=
+ sys=
+ for i in `PATH=/bin:/usr/bin:$PATH locale -a | grep -i '^[^C].*\.UTF[-8]*$'`
+ do IFS=.
+ set '' $i
+ IFS=$ifs
+ case $3 in
+ UTF-8) str=$3
+ break
+ ;;
+ *) if $SHELL -c "LC_CTYPE=$2.UTF-8 PATH=/bin:/usr/bin:$PATH locale LC_CTYPE | grep -i utf.*8" >/dev/null 2>&1
+ then str=UTF-8
+ break
+ fi
+ ;;
+ esac
+ sys=$3
+ done
+ case $str in
+ '') str=$sys ;;
+ esac
+ case $str in
+ '') echo "#define _locale_utf8_str 0" ;;
+ *) echo "#define _locale_utf8_str \"$str\"" ;;
+ esac
+}end
diff --git a/src/lib/libast/features/map.c b/src/lib/libast/features/map.c
new file mode 100644
index 0000000..52c35aa
--- /dev/null
+++ b/src/lib/libast/features/map.c
@@ -0,0 +1,565 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * some systems may pull in <ast_common.h> and its <ast_map.h>
+ * which we are in the process of generating ... this prevents it
+ */
+
+#define _def_map_ast 1
+
+#include "FEATURE/lib"
+#include "FEATURE/mmap"
+#include "FEATURE/options"
+#include "FEATURE/vmalloc"
+#include "FEATURE/eaccess"
+#include "FEATURE/api"
+
+#if _opt_map_libc && !defined(_map_libc)
+#define _map_libc 1
+#endif
+
+int
+main()
+{
+ printf("#pragma prototyped\n");
+ printf("\n");
+ printf("/*\n");
+ printf(" * prototypes provided for standard interfaces hijacked\n");
+ printf(" * by ast and mapped to _ast_* but already prototyped\n");
+ printf(" * unmapped in native headers included by <ast_std.h>\n");
+ printf(" */\n");
+ printf("\n");
+ printf("#if _BLD_ast && defined(__EXPORT__)\n");
+ printf("#define extern __EXPORT__\n");
+ printf("#endif\n");
+ printf("\n");
+#if __MVS__
+#undef _map_libc
+#define _map_libc 1
+ printf("\n");
+ printf("/* mvs.390 libc.dll routines can't be intercepted by user dlls */\n");
+ printf("#undef _mem_dd_fd_DIR\n");
+ printf("#undef _typ_long_double\n");
+#endif
+#if _map_libc
+#undef _map_malloc
+#define _map_malloc 1
+ printf("\n");
+ printf("#define _map_libc 1\n");
+ printf("#undef basename\n");
+ printf("#define basename _ast_basename\n");
+ printf("#undef dirname\n");
+ printf("#define dirname _ast_dirname\n");
+#if !_lib_eaccess
+ printf("#undef eaccess\n");
+ printf("#define eaccess _ast_eaccess\n");
+#endif
+#if !_lib_execvpe
+ printf("#undef execvpe\n");
+ printf("#define execvpe _ast_execvpe\n");
+ printf("extern int execvpe(const char*, char* const[], char* const[]);\n");
+#endif
+ printf("#undef fnmatch\n");
+ printf("#define fnmatch _ast_fnmatch\n");
+ printf("#undef fts_children\n");
+ printf("#define fts_children _ast_fts_children\n");
+ printf("#undef fts_close\n");
+ printf("#define fts_close _ast_fts_close\n");
+ printf("#undef fts_flags\n");
+ printf("#define fts_flags _ast_fts_flags\n");
+ printf("#undef fts_notify\n");
+ printf("#define fts_notify _ast_fts_notify\n");
+ printf("#undef fts_open\n");
+ printf("#define fts_open _ast_fts_open\n");
+ printf("#undef fts_read\n");
+ printf("#define fts_read _ast_fts_read\n");
+ printf("#undef fts_set\n");
+ printf("#define fts_set _ast_fts_set\n");
+ printf("#undef ftw\n");
+ printf("#define ftw _ast_ftw\n");
+ printf("#undef ftwalk\n");
+ printf("#define ftwalk _ast_ftwalk\n");
+ printf("#undef ftwflags\n");
+ printf("#define ftwflags _ast_ftwflags\n");
+#if !_WINIX
+ printf("#undef getcwd\n");
+ printf("#define getcwd _ast_getcwd\n");
+ printf("extern char* getcwd(char*, size_t);\n");
+#endif
+ printf("#undef getdate\n");
+ printf("#define getdate _ast_getdate\n");
+#if _lib_getopt || _lib_getsubopt || _lib_getopt_long || _lib_getopt_long_only
+ printf("#undef getopt\n");
+ printf("#define getopt _ast_getopt\n");
+ printf("#undef getsubopt\n");
+ printf("#define getsubopt _ast_getsubopt\n");
+ printf("#undef getopt_long\n");
+ printf("#define getopt_long _ast_getopt_long\n");
+ printf("#undef getopt_long_only\n");
+ printf("#define getopt_long_only _ast_getopt_long_only\n");
+ printf("#undef optopt\n");
+ printf("#define optopt _ast_optopt\n");
+ printf("#undef optarg\n");
+ printf("#define optarg _ast_optarg\n");
+ printf("#undef optind\n");
+ printf("#define optind _ast_optind\n");
+ printf("#undef opterr\n");
+ printf("#define opterr _ast_opterr\n");
+#endif
+ printf("#undef getwd\n");
+ printf("#define getwd _ast_getwd\n");
+ printf("extern char* getwd(char*);\n");
+ printf("#undef glob\n");
+ printf("#define glob _ast_glob\n");
+ printf("#undef globfree\n");
+ printf("#define globfree _ast_globfree\n");
+ printf("#undef memdup\n");
+ printf("#define memdup _ast_memdup\n");
+ printf("#undef memfatal\n");
+ printf("#define memfatal _ast_memfatal\n");
+ printf("#undef memhash\n");
+ printf("#define memhash _ast_memhash\n");
+ printf("#undef memsum\n");
+ printf("#define memsum _ast_memsum\n");
+ printf("#undef mkstemp\n");
+ printf("#define mkstemp _ast_mkstemp\n");
+ printf("extern int mkstemp(char*);\n");
+ printf("#undef mktemp\n");
+ printf("#define mktemp _ast_mktemp\n");
+ printf("extern char* mktemp(char*);\n");
+ printf("#undef mktime\n");
+ printf("#define mktime _ast_mktime\n");
+ printf("#undef nftw\n");
+ printf("#define nftw _ast_nftw\n");
+ printf("#undef optctx\n");
+ printf("#define optctx _ast_optctx\n");
+ printf("#undef optesc\n");
+ printf("#define optesc _ast_optesc\n");
+ printf("#undef optget\n");
+ printf("#define optget _ast_optget\n");
+ printf("#undef opthelp\n");
+ printf("#define opthelp _ast_opthelp\n");
+ printf("#undef optjoin\n");
+ printf("#define optjoin _ast_optjoin\n");
+ printf("#undef optstr\n");
+ printf("#define optstr _ast_optstr\n");
+ printf("#undef optusage\n");
+ printf("#define optusage _ast_optusage\n");
+ printf("#undef pathaccess\n");
+ printf("#define pathaccess _ast_pathaccess\n");
+ printf("#undef pathbin\n");
+ printf("#define pathbin _ast_pathbin\n");
+ printf("#undef pathcanon\n");
+ printf("#define pathcanon _ast_pathcanon\n");
+ printf("#undef pathcat\n");
+ printf("#define pathcat _ast_pathcat\n");
+ printf("#undef pathcd\n");
+ printf("#define pathcd _ast_pathcd\n");
+ printf("#undef pathcheck\n");
+ printf("#define pathcheck _ast_pathcheck\n");
+ printf("#undef pathexists\n");
+ printf("#define pathexists _ast_pathexists\n");
+ printf("#undef pathfind\n");
+ printf("#define pathfind _ast_pathfind\n");
+ printf("#undef pathgetlink\n");
+ printf("#define pathgetlink _ast_pathgetlink\n");
+ printf("#undef pathinclude\n");
+ printf("#define pathinclude _ast_pathinclude\n");
+ printf("#undef pathkey\n");
+ printf("#define pathkey _ast_pathkey\n");
+ printf("#undef pathnative\n");
+ printf("#define pathnative _ast_pathnative\n");
+ printf("#undef pathpath\n");
+ printf("#define pathpath _ast_pathpath\n");
+ printf("#undef pathposix\n");
+ printf("#define pathposix _ast_pathposix\n");
+ printf("#undef pathprobe\n");
+ printf("#define pathprobe _ast_pathprobe\n");
+ printf("#undef pathprog\n");
+ printf("#define pathprog _ast_pathprog\n");
+ printf("#undef pathrepl\n");
+ printf("#define pathrepl _ast_pathrepl\n");
+ printf("#undef pathsetlink\n");
+ printf("#define pathsetlink _ast_pathsetlink\n");
+ printf("#undef pathshell\n");
+ printf("#define pathshell _ast_pathshell\n");
+ printf("#undef pathstat\n");
+ printf("#define pathstat _ast_pathstat\n");
+ printf("#undef pathtemp\n");
+ printf("#define pathtemp _ast_pathtemp\n");
+ printf("#undef pathtmp\n");
+ printf("#define pathtmp _ast_pathtmp\n");
+ printf("#undef procclose\n");
+ printf("#define procclose _ast_procclose\n");
+ printf("#undef procfree\n");
+ printf("#define procfree _ast_procfree\n");
+ printf("#undef procopen\n");
+ printf("#define procopen _ast_procopen\n");
+ printf("#undef procrun\n");
+ printf("#define procrun _ast_procrun\n");
+ printf("#undef putenv\n");
+ printf("#define putenv _ast_putenv\n");
+ printf("#undef re_comp\n");
+ printf("#define re_comp _ast_re_comp\n");
+ printf("#undef re_exec\n");
+ printf("#define re_exec _ast_re_exec\n");
+ printf("#undef realpath\n");
+ printf("#define realpath _ast_realpath\n");
+ printf("extern char* realpath(const char*, char*);\n");
+ printf("#undef regaddclass\n");
+ printf("#define regaddclass _ast_regaddclass\n");
+ printf("#undef regalloc\n");
+ printf("#define regalloc _ast_regalloc\n");
+ printf("#undef regcache\n");
+ printf("#define regcache _ast_regcache\n");
+ printf("#undef regclass\n");
+ printf("#define regclass _ast_regclass\n");
+ printf("#undef regcmp\n");
+ printf("#define regcmp _ast_regcmp\n");
+ printf("#undef regcollate\n");
+ printf("#define regcollate _ast_regcollate\n");
+ printf("#undef regcomb\n");
+ printf("#define regcomb _ast_regcomb\n");
+ printf("#undef regcomp\n");
+ printf("#define regcomp _ast_regcomp\n");
+ printf("#undef regdecomp\n");
+ printf("#define regdecomp _ast_regdecomp\n");
+ printf("#undef regdup\n");
+ printf("#define regdup _ast_regdup\n");
+ printf("#undef regerror\n");
+ printf("#define regerror _ast_regerror\n");
+ printf("#undef regex\n");
+ printf("#define regex _ast_regex\n");
+ printf("#undef regexec\n");
+ printf("#define regexec _ast_regexec\n");
+ printf("#undef regfatal\n");
+ printf("#define regfatal _ast_regfatal\n");
+ printf("#undef regfatalpat\n");
+ printf("#define regfatalpat _ast_regfatalpat\n");
+ printf("#undef regfree\n");
+ printf("#define regfree _ast_regfree\n");
+ printf("#undef regncomp\n");
+ printf("#define regncomp _ast_regncomp\n");
+ printf("#undef regnexec\n");
+ printf("#define regnexec _ast_regnexec\n");
+ printf("#undef regrecord\n");
+ printf("#define regrecord _ast_regrecord\n");
+ printf("#undef regrexec\n");
+ printf("#define regrexec _ast_regrexec\n");
+ printf("#undef regstat\n");
+ printf("#define regstat _ast_regstat\n");
+ printf("#undef regsub\n");
+ printf("#define regsub _ast_regsub\n");
+ printf("#undef regsubcomp\n");
+ printf("#define regsubcomp _ast_regsubcomp\n");
+ printf("#undef regsubexec\n");
+ printf("#define regsubexec _ast_regsubexec\n");
+ printf("#undef regsubflags\n");
+ printf("#define regsubflags _ast_regsubflags\n");
+ printf("#undef regsubfree\n");
+ printf("#define regsubfree _ast_regsubfree\n");
+ printf("#undef remove\n");
+ printf("#define remove _ast_remove\n");
+ printf("extern int remove(const char*);\n");
+ printf("#undef resolvepath\n");
+ printf("#define resolvepath _ast_resolvepath\n");
+ printf("extern int resolvepath(const char*, char*, size_t);\n");
+ printf("#undef setenv\n");
+ printf("#define setenv _ast_setenv\n");
+ printf("extern int setenv(const char*, const char*, int);\n");
+ printf("#undef setenviron\n");
+ printf("#define setenviron _ast_setenviron\n");
+ printf("#undef sigcritical\n");
+ printf("#define sigcritical _ast_sigcritical\n");
+ printf("#undef signal\n");
+ printf("#define signal _ast_signal\n");
+ printf("#undef sigunblock\n");
+ printf("#define sigunblock _ast_sigunblock\n");
+ printf("#undef stracmp\n");
+ printf("#define stracmp _ast_stracmp\n");
+ printf("#undef strcopy\n");
+ printf("#define strcopy _ast_strcopy\n");
+ printf("#undef strelapsed\n");
+ printf("#define strelapsed _ast_strelapsed\n");
+ printf("#undef stresc\n");
+ printf("#define stresc _ast_stresc\n");
+ printf("#undef streval\n");
+ printf("#define streval _ast_streval\n");
+ printf("#undef strexpr\n");
+ printf("#define strexpr _ast_strexpr\n");
+ printf("#undef strftime\n");
+ printf("#define strftime _ast_strftime\n");
+ printf("#undef strgid\n");
+ printf("#define strgid _ast_strgid\n");
+ printf("#undef strgrpmatch\n");
+ printf("#define strgrpmatch _ast_strgrpmatch\n");
+ printf("#undef strhash\n");
+ printf("#define strhash _ast_strhash\n");
+ printf("#undef strkey\n");
+ printf("#define strkey _ast_strkey\n");
+ printf("#undef strlcat\n");
+ printf("#define strlcat _ast_strlcat\n");
+ printf("extern size_t strlcat(char*, const char*, size_t);\n");
+ printf("#undef strlcpy\n");
+ printf("#define strlcpy _ast_strlcpy\n");
+ printf("extern size_t strlcpy(char*, const char*, size_t);\n");
+ printf("#undef strlook\n");
+ printf("#define strlook _ast_strlook\n");
+ printf("#undef strmatch\n");
+ printf("#define strmatch _ast_strmatch\n");
+#endif
+#if _map_libc || _lib_strmode
+ printf("#undef strmode\n");
+ printf("#define strmode _ast_strmode\n");
+#endif
+#if _map_libc
+ printf("#undef strnacmp\n");
+ printf("#define strnacmp _ast_strnacmp\n");
+ printf("#undef strncopy\n");
+ printf("#define strncopy _ast_strncopy\n");
+ printf("#undef strntod\n");
+ printf("#define strntod _ast_strntod\n");
+ printf("#undef strntol\n");
+ printf("#define strntol _ast_strntol\n");
+ printf("#undef strntold\n");
+ printf("#define strntold _ast_strntold\n");
+ printf("#undef strntoll\n");
+ printf("#define strntoll _ast_strntoll\n");
+ printf("#undef strntoul\n");
+ printf("#define strntoul _ast_strntoul\n");
+ printf("#undef strntoull\n");
+ printf("#define strntoull _ast_strntoull\n");
+ printf("#undef stropt\n");
+ printf("#define stropt _ast_stropt\n");
+ printf("#undef strperm\n");
+ printf("#define strperm _ast_strperm\n");
+ printf("#undef strpsearch\n");
+ printf("#define strpsearch _ast_strpsearch\n");
+#if !_lib_strptime
+ printf("#undef strptime\n");
+ printf("#define strptime _ast_strptime\n");
+#endif
+ printf("#undef strsearch\n");
+ printf("#define strsearch _ast_strsearch\n");
+ printf("#undef strsort\n");
+ printf("#define strsort _ast_strsort\n");
+ printf("#undef strsubmatch\n");
+ printf("#define strsubmatch _ast_strsubmatch\n");
+ printf("#undef strsum\n");
+ printf("#define strsum _ast_strsum\n");
+ printf("#undef strtape\n");
+ printf("#define strtape _ast_strtape\n");
+ printf("#undef strtoip4\n");
+ printf("#define strtoip4 _ast_strtoip4\n");
+ printf("#undef strton\n");
+ printf("#define strton _ast_strton\n");
+ printf("#undef strtonll\n");
+ printf("#define strtonll _ast_strtonll\n");
+ printf("#undef struid\n");
+ printf("#define struid _ast_struid\n");
+ printf("#undef struniq\n");
+ printf("#define struniq _ast_struniq\n");
+ printf("#undef system\n");
+ printf("#define system _ast_system\n");
+ printf("extern int system(const char*);\n");
+ printf("#undef tempnam\n");
+ printf("#define tempnam _ast_tempnam\n");
+ printf("extern char* tempnam(const char*, const char*);\n");
+ printf("#undef tmpnam\n");
+ printf("#define tmpnam _ast_tmpnam\n");
+ printf("extern char* tmpnam(char*);\n");
+ printf("#undef touch\n");
+ printf("#define touch _ast_touch\n");
+ printf("#undef wordexp\n");
+ printf("#define wordexp _ast_wordexp\n");
+ printf("#undef wordfree\n");
+ printf("#define wordfree _ast_wordfree\n");
+ printf("#undef unsetenv\n");
+ printf("#define unsetenv _ast_unsetenv\n");
+#endif
+#if _std_malloc
+ printf("\n");
+ printf("/* no local malloc override */\n");
+ printf("#define _std_malloc 1\n");
+#else
+#if _map_malloc
+ printf("\n");
+ printf("/* cannot override local malloc */\n");
+ printf("#define _map_malloc 1\n");
+ printf("#undef calloc\n");
+ printf("#define calloc _ast_calloc\n");
+ printf("extern void* calloc(size_t, size_t);\n");
+ printf("#undef cfree\n");
+ printf("#define cfree _ast_cfree\n");
+ printf("extern void cfree(void*);\n");
+ printf("#undef free\n");
+ printf("#define free _ast_free\n");
+ printf("extern void free(void*);\n");
+#if _lib_mallinfo
+ printf("#undef mallinfo\n");
+ printf("#define mallinfo _ast_mallinfo\n");
+#endif
+ printf("#undef malloc\n");
+ printf("#define malloc _ast_malloc\n");
+ printf("extern void* malloc(size_t);\n");
+#if _lib_mallopt
+ printf("#undef mallopt\n");
+ printf("#define mallopt _ast_mallopt\n");
+#endif
+#if _lib_memalign
+ printf("#undef memalign\n");
+ printf("#define memalign _ast_memalign\n");
+ printf("extern void* memalign(size_t, size_t);\n");
+#endif
+#if _lib_mstats
+ printf("#undef mstats\n");
+ printf("#define mstats _ast_mstats\n");
+#endif
+#if _lib_pvalloc
+ printf("#undef pvalloc\n");
+ printf("#define pvalloc _ast_pvalloc\n");
+#endif
+ printf("#undef realloc\n");
+ printf("#define realloc _ast_realloc\n");
+ printf("extern void* realloc(void*, size_t);\n");
+ printf("#undef strdup\n");
+ printf("#define strdup _ast_strdup\n");
+ printf("extern char* strdup(const char*);\n");
+#if _lib_valloc
+ printf("#undef valloc\n");
+ printf("#define valloc _ast_valloc\n");
+ printf("extern void* valloc(size_t);\n");
+#endif
+#endif
+#endif
+
+ /*
+ * overriding <stdlib.h> strto*() is problematic to say the least
+ */
+
+#if _map_libc || _std_strtol
+#if !__CYGWIN__
+ printf("#undef strtol\n");
+ printf("#define strtol _ast_strtol\n");
+ printf("#undef strtoul\n");
+ printf("#define strtoul _ast_strtoul\n");
+#endif
+ printf("#undef strtoll\n");
+ printf("#define strtoll _ast_strtoll\n");
+ printf("#undef strtoull\n");
+ printf("#define strtoull _ast_strtoull\n");
+#endif
+#if _map_libc || _std_strtod
+ printf("#undef strtod\n");
+ printf("#define strtod _ast_strtod\n");
+#endif
+#if _map_libc || _std_strtold
+ printf("#undef strtold\n");
+ printf("#define strtold _ast_strtold\n");
+#endif
+#if !__CYGWIN__
+#if _npt_strtol || _map_libc || _std_strtol
+#if _npt_strtol && !_map_libc && !_std_strtol
+ printf("#ifndef _ISOC99_SOURCE\n");
+#endif
+ printf("extern long strtol(const char*, char**, int);\n");
+#if _npt_strtol && !_map_libc && !_std_strtol
+ printf("#endif\n");
+#endif
+#endif
+#if _npt_strtoul || _map_libc || _std_strtol
+#if _npt_strtoul && !_map_libc && !_std_strtol
+ printf("#ifndef _ISOC99_SOURCE\n");
+#endif
+ printf("extern unsigned long strtoul(const char*, char**, int);\n");
+#if _npt_strtoul && !_map_libc && !_std_strtol
+ printf("#endif\n");
+#endif
+#endif
+#endif
+#if _npt_strtod || _map_libc || _std_strtod
+#if _npt_strtod && !_map_libc && !_std_strtod
+ printf("#ifndef _ISOC99_SOURCE\n");
+#endif
+ printf("extern double strtod(const char*, char**);\n");
+#if _npt_strtod && !_map_libc && !_std_strtod
+ printf("#endif\n");
+#endif
+#endif
+ printf("#if !_UWIN\n");
+ printf("#undef extern\n");
+ printf("#endif\n");
+#if _npt_strtold || _map_libc || _std_strtold
+#if _npt_strtold && !_map_libc && !_std_strtold
+ printf("#ifndef _ISOC99_SOURCE\n");
+#endif
+ printf("extern _ast_fltmax_t strtold(const char*, char**);\n");
+#if _npt_strtold && !_map_libc && !_std_strtold
+ printf("#endif\n");
+#endif
+#endif
+ printf("#undef extern\n");
+#if _npt_strtoll || _map_libc || _std_strtol
+#if _npt_strtoll && !_map_libc && !_std_strtol
+ printf("#ifndef _ISOC99_SOURCE\n");
+#endif
+ printf("extern _ast_intmax_t strtoll(const char*, char**, int);\n");
+#if _npt_strtoll && !_map_libc && !_std_strtol
+ printf("#endif\n");
+#endif
+#endif
+#if _npt_strtoull || _map_libc || _std_strtol
+#if _npt_strtoull && !_map_libc && !_std_strtol
+ printf("#ifndef _ISOC99_SOURCE\n");
+#endif
+ printf("extern unsigned _ast_intmax_t strtoull(const char*, char**, int);\n");
+#if _npt_strtoull && !_map_libc && !_std_strtoul
+ printf("#endif\n");
+#endif
+#endif
+
+ /*
+ * finally some features/api mediation
+ */
+
+#if defined(_API_ast_MAP) && _map_libc
+ {
+ register const char* s;
+ register const char* t;
+
+ static const char map[] = _API_ast_MAP;
+
+ printf("\n");
+ t = map;
+ do
+ {
+ for (s = t; *t && *t != ' '; t++);
+ printf("#define %-.*s _ast_%-.*s\n", t - s, s, t - s, s);
+ } while (*t++);
+ }
+#endif
+ printf("\n");
+ printf("#undef extern\n");
+ return 0;
+}
diff --git a/src/lib/libast/features/mmap b/src/lib/libast/features/mmap
new file mode 100644
index 0000000..41ac44e
--- /dev/null
+++ b/src/lib/libast/features/mmap
@@ -0,0 +1,342 @@
+ref -D_def_map_ast=1
+
+sys mman
+
+tst lib_mmap note{ standard mmap interface that works }end execute{
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/mman.h>
+ #include <sys/stat.h>
+ #include <sys/times.h>
+
+ #define MAPSIZE (64*1024)
+ #define BUFSIZE (8*1024)
+ #define WRITE (64)
+
+ #define Failed(file) (remove(file),1)
+
+ int
+ #if _STD_
+ main(int argc, char** argv)
+ #else
+ main(argc,argv)
+ int argc;
+ char** argv;
+ #endif
+ {
+ caddr_t mm;
+ char *t, *u, *f;
+ int i, fd, okfixed;
+ char file[1024], buf[MAPSIZE];
+ struct tms stm, etm;
+ clock_t rdtm, mmtm;
+
+ /* create data file in a local fs if possible */
+ t = file;
+ if (access(f = "/tmp", 0) == 0 ||
+ access(f = "/usr/tmp", 0) == 0)
+ {
+ while (*t = *f++)
+ t++;
+ *t++ = '/';
+ }
+ u = t;
+ f = argv[0];
+ while (*t = *f++)
+ if (*t == '/')
+ t = u;
+ else if (*t != '.')
+ t++;
+ *t++ = '.'; *t++ = 'D'; *t = 0;
+ if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0666)) < 0)
+ return 1;
+
+ for (i = 0; i < sizeof(buf); ++i)
+ buf[i] = '0' + (i%10);
+ for (i = 0; i < WRITE; ++i)
+ if (write(fd,buf,sizeof(buf)) != sizeof(buf))
+ return Failed(file);
+ close(fd);
+
+ /* see if can overwrite fixed map */
+ #ifndef MAP_VARIABLE
+ #define MAP_VARIABLE 0
+ #endif
+ if ((fd = open(file, O_RDWR)) < 0)
+ return Failed(file);
+
+ mm = mmap((caddr_t)0, sizeof(buf), (PROT_READ|PROT_WRITE),
+ (MAP_PRIVATE|MAP_VARIABLE), fd, 0);
+ if(mm == (caddr_t)0 || mm == (caddr_t)(-1))
+ return Failed(file);
+ mm = mmap(mm, sizeof(buf), (PROT_READ|PROT_WRITE),
+ (MAP_PRIVATE|MAP_FIXED), fd, 0);
+ okfixed = (mm == (caddr_t)0 || mm == (caddr_t)(-1)) ? 0 : 1;
+ munmap(mm, sizeof(buf));
+ close(fd);
+
+ /* read time */
+ if((fd = open(file, O_RDWR)) < 0)
+ return Failed(file);
+ times(&stm);
+ for (i = 0; i < WRITE; ++i)
+ if (read(fd,buf,BUFSIZE) != BUFSIZE)
+ return Failed(file);
+ times(&etm);
+ close(fd);
+ rdtm = (etm.tms_utime-stm.tms_utime) + (etm.tms_stime-stm.tms_stime);
+
+ /* mmap time */
+ if ((fd = open(file, O_RDWR)) < 0)
+ return Failed(file);
+ times(&stm);
+ for(i = 0, mm = (caddr_t)0; i < WRITE; ++i)
+ { if(okfixed)
+ { mm = (caddr_t)mmap(mm, MAPSIZE,
+ (PROT_READ|PROT_WRITE),
+ (MAP_PRIVATE | (mm ? MAP_FIXED : MAP_VARIABLE)),
+ fd, i*MAPSIZE );
+ }
+ else
+ { if(mm)
+ munmap(mm, MAPSIZE);
+ mm = (caddr_t)mmap((caddr_t)0, MAPSIZE,
+ (PROT_READ|PROT_WRITE),
+ (MAP_PRIVATE|MAP_VARIABLE),
+ fd, i*MAPSIZE );
+ }
+ if(mm == (caddr_t)(-1) || mm == (caddr_t)0)
+ return Failed(file);
+ }
+ times(&etm);
+ close(fd);
+ remove(file);
+ mmtm = (etm.tms_utime-stm.tms_utime) + (etm.tms_stime-stm.tms_stime);
+
+ return rdtm+60 < mmtm ? 1 : 0;
+ }
+}end
+
+tst lib_mmap64 -D_LARGEFILE64_SOURCE note{ mmap64 interface and implementation work }end execute{
+ #if !_lib_mmap
+ (
+ #endif
+
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/mman.h>
+ #include <sys/stat.h>
+
+ int
+ main()
+ {
+ off64_t off;
+ int fd;
+ int n;
+ char* s;
+ struct stat64 st;
+ char file[32] = {'/','t','m','p','/','m','m','X','X','X','X','X','X'};
+
+ /* hey, stubs are supposed to fail! */
+ if (stat64(".", &st) || !st.st_mode || !st.st_mtime)
+ return 1;
+ if (!mktemp(file) || (fd = open64(file, O_CREAT|O_WRONLY, 0600)) < 0)
+ {
+ remove(file);
+ return 1;
+ }
+ off = (1<<8);
+ off *= off;
+ if (lseek64(fd, off, SEEK_SET) != off)
+ {
+ remove(file);
+ return 1;
+ }
+ n = strlen(file) + 1;
+ if (write(fd, file, n) != n)
+ {
+ remove(file);
+ return 1;
+ }
+ if (close(fd) < 0 || (fd = open64(file, O_RDWR)) < 0)
+ {
+ remove(file);
+ return 1;
+ }
+ if (!(s = mmap64((caddr_t)0, (size_t)n, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, off)))
+ {
+ remove(file);
+ return 1;
+ }
+ if (strcmp(s, file))
+ {
+ remove(file);
+ return 1;
+ }
+ close(fd);
+ remove(file);
+ return 0;
+ }
+}end
+
+tst mmap_anon note{ use mmap MAP_ANON to get raw memory }end execute{
+ #if !_lib_mmap
+ (
+ #endif
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/mman.h>
+ #if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
+ #define MAP_ANON MAP_ANONYMOUS
+ #endif
+ int
+ main()
+ { void *addr;
+ addr = mmap(0,1024*1024,PROT_READ|PROT_WRITE,MAP_ANON|MAP_PRIVATE,-1,0);
+ return (addr && addr != (void*)(-1)) ? 0 : 1;
+ }
+}end
+
+tst mmap_devzero note{ use mmap on /dev/zero to get raw memory }end execute{
+ #if !_lib_mmap
+ (
+ #endif
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/mman.h>
+ int
+ main()
+ { int fd;
+ void *addr;
+ if((fd = open("/dev/zero", O_RDWR)) < 0)
+ return 1;
+ addr = mmap(0,1024*1024,PROT_READ|PROT_WRITE,MAP_PRIVATE,fd,0);
+ return (addr && addr != (void*)(-1)) ? 0 : 1;
+ }
+}end
+
+tst note{ mmap is worth using }end output{
+ #if !_lib_mmap
+ (
+ #endif
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/mman.h>
+ #include <sys/stat.h>
+ #include <sys/times.h>
+
+ #define MAPSIZE (64*1024)
+ #define BUFSIZE (MAPSIZE/8)
+ #define WRITE (64)
+ #define RUN (64)
+
+ #define Failed(file) (remove(file),1)
+
+ int
+ #if _STD_
+ main(int argc, char** argv)
+ #else
+ main(argc,argv)
+ int argc;
+ char** argv;
+ #endif
+ {
+ caddr_t mm;
+ char *t, *f;
+ int i, fd, k, run;
+ char file[1024], buf[MAPSIZE];
+ struct tms stm, etm;
+ clock_t rdtm, mmtm;
+
+ /* create data file */
+ f = argv[0]; t = file;
+ while (*t = *f++)
+ t++;
+ *t++ = '.'; *t++ = 'D'; *t = 0;
+ if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0666)) < 0)
+ return 1;
+
+ for (i = 0; i < sizeof(buf); ++i)
+ buf[i] = '0' + (i%10);
+ for (i = 0; i < WRITE; ++i)
+ if (write(fd,buf,sizeof(buf)) != sizeof(buf))
+ return Failed(file);
+ close(fd);
+
+ /* read time */
+ times(&stm);
+ for(run = 0; run < RUN; ++run)
+ { if((fd = open(file, O_RDWR)) < 0)
+ return Failed(file);
+ for (i = 0; i < WRITE; ++i)
+ { for(k = 0; k < MAPSIZE; k += BUFSIZE)
+ if (read(fd,buf,BUFSIZE) != BUFSIZE)
+ return Failed(file);
+ }
+ close(fd);
+ }
+ times(&etm);
+ rdtm = (etm.tms_utime-stm.tms_utime) + (etm.tms_stime-stm.tms_stime);
+
+ /* mmap time */
+ times(&stm);
+ for(run = 0; run < RUN; ++run)
+ { if ((fd = open(file, O_RDWR)) < 0)
+ return Failed(file);
+ for(i = 0, mm = (caddr_t)0; i < WRITE; ++i)
+ { if(mm)
+ munmap(mm, MAPSIZE);
+ mm = (caddr_t)mmap((caddr_t)0, MAPSIZE,
+ (PROT_READ|PROT_WRITE),
+ MAP_PRIVATE, fd, i*MAPSIZE );
+ if(mm == (caddr_t)(-1) || mm == (caddr_t)0)
+ return Failed(file);
+
+ /* the memcpy is < BUFSIZE to simulate the
+ fact that functions like sfreserve/sfgetr do
+ not do buffer copying.
+ */
+ t = (char*)mm;
+ for(k = 0; k < MAPSIZE; k += BUFSIZE, t += BUFSIZE)
+ memcpy(buf,t,(3*BUFSIZE)/4);
+ }
+ close(fd);
+ }
+ times(&etm);
+ mmtm = (etm.tms_utime-stm.tms_utime) + (etm.tms_stime-stm.tms_stime);
+
+ remove(file);
+
+ if(4*mmtm <= 3*rdtm)
+ printf("#define _mmap_worthy 2 /* mmap is great */\n");
+ else if(4*mmtm <= 5*rdtm)
+ printf("#define _mmap_worthy 1 /* mmap is good */\n");
+
+ else
+ return 1;
+ return 0;
+ }
+}end
+
+cat{
+
+ /* some systems get it wrong but escape concise detection */
+ #ifndef _NO_MMAP
+ #if __CYGWIN__
+ #define _NO_MMAP 1
+ #endif
+ #endif
+
+ #if _NO_MMAP
+ #undef _lib_mmap
+ #undef _lib_mmap64
+ #undef _mmap_anon
+ #undef _mmap_devzero
+ #undef _mmap_worthy
+ #endif
+}end
diff --git a/src/lib/libast/features/mode.c b/src/lib/libast/features/mode.c
new file mode 100644
index 0000000..68b5e68
--- /dev/null
+++ b/src/lib/libast/features/mode.c
@@ -0,0 +1,218 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * generate mode features
+ */
+
+#include "limits.h"
+
+#include "FEATURE/param"
+
+#include <modecanon.h>
+
+int
+main()
+{
+ int n;
+ int idperm;
+ int idtype;
+
+ idperm = idtype = 1;
+#ifndef S_ITYPE
+#ifdef S_IFMT
+ printf("#define S_ITYPE(m) ((m)&S_IFMT)\n");
+#else
+ printf("#define S_ITYPE(m) ((m)&~S_IPERM)\n");
+#endif
+#endif
+#ifdef S_ISBLK
+ if (!S_ISBLK(X_IFBLK)) idtype = 0;
+#else
+#ifdef S_IFBLK
+ printf("#define S_ISBLK(m) (S_ITYPE(m)==S_IFBLK)\n");
+#else
+ printf("#define S_ISBLK(m) 0\n");
+#endif
+#endif
+#ifdef S_ISCHR
+ if (!S_ISCHR(X_IFCHR)) idtype = 0;
+#else
+#ifdef S_IFCHR
+ printf("#define S_ISCHR(m) (S_ITYPE(m)==S_IFCHR)\n");
+#else
+ printf("#define S_ISCHR(m) 0\n");
+#endif
+#endif
+#ifdef S_ISCTG
+ if (!S_ISCTG(X_IFCTG)) idtype = 0;
+#else
+#ifdef S_IFCTG
+ printf("#define S_ISCTG(m) (S_ITYPE(m)==S_IFCTG)\n");
+#endif
+#endif
+#ifdef S_ISDIR
+ if (!S_ISDIR(X_IFDIR)) idtype = 0;
+#else
+#ifdef S_IFDIR
+ printf("#define S_ISDIR(m) (S_ITYPE(m)==S_IFDIR)\n");
+#else
+ printf("#define S_ISDIR(m) 0\n");
+#endif
+#endif
+#ifdef S_ISFIFO
+ if (!S_ISFIFO(X_IFIFO)) idtype = 0;
+#else
+#ifdef S_IFIFO
+ printf("#define S_ISFIFO(m) (S_ITYPE(m)==S_IFIFO)\n");
+#else
+ printf("#define S_ISFIFO(m) 0\n");
+#endif
+#endif
+#ifdef S_ISLNK
+ if (!S_ISLNK(X_IFLNK)) idtype = 0;
+#else
+#ifdef S_IFLNK
+ printf("#define S_ISLNK(m) (S_ITYPE(m)==S_IFLNK)\n");
+#else
+ printf("#define S_ISLNK(m) 0\n");
+#endif
+#endif
+#ifdef S_ISREG
+ if (!S_ISREG(X_IFREG)) idtype = 0;
+#else
+#ifdef S_IFREG
+ printf("#define S_ISREG(m) (S_ITYPE(m)==S_IFREG)\n");
+#else
+ printf("#define S_ISREG(m) 0\n");
+#endif
+#endif
+#ifdef S_ISSOCK
+ if (!S_ISSOCK(X_IFSOCK)) idtype = 0;
+#else
+#ifdef S_IFSOCK
+ printf("#define S_ISSOCK(m) (S_ITYPE(m)==S_IFSOCK)\n");
+#endif
+#endif
+ printf("\n");
+#ifndef S_IPERM
+ printf("#define S_IPERM (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)\n");
+#endif
+#ifndef S_ISUID
+ printf("#define S_ISUID 0%04o\n", X_ISUID);
+#else
+ if (S_ISUID != X_ISUID) idperm = 0;
+#endif
+#ifndef S_ISGID
+ printf("#define S_ISGID 0%04o\n", X_ISGID);
+#else
+ if (S_ISGID != X_ISGID) idperm = 0;
+#endif
+#ifndef S_ISVTX
+ printf("#define S_ISVTX 0%04o\n", X_ISVTX);
+#else
+ if (S_ISVTX != X_ISVTX) idperm = 0;
+#endif
+#ifndef S_IRUSR
+ printf("#define S_IRUSR 0%04o\n", X_IRUSR);
+#else
+ if (S_IRUSR != X_IRUSR) idperm = 0;
+#endif
+#ifndef S_IWUSR
+ printf("#define S_IWUSR 0%04o\n", X_IWUSR);
+#else
+ if (S_IWUSR != X_IWUSR) idperm = 0;
+#endif
+#ifndef S_IXUSR
+ printf("#define S_IXUSR 0%04o\n", X_IXUSR);
+#else
+ if (S_IXUSR != X_IXUSR) idperm = 0;
+#endif
+#ifndef S_IRGRP
+ printf("#define S_IRGRP 0%04o\n", X_IRGRP);
+#else
+ if (S_IRGRP != X_IRGRP) idperm = 0;
+#endif
+#ifndef S_IWGRP
+ printf("#define S_IWGRP 0%04o\n", X_IWGRP);
+#else
+ if (S_IWGRP != X_IWGRP) idperm = 0;
+#endif
+#ifndef S_IXGRP
+ printf("#define S_IXGRP 0%04o\n", X_IXGRP);
+#else
+ if (S_IXGRP != X_IXGRP) idperm = 0;
+#endif
+#ifndef S_IROTH
+ printf("#define S_IROTH 0%04o\n", X_IROTH);
+#else
+ if (S_IROTH != X_IROTH) idperm = 0;
+#endif
+#ifndef S_IWOTH
+ printf("#define S_IWOTH 0%04o\n", X_IWOTH);
+#else
+ if (S_IWOTH != X_IWOTH) idperm = 0;
+#endif
+#ifndef S_IXOTH
+ printf("#define S_IXOTH 0%04o\n", X_IXOTH);
+#else
+ if (S_IXOTH != X_IXOTH) idperm = 0;
+#endif
+#ifndef S_IRWXU
+ printf("#define S_IRWXU (S_IRUSR|S_IWUSR|S_IXUSR)\n");
+#endif
+#ifndef S_IRWXG
+ printf("#define S_IRWXG (S_IRGRP|S_IWGRP|S_IXGRP)\n");
+#endif
+#ifndef S_IRWXO
+ printf("#define S_IRWXO (S_IROTH|S_IWOTH|S_IXOTH)\n");
+#endif
+ printf("\n");
+ if (idperm) printf("#define _S_IDPERM 1\n");
+ if (idtype) printf("#define _S_IDTYPE 1\n");
+ printf("\n");
+#ifdef BUFFERSIZE
+ n = BUFFERSIZE;
+#else
+#ifdef MAXBSIZE
+ n = MAXBSIZE;
+#else
+#ifdef SBUFSIZE
+ n = SBUFSIZE;
+#else
+#ifdef BUFSIZ
+ n = BUFSIZ;
+#else
+ if (sizeof(char*) > 4) n = 8192;
+ else if (sizeof(char*) < 4) n = 512;
+ else n = 4096;
+#endif
+#endif
+#endif
+#endif
+ printf("#define BUFFERSIZE %u\n", n);
+ printf("\n");
+ return 0;
+}
diff --git a/src/lib/libast/features/ndbm b/src/lib/libast/features/ndbm
new file mode 100644
index 0000000..d12d15c
--- /dev/null
+++ b/src/lib/libast/features/ndbm
@@ -0,0 +1,29 @@
+if tst -ldb note{ sleepycat ndbm compatibility }end link{
+ #define DB_DBM_HSEARCH 1
+ #include <db.h>
+ int main()
+ {
+ DBM* dbm = 0;
+ dbm_close(dbm);
+ return 0;
+ }
+ }end {
+ #ifndef DB_DBM_HSEARCH
+ #define DB_DBM_HSEARCH 1
+ #include <db.h>
+ #endif
+ #define _use_ndbm 1
+ }
+elif hdr gdbm-ndbm {
+ #include <gdbm-ndbm.h>
+ #define _use_ndbm 1
+}
+elif hdr gdbm/ndbm {
+ #include <gdbm/ndbm.h>
+ #define _use_ndbm 1
+}
+elif hdr ndbm {
+ #include <ndbm.h>
+ #define _use_ndbm 1
+}
+endif
diff --git a/src/lib/libast/features/nl_types b/src/lib/libast/features/nl_types
new file mode 100644
index 0000000..02cae3e
--- /dev/null
+++ b/src/lib/libast/features/nl_types
@@ -0,0 +1,64 @@
+set prototyped
+lib catopen,nl_langinfo
+hdr nl_types,langinfo
+nxt nl_types
+
+tst output{
+ #if !_lib_catopen
+ #undef _hdr_nl_types
+ #endif
+ #include "FEATURE/limits"
+ #if _hdr_nl_types
+ #include <nl_types.h>
+ #endif
+
+ int
+ main()
+ {
+ printf("#include <limits.h>\n");
+ #if _hdr_nl_types && defined(_nxt_nl_types_str)
+ printf("#include <%s> /* the native nl_types.h */\n", _nxt_nl_types_str);
+ #endif
+ printf("\n");
+ #ifndef NL_SETMAX
+ printf("#undef NL_SETMAX\n");
+ printf("#define NL_SETMAX 1023\n");
+ #endif
+ #ifndef NL_MSGMAX
+ printf("#undef NL_MSGMAX\n");
+ printf("#define NL_MSGMAX 32767\n");
+ #endif
+ #ifndef NL_SETD
+ printf("#undef NL_SETD\n");
+ printf("#define NL_SETD 1\n");
+ #endif
+ #ifndef NL_CAT_LOCALE
+ printf("#undef NL_CAT_LOCALE\n");
+ printf("#define NL_CAT_LOCALE 1\n");
+ #endif
+ #if _lib_catopen
+ printf("#undef nl_catd\n");
+ printf("#define nl_catd _ast_nl_catd\n");
+ printf("#undef catopen\n");
+ printf("#define catopen _ast_catopen\n");
+ printf("#undef catgets\n");
+ printf("#define catgets _ast_catgets\n");
+ printf("#undef catclose\n");
+ printf("#define catclose _ast_catclose\n");
+ #endif
+ printf("\n");
+ printf("typedef void* nl_catd;\n");
+ printf("\n");
+ printf("#if _BLD_ast && defined(__EXPORT__)\n");
+ printf("#define extern __EXPORT__\n");
+ printf("#endif\n");
+ printf("\n");
+ printf("extern nl_catd catopen(const char*, int);\n");
+ printf("extern char* catgets(nl_catd, int, int, const char*);\n");
+ printf("extern int catclose(nl_catd);\n");
+ printf("\n");
+ printf("#undef extern\n");
+ printf("\n");
+ return 0;
+ }
+}end
diff --git a/src/lib/libast/features/omitted b/src/lib/libast/features/omitted
new file mode 100644
index 0000000..1e4eca4
--- /dev/null
+++ b/src/lib/libast/features/omitted
@@ -0,0 +1,110 @@
+tst note{ check for win32 .exe botches }end output{
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ static int
+ cp(const char* from, const char* to)
+ {
+ ssize_t n;
+ int fd;
+ int td;
+ struct stat fs;
+ char buf[1024];
+
+ if ((fd = _open(from, O_RDONLY|O_BINARY)) < 0)
+ return -1;
+ if (_fstat(fd, &fs) || (td = _open(to, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, fs.st_mode & 0777)) < 0)
+ {
+ _close(fd);
+ return -1;
+ }
+ while ((n = _read(fd, buf, sizeof(buf))) > 0 && _write(td, buf, n) == n);
+ _close(fd);
+ _close(td);
+ return n ? -1 : 0;
+ }
+ int
+ main(int argc, char** argv)
+ {
+ int fd;
+ int fix;
+ struct stat st;
+ char buf[256];
+
+ snprintf(buf, sizeof(buf), "rm -rf /tmp/iff-%d", getpid());
+ if (_mkdir(buf+7, 0755))
+ return 1;
+ if (_chdir(buf+7))
+ return 1;
+ if (cp("/bin/cat.exe", "foo.exe"))
+ return 1;
+ fix = 0;
+ if (_access("foo", X_OK))
+ fix++,printf("#define _win32_botch_access 1\n");
+ if (_chmod("foo", 0755))
+ fix++,printf("#define _win32_botch_chmod 1\n");
+ if (cp("/bin/cat", "bam") || _access("bam.exe", X_OK))
+ fix++,printf("#define _win32_botch_copy 1\n");
+ if (_getpagesize() != 64 * 1024)
+ fix++,printf("#define _win32_botch_getpagesize 1\n");
+ #if !__EMX__
+ if (_link("foo", "bar") || _access("bar.exe", X_OK))
+ fix++,printf("#define _win32_botch_link 1\n");
+ else
+ #endif
+ cp("foo.exe", "bar.exe");
+ if ((fd = _open("foo", O_RDONLY)) < 0)
+ fix++,printf("#define _win32_botch_open 1\n");
+ else
+ _close(fd);
+ if (_pathconf("huh", _PC_NAME_MAX) >= 0)
+ fix++,printf("#define _win32_botch_pathconf 1\n");
+ if (_rename("foo", "aha") || _access("aha.exe", X_OK))
+ fix++,printf("#define _win32_botch_rename 1\n");
+ else
+ _rename("foo.exe", "aha.exe");
+ if (_stat("bar", &st))
+ {
+ fix++,printf("#define _win32_botch_stat 1\n");
+ if (sizeof(st.st_ino) == 8)
+ printf("#define _stat _stat64\n");
+ }
+ if (_truncate("aha", 0))
+ fix++,printf("#define _win32_botch_truncate 1\n");
+ if (_unlink("bar"))
+ fix++,printf("#define _win32_botch_unlink 1\n");
+ if (_utime("aha", 0))
+ fix++,printf("#define _win32_botch_utime 1\n");
+ if (fix)
+ {
+ printf("#define _win32_botch_execve 1\n");
+ printf("#define _win32_botch 1\n");
+ }
+ _chdir("/tmp");
+ system(buf);
+ return 0;
+ }
+}end
+
+tst win32_botch_alarm note{ win32 alarm(2) return botched }end noexecute{
+ #include <signal.h>
+ #include <unistd.h>
+ #include <time.h>
+
+ static int sigalrm = 0;
+
+ static void
+ handler(int sig)
+ {
+ sigalrm++;
+ }
+ int
+ main(int argc, char** argv)
+ {
+ signal(SIGALRM, handler);
+ alarm(2);
+ pause();
+ return sigalrm != 1 || alarm(0) != 0;
+ }
+}end
diff --git a/src/lib/libast/features/options b/src/lib/libast/features/options
new file mode 100644
index 0000000..500bd63
--- /dev/null
+++ b/src/lib/libast/features/options
@@ -0,0 +1 @@
+opt map-libc
diff --git a/src/lib/libast/features/param.sh b/src/lib/libast/features/param.sh
new file mode 100644
index 0000000..7d4a856
--- /dev/null
+++ b/src/lib/libast/features/param.sh
@@ -0,0 +1,47 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1985-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# David Korn <dgk@research.att.com> #
+# Phong Vo <kpv@research.att.com> #
+# #
+########################################################################
+: generate "<sys/param.h> + <sys/types.h> + <sys/stat.h>" include sequence
+case $# in
+0) ;;
+*) eval $1
+ shift
+ ;;
+esac
+for i in "#include <sys/param.h>" "#include <sys/param.h>
+#ifndef S_IFDIR
+#include <sys/stat.h>
+#endif" "#include <sys/param.h>
+#ifndef S_IFDIR
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif" "#ifndef S_IFDIR
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif"
+do echo "$i
+struct stat V_stat_V;
+F_stat_F() { V_stat_V.st_mode = 0; }" > $tmp.c
+ if $cc -c $tmp.c >/dev/null
+ then echo "$i"
+ break
+ fi
+done
diff --git a/src/lib/libast/features/preroot.sh b/src/lib/libast/features/preroot.sh
new file mode 100644
index 0000000..40ac2fc
--- /dev/null
+++ b/src/lib/libast/features/preroot.sh
@@ -0,0 +1,46 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1985-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# David Korn <dgk@research.att.com> #
+# Phong Vo <kpv@research.att.com> #
+# #
+########################################################################
+: generate preroot features
+case $# in
+0) ;;
+*) eval $1
+ shift
+ ;;
+esac
+if /etc/preroot / /bin/echo >/dev/null
+then cat <<!
+#pragma prototyped
+
+#define FS_PREROOT 1 /* preroot enabled */
+#define PR_BASE "CCS" /* preroot base env var */
+#define PR_COMMAND "/etc/preroot" /* the preroot command */
+#define PR_REAL "/dev/.." /* real root pathname */
+#define PR_SILENT "CCSQUIET" /* no command trace */
+
+extern char* getpreroot(char*, const char*);
+extern int ispreroot(const char*);
+extern int realopen(const char*, int, int);
+extern void setpreroot(char**, const char*);
+
+!
+else echo "/* preroot not enabled */"
+fi
diff --git a/src/lib/libast/features/prog b/src/lib/libast/features/prog
new file mode 100644
index 0000000..365ce88
--- /dev/null
+++ b/src/lib/libast/features/prog
@@ -0,0 +1,12 @@
+lib getexecname,_NSGetExecutablePath
+
+tst run{
+ for p in /proc/self/exe /proc/self/path/a.out
+ do if test -e $p
+ then echo "#define _PROC_PROG \"$p\""
+ break
+ fi
+ done
+}end
+
+_hdr_macho_o_dyld = hdr mach-o/dyld
diff --git a/src/lib/libast/features/sfinit.c b/src/lib/libast/features/sfinit.c
new file mode 100644
index 0000000..ccd0527
--- /dev/null
+++ b/src/lib/libast/features/sfinit.c
@@ -0,0 +1,94 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * generate sfio _Sftable static initializers
+ */
+
+#include "FEATURE/common"
+#include "FEATURE/float"
+
+int
+main()
+{
+ register int i;
+#if _ast_fltmax_double
+ char* fs = "";
+ char* ds = "";
+ char* ls = "";
+#else
+ char* fs = "F";
+ char* ds = "";
+ char* ls = "L";
+#endif
+
+ printf("\nstatic const float sf_flt_pow10[] =\n{\n");
+ for (i = 0; i <= FLT_MAX_10_EXP; i++)
+ printf("\t1E%d%s,\n", i, fs);
+ printf("};\n");
+ printf("\nstatic const double sf_dbl_pow10[] =\n{\n");
+ for (i = 0; i <= DBL_MAX_10_EXP; i++)
+ printf("\t1E%d%s,\n", i, ds);
+ printf("};\n");
+#if !_ast_fltmax_double
+ printf("\nstatic const _ast_fltmax_t sf_ldbl_pow10[] =\n{\n");
+ for (i = 0; i <= LDBL_MAX_10_EXP; i++)
+ printf("\t1E%d%s,\n", i, ls);
+ printf("};\n");
+#endif
+ printf("\nSftab_t _Sftable =\n{\n");
+ printf("\t{ 1E1%s, 1E2%s, 1E4%s, 1E8%s, 1E16%s, 1E32%s },\n", ls, ls, ls, ls, ls, ls);
+ printf("\t{ 1E-1%s, 1E-2%s, 1E-4%s, 1E-8%s, 1E-16%s, 1E-32%s },\n", ls, ls, ls, ls, ls, ls);
+ printf("\t{ '0','0', '0','1', '0','2', '0','3', '0','4',\n");
+ printf("\t '0','5', '0','6', '0','7', '0','8', '0','9',\n");
+ printf("\t '1','0', '1','1', '1','2', '1','3', '1','4',\n");
+ printf("\t '1','5', '1','6', '1','7', '1','8', '1','9',\n");
+ printf("\t '2','0', '2','1', '2','2', '2','3', '2','4',\n");
+ printf("\t '2','5', '2','6', '2','7', '2','8', '2','9',\n");
+ printf("\t '3','0', '3','1', '3','2', '3','3', '3','4',\n");
+ printf("\t '3','5', '3','6', '3','7', '3','8', '3','9',\n");
+ printf("\t '4','0', '4','1', '4','2', '4','3', '4','4',\n");
+ printf("\t '4','5', '4','6', '4','7', '4','8', '4','9',\n");
+ printf("\t '5','0', '5','1', '5','2', '5','3', '5','4',\n");
+ printf("\t '5','5', '5','6', '5','7', '5','8', '5','9',\n");
+ printf("\t '6','0', '6','1', '6','2', '6','3', '6','4',\n");
+ printf("\t '6','5', '6','6', '6','7', '6','8', '6','9',\n");
+ printf("\t '7','0', '7','1', '7','2', '7','3', '7','4',\n");
+ printf("\t '7','5', '7','6', '7','7', '7','8', '7','9',\n");
+ printf("\t '8','0', '8','1', '8','2', '8','3', '8','4',\n");
+ printf("\t '8','5', '8','6', '8','7', '8','8', '8','9',\n");
+ printf("\t '9','0', '9','1', '9','2', '9','3', '9','4',\n");
+ printf("\t '9','5', '9','6', '9','7', '9','8', '9','9',\n");
+ printf("\t},\n");
+ printf("\t\"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_\",\n");
+ printf("\tsfcvinit, 0,\n");
+ printf("\tsffmtpos,\n");
+ printf("\tsffmtint,\n");
+ printf("\t(float*)&sf_flt_pow10[0],\n");
+ printf("\t(double*)&sf_dbl_pow10[0],\n");
+#if _ast_fltmax_double
+ printf("\t0,\n");
+#else
+ printf("\t(_ast_fltmax_t*)&sf_ldbl_pow10[0],\n");
+#endif
+ printf("};\n");
+ return 0;
+}
diff --git a/src/lib/libast/features/sfio b/src/lib/libast/features/sfio
new file mode 100644
index 0000000..901935a
--- /dev/null
+++ b/src/lib/libast/features/sfio
@@ -0,0 +1,170 @@
+ref -D_def_map_ast=1
+hdr float,floatingpoint,math,values
+sys filio,ioctl
+lib qfrexp,qldexp
+key signed
+
+tst - note{ number of bits in pointer }end output{
+ #include <stdio.h>
+ int
+ main()
+ {
+ printf("#define _ptr_bits %d\n", sizeof(char*) * 8);
+ return 0;
+ }
+}end
+
+tst tmp_rmfail note{ open files cannot be removed }end execute{
+ #include <string.h>
+ #include <time.h>
+ int
+ main()
+ {
+ #if !_UWIN
+ int n;
+ char* s;
+ FILE* fr;
+ FILE* fw;
+ char file[16];
+ static char data[] = "0123456789";
+ s = file;
+ *s++ = '1';
+ *s++ = 'F';
+ *s++ = 'F';
+ *s++ = '3';
+ n = (int)time(0);
+ *s++ = (n & 0xF) + 'A';
+ *s++ = ((n >> 4) & 0xF) + 'A';
+ *s++ = ((n >> 8) & 0xF) + 'A';
+ *s++ = ((n >> 12) & 0xF) + 'A';
+ *s++ = '.';
+ *s++ = 'T';
+ *s++ = 'M';
+ *s++ = 'P';
+ *s = 0;
+ remove(file);
+ if (!(fw = fopen(file, "w")))
+ return 0;
+ if (!(fr = fopen(file, "r")))
+ {
+ fclose(fw);
+ remove(file);
+ return 0;
+ }
+ if (remove(file) < 0)
+ {
+ fclose(fr);
+ fclose(fw);
+ remove(file);
+ return 0;
+ }
+ if (fwrite(data, sizeof(data), 1, fw) != 1)
+ return 0;
+ fclose(fw);
+ if (fread(file, sizeof(data), 1, fr) != 1)
+ return 0;
+ fclose(fr);
+ if (strcmp(file, data) != 0)
+ return 0;
+ #endif
+ return 1;
+ }
+}end
+
+more void_int note{ voidptr is larger than int }end execute{
+ int
+ main()
+ {
+ return sizeof(char*) > sizeof(int) ? 0 : 1;
+ }
+}end
+
+more long_int note{ long is larger than int }end execute{
+ int
+ main()
+ {
+ return sizeof(long) > sizeof(int) ? 0 : 1;
+ }
+}end
+
+tst vax_asm note{ register layout ok for vax string operations }end execute{
+ int
+ main()
+ {
+ #ifndef vax
+ return absurd = -1;
+ #else
+ register int r11, r10, r9, r8, r7, r6;
+ r11 = r10 = r9 = r8 = r7 = r6 = -1;
+ asm("clrw r11");
+ asm("clrw r10");
+ asm("clrw r9");
+ asm("clrw r8");
+ asm("clrw r7");
+ asm("clrw r6");
+ if(sizeof(int) != sizeof(char*) || r11 || r10 || r9 || r8 || r7 || r6 )
+ return -1;
+ return 0;
+ #endif
+ }
+}end
+
+tst lib_cvt note{ native floating point conversions ok }end link{
+ _BEGIN_EXTERNS_
+ extern char* ecvt _ARG_((double, int, int*, int*));
+ extern char* fcvt _ARG_((double, int, int*, int*));
+ extern double strtod _ARG_((const char*, char**));
+ _END_EXTERNS_
+ int
+ main()
+ {
+ ecvt(0.0, 0, 0, 0);
+ fcvt(0.0, 0, 0, 0);
+ strtod(0, 0);
+ return 0;
+ }
+}end
+
+tst xopen_stdio note{ Stdio fseek/fflush are X/Open-compliant }end execute{
+ #define Failed(file) (unlink(file),1)
+ int
+ main(argc, argv)
+ int argc;
+ char** argv;
+ { FILE *f1, *f2;
+ char file[1024], buf[1024], *f, *t;
+ int i, fd;
+
+ /* create file */
+ for(f = argv[0], t = file; (*t = *f++) != 0; )
+ t++;
+ *t++ = '.'; *t++ = 'D'; *t++ = 0;
+ if((fd = creat(file,0666)) < 0)
+ return 1;
+
+ for (i = 0; i < sizeof(buf); ++i)
+ buf[i] = '0' + (i%10);
+ for (i = 0; i < 16; ++i)
+ if (write(fd,buf,sizeof(buf)) != sizeof(buf))
+ return Failed(file);
+ close(fd);
+
+ if(!(f1 = fopen(file,"r+")) ||
+ (fd = dup(fileno(f1))) < 0 ||
+ !(f2 = fdopen(fd,"r+")) )
+ return Failed(file);
+
+ if(fread(buf, 1, 7, f2) != 7 || ftell(f2) != 7)
+ return Failed(file);
+
+ if(fseek(f1, 1010, 0) < 0 || ftell(f1) != 1010)
+ return Failed(file);
+
+ fflush(f2); /* this should set the seek location to 1010 */
+ if(ftell(f2) != 1010)
+ return Failed(file);
+
+ unlink(file);
+ return 0;
+ }
+}end
diff --git a/src/lib/libast/features/sig.sh b/src/lib/libast/features/sig.sh
new file mode 100644
index 0000000..706372b
--- /dev/null
+++ b/src/lib/libast/features/sig.sh
@@ -0,0 +1,132 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1985-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# David Korn <dgk@research.att.com> #
+# Phong Vo <kpv@research.att.com> #
+# #
+########################################################################
+: generate sig features
+case $# in
+0) ;;
+*) eval $1
+ shift
+ ;;
+esac
+echo "#include <signal.h>
+int xxx;" > $tmp.c
+$cc -c $tmp.c >/dev/null 2>$tmp.e
+echo "#pragma prototyped
+#define sig_info _sig_info_
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide kill killpg
+#else
+#define kill ______kill
+#define killpg ______killpg
+#endif
+#include <signal.h>
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide kill killpg
+#else
+#undef kill
+#undef killpg
+#endif
+#ifndef sigmask
+#define sigmask(s) (1<<((s)-1))
+#endif"
+echo "#include <signal.h>
+#ifdef TYPE
+#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
+typedef TYPE (*Sig_handler_t)(ARG);
+#else
+typedef TYPE (*Sig_handler_t)();
+#endif
+#endif
+Sig_handler_t f()
+{
+ Sig_handler_t handler;
+ handler = signal(1, SIG_IGN);
+ return(handler);
+}" > $tmp.c
+if $cc -c $tmp.c >/dev/null
+then :
+else e=`wc -l $tmp.e`
+ i1= j1=
+ for i in void int
+ do for j in int,... ... int
+ do $cc -c -DTYPE=$i -DARG=$j $tmp.c >/dev/null 2>$tmp.e || continue
+ case `wc -l $tmp.e` in
+ $e) i1= j1=; break 2 ;;
+ esac
+ case $i1 in
+ "") i1=$i j1=$j ;;
+ esac
+ done
+ done
+ case $i1 in
+ ?*) i=$i1 j=$j1 ;;
+ esac
+ echo "typedef $i (*Sig_handler_t)($j);"
+fi
+echo '
+
+#define Handler_t Sig_handler_t
+
+#define SIG_REG_PENDING (-1)
+#define SIG_REG_POP 0
+#define SIG_REG_EXEC 00001
+#define SIG_REG_PROC 00002
+#define SIG_REG_TERM 00004
+#define SIG_REG_ALL 00777
+#define SIG_REG_SET 01000
+
+typedef struct
+{
+ char** name;
+ char** text;
+ int sigmax;
+} Sig_info_t;
+
+extern int kill(pid_t, int);
+extern int killpg(pid_t, int);
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+#if !_BLD_ast && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern Sig_info_t sig_info;
+
+#undef extern
+
+#if _lib_sigflag && _npt_sigflag
+extern int sigflag(int, int, int);
+#endif
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#if !_lib_sigflag
+extern int sigflag(int, int, int);
+#endif
+extern int sigcritical(int);
+extern int sigunblock(int);
+
+#undef extern'
diff --git a/src/lib/libast/features/siglist b/src/lib/libast/features/siglist
new file mode 100644
index 0000000..37d1bf0
--- /dev/null
+++ b/src/lib/libast/features/siglist
@@ -0,0 +1,14 @@
+lib strsignal string.h signal.h
+
+tst - run{
+ for sig in `/bin/kill -l 2>/dev/null`
+ do case $sig in
+ *[!A-Za-z0-9_]*|*MIN|*MAX)
+ ;;
+ *) echo "#if defined(SIG$sig) && !defined(HAD_SIG$sig)"
+ echo "0,\"$sig\",SIG$sig,"
+ echo "#endif"
+ ;;
+ esac
+ done
+}end
diff --git a/src/lib/libast/features/signal.c b/src/lib/libast/features/signal.c
new file mode 100644
index 0000000..07c9b4b
--- /dev/null
+++ b/src/lib/libast/features/signal.c
@@ -0,0 +1,371 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * generate signal features
+ */
+
+#include "FEATURE/standards"
+
+#define strsignal ______strsignal
+
+#include <signal.h>
+
+#undef strsignal
+
+struct _m_
+{
+ char* text;
+ char* name;
+ int value;
+};
+
+#define elementsof(x) (sizeof(x)/sizeof(x[0]))
+
+static struct _m_ map[] =
+{
+#ifdef SIGABRT
+#define HAD_SIGABRT 1
+"Abort", "ABRT", SIGABRT,
+#endif
+#ifdef SIGAIO
+#define HAD_SIGAIO 1
+"Asynchronous I/O", "AIO", SIGAIO,
+#endif
+#ifdef SIGALRM
+#define HAD_SIGALRM 1
+"Alarm call", "ALRM", SIGALRM,
+#endif
+#ifdef SIGAPOLLO
+#define HAD_SIGAPOLLO 1
+"Apollo", "APOLLO", SIGAPOLLO,
+#endif
+#ifdef SIGBUS
+#define HAD_SIGBUS 1
+"Bus error", "BUS", SIGBUS,
+#endif
+#ifdef SIGCHLD
+#define HAD_SIGCHLD 1
+"Child status change", "CHLD", SIGCHLD,
+#endif
+#ifdef SIGCLD
+#define HAD_SIGCLD 1
+"Death of child", "CLD", SIGCLD,
+#endif
+#ifdef SIGCONT
+#define HAD_SIGCONT 1
+"Stopped process continued", "CONT", SIGCONT,
+#endif
+#ifdef SIGDANGER
+#define HAD_SIGDANGER 1
+"System crash soon", "DANGER", SIGDANGER,
+#endif
+#ifdef SIGDEBUG
+#define HAD_SIGDEBUG 1
+"Debug trap", "DEBUG", SIGDEBUG,
+#endif
+#ifdef SIGDIL
+#define HAD_SIGDIL 1
+"DIL trap", "DIL", SIGDIL,
+#endif
+#ifdef SIGEMT
+#define HAD_SIGEMT 1
+"EMT trap", "EMT", SIGEMT,
+#endif
+#ifdef SIGERR
+#define HAD_SIGERR 1
+"ERR trap", "ERR", SIGERR,
+#endif
+#ifdef SIGEXIT
+#define HAD_SIGEXIT 1
+"Exit", "EXIT", SIGEXIT,
+#endif
+#ifdef SIGFPE
+#define HAD_SIGFPE 1
+"Floating exception", "FPE", SIGFPE,
+#endif
+#ifdef SIGFREEZE
+#define HAD_SIGFREEZE 1
+"CPR freeze", "FREEZE", SIGFREEZE,
+#endif
+#ifdef SIGHUP
+#define HAD_SIGHUP 1
+"Hangup", "HUP", SIGHUP,
+#endif
+#ifdef SIGILL
+#define HAD_SIGILL 1
+"Illegal instruction", "ILL", SIGILL,
+#endif
+#ifdef SIGINT
+#define HAD_SIGINT 1
+"Interrupt", "INT", SIGINT,
+#endif
+#ifdef SIGIO
+#define HAD_SIGIO 1
+"IO possible", "IO", SIGIO,
+#endif
+#ifdef SIGIOT
+#define HAD_SIGIOT 1
+"IOT trap", "IOT", SIGIOT,
+#endif
+#ifdef SIGKILL
+#define HAD_SIGKILL 1
+"Killed", "KILL", SIGKILL,
+#endif
+#ifdef SIGLAB
+#define HAD_SIGLAB 1
+"Security label changed", "LAB", SIGLAB,
+#endif
+#ifdef SIGLOST
+#define HAD_SIGLOST 1
+"Resources lost", "LOST", SIGLOST,
+#endif
+#ifdef SIGLWP
+#define HAD_SIGLWP 1
+"Thread event", "LWP", SIGLWP,
+#endif
+#ifdef SIGMIGRATE
+#define HAD_SIGMIGRATE 1
+"Migrate process", "MIGRATE", SIGMIGRATE,
+#endif
+#ifdef SIGPHONE
+#define HAD_SIGPHONE 1
+"Phone status change", "PHONE", SIGPHONE,
+#endif
+#ifdef SIGPIPE
+#define HAD_SIGPIPE 1
+"Broken pipe", "PIPE", SIGPIPE,
+#endif
+#ifdef SIGPOLL
+#define HAD_SIGPOLL 1
+"Poll event", "POLL", SIGPOLL,
+#endif
+#ifdef SIGPROF
+#define HAD_SIGPROF 1
+"Profile timer alarm", "PROF", SIGPROF,
+#endif
+#ifdef SIGPWR
+#define HAD_SIGPWR 1
+"Power fail", "PWR", SIGPWR,
+#endif
+#ifdef SIGQUIT
+#define HAD_SIGQUIT 1
+"Quit", "QUIT", SIGQUIT,
+#endif
+#ifdef SIGSEGV
+#define HAD_SIGSEGV 1
+"Memory fault", "SEGV", SIGSEGV,
+#endif
+#ifdef SIGSOUND
+#define HAD_SIGSOUND 1
+"Sound completed", "SOUND", SIGSOUND,
+#endif
+#ifdef SIGSSTOP
+#define HAD_SIGSSTOP 1
+"Sendable stop", "SSTOP", SIGSSTOP,
+#endif
+#ifdef gould
+#define HAD_gould 1
+"Stack overflow", "STKOV", 28,
+#endif
+#ifdef SIGSTOP
+#define HAD_SIGSTOP 1
+"Stopped (signal)", "STOP", SIGSTOP,
+#endif
+#ifdef SIGSYS
+#define HAD_SIGSYS 1
+"Bad system call", "SYS", SIGSYS,
+#endif
+#ifdef SIGTERM
+#define HAD_SIGTERM 1
+"Terminated", "TERM", SIGTERM,
+#endif
+#ifdef SIGTHAW
+#define HAD_SIGTHAW 1
+"CPR thaw", "THAW", SIGTHAW,
+#endif
+#ifdef SIGTINT
+#define HAD_SIGTINT 1
+"Interrupt (terminal)", "TINT", SIGTINT,
+#endif
+#ifdef SIGTRAP
+#define HAD_SIGTRAP 1
+"Trace trap", "TRAP", SIGTRAP,
+#endif
+#ifdef SIGTSTP
+#define HAD_SIGTSTP 1
+"Stopped", "TSTP", SIGTSTP,
+#endif
+#ifdef SIGTTIN
+#define HAD_SIGTTIN 1
+"Stopped (tty input)", "TTIN", SIGTTIN,
+#endif
+#ifdef SIGTTOU
+#define HAD_SIGTTOU 1
+"Stopped (tty output)", "TTOU", SIGTTOU,
+#endif
+#ifdef SIGURG
+#define HAD_SIGURG 1
+"Urgent IO", "URG", SIGURG,
+#endif
+#ifdef SIGUSR1
+#define HAD_SIGUSR1 1
+"User signal 1", "USR1", SIGUSR1,
+#endif
+#ifdef SIGUSR2
+#define HAD_SIGUSR2 1
+"User signal 2", "USR2", SIGUSR2,
+#endif
+#ifdef SIGVTALRM
+#define HAD_SIGVTALRM 1
+"Virtual timer alarm", "VTALRM", SIGVTALRM,
+#endif
+#ifdef SIGWAITING
+#define HAD_SIGWAITING 1
+"All threads blocked", "WAITING", SIGWAITING,
+#endif
+#ifdef SIGWINCH
+#define HAD_SIGWINCH 1
+"Window change", "WINCH", SIGWINCH,
+#endif
+#ifdef SIGWIND
+#define HAD_SIGWIND 1
+"Window change", "WIND", SIGWIND,
+#endif
+#ifdef SIGWINDOW
+#define HAD_SIGWINDOW 1
+"Window change", "WINDOW", SIGWINDOW,
+#endif
+#ifdef SIGXCPU
+#define HAD_SIGXCPU 1
+"CPU time limit", "XCPU", SIGXCPU,
+#endif
+#ifdef SIGXFSZ
+#define HAD_SIGXFSZ 1
+"File size limit", "XFSZ", SIGXFSZ,
+#endif
+#include "FEATURE/siglist"
+0
+};
+
+#define RANGE_MIN (1<<14)
+#define RANGE_MAX (1<<13)
+#define RANGE_RT (1<<12)
+
+#define RANGE_SIG (~(RANGE_MIN|RANGE_MAX|RANGE_RT))
+
+static int mapindex[1024];
+
+#if _lib_strsignal
+extern char* strsignal(int);
+#endif
+
+int
+main()
+{
+ register int i;
+ register int j;
+ register int k;
+ int m;
+ int n;
+#if _lib_strsignal
+ char* s;
+#endif
+
+ k = 0;
+ for (i = 0; map[i].name; i++)
+ if ((j = map[i].value) > 0 && j < elementsof(mapindex) && !mapindex[j])
+ {
+ if (j > k)
+ k = j;
+ mapindex[j] = i;
+ }
+#ifdef SIGRTMIN
+ i = SIGRTMIN;
+#ifdef SIGRTMAX
+ j = SIGRTMAX;
+#else
+ j = i;
+#endif
+ if (j >= elementsof(mapindex))
+ j = elementsof(mapindex) - 1;
+ if (i <= j && i > 0 && i < elementsof(mapindex) && j > 0 && j < elementsof(mapindex))
+ {
+ if (j > k)
+ k = j;
+ mapindex[i] = RANGE_MIN | RANGE_RT;
+ n = 1;
+ while (++i < j)
+ mapindex[i] = RANGE_RT | n++;
+ mapindex[j] = RANGE_MAX | RANGE_RT | n;
+ }
+#endif
+ printf("#pragma prototyped\n");
+ printf("#define SIG_MAX %d\n", k);
+ printf("\n");
+ printf("static const char* const sig_name[] =\n");
+ printf("{\n");
+ for (i = 0; i <= k; i++)
+ if (!(j = mapindex[i]))
+ printf(" \"%d\",\n", i);
+ else if (j & RANGE_RT)
+ {
+ if (j & RANGE_MIN)
+ printf(" \"RTMIN\",\n");
+ else if (j & RANGE_MAX)
+ printf(" \"RTMAX\",\n");
+ else
+ {
+ m = j & RANGE_SIG;
+ if (m > n / 2)
+ printf(" \"RTMAX-%d\",\n", n - m);
+ else
+ printf(" \"RTMIN+%d\",\n", m);
+ }
+ }
+ else
+ printf(" \"%s\",\n", map[j].name);
+ printf(" 0\n");
+ printf("};\n");
+ printf("\n");
+ printf("static const char* const sig_text[] =\n");
+ printf("{\n");
+ for (i = 0; i <= k; i++)
+ if (!(j = mapindex[i]))
+ printf(" \"Signal %d\",\n", i);
+ else if (j & RANGE_RT)
+ printf(" \"Realtime priority %d%s\",\n", j & RANGE_SIG, (j & RANGE_MIN) ? " (lo)" : (j & RANGE_MAX) ? " (hi)" : "");
+ else if (map[j].text)
+ printf(" \"%s\",\n", map[j].text);
+#if _lib_strsignal
+ else if (s = strsignal(i))
+ printf(" \"%s\",\n", s);
+#endif
+ else
+ printf(" \"Signal %d\",\n", i);
+ printf(" 0\n");
+ printf("};\n");
+ return 0;
+}
diff --git a/src/lib/libast/features/sizeof b/src/lib/libast/features/sizeof
new file mode 100644
index 0000000..06c8707
--- /dev/null
+++ b/src/lib/libast/features/sizeof
@@ -0,0 +1,13 @@
+tst - note{ sizeof(integral-type) }end output{
+ #include "FEATURE/common"
+ int
+ main()
+ {
+ printf("#define _ast_sizeof_char %d\n", sizeof(char));
+ printf("#define _ast_sizeof_short %d\n", sizeof(short));
+ printf("#define _ast_sizeof_int %d\n", sizeof(int));
+ printf("#define _ast_sizeof_long %d\n", sizeof(long));
+ printf("#define _ast_sizeof_intmax_t %d\n", sizeof(_ast_intmax_t));
+ return 0;
+ }
+}end
diff --git a/src/lib/libast/features/standards b/src/lib/libast/features/standards
new file mode 100644
index 0000000..adee277
--- /dev/null
+++ b/src/lib/libast/features/standards
@@ -0,0 +1,153 @@
+set stdio
+if tst note{ _ALL_SOURCE & _ISOC99_SOURCE & _POSIX_SOURCE & _POSIX_C_SOURCE & _XOPEN_SOURCE & __EXTENSIONS__ works }end compile{
+ #define _ALL_SOURCE 1
+ #define _ISOC99_SOURCE 1
+ #define _POSIX_SOURCE 1
+ #define _POSIX_C_SOURCE 21000101L
+ #define _XOPEN_SOURCE 9900
+ #define _GNU_SOURCE 1
+ #define __EXTENSIONS__ 1
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ }end {
+ #ifndef _ALL_SOURCE
+ #define _ALL_SOURCE 1
+ #endif
+ #ifndef _ISOC99_SOURCE
+ #define _ISOC99_SOURCE 1
+ #endif
+ #ifndef _POSIX_SOURCE
+ #define _POSIX_SOURCE 1
+ #endif
+ #ifndef _POSIX_C_SOURCE
+ #define _POSIX_C_SOURCE 21000101L
+ #endif
+ #ifndef _XOPEN_SOURCE
+ #define _XOPEN_SOURCE 9900
+ #endif
+ #ifndef _GNU_SOURCE
+ #define _GNU_SOURCE 1
+ #endif
+ #ifndef __EXTENSIONS__
+ #define __EXTENSIONS__ 1
+ #endif
+ }
+elif tst note{ _ALL_SOURCE & _ISOC99_SOURCE & _POSIX_SOURCE & _XOPEN_SOURCE & __EXTENSIONS__ works }end compile{
+ #define _ALL_SOURCE 1
+ #define _ISOC99_SOURCE 1
+ #define _POSIX_SOURCE 1
+ #define _XOPEN_SOURCE 9900
+ #define _GNU_SOURCE 1
+ #define __EXTENSIONS__ 1
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ }end {
+ #ifndef _ALL_SOURCE
+ #define _ALL_SOURCE 1
+ #endif
+ #ifndef _ISOC99_SOURCE
+ #define _ISOC99_SOURCE 1
+ #endif
+ #ifndef _POSIX_SOURCE
+ #define _POSIX_SOURCE 1
+ #endif
+ #ifndef _XOPEN_SOURCE
+ #define _XOPEN_SOURCE 9900
+ #endif
+ #ifndef _GNU_SOURCE
+ #define _GNU_SOURCE 1
+ #endif
+ #ifndef __EXTENSIONS__
+ #define __EXTENSIONS__ 1
+ #endif
+ }
+elif tst note{ _ISOC99_SOURCE & _POSIX_SOURCE & _POSIX_C_SOURCE & _XOPEN_SOURCE & __EXTENSIONS__ works }end compile{
+ #define _ISOC99_SOURCE 1
+ #define _POSIX_SOURCE 1
+ #define _POSIX_C_SOURCE 21000101L
+ #define _XOPEN_SOURCE 9900
+ #define _GNU_SOURCE 1
+ #define __EXTENSIONS__ 1
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ }end {
+ #ifndef _ISOC99_SOURCE
+ #define _ISOC99_SOURCE 1
+ #endif
+ #ifndef _POSIX_SOURCE
+ #define _POSIX_SOURCE 1
+ #endif
+ #ifndef _POSIX_C_SOURCE
+ #define _POSIX_C_SOURCE 21000101L
+ #endif
+ #ifndef _XOPEN_SOURCE
+ #define _XOPEN_SOURCE 9900
+ #endif
+ #ifndef _GNU_SOURCE
+ #define _GNU_SOURCE 1
+ #endif
+ #ifndef __EXTENSIONS__
+ #define __EXTENSIONS__ 1
+ #endif
+ }
+elif tst note{ _POSIX_SOURCE & _XOPEN_SOURCE & __EXTENSIONS__ works }end compile{
+ #define _POSIX_SOURCE 1
+ #define _XOPEN_SOURCE 1
+ #define __EXTENSIONS__ 1
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ }end {
+ #ifndef _POSIX_SOURCE
+ #define _POSIX_SOURCE 1
+ #endif
+ #ifndef _XOPEN_SOURCE
+ #define _XOPEN_SOURCE 1
+ #endif
+ #ifndef __EXTENSIONS__
+ #define __EXTENSIONS__ 1
+ #endif
+ }
+elif tst note{ _XOPEN_SOURCE & __EXTENSIONS__ works }end compile{
+ #define _XOPEN_SOURCE 1
+ #define __EXTENSIONS__ 1
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ }end {
+ #ifndef _XOPEN_SOURCE
+ #define _XOPEN_SOURCE 1
+ #endif
+ #ifndef __EXTENSIONS__
+ #define __EXTENSIONS__ 1
+ #endif
+ }
+elif tst note{ _XOPEN_SOURCE works }end compile{
+ #define _XOPEN_SOURCE 1
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ }end {
+ #ifndef _XOPEN_SOURCE
+ #define _XOPEN_SOURCE 1
+ #endif
+ }
+else tst note{ __EXTENSIONS__ works }end compile{
+ #define __EXTENSIONS__ 1
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ }end {
+ #ifndef __EXTENSIONS__
+ #define __EXTENSIONS__ 1
+ #endif
+ }
+endif
diff --git a/src/lib/libast/features/stdio b/src/lib/libast/features/stdio
new file mode 100644
index 0000000..b323893
--- /dev/null
+++ b/src/lib/libast/features/stdio
@@ -0,0 +1,568 @@
+set prototyped
+ref -D_def_map_ast=1
+iff SFSTDIO
+cat{
+ #define __FILE_typedef 1
+ #define _FILE_DEFINED 1
+ #define _FILE_defined 1
+ #define _FILEDEFED 1
+
+ #ifndef __FILE_TAG
+ #define __FILE_TAG _sfio_s
+ #endif
+
+ #undef FILE
+ #undef _FILE
+ #undef fpos_t
+ #undef fpos64_t
+
+ typedef struct _sfio_s _sfio_FILE;
+
+ #define FILE _sfio_FILE
+ #define _FILE FILE
+
+ #if !defined(__FILE) && !__CYGWIN__
+ #undef __FILE
+ #define __FILE FILE
+ #endif
+
+ #if defined(_AST_H) || defined(_SFIO_H)
+
+ #define BUFSIZ SF_BUFSIZE
+
+ #else
+
+ #ifndef BUFSIZ
+ #define BUFSIZ 8192
+ #endif
+
+ #ifndef EOF
+ #define EOF (-1)
+ #endif
+
+ #ifndef NULL
+ #define NULL 0
+ #endif
+
+ #ifndef SEEK_SET
+ #define SEEK_SET 0
+ #define SEEK_CUR 1
+ #define SEEK_END 2
+ #endif
+
+ #include <ast_std.h>
+
+ #include <sfio_s.h>
+
+ #if __cplusplus
+ #define _sf_(f) (f)
+ #else
+ #define _sf_(f) ((struct _sfio_s*)(f))
+ #endif
+
+ #define _SF_EOF 0000200
+ #define _SF_ERROR 0000400
+
+ #endif
+
+ #ifdef _NO_LARGEFILE64_SOURCE
+ #undef _LARGEFILE64_SOURCE
+ #endif
+
+ #ifdef _LARGEFILE64_SOURCE
+ #undef off_t
+ #endif
+
+ #define fpos_t _ast_fpos_t
+ #if _typ_int64_t
+ #define fpos64_t _ast_fpos_t
+ #endif
+
+ typedef struct _ast_fpos_s
+ {
+ intmax_t _sf_offset;
+ unsigned char _sf_state[64 - sizeof(intmax_t)];
+ } _ast_fpos_t;
+
+ #define _base _data
+ #define _ptr _next
+ #define _IOFBF 0
+ #define _IONBF 1
+ #define _IOLBF 2
+
+ #if defined(__cplusplus) && defined(__THROW) && !defined(_UWIN)
+
+ #undef FILE
+ #define FILE FILE
+ typedef struct _sfio_s FILE;
+
+ #undef strerror
+ extern char* strerror(int) __THROW;
+
+ extern int _doprnt(const char*, va_list, FILE*);
+ extern int _doscan(FILE*, const char*, va_list);
+ extern int asprintf(char**, const char*, ...);
+ extern int clearerr(FILE*);
+ extern int fclose(FILE*);
+ extern FILE* fdopen(int, const char*);
+ extern int feof(FILE*);
+ extern int ferror(FILE*);
+ extern int fflush(FILE*);
+ extern int fgetc(FILE*);
+ extern int fgetpos(FILE*, fpos_t*);
+ extern char* fgets(char*, int, FILE*);
+ extern int fileno(FILE*);
+ extern FILE* fopen(const char*, const char*);
+ extern int fprintf(FILE*, const char*, ...);
+ extern int fpurge(FILE*);
+ extern int fputc(int, FILE*);
+ extern int fputs(const char*, FILE*);
+ extern size_t fread(void*, size_t, size_t, FILE*);
+ extern FILE* freopen(const char*, const char*, FILE*);
+ extern int fscanf(FILE*, const char*, ...);
+ extern int fseek(FILE*, long, int);
+ extern int fseeko(FILE*, off_t, int);
+ extern int fsetpos(FILE*, const fpos_t*);
+ extern long ftell(FILE*);
+ extern off_t ftello(FILE*);
+ extern size_t fwrite(const void*, size_t, size_t, FILE*);
+ extern int getc(FILE*);
+ extern int getchar(void);
+ extern char* gets(char*);
+ extern int getw(FILE*);
+ extern int pclose(FILE*);
+ extern FILE* popen(const char*, const char*);
+ extern int printf(const char*, ...);
+ extern int putc(int, FILE*);
+ extern int putchar(int);
+ extern int puts(const char*);
+ extern int putw(int, FILE*);
+ extern void rewind(FILE*);
+ extern int scanf(const char*, ...);
+ extern void setbuf(FILE*, char*);
+ extern int setbuffer(FILE*, char*, int);
+ extern int setlinebuf(FILE*);
+ extern int setvbuf(FILE*, char*, int, size_t);
+ extern int snprintf(char*, int, const char*, ...);
+ extern int sprintf(char*, const char*, ...);
+ extern int sscanf(const char*, const char*, ...);
+ extern FILE* tmpfile(void);
+ extern int ungetc(int, FILE*);
+ extern int vasprintf(char**, const char*, va_list);
+ extern int vfprintf(FILE*, const char*, va_list);
+ extern int vfscanf(FILE*, const char*, va_list);
+ extern int vprintf(const char*, va_list);
+ extern int vscanf(const char*, va_list);
+ extern int vsnprintf(char*, int, const char*, va_list);
+ extern int vsprintf(char*, const char*, va_list);
+ extern int vsscanf(const char*, const char*, va_list);
+
+ #if _typ_int64_t
+
+ extern int fgetpos64(FILE*, fpos64_t*);
+ extern int fsetpos64(FILE*, const fpos64_t*);
+ extern int fseek64(FILE*, int64_t, int);
+ extern int fseeko64(FILE*, int64_t, int);
+ extern int64_t ftell64(FILE*);
+ extern int64_t ftello64(FILE*);
+
+ #endif
+
+ extern void clearerr_unlocked(FILE*);
+ extern int feof_unlocked(FILE*);
+ extern int ferror_unlocked(FILE*);
+ extern int fflush_unlocked(FILE*);
+ extern int fgetc_unlocked(FILE*);
+ extern char* fgets_unlocked(char*, int, FILE*);
+ extern int fileno_unlocked(FILE*);
+ extern int fputc_unlocked(int, FILE*);
+ extern int fputs_unlocked(char*, FILE*);
+ extern size_t fread_unlocked(void*, size_t, size_t, FILE*);
+ extern size_t fwrite_unlocked(void*, size_t, size_t, FILE*);
+ extern int getc_unlocked(FILE*);
+ extern int getchar_unlocked(void);
+ extern int putc_unlocked(int, FILE*);
+ extern int putchar_unlocked(int);
+
+ extern void flockfile(FILE*);
+ extern int ftrylockfile(FILE*);
+ extern void funlockfile(FILE*);
+
+ #ifdef _USE_GNU
+
+ extern int fcloseall(void);
+ extern FILE* fmemopen(void*, size_t, const char*);
+ extern ssize_t __getdelim(char**, size_t*, int, FILE*);
+ extern ssize_t getdelim(char**, size_t*, int, FILE*);
+ extern ssize_t getline(char**, size_t*, FILE*);
+
+ #endif
+
+ #endif
+}end
+output{
+ #include <stdio.h>
+ #ifndef FILENAME_MAX
+ #ifndef NAME_MAX
+ #ifndef _POSIX_NAME_MAX
+ #define _POSIX_NAME_MAX 14
+ #endif
+ #define NAME_MAX _POSIX_NAME_MAX
+ #endif
+ #define FILENAME_MAX NAME_MAX
+ #endif
+ #ifndef FOPEN_MAX
+ #ifdef STREAM_MAX
+ #define FOPEN_MAX STREAM_MAX
+ #else
+ #ifndef OPEN_MAX
+ #ifndef _POSIX_OPEN_MAX
+ #define _POSIX_OPEN_MAX 20
+ #endif
+ #define OPEN_MAX _POSIX_OPEN_MAX
+ #endif
+ #define FOPEN_MAX OPEN_MAX
+ #endif
+ #endif
+ #ifndef TMP_MAX
+ #define TMP_MAX 33520641
+ #endif
+ int
+ main()
+ {
+ printf("#ifndef FILENAME_MAX\n");
+ printf("#define FILENAME_MAX %d\n", FILENAME_MAX);
+ printf("#endif\n");
+ printf("#ifndef FOPEN_MAX\n");
+ printf("#define FOPEN_MAX %d\n", FOPEN_MAX);
+ printf("#endif\n");
+ printf("#ifndef TMP_MAX\n");
+ printf("#define TMP_MAX %d\n", TMP_MAX);
+ printf("#endif\n");
+ #if !_UWIN
+ printf("\n");
+ printf("#define _doprnt _ast_doprnt\n");
+ printf("#define _doscan _ast_doscan\n");
+ printf("#define asprintf _ast_asprintf\n");
+ printf("#define clearerr _ast_clearerr\n");
+ printf("#define fclose _ast_fclose\n");
+ printf("#define fdopen _ast_fdopen\n");
+ printf("#define fflush _ast_fflush\n");
+ printf("#define fgetc _ast_fgetc\n");
+ printf("#define fgetpos _ast_fgetpos\n");
+ printf("#define fgetpos64 _ast_fgetpos64\n");
+ printf("#define fgets _ast_fgets\n");
+ printf("#define fopen _ast_fopen\n");
+ printf("#define fprintf _ast_fprintf\n");
+ printf("#define fpurge _ast_fpurge\n");
+ printf("#define fputs _ast_fputs\n");
+ printf("#define fread _ast_fread\n");
+ printf("#define freopen _ast_freopen\n");
+ printf("#define fscanf _ast_fscanf\n");
+ printf("#define fseek _ast_fseek\n");
+ printf("#define fseek64 _ast_fseek64\n");
+ printf("#define fseeko _ast_fseeko\n");
+ printf("#define fseeko64 _ast_fseeko64\n");
+ printf("#define fsetpos _ast_fsetpos\n");
+ printf("#define fsetpos64 _ast_fsetpos64\n");
+ printf("#define ftell _ast_ftell\n");
+ printf("#define ftell64 _ast_ftell64\n");
+ printf("#define ftello _ast_ftello\n");
+ printf("#define ftello64 _ast_ftello64\n");
+ printf("#define fwrite _ast_fwrite\n");
+ printf("#define gets _ast_gets\n");
+ printf("#define getw _ast_getw\n");
+ printf("#define pclose _ast_pclose\n");
+ printf("#define popen _ast_popen\n");
+ printf("#define printf _ast_printf\n");
+ printf("#define puts _ast_puts\n");
+ printf("#define putw _ast_putw\n");
+ printf("#define rewind _ast_rewind\n");
+ printf("#define scanf _ast_scanf\n");
+ printf("#define setbuf _ast_setbuf\n");
+ printf("#undef setbuffer\n");
+ printf("#define setbuffer _ast_setbuffer\n");
+ printf("#define setlinebuf _ast_setlinebuf\n");
+ printf("#define setvbuf _ast_setvbuf\n");
+ printf("#define snprintf _ast_snprintf\n");
+ printf("#define sprintf _ast_sprintf\n");
+ printf("#define sscanf _ast_sscanf\n");
+ printf("#define tmpfile _ast_tmpfile\n");
+ printf("#define ungetc _ast_ungetc\n");
+ printf("#define vasprintf _ast_vasprintf\n");
+ printf("#define vfprintf _ast_vfprintf\n");
+ printf("#define vfscanf _ast_vfscanf\n");
+ printf("#define vprintf _ast_vprintf\n");
+ printf("#define vscanf _ast_vscanf\n");
+ printf("#define vsnprintf _ast_vsnprintf\n");
+ printf("#define vsprintf _ast_vsprintf\n");
+ printf("#define vsscanf _ast_vsscanf\n");
+
+ printf("#define fcloseall _ast_fcloseall\n");
+ printf("#define _filbuf _ast__filbuf\n");
+ printf("#define fmemopen _ast_fmemopen\n");
+ printf("#define __getdelim _ast___getdelim\n");
+ printf("#define getdelim _ast_getdelim\n");
+ printf("#define getline _ast_getline\n");
+
+ printf("#define clearerr_unlocked _ast_clearerr_unlocked\n");
+ printf("#define feof_unlocked _ast_feof_unlocked\n");
+ printf("#define ferror_unlocked _ast_ferror_unlocked\n");
+ printf("#define fflush_unlocked _ast_fflush_unlocked\n");
+ printf("#define fgetc_unlocked _ast_fgetc_unlocked\n");
+ printf("#define fgets_unlocked _ast_fgets_unlocked\n");
+ printf("#define fileno_unlocked _ast_fileno_unlocked\n");
+ printf("#define fputc_unlocked _ast_fputc_unlocked\n");
+ printf("#define fputs_unlocked _ast_fputs_unlocked\n");
+ printf("#define fread_unlocked _ast_fread_unlocked\n");
+ printf("#define fwrite_unlocked _ast_fwrite_unlocked\n");
+ printf("#define getc_unlocked _ast_getc_unlocked\n");
+ printf("#define getchar_unlocked _ast_getchar_unlocked\n");
+ printf("#define putc_unlocked _ast_putc_unlocked\n");
+ printf("#define putchar_unlocked _ast_putchar_unlocked\n");
+
+ printf("#define flockfile _ast_flockfile\n");
+ printf("#define ftrylockfile _ast_ftrylockfile\n");
+ printf("#define funlockfile _ast_funlockfile\n");
+
+ printf("\n");
+ #endif
+ return 0;
+ }
+}end
+macro{
+ <<"#if defined(__STDPP__directive) && defined(__STDPP__initial)">>
+ <<"__STDPP__directive pragma pp:initial">>
+ <<"#endif">>
+ <<"#ifndef P_tmpdir">>
+ #ifndef P_tmpdir
+ #define P_tmpdir "/usr/tmp/"
+ #endif
+ <<"#define P_tmpdir">> P_tmpdir <<"/*NOCATLITERAL*/">>
+ <<"#endif">>
+ <<"#ifndef L_ctermid">>
+ #ifndef L_ctermid
+ #define L_ctermid 9
+ #endif
+ <<"#define L_ctermid">> L_ctermid
+ <<"#endif">>
+ <<"#ifndef L_tmpnam">>
+ #ifndef L_tmpnam
+ #define L_tmpnam (sizeof(P_tmpdir)+15)
+ #endif
+ <<"#define L_tmpnam">> L_tmpnam
+ <<"#endif">>
+ <<"#if defined(__STDPP__directive) && defined(__STDPP__initial)">>
+ <<"__STDPP__directive pragma pp:noinitial">>
+ <<"#endif">>
+}end
+cat{
+ #if defined(__cplusplus) && defined(__THROW)
+ extern char* ctermid(char*) __THROW;
+ #else
+ extern char* ctermid(char*);
+ #endif
+ extern char* tmpnam(char*);
+ extern char* tempnam(const char*, const char*);
+ extern void perror(const char*);
+ #ifndef _AST_STD_H
+ #ifndef remove
+ extern int remove(const char*);
+ #endif
+ #ifndef rename
+ extern int rename(const char*, const char*);
+ #endif
+ #endif
+
+ #undef extern
+
+ #if _BLD_ast && defined(__EXPORT__)
+ #define extern __EXPORT__
+ #endif
+
+ extern int _doprnt(const char*, va_list, FILE*);
+ extern int _doscan(FILE*, const char*, va_list);
+ extern int asprintf(char**, const char*, ...);
+ extern int clearerr(FILE*);
+ extern int fclose(FILE*);
+ extern FILE* fdopen(int, const char*);
+ extern int feof(FILE*);
+ extern int ferror(FILE*);
+ extern int fflush(FILE*);
+ extern int fgetc(FILE*);
+ extern int fgetpos(FILE*, fpos_t*);
+ extern char* fgets(char*, int, FILE*);
+ extern int fileno(FILE*);
+ extern FILE* fopen(const char*, const char*);
+ extern int fprintf(FILE*, const char*, ...);
+ extern int fpurge(FILE*);
+ extern int fputc(int, FILE*);
+ extern int fputs(const char*, FILE*);
+ extern size_t fread(void*, size_t, size_t, FILE*);
+ extern FILE* freopen(const char*, const char*, FILE*);
+ extern int fscanf(FILE*, const char*, ...);
+ extern int fseek(FILE*, long, int);
+ extern int fseeko(FILE*, off_t, int);
+ extern int fsetpos(FILE*, const fpos_t*);
+ extern long ftell(FILE*);
+ extern off_t ftello(FILE*);
+ extern size_t fwrite(const void*, size_t, size_t, FILE*);
+ extern int getc(FILE*);
+ extern int getchar(void);
+ extern char* gets(char*);
+ extern int getw(FILE*);
+ extern int pclose(FILE*);
+ extern FILE* popen(const char*, const char*);
+ extern int printf(const char*, ...);
+ extern int putc(int, FILE*);
+ extern int putchar(int);
+ extern int puts(const char*);
+ extern int putw(int, FILE*);
+ extern void rewind(FILE*);
+ extern int scanf(const char*, ...);
+ extern void setbuf(FILE*, char*);
+ extern int setbuffer(FILE*, char*, int);
+ extern int setlinebuf(FILE*);
+ extern int setvbuf(FILE*, char*, int, size_t);
+ extern int snprintf(char*, int, const char*, ...);
+ extern int sprintf(char*, const char*, ...);
+ extern int sscanf(const char*, const char*, ...);
+ extern FILE* tmpfile(void);
+ extern int ungetc(int, FILE*);
+ extern int vasprintf(char**, const char*, va_list);
+ extern int vfprintf(FILE*, const char*, va_list);
+ extern int vfscanf(FILE*, const char*, va_list);
+ extern int vprintf(const char*, va_list);
+ extern int vscanf(const char*, va_list);
+ extern int vsnprintf(char*, int, const char*, va_list);
+ extern int vsprintf(char*, const char*, va_list);
+ extern int vsscanf(const char*, const char*, va_list);
+
+ #if _typ_int64_t
+
+ extern int fgetpos64(FILE*, fpos64_t*);
+ extern int fsetpos64(FILE*, const fpos64_t*);
+ extern int fseek64(FILE*, int64_t, int);
+ extern int fseeko64(FILE*, int64_t, int);
+ extern int64_t ftell64(FILE*);
+ extern int64_t ftello64(FILE*);
+
+ #ifdef _LARGEFILE64_SOURCE
+
+ #undef fpos_t
+ #undef off_t
+ #undef fgetpos
+ #undef fsetpos
+ #undef fseek
+ #undef fseeko
+ #undef ftell
+ #undef ftello
+
+ #define fpos_t fpos64_t
+ #if _typ_off64_t
+ #define off_t off64_t
+ #else
+ #define off_t int64_t
+ #endif
+
+ #define fgetpos fgetpos64
+ #define fsetpos fsetpos64
+ #define fseek fseek64
+ #define fseeko fseeko64
+ #define ftell ftell64
+ #define ftello ftello64
+
+ #endif
+
+ #endif
+
+ extern void clearerr_unlocked(FILE*);
+ extern int feof_unlocked(FILE*);
+ extern int ferror_unlocked(FILE*);
+ extern int fflush_unlocked(FILE*);
+ extern int fgetc_unlocked(FILE*);
+ extern char* fgets_unlocked(char*, int, FILE*);
+ extern int fileno_unlocked(FILE*);
+ extern int fputc_unlocked(int, FILE*);
+ extern int fputs_unlocked(char*, FILE*);
+ extern size_t fread_unlocked(void*, size_t, size_t, FILE*);
+ extern size_t fwrite_unlocked(void*, size_t, size_t, FILE*);
+ extern int getc_unlocked(FILE*);
+ extern int getchar_unlocked(void);
+ extern int putc_unlocked(int, FILE*);
+ extern int putchar_unlocked(int);
+
+ #ifdef _USE_GNU
+
+ extern int fcloseall(void);
+ extern FILE* fmemopen(void*, size_t, const char*);
+ extern ssize_t __getdelim(char**, size_t*, int, FILE*);
+ extern ssize_t getdelim(char**, size_t*, int, FILE*);
+ extern ssize_t getline(char**, size_t*, FILE*);
+
+ #endif
+
+ #undef extern
+
+ #if _BLD_DLL && _DLL_INDIRECT_DATA
+
+ #define stdin ((FILE*)_ast_dll->_ast_stdin)
+ #define stdout ((FILE*)_ast_dll->_ast_stdout)
+ #define stderr ((FILE*)_ast_dll->_ast_stderr)
+
+ #else
+
+ #define stdin (&_Sfstdin)
+ #define stdout (&_Sfstdout)
+ #define stderr (&_Sfstderr)
+
+ #endif
+
+ #if defined(_AST_H) || defined(_SFIO_H)
+
+ #define feof(f) sfeof(f)
+ #define ferror(f) sferror(f)
+ #define fileno(f) sffileno(f)
+ #define fputc(c,f) sfputc(f,c)
+ #define getc(f) sfgetc(f)
+ #define getchar() sfgetc(sfstdin)
+ #define putc(c,f) sfputc(f,c)
+ #define putchar(c) sfputc(sfstdout,c)
+
+ #else
+
+ #if !_UWIN
+ #if _BLD_ast && defined(__EXPORT__)
+ #define extern extern __EXPORT__
+ #endif
+ #if !_BLD_ast && defined(__IMPORT__)
+ #define extern extern __IMPORT__
+ #endif
+ #endif
+
+ extern FILE _Sfstdin;
+ extern FILE _Sfstdout;
+ extern FILE _Sfstderr;
+
+ #undef extern
+
+ #define feof(f) (_sf_(f)->_flags&_SF_EOF)
+ #define ferror(f) (_sf_(f)->_flags&_SF_ERROR)
+ #define fileno(f) (_sf_(f)->_file)
+ #define fputc(c,f) (_sf_(f)->_next>=_sf_(f)->_endw?_sfflsbuf(_sf_(f),(int)((unsigned char)(c))):(int)(*_sf_(f)->_next++=(unsigned char)(c)))
+ #define getc(f) (_sf_(f)->_next>=_sf_(f)->_endr?_sffilbuf(_sf_(f),0):(int)(*_sf_(f)->_next++))
+ #define getchar() getc(stdin)
+ #define putc(c,f) fputc(c,f)
+ #define putchar(c) fputc(c,stdout)
+
+ #if _BLD_ast && defined(__EXPORT__)
+ #define extern __EXPORT__
+ #endif
+
+ extern int _sffilbuf(FILE*, int);
+ extern int _sfflsbuf(FILE*, int);
+
+ #undef extern
+
+ #endif
+}end
diff --git a/src/lib/libast/features/sys b/src/lib/libast/features/sys
new file mode 100644
index 0000000..87ad1e5
--- /dev/null
+++ b/src/lib/libast/features/sys
@@ -0,0 +1,272 @@
+set prototyped
+iff AST_SYS
+ref -D_def_map_ast
+
+print #if __mips == 2 && !defined(_NO_LARGEFILE64_SOURCE)
+print #define _NO_LARGEFILE64_SOURCE 1
+print #endif
+print #if !defined(_NO_LARGEFILE64_SOURCE) && _typ_off64_t && _lib_lseek64 && _lib_stat64
+print #if !defined(_LARGEFILE64_SOURCE)
+print #define _LARGEFILE64_SOURCE 1
+print #endif
+print #if !defined(_LARGEFILE_SOURCE)
+print #define _LARGEFILE_SOURCE 1
+print #endif
+print #else
+print #undef _LARGEFILE64_SOURCE
+print #undef _LARGEFILE_SOURCE
+print #undef _typ_off64_t
+print #undef _typ_struct_dirent64
+print #undef _lib_creat64
+print #undef _lib_fstat64
+print #undef _lib_fstatvfs64
+print #undef _lib_ftruncate64
+print #undef _lib_lseek64
+print #undef _lib_lstat64
+print #undef _lib_mmap64
+print #undef _lib_open64
+print #undef _lib_readdir64
+print #undef _lib_stat64
+print #undef _lib_statvfs64
+print #undef _lib_truncate64
+print #endif
+
+print #if defined(__STDC__) && !defined(__USE_FIXED_PROTOTYPES__)
+print #define __USE_FIXED_PROTOTYPES__ 1 /* kick gcc out of the past */
+print #endif
+
+header stdlib.h
+header stddef.h
+header sys/types.h
+header stdint.h
+header inttypes.h
+header string.h
+header unistd.h
+header limits.h
+header fcntl.h
+header locale.h
+
+typ dev_t,nlink_t fail{
+ echo "#ifndef $m"
+ echo "#define $m 1"
+ echo "typedef short $v;"
+ echo "#endif"
+}end
+typ gid_t,mode_t,uid_t fail{
+ echo "#ifndef $m"
+ echo "#define $m 1"
+ echo "typedef unsigned short $v;"
+ echo "#endif"
+}end
+typ wchar_t stdio.h wchar.h fail{
+ echo "#ifndef $m"
+ echo "#define $m 1"
+ echo "typedef unsigned short $v;"
+ echo "#endif"
+}end
+typ pid_t,ssize_t fail{
+ echo "#ifndef $m"
+ echo "#define $m 1"
+ echo "typedef int $v;"
+ echo "#endif"
+}end
+typ wint_t stdio.h wchar.h fail{
+ echo "#ifndef $m"
+ echo "#define $m 1"
+ echo "typedef int $v;"
+ echo "#endif"
+}end
+typ socklen_t sys/socket.h fail{
+ echo "#ifndef $m"
+ echo "#define $m 1"
+ echo "typedef int $v;"
+ echo "#endif"
+}end
+typ size_t fail{
+ echo "#ifndef $m"
+ echo "#define $m 1"
+ echo "typedef unsigned int $v;"
+ echo "#endif"
+}end
+typ clock_t,ino_t,off_t,ptrdiff_t fail{
+ echo "#ifndef $m"
+ echo "#define $m 1"
+ echo "typedef long $v;"
+ echo "#endif"
+}end
+typ time_t fail{
+ echo "#ifndef $m"
+ echo "#define $m 1"
+ echo "typedef unsigned long $v;"
+ echo "#endif"
+}end
+typ div_t fail{
+ echo "#ifndef $m"
+ echo "#define $m 1"
+ echo "typedef struct { int quot; int rem; } $v;"
+ echo "#endif"
+}end
+typ ldiv_t fail{
+ echo "#ifndef $m"
+ echo "#define $m 1"
+ echo "typedef struct { long quot; long rem; } $v;"
+ echo "#endif"
+}end
+tst typ_signed_size_t output{
+ #include <sys/types.h>
+ int
+ main()
+ {
+ unsigned long u = ~0;
+ size_t s = ~0;
+ if (s >= 0)
+ return 1;
+ printf("#if !defined(__cplusplus) && !defined(c_plusplus) && !defined(_typ_signed_size_t)\n/* what dipsticks made size_t signed? sun. */\ntypedef unsigned %s _ast_size_t;\n#undef\tsize_t\n#define size_t\t_ast_size_t\n#endif\n", u == (unsigned long)s ? "long" : "int");
+ return 0;
+ }
+}end
+
+define offsetof (type,member) ((size_t)&(((type*)0)->member))
+define EXIT_FAILURE 1
+define EXIT_SUCCESS 0
+define MB_CUR_MAX 1
+define RAND_MAX 32767
+
+define STDIN_FILENO 0
+define STDOUT_FILENO 1
+define STDERR_FILENO 2
+
+define NULL 0
+
+define SEEK_SET 0
+define SEEK_CUR 1
+define SEEK_END 2
+
+define F_OK 0
+define X_OK 1
+define W_OK 2
+define R_OK 4
+
+print #if _BLD_ast && defined(__EXPORT__)
+print #define extern __EXPORT__
+print #endif
+
+extern _exit void (int)
+extern abort void (void)
+extern abs int (int)
+extern access int (const char*, int)
+extern alarm unsigned (unsigned)
+extern atexit int (void(*)(void))
+extern atof double (const char*)
+extern atoi int (const char*)
+extern atol long (const char*)
+extern bsearch void* (const void*, const void*, size_t, size_t, int(*)(const void*, const void*))
+extern calloc void* (size_t, size_t)
+extern cfree void (void*)
+extern chdir int (const char*)
+extern chown int (const char*, uid_t, gid_t)
+extern close int (int)
+extern confstr size_t (int, char*, size_t)
+extern div div_t (int, int)
+extern dup int (int)
+extern dup2 int (int, int)
+extern eaccess int (const char*, int)
+extern execl int (const char*, const char*, ...)
+extern execle int (const char*, const char*, ...)
+extern execlp int (const char*, const char*, ...)
+extern execv int (const char*, char* const[])
+extern execve int (const char*, char* const[], char* const[])
+extern execve int (const char*, char* const[], char* const[])
+extern execvp int (const char*, char* const[])
+extern execvpe int (const char*, char* const[], char* const[])
+extern exit void (int)
+extern fork pid_t (void)
+extern fpathconf long (int, int)
+extern free void (void*)
+extern fsync int (int)
+extern ftruncate int (int, off_t)
+extern getcwd char* (char*, size_t)
+extern getegid gid_t (void)
+extern getenv char* (const char*)
+extern geteuid uid_t (void)
+extern getgid gid_t (void)
+extern getgroups int (int, gid_t[])
+extern getlogin char* (void)
+extern getpgrp pid_t (void)
+extern getpid pid_t (void)
+extern getppid pid_t (void)
+extern gettxt char* (const char*, const char*)
+extern getuid uid_t (void)
+extern isatty int (int)
+extern labs long (long)
+extern ldiv ldiv_t (long, long)
+extern link int (const char*, const char*)
+extern lseek off_t (int, off_t, int)
+extern malloc void* (size_t)
+extern mblen int (const char*, size_t)
+extern mbstowcs size_t (wchar_t*, const char*, size_t)
+extern mbtowc int (wchar_t*, const char*, size_t)
+extern memalign void* (size_t, size_t)
+extern memccpy void* (void*, const void*, int, size_t)
+extern memchr void* (const void*, int, size_t)
+extern memcmp int (const void*, const void*, size_t)
+extern memcpy void* (void*, const void*, size_t)
+extern memmove void* (void*, const void*, size_t)
+extern memset void* (void*, int, size_t)
+extern pathconf long (const char*, int)
+extern pause int (void)
+extern pipe int (int[])
+extern pvalloc void* (size_t)
+extern qsort void (void*, size_t, size_t, int(*)(const void*, const void*))
+extern rand int (void)
+extern read ssize_t (int, void*, size_t)
+extern realloc void* (void*, size_t)
+extern realpath char* (const char*, char*)
+extern resolvepath char* (const char*, char*, size_t)
+extern rmdir int (const char*)
+extern setgid int (gid_t)
+extern setpgid int (pid_t, pid_t)
+extern setsid pid_t (void)
+extern setuid int (uid_t)
+extern sleep unsigned (unsigned int)
+extern spawnveg pid_t (const char*, char* const[], char* const[], pid_t)
+extern srand void (unsigned int)
+extern strcasecmp int (const char*, const char*)
+extern strcat char* (char*, const char*)
+extern strchr char* (const char*, int)
+extern strcmp int (const char*, const char*)
+extern strcoll int (const char*, const char*)
+extern strcpy char* (char*, const char*)
+extern strcspn size_t (const char*, const char*)
+extern strdup char* (const char*)
+extern strlcat size_t (char*, const char*, size_t)
+extern strlcpy size_t (char*, const char*, size_t)
+extern strlen size_t (const char*)
+extern strncasecmp int (const char*, const char*, size_t)
+extern strncat char* (char*, const char*, size_t)
+extern strncmp int (const char*, const char*, size_t)
+extern strncpy char* (char*, const char*, size_t)
+extern strpbrk char* (const char*, const char*)
+extern strrchr char* (const char*, int)
+extern strspn size_t (const char*, const char*)
+extern strstr char* (const char*, const char*)
+extern strtok char* (char*, const char*)
+extern strxfrm size_t (char*, const char*, size_t)
+extern swab void (const void*, void*, ssize_t)
+extern sysconf long (int)
+extern system int (const char*)
+extern tcgetpgrp pid_t (int)
+extern tcsetpgrp int (int, pid_t)
+extern truncate int (const char*, off_t)
+extern ttyname char* (int)
+extern unlink int (const char*)
+extern valloc void* (size_t)
+extern wcstombs size_t (char*, const wchar_t*, size_t)
+extern wctomb int (char*, wchar_t)
+extern write ssize_t (int, const void*, size_t)
+
+print #undef extern
+
+# <stdarg.h> is handled by proto so this must be after the last test
+
+print #include <stdarg.h>
diff --git a/src/lib/libast/features/syscall b/src/lib/libast/features/syscall
new file mode 100644
index 0000000..9788b9b
--- /dev/null
+++ b/src/lib/libast/features/syscall
@@ -0,0 +1,18 @@
+lib sysgetcwd note{ syscall(SYS_getcwd,buf,len) implemented }end link{
+ #include <sys/syscall.h>
+ int main()
+ {
+ char buf[256];
+ return syscall(SYS_getcwd, buf, sizeof(buf)) < 0;
+ }
+}end
+
+if ( _lib_sysgetcwd ) {
+ #include <sys/syscall.h>
+}
+endif
+
+if ( _lib_sysgetcwd ) {
+ #define SYSGETCWD(a,b) syscall(SYS_getcwd,a,b)
+}
+endif
diff --git a/src/lib/libast/features/time b/src/lib/libast/features/time
new file mode 100644
index 0000000..6c15113
--- /dev/null
+++ b/src/lib/libast/features/time
@@ -0,0 +1,46 @@
+set prototyped
+lib nanosleep,usleep,_strftime
+typ clock_t = uint32_t
+typ time_t = uint32_t
+
+if sys time {
+ #include <sys/time.h>
+}
+endif
+
+if ! mem tm.tm_sec sys/time.h
+ if hdr time {
+ #include <time.h>
+ }
+ endif
+endif
+
+if sys times {
+ #include <sys/times.h>
+}
+else {
+ struct tms
+ {
+ clock_t tms_utime;
+ clock_t tms_stime;
+ clock_t tms_cutime;
+ clock_t tms_cstime;
+ };
+ extern clock_t times(struct tms*);
+}
+endif
+
+if ! mem timeval.tv_sec sys/time.h {
+ struct timeval
+ {
+ time_t tv_sec;
+ time_t tv_usec;
+ };
+}
+endif
+
+cat{
+#if !defined(CLOCKS_PER_SEC) && defined(CLK_TCK)
+#define CLOCKS_PER_SEC CLK_TCK
+#endif
+}end
diff --git a/src/lib/libast/features/tmlib b/src/lib/libast/features/tmlib
new file mode 100644
index 0000000..221079c
--- /dev/null
+++ b/src/lib/libast/features/tmlib
@@ -0,0 +1,45 @@
+set prototyped
+
+_cc_export_dynamic = note{ probe CC.EXPORT.DYNAMIC supported }end run{
+ case `{ probe -l C make cc | grep '^CC.EXPORT.DYNAMIC = .'; } 2>/dev/null` in
+ '') exit 1 ;;
+ esac
+}end
+
+tst tzset_environ note{ tzset() bypasses user getenv() }end execute{
+ #if _UWIN || !_cc_export_dynamic
+ int main()
+ {
+ return 0;
+ }
+ #else
+ #include <time.h>
+ extern char** environ;
+ extern char* tzname[2];
+ #if _STD_
+ extern char* getenv(char* s)
+ #else
+ extern char* getenv(s)
+ char* s;
+ #endif
+ {
+ return "foo0bar";
+ }
+ int main()
+ {
+ tzset();
+ return tzname[0] && !strcmp(tzname[0], "foo") &&
+ tzname[1] && !strcmp(tzname[1], "bar");
+ }
+ #endif
+}end
+
+if ( _tzset_environ ) {
+ #define tmlocaltime(p) _tm_localtime(p)
+
+ extern struct tm* _tm_localtime(const time_t*);
+}
+else {
+ #define tmlocaltime(p) localtime(p)
+}
+endif
diff --git a/src/lib/libast/features/tmx b/src/lib/libast/features/tmx
new file mode 100644
index 0000000..ebf5c0f
--- /dev/null
+++ b/src/lib/libast/features/tmx
@@ -0,0 +1,106 @@
+set prototyped
+set explicit
+iff TMX
+
+cat{
+ /*
+ * AT&T Research
+ *
+ * high resolution Time_t support
+ */
+
+ #include <tm.h>
+ #include <tv.h>
+}end
+
+inc FEATURE/common
+
+if ( _ast_int8_t ) {
+ #define TMX_MAXDATE "2554-07-21+23:34:33.709551614 UTC"
+ #define TMX_MAXYEAR 2554
+ #define TMX_MAXSEC ((Time_t)18446744073)
+ #define TMX_MAXNSEC 709551614
+ #define TMX_RESOLUTION 1000000000
+
+ typedef uint64_t Time_t;
+ typedef uint64_t Tmxsec_t;
+ typedef uint32_t Tmxnsec_t;
+
+ #define tmxsec(t) ((Tmxsec_t)((t)/1000000000))
+ #define tmxnsec(t) ((Tmxnsec_t)((t)%1000000000))
+ #define tmxsns(s,n) (((((Time_t)(s))*1000000000))+((Time_t)(n)))
+}
+elif ( _ast_flt8_t ) {
+ #define TMX_FLOAT 1
+ #define TMX_MAXDATE "2106-02-07+06:28:15.999 UTC"
+ #define TMX_MAXYEAR 2106
+ #define TMX_MAXSEC 0xffffffffL
+ #define TMX_MAXNSEC 999000000L
+ #define TMX_RESOLUTION 1000
+
+ typedef _ast_flt8_t Time_t;
+ typedef uint32_t Tmxsec_t;
+ typedef uint32_t Tmxnsec_t;
+
+ #define tmxsec(t) ((Tmxsec_t)(t))
+ #define tmxnsec(t) (((Tmxnsec_t)(((t)-((uint32_t)(t))+0.0000005)*1000L))*1000000L)
+ #define tmxsns(s,n) (((Time_t)(s))+((((uint32_t)(n))/1000L)/1e6))
+}
+else {
+ #define TMX_MAXDATE "2106-02-07+06:28:14 UTC"
+ #define TMX_MAXYEAR 2106
+ #define TMX_MAXSEC 0xfffffffeL
+ #define TMX_MAXNSEC 0L
+ #define TMX_RESOLUTION 1
+
+ typedef uint32_t Time_t;
+ typedef uint32_t Tmxsec_t;
+ typedef uint32_t Tmxnsec_t;
+
+ #define tmxsec(t) ((Tmxsec_t)(t))
+ #define tmxnsec(t) (0)
+ #define tmxsns(s,n) ((Time_t)(s))
+}
+endif
+
+cat{
+ #define TMX_NOTIME ((Time_t)(-1))
+ #define TMX_NOW tmxgettime()
+ #define TMX_MAXTIME tmxsns(TMX_MAXSEC,TMX_MAXNSEC)
+
+ #define tmx2tv(t,v) ((v)->tv_nsec=tmxnsec(t),(v)->tv_sec=tmxsec(t))
+ #define tv2tmx(v) tmxsns((v)->tv_sec,(v)->tv_nsec)
+
+ #define tmxclock(p) tmxsns(((p)?*(p):time(NiL)),0)
+
+ #define tmxgetatime(s) tmxsns((s)->st_atime,ST_ATIME_NSEC_GET(s))
+ #define tmxgetctime(s) tmxsns((s)->st_ctime,ST_CTIME_NSEC_GET(s))
+ #define tmxgetmtime(s) tmxsns((s)->st_mtime,ST_MTIME_NSEC_GET(s))
+
+ #define tmxsetatime(s,t) ((s)->st_atime=tmxsec(t),ST_ATIME_NSEC_SET(s,tmxnsec(t)))
+ #define tmxsetctime(s,t) ((s)->st_ctime=tmxsec(t),ST_CTIME_NSEC_SET(s,tmxnsec(t)))
+ #define tmxsetmtime(s,t) ((s)->st_mtime=tmxsec(t),ST_MTIME_NSEC_SET(s,tmxnsec(t)))
+
+ #if _BLD_ast && defined(__EXPORT__)
+ #define extern __EXPORT__
+ #endif
+
+ extern Time_t tmxdate(const char*, char**, Time_t);
+ extern Time_t tmxduration(const char*, char**);
+ extern char* tmxfmt(char*, size_t, const char*, Time_t);
+ extern Time_t tmxleap(Time_t);
+ extern Tm_t* tmxmake(Time_t);
+ extern Time_t tmxscan(const char*, char**, const char*, char**, Time_t, long);
+ extern int tmxsleep(Time_t);
+ extern Time_t tmxtime(Tm_t*, int);
+ extern Tm_t* tmxtm(Tm_t*, Time_t, Tm_zone_t*);
+
+ extern Time_t tmxgettime(void);
+ extern int tmxsettime(Time_t);
+
+ extern int tmxtouch(const char*, Time_t, Time_t, Time_t, int);
+
+ extern char* fmttmx(const char*, Time_t);
+
+ #undef extern
+}end
diff --git a/src/lib/libast/features/tty b/src/lib/libast/features/tty
new file mode 100644
index 0000000..a75edeb
--- /dev/null
+++ b/src/lib/libast/features/tty
@@ -0,0 +1,127 @@
+hdr termios,termio,sgtty
+sys termios,termio,ioctl,bsdtty,nttyio,ttyio
+lib tcgetattr,tcgetpgrp termios.h
+mac _POSIX_VDISABLE termios.h
+mem termios.c_line termios.h
+
+cat{
+
+#ifdef _hdr_termios
+# if _mac__POSIX_VDISABLE
+# undef _POSIX_VDISABLE
+# endif
+# include <termios.h>
+#else
+# if defined(_sys_termios) && defined(_lib_tcgetattr)
+# include <sys/termios.h>
+# define _hdr_termios 1
+# else
+# undef _sys_termios
+# endif /* _sys_termios */
+#endif /* _hdr_termios */
+
+#ifdef _hdr_termios
+# undef _hdr_sgtty
+# undef tcgetattr
+# undef tcsetattr
+# undef tcgetpgrp
+# undef tcsetpgrp
+# undef cfgetospeed
+# ifndef TCSANOW
+# define TCSANOW TCSETS
+# define TCSADRAIN TCSETSW
+# define TCSAFLUSH TCSETSF
+# endif /* TCSANOW */
+ /* The following corrects bugs in some implementations */
+# if defined(TCSADFLUSH) && !defined(TCSAFLUSH)
+# define TCSAFLUSH TCSADFLUSH
+# endif /* TCSADFLUSH */
+# ifndef _lib_tcgetattr
+# undef tcgetattr
+# define tcgetattr(fd,tty) ioctl(fd, TCGETS, tty)
+# undef tcsetattr
+# define tcsetattr(fd,action,tty) ioctl(fd, action, tty)
+# undef cfgetospeed
+# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
+# endif /* _lib_tcgetattr */
+# undef TIOCGETC
+#else
+# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
+# define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
+# define cfsetispeed(tp,val) ((tp)->c_cflag &=~ CBAUD,(tp)->c_cflag|=(val))
+# define cfsetospeed(tp,val) ((tp)->c_cflag &=~ CBAUD,(tp)->c_cflag|=(val))
+# ifdef _hdr_termio
+# include <termio.h>
+# else
+# ifdef _sys_termio
+# include <sys/termio.h>
+# define _hdr_termio 1
+# endif /* _sys_termio */
+# endif /* _hdr_termio */
+# ifdef _hdr_termio
+# define termios termio
+# undef TIOCGETC
+# define tcgetattr(fd,tty) ioctl(fd, TCGETA, tty)
+# define tcsetattr(fd,action,tty) ioctl(fd, action, tty)
+
+# ifdef _sys_bsdtty
+# include <sys/bsdtty.h>
+# endif /* _sys_bsdtty */
+# else
+# ifdef _hdr_sgtty
+# include <sgtty.h>
+# ifndef LPENDIN
+# ifdef _sys_nttyio
+# include <sys/nttyio.h>
+# endif /* _sys_nttyio */
+# endif /* LPENDIN */
+# define termios sgttyb
+# ifdef TIOCSETN
+# undef TCSETAW
+# endif /* TIOCSETN */
+# ifdef TIOCGETP
+# define tcgetattr(fd,tty) ioctl(fd, TIOCGETP, tty)
+# define tcsetattr(fd,action,tty) ioctl(fd, action, tty)
+# else
+# define tcgetattr(fd,tty) gtty(fd, tty)
+# define tcsetattr(fd,action,tty) stty(fd, tty)
+# endif /* TIOCGETP */
+# else
+# ifdef _sys_ttyio
+# include <sys/ttyio.h>
+# endif
+# endif /* _hdr_sgtty */
+# endif /* hdr_termio */
+
+# ifndef TCSANOW
+# ifdef TCSETAW
+# define TCSANOW TCSETA
+# define TCSAFLUSH TCSETAF
+# else
+# ifdef TIOCSETN
+# define TCSANOW TIOCSETN
+# define TCSADRAIN TIOCSETN
+# define TCSAFLUSH TIOCSETP
+# endif /* TIOCSETN */
+# endif /* TCSETAW */
+# endif /* TCSANOW */
+#endif /* _hdr_termios */
+
+/* set ECHOCTL if driver can echo control charaters as ^c */
+#ifdef LCTLECH
+# ifndef ECHOCTL
+# define ECHOCTL LCTLECH
+# endif /* !ECHOCTL */
+#endif /* LCTLECH */
+#ifdef LNEW_CTLECH
+# ifndef ECHOCTL
+# define ECHOCTL LNEW_CTLECH
+# endif /* !ECHOCTL */
+#endif /* LNEW_CTLECH */
+#ifdef LNEW_PENDIN
+# ifndef PENDIN
+# define PENDIN LNEW_PENDIN
+# endif /* !PENDIN */
+#endif /* LNEW_PENDIN */
+
+}end
diff --git a/src/lib/libast/features/tv b/src/lib/libast/features/tv
new file mode 100644
index 0000000..ae15682
--- /dev/null
+++ b/src/lib/libast/features/tv
@@ -0,0 +1,81 @@
+set prototyped
+set explicit
+iff TV
+
+cat{
+ /*
+ * AT&T Research
+ *
+ * high resolution Tv_t interface definitions
+ */
+
+ #include <ast.h>
+
+ #define TV_NSEC_IGNORE (1000000000L)
+ #define TV_TOUCH_RETAIN ((Tv_t*)1)
+
+ typedef struct Tv_s
+ {
+ uint32_t tv_sec;
+ uint32_t tv_nsec;
+ } Tv_t;
+}end
+
+if mem stat.st_mtimespec.tv_nsec sys/stat.h {
+ #define ST_ATIME_NSEC_GET(st) ((st)->st_atimespec.tv_nsec)
+ #define ST_CTIME_NSEC_GET(st) ((st)->st_ctimespec.tv_nsec)
+ #define ST_MTIME_NSEC_GET(st) ((st)->st_mtimespec.tv_nsec)
+}
+elif mem stat.st_mtim.st__tim.tv_nsec sys/stat.h {
+ #define ST_ATIME_NSEC_GET(st) ((st)->st_atim.st__tim.tv_nsec)
+ #define ST_CTIME_NSEC_GET(st) ((st)->st_ctim.st__tim.tv_nsec)
+ #define ST_MTIME_NSEC_GET(st) ((st)->st_mtim.st__tim.tv_nsec)
+}
+elif mem stat.st_mtim.tv_nsec sys/stat.h {
+ #define ST_ATIME_NSEC_GET(st) ((st)->st_atim.tv_nsec)
+ #define ST_CTIME_NSEC_GET(st) ((st)->st_ctim.tv_nsec)
+ #define ST_MTIME_NSEC_GET(st) ((st)->st_mtim.tv_nsec)
+}
+elif mem stat.st_mtimensec sys/stat.h {
+ #define ST_ATIME_NSEC_GET(st) ((st)->st_atimensec)
+ #define ST_CTIME_NSEC_GET(st) ((st)->st_ctimensec)
+ #define ST_MTIME_NSEC_GET(st) ((st)->st_mtimensec)
+}
+else pass{ no_stat_nsec=1 }end {
+ #define ST_ATIME_NSEC_GET(st) 0
+ #define ST_CTIME_NSEC_GET(st) 0
+ #define ST_MTIME_NSEC_GET(st) 0
+
+ #define ST_ATIME_NSEC_SET(st,n) 0
+ #define ST_CTIME_NSEC_SET(st,n) 0
+ #define ST_MTIME_NSEC_SET(st,n) 0
+}
+endif
+if ( !no_stat_nsec ) {
+ #define ST_ATIME_NSEC_SET(st,n) (ST_ATIME_NSEC_GET(st)=(n))
+ #define ST_CTIME_NSEC_SET(st,n) (ST_CTIME_NSEC_GET(st)=(n))
+ #define ST_MTIME_NSEC_SET(st,n) (ST_MTIME_NSEC_GET(st)=(n))
+}
+endif
+
+cat{
+ #define tvgetatime(t,s) ((t)->tv_nsec=ST_ATIME_NSEC_GET(s),(t)->tv_sec=(s)->st_atime)
+ #define tvgetmtime(t,s) ((t)->tv_nsec=ST_MTIME_NSEC_GET(s),(t)->tv_sec=(s)->st_mtime)
+ #define tvgetctime(t,s) ((t)->tv_nsec=ST_CTIME_NSEC_GET(s),(t)->tv_sec=(s)->st_ctime)
+
+ #define tvsetatime(t,s) (ST_ATIME_NSEC_SET(s,(t)->tv_nsec),(s)->st_atime=(t)->tv_sec)
+ #define tvsetmtime(t,s) (ST_MTIME_NSEC_SET(s,(t)->tv_nsec),(s)->st_mtime=(t)->tv_sec)
+ #define tvsetctime(t,s) (ST_CTIME_NSEC_SET(s,(t)->tv_nsec),(s)->st_ctime=(t)->tv_sec)
+
+ #if _BLD_ast && defined(__EXPORT__)
+ #define extern __EXPORT__
+ #endif
+
+ extern int tvgettime(Tv_t*);
+ extern int tvsettime(const Tv_t*);
+ extern int tvcmp(const Tv_t*, const Tv_t*);
+ extern int tvtouch(const char*, const Tv_t*, const Tv_t*, const Tv_t*, int);
+ extern int tvsleep(const Tv_t*, Tv_t*);
+
+ extern char* fmttv(const char*, Tv_t*);
+}end
diff --git a/src/lib/libast/features/tvlib b/src/lib/libast/features/tvlib
new file mode 100644
index 0000000..9b2f64f
--- /dev/null
+++ b/src/lib/libast/features/tvlib
@@ -0,0 +1,80 @@
+hdr time
+lib clock_settime,gettimeofday,settimeofday,stime,utimes
+lib nanosleep,usleep
+lib utimensat -D_ATFILE_SOURCE sys/stat.h note{ complete utimensat implementation }end link{
+ #include <fcntl.h>
+ static struct timespec ts[2];
+ int
+ main()
+ {
+ ts[0].tv_nsec = UTIME_NOW;
+ ts[1].tv_nsec = UTIME_OMIT;
+ return utimensat(AT_FDCWD, ".", ts, AT_SYMLINK_NOFOLLOW) != 0;
+ }
+}end
+
+if ! mem timeval.tv_sec sys/time.h {
+ struct timeval
+ {
+ time_t tv_sec;
+ time_t tv_usec;
+ };
+}
+endif
+
+lib clock_gettime execute{
+ #include <time.h>
+ int
+ main()
+ {
+ struct timespec tv;
+ return clock_gettime(CLOCK_REALTIME, &tv) != 0;
+ }
+}end
+
+lib utimets link{
+ #include <time.h>
+ #include <sys/time.h>
+ static struct timespec tv;
+ int
+ main()
+ {
+ return utimets(".", &tv) != 0;
+ }
+}end
+
+tst - -DN=1 - -DN=2 - -DN=3 - -DN=4 output{
+ #include <sys/types.h>
+ #include <sys/time.h>
+ int
+ main()
+ {
+ struct timeval tv;
+#if N == 1
+ struct timezone tz;
+ if (gettimeofday(&tv, (struct timezone*)0) < 0)
+ return 1;
+ printf("#define tmgettimeofday(p) gettimeofday(p,(struct timezone*)0)\n");
+#if _lib_settimeofday
+ printf("#define tmsettimeofday(p) settimeofday(p,(struct timezone*)0)\n");
+#endif
+#endif
+#if N == 2
+ if (gettimeofday(&tv, (void*)0) < 0)
+ return 1;
+ printf("#define tmgettimeofday(p) gettimeofday(p,(void*)0)\n");
+#if _lib_settimeofday
+ printf("#define tmsettimeofday(p) gettimeofday(p,(void*)0)\n");
+#endif
+#endif
+#if N == 3
+ if (gettimeofday(&tv) < 0)
+ return 1;
+ printf("#define tmgettimeofday(p) gettimeofday(p)\n");
+#if _lib_settimeofday
+ printf("#define tmsettimeofday(p) settimeofday(p)\n");
+#endif
+#endif
+ return 0;
+ }
+}end
diff --git a/src/lib/libast/features/uwin b/src/lib/libast/features/uwin
new file mode 100644
index 0000000..b42cea1
--- /dev/null
+++ b/src/lib/libast/features/uwin
@@ -0,0 +1,10 @@
+lib a64l,acosh,asinh,atanh,cbrt,ceil,crypt,erf,exp,expm1,floor
+lib gamma,getpass,lgamma,log,log1p,random,rcmd,rint,srand48
+lib copysign,logb,finite,drem,sqrt,ilogb,remainder,scalb
+lib _copysign,_finite,_scalb,__iob_func,_p__iob,__p__iob
+
+dat _iob
+
+cat{
+ #define stricmp strcasecmp
+}end
diff --git a/src/lib/libast/features/vfork b/src/lib/libast/features/vfork
new file mode 100644
index 0000000..f1a0ea7
--- /dev/null
+++ b/src/lib/libast/features/vfork
@@ -0,0 +1,13 @@
+set prototyped
+hdr vfork
+sys vfork
+
+tst run{
+ if test "$_hdr_vfork" = 1
+ then echo "#include <vfork.h>"
+ elif test "$_sys_vfork" = 1
+ then echo "#include <sys/vfork.h>"
+ else echo '#include <unistd.h>' > $tmp.c
+ $cc -E $tmp.c | grep vfork
+ fi
+}end
diff --git a/src/lib/libast/features/vmalloc b/src/lib/libast/features/vmalloc
new file mode 100644
index 0000000..b3cc2d0
--- /dev/null
+++ b/src/lib/libast/features/vmalloc
@@ -0,0 +1,220 @@
+#
+# This file defines probes for local features that vmalloc requires.
+# Such probes are interpreted by the "iffe" language interpreter.
+# Results are stored in the FEATURE directory. Some of the
+# {lib,hdr,sys,typ} tests may also be done in the AST features/lib;
+# repeating them here allows for single standalone and AST sources.
+#
+
+ref -D_def_map_ast=1
+
+lib atexit,getpagesize,mallinfo,mallopt,memalign,mstats
+lib onexit,pvalloc,strdup,valloc,vmalloc
+lib _malloc,__malloc,__libc_malloc
+hdr alloca,malloc,stat,stdlib,unistd
+mem mallinfo.arena,mstats.bytes_total malloc.h
+sys stat
+typ ssize_t
+
+tst mem_sbrk note{ brk()/sbrk() work as expected }end execute{
+ #include <sys/types.h>
+ #include <unistd.h>
+ #undef uchar
+ #define uchar unsigned char
+ int main()
+ { uchar *brk0, *brk1;
+
+ /* allocate a big chunk */
+ if(!(brk0 = (uchar*)sbrk(0)) || brk0 == (uchar*)(-1))
+ return 1;
+ brk0 += 256*1024;
+ if(brk(brk0) != 0)
+ return 1;
+ if((brk1 = (uchar*)sbrk(0)) != brk0)
+ return 1;
+
+ /* now return half of it */
+ brk1 -= 128*1024;
+ if(brk(brk1) != 0 )
+ return 1;
+ if((brk0 = (uchar*)sbrk(0)) != brk1)
+ return 1;
+
+ return 0;
+ }
+}end
+
+tst map_malloc note{ map malloc to _ast_malloc }end noexecute{
+ #if __CYGWIN__
+ int main() { return 1; }
+ #else
+ static int user = 0;
+ _BEGIN_EXTERNS_
+ #if _lib_strdup
+ extern char* strdup _ARG_((const char*));
+ #define LOCAL() strdup("s")
+ #else
+ extern void* calloc _ARG_((unsigned int, unsigned int));
+ #define LOCAL() calloc(1,1)
+ #endif
+ #if __CYGWIN__
+ #define extern __declspec(dllexport)
+ #endif
+ #define HT double
+ static HT heap[1024 * 4];
+ static HT* hp = &heap[1];
+ static HT* op;
+ #define MALLOC(n) if(user)return&heap[0];op=hp;hp+=(n+sizeof(HT)-1)/sizeof(HT);return(void*)op;
+ #define INTERCEPTED(p) (((char*)(p))==((char*)&heap[0]))
+ #if _STD_
+ extern void free(void* p) { }
+ extern void _free(void* p) { }
+ extern void __free(void* p) { }
+ extern void __libc_free(void* p) { }
+ extern void* malloc(unsigned int n) { MALLOC(n); }
+ extern void* _malloc(unsigned int n) { MALLOC(n); }
+ extern void* __malloc(unsigned int n) { MALLOC(n); }
+ extern void* __libc_malloc(unsigned int n) { MALLOC(n); }
+ #else
+ extern void free(p) char* p; { }
+ extern void _free(p) char* p; { }
+ extern void __free(p) char* p; { }
+ extern void __libc_free(p) char* p; { }
+ extern void* malloc(n) unsigned int n; { MALLOC(n); }
+ extern void* _malloc(n) unsigned int n; { MALLOC(n); }
+ extern void* __malloc(n) unsigned int n; { MALLOC(n); }
+ extern void* __libc_malloc(n) unsigned int n; { MALLOC(n); }
+ #endif
+ _END_EXTERNS_
+ int main() { user = 1; return !INTERCEPTED(LOCAL()); }
+ #endif
+}end
+
+tst map_malloc note{ map malloc to _ast_malloc -- wimp-o mach? }end noexecute{
+ #if _map_malloc
+ int main() { return 0; }
+ #else
+ _BEGIN_EXTERNS_
+ #if _STD_
+ void* calloc(unsigned n, unsigned m) { exit(1); }
+ #else
+ void* calloc(n, m) unsigned n, m; { exit(1); }
+ #endif
+ _END_EXTERNS_
+ int main() { return 0; }
+ #endif
+}end
+
+lib alloca note{ alloca exists }end link{
+ #if _hdr_alloca
+ #include <alloca.h>
+ #endif
+ int
+ main()
+ { alloca(10);
+ }
+}end
+
+tst mal_alloca note{ alloca is based on malloc() }end execute{
+ #if __CYGWIN__
+ int main() { return 1; }
+ #else
+ #if _hdr_alloca
+ #include <alloca.h>
+ #endif
+ #if _STD_
+ void* malloc(unsigned int size)
+ #else
+ void* malloc(size) unsigned int size;
+ #endif
+ { exit(0);
+ return 0;
+ }
+ int main()
+ { alloca(10);
+ return 1;
+ }
+ #endif
+}end
+
+tst stk_down note{ stack grows downward }end execute{
+ static growdown()
+ { static char* addr = 0;
+ char array[4];
+ if(!addr)
+ { addr = &array[0];
+ return growdown();
+ }
+ else if(addr < &array[0])
+ return 0;
+ else return 1;
+ }
+ int main() { return growdown() ? 0 : 1; }
+}end
+
+tst malloc_hook note{ gnu malloc hooks work }end execute{
+ #include <malloc.h>
+
+ static int test_free_hit = 0;
+ static int test_malloc_hit = 0;
+ static int test_memalign_hit = 0;
+ static int test_realloc_hit = 0;
+
+ static void test_free_hook(void* ptr, const void* caller)
+ {
+ test_free_hit++;
+ }
+
+ static void* test_malloc_hook(size_t size, const void* caller)
+ {
+ test_malloc_hit++;
+ return 0;
+ }
+
+ static void* test_memalign_hook(size_t align, size_t size, const void* caller)
+ {
+ test_memalign_hit++;
+ return 0;
+ }
+
+ static void* test_realloc_hook(void* ptr, size_t size, const void* caller)
+ {
+ test_realloc_hit++;
+ return 0;
+ }
+
+ static void test_initialize_hook(void)
+ {
+ __free_hook = test_free_hook;
+ __malloc_hook = test_malloc_hook;
+ __memalign_hook = test_memalign_hook;
+ __realloc_hook = test_realloc_hook;
+ }
+
+ void (*__malloc_initialize_hook)(void) = test_initialize_hook;
+
+ int main()
+ {
+ void* p;
+
+ p = malloc(16);
+ p = realloc(p, 32);
+ free(p);
+ p = memalign(32, 32);
+ return !test_free_hit || !test_malloc_hit || !test_memalign_hit || !test_realloc_hit;
+ }
+}end
+
+cat{
+ #include "FEATURE/mmap"
+ #if _BLD_INSTRUMENT || cray || _UWIN && _BLD_ast
+ #undef _map_malloc
+ #define _std_malloc 1 /* defer to standard malloc */
+ #endif
+ #if _mmap_anon
+ #define _mem_mmap_anon 1
+ #endif
+ #if _mmap_devzero
+ #define _mem_mmap_zero 1
+ #endif
+}end
diff --git a/src/lib/libast/features/wait b/src/lib/libast/features/wait
new file mode 100644
index 0000000..74c8c81
--- /dev/null
+++ b/src/lib/libast/features/wait
@@ -0,0 +1,9 @@
+lib wait,wait2,wait3,wait4,waitpid
+tst ok_wif sys/types.h sys/wait.h note{ posix wait macros ok }end compile{
+ int ifexited = WIFEXITED(0);
+ int exitstatus = WEXITSTATUS(0);
+ int ifsignaled = WIFSIGNALED(0);
+ int termsig = WTERMSIG(0);
+ int ifstopped = WIFSTOPPED(0);
+ int stopsig = WSTOPSIG(0);
+}end
diff --git a/src/lib/libast/features/wchar b/src/lib/libast/features/wchar
new file mode 100644
index 0000000..ac51f0f
--- /dev/null
+++ b/src/lib/libast/features/wchar
@@ -0,0 +1,158 @@
+set prototyped
+iff
+set stdio ast_common.h
+set include .
+
+cat{
+ #ifndef _AST_WCHAR_H
+ #define _AST_WCHAR_H 1
+}end
+
+lib mbstowcs,wctomb,wcrtomb,wcslen,wcstombs,wcwidth stdlib.h stdio.h wchar.h
+lib towlower,towupper stdlib.h stdio.h wchar.h
+typ mbstate_t stdlib.h stdio.h wchar.h
+nxt wchar
+
+cat{
+ #ifndef _SFSTDIO_H
+ #include <ast_common.h>
+ #include <stdio.h>
+ #endif
+}end
+
+if tst note{ <wchar.h> requires native <stdio.h> }end nocompile{
+ /*<NOSTDIO>*/
+ #define _STDIO_INCLUDED 1
+ #define FILE void
+ #include <wchar.h>
+ int tst;
+ }end
+ if tst note{ <stdio.h> defines __va_list for <wchar.h> }end compile{
+ /*<NOSTDIO>*/
+ #define _STDIO_INCLUDED 1
+ #define FILE void
+ #include <stdarg.h>
+ #define __va_list va_list
+ #include <wchar.h>
+ int tst;
+ }end && {
+ #define __va_list va_list
+ }
+ endif
+endif
+
+if hdr - wctype wchar.h
+ if ! npt - iswalpha wchar.h {
+ #include <wctype.h> /* <wchar.h> includes <wctype.h> */
+ }
+ endif
+endif
+
+run{
+cat <<!
+ #if _hdr_wchar && defined(_nxt_wchar)
+ #include ${_nxt_wchar-_nxt_wchar} /* the native wchar.h */
+ #endif
+
+ #ifndef WEOF
+ #define WEOF (-1)
+ #endif
+
+ #undef fgetwc
+ #undef fgetws
+ #undef fputwc
+ #undef fputws
+ #undef getwc
+ #undef getwchar
+ #undef getws
+ #undef putwc
+ #undef putwchar
+ #undef ungetwc
+
+ #define fgetwc _ast_fgetwc
+ #define fgetws _ast_fgetws
+ #define fputwc _ast_fputwc
+ #define fputws _ast_fputws
+ #define fwide _ast_fwide
+ #define fwprintf _ast_fwprintf
+ #define fwscanf _ast_fwscanf
+ #define getwc _ast_getwc
+ #define getwchar _ast_getwchar
+ #define getws _ast_getws
+ #define putwc _ast_putwc
+ #define putwchar _ast_putwchar
+ #define swprintf _ast_swprintf
+ #define swscanf _ast_swscanf
+ #define ungetwc _ast_ungetwc
+ #define vfwprintf _ast_vfwprintf
+ #define vfwscanf _ast_vfwscanf
+ #define vswprintf _ast_vswprintf
+ #define vswscanf _ast_vswscanf
+ #define vwprintf _ast_vwprintf
+ #define vwscanf _ast_vwscanf
+ #define wprintf _ast_wprintf
+ #define wscanf _ast_wscanf
+
+ #if !_typ_mbstate_t
+ #undef _typ_mbstate_t
+ #define _typ_mbstate_t 1
+ typedef char mbstate_t;
+ #endif
+
+ #if _BLD_ast && defined(__EXPORT__)
+ #define extern __EXPORT__
+ #endif
+
+ #if !_lib_mbstowcs
+ extern size_t mbstowcs(wchar_t*, const char*, size_t);
+ #endif
+ #if !_lib_wctomb
+ extern int wctomb(char*, wchar_t);
+ #endif
+ #if !_lib_wcrtomb
+ extern size_t wcrtomb(char*, wchar_t, mbstate_t*);
+ #endif
+ #if !_lib_wcslen
+ extern size_t wcslen(const wchar_t*);
+ #endif
+ #if !_lib_wcstombs
+ extern size_t wcstombs(char*, const wchar_t*, size_t);
+ #endif
+
+ extern int fwprintf(FILE*, const wchar_t*, ...);
+ extern int fwscanf(FILE*, const wchar_t*, ...);
+ extern wint_t fgetwc(FILE*);
+ extern wchar_t* fgetws(wchar_t*, int, FILE*);
+ extern wint_t fputwc(wchar_t, FILE*);
+ extern int fputws(const wchar_t*, FILE*);
+ extern int fwide(FILE*, int);
+ extern wint_t getwc(FILE*);
+ extern wint_t getwchar(void);
+ extern wchar_t* getws(wchar_t*);
+ extern wint_t putwc(wchar_t, FILE*);
+ extern wint_t putwchar(wchar_t);
+ extern int swprintf(wchar_t*, size_t, const wchar_t*, ...);
+ extern int swscanf(const wchar_t*, const wchar_t*, ...);
+ extern wint_t ungetwc(wint_t, FILE*);
+ extern int vfwprintf(FILE*, const wchar_t*, va_list);
+ extern int vfwscanf(FILE*, const wchar_t*, va_list);
+ extern int vwprintf(const wchar_t*, va_list);
+ extern int vwscanf(const wchar_t*, va_list);
+ extern int vswprintf(wchar_t*, size_t, const wchar_t*, va_list);
+ extern int vswscanf(const wchar_t*, const wchar_t*, va_list);
+ extern int wprintf(const wchar_t*, ...);
+ extern int wscanf(const wchar_t*, ...);
+
+ #undef extern
+
+ #else
+
+ /* on some systems <wchar.h> is included multiple times with multiple effects */
+
+ #if _hdr_wchar && defined(_nxt_wchar)
+ #include ${_nxt_wchar-_nxt_wchar} /* the native wchar.h */
+ #endif
+
+ #endif
+!
+}end
diff --git a/src/lib/libast/features/wctype b/src/lib/libast/features/wctype
new file mode 100644
index 0000000..0f59bc1
--- /dev/null
+++ b/src/lib/libast/features/wctype
@@ -0,0 +1,14 @@
+set prototyped
+nxt wctype
+
+run{
+cat <<!
+ #if _hdr_wctype && defined(_nxt_wctype)
+ #include ${_nxt_wctype-_nxt_wctype} /* the native wctype.h */
+ #endif
+
+ #undef iswalpha
+
+ #define iswalpha(w) (ast.mb_alpha?(*ast.mb_alpha)(w):isalpha(w))
+!
+}end
diff --git a/src/lib/libast/hash/hashalloc.c b/src/lib/libast/hash/hashalloc.c
new file mode 100644
index 0000000..8c923f3
--- /dev/null
+++ b/src/lib/libast/hash/hashalloc.c
@@ -0,0 +1,200 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * hash table library
+ */
+
+static const char id_hash[] = "\n@(#)$Id: hash (AT&T Research) 1996-08-11 $\0\n";
+
+#include "hashlib.h"
+
+Hash_info_t hash_info = { 0 };
+
+/*
+ * create a new hash table
+ */
+
+Hash_table_t*
+hashalloc(Hash_table_t* ref, ...)
+{
+ register Hash_table_t* tab;
+ register Hash_table_t* ret = 0;
+ register int internal;
+ int n;
+ va_list ap;
+ va_list va[4];
+ va_list* vp = va;
+ Hash_region_f region = 0;
+ void* handle;
+
+ va_start(ap, ref);
+
+ /*
+ * check for HASH_region which must be first
+ */
+
+ n = va_arg(ap, int);
+ if (!ref && n == HASH_region)
+ {
+ region = va_arg(ap, Hash_region_f);
+ handle = va_arg(ap, void*);
+ n = va_arg(ap, int);
+ if (!(tab = (Hash_table_t*)(*region)(handle, NiL, sizeof(Hash_table_t), 0)))
+ goto out;
+ memset(tab, 0, sizeof(Hash_table_t));
+ }
+ else if (!(tab = newof(0, Hash_table_t, 1, 0)))
+ goto out;
+ tab->bucketsize = (sizeof(Hash_header_t) + sizeof(char*) - 1) / sizeof(char*);
+ if (ref)
+ {
+ tab->flags = ref->flags & ~HASH_RESET;
+ tab->root = ref->root;
+ internal = HASH_INTERNAL;
+ }
+ else
+ {
+ if (region)
+ {
+ if (!(tab->root = (Hash_root_t*)(*region)(handle, NiL, sizeof(Hash_root_t), 0)))
+ goto out;
+ memset(tab->root, 0, sizeof(Hash_root_t));
+ }
+ else if (!(tab->root = newof(0, Hash_root_t, 1, 0)))
+ goto out;
+ if (!(tab->root->local = newof(0, Hash_local_t, 1, 0)))
+ goto out;
+ if (tab->root->local->region = region)
+ tab->root->local->handle = handle;
+ tab->root->meanchain = HASHMEANCHAIN;
+ internal = 0;
+ }
+ tab->size = HASHMINSIZE;
+ for (;;)
+ {
+ switch (n)
+ {
+ case HASH_alloc:
+ if (ref) goto out;
+ tab->root->local->alloc = va_arg(ap, Hash_alloc_f);
+ break;
+ case HASH_bucketsize:
+ n = (va_arg(ap, int) + sizeof(char*) - 1) / sizeof(char*);
+ if (n > UCHAR_MAX) goto out;
+ if (n > tab->bucketsize) tab->bucketsize = n;
+ break;
+ case HASH_clear:
+ tab->flags &= ~(va_arg(ap, int) & ~internal);
+ break;
+ case HASH_compare:
+ if (ref) goto out;
+ tab->root->local->compare = va_arg(ap, Hash_compare_f);
+ break;
+ case HASH_free:
+ if (ref) goto out;
+ tab->root->local->free = va_arg(ap, Hash_free_f);
+ break;
+ case HASH_hash:
+ if (ref) goto out;
+ tab->root->local->hash = va_arg(ap, Hash_hash_f);
+ break;
+ case HASH_meanchain:
+ if (ref) goto out;
+ tab->root->meanchain = va_arg(ap, int);
+ break;
+ case HASH_name:
+ tab->name = va_arg(ap, char*);
+ break;
+ case HASH_namesize:
+ if (ref) goto out;
+ tab->root->namesize = va_arg(ap, int);
+ break;
+ case HASH_region:
+ goto out;
+ case HASH_set:
+ tab->flags |= (va_arg(ap, int) & ~internal);
+ break;
+ case HASH_size:
+ tab->size = va_arg(ap, int);
+ if (tab->size & (tab->size - 1)) tab->flags |= HASH_FIXED;
+ break;
+ case HASH_table:
+ tab->table = va_arg(ap, Hash_bucket_t**);
+ tab->flags |= HASH_STATIC;
+ break;
+ case HASH_va_list:
+ if (vp < &va[elementsof(va)])
+ {
+ va_copy(*vp, ap);
+ vp++;
+ }
+ va_copy(ap, va_listval(va_arg(ap, va_listarg)));
+ break;
+ case 0:
+ if (vp > va)
+ {
+ vp--;
+ va_copy(ap, *vp);
+ break;
+ }
+ if (tab->flags & HASH_SCOPE)
+ {
+ if (!(tab->scope = ref)) goto out;
+ ref->frozen++;
+ }
+ if (!tab->table)
+ {
+ if (region)
+ {
+ if (!(tab->table = (Hash_bucket_t**)(*region)(handle, NiL, sizeof(Hash_bucket_t*) * tab->size, 0)))
+ goto out;
+ memset(tab->table, 0, sizeof(Hash_bucket_t*) * tab->size);
+ }
+ else if (!(tab->table = newof(0, Hash_bucket_t*, tab->size, 0))) goto out;
+ }
+ if (!ref)
+ {
+ tab->root->flags = tab->flags & HASH_INTERNAL;
+ tab->root->next = hash_info.list;
+ hash_info.list = tab->root;
+ }
+ if (!region)
+ {
+ tab->next = tab->root->references;
+ tab->root->references = tab;
+ }
+ ret = tab;
+ goto out;
+ default:
+ goto out;
+ }
+ n = va_arg(ap, int);
+ }
+ out:
+ va_end(ap);
+ if (!ret) hashfree(tab);
+ return(ret);
+}
diff --git a/src/lib/libast/hash/hashdump.c b/src/lib/libast/hash/hashdump.c
new file mode 100644
index 0000000..3c2829a
--- /dev/null
+++ b/src/lib/libast/hash/hashdump.c
@@ -0,0 +1,173 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * hash table library
+ */
+
+#include "hashlib.h"
+
+/*
+ * dump HASH_* flags
+ */
+
+static void
+dumpflags(register int flags)
+{
+ if (flags & HASH_ALLOCATE) sfprintf(sfstderr, "allocate ");
+ if (flags & HASH_BUCKET) sfprintf(sfstderr, "bucket ");
+ if (flags & HASH_FIXED) sfprintf(sfstderr, "fixed ");
+ if (flags & HASH_HASHED) sfprintf(sfstderr, "hashed ");
+ if (flags & HASH_RESIZE) sfprintf(sfstderr, "resize ");
+ if (flags & HASH_STATIC) sfprintf(sfstderr, "static ");
+ if (flags & HASH_VALUE) sfprintf(sfstderr, "value ");
+}
+
+/*
+ * dump hash table bucket info
+ */
+
+static void
+dumpbucket(register Hash_table_t* tab, int flags)
+{
+ register Hash_bucket_t** sp;
+ register Hash_bucket_t* b;
+ Hash_bucket_t** sx;
+ int n;
+ unsigned char* s;
+
+ NoP(flags);
+ sx = tab->table + tab->size;
+ for (sp = tab->table; sp < sx; sp++)
+ {
+ n = 0;
+ for (b = *sp; b; b = b->next)
+ if (!(b->hash & HASH_DELETED) && (!(tab->flags & HASH_VALUE) || b->value))
+ n++;
+ if (n)
+ {
+ sfprintf(sfstderr, "%5d %2d :", sp - tab->table, n);
+ for (b = *sp; b; b = b->next)
+ if (!(b->hash & HASH_DELETED) && (!(tab->flags & HASH_VALUE) || b->value))
+ {
+ if (n = tab->root->namesize)
+ {
+ sfprintf(sfstderr, " 0x");
+ s = (unsigned char*)hashname(b);
+ while (n-- > 0)
+ sfprintf(sfstderr, "%02x", *s++);
+ }
+ else sfprintf(sfstderr, " %s", hashname(b));
+ if (b->hash & HASH_FLAGS)
+ {
+ sfprintf(sfstderr, "|");
+ if (b->hash & HASH_HIDES) sfprintf(sfstderr, "hides|");
+ if (b->hash & HASH_HIDDEN) sfprintf(sfstderr, "hidden|");
+ if (b->hash & HASH_KEEP) sfprintf(sfstderr, "keep|");
+ if (b->hash & HASH_OPAQUED) sfprintf(sfstderr, "opaque|");
+ }
+ if (tab->flags & HASH_VALUE) sfprintf(sfstderr, "=0x%08lx", (long)b->value);
+ }
+ sfprintf(sfstderr, "\n");
+ }
+ }
+ sfprintf(sfstderr, "\n");
+}
+
+/*
+ * dump info on a single table
+ */
+
+static void
+dumptable(register Hash_table_t* tab, register int flags)
+{
+ Hash_table_t* scope;
+ int level;
+
+ sfprintf(sfstderr, " name: %s", tab->name ? tab->name : "*no name*");
+ if (scope = tab->scope)
+ {
+ level = 1;
+ while (scope = scope->scope) level++;
+ sfprintf(sfstderr, " level %d scope on 0x%08lx", level, (unsigned long)tab->scope);
+ }
+ sfprintf(sfstderr, "\n");
+ sfprintf(sfstderr, " address: 0x%08lx\n", (unsigned long)tab);
+ sfprintf(sfstderr, " flags: ");
+ if (tab->frozen) sfprintf(sfstderr, "frozen=%d ", tab->frozen);
+ dumpflags(tab->flags);
+ sfprintf(sfstderr, "\n");
+ sfprintf(sfstderr, " size: %d\n", tab->size);
+ sfprintf(sfstderr, " buckets: %d\n", tab->buckets);
+ sfprintf(sfstderr, " bucketsize: %d\n", tab->bucketsize * sizeof(char*));
+ sfprintf(sfstderr, "\n");
+ if ((flags | tab->flags) & HASH_BUCKET) dumpbucket(tab, flags);
+}
+
+/*
+ * dump hash table root info
+ */
+
+static void
+dumproot(register Hash_root_t* root, register int flags)
+{
+ register Hash_table_t* tab;
+
+ sfprintf(sfstderr, " root\n");
+ sfprintf(sfstderr, " address: 0x%08lx\n", (unsigned long)root);
+ sfprintf(sfstderr, " flags: ");
+ dumpflags(root->flags);
+ if (root->namesize) sfprintf(sfstderr, "namesize=%d ", root->namesize);
+ if (root->local->alloc) sfprintf(sfstderr, "alloc=0x%08lx ", (unsigned long)root->local->alloc);
+ if (root->local->compare) sfprintf(sfstderr, "compare=0x%08lx ", (unsigned long)root->local->compare);
+ if (root->local->free) sfprintf(sfstderr, "free=0x%08lx ", (unsigned long)root->local->free);
+ if (root->local->hash) sfprintf(sfstderr, "hash=0x%08lx ", (unsigned long)root->local->hash);
+ if (root->local->region) sfprintf(sfstderr, "region=0x%08lx handle=0x%08lx ", (unsigned long)root->local->region, (unsigned long)root->local->handle);
+ sfprintf(sfstderr, "\n");
+ sfprintf(sfstderr, " meanchain: %d\n", root->meanchain);
+ sfprintf(sfstderr, " accesses: %d\n", root->accesses);
+ sfprintf(sfstderr, " collisions: %d\n", root->collisions);
+ sfprintf(sfstderr, "\n");
+ for (tab = root->references; tab; tab = tab->next)
+ dumptable(tab, flags);
+}
+
+/*
+ * dump hash table accounting info
+ * if tab is 0 then dump all tables in hash_info.list
+ * flags are HASH_* flags that specifiy optional dump info
+ */
+
+void
+hashdump(register Hash_table_t* tab, int flags)
+{
+ register Hash_root_t* root;
+
+ sfprintf(sfstderr, "\nhash table information:\n\n");
+ if (tab) dumproot(tab->root, flags);
+ else for (root = hash_info.list; root; root = root->next)
+ dumproot(root, flags);
+ sfsync(sfstderr);
+}
diff --git a/src/lib/libast/hash/hashfree.c b/src/lib/libast/hash/hashfree.c
new file mode 100644
index 0000000..b6998a3
--- /dev/null
+++ b/src/lib/libast/hash/hashfree.c
@@ -0,0 +1,144 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * hash table library
+ */
+
+#include "hashlib.h"
+
+/*
+ * free (remove) a hash table
+ * can be called for partially constructed tables
+ * scope covered table pointer is returned
+ * root info freed when last reference freed
+ */
+
+Hash_table_t*
+hashfree(register Hash_table_t* tab)
+{
+ register Hash_bucket_t** sp;
+ register Hash_bucket_t* b;
+ register Hash_bucket_t* p;
+ Hash_bucket_t** sx;
+ Hash_root_t* rp;
+ Hash_table_t* tp;
+ Hash_free_f freevalue;
+ Hash_free_f freebucket;
+ Hash_region_f region;
+ void* handle;
+
+ if (!tab) return(0);
+ if (tab->table)
+ {
+ freebucket = 0;
+ freevalue = 0;
+ if (tab->root->local->free)
+ {
+ if (tab->root->flags & HASH_BUCKET) freebucket = tab->root->local->free;
+ else freevalue = tab->root->local->free;
+ }
+ if (region = tab->root->local->region)
+ handle = tab->root->local->handle;
+ sx = &tab->table[tab->size];
+ sp = &tab->table[0];
+ while (sp < sx)
+ {
+ b = *sp++;
+ while (b)
+ {
+ p = b;
+ b = b->next;
+ if (freebucket) (*freebucket)((char*)p);
+ else if (freevalue && p->value) (*freevalue)(p->value);
+ if (p->hash & HASH_FREENAME)
+ {
+ p->hash &= ~HASH_FREENAME;
+ if (region) (*region)(handle, p->name, 0, 0);
+ else free(p->name);
+ }
+ if (!(p->hash & HASH_KEEP))
+ {
+ if (region) (*region)(handle, p, 0, 0);
+ else free(p);
+ }
+ else if (p->hash & HASH_HIDES)
+ {
+ p->hash &= ~HASH_HIDES;
+ p->name = ((Hash_bucket_t*)p->name)->name;
+ }
+ }
+ }
+ if ((tab->flags & (HASH_RESIZE|HASH_STATIC)) != HASH_STATIC)
+ {
+ if (region) (*region)(handle, tab->table, 0, 0);
+ else free(tab->table);
+ }
+ }
+ else region = 0;
+ if (tab->root)
+ {
+ if (!region)
+ {
+ /*
+ * remove from the table lists
+ */
+
+ if ((tp = tab->root->references) != tab)
+ {
+ for (; tp; tp = tp->next)
+ if (tp->next == tab)
+ {
+ tp->next = tab->next;
+ break;
+ }
+ }
+ else if (!(tab->root->references = tp->next))
+ {
+ if ((rp = hash_info.list) != tab->root)
+ {
+ for (; rp; rp = rp->next)
+ if (rp->next == tab->root)
+ {
+ rp->next = tab->root->next;
+ break;
+ }
+ }
+ else hash_info.list = rp->next;
+ }
+ }
+ if (!(tab->root->references))
+ {
+ if (tab->root->local)
+ free(tab->root->local);
+ if (region) (*region)(handle, tab->root, 0, 0);
+ else free(tab->root);
+ }
+ }
+ if (tp = tab->scope) tp->frozen--;
+ if (region) (*region)(handle, tab, 0, 0);
+ else free(tab);
+ return(tp);
+}
diff --git a/src/lib/libast/hash/hashlast.c b/src/lib/libast/hash/hashlast.c
new file mode 100644
index 0000000..0083477
--- /dev/null
+++ b/src/lib/libast/hash/hashlast.c
@@ -0,0 +1,43 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/* OBSOLETE 19960229 -- use tab->root->last.{table|bucket} */
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * hash table library
+ */
+
+#include "hashlib.h"
+
+/*
+ * return last lookup bucket for table
+ */
+
+Hash_bucket_t*
+hashlast(Hash_table_t* tab)
+{
+ return(tab->root->last.bucket);
+}
diff --git a/src/lib/libast/hash/hashlib.h b/src/lib/libast/hash/hashlib.h
new file mode 100644
index 0000000..2d225b9
--- /dev/null
+++ b/src/lib/libast/hash/hashlib.h
@@ -0,0 +1,104 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * hash table library private definitions
+ */
+
+#ifndef _HASHLIB_H
+#define _HASHLIB_H
+
+#include <ast.h>
+
+#define hash_info _hash_info_
+
+typedef void* (*Hash_alloc_f)(size_t);
+typedef int (*Hash_compare_f)(const char*, const char*, ...);
+typedef unsigned int (*Hash_hash_f)(const char*, ...);
+typedef void (*Hash_free_f)(void*);
+typedef void* (*Hash_region_f)(void*, void*, size_t, int);
+
+typedef struct /* root local pointers */
+{
+ Hash_hash_f hash; /* name hash routine */
+ Hash_compare_f compare; /* name comparision routine */
+ Hash_alloc_f alloc; /* value allocation routine */
+ Hash_free_f free; /* value free routine */
+ Hash_region_f region; /* region alloc/free routine */
+ void* handle; /* region handle arg */
+} Hash_local_t;
+
+#define _HASH_POSITION_PRIVATE_ \
+ Hash_table_t* tab; /* table pointer */ \
+ int flags; /* scan flags */ \
+ Hash_bucket_t** slot; /* table slot */ \
+ Hash_bucket_t** limit; /* slot limit */
+
+#define _HASH_LAST_PRIVATE_ \
+ const char* name; /* last lookup name */ \
+ unsigned int hash; /* last lookup hash */
+
+#define _HASH_ROOT_PRIVATE_ \
+ int namesize; /* fixed name size: 0 => string */ \
+ int meanchain; /* resize mean chain length */ \
+ Hash_local_t* local; /* root local pointers */ \
+ Hash_root_t* next; /* next in list of all roots */ \
+ Hash_table_t* references; /* referencing table list */
+
+#define _HASH_TABLE_PRIVATE_ \
+ unsigned char frozen; /* table freeze nesting */ \
+ unsigned char bucketsize; /* min bucket size in char*'s */ \
+ Hash_bucket_t** table; /* hash slot table */ \
+ Hash_table_t* next; /* root reference list link */
+
+#include <hash.h>
+
+#define HASHMINSIZE (1<<4) /* min table slots (power of 2) */
+#define HASHMEANCHAIN 2 /* def resize mean chain len */
+
+#define HASHMOD(t,h) (h &= (t->size - 1))
+#define HASHVAL(x) ((x)&~HASH_FLAGS)
+
+#define HASH(r,n,h) if (r->local->hash) h = r->namesize ? (*r->local->hash)(n, r->namesize) : (*r->local->hash)(n);\
+ else\
+ {\
+ register const char* _hash_s1 = n;\
+ h = 0;\
+ if (r->namesize)\
+ {\
+ register const char* _hash_s2 = _hash_s1 + r->namesize;\
+ while (_hash_s1 < _hash_s2) HASHPART(h, *_hash_s1++);\
+ }\
+ else while (*_hash_s1) HASHPART(h, *_hash_s1++);\
+ }
+
+typedef struct /* library private info */
+{
+ Hash_root_t* list; /* root table list */
+} Hash_info_t;
+
+extern Hash_info_t hash_info;
+
+#endif
diff --git a/src/lib/libast/hash/hashlook.c b/src/lib/libast/hash/hashlook.c
new file mode 100644
index 0000000..4b0ae81
--- /dev/null
+++ b/src/lib/libast/hash/hashlook.c
@@ -0,0 +1,367 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * hash table library
+ */
+
+#include "hashlib.h"
+
+/*
+ * hash table lookup
+ */
+
+char*
+hashlook(register Hash_table_t* tab, const char* name, long flags, const char* value)
+{
+ register Hash_bucket_t* b;
+ register unsigned int n;
+ register Hash_last_t* last;
+ Hash_table_t* top;
+ Hash_bucket_t* prev;
+ unsigned int i;
+
+ if ((flags & (HASH_LOOKUP|HASH_INTERNAL)) == (HASH_LOOKUP|HASH_INTERNAL))
+ {
+ register char* s1;
+ register const char* s2;
+ register int c;
+
+ if (flags & HASH_HASHED) n = *((unsigned int*)value);
+ else
+ {
+ s2 = name;
+ n = 0;
+ while (c = *s2++) HASHPART(n, c);
+ }
+ i = n;
+ for (;;)
+ {
+ HASHMOD(tab, n);
+ for (b = tab->table[n]; b; b = b->next)
+ {
+ s1 = hashname(b);
+ s2 = name;
+ while ((c = *s1++) == *s2++)
+ if (!c) return((flags & HASH_VALUE) ? b->value : (char*)b);
+ }
+ if (!(tab = tab->scope) || (flags & HASH_NOSCOPE))
+ return(0);
+ n = i;
+ }
+ }
+ tab->root->accesses++;
+ top = tab;
+ last = &tab->root->last;
+ if (name)
+ {
+ last->table = tab;
+ if (flags & (HASH_BUCKET|HASH_INSTALL))
+ {
+ last->bucket = (Hash_bucket_t*)name;
+ name = hashname(last->bucket);
+ }
+ else last->bucket = 0;
+ last->name = name;
+ if (flags & HASH_BUCKET) n = last->bucket->hash;
+ else if (tab->flags & HASH_HASHED)
+ {
+ n = (unsigned int)integralof(name);
+ if (!(flags & HASH_HASHED)) n >>= 3;
+ }
+ else if (flags & HASH_HASHED) n = *((unsigned int*)value);
+ else HASH(tab->root, name, n);
+ last->hash = i = HASHVAL(n);
+ for (;;)
+ {
+ HASHMOD(tab, n);
+ for (prev = 0, b = tab->table[n]; b; prev = b, b = b->next)
+ {
+ if (i == HASHVAL(b->hash) && ((b->hash & (HASH_DELETED|HASH_OPAQUED)) != HASH_DELETED || (flags & (HASH_CREATE|HASH_DELETE|HASH_INSTALL|HASH_RENAME))))
+ {
+ if (!tab->root->local->compare)
+ {
+ register char* s1 = hashname(b);
+ register const char* s2 = name;
+
+ if (tab->root->namesize)
+ {
+ register char* s3 = s1 + tab->root->namesize;
+
+ while (*s1++ == *s2++)
+ if (s1 >= s3) goto found;
+ }
+ else while (*s1 == *s2++)
+ if (!*s1++) goto found;
+ }
+ else if (tab->root->namesize)
+ {
+ if (!(*tab->root->local->compare)(hashname(b), name, tab->root->namesize)) goto found;
+ }
+ else if (!(*tab->root->local->compare)(hashname(b), name)) goto found;
+ }
+ tab->root->collisions++;
+ }
+ if (!tab->scope || (flags & (HASH_CREATE|HASH_INSTALL|HASH_NOSCOPE)) == HASH_NOSCOPE) break;
+ tab = tab->scope;
+ n = i;
+ }
+ }
+ else
+ {
+ tab = last->table;
+ name = last->name;
+ n = i = last->hash;
+ prev = 0;
+ HASHMOD(tab, n);
+ if (b = last->bucket)
+ {
+ /*
+ * found the bucket
+ */
+
+ found:
+ if (prev && !tab->frozen)
+ {
+ /*
+ * migrate popular buckets to the front
+ */
+
+ prev->next = b->next;
+ b->next = tab->table[n];
+ tab->table[n] = b;
+ }
+ switch (flags & (HASH_CREATE|HASH_DELETE|HASH_INSTALL|HASH_RENAME))
+ {
+ case HASH_CREATE:
+ case HASH_CREATE|HASH_INSTALL:
+ case HASH_INSTALL:
+ if (tab != top && !(flags & HASH_SCOPE)) break;
+ if (flags & HASH_OPAQUE) b->hash |= HASH_OPAQUED;
+ goto exists;
+
+ case HASH_DELETE:
+ value = 0;
+ if (tab == top || (flags & HASH_SCOPE))
+ {
+ if (flags & HASH_OPAQUE) b->hash &= ~HASH_OPAQUED;
+ else if (!(tab->root->flags & HASH_BUCKET))
+ {
+ if (tab->root->local->free && b->value)
+ {
+ (*tab->root->local->free)(b->value);
+ b->value = 0;
+ }
+ else if (tab->flags & HASH_VALUE)
+ {
+ value = b->value;
+ b->value = 0;
+ }
+ }
+ tab->buckets--;
+ if (tab->frozen || (b->hash & HASH_OPAQUED)) b->hash |= HASH_DELETED;
+ else
+ {
+ tab->table[n] = b->next;
+ name = (b->hash & HASH_FREENAME) ? (char*)b->name : (char*)0;
+ if (tab->root->local->free && (tab->root->flags & HASH_BUCKET)) (*tab->root->local->free)((char*)b);
+ else if (!(b->hash & HASH_KEEP))
+ {
+ if (tab->root->local->region) (*tab->root->local->region)(tab->root->local->handle, b, 0, 0);
+ else free(b);
+ }
+ if (name)
+ {
+ if (tab->root->local->region) (*tab->root->local->region)(tab->root->local->handle, (char*)name, 0, 0);
+ else free((char*)name);
+ }
+ }
+ }
+ return((char*)value);
+
+ case HASH_RENAME:
+ if (tab != top || tab->frozen || (b->hash & (HASH_KEEP|HASH_OPAQUED)) || hashlook(top, value, (flags&(HASH_HASHED|HASH_INTERNAL))|HASH_LOOKUP, NiL))
+ return(0);
+ name = (char*)b->name;
+ if (!(tab->flags & HASH_ALLOCATE)) b->name = (char*)value;
+ else if (b->name && tab->root->namesize)
+ {
+ memcpy(b->name, value, tab->root->namesize);
+ name = 0;
+ }
+ else
+ {
+ int m;
+ char* t;
+
+ if (!(i = tab->bucketsize))
+ i = (sizeof(Hash_bucket_t) + sizeof(char*) - 1) / sizeof(char*);
+ i *= sizeof(char*);
+ m = strlen(value);
+ if (b->name == ((char*)b + i) && strlen(b->name) <= m)
+ {
+ strcpy(b->name, value);
+ name = 0;
+ }
+ else
+ {
+ m++;
+ if (!(t = tab->root->local->region ? (char*)(*tab->root->local->region)(tab->root->local->handle, NiL, m, 0) : (char*)malloc(m)))
+ return(0);
+ b->name = strcpy(t, value);
+ }
+ }
+ if (name && (b->hash & HASH_FREENAME))
+ {
+ b->hash &= ~HASH_FREENAME;
+ if (tab->root->local->region) (*tab->root->local->region)(tab->root->local->handle, (char*)name, 0, 0);
+ else free((char*)name);
+ }
+ tab->buckets--;
+ tab->table[n] = b->next;
+ flags = HASH_CREATE|HASH_INSTALL;
+ last->bucket = b;
+ i = last->hash;
+ goto create;
+
+ default:
+ if (!(b->hash & HASH_DELETED)) goto exists;
+ return(0);
+ }
+ }
+ }
+ if (!(flags & (HASH_CREATE|HASH_INSTALL))) return(0);
+
+ /*
+ * create a new bucket
+ */
+
+ create:
+ if (tab == top) prev = 0;
+ else
+ {
+ if (prev = b)
+ {
+ name = (b->hash & HASH_HIDES) ? b->name : (char*)b;
+ i |= HASH_HIDES;
+ }
+ if (!(flags & HASH_SCOPE)) tab = top;
+ }
+
+ /*
+ * check for table expansion
+ */
+
+ if (!tab->frozen && !(tab->flags & HASH_FIXED) && tab->buckets > tab->root->meanchain * tab->size)
+ hashsize(tab, tab->size << 1);
+ if (flags & HASH_INSTALL)
+ {
+ b = last->bucket;
+ i |= HASH_KEEP;
+ }
+ else
+ {
+ int m = tab->bucketsize * sizeof(char*);
+
+ if (flags & HASH_VALUE)
+ {
+ tab->flags |= HASH_VALUE;
+ if (m < sizeof(Hash_bucket_t))
+ {
+ tab->bucketsize = (sizeof(Hash_bucket_t) + sizeof(char*) - 1) / sizeof(char*);
+ m = tab->bucketsize * sizeof(char*);
+ }
+ n = m;
+ }
+ else if (!(n = HASH_SIZEOF(flags)))
+ {
+ if (!(flags & HASH_FIXED)) n = m;
+ else if ((n = (int)integralof(value)) < m) n = m;
+ }
+ else if (n < m) n = m;
+ if (!prev && (tab->flags & HASH_ALLOCATE))
+ {
+ m = tab->root->namesize ? tab->root->namesize : strlen(name) + 1;
+ if (tab->root->local->region)
+ {
+ if (!(b = (Hash_bucket_t*)(*tab->root->local->region)(tab->root->local->handle, NiL, n + m, 0)))
+ return(0);
+ memset(b, 0, n + m);
+ }
+ else if (!(b = newof(0, Hash_bucket_t, 0, n + m)))
+ return(0);
+ b->name = (char*)b + n;
+ memcpy(b->name, name, m);
+ }
+ else
+ {
+ if (tab->root->local->region)
+ {
+ if (!(b = (Hash_bucket_t*)(*tab->root->local->region)(tab->root->local->handle, NiL, n, 0)))
+ return(0);
+ memset(b, 0, n);
+ }
+ else if (!(b = newof(0, Hash_bucket_t, 0, n)))
+ return(0);
+ b->name = (char*)name;
+ }
+ }
+ b->hash = n = i;
+ HASHMOD(tab, n);
+ b->next = tab->table[n];
+ tab->table[n] = b;
+ tab->buckets++;
+ if (flags & HASH_OPAQUE)
+ {
+ tab->buckets--;
+ b->hash |= HASH_DELETED|HASH_OPAQUED;
+ return(0);
+ }
+
+ /*
+ * finally got the bucket
+ */
+
+ exists:
+ if (b->hash & HASH_DELETED)
+ {
+ b->hash &= ~HASH_DELETED;
+ tab->buckets++;
+ }
+ last->bucket = b;
+ last->table = tab;
+ switch (flags & (HASH_CREATE|HASH_VALUE))
+ {
+ case HASH_CREATE|HASH_VALUE:
+ if (tab->root->local->free && !(tab->root->flags & HASH_BUCKET) && b->value) (*tab->root->local->free)(b->value);
+ if (value && tab->root->local->alloc) value = (*tab->root->local->alloc)((unsigned int)integralof(value));
+ b->value = (char*)value;
+ return((char*)hashname(b));
+ case HASH_VALUE:
+ return(b->value);
+ default:
+ return((char*)b);
+ }
+}
diff --git a/src/lib/libast/hash/hashscan.c b/src/lib/libast/hash/hashscan.c
new file mode 100644
index 0000000..5162c08
--- /dev/null
+++ b/src/lib/libast/hash/hashscan.c
@@ -0,0 +1,139 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * hash table library
+ */
+
+#include "hashlib.h"
+
+/*
+ * hash table sequential scan
+ *
+ * Hash_position_t* pos;
+ * Hash_bucket_t* b;
+ * pos = hashscan(tab, flags);
+ * while (b = hashnext(&pos)) ...;
+ * hashdone(pos);
+ */
+
+/*
+ * return pos for scan on table
+ */
+
+Hash_position_t*
+hashscan(register Hash_table_t* tab, register int flags)
+{
+ register Hash_position_t* pos;
+
+ static Hash_bucket_t empty;
+
+ if (!(pos = newof(0, Hash_position_t, 1, 0))) return(0);
+ pos->tab = tab->root->last.table = tab;
+ pos->bucket = &empty;
+ pos->slot = tab->table - 1;
+ pos->limit = tab->table + tab->size;
+ if (tab->scope && !(flags & HASH_NOSCOPE))
+ {
+ pos->flags = HASH_SCOPE;
+ do
+ {
+ register Hash_bucket_t* b;
+
+ if (tab->frozen)
+ {
+ register Hash_bucket_t** sp = tab->table;
+ register Hash_bucket_t** sx = tab->table + tab->size;
+
+ while (sp < sx)
+ for (b = *sp++; b; b = b->next)
+ b->hash &= ~HASH_HIDDEN;
+ }
+ } while (tab = tab->scope);
+ tab = pos->tab;
+ }
+ else pos->flags = 0;
+ tab->frozen++;
+ return(pos);
+}
+
+/*
+ * return next scan element
+ */
+
+Hash_bucket_t*
+hashnext(register Hash_position_t* pos)
+{
+ register Hash_bucket_t* b;
+
+ if (!pos) return(0);
+ b = pos->bucket;
+ for (;;)
+ {
+ if (!(b = b->next))
+ {
+ do
+ {
+ if (++pos->slot >= pos->limit)
+ {
+ pos->tab->frozen--;
+ if (!pos->flags || !pos->tab->scope) return(0);
+ pos->tab = pos->tab->scope;
+ pos->tab->root->last.table = pos->tab;
+ pos->limit = (pos->slot = pos->tab->table) + pos->tab->size;
+ pos->tab->frozen++;
+ }
+ } while (!(b = *pos->slot));
+ }
+ if (!(b->hash & HASH_DELETED) && (!(pos->tab->flags & HASH_VALUE) || b->value) && (!pos->flags || !(b->hash & (HASH_HIDDEN|HASH_HIDES)))) break;
+ if (b->hash & HASH_HIDES)
+ {
+ register Hash_bucket_t* h = (Hash_bucket_t*)b->name;
+
+ if (!(h->hash & HASH_HIDDEN))
+ {
+ h->hash |= HASH_HIDDEN;
+ if (!(b->hash & HASH_DELETED)) break;
+ }
+ }
+ else b->hash &= ~HASH_HIDDEN;
+ }
+ return(pos->tab->root->last.bucket = pos->bucket = b);
+}
+
+/*
+ * terminate scan
+ */
+
+void
+hashdone(register Hash_position_t* pos)
+{
+ if (pos)
+ {
+ if (pos->tab->frozen)
+ pos->tab->frozen--;
+ free(pos);
+ }
+}
diff --git a/src/lib/libast/hash/hashsize.c b/src/lib/libast/hash/hashsize.c
new file mode 100644
index 0000000..0c458ba
--- /dev/null
+++ b/src/lib/libast/hash/hashsize.c
@@ -0,0 +1,84 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * hash table library
+ */
+
+#include "hashlib.h"
+
+/*
+ * change table size and rehash
+ * size must be a power of 2
+ */
+
+void
+hashsize(register Hash_table_t* tab, int size)
+{
+ register Hash_bucket_t** old_s;
+ register Hash_bucket_t** new_s;
+ register Hash_bucket_t* old_b;
+ register Hash_bucket_t* new_b;
+ Hash_bucket_t** old_sx;
+ unsigned int index;
+ Hash_region_f region;
+ void* handle;
+
+ if (size > 0 && size != tab->size && !(size & (size - 1)))
+ {
+ if (region = tab->root->local->region)
+ {
+ handle = tab->root->local->handle;
+ new_s = (Hash_bucket_t**)(*region)(handle, NiL, sizeof(Hash_bucket_t*) * size, 0);
+ }
+ else new_s = newof(0, Hash_bucket_t*, size, 0);
+ if (!new_s) tab->flags |= HASH_FIXED;
+ else
+ {
+ old_sx = (old_s = tab->table) + tab->size;
+ tab->size = size;
+ while (old_s < old_sx)
+ {
+ old_b = *old_s++;
+ while (old_b)
+ {
+ new_b = old_b;
+ old_b = old_b->next;
+ index = new_b->hash;
+ HASHMOD(tab, index);
+ new_b->next = new_s[index];
+ new_s[index] = new_b;
+ }
+ }
+ if ((tab->flags & (HASH_RESIZE|HASH_STATIC)) != HASH_STATIC)
+ {
+ if (region) (*region)(handle, tab->table, 0, 0);
+ else free(tab->table);
+ }
+ tab->table = new_s;
+ tab->flags |= HASH_RESIZE;
+ }
+ }
+}
diff --git a/src/lib/libast/hash/hashview.c b/src/lib/libast/hash/hashview.c
new file mode 100644
index 0000000..585f1a1
--- /dev/null
+++ b/src/lib/libast/hash/hashview.c
@@ -0,0 +1,88 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * hash table library
+ */
+
+#include "hashlib.h"
+
+/*
+ * push/pop/query hash table scope
+ *
+ * bot==0 pop top scope
+ * bot==top query
+ * bot!=0 push top on bot
+ *
+ * scope table pointer returned
+ */
+
+Hash_table_t*
+hashview(Hash_table_t* top, Hash_table_t* bot)
+{
+ register Hash_bucket_t* b;
+ register Hash_bucket_t* p;
+ register Hash_bucket_t** sp;
+ register Hash_bucket_t** sx;
+
+ if (!top || top->frozen)
+ bot = 0;
+ else if (top == bot)
+ bot = top->scope;
+ else if (bot)
+ {
+ if (top->scope)
+ bot = 0;
+ else
+ {
+ sx = &top->table[top->size];
+ sp = &top->table[0];
+ while (sp < sx)
+ for (b = *sp++; b; b = b->next)
+ if (p = (Hash_bucket_t*)hashlook(bot, b->name, HASH_LOOKUP, NiL))
+ {
+ b->name = (p->hash & HASH_HIDES) ? p->name : (char*)b;
+ b->hash |= HASH_HIDES;
+ }
+ top->scope = bot;
+ bot->frozen++;
+ }
+ }
+ else if (bot = top->scope)
+ {
+ sx = &top->table[top->size];
+ sp = &top->table[0];
+ while (sp < sx)
+ for (b = *sp++; b; b = b->next)
+ if (b->hash & HASH_HIDES)
+ {
+ b->hash &= ~HASH_HIDES;
+ b->name = ((Hash_bucket_t*)b->name)->name;
+ }
+ top->scope = 0;
+ bot->frozen--;
+ }
+ return(bot);
+}
diff --git a/src/lib/libast/hash/hashwalk.c b/src/lib/libast/hash/hashwalk.c
new file mode 100644
index 0000000..d3e4610
--- /dev/null
+++ b/src/lib/libast/hash/hashwalk.c
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * hash table library
+ */
+
+#include "hashlib.h"
+
+/*
+ * apply walker to each active bucket in the table
+ */
+
+int
+hashwalk(Hash_table_t* tab, int flags, register int (*walker)(const char*, char*, void*), void* handle)
+{
+ register Hash_bucket_t* b;
+ register int v;
+ Hash_position_t* pos;
+
+ if (!(pos = hashscan(tab, flags)))
+ return(-1);
+ v = 0;
+ while (b = hashnext(pos))
+ if ((v = (*walker)(hashname(b), (tab->flags & HASH_VALUE) ? b->value : (char*)b, handle)) < 0)
+ break;
+ hashdone(pos);
+ return(v);
+}
diff --git a/src/lib/libast/hash/memhash.c b/src/lib/libast/hash/memhash.c
new file mode 100644
index 0000000..24f6465
--- /dev/null
+++ b/src/lib/libast/hash/memhash.c
@@ -0,0 +1,45 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * hash table library
+ */
+
+#include "hashlib.h"
+
+/*
+ * return the hash of buffer s of length n
+ */
+
+unsigned int
+memhash(const void* as, int n)
+{
+ register const unsigned char* s = (const unsigned char*)as;
+ register const unsigned char* e = s + n;
+ register unsigned int c = 0;
+
+ while (s < e) HASHPART(c, *s++);
+ return(c);
+}
diff --git a/src/lib/libast/hash/memsum.c b/src/lib/libast/hash/memsum.c
new file mode 100644
index 0000000..c426215
--- /dev/null
+++ b/src/lib/libast/hash/memsum.c
@@ -0,0 +1,53 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * hash table library
+ */
+
+#include "hashlib.h"
+
+/*
+ * return a running 32 bit checksum of buffer b of length n
+ *
+ * c is the return value from a previous
+ * memsum() or strsum() call, 0 on the first call
+ *
+ * the result is the same on all implementations
+ */
+
+unsigned long
+memsum(const void* ap, int n, register unsigned long c)
+{
+ register const unsigned char* p = (const unsigned char*)ap;
+ register const unsigned char* e = p + n;
+
+ while (p < e) HASHPART(c, *p++);
+#if LONG_MAX > 2147483647
+ return(c & 0xffffffff);
+#else
+ return(c);
+#endif
+}
diff --git a/src/lib/libast/hash/strhash.c b/src/lib/libast/hash/strhash.c
new file mode 100644
index 0000000..e9f4976
--- /dev/null
+++ b/src/lib/libast/hash/strhash.c
@@ -0,0 +1,45 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * hash table library
+ */
+
+#include "hashlib.h"
+
+/*
+ * return the hash of the null terminated string s
+ */
+
+unsigned int
+strhash(const char* as)
+{
+ register const unsigned char* s = (const unsigned char*)as;
+ register unsigned int i = 0;
+ register unsigned int c;
+
+ while (c = *s++) HASHPART(i, c);
+ return(i);
+}
diff --git a/src/lib/libast/hash/strkey.c b/src/lib/libast/hash/strkey.c
new file mode 100644
index 0000000..3ff7ead
--- /dev/null
+++ b/src/lib/libast/hash/strkey.c
@@ -0,0 +1,49 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include <ast.h>
+#include <hashkey.h>
+
+long
+strkey(register const char* s)
+{
+ register long x = 0;
+ register int n = 0;
+ register int c;
+
+ while (n++ < HASHKEYMAX)
+ {
+ c = *s;
+ if (c >= 'a' && c <= 'z')
+ x = HASHKEYPART(x, c);
+ else if (c >= '0' && c <= '9')
+ x = HASHKEYPART(x, HASHKEYN(c));
+ else break;
+ s++;
+ }
+ return x;
+}
diff --git a/src/lib/libast/hash/strsum.c b/src/lib/libast/hash/strsum.c
new file mode 100644
index 0000000..92b413d
--- /dev/null
+++ b/src/lib/libast/hash/strsum.c
@@ -0,0 +1,53 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * hash table library
+ */
+
+#include "hashlib.h"
+
+/*
+ * return a running 32 bit checksum of string s
+ *
+ * c is the return value from a previous
+ * memsum() or strsum() call, 0 on the first call
+ *
+ * the result is the same on all implementations
+ */
+
+unsigned long
+strsum(const char* as, register unsigned long c)
+{
+ register const unsigned char* s = (const unsigned char*)as;
+ register int n;
+
+ while (n = *s++) HASHPART(c, n);
+#if LONG_MAX > 2147483647
+ return(c & 0xffffffff);
+#else
+ return(c);
+#endif
+}
diff --git a/src/lib/libast/include/aso.h b/src/lib/libast/include/aso.h
new file mode 100644
index 0000000..1007e93
--- /dev/null
+++ b/src/lib/libast/include/aso.h
@@ -0,0 +1,183 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _ASO_H
+#define _ASO_H 1
+
+#define ASO_VERSION 20111111L
+
+#include <ast_common.h>
+
+/*
+ * ast atomic scalar operations interface definitions
+ */
+
+/* asometh() types (ordered mutually exclusive flags) */
+#define ASO_NEXT (-1)
+#define ASO_SIGNAL 1
+#define ASO_THREAD 2
+#define ASO_PROCESS 4
+#define ASO_INTRINSIC 8
+
+/* asolock() operations */
+#define ASO_UNLOCK 0 /* unlock if key matches */
+#define ASO_TRYLOCK 1 /* matched key means successful attempt */
+#define ASO_LOCK 2 /* matched key first, then spin-lock */
+#define ASO_SPINLOCK 3 /* no matching of key before locking */
+
+/* Asoerror_f types */
+#define ASO_EMETHOD 0 /* method specific error */
+#define ASO_EHUNG 1 /* asoloop() possibly hung */
+
+/* for internal use, but standardized for libs such as CDT and Vmalloc */
+#define ASO_RELAX ((1<<2)-1) /* cycles between spin-loop yield */
+#define ASOLOOP(k) asoloop(++(k))
+
+#define ASODISC(d,e) (memset(d,0,sizeof(*(d))),(d)->version=ASO_VERSION,(d)->errorf=(e))
+
+typedef int (*Asoerror_f)(int, const char*);
+typedef void* (*Asoinit_f)(void*, const char*);
+typedef ssize_t (*Asolock_f)(void*, ssize_t, void volatile*);
+
+typedef struct Asodisc_s
+{
+ uint32_t version;
+ unsigned int hung;
+ Asoerror_f errorf;
+} Asodisc_t;
+
+typedef struct Asometh_s
+{
+ const char* name;
+ int type;
+ Asoinit_f initf;
+ Asolock_f lockf;
+ const char* details;
+} Asometh_t;
+
+#if (_BLD_aso || _BLD_taso) && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+#if !(_BLD_aso || _BLD_taso) && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern Asometh_t* asometh(int, void*);
+
+#undef extern
+
+#if _BLD_aso && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+#if !_BLD_aso && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern Asometh_t* _asometh(int, void*);
+extern int asoinit(const char*, Asometh_t*, Asodisc_t*);
+extern int asolock(unsigned int volatile*, unsigned int, int);
+extern int asoloop(uintmax_t);
+extern int asorelax(long);
+
+extern uint8_t asocas8(uint8_t volatile*, int, int);
+extern uint8_t asoget8(uint8_t volatile*);
+extern uint8_t asoinc8(uint8_t volatile*);
+extern uint8_t asodec8(uint8_t volatile*);
+
+#define asocaschar(p,o,n) asocas8(p,o,n)
+#define asogetchar(p) asoget8(p)
+#define asoincchar(p) asoinc8(p)
+#define asodecchar(p) asodec8(p)
+
+extern uint16_t asocas16(uint16_t volatile*, uint16_t, uint16_t);
+extern uint16_t asoget16(uint16_t volatile*);
+extern uint16_t asoinc16(uint16_t volatile*);
+extern uint16_t asodec16(uint16_t volatile*);
+
+#define asocasshort(p,o,n) asocas16(p,o,n)
+#define asogetshort(p) asoget16(p)
+#define asoincshort(p) asoinc16(p)
+#define asodecshort(p) asodec16(p)
+
+extern uint32_t asocas32(uint32_t volatile*, uint32_t, uint32_t);
+extern uint32_t asoget32(uint32_t volatile*);
+extern uint32_t asoinc32(uint32_t volatile*);
+extern uint32_t asodec32(uint32_t volatile*);
+
+#if _ast_sizeof_int == 4
+#define asocasint(p,o,n) asocas32((uint32_t volatile*)p,o,n)
+#define asogetint(p) asoget32((uint32_t volatile*)p)
+#define asoincint(p) asoinc32((uint32_t volatile*)p)
+#define asodecint(p) asodec32((uint32_t volatile*)p)
+#endif
+
+#if _ast_sizeof_long == 4
+#define asocaslong(p,o,n) asocas32((uint32_t volatile*)p,o,n)
+#define asogetlong(p) asoget32((uint32_t volatile*)p)
+#define asoinclong(p) asoinc32((uint32_t volatile*)p)
+#define asodeclong(p) asodec32((uint32_t volatile*)p)
+#endif
+
+#if _ast_sizeof_size_t == 4
+#define asocassize(p,o,n) asocas32((uint32_t volatile*)p,o,n)
+#define asogetsize(p) asoget32((uint32_t volatile*)p)
+#define asoincsize(p) asoinc32((uint32_t volatile*)p)
+#define asodecsize(p) asodec32((uint32_t volatile*)p)
+#endif
+
+#ifdef _ast_int8_t
+
+extern uint64_t asocas64(uint64_t volatile*, uint64_t, uint64_t);
+extern uint64_t asoget64(uint64_t volatile*);
+extern uint64_t asoinc64(uint64_t volatile*);
+extern uint64_t asodec64(uint64_t volatile*);
+
+#if _ast_sizeof_int == 8
+#define asocasint(p,o,n) asocas64((uint64_t volatile*)p,o,n)
+#define asogetint(p) asoget64((uint64_t volatile*)p)
+#define asoincint(p) asoinc64((uint64_t volatile*)p)
+#define asodecint(p) asodec64((uint64_t volatile*)p)
+#endif
+
+#if _ast_sizeof_long == 8
+#define asocaslong(p,o,n) asocas64((uint64_t volatile*)p,o,n)
+#define asogetlong(p) asoget64((uint64_t volatile*)p)
+#define asoinclong(p) asoinc64((uint64_t volatile*)p)
+#define asodeclong(p) asodec64((uint64_t volatile*)p)
+#endif
+
+#if _ast_sizeof_size_t == 8
+#define asocassize(p,o,n) asocas64((uint64_t volatile*)p,o,n)
+#define asogetsize(p) asoget64((uint64_t volatile*)p)
+#define asoincsize(p) asoinc64((uint64_t volatile*)p)
+#define asodecsize(p) asodec64((uint64_t volatile*)p)
+#endif
+
+#endif
+
+extern void* asocasptr(void volatile*, void*, void*);
+extern void* asogetptr(void volatile*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/ast.h b/src/lib/libast/include/ast.h
new file mode 100644
index 0000000..719e7a9
--- /dev/null
+++ b/src/lib/libast/include/ast.h
@@ -0,0 +1,405 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Advanced Software Technology Library
+ * AT&T Research
+ *
+ * std + posix + ast
+ */
+
+#ifndef _AST_H
+#define _AST_H
+
+#ifndef _AST_STD_H
+#include <ast_std.h>
+#endif
+
+#ifndef _SFIO_H
+#include <sfio.h>
+#endif
+
+#ifndef ast
+#define ast _ast_info
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+/*
+ * workaround botched headers that assume <stdio.h>
+ */
+
+#ifndef FILE
+#ifndef _SFIO_H
+struct _sfio_s;
+#endif
+#define FILE struct _sfio_s
+#ifndef __FILE_typedef
+#define __FILE_typedef 1
+#endif
+#ifndef _FILEDEFED
+#define _FILEDEFED 1
+#endif
+#endif
+
+/*
+ * exit() support -- this matches shell exit codes
+ */
+
+#define EXIT_BITS 8 /* # exit status bits */
+
+#define EXIT_USAGE 2 /* usage exit code */
+#define EXIT_QUIT ((1<<(EXIT_BITS))-1) /* parent should quit */
+#define EXIT_NOTFOUND ((1<<(EXIT_BITS-1))-1) /* command not found */
+#define EXIT_NOEXEC ((1<<(EXIT_BITS-1))-2) /* other exec error */
+
+#define EXIT_CODE(x) ((x)&((1<<EXIT_BITS)-1))
+#define EXIT_CORE(x) (EXIT_CODE(x)|(1<<EXIT_BITS)|(1<<(EXIT_BITS-1)))
+#define EXIT_TERM(x) (EXIT_CODE(x)|(1<<EXIT_BITS))
+
+/*
+ * NOTE: for compatibility the following work for EXIT_BITS={7,8}
+ */
+
+#define EXIT_STATUS(x) (((x)&((1<<(EXIT_BITS-2))-1))?(x):EXIT_CODE((x)>>EXIT_BITS))
+
+#define EXITED_CORE(x) (((x)&((1<<EXIT_BITS)|(1<<(EXIT_BITS-1))))==((1<<EXIT_BITS)|(1<<(EXIT_BITS-1)))||((x)&((1<<(EXIT_BITS-1))|(1<<(EXIT_BITS-2))))==((1<<(EXIT_BITS-1))|(1<<(EXIT_BITS-2))))
+#define EXITED_TERM(x) ((x)&((1<<EXIT_BITS)|(1<<(EXIT_BITS-1))))
+
+/*
+ * astconflist() flags
+ */
+
+#define ASTCONF_parse 0x0001
+#define ASTCONF_write 0x0002
+#define ASTCONF_read 0x0004
+#define ASTCONF_lower 0x0008
+#define ASTCONF_base 0x0010
+#define ASTCONF_defined 0x0020
+#define ASTCONF_quote 0x0040
+#define ASTCONF_table 0x0080
+#define ASTCONF_matchcall 0x0100
+#define ASTCONF_matchname 0x0200
+#define ASTCONF_matchstandard 0x0400
+#define ASTCONF_error 0x0800
+#define ASTCONF_system 0x1000
+#define ASTCONF_AST 0x2000
+
+/*
+ * pathcanon() flags
+ */
+
+#define PATH_PHYSICAL 01
+#define PATH_DOTDOT 02
+#define PATH_EXISTS 04
+#define PATH_VERIFIED(n) (((n)&01777)<<5)
+
+/*
+ * pathaccess() flags
+ */
+
+#define PATH_READ 004
+#define PATH_WRITE 002
+#define PATH_EXECUTE 001
+#define PATH_REGULAR 010
+#define PATH_ABSOLUTE 020
+
+/*
+ * touch() flags
+ */
+
+#define PATH_TOUCH_CREATE 01
+#define PATH_TOUCH_VERBATIM 02
+
+/*
+ * pathcheck() info
+ */
+
+typedef struct
+{
+ unsigned long date;
+ char* feature;
+ char* host;
+ char* user;
+} Pathcheck_t;
+
+/*
+ * strgrpmatch() flags
+ */
+
+#define STR_MAXIMAL 01 /* maximal match */
+#define STR_LEFT 02 /* implicit left anchor */
+#define STR_RIGHT 04 /* implicit right anchor */
+#define STR_ICASE 010 /* ignore case */
+#define STR_GROUP 020 /* (|&) inside [@|&](...) only */
+
+/*
+ * fmtquote() flags
+ */
+
+#define FMT_ALWAYS 0x01 /* always quote */
+#define FMT_ESCAPED 0x02 /* already escaped */
+#define FMT_SHELL 0x04 /* escape $ ` too */
+#define FMT_WIDE 0x08 /* don't escape 8 bit chars */
+#define FMT_PARAM 0x10 /* disable FMT_SHELL ${$( quote */
+
+/*
+ * chrexp() flags
+ */
+
+#define FMT_EXP_CHAR 0x020 /* expand single byte chars */
+#define FMT_EXP_LINE 0x040 /* expand \n and \r */
+#define FMT_EXP_WIDE 0x080 /* expand \u \U \x wide chars */
+#define FMT_EXP_NOCR 0x100 /* skip \r */
+#define FMT_EXP_NONL 0x200 /* skip \n */
+
+/*
+ * multibyte macros
+ */
+
+#define mbmax() (ast.mb_cur_max)
+#define mberr() (ast.tmp_int<0)
+
+#define mbcoll() (ast.mb_xfrm!=0)
+#define mbwide() (mbmax()>1)
+
+#define mb2wc(w,p,n) (*ast.mb_towc)(&w,(char*)p,n)
+#define mbchar(p) (mbwide()?((ast.tmp_int=(*ast.mb_towc)(&ast.tmp_wchar,(char*)(p),mbmax()))>0?((p+=ast.tmp_int),ast.tmp_wchar):(p+=ast.mb_sync+1,ast.tmp_int)):(*(unsigned char*)(p++)))
+#define mbnchar(p,n) (mbwide()?((ast.tmp_int=(*ast.mb_towc)(&ast.tmp_wchar,(char*)(p),n))>0?((p+=ast.tmp_int),ast.tmp_wchar):(p+=ast.mb_sync+1,ast.tmp_int)):(*(unsigned char*)(p++)))
+#define mbinit() (mbwide()?(*ast.mb_towc)((wchar_t*)0,(char*)0,mbmax()):0)
+#define mbsize(p) (mbwide()?(*ast.mb_len)((char*)(p),mbmax()):((p),1))
+#define mbnsize(p,n) (mbwide()?(*ast.mb_len)((char*)(p),n):((p),1))
+#define mbconv(s,w) (ast.mb_conv?(*ast.mb_conv)(s,w):((*(s)=(w)),1))
+#define mbwidth(w) (ast.mb_width?(*ast.mb_width)(w):1)
+#define mbxfrm(t,f,n) (mbcoll()?(*ast.mb_xfrm)((char*)(t),(char*)(f),n):0)
+#define mbalpha(w) (ast.mb_alpha?(*ast.mb_alpha)(w):isalpha((w)&0xff))
+
+/*
+ * common macros
+ */
+
+#define elementsof(x) (sizeof(x)/sizeof(x[0]))
+#define integralof(x) (((char*)(x))-((char*)0))
+#define newof(p,t,n,x) ((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)calloc(1,sizeof(t)*(n)+(x)))
+#define oldof(p,t,n,x) ((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)malloc(sizeof(t)*(n)+(x)))
+#define pointerof(x) ((void*)((char*)0+(x)))
+#define roundof(x,y) (((x)+(y)-1)&~((y)-1))
+#define ssizeof(x) ((int)sizeof(x))
+
+#define streq(a,b) (*(a)==*(b)&&!strcmp(a,b))
+#define strneq(a,b,n) (*(a)==*(b)&&!strncmp(a,b,n))
+#define strsignal(s) fmtsignal(s)
+
+#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
+#define NiL 0
+#define NoP(x) (void)(x)
+#else
+#define NiL ((char*)0)
+#define NoP(x) (&x,1)
+#endif
+
+#if !defined(NoF)
+#define NoF(x) void _DATA_ ## x () {}
+#if !defined(_DATA_)
+#define _DATA_
+#endif
+#endif
+
+#if !defined(NoN)
+#define NoN(x) void _STUB_ ## x () {}
+#if !defined(_STUB_)
+#define _STUB_
+#endif
+#endif
+
+#define NOT_USED(x) NoP(x)
+
+typedef int (*Error_f)(void*, void*, int, ...);
+
+typedef int (*Ast_confdisc_f)(const char*, const char*, const char*);
+typedef int (*Strcmp_context_f)(const char*, const char*, void*);
+typedef int (*Strcmp_f)(const char*, const char*);
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char* astgetconf(const char*, const char*, const char*, int, Error_f);
+extern char* astconf(const char*, const char*, const char*);
+extern Ast_confdisc_f astconfdisc(Ast_confdisc_f);
+extern void astconflist(Sfio_t*, const char*, int, const char*);
+extern off_t astcopy(int, int, off_t);
+extern int astlicense(char*, int, char*, char*, int, int, int);
+extern int astquery(int, const char*, ...);
+extern void astwinsize(int, int*, int*);
+
+extern ssize_t base64encode(const void*, size_t, void**, void*, size_t, void**);
+extern ssize_t base64decode(const void*, size_t, void**, void*, size_t, void**);
+extern int chresc(const char*, char**);
+extern int chrexp(const char*, char**, int*, int);
+extern int chrtoi(const char*);
+extern char* conformance(const char*, size_t);
+extern int eaccess(const char*, int);
+extern char* fmtbase(intmax_t, int, int);
+#define fmtbasell(a,b,c) fmtbase(a,b,c) /* until 2014-01-01 */
+extern char* fmtbuf(size_t);
+extern char* fmtclock(Sfulong_t);
+extern char* fmtelapsed(unsigned long, int);
+extern char* fmterror(int);
+extern char* fmtesc(const char*);
+extern char* fmtesq(const char*, const char*);
+extern char* fmtident(const char*);
+extern char* fmtip4(uint32_t, int);
+extern char* fmtfmt(const char*);
+extern char* fmtgid(int);
+extern char* fmtint(intmax_t, int);
+extern char* fmtmatch(const char*);
+extern char* fmtmode(int, int);
+extern char* fmtnesq(const char*, const char*, size_t);
+extern char* fmtnum(unsigned long, int);
+extern char* fmtperm(int);
+extern char* fmtquote(const char*, const char*, const char*, size_t, int);
+extern char* fmtre(const char*);
+extern char* fmtscale(Sfulong_t, int);
+extern char* fmtsignal(int);
+extern char* fmttime(const char*, time_t);
+extern char* fmtuid(int);
+extern char* fmtversion(unsigned long);
+extern void* memdup(const void*, size_t);
+extern void memfatal(void);
+extern unsigned int memhash(const void*, int);
+extern unsigned long memsum(const void*, int, unsigned long);
+extern char* pathaccess(char*, const char*, const char*, const char*, int);
+extern char* pathaccess_20100601(const char*, const char*, const char*, int, char*, size_t);
+extern char* pathbin(void);
+extern char* pathcanon(char*, int);
+extern char* pathcanon_20100601(char*, size_t, int);
+extern char* pathcat(char*, const char*, int, const char*, const char*);
+extern char* pathcat_20100601(const char*, int, const char*, const char*, char*, size_t);
+extern int pathcd(const char*, const char*);
+extern int pathcheck(const char*, const char*, Pathcheck_t*);
+extern int pathexists(char*, int);
+extern char* pathfind(const char*, const char*, const char*, char*, size_t);
+extern int pathgetlink(const char*, char*, int);
+extern int pathinclude(const char*);
+extern char* pathkey(char*, char*, const char*, const char*, const char*);
+extern char* pathkey_20100601(const char*, const char*, const char*, char*, size_t, char*, size_t);
+extern size_t pathnative(const char*, char*, size_t);
+extern char* pathpath(char*, const char*, const char*, int);
+extern char* pathpath_20100601(const char*, const char*, int, char*, size_t);
+extern size_t pathposix(const char*, char*, size_t);
+extern char* pathprobe(char*, char*, const char*, const char*, const char*, int);
+extern char* pathprobe_20100601(const char*, const char*, const char*, int, char*, size_t, char*, size_t);
+extern size_t pathprog(const char*, char*, size_t);
+extern char* pathrepl(char*, const char*, const char*);
+extern char* pathrepl_20100601(char*, size_t, const char*, const char*);
+extern int pathsetlink(const char*, const char*);
+extern char* pathshell(void);
+extern char* pathtemp(char*, size_t, const char*, const char*, int*);
+extern char* pathtmp(char*, const char*, const char*, int*);
+extern char* setenviron(const char*);
+extern int stracmp(const char*, const char*);
+extern char* strcopy(char*, const char*);
+extern unsigned long strelapsed(const char*, char**, int);
+extern int stresc(char*);
+extern int strexp(char*, int);
+extern long streval(const char*, char**, long(*)(const char*, char**));
+extern long strexpr(const char*, char**, long(*)(const char*, char**, void*), void*);
+extern int strgid(const char*);
+extern int strgrpmatch(const char*, const char*, int*, int, int);
+extern unsigned int strhash(const char*);
+extern void* strlook(const void*, size_t, const char*);
+extern int strmatch(const char*, const char*);
+extern int strmode(const char*);
+extern int strnacmp(const char*, const char*, size_t);
+extern char* strncopy(char*, const char*, size_t);
+extern int strnpcmp(const char*, const char*, size_t);
+extern double strntod(const char*, size_t, char**);
+extern _ast_fltmax_t strntold(const char*, size_t, char**);
+extern long strntol(const char*, size_t, char**, int);
+extern intmax_t strntoll(const char*, size_t, char**, int);
+extern long strnton(const char*, size_t, char**, char*, int);
+extern unsigned long strntoul(const char*, size_t, char**, int);
+extern intmax_t strntonll(const char*, size_t, char**, char*, int);
+extern uintmax_t strntoull(const char*, size_t, char**, int);
+extern int strnvcmp(const char*, const char*, size_t);
+extern int stropt(const char*, const void*, int, int(*)(void*, const void*, int, const char*), void*);
+extern int strpcmp(const char*, const char*);
+extern int strperm(const char*, char**, int);
+extern void* strpsearch(const void*, size_t, size_t, const char*, char**);
+extern void* strsearch(const void*, size_t, size_t, Strcmp_f, const char*, void*);
+extern void strsort(char**, int, int(*)(const char*, const char*));
+extern char* strsubmatch(const char*, const char*, int);
+extern unsigned long strsum(const char*, unsigned long);
+extern char* strtape(const char*, char**);
+extern int strtoip4(const char*, char**, uint32_t*, unsigned char*);
+extern long strton(const char*, char**, char*, int);
+extern intmax_t strtonll(const char*, char**, char*, int);
+extern int struid(const char*);
+extern int struniq(char**, int);
+extern int strvcmp(const char*, const char*);
+extern int wc2utf8(char*, uint32_t);
+
+#undef extern
+
+/*
+ * C library global data symbols not prototyped by <unistd.h>
+ */
+
+#if !defined(environ) && defined(__DYNAMIC__)
+#define environ __DYNAMIC__(environ)
+#else
+extern char** environ;
+#endif
+
+/*
+ * really handy malloc()/free() (__FILE__,__LINE__,__FUNCTION__) tracing
+ * make with VMDEBUG==1 or debug=1 or CCFLAGS=$(CC.DEBUG)
+ * VMDEBUG==0 disables
+ * at runtime export VMALLOC_OPTIONS per vmalloc.3
+ * to list originating call locations
+ */
+
+#if !_std_malloc && !defined(VMFL) && !defined(_VMHDR_H) && \
+ (VMDEBUG || !defined(VMDEBUG) && _BLD_DEBUG)
+
+#define VMFL 1
+#include <vmalloc.h>
+
+#endif
+
+#include <ast_api.h>
+
+#undef AST_PLUGIN_VERSION
+#define AST_PLUGIN_VERSION(v) ((v)>AST_VERSION?(v):AST_VERSION)
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern unsigned long plugin_version(void);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/ast_dir.h b/src/lib/libast/include/ast_dir.h
new file mode 100644
index 0000000..260d4b6
--- /dev/null
+++ b/src/lib/libast/include/ast_dir.h
@@ -0,0 +1,77 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * AT&T Research
+ *
+ * common dirent maintenance interface
+ */
+
+#ifndef _AST_DIR_H
+#define _AST_DIR_H
+
+#include <ast_lib.h>
+
+#if _mem_d_fileno_dirent || _mem_d_ino_dirent
+#if !_mem_d_fileno_dirent
+#undef _mem_d_fileno_dirent
+#define _mem_d_fileno_dirent 1
+#define d_fileno d_ino
+#endif
+#endif
+
+#if _BLD_ast
+#include "dirlib.h"
+#else
+#include <dirent.h>
+#endif
+
+#if _mem_d_fileno_dirent
+#define D_FILENO(d) ((d)->d_fileno)
+#endif
+
+#if _mem_d_namlen_dirent
+#define D_NAMLEN(d) ((d)->d_namlen)
+#else
+#define D_NAMLEN(d) (strlen((d)->d_name))
+#endif
+
+#if _mem_d_reclen_dirent
+#define D_RECLEN(d) ((d)->d_reclen)
+#else
+#define D_RECLEN(d) D_RECSIZ(d,D_NAMLEN(d))
+#endif
+
+#define D_RECSIZ(d,n) (sizeof(*(d))-sizeof((d)->d_name)+((n)+sizeof(char*))&~(sizeof(char*)-1))
+
+/*
+ * NOTE: 2003-03-27 mac osx bug symlink==DT_REG bug discovered;
+ * the kernel *and* all directories must be fixed, so d_type
+ * is summarily disabled until we see that happen
+ */
+
+#if _mem_d_type_dirent && defined(DT_UNKNOWN) && defined(DT_REG) && defined(DT_DIR) && defined(DT_LNK) && ! ( __APPLE__ || __MACH__ )
+#define D_TYPE(d) ((d)->d_type)
+#endif
+
+#endif
diff --git a/src/lib/libast/include/ast_getopt.h b/src/lib/libast/include/ast_getopt.h
new file mode 100644
index 0000000..cf5efd3
--- /dev/null
+++ b/src/lib/libast/include/ast_getopt.h
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * legacy standard getopt interface
+ */
+
+#ifdef _AST_STD_I
+#undef _AST_GETOPT_H
+#define _AST_GETOPT_H -1
+#endif
+#ifndef _AST_GETOPT_H
+#define _AST_GETOPT_H 1
+
+extern int opterr;
+extern int optind;
+extern int optopt;
+extern char* optarg;
+
+extern int getopt(int, char* const*, const char*);
+extern int getsubopt(char**, char* const*, char**);
+
+#endif
diff --git a/src/lib/libast/include/ast_std.h b/src/lib/libast/include/ast_std.h
new file mode 100644
index 0000000..03f4fb3
--- /dev/null
+++ b/src/lib/libast/include/ast_std.h
@@ -0,0 +1,362 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Advanced Software Technology Library
+ * AT&T Research
+ *
+ * a union of standard headers that works
+ * with local extensions enabled
+ * and local omission compensation
+ */
+
+#ifndef _AST_STD_H
+#define _AST_STD_H 1
+#define _AST_STD_I 1
+
+#include <ast_common.h>
+
+#if _BLD_ast
+#define _BLD_aso 1
+#define _BLD_cdt 1
+#define _BLD_sfio 1
+#if !_UWIN
+#define _BLD_vmalloc 1
+#endif
+#endif
+
+#ifdef _SFSTDIO_H
+#define _SKIP_SFSTDIO_H
+#else
+#define _SFSTDIO_H
+#ifndef FILE
+#ifndef _SFIO_H
+struct _sfio_s;
+#endif
+#define FILE struct _sfio_s
+#ifndef __FILE_typedef
+#define __FILE_typedef 1
+#endif
+#ifndef _FILEDEFED
+#define _FILEDEFED 1
+#endif
+#endif
+#endif
+
+#include <ast_lib.h>
+#include <ast_sys.h>
+#include <ast_getopt.h> /* <stdlib.h> does this */
+#include <ast_fcntl.h>
+#include <ast_limits.h>
+#include <ast_botch.h>
+
+#ifdef _SKIP_SFSTDIO_H
+#undef _SKIP_SFSTDIO_H
+#else
+#undef _SFSTDIO_H
+#undef FILE
+#endif
+
+/* locale stuff */
+
+#if !_hdr_locale
+
+struct lconv
+{
+ char* decimal_point;
+ char* thousands_sep;
+ char* grouping;
+ char* int_curr_symbol;
+ char* currency_symbol;
+ char* mon_decimal_point;
+ char* mon_thousands_sep;
+ char* mon_grouping;
+ char* positive_sign;
+ char* negative_sign;
+ char int_frac_digits;
+ char frac_digits;
+ char p_cs_precedes;
+ char p_sep_by_space;
+ char n_cs_precedes;
+ char n_sep_by_space;
+ char p_sign_posn;
+ char n_sign_posn;
+};
+
+#endif
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#if !_UWIN /* for ast54 compatibility */
+
+#undef getenv
+#define getenv _ast_getenv
+
+#undef setenviron
+#define setenviron _ast_setenviron
+
+extern char* getenv(const char*);
+
+#endif
+
+#undef localeconv
+#define localeconv _ast_localeconv
+
+#undef setlocale
+#define setlocale _ast_setlocale
+
+#undef strerror
+#define strerror _ast_strerror
+
+extern struct lconv* localeconv(void);
+extern char* setenviron(const char*);
+extern char* setlocale(int, const char*);
+extern char* strerror(int);
+
+#define AST_MESSAGE_SET 3 /* see <mc.h> mcindex() */
+
+/*
+ * maintain this order when adding categories
+ */
+
+#define AST_LC_ALL 0
+#define AST_LC_COLLATE 1
+#define AST_LC_CTYPE 2
+#define AST_LC_MESSAGES 3
+#define AST_LC_MONETARY 4
+#define AST_LC_NUMERIC 5
+#define AST_LC_TIME 6
+#define AST_LC_IDENTIFICATION 7
+#define AST_LC_ADDRESS 8
+#define AST_LC_NAME 9
+#define AST_LC_TELEPHONE 10
+#define AST_LC_XLITERATE 11
+#define AST_LC_MEASUREMENT 12
+#define AST_LC_PAPER 13
+#define AST_LC_COUNT 14
+#define AST_LC_LANG 255
+
+#define AST_LC_internal 1
+#define AST_LC_test (1L<<26)
+#define AST_LC_setenv (1L<<27)
+#define AST_LC_find (1L<<28)
+#define AST_LC_debug (1L<<29)
+#define AST_LC_setlocale (1L<<30)
+#define AST_LC_translate (1L<<31)
+
+#ifndef LC_ALL
+#define LC_ALL (-AST_LC_ALL)
+#endif
+#ifndef LC_COLLATE
+#define LC_COLLATE (-AST_LC_COLLATE)
+#endif
+#ifndef LC_CTYPE
+#define LC_CTYPE (-AST_LC_CTYPE)
+#endif
+#ifndef LC_MESSAGES
+#define LC_MESSAGES (-AST_LC_MESSAGES)
+#endif
+#ifndef LC_MONETARY
+#define LC_MONETARY (-AST_LC_MONETARY)
+#endif
+#ifndef LC_NUMERIC
+#define LC_NUMERIC (-AST_LC_NUMERIC)
+#endif
+#ifndef LC_TIME
+#define LC_TIME (-AST_LC_TIME)
+#endif
+#ifndef LC_ADDRESS
+#define LC_ADDRESS (-AST_LC_ADDRESS)
+#endif
+#ifndef LC_IDENTIFICATION
+#define LC_IDENTIFICATION (-AST_LC_IDENTIFICATION)
+#endif
+#ifndef LC_NAME
+#define LC_NAME (-AST_LC_NAME)
+#endif
+#ifndef LC_TELEPHONE
+#define LC_TELEPHONE (-AST_LC_TELEPHONE)
+#endif
+#ifndef LC_XLITERATE
+#define LC_XLITERATE (-AST_LC_XLITERATE)
+#endif
+#ifndef LC_MEASUREMENT
+#define LC_MEASUREMENT (-AST_LC_MEASUREMENT)
+#endif
+#ifndef LC_PAPER
+#define LC_PAPER (-AST_LC_PAPER)
+#endif
+#ifndef LC_LANG
+#define LC_LANG (-AST_LC_LANG)
+#endif
+
+#undef extern
+
+#undef strcoll
+#if _std_strcoll
+#define strcoll _ast_info.collate
+#else
+#define strcoll strcmp
+#endif
+
+typedef struct
+{
+
+ char* id;
+
+ struct
+ {
+ uint32_t serial;
+ uint32_t set;
+ } locale;
+
+ long tmp_long;
+ size_t tmp_size;
+ short tmp_short;
+ char tmp_char;
+ wchar_t tmp_wchar;
+
+ int (*collate)(const char*, const char*);
+
+ int tmp_int;
+ void* tmp_pointer;
+
+ int mb_cur_max;
+ int (*mb_len)(const char*, size_t);
+ int (*mb_towc)(wchar_t*, const char*, size_t);
+ size_t (*mb_xfrm)(char*, const char*, size_t);
+ int (*mb_width)(wchar_t);
+ int (*mb_conv)(char*, wchar_t);
+
+ uint32_t env_serial;
+ uint32_t mb_sync;
+ uint32_t version;
+
+ int (*mb_alpha)(wchar_t);
+
+ char pad[936 - sizeof(void*)];
+
+} _Ast_info_t;
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+#if !_BLD_ast && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern _Ast_info_t _ast_info;
+
+#undef extern
+
+/* largefile hackery -- ast uses the large versions by default */
+
+#if _typ_off64_t
+#undef off_t
+#define off_t off64_t
+#endif
+#if !defined(ftruncate) && _lib_ftruncate64
+#define ftruncate ftruncate64
+extern int ftruncate64(int, off64_t);
+#endif
+#if !defined(lseek) && _lib_lseek64
+#define lseek lseek64
+extern off64_t lseek64(int, off64_t, int);
+#endif
+#if !defined(truncate) && _lib_truncate64
+#define truncate truncate64
+extern int truncate64(const char*, off64_t);
+#endif
+
+/* direct macro access for bsd crossover */
+
+#if !defined(__cplusplus)
+
+#if !defined(memcpy) && !defined(_lib_memcpy) && defined(_lib_bcopy)
+#define memcpy(t,f,n) (bcopy(f,t,n),(t))
+#endif
+
+#if !defined(memzero) && !defined(_lib_memzero)
+#if defined(_lib_memset) || !defined(_lib_bzero)
+#define memzero(b,n) memset(b,0,n)
+#else
+#define memzero(b,n) (bzero(b,n),(b))
+#endif
+#endif
+
+#endif
+
+#if !defined(remove)
+extern int remove(const char*);
+#endif
+
+#if !defined(rename)
+extern int rename(const char*, const char*);
+#endif
+
+#if !defined(strchr) && !defined(_lib_strchr) && defined(_lib_index)
+#define strchr(s,c) index(s,c)
+#endif
+
+#if !defined(strrchr) && !defined(_lib_strrchr) && defined(_lib_rindex)
+#define strrchr(s,c) rindex(s,c)
+#endif
+
+/* and now introducing prototypes botched by the standard(s) */
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#undef getpgrp
+#define getpgrp() _ast_getpgrp()
+extern int _ast_getpgrp(void);
+
+#undef extern
+
+/*
+ * and finally, standard interfaces hijacked by ast
+ * _AST_STD_I delays headers that require <ast_map.h>
+ */
+
+#include <ast_map.h>
+
+#undef _AST_STD_I
+
+#if _AST_GETOPT_H < 0
+#undef _AST_GETOPT_H
+#include <ast_getopt.h>
+#endif
+
+#if _GETOPT_H < 0
+#undef _GETOPT_H
+#include <getopt.h>
+#endif
+
+#if _REGEX_H < 0
+#undef _REGEX_H
+#include <regex.h>
+#endif
+
+#endif
diff --git a/src/lib/libast/include/ast_windows.h b/src/lib/libast/include/ast_windows.h
new file mode 100644
index 0000000..ed853e9
--- /dev/null
+++ b/src/lib/libast/include/ast_windows.h
@@ -0,0 +1,39 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * AT&T Research
+ *
+ * ast <windows.h> wrapper
+ * for libast only
+ * include after ast headers
+ */
+
+#ifndef _AST_WINDOWS_H
+#define _AST_WINDOWS_H 1
+
+#undef SF_ERROR /* clash in <oaidl.h> */
+
+#include <windows.h>
+
+#endif
diff --git a/src/lib/libast/include/ccode.h b/src/lib/libast/include/ccode.h
new file mode 100644
index 0000000..1335c85
--- /dev/null
+++ b/src/lib/libast/include/ccode.h
@@ -0,0 +1,90 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * character code map interface
+ *
+ * NOTE: used for mapping between 8-bit character encodings
+ * ISO character sets are handled by sfio
+ */
+
+#ifndef _CHARCODE_H
+#define _CHARCODE_H 1
+
+#include <ast_common.h>
+#include <ast_ccode.h>
+
+typedef struct Ccmap_s
+{
+ const char* name; /* code set name */
+ const char* match; /* strmatch() pattern */
+ const char* desc; /* code set description */
+ const char* canon; /* canonical name format */
+ const char* index; /* default index */
+ int ccode; /* <ccode.h> code index */
+ void* data; /* map specific data */
+} Ccmap_t;
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern unsigned char* _ccmap(int, int);
+extern void* _ccmapcpy(unsigned char*, void*, const void*, size_t);
+extern void* _ccmapstr(unsigned char*, void*, size_t);
+
+extern int ccmapid(const char*);
+extern char* ccmapname(int);
+extern void* ccnative(void*, const void*, size_t);
+extern Ccmap_t* ccmaplist(Ccmap_t*);
+
+#undef extern
+
+#define CCOP(i,o) ((i)==(o)?0:(((o)<<8)|(i)))
+#define CCIN(x) ((x)&0xFF)
+#define CCOUT(x) (((x)>>8)&0xFF)
+#define CCCONVERT(x) ((x)&0xFF00)
+
+#define CCCVT(x) CCMAP(x,0)
+#define CCMAP(i,o) ((i)==(o)?(unsigned char*)0:_ccmap(i,o))
+#define CCMAPCHR(m,c) ((m)?(m)[c]:(c))
+#define CCMAPCPY(m,t,f,n) ((m)?_ccmapcpy(m,t,f,n):memcpy(t,f,n))
+#define CCMAPSTR(m,s,n) ((m)?_ccmapstr(m,s,n):(void*)(s))
+
+#define ccmap(i,o) CCMAP(i,o)
+#define ccmapchr(m,c) CCMAPCHR(m,c)
+#define ccmapcpy(m,t,f,n) CCMAPCPY(m,t,f,n)
+#define ccmapstr(m,s,n) CCMAPSTR(m,s,n)
+
+#define CCMAPC(c,i,o) ((i)==(o)?(c):CCMAP(i,o)[c])
+#define CCMAPM(t,f,n,i,o) ((i)==(o)?memcpy(t,f,n):_ccmapcpy(CCMAP(i,o),t,f,n))
+#define CCMAPS(s,n,i,o) ((i)==(o)?(void*)(s):_ccmapstr(CCMAP(i,o),s,n))
+
+#define ccmapc(c,i,o) CCMAPC(c,i,o)
+#define ccmapm(t,f,n,i,o) CCMAPM(t,f,n,i,o)
+#define ccmaps(s,n,i,o) CCMAPS(s,n,i,o)
+
+#endif
diff --git a/src/lib/libast/include/cdt.h b/src/lib/libast/include/cdt.h
new file mode 100644
index 0000000..b757e74
--- /dev/null
+++ b/src/lib/libast/include/cdt.h
@@ -0,0 +1,354 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _CDT_H
+#define _CDT_H 1
+
+/* Public interface for the dictionary library
+**
+** Written by Kiem-Phong Vo
+*/
+
+#ifndef CDT_VERSION
+#ifdef _API_ast
+#define CDT_VERSION _API_ast
+#else
+#define CDT_VERSION 20111111L
+#endif /*_AST_api*/
+#endif /*CDT_VERSION*/
+#ifndef AST_PLUGIN_VERSION
+#define AST_PLUGIN_VERSION(v) (v)
+#endif
+#define CDT_PLUGIN_VERSION AST_PLUGIN_VERSION(20111111L)
+
+#if _PACKAGE_ast
+#include <ast_std.h>
+#else
+#include <ast_common.h>
+#include <string.h>
+#endif
+
+/* commonly used integers */
+#define DT_ZERO ((unsigned int)0) /* all zero bits */
+#define DT_ONES (~DT_ZERO) /* all one bits */
+#define DT_HIBIT (~(DT_ONES >> 1) ) /* highest 1 bit */
+#define DT_LOBIT ((unsigned int)1) /* lowest 1 bit */
+#define DT_NBITS (sizeof(unsigned int)*8) /* #bits */
+
+/* type of an integer with the same size as a pointer */
+#define Dtuint_t uintptr_t
+
+/* various types used by CDT */
+typedef struct _dtlink_s Dtlink_t;
+typedef struct _dthold_s Dthold_t;
+typedef struct _dtdisc_s Dtdisc_t;
+typedef struct _dtmethod_s Dtmethod_t;
+typedef struct _dtdata_s Dtdata_t;
+typedef struct _dtuser_s Dtuser_t;
+typedef struct _dt_s Dt_t;
+typedef struct _dtstat_s Dtstat_t;
+typedef Void_t* (*Dtsearch_f)_ARG_((Dt_t*,Void_t*,int));
+typedef Void_t* (*Dtmake_f)_ARG_((Dt_t*,Void_t*,Dtdisc_t*));
+typedef void (*Dtfree_f)_ARG_((Dt_t*,Void_t*,Dtdisc_t*));
+typedef int (*Dtcompar_f)_ARG_((Dt_t*,Void_t*,Void_t*,Dtdisc_t*));
+typedef unsigned int (*Dthash_f)_ARG_((Dt_t*,Void_t*,Dtdisc_t*));
+typedef Void_t* (*Dtmemory_f)_ARG_((Dt_t*,Void_t*,size_t,Dtdisc_t*));
+typedef int (*Dtevent_f)_ARG_((Dt_t*,int,Void_t*,Dtdisc_t*));
+typedef int (*Dttype_f)_ARG_((Dt_t*,int));
+
+struct _dtuser_s /* for application to access and use */
+{ unsigned int lock; /* used by dtapplock */
+ Void_t* data; /* for whatever data */
+};
+
+struct _dtlink_s
+{
+#if CDT_VERSION < 20111111L
+ Dtlink_t* right; /* right child */
+ union
+ { unsigned int _hash; /* hash value */
+ Dtlink_t* _left; /* left child */
+ } hl;
+#else
+ union
+ { Dtlink_t* __rght; /* right child or next */
+ Dtlink_t* __ptbl; /* Dtrehash parent tbl */
+ } rh;
+ union
+ { Dtlink_t* __left; /* left child or prev */
+ unsigned int __hash; /* hash value of object */
+ } lh;
+#endif
+};
+
+/* private structure to hold an object */
+struct _dthold_s
+{ Dtlink_t hdr; /* header to hold obj */
+ Void_t* obj; /* application object */
+};
+
+/* method to manipulate dictionary structure */
+struct _dtmethod_s
+{ Dtsearch_f searchf; /* search function */
+ unsigned int type; /* type of operation */
+ int (*eventf)_ARG_((Dt_t*, int, Void_t*));
+ char* name; /* name of method */
+ char* description; /* description */
+};
+
+/* structure to hold methods that manipulate an object */
+struct _dtdisc_s
+{ int key; /* where the key resides */
+ int size; /* key size and type */
+ int link; /* offset to Dtlink_t field */
+ Dtmake_f makef; /* object constructor */
+ Dtfree_f freef; /* object destructor */
+ Dtcompar_f comparf;/* to compare two objects */
+ Dthash_f hashf; /* to compute hash value */
+ Dtmemory_f memoryf;/* to allocate/free memory */
+ Dtevent_f eventf; /* to process events */
+};
+
+#define DTDISC(dc,ky,sz,lk,mkf,frf,cmpf,hshf,memf,evf) \
+ ( (dc)->key = (int)(ky), (dc)->size = (int)(sz), (dc)->link = (int)(lk), \
+ (dc)->makef = (mkf), (dc)->freef = (frf), \
+ (dc)->comparf = (cmpf), (dc)->hashf = (hshf), \
+ (dc)->memoryf = (memf), (dc)->eventf = (evf) )
+
+#ifdef offsetof
+#define DTOFFSET(struct_s, member) offsetof(struct_s, member)
+#else
+#define DTOFFSET(struct_s, member) ((int)(&((struct_s*)0)->member))
+#endif
+
+/* the dictionary structure itself */
+struct _dt_s
+{ Dtsearch_f searchf;/* search function */
+ Dtdisc_t* disc; /* object type definitition */
+ Dtdata_t* data; /* sharable data */
+ Dtmemory_f memoryf;/* for memory allocation */
+ Dtmethod_t* meth; /* storage method */
+ ssize_t nview; /* #parent view dictionaries */
+ Dt_t* view; /* next on viewpath */
+ Dt_t* walk; /* dictionary being walked */
+ Dtuser_t* user; /* for user's usage */
+ Dttype_f typef; /* for binary compatibility */
+};
+
+/* structure to get status of a dictionary */
+#define DT_MAXRECURSE 1024 /* limit to avoid stack overflow */
+#define DT_MAXSIZE 256 /* limit for size of below arrays */
+struct _dtstat_s
+{ unsigned int meth; /* method type */
+ ssize_t size; /* total # of elements in dictionary */
+ ssize_t space; /* memory usage of data structure */
+ ssize_t mlev; /* max #levels in tree or hash table */
+ ssize_t msize; /* max #defined elts in below arrays */
+ ssize_t lsize[DT_MAXSIZE]; /* #objects by level */
+ ssize_t tsize[DT_MAXSIZE]; /* #tables by level */
+};
+
+/* supported storage methods */
+#define DT_SET 0000000001 /* unordered set, unique elements */
+#define DT_BAG 0000000002 /* unordered set, repeated elements */
+#define DT_OSET 0000000004 /* ordered set */
+#define DT_OBAG 0000000010 /* ordered multiset */
+#define DT_LIST 0000000020 /* linked list */
+#define DT_STACK 0000000040 /* stack: insert/delete at top */
+#define DT_QUEUE 0000000100 /* queue: insert top, delete at tail */
+#define DT_DEQUE 0000000200 /* deque: insert top, append at tail */
+#define DT_RHSET 0000000400 /* rhset: sharable unique objects */
+#define DT_RHBAG 0000001000 /* rhbag: sharable repeated objects */
+#define DT_METHODS 0000001777 /* all currently supported methods */
+#define DT_ORDERED (DT_OSET|DT_OBAG)
+
+/* asserts to dtdisc() to improve performance when changing disciplines */
+#define DT_SAMECMP 0000000001 /* compare functions are equivalent */
+#define DT_SAMEHASH 0000000002 /* hash functions are equivalent */
+
+/* operation types */
+#define DT_INSERT 0000000001 /* insert object if not found */
+#define DT_DELETE 0000000002 /* delete a matching object if any */
+#define DT_SEARCH 0000000004 /* look for an object */
+#define DT_NEXT 0000000010 /* look for next element */
+#define DT_PREV 0000000020 /* find previous element */
+#define DT_FIRST 0000000200 /* get first object */
+#define DT_LAST 0000000400 /* get last object */
+#define DT_MATCH 0000001000 /* find object matching key */
+#define DT_ATTACH 0000004000 /* attach an object to dictionary */
+#define DT_DETACH 0000010000 /* detach an object from dictionary */
+#define DT_APPEND 0000020000 /* append an object */
+#define DT_ATLEAST 0000040000 /* find the least elt >= object */
+#define DT_ATMOST 0000100000 /* find the biggest elt <= object */
+#define DT_REMOVE 0002000000 /* remove a specific object */
+#define DT_TOANNOUNCE (DT_INSERT|DT_DELETE|DT_SEARCH|DT_NEXT|DT_PREV|DT_FIRST|DT_LAST|DT_MATCH|DT_ATTACH|DT_DETACH|DT_APPEND|DT_ATLEAST|DT_ATMOST|DT_REMOVE)
+
+#define DT_RELINK 0000002000 /* re-inserting (dtdisc,dtmethod...) */
+#define DT_FLATTEN 0000000040 /* flatten objects into a list */
+#define DT_CLEAR 0000000100 /* clearing all objects */
+#define DT_EXTRACT 0000200000 /* FLATTEN and clear dictionary */
+#define DT_RESTORE 0000400000 /* reinsert a list of elements */
+#define DT_STAT 0001000000 /* get statistics of dictionary */
+#define DT_OPERATIONS (DT_TOANNOUNCE|DT_RELINK|DT_FLATTEN|DT_CLEAR|DT_EXTRACT|DT_RESTORE|DT_STAT)
+
+/* these bits may combine with the DT_METHODS and DT_OPERATIONS bits */
+#define DT_INDATA 0010000000 /* Dt_t was allocated with Dtdata_t */
+#define DT_SHARE 0020000000 /* concurrent access mode */
+#define DT_ANNOUNCE 0040000000 /* announcing a successful operation */
+ /* the actual event will be this bit */
+ /* combined with the operation bit */
+#define DT_OPTIMIZE 0100000000 /* optimizing data structure */
+
+/* events for discipline and method event-handling functions */
+#define DT_OPEN 1 /* a dictionary is being opened */
+#define DT_ENDOPEN 5 /* end of dictionary opening */
+#define DT_CLOSE 2 /* a dictionary is being closed */
+#define DT_ENDCLOSE 6 /* end of dictionary closing */
+#define DT_DISC 3 /* discipline is about to be changed */
+#define DT_METH 4 /* method is about to be changed */
+#define DT_HASHSIZE 7 /* initialize hash table size */
+#define DT_ERROR 0xbad /* announcing an error */
+
+_BEGIN_EXTERNS_ /* data structures and functions */
+#if _BLD_cdt && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+#if !_BLD_cdt && defined(__IMPORT__)
+#define extern __IMPORT__
+#endif
+
+extern Dtmethod_t* Dtset;
+extern Dtmethod_t* Dtbag;
+extern Dtmethod_t* Dtoset;
+extern Dtmethod_t* Dtobag;
+extern Dtmethod_t* Dtlist;
+extern Dtmethod_t* Dtstack;
+extern Dtmethod_t* Dtqueue;
+extern Dtmethod_t* Dtdeque;
+
+#if _PACKAGE_ast /* dtplugin() for proprietary and non-standard methods -- requires -ldll */
+
+#define dtplugin(name) ((Dtmethod_t*)dllmeth("cdt", name, CDT_PLUGIN_VERSION))
+
+#define Dtrhbag dtplugin("rehash:Dtrhbag")
+#define Dtrhset dtplugin("rehash:Dtrhset")
+
+#else
+
+#if CDTPROPRIETARY
+
+extern Dtmethod_t* Dtrhset;
+extern Dtmethod_t* Dtrhbag;
+
+#endif /*CDTPROPRIETARY*/
+
+#endif /*_PACKAGE_ast*/
+
+#undef extern
+
+#if _BLD_cdt && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern Dt_t* dtopen _ARG_((Dtdisc_t*, Dtmethod_t*));
+extern int dtclose _ARG_((Dt_t*));
+extern Dt_t* dtview _ARG_((Dt_t*, Dt_t*));
+extern Dtdisc_t* dtdisc _ARG_((Dt_t* dt, Dtdisc_t*, int));
+extern Dtmethod_t* dtmethod _ARG_((Dt_t*, Dtmethod_t*));
+extern int dtwalk _ARG_((Dt_t*, int(*)(Dt_t*,Void_t*,Void_t*), Void_t*));
+extern int dtcustomize _ARG_((Dt_t*, int, int));
+extern unsigned int dtstrhash _ARG_((unsigned int, Void_t*, ssize_t));
+extern int dtuserlock _ARG_((Dt_t*, unsigned int, int));
+extern Void_t* dtuserdata _ARG_((Dt_t*, Void_t*, unsigned int));
+
+/* deal with upward binary compatibility (operation bit translation, etc.) */
+extern Dt_t* _dtopen _ARG_((Dtdisc_t*, Dtmethod_t*, unsigned long));
+#define dtopen(dc,mt) _dtopen((dc), (mt), CDT_VERSION)
+
+#undef extern
+
+#if _PACKAGE_ast && !defined(_CDTLIB_H)
+
+#if _BLD_dll && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern void* dllmeth(const char*, const char*, unsigned long);
+
+#undef extern
+
+#endif
+
+_END_EXTERNS_
+
+/* internal functions for translating among holder, object and key */
+#define _DT(dt) ((Dt_t*)(dt))
+
+#define _DTLNK(dc,o) ((Dtlink_t*)((char*)(o) + (dc)->link) ) /* get link from obj */
+
+#define _DTO(dc,l) (Void_t*)((char*)(l) - (dc)->link) /* get object from link */
+#define _DTOBJ(dc,l) ((dc)->link >= 0 ? _DTO(dc,l) : ((Dthold_t*)(l))->obj )
+
+#define _DTK(dc,o) ((char*)(o) + (dc)->key) /* get key from object */
+#define _DTKEY(dc,o) (Void_t*)((dc)->size >= 0 ? _DTK(dc,o) : *((char**)_DTK(dc,o)) )
+
+#define _DTCMP(dt,k1,k2,dc) \
+ ((dc)->comparf ? (*(dc)->comparf)((dt), (k1), (k2), (dc)) : \
+ (dc)->size > 0 ? memcmp((Void_t*)(k1), ((Void_t*)k2), (dc)->size) : \
+ strcmp((char*)(k1), ((char*)k2)) )
+
+#define _DTHSH(dt,ky,dc) ((dc)->hashf ? (*(dc)->hashf)((dt), (ky), (dc)) : \
+ dtstrhash(0, (ky), (dc)->size) )
+
+#define dtvnext(d) (_DT(d)->view)
+#define dtvcount(d) (_DT(d)->nview)
+#define dtvhere(d) (_DT(d)->walk)
+
+#define dtlink(d,e) (((Dtlink_t*)(e))->rh.__rght)
+#define dtobj(d,e) _DTOBJ(_DT(d)->disc, (e))
+
+#define dtfirst(d) (*(_DT(d)->searchf))((d),(Void_t*)(0),DT_FIRST)
+#define dtnext(d,o) (*(_DT(d)->searchf))((d),(Void_t*)(o),DT_NEXT)
+#define dtatleast(d,o) (*(_DT(d)->searchf))((d),(Void_t*)(o),DT_ATLEAST)
+#define dtlast(d) (*(_DT(d)->searchf))((d),(Void_t*)(0),DT_LAST)
+#define dtprev(d,o) (*(_DT(d)->searchf))((d),(Void_t*)(o),DT_PREV)
+#define dtatmost(d,o) (*(_DT(d)->searchf))((d),(Void_t*)(o),DT_ATMOST)
+#define dtsearch(d,o) (*(_DT(d)->searchf))((d),(Void_t*)(o),DT_SEARCH)
+#define dtmatch(d,o) (*(_DT(d)->searchf))((d),(Void_t*)(o),DT_MATCH)
+#define dtinsert(d,o) (*(_DT(d)->searchf))((d),(Void_t*)(o),DT_INSERT)
+#define dtappend(d,o) (*(_DT(d)->searchf))((d),(Void_t*)(o),DT_APPEND)
+#define dtdelete(d,o) (*(_DT(d)->searchf))((d),(Void_t*)(o),DT_DELETE)
+#define dtremove(d,o) (*(_DT(d)->searchf))((d),(Void_t*)(o),DT_REMOVE)
+#define dtattach(d,o) (*(_DT(d)->searchf))((d),(Void_t*)(o),DT_ATTACH)
+#define dtdetach(d,o) (*(_DT(d)->searchf))((d),(Void_t*)(o),DT_DETACH)
+#define dtclear(d) (*(_DT(d)->searchf))((d),(Void_t*)(0),DT_CLEAR)
+
+#define dtflatten(d) (Dtlink_t*)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_FLATTEN)
+#define dtextract(d) (Dtlink_t*)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_EXTRACT)
+#define dtrestore(d,l) (Dtlink_t*)(*(_DT(d)->searchf))((d),(Void_t*)(l),DT_RESTORE)
+
+#define dtstat(d,s) (ssize_t)(*(_DT(d)->searchf))((d),(Void_t*)(s),DT_STAT)
+#define dtsize(d) (ssize_t)(*(_DT(d)->searchf))((d),(Void_t*)(0),DT_STAT)
+
+#define DT_PRIME 17109811 /* 2#00000001 00000101 00010011 00110011 */
+#define dtcharhash(h,c) (((unsigned int)(h) + (unsigned int)(c)) * DT_PRIME )
+
+#endif /* _CDT_H */
diff --git a/src/lib/libast/include/cmdarg.h b/src/lib/libast/include/cmdarg.h
new file mode 100644
index 0000000..94ad39e
--- /dev/null
+++ b/src/lib/libast/include/cmdarg.h
@@ -0,0 +1,92 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * xargs/tw command arg list interface definitions
+ */
+
+#ifndef _CMDARG_H
+#define _CMDARG_H
+
+#include <error.h>
+
+#define CMD_CHECKED (1<<9) /* cmdopen() argv[0] ok */
+#define CMD_EMPTY (1<<0) /* run once, even if no args */
+#define CMD_EXACT (1<<1) /* last command must have argmax*/
+#define CMD_EXIT (1<<11) /* fatal error_info.exit() */
+#define CMD_IGNORE (1<<2) /* ignore EXIT_QUIT exit */
+#define CMD_INSERT (1<<3) /* argpat for insertion */
+#define CMD_MINIMUM (1<<4) /* argmax is a minimum */
+#define CMD_NEWLINE (1<<5) /* echo separator is newline */
+#define CMD_POST (1<<6) /* argpat is post arg position */
+#define CMD_QUERY (1<<7) /* trace and query each command */
+#define CMD_SILENT (1<<10) /* no error messages */
+#define CMD_TRACE (1<<8) /* trace each command */
+
+#define CMD_USER (1<<12)
+
+typedef struct Cmdarg_s /* cmd + args info */
+{
+ struct
+ {
+ size_t args; /* total args */
+ size_t commands; /* total commands */
+ } total;
+
+ Error_f errorf; /* optional error callback */
+
+ int argcount; /* current arg count */
+ int argmax; /* max # args */
+ int echo; /* just an echo */
+ int flags; /* CMD_* flags */
+ int insertlen; /* strlen(insert) */
+ int offset; /* post arg offset */
+
+ char** argv; /* exec argv */
+ char** firstarg; /* first argv file arg */
+ char** insertarg; /* argv before insert */
+ char** postarg; /* start of post arg list */
+ char** nextarg; /* next argv file arg */
+ char* nextstr; /* next string ends before here */
+ char* laststr; /* last string ends before here */
+ char* insert; /* replace with current arg */
+ char buf[1]; /* argv and arg buffer */
+} Cmdarg_t;
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#ifndef cmdopen
+extern Cmdarg_t* cmdopen(char**, int, int, const char*, int);
+#endif
+extern Cmdarg_t* cmdopen_20110505(char**, int, int, const char*, int, Error_f);
+extern int cmdflush(Cmdarg_t*);
+extern int cmdarg(Cmdarg_t*, const char*, int);
+extern int cmdclose(Cmdarg_t*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/debug.h b/src/lib/libast/include/debug.h
new file mode 100644
index 0000000..994fedb
--- /dev/null
+++ b/src/lib/libast/include/debug.h
@@ -0,0 +1,109 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * common ast debug definitions
+ * include after the ast headers
+ */
+
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+#include <ast.h>
+#include <error.h>
+
+#if !defined(DEBUG) && _BLD_DEBUG
+#define DEBUG _BLD_DEBUG
+#endif
+
+#if DEBUG || _BLD_DEBUG
+
+#define debug(x) x
+#define message(x) do if (error_info.trace < 0) { error x; } while (0)
+#define messagef(x) do if (error_info.trace < 0) { errorf x; } while (0)
+
+#define DEBUG_BEGTIME() debug_elapsed(1)
+#define DEBUG_GETTIME() debug_elapsed(0)
+#define DEBUG_ASSERT(p) ((p) ? 0 : (debug_fatal(__FILE__, __LINE__),0))
+#define DEBUG_COUNT(n) ((n) += 1)
+#define DEBUG_TALLY(c,n,v) ((c) ? ((n) += (v)) : (n))
+#define DEBUG_INCREASE(n) ((n) += 1)
+#define DEBUG_DECREASE(n) ((n) -= 1)
+#define DEBUG_DECLARE(t,v) t v
+#define DEBUG_SET(n,v) ((n) = (v))
+#define DEBUG_PRINT(fd,s,v) do {char _b[1024];write(fd,_b,sfsprintf(_b,sizeof(_b),s,v));} while(0)
+#define DEBUG_WRITE(fd,d,n) write((fd),(d),(n))
+#define DEBUG_TEMP(temp) (temp) /* debugging stuff that should be removed */
+#define DEBUG_BREAK break
+#define DEBUG_CONTINUE continue
+#define DEBUG_GOTO(label) do { debug_fatal(__FILE__, __LINE__); goto label; } while(0)
+#define DEBUG_RETURN(x) do { debug_fatal(__FILE__, __LINE__); return(x); } while(0)
+
+#else
+
+#define debug(x)
+#define message(x)
+#define messagef(x)
+
+#define DEBUG_BEGTIME()
+#define DEBUG_GETTIME()
+#define DEBUG_ASSERT(p)
+#define DEBUG_COUNT(n)
+#define DEBUG_TALLY(c,n,v)
+#define DEBUG_INCREASE(n)
+#define DEBUG_DECREASE(n)
+#define DEBUG_DECLARE(t,v)
+#define DEBUG_SET(n,v)
+#define DEBUG_PRINT(fd,s,v)
+#define DEBUG_WRITE(fd,d,n)
+#define DEBUG_TEMP(x)
+#define DEBUG_BREAK break
+#define DEBUG_CONTINUE continue
+#define DEBUG_GOTO(label) goto label
+#define DEBUG_RETURN(x) return(x)
+
+#endif
+
+#ifndef BREAK
+#define BREAK DEBUG_BREAK
+#endif
+#ifndef CONTINUE
+#define CONTINUE DEBUG_CONTINUE
+#endif
+#ifndef GOTO
+#define GOTO(label) DEBUG_GOTO(label)
+#endif
+#ifndef RETURN
+#define RETURN(x) DEBUG_RETURN(x)
+#endif
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern double debug_elapsed(int);
+extern void debug_fatal(const char*, int);
+extern void systrace(const char*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/dt.h b/src/lib/libast/include/dt.h
new file mode 100644
index 0000000..acc6713
--- /dev/null
+++ b/src/lib/libast/include/dt.h
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _DT_H
+#define _DT_H 1
+
+#include <cdt.h>
+#include <vmalloc.h>
+
+#if _BLD_cdt && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern Dt_t* dtnew(Vmalloc_t*, Dtdisc_t*, Dtmethod_t*);
+extern Dt_t* _dtnew(Vmalloc_t*, Dtdisc_t*, Dtmethod_t*, unsigned long);
+
+#undef extern
+
+#define dtnew(v,d,m) _dtnew(v,d,m,CDT_VERSION)
+
+#endif
diff --git a/src/lib/libast/include/error.h b/src/lib/libast/include/error.h
new file mode 100644
index 0000000..0253e4d
--- /dev/null
+++ b/src/lib/libast/include/error.h
@@ -0,0 +1,182 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * option, error and message formatter external definitions
+ */
+
+#ifndef _ERROR_H
+#define _ERROR_H
+
+#include <ast.h>
+#include <option.h>
+#include <errno.h>
+
+#define ERROR_VERSION 20070319L
+
+#if !defined(errno) && defined(__DYNAMIC__)
+#define errno __DYNAMIC__(errno)
+#endif
+
+#define ERROR_debug(n) (-(n))
+#define ERROR_exit(n) ((n)+ERROR_ERROR)
+#define ERROR_system(n) (((n)+ERROR_ERROR)|ERROR_SYSTEM)
+#define ERROR_usage(n) ((((n)?2:0)+ERROR_ERROR)|ERROR_USAGE)
+#define ERROR_warn(n) (ERROR_WARNING)
+
+#ifndef ERROR_catalog
+#define ERROR_catalog(t) t
+#endif
+#ifndef ERROR_dictionary
+#define ERROR_dictionary(t) t
+#endif
+
+#ifndef ERROR_translate
+#define ERROR_translating() (error_info.translate&&(ast.locale.set&(1<<AST_LC_MESSAGES)))
+#define ERROR_translate(l,i,d,m) (ERROR_translating()?errorx((const char*)(l),(const char*)(i),(const char*)(d),(const char*)(m)):(char*)(m))
+#endif
+
+#define ERROR_INFO 0 /* info message -- no err_id */
+#define ERROR_WARNING 1 /* warning message */
+#define ERROR_ERROR 2 /* error message -- no err_exit */
+#define ERROR_FATAL 3 /* error message with err_exit */
+#define ERROR_NOEXEC EXIT_NOEXEC /* shell convention */
+#define ERROR_NOENT EXIT_NOTFOUND /* shell convention */
+#define ERROR_PANIC ERROR_LEVEL /* panic message with err_exit */
+
+#define ERROR_LEVEL 0x00ff /* level portion of status */
+#define ERROR_SYSTEM 0x0100 /* report system errno message */
+#define ERROR_OUTPUT 0x0200 /* next arg is error fd */
+#define ERROR_SOURCE 0x0400 /* next 2 args are FILE,LINE */
+#define ERROR_USAGE 0x0800 /* usage message */
+#define ERROR_PROMPT 0x1000 /* omit trailing newline */
+#define ERROR_NOID 0x2000 /* omit err_id */
+#define ERROR_LIBRARY 0x4000 /* library routine error */
+
+#define ERROR_INTERACTIVE 0x0001 /* context is interactive */
+#define ERROR_SILENT 0x0002 /* context is silent */
+#define ERROR_NOTIFY 0x0004 /* main(-sig,0,ctx) on signal */
+
+#define ERROR_FREE 0x0010 /* free context on pop */
+#define ERROR_POP 0x0020 /* pop context */
+#define ERROR_PUSH 0x0040 /* push context */
+#define ERROR_SET 0x0080 /* set context */
+
+/*
+ * errorpush()/errorpop() are obsolete -- use errorctx() instead
+ */
+
+#ifndef ERROR_CONTEXT_T
+#define ERROR_CONTEXT_T Error_info_t
+#endif
+
+#define ERROR_CONTEXT_BASE ((Error_context_t*)&error_info.context)
+
+#define errorpush(p,f) (*(p)=*ERROR_CONTEXT_BASE,*ERROR_CONTEXT_BASE=error_info.empty,error_info.context=(Error_context_t*)(p),error_info.flags=(f))
+#define errorpop(p) (*ERROR_CONTEXT_BASE=*(p))
+
+typedef struct Error_info_s Error_info_t;
+typedef struct Error_context_s Error_context_t;
+
+#define ERROR_CONTEXT \
+ ERROR_CONTEXT_T* context; /* prev context stack element */ \
+ int errors; /* >= ERROR_ERROR count */ \
+ int flags; /* context flags */ \
+ int line; /* input|output line number */ \
+ int warnings; /* ERROR_WARNING count */ \
+ char* file; /* input|output file name */ \
+ char* id; /* command id */
+
+struct Error_context_s /* context stack element */
+{
+ ERROR_CONTEXT
+};
+
+struct Error_info_s /* error state */
+{
+ int fd; /* write(2) fd */
+
+ void (*exit)(int); /* error exit */
+ ssize_t (*write)(int, const void*, size_t); /* error output */
+
+ /* the rest are implicitly initialized */
+
+ int clear; /* default clear ERROR_* flags */
+ int core; /* level>=core -> core dump */
+ int indent; /* debug trace indent level */
+ int init; /* initialized */
+ int last_errno; /* last reported errno */
+ int mask; /* multi level debug trace mask */
+ int set; /* default set ERROR_* flags */
+ int trace; /* debug trace level */
+
+ char* version; /* ERROR_SOURCE command version */
+
+ int (*auxilliary)(Sfio_t*, int, int); /* aux info to append */
+
+ ERROR_CONTEXT /* top of context stack */
+
+ Error_context_t empty; /* empty context stack element */
+
+ unsigned long time; /* debug time trace */
+
+ char* (*translate)(const char*, const char*, const char*, const char*); /* format translator */
+
+ const char* catalog; /* message catalog */
+};
+
+#ifndef errno
+extern int errno; /* system call error status */
+#endif
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+#if !_BLD_ast && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern Error_info_t* _error_infop_;
+
+#define error_info (*_error_infop_)
+
+#undef extern
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern void error(int, ...);
+extern int errormsg(const char*, int, ...);
+extern int errorf(void*, void*, int, ...);
+extern void errorv(const char*, int, va_list);
+#ifndef errorx
+extern char* errorx(const char*, const char*, const char*, const char*);
+#endif
+extern Error_info_t* errorctx(Error_info_t*, int, int);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/find.h b/src/lib/libast/include/find.h
new file mode 100644
index 0000000..81049be
--- /dev/null
+++ b/src/lib/libast/include/find.h
@@ -0,0 +1,86 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * fast find interface definitions
+ */
+
+#ifndef _FIND_H
+#define _FIND_H
+
+#define FIND_VERSION 19980301L
+
+#ifndef FIND_CODES
+#define FIND_CODES "lib/find/codes"
+#endif
+
+#define FIND_CODES_ENV "FINDCODES"
+
+#define FIND_GENERATE (1<<0) /* generate new codes */
+#define FIND_ICASE (1<<1) /* ignore case in match */
+#define FIND_GNU (1<<2) /* generate gnu format codes */
+#define FIND_OLD (1<<3) /* generate old format codes */
+#define FIND_TYPE (1<<4) /* generate type with codes */
+#define FIND_VERIFY (1<<5) /* verify the dir hierarchy */
+
+#define FIND_USER (1L<<16) /* first user flag bit */
+
+struct Find_s;
+struct Finddisc_s;
+
+typedef int (*Findverify_f)(struct Find_s*, const char*, size_t, struct Finddisc_s*);
+
+typedef struct Finddisc_s
+{
+ unsigned long version; /* interface version */
+ unsigned long flags; /* FIND_* flags */
+ Error_f errorf; /* error function */
+ Findverify_f verifyf; /* dir verify function */
+ char** dirs; /* dir prefixes to search */
+} Finddisc_t;
+
+typedef struct Find_s
+{
+ const char* id; /* library id string */
+ unsigned long stamp; /* codes time stamp */
+
+#ifdef _FIND_PRIVATE_
+ _FIND_PRIVATE_
+#endif
+
+} Find_t;
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern Find_t* findopen(const char*, const char*, const char*, Finddisc_t*);
+extern char* findread(Find_t*);
+extern int findwrite(Find_t*, const char*, size_t, const char*);
+extern int findclose(Find_t*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/fnv.h b/src/lib/libast/include/fnv.h
new file mode 100644
index 0000000..793dde0
--- /dev/null
+++ b/src/lib/libast/include/fnv.h
@@ -0,0 +1,72 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * Landon Kurt Knoll
+ * Phong Vo
+ *
+ * FNV-1 linear congruent checksum/hash/PRNG
+ * see http://www.isthe.com/chongo/tech/comp/fnv/
+ */
+
+#ifndef _FNV_H
+#define _FNV_H
+
+#include <ast_common.h>
+
+#define FNV_INIT 0x811c9dc5L
+#define FNV_MULT 0x01000193L
+
+#define FNVINIT(h) (h = FNV_INIT)
+#define FNVPART(h,c) (h = (h) * FNV_MULT ^ (c))
+#define FNVSUM(h,s,n) do { \
+ register size_t _i_ = 0; \
+ while (_i_ < n) \
+ FNVPART(h, ((unsigned char*)s)[_i_++]); \
+ } while (0)
+
+#if _typ_int64_t
+
+#ifdef _ast_LL
+
+#define FNV_INIT64 0xcbf29ce484222325LL
+#define FNV_MULT64 0x00000100000001b3LL
+
+#else
+
+#define FNV_INIT64 ((int64_t)0xcbf29ce484222325)
+#define FNV_MULT64 ((int64_t)0x00000100000001b3)
+
+#endif
+
+#define FNVINIT64(h) (h = FNV_INIT64)
+#define FNVPART64(h,c) (h = (h) * FNV_MULT64 ^ (c))
+#define FNVSUM64(h,s,n) do { \
+ register int _i_ = 0; \
+ while (_i_ < n) \
+ FNVPART64(h, ((unsigned char*)s)[_i_++]); \
+ } while (0)
+
+#endif
+
+#endif
diff --git a/src/lib/libast/include/fs3d.h b/src/lib/libast/include/fs3d.h
new file mode 100644
index 0000000..9d3c992
--- /dev/null
+++ b/src/lib/libast/include/fs3d.h
@@ -0,0 +1,117 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * 3d fs interface definitions
+ */
+
+#ifndef _FS3D_H
+#define _FS3D_H
+
+#include <ast_fs.h>
+
+#if _int_st_spare1
+#define iview(p) ((p)->st_spare1)
+#define IVIEW(p,v) ((p)->st_spare1=(v))
+#else
+#if _ary_st_spare4
+#define iview(p) ((p)->st_spare4[0])
+#define IVIEW(p,v) ((p)->st_spare4[0]=(v))
+#else
+#if _ary_st_extra
+#define iview(p) ((p)->st_extra[0])
+#define IVIEW(p,v) ((p)->st_extra[0]=(v))
+#else
+#if _ary_st_pad4
+#define iview(p) ((p)->st_pad4[0])
+#define IVIEW(p,v) ((p)->st_pad4[0]=(v))
+#else
+#if _mem_st_rdev_stat
+#define iview(p) ((S_ISBLK((p)->st_mode)||S_ISCHR((p)->st_mode))?0:(p)->st_rdev)
+#define IVIEW(p,v) do{if(!S_ISBLK((p)->st_mode)&&!S_ISCHR((p)->st_mode))(p)->st_rdev=(v);}while(0)
+#else
+#define iview(p) 0
+#define IVIEW(p,v)
+#endif
+#endif
+#endif
+#endif
+#endif
+
+/*
+ * special options
+ */
+
+#define FS3D_init "/#option/init"
+#define FS3D_on "/#option/3d"
+#define FS3D_off "/#option/2d"
+
+/*
+ * fs3d(3) ops
+ */
+
+#define FS3D_OP(o,a) (((a)<<3)|(o))
+
+#define FS3D_INIT FS3D_OP_INIT /* re-initialize tables */
+#define FS3D_OFF FS3D_OP_OFF
+#define FS3D_ON FS3D_OP_ON
+#define FS3D_TEST FS3D_OP_TEST
+#define FS3D_LIMIT(n) FS3D_OP(FS3D_OP_LIMIT,n)
+
+#define FS3D_op(x) ((x)&07)
+#define FS3D_arg(x) (((x)>>3)&07777)
+
+#define FS3D_OP_OFF 0
+#define FS3D_OP_ON 1
+#define FS3D_OP_TEST 2
+#define FS3D_OP_LIMIT 3
+#define FS3D_OP_INIT 7
+
+/*
+ * mount(2) ops
+ */
+
+#define FS3D_ALL (FS3D_VIEW|FS3D_VERSION)
+#define FS3D_VIEW 002
+#define FS3D_VERSION 004
+#define FS3D_GET 010
+#define FS3D_SIZE(n) ((n)<<4)
+#define FS3D_SIZEOF(n) ((n)>>4)
+
+#if !_BLD_3d
+#define mount(s,t,f,d) fs3d_mount(s,t,f,d)
+#endif
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int fs3d(int);
+extern int fs3d_mount(const char*, char*, int, void*);
+extern char* pathnext(char*, char*, long*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/fts.h b/src/lib/libast/include/fts.h
new file mode 100644
index 0000000..3a22ad2
--- /dev/null
+++ b/src/lib/libast/include/fts.h
@@ -0,0 +1,162 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * David Korn
+ * Phong Vo
+ * AT&T Research
+ *
+ * fts interface definitions
+ */
+
+#ifndef _FTS_H
+#define _FTS_H
+
+#include <ast_std.h>
+#include <ast_fs.h>
+#include <ast_mode.h>
+
+/*
+ * fts_open flags
+ */
+
+#define FTS_LOGICAL 0 /* logical traversal, follow symlinks */
+#define FTS_META (1<<0) /* follow top dir symlinks even if phys */
+#define FTS_NOCHDIR (1<<1) /* don't chdir */
+#define FTS_NOPOSTORDER (1<<2) /* no postorder visits */
+#define FTS_NOPREORDER (1<<3) /* no preorder visits */
+#define FTS_NOSEEDOTDIR (1<<11) /* never retain leading . dir */
+#define FTS_NOSTAT (1<<4) /* don't stat children */
+#define FTS_ONEPATH (1<<5) /* pathnames arg is one const char* */
+#define FTS_PHYSICAL (1<<6) /* physical traversal, don't follow */
+#define FTS_SEEDOT (1<<7) /* return . and .. */
+#define FTS_SEEDOTDIR (1<<10) /* always retain leading . dir */
+#define FTS_TOP (1<<8) /* don't traverse subdirectories */
+#define FTS_XDEV (1<<9) /* don't cross mount points */
+
+#define FTS_USER (1<<12) /* first user flag bit */
+
+#define FTS_COMFOLLOW FTS_META
+
+/*
+ * fts_info flags
+ */
+
+#define FTS_DEFAULT 0 /* ok, someone must have wanted this */
+
+#define FTS_NS (1<<0) /* stat failed */
+#define FTS_F (1<<1) /* file - not directory or symbolic link*/
+#define FTS_SL (1<<2) /* symbolic link */
+#define FTS_D (1<<3) /* directory - pre-order visit */
+
+#define FTS_C (1<<4) /* causes cycle */
+#define FTS_ERR (1<<5) /* some other error */
+#define FTS_DD (1<<6) /* . or .. */
+#define FTS_NR (1<<7) /* cannot read */
+#define FTS_NX (1<<8) /* cannot search */
+#define FTS_OK (1<<9) /* no info but otherwise ok */
+#define FTS_P (1<<10) /* post-order visit */
+
+#define FTS_DC (FTS_D|FTS_C) /* dir - would cause cycle */
+#define FTS_DNR (FTS_D|FTS_NR) /* dir - no read permission */
+#define FTS_DNX (FTS_D|FTS_NX) /* dir - no search permission */
+#define FTS_DOT (FTS_D|FTS_DD) /* . or .. */
+#define FTS_DP (FTS_D|FTS_P) /* dir - post-order visit */
+#define FTS_NSOK (FTS_NS|FTS_OK) /* no stat (because you asked) */
+#define FTS_SLNONE (FTS_SL|FTS_NS) /* symlink - to nowhere */
+
+/*
+ * fts_set flags
+ */
+
+#define FTS_AGAIN FTS_TOP /* process entry again */
+#define FTS_FOLLOW FTS_META /* follow FTS_SL symlink */
+#define FTS_SKIP FTS_NOSTAT /* skip FTS_D directory */
+#define FTS_STAT FTS_PHYSICAL /* stat() done by user */
+
+typedef struct Fts FTS;
+typedef struct Ftsent FTSENT;
+
+struct Ftsent
+{
+ char* fts_accpath; /* path relative to . */
+ char* fts_name; /* file name */
+ char* fts_path; /* path relative to top dir */
+ FTSENT* fts_cycle; /* offender if cycle */
+ FTSENT* fts_link; /* next child */
+ FTSENT* fts_parent; /* parent directory */
+ struct stat* fts_statp; /* stat info */
+#ifdef _FTSENT_LOCAL_PRIVATE_
+ _FTSENT_LOCAL_PRIVATE_
+#else
+ void* fts_pointer; /* local pointer value */
+#endif
+ long fts_number; /* local numeric value */
+ int fts_errno; /* errno for this entry */
+ unsigned short fts_info; /* info flags */
+
+ unsigned short _fts_namelen; /* old fts_namelen */
+ unsigned short _fts_pathlen; /* old fts_pathlen */
+ short _fts_level; /* old fts_level */
+
+ short _fts_status; /* <ftwalk.h> compatibility */
+ struct stat _fts_statb; /* <ftwalk.h> compatibility */
+
+ FTS* fts; /* fts_open() handle */
+ size_t fts_namelen; /* strlen(fts_name) */
+ size_t fts_pathlen; /* strlen(fts_path) */
+ ssize_t fts_level; /* file tree depth, 0 at top */
+
+#ifdef _FTSENT_PRIVATE_
+ _FTSENT_PRIVATE_
+#endif
+
+};
+
+struct Fts
+{
+ int fts_errno; /* last errno */
+ void* fts_handle; /* user defined handle */
+
+#ifdef _FTS_PRIVATE_
+ _FTS_PRIVATE_
+#endif
+
+};
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern FTSENT* fts_children(FTS*, int);
+extern int fts_close(FTS*);
+extern int fts_flags(void);
+extern int fts_local(FTSENT*);
+extern int fts_notify(int(*)(FTS*, FTSENT*, void*), void*);
+extern FTS* fts_open(char* const*, int, int(*)(FTSENT* const*, FTSENT* const*));
+extern FTSENT* fts_read(FTS*);
+extern int fts_set(FTS*, FTSENT*, int);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/ftwalk.h b/src/lib/libast/include/ftwalk.h
new file mode 100644
index 0000000..a4f3955
--- /dev/null
+++ b/src/lib/libast/include/ftwalk.h
@@ -0,0 +1,124 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Phong Vo
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * ast ftwalk interface definitions
+ * ftwalk was the initial improvement on ftw and nftw
+ * which formed the basis for the POSIX fts proposal
+ *
+ * NOTE: this file is in cahoots with the fts implementation
+ */
+
+#ifndef _FTWALK_H
+#define _FTWALK_H
+
+#define fts_info info
+#define fts_level level
+#define fts_link link
+#define fts_name name
+#define fts_namelen namelen
+#define fts_parent parent
+#define fts_path path
+#define fts_pathlen pathlen
+#define _fts_status status
+#define _fts_statb statb
+
+#define FTSENT Ftw_t /* <fts.h> internal */
+#define Ftsent FTW /* <fts.h> internal */
+
+#define _FTSENT_LOCAL_PRIVATE_ /* <fts.h> internal */ \
+ union \
+ { \
+ long number; /* local numeric value */ \
+ void* pointer; /* local pointer value */ \
+ } local;
+
+#include <fts.h>
+
+/*
+ * ftwalk() argument flags
+ */
+
+#define FTW_CANON FTS_CANON
+#define FTW_CHILDREN (FTS_USER<<0)
+#define FTW_DELAY FTS_NOSTAT
+#define FTW_DOT FTS_NOCHDIR
+#define FTW_META FTS_META
+#define FTW_MOUNT FTS_XDEV
+#define FTW_MULTIPLE FTS_ONEPATH
+#define FTW_NOSEEDOTDIR FTS_NOSEEDOTDIR
+#define FTW_PHYSICAL FTS_PHYSICAL
+#define FTW_POST (FTS_USER<<1)
+#define FTW_SEEDOTDIR FTS_SEEDOTDIR
+#define FTW_TOP FTS_TOP
+#define FTW_TWICE (FTS_USER<<2)
+#define FTW_USER (FTS_USER<<3)
+
+/*
+ * Ftw_t.info type bits
+ */
+
+#define FTW_C FTS_C
+#define FTW_D FTS_D
+#define FTW_DC FTS_DC
+#define FTW_DNR FTS_DNR
+#define FTW_DNX FTS_DNX
+#define FTW_DP FTS_DP
+#define FTW_F FTS_F
+#define FTW_NR FTS_NR
+#define FTW_NS FTS_NS
+#define FTW_NSOK FTS_NSOK
+#define FTW_NX FTS_NX
+#define FTW_P FTS_P
+#define FTW_SL FTS_SL
+
+/*
+ * Ftw_t.status entry values
+ */
+
+#define FTW_NAME FTS_DOT /* access by Ftw_t.name */
+#define FTW_PATH FTS_NOCHDIR /* access by Ftw_t.path */
+
+/*
+ * Ftw_t.status return values
+ */
+
+#define FTW_AGAIN FTS_AGAIN
+#define FTW_FOLLOW FTS_FOLLOW
+#define FTW_NOPOST FTS_NOPOSTORDER
+#define FTW_SKIP FTS_SKIP
+#define FTW_STAT FTS_STAT
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int ftwalk(const char*, int(*)(Ftw_t*), int, int(*)(Ftw_t*, Ftw_t*));
+extern int ftwflags(void);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/glob.h b/src/lib/libast/include/glob.h
new file mode 100644
index 0000000..a118db9
--- /dev/null
+++ b/src/lib/libast/include/glob.h
@@ -0,0 +1,146 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * posix glob interface definitions with gnu extensions
+ */
+
+#ifndef _GLOB_H
+#define _GLOB_H
+
+#define GLOB_VERSION 20060717L
+
+#include <stdlib.h>
+
+struct dirent;
+struct stat;
+
+struct _glob_;
+struct _globlist_;
+
+typedef struct _glob_ glob_t;
+typedef struct _globlist_ globlist_t;
+
+struct _globlist_
+{
+ globlist_t* gl_next;
+ char* gl_begin;
+ unsigned char gl_flags;
+ char gl_path[1];
+};
+
+struct _glob_
+{
+ size_t gl_pathc;
+ char** gl_pathv;
+ size_t gl_offs;
+ globlist_t* gl_list;
+ int gl_flags;
+
+ /* GLOB_DISC data -- memset(&gl,0,sizeof(gl)) before using! */
+
+ const char* gl_fignore;
+ const char* gl_suffix;
+ unsigned char* gl_intr;
+
+ int gl_delim;
+
+ void* gl_handle;
+ void* (*gl_diropen)(glob_t*, const char*);
+ char* (*gl_dirnext)(glob_t*, void*);
+ void (*gl_dirclose)(glob_t*, void*);
+ int (*gl_type)(glob_t*, const char*, int);
+ int (*gl_attr)(glob_t*, const char*, int);
+
+ /* gnu extensions -- but how do you synthesize dirent and stat? */
+
+ void* (*gl_opendir)(const char*);
+ struct dirent* (*gl_readdir)(void*);
+ void (*gl_closedir)(void*);
+ int (*gl_stat)(const char*, struct stat*);
+ int (*gl_lstat)(const char*, struct stat*);
+
+ /* ast additions */
+
+ char* (*gl_nextdir)(glob_t*, char*);
+ unsigned long gl_status;
+ unsigned long gl_version;
+ unsigned short gl_extra;
+
+#ifdef _GLOB_PRIVATE_
+ _GLOB_PRIVATE_
+#else
+ char* gl_pad[23];
+#endif
+
+};
+
+/* standard interface */
+#define GLOB_APPEND 0x0001 /* append to previous */
+#define GLOB_DOOFFS 0x0002 /* gl_offs defines argv offset */
+#define GLOB_ERR 0x0004 /* abort on error */
+#define GLOB_MARK 0x0008 /* append / to directories */
+#define GLOB_NOCHECK 0x0010 /* nomatch is original pattern */
+#define GLOB_NOESCAPE 0x0020 /* don't treat \ specially */
+#define GLOB_NOSORT 0x0040 /* don't sort the list */
+
+/* extended interface */
+#define GLOB_STARSTAR 0x0080 /* enable [/]**[/] expansion */
+#define GLOB_BRACE 0x0100 /* enable {...} expansion */
+#define GLOB_ICASE 0x0200 /* ignore case on match */
+#define GLOB_COMPLETE 0x0400 /* shell file completeion */
+#define GLOB_AUGMENTED 0x0800 /* augmented shell patterns */
+#define GLOB_STACK 0x1000 /* allocate on current stack */
+#define GLOB_LIST 0x2000 /* just create gl_list */
+#define GLOB_ALTDIRFUNC 0x4000 /* gnu discipline functions */
+#define GLOB_DISC 0x8000 /* discipline initialized */
+
+#define GLOB_GROUP 0x10000 /* REG_SHELL_GROUP */
+
+/* gl_status */
+#define GLOB_NOTDIR 0x0001 /* last gl_dirnext() not a dir */
+
+/* gl_type return */
+#define GLOB_NOTFOUND 0 /* does not exist */
+#define GLOB_DEV 1 /* exists but not DIR EXE REG */
+#define GLOB_DIR 2 /* directory */
+#define GLOB_EXE 3 /* executable regular file */
+#define GLOB_REG 4 /* regular file */
+
+/* error return values */
+#define GLOB_ABORTED 1
+#define GLOB_NOMATCH 2
+#define GLOB_NOSPACE 3
+#define GLOB_INTR 4
+#define GLOB_APPERR 5
+#define GLOB_NOSYS 6
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int glob(const char*, int, int(*)(const char*,int), glob_t*);
+extern void globfree(glob_t*);
+
+#undef extern
+
+#endif /* _GLOB_H */
diff --git a/src/lib/libast/include/hash.h b/src/lib/libast/include/hash.h
new file mode 100644
index 0000000..b91e550
--- /dev/null
+++ b/src/lib/libast/include/hash.h
@@ -0,0 +1,202 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * hash table library interface definitions
+ *
+ * NOTE: new code should use the more general <cdt.h>
+ */
+
+#ifndef _HASH_H
+#define _HASH_H
+
+#define HASH_ALLOCATE (1L<<0) /* allocate new key names */
+#define HASH_FIXED (1L<<1) /* fixed table size */
+#define HASH_HASHED (1L<<6) /* key names already hashed */
+#define HASH_RESIZE (1L<<2) /* table has been resized */
+#define HASH_SCANNING (1L<<3) /* currently scanning scope */
+#define HASH_SCOPE (1L<<4) /* push scope / create in bot */
+#define HASH_STATIC (1L<<5) /* static table allocation */
+
+#define HASH_CREATE (1L<<8) /* create bucket if not found */
+#define HASH_DELETE (1L<<9) /* delete bucket if found */
+#define HASH_LOOKUP 0 /* default op */
+#define HASH_RENAME (1L<<7) /* rename bucket if found */
+
+#define HASH_BUCKET (1L<<11) /* name is installed bucket */
+#define HASH_INSTALL (1L<<12) /* install allocated bucket */
+#define HASH_NOSCOPE (1L<<13) /* top scope only */
+#define HASH_OPAQUE (1L<<14) /* opaque bucket */
+#define HASH_VALUE (1L<<15) /* value bucket field used */
+
+#define HASH_SIZE(n) (((long)(n))<<16) /* fixed bucket size */
+#define HASH_SIZEOF(f) ((((long)(f))>>16)&0xffff) /* extract size */
+
+#define HASH_DELETED ((unsigned long)1<<(8*sizeof(int)-1)) /* deleted placeholder */
+#define HASH_KEEP (1L<<(8*sizeof(int)-2)) /* no free on bucket */
+#define HASH_HIDDEN (1L<<(8*sizeof(int)-3)) /* hidden by scope */
+#define HASH_HIDES (1L<<(8*sizeof(int)-4)) /* hides lower scope */
+#define HASH_OPAQUED (1L<<(8*sizeof(int)-5)) /* opaqued placeholder */
+#define HASH_FREENAME (1L<<(8*sizeof(int)-6)) /* free bucket name */
+
+#define HASH_RESET (HASH_RESIZE|HASH_SCOPE|HASH_STATIC|HASH_VALUE)
+#define HASH_INTERNAL (HASH_BUCKET|HASH_RESIZE|HASH_SCANNING|HASH_STATIC)
+#define HASH_FLAGS (HASH_DELETED|HASH_FREENAME|HASH_HIDDEN|HASH_HIDES|HASH_KEEP|HASH_OPAQUED)
+
+#define HASH_alloc 1
+#define HASH_clear 2
+#define HASH_compare 3
+#define HASH_free 4
+#define HASH_hash 5
+#define HASH_meanchain 6
+#define HASH_name 7
+#define HASH_namesize 8
+#define HASH_set 9
+#define HASH_size 10
+#define HASH_table 11
+#define HASH_va_list 12
+
+#define HASH_bucketsize 13
+
+#define HASH_region 14
+
+#include <hashpart.h>
+
+#define hashclear(t,f) ((t)->flags &= ~((f) & ~HASH_INTERNAL))
+#define hashcover(b) (((b)->hash&HASH_HIDES)?(Hash_bucket_t*)((b)->name):(Hash_bucket_t*)0)
+#define hashdel(t,n) hashlook(t, (char*)(n), HASH_DELETE, (char*)0)
+#define hashget(t,n) hashlook(t, (char*)(n), HASH_LOOKUP|HASH_VALUE, (char*)0)
+#define hashgetbucket(s) ((Hash_bucket_t*)((s)-((sizeof(Hash_bucket_t)+sizeof(char*)-1)/sizeof(char*))*sizeof(char*)))
+#define hashkeep(b) ((b)->hash|=HASH_KEEP)
+#define hashname(b) ((((b)->hash&HASH_HIDES)?((Hash_bucket_t*)((b)->name)):(b))->name)
+#define hashput(t,n,v) hashlook(t, (char*)(n), HASH_CREATE|HASH_VALUE, (char*)(v))
+#define hashref(t,n) hashlook(t, (char*)(n), HASH_LOOKUP|HASH_INTERNAL|HASH_VALUE, (char*)0)
+#define hashscope(t) ((t)->scope)
+#define hashset(t,f) ((t)->flags |= ((f) & ~HASH_INTERNAL))
+
+/*
+ * DEPRECATED renames for compatibility
+ */
+
+#define Hashbin_t Hash_bucket_t
+#define HASHBUCKET Hash_bucket_t
+#define Hashhdr_t Hash_header_t
+#define HASHHEADER Hash_header_t
+#define Hashpos_t Hash_position_t
+#define HASHPOSITION Hash_position_t
+#define Hashtab_t Hash_table_t
+#define HASHTABLE Hash_table_t
+
+#define vhashalloc hashvalloc
+#define hashvalloc(t,a) hashalloc(t,HASH_va_list,a,0)
+
+/*
+ * the #define's avoid union tags
+ */
+
+typedef struct Hash_bucket Hash_bucket_t;
+typedef struct Hash_root Hash_root_t;
+typedef struct Hash_table Hash_table_t;
+
+#define HASH_HEADER /* common bucket header */ \
+ Hash_bucket_t* next; /* next in collision chain */ \
+ unsigned int hash; /* hash flags and value */ \
+ char* name /* key name */
+
+#define HASH_DEFAULT /* HASH_VALUE bucket elements */ \
+ char* value /* key value */
+
+typedef struct /* bucket header */
+{
+ HASH_HEADER;
+} Hash_header_t;
+
+struct Hash_bucket /* prototype bucket */
+{
+ HASH_HEADER;
+ HASH_DEFAULT;
+};
+
+typedef struct /* hash scan bucket position */
+{
+ Hash_bucket_t* bucket; /* bucket */
+#ifdef _HASH_POSITION_PRIVATE_
+ _HASH_POSITION_PRIVATE_
+#endif
+} Hash_position_t;
+
+typedef struct /* last lookup cache */
+{
+ Hash_table_t* table; /* last lookup table */
+ Hash_bucket_t* bucket; /* last lookup bucket */
+#ifdef _HASH_LAST_PRIVATE_
+ _HASH_LAST_PRIVATE_
+#endif
+} Hash_last_t;
+
+struct Hash_root /* root hash table information */
+{
+ int accesses; /* number of accesses */
+ int collisions; /* number of collisions */
+ int flags; /* flags: see HASH_[A-Z]* */
+ Hash_last_t last; /* last lookup cache */
+ void* context; /* user defined context */
+#ifdef _HASH_ROOT_PRIVATE_
+ _HASH_ROOT_PRIVATE_
+#endif
+};
+
+struct Hash_table /* hash table information */
+{
+ Hash_root_t* root; /* root hash table information */
+ int size; /* table size */
+ int buckets; /* active bucket count */
+ char* name; /* table name */
+ Hash_table_t* scope; /* scope covered table */
+ short flags; /* flags: see HASH_[A-Z]* */
+#ifdef _HASH_TABLE_PRIVATE_
+ _HASH_TABLE_PRIVATE_
+#endif
+};
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern Hash_table_t* hashalloc(Hash_table_t*, ...);
+extern void hashdone(Hash_position_t*);
+extern void hashdump(Hash_table_t*, int);
+extern Hash_table_t* hashfree(Hash_table_t*);
+extern Hash_bucket_t* hashlast(Hash_table_t*);
+extern char* hashlook(Hash_table_t*, const char*, long, const char*);
+extern Hash_bucket_t* hashnext(Hash_position_t*);
+extern Hash_position_t* hashscan(Hash_table_t*, int);
+extern void hashsize(Hash_table_t*, int);
+extern Hash_table_t* hashview(Hash_table_t*, Hash_table_t*);
+extern int hashwalk(Hash_table_t*, int, int (*)(const char*, char*, void*), void*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/hashkey.h b/src/lib/libast/include/hashkey.h
new file mode 100644
index 0000000..338f017
--- /dev/null
+++ b/src/lib/libast/include/hashkey.h
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * 1-6 char lower-case keyword -> long hash
+ * digit args passed as HASHKEYN('2')
+ */
+
+#ifndef _HASHKEY_H
+#define _HASHKEY_H
+
+#define HASHKEYMAX 6
+#define HASHKEYBIT 5
+#define HASHKEYOFF ('a'-1)
+#define HASHKEYPART(h,c) (((h)<<HASHKEYBIT)+HASHKEY1(c))
+
+#define HASHKEYN(n) ((n)-'0'+'z'+1)
+
+#define HASHKEY1(c1) ((c1)-HASHKEYOFF)
+#define HASHKEY2(c1,c2) HASHKEYPART(HASHKEY1(c1),c2)
+#define HASHKEY3(c1,c2,c3) HASHKEYPART(HASHKEY2(c1,c2),c3)
+#define HASHKEY4(c1,c2,c3,c4) HASHKEYPART(HASHKEY3(c1,c2,c3),c4)
+#define HASHKEY5(c1,c2,c3,c4,c5) HASHKEYPART(HASHKEY4(c1,c2,c3,c4),c5)
+#define HASHKEY6(c1,c2,c3,c4,c5,c6) HASHKEYPART(HASHKEY5(c1,c2,c3,c4,c5),c6)
+
+#define HASHNKEY1(n,c1) HASHKEY2((n)+HASHKEYOFF,c1)
+#define HASHNKEY2(n,c2,c1) HASHKEY3((n)+HASHKEYOFF,c2,c1)
+#define HASHNKEY3(n,c3,c2,c1) HASHKEY4((n)+HASHKEYOFF,c3,c2,c1)
+#define HASHNKEY4(n,c4,c3,c2,c1) HASHKEY5((n)+'a',c4,c3,c2,c1)
+#define HASHNKEY5(n,c5,c4,c3,c2,c1) HASHKEY6((n)+'a',c5,c4,c3,c2,c1)
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern long strkey(const char*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/hashpart.h b/src/lib/libast/include/hashpart.h
new file mode 100644
index 0000000..ae38262
--- /dev/null
+++ b/src/lib/libast/include/hashpart.h
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * K. P. Vo
+ * G. S. Fowler
+ * AT&T Research
+ *
+ * ``the best'' combined linear congruent checksum/hash/PRNG
+ */
+
+#ifndef _HASHPART_H
+#define _HASHPART_H
+
+#define HASH_ADD(h) (0x9c39c33dL)
+
+#if __sparc__ || __sparc || sparc
+
+#define HASH_A(h,n) ((((h) << 2) - (h)) << (n))
+#define HASH_B(h,n) ((((h) << 4) - (h)) << (n))
+#define HASH_C(h,n) ((HASH_A(h,7) + HASH_B(h,0)) << (n))
+#define HASH_MPY(h) (HASH_C(h,22)+HASH_C(h,10)+HASH_A(h,6)+HASH_A(h,3)+(h))
+
+#else
+
+#define HASH_MPY(h) ((h)*0x63c63cd9L)
+
+#endif
+
+#define HASHPART(h,c) (h = HASH_MPY(h) + HASH_ADD(h) + (c))
+
+#endif
diff --git a/src/lib/libast/include/ip6.h b/src/lib/libast/include/ip6.h
new file mode 100644
index 0000000..382ead8
--- /dev/null
+++ b/src/lib/libast/include/ip6.h
@@ -0,0 +1,40 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _IP6_H
+#define _IP6_H 1
+
+#define IP6ADDR 16
+#define IP6BITS IP6ADDR
+#define IP6PREFIX (IP6ADDR+1)
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char* fmtip6(const unsigned char*, int);
+extern int strtoip6(const char*, char**, unsigned char*, unsigned char*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/ls.h b/src/lib/libast/include/ls.h
new file mode 100644
index 0000000..fc1d623
--- /dev/null
+++ b/src/lib/libast/include/ls.h
@@ -0,0 +1,88 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * ls formatter interface definitions
+ */
+
+#ifndef _LS_H
+#define _LS_H
+
+#include <ast_std.h>
+#include <ast_fs.h>
+#include <ast_mode.h>
+
+/*
+ * some systems (could it beee AIX) pollute the std name space
+ */
+
+#undef fileid
+#define fileid fileID
+
+#define LS_BLOCKSIZE 512
+
+#define iblocks(p) _iblocks(p)
+
+#if _mem_st_rdev_stat
+#define idevice(p) ((p)->st_rdev)
+#define IDEVICE(p,v) ((p)->st_rdev=(v))
+#else
+#define idevice(p) 0
+#define IDEVICE(p,v)
+#endif
+
+#define LS_ATIME (1<<0) /* list st_atime */
+#define LS_BLOCKS (1<<1) /* list blocks used by file */
+#define LS_CTIME (1<<2) /* list st_ctime */
+#define LS_EXTERNAL (1<<3) /* st_mode is modex canonical */
+#define LS_INUMBER (1<<4) /* list st_ino */
+#define LS_LONG (1<<5) /* long listing */
+#define LS_MARK (1<<6) /* append file name marks */
+#define LS_NOGROUP (1<<7) /* omit group name for LS_LONG */
+#define LS_NOUSER (1<<8) /* omit user name for LS_LONG */
+#define LS_NUMBER (1<<9) /* number instead of name */
+
+#define LS_USER (1<<10) /* first user flag bit */
+
+#define LS_W_BLOCKS 6 /* LS_BLOCKS field width */
+#define LS_W_INUMBER 9 /* LS_INUMBER field width */
+#define LS_W_LONG 57 /* LS_LONG width (w/o names) */
+#define LS_W_LINK 4 /* link text width (w/o names) */
+#define LS_W_MARK 1 /* LS_MARK field width */
+#define LS_W_NAME 9 /* group|user name field width */
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern off_t _iblocks(struct stat*);
+extern char* fmtdev(struct stat*);
+extern char* fmtfs(struct stat*);
+extern char* fmtls(char*, const char*, struct stat*, const char*, const char*, int);
+extern int pathstat(const char*, struct stat*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/magic.h b/src/lib/libast/include/magic.h
new file mode 100644
index 0000000..9b2f96b
--- /dev/null
+++ b/src/lib/libast/include/magic.h
@@ -0,0 +1,86 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * magic interface definitions
+ */
+
+#ifndef _MAGIC_H
+#define _MAGIC_H
+
+#include <sfio.h>
+#include <ls.h>
+
+#define MAGIC_VERSION 19961031L
+
+#ifndef MAGIC_FILE
+#define MAGIC_FILE "lib/file/magic"
+#endif
+
+#ifndef MAGIC_DIR
+#define MAGIC_DIR "lib/file"
+#endif
+
+#define MAGIC_FILE_ENV "MAGICFILE"
+
+#define MAGIC_MIME (1<<0) /* magictype returns MIME type */
+#define MAGIC_VERBOSE (1<<1) /* verbose magic file errors */
+#define MAGIC_ALL (1<<2) /* list all table matches */
+
+#define MAGIC_USER (1L<<16) /* first user flag bit */
+
+struct Magic_s;
+struct Magicdisc_s;
+
+typedef struct Magicdisc_s
+{
+ unsigned long version; /* interface version */
+ unsigned long flags; /* MAGIC_* flags */
+ Error_f errorf; /* error function */
+} Magicdisc_t;
+
+typedef struct Magic_s
+{
+ const char* id; /* library id string */
+
+#ifdef _MAGIC_PRIVATE_
+ _MAGIC_PRIVATE_
+#endif
+
+} Magic_t;
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern Magic_t* magicopen(Magicdisc_t*);
+extern int magicload(Magic_t*, const char*, unsigned long);
+extern int magiclist(Magic_t*, Sfio_t*);
+extern char* magictype(Magic_t*, Sfio_t*, const char*, struct stat*);
+extern int magicclose(Magic_t*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/magicid.h b/src/lib/libast/include/magicid.h
new file mode 100644
index 0000000..73197d7
--- /dev/null
+++ b/src/lib/libast/include/magicid.h
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * generic binary magic id definitions
+ */
+
+#ifndef _MAGICID_H
+#define _MAGICID_H 1
+
+#include <ast_common.h>
+
+#define MAGICID 0x00010203
+
+typedef uint32_t Magicid_data_t;
+
+typedef struct Magicid_s
+{
+ Magicid_data_t magic; /* magic number */
+ char name[8]; /* generic data/application name*/
+ char type[12]; /* specific data type */
+ Magicid_data_t version; /* YYYYMMDD or 0xWWXXYYZZ */
+ Magicid_data_t size;
+} Magicid_t;
+
+#endif
diff --git a/src/lib/libast/include/mc.h b/src/lib/libast/include/mc.h
new file mode 100644
index 0000000..a23c7bb
--- /dev/null
+++ b/src/lib/libast/include/mc.h
@@ -0,0 +1,96 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * machine independent binary message catalog interface
+ *
+ * file layout
+ * all numbers are sfputu() format
+ *
+ * 4 char magic (^M^S^G0)
+ * <method locale YYYY-MM-DD>\0
+ * (<optional strings>\0)*
+ * \0
+ * string table size
+ * #msgs total
+ * #max set number
+ * #set-id 1
+ * #msgs in set 1
+ * ...
+ * #set-id #sets
+ * #msgs in set #sets
+ * end of sets (0)
+ * msg(1,1) size
+ * ...
+ * msg(#sets,#msgs) size
+ * string table
+ */
+
+#ifndef _MC_H
+#define _MC_H
+
+#include <ast.h>
+
+#define MC_MAGIC "\015\023\007\000"
+#define MC_MAGIC_SIZE 4
+
+#define MC_SET_MAX 1023
+#define MC_NUM_MAX 32767
+
+#define MC_NLS (1<<10)
+
+#define MC_MESSAGE_SET(s) mcindex(s,NiL,NiL,NiL)
+
+typedef struct Mcset_s
+{
+ char** msg;
+ int num;
+ int gen;
+} Mcset_t;
+
+typedef struct Mc_s
+{
+ Mcset_t* set;
+ int num;
+ int gen;
+ char* translation;
+#ifdef _MC_PRIVATE_
+ _MC_PRIVATE_
+#endif
+} Mc_t;
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char* mcfind(const char*, const char*, int, int, char*, size_t);
+extern Mc_t* mcopen(Sfio_t*);
+extern char* mcget(Mc_t*, int, int, const char*);
+extern int mcput(Mc_t*, int, int, const char*);
+extern int mcdump(Mc_t*, Sfio_t*);
+extern int mcindex(const char*, char**, int*, int*);
+extern int mcclose(Mc_t*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/mime.h b/src/lib/libast/include/mime.h
new file mode 100644
index 0000000..6fa7657
--- /dev/null
+++ b/src/lib/libast/include/mime.h
@@ -0,0 +1,91 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * mime/mailcap interface
+ */
+
+#ifndef _MIMETYPE_H
+#define _MIMETYPE_H 1
+
+#include <sfio.h>
+#include <ls.h>
+
+#define MIME_VERSION 19970717L
+
+#ifndef MIME_FILES
+#define MIME_FILES "~/.mailcap:/usr/local/etc/mailcap:/usr/etc/mailcap:/etc/mailcap:/etc/mail/mailcap:/usr/public/lib/mailcap"
+#endif
+
+#define MIME_FILES_ENV "MAILCAP"
+
+#define MIME_LIST (1<<0) /* mimeload arg is : list */
+#define MIME_NOMAGIC (1<<1) /* no magic for mimetype() */
+#define MIME_PIPE (1<<2) /* mimeview() io is piped */
+#define MIME_REPLACE (1<<3) /* replace existing definition */
+
+#define MIME_USER (1L<<16) /* first user flag bit */
+
+struct Mime_s;
+typedef struct Mime_s Mime_t;
+
+struct Mimedisc_s;
+typedef struct Mimedisc_s Mimedisc_t;
+
+typedef int (*Mimevalue_f)(Mime_t*, void*, char*, size_t, Mimedisc_t*);
+
+struct Mimedisc_s
+{
+ unsigned long version; /* interface version */
+ unsigned long flags; /* MIME_* flags */
+ Error_f errorf; /* error function */
+ Mimevalue_f valuef; /* value extraction function */
+};
+
+struct Mime_s
+{
+ const char* id; /* library id string */
+
+#ifdef _MIME_PRIVATE_
+ _MIME_PRIVATE_
+#endif
+
+};
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern Mime_t* mimeopen(Mimedisc_t*);
+extern int mimeload(Mime_t*, const char*, unsigned long);
+extern int mimelist(Mime_t*, Sfio_t*, const char*);
+extern int mimeclose(Mime_t*);
+extern int mimeset(Mime_t*, char*, unsigned long);
+extern char* mimetype(Mime_t*, Sfio_t*, const char*, struct stat*);
+extern char* mimeview(Mime_t*, const char*, const char*, const char*, const char*);
+extern int mimehead(Mime_t*, void*, size_t, size_t, char*);
+extern int mimecmp(const char*, const char*, char**);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/mnt.h b/src/lib/libast/include/mnt.h
new file mode 100644
index 0000000..698c730
--- /dev/null
+++ b/src/lib/libast/include/mnt.h
@@ -0,0 +1,58 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * mounted filesystem scan interface
+ */
+
+#ifndef _MNT_H
+#define _MNT_H 1
+
+#undef MNT_REMOTE /* aix clash */
+#define MNT_REMOTE (1<<0) /* remote mount */
+
+typedef struct
+{
+ char* fs; /* filesystem name */
+ char* dir; /* mounted dir */
+ char* type; /* filesystem type */
+ char* options; /* options */
+ int freq; /* backup frequency */
+ int npass; /* number of parallel passes */
+ int flags; /* MNT_* flags */
+} Mnt_t;
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern void* mntopen(const char*, const char*);
+extern Mnt_t* mntread(void*);
+extern int mntwrite(void*, const Mnt_t*);
+extern int mntclose(void*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/modecanon.h b/src/lib/libast/include/modecanon.h
new file mode 100644
index 0000000..5d1721f
--- /dev/null
+++ b/src/lib/libast/include/modecanon.h
@@ -0,0 +1,65 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * canonical mode_t representation
+ */
+
+#ifndef _MODECANON_H
+#define _MODECANON_H
+
+#define X_ITYPE(m) ((m)&X_IFMT)
+
+#define X_IFMT 0170000
+#define X_IFWHT 0160000
+#define X_IFDOOR 0150000
+#define X_IFSOCK 0140000
+#define X_IFLNK 0120000
+#define X_IFCTG 0110000
+#define X_IFREG 0100000
+#define X_IFBLK 0060000
+#define X_IFDIR 0040000
+#define X_IFCHR 0020000
+#define X_IFIFO 0010000
+
+#define X_IPERM 0007777
+#define X_ISUID 0004000
+#define X_ISGID 0002000
+#define X_ISVTX 0001000
+#define X_IRUSR 0000400
+#define X_IWUSR 0000200
+#define X_IXUSR 0000100
+#define X_IRGRP 0000040
+#define X_IWGRP 0000020
+#define X_IXGRP 0000010
+#define X_IROTH 0000004
+#define X_IWOTH 0000002
+#define X_IXOTH 0000001
+
+#define X_IRWXU (X_IRUSR|X_IWUSR|X_IXUSR)
+#define X_IRWXG (X_IRGRP|X_IWGRP|X_IXGRP)
+#define X_IRWXO (X_IROTH|X_IWOTH|X_IXOTH)
+
+#endif
diff --git a/src/lib/libast/include/modex.h b/src/lib/libast/include/modex.h
new file mode 100644
index 0000000..e8b52f7
--- /dev/null
+++ b/src/lib/libast/include/modex.h
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Research
+ *
+ * external mode_t representation support
+ */
+
+#ifndef _MODEX_H
+#define _MODEX_H
+
+#include <ast_fs.h>
+#include <modecanon.h>
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int modei(int);
+extern int modex(int);
+
+#undef extern
+
+#if _S_IDPERM
+#define modei(m) ((m)&X_IPERM)
+#if _S_IDTYPE
+#define modex(m) (m)
+#endif
+#endif
+
+#endif
diff --git a/src/lib/libast/include/namval.h b/src/lib/libast/include/namval.h
new file mode 100644
index 0000000..9c055cc
--- /dev/null
+++ b/src/lib/libast/include/namval.h
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * common name-value struct support
+ */
+
+#ifndef _NAMVAL_H
+#define _NAMVAL_H
+
+typedef struct
+{
+ char* name;
+ int value;
+#ifdef _NAMVAL_PRIVATE_
+ _NAMVAL_PRIVATE_
+#endif
+} Namval_t;
+
+#endif
diff --git a/src/lib/libast/include/option.h b/src/lib/libast/include/option.h
new file mode 100644
index 0000000..1d24690
--- /dev/null
+++ b/src/lib/libast/include/option.h
@@ -0,0 +1,106 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * command line option parse interface
+ */
+
+#ifndef _OPTION_H
+#define _OPTION_H
+
+#include <ast.h>
+
+#define OPT_VERSION 20070319L
+
+#define OPT_USER (1L<<16) /* first user flag bit */
+
+struct Opt_s;
+struct Optdisc_s;
+
+typedef int (*Optinfo_f)(struct Opt_s*, Sfio_t*, const char*, struct Optdisc_s*);
+
+typedef struct Optdisc_s
+{
+ unsigned long version; /* OPT_VERSION */
+ unsigned long flags; /* OPT_* flags */
+ char* catalog; /* error catalog id */
+ Optinfo_f infof; /* runtime info function */
+} Optdisc_t;
+
+/* NOTE: Opt_t member order fixed by a previous binary release */
+
+#ifndef _OPT_PRIVATE_
+#define _OPT_PRIVATE_ \
+ char pad[3*sizeof(void*)];
+#endif
+
+typedef struct Opt_s
+{
+ int again; /* see optjoin() */
+ char* arg; /* {:,#} string argument */
+ char** argv; /* most recent argv */
+ int index; /* argv index */
+ char* msg; /* error/usage message buffer */
+ long num; /* OBSOLETE -- use number */
+ int offset; /* char offset in argv[index] */
+ char option[8]; /* current flag {-,+} + option */
+ char name[64]; /* current long name or flag */
+ Optdisc_t* disc; /* user discipline */
+ intmax_t number; /* # numeric argument */
+ unsigned char assignment; /* option arg assigment op */
+ unsigned char pads[sizeof(void*)-1];
+ _OPT_PRIVATE_
+} Opt_t;
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+#if !_BLD_ast && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern Opt_t* _opt_infop_;
+
+#define opt_info (*_opt_infop_)
+
+#undef extern
+
+#define optinit(d,f) (memset(d,0,sizeof(*(d))),(d)->version=OPT_VERSION,(d)->infof=(f),opt_info.disc=(d))
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int optget(char**, const char*);
+extern int optjoin(char**, ...);
+extern char* opthelp(const char*, const char*);
+extern char* optusage(const char*);
+extern int optstr(const char*, const char*);
+extern int optesc(Sfio_t*, const char*, int);
+extern Opt_t* optctx(Opt_t*, Opt_t*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/proc.h b/src/lib/libast/include/proc.h
new file mode 100644
index 0000000..76fdf83
--- /dev/null
+++ b/src/lib/libast/include/proc.h
@@ -0,0 +1,108 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * process library interface
+ */
+
+#ifndef _PROC_H
+#define _PROC_H
+
+#include <ast.h>
+
+#define PROC_ARGMOD (1<<0) /* argv[-1],argv[0] can be modified */
+#define PROC_BACKGROUND (1<<1) /* shell background (&) setup */
+#define PROC_CHECK (1<<17) /* check that command exists */
+#define PROC_CLEANUP (1<<2) /* close parent redirect fds on error */
+#define PROC_DAEMON (1<<3) /* daemon setup */
+#define PROC_ENVCLEAR (1<<4) /* clear environment */
+#define PROC_FOREGROUND (1<<14) /* system(3) setup */
+#define PROC_GID (1<<5) /* setgid(getgid()) */
+#define PROC_IGNORE (1<<6) /* ignore parent pipe errors */
+#define PROC_IGNOREPATH (1<<16) /* procrun() intercept to ignore path */
+#define PROC_ORPHAN (1<<18) /* create orphaned process */
+#define PROC_OVERLAY (1<<7) /* overlay current process if possible */
+#define PROC_PARANOID (1<<8) /* restrict everything */
+#define PROC_PRIVELEGED (1<<9) /* setuid(0), setgid(getegid()) */
+#define PROC_READ (1<<10) /* proc pipe fd 1 returned */
+#define PROC_SESSION (1<<11) /* session leader */
+#define PROC_UID (1<<12) /* setuid(getuid()) */
+#define PROC_WRITE (1<<13) /* proc pipe fd 0 returned */
+#define PROC_ZOMBIE (1<<15) /* proc may leave a zombie behind */
+
+#define PROC_ARG_BIT 14 /* bits per op arg */
+#define PROC_OP_BIT 4 /* bits per op */
+
+#define PROC_ARG_NULL ((1<<PROC_ARG_BIT)-1)
+
+#define PROC_fd_dup 0x4
+#define PROC_FD_CHILD 0x1
+#define PROC_FD_PARENT 0x2
+
+#define PROC_sig_dfl 0x8
+#define PROC_sig_ign 0x9
+
+#define PROC_sys_pgrp 0xa
+#define PROC_sys_umask 0xb
+
+#define PROC_fd_ctty 0xc
+
+#define PROC_op1(o,a) (((o)<<(2*PROC_ARG_BIT))|((a)&((PROC_ARG_NULL<<PROC_ARG_BIT)|PROC_ARG_NULL)))
+#define PROC_op2(o,a,b) (((o)<<(2*PROC_ARG_BIT))|(((b)&PROC_ARG_NULL)<<PROC_ARG_BIT)|((a)&PROC_ARG_NULL))
+
+#define PROC_FD_CLOSE(p,f) PROC_op2(PROC_fd_dup|(f),p,PROC_ARG_NULL)
+#define PROC_FD_CTTY(f) PROC_op1(PROC_fd_ctty,f)
+#define PROC_FD_DUP(p,c,f) PROC_op2(PROC_fd_dup|(f),p,c)
+#define PROC_SIG_DFL(s) PROC_op1(PROC_sig_dfl,s,0)
+#define PROC_SIG_IGN(s) PROC_op1(PROC_sig_ign,s,0)
+#define PROC_SYS_PGRP(g) PROC_op1(PROC_sys_pgrp,g)
+#define PROC_SYS_UMASK(m) PROC_op1(PROC_sys_umask,m,0)
+
+#define PROC_OP(x) (((x)>>(2*PROC_ARG_BIT))&((1<<PROC_OP_BIT)-1))
+#define PROC_ARG(x,n) ((n)?(((x)>>(((n)-1)*PROC_ARG_BIT))&PROC_ARG_NULL):(((x)&~((1<<(2*PROC_ARG_BIT))-1))==~((1<<(2*PROC_ARG_BIT))-1))?(-1):((x)&~((1<<(2*PROC_ARG_BIT))-1)))
+
+typedef struct
+{
+ pid_t pid; /* process id */
+ pid_t pgrp; /* process group id */
+ int rfd; /* read fd if applicable */
+ int wfd; /* write fd if applicable */
+
+#ifdef _PROC_PRIVATE_
+_PROC_PRIVATE_
+#endif
+
+} Proc_t;
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int procclose(Proc_t*);
+extern int procfree(Proc_t*);
+extern Proc_t* procopen(const char*, char**, char**, long*, int);
+extern int procrun(const char*, char**, int);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/recfmt.h b/src/lib/libast/include/recfmt.h
new file mode 100644
index 0000000..aaae3c0
--- /dev/null
+++ b/src/lib/libast/include/recfmt.h
@@ -0,0 +1,83 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * record format interface
+ */
+
+#ifndef _RECFMT_H
+#define _RECFMT_H 1
+
+#include <ast.h>
+
+typedef uint32_t Recfmt_t;
+
+#define REC_delimited 0
+#define REC_fixed 1
+#define REC_variable 2
+#define REC_method 14
+#define REC_none 15
+
+#define REC_M_path 0
+#define REC_M_data 1
+
+#define RECTYPE(f) (((f)>>28)&((1<<4)-1))
+
+#define REC_D_TYPE(d) ((REC_delimited<<28)|((d)&((1<<8)-1)))
+#define REC_D_DELIMITER(f) ((f)&((1<<8)-1))
+
+#define REC_F_TYPE(s) ((REC_fixed<<28)|((s)&((1<<28)-1)))
+#define REC_F_SIZE(f) ((f)&((1<<28)-1))
+
+#define REC_U_TYPE(t,a) (((t)<<28)|((a)&((1<<28)-1)))
+#define REC_U_ATTRIBUTES(f) ((f)&~((1<<28)-1))
+
+#define REC_V_TYPE(h,o,z,l,i) ((REC_variable<<28)|((h)<<23)|((o)<<19)|(((z)-1)<<18)|((l)<<17)|((i)<<16))
+#define REC_V_RECORD(f,s) (((f)&(((1<<16)-1)<<16))|(s))
+#define REC_V_HEADER(f) (((f)>>23)&((1<<5)-1))
+#define REC_V_OFFSET(f) (((f)>>19)&((1<<4)-1))
+#define REC_V_LENGTH(f) ((((f)>>18)&1)+1)
+#define REC_V_LITTLE(f) (((f)>>17)&1)
+#define REC_V_INCLUSIVE(f) (((f)>>16)&1)
+#define REC_V_SIZE(f) ((f)&((1<<16)-1))
+#define REC_V_ATTRIBUTES(f) ((f)&~((1<<16)-1))
+
+#define REC_M_TYPE(i) ((REC_method<<28)|(i))
+#define REC_M_INDEX(f) ((f)&((1<<28)-1))
+
+#define REC_N_TYPE() 0xffffffff
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char* fmtrec(Recfmt_t, int);
+extern Recfmt_t recfmt(const void*, size_t, off_t);
+extern Recfmt_t recstr(const char*, char**);
+extern ssize_t reclen(Recfmt_t, const void*, size_t);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/regex.h b/src/lib/libast/include/regex.h
new file mode 100644
index 0000000..8b357fe
--- /dev/null
+++ b/src/lib/libast/include/regex.h
@@ -0,0 +1,248 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * regex library interface
+ */
+
+#ifdef _AST_STD_I
+#define _REGEX_H -1
+#define regex_t int
+#define regmatch_t int
+#endif
+#ifndef _REGEX_H
+#define _REGEX_H 1
+#undef regex_t
+#undef regmatch_t
+
+#include <ast_common.h>
+#include <ast_wchar.h>
+
+#define REG_VERSION 20100930L
+
+/* regcomp flags */
+
+#define REG_AUGMENTED 0x00000001 /* enable ! & < > */
+#define REG_EXTENDED 0x00000002 /* enable ( | ) */
+#define REG_ICASE 0x00000004 /* ignore case in match */
+#define REG_NEWLINE 0x00000008 /* ^/$ match embedded \n */
+#define REG_NOSUB 0x00000010 /* don't report subexp matches */
+#define REG_SHELL 0x00000020 /* shell pattern syntax */
+
+/* nonstandard regcomp flags */
+
+#define REG_LEFT 0x00000100 /* implicit ^... */
+#define REG_LITERAL 0x00000200 /* no operators */
+#define REG_MINIMAL 0x00000400 /* minimal match */
+#define REG_NULL 0x00000800 /* allow null patterns */
+#define REG_RIGHT 0x00001000 /* implicit ...$ */
+#define REG_LENIENT 0x00002000 /* look the other way */
+#define REG_ESCAPE 0x00004000 /* \ escapes delimiter in [...] */
+#define REG_FIRST 0x00008000 /* first match found will do */
+#define REG_MULTIPLE 0x00010000 /* multiple \n sep patterns */
+#define REG_DISCIPLINE 0x00020000 /* regex_t.re_disc is valid */
+#define REG_SPAN 0x00040000 /* . matches \n */
+#define REG_COMMENT 0x00080000 /* ignore pattern space & #...\n*/
+#define REG_MULTIREF 0x00100000 /* multiple digit backrefs */
+#define REG_MUSTDELIM 0x08000000 /* all delimiters required */
+#define REG_DELIMITED 0x10000000 /* pattern[0] is delimiter */
+#define REG_CLASS_ESCAPE 0x80000000 /* \ escapes in [...] */
+
+#define REG_SHELL_DOT 0x00200000 /* explicit leading . match */
+#define REG_SHELL_ESCAPED 0x00400000 /* \ not special */
+#define REG_SHELL_GROUP 0x20000000 /* (|&) inside [@|&](...) only */
+#define REG_SHELL_PATH 0x00800000 /* explicit / match */
+
+#define REG_REGEXP 0x40000000 /* <regexp.h> compatibility */
+
+/* regexec flags */
+
+#define REG_NOTBOL 0x00000040 /* ^ is not a special char */
+#define REG_NOTEOL 0x00000080 /* $ is not a special char */
+
+/* nonstandard regexec flags */
+
+#define REG_INVERT 0x01000000 /* invert regrexec match sense */
+#define REG_STARTEND 0x02000000 /* subject==match[0].rm_{so,eo} */
+#define REG_ADVANCE 0x04000000 /* advance match[0].rm_{so,eo} */
+
+/* regalloc flags */
+
+#define REG_NOFREE 0x00000001 /* don't free */
+
+/* regsub flags */
+
+#define REG_SUB_ALL 0x00000001 /* substitute all occurrences */
+#define REG_SUB_LOWER 0x00000002 /* substitute to lower case */
+#define REG_SUB_UPPER 0x00000004 /* substitute to upper case */
+#define REG_SUB_PRINT 0x00000010 /* internal no-op */
+#define REG_SUB_NUMBER 0x00000020 /* internal no-op */
+#define REG_SUB_STOP 0x00000040 /* internal no-op */
+#define REG_SUB_WRITE 0x00000080 /* internal no-op */
+#define REG_SUB_LAST 0x00000100 /* last substitution option */
+#define REG_SUB_FULL 0x00000200 /* fully delimited */
+#define REG_SUB_USER 0x00001000 /* first user flag bit */
+
+/* regex error codes */
+
+#define REG_ENOSYS (-1) /* not supported */
+#define REG_NOMATCH 1 /* regexec didn't match */
+#define REG_BADPAT 2 /* invalid regular expression */
+#define REG_ECOLLATE 3 /* invalid collation element */
+#define REG_ECTYPE 4 /* invalid character class */
+#define REG_EESCAPE 5 /* trailing \ in pattern */
+#define REG_ESUBREG 6 /* invalid \digit backreference */
+#define REG_EBRACK 7 /* [...] imbalance */
+#define REG_EPAREN 8 /* \(...\) or (...) imbalance */
+#define REG_EBRACE 9 /* \{...\} or {...} imbalance */
+#define REG_BADBR 10 /* invalid {...} digits */
+#define REG_ERANGE 11 /* invalid [...] range endpoint */
+#define REG_ESPACE 12 /* out of space */
+#define REG_BADRPT 13 /* unary op not preceded by re */
+#define REG_ENULL 14 /* empty subexpr in pattern */
+#define REG_ECOUNT 15 /* re component count overflow */
+#define REG_BADESC 16 /* invalid \char escape */
+#define REG_VERSIONID 17 /* version id (pseudo error) */
+#define REG_EFLAGS 18 /* flags conflict */
+#define REG_EDELIM 19 /* invalid or omitted delimiter */
+#define REG_PANIC 20 /* unrecoverable internal error */
+
+struct regex_s; typedef struct regex_s regex_t;
+struct regdisc_s; typedef struct regdisc_s regdisc_t;
+
+typedef int (*regclass_t)(int);
+typedef uint32_t regflags_t;
+typedef int regoff_t;
+typedef int (*regerror_t)(const regex_t*, regdisc_t*, int, ...);
+typedef void* (*regcomp_t)(const regex_t*, const char*, size_t, regdisc_t*);
+typedef int (*regexec_t)(const regex_t*, void*, const char*, size_t, const char*, size_t, char**, regdisc_t*);
+typedef void* (*regresize_t)(void*, void*, size_t);
+typedef int (*regrecord_t)(void*, const char*, size_t);
+
+typedef struct regmatch_s
+{
+ regoff_t rm_so; /* offset of start */
+ regoff_t rm_eo; /* offset of end */
+} regmatch_t;
+
+typedef struct regsub_s
+{
+ regflags_t re_flags; /* regsubcomp() flags */
+ char* re_buf; /* regsubexec() output buffer */
+ size_t re_len; /* re_buf length */
+ int re_min; /* regsubcomp() min matches */
+#ifdef _REG_SUB_PRIVATE_
+ _REG_SUB_PRIVATE_
+#endif
+} regsub_t;
+
+struct regdisc_s
+{
+ unsigned long re_version; /* discipline version */
+ regflags_t re_flags; /* discipline flags */
+ regerror_t re_errorf; /* error function */
+ int re_errorlevel; /* errorf level */
+ regresize_t re_resizef; /* alloc/free function */
+ void* re_resizehandle;/* resizef handle */
+ regcomp_t re_compf; /* (?{...}) compile function */
+ regexec_t re_execf; /* (?{...}) execute function */
+ unsigned char* re_map; /* external to native ccode map */
+};
+
+typedef struct regstat_s
+{
+ regflags_t re_flags; /* REG_* */
+ ssize_t re_min; /* min anchored match length */
+ ssize_t re_max; /* max anchored match length */
+ ssize_t re_record; /* regrexec() match length */
+ regflags_t re_info; /* REG_* info */
+} regstat_t;
+
+struct regex_s
+{
+ size_t re_nsub; /* number of subexpressions */
+ struct reglib_s*re_info; /* library private info */
+ size_t re_npat; /* number of pattern chars used */
+ regdisc_t* re_disc; /* REG_DISCIPLINE discipline */
+ regsub_t* re_sub; /* regsubcomp() data */
+};
+
+#define reginit(disc) (memset(disc,0,sizeof(*(disc))),(disc)->re_version=REG_VERSION)
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int regcomp(regex_t*, const char*, regflags_t);
+extern size_t regerror(int, const regex_t*, char*, size_t);
+extern int regexec(const regex_t*, const char*, size_t, regmatch_t*, regflags_t);
+extern void regfree(regex_t*);
+
+/* nonstandard hooks */
+
+#define _REG_cache 1 /* have regcache() */
+#define _REG_class 1 /* have regclass() */
+#define _REG_collate 1 /* have regcollate(), regclass() */
+#define _REG_comb 1 /* have regcomb() */
+#define _REG_decomp 1 /* have regdecomp() */
+#define _REG_dup 1 /* have regdup() */
+#define _REG_fatal 1 /* have regfatal(), regfatalpat() */
+#define _REG_ncomp 1 /* have regncomp() */
+#define _REG_nexec 1 /* have regnexec() */
+#define _REG_rexec 1 /* have regrexec(), regrecord() */
+#define _REG_stat 1 /* have regstat() */
+#define _REG_subcomp 1 /* have regsubcomp(), regsubexec() */
+
+extern regclass_t regclass(const char*, char**);
+extern int regaddclass(const char*, regclass_t);
+extern int regcollate(const char*, char**, char*, size_t, wchar_t*);
+extern int regcomb(regex_t*, regex_t*);
+extern size_t regdecomp(regex_t*, regflags_t, char*, size_t);
+extern int regdup(regex_t*, regex_t*);
+extern int regncomp(regex_t*, const char*, size_t, regflags_t);
+extern int regnexec(const regex_t*, const char*, size_t, size_t, regmatch_t*, regflags_t);
+extern void regfatal(regex_t*, int, int);
+extern void regfatalpat(regex_t*, int, int, const char*);
+extern int regrecord(const regex_t*);
+extern int regrexec(const regex_t*, const char*, size_t, size_t, regmatch_t*, regflags_t, int, void*, regrecord_t);
+extern regstat_t* regstat(const regex_t*);
+
+extern regex_t* regcache(const char*, regflags_t, int*);
+
+extern int regsubcomp(regex_t*, const char*, const regflags_t*, int, regflags_t);
+extern int regsubexec(const regex_t*, const char*, size_t, regmatch_t*);
+extern int regsubflags(regex_t*, const char*, char**, int, const regflags_t*, int*, regflags_t*);
+extern void regsubfree(regex_t*);
+
+/* obsolete hooks */
+
+#ifndef _SFIO_H
+struct _sfio_s;
+#endif
+
+extern void regalloc(void*, regresize_t, regflags_t);
+extern int regsub(const regex_t*, struct _sfio_s*, const char*, const char*, size_t, regmatch_t*, regflags_t);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/sfdisc.h b/src/lib/libast/include/sfdisc.h
new file mode 100644
index 0000000..b48eb43
--- /dev/null
+++ b/src/lib/libast/include/sfdisc.h
@@ -0,0 +1,70 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Research
+ *
+ * sfio discipline interface definitions
+ */
+
+#ifndef _SFDISC_H
+#define _SFDISC_H
+
+#include <ast.h>
+
+#define SFDCEVENT(a,b,n) ((((a)-'A'+1)<<11)^(((b)-'A'+1)<<6)^(n))
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#define SFSK_DISCARD SFDCEVENT('S','K',1)
+
+/*
+ * %(...) printf support
+ */
+
+typedef int (*Sf_key_lookup_t)(void*, Sffmt_t*, const char*, char**, Sflong_t*);
+typedef char* (*Sf_key_convert_t)(void*, Sffmt_t*, const char*, char*, Sflong_t);
+
+extern int sfkeyprintf(Sfio_t*, void*, const char*, Sf_key_lookup_t, Sf_key_convert_t);
+extern int sfkeyprintf_20000308(Sfio_t*, void*, const char*, Sf_key_lookup_t, Sf_key_convert_t);
+
+/*
+ * pure sfio read and/or write disciplines
+ */
+
+extern int sfdcdio(Sfio_t*, size_t);
+extern int sfdcdos(Sfio_t*);
+extern int sfdcfilter(Sfio_t*, const char*);
+extern int sfdcmore(Sfio_t*, const char*, int, int);
+extern int sfdcprefix(Sfio_t*, const char*);
+extern int sfdcseekable(Sfio_t*);
+extern int sfdcslow(Sfio_t*);
+extern int sfdctee(Sfio_t*, Sfio_t*);
+extern int sfdcunion(Sfio_t*, Sfio_t**, int);
+
+extern Sfio_t* sfdcsubstream(Sfio_t*, Sfio_t*, Sfoff_t, Sfoff_t);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/sfio.h b/src/lib/libast/include/sfio.h
new file mode 100644
index 0000000..1e3ede5
--- /dev/null
+++ b/src/lib/libast/include/sfio.h
@@ -0,0 +1,457 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _SFIO_H
+#define _SFIO_H 1
+
+#define SFIO_VERSION 20090915L
+
+/* Public header file for the sfio library
+**
+** Written by Kiem-Phong Vo
+*/
+
+typedef struct _sfio_s Sfio_t;
+typedef struct _sfdisc_s Sfdisc_t;
+
+#if defined(_AST_STD_H) || defined(_PACKAGE_ast) && defined(_SFIO_PRIVATE)
+#include <ast_std.h>
+#else
+#include <ast_common.h>
+#endif /* _PACKAGE_ast */
+
+/* Sfoff_t should be large enough for largest file address */
+#define Sfoff_t intmax_t
+#define Sflong_t intmax_t
+#define Sfulong_t uintmax_t
+#define Sfdouble_t _ast_fltmax_t
+
+typedef ssize_t (*Sfread_f)_ARG_((Sfio_t*, Void_t*, size_t, Sfdisc_t*));
+typedef ssize_t (*Sfwrite_f)_ARG_((Sfio_t*, const Void_t*, size_t, Sfdisc_t*));
+typedef Sfoff_t (*Sfseek_f)_ARG_((Sfio_t*, Sfoff_t, int, Sfdisc_t*));
+typedef int (*Sfexcept_f)_ARG_((Sfio_t*, int, Void_t*, Sfdisc_t*));
+typedef int (*Sfwalk_f)_ARG_((Sfio_t*, Void_t*));
+
+/* discipline structure */
+struct _sfdisc_s
+{ Sfread_f readf; /* read function */
+ Sfwrite_f writef; /* write function */
+ Sfseek_f seekf; /* seek function */
+ Sfexcept_f exceptf; /* to handle exceptions */
+ Sfdisc_t* disc; /* the continuing discipline */
+};
+
+#include <sfio_s.h>
+
+/* formatting environment */
+typedef struct _sffmt_s Sffmt_t;
+typedef int (*Sffmtext_f)_ARG_((Sfio_t*, Void_t*, Sffmt_t*));
+typedef int (*Sffmtevent_f)_ARG_((Sfio_t*, int, Void_t*, Sffmt_t*));
+struct _sffmt_s
+{ long version;/* version of this structure */
+ Sffmtext_f extf; /* function to process arguments */
+ Sffmtevent_f eventf; /* process events */
+
+ char* form; /* format string to stack */
+ va_list args; /* corresponding arg list */
+
+ int fmt; /* format character */
+ ssize_t size; /* object size */
+ int flags; /* formatting flags */
+ int width; /* width of field */
+ int precis; /* precision required */
+ int base; /* conversion base */
+
+ char* t_str; /* type string */
+ ssize_t n_str; /* length of t_str */
+
+ Void_t* mbs; /* multibyte state for format string */
+
+ Void_t* none; /* unused for now */
+};
+#define sffmtversion(fe,type) \
+ ((type) ? ((fe)->version = SFIO_VERSION) : (fe)->version)
+
+#define SFFMT_SSHORT 000000010 /* 'hh' flag, char */
+#define SFFMT_TFLAG 000000020 /* 't' flag, ptrdiff_t */
+#define SFFMT_ZFLAG 000000040 /* 'z' flag, size_t */
+
+#define SFFMT_LEFT 000000100 /* left-justification */
+#define SFFMT_SIGN 000000200 /* must have a sign */
+#define SFFMT_BLANK 000000400 /* if not signed, prepend a blank */
+#define SFFMT_ZERO 000001000 /* zero-padding on the left */
+#define SFFMT_ALTER 000002000 /* alternate formatting */
+#define SFFMT_THOUSAND 000004000 /* thousand grouping */
+#define SFFMT_SKIP 000010000 /* skip assignment in scanf() */
+#define SFFMT_SHORT 000020000 /* 'h' flag */
+#define SFFMT_LONG 000040000 /* 'l' flag */
+#define SFFMT_LLONG 000100000 /* 'll' flag */
+#define SFFMT_LDOUBLE 000200000 /* 'L' flag */
+#define SFFMT_VALUE 000400000 /* value is returned */
+#define SFFMT_ARGPOS 001000000 /* getting arg for $ patterns */
+#define SFFMT_IFLAG 002000000 /* 'I' flag */
+#define SFFMT_JFLAG 004000000 /* 'j' flag, intmax_t */
+#define SFFMT_CENTER 010000000 /* '=' flag, center justification */
+#define SFFMT_CHOP 020000000 /* chop long string values from left */
+#define SFFMT_SET 037777770 /* flags settable on calling extf */
+
+/* for sfmutex() call */
+#define SFMTX_LOCK 0 /* up mutex count */
+#define SFMTX_TRYLOCK 1 /* try to up mutex count */
+#define SFMTX_UNLOCK 2 /* down mutex count */
+#define SFMTX_CLRLOCK 3 /* clear mutex count */
+
+/* various constants */
+#ifndef NULL
+#define NULL 0
+#endif
+#ifndef EOF
+#define EOF (-1)
+#endif
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+/* bits for various types of files */
+#define SF_READ 0000001 /* open for reading */
+#define SF_WRITE 0000002 /* open for writing */
+#define SF_STRING 0000004 /* a string stream */
+#define SF_APPENDWR 0000010 /* file is in append mode only */
+#define SF_MALLOC 0000020 /* buffer is malloc-ed */
+#define SF_LINE 0000040 /* line buffering */
+#define SF_SHARE 0000100 /* stream with shared file descriptor */
+#define SF_EOF 0000200 /* eof was detected */
+#define SF_ERROR 0000400 /* an error happened */
+#define SF_STATIC 0001000 /* a stream that cannot be freed */
+#define SF_IOCHECK 0002000 /* call exceptf before doing IO */
+#define SF_PUBLIC 0004000 /* SF_SHARE and follow physical seek */
+#define SF_MTSAFE 0010000 /* need thread safety */
+#define SF_WHOLE 0020000 /* preserve wholeness of sfwrite/sfputr */
+#define SF_IOINTR 0040000 /* return on interrupts */
+#define SF_WCWIDTH 0100000 /* wcwidth display stream */
+
+#define SF_FLAGS 0177177 /* PUBLIC FLAGS PASSABLE TO SFNEW() */
+#define SF_SETS 0177163 /* flags passable to sfset() */
+
+#ifndef _SF_NO_OBSOLETE
+#define SF_BUFCONST 0400000 /* unused flag - for compatibility only */
+#endif
+
+/* for sfgetr/sfreserve to hold a record */
+#define SF_LOCKR 0000010 /* lock record, stop access to stream */
+#define SF_LASTR 0000020 /* get the last incomplete record */
+
+/* exception events: SF_NEW(0), SF_READ(1), SF_WRITE(2) and the below */
+#define SF_SEEK 3 /* seek error */
+#define SF_CLOSING 4 /* when stream is about to be closed */
+#define SF_DPUSH 5 /* when discipline is being pushed */
+#define SF_DPOP 6 /* when discipline is being popped */
+#define SF_DPOLL 7 /* see if stream is ready for I/O */
+#define SF_DBUFFER 8 /* buffer not empty during push or pop */
+#define SF_SYNC 9 /* announcing start/end synchronization */
+#define SF_PURGE 10 /* a sfpurge() call was issued */
+#define SF_FINAL 11 /* closing is done except stream free */
+#define SF_READY 12 /* a polled stream is ready */
+#define SF_LOCKED 13 /* stream is in a locked state */
+#define SF_ATEXIT 14 /* process is exiting */
+#define SF_EVENT 100 /* start of user-defined events */
+
+/* for stack and disciplines */
+#define SF_POPSTACK ((Sfio_t*)0) /* pop the stream stack */
+#define SF_POPDISC ((Sfdisc_t*)0) /* pop the discipline stack */
+
+/* for the notify function and discipline exception */
+#define SF_NEW 0 /* new stream */
+#define SF_SETFD (-1) /* about to set the file descriptor */
+#define SF_MTACCESS (-2) /* starting a multi-threaded stream */
+
+#define SF_BUFSIZE 8192 /* default buffer size */
+#define SF_UNBOUND (-1) /* unbounded buffer size */
+
+/* namespace incursion workarounds -- migrate to the new names */
+#if !_mac_SF_APPEND
+#define SF_APPEND SF_APPENDWR /* BSDI sys/stat.h */
+#endif
+#if !_mac_SF_CLOSE
+#define SF_CLOSE SF_CLOSING /* AIX sys/socket.h */
+#endif
+
+_BEGIN_EXTERNS_
+
+#if _BLD_sfio && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+#if !_BLD_sfio && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern ssize_t _Sfi;
+extern ssize_t _Sfmaxr;
+
+/* standard in/out/err streams */
+extern Sfio_t* sfstdin;
+extern Sfio_t* sfstdout;
+extern Sfio_t* sfstderr;
+
+#if _UWIN
+#undef extern
+#endif
+
+extern Sfio_t _Sfstdin;
+extern Sfio_t _Sfstdout;
+extern Sfio_t _Sfstderr;
+
+#undef extern
+
+#if _BLD_sfio && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern Sfio_t* sfnew _ARG_((Sfio_t*, Void_t*, size_t, int, int));
+extern Sfio_t* sfopen _ARG_((Sfio_t*, const char*, const char*));
+extern Sfio_t* sfpopen _ARG_((Sfio_t*, const char*, const char*));
+extern Sfio_t* sfstack _ARG_((Sfio_t*, Sfio_t*));
+extern Sfio_t* sfswap _ARG_((Sfio_t*, Sfio_t*));
+extern Sfio_t* sftmp _ARG_((size_t));
+extern int sfwalk _ARG_((Sfwalk_f, Void_t*, int));
+extern int sfpurge _ARG_((Sfio_t*));
+extern int sfpoll _ARG_((Sfio_t**, int, int));
+extern Void_t* sfreserve _ARG_((Sfio_t*, ssize_t, int));
+extern int sfresize _ARG_((Sfio_t*, Sfoff_t));
+extern int sfsync _ARG_((Sfio_t*));
+extern int sfclrlock _ARG_((Sfio_t*));
+extern Void_t* sfsetbuf _ARG_((Sfio_t*, Void_t*, size_t));
+extern Sfdisc_t* sfdisc _ARG_((Sfio_t*,Sfdisc_t*));
+extern int sfraise _ARG_((Sfio_t*, int, Void_t*));
+extern int sfnotify _ARG_((void(*)(Sfio_t*, int, void*)));
+extern int sfset _ARG_((Sfio_t*, int, int));
+extern int sfsetfd _ARG_((Sfio_t*, int));
+extern Sfio_t* sfpool _ARG_((Sfio_t*, Sfio_t*, int));
+extern ssize_t sfread _ARG_((Sfio_t*, Void_t*, size_t));
+extern ssize_t sfwrite _ARG_((Sfio_t*, const Void_t*, size_t));
+extern Sfoff_t sfmove _ARG_((Sfio_t*, Sfio_t*, Sfoff_t, int));
+extern int sfclose _ARG_((Sfio_t*));
+extern Sfoff_t sftell _ARG_((Sfio_t*));
+extern Sfoff_t sfseek _ARG_((Sfio_t*, Sfoff_t, int));
+extern ssize_t sfputr _ARG_((Sfio_t*, const char*, int));
+extern char* sfgetr _ARG_((Sfio_t*, int, int));
+extern ssize_t sfnputc _ARG_((Sfio_t*, int, size_t));
+extern int sfungetc _ARG_((Sfio_t*, int));
+extern int sfprintf _ARG_((Sfio_t*, const char*, ...));
+extern char* sfprints _ARG_((const char*, ...));
+extern ssize_t sfaprints _ARG_((char**, const char*, ...));
+extern ssize_t sfsprintf _ARG_((char*, size_t, const char*, ...));
+extern ssize_t sfvsprintf _ARG_((char*, size_t, const char*, va_list));
+extern ssize_t sfvasprints _ARG_((char**, const char*, va_list));
+extern int sfvprintf _ARG_((Sfio_t*, const char*, va_list));
+extern int sfscanf _ARG_((Sfio_t*, const char*, ...));
+extern int sfsscanf _ARG_((const char*, const char*, ...));
+extern int sfvsscanf _ARG_((const char*, const char*, va_list));
+extern int sfvscanf _ARG_((Sfio_t*, const char*, va_list));
+
+/* mutex locking for thread-safety */
+extern int sfmutex _ARG_((Sfio_t*, int));
+
+/* io functions with discipline continuation */
+extern ssize_t sfrd _ARG_((Sfio_t*, Void_t*, size_t, Sfdisc_t*));
+extern ssize_t sfwr _ARG_((Sfio_t*, const Void_t*, size_t, Sfdisc_t*));
+extern Sfoff_t sfsk _ARG_((Sfio_t*, Sfoff_t, int, Sfdisc_t*));
+extern ssize_t sfpkrd _ARG_((int, Void_t*, size_t, int, long, int));
+
+/* portable handling of primitive types */
+extern int sfdlen _ARG_((Sfdouble_t));
+extern int sfllen _ARG_((Sflong_t));
+extern int sfulen _ARG_((Sfulong_t));
+
+extern int sfputd _ARG_((Sfio_t*, Sfdouble_t));
+extern int sfputl _ARG_((Sfio_t*, Sflong_t));
+extern int sfputu _ARG_((Sfio_t*, Sfulong_t));
+extern int sfputm _ARG_((Sfio_t*, Sfulong_t, Sfulong_t));
+extern int sfputc _ARG_((Sfio_t*, int));
+
+extern Sfdouble_t sfgetd _ARG_((Sfio_t*));
+extern Sflong_t sfgetl _ARG_((Sfio_t*));
+extern Sfulong_t sfgetu _ARG_((Sfio_t*));
+extern Sfulong_t sfgetm _ARG_((Sfio_t*, Sfulong_t));
+extern int sfgetc _ARG_((Sfio_t*));
+
+extern int _sfputd _ARG_((Sfio_t*, Sfdouble_t));
+extern int _sfputl _ARG_((Sfio_t*, Sflong_t));
+extern int _sfputu _ARG_((Sfio_t*, Sfulong_t));
+extern int _sfputm _ARG_((Sfio_t*, Sfulong_t, Sfulong_t));
+extern int _sfflsbuf _ARG_((Sfio_t*, int));
+
+extern int _sffilbuf _ARG_((Sfio_t*, int));
+
+extern int _sfdlen _ARG_((Sfdouble_t));
+extern int _sfllen _ARG_((Sflong_t));
+extern int _sfulen _ARG_((Sfulong_t));
+
+/* miscellaneous function analogues of fast in-line functions */
+extern Sfoff_t sfsize _ARG_((Sfio_t*));
+extern int sfclrerr _ARG_((Sfio_t*));
+extern int sfeof _ARG_((Sfio_t*));
+extern int sferror _ARG_((Sfio_t*));
+extern int sffileno _ARG_((Sfio_t*));
+extern int sfstacked _ARG_((Sfio_t*));
+extern ssize_t sfvalue _ARG_((Sfio_t*));
+extern ssize_t sfslen _ARG_((void));
+extern ssize_t sfmaxr _ARG_((ssize_t, int));
+
+#undef extern
+_END_EXTERNS_
+
+/* coding long integers in a portable and compact fashion */
+#define SF_SBITS 6
+#define SF_UBITS 7
+#define SF_BBITS 8
+#define SF_SIGN (1 << SF_SBITS)
+#define SF_MORE (1 << SF_UBITS)
+#define SF_BYTE (1 << SF_BBITS)
+#define SF_U1 SF_MORE
+#define SF_U2 (SF_U1*SF_U1)
+#define SF_U3 (SF_U2*SF_U1)
+#define SF_U4 (SF_U3*SF_U1)
+
+#if __cplusplus
+#define _SF_(f) (f)
+#else
+#define _SF_(f) ((Sfio_t*)(f))
+#endif
+
+#define __sf_putd(f,v) (_sfputd(_SF_(f),(Sfdouble_t)(v)))
+#define __sf_putl(f,v) (_sfputl(_SF_(f),(Sflong_t)(v)))
+#define __sf_putu(f,v) (_sfputu(_SF_(f),(Sfulong_t)(v)))
+#define __sf_putm(f,v,m) (_sfputm(_SF_(f),(Sfulong_t)(v),(Sfulong_t)(m)))
+
+#define __sf_putc(f,c) (_SF_(f)->_next >= _SF_(f)->_endw ? \
+ _sfflsbuf(_SF_(f),(int)((unsigned char)(c))) : \
+ (int)(*_SF_(f)->_next++ = (unsigned char)(c)) )
+#define __sf_getc(f) (_SF_(f)->_next >= _SF_(f)->_endr ? _sffilbuf(_SF_(f),0) : \
+ (int)(*_SF_(f)->_next++) )
+
+#define __sf_dlen(v) (_sfdlen((Sfdouble_t)(v)) )
+#define __sf_llen(v) (_sfllen((Sflong_t)(v)) )
+#define __sf_ulen(v) ((Sfulong_t)(v) < SF_U1 ? 1 : (Sfulong_t)(v) < SF_U2 ? 2 : \
+ (Sfulong_t)(v) < SF_U3 ? 3 : (Sfulong_t)(v) < SF_U4 ? 4 : 5)
+
+#define __sf_fileno(f) (_SF_(f)->_file)
+#define __sf_eof(f) (_SF_(f)->_flags&SF_EOF)
+#define __sf_error(f) (_SF_(f)->_flags&SF_ERROR)
+#define __sf_clrerr(f) (_SF_(f)->_flags &= ~(SF_ERROR|SF_EOF))
+#define __sf_stacked(f) (_SF_(f)->_push != (Sfio_t*)0)
+#define __sf_value(f) (_SF_(f)->_val)
+#define __sf_slen() (_Sfi)
+#define __sf_maxr(n,s) ((s)?((_Sfi=_Sfmaxr),(_Sfmaxr=(n)),_Sfi):_Sfmaxr)
+
+#if defined(__INLINE__) && !_BLD_sfio
+
+__INLINE__ int sfputd(Sfio_t* f, Sfdouble_t v) { return __sf_putd(f,v); }
+__INLINE__ int sfputl(Sfio_t* f, Sflong_t v) { return __sf_putl(f,v); }
+__INLINE__ int sfputu(Sfio_t* f, Sfulong_t v) { return __sf_putu(f,v); }
+__INLINE__ int sfputm(Sfio_t* f, Sfulong_t v, Sfulong_t m)
+ { return __sf_putm(f,v,m); }
+
+__INLINE__ int sfputc(Sfio_t* f, int c) { return __sf_putc(f,c); }
+__INLINE__ int sfgetc(Sfio_t* f) { return __sf_getc(f); }
+
+__INLINE__ int sfdlen(Sfdouble_t v) { return __sf_dlen(v); }
+__INLINE__ int sfllen(Sflong_t v) { return __sf_llen(v); }
+__INLINE__ int sfulen(Sfulong_t v) { return __sf_ulen(v); }
+
+__INLINE__ int sffileno(Sfio_t* f) { return __sf_fileno(f); }
+__INLINE__ int sfeof(Sfio_t* f) { return __sf_eof(f); }
+__INLINE__ int sferror(Sfio_t* f) { return __sf_error(f); }
+__INLINE__ int sfclrerr(Sfio_t* f) { return __sf_clrerr(f); }
+__INLINE__ int sfstacked(Sfio_t* f) { return __sf_stacked(f); }
+__INLINE__ ssize_t sfvalue(Sfio_t* f) { return __sf_value(f); }
+__INLINE__ ssize_t sfslen() { return __sf_slen(); }
+__INLINE__ ssize_t sfmaxr(ssize_t n, int s) { return __sf_maxr(n,s); }
+
+#else
+
+#define sfputd(f,v) ( __sf_putd((f),(v)) )
+#define sfputl(f,v) ( __sf_putl((f),(v)) )
+#define sfputu(f,v) ( __sf_putu((f),(v)) )
+#define sfputm(f,v,m) ( __sf_putm((f),(v),(m)) )
+
+#define sfputc(f,c) ( __sf_putc((f),(c)) )
+#define sfgetc(f) ( __sf_getc(f) )
+
+#define sfdlen(v) ( __sf_dlen(v) )
+#define sfllen(v) ( __sf_llen(v) )
+#define sfulen(v) ( __sf_ulen(v) )
+
+#define sffileno(f) ( __sf_fileno(f) )
+#define sfeof(f) ( __sf_eof(f) )
+#define sferror(f) ( __sf_error(f) )
+#define sfclrerr(f) ( __sf_clrerr(f) )
+#define sfstacked(f) ( __sf_stacked(f) )
+#define sfvalue(f) ( __sf_value(f) )
+#define sfslen() ( __sf_slen() )
+#define sfmaxr(n,s) ( __sf_maxr(n,s) )
+
+#endif /*__INLINE__*/
+
+#ifndef _SFSTR_H /* GSF's string manipulation stuff */
+#define _SFSTR_H 1
+
+#define sfstropen() sfnew(0, 0, -1, -1, SF_READ|SF_WRITE|SF_STRING)
+#define sfstrclose(f) sfclose(f)
+
+#define sfstrseek(f,p,m) \
+ ( (m) == SEEK_SET ? \
+ (((p) < 0 || (p) > (f)->_size) ? (char*)0 : \
+ (char*)((f)->_next = (f)->_data+(p)) ) \
+ : (m) == SEEK_CUR ? \
+ ((f)->_next += (p), \
+ (((f)->_next < (f)->_data || (f)->_next > (f)->_data+(f)->_size) ? \
+ ((f)->_next -= (p), (char*)0) : (char*)(f)->_next ) ) \
+ : (m) == SEEK_END ? \
+ ( ((p) > 0 || (f)->_size+(p) < 0) ? (char*)0 : \
+ (char*)((f)->_next = (f)->_data+(f)->_size+(p)) ) \
+ : (char*)0 \
+ )
+
+#define sfstrsize(f) ((f)->_size)
+#define sfstrtell(f) ((f)->_next - (f)->_data)
+#define sfstrpend(f) ((f)->_size - sfstrtell())
+#define sfstrbase(f) ((char*)(f)->_data)
+
+#define sfstruse(f) \
+ (sfputc((f),0) < 0 ? (char*)0 : (char*)((f)->_next = (f)->_data) \
+ )
+
+#define sfstrrsrv(f,n) \
+ (sfreserve((f),(n),SF_WRITE|SF_LOCKR), sfwrite((f),(f)->_next,0), \
+ ((f)->_next+(n) <= (f)->_data+(f)->_size ? (char*)(f)->_next : (char*)0) \
+ )
+
+#define sfstrbuf(f,b,n,m) \
+ (sfsetbuf((f),(b),(n)), ((f)->_flags |= (m) ? SF_MALLOC : 0), \
+ ((f)->_data == (unsigned char*)(b) ? 0 : -1) \
+ )
+
+#endif /* _SFSTR_H */
+
+#endif /* _SFIO_H */
diff --git a/src/lib/libast/include/sfio_s.h b/src/lib/libast/include/sfio_s.h
new file mode 100644
index 0000000..0fb33de
--- /dev/null
+++ b/src/lib/libast/include/sfio_s.h
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _SFIO_S_H
+#define _SFIO_S_H 1
+
+/*
+ * sfio file structure used by sfio and the stdio source compatibility library
+ */
+
+#if !defined(_SFHDR_H) && defined(_SFIO_H) && SFIO_VERSION < 20020214L
+#define _data data
+#define _endb endb
+#define _next next
+#endif
+
+struct _sfio_s
+{ unsigned char* _next; /* next position to read/write from */
+ unsigned char* _endw; /* end of write buffer */
+ unsigned char* _endr; /* end of read buffer */
+ unsigned char* _endb; /* end of buffer */
+ struct _sfio_s* _push; /* the stream that was pushed on */
+ unsigned short _flags; /* type of stream */
+ short _file; /* file descriptor */
+ unsigned char* _data; /* base of data buffer */
+ ssize_t _size; /* buffer size */
+ ssize_t _val; /* values or string lengths */
+#ifdef _SFIO_PRIVATE
+ _SFIO_PRIVATE
+#endif
+};
+
+#endif
diff --git a/src/lib/libast/include/sfio_t.h b/src/lib/libast/include/sfio_t.h
new file mode 100644
index 0000000..9ff54a8
--- /dev/null
+++ b/src/lib/libast/include/sfio_t.h
@@ -0,0 +1,126 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _SFIO_T_H
+#define _SFIO_T_H 1
+
+/* This header file is for library writers who need to know certain
+** internal info concerning the full Sfio_t structure. Including this
+** file means that you agree to track closely with sfio development
+** in case its internal architecture is changed.
+**
+** Written by Kiem-Phong Vo
+*/
+
+/* the parts of Sfio_t private to sfio functions */
+#define _SFIO_PRIVATE \
+ Sfoff_t extent; /* current file size */ \
+ Sfoff_t here; /* current physical location */ \
+ unsigned char getr; /* the last sfgetr separator */ \
+ unsigned char tiny[1];/* for unbuffered read stream */ \
+ unsigned short bits; /* private flags */ \
+ unsigned int mode; /* current io mode */ \
+ struct _sfdisc_s* disc; /* discipline */ \
+ struct _sfpool_s* pool; /* the pool containing this */ \
+ struct _sfrsrv_s* rsrv; /* reserved buffer */ \
+ struct _sfproc_s* proc; /* coprocess id, etc. */ \
+ Void_t* mutex; /* mutex for thread-safety */ \
+ Void_t* stdio; /* stdio FILE if any */ \
+ Sfoff_t lpos; /* last seek position */ \
+ size_t iosz; /* preferred size for I/O */ \
+ size_t blksz; /* preferred block size */ \
+ Void_t* fill[1];/* modest expansion */
+
+#include "sfio.h"
+
+/* mode bit to indicate that the structure hasn't been initialized */
+#define SF_INIT 0000004
+#define SF_DCDOWN 00010000
+
+/* short-hand for common stream types */
+#define SF_RDWR (SF_READ|SF_WRITE)
+#define SF_RDSTR (SF_READ|SF_STRING)
+#define SF_WRSTR (SF_WRITE|SF_STRING)
+#define SF_RDWRSTR (SF_RDWR|SF_STRING)
+
+/* for static initialization of an Sfio_t structure */
+#define SFNEW(data,size,file,type,disc,mutex) \
+ { (unsigned char*)(data), /* next */ \
+ (unsigned char*)(data), /* endw */ \
+ (unsigned char*)(data), /* endr */ \
+ (unsigned char*)(data), /* endb */ \
+ (Sfio_t*)0, /* push */ \
+ (unsigned short)((type)&SF_FLAGS), /* flags */ \
+ (short)(file), /* file */ \
+ (unsigned char*)(data), /* data */ \
+ (ssize_t)(size), /* size */ \
+ (ssize_t)(-1), /* val */ \
+ (Sfoff_t)0, /* extent */ \
+ (Sfoff_t)0, /* here */ \
+ 0, /* getr */ \
+ {0}, /* tiny */ \
+ 0, /* bits */ \
+ (unsigned int)(((type)&(SF_RDWR))|SF_INIT), /* mode */ \
+ (struct _sfdisc_s*)(disc), /* disc */ \
+ (struct _sfpool_s*)0, /* pool */ \
+ (struct _sfrsrv_s*)0, /* rsrv */ \
+ (struct _sfproc_s*)0, /* proc */ \
+ (mutex), /* mutex */ \
+ (Void_t*)0, /* stdio */ \
+ (Sfoff_t)0, /* lpos */ \
+ (size_t)0 /* iosz */ \
+ }
+
+/* function to clear an Sfio_t structure */
+#define SFCLEAR(f,mtx) \
+ ( (f)->next = (unsigned char*)0, /* next */ \
+ (f)->endw = (unsigned char*)0, /* endw */ \
+ (f)->endr = (unsigned char*)0, /* endr */ \
+ (f)->endb = (unsigned char*)0, /* endb */ \
+ (f)->push = (Sfio_t*)0, /* push */ \
+ (f)->flags = (unsigned short)0, /* flags */ \
+ (f)->file = -1, /* file */ \
+ (f)->data = (unsigned char*)0, /* data */ \
+ (f)->size = (ssize_t)(-1), /* size */ \
+ (f)->val = (ssize_t)(-1), /* val */ \
+ (f)->extent = (Sfoff_t)(-1), /* extent */ \
+ (f)->here = (Sfoff_t)0, /* here */ \
+ (f)->getr = 0, /* getr */ \
+ (f)->tiny[0] = 0, /* tiny */ \
+ (f)->bits = 0, /* bits */ \
+ (f)->mode = 0, /* mode */ \
+ (f)->disc = (struct _sfdisc_s*)0, /* disc */ \
+ (f)->pool = (struct _sfpool_s*)0, /* pool */ \
+ (f)->rsrv = (struct _sfrsrv_s*)0, /* rsrv */ \
+ (f)->proc = (struct _sfproc_s*)0, /* proc */ \
+ (f)->mutex = (mtx), /* mutex */ \
+ (f)->stdio = (Void_t*)0, /* stdio */ \
+ (f)->lpos = (Sfoff_t)0, /* lpos */ \
+ (f)->iosz = (size_t)0 /* iosz */ \
+ )
+
+/* expose next stream inside discipline function; state saved in int f */
+#define SFDCNEXT(sp,f) (((f)=(sp)->bits&SF_DCDOWN),(sp)->bits|=SF_DCDOWN)
+
+/* restore SFDCNEXT() state from int f */
+#define SFDCPREV(sp,f) ((f)?(0):((sp)->bits&=~SF_DCDOWN))
+
+#endif /* _SFIO_T_H */
diff --git a/src/lib/libast/include/shcmd.h b/src/lib/libast/include/shcmd.h
new file mode 100644
index 0000000..16acdac
--- /dev/null
+++ b/src/lib/libast/include/shcmd.h
@@ -0,0 +1,112 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * ksh builtin command api
+ */
+
+#ifndef _SHCMD_H
+#define _SHCMD_H 1
+
+#ifndef AST_PLUGIN_VERSION
+#define AST_PLUGIN_VERSION(v) (v)
+#endif
+#define SH_PLUGIN_VERSION AST_PLUGIN_VERSION(20111111L)
+
+#if __STDC__
+#define SHLIB(m) unsigned long plugin_version(void) { return SH_PLUGIN_VERSION; }
+#else
+#define SHLIB(m) unsigned long plugin_version() { return SH_PLUGIN_VERSION; }
+#endif
+
+#ifndef SH_VERSION
+# define Shell_t void
+#endif
+#ifndef NV_DEFAULT
+# define Namval_t void
+#endif
+
+#undef Shbltin_t
+struct Shbltin_s;
+typedef struct Shbltin_s Shbltin_t;
+
+#ifdef _SHTABLE_H /* pre-ksh93u+ -- obsolete */
+typedef int (*Shbltin_f)(int, char**, void*);
+#else
+typedef int (*Shbltin_f)(int, char**, Shbltin_t*);
+#endif /* _SHTABLE_H */
+
+struct Shbltin_s
+{
+ Shell_t* shp;
+ void* ptr;
+ int version;
+ int (*shrun)(int, char**);
+ int (*shtrap)(const char*, int);
+ void (*shexit)(int);
+ Namval_t* (*shbltin)(const char*, Shbltin_f, void*);
+ unsigned char notify;
+ unsigned char sigset;
+ unsigned char nosfio;
+ Namval_t* bnode;
+ Namval_t* vnode;
+ char* data;
+ int flags;
+ char* (*shgetenv)(const char*);
+ char* (*shsetenv)(const char*);
+ int invariant;
+};
+
+#if defined(SH_VERSION) || defined(_SH_PRIVATE)
+# undef Shell_t
+# undef Namval_t
+#else
+# define sh_context(c) ((Shbltin_t*)(c))
+# define sh_run(c, ac, av) ((c)?(*sh_context(c)->shrun)(ac,av):-1)
+# define sh_system(c,str) ((c)?(*sh_context(c)->shtrap)(str,0):system(str))
+# define sh_exit(c,n) ((c)?(*sh_context(c)->shexit)(n):exit(n))
+# define sh_checksig(c) ((c) && sh_context(c)->sigset)
+# define sh_builtin(c,n,f,p) ((c)?(*sh_context(c)->shbltin)(n,(Shbltin_f)(f),sh_context(p)):0)
+# if defined(SFIO_VERSION) || defined(_AST_H)
+# define LIB_INIT(c)
+# else
+# define LIB_INIT(c) ((c) && (sh_context(c)->nosfio = 1))
+# endif
+# ifndef _CMD_H
+# ifndef ERROR_NOTIFY
+# define ERROR_NOTIFY 1
+# endif
+# define cmdinit(ac,av,c,cat,flg) do { if((ac)<=0) return(0); \
+ (sh_context(c)->notify = ((flg)&ERROR_NOTIFY)?1:0);} while(0)
+# endif
+#endif
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int astintercept(Shbltin_t*, int);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/stack.h b/src/lib/libast/include/stack.h
new file mode 100644
index 0000000..593a08c
--- /dev/null
+++ b/src/lib/libast/include/stack.h
@@ -0,0 +1,83 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * homogenous stack routine definitions
+ */
+
+#ifndef _STACK_H
+#define _STACK_H
+
+typedef struct stacktable* STACK; /* stack pointer */
+typedef struct stackposition STACKPOS; /* stack position */
+
+struct stackblock /* stack block cell */
+{
+ void** stack; /* actual stack */
+ struct stackblock* prev; /* previous block in list */
+ struct stackblock* next; /* next block in list */
+};
+
+struct stackposition /* stack position */
+{
+ struct stackblock* block; /* current block pointer */
+ int index; /* index within current block */
+};
+
+struct stacktable /* stack information */
+{
+ struct stackblock* blocks; /* stack table blocks */
+ void* error; /* error return value */
+ int size; /* size of each block */
+ STACKPOS position; /* current stack position */
+};
+
+/*
+ * map old names to new
+ */
+
+#define mkstack stackalloc
+#define rmstack stackfree
+#define clrstack stackclear
+#define getstack stackget
+#define pushstack stackpush
+#define popstack stackpop
+#define posstack stacktell
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern STACK stackalloc(int, void*);
+extern void stackfree(STACK);
+extern void stackclear(STACK);
+extern void* stackget(STACK);
+extern int stackpush(STACK, void*);
+extern int stackpop(STACK);
+extern void stacktell(STACK, int, STACKPOS*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/stak.h b/src/lib/libast/include/stak.h
new file mode 100644
index 0000000..ee34773
--- /dev/null
+++ b/src/lib/libast/include/stak.h
@@ -0,0 +1,55 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Research
+ *
+ * Interface definitions for a stack-like storage library
+ *
+ */
+
+#ifndef _STAK_H
+#define _STAK_H
+
+#include <stk.h>
+
+#define Stak_t Sfio_t
+#define staksp stkstd
+#define STAK_SMALL STK_SMALL
+
+#define stakptr(n) stkptr(stkstd,n)
+#define staktell() stktell(stkstd)
+#define stakputc(c) sfputc(stkstd,(c))
+#define stakwrite(b,n) sfwrite(stkstd,(b),(n))
+#define stakputs(s) (sfputr(stkstd,(s),0),--stkstd->_next)
+#define stakseek(n) stkseek(stkstd,n)
+#define stakcreate(n) stkopen(n)
+#define stakinstall(s,f) stkinstall(s,f)
+#define stakdelete(s) stkclose(s)
+#define staklink(s) stklink(s)
+#define stakalloc(n) stkalloc(stkstd,n)
+#define stakcopy(s) stkcopy(stkstd,s)
+#define stakset(c,n) stkset(stkstd,c,n)
+#define stakfreeze(n) stkfreeze(stkstd,n)
+
+#endif
diff --git a/src/lib/libast/include/stk.h b/src/lib/libast/include/stk.h
new file mode 100644
index 0000000..851e408
--- /dev/null
+++ b/src/lib/libast/include/stk.h
@@ -0,0 +1,78 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Research
+ *
+ * Interface definitions for a stack-like storage library
+ *
+ */
+
+#ifndef _STK_H
+#define _STK_H
+
+#include <sfio.h>
+
+#define _Stk_data _Stak_data
+
+#define stkstd (&_Stk_data)
+
+#define Stk_t Sfio_t
+
+#define STK_SMALL 1 /* small stkopen stack */
+#define STK_NULL 2 /* return NULL on overflow */
+
+#define stkptr(sp,n) ((char*)((sp)->_data)+(n))
+#define stktop(sp) ((char*)(sp)->_next)
+#define stktell(sp) ((sp)->_next-(sp)->_data)
+#define stkseek(sp,n) ((n)==0?(char*)((sp)->_next=(sp)->_data):_stkseek(sp,n))
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+#if !_BLD_ast && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern Sfio_t _Stk_data;
+
+#undef extern
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern Stk_t* stkopen(int);
+extern Stk_t* stkinstall(Stk_t*, char*(*)(int));
+extern int stkclose(Stk_t*);
+extern int stklink(Stk_t*);
+extern char* stkalloc(Stk_t*, size_t);
+extern char* stkcopy(Stk_t*, const char*);
+extern char* stkset(Stk_t*, char*, size_t);
+extern char* _stkseek(Stk_t*, ssize_t);
+extern char* stkfreeze(Stk_t*, size_t);
+extern int stkon(Stk_t*, char*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/swap.h b/src/lib/libast/include/swap.h
new file mode 100644
index 0000000..03a81f4
--- /dev/null
+++ b/src/lib/libast/include/swap.h
@@ -0,0 +1,53 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * integral representation conversion support definitions
+ * supports sizeof(integral_type)<=sizeof(intmax_t)
+ */
+
+#ifndef _SWAP_H
+#define _SWAP_H
+
+#include <ast_common.h>
+
+#define int_swap _ast_intswap
+
+#define SWAP_MAX 8
+
+#define SWAPOP(n) (((n)&int_swap)^(n))
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern void* swapmem(int, const void*, void*, size_t);
+extern intmax_t swapget(int, const void*, int);
+extern void* swapput(int, void*, int, intmax_t);
+extern int swapop(const void*, const void*, int);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/tar.h b/src/lib/libast/include/tar.h
new file mode 100644
index 0000000..847d6c6
--- /dev/null
+++ b/src/lib/libast/include/tar.h
@@ -0,0 +1,118 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Standard Archive Format
+ * USTAR - Uniform Standard Tape ARchive
+ */
+
+#ifndef _TAR_H
+#define _TAR_H
+
+#define TBLOCK 512
+#define NAMSIZ 100
+#define PFXSIZ 155
+
+#define TMODLEN 8
+#define TUIDLEN 8
+#define TGIDLEN 8
+#define TSIZLEN 12
+#define TMTMLEN 12
+#define TCKSLEN 8
+
+#define TMAGIC "ustar" /* ustar and a null */
+#define TMAGLEN 6
+#define TVERSION "00" /* 00 and no null */
+#define TVERSLEN 2
+#define TUNMLEN 32
+#define TGNMLEN 32
+#define TDEVLEN 8
+
+/*
+ * values used in typeflag field
+ */
+
+#define REGTYPE '0' /* regular file */
+#define AREGTYPE 0 /* alternate REGTYPE */
+#define LNKTYPE '1' /* hard link */
+#define SYMTYPE '2' /* soft link */
+#define CHRTYPE '3' /* character special */
+#define BLKTYPE '4' /* block special */
+#define DIRTYPE '5' /* directory */
+#define FIFOTYPE '6' /* FIFO special */
+#define CONTTYPE '7' /* reserved */
+#define SOKTYPE '8' /* socket */
+#define EXTTYPE 'x' /* extended header */
+#define GLBTYPE 'g' /* global extended header */
+#define LLNKTYPE 'K' /* long link path */
+#define LREGTYPE 'L' /* long file path */
+#define VERTYPE 'V' /* version */
+
+/*
+ * bits used in mode field
+ */
+
+#define TSUID 04000 /* set uid on exec */
+#define TSGID 02000 /* set gid on exec */
+#define TSVTX 01000 /* sticky bit -- reserved */
+
+/*
+ * file permissions
+ */
+
+#define TUREAD 00400 /* read by owner */
+#define TUWRITE 00200 /* write by owner */
+#define TUEXEC 00100 /* execute by owner */
+#define TGREAD 00040 /* read by group */
+#define TGWRITE 00020 /* execute by group */
+#define TGEXEC 00010 /* write by group */
+#define TOREAD 00004 /* read by other */
+#define TOWRITE 00002 /* write by other */
+#define TOEXEC 00001 /* execute by other */
+
+struct header
+{
+ char name[NAMSIZ];
+ char mode[TMODLEN];
+ char uid[TUIDLEN];
+ char gid[TGIDLEN];
+ char size[TSIZLEN];
+ char mtime[TMTMLEN];
+ char chksum[TCKSLEN];
+ char typeflag;
+ char linkname[NAMSIZ];
+ char magic[TMAGLEN];
+ char version[TVERSLEN];
+ char uname[TUNMLEN];
+ char gname[TGNMLEN];
+ char devmajor[TDEVLEN];
+ char devminor[TDEVLEN];
+ char prefix[PFXSIZ];
+};
+
+union hblock
+{
+ char dummy[TBLOCK];
+ struct header dbuf;
+};
+
+#endif
diff --git a/src/lib/libast/include/times.h b/src/lib/libast/include/times.h
new file mode 100644
index 0000000..c0c458d
--- /dev/null
+++ b/src/lib/libast/include/times.h
@@ -0,0 +1,54 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * -last clock_t,time_t interface definitions plus
+ *
+ * <ast.h>
+ * <time.h>
+ * <sys/time.h>
+ * <sys/times.h>
+ */
+
+#ifndef _TIMES_H
+#define _TIMES_H
+
+#include <ast.h>
+
+#undef _TIMES_H
+#include <ast_time.h>
+#ifndef _TIMES_H
+#define _TIMES_H
+#endif
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int touch(const char*, time_t, time_t, int);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/tm.h b/src/lib/libast/include/tm.h
new file mode 100644
index 0000000..bbd5980
--- /dev/null
+++ b/src/lib/libast/include/tm.h
@@ -0,0 +1,192 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time conversion support definitions
+ */
+
+#ifndef _TM_H
+#define _TM_H
+
+#define TM_VERSION 20070319L
+
+#include <ast.h>
+#include <times.h>
+
+#undef daylight
+
+#define tmset(z) tminit(z)
+#define tmisleapyear(y) (!((y)%4)&&(((y)%100)||!((((y)<1900)?((y)+1900):(y))%400)))
+
+#define TM_ADJUST (1<<0) /* local doesn't do leap secs */
+#define TM_LEAP (1<<1) /* do leap seconds */
+#define TM_UTC (1<<2) /* universal coordinated ref */
+
+#define TM_PEDANTIC (1<<3) /* pedantic date parse */
+#define TM_DATESTYLE (1<<4) /* date(1) style mmddHHMMccyy */
+#define TM_SUBSECOND (1<<5) /* <something>%S => ...%S.%P */
+
+#define TM_DST (-60) /* default minutes for DST */
+#define TM_LOCALZONE (25 * 60) /* use local time zone offset */
+#define TM_UTCZONE (26 * 60) /* UTC "time zone" */
+#define TM_MAXLEAP 1 /* max leap secs per leap */
+#define TM_WINDOW 69 /* century windowing guard year */
+
+/*
+ * these indices must agree with tm_dform[]
+ */
+
+#define TM_MONTH_ABBREV 0
+#define TM_MONTH 12
+#define TM_DAY_ABBREV 24
+#define TM_DAY 31
+#define TM_TIME 38
+#define TM_DATE 39
+#define TM_DEFAULT 40
+#define TM_MERIDIAN 41
+
+#define TM_UT 43
+#define TM_DT 47
+#define TM_SUFFIXES 51
+#define TM_PARTS 55
+#define TM_HOURS 62
+#define TM_DAYS 66
+#define TM_LAST 69
+#define TM_THIS 72
+#define TM_NEXT 75
+#define TM_EXACT 78
+#define TM_NOISE 81
+#define TM_ORDINAL 85
+#define TM_DIGITS 95
+#define TM_CTIME 105
+#define TM_DATE_1 106
+#define TM_INTERNATIONAL 107
+#define TM_RECENT 108
+#define TM_DISTANT 109
+#define TM_MERIDIAN_TIME 110
+#define TM_ERA 111
+#define TM_ERA_DATE 112
+#define TM_ERA_TIME 113
+#define TM_ERA_DEFAULT 114
+#define TM_ERA_YEAR 115
+#define TM_ORDINALS 116
+#define TM_FINAL 126
+#define TM_WORK 129
+
+#define TM_NFORM 132
+
+typedef struct /* leap second info */
+{
+ time_t time; /* the leap second event */
+ int total; /* inclusive total since epoch */
+} Tm_leap_t;
+
+typedef struct /* time zone info */
+{
+ char* type; /* type name */
+ char* standard; /* standard time name */
+ char* daylight; /* daylight or summertime name */
+ short west; /* minutes west of GMT */
+ short dst; /* add to tz.west for DST */
+} Tm_zone_t;
+
+typedef struct /* tm library readonly data */
+{
+ char** format; /* default TM_* format strings */
+ unsigned char* lex; /* format lex type classes */
+ char* digit; /* output digits */
+ short* days; /* days in month i */
+ short* sum; /* days in months before i */
+ Tm_leap_t* leap; /* leap second table */
+ Tm_zone_t* zone; /* alternate timezone table */
+} Tm_data_t;
+
+typedef struct /* tm library global info */
+{
+ char* deformat; /* TM_DEFAULT override */
+ int flags; /* flags */
+ char** format; /* current format strings */
+ Tm_zone_t* date; /* timezone from last tmdate() */
+ Tm_zone_t* local; /* local timezone */
+ Tm_zone_t* zone; /* current timezone */
+} Tm_info_t;
+
+typedef struct Tm_s
+{
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+ uint32_t tm_nsec;
+ Tm_zone_t* tm_zone;
+} Tm_t;
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+#if !_BLD_ast && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern Tm_data_t* _tm_datap_;
+extern Tm_info_t* _tm_infop_;
+
+#define tm_data (*_tm_datap_)
+#define tm_info (*_tm_infop_)
+
+#undef extern
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern time_t tmdate(const char*, char**, time_t*);
+extern int tmequiv(Tm_t*);
+extern Tm_t* tmfix(Tm_t*);
+extern char* tmfmt(char*, size_t, const char*, time_t*);
+extern char* tmform(char*, const char*, time_t*);
+extern int tmgoff(const char*, char**, int);
+extern void tminit(Tm_zone_t*);
+extern time_t tmleap(time_t*);
+extern int tmlex(const char*, char**, char**, int, char**, int);
+extern char** tmlocale(void);
+extern Tm_t* tmmake(time_t*);
+extern char* tmpoff(char*, size_t, const char*, int, int);
+extern time_t tmscan(const char*, char**, const char*, char**, time_t*, long);
+extern int tmsleep(time_t, time_t);
+extern time_t tmtime(Tm_t*, int);
+extern Tm_zone_t* tmtype(const char*, char**);
+extern int tmweek(Tm_t*, int, int, int);
+extern int tmword(const char*, char**, const char*, char**, int);
+extern Tm_zone_t* tmzone(const char*, char**, const char*, int*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/tok.h b/src/lib/libast/include/tok.h
new file mode 100644
index 0000000..f898218
--- /dev/null
+++ b/src/lib/libast/include/tok.h
@@ -0,0 +1,47 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * token stream interface definitions
+ */
+
+#ifndef _TOK_H
+#define _TOK_H
+
+#include <ast.h>
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern Sfio_t* tokline(const char*, int, int*);
+extern int tokscan(char*, char**, const char*, ...);
+extern char* tokopen(char*, int);
+extern void tokclose(char*);
+extern char* tokread(char*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/usage.h b/src/lib/libast/include/usage.h
new file mode 100644
index 0000000..c1ba317
--- /dev/null
+++ b/src/lib/libast/include/usage.h
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * error catalog and usage defaults
+ */
+
+#ifndef _USAGE_H
+#define _USAGE_H
+
+#ifndef ERROR_CATALOG
+#define ERROR_CATALOG 0
+#endif
+
+#ifndef USAGE_LICENSE
+#define USAGE_LICENSE "[-license?THIS IS AN UNLICENSED COPY]"
+#endif
+
+#endif
diff --git a/src/lib/libast/include/vdb.h b/src/lib/libast/include/vdb.h
new file mode 100644
index 0000000..e647215
--- /dev/null
+++ b/src/lib/libast/include/vdb.h
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * virtual db file directory entry constants
+ */
+
+#ifndef VDB_MAGIC
+
+#define VDB_MAGIC "vdb"
+
+#define VDB_DIRECTORY "DIRECTORY"
+#define VDB_UNION "UNION"
+#define VDB_DATE "DATE"
+#define VDB_MODE "MODE"
+
+#define VDB_DELIMITER ';'
+#define VDB_IGNORE '_'
+#define VDB_FIXED 10
+#define VDB_LENGTH ((int)sizeof(VDB_DIRECTORY)+2*(VDB_FIXED+1))
+#define VDB_OFFSET ((int)sizeof(VDB_DIRECTORY))
+#define VDB_SIZE (VDB_OFFSET+VDB_FIXED+1)
+
+#endif
diff --git a/src/lib/libast/include/vecargs.h b/src/lib/libast/include/vecargs.h
new file mode 100644
index 0000000..548c0b4
--- /dev/null
+++ b/src/lib/libast/include/vecargs.h
@@ -0,0 +1,45 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * vector argument interface definitions
+ */
+
+#ifndef _VECARGS_H
+#define _VECARGS_H
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int vecargs(char**, int*, char***);
+extern char** vecfile(const char*);
+extern void vecfree(char**, int);
+extern char** vecload(char*);
+extern char** vecstring(const char*);
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/include/vmalloc.h b/src/lib/libast/include/vmalloc.h
new file mode 100644
index 0000000..4825143
--- /dev/null
+++ b/src/lib/libast/include/vmalloc.h
@@ -0,0 +1,335 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _VMALLOC_H
+#define _VMALLOC_H 1
+
+/* Public header file for the virtual malloc package.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/1994.
+*/
+
+#define VMALLOC_VERSION 20110808L
+
+#if _PACKAGE_ast
+#include <ast_std.h>
+#else
+#include <ast_common.h>
+#endif
+
+typedef struct _vmalloc_s Vmalloc_t;
+typedef struct _vmstat_s Vmstat_t;
+typedef struct _vmdisc_s Vmdisc_t;
+typedef struct _vmethod_s Vmethod_t;
+typedef struct _vmdata_s Vmdata_t;
+typedef Void_t* (*Vmemory_f)_ARG_((Vmalloc_t*, Void_t*, size_t, size_t, Vmdisc_t*));
+typedef int (*Vmexcept_f)_ARG_((Vmalloc_t*, int, Void_t*, Vmdisc_t*));
+
+struct _vmstat_s
+{ int n_busy; /* number of busy blocks */
+ int n_free; /* number of free blocks */
+ size_t s_busy; /* total amount of busy space */
+ size_t s_free; /* total amount of free space */
+ size_t m_busy; /* largest busy piece */
+ size_t m_free; /* largest free piece */
+ int n_seg; /* number of segments */
+ size_t extent; /* total size of region */
+ int n_region; /* #parallel regions (Vmregion) */
+ int n_open; /* #calls that finds open reg */
+ int n_lock; /* #calls where reg was locked */
+ int n_probe; /* #probes to find a region */
+ int mode; /* region mode bits */
+};
+
+struct _vmdisc_s
+{ Vmemory_f memoryf; /* memory manipulator */
+ Vmexcept_f exceptf; /* exception handler */
+ size_t round; /* rounding requirement */
+ size_t size; /* actual size of discipline */
+};
+
+struct _vmethod_s
+{ Void_t* (*allocf)_ARG_((Vmalloc_t*,size_t,int));
+ Void_t* (*resizef)_ARG_((Vmalloc_t*,Void_t*,size_t,int,int));
+ int (*freef)_ARG_((Vmalloc_t*,Void_t*,int));
+ long (*addrf)_ARG_((Vmalloc_t*,Void_t*,int));
+ long (*sizef)_ARG_((Vmalloc_t*,Void_t*,int));
+ int (*compactf)_ARG_((Vmalloc_t*,int));
+ Void_t* (*alignf)_ARG_((Vmalloc_t*,size_t,size_t,int));
+ unsigned short meth;
+};
+
+struct _vmalloc_s
+{ Vmethod_t meth; /* method for allocation */
+ char* file; /* file name */
+ int line; /* line number */
+ char* func; /* calling function */
+ Vmdisc_t* disc; /* discipline to get space */
+ Vmdata_t* data; /* the real region data */
+ Vmalloc_t* next; /* linked list of regions */
+};
+
+#define VM_TRUST 0000000 /* obsolete */
+#define VM_TRACE 0000001 /* generate traces of calls */
+#define VM_DBCHECK 0000002 /* check for boundary overwrite */
+#define VM_DBABORT 0000004 /* abort on any warning */
+#define VM_SHARE 0000010 /* sharable across processes */
+#define VM_MEMORYF 0000020 /* vm was allocated by memoryf */
+#define VM_FLAGS 0000017 /* user-settable flags */
+
+#define VM_MTBEST 0000100 /* Vmbest method */
+#define VM_MTPOOL 0000200 /* Vmpool method */
+#define VM_MTLAST 0000400 /* Vmlast method */
+#define VM_MTDEBUG 0001000 /* Vmdebug method */
+#define VM_MTPROFILE 0002000 /* Vmdebug method */
+#define VM_METHODS 0003700 /* available allocation methods */
+
+#define VM_RSCOPY 0000001 /* copy old contents */
+#define VM_RSMOVE 0000002 /* old contents is moveable */
+#define VM_RSZERO 0000004 /* clear new space */
+
+/* exception types */
+#define VM_OPEN 1 /* region being opened */
+#define VM_ENDOPEN 2 /* end of region opening */
+#define VM_CLOSE 3 /* announce being closed */
+#define VM_ENDCLOSE 4 /* end of region closing */
+#define VM_DISC 5 /* discipline being changed */
+#define VM_NOMEM 6 /* can't obtain memory */
+#define VM_BADADDR (-1) /* currently a no-op */
+
+/* for application-specific data in shared/persistent regions */
+#define VM_MMGET 0 /* get data value (void*) */
+#define VM_MMSET 1 /* set data value (void*) */
+#define VM_MMADD 2 /* add data value (long) */
+
+_BEGIN_EXTERNS_ /* public data */
+#if _BLD_vmalloc && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+#if !_BLD_vmalloc && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern Vmethod_t* Vmbest; /* best allocation */
+extern Vmethod_t* Vmlast; /* last-block allocation */
+extern Vmethod_t* Vmpool; /* pool allocation */
+extern Vmethod_t* Vmdebug; /* allocation with debugging */
+extern Vmethod_t* Vmprofile; /* profiling memory usage */
+
+extern Vmdisc_t* Vmdcsystem; /* get memory from the OS */
+extern Vmdisc_t* Vmdcheap; /* get memory from Vmheap */
+extern Vmdisc_t* Vmdcsbrk; /* like Vmdcsystem - legacy use */
+
+extern Vmalloc_t _Vmheap; /* heap region - use with care! */
+extern Vmalloc_t* Vmheap; /* = &_Vmheap - safe to use */
+extern Vmalloc_t* Vmregion; /* malloc region */
+
+#undef extern
+_END_EXTERNS_
+
+_BEGIN_EXTERNS_ /* public functions */
+#if _BLD_vmalloc && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern Vmalloc_t* vmopen _ARG_(( Vmdisc_t*, Vmethod_t*, int ));
+extern int vmclose _ARG_(( Vmalloc_t* ));
+extern int vmclear _ARG_(( Vmalloc_t* ));
+extern int vmcompact _ARG_(( Vmalloc_t* ));
+
+extern Vmdisc_t* vmdisc _ARG_(( Vmalloc_t*, Vmdisc_t* ));
+
+extern Vmalloc_t* vmmopen _ARG_(( char*, int, ssize_t ));
+extern Void_t* vmmvalue _ARG_(( Vmalloc_t*, int, Void_t*, int ));
+extern void vmmrelease _ARG_(( Vmalloc_t*, int ));
+extern Void_t* vmmaddress _ARG_(( size_t ));
+
+extern Void_t* vmalloc _ARG_(( Vmalloc_t*, size_t ));
+extern Void_t* vmalign _ARG_(( Vmalloc_t*, size_t, size_t ));
+extern Void_t* vmresize _ARG_(( Vmalloc_t*, Void_t*, size_t, int ));
+extern Void_t* vmgetmem _ARG_(( Vmalloc_t*, Void_t*, size_t ));
+extern int vmfree _ARG_(( Vmalloc_t*, Void_t* ));
+
+extern long vmaddr _ARG_(( Vmalloc_t*, Void_t* ));
+extern long vmsize _ARG_(( Vmalloc_t*, Void_t* ));
+
+extern Vmalloc_t* vmregion _ARG_(( Void_t* ));
+extern Void_t* vmsegment _ARG_(( Vmalloc_t*, Void_t* ));
+extern int vmset _ARG_(( Vmalloc_t*, int, int ));
+
+extern Void_t* vmdbwatch _ARG_(( Void_t* ));
+extern int vmdbcheck _ARG_(( Vmalloc_t* ));
+extern int vmdebug _ARG_(( int ));
+
+extern int vmprofile _ARG_(( Vmalloc_t*, int ));
+
+extern int vmtrace _ARG_(( int ));
+extern int vmtrbusy _ARG_((Vmalloc_t*));
+
+extern int vmstat _ARG_((Vmalloc_t*, Vmstat_t*));
+
+extern int vmwalk _ARG_((Vmalloc_t*,
+ int(*)(Vmalloc_t*,Void_t*,size_t,Vmdisc_t*,Void_t*), Void_t*));
+extern char* vmstrdup _ARG_((Vmalloc_t*, const char*));
+
+#if !defined(_BLD_vmalloc) && !defined(_AST_STD_H) && \
+ !defined(__stdlib_h) && !defined(__STDLIB_H) && \
+ !defined(_STDLIB_INCLUDED) && !defined(_INC_STDLIB)
+extern Void_t* malloc _ARG_(( size_t ));
+extern Void_t* realloc _ARG_(( Void_t*, size_t ));
+extern void free _ARG_(( Void_t* ));
+extern void cfree _ARG_(( Void_t* ));
+extern Void_t* calloc _ARG_(( size_t, size_t ));
+extern Void_t* memalign _ARG_(( size_t, size_t ));
+extern Void_t* valloc _ARG_(( size_t ));
+#endif
+extern int setregmax _ARG_(( int ));
+
+#undef extern
+_END_EXTERNS_
+
+/* to coerce any value to a Vmalloc_t*, make ANSI happy */
+#define _VM_(vm) ((Vmalloc_t*)(vm))
+
+/* enable recording of where a call originates from */
+#ifdef VMFL
+
+#if defined(__FILE__)
+#define _VMFILE_(vm) (_VM_(vm)->file = (char*)__FILE__)
+#else
+#define _VMFILE_(vm) (_VM_(vm)->file = (char*)0)
+#endif
+
+#if defined(__LINE__)
+#define _VMLINE_(vm) (_VM_(vm)->line = __LINE__)
+#else
+#define _VMLINE_(vm) (_VM_(vm)->line = 0)
+#endif
+
+#if defined(__FUNCTION__)
+#define _VMFUNC_(vm) (_VM_(vm)->func = (char*)__FUNCTION__)
+#else
+#define _VMFUNC_(vm) (_VM_(vm)->func = (char*)0)
+#endif
+
+#define _VMFL_(vm) (_VMFILE_(vm), _VMLINE_(vm), _VMFUNC_(vm))
+
+#define vmalloc(vm,sz) (_VMFL_(vm), \
+ (*(_VM_(vm)->meth.allocf))((vm),(sz),0) )
+#define vmresize(vm,d,sz,type) (_VMFL_(vm), \
+ (*(_VM_(vm)->meth.resizef))\
+ ((vm),(Void_t*)(d),(sz),(type),0) )
+#define vmfree(vm,d) (_VMFL_(vm), \
+ (*(_VM_(vm)->meth.freef))((vm),(Void_t*)(d),0) )
+#define vmalign(vm,sz,align) (_VMFL_(vm), \
+ (*(_VM_(vm)->meth.alignf))((vm),(sz),(align),0) )
+
+#undef malloc
+#undef realloc
+#undef calloc
+#undef free
+#undef memalign
+#undef valloc
+
+#if _map_malloc
+
+#define malloc(s) (_VMFL_(Vmregion), _ast_malloc((size_t)(s)) )
+#define realloc(d,s) (_VMFL_(Vmregion), _ast_realloc((Void_t*)(d),(size_t)(s)) )
+#define calloc(n,s) (_VMFL_(Vmregion), _ast_calloc((size_t)n, (size_t)(s)) )
+#define free(d) (_VMFL_(Vmregion), _ast_free((Void_t*)(d)) )
+#define memalign(a,s) (_VMFL_(Vmregion), _ast_memalign((size_t)(a),(size_t)(s)) )
+#define valloc(s) (_VMFL_(Vmregion), _ast_valloc((size_t)(s) )
+
+#else
+
+#if !_std_malloc
+
+#if __STD_C || defined(__STDPP__) || defined(__GNUC__)
+
+#define malloc(s) (_VMFL_(Vmregion), malloc((size_t)(s)) )
+#define realloc(d,s) (_VMFL_(Vmregion), realloc((Void_t*)(d),(size_t)(s)) )
+#define calloc(n,s) (_VMFL_(Vmregion), calloc((size_t)n, (size_t)(s)) )
+#define free(d) (_VMFL_(Vmregion), free((Void_t*)(d)) )
+#define memalign(a,s) (_VMFL_(Vmregion), memalign((size_t)(a),(size_t)(s)) )
+#define valloc(s) (_VMFL_(Vmregion), valloc((size_t)(s) )
+#ifndef strdup
+#define strdup(s) ( _VMFL_(Vmregion), (strdup)((char*)(s)) )
+#endif
+
+#else
+
+#define _VMNM_(a,b,c,d,e,f) a/**/b/**/c/**/d/**/e/**/f
+#define malloc(s) (_VMFL_(Vmregion), _VMNM_(mallo,/,*,*,/,c)\
+ ((size_t)(s)) )
+#define realloc(d,s) (_VMFL_(Vmregion), _VMNM_(reallo,/,*,*,/,c)\
+ ((Void_t*)(d),(size_t)(s)) )
+#define calloc(n,s) (_VMFL_(Vmregion), _VMNM_(callo,/,*,*,/,c)\
+ ((size_t)n, (size_t)(s)) )
+#define free(d) (_VMFL_(Vmregion), _VMNM_(fre,/,*,*,/,e)((Void_t*)(d)) )
+#define memalign(a,s) (_VMFL_(Vmregion), _VMNM_(memalig,/,*,*,/,n)\
+ ((size_t)(a),(size_t)(s)) )
+#define valloc(s) (_VMFL_(Vmregion), _VMNM_(vallo,/,*,*,/,c)\
+ ((size_t)(s) )
+#ifndef strdup
+#define strdup(s) ( _VMFL_(Vmregion), _VMNM_(strdu,/,*,*,/,p)\
+ ((char*)(s)) )
+#endif
+
+#endif /*__STD_C || defined(__STDPP__) || defined(__GNUC__)*/
+
+#define cfree(d) free(d)
+
+#endif /*!_std_malloc*/
+
+#endif /*_map_malloc*/
+
+#endif /*VMFL*/
+
+/* non-debugging/profiling allocation calls */
+#ifndef vmalloc
+#define vmalloc(vm,sz) (*(_VM_(vm)->meth.allocf))((vm),(sz),0)
+#endif
+
+#ifndef vmresize
+#define vmresize(vm,d,sz,type) (*(_VM_(vm)->meth.resizef))\
+ ((vm),(Void_t*)(d),(sz),(type),0)
+#endif
+
+#ifndef vmfree
+#define vmfree(vm,d) (*(_VM_(vm)->meth.freef))((vm),(Void_t*)(d),0)
+#endif
+
+#ifndef vmalign
+#define vmalign(vm,sz,align) (*(_VM_(vm)->meth.alignf))((vm),(sz),(align),0)
+#endif
+
+#define vmaddr(vm,addr) (*(_VM_(vm)->meth.addrf))((vm),(Void_t*)(addr),0)
+#define vmsize(vm,addr) (*(_VM_(vm)->meth.sizef))((vm),(Void_t*)(addr),0)
+#define vmcompact(vm) (*(_VM_(vm)->meth.compactf))((vm),0)
+#define vmoldof(v,p,t,n,x) (t*)vmresize((v), (p), sizeof(t)*(n)+(x), \
+ (VM_RSMOVE) )
+#define vmnewof(v,p,t,n,x) (t*)vmresize((v), (p), sizeof(t)*(n)+(x), \
+ (VM_RSMOVE|VM_RSCOPY|VM_RSZERO) )
+
+#define vmdata(vm) ((Void_t*)(_VM_(vm)->data) )
+#define vmlocked(vm) (*((unsigned int*)(_VM_(vm)->data)) )
+
+#endif /* _VMALLOC_H */
diff --git a/src/lib/libast/include/wait.h b/src/lib/libast/include/wait.h
new file mode 100644
index 0000000..0dff619
--- /dev/null
+++ b/src/lib/libast/include/wait.h
@@ -0,0 +1,98 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * ast POSIX wait/exit support
+ */
+
+#ifndef _WAIT_H
+#define _WAIT_H
+
+#include <ast.h>
+#include <ast_wait.h>
+
+#if _sys_wait
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide wait waitpid
+#else
+#define wait ______wait
+#define waitpid ______waitpid
+#endif
+#include <sys/wait.h>
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide wait waitpid
+#else
+#undef wait
+#undef waitpid
+#endif
+#endif
+
+#ifndef WNOHANG
+#define WNOHANG 1
+#endif
+
+#ifndef WUNTRACED
+#define WUNTRACED 2
+#endif
+
+#if !_ok_wif
+#undef WIFEXITED
+#undef WEXITSTATUS
+#undef WIFSIGNALED
+#undef WTERMSIG
+#undef WIFSTOPPED
+#undef WSTOPSIG
+#undef WTERMCORE
+#endif
+
+#ifndef WIFEXITED
+#define WIFEXITED(x) (!((x)&((1<<(EXIT_BITS-1))-1)))
+#endif
+
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(x) (((x)>>EXIT_BITS)&((1<<EXIT_BITS)-1))
+#endif
+
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(x) (((x)&((1<<(EXIT_BITS-1))-1))!=0)
+#endif
+
+#ifndef WTERMSIG
+#define WTERMSIG(x) ((x)&((1<<(EXIT_BITS-1))-1))
+#endif
+
+#ifndef WIFSTOPPED
+#define WIFSTOPPED(x) (((x)&((1<<EXIT_BITS)-1))==((1<<(EXIT_BITS-1))-1))
+#endif
+
+#ifndef WSTOPSIG
+#define WSTOPSIG(x) WEXITSTATUS(x)
+#endif
+
+#ifndef WTERMCORE
+#define WTERMCORE(x) ((x)&(1<<(EXIT_BITS-1)))
+#endif
+
+extern pid_t wait(int*);
+extern pid_t waitpid(pid_t, int*, int);
+
+#endif
diff --git a/src/lib/libast/man/LIBAST.3 b/src/lib/libast/man/LIBAST.3
new file mode 100644
index 0000000..380ebde
--- /dev/null
+++ b/src/lib/libast/man/LIBAST.3
@@ -0,0 +1,98 @@
+.fp 5 CW
+.de Af
+.if \\$2 .nr ;G \\$1
+.ie !\\$3 \{\
+\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8"
+\}
+..
+.de aF
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8"
+.ft \\n(;G
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH LIBAST 3
+.UC 4
+.SH NAME
+libast \- introduction to the ast library
+.SH DESCRIPTION
+This section describes the
+.I AST
+(AT&T Software Technology) library functions of the
+.B libast
+library.
+.B libast
+serves three major purposes.
+First, it presents (a subset of) POSIX/ANSI standard headers and interfaces on
+non-compliant systems.
+Second, it provides a portable base of routines that implement concepts
+common to all UNIX system variants.
+Finally, it is a forum for
+modern implementations of features present (or lacking)
+in the standard C libraries.
+Features better provided by separate libraries are omitted from
+.BR libast .
+For example, most terminal driver interface issues are left for
+special purpose libraries such as
+.IR curses (3).
+.PP
+The
+.B libast
+related header files are installed in the directories
+.LR include/ast .
+Routines that do not advertize their own headers are prototyped in
+.LR <ast.h> .
+.L <ast.h>
+is ANSI, K&R and C++ compatible and includes or defines the equivalent of
+.LR <limits.h> ,
+.LR <stddef.h> ,
+.LR <stdlib.h> ,
+.LR <sys/types.h> ,
+.L <string.h>
+and
+.LR <unistd.h> .
+Other libraries that depend on
+.B libast
+may also have headers installed in the
+.L include/ast
+directories.
+.SH FILES
+.nf
+include/ast the \fBast\fP package header directory
+lib/libast.a the \fBlibast\fP library
+lib/libast-g.a the \fBlibast\fP library compiled for debugging
+lib/libast-pg.a the \fBlibast\fP library compiled for profiling
+lib/libast.so.4.0 the \fBlibast\fP shared library
+.fi
+.SH "SEE ALSO"
+intro(3),
+intro(2),
+cc(1)
+.SH CAVEATS
+The library documentation is still under construction.
+Yes, some of it has been in this state for 20 years.
+Thank goodness our commands self-document.
diff --git a/src/lib/libast/man/aso.3 b/src/lib/libast/man/aso.3
new file mode 100644
index 0000000..0e41d30
--- /dev/null
+++ b/src/lib/libast/man/aso.3
@@ -0,0 +1,355 @@
+.fp 5 CW
+.TH LIBASO 3
+.SH NAME
+\fBASO\fP \- Atomic Scalar Operations
+.SH SYNOPSIS
+.de Tp
+.fl
+.ne 2
+.TP
+..
+.de Ss
+.fl
+.ne 2
+.SS "\\$1"
+..
+.de Cs
+.nf
+.ft 5
+..
+.de Ce
+.ft 1
+.fi
+..
+.ta 1.0i 2.0i 3.0i 4.0i 5.0i
+.Cs
+#include <aso.h>
+.Ce
+.Ss "TYPES"
+.Cs
+typedef int (*Asoerror_f)(int, const char*);
+typedef void* (*Asoinit_f)(void*, const char*);
+typedef ssize_t (*Asolock_f)(void*, ssize_t, void volatile*);
+
+typedef struct Asodisc_s
+{
+ uint32_t version;
+ unsigned int hung;
+ Asoerror_f errorf;
+} Asodisc_t;
+
+typedef struct Asometh_s
+{
+ const char* name;
+ int type;
+ Asoinit_f initf;
+ Asolock_f lockf;
+ const char* details;
+} Asometh_t;
+.Ce
+.Ss "OPERATIONS"
+.Cs
+uint8_t asocas8(uint8_t volatile*, int, int);
+uint8_t asoget8(uint8_t volatile*);
+uint8_t asoinc8(uint8_t volatile*);
+uint8_t asodec8(uint8_t volatile*);
+
+uint16_t asocas16(uint16_t volatile*, uint16_t, uint16_t);
+uint16_t asoget16(uint16_t volatile*);
+uint16_t asoinc16(uint16_t volatile*);
+uint16_t asodec16(uint16_t volatile*);
+
+uint32_t asocas32(uint32_t volatile*, uint32_t, uint32_t);
+uint32_t asoget32(uint32_t volatile*);
+uint32_t asoinc32(uint32_t volatile*);
+uint32_t asodec32(uint32_t volatile*);
+
+uint64_t asocas64(uint64_t volatile*, uint64_t, uint64_t);
+uint64_t asoget64(uint64_t volatile*);
+uint64_t asoinc64(uint64_t volatile*);
+uint64_t asodec64(uint64_t volatile*);
+
+unsigned char asocaschar(unsigned char volatile*, int, int);
+unsigned char asogetchar(unsigned char volatile*);
+unsigned char asoincchar(unsigned char volatile*);
+unsigned char asodecchar(unsigned char volatile*);
+
+unsigned short asocasshort(unsigned short volatile*, unsigned short, unsigned short);
+unsigned short asogetshort(unsigned short volatile*);
+unsigned short asoincshort(unsigned short volatile*);
+unsigned short asodecshort(unsigned short volatile*);
+
+unsigned int asocasint(unsigned int volatile*, unsigned int, unsigned int);
+unsigned int asogetint(unsigned int volatile*);
+unsigned int asoincint(unsigned int volatile*);
+unsigned int asodecint(unsigned int volatile*);
+
+unsigned long asocaslong(unsigned long volatile*, unsigned long, unsigned long);
+unsigned long asogetlong(unsigned long volatile*);
+unsigned long asoinclong(unsigned long volatile*);
+unsigned long asodeclong(unsigned long volatile*);
+
+size_t asocassize(size_t volatile*, size_t, size_t);
+size_t asogetsize(size_t volatile*);
+size_t asoincsize(size_t volatile*);
+size_t asodecsize(size_t volatile*);
+
+void* asocasptr(void volatile*, void*, void*);
+void* asogetptr(void volatile*);
+
+void ASODISC(Asodisc_t*, Asoerror_f);
+Asometh_t* asometh(int, void*);
+int asoinit(const char*, Asometh_t*, Asodisc_t*);
+int asolock(unsigned int volatile*, unsigned int, int);
+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 \f5uint32_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
+\f5uint8_t, uint16_t, uint32_t, uint64_t\fP
+
+These are \fIunsigned integer\fP types of different sizes in bits.
+For example, \f5uint32_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 \f5*from\fP.
+.PP
+.Ss " uint32_t asoinc32(uint32_t* dest);"
+.Ss " uint32_t asodec32(uint32_t* dest);"
+These functions increment \f5*dest\fP by 1 and decrement \f5*dest\fP by 1 in an atomic step.
+The return value is the old value in \f5*dest\fP.
+
+Consider an example where two concurrent threads/processes call \f5asoinc32()\fP
+on the same \f5dest\fP with values, say \fIv1\fP and \fIv2\fP.
+The eventual value in \f5dest\fP
+will be as if \f5*dest += 2\fP was performed in a single-threaded execution.
+
+That should be constrasted with a situation where, instead of \f5asoinc32()\fP or \f5asodec32()\fP,
+only normal increment (++) or decrement (--) were used.
+Then, the end result could be either \f5*dest += 1\fP or \f5*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 \f5dest\fP is equal to \f5tstval\fP then it will be set to \f5newval\fP.
+If multiple threads/processes are performing the same operations only one will succeed with a
+return value of \f5tstval\fP.
+The return value is the old value in \f5*dest\fP.
+.PP
+.Ss " void asorelax(long nsec)"
+This function causes the calling process or thread to briefly pause
+for \f5nsec\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 \f5key\fP, a non-zero unsigned integer, to lock or unlock the \f5lock\fP.
+It returns \f50\fP on success and \f5-1\fP on failure.
+The argument \f5type\fP can take one of the following values:
+.Tp
+\f5ASO_UNLOCK\fP:
+This unlocks the lock if it was locked with \f5key\fP. It is an error to try
+unlocking a lock of a different key.
+.Tp
+\f5ASO_TRYLOCK\fP:
+This makes a single attempt to use the given \f5key\fP to acquire a lock.
+An error will result if the lock is already locked with a different key.
+.Tp
+\f5ASO_LOCK\fP:
+This is a regular locking call. If the lock is locked with a different key,
+this call will wait until the lock is open, then lock it with the given \f5key\fP.
+.Tp
+\f5ASO_SPINLOCK\fP:
+Regardless of what key is currently locking the lock,
+this call will always wait until the lock is open, then lock it with the given \f5key\fP.
+Note that, if the lock is already locked with \f5key\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
+uintmax_t iteration;
+iteration = 0;
+for (;;) {
+ /* test resource with an aso*() call */
+ if (asoloop(++iteration))
+ /* an error occurred */;
+}
+.Ce
+The value of \f5iteration\fP should be \f51\fP (\fInot\fP \f50\fP) for the first loop iteration.
+\f50\fP is returned on success, \f5-1\fP on failure.
+If \f5iteration mod 4\fP is \f50\fP then \f5asorelax(1)\fP is called to temporarily relinquish
+the processor.
+If \f5Asodisc_t.hung != 0\fP and \f5Asodisc_t.errorf != 0\fP and
+\f5iteration mod (2**Asodisc_t.hung-1)\fP is \f50\fP,
+then \f5Asodisc_t.errorf\fP is called with type \f5ASO_HUNG\fP
+and \f5-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 \f5asoinit()\fP function, described below.
+The structure members are:
+.Tp
+\f5uint32_t version;\fP
+This must be set to \f5ASO_VERSION\fP by the caller and is used by the implementation to detect
+release differences between the caller and the implementation.
+The version is integer of the form \fIYYYYMMDD\fP where \fIYYYY\fP is the release year, \fIMM\fP
+is the release month, and \fIDD\fP is the release day of month.
+This allows the implementation to be forwards and backwards binary compatible with all releases.
+.Tp
+\f5unsigned int hung;\fP
+An error occurs if \f5asoloop\fP() is called \f52**Asometh_t.hung\fP times without gaining access to the loop resource.
+The default value \f50\fP disables the test.
+.Tp
+\f5Asoerror_f errorf;\fP
+\f5int (*errorf)(int type, const char* mesg);\fP
+If \f5errorf\fP != \f50\fP then it is called for each \fIASO\fP fatal library condition.
+\f5type\fP may be one of: \f5ASO_METHOD\fP - a method error; \f5ASO_HUNG\fP - \f5asoloop\fP() was called
+\f52**Asometh_t.hung\fP times with no access to the loop resource.
+\f5mesg\fP is a 0-terminated messsage description.
+.Ss " void ASODISC(Asodisc_t* disc, Asoerror_f errorf);"
+.PP
+This function-like-macro initializes \f5disc->version = ASO_VERSION\fP, \f5disc->errorf = errorf\fP,
+and the remaining \f5disc\fP members to \f50\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 \f5asometh()\fP and \f5asoinit()\fP
+functions, described below.
+The \fIASO\fP method is global for all threads and forked children of the current process.
+A given method may have multiple types.
+The methods types are:
+.Tp
+\f5ASO_INTRINSIC\fP:
+Some hardware platforms provide machine instructions to implement these operations directly.
+In that case, if a local compiler permits, calls to these \fIintrinsic\fP functions
+may be translated directly into their corresponding machine instructions.
+When necessary the implementation can use only the intrinsic \fIcompare-and-swap\fP
+function on the largest integer type to emulate all other \fIASO\fP operations.
+The \f5ASO_INTRINSIC\fP method type is the default when supported by the compiler.
+It may be used for single-process single-thread, multi-thread, and
+multi-process applications.
+When supported by the hardware / compiler, the library provides the "\fBintrinsic\fP" method with type
+\f5ASO_INTRINSIC|ASO_PROCESS|ASO_THREAD|ASO_SIGNAL\fP.
+.Tp
+\f5ASO_SIGNAL\fP:
+This method type is suitable only for single-process single-thread applications.
+It can be used to provide locking between asyncronous \fBsignal\fP(2) handlers
+and the main program.
+The library provides the "\fBsignal\fP" method with type \f5ASO_SIGNAL\fP.
+This is the default method type when \f5ASO_INTRINSIC\fP is not supported.
+.Tp
+\f5ASO_THREAD\fP:
+This method type is suitable for single-process single-thread, and multi-thread applications.
+It typically requires thread library support, and since the default \f5aso\fP library
+is not linked with a thread library, no \f5ASO_THREAD\fP method is provided by default.
+Threaded applications must link with \fB-ltaso\fP (before \fB-laso\fP or \fB-last\fP)
+in order to access \f5ASO_THREAD\fP methods.
+The \fB-ltaso\fP library provides the "\fBspin\fP" (using \fBpthread_spin_lock\fP(3)) and
+"\fBmutex"\fP (using \fBpthread_mutex_lock\fP(3)) methods with type \f5ASO_THREAD|ASO_SIGNAL\fP.
+.Tp
+\f5ASO_PROCESS\fP:
+This method type is suitable for single-process single-thread, and multi-process applications.
+Some \f5ASO_PROCESS\fP methods may also be suitable for multi-thread applications (if they have the \f5ASO_THREAD\fP type.)
+These methods are typically and noticably \fIslow\fP, up to 2 orders of magnitude slower than
+\f5ASO_INTRINSIC\fP for some applications.
+They are provided as a last resort when other methods are not available.
+The library provides the "\fBsemaphore\fP" method with type \f5ASO_PROCESS|ASO_THREAD|ASO_SIGNAL\fP
+and the "\fBfcntl\fP" method with type \f5ASO_PROCESS|ASO_SIGNAL\fP.
+
+.Ss " Asometh_t* asometh(int type, void* data);"
+This function looks up methods by type or name.
+If type is \f50\fP and \f5data\fP is \f50\fP then the current method is returned; a valid method
+will always be returned for this call.
+If type is \f50\fP then \f5data\fP is treated as a \f50\fP-terminated string method name;
+\f50\fP is returned if no matching method is found.
+The pseudo-type \f5ASO_NEXT\fP generates the list of all methods in successive calls:
+.Cs
+Asometh_t* meth;
+meth = 0;
+while (meth = asometh(ASO_NEXT, meth))
+ /* examine meth->... */
+.Ce
+Otherwise if \f5type\fP is not \f50\fP and not \f5ASO_NEXT\fP it is treated as a combination of the ordered types
+\f5ASO_THREAD\fP, \f5ASO_SIGNAL\fP, \f5ASO_INTRINSIC\fP, \f5ASO_PROCESS\fP:
+the first method with \f5(meth->type & type) != 0\fP is returned;
+\f50\fP is returned if no matching method is found.
+
+Method names are treated as a name, optionally followed by a list of
+\fB,\fP\fIname\fP=\fIvalue\fP details, and optionally ending with \fB,\fP\fIpathname\fP.
+The \fBsemaphore\fP method uses \fBsize\fP=\fInumber\fP to specify
+the number of semaphores and hashes \fIpathname\fP to determine the semaphore IPC key.
+The \fBfcntl\fP method uses \fBsize\fP=\fInumber\fP to specify
+the number of 1 byte file locks and uses \fIpathname\fP as the
+file to lock using \f5fcntl(F_SETLCK[W])\fP.
+
+.Ss " int asoinit(const char* details, Asometh_t* meth, Asodisc_t* disc);"
+This function sets the global discipline to \f5disc\fP,
+closes the current method (releasing its resources),
+temporarily instantiates the default method
+(either \f5ASO_INTRINSIC\fP if available or \f5AS_SIGNAL\fP otherwise),
+and initializes \f5meth\fP and instantiates it as the new method.
+If \f5disc\fP is \f50\fP the the global discpline is not modified.
+If \f5meth\fP is \f50\fP or \f5meth->lockf\fP is \f50\fP and \f5(meth->type & ASO_INTRINSIC) != 0\fP
+then \f5-1\fP is returned and the current method is not changed.
+If an error occurs instantiating \f5meth\fP then the current method is
+set to the default and \f5-1\fP is returned.
+Otherwise \f50\fP is returned on success.
+
+Method resources are released by the next \f5asometh()\fP call,
+or by an \fIASO\fP cleanup function called via \f5atexit\fP(2).
+System global method resources are released on last use;
+this includes removing semaphore keys or
+physical files that may be used by some methods.
+In some cases \fIASO\fP maintains reference counts within
+the resource to determine last use.
+
+An application requiring a specific method must check the default method before
+using any \fIASO\fP operations. For example, a threaded application would
+do something like this:
+.Cs
+void* data = 0 /* \fIor\fP a method name string with optional details */
+Asometh_t* meth;
+if (data || !(asometh(0, 0)->type & (ASO_INTRINSIC|ASO_THREAD))) {
+ if (!(meth = asometh(ASO_INTRINSIC|ASO_THREAD, data)))
+ /* error -- suitable method not found */;
+ else if (asoinit(meth, 0, 0, ASO_VERSION))
+ /* error -- method initialization error */;
+}
+/* ready for \fIASO\fP operaions */
+.Ce
+A multi-process application would check for \f5(ASO_INTRINSIC|ASO_PROCESS)\fP
+instead of \f5(ASO_INTRINSIC|ASO_THREAD)\fP.
+
+.PP
+.SH IMPLEMENTATION NOTES
+Unlike other \fIAST\fP library discipline/method functions which can instantiate
+multiple discpline/method handles within a single process, the \fIASO\fP
+library allows only one discipline and method to be set at a time, with the additional
+restriction that it may only be set by the main and only thread of the calling process.
+For this reason there is no open/close interface with an instantation handle;
+instead the global discipline/method is simply initialized by \f5asoinit()\fP.
+
+\f5ASO_THREAD\fP and \f5ASO_PROCESS\fP methods rely on the \f5Asometh_t.lockf()\fP
+being sufficiently "heavy" to flush the calling thread/process memory cache
+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 \f5ASO_INTRINSIC\fP method.
+
+.PP
+.SH AUTHOR
+Kiem-Phong Vo, Adam Edgar, and Glenn Fowler
diff --git a/src/lib/libast/man/ast.3 b/src/lib/libast/man/ast.3
new file mode 100644
index 0000000..8055be9
--- /dev/null
+++ b/src/lib/libast/man/ast.3
@@ -0,0 +1,283 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH AST 3
+.SH NAME
+ast \- miscellaneous libast support
+.SH SYNOPSIS
+.EX
+#include <ast.h>
+
+char* astconf(const char* \fIname\fP, const char* \fIpath\fP, const char* \fIvalue\fP);
+Ast_confdisc_t astconfdisc(Ast_confdisc_t new_notify);
+void astconflist(Sfio_t* stream, const char* path, int flags);
+off_t astcopy(int \fIrfd\fP, int \fIwfd\fP, off_t \fIn\fP);
+int astquery(int \fIfd\fP, const char* \fIformat\fP , ...);
+.EE
+.SH DESCRIPTION
+.L astconf
+is a string interface to the
+.IR confstr (2),
+.IR pathconf (2),
+and
+.IR sysconf (2)
+calls.
+If
+.I value
+is
+.L 0
+then the configuration parameter value for
+.I name
+is returned.
+Some
+.I name
+configuration parameters may consult the
+.I path
+argument.
+In this case if
+.I path
+is
+.L 0
+then
+\f5"/"\fP
+is used.
+Otherwise if
+.I path
+is not
+.L 0
+then it must exist.
+The string return value for
+.I name
+remains unchanged until the next
+.L astconf
+call on
+.IR name .
+If
+.I value
+is
+.L 0
+then a valid string is always returned;
+\f5""\fP
+is returned if
+.I name
+has no configuration value.
+This simplifies the programming interface:
+.EX
+if (!strcmp(astconf("PATH_RESOLVE", NiL, NiL), "logical"))
+ /* the logical way ... */
+.EE
+If
+.I value
+is not
+.L 0
+then the configuration parameter value for
+.I name
+is set to
+.IR value .
+.L 0
+is returned if the value cannot be set.
+The paradigm is:
+.EX
+universe = astconf("UNIVERSE", 0, "att");
+\|.\|.\|.
+astconf("UNIVERSE", 0, universe);
+.EE
+The settable configuration names are:
+.TP
+.L FS_3D
+.L 1
+if
+.IR 3d (1)
+viewpathing is enabled,
+.L 0
+otherwise.
+This is an alternative to the
+.IR fs3d (3)
+interface.
+.TP
+.L PATH_RESOLVE
+.L logical
+if symbolic links are followed during file tree traversal,
+.L physical
+if symbolic links are not followed during file tree traversal,
+and
+.L metaphysical
+if symbolic links are followed at the top level during file tree traversal.
+These correspond to the generic
+.LR \-L ,
+.LR \-P ,
+and
+.L \-H
+command options.
+.TP
+.L UNIVERSE
+.L ucb
+for
+.I Berkeley
+style and
+.L att
+otherwise.
+This configuration parameter controls the
+.I universe
+setting on machines that support it (e.g., Pyramid).
+.L UNIVERSE
+also controls the behavior of some commands like
+.IR cat (1)
+and
+.IR echo (1).
+.PP
+User defined
+.I name
+values may also be set and queried, but these should probably have
+some form of vendor prefix to avoid being stomped by future standards.
+.PP
+.L astconfdisc
+registers a discipline function
+.EX
+int (*notify)(const char* \fIname\fP, const char* \fIpath\fP, const char* \fIvalue\fP);
+.EE
+that is called just before the configuration parameter
+.I name
+is set to
+.I value
+relative to
+.IR path .
+If
+.I notify
+returns
+.L 0
+then the configuration parameter value is not changed.
+.PP
+.L astconflist
+lists the current configuration names and values of
+.IR stream .
+If
+.I path
+is
+.L 0
+then \f5"/"\fP is used where appropriate.
+If
+.I flags
+is
+.L 0
+or
+.L R_OK|W_OK
+then all configuration parameters are listed.
+.L R_OK
+lists the readonly configuration parameters and
+.L W_OK
+lists the settable configuration parameters.
+.L X_OK
+lists the settable configuration parameters in a form that can be
+snarfed for input to the
+.IR getconf (1)
+command.
+.PP
+.L astcopy
+efficiently copies up to
+.I n
+bytes from the file descriptor
+.I rfd
+to the file descriptor
+.IR wfd .
+The actual number of bytes copied is returned; \-1 is returned on error.
+If
+.I n
+is 0 then an optimal number of bytes (with respect to both
+.I rfd
+and
+.IR wfd )
+is copied.
+.PP
+If possible
+.IR mmap (2)
+is used to do the transfer.
+Some implementations may bypass user buffer copies usually required by the
+.IR read (2)- write (2)
+paradigm.
+.PP
+.L astquery
+outputs an
+.IR sfprintf (3)
+prompt specified by
+.I "format, .\|.\|."
+to the controlling terminal and reads a response from the controlling terminal.
+Offirmative response returns
+.LR 0 ,
+.L EOF
+or quit response returns
+.LR \-1 ,
+otherwise
+.L 1
+is returned.
+If
+.I quit
+is greater than
+.L 0
+then
+.I exit(quit)
+is called on a quit response.
+The responses will eventually be locale specific.
+.PP
+.L astwinsize
+returns the number of rows in
+.I *rows
+and the number of columns
+.I *col
+for the terminal file descriptor
+.IR fd .
+If the number of rows or columns cannot be determined or if
+.I fd
+is not a terminal then
+.I *rows
+and
+.I *cols
+are set to
+.LR 0 .
+If
+.I ioctl (2)
+methods fail then the environment variable
+.L LINES
+is used to set
+.I *rows
+and the environment variable
+.L COLUMNS
+is used to set
+.IR *cols .
+.SH "SEE ALSO"
+getconf(1), confstr(2), mmap(2), pathconf(2), read(2), sysconf(2), write(2)
diff --git a/src/lib/libast/man/astsa.3 b/src/lib/libast/man/astsa.3
new file mode 100644
index 0000000..5b588a8
--- /dev/null
+++ b/src/lib/libast/man/astsa.3
@@ -0,0 +1,161 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.PP
+..
+.de Tp
+.fl
+.ne 3
+.TP
+..
+.de Ss
+.fl
+.ne 3
+.SS "\\$1"
+..
+.ta 1.0i 2.0i 3.0i 4.0i 5.0i
+.TH ASTSA 3
+.SH NAME
+astsa \- standalone libast support
+.SH SYNOPSIS
+.EX
+#include <ast.h>
+#include <ccode.h>
+#include <error.h>
+#include <option.h>
+#include <stk.h>
+.EE
+.SH DESCRIPTION
+.B astsa
+is a standalone subset of
+.BR ast (3)
+that requires only
+.BR cdt (3)
+and
+.BR sfio (3).
+.PP
+.B <ast.h>
+includes
+.BR <ast_common.h> ,
+.B <stdarg.h>
+or
+.BR <varargs.h> ,
+.BR <sfio.h> ,
+.BR <limits.h> ,
+and
+.B <limits.h>
+and
+.B <unistd.h>
+if supported by the local system.
+.PP
+The macros and functions provided by
+.B <ast.h>
+are described below.
+The other headers are described in
+.BR ccode (3),
+.BR error (3),
+.BR optget (3),
+and
+.BR stk (3).
+.SH MACROS
+.Ss "size_t elementsof(\fIx\fP)"
+Evaluates to the number of elements in the array variable
+.IR x .
+.Ss "\fItype\fP* newof(void* old, \fItype\fP, size_t \fIelements\fP, size_t \fIextra\fP)"
+Equivalent to (\fItype\fP*)realloc((char*)\fIold\fP,sizeof(\fItype\fP)*\fIelements\fP+\fIextra\fP)
+if \fIold\fP!=0 and
+(\fItype\fP*)calloc(1,sizeof(\fItype\fP)*\fIelements\fP+\fIextra\fP)
+otherwise.
+.Ss "\fItype\fP* oldof(void* old, \fItype\fP, size_t \fIelements\fP, size_t \fIextra\fP)"
+Equivalent to (\fItype\fP*)realloc((char*)\fIold\fP,sizeof(\fItype\fP)*\fIelements\fP+\fIextra\fP)
+if \fIold\fP!=0 and
+(\fItype\fP*)malloc(1,sizeof(\fItype\fP)*\fIelements\fP+\fIextra\fP)
+otherwise.
+.Ss "size_t roundof(\fIx\fP,\fIy\fP)"
+Evaluates to \fIx\fP rounded up to the next power of 2 boundary \fIy\fP.
+.Ss "int ssizeof(\fIx\fP)"
+Equivalent to (int)sizeof(\fIx\fP).
+.Ss "int streq(\fIa\fP,\fIb\fP)"
+Equivalent to (*(\fIa\fP)==*(\fIb\fP)&&strcmp(\fIa\fP,\fIb\fP)==0).
+.Ss "int strneq(\fIa\fP,\fIb\fP,\fIn\fP)"
+Equivalent to (*(\fIa\fP)==*(\fIb\fP)&&strncmp(\fIa\fP,\fIb\fP,\fIn\fP)==0).
+.SH FUNCTIONS
+.Ss "void astwinsize(int \fIfd\fP, int* \fIplines\fP, int* \fIpcolumns\fP)"
+If \fIplines\fP!=0 then *\fIplines\fP is set to the number of lines on the
+tty device corresponding to \fIfd\fP.
+If \fIpcolumns\fP!=0 then *\fIpcolumns\fP is set to the number of columns
+on the tty device corresponding to \fIfd\fP.
+The default if \fIfd\fP is not a terminal device, or if \fIfd\fP queries fail,
+is 24 lines and 80 columns.
+.Ss "char* fmterror(int \fIerrno\fP)"
+Returns the error message text corresponding to the
+.BR errno (3)
+\fIerrno\fP.
+.Ss "char* strerror(int \fIerrno\fP)"
+Equivalent to fmterror(\fIerrno\fP).
+.Ss "int strgrpmatch(const char* \fIstring\fP, const char* \fIpattern\fP, int* \fIsub\fP, int \fInsub\fP, int \fIflags\fP)"
+Matches the null terminated \fIstring\fP against the null terminated
+.BR ksh (1)
+augmented \fIpattern\fP.
+If \fIsub\fP!=0 then \fIsub\fP[2*\fIi\fP] is set to the start offset and \fIsub\fP[2*\fIi\fP+1] is set
+to the end offset of the \fIi\fP-th parenthesized subexpression.
+\fInsub\fP is 1/2 the number of elements in \fIsub\fP.
+\fIflags\fP controls the matching:
+.Tp
+\f5STR_MAXIMAL\fP:
+Maximal match.
+The default is minimal (first) match.
+.Tp
+\f5STR_LEFT\fP:
+Implicit left anchor.
+.Tp
+\f5STR_RIGHT\fP:
+Implicit right anchor.
+.Tp
+\f5STR_ICASE\fP:
+Ignore case.
+.Tp
+\f5STR_GROUP\fP:
+(|&) inside [@|*|+{n,m}](...) only.
+.Ss "int strmatch(const char* \fIstring\fP, const char* \fIpattern\fP, int* \fIsub\fP, int \fInsub\fP, int \fIflags\fP)"
+Equivalent to strgrpmatch(\fIstring\fP,\fIpattern\fP,0,0,STR_MAXIMAL|STR_LEFT|STR_RIGHT).
+.SH "SEE ALSO"
+.BR ast (3),
+.BR ccode (3),
+.BR cdt (3),
+.BR error (3),
+.BR malloc (3),
+.BR option (3),
+.BR sfio (3),
+.BR stk (3)
diff --git a/src/lib/libast/man/cdt.3 b/src/lib/libast/man/cdt.3
new file mode 100644
index 0000000..46bfe13
--- /dev/null
+++ b/src/lib/libast/man/cdt.3
@@ -0,0 +1,617 @@
+.fp 5 CW
+.TH LIBCDT 3
+.SH NAME
+\fBCdt\fR \- container data types
+.SH SYNOPSIS
+.de Tp
+.fl
+.ne 2
+.TP
+..
+.de Ss
+.fl
+.ne 2
+.SS "\\$1"
+..
+.de Cs
+.nf
+.ft 5
+..
+.de Ce
+.ft 1
+.fi
+..
+.ta 1.0i 2.0i 3.0i 4.0i 5.0i
+.Cs
+#include <cdt.h>
+.Ce
+.Ss "DICTIONARY TYPES"
+.Cs
+Void_t*;
+Dt_t;
+Dtdisc_t;
+Dtmethod_t;
+Dtlink_t;
+Dtstat_t;
+.Ce
+.Ss "DICTIONARY CONTROL"
+.Cs
+Dt_t* dtopen(const Dtdisc_t* disc, const Dtmethod_t* meth);
+int dtclose(Dt_t* dt);
+void dtclear(dt);
+Dtdisc_t* dtdisc(Dt_t* dt, const Dtdisc_t* disc, int type);
+Dtmethod_t* dtmethod(Dt_t* dt, const Dtmethod_t* meth);
+Dt_t* dtview(Dt_t* dt, Dt_t* view);
+int dtcustomize(Dt_t* dt, int type, Void_t* arg);
+int dtoptimize(Dt_t* dt);
+int dtshare(Dt_t* dt, int type);
+int dtlock(Dt_t* dt, unsigned int key, int type);
+.Ce
+.Ss "STORAGE METHODS"
+.Cs
+Dtmethod_t* Dtset;
+Dtmethod_t* Dtbag;
+Dtmethod_t* Dtrhset;
+Dtmethod_t* Dtrhbag;
+Dtmethod_t* Dtoset;
+Dtmethod_t* Dtobag;
+Dtmethod_t* Dtlist;
+Dtmethod_t* Dtstack;
+Dtmethod_t* Dtqueue;
+Dtmethod_t* Dtdeque;
+.Ce
+.Ss "DISCIPLINE"
+.Cs
+#define DTOFFSET(struct_s,member)
+#define DTDISC(disc,key,size,link,makef,freef,comparf,hashf,memoryf,eventf)
+typedef Void_t* (*Dtmake_f)(Dt_t*, Void_t*, Dtdisc_t*);
+typedef void (*Dtfree_f)(Dt_t*, Void_t*, Dtdisc_t*);
+typedef int (*Dtcompar_f)(Dt_t*, Void_t*, Void_t*, Dtdisc_t*);
+typedef unsigned int (*Dthash_f)(Dt_t*, Void_t*, Dtdisc_t*);
+typedef Void_t* (*Dtmemory_f)(Dt_t*, Void_t*, size_t, Dtdisc_t*);
+typedef int (*Dtevent_f)(Dt_t*, int, Void_t*, Dtdisc_t*);
+.Ce
+.Ss "OBJECT OPERATIONS"
+.Cs
+Void_t* dtinsert(Dt_t* dt, Void_t* obj);
+Void_t* dtappend(Dt_t* dt, Void_t* obj);
+Void_t* dtdelete(Dt_t* dt, Void_t* obj);
+Void_t* dtattach(Dt_t* dt, Void_t* obj);
+Void_t* dtdetach(Dt_t* dt, Void_t* obj);
+Void_t* dtsearch(Dt_t* dt, Void_t* obj);
+Void_t* dtmatch(Dt_t* dt, Void_t* key);
+Void_t* dtfirst(Dt_t* dt);
+Void_t* dtnext(Dt_t* dt, Void_t* obj);
+Void_t* dtlast(Dt_t* dt);
+Void_t* dtprev(Dt_t* dt, Void_t* obj);
+Void_t* dtleast(Dt_t* dt, Void_t* obj);
+Void_t* dtmost(Dt_t* dt, Void_t* obj);
+int dtwalk(Dt_t* dt, int (*userf)(Dt_t*, Void_t*, Void_t*), Void_t*);
+Dtlink_t* dtflatten(Dt_t* dt);
+Dtlink_t* dtlink(Dt_t* dt, Dtlink_t* link);
+Void_t* dtobj(Dt_t* dt, Dtlink_t* link);
+Dtlink_t* dtextract(Dt_t* dt);
+Dtlink_t* dtrestore(Dt_t* dt, Dtlink_t* link);
+.Ce
+.Ss "DICTIONARY STATUS"
+.Cs
+Dt_t* dtvnext(Dt_t* dt);
+ssize_t dtvcount(Dt_t* dt);
+Dt_t* dtvhere(Dt_t* dt);
+ssize_t dtsize(Dt_t* dt);
+ssize_t dtstat(Dt_t* dt, Dtstat_t* st);
+.Ce
+.Ss "HASH FUNCTIONS"
+.Cs
+unsigned int dtstrhash(unsigned int h, char* str, int n);
+unsigned int dtcharhash(unsigned int h, unsigned char c);
+.Ce
+.SH DESCRIPTION
+.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_t*"
+This type is used to pass objects between \fICdt\fP and application code.
+\f5Void_t\fP is defined as \f5void\fP for ANSI-C and C++
+and \f5char\fP for older C compilation environments.
+.PP
+.Ss " Dt_t"
+This is the type of a dictionary handle.
+.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 \f5dtdisc()\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 \f5dtdisc()\fP.)
+.PP
+.Ss " Dtstat_t"
+This is the type of a structure to return dictionary statistics (see \f5dtstat()\fP.)
+.PP
+.Ss "DICTIONARY CONTROL"
+.PP
+.Ss " Dt_t* dtopen(const Dtdisc_t* disc, const Dtmethod_t* meth)"
+This creates a new dictionary.
+\f5disc\fP is a discipline structure to describe object format.
+\f5meth\fP specifies a manipulation method.
+\f5dtopen()\fP returns the new dictionary or \f5NULL\fP on error.
+See also the events \f5DT_OPEN\fP and \f5DT_ENDOPEN\fP below.
+.PP
+.Ss " int dtclose(Dt_t* dt)"
+This deletes \f5dt\fP and its objects.
+Note that \f5dtclose()\fP fails if \f5dt\fP is being viewed by
+some other dictionaries (see \f5dtview()\fP).
+\f5dtclose()\fP returns \f50\fP on success and \f5-1\fP on error.
+See also the events \f5DT_CLOSE\fP and \f5DT_ENDCLOSE\fP below.
+.PP
+.Ss " void dtclear(Dt_t* dt)"
+This deletes all objects in \f5dt\fP without closing \f5dt\fP.
+.PP
+.Ss " Dtdisc_t* dtdisc(Dt_t* dt, const Dtdisc_t* disc, int type)"
+If \f5disc\fP is \f5NULL\fP, \f5dtdisc()\fP returns the current discipline.
+Otherwise, it changes the discipline of \f5dt\fP to \f5disc\fP.
+Objects may be rehashed, reordered, or removed as appropriate.
+\f5type\fP can be any bit combination of \f5DT_SAMECMP\fP and \f5DT_SAMEHASH\fP.
+\f5DT_SAMECMP\fP means that objects will compare exactly the same as before
+thus obviating the need for reordering or removing new duplicates.
+\f5DT_SAMEHASH\fP means that hash values of objects remain the same
+thus obviating the need to rehash.
+\f5dtdisc()\fP returns the previous discipline on success
+and \f5NULL\fP on error.
+.PP
+.Ss " Dtmethod_t dtmethod(Dt_t* dt, const Dtmethod_t* meth)"
+If \f5meth\fP is \f5NULL\fP, \f5dtmethod()\fP returns the current method.
+Otherwise, it changes the storage method of \f5dt\fP to \f5meth\fP.
+Objects may be rehashed, reordered, or removed as appropriate.
+\f5dtmethod()\fP returns the previous method or \f5NULL\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.
+\f5dtview()\fP first terminates any current view from \f5dt\fP to another dictionary.
+Then, if \f5view\fP is \f5NULL\fP, \f5dtview\fP returns the terminated view dictionary.
+If \f5view\fP is not \f5NULL\fP, a viewpath from \f5dt\fP to \f5view\fP is established.
+\f5dtview()\fP returns \f5dt\fP on success and \f5NULL\fP on error.
+.PP
+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, Void_t* arg)"
+This customizes a storage method. The \f5type\fP argument
+indicates the type of customization and \f5arg\fP gives additional
+information for the operation. Here are the types:
+.Tp
+\f5DT_SHARE\fP:
+This turns on/off the share mode for a dictionary.
+Concurrent accesses of a dictionary not in share mode
+may exhibit undefined behaviors including memory segmentation.
+
+Share mode allows multiple accessors, threads or processes, to access objects.
+Such objects could be in the same directory in the case of threads or shared
+memory in the case of processes.
+.Tp
+\f5DT_OPTIMIZE\fP:
+This causes the underlying method to optimize its internal
+data structure. For example, the splay tree underlying \f5Dtoset\fP
+would be balanced.
+.PP
+.Ss " int dtoptimize(Dt_t* dt)"
+This is a short-hand for invoking \f5dtcustomize()\fP with the \f5DT_OPTIMIZE\fP event.
+.PP
+.Ss " int dtshare(Dt_t* dt, int type)"
+This turns on or off share mode for dictionary \f5dt\fP depending on whether \f5type\fP
+is positive or non-positive. It returns -1 on failure.
+.PP
+.Ss " int dtlock(Dt_t* dt, unsigned int key, int type)"
+This globally locks/unlocks a dictionary using the given \f5key\fP.
+It returns 0 on success and -1 on failure.
+The value of \f5key\fP must not be 0.
+The argument \f5type\fP is used as follows:
+.Tp
+\f5type < 0\fP:
+Unlock the dictionary if it was locked with \f5key\fP.
+An error will result if the dictionary was locked with a different key.
+.Tp
+\f5type == 0\fP:
+Attempt to lock the dictionary with \f5key\fP if it is unlocked.
+An error will result if the dictionary was already locked with a different key.
+.Tp
+\f5type > 0\fP:
+Attempt to lock the dictionary with \f5key\fP.
+If the dictionary is already locked with a different key,
+the call will loop and wait until the lock is open to lock it.
+
+.PP
+.Ss "STORAGE METHODS"
+.PP
+Storage methods are of type \f5Dtmethod_t*\fP.
+\fICdt\fP supports the following methods:
+.PP
+.Ss " Dtoset"
+.Ss " Dtobag"
+Objects are ordered by comparisons.
+\f5Dtoset\fP keeps unique objects.
+\f5Dtobag\fP allows repeatable objects.
+.PP
+.Ss " Dtset"
+.Ss " Dtbag"
+Objects are unordered.
+\f5Dtset\fP keeps unique objects.
+\f5Dtbag\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 \f5Dtset\fP and \f5Dtbag\fP but are based on
+a recursive hashing data structure that allows table extension without
+object relocation. The data structure also supports lock-free
+concurrent search operations for share dictionaries.
+.PP
+.Ss " Dtlist"
+Objects are kept in a list.
+\fIA current object\fP is always defined to be either the head of
+the list or an object resulting from a recent search or insert operation.
+The call \f5dtinsert()\fP will insert a new object
+in front of such a current object
+while the call \f5dtappend()\fP will append in back of it.
+.PP
+.Ss " Dtdeque"
+Objects are kept in a deque. This is similar to \f5Dtlist\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
+defined in the type \f5Dtdisc_t\fP:
+.Cs
+ typedef struct
+ { ssize_t key, size;
+ ssize_t link;
+ Dtmake_f makef;
+ Dtfree_f freef;
+ Dtcompar_f comparf;
+ Dthash_f hashf;
+ Dtmemory_f memoryf;
+ Dtevent_f eventf;
+ } Dtdisc_t;
+.Ce
+.Ss " ssize_t key, size"
+Each object \f5obj\fP is identified by a key used for object comparison or hashing.
+\f5key\fP should be non-negative and defines an offset into \f5obj\fP.
+If \f5size\fP is negative, the key is a null-terminated
+string with starting address \f5*(Void_t**)((char*)obj+key)\fP.
+If \f5size\fP is zero, the key is a null-terminated string with starting address
+\f5(Void_t*)((char*)obj+key)\fP.
+Finally, if \f5size\fP is positive, the key is a byte array of length \f5size\fP
+starting at \f5(Void_t*)((char*)obj+key)\fP.
+.PP
+.Ss " ssize_t link"
+Let \f5obj\fP be an object to be inserted into \f5dt\fP.
+If \f5link\fP is negative, an object holder of type \f5Dtlink_t\fP
+will be allocated to hold \f5obj\fP.
+Otherwise, \f5obj\fP should have
+a \f5Dtlink_t\fP structure embedded \f5link\fP bytes into it,
+i.e., at address \f5(Dtlink_t*)((char*)obj+link)\fP.
+.PP
+.Ss " Void_t* (*makef)(Dt_t* dt, Void_t* obj, Dtdisc_t* disc)"
+If \f5makef\fP is not \f5NULL\fP,
+\f5dtinsert(dt,obj)\fP or \f5dtappend()\fP will call it
+to make a copy of \f5obj\fP suitable for insertion into \f5dt\fP.
+If \f5makef\fP is \f5NULL\fP, \f5obj\fP itself will be inserted into \f5dt\fP.
+.PP
+.Ss " void (*freef)(Dt_t* dt, Void_t* obj, Dtdisc_t* disc)"
+If not \f5NULL\fP,
+\f5freef\fP is used to destroy data associated with \f5obj\fP.
+.PP
+.Ss "int (*comparf)(Dt_t* dt, Void_t* key1, Void_t* key2, Dtdisc_t* disc)"
+If not \f5NULL\fP, \f5comparf\fP is used to compare two keys.
+Its return value should be \f5<0\fP, \f5=0\fP, or \f5>0\fP to indicate
+whether \f5key1\fP is smaller, equal to, or larger than \f5key2\fP.
+All three values are significant for method \f5Dtoset\fP and \f5Dtobag\fP.
+For other methods, a zero value
+indicates equality and a non-zero value indicates inequality.
+If \f5(*comparf)()\fP is \f5NULL\fP, an internal function is used
+to compare the keys as defined by the \f5Dtdisc_t.size\fP field.
+.PP
+.Ss " unsigned int (*hashf)(Dt_t* dt, Void_t* key, Dtdisc_t* disc)"
+If not \f5NULL\fP,
+\f5hashf\fP is used to compute the hash value of \f5key\fP.
+It is required that keys compared equal will also have same hash values.
+If \f5hashf\fP is \f5NULL\fP, an internal function is used to hash
+the key as defined by the \f5Dtdisc_t.size\fP field.
+.PP
+.Ss " Void_t* (*memoryf)(Dt_t* dt, Void_t* addr, size_t size, Dtdisc_t* disc)"
+If not \f5NULL\fP, \f5memoryf\fP is used to allocate and free memory.
+When \f5addr\fP is \f5NULL\fP, a memory segment of size \f5size\fP is requested.
+If \f5addr\fP is not \f5NULL\fP and \f5size\fP is zero, \f5addr\fP is to be freed.
+If \f5addr\fP is not \f5NULL\fP and \f5size\fP is positive,
+\f5addr\fP is to be resized to the given size.
+If \f5memoryf\fP is \f5NULL\fP, \fImalloc(3)\fP is used.
+.PP
+.Ss " int (*eventf)(Dt_t* dt, int type, Void_t* data, Dtdisc_t* disc)"
+If not \f5NULL\fP, \f5eventf\fP announces various events.
+Each event may have particular handling of the return values from \f5eventf\fP.
+But a negative return value typically means failure.
+Following are the events:
+.Tp
+\f5DT_OPEN\fP:
+This event is raised at the start of the process to open a new dictionary.
+The argument \f5data\fP will be a pointer to an object of type \f5Void_t*\fP
+initialized to \f5NULL\fP before the call. The return value of \f5eventf()\fP
+is significant as follows:
+
+On a negative return value, \f5dtopen()\fP will return failure.
+
+On a zero return value, \f5eventf()\fP may set \f5*(Void_t**)data\fP to some non-\f5NULL\fP
+value to indicate that the dictionary structure itself should be allocated
+along with the \f5Dtdisc_t.data\fP section.
+Otherwise, it will be allocated separately with \f5malloc(3)\fP.
+
+On a positive return value, the dictionary is being reconstructed
+based on existing states of some previous dictionary.
+In this case, \f5eventf()\fP should set \f5*(Void_t**)data\fP to point to
+the field \f5Dt_t.data\fP of the corresponding previous dictionary (see \f5DT_CLOSE\fP below).
+If the handle of the previous dictionary was created as discussed above
+in the case of the zero return value, it will be exactly restored.
+Otherwise, a new handle will be allocated with \f5malloc()\fP.
+The ability to create different dictionaries sharing the same set of objects
+allows for managing objects in shared and/or persistent memory.
+.Tp
+\f5DT_ENDOPEN\fP:
+This event is raised at the end of the process to open a dictionary.
+The return value of \f5eventf()\fP will be ignored.
+.Tp
+\f5DT_CLOSE\fP:
+This event is raised at the start of the process to close dictionary \f5dt\fP.
+The return value of \f5eventf\fP is significant as follows:
+
+On a negative return value, \f5dtclose()\fP will return failure.
+
+On a zero return value, all dictionary objects will be deleted and
+and all associated memory will be freed.
+
+On a positive return value, allocated objects and memory will be kept intact.
+This means that \f5dt->data\fP remains intact and can be reused in some future
+dictionary (see \f5DT_OPEN\fP above).
+Note, however, that \f5dt\fP itself would still be freed if it was allocated with \f5malloc(3)\fP.
+.Tp
+\f5DT_ENDCLOSE\fP:
+This event is raised at the end of the process to close a dictionary.
+The return value of \f5eventf()\fP will be ignored.
+.Tp
+\f5DT_DISC\fP:
+The discipline of \f5dt\fP is being changed to a new one given in
+\f5(Dtdisc_t*)data\fP.
+.Tp
+\f5DT_METH\fP:
+The method of \f5dt\fP is being changed to a new one given in
+\f5(Dtmethod_t*)data\fP.
+.Tp
+\f5DT_HASHSIZE\fP:
+This event is applicable to
+the methods \f5Dtset\fP, \f5Dtbag\fP, \f5Dtrhset\fP and \f5Dtrhbag\fP.
+It is typically issued when the respective internal data structure of
+a method is about to be initialized.
+If the return value of the event handling function is positive,
+\f5*(ssize_t*)data\fP is examined for further action;
+else, it is ignored.
+A positive return value means that the event function wishes to suggest a table size.
+It does that by setting \f5*(ssize_t*)data\fP to the desired size.
+Then, the actual table size will be the maximum of the absolute value
+of \f5*(ssize_t*)data\fP and some predefined value set by the method.
+In addition, if \f5*(ssize_t*)data\fP was negative,
+the \f5Dtset\fP and \f5Dtbag\fP methods will never resize the hash table.
+.Tp
+\f5DT_ERROR\fP:
+This event announces an error that occurred during some operations.
+The argument \f5(char*)data\fP is a null-terminated string describing the error.
+.PP
+.Ss "#define DTOFFSET(struct_s,member)"
+This macro function computes the offset of \f5member\fP from the start
+of structure \f5struct_s\fP. It is useful for getting the offset of
+a \f5Dtlink_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 \f5disc\fP
+with the given values.
+.PP
+.Ss "OBJECT OPERATIONS"
+.PP
+.Ss " Void_t* dtinsert(Dt_t* dt, Void_t* obj)"
+.Ss " Void_t* dtappend(Dt_t* dt, Void_t* obj)"
+These functions add an object prototyped by \f5obj\fP into \f5dt\fP.
+\f5dtinsert()\fP and \f5dtappend()\fP perform the same function
+for all methods except for \f5Dtlist\fP (see \f5Dtlist\fP for details).
+If there is an existing object in \f5dt\fP matching \f5obj\fP
+and the storage method is \f5Dtset\fP, \f5Dtrhset\fP or \f5Dtoset\fP,
+\f5dtinsert()\fP and \f5dtappend()\fP will simply return the matching object.
+Otherwise, a new object is inserted according to the method in use.
+See \f5Dtdisc_t.makef\fP for object construction.
+The new object or a matching object as noted will be returned on success
+while \f5NULL\fP is returned on error.
+.PP
+.Ss " Void_t* dtdelete(Dt_t* dt, Void_t* obj)"
+If \f5obj\fP is \f5NULL\fP, methods \f5Dtstack\fP and \f5Dtqueue\fP
+delete respectively stack top or queue head while other methods do nothing.
+If \f5obj\fP is not \f5NULL\fP, an object matching \f5obj\fP is deleted.
+See \f5Dtdisc_t.freef\fP for object destruction.
+\f5dtdelete()\fP returns the deleted object (even if it was deallocated)
+or \f5NULL\fP on error.
+.PP
+.Ss " Void_t* dtattach(Dt_t* dt, Void_t* obj)"
+This function is similar to \f5dtinsert()\fP but \f5obj\fP itself
+will be inserted into \f5dt\fP even if a discipline
+function \f5makef\fP is defined.
+.PP
+.Ss " Void_t* dtdetach(Dt_t* dt, Void_t* obj)"
+This function is similar to \f5dtdelete()\fP but the object to be deleted
+from \f5dt\fP will not be freed (via the discipline \f5freef\fP function).
+.PP
+.Ss " Void_t* dtsearch(Dt_t* dt, Void_t* obj)"
+.Ss " Void_t* dtmatch(Dt_t* dt, Void_t* key)"
+These functions find an object matching \f5obj\fP or \f5key\fP either from \f5dt\fP or
+from some dictionary accessible from \f5dt\fP via a viewpath (see \f5dtview()\fP.)
+\f5dtsearch()\fP and \f5dtmatch()\fP return the matching object or
+\f5NULL\fP on failure.
+.PP
+.Ss " Void_t* dtfirst(Dt_t* dt)"
+.Ss " Void_t* dtnext(Dt_t* dt, Void_t* obj)"
+\f5dtfirst()\fP returns the first object in \f5dt\fP.
+\f5dtnext()\fP returns the object that follows an object matching \f5obj\fP.
+Objects are ordered based on the storage method in use.
+For \f5Dtoset\fP and \f5Dtobag\fP, objects are ordered by object comparisons.
+For \f5Dtstack\fP, objects are ordered in reverse order of insertion.
+For \f5Dtqueue\fP, objects are ordered in order of insertion.
+For \f5Dtlist\fP, objects are ordered by list position.
+For \f5Dtset\fP, \f5Dtbag\fP, \f5Dtrhset\fP and \f5Dtrhbag\fP,
+objects are ordered by some internal order defined at the time when these
+functions are called.
+
+Objects in a dictionary or a viewpath can be walked using
+a \f5for(;;)\fP loop as below.
+.Cs
+ for(obj = dtfirst(dt); obj; obj = dtnext(dt,obj))
+.Ce
+.PP
+.Ss " Void_t* dtlast(Dt_t* dt)"
+.Ss " Void_t* dtprev(Dt_t* dt, Void_t* obj)"
+\f5dtlast()\fP and \f5dtprev()\fP are like \f5dtfirst()\fP and \f5dtnext()\fP
+but work in reverse order.
+For \f5Dtset\fP, \f5Dtbag\fP, \f5Dtrhset\fP and \f5Dtrhbag\fP,
+both reverse and forward orders are the same.
+Note that dictionaries on a viewpath are still walked in the order
+of the viewpath.
+.PP
+.Ss " Void_t* dtleast(Dt_t* dt, Void_t* obj)"
+.Ss " Void_t* dtmost(Dt_t* dt, Void_t* obj)"
+\f5dtleast()\fP returns the smallest object greater or equal to \f5obj\fP.
+\f5dtmost()\fP returns the largest object smaller or equal to \f5obj\fP.
+Again, object ordering depends on the storage method in use.
+For example, with \f5Dtoset\fP and \f5Dtobag\fP, the ordering of objects
+is well-defined and it is possible to call \f5dtleast()\fP or \f5dtmost()\fP
+on an object not in the dictionary and still get a meaningful result.
+On the other hand, with \f5Dtset\fP or \f5Dtrhset\fP, such a call will
+essentially be the same as \f5dtsearch()\fP because without matching
+an object, it cannot be determined what comes before or after.
+.PP
+.Ss " dtwalk(Dt_t* dt, int (*userf)(Dt_t*, Void_t*, Void_t*), Void_t* data)"
+This function calls \f5(*userf)(walk,obj,data)\fP on each object in \f5dt\fP and
+other dictionaries viewable from it.
+\f5walk\fP is the dictionary containing \f5obj\fP.
+If \f5userf()\fP returns a \f5<0\fP value,
+\f5dtwalk()\fP terminates and returns the same value.
+\f5dtwalk()\fP returns \f50\fP on completion.
+.PP
+.Ss " Dtlink_t* dtflatten(Dt_t* dt)"
+.Ss " Dtlink_t* dtlink(Dt_t* dt, Dtlink_t* link)"
+.Ss " Void_t* dtobj(Dt_t* dt, Dtlink_t* link)"
+Using \f5dtfirst()/dtnext()\fP or \f5dtlast()/dtprev()\fP
+to walk a single dictionary can incur significant cost due to function calls.
+For efficient walking of a single directory (i.e., no viewpathing),
+\f5dtflatten()\fP and \f5dtlink()\fP can be used.
+Objects in \f5dt\fP are made into a linked list and walked as follows:
+.Cs
+ for(link = dtflatten(dt); link; link = dtlink(dt,link) )
+.Ce
+.PP
+Note that \f5dtflatten()\fP returns a list of type \f5Dtlink_t*\fP,
+not \f5Void_t*\fP. That is, it returns a dictionary holder pointer,
+not a user object pointer
+(although both are the same if the discipline field \f5link\fP is zero.)
+The macro function \f5dtlink()\fP
+returns the dictionary holder object following \f5link\fP.
+The macro function \f5dtobj(dt,link)\fP
+returns the user object associated with \f5link\fP,
+Beware that the flattened object list is unflattened on any
+dictionary operations other than \f5dtlink()\fP.
+.PP
+.Ss " Dtlink_t* dtextract(Dt_t* dt)"
+.Ss " Dtlink_t* dtrestore(Dt_t* dt, Dtlink_t* list)"
+\f5dtextract()\fP extracts the list of objects from \f5dt\fP and makes it appear empty.
+\f5dtrestore()\fP repopulates \f5dt\fP with
+a list of objects previously obtained via \f5dtextract()\fP.
+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 \f5NULL\fP on error.
+
+.PP
+.Ss "DICTIONARY INFORMATION"
+.PP
+.Ss " Dt_t* dtvnext(Dt_t* dt)"
+This returns the dictionary that \f5dt\fP is viewing, if any.
+.Ss " ssize_t dtvcount(Dt_t* dt)"
+This returns the number of dictionaries that view \f5dt\fP.
+.Ss " Dt_t* dtvhere(Dt_t* dt)"
+This returns the dictionary \f5v\fP viewable from \f5dt\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 \f5dt\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 \f5dt\fP.
+.PP
+\f5Dtstat_t\fP contains the below fields:
+.Tp
+\f5int meth\fP:
+This returns the method used for the dictionary, e.g., \f5DT_SET\fP, \f5DT_OSET\fP, etc.
+.Tp
+\f5ssize_t size\fP:
+This has the number of objects in the dictionary.
+.Tp
+\f5ssize_t mlev\fP:
+This returns the maximum number of levels in the data structure used for object storage, i.e.,
+the binary tree or the recursive hash table.
+For a hash table with chaining (i.e., \f5Dtset\fP and \f5Dtbag\fP),
+it gives the length of the longest chain.
+.Tp
+\f5ssize_t lsize[]\fP:
+This gives the object counts at each level.
+For a hash table with chaining (i.e., \f5Dtset\fP and \f5Dtbag\fP),
+a level is defined as objects at that position in their chains.
+Since chains can be arbitrarily long, the report is limited
+to objects at a level less than \f5DT_MAXSIZE\fP.
+.Tp
+\f5ssize_t tsize[]\fP:
+For a hash table using a trie structure, this counts the number of
+sub-tables at each level. For example, \f5tsize[0]\fP should be 1
+only for this hash table type.
+.PP
+.Ss "HASH FUNCTIONS"
+.PP
+.Ss " unsigned int dtcharhash(unsigned int h, char c)"
+.Ss " unsigned int dtstrhash(unsigned int h, char* str, int n)"
+These functions compute hash values from bytes or strings.
+\f5dtcharhash()\fP computes a new hash value from byte \f5c\fP and seed value \f5h\fP.
+\f5dtstrhash()\fP computes a new hash value from string \f5str\fP and seed value \f5h\fP.
+If \f5n\fP is positive, \f5str\fP is a byte array of length \f5n\fP;
+otherwise, \f5str\fP is a null-terminated string.
+.PP
+.SH IMPLEMENTATION NOTES
+\f5Dtlist\fP, \f5Dtstack\fP and \f5Dtqueue\fP are based on doubly linked list.
+\f5Dtoset\fP and \f5Dtobag\fP are based on top-down splay trees.
+\f5Dtset\fP and \f5Dtbag\fP are based on hash tables with
+move-to-front collision chains.
+\f5Dtrhset\fP and \f5Dtrhbag\fP are based on a recursive hashing data structure
+that avoids table resizing.
+.PP
+.SH AUTHOR
+Kiem-Phong Vo, kpv@research.att.com
diff --git a/src/lib/libast/man/chr.3 b/src/lib/libast/man/chr.3
new file mode 100644
index 0000000..8d57648
--- /dev/null
+++ b/src/lib/libast/man/chr.3
@@ -0,0 +1,126 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH CHR 3
+.SH NAME
+chr \- character constant conversion routines
+.SH SYNOPSIS
+.EX
+#include <ast.h>
+
+int chresc(const char* \fIs\fP, char** \fIe\fP);
+int chrtoi(const char* \fIs\fP);
+.EE
+.SH DESCRIPTION
+.L chresc
+converts and returns the next character constant in the 0-terminated string
+.IR s .
+If
+.I e
+is not 0 then
+.I *e
+is set to point to the next character in
+.I s
+on return.
+0 is returned and
+.I e
+is not modified when the end of
+.I s
+is reached.
+.PP
+.L chrtoi
+converts the 0-terminated string
+.I s
+to an
+.I int
+and returns the value.
+The characters in
+.I s
+are converted in order from the left and shifted into the
+.I int
+value until up to the number of characters in an
+.I int
+is reached.
+This operation is inherently machine-dependent,
+but at least its defined in one place.
+.PP
+The following
+.B \e
+escape sequences are recognized:
+.TP
+.RI \e ooo
+The character represented by the octal code
+.IR ooo .
+.TP
+.RI \ex xx
+The character represented by the hex code
+.IR xx .
+.TP
+.L \ea
+Alert (bell).
+.TP
+.L \eb
+Backspace.
+.TP
+.L \ef
+Formfeed.
+.TP
+.L \en
+Newline.
+.TP
+.L \er
+Carriage return.
+.TP
+.L \et
+Horizontal tab.
+.TP
+.L \ev
+Vertical tab.
+.TP
+.L \eE
+ESC (escape).
+.TP
+.L \e\e
+Backslash.
+.PP
+Other characters following
+.B \e
+are undefined (although for backwards compatibility they
+translate to themselves).
+.SH "SEE ALSO"
+str(3)
diff --git a/src/lib/libast/man/compat.3 b/src/lib/libast/man/compat.3
new file mode 100644
index 0000000..eb5e8a7
--- /dev/null
+++ b/src/lib/libast/man/compat.3
@@ -0,0 +1,103 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH COMPATIBILITY 3
+.SH NAME
+compatibility \- ast library compatibility routines
+.SH SYNOPSIS
+.EX
+#include <ast.h>
+
+int atexit(void(*)(void));
+char* confstr(int);
+int dup2(int, int);
+long fpathconf(int, int);
+int getgroups(int, int*);
+char* getwd(char*);
+int killpg(int, int);
+int link(const char*, const char*);
+int lstat(const char*, struct stat*);
+int memcmp(const char*, const char*, unsigned int);
+char* memcpy(char*, const char*, int);
+char* memset(char*, char, int);
+int mkdir(const char*, mode_t);
+int mkfifo(const char*, mode_t);
+int mknod(const char*, mode_t);
+char* mktemp(char*);
+int mount(const char*, const char*, int);
+long pathconf(const char*, int);
+int perror(const char*);
+FILE* popen(const char*, const char*);
+int readlink(const char*, char*, int);
+int remove(const char*);
+int rename(const char*, const char*);
+int rmdir(const char*);
+int setpgid(pid_t, pid_t);
+int sigmask(int);
+int sigsetmask(long);
+int sigunblock(int);
+char* strchr(const char*, int);
+char* strrchr(const char*, int);
+double strtod(const char*, char**);
+long strtol(const char*, char**, int);
+int symlink(const char*, const char*);
+long sysconf(int);
+int system(const char*);
+char* tmpnam(char*);
+int unlink(const char*);
+int vfork(void);
+int waitpid(pid_t, int*, int);
+.EE
+.SH DESCRIPTION
+These routines are described in the ANSI C, POSIX, BSD and System V manual
+sections 2 and 3.
+The interfaces are preserved and present in all libast implementations.
+Where conflicts exist the POSIX syntax and semantics are implied.
+The appropriate error value is returned and
+.I errno
+is set to
+.L EINVAL
+when emulation is either too expensive or not possible.
+.SH CAVEATS
+If you
+.L "#undef foo"
+and then call
+.L foo
+you may end up with the local implementation of
+.LR foo ,
+and then you get what you payed for.
diff --git a/src/lib/libast/man/error.3 b/src/lib/libast/man/error.3
new file mode 100644
index 0000000..df47d34
--- /dev/null
+++ b/src/lib/libast/man/error.3
@@ -0,0 +1,283 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH ERROR 3
+.SH NAME
+error \- error and debug trace message formatter
+.SH SYNOPSIS
+.EX
+#include <error.h>
+
+Error_info_t error_info;
+
+void error(int \fIlevel\fP, ...);
+void errorv(const char* \fIlibrary\fP, int \fIlevel\fP, va_alist \fIargs\fP);
+void liberror(const char* \fIlibrary\fP, int \fIlevel\fP, ...);
+
+#include <debug.h>
+
+debug(\fIstatement\fP)
+message((int \fIlevel\fP, ...))
+libmessage((const char* \fIlibrary\fI, int \fIlevel\fP, ...))
+.EE
+.SH DESCRIPTION
+.L error
+is the error and debug trace message formatter.
+.I level
+is the severity level.
+Messages with
+.I "level < error_info.trace"
+are suppressed.
+.I error_info.trace
+is initially
+.LR 0 .
+The remaining arguments are passed on to
+.LR printf .
+A
+.I newline
+is appended to the message text, so none should appear in the
+.L printf
+format.
+If
+.I error_info.id
+is not
+.L 0
+then messages with
+.I "level > 0"
+are prefixed by
+.IR error_info.id: .
+.PP
+Before the message text is output to standard error
+it is passed to the function
+.LR "char* ERROR_translate(const char* \fItext\fP, int \fIflag\fP)" .
+By default
+.L ERROR_translate
+returns the
+.L text
+argument, but on some systems it may do language translation via lookup
+on the original source text.
+.RL ( error
+calls
+.L ERROR_translate
+with a 0
+.L flag
+argument).
+.PP
+.I level
+may be one of:
+.TP
+.B <0
+Negative values are for debug tracing.
+Debug messages are prefixed with
+.BI debug level.
+If
+.I "errno != error_info.last_errno"
+then
+.I error_info.last_errno
+is set to
+.I errno
+and the error text for errno is appended to the message.
+.TP
+.B "ERROR_INFO [0]"
+Information only; no prefixes are added to the message.
+.TP
+.B "ERROR_WARNING [1]"
+.L "warning:"
+is added after
+.L error_info.id
+and
+.I error_info.warnings
+is incremented.
+.TP
+.I "ERROR_ERROR [2]"
+(soft error)
+.I error_info.errors
+is incremented.
+.TP
+.B ">= ERROR_FATAL [3]"
+(hard error)
+.I error_info.errors
+is incremented and
+.L exit(\fIlevel\fP\-2)
+is called after the message is emitted.
+.TP
+.B "ERROR_PANIC [77]"
+(unrecoverable internal error)
+.L "panic:"
+is added after
+.IR error_info.id .
+.PP
+The following may be inclusive-or'd into
+.I level
+for alternate behavior:
+.TP
+.L ERROR_SYSTEM
+The error text for
+.I errno
+is appended to the message.
+.TP
+.L ERROR_OUTPUT
+The next argument is the file descriptor where the error message
+should be emitted.
+.TP
+.L ERROR_SOURCE
+Then next two arguments are a file name and line number that are added
+to the message after
+.IR error_info.id .
+.TP
+.L ERROR_USAGE
+A usage message is emitted.
+.TP
+.L ERROR_PROMPT
+The trailing
+.I newline
+is suppressed.
+.TP
+.L ERROR_NOID
+The
+.I error_info.id
+prefix is suppressed.
+.TP
+.L ERROR_LIBRARY
+The message is from a library routine.
+.SH ENVIRONMENT
+The elements of the global struct
+.I error_info
+control error output and actions.
+Parts of
+.I error_info
+can be initialized from the
+.L ERROR_OPTIONS
+environment variable.
+.L ERROR_OPTIONS
+contains space separated
+.IR name [ =value ]
+options, described below.
+.TP
+.I "int core"
+If
+.I "error_info.core != 0"
+then
+.I "level >= error_info.core"
+generates a core dump.
+Initialized by
+.EX
+ERROR_OPTIONS="core=\fIlevel\fP"
+.EE
+where
+.I level
+can be a number or one of
+.LR error ,
+.LR fatal ,
+or
+.LR panic .
+.I error_info.core
+is a handy way to get a stack trace at the exact point of error.
+.TP
+.I "int error_info.trace"
+If
+.I "error_info.trace != 0"
+and
+.I "level < error_info.trace"
+then the error message text is suppressed.
+.L exit()
+may still be called if appropriate for
+.IR level .
+Initialized by
+.EX
+ERROR_OPTIONS="trace=\fIlevel\fP"
+.EE
+where
+.I error_info.trace
+is set to the negative of
+.IR level .
+.PP
+Library error messages, suppressed by default, are enabled by
+.EX
+ERROR_OPTIONS="library"
+.EE
+The system
+.I errno
+message text can be forced for each message by
+.EX
+ERROR_OPTIONS="system"
+.EE
+.SH "EXTENDED DESCRIPTION"
+.L "<debug.h>"
+provides debugging message macros when
+.L DEBUG
+or
+.L _TRACE_
+are defined
+.RL ( _TRACE_
+is defined by
+.I makerules
+when
+.L CCFLAGS
+contains
+.LR \-g ).
+All of the macros expand to nothing when both
+.L DEBUG
+and
+.L _TRACE_
+are not defined.
+Otherwise
+.L debug
+expands its arg and
+.L libmessage
+and
+.L message
+call
+.L liberror
+and
+.L error
+respectively if
+.IR "error_info.trace<0" .
+Notice that
+.L libmessage
+and
+.L message
+are macro hacks that require double parentheses ((...)) around the
+arguments.
+.SH EXAMPLE
+To enable debugging message level -3, library messages, and system
+.I errno
+text for all commands:
+.EX
+export ERROR_OPTIONS="trace=3 library system"
+.EE
diff --git a/src/lib/libast/man/find.3 b/src/lib/libast/man/find.3
new file mode 100644
index 0000000..a14ceae
--- /dev/null
+++ b/src/lib/libast/man/find.3
@@ -0,0 +1,89 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH FIND 3
+.SH NAME
+find \- fastfind algorithm interface
+.SH SYNOPSIS
+.EX
+#include <find.h>
+
+void* findopen(const char* \fIpattern\fP);
+char* findnext(void* \fIhandle\fP);
+void findclose(void* \fIhandle\fP);
+.EE
+.SH DESCRIPTION
+These routines access the data generated by the
+.I fastfind
+algorithm.
+The data itself is generated by a standalone program that is run daily
+via
+.I cron
+or
+.IR at .
+.PP
+.L findopen
+returns a handle to a
+.I fastfind
+stream for the
+.I ksh
+file pattern
+.IR pattern .
+.L findnext
+returns the next pathname that matches the pattern specified by
+.IR handle .
+.L findnext
+returns
+.L 0
+when no more pathnames match the pattern.
+Finally,
+.L findclose
+closes the
+.I fastfind
+stream for
+.IR handle .
+.SH BUGS
+These rotuines are only as good as the
+.I fastfind
+information which is in the system administration domain.
+.SH "SEE ALSO"
+tw(1),
+find(1),
+strmatch(3)
+.br
+James A. Woods, \fIFast Find Algorithm\fP, Usenix ;login:, February/March, 1983, p. 8
diff --git a/src/lib/libast/man/fmt.3 b/src/lib/libast/man/fmt.3
new file mode 100644
index 0000000..dbe1aab
--- /dev/null
+++ b/src/lib/libast/man/fmt.3
@@ -0,0 +1,213 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH FMT 3
+.SH NAME
+fmt \- string formatting routines
+.SH SYNOPSIS
+.EX
+#include <ast.h>
+#include <ls.h>
+
+char* fmtbase(long \fInumber\fP, int \fIbase\fP, int \fIprefix\fP);
+char* fmtdev(struct stat* \fIst\fP);
+char* fmtelapsed(unsigned long \fIcount\fP, int \fIpersec\fP)
+char* fmterror(int \fIerrno\fP);
+char* fmtesc(const char* \fIstring\fP);
+char* fmtfs(struct stat* \fIst\fP);
+char* fmtgid(int \fIgid\fP);
+char* fmtmatch(const char* \fIre\fP);
+char* fmtmode(int \fImode\fP, int \fIexternal\fP);
+char* fmtperm(int \fIperm\fP);
+char* fmtre(const char* \fIpattern\fP);
+char* fmtsignal(int \fIsig\fP);
+char* fmttime(const char* \fIformat\fP, time_t \fItm\fP);
+char* fmtuid(int \fIuid\fP);
+.EE
+.SH DESCRIPTION
+These routines return a pointer to a formatted string for various numeric
+and string entities.
+Some routines may cache information to speed up the next call.
+Most of the routines return a pointer to a private buffer, the
+contents of which are overwritten on the next call to that routine.
+Most
+.L fmt
+routines have a corresponding
+.L str
+routine that converts in the other direction.
+There is nothing spectacular about this collection other than that
+it provides a single place where the exact format is spelled out.
+.PP
+.L fmtbase
+formats a base
+.I base
+representation for
+.IR number .
+If
+.I "prefix != 0"
+then the base prefix is included in the formatted string.
+If
+.I "number == 0"
+or
+.I "base == 0"
+then the output is signed base 10.
+.PP
+.L fmtdev
+returns the device handle name specified by the
+.L stat
+structure
+.IR st .
+This is the device information displayed by
+.IR "ls \-l" .
+.PP
+.L fmtelapsed
+formats the elapsed time for
+.I (count/persec)
+seconds.
+The two largest time units are used, limiting the return value length
+to at most 6 characters.
+The units are:
+.RS
+.TP
+.B s
+seconds
+.TP
+.B m
+minutes
+.TP
+.B h
+hours
+.TP
+.B days
+.TP
+.B weeks
+.TP
+.B M
+months
+.TP
+.B Y
+years
+.TP
+.B S
+scores
+.RE
+.PP
+.L fmterror
+returns the system error message text for the error number
+.IR errno .
+.PP
+.L fmtesc
+formats non-ASCII characters in
+.I string
+into C-style
+.B \e
+sequences.
+These sequences are understood by
+.L chresc
+and
+.LR chrtoi .
+.PP
+.L fmtfs
+returns the file system type name corresponding to the
+.L stat
+structure
+.IR st .
+.PP
+.L fmtgid
+returns the group name for
+.IR gid .
+.PP
+.L fmtmatch
+returns the
+.L strmatch
+equivalent pattern for the regular expression pattern
+.IR re .
+0 is returned for invalid
+.IR re .
+.PP
+.L fmtmode
+returns the
+.I "ls \-l"
+mode string for the file mode bits in
+.IR mode .
+If
+.I "external != 0"
+then
+.I mode
+is
+.IR modecanon (3)
+canonical.
+.PP
+.L fmtperm
+returns the
+.I chmod
+permission string for the permission bits in
+.IR perm .
+.PP
+.L fmtre
+returns the regular expression
+equivalent pattern for the
+.L strmatch
+pattern
+.IR pattern .
+0 is returned for invalid
+.IR pattern .
+.PP
+.L fmtsignal
+returns the signal name, sans
+.LR SIG ,
+for the signal number
+.IR sig .
+If
+.I "sig < 0"
+then the description text for
+.I \-sig
+is returned.
+.PP
+.L fmttime
+returns the results of
+.I "tmfmt(buf,sizeof(buf),format,tm)"
+in the private buffer
+.IR buf .
+.PP
+.L fmtuid
+returns the user name for
+.IR uid .
+.SH "SEE ALSO"
+modecanon(3),
+str(3)
diff --git a/src/lib/libast/man/fmtls.3 b/src/lib/libast/man/fmtls.3
new file mode 100644
index 0000000..50d872b
--- /dev/null
+++ b/src/lib/libast/man/fmtls.3
@@ -0,0 +1,143 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRLS 3
+.SH NAME
+fmtls \- format file information in buffer
+.SH SYNOPSIS
+.EX
+#include <ls.h>
+
+char* fmtls(char* \fIbuf\fP, char* \fIname\fP, struct stat* \fIst\fP, char* \fIinfo\fP, char* \fIlink\fP, int \fIflags\fP);
+.EE
+.SH DESCRIPTION
+.L fmtls
+formats
+.IR ls (1)
+style file information into the buffer
+.IR buf .
+A pointer to the trailing 0 in
+.I buf
+is returned.
+.I name
+is the file name.
+.I st
+is a pointer to the
+.B "struct stat
+status information for
+.I name
+obtained from one of the
+.IR stat (2)
+routines.
+.I info
+is an additional string that will appear before
+.I name
+in
+.I buf
+and
+.I link
+is the name of the related hard or soft link file.
+Both
+.I info
+and
+.I link
+may be 0.
+.I flags
+controls the format style and may be a combination of the following:
+.PP
+.TP
+.B LS_ATIME
+Use
+.I st->st_atime
+rather than
+.I st->st_mtime
+for
+.BR LS_LONG .
+.TP
+.B LS_CTIME
+Use
+.I st->st_mtime
+rather than
+.I st->st_mtime
+for
+.BR LS_LONG .
+.TP
+.B LS_BLOCKS
+List the number of blocks.
+.TP
+.B LS_INUMBER
+List the file serial number (inode number).
+.TP
+.B LS_LONG
+List the file mode, link count, user and group name,
+size or major/minor device number, and date along with the
+file name.
+.TP
+.B LS_MARK
+The file name is appended with
+.L /
+for directories,
+.L @
+for symbolic links,
+and
+.L *
+for executable files.
+.TP
+.B LS_NOGROUP
+Omit the group name from
+.BR LS_LONG .
+.TP
+.B LS_NOUSER
+Omit the user name from
+.BR LS_LONG .
+.PP
+The user and group fields are each
+.B LS_W_NAME
+characters wide,
+the
+.B LS_INUMBER
+field is
+.B LS_W_INUMBER
+characters wide,
+and the
+.B LS_BLOCKS
+field is
+.B LS_W_BLOCKS
+characters wide.
+.SH "SEE ALSO"
+ls(1), stat(2), strmode(3)
diff --git a/src/lib/libast/man/fs3d.3 b/src/lib/libast/man/fs3d.3
new file mode 100644
index 0000000..7dfd448
--- /dev/null
+++ b/src/lib/libast/man/fs3d.3
@@ -0,0 +1,92 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH FS3D 3
+.SH NAME
+fs3d \- 3D (nDFS) on/off switch
+.SH SYNOPSIS
+.EX
+#include <fs3d.h>
+
+int fs3d(int \fIop\fP);
+.EE
+.SH DESCRIPTION
+.L fs3d
+controls and queries the
+.B 3D
+file system
+.RB (aka nDFS )
+enable state.
+.L 0
+is returned if the current process cannot mount
+.B 3D
+files.
+.I op
+may be one of:
+.TP
+.B FS3D_TEST
+Returns
+.L "FS3D_ON [1]"
+if
+.B 3D
+is enabled,
+.L "FS3D_OFF [0]"
+otherwise.
+.TP
+.B FS3D_ON
+Enables
+.B 3D
+and returns the previous
+.L 3D
+state (either
+.B FS3D_ON
+or
+.BR FS3D_OFF ).
+.TP
+\fBFS3D_LIMIT(\fIlimit\fB)\fR
+Sets the viewpath level limit to
+.IR limit .
+The previous limit is returned.
+.TP
+.B FS3D_INIT
+Re-initialize the
+.B 3D
+tables.
+Used for debugging.
+.SH "SEE ALSO"
+3D(1)
diff --git a/src/lib/libast/man/ftwalk.3 b/src/lib/libast/man/ftwalk.3
new file mode 100644
index 0000000..f339ab7
--- /dev/null
+++ b/src/lib/libast/man/ftwalk.3
@@ -0,0 +1,235 @@
+.fp 5 CW
+.TH FTWALK 3
+.SH NAME
+\fBftwalk\fR \- file tree walker
+.SH SYNOPSIS
+.ta .75i 1.5i 2.25i 3i 3.75i 4.5i 5.25i 6i
+.PP
+.nf
+\f5
+#include <ftwalk.h>
+
+int ftwalk(char* path, int (*userf)(struct FTW* ftw), int options,
+ int (*comparf)(struct FTW* ftw1, struct FTW* ftw2));
+
+
+int ftwflags(void);
+\fR
+.fi
+.SH DESCRIPTION
+.PP
+\fIFtwalk\fR traverses a directory hierarchy using depth-first search.
+Upon visiting each file or directory in the hierarchy, it calls
+the user function \fIuserf\fP to process that file or directory.
+On a directory object, \fIuserf\fR may be called twice, once in preorder
+and once in postorder.
+On a terminal object such as a file or an unreadable directory,
+\fIuserf\fP is called only once.
+Cycles due to hard links or symbolic links are detected
+to avoid infinite loops.
+.PP
+\fIPath\fR is the starting point of the search.
+It may be an absolute path name or a path name relative to
+the current directory.
+If \fIpath\fR is a null pointer or points to an empty string, it is treated
+as if it points to the current (dot) directory.
+.PP
+\fIOptions\fR consists of zero or more of the following bits:
+.IP
+FTW_CHILDREN:
+This implies preorder calls to \fIuserf\fR on directory objects.
+On such a call to \fIuserf\fR,
+the field \fIftw->link\fR (below) points to a link list of
+the children of the respective directory.
+Upon returning from \fIuserf\fP,
+if the field \fIftw->status\fR of any child object
+is set to FTW_SKIP (below), that child is pruned from the search.
+.IP
+FTW_DELAY: When \fBFTW_CHILDREN\fP is turned on,
+the fields \fIftw->statb\fP (\fIstruct stat\fP) of children objects
+remain undefined until these objects are visited.
+.IP
+FTW_DOT: Do not use \fIchdir\fR(2) during the traversal.
+Normally \fIchdir\fR is used so that
+the base name of the object about to be processed can be used
+in accessing its data.
+This can enhance \fIftwalk\fR efficiency but certain program effects
+such as core dumps may be generated in unexpected places
+or may not even be generated at all.
+Whenever \fIchdir\fR generates an error, if possible,
+the current directory is restored to the starting directory
+(see FTW_NAME and FTW_PATH).
+.IP
+FTW_MULTIPLE: The \fIpath\fP argument is treated as a \fIchar**\fP
+pointer to a null-terminated array of path names.
+All hierarchies rooted at these paths will be searched
+.IP
+FTW_POST: Calls to the user function are issued only in postorder.
+That is, \fIuserf\fP is called on a directory only after its descendants have
+been processed.
+The absence of this bit indicates that calls to the user functions
+are issued in preorder. That is, \fIuserf\fP is
+called on a directory before its descendants are processed.
+.IP
+FTW_PHYSICAL: Use \fIlstat\fR(2) instead of \fIstat\fR(2) to get
+file status and allow detection of symbolic links.
+In addition, if each component
+of the absolute path to the starting object has search permission,
+the absolute path is used for early detection of cycles.
+.IP
+FTW_META|FTW_PHYSICAL: Use \fIstat\fR(2) for top level file status and
+\fIlstat\fR(2) for all other files.
+Used to implement the POSIX
+.B \-H
+option for commands like
+.IR ls .
+.IP
+FTW_TWICE: Calls to the user function are issued in both preorder and postorder
+for directory objects.
+.IP
+FTW_USER: The first of 6 user defined option bits.
+These bits are ignored by \fIftwalk\fP.
+.PP
+\fIUserf\fR is a user supplied function that is
+called upon different visits of an object.
+If the return value of \fIuserf\fR is non-zero,
+\fIftwalk\fR returns immediately with the same value.
+The \fIuserf\fP prototype is:
+.PP
+.nf
+ int userf(struct FTW* ftw)
+.fi
+.PP
+\fBstruct FTW\fP contains at least the following elements:
+.PP
+.nf
+ struct FTW* link; /* link list of children */
+ struct FTW* parent; /* parent object on the search path */
+ union
+ {
+ long number; /* local number */
+ void* pointer; /* local pointer */
+ } local; /* user defined */
+ struct stat statb; /* stat buffer of this object */
+ char* path; /* full pathname */
+ short pathlen; /* strlen(path) */
+ unsigned short info; /* type of object */
+ unsigned short status; /* status of object */
+ short level; /* depth of object on the search path */
+ short namelen; /* strlen(name) */
+ char name[]; /* file name of object */
+.fi
+.PP
+The \fIlink\fR field is normally NULL.
+If the option FTW_CHILDREN was turned on,
+it points to the start of the list of children
+of the directory being visited in preorder.
+Finally, if the directory being visited causes a cycle,
+\fIlink\fR points to the object on the search path that is
+identical to this directory. Note that if FTW_PHYSICAL was turned on,
+this may point to a directory that is an ancestor of the starting
+object.
+.PP
+The \fIparent\fR field points to the parent object
+on the search path. For convenience, a parent object is also supplied for
+the starting object.
+In this case, except for the \fIlocal\fR field which is initialized
+to 0 and the \fIlevel\fR field which contains a negative number,
+the rest of the structure may be undefined.
+.PP
+The \fIinfo\fR field indicates the type of the object
+being visited and the type of the visit. The types are:
+.IP
+FTW_D: A directory being visited in preorder, i.e.,
+none of its children has been visited by the search.
+.IP
+FTW_DNX: A directory being visited in preorder that does not have
+search permission.
+.IP
+FTW_DP: A directory being visited in postorder, i.e., all of its
+descendants have been completely processed.
+.IP
+FTW_DC: A directory that causes cycles. This is a terminal object.
+.IP
+FTW_DNR: A directory that cannot be opened for reading. This is a terminal object.
+.IP
+FTW_F: An ordinary file.
+.IP
+FTW_SL: A symbolic link.
+Unless FTW_FOLLOW (below) is issued by the user function,
+this object is terminal.
+.IP
+FTW_NS: \fIStat\fR failed on this object.
+The stat buffer \fIstatb\fR is undefined.
+This object is terminal.
+.PP
+The \fIstatus\fR field of \fIstruct FTW\fR is used to communicate information
+between \fIftwalk\fR and \fIuserf\fR. On calls to \fIuserf\fR, it has one of
+two values:
+.IP
+FTW_NAME: The name of the object as defined in \fIftw->name\fR should be used for
+accessing its file information. This is because \fIchdir\fR(2) has been used
+to set the current directory to a suitable place (see FTW_CHDIR).
+.IP
+FTW_PATH: The argument \fIpath\fR of \fIuserf\fR should be used
+for accessing the file information of the object.
+.PP
+Upon returning, \fIuserf\fR may set the \fIstatus\fR field
+to one of the following values:
+.IP
+FTW_AGAIN: If this is a directory object being visited in postorder,
+it will be processed \fIagain\fR as if it had not been visited.
+.IP
+FTW_NOPOST: If this is a directory object being visited in preorder,
+the user function will not be called on its postorder visit.
+.IP
+FTW_SKIP: This object and its descendants are pruned from the search.
+.IP
+FTW_FOLLOW: If this object is a symbolic link,
+follow the link to its physical counterpart.
+.PP
+\fIComparf\fR, if not NULL, is a pointer to a function
+used to define a search ordering for children of a directory.
+If FTW_CHILDREN is turned on, the ordering of the children of
+a directory is done before the preorder call to \fIuserf\fR on that directory.
+Therefore, in that case, \fIftw->link\fR will point to the smallest child.
+.PP
+The \fIcomparf\fP prototype is:
+.PP
+.nf
+ int comparf(struct FTW* ftw1, struct FTW* ftw2)
+.fi
+.PP
+\fIComparf\fR should return a value <0, 0, or >0 to indicate whether
+\fIftw1\fR is considered smaller, equal, or larger than \fIftw2\fR.
+.PP
+\fIFtwalk\fR normally returns 0.
+On hard errors such as running out of memory, it returns -1.
+\fIFtwalk\fR may also return other values as discussed with respect
+to \fIuserf\fR.
+.PP
+\fIFtwflags\fR returns a combination of \fB0, FTW_META, FTW_PHYSICAL\fR
+according to the
+preferences specified by
+\fBastconf("PATH_RESOLVE",0,0)\fR:
+.TP
+.B logical
+0
+.TP
+.B metaphysical
+.B "FTW_META|FTW_PHYSICAL"
+.TP
+.B physical
+.B FTW_PHYSICAL
+.SH HISTORY
+\fIFtwalk\fR performs similar functions as that of
+the routine \fIftw\fR provided in System V.
+However, it is more general than \fIftw\fR
+and suitable for use as a base in implementing
+popular tools such as \fIls, find, tar, du,\fR and \fIrm\fR.
+\fIFtwalk\fR also handles symbolic links and hard links gracefully.
+.SH AUTHORS
+Phong Vo, Glenn Fowler, Dave Korn
+.SH SEE ALSO
+find(1), rm(1), du(1), ls(1), tar(1), stat(2), symlink(2),
+astfeature(3), ftw(3), pathcd(3)
diff --git a/src/lib/libast/man/getcwd.3 b/src/lib/libast/man/getcwd.3
new file mode 100644
index 0000000..3403296
--- /dev/null
+++ b/src/lib/libast/man/getcwd.3
@@ -0,0 +1,67 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH GETCWD 3
+.SH NAME
+getcwd \- return absolute path to current directory
+.SH SYNOPSIS
+.EX
+#include <ast.h>
+
+char* getcwd(char* \fIbuf\fP, size_t \fIlen\fP);
+.EE
+.SH DESCRIPTION
+.L getcwd
+copies the absolute path name of the current directory info into
+.I buf
+of length
+.IR len .
+The return path may be longer than
+.LR PATH_MAX .
+If
+.I "buff == 0"
+then space is allocated via
+.IR malloc (3)
+and
+.I len
+extra characters are reserved after the generated path name.
+A pointer to the path name is returned,
+.L 0
+on error.
+.SH "SEE ALSO"
+pathcd(3)
diff --git a/src/lib/libast/man/hash.3 b/src/lib/libast/man/hash.3
new file mode 100644
index 0000000..162d62d
--- /dev/null
+++ b/src/lib/libast/man/hash.3
@@ -0,0 +1,644 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH HASH 3
+.SH NAME
+hash \- hash table support (obsolete: use \fBcdt\fP instead)
+.SH SYNOPSIS
+.L "#include <hash.h>"
+.SH DESCRIPTION
+The
+.I hash
+routines manipulate collections of dynamic, scoped hash tables.
+.PP
+A hash table provides an association between a
+.I key
+and its
+.IR value .
+A
+.I key
+is a sequence of
+.L char
+elements and a
+.I value
+is a user supplied pointer to the value.
+Each hash table has a dynamic number of slots,
+each pointing to the head of a forward linked
+.IR "collision chain" .
+.PP
+Hashing occurs as follows:
+a
+.I "hash function"
+takes a
+.I key
+as an argument and returns a non-negative index.
+The index modulo the table size produces a
+slot that points to a
+.IR "collision chain" .
+The collision chain is sequentially searched until a match is found for
+.IR key .
+The hash tables are automatically resized as new entries are added.
+.PP
+Each hash table has one key type.
+The default key type is a pointer to a null-terminated string.
+The alternate key type is a pointer to a fixed length byte buffer,
+declared for a given table by the
+.L hashalloc()
+function described below.
+.PP
+Hash table information is partitioned into two parts for efficient scoping.
+The
+.I root
+part contains fixed information that is shared among a set of related
+hash tables.
+The remaining information is maintained on a per-table basis.
+.PP
+These basic types are defined in the header file
+.B hash.h
+(alternate names are listed in parenthesis):
+.TP
+.L "Hash_table_t (HASHTABLE)"
+The per-table information.
+The readonly public elements are:
+.RS
+.TP
+.L "int buckets"
+The number of table entries.
+.TP
+.L "char* name"
+The hash table name.
+.TP
+.L "root"
+The root information.
+The public elements are:
+.RS
+.TP
+.L "int root->accesses"
+The number of lookups.
+.TP
+.L "int root->collisions"
+The number of lookup collisions.
+.RE
+.TP
+.L "Hash_table_t* scope"
+The table that this scope covers,
+.L NULL
+if the table is not a scope.
+.TP
+.L "int size"
+The current hash table size.
+.RE
+.TP
+.L "Hash_bucket_t (HASHBUCKET)"
+A collision chain hash bucket.
+The public structure elements are:
+.RS
+.TP
+.L "char* hashname(Hash_bucket_t*)"
+Returns a pointer to the hash bucket key given the bucket pointer.
+.TP
+.L "char* value"
+The value associated with the key.
+.RE
+.TP
+.L "Hash_header_t (HASHHEADER)"
+The hash bucket header that must be the first element in all user defined
+buckets.
+.L HASH_VALUE
+may not be used with user defined buckets.
+.TP
+.L "Hash_position_t (HASHPOSITION)"
+Stores the hash table position for
+.LR hashscan .
+The public elements are:
+.RS
+.TP
+.L "Hash_bucket_t* bucket"
+The current hash bucket pointer.
+.RE
+.PP
+The routines are:
+.TP
+.L "Hash_table_t* hashalloc(Hash_table_t* ref, int op, ...)"
+Creates a new hash table and returns a pointer to the table.
+.IR malloc (3)
+is used to allocate space for the table.
+.L NULL
+is returned if the table cannot be created.
+.L ref
+is a pointer to a reference hash table that provides
+default values for unspecified information.
+The new hash table and
+.L ref
+share the same root information.
+If
+.L ref
+is
+.L NULL
+then new root information is created for the new table.
+The remaining arguments appear in
+.I op-arg
+pairs, followed by a final
+.L 0
+argument.
+The
+.I op-arg
+pairs are:
+.RS
+.TP
+.L "HASH_alloc, (char(*)()) alloc"
+.L alloc
+is a function that is called to process
+.L Hash_bucket_t
+.L value
+assignments.
+The single argument is
+.L "char* value"
+and the processed
+.L char*
+value is returned.
+.TP
+.L "HASH_clear, int flags"
+.L flags
+are the
+.L ref
+flags to be cleared in the new hash table.
+See
+.L HASH_set
+below.
+.TP
+.L "HASH_compare, (int(*)()) compare"
+Specifies an alternate
+.I key
+comparison function.
+The arguments and return value for
+.L compare
+are the same as for
+.IR strncmp (3)
+if
+.L HASH_namesize
+is specified and
+.IR strcmp (3)
+otherwise.
+The first argument is the
+.I key
+from the current hash bucket on the
+.I "collision chain"
+and the second argument is the user supplied
+.IR key .
+.TP
+.L "HASH_free, (int(*)()) free"
+.L free
+is a function that is called when a hash bucket is freed.
+If
+.L HASH_BUCKET
+was set in
+.L hashalloc
+then the hash bucket pointer is passed, otherwise the bucket
+.L value
+pointer is passed.
+.TP
+.L "HASH_hash, (int(*)()) hash"
+Specifies an alternate
+.I key
+hash function.
+A
+.L char*
+key argument (and, if
+.L HASH_namesize
+is specified, an
+.L int
+key size argument) is passed to
+.LR hash .
+The return value must be a non-negative
+.LR int .
+.TP
+.L "HASH_meanchain, int meanchain"
+Specifies the mean collision chain length.
+The hash table is automatically resized when this value is exceeded.
+The default mean chain length is 2.
+.TP
+.L "HASH_name, char* name"
+Associates
+.L name
+with the hash table.
+Used by
+.LR hashdump) .
+.TP
+.L "HASH_namesize, int namesize"
+The fixed size in bytes for
+.I keys
+in the table.
+If
+.L namesize
+is 0 (the default) then the
+.I keys
+are interpreted as null-terminated strings.
+.TP
+.L "HASH_set, int flags"
+Changes the hash table flags by
+.IR or ing
+in
+.LR flags .
+The flags, which may be
+.IR or ed
+together, are:
+.RS
+.TP
+.L HASH_ALLOCATE
+Keys for new hash table entries are to be copied to data areas obtained from
+.IR malloc (3).
+.TP
+.L HASH_FIXED
+Fixes the hash table size, disabling any automatic table resizing.
+.TP
+.L HASH_SCOPE
+The new hash table is a scope that is to be pushed on top of
+.LR ref .
+.L ref
+must be
+.RL non- NULL .
+.RE
+.TP
+.L "HASH_va_list, va_list ap"
+.L ap
+is a
+.L va_list
+variable argument list pointer
+(see
+.LR <stdarg.h> ).
+.RE
+.TP
+.L "Hash_table_t* hashfree(Hash_table_t* tab)"
+The hash table
+.L tab
+is freed.
+The scope covered table pointer is returned,
+.L NULL
+if
+.L tab
+is not a scope.
+.TP
+.L "char* hashlook(Hash_table_t* tab, char* name, int flags, char* value)"
+Operates on the key
+.L name
+in the hash table
+.L tab
+according to
+.L flags
+and
+.LR value .
+A
+.L Hash_bucket_t
+pointer is returned unless otherwise noted.
+There are three basic lookup operations:
+.RS
+.TP
+.L HASH_CREATE
+.L name
+is entered into the top level scope if it does not already exist.
+If
+.L name
+also appears in a lower scope and
+.L HASH_ALLOC
+is set for the table then the new bucket will share the
+.L name
+field value with the lower scope.
+.TP
+.L HASH_DELETE
+.L name
+is deleted from the top level scope if it exists.
+.L NULL
+is returned.
+.TP
+.L HASH_LOOKUP
+The scopes are searched in order from top to bottom for
+.L name .
+The bucket pointer for the first occurrence is returned.
+.L NULL
+is returned if
+.L name
+is not found.
+.RE
+The basic operations may be qualified by the following
+(the qualifiers are restricted to the basic operations in
+the parenthesized list):
+.RS
+.TP
+.L "HASH_BUCKET (HASH_CREATE,HASH_DELETE,HASH_LOOKUP)"
+.L name
+is a pointer to a bucket that has already been entered into the table.
+.TP
+.L "HASH_FIXED (HASH_CREATE)"
+.L value
+is taken to be the size of the hash bucket to be created for
+.L name
+in the top level scope.
+The minimum bucket size is silently restricted to
+.LR sizeof(Hash_header_t) .
+.TP
+.L "HASH_INSTALL (HASH_CREATE)"
+.L name
+is a pointer to a bucket that has not been entered into the table.
+.TP
+.L "HASH_NOSCOPE (HASH_LOOKUP)"
+The lookup is restricted to the top level scope.
+.TP
+.L "HASH_OPAQUE (HASH_CREATE,HASH_DELETE)"
+Sets
+.L (HASH_CREATE)
+or clears
+.L (HASH_DELETE)
+the
+.I opaque
+property for the bucket.
+An opaque bucket is not visible in lower scopes.
+.TP
+.L "HASH_SCOPE (HASH_CREATE,HASH_DELETE)"
+All scopes are searched for the bucket.
+If the bucket is not found for
+.L HASH_CREATE
+then a new bucket is created in the lowest scope.
+.TP
+.L "HASH_VALUE (HASH_CREATE,HASH_LOOKUP)"
+For
+.L HASH_CREATE
+the bucket
+.L value
+field is set to
+.L value
+and the bucket
+.L name
+value is returned.
+For
+.L HASH_LOOKUP
+the bucket
+.L value
+field is returned,
+.L NULL
+if the bucket is not found.
+.RE
+If
+.L name
+.L NULL
+then the name from the most recent
+.L hashlook()
+is used, avoiding recomputation of some internal parameters.
+.TP
+.L "char* hashget(Hash_table_t* tab, char* name)"
+Returns the value
+associated with the key
+.L name
+in the hash table
+.LR tab .
+If
+.L name
+is
+.L NULL
+then the name from the most recent
+.L hashget()
+is used, avoiding recomputation of some internal parameters.
+.L NULL
+is returned if
+.L name
+is not in the table.
+All scope covered tables are searched.
+.TP
+.L "Hash_bucket_t* hashlast(Hash_table_t* tab)"
+Returns a pointer to the most recent hash bucket for
+.LR tab .
+The value is set by
+.LR hashlook() ,
+.L hashscan()
+and
+.LR hashwalk() .
+.TP
+.L "char* hashput(Hash_table_t* tab, char* name, char* value)"
+Set the value of the key
+.L name
+to
+.L value
+in the top level scope of the hash table
+.LR tab .
+.L name
+is entered into the top level scope if necessary.
+The (possibly re-allocated) key name pointer is returned
+(see
+.LR HASH_ALLOCATE ).
+If
+.L name
+is 0 then the most recent lookup
+.L name
+to
+.L hashlook()
+or
+.L hashget()
+is used.
+This eliminates a re-hash and re-lookup of
+.LR name .
+.TP
+.L "int hashwalk(Hash_table_t* tab, int flags, (int(*)()) walker, char* handle)"
+The function
+.L walker
+is applied to each entry (not covered by a scope starting at
+.LR tab )
+in the hash table
+.LR tab .
+If
+.L flags
+is
+.L HASH_NOSCOPE
+then only the top level hash table is used, otherwise the walk includes
+all scope covered tables.
+.L walker
+is called with
+.L char*
+.I key
+as the first argument,
+.L char*
+.I value
+as the second argument, and
+.L char*
+.I handle
+as the third argument.
+.I handle
+may be
+.LR 0 .
+The walk terminates after the last entry or when
+.L walker
+returns a negative value.
+The return value of the last call to
+.L walker
+is returned.
+Only one walk may be active within a collection of scoped tables.
+.TP
+.L "Hash_position_t* hashscan(Hash_table_t* tab, int flags)"
+Returns a
+.L Hash_position_t
+pointer for a sequential scan on the hash table
+.LR tab .
+If
+.L flags
+is
+.L HASH_NOSCOPE
+then only the top level hash table is used, otherwise the scan includes
+all scope covered tables.
+Only one scan may be active within a collection of scoped tables.
+.L hashdone()
+must be called to terminate the scan.
+.L 0
+is returned on error.
+.TP
+.L "Hash_bucket_t* hashnext(Hash_position_t* pos)"
+Returnes a pointer to the next bucket in the sequential scan set up by
+.L hashscan()
+on
+.LR pos .
+If no elements remain then
+.L 0
+is returned.
+.TP
+.L "void hashdone(Hash_position_t* pos)"
+Completes a scan initiated by
+.L hashscan()
+on
+.LR pos .
+.TP
+.L "int hashset(Hash_table_t* tab, int flags)"
+Sets the flags for the hash table
+.L tab
+by
+.IR or ing
+in
+.LR flags .
+Only
+.L HASH_ALLOCATE
+and
+.L HASH_FIXED
+may be set.
+.TP
+.L "int hashclear(Hash_table_t* tab, int flags)"
+Clears the flags for the hash table
+.L tab
+by masking out
+.LR flags .
+Only
+.L HASH_ALLOCATE
+and
+.L HASH_FIXED
+may be cleared.
+.TP
+.L "void hashdump(Hash_table_t* tab, int flags)"
+Dumps hash table accounting info to standard error.
+If
+.L tab
+is
+.L NULL
+then all allocated hash tables are dumped, otherwise only information on
+.L tab
+is dumped.
+If
+.L flags
+is
+.L HASH_BUCKET
+then the hash bucket
+.I key-value
+pairs for each collision chain are also dumped.
+.TP
+.L "void hashsize(Hash_table_t* tab, int size)"
+Changes the size of the hash table
+.L tab
+to
+.L size
+where
+.L size
+must be a power of 2.
+Explicit calls to this routine are not necessary as hash tables
+are automatically resized.
+.TP
+.L "int strhash(char* name)"
+Hashes the null terminated character string
+.L name
+using a linear congruent pseudo-random number generator algorithm
+and returns a non-negative
+.L int
+hash value.
+.TP
+.L "int memhash(char* buf, int siz)"
+Hashes the buffer
+.L buf
+of
+.L siz
+bytes using a linear congruent pseudo-random number generator algorithm
+and returns a non-negative
+.L int
+hash value.
+.TP
+.L "long strsum(char* name, long sum)"
+Returns a running 31-bit checksum of the string
+.L name
+where
+.L sum
+is
+.L 0
+on the first call and
+the return value from a previous
+.L memsum
+or
+.L strsum
+call otherwise.
+The checksum value is consistent across all implementations.
+.TP
+.L "long memsum(char* buf, int siz, long sum)"
+Returns a running 31-bit checksum of buffer
+.L buf
+of
+.L siz
+bytes where
+.L sum
+is
+.L 0
+on the first call and
+the return value from a previous
+.L memsum
+or
+.L strsum
+call otherwise.
+The checksum value is consistent across all implementations.
+.SH "SEE ALSO"
+sum(1)
diff --git a/src/lib/libast/man/iblocks.3 b/src/lib/libast/man/iblocks.3
new file mode 100644
index 0000000..0c615f8
--- /dev/null
+++ b/src/lib/libast/man/iblocks.3
@@ -0,0 +1,62 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH IBLOCKS 3
+.SH NAME
+iblocks \- compute number file blocks used
+.SH SYNOPSIS
+.EX
+#include <ls.h>
+
+long _iblocks(struct stat* \fIst\fP);
+.EE
+.SH DESCRIPTION
+.L _iblocks
+returns the number of blocks used by the file whose
+.IR stat (2)
+information is pointed to by
+.IR st .
+The count includes both data and indirect blocks.
+.PP
+This routine is used by
+.B <ls.h>
+on system without the
+.LI "struct stat" st_blocks
+field.
+.SH "SEE ALSO"
+ls(1), stat(2)
diff --git a/src/lib/libast/man/int.3 b/src/lib/libast/man/int.3
new file mode 100644
index 0000000..8d457c0
--- /dev/null
+++ b/src/lib/libast/man/int.3
@@ -0,0 +1,68 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH INT 3
+.SH NAME
+int \- integral type macros
+.SH SYNOPSIS
+.EX
+#include <int.h>
+.EE
+.SH DESCRIPTION
+This header defines macros for the local integral types.
+.LR int_1 ,
+.LR int_2
+and
+.L int_4
+are always defined to integral types with a size of
+1, 2 and 4 bytes respectively.
+The macros
+.LI int_ n
+where
+.I n
+is a power of 2 greater than 4 are defined if the type is supported.
+.L int_max
+is defined to be the largest support integral type.
+.L int_swap
+is the
+.IR swap (3)
+operation that converts a local
+.L int
+to canonical big-endian representation.
+.SH "SEE ALSO"
+swap(3)
diff --git a/src/lib/libast/man/ip6.3 b/src/lib/libast/man/ip6.3
new file mode 100644
index 0000000..1dadb05
--- /dev/null
+++ b/src/lib/libast/man/ip6.3
@@ -0,0 +1,85 @@
+.fp 5 B
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH IP6 3
+.SH NAME
+ip6 \- IP V6 address support
+.SH SYNOPSIS
+.EX
+#include <ip6.h>
+
+char* fmtip6(unsigned char* addr, int bits);
+int strtoip6(const char* str, char** end, unsigned char* addr, unsigned char* bits);
+.EE
+
+.SH DESCRIPTION
+.L fmtip6()
+formats the IPV6 address
+.L addr
+with optional prefix bits
+.L bits
+(0 if not a prefix) into a thread-specific 0-terminated temporary buffer and returns a pointer
+to the formatted value.
+
+.PP
+.L strtoip6()
+converts a formatted IPV6 address from the 0-terminated string
+.L str
+into a host order IPV6 address in
+.L addr
+which must be a buffer of at least
+.L IP6ADDR
+bytes.
+If
+.L bits
+is not 0 then an optional
+.BI / bits
+(prefix size in bits) is parsed and
+.L *bits
+is set to the number of prefix bits.
+If
+.L end
+is not 0 then
+.L *end
+will point to the first unparsed character in
+.L str
+on return.
+0 is returned on success, -1 on failure.
+
+.SH "SEE ALSO"
+dss(1)
diff --git a/src/lib/libast/man/magic.3 b/src/lib/libast/man/magic.3
new file mode 100644
index 0000000..e8bf0e3
--- /dev/null
+++ b/src/lib/libast/man/magic.3
@@ -0,0 +1,493 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH MAGIC 3
+.SH NAME
+magic \- magic file interface
+.SH SYNOPSIS
+.EX
+#include <magic.h>
+
+Magic_t
+{
+ unsigned long flags;
+};
+
+Magic_t* magicopen(unsigned long \fIflags\fP);
+void magicclose(Magic_t* \fImagic\fP);
+
+int magicload(Magic_t* \fImagic\fP, const char* \fIpath\fP, unsigned long \fIflags\fP);
+int magiclist(Magic_t* \fImagic\fP, Sfio_t* \fIsp\fP);
+
+char* magictype(Magic_t* \fImagic\fP, const char* \fIpath\fP, struct stat* \fIst\fP);
+.EE
+.SH DESCRIPTION
+These routines provide an interface to the
+.IR file (1)
+command magic file.
+.L magicopen
+returns a magic session handle that is passed to all of the other routines.
+.I flags
+may be
+.TP
+.L MAGIC_MIME
+Return the MIME type string rather than the magic file description.
+.TP
+.L MAGIC_PHYSICAL
+Don't follow symbolic links.
+.TP
+.L MAGIC_STAT
+The stat structure
+.I st
+passed to
+.I magictype
+will contain valid
+.I stat (2)
+information.
+See
+.L magictype
+below.
+.TP
+.L MAGIC_VERBOSE
+Enable verbose error messages.
+.PP
+.L magicclose
+closes the magic session.
+.PP
+.L magicload
+loads the magic file named by
+.I path
+into the magic session.
+.I flags
+are the same as with
+.LR magicopen .
+More than one magic file can be loaded into a session;
+the files are searched in load order.
+If
+.I path
+is
+.L 0
+then the default magic file is loaded.
+.PP
+.L magiclist
+lists the magic file contents on the
+.IR sfio (3)
+stream
+.IR sp .
+This is used for debugging magic entries.
+.PP
+.L magictype
+returns the type string for
+.I path
+with optional
+.IR stat (2)
+information
+.IR st .
+If
+.I "st == 0"
+then
+.L magictype
+calls
+.L stat
+on a private stat buffer,
+else if
+.L magicopen
+was called with the
+.L MAGIC_STAT
+flag then
+.I st
+is assumed to contain valid stat information, otherwise
+.L magictype
+calls
+.L stat
+on
+.IR st .
+.L magictype
+always returns a non-null string.
+If errors are encounterd on
+.I path
+then the return value will contain information on those errors, e.g.,
+.LR "cannot stat" .
+.SH FORMAT
+The magic file format is a backwards compatible extension of an
+ancient System V file implementation.
+However, with the extended format it is possible to write a single
+magic file that works on all platforms.
+Most of the net magic files floating around work with
+.LR magic ,
+but they usually double up on
+.I le
+and
+.I be
+entries that are automatically handled by
+.LR magic .
+.PP
+A magic file entry describes a procedure for determining a single file type
+based on the file pathname,
+.I stat (2)
+information, and the file data.
+An entry is a sequence of lines, each line being a record of
+.I space
+separated fields.
+The general record format is:
+.EX
+[op]offset type [mask]expression description [mimetype]
+.EE
+.L #
+in the first column introduces a comment.
+The first record in an entry contains no
+.LR op ;
+the remaining records for an entry contain an
+.LR op .
+Integer constants are as in C:
+.L 0x*
+or
+.L 0X*
+for hexadecimal,
+.L 0*
+for octal and decimal otherwise.
+.PP
+The
+.L op
+field may be one of:
+.TP
+.L +
+The previous records must match but the current record is optional.
+.L >
+is an old-style synonym for
+.LR + .
+.TP
+.L &
+The previous and current records must match.
+.TP
+.L {
+Starts a nesting block that is terminated by
+.LR } .
+A nesting block pushes a new context for the
+.L +
+and
+.L &
+ops.
+The
+.L {
+and
+.L }
+records have no other fields.
+.TP
+\fIid\f5{\fR
+A function declaration and call for the single character identifier
+.IR id .
+The function return is a nesting block end record
+.LR } .
+Function may be redefined.
+Functions have no arguments or return value.
+.TP
+\fIid\f5()\fR
+A call to the function
+.IR id .
+.PP
+The
+.L offset
+field is either the offset into the data upon which the current entry operates
+or a file metadata identifier.
+Offsets are either integer constants or offset expressions.
+An offset expression is contained in (...) and is a combination of
+integral arithmetic operators and the
+.L @
+indirection operator.
+Indirections take the form
+.LI @ integer
+where integer is the data offset for the indirection value.
+The size of the indirection value is taken either from one of the suffixes
+.LR B (byte, 1 char),
+.LR H (short, 2 chars),
+.LR L (long, 4 chars),
+pr
+.LR Q (quead, 8 chars),
+or from the
+.L type
+field.
+Valid file metadata identifiers are:
+.TP
+.L atime
+The string representation of
+.LR stat.st_atime .
+.TP
+.L blocks
+.LR stat.st_blocks .
+.TP
+.L ctime
+The string representation of
+.LR stat.st_ctime .
+.TP
+.L fstype
+The string representation of
+.LR stat.st_fstype .
+.TP
+.L gid
+The string representation of
+.LR stat.st_gid .
+.TP
+The
+.L stat.st_mode
+file mode bits in
+.IR modecanon (3)
+canonical representation (i.e., the good old octal values).
+.TP
+.L mtime
+The string representation of
+.LR stat.st_mtime .
+.TP
+.L nlink
+.LR stat.st_nlink .
+.TP
+.L size
+.LR stat.st_size .
+.TP
+.L name
+The file path name sans directory.
+.TP
+.L uid
+The string representation of
+.LR stat.st_uid .
+.PP
+The
+.L type
+field specifies the type of the data at
+.LR offset .
+Integral types may be prefixed by
+.L le
+or
+.L be
+for specifying exact little-endian or big-endian representation,
+but the internal algorithm automatically loops through the
+standard representations to find integral matches,
+so representation prefixes are rarely used.
+However, this looping may cause some magic entry conflicts; use the
+.L le
+or
+.L be
+prefix in these cases.
+Only one representation is used for all the records in an entry.
+Valid types are:
+.TP
+.L byte
+A 1 byte integer.
+.TP
+.L short
+A 2 byte integer.
+.TP
+.L long
+A 4 byte integer.
+.TP
+.L quad
+An 8 byte integer.
+Tests on this type may fail is the local compiler does not support
+an 8 byte integral type and the corresponding value overflows 4 bytes.
+.TP
+.L date
+The data at
+.L offset
+is interpreted as a 4 byte seconds-since-the-epoch date and
+converted to a string.
+.TP
+.L edit
+The
+.L expression
+field is an
+.IR ed (1)
+style substitution expression
+\fIdel old del new del \fP [ \fI flags \fP ]
+where the substituted value is made available to the
+.L description
+field
+.L %s
+format.
+In addition to the
+.I flags
+supported by
+.IR ed (3)
+are
+.L l
+that converts the substituted value to lower case and
+.L u
+that converts the substituted value to upper case.
+If
+.I old
+does not match the string data at
+.L offset
+then the entry record fails.
+.TP
+.L match
+.L expression
+field is a
+.IR strmatch (3)
+pattern that is matched against the string data at
+.LR offset .
+.TP
+.L string
+The
+.L expression
+field is a string that is compared with the string data at
+.LR offset .
+.PP
+The optional
+.L mask
+field takes the form
+.LI & number
+where
+.I number
+is
+.I anded
+with the integral value at
+.L offset
+before the
+.L expression
+is applied.
+.PP
+The contents of the expression field depends on the
+.LR type .
+String type expression are described in the
+.L type
+field entries above.
+.L *
+means any value and applies to all types.
+Integral
+.L type
+expression take the form [\fIoperator\fP] \fIoperand\P where
+.I operand
+is compared with the data value at
+.L offset
+using
+.IR operator .
+.I operator
+may be one of
+.LR < .
+.LR <= ,
+.LR == ,
+.LR >=
+or
+.LR > .
+.I operator
+defaults to
+.L ==
+if omitted.
+.I operand
+may be an integral constant or one of the following builtin function calls:
+.TP
+.L magic()
+A recursive call to the magic algorithm starting with the data at
+.LR offset .
+.TP
+\f5loop(\fIfunction\fP,\fIoffset\fP,\fIincrement\fP)\fR
+Call
+.I function
+starting at
+.I offset
+and increment
+.I offset
+by
+.I increment
+after each iteration.
+Iteration continues until the description text does not change.
+.PP
+The
+.L description
+field is the most important because it is this field that is presented
+to the outside world.
+When constructing description
+fields one must be very careful to follow the style layed out in the
+magic file, lest yet another layer of inconsistency creep into the system.
+The description for each matching record in an entry are concatenated
+to form the complete magic type.
+If the previous matching description in the current entry does not end with
+.I space
+and the current description is not empty and does not start with
+.I comma ,
+.I dot
+or
+.I backspace
+then a
+.I space
+is placed between the descriptions
+(most optional descriptions start with
+.IR comma .)
+The data value at
+.L offset
+can be referenced in the description using
+.L %s
+for the string types and
+.L %ld
+or
+.L %lu
+for the integral types.
+.PP
+The
+.L mimetype
+field specifies the MIME type, usually in the form
+.IR a / b .
+.SH FILES
+.L ../lib/file/magic
+located on
+.L $PATH
+.SH EXAMPLES
+.EX
+0 long 0x020c0108 hp s200 executable, pure
+o{
++36 long >0 , not stripped
++4 short >0 , version %ld
+}
+
+0 long 0x020c0107 hp s200 executable
+o()
+
+0 long 0x020c010b hp s200 executable, demand-load
+o()
+.EE
+The function
+.LR o() ,
+shared by 3 entries,
+determines if the executable is stripped and also extracts the version number.
+.EX
+0 long 0407 bsd 386 executable
+&mode long &0111!=0
++16 long >0 , not stripped
+.EE
+This entry requires that the file also has execute permission.
+.SH "SEE ALSO"
+file(1), mime(4), tw(1), modecanon(3)
diff --git a/src/lib/libast/man/mem.3 b/src/lib/libast/man/mem.3
new file mode 100644
index 0000000..70da0db
--- /dev/null
+++ b/src/lib/libast/man/mem.3
@@ -0,0 +1,98 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH MEM 3
+.SH NAME
+mem \- fixed string routines
+.SH SYNOPSIS
+.EX
+#include <ast.h>
+
+void mematoe(void* \fIout\fP, const void* \fIin\fP, size_t \fIn\fP);
+void* memdup(const void* \fIbuf\fP, size_t \fIn\fP)
+void memetoa(void* \fIout\fP, const void* \fIin\fP, size_t \fIn\fP);
+void* memzero(void* \fIbuf\fP, size_t \fIn\fP);
+.EE
+.SH DESCRIPTION
+.L mematoe
+converts
+.I n
+ASCII characters in
+.I in
+to EBCDIC characters in
+.IR out .
+.I in
+and
+.I out
+may be the same.
+.PP
+.L memdup
+copies the
+.I n
+byte buffer
+.I buf
+to a new location provided by
+.IR malloc (3)
+and returns a pointer to the new copy.
+0 is returned if
+.IR malloc (3)
+fails.
+.PP
+.L memetoa
+converts
+.I n
+EBCDIC characters in
+.I in
+to ASCII characters in
+.IR out .
+.I in
+and
+.I out
+may be the same.
+.PP
+.L memzero
+sets the first
+.I n
+bytes in
+.I buf
+to
+.IR 0 .
+.SH "SEE ALSO"
+Proposed Bell Laboratories ASCII/EBCDIC standard, April 16, 1979.
+.br
+str(3), vmalloc(3)
diff --git a/src/lib/libast/man/mime.3 b/src/lib/libast/man/mime.3
new file mode 100644
index 0000000..f540b2e
--- /dev/null
+++ b/src/lib/libast/man/mime.3
@@ -0,0 +1,117 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH MIME 3
+.SH NAME
+mime \- mime/mailcap interface
+.SH SYNOPSIS
+.EX
+#include <mime.h>
+
+Mime_t
+{
+ unsigned long flags;
+};
+
+Mime_t* mimeopen(unsigned long \fIflags\fP);
+void mimeclose(Mime_t* \fImime\fP);
+
+int mimeload(Mime_t* \fImime\fP, const char* \fIpath\fP, unsigned long \fIflags\fP);
+int mimelist(Mime_t* \fImime\fP, Sfio_t* \fIsp\fP, const char* \fIpattern\fP);
+
+char* mimeview(Mime_t* \fImime\fP, const char* \fIview\fP, const char* \fIname\fP, const char* \fItype\fP, const char* \fIopts\fP);
+int mimeset(Mime_t* \fImime\fP, char* \fIline\fP, unsigned long \fIflags\fP);
+.EE
+.SH DESCRIPTION
+These routines provide an interface to the MIME type database.
+.L mimeopen
+returns a mime session handle that is passed to all of the other routines.
+The
+.I flags
+argument is currently unused.
+.PP
+.L mimeclose
+closes the mime session.
+.PP
+.L mimeload
+loads the mime file named by
+.I path
+into the mime session.
+.I flags
+may be one of:
+.TP
+.L MIME_LIST
+The
+.I path
+argument is a
+.B :
+separated list of pathnames, each of which is loaded.
+Non-existent files are ignored
+.L MIME_LIST
+set.
+.TP
+.L MIME_REPLACE
+Replace existing entries by new entries with the same type.
+Otherwise original entries take precedence.
+.PP
+More than one mime file can be loaded into a session;
+the files are searched in load order.
+If
+.I path
+is
+.L 0
+then the default mime file is loaded.
+.PP
+.L mimelist
+lists the mime file contents on the
+.IR sfio (3)
+stream
+.IR sp .
+This is used for debugging mime entries.
+.PP
+.L mimetype
+returns the type string for
+.IR path .
+.L mimetype
+always returns a non-null string.
+If errors are encounterd on
+.I path
+then the return value will be
+.LR "error" .
+.SH "SEE ALSO"
+file(1), mime(4)
diff --git a/src/lib/libast/man/modecanon.3 b/src/lib/libast/man/modecanon.3
new file mode 100644
index 0000000..4a5d128
--- /dev/null
+++ b/src/lib/libast/man/modecanon.3
@@ -0,0 +1,104 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH MODECANON 3
+.SH NAME
+modecanon \- canonical file mode representation
+.SH SYNOPSIS
+#include <modex.h>
+
+int modei(int \fIexternal\fP);
+int modex(int \fIinternal\fP);
+.EE
+.SH DESCRIPTION
+POSIX threw out the file type bit macros and replaced them with
+function-like macros that test file type.
+This is bad in many ways, the worst of which is that it provides
+no way for a user program to synthesize file types in the mode bits.
+.IR pax (1),
+.IR tar (1)
+and
+.IR cpio (1)
+are examples of user programs that must convert between the internal mode
+representation and a private external representation.
+These routines provide a canonical external representation
+with macros to access and synthesize the bits in the external
+representation.
+.PP
+.L modei
+takes an external mode representation
+.I external
+and returns the equivalent internal representation.
+.PP
+.L modex
+takes an internal mode representation
+.I internal
+and returns the equivalent external representation.
+.PP
+The traditional bit access macro (\f5S_\fP prefix changes to \f5X_\fP) are:
+.L X_IFMT ,
+.L X_IFSOCK ,
+.L X_IFLNK ,
+.L X_IFCTG ,
+.L X_IFREG ,
+.L X_IFBLK ,
+.L X_IFDIR ,
+.L X_IFCHR ,
+.L X_IFIFO ,
+.L X_IPERM ,
+.L X_ISUID ,
+.L X_ISGID ,
+.L X_ISVTX ,
+.L X_IRUSR ,
+.L X_IWUSR ,
+.L X_IXUSR ,
+.L X_IRGRP ,
+.L X_IWGRP ,
+.L X_IXGRP ,
+.L X_IROTH ,
+.L X_IWOTH ,
+.L X_IXOTH ,
+.L X_IRWXU ,
+.L X_IRWXG
+and
+.L X_IRWXO .
+.LI X_ITYPE( mode )
+returns the type bits for
+.IR mode .
+.SH "SEE ALSO"
+pax(1), stat(2)
diff --git a/src/lib/libast/man/optget.3 b/src/lib/libast/man/optget.3
new file mode 100644
index 0000000..90afcb8
--- /dev/null
+++ b/src/lib/libast/man/optget.3
@@ -0,0 +1,68 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH OPTGET 3
+.SH NAME
+optget \- option parse assist
+.SH SYNOPSIS
+.EX
+#include <option.h>
+
+Opt_t
+{
+};
+
+Optdisc_t
+{
+ unsigned long version;
+ unsigned long flags;
+ char* catalog;
+ Optinfo_f infof;
+};
+
+Opt_t opt_info;
+
+void optinit(Optdisc_t* \fIdisc\fP, Error_f \fIerrorf\fP);
+int optget(char** \fIargv\fP, const char* \fIusage\fP);
+int optstr(const char* \fIstring\fP, const char* \fIusage\fP);
+int optjoin(char** \fIargv\fP, ... [int (*\fIoptfun\fP)(char** \fIargv\fP, int \fIlast\fP)]);
+char* optusage(const char* \fIopts\fP);
+int optesc(Sfio_t* \fIsp\fP, const char* \fIstring\fP, int \fIflags\fP);
+.EE
+.SH DESCRIPTION
+.SH "SEE ALSO"
diff --git a/src/lib/libast/man/path.3 b/src/lib/libast/man/path.3
new file mode 100644
index 0000000..8721888
--- /dev/null
+++ b/src/lib/libast/man/path.3
@@ -0,0 +1,391 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH PATH 3
+.SH NAME
+path \- file path routines
+.SH SYNOPSIS
+.EX
+#include <ast.h>
+
+char* pathaccess(char* \fIpath\fP, const char* \fIdirs\fP, const char* \fIa\fP, const char* \fIb\fP, int \fImode\fP);
+char* pathbin(void);
+char* pathcanon(char* \fIpath\fP, int \fIflags\fP);
+char* pathcat(char* \fIpath\fP, const char* \fIdirs\fP, int \fIsep\fP, const char* \fIa\fP, const char* \fIb\fP);
+char* pathcd(char* \fIpath\fP, const char* \fIhome\fP);
+int pathcheck(const char* \fIpackage\fP, const char* \fItool\fP, Pathcheck_t* \fIpc\fP);
+int pathgetlink(const char* \fIname\fP, char* \fIbuf\fP, int \fIsiz\fP);
+char* pathkey(char* \fIkey\fP, char* \fIattr\fP, const char* \fIlang\fP, const char* \fIpath\fP);
+char* pathnext(char* \fIpath\fP, char* \fIextra\fP, long* \fIvisits\fP);
+char* pathpath(char* \fIpath\fP, const char* \fIp\fP, const char* \fIa\fP, int \fImode\fP);
+char* pathprobe(char* \fIpath\fP, char* \fIattr\fP, const char* \fIlang\fP, const char* \fItool\fP, const char* \fIproc\fP, int \fIop\fP);
+char* pathrepl(char* \fIpath\fP, const char* \fImatch\fP, const char* \fIreplace\fP);
+int pathsetlink(const char* \fItext\fP, char* \fIname\fP);
+char* pathshell(void);
+int pathstat(const char* \fIpath\fP, struct stat* \fIst\fP);
+char* pathtemp(char* \fIpath\fP, const char* \fIdir\fP, const char* \fIpfx\fP);
+.EE
+.SH DESCRIPTION
+These routines operate on file path names.
+Path buffers are assumed to be of size
+.LR PATH_MAX .
+.L <ast.h>
+always defines
+.LR PATH_MAX ,
+even if it indeterminant on the local system.
+Yes, this was probably a bad choice, but it was made about 10 years ago.
+We will probably move to a <stk.h> based implementation.
+.PP
+.L pathaccess
+constructs a path in
+.L path
+to the file
+.L a/b
+with access
+.L mode
+using the
+.L :
+separated directories in
+.IR dirs .
+Both
+.I a
+and
+.I b
+may be
+.LR 0 .
+.L mode
+is the inclusive-or of:
+.TP
+.L F_OK
+File exists.
+.TP
+.L R_OK
+Read permission on file.
+.TP
+.L W_OK
+Write permission on file.
+.TP
+.L X_OK
+Execute permission on file.
+.TP
+.L PATH_REGULAR
+A regular file.
+.TP
+.L PATH_ABSOLUTE
+Generated path name is rooted at
+.LR / .
+.I path
+is returned, 0 on error.
+.PP
+.L pathbin
+returns a pointer to the
+.L :
+separated list of directories to search for executable commands.
+The
+.L PATH
+environment variable is first consulted.
+If not defined then
+.L confstr(_CS_PATH,...)
+is used.
+A valid string is always returned.
+.PP
+.L pathcanon
+canonicalizes the path
+.I path
+in place.
+A pointer to the trailing 0 in the canonicalized path is returned.
+A canonical path has:
+redundant
+.L .
+and
+.L /
+removed;
+.L ..
+moved to the front;
+.L /..
+preserved for super root hacks;
+.L ...
+resolved if
+.IR fs3d (3)
+is enabled.
+.I flags is the inclusive-or of:
+.TP
+.L PATH_DOTDOT
+Each
+.L ..
+is checked for access.
+.TP
+.L PATH_EXISTS
+Path must exist at each component.
+.TP
+.L PATH_PHYSICAL
+Symbolic links are resolved at each component.
+.PP
+0 is returned on error.
+If an error occurs and either of
+.L PATH_DOTDOT
+or
+.L PATH_EXISTS
+is set then
+.I path
+will contain the components following the failure point.
+.PP
+.L pathcat
+concatenates the first
+.I sep
+separated path component in
+.I dirs
+with the path components
+.I a
+and
+.I b
+into
+.LR path .
+The path is constructed in
+.I path
+by separating each path component with
+.IR / .
+Both
+.I a
+and
+.I b
+may be
+.LR 0 .
+A pointer to the next
+.I sep
+separated component in
+.I dirs
+is returned,
+.L 0
+when there are no more components.
+.L pathcat
+is used by
+.LR pathaccess .
+.PP
+.L pathcd
+sets the current working directory to
+.I path
+via
+.IR chdir (2).
+If
+.I path
+is longer than
+.L PATH_MAX
+then it is split up into a sequence of relative paths and
+.I chdir
+is called on each of these.
+For any given system, if you got to a directory, then
+.L pathcd
+can get you back, modulo permission and link changes.
+.PP
+.L pathcheck
+is a stub for license libraries.
+See
+.IR license (3).
+.PP
+.L pathgetlink
+returns the 0-terminated symbolic link text for
+.I path
+in the buffer
+.I bu
+of size
+.IR siz .
+The link text length is returned on success, \-1 on error.
+Weird
+.I universe (1)
+interactions with dynamic symbolic links are handled
+by converting non-standard dynamic link text to
+.LI .../$( UNIVERSE )/...
+.L pathsetsymlink
+converts in the other direction.
+.PP
+.L pathkey
+generates in
+.I key
+a 14 character lookup key (plus terminating 0) for the language
+.I lang
+processor in
+.IR path .
+A poihter to the key is returned, 0 on error.
+If
+.I "key == 0"
+then space is allocated via
+.IR malloc (3).
+Key specific attribute
+.I name=value
+pairs are copied into
+.I attr
+if
+.IR "attr != 0" .
+.PP
+.L pathpath
+constructs in
+.I path
+a path to
+.I p
+with
+.IR access (2)
+mode
+.I mode
+using the directories from
+.LR pathbin() .
+If \fIa != 0\fP then
+.IR a ,
+.IR argv [0]
+(if available via
+.IR optget (3)),
+and the
+.L _
+environment variable (set by
+.IR ksh (1) )
+are used for related root searching.
+If
+.I p
+also contains a
+.L /
+then
+.I ../p
+is searched for.
+.PP
+.L pathprobe
+generates in
+.I path
+the full path name of the
+.I tool
+specific
+.IR probe (1)
+information file for the
+.I lang
+langauge processor
+.IR proc .
+If
+.I "path == 0"
+then space is allocated via
+.IR malloc (3).
+Probe attribute
+.I name=value
+pairs are copied into
+.I attr
+if
+.IR "attr != 0" .
+.I op
+may be one of:
+.TP
+.B \-1
+return the path name with no access checks or generation
+.TP
+.B 0
+message emitted information must be generated via
+.IR probe (1)
+.TP
+.B 1
+no message emitted information must be probed via
+.IR probe (1)
+.PP
+0 is returned if the information does not exist and cannot be generated.
+.PP
+.L pathrepl
+does an in-place replacement of the first occurrence of
+.I /match/
+with
+.I /replace/
+in
+.IR path .
+.PP
+.L pathsetlink
+creates a symbolic link
+.I text
+in the path
+.IR name .
+See
+.L pathgetlink
+above for weird
+.IR universe (1)
+interactions hidden by this routine.
+.PP
+.L pathshell
+returns a pointer to the pathname for the shell for the current process.
+The
+.L SHELL
+environment variable is first consulted, but is rejected under suspicious
+ownership/setuid conditions of if it seems to point to
+.IR csh (1) ;
+otherwise
+.L confstr(_CS_SHELL,...)
+is used.
+A valid string is always returned.
+.PP
+.L pathstat
+first tries
+.LI stat( path,st )
+and if that fails it tries
+.LI lstat( path,st ).
+The
+.L stat
+or
+.L lstat
+return value is returned.
+.PP
+.L pathtemp
+generates in
+.I path
+a temporary file path name of the form
+.I dir/pfx<pid>.<suf>
+where the length of
+.IR pfx ,
+if !=0, is limited to 5, the length of
+.I <pid>
+(the base 64 representation of the current process id)
+is limited to 3, and
+.I <suf>
+(an internally generated suffix that avoid file confilicts)
+is limited to 3.
+The generated path name conforms to the classic UNIX 14 char and the DOS
+.LR 8.3
+limitations.
+Both
+.I dir
+and
+.I pfx
+may be
+.LR 0 .
+.IR access (2)
+is used to avoid file conflicts but the generated path name is not created,
+so you could lose in a race.
+.SH "SEE ALSO"
+3d(1), access(2), confstr(3), fs3d(3), lstat(2), stat(2)
diff --git a/src/lib/libast/man/preroot.3 b/src/lib/libast/man/preroot.3
new file mode 100644
index 0000000..025fc22
--- /dev/null
+++ b/src/lib/libast/man/preroot.3
@@ -0,0 +1,151 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH PREROOT 3
+.SH NAME
+preroot \- preroot support
+.SH SYNOPSIS
+.EX
+#include <preroot.h>
+
+char* getpreroot(char* \fIpath\fP, char* \fIcmd\fP);
+int ispreroot(char* \fIdir\fP);
+int realopen(char* \fIpath\fP, int \fImode\fP, int \fIperm\fP);
+void setpreroot(char** \fIargv\fP, char* \fIdir\fP);
+.EE
+.SH DESCRIPTION
+The
+.I preroot
+routines manipulate the process preroot.
+.I preroot
+is a kernel supported per-process two level viewpath.
+All pathnames rooted at
+.L /
+are first searched for in the process preroot directory
+and then in the system root directory.
+Setting the process preroot is a priveleged operation controlled by the
+.IR /etc/preroot (1)
+command.
+.PP
+.L <preroot.h>
+defines the symbol
+.B FS_PREROOT
+for those systems that support preroot.
+The following routines are valid only when
+.B FS_PREROOT
+is defined:
+.TP
+.L getpreroot
+returns a pointer to the absolute pathname of the preroot directory
+for the executable
+.IR cmd .
+The result is placed in
+.IR path .
+If
+.I path
+is
+.B 0
+then
+.IR malloc (3)
+is used to allocate the pathname space.
+.B 0
+is returned if
+.I cmd
+has no preroot or if an error was encountered.
+In this case
+.I errno
+is set to indicate the error.
+.TP
+.L ispreroot
+Non-zero is returned if
+.I dir
+is the current process preroot.
+If
+.I dir
+is
+.B 0
+then non-zero is returned if the current process has a preroot.
+.TP
+.L realopen
+temporarily disables the process preroot and does an
+.IR open (3)
+relative to the system root directory.
+The return value from
+.I open
+is returned.
+If there is no preroot then
+.I realopen
+is equivalent to
+.IR open .
+.TP
+.L setpreroot
+calls
+.IR execvp (3)
+as
+.L "execvp(a\fIrgv\fP[0],\fIargv\fP)"
+with the process preroot set to
+.IR dir .
+.I argv
+must be a
+.BR 0 -terminated
+argument array.
+If
+.I argv
+is
+.B 0
+then the value of
+.I opt_argv
+from
+.IR optget (3)
+is used.
+.L setpreroot
+returns immediately if
+.I dir
+is already the process preroot.
+.SH "SEE ALSO"
+/etc/preroot(1)
+.SH BUGS
+Preroot semantics should be preserved when reading directories.
+The
+.I ast
+.IR directory (3)
+routines do this.
+.IR 3d (1)
+viewpathing does
+.I preroot
+the right way.
diff --git a/src/lib/libast/man/proc.3 b/src/lib/libast/man/proc.3
new file mode 100644
index 0000000..64c1a6e
--- /dev/null
+++ b/src/lib/libast/man/proc.3
@@ -0,0 +1,319 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH PROC 3
+.SH NAME
+proc \- process control routines
+.SH SYNOPSIS
+.EX
+#include <proc.h>
+
+Proc_t* procopen(const char* \fIcommand\fP, char** \fIargv\fP, char** \fIenvv\fP, long* \fIopv\fP, long \fIflags\fP);
+int procfree(Proc_t* \fIproc\fP);
+int procclose(Proc_t* \fIproc\fP);
+int procrun(const char* \fIcommand\fP, char** \fIargv\fP);
+.EE
+.SH DESCRIPTION
+These routines provide a portable interface to process creation and execution.
+They work on systems with
+.IR fork (2)
+and
+.IR exec (2)
+as well as on systems with only
+.IR spawnve (2)
+or
+.IR spanwveg (3).
+.PP
+.L procopen
+runs
+.I command
+with arguments
+.IR argv ,
+environment modifications in
+.IR envv ,
+file descriptor, signal and process group operations in
+.I opv
+and flags in
+.IR flags .
+.PP
+.I command
+is searched for using the
+.L PATH
+environment variable from the calling environment.
+If
+.I command
+is
+.L 0
+then the current shell is used (see
+.IR pathshell (3)).
+If
+.I envv
+is not
+.L 0
+then it is a
+.L 0
+terminated vector of
+\fIname\fP[=\fIvalue\fP]
+strings that are added to the
+.I command
+environment using
+.IR setenviron (3).
+If
+.I name
+appears in the parent environment then its value is replaced with the new
+.IR value .
+If
+.RI = value
+is omitted then
+.I name
+is removed from the child environment.
+The
+.L _
+environment variable is set to contain the pathname for
+.I command
+and will appear at the top of the child environment.
+.PP
+If
+.I opv
+is not
+.L 0
+then it is a 0 terminaled vector of operations to perform.
+In the following
+.I context
+is a combination of
+.L PROC_FD_CHILD
+and
+.L PROC_FD_PARENT
+for the child and parent process context respectively.
+Valid operations are:
+.TP
+\f5PROC_FD_CLOSE(\fIfd\fP,\fIcontext\fP)\fR
+The file descriptor
+.I fd
+is closed in
+.IR context .
+.TP
+\f5PROC_FD_DUP(\fIfrom\fP,\fIto\fP,\fIcontext\fP)\fR
+The file descriptor
+.I from
+is
+.IR dup (2)'d
+into the file descriptor
+.I to
+in
+.IR context .
+.TP
+\f5PROC_SIG_DFL(\fIsig\fP)\fR
+The signal handler for
+.I sig
+is set to
+.L SIG_DFL
+in the child context.
+.TP
+\f5PROC_SIG_IGN(\fIsig\fP)\fR
+The signal handler for
+.I sig
+is set to
+.L SIG_IGN
+in the child context.
+.TP
+\f5PROC_SYS_PGRP(\fIpgid\fP)\fR
+The child process group is set to
+.IR pgid .
+.I pgid
+may have the following values:
+.TP
+.L <0
+The child process becomes a session leader.
+.TP
+.L 0
+The child process is in the parent process group.
+.TP
+.L 1
+The child process becomes a process group leader.
+.TP
+.L >1
+The child process joins the process group
+.IR pgid .
+.TP
+\f5PROC_SYS_UMASK(\fImask\fP)\fR
+The child process group file creation mask is set to
+.IR mask .
+.PP
+.I flags
+is the inclusive-or of the following:
+.TP
+.L PROC_ARGMOD
+.I "argv[-1]"
+and
+.I "argv[0]"
+may be modified.
+This is an optimization that avoids an environment vector
+.I realloc(3)
+when
+.I command
+is a shell script.
+.TP
+.L PROC_BACKGROUND
+Standard shell
+.L &
+setup is done for the child process.
+.TP
+.L PROC_CLEANUP
+Parent process redirection file discriptors are closed on error.
+.TP
+.L PROC_DAEMON
+Standard daemon setup is done for the child process.
+.TP
+.L PROC_ENVCLEAR
+The child environment is cleared before
+.I envv
+is added.
+.TP
+.L PROC_GID
+The child effective group id is set to the real group id.
+.TP
+.L PROC_IGNORE
+Parent pipe errors are ignored.
+.TP
+.L PROC_OVERLAY
+The current process is overlayed by
+.I command
+if possible
+(i.e., the
+.IR fork (2)
+call is omitted).
+.TP
+.L PROC_PARANOID
+Paranoid:
+.I command
+is searched using the default standard
+.LR PATH ;
+the child environment variable
+.L PATH
+is set to the default standard;
+the
+.L PROC_GID
+and
+.L PROC_UID
+modes are set;
+only
+.L /bin/sh
+is used to execute
+.I command
+if it is a shell script.
+.TP
+.L PROC_PRIVELEGED
+If the effective user id is
+.L 0
+then the child real user id is set to
+.L 0
+and the child real group id is set to the effective group id.
+.TP
+.L PROC_READ
+.I proc.rfd
+is connected to
+.IR command 's
+standard output.
+.TP
+.L PROC_SESSION
+The child process becomes a session group leader.
+(Equivalent to the
+.I opv
+entry
+.LR PROC_SYS_PGRP(-1) .)
+.TP
+.L PROC_UID
+The child effective user id is set to the real user id.
+.TP
+.L PROC_WRITE
+.I proc.wfd
+is connected to
+.IR commands 's
+standard input.
+.PP
+The return value is a pointer to a structure with the following members:
+.TP
+.L "pid_t \fIpid\fP"
+The child process id.
+.TP
+.L "pid_t \fIpgrp\fP"
+The child process group.
+.TP
+.L "int \fIrfd\fP"
+A read file descriptor connected to
+.IR command 's
+standard output.
+.TP
+.L "int \fIwfd\fP"
+A write file descriptor connected to
+.IR command 's
+standard input.
+.PP
+If an error occurs then
+.L 0
+is returned.
+.PP
+.L procclose
+waits for the process
+.I proc
+to complete and then closes the command stream
+.IR proc .
+The command exit status is returned.
+.L -1
+is returned if the child portion of
+.L procopen
+failed.
+.PP
+.L procfree
+frees the process stream without waiting for
+.I command
+to complete.
+Presumably some other mechanism will be used to wait for
+.IR proc.pid .
+.PP
+.L procrun
+combines
+.L procopen
+and
+.L procclose
+with the flags
+.L PROC_GID|PROC_UID
+and returns the command exit status.
+.SH "SEE ALSO"
+popen(3), sfpopen(3), spawnveg(3), system(3)
diff --git a/src/lib/libast/man/re.3 b/src/lib/libast/man/re.3
new file mode 100644
index 0000000..2e1010e
--- /dev/null
+++ b/src/lib/libast/man/re.3
@@ -0,0 +1,214 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH RE 3
+.SH NAME
+recomp, reexec, ressub, refree, reerror \(mi regular expression library
+.SH SYNOPSIS
+.EX
+#include <re.h>
+
+Re_program_t* recomp(char* \fIpattern\fP, int \fIflags\fP);
+int reexec(Re_program_t* \fIre\fP, char* \fIsource\fP);
+void ressub(Re_program_t* \fIre\fP, Sfio_t* \fIsp\fP, char* \fIold\fP, char* \fInew\fP, int \fIflags\fP);
+void reerror(char* \fImessage\fP);
+void refree(Re_program_t* \fIre\fP);
+.EE
+.SH DESCRIPTION
+.L recomp
+compiles a regular expression in
+.I pattern
+and returns a pointer to the compiled regular expression.
+The space is allocated by
+.IR malloc (3)
+and may be released by
+.LR refree .
+Regular expressions are as in
+.IR egrep (1)
+except that newlines are treated as ordinary
+characters and
+.L $
+matches the end of a null-terminated string.
+.I flags
+may be
+.L RE_EDSTYLE
+which specifies
+.IR ed (1)
+style special characters,
+.LR \e( ,
+.LR \e) ,
+.LR \e? ,
+.L \e+
+and
+.L \e|
+for the
+.IR egrep (1)
+.LR ( ,
+.LR ) ,
+.LR ? ,
+.L +
+and
+.LR | ,
+respectively.
+.PP
+.L reexec
+matches the null-terminated
+.I source
+string against the compiled regular expression
+.I re
+from a previous call to
+.LR recomp .
+If it matches,
+.L reexec
+returns a non-zero value.
+If
+.I flags
+is
+.L RE_MATCH
+then the array
+.I re\->match
+is filled with character pointers to the substrings of
+.I source
+that correspond to the
+parenthesized subexpressions of
+.IR pattern :
+.I re\->match[i].sp
+points to the beginning and
+.I re\->match[i].ep
+points just beyond
+the end of substring
+.IR i .
+(Subexpression
+.I i
+begins at the
+.IR i th
+matched left parenthesis, counting from 1.)
+Pointers in
+.I re\->match[0]
+pick out the substring that corresponds to
+the entire regular expression.
+Unused elements of
+.I re\->match
+are filled with zeros.
+Matches involving
+.LR * ,
+.LR + ,
+and
+.L ?
+are extended as far as possible.
+A maximum of 9 subexpressions will be matched.
+The structure of elements of
+.I re\->match
+is:
+.nf
+.ta 8n
+ typedef struct
+ {
+ char* sp;
+ char* ep;
+ } rematch;
+.fi
+.LP
+.L ressub
+places in the
+.IR sfio (3)
+stream
+.I sp
+a substitution instance of
+.I old
+to
+.I new
+in
+.I source
+in the context of the last
+.L reexec
+performed on
+.IR re\->match .
+Each instance of
+.LI \e n ,
+where
+.I n
+is a digit, is replaced by the
+string delimited by
+.LI re\->match[ n ].sp
+and
+.LI re\->match[ n ].ep .
+Each instance of
+.L &
+is replaced by the string delimited by
+.I re\->match[0].sp
+and
+.IR re\->match[0].ep .
+If
+.L RE_ALL
+is set in
+.I flags
+then all occurrences of
+.I old
+are replaced by
+.IR new .
+If
+.L RE_LOWER
+.RL [ RE_UPPER ]
+is set in
+.I flags
+then
+.I old
+is converted to lower [upper] case.
+.LP
+.L reerror,
+called whenever an error is detected in
+.L recomp,
+.L reexec,
+or
+.L ressub,
+writes the string
+.I msg
+on the standard error file and exits.
+.L reerror
+may be replaced to perform
+special error processing.
+.SH DIAGNOSTICS
+.L recomp
+returns 0 for an invalid expression or other failure.
+.L reexec
+returns 1 if
+.I source
+is accepted, 0 otherwise.
+.SH "SEE ALSO"
+ed(1), grep(1), expr(1)
diff --git a/src/lib/libast/man/regex.3 b/src/lib/libast/man/regex.3
new file mode 100644
index 0000000..7c15d21
--- /dev/null
+++ b/src/lib/libast/man/regex.3
@@ -0,0 +1,163 @@
+.fp 5 B
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH REGEX 3
+.SH NAME
+regex \- regular expression interface
+.SH SYNOPSIS
+.EX
+#include <regex.h>
+
+int regcomp(regex_t* \fIre\fP, const char* \fIregex\fP, int \fIcflags\fP);
+int regexec(const regex_t* \fIre\fP, const char* \fIstring\fP, size_t \fInmatch\fP, regmatch_t \fIpmatch\fP[], int \fIeflags\fP);
+size_t regerror(int \fIcode\fP, const regex_t* \fIre\fP, char* \fIerrbuf\fP, size_t \fIerrbuf_size\fP);
+void regfree(regex_t* \fIre\fP);
+
+regclass_t regclass(const char* \fIstr\fP, char** \fIend\fP);
+int regaddclass(const char* \fIname\fP, regclass_t \fIclassf\fP);
+int regcollate(const char* \fIstr\fP, char** \fIend\fP, char* \fIbuf\fP, int \fIsize\fP);
+
+int regcomb(regex_t* \fIre_1\fP, regex_t* \fIre_2\fP);
+size_t regdecomp(regex_t* \fIre\fP, regflags_t \fIflags\fP, char* \fIbuf\fP, size_t \fIsize\fP);
+int regdup(regex_t* \fIre_old\fP, regex_t* \fIre_new\fP);
+regstat_t* regstat(const regex_t* \fIre\fP);
+
+regex_t* regcache(const char* \fIpattern\fP, regflags_t \fIflags\fP, int* \fIpcode\fP);
+
+int regncomp(regex_t* \fIre\fP, const char* \fIpattern\fP, size_t \fIsize\fP, regflags_t \fIflags\fP);
+int regnexec(const regex_t* \fIre\fP, const char* \fIsubject\fP, size_t \fIsize\fP, size_t \fInmatch\fP, regmatch_t* \fImatch\fP, regflags_t \fIflags\fP);
+int regrecord(const regex_t* \fIre\fP);
+int regrexec(const regex_t* \fIre\fP, const char* \fIbuf\fP, size_t \fIsize\fP, size_t \fInmatch\fP, regmatch_t* \fImatch\fP, regflags_t \fIflags\fP, int \fIsep\fP, void* \fIhandle\fP, regrecord_t \fIrecordf\fP);
+void regfatal(regex_t* \fIre\fP, int \fIlevel\fP, int \fIcode\fP);
+void regfatalpat(regex_t* \fIre\fP, int \fIlevel\fP, int \fIcode\fP, const char* \fIpattern\fP);
+
+int regsubcomp(regex_t* \fIre\fP, const char* \fIstr\fP, const regflags_t* \fImap\fP, int \fIminmatch\fP, regflags_t \fIflags\fP);
+int regsubexec(const regex_t* \fIre\fP, const char* \fIsubject\fP, size_t \fInmatch\fP, regmatch_t* match);
+int regsubflags(regex_t* \fIre\fP, const char* \fIstr\fP, char** \fIend\fP, int \fIdelim\fP, const regflags_t* \fImap\fP, int* \fIpm\fP, regflags_t* \fIpf\fP);
+void regsubfree(regex_t* \fIre\fP);
+.EE
+
+.SH DESCRIPTION
+.LR regcomp() ,
+.LR regexec() ,
+.LR regerror() ,
+and
+.L regfree()
+are the POSIX regular expression functions.
+The remaining functions are
+.B ast
+extensions.
+.B ast
+also provides
+.I flags
+extensions to the
+.LR regcomp() ,
+.LR regexec()
+functions and
+.I code
+extensions to the
+.L regerror()
+function.
+
+.PP
+.L regcache()
+maintains a cache of compiled regular expressions for patterns of size
+255 bytes or less.
+The initial cache size is 8.
+.L pattern
+and
+.L flags
+are passed to
+.L regcomp()
+with an
+.L re
+pointer maintained by
+.LR regcache() .
+.LR pcode ,
+if not 0, points to the return value of the
+.L regcomp()
+call.
+If the
+.L regcomp()
+call fails,
+.L regcache()
+returns 0 and
+.L pcode
+will point to the non-zero error code.
+Do not call
+.L regfree()
+on the
+.L re
+returned by
+.LR regcache() .
+Both
+.L pattern
+and
+.L flags
+are used to match entries in the cache.
+When the cache is full the least recently used
+.L re
+is freed (via
+.LR regfree() )
+to make space for the new pattern.
+Any
+.L re
+previously returned by
+.L regcache()
+may be freed (invalidated) on the next call to
+.LR regcache() .
+If
+.L pattern
+is longer that 255 bytes then it is still passed on to
+.LR regcomp() ,
+but it will not be cached.
+If
+.L pattern
+is 0 then the cache is flushed.
+In addition, if the integer value of
+.L flags
+is greater than the current cache size, the cache size is increased
+to that integer value.
+0 is always returned when
+.L pattern
+is 0;
+.L pcode
+will point to a non-zero value on error.
+
+.SH "SEE ALSO"
+strmatch(3)
diff --git a/src/lib/libast/man/setenviron.3 b/src/lib/libast/man/setenviron.3
new file mode 100644
index 0000000..818f7fc
--- /dev/null
+++ b/src/lib/libast/man/setenviron.3
@@ -0,0 +1,79 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH LIBAST 3
+.SH NAME
+setenviron \- set environment value
+.SH SYNOPSIS
+.EX
+#include <ast.h>
+
+char* setenviron(const char* \fIkey\fP);
+.EE
+.SH DESCRIPTION
+.L setenviron
+controls environment
+.I name=value
+pairs.
+.L setenviron("\fIname=value\fP")
+adds
+.I name
+to the environment and returns a pointer to a
+.IR strdup (3)
+copy of
+.IR name=value .
+.L setenviron("\fIname\fP")
+removes
+.I name
+from the environment and returns the empty string.
+.L setenviron(0)
+reserves a few slots in an internal array and is usually called by
+a parent process that expects many children.
+0 is returned on error.
+.L setenviron
+preserves the
+.IR ksh (1)
+convention of
+.L _
+as the first environment variable name.
+.SH "SEE ALSO"
+env(1), exec(2)
+.SH BUGS
+POSIX will eventually settle on an interface.
+It has already picked a few of the names we did in .2 drafts.
+This is about the third name change for ours.
diff --git a/src/lib/libast/man/sfdisc.3 b/src/lib/libast/man/sfdisc.3
new file mode 100644
index 0000000..f0ce5b0
--- /dev/null
+++ b/src/lib/libast/man/sfdisc.3
@@ -0,0 +1,118 @@
+.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 \f5dcnewXXX()\fP to create
+a discipline of the type \f5XXX\fP and to use \f5dcdelXXX()\fP
+to destroy it.
+A discipline is enable by inserting it into the desired
+stream using the \f5sfdisc()\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, \f5dcnewXXX()\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);"
+\f5dcnewskable()\fP creates a discipline that when inserted
+on the stream \f5f\fP will ensure that \f5f\fP is seekable.
+If \f5f\fP is originally unseekable, data will be shadowed
+in a temporary file stream to allow seekability.
+\f5dcnewskable()\fP returns the discipline on success and \f5NULL\fP on failure.
+
+.Ss " Sfdisc_t* dcnewtee(Sfio_t* tee);"
+.Ss " int dcdeltee(Sfdisc_t* disc);"
+\f5dcnewtee()\fP creates a discipline that
+when inserted into a stream \f5f\fP will duplicate to the stream \f5tee\fP
+any data written to \f5f\fP.
+\f5dcnewtee()\fP returns the discipline on success and \f5NULL\fP on failure.
+
+.Ss " Sfdisc_t* dcnewfilter(char* cmd);"
+.Ss " int dcdelfilter(Sfdisc_t* disc);"
+\f5dcnewfilter()\fP creates a discipline that
+when inserted into a stream \f5f\fP will run the command \f5cmd\fP
+to process any input data before making it available to the application.
+For example, \f5dcnewfilter("uncompress")\fP is an equivalent but slower
+alternative to the lzw discipline below.
+\f5dcnewfilter()\fP returns the discipline on success and \f5NULL\fP on failure.
+
+.Ss " Sfdisc_t* dcnewsubstream(Sfio_t* base, long offset, long extent);"
+.Ss " int dcdelsubstream(Sfdisc_t* disc);"
+\f5dcnewsubstream()\fP creates a discipline that
+reserves a portion of the stream \f5base\fP starting at \f5offset\fP
+with length \f5extent\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 \f5base\fP stream.
+\f5dcnewsubstream()\fP returns the discipline on success and \f5NULL\fP on failure.
+
+.Ss " Sfdisc_t* dcnewlzw(void);
+.Ss " int dcdellzw(Sfdisc_t* disc);"
+\f5dcnewlzw()\fP creates a discipline that when inserted into
+a stream \f5f\fP will run the \fBuncompress\fP algorithm
+on input data from \f5f\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.
+\f5dcnewlzw()\fP returns the discipline on success and \f5NULL\fP on failure.
+
+.Ss " Sfdisc_t* dcnewunion(Sfio_t** list, int n);
+.Ss " int dcdelunion(Sfdisc_t* disc);"
+\f5dcnewunion()\fP creates a discipline that concatenates
+input data from all \f5n\fP streams in \f5list\fP.
+When inserted into a stream \f5f\fP, this discipline will cause
+all input operations on \f5f\fP to come from the merged data stream.
+\f5dcnewunion()\fP returns the discipline on success and \f5NULL\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.
diff --git a/src/lib/libast/man/sfio.3 b/src/lib/libast/man/sfio.3
new file mode 100644
index 0000000..f22d0b7
--- /dev/null
+++ b/src/lib/libast/man/sfio.3
@@ -0,0 +1,2373 @@
+.fp 5 CW
+.TH SFIO 3 "01 June 2008"
+.SH NAME
+\fBsfio\fR \- safe/fast string/file input/output
+.SH SYNOPSIS
+.de Tp
+.fl
+.ne 3
+.TP
+..
+.de Ss
+.fl
+.ne 3
+.SS "\\$1"
+..
+.ta 1.0i 2.0i 3.0i 4.0i 5.0i
+.Ss "LIBRARIES"
+.nf
+.ft 5
+#include <sfio.h>
+
+libsfio.a -lsfio
+libstdio.a -lstdio
+libsfio-mt.a -lsfio-mt
+libstdio-mt.a -lstdio-mt
+.ft 1
+.fi
+.Ss "DATA TYPES"
+.nf
+.ft 5
+Void_t;
+Sfoff_t;
+Sflong_t;
+Sfulong_t;
+Sfdouble_t;
+
+Sfio_t;
+
+Sfdisc_t;
+ssize_t (*Sfread_f)(Sfio_t*, Void_t*, size_t, Sfdisc_t*);
+ssize_t (*Sfwrite_f)(Sfio_t*, const Void_t*, size_t, Sfdisc_t*);
+Sfoff_t (*Sfseek_f)(Sfio_t*, Sfoff_t, int, Sfdisc_t*);
+int (*Sfexcept_f)(Sfio_t*, int, Void_t*, Sfdisc_t*);
+
+Sffmt_t;
+int (*Sffmtext_f)(Sfio_t*, Void_t*, Sffmt_t*);
+int (*Sffmtevent_f)(Sfio_t*, int, Void_t*, Sffmt_t*);
+
+SFIO_VERSION
+.ft 1
+.fi
+.Ss "BIT FLAGS"
+.nf
+.ft 5
+SF_STRING
+SF_READ
+SF_WRITE
+SF_APPENDWR (SF_APPEND)
+SF_LINE
+SF_SHARE
+SF_PUBLIC
+SF_MALLOC
+SF_STATIC
+SF_IOCHECK
+SF_WHOLE
+SF_MTSAFE
+SF_IOINTR
+.ft 1
+.fi
+.Ss "OPENING/CLOSING STREAMS"
+.nf
+.ft 5
+Sfio_t* sfnew(Sfio_t* f, Void_t* buf, size_t size, int fd, int flags);
+Sfio_t* sfopen(Sfio_t* f, const char* string, const char* mode);
+Sfio_t* sfpopen(Sfio_t* f, const char* cmd, const char* mode);
+Sfio_t* sftmp(size_t size);
+int sfclose(Sfio_t* f);
+
+
+.ft 1
+.fi
+.Ss "THREAD SAFETY"
+.nf
+.ft 5
+int sfmutex(Sfio_t* f, int type);
+
+SFMTX_LOCK
+SFMTX_TRYLOCK
+SFMTX_UNLOCK
+SFMTX_CLRLOCK
+.ft 1
+.fi
+.Ss "INPUT/OUTPUT OPERATIONS"
+.nf
+.ft 5
+int sfgetc(Sfio_t* f);
+int sfputc(Sfio_t* f, int c);
+int sfnputc(Sfio_t* f, int c, int n);
+int sfungetc(Sfio_t* f, int c);
+
+Sfulong_t sfgetm(Sfio_t* f, Sfulong_t max);
+int sfputm(Sfio_t* f, Sfulong_t v, Sfulong_t max);
+Sfulong_t sfgetu(Sfio_t* f);
+int sfputu(Sfio_t* f, Sfulong_t v);
+Sflong_t sfgetl(Sfio_t* f);
+int sfputl(Sfio_t* f, Sflong_t v);
+Sfdouble_t sfgetd(Sfio_t* f);
+int sfputd(Sfio_t* f, Sfdouble_t v);
+
+char* sfgetr(Sfio_t* f, int rsc, int type);
+ssize_t sfputr(Sfio_t* f, const char* s, int rsc);
+Sfoff_t sfmove(Sfio_t* fr, Sfio_t* fw, Sfoff_t n, int rsc);
+
+ssize_t sfread(Sfio_t* f, Void_t* buf, size_t n);
+ssize_t sfwrite(Sfio_t* f, const Void_t* buf, size_t n);
+Sfoff_t sfseek(Sfio_t* f, Sfoff_t offset, int type);
+Void_t* sfreserve(Sfio_t* f, ssize_t n, int type);
+.ft 1
+.fi
+.Ss "DATA FORMATTING"
+.nf
+.ft 5
+int sfscanf(Sfio_t* f, const char* format, ...);
+int sfsscanf(const char* s, const char* format, ...);
+int sfvsscanf(const char* s, const char* format, va_list args);
+int sfvscanf(Sfio_t* f, const char* format, va_list args);
+
+int sfprintf(Sfio_t* f, const char* format, ...);
+char* sfprints(const char* format, ...);
+char* sfvprints(const char* format, va_list args);
+ssize_t sfaprints(char** sp, const char* format, ...);
+ssize_t sfvaprints(char** sp, const char* format, va_list args);
+int sfsprintf(char* s, int n, const char* format, ...);
+int sfvsprintf(char* s, int n, const char* format, va_list args);
+int sfvprintf(Sfio_t* f, const char* format, va_list args);
+
+Sffmt_t;
+
+SFFMT_LEFT
+SFFMT_SIGN
+SFFMT_BLANK
+SFFMT_ZERO
+SFFMT_THOUSAND
+SFFMT_LONG
+SFFMT_LLONG
+SFFMT_SHORT
+SFFMT_LDOUBLE
+SFFMT_IFLAG
+SFFMT_JFLAG
+SFFMT_CENTER
+SFFMT_CHOP
+SFFMT_ALTER
+SFFMT_SKIP
+SFFMT_ARGPOS
+SFFMT_VALUE
+
+int (*Sffmtext_f)(Sfio_t* f, Void_t* v, Sffmt_t* fe);
+int (*Sffmtevent_f)(Sfio_t* f, int type, Void_t* v, Sffmt_t* fe);
+void va_copy(va_list to, va_list fr);
+long sffmtversion(Sffmt_t* fe, type);
+.ft 1
+.fi
+.Ss "BUFFERING, SYNCHRONIZATION"
+.nf
+.ft 5
+Void_t* sfsetbuf(Sfio_t* f, Void_t* buf, size_t size);
+int sfsync(Sfio_t* f);
+int sfpoll(Sfio_t** flist, int n, int timeout);
+Sfio_t* sfpool(Sfio_t* f, Sfio_t* poolf, int mode);
+int sfpurge(Sfio_t* f);
+.ft 1
+.fi
+.Ss "DISCIPLINE, EVENT HANDLING"
+.nf
+.ft 5
+Sfdisc_t* sfdisc(Sfio_t* f, Sfdisc_t* disc);
+int sfraise(Sfio_t* f, int type, Void_t* data);
+ssize_t sfrd(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc);
+ssize_t sfwr(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc);
+Sfoff_t sfsk(Sfio_t* f, Sfoff_t offset, int type, Sfdisc_t* disc);
+
+SF_NEW
+SF_READ
+SF_WRITE
+SF_SEEK
+SF_CLOSING (SF_CLOSE)
+SF_DPUSH
+SF_DPOP
+SF_DPOLL
+SF_DBUFFER
+SF_SYNC
+SF_PURGE
+SF_FINAL
+SF_READY
+SF_LOCKED
+SF_ATEXIT
+SF_EVENT
+.ft 1
+.fi
+.Ss "STREAM CONTROL"
+.nf
+.ft 5
+int sfresize(Sfio_t* f, Sfoff_t size);
+int sfset(Sfio_t* f, int flags, int i);
+int sfsetfd(Sfio_t* f, int fd);
+Sfio_t* sfstack(Sfio_t* base, Sfio_t* top);
+Sfio_t* sfswap(Sfio_t* f1, Sfio_t* f2);
+.ft 1
+.fi
+.Ss "STREAM INFORMATION"
+.nf
+.ft 5
+Sfoff_t sfsize(Sfio_t* f);
+Sfoff_t sftell(Sfio_t* f);
+ssize_t sfvalue(Sfio_t* f);
+int sffileno(Sfio_t* f);
+
+int sfstacked(Sfio_t* f);
+int sfeof(Sfio_t* f);
+int sferror(Sfio_t* f);
+int sfclrerr(Sfio_t* f);
+int sfclrlock(Sfio_t* f);
+
+int sfnotify(void (*notify)(Sfio_t* f, int type, Void_t* data));
+
+int sfwalk(Sfwalk_f walkf, Void_t* data, int type);
+.ft 1
+.fi
+.Ss "MISCELLANEOUS FUNCTIONS"
+.nf
+.ft 5
+ssize_t sfmaxr(ssize_t maxr, int s);
+ssize_t sfslen();
+int sfulen(Sfulong_t v);
+int sfllen(Sflong_t v);
+int sfdlen(Sfdouble_t v);
+ssize_t sfpkrd(int fd, Void_t* buf, size_t n,
+ int rsc, long tm, int action);
+.ft 1
+.fi
+.Ss "FULL STRUCTURE SFIO_T"
+.nf
+.ft 5
+#include <sfio_t.h>
+#define SFNEW(buf,size,file,flags,disc)
+.ft 1
+.fi
+.Ss "EXAMPLE DISCIPLINES"
+.nf
+.ft 5
+#include <sfdisc.h>
+
+int sfdcdio(Sfio_t* f, size_t bufsize);
+int sfdcdos(Sfio_t* f);
+int sfdcfilter(Sfio_t* f, const char* cmd);
+int sfdcseekable(Sfio_t* f);
+int sfdcslow(Sfio_t* f);
+int sfdcsubstream(Sfio_t* f, Sfio_t* parent,
+ Sfoff_t offset, Sfoff_t extent);
+int sfdctee(Sfio_t* f, Sfio_t* tee);
+int sfdcunion(Sfio_t* f, Sfio_t** array, int n);
+int sfdclzw(Sfio_t* f);
+int sfdcgzip(Sfio_t* f, int flags);
+.ft 1
+.fi
+.Ss "STDIO-COMPATIBILITY"
+.nf
+.ft 5
+#include <stdio.h>
+cc ... -lstdio -lsfio
+cc ... -lstdio-mt -lsfio-mt
+.ft 1
+.fi
+.SH DESCRIPTION
+.PP
+Sfio provides I/O functions to manage buffered streams.
+Each Sfio stream is a \fIfile stream\fP, representing a file (see \f5open(2)\fP),
+or a \fIstring stream\fP, representing a memory segment.
+Beyond the usual I/O operations on streams,
+Sfio provides I/O disciplines for extended data processing,
+stream stacks for recursive stream processing, and
+stream pools for automatic data synchronization.
+Applications can extend the \f5sfprintf()/sfscanf()\fP functions
+to define their own conversion patterns as well as redefine existing ones.
+.PP
+A discipline defines analogues of
+the system calls \f5read(2), write(2)\fP and \f5lseek(2)\fP.
+Such system calls or their discipline replacements are used to process stream data.
+Henceforth, ``\fIsystem call\fP'' will refer to either a system call
+or its discipline replacement.
+.PP
+A system call is said to cause an exception if its return value is non-positive.
+Unless overridden by exception handlers (see \f5sfdisc()\fP),
+an interrupted system call (\f5errno == EINTR\fP on UNIX systems)
+will be automatically reinvoked to continue the ongoing operation.
+.PP
+The buffer of a stream is typically a memory segment allocated via \f5malloc(3)\fP
+or supplied by the application.
+File streams may also use memory mapping (\f5mmap(2)\fP) if that is more efficient.
+When memory mapping is used,
+the underlying file should not be truncated while the stream is active.
+Memory mapping can be turned off using \f5sfsetbuf()\fP.
+.PP
+There are three \fIstandard streams\fP:
+\f5sfstdin\fP for input (file descriptor \f50\fP on UNIX systems),
+\f5sfstdout\fP for normal output (file descriptor \f51\fP), and
+\f5sfstderr\fP for error output (file descriptor \f52\fP).
+
+.PP
+.Ss "LIBRARIES"
+.PP
+This version of Sfio can be built and used for both uni-threaded and multi-threaded
+environments. In the former case, streams are not protected from
+simultaneous accesses by different threads. In the latter case, a stream
+is typically locked with a mutex during access so that another thread
+trying to access the same stream will block until the mutex is released.
+
+A program that does not use multiple threads can link with \fBlibsfio.a\fP
+while a program that uses multiple threads should link with \fBlibsfio-mt.a\fP.
+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_t*"
+This defines a type suitable to exchange
+data of unknown types between application and Sfio.
+\f5Void_t\fP is a macro defined as \f5void\fP for ANSI-C and C++ and
+\f5char\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_t*, size_t, Sfdisc_t*)"
+.Ss " ssize_t (*Sfwrite_f)(Sfio_t*, const Void_t*, size_t, Sfdisc_t*)"
+.Ss " Sfoff_t (*Sfseek_f)(Sfio_t*, Sfoff_t, int, Sfdisc_t*)"
+.Ss " int (*Sfexcept_f)(Sfio_t*, int, Void_t*, Sfdisc_t*)"
+\f5Sfdisc_t\fP defines a stream discipline structure.
+\f5Sfread_f\fP, \f5Sfwrite_f\fP and \f5Sfseek_f\fP are the types
+of discipline functions to replace the system calls:
+\f5read(2)\fP, \f5write(2)\fP and \f5lseek(2)\fP.
+\f5Sfexcept_f\fP is the type of an event-handling function.
+See \f5sfdisc()\fP for more details.
+.PP
+.Ss " Sffmt_t"
+.Ss " int (*Sffmtext_f)(Sfio_t*, Void_t*, Sffmt_t*)"
+.Ss " int (*Sffmtevent_f)(Sfio_t*, int, Void_t*, Sffmt_t*)"
+\f5Sffmt_t\fP defines a formatting environment that can be used
+to extend scanning and printing in the \f5sfprint()/sfscanf()\fP
+functions. \f5Sffmtext_f\fP and \f5Sffmtevent_f\fP define the types
+of extension functions definable in \f5Sffmt_t\fP.
+See \f5Sffmt_t\fP below for more details.
+.PP
+.Ss " SFIO_VERSION"
+This is a macro value of type \f5long int\fP that defines
+the current version number of Sfio. For example, the Sfio2000's
+version number is \f520000515L\fP
+(which also indicates its latest version date: 05/15/2000).
+
+.Ss "BIT FLAGS"
+A number of bit flags control stream operations.
+They are set either at stream initialization or by calling \f5sfset()\fP.
+Following are the flags:
+.Tp
+\f5SF_STRING\fP:
+The stream is memory-based.
+.Tp
+\f5SF_READ\fP, \f5SF_WRITE\fP, \f5SF_APPENDWR\fP (\f5SF_APPEND\fP):
+Flags \f5SF_READ\fP and \f5SF_WRITE\fP indicate readability and writability.
+Flag \f5SF_APPENDWR\fP asserts that the stream is a file opened in append mode
+(see \f5open(2)\fP and \f5fcntl(2)\fP)
+so that data is always output at the end of file.
+On systems without direct support for append mode,
+Sfio uses \f5lseek(2)\fP or its discipline replacement
+to approximate this behavior.
+.Tp
+\f5SF_LINE\fP:
+The stream is line-oriented.
+For a \f5SF_WRITE\fP stream,
+this means that buffered data is flushed
+whenever a new-line character, \f5\en\fP, is output.
+For a \f5SF_READ\fP stream, \f5SF_LINE\fP is only
+significant during calls to functions in the \f5sfscanf()\fP family.
+\f5SF_LINE\fP is set on initialization of
+any stream representing a terminal device.
+.Tp
+\f5SF_SHARE\fP, \f5SF_PUBLIC\fP:
+Flag \f5SF_SHARE\fP means that the underlying file descriptor
+is shared by independent entities (for example, multiple processes).
+
+For a seekable file stream, \f5SF_SHARE\fP means that
+the logical stream and the physical file positions will be made the same
+before a system call to perform physical I/O.
+There are different possibilities.
+If \f5SF_PUBLIC\fP is not set,
+the physical file position is made equal to the logical stream position.
+If \f5SF_PUBLIC\fP is set, there are two cases.
+If the physical file position has changed from its last known position,
+the logical stream position is made equal to the new physical file position.
+Finally, if the physical file location remains the same as its last known position,
+the physical file position is made the same as the logical stream position.
+
+For an unseekable stream (e.g., pipes or terminal devices), if possible,
+\f5SF_SHARE\fP means that
+the block and record I/O operations (\f5sfread()\fP, \f5sfwrite()\fP, \f5sfmove()\fP,
+\f5sfgetr()\fP, \f5sfputr()\fP, \f5sfreserve()\fP, \f5sfscanf()\fP
+and \f5sfvprintf()\fP) will ensure:
+(1) after each writing operation, the stream is synchronized and
+(2) each reading operation only reads the requested amount.
+Note, however, that (2) is not always possible
+without proper OS facilities such as \f5recv(2)\fP or \f5streamio(4)\fP.
+
+A standard stream that is seekable will be initialized with \f5SF_SHARE|SF_PUBLIC\fP.
+.Tp
+\f5SF_MALLOC\fP:
+The stream buffer was obtained via \f5malloc(3)\fP
+and can be reallocated or freed.
+.Tp
+\f5SF_STATIC\fP:
+The stream structure should not be freed when closed (\f5sfclose()\fP).
+This flag is used by an applications that allocate their own
+stream structures. Such applications must use the header file \f5sfio_t.h\fP
+instead of \f5sfio.h\fP.
+.Tp
+\f5SF_IOCHECK\fP:
+If the stream has a discipline exception handler,
+exceptions will be raised in \f5sfsync()\fP, \f5sfpurge()\fP
+or before a system call \f5read(2)\fP or \f5write(2)\fP (see \f5sfdisc()\fP).
+.Tp
+\f5SF_WHOLE\fP:
+This flag guarantees that data written in any single \f5sfwrite()\fP or
+\f5sfputr()\fP call will always be output as a whole to the output device.
+This is useful in certain applications (e.g., networking) where a complex object
+must be output without being split in different system calls.
+Note that the respective stream still buffers data as much as the buffer can accomodate.
+.Tp
+\f5SF_MTSAFE\fP:
+This flag indicates that the respective stream may be accessed by more than one threads.
+A mutex lock will be used to ensure that only one thread at a time can access
+the stream. Note that this flag can only be set at stream opening time
+(see \f5sfopen()\fP, \f5sfpopen()\fP and \f5sfnew()\fP).
+Certain fast macro functions such as \f5sfgetc()\fP and \f5sfputc()\fP will
+no longer behave as macros. Thus, an application that requires such fast macro functions
+should leave \f5SF_MTSAFE\fP off and performs explicit locking with \f5sfmutex()\fP.
+.Tp
+\f5SF_IOINTR\fP:
+This flag indicates that I/O system calls should not be resumed
+after being interrupted by signals. It is useful for
+aborting I/O operations on such interruptions. Note, however,
+than certain operating systems (e.g., BSD Unix systems) may automatically
+resume interrupted system calls outside the scope of the library. On such systems,
+\f5SF_IOINTR\fP will be ineffective.
+
+.PP
+.Ss "OPENING/CLOSING STREAMS"
+.PP
+.Ss " Sfio_t* sfnew(Sfio_t* f, Void_t* buf, size_t size, int fd, int flags)"
+This function creates or renews a stream.
+It returns the new stream on success and \f5NULL\fP on error.
+.Tp
+\f5f\fP:
+If \f5f\fP is \f5NULL\fP, a new stream is created.
+Otherwise, \f5f\fP is reused.
+In this case, if \f5flags\fP does not have \f5SF_EOF\fP,
+\f5f\fP shall be closed via \f5sfclose()\fP before being reused.
+During a stream renewal, buffer, pool and discipline stack are preserved.
+Note that, except for \f5SF_STATIC\fP streams,
+renewing a stream already closed will result in undefined behavior.
+.Tp
+\f5buf\fP, \f5size\fP:
+These determine a buffering scheme.
+See \f5sfsetbuf()\fP for more details.
+.Tp
+\f5fd\fP:
+If \f5SF_STRING\fP is specified in \f5flags\fP, this is ignored.
+Otherwise, \f5fd\fP is a file descriptor (e.g., from \f5open(2)\fP)
+to use for raw data I/O.
+Note that Sfio supports unseekable file descriptors
+opened for both read and write, e.g., sockets.
+.Tp
+\f5flags\fP:
+This is composed from \f5SF_EOF\fP and
+bit values defined in the \fBBIT FLAGS\fP section.
+Note, in particular, that a multi-threaded application should
+set the bit \f5SF_MTSAFE\fP to protect the new stream from
+being simultaneously accessed by multiple threads.
+
+.Ss " Sfio_t* sfopen(Sfio_t* f, const char* string, const char* mode)"
+
+If \f5string\fP is \f5NULL\fP,
+\f5f\fP is a file stream and
+\f5mode\fP does not imply a string stream,
+\f5sfopen()\fP changes the modes of \f5f\fP according to \f5mode\fP.
+In this case, \f5sfopen()\fP returns \f5f\fP on success and \f5NULL\fP on error.
+This somewhat unusual usage of \f5sfopen()\fP is good for
+resetting certain predefined modes in standard streams including
+\fItext/binary\fP and \fIappend\fP that are inherited from some parent process.
+Note also that \f5SF_READ\fP and \f5SF_WRITE\fP can only be reset if the stream
+is not yet initialized.
+
+\f5sfopen()\fP is normally used to create a new stream or renew a stream.
+In this case, it returns the new stream on success and \f5NULL\fP on error.
+Below are the meanings of the arguments:
+.Tp
+\f5f\fP:
+This is treated as in \f5sfnew()\fP.
+.Tp
+\f5string\fP:
+This is a file name or a string to perform I/O on.
+See above for when this is \f5NULL\fP.
+.Tp
+\f5mode\fP:
+This is composed from the set of letters \f5{s, r, w, +, a, b, t, x, m, u}\fP.
+When conflicting options are present in the same \f5mode\fP string,
+the last one will take effect.
+
+\f5s\fP specifies opening a string stream.
+\f5string\fP can be a null-terminated string or \f5NULL\fP.
+Specifying \f5s\fP alone is equivalent to specifying \f5sr\fP.
+If \f5s\fP is not specified, \f5string\fP defines a file name.
+
+\f5r\fP and \f5w\fP specify read and write modes.
+Write mode creates and/or truncates the given file to make an empty file.
+The \f5+\fP modifier indicates that the stream is opened for both read and write.
+
+\f5a\fP specifies append mode, i.e., data is always output at end of file.
+
+\f5b\fP and \f5t\fP specify binary and text modes.
+
+\f5x\fP specifies exclusive mode, i.e.,
+a file opened for writing should not already exist.
+
+\f5m\fP specifies that the stream needs to be protected from
+simultaneous accesses by multiple threads.
+This turns on the bit flag \f5SF_MTSAFE\fP.
+
+\f5u\fP specifies that the stream is guaranteed to be accessed
+by only one thread at a time. The bit flag \f5SF_MTSAFE\fP is left off.
+The absence of option \f5m\fP is the same as the presence of option \f5u\fP.
+
+.Ss " Sfio_t* sfpopen(Sfio_t* f, const char* cmd, const char* mode)"
+This function opens a stream that corresponds to the coprocess \f5cmd\fP.
+The argument \f5mode\fP should be composed from \f5r\fP, \f5w\fP, and \f5+\fP.
+The argument \f5f\fP, if not \f5NULL\fP, is a stream to be renewed (see \f5sfnew()\fP).
+\f5sfpopen()\fP returns the new stream or \f5NULL\fP on error.
+
+The standard input/output of \f5cmd\fP
+is connected to the application via a pipe if the stream is opened for writing/reading.
+If the stream is opened for both reading and writing,
+there will be two different associated file descriptors, one for each type of I/O
+(note the effect on \f5sffileno()\fP).
+
+On opening a coprocess for writing (i.e., \f5mode\fP contains \f5w\fP or \f5+\fP),
+the signal handler for \f5SIGPIPE\fP in the parent application
+will be set to \f5SIG_IGN\fP if it is \f5SIG_DFL\fP at that time.
+This protects the parent application from being accidentally killed
+on writing to a coprocess that closes its reading end.
+Applications that need to detect such write errors should use
+disciplines and exception handlers (see \f5sfdisc()\fP).
+
+The command \f5cmd\fP
+is executed by an \fIinterpreter\fP which is either \f5/bin/sh\fP
+or an executable command defined by the environment variable \f5SHELL\fP.
+In either case, the interpreter is invoked with 2 arguments, respectively \f5-c\fP
+and the given command \f5cmd\fP. When the interpreter is \f5/bin/sh\fP or
+\f5/bin/ksh\fP, \f5sfpopen()\fP may execute the command \f5cmd\fP itself
+if there are no shell meta-characters in \f5cmd\fP.
+
+.Ss " Sfio_t* sftmp(size_t size)"
+This function creates a stream for temporary data.
+It returns the new stream or \f5NULL\fP on error.
+
+A stream created by \f5sftmp()\fP can be completely or partially memory-resident.
+If \f5size\fP is \f5SF_UNBOUND\fP, the stream is a pure string stream.
+If \f5size\fP is zero, the stream is a pure file stream.
+Otherwise, the stream is first created as a string stream but when
+its buffer grows larger than \f5size\fP or on any attempt to change disciplines,
+a temporary file is created.
+Two environment variables, \f5TMPPATH\fP and \f5TMPDIR\fP,
+direct where temporary files are created.
+\f5TMPPATH\fP, if defined,
+specifies a colon-separated set of directories to be
+used in a round-robin fashion to create files.
+If \f5TMPPATH\fP is undefined,
+\f5TMPDIR\fP can be used to specify a single directory to create files.
+If neither of \f5TMPPATH\fP and \f5TMPDIR\fP are defined, \f5/tmp\fP is used.
+
+.Ss " int sfclose(Sfio_t* f)"
+This function closes the stream \f5f\fP and frees its resources.
+\f5SF_STATIC\fP should be used if the stream space is to be preserved.
+If \f5f\fP is the base of a stream stack (see \f5sfstack()\fP),
+all streams on the stack are closed.
+If \f5f\fP is a \f5sfpopen\fP-stream,
+\f5sfclose()\fP waits until the associated command terminates
+and returns its exit status.
+\f5sfclose()\fP returns \f5-1\fP for failure and \f50\fP for success.
+
+\f5SF_READ|SF_SHARE\fP and \f5SF_WRITE\fP streams
+are synchronized before closing (see \f5sfsync()\fP).
+If \f5f\fP has disciplines,
+their exception handlers will be called twice.
+The first exception handler call has the \f5type\fP argument as one of
+\f5SF_CLOSING\fP or \f5SF_NEW\fP (see \f5sfdisc()\fP.)
+The latter, \f5SF_NEW\fP is used when a stream is being closed via \f5sfnew()\fP
+so that it can be renewed.
+The second call uses \f5type\fP as \f5SF_FINAL\fP
+and is done after all closing operations have succeeded but before
+the stream itself is deallocated.
+In either case, if the exception handler returns a negative value,
+\f5sfclose()\fP will immediately return this value.
+If the exception handler returns a positive value,
+\f5sfclose()\fP will immediately return a zero value.
+
+.PP
+.Ss "THREAD SAFETY"
+.PP
+The libraries \f5libsfio.a\fP and \f5libstdio.a\fP (providing binary
+compatibility to Stdio-based code) only support uni-threaded code.
+Multi-threaded applications should link with
+\f5libsfio-mt.a\fP and \f5libstdio-mt.a\fP.
+When this is done, certain platforms may require additional
+thread libraries for linkage. For example, Linux, Irix and Solaris
+require \f5-lpthread\fP while HPUX requires \f5-lcma\fP.
+Aside from linkage differences, the Sfio API remains identical in all cases.
+
+Note that unlike Stdio streams which are in thread-safe mode by default.
+Sfio streams can be opened in either uni-threaded or multi-threaded mode.
+A uni-threaded stream is more efficient than a multi-threaded one.
+For example, functions such as \f5sfgetc()\fP and \f5sfputc()\fP
+remain as macro or inline functions for a uni-threaded stream while
+they will act as full function calls in a multi-threaded case.
+The three standard streams \f5sfstdin/sfstdout/sfstderr\fP
+are in multi-threaded mode by default
+(however, see \f5sfopen()\fP for how this may be changed).
+Other Sfio streams are normally opened uni-threaded unless
+the flag \f5SF_MTSAFE\fP or the option \f5m\fP were specified.
+Stdio-based code can also make a Stdio stream uni-threaded by
+using the option \f5u\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 \f5f\fP.
+It can be used by a thread to serialize a sequence of I/O operations
+executed together in some critical section.
+\f5sfmutex()\fP is implicitly used by
+all Sfio operations on a stream with the flag \f5SF_MTSAFE\fP to
+protect it from concurrent accesses via multiple threads.
+\f5sfmutex()\fP returns \f50\fP on success and some non-zero value on failure.
+
+Each stream has a lock count which starts at \f50\fP.
+When the count is positive, a single thread holds the stream.
+Only this thread can further lock or unlock the stream.
+A different thread attempting to acquire such a locked stream will suspend
+until the lock count returns to \f50\fP.
+Each successful locking operation increases the lock count
+while each successful unlocking operation decreases it,
+thus, allowing nesting of matching lock/unlock operations.
+
+The \f5type\fP argument of \f5sfmutex()\fP takes on the below values:
+.Tp
+\f5SFMTX_LOCK\fP:
+Locking a stream if it is unlocked or increasing the lock count of the stream
+if it is already locked by the same thread. This call will block until it is
+possible to lock the stream.
+.Tp
+\f5SFMTX_TRYLOCK\fP:
+This is the non-blocking version of \f5SFMTX_LOCK\fP.
+If the stream is already locked by a different thread, \f5sfmutex()\fP will
+immediately return with an error status.
+.Tp
+\f5SFMTX_UNLOCK\fP:
+Decreasing the lock count and releasing the stream when the lock count reaches 0.
+An attempt to unlock a stream without a previously successful lock may
+result in undefined behavior in certain implementations.
+The current Sfio implementation returns an error status.
+.Tp
+\f5SFMTX_CLRLOCK\fP:
+Resetting the lock count to \f50\fP and releasing the stream.
+As with \f5SFMTX_LOCK\fP,
+an attempt to clear the lock count without a previously successful lock
+may result in undefined behavior.
+.PP
+.Ss "INPUT/OUPUT 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 \f5f\fP.
+\f5sfgetc()\fP returns the byte read or \f5-1\fP on error.
+\f5sfputc()\fP returns \f5c\fP on success and \f5-1\fP on error.
+
+.Ss " ssize_t sfnputc(Sfio_t* f, int c, size_t n)"
+This function attempts to write the byte \f5c\fP to \f5f\fP \f5n\fP times.
+It returns the number of bytes actually written or \f5-1\fP on failure.
+
+.Ss " int sfungetc(Sfio_t* f, int c)"
+This function pushes the byte \f5c\fP back into \f5f\fP.
+If \f5c\fP matches the byte immediately before the current position in buffered data,
+the current position is simply backed up (note the effect on \f5sftell()\fP and
+\f5sfseek()\fP). There is no theoretical limit on the number of bytes that
+can be pushed back into a stream. Pushed back bytes not part of
+buffered data will be discarded on any operation that implies
+buffer synchronization.
+\f5sfungetc()\fP returns \f5c\fP on success and \f5-1\fP on failure.
+
+.Ss " Sfulong_t sfgetm(Sfio_t* f, Sfulong_t max)"
+.Ss " int sfputm(Sfio_t* f, Sfulong_t v, Sfulong_t max)"
+These functions read and write \f5Sfulong_t\fP values
+encoded in a portable format given that the values are at most \f5max\fP.
+Portability across a write architecture and a read architecture
+requires that the bit order in a byte is the same on both architectures and
+the written value is storable in an \f5Sfulong_t\fP on the read architecture.
+\f5sfgetm()\fP returns the value read or \f5-1\fP on error.
+\f5sfputm()\fP returns the number of bytes written or \f5-1\fP on error.
+
+.Ss " Sfulong_t sfgetu(Sfio_t* f)"
+.Ss " int sfputu(Sfio_t* f, Sfulong_t v)"
+These functions read and write \f5Sfulong_t\fP values
+in a compact variable-length portable format.
+Portability across a write architecture and a read architecture
+requires that the bit order in a byte is the same on both architectures and
+the written value is storable in an \f5Sfulong_t\fP on the read architecture.
+\f5sfgetu()\fP returns the value read or \f5-1\fP on error.
+\f5sfputu()\fP returns the number of bytes written or \f5-1\fP on error.
+See also \f5sfulen()\fP.
+
+.Ss " Sflong_t sfgetl(Sfio_t* f)"
+.Ss " int sfputl(Sfio_t* f, Sflong_t v)"
+These functions are similar to \f5sfgetu()\fP and \f5sfputu()\fP
+but for reading and writing (signed) \f5Sflong_t\fP values.
+See also \f5sfllen()\fP.
+
+.Ss " Sfdouble_t sfgetd(Sfio_t* f)"
+.Ss " int sfputd(Sfio_t* f, Sfdouble_t v)"
+These functions read and write \f5Sfdouble_t\fP values.
+In this case, portability depends on the input and output architectures
+having the same floating point value representation.
+Values are coded and decoded using \f5ldexp(3)\fP and \f5frexp(3)\fP
+so they are constrained to the sizes supported by these functions.
+See also \f5sfdlen()\fP.
+
+.Ss " char* sfgetr(Sfio_t* f, int rsc, int type)"
+This function reads a record of data ending in the record separator \f5rsc\fP.
+After \f5sfgetr()\fP returns, the length of the record even if it is incomplete
+can be retrieved with \f5sfvalue()\fP.
+\f5sfgetr()\fP returns the record on success and \f5NULL\fP on error.
+See also \f5sfmaxr()\fP for limiting the amount of data read to construct a record.
+
+The \f5type\fP argument is composed of some subset of the below bit flags:
+.Tp
+\f5SF_STRING\fP:
+A null byte will replace the record separator to make the record into a C string.
+Otherwise, the record separator is left alone.
+.Tp
+\f5SF_LOCKR\fP:
+Upon successfully obtaining a record \f5r\fP,
+the stream will be locked from further access until it is released with
+a call \f5sfread(f,r,0)\fP.
+.Tp
+\f5SF_LASTR\fP:
+This should be used only after a failed \f5sfgetr()\fP to retrieve
+the last incomplete record. In this case, \f5rsc\fP is ignored.
+
+.Ss " ssize_t sfputr(Sfio_t* f, const char* s, int rsc)"
+This function writes the null-terminated string \f5s\fP to \f5f\fP.
+If \f5rsc\fP is non-negative, \f5(unsigned char)rsc\fP is output after the string.
+\f5sfputr()\fP returns the number of bytes written or \f5-1\fP on failure.
+
+.Ss " Sfoff_t sfmove(Sfio_t* fr, Sfio_t* fw, Sfoff_t n, int rsc)"
+This function moves objects
+from input stream \f5fr\fP to output stream \f5fw\fP.
+\f5sfmove()\fP returns the number of objects moved or \f5-1\fP on failure.
+
+An object can be either a byte if the record separator argument
+\f5rsc\fP is negative or a record of \f5rsc\fP is non-negative.
+In the latter case, a record is incomplete if it does not end in \f5rsc\fP.
+Generally speaking, a stream can have at most one incomplete record.
+If \f5n\fP is negative, all complete objects of \f5fr\fP will be moved.
+Otherwise, \f5n\fP indicates the number of objects to move.
+If either \f5fr\fP or \f5fw\fP is \f5NULL\fP, it acts
+as if it is a stream corresponding to \f5/dev/null\fP,
+the UNIX device that has no read data and throws away any write data.
+For example, the call \f5sfmove(f,(Sfio_t*)0,(Sfoff_t)(-1),'\en')\fP
+counts the number of complete lines in stream \f5f\fP.
+
+.Ss " ssize_t sfread(Sfio_t* f, Void_t* buf, size_t n)"
+This function reads up to \f5n\fP bytes from \f5f\fP into buffer \f5buf\fP.
+It returns the number of bytes actually read or \f5-1\fP on error.
+
+.Ss " ssize_t sfwrite(Sfio_t* f, const Void_t* buf, size_t n)"
+This function writes \f5n\fP bytes from \f5buf\fP to \f5f\fP.
+If \f5f\fP is \f5SF_STRING\fP, and the buffer is not large enough,
+an \f5SF_WRITE\fP exception shall be raised.
+\f5sfwrite()\fP returns the number of bytes written or \f5-1\fP on failure.
+
+.Ss " Sfoff_t sfseek(Sfio_t* f, Sfoff_t offset, int type)"
+This function sets a new I/O position for \f5f\fP.
+It returns the new position or \f5-1\fP on failure.
+
+If the stream is a \f5SF_STRING\fP stream and the new
+address is beyond the current buffer extent,
+an \f5SF_SEEK\fP exception will be raised (see \f5sfdisc()\fP).
+
+The new position is determined based on \f5offset\fP and
+\f5type\fP which is composed from the bit flags:
+.Tp
+\f50\fP or \f5SEEK_SET\fP:
+\f5offset\fP is the desired position.
+.Tp
+\f51\fP or \f5SEEK_CUR\fP:
+\f5offset\fP is relative to the current position (see \f5SF_PUBLIC\fP below).
+.Tp
+\f52\fP or \f5SEEK_END\fP:
+\f5offset\fP is relative to the physical end of file.
+.Tp
+\f5SF_SHARE\fP:
+The stream is treated as if it has the control bit \f5SF_SHARE\fP on.
+This implies that a system call seek will be done to ensure that the
+location seeking to is valid.
+.Tp
+\f5SF_PUBLIC\fP:
+The stream is treated as if it has the control bit \f5SF_PUBLIC\fP on.
+If the physical file position has changed from its last known location,
+the current position is taken as the new physical position.
+Otherwise, the current position is the logical stream position.
+
+.Ss " Void_t* sfreserve(Sfio_t* f, ssize_t n, int type)"
+This function reserves a data block from the stream \f5f\fP.
+It returns the reserved data block on success and \f5NULL\fP on failure.
+
+If \f5f\fP is a \f5SF_READ\fP stream, the data block is a segment of input data.
+If \f5f\fP is a \f5SF_WRITE\fP stream, the data block is a buffer
+suitable for writing output data.
+For consistency, if \f5f\fP is opened with \f5SF_READ|SF_WRITE\fP,
+it will normally be treated as if it is a \f5SF_READ\fP stream
+(see \f5sfset()\fP for forcing a particular mode) but the returned
+buffer can also be written into (more below).
+However, it is possible to bias to \f5SF_WRITE\fP when the \f5type\fP
+argument is non-negative by adding the \f5SF_WRITE\fP bit \f5type\fP.
+In any case, a reserved data block is guaranteed to be valid only until
+a future access to the stream \f5f\fP.
+
+When \f5f\fP is \f5SF_READ\fP, \f5SF_SHARE\fP and unseekable,
+\f5sfreserve()\fP will attempt to peek at input data without
+consuming it. This enables separate processes to share in reading
+input from unseekable file descriptors (e.g., pipes or devices).
+However, this use of \f5sfreserve()\fP may fail
+on certain platforms that do not properly support
+peeking on unseekable file descriptors.
+
+After a \f5sfreserve()\fP call, whether or not it succeeds,
+\f5sfvalue(f)\fP gives the size of the available data block.
+Any partially reserved data block after a failed \f5sfreserve()\fP
+call can be obtained in another \f5sfreserve()\fP call with the argument
+\f5type\fP being \f5SF_LASTR\fP. The second argument \f5n\fP
+to \f5sfreserve()\fP will be ignored in this case.
+
+A \f5sfreserve()\fP call is successful if it can obtain a data block
+of size at least the absolute value of \f5n\fP.
+For a \f5SF_READ\fP atream, the argument \f5n\fP is treated as follows:
+.Tp
+\f5n < 0\fP:
+\f5sfreserve()\fP attempts to get \fIat least\fP \f5|n|\fP bytes
+into the buffer.
+.Tp
+\f5n == 0\fP:
+If the argument \f5type\fP is \f50\fP,
+\f5sfreserve()\fP attempts to get \fIat least\fP \f51\fP byte into the buffer
+but does not consume it (as consistent with \f5n == 0\fP).
+If \f5type != 0\fP, no attempt will be made to read data into the buffer.
+For example, the call \f5sfreserve(f, 0, -1)\fP only returns the buffer status,
+i.e., size of existing buffered data and pointer to such data, if any.
+The call \f5sfreserve(f, 0, SF_LOCKR)\fP is similar but also locks the stream.
+.Tp
+\f5n > 0\fP:
+\f5sfreserve()\fP will use attempt to get \fIat most\fP \f5n\fP bytes into
+the buffer. Further, if \f5type == \f5SF_LOCKR\fP (see below), read attempts
+end on a positive amount.
+
+For a successful reservation, the argument \f5type\fP dictates treatment
+as follows:
+.Tp
+\f5type == SF_LASTR\fP:
+After a \f5sfreserve()\fP call with \f5type != SF_LOCKR\fP fails,
+there may be some left over data not accessible via conventional Sfio calls.
+Immediately after such a failed call,
+another call to \f5sfreserve\fP with \f5type == SF_LASTR\fP will return any left over
+data and also advance the stream I/O position by the amount of returned data.
+.Tp
+\f5type < 0\fP:
+If \f5n > 0\fP, the stream I/O position is advanced by \f5n\fP.
+If \f5n < 0\fP, the stream I/O position is advanced by the amount
+of available data.
+For example, a successful \f5sfreserve(f, -1, -1)\fP call will return a
+buffer of data and simultanously advance the stream I/O position by the amount
+indicated by \f5sfvalue(f)\fP.
+.Tp
+\f5type == SF_LOCKR\fP:
+The stream I/O position remains unchanged.
+In addition, \f5f\fP will be locked from further access.
+As appropriate to the stream type (\f5SF_READ\fP, \f5SF_WRITE\fP or both),
+\f5f\fP can be unlocked later
+with one of \f5sfread(f,rsrv,size)\fP or \f5sfwrite(f,rsrv,size)\fP
+where \f5rsrv\fP is the reserved data block and \f5size\fP is the amount of
+data to be consumed. For example, if \f5f\fP is a locked \f5SF_READ\fP stream,
+the call \f5sfread(f,rsrv,1)\fP will reopen the stream and simultaneously
+advance the stream I/O position by \f51\fP.
+Finally, a stream opened for both reading and writing
+can release the lock with either call (with associated operational semantics!)
+For example, the below code reads 10 bytes of data from a stream
+opened with both \f5SF_READ\fP and \f5SF_WRITE\fP, modifies the data in place,
+then rewrites the new data back to the stream:
+
+.nf
+.ft 5
+ rsrv = sfreserve(f, 10, 1);
+ for(i = 0; i < 10; ++i)
+ rsrv[i] = toupper(rsrv[i]);
+ sfwrite(f, rsrv, 10);
+.ft 1
+.fi
+
+.ne 6
+.PP
+.Ss "DATA FORMATTING"
+.PP
+Data printing and scanning are done via the
+\f5sfprintf()\fP and \f5sfscanf()\fP family of functions.
+These functions are similar to their
+ANSI-C \f5fprintf()\fP and \f5fscanf()\fP counterparts.
+However, the Sfio versions have been extended for both portability and generality.
+In particular, a notion of a formatting environment stack is introduced.
+Each formatting element on the stack
+defines a separate \fIformatting pair\fP of a format specification string,
+\f5char* format\fP (the usual second argument in the formatting
+functions), and an argument list, \f5va_list args\fP (the third argument
+in functions \f5sfvprintf()\fP and \f5sfvscanf()\fP).
+A formatting environment element may also specify extension functions
+to obtain or assign arguments and to provide new semantics for pattern processing.
+To simplify the description below, whenever we talk
+about an argument list, unless noted otherwise,
+it is understood that this means either the true
+argument list when there is no extension function or the action to be taken
+by such a function in processing arguments.
+The manipulation of the formatting environment stack is done
+via the pattern \f5!\fP discussed below.
+
+.Ss "%! and Sffmt_t"
+The pattern \f5%!\fP manipulates the formatting environment stack to
+(1) change the top environment to a new environment,
+(2) stack a new environment on top of the current top,
+or (3) pop the top environment.
+The bottom of the environment stack always contains a virtual environment with the
+original formatting pair and without any extension functions.
+
+The top environment of a stack, say \f5fe\fP, is automatically popped whenever
+its format string is completely processed.
+In this case, its event-handling function (if any) is called
+as \f5(*eventf)(f,SF_FINAL,NIL(Void_t*),fe)\fP.
+The top environment
+can also be popped by giving an argument \f5NULL\fP to \f5%!\fP
+or by returning a negative value in an extension function.
+In these cases, the event-handling function is called
+as \f5(*eventf)(f,SF_DPOP,form,fe)\fP where \f5form\fP is the remainder
+of the format string. A negative return value from the event handling function
+will prevent the environment from being popped.
+
+A formatting environment is a structure of type \f5Sffmt_t\fP
+which contains the following elements:
+
+.nf
+.ft 5
+ Sffmtext_f extf; /* extension processor */
+ Sffmtevent_f eventf; /* event handler */
+
+ char* form; /* format string to stack */
+ va_list args; /* corresponding arg list */
+
+ int fmt; /* pattern being processed */
+ ssize_t size; /* object size */
+ int flags; /* formatting control flags */
+ int width; /* width of field */
+ int precis; /* precision required */
+ int base; /* conversion base */
+
+ char* t_str; /* extfdata string */
+ int n_str; /* length of t_str */
+.ft 1
+.fi
+
+The first four elements of \f5Sffmt_t\fP must be defined by the application
+before the structure is passed to a formatting function.
+The two function fields should not be changed during processing.
+Other elements of \f5Sffmt_t\fP are set by the respective formatting function
+before it calls the extension function \f5Sffmt_t.extf\fP and, subsequently,
+can be modified by this function to redirect formatting or scanning.
+For example, consider a call from a \f5sfprintf()\fP function to process an
+unknown pattern \f5%t\fP (which we may take to mean ``time'') based on a
+formatting environment \f5fe\fP.
+\f5fe->extf\fP may reset \f5fe->fmt\fP to `\f5d\fP' upon returing
+to cause \f5sfprintf()\fP to process the value being formatted as an integer.
+
+Below are the fields of \f5Sffmt_t\fP:
+.Tp
+\f5extf\fP:
+\f5extf\fP is a function to extend scanning and formatting patterns.
+Its usage is discussed below.
+.Tp
+\f5eventf\fP:
+This is a function to process events as discussed earlier.
+.Tp
+\f5form\fP and \f5args\fP:
+This is the formatting pair of a specification string and corresponding argument list.
+When an environment \f5fe\fP is being inserted into the stack,
+if \f5fe->form\fP is \f5NULL\fP, the top environment is changed to \f5fe\fP
+and its associated extension functions
+but processing of the current formatting pair continues.
+On the other hand, if \f5fe->form\fP is not \f5NULL\fP,
+the new environment is pushed onto the stack
+so that pattern processing will start with the new formatting pair as well as
+any associated extension functions.
+During processing, whenever \f5extf\fP is called,
+\f5form\fP and \f5args\fP will be set to the current values of
+the formatting pair in use.
+.Tp
+\f5fmt\fP:
+This is set to the pattern being processed or one of '.', 'I', '('.
+.Tp
+\f5size\fP:
+This is the size of the object being processed.
+.Tp
+\f5flags\fP:
+This is a collection of bits defining the formatting flags specified for the pattern.
+The bits are:
+
+\f5SFFMT_LEFT\fP: Flag \f5-\fP in \f5sfprintf()\fP.
+
+\f5SFFMT_SIGN\fP: Flag \f5+\fP in \f5sfprintf()\fP.
+
+\f5SFFMT_BLANK\fP: Flag \fIspace\fP in \f5sfprintf()\fP.
+
+\f5SFFMT_ZERO\fP: Flag \f50\fP in \f5sfprintf()\fP.
+
+\f5SFFMT_THOUSAND\fP: Flag \f5'\fP in \f5sfprintf()\fP.
+
+\f5SFFMT_LONG\fP: Flag \f5l\fP in \f5sfprintf()\fP and \f5sfscanf()\fP.
+
+\f5SFFMT_LLONG\fP: Flag \f5ll\fP in \f5sfprintf()\fP and \f5sfscanf()\fP.
+
+\f5SFFMT_SHORT\fP: Flag \f5h\fP in \f5sfprintf()\fP and \f5sfscanf()\fP.
+
+\f5SFFMT_LDOUBLE\fP: Flag \f5L\fP in \f5sfprintf()\fP and \f5sfscanf()\fP.
+
+\f5SFFMT_IFLAG\fP: flag \f5I\fP in \f5sfprintf()\fP and \f5sfscanf()\fP.
+
+\f5SFFMT_JFLAG\fP: flag \f5j\fP in \f5sfprintf()\fP and \f5sfscanf()\fP.
+
+\f5SFFMT_CENTER\fP: flag \f5=\fP in \f5sfprintf()\fP and \f5sfscanf()\fP.
+
+\f5SFFMT_CHOP\fP: flag \f5-\fP in \fIprecis\fP in \f5sfprintf()\fP and \f5sfscanf()\fP.
+
+\f5SFFMT_ALTER\fP: Flag \f5#\fP in \f5sfprintf()\fP and \f5sfscanf()\fP.
+
+\f5SFFMT_SKIP\fP: Flag \f5*\fP in \f5sfscanf()\fP.
+
+\f5SFFMT_ARGPOS\fP: This indicates argument processing for \f5pos$\fP.
+
+\f5SFFMT_VALUE\fP: This is set by \f5fe->extf\fP
+to indicate that it is returning a value to be formatted or
+the address of an object to be assigned.
+
+.Tp
+\f5width\fP:
+This is the field width.
+.Tp
+\f5precis\fP:
+This is the precision.
+.Tp
+\f5base\fP:
+This is the conversion base.
+.Tp
+\f5t_str\fP and \f5n_str\fP:
+This is the type string and its size.
+
+.Ss " int (*Sffmtext_f)(Sfio_t* f, Void_t* v, Sffmt_t* fe)"
+This is the type of the extension function \f5fe->extf\fP to process
+patterns and arguments.
+Arguments are always processed in order and
+\f5fe->extf\fP is called exactly once per argument.
+Note that, when \f5pos$\fP (below) is not used anywhere in a format string,
+each argument is used exactly once per a corresponding pattern.
+In that case, \f5fe->extf\fP is called
+as soon as the pattern is recognized and before any scanning or formatting.
+On the other hand, when \f5pos$\fP is used in a format string,
+an argument may be used multiple times.
+In this case, all arguments shall be processed in order
+by calling \f5fe->extf\fP exactly once per argument before any pattern processing.
+This case is signified by the flag \f5SFFMT_ARGPOS\fP in \f5fe->flags\fP.
+
+In addition to the predefined formatting patterns and other application-defined
+patterns, \f5fe->extf\fP may be called with \f5fe->fmt\fP being one
+of `\f5(\fP' (left parenthesis), `\f5.\fP' (dot), and `\f5I\fP'.
+
+The left parenthesis requests a string to be used as the \f5extfdata\fP string discussed below.
+In this case, upon returning, \f5fe->extf\fP should set the \f5fe->size\fP field
+to be the length of the string or a negative value to indicate a null-terminated string.
+
+The `\f5I\fP' requests an integer to define the object size.
+
+The dot requests an integer for width, precision, base, or a separator.
+In this case, the \f5fe->size\fP field will indicate how many dots have appeared
+in the pattern specification. Note that, if the actual conversion pattern is 'c' or 's',
+the value \f5*form\fP will be one of these characters.
+.Tp
+\f5f\fP:
+This is the input/output stream in the calling formatting function.
+During a call to \f5fe->extf\fP, the stream shall be unlocked
+so that \f5fe->extf\fP can read from or write to it as appropriate.
+.Tp
+\f5v\fP:
+For both \f5sfscanf()\fP and \f5sfprintf()\fP functions,
+\f5v\fP points to a location suitable for storing any scalars or pointers.
+On return, \f5fe->extf\fP treats \f5v\fP as discussed below.
+.Tp
+\f5fe\fP:
+This is the current formatting environment.
+.PP
+The return value \f5rv\fP of \f5fe->extf\fP directs further processing.
+There are two cases.
+When \f5pos$\fP is present, a negative return value means to ignore \f5fe\fP
+in further argument processing while a non-negative return value is treated
+as the case \f5rv == 0\fP below.
+When \f5pos$\fP is not present, \f5fe->extf\fP is called per argument
+immediately before pattern processing and its return values are treated
+as below:
+.Tp
+\f5rv < 0:\fP
+The environment stack is immediately popped.
+.Tp
+\f5rv == 0:\fP
+The extension function has not consumed (in a scanning case) or
+output (in a printing case) data out of or into the given stream \f5f\fP.
+The fields \f5fmt\fP, \f5flags\fP, \f5size\fP,
+\f5width\fP, \f5precis\fP and \f5base\fP of \f5fe\fP
+shall direct further processing.
+
+For \f5sfprintf()\fP functions, if \f5fe->flags\fP
+has the bit \f5SFFMT_VALUE\fP,
+\f5fe->extf\fP should have set \f5*v\fP to the value to be processed;
+otherwise, a value should be obtained from the argument list.
+Likewise, for \f5sfscanf()\fP functions,
+\f5SFFMT_VALUE\fP means that
+\f5*v\fP should have a suitable address; otherwise,
+an address to assign value should be obtained from the argument list.
+
+When \f5pos$\fP is present,
+if \f5fe->extf\fP changes \f5fe->fmt\fP, this pattern shall be used regardless of
+the pattern defined in the format string. On the other hand, if \f5fe->fmt\fP
+is unchanged by \f5fe->extf\fP, the pattern in the format string is used.
+In any case, the effective pattern should be one of the standardly defined pattern.
+Otherwise, it shall be treated as unmatched.
+.Tp
+\f5rv > 0:\fP
+The extension function has accessed the stream \f5f\fP
+to the extent of \f5rv\fP bytes.
+Processing of the current pattern ceases except that,
+for scanning functions, if \f5fe->flags\fP does not contain
+the bit \f5SFFMT_SKIP\fP, the assignment count shall increase by 1.
+
+.Ss "void va_copy(va_list to, va_list fr)"
+This macro function portably copies the argument list \f5fr\fP to
+the argument list \f5to\fP. It should be used to set the field \f5Sffmt_t.args\fP.
+
+.Ss "long sffmtversion(Sffmt_t* fe, int type)"
+This macro function initializes
+the formatting environment \f5fe\fP with a version number if \f5type\fP is
+non-zero. Otherwise, it returns the current value of the version number of \f5fe\fP.
+This is useful for applications to find out
+when the format of the structure \f5Sffmt_t\fP changes.
+Note that the version number corresponds to the Sfio version number
+which is defined in the macro value \f5SFIO_VERSION\fP.
+
+.Ss " int sfprintf(Sfio_t* f, const char* format, ...);"
+.Ss " char* sfprints(const char* format, ...);"
+.Ss " char* sfvprints(const char* format, va_list args);"
+.Ss " ssize_t sfaprints(char** sp, const char* format, ...);"
+.Ss " ssize_t sfvaprints(char** sp, const char* format, va_list args);"
+.Ss " int sfsprintf(char* s, int n, const char* format, ...)"
+.Ss " int sfvsprintf(char* s, int n, const char* format, va_list args);"
+.Ss " int sfvprintf(Sfio_t* f, const char* format, va_list args);"
+These functions format output data.
+\f5sfprintf()\fP and \f5sfvprintf()\fP write to output stream \f5f\fP.
+\f5sfsprintf()\fP and \f5sfvsprintf()\fP write to buffer \f5s\fP
+which is of size \f5n\fP.
+\f5sfprints()\fP and \f5sfvprints()\fP construct data in some Sfio-defined buffer.
+\f5sfaprints()\fP and \f5sfvaprints()\fP are similar to \f5sfprints()\fP
+and \f5sfvprints()\fP
+but they return a string constructed via \f5malloc()\fP in \f5*sp\fP
+and expect this string to be freed by the caller when no longer needed.
+\f5sfvprintf()\fP is the underlying primitive for the other functions.
+Except for \f5sfprints()\fP and \f5sfvprints()\fP
+which return a null-terminated string or \f5NULL\fP,
+other functions return the number of output bytes or \f5-1\fP on failure.
+
+The length of string constructed by \f5sfprints()\fP, \f5sfsprintf()\fP, or
+\f5sfvsprintf()\fP can be retrieved by \f5sfslen()\fP.
+.PP
+The standard patterns are:
+\f5n, s, c, %, h, i, d, p, u, o, x, X, g, G, e, E, f\fP and \f5!\fP.
+Except for \f5!\fP which shall be described below,
+see the ANSI-C specification of \f5fprintf(3)\fP for details on the other patterns.
+Let \f5z\fP be some pattern type. A formatting pattern is defined as below:
+
+.nf
+.ft 5
+ %[pos$][flag][width][.precision[.base]][(extfdata)]z
+.ft 1
+.fi
+
+.Tp
+\f5pos$\fP:
+A pattern can specify which argument in the argument list to use.
+This is done via \f5pos$\fP where \f5pos\fP is the argument position.
+Arguments are numbered so that the first argument after \f5format\fP is at position 1.
+If \f5pos\fP is not specified, the argument following the most recently used one
+will be used.
+The pattern \f5%!\fP (see below) cannot be used subsequent to a usage of \f5pos$\fP.
+Doing so may cause unexpected behaviors.
+.Tp
+\f5flag\fP:
+The flag characters are
+\f5h\fP, \f5hh\fP, \f5l\fP, \f5ll\fP, \f5L\fP, \f5I\fP, \f5j\fP, \f5t\fP, \f5z\fP,
+\f5\-\fP, \f5+\fP, \fIspace\fP, \f50\fP, \f5'\fP, \f5=\fP and \f5#\fP.
+
+Flag \f5I\fP defines the size or type of the object being formatted.
+There are two cases: (1) \f5I\fP by itself and (2) \f5I\fP
+followed by either a decimal number or `*'.
+
+In the first case, for integer and floating point patterns,
+the object type is taken to be the largest appropriate type
+(i.e., one of \f5Sflong_t\fP, \f5Sfulong_t\fP or \f5Sfdouble_t\fP).
+For conversion specifiers \f5s\fP and \f5c\fP, the flag is ignored.
+
+In the second case, a given decimal value would define a size while
+`*' would cause the size to be obtained from the argument list.
+Then, if the conversion specifier is \f5s\fP, this size defines the
+length of the string or strings being formatted (see the discussion of \f5base\fP below).
+For integer and floating point patterns,
+the size is used to select a type from one of the below lists as
+indicated by the conversion specifier:
+
+.nf
+.ft 5
+ Sflong_t, long, int, short
+ Sfulong_t, unsigned long, unsigned int, unsigned short
+ Sfdouble_t, double, float
+.ft 1
+.fi
+
+The selection algorithm always matches types from left to right in any given list.
+Although selection is generally based on sizes in bytes,
+for compatibility with Microsoft-C, the size 64
+is matched with an appropriate type with the same number of bits, if any.
+If the given size does not match any of the listed types,
+it shall match one of \f5int\fP, \f5unsigned int\fP, and \f5double\fP
+as defined by the formatting pattern.
+
+Below are a few examples of using the \f5I\fP flag.
+The first example prints an \f5Sflong_t\fP integer.
+This example is actually not portable and
+only works on platforms where \f5sizeof(Sflong_t)\fP is 8.
+The second example shows how to that portably.
+The third example specifies printing a string of length 16.
+This length shall be used regardless of whether or not the given string
+is shorter or longer than 16.
+The last example shows the use of the pattern \f5%n\fP to assign the amount
+of data already output into a \f5short\fP integer \f5n_output\fP.
+
+.nf
+.ft 5
+ sfprintf(sfstdout,"%I8d", Sflong_obj);
+ sfprintf(sfstdout,"%I*d", sizeof(Sflong_obj), Sflong_obj);
+ sfprintf(sfstdout,"%I*s", 16, s);
+ sfprintf(sfstdout,"%d%I*n", 1001, sizeof(short), &n_output);
+.ft 1
+.fi
+
+Flags \f5h\fP, \f5l\fP, \f5j\fP and \f5L\fP are the ANSI-C conventions to
+select the types of input objects.
+For example, \f5%hd\fP indicates a \f5short int\fP,
+while \f5%ld\fP indicates a \f5long int\fP.
+
+Flag \f5hh\fP addresses the byte value types, i.e., \f5char\fP and \f5unsigned char\fP.
+
+Flags \f5z\fP, \f5t\fP and \f5j\fP address respectively
+the types \f5size_t\fP, \f5ptrdiff_t\fP and \f5Sflong_t\fP.
+
+Flags \f5ll\fP and \f5L\fP address respectively
+the largest integer and floating value types, i.e.,
+\f5Sfulong_t\fP, \f5Sflong_t\fP, and \f5Sfdouble_t\fP.
+
+Flag \f5-\fP left-justifies data within the field (otherwise, right-justification).
+
+Flag \f5+\fP means that a signed conversion will always begin with a plus or minus sign.
+
+Flag \fIspace\fP is ignored if \f5+\fP is specified; otherwise,
+it means that if the first character of a signed conversion
+is not a sign or if the result is empty, a space will be prepended.
+
+Flag \f50\fP means padding with zeros on the left.
+
+Flag \f5'\fP outputs thousands-separator used by the current locale.
+\f5setlocale(3)\fP should have been used to set the desired locale.
+
+Flag \f5=\fP centers data within the field.
+
+Flag \f5#\fP indicates an alternative format processing.
+For \f5%o\fP, the first digit is always a zero.
+For \f5%x\fP and \f5%X\fP, a non-zero result will have a prefix
+\f50x\fP or \f50X\fP. For \f5%e\fP, \f5%E\fP, \f5%f\fP, \f5%g\fP, and \f5%G\fP,
+the result always contains a decimal point. For \f5%g\fP and \f5%G\fP,
+trailing zeros will not be removed. For \f5%d\fP, \f5%i\fP and \f5%u\fP,
+the form is \fIbase#number\fP where \fIbase\fP is the conversion base
+and \fInumber\fP is represented by digits for this \fIbase\fP.
+For example, a base \f52\fP conversion with \f5%#..2d\fP for \f510\fP
+is \f52#1010\fP instead of \f51010\fP as printed with \f5%..2d\fP.
+Finally, for \f5%c\fP, bytes will be printed in the C format.
+For example, when the ASCII character set is used,
+the byte value 10 will be printed as \f5\\n\fP while 255 is printed
+as \f5\\377\fP.
+.Tp
+\f5width\fP:
+This defines the width of the printing field. A value to be printed will
+be justified and padded if necessary to fill out the field width.
+.Tp
+\f5precis\fP:
+After a first dot appears, an integral value defines a precision.
+For floating point value patterns, precision is the number of precision digits.
+For \f5%c\fP, precision defines the number of times to repeat the
+character being formatted.
+For \f5%s\fP, precision defines the maximum number of characters to output;
+-\f5precis\fP also defines the maximum number of characters to output, but
+retains the rightmost \f5precis\fP characters.
+.Tp
+\f5base\fP:
+This is defined after exactly two dots have appeared.
+
+For \f5%i\fP, \f5%d\fP, and \f5%u\fP,
+\f5base\fP should be an integer value in the inclusive range \f5[2,64]\fP
+and defines a conversion base.
+If \f5base\fP is not in this range, it is defined to be \f510\fP.
+The digits to represent numbers are:
+
+.nf
+.ft 5
+ 01234567890
+ abcdefghijklmnopqrstuvwxyz
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ @_
+.ft 1
+.fi
+
+For \f5%s\fP and \f5%c\fP, \f5base\fP defines a separator.
+Then, for \f5%s\fP, the input argument is taken to be a NULL-terminated array of strings
+while, for \f5%c\fP, this is a null-terminated array of characters.
+The strings or characters will be formatted one of a time based
+on the usual width and precision rules.
+After each formatted string or character, except for the last one,
+the separator \f5base\fP is output if it is a non-zero.
+
+There are further restrictions on the syntax of \f5%s\fP and \f5%c\fP when
+a separator is defined.
+Below are the legitimate sequences for \f5%s\fP and \f5%c\fP after the second dot:
+
+.nf
+\f5 s c\fP
+\f5 *s *c\fP
+\f5 \fP\fIz\fP\f5s \fP\fIz\fP\f5c\fP
+.fi
+
+In the first case, no separator is defined so \f5base\fP is set to zero.
+In the second case, \f5base\fP is obtained from the argument list.
+In the third case, the character \fIz\fP
+must be non-alphanumeric and \f5base\fP will be set to this character.
+
+The below example shows both the call and the result
+of printing a \f5NULL\fP-terminated array
+of three strings \f5apple\fP, \f5orange\fP, and \f5grape\fP:
+
+.nf
+.ft 5
+ sfprintf(sfstdout,"|%8..:s|",list);
+ | apple: orange: grape|
+.ft 1
+.fi
+
+.Tp
+\f5(extfdata)\fP:
+This defines a string \f5extfdata\fP
+to be passed to the extension function \f5Sffmt_t.extf\fP.
+Parentheses shall be balanced.
+If \f5extfdata\fP is \f5*\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)"
+.Ss " int sfvscanf(Sfio_t* f, const char* format, va_list args)"
+These functions scan data items.
+\f5sfscanf()\fP scans from the input stream \f5f\fP
+while \f5sfsscanf()\fP and \f5sfvsscanf()\fP
+scan from the null-terminated string \f5s\fP.
+\f5sfvscanf()\fP is the underlying primitive that performs the actual scanning.
+Item types are determined from patterns in string \f5format\fP.
+These functions return
+the number of items successfully scanned or \f5-1\fP on error.
+.PP
+A white space character (blank, tab, or new-line) in \f5format\fP
+normally matches a maximal sequence of input white space characters.
+However, if the input stream is in \f5SF_LINE\fP mode (see \f5sfset()\fP),
+a new-line character only matches white spaces up to an input new-line character.
+This is useful to avoid blocking when scanning typed inputs.
+.PP
+The standard scan patterns are:
+\f5i, d, u, o, x, X, p, n, f, e, E, g, G, c, %, s, []\fP and \f5!\fP.
+Except for \f5!\fP which shall be described below,
+see the ANSI-C specification of \f5fscanf(3)\fP for details on other patterns.
+Let \f5z\fP be some pattern type. A formatting pattern is specified as below:
+
+.nf
+.ft 5
+ %[*][pos$][width][.width.base][(extfdata)][flag]z
+.ft 1
+.fi
+
+.Tp
+\f5pos$\fP:
+A pattern can specify which argument in the argument list to use.
+This is done via \f5pos$\fP where \f5pos\fP is the argument position.
+Arguments are numbered so that the first argument after \f5format\fP is at position 1.
+If \f5pos\fP is not specified, the argument following the most recently used one
+will be used.
+The pattern \f5%!\fP (see below) cannot be used subsequent to a usage of \f5pos$\fP.
+.Tp
+\f5*:\fP
+This discards the corresponding scanned item.
+.Tp
+\f5width\fP and \f5base\fP:
+\f5width\fP defines the maximum number of bytes to scan
+and \f5base\fP defines the base of an integral value being scanned.
+The `.' (dot) notation also allows specifying a `*' (star) to obtain
+the value from the argument list. The below example specifies scanning
+4 bytes to obtain the value of an integer in base 10. At the end of scanning,
+the variable \f5v\fP should have the value \f51234\fP.
+
+.nf
+.ft 5
+ sfsscanf("12345678","%.*.*d", 4, 10, &v);
+.ft 1
+.fi
+
+.Tp
+\f5(extfdata)\fP:
+This defines a string \f5extfdata\fP
+to be passed to the extension function \f5Sffmt_t.extf\fP.
+Parentheses shall be balanced.
+If \f5extfdata\fP is \f5*\fP, the string is obtained from the argument list.
+.Tp
+\f5flag:\fP
+This is \f5#\fP, \f5I\fP, or some sequence of \f5h\fP, \f5l\fP, and \f5L\fP.
+
+Flag \f5#\fP is significant for pattern \f5%i\fP and \f5%[\fP.
+For \f5%i\fP, it means that the \f5#\fP symbol does not have its usual
+meaning in an input sequence \f5base#value\fP.
+For example, the scanning result of \f5%#i\fP on input \f52#1001\fP is \f52\fP
+and the next \f5sfgetc()\fP call will return \f5#\fP.
+For \f5%[\fP, if the next character in the input stream does not match
+the given scan set of characters, \f5#\fP causes a match to a null string
+instead of a failure.
+
+Flag \f5I\fP defines the size or type of the object being formatted.
+There are two cases: (1) \f5I\fP by itself and (2) \f5I\fP
+followed by either a decimal number or `*'.
+
+In the first case, for integer and floating point patterns,
+the object type is taken to be the largest appropriate type
+(i.e., one of \f5Sflong_t\fP, \f5Sfulong_t\fP or \f5Sfdouble_t\fP).
+For string patterns such as \f5%s\fP, the flag is ignored.
+
+In the second case, a given decimal value would define a size while
+`*' would cause the size to be obtained from the argument list.
+For string patterns such as \f5%s\fP or \f5%[\fP, this size defines the
+length of the buffer to store scanned data.
+Specifying a buffer size only limits the amount of data copied into the buffer.
+Scanned data beyond the buffer limit will be discarded.
+For integer and floating point patterns,
+the size is used to select a type from one of the below lists as
+indicated by the conversion specifier:
+
+.nf
+.ft 5
+ Sflong_t, long, int, short
+ Sfulong_t, unsigned long, unsigned int, unsigned short
+ Sfdouble_t, double, float
+.ft 1
+.fi
+
+The selection algorithm always matches types from left to right in any given list.
+Although selection is generally based on sizes in bytes,
+for compatibility with Microsoft-C, the size 64
+is matched with an appropriate type with the same number of bits, if any.
+If the given size does not match any of the listed types,
+it shall match one of \f5int\fP, \f5unsigned int\fP, and \f5double\fP
+as indicated by the formatting pattern.
+
+Below are examples of using the \f5I\fP flag.
+The first example scans a 64-bit integer.
+The second scans some floating point value
+whose size is explicitly computed and given.
+The last example scans a string into a buffer with the given size 128.
+Note that if the scanned string is longer than 127, only the first 127
+bytes shall be copied into the buffer. The rest of the scanned data
+shall be discarded.
+
+.nf
+.ft 5
+ sfscanf(sfstdin,"%I64d", &int64_obj);
+ sfscanf(sfstdin,"%I*f", sizeof(float_obj), &float_obj);
+ sfscanf(sfstdin,"%I*s", 128, buffer);
+.ft 1
+.fi
+
+Flags \f5h\fP, \f5l\fP, and \f5L\fP are the ANSI-C conventions
+for indicating the type of a scanned element.
+For example, \f5%hd\fP means scanning a \f5short int\fP.
+The flags \f5ll\fP and \f5L\fP mean respectively scanning an
+integer or a floating point value with largest size
+(i.e, \f5Sflong_t\fP or \f5Sfdouble_t\fP).
+.PP
+The \f5%i\fP, \f5%d\fP and \f5%u\fP patterns scan numbers in bases
+from \f52\fP to \f564\fP.
+\f5%i\fP scans integral values in self-describing formats.
+Except for octal, decimal and hexadecimal numbers with the usual formats,
+numbers in general bases are assumed to be of the form: \fIbase#value\fP
+where \fIbase\fP is a number in base 10 and \fIvalue\fP
+is a number in the given base.
+For example, \f52#1001\fP is the binary representation of the decimal value \f59\fP.
+If \fIbase\fP is \f536\fP or less,
+the digits for \fIvalue\fP can be any combination of \f5[0-9], [a-z], [A-Z]\fP
+where upper and lower case digits are not distinguishable.
+If \fIbase\fP is larger than \f536\fP, the set of digits is:
+
+.nf
+.ft 5
+ 0123456789
+ abcdefghijklmnopqrstuvwxyz
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ @_
+.ft 1
+.fi
+
+.PP
+.Ss "BUFFERING, SYNCHRONIZATION"
+.PP
+.Ss " Void_t* sfsetbuf(Sfio_t* f, Void_t* buf, size_t size)"
+This function changes the buffering scheme for the stream \f5f\fP.
+The stream will be synchronized before any buffer modification.
+If a new buffer is successfully set and the old buffer has not been freed,
+\f5sfsetbuf()\fP returns the old buffer. Otherwise, it returns \f5NULL\fP.
+After a \f5sfsetbuf()\fP call,
+\f5sfvalue()\fP returns the size of the returned buffer.
+
+Sfio attempts to read data in blocks likely to be serviced fast by the file system.
+This means block sizes being multiples of a suitable alignment value
+(e.g., 512, 1024 or 8192). By default, the alignment value
+is computed via some internal mechanism depending on the local platform but
+it can also be explicitly set via the call \f5sfsetbuf(f, (Void_t*)f, size)\fP.
+
+In invocations of \f5sfsetbuf()\fP other than the above case,
+the \f5size\fP argument is treated as follows:
+.Tp
+\f5size == SF_UNBOUND\fP:
+Sfio will pick a suitable buffer size.
+If \f5buf\fP is \f5NULL\fP,
+Sfio will also pick a suitable buffering scheme (such as memory mapping.)
+If \f5buf\fP is not \f5NULL\fP, its actual value is ignored
+but the buffer will be allocated via \f5malloc(3)\fP.
+This can be used to avoid memory mapping.
+.Tp
+\f5size > 0\fP:
+This is the suggested size to use for buffering or memory mapping.
+If \f5buf\fP is \f5NULL\fP,
+Sfio will pick a suitable buffering scheme as discussed above.
+If \f5buf\fP is not \f5NULL\fP, then \f5buf\fP and \f5size\fP determine
+a buffer of the given size.
+.Tp
+\f5size == 0\fP:
+If \f5buf\fP is \f5NULL\fP, the stream will be unbuffered.
+If \f5buf\fP is not \f5NULL\fP,
+\f5sfsetbuf()\fP simply returns the stream buffer.
+In this case, no attempt will be made to synchronize the stream.
+
+.Ss " int sfsync(Sfio_t* f)"
+This function synchronizes the logical and physical views of stream \f5f\fP.
+It returns a negative value for failure and \f50\fP for success.
+
+For a \f5SF_WRITE\fP stream, synchronization means to write out any buffered data.
+For a seekable \f5SF_READ\fP file stream,
+the physical file position is aligned with the logical stream position and,
+if \f5SF_SHARE\fP is on, buffered data is discarded.
+If \f5f\fP is \f5NULL\fP, all streams are synchronized.
+If \f5f\fP is the base of a stream stack (see \f5sfstack()\fP),
+all stacked streams are synchronized.
+Note that a stacked stream can only be synchronized this way.
+If \f5f\fP is in a pool (see \f5sfpool()\fP) but not being the head,
+the pool head is synchronized.
+
+If \f5f\fP has flag \f5SF_IOCHECK\fP, the \f5SF_SYNC\fP event is raised
+before and after synchronization. See \f5sfdisc()\fP for details.
+
+.Ss " int sfpoll(Sfio_t** flist, int n, int timeout)"
+This function polls a set of streams to see if I/O operations
+can be performed on them without blocking.
+This is useful for multiplexing I/O over a set of streams.
+If a stream has a discipline, the exception function may be called
+before and after the stream is polled (see \f5sfdisc()\fP for details).
+After a successful \f5sfpoll()\fP call,
+for each ready stream \f5f\fP, \f5sfvalue(f)\fP returns
+a bit combination of \f5SF_READ\fP and \f5SF_WRITE\fP to tell which I/O
+mode is available. If \f5SF_READ\fP is available, an attempt to read
+a byte will not block. If \f5SF_WRITE\fP is available,
+an attempt to flush will not block.
+\f5sfpoll()\fP returns the number of ready streams or \f5-1\fP on failure.
+.Tp
+\f5flist\fP and \f5n\fP:
+\f5flist\fP is an array of \f5n\fP streams to be polled.
+Upon return, ready streams are moved to the front
+of \f5flist\fP in the same relative order.
+.Tp
+\f5timeout\fP:
+This defines an elapse time in milliseconds
+to wait to see if any stream is ready for I/O.
+If \f5timeout\fP is negative, \f5sfpoll()\fP will block until some stream become ready.
+Note that \f5SF_STRING\fP and normal file streams never block
+and are always ready for I/O.
+If a stream with discipline is being polled and
+its readiness is as yet undetermined (e.g., empty buffer,)
+the discipline exception function will be called with \f5SF_DPOLL\fP
+before querying the operating system.
+
+.Ss " Sfio_t* sfpool(Sfio_t* f, Sfio_t* poolf, int mode)"
+This function manipulates pools of streams.
+In a pool, only one stream is at the head and can have buffered data.
+All other streams in the pool will be synchronized.
+A stream becomes head when it is used for some I/O operation.
+\f5sfpool()\fP returns \f5NULL\fP on failure.
+.Tp
+\f5f\fP and \f5poolf\fP:
+If \f5f\fP is \f5NULL\fP,
+\f5sfpool()\fP simply returns the head of the pool containing \f5poolf\fP.
+If \f5f\fP is not \f5NULL\fP and \f5poolf\fP is \f5NULL\fP,
+\f5f\fP is deleted from its pool.
+In this case, if no other stream from the same pool can become head,
+\f5sfpool()\fP will return \f5NULL\fP; otherwise, it returns some stream
+from the remainder of the pool.
+If both \f5f\fP and \f5poolf\fP are not \f5NULL\fP,
+\f5f\fP is moved from its current pool (if any)
+into the same pool with \f5poolf\fP.
+In this case, \f5poolf\fP is returned.
+.Tp
+\f5mode\fP:
+If \f5poolf\fP is already in a pool, \f5mode\fP is ignored.
+Otherwise, \f5mode\fP should be \f50\fP or \f5SF_SHARE\fP.
+A \f5SF_SHARE\fP pool contains streams with \f5SF_WRITE\fP mode.
+In addition, on change to a new head stream,
+buffered write data of the current head
+is transferred to the new head.
+
+.Ss " int sfpurge(Sfio_t* f)"
+This function discards all buffered data
+unless \f5f\fP is a \f5SF_STRING\fP stream.
+Note that if \f5f\fP is a \f5SF_READ\fP stream based on an unseekable device,
+purged data will not be recoverable.
+If \f5f\fP is a \f5sfpopen\fP-stream opened for both read and write,
+data of both the read and write pipe ends will be purged
+(see \f5sfset()\fP to selectively turn off read or write mode
+if one set of data is to be preserved.)
+After purging, if \f5f\fP has flag \f5SF_IOCHECK\fP,
+the event \f5SF_PURGE\fP is raised.
+\f5sfpurge()\fP returns \f5-1\fP for failure and \f50\fP for success.
+
+.PP
+.Ss "DISCIPLINE, EVENT-HANDLING"
+.PP
+A file stream uses the system calls \f5read(2)\fP, \f5write(2)\fP
+and \f5lseek(2)\fP to read, write and position in the underlying file.
+Disciplines enable application-defined I/O methods including exception handling and
+data pre/post-processing.
+
+.Ss " Sfdisc_t* sfdisc(Sfio_t* f, Sfdisc_t* disc)"
+Each stream has a discipline stack whose bottom is a virtual discipline
+representing the actual system calls.
+\f5sfdisc()\fP manipulates the discipline stack of stream \f5f\fP.
+\f5f\fP will be synchronized before any discipline stack manipulation.
+After a successful discipline stack manipulation,
+the stream I/O position (see \f5sfseek()\fP and \f5sftell()\fP)
+and extent (see \f5sfsize()\fP) are updated
+to reflect that defined by the top discipline.
+\f5sfdisc()\fP returns \f5NULL\fP on failure.
+
+If the value of \f5disc\fP is identical to the value of \f5f\fP,
+then the top discipline on the discipline
+stack is returned without any further action.
+An application can then use this feature of \f5sfdisc()\fP
+and the field \f5disc\fP (below) of the discipline structure
+to traverse the entire discipline stack of a stream \f5f\fP as follows:
+
+.nf
+.ft 5
+ for(disc = sfdisc(f, (Sfdisc_t*)f); disc; disc = disc->disc)
+.ft 1
+.fi
+
+If \f5disc\fP is \f5SF_POPDISC\fP or \f5(Sfdisc_t*)0\fP,
+the top element of the stack, if any, is popped and its address is returned.
+Otherwise, \f5disc\fP is pushed onto the discipline stack.
+In this case, if successful, \f5sfdisc()\fP returns
+the discipline that was pushed down.
+
+Note that a discipline can be used on only one stream at a time.
+An application should take care to allocate different discipline
+structures for use with different streams.
+A discipline structure is of the type \f5Sfdisc_t\fP which
+contains the following public fields:
+
+.nf
+.ft 5
+ Sfread_f readf;
+ Sfwrite_f writef;
+ Sfseek_f seekf;
+ Sfexcept_f exceptf;
+ Sfdisc_t* disc;
+.ft 1
+.fi
+
+.PP
+The first three fields of \f5Sfdisc_t\fP specify alternative I/O functions.
+If any of them is \f5NULL\fP, it is inherited
+from a discipline pushed earlier on the stack.
+Note that a file stream always
+has \f5read(2)\fP, \f5write(2)\fP, \f5lseek(2)\fP and \f5NIL(Sfexcept_f)\fP
+as the \fIlogical bottom discipline\fP.
+Arguments to I/O discipline functions
+have the same meaning as that of the
+functions \f5sfrd()\fP, \f5sfwr()\fP and \f5sfsk()\fP described below.
+.PP
+The exception function, \f5(*exceptf)()\fP announces exceptional events during
+I/O operations.
+It is called as \f5(*exceptf)(Sfio_t* f, int type, Void_t* value, Sfdisc_t* disc)\fP.
+Unless noted otherwise, the return value of \f5(*exceptf)()\fP is used as follows:
+.Tp
+\f5<0\fP:
+The on-going operation shall terminate.
+.Tp
+\f5>0\fP:
+If the event was raised due to an I/O error,
+the error has been repaired and the on-going operation shall continue normally.
+For some events, e.g., \f5SF_DPOLL\fP, the return value may also have
+additional meanings.
+.Tp
+\f5=0\fP:
+The on-going operation performs default actions with respect to the raised event.
+For example, on a reading error or reaching end of file, the top stream of a stack
+will be popped and closed and the on-going operation continue with the new top
+stream.
+.PP
+The argument \f5type\fP of \f5(*exceptf)()\fP
+identifies the particular exceptional event:
+.Tp
+\f5SF_LOCKED\fP:
+The stream cannot be accessed.
+Note that this lock state is not related to the mutex lock
+that protects a stream from multiple accesses by different threads
+(see section THREAD SAFETY). Rather, the stream was frozen by
+certain operations such as \f5sfreserve()\fP or \f5sfstack()\fP.
+Thus, a stream can be in this state even if the application is uni-threaded.
+.Tp
+\f5SF_READ\fP, \f5SF_WRITE\fP:
+These events are raised around reading and writing operations.
+
+If \f5SF_IOCHECK\fP is on, \f5SF_READ\fP and \f5SF_WRITE\fP
+are raised immediately before \f5read(2) and write(2)\fP calls.
+In this case, \f5*((ssize_t*)value)\fP is the amount of data to be processed.
+The return value of \f5(*exceptf)()\fP, if negative,
+indicates that the stream is not ready for I/O
+and the calling operation will abort with failure.
+If it is positive, the stream is ready for I/O
+but the amount should be restricted to the amount specified by this value.
+If the return value is zero, the I/O operation is carried out normally.
+
+\f5SF_READ\fP and \f5SF_WRITE\fP are also raised on operation failures.
+In such a case, \f5*((ssize_t*)value)\fP
+is the return value from the failed operation.
+.Tp
+\f5SF_SEEK\fP:
+This event is raised when a seek operation fails.
+.Tp
+\f5SF_NEW\fP, \f5SF_CLOSING\fP (\f5SF_CLOSE\fP), \f5SF_FINAL\fP:
+These events are raised during a stream closing.
+\f5SF_NEW\fP is raised for a stream about to be closed to be renewed (see \f5sfnew()\fP).
+\f5SF_CLOSING\fP is raised for a stream about to be closed.
+\f5SF_FINAL\fP is raised after a stream has been closed and before
+its space is to be destroyed (see \f5sfclose()\fP).
+For these events, a non-zero return value from \f5(*exceptf)()\fP causes
+\f5sfclose()\fP to return immediately with the same value.
+.Tp
+\f5SF_DPUSH\fP, \f5SF_DPOP\fP, \f5SF_DBUFFER\fP:
+Events \f5SF_DPUSH\fP and \f5SF_DPOP\fP are raised when a
+discipline is about to be pushed or popped.
+\f5(Sfdisc_t*)value\fP is the to-be top discipline, if any.
+
+A stream buffer is always synchronized before pushing or popping a discipline.
+If this synchronization fails, \f5SF_DBUFFER\fP will be raised with
+\f5*((size_t*)value)\fP being the amount of data still in the buffer.
+If the return value of \f5exceptf\fP is non-negative,
+the push or pop operation will continue normally;
+otherwise, \f5sfdisc()\fP returns failure.
+.Tp
+\f5SF_DPOLL\fP:
+This event is raised by
+\f5sfpoll()\fP to see if the stream is ready for I/O.
+\f5*((int*)value)\fP indicates a time-out interval to wait.
+A negative return value from the exception function means blocking.
+A zero return value means that \f5sfpoll()\fP should
+query the underlying file descriptor.
+A positive return value means non-blocking. In addition,
+this value will be a bit combination of \f5SF_READ\fP and \f5SF_WRITE\fP
+to indicate what I/O modes are ready.
+.Tp
+\f5SF_READY\fP:
+This event is raised by \f5sfpoll()\fP for each ready stream.
+The third argument to the event handler is an integer composed with
+the two bits \f5SF_READ\fP and \f5SF_WRITE\fP to indicate which
+I/O modes are ready.
+.Tp
+\f5SF_SYNC\fP, \f5SF_PURGE\fP:
+If \f5SF_IOCHECK\fP is set,
+these events are raised respectively for a \f5sfsync()\fP or \f5sfpurge()\fP call.
+In each case, the respective event is raised once before the appropriate
+operation (synchronization or purging) with \f5((int)value)\fP being \f51\fP
+and once after with \f5((int)value)\fP being \f50\fP.
+Note that \f5sfsync()\fP is called for each
+\f5SF_WRITE\fP or \f5SF_SHARE|SF_READ\fP stream on closing.
+
+.Tp
+\f5SF_ATEXIT\fP:
+This event is raised for each open stream before the process exits.
+
+.Ss " int sfraise(Sfio_t* f, int type, Void_t* data)"
+If \f5f\fP is non-\f5NULL\fP, \f5sfraise()\fP calls all exception handlers
+of \f5f\fP with the event \f5type\fP and associated \f5data\fP.
+If an exception handler returns a non-zero value,
+\f5sfraise()\fP immediate returns the same value.
+Application-defined events should start from the value \f5SF_EVENT\fP
+so as to avoid confusion with system-defined events,
+\f5sfraise()\fP returns \f50\fP on success and \f5-1\fP on failure.
+
+If \f5f\fP is \f5NULL\fP, \f5sfraise()\fP iterates over all streams
+and raise events as described above. In this case,
+\f5sfraise()\fP returns \f50\fP on success and a negative value
+on failure. The absolute value of the return value tells how many
+streams failed on raising the given event.
+
+.Ss " ssize_t sfrd(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)"
+.Ss " ssize_t sfwr(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)"
+.Ss " Sfoff_t sfsk(Sfio_t* f, Sfoff_t offset, int type, Sfdisc_t* disc)"
+These functions provides safe methods for a discipline I/O function to invoke
+earlier discipline I/O functions and to properly handle exceptions.
+They should not be used in any other context.
+\f5sfrd()\fP and \f5sfwr()\fP return the number of bytes read or written.
+\f5sfsk()\fP returns the new seek position.
+On error, all three functions return a negative value which should be \f5-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 \f5f\P so that its extent is \f5size\fP.
+If the stream corresponds to a file, the file size is set to \f5size\fP
+via the system call \f5ftruncate()\fP.
+When a stream is made larger, the new data space is filled with zero's.
+\f5sfresize()\fP returns \f50\fP on success and a negative value on failure.
+
+.Ss " int sfset(Sfio_t* f, int flags, int set)"
+This function sets control flags for the stream \f5f\fP.
+It returns the previous set of flags or \f50\fP on error.
+
+Settable flags are:
+\f5SF_READ\fP, \f5SF_WRITE\fP, \f5SF_IOCHECK\fP,
+\f5SF_LINE\fP, \f5SF_SHARE\fP, \f5SF_PUBLIC\fP, \f5SF_MALLOC\fP and
+\f5SF_STATIC\fP.
+Note that \f5SF_READ\fP and \f5SF_WRITE\fP can be turned on or off only
+if the stream was opened as \f5SF_READ|SF_WRITE\fP.
+Turning off one of them means that the stream is to be treated exclusively
+in the other mode. It is not possible to turn off both.
+If legal, an attempt to turn on either \f5SF_READ\fP or \f5SF_WRITE\fP
+will cause the stream to be in the given I/O mode.
+.Tp
+\f5set == 0:\fP
+If \f5flags\fP is zero, the current set of flags is simply returned.
+Note that when a stream is first opened, not
+all of its flags are initialized yet (more below). If \f5flags\fP is
+non-zero, an attempt is made to turn off the specified flags.
+.Tp
+\f5set != 0:\fP
+If \f5flags\fP is zero, the stream is initialized if not yet done so.
+Then the current set of flags is returned.
+If \f5flags\fP is non-zero, an attempt is made to turn on the
+specified flags.
+
+.Ss " int sfsetfd(Sfio_t* f, int fd)"
+This function changes the file descriptor of \f5f\fP.
+Before a change is realized,
+\f5(*notify)(f,SF_SETFD,newfd)\fP (see \f5sfnotify()\fP) is called.
+\f5sfsetfd()\fP returns \f5-1\fP on failure and the new file descriptor on success.
+.Tp
+\f5fd >= 0\fP:
+If the current file descriptor is non-negative,
+it will be changed using \f5dup(3)\fP to a value larger or equal to \f5fd\fP.
+Upon a successful change, the previous file descriptor will be closed.
+If the current file descriptor is negative, it will be set to \f5fd\fP and
+the stream will be reinitialized.
+.Tp
+\f5fd < 0\fP:
+The stream is synchronized (see \f5sfsync()\fP) and its
+file descriptor will be set to this value.
+Then, except for \f5sfclose()\fP, the stream will be inaccessible
+until a future \f5sfsetfd()\fP call resets the file descriptor to a non-negative value.
+Thus, \f5sfsetfd(f,-1)\fP can be used to avoid closing the file descriptor
+of \f5f\fP when \f5f\fP is closed.
+
+.Ss " Sfio_t* sfstack(Sfio_t* base, Sfio_t* top)"
+This function stacks or unstacks stream.
+Every stream stack is identified by a base stream
+via which all I/O operations are performed.
+However, an I/O operation always takes effect on the top stream.
+If the top stream reaches the end of file or
+has an unrecoverable error condition,
+it is automatically popped and closed
+(see also \f5sfdisc()\fP for alternative handling of these conditions).
+.Tp
+\f5base\fP:
+This is the base stream of the stack.
+If it is \f5NULL\fP, \f5sfstack()\fP does nothing and returns \f5top\fP.
+.Tp
+\f5top\fP:
+If this is \f5SF_POPSTACK\fP or \f5(Sfio_t*)0\fP,
+the stack is popped and \f5sfstack()\fP returns the popped stream.
+Otherwise, \f5top\fP is pushed on top of the stack identified by \f5base\fP
+and \f5sfstack()\fP returns the \f5base\fP stream.
+
+.Ss " Sfio_t* sfswap(Sfio_t* f1, Sfio_t* f2)"
+This function swaps contents of \f5f1\fP and \f5f2\fP.
+This fails if either stream is in a stream stack but not being a base stream.
+If \f5f2\fP is \f5NULL\fP, a new stream is constructed as a duplicate of \f5f1\fP.
+\f5sfswap()\fP returns \f5f2\fP or \f5f1\fP duplicate on success and
+\f5NULL\fP on failure.
+
+.PP
+.Ss "STREAM INFORMATION"
+.PP
+.Ss " Sfoff_t sfsize(Sfio_t* f)"
+This function returns the size of stream \f5f\fP (see \f5sfnew()\fP).
+If \f5f\fP is not seekable or if its size is not determinable,
+\f5sfsize()\fP returns \f5-1\fP.
+
+.Ss " Sfoff_t sftell(Sfio_t* f)"
+This function returns the current I/O position in stream \f5f\fP.
+Note that if \f5f\fP is \f5SF_APPEND\fP
+and a writing operation was just performed,
+the current I/O position is at the physical end of file.
+If \f5f\fP is unseekable, \f5sftell\fP returns the number of bytes
+read from or written to \f5f\fP.
+See also \f5sfungetc()\fP.
+
+.Ss " ssize_t sfvalue(Sfio_t* f)"
+This function returns the string or buffer length
+for \f5sfreserve()\fP, \f5sfsetbuf()\fP, and \f5sfgetr()\fP.
+
+.Ss " int sffileno(Sfio_t* f)"
+This function returns the file descriptor of stream \f5f\fP.
+
+.Ss " int sfstacked(Sfio_t* f)"
+This function returns a non-zero value
+if stream \f5f\fP has been stacked.
+
+.Ss " int sfeof(Sfio_t* f)"
+.Ss " int sferror(Sfio_t* f)"
+.Ss " int sfclrerr(Sfio_t* f)"
+\f5sfeof()\fP tells whether or not the stream has an end-of-file condition.
+\f5sferror()\fP tells whether or not the stream has an error condition.
+\f5sfclrerr()\fP clears both end-of-file and error conditions.
+The end-of-file and error conditions are also cleared on an I/O operation.
+
+.Ss " int sfclrlock(Sfio_t* f)"
+This function restores the stream back to a normal state.
+This means clearing locks and possibly throwing away unprocessed data.
+As such, this operation is unsafe and should be used with care.
+For example, it may be used before a long jump (\f5longjmp(3)\fP)
+out of some discipline I/O function to restore the internal stream states.
+\f5sfclrlock()\fP returns the current set of flags.
+
+.Ss " int sfnotify((void(*)notify)(Sfio_t*, int, void*) )"
+This sets a function \f5(*notify)()\fP to be called
+as \f5(*notify)(f, type, data)\fP on various stream events.
+Arguments \f5type\fP and \f5data\fP indicate the reason for the call and accompanying data:
+.Tp
+\f5SF_NEW\fP:
+\f5f\fP is being opened and \f5data\fP is the underlying file descriptor.
+.Tp
+\f5SF_CLOSING\fP (\f5SF_CLOSE\fP):
+\f5f\fP is the stream being closed and \f5data\fP is the underlying file descriptor.
+.Tp
+\f5SF_SETFD\fP:
+The file descriptor of \f5f\fP is being changed to the one
+defined by \f5data\fP (see \f5sfsetfd()\fP.)
+.Tp
+\f5SF_READ\fP:
+An attempt to change \f5f\fP to read mode failed.
+\f5data\fP is the file descriptor of the stream.
+.Tp
+\f5SF_WRITE\fP:
+An attempt to change \f5f\fP to write mode failed.
+\f5data\fP is the file descriptor of the stream.
+.Tp
+\f5SF_MTACCESS\fP:
+When a notifying function was registered (see \f5sfnotify()\fP),
+every Sfio call on a stream with flag \f5SF_MTSAFE\fP will
+invoke the notifying function
+once on entry after the stream is locked
+as \f5(*notify)(f, SF_MTACCESS, Sfio_t** fp), and
+once on return before unlocking as
+as \f5(*notify)(f, SF_MTACCESS, (Sfio_t**)0).
+In the call entry case,
+the notification function could use the argument \f5fp\fP
+to set a stream that would be used for performing the actual I/O operation.
+In this way, certain global streams such as the standard streams \f5sfstdin\fP,
+\f5sfstdout\fP and \f5sfstderr\fP could be made to act differently when used
+in different streams.
+
+.Ss " int sfwalk(Sfwalk_f walkf, Void_t* data, int type)"
+This function invokes \f5(*walkf)(f, data)\fP on every open stream \f5f\fP
+whose flags as defined by \f5sfset()\fP contains all bit flags given in \f5type\fP.
+On such a call, if the return value is negative, \f5sfwalk()\fP will terminate.
+\f5sfwalk()\fP returns 0 if no stream was processed.
+Otherwise, it returns the return value from the last invocation of \f5walkf()\fP.
+
+As an example, the call \f5sfwalk(walkf, data, SF_READ)\fP will iterate over all streams
+opened for reading. Similarly, \f5sfwalk(walkf, data, SF_READ|SF_WRITE)\fP
+iterates over all streams opened for both reading and writing.
+Lastly, \f5sfwalk(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
+of memory used by \f5sfgetr()\fP. A different memory bound
+can be set via \f5sfmaxr()\fP. While a positive \f5maxr\fP hints to \f5sfgetr()\fP
+to use only about that much memory to construct a record, a non-positive bound
+allows \f5sfgetr()\fP to use as much memory as necessary.
+\f5sfmaxr()\fP sets the value only if \f5set\fP is non-zero.
+It returns the value before setting or the current value if not setting.
+
+.Ss " ssize_t sfslen()"
+This function returns the length of a string just constructed
+by \f5sfsprintf()\fP or \f5sfprints()\fP. See also \f5sfvalue()\fP.
+
+.Ss " int sfulen(Sfulong_t v)"
+.Ss " int sfllen(Sflong_t v)"
+.Ss " int sfdlen(Sfdouble_t v)"
+These functions return respectively the number of bytes required to code the
+\f5Sfulong_t\fP, \f5Sflong_t\fP or \f5Sfdouble_t\fP value \f5v\fP by \f5sfputu()\fP,
+\f5sfputl()\fP or \f5sfputd()\fP.
+
+.Ss " ssize_t sfpkrd(int fd, char* buf, size_t n, int rsc, long tm, int action)"
+This function acts directly on the file descriptor \f5fd\fP.
+It does a combination of peeking on incoming data and a time-out read.
+Upon success, it returns the number of bytes received.
+A return value of \f50\fP means that the end-of-file condition has been detected.
+A negative value represents an error.
+.Tp
+\f5buf\fP, \f5n\fP:
+These define a buffer and its size to read data into.
+.Tp
+\f5rsc\fP:
+If \f5>=0\fP, this defines a record separator.
+If the last returned byte is not the record separator, then
+the read data did not contain a complete record. Otherwise,
+it contains one or more records.
+See also \f5action\fP below.
+.Tp
+\f5tm\fP:
+If \f5>=0\fP, this defines a time interval in milliseconds to wait for incoming data.
+.Tp
+\f5action\fP:
+If \f5action > 0\fP, \f5sfpkrd()\fP will peek on incoming data but
+will not read past it. Therefore, a future \f5sfpkrd()\fP or \f5read(2)\fP will see
+the same data again.
+If \f5action <= 0\fP, \f5sfpkrd()\fP will not peek and there are two cases.
+If \f5rsc < 0\fP, an attempt is made to read \f5n\fP bytes.
+If \f5rsc >= 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 \f5sfio.h\fP which defines an abbreviated \f5Sfio_t\fP
+structure without certain fields private to Sfio.
+However, there are times (e.g., debugging)
+when an application may require more details about the full \f5Sfio_t\fP structure.
+In such cases, the header file \f5sfio_t.h\fP can be used in place of \f5sfio.h\fP.
+Note that an application doing this will become sensitive to changes
+in the internal architecture of Sfio.
+
+.Ss " #define SFNEW(buf,size,file,flags,disc)"
+This macro function is defined in \f5sfio_t.h\fP for
+use in static initialization of an \f5Sfio_t\fP structure.
+It requires five arguments:
+.Tp
+\f5buf, size\fP:
+These define a buffer and its size.
+.Tp
+\f5file\fP:
+This defines the underlying file descriptor if any.
+.Tp
+\f5flags\fP:
+This is composed from bit flags described above.
+.Tp
+\f5disc\fP:
+This defines a discipline if any.
+
+.PP
+.Ss "EXAMPLE DISCIPLINES"
+.PP
+The below functions create disciplines and insert them into
+the given streams \f5f\fP. These functions return \f50\fP
+on success and \f5-1\fP on failure.
+
+.Ss "int sfdcdio(Sfio_t* f, size_t bufsize)"
+This creates a discipline that uses the direct IO feature
+available on file systems such as SGI's XFS to speed up IO.
+The argument \f5bufsize\fP suggests a buffer size to use for data transfer.
+
+.Ss "int sfdcdos(Sfio_t* f)"
+This creates a discipline to read DOS text files.
+It basically transforms pairs of \er\en to \en.
+
+.Ss "int sfdcfilter(Sfio_t* f, const char* cmd)"
+This creates a discipline that sends data from \f5f\fP
+to the given command \f5cmd\fP to process, then reads back the processed data.
+
+.Ss "int sfdcseekable(Sfio_t* f)"
+This creates a discipline that makes an unseekable reading stream seekable.
+
+.Ss "int sfdcslow(Sfio_t* f)"
+This creates a discipline that makes all Sfio operations return immediately
+on interrupts. This is useful for dealing with slow devices.
+
+.Ss "int sfdcsubstream(Sfio_t* f, Sfio_t* parent, Sfoff_t offset, Sfoff_t extent)"
+This creates a discipline that makes \f5f\fP acts as if it
+corresponds exactly to the subsection of \f5parent\fP
+starting at \f5offset\fP with size \f5extent\fP.
+
+.Ss "int sfdctee(Sfio_t* f, Sfio_t* tee)"
+This creates a discipline that copies to the stream \f5tee\fP
+any data written to \f5f\fP.
+
+.Ss "int sfdcunion(Sfio_t* f, Sfio_t** array, int n)"
+This creates a discipline that makes \f5f\fP act as if it is
+the concatenation of the \f5n\fP streams given in \f5array\fP.
+
+.Ss "int sfdclzw(Sfio_t* f)"
+This creates a discipline that would decompress data in \f5f\fP.
+The stream \f5f\fP should have data from a source compressed by
+the Unix \fBcompress\fP program.
+
+.Ss "int sfdcgzip(Sfio_t* f, int opt)"
+This creates a discipline for reading/writing data compressed by zlib.
+The argument \f5opt\fP defines the optimization level.
+
+.PP
+.Ss "STDIO-COMPATIBILITY"
+.PP
+Sfio provides compatibility functions for all various popular
+Stdio implementations at source and binary level.
+The source Stdio-compatibility interface
+provides the header file \f5stdio.h\fP that defines
+a set of macros or inlined functions to map Stdio calls to Sfio ones.
+This mapping may benignly extend or change the meaning of certain
+original Stdio operations. For example, the Sfio's version of
+\f5popen()\fP allows a coprocess to be opened for both reading and writing
+unlike the original call which only allows a coprocess to be opened for a single mode.
+Similarly, the Sfio's \f5fopen()\fP call can be used to create
+string streams in addition to file streams.
+.PP
+The standard streams \f5stdin\fP, \f5stdout\fP and \f5stderr\fP
+are mapped via \f5#define\fP to \f5sfstdin\fP, \f5sfstdout\fP and \f5sfstderr\fP.
+The latter are typically declared of the type \f5Sfio_t*\fP.
+Certain older Stdio applications require these to be declared
+as addresses of structures so that static initializations of
+the sort ``\f5FILE*\ f\ =\ stdin;\fP'' would work.
+Such applications should use the compile time flag \f5SF_FILE_STRUCT\fP
+to achieve the desired effect.
+.PP
+The binary Stdio-compatibility libraries, \f5libstdio.a\fP and \f5libstdio-mt.a\fP,
+provide complete implementations of Stdio functions suitable
+for linking applications already compiled with native header \f5stdio.h\fP.
+These functions are also slightly altered or extended
+as discussed above.
+.PP
+Below are the supported Stdio functions:
+.PP
+.nf
+.ft 5
+FILE* fopen(const char* file, const char* mode);
+FILE* freopen(const char* file, const char* mode, FILE* stream);
+FILE* fdopen(int filedesc, const char* mode);
+FILE* popen(const char* command, const char* mode);
+FILE* tmpfile();
+int fclose(FILE* stream);
+int pclose(FILE* stream);
+
+void flockfile(FILE* stream)
+int ftrylockfile(FILE* stream)
+void funlockfile(FILE* stream)
+
+void setbuf(FILE* stream, char* buf);
+int setvbuf(FILE* stream, char* buf, int mode, size_t size);
+void setbuffer(FILE* stream, char* buf, size_t size);
+int setlinebuf(FILE* stream);
+int fflush(FILE* stream);
+int fpurge(FILE* stream);
+
+int fseek(FILE* stream, long offset, int whence);
+void rewind(FILE* stream);
+int fgetpos(FILE* stream, fpos_t* pos);
+int fsetpos(FILE* stream, fpos_t* pos);
+long ftell(FILE* stream);
+
+int getc(FILE* stream);
+int fgetc(FILE* stream);
+int getchar(void);
+int ungetc(int c, FILE* stream);
+int getw(FILE* stream);
+char* gets(char* s);
+char* fgets(char* s, int n, FILE* stream);
+size_t fread(Void_t* ptr, size_t size, size_t nelt, FILE* stream);
+
+int putc(int c, FILE* stream);
+int fputc(int c, FILE* stream);
+int putchar(int c);
+int putw(int w, FILE* stream);
+int puts(const char* s, FILE* stream);
+int fputs(const char* s, FILE* stream);
+size_t fwrite(const Void_t* ptr, size_t size, size_t nelt, FILE* stream);
+
+int fscanf(FILE* stream, const char* format, ...);
+int vfscanf(FILE* stream, const char* format, va_list args);
+int _doscan(FILE* stream, const char* format, va_list args);
+int scanf(const char* format, ...);
+int vscanf(const char* format, va_list args);
+int sscanf(const char* s, const char* format, ...);
+int vsscanf(const char* s, const char* format, va_list args);
+
+int fprintf(FILE* stream, const char* format, ...);
+int vfprintf(FILE* stream, const char* format, va_list args);
+int _doprnt(FILE* stream, const char* format, va_list args);
+int printf(const char* format, ...);
+int vprintf(const char* format, va_list args);
+int sprintf(const char* s, const char* format, ...);
+int snprintf(const char* s, int n, const char* format, ...);
+int vsprintf(const char* s, const char* format, va_list args);
+int vsnprintf(const char* s, int n, const char* format, va_list args);
+
+int feof(FILE* stream);
+int ferror(FILE* stream);
+int clearerr(FILE* stream);
+.ft 1
+.fi
+
+.PP
+.Ss "RECENT CHANGES"
+.PP
+A few exception types have been added. In particular, exception handlers shall
+be raised with \f5SF_LOCKED\fP on accessing a stream frozen either by
+an ongoing operation or a previous operation (e.g., \f5sfgetr()\fP).
+Before a process exits, the event \f5SF_ATEXIT\fP is raised for each open stream.
+.PP
+A number of disciplines were added for various processing functions.
+Of interests are disciplines to use the direct I/O feature on IRIX6.2,
+read DOS text files, and decompress files compressed by Unix \fIcompress\fP.
+.PP
+Various new stream and function flags have been added. For example,
+the third argument of \f5sfgetr()\fP is now a set of bit flags and not
+just a three-value object. However, the old semantics of this argument
+of \f5sfgetr()\fP is still supported.
+.PP
+The \f5sfopen()\fP call has been extended so that sfopen(f,NULL,mode) can be
+used to changed the mode of a file stream before any I/O operations.
+This is most useful for changing the modes of the standard streams.
+.PP
+The buffering strategy has been significantly enhanced for streams
+that perform many seek operations. Also, the handling of stream and
+file positions have been better clarified so that applications that
+share file descriptors across streams and/or processes can be sure that
+the file states will be consistent.
+.PP
+The strategy for mapping between Sfio and Stdio streams in the binary
+compatibility package has been significantly enhanced for efficiency.
+For most platforms, the mapping is now constant time per look-up.
+.PP
+The \f5SF_BUFCONST\fP flag was deleted. This is largely unused anyway.
+.PP
+The library can be built for thread-safety. This is based largely on
+Posix pthread mutexes except for on UWIN where native Windows APIs
+are used.
+.PP
+The functions \f5sfgetm()\fP and \f5sfputm()\fP were added to encode
+unsigned integer values with known ranges.
+.PP
+The flag \f5SF_APPEND\fP is identical to \f5SF_APPENDWR\fP.
+However it conflicts with a different token of the same name
+defined in the system header \f5stat.h\fP of BSDI Unix systems.
+On such systems, we shall not define \f5SF_APPEND\fP and this
+symbol may be removed in a future release.
+.PP
+Similarly, the exception \f5SF_CLOSE\fP is identical to \f5SF_CLOSING\fP.
+However it conflicts with a different token of the same name
+defined in the system header \f5socket.h\fP of AIX Unix systems.
+On such systems, we shall not define \f5SF_CLOSE\fP and this
+symbol may be removed in a future release.
+.PP
+The printing and scanning functions were extended to handle multibyte characters
+and to conform to the C99 standard.
+.PP
+The function \f5sfpoll()\fP was rehauled to make it useful
+for writing servers that must commnunicate with multiple streams
+without blocking.
+.PP
+The formatting pattern \f5%c\fP for \f5sf*printf\fP was extended
+to allow the flag \f5#\fP to print unprintable character values
+using the C convention. For example, \f5%#c\fP prints the octal value 012
+as \f5\\n\fP.
+
+.SH AUTHORS
+Kiem-Phong Vo, kpv@research.att.com,
+.br
+David G. Korn, dgk@research.att.com, and
+.br
+Glenn S. Fowler, gsf@research.att.com.
diff --git a/src/lib/libast/man/sig.3 b/src/lib/libast/man/sig.3
new file mode 100644
index 0000000..db41a2b
--- /dev/null
+++ b/src/lib/libast/man/sig.3
@@ -0,0 +1,75 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH SIG 3
+.SH NAME
+sig \- signal interface routines
+.SH SYNOPSIS
+.L "#include <ast.h>"
+.L "#include <sig.h>"
+.sp
+.L "int sigunblock(int sig);"
+.L "int sigcritical(int op);"
+.SH DESCRIPTION
+.L sigunblock
+is called to
+unblocks the signal
+.L sig
+from within a handler currently servicing
+.LR sig .
+.PP
+.L sigcritical
+controls a critical region for the
+.LR SIGINT ,
+.L SIGQUIT
+and
+.L SIGHUP
+signals.
+.L "op > 0"
+pushes the region,
+.L "op == 0"
+pops the region, and
+.L "op < 0"
+returns non-zero if any signals are being held in the current
+critical region.
+Signal critical regions may be nested.
+The current critical region level is returned,
+.L \-1
+on error.
+.SH "SEE ALSO"
+signal(2)
diff --git a/src/lib/libast/man/spawnveg.3 b/src/lib/libast/man/spawnveg.3
new file mode 100644
index 0000000..3dfd424
--- /dev/null
+++ b/src/lib/libast/man/spawnveg.3
@@ -0,0 +1,97 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH SPAWNVEG 3
+.SH NAME
+spawnveg \- process spawn with process group and session control
+.SH SYNOPSIS
+.L "#include <ast.h>"
+.sp
+.L "int spawnveg(const char* command, char** argv, char** envv, pid_t pgid);"
+.SH DESCRIPTION
+.L spwanveg
+combines
+.IR fork (2),
+.IR exec (2),
+.IR setpgid (2)
+and
+.IR setsid (2)
+into a single call.
+.PP
+.LR command ,
+.L argv
+and
+.L envv
+are as in
+.IR execve (2).
+.L pgid
+controls the new process group and session:
+.TP
+.L <0
+The new process becomes a session leader.
+is called in the child context.
+.TP
+.L 0
+The new process is in the callers process group.
+.TP
+.L 1
+The new process becomes a process group leader.
+.TP
+.L >1
+The new process joins the process group
+.IR pgid .
+.SH COMMENTS
+It is possible to code all process creation (except for
+.IR vfork (2)
+hack like in
+.IR csh (1))
+using
+.LR spawnveg .
+The
+.IR proc (3)
+routines and
+.IR ksh (1)
+do this on systems that don't support
+.IR fork (2).
+This makes porting to NT and Windows a snap: a simple
+.IR iffe (1)
+probe provides a
+.L spawnveg
+implementation using the NT or Windows process primitives.
+.SH "SEE ALSO"
+fork(2), exec(2), setpgid(2), setsid(2), spawnve(2)
diff --git a/src/lib/libast/man/stak.3 b/src/lib/libast/man/stak.3
new file mode 100644
index 0000000..5feac69
--- /dev/null
+++ b/src/lib/libast/man/stak.3
@@ -0,0 +1,169 @@
+.fp 5 CW
+.TH STAK 3
+.SH NAME
+\fBstak\fR \- data stack storage library (obsolete: use \fBstk\fR instead)
+.SH SYNOPSIS
+.ta .75i 1.5i 2.25i 3i 3.75i 4.5i 5.25i 6i
+.PP
+.nf
+\f5
+#include <stak.h>
+
+Stak_t *stakcreate(int \fIflags\fP);
+Stak_t *stakinstall(Stak_t *\fIstack\fP, char *(\fIoverflow\fP)(int));
+int stakdelete(Stak_t *\fIstack\fP);
+void staklink(Stak_t *\fIstack\fP)
+
+char *stakalloc(unsigned \fIsize\fP);
+char *stakcopy(const char *\fIstring\fP);
+char *stakset(char *\fIaddress\fP, unsigned \fIoffset\fP);
+
+char *stakseek(unsigned \fIoffset\fP);
+int stakputc(int \fIc\fP);
+int stakputs(const char *\fIstring\fP);
+int stakwrite(const char *\fIaddress\fP, unsigned \fIsize\fP);
+int staktell(void);
+char *stakptr(unsigned \fIoffset\fP);
+char *stakfreeze(unsigned \fIextra\fP);
+\fR
+.fi
+.SH DESCRIPTION
+.PP
+\f5stak\fP is a package of routines designed to provide efficient
+stack oriented dynamic storage.
+A stack abstraction consists of an ordered list of contiguous
+memory regions, called stack frames, that can hold objects of
+arbitrary size.
+A stack is represented by the type \f5Stak_t\fP
+defined in header \f5<stak.h>\fP.
+At any instant there is one active stack.
+Variable size objects can be
+added to the active stack
+and programs can reference these objects directly with pointers.
+In addition, the last object on the stack
+(referred to here as the current object)
+can be built incrementally.
+The current object has an associated offset that determines its
+current size.
+While the current object is being built incrementally,
+its location might
+change so that it is necessary to reference the object with
+relative offsets ranging from zero to the current offset of the object.
+.PP
+There is a preset initial active stack.
+To use an additional stack, it is necessary to create it and to
+install it as the active stack.
+A stack is created with the \f5stakcreate\fP() function.
+A \fIflags\fP argument of \f5STAK_SMALL\fP indicates that unused
+space on the stack should be freed whenever this stack ceases
+to be the active stack.
+If successful,
+\f5stakcreate\fP() returns a pointer to a stack whose reference
+count is 1.
+Otherwise, \f5stakcreate\fP() returns a null pointer.
+The \f5staklink\fP() function increases the reference count for the
+given \fIstack\fP.
+The \f5stakinstall\fP() function
+makes the specified \fIstack\fP the active stack and returns a pointer
+to the previous active stack.
+When the \fIoverflow\fP argument is not null,
+it specifies a function that will
+be called whenever \f5malloc\fP(3) fails while trying to grow the
+stack.
+The \fIoverflow\fP function will be called with the size that was passed
+to \f5malloc\fP(3).
+The \fIoverflow\fP function can call \f5exit\fP(3), call \f5longjmp\fP(3)
+or return.
+If the \f5overflow\fP function returns,
+it must return a pointer to a memory region of the given size.
+The default action is to write an error to standard error and to
+call \f5exit\fP(2) with a non-zero exit value.
+When \fIstack\fP is a null pointer,
+the active stack is not changed
+but the \fIoverflow\fP function for the active stack can be changed
+and a pointer to the active stack is returned.
+The \f5stakdelete\fP() function decrements the reference count and
+frees the memory associated with
+the specified stack
+when the reference count is zero.
+The effect of subsequent references to objects
+on the stack are undefined.
+.PP
+The
+\f5stakalloc\fP() function returns an aligned pointer to space on the
+active stack that can be used to hold any object of the given \fIsize\fP.
+\f5stakalloc\fP() is similar to \f5malloc\fP(3) except that individual
+items returned by \f5stakalloc\fP() can not be freed.
+\f5stakalloc\fP() causes the offset of the current object to be set to
+zero.
+.PP
+The
+\f5stakcopy\fP() function copies the given string onto the stack
+and returns a pointer to the \fIstring\fP on the stack.
+\f5stakcopy\fP() causes the offset of the current object to be set to
+zero.
+.PP
+The \f5stakset\fP() function finds the frame containing the given
+\fIaddress\fP, frees all frames that were created after the one containing
+the given \fIaddress\fP, and sets the current object to the given
+\fIaddress\fP.
+The top of the current object is set to \fIoffset\fP bytes from
+current object.
+If \fIaddress\fP is not the address of an object on the
+stack the result is undefined.
+.PP
+The remaining functions are used to build the current object incrementally.
+An object that is built incrementally on the stack will
+always occupy contiguous memory within a stack frame but
+until \f5stakfreeze\fP() is called,
+the location in memory for the object can change.
+There is a current offset associated with the current object that
+determines where subsequent operations apply.
+Initially, this offset is zero, and the offset changes as a result
+of the operations you specify.
+The \f5stakseek\fP() function is used set the offset for the
+current object.
+The \fIoffset\fP argument to \f5stakseek\fP() specifies the new
+offset for the current object.
+The frame will be extended or moved
+if \f5offset\fP causes the new current offset to extend beyond the
+current frame.
+\f5stakseek\fP() returns a pointer to the beginning of the current object.
+The \f5staktell\fP() function gives the offset of the current object.
+.PP
+The \f5stakputc\fP() function adds a given character to the current object
+on the stack.
+The current offset is advanced by 1.
+The \f5stakputs\fP() function appends the given \fIstring\fP onto the current
+object in the stack and returns the length of the string.
+The current offset is advanced by the length of the string.
+The \f5stakwrite\fP() function appends the given \fIsize\fP byte memory
+region starting at \fIaddress\fP onto the current
+object in the stack and advances the current offset by \fIsize\fP.
+The current offset is returned.
+.PP
+The \f5stakptr\fP() function converts the given \f5offset\fP
+for the current object into a memory address on the stack.
+This address is only valid until another stack operation is given.
+The result is not defined if \fIoffset\fP exceeds the size of the current
+object.
+The \f5stakfreeze\fP()
+function terminates the current object on the
+stack and returns a pointer to the beginning of this object.
+If \fIextra\fP is non-zero, \fIextra\fP bytes are added to the stack
+before the current object is terminated. The first added byte will
+contain zero and the contents of the remaining bytes are undefined.
+.PP
+.SH HISTORY
+The
+\f5stak\fP
+interface was derived from similar routines in the KornShell code
+that is used for building parse trees and carrying out expansions.
+It provides an efficient mechanism for grouping dynamically allocated
+objects so that they can be freed all at once rather than individually.
+.SH AUTHOR
+ David Korn
+.SH SEE ALSO
+\f5exit(2)\fP
+\f5longjmp(3)\fP
+\f5malloc(3)\fP
diff --git a/src/lib/libast/man/stk.3 b/src/lib/libast/man/stk.3
new file mode 100644
index 0000000..3e65821
--- /dev/null
+++ b/src/lib/libast/man/stk.3
@@ -0,0 +1,165 @@
+.fp 5 CW
+.TH STK 3
+.SH NAME
+\fBstk\fR \- data stack storage library
+.SH SYNOPSIS
+.ta .75i 1.5i 2.25i 3i 3.75i 4.5i 5.25i 6i
+.PP
+.nf
+\f5
+#include <stk.h>
+
+Stk_t *stkopen(int \fIflags\fP);
+Stk_t *stkinstall(Stk_t *\fIstack\fP, char *(\fIoverflow\fP)(int));
+int stkclose(Stk_t *\fIstack\fP);
+void stklink(Stk_t *\fIstack\fP)
+
+char *stkalloc(Stk_t *\fIstack\fP, unsigned \fIsize\fP);
+char *stkcopy(Stk_t *\fIstack\fP, const char *\fIstring\fP);
+char *stkset(Stk_t *\fIstack\fP, char *\fIaddress\fP, unsigned \fIoffset\fP);
+
+char *stkseek(Stk_t *\fIstack\fP, unsigned \fIoffset\fP);
+int stktell(Stk_t *\fIstack\fP);
+char *stkptr(Stk_t *\fIstack\fP, unsigned \fIoffset\fP);
+char *stkfreeze(Stk_t *\fIstack\fP, unsigned \fIextra\fP);
+int stkon(Stk *\fIstack\fP, char* \fIaddr\fP)
+\fR
+.fi
+.SH DESCRIPTION
+.PP
+\f5stk\fP is a package of routines designed to provide efficient
+stack oriented dynamic storage.
+A stack abstraction consists of an ordered list of contiguous
+memory regions, called stack frames, that can hold objects of
+arbitrary size.
+A stack is represented by the type \f5Stk_t\fP
+defined in header \f5<stk.h>\fP.
+The type \f5Stk_t\fP is compatible with the type \f5Sfio_t\fP
+defined by the \f5sfio\fP(3) library.
+At any instant there is one active stack which can be referenced
+by the constant \f5stkstd\fP.
+Variable size objects can be
+added to the active stack
+and programs can reference these objects directly with pointers.
+In addition, the last object on the stack
+(referred to here as the current object)
+can be built incrementally.
+The current object has an associated offset that determines its
+current size.
+While the current object is being built incrementally,
+its location might
+change so that it is necessary to reference the object with
+relative offsets ranging from zero to the current offset of the object.
+.PP
+There is a preset initial active stack.
+To use an additional stack, it is necessary to create it and to
+install it as the active stack.
+A stack is created with the \f5stkopen\fP() function.
+A \fIflags\fP argument of \f5STK_SMALL\fP indicates that unused
+space on the stack should be freed whenever this stack ceases
+to be the active stack.
+If successful,
+\f5stkopen\fP() returns a pointer to a stack whose reference
+count is 1.
+Otherwise, \f5stkopen\fP() returns a null pointer.
+The \f5stklink\fP() function increases the reference count for the
+given \fIstack\fP.
+The \f5stkinstall\fP() function
+makes the specified \fIstack\fP the active stack and returns a pointer
+to the previous active stack.
+When the \fIoverflow\fP argument is not null,
+it specifies a function that will
+be called whenever \f5malloc\fP(3) fails while trying to grow the
+stack.
+The \fIoverflow\fP function will be called with the size that was passed
+to \f5malloc\fP(3).
+The \fIoverflow\fP function can call \f5exit\fP(3), call \f5longjmp\fP(3)
+or return.
+If the \f5overflow\fP function returns,
+it must return a pointer to a memory region of the given size.
+The default action is to write an error to standard error and to
+call \f5exit\fP(2) with a non-zero exit value.
+When \fIstack\fP is a null pointer,
+the active stack is not changed
+but the \fIoverflow\fP function for the active stack can be changed
+and a pointer to the active stack is returned.
+The \f5stkclose\fP() function decrements the reference count and
+frees the memory associated with
+the specified stack
+when the reference count is zero.
+The effect of subsequent references to objects
+on the stack are undefined.
+.PP
+The
+\f5stkalloc\fP() function returns an aligned pointer to space on the
+active stack that can be used to hold any object of the given \fIsize\fP.
+\f5stkalloc\fP() is similar to \f5malloc\fP(3) except that individual
+items returned by \f5stkalloc\fP() can not be freed.
+\f5stkalloc\fP() causes the offset of the current object to be set to
+zero.
+.PP
+The
+\f5stkcopy\fP() function copies the given string onto the stack
+and returns a pointer to the \fIstring\fP on the stack.
+\f5stkcopy\fP() causes the offset of the current object to be set to
+zero.
+.PP
+The \f5stkset\fP() function finds the frame containing the given
+\fIaddress\fP, frees all frames that were created after the one containing
+the given \fIaddress\fP, and sets the current object to the given
+\fIaddress\fP.
+The top of the current object is set to \fIoffset\fP bytes from
+current object.
+If \fIaddress\fP is not the address of an object on the
+stack the result is undefined.
+.PP
+The \f5sfio\fP(3) output functions can be used to build
+current object incrementally.
+An object that is built incrementally on the stack will
+always occupy contiguous memory within a stack frame but
+until \f5stkfreeze\fP() is called,
+the location in memory for the object can change.
+There is a current offset associated with the current object that
+determines where subsequent operations apply.
+Initially, this offset is zero, and the offset changes as a result
+of the operations you specify.
+The \f5stkseek\fP() function is used set the offset for the
+current object.
+The \fIoffset\fP argument to \f5stkseek\fP() specifies the new
+offset for the current object.
+The frame will be extended or moved
+if \f5offset\fP causes the new current offset to extend beyond the
+current frame.
+\f5stkseek\fP() returns a pointer to the beginning of the current object.
+The \f5stktell\fP() function gives the offset of the current object.
+.PP
+The \f5stkptr\fP() function converts the given \f5offset\fP
+for the current object into a memory address on the stack.
+This address is only valid until another stack operation is given.
+The result is not defined if \fIoffset\fP exceeds the size of the current
+object.
+The \f5stkfreeze\fP()
+function terminates the current object on the
+stack and returns a pointer to the beginning of this object.
+If \fIextra\fP is non-zero, \fIextra\fP bytes are added to the stack
+before the current object is terminated. The first added byte will
+contain zero and the contents of the remaining bytes are undefined.
+.PP
+The \f5stkon\fP()
+function returns non-zero if the address given by \fIaddr\fP is
+on the stack \fIstack\fP and \f50\fP otherwise.
+.PP
+.SH HISTORY
+The
+\f5stk\fP
+interface was derived from similar routines in the KornShell code
+that is used for building parse trees and carrying out expansions.
+It provides an efficient mechanism for grouping dynamically allocated
+objects so that they can be freed all at once rather than individually.
+.SH AUTHOR
+ David Korn
+.SH SEE ALSO
+\f5exit(2)\fP
+\f5longjmp(3)\fP
+\f5malloc(3)\fP
+\f5sfio(3)\fP
diff --git a/src/lib/libast/man/strcopy.3 b/src/lib/libast/man/strcopy.3
new file mode 100644
index 0000000..c08d885
--- /dev/null
+++ b/src/lib/libast/man/strcopy.3
@@ -0,0 +1,54 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRCOPY 3
+.SH NAME
+strcopy \- copy strings
+.SH SYNOPSIS
+.L "char* strcopy(char* a, char* b)"
+.SH DESCRIPTION
+.I strcopy
+copies the nul-terminated string
+.I b
+into
+.IR a .
+A pointer to the 0 character in
+.I a
+is returned.
+.SH "SEE ALSO"
+strcpy(3)
diff --git a/src/lib/libast/man/strdup.3 b/src/lib/libast/man/strdup.3
new file mode 100644
index 0000000..3b26ec4
--- /dev/null
+++ b/src/lib/libast/man/strdup.3
@@ -0,0 +1,55 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRDUP 3
+.SH NAME
+strdup \- duplicate nul-terminated string
+.SH SYNOPSIS
+.L "char* strdup(char* s)"
+.SH DESCRIPTION
+.I strdup
+copies the nul-terminated string
+.I s
+to a new location provided by
+.IR malloc (3)
+and returns a pointer to the new copy.
+0 is returned if
+.IR malloc (3)
+failed.
+.SH "SEE ALSO"
+malloc(3), memdup(3)
diff --git a/src/lib/libast/man/strelapsed.3 b/src/lib/libast/man/strelapsed.3
new file mode 100644
index 0000000..8c3fa4a
--- /dev/null
+++ b/src/lib/libast/man/strelapsed.3
@@ -0,0 +1,77 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRELAPSED 3
+.SH NAME
+strelapsed \- parse elapsed time expression
+.SH SYNOPSIS
+.L "unsigned long strelapsed(char* buf, char** next, int persec)"
+.SH DESCRIPTION
+.I strelapsed
+returns a pointer to a string representation of the elapsed time for
+.L (count/persec)
+seconds.
+The two largest time units are used, limiting the return value length
+to at most 6 characters.
+The units are:
+.TP
+.B s
+seconds
+.TP
+.B m
+minutes
+.TP
+.B h
+hours
+.TP
+.B days
+.TP
+.B weeks
+.TP
+.B M
+months
+.TP
+.B Y
+years
+.TP
+.B S
+scores
+.SH "SEE ALSO"
+strelapsed(3)
+.SH CAVEATS
+The return value points to a static area that is overwritten on each call.
diff --git a/src/lib/libast/man/strerror.3 b/src/lib/libast/man/strerror.3
new file mode 100644
index 0000000..0084e3a
--- /dev/null
+++ b/src/lib/libast/man/strerror.3
@@ -0,0 +1,53 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRERROR 3
+.SH NAME
+strerror \- return error message string given error number
+.SH SYNOPSIS
+.L "char* strerror(int err)"
+.SH DESCRIPTION
+.I strerror
+returns the error message string corresponding to the error message number
+.IR err .
+.BI "Error " nnn
+is returned if
+.I err
+is invalid.
+.SH "SEE ALSO"
+error(3)
diff --git a/src/lib/libast/man/stresc.3 b/src/lib/libast/man/stresc.3
new file mode 100644
index 0000000..c09a0e9
--- /dev/null
+++ b/src/lib/libast/man/stresc.3
@@ -0,0 +1,53 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRESC 3
+.SH NAME
+stresc \- convert character constants in string
+.SH SYNOPSIS
+.L "int stresc(char* s)"
+.SH DESCRIPTION
+.I stresc
+converts
+.L \e
+character constant expressions in the nul-terminated string
+.I s
+in place and returns the length of the converted
+.IR s .
+.SH "SEE ALSO"
+chresc(3), ctoi(3)
diff --git a/src/lib/libast/man/streval.3 b/src/lib/libast/man/streval.3
new file mode 100644
index 0000000..2b491c8
--- /dev/null
+++ b/src/lib/libast/man/streval.3
@@ -0,0 +1,83 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STREVAL 3
+.SH NAME
+streval \- long integer arithmetic expression evaluator
+.SH SYNOPSIS
+.L "long streval(char* s, char** e, long (*conv)(char* cs, char** ce))"
+.SH DESCRIPTION
+.I streval
+evaluates the long integer arithmetic expression in the nul-terminated string
+.I s
+and returns the result.
+If
+.I e
+is not 0 then
+.I *e
+is set to point to the first unknown character in the expression.
+.PP
+If
+.I conv
+is not 0 then it is called when an unknown token is encountered in
+.IR s .
+.I cs
+points to the beginning of the unknown token.
+The return value is the long integer value of the unknown token and
+.I ce
+must be set to point to the first character after the unknown token.
+If an expression syntax error is encountered the
+.I conv
+is called with
+.I cs
+set to 0 and
+.I *ce
+pointing to the error message text.
+.PP
+In addition to the normal C expressions and integer constant styles,
+numbers in any base
+.I b
+<= 2 <=36
+may be represented as
+.IR b # nnnn ,
+where the extra digits in
+.I nnnn
+are taken from
+.BR [A-Z] .
+.SH "SEE ALSO"
+strtol(3)
diff --git a/src/lib/libast/man/strgid.3 b/src/lib/libast/man/strgid.3
new file mode 100644
index 0000000..d7a2663
--- /dev/null
+++ b/src/lib/libast/man/strgid.3
@@ -0,0 +1,53 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRGID 3
+.SH NAME
+strgid \- return group name given group number
+.SH SYNOPSIS
+.L "char* strgid(int gid)"
+.SH DESCRIPTION
+.I strgid
+returns the group id name string given the group number
+.IR gid .
+.I strgid
+maintains an internal cache to avoid repeated password database scans
+by the low level
+.IR getgrgid (3).
+.SH "SEE ALSO"
+getgrent(3)
diff --git a/src/lib/libast/man/strmatch.3 b/src/lib/libast/man/strmatch.3
new file mode 100644
index 0000000..5f5af89
--- /dev/null
+++ b/src/lib/libast/man/strmatch.3
@@ -0,0 +1,101 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRMATCH 3
+.SH NAME
+strmatch \- match shell file patterns
+.SH SYNOPSIS
+.L "int strmatch(char* s, char* p)"
+.br
+.L "char* submatch(char* s, char* p, int m)"
+.SH DESCRIPTION
+.I strmatch
+compares the string
+.I s
+with the shell pattern
+.I p
+and returns 1 for match and 0 otherwise.
+.I submatch
+does a leading substring match of the shell pattern
+.I p
+with the string
+.IR s .
+If
+.I m
+is 0 then the match is minimal, otherwise a maximal match is done.
+A pointer to the first character after the matched substring is returned,
+.I 0
+if there is no match.
+.PP
+Except for
+.I &
+and
+.IR ! ,
+each shell pattern has an equivalent
+.IR egrep (1)
+construct.
+.EX
+ \fBsh pattern egrep RE description\fP
+ * .* 0 or more chars
+ ? . any single char
+ [.] [.] char class
+ [!.] [^.] negated char class
+ *(.) (.)* 0 or more of
+ +(.) (.)+ 1 or more of
+ ?(.) (.)? 0 or 1 of
+ (.) (.) 1 of
+ @(.) (.) 1 of
+ a|b a|b a or b
+ a&b a and b
+ !(.) none of
+.EE
+.L \e
+is used to escape *, ?, (, |, &, ), [, and \e
+outside of [...].
+.SH "SEE ALSO"
+grep(1)
+.SH BUGS
+An unbalanced
+.L )
+terminates the top level pattern.
+.br
+Nested
+.L &
+and
+.L !
+constructs are non-intuitive and are computationally intensive.
diff --git a/src/lib/libast/man/stropt.3 b/src/lib/libast/man/stropt.3
new file mode 100644
index 0000000..f2a8dae
--- /dev/null
+++ b/src/lib/libast/man/stropt.3
@@ -0,0 +1,130 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STROPT 3
+.SH NAME
+stropt \- table driven option expression evaluator
+.SH SYNOPSIS
+.L "#include <namval.h>"
+.br
+.L "int stropt(char* s, struct namval* tab,
+.br
+.L " int (*fun)(void* a, struct namval* p, int n, char* v),"
+.br
+.L " void* a)"
+.SH DESCRIPTION
+.I stropt
+parses option expressions in the nul-terminated string
+.I s
+using the option names in
+.IR tab .
+.I tab
+is an array of
+.B "struct namval"
+name value pairs:
+.EX
+char* name;
+int value;
+.EE
+The last entry must be followed by a sentinel with
+.B name
+set to 0.
+.PP
+An option expression contains 0 or more of [\fBno\fP]\fIname\fP[=\fIvalue\fP]
+separate by
+.B space
+or
+.BR tab ,
+where
+.I name
+must be one of the option names in
+.IR tab ,
+.I value
+is an optional value, and
+.B no
+is for Boolean options.
+Each option is passed to
+.I fun
+for processing.
+.I a
+is the
+.L void*
+pointer that is passed from the
+.I stropt
+call but is otherwise not interpreted.
+.I p
+points to the option name value pair from
+.IR tab .
+.I n
+is 0 if
+.B no
+preceded the option
+.I name
+and
+.I v
+points to the beginning of the option
+.I value
+in
+.IR s .
+and
+If
+.I name
+is not found in
+.I tab
+then
+.I fun
+is called with
+.I p
+pointing to an internal
+.I namval
+entry with
+.I p\->name
+pointing to the unknown option and
+.I p\->value
+set to the
+.I value
+of the sentinel entry in
+.IR tab .
+.PP
+If
+.I fun
+returns non-zero then this value is returned and no further
+options are processed.
+Otherwise
+.I stropt
+returns 0 after processing all options.
diff --git a/src/lib/libast/man/strperm.3 b/src/lib/libast/man/strperm.3
new file mode 100644
index 0000000..9b68946
--- /dev/null
+++ b/src/lib/libast/man/strperm.3
@@ -0,0 +1,109 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRPERM 3
+.SH NAME
+strperm \- evaluate file permission expression
+.SH SYNOPSIS
+.L "int strperm(char* s, char** e, int p)"
+.SH DESCRIPTION
+.I strperm
+applies a file permission expression in the nul-terminated string
+.I s
+to the initial file permission mask
+.IR p .
+The new permission mask is returned.
+If
+.I e
+not 0 then
+.I *e
+is set to point to the first unrecognized character in
+.IR s .
+.PP
+A tape device specification is composed of one or more
+.I who-op-permission
+terms separated by
+.BR , .
+.I who
+selects portions of the permission bits and may be any combination of:
+.TP 3
+.B u
+the user permission bits;
+.TP
+.B g
+the group permission bits;
+.TP
+.B o
+the `other' permission bits;
+.TP
+.B a
+all permission bits.
+.PP
+If omitted, all permission bits are selected.
+.I op
+specifies how the original permission
+.I p
+is to be modified:
+.TP 3
+.B +
+.br
+.ns
+.B |
+the new bits are set in
+.IR p ;
+.TP 3
+.B \-
+the new bits are cleared in
+.IR p ;
+.TP
+.B &
+the new bits are and'd with
+.IR p ;
+.TP
+.B =
+the select bits in
+.I p
+are set equal to the new bits
+.PP
+A permission expression term may also be an octal number.
+Octal specifications are inherently non-portable.
+Refer to
+.IR chmod (1)
+for an explanation of this form.
+.SH "SEE ALSO"
+chmod(1), ls(1), strmode(3)
diff --git a/src/lib/libast/man/strsignal.3 b/src/lib/libast/man/strsignal.3
new file mode 100644
index 0000000..4141980
--- /dev/null
+++ b/src/lib/libast/man/strsignal.3
@@ -0,0 +1,53 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRSIGNAL 3
+.SH NAME
+strsignal \- return signal description string given signal number
+.SH SYNOPSIS
+.L "char* strsignal(int sig)"
+.SH DESCRIPTION
+.I strsignal
+returns the signal description string corresponding to the signal number
+.IR sig .
+.BI "Signal " nnn
+is returned if
+.I sig
+is invalid.
+.SH "SEE ALSO"
+signal(2), sigvec(2)
diff --git a/src/lib/libast/man/strsort.3 b/src/lib/libast/man/strsort.3
new file mode 100644
index 0000000..c48cfc2
--- /dev/null
+++ b/src/lib/libast/man/strsort.3
@@ -0,0 +1,73 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH HSORT 3
+.SH NAME
+hsort \- array heap sort
+.SH SYNOPSIS
+.EX
+#include <ast.h>
+
+void strsort(char** \fIarray\fP, int \fIelements\fP, int (*\fIcompare\fP)(const char* \fIa\fP, const char* \fIb\fP));
+.EE
+.SH DESCRIPTION
+.L strsort
+does a heap sort on the array of pointers
+.I array
+with
+.I elements
+elements using the comparison function
+.IR compare .
+.I compare
+returns
+.L \-1
+if
+.I a
+is lexicographically less than
+.IR b ,
+.L 0
+if
+.I a
+is equal to
+.IR b ,
+and
+.L 1
+if
+.I a
+is lexicographically greater than
+.IR b .
diff --git a/src/lib/libast/man/strtape.3 b/src/lib/libast/man/strtape.3
new file mode 100644
index 0000000..06c33ba
--- /dev/null
+++ b/src/lib/libast/man/strtape.3
@@ -0,0 +1,86 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRTAPE 3
+.SH NAME
+strtape \- convert string to tape device pathname
+.SH SYNOPSIS
+.L "char* strtape(char* s, char** e)"
+.SH DESCRIPTION
+.I strtape
+converts the generic tape device specification in the nul-terminated string
+.I s
+to a local tape device pathname.
+A pointer to the device pathname is returned.
+If
+.I e
+not 0 then
+.I *e
+is set to point to the first unrecognized character in
+.IR s .
+.PP
+A tape device specification is composed of
+.IR unit-density-rewind .
+All are optional.
+.I unit
+is a unit number in the range
+.BR [0-7] .
+The default unit is
+.BR 1 .
+Density may be one of:
+.TP 3
+.B l
+for low;
+.TP 3
+.B m
+for medium, and
+.TP
+.B h
+for high.
+.PP
+The default is
+.BR m .
+.I rewind
+is
+.B n
+for no-rewind on device close.
+The default is to rewind on device close.
+.SH "SEE ALSO"
+pax(1), tar(1)
+.SH CAVEATS
+The return value points to a static area that is overwritten on each call.
diff --git a/src/lib/libast/man/strton.3 b/src/lib/libast/man/strton.3
new file mode 100644
index 0000000..bfcf891
--- /dev/null
+++ b/src/lib/libast/man/strton.3
@@ -0,0 +1,97 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRTON 3
+.SH NAME
+strton \- convert string to long integer
+.SH SYNOPSIS
+.L "long strton(char* s, char** e)"
+.SH DESCRIPTION
+.I strton
+converts the nul-terminated string
+.I s
+to a long integer.
+If
+.I e
+not 0 then
+.I *e
+is set to point to the first unrecognized character in
+.IR s .
+Leading spaces in
+.I s
+are ignored.
+.PP
+A number is composed of
+.IR sign-base-number-suffix .
+All but
+.I number
+are optional.
+.I sign
+may be \+ or \-.
+.I base
+may be:
+.TP
+.B 0x
+for hexadecimal;
+.TP
+.B 0
+for octal, or
+.TP
+.IR nn #
+for base
+2 \(le
+.I nn
+\(le 36.
+.PP
+For bases greater than 10 the additional digits are take from the set
+.BR [a-zA-Z] .
+The suffix multiplies the converted number and may be:
+.TP
+.B b
+block (512)
+.TP
+.B g
+giga (1024 * 1024 * 1024)
+.TP
+.B k
+kilo (1024)
+.TP
+.B m
+mega (1024 * 1024)
+.SH "SEE ALSO"
+atoi(3), scanf(3), strtod(3)
diff --git a/src/lib/libast/man/struid.3 b/src/lib/libast/man/struid.3
new file mode 100644
index 0000000..522deb5
--- /dev/null
+++ b/src/lib/libast/man/struid.3
@@ -0,0 +1,53 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH STRUID 3
+.SH NAME
+struid \- return user name given user number
+.SH SYNOPSIS
+.L "char* struid(int uid)"
+.SH DESCRIPTION
+.I struid
+returns the user id name string given the user number
+.IR uid .
+.I struid
+maintains an internal cache to avoid repeated password database scans
+by the low level
+.IR getpwuid (3).
+.SH "SEE ALSO"
+getpwent(3)
diff --git a/src/lib/libast/man/swap.3 b/src/lib/libast/man/swap.3
new file mode 100644
index 0000000..82176de
--- /dev/null
+++ b/src/lib/libast/man/swap.3
@@ -0,0 +1,138 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH SWAP 3
+.SH NAME
+swap \- integral representation conversion routines
+.SH SYNOPSIS
+.L "#include <swap.h>"
+.sp
+.L "int swapop(const void* internal, const void* external, int width);
+.L "int_max swapget(int op, const void* from, int width);"
+.L "void* swapput(int op, void* to, int width, int_max value);"
+.L "void* swapmem(int op, const void* from, void* to, size_t n);"
+.SH DESCRIPTION
+These routines convert integral constants between internal and
+external representations.
+They are used to handle binary data generated by foreign programs.
+New binary data representations should use the compact canonical form
+provided by the
+.IR sfio (3)
+routines
+.L sfputu
+and
+.LR sgetu .
+.PP
+.L swapop
+returns the swap operation required to convert the
+.L width
+byte integer
+.L external
+to the
+.L width
+byte integer
+.LR internal .
+The swap operation is a bit mask:
+.TP
+.L 0
+No swapping necessary.
+.TP
+.L 1
+Swap byte
+.L 0
+with byte
+.LR 1 .
+.TP
+.L 2
+Swap bytes
+.L 0
+and
+.L 1
+with bytes
+.L 2
+and
+.LR 3 .
+.TP
+.L 4
+Swap bytes
+.L 0-3
+with bytes
+.LR 4-7 ,
+and so on.
+The largest native integral type is defined by the macro
+.L int_max
+in the header
+.L <int.h>
+described in
+.IR int (3).
+.PP
+.L swapget
+returns the
+.L width
+byte integer in the buffer
+.LR from ,
+swapped according to
+.LR op .
+.PP
+.L swapput
+copies the
+.L width
+byte integer
+.L value
+into the buffer
+.LR to ,
+swapped according to
+.LR op .
+.L to
+is returned.
+.PP
+.L swapmem
+swaps
+.L n
+bytes from the buffer
+.L from
+to the buffer
+.L to
+according to
+.LR op .
+.L to
+and
+.L from
+may be the same.
+.SH "SEE ALSO"
+int(3)
diff --git a/src/lib/libast/man/tab.3 b/src/lib/libast/man/tab.3
new file mode 100644
index 0000000..e1c76f3
--- /dev/null
+++ b/src/lib/libast/man/tab.3
@@ -0,0 +1,74 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH TAB 3
+.SH NAME
+tab \- simple table lookup routines
+.SH SYNOPSIS
+.L "#include <ast.h>"
+.sp
+.L "int tabindex(const void* tab, int size, const char* name);"
+.L "void* tablook(const void* tab, int size, const char* name);"
+.SH DESCRIPTION
+These routines do linear lookups in
+.I small
+tables (on the order of 32 elements).
+Each table element has a size of
+.L size
+bytes and the beginning of the element points to a name that is
+matched by the lookup routines.
+.PP
+.L tabindex
+returns the index of the table element in
+.L tab
+that matches
+.LR name .
+If there is no match then
+.L \-1
+is returned.
+.PP
+.L tablook
+returns a pointer to the table element in
+.L tab
+that matches
+.LR name .
+If there is no match then
+.L 0
+is returned.
+.SH "SEE ALSO"
+hash(3)
diff --git a/src/lib/libast/man/tm.3 b/src/lib/libast/man/tm.3
new file mode 100644
index 0000000..12eb4ec
--- /dev/null
+++ b/src/lib/libast/man/tm.3
@@ -0,0 +1,775 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH TM 3
+.SH NAME
+tm \- seconds resolution time conversion support
+.SH SYNOPSIS
+.L "#include <tm.h>"
+.SH DESCRIPTION
+The
+.I tm
+library supports conversion between
+string date specifications,
+seconds reolution
+.L time_t
+clock values and
+.LR Tm_t .
+.L Tm_t
+contains the elements of
+.L "struct tm"
+along with these additions:
+.TP
+.L "unsigned _ast_int4_t tm_nsec"
+The subsecond portion of the time in nanoseconds.
+.TP
+.L "Tm_zone_t* tm_zone"
+The time zone name.
+.PP
+.L localtime()
+and
+.L gmtime()
+(see
+.BR ctime (3))
+are used to determine local time zone and savings time information.
+.PP
+.L time_t
+values are the number of seconds since the epoch,
+.BR "Jan 1 00:00:00 GMT 1970" ,
+with leap seconds omitted.
+.PP
+The global variable
+.L "int tm_info.flags"
+contains flags that allow all programs using the library
+to be controlled in a consistent manner.
+.L tm_info.flags
+is initialized by the
+.L tminit()
+routine described below, and may be explicitly reset after
+.L tminit()
+is called.
+The flags are:
+.TP
+.L TM_ADJUST
+Set by
+.L tminit()
+if
+.L localtime()
+and
+.L gmtime()
+do not compensate for leap seconds.
+.TP
+.L TM_LEAP
+.L time_t
+values are interpreted as if they include leap seconds.
+Set by
+.L tminit()
+if the
+.L leap
+option is set in the
+.L TM_OPTIONS
+environment variable.
+.TP
+.L TM_UTC
+Times are relative to
+.B UTC
+(universal coordinated time, i.e.,
+.BR GMT .)
+Otherwise times are relative to the local time zone.
+Set by
+.L tminit()
+if the time zone name matches one of
+.L tm_info.format[43]
+through
+.L tm_info.format[46]
+described below.
+If the time zone name is not determined by
+.L localtime()
+then the environment variables
+.L TZNAME
+(as described in BSD 4.3) and
+.L TZ
+(as described in System V)
+are checked, in order.
+If this fails then the time zone name is constructed using
+the local time zone offset.
+.PP
+The routines are:
+.TP
+.L "time_t tmdate(const char* date, char** end, time_t* clock)"
+Parses the date specification
+.L date
+using the
+.L tm_info.format
+string table (described below)
+and returns the equivalent
+.L time_t
+value.
+If
+.RL non- NULL ,
+.L end
+is set to the position of the first unrecognized character in
+.LR date .
+.L clock
+is used to provide default values for omitted components in
+.LR date .
+If
+.L clock
+is
+.L NULL
+then the current time is used.
+.TP
+.L "Tm_t* tmfix(Tm_t* tp)"
+Corrects any out of bounds fields in
+.L tp
+and returns
+.L tp
+as its value.
+The corrections start with
+.L tp->tm_sec
+and propagate down to
+.LR tp->tm_year .
+For example, if
+.L tp->tm_sec
+were 61 then it would change to 1 and
+.L tp->tm_min
+would be incremented by 1, and so on.
+.L tp->tm_isdst
+is not changed -- call
+.L tmtime()
+to determine its proper value after the
+.L tmfix()
+adjustments.
+.TP
+.L "char* tmfmt(char* buf, size_t len, const char* format, time_t* clock)"
+Formats the date pointed to by
+.L clock
+into the buffer
+.L buf
+with size
+.L len
+bytes according to the format specification
+.LR format .
+If
+.L format
+is
+.L NULL
+or empty then the string
+.L tm_info.format[40]
+is used.
+If
+.L clock
+is
+.L NULL
+then the current time is used.
+A pointer to the end of
+.L buf
+(i.e., the terminating
+.LR "'\e0'" )
+is returned.
+.RS
+.PP
+.L format
+is in
+.BR printf (3)
+style, where
+.RI % field
+names a fixed size field, zero padded if necessary,
+and
+.I \ec
+and
+.I \ennn
+sequences are as in C. Invalid
+.RI % field
+specifications and all other characters are copied
+without change.
+.I field
+may be preceded by
+.B %-
+to turn off padding or
+.B %_
+to pad with space, otherwise numeric fields
+are padded with
+.B 0
+and string fields are padded with space.
+.I field
+may also be preceded by
+.B E
+for alternate era representation or
+.B O
+for alternate digit representation (if supported by the current locale.)
+Finally, an integral
+.I width
+preceding
+.I field
+truncates the field to
+.I width
+characters.
+sequences are interpreted as in the C language.
+String field values are taken from the
+.L tm_info.format
+string table.
+The
+.I fields
+are:
+.TP
+.PD 0
+.B %
+.B %
+character.
+.TP
+.B a
+Abbreviated weekday name.
+.TP
+.B A
+Full weekday name.
+.TP
+.B b
+Abbreviated month name.
+.TP
+.B c
+.BR ctime (3)
+style date without the trailing
+.BR newline .
+.TP
+.B C
+.BR date (1)
+style date.
+.TP
+.B d
+Day of month number.
+.TP
+.B D
+Date as
+.IR mm / dd / yy .
+.TP
+.B e
+Blank padded day of month number.
+.TP
+.B E
+Unpadded day of month number.
+.TP
+.B f
+Locale default override date format.
+.TP
+.B F
+Locale default date format
+.RL ( tm_info.format[40] .)
+.TP
+.B h
+Abbreviated month name.
+.TP
+.B H
+24-hour clock hour.
+.TP
+.B i
+International
+.BR date (1)
+date that includes the time zone type name
+.RL ( tm_info.format[107] .)
+.TP
+.B I
+12-hour clock hour.
+.TP
+.B j
+1-offset Julian date.
+.TP
+.B J
+0-offset Julian date.
+.TP
+.B k
+.BR date (1)
+style date
+.RL ( tm_info.format[106] .)
+.TP
+.B K
+Language neutral, all numeric, no embedded space date
+with larger to smaller time units from left to right,
+suitable for sorting:
+.LR '"%Y-%m-%d+%H:%M:%S"' .
+.TP
+.B l
+.BR ls (1)
+.B \-l
+date that lists recent dates with
+.L %g
+and distant dates with
+.BR %G .
+.TP
+.B m
+Month number.
+.TP
+.B M
+Minutes.
+.TP
+.B n
+.B newline
+character.
+.TP
+.B N
+The time zone type or nation code.
+.TP
+.B p
+Meridian (e.g.,
+.B AM
+or
+.BR PM .)
+.TP
+.B q
+The nanosecond part of the time.
+.TP
+\fB%Q\fP\fI<delim>recent<delim>distant<delim>\fP
+Recent dates are formatted with
+.I recent
+and distand dates are formatted with
+.IR distant ,
+where
+.I <delim>
+is any character not appearing in
+.I recent
+or
+.IR distant .
+.TP
+.B r
+12-hour time as
+.IR hh : mm : ss
+.IR meridian .
+.TP
+.B R
+24-hour time as
+.IR hh : mm .
+.TP
+.B s
+Seconds since the epoch.
+.RI . prec
+preceding
+.B s
+appends
+.I prec
+nanosecond digits,
+.B 9
+if
+.I prec
+is omitted.
+.TP
+.B S
+.I seconds.subseconds
+since the epoch.
+.TP
+.B t
+.B tab
+character.
+.TP
+.B T
+24-hour time as
+.IR hh : mm : ss .
+.TP
+.B u
+Weeday number with 1 for Monday, 7 for Sunday.
+.TP
+.B U
+Week number with Sunday as the first day.
+.TP
+.B V
+ISO week number (i18n is \fIfun\fP.)
+.TP
+.B w
+Weekday number with 0 for Sunday, 6 for Saturday.
+.TP
+.B W
+Week number with Monday as the first day.
+.TP
+.B x
+Local date style, using
+.LR tm_info.format[39] ,
+that includes the month, day and year.
+.TP
+.B X
+Local time style, using
+.LR tm_info.format[38] ,
+that includes the hours and minutes.
+.TP
+.B y
+2-digit year (you'll be sorry.)
+.TP
+.B Y
+4-digit year.
+.TP
+.B z
+Time zone
+.I SHHMM
+west of GMT offset where
+.I S
+is
+.B +
+or
+.BR - .
+.TP
+.B Z
+Time zone name.
+.TP
+=[=]][-+]]\fIflag\fP
+Set (default or +) or clear (-)
+.I flag
+in
+.L tm_info.flags
+for the remainder of
+.IR format ,
+or for the remainder of the process if
+.B ==
+is specified.
+.I flag
+may be:
+.RS
+.TP
+.B l
+.L (TM_LEAP)
+Enable leap second adjustments.
+.TP
+.B s
+.L (TM_SUBSECOND)
+Append nanosecond
+.B .%N
+to
+.BR %S .
+.TP
+.B u
+.L (TM_UTC)
+UTC time zone.
+.RE
+.TP
+.B #
+Equivalent to
+.BR %s .
+.TP
+\fP?\fP\fIalternate\fP
+Use
+.I alternate
+format is a default format override has not been specified.
+e.g.,
+.BR ls (1)
+uses
+.BR %?%l .
+Export
+\f5TM_OPTIONS="format='\fP\fIoverride\fP\f5'"\fP
+to override the default.
+.PD
+.RE
+.TP
+.L "void tminit(Tm_zone_t* zone)"
+Implicitly called by the other
+.I tm
+library routines to initialize global data, including the
+.L tm_info.format
+table and the
+.L tm_info.flags
+global flags.
+Global data should only be modified after an explicit call to
+.LR tminit .
+If
+.L "zone != 0"
+then it specifies a time zone other that the local time zone.
+.TP
+.L "void tmset(Tm_zone_t* zone);"
+.L tmset
+sets the reference timezoe to
+.LR zone .
+.L tm_info.local
+points to the local timezone and
+.L tm_info.zone
+points to the current reference timezone.
+.TP
+.L "time_t tmleap(time_t* clock)"
+Returns a
+.L time_t
+value for the time pointed to by
+.L clock
+with leap seconds adjusted for external
+routines that do not handle leap seconds.
+If
+.L clock
+is
+.L NULL
+then the current time is used.
+Adjustments are only done if the
+.L TM_ADJUST
+flag is set in
+.LR tm_info.flags .
+.TP
+.L "Tm_t* tmmake(time_t* clock)"
+Returns a pointer to the
+.L Tm_t
+struct corresponding to the time pointed to by
+.LR clock .
+If
+.L clock
+is
+.L NULL
+then the current time is used.
+.TP
+.L "time_t tmtime(Tm_t* tp, int west)"
+Returns the
+.L time_t
+value corresponding to
+.LR tp .
+If
+.L west
+is
+.L TM_LOCALZONE
+then
+.L tm
+is relative to the local time zone,
+otherwise
+.L west
+is the number of minutes west of
+.B UTC
+with daylight savings time taken into account.
+.LR tp->tm_wday ,
+.LR tp->tm_yday
+and
+.L tp->tm_isdst
+are ignored in the conversion.
+.PP
+The library routines use a table of date strings pointed to by
+.LR "char** tm_info.format" .
+The indices in
+.L tm_info.format
+are fixed by category.
+.L tm_info.format
+may be changed to point to other tables
+according to local language and date conventions.
+The contents by index (showing the USA English values) are:
+.RS
+.TP
+.PD 0
+.B 0-11
+3-character abbreviated month names.
+.TP
+.B 12-23
+Full month names.
+.TP
+.B 24-30
+3-character abbreviated weekday names.
+.TP
+.B 31-37
+Full weekday names.
+.TP
+.B 38
+.L tmfmt()
+local time format used by the
+.B %X
+field.
+.TP
+.B 39
+.L tmfmt()
+local date format used by the
+.B %x
+field.
+.TP
+.B 40
+.L tmfmt()
+format used if the
+.L format
+argument is
+.L NULL
+or empty.
+.TP
+.B 41-42
+Meridian names: AM, PM.
+.TP
+.B 43-46
+.B UTC
+time zone names: GMT, UTC, UCT, CUT.
+.TP
+.B 47-50
+Daylight savings time suffix names: DST.
+.TP
+.B 51-54
+Suffixes to be ignored when matching strings in
+.LR tmfmt() .
+.TP
+.B 55-61
+Time part names: second, hour, minute, day, week, month, year.
+.TP
+.B 62-65
+Hours of the day names: midnight, morning, noon, evening.
+.TP
+.B 66-68
+Relative day names: yesterday, today, tomorrow.
+.TP
+.B 69-71
+Past relative time references: last, ago, past.
+.TP
+.B 72-75
+Current relative time references: this, now, current.
+.TP
+.B 75-77
+Future relative time references: next, hence, coming.
+.TP
+.B 78-80
+Exact relative time references: exactly.
+.TP
+.B 81-84
+Noise words to be ignored: at, in, on.
+.TP
+.B 85-94
+Ordinal suffixes: st, nd, rd, th, th, th, th, th, th, th.
+.TP
+.B 95-104
+Digit names.
+.TP
+.B 105
+The
+.L tmfmt()
+format equivalent for
+.BR ctime (3):
+.LR '"%a %b %e %T %Y"' .
+.TP
+.B 106
+The
+.L tmfmt()
+.BR date (1)
+default format:
+.LR '"%a %b %e %T %Z %Y"' .
+.TP
+.B 107
+The
+.L tmfmt()
+.BR date (1)
+international format:
+.LR '"%a %b %e %T %z %Z %Y"' .
+.TP
+.B 108
+The
+.L tmfmt()
+.BR ls (1)
+recent date format:
+.LR '"%b %e %H:%M"' .
+.TP
+.B 109
+The
+.L tmfmt()
+.BR ls (1)
+distant date format:
+.LR '"%b %e %Y"' .
+.TP
+.B 110
+The
+.L tmfmt()
+.BR date (1)
+meridian date format:
+.LR '"%I:%M:%S %p"' .
+.TP
+.B 111
+The ERA name.
+.TP
+.B 112
+ERA alternative for
+.BR 39 .
+.TP
+.B 113
+ERA alternative for
+.BR 38 .
+.TP
+.B 114
+ERA alternative for
+.BR 40 .
+.TP
+.B 115
+The ERA year.
+.TP
+.B 116-125
+Ordinal names: first, \fIno second!\fP, third, fourth, fifth, sixth, seventh, eighth, ninth, tenth.
+.TP
+.B 126-128
+Final time references, as in \fIthe last in the list\fP: final, ending, nth.
+.PD
+.RE
+.PP
+Low level support functions and data are described in
+.LR <tm.h> .
+.SH EXAMPLES
+.EX
+#include <tm.h>
+main() {
+ int i;
+ time_t t;
+ char buf[128];
+ struct {
+ char* date;
+ char* format;
+ } x[] = {
+ "now", "%i",
+ "2 months ago", "%C",
+ "this Wednesday noon", "%x %I:%M %p",
+ "last December 25", "%A",
+ 0, 0
+ };
+ for (i = 0; x[i].date; i++) {
+ t = tmdate(x[i].date, (char*)0, (time_t*)0);
+ (void)tmfmt(buf, sizeof(buf), x[i].format, &t);
+ puts(buf);
+ }
+}
+.EE
+produces
+.EX
+Fri Sep 30 12:10:14 USA EDT 1988
+Fri Jul 1 00:00:00 EDT 1988
+10/05/88 12:00 PM
+Friday
+.EE
+.SH "SEE ALSO"
+.BR date (1),
+.BR time (2),
+.BR ctime (3)
+.SH BUGS
+The C library static
+.L "struct tm"
+values may get clobbered by
+.I tm
+library routines as the
+.BR ctime (3)
+and
+.BR localtime (3)
+routines typically return pointers to a single static
+.L "struct tm"
+area.
+.L tmdate()
+uses an internal international time zone name table that will
+probably always be incomplete.
diff --git a/src/lib/libast/man/tmx.3 b/src/lib/libast/man/tmx.3
new file mode 100644
index 0000000..268d40a
--- /dev/null
+++ b/src/lib/libast/man/tmx.3
@@ -0,0 +1,576 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH TM 3
+.SH NAME
+tm \- time conversion support
+.SH SYNOPSIS
+.L "#include <tm.h>"
+.SH DESCRIPTION
+The
+.I tm
+library supports conversion between
+string date specifications,
+.L time_t
+clock values and
+.L "struct tm"
+values.
+.L localtime()
+and
+.L gmtime()
+(see
+.IR ctime (3))
+are used to determine local time zone information.
+.PP
+.L time_t
+values are the number of seconds since the epoch,
+.BR "Jan 1 00:00:00 GMT 1970" ,
+with leap seconds omitted.
+.PP
+The global variable
+.L "int tm_info.flags"
+contains flags that allow all programs using the library
+to be controlled in a consistent manner.
+.L tm_info.flags
+is initialized by the
+.L tminit()
+routine described below, and may be explicitly reset after
+.L tminit()
+is called.
+The flags are:
+.TP
+.L TM_ADJUST
+Set by
+.L tminit()
+if
+.L localtime()
+and
+.L gmtime()
+do not compensate for leap seconds.
+.TP
+.L TM_LEAP
+.L time_t
+values are interpreted as if they include leap seconds.
+Set by
+.L tminit()
+if the
+.L leap
+option is set in the
+.L TM_OPTIONS
+environment variable.
+.TP
+.L TM_UTC
+Times are relative to
+.B UTC
+(universal coordinated time, i.e.,
+.BR GMT ).
+Otherwise times are relative to the local time zone.
+Set by
+.L tminit()
+if the time zone name matches one of
+.L tm_info.format[43]
+through
+.L tm_info.format[46]
+described below.
+If the time zone name is not determined by
+.L localtime()
+then the environment variables
+.L TZNAME
+(as described in BSD 4.3) and
+.L TZ
+(as described in System V)
+are checked, in order.
+If this fails then the time zone name is constructed using
+the local time zone offset.
+.PP
+The routines are:
+.TP
+.L "time_t tmdate(const char* date, char** end, time_t* clock)"
+Parses the date specification
+.L date
+using the
+.L tm_info.format
+string table (described below)
+and returns the equivalent
+.L time_t
+value.
+If
+.RL non- NULL ,
+.L end
+is set to the position of the first unrecognized character in
+.LR date .
+.L clock
+is used to provide default values for omitted components in
+.LR date .
+If
+.L clock
+is
+.L NULL
+then the current time is used.
+.TP
+.L "struct tm* tmfix(struct tm* tp)"
+Corrects any out of bounds fields in
+.L tp
+and returns
+.L tp
+as its value.
+The corrections start with
+.L tp->tm_sec
+and propagate down to
+.LR tp->tm_year .
+For example, if
+.L tp->tm_sec
+were 61 then it would change to 1 and
+.L tp->tm_min
+would be incremented by 1, and so on.
+.LR tp->tm_wday ,
+.LR tp->tm_yday
+and
+.L tp->tm_isdst
+are not changed as these can be computed from the other fields.
+.TP
+.L "char* tmfmt(char* buf, size_t len, const char* format, time_t* clock)"
+Formats the date pointed to by
+.L clock
+into the buffer
+.L buf
+with size
+.L len
+bytes according to the format specification
+.LR format .
+If
+.L format
+is
+.L NULL
+or empty then the string
+.L tm_info.format[40]
+is used.
+If
+.L clock
+is
+.L NULL
+then the current time is used.
+A pointer to the end of
+.L buf
+(i.e., the terminating
+.LR "'\e0'" )
+is returned.
+.RS
+.PP
+.L format
+is in the style of
+.IR printf (3),
+where
+.BI % field
+causes the corresponding fixed size field to be placed in
+.LR buf ,
+zero padded if necessary, and \e\fIc\fP and \e\fInnn\fP
+sequences are interpreted as in the C language.
+Otherwise invalid
+.BI % field
+specifications and all other characters in
+.L format
+are copied into
+.L buf
+without change.
+String field values are taken from the
+.L tm_info.format
+string table.
+The
+.I fields
+are:
+.TP
+.PD 0
+.B %
+.B %
+character.
+.TP
+.B a
+Abbreviated weekday name.
+.TP
+.B A
+Full weekday name.
+.TP
+.B b
+Abbreviated month name.
+.TP
+.B c
+.IR ctime (3)
+style date without the trailing
+.BR newline .
+.TP
+.B C
+.IR date (1)
+style date.
+.TP
+.B d
+Day of month number.
+.TP
+.B D
+Date as
+.IR mm / dd / yy .
+.TP
+.B e
+Blank padded day of month number.
+.TP
+.B E
+Unpadded day of month number.
+.TP
+.B h
+Abbreviated month name.
+.TP
+.B H
+24-hour clock hour.
+.TP
+.B i
+International
+.IR date (1)
+date that includes the time zone type name.
+.TP
+.B I
+12-hour clock hour.
+.TP
+.B j
+1-offset Julian date.
+.TP
+.B J
+0-offset Julian date.
+.TP
+.B l
+.IR ls (1)
+.B \-l
+date that lists recent dates with
+.IR hh : mm
+and distant dates with
+.IR yyyy .
+.TP
+.B m
+Month number.
+.TP
+.B M
+Minutes.
+.TP
+.B n
+.B newline
+character.
+.TP
+.B p
+Meridian (e.g.,
+.B AM
+or
+.BR PM ).
+.TP
+.B r
+12-hour time as
+.IR hh : mm : ss
+.IR meridian .
+.TP
+.B R
+24-hour time as
+.IR hh : mm .
+.TP
+.B S
+Seconds.
+.TP
+.B t
+.B tab
+character.
+.TP
+.B T
+24-hour time as
+.IR hh : mm : ss .
+.TP
+.B U
+Week number with Sunday as the first day.
+.TP
+.B w
+Weekday number.
+.TP
+.B W
+Week number with Monday as the first day.
+.TP
+.B x
+Local date style, using
+.LR tm_info.format[39] ,
+that includes the month, day and year.
+.TP
+.B X
+Local time style, using
+.LR tm_info.format[38] ,
+that includes the hours and minutes.
+.TP
+.B y
+2-digit year.
+.TP
+.B Y
+4-digit year.
+.TP
+.B z
+Time zone type name.
+.TP
+.B Z
+Time zone name.
+.TP
+.BI + flag
+.TP
+.BI \- flag
+Temporarily (until
+.L tmform()
+returns) sets (+) or clears (\-) the
+.L tm_info.flags
+flags specified by
+.IR flag :
+.RS
+.TP
+.B l
+.L TM_LEAP
+.TP
+.B u
+.L TM_UTC
+.RE
+.TP
+.B #
+Number of seconds since the epoch.
+.PD
+.RE
+.TP
+.L "void tminit(Tm_zone_t* zone)"
+Implicitly called by the other
+.I tm
+library routines to initialize global data, including the
+.L tm_info.format
+table and the
+.L tm_info.flags
+global flags.
+Global data should only be modified after an explicit call to
+.LR tminit .
+If
+.L "zone != 0"
+then it specifies a time zone other that the local time zone.
+.TP
+.L "void tmset(Tm_zone_t* zone);"
+.L tmset
+sets the reference timezoe to
+.LR zone .
+.L tm_info.local
+points to the local timezone and
+.L tm_info.zone
+points to the current reference timezone.
+.TP
+.L "time_t tmleap(time_t* clock)"
+Returns a
+.L time_t
+value for the time pointed to by
+.L clock
+with leap seconds adjusted for external
+routines that do not handle leap seconds.
+If
+.L clock
+is
+.L NULL
+then the current time is used.
+Adjustments are only done if the
+.L TM_ADJUST
+flag is set in
+.LR tm_info.flags .
+.TP
+.L "struct tm* tmmake(time_t* clock)"
+Returns a pointer to the
+.L tm
+struct corresponding to the time pointed to by
+.LR clock .
+If
+.L clock
+is
+.L NULL
+then the current time is used.
+.TP
+.L "time_t tmtime(struct tm* tp, int west)"
+Returns the
+.L time_t
+value corresponding to
+.LR tp .
+If
+.L west
+is
+.L TM_LOCALZONE
+then
+.L tm
+is relative to the local time zone,
+otherwise
+.L west
+is the number of minutes west of
+.B UTC
+with daylight savings time taken into account.
+.LR tp->tm_wday ,
+.LR tp->tm_yday
+and
+.L tp->tm_isdst
+are ignored in the conversion.
+.PP
+The library routines use a table of date strings pointed to by
+.LR "char** tm_info.format" .
+The indices in
+.L tm_info.format
+are fixed by category.
+.L tm_info.format
+may be changed to point to other tables
+according to local language and date conventions.
+The contents by index (showing the USA English values) are:
+.RS
+.TP
+.PD 0
+.B 0-11
+3-character abbreviated month names.
+.TP
+.B 12-23
+Full month names.
+.TP
+.B 24-30
+3-character abbreviated weekday names.
+.TP
+.B 31-37
+Full weekday names.
+.TP
+.B 38
+.L tmform()
+local time format used by the
+.B %X
+field.
+.TP
+.B 39
+.L tmform()
+local date format used by the
+.B %x
+field.
+.TP
+.B 40
+.L tmform()
+format used if the
+.L format
+argument is
+.L NULL
+or empty.
+.TP
+.B 41-42
+Meridian names: AM, PM.
+.TP
+.B 43-46
+.B UTC
+time zone names: GMT, UTC, UCT, CUT.
+.TP
+.B 47-50
+Daylight savings time suffix names: DST.
+.TP
+.B 51-54
+Suffixes to be ignored when matching strings in
+.LR tmform() .
+.TP
+.B 55-61
+Time part names: second, hour, minute, day, week, month, year.
+.TP
+.B 62-65
+Hours of the day names: midnight, morning, noon, evening.
+.TP
+.B 66-68
+Relative day names: yesterday, today, tomorrow.
+.TP
+.B 69-71
+Past relative time references: last, ago, past.
+.TP
+.B 72-75
+Current relative time references: this, now, current.
+.TP
+.B 75-77
+Future relative time references: next, hence, coming.
+.TP
+.B 78-80
+Exact relative time references: exactly.
+.TP
+.B 81-85
+Noise words to be ignored: at, in, on.
+.PD
+.RE
+.PP
+Low level support functions and data are described in
+.LR <tm.h> .
+.SH EXAMPLES
+.EX
+#include <tm.h>
+main() {
+ int i;
+ time_t t;
+ char buf[128];
+ struct {
+ char* date;
+ char* format;
+ } x[] = {
+ "now", "%i",
+ "2 months ago", "%C",
+ "this Wednesday noon", "%x %I:%M %p",
+ "last December 25", "%A",
+ 0, 0
+ };
+ for (i = 0; x[i].date; i++) {
+ t = tmdate(x[i].date, (char*)0, (time_t*)0);
+ (void)tmform(buf, x[i].format, &t);
+ puts(buf);
+ }
+}
+.EE
+produces
+.EX
+Fri Sep 30 12:10:14 USA EDT 1988
+Fri Jul 1 00:00:00 EDT 1988
+10/05/88 12:00 PM
+Friday
+.EE
+.SH "SEE ALSO"
+date(1), time(2), ctime(3)
+.SH BUGS
+.L "struct tm"
+values may get clobbered by the
+.I tm
+library routines as the
+.IR ctime (3)
+routines typically return pointers to a single static
+.L "struct tm"
+area.
+.L tmdate()
+uses an internal international time zone name table that will
+probably always be incomplete.
diff --git a/src/lib/libast/man/tok.3 b/src/lib/libast/man/tok.3
new file mode 100644
index 0000000..46fbff9
--- /dev/null
+++ b/src/lib/libast/man/tok.3
@@ -0,0 +1,217 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH TOK 3
+.SH NAME
+tok \- space separated token stream routines
+.SH SYNOPSIS
+.L "#include <ast.h>"
+.sp
+.L "void* tokopen(char* string)"
+.L "char* tokread(void* tok)"
+.L "void tokclose(void* tok)"
+.sp
+.L "int tokscan(char* string, char** next, const char* format, ...);"
+.sp
+.L "Sfio_t* tokline(const char* input, int flags, int* line);"
+.SH DESCRIPTION
+.L tokopen
+returns a pointer to a space separated token stream on the 0 terminated
+string
+.LR string .
+.L tokread
+returns a pointer to the next
+space separated token in the token stream
+.L tok
+as returned by
+.LR tokopen .
+0 is returned when no tokens remain.
+.L tokread
+temporarily modifies
+.L string
+by inserting 0's to terminate each token.
+.L tokclose
+closes the token stream and restores
+.L string
+to its original state.
+.PP
+.L tokscan
+scans the string
+.L string
+for tokens specified in
+.LR format .
+It is a more forgiving
+.IR sscanf (3).
+If
+.L "next != 0"
+then it will point to the next unread character in
+.L string
+on return.
+The number of scanned tokens is returned.
+.L \-1
+is returned if
+.L string
+was not empty and
+.L format
+failed to match and tokens.
+.PP
+.I space
+in
+.L format
+matches 0 or more
+.I space
+or
+.I tab
+characters.
+.I newline
+in format eats the remainder of the current line in
+.LR string .
+"...", '...' and \e\fIcharacter\fP quotes are interpreted.
+A quoted
+.I carriage-return
+is converted to
+.IR newline .
+.I newline
+in
+.L string
+is equivalent to end of string except when quoted.
+.I \enewline
+is a line splice.
+.PP
+.L %
+in
+.L format
+prefixes format conversion characters; each conversion character
+corresponds to a
+.L tokscan
+argument following the
+.L format
+argument.
+The format conversions are:
+.TP
+.L %c
+A single
+.LR char .
+.TP
+.L "%hd %d %ld"
+[short, int, long] base 10 integer.
+.TP
+.L "%hn %n %ln"
+[short, int, long] C-style base integer.
+.TP
+.L "%ho %o %lo"
+[short, int, long] base 8 integer.
+.TP
+.L %s
+String.
+.TP
+.L "%hu %u %lu"
+[short, int, long] C-style base unsigned integer.
+.TP
+.L %v
+The next two arguments are a pointer to a
+.L char**
+argument vector and the maximum number of elements in the vector.
+.TP
+.L "%hx %x %lx"
+[short, int, long] base 16 integer.
+.PP
+.L %s
+and
+.L %v
+data may also be counted length strings of the form
+\f5(\fIcount\fP:\fIdata\fP)\fR
+where
+.I count
+is the number of characters in
+.I data
+and the terminating
+.L )
+may also be a
+.IR tab ,
+or the data may be
+.L (null)
+which represents the
+.L NULL
+string.
+.PP
+.L tokline
+returns an
+.IR sfio (3)
+stream to a file or string that splices
+.I \enewline
+into single lines,
+allows "..." and '...' to quotes to span
+.I newlines
+(done by translating quoted
+.I newline
+to
+.IR carriage-return ;
+.L tokscan
+above converts quoted
+.I carriage-return
+back to
+.IR newline ),
+and deletes
+.I "# ... newline"
+comments.
+This is done by pushing an
+.I sfio
+discipline onto a string or file stream.
+Seeks are disabled on the resulting stream.
+If
+.L "flags == SF_READ"
+then
+.L input
+is a file name;
+If
+.L "flags == SF_STRING"
+then
+.L input
+is a 0 terminated string;
+otherwise
+.L input
+is an open
+.L Sfio_t*
+stream.
+If
+.L "line != 0"
+then it points to a line count that is initialized to 0
+and is incremented for each input line.
+.SH "SEE ALSO"
+sfio(3)
diff --git a/src/lib/libast/man/touch.3 b/src/lib/libast/man/touch.3
new file mode 100644
index 0000000..908a8b1
--- /dev/null
+++ b/src/lib/libast/man/touch.3
@@ -0,0 +1,68 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH TOUCH 3
+.SH NAME
+touch \- set file access and modify times
+.SH SYNOPSIS
+.L "#include <ast.h>"
+.sp
+.L "int touch(const char* path, time_t atime, time_t mtime, int force);"
+.SH DESCRIPTION
+.L touch
+sets the access and modify times of the file named by
+.LR path .
+If
+.L "force != 0"
+then the file is created if it doesn't exist;
+otherwise the file is not created and
+.L \-1
+is returned.
+If
+.L "force < 0"
+then
+.L atime
+and
+.L mtime
+are taken verbatim; otherwise
+.L "(time_t)(-1)"
+retains the current value for the file and
+.L "(time_t)(0)"
+uses the current time.
+.SH CAVEATS
+By default the change time is always changed to the current time.
diff --git a/src/lib/libast/man/tv.3 b/src/lib/libast/man/tv.3
new file mode 100644
index 0000000..b90a559
--- /dev/null
+++ b/src/lib/libast/man/tv.3
@@ -0,0 +1,173 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH TM 3
+.SH NAME
+tv \- high resolution time support
+.SH SYNOPSIS
+.L "#include <tv.h>"
+.SH DESCRIPTION
+The
+.I tv
+library supports high resolution
+.B Tv_t
+time specifications.
+.SS Tv_t
+contains these elements:
+.TP
+.L unsigned
+.L _ast_int4_t
+.L tv_sec
+Seconds since the epoch.
+.TP
+.L unsigned
+.L _ast_int4_t
+.L tv_nsec
+Nanosecond resolution.
+.PP
+In practice resolution is much coarser than 1 nanosecond.
+Systems that only support 1 second resolution always set
+.L tv_nsec
+to 0.
+.SS "int tvgettime(Tv_t* tv)"
+Sets
+.L tv
+to the current time.
+.L 0
+is returned on success,
+.L -1
+on error.
+.SS "int tvsettime(const Tv_t* tv)"
+Sets the system time to
+.LR tv .
+The caller must have sufficient privilege.
+.L 0
+is returned on success,
+.L -1
+on error.
+.SS "int tvcmp(const Tv_t* av, const Tv_t* bv)"
+Compares the times
+.L av
+and
+.L bv
+and returns
+.L -1
+if
+.L av
+is less than
+.LR bv ,
+.L 0
+if
+.L av
+is equal to
+.LR bv ,
+and
+.L 1
+if
+.L av
+is greater than
+.LR bv .
+.SS "time_t tvgetatime(Tv_t* tv, const struct stat* st)"
+.SS "time_t tvgetmtime(Tv_t* tv, const struct stat* st)"
+.SS "time_t tvgetctime(Tv_t* tv, const struct stat* st)"
+These macros set
+.L tv
+to the
+.L st
+the access, modify, or change time, respectively.
+The seconds portion of
+.L tv
+is returned.
+.SS "time_t tvsetatime(Tv_t* tv, struct stat* st)"
+.SS "time_t tvsetmtime(Tv_t* tv, struct stat* st)"
+.SS "time_t tvsetctime(Tv_t* tv, struct stat* st)"
+These macros set the
+.L st
+access, modify, or change time, respectively, to
+.LR tv .
+The seconds portion of
+.L tv
+is returned.
+.SS "int tvtouch(const char* path, const Tv_t* av, const Tv_t* mv, const Tv_t* cv, int copy)"
+Sets the file
+.L path
+access time from
+.LR av ,
+modify time from
+.LR mv ,
+and change time from
+.LR cv .
+Any of
+.LR av ,
+.LR mv ,
+and
+.L cv
+may be 0; the corresponding file time will retain the previous value if
+.L path
+exists and
+.L copy
+is
+.L 1 ;
+otherwise the corresponding file time will be set to the current time.
+.L 0
+is returned on success,
+.L -1
+on error.
+.SS "int tvsleep(const Tv_t* tv, Tv_t* rv)"
+Pauses execution for
+.L tv
+time.
+.L 0
+is returned if the full
+.L tv
+amount has expired.
+Otherwise
+.L -1
+is returned and
+.LR rv ,
+if not 0, is set to the sleep time remaining.
+.SH "RETURN VALUE"
+Except for
+.LR tvcmp() ,
+an error return of
+.L -1
+also sets
+.L errno
+to the corresponding error code.
+.SH "SEE ALSO"
+tm(3)
diff --git a/src/lib/libast/man/vecargs.3 b/src/lib/libast/man/vecargs.3
new file mode 100644
index 0000000..29e492b
--- /dev/null
+++ b/src/lib/libast/man/vecargs.3
@@ -0,0 +1,126 @@
+.fp 5 CW
+.de Af
+.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2
+.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+..
+.de aF
+.ie \\$3 .ft \\$1
+.el \{\
+.ds ;G \&
+.nr ;G \\n(.f
+.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+\\*(;G
+.ft \\n(;G \}
+..
+.de L
+.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de LR
+.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de RL
+.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH VECARGS 3
+.SH NAME
+vecargs \- command argument vector insertion routines
+.SH SYNOPSIS
+.L "#include <vecargs.h>"
+.sp
+.L "char** vecload(char* string);"
+.L "char** vecfile(const char* path);"
+.L "char** vecstring(const char* string);"
+.L "void vecfree(char**, int);"
+.L "int vecargs(char** vec, int* argcp, char*** argvp);"
+.SH DESCRIPTION
+.L vecload
+loads a string vector from lines in
+.LR string .
+.L string
+may be modified upon return.
+Each line in
+.L string
+is treated as a new vector element.
+Lines with
+.L #
+as the first character are comments.
+.I \enewline
+joins consecutive lines.
+A string vector pointer is returned, 0 on error.
+.PP
+.L vecfile
+constructs a string vector by calling
+.L vecload
+on the contents of the file named by
+.LR path .
+The string vector pointer is returned, 0 on error.
+.PP
+.L vecstring
+constructs a string vector by calling
+.L vecload
+on a copy of
+.LR string .
+The string vector pointer is returned, 0 on error.
+.PP
+.L vecfree
+frees a string vector allocated by
+.LR vecfile ,
+.L vecload
+or
+.LR vecstring .
+.PP
+.L vecargs
+inserts the string vector
+.L vec
+(as returned by
+.LR vecfile ,
+.L vecload
+or
+.LR vecstring )
+between
+.L "(*argvp)[0]"
+and
+.LR "(*argvp)[1]" ,
+sliding
+.L "(*argvp)[1] ..."
+over.
+NULL and empty string args in
+.L vec
+are not copied.
+.L "vecfree(vec)"
+is called before the return.
+.L \-1
+is returned if the insertion failed.
+.SH EXAMPLES
+.L vecargs
+is commonly used to modify command
+.L argv
+from fixed files.
+For example,
+.IR make (1)
+checks for the files
+.L ./Makeargs
+and
+.L ./makeargs
+to modify its arguments on startup.
+Its a handy way to override default options on a directory by directory basis
+without modify the standard control files
+(\f5Makefile\fP in this case.)
+.SH CAVEATS
+This paradigm is not recommended for all commands; only a few exceptions
+make sense.
diff --git a/src/lib/libast/man/vmalloc.3 b/src/lib/libast/man/vmalloc.3
new file mode 100644
index 0000000..3bc6413
--- /dev/null
+++ b/src/lib/libast/man/vmalloc.3
@@ -0,0 +1,640 @@
+.fp 5 CW
+.de MW
+\f5\\$1\fP
+..
+.TH VMALLOC 3 "1 May 1998"
+.SH NAME
+vmalloc \- virtual memory allocation
+.SH SYNOPSIS
+.MW "#include <vmalloc.h>"
+.SS Regions
+.nf
+.MW "Vmalloc_t* vmopen(Vmdisc_t* disc, Vmethod_t* meth, int flags);"
+.MW "int vmclose(Vmalloc_t*);"
+.MW "int vmclear(Vmalloc_t*);"
+.MW "int vmcompact(Vmalloc_t* region);"
+.MW "int vmset(Vmalloc_t* region, int flags, int type);"
+.MW "Vmalloc_t* Vmheap;"
+.MW "Vmdisc_t* vmdisc(Vmalloc_t* region, Vmdisc_t* disc);"
+.MW "Vmalloc_t* vmmopen(char* file, int project, ssize_t size);"
+.MW "Void_t* vmmvalue(Vmalloc_t* vm, int key, Void_t* value, int op);"
+.MW "Void_t* vmmcleanup(Vmalloc_t* vm);"
+.MW "Void_t* vmmaddress(size_t size);"
+.fi
+.SS "Allocation functions"
+.nf
+.MW "Void_t* vmalloc(Vmalloc_t* region, size_t size);"
+.MW "Void_t* vmalign(Vmalloc_t* region, size_t size, size_t align);"
+.MW "Void_t* vmresize(Vmalloc_t* region, Void_t* addr, size_t size, int type);"
+.MW "int vmfree(Vmalloc_t* region, Void_t* addr);"
+.MW "Void_t* vmnewof(Vmalloc_t* region, Void_t* addr, type, size_t n, size_t x);"
+.MW "Void_t* vmoldof(Vmalloc_t* region, Void_t* addr, type, size_t n, size_t x);"
+.MW "Void_t* vmgetmem(Vmalloc_t* region, Void_t* addr, size_t size);"
+.fi
+.SS "Debugging"
+.nf
+.MW "int vmdebug(int);"
+.MW "int vmdbcheck(Vmalloc_t* vm);"
+.MW "int vmdbwatch(Void_t* addr);"
+.MW "static void vmdbwarn(Vmalloc_t*, char* mesg, int n);"
+.fi
+.SS "Profiling"
+.nf
+.MW "void vmprofile(Vmalloc_t* vm, int fd);"
+.fi
+.SS "Information and statistics"
+.nf
+.MW "int vmbusy(Vmalloc_t* region);"
+.MW "Vmalloc_t* vmregion(Void_t* addr);"
+.MW "Void_t* vmsegment(Vmalloc_t* region, Void_t* addr);"
+.MW "int vmwalk(Vmalloc_t* region, int(*walkf)(Vmalloc_t*, Void_t*, size_t, Vmdisc_t*);"
+.MW "long vmaddr(Vmalloc_t* region, Void_t* addr);"
+.MW "long vmsize(Vmalloc_t* region, Void_t* addr);"
+.MW "int vmstat(Vmalloc_t* vm, Vmstat_t* statb);"
+.MW "int vmtrace(int fd);"
+.MW "int vmtrbusy(Vmalloc_t* vm);"
+.MW "Void_t* vmdata(Vmalloc_t* vm);"
+.fi
+.SS "Malloc-compatible functions"
+.nf
+.MW "Void_t* malloc(size_t size);"
+.MW "Void_t* realloc(Void_t* addr, size_t size);"
+.MW "Void_t* calloc(size_t n_obj, size_t s_obj);"
+.MW "int cfree(Void_t* addr);"
+.MW "void free(Void_t* addr);"
+.MW "Void_t* memalign(size_t align, size_t size);"
+.MW "Void_t* valloc(size_t size);"
+.MW "int setregmax(int regmax);"
+.fi
+.SH DESCRIPTION
+These functions for dynamic storage allocation work in
+\fIregions\fP of memory.
+Each region has an \fIallocation method\fP
+for parceling out blocks of storage and a
+\fImemory discipline\fP for obtaining raw space.
+Automatic locking prevents interference by reentrant
+access to a region.
+.PP
+Pointers to space have type \f5Void_t*\fP
+where \f5Void_t\fP is \f5#define\fPd as \f5void\fP if possible, otherwise \f5char\fP.
+Space is counted in type \f5size_t\fP.
+
+.ne 4
+.SS Regions
+Regions have type \f5Vmalloc_t\fP.
+Two predefined regions are pointed to by:
+.TP
+.MW Vmheap
+A general-purpose region, with best-fit
+allocation, and system memory discipline \f5Vmdcsystem\fP.
+.PP
+These functions manipulate regions:
+.PP
+.I vmopen
+creates a region with memory discipline \fIdisc\fP,
+allocation method \fImeth\fP,
+and a setting for control \fIflags\fP.
+It returns a pointer to the region on success and \f5NULL\fP on failure.
+The flags, represented by bit values or-ed together, are:
+.TP
+.MW VM_SHARE
+This region may be accessed concurrently by multiple threads or processes.
+.TP
+.MW VM_TRACE
+Place tracing messages for each allocation event
+on the tracing file established by \fIvmtrace\fP.
+.TP
+\f5VM_DBCHECK\fP, \f5VM_DBABORT\fP
+.br
+See \fBDebugging\fP below.
+.PP
+.I vmclose
+closes a \fIregion\fP and releases all associated memory
+according to the region's discipline.
+The first segment obtained from the discipline's
+\f5memoryf\fP function (see `Disciplines' below) will be the last released.
+\fIvmclose\fP returns \-1 on failure and a non-negative value otherwise.
+.PP
+.I vmclear
+frees all allocated blocks in \fIregion\fP regardless of methods.
+It returns \-1 on failure and a non-negative value otherwise.
+.PP
+.I vmcompact
+releases as much of a \fIregion\fP's
+free space to its discipline's \f5memoryf\fP
+function as possible.
+It returns a nonnegative value on success and \-1 on failure.
+.PP
+.I vmset
+adjusts and queries a \fIregion\fP's \fIflags\fP.
+The indicated flags are turned on if \fItype\fP is nonzero, off if zero.
+\fIvmset\fP returns the previous value of all flags.
+Thus, \f5vmset(region,0,0)\fP queries the flags without changing them.
+In addition to the settable flags, one of
+\f5VM_MTBEST\fP, \f5VM_MTDEBUG\fP, \f5VM_MTPROFILE\fP,
+\f5VM_MTPOOL\fP, or \f5VM_MTLAST\fP
+is returned to indicate the method used in creating the \fIregion\fP.
+.PP
+.I vmdisc
+changes the discipline of \fIregion\fP to the given new discipline
+\fIdisc\fP if \fIdisc\fP is not \f5NULL\fP and its \f5memoryf\fP function
+is the same as the current discipline. If the current discipline
+has an \f5exceptf\fP function, it will be called with event \f5VM_DISC\fP.
+This function always returns the current discipline.
+.PP
+.I vmmopen
+creates a region to allocate memory obtained via either
+\fImmap(2)\fP when \fIproject < 0\fP or \fIshmget(2)\fP when \fIproject >= 0\fP.
+The region is built from a single memory segment
+guaranteed to be at least as large as \fIsize\fP.
+When \fIproject >= 0\fP,
+\fIfile\fP and \fIproject\fP are used in a call to \fIftok(3)\fP
+to get a key suitable for getting a shared memory segment via \fIshmget(2)\fP.
+Otherwise, \fIfile\fP is the backing store for the mapped data.
+In this case, not only the region may be used concurrently by different processes,
+it is also persistent. That is, process could even exit, move the file to
+a different but similar machine then restart and open the same
+region to continue working.
+.PP
+Note that Vmalloc can protect concurrent accesses only on region entry and exit
+for memory allocation operations.
+This means that at the time when regions are being opened or closed, there will be no
+protection for the memory segments being attached into or detached from process memory space.
+This limitation has a special impact on \fIvmmopen()\fP as follows.
+.PP
+A shared memory segment opened via \fIvmmopen()\fP corresponds uniquely
+to a combination of the \fIfile\fP and \fIproject\fP parameters.
+Thus, if multiple \fIvmmopen()\fP calls are done in the same process using a
+same combination of \fIfile\fP and \fIproject\fP,
+the joined behavior of such regions will be unpredictable when opening and closing
+are done concurrently with other memory allocation operations.
+Beware that this effect can be subtle with library functions that may attempt
+to create their own memory allocation regions.
+.PP
+.I vmmvalue
+manages pairs of \fIkey\fP and \fIvalue\fP in a region opened via \fIvmopen()\fP.
+If \fIop\fP is \f5VM_MMGET\fP, the value associated with \f5key\fP is returned.
+If \fIop\fP is \f5VM_MMSET\fP, the value associated with \f5key\fP will be
+set to \fIvalue\fP.
+If \fIop\fP is \f5VM_MMADD\fP, the value associated with \f5key\fP will be
+treated as a signed long value to which \f5val\fP (also treated as a signed long value)
+will be added.
+The call always returns the updated data value associated with \fIkey\fP.
+.PP
+.I vmmcleanup
+sets region up to remove backing store or \fIshmid\fP on closing.
+.PP
+.I vmmaddress
+computes an address suitable for attaching a shared memory segment or
+memory mapping a segment of file data of the given \fIsize\fP.
+The address is chosen with hope to minimize collision with other activities
+related to memory such as growth of stack space or space used
+for dynamically linked libraries, etc.
+
+.SS "Allocation functions"
+.I vmalloc
+returns a pointer to a block of the requested \fIsize\fP
+in a \fIregion\fP, aligned to the \fIstrictest alignment\fP
+that is suitable for the needs of any basic data type.
+It returns \f5NULL\fP on failure.
+.PP
+.I vmalign
+works like \fIvmalloc\fP, but returns a block aligned to a common
+multiple of \fIalign\fP and the \fIstrictest alignment\fP.
+.PP
+.I vmresize
+attempts to change the length of the block pointed to by
+\fIaddr\fP to the specified \fIsize\fP.
+If that is impossible and \fItype\fP has
+at least one of \f5VM_RSMOVE\fP and \f5VM_RSCOPY\fP,
+a new block is allocated and the old block is freed.
+The bit \f5VM_RSCOPY\fP also causes
+the new block to be initialized with
+as much of the old contents as will fit.
+When a resized block gets larger, the new space will be cleared
+if \fItype\fP has the bit \f5VM_RSZERO\fP.
+\fIvmresize\fP
+returns a pointer to the final block, or \f5NULL\fP on failure.
+If \fIaddr\fP is \f5NULL\fP, \fIvmresize\fP behaves like \fIvmalloc\fP;
+otherwise, if \fIsize\fP is 0, it behaves like \fIvmfree\fP.
+.PP
+.I vmfree
+makes the currently allocated block pointed to by
+\fIaddr\fP available for future allocations in its \fIregion\fP.
+If \fIaddr\fP is \f5NULL\fP, \fIvmfree\fP does nothing.
+It returns \-1 on error, and nonnegative otherwise.
+.PP
+.I vmnewof
+is a macro function that attempts to change the length of
+the block pointed to by \fIaddr\fP to the size \f5n*sizeof(type)+x\fP.
+If the block is moved, new space will be initialized with as much of the
+old content as will fit.
+Additional space will be set to zero.
+.PP
+.I vmoldof
+is similar to \fIvmnewof\fP but it neither copies data nor clears space.
+.PP
+.I vmgetmem
+provides a handy function to creat/close regions and allocate/free memory
+based on chunks of memory obtained from the heap region \fIVmheap\fP.
+.TP
+.MW "vmgetmem(0,0,0)"
+This call opens a new region.
+.TP
+.MW "vmgetmem(region, 0, 0)"
+This call closes the given \f5region\fP.
+.TP
+.MW "vmgetmem(region,0,n)"
+This call allocates a block of length \f5n\fP and clears it to zeros.
+.TP
+.MW "vmgetmem(region,p,0)"
+This call frees the block \f5p\fP.
+.TP
+.MW "vmgetmem(region,p,n)"
+This call resizes the block \f5p\fP to length \f5n\fP
+and clears the new memory to zeros if the block grows.
+The block may be moved as deemed necessary by the allocator.
+.PP
+.SS "Memory disciplines"
+Memory disciplines have type \f5Vmdisc_t\fP,
+a structure with these members:
+.in +.5i
+.nf
+.MW "Void_t* (*memoryf)(Vmalloc_t *region, Void_t* obj,"
+.ti +.5i
+.MW "size_t csz, size_t nsz, Vmdisc_t *disc);"
+.MW "int (*exceptf)(Vmalloc_t *region, int type, Void_t* obj, Vmdisc_t *disc);"
+.MW "int round;"
+.fi
+.in -.5i
+.TP
+.MW round
+If this value is positive, all size arguments to the
+\f5memoryf\fP function will be multiples of it.
+.TP
+.MW memoryf
+Points to a function to get or release segments of space for the
+\fIregion\fP.
+.TP
+.MW exceptf
+If this pointer is not \f5NULL\fP,
+the function it points to is called to announce
+events in a \fIregion\fP.
+.PP
+There are two standard disciplines, both with \f5round\fP being 0 and \f5exceptf\fP being \f5NULL\fP.
+.TP
+.MW Vmdcsystem
+A discipline whose \f5memoryf\fP function gets space from the operation system
+via different available methods which include \fImmap(2)\fP, \fIsbrk(2)\fP and
+functions from the WIN32 API.
+For historical reason, \fIVmdcsbrk\fP is also available and functions like \fIVmdcsystem\fP.
+.TP
+.MW Vmdcheap
+A discipline whose \f5memoryf\fP function gets space from the region \f5Vmheap\fP.
+A region with \f5Vmdcheap\fP discipline and \f5Vmlast\fP
+allocation is good for building throwaway data structures.
+.PP
+A \fImemoryf\fP
+function returns a pointer to a memory segment on success, and \f5NULL\fP on failure.
+When \fInsz >= 0\fP and \fIcsz > 0\fP,
+the function first attempts to change the current segment \fIaddr\fP to fit \fInsz\fP
+(for example, \fInsz == 0\fP means deleting the segment \fIaddr\fP).
+If this attempt is successful, it should return \fIaddr\fP.
+Otherwise, if \fInsz > csz\fP, the function may try to allocate a new segment
+of size \fInsz-csz\fP. If successful, it should return the address of the new segment.
+In all other cases, it should return NULL.
+.PP
+An \fIexceptf\fP
+function is called for events identified by \fItype\fP, which is coded thus:
+.TP
+.MW VM_OPEN
+This event is raised at the start of the process to open a new region.
+Argument \fIobj\fP will be a pointer to an object of type \f5Void_t*\fP
+initialized to NULL before the call. The return value of \fIexceptf\fP
+is significant as follows:
+
+On a negative return value, \fIvmopen\fP will terminate with failure.
+
+On a zero return value, \fIexceptf\fP may set \f5*((Void_t**)obj)\fP
+to some non-NULL value to tell \fIvmopen\fP
+to allocate the region handle itself via \fImemoryf\fP. Otherwise,
+the region handle will be allocated from the \f5Vmheap\fP region.
+
+On a positive return value,
+the new region is being reconstructed
+based on existing states of some previous region.
+In this case, \fIexceptf\fP should set \f5*(Void_t**)\fP\fIobj\fP to point to
+the field \f5Vmalloc_t.data\fP of the corresponding previous region
+(see \f5VM_CLOSE\fP below).
+If the handle of the previous region was allocated
+via \fImemoryf\fP as discussed above in the case of the zero return value,
+then it will be exactly restored. Otherwise, a new handle will be allocated from \f5Vmheap\fP.
+The ability to create regions sharing the same states allows for
+managing shared and/or persistent memory.
+.TP
+.MW VM_ENDOPEN
+This event is raised at the end of the process to open a new region.
+The return value of \fIexceptf\fP will be ignored.
+.TP
+.MW VM_CLOSE
+This event is raised at the start of the process to close a region,
+The return value of \fIexceptf\fP is significant as follows:
+
+On a negative return value, \fIvmclose\fP immediately returns with failure.
+
+On a zero return value, \fIvmclose\fP proceeds normally by calling \f5memoryf\fP to free
+all allocated memory segments and also freeing the region itself.
+
+On a positive return value, \fIvmclose\fP will only free the region
+without deallocating the associated memory segments. That is,
+the field \fIVmalloc_t.data\fP of the region handle remains intact.
+This is useful for managing shared and/or persistent memory (see \f5VM_OPEN\fP above).
+.TP
+.MW VM_ENDCLOSE
+This event is raised at the end of the process to close a region.
+The return value of \fIexceptf\fP will be ignored.
+.TP
+.MW VM_NOMEM
+An attempt to extend the region by the amount
+\f5(size_t)\fP\fIobj\fP failed. The region is unlocked, so the
+\fIexceptf\fP function may free blocks.
+If the function returns a positive value the memory
+request will be repeated.
+.TP
+.MW VM_DISC
+The discipline structure is being changed.
+
+.SS "Allocation methods"
+Methods are of type \f5Vmethod_t*\fP.
+.TP
+.MW Vmbest
+An approximately best-fit allocation strategy.
+.TP
+.MW Vmlast
+A strategy for building structures that are only deleted in whole.
+Only the latest allocated block can be freed.
+This means that as soon as a block \f5a\fP is allocated,
+\fIvmfree\fP calls on blocks other than \c5a\fP are ignored.
+.TP
+.MW Vmpool
+A strategy for blocks of one size,
+set by the first \fIvmalloc\fP call after \fIvmopen\fP or \fIvmclear\fP.
+.TP
+.MW Vmdebug
+An allocation strategy with extra-stringent checking and locking.
+It is useful for finding misuses of dynamically allocated
+memory, such as writing beyond the boundary of a block, or
+freeing a block twice.
+.ne 3
+.TP
+.MW Vmprofile
+An allocation method that records and prints summaries of memory usage.
+
+.SS Debugging
+The method \f5Vmdebug\fP is used to debug common memory violation problems.
+When a problem is found,
+a warning message is written to file descriptor 2 (standard error).
+In addition, if flag \f5VM_DBABORT\fP is on,
+the program is terminated by calling \fIabort\fP(2).
+Each message is a line of self-explanatory fields separated by colons.
+The optional flag \f5-DVMFL\fP, if used during compilation,
+enables recording of file names and line numbers.
+The following functions work with method \f5Vmdebug\fP.
+.PP
+.I vmdebug
+resets the file descriptor to write out warnings to the given argument.
+By default, this file descriptor is 2, the standard error.
+\fIvmdebug\fP returns the previous file descriptor.
+.PP
+.I vmdbcheck
+checks a region using \f5Vmdebug\fP or \f5Vmbest\fP for integrity.
+If \f5Vmdebug\fP, this also checks for block overwriting errors.
+On errors, \fIvmdbwarn\fP is called.
+If flag \f5VM_DBCHECK\fP is on,
+\fIvmdbcheck\fP is called at each invocation of
+\fIvmalloc\fP, \fIvmfree\fP, or \fIvmresize\fP.
+.PP
+.I vmdbwatch
+causes address \fIaddr\fP
+to be watched, and reported whenever met in
+\fIvmalloc\fP, \fIvmresize\fP or \fIvmfree\fP.
+The watch list has finite size and if it becomes full,
+watches will be removed in a first-in-first-out fashion.
+If \fIaddr\fP is \f5NULL\fP,
+all current watches are canceled.
+\fIvmdbwatch\fP returns the watch bumped out due to an insertion
+into a full list or \f5NULL\fP otherwise.
+.PP
+.I vmdbwarn
+is an internal function that processes
+warning messages for discovered errors.
+It can't be called from outside the \fIvmalloc\fP package,
+but is a good place to plant debugger traps because
+control goes there at every trouble.
+
+.SS "Profiling"
+The method \f5Vmprofile\fP is used to profile memory usage.
+Profiling data are maintained in private memory of a process so
+\f5Vmprofile\fP should be avoided from regions manipulating
+persistent or shared memory.
+The optional flag \f5-DVMFL\fP, if used during compilation,
+enables recording of file names and line numbers.
+.PP
+.I vmprofile
+prints memory usage summary.
+The summary is restricted to region \fIvm\fP if \fIvm\fP is not \f5NULL\fP;
+otherwise, it is for all regions created with \f5Vmprofile\fP.
+Summary records are written to file descriptor \fIfd\fP as lines with
+colon-separated fields. Here are some of the fields:
+.TP
+.I n_alloc,n_free:
+Number of allocation and free calls respectively. Note that a resize
+operation is coded as a free and an allocation.
+.TP
+.I s_alloc,s_free:
+Total amounts allocated and freed. The difference between these numbers
+is the amount of space not yet freed.
+.TP
+.I max_busy, extent:
+These fields are only with the summary record for region.
+They show the maximum busy space at any time and the extent of the region.
+
+.SS "Information and statistics"
+.I vmbusy
+returns the busy status of a region.
+A region is busy if some allocation operation is accessing it.
+.PP
+.I vmregion
+returns the region to which the block pointed to by
+\fIaddr\fP belongs.
+This works only in regions that allocate with
+\f5Vmbest\fP, \f5Vmdebug\fP or \f5Vmprofile\fP.
+.PP
+.I vmsegment
+finds if some segment of memory in \fIregion\fP
+contains the address \fIaddr\fP.
+It returns the address of a found segment or \f5NULL\fP if none found.
+.PP
+.I vmwalk
+walks all segments in \fIregion\fP or if \fIregion\fP is \f5NULL\fP,
+all segments in all regions.
+At each segment, \fI(*walkf)(vm,addr,size,disc)\fP
+is called where \fIvm\fP is the region, \fIaddr\fP is the segment,
+\fIsize\fP is the size of the segment, and \fIdisc\fP is the region's discipline.
+If \fIwalkf\fP returns a negative value, the walk stops and returns the same value.
+On success, \fIvmwalk\fP returns 0; otherwise, it returns \-1.
+.PP
+.I vmaddr
+checks whether \fIaddr\fP
+points to an address within some allocated block of the given region.
+If not, it returns \-1.
+If so, it returns the offset from the beginning of the block.
+The function does not work for a \f5Vmlast\fP region except
+on the latest allocated block.
+.PP
+.I vmsize
+returns the size of the allocated block pointed to by \fIaddr\fP.
+It returns \-1 if \fIaddr\fP
+does not point to a valid block in the region.
+Sizes may be padded beyond that requested; in
+particular no block has size 0.
+The function does not work for a \f5Vmlast\fP region except
+on the latest allocated block.
+.PP
+.I vmstat
+gathers statistics on the given \fIregion\fP.
+If \f5region\fP is NULL, it computes statistics for the \fIMalloc\fP calls.
+This may include summing statistics from more than one regions constructed to avoid blocking
+due to parallel or asynchronous operations.
+If \fIstatb\fP is not NULL, \fIvmstat\fP computes and stores the statistics in \fIstatb\fP then returns 0.
+If \fIstatb\fP is NULL, no statistics will be computed and
+the returned value is either 1 if the region is busy, i.e.,
+being accessed by some allocation call or 0 otherwise.
+
+A \f5Vmstat_t\fP structure has at least these members:
+.in +.5i
+.nf
+.ta \w'\f5size_t \fP'u +\w'\f5extent \fP'u
+.MW "int n_busy; /* # of busy blocks */
+.MW "int n_free; /* # of free blocks */
+.MW "size_t s_busy; /* total busy space */
+.MW "size_t s_free; /* total free space */
+.MW "size_t m_busy; /* maximum busy block size */
+.MW "size_t m_free; /* maximum free block size */
+.MW "int n_seg; /* count of segments */
+.MW "size_t extent; /* memory extent of region */
+.MW "int n_region; /* total Malloc regions */
+.MW "int n_open; /* non-blocked operations */
+.MW "int n_lock; /* blocked operations */
+.MW "int n_probe; /* region searches */
+.fi
+.in -.5i
+.PP
+Bookeeping overhead is counted in \f5extent\fP,
+but not in \f5s_busy\fP or \f5s_free\fP.
+.PP
+.I vmtrace
+establishes file descriptor \fIfd\fP
+as the trace file and returns
+the previous value of the trace file descriptor.
+The trace descriptor is initially invalid.
+Output is sent to the trace file by successful allocation
+events when flag \f5VM_TRACE\fP is on.
+.PP
+Tools for analyzing traces are described in \fImtreplay\fP(1).
+The trace record for an allocation event
+is a line with colon-separated fields, four numbers and one string.
+.TP
+.I old
+Zero for a fresh allocation;
+the address argument for freeing and resizing.
+.TP
+.I new
+Zero for freeing;
+the address returned by allocation or resizing.
+.TP
+.I size
+The size argument for allocation or resizing;
+the size freed by freeing.
+Sizes may differ due to padding for alignment.
+.TP
+.I region
+The address of the affected region.
+.TP
+.I method
+A string that tells the region's method:
+\f5best\fP, \f5last\fP, \f5pool\fP, \f5profile\fP, or \f5debug\fP.
+.PP
+.I vmtrbusy
+outputs a trace of all currently busy blocks in region \f5vm\fP.
+This only works with the \f5Vmbest\fP, \f5Vmdebug\fP and \f5Vmprofile\fP methods.
+.PP
+.I vmdata
+returns the core data of the given region.
+The core data hold the data structures for allocated and free blocks.
+Depending on the region discipline,
+the core data of a region may be in shared or persistent memory even
+if the region pointer created with \fIvmopen\fP is always in private process memory.
+
+.SS "Malloc-compatible functions"
+This set of functions implement \fImalloc\fP(3).
+They allocate via the \fIVmregion\fP region which is initially set
+to be \fIVmheap\fP.
+
+Concurrent accesses are supported unless an application
+change \fIVmregion\fP to something other than \fIVmheap\fP.
+New regions may be created on the fly to avoid blocking.
+The maximum number of regions that can be created
+this way is set to 64 by default. An application could
+reduce this number by calling \fIsetregmax(regmax)\fP to
+set the maximum number of these extra regions to \fIregmax\fP.
+\fIsetregmax()\fP always returns the previous value.
+.PP
+These functions are instrumented for run-time debugging, profiling and tracing.
+For accurate reporting of files and line numbers,
+application code should include \f5vmalloc.h\fP and compile with \f5-DVMFL\fP.
+The following environment variables can be set before any memory allocation
+(e.g., before a process starts) to drive different modes:
+.TP
+.I VMETHOD
+This defines the method to use for allocation.
+Its value should be one of the strings:
+\fIVmbest, Vmdebug, Vmprofile, Vmlast, Vmpool\fP.
+The 'V' can be in lower case.
+.TP
+.I VMDEBUG
+This is ignored if
+a method other than \f5Vmdebug\fP has been selected with \fIVMETHOD\fP.
+\fIVMDEBUG\fP can be any combination of `a',
+a decimal number and a list of hexadecimal numbers.
+`a' causes the program to abort on any discovered allocation error.
+A hexadecimal number starts with either \fI0x\fP or \fI0X\fP
+and defines an address to watch (see \fIvmdbwatch\fP).
+Any other number is taken to be decimal and defines a period \fIp\fP
+to check the arena for integrity. The default period is 1, ie, the
+arena is checked on every call to a \fImalloc\fP function.
+Other letters not part of the defined set are ignored.
+.TP
+.I VMPROFILE
+This is ignored if a method other than \f5Vmprofile\fP
+has been selected by \fIVMETHOD\fP or \fIVMDEBUG\fP.
+\fIVMPROFILE\fP defines a file name to store profile data.
+Each instance of the pattern `%p' found in \fIVMPROFILE\fP
+is transformed to the process id of the running process.
+If the file cannot be created, file descriptor 2 (standard error)
+is used for output.
+.TP
+.I VMTRACE
+If this defines a valid writable file, trace messages of all allocation calls
+are written to the given file (see \fIvmopen()\fP and \fIvmtrace()\fP).
+Similar to \fIVMPROFILE\fP, each instance of the pattern `%p' found
+in \fIVMTRACE\fP is turned to the process id of the running process.
+
+.SH RECENT CHANGES
+\f5Vmlast\fP: allocated blocks are now allowed to be resized (09/1998).
+
+.SH SEE ALSO
+\fImtreplay\fP(1), \fImalloc\fP(3).
+
+.SH AUTHOR
+Kiem-Phong Vo, kpv@research.att.com
diff --git a/src/lib/libast/misc/astintercept.c b/src/lib/libast/misc/astintercept.c
new file mode 100644
index 0000000..c4e84cb
--- /dev/null
+++ b/src/lib/libast/misc/astintercept.c
@@ -0,0 +1,53 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "intercepts.h"
+
+/*
+ * NOTE: the "intercepts" definition is in getenv.c because some static linkers
+ * miss lone references to "intercepts" without "astintercept()"
+ */
+
+/*
+ * set/clear ast intercept callouts
+ */
+
+int
+astintercept(Shbltin_t* call, int set)
+{
+ if (call->shgetenv)
+ {
+ if (set)
+ intercepts.intercept_getenv = call->shgetenv;
+ else
+ intercepts.intercept_getenv = 0;
+ }
+ if (call->shsetenv)
+ {
+ if (set)
+ intercepts.intercept_setenviron = call->shsetenv;
+ else
+ intercepts.intercept_setenviron = 0;
+ }
+ return 0;
+}
diff --git a/src/lib/libast/misc/cmdarg.c b/src/lib/libast/misc/cmdarg.c
new file mode 100644
index 0000000..38d247b
--- /dev/null
+++ b/src/lib/libast/misc/cmdarg.c
@@ -0,0 +1,382 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * xargs/tw command arg list support
+ */
+
+#define _AST_API_H 1
+
+#include <ast.h>
+#include <cmdarg.h>
+
+Cmdarg_t*
+cmdopen(char** argv, int argmax, int size, const char* argpat, int flags)
+{
+ Error_f ef;
+
+ if (flags & CMD_SILENT)
+ ef = 0;
+ else
+ {
+ ef = errorf;
+ flags |= CMD_EXIT;
+ }
+ return cmdopen_20110505(argv, argmax, size, argpat, flags, ef);
+}
+
+#undef _AST_API_H
+
+#include <ast_api.h>
+
+#include <ctype.h>
+#include <proc.h>
+
+#ifndef ARG_MAX
+#define ARG_MAX (64*1024)
+#endif
+#ifndef EXIT_QUIT
+#define EXIT_QUIT 255
+#endif
+
+static const char* echo[] = { "echo", 0 };
+
+/*
+ * open a cmdarg stream
+ * initialize the command for execution
+ * argv[-1] is reserved for procrun(PROC_ARGMOD)
+ */
+
+Cmdarg_t*
+cmdopen_20110505(char** argv, int argmax, int size, const char* argpat, int flags, Error_f errorf)
+{
+ register Cmdarg_t* cmd;
+ register int n;
+ register char** p;
+ register char* s;
+ char* sh;
+ char* exe;
+ int c;
+ int m;
+ int argc;
+ long x;
+
+ char** post = 0;
+
+ n = sizeof(char**);
+ if (*argv)
+ {
+ for (p = argv + 1; *p; p++)
+ {
+ if ((flags & CMD_POST) && argpat && streq(*p, argpat))
+ {
+ *p = 0;
+ post = p + 1;
+ argpat = 0;
+ }
+ else
+ n += strlen(*p) + 1;
+ }
+ argc = p - argv;
+ }
+ else
+ argc = 0;
+ for (p = environ; *p; p++)
+ n += sizeof(char**) + strlen(*p) + 1;
+ if ((x = strtol(astconf("ARG_MAX", NiL, NiL), NiL, 0)) <= 0)
+ x = ARG_MAX;
+ if (size <= 0 || size > x)
+ size = x;
+ sh = pathshell();
+ m = n + (argc + 4) * sizeof(char**) + strlen(sh) + 1;
+ m = roundof(m, sizeof(char**));
+ if (size < m)
+ {
+ if (errorf)
+ (*errorf)(NiL, sh, 2, "size must be at least %d", m);
+ return 0;
+ }
+ if ((m = x / 10) > 2048)
+ m = 2048;
+ if (size > (x - m))
+ size = x - m;
+ n = size - n;
+ m = ((flags & CMD_INSERT) && argpat) ? (strlen(argpat) + 1) : 0;
+ if (!(cmd = newof(0, Cmdarg_t, 1, n + m)))
+ {
+ if (errorf)
+ (*errorf)(NiL, sh, ERROR_SYSTEM|2, "out of space");
+ return 0;
+ }
+ cmd->errorf = errorf;
+ c = n / sizeof(char**);
+ if (argmax <= 0 || argmax > c)
+ argmax = c;
+ s = cmd->buf;
+ if (!(exe = argv[0]))
+ {
+ exe = *(argv = (char**)echo);
+ cmd->echo = 1;
+ }
+ else if (streq(exe, echo[0]))
+ {
+ cmd->echo = 1;
+ flags &= ~CMD_NEWLINE;
+ }
+ else if (!(flags & CMD_CHECKED))
+ {
+ if (!pathpath(exe, NiL, PATH_REGULAR|PATH_EXECUTE, s, n + m))
+ {
+ n = EXIT_NOTFOUND;
+ if (errorf)
+ (*cmd->errorf)(NiL, cmd, ERROR_SYSTEM|2, "%s: command not found", exe);
+ if (flags & CMD_EXIT)
+ (*error_info.exit)(n);
+ free(cmd);
+ return 0;
+ }
+ exe = s;
+ }
+ s += strlen(s) + 1;
+ if (m)
+ {
+ cmd->insert = strcpy(s, argpat);
+ cmd->insertlen = m - 1;
+ s += m;
+ }
+ s += sizeof(char**) - (s - cmd->buf) % sizeof(char**);
+ p = (char**)s;
+ n -= strlen(*p++ = sh) + 1;
+ cmd->argv = p;
+ *p++ = exe;
+ while (*p = *++argv)
+ p++;
+ if (m)
+ {
+ argmax = 1;
+ *p++ = 0;
+ cmd->insertarg = p;
+ argv = cmd->argv;
+ c = *cmd->insert;
+ while (s = *argv)
+ {
+ while ((s = strchr(s, c)) && strncmp(cmd->insert, s, cmd->insertlen))
+ s++;
+ *p++ = s ? *argv : (char*)0;
+ argv++;
+ }
+ *p++ = 0;
+ }
+ cmd->firstarg = cmd->nextarg = p;
+ cmd->laststr = cmd->nextstr = cmd->buf + n;
+ cmd->argmax = argmax;
+ cmd->flags = flags;
+ cmd->offset = ((cmd->postarg = post) ? (argc - (post - argv)) : 0) + 3;
+ return cmd;
+}
+
+/*
+ * flush outstanding command file args
+ */
+
+int
+cmdflush(register Cmdarg_t* cmd)
+{
+ register char* s;
+ register char** p;
+ register int n;
+
+ if (cmd->flags & CMD_EMPTY)
+ cmd->flags &= ~CMD_EMPTY;
+ else if (cmd->nextarg <= cmd->firstarg)
+ return 0;
+ if ((cmd->flags & CMD_MINIMUM) && cmd->argcount < cmd->argmax)
+ {
+ if (cmd->errorf)
+ (*cmd->errorf)(NiL, cmd, 2, "%d arg command would be too long", cmd->argcount);
+ return -1;
+ }
+ cmd->total.args += cmd->argcount;
+ cmd->total.commands++;
+ cmd->argcount = 0;
+ if (p = cmd->postarg)
+ while (*cmd->nextarg++ = *p++);
+ else
+ *cmd->nextarg = 0;
+ if (s = cmd->insert)
+ {
+ char* a;
+ char* b;
+ char* e;
+ char* t;
+ char* u;
+ int c;
+ int m;
+
+ a = cmd->firstarg[0];
+ b = (char*)&cmd->nextarg[1];
+ e = cmd->nextstr;
+ c = *s;
+ m = cmd->insertlen;
+ for (n = 1; cmd->argv[n]; n++)
+ if (t = cmd->insertarg[n])
+ {
+ cmd->argv[n] = b;
+ for (;;)
+ {
+ if (!(u = strchr(t, c)))
+ {
+ b += sfsprintf(b, e - b, "%s", t);
+ break;
+ }
+ if (!strncmp(s, u, m))
+ {
+ b += sfsprintf(b, e - b, "%-.*s%s", u - t, t, a);
+ t = u + m;
+ }
+ else if (b >= e)
+ break;
+ else
+ {
+ *b++ = *u++;
+ t = u;
+ }
+ }
+ if (b < e)
+ *b++ = 0;
+ }
+ if (b >= e)
+ {
+ if (cmd->errorf)
+ (*cmd->errorf)(NiL, cmd, 2, "%s: command too large after insert", a);
+ return -1;
+ }
+ }
+ cmd->nextarg = cmd->firstarg;
+ cmd->nextstr = cmd->laststr;
+ if (cmd->flags & (CMD_QUERY|CMD_TRACE))
+ {
+ p = cmd->argv;
+ sfprintf(sfstderr, "+ %s", *p);
+ while (s = *++p)
+ sfprintf(sfstderr, " %s", s);
+ if (!(cmd->flags & CMD_QUERY))
+ sfprintf(sfstderr, "\n");
+ else if (astquery(1, "? "))
+ return 0;
+ }
+ if (cmd->echo)
+ {
+ n = (cmd->flags & CMD_NEWLINE) ? '\n' : ' ';
+ for (p = cmd->argv + 1; s = *p++;)
+ sfputr(sfstdout, s, *p ? n : '\n');
+ n = 0;
+ }
+ else if ((n = procrun(*cmd->argv, cmd->argv, PROC_ARGMOD|PROC_IGNOREPATH)) == -1)
+ {
+ n = EXIT_NOTFOUND - 1;
+ if (cmd->errorf)
+ (*cmd->errorf)(NiL, cmd, ERROR_SYSTEM|2, "%s: command exec error", *cmd->argv);
+ if (cmd->flags & CMD_EXIT)
+ (*error_info.exit)(n);
+ return n;
+ }
+ else if (n >= EXIT_NOTFOUND - 1)
+ {
+ if (cmd->flags & CMD_EXIT)
+ (*error_info.exit)(n);
+ }
+ else if (!(cmd->flags & CMD_IGNORE))
+ {
+ if (n == EXIT_QUIT && (cmd->flags & CMD_EXIT))
+ (*error_info.exit)(2);
+ if (n)
+ error_info.errors++;
+ }
+ return n;
+}
+
+/*
+ * add file to the command arg list
+ */
+
+int
+cmdarg(register Cmdarg_t* cmd, const char* file, register int len)
+{
+ int i;
+ int r;
+
+ r = 0;
+ if (len)
+ {
+ while ((cmd->nextstr -= len + 1) < (char*)(cmd->nextarg + cmd->offset))
+ {
+ if (cmd->nextarg == cmd->firstarg)
+ {
+ if (cmd->errorf)
+ (*cmd->errorf)(NiL, cmd, 2, "%s: path too long for exec args", file);
+ return -1;
+ }
+ if (i = cmdflush(cmd))
+ {
+ if (r < i)
+ r = i;
+ if (!(cmd->flags & CMD_IGNORE))
+ return r;
+ }
+ }
+ *cmd->nextarg++ = cmd->nextstr;
+ memcpy(cmd->nextstr, file, len);
+ cmd->nextstr[len] = 0;
+ cmd->argcount++;
+ if (cmd->argcount >= cmd->argmax && (i = cmdflush(cmd)) > r)
+ r = i;
+ }
+ return r;
+}
+
+/*
+ * close a cmdarg stream
+ */
+
+int
+cmdclose(Cmdarg_t* cmd)
+{
+ int n;
+
+ if ((cmd->flags & CMD_EXACT) && cmd->argcount < cmd->argmax)
+ {
+ if (cmd->errorf)
+ (*cmd->errorf)(NiL, cmd, 2, "only %d arguments for last command", cmd->argcount);
+ n = -1;
+ }
+ else
+ {
+ cmd->flags &= ~CMD_MINIMUM;
+ n = cmdflush(cmd);
+ }
+ free(cmd);
+ return n;
+}
diff --git a/src/lib/libast/misc/conformance.c b/src/lib/libast/misc/conformance.c
new file mode 100644
index 0000000..12ee2ca
--- /dev/null
+++ b/src/lib/libast/misc/conformance.c
@@ -0,0 +1,151 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <ctype.h>
+
+static char** ids;
+
+static const char* dflt[] = { "ast", "standard", 0 };
+
+/*
+ * initialize the conformance() id list
+ */
+
+static char**
+initconformance(void)
+{
+ char* m;
+ char** p;
+ char* t;
+ int h;
+ int i;
+ int j;
+ int c;
+ Sfio_t* sp;
+
+ static const char* conf[] = { "CONFORMANCE", "HOSTTYPE", "UNIVERSE" };
+
+ p = 0;
+ if (sp = sfstropen())
+ {
+ for (i = h = 0, j = 1; i < elementsof(conf); i++)
+ if (*(m = astconf(conf[i], NiL, NiL)) && (h |= (1<<i)) || !i && (m = "ast"))
+ {
+ t = m;
+ while ((c = *m++) && c != '.')
+ {
+ if (isupper(c))
+ c = tolower(c);
+ sfputc(sp, c);
+ }
+ sfputc(sp, 0);
+ j++;
+ if ((c = (m - t)) == 6 && strneq(t, "linux", 5))
+ {
+ sfputr(sp, "gnu", 0);
+ j++;
+ }
+ else if (c > 3 && strneq(t, "bsd", 3) || c == 7 && strneq(t, "debian", 7))
+ {
+ sfputr(sp, "bsd", 0);
+ j++;
+ }
+ if (h & 1)
+ break;
+ }
+ i = sfstrtell(sp);
+ sfstrseek(sp, 0, SEEK_SET);
+ if (p = newof(0, char*, j, i))
+ {
+ m = (char*)(p + j--);
+ memcpy(m, sfstrbase(sp), i);
+ i = 0;
+ p[i++] = m;
+ while (i < j)
+ {
+ while (*m++);
+ p[i++] = m;
+ }
+ p[i] = 0;
+ }
+ sfstrclose(sp);
+ }
+ if (!p)
+ p = (char**)dflt;
+ return ids = p;
+}
+
+/*
+ * return conformance id if s size n is in conformance
+ * prefix match of s on the conformance id table
+ * s==0 => "standard"
+ */
+
+char*
+conformance(const char* s, size_t n)
+{
+ char** p;
+ char** q;
+ char* m;
+ const char* e;
+ const char* t;
+
+ static uint32_t serial = ~(uint32_t)0;
+
+ if (!(p = ids) || serial != ast.env_serial)
+ {
+ serial = ast.env_serial;
+ if (ids)
+ {
+ if (ids != (char**)dflt)
+ free(ids);
+ ids = 0;
+ }
+ p = initconformance();
+ }
+ if (!s)
+ s = dflt[1];
+ if (!n)
+ n = strlen(s);
+ e = s + n;
+ if (*s == '(')
+ s++;
+ do
+ {
+ while (s < e && (isspace(*s) || *s == ',' || *s == '|'))
+ s++;
+ if (*s == ')')
+ break;
+ for (t = s; s < e && !isspace(*s) && *s != ',' && *s != '|' && *s != ')'; s++);
+ if (s == t)
+ break;
+ q = p;
+ while (m = *q++)
+ if (strneq(t, m, s - t))
+ return m;
+ if (s < e)
+ s++;
+ } while (s < e);
+ return 0;
+}
diff --git a/src/lib/libast/misc/debug.c b/src/lib/libast/misc/debug.c
new file mode 100644
index 0000000..791973c
--- /dev/null
+++ b/src/lib/libast/misc/debug.c
@@ -0,0 +1,66 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * <debug.h> support
+ */
+
+#include <ast.h>
+#include <error.h>
+#include <debug.h>
+
+void
+debug_fatal(const char* file, int line)
+{
+ error(2, "%s:%d: debug error", file, line);
+ abort();
+}
+
+#if _sys_times
+
+#include <times.h>
+#include <sys/resource.h>
+
+double
+debug_elapsed(int set)
+{
+ double tm;
+ struct rusage ru;
+
+ static double prev;
+
+ getrusage(RUSAGE_SELF, &ru);
+ tm = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec/1000000.0;
+ if (set)
+ return prev = tm;
+ return tm - prev;
+}
+
+#else
+
+double
+debug_elapsed(int set)
+{
+ return 0;
+}
+
+#endif
diff --git a/src/lib/libast/misc/error.c b/src/lib/libast/misc/error.c
new file mode 100644
index 0000000..8ac8c60
--- /dev/null
+++ b/src/lib/libast/misc/error.c
@@ -0,0 +1,659 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * error and message formatter
+ *
+ * level is the error level
+ * level >= error_info.core!=0 dumps core
+ * level >= ERROR_FATAL calls error_info.exit
+ * level < 0 is for debug tracing
+ *
+ * NOTE: id && ERROR_NOID && !ERROR_USAGE implies format=id for errmsg()
+ */
+
+#include "lclib.h"
+
+#include <ctype.h>
+#include <ccode.h>
+#include <namval.h>
+#include <sig.h>
+#include <stk.h>
+#include <times.h>
+#include <regex.h>
+
+/*
+ * 2007-03-19 move error_info from _error_info_ to (*_error_infop_)
+ * to allow future Error_info_t growth
+ * by 2009 _error_info_ can be static
+ */
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+
+extern Error_info_t _error_info_;
+
+Error_info_t _error_info_ =
+{
+ 2, exit, write,
+ 0,0,0,0,0,0,0,0,
+ 0, /* version */
+ 0, /* auxilliary */
+ 0,0,0,0,0,0,0, /* top of old context stack */
+ 0,0,0,0,0,0,0, /* old empty context */
+ 0, /* time */
+ translate,
+ 0 /* catalog */
+};
+
+#undef extern
+
+__EXTERN__(Error_info_t, _error_info_);
+
+__EXTERN__(Error_info_t*, _error_infop_);
+
+Error_info_t* _error_infop_ = &_error_info_;
+
+/*
+ * these should probably be in error_info
+ */
+
+static struct State_s
+{
+ char* prefix;
+ Sfio_t* tty;
+ unsigned long count;
+ int breakpoint;
+ regex_t* match;
+} error_state;
+
+#undef ERROR_CATALOG
+#define ERROR_CATALOG (ERROR_LIBRARY<<1)
+
+#define OPT_BREAK 1
+#define OPT_CATALOG 2
+#define OPT_CORE 3
+#define OPT_COUNT 4
+#define OPT_FD 5
+#define OPT_LIBRARY 6
+#define OPT_MASK 7
+#define OPT_MATCH 8
+#define OPT_PREFIX 9
+#define OPT_SYSTEM 10
+#define OPT_TIME 11
+#define OPT_TRACE 12
+
+static const Namval_t options[] =
+{
+ "break", OPT_BREAK,
+ "catalog", OPT_CATALOG,
+ "core", OPT_CORE,
+ "count", OPT_COUNT,
+ "debug", OPT_TRACE,
+ "fd", OPT_FD,
+ "library", OPT_LIBRARY,
+ "mask", OPT_MASK,
+ "match", OPT_MATCH,
+ "prefix", OPT_PREFIX,
+ "system", OPT_SYSTEM,
+ "time", OPT_TIME,
+ "trace", OPT_TRACE,
+ 0, 0
+};
+
+/*
+ * called by stropt() to set options
+ */
+
+static int
+setopt(void* a, const void* p, register int n, register const char* v)
+{
+ NoP(a);
+ if (p)
+ switch (((Namval_t*)p)->value)
+ {
+ case OPT_BREAK:
+ case OPT_CORE:
+ if (n)
+ switch (*v)
+ {
+ case 'e':
+ case 'E':
+ error_state.breakpoint = ERROR_ERROR;
+ break;
+ case 'f':
+ case 'F':
+ error_state.breakpoint = ERROR_FATAL;
+ break;
+ case 'p':
+ case 'P':
+ error_state.breakpoint = ERROR_PANIC;
+ break;
+ default:
+ error_state.breakpoint = strtol(v, NiL, 0);
+ break;
+ }
+ else
+ error_state.breakpoint = 0;
+ if (((Namval_t*)p)->value == OPT_CORE)
+ error_info.core = error_state.breakpoint;
+ break;
+ case OPT_CATALOG:
+ if (n)
+ error_info.set |= ERROR_CATALOG;
+ else
+ error_info.clear |= ERROR_CATALOG;
+ break;
+ case OPT_COUNT:
+ if (n)
+ error_state.count = strtol(v, NiL, 0);
+ else
+ error_state.count = 0;
+ break;
+ case OPT_FD:
+ error_info.fd = n ? strtol(v, NiL, 0) : -1;
+ break;
+ case OPT_LIBRARY:
+ if (n)
+ error_info.set |= ERROR_LIBRARY;
+ else
+ error_info.clear |= ERROR_LIBRARY;
+ break;
+ case OPT_MASK:
+ if (n)
+ error_info.mask = strtol(v, NiL, 0);
+ else
+ error_info.mask = 0;
+ break;
+ case OPT_MATCH:
+ if (error_state.match)
+ regfree(error_state.match);
+ if (n)
+ {
+ if ((error_state.match || (error_state.match = newof(0, regex_t, 1, 0))) && regcomp(error_state.match, v, REG_EXTENDED|REG_LENIENT))
+ {
+ free(error_state.match);
+ error_state.match = 0;
+ }
+ }
+ else if (error_state.match)
+ {
+ free(error_state.match);
+ error_state.match = 0;
+ }
+ break;
+ case OPT_PREFIX:
+ if (n)
+ error_state.prefix = strdup(v);
+ else if (error_state.prefix)
+ {
+ free(error_state.prefix);
+ error_state.prefix = 0;
+ }
+ break;
+ case OPT_SYSTEM:
+ if (n)
+ error_info.set |= ERROR_SYSTEM;
+ else
+ error_info.clear |= ERROR_SYSTEM;
+ break;
+ case OPT_TIME:
+ error_info.time = n ? 1 : 0;
+ break;
+ case OPT_TRACE:
+ if (n)
+ error_info.trace = -strtol(v, NiL, 0);
+ else
+ error_info.trace = 0;
+ break;
+ }
+ return 0;
+}
+
+/*
+ * print a name with optional delimiter, converting unprintable chars
+ */
+
+static void
+print(register Sfio_t* sp, register char* name, char* delim)
+{
+ if (mbwide())
+ sfputr(sp, name, -1);
+ else
+ {
+#if CC_NATIVE != CC_ASCII
+ register int c;
+ register unsigned char* n2a;
+ register unsigned char* a2n;
+ register int aa;
+ register int as;
+
+ n2a = ccmap(CC_NATIVE, CC_ASCII);
+ a2n = ccmap(CC_ASCII, CC_NATIVE);
+ aa = n2a['A'];
+ as = n2a[' '];
+ while (c = *name++)
+ {
+ c = n2a[c];
+ if (c & 0200)
+ {
+ c &= 0177;
+ sfputc(sp, '?');
+ }
+ if (c < as)
+ {
+ c += aa - 1;
+ sfputc(sp, '^');
+ }
+ c = a2n[c];
+ sfputc(sp, c);
+ }
+#else
+ register int c;
+
+ while (c = *name++)
+ {
+ if (c & 0200)
+ {
+ c &= 0177;
+ sfputc(sp, '?');
+ }
+ if (c < ' ')
+ {
+ c += 'A' - 1;
+ sfputc(sp, '^');
+ }
+ sfputc(sp, c);
+ }
+#endif
+ }
+ if (delim)
+ sfputr(sp, delim, -1);
+}
+
+/*
+ * print error context FIFO stack
+ */
+
+#define CONTEXT(f,p) (((f)&ERROR_PUSH)?((Error_context_t*)&(p)->context->context):((Error_context_t*)(p)))
+
+static void
+context(register Sfio_t* sp, register Error_context_t* cp)
+{
+ if (cp->context)
+ context(sp, CONTEXT(cp->flags, cp->context));
+ if (!(cp->flags & ERROR_SILENT))
+ {
+ if (cp->id)
+ print(sp, cp->id, NiL);
+ if (cp->line > ((cp->flags & ERROR_INTERACTIVE) != 0))
+ {
+ if (cp->file)
+ sfprintf(sp, ": \"%s\", %s %d", cp->file, ERROR_translate(NiL, NiL, ast.id, "line"), cp->line);
+ else
+ sfprintf(sp, "[%d]", cp->line);
+ }
+ sfputr(sp, ": ", -1);
+ }
+}
+
+/*
+ * debugging breakpoint
+ */
+
+extern void
+error_break(void)
+{
+ char* s;
+
+ if (error_state.tty || (error_state.tty = sfopen(NiL, "/dev/tty", "r+")))
+ {
+ sfprintf(error_state.tty, "error breakpoint: ");
+ if (s = sfgetr(error_state.tty, '\n', 1))
+ {
+ if (streq(s, "q") || streq(s, "quit"))
+ exit(0);
+ stropt(s, options, sizeof(*options), setopt, NiL);
+ }
+ }
+}
+
+void
+error(int level, ...)
+{
+ va_list ap;
+
+ va_start(ap, level);
+ errorv(NiL, level, ap);
+ va_end(ap);
+}
+
+void
+errorv(const char* id, int level, va_list ap)
+{
+ register int n;
+ int fd;
+ int flags;
+ char* s;
+ char* t;
+ char* format;
+ char* library;
+ const char* catalog;
+
+ int line;
+ char* file;
+
+#if !_PACKAGE_astsa
+ unsigned long d;
+ struct tms us;
+#endif
+
+ if (!error_info.init)
+ {
+ error_info.init = 1;
+ stropt(getenv("ERROR_OPTIONS"), options, sizeof(*options), setopt, NiL);
+ }
+ if (level > 0)
+ {
+ flags = level & ~ERROR_LEVEL;
+ level &= ERROR_LEVEL;
+ }
+ else
+ flags = 0;
+ if ((flags & (ERROR_USAGE|ERROR_NOID)) == ERROR_NOID)
+ {
+ format = (char*)id;
+ id = 0;
+ }
+ else
+ format = 0;
+ if (id)
+ {
+ catalog = (char*)id;
+ if (!*catalog || *catalog == ':')
+ {
+ catalog = 0;
+ library = 0;
+ }
+ else if ((library = strchr(catalog, ':')) && !*++library)
+ library = 0;
+ }
+ else
+ {
+ catalog = 0;
+ library = 0;
+ }
+ if (catalog)
+ id = 0;
+ else
+ {
+ id = (const char*)error_info.id;
+ catalog = error_info.catalog;
+ }
+ if (level < error_info.trace || (flags & ERROR_LIBRARY) && !(((error_info.set | error_info.flags) ^ error_info.clear) & ERROR_LIBRARY) || level < 0 && error_info.mask && !(error_info.mask & (1<<(-level - 1))))
+ {
+ if (level >= ERROR_FATAL)
+ (*error_info.exit)(level - 1);
+ return;
+ }
+ if (error_info.trace < 0)
+ flags |= ERROR_LIBRARY|ERROR_SYSTEM;
+ flags |= error_info.set | error_info.flags;
+ flags &= ~error_info.clear;
+ if (!library)
+ flags &= ~ERROR_LIBRARY;
+ fd = (flags & ERROR_OUTPUT) ? va_arg(ap, int) : error_info.fd;
+ if (error_info.write)
+ {
+ long off;
+ char* bas;
+
+ bas = stkptr(stkstd, 0);
+ if (off = stktell(stkstd))
+ stkfreeze(stkstd, 0);
+ file = error_info.id;
+ if (error_state.prefix)
+ sfprintf(stkstd, "%s: ", error_state.prefix);
+ if (flags & ERROR_USAGE)
+ {
+ if (flags & ERROR_NOID)
+ sfprintf(stkstd, " ");
+ else
+ sfprintf(stkstd, "%s: ", ERROR_translate(NiL, NiL, ast.id, "Usage"));
+ if (file || opt_info.argv && (file = opt_info.argv[0]))
+ print(stkstd, file, " ");
+ }
+ else
+ {
+ if (level && !(flags & ERROR_NOID))
+ {
+ if (error_info.context && level > 0)
+ context(stkstd, CONTEXT(error_info.flags, error_info.context));
+ if (file)
+ print(stkstd, file, (flags & ERROR_LIBRARY) ? " " : ": ");
+ if (flags & (ERROR_CATALOG|ERROR_LIBRARY))
+ {
+ sfprintf(stkstd, "[");
+ if (flags & ERROR_CATALOG)
+ sfprintf(stkstd, "%s %s%s",
+ catalog ? catalog : ERROR_translate(NiL, NiL, ast.id, "DEFAULT"),
+ ERROR_translate(NiL, NiL, ast.id, "catalog"),
+ (flags & ERROR_LIBRARY) ? ", " : "");
+ if (flags & ERROR_LIBRARY)
+ sfprintf(stkstd, "%s %s",
+ library,
+ ERROR_translate(NiL, NiL, ast.id, "library"));
+ sfprintf(stkstd, "]: ");
+ }
+ }
+ if (level > 0 && error_info.line > ((flags & ERROR_INTERACTIVE) != 0))
+ {
+ if (error_info.file && *error_info.file)
+ sfprintf(stkstd, "\"%s\", ", error_info.file);
+ sfprintf(stkstd, "%s %d: ", ERROR_translate(NiL, NiL, ast.id, "line"), error_info.line);
+ }
+ }
+#if !_PACKAGE_astsa
+ if (error_info.time)
+ {
+ if ((d = times(&us)) < error_info.time || error_info.time == 1)
+ error_info.time = d;
+ sfprintf(stkstd, " %05lu.%05lu.%05lu ", d - error_info.time, (unsigned long)us.tms_utime, (unsigned long)us.tms_stime);
+ }
+#endif
+ switch (level)
+ {
+ case 0:
+ flags &= ~ERROR_SYSTEM;
+ break;
+ case ERROR_WARNING:
+ sfprintf(stkstd, "%s: ", ERROR_translate(NiL, NiL, ast.id, "warning"));
+ break;
+ case ERROR_PANIC:
+ sfprintf(stkstd, "%s: ", ERROR_translate(NiL, NiL, ast.id, "panic"));
+ break;
+ default:
+ if (level < 0)
+ {
+ s = ERROR_translate(NiL, NiL, ast.id, "debug");
+ if (error_info.trace < -1)
+ sfprintf(stkstd, "%s%d:%s", s, level, level > -10 ? " " : "");
+ else
+ sfprintf(stkstd, "%s: ", s);
+ for (n = 0; n < error_info.indent; n++)
+ {
+ sfputc(stkstd, ' ');
+ sfputc(stkstd, ' ');
+ }
+ }
+ break;
+ }
+ if (flags & ERROR_SOURCE)
+ {
+ /*
+ * source ([version], file, line) message
+ */
+
+ file = va_arg(ap, char*);
+ line = va_arg(ap, int);
+ s = ERROR_translate(NiL, NiL, ast.id, "line");
+ if (error_info.version)
+ sfprintf(stkstd, "(%s: \"%s\", %s %d) ", error_info.version, file, s, line);
+ else
+ sfprintf(stkstd, "(\"%s\", %s %d) ", file, s, line);
+ }
+ if (format || (format = va_arg(ap, char*)))
+ {
+ if (!(flags & ERROR_USAGE))
+ format = ERROR_translate(NiL, id, catalog, format);
+ sfvprintf(stkstd, format, ap);
+ }
+ if (!(flags & ERROR_PROMPT))
+ {
+ /*
+ * level&ERROR_OUTPUT on return means message
+ * already output
+ */
+
+ if ((flags & ERROR_SYSTEM) && errno && errno != error_info.last_errno)
+ {
+ sfprintf(stkstd, " [%s]", fmterror(errno));
+ if (error_info.set & ERROR_SYSTEM)
+ errno = 0;
+ error_info.last_errno = (level >= 0) ? 0 : errno;
+ }
+ if (error_info.auxilliary && level >= 0)
+ level = (*error_info.auxilliary)(stkstd, level, flags);
+ sfputc(stkstd, '\n');
+ }
+ if (level > 0)
+ {
+ if ((level & ~ERROR_OUTPUT) > 1)
+ error_info.errors++;
+ else
+ error_info.warnings++;
+ }
+ if (level < 0 || !(level & ERROR_OUTPUT))
+ {
+ n = stktell(stkstd);
+ s = stkptr(stkstd, 0);
+ if (t = memchr(s, '\f', n))
+ {
+ n -= ++t - s;
+ s = t;
+ }
+#if HUH_19980401 /* nasty problems if sfgetr() is in effect! */
+ sfsync(sfstdin);
+#endif
+ sfsync(sfstdout);
+ sfsync(sfstderr);
+ if (fd == sffileno(sfstderr) && error_info.write == write)
+ {
+ sfwrite(sfstderr, s, n);
+ sfsync(sfstderr);
+ }
+ else
+ (*error_info.write)(fd, s, n);
+ }
+ else
+ {
+ s = 0;
+ level &= ERROR_LEVEL;
+ }
+ stkset(stkstd, bas, off);
+ }
+ else
+ s = 0;
+ if (level >= error_state.breakpoint && error_state.breakpoint && (!error_state.match || !regexec(error_state.match, s ? s : format, 0, NiL, 0)) && (!error_state.count || !--error_state.count))
+ {
+ if (error_info.core)
+ {
+#ifndef SIGABRT
+#ifdef SIGQUIT
+#define SIGABRT SIGQUIT
+#else
+#ifdef SIGIOT
+#define SIGABRT SIGIOT
+#endif
+#endif
+#endif
+#ifdef SIGABRT
+ signal(SIGABRT, SIG_DFL);
+ kill(getpid(), SIGABRT);
+ pause();
+#else
+ abort();
+#endif
+ }
+ else
+ error_break();
+ }
+ if (level >= ERROR_FATAL)
+ (*error_info.exit)(level - ERROR_FATAL + 1);
+}
+
+/*
+ * error_info context control
+ */
+
+static Error_info_t* freecontext;
+
+Error_info_t*
+errorctx(Error_info_t* p, int op, int flags)
+{
+ if (op & ERROR_POP)
+ {
+ if (!(_error_infop_ = p->context))
+ _error_infop_ = &_error_info_;
+ if (op & ERROR_FREE)
+ {
+ p->context = freecontext;
+ freecontext = p;
+ }
+ p = _error_infop_;
+ }
+ else
+ {
+ if (!p)
+ {
+ if (p = freecontext)
+ freecontext = freecontext->context;
+ else if (!(p = newof(0, Error_info_t, 1, 0)))
+ return 0;
+ *p = *_error_infop_;
+ p->errors = p->flags = p->line = p->warnings = 0;
+ p->catalog = p->file = 0;
+ }
+ if (op & ERROR_PUSH)
+ {
+ p->flags = flags;
+ p->context = _error_infop_;
+ _error_infop_ = p;
+ }
+ p->flags |= ERROR_PUSH;
+ }
+ return p;
+}
diff --git a/src/lib/libast/misc/errorf.c b/src/lib/libast/misc/errorf.c
new file mode 100644
index 0000000..0a67e97
--- /dev/null
+++ b/src/lib/libast/misc/errorf.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * generic error discipline function
+ */
+
+#include <error.h>
+
+int
+errorf(void* handle, void* discipline, int level, ...)
+{
+ va_list ap;
+
+ va_start(ap, level);
+ errorv((discipline && handle) ? *((char**)handle) : (char*)handle, (discipline || level < 0) ? level : (level | ERROR_LIBRARY), ap);
+ va_end(ap);
+ return 0;
+}
diff --git a/src/lib/libast/misc/errormsg.c b/src/lib/libast/misc/errormsg.c
new file mode 100644
index 0000000..555d4f1
--- /dev/null
+++ b/src/lib/libast/misc/errormsg.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * error function with specific dictionary
+ */
+
+#include <error.h>
+
+int
+errormsg(const char* dictionary, int level, ...)
+{
+ va_list ap;
+
+ va_start(ap, level);
+ errorv(dictionary, level, ap);
+ va_end(ap);
+ return 0;
+}
diff --git a/src/lib/libast/misc/errorx.c b/src/lib/libast/misc/errorx.c
new file mode 100644
index 0000000..70466de
--- /dev/null
+++ b/src/lib/libast/misc/errorx.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "lclib.h"
+
+/*
+ * low level for ERROR_translate()
+ * this fills in NiL arg defaults and calls error_info.translate
+ */
+
+char*
+errorx(const char* loc, const char* cmd, const char* cat, const char* msg)
+{
+ char* s;
+
+ if (!error_info.translate)
+ error_info.translate = translate; /* 2007-03-19 OLD_Error_info_t workaround */
+ if (ERROR_translating())
+ {
+ if (!loc)
+ loc = (const char*)locales[AST_LC_MESSAGES]->code;
+ if (!cmd)
+ cmd = (const char*)error_info.id;
+ if (!cat)
+ cat = (const char*)error_info.catalog;
+ if (s = (*error_info.translate)(loc, cmd, cat, msg))
+ return s;
+ }
+ return (char*)msg;
+}
diff --git a/src/lib/libast/misc/fastfind.c b/src/lib/libast/misc/fastfind.c
new file mode 100644
index 0000000..04d54d9
--- /dev/null
+++ b/src/lib/libast/misc/fastfind.c
@@ -0,0 +1,1282 @@
+#pragma prototyped
+/*
+ * original code
+ *
+ * James A. Woods, Informatics General Corporation,
+ * NASA Ames Research Center, 6/81.
+ * Usenix ;login:, February/March, 1983, p. 8.
+ *
+ * discipline/method interface
+ *
+ * Glenn Fowler
+ * AT&T Research
+ * modified from the original BSD source
+ *
+ * 'fastfind' scans a file list for the full pathname of a file
+ * given only a piece of the name. The list is processed with
+ * with "front-compression" and bigram coding. Front compression reduces
+ * space by a factor of 4-5, bigram coding by a further 20-25%.
+ *
+ * there are 4 methods:
+ *
+ * FF_old original with 7 bit bigram encoding (no magic)
+ * FF_gnu 8 bit clean front compression (FF_gnu_magic)
+ * FF_dir FF_gnu with sfgetl/sfputl and trailing / on dirs (FF_dir_magic)
+ * FF_typ FF_dir with (mime) types (FF_typ_magic)
+ *
+ * the bigram encoding steals the eighth bit (that's why its FF_old)
+ * maybe one day we'll limit it to readonly:
+ *
+ * 0-2*FF_OFF likeliest differential counts + offset to make nonnegative
+ * FF_ESC 4 byte big-endian out-of-range count+FF_OFF follows
+ * FF_MIN-FF_MAX ascii residue
+ * >=FF_MAX bigram codes
+ *
+ * a two-tiered string search technique is employed
+ *
+ * a metacharacter-free subpattern and partial pathname is matched
+ * backwards to avoid full expansion of the pathname list
+ *
+ * then the actual shell glob-style regular expression (if in this form)
+ * is matched against the candidate pathnames using the slower regexec()
+ *
+ * The original BSD code is covered by the BSD license:
+ *
+ * Copyright (c) 1985, 1993, 1999
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+static const char id[] = "\n@(#)$Id: fastfind (AT&T Research) 2002-10-02 $\0\n";
+
+static const char lib[] = "libast:fastfind";
+
+#include "findlib.h"
+
+#define FIND_MATCH "*/(find|locate)/*"
+
+/*
+ * this db could be anywhere
+ * findcodes[] directories are checked for findnames[i]
+ */
+
+static char* findcodes[] =
+{
+ 0,
+ 0,
+ FIND_CODES,
+ "/usr/local/share/lib",
+ "/usr/local/lib",
+ "/usr/share/lib",
+ "/usr/lib",
+ "/var/spool",
+ "/usr/local/var",
+ "/var/lib",
+ "/var/lib/slocate",
+ "/var/db",
+};
+
+static char* findnames[] =
+{
+ "find/codes",
+ "find/find.codes",
+ "locate/locatedb",
+ "locatedb",
+ "locate.database",
+ "slocate.db",
+};
+
+/*
+ * convert t to lower case and drop leading x- and x- after /
+ * converted value copied to b of size n
+ */
+
+char*
+typefix(char* buf, size_t n, register const char* t)
+{
+ register int c;
+ register char* b = buf;
+
+ if ((*t == 'x' || *t == 'X') && *(t + 1) == '-')
+ t += 2;
+ while (c = *t++)
+ {
+ if (isupper(c))
+ c = tolower(c);
+ if ((*b++ = c) == '/' && (*t == 'x' || *t == 'X') && *(t + 1) == '-')
+ t += 2;
+ }
+ *b = 0;
+ return buf;
+}
+
+/*
+ * return a fastfind stream handle for pattern
+ */
+
+Find_t*
+findopen(const char* file, const char* pattern, const char* type, Finddisc_t* disc)
+{
+ register Find_t* fp;
+ register char* p;
+ register char* s;
+ register char* b;
+ register int i;
+ register int j;
+ char* path;
+ int brace = 0;
+ int paren = 0;
+ int k;
+ int q;
+ int fd;
+ int uid;
+ Vmalloc_t* vm;
+ Type_t* tp;
+ struct stat st;
+
+
+ if (!(vm = vmopen(Vmdcheap, Vmbest, 0)))
+ goto nospace;
+
+ /*
+ * NOTE: searching for FIND_CODES would be much simpler if we
+ * just stuck with our own, but we also support GNU
+ * locate codes and have to search for the one of a
+ * bazillion possible names for that file
+ */
+
+ if (!findcodes[1])
+ findcodes[1] = getenv(FIND_CODES_ENV);
+ if (disc->flags & FIND_GENERATE)
+ {
+ if (!(fp = (Find_t*)vmnewof(vm, 0, Find_t, 1, sizeof(Encode_t) - sizeof(Code_t))))
+ goto nospace;
+ fp->vm = vm;
+ fp->id = lib;
+ fp->disc = disc;
+ fp->generate = 1;
+ if (file && (!*file || streq(file, "-")))
+ file = 0;
+ uid = geteuid();
+ j = (findcodes[0] = (char*)file) && *file == '/' ? 1 : elementsof(findcodes);
+
+ /*
+ * look for the codes file, but since it may not exist yet,
+ * also look for the containing directory if i<2 or if
+ * it is sufficiently qualified (FIND_MATCH)
+ */
+
+ for (i = 0; i < j; i++)
+ if (path = findcodes[i])
+ {
+ if (*path == '/')
+ {
+ if (!stat(path, &st))
+ {
+ if (S_ISDIR(st.st_mode))
+ {
+ for (k = 0; k < elementsof(findnames); k++)
+ {
+ sfsprintf(fp->encode.file, sizeof(fp->encode.file), "%s/%s", path, findnames[k]);
+ if (!eaccess(fp->encode.file, R_OK|W_OK))
+ {
+ path = fp->encode.file;
+ break;
+ }
+ if (strchr(findnames[k], '/') && (b = strrchr(fp->encode.file, '/')))
+ {
+ *b = 0;
+ if (!stat(fp->encode.file, &st) && st.st_uid == uid && (st.st_mode & S_IWUSR))
+ {
+ *b = '/';
+ path = fp->encode.file;
+ break;
+ }
+ }
+ }
+ if (k < elementsof(findnames))
+ break;
+ }
+ else if (st.st_uid == uid && (st.st_mode & S_IWUSR))
+ {
+ sfsprintf(fp->encode.file, sizeof(fp->encode.file), "%s", path);
+ path = fp->encode.file;
+ break;
+ }
+ }
+ else if (i < 2 || strmatch(path, FIND_MATCH))
+ {
+ sfsprintf(fp->encode.file, sizeof(fp->encode.file), "%s", path);
+ if (b = strrchr(fp->encode.file, '/'))
+ {
+ *b = 0;
+ if (!stat(fp->encode.file, &st) && st.st_uid == uid && (st.st_mode & S_IWUSR))
+ {
+ *b = '/';
+ path = fp->encode.file;
+ break;
+ }
+ }
+ }
+ }
+ else if (pathpath(path, "", PATH_REGULAR|PATH_READ|PATH_WRITE, fp->encode.file, sizeof(fp->encode.file)))
+ {
+ path = fp->encode.file;
+ break;
+ }
+ else if (b = strrchr(path, '/'))
+ {
+ sfsprintf(fp->encode.file, sizeof(fp->encode.file), "%-.*s", b - path, path);
+ if (pathpath(fp->encode.file, "", PATH_EXECUTE|PATH_READ|PATH_WRITE, fp->encode.temp, sizeof(fp->encode.temp)) &&
+ !stat(fp->encode.temp, &st) && st.st_uid == uid && (st.st_mode & S_IWUSR))
+ {
+ sfsprintf(fp->encode.file, sizeof(fp->encode.file), "%s%s", fp->encode.temp, b);
+ path = fp->encode.file;
+ break;
+ }
+ }
+ }
+ if (i >= j)
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, 2, "%s: cannot locate codes", file ? file : findcodes[2]);
+ goto drop;
+ }
+ if (fp->disc->flags & FIND_OLD)
+ {
+ /*
+ * FF_old generates temp data that is read
+ * in a second pass to generate the real codes
+ */
+
+ fp->method = FF_old;
+ if (!(fp->fp = sftmp(32 * PATH_MAX)))
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, ERROR_SYSTEM|2, "cannot create tmp file");
+ goto drop;
+ }
+ }
+ else
+ {
+ /*
+ * the rest generate into a temp file that
+ * is simply renamed on completion
+ */
+
+ if (s = strrchr(path, '/'))
+ {
+ *s = 0;
+ p = path;
+ }
+ else
+ p = ".";
+ if (!pathtemp(fp->encode.temp, sizeof(fp->encode.temp), p, "ff", &fd))
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, ERROR_SYSTEM|2, "%s: cannot create tmp file in this directory", p ? p : ".");
+ goto drop;
+ }
+ if (s)
+ *s = '/';
+ if (!(fp->fp = sfnew(NiL, NiL, (size_t)SF_UNBOUND, fd, SF_WRITE)))
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, ERROR_SYSTEM|2, "%s: cannot open tmp file", fp->encode.temp);
+ close(fd);
+ goto drop;
+ }
+ if (fp->disc->flags & FIND_TYPE)
+ {
+ fp->method = FF_typ;
+ fp->encode.namedisc.key = offsetof(Type_t, name);
+ fp->encode.namedisc.link = offsetof(Type_t, byname);
+ fp->encode.indexdisc.key = offsetof(Type_t, index);
+ fp->encode.indexdisc.size = sizeof(unsigned long);
+ fp->encode.indexdisc.link = offsetof(Type_t, byindex);
+ s = "system/dir";
+ if (!(fp->encode.namedict = dtopen(&fp->encode.namedisc, Dtoset)) || !(fp->encode.indexdict = dtopen(&fp->encode.indexdisc, Dtoset)) || !(tp = newof(0, Type_t, 1, strlen(s) + 1)))
+ {
+ if (fp->encode.namedict)
+ dtclose(fp->encode.namedict);
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, 2, "cannot allocate type table");
+ goto drop;
+ }
+
+ /*
+ * type index 1 is always system/dir
+ */
+
+ tp->index = ++fp->types;
+ strcpy(tp->name, s);
+ dtinsert(fp->encode.namedict, tp);
+ dtinsert(fp->encode.indexdict, tp);
+ }
+ else if (fp->disc->flags & FIND_GNU)
+ {
+ fp->method = FF_gnu;
+ sfputc(fp->fp, 0);
+ sfputr(fp->fp, FF_gnu_magic, 0);
+ }
+ else
+ {
+ fp->method = FF_dir;
+ sfputc(fp->fp, 0);
+ sfputr(fp->fp, FF_dir_magic, 0);
+ }
+ }
+ }
+ else
+ {
+ i = sizeof(Decode_t) + sizeof(Code_t);
+ if (!pattern || !*pattern)
+ pattern = "*";
+ i += (j = 2 * (strlen(pattern) + 1));
+ if (!(fp = (Find_t*)vmnewof(vm, 0, Find_t, 1, i)))
+ {
+ vmclose(vm);
+ return 0;
+ }
+ fp->vm = vm;
+ fp->id = lib;
+ fp->disc = disc;
+ if (disc->flags & FIND_ICASE)
+ fp->decode.ignorecase = 1;
+ j = (findcodes[0] = (char*)file) && *file == '/' ? 1 : elementsof(findcodes);
+ for (i = 0; i < j; i++)
+ if (path = findcodes[i])
+ {
+ if (*path == '/')
+ {
+ if (!stat(path, &st))
+ {
+ if (S_ISDIR(st.st_mode))
+ {
+ for (k = 0; k < elementsof(findnames); k++)
+ {
+ sfsprintf(fp->decode.path, sizeof(fp->decode.path), "%s/%s", path, findnames[k]);
+ if (fp->fp = sfopen(NiL, fp->decode.path, "r"))
+ {
+ path = fp->decode.path;
+ break;
+ }
+ }
+ if (fp->fp)
+ break;
+ }
+ else if (fp->fp = sfopen(NiL, path, "r"))
+ break;
+ }
+ }
+ else if ((path = pathpath(path, "", PATH_REGULAR|PATH_READ, fp->decode.path, sizeof(fp->decode.path))) && (fp->fp = sfopen(NiL, path, "r")))
+ break;
+ }
+ if (!fp->fp)
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, 2, "%s: cannot locate codes", file ? file : findcodes[2]);
+ goto drop;
+ }
+ if (fstat(sffileno(fp->fp), &st))
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, 2, "%s: cannot stat codes", path);
+ goto drop;
+ }
+ if (fp->secure = ((st.st_mode & (S_IRGRP|S_IROTH)) == S_IRGRP) && st.st_gid == getegid() && getegid() != getgid())
+ setgid(getgid());
+ fp->stamp = st.st_mtime;
+ b = (s = fp->decode.temp) + 1;
+ for (i = 0; i < elementsof(fp->decode.bigram1); i++)
+ {
+ if ((j = sfgetc(fp->fp)) == EOF)
+ goto invalid;
+ if (!(*s++ = fp->decode.bigram1[i] = j) && i)
+ {
+ i = -i;
+ break;
+ }
+ if ((j = sfgetc(fp->fp)) == EOF)
+ goto invalid;
+ if (!(*s++ = fp->decode.bigram2[i] = j) && (i || fp->decode.bigram1[0] >= '0' && fp->decode.bigram1[0] <= '1'))
+ break;
+ }
+ if (streq(b, FF_typ_magic))
+ {
+ if (type)
+ {
+ type = (const char*)typefix(fp->decode.bigram2, sizeof(fp->decode.bigram2), type);
+ memset(fp->decode.bigram1, 0, sizeof(fp->decode.bigram1));
+ }
+ fp->method = FF_typ;
+ for (j = 0, i = 1;; i++)
+ {
+ if (!(s = sfgetr(fp->fp, 0, 0)))
+ goto invalid;
+ if (!*s)
+ break;
+ if (type && strmatch(s, type))
+ {
+ FF_SET_TYPE(fp, i);
+ j++;
+ }
+ }
+ if (type && !j)
+ goto drop;
+ fp->types = j;
+ }
+ else if (streq(b, FF_dir_magic))
+ fp->method = FF_dir;
+ else if (streq(b, FF_gnu_magic))
+ fp->method = FF_gnu;
+ else if (!*b && *--b >= '0' && *b <= '1')
+ {
+ fp->method = FF_gnu;
+ while (j = sfgetc(fp->fp))
+ {
+ if (j == EOF || fp->decode.count >= sizeof(fp->decode.path))
+ goto invalid;
+ fp->decode.path[fp->decode.count++] = j;
+ }
+ }
+ else
+ {
+ fp->method = FF_old;
+ if (i < 0)
+ {
+ if ((j = sfgetc(fp->fp)) == EOF)
+ goto invalid;
+ fp->decode.bigram2[i = -i] = j;
+ }
+ while (++i < elementsof(fp->decode.bigram1))
+ {
+ if ((j = sfgetc(fp->fp)) == EOF)
+ goto invalid;
+ fp->decode.bigram1[i] = j;
+ if ((j = sfgetc(fp->fp)) == EOF)
+ goto invalid;
+ fp->decode.bigram2[i] = j;
+ }
+ if ((fp->decode.peek = sfgetc(fp->fp)) != FF_OFF)
+ goto invalid;
+ }
+
+ /*
+ * set up the physical dir table
+ */
+
+ if (disc->version >= 19980301L)
+ {
+ fp->verifyf = disc->verifyf;
+ if (disc->dirs && *disc->dirs)
+ {
+ for (k = 0; disc->dirs[k]; k++);
+ if (k == 1 && streq(disc->dirs[0], "/"))
+ k = 0;
+ if (k)
+ {
+ if (!(fp->dirs = vmnewof(fp->vm, 0, char*, 2 * k + 1, 0)))
+ goto drop;
+ if (!(fp->lens = vmnewof(fp->vm, 0, int, 2 * k, 0)))
+ goto drop;
+ p = 0;
+ b = fp->decode.temp;
+ j = fp->method == FF_old || fp->method == FF_gnu;
+
+ /*
+ * fill the dir list with logical and
+ * physical names since we don't know
+ * which way the db was encoded (it
+ * could be *both* ways)
+ */
+
+ for (i = q = 0; i < k; i++)
+ {
+ if (*(s = disc->dirs[i]) == '/')
+ sfsprintf(b, sizeof(fp->decode.temp) - 1, "%s", s);
+ else if (!p && !(p = getcwd(fp->decode.path, sizeof(fp->decode.path))))
+ goto nospace;
+ else
+ sfsprintf(b, sizeof(fp->decode.temp) - 1, "%s/%s", p, s);
+ s = pathcanon(b, sizeof(fp->decode.temp), 0);
+ *s = '/';
+ *(s + 1) = 0;
+ if (!(fp->dirs[q] = vmstrdup(fp->vm, b)))
+ goto nospace;
+ if (j)
+ (fp->dirs[q])[s - b] = 0;
+ q++;
+ *s = 0;
+ s = pathcanon(b, sizeof(fp->decode.temp), PATH_PHYSICAL);
+ *s = '/';
+ *(s + 1) = 0;
+ if (!strneq(b, fp->dirs[q - 1], s - b))
+ {
+ if (!(fp->dirs[q] = vmstrdup(fp->vm, b)))
+ goto nospace;
+ if (j)
+ (fp->dirs[q])[s - b] = 0;
+ q++;
+ }
+ }
+ strsort(fp->dirs, q, strcasecmp);
+ for (i = 0; i < q; i++)
+ fp->lens[i] = strlen(fp->dirs[i]);
+ }
+ }
+ }
+ if (fp->verifyf || (disc->flags & FIND_VERIFY))
+ {
+ if (fp->method != FF_dir && fp->method != FF_typ)
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, 2, "%s: %s code format does not support directory verification", path, fp->method == FF_gnu ? FF_gnu_magic : "OLD-BIGRAM");
+ goto drop;
+ }
+ fp->verify = 1;
+ }
+
+ /*
+ * extract last glob-free subpattern in name for fast pre-match
+ * prepend 0 for backwards match
+ */
+
+ if (p = s = (char*)pattern)
+ {
+ b = fp->decode.pattern;
+ for (;;)
+ {
+ switch (*b++ = *p++)
+ {
+ case 0:
+ break;
+ case '\\':
+ s = p;
+ if (!*p++)
+ break;
+ continue;
+ case '[':
+ if (!brace)
+ {
+ brace++;
+ if (*p == ']')
+ p++;
+ }
+ continue;
+ case ']':
+ if (brace)
+ {
+ brace--;
+ s = p;
+ }
+ continue;
+ case '(':
+ if (!brace)
+ paren++;
+ continue;
+ case ')':
+ if (!brace && paren > 0 && !--paren)
+ s = p;
+ continue;
+ case '|':
+ case '&':
+ if (!brace && !paren)
+ {
+ s = "";
+ break;
+ }
+ continue;
+ case '*':
+ case '?':
+ s = p;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ if (s != pattern && !streq(pattern, "*"))
+ {
+ fp->decode.match = 1;
+ if (i = regcomp(&fp->decode.re, pattern, REG_SHELL|REG_AUGMENTED|(fp->decode.ignorecase?REG_ICASE:0)))
+ {
+ if (disc->errorf)
+ {
+ regerror(i, &fp->decode.re, fp->decode.temp, sizeof(fp->decode.temp));
+ (*fp->disc->errorf)(fp, fp->disc, 2, "%s: %s", pattern, fp->decode.temp);
+ }
+ goto drop;
+ }
+ }
+ if (*s)
+ {
+ *b++ = 0;
+ while (i = *s++)
+ *b++ = i;
+ *b-- = 0;
+ fp->decode.end = b;
+ if (fp->decode.ignorecase)
+ for (s = fp->decode.pattern; s <= b; s++)
+ if (isupper(*s))
+ *s = tolower(*s);
+ }
+ }
+ }
+ return fp;
+ nospace:
+ if (disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, 2, "out of space");
+ if (!vm)
+ return 0;
+ if (!fp)
+ {
+ vmclose(vm);
+ return 0;
+ }
+ goto drop;
+ invalid:
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, 2, "%s: invalid codes", path);
+ drop:
+ if (!fp->generate && fp->decode.match)
+ regfree(&fp->decode.re);
+ if (fp->fp)
+ sfclose(fp->fp);
+ vmclose(fp->vm);
+ return 0;
+}
+
+/*
+ * return the next fastfind path
+ * 0 returned when list exhausted
+ */
+
+char*
+findread(register Find_t* fp)
+{
+ register char* p;
+ register char* q;
+ register char* s;
+ register char* b;
+ register char* e;
+ register int c;
+ register int n;
+ register int m;
+ int ignorecase;
+ int t;
+ unsigned char w[4];
+ struct stat st;
+
+ if (fp->generate)
+ return 0;
+ if (fp->decode.restore)
+ {
+ *fp->decode.restore = '/';
+ fp->decode.restore = 0;
+ }
+ ignorecase = fp->decode.ignorecase ? STR_ICASE : 0;
+ c = fp->decode.peek;
+ next:
+ for (;;)
+ {
+ switch (fp->method)
+ {
+ case FF_dir:
+ t = 0;
+ n = sfgetl(fp->fp);
+ goto grab;
+ case FF_gnu:
+ if ((c = sfgetc(fp->fp)) == EOF)
+ return 0;
+ if (c == 0x80)
+ {
+ if ((c = sfgetc(fp->fp)) == EOF)
+ return 0;
+ n = c << 8;
+ if ((c = sfgetc(fp->fp)) == EOF)
+ return 0;
+ n |= c;
+ if (n & 0x8000)
+ n = (n - 0xffff) - 1;
+ }
+ else if ((n = c) & 0x80)
+ n = (n - 0xff) - 1;
+ t = 0;
+ goto grab;
+ case FF_typ:
+ t = sfgetu(fp->fp);
+ n = sfgetl(fp->fp);
+ grab:
+ p = fp->decode.path + (fp->decode.count += n);
+ do
+ {
+ if ((c = sfgetc(fp->fp)) == EOF)
+ return 0;
+ } while (*p++ = c);
+ p -= 2;
+ break;
+ case FF_old:
+ if (c == EOF)
+ {
+ fp->decode.peek = c;
+ return 0;
+ }
+ if (c == FF_ESC)
+ {
+ if (sfread(fp->fp, w, sizeof(w)) != sizeof(w))
+ return 0;
+ if (fp->decode.swap >= 0)
+ {
+ c = (int32_t)((w[0] << 24) | (w[1] << 16) | (w[2] << 8) | w[3]);
+ if (!fp->decode.swap)
+ {
+ /*
+ * the old format uses machine
+ * byte order; this test uses
+ * the smallest magnitude of
+ * both byte orders on the
+ * first encoded path motion
+ * to determine the original
+ * byte order
+ */
+
+ m = c;
+ if (m < 0)
+ m = -m;
+ n = (int32_t)((w[3] << 24) | (w[2] << 16) | (w[1] << 8) | w[0]);
+ if (n < 0)
+ n = -n;
+ if (m < n)
+ fp->decode.swap = 1;
+ else
+ {
+ fp->decode.swap = -1;
+ c = (int32_t)((w[3] << 24) | (w[2] << 16) | (w[1] << 8) | w[0]);
+ }
+ }
+ }
+ else
+ c = (int32_t)((w[3] << 24) | (w[2] << 16) | (w[1] << 8) | w[0]);
+ }
+ fp->decode.count += c - FF_OFF;
+ for (p = fp->decode.path + fp->decode.count; (c = sfgetc(fp->fp)) > FF_ESC;)
+ if (c & (1<<(CHAR_BIT-1)))
+ {
+ *p++ = fp->decode.bigram1[c & ((1<<(CHAR_BIT-1))-1)];
+ *p++ = fp->decode.bigram2[c & ((1<<(CHAR_BIT-1))-1)];
+ }
+ else
+ *p++ = c;
+ *p-- = 0;
+ t = 0;
+ break;
+ }
+ b = fp->decode.path;
+ if (fp->decode.found)
+ fp->decode.found = 0;
+ else
+ b += fp->decode.count;
+ if (fp->dirs)
+ for (;;)
+ {
+ if (!*fp->dirs)
+ return 0;
+
+ /*
+ * use the ordering and lengths to prune
+ * comparison function calls
+ * (*fp->dirs)[*fp->lens]=='/' if its
+ * already been matched
+ */
+
+ if ((n = p - fp->decode.path + 1) > (m = *fp->lens))
+ {
+ if (!(*fp->dirs)[m])
+ goto next;
+ if (!strncasecmp(*fp->dirs, fp->decode.path, m))
+ break;
+ }
+ else if (n == m)
+ {
+ if (!(*fp->dirs)[m])
+ {
+ if (!(n = strcasecmp(*fp->dirs, fp->decode.path)) && (ignorecase || !strcmp(*fp->dirs, fp->decode.path)))
+ {
+ if (m > 0)
+ {
+ (*fp->dirs)[m] = '/';
+ if ((*fp->dirs)[m - 1] != '/')
+ (*fp->dirs)[++(*fp->lens)] = '/';
+ }
+ break;
+ }
+ if (n >= 0)
+ goto next;
+ }
+ }
+ else if (!(*fp->dirs)[m])
+ goto next;
+ fp->dirs++;
+ fp->lens++;
+ }
+ if (fp->verify && (*p == '/' || t == 1))
+ {
+ if ((n = p - fp->decode.path))
+ *p = 0;
+ else
+ n = 1;
+ if (fp->verifyf)
+ n = (*fp->verifyf)(fp, fp->decode.path, n, fp->disc);
+ else if (stat(fp->decode.path, &st))
+ n = -1;
+ else if ((unsigned long)st.st_mtime > fp->stamp)
+ n = 1;
+ else
+ n = 0;
+ *p = '/';
+
+ /*
+ * n<0 skip this subtree
+ * n==0 keep as is
+ * n>0 read this dir now
+ */
+
+ /* NOT IMPLEMENTED YET */
+ }
+ if (FF_OK_TYPE(fp, t))
+ {
+ if (fp->decode.end)
+ {
+ if (*(s = p) == '/')
+ s--;
+ if (*fp->decode.pattern == '/' && b > fp->decode.path)
+ b--;
+ for (; s >= b; s--)
+ if (*s == *fp->decode.end || ignorecase && tolower(*s) == *fp->decode.end)
+ {
+ if (ignorecase)
+ for (e = fp->decode.end - 1, q = s - 1; *e && (*q == *e || tolower(*q) == *e); e--, q--);
+ else
+ for (e = fp->decode.end - 1, q = s - 1; *e && *q == *e; e--, q--);
+ if (!*e)
+ {
+ fp->decode.found = 1;
+ if (!fp->decode.match || strgrpmatch(fp->decode.path, fp->decode.pattern, NiL, 0, STR_MAXIMAL|STR_LEFT|STR_RIGHT|ignorecase))
+ {
+ fp->decode.peek = c;
+ if (*p == '/')
+ *(fp->decode.restore = p) = 0;
+ if (!fp->secure || !access(fp->decode.path, F_OK))
+ return fp->decode.path;
+ }
+ break;
+ }
+ }
+ }
+ else if (!fp->decode.match || !(n = regexec(&fp->decode.re, fp->decode.path, 0, NiL, 0)))
+ {
+ fp->decode.peek = c;
+ if (*p == '/' && p > fp->decode.path)
+ *(fp->decode.restore = p) = 0;
+ if (!fp->secure || !access(fp->decode.path, F_OK))
+ return fp->decode.path;
+ }
+ else if (n != REG_NOMATCH)
+ {
+ if (fp->disc->errorf)
+ {
+ regerror(n, &fp->decode.re, fp->decode.temp, sizeof(fp->decode.temp));
+ (*fp->disc->errorf)(fp, fp->disc, 2, "%s: %s", fp->decode.pattern, fp->decode.temp);
+ }
+ return 0;
+ }
+ }
+ }
+}
+
+/*
+ * add path to the code table
+ * paths are assumed to be in sort order
+ */
+
+int
+findwrite(register Find_t* fp, const char* path, size_t len, const char* type)
+{
+ register unsigned char* s;
+ register unsigned char* e;
+ register unsigned char* p;
+ register int n;
+ register int d;
+ register Type_t* x;
+ register unsigned long u;
+
+ if (!fp->generate)
+ return -1;
+ if (type && fp->method == FF_dir)
+ {
+ len = sfsprintf(fp->encode.mark, sizeof(fp->encode.mark), "%-.*s/", len, path);
+ path = fp->encode.mark;
+ }
+ s = (unsigned char*)path;
+ if (len <= 0)
+ len = strlen(path);
+ if (len < sizeof(fp->encode.path))
+ e = s + len++;
+ else
+ {
+ len = sizeof(fp->encode.path) - 1;
+ e = s + len;
+ }
+ p = (unsigned char*)fp->encode.path;
+ while (s < e)
+ {
+ if (*s != *p++)
+ break;
+ s++;
+ }
+ n = s - (unsigned char*)path;
+ switch (fp->method)
+ {
+ case FF_gnu:
+ d = n - fp->encode.prefix;
+ if (d >= -127 && d <= 127)
+ sfputc(fp->fp, d & 0xff);
+ else
+ {
+ sfputc(fp->fp, 0x80);
+ sfputc(fp->fp, (d >> 8) & 0xff);
+ sfputc(fp->fp, d & 0xff);
+ }
+ fp->encode.prefix = n;
+ sfputr(fp->fp, (char*)s, 0);
+ break;
+ case FF_old:
+ sfprintf(fp->fp, "%ld", n - fp->encode.prefix + FF_OFF);
+ fp->encode.prefix = n;
+ sfputc(fp->fp, ' ');
+ p = s;
+ while (s < e)
+ {
+ n = *s++;
+ if (s >= e)
+ break;
+ fp->encode.code[n][*s++]++;
+ }
+ while (p < e)
+ {
+ if ((n = *p++) < FF_MIN || n >= FF_MAX)
+ n = '?';
+ sfputc(fp->fp, n);
+ }
+ sfputc(fp->fp, 0);
+ break;
+ case FF_typ:
+ if (type)
+ {
+ type = (const char*)typefix((char*)fp->encode.bigram, sizeof(fp->encode.bigram), type);
+ if (x = (Type_t*)dtmatch(fp->encode.namedict, type))
+ u = x->index;
+ else if (!(x = newof(0, Type_t, 1, strlen(type) + 1)))
+ u = 0;
+ else
+ {
+ u = x->index = ++fp->types;
+ strcpy(x->name, type);
+ dtinsert(fp->encode.namedict, x);
+ dtinsert(fp->encode.indexdict, x);
+ }
+ }
+ else
+ u = 0;
+ sfputu(fp->fp, u);
+ /*FALLTHROUGH...*/
+ case FF_dir:
+ d = n - fp->encode.prefix;
+ sfputl(fp->fp, d);
+ fp->encode.prefix = n;
+ sfputr(fp->fp, (char*)s, 0);
+ break;
+ }
+ memcpy(fp->encode.path, path, len);
+ return 0;
+}
+
+/*
+ * findsync() helper
+ */
+
+static int
+finddone(register Find_t* fp)
+{
+ int r;
+
+ if (sfsync(fp->fp))
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, 2, "%s: write error [sfsync]", fp->encode.file);
+ return -1;
+ }
+ if (sferror(fp->fp))
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, 2, "%s: write error [sferror]", fp->encode.file);
+ return -1;
+ }
+ r = sfclose(fp->fp);
+ fp->fp = 0;
+ if (r)
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, 2, "%s: write error [sfclose]", fp->encode.file);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * finish the code table
+ */
+
+static int
+findsync(register Find_t* fp)
+{
+ register char* s;
+ register int n;
+ register int m;
+ register int d;
+ register Type_t* x;
+ char* t;
+ int b;
+ long z;
+ Sfio_t* sp;
+
+ switch (fp->method)
+ {
+ case FF_dir:
+ case FF_gnu:
+ /*
+ * replace the real file with the temp file
+ */
+
+ if (finddone(fp))
+ goto bad;
+ remove(fp->encode.file);
+ if (rename(fp->encode.temp, fp->encode.file))
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, ERROR_SYSTEM|2, "%s: cannot rename from tmp file %s", fp->encode.file, fp->encode.temp);
+ remove(fp->encode.temp);
+ return -1;
+ }
+ break;
+ case FF_old:
+ /*
+ * determine the top FF_MAX bigrams
+ */
+
+ for (n = 0; n < FF_MAX; n++)
+ for (m = 0; m < FF_MAX; m++)
+ fp->encode.hits[fp->encode.code[n][m]]++;
+ fp->encode.hits[0] = 0;
+ m = 1;
+ for (n = USHRT_MAX; n >= 0; n--)
+ if (d = fp->encode.hits[n])
+ {
+ fp->encode.hits[n] = m;
+ if ((m += d) > FF_MAX)
+ break;
+ }
+ while (--n >= 0)
+ fp->encode.hits[n] = 0;
+ for (n = FF_MAX - 1; n >= 0; n--)
+ for (m = FF_MAX - 1; m >= 0; m--)
+ if (fp->encode.hits[fp->encode.code[n][m]])
+ {
+ d = fp->encode.code[n][m];
+ b = fp->encode.hits[d] - 1;
+ fp->encode.code[n][m] = b + FF_MAX;
+ if (fp->encode.hits[d]++ >= FF_MAX)
+ fp->encode.hits[d] = 0;
+ fp->encode.bigram[b *= 2] = n;
+ fp->encode.bigram[b + 1] = m;
+ }
+ else
+ fp->encode.code[n][m] = 0;
+
+ /*
+ * commit the real file
+ */
+
+ if (sfseek(fp->fp, (Sfoff_t)0, SEEK_SET))
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, ERROR_SYSTEM|2, "cannot rewind tmp file");
+ return -1;
+ }
+ if (!(sp = sfopen(NiL, fp->encode.file, "w")))
+ goto badcreate;
+
+ /*
+ * dump the bigrams
+ */
+
+ sfwrite(sp, fp->encode.bigram, sizeof(fp->encode.bigram));
+
+ /*
+ * encode the massaged paths
+ */
+
+ while (s = sfgetr(fp->fp, 0, 0))
+ {
+ z = strtol(s, &t, 0);
+ s = t;
+ if (z < 0 || z > 2 * FF_OFF)
+ {
+ sfputc(sp, FF_ESC);
+ sfputc(sp, (z >> 24));
+ sfputc(sp, (z >> 16));
+ sfputc(sp, (z >> 8));
+ sfputc(sp, z);
+ }
+ else
+ sfputc(sp, z);
+ while (n = *s++)
+ {
+ if (!(m = *s++))
+ {
+ sfputc(sp, n);
+ break;
+ }
+ if (d = fp->encode.code[n][m])
+ sfputc(sp, d);
+ else
+ {
+ sfputc(sp, n);
+ sfputc(sp, m);
+ }
+ }
+ }
+ sfclose(fp->fp);
+ fp->fp = sp;
+ if (finddone(fp))
+ goto bad;
+ break;
+ case FF_typ:
+ if (finddone(fp))
+ goto bad;
+ if (!(fp->fp = sfopen(NiL, fp->encode.temp, "r")))
+ {
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, ERROR_SYSTEM|2, "%s: cannot read tmp file", fp->encode.temp);
+ remove(fp->encode.temp);
+ return -1;
+ }
+
+ /*
+ * commit the output file
+ */
+
+ if (!(sp = sfopen(NiL, fp->encode.file, "w")))
+ goto badcreate;
+
+ /*
+ * write the header magic
+ */
+
+ sfputc(sp, 0);
+ sfputr(sp, FF_typ_magic, 0);
+
+ /*
+ * write the type table in index order starting with 1
+ */
+
+ for (x = (Type_t*)dtfirst(fp->encode.indexdict); x; x = (Type_t*)dtnext(fp->encode.indexdict, x))
+ sfputr(sp, x->name, 0);
+ sfputc(sp, 0);
+
+ /*
+ * append the front compressed strings
+ */
+
+ if (sfmove(fp->fp, sp, SF_UNBOUND, -1) < 0 || !sfeof(fp->fp))
+ {
+ sfclose(sp);
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, 2, "%s: cannot append codes", fp->encode.file);
+ goto bad;
+ }
+ sfclose(fp->fp);
+ fp->fp = sp;
+ if (finddone(fp))
+ goto bad;
+ remove(fp->encode.temp);
+ break;
+ }
+ return 0;
+ badcreate:
+ if (fp->disc->errorf)
+ (*fp->disc->errorf)(fp, fp->disc, 2, "%s: cannot write codes", fp->encode.file);
+ bad:
+ if (fp->fp)
+ {
+ sfclose(fp->fp);
+ fp->fp = 0;
+ }
+ remove(fp->encode.temp);
+ return -1;
+}
+
+/*
+ * close an open fastfind stream
+ */
+
+int
+findclose(register Find_t* fp)
+{
+ int n = 0;
+
+ if (!fp)
+ return -1;
+ if (fp->generate)
+ {
+ n = findsync(fp);
+ if (fp->encode.indexdict)
+ dtclose(fp->encode.indexdict);
+ if (fp->encode.namedict)
+ dtclose(fp->encode.namedict);
+ }
+ else
+ {
+ if (fp->decode.match)
+ regfree(&fp->decode.re);
+ n = 0;
+ }
+ if (fp->fp)
+ sfclose(fp->fp);
+ vmclose(fp->vm);
+ return n;
+}
diff --git a/src/lib/libast/misc/findlib.h b/src/lib/libast/misc/findlib.h
new file mode 100644
index 0000000..e42e619
--- /dev/null
+++ b/src/lib/libast/misc/findlib.h
@@ -0,0 +1,123 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * fast find private interface
+ */
+
+#ifndef _FINDLIB_H
+#define _FINDLIB_H
+
+#include <ast.h>
+#include <cdt.h>
+#include <ctype.h>
+#include <error.h>
+#include <ls.h>
+#include <regex.h>
+#include <vmalloc.h>
+
+#define FF_old 1 /* old format - 7 bit bigram */
+#define FF_gnu 2 /* gnu 8 bit no bigram */
+#define FF_dir 3 /* FF_gnu, dirs have trailing / */
+#define FF_typ 4 /* FF_dir with types */
+
+#define FF_gnu_magic "LOCATE02"
+#define FF_dir_magic "FIND-DIR-02"
+#define FF_typ_magic "FIND-DIR-TYPE-03"
+
+#define FF_ESC 0036
+#define FF_MAX 0200
+#define FF_MIN 0040
+#define FF_OFF 0016
+
+#define FF_SET_TYPE(p,i) ((p)->decode.bigram1[((i)>>3)&((1<<CHAR_BIT)-1)]|=(1<<((i)&07)))
+#define FF_OK_TYPE(p,i) (!(p)->types||((p)->decode.bigram1[((i)>>3)&((1<<CHAR_BIT)-1)]&(1<<((i)&07))))
+
+typedef struct
+{
+ char* end;
+ char* type;
+ char* restore;
+ int count;
+ int found;
+ int ignorecase;
+ int match;
+ int peek;
+ int swap;
+ regex_t re;
+ char bigram1[(1<<(CHAR_BIT-1))];
+ char bigram2[(1<<(CHAR_BIT-1))];
+ char path[PATH_MAX];
+ char temp[PATH_MAX];
+ char pattern[1];
+} Decode_t;
+
+typedef struct
+{
+ Dtdisc_t namedisc;
+ Dtdisc_t indexdisc;
+ Dt_t* namedict;
+ Dt_t* indexdict;
+ int prefix;
+ unsigned char bigram[2*FF_MAX];
+ unsigned short code[FF_MAX][FF_MAX];
+ unsigned short hits[USHRT_MAX+1];
+ char path[PATH_MAX];
+ char mark[PATH_MAX];
+ char file[PATH_MAX];
+ char temp[PATH_MAX];
+} Encode_t;
+
+typedef union
+{
+ Decode_t code_decode;
+ Encode_t code_encode;
+} Code_t;
+
+typedef struct
+{
+ Dtlink_t byname;
+ Dtlink_t byindex;
+ unsigned long index;
+ char name[1];
+} Type_t;
+
+#define _FIND_PRIVATE_ \
+ Finddisc_t* disc; \
+ Vmalloc_t* vm; \
+ char** dirs; \
+ int* lens; \
+ Sfio_t* fp; \
+ Findverify_f verifyf; \
+ int generate; \
+ int method; \
+ int secure; \
+ int types; \
+ int verify; \
+ Code_t code;
+
+#define decode code.code_decode
+#define encode code.code_encode
+
+#include <find.h>
+
+#endif
diff --git a/src/lib/libast/misc/fmtrec.c b/src/lib/libast/misc/fmtrec.c
new file mode 100644
index 0000000..36b2cd5
--- /dev/null
+++ b/src/lib/libast/misc/fmtrec.c
@@ -0,0 +1,102 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * return the record format string given a format descriptor
+ */
+
+#include <recfmt.h>
+#include <ctype.h>
+
+char*
+fmtrec(Recfmt_t f, int fs)
+{
+ char* b;
+ char* e;
+ char* s;
+ long n;
+ char del[2];
+
+ b = s = fmtbuf(n = 32);
+ e = b + n;
+ switch (RECTYPE(f))
+ {
+ case REC_delimited:
+ *s++ = 'd';
+ if ((del[0] = REC_D_DELIMITER(f)) != '\n')
+ {
+ del[1] = 0;
+ if (fs)
+ sfsprintf(s, e - s, "0x%02x", *(unsigned char*)del);
+ else
+ sfsprintf(s, e - s, "%s", fmtquote(del, NiL, NiL, 1, 0));
+ }
+ else
+ *s = 0;
+ break;
+ case REC_fixed:
+ if (!fs)
+ *s++ = 'f';
+ sfsprintf(s, e - s, "%lu", REC_F_SIZE(f));
+ break;
+ case REC_variable:
+ *s++ = 'v';
+ if (n = REC_V_SIZE(f))
+ s += sfsprintf(s, e - s, "%lu", n);
+ if (REC_V_HEADER(f) != 4)
+ s += sfsprintf(s, e - s, "h%u", REC_V_HEADER(f));
+ if (REC_V_OFFSET(f) != 0)
+ s += sfsprintf(s, e - s, "o%u", REC_V_OFFSET(f));
+ if (REC_V_LENGTH(f) != 2)
+ s += sfsprintf(s, e - s, "z%u", REC_V_LENGTH(f));
+ if (REC_V_LITTLE(f) != 0)
+ *s++ = 'l';
+ if (REC_V_INCLUSIVE(f) == 0)
+ *s++ = 'n';
+ *s = 0;
+ break;
+ case REC_method:
+ *s++ = 'm';
+ switch (n = REC_M_INDEX(f))
+ {
+ case REC_M_data:
+ sfsprintf(s, e - s, "data");
+ break;
+ case REC_M_path:
+ sfsprintf(s, e - s, "path");
+ break;
+ default:
+ sfsprintf(s, e - s, "%lu", n);
+ break;
+ }
+ break;
+ case REC_none:
+ *s++ = 'n';
+ *s = 0;
+ break;
+ default:
+ sfsprintf(s, e - s, "u%u.0x%07x", RECTYPE(f), REC_U_ATTRIBUTES(f));
+ break;
+ }
+ return b;
+}
diff --git a/src/lib/libast/misc/fs3d.c b/src/lib/libast/misc/fs3d.c
new file mode 100644
index 0000000..cc708f2
--- /dev/null
+++ b/src/lib/libast/misc/fs3d.c
@@ -0,0 +1,116 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * 3d fs operations
+ * only active for non-shared 3d library
+ */
+
+#define mount ______mount
+
+#include <ast.h>
+
+#undef mount
+
+#include <fs3d.h>
+
+int
+fs3d(register int op)
+{
+ register int cur;
+ register char* v;
+ char val[sizeof(FS3D_off) + 8];
+
+ static int fsview;
+ static char on[] = FS3D_on;
+ static char off[] = FS3D_off;
+
+ if (fsview < 0)
+ return 0;
+
+ /*
+ * get the current setting
+ */
+
+ if (!fsview && (!getenv("LD_PRELOAD") || mount("", "", 0, NiL)))
+ goto nope;
+ if (FS3D_op(op) == FS3D_OP_INIT && mount(FS3D_init, NiL, FS3D_VIEW, NiL))
+ goto nope;
+ if (mount(on, val, FS3D_VIEW|FS3D_GET|FS3D_SIZE(sizeof(val)), NiL))
+ goto nope;
+ if (v = strchr(val, ' '))
+ v++;
+ else
+ v = val;
+ if (!strcmp(v, on))
+ cur = FS3D_ON;
+ else if (!strncmp(v, off, sizeof(off) - 1) && v[sizeof(off)] == '=')
+ cur = FS3D_LIMIT((int)strtol(v + sizeof(off) + 1, NiL, 0));
+ else
+ cur = FS3D_OFF;
+ if (cur != op)
+ {
+ switch (FS3D_op(op))
+ {
+ case FS3D_OP_OFF:
+ v = off;
+ break;
+ case FS3D_OP_ON:
+ v = on;
+ break;
+ case FS3D_OP_LIMIT:
+ sfsprintf(val, sizeof(val), "%s=%d", off, FS3D_arg(op));
+ v = val;
+ break;
+ default:
+ v = 0;
+ break;
+ }
+ if (v && mount(v, NiL, FS3D_VIEW, NiL))
+ goto nope;
+ }
+ fsview = 1;
+ return cur;
+ nope:
+ fsview = -1;
+ return 0;
+}
+
+/*
+ * user code that includes <fs3d.h> will have mount() mapped to fs3d_mount()
+ * this restricts the various "standard" mount prototype conflicts to this spot
+ * this means that code that includes <fs3d.h> cannot access the real mount
+ * (at least without some additional macro hackery
+ */
+
+#undef mount
+
+extern int mount(const char*, char*, int, void*);
+
+int
+fs3d_mount(const char* source, char* target, int flags, void* data)
+{
+ return mount(source, target, flags, data);
+}
diff --git a/src/lib/libast/misc/fts.c b/src/lib/libast/misc/fts.c
new file mode 100644
index 0000000..d8bb34d
--- /dev/null
+++ b/src/lib/libast/misc/fts.c
@@ -0,0 +1,1605 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Phong Vo
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * fts implementation unwound from the kpv ftwalk() of 1988-10-30
+ */
+
+#include <ast.h>
+#include <ast_dir.h>
+#include <error.h>
+#include <fs3d.h>
+#include <ls.h>
+
+struct Ftsent;
+
+typedef int (*Compar_f)(struct Ftsent* const*, struct Ftsent* const*);
+typedef int (*Stat_f)(const char*, struct stat*);
+
+#define _fts_status status
+#define _fts_statb statb
+
+#define _FTS_PRIVATE_ \
+ FTSENT* parent; /* top parent */ \
+ FTSENT* todo; /* todo list */ \
+ FTSENT* top; /* top element */ \
+ FTSENT* root; \
+ FTSENT* bot; /* bottom element */ \
+ FTSENT* free; /* free element */ \
+ FTSENT* diroot; \
+ FTSENT* curdir; \
+ FTSENT* current; /* current element */ \
+ FTSENT* previous; /* previous current */ \
+ FTSENT* dotdot; \
+ FTSENT* link; /* real current fts_link*/ \
+ FTSENT* pwd; /* pwd parent */ \
+ DIR* dir; /* current dir stream */ \
+ Compar_f comparf; /* node comparison func */ \
+ size_t baselen; /* current strlen(base) */ \
+ size_t homesize; /* sizeof(home) */ \
+ int cd; /* chdir status */ \
+ int cpname; \
+ int flags; /* fts_open() flags */ \
+ int nd; \
+ unsigned char children; \
+ unsigned char fs3d; \
+ unsigned char nostat; \
+ unsigned char state; /* fts_read() state */ \
+ char* base; /* basename in path */ \
+ char* name; \
+ char* path; /* path workspace */ \
+ char* home; /* home/path buffer */ \
+ char* endbase; /* space to build paths */ \
+ char* endbuf; /* space to build paths */ \
+ char* pad[2]; /* $0.02 to splain this */
+
+/*
+ * NOTE: <ftwalk.h> relies on status and statb being the first two elements
+ */
+
+#define _FTSENT_PRIVATE_ \
+ int nd; /* popdir() count */ \
+ FTSENT* left; /* left child */ \
+ FTSENT* right; /* right child */ \
+ FTSENT* pwd; /* pwd parent */ \
+ FTSENT* stack; /* getlist() stack */ \
+ long nlink; /* FTS_D link count */ \
+ unsigned char must; /* must stat */ \
+ unsigned char type; /* DT_* type */ \
+ unsigned char symlink; /* originally a symlink */ \
+ char name[sizeof(int)]; /* fts_name data */
+
+#include <fts.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+
+#if MAXNAMLEN > 16
+#define MINNAME 32
+#else
+#define MINNAME 16
+#endif
+
+#define drop(p,f) (((f)->fts_namelen < MINNAME) ? ((f)->fts_link = (p)->free, (p)->free = (f)) : (free(f), (p)->free))
+
+#define ACCESS(p,f) ((p)->cd==0?(f)->fts_name:(f)->fts_path)
+#define PATH(f,p,l) ((!((f)->flags&FTS_SEEDOTDIR)&&(l)>0&&(p)[0]=='.'&&(p)[1]=='/')?((p)+2):(p))
+#define SAME(one,two) ((one)->st_ino==(two)->st_ino&&(one)->st_dev==(two)->st_dev)
+#define SKIPLINK(p,f) ((f)->fts_parent->nlink == 0)
+
+#ifdef D_TYPE
+#define ISTYPE(f,t) ((f)->type == (t))
+#define TYPE(f,t) ((f)->type = (t))
+#define SKIP(p,f) ((f)->fts_parent->must == 0 && (((f)->type == DT_UNKNOWN) ? SKIPLINK(p,f) : ((f)->type != DT_DIR && ((f)->type != DT_LNK || ((p)->flags & FTS_PHYSICAL)))))
+#else
+#undef DT_UNKNOWN
+#define DT_UNKNOWN 0
+#undef DT_LNK
+#define DT_LNK 1
+#define ISTYPE(f,t) ((t)==DT_UNKNOWN)
+#define TYPE(f,d)
+#define SKIP(p,f) ((f)->fts_parent->must == 0 && SKIPLINK(p,f))
+#endif
+
+#ifndef D_FILENO
+#define D_FILENO(d) (1)
+#endif
+
+/*
+ * NOTE: a malicious dir rename() could change .. underfoot so we
+ * must always verify; undef verify to enable the unsafe code
+ */
+
+#define verify 1
+
+/*
+ * FTS_NOSTAT requires a dir with
+ * D_TYPE(&dirent_t)!=DT_UNKNOWN
+ * OR
+ * st_nlink>=2
+ */
+
+#define FTS_children_resume 1
+#define FTS_children_return 2
+#define FTS_error 3
+#define FTS_popstack 4
+#define FTS_popstack_resume 5
+#define FTS_popstack_return 6
+#define FTS_preorder 7
+#define FTS_preorder_resume 8
+#define FTS_preorder_return 9
+#define FTS_readdir 10
+#define FTS_terminal 11
+#define FTS_todo 12
+#define FTS_top_return 13
+
+typedef int (*Notify_f)(FTS*, FTSENT*, void*);
+
+typedef struct Notify_s
+{
+ struct Notify_s* next;
+ Notify_f notifyf;
+ void* context;
+} Notify_t;
+
+static Notify_t* notify;
+
+/*
+ * allocate an FTSENT node
+ */
+
+static FTSENT*
+node(FTS* fts, FTSENT* parent, register char* name, register size_t namelen)
+{
+ register FTSENT* f;
+ register size_t n;
+
+ if (fts->free && namelen < MINNAME)
+ {
+ f = fts->free;
+ fts->free = f->fts_link;
+ }
+ else
+ {
+ n = (namelen < MINNAME ? MINNAME : namelen + 1) - sizeof(int);
+ if (!(f = newof(0, FTSENT, 1, n)))
+ {
+ fts->fts_errno = errno;
+ fts->state = FTS_error;
+ return 0;
+ }
+ f->fts = fts;
+ }
+ TYPE(f, DT_UNKNOWN);
+ f->status = 0;
+ f->symlink = 0;
+ f->fts_level = (f->fts_parent = parent)->fts_level + 1;
+#if __OBSOLETE__ < 20140101
+ f->_fts_level = (short)f->fts_level;
+#endif
+ f->fts_link = 0;
+ f->fts_pointer = 0;
+ f->fts_number = 0;
+ f->fts_errno = 0;
+ f->fts_namelen = namelen;
+#if __OBSOLETE__ < 20140101
+ f->_fts_namelen = (unsigned short)f->fts_namelen;
+#endif
+ f->fts_name = f->name;
+ f->fts_statp = &f->statb;
+ memcpy(f->fts_name, name, namelen + 1);
+ return f;
+}
+
+/*
+ * compare directories by device/inode
+ */
+
+static int
+statcmp(FTSENT* const* pf1, FTSENT* const* pf2)
+{
+ register const FTSENT* f1 = *pf1;
+ register const FTSENT* f2 = *pf2;
+
+ if (f1->statb.st_ino < f2->statb.st_ino)
+ return -1;
+ if (f1->statb.st_ino > f2->statb.st_ino)
+ return 1;
+ if (f1->statb.st_dev < f2->statb.st_dev)
+ return -1;
+ if (f1->statb.st_dev > f2->statb.st_dev)
+ return 1;
+
+ /*
+ * hack for NFS where <dev,ino> may not uniquely identify objects
+ */
+
+ if (f1->statb.st_mtime < f2->statb.st_mtime)
+ return -1;
+ if (f1->statb.st_mtime > f2->statb.st_mtime)
+ return 1;
+ return 0;
+}
+
+/*
+ * search trees with top-down splaying (a la Tarjan and Sleator)
+ * when used for insertion sort, this implements a stable sort
+ */
+
+#define RROTATE(r) (t = r->left, r->left = t->right, t->right = r, r = t)
+#define LROTATE(r) (t = r->right, r->right = t->left, t->left = r, r = t)
+
+static FTSENT*
+search(FTSENT* e, FTSENT* root, int(*comparf)(FTSENT* const*, FTSENT* const*), int insert)
+{
+ register int cmp;
+ register FTSENT* t;
+ register FTSENT* left;
+ register FTSENT* right;
+ register FTSENT* lroot;
+ register FTSENT* rroot;
+
+ left = right = lroot = rroot = 0;
+ while (root)
+ {
+ if (!(cmp = (*comparf)(&e, &root)) && !insert)
+ break;
+ if (cmp < 0)
+ {
+ /*
+ * this is the left zig-zig case
+ */
+
+ if (root->left && (cmp = (*comparf)(&e, &root->left)) <= 0)
+ {
+ RROTATE(root);
+ if (!cmp && !insert)
+ break;
+ }
+
+ /*
+ * stick all things > e to the right tree
+ */
+
+ if (right)
+ right->left = root;
+ else
+ rroot = root;
+ right = root;
+ root = root->left;
+ right->left = 0;
+ }
+ else
+ {
+ /*
+ * this is the right zig-zig case
+ */
+
+ if (root->right && (cmp = (*comparf)(&e, &root->right)) >= 0)
+ {
+ LROTATE(root);
+ if (!cmp && !insert)
+ break;
+ }
+
+ /*
+ * stick all things <= e to the left tree
+ */
+
+ if (left)
+ left->right = root;
+ else
+ lroot = root;
+ left = root;
+ root = root->right;
+ left->right = 0;
+ }
+ }
+ if (!root)
+ root = e;
+ else
+ {
+ if (right)
+ right->left = root->right;
+ else
+ rroot = root->right;
+ if (left)
+ left->right = root->left;
+ else
+ lroot = root->left;
+ }
+ root->left = lroot;
+ root->right = rroot;
+ return root;
+}
+
+/*
+ * delete the root element from the tree
+ */
+
+static FTSENT*
+deleteroot(register FTSENT* root)
+{
+ register FTSENT* t;
+ register FTSENT* left;
+ register FTSENT* right;
+
+ right = root->right;
+ if (!(left = root->left))
+ root = right;
+ else
+ {
+ while (left->right)
+ LROTATE(left);
+ left->right = right;
+ root = left;
+ }
+ return root;
+}
+
+/*
+ * generate ordered fts_link list from binary tree at root
+ * FTSENT.stack instead of recursion to avoid blowing the real
+ * stack on big directories
+ */
+
+static void
+getlist(register FTSENT** top, register FTSENT** bot, register FTSENT* root)
+{
+ register FTSENT* stack = 0;
+
+ for (;;)
+ {
+ if (root->left)
+ {
+ root->stack = stack;
+ stack = root;
+ root = root->left;
+ }
+ else
+ {
+ for (;;)
+ {
+ if (*top)
+ *bot = (*bot)->fts_link = root;
+ else
+ *bot = *top = root;
+ if (root->right)
+ {
+ root = root->right;
+ break;
+ }
+ if (!(root = stack))
+ {
+ (*bot)->fts_link = 0;
+ return;
+ }
+ stack = stack->stack;
+ }
+ }
+ }
+}
+
+/*
+ * set directory when curdir is lost in space
+ */
+
+static int
+setdir(register char* home, register char* path)
+{
+ register int cdrv;
+
+ if (path[0] == '/')
+ cdrv = pathcd(path, NiL);
+ else
+ {
+ /*
+ * note that path and home are in the same buffer
+ */
+
+ path[-1] = '/';
+ cdrv = pathcd(home, NiL);
+ path[-1] = 0;
+ }
+ if (cdrv < 0)
+ pathcd(home, NiL);
+ return cdrv;
+}
+
+/*
+ * set to parent dir
+ */
+
+static int
+setpdir(register char* home, register char* path, register char* base)
+{
+ register int c;
+ register int cdrv;
+
+ if (base > path)
+ {
+ c = base[0];
+ base[0] = 0;
+ cdrv = setdir(home, path);
+ base[0] = c;
+ }
+ else
+ cdrv = pathcd(home, NiL);
+ return cdrv;
+}
+
+/*
+ * pop a set of directories
+ */
+static int
+popdirs(FTS* fts)
+{
+ register FTSENT*f;
+ register char* s;
+ register char* e;
+#ifndef verify
+ register int verify;
+#endif
+ struct stat sb;
+ char buf[PATH_MAX];
+
+ if (!(f = fts->curdir) || f->fts_level < 0)
+ return -1;
+ e = buf + sizeof(buf) - 4;
+#ifndef verify
+ verify = 0;
+#endif
+ while (fts->nd > 0)
+ {
+ for (s = buf; s < e && fts->nd > 0; fts->nd--)
+ {
+ if (fts->pwd)
+ {
+#ifndef verify
+ verify |= fts->pwd->symlink;
+#endif
+ fts->pwd = fts->pwd->pwd;
+ }
+ *s++ = '.';
+ *s++ = '.';
+ *s++ = '/';
+ }
+ *s = 0;
+ if (chdir(buf))
+ return -1;
+ }
+ return (verify && (stat(".", &sb) < 0 || !SAME(&sb, f->fts_statp))) ? -1 : 0;
+}
+
+/*
+ * initialize st from path and fts_info from st
+ */
+
+static int
+info(FTS* fts, register FTSENT* f, const char* path, struct stat* sp, int flags)
+{
+ if (path)
+ {
+#ifdef S_ISLNK
+ if (!f->symlink && (ISTYPE(f, DT_UNKNOWN) || ISTYPE(f, DT_LNK)))
+ {
+ if (lstat(path, sp) < 0)
+ goto bad;
+ }
+ else
+#endif
+ if (stat(path, sp) < 0)
+ goto bad;
+ }
+#ifdef S_ISLNK
+ again:
+#endif
+ if (S_ISDIR(sp->st_mode))
+ {
+ if ((flags & FTS_NOSTAT) && !fts->fs3d)
+ {
+ f->fts_parent->nlink--;
+#ifdef D_TYPE
+ if ((f->nlink = sp->st_nlink) < 2)
+ {
+ f->must = 2;
+ f->nlink = 2;
+ }
+ else
+ f->must = 0;
+#else
+ if ((f->nlink = sp->st_nlink) >= 2)
+ f->must = 1;
+ else
+ f->must = 2;
+#endif
+ }
+ else
+ f->must = 2;
+ TYPE(f, DT_DIR);
+ f->fts_info = FTS_D;
+ }
+#ifdef S_ISLNK
+ else if (S_ISLNK((sp)->st_mode))
+ {
+ struct stat sb;
+
+ f->symlink = 1;
+ if (flags & FTS_PHYSICAL)
+ {
+ TYPE(f, DT_LNK);
+ f->fts_info = FTS_SL;
+ }
+ else if (stat(path, &sb) >= 0)
+ {
+ *sp = sb;
+ flags = FTS_PHYSICAL;
+ goto again;
+ }
+ else
+ {
+ TYPE(f, DT_LNK);
+ f->fts_info = FTS_SLNONE;
+ }
+ }
+#endif
+ else
+ {
+ TYPE(f, DT_REG);
+ f->fts_info = FTS_F;
+ }
+ return 0;
+ bad:
+ TYPE(f, DT_UNKNOWN);
+ f->fts_info = FTS_NS;
+ return -1;
+}
+
+/*
+ * get top list of elements to process
+ * ordering delayed until first fts_read()
+ * to give caller a chance to set fts->handle
+ */
+
+static FTSENT*
+toplist(FTS* fts, register char* const* pathnames)
+{
+ register char* path;
+ register FTSENT* f;
+ register FTSENT* top;
+ register FTSENT* bot;
+ int physical;
+ int metaphysical;
+ char* s;
+ struct stat st;
+
+ if (fts->flags & FTS_NOSEEDOTDIR)
+ fts->flags &= ~FTS_SEEDOTDIR;
+ physical = (fts->flags & FTS_PHYSICAL);
+ metaphysical = (fts->flags & (FTS_META|FTS_PHYSICAL)) == (FTS_META|FTS_PHYSICAL);
+ top = bot = 0;
+ while (path = *pathnames++)
+ {
+ /*
+ * make elements
+ */
+
+ if (!(f = node(fts, fts->parent, path, strlen(path))))
+ break;
+ path = f->fts_name;
+ if (!physical)
+ f->fts_namelen = (fts->flags & FTS_SEEDOTDIR) ? strlen(path) : (pathcanon(path, strlen(path) + 1, 0) - path);
+ else if (*path != '.')
+ {
+ f->fts_namelen = strlen(path);
+ fts->flags |= FTS_SEEDOTDIR;
+ }
+ else
+ {
+ if (fts->flags & FTS_NOSEEDOTDIR)
+ {
+ fts->flags &= ~FTS_SEEDOTDIR;
+ s = path;
+ while (*s++ == '.' && *s++ == '/')
+ {
+ while (*s == '/')
+ s++;
+ if (!*s)
+ break;
+ path = f->fts_name;
+ while (*path++ = *s++);
+ path = f->fts_name;
+ }
+ }
+ else
+ fts->flags |= FTS_SEEDOTDIR;
+ for (s = path + strlen(path); s > path && *(s - 1) == '/'; s--);
+ *s = 0;
+ f->fts_namelen = s - path;
+ }
+#if __OBSOLETE__ < 20140101
+ f->_fts_namelen = (unsigned short)f->fts_namelen;
+#endif
+ if (!*path)
+ {
+ errno = ENOENT;
+ f->fts_info = FTS_NS;
+ }
+ else
+ info(fts, f, path, f->fts_statp, fts->flags);
+#ifdef S_ISLNK
+
+ /*
+ * don't let any standards committee get
+ * away with calling your idea a hack
+ */
+
+ if (metaphysical && f->fts_info == FTS_SL)
+ {
+ if (stat(path, &st) >= 0)
+ {
+ *f->fts_statp = st;
+ info(fts, f, NiL, f->fts_statp, 0);
+ }
+ else
+ f->fts_info = FTS_SLNONE;
+ }
+#endif
+ if (bot)
+ {
+ bot->fts_link = f;
+ bot = f;
+ }
+ else
+ top = bot = f;
+ }
+ return top;
+}
+
+/*
+ * order fts->todo if fts->comparf != 0
+ */
+
+static void
+order(FTS* fts)
+{
+ register FTSENT* f;
+ register FTSENT* root;
+ FTSENT* top;
+ FTSENT* bot;
+
+ top = bot = root = 0;
+ for (f = fts->todo; f; f = f->fts_link)
+ root = search(f, root, fts->comparf, 1);
+ getlist(&top, &bot, root);
+ fts->todo = top;
+}
+
+/*
+ * resize the path buffer
+ * note that free() is not used because we may need to chdir(fts->home)
+ * if there isn't enough space to continue
+ */
+
+static int
+resize(register FTS* fts, size_t inc)
+{
+ register char* old;
+ register char* newp;
+ register size_t n_old;
+
+ /*
+ * add space for "/." used in testing FTS_DNX
+ */
+
+ n_old = fts->homesize;
+ fts->homesize = ((fts->homesize + inc + 4) / PATH_MAX + 1) * PATH_MAX;
+ if (!(newp = newof(0, char, fts->homesize, 0)))
+ {
+ fts->fts_errno = errno;
+ fts->state = FTS_error;
+ return -1;
+ }
+ old = fts->home;
+ fts->home = newp;
+ memcpy(newp, old, n_old);
+ if (fts->endbuf)
+ fts->endbuf = newp + fts->homesize - 4;
+ if (fts->path)
+ fts->path = newp + (fts->path - old);
+ if (fts->base)
+ fts->base = newp + (fts->base - old);
+ free(old);
+ return 0;
+}
+
+/*
+ * open a new fts stream on pathnames
+ */
+
+FTS*
+fts_open(char* const* pathnames, int flags, int (*comparf)(FTSENT* const*, FTSENT* const*))
+{
+ register FTS* fts;
+
+ if (!(fts = newof(0, FTS, 1, sizeof(FTSENT))))
+ return 0;
+ fts->flags = flags;
+ fts->cd = (flags & FTS_NOCHDIR) ? 1 : -1;
+ fts->comparf = comparf;
+ fts->fs3d = fs3d(FS3D_TEST);
+
+ /*
+ * set up the path work buffer
+ */
+
+ fts->homesize = 2 * PATH_MAX;
+ for (;;)
+ {
+ if (!(fts->home = newof(fts->home, char, fts->homesize, 0)))
+ {
+ free(fts);
+ return 0;
+ }
+ if (fts->cd > 0 || getcwd(fts->home, fts->homesize))
+ break;
+ if (errno == ERANGE)
+ fts->homesize += PATH_MAX;
+ else
+ fts->cd = 1;
+ }
+ fts->endbuf = fts->home + fts->homesize - 4;
+
+ /*
+ * initialize the tippity-top
+ */
+
+ fts->parent = (FTSENT*)(fts + 1);
+ fts->parent->fts_info = FTS_D;
+ memcpy(fts->parent->fts_accpath = fts->parent->fts_path = fts->parent->fts_name = fts->parent->name, ".", 2);
+ fts->parent->fts_level = -1;
+#if __OBSOLETE__ < 20140101
+ fts->parent->_fts_level = (short)fts->parent->fts_level;
+#endif
+ fts->parent->fts_statp = &fts->parent->statb;
+ fts->parent->must = 2;
+ fts->parent->type = DT_UNKNOWN;
+ fts->path = fts->home + strlen(fts->home) + 1;
+
+ /*
+ * make the list of top elements
+ */
+
+ if (!pathnames || (flags & FTS_ONEPATH) || !*pathnames)
+ {
+ char* v[2];
+
+ v[0] = pathnames && (flags & FTS_ONEPATH) ? (char*)pathnames : ".";
+ v[1] = 0;
+ fts->todo = toplist(fts, v);
+ }
+ else
+ fts->todo = toplist(fts, pathnames);
+#if _HUH_1997_01_07
+ if (!fts->todo || fts->todo->fts_info == FTS_NS && !fts->todo->fts_link)
+#else
+ if (!fts->todo)
+#endif
+ {
+ fts_close(fts);
+ return 0;
+ }
+ return fts;
+}
+
+/*
+ * return the next FTS entry
+ */
+
+FTSENT*
+fts_read(register FTS* fts)
+{
+ register char* s;
+ register int n;
+ register FTSENT* f;
+ struct dirent* d;
+ size_t i;
+ FTSENT* t;
+ Notify_t* p;
+#ifdef verify
+ struct stat sb;
+#endif
+
+ for (;;)
+ switch (fts->state)
+ {
+
+ case FTS_top_return:
+
+ f = fts->todo;
+ t = 0;
+ while (f)
+ if (f->status == FTS_SKIP)
+ {
+ if (t)
+ {
+ t->fts_link = f->fts_link;
+ drop(fts, f);
+ f = t->fts_link;
+ }
+ else
+ {
+ fts->todo = f->fts_link;
+ drop(fts, f);
+ f = fts->todo;
+ }
+ }
+ else
+ {
+ t = f;
+ f = f->fts_link;
+ }
+ /*FALLTHROUGH*/
+
+ case 0:
+
+ if (!fts->state && fts->comparf)
+ order(fts);
+ if (!(f = fts->todo))
+ return 0;
+ /*FALLTHROUGH*/
+
+ case FTS_todo:
+
+ /*
+ * process the top object on the stack
+ */
+
+ fts->root = fts->top = fts->bot = 0;
+
+ /*
+ * initialize the top level
+ */
+
+ if (f->fts_level == 0)
+ {
+ fts->parent->fts_number = f->fts_number;
+ fts->parent->fts_pointer = f->fts_pointer;
+ fts->parent->fts_statp = f->fts_statp;
+ fts->parent->statb = *f->fts_statp;
+ f->fts_parent = fts->parent;
+ fts->diroot = 0;
+ if (fts->cd == 0)
+ pathcd(fts->home, NiL);
+ else if (fts->cd < 0)
+ fts->cd = 0;
+ fts->pwd = f->fts_parent;
+ fts->curdir = fts->cd ? 0 : f->fts_parent;
+ *(fts->base = fts->path) = 0;
+ }
+
+ /*
+ * chdir to parent if asked for
+ */
+
+ if (fts->cd < 0)
+ {
+ fts->cd = setdir(fts->home, fts->path);
+ fts->pwd = f->fts_parent;
+ fts->curdir = fts->cd ? 0 : f->fts_parent;
+ }
+
+ /*
+ * add object's name to the path
+ */
+
+ if ((fts->baselen = f->fts_namelen) >= (fts->endbuf - fts->base) && resize(fts, fts->baselen))
+ return 0;
+ memcpy(fts->base, f->name, fts->baselen + 1);
+ fts->name = fts->cd ? fts->path : fts->base;
+ /*FALLTHROUGH*/
+
+ case FTS_preorder:
+
+ /*
+ * check for cycle and open dir
+ */
+
+ if (f->fts_info == FTS_D)
+ {
+ if ((fts->diroot = search(f, fts->diroot, statcmp, 0)) != f || f->fts_level > 0 && (t = f) && statcmp(&t, &f->fts_parent) == 0)
+ {
+ f->fts_info = FTS_DC;
+ f->fts_cycle = fts->diroot;
+ }
+ else if (!(fts->flags & FTS_TOP) && (!(fts->flags & FTS_XDEV) || f->statb.st_dev == f->fts_parent->statb.st_dev))
+ {
+ /*
+ * buffer is known to be large enough here!
+ */
+
+ if (fts->base[fts->baselen - 1] != '/')
+ memcpy(fts->base + fts->baselen, "/.", 3);
+ if (!(fts->dir = opendir(fts->name)))
+ f->fts_info = FTS_DNX;
+ fts->base[fts->baselen] = 0;
+ if (!fts->dir && !(fts->dir = opendir(fts->name)))
+ f->fts_info = FTS_DNR;
+ }
+ }
+ f->nd = f->fts_info & ~FTS_DNX;
+ if (f->nd || !(fts->flags & FTS_NOPREORDER))
+ {
+ fts->current = f;
+ fts->link = f->fts_link;
+ f->fts_link = 0;
+ f->fts_path = PATH(fts, fts->path, f->fts_level);
+ f->fts_pathlen = (fts->base - f->fts_path) + fts->baselen;
+ f->fts_accpath = ACCESS(fts, f);
+ fts->state = FTS_preorder_return;
+ goto note;
+ }
+ /*FALLTHROUGH*/
+
+ case FTS_preorder_resume:
+
+ /*
+ * prune
+ */
+
+ if (!fts->dir || f->nd || f->status == FTS_SKIP)
+ {
+ if (fts->dir)
+ {
+ closedir(fts->dir);
+ fts->dir = 0;
+ }
+ fts->state = FTS_popstack;
+ continue;
+ }
+
+ /*
+ * FTS_D or FTS_DNX, about to read children
+ */
+
+ if (fts->cd == 0)
+ {
+ if ((fts->cd = chdir(fts->name)) < 0)
+ pathcd(fts->home, NiL);
+ else if (fts->pwd != f)
+ {
+ f->pwd = fts->pwd;
+ fts->pwd = f;
+ }
+ fts->curdir = fts->cd < 0 ? 0 : f;
+ }
+ fts->nostat = fts->children > 1 || f->fts_info == FTS_DNX;
+ fts->cpname = fts->cd && !fts->nostat || !fts->children && !fts->comparf;
+ fts->dotdot = 0;
+ fts->endbase = fts->base + fts->baselen;
+ if (fts->endbase[-1] != '/')
+ *fts->endbase++ = '/';
+ fts->current = f;
+ /*FALLTHROUGH*/
+
+ case FTS_readdir:
+
+ while (d = readdir(fts->dir))
+ {
+ s = d->d_name;
+ if (s[0] == '.')
+ {
+ if (s[1] == 0)
+ {
+ fts->current->nlink--;
+ if (!(fts->flags & FTS_SEEDOT))
+ continue;
+ n = 1;
+ }
+ else if (s[1] == '.' && s[2] == 0)
+ {
+ fts->current->nlink--;
+ if (fts->current->must == 1)
+ fts->current->must = 0;
+ if (!(fts->flags & FTS_SEEDOT))
+ continue;
+ n = 2;
+ }
+ else
+ n = 0;
+ }
+ else
+ n = 0;
+
+ /*
+ * make a new entry
+ */
+
+ i = D_NAMLEN(d);
+ if (!(f = node(fts, fts->current, s, i)))
+ return 0;
+ TYPE(f, D_TYPE(d));
+
+ /*
+ * check for space
+ */
+
+ if (i >= fts->endbuf - fts->endbase)
+ {
+ if (resize(fts, i))
+ return 0;
+ fts->endbase = fts->base + fts->baselen;
+ if (fts->endbase[-1] != '/')
+ fts->endbase++;
+ }
+ if (fts->cpname)
+ {
+ memcpy(fts->endbase, s, i + 1);
+ if (fts->cd)
+ s = fts->path;
+ }
+ if (n)
+ {
+ /*
+ * don't recurse on . and ..
+ */
+
+ if (n == 1)
+ f->fts_statp = fts->current->fts_statp;
+ else
+ {
+ if (f->fts_info != FTS_NS)
+ fts->dotdot = f;
+ if (fts->current->fts_parent->fts_level < 0)
+ {
+ f->fts_statp = &fts->current->fts_parent->statb;
+ info(fts, f, s, f->fts_statp, 0);
+ }
+ else
+ f->fts_statp = fts->current->fts_parent->fts_statp;
+ }
+ f->fts_info = FTS_DOT;
+ }
+ else if ((fts->nostat || SKIP(fts, f)) && (f->fts_info = FTS_NSOK) || info(fts, f, s, &f->statb, fts->flags))
+ f->statb.st_ino = D_FILENO(d);
+ if (fts->comparf)
+ fts->root = search(f, fts->root, fts->comparf, 1);
+ else if (fts->children || f->fts_info == FTS_D || f->fts_info == FTS_SL)
+ {
+ if (fts->top)
+ fts->bot = fts->bot->fts_link = f;
+ else
+ fts->top = fts->bot = f;
+ }
+ else
+ {
+ /*
+ * terminal node
+ */
+
+ f->fts_path = PATH(fts, fts->path, 1);
+ f->fts_pathlen = fts->endbase - f->fts_path + f->fts_namelen;
+ f->fts_accpath = ACCESS(fts, f);
+ fts->previous = fts->current;
+ fts->current = f;
+ fts->state = FTS_terminal;
+ goto note;
+ }
+ }
+
+ /*
+ * done with the directory
+ */
+
+ closedir(fts->dir);
+ fts->dir = 0;
+ if (fts->root)
+ getlist(&fts->top, &fts->bot, fts->root);
+ if (fts->children)
+ {
+ /*
+ * try moving back to parent dir
+ */
+
+ fts->base[fts->baselen] = 0;
+ if (fts->cd <= 0)
+ {
+ f = fts->current->fts_parent;
+ if (fts->cd < 0
+ || f != fts->curdir
+ || !fts->dotdot
+ || !SAME(f->fts_statp, fts->dotdot->fts_statp)
+ || fts->pwd && fts->pwd->symlink
+ || (fts->cd = chdir("..")) < 0
+#ifdef verify
+ || stat(".", &sb) < 0
+ || !SAME(&sb, fts->dotdot->fts_statp)
+#endif
+ )
+ fts->cd = setpdir(fts->home, fts->path, fts->base);
+ if (fts->pwd)
+ fts->pwd = fts->pwd->pwd;
+ fts->curdir = fts->cd ? 0 : f;
+ }
+ f = fts->current;
+ fts->link = f->fts_link;
+ f->fts_link = fts->top;
+ f->fts_path = PATH(fts, fts->path, f->fts_level);
+ f->fts_pathlen = (fts->base - f->fts_path) + f->fts_namelen;
+ f->fts_accpath = ACCESS(fts, f);
+ fts->state = FTS_children_return;
+ goto note;
+ }
+ /*FALLTHROUGH*/
+
+ case FTS_children_resume:
+
+ fts->base[fts->baselen] = 0;
+ if (fts->top)
+ {
+ fts->bot->fts_link = fts->todo;
+ fts->todo = fts->top;
+ fts->top = 0;
+ }
+ /*FALLTHROUGH*/
+
+ case FTS_popstack:
+
+ /*
+ * pop objects completely processed
+ */
+
+ fts->nd = 0;
+ f = fts->current;
+ /*FALLTHROUGH*/
+
+ case FTS_popstack_resume:
+
+ while (fts->todo && f == fts->todo)
+ {
+ t = f->fts_parent;
+ if ((f->fts_info & FTS_DP) == FTS_D)
+ {
+ /*
+ * delete from <dev,ino> tree
+ */
+
+ if (f != fts->diroot)
+ fts->diroot = search(f, fts->diroot, statcmp, 0);
+ fts->diroot = deleteroot(fts->diroot);
+ if (f == fts->curdir)
+ {
+ fts->nd++;
+ fts->curdir = t;
+ }
+
+ /*
+ * perform post-order processing
+ */
+
+ if (!(fts->flags & FTS_NOPOSTORDER) &&
+ f->status != FTS_SKIP &&
+ f->status != FTS_NOPOSTORDER)
+ {
+ /*
+ * move to parent dir
+ */
+
+ if (fts->nd > 0)
+ fts->cd = popdirs(fts);
+ if (fts->cd < 0)
+ fts->cd = setpdir(fts->home, fts->path, fts->base);
+ fts->curdir = fts->cd ? 0 : t;
+ f->fts_info = FTS_DP;
+ f->fts_path = PATH(fts, fts->path, f->fts_level);
+ f->fts_pathlen = (fts->base - f->fts_path) + f->fts_namelen;
+ f->fts_accpath = ACCESS(fts, f);
+
+ /*
+ * re-stat to update nlink/times
+ */
+
+ stat(f->fts_accpath, f->fts_statp);
+ fts->link = f->fts_link;
+ f->fts_link = 0;
+ fts->state = FTS_popstack_return;
+ goto note;
+ }
+ }
+
+ /*
+ * reset base
+ */
+
+ if (fts->base > fts->path + t->fts_namelen)
+ fts->base--;
+ *fts->base = 0;
+ fts->base -= t->fts_namelen;
+
+ /*
+ * try again or delete from top of stack
+ */
+
+ if (f->status == FTS_AGAIN)
+ {
+ f->fts_info = FTS_D;
+ f->status = 0;
+ }
+ else
+ {
+ fts->todo = fts->todo->fts_link;
+ drop(fts, f);
+ }
+ f = t;
+ }
+
+ /*
+ * reset current directory
+ */
+
+ if (fts->nd > 0 && popdirs(fts) < 0)
+ {
+ pathcd(fts->home, NiL);
+ fts->curdir = 0;
+ fts->cd = -1;
+ }
+ if (fts->todo)
+ {
+ if (*fts->base)
+ fts->base += f->fts_namelen;
+ if (*(fts->base - 1) != '/')
+ *fts->base++ = '/';
+ *fts->base = 0;
+ f = fts->todo;
+ fts->state = FTS_todo;
+ continue;
+ }
+ return 0;
+
+ case FTS_children_return:
+
+ f = fts->current;
+ f->fts_link = fts->link;
+
+ /*
+ * chdir down again
+ */
+
+ i = f->fts_info != FTS_DNX;
+ n = f->status == FTS_SKIP;
+ if (!n && fts->cd == 0)
+ {
+ if ((fts->cd = chdir(fts->base)) < 0)
+ pathcd(fts->home, NiL);
+ else if (fts->pwd != f)
+ {
+ f->pwd = fts->pwd;
+ fts->pwd = f;
+ }
+ fts->curdir = fts->cd ? 0 : f;
+ }
+
+ /*
+ * prune
+ */
+
+ if (fts->base[fts->baselen - 1] != '/')
+ fts->base[fts->baselen] = '/';
+ for (fts->bot = 0, f = fts->top; f; )
+ if (n || f->status == FTS_SKIP)
+ {
+ if (fts->bot)
+ fts->bot->fts_link = f->fts_link;
+ else
+ fts->top = f->fts_link;
+ drop(fts, f);
+ f = fts->bot ? fts->bot->fts_link : fts->top;
+ }
+ else
+ {
+ if (fts->children > 1 && i)
+ {
+ if (f->status == FTS_STAT)
+ info(fts, f, NiL, f->fts_statp, 0);
+ else if (f->fts_info == FTS_NSOK && !SKIP(fts, f))
+ {
+ s = f->fts_name;
+ if (fts->cd)
+ {
+ memcpy(fts->endbase, s, f->fts_namelen + 1);
+ s = fts->path;
+ }
+ info(fts, f, s, f->fts_statp, fts->flags);
+ }
+ }
+ fts->bot = f;
+ f = f->fts_link;
+ }
+ fts->children = 0;
+ fts->state = FTS_children_resume;
+ continue;
+
+ case FTS_popstack_return:
+
+ f = fts->todo;
+ f->fts_link = fts->link;
+ f->fts_info = f->status == FTS_AGAIN ? FTS_DP : 0;
+ fts->state = FTS_popstack_resume;
+ continue;
+
+ case FTS_preorder_return:
+
+ f = fts->current;
+ f->fts_link = fts->link;
+
+ /*
+ * follow symlink if asked to
+ */
+
+ if (f->status == FTS_FOLLOW)
+ {
+ f->status = 0;
+ if (f->fts_info == FTS_SL || ISTYPE(f, DT_LNK) || f->fts_info == FTS_NSOK)
+ {
+ info(fts, f, f->fts_accpath, f->fts_statp, 0);
+ if (f->fts_info != FTS_SL)
+ {
+ fts->state = FTS_preorder;
+ continue;
+ }
+ }
+ }
+
+ /*
+ * about to prune this f and already at home
+ */
+
+ if (fts->cd == 0 && f->fts_level == 0 && f->nd)
+ fts->cd = -1;
+ fts->state = FTS_preorder_resume;
+ continue;
+
+ case FTS_terminal:
+
+ f = fts->current;
+ if (f->status == FTS_FOLLOW)
+ {
+ f->status = 0;
+ if (f->fts_info == FTS_SL || ISTYPE(f, DT_LNK) || f->fts_info == FTS_NSOK)
+ {
+ info(fts, f, f->fts_accpath, f->fts_statp, 0);
+ if (f->symlink && f->fts_info != FTS_SL)
+ {
+ if (!(f->fts_link = fts->top))
+ fts->bot = f;
+ fts->top = f;
+ fts->current = fts->previous;
+ fts->state = FTS_readdir;
+ continue;
+ }
+ }
+ }
+ f = f->fts_parent;
+ drop(fts, fts->current);
+ fts->current = f;
+ fts->state = FTS_readdir;
+ continue;
+
+ case FTS_error:
+
+ return 0;
+
+ default:
+
+ fts->fts_errno = EINVAL;
+ fts->state = FTS_error;
+ return 0;
+
+ }
+ note:
+#if __OBSOLETE__ < 20140101
+ f->_fts_pathlen = (unsigned short)f->fts_pathlen;
+#endif
+ for (p = notify; p; p = p->next)
+ if ((n = (*p->notifyf)(fts, f, p->context)) > 0)
+ break;
+ else if (n < 0)
+ {
+ fts->fts_errno = EINVAL;
+ fts->state = FTS_error;
+ return 0;
+ }
+ return f;
+}
+
+/*
+ * set stream or entry flags
+ */
+
+int
+fts_set(register FTS* fts, register FTSENT* f, int status)
+{
+ if (fts || !f || f->fts->current != f)
+ return -1;
+ switch (status)
+ {
+ case FTS_AGAIN:
+ break;
+ case FTS_FOLLOW:
+ if (!(f->fts_info & FTS_SL))
+ return -1;
+ break;
+ case FTS_NOPOSTORDER:
+ break;
+ case FTS_SKIP:
+ if ((f->fts_info & (FTS_D|FTS_P)) != FTS_D)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ f->status = status;
+ return 0;
+}
+
+/*
+ * return the list of child entries
+ */
+
+FTSENT*
+fts_children(register FTS* fts, int flags)
+{
+ register FTSENT* f;
+
+ switch (fts->state)
+ {
+
+ case 0:
+
+ if (fts->comparf)
+ order(fts);
+ fts->state = FTS_top_return;
+ return fts->todo;
+
+ case FTS_preorder_return:
+
+ fts->children = ((flags | fts->flags) & FTS_NOSTAT) ? 2 : 1;
+ if (f = fts_read(fts))
+ f = f->fts_link;
+ return f;
+
+ }
+ return 0;
+}
+
+/*
+ * return default (FTS_LOGICAL|FTS_META|FTS_PHYSICAL|FTS_SEEDOTDIR) flags
+ * conditioned by astconf()
+ */
+
+int
+fts_flags(void)
+{
+ register char* s;
+
+ s = astconf("PATH_RESOLVE", NiL, NiL);
+ if (streq(s, "logical"))
+ return FTS_LOGICAL;
+ if (streq(s, "physical"))
+ return FTS_PHYSICAL|FTS_SEEDOTDIR;
+ return FTS_META|FTS_PHYSICAL|FTS_SEEDOTDIR;
+}
+
+/*
+ * return 1 if ent is mounted on a local filesystem
+ */
+
+int
+fts_local(FTSENT* ent)
+{
+#ifdef ST_LOCAL
+ struct statvfs fs;
+
+ return statvfs(ent->fts_path, &fs) || (fs.f_flag & ST_LOCAL);
+#else
+ return !strgrpmatch(fmtfs(ent->fts_statp), "([an]fs|samb)", NiL, 0, STR_LEFT|STR_ICASE);
+#endif
+}
+
+/*
+ * close an open fts stream
+ */
+
+int
+fts_close(register FTS* fts)
+{
+ register FTSENT* f;
+ register FTSENT* x;
+
+ if (fts->dir)
+ closedir(fts->dir);
+ if (fts->cd == 0)
+ pathcd(fts->home, NiL);
+ free(fts->home);
+ if (fts->state == FTS_children_return)
+ fts->current->fts_link = fts->link;
+ if (fts->top)
+ {
+ fts->bot->fts_link = fts->todo;
+ fts->todo = fts->top;
+ }
+ for (f = fts->todo; f; f = x)
+ {
+ x = f->fts_link;
+ free(f);
+ }
+ for (f = fts->free; f; f = x)
+ {
+ x = f->fts_link;
+ free(f);
+ }
+ free(fts);
+ return 0;
+}
+
+/*
+ * register function to be called for each fts_read() entry
+ * context==0 => unregister notifyf
+ */
+
+int
+fts_notify(Notify_f notifyf, void* context)
+{
+ register Notify_t* np;
+ register Notify_t* pp;
+
+ if (context)
+ {
+ if (!(np = newof(0, Notify_t, 1, 0)))
+ return -1;
+ np->notifyf = notifyf;
+ np->context = context;
+ np->next = notify;
+ notify = np;
+ }
+ else
+ {
+ for (np = notify, pp = 0; np; pp = np, np = np->next)
+ if (np->notifyf == notifyf)
+ {
+ if (pp)
+ pp->next = np->next;
+ else
+ notify = np->next;
+ free(np);
+ return 0;
+ }
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/lib/libast/misc/ftwalk.c b/src/lib/libast/misc/ftwalk.c
new file mode 100644
index 0000000..30c293f
--- /dev/null
+++ b/src/lib/libast/misc/ftwalk.c
@@ -0,0 +1,156 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * ftwalk on top of fts
+ */
+
+#include <ast.h>
+#include <ftwalk.h>
+
+static struct
+{
+ int (*comparf)(Ftw_t*, Ftw_t*);
+} state;
+
+/*
+ * why does fts take FTSENT** instead of FTSENT*
+ */
+
+static int
+ftscompare(Ftw_t* const* pf1, Ftw_t* const* pf2)
+{
+ return (*state.comparf)(*pf1, *pf2);
+}
+
+/*
+ * the real thing -- well it used to be
+ */
+
+int
+ftwalk(const char* path, int (*userf)(Ftw_t*), int flags, int (*comparf)(Ftw_t*, Ftw_t*))
+{
+ register FTS* f;
+ register FTSENT* e;
+ register int children;
+ register int rv;
+ int oi;
+ int ns;
+ int os;
+ int nd;
+ FTSENT* x;
+ FTSENT* dd[2];
+
+ flags ^= FTS_ONEPATH;
+ if (flags & FTW_TWICE)
+ flags &= ~(FTS_NOPREORDER|FTS_NOPOSTORDER);
+ else if (flags & FTW_POST)
+ flags |= FTS_NOPREORDER;
+ else
+ flags |= FTS_NOPOSTORDER;
+ if (children = flags & FTW_CHILDREN)
+ flags |= FTS_SEEDOT;
+ state.comparf = comparf;
+ if (!(f = fts_open((char* const*)path, flags, comparf ? ftscompare : 0)))
+ {
+ if (!path || !(flags & FTS_ONEPATH) && !(path = (const char*)(*((char**)path))))
+ return -1;
+ ns = strlen(path) + 1;
+ if (!(e = newof(0, FTSENT, 1, ns)))
+ return -1;
+ e->fts_accpath = e->fts_name = e->fts_path = strcpy((char*)(e + 1), path);
+ e->fts_namelen = e->fts_pathlen = ns;
+ e->fts_info = FTS_NS;
+ e->parent = e;
+ e->parent->link = e;
+ rv = (*userf)((Ftw_t*)e);
+ free(e);
+ return rv;
+ }
+ rv = 0;
+ if (children && (e = fts_children(f, 0)))
+ {
+ nd = 0;
+ for (x = e; x; x = x->link)
+ if (x->info & FTS_DD)
+ {
+ x->statb = *x->fts_statp;
+ x->info &= ~FTS_DD;
+ dd[nd++] = x;
+ if (nd >= elementsof(dd))
+ break;
+ }
+ e->parent->link = e;
+ rv = (*userf)((Ftw_t*)e->parent);
+ e->parent->link = 0;
+ while (nd > 0)
+ dd[--nd]->info |= FTS_DD;
+ for (x = e; x; x = x->link)
+ if (!(x->info & FTS_D))
+ x->status = FTS_SKIP;
+ }
+ while (!rv && (e = fts_read(f)))
+ {
+ oi = e->info;
+ os = e->status;
+ ns = e->status = e->path == e->fts_accpath ? FTW_PATH : FTW_NAME;
+ nd = 0;
+ switch (e->info)
+ {
+ case FTS_D:
+ case FTS_DNX:
+ if (children)
+ for (x = fts_children(f, 0); x; x = x->link)
+ if (x->info & FTS_DD)
+ {
+ x->statb = *x->fts_statp;
+ x->info &= ~FTS_DD;
+ dd[nd++] = x;
+ if (nd >= elementsof(dd))
+ break;
+ }
+ break;
+ case FTS_DOT:
+ continue;
+ case FTS_ERR:
+ e->info = FTS_NS;
+ break;
+ case FTS_NSOK:
+ e->info = FTS_NSOK;
+ break;
+ case FTS_SLNONE:
+ e->info = FTS_SL;
+ break;
+ }
+ rv = (*userf)((Ftw_t*)e);
+ e->info = oi;
+ if (e->status == ns)
+ e->status = os;
+ while (nd > 0)
+ dd[--nd]->info |= FTS_DD;
+ }
+ fts_close(f);
+ return rv;
+}
diff --git a/src/lib/libast/misc/ftwflags.c b/src/lib/libast/misc/ftwflags.c
new file mode 100644
index 0000000..179a366
--- /dev/null
+++ b/src/lib/libast/misc/ftwflags.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * return default FTW_* flags conditioned by astconf()
+ */
+
+#include <ast.h>
+#include <ftwalk.h>
+
+int
+ftwflags(void)
+{
+ return fts_flags();
+}
diff --git a/src/lib/libast/misc/getcwd.c b/src/lib/libast/misc/getcwd.c
new file mode 100644
index 0000000..c509648
--- /dev/null
+++ b/src/lib/libast/misc/getcwd.c
@@ -0,0 +1,334 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * pwd library support
+ */
+
+#include <ast.h>
+
+#if _WINIX
+
+NoN(getcwd)
+
+#else
+
+#include "FEATURE/syscall"
+
+#if defined(SYSGETCWD)
+
+#include <error.h>
+
+#define ERROR(e) { errno = e; return 0; }
+
+char*
+getcwd(char* buf, size_t len)
+{
+ size_t n;
+ size_t r;
+ int oerrno;
+
+ if (buf)
+ return SYSGETCWD(buf, len) < 0 ? 0 : buf;
+ oerrno = errno;
+ n = PATH_MAX;
+ for (;;)
+ {
+ if (!(buf = newof(buf, char, n, 0)))
+ ERROR(ENOMEM);
+ if (SYSGETCWD(buf, n) >= 0)
+ {
+ if ((r = strlen(buf) + len + 1) != n && !(buf = newof(buf, char, r, 0)))
+ ERROR(ENOMEM);
+ break;
+ }
+ if (errno != ERANGE)
+ {
+ free(buf);
+ return 0;
+ }
+ n += PATH_MAX / 4;
+ }
+ errno = oerrno;
+ return buf;
+}
+
+#else
+
+#include <ast_dir.h>
+#include <error.h>
+#include <fs3d.h>
+
+#ifndef ERANGE
+#define ERANGE E2BIG
+#endif
+
+#define ERROR(e) { errno = e; goto error; }
+
+struct dirlist /* long path chdir(2) component */
+{
+ struct dirlist* next; /* next component */
+ int index; /* index from end of buf */
+};
+
+/*
+ * pop long dir component chdir stack
+ */
+
+static int
+popdir(register struct dirlist* d, register char* end)
+{
+ register struct dirlist* dp;
+ int v;
+
+ v = 0;
+ while (dp = d)
+ {
+ d = d->next;
+ if (!v)
+ {
+ if (d) *(end - d->index - 1) = 0;
+ v = chdir(end - dp->index);
+ if (d) *(end - d->index - 1) = '/';
+ }
+ free(dp);
+ }
+ return v;
+}
+
+/*
+ * push long dir component onto stack
+ */
+
+static struct dirlist*
+pushdir(register struct dirlist* d, char* dots, char* path, char* end)
+{
+ register struct dirlist* p;
+
+ if (!(p = newof(0, struct dirlist, 1, 0)) || chdir(dots))
+ {
+ if (p) free(p);
+ if (d) popdir(d, end);
+ return 0;
+ }
+ p->index = end - path;
+ p->next = d;
+ return p;
+}
+
+/*
+ * return a pointer to the absolute path name of .
+ * this path name may be longer than PATH_MAX
+ *
+ * a few environment variables are checked before the search algorithm
+ * return value is placed in buf of len chars
+ * if buf is 0 then space is allocated via malloc() with
+ * len extra chars after the path name
+ * 0 is returned on error with errno set as appropriate
+ */
+
+char*
+getcwd(char* buf, size_t len)
+{
+ register char* d;
+ register char* p;
+ register char* s;
+ DIR* dirp = 0;
+ int n;
+ int x;
+ size_t namlen;
+ ssize_t extra = -1;
+ struct dirent* entry;
+ struct dirlist* dirstk = 0;
+ struct stat* cur;
+ struct stat* par;
+ struct stat* tmp;
+ struct stat curst;
+ struct stat parst;
+ struct stat tstst;
+ char dots[PATH_MAX];
+
+ static struct
+ {
+ char* name;
+ char* path;
+ dev_t dev;
+ ino_t ino;
+ } env[] =
+ {
+ { /*previous*/0 },
+ { "PWD" },
+ { "HOME" },
+ };
+
+ if (buf && !len) ERROR(EINVAL);
+ if (fs3d(FS3D_TEST) && (namlen = mount(".", dots, FS3D_GET|FS3D_VIEW|FS3D_SIZE(sizeof(dots)), NiL)) > 1 && namlen < sizeof(dots))
+ {
+ p = dots;
+ easy:
+ namlen++;
+ if (buf)
+ {
+ if (len < namlen) ERROR(ERANGE);
+ }
+ else if (!(buf = newof(0, char, namlen, len))) ERROR(ENOMEM);
+ return (char*)memcpy(buf, p, namlen);
+ }
+ cur = &curst;
+ par = &parst;
+ if (stat(".", par)) ERROR(errno);
+ for (n = 0; n < elementsof(env); n++)
+ {
+ if ((env[n].name && (p = getenv(env[n].name)) || (p = env[n].path)) && *p == '/' && !stat(p, cur))
+ {
+ env[n].path = p;
+ env[n].dev = cur->st_dev;
+ env[n].ino = cur->st_ino;
+ if (cur->st_ino == par->st_ino && cur->st_dev == par->st_dev)
+ {
+ namlen = strlen(p);
+ goto easy;
+ }
+ }
+ }
+ if (!buf)
+ {
+ extra = len;
+ len = PATH_MAX;
+ if (!(buf = newof(0, char, len, extra))) ERROR(ENOMEM);
+ }
+ d = dots;
+ p = buf + len - 1;
+ *p = 0;
+ n = elementsof(env);
+ for (;;)
+ {
+ tmp = cur;
+ cur = par;
+ par = tmp;
+ if ((d - dots) > (PATH_MAX - 4))
+ {
+ if (!(dirstk = pushdir(dirstk, dots, p, buf + len - 1))) ERROR(ERANGE);
+ d = dots;
+ }
+ *d++ = '.';
+ *d++ = '.';
+ *d = 0;
+ if (!(dirp = opendir(dots))) ERROR(errno);
+#if !_dir_ok || _mem_dd_fd_DIR
+ if (fstat(dirp->dd_fd, par)) ERROR(errno);
+#else
+ if (stat(dots, par)) ERROR(errno);
+#endif
+ *d++ = '/';
+ if (par->st_dev == cur->st_dev)
+ {
+ if (par->st_ino == cur->st_ino)
+ {
+ closedir(dirp);
+ *--p = '/';
+ pop:
+ if (p != buf)
+ {
+ d = buf;
+ while (*d++ = *p++);
+ len = d - buf;
+ if (extra >= 0 && !(buf = newof(buf, char, len, extra))) ERROR(ENOMEM);
+ }
+ if (dirstk && popdir(dirstk, buf + len - 1))
+ {
+ dirstk = 0;
+ ERROR(errno);
+ }
+ if (env[0].path)
+ free(env[0].path);
+ env[0].path = strdup(buf);
+ return buf;
+ }
+#ifdef D_FILENO
+ while (entry = readdir(dirp))
+ if (D_FILENO(entry) == cur->st_ino)
+ {
+ namlen = D_NAMLEN(entry);
+ goto found;
+ }
+#endif
+
+ /*
+ * this fallthrough handles logical naming
+ */
+
+ rewinddir(dirp);
+ }
+ do
+ {
+ if (!(entry = readdir(dirp))) ERROR(ENOENT);
+ namlen = D_NAMLEN(entry);
+ if ((d - dots) > (PATH_MAX - 1 - namlen))
+ {
+ *d = 0;
+ if (namlen >= PATH_MAX || !(dirstk = pushdir(dirstk, dots + 3, p, buf + len - 1))) ERROR(ERANGE);
+ d = dots + 3;
+ }
+ memcpy(d, entry->d_name, namlen + 1);
+ } while (stat(dots, &tstst) || tstst.st_ino != cur->st_ino || tstst.st_dev != cur->st_dev);
+ found:
+ if (*p) *--p = '/';
+ while ((p -= namlen) <= (buf + 1))
+ {
+ x = (buf + len - 1) - (p += namlen);
+ s = buf + len;
+ if (extra < 0 || !(buf = newof(buf, char, len += PATH_MAX, extra))) ERROR(ERANGE);
+ p = buf + len;
+ while (p > buf + len - 1 - x) *--p = *--s;
+ }
+ if (n < elementsof(env))
+ {
+ memcpy(p, env[n].path, namlen);
+ goto pop;
+ }
+ memcpy(p, entry->d_name, namlen);
+ closedir(dirp);
+ dirp = 0;
+ for (n = 0; n < elementsof(env); n++)
+ if (env[n].ino == par->st_ino && env[n].dev == par->st_dev)
+ {
+ namlen = strlen(env[n].path);
+ goto found;
+ }
+ }
+ error:
+ if (buf)
+ {
+ if (dirstk) popdir(dirstk, buf + len - 1);
+ if (extra >= 0) free(buf);
+ }
+ if (dirp) closedir(dirp);
+ return 0;
+}
+
+#endif
+
+#endif
diff --git a/src/lib/libast/misc/getenv.c b/src/lib/libast/misc/getenv.c
new file mode 100644
index 0000000..7e24817
--- /dev/null
+++ b/src/lib/libast/misc/getenv.c
@@ -0,0 +1,113 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#if _UWIN && __STDPP__
+__STDPP__directive pragma pp:hide getenv
+#endif
+
+#include "intercepts.h"
+
+#if _UWIN && __STDPP__
+__STDPP__directive pragma pp:nohide getenv
+#endif
+
+/*
+ * NOTE: the "intercepts" definition is here instead of astintercept.c because some
+ * static linkers miss lone references to "intercepts" without "astintercept()"
+ * ALSO: { 0 } definition required by some dynamic linkers averse to common symbols
+ * UWIN: no _ast_getenv macro map to maintain ast54 compatibility
+ */
+
+Intercepts_t intercepts
+#if _BLD_3d
+ ;
+#else
+ = { 0 };
+#endif
+
+#if _UWIN && !defined(getenv)
+
+#include <windows.h>
+
+extern char** environ;
+
+static char*
+default_getenv(const char* name)
+{
+ register char** av;
+ register const char* cp;
+ register const char* sp;
+ register char c0;
+ register char c1;
+
+ av = environ;
+ if (!av || !name || !(c0 = *name))
+ return 0;
+ if (!(c1 = *++name))
+ c1 = '=';
+ while (cp = *av++)
+ {
+ if (cp[0] != c0 || cp[1] != c1)
+ continue;
+ sp = name;
+ cp++;
+ while (*sp && *sp++ == *cp++);
+ if (*(sp-1) != *(cp-1))
+ continue;
+ if (*sp == 0 && *cp == '=')
+ return (char*)(cp+1);
+ }
+ return 0;
+}
+
+#endif
+
+/*
+ * get name from the environment
+ */
+
+#if defined(__EXPORT__) && defined(getenv)
+#define extern __EXPORT__
+#endif
+
+extern char*
+getenv(const char* name)
+{
+#if _UWIN && !defined(getenv) /* for ast54 compatibility */
+ HANDLE dll;
+
+ static char* (*posix_getenv)(const char*);
+
+ if (!posix_getenv)
+ {
+ if (dll = GetModuleHandle("posix.dll"))
+ posix_getenv = (char*(*)(const char*))GetProcAddress(dll, "getenv");
+ if (!posix_getenv)
+ posix_getenv = default_getenv;
+ }
+ return intercepts.intercept_getenv ? (*intercepts.intercept_getenv)(name) : (*posix_getenv)(name);
+#else
+#undef getenv
+ return intercepts.intercept_getenv ? (*intercepts.intercept_getenv)(name) : getenv(name);
+#endif
+}
diff --git a/src/lib/libast/misc/glob.c b/src/lib/libast/misc/glob.c
new file mode 100644
index 0000000..f05b40e
--- /dev/null
+++ b/src/lib/libast/misc/glob.c
@@ -0,0 +1,829 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * file name expansion - posix.2 glob with gnu and ast extensions
+ *
+ * David Korn
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include <ast.h>
+#include <ls.h>
+#include <stak.h>
+#include <ast_dir.h>
+#include <error.h>
+#include <ctype.h>
+#include <regex.h>
+
+#define GLOB_MAGIC 0xaaaa0000
+
+#define MATCH_RAW 1
+#define MATCH_MAKE 2
+#define MATCH_META 4
+
+#define MATCHPATH(g) (offsetof(globlist_t,gl_path)+(g)->gl_extra)
+
+typedef int (*GL_error_f)(const char*, int);
+typedef void* (*GL_opendir_f)(const char*);
+typedef struct dirent* (*GL_readdir_f)(void*);
+typedef void (*GL_closedir_f)(void*);
+typedef int (*GL_stat_f)(const char*, struct stat*);
+
+#define _GLOB_PRIVATE_ \
+ GL_error_f gl_errfn; \
+ int gl_error; \
+ char* gl_nextpath; \
+ globlist_t* gl_rescan; \
+ globlist_t* gl_match; \
+ Stak_t* gl_stak; \
+ int re_flags; \
+ int re_first; \
+ regex_t* gl_ignore; \
+ regex_t* gl_ignorei; \
+ regex_t re_ignore; \
+ regex_t re_ignorei; \
+ unsigned long gl_starstar; \
+ char* gl_opt; \
+ char* gl_pat; \
+ char* gl_pad[4];
+
+#include <glob.h>
+
+/*
+ * default gl_diropen
+ */
+
+static void*
+gl_diropen(glob_t* gp, const char* path)
+{
+ return (*gp->gl_opendir)(path);
+}
+
+/*
+ * default gl_dirnext
+ */
+
+static char*
+gl_dirnext(glob_t* gp, void* handle)
+{
+ struct dirent* dp;
+
+ while (dp = (struct dirent*)(*gp->gl_readdir)(handle))
+ {
+#ifdef D_TYPE
+ if (D_TYPE(dp) != DT_UNKNOWN && D_TYPE(dp) != DT_DIR && D_TYPE(dp) != DT_LNK)
+ gp->gl_status |= GLOB_NOTDIR;
+#endif
+ return dp->d_name;
+ }
+ return 0;
+}
+
+/*
+ * default gl_dirclose
+ */
+
+static void
+gl_dirclose(glob_t* gp, void* handle)
+{
+ (gp->gl_closedir)(handle);
+}
+
+/*
+ * default gl_type
+ */
+
+static int
+gl_type(glob_t* gp, const char* path, int flags)
+{
+ register int type;
+ struct stat st;
+
+ if ((flags & GLOB_STARSTAR) ? (*gp->gl_lstat)(path, &st) : (*gp->gl_stat)(path, &st))
+ type = 0;
+ else if (S_ISDIR(st.st_mode))
+ type = GLOB_DIR;
+ else if (!S_ISREG(st.st_mode))
+ type = GLOB_DEV;
+ else if (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
+ type = GLOB_EXE;
+ else
+ type = GLOB_REG;
+ return type;
+}
+
+/*
+ * default gl_attr
+ */
+
+static int
+gl_attr(glob_t* gp, const char* path, int flags)
+{
+ return strchr(astconf("PATH_ATTRIBUTES", path, NiL), 'c') ? GLOB_ICASE : 0;
+}
+
+/*
+ * default gl_nextdir
+ */
+
+static char*
+gl_nextdir(glob_t* gp, char* dir)
+{
+ if (!(dir = gp->gl_nextpath))
+ dir = gp->gl_nextpath = stakcopy(pathbin());
+ switch (*gp->gl_nextpath)
+ {
+ case 0:
+ dir = 0;
+ break;
+ case ':':
+ while (*gp->gl_nextpath == ':')
+ gp->gl_nextpath++;
+ dir = ".";
+ break;
+ default:
+ while (*gp->gl_nextpath)
+ if (*gp->gl_nextpath++ == ':')
+ {
+ *(gp->gl_nextpath - 1) = 0;
+ break;
+ }
+ break;
+ }
+ return dir;
+}
+
+/*
+ * error intercept
+ */
+
+static int
+errorcheck(register glob_t* gp, const char* path)
+{
+ int r = 1;
+
+ if (gp->gl_errfn)
+ r = (*gp->gl_errfn)(path, errno);
+ if (gp->gl_flags & GLOB_ERR)
+ r = 0;
+ if (!r)
+ gp->gl_error = GLOB_ABORTED;
+ return r;
+}
+
+/*
+ * remove backslashes
+ */
+
+static void
+trim(register char* sp, register char* p1, int* n1, register char* p2, int* n2)
+{
+ register char* dp = sp;
+ register int c;
+
+ if (p1)
+ *n1 = 0;
+ if (p2)
+ *n2 = 0;
+ do
+ {
+ if ((c = *sp++) == '\\')
+ c = *sp++;
+ if (sp == p1)
+ {
+ p1 = 0;
+ *n1 = sp - dp - 1;
+ }
+ if (sp == p2)
+ {
+ p2 = 0;
+ *n2 = sp - dp - 1;
+ }
+ } while (*dp++ = c);
+}
+
+static void
+addmatch(register glob_t* gp, const char* dir, const char* pat, register const char* rescan, char* endslash, int meta)
+{
+ register globlist_t* ap;
+ int offset;
+ int type;
+
+ stakseek(MATCHPATH(gp));
+ if (dir)
+ {
+ stakputs(dir);
+ stakputc(gp->gl_delim);
+ }
+ if (endslash)
+ *endslash = 0;
+ stakputs(pat);
+ if (rescan)
+ {
+ if ((*gp->gl_type)(gp, stakptr(MATCHPATH(gp)), 0) != GLOB_DIR)
+ return;
+ stakputc(gp->gl_delim);
+ offset = staktell();
+ /* if null, reserve room for . */
+ if (*rescan)
+ stakputs(rescan);
+ else
+ stakputc(0);
+ stakputc(0);
+ rescan = stakptr(offset);
+ ap = (globlist_t*)stakfreeze(0);
+ ap->gl_begin = (char*)rescan;
+ ap->gl_next = gp->gl_rescan;
+ gp->gl_rescan = ap;
+ }
+ else
+ {
+ if (!endslash && (gp->gl_flags & GLOB_MARK) && (type = (*gp->gl_type)(gp, stakptr(MATCHPATH(gp)), 0)))
+ {
+ if ((gp->gl_flags & GLOB_COMPLETE) && type != GLOB_EXE)
+ {
+ stakseek(0);
+ return;
+ }
+ else if (type == GLOB_DIR && (gp->gl_flags & GLOB_MARK))
+ stakputc(gp->gl_delim);
+ }
+ ap = (globlist_t*)stakfreeze(1);
+ ap->gl_next = gp->gl_match;
+ gp->gl_match = ap;
+ gp->gl_pathc++;
+ }
+ ap->gl_flags = MATCH_RAW|meta;
+ if (gp->gl_flags & GLOB_COMPLETE)
+ ap->gl_flags |= MATCH_MAKE;
+}
+
+/*
+ * this routine builds a list of files that match a given pathname
+ * uses REG_SHELL of <regex> to match each component
+ * a leading . must match explicitly
+ */
+
+static void
+glob_dir(glob_t* gp, globlist_t* ap, int re_flags)
+{
+ register char* rescan;
+ register char* prefix;
+ register char* pat;
+ register char* name;
+ register int c;
+ char* dirname;
+ void* dirf;
+ char first;
+ regex_t* ire;
+ regex_t* pre;
+ regex_t rec;
+ regex_t rei;
+ int notdir;
+ int t1;
+ int t2;
+ int bracket;
+
+ int anymeta = ap->gl_flags & MATCH_META;
+ int complete = 0;
+ int err = 0;
+ int meta = ((gp->re_flags & REG_ICASE) && *ap->gl_begin != '/') ? MATCH_META : 0;
+ int quote = 0;
+ int savequote = 0;
+ char* restore1 = 0;
+ char* restore2 = 0;
+ regex_t* prec = 0;
+ regex_t* prei = 0;
+ char* matchdir = 0;
+ int starstar = 0;
+
+ if (*gp->gl_intr)
+ {
+ gp->gl_error = GLOB_INTR;
+ return;
+ }
+ pat = rescan = ap->gl_begin;
+ prefix = dirname = ap->gl_path + gp->gl_extra;
+ first = (rescan == prefix);
+again:
+ bracket = 0;
+ for (;;)
+ {
+ switch (c = *rescan++)
+ {
+ case 0:
+ if (meta)
+ {
+ rescan = 0;
+ break;
+ }
+ if (quote)
+ {
+ trim(ap->gl_begin, rescan, &t1, NiL, NiL);
+ rescan -= t1;
+ }
+ if (!first && !*rescan && *(rescan - 2) == gp->gl_delim)
+ {
+ *(rescan - 2) = 0;
+ c = (*gp->gl_type)(gp, prefix, 0);
+ *(rescan - 2) = gp->gl_delim;
+ if (c == GLOB_DIR)
+ addmatch(gp, NiL, prefix, NiL, rescan - 1, anymeta);
+ }
+ else if ((anymeta || !(gp->gl_flags & GLOB_NOCHECK)) && (*gp->gl_type)(gp, prefix, 0))
+ addmatch(gp, NiL, prefix, NiL, NiL, anymeta);
+ return;
+ case '[':
+ if (!bracket)
+ {
+ bracket = MATCH_META;
+ if (*rescan == '!' || *rescan == '^')
+ rescan++;
+ if (*rescan == ']')
+ rescan++;
+ }
+ continue;
+ case ']':
+ meta |= bracket;
+ continue;
+ case '(':
+ if (!(gp->gl_flags & GLOB_AUGMENTED))
+ continue;
+ case '*':
+ case '?':
+ meta = MATCH_META;
+ continue;
+ case '\\':
+ if (!(gp->gl_flags & GLOB_NOESCAPE))
+ {
+ quote = 1;
+ if (*rescan)
+ rescan++;
+ }
+ continue;
+ default:
+ if (c == gp->gl_delim)
+ {
+ if (meta)
+ break;
+ pat = rescan;
+ bracket = 0;
+ savequote = quote;
+ }
+ continue;
+ }
+ break;
+ }
+ anymeta |= meta;
+ if (matchdir)
+ goto skip;
+ if (pat == prefix)
+ {
+ prefix = 0;
+ if (!rescan && (gp->gl_flags & GLOB_COMPLETE))
+ {
+ complete = 1;
+ dirname = 0;
+ }
+ else
+ dirname = ".";
+ }
+ else
+ {
+ if (pat == prefix + 1)
+ dirname = "/";
+ if (savequote)
+ {
+ quote = 0;
+ trim(ap->gl_begin, pat, &t1, rescan, &t2);
+ pat -= t1;
+ if (rescan)
+ rescan -= t2;
+ }
+ *(restore1 = pat - 1) = 0;
+ }
+ if (!complete && (gp->gl_flags & GLOB_STARSTAR))
+ while (pat[0] == '*' && pat[1] == '*' && (pat[2] == '/' || pat[2]==0))
+ {
+ matchdir = pat;
+ if (pat[2])
+ {
+ pat += 3;
+ while (*pat=='/')
+ pat++;
+ if (*pat)
+ continue;
+ }
+ rescan = *pat?0:pat;
+ pat = "*";
+ goto skip;
+ }
+ if (matchdir)
+ {
+ rescan = pat;
+ goto again;
+ }
+skip:
+ if (rescan)
+ *(restore2 = rescan - 1) = 0;
+ if (rescan && !complete && (gp->gl_flags & GLOB_STARSTAR))
+ {
+ register char* p = rescan;
+
+ while (p[0] == '*' && p[1] == '*' && (p[2] == '/' || p[2]==0))
+ {
+ rescan = p;
+ if (starstar = (p[2]==0))
+ break;
+ p += 3;
+ while (*p=='/')
+ p++;
+ if (*p==0)
+ {
+ starstar = 2;
+ break;
+ }
+ }
+ }
+ if (matchdir)
+ gp->gl_starstar++;
+ if (gp->gl_opt)
+ pat = strcpy(gp->gl_opt, pat);
+ for (;;)
+ {
+ if (complete)
+ {
+ if (!(dirname = (*gp->gl_nextdir)(gp, dirname)))
+ break;
+ prefix = streq(dirname, ".") ? (char*)0 : dirname;
+ }
+ if ((!starstar && !gp->gl_starstar || (*gp->gl_type)(gp, dirname, GLOB_STARSTAR) == GLOB_DIR) && (dirf = (*gp->gl_diropen)(gp, dirname)))
+ {
+ if (!(gp->re_flags & REG_ICASE) && ((*gp->gl_attr)(gp, dirname, 0) & GLOB_ICASE))
+ {
+ if (!prei)
+ {
+ if (err = regcomp(&rei, pat, gp->re_flags|REG_ICASE))
+ break;
+ prei = &rei;
+ if (gp->re_first)
+ {
+ gp->re_first = 0;
+ gp->re_flags = regstat(prei)->re_flags & ~REG_ICASE;
+ }
+ }
+ pre = prei;
+ }
+ else
+ {
+ if (!prec)
+ {
+ if (err = regcomp(&rec, pat, gp->re_flags))
+ break;
+ prec = &rec;
+ if (gp->re_first)
+ {
+ gp->re_first = 0;
+ gp->re_flags = regstat(prec)->re_flags;
+ }
+ }
+ pre = prec;
+ }
+ if ((ire = gp->gl_ignore) && (gp->re_flags & REG_ICASE))
+ {
+ if (!gp->gl_ignorei)
+ {
+ if (regcomp(&gp->re_ignorei, gp->gl_fignore, re_flags|REG_ICASE))
+ {
+ gp->gl_error = GLOB_APPERR;
+ break;
+ }
+ gp->gl_ignorei = &gp->re_ignorei;
+ }
+ ire = gp->gl_ignorei;
+ }
+ if (restore2)
+ *restore2 = gp->gl_delim;
+ while ((name = (*gp->gl_dirnext)(gp, dirf)) && !*gp->gl_intr)
+ {
+ if (notdir = (gp->gl_status & GLOB_NOTDIR))
+ gp->gl_status &= ~GLOB_NOTDIR;
+ if (ire && !regexec(ire, name, 0, NiL, 0))
+ continue;
+ if (matchdir && (name[0] != '.' || name[1] && (name[1] != '.' || name[2])) && !notdir)
+ addmatch(gp, prefix, name, matchdir, NiL, anymeta);
+ if (!regexec(pre, name, 0, NiL, 0))
+ {
+ if (!rescan || !notdir)
+ addmatch(gp, prefix, name, rescan, NiL, anymeta);
+ if (starstar==1 || (starstar==2 && !notdir))
+ addmatch(gp, prefix, name, starstar==2?"":NiL, NiL, anymeta);
+ }
+ errno = 0;
+ }
+ (*gp->gl_dirclose)(gp, dirf);
+ if (err || errno && !errorcheck(gp, dirname))
+ break;
+ }
+ else if (!complete && !errorcheck(gp, dirname))
+ break;
+ if (!complete)
+ break;
+ if (*gp->gl_intr)
+ {
+ gp->gl_error = GLOB_INTR;
+ break;
+ }
+ }
+ if (restore1)
+ *restore1 = gp->gl_delim;
+ if (restore2)
+ *restore2 = gp->gl_delim;
+ if (prec)
+ regfree(prec);
+ if (prei)
+ regfree(prei);
+ if (err == REG_ESPACE)
+ gp->gl_error = GLOB_NOSPACE;
+}
+
+int
+glob(const char* pattern, int flags, int (*errfn)(const char*, int), register glob_t* gp)
+{
+ register globlist_t* ap;
+ register char* pat;
+ globlist_t* top;
+ Stak_t* oldstak;
+ char** argv;
+ char** av;
+ size_t skip;
+ unsigned long f;
+ int n;
+ int x;
+ int re_flags;
+
+ const char* nocheck = pattern;
+ int optlen = 0;
+ int suflen = 0;
+ int extra = 1;
+ unsigned char intr = 0;
+
+ gp->gl_rescan = 0;
+ gp->gl_error = 0;
+ gp->gl_errfn = errfn;
+ if (flags & GLOB_APPEND)
+ {
+ if ((gp->gl_flags |= GLOB_APPEND) ^ (flags|GLOB_MAGIC))
+ return GLOB_APPERR;
+ if (((gp->gl_flags & GLOB_STACK) == 0) == (gp->gl_stak == 0))
+ return GLOB_APPERR;
+ if (gp->gl_starstar > 1)
+ gp->gl_flags |= GLOB_STARSTAR;
+ else
+ gp->gl_starstar = 0;
+ }
+ else
+ {
+ gp->gl_flags = (flags&0xffff)|GLOB_MAGIC;
+ gp->re_flags = REG_SHELL|REG_NOSUB|REG_LEFT|REG_RIGHT|((flags&GLOB_AUGMENTED)?REG_AUGMENTED:0);
+ gp->gl_pathc = 0;
+ gp->gl_ignore = 0;
+ gp->gl_ignorei = 0;
+ gp->gl_starstar = 0;
+ if (!(flags & GLOB_DISC))
+ {
+ gp->gl_fignore = 0;
+ gp->gl_suffix = 0;
+ gp->gl_intr = 0;
+ gp->gl_delim = 0;
+ gp->gl_handle = 0;
+ gp->gl_diropen = 0;
+ gp->gl_dirnext = 0;
+ gp->gl_dirclose = 0;
+ gp->gl_type = 0;
+ gp->gl_attr = 0;
+ gp->gl_nextdir = 0;
+ gp->gl_stat = 0;
+ gp->gl_lstat = 0;
+ gp->gl_extra = 0;
+ }
+ if (!(flags & GLOB_ALTDIRFUNC))
+ {
+ gp->gl_opendir = (GL_opendir_f)opendir;
+ gp->gl_readdir = (GL_readdir_f)readdir;
+ gp->gl_closedir = (GL_closedir_f)closedir;
+ if (!gp->gl_stat)
+ gp->gl_stat = (GL_stat_f)pathstat;
+ }
+ if (!gp->gl_lstat)
+ gp->gl_lstat = (GL_stat_f)lstat;
+ if (!gp->gl_intr)
+ gp->gl_intr = &intr;
+ if (!gp->gl_delim)
+ gp->gl_delim = '/';
+ if (!gp->gl_diropen)
+ gp->gl_diropen = gl_diropen;
+ if (!gp->gl_dirnext)
+ gp->gl_dirnext = gl_dirnext;
+ if (!gp->gl_dirclose)
+ gp->gl_dirclose = gl_dirclose;
+ if (!gp->gl_type)
+ gp->gl_type = gl_type;
+ if (!gp->gl_attr)
+ gp->gl_attr = gl_attr;
+ if (flags & GLOB_GROUP)
+ gp->re_flags |= REG_SHELL_GROUP;
+ if (flags & GLOB_ICASE)
+ gp->re_flags |= REG_ICASE;
+ if (!gp->gl_fignore)
+ gp->re_flags |= REG_SHELL_DOT;
+ else if (*gp->gl_fignore)
+ {
+ if (regcomp(&gp->re_ignore, gp->gl_fignore, gp->re_flags))
+ return GLOB_APPERR;
+ gp->gl_ignore = &gp->re_ignore;
+ }
+ if (gp->gl_flags & GLOB_STACK)
+ gp->gl_stak = 0;
+ else if (!(gp->gl_stak = stakcreate(0)))
+ return GLOB_NOSPACE;
+ if ((gp->gl_flags & GLOB_COMPLETE) && !gp->gl_nextdir)
+ gp->gl_nextdir = gl_nextdir;
+ }
+ skip = gp->gl_pathc;
+ if (gp->gl_stak)
+ oldstak = stakinstall(gp->gl_stak, 0);
+ if (flags & GLOB_DOOFFS)
+ extra += gp->gl_offs;
+ if (gp->gl_suffix)
+ suflen = strlen(gp->gl_suffix);
+ if (*(pat = (char*)pattern) == '~' && *(pat + 1) == '(')
+ {
+ f = gp->gl_flags;
+ n = 1;
+ x = 1;
+ pat += 2;
+ for (;;)
+ {
+ switch (*pat++)
+ {
+ case 0:
+ case ':':
+ break;
+ case '-':
+ n = 0;
+ continue;
+ case '+':
+ n = 1;
+ continue;
+ case 'i':
+ if (n)
+ f |= GLOB_ICASE;
+ else
+ f &= ~GLOB_ICASE;
+ continue;
+ case 'M':
+ if (n)
+ f |= GLOB_BRACE;
+ else
+ f &= ~GLOB_BRACE;
+ continue;
+ case 'N':
+ if (n)
+ f &= ~GLOB_NOCHECK;
+ else
+ f |= GLOB_NOCHECK;
+ continue;
+ case 'O':
+ if (n)
+ f |= GLOB_STARSTAR;
+ else
+ f &= ~GLOB_STARSTAR;
+ continue;
+ case ')':
+ flags = (gp->gl_flags = f) & 0xffff;
+ if (f & GLOB_ICASE)
+ gp->re_flags |= REG_ICASE;
+ else
+ gp->re_flags &= ~REG_ICASE;
+ if (x)
+ optlen = pat - (char*)pattern;
+ break;
+ default:
+ x = 0;
+ continue;
+ }
+ break;
+ }
+ }
+ top = ap = (globlist_t*)stakalloc((optlen ? 2 : 1) * strlen(pattern) + sizeof(globlist_t) + suflen + gp->gl_extra);
+ ap->gl_next = 0;
+ ap->gl_flags = 0;
+ ap->gl_begin = ap->gl_path + gp->gl_extra;
+ pat = strcopy(ap->gl_begin, pattern + optlen);
+ if (suflen)
+ pat = strcopy(pat, gp->gl_suffix);
+ if (optlen)
+ strlcpy(gp->gl_pat = gp->gl_opt = pat + 1, pattern, optlen);
+ else
+ gp->gl_pat = 0;
+ suflen = 0;
+ if (!(flags & GLOB_LIST))
+ gp->gl_match = 0;
+ re_flags = gp->re_flags;
+ gp->re_first = 1;
+ do
+ {
+ gp->gl_rescan = ap->gl_next;
+ glob_dir(gp, ap, re_flags);
+ } while (!gp->gl_error && (ap = gp->gl_rescan));
+ gp->re_flags = re_flags;
+ if (gp->gl_pathc == skip)
+ {
+ if (flags & GLOB_NOCHECK)
+ {
+ gp->gl_pathc++;
+ top->gl_next = gp->gl_match;
+ gp->gl_match = top;
+ strcopy(top->gl_path + gp->gl_extra, nocheck);
+ }
+ else
+ gp->gl_error = GLOB_NOMATCH;
+ }
+ if (flags & GLOB_LIST)
+ gp->gl_list = gp->gl_match;
+ else
+ {
+ argv = (char**)stakalloc((gp->gl_pathc + extra) * sizeof(char*));
+ if (gp->gl_flags & GLOB_APPEND)
+ {
+ skip += --extra;
+ memcpy(argv, gp->gl_pathv, skip * sizeof(char*));
+ av = argv + skip;
+ }
+ else
+ {
+ av = argv;
+ while (--extra > 0)
+ *av++ = 0;
+ }
+ gp->gl_pathv = argv;
+ argv = av;
+ ap = gp->gl_match;
+ while (ap)
+ {
+ *argv++ = ap->gl_path + gp->gl_extra;
+ ap = ap->gl_next;
+ }
+ *argv = 0;
+ if (!(flags & GLOB_NOSORT) && (argv - av) > 1)
+ {
+ strsort(av, argv - av, strcoll);
+ if (gp->gl_starstar > 1)
+ av[gp->gl_pathc = struniq(av, argv - av)] = 0;
+ gp->gl_starstar = 0;
+ }
+ }
+ if (gp->gl_starstar > 1)
+ gp->gl_flags &= ~GLOB_STARSTAR;
+ if (gp->gl_stak)
+ stakinstall(oldstak, 0);
+ return gp->gl_error;
+}
+
+void
+globfree(glob_t* gp)
+{
+ if ((gp->gl_flags & GLOB_MAGIC) == GLOB_MAGIC)
+ {
+ gp->gl_flags &= ~GLOB_MAGIC;
+ if (gp->gl_stak)
+ stkclose(gp->gl_stak);
+ if (gp->gl_ignore)
+ regfree(gp->gl_ignore);
+ if (gp->gl_ignorei)
+ regfree(gp->gl_ignorei);
+ }
+}
diff --git a/src/lib/libast/misc/intercepts.h b/src/lib/libast/misc/intercepts.h
new file mode 100644
index 0000000..15959ea
--- /dev/null
+++ b/src/lib/libast/misc/intercepts.h
@@ -0,0 +1,40 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _INTERCEPTS_H
+#define _INTERCEPTS_H 1
+
+#include <ast.h>
+#include <shcmd.h>
+
+typedef struct Intercepts_s
+{
+ char* (*intercept_getenv)(const char*);
+ char* (*intercept_setenviron)(const char*);
+} Intercepts_t;
+
+#define intercepts _ast_intercepts
+
+extern Intercepts_t intercepts;
+
+#endif
diff --git a/src/lib/libast/misc/magic.c b/src/lib/libast/misc/magic.c
new file mode 100644
index 0000000..aa2706e
--- /dev/null
+++ b/src/lib/libast/misc/magic.c
@@ -0,0 +1,2497 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * library interface to file
+ *
+ * the sum of the hacks {s5,v10,planix} is _____ than the parts
+ */
+
+static const char id[] = "\n@(#)$Id: magic library (AT&T Research) 2011-03-09 $\0\n";
+
+static const char lib[] = "libast:magic";
+
+#include <ast.h>
+#include <ctype.h>
+#include <ccode.h>
+#include <dt.h>
+#include <modex.h>
+#include <error.h>
+#include <regex.h>
+#include <swap.h>
+
+#define T(m) (*m?ERROR_translate(NiL,NiL,lib,m):m)
+
+#define match(s,p) strgrpmatch(s,p,NiL,0,STR_LEFT|STR_RIGHT|STR_ICASE)
+
+#define MAXNEST 10 /* { ... } nesting limit */
+#define MINITEM 4 /* magic buffer rounding */
+
+typedef struct /* identifier dictionary entry */
+{
+ const char name[16]; /* identifier name */
+ int value; /* identifier value */
+ Dtlink_t link; /* dictionary link */
+} Info_t;
+
+typedef struct Edit /* edit substitution */
+{
+ struct Edit* next; /* next in list */
+ regex_t* from; /* from pattern */
+} Edit_t;
+
+struct Entry;
+
+typedef struct /* loop info */
+{
+ struct Entry* lab; /* call this function */
+ int start; /* start here */
+ int size; /* increment by this amount */
+ int count; /* dynamic loop count */
+ int offset; /* dynamic offset */
+} Loop_t;
+
+typedef struct Entry /* magic file entry */
+{
+ struct Entry* next; /* next in list */
+ char* expr; /* offset expression */
+ union
+ {
+ unsigned long num;
+ char* str;
+ struct Entry* lab;
+ regex_t* sub;
+ Loop_t* loop;
+ } value; /* comparison value */
+ char* desc; /* file description */
+ char* mime; /* file mime type */
+ unsigned long offset; /* offset in bytes */
+ unsigned long mask; /* mask before compare */
+ char cont; /* continuation operation */
+ char type; /* datum type */
+ char op; /* comparison operation */
+ char nest; /* { or } nesting operation */
+ char swap; /* forced swap order */
+} Entry_t;
+
+#define CC_BIT 5
+
+#if (CC_MAPS*CC_BIT) <= (CHAR_BIT*2)
+typedef unsigned short Cctype_t;
+#else
+typedef unsigned long Cctype_t;
+#endif
+
+#define CC_text 0x01
+#define CC_control 0x02
+#define CC_latin 0x04
+#define CC_binary 0x08
+#define CC_utf_8 0x10
+
+#define CC_notext CC_text /* CC_text is flipped before checking */
+
+#define CC_MASK (CC_binary|CC_latin|CC_control|CC_text)
+
+#define CCTYPE(c) (((c)>0240)?CC_binary:((c)>=0200)?CC_latin:((c)<040&&(c)!=007&&(c)!=011&&(c)!=012&&(c)!=013&&(c)!=015)?CC_control:CC_text)
+
+#define ID_NONE 0
+#define ID_ASM 1
+#define ID_C 2
+#define ID_COBOL 3
+#define ID_COPYBOOK 4
+#define ID_CPLUSPLUS 5
+#define ID_FORTRAN 6
+#define ID_HTML 7
+#define ID_INCL1 8
+#define ID_INCL2 9
+#define ID_INCL3 10
+#define ID_MAM1 11
+#define ID_MAM2 12
+#define ID_MAM3 13
+#define ID_NOTEXT 14
+#define ID_PL1 15
+#define ID_YACC 16
+
+#define ID_MAX ID_YACC
+
+#define INFO_atime 1
+#define INFO_blocks 2
+#define INFO_ctime 3
+#define INFO_fstype 4
+#define INFO_gid 5
+#define INFO_mode 6
+#define INFO_mtime 7
+#define INFO_name 8
+#define INFO_nlink 9
+#define INFO_size 10
+#define INFO_uid 11
+
+#define _MAGIC_PRIVATE_ \
+ Magicdisc_t* disc; /* discipline */ \
+ Vmalloc_t* vm; /* vmalloc region */ \
+ Entry_t* magic; /* parsed magic table */ \
+ Entry_t* magiclast; /* last entry in magic */ \
+ char* mime; /* MIME type */ \
+ unsigned char* x2n; /* CC_ALIEN=>CC_NATIVE */ \
+ char fbuf[SF_BUFSIZE + 1]; /* file data */ \
+ char xbuf[SF_BUFSIZE + 1]; /* indirect file data */ \
+ char nbuf[256]; /* !CC_NATIVE data */ \
+ char mbuf[64]; /* mime string */ \
+ char sbuf[64]; /* type suffix string */ \
+ char tbuf[2 * PATH_MAX]; /* type string */ \
+ Cctype_t cctype[UCHAR_MAX + 1]; /* char code types */ \
+ unsigned int count[UCHAR_MAX + 1]; /* char frequency count */ \
+ unsigned int multi[UCHAR_MAX + 1]; /* muti char count */ \
+ int keep[MAXNEST]; /* ckmagic nest stack */ \
+ char* cap[MAXNEST]; /* ckmagic mime stack */ \
+ char* msg[MAXNEST]; /* ckmagic text stack */ \
+ Entry_t* ret[MAXNEST]; /* ckmagic return stack */ \
+ int fbsz; /* fbuf size */ \
+ int fbmx; /* fbuf max size */ \
+ int xbsz; /* xbuf size */ \
+ int swap; /* swap() operation */ \
+ unsigned long flags; /* disc+open flags */ \
+ long xoff; /* xbuf offset */ \
+ int identifier[ID_MAX + 1]; /* Info_t identifier */ \
+ Sfio_t* fp; /* fbuf fp */ \
+ Sfio_t* tmp; /* tmp string */ \
+ regdisc_t redisc; /* regex discipline */ \
+ Dtdisc_t dtdisc; /* dict discipline */ \
+ Dt_t* idtab; /* identifier dict */ \
+ Dt_t* infotab; /* info keyword dict */
+
+#include <magic.h>
+
+static Info_t dict[] = /* keyword dictionary */
+{
+ { "COMMON", ID_FORTRAN },
+ { "COMPUTE", ID_COBOL },
+ { "COMP", ID_COPYBOOK },
+ { "COMPUTATIONAL",ID_COPYBOOK },
+ { "DCL", ID_PL1 },
+ { "DEFINED", ID_PL1 },
+ { "DIMENSION", ID_FORTRAN },
+ { "DIVISION", ID_COBOL },
+ { "FILLER", ID_COPYBOOK },
+ { "FIXED", ID_PL1 },
+ { "FUNCTION", ID_FORTRAN },
+ { "HTML", ID_HTML },
+ { "INTEGER", ID_FORTRAN },
+ { "MAIN", ID_PL1 },
+ { "OPTIONS", ID_PL1 },
+ { "PERFORM", ID_COBOL },
+ { "PIC", ID_COPYBOOK },
+ { "REAL", ID_FORTRAN },
+ { "REDEFINES", ID_COPYBOOK },
+ { "S9", ID_COPYBOOK },
+ { "SECTION", ID_COBOL },
+ { "SELECT", ID_COBOL },
+ { "SUBROUTINE", ID_FORTRAN },
+ { "TEXT", ID_ASM },
+ { "VALUE", ID_COPYBOOK },
+ { "attr", ID_MAM3 },
+ { "binary", ID_YACC },
+ { "block", ID_FORTRAN },
+ { "bss", ID_ASM },
+ { "byte", ID_ASM },
+ { "char", ID_C },
+ { "class", ID_CPLUSPLUS },
+ { "clr", ID_NOTEXT },
+ { "comm", ID_ASM },
+ { "common", ID_FORTRAN },
+ { "data", ID_ASM },
+ { "dimension", ID_FORTRAN },
+ { "done", ID_MAM2 },
+ { "double", ID_C },
+ { "even", ID_ASM },
+ { "exec", ID_MAM3 },
+ { "extern", ID_C },
+ { "float", ID_C },
+ { "function", ID_FORTRAN },
+ { "globl", ID_ASM },
+ { "h", ID_INCL3 },
+ { "html", ID_HTML },
+ { "include", ID_INCL1 },
+ { "int", ID_C },
+ { "integer", ID_FORTRAN },
+ { "jmp", ID_NOTEXT },
+ { "left", ID_YACC },
+ { "libc", ID_INCL2 },
+ { "long", ID_C },
+ { "make", ID_MAM1 },
+ { "mov", ID_NOTEXT },
+ { "private", ID_CPLUSPLUS },
+ { "public", ID_CPLUSPLUS },
+ { "real", ID_FORTRAN },
+ { "register", ID_C },
+ { "right", ID_YACC },
+ { "sfio", ID_INCL2 },
+ { "static", ID_C },
+ { "stdio", ID_INCL2 },
+ { "struct", ID_C },
+ { "subroutine", ID_FORTRAN },
+ { "sys", ID_NOTEXT },
+ { "term", ID_YACC },
+ { "text", ID_ASM },
+ { "tst", ID_NOTEXT },
+ { "type", ID_YACC },
+ { "typedef", ID_C },
+ { "u", ID_INCL2 },
+ { "union", ID_YACC },
+ { "void", ID_C },
+};
+
+static Info_t info[] =
+{
+ { "atime", INFO_atime },
+ { "blocks", INFO_blocks },
+ { "ctime", INFO_ctime },
+ { "fstype", INFO_fstype },
+ { "gid", INFO_gid },
+ { "mode", INFO_mode },
+ { "mtime", INFO_mtime },
+ { "name", INFO_name },
+ { "nlink", INFO_nlink },
+ { "size", INFO_size },
+ { "uid", INFO_uid },
+};
+
+/*
+ * return pointer to data at offset off and size siz
+ */
+
+static char*
+getdata(register Magic_t* mp, register long off, register int siz)
+{
+ register long n;
+
+ if (off < 0)
+ return 0;
+ if (off + siz <= mp->fbsz)
+ return mp->fbuf + off;
+ if (off < mp->xoff || off + siz > mp->xoff + mp->xbsz)
+ {
+ if (off + siz > mp->fbmx)
+ return 0;
+ n = (off / (SF_BUFSIZE / 2)) * (SF_BUFSIZE / 2);
+ if (sfseek(mp->fp, n, SEEK_SET) != n)
+ return 0;
+ if ((mp->xbsz = sfread(mp->fp, mp->xbuf, sizeof(mp->xbuf) - 1)) < 0)
+ {
+ mp->xoff = 0;
+ mp->xbsz = 0;
+ return 0;
+ }
+ mp->xbuf[mp->xbsz] = 0;
+ mp->xoff = n;
+ if (off + siz > mp->xoff + mp->xbsz)
+ return 0;
+ }
+ return mp->xbuf + off - mp->xoff;
+}
+
+/*
+ * @... evaluator for strexpr()
+ */
+
+static long
+indirect(const char* cs, char** e, void* handle)
+{
+ register char* s = (char*)cs;
+ register Magic_t* mp = (Magic_t*)handle;
+ register long n = 0;
+ register char* p;
+
+ if (s)
+ {
+ if (*s == '@')
+ {
+ n = *++s == '(' ? strexpr(s, e, indirect, mp) : strtol(s, e, 0);
+ switch (*(s = *e))
+ {
+ case 'b':
+ case 'B':
+ s++;
+ if (p = getdata(mp, n, 1))
+ n = *(unsigned char*)p;
+ else
+ s = (char*)cs;
+ break;
+ case 'h':
+ case 'H':
+ s++;
+ if (p = getdata(mp, n, 2))
+ n = swapget(mp->swap, p, 2);
+ else
+ s = (char*)cs;
+ break;
+ case 'q':
+ case 'Q':
+ s++;
+ if (p = getdata(mp, n, 8))
+ n = swapget(mp->swap, p, 8);
+ else
+ s = (char*)cs;
+ break;
+ default:
+ if (isalnum(*s))
+ s++;
+ if (p = getdata(mp, n, 4))
+ n = swapget(mp->swap, p, 4);
+ else
+ s = (char*)cs;
+ break;
+ }
+ }
+ *e = s;
+ }
+ else if ((mp->flags & MAGIC_VERBOSE) && mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 2, "%s in indirect expression", *e);
+ return n;
+}
+
+/*
+ * emit regex error message
+ */
+
+static void
+regmessage(Magic_t* mp, regex_t* re, int code)
+{
+ char buf[128];
+
+ if ((mp->flags & MAGIC_VERBOSE) && mp->disc->errorf)
+ {
+ regerror(code, re, buf, sizeof(buf));
+ (*mp->disc->errorf)(mp, mp->disc, 3, "regex: %s", buf);
+ }
+}
+
+/*
+ * decompose vcodex(3) method composition
+ */
+
+static char*
+vcdecomp(char* b, char* e, unsigned char* m, unsigned char* x)
+{
+ unsigned char* map;
+ const char* o;
+ int c;
+ int n;
+ int i;
+ int a;
+
+ map = CCMAP(CC_ASCII, CC_NATIVE);
+ a = 0;
+ i = 1;
+ for (;;)
+ {
+ if (i)
+ i = 0;
+ else
+ *b++ = '^';
+ if (m < (x - 1) && !*(m + 1))
+ {
+ /*
+ * obsolete indices
+ */
+
+ if (!a)
+ {
+ a = 1;
+ o = "old, ";
+ while (b < e && (c = *o++))
+ *b++ = c;
+ }
+ switch (*m)
+ {
+ case 0: o = "delta"; break;
+ case 1: o = "huffman"; break;
+ case 2: o = "huffgroup"; break;
+ case 3: o = "arith"; break;
+ case 4: o = "bwt"; break;
+ case 5: o = "rle"; break;
+ case 6: o = "mtf"; break;
+ case 7: o = "transpose"; break;
+ case 8: o = "table"; break;
+ case 9: o = "huffpart"; break;
+ case 50: o = "map"; break;
+ case 100: o = "recfm"; break;
+ case 101: o = "ss7"; break;
+ default: o = "UNKNOWN"; break;
+ }
+ m += 2;
+ while (b < e && (c = *o++))
+ *b++ = c;
+ }
+ else
+ while (b < e && m < x && (c = *m++))
+ {
+ if (map)
+ c = map[c];
+ *b++ = c;
+ }
+ if (b >= e)
+ break;
+ n = 0;
+ while (m < x)
+ {
+ n = (n<<7) | (*m & 0x7f);
+ if (!(*m++ & 0x80))
+ break;
+ }
+ if (n >= (x - m))
+ break;
+ m += n;
+ }
+ return b;
+}
+
+/*
+ * check for magic table match in buf
+ */
+
+static char*
+ckmagic(register Magic_t* mp, const char* file, char* buf, char* end, struct stat* st, unsigned long off)
+{
+ register Entry_t* ep;
+ register char* p;
+ register char* b;
+ register int level = 0;
+ int call = -1;
+ int all = 0;
+ int c;
+ int str;
+ char* q;
+ char* t;
+ char* cur;
+ char* base = 0;
+ unsigned long num;
+ unsigned long mask;
+ regmatch_t matches[10];
+
+ mp->swap = 0;
+ b = mp->msg[0] = cur = buf;
+ mp->mime = mp->cap[0] = 0;
+ mp->keep[0] = 0;
+ for (ep = mp->magic; ep; ep = ep->next)
+ {
+ fun:
+ if (ep->nest == '{')
+ {
+ if (++level >= MAXNEST)
+ {
+ call = -1;
+ level = 0;
+ mp->keep[0] = 0;
+ b = mp->msg[0];
+ mp->mime = mp->cap[0];
+ continue;
+ }
+ mp->keep[level] = mp->keep[level - 1] != 0;
+ mp->msg[level] = b;
+ mp->cap[level] = mp->mime;
+ }
+ switch (ep->cont)
+ {
+ case '#':
+ if (mp->keep[level] && b > cur)
+ {
+ if ((mp->flags & MAGIC_ALL) && b < (end - 3))
+ {
+ all = 1;
+ *b++ = '\n';
+ cur = b;
+ continue;
+ }
+ *b = 0;
+ return buf;
+ }
+ mp->swap = 0;
+ b = mp->msg[0] = cur;
+ mp->mime = mp->cap[0] = 0;
+ if (ep->type == ' ')
+ continue;
+ break;
+ case '$':
+ if (mp->keep[level] && call < (MAXNEST - 1))
+ {
+ mp->ret[++call] = ep;
+ ep = ep->value.lab;
+ goto fun;
+ }
+ continue;
+ case ':':
+ ep = mp->ret[call--];
+ if (ep->op == 'l')
+ goto fun;
+ continue;
+ case '|':
+ if (mp->keep[level] > 1)
+ goto checknest;
+ /*FALLTHROUGH*/
+ default:
+ if (!mp->keep[level])
+ {
+ b = mp->msg[level];
+ mp->mime = mp->cap[level];
+ goto checknest;
+ }
+ break;
+ }
+ p = "";
+ num = 0;
+ if (!ep->expr)
+ num = ep->offset + off;
+ else
+ switch (ep->offset)
+ {
+ case 0:
+ num = strexpr(ep->expr, NiL, indirect, mp) + off;
+ break;
+ case INFO_atime:
+ num = st->st_atime;
+ ep->type = 'D';
+ break;
+ case INFO_blocks:
+ num = iblocks(st);
+ ep->type = 'N';
+ break;
+ case INFO_ctime:
+ num = st->st_ctime;
+ ep->type = 'D';
+ break;
+ case INFO_fstype:
+ p = fmtfs(st);
+ ep->type = toupper(ep->type);
+ break;
+ case INFO_gid:
+ if (ep->type == 'e' || ep->type == 'm' || ep->type == 's')
+ {
+ p = fmtgid(st->st_gid);
+ ep->type = toupper(ep->type);
+ }
+ else
+ {
+ num = st->st_gid;
+ ep->type = 'N';
+ }
+ break;
+ case INFO_mode:
+ if (ep->type == 'e' || ep->type == 'm' || ep->type == 's')
+ {
+ p = fmtmode(st->st_mode, 0);
+ ep->type = toupper(ep->type);
+ }
+ else
+ {
+ num = modex(st->st_mode);
+ ep->type = 'N';
+ }
+ break;
+ case INFO_mtime:
+ num = st->st_ctime;
+ ep->type = 'D';
+ break;
+ case INFO_name:
+ if (!base)
+ {
+ if (base = strrchr(file, '/'))
+ base++;
+ else
+ base = (char*)file;
+ }
+ p = base;
+ ep->type = toupper(ep->type);
+ break;
+ case INFO_nlink:
+ num = st->st_nlink;
+ ep->type = 'N';
+ break;
+ case INFO_size:
+ num = st->st_size;
+ ep->type = 'N';
+ break;
+ case INFO_uid:
+ if (ep->type == 'e' || ep->type == 'm' || ep->type == 's')
+ {
+ p = fmtuid(st->st_uid);
+ ep->type = toupper(ep->type);
+ }
+ else
+ {
+ num = st->st_uid;
+ ep->type = 'N';
+ }
+ break;
+ }
+ switch (ep->type)
+ {
+
+ case 'b':
+ if (!(p = getdata(mp, num, 1)))
+ goto next;
+ num = *(unsigned char*)p;
+ break;
+
+ case 'h':
+ if (!(p = getdata(mp, num, 2)))
+ goto next;
+ num = swapget(ep->swap ? (~ep->swap ^ mp->swap) : mp->swap, p, 2);
+ break;
+
+ case 'd':
+ case 'l':
+ case 'v':
+ if (!(p = getdata(mp, num, 4)))
+ goto next;
+ num = swapget(ep->swap ? (~ep->swap ^ mp->swap) : mp->swap, p, 4);
+ break;
+
+ case 'q':
+ if (!(p = getdata(mp, num, 8)))
+ goto next;
+ num = swapget(ep->swap ? (~ep->swap ^ mp->swap) : mp->swap, p, 8);
+ break;
+
+ case 'e':
+ if (!(p = getdata(mp, num, 0)))
+ goto next;
+ /*FALLTHROUGH*/
+ case 'E':
+ if (!ep->value.sub)
+ goto next;
+ if ((c = regexec(ep->value.sub, p, elementsof(matches), matches, 0)) || (c = regsubexec(ep->value.sub, p, elementsof(matches), matches)))
+ {
+ c = mp->fbsz;
+ if (c >= sizeof(mp->nbuf))
+ c = sizeof(mp->nbuf) - 1;
+ p = (char*)memcpy(mp->nbuf, p, c);
+ p[c] = 0;
+ ccmapstr(mp->x2n, p, c);
+ if ((c = regexec(ep->value.sub, p, elementsof(matches), matches, 0)) || (c = regsubexec(ep->value.sub, p, elementsof(matches), matches)))
+ {
+ if (c != REG_NOMATCH)
+ regmessage(mp, ep->value.sub, c);
+ goto next;
+ }
+ }
+ p = ep->value.sub->re_sub->re_buf;
+ q = T(ep->desc);
+ t = *q ? q : p;
+ if (mp->keep[level]++ && b > cur && b < end && *(b - 1) != ' ' && *t && *t != ',' && *t != '.' && *t != '\b')
+ *b++ = ' ';
+ b += sfsprintf(b, end - b, *q ? q : "%s", p + (*p == '\b'));
+ if (ep->mime)
+ mp->mime = ep->mime;
+ goto checknest;
+
+ case 's':
+ if (!(p = getdata(mp, num, ep->mask)))
+ goto next;
+ goto checkstr;
+ case 'm':
+ if (!(p = getdata(mp, num, 0)))
+ goto next;
+ /*FALLTHROUGH*/
+ case 'M':
+ case 'S':
+ checkstr:
+ for (;;)
+ {
+ if (*ep->value.str == '*' && !*(ep->value.str + 1) && isprint(*p))
+ break;
+ if ((ep->type == 'm' || ep->type == 'M') ? strmatch(p, ep->value.str) : !memcmp(p, ep->value.str, ep->mask))
+ break;
+ if (p == mp->nbuf || ep->mask >= sizeof(mp->nbuf))
+ goto next;
+ p = (char*)memcpy(mp->nbuf, p, ep->mask);
+ p[ep->mask] = 0;
+ ccmapstr(mp->x2n, p, ep->mask);
+ }
+ q = T(ep->desc);
+ if (mp->keep[level]++ && b > cur && b < end && *(b - 1) != ' ' && *q && *q != ',' && *q != '.' && *q != '\b')
+ *b++ = ' ';
+ for (t = p; (c = *t) >= 0 && c <= 0177 && isprint(c) && c != '\n'; t++);
+ *t = 0;
+ b += sfsprintf(b, end - b, q + (*q == '\b'), p);
+ *t = c;
+ if (ep->mime)
+ mp->mime = ep->mime;
+ goto checknest;
+
+ }
+ if (mask = ep->mask)
+ num &= mask;
+ switch (ep->op)
+ {
+
+ case '=':
+ case '@':
+ if (num == ep->value.num)
+ break;
+ if (ep->cont != '#')
+ goto next;
+ if (!mask)
+ mask = ~mask;
+ if (ep->type == 'h')
+ {
+ if ((num = swapget(mp->swap = 1, p, 2) & mask) == ep->value.num)
+ {
+ if (!(mp->swap & (mp->swap + 1)))
+ mp->swap = 7;
+ goto swapped;
+ }
+ }
+ else if (ep->type == 'l')
+ {
+ for (c = 1; c < 4; c++)
+ if ((num = swapget(mp->swap = c, p, 4) & mask) == ep->value.num)
+ {
+ if (!(mp->swap & (mp->swap + 1)))
+ mp->swap = 7;
+ goto swapped;
+ }
+ }
+ else if (ep->type == 'q')
+ {
+ for (c = 1; c < 8; c++)
+ if ((num = swapget(mp->swap = c, p, 8) & mask) == ep->value.num)
+ goto swapped;
+ }
+ goto next;
+
+ case '!':
+ if (num != ep->value.num)
+ break;
+ goto next;
+
+ case '^':
+ if (num ^ ep->value.num)
+ break;
+ goto next;
+
+ case '>':
+ if (num > ep->value.num)
+ break;
+ goto next;
+
+ case '<':
+ if (num < ep->value.num)
+ break;
+ goto next;
+
+ case 'l':
+ if (num > 0 && mp->keep[level] && call < (MAXNEST - 1))
+ {
+ if (!ep->value.loop->count)
+ {
+ ep->value.loop->count = num;
+ ep->value.loop->offset = off;
+ off = ep->value.loop->start;
+ }
+ else if (!--ep->value.loop->count)
+ {
+ off = ep->value.loop->offset;
+ goto next;
+ }
+ else
+ off += ep->value.loop->size;
+ mp->ret[++call] = ep;
+ ep = ep->value.loop->lab;
+ goto fun;
+ }
+ goto next;
+
+ case 'm':
+ c = mp->swap;
+ t = ckmagic(mp, file, b + (b > cur), end, st, num);
+ mp->swap = c;
+ if (t)
+ {
+ if (b > cur && b < end)
+ *b = ' ';
+ b += strlen(b);
+ }
+ else if (ep->cont == '&')
+ goto next;
+ break;
+
+ case 'r':
+#if _UWIN
+ {
+ char* e;
+ Sfio_t* rp;
+ Sfio_t* gp;
+
+ if (!(t = strrchr(file, '.')))
+ goto next;
+ sfprintf(mp->tmp, "/reg/classes_root/%s", t);
+ if (!(t = sfstruse(mp->tmp)) || !(rp = sfopen(NiL, t, "r")))
+ goto next;
+ *ep->desc = 0;
+ *ep->mime = 0;
+ gp = 0;
+ while (t = sfgetr(rp, '\n', 1))
+ {
+ if (strneq(t, "Content Type=", 13))
+ {
+ ep->mime = vmnewof(mp->vm, ep->mime, char, sfvalue(rp), 0);
+ strcpy(ep->mime, t + 13);
+ if (gp)
+ break;
+ }
+ else
+ {
+ sfprintf(mp->tmp, "/reg/classes_root/%s", t);
+ if ((e = sfstruse(mp->tmp)) && (gp = sfopen(NiL, e, "r")))
+ {
+ ep->desc = vmnewof(mp->vm, ep->desc, char, strlen(t), 1);
+ strcpy(ep->desc, t);
+ if (*ep->mime)
+ break;
+ }
+ }
+ }
+ sfclose(rp);
+ if (!gp)
+ goto next;
+ if (!*ep->mime)
+ {
+ t = T(ep->desc);
+ if (!strncasecmp(t, "microsoft", 9))
+ t += 9;
+ while (isspace(*t))
+ t++;
+ e = "application/x-ms-";
+ ep->mime = vmnewof(mp->vm, ep->mime, char, strlen(t), strlen(e));
+ e = strcopy(ep->mime, e);
+ while ((c = *t++) && c != '.' && c != ' ')
+ *e++ = isupper(c) ? tolower(c) : c;
+ *e = 0;
+ }
+ while (t = sfgetr(gp, '\n', 1))
+ if (*t && !streq(t, "\"\""))
+ {
+ ep->desc = vmnewof(mp->vm, ep->desc, char, sfvalue(gp), 0);
+ strcpy(ep->desc, t);
+ break;
+ }
+ sfclose(gp);
+ if (!*ep->desc)
+ goto next;
+ if (!t)
+ for (t = T(ep->desc); *t; t++)
+ if (*t == '.')
+ *t = ' ';
+ if (!mp->keep[level])
+ mp->keep[level] = 2;
+ mp->mime = ep->mime;
+ break;
+ }
+#else
+ if (ep->cont == '#' && !mp->keep[level])
+ mp->keep[level] = 1;
+ goto next;
+#endif
+
+ case 'v':
+ if (!(p = getdata(mp, num, 4)))
+ goto next;
+ c = 0;
+ do
+ {
+ num++;
+ c = (c<<7) | (*p & 0x7f);
+ } while (*p++ & 0x80);
+ if (!(p = getdata(mp, num, c)))
+ goto next;
+ if (mp->keep[level]++ && b > cur && b < (end - 1) && *(b - 1) != ' ')
+ {
+ *b++ = ',';
+ *b++ = ' ';
+ }
+ b = vcdecomp(b, cur + PATH_MAX, (unsigned char*)p, (unsigned char*)p + c);
+ goto checknest;
+
+ }
+ swapped:
+ q = T(ep->desc);
+ if (mp->keep[level]++ && b > cur && b < end && *(b - 1) != ' ' && *q && *q != ',' && *q != '.' && *q != '\b')
+ *b++ = ' ';
+ if (*q == '\b')
+ q++;
+ str = 0;
+ for (t = q; *t; t++)
+ if (*t == '%' && (c = *(t + 1)))
+ {
+ if (c == '%')
+ t++;
+ else
+ while (c && c != '%')
+ {
+ if (c == 's')
+ {
+ str = 1;
+ break;
+ }
+ else if (c == 'c' || c == 'd' || c == 'i' || c == 'u' || c == 'x' || c == 'X')
+ goto format;
+ t++;
+ c = *(t + 1);
+ }
+ }
+ format:
+ if (!str)
+ b += sfsprintf(b, end - b, q, num, num == 1 ? "" : "s", 0, 0, 0, 0, 0, 0);
+ else if (ep->type == 'd' || ep->type == 'D')
+ b += sfsprintf(b, end - b, q, fmttime("%?%QL", (time_t)num), 0, 0, 0, 0, 0, 0, 0);
+ else if (ep->type == 'v')
+ b += sfsprintf(b, end - b, q, fmtversion(num), 0, 0, 0, 0, 0, 0, 0);
+ else
+ b += sfsprintf(b, end - b, q, fmtnum(num, 0), num == 1 ? "" : "s", 0, 0, 0, 0, 0, 0);
+ if (ep->mime && *ep->mime)
+ mp->mime = ep->mime;
+ checknest:
+ if (ep->nest == '}')
+ {
+ if (!mp->keep[level])
+ {
+ b = mp->msg[level];
+ mp->mime = mp->cap[level];
+ }
+ else if (level > 0)
+ mp->keep[level - 1] = mp->keep[level];
+ if (--level < 0)
+ {
+ level = 0;
+ mp->keep[0] = 0;
+ }
+ }
+ continue;
+ next:
+ if (ep->cont == '&')
+ mp->keep[level] = 0;
+ goto checknest;
+ }
+ if (all && b-- || mp->keep[level] && b > cur)
+ {
+ *b = 0;
+ return buf;
+ }
+ return 0;
+}
+
+/*
+ * check english language stats
+ */
+
+static int
+ckenglish(register Magic_t* mp, int pun, int badpun)
+{
+ register char* s;
+ register int vowl = 0;
+ register int freq = 0;
+ register int rare = 0;
+
+ if (5 * badpun > pun)
+ return 0;
+ if (2 * mp->count[';'] > mp->count['E'] + mp->count['e'])
+ return 0;
+ if ((mp->count['>'] + mp->count['<'] + mp->count['/']) > mp->count['E'] + mp->count['e'])
+ return 0;
+ for (s = "aeiou"; *s; s++)
+ vowl += mp->count[toupper(*s)] + mp->count[*s];
+ for (s = "etaion"; *s; s++)
+ freq += mp->count[toupper(*s)] + mp->count[*s];
+ for (s = "vjkqxz"; *s; s++)
+ rare += mp->count[toupper(*s)] + mp->count[*s];
+ return 5 * vowl >= mp->fbsz - mp->count[' '] && freq >= 10 * rare;
+}
+
+/*
+ * check programming language stats
+ */
+
+static char*
+cklang(register Magic_t* mp, const char* file, char* buf, char* end, struct stat* st)
+{
+ register int c;
+ register unsigned char* b;
+ register unsigned char* e;
+ register int q;
+ register char* s;
+ char* t;
+ char* base;
+ char* suff;
+ char* t1;
+ char* t2;
+ char* t3;
+ int n;
+ int badpun;
+ int code;
+ int pun;
+ Cctype_t flags;
+ Info_t* ip;
+
+ b = (unsigned char*)mp->fbuf;
+ e = b + mp->fbsz;
+ memzero(mp->count, sizeof(mp->count));
+ memzero(mp->multi, sizeof(mp->multi));
+ memzero(mp->identifier, sizeof(mp->identifier));
+
+ /*
+ * check character coding
+ */
+
+ flags = 0;
+ while (b < e)
+ flags |= mp->cctype[*b++];
+ b = (unsigned char*)mp->fbuf;
+ code = 0;
+ q = CC_ASCII;
+ n = CC_MASK;
+ for (c = 0; c < CC_MAPS; c++)
+ {
+ flags ^= CC_text;
+ if ((flags & CC_MASK) < n)
+ {
+ n = flags & CC_MASK;
+ q = c;
+ }
+ flags >>= CC_BIT;
+ }
+ flags = n;
+ if (!(flags & (CC_binary|CC_notext)))
+ {
+ if (q != CC_NATIVE)
+ {
+ code = q;
+ ccmaps(mp->fbuf, mp->fbsz, q, CC_NATIVE);
+ }
+ if (b[0] == '#' && b[1] == '!')
+ {
+ for (b += 2; b < e && isspace(*b); b++);
+ for (s = (char*)b; b < e && isprint(*b); b++);
+ c = *b;
+ *b = 0;
+ if ((st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) || match(s, "/*bin*/*") || !access(s, F_OK))
+ {
+ if (t = strrchr(s, '/'))
+ s = t + 1;
+ for (t = s; *t; t++)
+ if (isspace(*t))
+ {
+ *t = 0;
+ break;
+ }
+ sfsprintf(mp->mbuf, sizeof(mp->mbuf), "application/x-%s", *s ? s : "sh");
+ mp->mime = mp->mbuf;
+ if (match(s, "*sh"))
+ {
+ t1 = T("command");
+ if (streq(s, "sh"))
+ *s = 0;
+ else
+ {
+ *b++ = ' ';
+ *b = 0;
+ }
+ }
+ else
+ {
+ t1 = T("interpreter");
+ *b++ = ' ';
+ *b = 0;
+ }
+ sfsprintf(mp->sbuf, sizeof(mp->sbuf), T("%s%s script"), s, t1);
+ s = mp->sbuf;
+ goto qualify;
+ }
+ *b = c;
+ b = (unsigned char*)mp->fbuf;
+ }
+ badpun = 0;
+ pun = 0;
+ q = 0;
+ s = 0;
+ t = 0;
+ while (b < e)
+ {
+ c = *b++;
+ mp->count[c]++;
+ if (c == q && (q != '*' || *b == '/' && b++))
+ {
+ mp->multi[q]++;
+ q = 0;
+ }
+ else if (c == '\\')
+ {
+ s = 0;
+ b++;
+ }
+ else if (!q)
+ {
+ if (isalpha(c) || c == '_')
+ {
+ if (!s)
+ s = (char*)b - 1;
+ }
+ else if (!isdigit(c))
+ {
+ if (s)
+ {
+ if (s > mp->fbuf)
+ switch (*(s - 1))
+ {
+ case ':':
+ if (*b == ':')
+ mp->multi[':']++;
+ break;
+ case '.':
+ if (((char*)b - s) == 3 && (s == (mp->fbuf + 1) || *(s - 2) == '\n'))
+ mp->multi['.']++;
+ break;
+ case '\n':
+ case '\\':
+ if (*b == '{')
+ t = (char*)b + 1;
+ break;
+ case '{':
+ if (s == t && *b == '}')
+ mp->multi['X']++;
+ break;
+ }
+ if (!mp->idtab)
+ {
+ if (mp->idtab = dtnew(mp->vm, &mp->dtdisc, Dtset))
+ for (q = 0; q < elementsof(dict); q++)
+ dtinsert(mp->idtab, &dict[q]);
+ else if (mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 3, "out of space");
+ q = 0;
+ }
+ if (mp->idtab)
+ {
+ *(b - 1) = 0;
+ if (ip = (Info_t*)dtmatch(mp->idtab, s))
+ mp->identifier[ip->value]++;
+ *(b - 1) = c;
+ }
+ s = 0;
+ }
+ switch (c)
+ {
+ case '\t':
+ if (b == (unsigned char*)(mp->fbuf + 1) || *(b - 2) == '\n')
+ mp->multi['\t']++;
+ break;
+ case '"':
+ case '\'':
+ q = c;
+ break;
+ case '/':
+ if (*b == '*')
+ q = *b++;
+ else if (*b == '/')
+ q = '\n';
+ break;
+ case '$':
+ if (*b == '(' && *(b + 1) != ' ')
+ mp->multi['$']++;
+ break;
+ case '{':
+ case '}':
+ case '[':
+ case ']':
+ case '(':
+ mp->multi[c]++;
+ break;
+ case ')':
+ mp->multi[c]++;
+ goto punctuation;
+ case ':':
+ if (*b == ':' && isspace(*(b + 1)) && b > (unsigned char*)(mp->fbuf + 1) && isspace(*(b - 2)))
+ mp->multi[':']++;
+ goto punctuation;
+ case '.':
+ case ',':
+ case '%':
+ case ';':
+ case '?':
+ punctuation:
+ pun++;
+ if (*b != ' ' && *b != '\n')
+ badpun++;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ while (b < e)
+ mp->count[*b++]++;
+ base = (t1 = strrchr(file, '/')) ? t1 + 1 : (char*)file;
+ suff = (t1 = strrchr(base, '.')) ? t1 + 1 : "";
+ if (!flags)
+ {
+ if (match(suff, "*sh|bat|cmd"))
+ goto id_sh;
+ if (match(base, "*@(mkfile)"))
+ goto id_mk;
+ if (match(base, "*@(makefile|.mk)"))
+ goto id_make;
+ if (match(base, "*@(mamfile|.mam)"))
+ goto id_mam;
+ if (match(suff, "[cly]?(pp|xx|++)|cc|ll|yy"))
+ goto id_c;
+ if (match(suff, "f"))
+ goto id_fortran;
+ if (match(suff, "htm+(l)"))
+ goto id_html;
+ if (match(suff, "cpy"))
+ goto id_copybook;
+ if (match(suff, "cob|cbl|cb2"))
+ goto id_cobol;
+ if (match(suff, "pl[1i]"))
+ goto id_pl1;
+ if (match(suff, "tex"))
+ goto id_tex;
+ if (match(suff, "asm|s"))
+ goto id_asm;
+ if ((st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) && (!suff || suff != strchr(suff, '.')))
+ {
+ id_sh:
+ s = T("command script");
+ mp->mime = "application/sh";
+ goto qualify;
+ }
+ if (strmatch(mp->fbuf, "From * [0-9][0-9]:[0-9][0-9]:[0-9][0-9] *"))
+ {
+ s = T("mail message");
+ mp->mime = "message/rfc822";
+ goto qualify;
+ }
+ if (match(base, "*@(mkfile)"))
+ {
+ id_mk:
+ s = "mkfile";
+ mp->mime = "application/mk";
+ goto qualify;
+ }
+ if (match(base, "*@(makefile|.mk)") || mp->multi['\t'] >= mp->count[':'] && (mp->multi['$'] > 0 || mp->multi[':'] > 0))
+ {
+ id_make:
+ s = "makefile";
+ mp->mime = "application/make";
+ goto qualify;
+ }
+ if (mp->multi['.'] >= 3)
+ {
+ s = T("nroff input");
+ mp->mime = "application/x-troff";
+ goto qualify;
+ }
+ if (mp->multi['X'] >= 3)
+ {
+ s = T("TeX input");
+ mp->mime = "application/x-tex";
+ goto qualify;
+ }
+ if (mp->fbsz < SF_BUFSIZE &&
+ (mp->multi['('] == mp->multi[')'] &&
+ mp->multi['{'] == mp->multi['}'] &&
+ mp->multi['['] == mp->multi[']']) ||
+ mp->fbsz >= SF_BUFSIZE &&
+ (mp->multi['('] >= mp->multi[')'] &&
+ mp->multi['{'] >= mp->multi['}'] &&
+ mp->multi['['] >= mp->multi[']']))
+ {
+ c = mp->identifier[ID_INCL1];
+ if (c >= 2 && mp->identifier[ID_INCL2] >= c && mp->identifier[ID_INCL3] >= c && mp->count['.'] >= c ||
+ mp->identifier[ID_C] >= 5 && mp->count[';'] >= 5 ||
+ mp->count['='] >= 20 && mp->count[';'] >= 20)
+ {
+ id_c:
+ t1 = "";
+ t2 = "c ";
+ t3 = T("program");
+ switch (*suff)
+ {
+ case 'c':
+ case 'C':
+ mp->mime = "application/x-cc";
+ break;
+ case 'l':
+ case 'L':
+ t1 = "lex ";
+ mp->mime = "application/x-lex";
+ break;
+ default:
+ t3 = T("header");
+ if (mp->identifier[ID_YACC] < 5 || mp->count['%'] < 5)
+ {
+ mp->mime = "application/x-cc";
+ break;
+ }
+ /*FALLTHROUGH*/
+ case 'y':
+ case 'Y':
+ t1 = "yacc ";
+ mp->mime = "application/x-yacc";
+ break;
+ }
+ if (mp->identifier[ID_CPLUSPLUS] >= 3)
+ {
+ t2 = "c++ ";
+ mp->mime = "application/x-c++";
+ }
+ sfsprintf(mp->sbuf, sizeof(mp->sbuf), "%s%s%s", t1, t2, t3);
+ s = mp->sbuf;
+ goto qualify;
+ }
+ }
+ if (mp->identifier[ID_MAM1] >= 2 && mp->identifier[ID_MAM3] >= 2 &&
+ (mp->fbsz < SF_BUFSIZE && mp->identifier[ID_MAM1] == mp->identifier[ID_MAM2] ||
+ mp->fbsz >= SF_BUFSIZE && mp->identifier[ID_MAM1] >= mp->identifier[ID_MAM2]))
+ {
+ id_mam:
+ s = T("mam program");
+ mp->mime = "application/x-mam";
+ goto qualify;
+ }
+ if (mp->identifier[ID_FORTRAN] >= 8)
+ {
+ id_fortran:
+ s = T("fortran program");
+ mp->mime = "application/x-fortran";
+ goto qualify;
+ }
+ if (mp->identifier[ID_HTML] > 0 && mp->count['<'] >= 8 && (c = mp->count['<'] - mp->count['>']) >= -2 && c <= 2)
+ {
+ id_html:
+ s = T("html input");
+ mp->mime = "text/html";
+ goto qualify;
+ }
+ if (mp->identifier[ID_COPYBOOK] > 0 && mp->identifier[ID_COBOL] == 0 && (c = mp->count['('] - mp->count[')']) >= -2 && c <= 2)
+ {
+ id_copybook:
+ s = T("cobol copybook");
+ mp->mime = "application/x-cobol";
+ goto qualify;
+ }
+ if (mp->identifier[ID_COBOL] > 0 && mp->identifier[ID_COPYBOOK] > 0 && (c = mp->count['('] - mp->count[')']) >= -2 && c <= 2)
+ {
+ id_cobol:
+ s = T("cobol program");
+ mp->mime = "application/x-cobol";
+ goto qualify;
+ }
+ if (mp->identifier[ID_PL1] > 0 && (c = mp->count['('] - mp->count[')']) >= -2 && c <= 2)
+ {
+ id_pl1:
+ s = T("pl1 program");
+ mp->mime = "application/x-pl1";
+ goto qualify;
+ }
+ if (mp->count['{'] >= 6 && (c = mp->count['{'] - mp->count['}']) >= -2 && c <= 2 && mp->count['\\'] >= mp->count['{'])
+ {
+ id_tex:
+ s = T("TeX input");
+ mp->mime = "text/tex";
+ goto qualify;
+ }
+ if (mp->identifier[ID_ASM] >= 4)
+ {
+ id_asm:
+ s = T("as program");
+ mp->mime = "application/x-as";
+ goto qualify;
+ }
+ if (ckenglish(mp, pun, badpun))
+ {
+ s = T("english text");
+ mp->mime = "text/plain";
+ goto qualify;
+ }
+ }
+ else if (streq(base, "core"))
+ {
+ mp->mime = "x-system/core";
+ return T("core dump");
+ }
+ if (flags & (CC_binary|CC_notext))
+ {
+ b = (unsigned char*)mp->fbuf;
+ e = b + mp->fbsz;
+ n = 0;
+ for (;;)
+ {
+ c = *b++;
+ q = 0;
+ while (c & 0x80)
+ {
+ c <<= 1;
+ q++;
+ }
+ switch (q)
+ {
+ case 4:
+ if (b < e && (*b++ & 0xc0) != 0x80)
+ break;
+ case 3:
+ if (b < e && (*b++ & 0xc0) != 0x80)
+ break;
+ case 2:
+ if (b < e && (*b++ & 0xc0) != 0x80)
+ break;
+ n = 1;
+ case 0:
+ if (b >= e)
+ {
+ if (n)
+ {
+ flags &= ~(CC_binary|CC_notext);
+ flags |= CC_utf_8;
+ }
+ break;
+ }
+ continue;
+ }
+ break;
+ }
+ }
+ if (flags & (CC_binary|CC_notext))
+ {
+ unsigned long d = 0;
+
+ if ((q = mp->fbsz / UCHAR_MAX) >= 2)
+ {
+ /*
+ * compression/encryption via standard deviation
+ */
+
+
+ for (c = 0; c < UCHAR_MAX; c++)
+ {
+ pun = mp->count[c] - q;
+ d += pun * pun;
+ }
+ d /= mp->fbsz;
+ }
+ if (d <= 0)
+ s = T("binary");
+ else if (d < 4)
+ s = T("encrypted");
+ else if (d < 16)
+ s = T("packed");
+ else if (d < 64)
+ s = T("compressed");
+ else if (d < 256)
+ s = T("delta");
+ else
+ s = T("data");
+ mp->mime = "application/octet-stream";
+ return s;
+ }
+ mp->mime = "text/plain";
+ if (flags & CC_utf_8)
+ s = (flags & CC_control) ? T("utf-8 text with control characters") : T("utf-8 text");
+ else if (flags & CC_latin)
+ s = (flags & CC_control) ? T("latin text with control characters") : T("latin text");
+ else
+ s = (flags & CC_control) ? T("text with control characters") : T("text");
+ qualify:
+ if (!flags && mp->count['\n'] >= mp->count['\r'] && mp->count['\n'] <= (mp->count['\r'] + 1) && mp->count['\r'])
+ {
+ t = "dos ";
+ mp->mime = "text/dos";
+ }
+ else
+ t = "";
+ if (code)
+ {
+ if (code == CC_ASCII)
+ sfsprintf(buf, end - buf, "ascii %s%s", t, s);
+ else
+ {
+ sfsprintf(buf, end - buf, "ebcdic%d %s%s", code - 1, t, s);
+ mp->mime = "text/ebcdic";
+ }
+ s = buf;
+ }
+ else if (*t)
+ {
+ sfsprintf(buf, end - buf, "%s%s", t, s);
+ s = buf;
+ }
+ return s;
+}
+
+/*
+ * return the basic magic string for file,st in buf,size
+ */
+
+static char*
+type(register Magic_t* mp, const char* file, struct stat* st, char* buf, char* end)
+{
+ register char* s;
+ register char* t;
+
+ mp->mime = 0;
+ if (!S_ISREG(st->st_mode))
+ {
+ if (S_ISDIR(st->st_mode))
+ {
+ mp->mime = "x-system/dir";
+ return T("directory");
+ }
+ if (S_ISLNK(st->st_mode))
+ {
+ mp->mime = "x-system/lnk";
+ s = buf;
+ s += sfsprintf(s, end - s, T("symbolic link to "));
+ if (pathgetlink(file, s, end - s) < 0)
+ return T("cannot read symbolic link text");
+ return buf;
+ }
+ if (S_ISBLK(st->st_mode))
+ {
+ mp->mime = "x-system/blk";
+ sfsprintf(buf, PATH_MAX, T("block special (%s)"), fmtdev(st));
+ return buf;
+ }
+ if (S_ISCHR(st->st_mode))
+ {
+ mp->mime = "x-system/chr";
+ sfsprintf(buf, end - buf, T("character special (%s)"), fmtdev(st));
+ return buf;
+ }
+ if (S_ISFIFO(st->st_mode))
+ {
+ mp->mime = "x-system/fifo";
+ return "fifo";
+ }
+#ifdef S_ISSOCK
+ if (S_ISSOCK(st->st_mode))
+ {
+ mp->mime = "x-system/sock";
+ return "socket";
+ }
+#endif
+ }
+ if (!(mp->fbmx = st->st_size))
+ s = T("empty");
+ else if (!mp->fp)
+ s = T("cannot read");
+ else
+ {
+ mp->fbsz = sfread(mp->fp, mp->fbuf, sizeof(mp->fbuf) - 1);
+ if (mp->fbsz < 0)
+ s = fmterror(errno);
+ else if (mp->fbsz == 0)
+ s = T("empty");
+ else
+ {
+ mp->fbuf[mp->fbsz] = 0;
+ mp->xoff = 0;
+ mp->xbsz = 0;
+ if (!(s = ckmagic(mp, file, buf, end, st, 0)))
+ s = cklang(mp, file, buf, end, st);
+ }
+ }
+ if (!mp->mime)
+ mp->mime = "application/unknown";
+ else if ((t = strchr(mp->mime, '%')) && *(t + 1) == 's' && !*(t + 2))
+ {
+ register char* b;
+ register char* be;
+ register char* m;
+ register char* me;
+
+ b = mp->mime;
+ me = (m = mp->mime = mp->fbuf) + sizeof(mp->fbuf) - 1;
+ while (m < me && b < t)
+ *m++ = *b++;
+ b = t = s;
+ for (;;)
+ {
+ if (!(be = strchr(t, ' ')))
+ {
+ be = b + strlen(b);
+ break;
+ }
+ if (*(be - 1) == ',' || strneq(be + 1, "data", 4) || strneq(be + 1, "file", 4))
+ break;
+ b = t;
+ t = be + 1;
+ }
+ while (m < me && b < be)
+ if ((*m++ = *b++) == ' ')
+ *(m - 1) = '-';
+ *m = 0;
+ }
+ return s;
+}
+
+/*
+ * low level for magicload()
+ */
+
+static int
+load(register Magic_t* mp, char* file, register Sfio_t* fp)
+{
+ register Entry_t* ep;
+ register char* p;
+ register char* p2;
+ char* p3;
+ char* next;
+ int n;
+ int lge;
+ int lev;
+ int ent;
+ int old;
+ int cont;
+ Info_t* ip;
+ Entry_t* ret;
+ Entry_t* first;
+ Entry_t* last = 0;
+ Entry_t* fun['z' - 'a' + 1];
+
+ memzero(fun, sizeof(fun));
+ cont = '$';
+ ent = 0;
+ lev = 0;
+ old = 0;
+ ret = 0;
+ error_info.file = file;
+ error_info.line = 0;
+ first = ep = vmnewof(mp->vm, 0, Entry_t, 1, 0);
+ while (p = sfgetr(fp, '\n', 1))
+ {
+ error_info.line++;
+ for (; isspace(*p); p++);
+
+ /*
+ * nesting
+ */
+
+ switch (*p)
+ {
+ case 0:
+ case '#':
+ cont = '#';
+ continue;
+ case '{':
+ if (++lev < MAXNEST)
+ ep->nest = *p;
+ else if ((mp->flags & MAGIC_VERBOSE) && mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 1, "{ ... } operator nesting too deep -- %d max", MAXNEST);
+ continue;
+ case '}':
+ if (!last || lev <= 0)
+ {
+ if (mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 2, "`%c': invalid nesting", *p);
+ }
+ else if (lev-- == ent)
+ {
+ ent = 0;
+ ep->cont = ':';
+ ep->offset = ret->offset;
+ ep->nest = ' ';
+ ep->type = ' ';
+ ep->op = ' ';
+ ep->desc = "[RETURN]";
+ last = ep;
+ ep = ret->next = vmnewof(mp->vm, 0, Entry_t, 1, 0);
+ ret = 0;
+ }
+ else
+ last->nest = *p;
+ continue;
+ default:
+ if (*(p + 1) == '{' || *(p + 1) == '(' && *p != '+' && *p != '>' && *p != '&' && *p != '|')
+ {
+ n = *p++;
+ if (n >= 'a' && n <= 'z')
+ n -= 'a';
+ else
+ {
+ if (mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 2, "%c: invalid function name", n);
+ n = 0;
+ }
+ if (ret && mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 2, "%c: function has no return", ret->offset + 'a');
+ if (*p == '{')
+ {
+ ent = ++lev;
+ ret = ep;
+ ep->desc = "[FUNCTION]";
+ }
+ else
+ {
+ if (*(p + 1) != ')' && mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 2, "%c: invalid function call argument list", n + 'a');
+ ep->desc = "[CALL]";
+ }
+ ep->cont = cont;
+ ep->offset = n;
+ ep->nest = ' ';
+ ep->type = ' ';
+ ep->op = ' ';
+ last = ep;
+ ep = ep->next = vmnewof(mp->vm, 0, Entry_t, 1, 0);
+ if (ret)
+ fun[n] = last->value.lab = ep;
+ else if (!(last->value.lab = fun[n]) && mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 2, "%c: function not defined", n + 'a');
+ continue;
+ }
+ if (!ep->nest)
+ ep->nest = (lev > 0 && lev != ent) ? ('0' + lev - !!ent) : ' ';
+ break;
+ }
+
+ /*
+ * continuation
+ */
+
+ cont = '$';
+ switch (*p)
+ {
+ case '>':
+ old = 1;
+ if (*(p + 1) == *p)
+ {
+ /*
+ * old style nesting push
+ */
+
+ p++;
+ old = 2;
+ if (!lev && last)
+ {
+ lev = 1;
+ last->nest = '{';
+ if (last->cont == '>')
+ last->cont = '&';
+ ep->nest = '1';
+ }
+ }
+ /*FALLTHROUGH*/
+ case '+':
+ case '&':
+ case '|':
+ ep->cont = *p++;
+ break;
+ default:
+ if ((mp->flags & MAGIC_VERBOSE) && !isalpha(*p) && mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 1, "`%c': invalid line continuation operator", *p);
+ /*FALLTHROUGH*/
+ case '*':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ ep->cont = (lev > 0) ? '&' : '#';
+ break;
+ }
+ switch (old)
+ {
+ case 1:
+ old = 0;
+ if (lev)
+ {
+ /*
+ * old style nesting pop
+ */
+
+ lev = 0;
+ if (last)
+ last->nest = '}';
+ ep->nest = ' ';
+ if (ep->cont == '&')
+ ep->cont = '#';
+ }
+ break;
+ case 2:
+ old = 1;
+ break;
+ }
+ if (isdigit(*p))
+ {
+ /*
+ * absolute offset
+ */
+
+ ep->offset = strton(p, &next, NiL, 0);
+ p2 = next;
+ }
+ else
+ {
+ for (p2 = p; *p2 && !isspace(*p2); p2++);
+ if (!*p2)
+ {
+ if ((mp->flags & MAGIC_VERBOSE) && mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 1, "not enough fields: `%s'", p);
+ continue;
+ }
+
+ /*
+ * offset expression
+ */
+
+ *p2++ = 0;
+ ep->expr = vmstrdup(mp->vm, p);
+ if (isalpha(*p))
+ ep->offset = (ip = (Info_t*)dtmatch(mp->infotab, p)) ? ip->value : 0;
+ else if (*p == '(' && ep->cont == '>')
+ {
+ /*
+ * convert old style indirection to @
+ */
+
+ p = ep->expr + 1;
+ for (;;)
+ {
+ switch (*p++)
+ {
+ case 0:
+ case '@':
+ case '(':
+ break;
+ case ')':
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ if (*--p == ')')
+ {
+ *p = 0;
+ *ep->expr = '@';
+ }
+ }
+ }
+ for (; isspace(*p2); p2++);
+ for (p = p2; *p2 && !isspace(*p2); p2++);
+ if (!*p2)
+ {
+ if ((mp->flags & MAGIC_VERBOSE) && mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 1, "not enough fields: `%s'", p);
+ continue;
+ }
+ *p2++ = 0;
+
+ /*
+ * type
+ */
+
+ if ((*p == 'b' || *p == 'l') && *(p + 1) == 'e')
+ {
+ ep->swap = ~(*p == 'l' ? 7 : 0);
+ p += 2;
+ }
+ if (*p == 's')
+ {
+ if (*(p + 1) == 'h')
+ ep->type = 'h';
+ else
+ ep->type = 's';
+ }
+ else if (*p == 'a')
+ ep->type = 's';
+ else
+ ep->type = *p;
+ if (p = strchr(p, '&'))
+ {
+ /*
+ * old style mask
+ */
+
+ ep->mask = strton(++p, NiL, NiL, 0);
+ }
+ for (; isspace(*p2); p2++);
+ if (ep->mask)
+ *--p2 = '=';
+
+ /*
+ * comparison operation
+ */
+
+ p = p2;
+ if (p2 = strchr(p, '\t'))
+ *p2++ = 0;
+ else
+ {
+ int qe = 0;
+ int qn = 0;
+
+ /*
+ * assume balanced {}[]()\\""'' field
+ */
+
+ for (p2 = p;;)
+ {
+ switch (n = *p2++)
+ {
+ case 0:
+ break;
+ case '{':
+ if (!qe)
+ qe = '}';
+ if (qe == '}')
+ qn++;
+ continue;
+ case '(':
+ if (!qe)
+ qe = ')';
+ if (qe == ')')
+ qn++;
+ continue;
+ case '[':
+ if (!qe)
+ qe = ']';
+ if (qe == ']')
+ qn++;
+ continue;
+ case '}':
+ case ')':
+ case ']':
+ if (qe == n && qn > 0)
+ qn--;
+ continue;
+ case '"':
+ case '\'':
+ if (!qe)
+ qe = n;
+ else if (qe == n)
+ qe = 0;
+ continue;
+ case '\\':
+ if (*p2)
+ p2++;
+ continue;
+ default:
+ if (!qe && isspace(n))
+ break;
+ continue;
+ }
+ if (n)
+ *(p2 - 1) = 0;
+ else
+ p2--;
+ break;
+ }
+ }
+ lge = 0;
+ if (ep->type == 'e' || ep->type == 'm' || ep->type == 's')
+ ep->op = '=';
+ else
+ {
+ if (*p == '&')
+ {
+ ep->mask = strton(++p, &next, NiL, 0);
+ p = next;
+ }
+ switch (*p)
+ {
+ case '=':
+ case '>':
+ case '<':
+ case '*':
+ ep->op = *p++;
+ if (*p == '=')
+ {
+ p++;
+ switch (ep->op)
+ {
+ case '>':
+ lge = -1;
+ break;
+ case '<':
+ lge = 1;
+ break;
+ }
+ }
+ break;
+ case '!':
+ case '@':
+ ep->op = *p++;
+ if (*p == '=')
+ p++;
+ break;
+ case 'x':
+ p++;
+ ep->op = '*';
+ break;
+ default:
+ ep->op = '=';
+ if (ep->mask)
+ ep->value.num = ep->mask;
+ break;
+ }
+ }
+ if (ep->op != '*' && !ep->value.num)
+ {
+ if (ep->type == 'e')
+ {
+ if (ep->value.sub = vmnewof(mp->vm, 0, regex_t, 1, 0))
+ {
+ ep->value.sub->re_disc = &mp->redisc;
+ if (!(n = regcomp(ep->value.sub, p, REG_DELIMITED|REG_LENIENT|REG_NULL|REG_DISCIPLINE)))
+ {
+ p += ep->value.sub->re_npat;
+ if (!(n = regsubcomp(ep->value.sub, p, NiL, 0, 0)))
+ p += ep->value.sub->re_npat;
+ }
+ if (n)
+ {
+ regmessage(mp, ep->value.sub, n);
+ ep->value.sub = 0;
+ }
+ else if (*p && mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 1, "invalid characters after substitution: %s", p);
+ }
+ }
+ else if (ep->type == 'm')
+ {
+ ep->mask = stresc(p) + 1;
+ ep->value.str = vmnewof(mp->vm, 0, char, ep->mask + 1, 0);
+ memcpy(ep->value.str, p, ep->mask);
+ if ((!ep->expr || !ep->offset) && !strmatch(ep->value.str, "\\!\\(*\\)"))
+ ep->value.str[ep->mask - 1] = '*';
+ }
+ else if (ep->type == 's')
+ {
+ ep->mask = stresc(p);
+ ep->value.str = vmnewof(mp->vm, 0, char, ep->mask, 0);
+ memcpy(ep->value.str, p, ep->mask);
+ }
+ else if (*p == '\'')
+ {
+ stresc(p);
+ ep->value.num = *(unsigned char*)(p + 1) + lge;
+ }
+ else if (strmatch(p, "+([a-z])\\(*\\)"))
+ {
+ char* t;
+
+ t = p;
+ ep->type = 'V';
+ ep->op = *p;
+ while (*p && *p++ != '(');
+ switch (ep->op)
+ {
+ case 'l':
+ n = *p++;
+ if (n < 'a' || n > 'z')
+ {
+ if (mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 2, "%c: invalid function name", n);
+ }
+ else if (!fun[n -= 'a'])
+ {
+ if (mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 2, "%c: function not defined", n + 'a');
+ }
+ else
+ {
+ ep->value.loop = vmnewof(mp->vm, 0, Loop_t, 1, 0);
+ ep->value.loop->lab = fun[n];
+ while (*p && *p++ != ',');
+ ep->value.loop->start = strton(p, &t, NiL, 0);
+ while (*t && *t++ != ',');
+ ep->value.loop->size = strton(t, &t, NiL, 0);
+ }
+ break;
+ case 'm':
+ case 'r':
+ ep->desc = vmnewof(mp->vm, 0, char, 32, 0);
+ ep->mime = vmnewof(mp->vm, 0, char, 32, 0);
+ break;
+ case 'v':
+ break;
+ default:
+ if ((mp->flags & MAGIC_VERBOSE) && mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 1, "%-.*s: unknown function", p - t, t);
+ break;
+ }
+ }
+ else
+ {
+ ep->value.num = strton(p, NiL, NiL, 0) + lge;
+ if (ep->op == '@')
+ ep->value.num = swapget(0, (char*)&ep->value.num, sizeof(ep->value.num));
+ }
+ }
+
+ /*
+ * file description
+ */
+
+ if (p2)
+ {
+ for (; isspace(*p2); p2++);
+ if (p = strchr(p2, '\t'))
+ {
+ /*
+ * check for message catalog index
+ */
+
+ *p++ = 0;
+ if (isalpha(*p2))
+ {
+ for (p3 = p2; isalnum(*p3); p3++);
+ if (*p3++ == ':')
+ {
+ for (; isdigit(*p3); p3++);
+ if (!*p3)
+ {
+ for (p2 = p; isspace(*p2); p2++);
+ if (p = strchr(p2, '\t'))
+ *p++ = 0;
+ }
+ }
+ }
+ }
+ stresc(p2);
+ ep->desc = vmstrdup(mp->vm, p2);
+ if (p)
+ {
+ for (; isspace(*p); p++);
+ if (*p)
+ ep->mime = vmstrdup(mp->vm, p);
+ }
+ }
+ else
+ ep->desc = "";
+
+ /*
+ * get next entry
+ */
+
+ last = ep;
+ ep = ep->next = vmnewof(mp->vm, 0, Entry_t, 1, 0);
+ }
+ if (last)
+ {
+ last->next = 0;
+ if (mp->magiclast)
+ mp->magiclast->next = first;
+ else
+ mp->magic = first;
+ mp->magiclast = last;
+ }
+ vmfree(mp->vm, ep);
+ if ((mp->flags & MAGIC_VERBOSE) && mp->disc->errorf)
+ {
+ if (lev < 0)
+ (*mp->disc->errorf)(mp, mp->disc, 1, "too many } operators");
+ else if (lev > 0)
+ (*mp->disc->errorf)(mp, mp->disc, 1, "not enough } operators");
+ if (ret)
+ (*mp->disc->errorf)(mp, mp->disc, 2, "%c: function has no return", ret->offset + 'a');
+ }
+ error_info.file = 0;
+ error_info.line = 0;
+ return 0;
+}
+
+/*
+ * load a magic file into mp
+ */
+
+int
+magicload(register Magic_t* mp, const char* file, unsigned long flags)
+{
+ register char* s;
+ register char* e;
+ register char* t;
+ int n;
+ int found;
+ int list;
+ Sfio_t* fp;
+
+ mp->flags = mp->disc->flags | flags;
+ found = 0;
+ if (list = !(s = (char*)file) || !*s || (*s == '-' || *s == '.') && !*(s + 1))
+ {
+ if (!(s = getenv(MAGIC_FILE_ENV)) || !*s)
+ s = MAGIC_FILE;
+ }
+ for (;;)
+ {
+ if (!list)
+ e = 0;
+ else if (e = strchr(s, ':'))
+ {
+ /*
+ * ok, so ~ won't work for the last list element
+ * we do it for MAGIC_FILES_ENV anyway
+ */
+
+ if ((strneq(s, "~/", n = 2) || strneq(s, "$HOME/", n = 6) || strneq(s, "${HOME}/", n = 8)) && (t = getenv("HOME")))
+ {
+ sfputr(mp->tmp, t, -1);
+ s += n - 1;
+ }
+ sfwrite(mp->tmp, s, e - s);
+ if (!(s = sfstruse(mp->tmp)))
+ goto nospace;
+ }
+ if (!*s || streq(s, "-"))
+ s = MAGIC_FILE;
+ if (!(fp = sfopen(NiL, s, "r")))
+ {
+ if (list)
+ {
+ if (!(t = pathpath(s, "", PATH_REGULAR|PATH_READ, mp->fbuf, sizeof(mp->fbuf))) && !strchr(s, '/'))
+ {
+ strcpy(mp->fbuf, s);
+ sfprintf(mp->tmp, "%s/%s", MAGIC_DIR, mp->fbuf);
+ if (!(s = sfstruse(mp->tmp)))
+ goto nospace;
+ if (!(t = pathpath(s, "", PATH_REGULAR|PATH_READ, mp->fbuf, sizeof(mp->fbuf))))
+ goto next;
+ }
+ if (!(fp = sfopen(NiL, t, "r")))
+ goto next;
+ }
+ else
+ {
+ if (mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 3, "%s: cannot open magic file", s);
+ return -1;
+ }
+ }
+ found = 1;
+ n = load(mp, s, fp);
+ sfclose(fp);
+ if (n && !list)
+ return -1;
+ next:
+ if (!e)
+ break;
+ s = e + 1;
+ }
+ if (!found)
+ {
+ if (mp->flags & MAGIC_VERBOSE)
+ {
+ if (mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 2, "cannot find magic file");
+ }
+ return -1;
+ }
+ return 0;
+ nospace:
+ if (mp->disc->errorf)
+ (*mp->disc->errorf)(mp, mp->disc, 3, "out of space");
+ return -1;
+}
+
+/*
+ * open a magic session
+ */
+
+Magic_t*
+magicopen(Magicdisc_t* disc)
+{
+ register Magic_t* mp;
+ register int i;
+ register int n;
+ register int f;
+ register int c;
+ register Vmalloc_t* vm;
+ unsigned char* map[CC_MAPS + 1];
+
+ if (!(vm = vmopen(Vmdcheap, Vmbest, 0)))
+ return 0;
+ if (!(mp = vmnewof(vm, 0, Magic_t, 1, 0)))
+ {
+ vmclose(vm);
+ return 0;
+ }
+ mp->id = lib;
+ mp->disc = disc;
+ mp->vm = vm;
+ mp->flags = disc->flags;
+ mp->redisc.re_version = REG_VERSION;
+ mp->redisc.re_flags = REG_NOFREE;
+ mp->redisc.re_errorf = (regerror_t)disc->errorf;
+ mp->redisc.re_resizef = (regresize_t)vmgetmem;
+ mp->redisc.re_resizehandle = (void*)mp->vm;
+ mp->dtdisc.key = offsetof(Info_t, name);
+ mp->dtdisc.link = offsetof(Info_t, link);
+ if (!(mp->tmp = sfstropen()) || !(mp->infotab = dtnew(mp->vm, &mp->dtdisc, Dtoset)))
+ goto bad;
+ for (n = 0; n < elementsof(info); n++)
+ dtinsert(mp->infotab, &info[n]);
+ for (i = 0; i < CC_MAPS; i++)
+ map[i] = ccmap(i, CC_ASCII);
+ mp->x2n = ccmap(CC_ALIEN, CC_NATIVE);
+ for (n = 0; n <= UCHAR_MAX; n++)
+ {
+ f = 0;
+ i = CC_MAPS;
+ while (--i >= 0)
+ {
+ c = ccmapchr(map[i], n);
+ f = (f << CC_BIT) | CCTYPE(c);
+ }
+ mp->cctype[n] = f;
+ }
+ return mp;
+ bad:
+ magicclose(mp);
+ return 0;
+}
+
+/*
+ * close a magicopen() session
+ */
+
+int
+magicclose(register Magic_t* mp)
+{
+ if (!mp)
+ return -1;
+ if (mp->tmp)
+ sfstrclose(mp->tmp);
+ if (mp->vm)
+ vmclose(mp->vm);
+ return 0;
+}
+
+/*
+ * return the magic string for file with optional stat info st
+ */
+
+char*
+magictype(register Magic_t* mp, Sfio_t* fp, const char* file, register struct stat* st)
+{
+ off_t off;
+ char* s;
+
+ mp->flags = mp->disc->flags;
+ mp->mime = 0;
+ if (!st)
+ s = T("cannot stat");
+ else
+ {
+ if (mp->fp = fp)
+ off = sfseek(mp->fp, (off_t)0, SEEK_CUR);
+ s = type(mp, file, st, mp->tbuf, &mp->tbuf[sizeof(mp->tbuf)-1]);
+ if (mp->fp)
+ sfseek(mp->fp, off, SEEK_SET);
+ if (!(mp->flags & (MAGIC_MIME|MAGIC_ALL)))
+ {
+ if (S_ISREG(st->st_mode) && (st->st_size > 0) && (st->st_size < 128))
+ sfprintf(mp->tmp, "%s ", T("short"));
+ sfprintf(mp->tmp, "%s", s);
+ if (!mp->fp && (st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
+ sfprintf(mp->tmp, ", %s", S_ISDIR(st->st_mode) ? T("searchable") : T("executable"));
+ if (st->st_mode & S_ISUID)
+ sfprintf(mp->tmp, ", setuid=%s", fmtuid(st->st_uid));
+ if (st->st_mode & S_ISGID)
+ sfprintf(mp->tmp, ", setgid=%s", fmtgid(st->st_gid));
+ if (st->st_mode & S_ISVTX)
+ sfprintf(mp->tmp, ", sticky");
+ if (!(s = sfstruse(mp->tmp)))
+ s = T("out of space");
+ }
+ }
+ if (mp->flags & MAGIC_MIME)
+ s = mp->mime;
+ if (!s)
+ s = T("error");
+ return s;
+}
+
+/*
+ * list the magic table in mp on sp
+ */
+
+int
+magiclist(register Magic_t* mp, register Sfio_t* sp)
+{
+ register Entry_t* ep = mp->magic;
+ register Entry_t* rp = 0;
+
+ mp->flags = mp->disc->flags;
+ sfprintf(sp, "cont\toffset\ttype\top\tmask\tvalue\tmime\tdesc\n");
+ while (ep)
+ {
+ sfprintf(sp, "%c %c\t", ep->cont, ep->nest);
+ if (ep->expr)
+ sfprintf(sp, "%s", ep->expr);
+ else
+ sfprintf(sp, "%ld", ep->offset);
+ sfprintf(sp, "\t%s%c\t%c\t%lo\t", ep->swap == (char)~3 ? "L" : ep->swap == (char)~0 ? "B" : "", ep->type, ep->op, ep->mask);
+ switch (ep->type)
+ {
+ case 'm':
+ case 's':
+ sfputr(sp, fmtesc(ep->value.str), -1);
+ break;
+ case 'V':
+ switch (ep->op)
+ {
+ case 'l':
+ sfprintf(sp, "loop(%d,%d,%d,%d)", ep->value.loop->start, ep->value.loop->size, ep->value.loop->count, ep->value.loop->offset);
+ break;
+ case 'v':
+ sfprintf(sp, "vcodex()");
+ break;
+ default:
+ sfprintf(sp, "%p", ep->value.str);
+ break;
+ }
+ break;
+ default:
+ sfprintf(sp, "%lo", ep->value.num);
+ break;
+ }
+ sfprintf(sp, "\t%s\t%s\n", ep->mime ? ep->mime : "", fmtesc(ep->desc));
+ if (ep->cont == '$' && !ep->value.lab->mask)
+ {
+ rp = ep;
+ ep = ep->value.lab;
+ }
+ else
+ {
+ if (ep->cont == ':')
+ {
+ ep = rp;
+ ep->value.lab->mask = 1;
+ }
+ ep = ep->next;
+ }
+ }
+ return 0;
+}
diff --git a/src/lib/libast/misc/magic.tab b/src/lib/libast/misc/magic.tab
new file mode 100644
index 0000000..00df074
--- /dev/null
+++ b/src/lib/libast/misc/magic.tab
@@ -0,0 +1,1721 @@
+#
+# @(#)magic (AT&T Research) 2011-11-02
+#
+# magic number database for file(1) and magic(3)
+#
+# the tab separated fields are:
+#
+# [op]offset type [mask]operator description mime
+#
+# + previous fields must match, current optional
+# & previous and current fields must match
+# { start nesting block
+# } end nesting block
+# s{ function declaration and call
+# } function return
+# s() function call
+#
+# offset byte offset for magic number test or (@offset) expr
+# or file meta-data from { atime blocks ctime fstype
+# gid mode mtime name nlink size uid }
+# type { byte short long quad date edit match }
+# mask optional &number before operator
+# operator comparison operator { < <= > >= != == (default) }
+# description file description for magic number match
+# mime optional mime type
+#
+# numeric values may be decimal, octal, or hex
+# the description string may have one printf format spec for the
+# matched magic number
+#
+
+0 short 070707 binary cpio archive application/pax
+0 string 070707 cpio archive application/pax
++76 edit %!PAX!C!\([^!]*\).*%\1% , compressed, version %s
++76 edit %!PAX!D!\([^!]*\).*%\1% , delta, version %s
++76 string DELTA!!! , delta, version 88
++76 match !(*!*) , [ %s ... ]
+0 string 070701 System V asc cpio archive application/pax
++110 string * , [ %s ... ]
+0 string 070702 System V aschk cpio archive application/pax
++110 string * , [ %s ... ]
+0 long 0177555 System III ar archive application/x-ar
+0 short 0177545 pdp11 ar archive application/x-ar
+0 long 0x04034b50 zip archive application/zip
++2 byte >0 , version %d
+&3 byte * .%d
+0 long 0x223e9f78 ms outlook tnef archive application/pax
+0 string MSCF ms cabinet archive application/pax
+&4 long 0
++25 byte * , version %d
++24 byte * .%d
+0 string \x52\x61\x72\x21\x1a\x07 rar archive application/pax
+0 long 0x0d010b05 make object application/x-nmake
+o{
++4 byte <037 (version %ld)
++4 edit %.*\(..\)/\(..\)/\(..\).*%19\3-\1-\2% , version %s
++4 edit %.*\(....-..-..\).*%\1% , version %s
+}
+0 long 0177535 make object, old magic application/x-nmake
+o()
+0 long 0x090f0301 jmake project db application/x-jmake
++4 string * , version %s
+0 long 0x0b130800 ksh binary script application/ksh
++4 byte * , version %ld
+0 string vkda delta application/x-vdelta
++4 byte >0 (version %ld)
+0 long 0x03040200 cql db application/x-cql
++4 byte * , version %d
++5 byte * .%d
++6 string * , %s
+0 string !<cdb-
++6 edit %\([^-]*\)-\([0-9.]*\)>.*%cql db, \1 format, version \2% %s application/x-cql
+0 long 0x08091800
++32 string * %s application/x-cql
++0 byte * hashed index
++4 long >0 , %d record%s
++8 long >0 , %d max
++12 date >0 , stamp %s
+0 string \1S\1B\1C\1S sbcs delta application/x-sbcs
+0 long 0100554 apl workspace application/x-apl
+0 short 017037 packed data application/zip
+0 string <ar> System V 1.0 ar archive application/x-ar
+0 string !<arch>\n/ ar library application/x-ar
++68 long 0x020b0619 , hp s800 relocatable
++68 long 0x02100619 , hp pa-risc 1.1 relocatable
++68 long 0x02110619 , hp pa-risc 1.2 relocatable
++68 long 0x02140619 , hp pa-risc 2.0 relocatable
+0 string !<arch>\n__.SYMDEF ar library, ranlib application/x-ar
+0 string !<arch>\n__________E ar library, hybrid application/x-ar
+0 string !<arch>\n_______[0-9_][0-9_][0-9_]E[BL]E[BL]_ ar library, hybrid application/x-ar
+o{
++22 byte 'X' , out of date
++20 byte 'U' , ucode members
++21 byte >='A' , %c-endian members
++19 byte >='A' , %c-endian hash
+}
+0 string !<arch>\n________64E ar library, 64 bit hybrid application/x-ar
+o()
+0 string !<arch> ar archive application/x-ar
+0 string <aiaff>\n aix ar library application/x-ar
+0 string <bigaf>\n aix ar library, big application/x-ar
+20 short 0xa7dc zoo archive application/x-zoo
+&22 short 0xfdc4
++32 byte * , version %ld
++33 byte * .%ld
+
+0 string \326\303\304\330 vcodex data application/x-vczip
++5 void vcodex()
+
+0 long 0x080456
+{
+85 byte <10 sun
++85 byte <3 m680%d0
++85 byte 3 sparc
++85 byte >3 *unknown*
+}
++85 byte * core dump x-system/core
++128 string * from `%s'
++132 string * from `%s'
+0 long 050632 core dump x-system/core
+0 long &0xfff00000==0xe8c00000 Alliant core dump
++160 string * from `%s'
+
+0 long 0x02100106 hp pa-risc 1.1 object x-system/obj
+0 long 0x02100107 hp pa-risc 1.1 executable x-system/exe
+o{
++(@144) long 0x054ef630 , dynamically linked
++96 long >0 , not stripped
+}
+0 long 0x02100108 hp pa-risc 1.1 executable, shared x-system/exe
+o()
+0 long 0x0210010b hp pa-risc 1.1 executable, demand-load x-system/exe
+o()
+0 long 0x0210010e hp pa-risc 1.1 shared library x-system/dll
+o()
+0 long 0x0210010d hp pa-risc 1.1 shared library x-system/dll
+s{
++96 long >0 , not stripped
+}
+
+0 long 0x02140106 hp pa-risc 2.0 object x-system/obj
+0 long 0x02140107 hp pa-risc 2.0 executable x-system/exe
+o()
+0 long 0x02140108 hp pa-risc 2.0 executable, shared x-system/exe
+o()
+0 long 0x0214010b hp pa-risc 2.0 executable, demand-load x-system/exe
+o()
+0 long 0x0214010e hp pa-risc 2.0 shared library x-system/dll
+o()
+0 long 0x0214010d hp pa-risc 2.0 shared library x-system/dll
+s()
+
+0 long 0x020b0106 hp s800 object x-system/obj
+0 long 0x020b0107 hp s800 executable x-system/exe
+o()
+0 long 0x020b0108 hp s800 executable, shared x-system/exe
+o()
+0 long 0x020b010b hp s800 executable, demand-load x-system/exe
+o()
+0 long 0x020b010d hp s800 shared library x-system/dll
+s()
+0 long 0x020b010e hp s800 shared library x-system/dll
+s()
+
+0 long 0x02080108 hp s500 executable, pure x-system/exe
+o{
++16 long >0 , version %ld
+}
+0 long 0x02080107 hp s500 executable x-system/exe
+o()
+0 long 0x02080106 hp s500 executable, relocatable x-system/obj
+o()
+0 long 0x020c0108 hp s200 executable, pure x-system/exe
+o{
++36 long >0 , not stripped
++4 short >0 , version %ld
+}
+0 long 0x020c0107 hp s200 executable x-system/exe
+o()
+0 long 0x020c010b hp s200 executable, demand-load x-system/exe
+o()
+0 long 0x020a0108 hp s200 2.x executable, pure x-system/exe
+o()
+0 long 0x020a0107 hp s200 2.x executable x-system/exe
+o()
+0 long 0x020c0106 hp s200 executable, relocatable x-system/exe
++4 short >0 , version %ld
+0 long 0x0208ff65 hp s500 old archive application/x-ar
+0 long 0x020cff65 hp s200 old archive application/x-ar
+0 long 0x020aff65 hp s200 old archive application/x-ar
+0 short 0x8000 hp lif file
+0 long 0x020c010c hp compiled Lisp
+0 long 0x4da7eee8 hp windows font
++8 byte >0 , version %ld
+
+0 string Joy!peffpwpc PowerPC executable
+0 short 0x01df PowerPC object x-system/obj
+&3 byte 3
+
+0 long 0x50900107 pyramid 90x executable x-system/exe
+o{
++0 long &0x7=0x3 , paged
++0 long &0x8 , pure
++16 long >0 , not stripped
+}
+0 long 0x50900108 pyramid 90x object x-system/obj
+0 long 0x5090010b pyramid 90x executable x-system/exe
+o()
+
+0 long 0x000001EB plan9 386 executable x-system/exe
+0 long 0x00000107 plan9 68020 executable x-system/exe
+&mode long &0111!=0
+0 long 0x00000197 plan9 hobbit executable x-system/exe
+0 long 0x00000407 plan9 mips executable x-system/exe
+0 long 0x000002AB plan9 sparc executable x-system/exe
+
+0 long 0x7E004501 plan9 386 object x-system/obj
+0 long 0x4D013201 plan9 68020 object x-system/obj
+0 long 0x430D013C plan9 hobbit object x-system/obj
+0 long 0x3A11013C plan9 mips object x-system/obj
+0 long 0x7410013C plan9 sparc object x-system/obj
+
+0 long &0x0030FFFF==0x00000064 linux 386
+&0 long &0x000F0000>0
++20 long &0xEFDFFFFF==0 executable x-system/exe
++20 long &0xEFDFFFFF!=0 shared library x-system/dll
++0 long 0x01080064 , pure
++0 long 0x010B0064 , paged
++0 long 0x00CC0064 , paged, no page 0
+{
+20 long &0xEFDFFFFF==0
+&16 long >0 , not stripped
+}
+216 long 0421 linux core dump x-system/core
+
+0 long 0x00cc0064 linux 386 kernel code x-system/exe
++size long <600000 , compressed
+510 short 0xaa55 linux 386 kernel image x-system/exe
++size long <600000 , compressed
+0 long 0x03010410 minix 386 executable x-system/exe
+0 long 0x000186a3 minix 386 object x-system/obj
+
+0 long 0314 bsd 386 executable, paged, no page 0 x-system/exe
++16 long >0 , not stripped
+0 long 0407 bsd 386 executable x-system/exe
+&mode long &0111!=0
++16 long >0 , not stripped
+0 long 0407 bsd-or-linux 386 object x-system/obj
+0 long 0410 bsd 386 executable, pure x-system/exe
++16 long >0 , not stripped
+0 long 0413 bsd 386 executable, paged x-system/exe
++16 long >0 , not stripped
+
+0 belong 0xcafebabe java object x-java/obj
+&4 belong >30
++6 beshort * version %d
++6 beshort * .%d
+
+a{
++4 long &0x00ffffff=1 vax
++4 long &0x00ffffff=2 romp
++4 long &0x00ffffff=3 architecture=%ld
++4 long &0x00ffffff=4 ns32032
++4 long &0x00ffffff=5 ns32332
++4 long &0x00ffffff=6 m68k
++4 long &0x00ffffff=7 i386
++4 long &0x00ffffff=8 mips
++4 long &0x00ffffff=9 ns32532
++4 long &0x00ffffff=10 architecture=%ld
++4 long &0x00ffffff=11 hp pa-risc
++4 long &0x00ffffff=12 acorn
++4 long &0x00ffffff=13 m88k
++4 long &0x00ffffff=14 sparc
++4 long &0x00ffffff=15 i860-big
++4 long &0x00ffffff=16 i860
++4 long &0x00ffffff=17 rs6000
++4 long &0x00ffffff=18 powerpc
++4 long &0x00ffffff>=19 architecture=%ld
++4 long &0x01000000!=0 \b-64
+}
+
+0 belong 0xcafebabe universal binary [
++4 belong loop(a,4,20)
++4 belong * ]
++010000 void magic()
++0 void * ...
+
+0 long &0xfffffffe=0xfeedface mach-o
++0 long &0x00000001!=0 64-bit
+a()
++12 long <=0 filetype=%ld
+{
+12 long 1 relocatable x-system/obj
+&mode long &0111!=0
+}
+{
+12 long 1 object x-system/obj
+&mode long &0111==0
+}
++12 long 2 executable x-system/exe
++12 long 3 fixed vm shared library x-system/dll
++12 long 4 core x-system/core
++12 long 5 preload executable x-system/exe
++12 long 6 shared library x-system/dll
++12 long 7 dynamic link editor x-system/exe
++12 long 8 bundle x-system/dll
++12 long >=9 filetype=%ld
+
+2 short 0407
+m{
+1 byte <10 sun
++1 byte <3 m680%d0
++1 byte 3 sparc
++1 byte >3 *unknown*
+}
++0 byte !=0xffffffff object x-system/obj
+2 short 0410
+m()
++0 byte !=0xffffffff executable, pure x-system/exe
+o{
+{
+0 byte &0200
+&20 long >=0x2000 , dynamically linked
+}
++16 long >0 , not stripped
+}
+2 short 0413
+m()
+{
+0 byte &0200
+&20 long <0x2000 shared library x-system/dll
+}
++0 byte !=0xffffffff executable, paged x-system/exe
+o()
+
+0 short 0420 Alliant virtual executable x-system/exe
++16 long >0 , not stripped
+o{
++2 short &0x0001 , 68020 only
++2 short &0x0002 , vector instructions
++2 short &0x0008 , IP only
++2 short &0x0010 , CE only
++2 short &0x0020 , common library
++2 short &0x0200 , no complex
+}
+0 short 0421 Alliant object x-system/obj
++16 long 0 , no symbols
+o()
+
+0 short 0x01df aix RISC
+{
+18 short &0x2002==0x0002 executable x-system/exe
++18 short &0x1000 , dynamically linked
++12 long >0 , not stripped
+}
++18 short &0x2002==0 object x-system/obj
++18 short &0x2000 shared library x-system/dll
+0 short 0x0103 aix RT executable x-system/exe
++2 byte 0x50 , pure
++28 long >0 , not stripped
++6 short >0 , version %ld
+0 short 0x0104 aix shared library x-system/dll
+0 short 0x0105 aix ctab data
+0 short 0xfe04 aix structured file
+
+0 short 0401 unix-rt ldp
+0 short 0405 old overlay
+0 short 0437 pdp11 kernel overlay
+
+0 short 0407 System III executable x-system/exe
+o{
++16 long >0 , not stripped
++2 short >0 , version %ld
+}
+0 short 0410 System III executable, pure x-system/exe
+o()
+0 short 0411 System III executable, separate I&D x-system/exe
+o()
+
+0 long 0407 vax object x-system/obj
+0 long 0410 vax executable, pure x-system/exe
+o{
++16 long >0 , not stripped
+}
+0 long 0413 vax executable, paged x-system/exe
+o()
+
+0 short 0413 vax executable, pure x-system/exe
++8 short >0 , not stripped
++15 byte >0 , version %ld
+
+0 short 0570 vax
+o{
+{
+16 short >0 executable x-system/exe
++12 long >0 , not stripped
++22 short >0 , version %ld
+}
++16 short 0 object x-system/obj
+}
+0 short 0575 vax
+o()
+0 short 0502 basic-16
+o()
+0 short 0503 basic-16 (TV)
+o()
+0 short 0510 x86
+o()
+0 short 0511 x86 (TV)
+o()
+0 short 0550 3b20
+o()
+0 short 0551 3b20d (TV)
+o()
+
+0 long 0x464c457f elf
+&4 byte <2
+&5 byte 1
+o{
+{
++18 short 0 machine=UNKNOWN
++18 short 1 3b
++18 short 2 sparc
++18 short 3 i386
++18 short 4 m68k
++18 short 5 m88k
++18 short 6 i486
++18 short 7 i860
+{
+18 short 8
+{
+36 long &0xf00000f0==0x00000000
++4 byte 1 mips2
++4 byte 2 mips4
+}
++36 long &0xf0000000==0x10000000 mips2
++36 long &0xf0000000==0x20000000 mips3
++36 long &0xf0000000==0x30000000 mips4
++36 long &0xf00000f0==0x00000040 mips4
++36 long &0xf0000000==0x40000000 mips5
++36 long &0xf0000000==0x50000000 mips6
++36 long &0xf0000000==0x60000000 mips7
++36 long &0xf0000000==0x70000000 mips8
++36 long &0xf0000000==0x80000000 mips9
+}
++18 short 9 amdahl
++18 short 10 mips_le
++18 short 11 rs6000
++18 short 15 pa
++18 short 16 n-cube
++18 short 17 fujitsu500
++18 short 18 sparc32+
++18 short 20 powerpc
++18 short 21 powerpc-64
++18 short 22 s390
++18 short 23 cell-BE
++18 short 36 nec-v800
++18 short 37 fujitsu-fr20
++18 short 38 trw-rh32
++18 short 39 fujitsu-mma
++18 short 40 arm
++18 short 41 alpha
++18 short 42 hitachi-sh
++18 short 43 sparc64-v9
++18 short 44 siemens-tricore
++18 short 45 argonaut
++18 short 46 hitachi-h8/300
++18 short 47 hitachi-h8/300h
++18 short 48 hitachi-h8s
++18 short 49 hitachi-h8/500
++18 short 50 itanium
++18 short 51 mips-x
++18 short 52 motorola-coldfire
++18 short 53 motorola-m68hc12
++18 short 54 fujutsu-mma
++18 short 55 siemens-pcp
++18 short 56 sony-ncpu
++18 short 57 denso-ndr1
++18 short 58 motorola-startcore
++18 short 59 toyota-me16
++18 short 60 stm-st100
++18 short 61 alc-tinyj
++18 short 62 x86-64
++18 short 63 sony-dsp
++18 short 66 siemens-fx66
++18 short 67 stm-st9-16
++18 short 68 stm-st7-8
++18 short 69 motorola-mc68hc16
++18 short 70 motorola-mc68hc11
++18 short 71 motorola-mc68hc08
++18 short 72 motorola-mc68hc05
++18 short 73 sgi-svx
++18 short 74 stm-st19-8
++18 short 75 vax
++18 short 76 axis, 32-bit
++18 short 77 infineon-javelin-32
++18 short 78 element-14-firepath-64
++18 short 79 lsi-zsp-16
++18 short 80 knuth-mmix-64
++18 short 81 harvard-huany
++18 short 82 sitera-prism
++18 short 83 amtel-avr-8
++18 short 84 fujitsu-fr30
++18 short 85 mitsubishi-d10v
++18 short 86 mitsubishi-d30v
++18 short 87 nec-v850
++18 short 88 matsushita-m32r
++18 short 89 matsushita-mn10300
++18 short 90 matsushita-mn10200
++18 short 91 picojava
++18 short 92 openrisc-32
++18 short 93 arc-tangent-a5
++18 short 94 tensilica-xtensa
++18 short 0x9026 alpha
++18 short 0xa390 s390
+|18 short * machine=0x%04lX
+}
++16 short 0 type=UNKNOWN
++16 short 1 object x-system/obj
++16 short 2 executable x-system/exe
++16 short 3 shared library x-system/dll
+{
+16 short 4 core dump x-system/core
++(@28+@42H*@44H+104) string * from `%s'
+}
++16 short >4 type=%d
++4 byte 0 , 16-bit
++4 byte 1 , 32-bit
++5 byte 1 , little-endian
+{
+18 short ==8
+&36 long &0x000000f0==0x00000000
+&4 byte 1 , old
+}
+{
+18 short 1
++36 long 1 , mau
+}
++20 long >1 , version %ld
+{
+16 short 2
+&(@28+4*32) long 2 , dynamically linked
+}
+}
+
+0 long 0x7f454c46 elf
+&4 byte 1
+&5 byte 2
+o()
+
+0 long 0x464c457f elf
+&4 byte 2
+&5 byte 1
+o{
+{
++18 short 0 machine=UNKNOWN
++18 short 1 3b
++18 short 2 sparc
++18 short 3 i386
++18 short 4 m68k
++18 short 5 m88k
++18 short 6 i486
++18 short 7 i860
+{
+18 short 8
+{
+48 long &0xf00000f0==0x00000000
++4 byte 1 mips2
++4 byte 2 mips4
+}
++48 long &0xf0000000==0x10000000 mips2
++48 long &0xf0000000==0x20000000 mips3
++48 long &0xf0000000==0x30000000 mips4
++48 long &0xf00000f0==0x00000040 mips4
++48 long &0xf0000000==0x40000000 mips5
++48 long &0xf0000000==0x50000000 mips6
++48 long &0xf0000000==0x60000000 mips7
++48 long &0xf0000000==0x70000000 mips8
++48 long &0xf0000000==0x80000000 mips9
+}
++18 short 9 amdahl
++18 short 10 mips_le
++18 short 11 rs6000
++18 short 15 pa
++18 short 16 n-cube
++18 short 17 fujitsu500
++18 short 18 sparc32+
++18 short 20 powerpc
++18 short 21 powerpc-64
++18 short 22 s390
++18 short 23 cell-BE
++18 short 36 nec-v800
++18 short 37 fujitsu-fr20
++18 short 38 trw-rh32
++18 short 39 fujitsu-mma
++18 short 40 arm
++18 short 41 alpha
++18 short 42 hitachi-sh
++18 short 43 sparc64-v9
++18 short 44 siemens-tricore
++18 short 45 argonaut
++18 short 46 hitachi-h8/300
++18 short 47 hitachi-h8/300h
++18 short 48 hitachi-h8s
++18 short 49 hitachi-h8/500
++18 short 50 itanium
++18 short 51 mips-x
++18 short 52 motorola-coldfire
++18 short 53 motorola-m68hc12
++18 short 54 fujutsu-mma
++18 short 55 siemens-pcp
++18 short 56 sony-ncpu
++18 short 57 denso-ndr1
++18 short 58 motorola-startcore
++18 short 59 toyota-me16
++18 short 60 stm-st100
++18 short 61 alc-tinyj
++18 short 62 x86-64
++18 short 63 sony-dsp
++18 short 66 siemens-fx66
++18 short 67 stm-st9-16
++18 short 68 stm-st7-8
++18 short 69 motorola-mc68hc16
++18 short 70 motorola-mc68hc11
++18 short 71 motorola-mc68hc08
++18 short 72 motorola-mc68hc05
++18 short 73 sgi-svx
++18 short 74 stm-st19-8
++18 short 75 vax
++18 short 76 axis-32
++18 short 77 infineon-javelin-32
++18 short 78 element-14-firepath-64
++18 short 79 lsi-zsp-16
++18 short 80 knuth-mmix-64
++18 short 81 harvard-huany
++18 short 82 sitera-prism
++18 short 83 amtel-avr-8
++18 short 84 fujitsu-fr30
++18 short 85 mitsubishi-d10v
++18 short 86 mitsubishi-d30v
++18 short 87 nec-v850
++18 short 88 matsushita-m32r
++18 short 89 matsushita-mn10300
++18 short 90 matsushita-mn10200
++18 short 91 picojava
++18 short 92 openrisc-32
++18 short 93 arc-tangent-a5
++18 short 94 tensilica-xtensa
++18 short 0x9026 alpha
++18 short 0xa390 s390
+|18 short * machine=0x%04lX
+}
++16 short 0 type=UNKNOWN
++16 short 1 object x-system/obj
++16 short 2 executable x-system/exe
++16 short 3 shared library x-system/dll
+{
+16 short 4 core dump x-system/core
++(@28+@42H*@44H+104) string * from `%s'
+}
++16 short >4 type=%ld
++4 byte 2 , 64-bit
++5 byte 1 , little-endian
++20 long >1 , version %ld
+{
+16 short 2
++(@32Q+3*56) long 2 , dynamically linked
++(@32Q+4*56) long 2 , dynamically linked
+}
+}
+
+0 long 0x7f454c46 elf
+&4 byte 2
+&5 byte 2
+o()
+
+0 lelong 000000407 netbsd little-endian object x-system/obj
++16 lelong 0 , stripped
+0 belong 000000407 netbsd big-endian object x-system/obj
++16 belong 0 , stripped
+
+0 belong&0377777777 041400413 netbsd i386
+d{
+0 byte &0x80
++20 lelong <4096 shared library x-system/dll
++20 lelong >=4096 executable, dynamically linked x-system/exe
+}
++0 byte ^0x80 executable x-system/exe
++16 lelong 0 , stripped
+0 belong&0377777777 041400410 netbsd i386 pure
+p{
++0 byte &0x80 executable, dynamically linked x-system/exe
++0 byte ^0x80 executable x-system/exe
++16 lelong 0 , stripped
+}
+0 belong&0377777777 041400407 netbsd i386
+n{
++0 byte &0x80 executable, dynamically linked, impure x-system/exe
+{
+0 byte ^0x80
++0 byte &0x40 position independent
++20 lelong !0 executable x-system/exe
++20 lelong =0 object x-system/obj
+}
++16 lelong 0 , stripped
+}
+0 belong&0377777777 041400507 netbsd i386 core
+c{
++12 string * from '%s' x-system/core
+}
+
+0 belong&0377777777 042000413 netbsd m68k4k
+d()
+0 belong&0377777777 042000410 netbsd m68k4k pure
+p()
+0 belong&0377777777 042000407 netbsd m68k4k
+n()
+0 belong&0377777777 042000507 netbsd m68k4k core
+c()
+
+0 belong&0377777777 042200413 netbsd ns32532
+d()
+0 belong&0377777777 042200410 netbsd ns32532 pure
+p()
+0 belong&0377777777 042200407 netbsd ns32532
+n()
+0 belong&0377777777 042200507 netbsd ns32532 core
+c()
+
+0 belong&0377777777 042600413 netbsd pmax
+d()
+0 belong&0377777777 042600410 netbsd pmax pure
+p()
+0 belong&0377777777 042600407 netbsd pmax
+n()
+0 belong&0377777777 042600507 netbsd pmax core
+c()
+
+0 belong&0377777777 043000413 netbsd vax 1k
+d()
+0 belong&0377777777 043000410 netbsd vax 1k pure
+p()
+0 belong&0377777777 043000407 netbsd vax 1k
+n()
+0 belong&0377777777 043000507 netbsd vax 1k core
+c()
+
+0 belong&0377777777 045400413 netbsd vax 4k
+d()
+0 belong&0377777777 045400410 netbsd vax 4k pure
+p()
+0 belong&0377777777 045400407 netbsd vax 4k
+n()
+0 belong&0377777777 045400507 netbsd vax 4k core
+c()
+
+0 belong&0377777777 041600413 netbsd m68k
+d{
+0 byte &0x80
++20 belong <8192 shared library x-system/dll
++20 belong >=8192 executable, dynamically linked x-system/exe
+}
++0 byte ^0x80 executable x-system/exe
++16 belong 0 , stripped
+0 belong&0377777777 041600410 netbsd m68k pure
+p()
+0 belong&0377777777 041600407 netbsd m68k
+n()
+0 belong&0377777777 041600507 netbsd m68k core
+c()
+0 belong&0377777777 042400413 netbsd sparc
+d()
+
+0 belong&0377777777 042400410 netbsd sparc pure
+p()
+0 belong&0377777777 042400407 netbsd sparc
+n()
+0 belong&0377777777 042400507 netbsd sparc core
+c()
+
+0 belong&0377777777 043400413 netbsd mips
+d()
+0 belong&0377777777 043400410 netbsd mips pure
+p()
+0 belong&0377777777 043400407 netbsd mips
+n()
+0 belong&0377777777 043400507 netbsd mips core
+c()
+
+0 belong&0377777777 043600413 netbsd arm32
+d()
+0 belong&0377777777 043600410 netbsd arm32 pure
+p()
+0 belong&0377777777 043600407 netbsd arm32
+n()
+0 belong&0377777777 043600507 netbsd arm32 core
+c()
+
+0 lelong 0x00070185 ECOFF netbsd alpha binary
++10 leshort 0x0000 , stripped x-system/obj
+0 belong&0377777777 043200507 netbsd alpha core
+c()
+
+0 short 0560 3b
+{
+16 short >0 executable x-system/exe
++12 long >0 , not stripped
+}
++16 short 0 object x-system/obj
++18 short &010000 , paging 3b2/300
++18 short &020000 , 32100
++18 short &040000 , mau
+{
+16 short >0
++20 short 0443 , shared library x-system/dll
++20 short 0410 , swapped
++20 short 0413 , paged
++22 short >0 , version %ld
+}
+0 short 0561 3b (TV)
+{
+16 short >0 executable x-system/exe
++12 long >0 , not stripped
+}
++16 short 0 object x-system/obj
++18 short &020000 , 32100 required
++18 short &040000 , mau hardware required
+
+0 short 0512 pc 286 small model (COFF)
+o{
+{
+16 short >0 executable x-system/exe
++12 long >0 , not stripped
+}
++16 short 0 object x-system/obj
+{
+16 short >0
+&22 short >0 , version %ld
+}
+}
+0 short 0522 pc 286 large model (COFF)
+o()
+
+0 short 0514 pc 386
+o{
+{
+16 short >0 executable x-system/exe
++12 long >0 , not stripped
+}
++16 short 0 object x-system/obj
+{
+16 short >0
+&22 short >0 , version %ld
+}
++0 short !=0x8664 , 32 bit
++0 short 0x8664 , 64 bit
+}
+0 short 0x8664 pc 386
+o()
+0 short 0524 pc 386
+o()
+0 short 0604 pc alpha
+o()
+
+0 short 0520 m68k
+{
+16 short >0 executable x-system/exe
++12 long >0 , not stripped
+}
++16 short 0 object x-system/obj
+{
+16 short >0
++20 short 0410 , pure
++20 short 0413 , paged
++22 short >0 , version %ld
+}
+
+0 short 0521 m68k executable, shared x-system/exe
+o{
++12 long >0 , not stripped
+}
+0 short 0522 m68k executable, shared, paged x-system/exe
+o()
+
+0 long 0x02c5e2c4 mvs OpenEdition object x-system/obj
+&4 long 0x40404040
+0 long 0xc9c5e6d7 mvs OpenEdition executable x-system/exe
+&4 long 0xd3d4c840
+
+0 short 0530 u370 5.2/5.0
+o{
+{
+20 long !=0440
+&18 short &01 executable x-system/exe
++0 short &01==0 , pure
++12 long >0 , not stripped
+}
++20 long 0440 shared library x-system/dll
++18 short &01==0 object x-system/obj
++18 byte &0x40 , BIG
++49 byte &0xf!=0 , pre-XA
+{
+18 short &01
++24 long >0 , version %ld
+}
+}
+0 short 0531 amdahl 5.2
+o()
+0 short 0534 amdahl 5.2
+o()
+0 short 0535 u370 5.2
+o()
+
+0 short 0700 ncr tower32
+o{
++18 short &0040000 68000
++18 short &0040000==0 68020
++18 short &0020000 \b+68881
+{
+18 short &0000001==0 object x-system/obj
++22 short >0 , version %ld
+}
+{
+18 short &0001 executable x-system/exe
++20 short 0413 , paged
++20 short 0443 shared library x-system/dll
++20 short 0410 , pure, swapped
++20 short 0407 , swapped
++12 long >0 , not stripped
+}
+}
+0 short 0720 ncr towe32r/600
+o()
+0 short 0740 ncr tower32/800
+o()
+0 short 0610 ncr tower/XP rel 2
+o()
+0 short 0615 ncr tower/XP rel 2
+o()
+0 short 0620 ncr tower/XP rel 3
+o()
+0 short 0625 ncr tower/XP rel 3
+o()
+0 short 0630 ncr tower32/600/400
+o()
+0 short 0640 ncr tower32/800
++18 short &00040000 compatible
+o()
+0 short 0645 ncr tower32/800 68010
+o()
+
+0 short 0457 DG MV pure executable x-system/exe
++40 long >0 , not stripped
++2 short >0 , version %ld
+0 short 0460 DG MV object x-system/obj
++2 short >0 , version %ld
+0 short 0541 m88k pure executable x-system/exe
++12 long >0 , not stripped
++22 short >0 , version %ld
+0 short 0555 m88k object x-system/obj
++22 short >0 , version %ld
+
+0 short &0xfffd==0x0160 mips
+{
+18 short &02 executable x-system/exe
++20 short 0410 , pure
++20 short 0413 , paged
++20 short 0443 , shared library x-system/dll
++8 long !=0 , not stripped
+}
++18 short &02==0 object x-system/obj
+o{
++0 short &0x2 , little-endian
++22 byte * , version %ld
++23 byte * .%ld
+}
+0 short &0xfffd==0x180 mips ucode x-system/obj
+o()
+0 long 0xdeadadb0 mips core dump x-system/core
+f{
++4 long 1
+&16 string * from `%s'
++0 long &0xff==0xb0 , 32-bit, old
++0 long &0xff==0xbb , 32-bit
++0 long &0xff==0x40 , 64-bit
+}
+0 long 0xbabec0bb mips core dump x-system/core
+f()
+0 long 0xdeadad40 mips core dump x-system/core
+f()
+
+0 short 0603 alpha
+{
+22 short &02
+&22 short &030000!=020000 executable x-system/exe
++24 short 0410 , pure
++24 short 0413 , paged
++22 short &020000 , dynamically linked
++16 long !=0 , not stripped
+}
++22 short &030000==020000 shared library x-system/dll
+{
+22 short &030002==0
++24 short 0407 object x-system/obj
+}
++27 byte * , version %ld
++26 byte * .%ld
+
+0 short 0432 compiled terminfo entry
+0 short 0433 curses screen image
+0 short 0434 curses screen image
+
+0 long 0x14031008 tcpdump cons headers application/x-tcpdump
+v{
++4 long >0 , version %d
+&8 long * .%d
+}
+0 long 0x14031004 tcpdump cons data application/x-tcpdump
+v()
+
+257 string ustar pax archive application/pax
+&156 match [gx]
+o{
+&99 byte 0
+&100 match +([ 0-7])?
+}
+
+257 string ustar\ \ gnu tar archive application/pax
+o{
+&99 byte 0
+&100 match +([ 0-7])?
++0 match ???* , [ %s ... ]
+}
+
+257 string ustar tar archive application/pax
+o()
+
+99 byte 0 old tar archive application/pax
+o()
+
+0 string \301\304\331\100\323\311\302\331\306 ca librarian archive application/pax
+
+0 match <[hH][tT][mM][lL]> html input text/html
+0 match <!?(--)[Dd][Oo][Cc][Tt][Yy][Pp][Ee] [Hh][Tt][Mm][Ll] html input text/html
+
+0 long 0x02f78301
++16 string TeX TeX dvi output application/x-dvi
+
+0 byte 0201 shell history application/sh
+&1 byte <07 version %d
+
+0 byte 1
+&1 byte 0150
+&2 match [0-9][0-9][0-9][0-9][0-9] sccs application/x-sccs
+
+0 short 0x5a4d
+o{
+&24 short 0x0040
+{
++(@60H) short 0x454c os/2 linear
++(@60H) short 0x454e os/2
++(@60H) short 0x4550 win32
++(@60H+4) short 0x014c 386
++(@60H+4) short 0x0150 powerpc
++(@60H+4) short 0x0162 mips
++(@60H+4) short 0x0166 mips, big endian?
++(@60H+4) short 0x0184 alpha
++(@60H+4) short 0x8664 386
+|(@60H+4) short * machine=0x%04lX
+}
++(@60H+22) short &0x2002==0x0002 executable x-system/exe
++(@60H+22) short &0x2000 shared library x-system/dll
++(@60H+22) short &0x0120==0 , 16 bit
++(@60H+22) short &0x0120==0x0100 , 32 bit
++(@60H+22) short &0x0120==0x0020 , 64 bit
++(@60H+92) short 0 , unknown subsystem
++(@60H+92) short 1 , native
++(@60H+92) short 2 , windows gui
++(@60H+92) short 5 , os2
++(@60H+92) short 7 , posix
++(@60H+92) short >7 , subsystem %d
++50 string PKWARE , self extracting zip
++36 string LHA's , self extracting lha
++233 string PKSFX2 , self extracting zip
+}
+
+0 short 0x5a4c
+o()
+
+0 long 0x4c000000
+&4 long 0x01140200 windows shortcut application/x-windows-lnk
+
+0 string PMCC windows GRP application/dos-grp
+369 string MICROSOFT windows PIF application/dos-pif
+0 long 0xffffffff dos device driver application/dos-drv
+&name match *.(SYS|sys)
+0 string LZ dos builtin
+0 byte 0xe9 dos executable, COM application/x-dos
+0 byte 0xeb dos executable, COM application/x-dos
+0 byte 0xf0 dos library application/x-ar
+0 byte 0x80 dos object, OMF application/dos-omf
+
+0 match x[ ]T[ ] ditroff application/x-ditroff
+&4 string * for %s
+0 string %! postscript input application/postscript
+{
+2 string PS-Adobe- , conforming
++11 match +([0-9]).+([0-9]) , version %s
+}
+0 string %PDF adobe acrobat file application/x-pdf
++5 match +([0-9]).+([0-9]) , version %s
+0 string @document( imagen input
+
+0 long 0x2e736e64 audio data audio/basic
+o{
++12 long 1 , 8-bit u-law
++12 long 2 , 8-bit linear pcm
++12 long 3 , 16-bit linear pcm
++12 long 4 , 24-bit linear pcm
++12 long 5 , 32-bit linear pcm
++12 long 6 , 32-bit floating point
++12 long 7 , 64-bit floating point
++12 long 23 , compressed (G.721 ADPCM)
++20 long =1 , mono
++20 long =2 , stereo
++20 short =3 , 3 channels
++20 short =4 , quad
++20 short >4 , %d channel%s
++16 long * , %d hz
+}
+0 long 0x0064732E dec audio data audio/x-dec
+o()
+
+0 string Creative\ Voice\ File soundblaster audio data audio/x-soundblaster
+0 long 0x4e54524b multitrack audio data file audio/x-multitrack
++4 long * , version %ld
+
+0 string MThd standard midi data audio/midi
++9 byte >0 , format %d
++11 byte >1 , %d channel%s
+0 string CTMF creative music data
+0 string SBI soundblaster instrument data
+0 string Creative\ Voice\ File creative labs voice data
+&19 byte 0x1A
++23 byte >0 , version %d
++22 byte >0 \b.%d
+
+0 string RIFF riff audio data audio/riff
++8 string AIFF aiff format
++8 string AIFC aiff-c format
++8 string WAVE , wave format
++8 string 8SVX 8svx format
++34 leshort >0 , %d bit
++22 leshort =1 , mono
++22 leshort =2 , stereo
++22 leshort =3 , 3 channels
++22 leshort =4 , quad
++22 leshort >4 , %d channel%s
++24 lelong >0 , %d hz
+
+8 long 0x41494646 aiff audio data audio/aiff
+8 long 0x41494643 aiff-C audio data audio/aiff
+0 long 0x4e54524b multitrack audio data audio/multitrack
+
+0 string ;vdb;ciao ciao virtual database application/x-ciao
+0 string ;vdb; vdb archive application/pax
++5 string * , %s
+
+0 string #pragma pp:checkpoint preprocessor checkpoint application/x-libpp
++22 edit %"\([^"]*\)".*%\1% , version %s
+
+#
+# pc application files
+#
+
+0 string HDR*PowerBuilder power builder library application/x-powerbuilder
++18 edit %\([0-9][0-9]\)\([0-9][0-9]\).*%\1.\2% , version %s
+
+#
+# database files
+#
+
+0 long 0x13579ace dbm 1.x database application/x-dbm
+0 string GDBM gnu dbm 2.x database application/x-gdbm
+
+12 long 0x00042253 bsd db queue
++16 long >0 version %d
++12 belong 0x00042253 , big-endian
++12 lelong 0x00042253 , little-endian
+
+0 long 0x00053162 bsd db btree application/x-bsd-db
++4 long >2 1.86
++4 long <3 1.85
++4 long >0 , version %d
++0 belong 0x00053162 , big-endian
++0 lelong 0x00053162 , little-endian
++16 long * , %d record%s
++20 long * , flags 0x%x
+
+12 long 0x00053162 bsd db btree
++16 long >0 version %d
++12 belong 0x00053162 , big-endian
++12 lelong 0x00053162 , little-endian
+
+0 long 0x00061561 bsd db hash application/x-bsd-db
++4 long >2 1.86
++4 long <3 1.85
++4 long >0 version %d
++8 long 4321 , big-endian
++8 long 1234 , little-endian
++56 long * , %d key%s
+
+12 long 0x00061561 bsd db hash
++16 long >0 version %d
++12 belong 0x00061561 , big-endian
++12 lelong 0x00061561 , little-endian
+
+0 long 0x950412de gnu message catalog application/x-locale
++4 long * , revision %d
++8 long * , %d message%s
+
+#
+# from the net
+#
+
+1 string # This is a shell archive. shar archive application/x-shar
+81 string # This is a shell archive. shar archive application/x-shar
+
+0 short 0x1f9d compressed data application/zip
+{
+2 byte &0200
+&2 byte &037>0 , %d bit%s
+}
+0 short 017436 packed data application/zip
+0 short 0x9d1f compressed data application/zip
++2 byte &0200 , blocked
++2 byte &037>0 , with %d bit%s
+
+0 short 0x1f10 pzip compressed data application/pzip
+&2 byte >0 , version %d
+&3 byte <10 .%d
+
+0 short 0x1f8b pzip compressed data application/pzip
+&10 short 0x9217
+
+0 short 0x1f8b gzip compressed data application/gzip
++9 byte 0 , dos
++9 byte 1 , amiga
++9 byte 2 , vms
++9 byte 3 , unix
++9 byte 5 , atari
++9 byte 6 , os/2
++9 byte 7 , mac
++9 byte 10 , tops/20
++9 byte 11 , win/32
++2 byte <8 , reserved
++2 byte 8 , deflate
++3 byte &0x1 , ascii
++3 byte &0x2 , continuation
++3 byte &0x4 , extra field
++3 byte &0x8 , original name
++3 byte &0x10 , comment
++3 byte &0x20 , encrypted
++8 byte 2 , max compression
++8 byte 4 , max speed
++4 ledate >0 , %s
+
+0 string BZh bzip compressed data application/zip
++3 byte >='0'&<='9' , %c00k blocks
+0 long 0x0000abcd NOC newbridge raw stats
+v{
++4 short * , version %d
++6 short * .%d
+}
+0 long 0x0e130414 NOC switch stats
+v()
+0 long 0x0e13130d NOC switch summary stats
+v()
+
+0 leshort 0 windows icon resource application/x-ms-icon
+&2 leshort 1
++4 leshort x , %d icon%s
+
+0 string begin 0 uuencoded data application/x-uuencode
+0 string \x89PNG PNG image data image/png
+&4 belong 0x0d0a1a0a
++16 belong x , %ld x
++20 belong x %ld
++24 byte x , %d-bit
++25 byte 0 , grayscale
++25 byte 2 , color RGB
++25 byte 3 , colormap
++25 byte 4 , gray+alpha
++25 byte 6 , color RGBA
+#+26 byte 0 , deflate/32K
++28 byte 0 , non-interlaced
++28 byte 1 , interlaced
+0 string \377\330\377 JPEG image image/jpeg
+0 string GIF GIF image image/gif
++3 string * , version %-.3s
+{
+6 leshort >0 , %d
+&8 leshort >0 x %d
+}
++10 byte &0x40 , interlaced
++10 byte &0x03==0x00 , 2 colors
++10 byte &0x03==0x01 , 4 colors
++10 byte &0x03==0x02 , 8 colors
++10 byte &0x03==0x03 , 16 colors
++10 byte &0x03==0x04 , 32 colors
++10 byte &0x03==0x05 , 64 colors
++10 byte &0x03==0x06 , 128 colors
++10 byte &0x03==0x07 , 256 colors
+0 short 0x4d4d TIFF image, big-endian image/tiff
++2 short >0 , version %d
+0 short 0x4949 TIFF image, little-endian image/tiff
++2 short >0 , version %d
+0 short 000732 sgi imagelib image image/x-imagelib
++6 short * , %d
++8 short * x %d
+
+0 string gimp xcf gimp XCF image image/x-gimp
++9 string file , version 0
+{
+9 string v , version
+&10 string * %s
+}
++14 belong x , %lu x
++18 belong x %lu
++22 belong 0 , rgb color
++22 belong 1 , greyscale
++22 belong 2 , indexed color
+
+0 string MOVI sgi movie video/x-sgi
+
+0 byte 0
+&4 string moov quicktime movie video/quicktime
+0 byte 0
+&4 string mdat quicktime movie video/quicktime
+8 string AVI avi movie video/avi
+0 long 0x000001BA mpeg movie video/mpeg
+0 long 0x000001B3 mpeg movie video/mpeg
+
+0 string <MakerFile frame maker file application/framemaker
+0 string {\\rtf rich text application/rtf
+
+0 long 0xd0cf11e0 ms powerpoint document application/x-powerpoint
+
+0 string ms C/C++ program database ms program database application/x-dbx
++33 string * , version %s
+
+0 string \377WPC corel wordperfect document application/x-wordperfect
+
+0 beshort 0xedab
+&2 beshort 0xeedb red hat package manager
++4 byte * v%d
++8 beshort 1 i386
++8 beshort 2 alpha
++8 beshort 3 sparc
++8 beshort 4 mips
++8 beshort 5 powerpc
++8 beshort 6 68k
++8 beshort 7 sgi
++8 beshort >7 unknown
++6 beshort 0 binary
++6 beshort 1 source
++10 string * , %s
+
+0 short 0x9900 pgp key public ring application/pgp
+0 short 0x9501 pgp key security ring application/pgp
+0 short 0x9500 pgp key security ring application/pgp
+0 string -----BEGIN\040PGP pgp armored data application/pgp
++15 string PUBLIC\040KEY\040BLOCK- , public key block
++15 string MESSAGE- , message
++15 string SIGNED\040MESSAGE- , signed message
++15 string PGP\040SIGNATURE- , signature
+
+0 string Core osf unknown core dump x-system/core
+&name match core*
++24 string * from `%s'
+
+0 match From[ ] mail message message/rfc822
+0 match (BABYL|From|Received|Return-Path|To)?(:)[ ] mail message message/partial
+
+0 string \001fcp X11 portable compiled font x-X11/font
+
+0 string \357\273\277 utf-8 encoded text application/x-iconv
+0 string \376\377 utf-16 encoded text application/x-iconv
+0 string \377\376 utf-16 encoded text, little-endian application/x-iconv
+
+32769 string CD001 ISO 9660 CD-ROM filesystem image data/x-filesystem
++32808 string * , '%s'
++34816 string \000CD001\001EL\ TORITO\ SPECIFICATION , bootable
+37633 string CD001 ISO 9660 CD-ROM filesystem image, raw 2352 byte sectors data/x-filesystem
+32776 string CDROM High Sierra CD-ROM filesystem image data/x-filesystem
+
+#
+# front compression data
+#
+
+0 byte 0
+&1 edit %^\([A-Z_][A-Z_]*\)-\([^0-9]*\)-\([0-9][0-9]\)%\1 data, with \2, version \3%l %s application/x-%s
+0 byte 0
+&1 edit %^\([A-Z_][A-Z_]*\)\([0-9][0-9]\)%\1 data, version \2%l %s application/x-%s
+
+#
+# generic binary magic
+#
+
+0 long 0x00010203
+&4 string * %s application/x-%s
+&12 string * %s data
+&24 version * , version %s
++28 long >0 , size %u
+{
+&28 long >=4
+&32 long >0 , %u
+}
+{
+&28 long >=8
+&36 long >0 , %u
+}
+
+#
+# local additions
+#
+
+0 match info mam mam program application/x-mam
+0 edit %^!<\([^>]*\)>.*%\1%l %s data application/x-%s
+0 string \015\023\007\000 ast message catalog application/x-locale
++4 string * , %s
+
+#
+# last chance
+#
+
+name match *.(o|obj) unknown object x-system/obj
+name match core unknown core dump x-system/core
+name match core.* unknown core dump x-system/core
+
+#
+# we resisted til now
+#
+
+0 void registry()
+|name match *.acp Office.ActorPreview application/x-ms-office
+|name match *.act Office.Actor application/x-ms-office
+|name match *.ade Microsoft Access project extension application/x-ms
+|name match *.adp Microsoft Access project application/x-ms
+|name match *.aif AIFF Audio audio/x-aiff
+|name match *.aifc AIFF Audio audio/aiff
+|name match *.aiff AIFF Audio audio/aiff
+|name match *.aim AOL Instant Messenger Launch application/x-aim
+|name match *.ani Animated Cursor application/x-ms-anifile
+|name match *.app Application file application/x-ms
+|name match *.arc WinZip File application/x-ms-winzip
+|name match *.arj WinZip File application/x-ms-winzip
+|name match *.art ART Image image/x-jg
+|name match *.asp Active Server Page application/x-ms
+|name match *.asx Windows Media Audio / Video application/x-ms
+|name match *.au Sound Clip audio/basic
+|name match *.avi Video Clip video/avi
+|name match *.awx Custom AppWizard application/x-ms-awxfile
+|name match *.b64 WinZip File application/x-ms-winzip
+|name match *.bas Microsoft Visual Basic class module application/x-ms
+|name match *.bat MS-DOS Batch File application/x-ms-batfile
+|name match *.bfc Briefcase application/x-ms-briefcase
+|name match *.bhx WinZip File application/x-ms-winzip
+|name match *.bmp Bitmap Image image/bmp
+|name match *.bpg Borland Project Group application/x-ms-borlandprojectgroup
+|name match *.bpk C++Builder Package application/x-ms-bcbpackage
+|name match *.bpr C++Builder Project application/x-ms-bcbproject
+|name match *.bsc Browser Information application/x-ms-bscfile
+|name match *.cda CD Audio Track application/x-ms-cdafile
+|name match *.cdf Channel File application/x-netcdf
+|name match *.cer Internet Security Certificate application/x-x509-ca-cert
+|name match *.cfg CFG File application/x-ms-cfg_auto_file
+|name match *.chm Compiled HTML Help file application/x-ms-help
+|name match *.cil Clip Gallery Download Package application/x-ms-clipgallerydownloadpackage
+|name match *.class Java class file application/x-java
+|name match *.clp Clipboard Clip application/x-ms-clpfile
+|name match *.cmd Windows Command Script application/x-ms-cmdfile
+|name match *.com MS-DOS Application application/x-ms-comfile
+|name match *.cpl Control Panel extension application/x-ms-cplfile
+|name match *.cpp C++ Source File application/x-c++
+|name match *.crt Internet Security Certificate application/x-x509-ca-cert
+|name match *.css HyperText Style Sheet text/css
+|name match *.csv Microsoft Excel Comma Separated Values File application/x-ms-excel
+|name match *.cur Cursor application/x-ms-curfile
+|name match *.cxx C++ Source File application/x-c++
+|name match *.dcx DCX Image Document application/x-ms-dcximage
+|name match *.der Internet Security Certificate application/x-x509-ca-cert
+|name match *.dfm C++Builder Form application/x-ms-bcbform
+|name match *.dic Text Document application/x-ms-txtfile
+|name match *.dif DV video/x-dv
+|name match *.dll Windows dynamic link library application/x-ms-dll
+|name match *.doc Microsoft Word Document application/x-ms-word
+|name match *.dot Microsoft Word Template application/x-ms-word
+|name match *.drv Device driver application/x-ms-drvfile
+|name match *.dsm Developer Studio Macro File application/x-ms-dsmfile
+|name match *.dsn Microsoft OLE DB Provider for ODBC Drivers application/x-ms-msdasql
+|name match *.dsp Project File application/x-ms-dspfile
+|name match *.dsw Project Workspace application/x-ms-dswfile
+|name match *.dv DV video/x-dv
+|name match *.ebh Ebasic Files application/x-ms-hclebasich
+|name match *.ebx Ebrun Files application/x-ms-hclebrun
+|name match *.exc Text Document application/x-ms-txtfile
+|name match *.exe Application application/x-msdownload
+|name match *.fav Outlook Bar Shortcuts application/x-ms-outlook
+|name match *.fdf Adobe Acrobat Forms Document application/x-ms-acroexch
+|name match *.fnd Saved Search application/x-ms-fndfile
+|name match *.fon Font file application/x-ms-fonfile
+|name match *.fs Ftp Files application/x-ms-hclftp
+|name match *.fxp Microsoft Visual FoxPro compiled program application/x-ms-foxpro
+|name match *.gfi Genigraphics GraphicsLink application/x-ms-graphicslink
+|name match *.gfx Genigraphics GraphicsLink application/x-ms-graphicslink
+|name match *.gif GIF Image image/gif
+|name match *.gim Genigraphics GraphicsLink application/x-ms-graphicslink
+|name match *.gix Genigraphics GraphicsLink application/x-ms-graphicslink
+|name match *.gna Genigraphics GraphicsLink application/x-ms-graphicslink
+|name match *.gnx Genigraphics GraphicsLink application/x-ms-graphicslink
+|name match *.gra Microsoft Graph 97 Chart application/x-ms-msgraph
+|name match *.grp Microsoft Program Group application/x-ms-msprogramgroup
+|name match *.gst MSMap.Datainst.8 application/x-ms-msmap
+|name match *.gwx Genigraphics GraphicsLink application/x-ms-graphicslink
+|name match *.gwz Genigraphics GraphicsLink application/x-ms-graphicslink
+|name match *.gz WinZip File application/gzip
+|name match *.hep HostExplorer Session Profile application/x-ms-hostexplorer
+|name match *.hlp Help File application/x-ms-help
+|name match *.hpp C++ Header File application/x-c++
+|name match *.hqx WinZip File application/mac-binhex40
+|name match *.hs3 HostExplorer Hotspot Definition application/x-ms-hostexplorer
+|name match *.hs5 HostExplorer Hotspot Definition application/x-ms-hostexplorer
+|name match *.hsv HostExplorer Hotspot Definition application/x-ms-hostexplorer
+|name match *.ht HyperTerminal File application/x-ms-htfile
+|name match *.hta HTML program application/x-ms
+|name match *.htm html source text/html
+|name match *.hts Hummingbird Telnet Program v6.0.0.0 application/x-ms-hummingbird
+|name match *.htt HyperText Template text/webviewhtml
+|name match *.htw HTML Document application/x-ms-htmlfile
+|name match *.htx HTML Document text/html
+|name match *.hxx C++ Header File application/x-c++
+|name match *.ico Icon application/x-ms-icon
+|name match *.idb Intermediate File application/x-ms-mdpxfile
+|name match *.ilk Intermediate File application/x-ms-mdpxfile
+|name match *.inf Setup Information application/x-ms-setup
+|name match *.ini Configuration Settings application/x-ms-config
+|name match *.ins Internet Communication Settings application/x-internet-signup
+|name match *.iqy Microsoft Excel Web Query File application/x-ms-iqyfile
+|name match *.isp Internet Communication Settings application/x-internet-signup
+|name match *.its Internet Document Set application/x-ms-its
+|name match *.ivt InfoViewer Title application/x-ms-ivt
+|name match *.jfif JPEG Image image/jpeg
+|name match *.job Scheduler Job Object application/x-ms-jobobject
+|name match *.jod Microsoft.Jet.OLEDB.3.51 application/x-ms-microsoft
+|name match *.jpe JPEG Image image/jpeg
+|name match *.jpeg JPEG Image image/jpeg
+|name match *.jpg JPEG Image image/jpeg
+|name match *.js JavaScript file application/x-java
+|name match *.jse JavaScript Encoded Script file application/x-ms
+|name match *.jsp JavaScript Page application/x-ms
+|name match *.km3 HostExplorer KeyMap Definition application/x-ms-hostexplorer
+|name match *.km5 HostExplorer KeyMap Definition application/x-ms-hostexplorer
+|name match *.kmv HostExplorer KeyMap Definition application/x-ms-hostexplorer
+|name match *.lam LAMDocument application/x-ms-lamdocument
+|name match *.ldb Microsoft Access Record-Locking Information application/x-ms-access
+|name match *.lnk Shortcut application/x-ms
+|name match *.log Text Document application/x-text
+|name match *.lzh WinZip File application/x-ms-winzip
+|name match *.m1v Movie Clip video/mpeg
+|name match *.mac MacPaint Image image/x-macpaint
+|name match *.mad Microsoft Access Module Shortcut application/x-ms-access
+|name match *.maf Microsoft Access Form Shortcut application/x-ms-access
+|name match *.mam Microsoft Access Macro Shortcut application/x-ms-access
+|name match *.maq Microsoft Access Query Shortcut application/x-ms-access
+|name match *.mar Microsoft Access Report Shortcut application/x-ms-access
+|name match *.mat Microsoft Access Table Shortcut application/x-ms-access
+|name match *.mda Microsoft Access Add-in application/x-ms-access
+|name match *.mdb Microsoft Access Database application/x-ms-access
+|name match *.mdb Microsoft Access program application/x-ms
+|name match *.mde Microsoft Access MDE Database application/x-ms-access
+|name match *.mdn Microsoft Access Blank Database Template application/x-ms-access
+|name match *.mdp Project Workspace application/x-ms-mdpfile
+|name match *.mdt Microsoft Access Add-in Data application/x-ms-access
+|name match *.mdw Microsoft Access Workgroup Information application/x-ms-access
+|name match *.mdz Microsoft Access Database Wizard Template application/x-ms-access
+|name match *.mht Microsoft MHTML Document 4.0 message/rfc822
+|name match *.mhtml Microsoft MHTML Document 4.0 message/rfc822
+|name match *.mid MIDI Sequence audio/mid
+|name match *.mmm Media Clip application/x-ms-mplayer
+|name match *.mov QuickTime Movie video/quicktime
+|name match *.mp2 Movie Clip video/mpeg
+|name match *.mpa Movie Clip video/mpeg
+|name match *.mpe Movie Clip video/mpeg
+|name match *.mpeg Movie Clip video/mpeg
+|name match *.mpg Movie Clip video/mpeg
+|name match *.msc Microsoft Common Console Document application/x-ms-mmc
+|name match *.msg Outlook Item application/x-ms-msgfile
+|name match *.msi Microsoft Windows Installer package application/x-ms
+|name match *.msp Windows Installer patch application/x-ms
+|name match *.mst Visual Test source files application/x-ms
+|name match *.nsc Netscape Conference Call File application/x-conference
+|name match *.obd Microsoft Office Binder application/x-ms-office
+|name match *.obt Microsoft Office Binder Template application/x-ms-office
+|name match *.obz Microsoft Office Binder Wizard application/x-ms-office
+|name match *.odl Object Definition Language File application/x-ms-odlfile
+|name match *.ofn Other Office Documents... application/x-ms-office
+|name match *.oft Outlook Item Template application/x-ms-outlook
+|name match *.ops Microsoft Office profile settings file application/x-ms
+|name match *.opx MS Organization Chart 2.0 application/x-ms-orgpluswopx
+|name match *.oss Office Search application/x-ms-ossfile
+|name match *.pcd Photo CD Image application/x-ms-pcdfile
+|name match *.pch Intermediate File application/x-ms-mdpxfile
+|name match *.pct PICT Image image/pict
+|name match *.pcx PCX Image application/x-ms-pcxfile
+|name match *.pdb Intermediate File application/x-ms-mdpxfile
+|name match *.pdf Adobe Acrobat Document application/pdf
+|name match *.pfm Type 1 Font file application/x-ms-pfmfile
+|name match *.php Perl CGI Script File application/x-perl
+|name match *.pic PICT Image image/pict
+|name match *.pict PICT Image image/pict
+|name match *.pif Shortcut to MS-DOS Program application/x-ms-piffile
+|name match *.pif Shortcut to MS-DOS program application/x-ms
+|name match *.pkg Microsoft Developer Extension application/x-ms-pkgfile
+|name match *.pma Performance Monitor File application/x-ms-perffile
+|name match *.pmc Performance Monitor File application/x-ms-perffile
+|name match *.pml Performance Monitor File application/x-ms-perffile
+|name match *.pmr Performance Monitor File application/x-ms-perffile
+|name match *.pmw Performance Monitor File application/x-ms-perffile
+|name match *.pnf Precompiled Setup Information application/x-ms-pnffile
+|name match *.png PNG Image application/x-ms-pngfile
+|name match *.pntg MacPaint Image image/x-macpaint
+|name match *.pop HostExplorer Poppad Definition application/x-ms-hostexplorer
+|name match *.pot Microsoft PowerPoint Template application/vnd.ms-powerpoint
+|name match *.ppa Microsoft PowerPoint Addin application/vnd.ms-powerpoint
+|name match *.pps Microsoft PowerPoint SlideShow application/vnd.ms-powerpoint
+|name match *.ppt Microsoft PowerPoint Presentation application/vnd.ms-powerpoint
+|name match *.prf System file application/x-ms
+|name match *.prg Program source file application/x-ms
+|name match *.psd Photoshop Image image/x-photoshop
+|name match *.pwz Microsoft PowerPoint Wizard application/vnd.ms-powerpoint
+|name match *.qif QuickTime Image image/x-quicktime
+|name match *.qk3 HostExplorer QuickKeys application/x-ms-hostexplorer
+|name match *.qk5 HostExplorer QuickKeys application/x-ms-hostexplorer
+|name match *.qkv HostExplorer QuickKeys application/x-ms-hostexplorer
+|name match *.qt QuickTime Movie video/quicktime
+|name match *.qti QuickTime Image image/x-quicktime
+|name match *.qtif QuickTime Image image/x-quicktime
+|name match *.qtp QuickTime Preferences application/x-ms-quicktimepreferences
+|name match *.qts QuickTime application/x-ms-quicktimesystem
+|name match *.qtx QuickTime Extension application/x-ms-quicktimeextension
+|name match *.que Scheduler Queue Object application/x-ms-queueobject
+|name match *.rc Resource Template application/x-ms-rcfile
+|name match *.rct Resource Template application/x-ms-rcfile
+|name match *.reg Registration Entries application/x-ms-regfile
+|name match *.res Intermediate File application/x-ms-mdpxfile
+|name match *.rmi MIDI Sequence audio/mid
+|name match *.rnk Dial-Up Shortcut application/x-ms-rnkfile
+|name match *.rtf Rich Text Format application/x-ms-word
+|name match *.rx XRX Files application/x-ms-hclbroadway
+|name match *.sbr Intermediate File application/x-ms-mdpxfile
+|name match *.sc2 Microsoft Schedule+ 7.0 Application application/x-ms-scheduleplus
+|name match *.scd Microsoft Schedule+ 7.0 Application application/x-ms-scheduleplus
+|name match *.scf Windows Explorer Command application/x-ms-explorer
+|name match *.sch Microsoft Schedule+ 7.0 Application application/x-ms-scheduleplus
+|name match *.scp Text Document application/x-ms-txtfile
+|name match *.scr Screen Saver application/x-ms-scrfile
+|name match *.sct Windows Script Component application/x-ms
+|name match *.sd2 Sound Designer 2 audio/x-sd2
+|name match *.ses Xsession Files application/x-ms-hclxsession
+|name match *.shb Shortcut into a document application/x-ms-docshortcut
+|name match *.shs Scrap object application/x-ms-shellscrap
+|name match *.shtml Netscape Hypertext Document application/x-ms-netscapemarkup
+|name match *.slk Microsoft Excel SLK Data Import Format application/x-ms-excel
+|name match *.snd Sound Clip audio/basic
+|name match *.stm HTML Document text/html
+|name match *.sys System file application/x-ms-sysfile
+|name match *.taz WinZip File application/x-ms-winzip
+|name match *.tga TGA Image application/x-ms-tgafile
+|name match *.tif TIF Image Document image/tiff
+|name match *.tlb Type Library application/x-ms-tlbfile
+|name match *.ttf TrueType Font file application/x-ms-ttffile
+|name match *.txt Text Document text/plain
+|name match *.tz WinZip File application/x-ms-winzip
+|name match *.udl Microsoft Data Link application/x-ms-msdasc
+|name match *.url Internet Shortcut application/x-ms-internetshortcut
+|name match *.uue WinZip File application/x-ms-winzip
+|name match *.vb Microsoft Visual Basic Scripting Edition (VBScript) file application/x-ms
+|name match *.vbe VBScript Encoded Script file application/x-ms
+|name match *.vbs VBScript file application/x-ms
+|name match *.vir Virus Infected File application/x-ms-virus
+|name match *.wav Wave Sound audio/x-wav
+|name match *.wbk Microsoft Word Backup Document application/x-ms-word
+|name match *.wiz Microsoft Word Wizard application/x-ms-word
+|name match *.wll Microsoft Word Addin application/x-ms-word
+|name match *.wpd corel wordperfect document application/x-wordperfect
+|name match *.wri Write Document application/x-ms-wrifile
+|name match *.wrl SGI.CosmoPlayer.1 application/x-ms-sgi
+|name match *.wrz SGI.CosmoPlayer.1 application/x-ms-sgi
+|name match *.ws Wstart Files application/x-ms-hclwstart
+|name match *.wsc Windows Script Component application/x-ms
+|name match *.wsf Windows Script file application/x-ms
+|name match *.wsh Windows Script Host Settings file application/x-ms
+|name match *.wtx Text Document application/x-ms-txtfile
+|name match *.xbm Netscape Hypertext Document image/x-xbitmap
+|name match *.xif XIF Image Document application/x-ms-xifimage
+|name match *.xla Microsoft Excel Add-In application/x-ms-excel
+|name match *.xlb Microsoft Excel Worksheet application/x-ms-excel
+|name match *.xlc Microsoft Excel Chart application/x-ms-excel
+|name match *.xld Microsoft Excel 5.0 DialogSheet application/x-ms-excel
+|name match *.xlk Microsoft Excel Backup File application/x-ms-excel
+|name match *.xll Microsoft Excel XLL Add-In application/x-ms-excel
+|name match *.xlm Microsoft Excel 4.0 Macro application/x-ms-excel
+|name match *.xls Microsoft Excel Worksheet application/vnd.ms-excel
+|name match *.xlt Microsoft Excel Template application/x-ms-excel
+|name match *.xlv Microsoft Excel VBA Module application/x-ms-excel
+|name match *.xlw Microsoft Excel Workspace application/x-ms-excel
+|name match *.xnk Microsoft Exchange Shortcut application/x-ms-exchange
+|name match *.xs Microsoft Exchange start Files application/x-ms-exchange
+|name match *.xxe WinZip File application/x-ms-winzip
+|name match *.zip WinZip File application/x-zip-compressed
diff --git a/src/lib/libast/misc/mime.c b/src/lib/libast/misc/mime.c
new file mode 100644
index 0000000..49cfaa1
--- /dev/null
+++ b/src/lib/libast/misc/mime.c
@@ -0,0 +1,839 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * mime/mailcap support library
+ */
+
+static const char id[] = "\n@(#)$Id: mime library (AT&T Research) 2002-10-29 $\0\n";
+
+static const char lib[] = "libast:mime";
+
+#include "mimelib.h"
+
+typedef struct Att_s
+{
+ struct Att_s* next;
+ char* name;
+ char* value;
+} Att_t;
+
+typedef struct Cap_s
+{
+ struct Cap_s* next;
+ unsigned long flags;
+ Att_t att;
+ char* test;
+ char data[1];
+} Cap_t;
+
+typedef struct
+{
+ Dtlink_t link;
+ Cap_t* cap;
+ Cap_t* pac;
+ char name[1];
+} Ent_t;
+
+typedef struct
+{
+ char* data;
+ int size;
+} String_t;
+
+typedef struct
+{
+ char* next;
+ String_t name;
+ String_t value;
+} Parse_t;
+
+typedef struct
+{
+ const char* pattern;
+ int prefix;
+ Sfio_t* fp;
+ int hit;
+} Walk_t;
+
+/*
+ * convert c to lower case
+ */
+
+static int
+lower(register int c)
+{
+ return isupper(c) ? tolower(c) : c;
+}
+
+/*
+ * Ent_t case insensitive comparf
+ */
+
+static int
+order(Dt_t* dt, void* a, void* b, Dtdisc_t* disc)
+{
+ return strcasecmp(a, b);
+}
+
+/*
+ * Cap_t free
+ */
+
+static void
+dropcap(register Cap_t* cap)
+{
+ register Att_t* att;
+
+ while (att = cap->att.next)
+ {
+ cap->att.next = att->next;
+ free(att);
+ }
+ free(cap);
+}
+
+/*
+ * Ent_t freef
+ */
+
+static void
+drop(Dt_t* dt, void* object, Dtdisc_t* disc)
+{
+ register Ent_t* ent = (Ent_t*)object;
+ register Cap_t* cap;
+
+ while (cap = ent->cap)
+ {
+ ent->cap = cap->next;
+ dropcap(cap);
+ }
+ free(ent);
+}
+
+/*
+ * add mime type entry in s to mp
+ */
+
+int
+mimeset(Mime_t* mp, register char* s, unsigned long flags)
+{
+ register Ent_t* ent;
+ register Cap_t* cap;
+ register Att_t* att;
+ register char* t;
+ register char* v;
+ register char* k;
+ char* x;
+ Att_t* tta;
+ int q;
+
+ for (; isspace(*s); s++);
+ if (*s && *s != '#')
+ {
+ cap = 0;
+ for (v = s; *v && *v != ';'; v++)
+ if (isspace(*v) || *v == '/' && *(v + 1) == '*')
+ *v = 0;
+ if (*v)
+ {
+ *v++ = 0;
+ do
+ {
+ for (; isspace(*v); v++);
+ if (cap)
+ {
+ for (t = v; *t && !isspace(*t) && *t != '='; t++);
+ for (k = t; isspace(*t); t++);
+ if (!*t || *t == '=' || *t == ';')
+ {
+ if (*t)
+ while (isspace(*++t));
+ *k = 0;
+ k = v;
+ v = t;
+ }
+ else
+ k = 0;
+ }
+ if (*v == '"')
+ q = *v++;
+ else
+ q = 0;
+ for (t = v; *t; t++)
+ if (*t == '\\')
+ {
+ switch (*(t + 1))
+ {
+ case 0:
+ case '\\':
+ case '%':
+ *t = *(t + 1);
+ break;
+ default:
+ *t = ' ';
+ break;
+ }
+ if (!*++t)
+ break;
+ }
+ else if (*t == q)
+ {
+ *t = ' ';
+ q = 0;
+ }
+ else if (*t == ';' && !q)
+ {
+ *t = ' ';
+ break;
+ }
+ for (; t > v && isspace(*(t - 1)); t--);
+ if (t <= v && (!cap || !k))
+ break;
+ if (!cap)
+ {
+ if (!(cap = newof(0, Cap_t, 1, strlen(v) + 1)))
+ return -1;
+ if (*t)
+ *t++ = 0;
+ tta = &cap->att;
+ tta->name = "default";
+ x = strcopy(tta->value = cap->data, v) + 1;
+ }
+ else if (k)
+ {
+ if (*t)
+ *t++ = 0;
+ if (!(att = newof(0, Att_t, 1, 0)))
+ return -1;
+ x = strcopy(att->name = x, k) + 1;
+ x = strcopy(att->value = x, v) + 1;
+ tta = tta->next = att;
+ if (!strcasecmp(k, "test"))
+ cap->test = att->value;
+ }
+ } while (*(v = t));
+ }
+ ent = (Ent_t*)dtmatch(mp->cap, s);
+ if (cap)
+ {
+ if (ent)
+ {
+ register Cap_t* dup;
+ register Cap_t* pud;
+
+ for (pud = 0, dup = ent->cap; dup; pud = dup, dup = dup->next)
+ if (!cap->test && !dup->test || cap->test && dup->test && streq(cap->test, dup->test))
+ {
+ if (flags & MIME_REPLACE)
+ {
+ if (pud)
+ pud->next = cap;
+ else
+ ent->cap = cap;
+ if (!(cap->next = dup->next))
+ ent->pac = cap;
+ cap = dup;
+ }
+ dropcap(cap);
+ return 0;
+ }
+ ent->pac = ent->pac->next = cap;
+ }
+ else if (!(ent = newof(0, Ent_t, 1, strlen(s) + 1)))
+ return -1;
+ else
+ {
+ strcpy(ent->name, s);
+ ent->cap = ent->pac = cap;
+ dtinsert(mp->cap, ent);
+ }
+ }
+ else if (ent && (flags & MIME_REPLACE))
+ dtdelete(mp->cap, ent);
+ }
+ return 0;
+}
+
+/*
+ * load mime type files into mp
+ */
+
+int
+mimeload(Mime_t* mp, const char* file, unsigned long flags)
+{
+ register char* s;
+ register char* t;
+ register char* e;
+ register int n;
+ Sfio_t* fp;
+
+ if (!(s = (char*)file))
+ {
+ flags |= MIME_LIST;
+ if (!(s = getenv(MIME_FILES_ENV)))
+ s = MIME_FILES;
+ }
+ for (;;)
+ {
+ if (!(flags & MIME_LIST))
+ e = 0;
+ else if (e = strchr(s, ':'))
+ {
+ /*
+ * ok, so ~ won't work for the last list element
+ * we do it for MIME_FILES_ENV anyway
+ */
+
+ if ((strneq(s, "~/", n = 2) || strneq(s, "$HOME/", n = 6) || strneq(s, "${HOME}/", n = 8)) && (t = getenv("HOME")))
+ {
+ sfputr(mp->buf, t, -1);
+ s += n - 1;
+ }
+ sfwrite(mp->buf, s, e - s);
+ if (!(s = sfstruse(mp->buf)))
+ return -1;
+ }
+ if (fp = tokline(s, SF_READ, NiL))
+ {
+ while (t = sfgetr(fp, '\n', 1))
+ if (mimeset(mp, t, flags))
+ break;
+ sfclose(fp);
+ }
+ else if (!(flags & MIME_LIST))
+ return -1;
+ if (!e)
+ break;
+ s = e + 1;
+ }
+ return 0;
+}
+
+/*
+ * mimelist walker
+ */
+
+static int
+list(Dt_t* dt, void* object, void* context)
+{
+ register Walk_t* wp = (Walk_t*)context;
+ register Ent_t* ent = (Ent_t*)object;
+ register Cap_t* cap;
+ register Att_t* att;
+
+ if (!wp->pattern || !strncasecmp(ent->name, wp->pattern, wp->prefix) && (!ent->name[wp->prefix] || ent->name[wp->prefix] == '/'))
+ {
+ wp->hit++;
+ for (cap = ent->cap; cap; cap = cap->next)
+ {
+ sfprintf(wp->fp, "%s", ent->name);
+ for (att = &cap->att; att; att = att->next)
+ {
+ sfprintf(wp->fp, "\n\t");
+ if (att != &cap->att)
+ {
+ sfprintf(wp->fp, "%s", att->name);
+ if (*att->value)
+ sfprintf(wp->fp, " = ");
+ }
+ sfputr(wp->fp, att->value, -1);
+ }
+ sfprintf(wp->fp, "\n");
+ }
+ }
+ return 0;
+}
+
+/*
+ * find entry matching type
+ * if exact match fails then left and right x- and right version number
+ * permutations are attempted
+ */
+
+static Ent_t*
+find(Mime_t* mp, const char* type)
+{
+ register char* lp;
+ register char* rp;
+ register char* rb;
+ register char* rv;
+ register int rc;
+ register int i;
+ char* s;
+ Ent_t* ent;
+ char buf[256];
+
+ static const char* prefix[] = { "", "", "x-", "x-", "" };
+
+ if ((ent = (Ent_t*)dtmatch(mp->cap, type)) ||
+ !(rp = strchr(lp = (char*)type, '/')) ||
+ strlen(lp) >= sizeof(buf))
+ return ent;
+ strcpy(buf, type);
+ rp = buf + (rp - lp);
+ *rp++ = 0;
+ if (*rp == 'x' && *(rp + 1) == '-')
+ rp += 2;
+ lp = buf;
+ if (*lp == 'x' && *(lp + 1) == '-')
+ lp += 2;
+ rb = rp;
+ for (rv = rp + strlen(rp); rv > rp && (isdigit(*(rv - 1)) || *(rv - 1) == '.'); rv--);
+ rc = *rv;
+ do
+ {
+ rp = rb;
+ do
+ {
+ for (i = 0; i < elementsof(prefix) - 1; i++)
+ {
+ sfprintf(mp->buf, "%s%s/%s%s", prefix[i], lp, prefix[i + 1], rp);
+ if (!(s = sfstruse(mp->buf)))
+ return 0;
+ if (ent = (Ent_t*)dtmatch(mp->cap, s))
+ return ent;
+ if (rc)
+ {
+ *rv = 0;
+ sfprintf(mp->buf, "%s%s/%s%s", prefix[i], lp, prefix[i + 1], rp);
+ if (!(s = sfstruse(mp->buf)))
+ return 0;
+ if (ent = (Ent_t*)dtmatch(mp->cap, s))
+ return ent;
+ *rv = rc;
+ }
+ }
+ while (*rp && *rp++ != '-');
+ } while (*rp);
+ while (*lp && *lp++ != '-');
+ } while (*lp);
+ return (Ent_t*)dtmatch(mp->cap, buf);
+}
+
+/*
+ * list mime <type,data> for pat on fp
+ */
+
+int
+mimelist(Mime_t* mp, Sfio_t* fp, register const char* pattern)
+{
+ Ent_t* ent;
+ Walk_t ws;
+
+ ws.fp = fp;
+ ws.hit = 0;
+ ws.prefix = 0;
+ if (ws.pattern = pattern)
+ {
+ while (*pattern && *pattern++ != '/');
+ if (!*pattern || *pattern == '*' && !*(pattern + 1))
+ ws.prefix = pattern - ws.pattern;
+ else if (ent = find(mp, ws.pattern))
+ {
+ ws.pattern = 0;
+ list(mp->cap, ent, &ws);
+ return ws.hit;
+ }
+ }
+ dtwalk(mp->cap, list, &ws);
+ return ws.hit;
+}
+
+/*
+ * get next arg in pp
+ * 0 returned if no more args
+ */
+
+static int
+arg(register Parse_t* pp, int first)
+{
+ register char* s;
+ register int c;
+ register int q;
+ int x;
+
+ for (s = pp->next; isspace(*s) && *s != '\n'; s++);
+ if (!*s || *s == '\n')
+ {
+ pp->next = s;
+ return 0;
+ }
+ pp->name.data = s;
+ pp->value.data = 0;
+ q = 0;
+ x = 0;
+ while ((c = *s++) && c != ';' && c != '\n')
+ {
+ if (c == '"')
+ {
+ q = 1;
+ if (pp->value.data)
+ {
+ pp->value.data = s;
+ if (x)
+ x = -1;
+ else
+ x = 1;
+ }
+ else if (!x && pp->name.data == (s - 1))
+ {
+ x = 1;
+ pp->name.data = s;
+ }
+ do
+ {
+ if (!(c = *s++) || c == '\n')
+ {
+ s--;
+ break;
+ }
+ } while (c != '"');
+ if (first < 0 || x > 0)
+ {
+ c = ';';
+ break;
+ }
+ }
+ else if (c == '=' && !first)
+ {
+ first = 1;
+ pp->name.size = s - pp->name.data - 1;
+ pp->value.data = s;
+ }
+ else if (first >= 0 && isspace(c))
+ break;
+ }
+ pp->next = s - (c != ';');
+ if (first >= 0 || !q)
+ for (s--; s > pp->name.data && isspace(*(s - 1)); s--);
+ if (pp->value.data)
+ pp->value.size = s - pp->value.data - (q && first < 0);
+ else
+ {
+ pp->value.size = 0;
+ pp->name.size = s - pp->name.data - (q && first < 0);
+ }
+ if (first >= 0 && pp->name.size > 0 && pp->name.data[pp->name.size - 1] == ':')
+ return 0;
+ return pp->name.size > 0;
+}
+
+/*
+ * low level for mimeview()
+ */
+
+static char*
+expand(Mime_t* mp, register char* s, const char* name, const char* type, const char* opts)
+{
+ register char* t;
+ register char* v;
+ register int c;
+ register int e;
+ register int n;
+ Parse_t pp;
+
+ mp->disc->flags |= MIME_PIPE;
+ for (;;)
+ {
+ switch (c = *s++)
+ {
+ case 0:
+ case '\n':
+ break;
+ case '%':
+ if ((c = *s++) == '{' && (e = '}') || c == '(' && (e = ')'))
+ {
+ for (t = s; *s && *s != e; s++);
+ n = s - t;
+ switch (*s)
+ {
+ case '}':
+ s++;
+ c = '{';
+ break;
+ case ')':
+ s++;
+ if (c = *s)
+ s++;
+ break;
+ }
+ }
+ else
+ t = 0;
+ switch (c)
+ {
+ case 's':
+ v = (char*)name;
+ mp->disc->flags &= ~MIME_PIPE;
+ break;
+ case 't':
+ v = (char*)type;
+ break;
+ case '{':
+ for (t = s; *s && *s != '}'; s++);
+ if (*s && (c = s++ - t) && (pp.next = (char*)opts))
+ while (arg(&pp, 0))
+ if (pp.name.size == c && !strncasecmp(pp.name.data, t, c))
+ {
+ if (pp.value.size)
+ sfwrite(mp->buf, pp.value.data, pp.value.size);
+ break;
+ }
+ continue;
+ default:
+ sfputc(mp->buf, c);
+ continue;
+ }
+ if (v && *v)
+ n = strlen(v);
+ else if (t)
+ v = t;
+ else
+ continue;
+ sfputr(mp->buf, fmtquote(v, 0, 0, n, FMT_SHELL), -1);
+ continue;
+ default:
+ sfputc(mp->buf, c);
+ continue;
+ }
+ break;
+ }
+ return sfstruse(mp->buf);
+}
+
+/*
+ * return expanded command/path/value for <view,name,type,opts>
+ * return value valid until next mime*() call
+ */
+
+char*
+mimeview(Mime_t* mp, const char* view, const char* name, const char* type, const char* opts)
+{
+ register Ent_t* ent;
+ register Cap_t* cap;
+ register Att_t* att;
+ register char* s;
+ int c;
+
+ if (ent = find(mp, type))
+ {
+ cap = ent->cap;
+ if (!view || strcasecmp(view, "test"))
+ while (s = cap->test)
+ {
+ if (s = expand(mp, s, name, type, opts))
+ {
+ Parse_t a1;
+ Parse_t a2;
+ Parse_t a3;
+ Parse_t a4;
+
+ /*
+ * try to do a few common cases here
+ * mailcap consistency is a winning
+ * strategy
+ */
+
+ a1.next = s;
+ if (arg(&a1, -1))
+ {
+ if ((c = *a1.name.data == '!') && --a1.name.size <= 0 && !arg(&a1, -1))
+ goto lose;
+ if (a1.name.size == 6 && strneq(a1.name.data, "strcmp", 6) || a1.name.size == 10 && strneq(a1.name.data, "strcasecmp", 10))
+ {
+ a2.next = a1.next;
+ if (!arg(&a2, -1))
+ goto lose;
+ a3.next = a2.next;
+ if (!arg(&a3, -1))
+ goto lose;
+ if (a2.name.size != a3.name.size)
+ c ^= 0;
+ else c ^= (a1.name.size == 6 ? strncmp : strncasecmp)(a2.name.data, a3.name.data, a2.name.size) == 0;
+ if (c)
+ break;
+ goto skip;
+ }
+ else if (a1.name.size == 4 && strneq(a1.name.data, "test", 4))
+ {
+ if (!arg(&a1, -1))
+ goto lose;
+ a2.next = a1.next;
+ if (!arg(&a2, -1) || a2.name.size > 2 || a2.name.size == 1 && *a2.name.data != '=' || a2.name.size == 2 && (!strneq(a1.name.data, "!=", 2) || !strneq(a2.name.data, "==", 2)))
+ goto lose;
+ a3.next = a2.next;
+ if (!arg(&a3, -1))
+ goto lose;
+ if (*a3.name.data == '`' && *(a3.name.data + a3.name.size - 1) == '`')
+ {
+ a4 = a3;
+ a3 = a1;
+ a1 = a4;
+ }
+ if (*a1.name.data == '`' && *(a1.name.data + a1.name.size - 1) == '`')
+ {
+ a1.next = a1.name.data + 1;
+ if (!arg(&a1, -1) || a1.name.size != 4 || !strneq(a1.name.data, "echo", 4) || !arg(&a1, -1))
+ goto lose;
+ a4.next = a1.next;
+ if (!arg(&a4, 1) || a4.name.size < 21 || !strneq(a4.name.data, "| tr '[A-Z]' '[a-z]'`", 21))
+ goto lose;
+ }
+ else
+ a4.name.size = 0;
+ c = *a2.name.data == '!';
+ if (a1.name.size != a3.name.size)
+ c ^= 0;
+ else c ^= (a4.name.size ? strncasecmp : strncmp)(a1.name.data, a3.name.data, a1.name.size) == 0;
+ if (c)
+ break;
+ goto skip;
+ }
+ }
+ lose:
+ if (!system(s))
+ break;
+ }
+ skip:
+ if (!(cap = cap->next))
+ return 0;
+ }
+ att = &cap->att;
+ if (view && *view && !streq(view, "-"))
+ while (strcasecmp(view, att->name))
+ if (!(att = att->next))
+ return 0;
+ return expand(mp, att->value, name, type, opts);
+ }
+ return 0;
+}
+
+/*
+ * lower case identifier prefix strcmp
+ * if e!=0 then it will point to the next char after the match
+ */
+
+int
+mimecmp(register const char* s, register const char* v, char** e)
+{
+ register int n;
+
+ while (isalnum(*v) || *v == *s && (*v == '_' || *v == '-' || *v == '/'))
+ if (n = lower(*s++) - lower(*v++))
+ return n;
+ if (!isalnum(*s) && *s != '_' && *s != '-')
+ {
+ if (e)
+ *e = (char*)s;
+ return 0;
+ }
+ return lower(*s) - lower(*v);
+}
+
+/*
+ * parse mime headers in strsearch(tab,num,siz) from s
+ * return >0 if mime header consumed
+ */
+
+int
+mimehead(Mime_t* mp, void* tab, size_t num, size_t siz, register char* s)
+{
+ register void* p;
+ char* e;
+ Parse_t pp;
+ Mimevalue_f set;
+
+ set = mp->disc->valuef;
+ if (!strncasecmp(s, "original-", 9))
+ s += 9;
+ if (!strncasecmp(s, "content-", 8))
+ {
+ s += 8;
+ if ((p = strsearch(tab, num, siz, (Strcmp_f)mimecmp, s, &e)) && *e == ':')
+ {
+ pp.next = e + 1;
+ if (arg(&pp, 1))
+ {
+ if ((*set)(mp, p, pp.name.data, pp.name.size, mp->disc))
+ return 0;
+ while (arg(&pp, 0))
+ if (pp.value.size &&
+ (p = strsearch(tab, num, siz, (Strcmp_f)mimecmp, pp.name.data, &e)) &&
+ (*set)(mp, p, pp.value.data, pp.value.size, mp->disc))
+ return 0;
+ return 1;
+ }
+ }
+ else if (strchr(s, ':'))
+ return 1;
+ }
+ return !strncasecmp(s, "x-", 2);
+}
+
+/*
+ * open a mime library handle
+ */
+
+Mime_t*
+mimeopen(Mimedisc_t* disc)
+{
+ register Mime_t* mp;
+
+ if (!(mp = newof(0, Mime_t, 1, 0)))
+ return 0;
+ mp->id = lib;
+ mp->disc = disc;
+ mp->dict.key = offsetof(Ent_t, name);
+ mp->dict.comparf = order;
+ mp->dict.freef = drop;
+ if (!(mp->buf = sfstropen()) || !(mp->cap = dtopen(&mp->dict, Dtoset)))
+ {
+ mimeclose(mp);
+ return 0;
+ }
+ return mp;
+}
+
+/*
+ * close a mimeopen() handle
+ */
+
+int
+mimeclose(Mime_t* mp)
+{
+ if (mp)
+ {
+ if (mp->buf)
+ sfclose(mp->buf);
+ if (mp->cap)
+ dtclose(mp->cap);
+ if (mp->freef)
+ (*mp->freef)(mp);
+ free(mp);
+ }
+ return 0;
+}
diff --git a/src/lib/libast/misc/mimelib.h b/src/lib/libast/misc/mimelib.h
new file mode 100644
index 0000000..ebfa343
--- /dev/null
+++ b/src/lib/libast/misc/mimelib.h
@@ -0,0 +1,52 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * mime/mailcap internal interface
+ */
+
+#ifndef _MIMELIB_H
+#define _MIMELIB_H 1
+
+#include <ast.h>
+#include <cdt.h>
+#include <magic.h>
+#include <tok.h>
+
+struct Mime_s;
+
+typedef void (*Free_f)(struct Mime_s*);
+
+#define _MIME_PRIVATE_ \
+ Mimedisc_t* disc; /* mime discipline */ \
+ Dtdisc_t dict; /* cdt discipline */ \
+ Magicdisc_t magicd; /* magic discipline */ \
+ Dt_t* cap; /* capability tree */ \
+ Sfio_t* buf; /* string buffer */ \
+ Magic_t* magic; /* mimetype() magic handle */ \
+ Free_f freef; /* avoid magic lib if possible */ \
+
+#include <mime.h>
+#include <ctype.h>
+
+#endif
diff --git a/src/lib/libast/misc/mimetype.c b/src/lib/libast/misc/mimetype.c
new file mode 100644
index 0000000..63fdd0b
--- /dev/null
+++ b/src/lib/libast/misc/mimetype.c
@@ -0,0 +1,69 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * mime/mailcap to magic support
+ */
+
+#include "mimelib.h"
+
+/*
+ * close magic handle
+ * done this way so that magic is only pulled in
+ * if mimetype() is used
+ */
+
+static void
+drop(Mime_t* mp)
+{
+ if (mp->magic)
+ {
+ magicclose(mp->magic);
+ mp->magic = 0;
+ }
+}
+
+/*
+ * return mime type for file
+ */
+
+char*
+mimetype(Mime_t* mp, Sfio_t* fp, const char* file, struct stat* st)
+{
+ if (mp->disc->flags & MIME_NOMAGIC)
+ return 0;
+ if (!mp->magic)
+ {
+ mp->magicd.version = MAGIC_VERSION;
+ mp->magicd.flags = MAGIC_MIME;
+ mp->magicd.errorf = mp->disc->errorf;
+ if (!(mp->magic = magicopen(&mp->magicd)))
+ {
+ mp->disc->flags |= MIME_NOMAGIC;
+ return 0;
+ }
+ mp->freef = drop;
+ magicload(mp->magic, NiL, 0);
+ }
+ return magictype(mp->magic, fp, file, st);
+}
diff --git a/src/lib/libast/misc/optctx.c b/src/lib/libast/misc/optctx.c
new file mode 100644
index 0000000..1dbdf71
--- /dev/null
+++ b/src/lib/libast/misc/optctx.c
@@ -0,0 +1,70 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * _opt_infop_ context control
+ *
+ * allocate new context:
+ * new_context = optctx(0, 0);
+ * free new context:
+ * optctx(0, new_context);
+ * switch to new_context:
+ * old_context = optctx(new_context, 0);
+ * switch to old_context and free new_context:
+ * optctx(old_context, new_context);
+ */
+
+#include <optlib.h>
+
+static Opt_t* freecontext;
+
+Opt_t*
+optctx(Opt_t* p, Opt_t* o)
+{
+ if (o)
+ {
+ if (freecontext)
+ free(o);
+ else
+ freecontext = o;
+ if (!p)
+ return 0;
+ }
+ if (p)
+ {
+ o = _opt_infop_;
+ _opt_infop_ = p;
+ }
+ else
+ {
+ if (o = freecontext)
+ freecontext = 0;
+ else if (!(o = newof(0, Opt_t, 1, 0)))
+ return 0;
+ memset(o, 0, sizeof(Opt_t));
+ o->state = _opt_infop_->state;
+ }
+ return o;
+}
diff --git a/src/lib/libast/misc/optesc.c b/src/lib/libast/misc/optesc.c
new file mode 100644
index 0000000..8b023c5
--- /dev/null
+++ b/src/lib/libast/misc/optesc.c
@@ -0,0 +1,93 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * escape optget() special chars in s and write to sp
+ * esc == '?' or ':' also escaped
+ */
+
+#include <optlib.h>
+#include <ctype.h>
+
+int
+optesc(Sfio_t* sp, register const char* s, int esc)
+{
+ register const char* m;
+ register int c;
+
+ if (*s == '[' && *(s + 1) == '+' && *(s + 2) == '?')
+ {
+ c = strlen(s);
+ if (s[c - 1] == ']')
+ {
+ sfprintf(sp, "%-.*s", c - 4, s + 3);
+ return 0;
+ }
+ }
+ if (esc != '?' && esc != ':')
+ esc = 0;
+ while (c = *s++)
+ {
+ if (isalnum(c))
+ {
+ for (m = s - 1; isalnum(*s); s++);
+ if (isalpha(c) && *s == '(' && isdigit(*(s + 1)) && *(s + 2) == ')')
+ {
+ sfputc(sp, '\b');
+ sfwrite(sp, m, s - m);
+ sfputc(sp, '\b');
+ sfwrite(sp, s, 3);
+ s += 3;
+ }
+ else
+ sfwrite(sp, m, s - m);
+ }
+ else if (c == '-' && *s == '-' || c == '<')
+ {
+ m = s - 1;
+ if (c == '-')
+ s++;
+ else if (*s == '/')
+ s++;
+ while (isalnum(*s))
+ s++;
+ if (c == '<' && *s == '>' || isspace(*s) || *s == 0 || *s == '=' || *s == ':' || *s == ';' || *s == '.' || *s == ',')
+ {
+ sfputc(sp, '\b');
+ sfwrite(sp, m, s - m);
+ sfputc(sp, '\b');
+ }
+ else
+ sfwrite(sp, m, s - m);
+ }
+ else
+ {
+ if (c == ']' || c == esc)
+ sfputc(sp, c);
+ sfputc(sp, c);
+ }
+ }
+ return 0;
+}
diff --git a/src/lib/libast/misc/optget.c b/src/lib/libast/misc/optget.c
new file mode 100644
index 0000000..bd4df04
--- /dev/null
+++ b/src/lib/libast/misc/optget.c
@@ -0,0 +1,5751 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * command line option parser and usage formatter
+ * its a monster but its all in one place
+ * widen your window while you're at it
+ */
+
+#include <optlib.h>
+#include <debug.h>
+#include <ccode.h>
+#include <ctype.h>
+#include <errno.h>
+
+#define KEEP "*[A-Za-z][A-Za-z]*"
+#define OMIT "*@(\\[[-+]*\\?*\\]|\\@\\(#\\)|Copyright \\(c\\)|\\$\\I\\d\\: )*"
+
+#define GO '{' /* group nest open */
+#define OG '}' /* group nest close */
+
+#define OPT_WIDTH 80 /* default help text width */
+#define OPT_MARGIN 10 /* default help text margin */
+#define OPT_USAGE 7 /* usage continuation indent */
+
+#define OPT_flag 0x001 /* flag ( 0 or 1 ) */
+#define OPT_hidden 0x002 /* remaining are hidden */
+#define OPT_ignorecase 0x004 /* arg match ignores case */
+#define OPT_invert 0x008 /* flag inverts long sense */
+#define OPT_listof 0x010 /* arg is ' ' or ',' list */
+#define OPT_number 0x020 /* arg is strtonll() number */
+#define OPT_oneof 0x040 /* arg may be set once */
+#define OPT_optional 0x080 /* arg is optional */
+#define OPT_string 0x100 /* arg is string */
+
+#define OPT_preformat 0001 /* output preformat string */
+#define OPT_proprietary 0002 /* proprietary docs */
+
+#define OPT_TYPE (OPT_flag|OPT_number|OPT_string)
+
+#define STYLE_posix 0 /* posix getopt usage */
+#define STYLE_short 1 /* [default] short usage */
+#define STYLE_long 2 /* long usage */
+#define STYLE_match 3 /* long description of matches */
+#define STYLE_options 4 /* short and long descriptions */
+#define STYLE_man 5 /* pretty details */
+#define STYLE_html 6 /* html details */
+#define STYLE_nroff 7 /* nroff details */
+#define STYLE_api 8 /* program details */
+#define STYLE_keys 9 /* translation key strings */
+#define STYLE_usage 10 /* escaped usage string */
+
+#define FONT_BOLD 1
+#define FONT_ITALIC 2
+#define FONT_LITERAL 4
+
+#define HELP_head 0x01
+#define HELP_index 0x02
+
+#define TAG_NONE 0
+#define TAG_DIV 1
+#define TAG_DL 2
+
+#define SEP(c) ((c)=='-'||(c)=='_')
+
+typedef struct Attr_s
+{
+ const char* name;
+ int flag;
+} Attr_t;
+
+typedef struct Help_s
+{
+ const char* match; /* builtin help match name */
+ const char* name; /* builtin help name */
+ int style; /* STYLE_* */
+ const char* text; /* --? text */
+ unsigned int size; /* strlen text */
+} Help_t;
+
+typedef struct Font_s
+{
+ const char* html[2];
+ const char* nroff[2];
+ const char* term[2];
+} Font_t;
+
+typedef struct List_s
+{
+ int type; /* { - + : } */
+ const char* name; /* list name */
+ const char* text; /* help text */
+} List_t;
+
+typedef struct Msg_s
+{
+ const char* text; /* default message text */
+ Dtlink_t link; /* cdt link */
+} Msg_t;
+
+typedef struct Save_s
+{
+ Dtlink_t link; /* cdt link */
+ char text[1]; /* saved text text */
+} Save_t;
+
+typedef struct Push_s
+{
+ struct Push_s* next; /* next string */
+ char* ob; /* next char in old string */
+ char* oe; /* end of old string */
+ char* nb; /* next char in new string */
+ char* ne; /* end of new string */
+ int ch; /* localize() translation */
+} Push_t;
+
+typedef struct Tag_s
+{
+ unsigned char level; /* indent level */
+ unsigned char id; /* TAG_* id */
+} Tag_t;
+
+typedef struct Indent_s
+{
+ int stop; /* tab column position */
+} Indent_t;
+
+static Indent_t indent[] =
+{
+ 0,2, 4,10, 12,18, 20,26, 28,34, 36,42, 44,50, 0,0
+};
+
+static const char* end[] =
+{
+ "", "</DIV>\n", "</DL>\n"
+};
+
+static const char term_off[] = {CC_esc,'[','0','m',0};
+static const char term_B_on[] = {CC_esc,'[','1','m',0};
+static const char term_I_on[] = {CC_esc,'[','1',';','4','m',0};
+
+static const Font_t fonts[] =
+{
+ "", "", "", "", "", "",
+ "</B>", "<B>", "\\fP", "\\fB", &term_off[0], &term_B_on[0],
+ "</I>", "<I>", "\\fP", "\\fI", &term_off[0], &term_I_on[0],
+ "", "", "", "", "", "",
+ "</TT>","<TT>","\\fP", "\\f5", "", "",
+};
+
+static char native[] = "";
+
+static unsigned char map[UCHAR_MAX];
+
+static Optstate_t state;
+
+#if !_PACKAGE_astsa
+
+#define ID ast.id
+
+#define C(s) ERROR_catalog(s)
+#define D(s) (state.msgdict && dtmatch(state.msgdict, (s)))
+#define T(i,c,m) (X(c)?translate(i,c,C(m)):(m))
+#define X(c) (ERROR_translating()&&(c)!=native)
+#define Z(x) C(x),sizeof(x)-1
+
+/*
+ * translate with C_LC_MESSAGES_libast[] check
+ */
+
+static char*
+translate(const char* cmd, const char* cat, const char* msg)
+{
+ if (!X(cat))
+ return (char*)msg;
+ if (cat != (const char*)ID && D(msg))
+ cat = (const char*)ID;
+ return errorx(NiL, cmd, cat, msg);
+}
+
+#else
+
+static char ID[] = "ast";
+
+#define C(s) s
+#define D(s) (state.msgdict && dtmatch(state.msgdict, (s)))
+#define T(i,c,m) m
+#define X(c) 0
+#define Z(x) C(x),sizeof(x)-1
+
+#endif
+
+static const List_t help_head[] =
+{
+ '-', 0,
+ 0,
+ '+', C("NAME"),
+ C("options available to all \bast\b commands"),
+ '+', C("DESCRIPTION"),
+ C("\b-?\b and \b--?\b* options are the same \
+for all \bast\b commands. For any \aitem\a below, if \b--\b\aitem\a is not \
+supported by a given command then it is equivalent to \b--\?\?\b\aitem\a. The \
+\b--\?\?\b form should be used for portability. All output is written to the \
+standard error."),
+};
+
+static const Help_t styles[] =
+{
+ C("about"), "-", STYLE_match,
+ Z("List all implementation info."),
+ C("api"), "?api", STYLE_api,
+ Z("List detailed info in program readable form."),
+ C("help"), "", -1,
+ Z("List detailed help option info."),
+ C("html"), "?html", STYLE_html,
+ Z("List detailed info in html."),
+ C("keys"), "?keys", STYLE_keys,
+ Z("List the usage translation key strings with C style escapes."),
+ C("long"), "?long", STYLE_long,
+ Z("List long option usage."),
+ C("man"), "?man", STYLE_man,
+ Z("List detailed info in displayed man page form."),
+ C("nroff"), "?nroff", STYLE_nroff,
+ Z("List detailed info in nroff."),
+ C("options"), "?options", STYLE_options,
+ Z("List short and long option details."),
+ C("posix"), "?posix", STYLE_posix,
+ Z("List posix getopt usage."),
+ C("short"), "?short", STYLE_short,
+ Z("List short option usage."),
+ C("usage"), "?usage", STYLE_usage,
+ Z("List the usage string with C style escapes."),
+};
+
+static const List_t help_tail[] =
+{
+ ':', C("\?\?-\alabel\a"),
+ C("List implementation info matching \alabel\a*."),
+ ':', C("\?\?\aname\a"),
+ C("Equivalent to \b--help=\b\aname\a."),
+ ':', C("\?\?"),
+ C("Equivalent to \b--\?\?options\b."),
+ ':', C("\?\?\?\?"),
+ C("Equivalent to \b--\?\?man\b."),
+ ':', C("\?\?\?\?\?\?"),
+ C("Equivalent to \b--\?\?help\b."),
+ ':', C("\?\?\?\?\?\?\aitem\a"),
+ C("If the next argument is \b--\b\aoption\a then list \
+the \aoption\a output in the \aitem\a style. Otherwise print \
+\bversion=\b\an\a where \an\a>0 if \b--\?\?\b\aitem\a is supported, \b0\b \
+if not."),
+ ':', C("\?\?\?\?\?\?ESC"),
+ C("Emit escape codes even if output is not a terminal."),
+ ':', C("\?\?\?\?\?\?MAN[=\asection\a]]"),
+ C("List the \bman\b(1) section title for \asection\a [the \
+current command]]."),
+ ':', C("\?\?\?\?\?\?SECTION"),
+ C("List the \bman\b(1) section number for the current command."),
+ ':', C("\?\?\?\?\?\?TEST"),
+ C("Massage the output for regression testing."),
+};
+
+static const Attr_t attrs[] =
+{
+ "flag", OPT_flag,
+ "hidden", OPT_hidden,
+ "ignorecase", OPT_ignorecase,
+ "invert", OPT_invert,
+ "listof", OPT_listof,
+ "number", OPT_number,
+ "oneof", OPT_oneof,
+ "optional", OPT_optional,
+ "string", OPT_string,
+};
+
+static const char unknown[] = C("unknown option or attribute");
+
+static const char* heading[] =
+{
+ C("INDEX"),
+ C("USER COMMANDS"),
+ C("SYSTEM LIBRARY"),
+ C("USER LIBRARY"),
+ C("FILE FORMATS"),
+ C("MISCELLANEOUS"),
+ C("GAMES and DEMOS"),
+ C("SPECIAL FILES"),
+ C("ADMINISTRATIVE COMMANDS"),
+ C("GUIs"),
+};
+
+/*
+ * list of common man page strings
+ * NOTE: add but do not delete from this table
+ */
+
+static Msg_t C_LC_MESSAGES_libast[] =
+{
+ { C("APPLICATION USAGE") },
+ { C("ASYNCHRONOUS EVENTS") },
+ { C("BUGS") },
+ { C("CAVEATS") },
+ { C("CONSEQUENCES OF ERRORS") },
+ { C("DESCRIPTION") },
+ { C("ENVIRONMENT VARIABLES") },
+ { C("EXAMPLES") },
+ { C("EXIT STATUS") },
+ { C("EXTENDED DESCRIPTION") },
+ { C("INPUT FILES") },
+ { C("LIBRARY") },
+ { C("NAME") },
+ { C("OPERANDS") },
+ { C("OPTIONS") },
+ { C("OUTPUT FILES") },
+ { C("PLUGIN") },
+ { C("SEE ALSO") },
+ { C("STDERR") },
+ { C("STDIN") },
+ { C("STDOUT") },
+ { C("SYNOPSIS") },
+ { C("author") },
+ { C("copyright") },
+ { C("license") },
+ { C("name") },
+ { C("path") },
+ { C("version") },
+};
+
+/*
+ * 2007-03-19 move opt_info from _opt_info_ to (*_opt_data_)
+ * to allow future Opt_t growth
+ * by 2009 _opt_info_ can be static
+ */
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+
+extern Opt_t _opt_info_;
+
+Opt_t _opt_info_ = { 0,0,0,0,0,0,0,{0},{0},0,0,0,{0},{0},&state };
+
+#undef extern
+
+__EXTERN__(Opt_t, _opt_info_);
+
+__EXTERN__(Opt_t*, _opt_infop_);
+
+Opt_t* _opt_infop_ = &_opt_info_;
+
+Optstate_t*
+optstate(Opt_t* p)
+{
+ return &state;
+}
+
+#if DEBUG || _BLD_DEBUG
+
+/*
+ * debug usage string segment format
+ */
+
+static char*
+show(register char* s)
+{
+ register int c;
+ register char* t;
+ register char* e;
+
+ static char buf[32];
+
+ if (!s)
+ return "(null)";
+ t = buf;
+ e = buf + sizeof(buf) - 2;
+ while (t < e)
+ {
+ switch (c = *s++)
+ {
+ case 0:
+ goto done;
+ case '\a':
+ *t++ = '\\';
+ c = 'a';
+ break;
+ case '\b':
+ *t++ = '\\';
+ c = 'b';
+ break;
+ case '\f':
+ *t++ = '\\';
+ c = 'f';
+ break;
+ case '\n':
+ *t++ = '\\';
+ c = 'n';
+ break;
+ case '\t':
+ *t++ = '\\';
+ c = 't';
+ break;
+ case '\v':
+ *t++ = '\\';
+ c = 'v';
+ break;
+ }
+ *t++ = c;
+ }
+ done:
+ *t = 0;
+ return buf;
+}
+
+#endif
+
+typedef struct Section_s
+{
+ const char section[4];
+ const char* name;
+} Section_t;
+
+static const Section_t sections[] =
+{
+ "1M", "MAKE ASSERTION OPERATORS AND RULES",
+ "1", "USER COMMANDS",
+ "2", "SYSTEM CALLS",
+ "3F", "FORTRAN LIBRARY ROUTINES",
+ "3K", "KERNEL VM LIBRARY FUNCTIONS",
+ "3L", "LIGHTWEIGHT PROCESSES LIBRARY",
+ "3M", "MATHEMATICAL LIBRARY",
+ "3N", "NETWORK FUNCTIONS",
+ "3R", "RPC SERVICES LIBRARY",
+ "3S", "STANDARD I/O FUNCTIONS",
+ "3V", "SYSTEM V LIBRARY",
+ "3", "C LIBRARY FUNCTIONS",
+ "4F", "PROTOCOL FAMILIES",
+ "4P", "PROTOCOLS",
+ "4", "DEVICES AND NETWORK INTERFACES",
+ "5P", "PLUGINS",
+ "5", "FILE FORMATS",
+ "6", "GAMES AND DEMOS",
+ "7", "PUBLIC FILES AND TABLES",
+ "8", "ADMINISTRATIVE COMMANDS",
+ "L", "LOCAL COMMANDS",
+};
+
+/*
+ * return section name given abbreviation
+ */
+
+static char*
+secname(char* section)
+{
+ int i;
+ char* b;
+ char* t;
+ const char* s;
+
+ b = t = fmtbuf(64);
+ if (section[1])
+ {
+ switch (section[2] ? section[2] : section[1])
+ {
+ case 'C':
+ s = "COMPATIBILITY ";
+ break;
+ case 'U':
+ s = "UWIN ";
+ break;
+ case 'X':
+ s = "MISCELLANEOUS ";
+ break;
+ default:
+ s = 0;
+ break;
+ }
+ if (s)
+ t = strcopy(t, s);
+ }
+ s = 0;
+ for (i = 0; i < elementsof(sections); i++)
+ if (section[0] == sections[i].section[0] && (section[1] == sections[i].section[1] || !sections[i].section[1]))
+ {
+ s = sections[i].name;
+ break;
+ }
+ if (!s)
+ {
+ t = strcopy(t, "SECTION ");
+ s = section;
+ }
+ strcopy(t, s);
+ return b;
+}
+
+/*
+ * pop the push stack
+ */
+
+static Push_t*
+pop(register Push_t* psp)
+{
+ register Push_t* tsp;
+
+ while (tsp = psp)
+ {
+ psp = psp->next;
+ free(tsp);
+ }
+ return 0;
+}
+
+/*
+ * skip over line space to the next token
+ */
+
+static char*
+next(register char* s, int version)
+{
+ register char* b;
+
+ while (*s == '\t' || *s == '\r' || version >= 1 && *s == ' ')
+ s++;
+ if (*s == '\n')
+ {
+ b = s;
+ while (*++s == ' ' || *s == '\t' || *s == '\r');
+ if (*s == '\n')
+ return b;
+ }
+ return s;
+}
+
+/*
+ * skip to t1 or t2 or t3, whichever first, in s
+ * n==0 outside [...]
+ * n==1 inside [...] before ?
+ * n==2 inside [...] after ?
+ * b==0 outside {...}
+ * b==1 inside {...}
+ * past skips past the terminator to the next token
+ * otherwise a pointer to the terminator is returned
+ *
+ * ]] for ] inside [...]
+ * ?? for ? inside [...] before ?
+ * :: for : inside [...] before ?
+ */
+
+static char*
+skip(register char* s, register int t1, register int t2, register int t3, register int n, register int b, int past, int version)
+{
+ register int c;
+ register int on = n;
+ register int ob = b;
+
+ if (version < 1)
+ {
+ n = n >= 1;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ break;
+ case '[':
+ n++;
+ continue;
+ case ']':
+ if (--n <= 0)
+ break;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ }
+ else while (c = *s++)
+ {
+ message((-22, "optget: skip t1=%c t2=%c t3=%c n=%d b=%d `%s'", t1 ? t1 : '@', t2 ? t2 : '@', t3 ? t3 : '@', n, b, show(s - 1)));
+ if (c == '[')
+ {
+ if (!n)
+ n = 1;
+ }
+ else if (c == ']')
+ {
+ if (n)
+ {
+ if (*s == ']')
+ s++;
+ else if (on == 1)
+ break;
+ else
+ n = 0;
+ }
+ }
+ else if (c == GO)
+ {
+ if (n == 0)
+ b++;
+ }
+ else if (c == OG)
+ {
+ if (n == 0 && b-- == ob)
+ break;
+ }
+ else if (c == '?')
+ {
+ if (n == 1)
+ {
+ if (*s == '?')
+ s++;
+ else
+ {
+ if (n == on && (c == t1 || c == t2 || c == t3))
+ break;
+ n = 2;
+ }
+ }
+ }
+ else if (n == on && (c == t1 || c == t2 || c == t3))
+ {
+ if (n == 1 && c == ':' && *s == c)
+ s++;
+ else
+ break;
+ }
+ }
+ return past && *(s - 1) ? next(s, version) : s - 1;
+}
+
+/*
+ * *s points to '(' on input
+ * return is one past matching ')'
+ */
+
+static char*
+nest(register char* s)
+{
+ int n;
+
+ n = 0;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case '(':
+ n++;
+ continue;
+ case ')':
+ if (!--n)
+ break;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ return s;
+}
+
+/*
+ * match s with t
+ * t translated if possible
+ * embedded { - _ ' } ignored
+ * * separates required prefix from optional suffix
+ * otherwise prefix match
+ */
+
+static int
+match(char* s, char* t, int version, const char* id, const char* catalog)
+{
+ register char* w;
+ register char* x;
+ char* xw;
+ char* ww;
+ int n;
+ int v;
+ int j;
+
+ for (n = 0; n < 2; n++)
+ {
+ if (n)
+ x = t;
+ else
+ {
+ if (catalog)
+ {
+ w = skip(t, ':', '?', 0, 1, 0, 0, version);
+ w = sfprints("%-.*s", w - t, t);
+ x = T(id, catalog, w);
+ if (x == w)
+ continue;
+ }
+ x = T(NiL, ID, t);
+ if (x == t)
+ continue;
+ }
+ do
+ {
+ v = 0;
+ xw = x;
+ w = ww = s;
+ while (*x && *w)
+ {
+ if (isupper(*x))
+ xw = x;
+ if (isupper(*w))
+ ww = w;
+ if (*x == '*' && !v++ || *x == '\a')
+ {
+ if (*x == '\a')
+ do
+ {
+ if (!*++x)
+ {
+ x--;
+ break;
+ }
+ } while (*x != '\a');
+ j = *(x + 1);
+ if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
+ while (*w)
+ w++;
+ }
+ else if (SEP(*x))
+ xw = ++x;
+ else if (SEP(*w) && w != s)
+ ww = ++w;
+ else if (*x == *w)
+ {
+ x++;
+ w++;
+ }
+ else if (w == ww && x == xw)
+ break;
+ else
+ {
+ if (x != xw)
+ {
+ while (*x && !SEP(*x) && !isupper(*x))
+ x++;
+ if (!*x)
+ break;
+ if (SEP(*x))
+ x++;
+ xw = x;
+ }
+ while (w > ww && *w != *x)
+ w--;
+ }
+ }
+ if (!*w)
+ {
+ if (!v)
+ {
+ for (;;)
+ {
+ switch (*x++)
+ {
+ case 0:
+ case ':':
+ case '|':
+ case '?':
+ case ']':
+ return 1;
+ case '*':
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ break;
+ }
+ return 1;
+ }
+ } while (*(x = skip(x, '|', 0, 0, 1, 0, 0, version)) == '|' && x++);
+ }
+ return 0;
+}
+
+/*
+ * prefix search for s in tab with num elements of size
+ * with optional translation
+ */
+
+static void*
+search(const void* tab, size_t num, size_t siz, char* s)
+{
+ register char* p;
+ register char* e;
+
+ for (e = (p = (char*)tab) + num * siz; p < e; p += siz)
+ if (match(s, *((char**)p), -1, NiL, NiL))
+ return (void*)p;
+ return 0;
+}
+
+/*
+ * save ap+bp+cp and return the saved pointer
+ */
+
+static char*
+save(const char* ap, size_t az, const char* bp, size_t bz, const char* cp, size_t cz)
+{
+ char* b;
+ char* e;
+ const char* ep;
+ Save_t* p;
+ Dtdisc_t* d;
+ char buf[1024];
+
+ static Dt_t* dict;
+
+ if (!dict)
+ {
+ if (!(d = newof(0, Dtdisc_t, 1, 0)))
+ return (char*)ap;
+ d->key = offsetof(Save_t, text);
+ if (!(dict = dtopen(d, Dtset)))
+ return (char*)ap;
+ }
+ b = buf;
+ e = b + sizeof(buf) - 1;
+ for (ep = ap + az; b < e && ap < ep; *b++ = *ap++);
+ if (bp)
+ {
+ for (ep = bp + bz; b < e && bp < ep; *b++ = *bp++);
+ if (cp)
+ for (ep = cp + cz; b < e && cp < ep; *b++ = *cp++);
+ }
+ *b = 0;
+ if (!(p = (Save_t*)dtmatch(dict, buf)))
+ {
+ if (!(p = newof(0, Save_t, 1, b - buf)))
+ return (char*)ap;
+ strcpy(p->text, buf);
+ dtinsert(dict, p);
+ }
+ return p->text;
+}
+
+/*
+ * expand \f...\f info
+ * *p set to next char after second \f
+ * expanded value returned
+ */
+
+static char*
+expand(register char* s, register char* e, char** p, Sfio_t* ip, char* id)
+{
+ register int c;
+ register char* b = s;
+ int n;
+
+ n = sfstrtell(ip);
+ c = 1;
+ while ((!e || s < e) && (c = *s++) && c != '\f');
+ sfwrite(ip, b, s - b - 1);
+ sfputc(ip, 0);
+ b = sfstrbase(ip) + n;
+ n = sfstrtell(ip);
+ if (!c)
+ s--;
+ if (*b == '?')
+ {
+ if (!*++b || streq(b, "NAME"))
+ {
+ if (!(b = id))
+ b = "command";
+ sfstrseek(ip, 0, SEEK_SET);
+ sfputr(ip, b, -1);
+ n = 0;
+ }
+ else
+ n = 1;
+ }
+ else if (!opt_info.disc || !opt_info.disc->infof || (*opt_info.disc->infof)(&opt_info, ip, b, opt_info.disc) < 0)
+ n = 0;
+ *p = s;
+ if (s = sfstruse(ip))
+ s += n;
+ else
+ s = "error";
+ return s;
+}
+
+/*
+ * initialize the translation dictionary and flag maps
+ */
+
+static void
+initdict(void)
+{
+ register int n;
+
+ state.vp = sfstropen();
+ state.msgdisc.key = offsetof(Msg_t, text);
+ state.msgdisc.size = -1;
+ state.msgdisc.link = offsetof(Msg_t, link);
+ if (state.msgdict = dtopen(&state.msgdisc, Dtset))
+ for (n = 0; n < elementsof(C_LC_MESSAGES_libast); n++)
+ dtinsert(state.msgdict, C_LC_MESSAGES_libast + n);
+}
+
+/*
+ * initialize the attributes for pass p from opt string s
+ */
+
+static int
+init(register char* s, Optpass_t* p)
+{
+ register char* t;
+ register char* u;
+ register int c;
+ register int a;
+ register int n;
+ char* e;
+ int l;
+
+ if (!state.localized)
+ {
+ state.localized = 1;
+#if !_PACKAGE_astsa
+ if (!ast.locale.serial)
+ setlocale(LC_ALL, "");
+#endif
+ state.xp = sfstropen();
+ if (!map[OPT_FLAGS[0]])
+ for (n = 0, t = OPT_FLAGS; *t; t++)
+ map[*t] = ++n;
+ }
+#if _BLD_DEBUG
+ error(-1, "optget debug");
+#endif
+ p->oopts = s;
+ p->version = 0;
+ p->prefix = 2;
+ p->section[0] = '1';
+ p->section[1] = 0;
+ p->flags = 0;
+ p->id = error_info.id;
+ p->catalog = 0;
+ s = next(s, 0);
+ if (*s == ':')
+ s++;
+ if (*s == '+')
+ s++;
+ s = next(s, 0);
+ if (*s++ == '[')
+ {
+ if (*s == '+')
+ p->version = 1;
+ else if (*s++ == '-')
+ {
+ if (*s == '?' || *s == ']')
+ p->version = 1;
+ else
+ {
+ if (!isdigit(*s))
+ p->version = 1;
+ else
+ while (isdigit(*s))
+ p->version = p->version * 10 + (*s++ - '0');
+ while (*s && *s != ']')
+ {
+ if ((c = *s++) == '?')
+ {
+ p->release = s;
+ while (*s && *s != ']')
+ if (isspace(*s++))
+ p->release = s;
+ break;
+ }
+ else if (!isdigit(*s))
+ n = 1;
+ else
+ {
+ n = 0;
+ while (isdigit(*s))
+ n = n * 10 + (*s++ - '0');
+ }
+ switch (c)
+ {
+ case '+':
+ p->flags |= OPT_plus;
+ break;
+ case 'a':
+ p->flags |= OPT_append;
+ break;
+ case 'c':
+ p->flags |= OPT_cache;
+ break;
+ case 'i':
+ p->flags |= OPT_ignore;
+ break;
+ case 'l':
+ p->flags |= OPT_long;
+ break;
+ case 'm':
+ p->flags |= OPT_module;
+ break;
+ case 'n':
+ p->flags |= OPT_numeric;
+ break;
+ case 'o':
+ p->flags |= OPT_old;
+ break;
+ case 'p':
+ p->prefix = n;
+ break;
+ case 's':
+ if (n > 1 && n < 5)
+ {
+ p->flags |= OPT_functions;
+ p->prefix = 0;
+ }
+ p->section[0] = '0' + (n % 10);
+ n = 1;
+ if (isupper(*s))
+ p->section[n++] = *s++;
+ if (isupper(*s))
+ p->section[n++] = *s++;
+ p->section[n] = 0;
+ break;
+ }
+ }
+ }
+ }
+ while (*s)
+ if (*s++ == ']')
+ {
+ while (isspace(*s))
+ s++;
+ if (*s++ == '[')
+ {
+ if (*s++ != '-')
+ {
+ l = 0;
+ if (strneq(s - 1, "+NAME?", 6) && (s += 5) || strneq(s - 1, "+LIBRARY?", 9) && (s += 8) && (l = 1) || strneq(s - 1, "+PLUGIN?", 8) && (s += 7) && (l = 1))
+ {
+ for (; *s == '\a' || *s == '\b' || *s == '\v' || *s == ' '; s++);
+ if (*s == '\f')
+ {
+ if (*(s + 1) == '?' && *(s + 2) == '\f')
+ break;
+ s = expand(s + 1, NiL, &e, state.xp, p->id);
+ }
+ for (t = s; *t && *t != ' ' && *t != ']'; t++);
+ if (t > s)
+ {
+ u = t;
+ if (*(t - 1) == '\a' || *(t - 1) == '\b' || *(t - 1) == '\v')
+ t--;
+ if (t > s)
+ {
+ while (*u == ' ' || *u == '\\')
+ u++;
+ if (*u == '-' || *u == ']')
+ {
+ if (!l)
+ p->id = save(s, t - s, 0, 0, 0, 0);
+ else if ((a = strlen(p->id)) <= (n = t - s) || strncmp(p->id + a - n, s, n) || *(p->id + a - n - 1) != ':')
+ p->id = save(p->id, strlen(p->id), "::", 2, s, t - s);
+ }
+ }
+ }
+ }
+ break;
+ }
+ if (*s == '-')
+ s++;
+ if (strneq(s, "catalog?", 8))
+ p->catalog = s += 8;
+ }
+ }
+ }
+ if (!error_info.id)
+ {
+ if (!(error_info.id = p->id))
+ p->id = "command";
+ }
+ else if (p->id == error_info.id)
+ p->id = save(p->id, strlen(p->id), 0, 0, 0, 0);
+ if (s = p->catalog)
+ p->catalog = ((t = strchr(s, ']')) && (!p->id || (t - s) != strlen(p->id) || !strneq(s, p->id, t - s))) ? save(s, t - s, 0, 0, 0, 0) : (char*)0;
+ if (!p->catalog)
+ {
+ if (opt_info.disc && opt_info.disc->catalog && (!p->id || !streq(opt_info.disc->catalog, p->id)))
+ p->catalog = opt_info.disc->catalog;
+ else
+ p->catalog = ID;
+ }
+ s = p->oopts;
+ if (*s == ':')
+ s++;
+ if (*s == '+')
+ {
+ s++;
+ p->flags |= OPT_plus;
+ }
+ s = next(s, 0);
+ if (*s != '[')
+ for (t = s, a = 0; *t; t++)
+ if (!a && *t == '-')
+ {
+ p->flags |= OPT_minus;
+ break;
+ }
+ else if (*t == '[')
+ a++;
+ else if (*t == ']')
+ a--;
+ if (!p->version && (t = strchr(s, '(')) && strchr(t, ')') && (state.cp || (state.cp = sfstropen())))
+ {
+ /*
+ * solaris long option compatibility
+ */
+
+ p->version = 1;
+ for (t = p->oopts; t < s; t++)
+ sfputc(state.cp, *t);
+ n = t - p->oopts;
+ sfputc(state.cp, '[');
+ sfputc(state.cp, '-');
+ sfputc(state.cp, ']');
+ c = *s++;
+ while (c)
+ {
+ sfputc(state.cp, '[');
+ sfputc(state.cp, c);
+ if (a = (c = *s++) == ':')
+ c = *s++;
+ if (c == '(')
+ {
+ sfputc(state.cp, ':');
+ for (;;)
+ {
+ while ((c = *s++) && c != ')')
+ sfputc(state.cp, c);
+ if (!c || (c = *s++) != '(')
+ break;
+ sfputc(state.cp, '|');
+ }
+ }
+ sfputc(state.cp, ']');
+ if (a)
+ sfputr(state.cp, ":[string]", -1);
+ }
+ if (!(p->oopts = s = sfstruse(state.cp)))
+ return -1;
+ s += n;
+ }
+ p->opts = s;
+ message((-1, "version=%d prefix=%d section=%s flags=%04x id=%s catalog=%s oopts=%p", p->version, p->prefix, p->section, p->flags, p->id, p->catalog, p->oopts));
+ return 0;
+}
+
+/*
+ * return the bold set/unset sequence for style
+ */
+
+static const char*
+font(int f, int style, int set)
+{
+ switch (style)
+ {
+ case STYLE_html:
+ return fonts[f].html[set];
+ case STYLE_nroff:
+ return fonts[f].nroff[set];
+ case STYLE_short:
+ case STYLE_long:
+ case STYLE_posix:
+ case STYLE_api:
+ break;
+ default:
+ if (state.emphasis > 0)
+ return fonts[f].term[set];
+ break;
+ }
+ return "";
+}
+
+/*
+ * push \f...\f info
+ */
+
+static Push_t*
+info(Push_t* psp, char* s, char* e, Sfio_t* ip, char* id)
+{
+ register char* b;
+ int n;
+ Push_t* tsp;
+
+ static Push_t push;
+
+ b = expand(s, e, &s, ip, id);
+ n = strlen(b);
+ if (tsp = newof(0, Push_t, 1, n + 1))
+ {
+ tsp->nb = (char*)(tsp + 1);
+ tsp->ne = tsp->nb + n;
+ strcpy(tsp->nb, b);
+ }
+ else
+ tsp = &push;
+ tsp->next = psp;
+ tsp->ob = s;
+ tsp->oe = e;
+ return tsp;
+}
+
+/*
+ * push translation
+ */
+
+static Push_t*
+localize(Push_t* psp, char* s, char* e, int term, int n, Sfio_t* ip, int version, char* id, char* catalog)
+{
+ char* t;
+ char* u;
+ Push_t* tsp;
+ int c;
+
+ t = skip(s, term, 0, 0, n, 0, 0, version);
+ if (e && t > e)
+ t = e;
+ while (s < t)
+ {
+ switch (c = *s++)
+ {
+ case ':':
+ case '?':
+ if (term && *s == c)
+ s++;
+ break;
+ case ']':
+ if (*s == c)
+ s++;
+ break;
+ }
+ sfputc(ip, c);
+ }
+ if (!(s = sfstruse(ip)) || (u = T(id, catalog, s)) == s)
+ return 0;
+ n = strlen(u);
+ if (tsp = newof(0, Push_t, 1, n + 1))
+ {
+ tsp->nb = (char*)(tsp + 1);
+ tsp->ne = tsp->nb + n;
+ strcpy(tsp->nb, u);
+ tsp->ob = t;
+ tsp->oe = e;
+ tsp->ch = 1;
+ }
+ tsp->next = psp;
+ return tsp;
+}
+
+/*
+ * output label s from [ ...label...[?...] ] to sp
+ * 1 returned if the label was translated
+ */
+
+static int
+label(register Sfio_t* sp, int sep, register char* s, int about, int z, int level, int style, int f, Sfio_t* ip, int version, char* id, char* catalog)
+{
+ register int c;
+ register char* t;
+ register char* e;
+ int ostyle;
+ int a;
+ int i;
+ char* p;
+ char* q;
+ char* w;
+ char* y;
+ int va;
+ Push_t* tsp;
+
+ int r = 0;
+ int n = 1;
+ Push_t* psp = 0;
+
+ if ((ostyle = style) > (STYLE_nroff - (sep <= 0)) && f != FONT_LITERAL && f >= 0)
+ style = 0;
+ if (z < 0)
+ e = s + strlen(s);
+ else
+ e = s + z;
+ if (sep > 0)
+ {
+ if (sep == ' ' && style == STYLE_nroff)
+ sfputc(sp, '\\');
+ sfputc(sp, sep);
+ }
+ sep = !sep || z < 0;
+ va = 0;
+ y = 0;
+ if (about)
+ sfputc(sp, '(');
+ if (version < 1)
+ {
+ a = 0;
+ for (;;)
+ {
+ if (s >= e)
+ return r;
+ switch (c = *s++)
+ {
+ case '[':
+ a++;
+ break;
+ case ']':
+ if (--a < 0)
+ return r;
+ break;
+ }
+ sfputc(sp, c);
+ }
+ }
+ else if (level && (*(p = skip(s, 0, 0, 0, 1, level, 1, version)) == ':' || *p == '#'))
+ {
+ va = 0;
+ if (*++p == '?' || *p == *(p - 1))
+ {
+ p++;
+ va |= OPT_optional;
+ }
+ if (*(p = next(p, version)) == '[')
+ y = p + 1;
+ }
+ if (X(catalog) && (!level || *s == '\a' || *(s - 1) != '+') &&
+ (tsp = localize(psp, s, e, (sep || level) ? '?' : 0, sep || level, ip, version, id, catalog)))
+ {
+ psp = tsp;
+ s = psp->nb;
+ e = psp->ne;
+ r = psp->ch > 0;
+ }
+ switch (*s)
+ {
+ case '\a':
+ if (f == FONT_ITALIC || f < 0)
+ s++;
+ if (f > 0)
+ f = 0;
+ break;
+ case '\b':
+ if (f == FONT_BOLD || f < 0)
+ s++;
+ if (f > 0)
+ f = 0;
+ break;
+ case '\v':
+ if (f == FONT_LITERAL || f < 0)
+ s++;
+ if (f > 0)
+ f = 0;
+ break;
+ default:
+ if (f > 0)
+ sfputr(sp, font(f, style, 1), -1);
+ break;
+ }
+ for (;;)
+ {
+ if (s >= e)
+ {
+ if (!(tsp = psp))
+ goto restore;
+ s = psp->ob;
+ e = psp->oe;
+ psp = psp->next;
+ free(tsp);
+ continue;
+ }
+ switch (c = *s++)
+ {
+ case '(':
+ if (n)
+ {
+ n = 0;
+ if (f > 0)
+ {
+ sfputr(sp, font(f, style, 0), -1);
+ f = 0;
+ }
+ }
+ break;
+ case '?':
+ case ':':
+ case ']':
+ if (psp && psp->ch)
+ break;
+ if (y)
+ {
+ if (va & OPT_optional)
+ sfputc(sp, '[');
+ sfputc(sp, '=');
+ label(sp, 0, y, 0, -1, 0, style, f >= 0 ? FONT_ITALIC : f, ip, version, id, catalog);
+ if (va & OPT_optional)
+ sfputc(sp, ']');
+ y = 0;
+ }
+ switch (c)
+ {
+ case '?':
+ if (*s == '?')
+ s++;
+ else if (*s == ']' && *(s + 1) != ']')
+ continue;
+ else if (sep)
+ goto restore;
+ else if (X(catalog) && (tsp = localize(psp, s, e, 0, 1, ip, version, id, catalog)))
+ {
+ psp = tsp;
+ s = psp->nb;
+ e = psp->ne;
+ }
+ break;
+ case ']':
+ if (sep && *s++ != ']')
+ goto restore;
+ break;
+ case ':':
+ if (sep && *s++ != ':')
+ goto restore;
+ break;
+ }
+ break;
+ case '\a':
+ a = FONT_ITALIC;
+ setfont:
+ if (f >= 0)
+ {
+ if (f & ~a)
+ {
+ sfputr(sp, font(f, style, 0), -1);
+ f = 0;
+ }
+ if (!f && style == STYLE_html)
+ {
+ for (t = s; t < e && !isspace(*t) && !iscntrl(*t); t++);
+ if (*t == c && *++t == '(')
+ {
+ w = t;
+ if (++t < e && isdigit(*t))
+ while (++t < e && isupper(*t));
+ if (t < e && *t == ')' && t > w + 1)
+ {
+ sfprintf(sp, "<NOBR><A href=\"../man%-.*s/"
+ , t - w - 1, w + 1
+ );
+ for (q = s; q < w - 1; q++)
+ if (*q == ':' && q < w - 2 && *(q + 1) == ':')
+ {
+ sfputc(sp, '-');
+ q++;
+ }
+ else
+ sfputc(sp, *q);
+ sfprintf(sp, ".html\">%s%-.*s%s</A>%-.*s</NOBR>"
+ , font(a, style, 1)
+ , w - s - 1, s
+ , font(a, style, 0)
+ , t - w + 1, w
+ );
+ s = t + 1;
+ continue;
+ }
+ }
+ }
+ sfputr(sp, font(a, style, !!(f ^= a)), -1);
+ }
+ continue;
+ case '\b':
+ a = FONT_BOLD;
+ goto setfont;
+ case '\f':
+ psp = info(psp, s, e, ip, id);
+ if (psp->nb)
+ {
+ s = psp->nb;
+ e = psp->ne;
+ }
+ else
+ {
+ s = psp->ob;
+ psp = psp->next;
+ }
+ continue;
+ case '\n':
+ sfputc(sp, c);
+ for (i = 0; i < level; i++)
+ sfputc(sp, '\t');
+ continue;
+ case '\v':
+ a = FONT_LITERAL;
+ goto setfont;
+ case '<':
+ if (style == STYLE_html)
+ {
+ sfputr(sp, "&lt;", -1);
+ c = 0;
+ for (t = s; t < e; t++)
+ if (!isalnum(*t) && *t != '_' && *t != '.' && *t != '-')
+ {
+ if (*t == '@')
+ {
+ if (c)
+ break;
+ c = 1;
+ }
+ else if (*t == '>')
+ {
+ if (c)
+ {
+ sfprintf(sp, "<A href=\"mailto:%-.*s>%-.*s</A>&gt;", t - s, s, t - s, s);
+ s = t + 1;
+ }
+ break;
+ }
+ else
+ break;
+ }
+ continue;
+ }
+ break;
+ case '>':
+ if (style == STYLE_html)
+ {
+ sfputr(sp, "&gt;", -1);
+ continue;
+ }
+ break;
+ case '&':
+ if (style == STYLE_html)
+ {
+ sfputr(sp, "&amp;", -1);
+ continue;
+ }
+ break;
+ case '"':
+ if (style == STYLE_html)
+ {
+ sfputr(sp, "&quot;", -1);
+ continue;
+ }
+ break;
+ case '-':
+ if (ostyle == STYLE_nroff)
+ sfputc(sp, '\\');
+ break;
+ case '.':
+ if (ostyle == STYLE_nroff)
+ {
+ sfputc(sp, '\\');
+ sfputc(sp, '&');
+ }
+ break;
+ case '\\':
+ if (ostyle == STYLE_nroff)
+ {
+ c = 'e';
+ sfputc(sp, '\\');
+ }
+ break;
+ case ' ':
+ if (ostyle == STYLE_nroff)
+ sfputc(sp, '\\');
+ break;
+ }
+ sfputc(sp, c);
+ }
+ restore:
+ if (f > 0)
+ sfputr(sp, font(f, style, 0), -1);
+ if (about)
+ sfputc(sp, ')');
+ if (psp)
+ pop(psp);
+ return r;
+}
+
+/*
+ * output args description to sp from p of length n
+ */
+
+static void
+args(register Sfio_t* sp, register char* p, register int n, int flags, int style, Sfio_t* ip, int version, char* id, char* catalog)
+{
+ register int i;
+ register char* t;
+ register char* o;
+ register char* a = 0;
+ char* b;
+ int sep;
+
+ if (flags & OPT_functions)
+ sep = '\t';
+ else
+ {
+ sep = ' ';
+ o = T(NiL, ID, "options");
+ b = style == STYLE_nroff ? "\\ " : " ";
+ for (;;)
+ {
+ t = (char*)memchr(p, '\n', n);
+ if (style >= STYLE_man)
+ {
+ if (!(a = id))
+ a = "...";
+ sfprintf(sp, "\t%s%s%s%s[%s%s%s%s%s]", font(FONT_BOLD, style, 1), a, font(FONT_BOLD, style, 0), b, b, font(FONT_ITALIC, style, 1), o, font(FONT_ITALIC, style, 0), b);
+ }
+ else if (a)
+ sfprintf(sp, "%*.*s%s%s%s[%s%s%s]", OPT_USAGE - 1, OPT_USAGE - 1, T(NiL, ID, "Or:"), b, a, b, b, o, b);
+ else
+ {
+ if (!(a = error_info.id) && !(a = id))
+ a = "...";
+ if (!sfstrtell(sp))
+ sfprintf(sp, "[%s%s%s]", b, o, b);
+ }
+ if (!t)
+ break;
+ i = ++t - p;
+ if (i)
+ {
+ sfputr(sp, b, -1);
+ if (X(catalog))
+ {
+ sfwrite(ip, p, i);
+ if (b = sfstruse(ip))
+ sfputr(sp, T(id, catalog, b), -1);
+ else
+ sfwrite(sp, p, i);
+ }
+ else
+ sfwrite(sp, p, i);
+ }
+ if (style == STYLE_html)
+ sfputr(sp, "<BR>", '\n');
+ else if (style == STYLE_nroff)
+ sfputr(sp, ".br", '\n');
+ else if (style == STYLE_api)
+ sfputr(sp, ".BR", '\n');
+ p = t;
+ n -= i;
+ while (n > 0 && (*p == ' ' || *p == '\t'))
+ {
+ p++;
+ n--;
+ }
+ }
+ }
+ if (n)
+ label(sp, sep, p, 0, n, 0, style, 0, ip, version, id, catalog);
+}
+
+/*
+ * output [+-...label...?...] label s to sp
+ * according to {...} level and style
+ * return 0:header 1:paragraph
+ */
+
+static int
+item(Sfio_t* sp, char* s, int about, int level, int style, Sfio_t* ip, int version, char* id, char* catalog, int* hflags)
+{
+ register char* t;
+ int n;
+ int par;
+
+ sfputc(sp, '\n');
+ if (*s == '\n')
+ {
+ par = 0;
+ if (style >= STYLE_nroff)
+ sfprintf(sp, ".DS\n");
+ else
+ {
+ if (style == STYLE_html)
+ sfprintf(sp, "<PRE>\n");
+ else
+ sfputc(sp, '\n');
+ for (n = 0; n < level; n++)
+ sfputc(sp, '\t');
+ }
+ label(sp, 0, s + 1, about, -1, level, style, FONT_LITERAL, ip, version, id, catalog);
+ sfputc(sp, '\n');
+ if (style >= STYLE_nroff)
+ sfprintf(sp, ".DE");
+ else if (style == STYLE_html)
+ sfprintf(sp, "</PRE>");
+ }
+ else if (*s != ']' && (*s != '?' || *(s + 1) == '?'))
+ {
+ par = 0;
+ if (level)
+ {
+ if (style >= STYLE_nroff)
+ sfprintf(sp, ".H%d ", (level - (level > 2)) / 2);
+ else
+ for (n = 0; n < level; n++)
+ sfputc(sp, '\t');
+ }
+ if (style == STYLE_html)
+ {
+ if (!level)
+ {
+ if (*hflags & HELP_head)
+ sfputr(sp, "</DIV>", '\n');
+ else
+ *hflags |= HELP_head;
+ sfputr(sp, "<H4>", -1);
+ }
+ sfputr(sp, "<A name=\"", -1);
+ if (s[-1] == '-' && s[0] == 'l' && s[1] == 'i' && s[2] == 'c' && s[3] == 'e' && s[4] == 'n' && s[5] == 's' && s[6] == 'e' && s[7] == '?')
+ for (t = s + 8; *t && *t != ']'; t++)
+ if (t[0] == 'p' && (!strncmp(t, "proprietary", 11) || !strncmp(t, "private", 7)) || t[0] == 'n' && !strncmp(t, "noncommercial", 13))
+ {
+ state.flags |= OPT_proprietary;
+ break;
+ }
+ label(sp, 0, s, about, -1, level, style, -1, ip, version, id, catalog);
+ sfputr(sp, "\">", -1);
+ label(sp, 0, s, about, -1, level, style, level ? FONT_BOLD : 0, ip, version, id, catalog);
+ sfputr(sp, "</A>", -1);
+ if (!level)
+ {
+ if (!strncmp(s, C("SYNOPSIS"), strlen(C("SYNOPSIS"))))
+ sfputr(sp, "</H4>\n<DIV class=SY>", -1);
+ else
+ {
+ sfputr(sp, "</H4>\n<DIV class=SH>", -1);
+ if (!strncmp(s, C("NAME"), strlen(C("NAME"))) || !strncmp(s, C("PLUGIN"), strlen(C("PLUGIN"))))
+ *hflags |= HELP_index;
+ }
+ }
+ }
+ else
+ {
+ if (!level)
+ {
+ if (style >= STYLE_nroff)
+ sfprintf(sp, ".SH ");
+ else if (style == STYLE_man)
+ sfputc(sp, '\n');
+ else if (style != STYLE_options && style != STYLE_match || *s == '-' || *s == '+')
+ sfputc(sp, '\t');
+ }
+ label(sp, 0, s, about, -1, level, style, FONT_BOLD, ip, version, id, catalog);
+ }
+ }
+ else
+ {
+ par = 1;
+ if (style >= STYLE_nroff)
+ sfputr(sp, level ? ".SP" : ".PP", -1);
+ }
+ if (style >= STYLE_nroff || !level)
+ sfputc(sp, '\n');
+ if (par && style < STYLE_nroff)
+ for (n = 0; n < level; n++)
+ sfputc(sp, '\t');
+ return par;
+}
+
+/*
+ * output text to sp from p according to style
+ */
+
+#if _BLD_DEBUG
+
+static char* textout(Sfio_t*, char*, char*, int, int, int, int, Sfio_t*, int, char*, char*, int*);
+
+static char*
+trace_textout(Sfio_t* sp, register char* p, char* conform, int conformlen, int style, int level, int bump, Sfio_t* ip, int version, char* id, char* catalog, int* hflags, int line)
+{
+ static int depth = 0;
+
+ message((-21, "opthelp: txt#%d +++ %2d \"%s\" style=%d level=%d bump=%d", line, ++depth, show(p), style, level, bump));
+ p = textout(sp, p, conform, conformlen, style, level, bump, ip, version, id, catalog, hflags);
+ message((-21, "opthelp: txt#%d --- %2d \"%s\"", line, depth--, show(p)));
+ return p;
+}
+
+#endif
+
+static char*
+textout(Sfio_t* sp, register char* s, char* conform, int conformlen, int style, int level, int bump, Sfio_t* ip, int version, char* id, char* catalog, int* hflags)
+{
+#if _BLD_DEBUG
+#define textout(sp,s,conform,conformlen,style,level,bump,ip,version,id,catalog,hflags) trace_textout(sp,s,conform,conformlen,style,level,bump,ip,version,id,catalog,hflags,__LINE__)
+#endif
+ register char* t;
+ register int c;
+ register int n;
+ char* w;
+ char* q;
+ int a;
+ int f;
+ int par;
+ int about;
+ Push_t* tsp;
+
+ int ident = 0;
+ int lev = level;
+ Push_t* psp = 0;
+
+ again:
+ about = 0;
+ if ((c = *s) == GO)
+ {
+ for (;;)
+ {
+ while (*(s = next(s + 1, version)) == '\n');
+ if (*s == GO)
+ {
+ if (level > 1)
+ level++;
+ level++;
+ }
+ else if (*s != OG)
+ {
+ if (level <= 1 || *s != '[' || *(s + 1) != '-' || style == STYLE_man && *(s + 2) == '?' || isalpha(*(s + 2)))
+ break;
+ s = skip(s, 0, 0, 0, 1, level, 0, version);
+ }
+ else if ((level -= 2) <= lev)
+ return s + 1;
+ }
+ if (*s == '\f')
+ {
+ psp = info(psp, s + 1, NiL, ip, id);
+ if (psp->nb)
+ s = psp->nb;
+ else
+ {
+ s = psp->ob;
+ psp = psp->next;
+ }
+ }
+ if (*s != '[')
+ return s;
+ c = *++s;
+ if (level > 1)
+ level++;
+ level++;
+ }
+ if (c == '-' && level > 1)
+ {
+ if (style == STYLE_man)
+ {
+ about = 1;
+ if (*(s + 1) == '-')
+ s++;
+ }
+ else
+ for (;;)
+ {
+ s = skip(s, 0, 0, 0, 1, level, 0, version);
+ while (*(s = next(s + 1, version)) == '\n');
+ if (*s == '[')
+ {
+ if ((c = *++s) != '-')
+ break;
+ }
+ else if (*s == GO)
+ goto again;
+ else if (*s == OG)
+ return s + 1;
+ }
+ }
+ if (c == '+' || c == '-' && (bump = 3) || c != ' ' && level > 1)
+ {
+ s = skip(t = s + 1, '?', 0, 0, 1, level, 0, version);
+ if (c == '-' && (*t == '?' || isdigit(*t) || *s == '?' && *(s + 1) == '\n'))
+ {
+ if ((c = *s) != '?')
+ return skip(s, 0, 0, 0, 1, level, 1, version);
+ w = C("version");
+ par = item(sp, w, about, level, style, ip, version, id, ID, hflags);
+ for (;;)
+ {
+ while (isspace(*(s + 1)))
+ s++;
+ w = s;
+ if (w[1] == '@' && w[2] == '(' && w[3] == '#' && w[4] == ')')
+ s = w + 4;
+ else if (w[1] == '$' && w[2] == 'I' && w[3] == 'd' && w[4] == ':' && w[5] == ' ')
+ {
+ s = w + 5;
+ ident = 1;
+ }
+ else
+ break;
+ }
+ }
+ else
+ {
+ if (isdigit(c) && isdigit(*t))
+ {
+ while (isdigit(*t))
+ t++;
+ if (*t == ':')
+ t++;
+ }
+ else if (isalnum(c) && *t-- == ':')
+ {
+ if (X(catalog) || *t == *(t + 2))
+ t += 2;
+ else
+ {
+ sfprintf(ip, "%s", t);
+ if (w = sfstruse(ip))
+ *((t = w) + 1) = '|';
+ }
+ }
+ par = item(sp, t, about, level, style, ip, version, id, catalog, hflags);
+ c = *s;
+ }
+ if (!about && level)
+ par = 0;
+ }
+ else
+ {
+ if (style >= STYLE_nroff)
+ sfputc(sp, '\n');
+ else if (c == '?')
+ for (n = 0; n < level; n++)
+ sfputc(sp, '\t');
+ par = 0;
+ }
+ if (c == ':')
+ c = *(s = skip(s, '?', 0, 0, 1, 0, 0, version));
+ if ((c == ']' || c == '?' && *(s + 1) == ']' && *(s + 2) != ']' && s++) && (c = *(s = next(s + 1, version))) == GO)
+ {
+ s = textout(sp, s, conform, conformlen, style, level + bump + par + 1, 0, ip, version, id, catalog, hflags);
+ if (level > lev && *s && *(s = next(s, version)) == '[')
+ {
+ s++;
+ message((-21, "textout#%d s=%s", __LINE__, show(s)));
+ goto again;
+ }
+ }
+ else if (c == '?' || c == ' ')
+ {
+ s++;
+ if (c == ' ')
+ sfputc(sp, c);
+ else
+ {
+ if (X(catalog) && (tsp = localize(psp, s, NiL, 0, 1, ip, version, id, catalog)))
+ {
+ psp = tsp;
+ s = psp->nb;
+ }
+ if (style < STYLE_nroff)
+ for (n = 0; n < bump + 1; n++)
+ sfputc(sp, '\t');
+ }
+ if (conform)
+ {
+ sfprintf(sp, "[%-.*s %s] ", conformlen, conform, T(NiL, ID, "conformance"));
+ conform = 0;
+ }
+ if (*hflags & HELP_index)
+ {
+ *hflags &= ~HELP_index;
+ sfputr(sp, "<!--MAN-INDEX-->", -1);
+ }
+ f = 0;
+ for (;;)
+ {
+ switch (c = *s++)
+ {
+ case 0:
+ if (!(tsp = psp))
+ {
+ if (f)
+ sfputr(sp, font(f, style, 0), -1);
+ return s - 1;
+ }
+ s = psp->ob;
+ psp = psp->next;
+ free(tsp);
+ continue;
+ case ']':
+ if (psp && psp->ch)
+ break;
+ if (*s != ']')
+ {
+ if (f)
+ {
+ sfputr(sp, font(f, style, 0), -1);
+ f = 0;
+ }
+ for (;;)
+ {
+ if ((*s == '#' || *s == ':') && level > lev)
+ {
+ char* o;
+ char* v;
+ int j;
+ int m;
+ int ol;
+ int vl;
+
+ a = 0;
+ o = 0;
+ v = 0;
+ if (*++s == '?' || *s == *(s - 1))
+ {
+ s++;
+ a |= OPT_optional;
+ }
+ if (*(s = next(s, version)) == '[')
+ {
+ s = skip(s + 1, ':', '?', 0, 1, 0, 0, version);
+ while (*s == ':')
+ {
+ s = skip(t = s + 1, ':', '?', 0, 1, 0, 0, version);
+ m = s - t;
+ if (*t == '!')
+ {
+ o = t + 1;
+ ol = m - 1;
+ }
+ else if (*t == '=')
+ {
+ v = t + 1;
+ vl = m - 1;
+ }
+ else
+ for (j = 0; j < elementsof(attrs); j++)
+ if (strneq(t, attrs[j].name, m))
+ {
+ a |= attrs[j].flag;
+ break;
+ }
+ }
+ }
+ if (a & OPT_optional)
+ {
+ if (o)
+ {
+ sfprintf(sp, " %s ", T(NiL, ID, "If the option value is omitted then"));
+ sfputr(sp, font(FONT_BOLD, style, 1), -1);
+ t = o + ol;
+ while (o < t)
+ {
+ if (((c = *o++) == ':' || c == '?') && *o == c)
+ o++;
+ sfputc(sp, c);
+ }
+ sfputr(sp, font(FONT_BOLD, style, 0), -1);
+ sfprintf(sp, " %s.", T(NiL, ID, "is assumed"));
+ }
+ else
+ sfprintf(sp, " %s", T(NiL, ID, "The option value may be omitted."));
+ }
+ if (v)
+ {
+ sfprintf(sp, " %s ", T(NiL, ID, "The default value is"));
+ sfputr(sp, font(FONT_BOLD, style, 1), -1);
+ t = v + vl;
+ while (v < t)
+ {
+ if (((c = *v++) == ':' || c == '?') && *v == c)
+ v++;
+ sfputc(sp, c);
+ }
+ sfputr(sp, font(FONT_BOLD, style, 0), -1);
+ sfputc(sp, '.');
+ }
+ s = skip(s, 0, 0, 0, 1, 0, 1, version);
+ }
+ if (*(s = next(s, version)) == GO)
+ {
+ s = textout(sp, s, 0, 0, style, level + bump + !level, 0, ip, version, id, catalog, hflags);
+ if (*s && *(s = next(s, version)) == '[' && !isalnum(*(s + 1)))
+ {
+ s++;
+ message((-21, "textout#%d s=%s", __LINE__, show(s)));
+ goto again;
+ }
+ }
+ else if (*s == '[' && level > lev)
+ {
+ s++;
+ goto again;
+ }
+ else if (*s == '\f')
+ {
+ s++;
+ if (style != STYLE_keys)
+ {
+ psp = info(psp, s, NiL, ip, id);
+ if (psp->nb)
+ s = psp->nb;
+ else
+ {
+ s = psp->ob;
+ psp = psp->next;
+ }
+ }
+ }
+ else if (!*s)
+ {
+ if (!(tsp = psp))
+ break;
+ s = psp->ob;
+ psp = psp->next;
+ free(tsp);
+ }
+ else if (*s != OG)
+ break;
+ else
+ {
+ s++;
+ if ((level -= 2) <= lev)
+ break;
+ }
+ }
+ return s;
+ }
+ s++;
+ break;
+ case '\a':
+ a = FONT_ITALIC;
+ setfont:
+ if (f & ~a)
+ {
+ sfputr(sp, font(f, style, 0), -1);
+ f = 0;
+ }
+ if (!f && style == STYLE_html)
+ {
+ for (t = s; *t && !isspace(*t) && !iscntrl(*t); t++);
+ if (*t == c && *++t == '(')
+ {
+ w = t;
+ if (isdigit(*++t))
+ while (isupper(*++t));
+ if (*t == ')' && t > w + 1)
+ {
+ sfprintf(sp, "<NOBR><A href=\"../man%-.*s/"
+ , t - w - 1, w + 1
+ );
+ for (q = s; q < w - 1; q++)
+ if (*q == ':' && q < w - 2 && *(q + 1) == ':')
+ {
+ sfputc(sp, '-');
+ q++;
+ }
+ else
+ sfputc(sp, *q);
+ sfprintf(sp, ".html\">%s%-.*s%s</A>%-.*s</NOBR>"
+ , font(a, style, 1)
+ , w - s - 1, s
+ , font(a, style, 0)
+ , t - w + 1, w
+ );
+ s = t + 1;
+ continue;
+ }
+ }
+ }
+ sfputr(sp, font(a, style, !!(f ^= a)), -1);
+ continue;
+ case '\b':
+ a = FONT_BOLD;
+ goto setfont;
+ case '\f':
+ if (style != STYLE_keys)
+ {
+ psp = info(psp, s, NiL, ip, id);
+ if (psp->nb)
+ s = psp->nb;
+ else
+ {
+ s = psp->ob;
+ psp = psp->next;
+ }
+ }
+ continue;
+ case '\v':
+ a = FONT_LITERAL;
+ goto setfont;
+ case ' ':
+ if (ident && *s == '$')
+ {
+ while (*++s)
+ if (*s == ']')
+ {
+ if (*(s + 1) != ']')
+ break;
+ s++;
+ }
+ continue;
+ }
+ case '\n':
+ case '\r':
+ case '\t':
+ while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
+ s++;
+ if (*s == ']' && *(s + 1) != ']' && (!psp || !psp->ch))
+ continue;
+ c = ' ';
+ break;
+ case '<':
+ if (style == STYLE_html)
+ {
+ sfputr(sp, "&lt;", -1);
+ c = 0;
+ for (t = s; *t; t++)
+ if (!isalnum(*t) && *t != '_' && *t != '.' && *t != '-')
+ {
+ if (*t == '@')
+ {
+ if (c)
+ break;
+ c = 1;
+ }
+ else if (*t == '>')
+ {
+ if (c)
+ {
+ sfprintf(sp, "<A href=\"mailto:%-.*s\">%-.*s</A>&gt;", t - s, s, t - s, s);
+ s = t + 1;
+ }
+ break;
+ }
+ else
+ break;
+ }
+ continue;
+ }
+ break;
+ case '>':
+ if (style == STYLE_html)
+ {
+ sfputr(sp, "&gt;", -1);
+ continue;
+ }
+ break;
+ case '&':
+ if (style == STYLE_html)
+ {
+ sfputr(sp, "&amp;", -1);
+ continue;
+ }
+ break;
+ case '-':
+ if (style == STYLE_nroff)
+ sfputc(sp, '\\');
+ break;
+ case '.':
+ if (style == STYLE_nroff)
+ {
+ sfputc(sp, '\\');
+ sfputc(sp, '&');
+ }
+ break;
+ case '\\':
+ if (style == STYLE_nroff)
+ {
+ sfputc(sp, c);
+ c = 'e';
+ }
+ break;
+ }
+ sfputc(sp, c);
+ }
+ }
+ else if (c == '[' && level > lev)
+ {
+ s++;
+ goto again;
+ }
+ return s;
+}
+
+/*
+ * generate optget() help [...] list from lp
+ */
+
+static void
+list(Sfio_t* sp, register const List_t* lp)
+{
+ sfprintf(sp, "[%c", lp->type);
+ if (lp->name)
+ {
+ sfprintf(sp, "%s", lp->name);
+ if (lp->text)
+ sfprintf(sp, "?%s", lp->text);
+ }
+ sfputc(sp, ']');
+}
+
+/*
+ * return pointer to help message sans `Usage: command'
+ * if oopts is 0 then state.pass is used
+ * what:
+ * 0 ?short by default, ?long if any long options used
+ * * otherwise see help_text[] (--???)
+ * external formatter:
+ * \a...\a italic
+ * \b...\b bold
+ * \f...\f discipline infof callback on ...
+ * \v...\v literal
+ * internal formatter:
+ * \t indent
+ * \n newline
+ * margin flush pops to previous indent
+ */
+
+char*
+opthelp(const char* oopts, const char* what)
+{
+ register Sfio_t* sp;
+ register Sfio_t* mp;
+ register int c;
+ register char* p;
+ register Indent_t* ip;
+ char* t;
+ char* x;
+ char* w;
+ char* u;
+ char* y;
+ char* s;
+ char* d;
+ char* v;
+ char* cb;
+ char* dt;
+ char* ov;
+ char* pp;
+ char* rb;
+ char* re;
+ int f;
+ int i;
+ int j;
+ int m;
+ int n;
+ int a;
+ int cl;
+ int sl;
+ int vl;
+ int ol;
+ int wl;
+ int xl;
+ int rm;
+ int ts;
+ int co;
+ int z;
+ int style;
+ int head;
+ int margin;
+ int mode;
+ int mutex;
+ int prefix;
+ int version;
+ long tp;
+ char* id;
+ char* catalog;
+ Optpass_t* o;
+ Optpass_t* q;
+ Optpass_t* e;
+ Optpass_t one;
+ Optpass_t top;
+ Help_t* hp;
+ Tag_t ptstk[elementsof(indent) + 2];
+ Tag_t* pt;
+ Sfio_t* vp;
+ Push_t* tsp;
+
+ char* opts = (char*)oopts;
+ char* section = "1";
+ int flags = 0;
+ int bflags = 0;
+ int dflags = 0;
+ int hflags = 0;
+ int sflags = 0;
+ int matched = 0;
+ int paragraph = 0;
+ Push_t* psp = 0;
+ Sfio_t* sp_help = 0;
+ Sfio_t* sp_text = 0;
+ Sfio_t* sp_plus = 0;
+ Sfio_t* sp_head = 0;
+ Sfio_t* sp_body = 0;
+ Sfio_t* sp_info = 0;
+ Sfio_t* sp_misc = 0;
+
+ if (!(mp = state.mp) && !(mp = state.mp = sfstropen()))
+ goto nospace;
+ if (!what)
+ style = state.style;
+ else if (!*what)
+ style = STYLE_options;
+ else if (*what != '?')
+ style = STYLE_match;
+ else if (!*(what + 1))
+ style = STYLE_man;
+ else if ((hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), (char*)what + 1)) && hp->style >= 0)
+ {
+ style = hp->style;
+ if (*hp->name != '?')
+ what = hp->name;
+ }
+ else
+ {
+ if ((style = state.force) < STYLE_man)
+ style = STYLE_man;
+ if (!(sp_help = sfstropen()))
+ goto nospace;
+ for (i = 0; i < elementsof(help_head); i++)
+ list(sp_help, &help_head[i]);
+ for (i = 0; i < elementsof(styles); i++)
+ sfprintf(sp_help, "[:%s?%s]", styles[i].match, styles[i].text);
+ for (i = 0; i < elementsof(help_tail); i++)
+ list(sp_help, &help_tail[i]);
+ if (!(opts = sfstruse(sp_help)))
+ goto nospace;
+ }
+
+ /*
+ * this is a workaround for static optjoin() data
+ * clobbered by plugins/builtins that may be called
+ * evaluating \f...\f -- it would be good to hide
+ * optjoin() interactions a bit more ...
+ */
+
+ top = state.pass[0];
+ again:
+ if (opts)
+ {
+ for (i = 0; i < state.npass; i++)
+ if (state.pass[i].oopts == opts)
+ {
+ o = &state.pass[i];
+ break;
+ }
+ if (i >= state.npass)
+ {
+ o = &one;
+ if (init((char*)opts, o))
+ goto nospace;
+ }
+ e = o + 1;
+ }
+ else
+ {
+ if (state.npass > 0)
+ {
+ o = state.pass;
+ e = o + state.npass;
+ }
+ else if (state.npass < 0)
+ {
+ o = &state.cache->pass;
+ e = o + 1;
+ }
+ else
+ return T(NiL, ID, "[* call optget() before opthelp() *]");
+ oopts = (const char*)state.pass[0].oopts;
+ }
+ if (style <= STYLE_usage)
+ {
+ if (!(sp_text = sfstropen()) || !(sp_info = sfstropen()))
+ goto nospace;
+ if (style >= STYLE_match && style < STYLE_keys && !(sp_body = sfstropen()))
+ goto nospace;
+ }
+ switch (style)
+ {
+ case STYLE_api:
+ case STYLE_html:
+ case STYLE_nroff:
+ state.emphasis = 0;
+ break;
+ case STYLE_usage:
+ case STYLE_keys:
+ for (q = o; q < e; q++)
+ if (!(q->flags & OPT_ignore) && !streq(q->catalog, o->catalog))
+ o = q;
+ /*FALLTHROUGH*/
+ case STYLE_posix:
+ sfputc(mp, '\f');
+ break;
+ default:
+ if (!state.emphasis)
+ {
+ if (x = getenv("ERROR_OPTIONS"))
+ {
+ if (strmatch(x, "*noemphasi*"))
+ break;
+ if (strmatch(x, "*emphasi*"))
+ {
+ state.emphasis = 1;
+ break;
+ }
+ }
+ if ((x = getenv("TERM")) && strmatch(x, "(ansi|vt100|xterm)*") && isatty(sffileno(sfstderr)))
+ state.emphasis = 1;
+ }
+ break;
+ }
+ x = "";
+ xl = 0;
+ for (q = o; q < e; q++)
+ {
+ if (q->flags & OPT_ignore)
+ continue;
+ section = q->section;
+ flags |= q->flags;
+ p = q->opts;
+ prefix = q->prefix;
+ version = q->version;
+ id = q->id;
+ catalog = q->catalog;
+ switch (style)
+ {
+ case STYLE_usage:
+ if (xl)
+ sfputc(mp, '\n');
+ else
+ xl = 1;
+ psp = 0;
+ for (;;)
+ {
+ switch (c = *p++)
+ {
+ case 0:
+ if (!(tsp = psp))
+ goto style_usage;
+ p = psp->ob;
+ psp = psp->next;
+ free(tsp);
+ continue;
+ case '\a':
+ c = 'a';
+ break;
+ case '\b':
+ c = 'b';
+ break;
+ case '\f':
+ psp = info(psp, p, NiL, sp_info, id);
+ if (psp->nb)
+ p = psp->nb;
+ else
+ {
+ p = psp->ob;
+ psp = psp->next;
+ }
+ continue;
+ case '\n':
+ c = 'n';
+ break;
+ case '\r':
+ c = 'r';
+ break;
+ case '\t':
+ c = 't';
+ break;
+ case '\v':
+ c = 'v';
+ break;
+ case '"':
+ c = '"';
+ break;
+ case '\'':
+ c = '\'';
+ break;
+ case '\\':
+ c = '\\';
+ break;
+ default:
+ sfputc(mp, c);
+ continue;
+ }
+ sfputc(mp, '\\');
+ sfputc(mp, c);
+ }
+ style_usage:
+ continue;
+ case STYLE_keys:
+ a = 0;
+ psp = 0;
+ vl = 0;
+ for (;;)
+ {
+ if (!(c = *p++))
+ {
+ if (!(tsp = psp))
+ break;
+ p = psp->ob;
+ psp = psp->next;
+ free(tsp);
+ continue;
+ }
+ if (c == '\f')
+ {
+ psp = info(psp, p, NiL, sp_info, id);
+ if (psp->nb)
+ p = psp->nb;
+ else
+ {
+ p = psp->ob;
+ psp = psp->next;
+ }
+ continue;
+ }
+ f = z = 1;
+ t = 0;
+ if (a == 0 && (c == ' ' || c == '\n' && *p == '\n'))
+ {
+ if (c == ' ' && *p == ']')
+ {
+ p++;
+ continue;
+ }
+ if (*p == '\n')
+ p++;
+ a = c;
+ }
+ else if (c == '\n')
+ {
+ if (a == ' ')
+ a = -1;
+ else if (a == '\n' || *p == '\n')
+ {
+ a = -1;
+ p++;
+ }
+ continue;
+ }
+ else if ((c == ':' || c == '#') && (*p == '[' || *p == '?' && *(p + 1) == '[' && p++))
+ p++;
+ else if (c != '[')
+ {
+ if (c == GO)
+ vl++;
+ else if (c == OG)
+ vl--;
+ continue;
+ }
+ else if (*p == ' ')
+ {
+ p++;
+ continue;
+ }
+ else if (*p == '-')
+ {
+ z = 0;
+ if (*++p == '-')
+ {
+ p = skip(p, 0, 0, 0, 1, 0, 1, version);
+ continue;
+ }
+ }
+ else if (*p == '+')
+ {
+ p++;
+ if (vl > 0 && *p != '\a')
+ {
+ f = 0;
+ p = skip(p, '?', 0, 0, 1, 0, 0, version);
+ if (*p == '?')
+ p++;
+ }
+ }
+ else
+ {
+ if (*(p + 1) == '\f' && (vp = state.vp))
+ p = expand(p + 2, NiL, &t, vp, id);
+ p = skip(p, ':', '?', 0, 1, 0, 0, version);
+ if (*p == ':')
+ p++;
+ }
+ if (f && *p == '?' && *(p + 1) != '?')
+ {
+ f = 0;
+ if (z)
+ p++;
+ else
+ p = skip(p, 0, 0, 0, 1, 0, 0, version);
+ }
+ if (*p == ']' && *(p + 1) != ']')
+ {
+ p++;
+ continue;
+ }
+ if (!*p)
+ {
+ if (!t)
+ break;
+ p = t;
+ t = 0;
+ }
+ m = sfstrtell(mp);
+ sfputc(mp, '"');
+ xl = 1;
+ /*UNDENT...*/
+
+ for (;;)
+ {
+ if (!(c = *p++))
+ {
+ if (t)
+ {
+ p = t;
+ t = 0;
+ }
+ if (!(tsp = psp))
+ {
+ p--;
+ break;
+ }
+ p = psp->ob;
+ psp = psp->next;
+ free(tsp);
+ continue;
+ }
+ if (a > 0)
+ {
+ if (c == '\n')
+ {
+ if (a == ' ')
+ {
+ a = -1;
+ break;
+ }
+ if (a == '\n' || *p == '\n')
+ {
+ a = -1;
+ p++;
+ break;
+ }
+ }
+ }
+ else if (c == ']')
+ {
+ if (*p != ']')
+ {
+ sfputc(mp, 0);
+ y = sfstrbase(mp) + m + 1;
+ if (D(y) || !strmatch(y, KEEP) || strmatch(y, OMIT))
+ {
+ sfstrseek(mp, m, SEEK_SET);
+ xl = 0;
+ }
+ else
+ sfstrseek(mp, -1, SEEK_CUR);
+ break;
+ }
+ sfputc(mp, *p++);
+ continue;
+ }
+ switch (c)
+ {
+ case '?':
+ if (f)
+ {
+ if (*p == '?')
+ {
+ p++;
+ sfputc(mp, c);
+ }
+ else
+ {
+ f = 0;
+ sfputc(mp, 0);
+ y = sfstrbase(mp) + m + 1;
+ if (D(y) || !strmatch(y, KEEP) || strmatch(y, OMIT))
+ {
+ sfstrseek(mp, m, SEEK_SET);
+ xl = 0;
+ }
+ else
+ sfstrseek(mp, -1, SEEK_CUR);
+ if (z && (*p != ']' || *(p + 1) == ']'))
+ {
+ if (xl)
+ {
+ sfputc(mp, '"');
+ sfputc(mp, '\n');
+ }
+ m = sfstrtell(mp);
+ sfputc(mp, '"');
+ xl = 1;
+ }
+ else
+ {
+ p = skip(p, 0, 0, 0, 1, 0, 0, version);
+ if (*p == '?')
+ p++;
+ }
+ }
+ }
+ else
+ sfputc(mp, c);
+ continue;
+ case ':':
+ if (f && *p == ':')
+ p++;
+ sfputc(mp, c);
+ continue;
+ case '\a':
+ c = 'a';
+ break;
+ case '\b':
+ c = 'b';
+ break;
+ case '\f':
+ c = 'f';
+ break;
+ case '\n':
+ c = 'n';
+ break;
+ case '\r':
+ c = 'r';
+ break;
+ case '\t':
+ c = 't';
+ break;
+ case '\v':
+ c = 'v';
+ break;
+ case '"':
+ c = '"';
+ break;
+ case '\\':
+ c = '\\';
+ break;
+ case CC_esc:
+ c = 'E';
+ break;
+ default:
+ sfputc(mp, c);
+ continue;
+ }
+ sfputc(mp, '\\');
+ sfputc(mp, c);
+ }
+
+ /*...INDENT*/
+ if (xl)
+ {
+ sfputc(mp, '"');
+ sfputc(mp, '\n');
+ }
+ }
+ continue;
+ }
+ z = 0;
+ head = 0;
+ mode = 0;
+ mutex = 0;
+ if (style > STYLE_short && style < STYLE_nroff && version < 1)
+ {
+ style = STYLE_short;
+ if (sp_body)
+ {
+ sfclose(sp_body);
+ sp_body = 0;
+ }
+ }
+ else if (style == STYLE_short && prefix < 2)
+ style = STYLE_long;
+ if (*p == ':')
+ p++;
+ if (*p == '+')
+ {
+ p++;
+ if (!(sp = sp_plus) && !(sp = sp_plus = sfstropen()))
+ goto nospace;
+ }
+ else if (style >= STYLE_match)
+ sp = sp_body;
+ else
+ sp = sp_text;
+ psp = 0;
+ for (;;)
+ {
+ if (!(*(p = next(p, version))))
+ {
+ if (!(tsp = psp))
+ break;
+ p = psp->ob;
+ psp = psp->next;
+ free(tsp);
+ continue;
+ }
+ if (*p == '\f')
+ {
+ psp = info(psp, p + 1, NiL, sp_info, id);
+ if (psp->nb)
+ p = psp->nb;
+ else
+ {
+ p = psp->ob;
+ psp = psp->next;
+ }
+ continue;
+ }
+ if (*p == '\n' || *p == ' ')
+ {
+ if (*(x = p = next(p + 1, version)))
+ while (*++p)
+ if (*p == '\n')
+ {
+ while (*++p == ' ' || *p == '\t' || *p == '\r');
+ if (*p == '\n')
+ break;
+ }
+ xl = p - x;
+ if (!*p)
+ break;
+ continue;
+ }
+ if (*p == OG)
+ {
+ p++;
+ continue;
+ }
+ message((-20, "opthelp: opt %s", show(p)));
+ if (z < 0)
+ z = 0;
+ a = 0;
+ f = 0;
+ w = 0;
+ d = 0;
+ s = 0;
+ rb = re = 0;
+ sl = 0;
+ vl = 0;
+ if (*p == '[')
+ {
+ if ((c = *(p = next(p + 1, version))) == '(')
+ {
+ p = nest(cb = p);
+ cl = p - cb;
+ c = *p;
+ }
+ else
+ cb = 0;
+ if (c == '-')
+ {
+ if (style >= STYLE_man)
+ {
+ if (*(p + 1) != '-')
+ {
+ if (!sp_misc && !(sp_misc = sfstropen()))
+ goto nospace;
+ else
+ p = textout(sp_misc, p, cb, cl, style, 1, 3, sp_info, version, id, catalog, &hflags);
+ continue;
+ }
+ }
+ else if (style == STYLE_match && *what == '-')
+ {
+ if (*(p + 1) == '?' || *(s = skip(p + 1, ':', '?', 0, 1, 0, 0, version)) == '?' && isspace(*(s + 1)))
+ s = C("version");
+ else
+ s = p + 1;
+ w = (char*)what;
+ if (*s != '-' || *(w + 1) == '-')
+ {
+ if (*s == '-')
+ s++;
+ if (*(w + 1) == '-')
+ w++;
+ if (match(w + 1, s, version, id, catalog))
+ {
+ if (*(p + 1) == '-')
+ p++;
+ p = textout(sp, p, cb, cl, style, 1, 3, sp_info, version, id, catalog, &hflags);
+ matched = -1;
+ continue;
+ }
+ }
+ }
+ if (!z)
+ z = -1;
+ }
+ else if (c == '+')
+ {
+ if (style >= STYLE_man)
+ {
+ p = textout(sp_body, p, cb, cl, style, 0, 0, sp_info, version, id, catalog, &bflags);
+ if (!sp_head)
+ {
+ sp_head = sp_body;
+ hflags = dflags = bflags;
+ if (!(sp_body = sfstropen()))
+ goto nospace;
+ }
+ continue;
+ }
+ else if (style == STYLE_match && *what == '+')
+ {
+ if (paragraph)
+ {
+ if (p[1] == '?')
+ {
+ p = textout(sp, p, cb, cl, style, 1, 3, sp_info, version, id, catalog, &hflags);
+ continue;
+ }
+ paragraph = 0;
+ }
+ if (match((char*)what + 1, p + 1, version, id, catalog))
+ {
+ p = textout(sp, p, cb, cl, style, 1, 3, sp_info, version, id, catalog, &hflags);
+ matched = -1;
+ paragraph = 1;
+ continue;
+ }
+ }
+ if (!z)
+ z = -1;
+ }
+ else if (c == '[' || version < 1)
+ {
+ mutex++;
+ continue;
+ }
+ else
+ {
+ if (c == '!')
+ {
+ a |= OPT_invert;
+ p++;
+ }
+ rb = p;
+ if (*p != ':')
+ {
+ s = p;
+ if (*(p + 1) == '|')
+ {
+ while (*++p && *p != '=' && *p != '!' && *p != ':' && *p != '?');
+ if ((p - s) > 1)
+ sl = p - s;
+ if (*p == '!')
+ a |= OPT_invert;
+ }
+ if (*(p + 1) == '\f')
+ p++;
+ else
+ p = skip(p, ':', '?', 0, 1, 0, 0, version);
+ if (sl || (p - s) == 1 || *(s + 1) == '=' || *(s + 1) == '!' && (a |= OPT_invert) || *(s + 1) == '|')
+ f = *s;
+ }
+ re = p;
+ if (style <= STYLE_short)
+ {
+ if (!z && !f)
+ z = -1;
+ }
+ else
+ {
+ if (*p == '\f' && (vp = state.vp))
+ p = expand(p + 1, NiL, &t, vp, id);
+ else
+ t = 0;
+ if (*p == ':')
+ {
+ p = skip(w = p + 1, ':', '?', 0, 1, 0, 0, version);
+ if (!(wl = p - w))
+ w = 0;
+ }
+ else
+ wl = 0;
+ if (*p == ':' || *p == '?')
+ {
+ d = p;
+ p = skip(p, 0, 0, 0, 1, 0, 0, version);
+ }
+ else
+ d = 0;
+ if (style == STYLE_match)
+ {
+ if (wl && !match((char*)what, w, version, id, catalog))
+ wl = 0;
+ if ((!wl || *w == ':' || *w == '?') && (what[1] || sl && !memchr(s, what[0], sl) || !sl && what[0] != f))
+ {
+ w = 0;
+ if (!z)
+ z = -1;
+ }
+ else
+ matched = 1;
+ }
+ if (t)
+ {
+ p = t;
+ if (*p == ':' || *p == '?')
+ {
+ d = p;
+ p = skip(p, 0, 0, 0, 1, 0, 0, version);
+ }
+ }
+ }
+ }
+ p = skip(p, 0, 0, 0, 1, 0, 1, version);
+ if (*p == GO)
+ p = skip(p + 1, 0, 0, 0, 0, 1, 1, version);
+ }
+ else if (*p == ']')
+ {
+ if (mutex)
+ {
+ if (style >= STYLE_nroff)
+ sfputr(sp_body, "\n.OP - - anyof", '\n');
+ if (!(mutex & 1))
+ {
+ mutex--;
+ if (style <= STYLE_long)
+ {
+ sfputc(sp_body, ' ');
+ sfputc(sp_body, ']');
+ }
+ }
+ mutex--;
+ }
+ p++;
+ continue;
+ }
+ else if (*p == '?')
+ {
+ if (style < STYLE_match)
+ z = 1;
+ mode |= OPT_hidden;
+ p++;
+ continue;
+ }
+ else if (*p == '\\' && style==STYLE_posix)
+ {
+ if (*++p)
+ p++;
+ continue;
+ }
+ else
+ {
+ f = *p++;
+ s = 0;
+ if (style == STYLE_match && !z)
+ z = -1;
+ }
+ if (!z)
+ {
+ if (style == STYLE_long || prefix < 2 || (q->flags & OPT_long))
+ f = 0;
+ else if (style <= STYLE_short)
+ w = 0;
+ if (!f && !w)
+ z = -1;
+ }
+ ov = 0;
+ u = v = y = 0;
+ if (*p == ':' && (a |= OPT_string) || *p == '#' && (a |= OPT_number))
+ {
+ message((-21, "opthelp: arg %s", show(p)));
+ if (*++p == '?' || *p == *(p - 1))
+ {
+ p++;
+ a |= OPT_optional;
+ }
+ if (*(p = next(p, version)) == '[')
+ {
+ if (!z)
+ {
+ p = skip(y = p + 1, ':', '?', 0, 1, 0, 0, version);
+ while (*p == ':')
+ {
+ p = skip(t = p + 1, ':', '?', 0, 1, 0, 0, version);
+ m = p - t;
+ if (*t == '!')
+ {
+ ov = t + 1;
+ ol = m - 1;
+ }
+ else if (*t == '=')
+ {
+ v = t + 1;
+ vl = m - 1;
+ }
+ else
+ for (j = 0; j < elementsof(attrs); j++)
+ if (strneq(t, attrs[j].name, m))
+ {
+ a |= attrs[j].flag;
+ break;
+ }
+ }
+ if (*p == '?')
+ u = p;
+ p = skip(p, 0, 0, 0, 1, 0, 1, version);
+ }
+ else
+ p = skip(p + 1, 0, 0, 0, 1, 0, 1, version);
+ }
+ else
+ y = (a & OPT_number) ? T(NiL, ID, "#") : T(NiL, ID, "arg");
+ }
+ else
+ a |= OPT_flag;
+ if (!z)
+ {
+ if (style <= STYLE_short && !y && !mutex || style == STYLE_posix)
+ {
+ if (style != STYLE_posix && !sfstrtell(sp))
+ {
+ sfputc(sp, '[');
+ if (sp == sp_plus)
+ sfputc(sp, '+');
+ sfputc(sp, '-');
+ }
+ if (!sl)
+ sfputc(sp, f);
+ else
+ for (c = 0; c < sl; c++)
+ if (s[c] != '|')
+ sfputc(sp, s[c]);
+ if (style == STYLE_posix && y)
+ sfputc(sp, ':');
+ }
+ else
+ {
+ if (style >= STYLE_match)
+ {
+ sfputc(sp_body, '\n');
+ if (!head)
+ {
+ head = 1;
+ item(sp_body, (flags & OPT_functions) ? C("FUNCTIONS") : C("OPTIONS"), 0, 0, style, sp_info, version, id, ID, &bflags);
+ }
+ if (style >= STYLE_nroff)
+ {
+ if (mutex & 1)
+ {
+ mutex++;
+ sfputr(sp_body, "\n.OP - - oneof", '\n');
+ }
+ }
+ else
+ sfputc(sp_body, '\t');
+ }
+ else
+ {
+ if (sp_body)
+ sfputc(sp_body, ' ');
+ else if (!(sp_body = sfstropen()))
+ goto nospace;
+ if (mutex)
+ {
+ if (mutex & 1)
+ {
+ mutex++;
+ sfputc(sp_body, '[');
+ }
+ else
+ sfputc(sp_body, '|');
+ sfputc(sp_body, ' ');
+ }
+ else
+ sfputc(sp_body, '[');
+ }
+ if (style >= STYLE_nroff)
+ {
+ if (flags & OPT_functions)
+ {
+ sfputr(sp_body, ".FN", ' ');
+ if (re > rb)
+ sfwrite(sp_body, rb, re - rb);
+ else
+ sfputr(sp, "void", -1);
+ if (w)
+ label(sp_body, ' ', w, 0, -1, 0, style, FONT_BOLD, sp_info, version, id, catalog);
+ }
+ else
+ {
+ sfputr(sp_body, ".OP", ' ');
+ if (sl)
+ sfwrite(sp_body, s, sl);
+ else
+ sfputc(sp_body, f ? f : '-');
+ sfputc(sp_body, ' ');
+ if (w)
+ {
+ if (label(sp_body, 0, w, 0, -1, 0, style, 0, sp_info, version, id, catalog))
+ {
+ sfputc(sp_body, '|');
+ label(sp_body, 0, w, 0, -1, 0, style, 0, sp_info, version, id, native);
+ }
+ }
+ else
+ sfputc(sp_body, '-');
+ sfputc(sp_body, ' ');
+ m = a & OPT_TYPE;
+ for (j = 0; j < elementsof(attrs); j++)
+ if (m & attrs[j].flag)
+ {
+ sfputr(sp_body, attrs[j].name, -1);
+ break;
+ }
+ if (m = (a & ~m) | mode)
+ for (j = 0; j < elementsof(attrs); j++)
+ if (m & attrs[j].flag)
+ {
+ sfputc(sp_body, ':');
+ sfputr(sp_body, attrs[j].name, -1);
+ }
+ sfputc(sp_body, ' ');
+ if (y)
+ label(sp_body, 0, y, 0, -1, 0, style, 0, sp_info, version, id, catalog);
+ else
+ sfputc(sp_body, '-');
+ if (v)
+ sfprintf(sp_body, " %-.*s", vl, v);
+ }
+ }
+ else
+ {
+ if (f)
+ {
+ if (sp_body == sp_plus)
+ sfputc(sp_body, '+');
+ sfputc(sp_body, '-');
+ sfputr(sp_body, font(FONT_BOLD, style, 1), -1);
+ if (!sl)
+ {
+ sfputc(sp_body, f);
+ if (f == '-' && y)
+ {
+ y = 0;
+ sfputr(sp_body, C("long-option[=value]"), -1);
+ }
+ }
+ else
+ sfwrite(sp_body, s, sl);
+ sfputr(sp_body, font(FONT_BOLD, style, 0), -1);
+ if (w)
+ {
+ sfputc(sp_body, ',');
+ sfputc(sp_body, ' ');
+ }
+ }
+ else if ((flags & OPT_functions) && re > rb)
+ {
+ sfwrite(sp_body, rb, re - rb);
+ sfputc(sp_body, ' ');
+ }
+ if (w)
+ {
+ if (prefix > 0)
+ {
+ sfputc(sp_body, '-');
+ if (prefix > 1)
+ sfputc(sp_body, '-');
+ }
+ if (label(sp_body, 0, w, 0, -1, 0, style, FONT_BOLD, sp_info, version, id, catalog))
+ {
+ sfputc(sp_body, '|');
+ label(sp_body, 0, w, 0, -1, 0, style, FONT_BOLD, sp_info, version, id, native);
+ }
+ }
+ if (y)
+ {
+ if (a & OPT_optional)
+ sfputc(sp_body, '[');
+ else if (!w)
+ sfputc(sp_body, ' ');
+ if (w)
+ sfputc(sp_body, prefix == 1 ? ' ' : '=');
+ label(sp_body, 0, y, 0, -1, 0, style, FONT_ITALIC, sp_info, version, id, catalog);
+ if (a & OPT_optional)
+ sfputc(sp_body, ']');
+ }
+ }
+ if (style >= STYLE_match)
+ {
+ if (d)
+ {
+ textout(sp_body, d, cb, cl, style, 0, 3, sp_info, version, id, catalog, &bflags);
+ cb = 0;
+ }
+ if (u)
+ textout(sp_body, u, cb, cl, style, 0, 3, sp_info, version, id, catalog, &bflags);
+ if ((a & OPT_invert) && w && (d || u))
+ {
+ u = skip(w, ':', '?', 0, 1, 0, 0, version);
+ if (f)
+ sfprintf(sp_info, " %s; -\b%c\b %s --\bno%-.*s\b.", T(NiL, ID, "On by default"), f, T(NiL, ID, "means"), u - w, w);
+ else
+ sfprintf(sp_info, " %s %s\bno%-.*s\b %s.", T(NiL, ID, "On by default; use"), "--"+2-prefix, u - w, w, T(NiL, ID, "to turn off"));
+ if (!(t = sfstruse(sp_info)))
+ goto nospace;
+ textout(sp_body, t, 0, 0, style, 0, 0, sp_info, version, NiL, NiL, &bflags);
+ }
+ if (*p == GO)
+ {
+ p = u ? skip(p + 1, 0, 0, 0, 0, 1, 1, version) : textout(sp_body, p, 0, 0, style, 4, 0, sp_info, version, id, catalog, &bflags);
+ y = "+?";
+ }
+ else
+ y = " ";
+ if (a & OPT_optional)
+ {
+ if (ov)
+ {
+ sfprintf(sp_info, "%s%s \b", y, T(NiL, ID, "If the option value is omitted then"));
+ t = ov + ol;
+ while (ov < t)
+ {
+ if (((c = *ov++) == ':' || c == '?') && *ov == c)
+ ov++;
+ sfputc(sp_info, c);
+ }
+ sfprintf(sp_info, "\b %s.", T(NiL, ID, "is assumed"));
+ }
+ else
+ sfprintf(sp_info, "%s%s", y, T(NiL, ID, "The option value may be omitted."));
+ if (!(t = sfstruse(sp_info)))
+ goto nospace;
+ textout(sp_body, t, 0, 0, style, 4, 0, sp_info, version, NiL, NiL, &bflags);
+ y = " ";
+ }
+ if (v)
+ {
+ sfprintf(sp_info, "%s%s \b", y, T(NiL, ID, "The default value is"));
+ t = v + vl;
+ while (v < t)
+ {
+ if (((c = *v++) == ':' || c == '?') && *v == c)
+ v++;
+ sfputc(sp_info, c);
+ }
+ sfputc(sp_info, '\b');
+ sfputc(sp_info, '.');
+ if (!(t = sfstruse(sp_info)))
+ goto nospace;
+ textout(sp_body, t, 0, 0, style, 4, 0, sp_info, version, NiL, NiL, &bflags);
+ }
+ }
+ else if (!mutex)
+ sfputc(sp_body, ']');
+ }
+ if (*p == GO)
+ {
+ if (style >= STYLE_match)
+ p = textout(sp_body, p, 0, 0, style, 4, 0, sp_info, version, id, catalog, &bflags);
+ else
+ p = skip(p + 1, 0, 0, 0, 0, 1, 1, version);
+ }
+ }
+ else if (*p == GO)
+ p = skip(p + 1, 0, 0, 0, 0, 1, 1, version);
+ }
+ psp = pop(psp);
+ if (sp_misc)
+ {
+ if (!(p = sfstruse(sp_misc)))
+ goto nospace;
+ for (t = p; *t == '\t' || *t == '\n'; t++);
+ if (*t)
+ {
+ item(sp_body, C("IMPLEMENTATION"), 0, 0, style, sp_info, version, id, ID, &bflags);
+ sfputr(sp_body, p, -1);
+ }
+ }
+ }
+ if (oopts != o->oopts && oopts == top.oopts)
+ state.pass[0] = top;
+ version = o->version;
+ id = o->id;
+ catalog = o->catalog;
+ if (style >= STYLE_keys)
+ {
+ if (sp_info)
+ sfclose(sp_info);
+ if (style == STYLE_keys && sfstrtell(mp) > 1)
+ sfstrseek(mp, -1, SEEK_CUR);
+ if (!(p = sfstruse(mp)))
+ goto nospace;
+ return opt_info.msg = p;
+ }
+ sp = sp_text;
+ if (sfstrtell(sp) && style != STYLE_posix)
+ sfputc(sp, ']');
+ if (style == STYLE_nroff)
+ {
+ char rd[64];
+ char ud[64];
+
+ s = o->id;
+ t = ud;
+ while (t < &ud[sizeof(ud)-2] && (c = *s++))
+ {
+ if (islower(c))
+ c = toupper(c);
+ *t++ = c;
+ }
+ *t = 0;
+ t = rd;
+ if (s = o->release)
+ {
+ *t++ = ' ';
+ while (t < &rd[sizeof(rd)-2] && (c = *s++) && c != ']')
+ *t++ = c;
+ }
+ *t = 0;
+ sfprintf(sp, "\
+.\\\" format with nroff|troff|groff -man\n\
+.TH %s %s%s\n\
+.fp 5 CW\n\
+.nr mH 5\n\
+.de H0\n\
+.nr mH 0\n\
+.in 5n\n\
+\\fB\\\\$1\\fP\n\
+.in 7n\n\
+..\n\
+.de H1\n\
+.nr mH 1\n\
+.in 7n\n\
+\\fB\\\\$1\\fP\n\
+.in 9n\n\
+..\n\
+.de H2\n\
+.nr mH 2\n\
+.in 11n\n\
+\\fB\\\\$1\\fP\n\
+.in 13n\n\
+..\n\
+.de H3\n\
+.nr mH 3\n\
+.in 15n\n\
+\\fB\\\\$1\\fP\n\
+.in 17n\n\
+..\n\
+.de H4\n\
+.nr mH 4\n\
+.in 19n\n\
+\\fB\\\\$1\\fP\n\
+.in 21n\n\
+..\n\
+.de OP\n\
+.nr mH 0\n\
+.ie !'\\\\$1'-' \\{\n\
+.ds mO \\\\fB\\\\-\\\\$1\\\\fP\n\
+.ds mS ,\\\\0\n\
+.\\}\n\
+.el \\{\n\
+.ds mO \\\\&\n\
+.ds mS \\\\&\n\
+.\\}\n\
+.ie '\\\\$2'-' \\{\n\
+.if !'\\\\$4'-' .as mO \\\\0\\\\fI\\\\$4\\\\fP\n\
+.\\}\n\
+.el \\{\n\
+.as mO \\\\*(mS\\\\fB%s\\\\$2\\\\fP\n\
+.if !'\\\\$4'-' .as mO =\\\\fI\\\\$4\\\\fP\n\
+.\\}\n\
+.in 5n\n\
+\\\\*(mO\n\
+.in 9n\n\
+..\n\
+.de SP\n\
+.if \\\\n(mH==2 .in 9n\n\
+.if \\\\n(mH==3 .in 13n\n\
+.if \\\\n(mH==4 .in 17n\n\
+..\n\
+.de FN\n\
+.nr mH 0\n\
+.in 5n\n\
+\\\\$1 \\\\$2\n\
+.in 9n\n\
+..\n\
+.de DS\n\
+.in +3n\n\
+.ft 5\n\
+.nf\n\
+..\n\
+.de DE\n\
+.fi\n\
+.ft R\n\
+.in -3n\n\
+..\n\
+"
+, ud
+, section
+, rd
+, o->prefix == 2 ? "\\\\-\\\\-" : o->prefix == 1 ? "\\\\-" : ""
+);
+ }
+ if (style == STYLE_match)
+ {
+ if (!matched)
+ {
+ if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), (char*)what))
+ {
+ if (!sp_help && !(sp_help = sfstropen()))
+ goto nospace;
+ sfprintf(sp_help, "[-][:%s?%s]", hp->match, hp->text);
+ if (!(opts = sfstruse(sp_help)))
+ goto nospace;
+ goto again;
+ }
+ s = (char*)unknown;
+ goto nope;
+ }
+ else if (matched < 0)
+ x = 0;
+ }
+ if (sp_plus)
+ {
+ if (sfstrtell(sp_plus))
+ {
+ if (sfstrtell(sp))
+ sfputc(sp, ' ');
+ if (!(t = sfstruse(sp_plus)))
+ goto nospace;
+ sfputr(sp, t, ']');
+ }
+ sfclose(sp_plus);
+ }
+ if (style >= STYLE_man)
+ {
+ if (sp_head)
+ {
+ if (!(t = sfstruse(sp_head)))
+ goto nospace;
+ for (; *t == '\n'; t++);
+ sfputr(sp, t, '\n');
+ sfclose(sp_head);
+ sp_head = 0;
+ }
+ if (x)
+ item(sp, C("SYNOPSIS"), 0, 0, style, sp_info, version, id, ID, &hflags);
+ }
+ if (x)
+ {
+ for (t = x + xl; t > x && (*(t - 1) == '\n' || *(t - 1) == '\r'); t--);
+ xl = t - x;
+ if (style >= STYLE_match)
+ {
+ u = id;
+ if (o->flags & OPT_functions)
+ t = 0;
+ else if (t = strchr(u, ':'))
+ {
+ if ((o->flags & OPT_module) && *(t + 1) == ':' && *(t + 2))
+ {
+ u = t + 2;
+ t = 0;
+ }
+ else
+ *t = 0;
+ }
+ args(sp, x, xl, o->flags, style, sp_info, version, u, catalog);
+ if (t)
+ *t = ':';
+ x = 0;
+ }
+ }
+ if (sp_body)
+ {
+ if (sfstrtell(sp_body))
+ {
+ if (style < STYLE_match && sfstrtell(sp))
+ sfputc(sp, ' ');
+ if (!(t = sfstruse(sp_body)))
+ goto nospace;
+ if (style == STYLE_html && !(dflags & HELP_head) && (bflags & HELP_head))
+ sfputr(sp, "\n</DIV>", '\n');
+ sfputr(sp, t, -1);
+ }
+ sfclose(sp_body);
+ sp_body = 0;
+ }
+ if (x && style != STYLE_posix)
+ args(sp, x, xl, flags, style, sp_info, version, id, catalog);
+ if (sp_info)
+ {
+ sfclose(sp_info);
+ sp_info = 0;
+ }
+ if (sp_misc)
+ {
+ sfclose(sp_misc);
+ sp_misc = 0;
+ }
+ if (!(p = sfstruse(sp)))
+ goto nospace;
+ astwinsize(1, NiL, &state.width);
+ if (state.width < 20)
+ state.width = OPT_WIDTH;
+ m = strlen((style <= STYLE_long && error_info.id && !strchr(error_info.id, '/')) ? error_info.id : id) + 1;
+ margin = style == STYLE_api ? (8 * 1024) : (state.width - 1);
+ if (!(state.flags & OPT_preformat))
+ {
+ if (style >= STYLE_man || matched < 0)
+ {
+ sfputc(mp, '\f');
+ ts = 0;
+ }
+ else
+ ts = OPT_USAGE + m;
+ if (style == STYLE_html)
+ {
+ char ud[64];
+
+ s = id;
+ t = ud;
+ while (t < &ud[sizeof(ud)-2] && (c = *s++))
+ {
+ if (islower(c))
+ c = toupper(c);
+ *t++ = c;
+ }
+ *t = 0;
+ sfprintf(mp, "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n<HTML>\n<HEAD>\n<META name=\"generator\" content=\"optget (AT&T Research) 2011-11-11\">\n%s<TITLE>%s man document</TITLE>\n<STYLE type=\"text/css\">\ndiv.SH { padding-left:2em; text-indent:0em; }\ndiv.SY { padding-left:4em; text-indent:-2em; }\ndt { float:left; clear:both; }\ndd { margin-left:3em; }\n</STYLE>\n</HEAD>\n<BODY bgcolor=white>\n", (state.flags & OPT_proprietary) ? "<!--INTERNAL-->\n" : "", id);
+ sfprintf(mp, "<H4><TABLE width=100%%><TR><TH align=left>%s&nbsp;(&nbsp;%s&nbsp;)&nbsp;<TH align=center><A href=\".\" title=\"Index\">%s</A><TH align=right>%s&nbsp;(&nbsp;%s&nbsp;)</TR></TABLE></H4>\n<HR>\n", ud, section, T(NiL, ID, secname(section)), ud, section);
+ co = 2;
+ pt = ptstk;
+ pt->level = 0;
+ pt->id = TAG_DIV;
+ }
+ else
+ co = 0;
+ if ((rm = margin - ts) < OPT_MARGIN)
+ rm = OPT_MARGIN;
+ ip = indent;
+ ip->stop = (ip+1)->stop = style >= STYLE_html ? 0 : 2;
+ tp = 0;
+ n = 0;
+ head = 1;
+ while (*p == '\n')
+ p++;
+ while (c = *p++)
+ {
+ if (c == '\n')
+ {
+ ip = indent;
+ n = 0;
+ tp = 0;
+ sfputc(mp, '\n');
+ co = 0;
+ rm = margin;
+ ts = ip->stop;
+ if (*p == '\n')
+ {
+ while (*++p == '\n');
+ if ((style == STYLE_man || style == STYLE_html) && (!head || *p != ' ' && *p != '\t'))
+ {
+ if (style == STYLE_man)
+ p--;
+ else
+ sfprintf(mp, "<P>\n");
+ }
+ }
+ head = *p != ' ' && *p != '\t';
+ if (style == STYLE_html && (*p != '<' || !strneq(p, "<BR>", 4) && !strneq(p, "<P>", 3)))
+ {
+ y = p;
+ while (*p == '\t')
+ p++;
+ if (*p == '\n')
+ continue;
+ j = p - y;
+ if (j > pt->level)
+ {
+ pt++;
+ pt->level = j;
+ pt->id = TAG_NONE;
+ for (y = p; *y && *y != '\n'; y++)
+ if (*y == '\t')
+ {
+ pt->id = TAG_DL;
+ sfprintf(mp, "<DL>\n");
+ break;
+ }
+ }
+ else
+ while (j < pt->level && pt > ptstk)
+ {
+ sfprintf(mp, "%s", end[pt->id]);
+ pt--;
+ }
+ if (pt->id == TAG_DL)
+ {
+ dt = p;
+ sfprintf(mp, "<DT>");
+ }
+ else
+ dt = 0;
+ }
+ }
+ else if (c == '\t')
+ {
+ if (style == STYLE_html)
+ {
+ while (*p == '\t')
+ p++;
+ if (*p != '\n')
+ {
+ co += sfprintf(mp, "<DD>");
+ if (dt)
+ {
+ c = 0;
+ m = 0;
+ for (;;)
+ {
+ switch (*dt++)
+ {
+ case '\t':
+ break;
+ case '<':
+ c = '>';
+ continue;
+ case '>':
+ if (c == '>')
+ c = 0;
+ else
+ m++;
+ continue;
+ case '&':
+ c = ';';
+ continue;
+ case ';':
+ if (c == ';')
+ c = 0;
+ m++;
+ continue;
+ default:
+ if (!c)
+ m++;
+ continue;
+ }
+ break;
+ }
+ if (m >= 5)
+ co += sfprintf(mp, "<BR>");
+ }
+ }
+ }
+ else
+ {
+ if ((ip+1)->stop)
+ {
+ do
+ {
+ ip++;
+ if (*p != '\t')
+ break;
+ p++;
+ } while ((ip+1)->stop);
+ if (*p == '\n')
+ continue;
+ ts = ip->stop;
+ if (co >= ts)
+ {
+ sfputc(mp, '\n');
+ co = 0;
+ rm = margin;
+ ts = ip->stop;
+ }
+ }
+ while (co < ts)
+ {
+ sfputc(mp, ' ');
+ co++;
+ }
+ }
+ }
+ else
+ {
+ if (c == ' ' && !n)
+ {
+ if (co >= rm)
+ tp = 0;
+ else
+ {
+ tp = sfstrtell(mp);
+ pp = p;
+ }
+ if (style == STYLE_nroff && !co)
+ continue;
+ }
+ else if (style == STYLE_html)
+ {
+ if (c == '<')
+ {
+ if (strneq(p, "NOBR>", 5))
+ n++;
+ else if (n && strneq(p, "/NOBR>", 6) && !--n)
+ {
+ for (y = p += 6; (c = *p) && c != ' ' && c != '\t' && c != '\n' && c != '<'; p++)
+ if (c == '[')
+ sfputr(mp, "&#0091;", -1);
+ else if (c == ']')
+ sfputr(mp, "&#0093;", -1);
+ else
+ sfputc(mp, c);
+ sfwrite(mp, "</NOBR", 6);
+ c = '>';
+ co += p - y + 6;
+ }
+ }
+ else if (c == '>' && !n)
+ {
+ for (y = --p; (c = *p) && c != ' ' && c != '\t' && c != '\n' && c != '<'; p++)
+ if (c == '[')
+ sfputr(mp, "&#0091;", -1);
+ else if (c == ']')
+ sfputr(mp, "&#0093;", -1);
+ else
+ sfputc(mp, c);
+ c = *sfstrseek(mp, -1, SEEK_CUR);
+ if (p > y + 1)
+ {
+ tp = 0;
+ co += p - y - 1;
+ }
+ if (co >= rm)
+ tp = 0;
+ else
+ {
+ tp = sfstrtell(mp);
+ pp = p;
+ }
+ }
+ else if (c == '[')
+ {
+ sfputr(mp, "&#0091", -1);
+ c = ';';
+ }
+ else if (c == ']')
+ {
+ sfputr(mp, "&#0093", -1);
+ c = ';';
+ }
+ else if (c == 'h')
+ {
+ y = p;
+ if (*y++ == 't' && *y++ == 't' && *y++ == 'p' && (*y == ':' || *y++ == 's' && *y == ':') && *y++ == ':' && *y++ == '/' && *y++ == '/')
+ {
+ while (isalnum(*y) || *y == '_' || *y == '/' || *y == '-' || *y == '.')
+ y++;
+ if (*y == '?')
+ while (isalnum(*y) || *y == '_' || *y == '/' || *y == '-' || *y == '.' || *y == '?' || *y == '=' || *y == '%' || *y == '&' || *y == ';' || *y == '#')
+ y++;
+ if (*(y - 1) == '.')
+ y--;
+ p--;
+ sfprintf(mp, "<A href=\"%-.*s\">%-.*s</A", y - p, p, y - p, p);
+ p = y;
+ c = '>';
+ }
+ }
+ else if (c == 'C')
+ {
+ y = p;
+ if (*y++ == 'o' && *y++ == 'p' && *y++ == 'y' && *y++ == 'r' && *y++ == 'i' && *y++ == 'g' && *y++ == 'h' && *y++ == 't' && *y++ == ' ' && *y++ == '(' && (*y++ == 'c' || *(y - 1) == 'C') && *y++ == ')')
+ {
+ sfputr(mp, "Copyright &copy", -1);
+ p = y;
+ c = ';';
+ }
+ }
+ }
+ else if (c == ']')
+ {
+ if (n)
+ n--;
+ }
+ else if (c == '[')
+ n++;
+ if (c == CC_esc)
+ {
+ sfputc(mp, c);
+ do
+ {
+ if (!(c = *p++))
+ {
+ p--;
+ break;
+ }
+ sfputc(mp, c);
+ } while (c < 'a' || c > 'z');
+ }
+ else if (co++ >= rm && !n)
+ {
+ if (tp)
+ {
+ if (*sfstrseek(mp, tp, SEEK_SET) != ' ')
+ sfstrseek(mp, 1, SEEK_CUR);
+ tp = 0;
+ p = pp;
+ n = 0;
+ }
+ else if (c != ' ' && c != '\n')
+ sfputc(mp, c);
+ if (*p == ' ')
+ p++;
+ if (*p != '\n')
+ {
+ sfputc(mp, '\n');
+ for (co = 0; co < ts; co++)
+ sfputc(mp, ' ');
+ rm = margin;
+ }
+ }
+ else
+ sfputc(mp, c);
+ }
+ }
+ for (d = sfstrbase(mp), t = sfstrseek(mp, 0, SEEK_CUR); t > d && ((c = *(t - 1)) == '\n' || c == '\r' || c == ' ' || c == '\t'); t--);
+ sfstrseek(mp, t - d, SEEK_SET);
+ if (style == STYLE_html)
+ {
+ sfprintf(mp, "\n");
+ while (pt > ptstk)
+ {
+ sfprintf(mp, "%s", end[pt->id]);
+ pt--;
+ }
+ sfprintf(mp, "</DIV>\n</BODY>\n</HTML>");
+ }
+ }
+ else
+ sfputr(mp, p, 0);
+ if (!(p = sfstruse(mp)))
+ goto nospace;
+ if (sp)
+ sfclose(sp);
+ return opt_info.msg = p;
+ nospace:
+ s = T(NiL, ID, "[* out of space *]");
+ nope:
+ if (psp)
+ pop(psp);
+ if (sp_help)
+ sfclose(sp_help);
+ if (sp_text)
+ sfclose(sp_text);
+ if (sp_plus)
+ sfclose(sp_plus);
+ if (sp_info)
+ sfclose(sp_info);
+ if (sp_head)
+ sfclose(sp_head);
+ if (sp_body)
+ sfclose(sp_body);
+ if (sp_misc)
+ sfclose(sp_misc);
+ return s;
+}
+
+/*
+ * compatibility wrapper to opthelp()
+ */
+
+char*
+optusage(const char* opts)
+{
+ return opthelp(opts, NiL);
+}
+
+/*
+ * convert number using strtonll() *except* that
+ * 0*[[:digit:]].* is treated as [[:digit:]].*
+ * i.e., it looks octal but isn't, to meet
+ * posix Utility Argument Syntax -- use
+ * 0x.* or <base>#* for alternate bases
+ */
+
+static intmax_t
+optnumber(const char* s, char** t, int* e)
+{
+ intmax_t n;
+ int oerrno;
+
+ while (*s == '0' && isdigit(*(s + 1)))
+ s++;
+ oerrno = errno;
+ errno = 0;
+ n = strtonll(s, t, NiL, 0);
+ if (e)
+ *e = errno;
+ errno = oerrno;
+ return n;
+}
+
+/*
+ * point opt_info.arg to an error/info message for opt_info.name
+ * p points to opts location for opt_info.name
+ * optget() return value is returned
+ */
+
+static int
+opterror(register char* p, int err, int version, char* id, char* catalog)
+{
+ register Sfio_t* mp;
+ register Sfio_t* tp;
+ register char* s;
+ register int c;
+
+ if (opt_info.num != LONG_MIN)
+ opt_info.num = (long)(opt_info.number = 0);
+ if (!p || !(mp = state.mp) && !(mp = state.mp = sfstropen()))
+ goto nospace;
+ s = *p == '-' ? p : opt_info.name;
+ if (*p == '!')
+ {
+ while (*s == '-')
+ sfputc(mp, *s++);
+ sfputc(mp, 'n');
+ sfputc(mp, 'o');
+ }
+ sfputr(mp, s, ':');
+ sfputc(mp, ' ');
+ if (*p == '#' || *p == ':')
+ {
+ if (*p == '#')
+ {
+ s = T(NiL, ID, "numeric");
+ sfputr(mp, s, ' ');
+ }
+ if (*(p = next(p + 1, version)) == '[')
+ {
+ p = skip(s = p + 1, ':', '?', 0, 1, 0, 0, version);
+ tp = X(catalog) ? state.xp : mp;
+ while (s < p)
+ {
+ if ((c = *s++) == '?' || c == ']')
+ s++;
+ sfputc(tp, c);
+ }
+ if (!X(catalog))
+ sfputc(mp, ' ');
+ else if (p = sfstruse(tp))
+ sfputr(mp, T(id, catalog, p), ' ');
+ else
+ goto nospace;
+ }
+ p = opt_info.name[2] ? C("value expected") : C("argument expected");
+ }
+ else if (*p == '*' || *p == '&')
+ {
+ sfputr(mp, opt_info.arg, ':');
+ sfputc(mp, ' ');
+ p = *p == '&' ? C("ambiguous option argument value") : C("unknown option argument value");
+ }
+ else if (*p == '=' || *p == '!')
+ p = C("value not expected");
+ else if (*p == '?')
+ p = *(p + 1) == '?' ? C("optget: option not supported") : C("ambiguous option");
+ else if (*p == '+')
+ p = C("section not found");
+ else
+ {
+ if (opt_info.option[0] != '?' && opt_info.option[0] != '-' || opt_info.option[1] != '?' && opt_info.option[1] != '-')
+ opt_info.option[0] = 0;
+ p = C("unknown option");
+ }
+ p = T(NiL, ID, p);
+ sfputr(mp, p, -1);
+ if (err)
+ sfputr(mp, " -- out of range", -1);
+ if (opt_info.arg = sfstruse(mp))
+ return ':';
+ nospace:
+ opt_info.arg = T(NiL, ID, "[* out of space *]");
+ return ':';
+}
+
+/*
+ * argv: command line argv where argv[0] is command name
+ *
+ * opts: option control string
+ *
+ * '[' [flag][=][index][:<long-name>[|<alias-name>...]['?'description]] ']'
+ * long option name, index, description; -index returned
+ * ':' option takes string arg
+ * '#' option takes numeric arg (concat option may follow)
+ * '?' (option) following options not in usage
+ * (following # or :) optional arg
+ * '[' '[' ... ] ... '[' ... ']' ']'
+ * mutually exclusive option grouping
+ * '[' name [:attr]* [?description] ']'
+ * (following # or :) optional option arg description
+ * '\n'[' '|'\t']* ignored for legibility
+ * ' ' ... optional argument(s) description (to end of string)
+ * or after blank line
+ * ']]' literal ']' within '[' ... ']'
+ *
+ * return:
+ * 0 no more options
+ * '?' usage: opt_info.arg points to message sans
+ * `Usage: command '
+ * ':' error: opt_info.arg points to message sans `command: '
+ *
+ * ':' '#' ' ' '[' ']'
+ * invalid option chars
+ *
+ * -- terminates option list and returns 0
+ *
+ * + as first opts char makes + equivalent to -
+ *
+ * if any # option is specified then numeric options (e.g., -123)
+ * are associated with the leftmost # option in opts
+ *
+ * usage info in placed opt_info.arg when '?' returned
+ * see help_text[] (--???) for more info
+ */
+
+int
+optget(register char** argv, const char* oopts)
+{
+ register int c;
+ register char* s;
+ char* a;
+ char* b;
+ char* e;
+ char* f;
+ char* g;
+ char* v;
+ char* w;
+ char* p;
+ char* q;
+ char* t;
+ char* y;
+ char* numopt;
+ char* opts;
+ char* id;
+ char* catalog;
+ int n;
+ int m;
+ int k;
+ int j;
+ int x;
+ int err;
+ int no;
+ int nov;
+ int num;
+ int numchr;
+ int prefix;
+ int version;
+ Help_t* hp;
+ Push_t* psp;
+ Push_t* tsp;
+ Sfio_t* vp;
+ Sfio_t* xp;
+ Optcache_t* cache;
+ Optcache_t* pcache;
+ Optpass_t* pass;
+
+#if !_PACKAGE_astsa && !_YOU_FIGURED_OUT_HOW_TO_GET_ALL_DLLS_TO_DO_THIS_
+ /*
+ * these are not initialized by all dlls!
+ */
+
+ extern Error_info_t _error_info_;
+ extern Opt_t _opt_info_;
+
+ if (!_error_infop_)
+ _error_infop_ = &_error_info_;
+ if (!_opt_infop_)
+ _opt_infop_ = &_opt_info_;
+#endif
+ if (!oopts)
+ return 0;
+ state.pindex = opt_info.index;
+ state.poffset = opt_info.offset;
+ if (!opt_info.index)
+ {
+ opt_info.index = 1;
+ opt_info.offset = 0;
+ if (state.npass)
+ {
+ state.npass = 0;
+ state.join = 0;
+ }
+ }
+ if (!argv)
+ cache = 0;
+ else
+ for (pcache = 0, cache = state.cache; cache; pcache = cache, cache = cache->next)
+ if (cache->pass.oopts == (char*)oopts)
+ break;
+ if (cache)
+ {
+ if (pcache)
+ {
+ pcache->next = cache->next;
+ cache->next = state.cache;
+ state.cache = cache;
+ }
+ pass = &cache->pass;
+ state.npass = -1;
+ }
+ else
+ {
+ if (!argv)
+ n = state.npass ? state.npass : 1;
+ else if ((n = state.join - 1) < 0)
+ n = 0;
+ if (n >= state.npass || state.pass[n].oopts != (char*)oopts)
+ {
+ for (m = 0; m < state.npass && state.pass[m].oopts != (char*)oopts; m++);
+ if (m < state.npass)
+ n = m;
+ else
+ {
+ if (n >= elementsof(state.pass))
+ n = elementsof(state.pass) - 1;
+ init((char*)oopts, &state.pass[n]);
+ if (state.npass <= n)
+ state.npass = n + 1;
+ }
+ }
+ if (!argv)
+ return 0;
+ pass = &state.pass[n];
+ }
+ opts = pass->opts;
+ prefix = pass->prefix;
+ version = pass->version;
+ id = pass->id;
+ if (!(xp = state.xp) || (catalog = pass->catalog) && !X(catalog))
+ catalog = 0;
+ else /* if (!error_info.catalog) */
+ error_info.catalog = catalog;
+ again:
+ psp = 0;
+
+ /*
+ * check if any options remain and determine if the
+ * next option is short or long
+ */
+
+ opt_info.assignment = 0;
+ num = 1;
+ w = v = 0;
+ x = 0;
+ for (;;)
+ {
+ if (!opt_info.offset)
+ {
+ /*
+ * finished with the previous arg
+ */
+
+ if (opt_info.index == 1 && opt_info.argv != state.strv)
+ {
+ opt_info.argv = 0;
+ state.argv[0] = 0;
+ if (argv[0] && (state.argv[0] = save(argv[0], strlen(argv[0]), 0, 0, 0, 0)))
+ opt_info.argv = state.argv;
+ state.style = STYLE_short;
+ }
+ if (!(s = argv[opt_info.index]))
+ return 0;
+ if (!prefix)
+ {
+ /*
+ * long with no prefix (dd style)
+ */
+
+ n = 2;
+ if ((c = *s) != '-' && c != '+')
+ c = '-';
+ else if (*++s == c)
+ {
+ if (!*++s)
+ {
+ opt_info.index++;
+ return 0;
+ }
+ else if (*s == c)
+ return 0;
+ }
+ else if (*s == '?')
+ n = 1;
+ }
+ else if ((c = *s++) != '-' && (c != '+' || !(pass->flags & OPT_plus) && (!(pass->flags & OPT_numeric) || !isdigit(*s))))
+ {
+ if (!(pass->flags & OPT_old) || !isalpha(c))
+ return 0;
+ s--;
+ n = 1;
+ opt_info.offset--;
+ }
+ else if (*s == c)
+ {
+ if (!*++s)
+ {
+ /*
+ * -- or ++ end of options
+ */
+
+ opt_info.index++;
+ return 0;
+ }
+ else if (*s == c)
+ {
+ /*
+ * ---* or +++* are operands
+ */
+
+ return 0;
+ }
+ if (version || *s == '?' || !(pass->flags & OPT_minus))
+ {
+ /*
+ * long with double prefix
+ */
+
+ n = 2;
+ }
+ else
+ {
+ /*
+ * short option char '-'
+ */
+
+ s--;
+ n = 1;
+ }
+ }
+ else if (prefix == 1 && *s != '?')
+ {
+ /*
+ * long with single prefix (find style)
+ */
+
+ n = 2;
+ }
+ else
+ {
+ /*
+ * short (always with single prefix)
+ */
+
+ n = 1;
+ }
+
+ /*
+ * just a prefix is an option (e.g., `-' == stdin)
+ */
+
+ if (!*s)
+ return 0;
+ if (c == '+')
+ opt_info.arg = 0;
+ if (n == 2)
+ {
+ x = 0;
+ state.style = STYLE_long;
+ opt_info.option[0] = opt_info.name[0] = opt_info.name[1] = c;
+ w = &opt_info.name[prefix];
+ if ((*s == 'n' || *s == 'N') && (*(s + 1) == 'o' || *(s + 1) == 'O') && *(s + 2) && *(s + 2) != '=')
+ no = *(s + 2) == '-' ? 3 : 2;
+ else
+ no = 0;
+ for (c = *s; *s; s++)
+ {
+ if (*s == '=')
+ {
+ if (*(s + 1) == '=')
+ s++;
+ if (!isalnum(*(s - 1)) && *(w - 1) == (opt_info.assignment = *(s - 1)))
+ w--;
+ v = ++s;
+ break;
+ }
+ if (w < &opt_info.name[elementsof(opt_info.name) - 1] && *s != ':' && *s != '|' && *s != '[' && *s != ']')
+ *w++ = *s;
+ }
+ *w = 0;
+ w = &opt_info.name[prefix];
+ c = *w;
+ opt_info.offset = 0;
+ opt_info.index++;
+ break;
+ }
+ opt_info.offset++;
+ }
+ if (!argv[opt_info.index])
+ return 0;
+ if (c = argv[opt_info.index][opt_info.offset++])
+ {
+ if ((k = argv[opt_info.index][0]) != '-' && k != '+')
+ k = '-';
+ opt_info.option[0] = opt_info.name[0] = k;
+ opt_info.option[1] = opt_info.name[1] = c;
+ opt_info.option[2] = opt_info.name[2] = 0;
+ break;
+ }
+ opt_info.offset = 0;
+ opt_info.index++;
+ }
+
+ /*
+ * at this point:
+ *
+ * c the first character of the option
+ * w long option name if != 0, otherwise short
+ * v long option value (via =) if w != 0
+ */
+
+ if (c == '?')
+ {
+ /*
+ * ? always triggers internal help
+ */
+
+ if (!state.msgdict)
+ initdict();
+ if (w)
+ {
+ if (!v && (*(w + 1) || !(v = argv[opt_info.index]) || !++opt_info.index))
+ v = w + 1;
+ else if (w[0] != '?' || w[1])
+ {
+ s = w;
+ w = v;
+ v = s + 1;
+ }
+ }
+ opt_info.option[1] = c;
+ opt_info.option[2] = 0;
+ if (!w)
+ {
+ opt_info.name[1] = c;
+ opt_info.name[2] = 0;
+ }
+ goto help;
+ }
+ else if (w && !state.msgdict)
+ initdict();
+ numopt = 0;
+ f = 0;
+ s = opts;
+
+ /*
+ * no option can start with these characters
+ */
+
+ if (c == ':' || c == '#' || c == ' ' || c == '[' || c == ']')
+ {
+ if (c != *s)
+ s = "";
+ }
+ else
+ {
+ a = 0;
+ if (!w && (pass->flags & OPT_cache))
+ {
+ if (cache)
+ {
+ if (k = cache->flags[map[c]])
+ {
+ opt_info.arg = 0;
+
+ /*
+ * this is a ksh getopts workaround
+ */
+
+ if (opt_info.num != LONG_MIN)
+ opt_info.num = (long)(opt_info.number = !(k & OPT_cache_invert));
+ if (!(k & (OPT_cache_string|OPT_cache_numeric)))
+ return c;
+ if (*(opt_info.arg = &argv[opt_info.index++][opt_info.offset]))
+ {
+ if (!(k & OPT_cache_numeric))
+ {
+ opt_info.offset = 0;
+ return c;
+ }
+ opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
+ if (err || e == opt_info.arg)
+ {
+ if (!err && (k & OPT_cache_optional))
+ {
+ opt_info.arg = 0;
+ opt_info.index--;
+ return c;
+ }
+ }
+ else if (*e)
+ {
+ opt_info.offset += e - opt_info.arg;
+ opt_info.index--;
+ return c;
+ }
+ else
+ {
+ opt_info.offset = 0;
+ return c;
+ }
+ }
+ else if (opt_info.arg = argv[opt_info.index])
+ {
+ opt_info.index++;
+ if ((k & OPT_cache_optional) && (*opt_info.arg == '-' || (pass->flags & OPT_plus) && *opt_info.arg == '+') && *(opt_info.arg + 1))
+ {
+ opt_info.arg = 0;
+ opt_info.index--;
+ opt_info.offset = 0;
+ return c;
+ }
+ if (k & OPT_cache_string)
+ {
+ opt_info.offset = 0;
+ return c;
+ }
+ opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
+ if (!err)
+ {
+ if (!*e)
+ {
+ opt_info.offset = 0;
+ return c;
+ }
+ if (k & OPT_cache_optional)
+ {
+ opt_info.arg = 0;
+ opt_info.index--;
+ opt_info.offset = 0;
+ return c;
+ }
+ }
+ }
+ else if (k & OPT_cache_optional)
+ {
+ opt_info.offset = 0;
+ return c;
+ }
+ opt_info.index--;
+ }
+ cache = 0;
+ }
+ else if (cache = newof(0, Optcache_t, 1, 0))
+ {
+ cache->caching = c;
+ c = 0;
+ cache->pass = *pass;
+ cache->next = state.cache;
+ state.cache = cache;
+ }
+ }
+ else
+ cache = 0;
+ for (;;)
+ {
+ if (!(*(s = next(s, version))) || *s == '\n' || *s == ' ')
+ {
+ if (!(tsp = psp))
+ {
+ if (cache)
+ {
+ /*
+ * the first loop pass
+ * initialized the cache
+ * so one more pass to
+ * check the cache or
+ * bail for a full scan
+ */
+
+ cache->flags[0] = 0;
+ c = cache->caching;
+ cache->caching = 0;
+ cache = 0;
+ s = opts;
+ continue;
+ }
+ if (!x && catalog)
+ {
+ /*
+ * the first loop pass
+ * translated long
+ * options and there
+ * were no matches so
+ * one more pass for C
+ * locale
+ */
+
+ catalog = 0;
+ s = opts;
+ continue;
+ }
+ s = "";
+ break;
+ }
+ s = psp->ob;
+ psp = psp->next;
+ free(tsp);
+ continue;
+ }
+ if (*s == '\f')
+ {
+ psp = info(psp, s + 1, NiL, xp, id);
+ if (psp->nb)
+ s = psp->nb;
+ else
+ {
+ s = psp->ob;
+ psp = psp->next;
+ }
+ continue;
+ }
+ message((-20, "optget: opt %s c %c w %s num %ld", show(s), c, w, num));
+ if (*s == c && !w)
+ break;
+ else if (*s == '[')
+ {
+ s = next(s + 1, version);
+ if (*s == '(')
+ {
+ s = nest(f = s);
+ if (!conformance(f, s - f))
+ goto disable;
+ }
+ k = *(f = s);
+ if (k == '+' || k == '-')
+ /* ignore */;
+ else if (k == '[' || version < 1)
+ continue;
+ else if (w && !cache)
+ {
+ nov = no;
+ if (*(s + 1) == '\f' && (vp = state.vp))
+ {
+ sfputc(vp, k);
+ s = expand(s + 2, NiL, &t, vp, id);
+ if (*s)
+ *(f = s - 1) = k;
+ else
+ {
+ f = sfstrbase(vp);
+ if (s = strrchr(f, ':'))
+ f = s - 1;
+ else
+ s = f + 1;
+ }
+ }
+ else
+ t = 0;
+ if (*s != ':')
+ s = skip(s, ':', '?', 0, 1, 0, 0, version);
+ if (*s == ':')
+ {
+ if (catalog)
+ {
+ p = skip(s + 1, '?', 0, 0, 1, 0, 0, version);
+ e = sfprints("%-.*s", p - (s + 1), s + 1);
+ g = T(id, catalog, e);
+ if (g == e)
+ p = 0;
+ else
+ {
+ sfprintf(xp, ":%s|%s?", g, e);
+ if (!(s = sfstruse(xp)))
+ goto nospace;
+ }
+ }
+ else
+ p = 0;
+ y = w;
+ for (;;)
+ {
+ n = m = 0;
+ e = s + 1;
+ while (*++s)
+ {
+ if (*s == '*' || *s == '\a')
+ {
+ if (*s == '\a')
+ do
+ {
+ if (!*++s)
+ {
+ s--;
+ break;
+ }
+ } while (*s != '\a');
+ j = *(s + 1);
+ if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
+ {
+ while (*w)
+ w++;
+ m = 0;
+ break;
+ }
+ m = 1;
+ }
+ else if (*s == *w || SEP(*s) && SEP(*w))
+ w++;
+ else if (*w == 0)
+ break;
+ else if (!SEP(*s))
+ {
+ if (SEP(*w))
+ {
+ if (*++w == *s)
+ {
+ w++;
+ continue;
+ }
+ }
+ else if (w == y || SEP(*(w - 1)) || isupper(*(w - 1)) && islower(*w))
+ break;
+ for (q = s; *q && !SEP(*q) && *q != '|' && *q != '?' && *q != ']'; q++);
+ if (!SEP(*q))
+ break;
+ for (s = q; w > y && *w != *(s + 1); w--);
+ }
+ else if (*w != *(s + 1))
+ break;
+ }
+ if (!*w)
+ {
+ nov = 0;
+ break;
+ }
+ if (n = no)
+ {
+ m = 0;
+ s = e - 1;
+ w = y + n;
+ while (*++s)
+ {
+ if (*s == '*' || *s == '\a')
+ {
+ if (*s == '\a')
+ do
+ {
+ if (!*++s)
+ {
+ s--;
+ break;
+ }
+ } while (*s != '\a');
+ j = *(s + 1);
+ if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
+ {
+ while (*w)
+ w++;
+ m = 0;
+ break;
+ }
+ m = 1;
+ }
+ else if (*s == *w || SEP(*s) && SEP(*w))
+ w++;
+ else if (*w == 0)
+ break;
+ else if (!SEP(*s))
+ {
+ if (SEP(*w))
+ {
+ if (*++w == *s)
+ {
+ w++;
+ continue;
+ }
+ }
+ else if (w == y || SEP(*(w - 1)) || isupper(*(w - 1)) && islower(*w))
+ break;
+ for (q = s; *q && !SEP(*q) && *q != '|' && *q != '?' && *q != ']'; q++);
+ if (!SEP(*q))
+ break;
+ for (s = q; w > y && *w != *(s + 1); w--);
+ }
+ else if (*w != *(s + 1))
+ break;
+ }
+ if (!*w)
+ break;
+ }
+ if (*(s = skip(s, ':', '|', '?', 1, 0, 0, version)) != '|')
+ break;
+ w = y;
+ }
+ if (p)
+ s = p;
+ if (!*w)
+ {
+ if (n)
+ num = 0;
+ if (!(n = (m || *s == ':' || *s == '|' || *s == '?' || *s == ']' || *s == 0)) && x)
+ {
+ psp = pop(psp);
+ return opterror("?", 0, version, id, catalog);
+ }
+ for (x = k; *(f + 1) == '|' && (j = *(f + 2)) && j != '!' && j != '=' && j != ':' && j != '?' && j != ']'; f += 2);
+ if (*f == ':')
+ {
+ x = -1;
+ opt_info.option[1] = '-';
+ opt_info.option[2] = 0;
+ }
+ else if (*(f + 1) == ':' || *(f + 1) == '!' && *(f + 2) == ':')
+ {
+ opt_info.option[1] = x;
+ opt_info.option[2] = 0;
+ }
+ else
+ {
+ a = f;
+ if (*a == '=')
+ a++;
+ else
+ {
+ if (*(a + 1) == '!')
+ a++;
+ if (*(a + 1) == '=')
+ a += 2;
+ }
+ x = -strtol(a, &b, 0);
+ if ((b - a) > sizeof(opt_info.option) - 2)
+ b = a + sizeof(opt_info.option) - 2;
+ memcpy(&opt_info.option[1], a, b - a);
+ opt_info.option[b - a + 1] = 0;
+ }
+ b = e;
+ if (t)
+ {
+ s = t;
+ t = 0;
+ }
+ a = s = skip(s, 0, 0, 0, 1, 0, 0, version);
+ if (n)
+ {
+ w = y;
+ break;
+ }
+ }
+ w = y;
+ }
+ else if (k == c && prefix == 1)
+ {
+ w = 0;
+ opt_info.name[1] = c;
+ opt_info.name[2] = 0;
+ opt_info.offset = 2;
+ opt_info.index--;
+ break;
+ }
+ if (t)
+ {
+ s = t;
+ if (a)
+ a = t;
+ }
+ }
+ disable:
+ s = skip(s, 0, 0, 0, 1, 0, 1, version);
+ if (*s == GO)
+ s = skip(s + 1, 0, 0, 0, 0, 1, 1, version);
+ if (cache)
+ {
+ m = OPT_cache_flag;
+ v = s;
+ if (*v == '#')
+ {
+ v++;
+ m |= OPT_cache_numeric;
+ }
+ else if (*v == ':')
+ {
+ v++;
+ m |= OPT_cache_string;
+ }
+ if (*v == '?')
+ {
+ v++;
+ m |= OPT_cache_optional;
+ }
+ else if (*v == *(v - 1))
+ v++;
+ if (*(v = next(v, version)) == '[')
+ v = skip(v + 1, 0, 0, 0, 1, 0, 1, version);
+ if (*v != GO)
+ {
+ v = f;
+ for (;;)
+ {
+ if (isdigit(*f) && isdigit(*(f + 1)))
+ while (isdigit(*(f + 1)))
+ f++;
+ else if (*(f + 1) == '=')
+ break;
+ else
+ cache->flags[map[*f]] = m;
+ j = 0;
+ while (*(f + 1) == '|')
+ {
+ f += 2;
+ if (!(j = *f) || j == '!' || j == '=' || j == ':' || j == '?' || j == ']')
+ break;
+ cache->flags[map[j]] = m;
+ }
+ if (j != '!' || (m & OPT_cache_invert))
+ break;
+ f = v;
+ m |= OPT_cache_invert;
+ }
+ }
+ }
+ else
+ {
+ m = 0;
+ if (!w)
+ {
+ if (isdigit(*f) && isdigit(*(f + 1)))
+ k = -1;
+ if (c == k)
+ m = 1;
+ while (*(f + 1) == '|')
+ {
+ f += 2;
+ if (!(j = *f))
+ {
+ m = 0;
+ break;
+ }
+ else if (j == c)
+ m = 1;
+ else if (j == '!' || j == '=' || j == ':' || j == '?' || j == ']')
+ break;
+ }
+ }
+ if (m)
+ {
+ s--;
+ if (*++f == '!')
+ {
+ f++;
+ num = 0;
+ }
+ if (*f == '=')
+ {
+ c = -strtol(++f, &b, 0);
+ if ((b - f) > sizeof(opt_info.option) - 2)
+ b = f + sizeof(opt_info.option) - 2;
+ memcpy(&opt_info.option[1], f, b - f);
+ opt_info.option[b - f + 1] = 0;
+ }
+ else
+ c = k;
+ break;
+ }
+ }
+ if (*s == '#')
+ {
+ if (!numopt && s > opts)
+ {
+ numopt = s - 1;
+ numchr = k;
+ if (*f == ':')
+ numchr = -1;
+ else if (*(f + 1) != ':' && *(f + 1) != '!' && *(f + 1) != ']')
+ {
+ a = f;
+ if (*a == '=')
+ a++;
+ else
+ {
+ if (*(a + 1) == '!')
+ a++;
+ if (*(a + 1) == '=')
+ a += 2;
+ }
+ numchr = -strtol(a, NiL, 0);
+ }
+ }
+ }
+ else if (*s != ':')
+ continue;
+ }
+ else if (*s == ']')
+ {
+ s++;
+ continue;
+ }
+ else if (*s == '#')
+ {
+ if (!numopt && s > opts)
+ numchr = *(numopt = s - 1);
+ }
+ else if (*s != ':')
+ {
+ if (cache)
+ {
+ m = OPT_cache_flag;
+ if (*(s + 1) == '#')
+ {
+ m |= OPT_cache_numeric;
+ if (*(s + 2) == '?')
+ m |= OPT_cache_optional;
+ }
+ else if (*(s + 1) == ':')
+ {
+ m |= OPT_cache_string;
+ if (*(s + 2) == '?')
+ m |= OPT_cache_optional;
+ }
+ cache->flags[map[*s]] = m;
+ }
+ s++;
+ continue;
+ }
+ message((-21, "optget: opt %s", show(s)));
+ if (*++s == '?' || *s == *(s - 1))
+ s++;
+ if (*(s = next(s, version)) == '[')
+ {
+ s = skip(s + 1, 0, 0, 0, 1, 0, 1, version);
+ if (*s == GO)
+ s = skip(s + 1, 0, 0, 0, 0, 1, 1, version);
+ }
+ message((-21, "optget: opt %s", show(s)));
+ }
+ if (w && x)
+ {
+ s = skip(b, '|', '?', 0, 1, 0, 0, version);
+ if (v && (a == 0 || *a == 0 || *(a + 1) != ':' && *(a + 1) != '#') && (*v == '0' || *v == '1') && !*(v + 1))
+ {
+ if (*v == '0')
+ num = !num;
+ v = 0;
+ }
+ if ((s - b) >= elementsof(opt_info.name))
+ s = b + elementsof(opt_info.name) - 1;
+ for (;;)
+ {
+ if (b >= s)
+ {
+ *w = 0;
+ break;
+ }
+ if (*b == '*')
+ break;
+ *w++ = *b++;
+ }
+ if (!num && v)
+ return opterror(no ? "!" : "=", 0, version, id, catalog);
+ w = &opt_info.name[prefix];
+ c = x;
+ s = a;
+ }
+ }
+ if (!*s)
+ {
+ if (w)
+ {
+ if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), w))
+ {
+ if (!v)
+ v = (char*)hp->name;
+ goto help;
+ }
+ if (!v)
+ {
+ v = opt_info.name;
+ goto help;
+ }
+ }
+ if (w || !isdigit(c) || !numopt || !(pass->flags & OPT_numeric))
+ {
+ pop(psp);
+ return opterror("", 0, version, id, catalog);
+ }
+ s = numopt;
+ c = opt_info.option[1] = numchr;
+ opt_info.offset--;
+ }
+ opt_info.arg = 0;
+
+ /*
+ * this is a ksh getopts workaround
+ */
+
+ if (opt_info.num != LONG_MIN)
+ opt_info.num = (long)(opt_info.number = num);
+ if ((n = *++s == '#') || *s == ':' || w && !nov && v && (optnumber(v, &e, NiL), n = !*e))
+ {
+ if (w)
+ {
+ if (nov)
+ {
+ if (v)
+ {
+ pop(psp);
+ return opterror("!", 0, version, id, catalog);
+ }
+ opt_info.num = (long)(opt_info.number = 0);
+ }
+ else
+ {
+ if (!v && *(s + 1) != '?' && (v = argv[opt_info.index]))
+ {
+ opt_info.index++;
+ opt_info.offset = 0;
+ }
+ if (!(opt_info.arg = v) || (*v == '0' || *v == '1') && !*(v + 1))
+ {
+ if (*(s + 1) != '?')
+ {
+ if (!opt_info.arg)
+ {
+ pop(psp);
+ return opterror(s, 0, version, id, catalog);
+ }
+ }
+ else if (*(t = next(s + 2, version)) == '[')
+ while (*(t = skip(t, ':', 0, 0, 1, 0, 0, version)) == ':')
+ if (*++t == '!')
+ {
+ if (!v || *v == '1')
+ {
+ e = skip(t, ':', '?', ']', 1, 0, 0, version);
+ opt_info.arg = sfprints("%-.*s", e - t - 1, t + 1);
+ }
+ else
+ {
+ opt_info.arg = 0;
+ opt_info.num = (long)(opt_info.number = 0);
+ }
+ break;
+ }
+ }
+ if (opt_info.arg && n)
+ {
+ opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
+ if (err || e == opt_info.arg)
+ {
+ pop(psp);
+ return opterror(s, err, version, id, catalog);
+ }
+ }
+ }
+ goto optarg;
+ }
+ else if (*(opt_info.arg = &argv[opt_info.index++][opt_info.offset]))
+ {
+ if (*s == '#')
+ {
+ opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
+ if (err || e == opt_info.arg)
+ {
+ if (!err && *(s + 1) == '?')
+ {
+ opt_info.arg = 0;
+ opt_info.index--;
+ }
+ else
+ {
+ opt_info.offset = 0;
+ c = opterror(s, err, version, id, catalog);
+ }
+ pop(psp);
+ return c;
+ }
+ else if (*e)
+ {
+ opt_info.offset += e - opt_info.arg;
+ opt_info.index--;
+ pop(psp);
+ return c;
+ }
+ }
+ }
+ else if (opt_info.arg = argv[opt_info.index])
+ {
+ opt_info.index++;
+ if (*(s + 1) == '?' && (*opt_info.arg == '-' || (pass->flags & OPT_plus) && *opt_info.arg == '+') && *(opt_info.arg + 1))
+ {
+ opt_info.index--;
+ opt_info.arg = 0;
+ }
+ else if (*s == '#')
+ {
+ opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
+ if (err || *e)
+ {
+ if (!err && *(s + 1) == '?')
+ {
+ opt_info.arg = 0;
+ opt_info.index--;
+ }
+ else
+ {
+ pop(psp);
+ opt_info.offset = 0;
+ return opterror(s, err, version, id, catalog);
+ }
+ }
+ }
+ }
+ else if (*(s + 1) != '?')
+ {
+ opt_info.index--;
+ pop(psp);
+ return opterror(s, 0, version, id, catalog);
+ }
+ opt_info.offset = 0;
+ optarg:
+ if (*s == ':' && *(s = skip(s, 0, 0, 0, 1, 0, 1, version)) == GO && *(s = next(s + 1, version)) == '[' && isalnum(*(s + 1)))
+ {
+ x = 0;
+ if (opt_info.arg)
+ {
+ do
+ {
+ w = y = opt_info.arg;
+ f = s = next(s + 1, version);
+ k = *f;
+ if (k == *w && isalpha(k) && !*(w + 1))
+ {
+ x = k;
+ break;
+ }
+ if (*s == '+' || *s == '-')
+ continue;
+ else if (*s == '[' || version < 1)
+ continue;
+ else
+ {
+ if (*s != ':')
+ s = skip(s, ':', '?', 0, 1, 0, 0, version);
+ if (*s == ':')
+ {
+ if (catalog)
+ {
+ p = skip(s + 1, '?', 0, 0, 1, 0, 0, version);
+ e = sfprints("%-.*s", p - (s + 1), s + 1);
+ b = T(id, catalog, e);
+ if (b == e)
+ p = 0;
+ else
+ {
+ sfprintf(xp, ":%s|%s?", b, e);
+ if (!(s = sfstruse(xp)))
+ goto nospace;
+ }
+ }
+ else
+ p = 0;
+ for (;;)
+ {
+ n = m = 0;
+ e = s + 1;
+ while (*++s)
+ {
+ if (*s == '*' || *s == '\a')
+ {
+ if (*s == '\a')
+ do
+ {
+ if (!*++s)
+ {
+ s--;
+ break;
+ }
+ } while (*s != '\a');
+ j = *(s + 1);
+ if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
+ {
+ while (*w)
+ w++;
+ m = 0;
+ break;
+ }
+ m = 1;
+ }
+ else if (*s == *w || SEP(*s) && SEP(*w))
+ w++;
+ else if (*w == 0)
+ break;
+ else if (!SEP(*s))
+ {
+ if (SEP(*w))
+ {
+ if (*++w == *s)
+ {
+ w++;
+ continue;
+ }
+ }
+ else if (w == y || SEP(*(w - 1)) || isupper(*(w - 1)) && islower(*w))
+ break;
+ for (q = s; *q && !SEP(*q) && *q != '|' && *q != '?' && *q != ']'; q++);
+ if (!SEP(*q))
+ break;
+ for (s = q; w > y && *w != *(s + 1); w--);
+ }
+ else if (*w != *(s + 1))
+ break;
+ }
+ if (!*w)
+ {
+ nov = 0;
+ break;
+ }
+ if (*(s = skip(s, ':', '|', '?', 1, 0, 0, version)) != '|')
+ break;
+ w = y;
+ }
+ if (p)
+ s = p;
+ if (!*w)
+ {
+ if (n)
+ num = 0;
+ if (!(n = (m || *s == ':' || *s == '|' || *s == '?' || *s == ']')) && x)
+ {
+ pop(psp);
+ return opterror("&", 0, version, id, catalog);
+ }
+ for (x = k; *(f + 1) == '|' && (j = *(f + 2)) && j != '!' && j != '=' && j != ':' && j != '?' && j != ']'; f += 2);
+ if (*f == ':')
+ x = -1;
+ else if (*(f + 1) == ':' || *(f + 1) == '!' && *(f + 2) == ':')
+ /* ok */;
+ else
+ {
+ a = f;
+ if (*a == '=')
+ a++;
+ else
+ {
+ if (*(a + 1) == '!')
+ a++;
+ if (*(a + 1) == '=')
+ a += 2;
+ }
+ x = -strtol(a, &b, 0);
+ }
+ b = e;
+ a = s = skip(s, 0, 0, 0, 1, 0, 0, version);
+ if (n)
+ break;
+ }
+ }
+ }
+ } while (*(s = skip(s, 0, 0, 0, 1, 0, 1, version)) == '[');
+ if (!(opt_info.num = (long)(opt_info.number = x)))
+ {
+ pop(psp);
+ return opterror("*", 0, version, id, catalog);
+ }
+ }
+ }
+ }
+ else if (w && v)
+ {
+ pop(psp);
+ return opterror("=", 0, version, id, catalog);
+ }
+ else
+ {
+ opt_info.num = (long)(opt_info.number = num);
+ if (!w && !argv[opt_info.index][opt_info.offset])
+ {
+ opt_info.offset = 0;
+ opt_info.index++;
+ }
+ }
+ pop(psp);
+ return c;
+ help:
+ if (v && *v == '?' && *(v + 1) == '?' && *(v + 2))
+ {
+ s = v + 2;
+ if ((s[0] == 'n' || s[0] == 'N') && (s[1] == 'o' || s[1] == 'O'))
+ {
+ s += 2;
+ n = -1;
+ }
+ else
+ n = 1;
+ if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), s))
+ {
+ if (hp->style < STYLE_man || !(s = argv[opt_info.index]) || s[0] != '-' || s[1] != '-' || !s[2])
+ {
+ opt_info.arg = sfprints("\fversion=%d", version);
+ pop(psp);
+ return '?';
+ }
+ state.force = hp->style;
+ }
+ else if (match(s, "CONFORMANCE", -1, ID, NiL))
+ {
+ opt_info.arg = sfprints("\f%s", conformance(w, 0));
+ pop(psp);
+ return '?';
+ }
+ else if (match(s, "ESC", -1, ID, NiL) || match(s, "EMPHASIS", -1, ID, NiL))
+ state.emphasis = n;
+ else if (match(s, "MAN", -1, ID, NiL))
+ {
+ opt_info.arg = sfprints("\f%s", secname(*w != '?' ? w : pass->section));
+ pop(psp);
+ return '?';
+ }
+ else if (match(s, "PREFORMAT", -1, ID, NiL))
+ state.flags |= OPT_preformat;
+ else if (match(s, "SECTION", -1, ID, NiL))
+ {
+ opt_info.arg = sfprints("\f%s", pass->section);
+ pop(psp);
+ return '?';
+ }
+ else if (match(s, "TEST", -1, ID, NiL))
+ {
+ state.width = OPT_WIDTH;
+ state.emphasis = 1;
+ }
+ else
+ {
+ pop(psp);
+ return opterror(v, 0, version, id, catalog);
+ }
+ psp = pop(psp);
+ if (argv == state.strv)
+ return '#';
+ goto again;
+ }
+ if ((opt_info.arg = opthelp(NiL, v)) == (char*)unknown)
+ {
+ pop(psp);
+ return opterror(v, 0, version, id, catalog);
+ }
+ pop(psp);
+ return '?';
+ nospace:
+ pop(psp);
+ return opterror(NiL, 0, 0, NiL, NiL);
+}
+
+/*
+ * parse long options with 0,1,2 leading '-' or '+' from string and pass to optget()
+ * syntax is the unquoted
+ *
+ * <length> [-|+|--|++]<name>[[-+:|&=]=<value>\n (or \0 for the last)
+ *
+ * or the quoted
+ *
+ * [-|+|--|++][no]name[[-+:|&=]=['"{(]value[)}"']][, ]...
+ *
+ * with \x escapes passed to chresc()
+ *
+ * return '#' for `label:', with opt_info.name==label
+ * str[opt_info.offset] next arg
+ *
+ * optstr(s, 0)
+ * return '-' if arg, 0 otherwise
+ * optstr(0, opts)
+ * use previous parsed str
+ */
+
+int
+optstr(const char* str, const char* opts)
+{
+ register char* s = (char*)str;
+ register Sfio_t* mp;
+ register int c;
+ register int ql;
+ register int qr;
+ register int qc;
+ int v;
+ char* e;
+
+ again:
+ if (s)
+ {
+ if (!(mp = state.strp) && !(mp = state.strp = sfstropen()))
+ return 0;
+ if (state.str != s)
+ state.str = s;
+ else if (opt_info.index == 1)
+ s += opt_info.offset;
+ while (*s == ',' || *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
+ s++;
+ if (!*s)
+ {
+ state.str = 0;
+ return 0;
+ }
+ if (*s == '-' || *s == '+')
+ {
+ c = *s++;
+ sfputc(mp, c);
+ if (*s == c)
+ {
+ sfputc(mp, c);
+ s++;
+ }
+ }
+ else
+ {
+ sfputc(mp, '-');
+ sfputc(mp, '-');
+ }
+ if (isdigit(*s) && (v = (int)strtol(s, &e, 10)) > 1 && isspace(*e) && --v <= strlen(s) && (s[v] == 0 || s[v] == '\n'))
+ {
+ s += v;
+ while (isspace(*++e));
+ sfwrite(mp, e, s - e);
+ }
+ else
+ {
+ while (*s && *s != ',' && *s != ' ' && *s != '\t' && *s != '\n' && *s != '\r' && *s != '=' && *s != ':')
+ sfputc(mp, *s++);
+ if ((c = *s) == ':' && *(s + 1) != '=')
+ {
+ opt_info.index = 1;
+ opt_info.offset = ++s - (char*)str;
+ if (!(s = sfstruse(mp)))
+ goto nospace;
+ s += 2;
+ e = opt_info.name;
+ while (e < &opt_info.name[sizeof(opt_info.name)-1] && (*e++ = *s++));
+ opt_info.arg = 0;
+ opt_info.num = (long)(opt_info.number = 0);
+ opt_info.option[0] = ':';
+ opt_info.option[1] = 0;
+ return '#';
+ }
+ if (c == ':' || c == '=')
+ {
+ sfputc(mp, c);
+ ql = qr = 0;
+ while (c = *++s)
+ {
+ if (c == '\\')
+ {
+ sfputc(mp, chresc(s, &e));
+ s = e - 1;
+ }
+ else if (c == qr)
+ {
+ if (qr != ql)
+ sfputc(mp, c);
+ if (--qc <= 0)
+ qr = ql = 0;
+ }
+ else if (c == ql)
+ {
+ sfputc(mp, c);
+ qc++;
+ }
+ else if (qr)
+ sfputc(mp, c);
+ else if (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r')
+ break;
+ else if (c == '"' || c == '\'')
+ {
+ ql = qr = c;
+ qc = 1;
+ }
+ else
+ {
+ sfputc(mp, c);
+ if (c == GO)
+ {
+ ql = c;
+ qr = OG;
+ qc = 1;
+ }
+ else if (c == '(')
+ {
+ ql = c;
+ qr = ')';
+ qc = 1;
+ }
+ }
+ }
+ }
+ }
+ opt_info.argv = state.strv;
+ state.strv[0] = T(NiL, ID, "option");
+ if (!(state.strv[1] = sfstruse(mp)))
+ goto nospace;
+ state.strv[2] = 0;
+ opt_info.offset = s - (char*)str;
+ }
+ if (opts)
+ {
+ if (!state.strv[1])
+ {
+ state.str = 0;
+ return 0;
+ }
+ opt_info.index = 1;
+ v = opt_info.offset;
+ opt_info.offset = 0;
+ c = optget(state.strv, opts);
+ opt_info.index = 1;
+ opt_info.offset = v;
+ if (c == '#')
+ {
+ s = state.str;
+ goto again;
+ }
+ if ((c == '?' || c == ':') && (opt_info.arg[0] == '-' && opt_info.arg[1] == '-'))
+ opt_info.arg += 2;
+ s = opt_info.name;
+ if (*s++ == '-' && *s++ == '-' && *s)
+ {
+ e = opt_info.name;
+ while (*e++ = *s++);
+ }
+ }
+ else
+ c = '-';
+ return c;
+ nospace:
+ return opterror(NiL, 0, 0, NiL, NiL);
+}
diff --git a/src/lib/libast/misc/optjoin.c b/src/lib/libast/misc/optjoin.c
new file mode 100644
index 0000000..1648dec
--- /dev/null
+++ b/src/lib/libast/misc/optjoin.c
@@ -0,0 +1,129 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * multi-pass commmand line option parse assist
+ *
+ * int fun(char** argv, int last)
+ *
+ * each fun() argument parses as much of argv as
+ * possible starting at (opt_info.index,opt_info.offset) using
+ * optget()
+ *
+ * if last!=0 then fun is the last pass to view
+ * the current arg, otherwise fun sets opt_info.again=1
+ * and another pass will get a crack at it
+ *
+ * 0 fun() return causes immediate optjoin() 0 return
+ *
+ * optjoin() returns non-zero if more args remain
+ * to be parsed at opt_info.index
+ */
+
+#include <optlib.h>
+
+typedef int (*Optpass_f)(char**, int);
+
+int
+optjoin(char** argv, ...)
+{
+ va_list ap;
+ register Optpass_f fun;
+ register Optpass_f rep;
+ Optpass_f err;
+ Optstate_t* state;
+ int r;
+ int more;
+ int user;
+ int last_index;
+ int last_offset;
+ int err_index;
+ int err_offset;
+
+ state = optstate(&opt_info);
+ err = rep = 0;
+ r = -1;
+ while (r < 0)
+ {
+ va_start(ap, argv);
+ state->join = 0;
+ while (fun = va_arg(ap, Optpass_f))
+ {
+ last_index = opt_info.index;
+ last_offset = opt_info.offset;
+ state->join++;
+ user = (*fun)(argv, 0);
+ more = argv[opt_info.index] != 0;
+ if (!opt_info.again)
+ {
+ if (!more)
+ {
+ state->join = 0;
+ r = 0;
+ break;
+ }
+ if (!user)
+ {
+ if (*argv[opt_info.index] != '+')
+ {
+ state->join = 0;
+ r = 1;
+ break;
+ }
+ opt_info.again = -1;
+ }
+ else
+ err = 0;
+ }
+ if (opt_info.again)
+ {
+ if (opt_info.again > 0 && (!err || err_index < opt_info.index || err_index == opt_info.index && err_offset < opt_info.offset))
+ {
+ err = fun;
+ err_index = opt_info.index;
+ err_offset = opt_info.offset;
+ }
+ opt_info.again = 0;
+ opt_info.index = state->pindex ? state->pindex : 1;
+ opt_info.offset = state->poffset;
+ }
+ if (!rep || opt_info.index != last_index || opt_info.offset != last_offset)
+ rep = fun;
+ else if (fun == rep)
+ {
+ if (!err)
+ {
+ state->join = 0;
+ r = 1;
+ break;
+ }
+ (*err)(argv, 1);
+ opt_info.offset = 0;
+ }
+ }
+ va_end(ap);
+ }
+ return r;
+}
diff --git a/src/lib/libast/misc/optlib.h b/src/lib/libast/misc/optlib.h
new file mode 100644
index 0000000..5cafed9
--- /dev/null
+++ b/src/lib/libast/misc/optlib.h
@@ -0,0 +1,115 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * command line option parser and usage formatter private definitions
+ */
+
+#ifndef _OPTLIB_H
+#define _OPTLIB_H
+
+#include <ast.h>
+#include <cdt.h>
+
+#define OPT_append 0x001
+#define OPT_cache 0x002
+#define OPT_functions 0x004
+#define OPT_ignore 0x008
+#define OPT_long 0x010
+#define OPT_minus 0x020
+#define OPT_module 0x040
+#define OPT_numeric 0x080
+#define OPT_old 0x100
+#define OPT_plus 0x200
+
+#define OPT_cache_flag 0x001
+#define OPT_cache_invert 0x002
+#define OPT_cache_numeric 0x004
+#define OPT_cache_optional 0x008
+#define OPT_cache_string 0x010
+
+#define OPT_CACHE 128
+#define OPT_FLAGS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+
+struct Optdisc_s;
+
+typedef struct Optpass_s
+{
+ char* opts;
+ char* oopts;
+ char* id;
+ char* catalog;
+ char* release;
+ char section[4];
+ unsigned char version;
+ unsigned char prefix;
+ unsigned short flags;
+} Optpass_t;
+
+typedef struct Optcache_s
+{
+ struct Optcache_s* next;
+ Optpass_t pass;
+ int caching;
+ unsigned char flags[sizeof(OPT_FLAGS)];
+} Optcache_t;
+
+typedef struct Optstate_s
+{
+ Sfio_t* mp; /* opt_info.msg string stream */
+ Sfio_t* vp; /* translation string stream */
+ Sfio_t* xp; /* translation string stream */
+ Sfio_t* cp; /* compatibility string stream */
+ Optpass_t pass[8]; /* optjoin() list */
+ char* argv[2]; /* initial argv copy */
+ char* strv[3]; /* optstr() argv */
+ char* str; /* optstr() string */
+ Sfio_t* strp; /* optstr() stream */
+ int force; /* force this style */
+ int pindex; /* prev index for backup */
+ int poffset; /* prev offset for backup */
+ int npass; /* # optjoin() passes */
+ int join; /* optjoin() pass # */
+ int plus; /* + ok */
+ int style; /* default opthelp() style */
+ int width; /* format line width */
+ int flags; /* display flags */
+ int emphasis; /* ansi term emphasis ok */
+ int localized; /* locale initialized */
+ Dtdisc_t msgdisc; /* msgdict discipline */
+ Dt_t* msgdict; /* default ast.id catalog msgs */
+ Optcache_t* cache; /* OPT_cache cache */
+ char** conformance; /* conformance id vector */
+} Optstate_t;
+
+#define _OPT_PRIVATE_ \
+ char pad[2*sizeof(void*)]; \
+ Optstate_t* state;
+
+#include <error.h>
+
+extern Optstate_t* optstate(Opt_t*);
+
+#endif
diff --git a/src/lib/libast/misc/procclose.c b/src/lib/libast/misc/procclose.c
new file mode 100644
index 0000000..a492454
--- /dev/null
+++ b/src/lib/libast/misc/procclose.c
@@ -0,0 +1,98 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * close a proc opened by procopen()
+ * otherwise exit() status of process is returned
+ */
+
+#include "proclib.h"
+
+int
+procclose(register Proc_t* p)
+{
+ int pid;
+ int flags = 0;
+ int status = -1;
+
+ if (p)
+ {
+ if (p->rfd >= 0)
+ close(p->rfd);
+ if (p->wfd >= 0 && p->wfd != p->rfd)
+ close(p->wfd);
+ if (p->flags & PROC_ORPHAN)
+ status = 0;
+ else
+ {
+ if (p->flags & PROC_ZOMBIE)
+ {
+ /*
+ * process may leave a zombie behind
+ * give it a chance to do that but
+ * don't hang waiting for it
+ */
+
+ flags |= WNOHANG;
+ sleep(1);
+ }
+ if (!(p->flags & PROC_FOREGROUND))
+ sigcritical(SIG_REG_EXEC|SIG_REG_PROC);
+ while ((pid = waitpid(p->pid, &status, flags)) == -1 && errno == EINTR);
+ if (pid != p->pid && (flags & WNOHANG))
+ status = 0;
+ if (!(p->flags & PROC_FOREGROUND))
+ sigcritical(0);
+ else
+ {
+ if (p->sigint != SIG_IGN)
+ signal(SIGINT, p->sigint);
+ if (p->sigquit != SIG_IGN)
+ signal(SIGQUIT, p->sigquit);
+#if defined(SIGCHLD)
+#if _lib_sigprocmask
+ sigprocmask(SIG_SETMASK, &p->mask, NiL);
+#else
+#if _lib_sigsetmask
+ sigsetmask(p->mask);
+#else
+ if (p->sigchld != SIG_DFL)
+ signal(SIGCHLD, p->sigchld);
+#endif
+#endif
+#endif
+ }
+ status = status == -1 ?
+ EXIT_QUIT :
+ WIFSIGNALED(status) ?
+ EXIT_TERM(WTERMSIG(status)) :
+ EXIT_CODE(WEXITSTATUS(status));
+ }
+ procfree(p);
+ }
+ else
+ status = errno == ENOENT ? EXIT_NOTFOUND : EXIT_NOEXEC;
+ return status;
+}
diff --git a/src/lib/libast/misc/procfree.c b/src/lib/libast/misc/procfree.c
new file mode 100644
index 0000000..d14ff35
--- /dev/null
+++ b/src/lib/libast/misc/procfree.c
@@ -0,0 +1,43 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * free a proc opened by procopen()
+ * skipping wait() and close()
+ */
+
+#include "proclib.h"
+
+int
+procfree(register Proc_t* p)
+{
+ if (!p)
+ return -1;
+ if (p == &proc_default)
+ p->pid = -1;
+ else
+ free(p);
+ return 0;
+}
diff --git a/src/lib/libast/misc/proclib.h b/src/lib/libast/misc/proclib.h
new file mode 100644
index 0000000..45fc242
--- /dev/null
+++ b/src/lib/libast/misc/proclib.h
@@ -0,0 +1,64 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * process library definitions
+ */
+
+#ifndef _PROCLIB_H
+#define _PROCLIB_H
+
+#include <ast.h>
+#include <errno.h>
+#include <sig.h>
+#include <wait.h>
+
+#if _lib_sigprocmask
+typedef sigset_t Sig_mask_t;
+#else
+typedef unsigned long Sig_mask_t;
+#endif
+
+struct Mods_s;
+
+#define _PROC_PRIVATE_ \
+ struct Mod_s* mods; /* process modification state */ \
+ long flags; /* original PROC_* flags */ \
+ Sig_mask_t mask; /* original blocked sig mask */ \
+ Sig_handler_t sigchld; /* PROC_FOREGROUND SIG_DFL */ \
+ Sig_handler_t sigint; /* PROC_FOREGROUND SIG_IGN */ \
+ Sig_handler_t sigquit; /* PROC_FOREGROUND SIG_IGN */
+
+#include <proc.h>
+
+#define proc_default _proc_info_ /* hide external symbol */
+
+extern Proc_t proc_default; /* first proc */
+
+#ifndef errno
+extern int errno;
+#endif
+
+#endif
diff --git a/src/lib/libast/misc/procopen.c b/src/lib/libast/misc/procopen.c
new file mode 100644
index 0000000..aa8240a
--- /dev/null
+++ b/src/lib/libast/misc/procopen.c
@@ -0,0 +1,941 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * common process execution support with
+ * proper sfio, signal and wait() syncronization
+ *
+ * _ contains the process path name and is
+ * placed at the top of the environment
+ */
+
+#include "proclib.h"
+
+#include <ls.h>
+#include <ast_tty.h>
+
+/*
+ * not quite ready for _use_spawnveg
+ */
+
+#if _use_spawnveg
+#if _lib_fork
+#undef _use_spawnveg
+#else
+#if _WINIX
+#define _lib_fork 1
+#endif
+#endif
+#endif
+
+#ifndef DEBUG_PROC
+#define DEBUG_PROC 1
+#endif
+
+#if _lib_socketpair
+#if _sys_socket
+#include <sys/types.h>
+#include <sys/socket.h>
+#else
+#undef _lib_socketpair
+#endif
+#endif
+
+Proc_t proc_default = { -1 };
+
+#if DEBUG_PROC
+
+#include <namval.h>
+
+#define PROC_ENV_OPTIONS "PROC_OPTIONS"
+
+#define PROC_OPT_ENVIRONMENT (1<<0)
+#define PROC_OPT_EXEC (1<<1)
+#define PROC_OPT_TRACE (1<<2)
+#define PROC_OPT_VERBOSE (1<<3)
+
+static const Namval_t options[] =
+{
+ "debug", PROC_OPT_VERBOSE,
+ "environment", PROC_OPT_ENVIRONMENT,
+ "exec", PROC_OPT_EXEC,
+ "trace", PROC_OPT_TRACE,
+ "verbose", PROC_OPT_VERBOSE,
+ 0, 0
+};
+
+/*
+ * called by stropt() to set options
+ */
+
+static int
+setopt(register void* a, register const void* p, register int n, const char* v)
+{
+ NoP(v);
+ if (p)
+ {
+ if (n)
+ *((int*)a) |= ((Namval_t*)p)->value;
+ else
+ *((int*)a) &= ~((Namval_t*)p)->value;
+ }
+ return 0;
+}
+
+#endif
+
+#if _use_spawnveg
+
+typedef struct Fd_s
+{
+ short fd;
+ short flag;
+} Fd_t;
+
+typedef struct Mod_s
+{
+ struct Mod_s* next;
+ short op;
+ short save;
+
+ union
+ {
+
+ struct
+ {
+ Fd_t parent;
+ Fd_t child;
+ } fd;
+
+ Handler_t handler;
+
+ } arg;
+
+} Modify_t;
+
+#endif
+
+#ifdef SIGPIPE
+
+/*
+ * catch but ignore sig
+ * avoids SIG_IGN being passed to children
+ */
+
+static void
+ignoresig(int sig)
+{
+ signal(sig, ignoresig);
+}
+
+#endif
+
+/*
+ * do modification op and save previous state for restore()
+ */
+
+static int
+modify(Proc_t* proc, int forked, int op, long arg1, long arg2)
+{
+#if _lib_fork
+ if (forked)
+ {
+ int i;
+ int k;
+#ifndef TIOCSCTTY
+ char* s;
+#endif
+
+ switch (op)
+ {
+ case PROC_fd_dup:
+ case PROC_fd_dup|PROC_FD_PARENT:
+ case PROC_fd_dup|PROC_FD_CHILD:
+ case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
+ if (arg1 != arg2)
+ {
+ if (arg2 != PROC_ARG_NULL)
+ {
+ close(arg2);
+ if (fcntl(arg1, F_DUPFD, arg2) != arg2)
+ return -1;
+ }
+ if (op & PROC_FD_CHILD)
+ close(arg1);
+ }
+ break;
+ case PROC_fd_ctty:
+ setsid();
+ for (i = 0; i <= 2; i++)
+ if (arg1 != i)
+ close(i);
+ arg2 = -1;
+#ifdef TIOCSCTTY
+ if (ioctl(arg1, TIOCSCTTY, NiL) < 0)
+ return -1;
+#else
+ if (!(s = ttyname(arg1)))
+ return -1;
+ if ((arg2 = open(s, O_RDWR)) < 0)
+ return -1;
+#endif
+ for (i = 0; i <= 2; i++)
+ if (arg1 != i && arg2 != i && (k = fcntl(arg1, F_DUPFD, i)) != i)
+ return -1;
+ if (arg1 > 2)
+ close(arg1);
+ if (arg2 > 2)
+ close(arg2);
+ break;
+ case PROC_sig_dfl:
+ signal(arg1, SIG_DFL);
+ break;
+ case PROC_sig_ign:
+ signal(arg1, SIG_IGN);
+ break;
+ case PROC_sys_pgrp:
+ if (arg1 < 0)
+ setsid();
+ else if (arg1 > 0)
+ {
+ if (arg1 == 1)
+ arg1 = 0;
+ if (setpgid(0, arg1) < 0 && arg1 && errno == EPERM)
+ setpgid(0, 0);
+ }
+ break;
+ case PROC_sys_umask:
+ umask(arg1);
+ break;
+ default:
+ return -1;
+ }
+ }
+#if _use_spawnveg
+ else
+#endif
+#else
+ NoP(forked);
+#endif
+#if _use_spawnveg
+ {
+ register Modify_t* m;
+
+ if (!(m = newof(NiL, Modify_t, 1, 0)))
+ return -1;
+ m->next = proc->mods;
+ proc->mods = m;
+ switch (m->op = op)
+ {
+ case PROC_fd_dup:
+ case PROC_fd_dup|PROC_FD_PARENT:
+ case PROC_fd_dup|PROC_FD_CHILD:
+ case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
+ m->arg.fd.parent.fd = (short)arg1;
+ m->arg.fd.parent.flag = fcntl(arg1, F_GETFD, 0);
+ if ((m->arg.fd.child.fd = (short)arg2) != arg1)
+ {
+ if (arg2 != PROC_ARG_NULL)
+ {
+ m->arg.fd.child.flag = fcntl(arg2, F_GETFD, 0);
+ if ((m->save = fcntl(arg2, F_DUPFD, 3)) < 0)
+ {
+ m->op = 0;
+ return -1;
+ }
+ fcntl(m->save, F_SETFD, FD_CLOEXEC);
+ close(arg2);
+ if (fcntl(arg1, F_DUPFD, arg2) != arg2)
+ return -1;
+ if (op & PROC_FD_CHILD)
+ close(arg1);
+ }
+ else if (op & PROC_FD_CHILD)
+ {
+ if (m->arg.fd.parent.flag)
+ break;
+ fcntl(arg1, F_SETFD, FD_CLOEXEC);
+ }
+ else if (!m->arg.fd.parent.flag)
+ break;
+ else
+ fcntl(arg1, F_SETFD, 0);
+ return 0;
+ }
+ break;
+ case PROC_sig_dfl:
+ if ((m->arg.handler = signal(arg1, SIG_DFL)) == SIG_DFL)
+ break;
+ m->save = (short)arg1;
+ return 0;
+ case PROC_sig_ign:
+ if ((m->arg.handler = signal(arg1, SIG_IGN)) == SIG_IGN)
+ break;
+ m->save = (short)arg1;
+ return 0;
+ case PROC_sys_pgrp:
+ proc->pgrp = arg1;
+ break;
+ case PROC_sys_umask:
+ if ((m->save = (short)umask(arg1)) == arg1)
+ break;
+ return 0;
+ default:
+ proc->mods = m->next;
+ free(m);
+ return -1;
+ }
+ proc->mods = m->next;
+ free(m);
+ }
+#else
+ NoP(proc);
+#endif
+ return 0;
+}
+
+#if _use_spawnveg
+
+/*
+ * restore modifications
+ */
+
+static void
+restore(Proc_t* proc)
+{
+ register Modify_t* m;
+ register Modify_t* p;
+ int oerrno;
+
+ NoP(proc);
+ oerrno = errno;
+ m = proc->mods;
+ proc->mods = 0;
+ while (m)
+ {
+ switch (m->op)
+ {
+ case PROC_fd_dup:
+ case PROC_fd_dup|PROC_FD_PARENT:
+ case PROC_fd_dup|PROC_FD_CHILD:
+ case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
+ if (m->op & PROC_FD_PARENT)
+ close(m->arg.fd.parent.fd);
+ if (m->arg.fd.child.fd != m->arg.fd.parent.fd && m->arg.fd.child.fd != PROC_ARG_NULL)
+ {
+ if (!(m->op & PROC_FD_PARENT))
+ {
+ if (m->op & PROC_FD_CHILD)
+ {
+ close(m->arg.fd.parent.fd);
+ fcntl(m->arg.fd.child.fd, F_DUPFD, m->arg.fd.parent.fd);
+ }
+ fcntl(m->arg.fd.parent.fd, F_SETFD, m->arg.fd.parent.flag);
+ }
+ close(m->arg.fd.child.fd);
+ fcntl(m->save, F_DUPFD, m->arg.fd.child.fd);
+ close(m->save);
+ if (m->arg.fd.child.flag)
+ fcntl(m->arg.fd.child.fd, F_SETFD, FD_CLOEXEC);
+ }
+ else if ((m->op & (PROC_FD_PARENT|PROC_FD_CHILD)) == PROC_FD_CHILD)
+ fcntl(m->arg.fd.parent.fd, F_SETFD, 0);
+ break;
+ case PROC_sig_dfl:
+ case PROC_sig_ign:
+ signal(m->save, m->arg.handler);
+ break;
+ case PROC_sys_umask:
+ umask(m->save);
+ break;
+ }
+ p = m;
+ m = m->next;
+ free(p);
+ }
+ errno = oerrno;
+}
+
+#else
+
+#define restore(p)
+
+#endif
+
+/*
+ * fork and exec or spawn proc(argv) and return a Proc_t handle
+ *
+ * pipe not used when PROC_READ|PROC_WRITE omitted
+ * argv==0 duplicates current process if possible
+ * cmd==0 names the current shell
+ * cmd=="" does error cleanup
+ * envv is the child environment
+ * modv is the child modification vector of PROC_*() ops
+ */
+
+Proc_t*
+procopen(const char* cmd, char** argv, char** envv, long* modv, int flags)
+{
+ register Proc_t* proc = 0;
+ register int procfd;
+ register char** p;
+ char** v;
+ int i;
+ int forked = 0;
+ int signalled = 0;
+ long n;
+ char path[PATH_MAX];
+ char env[PATH_MAX + 2];
+ int pio[2];
+#if _lib_fork
+ int pop[2];
+#endif
+#if !_pipe_rw && !_lib_socketpair
+ int poi[2];
+#endif
+#if defined(SIGCHLD) && ( _lib_sigprocmask || _lib_sigsetmask )
+ Sig_mask_t mask;
+#endif
+#if _use_spawnveg
+ int newenv = 0;
+#endif
+#if DEBUG_PROC
+ int debug = PROC_OPT_EXEC;
+#endif
+
+#if _lib_fork
+ if (!argv && (flags & (PROC_ORPHAN|PROC_OVERLAY)))
+#else
+ if (!argv || (flags & PROC_ORPHAN))
+#endif
+ {
+ errno = ENOEXEC;
+ return 0;
+ }
+ pio[0] = pio[1] = -1;
+#if _lib_fork
+ pop[0] = pop[1] = -1;
+#endif
+#if !_pipe_rw && !_lib_socketpair
+ poi[0] = poi[1] = -1;
+#endif
+ if (cmd && (!*cmd || !pathpath(cmd, NiL, PATH_REGULAR|PATH_EXECUTE, path, sizeof(path))))
+ goto bad;
+ switch (flags & (PROC_READ|PROC_WRITE))
+ {
+ case 0:
+ procfd = -1;
+ break;
+ case PROC_READ:
+ procfd = 1;
+ break;
+ case PROC_WRITE:
+ procfd = 0;
+ break;
+ case PROC_READ|PROC_WRITE:
+ procfd = 2;
+ break;
+ }
+ if (proc_default.pid == -1)
+ proc = &proc_default;
+ else if (!(proc = newof(0, Proc_t, 1, 0)))
+ goto bad;
+ proc->pid = -1;
+ proc->pgrp = 0;
+ proc->rfd = -1;
+ proc->wfd = -1;
+ proc->flags = flags;
+ sfsync(NiL);
+ if (environ && envv != (char**)environ && (envv || (flags & PROC_PARANOID) || argv && (environ[0][0] != '_' || environ[0][1] != '=')))
+ {
+ if (!setenviron(NiL))
+ goto bad;
+#if _use_spawnveg
+ if (!(flags & PROC_ORPHAN))
+ newenv = 1;
+#endif
+ }
+ if (procfd >= 0)
+ {
+#if _pipe_rw
+ if (pipe(pio))
+ goto bad;
+#else
+ if (procfd > 1)
+ {
+#if _lib_socketpair
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, pio))
+ goto bad;
+#else
+ if (pipe(pio) || pipe(poi))
+ goto bad;
+#endif
+ }
+ else if (pipe(pio))
+ goto bad;
+#endif
+ }
+ if (flags & PROC_OVERLAY)
+ {
+ proc->pid = 0;
+ forked = 1;
+ }
+#if _use_spawnveg
+ else if (argv && !(flags & PROC_ORPHAN))
+ proc->pid = 0;
+#endif
+#if _lib_fork
+ else
+ {
+ if (!(flags & PROC_FOREGROUND))
+ sigcritical(SIG_REG_EXEC|SIG_REG_PROC);
+ else
+ {
+ signalled = 1;
+ proc->sigint = signal(SIGINT, SIG_IGN);
+ proc->sigquit = signal(SIGQUIT, SIG_IGN);
+#if defined(SIGCHLD)
+#if _lib_sigprocmask
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &mask, &proc->mask);
+#else
+#if _lib_sigsetmask
+ mask = sigmask(SIGCHLD);
+ proc->mask = sigblock(mask);
+#else
+ proc->sigchld = signal(SIGCHLD, SIG_DFL);
+#endif
+#endif
+#endif
+ }
+ if ((flags & PROC_ORPHAN) && pipe(pop))
+ goto bad;
+ proc->pid = fork();
+ if (!(flags & PROC_FOREGROUND))
+ sigcritical(0);
+ else if (!proc->pid)
+ {
+ if (proc->sigint != SIG_IGN)
+ {
+ proc->sigint = SIG_DFL;
+ signal(SIGINT, proc->sigint);
+ }
+ if (proc->sigquit != SIG_IGN)
+ {
+ proc->sigquit = SIG_DFL;
+ signal(SIGQUIT, proc->sigquit);
+ }
+#if defined(SIGCHLD)
+#if _lib_sigprocmask
+ sigprocmask(SIG_SETMASK, &proc->mask, NiL);
+#else
+#if _lib_sigsetmask
+ sigsetmask(proc->mask);
+#else
+ if (proc->sigchld != SIG_IGN)
+ signal(SIGCHLD, SIG_DFL);
+#endif
+#endif
+#endif
+ }
+ else if (proc->pid == -1)
+ goto bad;
+ forked = 1;
+ }
+#endif
+ if (!proc->pid)
+ {
+#if _use_spawnveg
+ char** oenviron = 0;
+ char* oenviron0 = 0;
+
+ v = 0;
+#endif
+#if _lib_fork
+ if (flags & PROC_ORPHAN)
+ {
+ if (!(proc->pid = fork()))
+ {
+ close(pop[0]);
+ close(pop[1]);
+ }
+ else
+ {
+ if (proc->pid > 0)
+ write(pop[1], &proc->pid, sizeof(proc->pid));
+ _exit(EXIT_NOEXEC);
+ }
+ }
+#endif
+#if DEBUG_PROC
+ stropt(getenv(PROC_ENV_OPTIONS), options, sizeof(*options), setopt, &debug);
+#if _lib_fork
+ if (debug & PROC_OPT_TRACE)
+ {
+ if (!fork())
+ {
+ sfsprintf(path, sizeof(path), "%d", getppid());
+ execlp("trace", "trace", "-p", path, NiL);
+ _exit(EXIT_NOTFOUND);
+ }
+ sleep(2);
+ }
+#endif
+#endif
+ if (flags & PROC_DAEMON)
+ {
+#ifdef SIGHUP
+ modify(proc, forked, PROC_sig_ign, SIGHUP, 0);
+#endif
+ modify(proc, forked, PROC_sig_dfl, SIGTERM, 0);
+#ifdef SIGTSTP
+ modify(proc, forked, PROC_sig_ign, SIGTSTP, 0);
+#endif
+#ifdef SIGTTIN
+ modify(proc, forked, PROC_sig_ign, SIGTTIN, 0);
+#endif
+#ifdef SIGTTOU
+ modify(proc, forked, PROC_sig_ign, SIGTTOU, 0);
+#endif
+ }
+ if (flags & (PROC_BACKGROUND|PROC_DAEMON))
+ {
+ modify(proc, forked, PROC_sig_ign, SIGINT, 0);
+#ifdef SIGQUIT
+ modify(proc, forked, PROC_sig_ign, SIGQUIT, 0);
+#endif
+ }
+ if (flags & (PROC_DAEMON|PROC_SESSION))
+ modify(proc, forked, PROC_sys_pgrp, -1, 0);
+ if (forked || (flags & PROC_OVERLAY))
+ {
+ if ((flags & PROC_PRIVELEGED) && !geteuid())
+ {
+ setuid(geteuid());
+ setgid(getegid());
+ }
+ if (flags & (PROC_PARANOID|PROC_GID))
+ setgid(getgid());
+ if (flags & (PROC_PARANOID|PROC_UID))
+ setuid(getuid());
+ }
+ if (procfd > 1)
+ {
+ if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[0], PROC_ARG_NULL))
+ goto cleanup;
+ if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[1], 1))
+ goto cleanup;
+#if _pipe_rw || _lib_socketpair
+ if (modify(proc, forked, PROC_fd_dup, 1, 0))
+ goto cleanup;
+#else
+ if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, poi[0], 0))
+ goto cleanup;
+ if (poi[1] != 0 && modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, poi[1], PROC_ARG_NULL))
+ goto cleanup;
+#endif
+ }
+ else if (procfd >= 0)
+ {
+ if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[!!procfd], !!procfd))
+ goto cleanup;
+ if (pio[!procfd] != !!procfd && modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[!procfd], PROC_ARG_NULL))
+ goto cleanup;
+ }
+ if (modv)
+ for (i = 0; n = modv[i]; i++)
+ switch (PROC_OP(n))
+ {
+ case PROC_fd_dup:
+ case PROC_fd_dup|PROC_FD_PARENT:
+ case PROC_fd_dup|PROC_FD_CHILD:
+ case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
+ if (modify(proc, forked, PROC_OP(n), PROC_ARG(n, 1), PROC_ARG(n, 2)))
+ goto cleanup;
+ break;
+ default:
+ if (modify(proc, forked, PROC_OP(n), PROC_ARG(n, 1), 0))
+ goto cleanup;
+ break;
+ }
+#if _lib_fork
+ if (forked && (flags & PROC_ENVCLEAR))
+ environ = 0;
+#if _use_spawnveg
+ else
+#endif
+#endif
+#if _use_spawnveg
+ if (newenv)
+ {
+ p = environ;
+ while (*p++);
+ if (!(oenviron = (char**)memdup(environ, (p - environ) * sizeof(char*))))
+ goto cleanup;
+ }
+#endif
+ if (argv && envv != (char**)environ)
+ {
+#if _use_spawnveg
+ if (!newenv && environ[0][0] == '_' && environ[0][1] == '=')
+ oenviron0 = environ[0];
+#endif
+ env[0] = '_';
+ env[1] = '=';
+ env[2] = 0;
+ if (!setenviron(env))
+ goto cleanup;
+ }
+ if ((flags & PROC_PARANOID) && setenv("PATH", astconf("PATH", NiL, NiL), 1))
+ goto cleanup;
+ if ((p = envv) && p != (char**)environ)
+ while (*p)
+ if (!setenviron(*p++))
+ goto cleanup;
+ p = argv;
+#if _lib_fork
+ if (forked && !p)
+ return proc;
+#endif
+#if DEBUG_PROC
+ if (!(debug & PROC_OPT_EXEC) || (debug & PROC_OPT_VERBOSE))
+ {
+ if ((debug & PROC_OPT_ENVIRONMENT) && (p = environ))
+ while (*p)
+ sfprintf(sfstderr, "%s\n", *p++);
+ sfprintf(sfstderr, "+ %s", cmd ? path : "sh");
+ if ((p = argv) && *p)
+ while (*++p)
+ sfprintf(sfstderr, " %s", *p);
+ sfprintf(sfstderr, "\n");
+sfsync(sfstderr);
+ if (!(debug & PROC_OPT_EXEC))
+ _exit(0);
+ p = argv;
+ }
+#endif
+ if (cmd)
+ {
+ strcpy(env + 2, path);
+ if (forked || (flags & PROC_OVERLAY))
+ execve(path, p, environ);
+#if _use_spawnveg
+ else if ((proc->pid = spawnveg(path, p, environ, proc->pgrp)) != -1)
+ goto cleanup;
+#endif
+ if (errno != ENOEXEC)
+ goto cleanup;
+
+ /*
+ * try cmd as a shell script
+ */
+
+ if (!(flags & PROC_ARGMOD))
+ {
+ while (*p++);
+ if (!(v = newof(0, char*, p - argv + 2, 0)))
+ goto cleanup;
+ p = v + 2;
+ if (*argv)
+ argv++;
+ while (*p++ = *argv++);
+ p = v + 1;
+ }
+ *p = path;
+ *--p = "sh";
+ }
+ strcpy(env + 2, (flags & PROC_PARANOID) ? astconf("SH", NiL, NiL) : pathshell());
+ if (forked || (flags & PROC_OVERLAY))
+ execve(env + 2, p, environ);
+#if _use_spawnveg
+ else
+ proc->pid = spawnveg(env + 2, p, environ, proc->pgrp);
+#endif
+ cleanup:
+ if (forked)
+ {
+ if (!(flags & PROC_OVERLAY))
+ _exit(errno == ENOENT ? EXIT_NOTFOUND : EXIT_NOEXEC);
+ goto bad;
+ }
+#if _use_spawnveg
+ if (v)
+ free(v);
+ if (p = oenviron)
+ {
+ environ = 0;
+ while (*p)
+ if (!setenviron(*p++))
+ goto bad;
+ free(oenviron);
+ }
+ else if (oenviron0)
+ environ[0] = oenviron0;
+ restore(proc);
+ if (flags & PROC_OVERLAY)
+ exit(0);
+#endif
+ }
+ if (proc->pid != -1)
+ {
+ if (!forked)
+ {
+ if (flags & PROC_FOREGROUND)
+ {
+ signalled = 1;
+ proc->sigint = signal(SIGINT, SIG_IGN);
+ proc->sigquit = signal(SIGQUIT, SIG_IGN);
+#if defined(SIGCHLD)
+#if _lib_sigprocmask
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &mask, &proc->mask);
+#else
+#if _lib_sigsetmask
+ mask = sigmask(SIGCHLD);
+ proc->mask = sigblock(mask);
+#else
+ proc->sigchld = signal(SIGCHLD, SIG_DFL);
+#endif
+#endif
+#endif
+ }
+ }
+ else if (modv)
+ for (i = 0; n = modv[i]; i++)
+ switch (PROC_OP(n))
+ {
+ case PROC_fd_dup|PROC_FD_PARENT:
+ case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
+ close(PROC_ARG(n, 1));
+ break;
+ case PROC_sys_pgrp:
+ if (proc->pgrp < 0)
+ proc->pgrp = proc->pid;
+ else if (proc->pgrp > 0)
+ {
+ if (proc->pgrp == 1)
+ proc->pgrp = proc->pid;
+ if (setpgid(proc->pid, proc->pgrp) < 0 && proc->pid != proc->pgrp && errno == EPERM)
+ setpgid(proc->pid, proc->pid);
+ }
+ break;
+ }
+ if (procfd >= 0)
+ {
+#ifdef SIGPIPE
+ if ((flags & (PROC_WRITE|PROC_IGNORE)) == (PROC_WRITE|PROC_IGNORE))
+ {
+ Handler_t handler;
+
+ if ((handler = signal(SIGPIPE, ignoresig)) != SIG_DFL && handler != ignoresig)
+ signal(SIGPIPE, handler);
+ }
+#endif
+ switch (procfd)
+ {
+ case 0:
+ proc->wfd = pio[1];
+ close(pio[0]);
+ break;
+ default:
+#if _pipe_rw || _lib_socketpair
+ proc->wfd = pio[0];
+#else
+ proc->wfd = poi[1];
+ close(poi[0]);
+#endif
+ /*FALLTHROUGH*/
+ case 1:
+ proc->rfd = pio[0];
+ close(pio[1]);
+ break;
+ }
+ if (proc->rfd > 2)
+ fcntl(proc->rfd, F_SETFD, FD_CLOEXEC);
+ if (proc->wfd > 2)
+ fcntl(proc->wfd, F_SETFD, FD_CLOEXEC);
+ }
+ if (!proc->pid)
+ proc->pid = getpid();
+ else if (flags & PROC_ORPHAN)
+ {
+ while (waitpid(proc->pid, &i, 0) == -1 && errno == EINTR);
+ if (read(pop[0], &proc->pid, sizeof(proc->pid)) != sizeof(proc->pid))
+ goto bad;
+ close(pop[0]);
+ }
+ return proc;
+ }
+ bad:
+ if (signalled)
+ {
+ if (proc->sigint != SIG_IGN)
+ signal(SIGINT, proc->sigint);
+ if (proc->sigquit != SIG_IGN)
+ signal(SIGQUIT, proc->sigquit);
+#if defined(SIGCHLD)
+#if _lib_sigprocmask
+ sigprocmask(SIG_SETMASK, &proc->mask, NiL);
+#else
+#if _lib_sigsetmask
+ sigsetmask(proc->mask);
+#else
+ if (proc->sigchld != SIG_DFL)
+ signal(SIGCHLD, proc->sigchld);
+#endif
+#endif
+#endif
+ }
+ if ((flags & PROC_CLEANUP) && modv)
+ for (i = 0; n = modv[i]; i++)
+ switch (PROC_OP(n))
+ {
+ case PROC_fd_dup:
+ case PROC_fd_dup|PROC_FD_PARENT:
+ case PROC_fd_dup|PROC_FD_CHILD:
+ case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD:
+ if (PROC_ARG(n, 2) != PROC_ARG_NULL)
+ close(PROC_ARG(n, 1));
+ break;
+ }
+ if (pio[0] >= 0)
+ close(pio[0]);
+ if (pio[1] >= 0)
+ close(pio[1]);
+ if (pop[0] >= 0)
+ close(pop[0]);
+ if (pop[1] >= 0)
+ close(pop[1]);
+#if !_pipe_rw && !_lib_socketpair
+ if (poi[0] >= 0)
+ close(poi[0]);
+ if (poi[1] >= 0)
+ close(poi[1]);
+#endif
+ procfree(proc);
+ return 0;
+}
diff --git a/src/lib/libast/misc/procrun.c b/src/lib/libast/misc/procrun.c
new file mode 100644
index 0000000..a37e067
--- /dev/null
+++ b/src/lib/libast/misc/procrun.c
@@ -0,0 +1,49 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * procopen() + procclose()
+ * no env changes
+ * no modifications
+ * effective=real
+ * parent ignores INT & QUIT
+ */
+
+#include "proclib.h"
+
+int
+procrun(const char* path, char** argv, int flags)
+{
+#if __OBSOLETE__ < 20090101
+ flags &= argv ? PROC_ARGMOD : PROC_CHECK;
+#endif
+ if (flags & PROC_CHECK)
+ {
+ char buf[PATH_MAX];
+
+ return pathpath(path, NiL, PATH_REGULAR|PATH_EXECUTE, buf, sizeof(buf)) ? 0 : -1;
+ }
+ return procclose(procopen(path, argv, NiL, NiL, flags|PROC_FOREGROUND|PROC_GID|PROC_UID));
+}
diff --git a/src/lib/libast/misc/recfmt.c b/src/lib/libast/misc/recfmt.c
new file mode 100644
index 0000000..09c3220
--- /dev/null
+++ b/src/lib/libast/misc/recfmt.c
@@ -0,0 +1,165 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * determine record format by sampling data in <buf,size>
+ * total is the total file size, <=0 if not available
+ * return r:
+ * -1 could not determine
+ * RECTYPE(r)==REC_fixed fixed length REC_F_SIZE(r)
+ * RECTYPE(r)==REC_delimited variable length delimiter=REC_D_DELIMITER(r)
+ * RECTYPE(r)==REC_variable variable length
+ */
+
+#include <recfmt.h>
+
+typedef struct
+{
+ unsigned int rep[4 * 1024];
+ unsigned int hit[UCHAR_MAX + 1];
+} Sample_t;
+
+Recfmt_t
+recfmt(const void* buf, size_t size, off_t total)
+{
+ register unsigned char* s;
+ register unsigned char* t;
+ register Sample_t* q;
+ register unsigned int* h;
+ register unsigned int i;
+ unsigned int j;
+ unsigned int k;
+ unsigned int n;
+ unsigned int m;
+ unsigned int x;
+ unsigned long f;
+ unsigned long g;
+
+ static unsigned char terminators[] = { '\n', 0x15, 0x25 };
+
+ /*
+ * check for V format
+ */
+
+ s = (unsigned char*)buf;
+ t = s + size;
+ while ((k = (t - s)) >= 4 && !s[2] && !s[3])
+ {
+ if ((i = (s[0]<<8)|s[1]) > k)
+ break;
+ s += i;
+ }
+ if (!k || size > 2 * k)
+ return REC_V_TYPE(4, 0, 2, 0, 1);
+ s = (unsigned char*)buf;
+
+ /*
+ * check for terminated records
+ */
+
+ for (i = 0; i < elementsof(terminators); i++)
+ if ((t = (unsigned char*)memchr((void*)s, k = terminators[i], size / 2)) && (n = t - s + 1) > 1 && (total <= 0 || !(total % n)))
+ {
+ for (j = n - 1; j < size; j += n)
+ if (s[j] != k)
+ {
+ n = 0;
+ break;
+ }
+ if (n)
+ return REC_D_TYPE(terminators[i]);
+ }
+
+ /*
+ * check fixed length record frequencies
+ */
+
+ if (!(q = newof(0, Sample_t, 1, 0)))
+ return REC_N_TYPE();
+ x = 0;
+ for (i = 0; i < size; i++)
+ {
+ h = q->hit + s[i];
+ m = i - *h;
+ *h = i;
+ if (m < elementsof(q->rep))
+ {
+ if (m > x)
+ x = m;
+ q->rep[m]++;
+ }
+ }
+ n = 0;
+ m = 0;
+ f = ~0;
+ for (i = x; i > 1; i--)
+ {
+ if ((total <= 0 || !(total % i)) && q->rep[i] > q->rep[n])
+ {
+ m++;
+ g = 0;
+ for (j = i; j < size - i; j += i)
+ for (k = 0; k < i; k++)
+ if (s[j + k] != s[j + k - i])
+ g++;
+ g = (((g * 100) / i) * 100) / q->rep[i];
+ if (g <= f)
+ {
+ f = g;
+ n = i;
+ }
+ }
+ }
+ if (m <= 1 && n <= 2 && total > 1 && total < 256)
+ {
+ n = 0;
+ for (i = 0; i < size; i++)
+ for (j = 0; j < elementsof(terminators); j++)
+ if (s[i] == terminators[j])
+ n++;
+ n = n ? 0 : total;
+ }
+ free(q);
+ return n ? REC_F_TYPE(n) : REC_N_TYPE();
+}
+
+#if MAIN
+
+main()
+{
+ void* s;
+ size_t size;
+ off_t total;
+
+ if (!(s = sfreserve(sfstdin, SF_UNBOUND, 0)))
+ {
+ sfprintf(sfstderr, "read error\n");
+ return 1;
+ }
+ size = sfvalue(sfstdin);
+ total = sfsize(sfstdin);
+ sfprintf(sfstdout, "%d\n", recfmt(s, size, total));
+ return 0;
+}
+
+#endif
diff --git a/src/lib/libast/misc/reclen.c b/src/lib/libast/misc/reclen.c
new file mode 100644
index 0000000..ec927f8
--- /dev/null
+++ b/src/lib/libast/misc/reclen.c
@@ -0,0 +1,71 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * return the length of the current record at b, size n, according to f
+ * -1 returned on error
+ * 0 returned if more data is required
+ */
+
+#include <recfmt.h>
+#include <ctype.h>
+
+ssize_t
+reclen(Recfmt_t f, const void* b, size_t n)
+{
+ register unsigned char* s = (unsigned char*)b;
+ register unsigned char* e;
+ size_t h;
+ size_t z;
+
+ switch (RECTYPE(f))
+ {
+ case REC_delimited:
+ if (e = (unsigned char*)memchr(s, REC_D_DELIMITER(f), n))
+ return e - s + 1;
+ return 0;
+ case REC_fixed:
+ return REC_F_SIZE(f);
+ case REC_variable:
+ h = REC_V_HEADER(f);
+ if (n < h)
+ return 0;
+ z = 0;
+ s += REC_V_OFFSET(f);
+ e = s + REC_V_LENGTH(f);
+ if (REC_V_LITTLE(f))
+ while (e > s)
+ z = (z<<8)|*--e;
+ else
+ while (s < e)
+ z = (z<<8)|*s++;
+ if (!REC_V_INCLUSIVE(f))
+ z += h;
+ else if (z < h)
+ z = h;
+ return z;
+ case REC_method:
+ return -1;
+ }
+ return -1;
+}
diff --git a/src/lib/libast/misc/recstr.c b/src/lib/libast/misc/recstr.c
new file mode 100644
index 0000000..8ba8337
--- /dev/null
+++ b/src/lib/libast/misc/recstr.c
@@ -0,0 +1,206 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * return the record format descriptor given a format string
+ * e!=0 set to the first unrecognized char after the format
+ * REC_N_TYPE() returned on error
+ *
+ * d[0xNN|delimiter] (delimited, newline default)
+ * [f][+]size (fixed length)
+ * v hN oN zN b|l i|n (variable length with size header)
+ * h header size in bytes (ibm V 4)
+ * o size offset in bytes (ibm V 0)
+ * z size length in bytes (ibm V 2)
+ * l|b little-endian or big-endian size (ibm V b (0))
+ * i|n header included/not-included in size (ibm V i (1))
+ */
+
+#include <recfmt.h>
+#include <ctype.h>
+
+Recfmt_t
+recstr(register const char* s, char** e)
+{
+ char* t;
+ int n;
+ long v;
+ int a[6];
+
+ while (*s == ' ' || *s == '\t' || *s == ',')
+ s++;
+ switch (*s)
+ {
+ case 'd':
+ case 'D':
+ if (!*++s)
+ n = '\n';
+ else
+ {
+ if (*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))
+ n = (int)strtol(s, &t, 0);
+ else
+ n = chresc(s, &t);
+ s = (const char*)t;
+ }
+ if (e)
+ *e = (char*)s;
+ return REC_D_TYPE(n);
+ case 'f':
+ case 'F':
+ while (*++s == ' ' || *s == '\t' || *s == ',');
+ /*FALLTHROUGH*/
+ case '+':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = strton(s, &t, NiL, 0);
+ if (n > 0 && t > (char*)s)
+ {
+ if (e)
+ *e = t;
+ return REC_F_TYPE(n);
+ }
+ break;
+ case 'm':
+ case 'M':
+ while (*++s == ' ' || *s == '\t' || *s == ',');
+ for (t = (char*)s; *t && *t != ' ' && *t != '\t' && *t != ','; t++);
+ if ((t - s) == 4)
+ {
+ if (strneq(s, "data", 4))
+ {
+ if (e)
+ *e = t;
+ return REC_M_TYPE(REC_M_data);
+ }
+ else if (strneq(s, "path", 4))
+ {
+ if (e)
+ *e = t;
+ return REC_M_TYPE(REC_M_path);
+ }
+ }
+
+ /*
+ * TBD: look up name in method libraries
+ * and assign an integer index
+ */
+
+ break;
+ case 'u':
+ case 'U':
+ while (*++s == ' ' || *s == '\t' || *s == ',');
+ n = strtol(s, &t, 0);
+ if (n < 0 || n > 15 || *t++ != '.')
+ break;
+ v = strtol(t, &t, 0);
+ if (*t)
+ break;
+ if (e)
+ *e = t;
+ return REC_U_TYPE(n, v);
+ case 'v':
+ case 'V':
+ a[0] = 0;
+ a[1] = 4;
+ a[2] = 0;
+ a[3] = 2;
+ a[4] = 0;
+ a[5] = 1;
+ n = 0;
+ for (;;)
+ {
+ switch (*++s)
+ {
+ case 0:
+ break;
+ case 'm':
+ case 'M':
+ n = 0;
+ continue;
+ case 'h':
+ case 'H':
+ n = 1;
+ continue;
+ case 'o':
+ case 'O':
+ n = 2;
+ continue;
+ case 'z':
+ case 'Z':
+ n = 3;
+ continue;
+ case 'b':
+ case 'B':
+ n = 4;
+ a[n++] = 0;
+ continue;
+ case 'l':
+ case 'L':
+ n = 4;
+ a[n++] = 1;
+ continue;
+ case 'n':
+ case 'N':
+ n = 0;
+ a[5] = 0;
+ continue;
+ case 'i':
+ case 'I':
+ n = 0;
+ a[5] = 1;
+ continue;
+ case ' ':
+ case '\t':
+ case ',':
+ case '-':
+ case '+':
+ continue;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ v = 0;
+ a[n++] = strtol(s, &t, 0);
+ s = (const char*)t - 1;
+ continue;
+ }
+ break;
+ }
+ if (e)
+ *e = (char*)s;
+ if (a[3] > (a[1] - a[2]))
+ a[3] = a[1] - a[2];
+ return REC_V_RECORD(REC_V_TYPE(a[1], a[2], a[3], a[4], a[5]), a[0]);
+ case '%':
+ if (e)
+ *e = (char*)s + 1;
+ return REC_M_TYPE(REC_M_path);
+ case '-':
+ case '?':
+ if (e)
+ *e = (char*)s + 1;
+ return REC_M_TYPE(REC_M_data);
+ }
+ if (e)
+ *e = (char*)s;
+ return REC_N_TYPE();
+}
diff --git a/src/lib/libast/misc/setenviron.c b/src/lib/libast/misc/setenviron.c
new file mode 100644
index 0000000..c67477e
--- /dev/null
+++ b/src/lib/libast/misc/setenviron.c
@@ -0,0 +1,147 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "intercepts.h"
+
+#include <fs3d.h>
+
+/*
+ * put name=value in the environment
+ * pointer to value returned
+ * environ==0 is ok
+ *
+ * setenviron("N=V") add N=V
+ * setenviron("N") delete N
+ * setenviron(0) expect more (pre-fork optimization)
+ *
+ * _ always placed at the top
+ */
+
+#define INCREMENT 16 /* environ increment */
+
+char*
+setenviron(const char* akey)
+{
+#undef setenviron
+ static char** envv; /* recorded environ */
+ static char** next; /* next free slot */
+ static char** last; /* last free slot (0) */
+ static char ok[] = ""; /* delete/optimization ok return*/
+
+ char* key = (char*)akey;
+ register char** v = environ;
+ register char** p = envv;
+ register char* s;
+ register char* t;
+ int n;
+
+ ast.env_serial++;
+ if (intercepts.intercept_setenviron)
+ return (*intercepts.intercept_setenviron)(akey);
+ if (p && !v)
+ {
+ environ = next = p;
+ *++next = 0;
+ }
+ else if (p != v || !v)
+ {
+ if (v)
+ {
+ while (*v++);
+ n = v - environ + INCREMENT;
+ v = environ;
+ }
+ else
+ n = INCREMENT;
+ if (!p || (last - p + 1) < n)
+ {
+ if (!p && fs3d(FS3D_TEST))
+ {
+ /*
+ * kick 3d initialization
+ */
+
+ close(open(".", O_RDONLY));
+ v = environ;
+ }
+ if (!(p = newof(p, char*, n, 0)))
+ return 0;
+ last = p + n - 1;
+ }
+ envv = environ = p;
+ if (v && v[0] && v[0][0] == '_' && v[0][1] == '=')
+ *p++ = *v++;
+ else
+ *p++ = "_=";
+ if (!v)
+ *p = 0;
+ else
+ while (*p = *v++)
+ if (p[0][0] == '_' && p[0][1] == '=')
+ envv[0] = *p;
+ else
+ p++;
+ next = p;
+ p = envv;
+ }
+ else if (next == last)
+ {
+ n = last - v + INCREMENT + 1;
+ if (!(p = newof(p, char*, n, 0)))
+ return 0;
+ last = p + n - 1;
+ next = last - INCREMENT;
+ envv = environ = p;
+ }
+ if (!key)
+ return ok;
+ for (; s = *p; p++)
+ {
+ t = key;
+ do
+ {
+ if (!*t || *t == '=')
+ {
+ if (*s == '=')
+ {
+ if (!*t)
+ {
+ v = p++;
+ while (*v++ = *p++);
+ next--;
+ return ok;
+ }
+ *p = key;
+ return (s = strchr(key, '=')) ? s + 1 : (char*)0;
+ }
+ break;
+ }
+ } while (*t++ == *s++);
+ }
+ if (!(s = strchr(key, '=')))
+ return ok;
+ p = next;
+ *++next = 0;
+ *p = key;
+ return s + 1;
+}
diff --git a/src/lib/libast/misc/sigcrit.c b/src/lib/libast/misc/sigcrit.c
new file mode 100644
index 0000000..243c478
--- /dev/null
+++ b/src/lib/libast/misc/sigcrit.c
@@ -0,0 +1,199 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * signal critical region support
+ */
+
+#include <ast.h>
+#include <sig.h>
+
+static struct
+{
+ int sig;
+ int op;
+}
+signals[] = /* held inside critical region */
+{
+ SIGINT, SIG_REG_EXEC,
+#ifdef SIGPIPE
+ SIGPIPE, SIG_REG_EXEC,
+#endif
+#ifdef SIGQUIT
+ SIGQUIT, SIG_REG_EXEC,
+#endif
+#ifdef SIGHUP
+ SIGHUP, SIG_REG_EXEC,
+#endif
+#if defined(SIGCHLD) && ( !defined(SIGCLD) || SIGCHLD != SIGCLD || _lib_sigprocmask || _lib_sigsetmask )
+ SIGCHLD, SIG_REG_PROC,
+#endif
+#ifdef SIGTSTP
+ SIGTSTP, SIG_REG_TERM,
+#endif
+#ifdef SIGTTIN
+ SIGTTIN, SIG_REG_TERM,
+#endif
+#ifdef SIGTTOU
+ SIGTTOU, SIG_REG_TERM,
+#endif
+};
+
+#ifndef SIG_SETMASK
+#undef _lib_sigprocmask
+#endif
+
+#if !_lib_sigprocmask && !_lib_sigsetmask
+
+static long hold; /* held signal mask */
+
+/*
+ * hold last signal for later delivery
+ */
+
+static void
+interrupt(int sig)
+{
+ signal(sig, interrupt);
+ hold |= sigmask(sig);
+}
+
+#endif
+
+/*
+ * critical signal region handler
+ *
+ * op>0 new region according to SIG_REG_*, return region level
+ * op==0 pop region, return region level
+ * op<0 return non-zero if any signals held in current region
+ *
+ * signals[] held until region popped
+ */
+
+int
+sigcritical(int op)
+{
+ register int i;
+ static int region;
+ static int level;
+#if _lib_sigprocmask
+ static sigset_t mask;
+ sigset_t nmask;
+#else
+#if _lib_sigsetmask
+ static long mask;
+#else
+ static Sig_handler_t handler[elementsof(signals)];
+#endif
+#endif
+
+ if (op > 0)
+ {
+ if (!level++)
+ {
+ region = op;
+ if (op & SIG_REG_SET)
+ level--;
+#if _lib_sigprocmask
+ sigemptyset(&nmask);
+ for (i = 0; i < elementsof(signals); i++)
+ if (op & signals[i].op)
+ sigaddset(&nmask, signals[i].sig);
+ sigprocmask(SIG_BLOCK, &nmask, &mask);
+#else
+#if _lib_sigsetmask
+ mask = 0;
+ for (i = 0; i < elementsof(signals); i++)
+ if (op & signals[i].op)
+ mask |= sigmask(signals[i].sig);
+ mask = sigblock(mask);
+#else
+ hold = 0;
+ for (i = 0; i < elementsof(signals); i++)
+ if ((op & signals[i].op) && (handler[i] = signal(signals[i].sig, interrupt)) == SIG_IGN)
+ {
+ signal(signals[i].sig, handler[i]);
+ hold &= ~sigmask(signals[i].sig);
+ }
+#endif
+#endif
+ }
+ return level;
+ }
+ else if (op < 0)
+ {
+#if _lib_sigprocmask
+ sigpending(&nmask);
+ for (i = 0; i < elementsof(signals); i++)
+ if (region & signals[i].op)
+ {
+ if (sigismember(&nmask, signals[i].sig))
+ return 1;
+ }
+ return 0;
+#else
+#if _lib_sigsetmask
+ /* no way to get pending signals without installing handler */
+ return 0;
+#else
+ return hold != 0;
+#endif
+#endif
+ }
+ else
+ {
+ /*
+ * a vfork() may have intervened so we
+ * allow apparent nesting mismatches
+ */
+
+ if (--level <= 0)
+ {
+ level = 0;
+#if _lib_sigprocmask
+ sigprocmask(SIG_SETMASK, &mask, NiL);
+#else
+#if _lib_sigsetmask
+ sigsetmask(mask);
+#else
+ for (i = 0; i < elementsof(signals); i++)
+ if (region & signals[i].op)
+ signal(signals[i].sig, handler[i]);
+ if (hold)
+ {
+ for (i = 0; i < elementsof(signals); i++)
+ if (region & signals[i].op)
+ {
+ if (hold & sigmask(signals[i].sig))
+ kill(getpid(), signals[i].sig);
+ }
+ pause();
+ }
+#endif
+#endif
+ }
+ return level;
+ }
+}
diff --git a/src/lib/libast/misc/sigdata.c b/src/lib/libast/misc/sigdata.c
new file mode 100644
index 0000000..657aeed
--- /dev/null
+++ b/src/lib/libast/misc/sigdata.c
@@ -0,0 +1,40 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * signal name and text data
+ */
+
+#include <ast.h>
+#include <sig.h>
+
+#include "FEATURE/signal"
+
+Sig_info_t _sig_info_ = { (char**)sig_name, (char**)sig_text, SIG_MAX };
+
+__EXTERN__(Sig_info_t, _sig_info_);
+
+#ifdef NoF
+NoF(sigdata)
+#endif
diff --git a/src/lib/libast/misc/signal.c b/src/lib/libast/misc/signal.c
new file mode 100644
index 0000000..0d5fe9d
--- /dev/null
+++ b/src/lib/libast/misc/signal.c
@@ -0,0 +1,136 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * signal that disables syscall restart on interrupt with clear signal mask
+ * fun==SIG_DFL also unblocks signal
+ */
+
+#if !_UWIN
+
+#undef signal
+#define signal ______signal
+
+#endif
+
+#include <ast.h>
+#include <sig.h>
+
+#if !_UWIN
+
+#undef signal
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#endif
+
+#if defined(SV_ABORT)
+#undef SV_INTERRUPT
+#define SV_INTERRUPT SV_ABORT
+#endif
+
+#if !_std_signal && (_lib_sigaction && defined(SA_NOCLDSTOP) || _lib_sigvec && defined(SV_INTERRUPT))
+
+#if !defined(SA_NOCLDSTOP) || !defined(SA_INTERRUPT) && defined(SV_INTERRUPT)
+#undef SA_INTERRUPT
+#define SA_INTERRUPT SV_INTERRUPT
+#undef sigaction
+#define sigaction sigvec
+#undef sigemptyset
+#define sigemptyset(p) (*(p)=0)
+#undef sa_flags
+#define sa_flags sv_flags
+#undef sa_handler
+#define sa_handler sv_handler
+#undef sa_mask
+#define sa_mask sv_mask
+#endif
+
+extern Sig_handler_t
+signal(int sig, Sig_handler_t fun)
+{
+ struct sigaction na;
+ struct sigaction oa;
+ int unblock;
+#ifdef SIGNO_MASK
+ unsigned int flags;
+#endif
+
+ if (sig < 0)
+ {
+ sig = -sig;
+ unblock = 0;
+ }
+ else
+ unblock = fun == SIG_DFL;
+#ifdef SIGNO_MASK
+ flags = sig & ~SIGNO_MASK;
+ sig &= SIGNO_MASK;
+#endif
+ memzero(&na, sizeof(na));
+ na.sa_handler = fun;
+#if defined(SA_INTERRUPT) || defined(SA_RESTART)
+ switch (sig)
+ {
+#if defined(SIGIO) || defined(SIGTSTP) || defined(SIGTTIN) || defined(SIGTTOU)
+#if defined(SIGIO)
+ case SIGIO:
+#endif
+#if defined(SIGTSTP)
+ case SIGTSTP:
+#endif
+#if defined(SIGTTIN)
+ case SIGTTIN:
+#endif
+#if defined(SIGTTOU)
+ case SIGTTOU:
+#endif
+#if defined(SA_RESTART)
+ na.sa_flags = SA_RESTART;
+#endif
+ break;
+#endif
+ default:
+#if defined(SA_INTERRUPT)
+ na.sa_flags = SA_INTERRUPT;
+#endif
+ break;
+ }
+#endif
+ if (sigaction(sig, &na, &oa))
+ return 0;
+ if (unblock)
+ sigunblock(sig);
+ return oa.sa_handler;
+}
+
+#else
+
+NoN(signal)
+
+#endif
diff --git a/src/lib/libast/misc/stack.c b/src/lib/libast/misc/stack.c
new file mode 100644
index 0000000..fdad3ff
--- /dev/null
+++ b/src/lib/libast/misc/stack.c
@@ -0,0 +1,172 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * pointer stack routines
+ */
+
+static const char id_stack[] = "\n@(#)$Id: stack (AT&T Bell Laboratories) 1984-05-01 $\0\n";
+
+#include <ast.h>
+#include <stack.h>
+
+/*
+ * create a new stack
+ */
+
+STACK
+stackalloc(register int size, void* error)
+{
+ register STACK stack;
+ register struct stackblock *b;
+
+ if (size <= 0) size = 100;
+ if (!(stack = newof(0, struct stacktable, 1, 0))) return(0);
+ if (!(b = newof(0, struct stackblock, 1, 0)))
+ {
+ free(stack);
+ return(0);
+ }
+ if (!(b->stack = newof(0, void*, size, 0)))
+ {
+ free(b);
+ free(stack);
+ return(0);
+ }
+ stack->blocks = b;
+ stack->size = size;
+ stack->error = error;
+ stack->position.block = b;
+ stack->position.index = -1;
+ b->next = 0;
+ b->prev = 0;
+ return(stack);
+}
+
+/*
+ * remove a stack
+ */
+
+void
+stackfree(register STACK stack)
+{
+ register struct stackblock* b;
+ register struct stackblock* p;
+
+ b = stack->blocks;
+ while (p = b)
+ {
+ b = p->next;
+ free(p->stack);
+ free(p);
+ }
+ free(stack);
+}
+
+/*
+ * clear stack
+ */
+
+void
+stackclear(register STACK stack)
+{
+ stack->position.block = stack->blocks;
+ stack->position.index = -1;
+}
+
+/*
+ * get value on top of stack
+ */
+
+void*
+stackget(register STACK stack)
+{
+ if (stack->position.index < 0) return(stack->error);
+ else return(stack->position.block->stack[stack->position.index]);
+}
+
+/*
+ * push value on to stack
+ */
+
+int
+stackpush(register STACK stack, void* value)
+{
+ register struct stackblock *b;
+
+ if (++stack->position.index >= stack->size)
+ {
+ b = stack->position.block;
+ if (b->next) b = b->next;
+ else
+ {
+ if (!(b->next = newof(0, struct stackblock, 1, 0)))
+ return(-1);
+ b = b->next;
+ if (!(b->stack = newof(0, void*, stack->size, 0)))
+ return(-1);
+ b->prev = stack->position.block;
+ b->next = 0;
+ }
+ stack->position.block = b;
+ stack->position.index = 0;
+ }
+ stack->position.block->stack[stack->position.index] = value;
+ return(0);
+}
+
+/*
+ * pop value off stack
+ */
+
+int
+stackpop(register STACK stack)
+{
+ /*
+ * return:
+ *
+ * -1 if stack empty before pop
+ * 0 if stack empty after pop
+ * 1 if stack not empty before & after pop
+ */
+
+ if (stack->position.index < 0) return(-1);
+ else if (--stack->position.index < 0)
+ {
+ if (!stack->position.block->prev) return(0);
+ stack->position.block = stack->position.block->prev;
+ stack->position.index = stack->size - 1;
+ return(1);
+ }
+ else return(1);
+}
+
+/*
+ * set|get stack position
+ */
+
+void
+stacktell(register STACK stack, int set, STACKPOS* position)
+{
+ if (set) stack->position = *position;
+ else *position = stack->position;
+}
diff --git a/src/lib/libast/misc/state.c b/src/lib/libast/misc/state.c
new file mode 100644
index 0000000..0e73be4
--- /dev/null
+++ b/src/lib/libast/misc/state.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+static const char id[] = "\n@(#)$Id: ast (AT&T Research) 2010-01-02 $\0\n";
+
+#include <ast.h>
+
+#undef strcmp
+
+_Ast_info_t _ast_info =
+{
+ "libast", /* id */
+ { 0 },
+ 0,0,0,0,0,
+ strcmp, /* collate */
+ 0,0,
+ 1, /* mb_cur_max */
+ 0,0,0,0,0,0,0,
+ 20100102 /* version */
+};
+
+__EXTERN__(_Ast_info_t, _ast_info);
diff --git a/src/lib/libast/misc/stk.c b/src/lib/libast/misc/stk.c
new file mode 100644
index 0000000..1abc28d
--- /dev/null
+++ b/src/lib/libast/misc/stk.c
@@ -0,0 +1,553 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Routines to implement a stack-like storage library
+ *
+ * A stack consists of a link list of variable size frames
+ * The beginning of each frame is initialized with a frame structure
+ * that contains a pointer to the previous frame and a pointer to the
+ * end of the current frame.
+ *
+ * This is a rewrite of the stk library that uses sfio
+ *
+ * David Korn
+ * AT&T Research
+ * dgk@research.att.com
+ *
+ */
+
+#include <sfio_t.h>
+#include <ast.h>
+#include <align.h>
+#include <stk.h>
+
+/*
+ * A stack is a header and a linked list of frames
+ * The first frame has structure
+ * Sfio_t
+ * Sfdisc_t
+ * struct stk
+ * Frames have structure
+ * struct frame
+ * data
+ */
+
+#define STK_ALIGN ALIGN_BOUND
+#define STK_FSIZE (1024*sizeof(char*))
+#define STK_HDRSIZE (sizeof(Sfio_t)+sizeof(Sfdisc_t))
+
+typedef char* (*_stk_overflow_)(int);
+
+static int stkexcept(Sfio_t*,int,void*,Sfdisc_t*);
+static Sfdisc_t stkdisc = { 0, 0, 0, stkexcept };
+
+Sfio_t _Stak_data = SFNEW((char*)0,0,-1,SF_STATIC|SF_WRITE|SF_STRING,&stkdisc,0);
+
+__EXTERN__(Sfio_t, _Stak_data);
+
+struct frame
+{
+ char *prev; /* address of previous frame */
+ char *end; /* address of end this frame */
+ char **aliases; /* address aliases */
+ int nalias; /* number of aliases */
+};
+
+struct stk
+{
+ _stk_overflow_ stkoverflow; /* called when malloc fails */
+ short stkref; /* reference count; */
+ short stkflags; /* stack attributes */
+ char *stkbase; /* beginning of current stack frame */
+ char *stkend; /* end of current stack frame */
+};
+
+static size_t init; /* 1 when initialized */
+static struct stk *stkcur; /* pointer to current stk */
+static char *stkgrow(Sfio_t*, size_t);
+
+#define stream2stk(stream) ((stream)==stkstd? stkcur:\
+ ((struct stk*)(((char*)(stream))+STK_HDRSIZE)))
+#define stk2stream(sp) ((Sfio_t*)(((char*)(sp))-STK_HDRSIZE))
+#define stkleft(stream) ((stream)->_endb-(stream)->_data)
+
+
+#ifdef STKSTATS
+ static struct
+ {
+ int create;
+ int delete;
+ int install;
+ int alloc;
+ int copy;
+ int puts;
+ int seek;
+ int set;
+ int grow;
+ int addsize;
+ int delsize;
+ int movsize;
+ } _stkstats;
+# define increment(x) (_stkstats.x++)
+# define count(x,n) (_stkstats.x += (n))
+#else
+# define increment(x)
+# define count(x,n)
+#endif /* STKSTATS */
+
+static const char Omsg[] = "malloc failed while growing stack\n";
+
+/*
+ * default overflow exception
+ */
+static char *overflow(int n)
+{
+ NoP(n);
+ write(2,Omsg, sizeof(Omsg)-1);
+ exit(2);
+ /* NOTREACHED */
+ return(0);
+}
+
+/*
+ * initialize stkstd, sfio operations may have already occcured
+ */
+static void stkinit(size_t size)
+{
+ register Sfio_t *sp;
+ init = size;
+ sp = stkopen(0);
+ init = 1;
+ stkinstall(sp,overflow);
+}
+
+static int stkexcept(register Sfio_t *stream, int type, void* val, Sfdisc_t* dp)
+{
+ NoP(dp);
+ NoP(val);
+ switch(type)
+ {
+ case SF_CLOSING:
+ {
+ register struct stk *sp = stream2stk(stream);
+ register char *cp = sp->stkbase;
+ register struct frame *fp;
+ if(--sp->stkref<=0)
+ {
+ increment(delete);
+ if(stream==stkstd)
+ stkset(stream,(char*)0,0);
+ else
+ {
+ while(1)
+ {
+ fp = (struct frame*)cp;
+ if(fp->prev)
+ {
+ cp = fp->prev;
+ free(fp);
+ }
+ else
+ {
+ free(fp);
+ break;
+ }
+ }
+ }
+ }
+ stream->_data = stream->_next = 0;
+ }
+ return(0);
+ case SF_FINAL:
+ free(stream);
+ return(1);
+ case SF_DPOP:
+ return(-1);
+ case SF_WRITE:
+ case SF_SEEK:
+ {
+ long size = sfvalue(stream);
+ if(init)
+ {
+ Sfio_t *old = 0;
+ if(stream!=stkstd)
+ old = stkinstall(stream,NiL);
+ if(!stkgrow(stkstd,size-(stkstd->_endb-stkstd->_data)))
+ return(-1);
+ if(old)
+ stkinstall(old,NiL);
+ }
+ else
+ stkinit(size);
+ }
+ return(1);
+ case SF_NEW:
+ return(-1);
+ }
+ return(0);
+}
+
+/*
+ * create a stack
+ */
+Sfio_t *stkopen(int flags)
+{
+ register size_t bsize;
+ register Sfio_t *stream;
+ register struct stk *sp;
+ register struct frame *fp;
+ register Sfdisc_t *dp;
+ register char *cp;
+ if(!(stream=newof((char*)0,Sfio_t, 1, sizeof(*dp)+sizeof(*sp))))
+ return(0);
+ increment(create);
+ count(addsize,sizeof(*stream)+sizeof(*dp)+sizeof(*sp));
+ dp = (Sfdisc_t*)(stream+1);
+ dp->exceptf = stkexcept;
+ sp = (struct stk*)(dp+1);
+ sp->stkref = 1;
+ sp->stkflags = (flags&STK_SMALL);
+ if(flags&STK_NULL) sp->stkoverflow = 0;
+ else sp->stkoverflow = stkcur?stkcur->stkoverflow:overflow;
+ bsize = init+sizeof(struct frame);
+#ifndef USE_REALLOC
+ if(flags&STK_SMALL)
+ bsize = roundof(bsize,STK_FSIZE/16);
+ else
+#endif /* USE_REALLOC */
+ bsize = roundof(bsize,STK_FSIZE);
+ bsize -= sizeof(struct frame);
+ if(!(fp=newof((char*)0,struct frame, 1,bsize)))
+ {
+ free(stream);
+ return(0);
+ }
+ count(addsize,sizeof(*fp)+bsize);
+ cp = (char*)(fp+1);
+ sp->stkbase = (char*)fp;
+ fp->prev = 0;
+ fp->nalias = 0;
+ fp->aliases = 0;
+ fp->end = sp->stkend = cp+bsize;
+ if(!sfnew(stream,cp,bsize,-1,SF_STRING|SF_WRITE|SF_STATIC|SF_EOF))
+ return((Sfio_t*)0);
+ sfdisc(stream,dp);
+ return(stream);
+}
+
+/*
+ * return a pointer to the current stack
+ * if <stream> is not null, it becomes the new current stack
+ * <oflow> becomes the new overflow function
+ */
+Sfio_t *stkinstall(Sfio_t *stream, _stk_overflow_ oflow)
+{
+ Sfio_t *old;
+ register struct stk *sp;
+ if(!init)
+ {
+ stkinit(1);
+ if(oflow)
+ stkcur->stkoverflow = oflow;
+ return((Sfio_t*)0);
+ }
+ increment(install);
+ old = stkcur?stk2stream(stkcur):0;
+ if(stream)
+ {
+ sp = stream2stk(stream);
+ while(sfstack(stkstd, SF_POPSTACK));
+ if(stream!=stkstd)
+ sfstack(stkstd,stream);
+ stkcur = sp;
+#ifdef USE_REALLOC
+ /*** someday ***/
+#endif /* USE_REALLOC */
+ }
+ else
+ sp = stkcur;
+ if(oflow)
+ sp->stkoverflow = oflow;
+ return(old);
+}
+
+/*
+ * increase the reference count on the given <stack>
+ */
+int stklink(register Sfio_t* stream)
+{
+ register struct stk *sp = stream2stk(stream);
+ return(sp->stkref++);
+}
+
+/*
+ * terminate a stack and free up the space
+ * >0 returned if reference decremented but still > 0
+ * 0 returned on last close
+ * <0 returned on error
+ */
+int stkclose(Sfio_t* stream)
+{
+ register struct stk *sp = stream2stk(stream);
+ if(sp->stkref>1)
+ {
+ sp->stkref--;
+ return(1);
+ }
+ return(sfclose(stream));
+}
+
+/*
+ * returns 1 if <loc> is on this stack
+ */
+int stkon(register Sfio_t * stream, register char* loc)
+{
+ register struct stk *sp = stream2stk(stream);
+ register struct frame *fp;
+ for(fp=(struct frame*)sp->stkbase; fp; fp=(struct frame*)fp->prev)
+ if(loc>=((char*)(fp+1)) && loc< fp->end)
+ return(1);
+ return(0);
+}
+/*
+ * reset the bottom of the current stack back to <loc>
+ * if <loc> is not in this stack, then the stack is reset to the beginning
+ * otherwise, the top of the stack is set to stkbot+<offset>
+ *
+ */
+char *stkset(register Sfio_t * stream, register char* loc, size_t offset)
+{
+ register struct stk *sp = stream2stk(stream);
+ register char *cp;
+ register struct frame *fp;
+ register int frames = 0;
+ int n;
+ if(!init)
+ stkinit(offset+1);
+ increment(set);
+ while(1)
+ {
+ fp = (struct frame*)sp->stkbase;
+ cp = sp->stkbase + roundof(sizeof(struct frame), STK_ALIGN);
+ n = fp->nalias;
+ while(n-->0)
+ {
+ if(loc==fp->aliases[n])
+ {
+ loc = cp;
+ break;
+ }
+ }
+ /* see whether <loc> is in current stack frame */
+ if(loc>=cp && loc<=sp->stkend)
+ {
+ if(frames)
+ sfsetbuf(stream,cp,sp->stkend-cp);
+ stream->_data = (unsigned char*)(cp + roundof(loc-cp,STK_ALIGN));
+ stream->_next = (unsigned char*)loc+offset;
+ goto found;
+ }
+ if(fp->prev)
+ {
+ sp->stkbase = fp->prev;
+ sp->stkend = ((struct frame*)(fp->prev))->end;
+ free((void*)fp);
+ }
+ else
+ break;
+ frames++;
+ }
+ /* set stack back to the beginning */
+ cp = (char*)(fp+1);
+ if(frames)
+ sfsetbuf(stream,cp,sp->stkend-cp);
+ else
+ stream->_data = stream->_next = (unsigned char*)cp;
+found:
+ return((char*)stream->_data);
+}
+
+/*
+ * allocate <n> bytes on the current stack
+ */
+char *stkalloc(register Sfio_t *stream, register size_t n)
+{
+ register unsigned char *old;
+ if(!init)
+ stkinit(n);
+ increment(alloc);
+ n = roundof(n,STK_ALIGN);
+ if(stkleft(stream) <= (int)n && !stkgrow(stream,n))
+ return(0);
+ old = stream->_data;
+ stream->_data = stream->_next = old+n;
+ return((char*)old);
+}
+
+/*
+ * begin a new stack word of at least <n> bytes
+ */
+char *_stkseek(register Sfio_t *stream, register ssize_t n)
+{
+ if(!init)
+ stkinit(n);
+ increment(seek);
+ if(stkleft(stream) <= n && !stkgrow(stream,n))
+ return(0);
+ stream->_next = stream->_data+n;
+ return((char*)stream->_data);
+}
+
+/*
+ * advance the stack to the current top
+ * if extra is non-zero, first add a extra bytes and zero the first
+ */
+char *stkfreeze(register Sfio_t *stream, register size_t extra)
+{
+ register unsigned char *old, *top;
+ if(!init)
+ stkinit(extra);
+ old = stream->_data;
+ top = stream->_next;
+ if(extra)
+ {
+ if(extra > (stream->_endb-stream->_next))
+ {
+ if (!(top = (unsigned char*)stkgrow(stream,extra)))
+ return(0);
+ old = stream->_data;
+ }
+ *top = 0;
+ top += extra;
+ }
+ stream->_next = stream->_data += roundof(top-old,STK_ALIGN);
+ return((char*)old);
+}
+
+/*
+ * copy string <str> onto the stack as a new stack word
+ */
+char *stkcopy(Sfio_t *stream, const char* str)
+{
+ register unsigned char *cp = (unsigned char*)str;
+ register size_t n;
+ register int off=stktell(stream);
+ char buff[40], *tp=buff;
+ if(off)
+ {
+ if(off > sizeof(buff))
+ {
+ if(!(tp = malloc(off)))
+ {
+ struct stk *sp = stream2stk(stream);
+ if(!sp->stkoverflow || !(tp = (*sp->stkoverflow)(off)))
+ return(0);
+ }
+ }
+ memcpy(tp, stream->_data, off);
+ }
+ while(*cp++);
+ n = roundof(cp-(unsigned char*)str,STK_ALIGN);
+ if(!init)
+ stkinit(n);
+ increment(copy);
+ if(stkleft(stream) <= n && !stkgrow(stream,n))
+ cp = 0;
+ else
+ {
+ strcpy((char*)(cp=stream->_data),str);
+ stream->_data = stream->_next = cp+n;
+ if(off)
+ {
+ _stkseek(stream,off);
+ memcpy(stream->_data, tp, off);
+ }
+ }
+ if(tp!=buff)
+ free((void*)tp);
+ return((char*)cp);
+}
+
+/*
+ * add a new stack frame of size >= <n> to the current stack.
+ * if <n> > 0, copy the bytes from stkbot to stktop to the new stack
+ * if <n> is zero, then copy the remainder of the stack frame from stkbot
+ * to the end is copied into the new stack frame
+ */
+
+static char *stkgrow(register Sfio_t *stream, size_t size)
+{
+ register size_t n = size;
+ register struct stk *sp = stream2stk(stream);
+ register struct frame *fp= (struct frame*)sp->stkbase;
+ register char *cp, *dp=0;
+ register size_t m = stktell(stream);
+ char *end=0;
+ int nn=0,add=1;
+ n += (m + sizeof(struct frame)+1);
+ if(sp->stkflags&STK_SMALL)
+#ifndef USE_REALLOC
+ n = roundof(n,STK_FSIZE/16);
+ else
+#endif /* !USE_REALLOC */
+ n = roundof(n,STK_FSIZE);
+ /* see whether current frame can be extended */
+ if(stkptr(stream,0)==sp->stkbase+sizeof(struct frame))
+ {
+ nn = fp->nalias+1;
+ dp=sp->stkbase;
+ sp->stkbase = ((struct frame*)dp)->prev;
+ end = fp->end;
+ }
+ cp = newof(dp, char, n, nn*sizeof(char*));
+ if(!cp && (!sp->stkoverflow || !(cp = (*sp->stkoverflow)(n))))
+ return(0);
+ increment(grow);
+ count(addsize,n - (dp?m:0));
+ if(dp && cp==dp)
+ {
+ nn--;
+ add=0;
+ }
+ fp = (struct frame*)cp;
+ fp->prev = sp->stkbase;
+ sp->stkbase = cp;
+ sp->stkend = fp->end = cp+n;
+ cp = (char*)(fp+1);
+ cp = sp->stkbase + roundof((cp-sp->stkbase),STK_ALIGN);
+ if(fp->nalias=nn)
+ {
+ fp->aliases = (char**)fp->end;
+ if(end)
+ memmove(fp->aliases,end,nn*sizeof(char*));
+ if(add)
+ fp->aliases[nn-1] = dp + roundof(sizeof(struct frame),STK_ALIGN);
+ }
+ if(m && !dp)
+ {
+ memcpy(cp,(char*)stream->_data,m);
+ count(movsize,m);
+ }
+ sfsetbuf(stream,cp,sp->stkend-cp);
+ return((char*)(stream->_next = stream->_data+m));
+}
diff --git a/src/lib/libast/misc/systrace.c b/src/lib/libast/misc/systrace.c
new file mode 100644
index 0000000..a084c29
--- /dev/null
+++ b/src/lib/libast/misc/systrace.c
@@ -0,0 +1,68 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * trace systems calls if possible
+ */
+
+#include <ast.h>
+#include <error.h>
+#include <proc.h>
+#include <debug.h>
+
+void
+systrace(const char* id)
+{
+ register int n;
+ register char* out;
+ char* s;
+ char buf[PATH_MAX];
+ char* av[7];
+ long ov[2];
+
+ static char* trace[] = { "trace", "truss", "strace", "traces" };
+
+ if (!(s = getenv("HOME")))
+ return;
+ if (!id && !(id = (const char*)error_info.id))
+ id = (const char*)trace[0];
+ out = buf;
+ out += sfsprintf(out, sizeof(buf), "%s/.%s/%s", s, trace[0], id);
+ if (access(buf, F_OK))
+ return;
+ av[1] = trace[0];
+ av[2] = "-o";
+ av[3] = buf;
+ av[4] = "-p";
+ av[5] = out + 1;
+ av[6] = 0;
+ ov[0] = PROC_FD_DUP(open("/dev/null", O_WRONLY), 2, PROC_FD_PARENT|PROC_FD_CHILD);
+ ov[1] = 0;
+ sfsprintf(out, &buf[sizeof(buf)] - out, ".%d", getpid());
+ for (n = 0; n < elementsof(trace); n++)
+ if (!procfree(procopen(trace[n], av + 1, NiL, ov, PROC_ARGMOD|PROC_GID|PROC_UID|(n == (elementsof(trace) - 1) ? PROC_CLEANUP : 0))))
+ {
+ sleep(1);
+ break;
+ }
+}
diff --git a/src/lib/libast/misc/translate.c b/src/lib/libast/misc/translate.c
new file mode 100644
index 0000000..0c9fbe3
--- /dev/null
+++ b/src/lib/libast/misc/translate.c
@@ -0,0 +1,437 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * AT&T Research and SCO
+ * ast l10n message translation
+ */
+
+#include "lclib.h"
+
+#include <cdt.h>
+#include <error.h>
+#include <mc.h>
+#include <nl_types.h>
+
+#ifndef DEBUG_trace
+#define DEBUG_trace 0
+#endif
+
+#define NOCAT ((nl_catd)-1)
+#define GAP 100
+
+typedef struct
+{
+ Dtlink_t link; /* dictionary link */
+ Dt_t* messages; /* message dictionary handle */
+ nl_catd cat; /* message catalog handle */
+ int debug; /* special debug locale */
+ const char* locale; /* message catalog locale */
+ const char* nlspath; /* message catalog NLSPATH */
+ char name[1]; /* catalog name */
+} Catalog_t;
+
+typedef struct
+{
+ Dtlink_t link; /* dictionary link */
+ Catalog_t* cat; /* current catalog pointer */
+ int set; /* set number */
+ int seq; /* sequence number */
+ char text[1]; /* message text */
+} Message_t;
+
+typedef struct
+{
+ Sfio_t* sp; /* temp string stream */
+ int off; /* string base offset */
+} Temp_t;
+
+typedef struct
+{
+ Dtdisc_t message_disc; /* message dict discipline */
+ Dtdisc_t catalog_disc; /* catalog dict discipline */
+ Dt_t* catalogs; /* catalog dictionary handle */
+ Sfio_t* tmp; /* temporary string stream */
+ int error; /* no dictionaries! */
+ char null[1]; /* null string */
+} State_t;
+
+static State_t state =
+{
+ { offsetof(Message_t, text), 0, 0 },
+ { offsetof(Catalog_t, name), 0, 0 },
+};
+
+static int
+tempget(Sfio_t* sp)
+{
+ if (sfstrtell(sp) > sfstrsize(sp) / 2)
+ sfstrseek(sp, 0, SEEK_SET);
+ return sfstrtell(sp);
+}
+
+static char*
+tempuse(Sfio_t* sp, int off)
+{
+ sfputc(sp, 0);
+ return sfstrbase(sp) + off;
+}
+
+/*
+ * add msg to dict
+ */
+
+static int
+entry(Dt_t* dict, int set, int seq, const char* msg)
+{
+ Message_t* mp;
+
+ if (!(mp = newof(0, Message_t, 1, strlen(msg))))
+ return 0;
+ strcpy(mp->text, msg);
+ mp->set = set;
+ mp->seq = seq;
+ if (!dtinsert(dict, mp))
+ {
+ free(mp);
+ return 0;
+ }
+#if DEBUG_trace > 1
+sfprintf(sfstderr, "AHA#%d:%s set %d seq %d msg `%s'\n", __LINE__, __FILE__, set, seq, msg);
+#endif
+ return 1;
+}
+
+/*
+ * find catalog in locale and return catopen() descriptor
+ */
+
+static nl_catd
+find(const char* locale, const char* catalog)
+{
+ char* o;
+ nl_catd d;
+ char path[PATH_MAX];
+
+ if (!mcfind(locale, catalog, LC_MESSAGES, 0, path, sizeof(path)) || (d = catopen(path, NL_CAT_LOCALE)) == NOCAT)
+ {
+ if (locale == (const char*)lc_categories[AST_LC_MESSAGES].prev)
+ o = 0;
+ else if (o = setlocale(LC_MESSAGES, NiL))
+ {
+ ast.locale.set |= AST_LC_internal;
+ setlocale(LC_MESSAGES, locale);
+ }
+ d = catopen(catalog, NL_CAT_LOCALE);
+ if (o)
+ {
+ setlocale(LC_MESSAGES, o);
+ ast.locale.set &= ~AST_LC_internal;
+ }
+ }
+ return d;
+}
+
+/*
+ * initialize the catalog s by loading in the default locale messages
+ */
+
+static Catalog_t*
+init(register char* s)
+{
+ register Catalog_t* cp;
+ register char* u;
+ register int n;
+ register int m;
+ register int set;
+ nl_catd d;
+
+ static const int sets[] = { AST_MESSAGE_SET, 1 };
+
+ /*
+ * insert into the catalog dictionary
+ */
+
+ if (!(cp = newof(0, Catalog_t, 1, strlen(s))))
+ return 0;
+ strcpy(cp->name, s);
+ if (!dtinsert(state.catalogs, cp))
+ {
+ free(cp);
+ return 0;
+ }
+ cp->cat = NOCAT;
+
+ /*
+ * locate the default locale catalog
+ */
+
+ if ((d = find("C", s)) != NOCAT)
+ {
+ /*
+ * load the default locale messages
+ * this assumes one mesage set for ast (AST_MESSAGE_SET or fallback to 1)
+ * different packages can share the same message catalog
+ * name by using different message set numbers
+ * see <mc.h> mcindex()
+ *
+ * this method requires a scan of each catalog, and the
+ * catalogs do not advertise the max message number, so
+ * we assume there are no messages after a gap of GAP
+ * missing messages
+ */
+
+ if (cp->messages = dtopen(&state.message_disc, Dtset))
+ {
+ n = m = 0;
+ for (;;)
+ {
+ n++;
+ if (((s = catgets(d, set = AST_MESSAGE_SET, n, state.null)) && *s || (s = catgets(d, set = 1, n, state.null)) && *s) && entry(cp->messages, set, n, s))
+ m = n;
+ else if ((n - m) > GAP)
+ break;
+ }
+ if (!m)
+ {
+ dtclose(cp->messages);
+ cp->messages = 0;
+ }
+ }
+ catclose(d);
+ }
+ return cp;
+}
+
+/*
+ * return the C locale message pointer for msg in cat
+ * cat may be a : separated list of candidate names
+ */
+
+static Message_t*
+match(const char* cat, const char* msg)
+{
+ register char* s;
+ register char* t;
+ Catalog_t* cp;
+ Message_t* mp;
+ size_t n;
+
+ char buf[1024];
+
+ s = (char*)cat;
+ for (;;)
+ {
+ if (t = strchr(s, ':'))
+ {
+ if (s == (char*)cat)
+ {
+ if ((n = strlen(s)) >= sizeof(buf))
+ n = sizeof(buf) - 1;
+ s = (char*)memcpy(buf, s, n);
+ s[n] = 0;
+ t = strchr(s, ':');
+ }
+ *t = 0;
+ }
+ if (*s && ((cp = (Catalog_t*)dtmatch(state.catalogs, s)) || (cp = init(s))) && cp->messages && (mp = (Message_t*)dtmatch(cp->messages, msg)))
+ {
+ mp->cat = cp;
+ return mp;
+ }
+ if (!t)
+ break;
+ s = t + 1;
+ }
+ return 0;
+}
+
+/*
+ * translate() is called with four arguments:
+ *
+ * loc the LC_MESSAGES locale name
+ * cmd the calling command name
+ * cat the catalog name, possibly a : separated list
+ * "libFOO" FOO library messages
+ * "libshell" ksh command messages
+ * "SCRIPT" script SCRIPT application messages
+ * msg message text to be translated
+ *
+ * the translated message text is returned on success
+ * otherwise the original msg is returned
+ *
+ * The first time translate() is called (for a non-C locale)
+ * it creates the state.catalogs dictionary. A dictionary entry
+ * (Catalog_t) is made each time translate() is called with a new
+ * cmd:cat argument.
+ *
+ * The X/Open interface catgets() is used to obtain a translated
+ * message. Its arguments include the message catalog name
+ * and the set/sequence numbers within the catalog. An additional
+ * dictionary, with entries of type Message_t, is needed for
+ * mapping untranslated message strings to the set/sequence numbers
+ * needed by catgets(). A separate Message_t dictionary is maintained
+ * for each Catalog_t.
+ */
+
+char*
+translate(const char* loc, const char* cmd, const char* cat, const char* msg)
+{
+ register char* r;
+ char* t;
+ int p;
+ int oerrno;
+ Catalog_t* cp;
+ Message_t* mp;
+
+ static uint32_t serial;
+ static char* nlspath;
+
+ oerrno = errno;
+ r = (char*)msg;
+
+ /*
+ * quick out
+ */
+
+ if (!cmd && !cat)
+ goto done;
+ if (cmd && (t = strrchr(cmd, '/')))
+ cmd = (const char*)(t + 1);
+
+ /*
+ * initialize the catalogs dictionary
+ */
+
+ if (!state.catalogs)
+ {
+ if (state.error)
+ goto done;
+ if (!(state.tmp = sfstropen()))
+ {
+ state.error = 1;
+ goto done;
+ }
+ if (!(state.catalogs = dtopen(&state.catalog_disc, Dtset)))
+ {
+ sfclose(state.tmp);
+ state.error = 1;
+ goto done;
+ }
+ }
+
+ /*
+ * get the message
+ * or do we have to spell it out for you
+ */
+
+ if ((!cmd || !(mp = match(cmd, msg))) &&
+ (!cat || !(mp = match(cat, msg))) &&
+ (!error_info.catalog || !(mp = match(error_info.catalog, msg))) &&
+ (!ast.id || !(mp = match(ast.id, msg))) ||
+ !(cp = mp->cat))
+ {
+#if DEBUG_trace > 1
+sfprintf(sfstderr, "AHA#%d:%s cmd %s cat %s:%s id %s msg `%s'\n", __LINE__, __FILE__, cmd, cat, error_info.catalog, ast.id, msg);
+#endif
+ cp = 0;
+ goto done;
+ }
+
+ /*
+ * adjust for the current locale
+ */
+
+#if DEBUG_trace
+sfprintf(sfstderr, "AHA#%d:%s cp->locale `%s' %p loc `%s' %p\n", __LINE__, __FILE__, cp->locale, cp->locale, loc, loc);
+#endif
+ if (serial != ast.env_serial)
+ {
+ serial = ast.env_serial;
+ nlspath = getenv("NLSPATH");
+ }
+ if (cp->locale != loc || cp->nlspath != nlspath)
+ {
+ cp->locale = loc;
+ cp->nlspath = nlspath;
+ if (cp->cat != NOCAT)
+ catclose(cp->cat);
+ if ((cp->cat = find(cp->locale, cp->name)) == NOCAT)
+ cp->debug = streq(cp->locale, "debug");
+ else
+ cp->debug = 0;
+#if DEBUG_trace
+sfprintf(sfstderr, "AHA#%d:%s cp->cat %p cp->debug %d NOCAT %p\n", __LINE__, __FILE__, cp->cat, cp->debug, NOCAT);
+#endif
+ }
+ if (cp->cat == NOCAT)
+ {
+ if (cp->debug)
+ {
+ p = tempget(state.tmp);
+ sfprintf(state.tmp, "(%s,%d,%d)", cp->name, mp->set, mp->seq);
+ r = tempuse(state.tmp, p);
+ }
+ else if (ast.locale.set & AST_LC_debug)
+ {
+ p = tempget(state.tmp);
+ sfprintf(state.tmp, "(%s,%d,%d)%s", cp->name, mp->set, mp->seq, r);
+ r = tempuse(state.tmp, p);
+ }
+ }
+ else
+ {
+ /*
+ * get the translated message
+ */
+
+ r = catgets(cp->cat, mp->set, mp->seq, msg);
+ if (r != (char*)msg)
+ {
+ if (streq(r, (char*)msg))
+ r = (char*)msg;
+ else if (strcmp(fmtfmt(r), fmtfmt(msg)))
+ {
+ sfprintf(sfstderr, "locale %s catalog %s message %d.%d \"%s\" does not match \"%s\"\n", cp->locale, cp->name, mp->set, mp->seq, r, msg);
+ r = (char*)msg;
+ }
+ }
+ if (ast.locale.set & AST_LC_debug)
+ {
+ p = tempget(state.tmp);
+ sfprintf(state.tmp, "(%s,%d,%d)%s", cp->name, mp->set, mp->seq, r);
+ r = tempuse(state.tmp, p);
+ }
+ }
+ if (ast.locale.set & AST_LC_translate)
+ sfprintf(sfstderr, "translate locale=%s catalog=%s set=%d seq=%d \"%s\" => \"%s\"\n", cp->locale, cp->name, mp->set, mp->seq, msg, r == (char*)msg ? "NOPE" : r);
+ done:
+ if (r == (char*)msg && (!cp && streq(loc, "debug") || cp && cp->debug))
+ {
+ p = tempget(state.tmp);
+ sfprintf(state.tmp, "(%s,%s,%s,%s)", loc, cmd, cat, r);
+ r = tempuse(state.tmp, p);
+ }
+ errno = oerrno;
+ return r;
+}
diff --git a/src/lib/libast/misc/univdata.c b/src/lib/libast/misc/univdata.c
new file mode 100644
index 0000000..0cc04df
--- /dev/null
+++ b/src/lib/libast/misc/univdata.c
@@ -0,0 +1,58 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * universe common data
+ */
+
+#include "univlib.h"
+
+#ifndef UNIV_MAX
+
+char univ_env[] = "__UNIVERSE__";
+
+#else
+
+#ifndef NUMUNIV
+
+#if !_lib_universe
+#undef U_GET
+#endif
+
+#ifdef U_GET
+char* univ_name[] = { "ucb", "att" };
+#else
+char* univ_name[] = { "att", "ucb" };
+#endif
+
+int univ_max = sizeof(univ_name) / sizeof(univ_name[0]);
+
+#endif
+
+char univ_cond[] = "$(UNIVERSE)";
+
+int univ_size = sizeof(univ_cond) - 1;
+
+#endif
diff --git a/src/lib/libast/misc/univlib.h b/src/lib/libast/misc/univlib.h
new file mode 100644
index 0000000..ba319c5
--- /dev/null
+++ b/src/lib/libast/misc/univlib.h
@@ -0,0 +1,93 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * universe support
+ *
+ * symbolic link external representation has trailing '\0' and $(...) style
+ * conditionals where $(...) corresponds to a kernel object (i.e., probably
+ * not environ)
+ *
+ * universe symlink conditionals use $(UNIVERSE)
+ */
+
+#ifndef _UNIVLIB_H
+#define _UNIVLIB_H
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide getuniverse readlink setuniverse symlink universe
+#else
+#define getuniverse ______getuniverse
+#define readlink ______readlink
+#define setuniverse ______setuniverse
+#define symlink ______symlink
+#define universe ______universe
+#endif
+
+#include <ast.h>
+#include <ls.h>
+#include <errno.h>
+
+#define UNIV_SIZE 9
+
+#if _cmd_universe && _sys_universe
+#include <sys/universe.h>
+#endif
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide getuniverse readlink setuniverse symlink universe
+#else
+#undef getuniverse
+#undef readlink
+#undef setuniverse
+#undef symlink
+#undef universe
+#endif
+
+#if _cmd_universe
+#ifdef NUMUNIV
+#define UNIV_MAX NUMUNIV
+#else
+#define UNIV_MAX univ_max
+extern char* univ_name[];
+extern int univ_max;
+#endif
+
+extern char univ_cond[];
+extern int univ_size;
+
+#else
+
+extern char univ_env[];
+
+#endif
+
+extern int getuniverse(char*);
+extern int readlink(const char*, char*, int);
+extern int setuniverse(int);
+extern int symlink(const char*, const char*);
+extern int universe(int);
+
+#endif
diff --git a/src/lib/libast/obsolete/spawn.c b/src/lib/libast/obsolete/spawn.c
new file mode 100644
index 0000000..282ec3a
--- /dev/null
+++ b/src/lib/libast/obsolete/spawn.c
@@ -0,0 +1,152 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * OBSOLETE 20030321 -- use spawnveg()
+ */
+
+#include <ast_lib.h>
+
+#if !_lib_spawnve
+#define spawnve ______spawnve
+#endif
+#if !_lib_spawnvpe
+#define spawnvpe ______spawnvpe
+#endif
+#if !_lib_spawnvp
+#define spawnvp ______spawnvp
+#endif
+#if !_lib_spawnlp
+#define spawnlp ______spawnlp
+#endif
+
+#include <ast.h>
+#include <error.h>
+
+#if !_lib_spawnve
+#undef spawnve
+#endif
+#if !_lib_spawnvpe
+#undef spawnvpe
+#endif
+#if !_lib_spawnvp
+#undef spawnvp
+#endif
+#if !_lib_spawnlp
+#undef spawnlp
+#endif
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#if _lib_spawnve
+
+NoN(spawnve)
+
+#else
+
+extern pid_t
+spawnve(const char* cmd, char* const argv[], char* const envv[])
+{
+ return spawnveg(cmd, argv, envv, 0);
+}
+
+#endif
+
+#if _lib_spawnvpe
+
+NoN(spawnvpe)
+
+#else
+
+extern pid_t
+spawnvpe(const char* name, char* const argv[], char* const envv[])
+{
+ register const char* path = name;
+ pid_t pid;
+ char buffer[PATH_MAX];
+
+ if (*path != '/')
+ path = pathpath(name, NULL, PATH_REGULAR|PATH_EXECUTE, buffer, sizeof(buffer));
+ if ((pid = spawnve(path, argv, envv)) >= 0)
+ return pid;
+ if (errno == ENOEXEC)
+ {
+ register char** newargv;
+ register char** ov;
+ register char** nv;
+
+ for (ov = (char**)argv; *ov++;);
+ if (newargv = newof(0, char*, ov + 1 - (char**)argv, 0))
+ {
+ nv = newargv;
+ *nv++ = "sh";
+ *nv++ = (char*)path;
+ ov = (char**)argv;
+ while (*nv++ = *++ov);
+ path = pathshell();
+ pid = spawnve(path, newargv, environ);
+ free(newargv);
+ }
+ else
+ errno = ENOMEM;
+ }
+ return pid;
+}
+
+#endif
+
+#if _lib_spawnvp
+
+NoN(spawnvp)
+
+#else
+
+extern pid_t
+spawnvp(const char* name, char* const argv[])
+{
+ return spawnvpe(name, argv, environ);
+}
+
+#endif
+
+#if _lib_spawnlp
+
+NoN(spawnlp)
+
+#else
+
+extern pid_t
+spawnlp(const char* name, const char* arg, ...)
+{
+ va_list ap;
+ pid_t pid;
+
+ va_start(ap, arg);
+ pid = spawnvp(name, (char* const*)&arg);
+ va_end(ap);
+ return pid;
+}
+
+#endif
diff --git a/src/lib/libast/path/pathaccess.c b/src/lib/libast/path/pathaccess.c
new file mode 100644
index 0000000..7bbec12
--- /dev/null
+++ b/src/lib/libast/path/pathaccess.c
@@ -0,0 +1,69 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * return path to file a/b with access mode using : separated dirs
+ * both a and b may be 0
+ * if a==".." then relative paths in dirs are ignored
+ * if (mode&PATH_REGULAR) then path must not be a directory
+ * if (mode&PATH_ABSOLUTE) then path must be rooted
+ * path returned in path buffer
+ */
+
+#define _AST_API_H 1
+
+#include <ast.h>
+
+char*
+pathaccess(char* path, const char* dirs, const char* a, const char* b, int mode)
+{
+ return pathaccess_20100601(dirs, a, b, mode, path, PATH_MAX);
+}
+
+#undef _AST_API_H
+
+#include <ast_api.h>
+
+char*
+pathaccess_20100601(register const char* dirs, const char* a, const char* b, register int mode, register char* path, size_t size)
+{
+ int sib = a && a[0] == '.' && a[1] == '.' && a[2] == 0;
+ int sep = ':';
+ char cwd[PATH_MAX];
+
+ do
+ {
+ dirs = pathcat(dirs, sep, a, b, path, size);
+ pathcanon(path, size, 0);
+ if ((!sib || *path == '/') && pathexists(path, mode))
+ {
+ if (*path == '/' || !(mode & PATH_ABSOLUTE))
+ return path;
+ dirs = getcwd(cwd, sizeof(cwd));
+ sep = 0;
+ }
+ } while (dirs);
+ return 0;
+}
diff --git a/src/lib/libast/path/pathbin.c b/src/lib/libast/path/pathbin.c
new file mode 100644
index 0000000..cc9cdfa
--- /dev/null
+++ b/src/lib/libast/path/pathbin.c
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * return current PATH
+ */
+
+#include <ast.h>
+
+char*
+pathbin(void)
+{
+ register char* bin;
+
+ static char* val;
+
+ if ((!(bin = getenv("PATH")) || !*bin) && !(bin = val))
+ {
+ if (!*(bin = astconf("PATH", NiL, NiL)) || !(bin = strdup(bin)))
+ bin = "/bin:/usr/bin:/usr/local/bin";
+ val = bin;
+ }
+ return bin;
+}
diff --git a/src/lib/libast/path/pathcanon.c b/src/lib/libast/path/pathcanon.c
new file mode 100644
index 0000000..8d3cfa6
--- /dev/null
+++ b/src/lib/libast/path/pathcanon.c
@@ -0,0 +1,222 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * in-place path name canonicalization -- preserves the logical view
+ * pointer to trailing 0 in path returned
+ *
+ * remove redundant .'s and /'s
+ * move ..'s to the front
+ * /.. preserved (for pdu and newcastle hacks)
+ * FS_3D handles ...
+ * if (flags&PATH_PHYSICAL) then symlinks resolved at each component
+ * if (flags&PATH_DOTDOT) then each .. checked for access
+ * if (flags&PATH_EXISTS) then path must exist at each component
+ * if (flags&PATH_VERIFIED(n)) then first n chars of path exist
+ *
+ * longer pathname possible if (flags&PATH_PHYSICAL) or FS_3D ... involved
+ * 0 returned on error and if (flags&(PATH_DOTDOT|PATH_EXISTS)) then path
+ * will contain the components following the failure point
+ */
+
+#define _AST_API_H 1
+
+#include <ast.h>
+#include <ls.h>
+#include <fs3d.h>
+#include <error.h>
+
+char*
+pathcanon(char* path, int flags)
+{
+ return pathcanon_20100601(path, PATH_MAX, flags);
+}
+
+#undef _AST_API_H
+
+#include <ast_api.h>
+
+char*
+pathcanon_20100601(char* path, size_t size, int flags)
+{
+ register char* p;
+ register char* r;
+ register char* s;
+ register char* t;
+ register int dots;
+ char* phys;
+ char* v;
+ int loop;
+ int oerrno;
+#if defined(FS_3D)
+ long visits = 0;
+#endif
+
+ oerrno = errno;
+ dots = loop = 0;
+ phys = path;
+ v = path + ((flags >> 5) & 01777);
+ if (!size)
+ size = strlen(path) + 1;
+ if (*path == '/')
+ {
+ if (*(path + 1) == '/' && *astconf("PATH_LEADING_SLASHES", NiL, NiL) == '1')
+ do path++; while (*path == '/' && *(path + 1) == '/');
+ if (!*(path + 1))
+ return path + 1;
+ }
+ p = r = s = t = path;
+ for (;;)
+ switch (*t++ = *s++)
+ {
+ case '.':
+ dots++;
+ break;
+ case 0:
+ s--;
+ /*FALLTHROUGH*/
+ case '/':
+ while (*s == '/') s++;
+ switch (dots)
+ {
+ case 1:
+ t -= 2;
+ break;
+ case 2:
+ if ((flags & (PATH_DOTDOT|PATH_EXISTS)) == PATH_DOTDOT && (t - 2) >= v)
+ {
+ struct stat st;
+
+ *(t - 2) = 0;
+ if (stat(phys, &st))
+ {
+ strcpy(path, s);
+ return 0;
+ }
+ *(t - 2) = '.';
+ }
+#if PRESERVE_TRAILING_SLASH
+ if (t - 5 < r) r = t;
+#else
+ if (t - 5 < r)
+ {
+ if (t - 4 == r) t = r + 1;
+ else r = t;
+ }
+#endif
+ else for (t -= 5; t > r && *(t - 1) != '/'; t--);
+ break;
+ case 3:
+#if defined(FS_3D)
+ {
+ char* x;
+ char* o;
+ int c;
+
+ o = t;
+ if ((t -= 5) <= path) t = path + 1;
+ c = *t;
+ *t = 0;
+ if (x = pathnext(phys, s - (*s != 0), &visits))
+ {
+ r = path;
+ if (t == r + 1) x = r;
+ v = s = t = x;
+ }
+ else
+ {
+ *t = c;
+ t = o;
+ }
+ }
+#else
+ r = t;
+#endif
+ break;
+ default:
+ if ((flags & PATH_PHYSICAL) && loop < 32 && (t - 1) > path)
+ {
+ int c;
+ char buf[PATH_MAX];
+
+ c = *(t - 1);
+ *(t - 1) = 0;
+ dots = pathgetlink(phys, buf, sizeof(buf));
+ *(t - 1) = c;
+ if (dots > 0)
+ {
+ loop++;
+ strcpy(buf + dots, s - (*s != 0));
+ if (*buf == '/') p = r = path;
+ v = s = t = p;
+ strcpy(p, buf);
+ }
+ else if (dots < 0 && errno == ENOENT)
+ {
+ if (flags & PATH_EXISTS)
+ {
+ strcpy(path, s);
+ return 0;
+ }
+ flags &= ~(PATH_PHYSICAL|PATH_DOTDOT);
+ }
+ dots = 4;
+ }
+ break;
+ }
+ if (dots >= 4 && (flags & PATH_EXISTS) && (t - 1) >= v && (t > path + 1 || t > path && *(t - 1) && *(t - 1) != '/'))
+ {
+ struct stat st;
+
+ *(t - 1) = 0;
+ if (stat(phys, &st))
+ {
+ strcpy(path, s);
+ return 0;
+ }
+ v = t;
+ if (*s) *(t - 1) = '/';
+ }
+ if (!*s)
+ {
+ if (t > path && !*(t - 1)) t--;
+ if (t == path) *t++ = '.';
+#if DONT_PRESERVE_TRAILING_SLASH
+ else if (t > path + 1 && *(t - 1) == '/') t--;
+#else
+ else if ((s <= path || *(s - 1) != '/') && t > path + 1 && *(t - 1) == '/') t--;
+#endif
+ *t = 0;
+ errno = oerrno;
+ return t;
+ }
+ dots = 0;
+ p = t;
+ break;
+ default:
+ dots = 4;
+ break;
+ }
+}
diff --git a/src/lib/libast/path/pathcat.c b/src/lib/libast/path/pathcat.c
new file mode 100644
index 0000000..2fa9cde
--- /dev/null
+++ b/src/lib/libast/path/pathcat.c
@@ -0,0 +1,98 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * single dir support for pathaccess()
+ */
+
+#define _AST_API_H 1
+
+#include <ast.h>
+
+/*
+ * building 3d flirts with the dark side
+ */
+
+#if _BLD_3d
+
+#undef pathcat
+#define pathcat_20100601 _3d_pathcat
+
+#else
+
+char*
+pathcat(char* path, const char* dirs, int sep, const char* a, const char* b)
+{
+ return pathcat_20100601(dirs, sep, a, b, path, PATH_MAX);
+}
+
+#endif
+
+#undef _AST_API
+
+#include <ast_api.h>
+
+char*
+pathcat_20100601(register const char* dirs, int sep, const char* a, register const char* b, char* path, size_t size)
+{
+ register char* s;
+ register char* e;
+
+ s = path;
+ e = path + size;
+ while (*dirs && *dirs != sep)
+ {
+ if (s >= e)
+ return 0;
+ *s++ = *dirs++;
+ }
+ if (s != path)
+ {
+ if (s >= e)
+ return 0;
+ *s++ = '/';
+ }
+ if (a)
+ {
+ while (*s = *a++)
+ if (++s >= e)
+ return 0;
+ if (b)
+ {
+ if (s >= e)
+ return 0;
+ *s++ = '/';
+ }
+ }
+ else if (!b)
+ b = ".";
+ if (b)
+ do
+ {
+ if (s >= e)
+ return 0;
+ } while (*s++ = *b++);
+ return *dirs ? (char*)++dirs : 0;
+}
diff --git a/src/lib/libast/path/pathcd.c b/src/lib/libast/path/pathcd.c
new file mode 100644
index 0000000..340a115
--- /dev/null
+++ b/src/lib/libast/path/pathcd.c
@@ -0,0 +1,142 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * K. P. Vo
+ * G. S. Fowler
+ * AT&T Research
+ */
+
+#include <ast.h>
+#include <error.h>
+#include <stk.h>
+
+#if DEBUG
+
+#undef PATH_MAX
+
+#define PATH_MAX 16
+
+static int
+vchdir(const char* path)
+{
+ int n;
+
+ if (strlen(path) >= PATH_MAX)
+ {
+ errno = ENAMETOOLONG;
+ n = -1;
+ }
+ else n = chdir(path);
+ return n;
+}
+
+#define chdir(p) vchdir(p)
+
+#endif
+
+/*
+ * set the current directory to path
+ * if path is long and home!=0 then pathcd(home,0)
+ * is called on intermediate chdir errors
+ */
+
+int
+pathcd(const char* path, const char* home)
+{
+ register char* p = (char*)path;
+ register char* s;
+ register int n;
+ int i;
+ int r;
+
+ r = 0;
+ for (;;)
+ {
+ /*
+ * this should work 99% of the time
+ */
+
+ if (!chdir(p))
+ return r;
+
+ /*
+ * chdir failed
+ */
+
+ if ((n = strlen(p)) < PATH_MAX)
+ return -1;
+#ifdef ENAMETOOLONG
+ if (errno != ENAMETOOLONG)
+ return -1;
+#endif
+
+ /*
+ * path is too long -- copy so it can be modified in place
+ */
+
+ i = stktell(stkstd);
+ sfputr(stkstd, p, 0);
+ stkseek(stkstd, i);
+ p = stkptr(stkstd, i);
+ for (;;)
+ {
+ /*
+ * get a short prefix component
+ */
+
+ s = p + PATH_MAX;
+ while (--s >= p && *s != '/');
+ if (s <= p)
+ break;
+
+ /*
+ * chdir to the prefix
+ */
+
+ *s++ = 0;
+ if (chdir(p))
+ break;
+
+ /*
+ * do the remainder
+ */
+
+ if ((n -= s - p) < PATH_MAX)
+ {
+ if (chdir(s))
+ break;
+ return r;
+ }
+ p = s;
+ }
+
+ /*
+ * try to recover back to home
+ */
+
+ if (!(p = (char*)home))
+ return -1;
+ home = 0;
+ r = -1;
+ }
+}
diff --git a/src/lib/libast/path/pathcheck.c b/src/lib/libast/path/pathcheck.c
new file mode 100644
index 0000000..4ff79f6
--- /dev/null
+++ b/src/lib/libast/path/pathcheck.c
@@ -0,0 +1,91 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * check if package+tool is ok to run
+ * a no-op here except for PARANOID packages
+ * this allows PARANOID_COMPANY to post PARANOID binaries to the www
+ *
+ * warn that the user should pay up if
+ *
+ * (1) the tool matches PARANOID
+ * (2) $_ is more than 90 days old
+ * (3) running on an PARANOID_PAY machine
+ * (4) (1)-(3) have not been defeated
+ *
+ * hows that
+ */
+
+#define PARANOID_TOOLS PARANOID
+#define PARANOID_COMPANY "Lucent Technologies"
+#define PARANOID_MAIL "stc@lucent.com"
+#define PARANOID_PAY "135.*&!(135.104.*)"
+#define PARANOID_FREE "(192|224).*"
+
+#include <ast.h>
+#include <ls.h>
+#include <error.h>
+#include <times.h>
+#include <ctype.h>
+
+int
+pathcheck(const char* package, const char* tool, Pathcheck_t* pc)
+{
+#ifdef PARANOID
+ register char* s;
+ struct stat st;
+
+ if (strmatch(tool, PARANOID) && environ && (s = *environ) && *s++ == '_' && *s++ == '=' && !stat(s, &st))
+ {
+ unsigned long n;
+ unsigned long o;
+ Sfio_t* sp;
+
+ n = time(NiL);
+ o = st.st_ctime;
+ if (n > o && (n - o) > (unsigned long)(60 * 60 * 24 * 90) && (sp = sfopen(NiL, "/etc/hosts", "r")))
+ {
+ /*
+ * this part is infallible
+ */
+
+ n = 0;
+ o = 0;
+ while (n++ < 64 && (s = sfgetr(sp, '\n', 0)))
+ if (strmatch(s, PARANOID_PAY))
+ {
+ error(1, "licensed for external use -- %s employees should contact %s for the internal license", PARANOID_COMPANY, PARANOID_MAIL);
+ break;
+ }
+ else if (*s != '#' && !isspace(*s) && !strneq(s, "127.", 4) && !strmatch(s, PARANOID_FREE) && o++ > 4)
+ break;
+ sfclose(sp);
+ }
+ }
+#else
+ NoP(tool);
+#endif
+ NoP(package);
+ if (pc) memzero(pc, sizeof(*pc));
+ return(0);
+}
diff --git a/src/lib/libast/path/pathexists.c b/src/lib/libast/path/pathexists.c
new file mode 100644
index 0000000..90b4ae7
--- /dev/null
+++ b/src/lib/libast/path/pathexists.c
@@ -0,0 +1,134 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return 1 if path exisis
+ * maintains a cache to minimize stat(2) calls
+ * path is modified in-place but restored on return
+ * path components checked in pairs to cut stat()'s
+ * in half by checking ENOTDIR vs. ENOENT
+ * case ignorance infection unavoidable here
+ */
+
+#include "lclib.h"
+
+#include <ls.h>
+#include <error.h>
+
+typedef struct Tree_s
+{
+ struct Tree_s* next;
+ struct Tree_s* tree;
+ int mode;
+ char name[1];
+} Tree_t;
+
+int
+pathexists(char* path, int mode)
+{
+ register char* s;
+ register char* e;
+ register Tree_t* p;
+ register Tree_t* t;
+ register int c;
+ char* ee;
+ int cc;
+ int x;
+ struct stat st;
+ int (*cmp)(const char*, const char*);
+
+ static Tree_t tree;
+
+ t = &tree;
+ e = (c = *path) == '/' ? path + 1 : path;
+ cmp = strchr(astconf("PATH_ATTRIBUTES", path, NiL), 'c') ? strcasecmp : strcmp;
+ if ((ast.locale.set & (AST_LC_debug|AST_LC_find)) == (AST_LC_debug|AST_LC_find))
+ sfprintf(sfstderr, "locale test %s\n", path);
+ while (c)
+ {
+ p = t;
+ for (s = e; *e && *e != '/'; e++);
+ c = *e;
+ *e = 0;
+ for (t = p->tree; t && (*cmp)(s, t->name); t = t->next);
+ if (!t)
+ {
+ if (!(t = newof(0, Tree_t, 1, strlen(s))))
+ {
+ *e = c;
+ return 0;
+ }
+ strcpy(t->name, s);
+ t->next = p->tree;
+ p->tree = t;
+ if (c)
+ {
+ *e = c;
+ for (s = ee = e + 1; *ee && *ee != '/'; ee++);
+ cc = *ee;
+ *ee = 0;
+ }
+ else
+ ee = 0;
+ if ((ast.locale.set & (AST_LC_debug|AST_LC_find)) == (AST_LC_debug|AST_LC_find))
+ sfprintf(sfstderr, "locale stat %s\n", path);
+ x = stat(path, &st);
+ if (ee)
+ {
+ e = ee;
+ c = cc;
+ if (!x || errno == ENOENT)
+ t->mode = PATH_READ|PATH_EXECUTE;
+ if (!(p = newof(0, Tree_t, 1, strlen(s))))
+ {
+ *e = c;
+ return 0;
+ }
+ strcpy(p->name, s);
+ p->next = t->tree;
+ t->tree = p;
+ t = p;
+ }
+ if (x)
+ {
+ *e = c;
+ return 0;
+ }
+ if (st.st_mode & (S_IRUSR|S_IRGRP|S_IROTH))
+ t->mode |= PATH_READ;
+ if (st.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))
+ t->mode |= PATH_WRITE;
+ if (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
+ t->mode |= PATH_EXECUTE;
+ if (!S_ISDIR(st.st_mode))
+ t->mode |= PATH_REGULAR;
+ }
+ *e++ = c;
+ if (!t->mode || c && (t->mode & PATH_REGULAR))
+ return 0;
+ }
+ mode &= (PATH_READ|PATH_WRITE|PATH_EXECUTE|PATH_REGULAR);
+ return (t->mode & mode) == mode;
+}
diff --git a/src/lib/libast/path/pathfind.c b/src/lib/libast/path/pathfind.c
new file mode 100644
index 0000000..54dc140
--- /dev/null
+++ b/src/lib/libast/path/pathfind.c
@@ -0,0 +1,168 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * include style search support
+ */
+
+#include <ast.h>
+#include <error.h>
+#include <ls.h>
+
+#define directory(p,s) (stat((p),(s))>=0&&S_ISDIR((s)->st_mode))
+#define regular(p,s) (stat((p),(s))>=0&&(S_ISREG((s)->st_mode)||streq(p,"/dev/null")))
+
+typedef struct Dir_s /* directory list element */
+{
+ struct Dir_s* next; /* next in list */
+ char dir[1]; /* directory path */
+} Dir_t;
+
+static struct /* directory list state */
+{
+ Dir_t* head; /* directory list head */
+ Dir_t* tail; /* directory list tail */
+} state;
+
+/*
+ * append dir to pathfind() include list
+ */
+
+int
+pathinclude(const char* dir)
+{
+ register Dir_t* dp;
+ struct stat st;
+
+ if (dir && *dir && !streq(dir, ".") && directory(dir, &st))
+ {
+ for (dp = state.head; dp; dp = dp->next)
+ if (streq(dir, dp->dir))
+ return 0;
+ if (!(dp = oldof(0, Dir_t, 1, strlen(dir))))
+ return -1;
+ strcpy(dp->dir, dir);
+ dp->next = 0;
+ if (state.tail)
+ state.tail = state.tail->next = dp;
+ else
+ state.head = state.tail = dp;
+ }
+ return 0;
+}
+
+/*
+ * return path to name using pathinclude() list
+ * path placed in <buf,size>
+ * if lib!=0 then pathpath() attempted after include search
+ * if type!=0 and name has no '.' then file.type also attempted
+ * any *: prefix in lib is ignored (discipline library dictionary support)
+ */
+
+char*
+pathfind(const char* name, const char* lib, const char* type, char* buf, size_t size)
+{
+ register Dir_t* dp;
+ register char* s;
+ char tmp[PATH_MAX];
+ struct stat st;
+
+ if (((s = strrchr(name, '/')) || (s = (char*)name)) && strchr(s, '.'))
+ type = 0;
+
+ /*
+ * always check the unadorned path first
+ * this handles . and absolute paths
+ */
+
+ if (regular(name, &st))
+ {
+ strncopy(buf, name, size);
+ return buf;
+ }
+ if (type)
+ {
+ sfsprintf(buf, size, "%s.%s", name, type);
+ if (regular(buf, &st))
+ return buf;
+ }
+ if (*name == '/')
+ return 0;
+
+ /*
+ * check the directory of the including file
+ * on the assumption that error_info.file is properly stacked
+ */
+
+ if (error_info.file && (s = strrchr(error_info.file, '/')))
+ {
+ sfsprintf(buf, size, "%-.*s%s", s - error_info.file + 1, error_info.file, name);
+ if (regular(buf, &st))
+ return buf;
+ if (type)
+ {
+ sfsprintf(buf, size, "%-.*s%s%.s", s - error_info.file + 1, error_info.file, name, type);
+ if (regular(buf, &st))
+ return buf;
+ }
+ }
+
+ /*
+ * check the include dir list
+ */
+
+ for (dp = state.head; dp; dp = dp->next)
+ {
+ sfsprintf(tmp, sizeof(tmp), "%s/%s", dp->dir, name);
+ if (pathpath(tmp, "", PATH_REGULAR, buf, size))
+ return buf;
+ if (type)
+ {
+ sfsprintf(tmp, sizeof(tmp), "%s/%s.%s", dp->dir, name, type);
+ if (pathpath(tmp, "", PATH_REGULAR, buf, size))
+ return buf;
+ }
+ }
+
+ /*
+ * finally a lib related search on PATH
+ */
+
+ if (lib)
+ {
+ if (s = strrchr((char*)lib, ':'))
+ lib = (const char*)s + 1;
+ sfsprintf(tmp, sizeof(tmp), "lib/%s/%s", lib, name);
+ if (pathpath(tmp, "", PATH_REGULAR, buf, size))
+ return buf;
+ if (type)
+ {
+ sfsprintf(tmp, sizeof(tmp), "lib/%s/%s.%s", lib, name, type);
+ if (pathpath(tmp, "", PATH_REGULAR, buf, size))
+ return buf;
+ }
+ }
+ return 0;
+}
diff --git a/src/lib/libast/path/pathgetlink.c b/src/lib/libast/path/pathgetlink.c
new file mode 100644
index 0000000..0022594
--- /dev/null
+++ b/src/lib/libast/path/pathgetlink.c
@@ -0,0 +1,102 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+* Glenn Fowler
+* AT&T Bell Laboratories
+*/
+
+#include "univlib.h"
+
+#ifdef UNIV_MAX
+
+#include <ctype.h>
+
+#endif
+
+/*
+ * return external representation for symbolic link text of name in buf
+ * the link text string length is returned
+ */
+
+int
+pathgetlink(const char* name, char* buf, int siz)
+{
+ int n;
+
+ if ((n = readlink(name, buf, siz)) < 0) return(-1);
+ if (n >= siz)
+ {
+ errno = EINVAL;
+ return(-1);
+ }
+ buf[n] = 0;
+#ifdef UNIV_MAX
+ if (isspace(*buf))
+ {
+ register char* s;
+ register char* t;
+ register char* u;
+ register char* v;
+ int match = 0;
+ char tmp[PATH_MAX];
+
+ s = buf;
+ t = tmp;
+ while (isalnum(*++s) || *s == '_' || *s == '.');
+ if (*s++)
+ {
+ for (;;)
+ {
+ if (!*s || isspace(*s))
+ {
+ if (match)
+ {
+ *t = 0;
+ n = t - tmp;
+ strcpy(buf, tmp);
+ }
+ break;
+ }
+ if (t >= &tmp[sizeof(tmp)]) break;
+ *t++ = *s++;
+ if (!match && t < &tmp[sizeof(tmp) - univ_size + 1]) for (n = 0; n < UNIV_MAX; n++)
+ {
+ if (*(v = s - 1) == *(u = univ_name[n]))
+ {
+ while (*u && *v++ == *u) u++;
+ if (!*u)
+ {
+ match = 1;
+ strcpy(t - 1, univ_cond);
+ t += univ_size - 1;
+ s = v;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+ return(n);
+}
diff --git a/src/lib/libast/path/pathkey.c b/src/lib/libast/path/pathkey.c
new file mode 100644
index 0000000..2432d83
--- /dev/null
+++ b/src/lib/libast/path/pathkey.c
@@ -0,0 +1,320 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * generate 14 char lookup key for lang path in key
+ * based on 32-bit checksum on path
+ *
+ * if key==0 then space is malloc'd
+ * if attr != 0 then attribute var assignments placed here:
+ * ATTRIBUTES list of attribute names
+ */
+
+#define _AST_API_H 1
+
+#include <ast.h>
+#include <ctype.h>
+#include <fs3d.h>
+#include <preroot.h>
+#include <ls.h>
+
+char*
+pathkey(char* key, char* attr, const char* lang, const char* tool, const char* path)
+{
+ return pathkey_20100601(lang, tool, path, key, 16, attr, PATH_MAX);
+}
+
+#undef _AST_API_H
+
+#include <ast_api.h>
+
+char*
+pathkey_20100601(const char* lang, const char* tool, const char* apath, char* key, size_t keysize, char* attr, size_t attrsize)
+{
+ register char* path = (char*)apath;
+ register char* s;
+ register char* k;
+ char* t;
+ char* flags;
+ char** p;
+ int c;
+ unsigned long n;
+ char buf[15];
+ char* usr[16];
+ char* env[elementsof(usr) + 3];
+ char* ver[2];
+ char tmp[PATH_MAX];
+#if _UWIN
+ struct stat st;
+#endif
+
+ static char let[] = "ABCDEFGHIJKLMNOP";
+
+ if (!key)
+ key = buf;
+ if (tool && streq(tool, "mam"))
+ {
+ for (n = 0; *path; path++)
+ n = n * 0x63c63cd9L + *path + 0x9c39c33dL;
+ k = key;
+ for (n &= 0xffffffffL; n; n >>= 4)
+ *k++ = let[n & 0xf];
+ *k = 0;
+ }
+ else
+ {
+ for (c = 0; c < elementsof(env); c++)
+ env[c] = 0;
+ n = 0;
+
+ /*
+ * trailing flags in path
+ */
+
+ if (flags = strchr(path, ' '))
+ {
+ if (flags == path)
+ flags = 0;
+ else
+ {
+ strlcpy(tmp, path, sizeof(tmp));
+ *(flags = tmp + (flags - path)) = 0;
+ path = tmp;
+ }
+ }
+
+ /*
+ * 3D
+ */
+
+ if (!flags && fs3d(FS3D_TEST) && (c = mount(path, tmp, FS3D_GET|FS3D_ALL|FS3D_SIZE(PATH_MAX), NiL)) > 1 && c < PATH_MAX)
+ path = tmp;
+
+ /*
+ * preroot
+ */
+
+ if (attr)
+ attr = strcopy(attr, "PREROOT='");
+#if FS_PREROOT
+ if (k = getenv(PR_BASE))
+ {
+ if (s = strrchr(k, '/'))
+ k = s + 1;
+ n = memsum(k, strlen(k), n);
+ }
+ if (attr && (getpreroot(attr, path) || getpreroot(attr, NiL)))
+ attr += strlen(attr);
+#else
+ if ((k = getenv("VIRTUAL_ROOT")) && *k == '/')
+ {
+ n = memsum(k, strlen(k), n);
+ if (attr)
+ attr = strcopy(attr, k);
+ }
+#endif
+#if _UWIN
+ if (!stat("/", &st) && st.st_ino == 64)
+ {
+ k = "/64";
+ n = memsum(k, strlen(k), n);
+ if (attr)
+ attr = strcopy(attr, k);
+ }
+#endif
+
+ /*
+ * universe
+ */
+
+ if (attr)
+ attr = strcopy(attr, "' UNIVERSE='");
+ if (k = astconf("UNIVERSE", NiL, NiL))
+ {
+ n = memsum(k, strlen(k), n);
+ if (attr)
+ attr = strcopy(attr, k);
+ }
+
+ /*
+ * environment
+ *
+ * ${PROBE_ATTRIBUTES} || ${VERSION_ENVIRONMENT} : list of alternate env vars
+ * ${VERSION_ENVIRONMENT} : list of alternate env vars
+ * ${VERSION_<lang>}
+ * ${VERSION_<base(path)>}
+ * ${<toupper(base(path))>VER}
+ * ${OBJTYPE}
+ */
+
+ if (attr)
+ *attr++ = '\'';
+ c = 0;
+ usr[c++] = "OBJTYPE";
+ if (!(k = getenv("PROBE_ATTRIBUTES")))
+ k = getenv("VERSION_ENVIRONMENT");
+ if (k)
+ while (c < (elementsof(usr) - 1))
+ {
+ while (*k && (*k == ':' || *k == ' '))
+ k++;
+ if (!*k)
+ break;
+ usr[c++] = k;
+ while (*k && *k != ':' && *k != ' ')
+ k++;
+ }
+ usr[c] = 0;
+ ver[0] = (char*)lang;
+ ver[1] = k = (s = strrchr(path, '/')) ? s + 1 : path;
+ s = buf;
+ if (isdigit(*k))
+ {
+ if (*k == '3' && *(k + 1) == 'b')
+ {
+ /*
+ * cuteness never pays
+ */
+
+ k += 2;
+ *s++ = 'B';
+ *s++ = 'B';
+ *s++ = 'B';
+ }
+ else
+ *s++ = 'U';
+ }
+ for (; (c = *k) && s < &buf[sizeof(buf) - 1]; k++)
+ {
+ if (!isalnum(c))
+ c = '_';
+ else if (islower(c))
+ c = toupper(c);
+ *s++ = c;
+ }
+ *s = 0;
+ for (p = environ; *p; p++)
+ {
+ s = "VERSION_";
+ for (k = *p; *k && *k == *s; k++, s++);
+ if (*k && !*s)
+ {
+ for (c = 0; c < elementsof(ver); c++)
+ if (!env[c] && (s = ver[c]))
+ {
+ for (t = k; *t && *t != '=' && *t++ == *s; s++);
+ if (*t == '=' && (!*s || (s - ver[c]) > 1))
+ {
+ env[c] = *p;
+ goto found;
+ }
+ }
+ }
+ if (!env[2])
+ {
+ s = buf;
+ for (k = *p; *k && *s++ == *k; k++);
+ if ((s - buf) > 2 && k[0] == 'V' && k[1] == 'E' && k[2] == 'R' && k[3] == '=')
+ {
+ env[2] = *p;
+ goto found;
+ }
+ }
+ for (c = 0; c < elementsof(usr) && (s = usr[c]); c++)
+ if (!env[c + elementsof(env) - elementsof(usr)])
+ {
+ for (k = *p; *k && *k == *s; k++, s++);
+ if (*k == '=' && (!*s || *s == ':' || *s == ' '))
+ {
+ env[c + elementsof(env) - elementsof(usr)] = *p;
+ goto found;
+ }
+ }
+ found: ;
+ }
+ for (c = 0; c < elementsof(env); c++)
+ if (k = env[c])
+ {
+ if (attr)
+ {
+ *attr++ = ' ';
+ while ((*attr++ = *k++) != '=');
+ *attr++ = '\'';
+ attr = strcopy(attr, k);
+ *attr++ = '\'';
+ }
+ else
+ while (*k && *k++ != '=');
+ n = memsum(k, strlen(k), n);
+ }
+ if (attr)
+ {
+ attr = strcopy(attr, " ATTRIBUTES='PREROOT UNIVERSE");
+ for (c = 0; c < elementsof(env); c++)
+ if (k = env[c])
+ {
+ *attr++ = ' ';
+ while ((*attr = *k++) != '=')
+ attr++;
+ }
+ *attr++ = '\'';
+ *attr = 0;
+ }
+
+ /*
+ * now the normal stuff
+ */
+
+ if (flags)
+ *flags = ' ';
+ s = path + strlen(path);
+ sfsprintf(key, 15, "%08lX", memsum(path, s - path, n));
+ k = key + 14;
+ *k = 0;
+ if (!flags)
+ t = path;
+ else if ((t = s - 4) < flags)
+ t = flags + 1;
+ for (;;)
+ {
+ if (--s < t)
+ {
+ if (t == path)
+ break;
+ s = flags - 2;
+ t = path;
+ }
+ if (*s != '/' && *s != ' ')
+ {
+ *--k = *s;
+ if (k <= key + 8)
+ break;
+ }
+ }
+ while (k > key + 8)
+ *--k = '.';
+ }
+ return key == buf ? strdup(key) : key;
+}
diff --git a/src/lib/libast/path/pathnative.c b/src/lib/libast/path/pathnative.c
new file mode 100644
index 0000000..c683d17
--- /dev/null
+++ b/src/lib/libast/path/pathnative.c
@@ -0,0 +1,126 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * convert path to native fs representation in <buf,siz>
+ * length of converted path returned
+ * if return length >= siz then buf is indeterminate, but another call
+ * with siz=length+1 would work
+ * if buf==0 then required size is returned
+ */
+
+#include <ast.h>
+
+#if _UWIN
+
+extern int uwin_path(const char*, char*, int);
+
+size_t
+pathnative(const char* path, char* buf, size_t siz)
+{
+ return uwin_path(path, buf, siz);
+}
+
+#else
+
+#if __CYGWIN__
+
+extern void cygwin_conv_to_win32_path(const char*, char*);
+
+size_t
+pathnative(const char* path, char* buf, size_t siz)
+{
+ size_t n;
+
+ if (!buf || siz < PATH_MAX)
+ {
+ char tmp[PATH_MAX];
+
+ cygwin_conv_to_win32_path(path, tmp);
+ if ((n = strlen(tmp)) < siz && buf)
+ memcpy(buf, tmp, n + 1);
+ return n;
+ }
+ cygwin_conv_to_win32_path(path, buf);
+ return strlen(buf);
+}
+
+#else
+
+#if __EMX__
+
+size_t
+pathnative(const char* path, char* buf, size_t siz)
+{
+ char* s;
+ size_t n;
+
+ if (!_fullpath(buf, path, siz))
+ {
+ for (s = buf; *s; s++)
+ if (*s == '/')
+ *s = '\\';
+ }
+ else if ((n = strlen(path)) < siz && buf)
+ memcpy(buf, path, n + 1);
+ return n;
+}
+
+#else
+
+#if __INTERIX
+
+#include <interix/interix.h>
+
+size_t
+pathnative(const char* path, char* buf, size_t siz)
+{
+ *buf = 0;
+ if (path[1] == ':')
+ strlcpy(buf, path, siz);
+ else
+ unixpath2win(path, 0, buf, siz);
+ return strlen(buf);
+}
+
+#else
+
+size_t
+pathnative(const char* path, char* buf, size_t siz)
+{
+ size_t n;
+
+ if ((n = strlen(path)) < siz && buf)
+ memcpy(buf, path, n + 1);
+ return n;
+}
+
+#endif
+
+#endif
+
+#endif
+
+#endif
diff --git a/src/lib/libast/path/pathpath.c b/src/lib/libast/path/pathpath.c
new file mode 100644
index 0000000..4c0831d
--- /dev/null
+++ b/src/lib/libast/path/pathpath.c
@@ -0,0 +1,127 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return full path to p with mode access using $PATH
+ * a!=0 enables related root search
+ * a!=0 && a!="" searches a dir first
+ * the related root must have a bin subdir
+ * p==0 sets the cached relative dir to a
+ * full path returned in path buffer
+ * if path==0 then the space is malloc'd
+ */
+
+#define _AST_API_H 1
+
+#include <ast.h>
+
+char*
+pathpath(char* path, const char* p, const char* a, int mode)
+{
+ return pathpath_20100601(p, a, mode, path, PATH_MAX);
+}
+
+#undef _AST_API_H
+
+#include <ast_api.h>
+
+char*
+pathpath_20100601(const char* p, const char* a, int mode, register char* path, size_t size)
+{
+ register char* s;
+ char* x;
+ char buf[PATH_MAX];
+
+ static char* cmd;
+
+ if (!path)
+ {
+ path = buf;
+ if (!size || size > sizeof(buf))
+ size = sizeof(buf);
+ }
+ if (!p)
+ {
+ if (cmd)
+ free(cmd);
+ cmd = a ? strdup(a) : (char*)0;
+ return 0;
+ }
+ if (strlen(p) < size)
+ {
+ strcpy(path, p);
+ if (pathexists(path, mode))
+ {
+ if (*p != '/' && (mode & PATH_ABSOLUTE))
+ {
+ getcwd(buf, sizeof(buf));
+ s = buf + strlen(buf);
+ sfsprintf(s, sizeof(buf) - (s - buf), "/%s", p);
+ if (path != buf)
+ strcpy(path, buf);
+ }
+ return (path == buf) ? strdup(path) : path;
+ }
+ }
+ if (*p == '/')
+ a = 0;
+ else if (s = (char*)a)
+ {
+ x = s;
+ if (strchr(p, '/'))
+ {
+ a = p;
+ p = "..";
+ }
+ else
+ a = 0;
+ if ((!cmd || *cmd) && (strchr(s, '/') || (s = cmd)))
+ {
+ if (!cmd && *s == '/')
+ cmd = strdup(s);
+ if (strlen(s) < (sizeof(buf) - 6))
+ {
+ s = strcopy(path, s);
+ for (;;)
+ {
+ do if (s <= path) goto normal; while (*--s == '/');
+ do if (s <= path) goto normal; while (*--s != '/');
+ strcpy(s + 1, "bin");
+ if (pathexists(path, PATH_EXECUTE))
+ {
+ if (s = pathaccess(path, p, a, mode, path, size))
+ return path == buf ? strdup(s) : s;
+ goto normal;
+ }
+ }
+ normal: ;
+ }
+ }
+ }
+ x = !a && strchr(p, '/') ? "" : pathbin();
+ if (!(s = pathaccess(x, p, a, mode, path, size)) && !*x && (x = getenv("FPATH")))
+ s = pathaccess(x, p, a, mode, path, size);
+ return (s && path == buf) ? strdup(s) : s;
+}
diff --git a/src/lib/libast/path/pathposix.c b/src/lib/libast/path/pathposix.c
new file mode 100644
index 0000000..d220591
--- /dev/null
+++ b/src/lib/libast/path/pathposix.c
@@ -0,0 +1,128 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * convert native path to posix fs representation in <buf,siz>
+ * length of converted path returned
+ * if return length >= siz then buf is indeterminate, but another call
+ * with siz=length+1 would work
+ * if buf==0 then required size is returned
+ */
+
+#include <ast.h>
+
+#if _UWIN
+
+#include <uwin.h>
+
+size_t
+pathposix(const char* path, char* buf, size_t siz)
+{
+ return uwin_unpath(path, buf, siz);
+}
+
+#else
+
+#if __CYGWIN__
+
+extern void cygwin_conv_to_posix_path(const char*, char*);
+
+size_t
+pathposix(const char* path, char* buf, size_t siz)
+{
+ size_t n;
+
+ if (!buf || siz < PATH_MAX)
+ {
+ char tmp[PATH_MAX];
+
+ cygwin_conv_to_posix_path(path, tmp);
+ if ((n = strlen(tmp)) < siz && buf)
+ memcpy(buf, tmp, n + 1);
+ return n;
+ }
+ cygwin_conv_to_posix_path(path, buf);
+ return strlen(buf);
+}
+
+#else
+
+#if __EMX__ && 0 /* show me the docs */
+
+size_t
+pathposix(const char* path, char* buf, size_t siz)
+{
+ char* s;
+ size_t n;
+
+ if (!_posixpath(buf, path, siz))
+ {
+ for (s = buf; *s; s++)
+ if (*s == '/')
+ *s = '\\';
+ }
+ else if ((n = strlen(path)) < siz && buf)
+ memcpy(buf, path, n + 1);
+ return n;
+}
+
+#else
+
+#if __INTERIX
+
+#include <interix/interix.h>
+
+size_t
+pathposix(const char* path, char *buf, size_t siz)
+{
+ static const char pfx[] = "/dev/fs";
+
+ *buf = 0;
+ if (!strncasecmp(path, pfx, sizeof(pfx) - 1))
+ strlcpy(buf, path, siz);
+ else
+ winpath2unix(path, PATH_NONSTRICT, buf, siz);
+ return strlen(buf);
+}
+
+#else
+
+size_t
+pathposix(const char* path, char* buf, size_t siz)
+{
+ size_t n;
+
+ if ((n = strlen(path)) < siz && buf)
+ memcpy(buf, path, n + 1);
+ return n;
+}
+
+#endif
+
+#endif
+
+#endif
+
+#endif
diff --git a/src/lib/libast/path/pathprobe.c b/src/lib/libast/path/pathprobe.c
new file mode 100644
index 0000000..26d1fe3
--- /dev/null
+++ b/src/lib/libast/path/pathprobe.c
@@ -0,0 +1,316 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return in path the full path name of the probe(1)
+ * information for lang and tool using proc
+ * if attr != 0 then path attribute assignments placed here
+ *
+ * if path==0 then the space is malloc'd
+ *
+ * op:
+ *
+ * -3 return non-writable path name with no generation
+ * -2 return path name with no generation
+ * -1 return no $HOME path name with no generation
+ * 0 verbose probe
+ * 1 silent probe
+ *
+ * 0 returned if the info does not exist and cannot be generated
+ */
+
+#define _AST_API_H 1
+
+#include <ast.h>
+#include <error.h>
+#include <ls.h>
+#include <proc.h>
+
+char*
+pathprobe(char* path, char* attr, const char* lang, const char* tool, const char* proc, int op)
+{
+ return pathprobe_20100601(lang, tool, proc, op, path, PATH_MAX, attr, PATH_MAX);
+}
+
+#undef _AST_API_H
+
+#include <ast_api.h>
+
+#ifndef PROBE
+#define PROBE "probe"
+#endif
+
+#if defined(ST_RDONLY) || defined(ST_NOSUID)
+
+/*
+ * return non-0 if path is in a readonly or non-setuid fs
+ */
+
+static int
+rofs(const char* path)
+{
+ struct statvfs vfs;
+ struct stat st;
+
+ if (!statvfs(path, &vfs))
+ {
+#if defined(ST_RDONLY)
+ if (vfs.f_flag & ST_RDONLY)
+ return 1;
+#endif
+#if defined(ST_NOSUID)
+ if ((vfs.f_flag & ST_NOSUID) && (stat(path, &st) || st.st_uid != getuid() && st.st_uid != geteuid()))
+ return 1;
+#endif
+ }
+ return 0;
+}
+
+#else
+
+#define rofs(p) 0
+
+#endif
+
+char*
+pathprobe_20100601(const char* lang, const char* tool, const char* aproc, int op, char* path, size_t pathsize, char* attr, size_t attrsize)
+{
+ char* proc = (char*)aproc;
+ register char* p;
+ register char* k;
+ register char* x;
+ register char** ap;
+ int n;
+ int v;
+ int force;
+ ssize_t r;
+ char* e;
+ char* np;
+ char* nx;
+ char* probe;
+ const char* dirs;
+ const char* dir;
+ Proc_t* pp;
+ Sfio_t* sp;
+ char buf[PATH_MAX];
+ char cmd[PATH_MAX];
+ char exe[PATH_MAX];
+ char lib[PATH_MAX];
+ char ver[PATH_MAX];
+ char key[16];
+ char* arg[8];
+ long ops[2];
+ unsigned long ptime;
+ struct stat st;
+ struct stat ps;
+
+ if (*proc != '/')
+ {
+ if (p = strchr(proc, ' '))
+ {
+ strncopy(buf, proc, p - proc + 1);
+ proc = buf;
+ }
+ if (!(proc = pathpath(proc, NiL, PATH_ABSOLUTE|PATH_REGULAR|PATH_EXECUTE, cmd, sizeof(cmd))))
+ proc = (char*)aproc;
+ else if (p)
+ {
+ n = strlen(proc);
+ strncopy(proc + n, p, PATH_MAX - n - 1);
+ }
+ }
+ if (!path)
+ {
+ path = buf;
+ pathsize = sizeof(buf);
+ }
+ probe = PROBE;
+ x = lib + sizeof(lib) - 1;
+ k = lib + sfsprintf(lib, x - lib, "lib/%s/", probe);
+ p = k + sfsprintf(k, x - k, "%s/%s/", lang, tool);
+ pathkey(lang, tool, proc, key, sizeof(key), attr, attrsize);
+ if (op >= -2)
+ {
+ strncopy(p, key, x - p);
+ if (pathpath(lib, "", PATH_ABSOLUTE, path, pathsize) && !stat(path, &st) && (st.st_mode & S_IWUSR))
+ return path == buf ? strdup(path) : path;
+ }
+ e = strncopy(p, probe, x - p);
+ if (!pathpath(lib, "", PATH_ABSOLUTE|PATH_EXECUTE, path, pathsize) || stat(path, &ps))
+ return 0;
+ for (;;)
+ {
+ ptime = ps.st_mtime;
+ n = strlen(path);
+ if (n < (PATH_MAX - 5))
+ {
+ strcpy(path + n, ".ini");
+ if (!stat(path, &st) && st.st_size && ptime < (unsigned long)st.st_mtime)
+ ptime = st.st_mtime;
+ path[n] = 0;
+ }
+ np = path + n - (e - k);
+ nx = path + PATH_MAX - 1;
+ strncopy(np, probe, nx - np);
+ if (!stat(path, &st))
+ break;
+
+ /*
+ * yes lib/probe/<lang>/<proc>/probe
+ * no lib/probe/probe
+ *
+ * do a manual pathaccess() to find a dir with both
+ */
+
+ sfsprintf(exe, sizeof(exe), "lib/%s/%s", probe, probe);
+ dirs = pathbin();
+ for (;;)
+ {
+ if (!(dir = dirs))
+ return 0;
+ dirs = pathcat(dir, ':', "..", exe, path, pathsize);
+ pathcanon(path, pathsize, 0);
+ if (*path == '/' && pathexists(path, PATH_REGULAR|PATH_EXECUTE))
+ {
+ pathcat(dir, ':', "..", lib, path, pathsize);
+ pathcanon(path, pathsize, 0);
+ if (*path == '/' && pathexists(path, PATH_REGULAR|PATH_EXECUTE) && !stat(path, &ps))
+ break;
+ }
+ }
+ }
+ strncopy(p, key, x - p);
+ p = np;
+ x = nx;
+ strcpy(exe, path);
+ if (op >= -1 && (!(st.st_mode & S_ISUID) && ps.st_uid != geteuid() || rofs(path)))
+ {
+ if (!(p = getenv("HOME")))
+ return 0;
+ p = path + sfsprintf(path, PATH_MAX - 1, "%s/.%s/%s/", p, probe, HOSTTYPE);
+ }
+ strncopy(p, k, x - p);
+ force = 0;
+ if (op >= 0 && !stat(path, &st))
+ {
+ if (ptime <= (unsigned long)st.st_mtime || ptime <= (unsigned long)st.st_ctime)
+ {
+ /*
+ * verify (<sep><name><sep><option><sep><value>)* header
+ */
+
+ if (sp = sfopen(NiL, path, "r"))
+ {
+ if (x = sfgetr(sp, '\n', 1))
+ {
+ while (*x && *x != ' ')
+ x++;
+ while (*x == ' ')
+ x++;
+ if (n = *x++)
+ for (;;)
+ {
+ for (k = x; *x && *x != n; x++);
+ if (!*x)
+ break;
+ *x++ = 0;
+ for (p = x; *x && *x != n; x++);
+ if (!*x)
+ break;
+ *x++ = 0;
+ for (e = x; *x && *x != n; x++);
+ if (!*x)
+ break;
+ *x++ = 0;
+ if (streq(k, "VERSION"))
+ {
+ ap = arg;
+ *ap++ = proc;
+ *ap++ = p;
+ *ap = 0;
+ ops[0] = PROC_FD_DUP(1, 2, 0);
+ ops[1] = 0;
+ if (pp = procopen(proc, arg, NiL, ops, PROC_READ))
+ {
+ if ((v = x - e) >= sizeof(ver))
+ v = sizeof(ver) - 1;
+ for (k = p = ver;; k++)
+ {
+ if (k >= p)
+ {
+ if (v <= 0 || (r = read(pp->rfd, k, v)) <= 0)
+ break;
+ v -= r;
+ p = k + r;
+ }
+ if (*k == '\n' || *k == '\r')
+ break;
+ if (*k == n)
+ *k = ' ';
+ }
+ *k = 0;
+ if (strcmp(ver, e))
+ {
+ force = 1;
+ error(0, "probe processor %s version \"%s\" changed -- expected \"%s\"", proc, ver, e);
+ }
+ procclose(pp);
+ }
+ break;
+ }
+ }
+ }
+ sfclose(sp);
+ }
+ if (!force)
+ op = -1;
+ }
+ if (op >= 0 && (st.st_mode & S_IWUSR))
+ {
+ if (op == 0)
+ error(0, "%s probe information for %s language processor %s must be manually regenerated", tool, lang, proc);
+ op = -1;
+ force = 0;
+ }
+ }
+ if (op >= 0)
+ {
+ ap = arg;
+ *ap++ = exe;
+ if (force)
+ *ap++ = "-f";
+ if (op > 0)
+ *ap++ = "-s";
+ *ap++ = (char*)lang;
+ *ap++ = (char*)tool;
+ *ap++ = proc;
+ *ap = 0;
+ if (procrun(exe, arg, 0))
+ return 0;
+ if (eaccess(path, R_OK))
+ return 0;
+ }
+ return path == buf ? strdup(path) : path;
+}
diff --git a/src/lib/libast/path/pathprog.c b/src/lib/libast/path/pathprog.c
new file mode 100644
index 0000000..ac29427
--- /dev/null
+++ b/src/lib/libast/path/pathprog.c
@@ -0,0 +1,128 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return the full path of the current program in path
+ * command!=0 is used as a default
+ */
+
+#include <ast.h>
+
+#if _WINIX
+#include <ast_windows.h>
+#include <ctype.h>
+#endif
+
+#include "FEATURE/prog"
+
+#if _hdr_macho_o_dyld && _lib__NSGetExecutablePath
+#include <mach-o/dyld.h>
+#else
+#undef _lib__NSGetExecutablePath
+#endif
+
+static size_t
+prog(const char* command, char* path, size_t size)
+{
+ ssize_t n;
+ char* s;
+#if _WINIX
+ char* t;
+ char* e;
+ int c;
+ int q;
+#endif
+#if _lib__NSGetExecutablePath
+ uint32_t z;
+#endif
+
+#ifdef _PROC_PROG
+ if ((n = readlink(_PROC_PROG, path, size)) > 0 && *path == '/')
+ {
+ if (n < size)
+ path[n] = 0;
+ return n;
+ }
+#endif
+#if _lib_getexecname
+ if ((s = (char*)getexecname()) && *s == '/')
+ goto found;
+#endif
+#if _lib__NSGetExecutablePath
+ z = size;
+ if (!_NSGetExecutablePath(path, &z) && *s == '/')
+ return strlen(s);
+#endif
+#if _WINIX
+ if (s = GetCommandLine())
+ {
+ n = 0;
+ q = 0;
+ t = path;
+ e = path + size - 1;
+ while (c = *s++)
+ {
+ if (c == q)
+ q = 0;
+ else if (!q && c == '"')
+ q = c;
+ else if (!q && isspace(c))
+ break;
+ else if (t < e)
+ *t++ = c == '\\' ? '/' : c;
+ else
+ n++;
+ }
+ if (t < e)
+ *t = 0;
+ return (t - path) + n;
+ }
+#endif
+ if (command)
+ {
+ s = (char*)command;
+ goto found;
+ }
+ return 0;
+ found:
+ n = strlen(s);
+ if (n < size)
+ memcpy(path, s, n + 1);
+ return n;
+}
+
+size_t
+pathprog(const char* command, char* path, size_t size)
+{
+ char* rel;
+ ssize_t n;
+
+ if ((n = prog(command, path, size)) > 0 && n < size && *path != '/' && (rel = strdup(path)))
+ {
+ n = pathpath(rel, NiL, PATH_REGULAR|PATH_EXECUTE, path, size) ? strlen(path) : 0;
+ free(rel);
+ }
+ return n;
+}
diff --git a/src/lib/libast/path/pathrepl.c b/src/lib/libast/path/pathrepl.c
new file mode 100644
index 0000000..d16a390
--- /dev/null
+++ b/src/lib/libast/path/pathrepl.c
@@ -0,0 +1,93 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * in place replace of first occurrence of /match/ with /replace/ in path
+ * end of path returned
+ */
+
+#define _AST_API_H 1
+
+#include <ast.h>
+
+char*
+pathrepl(char* path, const char* match, const char* replace)
+{
+ return pathrepl_20100601(path, PATH_MAX, match, replace);
+}
+
+#undef _AST_API_H
+
+#include <ast_api.h>
+
+char*
+pathrepl_20100601(register char* path, size_t size, const char* match, register const char* replace)
+{
+ register const char* m = match;
+ register const char* r;
+ char* t;
+
+ if (!match)
+ match = "";
+ if (!replace)
+ replace = "";
+ if (streq(match, replace))
+ return(path + strlen(path));
+ if (!size)
+ size = strlen(path) + 1;
+ for (;;)
+ {
+ while (*path && *path++ != '/');
+ if (!*path) break;
+ if (*path == *m)
+ {
+ t = path;
+ while (*m && *m++ == *path) path++;
+ if (!*m && *path == '/')
+ {
+ register char* p;
+
+ p = t;
+ r = replace;
+ while (p < path && *r) *p++ = *r++;
+ if (p < path) while (*p++ = *path++);
+ else if (*r && p >= path)
+ {
+ register char* u;
+
+ t = path + strlen(path);
+ u = t + strlen(r);
+ while (t >= path) *u-- = *t--;
+ while (*r) *p++ = *r++;
+ }
+ else p += strlen(p) + 1;
+ return(p - 1);
+ }
+ path = t;
+ m = match;
+ }
+ }
+ return(path);
+}
diff --git a/src/lib/libast/path/pathsetlink.c b/src/lib/libast/path/pathsetlink.c
new file mode 100644
index 0000000..48aa4fe
--- /dev/null
+++ b/src/lib/libast/path/pathsetlink.c
@@ -0,0 +1,72 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+* Glenn Fowler
+* AT&T Bell Laboratories
+*/
+
+#include "univlib.h"
+
+/*
+ * create symbolic name from external representation text in buf
+ * the arg order matches link(2)
+ */
+
+int
+pathsetlink(const char* buf, const char* name)
+{
+ register char* t = (char*)buf;
+#ifdef UNIV_MAX
+ register char* s = (char*)buf;
+ register char* v;
+ int n;
+ char tmp[PATH_MAX];
+
+ while (*s)
+ {
+ if (*s++ == univ_cond[0] && !strncmp(s - 1, univ_cond, univ_size))
+ {
+ s--;
+ t = tmp;
+ for (n = 0; n < UNIV_MAX; n++)
+ if (*univ_name[n])
+ {
+ *t++ = ' ';
+#ifdef ATT_UNIV
+ *t++ = '1' + n;
+ *t++ = ':';
+#else
+ for (v = univ_name[n]; *t = *v++; t++);
+ *t++ = '%';
+#endif
+ for (v = (char*)buf; v < s; *t++ = *v++);
+ for (v = univ_name[n]; *t = *v++; t++);
+ for (v = s + univ_size; *t = *v++; t++);
+ }
+ t = tmp;
+ break;
+ }
+ }
+#endif
+ return(symlink(t, name));
+}
diff --git a/src/lib/libast/path/pathshell.c b/src/lib/libast/path/pathshell.c
new file mode 100644
index 0000000..f4b2557
--- /dev/null
+++ b/src/lib/libast/path/pathshell.c
@@ -0,0 +1,112 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * G. S. Fowler
+ * D. G. Korn
+ * AT&T Bell Laboratories
+ *
+ * shell library support
+ */
+
+#include <ast.h>
+#include <sys/stat.h>
+
+/*
+ * return pointer to the full path name of the shell
+ *
+ * SHELL is read from the environment and must start with /
+ *
+ * if set-uid or set-gid then the executable and its containing
+ * directory must not be owned by the real user/group
+ *
+ * root/administrator has its own test
+ *
+ * astconf("SH",NiL,NiL) is returned by default
+ *
+ * NOTE: csh is rejected because the bsh/csh differentiation is
+ * not done for `csh script arg ...'
+ */
+
+char*
+pathshell(void)
+{
+ register char* sh;
+ int ru;
+ int eu;
+ int rg;
+ int eg;
+ struct stat st;
+
+ static char* val;
+
+ if ((sh = getenv("SHELL")) && *sh == '/' && strmatch(sh, "*/(sh|*[!cC]sh)*([[:digit:]])?(-+([.[:alnum:]]))?(.exe)"))
+ {
+ if (!(ru = getuid()) || !eaccess("/bin", W_OK))
+ {
+ if (stat(sh, &st))
+ goto defshell;
+ if (ru != st.st_uid && !strmatch(sh, "?(/usr)?(/local)/?([ls])bin/?([[:lower:]])sh?(.exe)"))
+ goto defshell;
+ }
+ else
+ {
+ eu = geteuid();
+ rg = getgid();
+ eg = getegid();
+ if (ru != eu || rg != eg)
+ {
+ char* s;
+ char dir[PATH_MAX];
+
+ s = sh;
+ for (;;)
+ {
+ if (stat(s, &st))
+ goto defshell;
+ if (ru != eu && st.st_uid == ru)
+ goto defshell;
+ if (rg != eg && st.st_gid == rg)
+ goto defshell;
+ if (s != sh)
+ break;
+ if (strlen(s) >= sizeof(dir))
+ goto defshell;
+ strcpy(dir, s);
+ if (!(s = strrchr(dir, '/')))
+ break;
+ *s = 0;
+ s = dir;
+ }
+ }
+ }
+ return sh;
+ }
+ defshell:
+ if (!(sh = val))
+ {
+ if (!*(sh = astconf("SH", NiL, NiL)) || *sh != '/' || eaccess(sh, X_OK) || !(sh = strdup(sh)))
+ sh = "/bin/sh";
+ val = sh;
+ }
+ return sh;
+}
diff --git a/src/lib/libast/path/pathstat.c b/src/lib/libast/path/pathstat.c
new file mode 100644
index 0000000..6d414ca
--- /dev/null
+++ b/src/lib/libast/path/pathstat.c
@@ -0,0 +1,45 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <ls.h>
+#include <error.h>
+
+/*
+ * physical stat if logical fails
+ */
+
+int
+pathstat(const char* path, struct stat* st)
+{
+#if _lib_lstat
+ int oerrno;
+
+ oerrno = errno;
+ if (!stat(path, st)) return(0);
+ errno = oerrno;
+ return(lstat(path, st));
+#else
+ return(stat(path, st));
+#endif
+}
diff --git a/src/lib/libast/path/pathtemp.c b/src/lib/libast/path/pathtemp.c
new file mode 100644
index 0000000..844c86a
--- /dev/null
+++ b/src/lib/libast/path/pathtemp.c
@@ -0,0 +1,337 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Research
+ *
+ * generate a temp file / name
+ *
+ * [<dir>/][<pfx>]<bas>.<suf>
+ *
+ * length(<pfx>)<=5
+ * length(<bas>)==3
+ * length(<suf>)==3
+ *
+ * pathtmp(a,b,c,d) pathtemp(a,L_tmpnam,b,c,0)
+ * tmpfile() char*p=pathtemp(0,0,0,"tf",&sp);
+ * remove(p);
+ * free(p)
+ * tmpnam(0) static char p[L_tmpnam];
+ * pathtemp(p,sizeof(p),0,"tn",0)
+ * tmpnam(p) pathtemp(p,L_tmpnam,0,"tn",0)
+ * tempnam(d,p) pathtemp(0,d,p,0)
+ * mktemp(p) pathtemp(0,0,p,0)
+ *
+ * if buf==0 then space is malloc'd
+ * buf size is size
+ * dir and pfx may be 0
+ * if pfx contains trailing X's then it is a mktemp(3) template
+ * otherwise only first 5 chars of pfx are used
+ * if fdp!=0 then the path is opened O_EXCL and *fdp is the open fd
+ * malloc'd space returned by successful pathtemp() calls
+ * must be freed by the caller
+ *
+ * generated names are pseudo-randomized to avoid both
+ * collisions and predictions (same alg in sfio/sftmp.c)
+ *
+ * / as first pfx char provides tmp file generation control
+ * 0 returned for unknown ops
+ *
+ * /cycle dir specifies TMPPATH cycle control
+ * automatic (default) cycled with each tmp file
+ * manual cycled by application with dir=(nil)
+ * (nil) cycle TMPPATH
+ * /prefix dir specifies the default prefix (default ast)
+ * /private private file/dir modes
+ * /public public file/dir modes
+ * /seed dir specifies pseudo-random generator seed
+ * 0 or "0" to re-initialize
+ * /TMPPATH dir overrides the env value
+ * /TMPDIR dir overrides the env value
+ */
+
+#include <ast.h>
+#include <ls.h>
+#include <tv.h>
+#include <tm.h>
+
+#define ATTEMPT 10
+
+#define TMP_ENV "TMPDIR"
+#define TMP_PATH_ENV "TMPPATH"
+#define TMP1 "/tmp"
+#define TMP2 "/usr/tmp"
+
+#define VALID(d) (*(d)&&!eaccess(d,W_OK|X_OK))
+
+static struct
+{
+ mode_t mode;
+ char** vec;
+ char** dir;
+ uint32_t key;
+ uint32_t rng;
+ pid_t pid;
+ int manual;
+ int seed;
+ char* pfx;
+ char* tmpdir;
+ char* tmppath;
+} tmp = { S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH };
+
+char*
+pathtemp(char* buf, size_t len, const char* dir, const char* pfx, int* fdp)
+{
+ register char* d;
+ register char* b;
+ register char* s;
+ register char* x;
+ uint32_t key;
+ int m;
+ int n;
+ int l;
+ int r;
+ int z;
+ int attempt;
+ Tv_t tv;
+ char keybuf[16];
+
+ if (pfx && *pfx == '/')
+ {
+ pfx++;
+ if (streq(pfx, "cycle"))
+ {
+ if (!dir)
+ {
+ tmp.manual = 1;
+ if (tmp.dir && !*tmp.dir++)
+ tmp.dir = tmp.vec;
+ }
+ else
+ tmp.manual = streq(dir, "manual");
+ return (char*)pfx;
+ }
+ else if (streq(pfx, "prefix"))
+ {
+ if (tmp.pfx)
+ free(tmp.pfx);
+ tmp.pfx = dir ? strdup(dir) : (char*)0;
+ return (char*)pfx;
+ }
+ else if (streq(pfx, "private"))
+ {
+ tmp.mode = S_IRUSR|S_IWUSR;
+ return (char*)pfx;
+ }
+ else if (streq(pfx, "public"))
+ {
+ tmp.mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
+ return (char*)pfx;
+ }
+ else if (streq(pfx, "seed"))
+ {
+ tmp.key = (tmp.seed = (tmp.rng = dir ? (uint32_t)strtoul(dir, NiL, 0) : (uint32_t)1) != 0)? (uint32_t)0x63c63cd9L : 0;
+ return (char*)pfx;
+ }
+ else if (streq(pfx, TMP_ENV))
+ {
+ if (tmp.vec)
+ {
+ free(tmp.vec);
+ tmp.vec = 0;
+ }
+ if (tmp.tmpdir)
+ free(tmp.tmpdir);
+ tmp.tmpdir = dir ? strdup(dir) : (char*)0;
+ return (char*)pfx;
+ }
+ else if (streq(pfx, TMP_PATH_ENV))
+ {
+ if (tmp.vec)
+ {
+ free(tmp.vec);
+ tmp.vec = 0;
+ }
+ if (tmp.tmppath)
+ free(tmp.tmppath);
+ tmp.tmppath = dir ? strdup(dir) : (char*)0;
+ return (char*)pfx;
+ }
+ return 0;
+ }
+ if (tmp.seed)
+ tv.tv_nsec = 0;
+ else
+ tvgettime(&tv);
+ if (!(d = (char*)dir) || *d && eaccess(d, W_OK|X_OK))
+ {
+ if (!tmp.vec)
+ {
+ if ((x = tmp.tmppath) || (x = getenv(TMP_PATH_ENV)))
+ {
+ n = 2;
+ s = x;
+ while (s = strchr(s, ':'))
+ {
+ s++;
+ n++;
+ }
+ if (!(tmp.vec = newof(0, char*, n, strlen(x) + 1)))
+ return 0;
+ tmp.dir = tmp.vec;
+ x = strcpy((char*)(tmp.dir + n), x);
+ *tmp.dir++ = x;
+ while (x = strchr(x, ':'))
+ {
+ *x++ = 0;
+ if (!VALID(*(tmp.dir - 1)))
+ tmp.dir--;
+ *tmp.dir++ = x;
+ }
+ if (!VALID(*(tmp.dir - 1)))
+ tmp.dir--;
+ *tmp.dir = 0;
+ }
+ else
+ {
+ if (((d = tmp.tmpdir) || (d = getenv(TMP_ENV))) && !VALID(d))
+ d = 0;
+ if (!(tmp.vec = newof(0, char*, 2, d ? (strlen(d) + 1) : 0)))
+ return 0;
+ if (d)
+ *tmp.vec = strcpy((char*)(tmp.vec + 2), d);
+ }
+ tmp.dir = tmp.vec;
+ }
+ if (!(d = *tmp.dir++))
+ {
+ tmp.dir = tmp.vec;
+ d = *tmp.dir++;
+ }
+ if (!d && (!*(d = astconf("TMP", NiL, NiL)) || eaccess(d, W_OK|X_OK)) && eaccess(d = TMP1, W_OK|X_OK) && eaccess(d = TMP2, W_OK|X_OK))
+ return 0;
+ }
+ if (!len)
+ len = PATH_MAX;
+ len--;
+ if (!(b = buf) && !(b = newof(0, char, len, 1)))
+ return 0;
+ z = 0;
+ if (!pfx && !(pfx = tmp.pfx))
+ pfx = "ast";
+ m = strlen(pfx);
+ if (buf && dir && (buf == (char*)dir && (buf + strlen(buf) + 1) == (char*)pfx || buf == (char*)pfx && !*dir) && !strcmp((char*)pfx + m + 1, "XXXXX"))
+ {
+ d = (char*)dir;
+ len = m += strlen(d) + 8;
+ l = 3;
+ r = 3;
+ }
+ else if (*pfx && pfx[m - 1] == 'X')
+ {
+ for (l = m; l && pfx[l - 1] == 'X'; l--);
+ r = m - l;
+ m = l;
+ l = r / 2;
+ r -= l;
+ }
+ else if (strchr(pfx, '.'))
+ {
+ m = 5;
+ l = 3;
+ r = 3;
+ }
+ else
+ {
+ z = '.';
+ m = 5;
+ l = 2;
+ r = 3;
+ }
+ x = b + len;
+ s = b;
+ if (d)
+ {
+ while (s < x && (n = *d++))
+ *s++ = n;
+ if (s < x && s > b && *(s - 1) != '/')
+ *s++ = '/';
+ }
+ if ((x - s) > m)
+ x = s + m;
+ while (s < x && (n = *pfx++))
+ {
+ if (n == '/' || n == '\\' || n == z)
+ n = '_';
+ *s++ = n;
+ }
+ *s = 0;
+ len -= (s - b);
+ for (attempt = 0; attempt < ATTEMPT; attempt++)
+ {
+ if (!tmp.rng || !tmp.seed && (attempt || tmp.pid != getpid()))
+ {
+ register int r;
+
+ /*
+ * get a quasi-random coefficient
+ */
+
+ tmp.pid = getpid();
+ tmp.rng = (uint32_t)tmp.pid * ((uint32_t)time(NiL) ^ (((uint32_t)integralof(&attempt)) >> 3) ^ (((uint32_t)integralof(tmp.dir)) >> 3));
+ if (!tmp.key)
+ tmp.key = (tmp.rng >> 16) | ((tmp.rng & 0xffff) << 16);
+ tmp.rng ^= tmp.key;
+
+ /*
+ * Knuth vol.2, page.16, Thm.A
+ */
+
+ if ((r = (tmp.rng - 1) & 03))
+ tmp.rng += 4 - r;
+ }
+
+ /*
+ * generate a pseudo-random name
+ */
+
+ key = tmp.rng * tmp.key + tv.tv_nsec;
+ if (!tmp.seed)
+ tvgettime(&tv);
+ tmp.key = tmp.rng * key + tv.tv_nsec;
+ sfsprintf(keybuf, sizeof(keybuf), "%07.7.32I*u%07.7.32I*u", sizeof(key), key, sizeof(tmp.key), tmp.key);
+ sfsprintf(s, len, "%-.*s%s%-.*s", l, keybuf, z ? "." : "", r, keybuf + sizeof(keybuf) / 2);
+ if (fdp)
+ {
+ if ((n = open(b, O_CREAT|O_RDWR|O_EXCL|O_TEMPORARY, tmp.mode)) >= 0)
+ {
+ *fdp = n;
+ return b;
+ }
+ }
+ else if (access(b, F_OK))
+ return b;
+ }
+ if (!buf)
+ free(b);
+ return 0;
+}
diff --git a/src/lib/libast/path/pathtmp.c b/src/lib/libast/path/pathtmp.c
new file mode 100644
index 0000000..aac0243
--- /dev/null
+++ b/src/lib/libast/path/pathtmp.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * obsolete -- use pathtemp()
+ */
+
+#include <ast.h>
+#include <stdio.h>
+
+#ifndef L_tmpnam
+#define L_tmpnam 25
+#endif
+
+char*
+pathtmp(char* buf, const char* dir, const char* pfx, int* fdp)
+{
+ size_t len;
+
+ len = !buf ? 0 : !dir ? L_tmpnam : (strlen(dir) + 14);
+ return pathtemp(buf, len, dir, pfx, fdp);
+}
diff --git a/src/lib/libast/port/astconf.c b/src/lib/libast/port/astconf.c
new file mode 100644
index 0000000..ee199fa
--- /dev/null
+++ b/src/lib/libast/port/astconf.c
@@ -0,0 +1,1718 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * string interface to confstr(),pathconf(),sysconf(),sysinfo()
+ * extended to allow some features to be set per-process
+ */
+
+static const char id[] = "\n@(#)$Id: getconf (AT&T Research) 2011-05-18 $\0\n";
+
+#include "univlib.h"
+
+#include <ast.h>
+#include <error.h>
+#include <fs3d.h>
+#include <ctype.h>
+#include <regex.h>
+#include <proc.h>
+#include <ls.h>
+#include <sys/utsname.h>
+
+#include "conftab.h"
+#include "FEATURE/libpath"
+
+#ifndef DEBUG_astconf
+#define DEBUG_astconf 0
+#endif
+
+#ifndef _pth_getconf
+#undef ASTCONF_system
+#define ASTCONF_system 0
+#endif
+
+#if _sys_systeminfo
+# if !_lib_sysinfo
+# if _lib_systeminfo
+# define _lib_sysinfo 1
+# define sysinfo(a,b,c) systeminfo(a,b,c)
+# else
+# if _lib_syscall && _sys_syscall
+# include <sys/syscall.h>
+# if defined(SYS_systeminfo)
+# define _lib_sysinfo 1
+# define sysinfo(a,b,c) syscall(SYS_systeminfo,a,b,c)
+# endif
+# endif
+# endif
+# endif
+#else
+# undef _lib_sysinfo
+#endif
+
+#define CONF_ERROR (CONF_USER<<0)
+#define CONF_READONLY (CONF_USER<<1)
+#define CONF_ALLOC (CONF_USER<<2)
+#define CONF_GLOBAL (CONF_USER<<3)
+
+#define DEFAULT(o) ((state.std||!dynamic[o].ast)?dynamic[o].std:dynamic[o].ast)
+#define INITIALIZE() do{if(!state.data)synthesize(NiL,NiL,NiL);}while(0)
+#define STANDARD(v) (streq(v,"standard")||streq(v,"strict")||streq(v,"posix")||streq(v,"xopen"))
+
+#define MAXVAL 256
+
+#if MAXVAL <= UNIV_SIZE
+#undef MAXVAL
+#define MAXVAL (UNIV_SIZE+1)
+#endif
+
+#ifndef _UNIV_DEFAULT
+#define _UNIV_DEFAULT "att"
+#endif
+
+static char null[1];
+static char root[2] = "/";
+
+typedef struct Feature_s
+{
+ struct Feature_s*next;
+ const char* name;
+ char* value;
+ char* std;
+ char* ast;
+ short length;
+ short standard;
+ unsigned int flags;
+ short op;
+} Feature_t;
+
+typedef struct Lookup_s
+{
+ Conf_t* conf;
+ const char* name;
+ unsigned int flags;
+ short call;
+ short standard;
+ short section;
+} Lookup_t;
+
+static Feature_t dynamic[] =
+{
+#define OP_architecture 0
+ {
+ &dynamic[OP_architecture+1],
+ "ARCHITECTURE",
+ &null[0],
+ 0,
+ 0,
+ 12,
+ CONF_AST,
+ 0,
+ OP_architecture
+ },
+#define OP_conformance 1
+ {
+ &dynamic[OP_conformance+1],
+ "CONFORMANCE",
+ "ast",
+ "standard",
+ "ast",
+ 11,
+ CONF_AST,
+ 0,
+ OP_conformance
+ },
+#define OP_fs_3d 2
+ {
+ &dynamic[OP_fs_3d+1],
+ "FS_3D",
+ &null[0],
+ "0",
+ 0,
+ 5,
+ CONF_AST,
+ 0,
+ OP_fs_3d
+ },
+#define OP_getconf 3
+ {
+ &dynamic[OP_getconf+1],
+ "GETCONF",
+#ifdef _pth_getconf
+ _pth_getconf,
+#else
+ &null[0],
+#endif
+ 0,
+ 0,
+ 7,
+ CONF_AST,
+ CONF_READONLY,
+ OP_getconf
+ },
+#define OP_hosttype 4
+ {
+ &dynamic[OP_hosttype+1],
+ "HOSTTYPE",
+ HOSTTYPE,
+ 0,
+ 0,
+ 8,
+ CONF_AST,
+ CONF_READONLY,
+ OP_hosttype
+ },
+#define OP_libpath 5
+ {
+ &dynamic[OP_libpath+1],
+ "LIBPATH",
+#ifdef CONF_LIBPATH
+ CONF_LIBPATH,
+#else
+ &null[0],
+#endif
+ 0,
+ 0,
+ 7,
+ CONF_AST,
+ 0,
+ OP_libpath
+ },
+#define OP_libprefix 6
+ {
+ &dynamic[OP_libprefix+1],
+ "LIBPREFIX",
+#ifdef CONF_LIBPREFIX
+ CONF_LIBPREFIX,
+#else
+ "lib",
+#endif
+ 0,
+ 0,
+ 9,
+ CONF_AST,
+ 0,
+ OP_libprefix
+ },
+#define OP_libsuffix 7
+ {
+ &dynamic[OP_libsuffix+1],
+ "LIBSUFFIX",
+#ifdef CONF_LIBSUFFIX
+ CONF_LIBSUFFIX,
+#else
+ ".so",
+#endif
+ 0,
+ 0,
+ 9,
+ CONF_AST,
+ 0,
+ OP_libsuffix
+ },
+#define OP_path_attributes 8
+ {
+ &dynamic[OP_path_attributes+1],
+ "PATH_ATTRIBUTES",
+#if _WINIX
+ "c",
+#else
+ &null[0],
+#endif
+ &null[0],
+ 0,
+ 15,
+ CONF_AST,
+ CONF_READONLY,
+ OP_path_attributes
+ },
+#define OP_path_resolve 9
+ {
+ &dynamic[OP_path_resolve+1],
+ "PATH_RESOLVE",
+ &null[0],
+ "physical",
+ "metaphysical",
+ 12,
+ CONF_AST,
+ 0,
+ OP_path_resolve
+ },
+#define OP_universe 10
+ {
+ 0,
+ "UNIVERSE",
+ &null[0],
+ "att",
+ 0,
+ 8,
+ CONF_AST,
+ 0,
+ OP_universe
+ },
+ {
+ 0
+ }
+};
+
+typedef struct State_s
+{
+
+ const char* id;
+ const char* name;
+ const char* standard;
+ const char* strict;
+ Feature_t* features;
+
+ int std;
+
+ /* default initialization from here down */
+
+ int prefix;
+ int synthesizing;
+
+ char* data;
+ char* last;
+
+ Feature_t* recent;
+
+ Ast_confdisc_f notify;
+
+} State_t;
+
+static State_t state = { "getconf", "_AST_FEATURES", "CONFORMANCE = standard", "POSIXLY_CORRECT", dynamic, -1 };
+
+static char* feature(Feature_t*, const char*, const char*, const char*, unsigned int, Error_f);
+
+/*
+ * return fmtbuf() copy of s
+ */
+
+static char*
+buffer(char* s)
+{
+ return strcpy(fmtbuf(strlen(s) + 1), s);
+}
+
+/*
+ * synthesize state for fp
+ * fp==0 initializes from getenv(state.name)
+ * value==0 just does lookup
+ * otherwise state is set to value
+ */
+
+static char*
+synthesize(register Feature_t* fp, const char* path, const char* value)
+{
+ register char* s;
+ register char* d;
+ register char* v;
+ register char* p;
+ register int n;
+
+#if DEBUG_astconf
+ if (fp)
+ error(-2, "astconf synthesize name=%s path=%s value=%s fp=%p%s", fp->name, path, value, fp, state.synthesizing ? " SYNTHESIZING" : "");
+#endif
+ if (state.synthesizing)
+ return null;
+ if (!state.data)
+ {
+ char* se;
+ char* de;
+ char* ve;
+
+ state.prefix = strlen(state.name) + 1;
+ n = state.prefix + 3 * MAXVAL;
+ if ((s = getenv(state.name)) || getenv(state.strict) && (s = (char*)state.standard))
+ n += strlen(s) + 1;
+ n = roundof(n, 32);
+ if (!(state.data = newof(0, char, n, 0)))
+ return 0;
+ state.last = state.data + n - 1;
+ strcpy(state.data, state.name);
+ state.data += state.prefix - 1;
+ *state.data++ = '=';
+ if (s)
+ strcpy(state.data, s);
+ ve = state.data;
+ state.synthesizing = 1;
+ for (;;)
+ {
+ for (s = ve; isspace(*s); s++);
+ for (d = s; *d && !isspace(*d); d++);
+ for (se = d; isspace(*d); d++);
+ for (v = d; *v && !isspace(*v); v++);
+ for (de = v; isspace(*v); v++);
+ if (!*v)
+ break;
+ for (ve = v; *ve && !isspace(*ve); ve++);
+ if (*ve)
+ *ve = 0;
+ else
+ ve = 0;
+ *de = 0;
+ *se = 0;
+ feature(0, s, d, v, 0, 0);
+ *se = ' ';
+ *de = ' ';
+ if (!ve)
+ break;
+ *ve++ = ' ';
+ }
+ state.synthesizing = 0;
+ }
+ if (!fp)
+ return state.data;
+ if (!state.last)
+ {
+ if (!value)
+ return 0;
+ n = strlen(value);
+ goto ok;
+ }
+ s = (char*)fp->name;
+ n = fp->length;
+ d = state.data;
+ for (;;)
+ {
+ while (isspace(*d))
+ d++;
+ if (!*d)
+ break;
+ if (strneq(d, s, n) && isspace(d[n]))
+ {
+ if (!value)
+ {
+ for (d += n + 1; *d && !isspace(*d); d++);
+ for (; isspace(*d); d++);
+ for (s = d; *s && !isspace(*s); s++);
+ n = s - d;
+ value = (const char*)d;
+ goto ok;
+ }
+ for (s = p = d + n + 1; *s && !isspace(*s); s++);
+ for (; isspace(*s); s++);
+ for (v = s; *s && !isspace(*s); s++);
+ n = s - v;
+ if ((!path || *path == *p && strlen(path) == (v - p - 1) && !memcmp(path, p, v - p - 1)) && strneq(v, value, n))
+ goto ok;
+ for (; isspace(*s); s++);
+ if (*s)
+ for (; *d = *s++; d++);
+ else if (d != state.data)
+ d--;
+ break;
+ }
+ for (; *d && !isspace(*d); d++);
+ for (; isspace(*d); d++);
+ for (; *d && !isspace(*d); d++);
+ for (; isspace(*d); d++);
+ for (; *d && !isspace(*d); d++);
+ }
+ if (!value)
+ {
+ if (!fp->op)
+ {
+ if (fp->flags & CONF_ALLOC)
+ fp->value[0] = 0;
+ else
+ fp->value = null;
+ }
+ return 0;
+ }
+ if (!value[0])
+ value = "0";
+ if (!path || !path[0] || path[0] == '/' && !path[1])
+ path = "-";
+ n += strlen(path) + strlen(value) + 3;
+ if (d + n >= state.last)
+ {
+ int c;
+ int i;
+
+ i = d - state.data;
+ state.data -= state.prefix;
+ c = n + state.last - state.data + 3 * MAXVAL;
+ c = roundof(c, 32);
+ if (!(state.data = newof(state.data, char, c, 0)))
+ return 0;
+ state.last = state.data + c - 1;
+ state.data += state.prefix;
+ d = state.data + i;
+ }
+ if (d != state.data)
+ *d++ = ' ';
+ for (s = (char*)fp->name; *d = *s++; d++);
+ *d++ = ' ';
+ for (s = (char*)path; *d = *s++; d++);
+ *d++ = ' ';
+ for (s = (char*)value; *d = *s++; d++);
+#if DEBUG_astconf
+ error(-3, "astconf synthesize %s", state.data - state.prefix);
+#endif
+ setenviron(state.data - state.prefix);
+ if (state.notify)
+ (*state.notify)(NiL, NiL, state.data - state.prefix);
+ n = s - (char*)value - 1;
+ ok:
+ if (!(fp->flags & CONF_ALLOC))
+ fp->value = 0;
+ if (n == 1 && (*value == '0' || *value == '-'))
+ n = 0;
+ if (!(fp->value = newof(fp->value, char, n, 1)))
+ fp->value = null;
+ else
+ {
+ fp->flags |= CONF_ALLOC;
+ memcpy(fp->value, value, n);
+ fp->value[n] = 0;
+ }
+ return fp->value;
+}
+
+/*
+ * initialize the value for fp
+ * if command!=0 then it is checked for on $PATH
+ * synthesize(fp,path,succeed) called on success
+ * otherwise synthesize(fp,path,fail) called
+ */
+
+static void
+initialize(register Feature_t* fp, const char* path, const char* command, const char* succeed, const char* fail)
+{
+ register char* p;
+ register int ok = 1;
+
+#if DEBUG_astconf
+ error(-2, "astconf initialize name=%s path=%s command=%s succeed=%s fail=%s fp=%p%s", fp->name, path, command, succeed, fail, fp, state.synthesizing ? " SYNTHESIZING" : "");
+#endif
+ switch (fp->op)
+ {
+ case OP_architecture:
+ ok = 1;
+ break;
+ case OP_conformance:
+ ok = getenv(state.strict) != 0;
+ break;
+ case OP_hosttype:
+ ok = 1;
+ break;
+ case OP_path_attributes:
+ ok = 1;
+ break;
+ case OP_path_resolve:
+ ok = fs3d(FS3D_TEST);
+ break;
+ case OP_universe:
+ ok = streq(_UNIV_DEFAULT, DEFAULT(OP_universe));
+ /*FALLTHROUGH...*/
+ default:
+ if (p = getenv("PATH"))
+ {
+ register int r = 1;
+ register char* d = p;
+ Sfio_t* tmp;
+
+#if DEBUG_astconf
+ error(-2, "astconf initialize name=%s ok=%d PATH=%s", fp->name, ok, p);
+#endif
+ if (tmp = sfstropen())
+ {
+ for (;;)
+ {
+ switch (*p++)
+ {
+ case 0:
+ break;
+ case ':':
+ if (command && fp->op != OP_universe)
+ {
+ if (r = p - d - 1)
+ {
+ sfwrite(tmp, d, r);
+ sfputc(tmp, '/');
+ sfputr(tmp, command, 0);
+ if ((d = sfstruse(tmp)) && !eaccess(d, X_OK))
+ {
+ ok = 1;
+ if (fp->op != OP_universe)
+ break;
+ }
+ }
+ d = p;
+ }
+ r = 1;
+ continue;
+ case '/':
+ if (r)
+ {
+ r = 0;
+ if (fp->op == OP_universe)
+ {
+ if (p[0] == 'u' && p[1] == 's' && p[2] == 'r' && p[3] == '/')
+ for (p += 4; *p == '/'; p++);
+ if (p[0] == 'b' && p[1] == 'i' && p[2] == 'n')
+ {
+ for (p += 3; *p == '/'; p++);
+ if (!*p || *p == ':')
+ break;
+ }
+ }
+ }
+ if (fp->op == OP_universe)
+ {
+ if (strneq(p, "xpg", 3) || strneq(p, "5bin", 4))
+ {
+ ok = 1;
+ break;
+ }
+ if (strneq(p, "bsd", 3) || strneq(p, "ucb", 3))
+ {
+ ok = 0;
+ break;
+ }
+ }
+ continue;
+ default:
+ r = 0;
+ continue;
+ }
+ break;
+ }
+ sfclose(tmp);
+ }
+ else
+ ok = 1;
+ }
+ break;
+ }
+#if DEBUG_astconf
+ error(-1, "AHA#%d state.std=%d %s [%s] std=%s ast=%s value=%s ok=%d", __LINE__, state.std, fp->name, ok ? succeed : fail, fp->std, fp->ast, fp->value, ok);
+#endif
+ synthesize(fp, path, ok ? succeed : fail);
+}
+
+/*
+ * format synthesized value
+ */
+
+static char*
+format(register Feature_t* fp, const char* path, const char* value, unsigned int flags, Error_f conferror)
+{
+ register Feature_t* sp;
+ register int n;
+#if _UWIN && ( _X86_ || _X64_ )
+ struct stat st;
+#else
+ static struct utsname uts;
+#endif
+
+#if DEBUG_astconf
+ error(-2, "astconf format name=%s path=%s value=%s flags=%04x fp=%p%s", fp->name, path, value, flags, fp, state.synthesizing ? " SYNTHESIZING" : "");
+#endif
+ if (value)
+ fp->flags &= ~CONF_GLOBAL;
+ else if (fp->flags & CONF_GLOBAL)
+ return fp->value;
+ switch (fp->op)
+ {
+
+ case OP_architecture:
+#if _UWIN && ( _X86_ || _X64_ )
+ if (!stat("/", &st))
+ {
+ if (st.st_ino == 64)
+ {
+ fp->value = "x64";
+ break;
+ }
+ if (st.st_ino == 32)
+ {
+ fp->value = "x86";
+ break;
+ }
+ }
+#if _X64_
+ fp->value = "x64";
+#else
+ fp->value = "x86";
+#endif
+#else
+ if (!uname(&uts))
+ return fp->value = uts.machine;
+ if (!(fp->value = getenv("HOSTNAME")))
+ fp->value = "unknown";
+#endif
+ break;
+
+ case OP_conformance:
+ if (value && STANDARD(value))
+ value = fp->std;
+ state.std = streq(fp->value, fp->std);
+#if DEBUG_astconf
+ error(-1, "AHA#%d state.std=%d %s [%s] std=%s ast=%s value=%s", __LINE__, state.std, fp->name, value, fp->std, fp->ast, fp->value);
+#endif
+ if (state.synthesizing && value == (char*)fp->std)
+ fp->value = (char*)value;
+ else if (!synthesize(fp, path, value))
+ initialize(fp, path, NiL, fp->std, fp->value);
+#if DEBUG_astconf
+ error(-1, "AHA#%d state.std=%d %s [%s] std=%s ast=%s value=%s", __LINE__, state.std, fp->name, value, fp->std, fp->ast, fp->value);
+#endif
+ if (!state.std && value == fp->std)
+ {
+ state.std = 1;
+ for (sp = state.features; sp; sp = sp->next)
+ if (sp->std && sp->op && sp->op != OP_conformance)
+ feature(sp, 0, path, sp->std, 0, 0);
+ }
+#if DEBUG_astconf
+ error(-1, "AHA#%d state.std=%d %s [%s] std=%s ast=%s value=%s", __LINE__, state.std, fp->name, value, fp->std, fp->ast, fp->value);
+#endif
+ break;
+
+ case OP_fs_3d:
+ fp->value = fs3d(value ? value[0] ? FS3D_ON : FS3D_OFF : FS3D_TEST) ? "1" : null;
+ break;
+
+ case OP_hosttype:
+ break;
+
+ case OP_path_attributes:
+#ifdef _PC_PATH_ATTRIBUTES
+ {
+ register char* s;
+ register char* e;
+ intmax_t v;
+
+ /*
+ * _PC_PATH_ATTRIBUTES is a bitmap for 'a' to 'z'
+ */
+
+ if ((v = pathconf(path, _PC_PATH_ATTRIBUTES)) == -1L)
+ return 0;
+ s = fp->value;
+ e = s + sizeof(fp->value) - 1;
+ for (n = 'a'; n <= 'z'; n++)
+ if (v & (1 << (n - 'a')))
+ {
+ *s++ = n;
+ if (s >= e)
+ break;
+ }
+ *s = 0;
+ }
+#endif
+ break;
+
+ case OP_path_resolve:
+ if (state.synthesizing && value == (char*)fp->std)
+ fp->value = (char*)value;
+ else if (!synthesize(fp, path, value))
+ initialize(fp, path, NiL, "logical", DEFAULT(OP_path_resolve));
+ break;
+
+ case OP_universe:
+#if _lib_universe
+ if (getuniverse(fp->value) < 0)
+ strcpy(fp->value, DEFAULT(OP_universe));
+ if (value)
+ setuniverse(value);
+#else
+#ifdef UNIV_MAX
+ n = 0;
+ if (value)
+ {
+ while (n < univ_max && !streq(value, univ_name[n]))
+ n++;
+ if (n >= univ_max)
+ {
+ if (conferror)
+ (*conferror)(&state, &state, 2, "%s: %s: universe value too large", fp->name, value);
+ return 0;
+ }
+ }
+#ifdef ATT_UNIV
+ n = setuniverse(n + 1);
+ if (!value && n > 0)
+ setuniverse(n);
+#else
+ n = universe(value ? n + 1 : U_GET);
+#endif
+ if (n <= 0 || n >= univ_max)
+ n = 1;
+ strcpy(fp->value, univ_name[n - 1]);
+#else
+ if (value && streq(path, "="))
+ {
+ if (state.synthesizing)
+ {
+ if (!(fp->flags & CONF_ALLOC))
+ fp->value = 0;
+ n = strlen(value);
+ if (!(fp->value = newof(fp->value, char, n, 1)))
+ fp->value = null;
+ else
+ {
+ fp->flags |= CONF_ALLOC;
+ memcpy(fp->value, value, n);
+ fp->value[n] = 0;
+ }
+ }
+ else
+ synthesize(fp, path, value);
+ }
+ else
+ initialize(fp, path, "echo", DEFAULT(OP_universe), "ucb");
+#endif
+#endif
+ break;
+
+ default:
+ if (state.synthesizing && value == (char*)fp->std)
+ fp->value = (char*)value;
+ else
+ synthesize(fp, path, value);
+ break;
+
+ }
+ if (streq(path, "="))
+ fp->flags |= CONF_GLOBAL;
+ return fp->value;
+}
+
+/*
+ * value==0 get feature name
+ * value!=0 set feature name
+ * 0 returned if error or not defined; otherwise previous value
+ */
+
+static char*
+feature(register Feature_t* fp, const char* name, const char* path, const char* value, unsigned int flags, Error_f conferror)
+{
+ register int n;
+
+ if (value && (streq(value, "-") || streq(value, "0")))
+ value = null;
+ if (!fp)
+ for (fp = state.features; fp && !streq(fp->name, name); fp = fp->next);
+#if DEBUG_astconf
+ error(-2, "astconf feature name=%s path=%s value=%s flags=%04x fp=%p%s", name, path, value, flags, fp, state.synthesizing ? " SYNTHESIZING" : "");
+#endif
+ if (!fp)
+ {
+ if (!value)
+ return 0;
+ if (state.notify && !(*state.notify)(name, path, value))
+ return 0;
+ n = strlen(name);
+ if (!(fp = newof(0, Feature_t, 1, n + 1)))
+ {
+ if (conferror)
+ (*conferror)(&state, &state, 2, "%s: out of space", name);
+ return 0;
+ }
+ fp->op = -1;
+ fp->name = (const char*)fp + sizeof(Feature_t);
+ strcpy((char*)fp->name, name);
+ fp->length = n;
+ fp->std = &null[0];
+ fp->next = state.features;
+ state.features = fp;
+ }
+ else if (value)
+ {
+ if (fp->flags & CONF_READONLY)
+ {
+ if (conferror)
+ (*conferror)(&state, &state, 2, "%s: cannot set readonly symbol", fp->name);
+ return 0;
+ }
+ if (state.notify && !streq(fp->value, value) && !(*state.notify)(name, path, value))
+ return 0;
+ }
+ else
+ state.recent = fp;
+ return format(fp, path, value, flags, conferror);
+}
+
+/*
+ * binary search for name in conf[]
+ */
+
+static int
+lookup(register Lookup_t* look, const char* name, unsigned int flags)
+{
+ register Conf_t* mid = (Conf_t*)conf;
+ register Conf_t* lo = mid;
+ register Conf_t* hi = mid + conf_elements;
+ register int v;
+ register int c;
+ char* e;
+ const Prefix_t* p;
+
+ static Conf_t num;
+
+ look->flags = 0;
+ look->call = -1;
+ look->standard = (flags & ASTCONF_AST) ? CONF_AST : -1;
+ look->section = -1;
+ while (*name == '_')
+ name++;
+ again:
+ for (p = prefix; p < &prefix[prefix_elements]; p++)
+ if (strneq(name, p->name, p->length) && ((c = name[p->length] == '_' || name[p->length] == '(' || name[p->length] == '#') || (v = isdigit(name[p->length]) && name[p->length + 1] == '_')))
+ {
+ if (p->call < 0)
+ {
+ if (look->standard >= 0)
+ break;
+ look->standard = p->standard;
+ }
+ else
+ {
+ if (look->call >= 0)
+ break;
+ look->call = p->call;
+ }
+ if (name[p->length] == '(' || name[p->length] == '#')
+ {
+ look->conf = &num;
+ strlcpy((char*)num.name, name, sizeof(num.name));
+ num.call = p->call;
+ num.flags = *name == 'C' ? CONF_STRING : 0;
+ num.op = (short)strtol(name + p->length + 1, &e, 10);
+ if (name[p->length] == '(' && *e == ')')
+ e++;
+ if (*e)
+ break;
+ return 1;
+ }
+ name += p->length + c;
+ if (look->section < 0 && !c && v)
+ {
+ look->section = name[0] - '0';
+ name += 2;
+ }
+ goto again;
+ }
+#if HUH_2006_02_10
+ if (look->section < 0)
+ look->section = 1;
+#endif
+ look->name = name;
+#if DEBUG_astconf
+ error(-2, "astconf normal name=%s standard=%d section=%d call=%d flags=%04x elements=%d", look->name, look->standard, look->section, look->call, flags, conf_elements);
+#endif
+ c = *((unsigned char*)name);
+ while (lo <= hi)
+ {
+ mid = lo + (hi - lo) / 2;
+#if DEBUG_astconf
+ error(-3, "astconf lookup name=%s mid=%s", name, mid->name);
+#endif
+ if (!(v = c - *((unsigned char*)mid->name)) && !(v = strcmp(name, mid->name)))
+ {
+ hi = mid;
+ lo = (Conf_t*)conf;
+ do
+ {
+ if ((look->standard < 0 || look->standard == mid->standard) &&
+ (look->section < 0 || look->section == mid->section) &&
+ (look->call < 0 || look->call == mid->call))
+ goto found;
+ } while (mid-- > lo && streq(mid->name, look->name));
+ mid = hi;
+ hi = lo + conf_elements - 1;
+ while (++mid < hi && streq(mid->name, look->name))
+ {
+ if ((look->standard < 0 || look->standard == mid->standard) &&
+ (look->section < 0 || look->section == mid->section) &&
+ (look->call < 0 || look->call == mid->call))
+ goto found;
+ }
+ break;
+ }
+ else if (v > 0)
+ lo = mid + 1;
+ else
+ hi = mid - 1;
+ }
+ return 0;
+ found:
+ if (look->call < 0 && look->standard >= 0 && (look->section <= 1 || (mid->flags & CONF_MINMAX)))
+ look->flags |= CONF_MINMAX;
+ look->conf = mid;
+#if DEBUG_astconf
+ error(-2, "astconf lookup name=%s standard=%d:%d section=%d:%d call=%d:%d", look->name, look->standard, mid->standard, look->section, mid->section, look->call, mid->call);
+#endif
+ return 1;
+}
+
+/*
+ * return a tolower'd copy of s
+ */
+
+static char*
+fmtlower(register const char* s)
+{
+ register int c;
+ register char* t;
+ char* b;
+
+ b = t = fmtbuf(strlen(s) + 1);
+ while (c = *s++)
+ {
+ if (isupper(c))
+ c = tolower(c);
+ *t++ = c;
+ }
+ *t = 0;
+ return b;
+}
+
+/*
+ * print value line for p
+ * if !name then value prefixed by "p->name="
+ * if (flags & CONF_MINMAX) then default minmax value used
+ */
+
+static char*
+print(Sfio_t* sp, register Lookup_t* look, const char* name, const char* path, int listflags, Error_f conferror)
+{
+ register Conf_t* p = look->conf;
+ register unsigned int flags = look->flags;
+ Feature_t* fp;
+ char* call;
+ char* f;
+ const char* s;
+ int i;
+ int n;
+ int olderrno;
+ int drop;
+ int defined;
+ intmax_t v;
+ char buf[PATH_MAX];
+ char flg[16];
+
+ if (!name && !(p->flags & CONF_STRING) && (p->flags & (CONF_FEATURE|CONF_LIMIT|CONF_MINMAX)) && (p->flags & (CONF_LIMIT|CONF_PREFIXED)) != CONF_LIMIT)
+ flags |= CONF_PREFIXED;
+ olderrno = errno;
+ errno = 0;
+#if DEBUG_astconf
+ error(-1, "astconf name=%s:%s:%s standard=%d section=%d call=%s op=%d flags=|%s%s%s%s%s:|%s%s%s%s%s%s%s%s%s%s"
+ , name, look->name, p->name, p->standard, p->section, prefix[p->call + CONF_call].name, p->op
+ , (flags & CONF_FEATURE) ? "FEATURE|" : ""
+ , (flags & CONF_LIMIT) ? "LIMIT|" : ""
+ , (flags & CONF_MINMAX) ? "MINMAX|" : ""
+ , (flags & CONF_PREFIXED) ? "PREFIXED|" : ""
+ , (flags & CONF_STRING) ? "STRING|" : ""
+ , (p->flags & CONF_DEFER_CALL) ? "DEFER_CALL|" : ""
+ , (p->flags & CONF_DEFER_MM) ? "DEFER_MM|" : ""
+ , (p->flags & CONF_FEATURE) ? "FEATURE|" : ""
+ , (p->flags & CONF_LIMIT_DEF) ? "LIMIT_DEF|" : (p->flags & CONF_LIMIT) ? "LIMIT|" : ""
+ , (p->flags & CONF_MINMAX_DEF) ? "MINMAX_DEF|" : (p->flags & CONF_MINMAX) ? "MINMAX|" : ""
+ , (p->flags & CONF_NOUNDERSCORE) ? "NOUNDERSCORE|" : ""
+ , (p->flags & CONF_PREFIXED) ? "PREFIXED|" : ""
+ , (p->flags & CONF_PREFIX_ONLY) ? "PREFIX_ONLY|" : ""
+ , (p->flags & CONF_STANDARD) ? "STANDARD|" : ""
+ , (p->flags & CONF_STRING) ? "STRING|" : ""
+ , (p->flags & CONF_UNDERSCORE) ? "UNDERSCORE|" : ""
+ );
+#endif
+ flags |= CONF_LIMIT_DEF|CONF_MINMAX_DEF;
+ if (conferror && name)
+ {
+ if ((p->flags & CONF_PREFIX_ONLY) && look->standard < 0)
+ goto bad;
+ if (!(flags & CONF_MINMAX) || !(p->flags & CONF_MINMAX))
+ {
+ switch (p->call)
+ {
+ case CONF_pathconf:
+ if (path == root)
+ {
+ (*conferror)(&state, &state, 2, "%s: path expected", name);
+ goto bad;
+ }
+ break;
+ default:
+ if (path != root)
+ {
+ (*conferror)(&state, &state, 2, "%s: path not expected", name);
+ goto bad;
+ }
+ break;
+ }
+#ifdef _pth_getconf
+ if (p->flags & CONF_DEFER_CALL)
+ goto bad;
+#endif
+ }
+ else
+ {
+ if (path != root)
+ {
+ (*conferror)(&state, &state, 2, "%s: path not expected", name);
+ goto bad;
+ }
+#ifdef _pth_getconf
+ if ((p->flags & CONF_DEFER_MM) || !(p->flags & CONF_MINMAX_DEF))
+ goto bad;
+#endif
+ }
+ if (look->standard >= 0 && (name[0] != '_' && ((p->flags & CONF_UNDERSCORE) || look->section <= 1) || name[0] == '_' && (p->flags & CONF_NOUNDERSCORE)) || look->standard < 0 && name[0] == '_')
+ goto bad;
+ }
+ s = 0;
+ defined = 1;
+ switch (i = (p->op < 0 || (flags & CONF_MINMAX) && (p->flags & CONF_MINMAX_DEF)) ? 0 : p->call)
+ {
+ case CONF_confstr:
+ call = "confstr";
+#if _lib_confstr
+ if (!(v = confstr(p->op, buf, sizeof(buf))))
+ {
+ defined = 0;
+ v = -1;
+ errno = EINVAL;
+ }
+ else if (v > 0)
+ {
+ buf[sizeof(buf) - 1] = 0;
+ s = (const char*)buf;
+ }
+ else
+ defined = 0;
+ break;
+#else
+ goto predef;
+#endif
+ case CONF_pathconf:
+ call = "pathconf";
+#if _lib_pathconf
+ if ((v = pathconf(path, p->op)) < 0)
+ defined = 0;
+ break;
+#else
+ goto predef;
+#endif
+ case CONF_sysconf:
+ call = "sysconf";
+#if _lib_sysconf
+ if ((v = sysconf(p->op)) < 0)
+ defined = 0;
+ break;
+#else
+ goto predef;
+#endif
+ case CONF_sysinfo:
+ call = "sysinfo";
+#if _lib_sysinfo
+ if ((v = sysinfo(p->op, buf, sizeof(buf))) >= 0)
+ {
+ buf[sizeof(buf) - 1] = 0;
+ s = (const char*)buf;
+ }
+ else
+ defined = 0;
+ break;
+#else
+ goto predef;
+#endif
+ default:
+ call = "synthesis";
+ errno = EINVAL;
+ v = -1;
+ defined = 0;
+ break;
+ case 0:
+ call = 0;
+ if (p->standard == CONF_AST)
+ {
+ if (streq(p->name, "RELEASE") && (i = open("/proc/version", O_RDONLY)) >= 0)
+ {
+ n = read(i, buf, sizeof(buf) - 1);
+ close(i);
+ if (n > 0 && buf[n - 1] == '\n')
+ n--;
+ if (n > 0 && buf[n - 1] == '\r')
+ n--;
+ buf[n] = 0;
+ if (buf[0])
+ {
+ v = 0;
+ s = buf;
+ break;
+ }
+ }
+ }
+ if (p->flags & CONF_MINMAX_DEF)
+ {
+ if (!((p->flags & CONF_LIMIT_DEF)))
+ flags |= CONF_MINMAX;
+ listflags &= ~ASTCONF_system;
+ }
+ predef:
+ if (look->standard == CONF_AST)
+ {
+ if (streq(p->name, "VERSION"))
+ {
+ v = ast.version;
+ break;
+ }
+ }
+ if (flags & CONF_MINMAX)
+ {
+ if ((p->flags & CONF_MINMAX_DEF) && (!(listflags & ASTCONF_system) || !(p->flags & CONF_DEFER_MM)))
+ {
+ v = p->minmax.number;
+ s = p->minmax.string;
+ break;
+ }
+ }
+ else if ((p->flags & CONF_LIMIT_DEF) && (!(listflags & ASTCONF_system) || !(p->flags & CONF_DEFER_CALL)))
+ {
+ v = p->limit.number;
+ s = p->limit.string;
+ break;
+ }
+ flags &= ~(CONF_LIMIT_DEF|CONF_MINMAX_DEF);
+ v = -1;
+ errno = EINVAL;
+ defined = 0;
+ break;
+ }
+ if (!defined)
+ {
+ if (!errno)
+ {
+ if ((p->flags & CONF_FEATURE) || !(p->flags & (CONF_LIMIT|CONF_MINMAX)))
+ flags &= ~(CONF_LIMIT_DEF|CONF_MINMAX_DEF);
+ }
+ else if (flags & CONF_PREFIXED)
+ flags &= ~(CONF_LIMIT_DEF|CONF_MINMAX_DEF);
+ else if (errno != EINVAL || !i)
+ {
+ if (!sp)
+ {
+ if (conferror)
+ {
+ if (call)
+ (*conferror)(&state, &state, ERROR_SYSTEM|2, "%s: %s error", p->name, call);
+ else if (!(listflags & ASTCONF_system))
+ (*conferror)(&state, &state, 2, "%s: unknown name", p->name);
+ }
+ goto bad;
+ }
+ else
+ {
+ flags &= ~(CONF_LIMIT_DEF|CONF_MINMAX_DEF);
+ flags |= CONF_ERROR;
+ }
+ }
+ }
+ errno = olderrno;
+ if ((listflags & ASTCONF_defined) && !(flags & (CONF_LIMIT_DEF|CONF_MINMAX_DEF)))
+ goto bad;
+ if ((drop = !sp) && !(sp = sfstropen()))
+ goto bad;
+ if (listflags & ASTCONF_table)
+ {
+ f = flg;
+ if (p->flags & CONF_DEFER_CALL)
+ *f++ = 'C';
+ if (p->flags & CONF_DEFER_MM)
+ *f++ = 'D';
+ if (p->flags & CONF_FEATURE)
+ *f++ = 'F';
+ if (p->flags & CONF_LIMIT)
+ *f++ = 'L';
+ if (p->flags & CONF_MINMAX)
+ *f++ = 'M';
+ if (p->flags & CONF_NOSECTION)
+ *f++ = 'N';
+ if (p->flags & CONF_PREFIXED)
+ *f++ = 'P';
+ if (p->flags & CONF_STANDARD)
+ *f++ = 'S';
+ if (p->flags & CONF_UNDERSCORE)
+ *f++ = 'U';
+ if (p->flags & CONF_NOUNDERSCORE)
+ *f++ = 'V';
+ if (p->flags & CONF_PREFIX_ONLY)
+ *f++ = 'W';
+ if (f == flg)
+ *f++ = 'X';
+ *f = 0;
+ sfprintf(sp, "%*s %*s %d %2s %4d %6s ", sizeof(p->name), p->name, sizeof(prefix[p->standard].name), prefix[p->standard].name, p->section, prefix[p->call + CONF_call].name, p->op, flg);
+ if (p->flags & CONF_LIMIT_DEF)
+ {
+ if (p->limit.string)
+ sfprintf(sp, "L[%s] ", (listflags & ASTCONF_quote) ? fmtquote(p->limit.string, "\"", "\"", strlen(p->limit.string), FMT_SHELL) : p->limit.string);
+ else
+ sfprintf(sp, "L[%I*d] ", sizeof(p->limit.number), p->limit.number);
+ }
+ if (p->flags & CONF_MINMAX_DEF)
+ {
+ if (p->minmax.string)
+ sfprintf(sp, "M[%s] ", (listflags & ASTCONF_quote) ? fmtquote(p->minmax.string, "\"", "\"", strlen(p->minmax.string), FMT_SHELL) : p->minmax.string);
+ else
+ sfprintf(sp, "M[%I*d] ", sizeof(p->minmax.number), p->minmax.number);
+ }
+ if (flags & CONF_ERROR)
+ sfprintf(sp, "error");
+ else if (defined)
+ {
+ if (s)
+ sfprintf(sp, "%s", (listflags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s);
+ else if (v != -1)
+ sfprintf(sp, "%I*d", sizeof(v), v);
+ else
+ sfprintf(sp, "%I*u", sizeof(v), v);
+ }
+ sfprintf(sp, "\n");
+ }
+ else
+ {
+ if (!(flags & CONF_PREFIXED) || (listflags & ASTCONF_base))
+ {
+ if (!name)
+ {
+ if ((p->flags & (CONF_PREFIXED|CONF_STRING)) == (CONF_PREFIXED|CONF_STRING) && (!(listflags & ASTCONF_base) || p->standard != CONF_POSIX))
+ {
+ if ((p->flags & CONF_UNDERSCORE) && !(listflags & ASTCONF_base))
+ sfprintf(sp, "_");
+ sfprintf(sp, "%s", (listflags & ASTCONF_lower) ? fmtlower(prefix[p->standard].name) : prefix[p->standard].name);
+ if (p->section > 1)
+ sfprintf(sp, "%d", p->section);
+ sfprintf(sp, "_");
+ }
+ sfprintf(sp, "%s=", (listflags & ASTCONF_lower) ? fmtlower(p->name) : p->name);
+ }
+ if (flags & CONF_ERROR)
+ sfprintf(sp, "error");
+ else if (defined)
+ {
+ if (s)
+ sfprintf(sp, "%s", (listflags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s);
+ else if (v != -1)
+ sfprintf(sp, "%I*d", sizeof(v), v);
+ else
+ sfprintf(sp, "%I*u", sizeof(v), v);
+ }
+ else
+ sfprintf(sp, "undefined");
+ if (!name)
+ sfprintf(sp, "\n");
+ }
+ if (!name && !(listflags & ASTCONF_base) && !(p->flags & CONF_STRING) && (p->flags & (CONF_FEATURE|CONF_MINMAX)))
+ {
+ if (p->flags & CONF_UNDERSCORE)
+ sfprintf(sp, "_");
+ sfprintf(sp, "%s", (listflags & ASTCONF_lower) ? fmtlower(prefix[p->standard].name) : prefix[p->standard].name);
+ if (p->section > 1)
+ sfprintf(sp, "%d", p->section);
+ sfprintf(sp, "_%s=", (listflags & ASTCONF_lower) ? fmtlower(p->name) : p->name);
+ if (v != -1)
+ sfprintf(sp, "%I*d", sizeof(v), v);
+ else if (defined)
+ sfprintf(sp, "%I*u", sizeof(v), v);
+ else
+ sfprintf(sp, "undefined");
+ sfprintf(sp, "\n");
+ }
+ }
+ if (drop)
+ {
+ if (call = sfstruse(sp))
+ call = buffer(call);
+ else
+ call = "[ out of space ]";
+ sfclose(sp);
+ return call;
+ }
+ bad:
+ if (!(listflags & ~(ASTCONF_error|ASTCONF_system)))
+ for (fp = state.features; fp; fp = fp->next)
+ if (streq(name, fp->name))
+ return format(fp, path, 0, listflags, conferror);
+ return (listflags & ASTCONF_error) ? (char*)0 : null;
+}
+
+/*
+ * return read stream to native getconf utility
+ */
+
+static Sfio_t*
+nativeconf(Proc_t** pp, const char* operand)
+{
+#ifdef _pth_getconf
+ Sfio_t* sp;
+ char* cmd[3];
+ long ops[2];
+
+#if DEBUG_astconf
+ error(-2, "astconf defer %s %s", _pth_getconf, operand);
+#endif
+ cmd[0] = (char*)state.id;
+ cmd[1] = (char*)operand;
+ cmd[2] = 0;
+ ops[0] = PROC_FD_DUP(open("/dev/null",O_WRONLY,0), 2, PROC_FD_CHILD);
+ ops[1] = 0;
+ if (*pp = procopen(_pth_getconf, cmd, environ, ops, PROC_READ))
+ {
+ if (sp = sfnew(NiL, NiL, SF_UNBOUND, (*pp)->rfd, SF_READ))
+ {
+ sfdisc(sp, SF_POPDISC);
+ return sp;
+ }
+ procclose(*pp);
+ }
+#endif
+ return 0;
+}
+
+/*
+ * value==0 gets value for name
+ * value!=0 sets value for name and returns previous value
+ * path==0 implies path=="/"
+ *
+ * settable return values are in permanent store
+ * non-settable return values copied to a tmp fmtbuf() buffer
+ *
+ * if (streq(astgetconf("PATH_RESOLVE", NiL, NiL, 0, 0), "logical"))
+ * our_way();
+ *
+ * universe = astgetconf("UNIVERSE", NiL, "att", 0, 0);
+ * astgetconf("UNIVERSE", NiL, universe, 0, 0);
+ *
+ * if (flags&ASTCONF_error)!=0 then error return value is 0
+ * otherwise 0 not returned
+ */
+
+#define ALT 16
+
+char*
+astgetconf(const char* name, const char* path, const char* value, int flags, Error_f conferror)
+{
+ register char* s;
+ int n;
+ Lookup_t look;
+ Sfio_t* tmp;
+
+#if __OBSOLETE__ < 20080101
+ if (pointerof(flags) == (void*)errorf)
+ {
+ conferror = errorf;
+ flags = ASTCONF_error;
+ }
+ else if (conferror && conferror != errorf)
+ conferror = 0;
+#endif
+ if (!name)
+ {
+ if (path)
+ return null;
+ if (!(name = value))
+ {
+ if (state.data)
+ {
+ Ast_confdisc_f notify;
+
+#if _HUH20000515 /* doesn't work for shell builtins */
+ free(state.data - state.prefix);
+#endif
+ state.data = 0;
+ notify = state.notify;
+ state.notify = 0;
+ INITIALIZE();
+ state.notify = notify;
+ }
+ return null;
+ }
+ value = 0;
+ }
+ INITIALIZE();
+ if (!path)
+ path = root;
+ if (state.recent && streq(name, state.recent->name) && (s = format(state.recent, path, value, flags, conferror)))
+ return s;
+ if (lookup(&look, name, flags))
+ {
+ if (value)
+ {
+ ro:
+ errno = EINVAL;
+ if (conferror)
+ (*conferror)(&state, &state, 2, "%s: cannot set value", name);
+ return (flags & ASTCONF_error) ? (char*)0 : null;
+ }
+ return print(NiL, &look, name, path, flags, conferror);
+ }
+ if ((n = strlen(name)) > 3 && n < (ALT + 3))
+ {
+ if (streq(name + n - 3, "DEV"))
+ {
+ if (tmp = sfstropen())
+ {
+ sfprintf(tmp, "/dev/");
+ for (s = (char*)name; s < (char*)name + n - 3; s++)
+ sfputc(tmp, isupper(*s) ? tolower(*s) : *s);
+ if ((s = sfstruse(tmp)) && !access(s, F_OK))
+ {
+ if (value)
+ goto ro;
+ s = buffer(s);
+ sfclose(tmp);
+ return s;
+ }
+ sfclose(tmp);
+ }
+ }
+ else if (streq(name + n - 3, "DIR"))
+ {
+ Lookup_t altlook;
+ char altname[ALT];
+
+ static const char* dirs[] = { "/usr/lib", "/usr", null };
+
+ strcpy(altname, name);
+ altname[n - 3] = 0;
+ if (lookup(&altlook, altname, flags))
+ {
+ if (value)
+ {
+ errno = EINVAL;
+ if (conferror)
+ (*conferror)(&state, &state, 2, "%s: cannot set value", altname);
+ return (flags & ASTCONF_error) ? (char*)0 : null;
+ }
+ return print(NiL, &altlook, altname, path, flags, conferror);
+ }
+ for (s = altname; *s; s++)
+ if (isupper(*s))
+ *s = tolower(*s);
+ if (tmp = sfstropen())
+ {
+ for (n = 0; n < elementsof(dirs); n++)
+ {
+ sfprintf(tmp, "%s/%s/.", dirs[n], altname);
+ if ((s = sfstruse(tmp)) && !access(s, F_OK))
+ {
+ if (value)
+ goto ro;
+ s = buffer(s);
+ sfclose(tmp);
+ return s;
+ }
+ }
+ sfclose(tmp);
+ }
+ }
+ }
+ if ((look.standard < 0 || look.standard == CONF_AST) && look.call <= 0 && look.section <= 1 && (s = feature(0, look.name, path, value, flags, conferror)))
+ return s;
+ errno = EINVAL;
+ if (conferror && !(flags & ASTCONF_system))
+ (*conferror)(&state, &state, 2, "%s: unknown name", name);
+ return (flags & ASTCONF_error) ? (char*)0 : null;
+}
+
+/*
+ * astconf() never returns 0
+ */
+
+char*
+astconf(const char* name, const char* path, const char* value)
+{
+ return astgetconf(name, path, value, 0, 0);
+}
+
+/*
+ * set discipline function to be called when features change
+ * old discipline function returned
+ */
+
+Ast_confdisc_f
+astconfdisc(Ast_confdisc_f new_notify)
+{
+ Ast_confdisc_f old_notify;
+
+ INITIALIZE();
+ old_notify = state.notify;
+ state.notify = new_notify;
+ return old_notify;
+}
+
+/*
+ * list all name=value entries on sp
+ * path==0 implies path=="/"
+ */
+
+void
+astconflist(Sfio_t* sp, const char* path, int flags, const char* pattern)
+{
+ char* s;
+ char* f;
+ char* call;
+ Feature_t* fp;
+ Lookup_t look;
+ regex_t re;
+ regdisc_t redisc;
+ int olderrno;
+ char flg[8];
+#ifdef _pth_getconf_a
+ Proc_t* proc;
+ Sfio_t* pp;
+#endif
+
+ INITIALIZE();
+ if (!path)
+ path = root;
+ else if (access(path, F_OK))
+ {
+ errorf(&state, &state, 2, "%s: not found", path);
+ return;
+ }
+ olderrno = errno;
+ look.flags = 0;
+ if (!(flags & (ASTCONF_read|ASTCONF_write|ASTCONF_parse)))
+ flags |= ASTCONF_read|ASTCONF_write;
+ else if (flags & ASTCONF_parse)
+ flags |= ASTCONF_write;
+ if (!(flags & (ASTCONF_matchcall|ASTCONF_matchname|ASTCONF_matchstandard)))
+ pattern = 0;
+ if (pattern)
+ {
+ memset(&redisc, 0, sizeof(redisc));
+ redisc.re_version = REG_VERSION;
+ redisc.re_errorf = (regerror_t)errorf;
+ re.re_disc = &redisc;
+ if (regcomp(&re, pattern, REG_DISCIPLINE|REG_EXTENDED|REG_LENIENT|REG_NULL))
+ return;
+ }
+ if (flags & ASTCONF_read)
+ {
+ for (look.conf = (Conf_t*)conf; look.conf < (Conf_t*)&conf[conf_elements]; look.conf++)
+ {
+ if (pattern)
+ {
+ if (flags & ASTCONF_matchcall)
+ {
+ if (regexec(&re, prefix[look.conf->call + CONF_call].name, 0, NiL, 0))
+ continue;
+ }
+ else if (flags & ASTCONF_matchname)
+ {
+ if (regexec(&re, look.conf->name, 0, NiL, 0))
+ continue;
+ }
+ else if (flags & ASTCONF_matchstandard)
+ {
+ if (regexec(&re, prefix[look.conf->standard].name, 0, NiL, 0))
+ continue;
+ }
+ }
+ look.standard = look.conf->standard;
+ look.section = look.conf->section;
+ print(sp, &look, NiL, path, flags, errorf);
+ }
+#ifdef _pth_getconf_a
+ if (pp = nativeconf(&proc, _pth_getconf_a))
+ {
+ call = "GC";
+ while (f = sfgetr(pp, '\n', 1))
+ {
+ for (s = f; *s && *s != '=' && *s != ':' && !isspace(*s); s++);
+ if (*s)
+ for (*s++ = 0; isspace(*s); s++);
+ if (!lookup(&look, f, flags))
+ {
+ if (flags & ASTCONF_table)
+ {
+ if (look.standard < 0)
+ look.standard = 0;
+ if (look.section < 1)
+ look.section = 1;
+ sfprintf(sp, "%*s %*s %d %2s %4d %5s %s\n", sizeof(conf[0].name), f, sizeof(prefix[look.standard].name), prefix[look.standard].name, look.section, call, 0, "N", s);
+ }
+ else if (flags & ASTCONF_parse)
+ sfprintf(sp, "%s %s - %s\n", state.id, f, s);
+ else
+ sfprintf(sp, "%s=%s\n", f, (flags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s);
+ }
+ }
+ sfclose(pp);
+ procclose(proc);
+ }
+#endif
+ }
+ if (flags & ASTCONF_write)
+ {
+ call = "AC";
+ for (fp = state.features; fp; fp = fp->next)
+ {
+ if (pattern)
+ {
+ if (flags & ASTCONF_matchcall)
+ {
+ if (regexec(&re, call, 0, NiL, 0))
+ continue;
+ }
+ else if (flags & ASTCONF_matchname)
+ {
+ if (regexec(&re, fp->name, 0, NiL, 0))
+ continue;
+ }
+ else if (flags & ASTCONF_matchstandard)
+ {
+ if (regexec(&re, prefix[fp->standard].name, 0, NiL, 0))
+ continue;
+ }
+ }
+ if (!(s = feature(fp, 0, path, NiL, 0, 0)) || !*s)
+ s = "0";
+ if (flags & ASTCONF_table)
+ {
+ f = flg;
+ if (fp->flags & CONF_ALLOC)
+ *f++ = 'A';
+ if (fp->flags & CONF_READONLY)
+ *f++ = 'R';
+ if (f == flg)
+ *f++ = 'X';
+ *f = 0;
+ sfprintf(sp, "%*s %*s %d %2s %4d %5s %s\n", sizeof(conf[0].name), fp->name, sizeof(prefix[fp->standard].name), prefix[fp->standard].name, 1, call, 0, flg, s);
+ }
+ else if (flags & ASTCONF_parse)
+ sfprintf(sp, "%s %s - %s\n", state.id, (flags & ASTCONF_lower) ? fmtlower(fp->name) : fp->name, fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL));
+ else
+ sfprintf(sp, "%s=%s\n", (flags & ASTCONF_lower) ? fmtlower(fp->name) : fp->name, (flags & ASTCONF_quote) ? fmtquote(s, "\"", "\"", strlen(s), FMT_SHELL) : s);
+ }
+ }
+ if (pattern)
+ regfree(&re);
+ errno = olderrno;
+}
diff --git a/src/lib/libast/port/astcopy.c b/src/lib/libast/port/astcopy.c
new file mode 100644
index 0000000..853eb9a
--- /dev/null
+++ b/src/lib/libast/port/astcopy.c
@@ -0,0 +1,90 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * copy from rfd to wfd (with conditional mmap hacks)
+ */
+
+#include <ast.h>
+#include <ast_mmap.h>
+
+#if _mmap_worthy > 1
+
+#include <ls.h>
+
+#define MAPSIZE (1024*256)
+
+#endif
+
+#undef BUFSIZ
+#define BUFSIZ 4096
+
+/*
+ * copy n bytes from rfd to wfd
+ * actual byte count returned
+ * if n<=0 then ``good'' size is used
+ */
+
+off_t
+astcopy(int rfd, int wfd, off_t n)
+{
+ register off_t c;
+#ifdef MAPSIZE
+ off_t pos;
+ off_t mapsize;
+ char* mapbuf;
+ struct stat st;
+#endif
+
+ static int bufsiz;
+ static char* buf;
+
+ if (n <= 0 || n >= BUFSIZ * 2)
+ {
+#if MAPSIZE
+ if (!fstat(rfd, &st) && S_ISREG(st.st_mode) && (pos = lseek(rfd, (off_t)0, 1)) != ((off_t)-1))
+ {
+ if (pos >= st.st_size) return(0);
+ mapsize = st.st_size - pos;
+ if (mapsize > MAPSIZE) mapsize = (mapsize > n && n > 0) ? n : MAPSIZE;
+ if (mapsize >= BUFSIZ * 2 && (mapbuf = (char*)mmap(NiL, mapsize, PROT_READ, MAP_SHARED, rfd, pos)) != ((caddr_t)-1))
+ {
+ if (write(wfd, mapbuf, mapsize) != mapsize || lseek(rfd, mapsize, 1) == ((off_t)-1)) return(-1);
+ munmap((caddr_t)mapbuf, mapsize);
+ return(mapsize);
+ }
+ }
+#endif
+ if (n <= 0) n = BUFSIZ;
+ }
+ if (n > bufsiz)
+ {
+ if (buf) free(buf);
+ bufsiz = roundof(n, BUFSIZ);
+ if (!(buf = newof(0, char, bufsiz, 0))) return(-1);
+ }
+ if ((c = read(rfd, buf, (size_t)n)) > 0 && write(wfd, buf, (size_t)c) != c) c = -1;
+ return(c);
+}
diff --git a/src/lib/libast/port/astdynamic.c b/src/lib/libast/port/astdynamic.c
new file mode 100644
index 0000000..c3035a8
--- /dev/null
+++ b/src/lib/libast/port/astdynamic.c
@@ -0,0 +1,132 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * ast dynamic data initialization
+ */
+
+#ifdef _UWIN
+
+#define _std_def_cfree 1
+
+#include <sfio_t.h>
+#include <ast.h>
+
+#undef strcoll
+
+#include <ast_windows.h>
+
+extern Sfio_t _Sfstdin;
+extern Sfio_t _Sfstdout;
+extern Sfio_t _Sfstderr;
+
+#include "sfhdr.h"
+
+#undef sfstdin
+#undef sfstdout
+#undef sfstderr
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+/*
+ * for backward compatibility with early UNIX
+ */
+
+extern void
+cfree(void* addr)
+{
+ free(addr);
+}
+
+extern void
+_ast_libinit(void* in, void* out, void* err)
+{
+ Sfio_t* sp;
+
+ sp = (Sfio_t*)in;
+ *sp = _Sfstdin;
+ sfstdin = sp;
+ sp = (Sfio_t*)out;
+ *sp = _Sfstdout;
+ sfstdout = sp;
+ sp = (Sfio_t*)err;
+ *sp = _Sfstderr;
+ sfstderr = sp;
+}
+
+extern void
+_ast_init(void)
+{
+ struct _astdll* ap = _ast_getdll();
+
+ _ast_libinit(ap->_ast_stdin,ap->_ast_stdout,ap->_ast_stderr);
+}
+
+extern void
+_ast_exit(void)
+{
+ if (_Sfcleanup)
+ (*_Sfcleanup)();
+}
+
+BOOL WINAPI
+DllMain(HINSTANCE hinst, DWORD reason, VOID* reserved)
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ break;
+ case DLL_PROCESS_DETACH:
+ _ast_exit();
+ break;
+ }
+ return 1;
+}
+
+#else
+
+#include <ast.h>
+
+#if _dll_data_intercept && ( _DLL_BLD || _BLD_DLL )
+
+#undef environ
+
+extern char** environ;
+
+struct _astdll _ast_dll = { &environ };
+
+struct _astdll*
+_ast_getdll(void)
+{
+ return &_ast_dll;
+}
+
+#else
+
+NoN(astdynamic)
+
+#endif
+
+#endif
diff --git a/src/lib/libast/port/astlicense.c b/src/lib/libast/port/astlicense.c
new file mode 100644
index 0000000..913e9ca
--- /dev/null
+++ b/src/lib/libast/port/astlicense.c
@@ -0,0 +1,1292 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * generate a license comment -- see proto(1)
+ *
+ * NOTE: coded for minimal library dependence
+ * not so for the legal department
+ */
+
+#ifndef _PPLIB_H
+#include <ast.h>
+#include <time.h>
+#endif
+
+#undef copy
+#undef BSD /* guess who defines this */
+#undef END
+#undef INLINE
+#undef TEST
+#undef VERBOSE
+
+#define NONE 0
+#define INLINE 1
+#define TEST 2
+#define VERBOSE 3
+#define USAGE 4
+#define OPEN 5
+#define CPL 6
+#define EPL 7
+#define BSD 8
+#define ZLIB 9
+#define MIT 10
+#define GPL 11
+#define SPECIAL 12
+#define NONEXCLUSIVE 13
+#define NONCOMMERCIAL 14
+#define PROPRIETARY 15
+
+#define AUTHOR 0
+#define CLASS 1
+#define COMPANY 2
+#define COMPONENT 3
+#define CONTRIBUTOR 4
+#define CORPORATION 5
+#define DOMAIN 6
+#define ID 7
+#define INCORPORATION 8
+#define LICENSE 9
+#define LOCATION 10
+#define NAME 11
+#define NOTICE 12
+#define ORGANIZATION 13
+#define PACKAGE 14
+#define PARENT 15
+#define QUERY 16
+#define SINCE 17
+#define SOURCE 18
+#define START 19
+#define STYLE 20
+#define URL 21
+#define URLMD5 22
+#define VERSION 23
+
+#define IDS 64
+
+#define COMDATA 70
+#define COMLINE (COMDATA+4)
+#define COMLONG (COMDATA-32)
+#define COMMENT(x,b,s,u) comment(x,b,s,sizeof(s)-1,u)
+
+#define PUT(b,c) (((b)->nxt<(b)->end)?(*(b)->nxt++=(c)):((c),(-1)))
+#define BUF(b) ((b)->buf)
+#define USE(b) ((b)->siz=(b)->nxt-(b)->buf,(b)->nxt=(b)->buf,(b)->siz)
+#define SIZ(b) ((b)->nxt-(b)->buf)
+#define END(b) (*((b)->nxt>=(b)->end?((b)->nxt=(b)->end-1):(b)->nxt)=0,(b)->nxt-(b)->buf)
+
+#ifndef NiL
+#define NiL ((char*)0)
+#endif
+
+typedef struct Buffer_s
+{
+ char* buf;
+ char* nxt;
+ char* end;
+ int siz;
+} Buffer_t;
+
+typedef struct Item_s
+{
+ char* data;
+ int size;
+ int quote;
+} Item_t;
+
+typedef struct Id_s
+{
+ Item_t name;
+ Item_t value;
+} Id_t;
+
+/*
+ * NOTE: key[] element order must match the corresponding macro
+ */
+
+#define KEY(s) {s,sizeof(s)-1,0}
+
+static const Item_t key[] =
+{
+ KEY("author"),
+ KEY("class"),
+ KEY("company"),
+ KEY("component"),
+ KEY("contributor"),
+ KEY("corporation"),
+ KEY("domain"),
+ KEY("id"),
+ KEY("incorporation"),
+ KEY("license"),
+ KEY("location"),
+ KEY("name"),
+ KEY("notice"),
+ KEY("organization"),
+ KEY("package"),
+ KEY("parent"),
+ KEY("query"),
+ KEY("since"),
+ KEY("source"),
+ KEY("start"),
+ KEY("type"),
+ KEY("url"),
+ KEY("urlmd5"),
+ KEY("version"),
+ {0}
+};
+
+#define ITEMS (sizeof(key)/sizeof(key[0])-1)
+
+#define LIC(s,c) {s,sizeof(s)-1,c}
+
+static const Item_t lic[] =
+{
+ LIC("none", NONE),
+ LIC("inline", SPECIAL),
+ LIC("test", TEST),
+ LIC("verbose", VERBOSE),
+ LIC("usage", USAGE),
+ LIC("open", OPEN),
+ LIC("cpl", OPEN),
+ LIC("epl", OPEN),
+ LIC("bsd", OPEN),
+ LIC("zlib", OPEN),
+ LIC("mit", OPEN),
+ LIC("gpl", GPL),
+ LIC("special", SPECIAL),
+ LIC("nonexclusive", SPECIAL),
+ LIC("noncommercial", SPECIAL),
+ LIC("proprietary", PROPRIETARY),
+ {0}
+};
+
+typedef struct Notice_s
+{
+ int test;
+ int type;
+ int verbose;
+ int ids;
+ Item_t item[ITEMS];
+ Id_t id[IDS];
+ char cc[3];
+} Notice_t;
+
+/*
+ * return index given <name,size>
+ */
+
+static int
+lookup(register const Item_t* item, const char* name, int size)
+{
+ register int c;
+ register int i;
+
+ c = name[0];
+ for (i = 0; item[i].data; i++)
+ if (c == item[i].data[0] && size == item[i].size && !strncmp(name, item[i].data, size))
+ return i;
+ return -1;
+}
+
+/*
+ * copy s of size n to b
+ * n<0 means 0 terminated string
+ */
+
+static void
+copy(register Buffer_t* b, register char* s, int n)
+{
+ if (n < 0)
+ n = strlen(s);
+ while (n--)
+ PUT(b, *s++);
+}
+
+/*
+ * center and copy comment line s to p
+ * if s==0 then
+ * n>0 first frame line
+ * n=0 blank line
+ * n<0 last frame line
+ * if u>0 then s converted to upper case
+ * if u<0 then s is left justified
+ */
+
+static void
+comment(Notice_t* notice, register Buffer_t* b, register char* s, register int n, int u)
+{
+ register int i;
+ register int m;
+ register int x;
+ int cc;
+
+ cc = notice->cc[1];
+ if (!s)
+ {
+ if (n)
+ {
+ PUT(b, notice->cc[n > 0 ? 0 : 1]);
+ for (i = 0; i < COMDATA; i++)
+ PUT(b, cc);
+ PUT(b, notice->cc[n > 0 ? 1 : 2]);
+ }
+ else
+ s = "";
+ }
+ if (s)
+ {
+ if (n > COMDATA)
+ n = COMDATA;
+ PUT(b, cc);
+ m = (u < 0) ? 1 : (COMDATA - n) / 2;
+ if ((x = COMDATA - m - n) < 0)
+ n--;
+ while (m-- > 0)
+ PUT(b, ' ');
+ while (n-- > 0)
+ {
+ i = *s++;
+ if (u > 0 && i >= 'a' && i <= 'z')
+ i = i - 'a' + 'A';
+ PUT(b, i);
+ }
+ while (x-- > 0)
+ PUT(b, ' ');
+ PUT(b, cc);
+ }
+ PUT(b, '\n');
+}
+
+/*
+ * expand simple ${...}
+ */
+
+static void
+expand(Notice_t* notice, register Buffer_t* b, const Item_t* item)
+{
+ register char* t;
+ register char* e;
+ register int q;
+ register char* x;
+ register char* z;
+ register int c;
+ int m;
+ int i;
+ int k;
+
+ if (t = item->data)
+ {
+ q = item->quote;
+ e = t + item->size;
+ i = 0;
+ while (t < e)
+ {
+ if (*t == '$' && t < (e + 2) && *(t + 1) == '{')
+ {
+ k = m = 0;
+ x = t += 2;
+ while (t < e && (c = *t++) != '}')
+ if (c == '.')
+ x = t;
+ else if (c == '-')
+ {
+ k = 1;
+ break;
+ }
+ else if (c == '/')
+ {
+ m = 1;
+ break;
+ }
+ if ((c = lookup(key, x, t - x - 1)) >= 0 && (x = notice->item[c].data))
+ {
+ z = x + notice->item[c].size;
+ while (x < z)
+ {
+ c = *x++;
+ if (!m || c >= '0' && c <= '9')
+ PUT(b, c);
+ }
+ }
+ else if (k)
+ {
+ k = 0;
+ i++;
+ }
+ if (k || m)
+ {
+ k = 1;
+ while (t < e)
+ if ((c = *t++) == '{')
+ k++;
+ else if (c == '}' && !--k)
+ break;
+ }
+ }
+ else if (q > 0 && *t == '\\' && (*(t + 1) == q || *(t + 1) == '\\'))
+ t++;
+ else if (*t == '}' && i)
+ {
+ t++;
+ i--;
+ }
+ else
+ PUT(b, *t++);
+ }
+ }
+}
+
+/*
+ * generate a copright notice
+ */
+
+static void
+copyright(Notice_t* notice, register Buffer_t* b)
+{
+ register char* x;
+ register char* t;
+ time_t clock;
+
+ copy(b, "Copyright (c) ", -1);
+ if (notice->test)
+ clock = (time_t)1000212300;
+ else if (!(t = notice->item[SOURCE].data))
+ {
+ time(&clock);
+ t = ctime(&clock) + 20;
+ }
+ if ((x = notice->item[START].data) && strncmp(t, x, 4) < 0)
+ t = x;
+ if ((x = notice->item[SINCE].data) && strncmp(x, t, 4) < 0)
+ {
+ expand(notice, b, &notice->item[SINCE]);
+ PUT(b, '-');
+ }
+ copy(b, t, 4);
+ if (notice->item[PARENT].data)
+ {
+ PUT(b, ' ');
+ expand(notice, b, &notice->item[PARENT]);
+ }
+ if (notice->item[CORPORATION].data)
+ {
+ PUT(b, ' ');
+ expand(notice, b, &notice->item[CORPORATION]);
+ if (notice->item[INCORPORATION].data)
+ {
+ PUT(b, ' ');
+ expand(notice, b, &notice->item[INCORPORATION]);
+ }
+ }
+ else if (notice->item[COMPANY].data)
+ {
+ PUT(b, ' ');
+ expand(notice, b, &notice->item[COMPANY]);
+ }
+}
+
+typedef struct Stack_s
+{
+ char* info;
+ char* file;
+ int line;
+ int size;
+} Stack_t;
+
+static int
+push(Stack_t* sp, char* file, char* parent, char* info, int size, Buffer_t* buf)
+{
+ char* s;
+ char* t;
+ int i;
+ int n;
+ char path[1024];
+
+ if (size <= 8)
+ {
+ copy(buf, file, -1);
+ copy(buf, ": no space", -1);
+ PUT(buf, 0);
+ return -1;
+ }
+ if (*file != '/' && parent && (s = strrchr(parent, '/')))
+ {
+ n = s - parent + 1;
+ if ((strlen(file) + n + 1) <= sizeof(path))
+ {
+ memcpy(path, parent, n);
+ strcpy(path + n, file);
+ file = path;
+ }
+ }
+ if ((i = open(file, O_RDONLY)) < 0)
+ {
+ /* this hack viewpath lookup works for default package setups */
+ if (file == path)
+ for (s = path; *s; s++)
+ if (s[0] == '/' && s[1] == 'a' && s[2] == 'r' && s[3] == 'c' && s[4] == 'h' && s[5] == '/')
+ {
+ t = s;
+ for (s += 6; *s && *s != '/'; s++);
+ while (*t++ = *s++);
+ i = open(file, O_RDONLY);
+ }
+ if (i < 0)
+ {
+ copy(buf, file, -1);
+ copy(buf, ": cannot open", -1);
+ PUT(buf, 0);
+ return -1;
+ }
+ }
+ n = read(i, info, size - 1);
+ close(i);
+ if (n < 0)
+ {
+ copy(buf, file, -1);
+ copy(buf, ": cannot read", -1);
+ PUT(buf, 0);
+ return -1;
+ }
+ info[n++] = 0;
+ sp->file = file;
+ sp->info = info;
+ sp->line = 0;
+ sp->size = n;
+ return 0;
+}
+
+/*
+ * read the license file and generate a comment in p, length size
+ * license length in p returned, -1 on error
+ * -1 return places 0 terminated error string in p
+ */
+
+int
+astlicense(char* p, int size, char* file, char* options, int cc1, int cc2, int cc3)
+{
+ register char* s;
+ register char* v;
+ register char* x;
+ register int c;
+ int i;
+ int h;
+ int k;
+ int n;
+ int q;
+ int contributor;
+ int first;
+ int level;
+ int quote;
+ char* data;
+ char tmpbuf[COMLINE];
+ char info[8 * 1024];
+ Stack_t input[4];
+ Notice_t notice;
+ Item_t item;
+ Buffer_t buf;
+ Buffer_t tmp;
+
+ buf.end = (buf.buf = buf.nxt = p) + size;
+ tmp.end = (tmp.buf = tmp.nxt = tmpbuf) + sizeof(tmpbuf);
+ level = 0;
+ data = info;
+ level = -1;
+ if (options)
+ {
+ level++;
+ input[level].file = "<options>";
+ input[level].info = options;
+ input[level].line = 0;
+ }
+ if (file && *file)
+ {
+ if (push(&input[++level], file, 0, data, &info[sizeof(info)] - data, &buf))
+ return -1;
+ data += input[level].size;
+ }
+ if (level < 0)
+ return 0;
+ s = input[level].info;
+ notice.test = 0;
+ notice.type = NONE;
+ notice.verbose = 0;
+ notice.ids = 0;
+ notice.cc[0] = cc1;
+ notice.cc[1] = cc2;
+ notice.cc[2] = cc3;
+ for (i = 0; i < ITEMS; i++)
+ notice.item[i].data = 0;
+ notice.item[STYLE] = notice.item[CLASS] = lic[notice.type];
+ notice.item[STYLE].quote = notice.item[CLASS].quote = 0;
+ contributor = i = k = 0;
+ for (;;)
+ {
+ first = 1;
+ while (c = *s)
+ {
+ while (c == ' ' || c == '\t' || c == '\n' && ++input[level].line || c == '\r' || c == ',' || c == ';' || c == ')')
+ c = *++s;
+ if (!c)
+ break;
+ if (c == '#')
+ {
+ while (*++s && *s != '\n');
+ if (*s)
+ s++;
+ input[level].line++;
+ continue;
+ }
+ if (c == '.')
+ {
+ while ((c = *++s) && (c == ' ' || c == '\t'));
+ file = s;
+ while (c && c != ' ' && c != '\t' && c != '\r' && c != '\n')
+ c = *++s;
+ *s = 0;
+ while (c && c != '\n')
+ c = *++s;
+ if (*file)
+ {
+ input[level].info = s + (c != 0);
+ if (++level >= (sizeof(input) / sizeof(input[0])) || push(&input[level], file, input[level-1].file, data, &info[sizeof(info)] - data, &buf))
+ return -1;
+ data += input[level].size;
+ s = input[level].info;
+ }
+ continue;
+ }
+ if (c == '\n')
+ {
+ s++;
+ input[level].line++;
+ continue;
+ }
+ if (c == '[')
+ c = *++s;
+ x = s;
+ n = 0;
+ while (c && c != '+' && c != '=' && c != ']' && c != ')' && c != ',' && c != ' ' && c != '\t' && c != '\n' && c != '\r')
+ c = *++s;
+ n = s - x;
+ h = lookup(key, x, n);
+ if (c == '+' || c == ']')
+ c = *++s;
+ quote = 0;
+ if (c == '=' || first)
+ {
+ if (c == '=')
+ {
+ q = ((c = *++s) == '"' || c == '\'') ? *s++ : 0;
+ if (c == '(')
+ {
+ s++;
+ if (h == LICENSE)
+ contributor = 0;
+ else if (h == CONTRIBUTOR)
+ contributor = 1;
+ else
+ {
+ q = 1;
+ i = 0;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ s--;
+ break;
+ case '(':
+ if (!i)
+ q++;
+ continue;
+ case ')':
+ if (!i && !--q)
+ break;
+ continue;
+ case '"':
+ case '\'':
+ if (!i)
+ i = *(s - 1);
+ else if (i == *(s - 1))
+ i = 0;
+ continue;
+ case '\\':
+ if (*s == i && i == '"')
+ i++;
+ continue;
+ case '\n':
+ input[level].line++;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ }
+ continue;
+ }
+ v = s;
+ while ((c = *s) && (q == '"' && (c == '\\' && (*(s + 1) == '"' || *(s + 1) == '\\') && s++ && (quote = q)) || q && c != q || !q && c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != ',' && c != ';'))
+ {
+ if (c == '\n')
+ input[level].line++;
+ s++;
+ }
+ }
+ else
+ {
+ h = STYLE;
+ v = x;
+ }
+ if (c == '\n')
+ input[level].line++;
+ if (contributor)
+ {
+ for (i = 0; i < notice.ids; i++)
+ if (n == notice.id[i].name.size && !strncmp(x, notice.id[i].name.data, n))
+ break;
+ if (i < IDS)
+ {
+ notice.id[i].name.data = x;
+ notice.id[i].name.size = n;
+ notice.id[i].name.quote = 0;
+ notice.id[i].value.data = v;
+ notice.id[i].value.size = s - v;
+ notice.id[i].value.quote = quote;
+ if (notice.ids <= i)
+ notice.ids = i + 1;
+ }
+ }
+ else if (h == QUERY)
+ {
+ if ((s - v) == 3 && v[0] == 'a' && v[1] == 'l' && v[2] == 'l')
+ {
+ for (i = 0; i < ITEMS; i++)
+ if (notice.item[i].size)
+ {
+ expand(&notice, &buf, &key[i]);
+ PUT(&buf, '=');
+ for (h = 0;; h++)
+ if (h >= notice.item[i].size)
+ {
+ h = 0;
+ break;
+ }
+ else if (notice.item[i].data[h] == ' ' || notice.item[i].data[h] == '\t')
+ break;
+ if (h)
+ PUT(&buf, '\'');
+ expand(&notice, &buf, &notice.item[i]);
+ if (h)
+ PUT(&buf, '\'');
+ PUT(&buf, '\n');
+ }
+ }
+ else
+ {
+ if ((h = lookup(key, v, s - v)) < 0)
+ {
+ item.data = v;
+ item.size = s - v;
+ item.quote = 0;
+ expand(&notice, &buf, &item);
+ }
+ else
+ expand(&notice, &buf, &notice.item[h]);
+ PUT(&buf, '\n');
+ }
+ return END(&buf);
+ }
+ else
+ {
+ if (h == STYLE)
+ switch (c = lookup(lic, v, s - v))
+ {
+ case NONE:
+ return 0;
+ case TEST:
+ notice.test = 1;
+ h = -1;
+ break;
+ case VERBOSE:
+ notice.verbose = 1;
+ h = -1;
+ break;
+ case USAGE:
+ notice.type = c;
+ h = -1;
+ break;
+ case -1:
+ c = SPECIAL;
+ /*FALLTHROUGH*/
+ default:
+ notice.type = c;
+ notice.item[CLASS].data = lic[lic[c].quote].data;
+ notice.item[CLASS].size = lic[lic[c].quote].size;
+ if (notice.item[STYLE].data != lic[NONE].data)
+ h = -1;
+ break;
+ }
+ if (h >= 0)
+ {
+ notice.item[h].data = (notice.item[h].size = s - v) ? v : (char*)0;
+ notice.item[h].quote = quote;
+ k = 1;
+ }
+ }
+ }
+ else
+ {
+ if (input[level].file)
+ {
+ copy(&buf, "\"", -1);
+ copy(&buf, input[level].file, -1);
+ copy(&buf, "\", line ", -1);
+ x = &tmpbuf[sizeof(tmpbuf)];
+ *--x = 0;
+ n = ++input[level].line;
+ do *--x = ("0123456789")[n % 10]; while (n /= 10);
+ copy(&buf, x, -1);
+ copy(&buf, ": ", -1);
+ }
+ copy(&buf, "option error: assignment expected", -1);
+ PUT(&buf, 0);
+ return -1;
+ }
+ if (*s)
+ s++;
+ first = 0;
+ }
+ if (!level--)
+ break;
+ s = input[level].info;
+ }
+ if (!k)
+ return 0;
+ if (notice.type == INLINE && (!notice.verbose || !notice.item[NOTICE].data))
+ return 0;
+ if (notice.type != USAGE)
+ {
+ if (!notice.type)
+ notice.type = SPECIAL;
+ comment(&notice, &buf, NiL, 1, 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ if (notice.item[PACKAGE].data)
+ {
+ copy(&tmp, "This software is part of the ", -1);
+ expand(&notice, &tmp, &notice.item[PACKAGE]);
+ copy(&tmp, " package", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ if (notice.type >= OPEN)
+ {
+ copyright(&notice, &tmp);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.type >= SPECIAL)
+ COMMENT(&notice, &buf, "All Rights Reserved", 0);
+ }
+ if (notice.type == CPL || notice.type == EPL)
+ {
+ copy(&tmp, notice.item[PACKAGE].data ? "and" : "This software", -1);
+ copy(&tmp, " is licensed under the", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.type == EPL)
+ copy(&tmp, "Eclipse Public License", -1);
+ else
+ copy(&tmp, "Common Public License", -1);
+ if (notice.item[VERSION].data)
+ {
+ copy(&tmp, ", Version ", -1);
+ expand(&notice, &tmp, &notice.item[VERSION]);
+ }
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[CORPORATION].data || notice.item[COMPANY].data)
+ {
+ copy(&tmp, "by ", -1);
+ if (notice.item[PARENT].data)
+ {
+ expand(&notice, &tmp, &notice.item[PARENT]);
+ copy(&tmp, " ", -1);
+ }
+ if (notice.item[CORPORATION].data)
+ {
+ expand(&notice, &tmp, &notice.item[CORPORATION]);
+ if (notice.item[INCORPORATION].data)
+ {
+ copy(&tmp, " ", -1);
+ expand(&notice, &tmp, &notice.item[INCORPORATION]);
+ }
+ }
+ else if (notice.item[COMPANY].data)
+ expand(&notice, &tmp, &notice.item[COMPANY]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "A copy of the License is available at", 0);
+ if (notice.item[URL].data)
+ {
+ expand(&notice, &tmp, &notice.item[URL]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[URLMD5].data)
+ {
+ copy(&tmp, "(with md5 checksum ", -1);
+ expand(&notice, &tmp, &notice.item[URLMD5]);
+ copy(&tmp, ")", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ }
+ else if (notice.type == EPL)
+ COMMENT(&notice, &buf, "http://www.eclipse.org/org/documents/epl-v10.html", 0);
+ else
+ COMMENT(&notice, &buf, "http://www.opensource.org/licenses/cpl", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == OPEN)
+ {
+ copy(&tmp, notice.item[PACKAGE].data ? "and it" : "This software", -1);
+ copy(&tmp, " may only be used by you under license from", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[i = CORPORATION].data)
+ {
+ if (notice.item[PARENT].data)
+ {
+ expand(&notice, &tmp, &notice.item[i = PARENT]);
+ copy(&tmp, " ", -1);
+ }
+ expand(&notice, &tmp, &notice.item[CORPORATION]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ else if (notice.item[i = COMPANY].data)
+ {
+ if (notice.item[PARENT].data)
+ {
+ expand(&notice, &tmp, &notice.item[i = PARENT]);
+ copy(&tmp, " ", -1);
+ }
+ expand(&notice, &tmp, &notice.item[COMPANY]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ else
+ i = -1;
+ if (notice.item[URL].data)
+ {
+ COMMENT(&notice, &buf, "A copy of the Source Code Agreement is available", 0);
+ copy(&tmp, "at the ", -1);
+ if (i >= 0)
+ expand(&notice, &tmp, &notice.item[i]);
+ copy(&tmp, " Internet web site URL", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ expand(&notice, &tmp, &notice.item[URL]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[URLMD5].data)
+ {
+ copy(&tmp, "(with an md5 checksum of ", -1);
+ expand(&notice, &tmp, &notice.item[URLMD5]);
+ copy(&tmp, ")", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ COMMENT(&notice, &buf, "If you have copied or used this software without agreeing", 0);
+ COMMENT(&notice, &buf, "to the terms of the license you are infringing on", 0);
+ COMMENT(&notice, &buf, "the license and copyright and are violating", 0);
+ if (i >= 0)
+ expand(&notice, &tmp, &notice.item[i]);
+ copy(&tmp, "'s", -1);
+ if (n >= COMLONG)
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ else
+ PUT(&tmp, ' ');
+ copy(&tmp, "intellectual property rights.", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == GPL)
+ {
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "This is free software; you can redistribute it and/or", 0);
+ COMMENT(&notice, &buf, "modify it under the terms of the GNU General Public License", 0);
+ COMMENT(&notice, &buf, "as published by the Free Software Foundation;", 0);
+ COMMENT(&notice, &buf, "either version 2, or (at your option) any later version.", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "This software is distributed in the hope that it", 0);
+ COMMENT(&notice, &buf, "will be useful, but WITHOUT ANY WARRANTY;", 0);
+ COMMENT(&notice, &buf, "without even the implied warranty of MERCHANTABILITY", 0);
+ COMMENT(&notice, &buf, "or FITNESS FOR A PARTICULAR PURPOSE.", 0);
+ COMMENT(&notice, &buf, "See the GNU General Public License for more details.", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "You should have received a copy of the", 0);
+ COMMENT(&notice, &buf, "GNU General Public License", 0);
+ COMMENT(&notice, &buf, "along with this software (see the file COPYING.)", 0);
+ COMMENT(&notice, &buf, "If not, a copy is available at", 0);
+ COMMENT(&notice, &buf, "http://www.gnu.org/copyleft/gpl.html", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == BSD)
+ {
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "Redistribution and use in source and binary forms, with or", -1);
+ COMMENT(&notice, &buf, "without modification, are permitted provided that the following", -1);
+ COMMENT(&notice, &buf, "conditions are met:", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, " 1. Redistributions of source code must retain the above", -1);
+ COMMENT(&notice, &buf, " copyright notice, this list of conditions and the", -1);
+ COMMENT(&notice, &buf, " following disclaimer.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, " 2. Redistributions in binary form must reproduce the above", -1);
+ COMMENT(&notice, &buf, " copyright notice, this list of conditions and the", -1);
+ COMMENT(&notice, &buf, " following disclaimer in the documentation and/or other", -1);
+ COMMENT(&notice, &buf, " materials provided with the distribution.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ copy(&tmp, " 3. Neither the name of ", -1);
+ if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data || notice.item[i = COMPANY].data)
+ expand(&notice, &tmp, &notice.item[i]);
+ else
+ copy(&tmp, "the copyright holder", -1);
+ copy(&tmp, " nor the", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), -1);
+ COMMENT(&notice, &buf, " names of its contributors may be used to endorse or", -1);
+ COMMENT(&notice, &buf, " promote products derived from this software without", -1);
+ COMMENT(&notice, &buf, " specific prior written permission.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND", -1);
+ COMMENT(&notice, &buf, "CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,", -1);
+ COMMENT(&notice, &buf, "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF", -1);
+ COMMENT(&notice, &buf, "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE", -1);
+ COMMENT(&notice, &buf, "DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS", -1);
+ COMMENT(&notice, &buf, "BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,", -1);
+ COMMENT(&notice, &buf, "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED", -1);
+ COMMENT(&notice, &buf, "TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,", -1);
+ COMMENT(&notice, &buf, "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON", -1);
+ COMMENT(&notice, &buf, "ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,", -1);
+ COMMENT(&notice, &buf, "OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY", -1);
+ COMMENT(&notice, &buf, "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE", -1);
+ COMMENT(&notice, &buf, "POSSIBILITY OF SUCH DAMAGE.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == ZLIB)
+ {
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "This software is provided 'as-is', without any express or implied", -1);
+ COMMENT(&notice, &buf, "warranty. In no event will the authors be held liable for any", -1);
+ COMMENT(&notice, &buf, "damages arising from the use of this software.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "Permission is granted to anyone to use this software for any", -1);
+ COMMENT(&notice, &buf, "purpose, including commercial applications, and to alter it and", -1);
+ COMMENT(&notice, &buf, "redistribute it freely, subject to the following restrictions:", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, " 1. The origin of this software must not be misrepresented;", -1);
+ COMMENT(&notice, &buf, " you must not claim that you wrote the original software. If", -1);
+ COMMENT(&notice, &buf, " you use this software in a product, an acknowledgment in the", -1);
+ COMMENT(&notice, &buf, " product documentation would be appreciated but is not", -1);
+ COMMENT(&notice, &buf, " required.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, " 2. Altered source versions must be plainly marked as such,", -1);
+ COMMENT(&notice, &buf, " and must not be misrepresented as being the original", -1);
+ COMMENT(&notice, &buf, " software.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, " 3. This notice may not be removed or altered from any source", -1);
+ COMMENT(&notice, &buf, " distribution.", -1);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == MIT)
+ {
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "Permission is hereby granted, free of charge, to any person", 0);
+ COMMENT(&notice, &buf, "obtaining a copy of this software and associated", 0);
+ COMMENT(&notice, &buf, "documentation files (the \"Software\"), to deal in the", 0);
+ COMMENT(&notice, &buf, "Software without restriction, including without limitation", 0);
+ COMMENT(&notice, &buf, "the rights to use, copy, modify, merge, publish, distribute,", 0);
+ COMMENT(&notice, &buf, "sublicense, and/or sell copies of the Software, and to", 0);
+ COMMENT(&notice, &buf, "permit persons to whom the Software is furnished to do so,", 0);
+ COMMENT(&notice, &buf, "subject to the following conditions:", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "The above copyright notice and this permission notice shall", 0);
+ COMMENT(&notice, &buf, "be included in all copies or substantial portions of the", 0);
+ COMMENT(&notice, &buf, "Software.", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ COMMENT(&notice, &buf, "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY", 0);
+ COMMENT(&notice, &buf, "KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE", 0);
+ COMMENT(&notice, &buf, "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR", 0);
+ COMMENT(&notice, &buf, "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS", 0);
+ COMMENT(&notice, &buf, "OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR", 0);
+ COMMENT(&notice, &buf, "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR", 0);
+ COMMENT(&notice, &buf, "OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE", 0);
+ COMMENT(&notice, &buf, "SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else
+ {
+ if (notice.type == PROPRIETARY)
+ {
+ if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data || notice.item[i = COMPANY].data)
+ {
+ expand(&notice, &tmp, &notice.item[i]);
+ copy(&tmp, " - ", -1);
+ }
+ else
+ i = -1;
+ copy(&tmp, "Proprietary", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
+ comment(&notice, &buf, NiL, 0, 0);
+ if (notice.item[URL].data)
+ {
+ copy(&tmp, "This is proprietary source code", -1);
+ if (i >= 0)
+ copy(&tmp, " licensed by", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
+ if (notice.item[PARENT].data)
+ {
+ expand(&notice, &tmp, &notice.item[PARENT]);
+ copy(&tmp, " ", -1);
+ }
+ if (notice.item[CORPORATION].data)
+ {
+ expand(&notice, &tmp, &notice.item[CORPORATION]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
+ }
+ else if (notice.item[COMPANY].data)
+ {
+ expand(&notice, &tmp, &notice.item[COMPANY]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
+ }
+ }
+ else
+ {
+ copy(&tmp, "This is unpublished proprietary source code", -1);
+ if (i >= 0)
+ copy(&tmp, " of", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
+ if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data)
+ expand(&notice, &tmp, &notice.item[i]);
+ if (notice.item[COMPANY].data)
+ {
+ if (SIZ(&tmp))
+ PUT(&tmp, ' ');
+ expand(&notice, &tmp, &notice.item[COMPANY]);
+ }
+ if (SIZ(&tmp))
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 1);
+ COMMENT(&notice, &buf, "and is not to be disclosed or used except in", 1);
+ COMMENT(&notice, &buf, "accordance with applicable agreements", 1);
+ }
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == NONEXCLUSIVE)
+ {
+ COMMENT(&notice, &buf, "For nonexclusive individual use", 1);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == NONCOMMERCIAL)
+ {
+ COMMENT(&notice, &buf, "For noncommercial use", 1);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ if (notice.type >= PROPRIETARY && !notice.item[URL].data)
+ {
+ COMMENT(&notice, &buf, "Unpublished & Not for Publication", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ if (notice.item[URL].data)
+ {
+ copy(&tmp, "This software is licensed", -1);
+ if (notice.item[CORPORATION].data || notice.item[COMPANY].data)
+ {
+ copy(&tmp, " by", -1);
+ if ((notice.item[PARENT].size + (notice.item[CORPORATION].data ? (notice.item[CORPORATION].size + notice.item[INCORPORATION].size) : notice.item[COMPANY].size)) >= (COMLONG - 6))
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ else
+ PUT(&tmp, ' ');
+ if (notice.item[PARENT].data)
+ {
+ expand(&notice, &tmp, &notice.item[PARENT]);
+ copy(&tmp, " ", -1);
+ }
+ if (notice.item[CORPORATION].data)
+ {
+ expand(&notice, &tmp, &notice.item[CORPORATION]);
+ if (notice.item[INCORPORATION].data)
+ {
+ copy(&tmp, " ", -1);
+ expand(&notice, &tmp, &notice.item[INCORPORATION]);
+ }
+ }
+ else if (notice.item[COMPANY].data)
+ expand(&notice, &tmp, &notice.item[COMPANY]);
+ }
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ COMMENT(&notice, &buf, "under the terms and conditions of the license in", 0);
+ expand(&notice, &tmp, &notice.item[URL]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[URLMD5].data)
+ {
+ copy(&tmp, "(with an md5 checksum of ", -1);
+ expand(&notice, &tmp, &notice.item[URLMD5]);
+ copy(&tmp, ")", -1);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ else if (notice.type == PROPRIETARY)
+ {
+ COMMENT(&notice, &buf, "The copyright notice above does not evidence any", 0);
+ COMMENT(&notice, &buf, "actual or intended publication of such source code", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ }
+ if (v = notice.item[NOTICE].data)
+ {
+ x = v + notice.item[NOTICE].size;
+ if (*v == '\n')
+ v++;
+ item.quote = notice.item[NOTICE].quote;
+ do
+ {
+ for (item.data = v; v < x && *v != '\n'; v++);
+ if ((item.size = v - item.data) && *item.data == '\t')
+ {
+ item.data++;
+ item.size--;
+ h = 0;
+ }
+ else
+ h = -1;
+ expand(&notice, &tmp, &item);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), h);
+ } while (v++ < x);
+ if (item.size)
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ if (notice.item[ORGANIZATION].data)
+ {
+ expand(&notice, &tmp, &notice.item[ORGANIZATION]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[i = PARENT].data || notice.item[i = CORPORATION].data)
+ expand(&notice, &tmp, &notice.item[i]);
+ if (notice.item[COMPANY].data)
+ {
+ if (SIZ(&tmp))
+ PUT(&tmp, ' ');
+ expand(&notice, &tmp, &notice.item[COMPANY]);
+ }
+ if (SIZ(&tmp))
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ if (notice.item[LOCATION].data)
+ {
+ expand(&notice, &tmp, &notice.item[LOCATION]);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ }
+ if (v = notice.item[AUTHOR].data)
+ {
+ x = v + notice.item[AUTHOR].size;
+ q = (x - v) == 1 && (*v == '*' || *v == '-');
+ k = q && notice.type != USAGE ? -1 : 0;
+ for (;;)
+ {
+ if (!q)
+ {
+ while (v < x && (*v == ' ' || *v == '\t' || *v == '\r' || *v == '\n' || *v == ',' || *v == '+'))
+ v++;
+ if (v >= x)
+ break;
+ item.data = v;
+ while (v < x && *v != ',' && *v != '+' && *v++ != '>');
+ item.size = v - item.data;
+ item.quote = notice.item[AUTHOR].quote;
+ }
+ h = 0;
+ for (i = 0; i < notice.ids; i++)
+ if (q || item.size == notice.id[i].name.size && !strncmp(item.data, notice.id[i].name.data, item.size))
+ {
+ h = 1;
+ if (notice.type == USAGE)
+ {
+ copy(&buf, "[-author?", -1);
+ expand(&notice, &buf, &notice.id[i].value);
+ PUT(&buf, ']');
+ }
+ else
+ {
+ if (k < 0)
+ {
+ COMMENT(&notice, &buf, "CONTRIBUTORS", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ k = 1;
+ expand(&notice, &tmp, &notice.id[i].value);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ if (!q)
+ break;
+ }
+ if (q)
+ break;
+ if (!h)
+ {
+ if (notice.type == USAGE)
+ {
+ copy(&buf, "[-author?", -1);
+ expand(&notice, &buf, &item);
+ PUT(&buf, ']');
+ }
+ else
+ {
+ if (k < 0)
+ {
+ COMMENT(&notice, &buf, "CONTRIBUTORS", 0);
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ k = 1;
+ expand(&notice, &tmp, &item);
+ comment(&notice, &buf, BUF(&tmp), USE(&tmp), 0);
+ }
+ }
+ }
+ if (k > 0)
+ comment(&notice, &buf, NiL, 0, 0);
+ }
+ if (notice.type == USAGE)
+ {
+ copy(&buf, "[-copyright?", -1);
+ copyright(&notice, &buf);
+ PUT(&buf, ']');
+ if (notice.item[URL].data)
+ {
+ copy(&buf, "[-license?", -1);
+ expand(&notice, &buf, &notice.item[URL]);
+ PUT(&buf, ']');
+ }
+ PUT(&buf, '\n');
+ }
+ else
+ comment(&notice, &buf, NiL, -1, 0);
+ return END(&buf);
+}
diff --git a/src/lib/libast/port/astmath.c b/src/lib/libast/port/astmath.c
new file mode 100644
index 0000000..395312e
--- /dev/null
+++ b/src/lib/libast/port/astmath.c
@@ -0,0 +1,72 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * used to test if -last requires -lm
+ *
+ * arch -last -lm
+ * ---- ----- ---
+ * linux.sparc sfdlen,sfputd frexp,ldexp
+ */
+
+#if N >= 8
+#define _ISOC99_SOURCE 1
+#endif
+
+#include <math.h>
+
+int
+main()
+{
+#if N & 1
+ long double value = 0;
+#else
+ double value = 0;
+#endif
+#if N < 5
+ int exp = 0;
+#endif
+
+#if N == 1
+ return ldexpl(value, exp) != 0;
+#endif
+#if N == 2
+ return ldexp(value, exp) != 0;
+#endif
+#if N == 3
+ return frexpl(value, &exp) != 0;
+#endif
+#if N == 4
+ return frexp(value, &exp) != 0;
+#endif
+#if N == 5
+ return isnan(value);
+#endif
+#if N == 6
+ return isnan(value);
+#endif
+#if N == 7
+ return copysign(1.0, value) < 0;
+#endif
+#if N == 8
+ return signbit(value);
+#endif
+}
diff --git a/src/lib/libast/port/astquery.c b/src/lib/libast/port/astquery.c
new file mode 100644
index 0000000..d0d87db
--- /dev/null
+++ b/src/lib/libast/port/astquery.c
@@ -0,0 +1,114 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Research
+ *
+ * output printf prompt and read response
+ * if format==0 then verify that interaction is possible
+ *
+ * return:
+ *
+ * 0 [1yY+]
+ * -1 [qQ] or EOF
+ * 1 otherwise
+ *
+ * if (quit&ERROR_PROMPT) then tty forced for IO
+ * if quit>=0 then [qQ] or EOF calls exit(quit)
+ */
+
+#include <ast.h>
+#include <error.h>
+
+int
+astquery(int quit, const char* format, ...)
+{
+ va_list ap;
+ register int n;
+ register int c;
+ int r;
+ Sfio_t* ip;
+ Sfio_t* op;
+
+ static Sfio_t* rfp;
+ static Sfio_t* wfp;
+
+ r = 0;
+ va_start(ap, format);
+ if (!format)
+ goto done;
+ r = -1;
+ if (!rfp)
+ {
+ c = errno;
+ if (isatty(sffileno(sfstdin)))
+ rfp = sfstdin;
+ else if (!(rfp = sfopen(NiL, "/dev/tty", "r")))
+ goto done;
+ if (isatty(sffileno(sfstderr)))
+ wfp = sfstderr;
+ else if (!(wfp = sfopen(NiL, "/dev/tty", "w")))
+ goto done;
+ errno = c;
+ }
+ if (quit & ERROR_PROMPT)
+ {
+ quit &= ~ERROR_PROMPT;
+ ip = rfp;
+ op = wfp;
+ }
+ else
+ {
+ ip = sfstdin;
+ op = sfstderr;
+ }
+ sfsync(sfstdout);
+ sfvprintf(op, format, ap);
+ sfsync(op);
+ for (n = c = sfgetc(ip);; c = sfgetc(ip))
+ switch (c)
+ {
+ case EOF:
+ n = c;
+ /*FALLTHROUGH*/
+ case '\n':
+ switch (n)
+ {
+ case EOF:
+ case 'q':
+ case 'Q':
+ if (quit >= 0)
+ exit(quit);
+ goto done;
+ case '1':
+ case 'y':
+ case 'Y':
+ case '+':
+ r = 0;
+ goto done;
+ }
+ return 1;
+ }
+ done:
+ va_end(ap);
+ return r;
+}
diff --git a/src/lib/libast/port/aststatic.c b/src/lib/libast/port/aststatic.c
new file mode 100644
index 0000000..7517572
--- /dev/null
+++ b/src/lib/libast/port/aststatic.c
@@ -0,0 +1,44 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * ast static data initialization
+ */
+
+#include <ast.h>
+
+#if _dll_data_intercept && ( _DLL_BLD || _BLD_DLL )
+
+void
+_ast_init(void)
+{
+ struct _astdll* ap = _ast_getdll();
+
+ ap->_dll_environ = &environ;
+}
+
+#else
+
+NoN(aststatic)
+
+#endif
diff --git a/src/lib/libast/port/astwinsize.c b/src/lib/libast/port/astwinsize.c
new file mode 100644
index 0000000..66f4e09
--- /dev/null
+++ b/src/lib/libast/port/astwinsize.c
@@ -0,0 +1,143 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * AT&T Research
+ * return terminal rows and cols
+ */
+
+#include <ast.h>
+#include <ast_tty.h>
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide ioctl sleep
+#else
+#define ioctl ______ioctl
+#define sleep ______sleep
+#endif
+
+#if _sys_ioctl
+#include <sys/ioctl.h>
+#endif
+
+#if defined(TIOCGWINSZ)
+#if _sys_stream && _sys_ptem
+#include <sys/stream.h>
+#include <sys/ptem.h>
+#endif
+#else
+#if !defined(TIOCGSIZE) && !defined(TIOCGWINSZ)
+#if _hdr_jioctl
+#define jwinsize winsize
+#include <jioctl.h>
+#else
+#if _sys_jioctl
+#define jwinsize winsize
+#include <sys/jioctl.h>
+#endif
+#endif
+#endif
+#endif
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide ioctl sleep
+#else
+#undef ioctl
+#undef sleep
+#endif
+
+static int ttctl(int, int, void*);
+
+void
+astwinsize(int fd, register int* rows, register int* cols)
+{
+#ifdef TIOCGWINSZ
+#define NEED_ttctl
+ struct winsize ws;
+
+ if (!ttctl(fd, TIOCGWINSZ, &ws) && ws.ws_col > 0 && ws.ws_row > 0)
+ {
+ if (rows) *rows = ws.ws_row;
+ if (cols) *cols = ws.ws_col;
+ }
+ else
+#else
+#ifdef TIOCGSIZE
+#define NEED_ttctl
+ struct ttysize ts;
+
+ if (!ttctl(fd, TIOCGSIZE, &ts) && ts.ts_lines > 0 && ts.ts_cols > 0)
+ {
+ if (rows) *rows = ts.ts_lines;
+ if (cols) *cols = ts.ts_cols;
+ }
+ else
+#else
+#ifdef JWINSIZE
+#define NEED_ttctl
+ struct winsize ws;
+
+ if (!ttctl(fd, JWINSIZE, &ws) && ws.bytesx > 0 && ws.bytesy > 0)
+ {
+ if (rows) *rows = ws.bytesy;
+ if (cols) *cols = ws.bytesx;
+ }
+ else
+#endif
+#endif
+#endif
+ {
+ char* s;
+
+ if (rows) *rows = (s = getenv("LINES")) ? strtol(s, NiL, 0) : 0;
+ if (cols) *cols = (s = getenv("COLUMNS")) ? strtol(s, NiL, 0) : 0;
+ }
+}
+
+#ifdef NEED_ttctl
+
+/*
+ * tty ioctl() -- no cache
+ */
+
+static int
+ttctl(register int fd, int op, void* tt)
+{
+ register int v;
+
+ if (fd < 0)
+ {
+ for (fd = 0; fd <= 2; fd++)
+ if (!ioctl(fd, op, tt)) return(0);
+ if ((fd = open("/dev/tty", O_RDONLY)) >= 0)
+ {
+ v = ioctl(fd, op, tt);
+ close(fd);
+ return(v);
+ }
+ }
+ else if (!ioctl(fd, op, tt)) return(0);
+ return(-1);
+}
+
+#endif
diff --git a/src/lib/libast/port/atmain.C b/src/lib/libast/port/atmain.C
new file mode 100644
index 0000000..b6d7560
--- /dev/null
+++ b/src/lib/libast/port/atmain.C
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if ! __MVS__
+
+void _STUB_atmain(){}
+
+#else
+
+extern "C" void _ast_init();
+
+class Atmain_t
+{
+public: Atmain_t() { _ast_init(); }
+};
+
+static Atmain_t atmain();
+
+#endif
diff --git a/src/lib/libast/port/iblocks.c b/src/lib/libast/port/iblocks.c
new file mode 100644
index 0000000..a768b84
--- /dev/null
+++ b/src/lib/libast/port/iblocks.c
@@ -0,0 +1,95 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * aux function for <ls.h> iblocks() macro
+ *
+ * return number of blocks, including indirect block count
+ * given stat info
+ *
+ * mail gsf@research.att.com when you figure out the stat.st_blocks units
+ * until then we assume LS_BLOCKSIZE (512)
+ */
+
+#include <ast.h>
+#if _AIX /* XXX */
+#undef major
+#undef minor
+#undef makedev
+#endif
+#include <ast_param.h>
+#include <ls.h>
+
+#if !_mem_st_blocks_stat
+
+#ifndef B_DIRECT
+#define B_DIRECT 10
+#endif
+
+#ifdef BITFS
+
+#define B_SIZE BSIZE(st->st_dev)
+#define B_INDIRECT NINDIR(st->st_dev)
+
+#else
+
+#ifdef BSIZE
+#define B_SIZE BSIZE
+#else
+#define B_SIZE 1024
+#endif
+
+#ifdef NINDIR
+#define B_INDIRECT NINDIR
+#else
+#define B_INDIRECT 128
+#endif
+
+#endif
+
+#endif
+
+off_t
+_iblocks(register struct stat* st)
+{
+#if _mem_st_blocks_stat
+
+ return (st->st_blocks <= 0 || st->st_size <= 0) ? 0 : st->st_blocks;
+
+#else
+ unsigned long b;
+ unsigned long t;
+
+ t = b = (st->st_size + B_SIZE - 1) / B_SIZE;
+ if ((b -= B_DIRECT) > 0)
+ {
+ t += (b - 1) / B_INDIRECT + 1;
+ if ((b -= B_INDIRECT) > 0)
+ {
+ t += (b - 1) / (B_INDIRECT * B_INDIRECT) + 1;
+ if (b > B_INDIRECT * B_INDIRECT)
+ t++;
+ }
+ }
+ return t * B_SIZE / LS_BLOCKSIZE;
+#endif
+}
diff --git a/src/lib/libast/port/lc.c b/src/lib/libast/port/lc.c
new file mode 100644
index 0000000..488dd8d
--- /dev/null
+++ b/src/lib/libast/port/lc.c
@@ -0,0 +1,883 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * locale state implementation
+ */
+
+#include "lclib.h"
+#include "lclang.h"
+#include "FEATURE/locale"
+
+#include <ctype.h>
+
+typedef struct Local_s
+{
+ const char* name;
+ int size;
+} Local_t;
+
+#undef setlocale /* this file deals with the system locale */
+
+static Lc_numeric_t default_numeric = { '.', -1 };
+
+static Lc_t default_lc =
+{
+ "C",
+ "POSIX",
+ &lc_languages[0],
+ &lc_territories[0],
+ &lc_charsets[0],
+ 0,
+ LC_default|LC_checked|LC_local,
+ 0,
+ {
+ { &default_lc, 0, 0 },
+ { &default_lc, 0, 0 },
+ { &default_lc, 0, 0 },
+ { &default_lc, 0, 0 },
+ { &default_lc, 0, 0 },
+ { &default_lc, 0, (void*)&default_numeric },
+ { &default_lc, 0, 0 },
+ { &default_lc, 0, 0 },
+ { &default_lc, 0, 0 },
+ { &default_lc, 0, 0 },
+ { &default_lc, 0, 0 },
+ { &default_lc, 0, 0 },
+ { &default_lc, 0, 0 },
+ { &default_lc, 0, 0 }
+ }
+};
+
+static Lc_numeric_t debug_numeric = { ',', '.' };
+
+static Lc_t debug_lc =
+{
+ "debug",
+ "debug",
+ &lc_languages[1],
+ &lc_territories[1],
+ &lc_charsets[0],
+ 0,
+ LC_debug|LC_checked|LC_local,
+ 0,
+ {
+ { &debug_lc, 0, 0 },
+ { &debug_lc, 0, 0 },
+ { &debug_lc, 0, 0 },
+ { &debug_lc, 0, 0 },
+ { &debug_lc, 0, 0 },
+ { &debug_lc, 0, (void*)&debug_numeric },
+ { &debug_lc, 0, 0 },
+ { &debug_lc, 0, 0 },
+ { &debug_lc, 0, 0 },
+ { &debug_lc, 0, 0 },
+ { &debug_lc, 0, 0 },
+ { &debug_lc, 0, 0 },
+ { &debug_lc, 0, 0 },
+ { &debug_lc, 0, 0 }
+ },
+ &default_lc
+};
+
+static Lc_t* lcs = &debug_lc;
+
+Lc_t* locales[] =
+{
+ &default_lc,
+ &default_lc,
+ &default_lc,
+ &default_lc,
+ &default_lc,
+ &default_lc,
+ &default_lc,
+ &default_lc,
+ &default_lc,
+ &default_lc,
+ &default_lc,
+ &default_lc,
+ &default_lc,
+ &default_lc
+};
+
+/*
+ * return the internal category index for category
+ */
+
+int
+lcindex(int category, int min)
+{
+ switch (category)
+ {
+ case LC_ALL: return min ? -1 : AST_LC_ALL;
+ case LC_ADDRESS: return AST_LC_ADDRESS;
+ case LC_COLLATE: return AST_LC_COLLATE;
+ case LC_CTYPE: return AST_LC_CTYPE;
+ case LC_IDENTIFICATION: return AST_LC_IDENTIFICATION;
+ case LC_LANG: return AST_LC_LANG;
+ case LC_MEASUREMENT: return AST_LC_MEASUREMENT;
+ case LC_MESSAGES: return AST_LC_MESSAGES;
+ case LC_MONETARY: return AST_LC_MONETARY;
+ case LC_NAME: return AST_LC_NAME;
+ case LC_NUMERIC: return AST_LC_NUMERIC;
+ case LC_PAPER: return AST_LC_PAPER;
+ case LC_TELEPHONE: return AST_LC_TELEPHONE;
+ case LC_TIME: return AST_LC_TIME;
+ case LC_XLITERATE: return AST_LC_XLITERATE;
+ }
+ return -1;
+}
+
+/*
+ * return the first category table entry
+ */
+
+Lc_category_t*
+lccategories(void)
+{
+ return (Lc_category_t*)&lc_categories[0];
+}
+
+/*
+ * return the current info for category
+ */
+
+Lc_info_t*
+lcinfo(register int category)
+{
+ if ((category = lcindex(category, 0)) < 0)
+ return 0;
+ return LCINFO(category);
+}
+
+/*
+ * return 1 if s matches the alternation pattern p
+ * if minimum!=0 then at least that many chars must match
+ * if standard!=0 and s[0] is a digit leading non-digits are ignored in p
+ */
+
+static int
+match(const char* s, register const char* p, int minimum, int standard)
+{
+ register const char* t;
+ const char* x;
+ int w;
+ int z;
+
+ z = 0;
+ do
+ {
+ t = s;
+ if (standard)
+ {
+ if (isdigit(*t))
+ while (*p && !isdigit(*p))
+ p++;
+ else if (isdigit(*p))
+ while (*t && !isdigit(*t))
+ t++;
+ }
+ if (*p)
+ {
+ w = 0;
+ x = p;
+ while (*p && *p != '|')
+ {
+ if (!*t || *t == ',')
+ break;
+ else if (*t == *p)
+ /*ok*/;
+ else if (*t == '-')
+ {
+ if (standard && isdigit(*p))
+ {
+ t++;
+ continue;
+ }
+ while (*p && *p != '-')
+ p++;
+ if (!*p)
+ break;
+ }
+ else if (*p == '-')
+ {
+ if (standard && isdigit(*t))
+ {
+ p++;
+ continue;
+ }
+ w = 1;
+ while (*t && *t != '-')
+ t++;
+ if (!*t)
+ break;
+ }
+ else
+ break;
+ t++;
+ p++;
+ }
+ if ((!*t || *t == ',') && (!*p || *p == '|' || w))
+ return p - x;
+ if (minimum && z < (p - x) && (p - x) >= minimum)
+ z = p - x;
+ }
+ while (*p && *p != '|')
+ p++;
+ } while (*p++);
+ return z;
+}
+
+/*
+ * return 1 if s matches the charset names in cp
+ */
+
+static int
+match_charset(register const char* s, register const Lc_charset_t* cp)
+{
+ return match(s, cp->code, 0, 1) || match(s, cp->alternates, 3, 1) || cp->ms && match(s, cp->ms, 0, 1);
+}
+
+/*
+ * low level for lccanon
+ */
+
+static size_t
+canonical(const Lc_language_t* lp, const Lc_territory_t* tp, const Lc_charset_t* cp, const Lc_attribute_list_t* ap, unsigned long flags, char* buf, size_t siz)
+{
+ register int c;
+ register int u;
+ register char* s;
+ register char* e;
+ register const char* t;
+ char* p;
+ char* r;
+
+ if (!(flags & (LC_abbreviated|LC_default|LC_local|LC_qualified|LC_verbose)))
+ flags |= LC_abbreviated;
+ s = buf;
+ e = &buf[siz - 3];
+ if (lp)
+ {
+ if (lp->flags & (LC_debug|LC_default))
+ {
+ for (t = lp->code; s < e && (*s = *t++); s++);
+ *s++ = 0;
+ return s - buf;
+ }
+ if (flags & LC_verbose)
+ {
+ u = 1;
+ t = lp->name;
+ while (s < e && (c = *t++))
+ {
+ if (u)
+ {
+ u = 0;
+ c = toupper(c);
+ }
+ else if (!isalnum(c))
+ u = 1;
+ *s++ = c;
+ }
+ }
+ else
+ for (t = lp->code; s < e && (*s = *t++); s++);
+ }
+ if (s < e)
+ {
+ if (tp && tp != &lc_territories[0])
+ {
+ r = 0;
+ if (lp)
+ {
+ if ((flags & (LC_abbreviated|LC_default)) && streq(lp->code, tp->code))
+ r = s;
+ *s++ = '_';
+ }
+ if (flags & LC_verbose)
+ {
+ u = 1;
+ t = tp->name;
+ while (s < e && (c = *t++) && c != '|')
+ {
+ if (u)
+ {
+ u = 0;
+ c = toupper(c);
+ }
+ else if (!isalnum(c))
+ u = 1;
+ *s++ = c;
+ }
+ }
+ else
+ for (t = tp->code; s < e && (*s = toupper(*t++)); s++);
+ if (r)
+ {
+ *s = 0;
+ if ((p = setlocale(LC_MESSAGES, 0)) && (p = strdup(p)))
+ {
+ if (!setlocale(LC_MESSAGES, buf))
+ {
+ *r = 0;
+ if (!setlocale(LC_MESSAGES, buf))
+ *r = '_';
+ }
+ setlocale(LC_MESSAGES, p);
+ free(p);
+ }
+ }
+ }
+ if (lp && (!(flags & (LC_abbreviated|LC_default)) || cp != lp->charset) && s < e)
+ {
+ *s++ = '.';
+ t = cp->code;
+ if (streq(cp->code, "utf8") && (t = _locale_utf8_str))
+ for (; s < e && (c = *t++); s++)
+ *s = c;
+ else
+ for (t = cp->code; s < e && (c = *t++); s++)
+ {
+ if (islower(c))
+ c = toupper(c);
+ *s = c;
+ }
+ }
+ for (c = '@'; ap && s < e; ap = ap->next)
+ if (!(flags & (LC_abbreviated|LC_default|LC_verbose)) || !(ap->attribute->flags & LC_default))
+ {
+ *s++ = c;
+ c = ',';
+ for (t = ap->attribute->name; s < e && (*s = *t++); s++);
+ }
+ }
+ *s++ = 0;
+ return s - buf;
+}
+
+/*
+ * generate a canonical locale name in buf
+ */
+
+size_t
+lccanon(Lc_t* lc, unsigned long flags, char* buf, size_t siz)
+{
+ if ((flags & LC_local) && (!lc->language || !(lc->language->flags & (LC_debug|LC_default))))
+ {
+#if _WINIX
+ char lang[64];
+ char code[64];
+ char ctry[64];
+
+ if (lc->index &&
+ GetLocaleInfo(lc->index, LOCALE_SENGLANGUAGE, lang, sizeof(lang)) &&
+ GetLocaleInfo(lc->index, LOCALE_SENGCOUNTRY, ctry, sizeof(ctry)))
+ {
+ if (!GetLocaleInfo(lc->index, LOCALE_IDEFAULTANSICODEPAGE, code, sizeof(code)))
+ code[0] = 0;
+ if (!lc->charset || !lc->charset->ms)
+ return sfsprintf(buf, siz, "%s_%s", lang, ctry);
+ else if (streq(lc->charset->ms, code))
+ return sfsprintf(buf, siz, "%s_%s.%s", lang, ctry, code);
+ else
+ return sfsprintf(buf, siz, "%s_%s.%s,%s", lang, ctry, code, lc->charset->ms);
+ }
+#endif
+ buf[0] = '-';
+ buf[1] = 0;
+ return 0;
+ }
+ return canonical(lc->language, lc->territory, lc->charset, lc->attributes, flags, buf, siz);
+}
+
+/*
+ * make an Lc_t from a locale name
+ */
+
+Lc_t*
+lcmake(const char* name)
+{
+ register int c;
+ register char* s;
+ register char* e;
+ register const char* t;
+ const char* a;
+ char* w;
+ char* language_name;
+ char* territory_name;
+ char* charset_name;
+ char* attributes_name;
+ Lc_t* lc;
+ const Lc_map_t* mp;
+ const Lc_language_t* lp;
+ const Lc_territory_t* tp;
+ const Lc_territory_t* tpb;
+ const Lc_territory_t* primary;
+ const Lc_charset_t* cp;
+ const Lc_charset_t* ppa;
+ const Lc_attribute_t* ap;
+ Lc_attribute_list_t* ai;
+ Lc_attribute_list_t* al;
+ int i;
+ int n;
+ int z;
+ char buf[PATH_MAX / 2];
+ char tmp[PATH_MAX / 2];
+ Local_t local[2];
+
+ if (!(t = name) || !*t)
+ return &default_lc;
+ for (lc = lcs; lc; lc = lc->next)
+ if (!strcasecmp(t, lc->code) || !strcasecmp(t, lc->name))
+ return lc;
+ for (mp = lc_maps; mp->code; mp++)
+ if (streq(t, mp->code))
+ {
+ lp = mp->language;
+ tp = mp->territory;
+ cp = mp->charset;
+ if (!mp->attribute)
+ al = 0;
+ else if (al = newof(0, Lc_attribute_list_t, 1, 0))
+ al->attribute = mp->attribute;
+ goto mapped;
+ }
+ language_name = buf;
+ territory_name = charset_name = attributes_name = 0;
+ s = buf;
+ e = &buf[sizeof(buf)-2];
+ a = 0;
+ n = 0;
+ while (s < e && (c = *t++))
+ {
+ if (isspace(c) || (c == '(' || c == '-' && *t == '-') && ++n)
+ {
+ while ((c = *t++) && (isspace(c) || (c == '-' || c == '(' || c == ')') && ++n))
+ if (!c)
+ break;
+ if (isalnum(c) && !n)
+ *s++ = '-';
+ else
+ {
+ n = 0;
+ if (!a)
+ {
+ a = t - 1;
+ while (c && c != '_' && c != '.' && c != '@')
+ c = *t++;
+ if (!c)
+ break;
+ }
+ }
+ }
+ if (c == '_' && !territory_name)
+ {
+ *s++ = 0;
+ territory_name = s;
+ }
+ else if (c == '.' && !charset_name)
+ {
+ *s++ = 0;
+ charset_name = s;
+ }
+ else if (c == '@' && !attributes_name)
+ {
+ *s++ = 0;
+ attributes_name = s;
+ }
+ else
+ {
+ if (isupper(c))
+ c = tolower(c);
+ *s++ = c;
+ }
+ }
+ if ((t = a) && s < e)
+ {
+ if (attributes_name)
+ *s++ = ',';
+ else
+ {
+ *s++ = 0;
+ attributes_name = s;
+ }
+ while (s < e && (c = *t++))
+ {
+ if (isspace(c) || (c == '(' || c == ')' || c == '-' && *t == '-') && ++n)
+ {
+ while ((c = *t++) && (isspace(c) || (c == '-' || c == '(' || c == ')') && ++n))
+ if (!c)
+ break;
+ if (isalnum(c) && !n)
+ *s++ = '-';
+ else
+ n = 0;
+ }
+ if (c == '_' || c == '.' || c == '@')
+ break;
+ if (isupper(c))
+ c = tolower(c);
+ *s++ = c;
+ }
+ }
+ *s = 0;
+#if AHA
+ if ((ast.locale.set & AST_LC_debug) && !(ast.locale.set & AST_LC_internal))
+ sfprintf(sfstderr, "locale make %s language=%s territory=%s charset=%s attributes=%s\n", name, language_name, territory_name, charset_name, attributes_name);
+#endif
+ tp = 0;
+ cp = ppa = 0;
+ al = 0;
+
+ /*
+ * language
+ */
+
+ n = strlen(s = language_name);
+ if (n == 2)
+ for (lp = lc_languages; lp->code && !streq(s, lp->code); lp++);
+ else if (n == 3)
+ {
+ for (lp = lc_languages; lp->code && (!lp->alternates || !match(s, lp->alternates, n, 0)); lp++);
+ if (!lp->code)
+ {
+ c = s[2];
+ s[2] = 0;
+ for (lp = lc_languages; lp->code && !streq(s, lp->code); lp++);
+ s[2] = c;
+ if (lp->code)
+ n = 1;
+ }
+ }
+ else if (streq(s, "c") || streq(s, "posix"))
+ lp = &lc_languages[0];
+ else
+ lp = 0;
+ if (!lp || !lp->code)
+ {
+ for (lp = lc_languages; lp->code && !match(s, lp->name, 0, 0); lp++);
+ if (!lp || !lp->code)
+ {
+ if (!territory_name)
+ {
+ if (n == 2)
+ for (tp = lc_territories; tp->code && !streq(s, tp->code); tp++);
+ else
+ {
+ z = 0;
+ tpb = 0;
+ for (tp = lc_territories; tp->name; tp++)
+ if ((i = match(s, tp->name, 3, 0)) > z)
+ {
+ tpb = tp;
+ if ((z = i) == n)
+ break;
+ }
+ if (tpb)
+ tp = tpb;
+ }
+ if (tp->code)
+ lp = tp->languages[0];
+ }
+ if (!lp || !lp->code)
+ {
+ /*
+ * name not in the tables so let
+ * _ast_setlocale() and/or setlocale()
+ * handle the validity checks
+ */
+
+ s = (char*)name;
+ z = strlen(s) + 1;
+ if (!(lp = newof(0, Lc_language_t, 1, z)))
+ return 0;
+ name = ((Lc_language_t*)lp)->code = ((Lc_language_t*)lp)->name = (const char*)(lp + 1);
+ memcpy((char*)lp->code, s, z - 1);
+ tp = &lc_territories[0];
+ cp = &lc_charsets[0];
+ if (charset_name)
+ for (ppa = lc_charsets; ppa->code; ppa++)
+ if (match_charset(charset_name, ppa))
+ {
+ cp = ppa;
+ break;
+ }
+ ((Lc_language_t*)lp)->charset = cp;
+ al = 0;
+ goto override;
+ }
+ }
+ }
+
+ /*
+ * territory
+ */
+
+ if (!tp || !tp->code)
+ {
+ if (!(s = territory_name))
+ {
+ n = 0;
+ primary = 0;
+ for (tp = lc_territories; tp->code; tp++)
+ if (tp->languages[0] == lp)
+ {
+ if (tp->flags & LC_primary)
+ {
+ n = 1;
+ primary = tp;
+ break;
+ }
+ n++;
+ primary = tp;
+ }
+ if (n == 1)
+ tp = primary;
+ s = (char*)lp->code;
+ }
+ if (!tp || !tp->code)
+ {
+ n = strlen(s);
+ if (n == 2)
+ {
+ for (tp = lc_territories; tp->code; tp++)
+ if (streq(s, tp->code))
+ {
+ if (lp != &lc_languages[0])
+ {
+ for (i = 0; i < elementsof(tp->languages) && lp != tp->languages[i]; i++);
+ if (i >= elementsof(tp->languages))
+ tp = 0;
+ }
+ break;
+ }
+ }
+ else
+ {
+ for (tp = lc_territories; tp->code; tp++)
+ if (match(s, tp->name, 3, 0))
+ {
+ for (i = 0; i < elementsof(tp->languages) && lp != tp->languages[i]; i++);
+ if (i < elementsof(tp->languages))
+ break;
+ }
+ }
+ if (tp && !tp->code)
+ tp = 0;
+ }
+ }
+
+ /*
+ * attributes -- done here to catch misplaced charset references
+ */
+
+ if (s = attributes_name)
+ {
+ do
+ {
+ for (w = s; *s && *s != ','; s++);
+ c = *s;
+ *s = 0;
+ if (!(cp = lp->charset) || !match_charset(w, cp))
+ for (cp = lc_charsets; cp->code; cp++)
+ if (match_charset(w, cp))
+ {
+ ppa = cp;
+ break;
+ }
+ if (!cp->code)
+ {
+ for (i = 0; i < elementsof(lp->attributes) && (ap = lp->attributes[i]); i++)
+ if (match(w, ap->name, 5, 0))
+ {
+ if (ai = newof(0, Lc_attribute_list_t, 1, 0))
+ {
+ ai->attribute = ap;
+ ai->next = al;
+ al = ai;
+ }
+ break;
+ }
+ if (i >= elementsof(lp->attributes) && (ap = newof(0, Lc_attribute_t, 1, sizeof(Lc_attribute_list_t) + s - w + 1)))
+ {
+ ai = (Lc_attribute_list_t*)(ap + 1);
+ strcpy((char*)(((Lc_attribute_t*)ap)->name = (const char*)(ai + 1)), w);
+ ai->attribute = ap;
+ ai->next = al;
+ al = ai;
+ }
+ }
+ *s = c;
+ } while (*s++);
+ }
+
+ /*
+ * charset
+ */
+
+ if (s = charset_name)
+ for (cp = lc_charsets; cp->code; cp++)
+ if (match_charset(s, cp))
+ break;
+#if AHA
+ if ((ast.locale.set & AST_LC_debug) && !(ast.locale.set & AST_LC_internal))
+ sfprintf(sfstderr, "locale make %s charset_name=%s cp=%s ppa=%s lp=%s\n", name, charset_name, cp ? cp->code : 0, ppa, lp->charset);
+#endif
+ if (!cp || !cp->code)
+ cp = ppa ? ppa : lp->charset;
+ mapped:
+ z = canonical(lp, tp, cp, al, 0, s = tmp, sizeof(tmp));
+
+ /*
+ * add to the list of possibly active locales
+ */
+
+ override:
+ n = strlen(name) + 1;
+ local[0].name = default_lc.name;
+ local[0].size = strlen(local[0].name);
+ local[1].name = default_lc.code;
+ local[1].size = strlen(local[1].name);
+ i = -1;
+ for (c = 0; c < elementsof(local); ++c)
+ if (strneq(name, local[c].name, local[c].size))
+ {
+ switch (name[local[c].size])
+ {
+ case '.':
+ case '_':
+ case 0:
+ i = c;
+ z += local[!i].size + n;
+ break;
+ }
+ break;
+ }
+ if (!(lc = newof(0, Lc_t, 1, n + z)))
+ return 0;
+ strcpy((char*)(lc->name = (const char*)(lc + 1)), name);
+ lc->code = lc->name + n;
+ if (i >= 0)
+ {
+ lc->flags |= LC_local;
+ strcpy((char*)lc->code, local[!i].name);
+ strcpy((char*)lc->code + local[!i].size, name + local[i].size);
+ }
+ else
+ strcpy((char*)lc->code, s);
+ lc->language = lp ? lp : &lc_languages[0];
+ lc->territory = tp ? tp : &lc_territories[0];
+ lc->charset = cp ? cp : &lc_charsets[0];
+ if (streq(lc->charset->code, "utf8"))
+ lc->flags |= LC_utf8;
+ lc->attributes = al;
+ for (i = 0; i < elementsof(lc->info); i++)
+ lc->info[i].lc = lc;
+#if _WINIX
+ n = SUBLANG_DEFAULT;
+ if (tp)
+ for (i = 0; i < elementsof(tp->languages); i++)
+ if (lp == tp->languages[i])
+ {
+ n = tp->indices[i];
+ break;
+ }
+ lc->index = MAKELCID(MAKELANGID(lp->index, n), SORT_DEFAULT);
+#endif
+ lc->next = lcs;
+ lcs = lc;
+ if ((ast.locale.set & AST_LC_debug) && !(ast.locale.set & AST_LC_internal))
+ sfprintf(sfstderr, "locale make %17s %16s %16s %16s language=%s territory=%s charset=%s%s\n", "", lc->name, lc->code, "", lc->language->name, lc->territory->name, lc->charset->code, (lc->flags & LC_local) ? " local" : "");
+ return lc;
+}
+
+/*
+ * return an Lc_t* for each locale in the tables
+ * one Lc_t is allocated on the first call with lc==0
+ * this is freed when 0 returned
+ * the return value is not part of the lcmake() cache
+ */
+
+typedef struct Lc_scan_s
+{
+ Lc_t lc;
+ Lc_attribute_list_t list;
+ int territory;
+ int language;
+ int attribute;
+ char buf[256];
+} Lc_scan_t;
+
+Lc_t*
+lcscan(Lc_t* lc)
+{
+ register Lc_scan_t* ls;
+
+ if (!(ls = (Lc_scan_t*)lc))
+ {
+ if (!(ls = newof(0, Lc_scan_t, 1, 0)))
+ return 0;
+ ls->lc.code = ls->lc.name = ls->buf;
+ ls->territory = -1;
+ ls->language = elementsof(ls->lc.territory->languages);
+ ls->attribute = elementsof(ls->lc.language->attributes);
+ }
+ if (++ls->attribute >= elementsof(ls->lc.language->attributes) || !(ls->list.attribute = ls->lc.language->attributes[ls->attribute]))
+ {
+ if (++ls->language >= elementsof(ls->lc.territory->languages) || !(ls->lc.language = ls->lc.territory->languages[ls->language]))
+ {
+ if (!lc_territories[++ls->territory].code)
+ {
+ free(ls);
+ return 0;
+ }
+ ls->lc.territory = &lc_territories[ls->territory];
+ ls->lc.language = ls->lc.territory->languages[ls->language = 0];
+ }
+ if (ls->lc.language)
+ {
+ ls->lc.charset = ls->lc.language->charset ? ls->lc.language->charset : &lc_charsets[0];
+ ls->list.attribute = ls->lc.language->attributes[ls->attribute = 0];
+ }
+ else
+ {
+ ls->lc.charset = &lc_charsets[0];
+ ls->list.attribute = 0;
+ }
+ }
+ ls->lc.attributes = ls->list.attribute ? &ls->list : (Lc_attribute_list_t*)0;
+#if _WINIX
+ if (!ls->lc.language || !ls->lc.language->index)
+ ls->lc.index = 0;
+ else
+ {
+ if ((!ls->list.attribute || !(ls->lc.index = ls->list.attribute->index)) &&
+ (!ls->lc.territory || !(ls->lc.index = ls->lc.territory->indices[ls->language])))
+ ls->lc.index = SUBLANG_DEFAULT;
+ ls->lc.index = MAKELCID(MAKELANGID(ls->lc.language->index, ls->lc.index), SORT_DEFAULT);
+ }
+#endif
+ canonical(ls->lc.language, ls->lc.territory, ls->lc.charset, ls->lc.attributes, 0, ls->buf, sizeof(ls->buf));
+ return (Lc_t*)ls;
+}
diff --git a/src/lib/libast/port/lc.tab b/src/lib/libast/port/lc.tab
new file mode 100644
index 0000000..87905a1
--- /dev/null
+++ b/src/lib/libast/port/lc.tab
@@ -0,0 +1,275 @@
+#
+# language_territory.charset@attribute tables
+#
+
+:charset:
+
+ iso8859-1 latin1|west-europe 1252
+ iso8859-2 latin2|east-europe 1250
+ iso8859-3 latin3|south-europe 1257
+ iso8859-4 latin4|north-europe
+ iso8859-5 cyrillic 1251
+ iso8859-6 arabic 1256
+ iso8859-7 greek 1253
+ iso8859-8 hebrew 1255
+ iso8859-9 latin5|turkish 1254
+ iso8859-10 latin6|nordic
+ iso8859-13 latin7
+ iso8859-14 latin8|celtic
+ iso8859-15 latin0
+ iso2022 japanese|korean
+ iso4873 japanese-ascii|korean-ascii
+ koi8-r russian
+ utf8 plan9
+
+:language:
+
+ aa afar
+ ab abkhazian
+ af afrikaans afr
+ am amharic
+ ar arabic ara iso8859-6
+ as assamese
+ ay aymara
+ az azerbaijani
+ ba bashkir
+ be belarusian bel
+ bg bulgarian bul iso8859-5
+ bh bihari
+ bi bislama
+ bn bengali-bangla
+ bo tibetan
+ br breton
+ ca catalan cat
+ co corsican
+ cs czech ces|cze iso8859-2
+ cy welsh
+ da danish dan
+ de german deu|ger
+ dz bhutani
+ el greek ell|gre iso8859-7
+ en english eng
+ eo esperanto
+ es spanish spa - traditional:default|modern
+ et estonian est iso8859-3
+ eu basque eus|baq
+ fa persian
+ fi finnish fin
+ fj fiji
+ fo faeroese
+ fr french fra|fre
+ fy frisian
+ ga irish - iso8859-14
+ gd scots-gaelic - iso8859-14
+ gl galician
+ gn guarani
+ gu gujarati
+ ha hausa
+ he hebrew heb iso8859-8
+ hi hindi
+ hr croatian hrv|scr iso8859-2
+ hu hungarian hun iso8859-2
+ hy armenian
+ ia interlingua
+ id indonesian ind
+ ie interlingue
+ ik inupiak
+ in indonesian
+ is icelandic isl|ice
+ it italian ita
+ iw hebrew
+ ja japanese jpn
+ ji yiddish
+ jw javanese
+ ka georgian
+ kk kazakh kaz
+ kl greenlandic
+ km cambodian
+ kn kannada
+ ko korean kor
+ ks kashmiri
+ ku kurdish
+ ky kirghiz
+ la latin
+ ln lingala
+ lo laothian
+ lt lithuanian lit iso8859-13
+ lv latvian lav iso8859-13
+ mg malagasy
+ mi maori
+ mk macedonian mkd|mac
+ ml malayalam mal
+ mn mongolian
+ mo moldavian
+ mr marathi
+ ms malay msa|may
+ mt maltese
+ my burmese
+ na nauru
+ nb norwegian-bokmal nob
+ ne nepali
+ nl dutch nld|dut
+ nn norwegian-nynorsk nno|non
+ no norwegian nor
+ oc occitan
+ om oromo
+ or oriya
+ pa punjabi
+ pl polish pol iso8859-2
+ ps pushto
+ pt portuguese por
+ qu quechua
+ rm rhaeto-romance
+ rn kirundi
+ ro romanian ron|rum iso8859-2
+ ru russian rus iso8859-5
+ rw kinyarwanda
+ sa sanskrit
+ sd sindhi
+ sg sangro
+ sh serbo-croatian
+ si singhalese
+ sk slovak slk|slo iso8859-2
+ sl slovenian slv iso8859-2
+ sm samoan
+ sn shona
+ so somali
+ sq albanian sqi|alb
+ sr serbian srp iso8859-2
+ ss siswati
+ st sesotho
+ su sudanese
+ sv swedish swe
+ sw swahili swa
+ ta tamil
+ te telugu
+ tg tajik
+ th thai tha
+ ti tigrinya
+ tk turkmen
+ tl tagalog
+ tn setswana
+ to tonga
+ tr turkish tur iso8859-9
+ ts tsonga
+ tt tatar tat
+ tw chinese-traditional cht
+ uk ukrainian ukr iso8859-5
+ ur urdu
+ uz uzbek uzb
+ vi vietnamese
+ vo volapuk
+ wo wolof
+ xh xhosa
+ yo yoruba
+ zh chinese-simplified zho|chi|chs
+ zu zulu
+
+:territory:
+
+ al albania
+ an netherlands-antilles nl
+ ar argentina es
+ at austria de
+ au australia en
+ az azerbaijan
+ be belgium nl|fr|de
+ bg bulgaria bg
+ bn brunei-darussalam ar
+ bo bolivia es
+ br brazil pt
+ bw botswana en
+ by belarus ru
+ bz belize en
+ ca canada en|fr
+ ch switzerland fr|de|it
+ cl chile es
+ cn china zh:primary
+ co colombia es
+ cr costa-rica es
+ cz czech-republic cs
+ de germany de
+ dk denmark da|en
+ do dominican-republic es
+ dz algeria
+ ec ecuador es
+ ee estonia et
+ eg egypt ar
+ es spain es|ca|eu|gl
+ fi finland sv
+ fo faroe-islands fo
+ fr france fr
+ gb united-kingdom|great-britain|england en:primary
+ gl greenland kl
+ gr greece el
+ gt guatemala es
+ hk hong-kong zh
+ hn honduras es
+ hr croatia hr
+ hu hungary hu
+ id indonesia id
+ ie ireland en|ga
+ il israel he
+ iq iraq ar
+ is iceland is
+ it italy it
+ jm jamaica en
+ jo jordan ar
+ jp japan ja
+ ke kenya
+ kr south-korea ko
+ kw kuwait ar
+ lb lebanon ar
+ li liechtenstein de|fr
+ lt lithuania lt
+ lu luxembourg de|fr
+ lv latvia lv
+ ly libya ar
+ ma morocco ar
+ mk macedonia mk
+ mo macau zh
+ mx mexico es
+ my malaysia
+ ni nicaragua es
+ nl netherlands nl
+ no norway nb|no|nn
+ nz new-zealand en
+ om oman ar
+ pa panama es
+ pe peru es
+ pl poland pl
+ pr puerto-rico es
+ pt portugal pt
+ py paraguay es
+ ro romania ro
+ ru russia ru
+ sa saudi-arabia ar
+ se sweden sv:primary
+ sg singapore zh
+ si slovenia sl
+ sk slovakia sk
+ sp serbia sr
+ sv el-salvador es
+ sy syria ar
+ th thailand th
+ tn tunisia ar
+ tr turkey tr
+ tt trinidad&tobago en
+ tw taiwan tw
+ ua ukraine uk|ru
+ uk united-kingdom en:primary
+ us united-states|usa en
+ uy uruguay es
+ ve venezuela es
+ yu yugoslavia sr
+ za south-africa af
+ zw zimbabwe en
+
+:map:
+
+ enu en us
+ enz en nz
+ esm es mx
+ esn es es - modern
+ esp es es - traditional
+ usa en us
diff --git a/src/lib/libast/port/lcgen.c b/src/lib/libast/port/lcgen.c
new file mode 100644
index 0000000..82eb88d
--- /dev/null
+++ b/src/lib/libast/port/lcgen.c
@@ -0,0 +1,791 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * generate <lc.h> implementation tables from lc.tab
+ * this must make it through vanilla cc with no -last
+ *
+ * # comment
+ * :charset:
+ * code name ms-codepage
+ * :language:
+ * code name alt1|alt2... charset|... attr1|attr2|...
+ * ...
+ * :territory:
+ * code name lang1|lang2...
+ * :abbreviation:
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+typedef struct Link_s
+{
+ struct Link_s* next;
+ char* code;
+ int index;
+} Link_t;
+
+typedef struct Table_s
+{
+ Link_t* root;
+ int count;
+} Table_t;
+
+typedef struct Abbreviation_s
+{
+ Link_t link;
+ char* value;
+} Abbreviation_t;
+
+typedef struct Attribute_s
+{
+ Link_t link;
+} Attribute_t;
+
+typedef struct Attribute_list_s
+{
+ struct Attribute_list_s*next;
+ Attribute_t* attribute;
+} Attribute_list_t;
+
+typedef struct Charset_s
+{
+ Link_t link;
+ char* alternates;
+ char* ms;
+} Charset_t;
+
+typedef struct Language_s
+{
+ Link_t link;
+ char* name;
+ char* alternates;
+ Charset_t* charset;
+ Attribute_list_t* attributes;
+} Language_t;
+
+typedef struct Language_list_s
+{
+ struct Language_list_s* next;
+ Language_t* language;
+} Language_list_t;
+
+typedef struct Territory_s
+{
+ Link_t link;
+ char* name;
+ Language_list_t* languages;
+ int primary;
+ int index;
+} Territory_t;
+
+typedef struct Map_s
+{
+ Link_t link;
+ Language_t* language;
+ Territory_t* territory;
+ Charset_t* charset;
+ Attribute_t* attribute;
+} Map_t;
+
+static struct State_s
+{
+ Table_t attribute;
+ Table_t charset;
+ Table_t language;
+ Table_t territory;
+ Table_t map;
+} state;
+
+#define INIT 0
+#define CHARSET 1
+#define LANGUAGE 2
+#define TERRITORY 3
+#define MAP 4
+
+#define elementsof(x) (sizeof(x)/sizeof(x[0]))
+#define newof(p,t,n,x) ((t*)malloc(sizeof(t)*(n)+(x)))
+
+static Link_t*
+#if defined(__STDC__) || defined(__cplusplus)
+enter(register Table_t* tab, register Link_t* v)
+#else
+enter(tab, v)
+register Table_t* tab;
+register Link_t* v;
+#endif
+{
+ register Link_t* x;
+ register Link_t* p;
+
+ for (p = 0, x = tab->root; x; p = x, x = x->next)
+ if (!strcmp(x->code, v->code))
+ return x;
+ if (p)
+ p->next = v;
+ else
+ tab->root = v;
+ v->next = 0;
+ v->index = tab->count++;
+ return v;
+}
+
+static Link_t*
+#if defined(__STDC__) || defined(__cplusplus)
+lookup(register Table_t* tab, register char* s)
+#else
+lookup(tab, s)
+register Table_t* tab;
+register char* s;
+#endif
+{
+ register Link_t* x;
+
+ for (x = tab->root; x; x = x->next)
+ if (!strcmp(x->code, s))
+ return x;
+ return 0;
+}
+
+static char*
+#if defined(__STDC__) || defined(__cplusplus)
+copy(char** p, register char* f)
+#else
+copy(p, f)
+char** p;
+register char* f;
+#endif
+{
+ register char* t;
+ char* b;
+
+ if (!f)
+ return 0;
+ b = t = *p;
+ while (*t++ = *f++);
+ *p = t;
+ return b;
+}
+
+static void
+#if defined(__STDC__) || defined(__cplusplus)
+macro(FILE* f, char* p1, char* p2, char* p3)
+#else
+macro(f, p1, p2, p3)
+FILE* f;
+char* p1;
+char* p2;
+char* p3;
+#endif
+{
+ register int c;
+ register char* s;
+ register char* b;
+ register char* e;
+ int i;
+ int m;
+ int n;
+ char* part[4];
+ char buf[128];
+
+ part[0] = p1;
+ part[1] = p2;
+ part[2] = p3;
+ part[3] = 0;
+ n = 0;
+ fprintf(f, "\n");
+ do
+ {
+ i = m = 0;
+ b = buf;
+ e = &buf[sizeof(buf)-1];
+ while (b < e)
+ {
+ if (!(s = part[i++]))
+ break;
+ if (i > 1)
+ *b++ = '_';
+ while ((c = *s++) && b < e)
+ {
+ if (c == '|')
+ {
+ part[i-1] = s;
+ m = 1;
+ break;
+ }
+ else if (islower(c))
+ c = toupper(c);
+ else if (!isalnum(c))
+ c = '_';
+ *b++ = c;
+ }
+ }
+ *b = 0;
+ fprintf(f, "#ifdef %s\n%s,\n#else\n", buf, buf);
+ n++;
+ } while (m);
+ fprintf(f, "0,\n");
+ while (n-- > 0)
+ fprintf(f, "#endif\n");
+}
+
+#if defined(__STDC__) || defined(__cplusplus)
+int
+main(int argc, char** argv)
+#else
+int
+main(argc, argv)
+int argc;
+char** argv;
+#endif
+{
+ register char* s;
+ register char** vp;
+ register char** ve;
+ Attribute_t* ap;
+ Attribute_list_t* al;
+ Attribute_list_t* az;
+ Charset_t* cp;
+ Territory_t* tp;
+ Language_t* lp;
+ Language_list_t* ll;
+ Language_list_t* lz;
+ Map_t* mp;
+ char* b;
+ char* f;
+ char* command;
+ char* hdr;
+ char* lib;
+ FILE* hf;
+ FILE* lf;
+ int c;
+ int i;
+ int line;
+ int type;
+ int language_attribute_max;
+ int territory_language_max;
+ char* arg[5];
+ char buf[1024];
+
+ command = *argv++;
+ line = 0;
+ if (!(hdr = *argv++) || !(lib = *argv++) || *argv)
+ {
+ fprintf(stderr, "%s: { hdr lib tab } arguments expected\n", command);
+ return 1;
+ }
+ if (!(hf = fopen(hdr, "w")))
+ {
+ fprintf(stderr, "%s: %s: cannot write\n", command, hdr);
+ return 1;
+ }
+ if (!(lf = fopen(lib, "w")))
+ {
+ fprintf(stderr, "%s: %s: cannot write\n", command, lib);
+ return 1;
+ }
+ type = 0;
+ language_attribute_max = 0;
+ territory_language_max = 0;
+ state.language.count = 2;
+ state.territory.count = 3;
+ ve = &arg[elementsof(arg)];
+ fprintf(hf, "/* : : generated by %s : : */\n", command);
+ fprintf(hf, "#pragma prototyped\n");
+ fprintf(hf, "\n");
+ fprintf(hf, "#ifndef _LC_H\n");
+ fprintf(hf, "#define _LC_H\t\t\t1\n");
+ fprintf(hf, "\n");
+ fprintf(hf, "#include <ast.h>\n");
+ fprintf(hf, "\n");
+ fprintf(hf, "#define LC_abbreviated\t\t0x00001\n");
+ fprintf(hf, "#define LC_checked\t\t0x00002\n");
+ fprintf(hf, "#define LC_debug\t\t0x00004\n");
+ fprintf(hf, "#define LC_default\t\t0x00008\n");
+ fprintf(hf, "#define LC_defined\t\t0x00010\n");
+ fprintf(hf, "#define LC_local\t\t0x00020\n");
+ fprintf(hf, "#define LC_primary\t\t0x00040\n");
+ fprintf(hf, "#define LC_qualified\t\t0x00080\n");
+ fprintf(hf, "#define LC_undefined\t\t0x00100\n");
+ fprintf(hf, "#define LC_utf8\t\t\t0x00200\n");
+ fprintf(hf, "#define LC_verbose\t\t0x00400\n");
+ fprintf(hf, "#define LC_setlocale\t\t0x10000\n");
+ fprintf(hf, "#define LC_setenv\t\t0x20000\n");
+ fprintf(hf, "#define LC_user\t\t\t0x40000\n");
+ fprintf(lf, "/* : : generated by %s : : */\n", command);
+ fprintf(lf, "\n");
+ fprintf(lf, "#include \"lclib.h\"\n");
+ fprintf(lf, "#include \"lclang.h\"\n");
+ fprintf(lf, "\n");
+ while (s = fgets(buf, sizeof(buf), stdin))
+ {
+ line++;
+ while (isspace(*s))
+ s++;
+ if (!*s || *s == '#')
+ continue;
+ b = s;
+ vp = arg;
+ for (;;)
+ {
+ for (*vp++ = s; *s && !isspace(*s); s++);
+ if (!*s)
+ break;
+ for (*s++ = 0; isspace(*s); s++);
+ if (!strcmp(*(vp - 1), "-"))
+ *(vp - 1) = 0;
+ if (!*s || vp >= ve)
+ break;
+ }
+ while (vp < ve)
+ *vp++ = 0;
+ if (*arg[0] == ':')
+ {
+ if (!strcmp(arg[0], ":map:"))
+ {
+ if (type != TERRITORY)
+ {
+ fprintf(stderr, "%s: %d: %s: must be specified after :territory:\n", command, line, arg[0]);
+ return 1;
+ }
+ type = MAP;
+ continue;
+ }
+ else if (!strcmp(arg[0], ":charset:"))
+ {
+ if (type != INIT)
+ {
+ fprintf(stderr, "%s: %d: %s must be specified first\n", command, line, arg[0]);
+ return 1;
+ }
+ type = CHARSET;
+ continue;
+ }
+ else if (!strcmp(arg[0], ":territory:"))
+ {
+ if (type != LANGUAGE)
+ {
+ fprintf(stderr, "%s: %d: %s: must be specified after :language:\n", command, line, arg[0]);
+ return 1;
+ }
+ type = TERRITORY;
+ continue;
+ }
+ else if (!strcmp(arg[0], ":language:"))
+ {
+ if (type != CHARSET)
+ {
+ fprintf(stderr, "%s: %d: %s must be specified after :charset:\n", command, line, arg[0]);
+ return 1;
+ }
+ type = LANGUAGE;
+ continue;
+ }
+ else
+ {
+ fprintf(stderr, "%s: %d: %s invalid\n", command, line, arg[0]);
+ return 1;
+ }
+ }
+ if (!arg[1])
+ {
+ fprintf(stderr, "%s: %d: at least two arguments expected\n", command, line);
+ return 1;
+ }
+ switch (type)
+ {
+ case CHARSET:
+ if (!(cp = newof(0, Charset_t, 1, s - b + 1)))
+ {
+ fprintf(stderr, "%s: %d: out of space\n", command, line);
+ return 1;
+ }
+ b = (char*)(cp + 1);
+ cp->link.code = copy(&b, arg[0]);
+ cp->alternates = copy(&b, arg[1]);
+ cp->ms = copy(&b, arg[2]);
+ if (cp != (Charset_t*)enter(&state.charset, (Link_t*)cp))
+ {
+ fprintf(stderr, "%s: %d: %s: duplicate charset\n", command, line, cp->link.code);
+ return 1;
+ }
+ break;
+ case TERRITORY:
+ if (!(tp = newof(0, Territory_t, 1, s - b + 1)))
+ {
+ fprintf(stderr, "%s: %d: out of space\n", command, line);
+ return 1;
+ }
+ b = (char*)(tp + 1);
+ tp->link.code = copy(&b, arg[0]);
+ tp->name = copy(&b, arg[1]);
+ tp->languages = 0;
+ if (s = copy(&b, arg[2]))
+ {
+ i = 0;
+ while (*(b = s))
+ {
+ for (; *s && *s != ':' && *s != '|'; s++);
+ if (c = *s)
+ *s++ = 0;
+ if (!(lp = (Language_t*)lookup(&state.language, b)))
+ {
+ fprintf(stderr, "%s: %d: %s: unknown language\n", command, line, b);
+ return 1;
+ }
+ if (!(ll = newof(0, Language_list_t, 1, 0)))
+ {
+ fprintf(stderr, "%s: %d: out of space\n", command, line);
+ return 1;
+ }
+ if (!tp->languages)
+ tp->languages = ll;
+ else
+ lz->next = ll;
+ lz = ll;
+ ll->language = lp;
+ ll->next = 0;
+ i++;
+ if (c == ':')
+ {
+ for (b = s; *s && *s != '|'; s++);
+ if (*s)
+ *s++ = 0;
+ if (!strcmp(b, "primary"))
+ tp->primary = 1;
+ }
+ }
+ if (territory_language_max < i)
+ territory_language_max = i;
+ }
+ if (tp != (Territory_t*)enter(&state.territory, (Link_t*)tp))
+ {
+ fprintf(stderr, "%s: %d: %s: duplicate territory\n", command, line, tp->link.code);
+ return 1;
+ }
+ break;
+ case LANGUAGE:
+ if (!(lp = newof(0, Language_t, 1, s - b + 1)))
+ {
+ fprintf(stderr, "%s: %d: out of space\n", command, line);
+ return 1;
+ }
+ b = (char*)(lp + 1);
+ lp->link.code = copy(&b, arg[0]);
+ lp->name = copy(&b, arg[1]);
+ lp->alternates = copy(&b, arg[2]);
+ if (!arg[3])
+ lp->charset = 0;
+ else if (!(lp->charset = (Charset_t*)lookup(&state.charset, arg[3])))
+ {
+ fprintf(stderr, "%s: %d: %s: unknown charset\n", command, line, arg[3]);
+ return 1;
+ }
+ lp->attributes = 0;
+ if (s = copy(&b, arg[4]))
+ {
+ i = 0;
+ fprintf(lf, "\nconst Lc_attribute_t attribute_%s[] =\n{\n", lp->link.code);
+ while (*(b = s))
+ {
+ for (f = 0; *s && *s != '|'; s++)
+ if (*s == ':')
+ {
+ *s++ = 0;
+ f = s;
+ }
+ if (*s)
+ *s++ = 0;
+ fprintf(lf, "{\"%s\",", b);
+ if (f)
+ fprintf(lf, "LC_%s,", f);
+ else
+ fprintf(lf, "0,");
+ if (!(ap = newof(0, Attribute_t, 1, 0)))
+ {
+ fprintf(stderr, "%s: %d: out of space\n", command, line);
+ return 1;
+ }
+ ap->link.code = b;
+ ap->link.index = i++;
+ if (!(al = newof(0, Attribute_list_t, 1, 0)))
+ {
+ fprintf(stderr, "%s: %d: out of space\n", command, line);
+ return 1;
+ }
+ if (!lp->attributes)
+ lp->attributes = al;
+ else
+ az->next = al;
+ az = al;
+ al->attribute = ap;
+ al->next = 0;
+ macro(lf, "SUBLANG", lp->name, b);
+ fprintf(lf, "\n},\n");
+ }
+ if (language_attribute_max < i)
+ language_attribute_max = i;
+ fprintf(lf, "};\n");
+ }
+ if (lp != (Language_t*)enter(&state.language, (Link_t*)lp))
+ {
+ fprintf(stderr, "%s: %d: %s: duplicate language\n", command, line, lp->link.code);
+ return 1;
+ }
+ break;
+ case MAP:
+ if (!(mp = newof(0, Map_t, 1, s - b + 1)))
+ {
+ fprintf(stderr, "%s: %d: out of space\n", command, line);
+ return 1;
+ }
+ b = (char*)(mp + 1);
+ mp->link.code = copy(&b, arg[0]);
+ if (!arg[2])
+ {
+ fprintf(stderr, "%s: %d: territory code expected\n", command, line);
+ return 1;
+ }
+ if (!(mp->language = (Language_t*)lookup(&state.language, arg[1])))
+ {
+ fprintf(stderr, "%s: %d: %s: unknown language\n", command, line, arg[1]);
+ return 1;
+ }
+ if (!(mp->territory = (Territory_t*)lookup(&state.territory, arg[2])))
+ {
+ fprintf(stderr, "%s: %d: %s: unknown territory\n", command, line, arg[2]);
+ return 1;
+ }
+ if (!arg[3])
+ mp->charset = 0;
+ else if (!(mp->charset = (Charset_t*)lookup(&state.charset, arg[3])))
+ {
+ fprintf(stderr, "%s: %d: %s: unknown charset\n", command, line, arg[3]);
+ return 1;
+ }
+ mp->attribute = 0;
+ if (arg[4])
+ {
+ for (al = mp->language->attributes; al; al = al->next)
+ if (!strcmp(al->attribute->link.code, arg[4]))
+ {
+ mp->attribute = al->attribute;
+ break;
+ }
+ if (!mp->attribute)
+ {
+ fprintf(stderr, "%s: %d: %s: unknown attribute\n", command, line, arg[4]);
+ return 1;
+ }
+ }
+ if (mp != (Map_t*)enter(&state.map, (Link_t*)mp))
+ {
+ fprintf(stderr, "%s: %d: %s: duplicate map\n", command, line, mp->link.code);
+ return 1;
+ }
+ break;
+ }
+ }
+ if (!language_attribute_max)
+ language_attribute_max = 1;
+ if (!territory_language_max)
+ territory_language_max = 1;
+ fprintf(hf, "\n#define LC_language_attribute_max\t%d\n", language_attribute_max);
+ fprintf(hf, "#define LC_territory_language_max\t%d\n", territory_language_max);
+ fprintf(hf, "\nstruct Lc_s;\n");
+ fprintf(hf, "\ntypedef struct Lc_info_s\n{\n");
+ fprintf(hf, "\tconst struct Lc_s*\tlc;\n");
+ fprintf(hf, "\tunsigned long\t\tnumber;\n");
+ fprintf(hf, "\tvoid*\t\t\tdata;\n");
+ fprintf(hf, "} Lc_info_t;\n");
+ fprintf(hf, "\ntypedef struct Lc_attribute_s\n{\n");
+ fprintf(hf, "\tconst char*\t\tname;\n");
+ fprintf(hf, "\tunsigned long\t\tflags;\n");
+ fprintf(hf, "\tunsigned long\t\tindex;\n");
+ fprintf(hf, "} Lc_attribute_t;\n");
+ fprintf(hf, "\ntypedef struct Lc_charset_s\n{\n");
+ fprintf(hf, "\tconst char*\t\tcode;\n");
+ fprintf(hf, "\tconst char*\t\talternates;\n");
+ fprintf(hf, "\tconst char*\t\tms;\n");
+ fprintf(hf, "\tunsigned long\t\tindex;\n");
+ fprintf(hf, "} Lc_charset_t;\n");
+ fprintf(hf, "\ntypedef struct Lc_language_s\n{\n");
+ fprintf(hf, "\tconst char*\t\tcode;\n");
+ fprintf(hf, "\tconst char*\t\tname;\n");
+ fprintf(hf, "\tconst char*\t\talternates;\n");
+ fprintf(hf, "\tconst Lc_charset_t*\tcharset;\n");
+ fprintf(hf, "\tunsigned long\t\tflags;\n");
+ fprintf(hf, "\tunsigned long\t\tindex;\n");
+ fprintf(hf, "\tconst Lc_attribute_t*\tattributes[LC_language_attribute_max];\n");
+ fprintf(hf, "} Lc_language_t;\n");
+ fprintf(hf, "\ntypedef struct Lc_territory_s\n{\n");
+ fprintf(hf, "\tconst char*\t\tcode;\n");
+ fprintf(hf, "\tconst char*\t\tname;\n");
+ fprintf(hf, "\tunsigned long\t\tflags;\n");
+ fprintf(hf, "\tunsigned long\t\tindex;\n");
+ fprintf(hf, "\tconst Lc_language_t*\tlanguages[LC_territory_language_max];\n");
+ fprintf(hf, "#ifdef _LC_TERRITORY_PRIVATE_\n");
+ fprintf(hf, "\t_LC_TERRITORY_PRIVATE_\n");
+ fprintf(hf, "#endif\n");
+ fprintf(hf, "} Lc_territory_t;\n");
+ fprintf(hf, "\ntypedef struct Lc_map_s\n{\n");
+ fprintf(hf, "\tconst char*\t\tcode;\n");
+ fprintf(hf, "\tconst Lc_language_t*\tlanguage;\n");
+ fprintf(hf, "\tconst Lc_territory_t*\tterritory;\n");
+ fprintf(hf, "\tconst Lc_charset_t*\tcharset;\n");
+ fprintf(hf, "\tconst Lc_attribute_t*\tattribute;\n");
+ fprintf(hf, "} Lc_map_t;\n");
+ fprintf(hf, "\ntypedef struct Lc_attribute_list_s\n{\n");
+ fprintf(hf, "\tstruct Lc_attribute_list_s*\tnext;\n");
+ fprintf(hf, "\tconst Lc_attribute_t*\t\tattribute;\n");
+ fprintf(hf, "} Lc_attribute_list_t;\n");
+ fprintf(hf, "\ntypedef struct Lc_s\n{\n");
+ fprintf(hf, "\tconst char*\t\tname;\n");
+ fprintf(hf, "\tconst char*\t\tcode;\n");
+ fprintf(hf, "\tconst Lc_language_t*\tlanguage;\n");
+ fprintf(hf, "\tconst Lc_territory_t*\tterritory;\n");
+ fprintf(hf, "\tconst Lc_charset_t*\tcharset;\n");
+ fprintf(hf, "\tconst Lc_attribute_list_t*\tattributes;\n");
+ fprintf(hf, "\tunsigned long\t\tflags;\n");
+ fprintf(hf, "\tunsigned long\t\tindex;\n");
+ fprintf(hf, "#ifdef _LC_PRIVATE_\n");
+ fprintf(hf, "\t_LC_PRIVATE_\n");
+ fprintf(hf, "#endif\n");
+ fprintf(hf, "} Lc_t;\n");
+ fprintf(hf, "\nstruct Lc_category_s;\n");
+ fprintf(hf, "\ntypedef int (*Lc_category_set_f)(struct Lc_category_s*);\n");
+ fprintf(hf, "\ntypedef struct Lc_category_s\n{\n");
+ fprintf(hf, "\tconst char*\t\tname;\n");
+ fprintf(hf, "\tint\t\t\texternal;\n");
+ fprintf(hf, "\tint\t\t\tinternal;\n");
+ fprintf(hf, "\tLc_category_set_f\tsetf;\n");
+ fprintf(hf, "\tLc_t*\t\t\tprev;\n");
+ fprintf(hf, "\tunsigned int\t\tflags;\n");
+ fprintf(hf, "} Lc_category_t;\n");
+ fprintf(hf, "\n");
+ fprintf(hf, "#if _BLD_ast && defined(__EXPORT__)\n");
+ fprintf(hf, "#define extern\t\t__EXPORT__\n");
+ fprintf(hf, "#endif\n");
+ fprintf(hf, "\n");
+ fprintf(hf, "extern size_t\t\tlccanon(Lc_t*, unsigned long flags, char*, size_t);\n");
+ fprintf(hf, "extern Lc_category_t*\tlccategories(void);\n");
+ fprintf(hf, "extern int\t\tlcindex(int, int);\n");
+ fprintf(hf, "extern Lc_info_t*\tlcinfo(int);\n");
+ fprintf(hf, "extern Lc_t*\t\tlcmake(const char*);\n");
+ fprintf(hf, "extern Lc_t*\t\tlcscan(Lc_t*);\n");
+ fprintf(hf, "\n");
+ fprintf(hf, "#undef\textern\n");
+ fprintf(lf, "\nconst Lc_charset_t lc_charsets[] =\n{\n");
+ for (cp = (Charset_t*)state.charset.root; cp; cp = (Charset_t*)cp->link.next)
+ {
+ fprintf(lf, "{\"%s\",", cp->link.code);
+ if (cp->alternates)
+ fprintf(lf, "\"%s\",", cp->alternates);
+ else
+ fprintf(lf, "0,");
+ if (cp->ms)
+ fprintf(lf, "\"%s\",", cp->ms);
+ else
+ fprintf(lf, "0");
+ fprintf(lf, "},\n");
+ }
+ fprintf(lf, "\t0\n};\n");
+ fprintf(lf, "\nconst Lc_language_t lc_languages[] =\n{\n");
+ fprintf(lf, "{\"C\",\"C\",\"POSIX\",&lc_charsets[0],LC_default,0,");
+ for (i = 0; i < language_attribute_max; i++)
+ fprintf(lf, "0,");
+ fprintf(lf, "},\n");
+ fprintf(lf, "{\"debug\",\"debug\",0,&lc_charsets[0],LC_debug,0,");
+ for (i = 0; i < language_attribute_max; i++)
+ fprintf(lf, "0,");
+ fprintf(lf, "},\n");
+ for (lp = (Language_t*)state.language.root; lp; lp = (Language_t*)lp->link.next)
+ {
+ fprintf(lf, "{\"%s\",\"%s\",", lp->link.code, lp->name);
+ if (lp->alternates)
+ fprintf(lf, "\"%s\",", lp->alternates);
+ else
+ fprintf(lf, "0,");
+ fprintf(lf, "&lc_charsets[%d],0,", lp->charset ? lp->charset->link.index : 0);
+ macro(lf, "LANG", lp->name, (char*)0);
+ for (i = 0, al = lp->attributes; al; al = al->next, i++)
+ fprintf(lf, "&attribute_%s[%d],", lp->link.code, al->attribute->link.index);
+ for (; i < language_attribute_max; i++)
+ fprintf(lf, "0,");
+ fprintf(lf, "\n},\n");
+ }
+ fprintf(lf, "\t0\n};\n");
+ fprintf(lf, "\nconst Lc_territory_t lc_territories[] =\n{\n");
+ fprintf(lf, "{\"C\",\"C\",LC_default,0,&lc_languages[0],");
+ for (i = 1; i < 2 * territory_language_max; i++)
+ fprintf(lf, "0,");
+ fprintf(lf, "},\n");
+ fprintf(lf, "{\"debug\",\"debug\",LC_debug,0,&lc_languages[1],");
+ for (i = 1; i < 2 * territory_language_max; i++)
+ fprintf(lf, "0,");
+ fprintf(lf, "},\n");
+ fprintf(lf, "{\"eu\",\"euro\",0,0,&lc_languages[0],");
+ for (i = 1; i < 2 * territory_language_max; i++)
+ fprintf(lf, "0,");
+ fprintf(lf, "},\n");
+ for (tp = (Territory_t*)state.territory.root; tp; tp = (Territory_t*)tp->link.next)
+ {
+ fprintf(lf, "{\"%s\",\"%s\",", tp->link.code, tp->name);
+ if (tp->primary)
+ fprintf(lf, "LC_primary,");
+ else
+ fprintf(lf, "0,");
+ macro(lf, "CTRY", tp->name, (char*)0);
+ for (i = 0, ll = tp->languages; ll; ll = ll->next, i++)
+ fprintf(lf, "&lc_languages[%d],", ll->language->link.index);
+ for (; i < territory_language_max; i++)
+ fprintf(lf, "0,");
+ for (i = 0, ll = tp->languages; ll; ll = ll->next, i++)
+ macro(lf, "SUBLANG", ll->language->name, tp->name);
+ for (; i < territory_language_max; i++)
+ fprintf(lf, "0,");
+ fprintf(lf, "\n},\n");
+ }
+ fprintf(lf, "\t0\n};\n");
+ fprintf(lf, "\nconst Lc_map_t lc_maps[] =\n{\n");
+ for (mp = (Map_t*)state.map.root; mp; mp = (Map_t*)mp->link.next)
+ {
+ fprintf(lf, "{\"%s\",", mp->link.code);
+ fprintf(lf, "&lc_languages[%d],", mp->language->link.index);
+ fprintf(lf, "&lc_territories[%d],", mp->territory->link.index);
+ fprintf(lf, "&lc_charsets[%d],", mp->charset ? mp->charset->link.index : 0);
+ if (mp->attribute)
+ fprintf(lf, "&attribute_%s[%d]", mp->language->link.code, mp->attribute->link.index);
+ else
+ fprintf(lf, "0");
+ fprintf(lf, "},\n");
+ }
+ fprintf(lf, "\t0\n};\n");
+ fclose(lf);
+ fprintf(hf, "\n#endif\n");
+ fclose(hf);
+ return 0;
+}
diff --git a/src/lib/libast/port/lclang.h b/src/lib/libast/port/lclang.h
new file mode 100644
index 0000000..356f2b0
--- /dev/null
+++ b/src/lib/libast/port/lclang.h
@@ -0,0 +1,120 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * lc (sub)lang definitions -- very windowsish
+ */
+
+#if _WINIX
+
+#include <ast_windows.h>
+
+#ifndef LANG_CHINESE_SIMPLIFIED
+#define LANG_CHINESE_SIMPLIFIED LANG_CHINESE
+#endif
+#ifndef LANG_CHINESE_TRADITIONAL
+#define LANG_CHINESE_TRADITIONAL LANG_CHINESE
+#endif
+#ifndef LANG_NORWEGIAN_BOKMAL
+#define LANG_NORWEGIAN_BOKMAL LANG_NORWEGIAN
+#endif
+#ifndef LANG_NORWEGIAN_NYNORSK
+#define LANG_NORWEGIAN_NYNORSK LANG_NORWEGIAN
+#endif
+#ifndef LANG_SERBO_CROATIAN
+#define LANG_SERBO_CROATIAN LANG_CROATIAN
+#endif
+
+#ifndef CTRY_CZECH_REPUBLIC
+#define CTRY_CZECH_REPUBLIC CTRY_CZECH
+#endif
+
+#ifndef SUBLANG_CHINESE_SIMPLIFIED_CHINA
+#define SUBLANG_CHINESE_SIMPLIFIED_CHINA SUBLANG_CHINESE_SIMPLIFIED
+#endif
+#ifndef SUBLANG_CHINESE_SIMPLIFIED_HONG_KONG
+#define SUBLANG_CHINESE_SIMPLIFIED_HONG_KONG SUBLANG_CHINESE_HONGKONG
+#endif
+#ifndef SUBLANG_CHINESE_SIMPLIFIED_SINGAPORE
+#define SUBLANG_CHINESE_SIMPLIFIED_SINGAPORE SUBLANG_CHINESE_SINGAPORE
+#endif
+#ifndef SUBLANG_CHINESE_TRADITIONAL_TAIWAN
+#define SUBLANG_CHINESE_TRADITIONAL_TAIWAN SUBLANG_CHINESE_TRADITIONAL
+#endif
+#ifndef SUBLANG_DUTCH_NETHERLANDS_ANTILLES
+#define SUBLANG_DUTCH_NETHERLANDS_ANTILLES SUBLANG_DUTCH
+#endif
+#ifndef SUBLANG_DUTCH_BELGIUM
+#define SUBLANG_DUTCH_BELGIUM SUBLANG_DUTCH_BELGIAN
+#endif
+#ifndef SUBLANG_ENGLISH_AUSTRALIA
+#define SUBLANG_ENGLISH_AUSTRALIA SUBLANG_ENGLISH_AUS
+#endif
+#ifndef SUBLANG_ENGLISH_CANADA
+#define SUBLANG_ENGLISH_CANADA SUBLANG_ENGLISH_CAN
+#endif
+#ifndef SUBLANG_ENGLISH_IRELAND
+#define SUBLANG_ENGLISH_IRELAND SUBLANG_ENGLISH_EIRE
+#endif
+#ifndef SUBLANG_ENGLISH_NEW_ZEALAND
+#define SUBLANG_ENGLISH_NEW_ZEALAND SUBLANG_ENGLISH_NZ
+#endif
+#ifndef SUBLANG_ENGLISH_TRINIDAD_TOBAGO
+#define SUBLANG_ENGLISH_TRINIDAD_TOBAGO SUBLANG_ENGLISH_CARIBBEAN
+#endif
+#ifndef SUBLANG_ENGLISH_UNITED_KINGDOM
+#define SUBLANG_ENGLISH_UNITED_KINGDOM SUBLANG_ENGLISH_UK
+#endif
+#ifndef SUBLANG_ENGLISH_UNITED_STATES
+#define SUBLANG_ENGLISH_UNITED_STATES SUBLANG_ENGLISH_US
+#endif
+#ifndef SUBLANG_FRENCH_BELGIUM
+#define SUBLANG_FRENCH_BELGIUM SUBLANG_FRENCH_BELGIAN
+#endif
+#ifndef SUBLANG_FRENCH_CANADA
+#define SUBLANG_FRENCH_CANADA SUBLANG_FRENCH_CANADIAN
+#endif
+#ifndef SUBLANG_FRENCH_SWITZERLAND
+#define SUBLANG_FRENCH_SWITZERLAND SUBLANG_FRENCH_SWISS
+#endif
+#ifndef SUBLANG_GERMAN_AUSTRIA
+#define SUBLANG_GERMAN_AUSTRIA SUBLANG_GERMAN_AUSTRIAN
+#endif
+#ifndef SUBLANG_GERMAN_SWITZERLAND
+#define SUBLANG_GERMAN_SWITZERLAND SUBLANG_GERMAN_SWISS
+#endif
+#ifndef SUBLANG_ITALIAN_SWITZERLAND
+#define SUBLANG_ITALIAN_SWITZERLAND SUBLANG_ITALIAN_SWISS
+#endif
+#ifndef SUBLANG_NORWEGIAN_BOKMAL_NORWAY
+#define SUBLANG_NORWEGIAN_BOKMAL_NORWAY SUBLANG_NORWEGIAN_BOKMAL
+#endif
+#ifndef SUBLANG_NORWEGIAN_NORWAY
+#define SUBLANG_NORWEGIAN_NORWAY SUBLANG_NORWEGIAN_BOKMAL
+#endif
+#ifndef SUBLANG_NORWEGIAN_NYNORSK_NORWAY
+#define SUBLANG_NORWEGIAN_NYNORSK_NORWAY SUBLANG_NORWEGIAN_NYNORSK
+#endif
+#ifndef SUBLANG_PORTUGUESE_BRAZIL
+#define SUBLANG_PORTUGUESE_BRAZIL SUBLANG_PORTUGUESE_BRAZILIAN
+#endif
+
+#endif
diff --git a/src/lib/libast/port/lclib.h b/src/lib/libast/port/lclib.h
new file mode 100644
index 0000000..5daeb8a
--- /dev/null
+++ b/src/lib/libast/port/lclib.h
@@ -0,0 +1,71 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * locale state private definitions
+ */
+
+#ifndef _LCLIB_H
+#define _LCLIB_H 1
+
+#define locales _ast_locales
+#define translate _ast_translate
+
+#define lc_categories _ast_lc_categories
+#define lc_charsets _ast_lc_charsets
+#define lc_languages _ast_lc_languages
+#define lc_maps _ast_lc_maps
+#define lc_territories _ast_lc_territories
+
+struct Lc_info_s;
+
+#define _LC_PRIVATE_ \
+ struct Lc_info_s info[AST_LC_COUNT]; \
+ struct Lc_s* next;
+
+#define _LC_TERRITORY_PRIVATE_ \
+ unsigned char indices[LC_territory_language_max];
+
+#include <ast.h>
+#include <error.h>
+#include <lc.h>
+
+typedef struct Lc_numeric_s
+{
+ int decimal;
+ int thousand;
+} Lc_numeric_t;
+
+#define LCINFO(c) (&locales[c]->info[c])
+
+extern const Lc_charset_t lc_charsets[];
+extern const Lc_language_t lc_languages[];
+extern const Lc_map_t lc_maps[];
+extern const Lc_territory_t lc_territories[];
+
+extern Lc_category_t lc_categories[];
+extern Lc_t* locales[];
+
+extern char* translate(const char*, const char*, const char*, const char*);
+
+#endif
diff --git a/src/lib/libast/port/mc.c b/src/lib/libast/port/mc.c
new file mode 100644
index 0000000..f2ee65c
--- /dev/null
+++ b/src/lib/libast/port/mc.c
@@ -0,0 +1,675 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * machine independent binary message catalog implementation
+ */
+
+#include "sfhdr.h"
+#include "lclib.h"
+
+#include <iconv.h>
+
+#define _MC_PRIVATE_ \
+ size_t nstrs; \
+ size_t nmsgs; \
+ iconv_t cvt; \
+ Sfio_t* tmp; \
+ Vmalloc_t* vm;
+
+#include <vmalloc.h>
+#include <error.h>
+#include <mc.h>
+#include <nl_types.h>
+
+/*
+ * find the binary message catalog path for <locale,catalog>
+ * result placed in path of size PATH_MAX
+ * pointer to path returned
+ * catalog==0 tests for category directory or file
+ * nls!=0 enables NLSPATH+LANG hack (not implemented yet)
+ */
+
+char*
+mcfind(const char* locale, const char* catalog, int category, int nls, char* path, size_t size)
+{
+ register int c;
+ register char* s;
+ register char* e;
+ register char* p;
+ register const char* v;
+ int i;
+ int first;
+ int next;
+ int last;
+ int oerrno;
+ Lc_t* lc;
+ char file[PATH_MAX];
+ char* paths[5];
+
+ static char lc_messages[] = "LC_MESSAGES";
+
+ if ((category = lcindex(category, 1)) < 0)
+ return 0;
+ if (!(lc = locale ? lcmake(locale) : locales[category]))
+ return 0;
+ oerrno = errno;
+ if (catalog && *catalog == '/')
+ {
+ i = eaccess(catalog, R_OK);
+ errno = oerrno;
+ if (i)
+ return 0;
+ strlcpy(path, catalog, size);
+ return path;
+ }
+ i = 0;
+ if ((p = getenv("NLSPATH")) && *p)
+ paths[i++] = p;
+ paths[i++] = "share/lib/locale/%l/%C/%N";
+ paths[i++] = "share/locale/%l/%C/%N";
+ paths[i++] = "lib/locale/%l/%C/%N";
+ paths[i] = 0;
+ next = 1;
+ for (i = 0; p = paths[i]; i += next)
+ {
+ first = 1;
+ last = 0;
+ e = &file[elementsof(file) - 1];
+ while (*p)
+ {
+ s = file;
+ for (;;)
+ {
+ switch (c = *p++)
+ {
+ case 0:
+ p--;
+ break;
+ case ':':
+ break;
+ case '%':
+ if (s < e)
+ {
+ switch (c = *p++)
+ {
+ case 0:
+ p--;
+ continue;
+ case 'N':
+ v = catalog;
+ break;
+ case 'L':
+ if (first)
+ {
+ first = 0;
+ if (next)
+ {
+ v = lc->code;
+ if (lc->code != lc->language->code)
+ next = 0;
+ }
+ else
+ {
+ next = 1;
+ v = lc->language->code;
+ }
+ }
+ break;
+ case 'l':
+ v = lc->language->code;
+ break;
+ case 't':
+ v = lc->territory->code;
+ break;
+ case 'c':
+ v = lc->charset->code;
+ break;
+ case 'C':
+ case_C:
+ if (!catalog)
+ last = 1;
+ v = lc_categories[category].name;
+ break;
+ default:
+ *s++ = c;
+ continue;
+ }
+ if (v)
+ while (*v && s < e)
+ *s++ = *v++;
+ }
+ continue;
+ case '/':
+ if (last)
+ break;
+ if (category != AST_LC_MESSAGES && strneq(p, lc_messages, sizeof(lc_messages) - 1) && p[sizeof(lc_messages)-1] == '/')
+ {
+ p += sizeof(lc_messages) - 1;
+ goto case_C;
+ }
+ /*FALLTHROUGH*/
+ default:
+ if (s < e)
+ *s++ = c;
+ continue;
+ }
+ break;
+ }
+ if (s > file)
+ *s = 0;
+ else if (!catalog)
+ continue;
+ else
+ strlcpy(file, catalog, elementsof(file));
+ if (ast.locale.set & AST_LC_find)
+ sfprintf(sfstderr, "locale find %s\n", file);
+ if (s = pathpath(file, "", (!catalog && category == AST_LC_MESSAGES) ? PATH_READ : (PATH_REGULAR|PATH_READ|PATH_ABSOLUTE), path, size))
+ {
+ if (ast.locale.set & (AST_LC_find|AST_LC_setlocale))
+ sfprintf(sfstderr, "locale path %s\n", s);
+ errno = oerrno;
+ return s;
+ }
+ }
+ }
+ errno = oerrno;
+ return 0;
+}
+
+/*
+ * allocate and read the binary message catalog ip
+ * if ip==0 then space is allocated for mcput()
+ * 0 returned on any error
+ */
+
+Mc_t*
+mcopen(register Sfio_t* ip)
+{
+ register Mc_t* mc;
+ register char** mp;
+ register char* sp;
+ Vmalloc_t* vm;
+ char* rp;
+ int i;
+ int j;
+ int oerrno;
+ size_t n;
+ char buf[MC_MAGIC_SIZE];
+
+ oerrno = errno;
+ if (ip)
+ {
+ /*
+ * check the magic
+ */
+
+ if (sfread(ip, buf, MC_MAGIC_SIZE) != MC_MAGIC_SIZE)
+ {
+ errno = oerrno;
+ return 0;
+ }
+ if (memcmp(buf, MC_MAGIC, MC_MAGIC_SIZE))
+ return 0;
+ }
+
+ /*
+ * allocate the region
+ */
+
+ if (!(vm = vmopen(Vmdcheap, Vmbest, 0)) || !(mc = vmnewof(vm, 0, Mc_t, 1, 0)))
+ {
+ errno = oerrno;
+ return 0;
+ }
+ mc->vm = vm;
+ mc->cvt = (iconv_t)(-1);
+ if (ip)
+ {
+ /*
+ * read the translation record
+ */
+
+ if (!(sp = sfgetr(ip, 0, 0)) || !(mc->translation = vmstrdup(vm, sp)))
+ goto bad;
+
+ /*
+ * read the optional header records
+ */
+
+ do
+ {
+ if (!(sp = sfgetr(ip, 0, 0)))
+ goto bad;
+ } while (*sp);
+
+ /*
+ * get the component dimensions
+ */
+
+ mc->nstrs = sfgetu(ip);
+ mc->nmsgs = sfgetu(ip);
+ mc->num = sfgetu(ip);
+ if (sfeof(ip))
+ goto bad;
+ }
+ else if (!(mc->translation = vmnewof(vm, 0, char, 1, 0)))
+ goto bad;
+
+ /*
+ * allocate the remaining space
+ */
+
+ if (!(mc->set = vmnewof(vm, 0, Mcset_t, mc->num + 1, 0)))
+ goto bad;
+ if (!ip)
+ return mc;
+ if (!(mp = vmnewof(vm, 0, char*, mc->nmsgs + mc->num + 1, 0)))
+ goto bad;
+ if (!(rp = sp = vmalloc(vm, mc->nstrs + 1)))
+ goto bad;
+
+ /*
+ * get the set dimensions and initialize the msg pointers
+ */
+
+ while (i = sfgetu(ip))
+ {
+ if (i > mc->num)
+ goto bad;
+ n = sfgetu(ip);
+ mc->set[i].num = n;
+ mc->set[i].msg = mp;
+ mp += n + 1;
+ }
+
+ /*
+ * read the msg sizes and set up the msg pointers
+ */
+
+ for (i = 1; i <= mc->num; i++)
+ for (j = 1; j <= mc->set[i].num; j++)
+ if (n = sfgetu(ip))
+ {
+ mc->set[i].msg[j] = sp;
+ sp += n;
+ }
+
+ /*
+ * read the string table
+ */
+
+ if (sfread(ip, rp, mc->nstrs) != mc->nstrs || sfgetc(ip) != EOF)
+ goto bad;
+ if (!(mc->tmp = sfstropen()))
+ goto bad;
+ mc->cvt = iconv_open("", "utf");
+ errno = oerrno;
+ return mc;
+ bad:
+ vmclose(vm);
+ errno = oerrno;
+ return 0;
+}
+
+/*
+ * return the <set,num> message in mc
+ * msg returned on error
+ * utf message text converted to ucs
+ */
+
+char*
+mcget(register Mc_t* mc, int set, int num, const char* msg)
+{
+ char* s;
+ size_t n;
+ int p;
+
+ if (!mc || set < 0 || set > mc->num || num < 1 || num > mc->set[set].num || !(s = mc->set[set].msg[num]))
+ return (char*)msg;
+ if (mc->cvt == (iconv_t)(-1))
+ return s;
+ if ((p = sfstrtell(mc->tmp)) > sfstrsize(mc->tmp) / 2)
+ {
+ p = 0;
+ sfstrseek(mc->tmp, p, SEEK_SET);
+ }
+ n = strlen(s) + 1;
+ iconv_write(mc->cvt, mc->tmp, &s, &n, NiL);
+ return sfstrbase(mc->tmp) + p;
+}
+
+/*
+ * set message <set,num> to msg
+ * msg==0 deletes the message
+ * the message and set counts are adjusted
+ * 0 returned on success, -1 otherwise
+ */
+
+int
+mcput(register Mc_t* mc, int set, int num, const char* msg)
+{
+ register int i;
+ register char* s;
+ register Mcset_t* sp;
+ register char** mp;
+
+ /*
+ * validate the arguments
+ */
+
+ if (!mc || set > MC_SET_MAX || num > MC_NUM_MAX)
+ return -1;
+
+ /*
+ * deletions don't kick in allocations (duh)
+ */
+
+ if (!msg)
+ {
+ if (set <= mc->num && num <= mc->set[set].num && (s = mc->set[set].msg[num]))
+ {
+ /*
+ * decrease the string table size
+ */
+
+ mc->set[set].msg[num] = 0;
+ mc->nstrs -= strlen(s) + 1;
+ if (mc->set[set].num == num)
+ {
+ /*
+ * decrease the max msg num
+ */
+
+ mp = mc->set[set].msg + num;
+ while (num && !mp[--num]);
+ mc->nmsgs -= mc->set[set].num - num;
+ if (!(mc->set[set].num = num) && mc->num == set)
+ {
+ /*
+ * decrease the max set num
+ */
+
+ while (num && !mc->set[--num].num);
+ mc->num = num;
+ }
+ }
+ }
+ return 0;
+ }
+
+ /*
+ * keep track of the highest set and allocate if necessary
+ */
+
+ if (set > mc->num)
+ {
+ if (set > mc->gen)
+ {
+ i = MC_SET_MAX;
+ if (!(sp = vmnewof(mc->vm, 0, Mcset_t, i + 1, 0)))
+ return -1;
+ mc->gen = i;
+ for (i = 1; i <= mc->num; i++)
+ sp[i] = mc->set[i];
+ mc->set = sp;
+ }
+ mc->num = set;
+ }
+ sp = mc->set + set;
+
+ /*
+ * keep track of the highest msg and allocate if necessary
+ */
+
+ if (num > sp->num)
+ {
+ if (num > sp->gen)
+ {
+ if (!mc->gen)
+ {
+ i = (MC_NUM_MAX + 1) / 32;
+ if (i <= num)
+ i = 2 * num;
+ if (i > MC_NUM_MAX)
+ i = MC_NUM_MAX;
+ if (!(mp = vmnewof(mc->vm, 0, char*, i + 1, 0)))
+ return -1;
+ mc->gen = i;
+ sp->msg = mp;
+ for (i = 1; i <= sp->num; i++)
+ mp[i] = sp->msg[i];
+ }
+ else
+ {
+ i = 2 * mc->gen;
+ if (i > MC_NUM_MAX)
+ i = MC_NUM_MAX;
+ if (!(mp = vmnewof(mc->vm, sp->msg, char*, i + 1, 0)))
+ return -1;
+ sp->gen = i;
+ sp->msg = mp;
+ }
+ }
+ mc->nmsgs += num - sp->num;
+ sp->num = num;
+ }
+
+ /*
+ * decrease the string table size
+ */
+
+ if (s = sp->msg[num])
+ {
+ /*
+ * no-op if no change
+ */
+
+ if (streq(s, msg))
+ return 0;
+ mc->nstrs -= strlen(s) + 1;
+ }
+
+ /*
+ * allocate, add and adjust the string table size
+ */
+
+ if (!(s = vmstrdup(mc->vm, msg)))
+ return -1;
+ sp->msg[num] = s;
+ mc->nstrs += strlen(s) + 1;
+ return 0;
+}
+
+/*
+ * dump message catalog mc to op
+ * 0 returned on success, -1 otherwise
+ */
+
+int
+mcdump(register Mc_t* mc, register Sfio_t* op)
+{
+ register int i;
+ register int j;
+ register int n;
+ register char* s;
+ register Mcset_t* sp;
+
+ /*
+ * write the magic
+ */
+
+ if (sfwrite(op, MC_MAGIC, MC_MAGIC_SIZE) != MC_MAGIC_SIZE)
+ return -1;
+
+ /*
+ * write the translation record
+ */
+
+ sfputr(op, mc->translation, 0);
+
+ /* optional header records here */
+
+ /*
+ * end of optional header records
+ */
+
+ sfputu(op, 0);
+
+ /*
+ * write the global dimensions
+ */
+
+ sfputu(op, mc->nstrs);
+ sfputu(op, mc->nmsgs);
+ sfputu(op, mc->num);
+
+ /*
+ * write the set dimensions
+ */
+
+ for (i = 1; i <= mc->num; i++)
+ if (mc->set[i].num)
+ {
+ sfputu(op, i);
+ sfputu(op, mc->set[i].num);
+ }
+ sfputu(op, 0);
+
+ /*
+ * write the message sizes
+ */
+
+ for (i = 1; i <= mc->num; i++)
+ if (mc->set[i].num)
+ {
+ sp = mc->set + i;
+ for (j = 1; j <= sp->num; j++)
+ {
+ n = (s = sp->msg[j]) ? (strlen(s) + 1) : 0;
+ sfputu(op, n);
+ }
+ }
+
+ /*
+ * write the string table
+ */
+
+ for (i = 1; i <= mc->num; i++)
+ if (mc->set[i].num)
+ {
+ sp = mc->set + i;
+ for (j = 1; j <= sp->num; j++)
+ if (s = sp->msg[j])
+ sfputr(op, s, 0);
+ }
+
+ /*
+ * sync and return
+ */
+
+ return sfsync(op);
+}
+
+/*
+ * parse <set,msg> number from s
+ * e!=0 is set to the next char after the parse
+ * set!=0 is set to message set number
+ * msg!=0 is set to message number
+ * the message set number is returned
+ *
+ * the base 36 hash gives reasonable values for these:
+ *
+ * "ast" : ((((36#a^36#s^36#t)-9)&63)+1) = 3
+ * "gnu" : ((((36#g^36#n^36#u)-9)&63)+1) = 17
+ * "sgi" : ((((36#s^36#g^36#i)-9)&63)+1) = 22
+ * "sun" : ((((36#s^36#u^36#n)-9)&63)+1) = 13
+ */
+
+int
+mcindex(register const char* s, char** e, int* set, int* msg)
+{
+ register int c;
+ register int m;
+ register int n;
+ register int r;
+ register unsigned char* cv;
+ char* t;
+
+ m = 0;
+ n = strtol(s, &t, 0);
+ if (t == (char*)s)
+ {
+ SFCVINIT();
+ cv = _Sfcv36;
+ for (n = m = 0; (c = cv[*s]) < 36; s++)
+ {
+ m++;
+ n ^= c;
+ }
+ m = (m <= 3) ? 63 : ((1 << (m + 3)) - 1);
+ n = ((n - 9) & m) + 1;
+ }
+ else
+ s = (const char*)t;
+ r = n;
+ if (*s)
+ m = strtol(s + 1, e, 0);
+ else
+ {
+ if (e)
+ *e = (char*)s;
+ if (m)
+ m = 0;
+ else
+ {
+ m = n;
+ n = 1;
+ }
+ }
+ if (set)
+ *set = n;
+ if (msg)
+ *msg = m;
+ return r;
+}
+
+/*
+ * close the message catalog mc
+ */
+
+int
+mcclose(register Mc_t* mc)
+{
+ if (!mc)
+ return -1;
+ if (mc->tmp)
+ sfclose(mc->tmp);
+ if (mc->cvt != (iconv_t)(-1))
+ iconv_close(mc->cvt);
+ vmclose(mc->vm);
+ return 0;
+}
diff --git a/src/lib/libast/port/mnt.c b/src/lib/libast/port/mnt.c
new file mode 100644
index 0000000..f773ae8
--- /dev/null
+++ b/src/lib/libast/port/mnt.c
@@ -0,0 +1,816 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * mounted filesystem scan support
+ * where are the standards when you really need them
+ */
+
+#include <ast.h>
+#include <mnt.h>
+#include <ls.h>
+
+#if _lib_mntopen && _lib_mntread && _lib_mntclose
+
+NoN(mnt)
+
+#else
+
+/*
+ * the original interface just had mode
+ */
+
+#define FIXARGS(p,m,s) do { \
+ if ((p)&&*(p)!='/') { \
+ mode = p; \
+ path = 0; \
+ } \
+ if (!path) \
+ path = s; \
+ } while (0)
+typedef struct
+{
+ Mnt_t mnt;
+ char buf[128];
+#if __CYGWIN__
+ char typ[128];
+ char opt[128];
+#endif
+} Header_t;
+
+#if __CYGWIN__
+#include <ast_windows.h>
+#endif
+
+static void
+set(register Header_t* hp, const char* fs, const char* dir, const char* type, const char* options)
+{
+ const char* x;
+
+ hp->mnt.flags = 0;
+ if (x = (const char*)strchr(fs, ':'))
+ {
+ if (*++x && *x != '\\')
+ {
+ hp->mnt.flags |= MNT_REMOTE;
+ if (*x == '(')
+ {
+ fs = x;
+ type = "auto";
+ }
+ }
+ }
+ else if (x = (const char*)strchr(fs, '@'))
+ {
+ hp->mnt.flags |= MNT_REMOTE;
+ sfsprintf(hp->buf, sizeof(hp->buf) - 1, "%s:%*.*s", x + 1, x - fs, x - fs, fs);
+ fs = (const char*)hp->buf;
+ }
+ else if (strmatch(type, "[aAnN][fF][sS]*"))
+ hp->mnt.flags |= MNT_REMOTE;
+ if (streq(fs, "none"))
+ fs = dir;
+ hp->mnt.fs = (char*)fs;
+ hp->mnt.dir = (char*)dir;
+ hp->mnt.type = (char*)type;
+ hp->mnt.options = (char*)options;
+#if __CYGWIN__
+ if (streq(type, "system") || streq(type, "user"))
+ {
+ char* s;
+ int mode;
+ DWORD vser;
+ DWORD flags;
+ DWORD len;
+ char drive[4];
+
+ mode = SetErrorMode(SEM_FAILCRITICALERRORS);
+ drive[0] = fs[0];
+ drive[1] = ':';
+ drive[2] = '\\';
+ drive[3] = 0;
+ if (GetVolumeInformation(drive, 0, 0, &vser, &len, &flags, hp->typ, sizeof(hp->typ) - 1))
+ hp->mnt.type = hp->typ;
+ else
+ flags = 0;
+ SetErrorMode(mode);
+ s = strcopy(hp->mnt.options = hp->opt, type);
+ s = strcopy(s, ",ignorecase");
+ if (options)
+ {
+ *s++ = ',';
+ strcpy(s, options);
+ }
+ }
+#endif
+}
+
+#undef MNT_REMOTE
+
+#if _sys_mount && ( _lib_getfsstat || _lib_getmntinfo )
+
+/*
+ * 4.4 bsd getmntinfo
+ *
+ * what a crappy interface
+ * data returned in static buffer -- ok
+ * big chunk of allocated memory that cannot be freed -- come on
+ * *and* netbsd changed the interface somewhere along the line
+ * private interface? my bad -- public interface? par for the bsd course
+ *
+ * we assume getfsstat may suffer the same statfs/statvfs confusion
+ */
+
+#include <sys/param.h> /* expect some macro redefinitions here */
+#include <sys/mount.h>
+
+#if _lib_getfsstat
+#if _lib_getfsstat_statvfs
+#define statfs statvfs
+#define f_flags f_flag
+#endif
+#else
+#if _lib_getmntinfo_statvfs
+#define statfs statvfs
+#define f_flags f_flag
+#endif
+#endif
+
+typedef struct
+{
+ Header_t hdr;
+ struct statfs* next;
+ struct statfs* last;
+ char opt[256];
+#if _lib_getfsstat
+ struct statfs buf[1];
+#endif
+} Handle_t;
+
+#ifdef MFSNAMELEN
+#define TYPE(f) ((f)->f_fstypename)
+#else
+#ifdef INITMOUNTNAMES
+#define TYPE(f) ((char*)type[(f)->f_type])
+static const char* type[] = INITMOUNTNAMES;
+#else
+#if _sys_fs_types
+#define TYPE(f) ((char*)mnt_names[(f)->f_type])
+#include <sys/fs_types.h>
+#else
+#define TYPE(f) (strchr((f)->f_mntfromname,':')?"nfs":"ufs")
+#endif
+#endif
+#endif
+
+static struct Mnt_options_t
+{
+ unsigned long flag;
+ const char* name;
+}
+options[] =
+{
+#ifdef MNT_RDONLY
+ MNT_RDONLY, "rdonly",
+#endif
+#ifdef MNT_SYNCHRONOUS
+ MNT_SYNCHRONOUS,"synchronous",
+#endif
+#ifdef MNT_NOEXEC
+ MNT_NOEXEC, "noexec",
+#endif
+#ifdef MNT_NOSUID
+ MNT_NOSUID, "nosuid",
+#endif
+#ifdef MNT_NODEV
+ MNT_NODEV, "nodev",
+#endif
+#ifdef MNT_UNION
+ MNT_UNION, "union",
+#endif
+#ifdef MNT_ASYNC
+ MNT_ASYNC, "async",
+#endif
+#ifdef MNT_NOCOREDUMP
+ MNT_NOCOREDUMP, "nocoredump",
+#endif
+#ifdef MNT_NOATIME
+ MNT_NOATIME, "noatime",
+#endif
+#ifdef MNT_SYMPERM
+ MNT_SYMPERM, "symperm",
+#endif
+#ifdef MNT_NODEVMTIME
+ MNT_NODEVMTIME, "nodevmtime",
+#endif
+#ifdef MNT_SOFTDEP
+ MNT_SOFTDEP, "softdep",
+#endif
+#ifdef MNT_EXRDONLY
+ MNT_EXRDONLY, "exrdonly",
+#endif
+#ifdef MNT_EXPORTED
+ MNT_EXPORTED, "exported",
+#endif
+#ifdef MNT_DEFEXPORTED
+ MNT_DEFEXPORTED,"defexported",
+#endif
+#ifdef MNT_EXPORTANON
+ MNT_EXPORTANON, "exportanon",
+#endif
+#ifdef MNT_EXKERB
+ MNT_EXKERB, "exkerb",
+#endif
+#ifdef MNT_EXNORESPORT
+ MNT_EXNORESPORT,"exnoresport",
+#endif
+#ifdef MNT_EXPUBLIC
+ MNT_EXPUBLIC, "expublic",
+#endif
+#ifdef MNT_LOCAL
+ MNT_LOCAL, "local",
+#endif
+#ifdef MNT_QUOTA
+ MNT_QUOTA, "quota",
+#endif
+#ifdef MNT_ROOTFS
+ MNT_ROOTFS, "rootfs",
+#endif
+ 0, "unknown",
+};
+
+void*
+mntopen(const char* path, const char* mode)
+{
+ register Handle_t* mp;
+ register int n;
+
+ FIXARGS(path, mode, 0);
+#if _lib_getfsstat
+ if ((n = getfsstat(NiL, 0, MNT_WAIT)) <= 0)
+ return 0;
+ n = (n - 1) * sizeof(struct statfs);
+#else
+ n = 0;
+#endif
+ if (!(mp = newof(0, Handle_t, 1, n)))
+ return 0;
+#if _lib_getfsstat
+ n = getfsstat(mp->next = mp->buf, n + sizeof(struct statfs), MNT_WAIT);
+#else
+ n = getmntinfo(&mp->next, 0);
+#endif
+ if (n <= 0)
+ {
+ free(mp);
+ return 0;
+ }
+ mp->last = mp->next + n;
+ return (void*)mp;
+}
+
+Mnt_t*
+mntread(void* handle)
+{
+ register Handle_t* mp = (Handle_t*)handle;
+ register int i;
+ register int n;
+ register unsigned long flags;
+
+ if (mp->next < mp->last)
+ {
+ flags = mp->next->f_flags;
+ n = 0;
+ for (i = 0; i < elementsof(options); i++)
+ if (flags & options[i].flag)
+ n += sfsprintf(mp->opt + n, sizeof(mp->opt) - n - 1, ",%s", options[i].name);
+ set(&mp->hdr, mp->next->f_mntfromname, mp->next->f_mntonname, TYPE(mp->next), n ? (mp->opt + 1) : (char*)0);
+ mp->next++;
+ return &mp->hdr.mnt;
+ }
+ return 0;
+}
+
+int
+mntclose(void* handle)
+{
+ register Handle_t* mp = (Handle_t*)handle;
+
+ if (!mp)
+ return -1;
+ free(mp);
+ return 0;
+}
+
+#else
+
+#if _lib_mntctl && _sys_vmount
+
+/*
+ * aix
+ */
+
+#include <sys/vmount.h>
+
+#define SIZE (16 * 1024)
+
+static const char* type[] =
+{
+ "aix", "aix#1", "nfs", "jfs", "aix#4", "cdrom"
+};
+
+typedef struct
+{
+ Header_t hdr;
+ long count;
+ struct vmount* next;
+ char remote[128];
+ char type[16];
+ struct vmount info[1];
+} Handle_t;
+
+void*
+mntopen(const char* path, const char* mode)
+{
+ register Handle_t* mp;
+
+ FIXARGS(path, mode, 0);
+ if (!(mp = newof(0, Handle_t, 1, SIZE)))
+ return 0;
+ if ((mp->count = mntctl(MCTL_QUERY, sizeof(Handle_t) + SIZE, &mp->info)) <= 0)
+ {
+ free(mp);
+ return 0;
+ }
+ mp->next = mp->info;
+ return (void*)mp;
+}
+
+Mnt_t*
+mntread(void* handle)
+{
+ register Handle_t* mp = (Handle_t*)handle;
+ register char* s;
+ register char* t;
+ register char* o;
+
+ if (mp->count > 0)
+ {
+ if (vmt2datasize(mp->next, VMT_HOST) && (s = vmt2dataptr(mp->next, VMT_HOST)) && !streq(s, "-"))
+ {
+ sfsprintf(mp->remote, sizeof(mp->remote) - 1, "%s:%s", s, vmt2dataptr(mp->next, VMT_OBJECT));
+ s = mp->remote;
+ }
+ else
+ s = vmt2dataptr(mp->next, VMT_OBJECT);
+ if (vmt2datasize(mp->next, VMT_ARGS))
+ o = vmt2dataptr(mp->next, VMT_ARGS);
+ else
+ o = NiL;
+ switch (mp->next->vmt_gfstype)
+ {
+#ifdef MNT_AIX
+ case MNT_AIX:
+ t = "aix";
+ break;
+#endif
+#ifdef MNT_NFS
+ case MNT_NFS:
+ t = "nfs";
+ break;
+#endif
+#ifdef MNT_JFS
+ case MNT_JFS:
+ t = "jfs";
+ break;
+#endif
+#ifdef MNT_CDROM
+ case MNT_CDROM:
+ t = "cdrom";
+ break;
+#endif
+#ifdef MNT_SFS
+ case MNT_SFS:
+ t = "sfs";
+ break;
+#endif
+#ifdef MNT_CACHEFS
+ case MNT_CACHEFS:
+ t = "cachefs";
+ break;
+#endif
+#ifdef MNT_NFS3
+ case MNT_NFS3:
+ t = "nfs3";
+ break;
+#endif
+#ifdef MNT_AUTOFS
+ case MNT_AUTOFS:
+ t = "autofs";
+ break;
+#endif
+ default:
+ sfsprintf(t = mp->type, sizeof(mp->type), "aix%+d", mp->next->vmt_gfstype);
+ break;
+ }
+ set(&mp->hdr, s, vmt2dataptr(mp->next, VMT_STUB), t, o);
+ if (--mp->count > 0)
+ mp->next = (struct vmount*)((char*)mp->next + mp->next->vmt_length);
+ return &mp->hdr.mnt;
+ }
+ return 0;
+}
+
+int
+mntclose(void* handle)
+{
+ register Handle_t* mp = (Handle_t*)handle;
+
+ if (!mp)
+ return -1;
+ free(mp);
+ return 0;
+}
+
+#else
+
+#if !_lib_setmntent
+#undef _lib_getmntent
+#if !_SCO_COFF && !_SCO_ELF && !_UTS
+#undef _hdr_mnttab
+#endif
+#endif
+
+#if _lib_getmntent && ( _hdr_mntent || _sys_mntent && !_sys_mnttab )
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide endmntent getmntent
+#else
+#define endmntent ______endmntent
+#define getmntent ______getmntent
+#endif
+
+#include <stdio.h>
+#if _hdr_mntent
+#include <mntent.h>
+#else
+#include <sys/mntent.h>
+#endif
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide endmntent getmntent
+#else
+#undef endmntent
+#undef getmntent
+#endif
+
+extern int endmntent(FILE*);
+extern struct mntent* getmntent(FILE*);
+
+#else
+
+#undef _lib_getmntent
+
+#if _hdr_mnttab
+#include <mnttab.h>
+#else
+#if _sys_mnttab
+#include <sys/mnttab.h>
+#endif
+#endif
+
+#endif
+
+#ifndef MOUNTED
+#ifdef MNT_MNTTAB
+#define MOUNTED MNT_MNTTAB
+#else
+#if _hdr_mnttab || _sys_mnttab
+#define MOUNTED "/etc/mnttab"
+#else
+#define MOUNTED "/etc/mtab"
+#endif
+#endif
+#endif
+
+#ifdef __Lynx__
+#undef MOUNTED
+#define MOUNTED "/etc/fstab"
+#define SEP ':'
+#endif
+
+#if _lib_getmntent
+
+typedef struct
+#if _mem_mnt_opts_mntent
+#define OPTIONS(p) ((p)->mnt_opts)
+#else
+#define OPTIONS(p) NiL
+#endif
+
+{
+ Header_t hdr;
+ FILE* fp;
+} Handle_t;
+
+void*
+mntopen(const char* path, const char* mode)
+{
+ register Handle_t* mp;
+
+ FIXARGS(path, mode, MOUNTED);
+ if (!(mp = newof(0, Handle_t, 1, 0)))
+ return 0;
+ if (!(mp->fp = setmntent(path, mode)))
+ {
+ free(mp);
+ return 0;
+ }
+ return (void*)mp;
+}
+
+Mnt_t*
+mntread(void* handle)
+{
+ register Handle_t* mp = (Handle_t*)handle;
+ register struct mntent* mnt;
+
+ if (mnt = getmntent(mp->fp))
+ {
+ set(&mp->hdr, mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, OPTIONS(mnt));
+ return &mp->hdr.mnt;
+ }
+ return 0;
+}
+
+int
+mntclose(void* handle)
+{
+ register Handle_t* mp = (Handle_t*)handle;
+
+ if (!mp)
+ return -1;
+ endmntent(mp->fp);
+ free(mp);
+ return 0;
+}
+
+#else
+
+#if _sys_mntent && _lib_w_getmntent
+
+#include <sys/mntent.h>
+
+#define mntent w_mntent
+
+#define mnt_dir mnt_mountpoint
+#define mnt_type mnt_fstname
+
+#define MNTBUFSIZE (sizeof(struct w_mnth)+16*sizeof(struct w_mntent))
+
+#if _mem_mnt_opts_w_mntent
+#define OPTIONS(p) ((p)->mnt_opts)
+#else
+#define OPTIONS(p) NiL
+#endif
+
+#else
+
+#undef _lib_w_getmntent
+
+#define MNTBUFSIZE sizeof(struct mntent)
+
+#if !_mem_mt_dev_mnttab || !_mem_mt_filsys_mnttab
+#undef _hdr_mnttab
+#endif
+
+#if _hdr_mnttab
+
+#define mntent mnttab
+
+#define mnt_fsname mt_dev
+#define mnt_dir mt_filsys
+#if _mem_mt_fstyp_mnttab
+#define mnt_type mt_fstyp
+#endif
+
+#if _mem_mnt_opts_mnttab
+#define OPTIONS(p) ((p)->mnt_opts)
+#else
+#define OPTIONS(p) NiL
+#endif
+
+#else
+
+struct mntent
+{
+ char mnt_fsname[256];
+ char mnt_dir[256];
+ char mnt_type[32];
+ char mnt_opts[64];
+};
+
+#define OPTIONS(p) ((p)->mnt_opts)
+
+#endif
+
+#endif
+
+typedef struct
+{
+ Header_t hdr;
+ Sfio_t* fp;
+ struct mntent* mnt;
+#if _lib_w_getmntent
+ int count;
+#endif
+ char buf[MNTBUFSIZE];
+} Handle_t;
+
+void*
+mntopen(const char* path, const char* mode)
+{
+ register Handle_t* mp;
+
+ FIXARGS(path, mode, MOUNTED);
+ if (!(mp = newof(0, Handle_t, 1, 0)))
+ return 0;
+#if _lib_w_getmntent
+ if ((mp->count = w_getmntent(mp->buf, sizeof(mp->buf))) > 0)
+ mp->mnt = (struct mntent*)(((struct w_mnth*)mp->buf) + 1);
+ else
+#else
+ mp->mnt = (struct mntent*)mp->buf;
+ if (!(mp->fp = sfopen(NiL, path, mode)))
+#endif
+ {
+ free(mp);
+ return 0;
+ }
+ return (void*)mp;
+}
+
+Mnt_t*
+mntread(void* handle)
+{
+ register Handle_t* mp = (Handle_t*)handle;
+
+#if _lib_w_getmntent
+
+ if (mp->count-- <= 0)
+ {
+ if ((mp->count = w_getmntent(mp->buf, sizeof(mp->buf))) <= 0)
+ return 0;
+ mp->count--;
+ mp->mnt = (struct mntent*)(((struct w_mnth*)mp->buf) + 1);
+ }
+ set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt));
+ mp->mnt++;
+ return &mp->hdr.mnt;
+
+#else
+
+#if _hdr_mnttab
+
+ while (sfread(mp->fp, &mp->buf, sizeof(mp->buf)) == sizeof(mp->buf))
+ if (*mp->mnt->mnt_fsname && *mp->mnt->mnt_dir)
+ {
+#ifndef mnt_type
+ struct stat st;
+
+ static char typ[32];
+
+ set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, stat(mp->mnt->mnt_dir, &st) ? FS_default : strlcpy(typ, fmtfs(&st), sizeof(typ)), OPTIONS(mp->mnt));
+#else
+ set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt));
+#endif
+ return &mp->hdr.mnt;
+ }
+ return 0;
+
+#else
+
+ register int c;
+ register char* s;
+ register char* m;
+ register char* b;
+ register int q;
+ register int x;
+
+ again:
+ q = 0;
+ x = 0;
+ b = s = mp->mnt->mnt_fsname;
+ m = s + sizeof(mp->mnt->mnt_fsname) - 1;
+ for (;;) switch (c = sfgetc(mp->fp))
+ {
+ case EOF:
+ return 0;
+ case '"':
+ case '\'':
+ if (q == c)
+ q = 0;
+ else if (!q)
+ q = c;
+ break;
+#ifdef SEP
+ case SEP:
+#else
+ case ' ':
+ case '\t':
+#endif
+ if (s != b && !q) switch (++x)
+ {
+ case 1:
+ *s = 0;
+ b = s = mp->mnt->mnt_dir;
+ m = s + sizeof(mp->mnt->mnt_dir) - 1;
+ break;
+ case 2:
+ *s = 0;
+ b = s = mp->mnt->mnt_type;
+ m = s + sizeof(mp->mnt->mnt_type) - 1;
+ break;
+ case 3:
+ *s = 0;
+ b = s = mp->mnt->mnt_opts;
+ m = s + sizeof(mp->mnt->mnt_opts) - 1;
+ break;
+ case 4:
+ *s = 0;
+ b = s = m = 0;
+ break;
+ }
+ break;
+ case '\n':
+ if (x >= 3)
+ {
+ set(&mp->hdr, mp->mnt->mnt_fsname, mp->mnt->mnt_dir, mp->mnt->mnt_type, OPTIONS(mp->mnt));
+ return &mp->hdr.mnt;
+ }
+ goto again;
+ default:
+ if (s < m)
+ *s++ = c;
+ break;
+ }
+
+#endif
+
+#endif
+
+}
+
+int
+mntclose(void* handle)
+{
+ register Handle_t* mp = (Handle_t*)handle;
+
+ if (!mp)
+ return -1;
+ sfclose(mp->fp);
+ free(mp);
+ return 0;
+}
+
+#endif
+
+#endif
+
+#endif
+
+/*
+ * currently no write
+ */
+
+int
+mntwrite(void* handle, const Mnt_t* mnt)
+{
+ NoP(handle);
+ NoP(mnt);
+ return -1;
+}
+
+#endif
diff --git a/src/lib/libast/port/touch.c b/src/lib/libast/port/touch.c
new file mode 100644
index 0000000..c921181
--- /dev/null
+++ b/src/lib/libast/port/touch.c
@@ -0,0 +1,74 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * touch file access and modify times of file
+ * if flags&PATH_TOUCH_CREATE then file will be created if it doesn't exist
+ * if flags&PATH_TOUCH_VERBATIM then times are taken verbatim
+ * times have one second granularity
+ *
+ * (time_t)(-1) retain old time
+ * 0 use current time
+ *
+ * the old interface flag values were:
+ * 1 PATH_TOUCH_CREATE
+ * -1 PATH_TOUCH_CREATE|PATH_TOUCH_VERBATIM
+ * PATH_TOUCH_VERBATIM -- not supported
+ */
+
+#include <ast.h>
+#include <times.h>
+#include <tv.h>
+
+int
+touch(const char* path, time_t at, time_t mt, int flags)
+{
+ Tv_t av;
+ Tv_t mv;
+ Tv_t* ap;
+ Tv_t* mp;
+
+ if (at == (time_t)(-1) && !(flags & PATH_TOUCH_VERBATIM))
+ ap = TV_TOUCH_RETAIN;
+ else if (!at && !(flags & PATH_TOUCH_VERBATIM))
+ ap = 0;
+ else
+ {
+ av.tv_sec = at;
+ av.tv_nsec = 0;
+ ap = &av;
+ }
+ if (mt == (time_t)(-1) && !(flags & PATH_TOUCH_VERBATIM))
+ mp = TV_TOUCH_RETAIN;
+ else if (!mt && !(flags & PATH_TOUCH_VERBATIM))
+ mp = 0;
+ else
+ {
+ mv.tv_sec = mt;
+ mv.tv_nsec = 0;
+ mp = &mv;
+ }
+ return tvtouch(path, ap, mp, NiL, flags & 1);
+}
diff --git a/src/lib/libast/preroot/getpreroot.c b/src/lib/libast/preroot/getpreroot.c
new file mode 100644
index 0000000..3747d19
--- /dev/null
+++ b/src/lib/libast/preroot/getpreroot.c
@@ -0,0 +1,165 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Bell Laboratories
+ * return the real absolute pathname of the preroot dir for cmd
+ * if cmd==0 then current preroot path returned
+ */
+
+#include <ast.h>
+#include <preroot.h>
+
+#if FS_PREROOT
+
+#include <ast_dir.h>
+#include <ls.h>
+#include <error.h>
+#include <stdio.h>
+
+#ifndef ERANGE
+#define ERANGE E2BIG
+#endif
+
+#define ERROR(e) {errno=e;goto error;}
+
+char*
+getpreroot(char* path, const char* cmd)
+{
+ register int c;
+ register FILE* fp;
+ register char* p;
+ char buf[PATH_MAX];
+
+ if (!path) path = buf;
+ if (cmd)
+ {
+ sfsprintf(buf, sizeof(buf), "set x `%s= %s - </dev/null 2>&1`\nwhile :\ndo\nshift\ncase $# in\n[012]) break ;;\nesac\ncase \"$1 $2\" in\n\"+ %s\") echo $3; exit ;;\nesac\ndone\necho\n", PR_SILENT, cmd, PR_COMMAND);
+ if (!(fp = popen(buf, "rug"))) return(0);
+ for (p = path; (c = getc(fp)) != EOF && c != '\n'; *p++ = c);
+ *p = 0;
+ pclose(fp);
+ if (path == p) return(0);
+ return(path == buf ? strdup(path) : path);
+ }
+ else
+ {
+ char* d;
+ DIR* dirp = 0;
+ int namlen;
+ int euid;
+ int ruid;
+ struct dirent* entry;
+ struct stat* cur;
+ struct stat* par;
+ struct stat* tmp;
+ struct stat curst;
+ struct stat parst;
+ struct stat tstst;
+ char dots[PATH_MAX];
+
+ cur = &curst;
+ par = &parst;
+ if ((ruid = getuid()) != (euid = geteuid())) setuid(ruid);
+ if (stat(PR_REAL, cur) || stat("/", par) || cur->st_dev == par->st_dev && cur->st_ino == par->st_ino) ERROR(ENOTDIR);
+
+ /*
+ * like getcwd() but starting at the preroot
+ */
+
+ d = dots;
+ *d++ = '/';
+ p = path + PATH_MAX - 1;
+ *p = 0;
+ for (;;)
+ {
+ tmp = cur;
+ cur = par;
+ par = tmp;
+ if ((d - dots) > (PATH_MAX - 4)) ERROR(ERANGE);
+ *d++ = '.';
+ *d++ = '.';
+ *d = 0;
+ if (!(dirp = opendir(dots))) ERROR(errno);
+#if !_dir_ok || _mem_dd_fd_DIR
+ if (fstat(dirp->dd_fd, par)) ERROR(errno);
+#else
+ if (stat(dots, par)) ERROR(errno);
+#endif
+ *d++ = '/';
+ if (par->st_dev == cur->st_dev)
+ {
+ if (par->st_ino == cur->st_ino)
+ {
+ closedir(dirp);
+ *--p = '/';
+ if (ruid != euid) setuid(euid);
+ if (path == buf) return(strdup(p));
+ if (path != p)
+ {
+ d = path;
+ while (*d++ = *p++);
+ }
+ return(path);
+ }
+#ifdef D_FILENO
+ while (entry = readdir(dirp))
+ if (D_FILENO(entry) == cur->st_ino)
+ {
+ namlen = D_NAMLEN(entry);
+ goto found;
+ }
+#endif
+
+ /*
+ * this fallthrough handles logical naming
+ */
+
+ rewinddir(dirp);
+ }
+ do
+ {
+ if (!(entry = readdir(dirp))) ERROR(ENOENT);
+ namlen = D_NAMLEN(entry);
+ if ((d - dots) > (PATH_MAX - 1 - namlen)) ERROR(ERANGE);
+ memcpy(d, entry->d_name, namlen + 1);
+ if (stat(dots, &tstst)) ERROR(errno);
+ } while (tstst.st_ino != cur->st_ino || tstst.st_dev != cur->st_dev);
+ found:
+ if (*p) *--p = '/';
+ if ((p -= namlen) <= (path + 1)) ERROR(ERANGE);
+ memcpy(p, entry->d_name, namlen);
+ closedir(dirp);
+ dirp = 0;
+ }
+ error:
+ if (dirp) closedir(dirp);
+ if (ruid != euid) setuid(euid);
+ }
+ return(0);
+}
+
+#else
+
+NoN(getpreroot)
+
+#endif
diff --git a/src/lib/libast/preroot/ispreroot.c b/src/lib/libast/preroot/ispreroot.c
new file mode 100644
index 0000000..36bf62c
--- /dev/null
+++ b/src/lib/libast/preroot/ispreroot.c
@@ -0,0 +1,71 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Bell Laboratories
+ * return 1 if dir [any dir] is the preroot
+ */
+
+#include <ast.h>
+#include <preroot.h>
+
+#if FS_PREROOT
+
+#include <ls.h>
+
+/*
+ * return 1 if files a and b are the same under preroot
+ *
+ * NOTE: the kernel disables preroot for set-uid processes
+ */
+
+static int
+same(const char* a, const char* b)
+{
+ int i;
+ int euid;
+ int ruid;
+
+ struct stat ast;
+ struct stat bst;
+
+ if ((ruid = getuid()) != (euid = geteuid())) setuid(ruid);
+ i = !stat(a, &ast) && !stat(b, &bst) && ast.st_dev == bst.st_dev && ast.st_ino == bst.st_ino;
+ if (ruid != euid) setuid(euid);
+ return(i);
+}
+
+int
+ispreroot(const char* dir)
+{
+ static int prerooted = -1;
+
+ if (dir) return(same("/", dir));
+ if (prerooted < 0) prerooted = !same("/", PR_REAL);
+ return(prerooted);
+}
+
+#else
+
+NoN(ispreroot)
+
+#endif
diff --git a/src/lib/libast/preroot/realopen.c b/src/lib/libast/preroot/realopen.c
new file mode 100644
index 0000000..387559b
--- /dev/null
+++ b/src/lib/libast/preroot/realopen.c
@@ -0,0 +1,47 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Bell Laboratories
+ * disable preroot and open path relative to the real root
+ */
+
+#include <ast.h>
+#include <preroot.h>
+
+#if FS_PREROOT
+
+int
+realopen(const char* path, int mode, int perm)
+{
+ char buf[PATH_MAX + 8];
+
+ if (*path != '/' || !ispreroot(NiL)) return(-1);
+ strcopy(strcopy(buf, PR_REAL), path);
+ return(open(buf, mode, perm));
+}
+
+#else
+
+NoN(realopen)
+
+#endif
diff --git a/src/lib/libast/preroot/setpreroot.c b/src/lib/libast/preroot/setpreroot.c
new file mode 100644
index 0000000..1e8b6c1
--- /dev/null
+++ b/src/lib/libast/preroot/setpreroot.c
@@ -0,0 +1,75 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Bell Laboratories
+ * force current command to run under dir preroot
+ */
+
+#include <ast.h>
+#include <preroot.h>
+
+#if FS_PREROOT
+
+#include <option.h>
+
+void
+setpreroot(register char** argv, const char* dir)
+{
+ register char* s;
+ register char** ap;
+ int argc;
+ char* cmd;
+ char** av;
+ char buf[PATH_MAX];
+
+ if ((argv || (argv = opt_info.argv)) && (dir || (dir = getenv(PR_BASE)) && *dir) && !ispreroot(dir) && (*(cmd = *argv++) == '/' || (cmd = pathpath(cmd, NiL, PATH_ABSOLUTE|PATH_REGULAR|PATH_EXECUTE, buf, sizeof(buf)))))
+ {
+ argc = 3;
+ for (ap = argv; *ap++; argc++);
+ if (av = newof(0, char*, argc, 0))
+ {
+ ap = av;
+ *ap++ = PR_COMMAND;
+ *ap++ = (char*)dir;
+ *ap++ = cmd;
+ while (*ap++ = *argv++);
+ if (!(s = getenv(PR_SILENT)) || !*s)
+ {
+ sfprintf(sfstderr, "+");
+ ap = av;
+ while (s = *ap++)
+ sfprintf(sfstderr, " %s", s);
+ sfprintf(sfstderr, "\n");
+ sfsync(sfstderr);
+ }
+ execv(*av, av);
+ free(av);
+ }
+ }
+}
+
+#else
+
+NoN(setpreroot)
+
+#endif
diff --git a/src/lib/libast/regex/regalloc.c b/src/lib/libast/regex/regalloc.c
new file mode 100644
index 0000000..03807a4
--- /dev/null
+++ b/src/lib/libast/regex/regalloc.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * posix regex alloc control
+ */
+
+#include "reglib.h"
+
+void
+regalloc(void* handle, void*(*resize)(void*,void*,size_t), regflags_t flags)
+{
+ state.disc.re_flags = flags;
+ state.disc.re_resizef = resize;
+ state.disc.re_resizehandle = handle;
+}
diff --git a/src/lib/libast/regex/regcache.c b/src/lib/libast/regex/regcache.c
new file mode 100644
index 0000000..a45f0e3
--- /dev/null
+++ b/src/lib/libast/regex/regcache.c
@@ -0,0 +1,198 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * regcomp() regex_t cache
+ * at&t research
+ */
+
+#include <ast.h>
+#include <regex.h>
+
+#define CACHE 8 /* default # cached re's */
+#define ROUND 64 /* pattern buffer size round */
+
+typedef unsigned long Key_t;
+
+typedef struct Cache_s
+{
+ char* pattern;
+ regex_t re;
+ unsigned long serial;
+ regflags_t reflags;
+ int keep;
+ int size;
+} Cache_t;
+
+typedef struct State_s
+{
+ unsigned int size;
+ unsigned long serial;
+ char* locale;
+ Cache_t** cache;
+} State_t;
+
+static State_t matchstate;
+
+/*
+ * flush the cache
+ */
+
+static void
+flushcache(void)
+{
+ register int i;
+
+ for (i = matchstate.size; i--;)
+ if (matchstate.cache[i] && matchstate.cache[i]->keep)
+ {
+ matchstate.cache[i]->keep = 0;
+ regfree(&matchstate.cache[i]->re);
+ }
+}
+
+/*
+ * return regcomp() compiled re for pattern and reflags
+ */
+
+regex_t*
+regcache(const char* pattern, regflags_t reflags, int* status)
+{
+ register Cache_t* cp;
+ register int i;
+ char* s;
+ int empty;
+ int unused;
+ int old;
+ Key_t key;
+
+ /*
+ * 0 pattern flushes the cache and reflags>0 extends cache
+ */
+
+ if (!pattern)
+ {
+ flushcache();
+ i = 0;
+ if (reflags > matchstate.size)
+ {
+ if (matchstate.cache = newof(matchstate.cache, Cache_t*, reflags, 0))
+ matchstate.size = reflags;
+ else
+ {
+ matchstate.size = 0;
+ i = 1;
+ }
+ }
+ if (status)
+ *status = i;
+ return 0;
+ }
+ if (!matchstate.cache)
+ {
+ if (!(matchstate.cache = newof(0, Cache_t*, CACHE, 0)))
+ return 0;
+ matchstate.size = CACHE;
+ }
+
+ /*
+ * flush the cache if the locale changed
+ * the ast setlocale() intercept maintains
+ * persistent setlocale() return values
+ */
+
+ if ((s = setlocale(LC_CTYPE, NiL)) != matchstate.locale)
+ {
+ matchstate.locale = s;
+ flushcache();
+ }
+
+ /*
+ * check if the pattern is in the cache
+ */
+
+ for (i = 0; i < sizeof(key) && pattern[i]; i++)
+ ((char*)&key)[i] = pattern[i];
+ for (; i < sizeof(key); i++)
+ ((char*)&key)[i] = 0;
+ empty = unused = -1;
+ old = 0;
+ for (i = matchstate.size; i--;)
+ if (!matchstate.cache[i])
+ empty = i;
+ else if (!matchstate.cache[i]->keep)
+ unused = i;
+ else if (*(Key_t*)matchstate.cache[i]->pattern == key && !strcmp(matchstate.cache[i]->pattern, pattern) && matchstate.cache[i]->reflags == reflags)
+ break;
+ else if (!matchstate.cache[old] || matchstate.cache[old]->serial > matchstate.cache[i]->serial)
+ old = i;
+ if (i < 0)
+ {
+ if (unused < 0)
+ {
+ if (empty < 0)
+ unused = old;
+ else
+ unused = empty;
+ }
+ if (!(cp = matchstate.cache[unused]) && !(cp = matchstate.cache[unused] = newof(0, Cache_t, 1, 0)))
+ {
+ if (status)
+ *status = REG_ESPACE;
+ return 0;
+ }
+ if (cp->keep)
+ {
+ cp->keep = 0;
+ regfree(&cp->re);
+ }
+ if ((i = strlen(pattern) + 1) > cp->size)
+ {
+ cp->size = roundof(i, ROUND);
+ if (!(cp->pattern = newof(cp->pattern, char, cp->size, 0)))
+ {
+ if (status)
+ *status = REG_ESPACE;
+ return 0;
+ }
+ }
+ strcpy(cp->pattern, pattern);
+ while (++i < sizeof(Key_t))
+ cp->pattern[i] = 0;
+ pattern = (const char*)cp->pattern;
+ if (i = regcomp(&cp->re, pattern, reflags))
+ {
+ if (status)
+ *status = i;
+ return 0;
+ }
+ cp->keep = 1;
+ cp->reflags = reflags;
+ }
+ else
+ cp = matchstate.cache[i];
+ cp->serial = ++matchstate.serial;
+ if (status)
+ *status = 0;
+ return &cp->re;
+}
diff --git a/src/lib/libast/regex/regclass.c b/src/lib/libast/regex/regclass.c
new file mode 100644
index 0000000..87ada74
--- /dev/null
+++ b/src/lib/libast/regex/regclass.c
@@ -0,0 +1,298 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * RE character class support
+ */
+
+#include "reglib.h"
+
+struct Ctype_s; typedef struct Ctype_s Ctype_t;
+
+struct Ctype_s
+{
+ const char* name;
+ size_t size;
+ regclass_t ctype;
+ Ctype_t* next;
+#if _lib_wctype
+ wctype_t wtype;
+#endif
+};
+
+static Ctype_t* ctypes;
+
+/*
+ * this stuff gets around posix failure to define isblank,
+ * and the fact that ctype functions are macros
+ * and any local extensions that may not even have functions or macros
+ */
+
+#if _need_iswblank
+
+int
+_reg_iswblank(wint_t wc)
+{
+ static int initialized;
+ static wctype_t wt;
+
+ if (!initialized)
+ {
+ initialized = 1;
+ wt = wctype("blank");
+ }
+ return iswctype(wc, wt);
+}
+
+#endif
+
+static int Isalnum(int c) { return iswalnum(c); }
+static int Isalpha(int c) { return iswalpha(c); }
+static int Isblank(int c) { return iswblank(c); }
+static int Iscntrl(int c) { return iswcntrl(c); }
+static int Isdigit(int c) { return iswdigit(c); }
+static int Notdigit(int c) { return !iswdigit(c); }
+static int Isgraph(int c) { return iswgraph(c); }
+static int Islower(int c) { return iswlower(c); }
+static int Isprint(int c) { return iswprint(c); }
+static int Ispunct(int c) { return iswpunct(c); }
+static int Isspace(int c) { return iswspace(c); }
+static int Notspace(int c) { return !iswspace(c); }
+static int Isupper(int c) { return iswupper(c); }
+static int Isword(int c) { return iswalnum(c) || c == '_'; }
+static int Notword(int c) { return !iswalnum(c) && c != '_'; }
+static int Isxdigit(int c) { return iswxdigit(c);}
+
+#if _lib_wctype
+
+static int Is_wc_1(int);
+static int Is_wc_2(int);
+static int Is_wc_3(int);
+static int Is_wc_4(int);
+static int Is_wc_5(int);
+static int Is_wc_6(int);
+static int Is_wc_7(int);
+static int Is_wc_8(int);
+static int Is_wc_9(int);
+static int Is_wc_10(int);
+static int Is_wc_11(int);
+static int Is_wc_12(int);
+static int Is_wc_13(int);
+static int Is_wc_14(int);
+static int Is_wc_15(int);
+static int Is_wc_16(int);
+
+#endif
+
+#define SZ(s) s,(sizeof(s)-1)
+
+static Ctype_t ctype[] =
+{
+ { SZ("alnum"), Isalnum },
+ { SZ("alpha"), Isalpha },
+ { SZ("blank"), Isblank },
+ { SZ("cntrl"), Iscntrl },
+ { SZ("digit"), Isdigit },
+ { SZ("graph"), Isgraph },
+ { SZ("lower"), Islower },
+ { SZ("print"), Isprint },
+ { SZ("punct"), Ispunct },
+ { SZ("space"), Isspace },
+ { SZ("upper"), Isupper },
+ { SZ("word"), Isword },
+ { SZ("xdigit"),Isxdigit},
+
+#define CTYPES 13
+
+#if _lib_wctype
+ { 0, 0, Is_wc_1 },
+ { 0, 0, Is_wc_2 },
+ { 0, 0, Is_wc_3 },
+ { 0, 0, Is_wc_4 },
+ { 0, 0, Is_wc_5 },
+ { 0, 0, Is_wc_6 },
+ { 0, 0, Is_wc_7 },
+ { 0, 0, Is_wc_8 },
+ { 0, 0, Is_wc_9 },
+ { 0, 0, Is_wc_10 },
+ { 0, 0, Is_wc_11 },
+ { 0, 0, Is_wc_12 },
+ { 0, 0, Is_wc_13 },
+ { 0, 0, Is_wc_14 },
+ { 0, 0, Is_wc_15 },
+ { 0, 0, Is_wc_16 },
+
+#define WTYPES 16
+
+#else
+
+#define WTYPES 0
+
+#endif
+};
+
+#if _lib_wctype
+
+static int Is_wc_1(int c) { return iswctype(c, ctype[CTYPES+0].wtype); }
+static int Is_wc_2(int c) { return iswctype(c, ctype[CTYPES+1].wtype); }
+static int Is_wc_3(int c) { return iswctype(c, ctype[CTYPES+2].wtype); }
+static int Is_wc_4(int c) { return iswctype(c, ctype[CTYPES+3].wtype); }
+static int Is_wc_5(int c) { return iswctype(c, ctype[CTYPES+4].wtype); }
+static int Is_wc_6(int c) { return iswctype(c, ctype[CTYPES+5].wtype); }
+static int Is_wc_7(int c) { return iswctype(c, ctype[CTYPES+6].wtype); }
+static int Is_wc_8(int c) { return iswctype(c, ctype[CTYPES+7].wtype); }
+static int Is_wc_9(int c) { return iswctype(c, ctype[CTYPES+8].wtype); }
+static int Is_wc_10(int c) { return iswctype(c, ctype[CTYPES+9].wtype); }
+static int Is_wc_11(int c) { return iswctype(c, ctype[CTYPES+10].wtype); }
+static int Is_wc_12(int c) { return iswctype(c, ctype[CTYPES+11].wtype); }
+static int Is_wc_13(int c) { return iswctype(c, ctype[CTYPES+12].wtype); }
+static int Is_wc_14(int c) { return iswctype(c, ctype[CTYPES+13].wtype); }
+static int Is_wc_15(int c) { return iswctype(c, ctype[CTYPES+14].wtype); }
+static int Is_wc_16(int c) { return iswctype(c, ctype[CTYPES+15].wtype); }
+
+#endif
+
+/*
+ * return pointer to ctype function for :class:] in s
+ * s points to the first char after the initial [
+ * dynamic wctype classes are locale-specific
+ * dynamic entry locale is punned in Ctype_t.next
+ * the search does a lazy (one entry at a time) flush on locale mismatch
+ * if e!=0 it points to next char in s
+ * 0 returned on error
+ */
+
+regclass_t
+regclass(const char* s, char** e)
+{
+ register Ctype_t* cp;
+ register int c;
+ register size_t n;
+ register const char* t;
+ Ctype_t* lc;
+ Ctype_t* xp;
+ Ctype_t* zp;
+
+ if (!(c = *s++))
+ return 0;
+ for (t = s; *t && (*t != c || *(t + 1) != ']'); t++);
+ if (*t != c || !(n = t - s))
+ return 0;
+ for (cp = ctypes; cp; cp = cp->next)
+ if (n == cp->size && strneq(s, cp->name, n))
+ goto found;
+ xp = zp = 0;
+ lc = (Ctype_t*)setlocale(LC_CTYPE, NiL);
+ for (cp = ctype; cp < &ctype[elementsof(ctype)]; cp++)
+ {
+#if _lib_wctype
+ if (!zp)
+ {
+ if (!cp->size)
+ zp = cp;
+ else if (!xp && cp->next && cp->next != lc)
+ xp = cp;
+ }
+#endif
+ if (n == cp->size && strneq(s, cp->name, n) && (!cp->next || cp->next == lc))
+ goto found;
+ }
+#if _lib_wctype
+ if (!(cp = zp))
+ {
+ if (!(cp = xp))
+ return 0;
+ cp->size = 0;
+ if (!streq(cp->name, s))
+ {
+ free((char*)cp->name);
+ cp->name = 0;
+ }
+ }
+ if (!cp->name)
+ {
+ if (!(cp->name = (const char*)memdup(s, n + 1)))
+ return 0;
+ *((char*)cp->name + n) = 0;
+ }
+ /* mvs.390 needs the (char*) cast -- barf */
+ if (!(cp->wtype = wctype((char*)cp->name)))
+ {
+ free((char*)cp->name);
+ cp->name = 0;
+ return 0;
+ }
+ cp->size = n;
+ cp->next = lc;
+#endif
+ found:
+ if (e)
+ *e = (char*)t + 2;
+ return cp->ctype;
+}
+
+/*
+ * associate the ctype function fun with name
+ */
+
+int
+regaddclass(const char* name, regclass_t fun)
+{
+ register Ctype_t* cp;
+ register Ctype_t* np;
+ register size_t n;
+
+ n = strlen(name);
+ for (cp = ctypes; cp; cp = cp->next)
+ if (cp->size == n && strneq(name, cp->name, n))
+ {
+ cp->ctype = fun;
+ return 0;
+ }
+ if (!(np = newof(0, Ctype_t, 1, n + 1)))
+ return REG_ESPACE;
+ np->size = n;
+ np->name = strcpy((char*)(np + 1), name);
+ np->ctype = fun;
+ np->next = ctypes;
+ ctypes = np;
+ return 0;
+}
+
+/*
+ * return pointer to ctype function for token
+ */
+
+regclass_t
+classfun(int type)
+{
+ switch (type)
+ {
+ case T_ALNUM: return Isword;
+ case T_ALNUM_NOT: return Notword;
+ case T_DIGIT: return Isdigit;
+ case T_DIGIT_NOT: return Notdigit;
+ case T_SPACE: return Isspace;
+ case T_SPACE_NOT: return Notspace;
+ }
+ return 0;
+}
diff --git a/src/lib/libast/regex/regcoll.c b/src/lib/libast/regex/regcoll.c
new file mode 100644
index 0000000..64dc7a8
--- /dev/null
+++ b/src/lib/libast/regex/regcoll.c
@@ -0,0 +1,120 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * regex collation symbol support
+ */
+
+#include "reglib.h"
+
+/*
+ * return the collating symbol delimited by [c c], where c is either '=' or '.'
+ * s points to the first char after the initial [
+ * if e!=0 it is set to point to the next char in s on return
+ *
+ * the collating symbol is converted to multibyte in <buf,size>
+ * the return value is:
+ * -1 syntax error / invalid collating element
+ * >=0 size with 0-terminated mb character (*wc != 0)
+ * or collating element (*wc == 0) in buf
+ */
+
+int
+regcollate(register const char* s, char** e, char* buf, size_t size, wchar_t* wc)
+{
+ register int c;
+ register char* b;
+ register char* x;
+ const char* t;
+ int i;
+ int r;
+ int term;
+ wchar_t w;
+ char xfm[256];
+ char tmp[sizeof(xfm)];
+
+ if (size < 2 || (term = *s) != '.' && term != '=' || !*++s || *s == term && *(s + 1) == ']')
+ goto nope;
+ t = s;
+ w = mbchar(s);
+ if ((r = (s - t)) > 1)
+ {
+ if (*s++ != term || *s++ != ']')
+ goto oops;
+ goto done;
+ }
+ if (*s == term && *(s + 1) == ']')
+ {
+ s += 2;
+ goto done;
+ }
+ b = buf;
+ x = buf + size - 2;
+ s = t;
+ for (;;)
+ {
+ if (!(c = *s++))
+ goto oops;
+ if (c == term)
+ {
+ if (!(c = *s++))
+ goto oops;
+ if (c != term)
+ {
+ if (c != ']')
+ goto oops;
+ break;
+ }
+ }
+ if (b < x)
+ *b++ = c;
+ }
+ r = s - t - 2;
+ w = 0;
+ if (b >= x)
+ goto done;
+ *b = 0;
+ for (i = 0; i < r && i < sizeof(tmp) - 1; i++)
+ tmp[i] = '0';
+ tmp[i] = 0;
+ if (mbxfrm(xfm, buf, sizeof(xfm)) >= mbxfrm(xfm, tmp, sizeof(xfm)))
+ goto nope;
+ t = (const char*)buf;
+ done:
+ if (r <= size)
+ {
+ memcpy(buf, t, r);
+ if (r < size)
+ buf[r] = 0;
+ }
+ if (wc)
+ *wc = w;
+ if (e)
+ *e = (char*)s;
+ return r;
+ oops:
+ s--;
+ nope:
+ if (e)
+ *e = (char*)s;
+ return -1;
+}
diff --git a/src/lib/libast/regex/regcomp.c b/src/lib/libast/regex/regcomp.c
new file mode 100644
index 0000000..416d453
--- /dev/null
+++ b/src/lib/libast/regex/regcomp.c
@@ -0,0 +1,3544 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * posix regex compiler
+ */
+
+#include "reglib.h"
+
+#if _PACKAGE_ast
+#include "lclib.h"
+#endif
+
+#define serialize re_serialize /* hp.ia64 <unistd.h>! */
+
+#define C_ESC (-1)
+#define C_MB (-2)
+
+#if _AST_REGEX_DEBUG
+
+#define DEBUG_TEST(f,y,n) ((debug&(debug_flag=f))?(y):(n))
+#define DEBUG_CODE(f,y,n) do if(debug&(f)){y}else{n} while(0)
+#define DEBUG_INIT() do { char* t; if (!debug) { debug = 0x80000000; if (t = getenv("_AST_regex_comp_debug")) debug |= strtoul(t, NiL, 0); } } while (0)
+
+static unsigned long debug;
+static unsigned long debug_flag;
+
+#else
+
+#define DEBUG_INIT()
+#define DEBUG_TEST(f,y,n) (n)
+#define DEBUG_CODE(f,y,n) do {n} while(0)
+
+#endif
+
+#if _PACKAGE_ast
+
+typedef struct Cchr_s
+{
+ Dtlink_t lnk;
+ unsigned char nam[2];
+ Ckey_t key;
+} Cchr_t;
+
+#endif
+
+#define eat(p) do{if ((p)->token.push)(p)->token.push=0;else (p)->cursor+=(p)->token.len;}while (0)
+
+/*
+ * determine whether greedy matching will work, i.e. produce
+ * the best match first. such expressions are "easy", and
+ * need no backtracking once a complete match is found.
+ * if an expression has backreferences or alts it's hard
+ * else if it has only one closure it's easy
+ * else if all closures are simple (i.e. one-character) it's easy
+ * else it's hard.
+ */
+
+typedef struct Stats_s
+{
+ unsigned long l; /* min length to left of x */
+ unsigned long k; /* min length to left of y */
+ unsigned long m; /* min length */
+ unsigned long n; /* max length */
+ unsigned short a; /* number of alternations */
+ unsigned short b; /* number of backrefs */
+ unsigned short c; /* number of closures */
+ unsigned short e; /* $ */
+ unsigned short i; /* number of negations */
+ unsigned short p; /* number of named subexpressions */
+ unsigned short s; /* number of simple closures */
+ unsigned short t; /* number of tries */
+ unsigned short u; /* number of unnamed subexpressions */
+ Rex_t* x; /* max length REX_STRING */
+ Rex_t* y; /* max length REX_TRIE */
+} Stats_t;
+
+typedef struct Token_s
+{
+ unsigned long min;
+ unsigned long max;
+ short lex;
+ short len;
+ short esc;
+ short att;
+ short push;
+} Token_t;
+
+typedef struct Cenv_s
+{
+ int delimiter; /* pattern delimiter */
+ int error; /* last error */
+ int explicit; /* explicit match on this char */
+ int mappeddot; /* inverse mapped '.' */
+ int mappednewline; /* inverse mapped '\n' */
+ int mappedslash; /* inverse mapped '/' */
+ regflags_t flags; /* flags arg to regcomp */
+ int type; /* BRE,ERE,ARE,SRE,KRE */
+ unsigned char* cursor; /* curent point in re */
+ unsigned char* pattern; /* the original pattern */
+ unsigned char* literal; /* literal restart pattern */
+ int parno; /* number of last open paren */
+ int parnest; /* paren nest count */
+ int posixkludge; /* to make * nonspecial */
+ int regexp; /* <regexp.h> compatibility */
+ Token_t token; /* token lookahead */
+ Stats_t stats; /* RE statistics */
+ int terminator; /* pattern terminator */
+ Rex_t* paren[2*(BACK_REF_MAX+2)];
+ /* paren[i]!=0 if \i defined */
+ regex_t* regex; /* user handle */
+ regdisc_t* disc; /* user discipline */
+ unsigned char* map; /* external to native ccode map */
+ unsigned char* MAP; /* fold and/or map */
+} Cenv_t;
+
+/*
+ * allocate a new Rex_t node
+ */
+
+#if _BLD_DEBUG
+#define node(a,b,c,d,e) node(a,b,c,d,e, const char* file, unsigned int line)
+#endif
+
+static Rex_t*
+node(Cenv_t* env, int type, int lo, int hi, size_t extra)
+{
+ register Rex_t* e;
+
+ DEBUG_TEST(0x0800,(sfprintf(sfstdout, "%s:%d node(%d,%d,%d,%u)\n", file, line, type, lo, hi, sizeof(Rex_t) + extra)),(0));
+ if (e = (Rex_t*)alloc(env->disc, 0, sizeof(Rex_t) + extra))
+ {
+ memset(e, 0, sizeof(Rex_t) + extra);
+ e->type = type;
+ e->marked = 0;
+ e->lo = lo;
+ e->hi = hi;
+ e->flags = env->flags;
+ e->map = (e->flags & REG_ICASE) ? env->MAP : env->map;
+ e->explicit = env->explicit;
+ if (extra)
+ e->re.data = (char*)e + sizeof(Rex_t);
+ }
+ return e;
+}
+
+#if _BLD_DEBUG
+#undef node
+#define node(a,b,c,d,e) node(a,b,c,d,e,__FILE__,__LINE__)
+#endif
+
+/*
+ * free a Trie_node_t node
+ */
+
+static void
+triedrop(regdisc_t* disc, Trie_node_t* e)
+{
+ if (e)
+ {
+ triedrop(disc, e->son);
+ triedrop(disc, e->sib);
+ alloc(disc, e, 0);
+ }
+}
+
+/*
+ * free a Rex_t node
+ */
+
+void
+drop(regdisc_t* disc, Rex_t* e)
+{
+ int i;
+ Rex_t* x;
+
+ if (e && !(disc->re_flags & REG_NOFREE))
+ do
+ {
+ switch (e->type)
+ {
+ case REX_ALT:
+ case REX_CONJ:
+ drop(disc, e->re.group.expr.binary.left);
+ drop(disc, e->re.group.expr.binary.right);
+ break;
+ case REX_GROUP:
+ case REX_GROUP_AHEAD:
+ case REX_GROUP_AHEAD_NOT:
+ case REX_GROUP_BEHIND:
+ case REX_GROUP_BEHIND_NOT:
+ case REX_GROUP_CUT:
+ case REX_NEG:
+ case REX_REP:
+ drop(disc, e->re.group.expr.rex);
+ break;
+ case REX_TRIE:
+ for (i = 0; i <= UCHAR_MAX; i++)
+ triedrop(disc, e->re.trie.root[i]);
+ break;
+ }
+ x = e->next;
+ alloc(disc, e, 0);
+ } while (e = x);
+}
+
+/*
+ * mark e and descendants minimal
+ */
+
+static void
+mark(register Rex_t* e, int set)
+{
+ if (e && !e->marked)
+ do
+ {
+ e->marked = 1;
+ if (set)
+ e->flags |= REG_MINIMAL;
+ else
+ e->flags &= ~REG_MINIMAL;
+ switch (e->type)
+ {
+ case REX_ALT:
+ case REX_CONJ:
+ case REX_GROUP_COND:
+ if (e->re.group.expr.binary.left)
+ mark(e->re.group.expr.binary.left, set);
+ if (e->re.group.expr.binary.right)
+ mark(e->re.group.expr.binary.right, set);
+ break;
+ case REX_GROUP:
+ case REX_GROUP_AHEAD:
+ case REX_GROUP_AHEAD_NOT:
+ case REX_GROUP_BEHIND:
+ case REX_GROUP_BEHIND_NOT:
+ case REX_GROUP_CUT:
+ case REX_NEG:
+ case REX_REP:
+ case REX_TRIE:
+ mark(e->re.group.expr.rex, set);
+ break;
+ }
+ } while (e = e->next);
+}
+
+/*
+ * assign subexpression numbers by a preorder tree walk
+ */
+
+static int
+serialize(Cenv_t* env, Rex_t* e, int n)
+{
+ do
+ {
+ e->serial = n++;
+ switch (e->type)
+ {
+ case REX_ALT:
+ case REX_GROUP_COND:
+ if (e->re.group.expr.binary.left)
+ n = serialize(env, e->re.group.expr.binary.left, n);
+ e->re.group.expr.binary.serial = n++;
+ if (e->re.group.expr.binary.right)
+ n = serialize(env, e->re.group.expr.binary.right, n);
+ break;
+ case REX_CONJ:
+ n = serialize(env, e->re.group.expr.binary.left, n);
+ n = serialize(env, e->re.group.expr.binary.right, n);
+ break;
+ case REX_GROUP:
+ case REX_GROUP_AHEAD:
+ case REX_GROUP_AHEAD_NOT:
+ case REX_GROUP_BEHIND:
+ case REX_GROUP_BEHIND_NOT:
+ case REX_GROUP_CUT:
+ case REX_NEG:
+ case REX_REP:
+ n = serialize(env, e->re.group.expr.rex, n);
+ break;
+ }
+ } while (e = e->next);
+ return n;
+}
+
+/*
+ * catenate e and f into a sequence, collapsing them if possible
+ */
+
+static Rex_t*
+cat(Cenv_t* env, Rex_t* e, Rex_t* f)
+{
+ Rex_t* g;
+
+ if (!f)
+ {
+ drop(env->disc, e);
+ return 0;
+ }
+ if (e->type == REX_NULL)
+ {
+ drop(env->disc, e);
+ return f;
+ }
+ if (f->type == REX_NULL)
+ {
+ g = f->next;
+ f->next = 0;
+ drop(env->disc, f);
+ f = g;
+ }
+ else if (e->type == REX_DOT && f->type == REX_DOT)
+ {
+ unsigned int m = e->lo + f->lo;
+ unsigned int n = e->hi + f->hi;
+
+ if (m <= RE_DUP_MAX)
+ {
+ if (e->hi > RE_DUP_MAX || f->hi > RE_DUP_MAX)
+ {
+ n = RE_DUP_INF;
+ goto combine;
+ }
+ else if (n <= RE_DUP_MAX)
+ {
+ combine:
+ e->lo = m;
+ e->hi = n;
+ g = f->next;
+ f->next = 0;
+ drop(env->disc, f);
+ f = g;
+ }
+ }
+ }
+ e->next = f;
+ return e;
+}
+
+/*
+ * collect re statistics
+ */
+
+static int
+stats(register Cenv_t* env, register Rex_t* e)
+{
+ register unsigned long n;
+ register unsigned long m;
+ unsigned long cm;
+ unsigned long nm;
+ unsigned long cn;
+ unsigned long nn;
+ unsigned long l;
+ unsigned long k;
+ unsigned long t;
+ Rex_t* q;
+ Rex_t* x;
+ Rex_t* y;
+ unsigned char c;
+ unsigned char b;
+
+ do
+ {
+ switch (e->type)
+ {
+ case REX_ALT:
+ x = env->stats.x;
+ l = env->stats.l;
+ y = env->stats.y;
+ k = env->stats.k;
+ t = env->stats.t;
+ if (++env->stats.a <= 0)
+ return 1;
+ cm = env->stats.m;
+ env->stats.m = 0;
+ cn = env->stats.n;
+ env->stats.n = 0;
+ if (stats(env, e->re.group.expr.binary.left))
+ return 1;
+ m = env->stats.m;
+ env->stats.m = 0;
+ n = env->stats.n;
+ env->stats.n = 0;
+ if (e->re.group.expr.binary.right && stats(env, e->re.group.expr.binary.right))
+ return 1;
+ if (env->stats.m > m)
+ env->stats.m = m;
+ else
+ m = env->stats.m;
+ if ((env->stats.m += cm) < m)
+ return 1;
+ if (env->stats.n < n)
+ env->stats.n = n;
+ else
+ n = env->stats.n;
+ if ((env->stats.n += cn) < n)
+ return 1;
+ env->stats.x = x;
+ env->stats.l = l;
+ env->stats.y = y;
+ env->stats.k = k;
+ env->stats.t = t;
+ break;
+ case REX_BACK:
+ if (++env->stats.b <= 0)
+ return 1;
+ break;
+ case REX_CLASS:
+ case REX_COLL_CLASS:
+ case REX_DOT:
+ case REX_ONECHAR:
+ n = env->stats.m;
+ if ((env->stats.m += e->lo) < n)
+ return 1;
+ if (e->hi != RE_DUP_INF)
+ {
+ n = env->stats.n;
+ if ((env->stats.n += e->hi) < n)
+ return 1;
+ }
+ if (e->lo != e->hi)
+ {
+ if (++env->stats.c <= 0)
+ return 1;
+ if (++env->stats.s <= 0)
+ return 1;
+ }
+ break;
+ case REX_CONJ:
+ cm = env->stats.m;
+ env->stats.m = 0;
+ cn = env->stats.n;
+ env->stats.n = 0;
+ if (stats(env, e->re.group.expr.binary.left))
+ return 1;
+ nm = env->stats.m;
+ env->stats.m = 0;
+ nn = env->stats.n;
+ env->stats.n = 0;
+ if (stats(env, e->re.group.expr.binary.right))
+ return 1;
+ if (env->stats.m < nm)
+ env->stats.m = nm;
+ else
+ nm = env->stats.m;
+ if ((env->stats.m += cm) < nm)
+ return 1;
+ if (env->stats.n < nn)
+ env->stats.n = nn;
+ else
+ nn = env->stats.n;
+ if ((env->stats.n += cn) < nn)
+ return 1;
+ break;
+ case REX_END:
+ env->stats.e = 1;
+ break;
+ case REX_GROUP:
+ if (e->re.group.number && ++env->stats.p <= 0 || !e->re.group.number && ++env->stats.u <= 0)
+ return 1;
+ if (stats(env, e->re.group.expr.rex))
+ return 1;
+ break;
+ case REX_GROUP_AHEAD:
+ case REX_GROUP_AHEAD_NOT:
+ case REX_GROUP_BEHIND:
+ case REX_GROUP_BEHIND_NOT:
+ m = env->stats.m;
+ n = env->stats.n;
+ x = env->stats.x;
+ y = env->stats.y;
+ if (stats(env, e->re.group.expr.rex))
+ return 1;
+ env->stats.m = m;
+ env->stats.n = n;
+ env->stats.x = x;
+ env->stats.y = y;
+ switch (e->type)
+ {
+ case REX_GROUP_AHEAD:
+ case REX_GROUP_BEHIND:
+ if (++env->stats.u <= 0)
+ return 1;
+ break;
+ }
+ break;
+ case REX_GROUP_COND:
+ if (++env->stats.u <= 0)
+ return 1;
+ m = env->stats.m;
+ n = env->stats.n;
+ x = env->stats.x;
+ y = env->stats.y;
+ if (e->re.group.size > 0 && ++env->stats.b <= 0)
+ return 1;
+ if (e->re.group.expr.binary.left && stats(env, e->re.group.expr.binary.left))
+ return 1;
+ if (q = e->re.group.expr.binary.right)
+ {
+ if (q->re.group.expr.binary.left && stats(env, q->re.group.expr.binary.left))
+ return 1;
+ if (q->re.group.expr.binary.right && stats(env, q->re.group.expr.binary.right))
+ return 1;
+ }
+ env->stats.m = m;
+ env->stats.n = n;
+ env->stats.x = x;
+ env->stats.y = y;
+ break;
+ case REX_GROUP_CUT:
+ if (++env->stats.u <= 0)
+ return 1;
+ m = env->stats.m;
+ n = env->stats.n;
+ x = env->stats.x;
+ y = env->stats.y;
+ if (stats(env, e->re.group.expr.rex))
+ return 1;
+ env->stats.m = m;
+ env->stats.n = n;
+ env->stats.x = x;
+ env->stats.y = y;
+ break;
+ case REX_NEG:
+ env->stats.i++;
+ x = env->stats.x;
+ l = env->stats.l;
+ y = env->stats.y;
+ k = env->stats.k;
+ t = env->stats.t;
+ cm = env->stats.m;
+ env->stats.m = 0;
+ if (stats(env, e->re.group.expr.rex))
+ return 1;
+ env->stats.m = !env->stats.m;
+ if ((env->stats.m += cm) < cm)
+ return 1;
+ env->stats.x = x;
+ env->stats.l = l;
+ env->stats.y = y;
+ env->stats.k = k;
+ env->stats.t = t;
+ break;
+ case REX_REP:
+ x = env->stats.x;
+ l = env->stats.l;
+ y = env->stats.y;
+ k = env->stats.k;
+ t = env->stats.t;
+ if (++env->stats.c <= 0)
+ return 1;
+ b = env->stats.b;
+ c = env->stats.c;
+ cm = env->stats.m;
+ env->stats.m = 0;
+ if (stats(env, e->re.group.expr.rex))
+ return 1;
+ if (env->stats.m == 1 && b == env->stats.b && c == env->stats.c && ++env->stats.s <= 0)
+ return 1;
+ if (e->lo < 1)
+ {
+ env->stats.x = x;
+ env->stats.l = l;
+ env->stats.y = y;
+ env->stats.k = k;
+ env->stats.t = t;
+ env->stats.m = cm;
+ }
+ else
+ {
+ m = env->stats.m;
+ if ((env->stats.m *= e->lo) > 0 && env->stats.m < m)
+ return 1;
+ m = env->stats.m;
+ if ((env->stats.m += cm) < m)
+ return 1;
+ if (env->stats.x != x)
+ env->stats.l = cm;
+ if (env->stats.y != y)
+ env->stats.k = cm;
+ }
+ break;
+ case REX_STRING:
+ if (!e->map)
+ {
+ cm = env->stats.m;
+ if ((env->stats.m += e->re.string.size) < cm)
+ return 1;
+ cn = env->stats.n;
+ if ((env->stats.n += e->re.string.size) < cn)
+ return 1;
+ if (!env->stats.x || env->stats.x->re.string.size < e->re.string.size)
+ {
+ env->stats.x = e;
+ env->stats.l = cm;
+ }
+ }
+ break;
+ case REX_TRIE:
+ if (++env->stats.s <= 0)
+ return 1;
+ cm = env->stats.m;
+ if ((env->stats.m += e->re.trie.min) < cm)
+ return 1;
+ cn = env->stats.n;
+ if ((env->stats.n += e->re.trie.max) < cn)
+ return 1;
+ env->stats.t++;
+ if (!env->stats.y || env->stats.y->re.trie.min < e->re.trie.min)
+ {
+ env->stats.y = e;
+ env->stats.k = cm;
+ }
+ break;
+ }
+ } while (e = e->next);
+ return 0;
+}
+
+static int token(Cenv_t*);
+
+static int
+magic(register Cenv_t* env, register int c, int escaped)
+{
+ register char* sp;
+ register int n;
+ int o = c;
+ int e = env->error;
+ int l = env->token.len;
+ short* mp;
+ char* ep;
+
+ if (mp = state.magic[c])
+ {
+ c = mp[env->type+escaped];
+ if (c >= T_META)
+ {
+ sp = (char*)env->cursor + env->token.len;
+ switch (c)
+ {
+ case T_LEFT:
+ n = 0;
+ ep = sp;
+ while (*sp >= '0' && *sp <= '9')
+ {
+ if (n > (INT_MAX / 10))
+ {
+ env->error = REG_BADBR;
+ goto bad;
+ }
+ n = n * 10 + *sp++ - '0';
+ }
+ if (sp == ep)
+ {
+ if (env->type < SRE || *sp != ',')
+ {
+ env->error = *sp ? REG_BADBR : REG_EBRACE;
+ goto bad;
+ }
+ }
+ else if (n > RE_DUP_MAX)
+ {
+ env->error = REG_BADBR;
+ goto bad;
+ }
+ env->token.min = n;
+ if (*sp == ',')
+ {
+ n = 0;
+ ep = ++sp;
+ while (*sp >= '0' && *sp <= '9')
+ {
+ if (n > (INT_MAX / 10))
+ {
+ env->error = REG_BADBR;
+ goto bad;
+ }
+ n = n * 10 + *sp++ - '0';
+ }
+ if (sp == ep)
+ n = RE_DUP_INF;
+ else if (n < env->token.min)
+ {
+ env->error = REG_BADBR;
+ goto bad;
+ }
+ }
+ env->token.max = n;
+ switch (*sp)
+ {
+ case 0:
+ env->error = REG_EBRACE;
+ goto bad;
+ case '\\':
+ if (!escaped)
+ {
+ env->error = REG_BADBR;
+ goto bad;
+ }
+ sp++;
+ break;
+ default:
+ if (escaped)
+ {
+ env->error = REG_BADBR;
+ goto bad;
+ }
+ break;
+ }
+ switch (*sp++)
+ {
+ case 0:
+ env->error = REG_EBRACE;
+ goto bad;
+ case '}':
+ break;
+ default:
+ env->error = REG_BADBR;
+ goto bad;
+ }
+ env->token.len = sp - (char*)env->cursor;
+ break;
+ case T_RIGHT:
+ env->error = REG_EBRACE;
+ goto bad;
+ case T_OPEN:
+ if (env->type < SRE && *sp == '?')
+ {
+ env->token.len++;
+ env->token.lex = 0;
+ goto group;
+ }
+ break;
+ case T_ESCAPE:
+ c = chresc(sp - 2, &ep);
+ if (ep < sp)
+ goto bad;
+ env->token.len += ep - sp;
+ if (c >= T_META)
+ {
+ env->token.lex = c;
+ c = C_ESC;
+ }
+ return c;
+ case T_BACK+0:
+ case T_BACK+1:
+ case T_BACK+2:
+ case T_BACK+3:
+ case T_BACK+4:
+ case T_BACK+5:
+ case T_BACK+6:
+ case T_BACK+7:
+ n = chresc(sp - 2, &ep);
+ if (ep > sp + 1)
+ {
+ env->token.len += ep - sp;
+ return n;
+ }
+ /*FALLTHROUGH*/
+ case T_BACK+8:
+ case T_BACK+9:
+ if (env->type == SRE || c == T_BACK && !(env->flags & REG_LENIENT))
+ {
+ env->error = REG_BADESC;
+ goto bad;
+ }
+ if ((env->flags & REG_MULTIREF) && isdigit(*sp))
+ {
+ c = (c - T_BACK) * 10 + (*sp - '0');
+ if (c > 0 && c <= env->parno && env->paren[c])
+ c += T_BACK;
+ else
+ c = chresc(sp - 2, &ep);
+ env->token.len++;
+ }
+ if (c == T_BACK)
+ c = 0;
+ break;
+ case T_BAD:
+ if (escaped == 1 && (env->flags & REG_LENIENT) && (c = mp[env->type+escaped+2]) >= T_META)
+ return c;
+ goto bad;
+ }
+ if (env->type >= SRE)
+ {
+ if (c == T_DOT)
+ c = '.';
+ else if (c < T_OPEN)
+ {
+ if (env->type == KRE && *(env->cursor + env->token.len) == '-' && *(env->cursor + env->token.len + 1) == '(')
+ {
+ env->token.len++;
+ env->token.att = 1;
+ }
+ if (env->type == KRE && *(env->cursor + env->token.len) == '(')
+ {
+ env->token.len++;
+ switch (c)
+ {
+ case T_AT:
+ break;
+ case T_PERCENT:
+ env->token.lex = c;
+ goto group;
+ case T_TILDE:
+ env->token.lex = 0;
+ goto group;
+ default:
+ env->token.lex = c;
+ break;
+ }
+ c = T_OPEN;
+ }
+ else if (c == T_STAR)
+ c = T_DOTSTAR;
+ else if (c == T_QUES)
+ c = T_DOT;
+ else
+ {
+ c = o;
+ env->token.len = l;
+ }
+ }
+ else if (c > T_BACK)
+ {
+ c = (c - T_BACK) * 2 - 1;
+ c = (c > env->parno || !env->paren[c]) ? o : T_BACK + c;
+ }
+ else if (env->type == KRE && !env->parnest && (env->flags & REG_SHELL_GROUP))
+ {
+ if (c == T_AND)
+ c = '&';
+ else if (c == T_BAR)
+ c = '|';
+ else if (c == T_OPEN)
+ c = '(';
+ }
+ }
+ }
+ }
+ else if (escaped == 2)
+ {
+ if (env->type >= SRE && !(env->flags & REG_SHELL_ESCAPED) || (env->flags & REG_ESCAPE) && (c == '[' || c == '-' || c == ']' || env->delimiter && c == env->delimiter))
+ /*ok*/;
+ else
+ {
+ env->error = REG_BADESC;
+ goto bad;
+ }
+ }
+ else if (escaped && !(env->flags & REG_LENIENT) && c != ']')
+ {
+ env->error = REG_BADESC;
+ goto bad;
+ }
+ return c;
+ group:
+ sp = (char*)env->cursor + env->token.len;
+ switch (*sp++)
+ {
+ case ')':
+ break;
+ case '#':
+ for (;;)
+ {
+ switch (*sp++)
+ {
+ case 0:
+ env->error = REG_EPAREN;
+ return T_BAD;
+ case ')':
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ break;
+ default:
+ return T_GROUP;
+ }
+ env->cursor = (unsigned char*)sp;
+ return token(env);
+ bad:
+ if (escaped == 2)
+ env->error = e;
+ else if (env->flags & REG_LENIENT)
+ return o;
+ else if (escaped == 1 && !env->error)
+ {
+ if (mp || o == ']')
+ return o;
+ env->error = REG_BADESC;
+ }
+ return T_BAD;
+}
+
+static int
+token(register Cenv_t* env)
+{
+ int c;
+ int posixkludge;
+
+ if (env->token.push)
+ return env->token.lex;
+ env->token.att = env->token.esc = 0;
+ if ((env->token.len = MBSIZE(env->cursor)) > 1)
+ return env->token.lex = C_MB;
+ env->token.lex = 0;
+ for (;;)
+ {
+ c = *env->cursor;
+ if (c == 0 || c == env->delimiter || c == env->terminator)
+ return T_END;
+ if (!(env->flags & REG_COMMENT))
+ break;
+ if (c == '#')
+ {
+ do
+ {
+ c = *++env->cursor;
+ if (c == 0 || c == env->delimiter)
+ return T_END;
+ } while (c != '\n');
+ }
+ else if (!isspace(c))
+ break;
+ env->cursor++;
+ }
+ if (c == '\n' && (env->flags & REG_MULTIPLE) && !env->delimiter)
+ {
+ if (env->parnest)
+ {
+ env->error = REG_EPAREN;
+ return T_BAD;
+ }
+ env->parno = 0;
+ env->pattern = env->cursor + 1;
+ return T_BAR;
+ }
+ if (env->flags & REG_LITERAL)
+ return c;
+ if (posixkludge = env->posixkludge)
+ {
+ env->posixkludge = 0;
+ if (c == '*')
+ return c;
+ }
+ if (c == '\\')
+ {
+ if (env->flags & REG_SHELL_ESCAPED)
+ return c;
+ if (!(c = *(env->cursor + 1)) || c == env->terminator)
+ {
+ if (env->flags & REG_LENIENT)
+ {
+ if (c)
+ {
+ env->token.esc = env->token.len;
+ env->token.len += MBSIZE(env->cursor + 1);
+ return c;
+ }
+ return '\\';
+ }
+ env->error = REG_EESCAPE;
+ return T_BAD;
+ }
+ env->token.esc = env->token.len;
+ env->token.len += MBSIZE(env->cursor + 1);
+ if (env->delimiter && c == 'n')
+ return '\n';
+ else if (c == env->delimiter)
+ return magic(env, c, 0);
+ else if (c == '(' && env->type == BRE)
+ env->posixkludge = 1;
+ else if (c == ')' && env->type == BRE && env->parnest <= 0)
+ {
+ env->error = REG_EPAREN;
+ return T_BAD;
+ }
+ else if (isspace(c) && (env->flags & REG_COMMENT))
+ return c;
+ return magic(env, c, 1);
+ }
+ else if (c == '$')
+ {
+ if (env->type == BRE && (*(env->cursor + 1) == 0 || *(env->cursor + 1) == env->delimiter || *(env->cursor + 1) == env->terminator || *(env->cursor + 1) == '\\' && *(env->cursor + 2) == ')') || (env->flags & REG_MULTIPLE) && *(env->cursor + 1) == '\n')
+ return T_DOLL;
+ }
+ else if (c == '^')
+ {
+ if (env->type == BRE && (env->cursor == env->pattern || posixkludge == 1))
+ {
+ env->posixkludge = 2;
+ return T_CFLX;
+ }
+ }
+ else if (c == ')')
+ {
+ if (env->type != BRE && env->parnest <= 0)
+ return c;
+ }
+ else if (c == '/' && env->explicit == env->mappedslash)
+ {
+ while (*(env->cursor + env->token.len) == c)
+ env->token.len++;
+ return T_SLASHPLUS;
+ }
+ return magic(env, c, 0);
+}
+
+static Celt_t*
+col(Celt_t* ce, int ic, unsigned char* bp, int bw, int bc, unsigned char* ep, int ew, int ec)
+{
+ register char* s;
+ register unsigned char* k;
+ register unsigned char* e;
+ register int c;
+ register int cc;
+ int bt;
+ int et;
+ Ckey_t key;
+
+ cc = 0;
+ for (;;)
+ {
+ k = key;
+ if (bw == 1)
+ {
+ c = bc;
+ if (ic)
+ {
+ if (isupper(c))
+ {
+ c = tolower(c);
+ cc = -1;
+ }
+ else if (islower(c))
+ {
+ c = toupper(c);
+ cc = -1;
+ }
+ }
+ *k++ = c;
+ }
+ else if (bw < COLL_KEY_MAX)
+ {
+ s = (char*)bp;
+ if (ic)
+ {
+ c = mbchar(s);
+ if (iswupper(c))
+ {
+ c = towlower(c);
+ cc = 1;
+ }
+ else if (iswlower(c))
+ {
+ c = towupper(c);
+ cc = 1;
+ }
+ }
+ if (cc > 0)
+ {
+ cc = -1;
+ k += mbconv((char*)k, c);
+ }
+ else
+ for (e = k + bw; k < e; *k++ = *s++);
+ }
+ *k = 0;
+ mbxfrm(ce->beg, key, COLL_KEY_MAX);
+ if (ep)
+ {
+ k = key;
+ c = mbchar(k);
+ if (iswupper(c))
+ bt = COLL_range_uc;
+ else if (iswlower(c))
+ bt = COLL_range_lc;
+ else
+ bt = COLL_range;
+ k = key;
+ if (ew == 1)
+ {
+ c = ec;
+ if (ic)
+ {
+ if (isupper(c))
+ {
+ c = tolower(c);
+ cc = -1;
+ }
+ else if (islower(c))
+ {
+ c = toupper(c);
+ cc = -1;
+ }
+ }
+ *k++ = c;
+ }
+ else if (ew < COLL_KEY_MAX)
+ {
+ s = (char*)ep;
+ if (ic)
+ {
+ c = mbchar(s);
+ if (iswupper(c))
+ {
+ c = towlower(c);
+ cc = 1;
+ }
+ else if (iswlower(c))
+ {
+ c = towupper(c);
+ cc = 1;
+ }
+ }
+ if (cc > 0)
+ {
+ cc = -1;
+ k += mbconv((char*)k, c);
+ }
+ else
+ for (e = k + ew; k < e; *k++ = *s++);
+ }
+ *k = 0;
+ mbxfrm(ce->end, key, COLL_KEY_MAX);
+ k = key;
+ c = mbchar(k);
+ if (iswupper(c))
+ et = COLL_range_uc;
+ else if (iswlower(c))
+ et = COLL_range_lc;
+ else
+ et = COLL_range;
+ ce->typ = bt == et ? bt : COLL_range;
+ }
+ else
+ ce->typ = COLL_char;
+ ce++;
+ if (!ic || !cc)
+ break;
+ ic = 0;
+ }
+ return ce;
+}
+
+static Rex_t*
+bra(Cenv_t* env)
+{
+ Rex_t* e;
+ int c;
+ int i;
+ int w;
+ int neg;
+ int last;
+ int inrange;
+ int complicated;
+ int collate;
+ int elements;
+ unsigned char* first;
+ unsigned char* start;
+ unsigned char* begin;
+ unsigned char* s;
+ regclass_t f;
+ unsigned char buf[4 * (COLL_KEY_MAX + 1)];
+#if _PACKAGE_ast
+ int ic;
+ char mbc[COLL_KEY_MAX + 1];
+#endif
+
+ if (!(e = node(env, REX_CLASS, 1, 1, sizeof(Set_t))))
+ return 0;
+ collate = complicated = elements = 0;
+ if (*env->cursor == '^' || env->type >= SRE && *env->cursor == '!')
+ {
+ env->cursor++;
+ neg = 1;
+ }
+ else
+ neg = 0;
+ first = env->cursor;
+ start = first + MBSIZE(first);
+ if (*env->cursor == 0 || *(env->cursor + 1) == 0 || *env->cursor == env->terminator || *(env->cursor + 1) == env->terminator || (env->flags & REG_ESCAPE) && (*env->cursor == env->delimiter || *env->cursor != '\\' && *(env->cursor + 1) == env->delimiter))
+ goto error;
+ begin = env->cursor + MBSIZE(env->cursor);
+
+ /*
+ * inrange: 0=no, 1=possibly, 2=definitely
+ */
+
+ inrange = 0;
+ for (;;)
+ {
+ if (!(c = *env->cursor) || c == env->terminator || c == env->delimiter && (env->flags & REG_ESCAPE))
+ goto error;
+ env->cursor += (w = MBSIZE(env->cursor));
+ if (c == '\\' && ((env->flags & REG_CLASS_ESCAPE) || *env->cursor == env->delimiter && (env->flags & REG_ESCAPE)))
+ {
+ if (*env->cursor)
+ {
+ if (*env->cursor == 'n')
+ {
+ env->cursor++;
+ c = '\n';
+ }
+ else if (env->type < SRE || !(env->flags & REG_SHELL_ESCAPED))
+ {
+ env->token.len = 1;
+ w = magic(env, *env->cursor, 2);
+ if (env->token.len > 1 || w != T_BAD)
+ {
+ if (env->token.len == 1 && (f = classfun(w)))
+ {
+ if (inrange > 1)
+ {
+ if (env->type < SRE && !(env->flags & REG_LENIENT))
+ goto erange;
+ inrange = 0;
+ }
+ env->cursor++;
+ for (c = 0; c <= UCHAR_MAX; c++)
+ if ((*f)(c))
+ setadd(e->re.charclass, c);
+ complicated++;
+ elements++;
+ continue;
+ }
+ if (env->token.len > 1 || w >= 0 && w < T_META)
+ {
+ c = w;
+ if (c > UCHAR_MAX)
+ {
+ if (env->type < SRE && !(env->flags & REG_LENIENT) && !mbwide())
+ goto erange;
+ c = UCHAR_MAX;
+ }
+ env->cursor += env->token.len;
+ }
+ }
+ }
+ }
+ }
+ else if (c == ']')
+ {
+ if (env->cursor == begin)
+ {
+ last = c;
+ inrange = 1;
+ continue;
+ }
+ if (inrange != 0)
+ {
+ setadd(e->re.charclass, last);
+ elements++;
+ if (inrange == 2)
+ {
+ setadd(e->re.charclass, '-');
+ elements++;
+ }
+ }
+ break;
+ }
+ else if (c == '-')
+ {
+ if (!inrange && env->cursor != begin && *env->cursor != ']')
+ {
+ if (env->type < SRE && !(env->flags & REG_LENIENT))
+ goto erange;
+ continue;
+ }
+ else if (inrange == 1)
+ {
+ inrange = 2;
+ complicated++;
+ continue;
+ }
+ }
+ else if (c == '[')
+ {
+ switch (*env->cursor)
+ {
+ case 0:
+ goto error;
+ case ':':
+ if (env->regexp)
+ goto normal;
+ if (inrange == 1)
+ {
+ setadd(e->re.charclass, last);
+ elements++;
+ }
+ if (!(f = regclass((char*)env->cursor, (char**)&env->cursor)))
+ {
+ if (env->cursor == start && (c = *(env->cursor + 1)))
+ {
+ s = start = env->cursor + 1;
+ while (*++s && *s != ':');
+ if (*s == ':' && *(s + 1) == ']' && *(s + 2) == ']')
+ {
+ if ((i = (s - start)) == 1)
+ {
+ switch (c)
+ {
+ case '<':
+ i = REX_WBEG;
+ break;
+ case '>':
+ i = REX_WEND;
+ break;
+ default:
+ i = 0;
+ break;
+ }
+ if (i)
+ {
+ env->cursor = s + 3;
+ drop(env->disc, e);
+ return node(env, i, 0, 0, 0);
+ }
+ }
+ }
+ }
+ env->error = REG_ECTYPE;
+ goto error;
+ }
+ for (c = 0; c <= UCHAR_MAX; c++)
+ if ((*f)(c))
+ setadd(e->re.charclass, c);
+ inrange = 0;
+ complicated++;
+ elements++;
+ continue;
+ case '=':
+ if (env->regexp)
+ goto normal;
+ if (inrange == 2)
+ goto erange;
+ if (inrange == 1)
+ {
+ setadd(e->re.charclass, last);
+ elements++;
+ }
+ if ((c = regcollate((char*)env->cursor, (char**)&env->cursor, (char*)buf, sizeof(buf), NiL)) < 0)
+ goto ecollate;
+ if (c > 1)
+ collate++;
+ else
+ setadd(e->re.charclass, buf[0]);
+ c = buf[0];
+ inrange = 0;
+ complicated++;
+ elements++;
+ continue;
+ case '.':
+ if (env->regexp)
+ goto normal;
+ if ((c = regcollate((char*)env->cursor, (char**)&env->cursor, (char*)buf, sizeof(buf), NiL)) < 0)
+ goto ecollate;
+ if (c > 1)
+ collate++;
+ c = buf[0];
+ complicated++;
+ break;
+ default:
+ normal:
+ if (*env->cursor == env->terminator || *env->cursor == env->delimiter && (env->flags & REG_ESCAPE))
+ goto error;
+ break;
+ }
+ }
+ else if (w > 1)
+ complicated++;
+ if (inrange == 2)
+ {
+ if (last <= c)
+ {
+ for (i = last; i <= c; i++)
+ setadd(e->re.charclass, i);
+ inrange = env->type >= SRE || (env->flags & REG_LENIENT);
+ elements += 2;
+ }
+ else if (env->type >= SRE)
+ {
+ setadd(e->re.charclass, last);
+ setadd(e->re.charclass, c);
+ elements += 2;
+ inrange = 1;
+ }
+ else if (!(env->flags & REG_LENIENT))
+ goto erange;
+ else
+ inrange = 0;
+ }
+ else if (inrange == 1)
+ {
+ setadd(e->re.charclass, last);
+ elements++;
+ }
+ else
+ inrange = 1;
+ last = c;
+ }
+#if _PACKAGE_ast
+ if (complicated && mbcoll())
+ {
+ Dt_t* dt;
+ Cchr_t* cc;
+ Cchr_t* tc;
+ Cchr_t* xc;
+ Celt_t* ce;
+ Cchr_t key;
+ int rw;
+ int rc;
+ wchar_t wc;
+ unsigned char* rp;
+ unsigned char* pp;
+ char* wp;
+ char cb[2][COLL_KEY_MAX+1];
+
+ static Dtdisc_t disc;
+
+ static const char primary[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+ if (!(dt = (Dt_t*)LCINFO(AST_LC_COLLATE)->data))
+ {
+ disc.key = offsetof(Cchr_t, key);
+ if ((cc = newof(0, Cchr_t, elementsof(primary), 0)) && (dt = dtopen(&disc, Dtoset)))
+ {
+ for (i = 0; i < elementsof(primary) - 1; i++, cc++)
+ {
+ cc->nam[0] = primary[i];
+ mbxfrm(cc->key, cc->nam, COLL_KEY_MAX);
+ dtinsert(dt, cc);
+ }
+ for (i = 0; i < elementsof(cc->key); i++)
+ cc->key[i] = ~0;
+ dtinsert(dt, cc);
+ LCINFO(AST_LC_COLLATE)->data = (void*)dt;
+ }
+ else
+ {
+ if (cc)
+ free(cc);
+ drop(env->disc, e);
+ return 0;
+ }
+ }
+ if (dt)
+ {
+ drop(env->disc, e);
+ if (ic = env->flags & REG_ICASE)
+ elements *= 2;
+ if (!(e = node(env, REX_COLL_CLASS, 1, 1, (elements + 3) * sizeof(Celt_t))))
+ return 0;
+ ce = (Celt_t*)e->re.data;
+ e->re.collate.invert = neg;
+ e->re.collate.elements = ce;
+ env->cursor = first;
+ inrange = 0;
+ for (;;)
+ {
+ if ((c = *env->cursor) == 0 || c == env->terminator || (env->flags & REG_ESCAPE) && c == env->delimiter)
+ goto error;
+ pp = env->cursor;
+ env->cursor += (w = MBSIZE(env->cursor));
+ if (c == '\\' && ((env->flags & REG_CLASS_ESCAPE) || *env->cursor == env->delimiter && (env->flags & REG_ESCAPE)))
+ {
+ if (*env->cursor)
+ {
+ if (*env->cursor == 'n')
+ {
+ pp = env->cursor++;
+ c = '\n';
+ }
+ else if (env->type < SRE || !(env->flags & REG_SHELL_ESCAPED))
+ {
+ env->token.len = 1;
+ w = magic(env, *env->cursor, 2);
+ if (env->token.len > 1 || w != T_BAD)
+ {
+ if (env->token.len == 1 && (f = classfun(w)))
+ {
+ if (inrange > 1)
+ {
+ if (env->type < SRE && !(env->flags & REG_LENIENT))
+ goto erange;
+ inrange = 0;
+ }
+ env->cursor++;
+ ce->fun = f;
+ ce->typ = COLL_call;
+ ce++;
+ continue;
+ }
+ if (env->token.len > 1 || w >= 0 && w < T_META)
+ {
+ c = w;
+ w = mbconv(mbc, c);
+ pp = (unsigned char*)mbc;
+ env->cursor += env->token.len;
+ }
+ }
+ }
+ }
+ }
+ else if (c == ']')
+ {
+ if (env->cursor == begin)
+ {
+ rp = pp;
+ rw = w;
+ inrange = 1;
+ continue;
+ }
+ if (inrange != 0)
+ {
+ ce = col(ce, ic, rp, rw, rc, NiL, 0, 0);
+ if (inrange == 2)
+ ce = col(ce, ic, NiL, 1, '-', NiL, 0, 0);
+ }
+ break;
+ }
+ else if (c == '-')
+ {
+ if (!inrange && env->cursor != begin && *env->cursor != ']')
+ {
+ if (env->type < SRE && !(env->flags & REG_LENIENT))
+ goto erange;
+ continue;
+ }
+ else if (inrange == 1)
+ {
+ inrange = 2;
+ continue;
+ }
+ }
+ else if (c == '[')
+ {
+ switch (*env->cursor)
+ {
+ case 0:
+ goto error;
+ case ':':
+ if (env->regexp)
+ goto complicated_normal;
+ if (inrange == 1)
+ ce = col(ce, ic, rp, rw, rc, NiL, 0, 0);
+ if (!(f = regclass((char*)env->cursor, (char**)&env->cursor)))
+ {
+ if (env->cursor == start && (c = *(env->cursor + 1)) && *(env->cursor + 2) == ':' && *(env->cursor + 3) == ']' && *(env->cursor + 4) == ']')
+ {
+ switch (c)
+ {
+ case '<':
+ i = REX_WBEG;
+ break;
+ case '>':
+ i = REX_WEND;
+ break;
+ default:
+ i = 0;
+ break;
+ }
+ if (i)
+ {
+ env->cursor += 5;
+ drop(env->disc, e);
+ return node(env, i, 0, 0, 0);
+ }
+ }
+ env->error = REG_ECTYPE;
+ goto error;
+ }
+ ce->fun = f;
+ ce->typ = COLL_call;
+ ce++;
+ inrange = 0;
+ continue;
+ case '=':
+ if (env->regexp)
+ goto complicated_normal;
+ if (inrange == 2)
+ goto erange;
+ if (inrange == 1)
+ ce = col(ce, ic, rp, rw, rc, NiL, 0, 0);
+ pp = (unsigned char*)cb[inrange];
+ rp = env->cursor + 1;
+ if ((rw = regcollate((char*)env->cursor, (char**)&env->cursor, (char*)pp, COLL_KEY_MAX, &wc)) < 0)
+ goto ecollate;
+ c = 0;
+ if (ic)
+ {
+ if (iswupper(wc))
+ {
+ wc = towlower(wc);
+ rw = mbconv((char*)pp, wc);
+ c = 'u';
+ }
+ else if (iswlower(wc))
+ c = 'l';
+ }
+ i = 1;
+ for (;;)
+ {
+ mbxfrm(key.key, (char*)pp, COLL_KEY_MAX);
+ if (!(cc = (Cchr_t*)dtsearch(dt, &key)) && !(cc = (Cchr_t*)dtprev(dt, &key)))
+ {
+ if (i)
+ {
+ c = *pp;
+ goto singleton;
+ }
+ goto ecollate;
+ }
+ xc = (tc = (Cchr_t*)dtprev(dt, cc)) && !strcasecmp((char*)tc->nam, (char*)cc->nam) ? tc : cc;
+ if (c == 'l' || c == 'L' && !(c = 0))
+ ce->typ = COLL_range_lc;
+ else if (c == 'u' || c == 'U' && !(c = 0))
+ ce->typ = COLL_range_uc;
+ else
+ ce->typ = COLL_range;
+ strcpy((char*)ce->beg, (char*)xc->key);
+ if (!(cc = (Cchr_t*)dtnext(dt, cc)))
+ {
+ if (i)
+ {
+ c = *pp;
+ goto singleton;
+ }
+ goto ecollate;
+ }
+ if (!strcasecmp((char*)xc->nam, (char*)cc->nam) && (tc = (Cchr_t*)dtnext(dt, cc)))
+ cc = tc;
+ strcpy((char*)ce->end, (char*)cc->key);
+ ce->max = -1;
+ ce++;
+ if (!c)
+ break;
+ if (c == 'u')
+ {
+ wc = towlower(wc);
+ c = 'L';
+ }
+ else
+ {
+ wc = towupper(wc);
+ c = 'U';
+ }
+ rw = mbconv((char*)pp, wc);
+ i = 0;
+ }
+ inrange = 0;
+ c = *pp;
+ continue;
+ case '.':
+ if (env->regexp)
+ goto complicated_normal;
+ pp = (unsigned char*)cb[inrange];
+ if ((w = regcollate((char*)env->cursor, (char**)&env->cursor, (char*)pp, COLL_KEY_MAX, NiL)) < 0)
+ goto ecollate;
+ c = *pp;
+ break;
+ default:
+ complicated_normal:
+ if (*env->cursor == env->terminator || *env->cursor == env->delimiter && (env->flags & REG_ESCAPE))
+ goto error;
+ break;
+ }
+ }
+ singleton:
+ if (inrange == 2)
+ {
+ ce = col(ce, ic, rp, rw, rc, pp, w, c);
+ if (strcmp((char*)ce->beg, (char*)ce->end) > 0)
+ {
+ if (env->type < SRE && !(env->flags & REG_LENIENT))
+ goto erange;
+ (ce-1)->typ = COLL_char;
+ strcpy((char*)ce->beg, (char*)(ce-1)->end);
+ ce->typ = COLL_char;
+ ce++;
+ }
+ inrange = env->type >= SRE || (env->flags & REG_LENIENT);
+ }
+ else if (inrange == 1)
+ ce = col(ce, ic, rp, rw, rc, NiL, 0, 0);
+ else
+ inrange = 1;
+ rp = pp;
+ rw = w;
+ rc = c;
+ }
+ ce->typ = COLL_end;
+ return e;
+ }
+ }
+#endif
+ if (collate)
+ goto ecollate;
+ if (env->flags & REG_ICASE)
+ for (i = 0; i <= UCHAR_MAX; i++)
+ if (settst(e->re.charclass, i))
+ {
+ if (isupper(i))
+ c = tolower(i);
+ else if (islower(i))
+ c = toupper(i);
+ else
+ continue;
+ setadd(e->re.charclass, c);
+ }
+ if (neg)
+ {
+ for (i = 0; i < elementsof(e->re.charclass->bits); i++)
+ e->re.charclass->bits[i] ^= ~0;
+ if (env->explicit >= 0)
+ setclr(e->re.charclass, env->explicit);
+ }
+ return e;
+ ecollate:
+ env->error = REG_ECOLLATE;
+ goto error;
+ erange:
+ env->error = REG_ERANGE;
+ error:
+ drop(env->disc, e);
+ if (!env->error)
+ env->error = REG_EBRACK;
+ return 0;
+}
+
+static Rex_t*
+ccl(Cenv_t* env, int type)
+{
+ int i;
+ Rex_t* e;
+ Celt_t* ce;
+ regclass_t f;
+
+ if (!(f = classfun(type)))
+ {
+ env->error = REG_BADESC;
+ return 0;
+ }
+ if (!mbcoll())
+ {
+ if (!(e = node(env, REX_CLASS, 1, 1, sizeof(Set_t))))
+ return 0;
+ for (i = 0; i <= UCHAR_MAX; i++)
+ if ((*f)(i))
+ setadd(e->re.charclass, i);
+ if (env->explicit >= 0)
+ setclr(e->re.charclass, env->explicit);
+ }
+ else
+ {
+ if (!(e = node(env, REX_COLL_CLASS, 1, 1, 2 * sizeof(Celt_t))))
+ return 0;
+ ce = (Celt_t*)e->re.data;
+ e->re.collate.invert = 0;
+ e->re.collate.elements = ce;
+ ce->fun = f;
+ ce->typ = COLL_call;
+ ce++;
+ ce->typ = COLL_end;
+ }
+ return e;
+}
+
+static Rex_t*
+rep(Cenv_t* env, Rex_t* e, int number, int last)
+{
+ Rex_t* f;
+ unsigned long m = 0;
+ unsigned long n = RE_DUP_INF;
+ int minimal = -1;
+
+ if (!e)
+ return 0;
+ switch (token(env))
+ {
+ case T_BANG:
+ eat(env);
+ if (!(f = node(env, REX_NEG, m, n, 0)))
+ {
+ drop(env->disc, e);
+ return 0;
+ }
+ f->re.group.expr.rex = e;
+ return f;
+ case T_QUES:
+ eat(env);
+ n = 1;
+ break;
+ case T_STAR:
+ eat(env);
+ break;
+ case T_PLUS:
+ eat(env);
+ m = 1;
+ break;
+ case T_LEFT:
+ eat(env);
+ m = env->token.min;
+ n = env->token.max;
+ break;
+ default:
+ return e;
+ }
+ if (env->token.att)
+ minimal = 1;
+ else if (env->type < SRE)
+ switch (token(env))
+ {
+ case T_QUES:
+ eat(env);
+ minimal = !(env->flags & REG_MINIMAL);
+ break;
+ case T_STAR: /*AST*/
+ eat(env);
+ minimal = !!(env->flags & REG_MINIMAL);
+ break;
+ }
+ switch (e->type)
+ {
+ case REX_DOT:
+ case REX_CLASS:
+ case REX_COLL_CLASS:
+ case REX_ONECHAR:
+ e->lo = m;
+ e->hi = n;
+ if (minimal >= 0)
+ mark(e, minimal);
+ return e;
+#if HUH_2002_08_07
+ case REX_BEG:
+#endif
+ case REX_BEG_STR:
+ case REX_END_STR:
+ case REX_FIN_STR:
+ case REX_WBEG:
+ case REX_WEND:
+ case REX_WORD:
+ case REX_WORD_NOT:
+ env->error = REG_BADRPT;
+ drop(env->disc, e);
+ return 0;
+ }
+ if (m == 1 && n == 1)
+ {
+ if (minimal >= 0)
+ mark(e, minimal);
+ return e;
+ }
+ if (!(f = node(env, REX_REP, m, n, 0)))
+ {
+ drop(env->disc, e);
+ return 0;
+ }
+ f->re.group.expr.rex = e;
+ f->re.group.number = number;
+ f->re.group.last = last;
+ if (minimal >= 0)
+ mark(f, minimal);
+ if (m <= n && n)
+ {
+ for (; e && e->type >= REX_GROUP && e->type <= REX_GROUP_CUT; e = e->re.group.expr.rex);
+ if (e && e->type == REX_NEG)
+ f->type = REX_GROUP;
+ }
+ return f;
+}
+
+static int
+isstring(Rex_t* e)
+{
+ switch (e->type)
+ {
+ case REX_ONECHAR:
+ return e->lo == 1 && e->hi == 1;
+ case REX_STRING:
+ return 1;
+ }
+ return 0;
+}
+
+static Trie_node_t*
+trienode(Cenv_t* env, int c)
+{
+ Trie_node_t* t;
+
+ if (t = (Trie_node_t*)alloc(env->disc, 0, sizeof(Trie_node_t)))
+ {
+ memset(t, 0, sizeof(Trie_node_t));
+ t->c = c;
+ }
+ return t;
+}
+
+static int
+insert(Cenv_t* env, Rex_t* f, Rex_t* g)
+{
+ unsigned char* s;
+ unsigned char* e;
+ Trie_node_t* t;
+ int len;
+ unsigned char tmp[2];
+
+ switch (f->type)
+ {
+ case REX_ONECHAR:
+ *(s = tmp) = f->re.onechar;
+ e = s + 1;
+ break;
+ case REX_STRING:
+ s = f->re.string.base;
+ e = s + f->re.string.size;
+ break;
+ default:
+ return 1;
+ }
+ if (!(t = g->re.trie.root[*s]) && !(t = g->re.trie.root[*s] = trienode(env, *s)))
+ return 1;
+ for (len = 1;;)
+ {
+ if (t->c == *s)
+ {
+ if (++s >= e)
+ break;
+ if (!t->son && !(t->son = trienode(env, *s)))
+ return 1;
+ t = t->son;
+ len++;
+ }
+ else
+ {
+ if (!t->sib && !(t->sib = trienode(env, *s)))
+ return 1;
+ t = t->sib;
+ }
+ }
+ if (g->re.trie.min > len)
+ g->re.trie.min = len;
+ if (g->re.trie.max < len)
+ g->re.trie.max = len;
+ t->end = 1;
+ return 0;
+}
+
+/*
+ * trie() tries to combine nontrivial e and f into a REX_TRIE
+ * unless 0 is returned, e and f are deleted as far as possible
+ * also called by regcomb
+ */
+
+static Rex_t*
+trie(Cenv_t* env, Rex_t* e, Rex_t* f)
+{
+ Rex_t* g;
+
+ if (e->next || f->next || !isstring(e) || e->flags != f->flags)
+ return 0;
+ if (isstring(f))
+ {
+ if (!(g = node(env, REX_TRIE, 0, 0, (UCHAR_MAX + 1) * sizeof(Trie_node_t*))))
+ return 0;
+ g->re.trie.min = INT_MAX;
+ if (insert(env, f, g))
+ goto nospace;
+ drop(env->disc, f);
+ }
+ else if (f->type != REX_TRIE)
+ return 0;
+ else
+ g = f;
+ if (insert(env, e, g))
+ goto nospace;
+ drop(env->disc, e);
+ return g;
+ nospace:
+ if (g != f)
+ drop(env->disc, g);
+ return 0;
+}
+
+static Rex_t* alt(Cenv_t*, int, int);
+
+static int
+chr(register Cenv_t* env, int* escaped)
+{
+ unsigned char* p;
+ int c;
+
+ *escaped = 0;
+ if (!(c = *env->cursor))
+ return -1;
+ env->cursor++;
+ if (c == '\\')
+ {
+ if (env->flags & REG_SHELL_ESCAPED)
+ return c;
+ if (!(c = *(env->cursor + 1)) || c == env->terminator)
+ {
+ if (env->flags & REG_LENIENT)
+ return c ? c : '\\';
+ env->error = REG_EESCAPE;
+ return -1;
+ }
+ p = env->cursor;
+ c = chresc((char*)env->cursor - 1, (char**)&env->cursor);
+ *escaped = env->cursor - p;
+ }
+ return c;
+}
+
+/*
+ * open the perly gates
+ */
+
+static Rex_t*
+grp(Cenv_t* env, int parno)
+{
+ Rex_t* e;
+ Rex_t* f;
+ int c;
+ int i;
+ int n;
+ int x;
+ int esc;
+ int typ;
+ int beg;
+ unsigned char* p;
+
+ beg = env->pattern == env->cursor - env->token.len;
+ if (!(c = env->token.lex) && (c = *env->cursor))
+ env->cursor++;
+ env->token.len = 0;
+ env->parnest++;
+ typ = -1;
+ switch (c)
+ {
+ case '-':
+ case '+':
+ case 'a':
+ case 'g':
+ case 'i':
+ case 'l':
+ case 'm':
+ case 'p':
+ case 'r':
+ case 's':
+ case 'x':
+ case 'A':
+ case 'B':
+ case 'E':
+ case 'F':
+ case 'G':
+ case 'I':
+ case 'K':
+ case 'L':
+ case 'M': /* glob(3) */
+ case 'N': /* glob(3) */
+ case 'O': /* glob(3) */
+ case 'P':
+ case 'R': /* pcre */
+ case 'S':
+ case 'U': /* pcre */
+ case 'X': /* pcre */
+ x = REX_GROUP;
+ i = 1;
+ env->token.push = 1;
+ for (;;)
+ {
+ switch (c)
+ {
+ case ')':
+ if (!(env->flags & REG_LITERAL))
+ {
+ env->error = REG_BADRPT;
+ return 0;
+ }
+ /*FALLTHROUGH*/
+ case 0:
+ case T_CLOSE:
+ x = 0;
+ goto done;
+ case ':':
+ eat(env);
+ if (token(env) == T_CLOSE)
+ x = 0;
+ goto done;
+ case '-':
+ i = 0;
+ break;
+ case '+':
+ i = 1;
+ break;
+ case 'a':
+ if (i)
+ env->flags |= (REG_LEFT|REG_RIGHT);
+ else
+ env->flags &= ~(REG_LEFT|REG_RIGHT);
+ break;
+ case 'g':
+ if (i)
+ env->flags &= ~REG_MINIMAL;
+ else
+ env->flags |= REG_MINIMAL;
+ break;
+ case 'i':
+ if (i)
+ env->flags |= REG_ICASE;
+ else
+ env->flags &= ~REG_ICASE;
+ break;
+ case 'l':
+ if (i)
+ env->flags |= REG_LEFT;
+ else
+ env->flags &= ~REG_LEFT;
+ break;
+ case 'm':
+ if (i)
+ env->flags |= REG_NEWLINE;
+ else
+ env->flags &= ~REG_NEWLINE;
+ env->explicit = (env->flags & (REG_NEWLINE|REG_SPAN)) == REG_NEWLINE ? env->mappednewline : -1;
+ break;
+ case 'p':
+ if (i)
+ env->flags &= ~REG_LENIENT;
+ else
+ env->flags |= REG_LENIENT;
+ break;
+ case 'r':
+ if (i)
+ env->flags |= REG_RIGHT;
+ else
+ env->flags &= ~REG_RIGHT;
+ break;
+ case 's':
+ if (i)
+ env->flags |= REG_SPAN;
+ else
+ env->flags &= ~REG_SPAN;
+ env->explicit = (env->flags & (REG_NEWLINE|REG_SPAN)) == REG_NEWLINE ? env->mappednewline : -1;
+ break;
+ case 'x':
+ if (i)
+ env->flags |= REG_COMMENT;
+ else
+ env->flags &= ~REG_COMMENT;
+ break;
+ case 'X':
+ if (typ >= 0 || env->type == ERE && (env->flags & REG_CLASS_ESCAPE))
+ break; /* PCRE_EXTRA */
+ /*FALLTHROUGH*/
+ case 'A':
+ env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
+ env->flags |= REG_AUGMENTED|REG_EXTENDED;
+ typ = ARE;
+ break;
+ case 'B':
+ case 'G':
+ env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
+ typ = BRE;
+ break;
+ case 'E':
+ env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
+ env->flags |= REG_EXTENDED;
+ typ = ERE;
+ break;
+ case 'F':
+ case 'L':
+ env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
+ env->flags |= REG_LITERAL;
+ typ = ERE;
+ break;
+ case 'K':
+ env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
+ env->flags |= REG_AUGMENTED|REG_SHELL|REG_LEFT|REG_RIGHT;
+ typ = KRE;
+ break;
+ case 'M':
+ /* used by caller to disable glob(3) GLOB_BRACE */
+ break;
+ case 'N':
+ /* used by caller to disable glob(3) GLOB_NOCHECK */
+ break;
+ case 'O':
+ /* used by caller to disable glob(3) GLOB_STARSTAR */
+ break;
+ case 'P':
+ env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
+ env->flags |= REG_EXTENDED|REG_CLASS_ESCAPE;
+ typ = ERE;
+ break;
+ case 'S':
+ env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
+ env->flags |= REG_SHELL|REG_LEFT|REG_RIGHT;
+ typ = SRE;
+ break;
+ case 'U': /* PCRE_UNGREEDY */
+ if (typ >= 0 || env->type == ERE && (env->flags & REG_CLASS_ESCAPE))
+ {
+ if (i)
+ env->flags |= REG_MINIMAL;
+ else
+ env->flags &= ~REG_MINIMAL;
+ }
+ break;
+ default:
+ env->error = REG_BADRPT;
+ return 0;
+ }
+ eat(env);
+ c = token(env);
+ }
+ done:
+ break;
+ case ':':
+ x = REX_GROUP;
+ break;
+ case '=':
+ x = REX_GROUP_AHEAD;
+ break;
+ case '!':
+ x = REX_GROUP_AHEAD_NOT;
+ break;
+ case '<':
+ switch (token(env))
+ {
+ case '=':
+ x = REX_GROUP_BEHIND;
+ break;
+ case '!':
+ case T_BANG:
+ x = REX_GROUP_BEHIND_NOT;
+ break;
+ default:
+ env->error = REG_BADRPT;
+ return 0;
+ }
+ eat(env);
+ break;
+ case '>':
+ x = REX_GROUP_CUT;
+ break;
+ case '%':
+ case T_PERCENT:
+ e = node(env, REX_NEST, 0, 0, (UCHAR_MAX + 1) * sizeof(unsigned short));
+ e->re.nest.primary = isalnum(*env->cursor) ? -1 : *env->cursor;
+ n = 1;
+ for (;;)
+ {
+ switch (i = chr(env, &esc))
+ {
+ case -1:
+ case 0:
+ invalid:
+ env->cursor -= esc + 1;
+ env->error = REG_EPAREN;
+ return 0;
+ case 'D':
+ x = REX_NEST_delimiter;
+ /*FALLTHROUGH*/
+ delimiter:
+ if ((i = chr(env, &esc)) < 0)
+ goto invalid;
+ if (e->re.nest.type[i] & ~x)
+ goto invalid;
+ e->re.nest.type[i] = x;
+ continue;
+ case 'E':
+ x = REX_NEST_escape;
+ goto delimiter;
+ case 'L':
+ x = REX_NEST_literal;
+ goto quote;
+ case 'O':
+ switch (i = chr(env, &esc))
+ {
+ case 'T':
+ e->re.nest.type[UCHAR_MAX+1] |= REX_NEST_terminator;
+ break;
+ default:
+ goto invalid;
+ }
+ continue;
+ case 'Q':
+ x = REX_NEST_quote;
+ /*FALLTHROUGH*/
+ quote:
+ if ((i = chr(env, &esc)) < 0)
+ goto invalid;
+ if (e->re.nest.type[i] & ~x)
+ goto invalid;
+ e->re.nest.type[i] = x|REX_NEST_open|REX_NEST_close|(i<<REX_NEST_SHIFT);
+ continue;
+ case 'S':
+ x = REX_NEST_separator;
+ goto delimiter;
+ case 'T':
+ x = REX_NEST_terminator;
+ goto delimiter;
+ case '|':
+ case '&':
+ if (!esc)
+ goto invalid;
+ goto nesting;
+ case '(':
+ if (!esc)
+ n++;
+ goto nesting;
+ case ')':
+ if (!esc && !--n)
+ break;
+ goto nesting;
+ default:
+ nesting:
+ if (isalnum(i) || (e->re.nest.type[i] & (REX_NEST_close|REX_NEST_escape|REX_NEST_literal|REX_NEST_quote|REX_NEST_delimiter|REX_NEST_separator|REX_NEST_terminator)))
+ goto invalid;
+ e->re.nest.type[i] = REX_NEST_open;
+ if ((x = chr(env, &esc)) < 0 || (e->re.nest.type[x] & (REX_NEST_close|REX_NEST_escape|REX_NEST_delimiter|REX_NEST_separator|REX_NEST_terminator)))
+ goto invalid;
+ if (!esc)
+ {
+ if (x == ')' && !--n)
+ goto invalid;
+ else if (x == '(')
+ n++;
+ }
+ e->re.nest.type[x] |= REX_NEST_close;
+ e->re.nest.type[i] |= x << REX_NEST_SHIFT;
+ continue;
+ }
+ break;
+ }
+ env->parnest--;
+ if (c == T_PERCENT)
+ for (n = 0; n < 2; n++)
+ {
+ parno = ++env->parno;
+ if (!(f = node(env, REX_GROUP, 0, 0, 0)))
+ {
+ drop(env->disc, e);
+ return 0;
+ }
+ if (parno < elementsof(env->paren))
+ env->paren[parno] = f;
+ f->re.group.back = 0;
+ f->re.group.number = parno;
+ f->re.group.expr.rex = e;
+ e = f;
+ }
+ return e;
+ case '(':
+ c = 0;
+ if (isdigit(*env->cursor))
+ {
+ f = 0;
+ do
+ {
+ if (c > (INT_MAX / 10))
+ {
+ env->error = REG_BADRPT;
+ return 0;
+ }
+ c = c * 10 + (*env->cursor++ - '0');
+ } while (isdigit(*env->cursor));
+ if (*env->cursor++ != ')')
+ {
+ env->error = REG_BADRPT;
+ return 0;
+ }
+ if (c && env->type >= SRE)
+ c = c * 2 - 1;
+ if (!c || c > env->parno || !env->paren[c])
+ {
+ if (!(env->flags & REG_LENIENT))
+ {
+ env->error = REG_ESUBREG;
+ return 0;
+ }
+ if (c)
+ c = -1;
+ }
+ }
+ else
+ {
+ if (env->type < SRE && *env->cursor++ != '?')
+ {
+ env->error = REG_BADRPT;
+ return 0;
+ }
+ if (!(f = grp(env, parno + 1)) && env->error)
+ return 0;
+ }
+ if (!(e = node(env, REX_GROUP_COND, 0, 0, 0)))
+ {
+ drop(env->disc, f);
+ return 0;
+ }
+ e->re.group.size = c;
+ e->re.group.expr.binary.left = f;
+ if (!(e->re.group.expr.binary.right = alt(env, parno, 1)))
+ {
+ drop(env->disc, e);
+ return 0;
+ }
+ if (token(env) != T_CLOSE)
+ {
+ env->error = REG_EPAREN;
+ return 0;
+ }
+ eat(env);
+ env->parnest--;
+ return rep(env, e, parno, parno);
+ case '{':
+ p = env->cursor;
+ n = 1;
+ while (c = *env->cursor)
+ {
+ if (c == '\\' && *(env->cursor + 1))
+ env->cursor++;
+ else if (c == '{')
+ n++;
+ else if (c == '}' && !--n)
+ break;
+ else if (c == env->delimiter || c == env->terminator)
+ break;
+ env->cursor++;
+ }
+ if (c != '}')
+ {
+ env->error = REG_EBRACE;
+ return 0;
+ }
+ if (*++env->cursor != ')')
+ {
+ env->error = REG_EPAREN;
+ return 0;
+ }
+ env->cursor++;
+ env->parnest--;
+ if (env->disc->re_version < REG_VERSION_EXEC)
+ {
+ env->error = REG_BADRPT;
+ return 0;
+ }
+ if (!env->disc->re_execf)
+ return 0;
+ if (!(e = node(env, REX_EXEC, 0, 0, 0)))
+ return 0;
+ e->re.exec.text = (const char*)p;
+ e->re.exec.size = env->cursor - p - 2;
+ if (!env->disc->re_compf)
+ e->re.exec.data = 0;
+ else
+ e->re.exec.data = (*env->disc->re_compf)(env->regex, e->re.exec.text, e->re.exec.size, env->disc);
+ return e;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ c -= '0';
+ while (isdigit(*env->cursor))
+ {
+ if (c > (INT_MAX / 10))
+ {
+ env->error = REG_ESUBREG;
+ return 0;
+ }
+ c = c * 10 + *env->cursor++ - '0';
+ }
+ if (*env->cursor == ')')
+ {
+ env->cursor++;
+ env->parnest--;
+ env->token.len = 1;
+ if (c > env->parno || !env->paren[c])
+ {
+ env->error = REG_ESUBREG;
+ return 0;
+ }
+ env->paren[c]->re.group.back = 1;
+ return rep(env, node(env, REX_BACK, c, 0, 0), 0, 0);
+ }
+ /*FALLTHROUGH*/
+ default:
+ env->error = REG_BADRPT;
+ return 0;
+ }
+ if (x && !(e = alt(env, parno, 0)))
+ return 0;
+ c = token(env);
+ env->parnest--;
+ if (c != T_CLOSE && (!(env->flags & REG_LITERAL) || c != ')'))
+ {
+ env->error = REG_EPAREN;
+ return 0;
+ }
+ eat(env);
+ if (typ >= 0)
+ {
+ if (beg)
+ env->pattern = env->cursor;
+ env->type = typ;
+ }
+ if (!x)
+ return 0;
+ if (!(f = node(env, x, 0, 0, 0)))
+ {
+ drop(env->disc, e);
+ return 0;
+ }
+ f->re.group.expr.rex = e;
+ if (x == REX_GROUP_BEHIND || x == REX_GROUP_BEHIND_NOT)
+ {
+ if (stats(env, e))
+ {
+ drop(env->disc, f);
+ if (!env->error)
+ env->error = REG_ECOUNT;
+ return 0;
+ }
+ f->re.group.size = env->stats.m;
+ memset(&env->stats, 0, sizeof(env->stats));
+ }
+ switch (x)
+ {
+ case REX_GROUP:
+ case REX_GROUP_CUT:
+ f = rep(env, f, parno, env->parno);
+ break;
+ }
+ return f;
+}
+
+static Rex_t*
+seq(Cenv_t* env)
+{
+ Rex_t* e;
+ Rex_t* f;
+ Token_t tok;
+ int c;
+ int i;
+ int n;
+ int x;
+ int parno;
+ int type;
+ regflags_t flags;
+ unsigned char* s;
+ unsigned char* p;
+ unsigned char* t;
+ unsigned char* u;
+ unsigned char buf[256];
+
+ for (;;)
+ {
+ s = buf;
+ while ((c = token(env)) < T_META && s < &buf[sizeof(buf) - env->token.len])
+ {
+ x = c;
+ p = env->cursor;
+ if (c >= 0)
+ {
+ n = 1;
+ *s++ = (env->flags & REG_ICASE) ? toupper(c) : c;
+ }
+ else if (c == C_ESC || (env->flags & REG_ICASE))
+ {
+ c = (c == C_ESC) ? env->token.lex : mbchar(p);
+ if (env->flags & REG_ICASE)
+ c = towupper(c);
+ if ((&buf[sizeof(buf)] - s) < MB_CUR_MAX)
+ break;
+ if ((n = mbconv((char*)s, c)) < 0)
+ *s++ = c;
+ else if (n)
+ s += n;
+ else
+ {
+ n = 1;
+ *s++ = 0;
+ }
+ }
+ else
+ {
+ n = env->token.len - env->token.esc;
+ for (t = p, u = s + n; s < u; *s++ = *t++);
+ }
+ eat(env);
+ }
+ if (c == T_BAD)
+ return 0;
+ if (s > buf)
+ switch (c)
+ {
+ case T_STAR:
+ case T_PLUS:
+ case T_LEFT:
+ case T_QUES:
+ case T_BANG:
+ if ((s -= n) == buf)
+ e = 0;
+ else
+ {
+ i = s - buf;
+ if (!(e = node(env, REX_STRING, 0, 0, i)))
+ return 0;
+ memcpy((char*)(e->re.string.base = (unsigned char*)e->re.data), (char*)buf, i);
+ e->re.string.size = i;
+ }
+ if (x >= 0)
+ {
+ if (!(f = node(env, REX_ONECHAR, 1, 1, 0)))
+ {
+ drop(env->disc, e);
+ return 0;
+ }
+ f->re.onechar = (env->flags & REG_ICASE) ? toupper(x) : x;
+ }
+ else
+ {
+ if (!(f = node(env, REX_STRING, 0, 0, n)))
+ return 0;
+ memcpy((char*)(f->re.string.base = (unsigned char*)f->re.data), (char*)p, n);
+ f->re.string.size = n;
+ }
+ if (!(f = rep(env, f, 0, 0)) || !(f = cat(env, f, seq(env))))
+ {
+ drop(env->disc, e);
+ return 0;
+ }
+ if (e)
+ f = cat(env, e, f);
+ return f;
+ default:
+ c = s - buf;
+ if (!(e = node(env, REX_STRING, 0, 0, c)))
+ return 0;
+ memcpy((char*)(e->re.string.base = (unsigned char*)e->re.data), (char*)buf, c);
+ e->re.string.size = c;
+ return cat(env, e, seq(env));
+ }
+ else if (c > T_BACK)
+ {
+ eat(env);
+ c -= T_BACK;
+ if (c > env->parno || !env->paren[c])
+ {
+ env->error = REG_ESUBREG;
+ return 0;
+ }
+ env->paren[c]->re.group.back = 1;
+ e = rep(env, node(env, REX_BACK, c, 0, 0), 0, 0);
+ }
+ else
+ switch (c)
+ {
+ case T_AND:
+ case T_CLOSE:
+ case T_BAR:
+ case T_END:
+ return node(env, REX_NULL, 0, 0, 0);
+ case T_DOLL:
+ eat(env);
+ e = rep(env, node(env, REX_END, 0, 0, 0), 0, 0);
+ break;
+ case T_CFLX:
+ eat(env);
+ if ((e = node(env, REX_BEG, 0, 0, 0)) && (env->flags & REG_EXTENDED))
+ e = rep(env, e, 0, 0);
+ break;
+ case T_OPEN:
+ tok = env->token;
+ eat(env);
+ flags = env->flags;
+ type = env->type;
+ if (env->token.att)
+ env->flags |= REG_MINIMAL;
+ env->parnest++;
+ if (env->type == KRE)
+ ++env->parno;
+ parno = ++env->parno;
+ if (!(e = alt(env, parno + 1, 0)))
+ break;
+ if (e->type == REX_NULL && env->type == ERE && !(env->flags & REG_NULL))
+ {
+ drop(env->disc, e);
+ env->error = (*env->cursor == 0 || *env->cursor == env->delimiter || *env->cursor == env->terminator) ? REG_EPAREN : REG_ENULL;
+ return 0;
+ }
+ if (token(env) != T_CLOSE)
+ {
+ drop(env->disc, e);
+ env->error = REG_EPAREN;
+ return 0;
+ }
+ env->parnest--;
+ eat(env);
+ if (!(f = node(env, REX_GROUP, 0, 0, 0)))
+ {
+ drop(env->disc, e);
+ return 0;
+ }
+ if (parno < elementsof(env->paren))
+ env->paren[parno] = f;
+ f->re.group.back = 0;
+ f->re.group.number = parno;
+ f->re.group.expr.rex = e;
+ if (tok.lex)
+ {
+ tok.push = 1;
+ env->token = tok;
+ }
+ if (!(e = rep(env, f, parno, env->parno)))
+ return 0;
+ if (env->type == KRE)
+ {
+ if (!(f = node(env, REX_GROUP, 0, 0, 0)))
+ {
+ drop(env->disc, e);
+ return 0;
+ }
+ if (--parno < elementsof(env->paren))
+ env->paren[parno] = f;
+ f->re.group.back = 0;
+ f->re.group.number = parno;
+ f->re.group.expr.rex = e;
+ e = f;
+ }
+ env->flags = flags;
+ env->type = type;
+ break;
+ case T_GROUP:
+ p = env->cursor;
+ eat(env);
+ flags = env->flags;
+ type = env->type;
+ if (!(e = grp(env, env->parno + 1)))
+ {
+ if (env->error)
+ return 0;
+ if (env->literal == env->pattern && env->literal == p)
+ env->literal = env->cursor;
+ continue;
+ }
+ env->flags = flags;
+ env->type = type;
+ break;
+ case T_BRA:
+ eat(env);
+ if (e = bra(env))
+ e = rep(env, e, 0, 0);
+ break;
+ case T_ALNUM:
+ case T_ALNUM_NOT:
+ case T_DIGIT:
+ case T_DIGIT_NOT:
+ case T_SPACE:
+ case T_SPACE_NOT:
+ eat(env);
+ if (e = ccl(env, c))
+ e = rep(env, e, 0, 0);
+ break;
+ case T_LT:
+ eat(env);
+ e = rep(env, node(env, REX_WBEG, 0, 0, 0), 0, 0);
+ break;
+ case T_GT:
+ eat(env);
+ e = rep(env, node(env, REX_WEND, 0, 0, 0), 0, 0);
+ break;
+ case T_DOT:
+ eat(env);
+ e = rep(env, node(env, REX_DOT, 1, 1, 0), 0, 0);
+ break;
+ case T_DOTSTAR:
+ eat(env);
+ env->token.lex = T_STAR;
+ env->token.push = 1;
+ e = rep(env, node(env, REX_DOT, 1, 1, 0), 0, 0);
+ break;
+ case T_SLASHPLUS:
+ eat(env);
+ env->token.lex = T_PLUS;
+ env->token.push = 1;
+ if (e = node(env, REX_ONECHAR, 1, 1, 0))
+ {
+ e->re.onechar = '/';
+ e = rep(env, e, 0, 0);
+ }
+ break;
+ case T_WORD:
+ eat(env);
+ e = rep(env, node(env, REX_WORD, 0, 0, 0), 0, 0);
+ break;
+ case T_WORD_NOT:
+ eat(env);
+ e = rep(env, node(env, REX_WORD_NOT, 0, 0, 0), 0, 0);
+ break;
+ case T_BEG_STR:
+ eat(env);
+ e = rep(env, node(env, REX_BEG_STR, 0, 0, 0), 0, 0);
+ break;
+ case T_END_STR:
+ eat(env);
+ e = rep(env, node(env, REX_END_STR, 0, 0, 0), 0, 0);
+ break;
+ case T_FIN_STR:
+ eat(env);
+ e = rep(env, node(env, REX_FIN_STR, 0, 0, 0), 0, 0);
+ break;
+ default:
+ env->error = REG_BADRPT;
+ return 0;
+ }
+ if (e && *env->cursor != 0 && *env->cursor != env->delimiter && *env->cursor != env->terminator)
+ e = cat(env, e, seq(env));
+ return e;
+ }
+}
+
+static Rex_t*
+con(Cenv_t* env)
+{
+ Rex_t* e;
+ Rex_t* f;
+ Rex_t* g;
+
+ if (!(e = seq(env)) || !(env->flags & REG_AUGMENTED) || token(env) != T_AND)
+ return e;
+ eat(env);
+ if (!(f = con(env)))
+ {
+ drop(env->disc, e);
+ return 0;
+ }
+ if (!(g = node(env, REX_CONJ, 0, 0, 0)))
+ {
+ drop(env->disc, e);
+ drop(env->disc, f);
+ return 0;
+ }
+ g->re.group.expr.binary.left = e;
+ g->re.group.expr.binary.right = f;
+ return g;
+}
+
+static Rex_t*
+alt(Cenv_t* env, int number, int cond)
+{
+ Rex_t* e;
+ Rex_t* f;
+ Rex_t* g;
+
+ if (!(e = con(env)))
+ return 0;
+ else if (token(env) != T_BAR)
+ {
+ if (!cond)
+ return e;
+ f = 0;
+ if (e->type == REX_NULL)
+ goto bad;
+ }
+ else
+ {
+ eat(env);
+ if (!(f = alt(env, number, 0)))
+ {
+ drop(env->disc, e);
+ return 0;
+ }
+ if ((e->type == REX_NULL || f->type == REX_NULL) && !(env->flags & REG_NULL))
+ goto bad;
+ if (!cond && (g = trie(env, e, f)))
+ return g;
+ }
+ if (!(g = node(env, REX_ALT, 0, 0, 0)))
+ {
+ env->error = REG_ESPACE;
+ goto bad;
+ }
+ g->re.group.number = number;
+ g->re.group.last = env->parno;
+ g->re.group.expr.binary.left = e;
+ g->re.group.expr.binary.right = f;
+ return g;
+ bad:
+ drop(env->disc, e);
+ drop(env->disc, f);
+ if (!env->error)
+ env->error = REG_ENULL;
+ return 0;
+}
+
+/*
+ * add v to REX_BM tables
+ */
+
+static void
+bmstr(Cenv_t* env, register Rex_t* a, unsigned char* v, int n, Bm_mask_t b)
+{
+ int c;
+ int m;
+ size_t z;
+
+ for (m = 0; m < n; m++)
+ {
+ if (!(z = n - m - 1))
+ z = HIT;
+ c = v[m];
+ a->re.bm.mask[m][c] |= b;
+ if (z == HIT || !a->re.bm.skip[c] || a->re.bm.skip[c] > z && a->re.bm.skip[c] < HIT)
+ a->re.bm.skip[c] = z;
+ if (a->flags & REG_ICASE)
+ {
+ if (isupper(c))
+ c = tolower(c);
+ else if (islower(c))
+ c = toupper(c);
+ else
+ continue;
+ a->re.bm.mask[m][c] |= b;
+ if (z == HIT || !a->re.bm.skip[c] || a->re.bm.skip[c] > z && a->re.bm.skip[c] < HIT)
+ a->re.bm.skip[c] = z;
+ }
+ }
+}
+
+/*
+ * set up BM table from trie
+ */
+
+static int
+bmtrie(Cenv_t* env, Rex_t* a, unsigned char* v, Trie_node_t* x, int n, int m, Bm_mask_t b)
+{
+ do
+ {
+ v[m] = x->c;
+ if (m >= (n - 1))
+ {
+ bmstr(env, a, v, n, b);
+ if (!(b <<= 1))
+ {
+ b = 1;
+ a->re.bm.complete = 0;
+ }
+ else if (x->son)
+ a->re.bm.complete = 0;
+ }
+ else if (x->son)
+ b = bmtrie(env, a, v, x->son, n, m + 1, b);
+ } while (x = x->sib);
+ return b;
+}
+
+/*
+ * rewrite the expression tree for some special cases
+ * 1. it is a null expression - illegal
+ * 2. max length fixed string found -- use BM algorithm
+ * 3. it begins with an unanchored string - use KMP algorithm
+ * 0 returned on success
+ */
+
+static int
+special(Cenv_t* env, regex_t* p)
+{
+ Rex_t* a;
+ Rex_t* e;
+ Rex_t* t;
+ Rex_t* x;
+ Rex_t* y;
+ unsigned char* s;
+ int* f;
+ int n;
+ int m;
+ int k;
+
+ DEBUG_INIT();
+ if (e = p->env->rex)
+ {
+ if ((x = env->stats.x) && x->re.string.size < 3)
+ x = 0;
+ if ((t = env->stats.y) && t->re.trie.min < 3)
+ t = 0;
+ if (x && t)
+ {
+ if (x->re.string.size >= t->re.trie.min)
+ t = 0;
+ else
+ x = 0;
+ }
+ if (x || t)
+ {
+ Bm_mask_t** mask;
+ Bm_mask_t* h;
+ unsigned char* v;
+ size_t* q;
+ unsigned long l;
+ int i;
+ int j;
+
+ if (x)
+ {
+ y = x;
+ n = m = x->re.string.size;
+ l = env->stats.l;
+ }
+ else
+ {
+ y = t;
+ n = t->re.trie.min;
+ m = t->re.trie.max;
+ l = env->stats.k;
+ }
+ if (!(q = (size_t*)alloc(env->disc, 0, (n + 1) * sizeof(size_t))))
+ return 1;
+ if (!(a = node(env, REX_BM, 0, 0, n * (sizeof(Bm_mask_t*) + (UCHAR_MAX + 1) * sizeof(Bm_mask_t)) + (UCHAR_MAX + n + 2) * sizeof(size_t))))
+ {
+ alloc(env->disc, q, 0);
+ return 1;
+ }
+ a->flags = y->flags;
+ a->map = y->map;
+ a->re.bm.size = n;
+ a->re.bm.back = (y == e || y == e->re.group.expr.rex) ? (m - n) : -1;
+ a->re.bm.left = l - 1;
+ a->re.bm.right = env->stats.m - l - n;
+ a->re.bm.complete = (env->stats.e || y != e && (e->type != REX_GROUP || y != e->re.group.expr.rex) || e->next || ((a->re.bm.left + a->re.bm.right) >= 0)) ? 0 : n;
+ h = (Bm_mask_t*)&a->re.bm.mask[n];
+ a->re.bm.skip = (size_t*)(h + n * (UCHAR_MAX + 1));
+ a->re.bm.fail = &a->re.bm.skip[UCHAR_MAX + 1];
+ for (m = 0; m <= UCHAR_MAX; m++)
+ a->re.bm.skip[m] = n;
+ a->re.bm.skip[0] = a->re.bm.skip[env->mappednewline] = (y->next && y->next->type == REX_END) ? HIT : (n + a->re.bm.left);
+ for (i = 1; i <= n; i++)
+ a->re.bm.fail[i] = 2 * n - i;
+ mask = a->re.bm.mask;
+ for (m = 0; m < n; m++)
+ {
+ mask[m] = h;
+ h += UCHAR_MAX + 1;
+ }
+ if (x)
+ bmstr(env, a, x->re.string.base, n, 1);
+ else
+ {
+ v = (unsigned char*)q;
+ memset(v, 0, n);
+ m = 1;
+ for (i = 0; i <= UCHAR_MAX; i++)
+ if (t->re.trie.root[i])
+ m = bmtrie(env, a, v, t->re.trie.root[i], n, 0, m);
+ }
+ mask--;
+ memset(q, 0, n * sizeof(*q));
+ for (k = (j = n) + 1; j > 0; j--, k--)
+ {
+ DEBUG_TEST(0x0010,(sfprintf(sfstderr, "BM#0: k=%d j=%d\n", k, j)),(0));
+ for (q[j] = k; k <= n; k = q[k])
+ {
+ for (m = 0; m <= UCHAR_MAX; m++)
+ if (mask[k][m] == mask[j][m])
+ {
+ DEBUG_TEST(0x0010,sfprintf(sfstderr, "CUT1: mask[%d][%c]=mask[%d][%c]\n", k, m, j, m), (0));
+ goto cut;
+ }
+ DEBUG_TEST(0x0010,sfprintf(sfstderr, "BM#2: fail[%d]=%d => %d\n", k, a->re.bm.fail[k], (a->re.bm.fail[k] > n - j) ? (n - j) : a->re.bm.fail[k]), (0));
+ if (a->re.bm.fail[k] > n - j)
+ a->re.bm.fail[k] = n - j;
+ }
+ cut: ;
+ }
+ for (i = 1; i <= n; i++)
+ if (a->re.bm.fail[i] > n + k - i)
+ {
+ DEBUG_TEST(0x0010,sfprintf(sfstderr, "BM#4: fail[%d]=%d => %d\n", i, a->re.bm.fail[i], n + k - i), (0));
+ a->re.bm.fail[i] = n + k - i;
+ }
+#if _AST_REGEX_DEBUG
+ if (DEBUG_TEST(0x0020,(1),(0)))
+ {
+ sfprintf(sfstderr, "STAT: complete=%d n=%d k=%d l=%d r=%d y=%d:%d e=%d:%d\n", a->re.bm.complete, n, k, a->re.bm.left, a->re.bm.right, y->type, y->next ? y->next->type : 0, e->type, e->next ? e->next->type : 0);
+ for (m = 0; m < n; m++)
+ for (i = 1; i <= UCHAR_MAX; i++)
+ if (a->re.bm.mask[m][i])
+ sfprintf(sfstderr, "MASK: [%d]['%c'] = %032..2u\n", m, i, a->re.bm.mask[m][i]);
+ for (i = ' '; i <= UCHAR_MAX; i++)
+ if (a->re.bm.skip[i] >= HIT)
+ sfprintf(sfstderr, "SKIP: ['%c'] = *\n", i);
+ else if (a->re.bm.skip[i] > 0 && a->re.bm.skip[i] < n)
+ sfprintf(sfstderr, "SKIP: ['%c'] = %3d\n", i, a->re.bm.skip[i]);
+ for (j = 31; j >= 0; j--)
+ {
+ sfprintf(sfstderr, " ");
+ next:
+ for (m = 0; m < n; m++)
+ {
+ for (i = 0040; i < 0177; i++)
+ if (a->re.bm.mask[m][i] & (1 << j))
+ {
+ sfprintf(sfstderr, " %c", i);
+ break;
+ }
+ if (i >= 0177)
+ {
+ if (j > 0)
+ {
+ j--;
+ goto next;
+ }
+ sfprintf(sfstderr, " ?");
+ }
+ }
+ sfprintf(sfstderr, "\n");
+ }
+ sfprintf(sfstderr, "FAIL: ");
+ for (m = 1; m <= n; m++)
+ sfprintf(sfstderr, "%3d", a->re.bm.fail[m]);
+ sfprintf(sfstderr, "\n");
+ }
+#endif
+ alloc(env->disc, q, 0);
+ a->next = e;
+ p->env->rex = a;
+ return 0;
+ }
+ switch (e->type)
+ {
+ case REX_BEG:
+ if (env->flags & REG_NEWLINE)
+ return 0;
+ break;
+ case REX_GROUP:
+ if (env->stats.b)
+ return 0;
+ e = e->re.group.expr.rex;
+ if (e->type != REX_DOT)
+ return 0;
+ /*FALLTHROUGH*/
+ case REX_DOT:
+ if (e->lo == 0 && e->hi == RE_DUP_INF)
+ break;
+ return 0;
+ case REX_NULL:
+ if (env->flags & REG_NULL)
+ break;
+ env->error = REG_ENULL;
+ return 1;
+ case REX_STRING:
+ if ((env->flags & (REG_LEFT|REG_LITERAL|REG_RIGHT)) || e->map)
+ return 0;
+ s = e->re.string.base;
+ n = e->re.string.size;
+ if (!(a = node(env, REX_KMP, 0, 0, n * (sizeof(int*) + 1))))
+ return 1;
+ a->flags = e->flags;
+ a->map = e->map;
+ f = a->re.string.fail;
+ memcpy((char*)(a->re.string.base = (unsigned char*)&f[n]), (char*)s, n);
+ s = a->re.string.base;
+ a->re.string.size = n;
+ f[0] = m = -1;
+ for (k = 1; k < n; k++)
+ {
+ while (m >= 0 && s[m+1] != s[k])
+ m = f[m];
+ if (s[m+1] == s[k])
+ m++;
+ f[k] = m;
+ }
+ a->next = e->next;
+ p->env->rex = a;
+ e->next = 0;
+ drop(env->disc, e);
+ break;
+ default:
+ return 0;
+ }
+ }
+ p->env->once = 1;
+ return 0;
+}
+
+int
+regcomp(regex_t* p, const char* pattern, regflags_t flags)
+{
+ Rex_t* e;
+ Rex_t* f;
+ regdisc_t* disc;
+ unsigned char* fold;
+ int i;
+ Cenv_t env;
+
+ if (!p)
+ return REG_BADPAT;
+ if (flags & REG_DISCIPLINE)
+ {
+ flags &= ~REG_DISCIPLINE;
+ disc = p->re_disc;
+ }
+ else
+ disc = &state.disc;
+ if (!disc->re_errorlevel)
+ disc->re_errorlevel = 2;
+ p->env = 0;
+ if (!pattern)
+ return fatal(disc, REG_BADPAT, pattern);
+ if (!state.initialized)
+ {
+ state.initialized = 1;
+ for (i = 0; i < elementsof(state.escape); i++)
+ state.magic[state.escape[i].key] = state.escape[i].val;
+ }
+ if (!(fold = (unsigned char*)LCINFO(AST_LC_CTYPE)->data))
+ {
+ if (!(fold = newof(0, unsigned char, UCHAR_MAX, 1)))
+ return fatal(disc, REG_ESPACE, pattern);
+ for (i = 0; i <= UCHAR_MAX; i++)
+ fold[i] = toupper(i);
+ LCINFO(AST_LC_CTYPE)->data = (void*)fold;
+ }
+ again:
+ if (!(p->env = (Env_t*)alloc(disc, 0, sizeof(Env_t))))
+ return fatal(disc, REG_ESPACE, pattern);
+ memset(p->env, 0, sizeof(*p->env));
+ memset(&env, 0, sizeof(env));
+ env.regex = p;
+ env.flags = flags;
+ env.disc = p->env->disc = disc;
+ if (env.flags & REG_AUGMENTED)
+ env.flags |= REG_EXTENDED;
+ env.mappeddot = '.';
+ env.mappednewline = '\n';
+ env.mappedslash = '/';
+ if (disc->re_version >= REG_VERSION_MAP && disc->re_map)
+ {
+ env.map = disc->re_map;
+ env.MAP = p->env->fold;
+ for (i = 0; i <= UCHAR_MAX; i++)
+ {
+ env.MAP[i] = fold[env.map[i]];
+ if (env.map[i] == '.')
+ env.mappeddot = i;
+ if (env.map[i] == '\n')
+ env.mappednewline = i;
+ if (env.map[i] == '/')
+ env.mappedslash = i;
+ }
+ }
+ else
+ env.MAP = fold;
+ env.type = (env.flags & REG_AUGMENTED) ? ARE : (env.flags & REG_EXTENDED) ? ERE : BRE;
+ env.explicit = -1;
+ if (env.flags & REG_SHELL)
+ {
+ if (env.flags & REG_SHELL_PATH)
+ env.explicit = env.mappedslash;
+ if (!(env.flags & REG_SHELL_ESCAPED))
+ env.flags |= REG_CLASS_ESCAPE;
+ env.flags |= REG_LENIENT|REG_NULL;
+ env.type = env.type == BRE ? SRE : KRE;
+ }
+ else
+ env.flags &= ~(REG_SHELL_DOT|REG_SHELL_ESCAPED|REG_SHELL_GROUP|REG_SHELL_PATH);
+ if ((env.flags & (REG_NEWLINE|REG_SPAN)) == REG_NEWLINE)
+ env.explicit = env.mappednewline;
+ p->env->leading = (env.flags & REG_SHELL_DOT) ? env.mappeddot : -1;
+ env.posixkludge = !(env.flags & (REG_EXTENDED|REG_SHELL));
+ env.regexp = !!(env.flags & REG_REGEXP);
+ env.token.lex = 0;
+ env.token.push = 0;
+ if (env.flags & REG_DELIMITED)
+ {
+ switch (env.delimiter = *pattern++)
+ {
+ case 0:
+ case '\\':
+ case '\n':
+ case '\r':
+ env.error = REG_EDELIM;
+ goto bad;
+ }
+ env.terminator = '\n';
+ }
+ env.literal = env.pattern = env.cursor = (unsigned char*)pattern;
+ if (!(p->env->rex = alt(&env, 1, 0)))
+ goto bad;
+ if (env.parnest)
+ {
+ env.error = REG_EPAREN;
+ goto bad;
+ }
+ if ((env.flags & REG_LEFT) && p->env->rex->type != REX_BEG)
+ {
+ if (p->env->rex->type == REX_ALT)
+ env.flags &= ~REG_FIRST;
+ if (!(e = node(&env, REX_BEG, 0, 0, 0)))
+ {
+ regfree(p);
+ return fatal(disc, REG_ESPACE, pattern);
+ }
+ e->next = p->env->rex;
+ p->env->rex = e;
+ p->env->once = 1;
+ }
+ for (e = p->env->rex; e->next; e = e->next);
+ p->env->done.type = REX_DONE;
+ p->env->done.flags = e->flags;
+ if ((env.flags & REG_RIGHT) && e->type != REX_END)
+ {
+ if (p->env->rex->type == REX_ALT)
+ env.flags &= ~REG_FIRST;
+ if (!(f = node(&env, REX_END, 0, 0, 0)))
+ {
+ regfree(p);
+ return fatal(disc, REG_ESPACE, pattern);
+ }
+ f->flags = e->flags;
+ f->map = e->map;
+ e->next = f;
+ }
+ if (stats(&env, p->env->rex))
+ {
+ if (!env.error)
+ env.error = REG_ECOUNT;
+ goto bad;
+ }
+ if (env.stats.b)
+ p->env->hard = p->env->separate = 1;
+ else if (!(env.flags & REG_FIRST) && (env.stats.a || env.stats.c > 1 && env.stats.c != env.stats.s || env.stats.t && (env.stats.t > 1 || env.stats.a || env.stats.c)))
+ p->env->hard = 1;
+ if (p->env->hard || env.stats.c || env.stats.i)
+ p->env->stats.re_min = p->env->stats.re_max = -1;
+ else
+ {
+ if (!(p->env->stats.re_min = env.stats.m))
+ p->env->stats.re_min = -1;
+ if (!(p->env->stats.re_max = env.stats.n))
+ p->env->stats.re_max = -1;
+ }
+ if (special(&env, p))
+ goto bad;
+ serialize(&env, p->env->rex, 1);
+ p->re_nsub = env.stats.p;
+ if (env.type == KRE)
+ p->re_nsub /= 2;
+ if (env.flags & REG_DELIMITED)
+ {
+ p->re_npat = env.cursor - env.pattern + 1;
+ if (*env.cursor == env.delimiter)
+ p->re_npat++;
+ else if (env.flags & REG_MUSTDELIM)
+ {
+ env.error = REG_EDELIM;
+ goto bad;
+ }
+ else
+ env.flags &= ~REG_DELIMITED;
+ }
+ p->env->explicit = env.explicit;
+ p->env->flags = env.flags & REG_COMP;
+ p->env->min = env.stats.m;
+ p->env->nsub = env.stats.p + env.stats.u;
+ p->env->refs = 1;
+ return 0;
+ bad:
+ regfree(p);
+ if (!env.error)
+ env.error = REG_ESPACE;
+ if (env.type >= SRE && env.error != REG_ESPACE && !(flags & REG_LITERAL))
+ {
+ flags |= REG_LITERAL;
+ pattern = (const char*)env.literal;
+ goto again;
+ }
+ return fatal(disc, env.error, pattern);
+}
+
+/*
+ * regcomp() on sized pattern
+ * the lazy way around adding and checking env.end
+ */
+
+int
+regncomp(regex_t* p, const char* pattern, size_t size, regflags_t flags)
+{
+ char* s;
+ int r;
+
+ if (!(s = malloc(size + 1)))
+ return fatal((flags & REG_DISCIPLINE) ? p->re_disc : &state.disc, REG_ESPACE, pattern);
+ memcpy(s, pattern, size);
+ s[size] = 0;
+ r = regcomp(p, s, flags);
+ free(s);
+ return r;
+}
+
+/*
+ * combine two compiled regular expressions if possible,
+ * replacing first with the combination and freeing second.
+ * return 0 on success.
+ * the only combinations handled are building a Trie
+ * from String|Kmp|Trie and String|Kmp
+ */
+
+int
+regcomb(regex_t* p, regex_t* q)
+{
+ Rex_t* e = p->env->rex;
+ Rex_t* f = q->env->rex;
+ Rex_t* g;
+ Rex_t* h;
+ Cenv_t env;
+
+ if (!e || !f)
+ return fatal(p->env->disc, REG_BADPAT, NiL);
+ if (p->env->separate || q->env->separate)
+ return REG_ESUBREG;
+ memset(&env, 0, sizeof(env));
+ env.disc = p->env->disc;
+ if (e->type == REX_BM)
+ {
+ p->env->rex = e->next;
+ e->next = 0;
+ drop(env.disc, e);
+ e = p->env->rex;
+ }
+ if (f->type == REX_BM)
+ {
+ q->env->rex = f->next;
+ f->next = 0;
+ drop(env.disc, f);
+ f = q->env->rex;
+ }
+ if (e->type == REX_BEG && f->type == REX_BEG)
+ {
+ p->env->flags |= REG_LEFT;
+ p->env->rex = e->next;
+ e->next = 0;
+ drop(env.disc, e);
+ e = p->env->rex;
+ q->env->rex = f->next;
+ f->next = 0;
+ drop(env.disc, f);
+ f = q->env->rex;
+ }
+ for (g = e; g->next; g = g->next);
+ for (h = f; h->next; h = h->next);
+ if (g->next && g->next->type == REX_END && h->next && h->next->type == REX_END)
+ {
+ p->env->flags |= REG_RIGHT;
+ drop(env.disc, g->next);
+ g->next = 0;
+ drop(env.disc, h->next);
+ h->next = 0;
+ }
+ if (!(g = trie(&env, f, e)))
+ return fatal(p->env->disc, REG_BADPAT, NiL);
+ p->env->rex = g;
+ if (!q->env->once)
+ p->env->once = 0;
+ q->env->rex = 0;
+ if (p->env->flags & REG_LEFT)
+ {
+ if (!(e = node(&env, REX_BEG, 0, 0, 0)))
+ {
+ regfree(p);
+ return fatal(p->env->disc, REG_ESPACE, NiL);
+ }
+ e->next = p->env->rex;
+ p->env->rex = e;
+ p->env->once = 1;
+ }
+ if (p->env->flags & REG_RIGHT)
+ {
+ for (f = p->env->rex; f->next; f = f->next);
+ if (f->type != REX_END)
+ {
+ if (!(e = node(&env, REX_END, 0, 0, 0)))
+ {
+ regfree(p);
+ return fatal(p->env->disc, REG_ESPACE, NiL);
+ }
+ f->next = e;
+ }
+ }
+ env.explicit = p->env->explicit;
+ env.flags = p->env->flags;
+ env.disc = p->env->disc;
+ if (stats(&env, p->env->rex))
+ {
+ regfree(p);
+ return fatal(p->env->disc, env.error ? env.error : REG_ECOUNT, NiL);
+ }
+ if (special(&env, p))
+ {
+ regfree(p);
+ return fatal(p->env->disc, env.error ? env.error : REG_ESPACE, NiL);
+ }
+ p->env->min = g->re.trie.min;
+ return 0;
+}
+
+/*
+ * copy a reference of p into q
+ * p and q may then have separate regsubcomp() instantiations
+ */
+
+int
+regdup(regex_t* p, regex_t* q)
+{
+ if (!p || !q)
+ return REG_BADPAT;
+ *q = *p;
+ p->env->refs++;
+ q->re_sub = 0;
+ return 0;
+}
diff --git a/src/lib/libast/regex/regdecomp.c b/src/lib/libast/regex/regdecomp.c
new file mode 100644
index 0000000..a9fe6f3
--- /dev/null
+++ b/src/lib/libast/regex/regdecomp.c
@@ -0,0 +1,448 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * posix regex decompiler
+ */
+
+#include "reglib.h"
+
+#undef ismeta
+#define ismeta(c,t,e,d) (state.magic[c] && state.magic[c][(t)+(e)] >= T_META || (c) == (d))
+#define meta(f,c,t,e,d) do { if (ismeta(c,t,e,d)) sfputc(f, '\\'); sfputc(f, c); } while (0)
+
+static void
+detrie(Trie_node_t* x, Sfio_t* sp, char* b, char* p, char* e, int delimiter)
+{
+ register Trie_node_t* y;
+ char* o;
+ int k;
+
+ o = p;
+ k = 1;
+ do
+ {
+ if (k)
+ {
+ o = p;
+ if (p < e)
+ *p++ = x->c;
+ }
+ sfputc(sp, x->c);
+ for (y = x->sib; y; y = y->sib)
+ {
+ sfputc(sp, '|');
+ sfputc(sp, '<');
+ sfwrite(sp, b, p - b);
+ sfputc(sp, '>');
+ detrie(y, sp, b, p, e, delimiter);
+ }
+ if (x->end && x->son)
+ {
+ sfputc(sp, '|');
+ sfputc(sp, '{');
+ sfwrite(sp, b, p - b);
+ sfputc(sp, '}');
+ p = o;
+ }
+ } while (x = x->son);
+}
+
+static int
+decomp(register Rex_t* e, Sfio_t* sp, int type, int delimiter, regflags_t flags)
+{
+ Rex_t* q;
+ unsigned char* s;
+ unsigned char* t;
+ int c;
+ int m;
+ int cb;
+ int cd;
+ int cr;
+ int ib;
+ int ie;
+ int nb;
+ int ne;
+ unsigned char ic[2*UCHAR_MAX];
+ unsigned char nc[2*UCHAR_MAX];
+
+ do
+ {
+ switch (e->type)
+ {
+ case REX_ALT:
+ if (decomp(e->re.group.expr.binary.left, sp, type, delimiter, flags))
+ return 1;
+ sfputc(sp, '|');
+ if (e->re.group.expr.binary.right && decomp(e->re.group.expr.binary.right, sp, type, delimiter, flags))
+ return 1;
+ break;
+ case REX_BACK:
+ sfprintf(sp, "\\%d", e->lo);
+ break;
+ case REX_BEG:
+ if (type < SRE)
+ sfputc(sp, '^');
+ break;
+ case REX_END:
+ if (type < SRE)
+ sfputc(sp, '$');
+ break;
+ case REX_WBEG:
+ meta(sp, '<', type, 1, delimiter);
+ break;
+ case REX_WEND:
+ meta(sp, '<', type, 1, delimiter);
+ break;
+ case REX_WORD:
+ sfprintf(sp, "\\w");
+ break;
+ case REX_CLASS:
+ case REX_COLL_CLASS:
+ case REX_ONECHAR:
+ case REX_DOT:
+ case REX_REP:
+ if (type >= SRE)
+ {
+ c = ')';
+ if (e->hi == RE_DUP_INF)
+ {
+ if (!e->lo)
+ sfputc(sp, '*');
+ else if (e->lo == 1)
+ sfputc(sp, '+');
+ else
+ sfprintf(sp, "{%d,}", e->lo);
+ }
+ else if (e->hi != 1)
+ sfprintf(sp, "{%d,%d}", e->lo, e->hi);
+ else if (e->lo == 0)
+ sfputc(sp, '?');
+ else
+ c = 0;
+ }
+ switch (e->type)
+ {
+ case REX_REP:
+ if (decomp(e->re.group.expr.rex, sp, type, delimiter, flags))
+ return 1;
+ break;
+ case REX_CLASS:
+ sfputc(sp, '[');
+ nb = ne = ib = ie = -2;
+ cb = cd = cr = 0;
+ s = nc;
+ t = ic;
+ for (m = 0; m <= UCHAR_MAX; m++)
+ if (settst(e->re.charclass, m))
+ {
+ if (m == ']')
+ cb = 1;
+ else if (m == '-')
+ cr = 1;
+ else if (m == delimiter)
+ cd = 1;
+ else if (nb < 0)
+ ne = nb = m;
+ else if (ne == (m - 1))
+ ne = m;
+ else
+ {
+ if (ne == nb)
+ *s++ = ne;
+ else
+ {
+ *s++ = nb;
+ *s++ = '-';
+ *s++ = ne;
+ }
+ ne = nb = m;
+ }
+ }
+ else
+ {
+ if (m == ']')
+ cb = -1;
+ else if (m == '-')
+ cr = -1;
+ else if (m == delimiter)
+ cd = -1;
+ else if (ib < 0)
+ ie = ib = m;
+ else if (ie == (m - 1))
+ ie = m;
+ else
+ {
+ if (ie == ib)
+ *t++ = ie;
+ else
+ {
+ *t++ = ib;
+ *t++ = '-';
+ *t++ = ie;
+ }
+ ie = ib = m;
+ }
+ }
+ if (nb >= 0)
+ {
+ *s++ = nb;
+ if (ne != nb)
+ {
+ *s++ = '-';
+ *s++ = ne;
+ }
+ }
+ if (ib >= 0)
+ {
+ *t++ = ib;
+ if (ie != ib)
+ {
+ *t++ = '-';
+ *t++ = ie;
+ }
+ }
+ if ((t - ic + 1) < (s - nc + (nc[0] == '^')))
+ {
+ sfputc(sp, '^');
+ if (cb < 0)
+ sfputc(sp, ']');
+ if (cr < 0)
+ sfputc(sp, '-');
+ if (cd < 0 && delimiter > 0)
+ {
+ if (flags & REG_ESCAPE)
+ sfputc(sp, '\\');
+ sfputc(sp, delimiter);
+ }
+ sfwrite(sp, ic, t - ic);
+ }
+ else
+ {
+ if (cb > 0)
+ sfputc(sp, ']');
+ if (cr > 0)
+ sfputc(sp, '-');
+ if (cd > 0 && delimiter > 0)
+ {
+ if (flags & REG_ESCAPE)
+ sfputc(sp, '\\');
+ sfputc(sp, delimiter);
+ }
+ if (nc[0] == '^')
+ {
+ sfwrite(sp, nc + 1, s - nc - 1);
+ sfputc(sp, '^');
+ }
+ else
+ sfwrite(sp, nc, s - nc);
+ }
+ sfputc(sp, ']');
+ break;
+ case REX_COLL_CLASS:
+ break;
+ case REX_ONECHAR:
+ meta(sp, e->re.onechar, type, 0, delimiter);
+ break;
+ case REX_DOT:
+ sfputc(sp, '.');
+ break;
+ }
+ if (type < SRE)
+ {
+ if (e->hi == RE_DUP_INF)
+ {
+ if (!e->lo)
+ sfputc(sp, '*');
+ else if (e->lo == 1 && ismeta('+', type, 0, delimiter))
+ meta(sp, '+', type, 1, delimiter);
+ else
+ {
+ meta(sp, '{', type, 1, delimiter);
+ sfprintf(sp, "%d,", e->lo);
+ meta(sp, '}', type, 1, delimiter);
+ }
+ }
+ else if (e->hi != 1 || e->lo == 0 && !ismeta('?', type, 0, delimiter))
+ {
+ meta(sp, '{', type, 1, delimiter);
+ sfprintf(sp, "%d,%d", e->lo, e->hi);
+ meta(sp, '}', type, 1, delimiter);
+ }
+ else if (e->lo == 0)
+ meta(sp, '?', type, 1, delimiter);
+ }
+ else if (c)
+ sfputc(sp, c);
+ break;
+ case REX_STRING:
+ case REX_KMP:
+ t = (s = e->re.string.base) + e->re.string.size;
+ while (s < t)
+ {
+ c = *s++;
+ meta(sp, c, type, 0, delimiter);
+ }
+ break;
+ case REX_TRIE:
+ ib = 0;
+ for (c = 0; c <= UCHAR_MAX; c++)
+ if (e->re.trie.root[c])
+ {
+ char pfx[1024];
+
+ if (ib)
+ sfputc(sp, '|');
+ else
+ ib = 1;
+ detrie(e->re.trie.root[c], sp, pfx, pfx, &pfx[sizeof(pfx)], delimiter);
+ }
+ break;
+ case REX_NEG:
+ if (type >= SRE)
+ sfprintf(sp, "!(");
+ if (decomp(e->re.group.expr.rex, sp, type, delimiter, flags))
+ return 1;
+ if (type >= SRE)
+ sfputc(sp, ')');
+ else
+ sfputc(sp, '!');
+ break;
+ case REX_CONJ:
+ if (decomp(e->re.group.expr.binary.left, sp, type, delimiter, flags))
+ return 1;
+ sfputc(sp, '&');
+ if (decomp(e->re.group.expr.binary.right, sp, type, delimiter, flags))
+ return 1;
+ break;
+ case REX_GROUP:
+ if (type >= SRE)
+ sfputc(sp, '@');
+ meta(sp, '(', type, 1, delimiter);
+ if (decomp(e->re.group.expr.rex, sp, type, delimiter, flags))
+ return 1;
+ meta(sp, ')', type, 1, delimiter);
+ break;
+ case REX_GROUP_AHEAD:
+ case REX_GROUP_AHEAD_NOT:
+ case REX_GROUP_BEHIND:
+ case REX_GROUP_BEHIND_NOT:
+ meta(sp, '(', type, 1, delimiter);
+ sfputc(sp, '?');
+ if (decomp(e->re.group.expr.rex, sp, type, delimiter, flags))
+ return 1;
+ meta(sp, ')', type, 1, delimiter);
+ break;
+ case REX_GROUP_COND:
+ meta(sp, '(', type, 1, delimiter);
+ sfputc(sp, '?');
+ if (e->re.group.expr.binary.left && decomp(e->re.group.expr.binary.left, sp, type, delimiter, flags))
+ return 1;
+ if (q = e->re.group.expr.binary.right)
+ {
+ sfputc(sp, ':');
+ if (q->re.group.expr.binary.left && decomp(q->re.group.expr.binary.left, sp, type, delimiter, flags))
+ return 1;
+ sfputc(sp, ':');
+ if (q->re.group.expr.binary.right && decomp(q->re.group.expr.binary.right, sp, type, delimiter, flags))
+ return 1;
+ }
+ meta(sp, ')', type, 1, delimiter);
+ break;
+ case REX_GROUP_CUT:
+ meta(sp, '(', type, 1, delimiter);
+ sfputc(sp, '?');
+ if (decomp(e->re.group.expr.rex, sp, type, delimiter, flags))
+ return 1;
+ meta(sp, ')', type, 1, delimiter);
+ break;
+ case REX_BM:
+ break;
+ default:
+ sfprintf(sp, "<ERROR:REX_%d>", e->type);
+ break;
+ }
+ } while (e = e->next);
+ return 0;
+}
+
+/*
+ * reconstruct pattern from compiled re p into sp
+ */
+
+size_t
+regdecomp(regex_t* p, regflags_t flags, char* buf, size_t n)
+{
+ Sfio_t* sp;
+ char* s;
+ int type;
+ int delimiter;
+ size_t r;
+
+ if (!(sp = sfstropen()))
+ return 0;
+ if (flags == (regflags_t)~0)
+ flags = p->env->flags;
+ switch (flags & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL))
+ {
+ case 0:
+ type = BRE;
+ break;
+ case REG_AUGMENTED:
+ case REG_AUGMENTED|REG_EXTENDED:
+ type = ARE;
+ break;
+ case REG_EXTENDED:
+ type = ERE;
+ break;
+ case REG_SHELL:
+ type = SRE;
+ break;
+ default:
+ type = KRE;
+ break;
+ }
+ if (flags & REG_DELIMITED)
+ {
+ delimiter = '/';
+ sfputc(sp, delimiter);
+ }
+ else
+ delimiter = -1;
+ if (decomp(p->env->rex, sp, type, delimiter, flags))
+ r = 0;
+ else
+ {
+ if (delimiter > 0)
+ sfputc(sp, delimiter);
+ if ((r = sfstrtell(sp) + 1) <= n)
+ {
+ if (!(s = sfstruse(sp)))
+ r = 0;
+ else
+ memcpy(buf, s, r);
+ }
+ }
+ sfstrclose(sp);
+ return r;
+}
diff --git a/src/lib/libast/regex/regerror.c b/src/lib/libast/regex/regerror.c
new file mode 100644
index 0000000..3d0e40d
--- /dev/null
+++ b/src/lib/libast/regex/regerror.c
@@ -0,0 +1,95 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * posix regex error message handler
+ */
+
+static const char id[] = "\n@(#)$Id: regex (AT&T Research) 2010-09-22 $\0\n";
+
+#include "reglib.h"
+
+static const char* reg_error[] =
+{
+ /* REG_ENOSYS */ "not supported",
+ /* REG_SUCCESS */ "success",
+ /* REG_NOMATCH */ "no match",
+ /* REG_BADPAT */ "invalid regular expression",
+ /* REG_ECOLLATE */ "invalid collation element",
+ /* REG_ECTYPE */ "invalid character class",
+ /* REG_EESCAPE */ "trailing \\ in pattern",
+ /* REG_ESUBREG */ "invalid \\digit backreference",
+ /* REG_EBRACK */ "[...] imbalance",
+ /* REG_EPAREN */ "\\(...\\) or (...) imbalance",
+ /* REG_EBRACE */ "\\{...\\} or {...} imbalance",
+ /* REG_BADBR */ "invalid {...} digits",
+ /* REG_ERANGE */ "invalid [...] range endpoint",
+ /* REG_ESPACE */ "out of space",
+ /* REG_BADRPT */ "unary op not preceded by re",
+ /* REG_ENULL */ "empty subexpr in pattern",
+ /* REG_ECOUNT */ "re component count overflow",
+ /* REG_BADESC */ "invalid \\char escape",
+ /* REG_VERSIONID*/ &id[10],
+ /* REG_EFLAGS */ "conflicting flags",
+ /* REG_EDELIM */ "invalid or omitted delimiter",
+ /* REG_PANIC */ "unrecoverable internal error",
+};
+
+size_t
+regerror(int code, const regex_t* p, char* buf, size_t size)
+{
+ const char* s;
+
+ NoP(p);
+ if (code++ == REG_VERSIONID)
+ s = (const char*)fmtident(&id[1]);
+ else if (code >= 0 && code < elementsof(reg_error))
+ s = reg_error[code];
+ else
+ s = (const char*)"unknown error";
+ if (size)
+ {
+ strlcpy(buf, s, size);
+ buf[size - 1] = 0;
+ }
+ else
+ buf = (char*)s;
+ return strlen(buf) + 1;
+}
+
+/*
+ * discipline error intercept
+ */
+
+int
+fatal(regdisc_t* disc, int code, const char* pattern)
+{
+ if (disc->re_errorf)
+ {
+ if (pattern)
+ (*disc->re_errorf)(NiL, disc, disc->re_errorlevel, "regular expression: %s: %s", pattern, reg_error[code+1]);
+ else
+ (*disc->re_errorf)(NiL, disc, disc->re_errorlevel, "regular expression: %s", reg_error[code+1]);
+ }
+ return code;
+}
diff --git a/src/lib/libast/regex/regexec.c b/src/lib/libast/regex/regexec.c
new file mode 100644
index 0000000..fb8f428
--- /dev/null
+++ b/src/lib/libast/regex/regexec.c
@@ -0,0 +1,54 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * posix regex executor
+ * single unsized-string interface
+ */
+
+#include "reglib.h"
+
+/*
+ * standard wrapper for the sized-record interface
+ */
+
+int
+regexec(const regex_t* p, const char* s, size_t nmatch, regmatch_t* match, regflags_t flags)
+{
+ if (flags & REG_STARTEND)
+ {
+ int r;
+ int m = match->rm_so;
+ regmatch_t* e;
+
+ if (!(r = regnexec(p, s + m, match->rm_eo - m, nmatch, match, flags)) && m > 0)
+ for (e = match + nmatch; match < e; match++)
+ if (match->rm_so >= 0)
+ {
+ match->rm_so += m;
+ match->rm_eo += m;
+ }
+ return r;
+ }
+ return regnexec(p, s, s ? strlen(s) : 0, nmatch, match, flags);
+}
diff --git a/src/lib/libast/regex/regfatal.c b/src/lib/libast/regex/regfatal.c
new file mode 100644
index 0000000..09e8689
--- /dev/null
+++ b/src/lib/libast/regex/regfatal.c
@@ -0,0 +1,49 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * posix regex fatal error interface to error()
+ */
+
+#include "reglib.h"
+
+#include <error.h>
+
+void
+regfatalpat(regex_t* p, int level, int code, const char* pat)
+{
+ char buf[128];
+
+ regerror(code, p, buf, sizeof(buf));
+ regfree(p);
+ if (pat)
+ error(level, "regular expression: %s: %s", pat, buf);
+ else
+ error(level, "regular expression: %s", buf);
+}
+
+void
+regfatal(regex_t* p, int level, int code)
+{
+ regfatalpat(p, level, code, NiL);
+}
diff --git a/src/lib/libast/regex/reginit.c b/src/lib/libast/regex/reginit.c
new file mode 100644
index 0000000..e4719b4
--- /dev/null
+++ b/src/lib/libast/regex/reginit.c
@@ -0,0 +1,412 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * posix regex state and alloc
+ */
+
+#include "reglib.h"
+
+#if _PACKAGE_ast
+
+#include <ccode.h>
+
+#else
+
+#define CC_bel '\a'
+#define CC_esc '\033'
+#define CC_vt '\v'
+
+#endif
+
+/*
+ * state shared by all threads
+ */
+
+State_t state =
+{
+ { -1, -1 },
+
+ /*
+ * escape code table
+ * the "funny" things get special treatment at ends of BRE
+ *
+ * BRE 0:normal 1:escaped 2:escaped-char-class
+ * ERE 3:normal 4:escaped 5:escaped-char-class
+ * ARE 6:normal 7:escaped 8:escaped-char-class
+ * SRE 9:normal 10:escaped 11:escaped-char-class
+ * KRE 12:normal 13:escaped 14:escaped-char-class
+ */
+
+ '\\',
+ '\\', '\\', '\\',
+ '\\', '\\', '\\',
+ '\\', '\\', '\\',
+ '\\', '\\', '\\',
+ '\\', '\\', '\\',
+ '^', /* funny */
+ '^', '^', '^',
+ T_CFLX, '^', '^',
+ T_CFLX, '^', '^',
+ '^', '^', '^',
+ '^', '^', '^',
+ '.',
+ T_DOT, '.', T_BAD,
+ T_DOT, '.', T_BAD,
+ T_DOT, '.', T_BAD,
+ '.', '.', T_BAD,
+ '.', '.', T_BAD,
+ '$', /* funny */
+ '$', '$', T_BAD,
+ T_DOLL, '$', T_BAD,
+ T_DOLL, '$', T_BAD,
+ '$', '$', T_BAD,
+ '$', '$', T_BAD,
+ '*',
+ T_STAR, '*', T_BAD,
+ T_STAR, '*', T_BAD,
+ T_STAR, '*', T_BAD,
+ T_STAR, '*', '*',
+ T_STAR, '*', '*',
+ '[',
+ T_BRA, '[', '[',
+ T_BRA, '[', '[',
+ T_BRA, '[', '[',
+ T_BRA, '[', '[',
+ T_BRA, '[', '[',
+ '|',
+ '|', T_BAD, T_BAD,
+ T_BAR, '|', T_BAD,
+ T_BAR, '|', T_BAD,
+ '|', '|', T_BAD,
+ T_BAR, '|', T_BAD,
+ '+',
+ '+', T_BAD, T_BAD,
+ T_PLUS, '+', T_BAD,
+ T_PLUS, '+', T_BAD,
+ '+', '+', T_BAD,
+ T_PLUS, '+', T_BAD,
+ '?',
+ '?', T_BAD, T_BAD,
+ T_QUES, '?', T_BAD,
+ T_QUES, '?', T_BAD,
+ T_QUES, '?', '?',
+ T_QUES, '?', '?',
+ '(',
+ '(', T_OPEN, T_BAD,
+ T_OPEN, '(', T_BAD,
+ T_OPEN, '(', T_BAD,
+ '(', '(', '(',
+ T_OPEN, '(', '(',
+ ')',
+ ')', T_CLOSE, T_BAD,
+ T_CLOSE, ')', T_BAD,
+ T_CLOSE, ')', T_BAD,
+ ')', ')', ')',
+ T_CLOSE, ')', ')',
+ '{',
+ '{', T_LEFT, T_BAD,
+ T_LEFT, '{', T_BAD,
+ T_LEFT, '{', T_BAD,
+ '{', '{', '{',
+ T_LEFT, '{', '{',
+ '}',
+ '}', T_RIGHT, T_BAD,
+ '}', T_BAD, T_BAD,
+ '}', T_BAD, T_BAD,
+ '}', '}', '}',
+ '}', '}', '}',
+ '&',
+ '&', T_BAD, T_BAD,
+ '&', T_AND, T_BAD,
+ T_AND, '&', T_BAD,
+ '&', '&', T_BAD,
+ T_AND, '&', T_BAD,
+ '!',
+ '!', T_BAD, T_BAD,
+ '!', T_BANG, T_BAD,
+ T_BANG, '!', T_BAD,
+ '!', '!', T_BAD,
+ T_BANG, '!', T_BAD,
+ '@',
+ '@', T_BAD, T_BAD,
+ '@', T_BAD, T_BAD,
+ '@', T_BAD, T_BAD,
+ '@', '@', T_BAD,
+ T_AT, '@', T_BAD,
+ '~',
+ '~', T_BAD, T_BAD,
+ '~', T_BAD, T_BAD,
+ '~', T_BAD, T_BAD,
+ '~', '~', T_BAD,
+ T_TILDE, '~', T_BAD,
+ '%',
+ '%', T_BAD, T_BAD,
+ '%', T_BAD, T_BAD,
+ '%', T_BAD, T_BAD,
+ '%', '%', T_BAD,
+ T_PERCENT, '%', T_BAD,
+ '<',
+ '<', T_LT, T_BAD,
+ '<', T_LT, T_BAD,
+ T_LT, '<', T_BAD,
+ '<', '<', T_BAD,
+ '<', '<', T_BAD,
+ '>',
+ '>', T_GT, T_BAD,
+ '>', T_GT, T_BAD,
+ T_GT, '>', T_BAD,
+ '>', '>', T_BAD,
+ '>', '>', T_BAD,
+
+ /* backrefs */
+
+ '0',
+ '0', T_BACK+0, T_ESCAPE,
+ '0', T_BACK+0, T_ESCAPE,
+ '0', T_BACK+0, T_ESCAPE,
+ '0', T_BACK+0, T_ESCAPE,
+ '0', T_BACK+0, T_ESCAPE,
+ '1',
+ '1', T_BACK+1, T_ESCAPE,
+ '1', T_BACK+1, T_ESCAPE,
+ '1', T_BACK+1, T_ESCAPE,
+ '1', T_BACK+1, T_ESCAPE,
+ '1', T_BACK+1, T_ESCAPE,
+ '2',
+ '2', T_BACK+2, T_ESCAPE,
+ '2', T_BACK+2, T_ESCAPE,
+ '2', T_BACK+2, T_ESCAPE,
+ '2', T_BACK+2, T_ESCAPE,
+ '2', T_BACK+2, T_ESCAPE,
+ '3',
+ '3', T_BACK+3, T_ESCAPE,
+ '3', T_BACK+3, T_ESCAPE,
+ '3', T_BACK+3, T_ESCAPE,
+ '3', T_BACK+3, T_ESCAPE,
+ '3', T_BACK+3, T_ESCAPE,
+ '4',
+ '4', T_BACK+4, T_ESCAPE,
+ '4', T_BACK+4, T_ESCAPE,
+ '4', T_BACK+4, T_ESCAPE,
+ '4', T_BACK+4, T_ESCAPE,
+ '4', T_BACK+4, T_ESCAPE,
+ '5',
+ '5', T_BACK+5, T_ESCAPE,
+ '5', T_BACK+5, T_ESCAPE,
+ '5', T_BACK+5, T_ESCAPE,
+ '5', T_BACK+5, T_ESCAPE,
+ '5', T_BACK+5, T_ESCAPE,
+ '6',
+ '6', T_BACK+6, T_ESCAPE,
+ '6', T_BACK+6, T_ESCAPE,
+ '6', T_BACK+6, T_ESCAPE,
+ '6', T_BACK+6, T_ESCAPE,
+ '6', T_BACK+6, T_ESCAPE,
+ '7',
+ '7', T_BACK+7, T_ESCAPE,
+ '7', T_BACK+7, T_ESCAPE,
+ '7', T_BACK+7, T_ESCAPE,
+ '7', T_BACK+7, T_ESCAPE,
+ '7', T_BACK+7, T_ESCAPE,
+ '8',
+ '8', T_BACK+8, T_ESCAPE,
+ '8', T_BACK+8, T_ESCAPE,
+ '8', T_BACK+8, T_ESCAPE,
+ '8', '8', T_ESCAPE,
+ '8', T_BACK+8, T_ESCAPE,
+ '9',
+ '9', T_BACK+9, T_ESCAPE,
+ '9', T_BACK+9, T_ESCAPE,
+ '9', T_BACK+9, T_ESCAPE,
+ '9', '9', T_ESCAPE,
+ '9', T_BACK+9, T_ESCAPE,
+
+ /* perl */
+
+ 'A',
+ 'A', T_BEG_STR, T_BAD,
+ 'A', T_BEG_STR, T_BAD,
+ 'A', T_BEG_STR, T_BAD,
+ 'A', T_BEG_STR, T_BAD,
+ 'A', T_BEG_STR, T_BAD,
+ 'b',
+ 'b', T_WORD, '\b',
+ 'b', T_WORD, '\b',
+ 'b', T_WORD, '\b',
+ 'b', T_WORD, '\b',
+ 'b', T_WORD, '\b',
+ 'B',
+ 'B', T_WORD_NOT, T_BAD,
+ 'B', T_WORD_NOT, T_BAD,
+ 'B', T_WORD_NOT, T_BAD,
+ 'B', T_WORD_NOT, T_BAD,
+ 'B', T_WORD_NOT, T_BAD,
+ 'd',
+ 'd', T_DIGIT, T_DIGIT,
+ 'd', T_DIGIT, T_DIGIT,
+ 'd', T_DIGIT, T_DIGIT,
+ 'd', T_DIGIT, T_DIGIT,
+ 'd', T_DIGIT, T_DIGIT,
+ 'D',
+ 'D', T_DIGIT_NOT, T_DIGIT_NOT,
+ 'D', T_DIGIT_NOT, T_DIGIT_NOT,
+ 'D', T_DIGIT_NOT, T_DIGIT_NOT,
+ 'D', T_DIGIT_NOT, T_DIGIT_NOT,
+ 'D', T_DIGIT_NOT, T_DIGIT_NOT,
+ 's',
+ 's', T_SPACE, T_SPACE,
+ 's', T_SPACE, T_SPACE,
+ 's', T_SPACE, T_SPACE,
+ 's', T_SPACE, T_SPACE,
+ 's', T_SPACE, T_SPACE,
+ 'S',
+ 'S', T_SPACE_NOT, T_SPACE_NOT,
+ 'S', T_SPACE_NOT, T_SPACE_NOT,
+ 'S', T_SPACE_NOT, T_SPACE_NOT,
+ 'S', T_SPACE_NOT, T_SPACE_NOT,
+ 'S', T_SPACE_NOT, T_SPACE_NOT,
+ 'w',
+ 'w', T_ALNUM, T_ALNUM,
+ 'w', T_ALNUM, T_ALNUM,
+ 'w', T_ALNUM, T_ALNUM,
+ 'w', T_ALNUM, T_ALNUM,
+ 'w', T_ALNUM, T_ALNUM,
+ 'W',
+ 'W', T_ALNUM_NOT, T_ALNUM_NOT,
+ 'W', T_ALNUM_NOT, T_ALNUM_NOT,
+ 'W', T_ALNUM_NOT, T_ALNUM_NOT,
+ 'W', T_ALNUM_NOT, T_ALNUM_NOT,
+ 'W', T_ALNUM_NOT, T_ALNUM_NOT,
+ 'z',
+ 'z', T_FIN_STR, T_BAD,
+ 'z', T_FIN_STR, T_BAD,
+ 'z', T_FIN_STR, T_BAD,
+ 'z', T_FIN_STR, T_BAD,
+ 'z', T_FIN_STR, T_BAD,
+ 'Z',
+ 'Z', T_END_STR, T_BAD,
+ 'Z', T_END_STR, T_BAD,
+ 'Z', T_END_STR, T_BAD,
+ 'Z', T_END_STR, T_BAD,
+ 'Z', T_END_STR, T_BAD,
+
+ /* C escapes */
+
+ 'a',
+ 'a', CC_bel, CC_bel,
+ 'a', CC_bel, CC_bel,
+ 'a', CC_bel, CC_bel,
+ 'a', CC_bel, CC_bel,
+ 'a', CC_bel, CC_bel,
+ 'c',
+ 'c', T_ESCAPE, T_ESCAPE,
+ 'c', T_ESCAPE, T_ESCAPE,
+ 'c', T_ESCAPE, T_ESCAPE,
+ 'c', T_ESCAPE, T_ESCAPE,
+ 'c', T_ESCAPE, T_ESCAPE,
+ 'C',
+ 'C', T_ESCAPE, T_ESCAPE,
+ 'C', T_ESCAPE, T_ESCAPE,
+ 'C', T_ESCAPE, T_ESCAPE,
+ 'C', T_ESCAPE, T_ESCAPE,
+ 'C', T_ESCAPE, T_ESCAPE,
+ 'e',
+ 'e', CC_esc, CC_esc,
+ 'e', CC_esc, CC_esc,
+ 'e', CC_esc, CC_esc,
+ 'e', CC_esc, CC_esc,
+ 'e', CC_esc, CC_esc,
+ 'E',
+ 'E', CC_esc, CC_esc,
+ 'E', CC_esc, CC_esc,
+ 'E', CC_esc, CC_esc,
+ 'E', CC_esc, CC_esc,
+ 'E', CC_esc, CC_esc,
+ 'f',
+ 'f', '\f', '\f',
+ 'f', '\f', '\f',
+ 'f', '\f', '\f',
+ 'f', '\f', '\f',
+ 'f', '\f', '\f',
+ 'n',
+ 'n', '\n', '\n',
+ 'n', '\n', '\n',
+ 'n', '\n', '\n',
+ 'n', '\n', '\n',
+ 'n', '\n', '\n',
+ 'r',
+ 'r', '\r', '\r',
+ 'r', '\r', '\r',
+ 'r', '\r', '\r',
+ 'r', '\r', '\r',
+ 'r', '\r', '\r',
+ 't',
+ 't', '\t', '\t',
+ 't', '\t', '\t',
+ 't', '\t', '\t',
+ 't', '\t', '\t',
+ 't', '\t', '\t',
+ 'v',
+ 'v', CC_vt, CC_vt,
+ 'v', CC_vt, CC_vt,
+ 'v', CC_vt, CC_vt,
+ 'v', CC_vt, CC_vt,
+ 'v', CC_vt, CC_vt,
+ 'x',
+ 'x', T_ESCAPE, T_ESCAPE,
+ 'x', T_ESCAPE, T_ESCAPE,
+ 'x', T_ESCAPE, T_ESCAPE,
+ 'x', T_ESCAPE, T_ESCAPE,
+ 'x', T_ESCAPE, T_ESCAPE,
+};
+
+/*
+ * all allocation/free done here
+ * interface compatible with vmresize()
+ *
+ * malloc(n) alloc(0,n)
+ * realloc(p,n) alloc(p,n)
+ * free(p) alloc(p,0)
+ */
+
+void*
+alloc(register regdisc_t* disc, void* p, size_t n)
+{
+ if (disc->re_resizef)
+ {
+ if (!n && (disc->re_flags & REG_NOFREE))
+ return 0;
+ return (*disc->re_resizef)(disc->re_resizehandle, p, n);
+ }
+ else if (!n)
+ {
+ if (!(disc->re_flags & REG_NOFREE))
+ free(p);
+ return 0;
+ }
+ else if (p)
+ return realloc(p, n);
+ else
+ return malloc(n);
+}
diff --git a/src/lib/libast/regex/reglib.h b/src/lib/libast/regex/reglib.h
new file mode 100644
index 0000000..6b84e5d
--- /dev/null
+++ b/src/lib/libast/regex/reglib.h
@@ -0,0 +1,582 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * posix regex implementation
+ *
+ * based on Doug McIlroy's C++ implementation
+ * Knuth-Morris-Pratt adapted from Corman-Leiserson-Rivest
+ * Boyer-Moore from conversations with David Korn, Phong Vo, Andrew Hume
+ */
+
+#ifndef _REGLIB_H
+#define _REGLIB_H
+
+#define REG_VERSION_EXEC 20020509L
+#define REG_VERSION_MAP 20030916L /* regdisc_t.re_map */
+
+#define re_info env
+
+#define alloc _reg_alloc
+#define classfun _reg_classfun
+#define drop _reg_drop
+#define fatal _reg_fatal
+#define state _reg_state
+
+typedef struct regsubop_s
+{
+ int op; /* REG_SUB_LOWER,REG_SUB_UPPER */
+ int off; /* re_rhs or match[] offset */
+ int len; /* re_rhs len or len==0 match[] */
+} regsubop_t;
+
+#define _REG_SUB_PRIVATE_ \
+ char* re_cur; /* re_buf cursor */ \
+ char* re_end; /* re_buf end */ \
+ regsubop_t* re_ops; /* rhs ops */ \
+ char re_rhs[1]; /* substitution rhs */
+
+#include <ast.h>
+#include <cdt.h>
+#include <stk.h>
+
+#include "regex.h"
+
+#include <ctype.h>
+#include <errno.h>
+
+#if _BLD_DEBUG && !defined(_AST_REGEX_DEBUG)
+#define _AST_REGEX_DEBUG 1
+#endif
+
+#define MBSIZE(p) ((ast.tmp_int=mbsize(p))>0?ast.tmp_int:1)
+
+#undef RE_DUP_MAX /* posix puts this in limits.h! */
+#define RE_DUP_MAX (INT_MAX/2-1) /* 2*RE_DUP_MAX won't overflow */
+#define RE_DUP_INF (RE_DUP_MAX+1) /* infinity, for * */
+#define BACK_REF_MAX 9
+
+#define REG_COMP (~REG_EXEC)
+#define REG_EXEC (REG_ADVANCE|REG_INVERT|REG_NOTBOL|REG_NOTEOL|REG_STARTEND)
+
+#define REX_NULL 0 /* null string (internal) */
+#define REX_ALT 1 /* a|b */
+#define REX_ALT_CATCH 2 /* REX_ALT catcher */
+#define REX_BACK 3 /* \1, \2, etc */
+#define REX_BEG 4 /* initial ^ */
+#define REX_BEG_STR 5 /* initial ^ w/ no newline */
+#define REX_BM 6 /* Boyer-Moore */
+#define REX_CAT 7 /* catenation catcher */
+#define REX_CLASS 8 /* [...] */
+#define REX_COLL_CLASS 9 /* collation order [...] */
+#define REX_CONJ 10 /* a&b */
+#define REX_CONJ_LEFT 11 /* REX_CONJ left catcher */
+#define REX_CONJ_RIGHT 12 /* REX_CONJ right catcher */
+#define REX_DONE 13 /* completed match (internal) */
+#define REX_DOT 14 /* . */
+#define REX_END 15 /* final $ */
+#define REX_END_STR 16 /* final $ before tail newline */
+#define REX_EXEC 17 /* call re.re_exec() */
+#define REX_FIN_STR 18 /* final $ w/ no newline */
+#define REX_GROUP 19 /* \(...\) */
+#define REX_GROUP_CATCH 20 /* REX_GROUP catcher */
+#define REX_GROUP_AHEAD 21 /* 0-width lookahead */
+#define REX_GROUP_AHEAD_CATCH 22 /* REX_GROUP_AHEAD catcher */
+#define REX_GROUP_AHEAD_NOT 23 /* inverted 0-width lookahead */
+#define REX_GROUP_BEHIND 24 /* 0-width lookbehind */
+#define REX_GROUP_BEHIND_CATCH 25 /* REX_GROUP_BEHIND catcher */
+#define REX_GROUP_BEHIND_NOT 26 /* inverted 0-width lookbehind */
+#define REX_GROUP_BEHIND_NOT_CATCH 27 /* REX_GROUP_BEHIND_NOT catcher */
+#define REX_GROUP_COND 28 /* conditional group */
+#define REX_GROUP_COND_CATCH 29 /* conditional group catcher */
+#define REX_GROUP_CUT 30 /* don't backtrack over this */
+#define REX_GROUP_CUT_CATCH 31 /* REX_GROUP_CUT catcher */
+#define REX_KMP 32 /* Knuth-Morris-Pratt */
+#define REX_NEG 33 /* negation */
+#define REX_NEG_CATCH 34 /* REX_NEG catcher */
+#define REX_NEST 35 /* nested match */
+#define REX_ONECHAR 36 /* a single-character literal */
+#define REX_REP 37 /* Kleene closure */
+#define REX_REP_CATCH 38 /* REX_REP catcher */
+#define REX_STRING 39 /* some chars */
+#define REX_TRIE 40 /* alternation of strings */
+#define REX_WBEG 41 /* \< */
+#define REX_WEND 42 /* \> */
+#define REX_WORD 43 /* word boundary */
+#define REX_WORD_NOT 44 /* not word boundary */
+
+#define T_META ((int)UCHAR_MAX+1)
+#define T_STAR (T_META+0)
+#define T_PLUS (T_META+1)
+#define T_QUES (T_META+2)
+#define T_BANG (T_META+3)
+#define T_AT (T_META+4)
+#define T_TILDE (T_META+5)
+#define T_PERCENT (T_META+6)
+#define T_LEFT (T_META+7)
+#define T_OPEN (T_META+8)
+#define T_CLOSE (T_OPEN+1)
+#define T_RIGHT (T_OPEN+2)
+#define T_CFLX (T_OPEN+3)
+#define T_DOT (T_OPEN+4)
+#define T_DOTSTAR (T_OPEN+5)
+#define T_END (T_OPEN+6)
+#define T_BAD (T_OPEN+7)
+#define T_DOLL (T_OPEN+8)
+#define T_BRA (T_OPEN+9)
+#define T_BAR (T_OPEN+10)
+#define T_AND (T_OPEN+11)
+#define T_LT (T_OPEN+12)
+#define T_GT (T_OPEN+13)
+#define T_SLASHPLUS (T_OPEN+14)
+#define T_GROUP (T_OPEN+15)
+#define T_WORD (T_OPEN+16)
+#define T_WORD_NOT (T_WORD+1)
+#define T_BEG_STR (T_WORD+2)
+#define T_END_STR (T_WORD+3)
+#define T_FIN_STR (T_WORD+4)
+#define T_ESCAPE (T_WORD+5)
+#define T_ALNUM (T_WORD+6)
+#define T_ALNUM_NOT (T_ALNUM+1)
+#define T_DIGIT (T_ALNUM+2)
+#define T_DIGIT_NOT (T_ALNUM+3)
+#define T_SPACE (T_ALNUM+4)
+#define T_SPACE_NOT (T_ALNUM+5)
+#define T_BACK (T_ALNUM+6)
+
+#define BRE 0
+#define ERE 3
+#define ARE 6
+#define SRE 9
+#define KRE 12
+
+#define HIT SSIZE_MAX
+
+#define bitclr(p,c) ((p)[((c)>>3)&037]&=(~(1<<((c)&07))))
+#define bitset(p,c) ((p)[((c)>>3)&037]|=(1<<((c)&07)))
+#define bittst(p,c) ((p)[((c)>>3)&037]&(1<<((c)&07)))
+
+#define setadd(p,c) bitset((p)->bits,c)
+#define setclr(p,c) bitclr((p)->bits,c)
+#define settst(p,c) bittst((p)->bits,c)
+
+#if _hdr_wchar && _lib_wctype && _lib_iswctype
+
+#include <stdio.h> /* because <wchar.h> includes it and we generate it */
+#include <wchar.h>
+#if _hdr_wctype
+#include <wctype.h>
+#endif
+
+#if !defined(iswblank) && !_lib_iswblank
+#define _need_iswblank 1
+#define iswblank(x) _reg_iswblank(x)
+extern int _reg_iswblank(wint_t);
+#endif
+
+#if !defined(towupper) && !_lib_towupper
+#define towupper(x) toupper(x)
+#endif
+
+#if !defined(towlower) && !_lib_towlower
+#define towlower(x) tolower(x)
+#endif
+
+#else
+
+#undef _lib_wctype
+
+#ifndef iswalnum
+#define iswalnum(x) isalnum(x)
+#endif
+#ifndef iswalpha
+#define iswalpha(x) isalpha(x)
+#endif
+#ifndef iswcntrl
+#define iswcntrl(x) iscntrl(x)
+#endif
+#ifndef iswdigit
+#define iswdigit(x) isdigit(x)
+#endif
+#ifndef iswgraph
+#define iswgraph(x) isgraph(x)
+#endif
+#ifndef iswlower
+#define iswlower(x) islower(x)
+#endif
+#ifndef iswprint
+#define iswprint(x) isprint(x)
+#endif
+#ifndef iswpunct
+#define iswpunct(x) ispunct(x)
+#endif
+#ifndef iswspace
+#define iswspace(x) isspace(x)
+#endif
+#ifndef iswupper
+#define iswupper(x) isupper(x)
+#endif
+#ifndef iswxdigit
+#define iswxdigit(x) isxdigit(x)
+#endif
+
+#ifndef towlower
+#define towlower(x) tolower(x)
+#endif
+#ifndef towupper
+#define towupper(x) toupper(x)
+#endif
+
+#endif
+
+#ifndef iswblank
+#define iswblank(x) ((x)==' '||(x)=='\t')
+#endif
+
+#ifndef iswgraph
+#define iswgraph(x) (iswprint(x)&&!iswblank(x))
+#endif
+
+#define isword(x) (isalnum(x)||(x)=='_')
+
+/*
+ * collation element support
+ */
+
+#define COLL_KEY_MAX 32
+
+#if COLL_KEY_MAX < MB_LEN_MAX
+#undef COLL_KEY_MAX
+#define COLL_KEY_MAX MB_LEN_MAX
+#endif
+
+typedef unsigned char Ckey_t[COLL_KEY_MAX+1];
+
+#define COLL_end 0
+#define COLL_call 1
+#define COLL_char 2
+#define COLL_range 3
+#define COLL_range_lc 4
+#define COLL_range_uc 5
+
+typedef struct Celt_s
+{
+ short typ;
+ short min;
+ short max;
+ regclass_t fun;
+ Ckey_t beg;
+ Ckey_t end;
+} Celt_t;
+
+/*
+ * private stuff hanging off regex_t
+ */
+
+typedef struct Stk_pos_s
+{
+ off_t offset;
+ char* base;
+} Stk_pos_t;
+
+typedef struct Vector_s
+{
+ Stk_t* stk; /* stack pointer */
+ char* vec; /* the data */
+ int inc; /* growth increment */
+ int siz; /* element size */
+ int max; /* max index */
+ int cur; /* current index -- user domain */
+} Vector_t;
+
+/*
+ * Rex_t subtypes
+ */
+
+typedef struct Cond_s
+{
+ unsigned char* beg; /* beginning of next match */
+ struct Rex_s* next[2]; /* 0:no 1:yes next pattern */
+ struct Rex_s* cont; /* right catcher */
+ int yes; /* yes condition hit */
+} Cond_t;
+
+typedef struct Conj_left_s
+{
+ unsigned char* beg; /* beginning of left match */
+ struct Rex_s* right; /* right pattern */
+ struct Rex_s* cont; /* right catcher */
+} Conj_left_t;
+
+typedef struct Conj_right_s
+{
+ unsigned char* end; /* end of left match */
+ struct Rex_s* cont; /* ambient continuation */
+} Conj_right_t;
+
+typedef unsigned int Bm_mask_t;
+
+typedef struct Bm_s
+{
+ Bm_mask_t** mask;
+ size_t* skip;
+ size_t* fail;
+ size_t size;
+ ssize_t back;
+ ssize_t left;
+ ssize_t right;
+ size_t complete;
+} Bm_t;
+
+typedef struct String_s
+{
+ int* fail;
+ unsigned char* base;
+ size_t size;
+} String_t;
+
+typedef struct Set_s
+{
+ unsigned char bits[(UCHAR_MAX+1)/CHAR_BIT];
+} Set_t;
+
+typedef struct Collate_s
+{
+ int invert;
+ Celt_t* elements;
+} Collate_t;
+
+typedef struct Binary_s
+{
+ struct Rex_s* left;
+ struct Rex_s* right;
+ int serial;
+} Binary_t;
+
+typedef struct Group_s
+{
+ int number; /* group number */
+ int last; /* last contained group number */
+ int size; /* lookbehind size */
+ int back; /* backreferenced */
+ regflags_t flags; /* group flags */
+ union
+ {
+ Binary_t binary;
+ struct Rex_s* rex;
+ } expr;
+} Group_t;
+
+typedef struct Exec_s
+{
+ void* data;
+ const char* text;
+ size_t size;
+} Exec_t;
+
+#define REX_NEST_open 0x01
+#define REX_NEST_close 0x02
+#define REX_NEST_escape 0x04
+#define REX_NEST_quote 0x08
+#define REX_NEST_literal 0x10
+#define REX_NEST_delimiter 0x20
+#define REX_NEST_terminator 0x40
+#define REX_NEST_separator 0x80
+
+#define REX_NEST_SHIFT 8
+
+typedef struct Nest_s
+{
+ int primary;
+ unsigned short none; /* for Nest_t.type[-1] */
+ unsigned short type[1];
+} Nest_t;
+
+/*
+ * REX_ALT catcher, solely to get control at the end of an
+ * alternative to keep records for comparing matches.
+ */
+
+typedef struct Alt_catch_s
+{
+ struct Rex_s* cont;
+} Alt_catch_t;
+
+typedef struct Group_catch_s
+{
+ struct Rex_s* cont;
+ regoff_t* eo;
+} Group_catch_t;
+
+typedef struct Behind_catch_s
+{
+ struct Rex_s* cont;
+ unsigned char* beg;
+ unsigned char* end;
+} Behind_catch_t;
+
+/*
+ * REX_NEG catcher determines what string lengths can be matched,
+ * then Neg investigates continuations of other lengths.
+ * This is inefficient. For !POSITIONS expressions, we can do better:
+ * since matches to rex will be enumerated in decreasing order,
+ * we can investigate continuations whenever a length is skipped.
+ */
+
+typedef struct Neg_catch_s
+{
+ unsigned char* beg;
+ unsigned char* index;
+} Neg_catch_t;
+
+/*
+ * REX_REP catcher. One is created on the stack for
+ * each iteration of a complex repetition.
+ */
+
+typedef struct Rep_catch_s
+{
+ struct Rex_s* cont;
+ struct Rex_s* ref;
+ unsigned char* beg;
+ int n;
+} Rep_catch_t;
+
+/*
+ * data structure for an alternation of pure strings
+ * son points to a subtree of all strings with a common
+ * prefix ending in character c. sib links alternate
+ * letters in the same position of a word. end=1 if
+ * some word ends with c. the order of strings is
+ * irrelevant, except long words must be investigated
+ * before short ones.
+ */
+
+typedef struct Trie_node_s
+{
+ unsigned char c;
+ unsigned char end;
+ struct Trie_node_s* son;
+ struct Trie_node_s* sib;
+} Trie_node_t;
+
+typedef struct Trie_s
+{
+ Trie_node_t** root;
+ int min;
+ int max;
+} Trie_t;
+
+/*
+ * Rex_t is a node in a regular expression
+ */
+
+typedef struct Rex_s
+{
+ unsigned char type; /* node type */
+ unsigned char marked; /* already marked */
+ short serial; /* subpattern number */
+ regflags_t flags; /* scoped flags */
+ int explicit; /* scoped explicit match*/
+ struct Rex_s* next; /* remaining parts */
+ int lo; /* lo dup count */
+ int hi; /* hi dup count */
+ unsigned char* map; /* fold and/or ccode map*/
+ union
+ {
+ Alt_catch_t alt_catch; /* alt catcher */
+ Bm_t bm; /* bm */
+ Behind_catch_t behind_catch; /* behind catcher */
+ Set_t* charclass; /* char class */
+ Collate_t collate; /* collation class */
+ Cond_t cond_catch; /* cond catcher */
+ Conj_left_t conj_left; /* conj left catcher */
+ Conj_right_t conj_right; /* conj right catcher */
+ void* data; /* data after Rex_t */
+ Exec_t exec; /* re.re_exec() args */
+ Group_t group; /* a|b or rep */
+ Group_catch_t group_catch; /* group catcher */
+ Neg_catch_t neg_catch; /* neg catcher */
+ Nest_t nest; /* nested match */
+ unsigned char onechar; /* single char */
+ Rep_catch_t rep_catch; /* rep catcher */
+ String_t string; /* string/kmp */
+ Trie_t trie; /* trie */
+ } re;
+} Rex_t;
+
+typedef struct reglib_s /* library private regex_t info */
+{
+ struct Rex_s* rex; /* compiled expression */
+ regdisc_t* disc; /* REG_DISCIPLINE discipline */
+ const regex_t* regex; /* from regexec */
+ unsigned char* beg; /* beginning of string */
+ unsigned char* end; /* end of string */
+ Vector_t* pos; /* posns of certain subpatterns */
+ Vector_t* bestpos; /* ditto for best match */
+ regmatch_t* match; /* subexrs in current match */
+ regmatch_t* best; /* ditto in best match yet */
+ Stk_pos_t stk; /* exec stack pos */
+ size_t min; /* minimum match length */
+ size_t nsub; /* internal re_nsub */
+ regflags_t flags; /* flags from regcomp() */
+ int error; /* last error */
+ int explicit; /* explicit match on this char */
+ int leading; /* leading match on this char */
+ int refs; /* regcomp()+regdup() references*/
+ Rex_t done; /* the last continuation */
+ regstat_t stats; /* for regstat() */
+ unsigned char fold[UCHAR_MAX+1]; /* REG_ICASE map */
+ unsigned char hard; /* hard comp */
+ unsigned char once; /* if 1st parse fails, quit */
+ unsigned char separate; /* cannot combine */
+ unsigned char stack; /* hard comp or exec */
+ unsigned char sub; /* re_sub is valid */
+ unsigned char test; /* debug/test bitmask */
+} Env_t;
+
+typedef struct State_s /* shared state */
+{
+ regmatch_t nomatch;
+ struct
+ {
+ unsigned char key;
+ short val[15];
+ } escape[52];
+ short* magic[UCHAR_MAX+1];
+ regdisc_t disc;
+ int fatal;
+ int initialized;
+ Dt_t* attrs;
+ Dt_t* names;
+ Dtdisc_t dtdisc;
+} State_t;
+
+extern State_t state;
+
+extern void* alloc(regdisc_t*, void*, size_t);
+extern regclass_t classfun(int);
+extern void drop(regdisc_t*, Rex_t*);
+extern int fatal(regdisc_t*, int, const char*);
+
+#endif
diff --git a/src/lib/libast/regex/regnexec.c b/src/lib/libast/regex/regnexec.c
new file mode 100644
index 0000000..0c3a0aa
--- /dev/null
+++ b/src/lib/libast/regex/regnexec.c
@@ -0,0 +1,2045 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * posix regex executor
+ * single sized-record interface
+ */
+
+#include "reglib.h"
+
+#if _AST_REGEX_DEBUG
+
+#define DEBUG_TEST(f,y,n) ((debug&(debug_flag=f))?(y):(n))
+#define DEBUG_CODE(f,y,n) do if(debug&(f)){y}else{n} while(0)
+#define DEBUG_INIT() do { char* t; if (!debug) { debug = 0x80000000; if (t = getenv("_AST_regex_exec_debug")) debug |= strtoul(t, NiL, 0); } } while (0)
+
+static unsigned long debug;
+static unsigned long debug_flag;
+
+static const char* rexnames[] =
+{
+ "REX_NULL",
+ "REX_ALT",
+ "REX_ALT_CATCH",
+ "REX_BACK",
+ "REX_BEG",
+ "REX_BEG_STR",
+ "REX_BM",
+ "REX_CAT",
+ "REX_CLASS",
+ "REX_COLL_CLASS",
+ "REX_CONJ",
+ "REX_CONJ_LEFT",
+ "REX_CONJ_RIGHT",
+ "REX_DONE",
+ "REX_DOT",
+ "REX_END",
+ "REX_END_STR",
+ "REX_EXEC",
+ "REX_FIN_STR",
+ "REX_GROUP",
+ "REX_GROUP_CATCH",
+ "REX_GROUP_AHEAD",
+ "REX_GROUP_AHEAD_CATCH",
+ "REX_GROUP_AHEAD_NOT",
+ "REX_GROUP_BEHIND",
+ "REX_GROUP_BEHIND_CATCH",
+ "REX_GROUP_BEHIND_NOT",
+ "REX_GROUP_BEHIND_NOT_CATCH",
+ "REX_GROUP_COND",
+ "REX_GROUP_COND_CATCH",
+ "REX_GROUP_CUT",
+ "REX_GROUP_CUT_CATCH",
+ "REX_KMP",
+ "REX_NEG",
+ "REX_NEG_CATCH",
+ "REX_NEST",
+ "REX_ONECHAR",
+ "REX_REP",
+ "REX_REP_CATCH",
+ "REX_STRING",
+ "REX_TRIE",
+ "REX_WBEG",
+ "REX_WEND",
+ "REX_WORD",
+ "REX_WORD_NOT"
+};
+
+static const char* rexname(Rex_t* rex)
+{
+ if (!rex)
+ return "NIL";
+ if (rex->type >= elementsof(rexnames))
+ return "ERROR";
+ return rexnames[rex->type];
+}
+
+#else
+
+#define DEBUG_INIT()
+#define DEBUG_TEST(f,y,n) (n)
+#define DEBUG_CODE(f,y,n) do {n} while(0)
+
+#endif
+
+#define BEG_ALT 1 /* beginning of an alt */
+#define BEG_ONE 2 /* beginning of one iteration of a rep */
+#define BEG_REP 3 /* beginning of a repetition */
+#define BEG_SUB 4 /* beginning of a subexpression */
+#define END_ANY 5 /* end of any of above */
+
+/*
+ * returns from parse()
+ */
+
+#define NONE 0 /* no parse found */
+#define GOOD 1 /* some parse was found */
+#define CUT 2 /* no match and no backtrack */
+#define BEST 3 /* an unbeatable parse was found */
+#define BAD 4 /* error ocurred */
+
+/*
+ * REG_SHELL_DOT test
+ */
+
+#define LEADING(e,r,s) (*(s)==(e)->leading&&((s)==(e)->beg||*((s)-1)==(r)->explicit))
+
+/*
+ * Pos_t is for comparing parses. An entry is made in the
+ * array at the beginning and at the end of each Group_t,
+ * each iteration in a Group_t, and each Binary_t.
+ */
+
+typedef struct
+{
+ unsigned char* p; /* where in string */
+ size_t length; /* length in string */
+ short serial; /* preorder subpattern number */
+ short be; /* which end of pair */
+} Pos_t;
+
+/* ===== begin library support ===== */
+
+#define vector(t,v,i) (((i)<(v)->max)?(t*)((v)->vec+(i)*(v)->siz):(t*)vecseek(&(v),i))
+
+static Vector_t*
+vecopen(int inc, int siz)
+{
+ Vector_t* v;
+ Stk_t* sp;
+
+ if (inc <= 0)
+ inc = 16;
+ if (!(sp = stkopen(STK_SMALL|STK_NULL)))
+ return 0;
+ if (!(v = (Vector_t*)stkseek(sp, sizeof(Vector_t) + inc * siz)))
+ {
+ stkclose(sp);
+ return 0;
+ }
+ v->stk = sp;
+ v->vec = (char*)v + sizeof(Vector_t);
+ v->max = v->inc = inc;
+ v->siz = siz;
+ v->cur = 0;
+ return v;
+}
+
+static void*
+vecseek(Vector_t** p, int index)
+{
+ Vector_t* v = *p;
+
+ if (index >= v->max)
+ {
+ while ((v->max += v->inc) <= index);
+ if (!(v = (Vector_t*)stkseek(v->stk, sizeof(Vector_t) + v->max * v->siz)))
+ return 0;
+ *p = v;
+ v->vec = (char*)v + sizeof(Vector_t);
+ }
+ return v->vec + index * v->siz;
+}
+
+static void
+vecclose(Vector_t* v)
+{
+ if (v)
+ stkclose(v->stk);
+}
+
+typedef struct
+{
+ Stk_pos_t pos;
+ char data[1];
+} Stk_frame_t;
+
+#define stknew(s,p) ((p)->offset=stktell(s),(p)->base=stkfreeze(s,0))
+#define stkold(s,p) stkset(s,(p)->base,(p)->offset)
+
+#define stkframe(s) (*((Stk_frame_t**)stktop(s)-1))
+#define stkdata(s,t) ((t*)stkframe(s)->data)
+#define stkpop(s) stkold(s,&(stkframe(s)->pos))
+
+static void*
+stkpush(Stk_t* sp, size_t size)
+{
+ Stk_frame_t* f;
+ Stk_pos_t p;
+
+ stknew(sp, &p);
+ size = sizeof(Stk_frame_t) + sizeof(size_t) + size - 1;
+ if (!(f = (Stk_frame_t*)stkalloc(sp, sizeof(Stk_frame_t) + sizeof(Stk_frame_t*) + size - 1)))
+ return 0;
+ f->pos = p;
+ stkframe(sp) = f;
+ return f->data;
+}
+
+/* ===== end library support ===== */
+
+/*
+ * Match_frame_t is for saving and restoring match records
+ * around alternate attempts, so that fossils will not be
+ * left in the match array. These are the only entries in
+ * the match array that are not otherwise guaranteed to
+ * have current data in them when they get used.
+ */
+
+typedef struct
+{
+ size_t size;
+ regmatch_t* match;
+ regmatch_t save[1];
+} Match_frame_t;
+
+#define matchpush(e,x) ((x)->re.group.number?_matchpush(e,x):0)
+#define matchcopy(e,x) do if ((x)->re.group.number) { Match_frame_t* fp = (void*)stkframe(stkstd)->data; memcpy(fp->match, fp->save, fp->size); } while (0)
+#define matchpop(e,x) do if ((x)->re.group.number) { Match_frame_t* fp = (void*)stkframe(stkstd)->data; memcpy(fp->match, fp->save, fp->size); stkpop(stkstd); } while (0)
+
+#define pospop(e) (--(e)->pos->cur)
+
+/*
+ * allocate a frame and push a match onto the stack
+ */
+
+static int
+_matchpush(Env_t* env, Rex_t* rex)
+{
+ Match_frame_t* f;
+ regmatch_t* m;
+ regmatch_t* e;
+ regmatch_t* s;
+ int num;
+
+ if (rex->re.group.number <= 0 || (num = rex->re.group.last - rex->re.group.number + 1) <= 0)
+ num = 0;
+ if (!(f = (Match_frame_t*)stkpush(stkstd, sizeof(Match_frame_t) + (num - 1) * sizeof(regmatch_t))))
+ {
+ env->error = REG_ESPACE;
+ return 1;
+ }
+ f->size = num * sizeof(regmatch_t);
+ f->match = m = env->match + rex->re.group.number;
+ e = m + num;
+ s = f->save;
+ while (m < e)
+ {
+ *s++ = *m;
+ *m++ = state.nomatch;
+ }
+ return 0;
+}
+
+/*
+ * allocate a frame and push a pos onto the stack
+ */
+
+static int
+pospush(Env_t* env, Rex_t* rex, unsigned char* p, int be)
+{
+ Pos_t* pos;
+
+ if (!(pos = vector(Pos_t, env->pos, env->pos->cur)))
+ {
+ env->error = REG_ESPACE;
+ return 1;
+ }
+ pos->serial = rex->serial;
+ pos->p = p;
+ pos->be = be;
+ env->pos->cur++;
+ return 0;
+}
+
+/*
+ * two matches are known to have the same length
+ * os is start of old pos array, ns is start of new,
+ * oend and nend are end+1 pointers to ends of arrays.
+ * oe and ne are ends (not end+1) of subarrays.
+ * returns 1 if new is better, -1 if old, else 0.
+ */
+
+static int
+better(Env_t* env, Pos_t* os, Pos_t* ns, Pos_t* oend, Pos_t* nend, int level)
+{
+ Pos_t* oe;
+ Pos_t* ne;
+ int k;
+ int n;
+
+ if (env->error)
+ return -1;
+ for (;;)
+ {
+ DEBUG_CODE(0x0080,{sfprintf(sfstdout, " %-*.*sold ", (level + 3) * 4, (level + 3) * 4, "");for (oe = os; oe < oend; oe++)sfprintf(sfstdout, "<%d,%d,%d>", oe->p - env->beg, oe->serial, oe->be);sfprintf(sfstdout, "\n %-*.*snew ", (level + 3) * 4, (level + 3) * 4, "");for (oe = ns; oe < nend; oe++)sfprintf(sfstdout, "<%d,%d,%d>", oe->p - env->beg, oe->serial, oe->be);sfprintf(sfstdout, "\n");},{0;});
+ if (ns >= nend)
+ return DEBUG_TEST(0x8000,(os < oend),(0));
+ if (os >= oend)
+ return DEBUG_TEST(0x8000,(-1),(1));
+ n = os->serial;
+ if (ns->serial > n)
+ return -1;
+ if (n > ns->serial)
+ {
+ env->error = REG_PANIC;
+ return -1;
+ }
+ if (ns->p > os->p)
+ return 1;
+ if (os->p > ns->p)
+ return -1;
+ oe = os;
+ k = 0;
+ for (;;)
+ if ((++oe)->serial == n)
+ {
+ if (oe->be != END_ANY)
+ k++;
+ else if (k-- <= 0)
+ break;
+ }
+ ne = ns;
+ k = 0;
+ for (;;)
+ if ((++ne)->serial == n)
+ {
+ if (ne->be != END_ANY)
+ k++;
+ else if (k-- <= 0)
+ break;
+ }
+ if (ne->p > oe->p)
+ return 1;
+ if (oe->p > ne->p)
+ return -1;
+ if (k = better(env, os + 1, ns + 1, oe, ne, level + 1))
+ return k;
+ os = oe + 1;
+ ns = ne + 1;
+ }
+}
+
+#if _AST_REGEX_DEBUG
+
+static void
+showmatch(regmatch_t* p)
+{
+ sfputc(sfstdout, '(');
+ if (p->rm_so < 0)
+ sfputc(sfstdout, '?');
+ else
+ sfprintf(sfstdout, "%d", p->rm_so);
+ sfputc(sfstdout, ',');
+ if (p->rm_eo < 0)
+ sfputc(sfstdout, '?');
+ else
+ sfprintf(sfstdout, "%d", p->rm_eo);
+ sfputc(sfstdout, ')');
+}
+
+static int
+_better(Env_t* env, Pos_t* os, Pos_t* ns, Pos_t* oend, Pos_t* nend, int level)
+{
+ int i;
+
+ DEBUG_CODE(0x0040,{sfprintf(sfstdout, "AHA better old ");for (i = 0; i <= env->nsub; i++)showmatch(&env->best[i]);sfprintf(sfstdout, "\n new ");for (i = 0; i <= env->nsub; i++)showmatch(&env->match[i]);sfprintf(sfstdout, "\n");},{0;});
+ i = better(env, os, ns, oend, nend, 0);
+ DEBUG_TEST(0x0040,(sfprintf(sfstdout, " %s\n", i <= 0 ? "OLD" : "NEW")),(0));
+ return i;
+}
+
+#define better _better
+
+#endif
+
+#define follow(e,r,c,s) ((r)->next?parse(e,(r)->next,c,s):(c)?parse(e,c,0,s):BEST)
+
+static int parse(Env_t*, Rex_t*, Rex_t*, unsigned char*);
+
+static int
+parserep(Env_t* env, Rex_t* rex, Rex_t* cont, unsigned char* s, int n)
+{
+ int i;
+ int r = NONE;
+ Rex_t catcher;
+
+ DEBUG_TEST(0x0010,(sfprintf(sfstdout, "AHA#%04d 0x%04x parserep %s %d %d %d %d `%-.*s'\n", __LINE__, debug_flag, rexname(rex->re.group.expr.rex), rex->re.group.number, rex->lo, n, rex->hi, env->end - s, s)),(0));
+ if ((rex->flags & REG_MINIMAL) && n >= rex->lo && n < rex->hi)
+ {
+ if (env->stack && pospush(env, rex, s, END_ANY))
+ return BAD;
+ i = follow(env, rex, cont, s);
+ if (env->stack)
+ pospop(env);
+ switch (i)
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ case GOOD:
+ return BEST;
+ }
+ }
+ if (n < rex->hi)
+ {
+ catcher.type = REX_REP_CATCH;
+ catcher.serial = rex->serial;
+ catcher.re.rep_catch.ref = rex;
+ catcher.re.rep_catch.cont = cont;
+ catcher.re.rep_catch.beg = s;
+ catcher.re.rep_catch.n = n + 1;
+ catcher.next = rex->next;
+ if (n == 0)
+ rex->re.rep_catch.beg = s;
+ if (env->stack)
+ {
+ if (matchpush(env, rex))
+ return BAD;
+ if (pospush(env, rex, s, BEG_ONE))
+ return BAD;
+DEBUG_TEST(0x0004,(sfprintf(sfstdout,"AHA#%04d 0x%04x PUSH %d (%d,%d)(%d,%d)(%d,%d) (%d,%d)(%d,%d)(%d,%d)\n", __LINE__, debug_flag, rex->re.group.number, env->best[0].rm_so, env->best[0].rm_eo, env->best[1].rm_so, env->best[1].rm_eo, env->best[2].rm_so, env->best[2].rm_eo, env->match[0].rm_so, env->match[0].rm_eo, env->match[1].rm_so, env->match[1].rm_eo, env->match[2].rm_so, env->match[2].rm_eo)),(0));
+ }
+ r = parse(env, rex->re.group.expr.rex, &catcher, s);
+ DEBUG_TEST(0x0010,(sfprintf(sfstdout, "AHA#%04d 0x%04x parserep parse %d %d `%-.*s'\n", __LINE__, debug_flag, rex->re.group.number, r, env->end - s, s)),(0));
+ if (env->stack)
+ {
+ pospop(env);
+ matchpop(env, rex);
+DEBUG_TEST(0x0004,(sfprintf(sfstdout,"AHA#%04d 0x%04x POP %d %d (%d,%d)(%d,%d)(%d,%d) (%d,%d)(%d,%d)(%d,%d)\n", __LINE__, debug_flag, rex->re.group.number, r, env->best[0].rm_so, env->best[0].rm_eo, env->best[1].rm_so, env->best[1].rm_eo, env->best[2].rm_so, env->best[2].rm_eo, env->match[0].rm_so, env->match[0].rm_eo, env->match[1].rm_so, env->match[1].rm_eo, env->match[2].rm_so, env->match[2].rm_eo)),(0));
+ }
+ switch (r)
+ {
+ case BAD:
+ return BAD;
+ case BEST:
+ return BEST;
+ case CUT:
+ r = NONE;
+ break;
+ case GOOD:
+ if (rex->flags & REG_MINIMAL)
+ return BEST;
+ r = GOOD;
+ break;
+ }
+ }
+ if (n < rex->lo)
+ return r;
+ if (!(rex->flags & REG_MINIMAL) || n >= rex->hi)
+ {
+ if (env->stack && pospush(env, rex, s, END_ANY))
+ return BAD;
+ i = follow(env, rex, cont, s);
+ if (env->stack)
+ pospop(env);
+ switch (i)
+ {
+ case BAD:
+ r = BAD;
+ break;
+ case CUT:
+ r = CUT;
+ break;
+ case BEST:
+ r = BEST;
+ break;
+ case GOOD:
+ r = (rex->flags & REG_MINIMAL) ? BEST : GOOD;
+ break;
+ }
+ }
+ return r;
+}
+
+static int
+parsetrie(Env_t* env, Trie_node_t* x, Rex_t* rex, Rex_t* cont, unsigned char* s)
+{
+ unsigned char* p;
+ int r;
+
+ if (p = rex->map)
+ {
+ for (;;)
+ {
+ if (s >= env->end)
+ return NONE;
+ while (x->c != p[*s])
+ if (!(x = x->sib))
+ return NONE;
+ if (x->end)
+ break;
+ x = x->son;
+ s++;
+ }
+ }
+ else
+ {
+ for (;;)
+ {
+ if (s >= env->end)
+ return NONE;
+ while (x->c != *s)
+ if (!(x = x->sib))
+ return NONE;
+ if (x->end)
+ break;
+ x = x->son;
+ s++;
+ }
+ }
+ s++;
+ if (rex->flags & REG_MINIMAL)
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ case GOOD:
+ return BEST;
+ }
+ if (x->son)
+ switch (parsetrie(env, x->son, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ return BEST;
+ case GOOD:
+ if (rex->flags & REG_MINIMAL)
+ return BEST;
+ r = GOOD;
+ break;
+ default:
+ r = NONE;
+ break;
+ }
+ else
+ r = NONE;
+ if (!(rex->flags & REG_MINIMAL))
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ return BEST;
+ case GOOD:
+ return GOOD;
+ }
+ return r;
+}
+
+static int
+collelt(register Celt_t* ce, char* key, int c, int x)
+{
+ Ckey_t elt;
+
+ mbxfrm(elt, key, COLL_KEY_MAX);
+ for (;; ce++)
+ {
+ switch (ce->typ)
+ {
+ case COLL_call:
+ if (!x && (*ce->fun)(c))
+ return 1;
+ continue;
+ case COLL_char:
+ if (!strcmp((char*)ce->beg, (char*)elt))
+ return 1;
+ continue;
+ case COLL_range:
+ if (strcmp((char*)ce->beg, (char*)elt) <= ce->min && strcmp((char*)elt, (char*)ce->end) <= ce->max)
+ return 1;
+ continue;
+ case COLL_range_lc:
+ if (strcmp((char*)ce->beg, (char*)elt) <= ce->min && strcmp((char*)elt, (char*)ce->end) <= ce->max && (iswlower(c) || !iswupper(c)))
+ return 1;
+ continue;
+ case COLL_range_uc:
+ if (strcmp((char*)ce->beg, (char*)elt) <= ce->min && strcmp((char*)elt, (char*)ce->end) <= ce->max && (iswupper(c) || !iswlower(c)))
+ return 1;
+ continue;
+ }
+ break;
+ }
+ return 0;
+}
+
+static int
+collic(register Celt_t* ce, char* key, register char* nxt, int c, int x)
+{
+ if (!x)
+ {
+ if (collelt(ce, key, c, x))
+ return 1;
+ if (iswlower(c))
+ c = towupper(c);
+ else if (iswupper(c))
+ c = towlower(c);
+ else
+ return 0;
+ x = mbconv(key, c);
+ key[x] = 0;
+ return collelt(ce, key, c, 0);
+ }
+ while (*nxt)
+ {
+ if (collic(ce, key, nxt + 1, c, x))
+ return 1;
+ if (islower(*nxt))
+ *nxt = toupper(*nxt);
+ else if (isupper(*nxt))
+ *nxt = tolower(*nxt);
+ else
+ return 0;
+ nxt++;
+ }
+ return collelt(ce, key, c, x);
+}
+
+static int
+collmatch(Rex_t* rex, unsigned char* s, unsigned char* e, unsigned char** p)
+{
+ unsigned char* t;
+ wchar_t c;
+ int w;
+ int r;
+ int x;
+ int ic;
+ Ckey_t key;
+ Ckey_t elt;
+
+ ic = (rex->flags & REG_ICASE);
+ if ((w = MBSIZE(s)) > 1)
+ {
+ memcpy((char*)key, (char*)s, w);
+ key[w] = 0;
+ t = s;
+ c = mbchar(t);
+#if !_lib_wctype
+ c &= 0xff;
+#endif
+ x = 0;
+ }
+ else
+ {
+ c = s[0];
+ if (ic && isupper(c))
+ c = tolower(c);
+ key[0] = c;
+ key[1] = 0;
+ if (isalpha(c))
+ {
+ x = e - s;
+ if (x > COLL_KEY_MAX)
+ x = COLL_KEY_MAX;
+ while (w < x)
+ {
+ c = s[w];
+ if (!isalpha(c))
+ break;
+ r = mbxfrm(elt, key, COLL_KEY_MAX);
+ if (ic && isupper(c))
+ c = tolower(c);
+ key[w] = c;
+ key[w + 1] = 0;
+ if (mbxfrm(elt, key, COLL_KEY_MAX) != r)
+ break;
+ w++;
+ }
+ }
+ key[w] = 0;
+ c = key[0];
+ x = w - 1;
+ }
+ r = 1;
+ for (;;)
+ {
+ if (ic ? collic(rex->re.collate.elements, (char*)key, (char*)key, c, x) : collelt(rex->re.collate.elements, (char*)key, c, x))
+ break;
+ if (!x)
+ {
+ r = 0;
+ break;
+ }
+ w = x--;
+ key[w] = 0;
+ }
+ *p = s + w;
+ return rex->re.collate.invert ? !r : r;
+}
+
+static unsigned char*
+nestmatch(register unsigned char* s, register unsigned char* e, const unsigned short* type, register int co)
+{
+ register int c;
+ register int cc;
+ unsigned int n;
+ int oc;
+
+ if (type[co] & (REX_NEST_literal|REX_NEST_quote))
+ {
+ n = (type[co] & REX_NEST_literal) ? REX_NEST_terminator : (REX_NEST_escape|REX_NEST_terminator);
+ while (s < e)
+ {
+ c = *s++;
+ if (c == co)
+ return s;
+ else if (type[c] & n)
+ {
+ if (s >= e || (type[c] & REX_NEST_terminator))
+ break;
+ s++;
+ }
+ }
+ }
+ else
+ {
+ cc = type[co] >> REX_NEST_SHIFT;
+ oc = type[co] & (REX_NEST_open|REX_NEST_close);
+ n = 1;
+ while (s < e)
+ {
+ c = *s++;
+ switch (type[c] & (REX_NEST_escape|REX_NEST_open|REX_NEST_close|REX_NEST_delimiter|REX_NEST_separator|REX_NEST_terminator))
+ {
+ case REX_NEST_delimiter:
+ case REX_NEST_terminator:
+ return oc ? 0 : s;
+ case REX_NEST_separator:
+ if (!oc)
+ return s;
+ break;
+ case REX_NEST_escape:
+ if (s >= e)
+ return 0;
+ s++;
+ break;
+ case REX_NEST_open|REX_NEST_close:
+ if (c == cc)
+ {
+ if (!--n)
+ return s;
+ }
+ /*FALLTHROUGH*/
+ case REX_NEST_open:
+ if (c == co)
+ {
+ if (!++n)
+ return 0;
+ }
+ else if (!(s = nestmatch(s, e, type, c)))
+ return 0;
+ break;
+ case REX_NEST_close:
+ if (c != cc)
+ return 0;
+ if (!--n)
+ return s;
+ break;
+ }
+ }
+ return (oc || !(type[UCHAR_MAX+1] & REX_NEST_terminator)) ? 0 : s;
+ }
+ return 0;
+}
+
+static int
+parse(Env_t* env, Rex_t* rex, Rex_t* cont, unsigned char* s)
+{
+ int c;
+ int d;
+ int i;
+ int m;
+ int n;
+ int r;
+ int* f;
+ unsigned char* p;
+ unsigned char* t;
+ unsigned char* b;
+ unsigned char* e;
+ char* u;
+ regmatch_t* o;
+ Trie_node_t* x;
+ Rex_t* q;
+ Rex_t catcher;
+ Rex_t next;
+
+ for (;;)
+ {
+DEBUG_TEST(0x0008,(sfprintf(sfstdout, "AHA#%04d 0x%04x parse %s `%-.*s'\n", __LINE__, debug_flag, rexname(rex), env->end - s, s)),(0));
+ switch (rex->type)
+ {
+ case REX_ALT:
+ if (env->stack)
+ {
+ if (matchpush(env, rex))
+ return BAD;
+ if (pospush(env, rex, s, BEG_ALT))
+ return BAD;
+ catcher.type = REX_ALT_CATCH;
+ catcher.serial = rex->serial;
+ catcher.re.alt_catch.cont = cont;
+ catcher.next = rex->next;
+ r = parse(env, rex->re.group.expr.binary.left, &catcher, s);
+ if (r < BEST || (rex->flags & REG_MINIMAL))
+ {
+ matchcopy(env, rex);
+ ((Pos_t*)env->pos->vec + env->pos->cur - 1)->serial = catcher.serial = rex->re.group.expr.binary.serial;
+ n = parse(env, rex->re.group.expr.binary.right, &catcher, s);
+ if (n != NONE)
+ r = n;
+ }
+ pospop(env);
+ matchpop(env, rex);
+ }
+ else
+ {
+ if ((r = parse(env, rex->re.group.expr.binary.left, cont, s)) == NONE)
+ r = parse(env, rex->re.group.expr.binary.right, cont, s);
+ if (r == GOOD)
+ r = BEST;
+ }
+ return r;
+ case REX_ALT_CATCH:
+ if (pospush(env, rex, s, END_ANY))
+ return BAD;
+ r = follow(env, rex, rex->re.alt_catch.cont, s);
+ pospop(env);
+ return r;
+ case REX_BACK:
+ o = &env->match[rex->lo];
+ if (o->rm_so < 0)
+ return NONE;
+ i = o->rm_eo - o->rm_so;
+ e = s + i;
+ if (e > env->end)
+ return NONE;
+ t = env->beg + o->rm_so;
+ if (!(p = rex->map))
+ {
+ while (s < e)
+ if (*s++ != *t++)
+ return NONE;
+ }
+ else if (!mbwide())
+ {
+ while (s < e)
+ if (p[*s++] != p[*t++])
+ return NONE;
+ }
+ else
+ {
+ while (s < e)
+ {
+ c = mbchar(s);
+ d = mbchar(t);
+ if (towupper(c) != towupper(d))
+ return NONE;
+ }
+ }
+ break;
+ case REX_BEG:
+ if ((!(rex->flags & REG_NEWLINE) || s <= env->beg || *(s - 1) != '\n') && ((env->flags & REG_NOTBOL) || s != env->beg))
+ return NONE;
+ break;
+ case REX_CLASS:
+ if (LEADING(env, rex, s))
+ return NONE;
+ n = rex->hi;
+ if (n > env->end - s)
+ n = env->end - s;
+ m = rex->lo;
+ if (m > n)
+ return NONE;
+ r = NONE;
+ if (!(rex->flags & REG_MINIMAL))
+ {
+ for (i = 0; i < n; i++)
+ if (!settst(rex->re.charclass, s[i]))
+ {
+ n = i;
+ break;
+ }
+ for (s += n; n-- >= m; s--)
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ return BEST;
+ case GOOD:
+ r = GOOD;
+ break;
+ }
+ }
+ else
+ {
+ for (e = s + m; s < e; s++)
+ if (!settst(rex->re.charclass, *s))
+ return r;
+ e += n - m;
+ for (;;)
+ {
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ case GOOD:
+ return BEST;
+ }
+ if (s >= e || !settst(rex->re.charclass, *s))
+ break;
+ s++;
+ }
+ }
+ return r;
+ case REX_COLL_CLASS:
+ if (LEADING(env, rex, s))
+ return NONE;
+ n = rex->hi;
+ if (n > env->end - s)
+ n = env->end - s;
+ m = rex->lo;
+ if (m > n)
+ return NONE;
+ r = NONE;
+ e = env->end;
+ if (!(rex->flags & REG_MINIMAL))
+ {
+ if (!(b = (unsigned char*)stkpush(stkstd, n)))
+ {
+ env->error = REG_ESPACE;
+ return BAD;
+ }
+ for (i = 0; s < e && i < n && collmatch(rex, s, e, &t); i++)
+ {
+ b[i] = t - s;
+ s = t;
+ }
+ for (; i-- >= rex->lo; s -= b[i])
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ stkpop(stkstd);
+ return BAD;
+ case CUT:
+ stkpop(stkstd);
+ return CUT;
+ case BEST:
+ stkpop(stkstd);
+ return BEST;
+ case GOOD:
+ r = GOOD;
+ break;
+ }
+ stkpop(stkstd);
+ }
+ else
+ {
+ for (i = 0; i < m && s < e; i++, s = t)
+ if (!collmatch(rex, s, e, &t))
+ return r;
+ while (i++ <= n)
+ {
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ case GOOD:
+ return BEST;
+ }
+ if (s >= e || !collmatch(rex, s, e, &s))
+ break;
+ }
+ }
+ return r;
+ case REX_CONJ:
+ next.type = REX_CONJ_RIGHT;
+ next.re.conj_right.cont = cont;
+ next.next = rex->next;
+ catcher.type = REX_CONJ_LEFT;
+ catcher.re.conj_left.right = rex->re.group.expr.binary.right;
+ catcher.re.conj_left.cont = &next;
+ catcher.re.conj_left.beg = s;
+ catcher.next = 0;
+ return parse(env, rex->re.group.expr.binary.left, &catcher, s);
+ case REX_CONJ_LEFT:
+ rex->re.conj_left.cont->re.conj_right.end = s;
+ cont = rex->re.conj_left.cont;
+ s = rex->re.conj_left.beg;
+ rex = rex->re.conj_left.right;
+ continue;
+ case REX_CONJ_RIGHT:
+ if (rex->re.conj_right.end != s)
+ return NONE;
+ cont = rex->re.conj_right.cont;
+ break;
+ case REX_DONE:
+ if (!env->stack)
+ return BEST;
+ n = s - env->beg;
+ r = env->nsub;
+ DEBUG_TEST(0x0100,(sfprintf(sfstdout,"AHA#%04d 0x%04x %s (%d,%d)(%d,%d)(%d,%d)(%d,%d) (%d,%d)(%d,%d)\n", __LINE__, debug_flag, rexname(rex), env->best[0].rm_so, env->best[0].rm_eo, env->best[1].rm_so, env->best[1].rm_eo, env->best[2].rm_so, env->best[2].rm_eo, env->best[3].rm_so, env->best[3].rm_eo, env->match[0].rm_so, env->match[0].rm_eo, env->match[1].rm_so, env->match[1].rm_eo)),(0));
+ if ((i = env->best[0].rm_eo) >= 0)
+ {
+ if (rex->flags & REG_MINIMAL)
+ {
+ if (n > i)
+ return GOOD;
+ }
+ else
+ {
+ if (n < i)
+ return GOOD;
+ }
+ if (n == i && better(env,
+ (Pos_t*)env->bestpos->vec,
+ (Pos_t*)env->pos->vec,
+ (Pos_t*)env->bestpos->vec+env->bestpos->cur,
+ (Pos_t*)env->pos->vec+env->pos->cur,
+ 0) <= 0)
+ return GOOD;
+ }
+ env->best[0].rm_eo = n;
+ memcpy(&env->best[1], &env->match[1], r * sizeof(regmatch_t));
+ n = env->pos->cur;
+ if (!vector(Pos_t, env->bestpos, n))
+ {
+ env->error = REG_ESPACE;
+ return BAD;
+ }
+ env->bestpos->cur = n;
+ memcpy(env->bestpos->vec, env->pos->vec, n * sizeof(Pos_t));
+ DEBUG_TEST(0x0100,(sfprintf(sfstdout,"AHA#%04d 0x%04x %s (%d,%d)(%d,%d)(%d,%d)(%d,%d) (%d,%d)(%d,%d)\n", __LINE__, debug_flag, rexname(rex), env->best[0].rm_so, env->best[0].rm_eo, env->best[1].rm_so, env->best[1].rm_eo, env->best[2].rm_so, env->best[2].rm_eo, env->best[3].rm_so, env->best[3].rm_eo, env->match[0].rm_so, env->match[0].rm_eo, env->match[1].rm_so, env->match[1].rm_eo)),(0));
+ return GOOD;
+ case REX_DOT:
+ if (LEADING(env, rex, s))
+ return NONE;
+ n = rex->hi;
+ if (n > env->end - s)
+ n = env->end - s;
+ m = rex->lo;
+ if (m > n)
+ return NONE;
+ if ((c = rex->explicit) >= 0 && !mbwide())
+ for (i = 0; i < n; i++)
+ if (s[i] == c)
+ {
+ n = i;
+ break;
+ }
+ r = NONE;
+ if (!(rex->flags & REG_MINIMAL))
+ {
+ if (!mbwide())
+ {
+ for (s += n; n-- >= m; s--)
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ return BEST;
+ case GOOD:
+ r = GOOD;
+ break;
+ }
+ }
+ else
+ {
+ if (!(b = (unsigned char*)stkpush(stkstd, n)))
+ {
+ env->error = REG_ESPACE;
+ return BAD;
+ }
+ e = env->end;
+ for (i = 0; s < e && i < n && *s != c; i++)
+ s += b[i] = MBSIZE(s);
+ for (; i-- >= m; s -= b[i])
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ stkpop(stkstd);
+ return BAD;
+ case CUT:
+ stkpop(stkstd);
+ return CUT;
+ case BEST:
+ stkpop(stkstd);
+ return BEST;
+ case GOOD:
+ r = GOOD;
+ break;
+ }
+ stkpop(stkstd);
+ }
+ }
+ else
+ {
+ if (!mbwide())
+ {
+ e = s + n;
+ for (s += m; s <= e; s++)
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ case GOOD:
+ return BEST;
+ }
+ }
+ else
+ {
+ e = env->end;
+ for (i = 0; s < e && i < m && *s != c; i++)
+ s += MBSIZE(s);
+ if (i >= m)
+ for (; s <= e && i <= n; s += MBSIZE(s), i++)
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ case GOOD:
+ return BEST;
+ }
+ }
+ }
+ return r;
+ case REX_END:
+ if ((!(rex->flags & REG_NEWLINE) || *s != '\n') && ((env->flags & REG_NOTEOL) || s < env->end))
+ return NONE;
+ break;
+ case REX_GROUP:
+DEBUG_TEST(0x0200,(sfprintf(sfstdout,"AHA#%04d 0x%04x parse %s `%-.*s'\n", __LINE__, debug_flag, rexname(rex), env->end - s, s)),(0));
+ if (env->stack)
+ {
+ if (rex->re.group.number)
+ env->match[rex->re.group.number].rm_so = s - env->beg;
+ if (pospush(env, rex, s, BEG_SUB))
+ return BAD;
+ catcher.re.group_catch.eo = rex->re.group.number ? &env->match[rex->re.group.number].rm_eo : (regoff_t*)0;
+ }
+ catcher.type = REX_GROUP_CATCH;
+ catcher.serial = rex->serial;
+ catcher.re.group_catch.cont = cont;
+ catcher.next = rex->next;
+ r = parse(env, rex->re.group.expr.rex, &catcher, s);
+ if (env->stack)
+ {
+ pospop(env);
+ if (rex->re.group.number)
+ env->match[rex->re.group.number].rm_so = -1;
+ }
+ return r;
+ case REX_GROUP_CATCH:
+DEBUG_TEST(0x0200,(sfprintf(sfstdout,"AHA#%04d 0x%04x parse %s=>%s `%-.*s'\n", __LINE__, debug_flag, rexname(rex), rexname(rex->re.group_catch.cont), env->end - s, s)),(0));
+ if (env->stack)
+ {
+ if (rex->re.group_catch.eo)
+ *rex->re.group_catch.eo = s - env->beg;
+ if (pospush(env, rex, s, END_ANY))
+ return BAD;
+ }
+ r = follow(env, rex, rex->re.group_catch.cont, s);
+ if (env->stack)
+ {
+ pospop(env);
+ if (rex->re.group_catch.eo)
+ *rex->re.group_catch.eo = -1;
+ }
+ return r;
+ case REX_GROUP_AHEAD:
+ catcher.type = REX_GROUP_AHEAD_CATCH;
+ catcher.flags = rex->flags;
+ catcher.serial = rex->serial;
+ catcher.re.rep_catch.beg = s;
+ catcher.re.rep_catch.cont = cont;
+ catcher.next = rex->next;
+ return parse(env, rex->re.group.expr.rex, &catcher, s);
+ case REX_GROUP_AHEAD_CATCH:
+ return follow(env, rex, rex->re.rep_catch.cont, rex->re.rep_catch.beg);
+ case REX_GROUP_AHEAD_NOT:
+ r = parse(env, rex->re.group.expr.rex, NiL, s);
+ if (r == NONE)
+ r = follow(env, rex, cont, s);
+ else if (r != BAD)
+ r = NONE;
+ return r;
+ case REX_GROUP_BEHIND:
+ if ((s - env->beg) < rex->re.group.size)
+ return NONE;
+ catcher.type = REX_GROUP_BEHIND_CATCH;
+ catcher.flags = rex->flags;
+ catcher.serial = rex->serial;
+ catcher.re.behind_catch.beg = s;
+ catcher.re.behind_catch.end = e = env->end;
+ catcher.re.behind_catch.cont = cont;
+ catcher.next = rex->next;
+ for (t = s - rex->re.group.size; t >= env->beg; t--)
+ {
+ env->end = s;
+ r = parse(env, rex->re.group.expr.rex, &catcher, t);
+ env->end = e;
+ if (r != NONE)
+ return r;
+ }
+ return NONE;
+ case REX_GROUP_BEHIND_CATCH:
+ if (s != rex->re.behind_catch.beg)
+ return NONE;
+ env->end = rex->re.behind_catch.end;
+ return follow(env, rex, rex->re.behind_catch.cont, rex->re.behind_catch.beg);
+ case REX_GROUP_BEHIND_NOT:
+ if ((s - env->beg) < rex->re.group.size)
+ r = NONE;
+ else
+ {
+ catcher.type = REX_GROUP_BEHIND_NOT_CATCH;
+ catcher.re.neg_catch.beg = s;
+ catcher.next = 0;
+ e = env->end;
+ env->end = s;
+ for (t = s - rex->re.group.size; t >= env->beg; t--)
+ {
+ r = parse(env, rex->re.group.expr.rex, &catcher, t);
+ if (r != NONE)
+ break;
+ }
+ env->end = e;
+ }
+ if (r == NONE)
+ r = follow(env, rex, cont, s);
+ else if (r != BAD)
+ r = NONE;
+ return r;
+ case REX_GROUP_BEHIND_NOT_CATCH:
+ return s == rex->re.neg_catch.beg ? GOOD : NONE;
+ case REX_GROUP_COND:
+ if (q = rex->re.group.expr.binary.right)
+ {
+ catcher.re.cond_catch.next[0] = q->re.group.expr.binary.right;
+ catcher.re.cond_catch.next[1] = q->re.group.expr.binary.left;
+ }
+ else
+ catcher.re.cond_catch.next[0] = catcher.re.cond_catch.next[1] = 0;
+ if (q = rex->re.group.expr.binary.left)
+ {
+ catcher.type = REX_GROUP_COND_CATCH;
+ catcher.flags = rex->flags;
+ catcher.serial = rex->serial;
+ catcher.re.cond_catch.yes = 0;
+ catcher.re.cond_catch.beg = s;
+ catcher.re.cond_catch.cont = cont;
+ catcher.next = rex->next;
+ r = parse(env, q, &catcher, s);
+ if (r == BAD || catcher.re.cond_catch.yes)
+ return r;
+ }
+ else if (!rex->re.group.size || rex->re.group.size > 0 && env->match[rex->re.group.size].rm_so >= 0)
+ r = GOOD;
+ else
+ r = NONE;
+ if (q = catcher.re.cond_catch.next[r != NONE])
+ {
+ catcher.type = REX_CAT;
+ catcher.flags = q->flags;
+ catcher.serial = q->serial;
+ catcher.re.group_catch.cont = cont;
+ catcher.next = rex->next;
+ return parse(env, q, &catcher, s);
+ }
+ return follow(env, rex, cont, s);
+ case REX_GROUP_COND_CATCH:
+ rex->re.cond_catch.yes = 1;
+ catcher.type = REX_CAT;
+ catcher.flags = rex->flags;
+ catcher.serial = rex->serial;
+ catcher.re.group_catch.cont = rex->re.cond_catch.cont;
+ catcher.next = rex->next;
+ return parse(env, rex->re.cond_catch.next[1], &catcher, rex->re.cond_catch.beg);
+ case REX_CAT:
+ return follow(env, rex, rex->re.group_catch.cont, s);
+ case REX_GROUP_CUT:
+ catcher.type = REX_GROUP_CUT_CATCH;
+ catcher.flags = rex->flags;
+ catcher.serial = rex->serial;
+ catcher.re.group_catch.cont = cont;
+ catcher.next = rex->next;
+ return parse(env, rex->re.group.expr.rex, &catcher, s);
+ case REX_GROUP_CUT_CATCH:
+ switch (r = follow(env, rex, rex->re.group_catch.cont, s))
+ {
+ case GOOD:
+ r = BEST;
+ break;
+ case NONE:
+ r = CUT;
+ break;
+ }
+ return r;
+ case REX_KMP:
+ f = rex->re.string.fail;
+ b = rex->re.string.base;
+ n = rex->re.string.size;
+ t = s;
+ e = env->end;
+ if (p = rex->map)
+ {
+ while (t + n <= e)
+ {
+ for (i = -1; t < e; t++)
+ {
+ while (i >= 0 && b[i+1] != p[*t])
+ i = f[i];
+ if (b[i+1] == p[*t])
+ i++;
+ if (i + 1 == n)
+ {
+ t++;
+ if (env->stack)
+ env->best[0].rm_so = t - s - n;
+ switch (follow(env, rex, cont, t))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ case GOOD:
+ return BEST;
+ }
+ t -= n - 1;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ while (t + n <= e)
+ {
+ for (i = -1; t < e; t++)
+ {
+ while (i >= 0 && b[i+1] != *t)
+ i = f[i];
+ if (b[i+1] == *t)
+ i++;
+ if (i + 1 == n)
+ {
+ t++;
+ if (env->stack)
+ env->best[0].rm_so = t - s - n;
+ switch (follow(env, rex, cont, t))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ case GOOD:
+ return BEST;
+ }
+ t -= n - 1;
+ break;
+ }
+ }
+ }
+ }
+ return NONE;
+ case REX_NEG:
+ if (LEADING(env, rex, s))
+ return NONE;
+ i = env->end - s;
+ n = ((i + 7) >> 3) + 1;
+ catcher.type = REX_NEG_CATCH;
+ catcher.re.neg_catch.beg = s;
+ if (!(p = (unsigned char*)stkpush(stkstd, n)))
+ return BAD;
+ memset(catcher.re.neg_catch.index = p, 0, n);
+ catcher.next = rex->next;
+ if (parse(env, rex->re.group.expr.rex, &catcher, s) == BAD)
+ r = BAD;
+ else
+ {
+ r = NONE;
+ for (; i >= 0; i--)
+ if (!bittst(p, i))
+ {
+ switch (follow(env, rex, cont, s + i))
+ {
+ case BAD:
+ r = BAD;
+ break;
+ case BEST:
+ r = BEST;
+ break;
+ case CUT:
+ r = CUT;
+ break;
+ case GOOD:
+ r = GOOD;
+ /*FALLTHROUGH*/
+ default:
+ continue;
+ }
+ break;
+ }
+ }
+ stkpop(stkstd);
+ return r;
+ case REX_NEG_CATCH:
+ bitset(rex->re.neg_catch.index, s - rex->re.neg_catch.beg);
+ return NONE;
+ case REX_NEST:
+ if (s >= env->end)
+ return NONE;
+ do
+ {
+ if ((c = *s++) == rex->re.nest.primary)
+ {
+ if (s >= env->end || !(s = nestmatch(s, env->end, rex->re.nest.type, c)))
+ return NONE;
+ break;
+ }
+ if (rex->re.nest.primary >= 0)
+ return NONE;
+ if (rex->re.nest.type[c] & (REX_NEST_delimiter|REX_NEST_separator|REX_NEST_terminator))
+ break;
+ if (!(s = nestmatch(s, env->end, rex->re.nest.type, c)))
+ return NONE;
+ } while (s < env->end && !(rex->re.nest.type[*(s-1)] & (REX_NEST_delimiter|REX_NEST_separator|REX_NEST_terminator)));
+ break;
+ case REX_NULL:
+ break;
+ case REX_ONECHAR:
+ n = rex->hi;
+ if (n > env->end - s)
+ n = env->end - s;
+ m = rex->lo;
+ if (m > n)
+ return NONE;
+ r = NONE;
+ c = rex->re.onechar;
+ if (!(rex->flags & REG_MINIMAL))
+ {
+ if (!mbwide())
+ {
+ if (p = rex->map)
+ {
+ for (i = 0; i < n; i++, s++)
+ if (p[*s] != c)
+ break;
+ }
+ else
+ {
+ for (i = 0; i < n; i++, s++)
+ if (*s != c)
+ break;
+ }
+ for (; i-- >= m; s--)
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case BEST:
+ return BEST;
+ case CUT:
+ return CUT;
+ case GOOD:
+ r = GOOD;
+ break;
+ }
+ }
+ else
+ {
+ if (!(b = (unsigned char*)stkpush(stkstd, n)))
+ {
+ env->error = REG_ESPACE;
+ return BAD;
+ }
+ e = env->end;
+ if (!(rex->flags & REG_ICASE))
+ {
+ for (i = 0; s < e && i < n; i++, s = t)
+ {
+ t = s;
+ if (mbchar(t) != c)
+ break;
+ b[i] = t - s;
+ }
+ }
+ else
+ {
+ for (i = 0; s < e && i < n; i++, s = t)
+ {
+ t = s;
+ if (towupper(mbchar(t)) != c)
+ break;
+ b[i] = t - s;
+ }
+ }
+ for (; i-- >= m; s -= b[i])
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ stkpop(stkstd);
+ return BAD;
+ case BEST:
+ stkpop(stkstd);
+ return BEST;
+ case CUT:
+ stkpop(stkstd);
+ return CUT;
+ case GOOD:
+ r = GOOD;
+ break;
+ }
+ stkpop(stkstd);
+ }
+ }
+ else
+ {
+ if (!mbwide())
+ {
+ e = s + m;
+ if (p = rex->map)
+ {
+ for (; s < e; s++)
+ if (p[*s] != c)
+ return r;
+ e += n - m;
+ for (;;)
+ {
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ case GOOD:
+ return BEST;
+ }
+ if (s >= e || p[*s++] != c)
+ break;
+ }
+ }
+ else
+ {
+ for (; s < e; s++)
+ if (*s != c)
+ return r;
+ e += n - m;
+ for (;;)
+ {
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ case GOOD:
+ return BEST;
+ }
+ if (s >= e || *s++ != c)
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (!(rex->flags & REG_ICASE))
+ {
+ for (i = 0; i < m && s < e; i++, s = t)
+ {
+ t = s;
+ if (mbchar(t) != c)
+ return r;
+ }
+ while (i++ <= n)
+ {
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ case GOOD:
+ return BEST;
+ }
+ if (s >= e || mbchar(s) != c)
+ break;
+ }
+ }
+ else
+ {
+ for (i = 0; i < m && s < e; i++, s = t)
+ {
+ t = s;
+ if (towupper(mbchar(t)) != c)
+ return r;
+ }
+ while (i++ <= n)
+ {
+ switch (follow(env, rex, cont, s))
+ {
+ case BAD:
+ return BAD;
+ case CUT:
+ return CUT;
+ case BEST:
+ case GOOD:
+ return BEST;
+ }
+ if (s >= e || towupper(mbchar(s)) != c)
+ break;
+ }
+ }
+ }
+ }
+ return r;
+ case REX_REP:
+ if (env->stack && pospush(env, rex, s, BEG_REP))
+ return BAD;
+ r = parserep(env, rex, cont, s, 0);
+ if (env->stack)
+ pospop(env);
+ return r;
+ case REX_REP_CATCH:
+ DEBUG_TEST(0x0020,(sfprintf(sfstdout, "AHA#%04d 0x%04x %s n %d len %d s `%-.*s'\n", __LINE__, debug_flag, rexname(rex), rex->re.rep_catch.n, s - rex->re.rep_catch.beg, env->end - s, s)),(0));
+ if (env->stack && pospush(env, rex, s, END_ANY))
+ return BAD;
+ if (s == rex->re.rep_catch.beg && rex->re.rep_catch.n > rex->re.rep_catch.ref->lo)
+ {
+ /*
+ * optional empty iteration
+ */
+
+DEBUG_TEST(0x0002,(sfprintf(sfstdout, "AHA#%04d %p re.group.back=%d re.group.expr.rex=%s\n", __LINE__, rex->re.rep_catch.ref->re.group.expr.rex, rex->re.rep_catch.ref->re.group.expr.rex->re.group.back, rexname(rex->re.rep_catch.ref->re.group.expr.rex))),(0));
+ if (!env->stack || s != rex->re.rep_catch.ref->re.rep_catch.beg && !rex->re.rep_catch.ref->re.group.expr.rex->re.group.back)
+ r = NONE;
+ else if (pospush(env, rex, s, END_ANY))
+ r = BAD;
+ else
+ {
+ r = follow(env, rex, rex->re.rep_catch.cont, s);
+ pospop(env);
+ }
+ }
+ else
+ r = parserep(env, rex->re.rep_catch.ref, rex->re.rep_catch.cont, s, rex->re.rep_catch.n);
+ if (env->stack)
+ pospop(env);
+ return r;
+ case REX_STRING:
+DEBUG_TEST(0x0200,(sfprintf(sfstdout,"AHA#%04d 0x%04x parse %s \"%-.*s\" `%-.*s'\n", __LINE__, debug_flag, rexname(rex), rex->re.string.size, rex->re.string.base, env->end - s, s)),(0));
+ if (rex->re.string.size > (env->end - s))
+ return NONE;
+ t = rex->re.string.base;
+ e = t + rex->re.string.size;
+ if (!(p = rex->map))
+ {
+ while (t < e)
+ if (*s++ != *t++)
+ return NONE;
+ }
+ else if (!mbwide())
+ {
+ while (t < e)
+ if (p[*s++] != *t++)
+ return NONE;
+ }
+ else
+ {
+ while (t < e)
+ {
+ c = mbchar(s);
+ d = mbchar(t);
+ if (towupper(c) != d)
+ return NONE;
+ }
+ }
+ break;
+ case REX_TRIE:
+ if (((s + rex->re.trie.min) > env->end) || !(x = rex->re.trie.root[rex->map ? rex->map[*s] : *s]))
+ return NONE;
+ return parsetrie(env, x, rex, cont, s);
+ case REX_EXEC:
+ u = 0;
+ r = (*env->disc->re_execf)(env->regex, rex->re.exec.data, rex->re.exec.text, rex->re.exec.size, (const char*)s, env->end - s, &u, env->disc);
+ e = (unsigned char*)u;
+ if (e >= s && e <= env->end)
+ s = e;
+ switch (r)
+ {
+ case 0:
+ break;
+ case REG_NOMATCH:
+ return NONE;
+ default:
+ env->error = r;
+ return BAD;
+ }
+ break;
+ case REX_WBEG:
+ if (!isword(*s) || s > env->beg && isword(*(s - 1)))
+ return NONE;
+ break;
+ case REX_WEND:
+ if (isword(*s) || s > env->beg && !isword(*(s - 1)))
+ return NONE;
+ break;
+ case REX_WORD:
+ if (s > env->beg && isword(*(s - 1)) == isword(*s))
+ return NONE;
+ break;
+ case REX_WORD_NOT:
+ if (s == env->beg || isword(*(s - 1)) != isword(*s))
+ return NONE;
+ break;
+ case REX_BEG_STR:
+ if (s != env->beg)
+ return NONE;
+ break;
+ case REX_END_STR:
+ for (t = s; t < env->end && *t == '\n'; t++);
+ if (t < env->end)
+ return NONE;
+ break;
+ case REX_FIN_STR:
+ if (s < env->end)
+ return NONE;
+ break;
+ }
+ if (!(rex = rex->next))
+ {
+ if (!(rex = cont))
+ break;
+ cont = 0;
+ }
+ }
+ return GOOD;
+}
+
+#if _AST_REGEX_DEBUG
+
+static void
+listnode(Rex_t* e, int level)
+{
+ int i;
+
+ if (e)
+ {
+ do
+ {
+ for (i = 0; i < level; i++)
+ sfprintf(sfstderr, " ");
+ sfprintf(sfstderr, "%s\n", rexname(e));
+ switch (e->type)
+ {
+ case REX_ALT:
+ case REX_CONJ:
+ listnode(e->re.group.expr.binary.left, level + 1);
+ listnode(e->re.group.expr.binary.right, level + 1);
+ break;
+ case REX_GROUP:
+ case REX_GROUP_AHEAD:
+ case REX_GROUP_AHEAD_NOT:
+ case REX_GROUP_BEHIND:
+ case REX_GROUP_BEHIND_NOT:
+ case REX_GROUP_CUT:
+ case REX_NEG:
+ case REX_REP:
+ listnode(e->re.group.expr.rex, level + 1);
+ break;
+ }
+ } while (e = e->next);
+ }
+}
+
+static int
+list(Env_t* env, Rex_t* rex)
+{
+ sfprintf(sfstderr, "AHA regex hard=%d stack=%p\n", env->hard, env->stack);
+ if (rex)
+ listnode(rex, 1);
+ return 0;
+}
+
+#endif
+
+/*
+ * returning REG_BADPAT or REG_ESPACE is not explicitly
+ * countenanced by the standard
+ */
+
+int
+regnexec(const regex_t* p, const char* s, size_t len, size_t nmatch, regmatch_t* match, regflags_t flags)
+{
+ register int n;
+ register int i;
+ int j;
+ int k;
+ int m;
+ int advance;
+ Env_t* env;
+ Rex_t* e;
+
+ DEBUG_INIT();
+ DEBUG_TEST(0x0001,(sfprintf(sfstdout, "AHA#%04d 0x%04x regnexec %d 0x%08x `%-.*s'\n", __LINE__, debug_flag, nmatch, flags, len, s)),(0));
+ if (!p || !(env = p->env))
+ return REG_BADPAT;
+ if (!s)
+ return fatal(env->disc, REG_BADPAT, NiL);
+ if (len < env->min)
+ {
+ DEBUG_TEST(0x0080,(sfprintf(sfstdout, "AHA#%04d REG_NOMATCH %d %d\n", __LINE__, len, env->min)),(0));
+ return REG_NOMATCH;
+ }
+ env->regex = p;
+ env->beg = (unsigned char*)s;
+ env->end = env->beg + len;
+ stknew(stkstd, &env->stk);
+ env->flags &= ~REG_EXEC;
+ env->flags |= (flags & REG_EXEC);
+ advance = 0;
+ if (env->stack = env->hard || !(env->flags & REG_NOSUB) && nmatch)
+ {
+ n = env->nsub;
+ if (!(env->match = (regmatch_t*)stkpush(stkstd, 2 * (n + 1) * sizeof(regmatch_t))) ||
+ !env->pos && !(env->pos = vecopen(16, sizeof(Pos_t))) ||
+ !env->bestpos && !(env->bestpos = vecopen(16, sizeof(Pos_t))))
+ {
+ k = REG_ESPACE;
+ goto done;
+ }
+ env->pos->cur = env->bestpos->cur = 0;
+ env->best = &env->match[n + 1];
+ env->best[0].rm_so = 0;
+ env->best[0].rm_eo = -1;
+ for (i = 0; i <= n; i++)
+ env->match[i] = state.nomatch;
+ if (flags & REG_ADVANCE)
+ advance = 1;
+ }
+ DEBUG_TEST(0x1000,(list(env,env->rex)),(0));
+ k = REG_NOMATCH;
+ if ((e = env->rex)->type == REX_BM)
+ {
+ DEBUG_TEST(0x0080,(sfprintf(sfstdout, "AHA#%04d REX_BM\n", __LINE__)),(0));
+ if (len < e->re.bm.right)
+ {
+ DEBUG_TEST(0x0080,(sfprintf(sfstdout, "AHA#%04d REG_NOMATCH %d %d\n", __LINE__, len, e->re.bm.right)),(0));
+ goto done;
+ }
+ else if (!(flags & REG_LEFT))
+ {
+ register unsigned char* buf = (unsigned char*)s;
+ register size_t index = e->re.bm.left + e->re.bm.size;
+ register size_t mid = len - e->re.bm.right;
+ register size_t* skip = e->re.bm.skip;
+ register size_t* fail = e->re.bm.fail;
+ register Bm_mask_t** mask = e->re.bm.mask;
+ Bm_mask_t m;
+ size_t x;
+
+ DEBUG_TEST(0x0080,(sfprintf(sfstdout, "AHA#%04d REX_BM len=%d right=%d left=%d size=%d %d %d\n", __LINE__, len, e->re.bm.right, e->re.bm.left, e->re.bm.size, index, mid)),(0));
+ for (;;)
+ {
+ while ((index += skip[buf[index]]) < mid);
+ if (index < HIT)
+ {
+ DEBUG_TEST(0x0080,(sfprintf(sfstdout, "AHA#%04d REG_NOMATCH %d %d\n", __LINE__, index, HIT)),(0));
+ goto done;
+ }
+ index -= HIT;
+ m = mask[n = e->re.bm.size - 1][buf[index]];
+ do
+ {
+ if (!n--)
+ {
+ if (e->re.bm.back < 0)
+ goto possible;
+ if (advance)
+ {
+ i = index - e->re.bm.back;
+ s += i;
+ if (env->stack)
+ env->best[0].rm_so += i;
+ goto possible;
+ }
+ x = index;
+ if (index < e->re.bm.back)
+ index = 0;
+ else
+ index -= e->re.bm.back;
+ while (index <= x)
+ {
+ if ((i = parse(env, e->next, &env->done, buf + index)) != NONE)
+ {
+ if (env->stack)
+ env->best[0].rm_so = index;
+ n = env->nsub;
+ goto hit;
+ }
+ index++;
+ }
+ index += e->re.bm.size;
+ break;
+ }
+ } while (m &= mask[n][buf[--index]]);
+ if ((index += fail[n + 1]) >= len)
+ goto done;
+ }
+ }
+ possible:
+ n = env->nsub;
+ e = e->next;
+ }
+ j = env->once || (flags & REG_LEFT);
+ DEBUG_TEST(0x0080,(sfprintf(sfstdout, "AHA#%04d parse once=%d\n", __LINE__, j)),(0));
+ while ((i = parse(env, e, &env->done, (unsigned char*)s)) == NONE || advance && !env->best[0].rm_eo && !(advance = 0))
+ {
+ if (j)
+ goto done;
+ i = MBSIZE(s);
+ s += i;
+ if ((unsigned char*)s > env->end - env->min)
+ goto done;
+ if (env->stack)
+ env->best[0].rm_so += i;
+ }
+ if ((flags & REG_LEFT) && env->stack && env->best[0].rm_so)
+ goto done;
+ hit:
+ if (k = env->error)
+ goto done;
+ if (i == CUT)
+ {
+ k = env->error = REG_NOMATCH;
+ goto done;
+ }
+ if (!(env->flags & REG_NOSUB))
+ {
+ k = (env->flags & (REG_SHELL|REG_AUGMENTED)) == (REG_SHELL|REG_AUGMENTED);
+ for (i = j = m = 0; j < nmatch; i++)
+ if (!i || !k || (i & 1))
+ {
+ if (i > n)
+ match[j] = state.nomatch;
+ else
+ match[m = j] = env->best[i];
+ j++;
+ }
+ if (k)
+ {
+ while (m > 0 && match[m].rm_so == -1 && match[m].rm_eo == -1)
+ m--;
+ ((regex_t*)p)->re_nsub = m;
+ }
+ }
+ k = 0;
+ done:
+ stkold(stkstd, &env->stk);
+ env->stk.base = 0;
+ if (k > REG_NOMATCH)
+ fatal(p->env->disc, k, NiL);
+ return k;
+}
+
+void
+regfree(regex_t* p)
+{
+ Env_t* env;
+
+ if (p && (env = p->env))
+ {
+#if _REG_subcomp
+ if (env->sub)
+ {
+ regsubfree(p);
+ p->re_sub = 0;
+ }
+#endif
+ p->env = 0;
+ if (--env->refs <= 0 && !(env->disc->re_flags & REG_NOFREE))
+ {
+ drop(env->disc, env->rex);
+ if (env->pos)
+ vecclose(env->pos);
+ if (env->bestpos)
+ vecclose(env->bestpos);
+ if (env->stk.base)
+ stkold(stkstd, &env->stk);
+ alloc(env->disc, env, 0);
+ }
+ }
+}
diff --git a/src/lib/libast/regex/regrecord.c b/src/lib/libast/regex/regrecord.c
new file mode 100644
index 0000000..001d14c
--- /dev/null
+++ b/src/lib/libast/regex/regrecord.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * return 1 if regrexec() can be used
+ */
+
+#include "reglib.h"
+
+int
+regrecord(const regex_t* p)
+{
+ return p && p->env && p->env->rex->type == REX_BM;
+}
diff --git a/src/lib/libast/regex/regrexec.c b/src/lib/libast/regex/regrexec.c
new file mode 100644
index 0000000..6cb1272
--- /dev/null
+++ b/src/lib/libast/regex/regrexec.c
@@ -0,0 +1,145 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * posix regex record executor
+ * multiple record sized-buffer interface
+ */
+
+#include "reglib.h"
+
+/*
+ * call regnexec() on records selected by Boyer-Moore
+ */
+
+int
+regrexec(const regex_t* p, const char* s, size_t len, size_t nmatch, regmatch_t* match, regflags_t flags, int sep, void* handle, regrecord_t record)
+{
+ register unsigned char* buf = (unsigned char*)s;
+ register unsigned char* beg;
+ register unsigned char* l;
+ register unsigned char* r;
+ register unsigned char* x;
+ register size_t* skip;
+ register size_t* fail;
+ register Bm_mask_t** mask;
+ register size_t index;
+ register int n;
+ unsigned char* end;
+ size_t mid;
+ int complete;
+ int exactlen;
+ int leftlen;
+ int rightlen;
+ int inv;
+ Bm_mask_t m;
+ Env_t* env;
+ Rex_t* e;
+
+ if (!s || !p || !(env = p->env) || (e = env->rex)->type != REX_BM)
+ return REG_BADPAT;
+ inv = (flags & REG_INVERT) != 0;
+ buf = beg = (unsigned char*)s;
+ end = buf + len;
+ mid = (len < e->re.bm.right) ? 0 : (len - e->re.bm.right);
+ skip = e->re.bm.skip;
+ fail = e->re.bm.fail;
+ mask = e->re.bm.mask;
+ complete = e->re.bm.complete && !nmatch;
+ exactlen = e->re.bm.size;
+ leftlen = e->re.bm.left + exactlen;
+ rightlen = exactlen + e->re.bm.right;
+ index = leftlen++;
+ for (;;)
+ {
+ while ((index += skip[buf[index]]) < mid);
+ if (index < HIT)
+ goto impossible;
+ index -= HIT;
+ m = mask[n = exactlen - 1][buf[index]];
+ do
+ {
+ if (!n--)
+ goto possible;
+ } while (m &= mask[n][buf[--index]]);
+ if ((index += fail[n + 1]) < len)
+ continue;
+ impossible:
+ if (inv)
+ {
+ l = r = buf + len;
+ goto invert;
+ }
+ n = 0;
+ goto done;
+ possible:
+ r = (l = buf + index) + exactlen;
+ while (l > beg)
+ if (*--l == sep)
+ {
+ l++;
+ break;
+ }
+ if ((r - l) < leftlen)
+ goto spanned;
+ while (r < end && *r != sep)
+ r++;
+ if ((r - (buf + index)) < rightlen)
+ goto spanned;
+ if (complete || (env->rex = ((r - l) > 128) ? e : e->next) && !(n = regnexec(p, (char*)l, r - l, nmatch, match, flags)))
+ {
+ if (inv)
+ {
+ invert:
+ x = beg;
+ while (beg < l)
+ {
+ while (x < l && *x != sep)
+ x++;
+ if (n = (*record)(handle, (char*)beg, x - beg))
+ goto done;
+ beg = ++x;
+ }
+ }
+ else if (n = (*record)(handle, (char*)l, r - l))
+ goto done;
+ if ((index = (r - buf) + leftlen) >= len)
+ {
+ n = (inv && (++r - buf) < len) ? (*record)(handle, (char*)r, (buf + len) - r): 0;
+ goto done;
+ }
+ beg = r + 1;
+ }
+ else if (n != REG_NOMATCH)
+ goto done;
+ else
+ {
+ spanned:
+ if ((index += exactlen) >= mid)
+ goto impossible;
+ }
+ }
+ done:
+ env->rex = e;
+ return n;
+}
diff --git a/src/lib/libast/regex/regstat.c b/src/lib/libast/regex/regstat.c
new file mode 100644
index 0000000..c7f725f
--- /dev/null
+++ b/src/lib/libast/regex/regstat.c
@@ -0,0 +1,53 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * return p stat info
+ */
+
+#include "reglib.h"
+
+regstat_t*
+regstat(const regex_t* p)
+{
+ register Rex_t* e;
+
+ p->env->stats.re_flags = p->env->flags;
+ p->env->stats.re_info = 0;
+ e = p->env->rex;
+ if (e && e->type == REX_BM)
+ {
+ p->env->stats.re_record = p->env->rex->re.bm.size;
+ e = e->next;
+ }
+ else
+ p->env->stats.re_record = 0;
+ if (e && e->type == REX_BEG)
+ e = e->next;
+ if (e && e->type == REX_STRING)
+ e = e->next;
+ if (!e || e->type == REX_END && !e->next)
+ p->env->stats.re_info |= REG_LITERAL;
+ p->env->stats.re_record = (p && p->env && p->env->rex->type == REX_BM) ? p->env->rex->re.bm.size : -1;
+ return &p->env->stats;
+}
diff --git a/src/lib/libast/regex/regsub.c b/src/lib/libast/regex/regsub.c
new file mode 100644
index 0000000..8e89bea
--- /dev/null
+++ b/src/lib/libast/regex/regsub.c
@@ -0,0 +1,269 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * OBSOLETE Sfio_t buffer interface -- use regsubcomp(),regsubexec()
+ */
+
+#include "reglib.h"
+
+/*
+ * do a single substitution
+ */
+
+static int
+subold(register Sfio_t* dp, const char* op, register const char* sp, size_t nmatch, register regmatch_t* match, register regflags_t flags, int sre)
+{
+ register int c;
+ char* s;
+ char* e;
+ const char* b;
+ regflags_t f;
+
+ f = flags &= (REG_SUB_LOWER|REG_SUB_UPPER);
+ for (;;)
+ {
+ switch (c = *sp++)
+ {
+ case 0:
+ return 0;
+ case '~':
+ if (!sre || *sp != '(')
+ {
+ sfputc(dp, c);
+ continue;
+ }
+ b = sp - 1;
+ sp++;
+ break;
+ case '\\':
+ if (sre)
+ {
+ sfputc(dp, chresc(sp - 1, &s));
+ sp = (const char*)s;
+ continue;
+ }
+ if (*sp == '&')
+ {
+ c = *sp++;
+ sfputc(dp, c);
+ continue;
+ }
+ break;
+ case '&':
+ if (sre)
+ {
+ sfputc(dp, c);
+ continue;
+ }
+ sp--;
+ break;
+ default:
+ switch (flags)
+ {
+ case REG_SUB_UPPER:
+ if (islower(c))
+ c = toupper(c);
+ break;
+ case REG_SUB_LOWER:
+ if (isupper(c))
+ c = tolower(c);
+ break;
+ case REG_SUB_UPPER|REG_SUB_LOWER:
+ if (isupper(c))
+ c = tolower(c);
+ else if (islower(c))
+ c = toupper(c);
+ break;
+ }
+ sfputc(dp, c);
+ continue;
+ }
+ switch (c = *sp++)
+ {
+ case 0:
+ sp--;
+ continue;
+ case '&':
+ c = 0;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ c -= '0';
+ if (sre)
+ while (isdigit(*sp))
+ c = c * 10 + *sp++ - '0';
+ break;
+ case 'l':
+ if (sre && *sp != ')')
+ {
+ c = -1;
+ break;
+ }
+ if (c = *sp)
+ {
+ sp++;
+ if (isupper(c))
+ c = tolower(c);
+ sfputc(dp, c);
+ }
+ continue;
+ case 'u':
+ if (sre)
+ {
+ if (*sp != ')')
+ {
+ c = -1;
+ break;
+ }
+ sp++;
+ }
+ if (c = *sp)
+ {
+ sp++;
+ if (islower(c))
+ c = toupper(c);
+ sfputc(dp, c);
+ }
+ continue;
+ case 'E':
+ if (sre)
+ {
+ if (*sp != ')')
+ {
+ c = -1;
+ break;
+ }
+ sp++;
+ }
+ flags = f;
+ continue;
+ case 'L':
+ if (sre)
+ {
+ if (*sp != ')')
+ {
+ c = -1;
+ break;
+ }
+ sp++;
+ }
+ f = flags;
+ flags = REG_SUB_LOWER;
+ continue;
+ case 'U':
+ if (sre)
+ {
+ if (*sp != ')')
+ {
+ c = -1;
+ break;
+ }
+ sp++;
+ }
+ f = flags;
+ flags = REG_SUB_UPPER;
+ continue;
+ default:
+ if (!sre)
+ {
+ sfputc(dp, chresc(sp - 2, &s));
+ sp = (const char*)s;
+ continue;
+ }
+ sp--;
+ c = -1;
+ break;
+ }
+ if (sre)
+ {
+ if (c < 0 || *sp != ')')
+ {
+ for (; b < sp; b++)
+ sfputc(dp, *b);
+ continue;
+ }
+ sp++;
+ }
+ if (c >= nmatch)
+ return REG_ESUBREG;
+ s = (char*)op + match[c].rm_so;
+ e = (char*)op + match[c].rm_eo;
+ while (s < e)
+ {
+ c = *s++;
+ switch (flags)
+ {
+ case REG_SUB_UPPER:
+ if (islower(c))
+ c = toupper(c);
+ break;
+ case REG_SUB_LOWER:
+ if (isupper(c))
+ c = tolower(c);
+ break;
+ case REG_SUB_UPPER|REG_SUB_LOWER:
+ if (isupper(c))
+ c = tolower(c);
+ else if (islower(c))
+ c = toupper(c);
+ break;
+ }
+ sfputc(dp, c);
+ }
+ }
+}
+
+/*
+ * ed(1) style substitute using matches from last regexec()
+ */
+
+int
+regsub(const regex_t* p, Sfio_t* dp, const char* op, const char* sp, size_t nmatch, regmatch_t* match, regflags_t flags)
+{
+ int m;
+ int r;
+ int sre;
+
+ if ((p->env->flags & REG_NOSUB) || !nmatch)
+ return fatal(p->env->disc, REG_BADPAT, NiL);
+ m = (flags >> 16) & 0x3fff;
+ sre = !!(p->env->flags & REG_SHELL);
+ r = 0;
+ do
+ {
+ if (--m > 0)
+ sfwrite(dp, op, match->rm_eo);
+ else
+ {
+ sfwrite(dp, op, match->rm_so);
+ if (r = subold(dp, op, sp, nmatch, match, flags, sre))
+ return fatal(p->env->disc, r, NiL);
+ }
+ op += match->rm_eo;
+ } while ((m > 0 || (flags & REG_SUB_ALL)) && !(r = regexec(p, op, nmatch, match, p->env->flags|(match->rm_so == match->rm_eo ? REG_ADVANCE : 0))));
+ if (r && r != REG_NOMATCH)
+ return fatal(p->env->disc, r, NiL);
+ sfputr(dp, op, -1);
+ return 0;
+}
diff --git a/src/lib/libast/regex/regsubcomp.c b/src/lib/libast/regex/regsubcomp.c
new file mode 100644
index 0000000..73bde4c
--- /dev/null
+++ b/src/lib/libast/regex/regsubcomp.c
@@ -0,0 +1,377 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * posix regex ed(1) style substitute compile
+ */
+
+#include "reglib.h"
+
+static const regflags_t submap[] =
+{
+ 'g', REG_SUB_ALL,
+ 'l', REG_SUB_LOWER,
+ 'n', REG_SUB_NUMBER,
+ 'p', REG_SUB_PRINT,
+ 's', REG_SUB_STOP,
+ 'u', REG_SUB_UPPER,
+ 'w', REG_SUB_WRITE|REG_SUB_LAST,
+ 0, 0
+};
+
+int
+regsubflags(regex_t* p, register const char* s, char** e, int delim, register const regflags_t* map, int* pm, regflags_t* pf)
+{
+ register int c;
+ register const regflags_t* m;
+ regflags_t flags;
+ int minmatch;
+ regdisc_t* disc;
+
+ flags = pf ? *pf : 0;
+ minmatch = pm ? *pm : 0;
+ if (!map)
+ map = submap;
+ while (!(flags & REG_SUB_LAST))
+ {
+ if (!(c = *s++) || c == delim)
+ {
+ s--;
+ break;
+ }
+ else if (c >= '0' && c <= '9')
+ {
+ if (minmatch)
+ {
+ disc = p->env->disc;
+ regfree(p);
+ return fatal(disc, REG_EFLAGS, s - 1);
+ }
+ minmatch = c - '0';
+ while (*s >= '0' && *s <= '9')
+ minmatch = minmatch * 10 + *s++ - '0';
+ }
+ else
+ {
+ for (m = map; *m; m++)
+ if (*m++ == c)
+ {
+ if (flags & *m)
+ {
+ disc = p->env->disc;
+ regfree(p);
+ return fatal(disc, REG_EFLAGS, s - 1);
+ }
+ flags |= *m--;
+ break;
+ }
+ if (!*m)
+ {
+ s--;
+ break;
+ }
+ }
+ }
+ if (pf)
+ *pf = flags;
+ if (pm)
+ *pm = minmatch;
+ if (e)
+ *e = (char*)s;
+ return 0;
+}
+
+/*
+ * compile substitute rhs and optional flags
+ */
+
+int
+regsubcomp(regex_t* p, register const char* s, const regflags_t* map, int minmatch, regflags_t flags)
+{
+ register regsub_t* sub;
+ register int c;
+ register int d;
+ register char* t;
+ register regsubop_t* op;
+ char* e;
+ const char* r;
+ int sre;
+ int f;
+ int g;
+ int n;
+ int nops;
+ const char* o;
+ regdisc_t* disc;
+
+ disc = p->env->disc;
+ if (p->env->flags & REG_NOSUB)
+ {
+ regfree(p);
+ return fatal(disc, REG_BADPAT, NiL);
+ }
+ if (!(sub = (regsub_t*)alloc(p->env->disc, 0, sizeof(regsub_t) + strlen(s))) || !(sub->re_ops = (regsubop_t*)alloc(p->env->disc, 0, (nops = 8) * sizeof(regsubop_t))))
+ {
+ if (sub)
+ alloc(p->env->disc, sub, 0);
+ regfree(p);
+ return fatal(disc, REG_ESPACE, s);
+ }
+ sub->re_buf = sub->re_end = 0;
+ p->re_sub = sub;
+ p->env->sub = 1;
+ op = sub->re_ops;
+ o = s;
+ if (!(p->env->flags & REG_DELIMITED))
+ d = 0;
+ else
+ switch (d = *(s - 1))
+ {
+ case '\\':
+ case '\n':
+ case '\r':
+ regfree(p);
+ return fatal(disc, REG_EDELIM, s);
+ }
+ sre = p->env->flags & REG_SHELL;
+ t = sub->re_rhs;
+ if (d)
+ {
+ r = s;
+ for (;;)
+ {
+ if (!*s)
+ {
+ if (p->env->flags & REG_MUSTDELIM)
+ {
+ regfree(p);
+ return fatal(disc, REG_EDELIM, r);
+ }
+ break;
+ }
+ else if (*s == d)
+ {
+ flags |= REG_SUB_FULL;
+ s++;
+ break;
+ }
+ else if (*s++ == '\\' && !*s++)
+ {
+ regfree(p);
+ return fatal(disc, REG_EESCAPE, r);
+ }
+ }
+ if (*s)
+ {
+ if (n = regsubflags(p, s, &e, d, map, &minmatch, &flags))
+ return n;
+ s = (const char*)e;
+ }
+ p->re_npat = s - o;
+ s = r;
+ }
+ else
+ p->re_npat = 0;
+ op->op = f = g = flags & (REG_SUB_LOWER|REG_SUB_UPPER);
+ op->off = 0;
+ while ((c = *s++) != d)
+ {
+ again:
+ if (!c)
+ {
+ p->re_npat = s - o - 1;
+ break;
+ }
+ else if (c == '\\')
+ {
+ if (*s == c)
+ {
+ *t++ = *s++;
+ continue;
+ }
+ if ((c = *s++) == d)
+ goto again;
+ if (!c)
+ {
+ regfree(p);
+ return fatal(disc, REG_EESCAPE, s - 2);
+ }
+ if (c == '&')
+ {
+ *t++ = c;
+ continue;
+ }
+ }
+ else if (c == '&')
+ {
+ if (sre)
+ {
+ *t++ = c;
+ continue;
+ }
+ }
+ else
+ {
+ switch (op->op)
+ {
+ case REG_SUB_UPPER:
+ if (islower(c))
+ c = toupper(c);
+ break;
+ case REG_SUB_LOWER:
+ if (isupper(c))
+ c = tolower(c);
+ break;
+ case REG_SUB_UPPER|REG_SUB_LOWER:
+ if (isupper(c))
+ c = tolower(c);
+ else if (islower(c))
+ c = toupper(c);
+ break;
+ }
+ *t++ = c;
+ continue;
+ }
+ switch (c)
+ {
+ case 0:
+ s--;
+ continue;
+ case '&':
+ c = 0;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ c -= '0';
+ if (isdigit(*s) && (p->env->flags & REG_MULTIREF))
+ c = c * 10 + *s++ - '0';
+ break;
+ case 'l':
+ if (c = *s)
+ {
+ s++;
+ if (isupper(c))
+ c = tolower(c);
+ *t++ = c;
+ }
+ continue;
+ case 'u':
+ if (c = *s)
+ {
+ s++;
+ if (islower(c))
+ c = toupper(c);
+ *t++ = c;
+ }
+ continue;
+ case 'E':
+ f = g;
+ set:
+ if ((op->len = (t - sub->re_rhs) - op->off) && (n = ++op - sub->re_ops) >= nops)
+ {
+ if (!(sub->re_ops = (regsubop_t*)alloc(p->env->disc, sub->re_ops, (nops *= 2) * sizeof(regsubop_t))))
+ {
+ regfree(p);
+ return fatal(disc, REG_ESPACE, NiL);
+ }
+ op = sub->re_ops + n;
+ }
+ op->op = f;
+ op->off = t - sub->re_rhs;
+ continue;
+ case 'L':
+ g = f;
+ f = REG_SUB_LOWER;
+ goto set;
+ case 'U':
+ g = f;
+ f = REG_SUB_UPPER;
+ goto set;
+ default:
+ if (!sre)
+ {
+ *t++ = chresc(s - 2, &e);
+ s = (const char*)e;
+ continue;
+ }
+ s--;
+ c = -1;
+ break;
+ }
+ if (c > p->re_nsub)
+ {
+ regfree(p);
+ return fatal(disc, REG_ESUBREG, s - 1);
+ }
+ if ((n = op - sub->re_ops) >= (nops - 2))
+ {
+ if (!(sub->re_ops = (regsubop_t*)alloc(p->env->disc, sub->re_ops, (nops *= 2) * sizeof(regsubop_t))))
+ {
+ regfree(p);
+ return fatal(disc, REG_ESPACE, NiL);
+ }
+ op = sub->re_ops + n;
+ }
+ if (op->len = (t - sub->re_rhs) - op->off)
+ op++;
+ op->op = f;
+ op->off = c;
+ op->len = 0;
+ op++;
+ op->op = f;
+ op->off = t - sub->re_rhs;
+ }
+ if ((op->len = (t - sub->re_rhs) - op->off) && (n = ++op - sub->re_ops) >= nops)
+ {
+ if (!(sub->re_ops = (regsubop_t*)alloc(p->env->disc, sub->re_ops, (nops *= 2) * sizeof(regsubop_t))))
+ {
+ regfree(p);
+ return fatal(disc, REG_ESPACE, NiL);
+ }
+ op = sub->re_ops + n;
+ }
+ op->len = -1;
+ sub->re_flags = flags;
+ sub->re_min = minmatch;
+ return 0;
+}
+
+void
+regsubfree(regex_t* p)
+{
+ Env_t* env;
+ regsub_t* sub;
+
+ if (p && (env = p->env) && env->sub && (sub = p->re_sub))
+ {
+ env->sub = 0;
+ p->re_sub = 0;
+ if (!(env->disc->re_flags & REG_NOFREE))
+ {
+ if (sub->re_buf)
+ alloc(env->disc, sub->re_buf, 0);
+ if (sub->re_ops)
+ alloc(env->disc, sub->re_ops, 0);
+ alloc(env->disc, sub, 0);
+ }
+ }
+}
diff --git a/src/lib/libast/regex/regsubexec.c b/src/lib/libast/regex/regsubexec.c
new file mode 100644
index 0000000..78caeba
--- /dev/null
+++ b/src/lib/libast/regex/regsubexec.c
@@ -0,0 +1,196 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * posix regex ed(1) style substitute execute
+ */
+
+#include "reglib.h"
+
+#define NEED(p,b,n,r) \
+ do \
+ { \
+ if (((b)->re_end - (b)->re_cur) < (n)) \
+ { \
+ size_t o = (b)->re_cur - (b)->re_buf; \
+ size_t a = ((b)->re_end - (b)->re_buf); \
+ if (a < n) \
+ a = roundof(n, 128); \
+ a *= 2; \
+ if (!((b)->re_buf = alloc(p->env->disc, (b)->re_buf, a))) \
+ { \
+ (b)->re_buf = (b)->re_cur = (b)->re_end = 0; \
+ c = REG_ESPACE; \
+ r; \
+ } \
+ (b)->re_cur = (b)->re_buf + o; \
+ (b)->re_end = (b)->re_buf + a; \
+ } \
+ } while (0)
+
+#define PUTC(p,b,x,r) \
+ do \
+ { \
+ NEED(p, b, 1, r); \
+ *(b)->re_cur++ = (x); \
+ } while (0)
+
+#define PUTS(p,b,x,z,r) \
+ do if (z) \
+ { \
+ NEED(p, b, z, r); \
+ memcpy((b)->re_cur, x, z); \
+ (b)->re_cur += (z); \
+ } while (0)
+
+/*
+ * do a single substitution
+ */
+
+static int
+sub(const regex_t* p, register regsub_t* b, const char* ss, register regsubop_t* op, size_t nmatch, register regmatch_t* match)
+{
+ register char* s;
+ register char* e;
+ register int c;
+
+ for (;; op++)
+ {
+ switch (op->len)
+ {
+ case -1:
+ break;
+ case 0:
+ if (op->off >= nmatch)
+ return REG_ESUBREG;
+ if ((c = match[op->off].rm_so) < 0)
+ continue;
+ s = (char*)ss + c;
+ if ((c = match[op->off].rm_eo) < 0)
+ continue;
+ e = (char*)ss + c;
+ NEED(p, b, e - s, return c);
+ switch (op->op)
+ {
+ case REG_SUB_UPPER:
+ while (s < e)
+ {
+ c = *s++;
+ if (islower(c))
+ c = toupper(c);
+ *b->re_cur++ = c;
+ }
+ break;
+ case REG_SUB_LOWER:
+ while (s < e)
+ {
+ c = *s++;
+ if (isupper(c))
+ c = tolower(c);
+ *b->re_cur++ = c;
+ }
+ break;
+ case REG_SUB_UPPER|REG_SUB_LOWER:
+ while (s < e)
+ {
+ c = *s++;
+ if (isupper(c))
+ c = tolower(c);
+ else if (islower(c))
+ c = toupper(c);
+ *b->re_cur++ = c;
+ }
+ break;
+ default:
+ while (s < e)
+ *b->re_cur++ = *s++;
+ break;
+ }
+ continue;
+ default:
+ NEED(p, b, op->len, return c);
+ s = b->re_rhs + op->off;
+ e = s + op->len;
+ while (s < e)
+ *b->re_cur++ = *s++;
+ continue;
+ }
+ break;
+ }
+ return 0;
+}
+
+/*
+ * ed(1) style substitute using matches from last regexec()
+ */
+
+int
+regsubexec(const regex_t* p, const char* s, size_t nmatch, regmatch_t* match)
+{
+ register int c;
+ register regsub_t* b;
+ const char* e;
+ int m;
+
+ if (!p->env->sub || (p->env->flags & REG_NOSUB) || !nmatch)
+ return fatal(p->env->disc, REG_BADPAT, NiL);
+ b = p->re_sub;
+ m = b->re_min;
+ b->re_cur = b->re_buf;
+ e = (const char*)p->env->end;
+ c = 0;
+ for (;;)
+ {
+ if (--m > 0)
+ PUTS(p, b, s, match->rm_eo, return fatal(p->env->disc, c, NiL));
+ else
+ {
+ PUTS(p, b, s, match->rm_so, return fatal(p->env->disc, c, NiL));
+ if (!c && (c = sub(p, b, s, b->re_ops, nmatch, match)))
+ return fatal(p->env->disc, c, NiL);
+ }
+ s += match->rm_eo;
+ if (m <= 0 && !(b->re_flags & REG_SUB_ALL) || !*s)
+ break;
+ if (c = regnexec(p, s, e - s, nmatch, match, p->env->flags|(match->rm_so == match->rm_eo ? REG_ADVANCE : 0)))
+ {
+ if (c != REG_NOMATCH)
+ return fatal(p->env->disc, c, NiL);
+ break;
+ }
+ if (!match->rm_so && !match->rm_eo && *s && m <= 1)
+ {
+ match->rm_so = match->rm_eo = 1;
+ c = 1;
+ }
+ }
+ while (s < e)
+ {
+ c = *s++;
+ PUTC(p, b, c, return fatal(p->env->disc, c, NiL));
+ }
+ NEED(p, b, 1, return fatal(p->env->disc, c, NiL));
+ *b->re_cur = 0;
+ b->re_len = b->re_cur - b->re_buf;
+ return 0;
+}
diff --git a/src/lib/libast/sfio/_sfclrerr.c b/src/lib/libast/sfio/_sfclrerr.c
new file mode 100644
index 0000000..e00dc1b
--- /dev/null
+++ b/src/lib/libast/sfio/_sfclrerr.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfclrerr
+
+#if __STD_C
+int sfclrerr(reg Sfio_t* f)
+#else
+int sfclrerr(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_clrerr(f);
+}
diff --git a/src/lib/libast/sfio/_sfdlen.c b/src/lib/libast/sfio/_sfdlen.c
new file mode 100644
index 0000000..0b0a9f5
--- /dev/null
+++ b/src/lib/libast/sfio/_sfdlen.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfdlen
+
+#if __STD_C
+int sfdlen(reg Sfdouble_t v)
+#else
+int sfdlen(v)
+reg Sfdouble_t v;
+#endif
+{
+ return __sf_dlen(v);
+}
diff --git a/src/lib/libast/sfio/_sfeof.c b/src/lib/libast/sfio/_sfeof.c
new file mode 100644
index 0000000..63dc002
--- /dev/null
+++ b/src/lib/libast/sfio/_sfeof.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfeof
+
+#if __STD_C
+int sfeof(reg Sfio_t* f)
+#else
+int sfeof(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_eof(f);
+}
diff --git a/src/lib/libast/sfio/_sferror.c b/src/lib/libast/sfio/_sferror.c
new file mode 100644
index 0000000..43b1a03
--- /dev/null
+++ b/src/lib/libast/sfio/_sferror.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sferror
+
+#if __STD_C
+int sferror(reg Sfio_t* f)
+#else
+int sferror(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_error(f);
+}
diff --git a/src/lib/libast/sfio/_sffileno.c b/src/lib/libast/sfio/_sffileno.c
new file mode 100644
index 0000000..f61a830
--- /dev/null
+++ b/src/lib/libast/sfio/_sffileno.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sffileno
+
+#if __STD_C
+int sffileno(reg Sfio_t* f)
+#else
+int sffileno(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_fileno(f);
+}
diff --git a/src/lib/libast/sfio/_sfgetc.c b/src/lib/libast/sfio/_sfgetc.c
new file mode 100644
index 0000000..08a51b3
--- /dev/null
+++ b/src/lib/libast/sfio/_sfgetc.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfgetc
+
+#if __STD_C
+int sfgetc(reg Sfio_t* f)
+#else
+int sfgetc(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_getc(f);
+}
diff --git a/src/lib/libast/sfio/_sfgetl.c b/src/lib/libast/sfio/_sfgetl.c
new file mode 100644
index 0000000..cc66462
--- /dev/null
+++ b/src/lib/libast/sfio/_sfgetl.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/*
+ * for backwards compatibility with pre-threaded sfgetl() inline
+ */
+
+#ifdef __EXPORT__
+#define extern __EXPORT__
+#endif
+
+extern
+#if __STD_C
+Sflong_t _sfgetl(reg Sfio_t* f)
+#else
+Sflong_t _sfgetl(f)
+reg Sfio_t* f;
+#endif
+{
+ sfungetc(f, (unsigned char)_SF_(f)->val);
+ return sfgetl(f);
+}
diff --git a/src/lib/libast/sfio/_sfgetl2.c b/src/lib/libast/sfio/_sfgetl2.c
new file mode 100644
index 0000000..a6f9373
--- /dev/null
+++ b/src/lib/libast/sfio/_sfgetl2.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/* OBSOLETE 19961031 -- for shared library compatibility */
+
+#include "sfhdr.h"
+
+#undef _sfgetl2
+
+_BEGIN_EXTERNS_
+#if _BLD_sfio && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern long _sfgetl2 _ARG_((Sfio_t*, long));
+
+#undef extern
+_END_EXTERNS_
+
+#if __STD_C
+long _sfgetl2(reg Sfio_t* f, long v)
+#else
+long _sfgetl2(f, v)
+reg Sfio_t* f;
+long v;
+#endif
+{
+ if (v < 0)
+ return -1;
+ sfungetc(f, v);
+ return sfgetl(f);
+}
diff --git a/src/lib/libast/sfio/_sfgetu.c b/src/lib/libast/sfio/_sfgetu.c
new file mode 100644
index 0000000..183f1a4
--- /dev/null
+++ b/src/lib/libast/sfio/_sfgetu.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/*
+ * for backwards compatibility with pre-threaded sfgetl() inline
+ */
+
+#ifdef __EXPORT__
+#define extern __EXPORT__
+#endif
+
+extern
+#if __STD_C
+Sfulong_t _sfgetu(reg Sfio_t* f)
+#else
+Sfulong_t _sfgetu(f)
+reg Sfio_t* f;
+#endif
+{
+ sfungetc(f, (unsigned char)_SF_(f)->val);
+ return sfgetu(f);
+}
diff --git a/src/lib/libast/sfio/_sfgetu2.c b/src/lib/libast/sfio/_sfgetu2.c
new file mode 100644
index 0000000..27f5661
--- /dev/null
+++ b/src/lib/libast/sfio/_sfgetu2.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/* OBSOLETE 19961031 -- for shared library compatibility */
+
+#include "sfhdr.h"
+
+#undef _sfgetu2
+
+_BEGIN_EXTERNS_
+#if _BLD_sfio && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern long _sfgetu2 _ARG_((Sfio_t*, long));
+
+#undef extern
+_END_EXTERNS_
+
+#if __STD_C
+long _sfgetu2(reg Sfio_t* f, long v)
+#else
+long _sfgetu2(f, v)
+reg Sfio_t* f;
+long v;
+#endif
+{
+ if (v < 0)
+ return -1;
+ sfungetc(f, v);
+ return sfgetu(f);
+}
diff --git a/src/lib/libast/sfio/_sfllen.c b/src/lib/libast/sfio/_sfllen.c
new file mode 100644
index 0000000..2e735e3
--- /dev/null
+++ b/src/lib/libast/sfio/_sfllen.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfllen
+
+#if __STD_C
+int sfllen(reg Sflong_t v)
+#else
+int sfllen(v)
+reg Sflong_t v;
+#endif
+{
+ return __sf_llen(v);
+}
diff --git a/src/lib/libast/sfio/_sfopen.c b/src/lib/libast/sfio/_sfopen.c
new file mode 100644
index 0000000..9ad93fc
--- /dev/null
+++ b/src/lib/libast/sfio/_sfopen.c
@@ -0,0 +1,219 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Open a file/string for IO.
+** If f is not nil, it is taken as an existing stream that should be
+** closed and its structure reused for the new stream.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if _BLD_sfio && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+extern
+#undef extern
+
+#if __STD_C
+Sfio_t* _sfopen(Sfio_t* f, const char* file, const char* mode)
+#else
+Sfio_t* _sfopen(f,file,mode)
+Sfio_t* f; /* old stream structure */
+char* file; /* file/string to be opened */
+char* mode; /* mode of the stream */
+#endif
+{
+ int fd, oldfd, oflags, sflags;
+ SFMTXDECL(f);
+
+ /* get the control flags */
+ if((sflags = _sftype(mode,&oflags,NIL(int*))) == 0)
+ return NIL(Sfio_t*);
+
+ /* changing the control flags */
+ if(f && !file && !((f->flags|sflags)&SF_STRING) )
+ { SFMTXENTER(f, NIL(Sfio_t*));
+
+ if(f->mode&SF_INIT ) /* stream uninitialized, ok to set flags */
+ { f->flags |= (sflags & (SF_FLAGS & ~SF_RDWR));
+
+ if((sflags &= SF_RDWR) != 0) /* reset read/write modes */
+ { f->flags = (f->flags & ~SF_RDWR) | sflags;
+
+ if((f->flags&SF_RDWR) == SF_RDWR)
+ f->bits |= SF_BOTH;
+ else f->bits &= ~SF_BOTH;
+
+ if(f->flags&SF_READ)
+ f->mode = (f->mode&~SF_WRITE)|SF_READ;
+ else f->mode = (f->mode&~SF_READ)|SF_WRITE;
+ }
+ }
+ else /* make sure there is no buffered data */
+ { if(sfsync(f) < 0)
+ SFMTXRETURN(f,NIL(Sfio_t*));
+ }
+
+ if(f->file >= 0 && (oflags &= (O_TEXT|O_BINARY|O_APPEND)) != 0 )
+ { /* set file access control */
+ int ctl = sysfcntlf(f->file, F_GETFL, 0);
+ ctl = (ctl & ~(O_TEXT|O_BINARY|O_APPEND)) | oflags;
+ sysfcntlf(f->file, F_SETFL, ctl);
+ }
+
+ SFMTXRETURN(f,f);
+ }
+
+ if(sflags&SF_STRING)
+ { f = sfnew(f,(char*)file,
+ file ? (size_t)strlen((char*)file) : (size_t)SF_UNBOUND,
+ -1,sflags);
+ }
+ else
+ { if(!file)
+ return NIL(Sfio_t*);
+
+#if _has_oflags /* open the file */
+ while((fd = sysopenf((char*)file,oflags,SF_CREATMODE)) < 0 && errno == EINTR)
+ errno = 0;
+#else
+ while((fd = sysopenf(file,oflags&O_ACCMODE)) < 0 && errno == EINTR)
+ errno = 0;
+ if(fd >= 0)
+ { if((oflags&(O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) )
+ { CLOSE(fd); /* error: file already exists */
+ return NIL(Sfio_t*);
+ }
+ if(oflags&O_TRUNC ) /* truncate file */
+ { reg int tf;
+ while((tf = syscreatf(file,SF_CREATMODE)) < 0 &&
+ errno == EINTR)
+ errno = 0;
+ CLOSE(tf);
+ }
+ }
+ else if(oflags&O_CREAT)
+ { while((fd = syscreatf(file,SF_CREATMODE)) < 0 && errno == EINTR)
+ errno = 0;
+ if((oflags&O_ACCMODE) != O_WRONLY)
+ { /* the file now exists, reopen it for read/write */
+ CLOSE(fd);
+ while((fd = sysopenf(file,oflags&O_ACCMODE)) < 0 &&
+ errno == EINTR)
+ errno = 0;
+ }
+ }
+#endif
+ if(fd < 0)
+ return NIL(Sfio_t*);
+
+ /* we may have to reset the file descriptor to its old value */
+ oldfd = f ? f->file : -1;
+ if((f = sfnew(f,NIL(char*),(size_t)SF_UNBOUND,fd,sflags)) && oldfd >= 0)
+ (void)sfsetfd(f,oldfd);
+ }
+
+ return f;
+}
+
+#if __STD_C
+int _sftype(reg const char* mode, int* oflagsp, int* uflagp)
+#else
+int _sftype(mode, oflagsp, uflagp)
+reg char* mode;
+int* oflagsp;
+int* uflagp;
+#endif
+{
+ reg int sflags, oflags, uflag;
+
+ if(!mode)
+ return 0;
+
+ /* construct the open flags */
+ sflags = oflags = uflag = 0;
+ while(1) switch(*mode++)
+ {
+ case 'a' :
+ sflags |= SF_WRITE | SF_APPENDWR;
+ oflags |= O_WRONLY | O_APPEND | O_CREAT;
+ continue;
+ case 'b' :
+ oflags |= O_BINARY;
+ continue;
+ case 'm' :
+ sflags |= SF_MTSAFE;
+ uflag = 0;
+ continue;
+ case 'r' :
+ sflags |= SF_READ;
+ oflags |= O_RDONLY;
+ continue;
+ case 's' :
+ sflags |= SF_STRING;
+ continue;
+ case 't' :
+ oflags |= O_TEXT;
+ continue;
+ case 'u' :
+ sflags &= ~SF_MTSAFE;
+ uflag = 1;
+ continue;
+ case 'w' :
+ sflags |= SF_WRITE;
+ oflags |= O_WRONLY | O_CREAT;
+ if(!(sflags&SF_READ))
+ oflags |= O_TRUNC;
+ continue;
+ case 'x' :
+ oflags |= O_EXCL;
+ continue;
+ case 'F':
+ /* stdio compatibility -- fd >= FOPEN_MAX (or other magic number) ok */
+ continue;
+ case 'W' :
+ sflags |= SF_WCWIDTH;
+ uflag = 0;
+ continue;
+ case '+' :
+ if(sflags)
+ sflags |= SF_READ|SF_WRITE;
+ continue;
+ default :
+ if(!(oflags&O_CREAT) )
+ oflags &= ~O_EXCL;
+#if _WIN32 && !_WINIX
+ if(!(oflags&(O_BINARY|O_TEXT)))
+ oflags |= O_BINARY;
+#endif
+ if((sflags&SF_RDWR) == SF_RDWR)
+ oflags = (oflags&~O_ACCMODE)|O_RDWR;
+ if(oflagsp)
+ *oflagsp = oflags;
+ if(uflagp)
+ *uflagp = uflag;
+ if((sflags&(SF_STRING|SF_RDWR)) == SF_STRING)
+ sflags |= SF_READ;
+ return sflags;
+ }
+}
diff --git a/src/lib/libast/sfio/_sfputc.c b/src/lib/libast/sfio/_sfputc.c
new file mode 100644
index 0000000..8f577e4
--- /dev/null
+++ b/src/lib/libast/sfio/_sfputc.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfputc
+
+#if __STD_C
+int sfputc(reg Sfio_t* f, reg int c)
+#else
+int sfputc(f,c)
+reg Sfio_t* f;
+reg int c;
+#endif
+{
+ return __sf_putc(f,c);
+}
diff --git a/src/lib/libast/sfio/_sfputd.c b/src/lib/libast/sfio/_sfputd.c
new file mode 100644
index 0000000..733caa6
--- /dev/null
+++ b/src/lib/libast/sfio/_sfputd.c
@@ -0,0 +1,96 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write out a floating point value in a portable format
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int _sfputd(Sfio_t* f, Sfdouble_t v)
+#else
+int _sfputd(f,v)
+Sfio_t* f;
+Sfdouble_t v;
+#endif
+{
+#define N_ARRAY (16*sizeof(Sfdouble_t))
+ reg ssize_t n, w;
+ reg uchar *s, *ends;
+ int exp;
+ uchar c[N_ARRAY];
+ Sfdouble_t x;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,-1);
+
+ if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ /* get the sign of v */
+ if(v < 0.)
+ { v = -v;
+ n = 1;
+ }
+ else n = 0;
+
+ /* make the magnitude of v < 1 */
+ if(v != 0.)
+ v = frexpl(v,&exp);
+ else exp = 0;
+
+ /* code the sign of v and exp */
+ if((w = exp) < 0)
+ { n |= 02;
+ w = -w;
+ }
+
+ /* write out the signs and the exp */
+ SFOPEN(f,0);
+ if(sfputc(f,n) < 0 || (w = sfputu(f,w)) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+ w += 1;
+
+ s = (ends = &c[0])+sizeof(c);
+ while(s > ends)
+ { /* get 2^SF_PRECIS precision at a time */
+ n = (int)(x = ldexpl(v,SF_PRECIS));
+ *--s = n|SF_MORE;
+ v = x-n;
+ if(v <= 0.)
+ break;
+ }
+
+ /* last byte is not SF_MORE */
+ ends = &c[0] + sizeof(c) -1;
+ *ends &= ~SF_MORE;
+
+ /* write out coded bytes */
+ n = ends - s + 1;
+ w = SFWRITE(f,(Void_t*)s,n) == n ? w+n : -1;
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f,w);
+}
diff --git a/src/lib/libast/sfio/_sfputl.c b/src/lib/libast/sfio/_sfputl.c
new file mode 100644
index 0000000..df3d9a7
--- /dev/null
+++ b/src/lib/libast/sfio/_sfputl.c
@@ -0,0 +1,82 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write out a long value in a portable format
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int _sfputl(Sfio_t* f, Sflong_t v)
+#else
+int _sfputl(f,v)
+Sfio_t* f; /* write a portable long to this stream */
+Sflong_t v; /* the value to be written */
+#endif
+{
+#define N_ARRAY (2*sizeof(Sflong_t))
+ reg uchar *s, *ps;
+ reg ssize_t n, p;
+ uchar c[N_ARRAY];
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,-1);
+ if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ s = ps = &(c[N_ARRAY-1]);
+ if(v < 0)
+ { /* add 1 to avoid 2-complement problems with -SF_MAXINT */
+ v = -(v+1);
+ *s = (uchar)(SFSVALUE(v) | SF_SIGN);
+ }
+ else *s = (uchar)(SFSVALUE(v));
+ v = (Sfulong_t)v >> SF_SBITS;
+
+ while(v > 0)
+ { *--s = (uchar)(SFUVALUE(v) | SF_MORE);
+ v = (Sfulong_t)v >> SF_UBITS;
+ }
+ n = (ps-s)+1;
+
+ if(n > 8 || SFWPEEK(f,ps,p) < n)
+ n = SFWRITE(f,(Void_t*)s,n); /* write the hard way */
+ else
+ { switch(n)
+ {
+ case 8 : *ps++ = *s++;
+ case 7 : *ps++ = *s++;
+ case 6 : *ps++ = *s++;
+ case 5 : *ps++ = *s++;
+ case 4 : *ps++ = *s++;
+ case 3 : *ps++ = *s++;
+ case 2 : *ps++ = *s++;
+ case 1 : *ps++ = *s++;
+ }
+ f->next = ps;
+ }
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, n);
+}
diff --git a/src/lib/libast/sfio/_sfputm.c b/src/lib/libast/sfio/_sfputm.c
new file mode 100644
index 0000000..1fa9d9d
--- /dev/null
+++ b/src/lib/libast/sfio/_sfputm.c
@@ -0,0 +1,78 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write out an unsigned long value in a portable format.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int _sfputm(Sfio_t* f, Sfulong_t v, Sfulong_t m)
+#else
+int _sfputm(f,v,m)
+Sfio_t* f; /* write a portable ulong to this stream */
+Sfulong_t v; /* the unsigned value to be written */
+Sfulong_t m; /* the max value of the range */
+#endif
+{
+#define N_ARRAY (2*sizeof(Sfulong_t))
+ reg uchar *s, *ps;
+ reg ssize_t n, p;
+ uchar c[N_ARRAY];
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, -1);
+
+ if(v > m || (f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0) )
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ /* code v as integers in base SF_UBASE */
+ s = ps = &(c[N_ARRAY-1]);
+ *s = (uchar)SFBVALUE(v);
+ while((m >>= SF_BBITS) > 0 )
+ { v >>= SF_BBITS;
+ *--s = (uchar)SFBVALUE(v);
+ }
+ n = (ps-s)+1;
+
+ if(n > 8 || SFWPEEK(f,ps,p) < n)
+ n = SFWRITE(f,(Void_t*)s,n); /* write the hard way */
+ else
+ { switch(n)
+ {
+ case 8 : *ps++ = *s++;
+ case 7 : *ps++ = *s++;
+ case 6 : *ps++ = *s++;
+ case 5 : *ps++ = *s++;
+ case 4 : *ps++ = *s++;
+ case 3 : *ps++ = *s++;
+ case 2 : *ps++ = *s++;
+ case 1 : *ps++ = *s++;
+ }
+ f->next = ps;
+ }
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, (int)n);
+}
diff --git a/src/lib/libast/sfio/_sfputu.c b/src/lib/libast/sfio/_sfputu.c
new file mode 100644
index 0000000..e632d9d
--- /dev/null
+++ b/src/lib/libast/sfio/_sfputu.c
@@ -0,0 +1,75 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write out an unsigned long value in a portable format.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int _sfputu(Sfio_t* f, Sfulong_t v)
+#else
+int _sfputu(f,v)
+Sfio_t* f; /* write a portable ulong to this stream */
+Sfulong_t v; /* the unsigned value to be written */
+#endif
+{
+#define N_ARRAY (2*sizeof(Sfulong_t))
+ reg uchar *s, *ps;
+ reg ssize_t n, p;
+ uchar c[N_ARRAY];
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, -1);
+
+ if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ /* code v as integers in base SF_UBASE */
+ s = ps = &(c[N_ARRAY-1]);
+ *s = (uchar)SFUVALUE(v);
+ while((v >>= SF_UBITS) )
+ *--s = (uchar)(SFUVALUE(v) | SF_MORE);
+ n = (ps-s)+1;
+
+ if(n > 8 || SFWPEEK(f,ps,p) < n)
+ n = SFWRITE(f,(Void_t*)s,n); /* write the hard way */
+ else
+ { switch(n)
+ {
+ case 8 : *ps++ = *s++;
+ case 7 : *ps++ = *s++;
+ case 6 : *ps++ = *s++;
+ case 5 : *ps++ = *s++;
+ case 4 : *ps++ = *s++;
+ case 3 : *ps++ = *s++;
+ case 2 : *ps++ = *s++;
+ case 1 : *ps++ = *s++;
+ }
+ f->next = ps;
+ }
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, (int)n);
+}
diff --git a/src/lib/libast/sfio/_sfslen.c b/src/lib/libast/sfio/_sfslen.c
new file mode 100644
index 0000000..e34958e
--- /dev/null
+++ b/src/lib/libast/sfio/_sfslen.c
@@ -0,0 +1,33 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfslen
+
+#if __STD_C
+ssize_t sfslen(void)
+#else
+ssize_t sfslen()
+#endif
+{
+ return __sf_slen();
+}
diff --git a/src/lib/libast/sfio/_sfstacked.c b/src/lib/libast/sfio/_sfstacked.c
new file mode 100644
index 0000000..a785ed5
--- /dev/null
+++ b/src/lib/libast/sfio/_sfstacked.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfstacked
+
+#if __STD_C
+int sfstacked(reg Sfio_t* f)
+#else
+int sfstacked(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_stacked(f);
+}
diff --git a/src/lib/libast/sfio/_sfulen.c b/src/lib/libast/sfio/_sfulen.c
new file mode 100644
index 0000000..71bb258
--- /dev/null
+++ b/src/lib/libast/sfio/_sfulen.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfulen
+
+#if __STD_C
+int sfulen(reg Sfulong_t v)
+#else
+int sfulen(v)
+reg Sfulong_t v;
+#endif
+{
+ return __sf_ulen(v);
+}
diff --git a/src/lib/libast/sfio/_sfvalue.c b/src/lib/libast/sfio/_sfvalue.c
new file mode 100644
index 0000000..b8dcce7
--- /dev/null
+++ b/src/lib/libast/sfio/_sfvalue.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfvalue
+
+#if __STD_C
+ssize_t sfvalue(reg Sfio_t* f)
+#else
+ssize_t sfvalue(f)
+reg Sfio_t* f;
+#endif
+{
+ return __sf_value(f);
+}
diff --git a/src/lib/libast/sfio/sfclose.c b/src/lib/libast/sfio/sfclose.c
new file mode 100644
index 0000000..4fb6529
--- /dev/null
+++ b/src/lib/libast/sfio/sfclose.c
@@ -0,0 +1,178 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Close a stream. A file stream is synced before closing.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+int sfclose(Sfio_t* f)
+#else
+int sfclose(f)
+Sfio_t* f;
+#endif
+{
+ reg int local, ex, rv;
+ Void_t* data = NIL(Void_t*);
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f, -1);
+
+ GETLOCAL(f,local);
+
+ if(!(f->mode&SF_INIT) &&
+ SFMODE(f,local) != (f->mode&SF_RDWR) &&
+ SFMODE(f,local) != (f->mode&(SF_READ|SF_SYNCED)) &&
+ _sfmode(f,SF_SYNCED,local) < 0)
+ SFMTXRETURN(f,-1);
+
+ /* closing a stack of streams */
+ while(f->push)
+ { reg Sfio_t* pop;
+
+ if(!(pop = (*_Sfstack)(f,NIL(Sfio_t*))) )
+ SFMTXRETURN(f,-1);
+
+ if(sfclose(pop) < 0)
+ { (*_Sfstack)(f,pop);
+ SFMTXRETURN(f,-1);
+ }
+ }
+
+ rv = 0;
+ if(f->disc == _Sfudisc) /* closing the ungetc stream */
+ f->disc = NIL(Sfdisc_t*);
+ else if(f->file >= 0) /* sync file pointer */
+ { f->bits |= SF_ENDING;
+ rv = sfsync(f);
+ }
+
+ SFLOCK(f,0);
+
+ /* raise discipline exceptions */
+ if(f->disc && (ex = SFRAISE(f,local ? SF_NEW : SF_CLOSING,NIL(Void_t*))) != 0)
+ SFMTXRETURN(f,ex);
+
+ if(!local && f->pool)
+ { /* remove from pool */
+ if(f->pool == &_Sfpool)
+ { reg int n;
+
+ POOLMTXLOCK(&_Sfpool);
+ for(n = 0; n < _Sfpool.n_sf; ++n)
+ { if(_Sfpool.sf[n] != f)
+ continue;
+ /* found it */
+ _Sfpool.n_sf -= 1;
+ for(; n < _Sfpool.n_sf; ++n)
+ _Sfpool.sf[n] = _Sfpool.sf[n+1];
+ break;
+ }
+ POOLMTXUNLOCK(&_Sfpool);
+ }
+ else
+ { f->mode &= ~SF_LOCK; /**/ASSERT(_Sfpmove);
+ if((*_Sfpmove)(f,-1) < 0)
+ { SFOPEN(f,0);
+ SFMTXRETURN(f,-1);
+ }
+ f->mode |= SF_LOCK;
+ }
+ f->pool = NIL(Sfpool_t*);
+ }
+
+ if(f->data && (!local || (f->flags&SF_STRING) || (f->bits&SF_MMAP) ) )
+ { /* free buffer */
+#ifdef MAP_TYPE
+ if(f->bits&SF_MMAP)
+ SFMUNMAP(f,f->data,f->endb-f->data);
+ else
+#endif
+ if(f->flags&SF_MALLOC)
+ data = (Void_t*)f->data;
+
+ f->data = NIL(uchar*);
+ f->size = -1;
+ }
+
+ /* zap the file descriptor */
+ if(_Sfnotify)
+ (*_Sfnotify)(f, SF_CLOSING, (void*)((long)f->file));
+ if(f->file >= 0 && !(f->flags&SF_STRING))
+ { while(sysclosef(f->file) < 0 )
+ { if(errno == EINTR)
+ errno = 0;
+ else
+ { rv = -1;
+ break;
+ }
+ }
+ }
+ f->file = -1;
+
+ SFKILL(f);
+ f->flags &= SF_STATIC;
+ f->here = 0;
+ f->extent = -1;
+ f->endb = f->endr = f->endw = f->next = f->data;
+
+ /* zap any associated auxiliary buffer */
+ if(f->rsrv)
+ { free(f->rsrv);
+ f->rsrv = NIL(Sfrsrv_t*);
+ }
+
+ /* delete any associated sfpopen-data */
+ if(f->proc && _sfpclose(f) < 0 )
+ rv = -1;
+
+ /* destroy the mutex */
+ if(f->mutex)
+ { (void)vtmtxclrlock(f->mutex);
+ if(f != sfstdin && f != sfstdout && f != sfstderr)
+ { (void)vtmtxclose(f->mutex);
+ f->mutex = NIL(Vtmutex_t*);
+ }
+ }
+
+ if(!local)
+ { if(f->disc && (ex = SFRAISE(f,SF_FINAL,NIL(Void_t*))) != 0 )
+ { rv = ex;
+ goto done;
+ }
+
+ if(!(f->flags&SF_STATIC) )
+ free(f);
+ else
+ { f->disc = NIL(Sfdisc_t*);
+ f->stdio = NIL(Void_t*);
+ f->mode = SF_AVAIL;
+ }
+ }
+
+done:
+ if(data)
+ free(data);
+ return rv;
+}
diff --git a/src/lib/libast/sfio/sfclrlock.c b/src/lib/libast/sfio/sfclrlock.c
new file mode 100644
index 0000000..711756a
--- /dev/null
+++ b/src/lib/libast/sfio/sfclrlock.c
@@ -0,0 +1,63 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Function to clear a locked stream.
+** This is useful for programs that longjmp from the mid of an sfio function.
+** There is no guarantee on data integrity in such a case.
+**
+** Written by Kiem-Phong Vo
+*/
+#if __STD_C
+int sfclrlock(Sfio_t* f)
+#else
+int sfclrlock(f)
+Sfio_t *f;
+#endif
+{
+ int rv;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ /* already closed */
+ if(f && (f->mode&SF_AVAIL))
+ return 0;
+
+ SFMTXENTER(f,0);
+
+ /* clear error bits */
+ f->flags &= ~(SF_ERROR|SF_EOF);
+
+ /* clear peek locks */
+ if(f->mode&SF_PKRD)
+ { f->here -= f->endb-f->next;
+ f->endb = f->next;
+ }
+
+ SFCLRBITS(f);
+
+ /* throw away all lock bits except for stacking state SF_PUSH */
+ f->mode &= (SF_RDWR|SF_INIT|SF_POOL|SF_PUSH|SF_SYNCED|SF_STDIO);
+
+ rv = (f->mode&SF_PUSH) ? 0 : (f->flags&SF_FLAGS);
+
+ SFMTXRETURN(f, rv);
+}
diff --git a/src/lib/libast/sfio/sfcvt.c b/src/lib/libast/sfio/sfcvt.c
new file mode 100644
index 0000000..ca01f20
--- /dev/null
+++ b/src/lib/libast/sfio/sfcvt.c
@@ -0,0 +1,532 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if __STDC__
+#include "FEATURE/isoc99"
+#endif
+#include "sfhdr.h"
+
+/* Convert a floating point value to ASCII.
+**
+** Written by Kiem-Phong Vo and Glenn Fowler (SFFMT_AFORMAT)
+*/
+
+static char *lc_inf = "inf", *uc_inf = "INF";
+static char *lc_nan = "nan", *uc_nan = "NAN";
+static char *Zero = "0";
+#define SF_INF ((_Sfi = 3), strlcpy(buf, (format & SFFMT_UPPER) ? uc_inf : lc_inf, size), buf)
+#define SF_NAN ((_Sfi = 3), strlcpy(buf, (format & SFFMT_UPPER) ? uc_nan : lc_nan, size), buf)
+#define SF_ZERO ((_Sfi = 1), strlcpy(buf, Zero, size), buf)
+#define SF_INTPART (SF_IDIGITS/2)
+
+#if ! _lib_isnan
+#if _lib_fpclassify
+#define isnan(n) (fpclassify(n)==FP_NAN)
+#define isnanl(n) (fpclassify(n)==FP_NAN)
+#else
+#define isnan(n) (memcmp((void*)&n,(void*)&_Sfdnan,sizeof(n))==0)
+#define isnanl(n) (memcmp((void*)&n,(void*)&_Sflnan,sizeof(n))==0)
+#endif
+#else
+#if ! _lib_isnanl
+#define isnanl(n) isnan(n)
+#endif
+#endif
+
+#if ! _lib_signbit && defined(signbit)
+#undef _lib_signbit
+#define _lib_signbit 1
+#endif
+
+#if ! _lib_signbit
+#if ! _ast_fltmax_double
+static int neg0ld(Sfdouble_t f)
+{
+ Sfdouble_t z = -0.0;
+ return !memcmp(&f, &z, sizeof(f));
+}
+#endif
+static int neg0d(double f)
+{
+ double z = -0.0;
+ return !memcmp(&f, &z, sizeof(f));
+}
+#endif
+
+#if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
+#define CVT_LDBL_INT long
+#define CVT_LDBL_MAXINT LONG_MAX
+#else
+#if UINT_DIG && UINT_DIG < (DBL_DIG-1)
+#define CVT_LDBL_INT int
+#define CVT_LDBL_MAXINT INT_MAX
+#else
+#define CVT_LDBL_INT long
+#define CVT_LDBL_MAXINT SF_MAXLONG
+#endif
+#endif
+
+#if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
+#define CVT_DBL_INT long
+#define CVT_DBL_MAXINT LONG_MAX
+#else
+#if UINT_DIG && UINT_DIG < (DBL_DIG-1)
+#define CVT_DBL_INT int
+#define CVT_DBL_MAXINT INT_MAX
+#else
+#define CVT_DBL_INT long
+#define CVT_DBL_MAXINT SF_MAXLONG
+#endif
+#endif
+
+#if __STD_C
+char* _sfcvt(Void_t* vp, char* buf, size_t size, int n_digit,
+ int* decpt, int* sign, int* len, int format)
+#else
+char* _sfcvt(vp,buf,size,n_digit,decpt,sign,len,format)
+Void_t* vp; /* pointer to value to convert */
+char* buf; /* conversion goes here */
+size_t size; /* size of buf */
+int n_digit; /* number of digits wanted */
+int* decpt; /* to return decimal point */
+int* sign; /* to return sign */
+int* len; /* return string length */
+int format; /* conversion format */
+#endif
+{
+ reg char *sp;
+ reg long n, v;
+ reg char *ep, *b, *endsp, *t;
+ int x;
+ _ast_flt_unsigned_max_t m;
+
+ static char lx[] = "0123456789abcdef";
+ static char ux[] = "0123456789ABCDEF";
+
+ *sign = *decpt = 0;
+
+#if !_ast_fltmax_double
+ if(format&SFFMT_LDOUBLE)
+ { Sfdouble_t f = *(Sfdouble_t*)vp;
+
+ if(isnanl(f))
+ {
+#if _lib_signbit
+ if (signbit(f))
+#else
+ if (f < 0)
+#endif
+ *sign = 1;
+ return SF_NAN;
+ }
+#if _lib_isinf
+ if (n = isinf(f))
+ {
+#if _lib_signbit
+ if (signbit(f))
+#else
+ if (n < 0 || f < 0)
+#endif
+ *sign = 1;
+ return SF_INF;
+ }
+#endif
+# if _c99_in_the_wild
+# if _lib_signbit
+ if (signbit(f))
+# else
+# if _lib_copysignl
+ if (copysignl(1.0, f) < 0.0)
+# else
+# if _lib_copysign
+ if (copysign(1.0, (double)f) < 0.0)
+# else
+ if (f < 0.0)
+# endif
+# endif
+# endif
+ { f = -f;
+ *sign = 1;
+ }
+# if _lib_fpclassify
+ switch (fpclassify(f))
+ {
+ case FP_INFINITE:
+ return SF_INF;
+ case FP_NAN:
+ return SF_NAN;
+ case FP_ZERO:
+ return SF_ZERO;
+ }
+# endif
+# else
+# if _lib_signbit
+ if (signbit(f))
+# else
+ if (f < 0.0 || f == 0.0 && neg0ld(f))
+# endif
+ { f = -f;
+ *sign = 1;
+ }
+# endif
+ if(f < LDBL_MIN)
+ return SF_ZERO;
+ if(f > LDBL_MAX)
+ return SF_INF;
+
+ if(format & SFFMT_AFORMAT)
+ { Sfdouble_t g;
+ b = sp = buf;
+ ep = (format & SFFMT_UPPER) ? ux : lx;
+ if(n_digit <= 0 || n_digit >= (size - 9))
+ n_digit = size - 9;
+ endsp = sp + n_digit + 1;
+
+ g = frexpl(f, &x);
+ *decpt = x;
+ f = ldexpl(g, 8 * sizeof(m) - 3);
+
+ for (;;)
+ { m = f;
+ x = 8 * sizeof(m);
+ while ((x -= 4) >= 0)
+ { *sp++ = ep[(m >> x) & 0xf];
+ if (sp >= endsp)
+ goto around;
+ }
+ f -= m;
+ f = ldexpl(f, 8 * sizeof(m));
+ }
+ }
+
+ n = 0;
+ if(f >= (Sfdouble_t)CVT_LDBL_MAXINT)
+ { /* scale to a small enough number to fit an int */
+ v = SF_MAXEXP10-1;
+ do
+ { if(f < _Sfpos10[v])
+ v -= 1;
+ else
+ {
+ f *= _Sfneg10[v];
+ if((n += (1<<v)) >= SF_IDIGITS)
+ return SF_INF;
+ }
+ } while(f >= (Sfdouble_t)CVT_LDBL_MAXINT);
+ }
+ else if(f > 0.0 && f < 0.1)
+ { /* scale to avoid excessive multiply by 10 below */
+ v = SF_MAXEXP10-1;
+ do
+ { if(f <= _Sfneg10[v])
+ { f *= _Sfpos10[v];
+ if((n += (1<<v)) >= SF_IDIGITS)
+ return SF_INF;
+ }
+ else if (--v < 0)
+ break;
+ } while(f < 0.1);
+ n = -n;
+ }
+ *decpt = (int)n;
+
+ b = sp = buf + SF_INTPART;
+ if((v = (CVT_LDBL_INT)f) != 0)
+ { /* translate the integer part */
+ f -= (Sfdouble_t)v;
+
+ sfucvt(v,sp,n,ep,CVT_LDBL_INT,unsigned CVT_LDBL_INT);
+
+ n = b-sp;
+ if((*decpt += (int)n) >= SF_IDIGITS)
+ return SF_INF;
+ b = sp;
+ sp = buf + SF_INTPART;
+ }
+ else n = 0;
+
+ /* remaining number of digits to compute; add 1 for later rounding */
+ n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n;
+ if(n_digit > 0)
+ { if(n_digit > LDBL_DIG)
+ n_digit = LDBL_DIG;
+ n += n_digit;
+ }
+
+ if((ep = (sp+n)) > (endsp = buf+(size-2)))
+ ep = endsp;
+ if(sp > ep)
+ sp = ep;
+ else
+ {
+ if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.)
+ { Sfdouble_t d;
+ while((long)(d = f*10.) == 0)
+ { f = d;
+ *decpt -= 1;
+ }
+ }
+
+ while(sp < ep)
+ { /* generate fractional digits */
+ if(f <= 0.)
+ { /* fill with 0's */
+ do { *sp++ = '0'; } while(sp < ep);
+ goto done;
+ }
+ else if((n = (long)(f *= 10.)) < 10)
+ { *sp++ = '0' + n;
+ f -= n;
+ }
+ else /* n == 10 */
+ { do { *sp++ = '9'; } while(sp < ep);
+ }
+ }
+ }
+ } else
+#endif
+ { double f = *(double*)vp;
+
+ if(isnan(f))
+ {
+#if _lib_signbit
+ if (signbit(f))
+#else
+ if (f < 0)
+#endif
+ *sign = 1;
+ return SF_NAN;
+ }
+#if _lib_isinf
+ if (n = isinf(f))
+ {
+#if _lib_signbit
+ if (signbit(f))
+#else
+ if (n < 0 || f < 0)
+#endif
+ *sign = 1;
+ return SF_INF;
+ }
+#endif
+#if _c99_in_the_wild
+# if _lib_signbit
+ if (signbit(f))
+# else
+# if _lib_copysign
+ if (copysign(1.0, f) < 0.0)
+# else
+ if (f < 0.0)
+# endif
+# endif
+ { f = -f;
+ *sign = 1;
+ }
+# if _lib_fpclassify
+ switch (fpclassify(f))
+ {
+ case FP_INFINITE:
+ return SF_INF;
+ case FP_NAN:
+ return SF_NAN;
+ case FP_ZERO:
+ return SF_ZERO;
+ }
+# endif
+#else
+# if _lib_signbit
+ if (signbit(f))
+# else
+ if (f < 0.0 || f == 0.0 && neg0d(f))
+# endif
+ { f = -f;
+ *sign = 1;
+ }
+#endif
+ if(f < DBL_MIN)
+ return SF_ZERO;
+ if(f > DBL_MAX)
+ return SF_INF;
+
+ if(format & SFFMT_AFORMAT)
+ { double g;
+ b = sp = buf;
+ ep = (format & SFFMT_UPPER) ? ux : lx;
+ if(n_digit <= 0 || n_digit >= (size - 9))
+ n_digit = size - 9;
+ endsp = sp + n_digit + 1;
+
+ g = frexp(f, &x);
+ *decpt = x;
+ f = ldexp(g, 8 * sizeof(m) - 3);
+
+ for (;;)
+ { m = f;
+ x = 8 * sizeof(m);
+ while ((x -= 4) >= 0)
+ { *sp++ = ep[(m >> x) & 0xf];
+ if (sp >= endsp)
+ goto around;
+ }
+ f -= m;
+ f = ldexp(f, 8 * sizeof(m));
+ }
+ }
+ n = 0;
+ if(f >= (double)CVT_DBL_MAXINT)
+ { /* scale to a small enough number to fit an int */
+ v = SF_MAXEXP10-1;
+ do
+ { if(f < _Sfpos10[v])
+ v -= 1;
+ else
+ { f *= _Sfneg10[v];
+ if((n += (1<<v)) >= SF_IDIGITS)
+ return SF_INF;
+ }
+ } while(f >= (double)CVT_DBL_MAXINT);
+ }
+ else if(f > 0.0 && f < 1e-8)
+ { /* scale to avoid excessive multiply by 10 below */
+ v = SF_MAXEXP10-1;
+ do
+ { if(f <= _Sfneg10[v])
+ { f *= _Sfpos10[v];
+ if((n += (1<<v)) >= SF_IDIGITS)
+ return SF_INF;
+ }
+ else if(--v < 0)
+ break;
+ } while(f < 0.1);
+ n = -n;
+ }
+ *decpt = (int)n;
+
+ b = sp = buf + SF_INTPART;
+ if((v = (CVT_DBL_INT)f) != 0)
+ { /* translate the integer part */
+ f -= (double)v;
+
+ sfucvt(v,sp,n,ep,CVT_DBL_INT,unsigned CVT_DBL_INT);
+
+ n = b-sp;
+ if((*decpt += (int)n) >= SF_IDIGITS)
+ return SF_INF;
+ b = sp;
+ sp = buf + SF_INTPART;
+ }
+ else n = 0;
+
+ /* remaining number of digits to compute; add 1 for later rounding */
+ n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n;
+ if(n_digit > 0)
+ { if(n_digit > DBL_DIG)
+ n_digit = DBL_DIG;
+ n += n_digit;
+ }
+
+ if((ep = (sp+n)) > (endsp = buf+(size-2)))
+ ep = endsp;
+ if(sp > ep)
+ sp = ep;
+ else
+ {
+ if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.)
+ { reg double d;
+ while((long)(d = f*10.) == 0)
+ { f = d;
+ *decpt -= 1;
+ }
+ }
+
+ while(sp < ep)
+ { /* generate fractional digits */
+ if(f <= 0.)
+ { /* fill with 0's */
+ do { *sp++ = '0'; } while(sp < ep);
+ goto done;
+ }
+ else if((n = (long)(f *= 10.)) < 10)
+ { *sp++ = (char)('0' + n);
+ f -= n;
+ }
+ else /* n == 10 */
+ { do { *sp++ = '9'; } while(sp < ep);
+ break;
+ }
+ }
+ }
+ }
+
+ if(ep <= b)
+ ep = b+1;
+ else if(ep < endsp)
+ { /* round the last digit */
+ *--sp += 5;
+ while(*sp > '9')
+ { *sp = '0';
+ if(sp > b)
+ *--sp += 1;
+ else
+ { /* next power of 10 */
+ *sp = '1';
+ *decpt += 1;
+ if(!(format&SFFMT_EFORMAT))
+ { /* add one more 0 for %f precision */
+ ep[-1] = '0';
+ ep += 1;
+ }
+ }
+ }
+ }
+
+ done:
+ *--ep = '\0';
+ if(len)
+ *len = ep-b;
+ return b;
+ around:
+ if (((m >> x) & 0xf) >= 8)
+ { t = sp - 1;
+ for (;;)
+ { if (--t <= b)
+ { (*decpt)++;
+ break;
+ }
+ switch (*t)
+ {
+ case 'f':
+ case 'F':
+ *t = '0';
+ continue;
+ case '9':
+ *t = ep[10];
+ break;
+ default:
+ (*t)++;
+ break;
+ }
+ break;
+ }
+ }
+ ep = sp + 1;
+ goto done;
+}
diff --git a/src/lib/libast/sfio/sfdisc.c b/src/lib/libast/sfio/sfdisc.c
new file mode 100644
index 0000000..8ffc559
--- /dev/null
+++ b/src/lib/libast/sfio/sfdisc.c
@@ -0,0 +1,271 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Add a new discipline to the discipline stack. Each discipline
+** provides alternative I/O functions that are analogues of the
+** system calls.
+**
+** When the application fills or flushes the stream buffer, data
+** will be processed through discipline functions. A case deserving
+** consideration is stacking a discipline onto a read stream. Each
+** discipline operation implies buffer synchronization so the stream
+** buffer should be empty. However, a read stream representing an
+** unseekable device (eg, a pipe) may not be synchronizable. In that
+** case, any buffered data must then be fed to the new discipline
+** to preserve data processing semantics. This is done by creating
+** a temporary discipline to cache such buffered data and feed
+** them to the new discipline when its readf() asks for new data.
+** Care must then be taken to remove this temporary discipline
+** when it runs out of cached data.
+**
+** Written by Kiem-Phong Vo
+*/
+
+typedef struct _dccache_s
+{ Sfdisc_t disc;
+ uchar* data;
+ uchar* endb;
+} Dccache_t;
+
+#if __STD_C
+static int _dccaexcept(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc)
+#else
+static int _dccaexcept(f,type,val,disc)
+Sfio_t* f;
+int type;
+Void_t* val;
+Sfdisc_t* disc;
+#endif
+{
+ if(disc && type == SF_FINAL)
+ free(disc);
+ return 0;
+}
+
+#if __STD_C
+static ssize_t _dccaread(Sfio_t* f, Void_t* buf, size_t size, Sfdisc_t* disc)
+#else
+static ssize_t _dccaread(f, buf, size, disc)
+Sfio_t* f;
+Void_t* buf;
+size_t size;
+Sfdisc_t* disc;
+#endif
+{
+ ssize_t sz;
+ Sfdisc_t *prev;
+ Dccache_t *dcca;
+
+ if(!f) /* bad stream */
+ return -1;
+
+ /* make sure that this is on the discipline stack */
+ for(prev = f->disc; prev; prev = prev->disc)
+ if(prev->disc == disc)
+ break;
+ if(!prev)
+ return -1;
+
+ if(size <= 0) /* nothing to do */
+ return size;
+
+ /* read from available data */
+ dcca = (Dccache_t*)disc;
+ if((sz = dcca->endb - dcca->data) > (ssize_t)size)
+ sz = (ssize_t)size;
+ memcpy(buf, dcca->data, sz);
+
+ if((dcca->data += sz) >= dcca->endb) /* free empty cache */
+ { prev->disc = disc->disc;
+ free(disc);
+ }
+
+ return sz;
+}
+
+#if __STD_C
+Sfdisc_t* sfdisc(Sfio_t* f, Sfdisc_t* disc)
+#else
+Sfdisc_t* sfdisc(f,disc)
+Sfio_t* f;
+Sfdisc_t* disc;
+#endif
+{
+ Sfdisc_t *d, *rdisc;
+ Sfread_f oreadf;
+ Sfwrite_f owritef;
+ Sfseek_f oseekf;
+ ssize_t n;
+ Dccache_t *dcca = NIL(Dccache_t*);
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f, NIL(Sfdisc_t*));
+
+ if((Sfio_t*)disc == f) /* special case to get the top discipline */
+ SFMTXRETURN(f,f->disc);
+
+ if((f->flags&SF_READ) && f->proc && (f->mode&SF_WRITE) )
+ { /* make sure in read mode to check for read-ahead data */
+ if(_sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, NIL(Sfdisc_t*));
+ }
+ else
+ { if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
+ SFMTXRETURN(f, NIL(Sfdisc_t*));
+ }
+
+ SFLOCK(f,0);
+ rdisc = NIL(Sfdisc_t*);
+
+ /* disallow popping while there is cached data */
+ if(!disc && f->disc && f->disc->disc && f->disc->disc->readf == _dccaread )
+ goto done;
+
+ /* synchronize before switching to a new discipline */
+ if(!(f->flags&SF_STRING))
+ { (void)SFSYNC(f); /* do a silent buffer synch */
+ if((f->mode&SF_READ) && (f->mode&SF_SYNCED) )
+ { f->mode &= ~SF_SYNCED;
+ f->endb = f->next = f->endr = f->endw = f->data;
+ }
+
+ /* if there is buffered data, ask app before proceeding */
+ if(((f->mode&SF_WRITE) && (n = f->next-f->data) > 0) ||
+ ((f->mode&SF_READ) && (n = f->endb-f->next) > 0) )
+ { int rv = 0;
+ if(rv == 0 && f->disc && f->disc->exceptf) /* ask current discipline */
+ { SFOPEN(f,0);
+ rv = (*f->disc->exceptf)(f, SF_DBUFFER, &n, f->disc);
+ SFLOCK(f,0);
+ }
+ if(rv == 0 && disc && disc->exceptf) /* ask discipline being pushed */
+ { SFOPEN(f,0);
+ rv = (*disc->exceptf)(f, SF_DBUFFER, &n, disc);
+ SFLOCK(f,0);
+ }
+ if(rv < 0)
+ goto done;
+ }
+
+ /* trick the new discipline into processing already buffered data */
+ if((f->mode&SF_READ) && n > 0 && disc && disc->readf )
+ { if(!(dcca = (Dccache_t*)malloc(sizeof(Dccache_t)+n)) )
+ goto done;
+ memclear(dcca, sizeof(Dccache_t));
+
+ dcca->disc.readf = _dccaread;
+ dcca->disc.exceptf = _dccaexcept;
+
+ /* move buffered data into the temp discipline */
+ dcca->data = ((uchar*)dcca) + sizeof(Dccache_t);
+ dcca->endb = dcca->data + n;
+ memcpy(dcca->data, f->next, n);
+ f->endb = f->next = f->endr = f->endw = f->data;
+ }
+ }
+
+ /* save old readf, writef, and seekf to see if stream need reinit */
+#define GETDISCF(func,iof,type) \
+ { for(d = f->disc; d && !d->iof; d = d->disc) ; \
+ func = d ? d->iof : NIL(type); \
+ }
+ GETDISCF(oreadf,readf,Sfread_f);
+ GETDISCF(owritef,writef,Sfwrite_f);
+ GETDISCF(oseekf,seekf,Sfseek_f);
+
+ if(disc == SF_POPDISC)
+ { /* popping, warn the being popped discipline */
+ if(!(d = f->disc) )
+ goto done;
+ disc = d->disc;
+ if(d->exceptf)
+ { SFOPEN(f,0);
+ if((*(d->exceptf))(f,SF_DPOP,(Void_t*)disc,d) < 0 )
+ goto done;
+ SFLOCK(f,0);
+ }
+ f->disc = disc;
+ rdisc = d;
+ }
+ else
+ { /* pushing, warn being pushed discipline */
+ do
+ { /* loop to handle the case where d may pop itself */
+ d = f->disc;
+ if(d && d->exceptf)
+ { SFOPEN(f,0);
+ if( (*(d->exceptf))(f,SF_DPUSH,(Void_t*)disc,d) < 0 )
+ goto done;
+ SFLOCK(f,0);
+ }
+ } while(d != f->disc);
+
+ /* make sure we are not creating an infinite loop */
+ for(; d; d = d->disc)
+ if(d == disc)
+ goto done;
+
+ /* set new disc */
+ if(dcca) /* insert the discipline with cached data */
+ { dcca->disc.disc = f->disc;
+ disc->disc = &dcca->disc;
+ }
+ else disc->disc = f->disc;
+ f->disc = disc;
+ rdisc = disc;
+ }
+
+ if(!(f->flags&SF_STRING) )
+ { /* this stream may have to be reinitialized */
+ reg int reinit = 0;
+#define DISCF(dst,iof,type) (dst ? dst->iof : NIL(type))
+#define REINIT(oiof,iof,type) \
+ if(!reinit) \
+ { for(d = f->disc; d && !d->iof; d = d->disc) ; \
+ if(DISCF(d,iof,type) != oiof) \
+ reinit = 1; \
+ }
+
+ REINIT(oreadf,readf,Sfread_f);
+ REINIT(owritef,writef,Sfwrite_f);
+ REINIT(oseekf,seekf,Sfseek_f);
+
+ if(reinit)
+ { SETLOCAL(f);
+ f->bits &= ~SF_NULL; /* turn off /dev/null handling */
+ if((f->bits&SF_MMAP) || (f->mode&SF_INIT))
+ sfsetbuf(f,NIL(Void_t*),(size_t)SF_UNBOUND);
+ else if(f->data == f->tiny)
+ sfsetbuf(f,NIL(Void_t*),0);
+ else
+ { int flags = f->flags;
+ sfsetbuf(f,(Void_t*)f->data,f->size);
+ f->flags |= (flags&SF_MALLOC);
+ }
+ }
+ }
+
+done :
+ SFOPEN(f,0);
+ SFMTXRETURN(f, rdisc);
+}
diff --git a/src/lib/libast/sfio/sfdlen.c b/src/lib/libast/sfio/sfdlen.c
new file mode 100644
index 0000000..69d6cb4
--- /dev/null
+++ b/src/lib/libast/sfio/sfdlen.c
@@ -0,0 +1,58 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Return the length of a double value if coded in a portable format
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+int _sfdlen(Sfdouble_t v)
+#else
+int _sfdlen(v)
+Sfdouble_t v;
+#endif
+{
+#define N_ARRAY (16*sizeof(Sfdouble_t))
+ reg int n, w;
+ Sfdouble_t x;
+ int exp;
+
+ if(v < 0)
+ v = -v;
+
+ /* make the magnitude of v < 1 */
+ if(v != 0.)
+ v = frexpl(v,&exp);
+ else exp = 0;
+
+ for(w = 1; w <= N_ARRAY; ++w)
+ { /* get 2^SF_PRECIS precision at a time */
+ n = (int)(x = ldexpl(v,SF_PRECIS));
+ v = x-n;
+ if(v <= 0.)
+ break;
+ }
+
+ return 1 + sfulen(exp) + w;
+}
diff --git a/src/lib/libast/sfio/sfecvt.c b/src/lib/libast/sfio/sfecvt.c
new file mode 100644
index 0000000..35d034b
--- /dev/null
+++ b/src/lib/libast/sfio/sfecvt.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#if __STD_C
+char* sfecvt(double dval, int n_digit, int* decpt, int* sign)
+#else
+char* sfecvt(dval,n_digit,decpt,sign)
+double dval; /* value to convert */
+int n_digit; /* number of digits wanted */
+int* decpt; /* to return decimal point */
+int* sign; /* to return sign */
+#endif
+{
+ int len;
+ static char buf[SF_MAXDIGITS];
+
+ return _sfcvt(&dval,buf,sizeof(buf),n_digit,decpt,sign,&len,SFFMT_EFORMAT);
+}
diff --git a/src/lib/libast/sfio/sfexcept.c b/src/lib/libast/sfio/sfexcept.c
new file mode 100644
index 0000000..fc08d6e
--- /dev/null
+++ b/src/lib/libast/sfio/sfexcept.c
@@ -0,0 +1,133 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Function to handle io exceptions.
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+int _sfexcept(Sfio_t* f, int type, ssize_t io, Sfdisc_t* disc)
+#else
+int _sfexcept(f,type,io,disc)
+Sfio_t* f; /* stream where the exception happened */
+int type; /* io type that was performed */
+ssize_t io; /* the io return value that indicated exception */
+Sfdisc_t* disc; /* discipline in use */
+#endif
+{
+ reg int ev, local, lock;
+ reg ssize_t size;
+ reg uchar* data;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f,-1);
+
+ GETLOCAL(f,local);
+ lock = f->mode&SF_LOCK;
+
+ if(local && io <= 0)
+ f->flags |= io < 0 ? SF_ERROR : SF_EOF;
+
+ if(disc && disc->exceptf)
+ { /* let the stream be generally accessible for this duration */
+ if(local && lock)
+ SFOPEN(f,0);
+
+ /* so that exception handler knows what we are asking for */
+ _Sfi = f->val = io;
+ ev = (*(disc->exceptf))(f,type,&io,disc);
+
+ /* relock if necessary */
+ if(local && lock)
+ SFLOCK(f,0);
+
+ if(io > 0 && !(f->flags&SF_STRING) )
+ SFMTXRETURN(f, ev);
+ if(ev < 0)
+ SFMTXRETURN(f, SF_EDONE);
+ if(ev > 0)
+ SFMTXRETURN(f, SF_EDISC);
+ }
+
+ if(f->flags&SF_STRING)
+ { if(type == SF_READ)
+ goto chk_stack;
+ else if(type != SF_WRITE && type != SF_SEEK)
+ SFMTXRETURN(f, SF_EDONE);
+ if(local && io >= 0)
+ { if(f->size >= 0 && !(f->flags&SF_MALLOC))
+ goto chk_stack;
+ /* extend buffer */
+ if((size = f->size) < 0)
+ size = 0;
+ if((io -= size) <= 0)
+ io = SF_GRAIN;
+ size = ((size+io+SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
+ if(f->size > 0)
+ data = (uchar*)realloc((char*)f->data,size);
+ else data = (uchar*)malloc(size);
+ if(!data)
+ goto chk_stack;
+ f->endb = data + size;
+ f->next = data + (f->next - f->data);
+ f->endr = f->endw = f->data = data;
+ f->size = size;
+ }
+ SFMTXRETURN(f, SF_EDISC);
+ }
+
+ if(errno == EINTR)
+ { if(_Sfexiting || (f->bits&SF_ENDING) || /* stop being a hero */
+ (f->flags&SF_IOINTR) ) /* application requests to return */
+ SFMTXRETURN(f, SF_EDONE);
+
+ /* a normal interrupt, we can continue */
+ errno = 0;
+ f->flags &= ~(SF_EOF|SF_ERROR);
+ SFMTXRETURN(f, SF_ECONT);
+ }
+
+chk_stack:
+ if(local && f->push &&
+ ((type == SF_READ && f->next >= f->endb) ||
+ (type == SF_WRITE && f->next <= f->data)))
+ { /* pop the stack */
+ reg Sfio_t *pf;
+
+ if(lock)
+ SFOPEN(f,0);
+
+ /* pop and close */
+ pf = (*_Sfstack)(f,NIL(Sfio_t*));
+ if((ev = sfclose(pf)) < 0) /* can't close, restack */
+ (*_Sfstack)(f,pf);
+
+ if(lock)
+ SFLOCK(f,0);
+
+ ev = ev < 0 ? SF_EDONE : SF_ESTACK;
+ }
+ else ev = SF_EDONE;
+
+ SFMTXRETURN(f, ev);
+}
diff --git a/src/lib/libast/sfio/sfextern.c b/src/lib/libast/sfio/sfextern.c
new file mode 100644
index 0000000..e5f2c6e
--- /dev/null
+++ b/src/lib/libast/sfio/sfextern.c
@@ -0,0 +1,99 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* External variables and functions used only by Sfio
+** Written by Kiem-Phong Vo
+*/
+
+/* code to initialize mutexes */
+static Vtmutex_t Sfmutex;
+static Vtonce_t Sfonce = VTONCE_INITDATA;
+static void _sfoncef()
+{ (void)vtmtxopen(_Sfmutex, VT_INIT);
+ (void)vtmtxopen(&_Sfpool.mutex, VT_INIT);
+ (void)vtmtxopen(sfstdin->mutex, VT_INIT);
+ (void)vtmtxopen(sfstdout->mutex, VT_INIT);
+ (void)vtmtxopen(sfstderr->mutex, VT_INIT);
+ _Sfdone = 1;
+}
+
+/* global variables used internally to the package */
+Sfextern_t _Sfextern =
+{ 0, /* _Sfpage */
+ { NIL(Sfpool_t*), 0, 0, 0, NIL(Sfio_t**) }, /* _Sfpool */
+ NIL(int(*)_ARG_((Sfio_t*,int))), /* _Sfpmove */
+ NIL(Sfio_t*(*)_ARG_((Sfio_t*, Sfio_t*))), /* _Sfstack */
+ NIL(void(*)_ARG_((Sfio_t*, int, void*))), /* _Sfnotify */
+ NIL(int(*)_ARG_((Sfio_t*))), /* _Sfstdsync */
+ { NIL(Sfread_f), /* _Sfudisc */
+ NIL(Sfwrite_f),
+ NIL(Sfseek_f),
+ NIL(Sfexcept_f),
+ NIL(Sfdisc_t*)
+ },
+ NIL(void(*)_ARG_((void)) ), /* _Sfcleanup */
+ 0, /* _Sfexiting */
+ 0, /* _Sfdone */
+ &Sfonce, /* _Sfonce */
+ _sfoncef, /* _Sfoncef */
+ &Sfmutex /* _Sfmutex */
+};
+
+ssize_t _Sfi = -1; /* value for a few fast macro functions */
+ssize_t _Sfmaxr = 0; /* default (unlimited) max record size */
+
+#if vt_threaded
+static Vtmutex_t _Sfmtxin, _Sfmtxout, _Sfmtxerr;
+#define SFMTXIN (&_Sfmtxin)
+#define SFMTXOUT (&_Sfmtxout)
+#define SFMTXERR (&_Sfmtxerr)
+#define SF_STDSAFE SF_MTSAFE
+#else
+#define SFMTXIN (0)
+#define SFMTXOUT (0)
+#define SFMTXERR (0)
+#define SF_STDSAFE (0)
+#endif
+
+Sfio_t _Sfstdin = SFNEW(NIL(char*),-1,0,
+ (SF_READ |SF_STATIC|SF_STDSAFE),NIL(Sfdisc_t*),SFMTXIN);
+Sfio_t _Sfstdout = SFNEW(NIL(char*),-1,1,
+ (SF_WRITE|SF_STATIC|SF_STDSAFE),NIL(Sfdisc_t*),SFMTXOUT);
+Sfio_t _Sfstderr = SFNEW(NIL(char*),-1,2,
+ (SF_WRITE|SF_STATIC|SF_STDSAFE),NIL(Sfdisc_t*),SFMTXERR);
+
+#undef sfstdin
+#undef sfstdout
+#undef sfstderr
+
+Sfio_t* sfstdin = &_Sfstdin;
+Sfio_t* sfstdout = &_Sfstdout;
+Sfio_t* sfstderr = &_Sfstderr;
+
+__EXTERN__(ssize_t,_Sfi);
+__EXTERN__(Sfio_t,_Sfstdin);
+__EXTERN__(Sfio_t,_Sfstdout);
+__EXTERN__(Sfio_t,_Sfstderr);
+__EXTERN__(Sfio_t*,sfstdin);
+__EXTERN__(Sfio_t*,sfstdout);
+__EXTERN__(Sfio_t*,sfstderr);
diff --git a/src/lib/libast/sfio/sffcvt.c b/src/lib/libast/sfio/sffcvt.c
new file mode 100644
index 0000000..ade6d5e
--- /dev/null
+++ b/src/lib/libast/sfio/sffcvt.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#if __STD_C
+char *sffcvt(double dval, int n_digit, int* decpt, int* sign)
+#else
+char *sffcvt(dval,n_digit,decpt,sign)
+double dval; /* value to convert */
+int n_digit; /* number of digits wanted */
+int* decpt; /* to return decimal point */
+int* sign; /* to return sign */
+#endif
+{
+ int len;
+ static char buf[SF_MAXDIGITS];
+
+ return _sfcvt(&dval,buf,sizeof(buf),n_digit,decpt,sign,&len,0);
+}
diff --git a/src/lib/libast/sfio/sffilbuf.c b/src/lib/libast/sfio/sffilbuf.c
new file mode 100644
index 0000000..16d5e3a
--- /dev/null
+++ b/src/lib/libast/sfio/sffilbuf.c
@@ -0,0 +1,116 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Fill the buffer of a stream with data.
+** If n < 0, sffilbuf() attempts to fill the buffer if it's empty.
+** If n == 0, if the buffer is not empty, just return the first byte;
+** otherwise fill the buffer and return the first byte.
+** If n > 0, even if the buffer is not empty, try a read to get as
+** close to n as possible. n is reset to -1 if stack pops.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+int _sffilbuf(Sfio_t* f, reg int n)
+#else
+int _sffilbuf(f,n)
+Sfio_t* f; /* fill the read buffer of this stream */
+reg int n; /* see above */
+#endif
+{
+ reg ssize_t r;
+ reg int first, local, rcrv, rc, justseek;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f,-1);
+
+ GETLOCAL(f,local);
+
+ /* any peek data must be preserved across stacked streams */
+ rcrv = f->mode&(SF_RC|SF_RV|SF_LOCK);
+ rc = f->getr;
+
+ justseek = f->bits&SF_JUSTSEEK; f->bits &= ~SF_JUSTSEEK;
+
+ for(first = 1;; first = 0, (f->mode &= ~SF_LOCK) )
+ { /* check mode */
+ if(SFMODE(f,local) != SF_READ && _sfmode(f,SF_READ,local) < 0)
+ SFMTXRETURN(f,-1);
+ SFLOCK(f,local);
+
+ /* current extent of available data */
+ if((r = f->endb-f->next) > 0)
+ { /* on first iteration, n is amount beyond current buffer;
+ afterward, n is the exact amount requested */
+ if((first && n <= 0) || (!first && n <= r) ||
+ (f->flags&SF_STRING))
+ break;
+
+ /* try shifting left to make room for new data */
+ if(!(f->bits&SF_MMAP) && f->next > f->data &&
+ n > (f->size - (f->endb-f->data)) )
+ { ssize_t s = r;
+
+ /* try to maintain block alignment */
+ if(f->blksz > 0 && (f->here%f->blksz) == 0 )
+ { s = ((r + f->blksz-1)/f->blksz)*f->blksz;
+ if(s+n > f->size)
+ s = r;
+ }
+
+ memmove(f->data, f->endb-s, s);
+ f->next = f->data + (s-r);
+ f->endb = f->data + s;
+ }
+ }
+ else if(!(f->flags&SF_STRING) && !(f->bits&SF_MMAP) )
+ f->next = f->endb = f->endr = f->data;
+
+ if(f->bits&SF_MMAP)
+ r = n > 0 ? n : f->size;
+ else if(!(f->flags&SF_STRING) )
+ { r = f->size - (f->endb - f->data); /* available buffer */
+ if(n > 0)
+ { if(r > n && f->extent < 0 && (f->flags&SF_SHARE) )
+ r = n; /* read only as much as requested */
+ else if(justseek && n <= f->iosz && f->iosz <= f->size)
+ r = f->iosz; /* limit buffer filling */
+ }
+ }
+
+ /* SFRD takes care of discipline read and stack popping */
+ f->mode |= rcrv;
+ f->getr = rc;
+ if((r = SFRD(f,f->endb,r,f->disc)) >= 0)
+ { r = f->endb - f->next;
+ break;
+ }
+ }
+
+ SFOPEN(f,local);
+
+ rcrv = (n == 0) ? (r > 0 ? (int)(*f->next++) : EOF) : (int)r;
+
+ SFMTXRETURN(f,rcrv);
+}
diff --git a/src/lib/libast/sfio/sfflsbuf.c b/src/lib/libast/sfio/sfflsbuf.c
new file mode 100644
index 0000000..36d78dc
--- /dev/null
+++ b/src/lib/libast/sfio/sfflsbuf.c
@@ -0,0 +1,126 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write a buffer out to a file descriptor or
+** extending a buffer for a SF_STRING stream.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+int _sfflsbuf(Sfio_t* f, int c)
+#else
+int _sfflsbuf(f,c)
+Sfio_t* f; /* write out the buffered content of this stream */
+int c; /* if c>=0, c is also written out */
+#endif
+{
+ ssize_t n, w, written;
+ uchar* data;
+ uchar outc;
+ int local, isall;
+ int inpc = c;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f,-1);
+
+ GETLOCAL(f,local);
+
+ for(written = 0;; f->mode &= ~SF_LOCK)
+ { /* check stream mode */
+ if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,local);
+
+ /* current data extent */
+ n = f->next - (data = f->data);
+
+ if(n == (f->endb-data) && (f->flags&SF_STRING))
+ { /* call sfwr() to extend string buffer and process events */
+ w = ((f->bits&SF_PUTR) && f->val > 0) ? f->val : 1;
+ (void)SFWR(f, data, w, f->disc);
+
+ /* !(f->flags&SF_STRING) is required because exception
+ handlers may turn a string stream to a file stream */
+ if(f->next < f->endb || !(f->flags&SF_STRING) )
+ n = f->next - (data = f->data);
+ else
+ { SFOPEN(f,local);
+ SFMTXRETURN(f, -1);
+ }
+ }
+
+ if(c >= 0)
+ { /* write into buffer */
+ if(n < (f->endb - (data = f->data)))
+ { *f->next++ = c;
+ if(c == '\n' &&
+ (f->flags&SF_LINE) && !(f->flags&SF_STRING))
+ { c = -1;
+ n += 1;
+ }
+ else break;
+ }
+ else if(n == 0)
+ { /* unbuffered io */
+ outc = (uchar)c;
+ data = &outc;
+ c = -1;
+ n = 1;
+ }
+ }
+
+ if(n == 0 || (f->flags&SF_STRING))
+ break;
+
+ isall = SFISALL(f,isall);
+ if((w = SFWR(f,data,n,f->disc)) > 0)
+ { if((n -= w) > 0) /* save unwritten data, then resume */
+ memcpy((char*)f->data,(char*)data+w,n);
+ written += w;
+ f->next = f->data+n;
+ if(c < 0 && (!isall || n == 0))
+ break;
+ }
+ else if(w == 0)
+ { if(written > 0) /* some buffer was cleared */
+ break; /* do normal exit below */
+ else /* nothing was done, returning failure */
+ { SFOPEN(f,local);
+ SFMTXRETURN(f, -1);
+ }
+ }
+ else /* w < 0 means SF_EDISC or SF_ESTACK in sfwr() */
+ { if(c < 0) /* back to the calling write operation */
+ break;
+ else continue; /* try again to write out c */
+ }
+ }
+
+ SFOPEN(f,local);
+
+ if(inpc < 0)
+ inpc = f->endb-f->next;
+
+ SFMTXRETURN(f,inpc);
+}
diff --git a/src/lib/libast/sfio/sfgetd.c b/src/lib/libast/sfio/sfgetd.c
new file mode 100644
index 0000000..8c885c9
--- /dev/null
+++ b/src/lib/libast/sfio/sfgetd.c
@@ -0,0 +1,79 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read a portably coded double value
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+Sfdouble_t sfgetd(Sfio_t* f)
+#else
+Sfdouble_t sfgetd(f)
+Sfio_t* f;
+#endif
+{
+ reg uchar *s, *ends, c;
+ reg int p, sign, exp;
+ Sfdouble_t v;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f,-1.);
+
+ if((sign = sfgetc(f)) < 0 || (exp = (int)sfgetu(f)) < 0)
+ SFMTXRETURN(f, -1.);
+
+ if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, -1.);
+
+ SFLOCK(f,0);
+
+ v = 0.;
+ for(;;)
+ { /* fast read for data */
+ if(SFRPEEK(f,s,p) <= 0)
+ { f->flags |= SF_ERROR;
+ v = -1.;
+ goto done;
+ }
+
+ for(ends = s+p; s < ends; )
+ { c = *s++;
+ v += SFUVALUE(c);
+ v = ldexpl(v,-SF_PRECIS);
+ if(!(c&SF_MORE))
+ { f->next = s;
+ goto done;
+ }
+ }
+ f->next = s;
+ }
+
+done:
+ v = ldexpl(v,(sign&02) ? -exp : exp);
+ if(sign&01)
+ v = -v;
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, v);
+}
diff --git a/src/lib/libast/sfio/sfgetl.c b/src/lib/libast/sfio/sfgetl.c
new file mode 100644
index 0000000..bc83229
--- /dev/null
+++ b/src/lib/libast/sfio/sfgetl.c
@@ -0,0 +1,70 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read a long value coded in a portable format.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+Sflong_t sfgetl(Sfio_t* f)
+#else
+Sflong_t sfgetl(f)
+Sfio_t* f;
+#endif
+{
+ Sflong_t v;
+ uchar *s, *ends, c;
+ int p;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f,(Sflong_t)(-1));
+
+ if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, (Sflong_t)(-1));
+ SFLOCK(f,0);
+
+ for(v = 0;;)
+ { if(SFRPEEK(f,s,p) <= 0)
+ { f->flags |= SF_ERROR;
+ v = (Sflong_t)(-1);
+ goto done;
+ }
+ for(ends = s+p; s < ends;)
+ { c = *s++;
+ if(c&SF_MORE)
+ v = ((Sfulong_t)v << SF_UBITS) | SFUVALUE(c);
+ else
+ { /* special translation for this byte */
+ v = ((Sfulong_t)v << SF_SBITS) | SFSVALUE(c);
+ f->next = s;
+ v = (c&SF_SIGN) ? -v-1 : v;
+ goto done;
+ }
+ }
+ f->next = s;
+ }
+done :
+ SFOPEN(f,0);
+ SFMTXRETURN(f, v);
+}
diff --git a/src/lib/libast/sfio/sfgetm.c b/src/lib/libast/sfio/sfgetm.c
new file mode 100644
index 0000000..16598eb
--- /dev/null
+++ b/src/lib/libast/sfio/sfgetm.c
@@ -0,0 +1,68 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read an unsigned long value coded portably for a given range.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+Sfulong_t sfgetm(Sfio_t* f, Sfulong_t m)
+#else
+Sfulong_t sfgetm(f, m)
+Sfio_t* f;
+Sfulong_t m;
+#endif
+{
+ Sfulong_t v;
+ reg uchar *s, *ends, c;
+ reg int p;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (Sfulong_t)(-1));
+
+ if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, (Sfulong_t)(-1));
+
+ SFLOCK(f,0);
+
+ for(v = 0;; )
+ { if(SFRPEEK(f,s,p) <= 0)
+ { f->flags |= SF_ERROR;
+ v = (Sfulong_t)(-1);
+ goto done;
+ }
+ for(ends = s+p; s < ends;)
+ { c = *s++;
+ v = (v << SF_BBITS) | SFBVALUE(c);
+ if((m >>= SF_BBITS) <= 0)
+ { f->next = s;
+ goto done;
+ }
+ }
+ f->next = s;
+ }
+done:
+ SFOPEN(f,0);
+ SFMTXRETURN(f, v);
+}
diff --git a/src/lib/libast/sfio/sfgetr.c b/src/lib/libast/sfio/sfgetr.c
new file mode 100644
index 0000000..a3b9d34
--- /dev/null
+++ b/src/lib/libast/sfio/sfgetr.c
@@ -0,0 +1,169 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read a record delineated by a character.
+** The record length can be accessed via sfvalue(f).
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+char* sfgetr(Sfio_t *f, int rc, int type)
+#else
+char* sfgetr(f,rc,type)
+Sfio_t* f; /* stream to read from */
+int rc; /* record separator */
+int type;
+#endif
+{
+ ssize_t n, un;
+ uchar *s, *ends, *us;
+ int found;
+ Sfrsrv_t* rsrv;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f, NIL(char*));
+
+ if(rc < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) )
+ SFMTXRETURN(f, NIL(char*));
+ SFLOCK(f,0);
+
+ /* buffer to be returned */
+ rsrv = NIL(Sfrsrv_t*);
+ us = NIL(uchar*);
+ un = 0;
+ found = 0;
+
+ /* compatibility mode */
+ type = type < 0 ? SF_LASTR : type == 1 ? SF_STRING : type;
+
+ if(type&SF_LASTR) /* return the broken record */
+ { if((f->flags&SF_STRING) && (un = f->endb - f->next))
+ { us = f->next;
+ f->next = f->endb;
+ found = 1;
+ }
+ else if((rsrv = f->rsrv) && (un = -rsrv->slen) > 0)
+ { us = rsrv->data;
+ found = 1;
+ }
+ goto done;
+ }
+
+ while(!found)
+ { /* fill buffer if necessary */
+ if((n = (ends = f->endb) - (s = f->next)) <= 0)
+ { /* for unseekable devices, peek-read 1 record */
+ f->getr = rc;
+ f->mode |= SF_RC;
+
+ /* fill buffer the conventional way */
+ if(SFRPEEK(f,s,n) <= 0)
+ { us = NIL(uchar*);
+ goto done;
+ }
+ else
+ { ends = s+n;
+ if(f->mode&SF_RC)
+ { s = ends[-1] == rc ? ends-1 : ends;
+ goto do_copy;
+ }
+ }
+ }
+
+#if _lib_memchr
+ if(!(s = (uchar*)memchr((char*)s,rc,n)))
+ s = ends;
+#else
+ while(*s != rc)
+ if((s += 1) == ends)
+ break;
+#endif
+ do_copy:
+ if(s < ends) /* found separator */
+ { s += 1; /* include the separator */
+ found = 1;
+
+ if(!us &&
+ (!(type&SF_STRING) || !(f->flags&SF_STRING) ||
+ ((f->flags&SF_STRING) && (f->bits&SF_BOTH) ) ) )
+ { /* returning data in buffer */
+ us = f->next;
+ un = s - f->next;
+ f->next = s;
+ goto done;
+ }
+ }
+
+ /* amount to be read */
+ n = s - f->next;
+
+ if(!found && (_Sfmaxr > 0 && un+n+1 >= _Sfmaxr || (f->flags&SF_STRING))) /* already exceed limit */
+ { us = NIL(uchar*);
+ goto done;
+ }
+
+ /* get internal buffer */
+ if(!rsrv || rsrv->size < un+n+1)
+ { if(rsrv)
+ rsrv->slen = un;
+ if((rsrv = _sfrsrv(f,un+n+1)) != NIL(Sfrsrv_t*))
+ us = rsrv->data;
+ else
+ { us = NIL(uchar*);
+ goto done;
+ }
+ }
+
+ /* now copy data */
+ s = us+un;
+ un += n;
+ ends = f->next;
+ f->next += n;
+ MEMCPY(s,ends,n);
+ }
+
+done:
+ _Sfi = f->val = un;
+ f->getr = 0;
+ if(found && rc != 0 && (type&SF_STRING) )
+ { us[un-1] = '\0';
+ if(us >= f->data && us < f->endb)
+ { f->getr = rc;
+ f->mode |= SF_GETR;
+ }
+ }
+
+ /* prepare for a call to get the broken record */
+ if(rsrv)
+ rsrv->slen = found ? 0 : -un;
+
+ SFOPEN(f,0);
+
+ if(us && (type&SF_LOCKR) )
+ { f->mode |= SF_PEEK|SF_GETR;
+ f->endr = f->data;
+ }
+
+ SFMTXRETURN(f, (char*)us);
+}
diff --git a/src/lib/libast/sfio/sfgetu.c b/src/lib/libast/sfio/sfgetu.c
new file mode 100644
index 0000000..d0d6b5f
--- /dev/null
+++ b/src/lib/libast/sfio/sfgetu.c
@@ -0,0 +1,67 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read an unsigned long value coded in a portable format.
+**
+** Written by Kiem-Phong Vo
+*/
+
+#if __STD_C
+Sfulong_t sfgetu(Sfio_t* f)
+#else
+Sfulong_t sfgetu(f)
+Sfio_t* f;
+#endif
+{
+ Sfulong_t v;
+ uchar *s, *ends, c;
+ int p;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f, (Sfulong_t)(-1));
+
+ if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, (Sfulong_t)(-1));
+
+ SFLOCK(f,0);
+
+ for(v = 0;;)
+ { if(SFRPEEK(f,s,p) <= 0)
+ { f->flags |= SF_ERROR;
+ v = (Sfulong_t)(-1);
+ goto done;
+ }
+ for(ends = s+p; s < ends;)
+ { c = *s++;
+ v = (v << SF_UBITS) | SFUVALUE(c);
+ if(!(c&SF_MORE))
+ { f->next = s;
+ goto done;
+ }
+ }
+ f->next = s;
+ }
+done:
+ SFOPEN(f,0);
+ SFMTXRETURN(f, v);
+}
diff --git a/src/lib/libast/sfio/sfhdr.h b/src/lib/libast/sfio/sfhdr.h
new file mode 100644
index 0000000..d5f15cf
--- /dev/null
+++ b/src/lib/libast/sfio/sfhdr.h
@@ -0,0 +1,1302 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _SFHDR_H
+#define _SFHDR_H 1
+#if !defined(_BLD_sfio) && !defined(_BLD_stdio)
+#define _BLD_sfio 1
+#endif
+
+/* Internal definitions for sfio.
+** Written by Kiem-Phong Vo
+*/
+
+#define _next next
+#define _endw endw
+#define _endr endr
+#define _endb endb
+#define _push push
+#define _flags flags
+#define _file file
+#define _data data
+#define _size size
+#define _val val
+
+#include "FEATURE/sfio"
+#include "FEATURE/mmap"
+
+/* define va_list, etc. before including sfio_t.h (sfio.h) */
+#if !_PACKAGE_ast
+
+/* some systems don't know large files */
+#if defined(_NO_LARGEFILE64_SOURCE) || _mips == 2 /* || __hppa */
+#undef _NO_LARGEFILE64_SOURCE
+#define _NO_LARGEFILE64_SOURCE 1
+#undef _LARGEFILE64_SOURCE
+#undef _LARGEFILE_SOURCE
+#endif
+
+#if !_NO_LARGEFILE64_SOURCE && _typ_off64_t && _lib_lseek64 && _lib_stat64
+#undef _LARGEFILE64_SOURCE
+#undef _LARGEFILE_SOURCE
+#undef _FILE_OFFSET_BITS
+#define _LARGEFILE64_SOURCE 1 /* enabling the *64 stuff */
+#define _LARGEFILE_SOURCE 1
+#endif
+
+#if _hdr_stdarg
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "FEATURE/common"
+#if !__STD_C
+#define const
+#endif
+#endif /* !_PACKAGE_ast */
+
+#include "sfio_t.h"
+
+/* note that the macro vt_threaded has effect on vthread.h */
+#include <vthread.h>
+
+/* file system info */
+#if _PACKAGE_ast
+
+#include <ast.h>
+#include <ast_time.h>
+#include <ast_tty.h>
+#include <ls.h>
+
+/* ast always provides multibyte handling */
+#undef _hdr_wchar
+#undef _lib_mbrtowc
+#undef _lib_wcrtomb
+#define _hdr_wchar 1
+#define _lib_mbrtowc 1
+#define _lib_wcrtomb 1
+
+#if _mem_st_blksize_stat
+#define _stat_blksize 1
+#endif
+
+#if _lib_localeconv && _hdr_locale
+#define _lib_locale 1
+#endif
+
+#define sfoff_t off_t
+#define sfstat_t struct stat
+#define sysclosef close
+#define syscreatf creat
+#define sysdupf dup
+#define sysfcntlf fcntl
+#define sysfstatf fstat
+#define sysftruncatef ftruncate
+#define syslseekf lseek
+#define sysmmapf mmap
+#define sysmunmapf munmap
+#define sysopenf open
+#define syspipef pipe
+#define sysreadf read
+#define sysremovef remove
+#define sysstatf stat
+#define syswritef write
+
+#else /*!_PACKAGE_ast*/
+
+/* when building the binary compatibility package, a number of header files
+ are not needed and they may get in the way so we remove them here.
+*/
+#if _SFBINARY_H
+#undef _hdr_time
+#undef _sys_time
+#undef _sys_stat
+#undef _hdr_stat
+#undef _hdr_filio
+#undef _sys_filio
+#undef _lib_poll
+#undef _stream_peek
+#undef _socket_peek
+#undef _hdr_vfork
+#undef _sys_vfork
+#undef _lib_vfork
+#undef _hdr_values
+#undef _hdr_math
+#undef _sys_mman
+#undef _hdr_mman
+#undef _sys_ioctl
+#endif
+
+#if _hdr_stdlib
+#include <stdlib.h>
+#endif
+
+#if _hdr_string
+#include <string.h>
+#endif
+
+#if _hdr_time
+#include <time.h>
+#endif
+#if _sys_time
+#include <sys/time.h>
+#endif
+
+#if _sys_stat
+#include <sys/stat.h>
+#else
+#if _hdr_stat
+#include <stat.h>
+#ifndef _sys_stat
+#define _sys_stat 1
+#endif
+#endif
+#endif /*_sys_stat*/
+
+#ifndef _sys_stat
+#define _sys_stat 0
+#endif
+
+#include <fcntl.h>
+
+#ifndef F_SETFD
+#ifndef FIOCLEX
+#if _hdr_filio
+#include <filio.h>
+#else
+#if _sys_filio
+#include <sys/filio.h>
+#endif /*_sys_filio*/
+#endif /*_hdr_filio*/
+#endif /*_FIOCLEX*/
+#endif /*F_SETFD*/
+
+#if _hdr_unistd
+#include <unistd.h>
+#endif
+
+#if !_LARGEFILE64_SOURCE /* turn off the *64 stuff */
+#undef _typ_off64_t
+#undef _typ_struct_stat64
+#undef _lib_creat64
+#undef _lib_open64
+#undef _lib_close64
+#undef _lib_stat64
+#undef _lib_fstat64
+#undef _lib_ftruncate64
+#undef _lib_lseek64
+#undef _lib_mmap64
+#undef _lib_munmap64
+#endif /*!_LARGEFILE64_SOURCE */
+
+/* see if we can use memory mapping for io */
+#if _LARGEFILE64_SOURCE && !_lib_mmap64
+#undef _mmap_worthy
+#endif
+#if !_mmap_worthy
+#undef _hdr_mman
+#undef _sys_mman
+#endif
+#if _hdr_mman
+#include <mman.h>
+#endif
+#if _sys_mman
+#include <sys/mman.h>
+#endif
+
+/* standardize system calls and types dealing with files */
+#if _typ_off64_t
+#define sfoff_t off64_t
+#else
+#define sfoff_t off_t
+#endif
+#if _typ_struct_stat64
+#define sfstat_t struct stat64
+#else
+#define sfstat_t struct stat
+#endif
+#if _lib_lseek64
+#define syslseekf lseek64
+#else
+#define syslseekf lseek
+#endif
+#if _lib_stat64
+#define sysstatf stat64
+#else
+#define sysstatf stat
+#endif
+#if _lib_fstat64
+#define sysfstatf fstat64
+#else
+#define sysfstatf fstat
+#endif
+#if _lib_mmap64
+#define sysmmapf mmap64
+#else
+#define sysmmapf mmap
+#endif
+#if _lib_munmap64
+#define sysmunmapf munmap64
+#else
+#define sysmunmapf munmap
+#endif
+#if _lib_open64
+#define sysopenf open64
+#else
+#define sysopenf open
+#endif
+#if _lib_creat64
+#define syscreatf creat64
+#else
+#define syscreatf creat
+#endif
+#if _lib_close64
+#define sysclosef close64
+#else
+#define sysclosef close
+#endif
+#if _lib_ftruncate64
+#undef _lib_ftruncate
+#define _lib_ftruncate 1
+#define sysftruncatef ftruncate64
+#endif
+#if !_lib_ftruncate64 && _lib_ftruncate
+#define sysftruncatef ftruncate
+#endif
+#if _lib_remove
+#define sysremovef remove
+#else
+#define sysremovef unlink
+#endif
+
+#define sysreadf read
+#define syswritef write
+#define syspipef pipe
+#define sysdupf dup
+#define sysfcntlf fcntl
+
+#endif /*_PACKAGE_ast*/
+
+#if !_mmap_worthy
+#undef MAP_TYPE
+#endif
+
+#include "FEATURE/float"
+
+#include <errno.h>
+#include <ctype.h>
+
+/* deal with multi-byte character and string conversions */
+#if _PACKAGE_ast
+
+#include <wchar.h>
+
+#define _has_multibyte 1
+
+#define SFMBMAX mbmax()
+#define SFMBCPY(to,fr) memcpy((to), (fr), sizeof(mbstate_t))
+#define SFMBCLR(mb) memset((mb), 0, sizeof(mbstate_t))
+#define SFMBSET(lhs,v) (lhs = (v))
+#define SFMBLEN(s,mb) mbsize(s)
+#define SFMBDCL(ms) mbstate_t ms;
+
+#else
+
+#if _hdr_wchar && _typ_mbstate_t && _lib_wcrtomb && _lib_mbrtowc
+#define _has_multibyte 1 /* Xopen-compliant */
+#if _typ___va_list && !defined(__va_list)
+#define __va_list va_list
+#endif
+#include <wchar.h>
+#define SFMBCPY(to,fr) memcpy((to), (fr), sizeof(mbstate_t))
+#define SFMBCLR(mb) memset((mb), 0, sizeof(mbstate_t))
+#define SFMBSET(lhs,v) (lhs = (v))
+#define SFMBDCL(mb) mbstate_t mb;
+#define SFMBLEN(s,mb) mbrtowc(NIL(wchar_t*), (s), SFMBMAX, (mb) )
+#endif /*_hdr_wchar && _typ_mbstate_t && _lib_wcrtomb && _lib_mbrtowc*/
+
+#if !_has_multibyte && _hdr_wchar && _lib_mbtowc && _lib_wctomb
+#define _has_multibyte 2 /* no shift states */
+#include <wchar.h>
+#undef mbrtowc
+#define mbrtowc(wp,s,n,mb) mbtowc(wp, s, n)
+#undef wcrtomb
+#define wcrtomb(s,wc,mb) wctomb(s, wc)
+#define SFMBCPY(to,fr)
+#define SFMBCLR(mb)
+#define SFMBSET(lhs,v)
+#define SFMBDCL(mb)
+#define SFMBLEN(s,mb) mbrtowc(NIL(wchar_t*), (s), SFMBMAX, (mb) )
+#endif /*!_has_multibyte && _hdr_wchar && _lib_mbtowc && _lib_wctomb*/
+
+#ifdef MB_CUR_MAX
+#define SFMBMAX MB_CUR_MAX
+#else
+#define SFMBMAX sizeof(Sflong_t)
+#endif
+
+#endif /* _PACKAGE_ast */
+
+#if !_has_multibyte
+#define _has_multibyte 0 /* no multibyte support */
+#define SFMBCPY(to,fr)
+#define SFMBCLR(mb)
+#define SFMBSET(lhs,v)
+#define SFMBLEN(s,mb) (*(s) ? 1 : 0)
+#define SFMBDCL(mb)
+#endif /* _has_multibyte */
+
+/* dealing with streams that might be accessed concurrently */
+#if vt_threaded
+
+#define SFMTXdecl(ff,_mf_) Sfio_t* _mf_ = (ff)
+#define SFMTXbegin(ff,_mf_,rv) \
+ { if((ff)->_flags&SF_MTSAFE) \
+ { (_mf_) = (ff); \
+ if(sfmutex((ff), SFMTX_LOCK) != 0) return(rv); \
+ if(_Sfnotify) \
+ { (*_Sfnotify)((_mf_), SF_MTACCESS, (Void_t*)(&(ff)) ); \
+ if(!(ff)) (ff) = (_mf_); \
+ } \
+ } \
+ }
+#define SFMTXend(ff,_mf_) \
+ { if((ff)->_flags&SF_MTSAFE) \
+ { if(_Sfnotify) \
+ (*_Sfnotify)((_mf_), SF_MTACCESS, NIL(Void_t*) ); \
+ sfmutex((ff), SFMTX_UNLOCK); \
+ (ff) = (_mf_); \
+ } \
+ }
+
+#define SFONCE() (_Sfdone ? 0 : vtonce(_Sfonce,_Sfoncef))
+
+#define SFMTXLOCK(f) (((f)->flags&SF_MTSAFE) ? sfmutex(f,SFMTX_LOCK) : 0)
+#define SFMTXUNLOCK(f) (((f)->flags&SF_MTSAFE) ? sfmutex(f,SFMTX_UNLOCK) : 0)
+
+#define SFMTXDECL(ff) SFMTXdecl((ff), _mtxf1_)
+#define SFMTXBEGIN(ff,v) { SFMTXbegin((ff), _mtxf1_, (v) ); }
+#define SFMTXEND(ff) { SFMTXend(ff, _mtxf1_); }
+#define SFMTXENTER(ff,v) { if(!(ff)) return(v); SFMTXBEGIN((ff), (v)); }
+#define SFMTXRETURN(ff,v) { SFMTXEND(ff); return(v); }
+
+#define SFMTXDECL2(ff) SFMTXdecl((ff), _mtxf2_)
+#define SFMTXBEGIN2(ff,v) { SFMTXbegin((ff), _mtxf2_, (v) ); }
+#define SFMTXEND2(ff) { SFMTXend((ff), _mtxf2_); }
+
+#define POOLMTXLOCK(p) ( vtmtxlock(&(p)->mutex) )
+#define POOLMTXUNLOCK(p) ( vtmtxunlock(&(p)->mutex) )
+#define POOLMTXENTER(p) { POOLMTXLOCK(p); }
+#define POOLMTXRETURN(p,rv) { POOLMTXUNLOCK(p); return(rv); }
+
+#else /*!vt_threaded*/
+
+#undef SF_MTSAFE /* no need to worry about thread-safety */
+#define SF_MTSAFE 0
+
+#define SFONCE() /*(0)*/
+
+#define SFMTXLOCK(f) /*(0)*/
+#define SFMTXUNLOCK(f) /*(0)*/
+
+#define SFMTXDECL(ff) /*(0)*/
+#define SFMTXBEGIN(ff,v) /*(0)*/
+#define SFMTXEND(ff) /*(0)*/
+#define SFMTXENTER(ff,v) { if(!(ff)) return(v); }
+#define SFMTXRETURN(ff,v) { return(v); }
+
+#define SFMTXDECL2(ff) /*(0)*/
+#define SFMTXBEGIN2(ff,v) /*(0)*/
+#define SFMTXEND2(ff) /*(0)*/
+
+#define POOLMTXLOCK(p)
+#define POOLMTXUNLOCK(p)
+#define POOLMTXENTER(p)
+#define POOLMTXRETURN(p,v) { return(v); }
+
+#endif /*vt_threaded*/
+
+
+/* functions for polling readiness of streams */
+#if _lib_select
+#undef _lib_poll
+#else
+#if _lib_poll_fd_1 || _lib_poll_fd_2
+#define _lib_poll 1
+#endif
+#endif /*_lib_select_*/
+
+#if _lib_poll
+#include <poll.h>
+
+#if _lib_poll_fd_1
+#define SFPOLL(pfd,n,tm) poll((pfd),(ulong)(n),(tm))
+#else
+#define SFPOLL(pfd,n,tm) poll((ulong)(n),(pfd),(tm))
+#endif
+#endif /*_lib_poll*/
+
+#if _stream_peek
+#include <stropts.h>
+#endif
+
+#if _socket_peek
+#include <sys/socket.h>
+#endif
+
+/* to test for executable access mode of a file */
+#ifndef X_OK
+#define X_OK 01
+#endif
+
+/* alternative process forking */
+#if _lib_vfork && !defined(fork) && !defined(sparc) && !defined(__sparc)
+#if _hdr_vfork
+#include <vfork.h>
+#endif
+#if _sys_vfork
+#include <sys/vfork.h>
+#endif
+#define fork vfork
+#endif
+
+/* to get rid of pesky compiler warnings */
+#if __STD_C
+#define NOTUSED(x) (void)(x)
+#else
+#define NOTUSED(x) (&x,1)
+#endif
+
+/* Private flags in the "bits" field */
+#define SF_MMAP 00000001 /* in memory mapping mode */
+#define SF_BOTH 00000002 /* both read/write */
+#define SF_HOLE 00000004 /* a hole of zero's was created */
+#define SF_NULL 00000010 /* stream is /dev/null */
+#define SF_SEQUENTIAL 00000020 /* sequential access */
+#define SF_JUSTSEEK 00000040 /* just did a sfseek */
+#define SF_PRIVATE 00000100 /* private stream to Sfio, no mutex */
+#define SF_ENDING 00000200 /* no re-io on interrupts at closing */
+#define SF_WIDE 00000400 /* in wide mode - stdio only */
+#define SF_PUTR 00001000 /* in sfputr() */
+
+/* "bits" flags that must be cleared in sfclrlock */
+#define SF_TMPBITS 00170000
+#define SF_DCDOWN 00010000 /* recurse down the discipline stack */
+
+#define SF_WCFORMAT 00020000 /* wchar_t formatting - stdio only */
+#if _has_multibyte
+#define SFWCSET(f) ((f)->bits |= SF_WCFORMAT)
+#define SFWCGET(f,v) (((v) = (f)->bits & SF_WCFORMAT), ((f)->bits &= ~SF_WCFORMAT) )
+#else
+#define SFWCSET(f)
+#define SFWCGET(f,v)
+#endif
+
+#define SF_MVSIZE 00040000 /* f->size was reset in sfmove() */
+#define SFMVSET(f) (((f)->size *= SF_NMAP), ((f)->bits |= SF_MVSIZE) )
+#define SFMVUNSET(f) (!((f)->bits&SF_MVSIZE) ? 0 : \
+ (((f)->bits &= ~SF_MVSIZE), ((f)->size /= SF_NMAP)) )
+
+#define SFCLRBITS(f) (SFMVUNSET(f), ((f)->bits &= ~SF_TMPBITS) )
+
+
+/* bits for the mode field, SF_INIT defined in sfio_t.h */
+#define SF_RC 00000010 /* peeking for a record */
+#define SF_RV 00000020 /* reserve without read or most write */
+#define SF_LOCK 00000040 /* stream is locked for io op */
+#define SF_PUSH 00000100 /* stream has been pushed */
+#define SF_POOL 00000200 /* stream is in a pool but not current */
+#define SF_PEEK 00000400 /* there is a pending peek */
+#define SF_PKRD 00001000 /* did a peek read */
+#define SF_GETR 00002000 /* did a getr on this stream */
+#define SF_SYNCED 00004000 /* stream was synced */
+#define SF_STDIO 00010000 /* given up the buffer to stdio */
+#define SF_AVAIL 00020000 /* was closed, available for reuse */
+#define SF_LOCAL 00100000 /* sentinel for a local call */
+
+#ifdef DEBUG
+#define ASSERT(p) ((p) ? 0 : (abort(),0) )
+#else
+#define ASSERT(p)
+#endif
+
+/* short-hands */
+#define NIL(t) ((t)0)
+#define reg register
+#ifndef uchar
+#define uchar unsigned char
+#endif
+#ifndef ulong
+#define ulong unsigned long
+#endif
+#ifndef uint
+#define uint unsigned int
+#endif
+#ifndef ushort
+#define ushort unsigned short
+#endif
+
+#define SECOND 1000 /* millisecond units */
+
+/* macros do determine stream types from sfstat_t data */
+#ifndef S_IFDIR
+#define S_IFDIR 0
+#endif
+#ifndef S_IFREG
+#define S_IFREG 0
+#endif
+#ifndef S_IFCHR
+#define S_IFCHR 0
+#endif
+#ifndef S_IFIFO
+#define S_IFIFO 0
+#endif
+#ifndef S_ISOCK
+#define S_ISOCK 0
+#endif
+
+#ifndef S_IFMT
+#define S_IFMT (S_IFDIR|S_IFREG|S_IFCHR|S_IFIFO|S_ISOCK)
+#endif
+
+#ifndef S_ISDIR
+#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
+#endif
+#ifndef S_ISREG
+#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
+#endif
+#ifndef S_ISCHR
+#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR)
+#endif
+
+#ifndef S_ISFIFO
+# if S_IFIFO
+# define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO)
+# else
+# define S_ISFIFO(m) (0)
+# endif
+#endif
+
+#ifdef S_IRUSR
+#define SF_CREATMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
+#else
+#define SF_CREATMODE 0666
+#endif
+
+/* set close-on-exec */
+#ifdef F_SETFD
+# ifndef FD_CLOEXEC
+# define FD_CLOEXEC 1
+# endif /*FD_CLOEXEC*/
+# define SETCLOEXEC(fd) ((void)fcntl((fd),F_SETFD,FD_CLOEXEC))
+#else
+# ifdef FIOCLEX
+# define SETCLOEXEC(fd) ((void)ioctl((fd),FIOCLEX,0))
+# else
+# define SETCLOEXEC(fd)
+# endif /*FIOCLEX*/
+#endif /*F_SETFD*/
+
+/* a couple of error number that we use, default values are like Linux */
+#ifndef EINTR
+#define EINTR 4
+#endif
+#ifndef EBADF
+#define EBADF 9
+#endif
+#ifndef EAGAIN
+#define EAGAIN 11
+#endif
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+#ifndef EINVAL
+#define EINVAL 22
+#endif
+#ifndef ESPIPE
+#define ESPIPE 29
+#endif
+
+/* function to get the decimal point for local environment */
+#if !defined(SFSETLOCALE) && _PACKAGE_ast
+#include "lclib.h"
+#define SFSETLOCALE(dp,tp) \
+ do if (*(dp) == 0) { \
+ Lc_numeric_t* lv = (Lc_numeric_t*)LCINFO(AST_LC_NUMERIC)->data; \
+ *(dp) = lv->decimal; \
+ if (tp) *(tp) = lv->thousand; \
+ } while (0)
+#endif /*!defined(SFSETLOCALE) && _PACKAGE_ast*/
+
+#if !defined(SFSETLOCALE) && _lib_locale
+#include <locale.h>
+#define SFSETLOCALE(decimal,thousand) \
+ do { struct lconv* lv; \
+ if(*(decimal) == 0) \
+ { *(decimal) = '.'; \
+ if (thousand) *(thousand) = -1; \
+ if((lv = localeconv())) \
+ { if(lv->decimal_point && *lv->decimal_point) \
+ *(decimal) = *(unsigned char*)lv->decimal_point; \
+ if(thousand && lv->thousands_sep && *lv->thousands_sep) \
+ *(thousand) = *(unsigned char*)lv->thousands_sep; \
+ } \
+ } \
+ } while (0)
+#endif /*!defined(SFSETLOCALE) && _lib_locale*/
+
+#if !defined(SFSETLOCALE)
+#define SFSETLOCALE(decimal,thousand) (*(decimal)='.')
+#endif
+
+/* stream pool structure. */
+typedef struct _sfpool_s Sfpool_t;
+struct _sfpool_s
+{ Sfpool_t* next;
+ int mode; /* type of pool */
+ int s_sf; /* size of pool array */
+ int n_sf; /* number currently in pool */
+ Sfio_t** sf; /* array of streams */
+ Sfio_t* array[3]; /* start with 3 */
+ Vtmutex_t mutex; /* mutex lock object */
+};
+
+/* reserve buffer structure */
+typedef struct _sfrsrv_s Sfrsrv_t;
+struct _sfrsrv_s
+{ ssize_t slen; /* last string length */
+ ssize_t size; /* buffer size */
+ uchar data[1]; /* data buffer */
+};
+
+/* co-process structure */
+typedef struct _sfproc_s Sfproc_t;
+struct _sfproc_s
+{ int pid; /* process id */
+ uchar* rdata; /* read data being cached */
+ int ndata; /* size of cached data */
+ int size; /* buffer size */
+ int file; /* saved file descriptor */
+ int sigp; /* sigpipe protection needed */
+};
+
+/* extensions to sfvprintf/sfvscanf */
+#define FP_SET(fp,fn) (fp < 0 ? (fn += 1) : (fn = fp) )
+#define FP_WIDTH 0
+#define FP_PRECIS 1
+#define FP_BASE 2
+#define FP_STR 3
+#define FP_SIZE 4
+#define FP_INDEX 5 /* index size */
+
+typedef struct _fmt_s Fmt_t;
+typedef struct _fmtpos_s Fmtpos_t;
+typedef union
+{ int i, *ip;
+ long l, *lp;
+ short h, *hp;
+ uint ui;
+ ulong ul;
+ ushort uh;
+ Sflong_t ll, *llp;
+ Sfulong_t lu;
+ Sfdouble_t ld;
+ double d;
+ float f;
+#if _has_multibyte
+ wchar_t wc;
+ wchar_t *ws, **wsp;
+#endif
+ char c, *s, **sp;
+ uchar uc, *us, **usp;
+ Void_t *vp;
+ Sffmt_t *ft;
+} Argv_t;
+
+struct _fmt_s
+{ char* form; /* format string */
+ va_list args; /* corresponding arglist */
+ SFMBDCL(mbs) /* multibyte parsing state */
+
+ char* oform; /* original format string */
+ va_list oargs; /* original arg list */
+ int argn; /* number of args already used */
+ Fmtpos_t* fp; /* position list */
+
+ Sffmt_t* ft; /* formatting environment */
+ Sffmtevent_f eventf; /* event function */
+ Fmt_t* next; /* stack frame pointer */
+};
+
+struct _fmtpos_s
+{ Sffmt_t ft; /* environment */
+ Argv_t argv; /* argument value */
+ int fmt; /* original format */
+ int need[FP_INDEX]; /* positions depending on */
+};
+
+#define LEFTP '('
+#define RIGHTP ')'
+#define QUOTE '\''
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#define FMTSET(ft, frm,ags, fv, sz, flgs, wid,pr,bs, ts,ns) \
+ ((ft->form = (char*)frm), va_copy(ft->args,ags), \
+ (ft->fmt = fv), (ft->size = sz), \
+ (ft->flags = (flgs&SFFMT_SET)), \
+ (ft->width = wid), (ft->precis = pr), (ft->base = bs), \
+ (ft->t_str = ts), (ft->n_str = ns) )
+#define FMTGET(ft, frm,ags, fv, sz, flgs, wid,pr,bs) \
+ ((frm = ft->form), va_copy(ags,ft->args), \
+ (fv = ft->fmt), (sz = ft->size), \
+ (flgs = (flgs&~(SFFMT_SET))|(ft->flags&SFFMT_SET)), \
+ (wid = ft->width), (pr = ft->precis), (bs = ft->base) )
+
+/* format flags&types, must coexist with those in sfio.h */
+#define SFFMT_FORBIDDEN 000077777777 /* for sfio.h only */
+#define SFFMT_EFORMAT 001000000000 /* sfcvt converting %e */
+#define SFFMT_MINUS 002000000000 /* minus sign */
+#define SFFMT_AFORMAT 004000000000 /* sfcvt converting %a */
+#define SFFMT_UPPER 010000000000 /* sfcvt converting upper */
+
+#define SFFMT_TYPES (SFFMT_SHORT|SFFMT_SSHORT | SFFMT_LONG|SFFMT_LLONG|\
+ SFFMT_LDOUBLE | SFFMT_IFLAG|SFFMT_JFLAG| \
+ SFFMT_TFLAG | SFFMT_ZFLAG )
+
+/* type of elements to be converted */
+#define SFFMT_INT 001 /* %d,%i */
+#define SFFMT_UINT 002 /* %u,o,x etc. */
+#define SFFMT_FLOAT 004 /* %f,e,g etc. */
+#define SFFMT_CHAR 010 /* %c,C */
+#define SFFMT_POINTER 020 /* %p,n,s,S */
+#define SFFMT_CLASS 040 /* %[ */
+
+/* local variables used across sf-functions */
+#define _Sfpage (_Sfextern.sf_page)
+#define _Sfpool (_Sfextern.sf_pool)
+#define _Sfpmove (_Sfextern.sf_pmove)
+#define _Sfstack (_Sfextern.sf_stack)
+#define _Sfnotify (_Sfextern.sf_notify)
+#define _Sfstdsync (_Sfextern.sf_stdsync)
+#define _Sfudisc (&(_Sfextern.sf_udisc))
+#define _Sfcleanup (_Sfextern.sf_cleanup)
+#define _Sfexiting (_Sfextern.sf_exiting)
+#define _Sfdone (_Sfextern.sf_done)
+#define _Sfonce (_Sfextern.sf_once)
+#define _Sfoncef (_Sfextern.sf_oncef)
+#define _Sfmutex (_Sfextern.sf_mutex)
+typedef struct _sfextern_s
+{ ssize_t sf_page;
+ struct _sfpool_s sf_pool;
+ int (*sf_pmove)_ARG_((Sfio_t*, int));
+ Sfio_t* (*sf_stack)_ARG_((Sfio_t*, Sfio_t*));
+ void (*sf_notify)_ARG_((Sfio_t*, int, void*));
+ int (*sf_stdsync)_ARG_((Sfio_t*));
+ struct _sfdisc_s sf_udisc;
+ void (*sf_cleanup)_ARG_((void));
+ int sf_exiting;
+ int sf_done;
+ Vtonce_t* sf_once;
+ void (*sf_oncef)_ARG_((void));
+ Vtmutex_t* sf_mutex;
+} Sfextern_t;
+
+/* get the real value of a byte in a coded long or ulong */
+#define SFUVALUE(v) (((ulong)(v))&(SF_MORE-1))
+#define SFSVALUE(v) ((( long)(v))&(SF_SIGN-1))
+#define SFBVALUE(v) (((ulong)(v))&(SF_BYTE-1))
+
+/* pick this many bits in each iteration of double encoding */
+#define SF_PRECIS 7
+
+/* grain size for buffer increment */
+#define SF_GRAIN 1024
+#define SF_PAGE ((ssize_t)(SF_GRAIN*sizeof(int)*2))
+
+/* when the buffer is empty, certain io requests may be better done directly
+ on the given application buffers. The below condition determines when.
+*/
+#define SFDIRECT(f,n) (((ssize_t)(n) >= (f)->size) || \
+ ((n) >= SF_GRAIN && (ssize_t)(n) >= (f)->size/16 ) )
+
+/* number of pages to memory map at a time */
+#if _ptr_bits >= 64
+#define SF_NMAP 1024
+#else
+#define SF_NMAP 32
+#endif
+
+#ifndef MAP_VARIABLE
+#define MAP_VARIABLE 0
+#endif
+#ifndef _mmap_fixed
+#define _mmap_fixed 0
+#endif
+
+/* set/unset sequential states for mmap */
+#if _lib_madvise && defined(MADV_SEQUENTIAL) && defined(MADV_NORMAL)
+#define SFMMSEQON(f,a,s) \
+ do { int oerrno = errno; \
+ (void)madvise((caddr_t)(a),(size_t)(s),MADV_SEQUENTIAL); \
+ errno = oerrno; \
+ } while(0)
+#define SFMMSEQOFF(f,a,s) \
+ do { int oerrno = errno; \
+ (void)madvise((caddr_t)(a),(size_t)(s),MADV_NORMAL); \
+ errno = oerrno; \
+ } while(0)
+#else
+#define SFMMSEQON(f,a,s)
+#define SFMMSEQOFF(f,a,s)
+#endif
+
+#define SFMUNMAP(f,a,s) (sysmunmapf((caddr_t)(a),(size_t)(s)), \
+ ((f)->endb = (f)->endr = (f)->endw = (f)->next = \
+ (f)->data = NIL(uchar*)) )
+
+/* safe closing function */
+#define CLOSE(f) { while(sysclosef(f) < 0 && errno == EINTR) errno = 0; }
+
+/* the bottomless bit bucket */
+#define DEVNULL "/dev/null"
+#define SFSETNULL(f) ((f)->extent = (Sfoff_t)(-1), (f)->bits |= SF_NULL)
+#define SFISNULL(f) ((f)->extent < 0 && ((f)->bits&SF_NULL) )
+
+#define SFKILL(f) ((f)->mode = (SF_AVAIL|SF_LOCK) )
+#define SFKILLED(f) (((f)->mode&(SF_AVAIL|SF_LOCK)) == (SF_AVAIL|SF_LOCK) )
+
+/* exception types */
+#define SF_EDONE 0 /* stop this operation and return */
+#define SF_EDISC 1 /* discipline says it's ok */
+#define SF_ESTACK 2 /* stack was popped */
+#define SF_ECONT 3 /* can continue normally */
+
+#define SETLOCAL(f) ((f)->mode |= SF_LOCAL)
+#define GETLOCAL(f,v) ((v) = ((f)->mode&SF_LOCAL), (f)->mode &= ~SF_LOCAL, (v))
+#define SFWRALL(f) ((f)->mode |= SF_RV)
+#define SFISALL(f,v) ((((v) = (f)->mode&SF_RV) ? ((f)->mode &= ~SF_RV) : 0), \
+ ((v) || ((f)->flags&(SF_SHARE|SF_APPENDWR|SF_WHOLE)) ) )
+#define SFSK(f,a,o,d) (SETLOCAL(f),sfsk(f,(Sfoff_t)a,o,d))
+#define SFRD(f,b,n,d) (SETLOCAL(f),sfrd(f,(Void_t*)b,n,d))
+#define SFWR(f,b,n,d) (SETLOCAL(f),sfwr(f,(Void_t*)b,n,d))
+#define SFSYNC(f) (SETLOCAL(f),sfsync(f))
+#define SFCLOSE(f) (SETLOCAL(f),sfclose(f))
+#define SFFLSBUF(f,n) (SETLOCAL(f),_sfflsbuf(f,n))
+#define SFFILBUF(f,n) (SETLOCAL(f),_sffilbuf(f,n))
+#define SFSETBUF(f,s,n) (SETLOCAL(f),sfsetbuf(f,s,n))
+#define SFWRITE(f,s,n) (SETLOCAL(f),sfwrite(f,s,n))
+#define SFREAD(f,s,n) (SETLOCAL(f),sfread(f,s,n))
+#define SFSEEK(f,p,t) (SETLOCAL(f),sfseek(f,p,t))
+#define SFNPUTC(f,c,n) (SETLOCAL(f),sfnputc(f,c,n))
+#define SFRAISE(f,e,d) (SETLOCAL(f),sfraise(f,e,d))
+
+/* lock/open a stream */
+#define SFMODE(f,l) ((f)->mode & ~(SF_RV|SF_RC|((l) ? SF_LOCK : 0)) )
+#define SFLOCK(f,l) (void)((f)->mode |= SF_LOCK, (f)->endr = (f)->endw = (f)->data)
+#define _SFOPENRD(f) ((f)->endr = ((f)->flags&SF_MTSAFE) ? (f)->data : (f)->endb)
+#define _SFOPENWR(f) ((f)->endw = ((f)->flags&(SF_MTSAFE|SF_LINE)) ? (f)->data : (f)->endb)
+#define _SFOPEN(f) ((f)->mode == SF_READ ? _SFOPENRD(f) : \
+ (f)->mode == SF_WRITE ? _SFOPENWR(f) : \
+ ((f)->endw = (f)->endr = (f)->data) )
+#define SFOPEN(f,l) (void)((l) ? 0 : \
+ ((f)->mode &= ~(SF_LOCK|SF_RC|SF_RV), _SFOPEN(f), 0) )
+
+/* check to see if the stream can be accessed */
+#define SFFROZEN(f) (((f)->mode&(SF_PUSH|SF_LOCK|SF_PEEK)) ? 1 : \
+ !((f)->mode&SF_STDIO) ? 0 : \
+ _Sfstdsync ? (*_Sfstdsync)(f) : (((f)->mode &= ~SF_STDIO),0) )
+
+
+/* set discipline code */
+#define SFDISC(f,dc,iof) \
+ { Sfdisc_t* d; \
+ if(!(dc)) \
+ d = (dc) = (f)->disc; \
+ else d = (f->bits&SF_DCDOWN) ? ((dc) = (dc)->disc) : (dc); \
+ while(d && !(d->iof)) d = d->disc; \
+ if(d) (dc) = d; \
+ }
+#define SFDCRD(f,buf,n,dc,rv) \
+ { int dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \
+ rv = (*dc->readf)(f,buf,n,dc); \
+ if(!dcdown) f->bits &= ~SF_DCDOWN; \
+ }
+#define SFDCWR(f,buf,n,dc,rv) \
+ { int dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \
+ rv = (*dc->writef)(f,buf,n,dc); \
+ if(!dcdown) f->bits &= ~SF_DCDOWN; \
+ }
+#define SFDCSK(f,addr,type,dc,rv) \
+ { int dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \
+ rv = (*dc->seekf)(f,addr,type,dc); \
+ if(!dcdown) f->bits &= ~SF_DCDOWN; \
+ }
+
+/* fast peek of a stream */
+#define _SFAVAIL(f,s,n) ((n) = (f)->endb - ((s) = (f)->next) )
+#define SFRPEEK(f,s,n) (_SFAVAIL(f,s,n) > 0 ? (n) : \
+ ((n) = SFFILBUF(f,-1), (s) = (f)->next, (n)) )
+#define SFWPEEK(f,s,n) (_SFAVAIL(f,s,n) > 0 ? (n) : \
+ ((n) = SFFLSBUF(f,-1), (s) = (f)->next, (n)) )
+
+/* more than this for a line buffer, we might as well flush */
+#define HIFORLINE 128
+
+/* string stream extent */
+#define SFSTRSIZE(f) { Sfoff_t s = (f)->next - (f)->data; \
+ if(s > (f)->here) \
+ { (f)->here = s; if(s > (f)->extent) (f)->extent = s; } \
+ }
+
+/* control flags for open() */
+#ifdef O_CREAT
+#define _has_oflags 1
+#else /* for example, research UNIX */
+#define _has_oflags 0
+#define O_CREAT 004
+#define O_TRUNC 010
+#define O_APPEND 020
+#define O_EXCL 040
+
+#ifndef O_RDONLY
+#define O_RDONLY 000
+#endif
+#ifndef O_WRONLY
+#define O_WRONLY 001
+#endif
+#ifndef O_RDWR
+#define O_RDWR 002
+#endif
+#endif /*O_CREAT*/
+
+#ifndef O_BINARY
+#define O_BINARY 000
+#endif
+#ifndef O_TEXT
+#define O_TEXT 000
+#endif
+#ifndef O_TEMPORARY
+#define O_TEMPORARY 000
+#endif
+
+#define SF_RADIX 64 /* maximum integer conversion base */
+
+#if _PACKAGE_ast
+#define SF_MAXINT INT_MAX
+#define SF_MAXLONG LONG_MAX
+#else
+#define SF_MAXINT ((int)(((uint)~0) >> 1))
+#define SF_MAXLONG ((long)(((ulong)~0L) >> 1))
+#endif
+
+#define SF_MAXCHAR ((uchar)(~0))
+
+/* floating point to ascii conversion */
+#define SF_MAXEXP10 6
+#define SF_MAXPOW10 (1 << SF_MAXEXP10)
+#if !_ast_fltmax_double
+#define SF_FDIGITS 1024 /* max allowed fractional digits */
+#define SF_IDIGITS (8*1024) /* max number of digits in int part */
+#else
+#define SF_FDIGITS 256 /* max allowed fractional digits */
+#define SF_IDIGITS 1024 /* max number of digits in int part */
+#endif
+#define SF_MAXDIGITS (((SF_FDIGITS+SF_IDIGITS)/sizeof(int) + 1)*sizeof(int))
+
+/* tables for numerical translation */
+#define _Sfpos10 (_Sftable.sf_pos10)
+#define _Sfneg10 (_Sftable.sf_neg10)
+#define _Sfdec (_Sftable.sf_dec)
+#define _Sfdigits (_Sftable.sf_digits)
+#define _Sfcvinitf (_Sftable.sf_cvinitf)
+#define _Sfcvinit (_Sftable.sf_cvinit)
+#define _Sffmtposf (_Sftable.sf_fmtposf)
+#define _Sffmtintf (_Sftable.sf_fmtintf)
+#define _Sfcv36 (_Sftable.sf_cv36)
+#define _Sfcv64 (_Sftable.sf_cv64)
+#define _Sftype (_Sftable.sf_type)
+#define _Sfieee (&_Sftable.sf_ieee)
+#define _Sffinf (_Sftable.sf_ieee.fltinf)
+#define _Sfdinf (_Sftable.sf_ieee.dblinf)
+#define _Sflinf (_Sftable.sf_ieee.ldblinf)
+#define _Sffnan (_Sftable.sf_ieee.fltnan)
+#define _Sfdnan (_Sftable.sf_ieee.dblnan)
+#define _Sflnan (_Sftable.sf_ieee.ldblnan)
+#define _Sffpow10 (_Sftable.sf_flt_pow10)
+#define _Sfdpow10 (_Sftable.sf_dbl_pow10)
+#define _Sflpow10 (_Sftable.sf_ldbl_pow10)
+typedef struct _sfieee_s Sfieee_t;
+struct _sfieee_s
+{ float fltnan; /* float NAN */
+ float fltinf; /* float INF */
+ double dblnan; /* double NAN */
+ double dblinf; /* double INF */
+ Sfdouble_t ldblnan; /* Sfdouble_t NAN */
+ Sfdouble_t ldblinf; /* Sfdouble_t INF */
+};
+typedef struct _sftab_
+{ Sfdouble_t sf_pos10[SF_MAXEXP10]; /* positive powers of 10 */
+ Sfdouble_t sf_neg10[SF_MAXEXP10]; /* negative powers of 10 */
+ uchar sf_dec[200]; /* ascii reps of values < 100 */
+ char* sf_digits; /* digits for general bases */
+ int (*sf_cvinitf)(); /* initialization function */
+ int sf_cvinit; /* initialization state */
+ Fmtpos_t* (*sf_fmtposf)_ARG_((Sfio_t*,const char*,va_list,Sffmt_t*,int));
+ char* (*sf_fmtintf)_ARG_((const char*,int*));
+ float* sf_flt_pow10; /* float powers of 10 */
+ double* sf_dbl_pow10; /* double powers of 10 */
+ Sfdouble_t* sf_ldbl_pow10; /* Sfdouble_t powers of 10 */
+ uchar sf_cv36[SF_MAXCHAR+1]; /* conversion for base [2-36] */
+ uchar sf_cv64[SF_MAXCHAR+1]; /* conversion for base [37-64] */
+ uchar sf_type[SF_MAXCHAR+1]; /* conversion formats&types */
+ Sfieee_t sf_ieee; /* IEEE floating point constants*/
+} Sftab_t;
+
+/* thread-safe macro/function to initialize _Sfcv* conversion tables */
+#define SFCVINIT() (_Sfcvinit ? 1 : (_Sfcvinit = (*_Sfcvinitf)()) )
+
+/* sfucvt() converts decimal integers to ASCII */
+#define SFDIGIT(v,scale,digit) \
+ { if(v < 5*scale) \
+ if(v < 2*scale) \
+ if(v < 1*scale) \
+ { digit = '0'; } \
+ else { digit = '1'; v -= 1*scale; } \
+ else if(v < 3*scale) \
+ { digit = '2'; v -= 2*scale; } \
+ else if(v < 4*scale) \
+ { digit = '3'; v -= 3*scale; } \
+ else { digit = '4'; v -= 4*scale; } \
+ else if(v < 7*scale) \
+ if(v < 6*scale) \
+ { digit = '5'; v -= 5*scale; } \
+ else { digit = '6'; v -= 6*scale; } \
+ else if(v < 8*scale) \
+ { digit = '7'; v -= 7*scale; } \
+ else if(v < 9*scale) \
+ { digit = '8'; v -= 8*scale; } \
+ else { digit = '9'; v -= 9*scale; } \
+ }
+#define sfucvt(v,s,n,list,type,utype) \
+ { while((utype)v >= 10000) \
+ { n = v; v = (type)(((utype)v)/10000); \
+ n = (type)((utype)n - ((utype)v)*10000); \
+ s -= 4; SFDIGIT(n,1000,s[0]); SFDIGIT(n,100,s[1]); \
+ s[2] = *(list = (char*)_Sfdec + (n <<= 1)); s[3] = *(list+1); \
+ } \
+ if(v < 100) \
+ { if(v < 10) \
+ { s -= 1; s[0] = (char)('0'+v); \
+ } else \
+ { s -= 2; s[0] = *(list = (char*)_Sfdec + (v <<= 1)); s[1] = *(list+1); \
+ } \
+ } else \
+ { if(v < 1000) \
+ { s -= 3; SFDIGIT(v,100,s[0]); \
+ s[1] = *(list = (char*)_Sfdec + (v <<= 1)); s[2] = *(list+1); \
+ } else \
+ { s -= 4; SFDIGIT(v,1000,s[0]); SFDIGIT(v,100,s[1]); \
+ s[2] = *(list = (char*)_Sfdec + (v <<= 1)); s[3] = *(list+1); \
+ } \
+ } \
+ }
+
+/* handy functions */
+#undef min
+#undef max
+#define min(x,y) ((x) < (y) ? (x) : (y))
+#define max(x,y) ((x) > (y) ? (x) : (y))
+
+/* fast functions for memory copy and memory clear */
+#if _PACKAGE_ast
+#define memclear(s,n) memzero(s,n)
+#else
+#if _lib_bcopy && !_lib_memcpy
+#define memcpy(to,fr,n) bcopy((fr),(to),(n))
+#endif
+#if _lib_bzero && !_lib_memset
+#define memclear(s,n) bzero((s),(n))
+#else
+#define memclear(s,n) memset((s),'\0',(n))
+#endif
+#endif /*_PACKAGE_ast*/
+
+/* note that MEMCPY advances the associated pointers */
+#define MEMCPY(to,fr,n) \
+ switch(n) \
+ { default : memcpy((Void_t*)to,(Void_t*)fr,n); to += n; fr += n; break; \
+ case 7 : *to++ = *fr++; \
+ case 6 : *to++ = *fr++; \
+ case 5 : *to++ = *fr++; \
+ case 4 : *to++ = *fr++; \
+ case 3 : *to++ = *fr++; \
+ case 2 : *to++ = *fr++; \
+ case 1 : *to++ = *fr++; \
+ }
+#define MEMSET(s,c,n) \
+ switch(n) \
+ { default : memset((Void_t*)s,(int)c,n); s += n; break; \
+ case 7 : *s++ = c; \
+ case 6 : *s++ = c; \
+ case 5 : *s++ = c; \
+ case 4 : *s++ = c; \
+ case 3 : *s++ = c; \
+ case 2 : *s++ = c; \
+ case 1 : *s++ = c; \
+ }
+
+_BEGIN_EXTERNS_
+
+extern Sftab_t _Sftable;
+
+extern int _sfpopen _ARG_((Sfio_t*, int, int, int));
+extern int _sfpclose _ARG_((Sfio_t*));
+extern int _sfexcept _ARG_((Sfio_t*, int, ssize_t, Sfdisc_t*));
+extern Sfrsrv_t* _sfrsrv _ARG_((Sfio_t*, ssize_t));
+extern int _sfsetpool _ARG_((Sfio_t*));
+extern char* _sfcvt _ARG_((Void_t*,char*,size_t,int,int*,int*,int*,int));
+extern char** _sfgetpath _ARG_((char*));
+
+#if _BLD_sfio && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+#if !_BLD_sfio && defined(__IMPORT__)
+#define extern extern __IMPORT__
+#endif
+
+extern Sfextern_t _Sfextern;
+
+extern int _sfmode _ARG_((Sfio_t*, int, int));
+extern int _sftype _ARG_((const char*, int*, int*));
+
+#undef extern
+
+#ifndef errno
+extern int errno;
+#endif
+
+/* for portable encoding of double values */
+#ifndef frexpl
+#if _ast_fltmax_double
+#define frexpl frexp
+#endif
+#if !__STDC__
+extern Sfdouble_t frexpl _ARG_((Sfdouble_t, int*));
+#endif
+#endif
+#ifndef ldexpl
+#if _ast_fltmax_double
+#define ldexpl ldexp
+#endif
+#if !__STDC__
+extern Sfdouble_t ldexpl _ARG_((Sfdouble_t, int));
+#endif
+#endif
+
+#if !_PACKAGE_ast
+
+#if !__STDC__ && !_hdr_stdlib
+extern void abort _ARG_((void));
+extern int atexit _ARG_((void(*)(void)));
+extern char* getenv _ARG_((const char*));
+extern void* malloc _ARG_((size_t));
+extern void* realloc _ARG_((void*, size_t));
+extern void free _ARG_((void*));
+extern size_t strlen _ARG_((const char*));
+extern char* strcpy _ARG_((char*, const char*));
+
+extern Void_t* memset _ARG_((void*, int, size_t));
+extern Void_t* memchr _ARG_((const void*, int, size_t));
+extern Void_t* memccpy _ARG_((void*, const void*, int, size_t));
+#ifndef memcpy
+extern Void_t* memcpy _ARG_((void*, const void*, size_t));
+#endif
+#if !defined(strtod)
+extern double strtod _ARG_((const char*, char**));
+#endif
+#if !defined(remove)
+extern int sysremovef _ARG_((const char*));
+#endif
+#endif /* !__STDC__ && !_hdr_stdlib */
+
+#if !_hdr_unistd
+#if _proto_open && __cplusplus
+extern int sysopenf _ARG_((const char*, int, ...));
+#endif
+extern int sysclosef _ARG_((int));
+extern ssize_t sysreadf _ARG_((int, void*, size_t));
+extern ssize_t syswritef _ARG_((int, const void*, size_t));
+extern sfoff_t syslseekf _ARG_((int, sfoff_t, int));
+extern int sysdupf _ARG_((int));
+extern int syspipef _ARG_((int*));
+extern int sysaccessf _ARG_((const char*, int));
+extern int sysremovef _ARG_((const char*));
+extern int sysfstatf _ARG_((int, sfstat_t*));
+extern int sysstatf _ARG_((const char*, sfstat_t*));
+
+extern int isatty _ARG_((int));
+
+extern int wait _ARG_((int*));
+extern uint sleep _ARG_((uint));
+extern int execl _ARG_((const char*, const char*,...));
+extern int execv _ARG_((const char*, char**));
+#if !defined(fork)
+extern int fork _ARG_((void));
+#endif
+#if _lib_unlink
+extern int unlink _ARG_((const char*));
+#endif
+
+#endif /*_hdr_unistd*/
+
+#if _lib_bcopy && !_proto_bcopy
+extern void bcopy _ARG_((const void*, void*, size_t));
+#endif
+#if _lib_bzero && !_proto_bzero
+extern void bzero _ARG_((void*, size_t));
+#endif
+
+extern time_t time _ARG_((time_t*));
+extern int waitpid _ARG_((int,int*,int));
+extern void _exit _ARG_((int));
+typedef int(* Onexit_f)_ARG_((void));
+extern Onexit_f onexit _ARG_((Onexit_f));
+
+#if _lib_vfork && !_hdr_vfork && !_sys_vfork
+extern pid_t vfork _ARG_((void));
+#endif /*_lib_vfork*/
+
+#if _lib_poll
+#if _lib_poll_fd_1
+extern int poll _ARG_((struct pollfd*, ulong, int));
+#else
+extern int poll _ARG_((ulong, struct pollfd*, int));
+#endif
+#endif /*_lib_poll*/
+
+#endif /* _PACKAGE_ast */
+
+_END_EXTERNS_
+
+#endif /*_SFHDR_H*/
diff --git a/src/lib/libast/sfio/sfllen.c b/src/lib/libast/sfio/sfllen.c
new file mode 100644
index 0000000..4dd4879
--- /dev/null
+++ b/src/lib/libast/sfio/sfllen.c
@@ -0,0 +1,39 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Get size of a long value coded in a portable format
+**
+** Written by Kiem-Phong Vo
+*/
+#if __STD_C
+int _sfllen(Sflong_t v)
+#else
+int _sfllen(v)
+Sflong_t v;
+#endif
+{
+ if(v < 0)
+ v = -(v+1);
+ v = (Sfulong_t)v >> SF_SBITS;
+ return 1 + (v > 0 ? sfulen(v) : 0);
+}
diff --git a/src/lib/libast/sfio/sfmode.c b/src/lib/libast/sfio/sfmode.c
new file mode 100644
index 0000000..97182fb
--- /dev/null
+++ b/src/lib/libast/sfio/sfmode.c
@@ -0,0 +1,596 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+static char* Version = "\n@(#)$Id: sfio (AT&T Labs - Research) 2009-09-15 $\0\n";
+
+/* Functions to set a given stream to some desired mode
+**
+** Written by Kiem-Phong Vo.
+**
+** Modifications:
+** 06/27/1990 (first version)
+** 01/06/1991
+** 07/08/1991
+** 06/18/1992
+** 02/02/1993
+** 05/25/1993
+** 02/07/1994
+** 05/21/1996
+** 08/01/1997
+** 08/01/1998 (extended formatting)
+** 09/09/1999 (thread-safe)
+** 02/01/2001 (adaptive buffering)
+** 05/31/2002 (multi-byte handling in sfvprintf/vscanf)
+** 09/06/2002 (SF_IOINTR flag)
+** 11/15/2002 (%#c for sfvprintf)
+** 05/31/2003 (sfsetbuf(f,f,align_size) to set alignment for data)
+** (%I1d is fixed to handle "signed char" correctly)
+** 01/01/2004 Porting issues to various platforms resolved.
+** 06/01/2008 Allowing notify() at entering/exiting thread-safe routines.
+** 09/15/2008 Add sfwalk().
+*/
+
+/* the below is for protecting the application from SIGPIPE */
+#if _PACKAGE_ast
+#include <sig.h>
+#include <wait.h>
+#define Sfsignal_f Sig_handler_t
+#else
+#include <signal.h>
+typedef void(* Sfsignal_f)_ARG_((int));
+#endif
+static int _Sfsigp = 0; /* # of streams needing SIGPIPE protection */
+
+/* done at exiting time */
+#if __STD_C
+static void _sfcleanup(void)
+#else
+static void _sfcleanup()
+#endif
+{
+ reg Sfpool_t* p;
+ reg Sfio_t* f;
+ reg int n;
+ reg int pool;
+
+ f = (Sfio_t*)Version; /* shut compiler warning */
+
+ /* set this so that no more buffering is allowed for write streams */
+ _Sfexiting = 1001;
+
+ sfsync(NIL(Sfio_t*));
+
+ for(p = &_Sfpool; p; p = p->next)
+ { for(n = 0; n < p->n_sf; ++n)
+ { if(!(f = p->sf[n]) || SFFROZEN(f) )
+ continue;
+
+ SFLOCK(f,0);
+ SFMTXLOCK(f);
+
+ /* let application know that we are leaving */
+ (void)SFRAISE(f, SF_ATEXIT, NIL(Void_t*));
+
+ if(f->flags&SF_STRING)
+ continue;
+
+ /* from now on, write streams are unbuffered */
+ pool = f->mode&SF_POOL;
+ f->mode &= ~SF_POOL;
+ if((f->flags&SF_WRITE) && !(f->mode&SF_WRITE))
+ (void)_sfmode(f,SF_WRITE,1);
+ if(f->data &&
+ ((f->bits&SF_MMAP) ||
+ ((f->mode&SF_WRITE) && f->next == f->data) ) )
+ (void)SFSETBUF(f,NIL(Void_t*),0);
+ f->mode |= pool;
+
+ SFMTXUNLOCK(f);
+ SFOPEN(f,0);
+ }
+ }
+}
+
+/* put into discrete pool */
+#if __STD_C
+int _sfsetpool(Sfio_t* f)
+#else
+int _sfsetpool(f)
+Sfio_t* f;
+#endif
+{
+ reg Sfpool_t* p;
+ reg Sfio_t** array;
+ reg int n, rv;
+
+ if(!_Sfcleanup)
+ { _Sfcleanup = _sfcleanup;
+ (void)atexit(_sfcleanup);
+ }
+
+ if(!(p = f->pool) )
+ p = f->pool = &_Sfpool;
+
+ POOLMTXENTER(p);
+
+ rv = -1;
+
+ if(p->n_sf >= p->s_sf)
+ { if(p->s_sf == 0) /* initialize pool array */
+ { p->s_sf = sizeof(p->array)/sizeof(p->array[0]);
+ p->sf = p->array;
+ }
+ else /* allocate a larger array */
+ { n = (p->sf != p->array ? p->s_sf : (p->s_sf/4 + 1)*4) + 4;
+ if(!(array = (Sfio_t**)malloc(n*sizeof(Sfio_t*))) )
+ goto done;
+
+ /* move old array to new one */
+ memcpy((Void_t*)array,(Void_t*)p->sf,p->n_sf*sizeof(Sfio_t*));
+ if(p->sf != p->array)
+ free((Void_t*)p->sf);
+
+ p->sf = array;
+ p->s_sf = n;
+ }
+ }
+
+ /* always add at end of array because if this was done during some sort
+ of walk thru all streams, we'll want the new stream to be seen.
+ */
+ p->sf[p->n_sf++] = f;
+ rv = 0;
+
+done:
+ POOLMTXRETURN(p, rv);
+}
+
+/* create an auxiliary buffer for sfgetr/sfreserve/sfputr */
+#if __STD_C
+Sfrsrv_t* _sfrsrv(reg Sfio_t* f, reg ssize_t size)
+#else
+Sfrsrv_t* _sfrsrv(f,size)
+reg Sfio_t* f;
+reg ssize_t size;
+#endif
+{
+ Sfrsrv_t *rsrv, *rs;
+
+ /* make buffer if nothing yet */
+ size = ((size + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
+ if(!(rsrv = f->rsrv) || size > rsrv->size)
+ { if(!(rs = (Sfrsrv_t*)malloc(size+sizeof(Sfrsrv_t))))
+ size = -1;
+ else
+ { if(rsrv)
+ { if(rsrv->slen > 0)
+ memcpy(rs,rsrv,sizeof(Sfrsrv_t)+rsrv->slen);
+ free(rsrv);
+ }
+ f->rsrv = rsrv = rs;
+ rsrv->size = size;
+ rsrv->slen = 0;
+ }
+ }
+
+ if(rsrv && size > 0)
+ rsrv->slen = 0;
+
+ return size >= 0 ? rsrv : NIL(Sfrsrv_t*);
+}
+
+#ifdef SIGPIPE
+#if __STD_C
+static void ignoresig(int sig)
+#else
+static void ignoresig(sig)
+int sig;
+#endif
+{
+ signal(sig, ignoresig);
+}
+#endif
+
+#if __STD_C
+int _sfpopen(reg Sfio_t* f, int fd, int pid, int stdio)
+#else
+int _sfpopen(f, fd, pid, stdio)
+reg Sfio_t* f;
+int fd;
+int pid;
+int stdio; /* stdio popen() does not reset SIGPIPE handler */
+#endif
+{
+ reg Sfproc_t* p;
+
+ if(f->proc)
+ return 0;
+
+ if(!(p = f->proc = (Sfproc_t*)malloc(sizeof(Sfproc_t))) )
+ return -1;
+
+ p->pid = pid;
+ p->size = p->ndata = 0;
+ p->rdata = NIL(uchar*);
+ p->file = fd;
+ p->sigp = (!stdio && pid >= 0 && (f->flags&SF_WRITE)) ? 1 : 0;
+
+#ifdef SIGPIPE /* protect from broken pipe signal */
+ if(p->sigp)
+ { Sfsignal_f handler;
+
+ (void)vtmtxlock(_Sfmutex);
+ if((handler = signal(SIGPIPE, ignoresig)) != SIG_DFL &&
+ handler != ignoresig)
+ signal(SIGPIPE, handler); /* honor user handler */
+ _Sfsigp += 1;
+ (void)vtmtxunlock(_Sfmutex);
+ }
+#endif
+
+ return 0;
+}
+
+#if __STD_C
+int _sfpclose(reg Sfio_t* f)
+#else
+int _sfpclose(f)
+reg Sfio_t* f; /* stream to close */
+#endif
+{
+ Sfproc_t* p;
+ int pid, status;
+
+ if(!(p = f->proc))
+ return -1;
+ f->proc = NIL(Sfproc_t*);
+
+ if(p->rdata)
+ free(p->rdata);
+
+ if(p->pid < 0)
+ status = 0;
+ else
+ { /* close the associated stream */
+ if(p->file >= 0)
+ CLOSE(p->file);
+
+ /* wait for process termination */
+#if _PACKAGE_ast
+ sigcritical(SIG_REG_EXEC|SIG_REG_PROC);
+#endif
+ while ((pid = waitpid(p->pid,&status,0)) == -1 && errno == EINTR)
+ ;
+ if(pid == -1)
+ status = -1;
+#if _PACKAGE_ast
+ sigcritical(0);
+#endif
+
+#ifdef SIGPIPE
+ (void)vtmtxlock(_Sfmutex);
+ if(p->sigp && (_Sfsigp -= 1) <= 0)
+ { Sfsignal_f handler;
+ if((handler = signal(SIGPIPE,SIG_DFL)) != SIG_DFL &&
+ handler != ignoresig)
+ signal(SIGPIPE,handler); /* honor user handler */
+ _Sfsigp = 0;
+ }
+ (void)vtmtxunlock(_Sfmutex);
+#endif
+ }
+
+ free(p);
+ return status;
+}
+
+#if __STD_C
+static int _sfpmode(Sfio_t* f, int type)
+#else
+static int _sfpmode(f,type)
+Sfio_t* f;
+int type;
+#endif
+{
+ Sfproc_t* p;
+
+ if(!(p = f->proc) )
+ return -1;
+
+ if(type == SF_WRITE)
+ { /* save unread data */
+ p->ndata = f->endb-f->next;
+ if(p->ndata > p->size)
+ { if(p->rdata)
+ free((char*)p->rdata);
+ if((p->rdata = (uchar*)malloc(p->ndata)) )
+ p->size = p->ndata;
+ else
+ { p->size = 0;
+ return -1;
+ }
+ }
+ if(p->ndata > 0)
+ memcpy((Void_t*)p->rdata,(Void_t*)f->next,p->ndata);
+ f->endb = f->data;
+ }
+ else
+ { /* restore read data */
+ if(p->ndata > f->size) /* may lose data!!! */
+ p->ndata = f->size;
+ if(p->ndata > 0)
+ { memcpy((Void_t*)f->data,(Void_t*)p->rdata,p->ndata);
+ f->endb = f->data+p->ndata;
+ p->ndata = 0;
+ }
+ }
+
+ /* switch file descriptor */
+ if(p->pid >= 0)
+ { type = f->file;
+ f->file = p->file;
+ p->file = type;
+ }
+
+ return 0;
+}
+
+#if __STD_C
+int _sfmode(reg Sfio_t* f, reg int wanted, reg int local)
+#else
+int _sfmode(f, wanted, local)
+reg Sfio_t* f; /* change r/w mode and sync file pointer for this stream */
+reg int wanted; /* desired mode */
+reg int local; /* a local call */
+#endif
+{
+ reg int n;
+ Sfoff_t addr;
+ reg int rv = 0;
+
+ SFONCE(); /* initialize mutexes */
+
+ if(wanted&SF_SYNCED) /* for (SF_SYNCED|SF_READ) stream, just junk data */
+ { wanted &= ~SF_SYNCED;
+ if((f->mode&(SF_SYNCED|SF_READ)) == (SF_SYNCED|SF_READ) )
+ { f->next = f->endb = f->endr = f->data;
+ f->mode &= ~SF_SYNCED;
+ }
+ }
+
+ if((!local && SFFROZEN(f)) || (!(f->flags&SF_STRING) && f->file < 0))
+ { if(local || !f->disc || !f->disc->exceptf)
+ { local = 1;
+ goto err_notify;
+ }
+
+ for(;;)
+ { if((rv = (*f->disc->exceptf)(f,SF_LOCKED,0,f->disc)) < 0)
+ return rv;
+ if((!local && SFFROZEN(f)) ||
+ (!(f->flags&SF_STRING) && f->file < 0) )
+ { if(rv == 0)
+ { local = 1;
+ goto err_notify;
+ }
+ else continue;
+ }
+ else break;
+ }
+ }
+
+ if(f->mode&SF_GETR)
+ { f->mode &= ~SF_GETR;
+#ifdef MAP_TYPE
+ if((f->bits&SF_MMAP) && (f->tiny[0] += 1) >= (4*SF_NMAP) )
+ { /* turn off mmap to avoid page faulting */
+ sfsetbuf(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND);
+ f->tiny[0] = 0;
+ }
+ else
+#endif
+ if(f->getr)
+ { f->next[-1] = f->getr;
+ f->getr = 0;
+ }
+ }
+
+ if(f->mode&SF_STDIO) /* synchronizing with stdio pointers */
+ (*_Sfstdsync)(f);
+
+ if(f->disc == _Sfudisc && wanted == SF_WRITE &&
+ sfclose((*_Sfstack)(f,NIL(Sfio_t*))) < 0 )
+ { local = 1;
+ goto err_notify;
+ }
+
+ if(f->mode&SF_POOL)
+ { /* move to head of pool */
+ if(f == f->pool->sf[0] || (*_Sfpmove)(f,0) < 0 )
+ { local = 1;
+ goto err_notify;
+ }
+ f->mode &= ~SF_POOL;
+ }
+
+ SFLOCK(f,local);
+
+ /* buffer initialization */
+ wanted &= SF_RDWR;
+ if(f->mode&SF_INIT)
+ {
+ if(!f->pool && _sfsetpool(f) < 0)
+ { rv = -1;
+ goto done;
+ }
+
+ if(wanted == 0)
+ goto done;
+
+ if(wanted != (int)(f->mode&SF_RDWR) && !(f->flags&wanted) )
+ goto err_notify;
+
+ if((f->flags&SF_STRING) && f->size >= 0 && f->data)
+ { f->mode &= ~SF_INIT;
+ f->extent = ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ?
+ f->size : 0;
+ f->here = 0;
+ f->endb = f->data + f->size;
+ f->next = f->endr = f->endw = f->data;
+ if(f->mode&SF_READ)
+ f->endr = f->endb;
+ else f->endw = f->endb;
+ }
+ else
+ { n = f->flags;
+ (void)SFSETBUF(f,f->data,f->size);
+ f->flags |= (n&SF_MALLOC);
+ }
+ }
+
+ if(wanted == (int)SFMODE(f,1))
+ goto done;
+
+ switch(SFMODE(f,1))
+ {
+ case SF_WRITE: /* switching to SF_READ */
+ if(wanted == 0 || wanted == SF_WRITE)
+ break;
+ if(!(f->flags&SF_READ) )
+ goto err_notify;
+ else if(f->flags&SF_STRING)
+ { SFSTRSIZE(f);
+ f->endb = f->data+f->extent;
+ f->mode = SF_READ;
+ break;
+ }
+
+ /* reset buffer */
+ if(f->next > f->data && SFFLSBUF(f,-1) < 0)
+ goto err_notify;
+
+ if(f->size == 0)
+ { /* unbuffered */
+ f->data = f->tiny;
+ f->size = sizeof(f->tiny);
+ }
+ f->next = f->endr = f->endw = f->endb = f->data;
+ f->mode = SF_READ|SF_LOCK;
+
+ /* restore saved read data for coprocess */
+ if(f->proc && _sfpmode(f,wanted) < 0)
+ goto err_notify;
+
+ break;
+
+ case (SF_READ|SF_SYNCED): /* a previously sync-ed read stream */
+ if(wanted != SF_WRITE)
+ { /* just reset the pointers */
+ f->mode = SF_READ|SF_LOCK;
+
+ /* see if must go with new physical location */
+ if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC) &&
+ (addr = SFSK(f,0,SEEK_CUR,f->disc)) != f->here)
+ {
+#ifdef MAP_TYPE
+ if((f->bits&SF_MMAP) && f->data)
+ { SFMUNMAP(f,f->data,f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+#endif
+ f->endb = f->endr = f->endw = f->next = f->data;
+ f->here = addr;
+ }
+ else
+ { addr = f->here + (f->endb - f->next);
+ if(SFSK(f,addr,SEEK_SET,f->disc) < 0)
+ goto err_notify;
+ f->here = addr;
+ }
+
+ break;
+ }
+ /* fall thru */
+
+ case SF_READ: /* switching to SF_WRITE */
+ if(wanted != SF_WRITE)
+ break;
+ else if(!(f->flags&SF_WRITE))
+ goto err_notify;
+ else if(f->flags&SF_STRING)
+ { f->endb = f->data+f->size;
+ f->mode = SF_WRITE|SF_LOCK;
+ break;
+ }
+
+ /* save unread data before switching mode */
+ if(f->proc && _sfpmode(f,wanted) < 0)
+ goto err_notify;
+
+ /* reset buffer and seek pointer */
+ if(!(f->mode&SF_SYNCED) )
+ { n = f->endb - f->next;
+ if(f->extent >= 0 && (n > 0 || (f->data && (f->bits&SF_MMAP))) )
+ { /* reset file pointer */
+ addr = f->here - n;
+ if(SFSK(f,addr,SEEK_SET,f->disc) < 0)
+ goto err_notify;
+ f->here = addr;
+ }
+ }
+
+ f->mode = SF_WRITE|SF_LOCK;
+#ifdef MAP_TYPE
+ if(f->bits&SF_MMAP)
+ { if(f->data)
+ SFMUNMAP(f,f->data,f->endb-f->data);
+ (void)SFSETBUF(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND);
+ }
+#endif
+ if(f->data == f->tiny)
+ { f->endb = f->data = f->next = NIL(uchar*);
+ f->size = 0;
+ }
+ else f->endb = (f->next = f->data) + f->size;
+
+ break;
+
+ default: /* unknown case */
+ err_notify:
+ if((wanted &= SF_RDWR) == 0 && (wanted = f->flags&SF_RDWR) == SF_RDWR)
+ wanted = SF_READ;
+
+ /* set errno for operations that access wrong stream type */
+ if(wanted != (f->mode&SF_RDWR) && f->file >= 0)
+ errno = EBADF;
+
+ if(_Sfnotify) /* notify application of the error */
+ (*_Sfnotify)(f, wanted, (void*)((long)f->file));
+
+ rv = -1;
+ break;
+ }
+
+done:
+ SFOPEN(f,local);
+ return rv;
+}
diff --git a/src/lib/libast/sfio/sfmove.c b/src/lib/libast/sfio/sfmove.c
new file mode 100644
index 0000000..9e39657
--- /dev/null
+++ b/src/lib/libast/sfio/sfmove.c
@@ -0,0 +1,242 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Move data from one stream to another.
+** This code is written so that it'll work even in the presence
+** of stacking streams, pool, and discipline.
+** If you must change it, be gentle.
+**
+** Written by Kiem-Phong Vo.
+*/
+#define MAX_SSIZE ((ssize_t)((~((size_t)0)) >> 1))
+
+#if __STD_C
+Sfoff_t sfmove(Sfio_t* fr, Sfio_t* fw, Sfoff_t n, reg int rc)
+#else
+Sfoff_t sfmove(fr,fw,n,rc)
+Sfio_t* fr; /* moving data from this stream */
+Sfio_t* fw; /* moving data to this stream */
+Sfoff_t n; /* number of bytes/records to move. <0 for unbounded move */
+reg int rc; /* record separator */
+#endif
+{
+ reg uchar *cp, *next;
+ reg ssize_t r, w;
+ reg uchar *endb;
+ reg int direct;
+ Sfoff_t n_move, sk, cur;
+ uchar *rbuf = NIL(uchar*);
+ ssize_t rsize = 0;
+ SFMTXDECL(fr); /* declare a shadow stream variable for from stream */
+ SFMTXDECL2(fw); /* declare a shadow stream variable for to stream */
+
+ SFMTXENTER(fr, (Sfoff_t)0);
+ if(fw)
+ SFMTXBEGIN2(fw, (Sfoff_t)0);
+
+ for(n_move = 0; n != 0; )
+ {
+ if(rc >= 0) /* moving records, let sfgetr() deal with record reading */
+ { if(!(cp = (uchar*)sfgetr(fr,rc,0)) )
+ n = 0;
+ else
+ { r = sfvalue(fr);
+ if(fw && (w = SFWRITE(fw, cp, r)) != r)
+ { if(fr->extent >= 0 )
+ (void)SFSEEK(fr,(Sfoff_t)(-r),SEEK_CUR);
+ if(fw->extent >= 0 && w > 0)
+ (void)SFSEEK(fw,(Sfoff_t)(-w),SEEK_CUR);
+ n = 0;
+ }
+ else
+ { n_move += 1;
+ if(n > 0)
+ n -= 1;
+ }
+ }
+ continue;
+ }
+
+ /* get the streams into the right mode */
+ if(fr->mode != SF_READ && _sfmode(fr,SF_READ,0) < 0)
+ break;
+
+ SFLOCK(fr,0);
+
+ /* flush the write buffer as necessary to make room */
+ if(fw)
+ { if(fw->mode != SF_WRITE && _sfmode(fw,SF_WRITE,0) < 0 )
+ break;
+ SFLOCK(fw,0);
+ if(fw->next >= fw->endb ||
+ (fw->next > fw->data && fr->extent < 0 &&
+ (fw->extent < 0 || (fw->flags&SF_SHARE)) ) )
+ if(SFFLSBUF(fw,-1) < 0 )
+ break;
+ }
+ else if((cur = SFSEEK(fr, (Sfoff_t)0, SEEK_CUR)) >= 0 )
+ { sk = n > 0 ? SFSEEK(fr, n, SEEK_CUR) : SFSEEK(fr, 0, SEEK_END);
+ if(sk > cur) /* safe to skip over data in current stream */
+ { n_move += sk - cur;
+ if(n > 0)
+ n -= sk - cur;
+ continue;
+ }
+ /* else: stream unstacking may happen below */
+ }
+
+ /* about to move all, set map to a large amount */
+ if(n < 0 && (fr->bits&SF_MMAP) && !(fr->bits&SF_MVSIZE) )
+ { SFMVSET(fr);
+ fr->bits |= SF_SEQUENTIAL; /* sequentially access data */
+ }
+
+ /* try reading a block of data */
+ direct = 0;
+ if((r = fr->endb - (next = fr->next)) <= 0)
+ { /* amount of data remained to be read */
+ if((w = n > MAX_SSIZE ? MAX_SSIZE : (ssize_t)n) < 0)
+ { if(fr->extent < 0)
+ w = fr->data == fr->tiny ? SF_GRAIN : fr->size;
+ else if((fr->extent-fr->here) > SF_NMAP*SF_PAGE)
+ w = SF_NMAP*SF_PAGE;
+ else w = (ssize_t)(fr->extent-fr->here);
+ }
+
+ /* use a decent buffer for data transfer but make sure
+ that if we overread, the left over can be retrieved
+ */
+ if(!(fr->flags&SF_STRING) && !(fr->bits&SF_MMAP) &&
+ (n < 0 || fr->extent >= 0) )
+ { reg ssize_t maxw = 4*(_Sfpage > 0 ? _Sfpage : SF_PAGE);
+
+ /* direct transfer to a seekable write stream */
+ if(fw && fw->extent >= 0 && w <= (fw->endb-fw->next) )
+ { w = fw->endb - (next = fw->next);
+ direct = SF_WRITE;
+ }
+ else if(w > fr->size && maxw > fr->size)
+ { /* making our own buffer */
+ if(w >= maxw)
+ w = maxw;
+ else w = ((w+fr->size-1)/fr->size)*fr->size;
+ if(rsize <= 0 && (rbuf = (uchar*)malloc(w)) )
+ rsize = w;
+ if(rbuf)
+ { next = rbuf;
+ w = rsize;
+ direct = SF_STRING;
+ }
+ }
+ }
+
+ if(!direct)
+ { /* make sure we don't read too far ahead */
+ if(n > 0 && fr->extent < 0 && (fr->flags&SF_SHARE) )
+ { if((Sfoff_t)(r = fr->size) > n)
+ r = (ssize_t)n;
+ }
+ else r = -1;
+ if((r = SFFILBUF(fr,r)) <= 0)
+ break;
+ next = fr->next;
+ }
+ else
+ { /* actual amount to be read */
+ if(n > 0 && n < w)
+ w = (ssize_t)n;
+
+ if((r = SFRD(fr,next,w,fr->disc)) > 0)
+ fr->next = fr->endb = fr->endr = fr->data;
+ else if(r == 0)
+ break; /* eof */
+ else goto again; /* popped stack */
+ }
+ }
+
+ /* compute the extent of data to be moved */
+ endb = next+r;
+ if(n > 0)
+ { if(r > n)
+ r = (ssize_t)n;
+ n -= r;
+ }
+ n_move += r;
+ cp = next+r;
+
+ if(!direct)
+ fr->next += r;
+ else if((w = endb-cp) > 0)
+ { /* move left-over to read stream */
+ if(w > fr->size)
+ w = fr->size;
+ memcpy((Void_t*)fr->data,(Void_t*)cp,w);
+ fr->endb = fr->data+w;
+ if((w = endb - (cp+w)) > 0)
+ (void)SFSK(fr,(Sfoff_t)(-w),SEEK_CUR,fr->disc);
+ }
+
+ if(fw)
+ { if(direct == SF_WRITE)
+ fw->next += r;
+ else if(r <= (fw->endb-fw->next) )
+ { memcpy((Void_t*)fw->next,(Void_t*)next,r);
+ fw->next += r;
+ }
+ else if((w = SFWRITE(fw,(Void_t*)next,r)) != r)
+ { /* a write error happened */
+ if(w > 0)
+ { r -= w;
+ n_move -= r;
+ }
+ if(fr->extent >= 0)
+ (void)SFSEEK(fr,(Sfoff_t)(-r),SEEK_CUR);
+ break;
+ }
+ }
+
+ again:
+ SFOPEN(fr,0);
+ if(fw)
+ SFOPEN(fw,0);
+ }
+
+ if(n < 0 && (fr->bits&SF_MMAP) && (fr->bits&SF_MVSIZE))
+ { /* back to normal access mode */
+ SFMVUNSET(fr);
+ if((fr->bits&SF_SEQUENTIAL) && (fr->data))
+ SFMMSEQOFF(fr,fr->data,fr->endb-fr->data);
+ fr->bits &= ~SF_SEQUENTIAL;
+ }
+
+ if(rbuf)
+ free(rbuf);
+
+ if(fw)
+ { SFOPEN(fw,0);
+ SFMTXEND2(fw);
+ }
+
+ SFOPEN(fr,0);
+ SFMTXRETURN(fr, n_move);
+}
diff --git a/src/lib/libast/sfio/sfmutex.c b/src/lib/libast/sfio/sfmutex.c
new file mode 100644
index 0000000..cc3a4b7
--- /dev/null
+++ b/src/lib/libast/sfio/sfmutex.c
@@ -0,0 +1,69 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Obtain/release exclusive use of a stream.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+/* the main locking/unlocking interface */
+#if __STD_C
+int sfmutex(Sfio_t* f, int type)
+#else
+int sfmutex(f, type)
+Sfio_t* f;
+int type;
+#endif
+{
+#if !vt_threaded
+ NOTUSED(f); NOTUSED(type);
+ return 0;
+#else
+
+ SFONCE();
+
+ if(!f)
+ return -1;
+
+ if(!f->mutex)
+ { if(f->bits&SF_PRIVATE)
+ return 0;
+
+ vtmtxlock(_Sfmutex);
+ f->mutex = vtmtxopen(NIL(Vtmutex_t*), VT_INIT);
+ vtmtxunlock(_Sfmutex);
+ if(!f->mutex)
+ return -1;
+ }
+
+ if(type == SFMTX_LOCK)
+ return vtmtxlock(f->mutex);
+ else if(type == SFMTX_TRYLOCK)
+ return vtmtxtrylock(f->mutex);
+ else if(type == SFMTX_UNLOCK)
+ return vtmtxunlock(f->mutex);
+ else if(type == SFMTX_CLRLOCK)
+ return vtmtxclrlock(f->mutex);
+ else return -1;
+#endif /*vt_threaded*/
+}
diff --git a/src/lib/libast/sfio/sfnew.c b/src/lib/libast/sfio/sfnew.c
new file mode 100644
index 0000000..a6feddc
--- /dev/null
+++ b/src/lib/libast/sfio/sfnew.c
@@ -0,0 +1,129 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Fundamental function to create a new stream.
+** The argument flags defines the type of stream and the scheme
+** of buffering.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+Sfio_t* sfnew(Sfio_t* oldf, Void_t* buf, size_t size, int file, int flags)
+#else
+Sfio_t* sfnew(oldf,buf,size,file,flags)
+Sfio_t* oldf; /* old stream to be reused */
+Void_t* buf; /* a buffer to read/write, if NULL, will be allocated */
+size_t size; /* buffer size if buf is given or desired buffer size */
+int file; /* file descriptor to read/write from */
+int flags; /* type of file stream */
+#endif
+{
+ reg Sfio_t* f;
+ reg int sflags;
+
+ SFONCE(); /* initialize mutexes */
+
+ if(!(flags&SF_RDWR))
+ return NIL(Sfio_t*);
+
+ sflags = 0;
+ if((f = oldf) )
+ { if(flags&SF_EOF)
+ { if(f != sfstdin && f != sfstdout && f != sfstderr)
+ f->mutex = NIL(Vtmutex_t*);
+ SFCLEAR(f, f->mutex);
+ oldf = NIL(Sfio_t*);
+ }
+ else if(f->mode&SF_AVAIL)
+ { /* only allow SF_STATIC to be already closed */
+ if(!(f->flags&SF_STATIC) )
+ return NIL(Sfio_t*);
+ sflags = f->flags;
+ oldf = NIL(Sfio_t*);
+ }
+ else
+ { /* reopening an open stream, close it first */
+ sflags = f->flags;
+
+ if(((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0) ||
+ SFCLOSE(f) < 0 )
+ return NIL(Sfio_t*);
+
+ if(f->data && ((flags&SF_STRING) || size != (size_t)SF_UNBOUND) )
+ { if(sflags&SF_MALLOC)
+ free((Void_t*)f->data);
+ f->data = NIL(uchar*);
+ }
+ if(!f->data)
+ sflags &= ~SF_MALLOC;
+ }
+ }
+
+ if(!f)
+ { /* reuse a standard stream structure if possible */
+ if(!(flags&SF_STRING) && file >= 0 && file <= 2)
+ { f = file == 0 ? sfstdin : file == 1 ? sfstdout : sfstderr;
+ if(f)
+ { if(f->mode&SF_AVAIL)
+ { sflags = f->flags;
+ SFCLEAR(f, f->mutex);
+ }
+ else f = NIL(Sfio_t*);
+ }
+ }
+
+ if(!f)
+ { if(!(f = (Sfio_t*)malloc(sizeof(Sfio_t))) )
+ return NIL(Sfio_t*);
+ SFCLEAR(f, NIL(Vtmutex_t*));
+ }
+ }
+
+ /* create a mutex */
+ if(!f->mutex)
+ f->mutex = vtmtxopen(NIL(Vtmutex_t*), VT_INIT);
+
+ /* stream type */
+ f->mode = (flags&SF_READ) ? SF_READ : SF_WRITE;
+ f->flags = (flags&SF_FLAGS) | (sflags&(SF_MALLOC|SF_STATIC));
+ f->bits = (flags&SF_RDWR) == SF_RDWR ? SF_BOTH : 0;
+ f->file = file;
+ f->here = f->extent = 0;
+ f->getr = f->tiny[0] = 0;
+
+ f->mode |= SF_INIT;
+ if(size != (size_t)SF_UNBOUND)
+ { f->size = size;
+ f->data = size <= 0 ? NIL(uchar*) : (uchar*)buf;
+ }
+ f->endb = f->endr = f->endw = f->next = f->data;
+
+ if(_Sfnotify)
+ (*_Sfnotify)(f, SF_NEW, (void*)((long)f->file));
+
+ if(f->flags&SF_STRING)
+ (void)_sfmode(f,f->mode&SF_RDWR,0);
+
+ return f;
+}
diff --git a/src/lib/libast/sfio/sfnotify.c b/src/lib/libast/sfio/sfnotify.c
new file mode 100644
index 0000000..06cc857
--- /dev/null
+++ b/src/lib/libast/sfio/sfnotify.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+
+/* Set the function to be called when a stream is opened or closed
+**
+** Written by Kiem-Phong Vo.
+*/
+#if __STD_C
+int sfnotify(void(*notify)(Sfio_t*, int, void*))
+#else
+int sfnotify(notify)
+void (*notify)();
+#endif
+{
+ _Sfnotify = notify;
+ return 0;
+}
diff --git a/src/lib/libast/sfio/sfnputc.c b/src/lib/libast/sfio/sfnputc.c
new file mode 100644
index 0000000..58a1430
--- /dev/null
+++ b/src/lib/libast/sfio/sfnputc.c
@@ -0,0 +1,81 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write out a character n times
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+ssize_t sfnputc(Sfio_t* f, int c, size_t n)
+#else
+ssize_t sfnputc(f,c,n)
+Sfio_t* f; /* file to write */
+int c; /* char to be written */
+size_t n; /* number of time to repeat */
+#endif
+{
+ reg uchar* ps;
+ reg ssize_t p, w;
+ uchar buf[128];
+ reg int local;
+ SFMTXDECL(f); /* declare a local stream variable for multithreading */
+
+ SFMTXENTER(f,-1);
+
+ GETLOCAL(f,local);
+ if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0)
+ SFMTXRETURN(f, -1);
+
+ SFLOCK(f,local);
+
+ /* write into a suitable buffer */
+ if((size_t)(p = (f->endb-(ps = f->next))) < n)
+ { ps = buf; p = sizeof(buf); }
+ if((size_t)p > n)
+ p = n;
+ MEMSET(ps,c,p);
+ ps -= p;
+
+ w = n;
+ if(ps == f->next)
+ { /* simple sfwrite */
+ f->next += p;
+ if(c == '\n')
+ (void)SFFLSBUF(f,-1);
+ goto done;
+ }
+
+ for(;;)
+ { /* hard write of data */
+ if((p = SFWRITE(f,(Void_t*)ps,p)) <= 0 || (n -= p) <= 0)
+ { w -= n;
+ goto done;
+ }
+ if((size_t)p > n)
+ p = n;
+ }
+done :
+ SFOPEN(f,local);
+ SFMTXRETURN(f, w);
+}
diff --git a/src/lib/libast/sfio/sfopen.c b/src/lib/libast/sfio/sfopen.c
new file mode 100644
index 0000000..522bd9e
--- /dev/null
+++ b/src/lib/libast/sfio/sfopen.c
@@ -0,0 +1,40 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/*
+ * _sfopen() wrapper to allow user sfopen() intercept
+ */
+
+extern Sfio_t* _sfopen _ARG_((Sfio_t*, const char*, const char*));
+
+#if __STD_C
+Sfio_t* sfopen(Sfio_t* f, const char* file, const char* mode)
+#else
+Sfio_t* sfopen(f,file,mode)
+Sfio_t* f; /* old stream structure */
+char* file; /* file/string to be opened */
+reg char* mode; /* mode of the stream */
+#endif
+{
+ return _sfopen(f, file, mode);
+}
diff --git a/src/lib/libast/sfio/sfpeek.c b/src/lib/libast/sfio/sfpeek.c
new file mode 100644
index 0000000..22cf807
--- /dev/null
+++ b/src/lib/libast/sfio/sfpeek.c
@@ -0,0 +1,89 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Safe access to the internal stream buffer.
+** This function is obsolete. sfreserve() should be used.
+**
+** Written by Kiem-Phong Vo (06/27/90).
+*/
+
+#if _BLD_sfio && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#if __STD_C
+extern ssize_t sfpeek(reg Sfio_t* f, Void_t** bp, reg size_t size)
+#else
+extern ssize_t sfpeek(f,bp,size)
+reg Sfio_t* f; /* file to peek */
+Void_t** bp; /* start of data area */
+reg size_t size; /* size of peek */
+#endif
+{ reg ssize_t n, sz;
+ reg int mode;
+
+ /* query for the extent of the remainder of the buffer */
+ if((sz = size) == 0 || !bp)
+ { if(f->mode&SF_INIT)
+ (void)_sfmode(f,0,0);
+
+ if((f->flags&SF_RDWRSTR) == SF_RDWRSTR)
+ { SFSTRSIZE(f);
+ n = (f->data+f->here) - f->next;
+ }
+ else n = f->endb - f->next;
+
+ if(!bp)
+ return n;
+ else if(n > 0) /* size == 0 */
+ { *bp = (Void_t*)f->next;
+ return 0;
+ }
+ /* else fall down and fill buffer */
+ }
+
+ if(!(mode = f->flags&SF_READ) )
+ mode = SF_WRITE;
+ if((int)f->mode != mode && _sfmode(f,mode,0) < 0)
+ return -1;
+
+ *bp = sfreserve(f, sz <= 0 ? 0 : sz > f->size ? f->size : sz, 0);
+
+ if(*bp && sz >= 0)
+ return sz;
+
+ if((n = sfvalue(f)) > 0)
+ { *bp = (Void_t*)f->next;
+ if(sz < 0)
+ { f->mode |= SF_PEEK;
+ f->endr = f->endw = f->data;
+ }
+ else
+ { if(sz > n)
+ sz = n;
+ f->next += sz;
+ }
+ }
+
+ return (sz >= 0 && n >= sz) ? sz : n;
+}
diff --git a/src/lib/libast/sfio/sfpkrd.c b/src/lib/libast/sfio/sfpkrd.c
new file mode 100644
index 0000000..2572e6d
--- /dev/null
+++ b/src/lib/libast/sfio/sfpkrd.c
@@ -0,0 +1,325 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+#if !_PACKAGE_ast
+#ifndef FIONREAD
+#if _sys_ioctl
+#include <sys/ioctl.h>
+#endif
+#endif
+#endif
+
+/* Read/Peek a record from an unseekable device
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#define STREAM_PEEK 001
+#define SOCKET_PEEK 002
+
+#if __STD_C
+ssize_t sfpkrd(int fd, Void_t* argbuf, size_t n, int rc, long tm, int action)
+#else
+ssize_t sfpkrd(fd, argbuf, n, rc, tm, action)
+int fd; /* file descriptor */
+Void_t* argbuf; /* buffer to read data */
+size_t n; /* buffer size */
+int rc; /* record character */
+long tm; /* time-out */
+int action; /* >0: peeking, if rc>=0, get action records,
+ <0: no peeking, if rc>=0, get -action records,
+ =0: no peeking, if rc>=0, must get a single record
+ */
+#endif
+{
+ reg ssize_t r;
+ reg int ntry, t;
+ reg char *buf = (char*)argbuf, *endbuf;
+
+ if(rc < 0 && tm < 0 && action <= 0)
+ return sysreadf(fd,buf,n);
+
+ t = (action > 0 || rc >= 0) ? (STREAM_PEEK|SOCKET_PEEK) : 0;
+#if !_stream_peek
+ t &= ~STREAM_PEEK;
+#endif
+#if !_socket_peek
+ t &= ~SOCKET_PEEK;
+#endif
+
+ for(ntry = 0; ntry < 2; ++ntry)
+ {
+ r = -1;
+#if _stream_peek
+ if((t&STREAM_PEEK) && (ntry == 1 || tm < 0) )
+ {
+#ifdef __sun
+ /*
+ * I_PEEK on stdin can hang rsh+ksh on solaris
+ * this kludge will have to do until sun^H^H^Horacle fixes I_PEEK/rsh
+ */
+ static int stream_peek;
+ if (stream_peek == 0) /* this will be done just once */
+ { char *e;
+ stream_peek = (
+ getenv("LOGNAME") == 0 &&
+ getenv("MAIL") == 0 &&
+ ((e = getenv("LANG")) == 0 || strcmp(e, "C") == 0) &&
+ ((e = getenv("PATH")) == 0 || strncmp(e, "/usr/bin:", 9) == 0)
+ ) ? -1 : 1;
+ }
+ if(stream_peek < 0)
+ t &= ~STREAM_PEEK;
+ else
+#endif
+ { struct strpeek pbuf;
+ pbuf.flags = 0;
+ pbuf.ctlbuf.maxlen = -1;
+ pbuf.ctlbuf.len = 0;
+ pbuf.ctlbuf.buf = NIL(char*);
+ pbuf.databuf.maxlen = n;
+ pbuf.databuf.buf = buf;
+ pbuf.databuf.len = 0;
+
+ if((r = ioctl(fd,I_PEEK,&pbuf)) < 0)
+ { if(errno == EINTR)
+ return -1;
+ t &= ~STREAM_PEEK;
+ }
+ else
+ { t &= ~SOCKET_PEEK;
+ if(r > 0 && (r = pbuf.databuf.len) <= 0)
+ { if(action <= 0) /* read past eof */
+ r = sysreadf(fd,buf,1);
+ return r;
+ }
+ if(r == 0)
+ r = -1;
+ else if(r > 0)
+ break;
+ }
+ }
+ }
+#endif /* stream_peek */
+
+ if(ntry == 1)
+ break;
+
+ /* poll or select to see if data is present. */
+ while(tm >= 0 || action > 0 ||
+ /* block until there is data before peeking again */
+ ((t&STREAM_PEEK) && rc >= 0) ||
+ /* let select be interrupted instead of recv which autoresumes */
+ (t&SOCKET_PEEK) )
+ { r = -2;
+#if _lib_poll
+ if(r == -2)
+ {
+ struct pollfd po;
+ po.fd = fd;
+ po.events = POLLIN;
+ po.revents = 0;
+
+ if((r = SFPOLL(&po,1,tm)) < 0)
+ { if(errno == EINTR)
+ return -1;
+ else if(errno == EAGAIN)
+ { errno = 0;
+ continue;
+ }
+ else r = -2;
+ }
+ else r = (po.revents&POLLIN) ? 1 : -1;
+ }
+#endif /*_lib_poll*/
+#if _lib_select
+ if(r == -2)
+ {
+#if _hpux_threads && vt_threaded
+#define fd_set int
+#endif
+ fd_set rd;
+ struct timeval tmb, *tmp;
+ FD_ZERO(&rd);
+ FD_SET(fd,&rd);
+ if(tm < 0)
+ tmp = NIL(struct timeval*);
+ else
+ { tmp = &tmb;
+ tmb.tv_sec = tm/SECOND;
+ tmb.tv_usec = (tm%SECOND)*SECOND;
+ }
+ r = select(fd+1,&rd,NIL(fd_set*),NIL(fd_set*),tmp);
+ if(r < 0)
+ { if(errno == EINTR)
+ return -1;
+ else if(errno == EAGAIN)
+ { errno = 0;
+ continue;
+ }
+ else r = -2;
+ }
+ else r = FD_ISSET(fd,&rd) ? 1 : -1;
+ }
+#endif /*_lib_select*/
+ if(r == -2)
+ {
+#if !_lib_poll && !_lib_select /* both poll and select can't be used */
+#ifdef FIONREAD /* quick and dirty check for availability */
+ long nsec = tm < 0 ? 0 : (tm+999)/1000;
+ while(nsec > 0 && r < 0)
+ { long avail = -1;
+ if((r = ioctl(fd,FIONREAD,&avail)) < 0)
+ { if(errno == EINTR)
+ return -1;
+ else if(errno == EAGAIN)
+ { errno = 0;
+ continue;
+ }
+ else /* ioctl failed completely */
+ { r = -2;
+ break;
+ }
+ }
+ else r = avail <= 0 ? -1 : (ssize_t)avail;
+
+ if(r < 0 && nsec-- > 0)
+ sleep(1);
+ }
+#endif
+#endif
+ }
+
+ if(r > 0) /* there is data now */
+ { if(action <= 0 && rc < 0)
+ return sysreadf(fd,buf,n);
+ else r = -1;
+ }
+ else if(tm >= 0) /* timeout exceeded */
+ return -1;
+ else r = -1;
+ break;
+ }
+
+#if _socket_peek
+ if(t&SOCKET_PEEK)
+ {
+#if __MACH__ && __APPLE__ /* check 10.4 recv(MSG_PEEK) bug that consumes pipe data */
+ static int recv_peek_pipe;
+ if (recv_peek_pipe == 0) /* this will be done just once */
+ { int fds[2], r;
+ char tst[2];
+
+ tst[0] = 'a'; tst[1] = 'z';
+
+ /* open a pipe and write to it */
+ recv_peek_pipe = 1;
+ if(recv_peek_pipe == 1 && pipe(fds) < 0)
+ recv_peek_pipe = -1;
+ if(recv_peek_pipe == 1 && write(fds[1], tst, 2) != 2)
+ recv_peek_pipe = -1;
+
+ /* try recv() to see if it gets anything */
+ tst[0] = tst[1] = 0;
+ if(recv_peek_pipe == 1 && (r = recv(fds[0], tst, 1, MSG_PEEK)) != 1)
+ recv_peek_pipe = -1;
+ if(recv_peek_pipe == 1 && tst[0] != 'a')
+ recv_peek_pipe = -1;
+
+ /* make sure that recv() did not consume data */
+ tst[0] = tst[1] = 0;
+ if(recv_peek_pipe == 1 && (r = recv(fds[0], tst, 2, MSG_PEEK)) != 2)
+ recv_peek_pipe = -1;
+ if(recv_peek_pipe == 1 && (tst[0] != 'a' || tst[1] != 'z') )
+ recv_peek_pipe = -1;
+
+ close(fds[0]);
+ close(fds[1]);
+ }
+
+ if(recv_peek_pipe < 0)
+ { struct stat st; /* recv should work on sockets */
+ if(fstat(fd, &st) < 0 || !S_ISSOCK(st.st_mode) )
+ { r = -1;
+ t &= ~SOCKET_PEEK;
+ }
+ }
+#endif
+ while((t&SOCKET_PEEK) && (r = recv(fd,(char*)buf,n,MSG_PEEK)) < 0)
+ { if(errno == EINTR)
+ return -1;
+ else if(errno == EAGAIN)
+ errno = 0;
+ else t &= ~SOCKET_PEEK;
+ }
+ if(r >= 0)
+ { t &= ~STREAM_PEEK;
+ if(r > 0)
+ break;
+ else /* read past eof */
+ { if(action <= 0)
+ r = sysreadf(fd,buf,1);
+ return r;
+ }
+ }
+ }
+#endif
+ }
+
+ if(r < 0)
+ { if(tm >= 0 || action > 0)
+ return -1;
+ else /* get here means: tm < 0 && action <= 0 && rc >= 0 */
+ { /* number of records read at a time */
+ if((action = action ? -action : 1) > (int)n)
+ action = n;
+ r = 0;
+ while((t = sysreadf(fd,buf,action)) > 0)
+ { r += t;
+ for(endbuf = buf+t; buf < endbuf;)
+ if(*buf++ == rc)
+ action -= 1;
+ if(action == 0 || (int)(n-r) < action)
+ break;
+ }
+ return r == 0 ? t : r;
+ }
+ }
+
+ /* successful peek, find the record end */
+ if(rc >= 0)
+ { reg char* sp;
+
+ t = action == 0 ? 1 : action < 0 ? -action : action;
+ for(endbuf = (sp = buf)+r; sp < endbuf; )
+ if(*sp++ == rc)
+ if((t -= 1) == 0)
+ break;
+ r = sp - buf;
+ }
+
+ /* advance */
+ if(action <= 0)
+ r = sysreadf(fd,buf,r);
+
+ return r;
+}
diff --git a/src/lib/libast/sfio/sfpoll.c b/src/lib/libast/sfio/sfpoll.c
new file mode 100644
index 0000000..09110aa
--- /dev/null
+++ b/src/lib/libast/sfio/sfpoll.c
@@ -0,0 +1,250 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Poll a set of streams to see if any is available for I/O.
+** Ready streams are moved to front of array but retain the
+** same relative order.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfpoll(Sfio_t** fa, reg int n, int tm)
+#else
+int sfpoll(fa, n, tm)
+Sfio_t** fa; /* array of streams to poll */
+reg int n; /* number of streams in array */
+int tm; /* time in millisecs for select/poll */
+#endif
+{
+ reg int r, c, m, np, eintr;
+ reg Sfio_t* f;
+ reg int *status, *check;
+
+ if(n <= 0 || !fa)
+ return -1;
+
+ if(!(status = (int*)malloc(2*n*sizeof(int))) )
+ return -1;
+ check = status+n; /* streams that need polling */
+
+ /* a SF_READ stream is ready if there is buffered read data */
+#define RDREADY(f) (((f->mode&SF_READ) && f->next < f->endb) || \
+ ((f->mode&SF_WRITE) && f->proc && f->proc->ndata > 0) )
+
+ /* a SF_WRITE stream is ready if there is no write data */
+#define WRREADY(f) (!(f->mode&SF_WRITE) || f->next == f->data)
+
+#define HASAUXFD(f) (f->proc && f->proc->file >= 0 && f->proc->file != f->file)
+
+ for(r = c = eintr = 0; r < n; ++r) /* compute streams that must be checked */
+ { f = fa[r];
+ status[r] = 0;
+
+ /* terminate poll on interrupt? */
+ if(f->flags&SF_IOINTR)
+ eintr++;
+ /* check accessibility */
+ m = f->mode&SF_RDWR;
+ if((int)f->mode != m && _sfmode(f,m,0) < 0)
+ continue;
+
+ if((f->flags&SF_READ) && RDREADY(f))
+ status[r] |= SF_READ;
+
+ if((f->flags&SF_WRITE) && WRREADY(f))
+ status[r] |= SF_WRITE;
+
+ if((f->flags&SF_RDWR) == status[r])
+ continue;
+
+ /* has discipline, ask its opinion */
+ if(f->disc && f->disc->exceptf)
+ { if((m = (*f->disc->exceptf)(f,SF_DPOLL,&tm,f->disc)) < 0)
+ continue;
+ else if(m > 0)
+ { status[r] = m&SF_RDWR;
+ continue;
+ }
+ }
+
+ if(f->extent < 0) /* unseekable stream, must poll/select */
+ check[c++] = r;
+ else /* seekable streams are always ready */
+ { if(f->flags&SF_READ)
+ status[r] |= SF_READ;
+ if(f->flags&SF_WRITE)
+ status[r] |= SF_WRITE;
+ }
+ }
+ /* terminate poll on interrupt only if all streams marked SF_IOINTR */
+ eintr = eintr == n ? -1 : EINTR;
+
+ np = -1;
+#if _lib_poll
+ if(c > 0)
+ { struct pollfd* fds;
+
+ /* construct the poll array */
+ for(m = 0, r = 0; r < c; ++r, ++m)
+ { f = fa[check[r]];
+ if(HASAUXFD(f))
+ m += 1;
+ }
+ if(!(fds = (struct pollfd*)malloc(m*sizeof(struct pollfd))) )
+ return -1;
+
+ for(m = 0, r = 0; r < c; ++r, ++m)
+ { f = fa[check[r]];
+
+ fds[m].fd = f->file;
+ fds[m].events = fds[m].revents = 0;
+
+ if((f->flags&SF_WRITE) && !WRREADY(f) )
+ fds[m].events |= POLLOUT;
+
+ if((f->flags&SF_READ) && !RDREADY(f) )
+ { /* a sfpopen situation with two file descriptors */
+ if((f->mode&SF_WRITE) && HASAUXFD(f))
+ { m += 1;
+ fds[m].fd = f->proc->file;
+ fds[m].revents = 0;
+ }
+
+ fds[m].events |= POLLIN;
+ }
+ }
+
+ while((np = SFPOLL(fds,m,tm)) < 0 )
+ { if(errno == eintr || errno == EAGAIN)
+ errno = 0;
+ else break;
+ }
+ if(np > 0) /* poll succeeded */
+ np = c;
+
+ for(m = 0, r = 0; r < np; ++r, ++m)
+ { f = fa[check[r]];
+
+ if((f->flags&SF_WRITE) && !WRREADY(f) )
+ { if(fds[m].revents&POLLOUT)
+ status[check[r]] |= SF_WRITE;
+ }
+
+ if((f->flags&SF_READ) && !RDREADY(f))
+ { if((f->mode&SF_WRITE) && HASAUXFD(f))
+ m += 1;
+ if(fds[m].revents&POLLIN)
+ status[check[r]] |= SF_READ;
+ }
+ }
+
+ free((Void_t*)fds);
+ }
+#endif /*_lib_poll*/
+
+#if _lib_select
+ if(np < 0 && c > 0)
+ { fd_set rd, wr;
+ struct timeval tmb, *tmp;
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wr);
+ m = 0;
+ for(r = 0; r < c; ++r)
+ { f = fa[check[r]];
+
+ if(f->file > m)
+ m = f->file;
+
+ if((f->flags&SF_WRITE) && !WRREADY(f))
+ FD_SET(f->file,&wr);
+
+ if((f->flags&SF_READ) && !RDREADY(f))
+ { if((f->mode&SF_WRITE) && HASAUXFD(f))
+ { if(f->proc->file > m)
+ m = f->proc->file;
+ FD_SET(f->proc->file, &rd);
+ }
+ else FD_SET(f->file,&rd);
+ }
+ }
+ if(tm < 0)
+ tmp = NIL(struct timeval*);
+ else
+ { tmp = &tmb;
+ tmb.tv_sec = tm/SECOND;
+ tmb.tv_usec = (tm%SECOND)*SECOND;
+ }
+
+ while((np = select(m+1,&rd,&wr,NIL(fd_set*),tmp)) < 0 )
+ { if(errno == eintr)
+ errno = 0;
+ else break;
+ }
+ if(np > 0)
+ np = c;
+
+ for(r = 0; r < np; ++r)
+ { f = fa[check[r]];
+
+ if((f->flags&SF_WRITE) && !WRREADY(f) )
+ { if(FD_ISSET(f->file,&wr) )
+ status[check[r]] |= SF_WRITE;
+ }
+
+ if((f->flags&SF_READ) && !RDREADY(f) )
+ { if((f->mode&SF_WRITE) && HASAUXFD(f) )
+ { if(FD_ISSET(f->proc->file, &rd) )
+ status[check[r]] |= SF_READ;
+ }
+ else
+ { if(FD_ISSET(f->file,&rd) )
+ status[check[r]] |= SF_READ;
+ }
+ }
+ }
+ }
+#endif /*_lib_select*/
+
+ for(r = c = 0; c < n; ++c)
+ { if(status[c] == 0)
+ continue;
+
+ f = fa[c];
+ f->val = (ssize_t)status[c];
+
+ /* announce status */
+ if(f->disc && f->disc->exceptf)
+ (*f->disc->exceptf)(f,SF_READY,(Void_t*)(long)status[c],f->disc);
+
+ if(c > r) /* move to front of list */
+ { fa[c] = fa[r];
+ fa[r] = f;
+ }
+ r += 1;
+ }
+
+ free((Void_t*)status);
+ return r ? r : np < 0 ? -1 : 0;
+}
diff --git a/src/lib/libast/sfio/sfpool.c b/src/lib/libast/sfio/sfpool.c
new file mode 100644
index 0000000..dbfc045
--- /dev/null
+++ b/src/lib/libast/sfio/sfpool.c
@@ -0,0 +1,369 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Management of pools of streams.
+** If pf is not nil, f is pooled with pf and f becomes current;
+** otherwise, f is isolated from its pool. flag can be one of
+** 0 or SF_SHARE.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+/* Note that we do not free the space for a pool once it is allocated.
+** This is to prevent memory faults in calls such as sfsync(NULL) that walk the pool
+** link list and during such walks may free up streams&pools. Free pools will be
+** reused in newpool().
+*/
+#if __STD_C
+static int delpool(reg Sfpool_t* p)
+#else
+static int delpool(p)
+reg Sfpool_t* p;
+#endif
+{
+ POOLMTXENTER(p);
+
+ if(p->s_sf && p->sf != p->array)
+ free((Void_t*)p->sf);
+ p->mode = SF_AVAIL;
+
+ POOLMTXRETURN(p,0);
+}
+
+#if __STD_C
+static Sfpool_t* newpool(reg int mode)
+#else
+static Sfpool_t* newpool(mode)
+reg int mode;
+#endif
+{
+ reg Sfpool_t *p, *last = &_Sfpool;
+
+ /* look to see if there is a free pool */
+ for(last = &_Sfpool, p = last->next; p; last = p, p = p->next)
+ { if(p->mode == SF_AVAIL )
+ { p->mode = 0;
+ break;
+ }
+ }
+
+ if(!p)
+ { POOLMTXLOCK(last);
+
+ if(!(p = (Sfpool_t*) malloc(sizeof(Sfpool_t))) )
+ { POOLMTXUNLOCK(last);
+ return NIL(Sfpool_t*);
+ }
+
+ (void)vtmtxopen(&p->mutex, VT_INIT); /* initialize mutex */
+
+ p->mode = 0;
+ p->n_sf = 0;
+ p->next = NIL(Sfpool_t*);
+ last->next = p;
+
+ POOLMTXUNLOCK(last);
+ }
+
+ POOLMTXENTER(p);
+
+ p->mode = mode&SF_SHARE;
+ p->s_sf = sizeof(p->array)/sizeof(p->array[0]);
+ p->sf = p->array;
+
+ POOLMTXRETURN(p,p);
+}
+
+/* move a stream to head */
+#if __STD_C
+static int _sfphead(Sfpool_t* p, Sfio_t* f, int n)
+#else
+static int _sfphead(p, f, n)
+Sfpool_t* p; /* the pool */
+Sfio_t* f; /* the stream */
+int n; /* current position in pool */
+#endif
+{
+ reg Sfio_t* head;
+ reg ssize_t k, w, v;
+ reg int rv;
+
+ POOLMTXENTER(p);
+
+ if(n == 0)
+ POOLMTXRETURN(p,0);
+
+ head = p->sf[0];
+ if(SFFROZEN(head) )
+ POOLMTXRETURN(p,-1);
+
+ SFLOCK(head,0);
+ rv = -1;
+
+ if(!(p->mode&SF_SHARE) || (head->mode&SF_READ) || (f->mode&SF_READ) )
+ { if(SFSYNC(head) < 0)
+ goto done;
+ }
+ else /* shared pool of write-streams, data can be moved among streams */
+ { if(SFMODE(head,1) != SF_WRITE && _sfmode(head,SF_WRITE,1) < 0)
+ goto done;
+ /**/ASSERT(f->next == f->data);
+
+ v = head->next - head->data; /* pending data */
+ if((k = v - (f->endb-f->data)) <= 0)
+ k = 0;
+ else /* try to write out amount exceeding f's capacity */
+ { if((w = SFWR(head,head->data,k,head->disc)) == k)
+ v -= k;
+ else /* write failed, recover buffer then quit */
+ { if(w > 0)
+ { v -= w;
+ memcpy(head->data,(head->data+w),v);
+ }
+ head->next = head->data+v;
+ goto done;
+ }
+ }
+
+ /* move data from head to f */
+ if((head->data+k) != f->data )
+ memcpy(f->data,(head->data+k),v);
+ f->next = f->data+v;
+ }
+
+ f->mode &= ~SF_POOL;
+ head->mode |= SF_POOL;
+ head->next = head->endr = head->endw = head->data; /* clear write buffer */
+
+ p->sf[n] = head;
+ p->sf[0] = f;
+ rv = 0;
+
+done:
+ head->mode &= ~SF_LOCK; /* partially unlock because it's no longer head */
+
+ POOLMTXRETURN(p,rv);
+}
+
+/* delete a stream from its pool */
+#if __STD_C
+static int _sfpdelete(Sfpool_t* p, Sfio_t* f, int n)
+#else
+static int _sfpdelete(p, f, n)
+Sfpool_t* p; /* the pool */
+Sfio_t* f; /* the stream */
+int n; /* position in pool */
+#endif
+{
+ POOLMTXENTER(p);
+
+ p->n_sf -= 1;
+ for(; n < p->n_sf; ++n)
+ p->sf[n] = p->sf[n+1];
+
+ f->pool = NIL(Sfpool_t*);
+ f->mode &= ~SF_POOL;
+
+ if(p->n_sf == 0 || p == &_Sfpool)
+ { if(p != &_Sfpool)
+ delpool(p);
+ goto done;
+ }
+
+ /* !_Sfpool, make sure head stream is an open stream */
+ for(n = 0; n < p->n_sf; ++n)
+ if(!SFFROZEN(p->sf[n]))
+ break;
+ if(n < p->n_sf && n > 0)
+ { f = p->sf[n];
+ p->sf[n] = p->sf[0];
+ p->sf[0] = f;
+ }
+
+ /* head stream has SF_POOL off */
+ f = p->sf[0];
+ f->mode &= ~SF_POOL;
+ if(!SFFROZEN(f))
+ _SFOPEN(f);
+
+ /* if only one stream left, delete pool */
+ if(p->n_sf == 1 )
+ { _sfpdelete(p,f,0);
+ _sfsetpool(f);
+ }
+
+done:
+ POOLMTXRETURN(p,0);
+}
+
+#if __STD_C
+static int _sfpmove(reg Sfio_t* f, reg int type)
+#else
+static int _sfpmove(f,type)
+reg Sfio_t* f;
+reg int type; /* <0 : deleting, 0: move-to-front, >0: inserting */
+#endif
+{
+ reg Sfpool_t* p;
+ reg int n;
+
+ if(type > 0)
+ return _sfsetpool(f);
+ else
+ { if(!(p = f->pool) )
+ return -1;
+ for(n = p->n_sf-1; n >= 0; --n)
+ if(p->sf[n] == f)
+ break;
+ if(n < 0)
+ return -1;
+
+ return type == 0 ? _sfphead(p,f,n) : _sfpdelete(p,f,n);
+ }
+}
+
+#if __STD_C
+Sfio_t* sfpool(reg Sfio_t* f, reg Sfio_t* pf, reg int mode)
+#else
+Sfio_t* sfpool(f,pf,mode)
+reg Sfio_t* f;
+reg Sfio_t* pf;
+reg int mode;
+#endif
+{
+ int k;
+ Sfpool_t* p;
+ Sfio_t* rv;
+
+ _Sfpmove = _sfpmove;
+
+ if(!f) /* return head of pool of pf regardless of lock states */
+ { if(!pf)
+ return NIL(Sfio_t*);
+ else if(!pf->pool || pf->pool == &_Sfpool)
+ return pf;
+ else return pf->pool->sf[0];
+ }
+
+ if(f) /* check for permissions */
+ { SFMTXLOCK(f);
+ if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
+ { SFMTXUNLOCK(f);
+ return NIL(Sfio_t*);
+ }
+ if(f->disc == _Sfudisc)
+ (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*)));
+ }
+ if(pf)
+ { SFMTXLOCK(pf);
+ if((pf->mode&SF_RDWR) != pf->mode && _sfmode(pf,0,0) < 0)
+ { if(f)
+ SFMTXUNLOCK(f);
+ SFMTXUNLOCK(pf);
+ return NIL(Sfio_t*);
+ }
+ if(pf->disc == _Sfudisc)
+ (void)sfclose((*_Sfstack)(pf,NIL(Sfio_t*)));
+ }
+
+ /* f already in the same pool with pf */
+ if(f == pf || (pf && f->pool == pf->pool && f->pool != &_Sfpool) )
+ { if(f)
+ SFMTXUNLOCK(f);
+ if(pf)
+ SFMTXUNLOCK(pf);
+ return pf;
+ }
+
+ /* lock streams before internal manipulations */
+ rv = NIL(Sfio_t*);
+ SFLOCK(f,0);
+ if(pf)
+ SFLOCK(pf,0);
+
+ if(!pf) /* deleting f from its current pool */
+ { if((p = f->pool) != NIL(Sfpool_t*) && p != &_Sfpool)
+ for(k = 0; k < p->n_sf && pf == NIL(Sfio_t*); ++k)
+ if(p->sf[k] != f) /* a stream != f represents the pool */
+ pf = p->sf[k];
+ if(!pf) /* already isolated */
+ { rv = f; /* just return self */
+ goto done;
+ }
+
+ if(_sfpmove(f,-1) < 0 || _sfsetpool(f) < 0)
+ goto done; /* can't delete */
+
+ if(!pf->pool || pf->pool == &_Sfpool || pf->pool->n_sf <= 0 )
+ rv = pf;
+ else rv = pf->pool->sf[0]; /* return head of old pool */
+ goto done;
+ }
+
+ if(pf->pool && pf->pool != &_Sfpool) /* always use current mode */
+ mode = pf->pool->mode;
+
+ if(mode&SF_SHARE) /* can only have write streams */
+ { if(SFMODE(f,1) != SF_WRITE && _sfmode(f,SF_WRITE,1) < 0)
+ goto done;
+ if(SFMODE(pf,1) != SF_WRITE && _sfmode(pf,SF_WRITE,1) < 0)
+ goto done;
+ if(f->next > f->data && SFSYNC(f) < 0) /* start f clean */
+ goto done;
+ }
+
+ if(_sfpmove(f,-1) < 0) /* isolate f from current pool */
+ goto done;
+
+ if(!(p = pf->pool) || p == &_Sfpool) /* making a new pool */
+ { if(!(p = newpool(mode)) )
+ goto done;
+ if(_sfpmove(pf,-1) < 0) /* isolate pf from its current pool */
+ goto done;
+ pf->pool = p;
+ p->sf[0] = pf;
+ p->n_sf += 1;
+ }
+
+ f->pool = p; /* add f to pf's pool */
+ if(_sfsetpool(f) < 0)
+ goto done;
+
+ /**/ASSERT(p->sf[0] == pf && p->sf[p->n_sf-1] == f);
+ SFOPEN(pf,0);
+ SFOPEN(f,0);
+ if(_sfpmove(f,0) < 0) /* make f head of pool */
+ goto done;
+ rv = pf;
+
+done:
+ if(f)
+ { SFOPEN(f,0);
+ SFMTXUNLOCK(f);
+ }
+ if(pf)
+ { SFOPEN(pf,0);
+ SFMTXUNLOCK(pf);
+ }
+ return rv;
+}
diff --git a/src/lib/libast/sfio/sfpopen.c b/src/lib/libast/sfio/sfpopen.c
new file mode 100644
index 0000000..ed3ea7f
--- /dev/null
+++ b/src/lib/libast/sfio/sfpopen.c
@@ -0,0 +1,293 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Create a coprocess.
+** Written by Kiem-Phong Vo.
+*/
+
+#if _PACKAGE_ast
+#include <proc.h>
+#else
+
+#define EXIT_NOTFOUND 127
+
+#define READ 0
+#define WRITE 1
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+static char Meta[1<<CHAR_BIT], **Path;
+
+/* execute command directly if possible; else use the shell */
+#if __STD_C
+static void execute(const char* argcmd)
+#else
+static void execute(argcmd)
+char* argcmd;
+#endif
+{
+ reg char *s, *cmd, **argv, **p, *interp;
+ reg int n;
+
+ /* define interpreter */
+ if(!(interp = getenv("SHELL")) || !interp[0])
+ interp = "/bin/sh";
+
+ if(strcmp(interp,"/bin/sh") != 0 && strcmp(interp,"/bin/ksh") != 0 )
+ { if(access(interp,X_OK) == 0)
+ goto do_interp;
+ else interp = "/bin/sh";
+ }
+
+ /* if there is a meta character, let the shell do it */
+ for(s = (char*)argcmd; *s; ++s)
+ if(Meta[(uchar)s[0]])
+ goto do_interp;
+
+ /* try to construct argv */
+ if(!(cmd = (char*)malloc(strlen(argcmd)+1)) )
+ goto do_interp;
+ strcpy(cmd,argcmd);
+ if(!(argv = (char**)malloc(16*sizeof(char*))) )
+ goto do_interp;
+ for(n = 0, s = cmd;; )
+ { while(isspace(s[0]))
+ s += 1;
+ if(s[0] == 0)
+ break;
+
+ /* new argument */
+ argv[n++] = s;
+ if((n%16) == 0 && !(argv = (char**)realloc(argv,(n+16)*sizeof(char*))) )
+ goto do_interp;
+
+ /* make this into a C string */
+ while(s[0] && !isspace(s[0]))
+ s += 1;
+ if(!s[0])
+ *s++ = 0;
+ }
+ if(n == 0)
+ goto do_interp;
+ argv[n] = NIL(char*);
+
+ /* get the command name */
+ cmd = argv[0];
+ for(s = cmd+strlen(cmd)-1; s >= cmd; --s)
+ if(*s == '/')
+ break;
+ argv[0] = s+1;
+
+ /* Non-standard pathnames as in nDFS should be handled by the shell */
+ for(s = cmd+strlen(cmd)-1; s >= cmd+2; --s)
+ if(s[0] == '.' && s[-1] == '.' && s[-2] == '.')
+ goto do_interp;
+
+ if(cmd[0] == '/' ||
+ (cmd[0] == '.' && cmd[1] == '/') ||
+ (cmd[0] == '.' && cmd[1] == '.' && cmd[2] == '/') )
+ { if(access(cmd,X_OK) != 0)
+ goto do_interp;
+ else execv(cmd,argv);
+ }
+ else
+ { for(p = Path; *p; ++p)
+ { s = sfprints("%s/%s", *p, cmd);
+ if(access(s,X_OK) == 0)
+ execv(s,argv);
+ }
+ }
+
+ /* if get here, let the interpreter do it */
+do_interp:
+ for(s = interp+strlen(interp)-1; s >= interp; --s)
+ if(*s == '/')
+ break;
+ execl(interp, s+1, "-c", argcmd, NIL(char*));
+ _exit(EXIT_NOTFOUND);
+}
+
+#endif /*_PACKAGE_ast*/
+
+#if __STD_C
+Sfio_t* sfpopen(Sfio_t* f, const char* command, const char* mode)
+#else
+Sfio_t* sfpopen(f,command,mode)
+Sfio_t* f;
+char* command; /* command to execute */
+char* mode; /* mode of the stream */
+#endif
+{
+#if _PACKAGE_ast
+ reg Proc_t* proc;
+ reg int sflags;
+ reg long flags;
+ reg int pflags;
+ char* av[4];
+
+ if (!command || !command[0] || !mode)
+ return 0;
+ sflags = _sftype(mode, NiL, NiL);
+
+ if(f == (Sfio_t*)(-1))
+ { /* stdio compatibility mode */
+ f = NIL(Sfio_t*);
+ pflags = 1;
+ }
+ else pflags = 0;
+
+ flags = 0;
+ if (sflags & SF_READ)
+ flags |= PROC_READ;
+ if (sflags & SF_WRITE)
+ flags |= PROC_WRITE;
+ av[0] = "sh";
+ av[1] = "-c";
+ av[2] = (char*)command;
+ av[3] = 0;
+ if (!(proc = procopen(0, av, 0, 0, flags)))
+ return 0;
+ if (!(f = sfnew(f, NIL(Void_t*), (size_t)SF_UNBOUND,
+ (sflags&SF_READ) ? proc->rfd : proc->wfd, sflags|((sflags&SF_RDWR)?0:SF_READ))) ||
+ _sfpopen(f, (sflags&SF_READ) ? proc->wfd : -1, proc->pid, pflags) < 0)
+ {
+ if (f) sfclose(f);
+ procclose(proc);
+ return 0;
+ }
+ procfree(proc);
+ return f;
+#else
+ reg int pid, fd, pkeep, ckeep, sflags;
+ int stdio, parent[2], child[2];
+ Sfio_t sf;
+
+ /* set shell meta characters */
+ if(Meta[0] == 0)
+ { reg char* s;
+ Meta[0] = 1;
+ for(s = "!@#$%&*(){}[]:;<>~`'|\"\\"; *s; ++s)
+ Meta[(uchar)s[0]] = 1;
+ }
+ if(!Path)
+ Path = _sfgetpath("PATH");
+
+ /* sanity check */
+ if(!command || !command[0] || !mode)
+ return NIL(Sfio_t*);
+ sflags = _sftype(mode,NIL(int*),NIL(int*));
+
+ /* make pipes */
+ parent[0] = parent[1] = child[0] = child[1] = -1;
+ if(sflags&SF_RDWR)
+ { if(syspipef(parent) < 0)
+ goto error;
+ if((sflags&SF_RDWR) == SF_RDWR && syspipef(child) < 0)
+ goto error;
+ }
+
+ switch((pid = fork()) )
+ {
+ default : /* in parent process */
+ if(sflags&SF_READ)
+ { pkeep = READ; ckeep = WRITE; }
+ else { pkeep = WRITE; ckeep = READ; }
+
+ if(f == (Sfio_t*)(-1))
+ { /* stdio compatibility mode */
+ f = NIL(Sfio_t*);
+ stdio = 1;
+ }
+ else stdio = 0;
+
+ /* make the streams */
+ if(!(f = sfnew(f,NIL(Void_t*),(size_t)SF_UNBOUND,parent[pkeep],sflags|((sflags&SF_RDWR)?0:SF_READ))))
+ goto error;
+ if(sflags&SF_RDWR)
+ { CLOSE(parent[!pkeep]);
+ SETCLOEXEC(parent[pkeep]);
+ if((sflags&SF_RDWR) == SF_RDWR)
+ { CLOSE(child[!ckeep]);
+ SETCLOEXEC(child[ckeep]);
+ }
+ }
+
+ /* save process info */
+ fd = (sflags&SF_RDWR) == SF_RDWR ? child[ckeep] : -1;
+ if(_sfpopen(f,fd,pid,stdio) < 0)
+ { (void)sfclose(f);
+ goto error;
+ }
+
+ return f;
+
+ case 0 : /* in child process */
+ /* determine what to keep */
+ if(sflags&SF_READ)
+ { pkeep = WRITE; ckeep = READ; }
+ else { pkeep = READ; ckeep = WRITE; }
+
+ /* zap fd that we don't need */
+ if(sflags&SF_RDWR)
+ { CLOSE(parent[!pkeep]);
+ if((sflags&SF_RDWR) == SF_RDWR)
+ CLOSE(child[!ckeep]);
+ }
+
+ /* use sfsetfd to make these descriptors the std-ones */
+ SFCLEAR(&sf,NIL(Vtmutex_t*));
+
+ /* must be careful so not to close something useful */
+ if((sflags&SF_RDWR) == SF_RDWR && pkeep == child[ckeep])
+ if((child[ckeep] = sysdupf(pkeep)) < 0)
+ _exit(EXIT_NOTFOUND);
+
+ if(sflags&SF_RDWR)
+ { if (parent[pkeep] != pkeep)
+ { sf.file = parent[pkeep];
+ CLOSE(pkeep);
+ if(sfsetfd(&sf,pkeep) != pkeep)
+ _exit(EXIT_NOTFOUND);
+ }
+ if((sflags&SF_RDWR) == SF_RDWR && child[ckeep] != ckeep)
+ { sf.file = child[ckeep];
+ CLOSE(ckeep);
+ if(sfsetfd(&sf,ckeep) != ckeep)
+ _exit(EXIT_NOTFOUND);
+ }
+ }
+
+ execute(command);
+ return NIL(Sfio_t*);
+
+ case -1 : /* error */
+ error:
+ if(parent[0] >= 0)
+ { CLOSE(parent[0]); CLOSE(parent[1]); }
+ if(child[0] >= 0)
+ { CLOSE(child[0]); CLOSE(child[1]); }
+ return NIL(Sfio_t*);
+ }
+#endif /*_PACKAGE_ast*/
+}
diff --git a/src/lib/libast/sfio/sfprintf.c b/src/lib/libast/sfio/sfprintf.c
new file mode 100644
index 0000000..50b0804
--- /dev/null
+++ b/src/lib/libast/sfio/sfprintf.c
@@ -0,0 +1,114 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Print data with a given format
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfprintf(Sfio_t* f, const char* form, ...)
+#else
+int sfprintf(va_alist)
+va_dcl
+#endif
+{
+ va_list args;
+ reg int rv;
+
+#if __STD_C
+ va_start(args,form);
+#else
+ reg Sfio_t* f;
+ reg char* form;
+ va_start(args);
+ f = va_arg(args,Sfio_t*);
+ form = va_arg(args,char*);
+#endif
+ rv = sfvprintf(f,form,args);
+
+ va_end(args);
+ return rv;
+}
+
+#if __STD_C
+ssize_t sfvsprintf(char* s, size_t n, const char* form, va_list args)
+#else
+ssize_t sfvsprintf(s, n, form, args)
+char* s;
+size_t n;
+char* form;
+va_list args;
+#endif
+{
+ Sfio_t *f;
+ ssize_t rv;
+
+ /* make a temp stream */
+ if(!(f = sfnew(NIL(Sfio_t*),NIL(char*),(size_t)SF_UNBOUND,
+ -1,SF_WRITE|SF_STRING)) )
+ return -1;
+
+ if((rv = sfvprintf(f,form,args)) >= 0 && s && n > 0)
+ { if((rv+1) >= n)
+ n--;
+ else
+ n = rv;
+ memcpy(s, f->data, n);
+ s[n] = 0;
+ }
+
+ sfclose(f);
+
+ _Sfi = rv;
+
+ return rv;
+}
+
+#if __STD_C
+ssize_t sfsprintf(char* s, size_t n, const char* form, ...)
+#else
+ssize_t sfsprintf(va_alist)
+va_dcl
+#endif
+{
+ va_list args;
+ ssize_t rv;
+
+#if __STD_C
+ va_start(args,form);
+#else
+ reg char* s;
+ reg size_t n;
+ reg char* form;
+ va_start(args);
+ s = va_arg(args,char*);
+ n = va_arg(args,size_t);
+ form = va_arg(args,char*);
+#endif
+
+ rv = sfvsprintf(s,n,form,args);
+ va_end(args);
+
+ return rv;
+}
diff --git a/src/lib/libast/sfio/sfprints.c b/src/lib/libast/sfio/sfprints.c
new file mode 100644
index 0000000..d69cc34
--- /dev/null
+++ b/src/lib/libast/sfio/sfprints.c
@@ -0,0 +1,125 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Construct a string with the given format and data.
+** These functions allocate space as necessary to store the string.
+** This avoids overflow problems typical with sprintf() in stdio.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+char* sfvprints(const char* form, va_list args)
+#else
+char* sfvprints(form, args)
+char* form;
+va_list args;
+#endif
+{
+ reg int rv;
+ static Sfio_t* f;
+
+ /* make a fake stream */
+ if(!f &&
+ !(f = sfnew(NIL(Sfio_t*),NIL(char*),(size_t)SF_UNBOUND,
+ -1,SF_WRITE|SF_STRING)) )
+ return NIL(char*);
+
+ sfseek(f,(Sfoff_t)0,SEEK_SET);
+ rv = sfvprintf(f,form,args);
+
+ if(rv < 0 || sfputc(f,'\0') < 0)
+ return NIL(char*);
+
+ _Sfi = (f->next - f->data) - 1;
+ return (char*)f->data;
+}
+
+#if __STD_C
+char* sfprints(const char* form, ...)
+#else
+char* sfprints(va_alist)
+va_dcl
+#endif
+{
+ char* s;
+ va_list args;
+
+#if __STD_C
+ va_start(args,form);
+#else
+ char *form;
+ va_start(args);
+ form = va_arg(args,char*);
+#endif
+ s = sfvprints(form, args);
+ va_end(args);
+
+ return s;
+}
+
+#if __STD_C
+ssize_t sfvaprints(char** sp, const char* form, va_list args)
+#else
+ssize_t sfvaprints(sp, form, args)
+char** sp;
+char* form;
+va_list args;
+#endif
+{
+ char *s;
+ ssize_t n;
+
+ if(!sp || !(s = sfvprints(form,args)) )
+ return -1;
+ else
+ { if(!(*sp = (char*)malloc(n = strlen(s)+1)) )
+ return -1;
+ memcpy(*sp, s, n);
+ return n-1;
+ }
+}
+
+#if __STD_C
+ssize_t sfaprints(char** sp, const char* form, ...)
+#else
+ssize_t sfaprints(va_alist)
+va_dcl
+#endif
+{
+ ssize_t n;
+ va_list args;
+
+#if __STD_C
+ va_start(args,form);
+#else
+ char **sp, *form;
+ va_start(args);
+ sp = va_arg(args, char**);
+ form = va_arg(args, char*);
+#endif
+ n = sfvaprints(sp, form, args);
+ va_end(args);
+
+ return n;
+}
diff --git a/src/lib/libast/sfio/sfpurge.c b/src/lib/libast/sfio/sfpurge.c
new file mode 100644
index 0000000..c3b4106
--- /dev/null
+++ b/src/lib/libast/sfio/sfpurge.c
@@ -0,0 +1,98 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Delete all pending data in the buffer
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfpurge(Sfio_t* f)
+#else
+int sfpurge(f)
+Sfio_t* f;
+#endif
+{
+ reg int mode;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,-1);
+
+ if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode|SF_SYNCED,0) < 0)
+ SFMTXRETURN(f, -1);
+
+ if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
+ (void)(*f->disc->exceptf)(f,SF_PURGE,(Void_t*)((int)1),f->disc);
+
+ if(f->disc == _Sfudisc)
+ (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*)));
+
+ /* cannot purge read string streams */
+ if((f->flags&SF_STRING) && (f->mode&SF_READ) )
+ goto done;
+
+ SFLOCK(f,0);
+
+ /* if memory map must be a read stream, pretend data is gone */
+#ifdef MAP_TYPE
+ if(f->bits&SF_MMAP)
+ { f->here -= f->endb - f->next;
+ if(f->data)
+ { SFMUNMAP(f,f->data,f->endb-f->data);
+ (void)SFSK(f,f->here,SEEK_SET,f->disc);
+ }
+ SFOPEN(f,0);
+ SFMTXRETURN(f, 0);
+ }
+#endif
+
+ switch(f->mode&~SF_LOCK)
+ {
+ default :
+ SFOPEN(f,0);
+ SFMTXRETURN(f, -1);
+ case SF_WRITE :
+ f->next = f->data;
+ if(!f->proc || !(f->flags&SF_READ) || !(f->mode&SF_WRITE) )
+ break;
+
+ /* 2-way pipe, must clear read buffer */
+ (void)_sfmode(f,SF_READ,1);
+ /* fall through */
+ case SF_READ:
+ if(f->extent >= 0 && f->endb > f->next)
+ { f->here -= f->endb-f->next;
+ (void)SFSK(f,f->here,SEEK_SET,f->disc);
+ }
+ f->endb = f->next = f->data;
+ break;
+ }
+
+ SFOPEN(f,0);
+
+done:
+ if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
+ (void)(*f->disc->exceptf)(f,SF_PURGE,(Void_t*)((int)0),f->disc);
+
+ SFMTXRETURN(f, 0);
+}
diff --git a/src/lib/libast/sfio/sfputd.c b/src/lib/libast/sfio/sfputd.c
new file mode 100644
index 0000000..3129cd5
--- /dev/null
+++ b/src/lib/libast/sfio/sfputd.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfputd
+
+#if __STD_C
+int sfputd(reg Sfio_t* f, Sfdouble_t d)
+#else
+int sfputd(f,d)
+reg Sfio_t* f;
+reg Sfdouble_t d;
+#endif
+{
+ return __sf_putd(f,d);
+}
diff --git a/src/lib/libast/sfio/sfputl.c b/src/lib/libast/sfio/sfputl.c
new file mode 100644
index 0000000..ceaa6b9
--- /dev/null
+++ b/src/lib/libast/sfio/sfputl.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfputl
+
+#if __STD_C
+int sfputl(reg Sfio_t* f, Sflong_t l)
+#else
+int sfputl(f,l)
+reg Sfio_t* f;
+reg Sflong_t l;
+#endif
+{
+ return __sf_putl(f,l);
+}
diff --git a/src/lib/libast/sfio/sfputm.c b/src/lib/libast/sfio/sfputm.c
new file mode 100644
index 0000000..8082a7b
--- /dev/null
+++ b/src/lib/libast/sfio/sfputm.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfputm
+
+#if __STD_C
+int sfputm(Sfio_t* f, Sfulong_t u, Sfulong_t m)
+#else
+int sfputm(f,u,m)
+Sfio_t* f;
+Sfulong_t u;
+Sfulong_t m;
+#endif
+{
+ return __sf_putm(f, u, m);
+}
diff --git a/src/lib/libast/sfio/sfputr.c b/src/lib/libast/sfio/sfputr.c
new file mode 100644
index 0000000..21bfb0a
--- /dev/null
+++ b/src/lib/libast/sfio/sfputr.c
@@ -0,0 +1,136 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Put out a null-terminated string
+**
+** Written by Kiem-Phong Vo.
+*/
+#if __STD_C
+ssize_t sfputr(Sfio_t* f, const char* s, int rc)
+#else
+ssize_t sfputr(f,s,rc)
+Sfio_t* f; /* write to this stream */
+char* s; /* string to write */
+int rc; /* record separator. */
+#endif
+{
+ ssize_t p, n, w, sn;
+ uchar *ps;
+ char *ss;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,-1);
+
+ if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0)
+ SFMTXRETURN(f, -1);
+
+ SFLOCK(f,0);
+
+ f->val = sn = -1; ss = (char*)s;
+ for(w = 0; (*s || rc >= 0); )
+ { /* need to communicate string size to exception handler */
+ if((f->flags&SF_STRING) && f->next >= f->endb )
+ { sn = sn < 0 ? strlen(s) : (sn - (s-ss));
+ ss = (char*)s; /* save current checkpoint */
+ f->val = sn + (rc >= 0 ? 1 : 0); /* space requirement */
+ f->bits |= SF_PUTR; /* tell sfflsbuf to use f->val */
+ }
+
+ SFWPEEK(f,ps,p);
+ f->bits &= ~SF_PUTR; /* remove any trace of this */
+
+ if(p < 0 ) /* something not right about buffering */
+ break;
+
+ if(p == 0 || (f->flags&SF_WHOLE) )
+ { n = sn < 0 ? strlen(s) : sn - (s-ss);
+ if(p >= (n + (rc < 0 ? 0 : 1)) )
+ { /* buffer can hold everything */
+ if(n > 0)
+ { memcpy(ps, s, n);
+ ps += n;
+ w += n;
+ }
+ if(rc >= 0)
+ { *ps++ = rc;
+ w += 1;
+ }
+ f->next = ps;
+ }
+ else
+ { /* create a reserve buffer to hold data */
+ Sfrsrv_t* rsrv;
+
+ p = n + (rc >= 0 ? 1 : 0);
+ if(!(rsrv = _sfrsrv(f, p)) )
+ n = 0;
+ else
+ { if(n > 0)
+ memcpy(rsrv->data, s, n);
+ if(rc >= 0)
+ rsrv->data[n] = rc;
+ if((n = SFWRITE(f,rsrv->data,p)) < 0 )
+ n = 0;
+ }
+
+ w += n;
+ }
+ break;
+ }
+
+ if(*s == 0)
+ { *ps++ = rc;
+ f->next = ps;
+ w += 1;
+ break;
+ }
+
+#if _lib_memccpy && !__ia64 /* these guys may never get it right */
+ if((ps = (uchar*)memccpy(ps,s,'\0',p)) != NIL(uchar*))
+ ps -= 1;
+ else ps = f->next+p;
+ s += ps - f->next;
+#else
+ for(; p > 0; --p, ++ps, ++s)
+ if((*ps = *s) == 0)
+ break;
+#endif
+ w += ps - f->next;
+ f->next = ps;
+ }
+
+ /* sync unseekable shared streams */
+ if(f->extent < 0 && (f->flags&SF_SHARE) )
+ (void)SFFLSBUF(f,-1);
+
+ /* check for line buffering */
+ else if((f->flags&SF_LINE) && !(f->flags&SF_STRING) && (n = f->next-f->data) > 0)
+ { if(n > w)
+ n = w;
+ f->next -= n;
+ (void)SFWRITE(f,(Void_t*)f->next,n);
+ }
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, w);
+}
diff --git a/src/lib/libast/sfio/sfputu.c b/src/lib/libast/sfio/sfputu.c
new file mode 100644
index 0000000..17f1567
--- /dev/null
+++ b/src/lib/libast/sfio/sfputu.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+#undef sfputu
+
+#if __STD_C
+int sfputu(reg Sfio_t* f, Sfulong_t u)
+#else
+int sfputu(f,u)
+reg Sfio_t* f;
+reg Sfulong_t u;
+#endif
+{
+ return __sf_putu(f,u);
+}
diff --git a/src/lib/libast/sfio/sfraise.c b/src/lib/libast/sfio/sfraise.c
new file mode 100644
index 0000000..7ea4ef3
--- /dev/null
+++ b/src/lib/libast/sfio/sfraise.c
@@ -0,0 +1,107 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Invoke event handlers for a stream
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+static int _sfraiseall(int type, Void_t* data)
+#else
+static int _sfraiseall(type, data)
+int type; /* type of event */
+Void_t* data; /* associated data */
+#endif
+{
+ Sfio_t *f;
+ Sfpool_t *p, *next;
+ int n, rv;
+
+ rv = 0;
+ for(p = &_Sfpool; p; p = next)
+ {
+ for(next = p->next; next; next = next->next)
+ if(next->n_sf > 0)
+ break;
+ for(n = 0; n < p->n_sf; ++n)
+ { f = p->sf[n];
+ if(sfraise(f, type, data) < 0)
+ rv -= 1;
+ }
+ }
+ return rv;
+}
+
+#if __STD_C
+int sfraise(Sfio_t* f, int type, Void_t* data)
+#else
+int sfraise(f, type, data)
+Sfio_t* f; /* stream */
+int type; /* type of event */
+Void_t* data; /* associated data */
+#endif
+{
+ reg Sfdisc_t *disc, *next, *d;
+ reg int local, rv;
+ SFMTXDECL(f);
+
+ if(!f)
+ return _sfraiseall(type,data);
+
+ SFMTXENTER(f, -1);
+
+ GETLOCAL(f,local);
+ if(!SFKILLED(f) &&
+ !(local &&
+ (type == SF_NEW || type == SF_CLOSING ||
+ type == SF_FINAL || type == SF_ATEXIT)) &&
+ SFMODE(f,local) != (f->mode&SF_RDWR) && _sfmode(f,0,local) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,local);
+
+ for(disc = f->disc; disc; )
+ { next = disc->disc;
+ if(type == SF_FINAL)
+ f->disc = next;
+
+ if(disc->exceptf)
+ { SFOPEN(f,0);
+ if((rv = (*disc->exceptf)(f,type,data,disc)) != 0 )
+ SFMTXRETURN(f, rv);
+ SFLOCK(f,0);
+ }
+
+ if((disc = next) )
+ { /* make sure that "next" hasn't been popped */
+ for(d = f->disc; d; d = d->disc)
+ if(d == disc)
+ break;
+ if(!d)
+ disc = f->disc;
+ }
+ }
+
+ SFOPEN(f,local);
+ SFMTXRETURN(f, 0);
+}
diff --git a/src/lib/libast/sfio/sfrd.c b/src/lib/libast/sfio/sfrd.c
new file mode 100644
index 0000000..09a493c
--- /dev/null
+++ b/src/lib/libast/sfio/sfrd.c
@@ -0,0 +1,317 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Internal function to do a hard read.
+** This knows about discipline and memory mapping, peek read.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+/* synchronize unseekable write streams */
+#if __STD_C
+static void _sfwrsync(void)
+#else
+static void _sfwrsync()
+#endif
+{ reg Sfpool_t* p;
+ reg Sfio_t* f;
+ reg int n;
+
+ /* sync all pool heads */
+ for(p = _Sfpool.next; p; p = p->next)
+ { if(p->n_sf <= 0)
+ continue;
+ f = p->sf[0];
+ if(!SFFROZEN(f) && f->next > f->data &&
+ (f->mode&SF_WRITE) && f->extent < 0 )
+ (void)_sfflsbuf(f,-1);
+ }
+
+ /* and all the ones in the discrete pool */
+ for(n = 0; n < _Sfpool.n_sf; ++n)
+ { f = _Sfpool.sf[n];
+
+ if(!SFFROZEN(f) && f->next > f->data &&
+ (f->mode&SF_WRITE) && f->extent < 0 )
+ (void)_sfflsbuf(f,-1);
+ }
+}
+
+#if __STD_C
+ssize_t sfrd(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+ssize_t sfrd(f,buf,n,disc)
+Sfio_t* f;
+Void_t* buf;
+size_t n;
+Sfdisc_t* disc;
+#endif
+{
+ Sfoff_t r;
+ reg Sfdisc_t* dc;
+ reg int local, rcrv, dosync, oerrno;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,-1);
+
+ GETLOCAL(f,local);
+ if((rcrv = f->mode & (SF_RC|SF_RV)) )
+ f->mode &= ~(SF_RC|SF_RV);
+ f->bits &= ~SF_JUSTSEEK;
+
+ if(f->mode&SF_PKRD)
+ SFMTXRETURN(f, -1);
+
+ if(!local && !(f->bits&SF_DCDOWN)) /* an external user's call */
+ { if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, -1);
+ if(f->next < f->endb)
+ { if(SFSYNC(f) < 0)
+ SFMTXRETURN(f, -1);
+ if((f->mode&(SF_SYNCED|SF_READ)) == (SF_SYNCED|SF_READ) )
+ { f->endb = f->next = f->endr = f->data;
+ f->mode &= ~SF_SYNCED;
+ }
+#ifdef MAP_TYPE
+ if((f->bits&SF_MMAP) && f->data)
+ { SFMUNMAP(f, f->data, f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+#endif
+ f->next = f->endb = f->endr = f->endw = f->data;
+ }
+ }
+
+ for(dosync = 0;;)
+ { /* stream locked by sfsetfd() */
+ if(!(f->flags&SF_STRING) && f->file < 0)
+ SFMTXRETURN(f, 0);
+
+ f->flags &= ~(SF_EOF|SF_ERROR);
+
+ dc = disc;
+ if(f->flags&SF_STRING)
+ { if((r = (f->data+f->extent) - f->next) < 0)
+ r = 0;
+ if(r <= 0)
+ goto do_except;
+ SFMTXRETURN(f, (ssize_t)r);
+ }
+
+ /* warn that a read is about to happen */
+ SFDISC(f,dc,readf);
+ if(dc && dc->exceptf && (f->flags&SF_IOCHECK) )
+ { reg int rv;
+ if(local)
+ SETLOCAL(f);
+ if((rv = _sfexcept(f,SF_READ,n,dc)) > 0)
+ n = rv;
+ else if(rv < 0)
+ { f->flags |= SF_ERROR;
+ SFMTXRETURN(f, (ssize_t)rv);
+ }
+ }
+
+#ifdef MAP_TYPE
+ if(f->bits&SF_MMAP)
+ { reg ssize_t a, round;
+ sfstat_t st;
+
+ /* determine if we have to copy data to buffer */
+ if((uchar*)buf >= f->data && (uchar*)buf <= f->endb)
+ { n += f->endb - f->next;
+ buf = NIL(char*);
+ }
+
+ /* actual seek location */
+ if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC) &&
+ (r = SFSK(f,(Sfoff_t)0,SEEK_CUR,dc)) != f->here)
+ f->here = r;
+ else f->here -= f->endb-f->next;
+
+ /* before mapping, make sure we have data to map */
+ if((f->flags&SF_SHARE) || (size_t)(r = f->extent-f->here) < n)
+ { if((r = sysfstatf(f->file,&st)) < 0)
+ goto do_except;
+ if((r = (f->extent = st.st_size) - f->here) <= 0 )
+ { r = 0; /* eof */
+ goto do_except;
+ }
+ }
+
+ /* make sure current position is page aligned */
+ if((a = (size_t)(f->here%_Sfpage)) != 0)
+ { f->here -= a;
+ r += a;
+ }
+
+ /* map minimal requirement */
+ if(r > (round = (1 + (n+a)/f->size)*f->size) )
+ r = round;
+
+ if(f->data)
+ SFMUNMAP(f, f->data, f->endb-f->data);
+
+ for(;;)
+ { f->data = (uchar*) sysmmapf((caddr_t)0, (size_t)r,
+ (PROT_READ|PROT_WRITE),
+ MAP_PRIVATE,
+ f->file, (sfoff_t)f->here);
+ if(f->data && (caddr_t)f->data != (caddr_t)(-1))
+ break;
+ else
+ { f->data = NIL(uchar*);
+ if((r >>= 1) < (_Sfpage*SF_NMAP) ||
+ (errno != EAGAIN && errno != ENOMEM) )
+ break;
+ }
+ }
+
+ if(f->data)
+ { if(f->bits&SF_SEQUENTIAL)
+ SFMMSEQON(f,f->data,r);
+ f->next = f->data+a;
+ f->endr = f->endb = f->data+r;
+ f->endw = f->data;
+ f->here += r;
+
+ /* make known our seek location */
+ (void)SFSK(f,f->here,SEEK_SET,dc);
+
+ if(buf)
+ { if(n > (size_t)(r-a))
+ n = (ssize_t)(r-a);
+ memcpy(buf,f->next,n);
+ f->next += n;
+ }
+ else n = f->endb - f->next;
+
+ SFMTXRETURN(f, n);
+ }
+ else
+ { r = -1;
+ f->here += a;
+
+ /* reset seek pointer to its physical location */
+ (void)SFSK(f,f->here,SEEK_SET,dc);
+
+ /* make a buffer */
+ (void)SFSETBUF(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND);
+
+ if(!buf)
+ { buf = (Void_t*)f->data;
+ n = f->size;
+ }
+ }
+ }
+#endif
+
+ /* sync unseekable write streams to prevent deadlock */
+ if(!dosync && f->extent < 0)
+ { dosync = 1;
+ _sfwrsync();
+ }
+
+ /* make sure file pointer is right */
+ if(f->extent >= 0 && (f->flags&SF_SHARE) )
+ { if(!(f->flags&SF_PUBLIC) )
+ f->here = SFSK(f,f->here,SEEK_SET,dc);
+ else f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,dc);
+ }
+
+ oerrno = errno;
+ errno = 0;
+
+ if(dc && dc->readf)
+ { int share = f->flags&SF_SHARE;
+
+ if(rcrv) /* pass on rcrv for possible continuations */
+ f->mode |= rcrv;
+ /* tell readf that no peeking necessary */
+ else f->flags &= ~SF_SHARE;
+
+ SFDCRD(f,buf,n,dc,r);
+
+ /* reset flags */
+ if(rcrv)
+ f->mode &= ~rcrv;
+ else f->flags |= share;
+ }
+ else if(SFISNULL(f))
+ r = 0;
+ else if(f->extent < 0 && (f->flags&SF_SHARE) && rcrv)
+ { /* try peek read */
+ r = sfpkrd(f->file, (char*)buf, n,
+ (rcrv&SF_RC) ? (int)f->getr : -1,
+ -1L, (rcrv&SF_RV) ? 1 : 0);
+ if(r > 0)
+ { if(rcrv&SF_RV)
+ f->mode |= SF_PKRD;
+ else f->mode |= SF_RC;
+ }
+ }
+ else r = sysreadf(f->file,buf,n);
+
+ if(errno == 0 )
+ errno = oerrno;
+
+ if(r > 0 )
+ { if(!(f->bits&SF_DCDOWN) ) /* not a continuation call */
+ { if(!(f->mode&SF_PKRD) )
+ { f->here += r;
+ if(f->extent >= 0 && f->extent < f->here)
+ f->extent = f->here;
+ }
+ if((uchar*)buf >= f->data &&
+ (uchar*)buf < f->data+f->size)
+ f->endb = f->endr = ((uchar*)buf) + r;
+ }
+
+ SFMTXRETURN(f, (ssize_t)r);
+ }
+
+ do_except:
+ if(local)
+ SETLOCAL(f);
+ switch(_sfexcept(f,SF_READ,(ssize_t)r,dc))
+ {
+ case SF_ECONT :
+ goto do_continue;
+ case SF_EDONE :
+ n = local ? 0 : (ssize_t)r;
+ SFMTXRETURN(f,n);
+ case SF_EDISC :
+ if(!local && !(f->flags&SF_STRING))
+ goto do_continue;
+ /* else fall thru */
+ case SF_ESTACK :
+ SFMTXRETURN(f, -1);
+ }
+
+ do_continue:
+ for(dc = f->disc; dc; dc = dc->disc)
+ if(dc == disc)
+ break;
+ disc = dc;
+ }
+}
diff --git a/src/lib/libast/sfio/sfread.c b/src/lib/libast/sfio/sfread.c
new file mode 100644
index 0000000..a3aed97
--- /dev/null
+++ b/src/lib/libast/sfio/sfread.c
@@ -0,0 +1,140 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read n bytes from a stream into a buffer
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+ssize_t sfread(Sfio_t* f, Void_t* buf, size_t n)
+#else
+ssize_t sfread(f,buf,n)
+Sfio_t* f; /* read from this stream. */
+Void_t* buf; /* buffer to read into */
+size_t n; /* number of bytes to be read. */
+#endif
+{
+ reg uchar *s, *begs;
+ reg ssize_t r;
+ reg int local, justseek;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (ssize_t)(-1));
+
+ GETLOCAL(f,local);
+ justseek = f->bits&SF_JUSTSEEK; f->bits &= ~SF_JUSTSEEK;
+
+ if(!buf)
+ SFMTXRETURN(f, (ssize_t)(n == 0 ? 0 : -1) );
+
+ /* release peek lock */
+ if(f->mode&SF_PEEK)
+ { if(!(f->mode&SF_READ) )
+ SFMTXRETURN(f, (ssize_t)(-1));
+
+ if(f->mode&SF_GETR)
+ { if(((uchar*)buf + f->val) != f->next &&
+ (!f->rsrv || f->rsrv->data != (uchar*)buf) )
+ SFMTXRETURN(f, (ssize_t)(-1));
+ f->mode &= ~SF_PEEK;
+ SFMTXRETURN(f, 0);
+ }
+ else
+ { if((uchar*)buf != f->next)
+ SFMTXRETURN(f, (ssize_t)(-1));
+ f->mode &= ~SF_PEEK;
+ if(f->mode&SF_PKRD)
+ { /* actually read the data now */
+ f->mode &= ~SF_PKRD;
+ if(n > 0)
+ n = (r = sysreadf(f->file,f->data,n)) < 0 ? 0 : r;
+ f->endb = f->data+n;
+ f->here += n;
+ }
+ f->next += n;
+ f->endr = f->endb;
+ SFMTXRETURN(f, n);
+ }
+ }
+
+ s = begs = (uchar*)buf;
+ for(;; f->mode &= ~SF_LOCK)
+ { /* check stream mode */
+ if(SFMODE(f,local) != SF_READ && _sfmode(f,SF_READ,local) < 0)
+ { n = s > begs ? s-begs : (size_t)(-1);
+ SFMTXRETURN(f, (ssize_t)n);
+ }
+
+ SFLOCK(f,local);
+
+ if((r = f->endb - f->next) > 0) /* has buffered data */
+ { if(r > (ssize_t)n)
+ r = (ssize_t)n;
+ if(s != f->next)
+ memcpy(s, f->next, r);
+ f->next += r;
+ s += r;
+ n -= r;
+ }
+
+ if(n <= 0) /* all done */
+ break;
+
+ if(!(f->flags&SF_STRING) && !(f->bits&SF_MMAP) )
+ { f->next = f->endb = f->data;
+
+ /* exact IO is desirable for these cases */
+ if(SFDIRECT(f,n) ||
+ ((f->flags&SF_SHARE) && f->extent < 0) )
+ r = (ssize_t)n;
+ else if(justseek && n <= f->iosz && f->iosz <= f->size)
+ r = f->iosz; /* limit buffering */
+ else r = f->size; /* full buffering */
+
+ /* if read almost full size, then just do it direct */
+ if(r > (ssize_t)n && (r - r/8) <= (ssize_t)n)
+ r = (ssize_t)n;
+
+ /* read directly to user's buffer */
+ if(r == (ssize_t)n && (r = SFRD(f,s,r,f->disc)) >= 0)
+ { s += r;
+ n -= r;
+ if(r == 0 || n == 0) /* eof or eob */
+ break;
+ }
+ else goto do_filbuf;
+ }
+ else
+ { do_filbuf:
+ if(justseek)
+ f->bits |= SF_JUSTSEEK;
+ if(SFFILBUF(f,-1) <= 0)
+ break;
+ }
+ }
+
+ SFOPEN(f,local);
+ r = s-begs;
+ SFMTXRETURN(f, r);
+}
diff --git a/src/lib/libast/sfio/sfreserve.c b/src/lib/libast/sfio/sfreserve.c
new file mode 100644
index 0000000..29772a2
--- /dev/null
+++ b/src/lib/libast/sfio/sfreserve.c
@@ -0,0 +1,210 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Reserve a segment of data or buffer.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+Void_t* sfreserve(Sfio_t* f, ssize_t size, int type)
+#else
+Void_t* sfreserve(f,size,type)
+Sfio_t* f; /* file to peek */
+ssize_t size; /* size of peek */
+int type; /* LOCKR: lock stream, LASTR: last record */
+#endif
+{
+ reg ssize_t n, now, sz, iosz;
+ reg Sfrsrv_t* rsrv;
+ reg Void_t* data;
+ reg int mode, local;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,NIL(Void_t*));
+
+ sz = size < 0 ? -size : size;
+
+ /* see if we need to bias toward SF_WRITE instead of the default SF_READ */
+ if(type < 0)
+ mode = 0;
+ else if((mode = type&SF_WRITE) )
+ type &= ~SF_WRITE;
+
+ /* return the last record */
+ if(type == SF_LASTR )
+ { if((n = f->endb - f->next) > 0 && n == f->val )
+ { data = (Void_t*)f->next;
+ f->next += n;
+ }
+ else if((rsrv = f->rsrv) && (n = -rsrv->slen) > 0)
+ { rsrv->slen = 0;
+ _Sfi = f->val = n;
+ data = (Void_t*)rsrv->data;
+ }
+ else
+ { _Sfi = f->val = -1;
+ data = NIL(Void_t*);
+ }
+
+ SFMTXRETURN(f, data);
+ }
+
+ if(type > 0)
+ { if(type == 1 ) /* upward compatibility mode */
+ type = SF_LOCKR;
+ else if(type != SF_LOCKR)
+ SFMTXRETURN(f, NIL(Void_t*));
+ }
+
+ if(size == 0 && (type < 0 || type == SF_LOCKR) )
+ { if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
+ SFMTXRETURN(f, NIL(Void_t*));
+
+ SFLOCK(f,0);
+ if((n = f->endb - f->next) < 0)
+ n = 0;
+
+ goto done;
+ }
+
+ /* iterate until get to a stream that has data or buffer space */
+ for(local = 0;; local = SF_LOCAL)
+ { _Sfi = f->val = -1;
+
+ if(!mode && !(mode = f->flags&SF_READ) )
+ mode = SF_WRITE;
+ if((int)f->mode != mode && _sfmode(f,mode,local) < 0)
+ { SFOPEN(f,0);
+ SFMTXRETURN(f, NIL(Void_t*));
+ }
+
+ SFLOCK(f,local);
+
+ if((n = now = f->endb - f->next) < 0)
+ n = 0;
+ if(n > 0 && n >= sz) /* all done */
+ break;
+
+ /* set amount to perform IO */
+ if(size == 0 || (f->mode&SF_WRITE))
+ iosz = -1;
+ else if(size < 0 && n == 0 && f->push) /* maybe stack-pop */
+ { if((iosz = f->push->endb - f->push->next) == 0)
+ iosz = f->push->size;
+ if(iosz < sz)
+ iosz = sz; /* so only get what is asked for */
+ }
+ else
+ { iosz = sz - n; /* get enough to fulfill requirement */
+ if(size < 0 && iosz < (f->size - n) )
+ iosz = f->size - n; /* get as much as possible */
+ if(iosz <= 0) /* nothing to do */
+ break;
+ }
+
+ /* do a buffer refill or flush */
+ now = n;
+ if(f->mode&SF_WRITE)
+ (void)SFFLSBUF(f, iosz);
+ else if(type == SF_LOCKR && f->extent < 0 && (f->flags&SF_SHARE) )
+ { if(n == 0) /* peek-read only if there is no buffered data */
+ { f->mode |= SF_RV;
+ (void)SFFILBUF(f, iosz );
+ }
+ if((n = f->endb - f->next) < sz)
+ { if(f->mode&SF_PKRD)
+ { f->endb = f->endr = f->next;
+ f->mode &= ~SF_PKRD;
+ }
+ break;
+ }
+ }
+ else
+ { /* sfreserve(f,0,0) == sfread(f, sfreserve(f,-1,SF_LOCKR), 0) */
+ if(size == 0 && type == 0)
+ f->mode |= SF_RV;
+
+ (void)SFFILBUF(f, iosz );
+ }
+
+ if((n = f->endb - f->next) <= 0)
+ n = 0;
+
+ if(n >= sz) /* got it */
+ break;
+
+ if(n == now || sferror(f) || sfeof(f)) /* no progress */
+ break;
+
+ /* request was only to assess data availability */
+ if(type == SF_LOCKR && size > 0 && n > 0 )
+ break;
+ }
+
+done: /* compute the buffer to be returned */
+ data = NIL(Void_t*);
+ if(size == 0 || n == 0)
+ { if(n > 0) /* got data */
+ data = (Void_t*)f->next;
+ else if(type == SF_LOCKR && size == 0 && (rsrv = _sfrsrv(f,0)) )
+ data = (Void_t*)rsrv->data;
+ }
+ else if(n >= sz) /* got data */
+ data = (Void_t*)f->next;
+ else if(f->flags&SF_STRING) /* try extending string buffer */
+ { if((f->mode&SF_WRITE) && (f->flags&SF_MALLOC) )
+ { (void)SFWR(f,f->next,sz,f->disc);
+ if((n = f->endb - f->next) >= sz )
+ data = (Void_t*)f->next;
+ }
+ }
+ else if(f->mode&SF_WRITE) /* allocate side buffer */
+ { if(type == SF_LOCKR && (rsrv = _sfrsrv(f, sz)) )
+ data = (Void_t*)rsrv->data;
+ }
+ else if(type != SF_LOCKR && sz > f->size && (rsrv = _sfrsrv(f,sz)) )
+ { if((n = SFREAD(f,(Void_t*)rsrv->data,sz)) >= sz) /* read side buffer */
+ data = (Void_t*)rsrv->data;
+ else rsrv->slen = -n;
+ }
+
+ SFOPEN(f,0);
+
+ if(data)
+ { if(type == SF_LOCKR)
+ { f->mode |= SF_PEEK;
+ if((f->mode & SF_READ) && size == 0 && data != f->next)
+ f->mode |= SF_GETR; /* so sfread() will unlock */
+ f->endr = f->endw = f->data;
+ }
+ else
+ { if(data == (Void_t*)f->next)
+ f->next += (size >= 0 ? size : n);
+ }
+ }
+
+ _Sfi = f->val = n; /* return true buffer size */
+
+ SFMTXRETURN(f, data);
+}
diff --git a/src/lib/libast/sfio/sfresize.c b/src/lib/libast/sfio/sfresize.c
new file mode 100644
index 0000000..ae5c83c
--- /dev/null
+++ b/src/lib/libast/sfio/sfresize.c
@@ -0,0 +1,83 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Resize a stream.
+ Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfresize(Sfio_t* f, Sfoff_t size)
+#else
+int sfresize(f, size)
+Sfio_t* f;
+Sfoff_t size;
+#endif
+{
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, -1);
+
+ if(size < 0 || f->extent < 0 ||
+ (f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0) )
+ SFMTXRETURN(f, -1);
+
+ SFLOCK(f,0);
+
+ if(f->flags&SF_STRING)
+ { SFSTRSIZE(f);
+
+ if(f->extent >= size)
+ { if((f->flags&SF_MALLOC) && (f->next - f->data) <= size)
+ { size_t s = (((size_t)size + 1023)/1024)*1024;
+ Void_t* d;
+ if(s < f->size && (d = realloc(f->data, s)) )
+ { f->data = d;
+ f->size = s;
+ f->extent = s;
+ }
+ }
+ memclear((char*)(f->data+size), (int)(f->extent-size));
+ }
+ else
+ { if(SFSK(f, size, SEEK_SET, f->disc) != size)
+ SFMTXRETURN(f, -1);
+ memclear((char*)(f->data+f->extent), (int)(size-f->extent));
+ }
+ }
+ else
+ { if(f->next > f->data)
+ SFSYNC(f);
+#if _lib_ftruncate
+ if(ftruncate(f->file, (sfoff_t)size) < 0)
+ SFMTXRETURN(f, -1);
+#else
+ SFMTXRETURN(f, -1);
+#endif
+ }
+
+ f->extent = size;
+
+ SFOPEN(f, 0);
+
+ SFMTXRETURN(f, 0);
+}
diff --git a/src/lib/libast/sfio/sfscanf.c b/src/lib/libast/sfio/sfscanf.c
new file mode 100644
index 0000000..12eec1a
--- /dev/null
+++ b/src/lib/libast/sfio/sfscanf.c
@@ -0,0 +1,102 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Read formated data from a stream
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfscanf(Sfio_t* f, const char* form, ...)
+#else
+int sfscanf(va_alist)
+va_dcl
+#endif
+{
+ va_list args;
+ reg int rv;
+
+#if __STD_C
+ va_start(args,form);
+#else
+ reg Sfio_t* f;
+ reg char* form;
+ va_start(args);
+ f = va_arg(args,Sfio_t*);
+ form = va_arg(args,char*);
+#endif
+
+ rv = (f && form) ? sfvscanf(f,form,args) : -1;
+ va_end(args);
+ return rv;
+}
+
+#if __STD_C
+int sfvsscanf(const char* s, const char* form, va_list args)
+#else
+int sfvsscanf(s, form, args)
+char* s;
+char* form;
+va_list args;
+#endif
+{
+ Sfio_t f;
+
+ if(!s || !form)
+ return -1;
+
+ /* make a fake stream */
+ SFCLEAR(&f,NIL(Vtmutex_t*));
+ f.flags = SF_STRING|SF_READ;
+ f.bits = SF_PRIVATE;
+ f.mode = SF_READ;
+ f.size = strlen((char*)s);
+ f.data = f.next = f.endw = (uchar*)s;
+ f.endb = f.endr = f.data+f.size;
+
+ return sfvscanf(&f,form,args);
+}
+
+#if __STD_C
+int sfsscanf(const char* s, const char* form,...)
+#else
+int sfsscanf(va_alist)
+va_dcl
+#endif
+{
+ va_list args;
+ reg int rv;
+#if __STD_C
+ va_start(args,form);
+#else
+ reg char* s;
+ reg char* form;
+ va_start(args);
+ s = va_arg(args,char*);
+ form = va_arg(args,char*);
+#endif
+
+ rv = (s && form) ? sfvsscanf(s,form,args) : -1;
+ va_end(args);
+ return rv;
+}
diff --git a/src/lib/libast/sfio/sfseek.c b/src/lib/libast/sfio/sfseek.c
new file mode 100644
index 0000000..1f446ba
--- /dev/null
+++ b/src/lib/libast/sfio/sfseek.c
@@ -0,0 +1,281 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Set the IO pointer to a specific location in the stream
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+static void newpos(Sfio_t* f, Sfoff_t p)
+#else
+static void newpos(f, p)
+Sfio_t* f;
+Sfoff_t p;
+#endif
+{
+#ifdef MAP_TYPE
+ if((f->bits&SF_MMAP) && f->data)
+ { SFMUNMAP(f, f->data, f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+#endif
+ f->next = f->endr = f->endw = f->data;
+ f->endb = (f->mode&SF_WRITE) ? f->data+f->size : f->data;
+ if((f->here = p) < 0)
+ { f->extent = -1;
+ f->here = 0;
+ }
+}
+
+#if __STD_C
+Sfoff_t sfseek(Sfio_t* f, Sfoff_t p, int type)
+#else
+Sfoff_t sfseek(f,p,type)
+Sfio_t* f; /* seek to a new location in this stream */
+Sfoff_t p; /* place to seek to */
+int type; /* 0: from org, 1: from here, 2: from end */
+#endif
+{
+ Sfoff_t r, s;
+ int mode, local, hardseek, mustsync;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (Sfoff_t)(-1));
+
+ GETLOCAL(f,local);
+
+ hardseek = (type|f->flags)&(SF_SHARE|SF_PUBLIC);
+
+ if(hardseek && f->mode == (SF_READ|SF_SYNCED) )
+ { newpos(f,f->here);
+ f->mode = SF_READ;
+ }
+
+ /* set and initialize the stream to a definite mode */
+ if((int)SFMODE(f,local) != (mode = f->mode&SF_RDWR))
+ { int flags = f->flags;
+
+ if(hardseek&SF_PUBLIC) /* seek ptr must follow file descriptor */
+ f->flags |= SF_SHARE|SF_PUBLIC;
+ mode = _sfmode(f,mode,local);
+ if(hardseek&SF_PUBLIC)
+ f->flags = flags;
+
+ if(mode < 0)
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+ }
+
+ mustsync = (type&SF_SHARE) && !(type&SF_PUBLIC) &&
+ (f->mode&SF_READ) && !(f->flags&SF_STRING);
+
+ /* Xopen-compliant */
+ if((type &= (SEEK_SET|SEEK_CUR|SEEK_END)) != SEEK_SET &&
+ type != SEEK_CUR && type != SEEK_END )
+ { errno = EINVAL;
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+ }
+
+ if(f->extent < 0)
+ { /* let system call set errno */
+ (void)SFSK(f,(Sfoff_t)0,SEEK_CUR,f->disc);
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+ }
+
+ /* throw away ungetc data */
+ if(f->disc == _Sfudisc)
+ (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*)));
+
+ /* lock the stream for internal manipulations */
+ SFLOCK(f,local);
+
+ /* clear error and eof bits */
+ f->flags &= ~(SF_EOF|SF_ERROR);
+
+ while(f->flags&SF_STRING)
+ { SFSTRSIZE(f);
+
+ if(type == SEEK_CUR)
+ r = p + (f->next - f->data);
+ else if(type == SEEK_END)
+ r = p + f->extent;
+ else r = p;
+
+ if(r >= 0 && r <= f->size)
+ { p = r;
+ f->next = f->data+p;
+ f->here = p;
+ if(p > f->extent)
+ memclear((char*)(f->data+f->extent),(int)(p-f->extent));
+ goto done;
+ }
+
+ /* check exception handler, note that this may pop stream */
+ if(SFSK(f,r,SEEK_SET,f->disc) != r)
+ { p = -1;
+ goto done;
+ }
+ else if(!(f->flags&SF_STRING))
+ { p = r;
+ goto done;
+ }
+ }
+
+ if(f->mode&SF_WRITE)
+ { /* see if we can avoid flushing buffer */
+ if(!hardseek && type < SEEK_END && !(f->flags&SF_APPENDWR) )
+ { s = f->here + (f->next - f->data);
+ r = p + (type == SEEK_SET ? 0 : s);
+ if(r == s)
+ { p = r;
+ goto done;
+ }
+ }
+
+ if(f->next > f->data && SFSYNC(f) < 0)
+ { p = -1;
+ goto done;
+ }
+ }
+
+ if(type == SEEK_END || (f->mode&SF_WRITE) )
+ { if((hardseek&SF_PUBLIC) || type == SEEK_END)
+ p = SFSK(f, p, type, f->disc);
+ else
+ { r = p + (type == SEEK_CUR ? f->here : 0);
+ p = (hardseek || r != f->here) ? SFSK(f,r,SEEK_SET,f->disc) : r;
+ }
+ if(p >= 0)
+ newpos(f,p);
+
+ goto done;
+ }
+
+ /* if get here, must be a read stream */
+ s = f->here - (f->endb - f->next);
+ r = p + (type == SEEK_CUR ? s : 0);
+ if(r <= f->here && r >= (f->here - (f->endb-f->data)) )
+ { if((hardseek || (type == SEEK_CUR && p == 0)) )
+ { if((s = SFSK(f, (Sfoff_t)0, SEEK_CUR, f->disc)) == f->here ||
+ (s >= 0 && !(hardseek&SF_PUBLIC) &&
+ (s = SFSK(f, f->here, SEEK_SET, f->disc)) == f->here) )
+ goto near_done;
+ else if(s < 0)
+ { p = -1;
+ goto done;
+ }
+ else
+ { newpos(f,s);
+ hardseek = 0;
+ }
+ }
+ else
+ { near_done:
+ f->next = f->endb - (f->here - r);
+ p = r;
+ goto done;
+ }
+ }
+
+ /* desired position */
+ if((p += type == SEEK_CUR ? s : 0) < 0)
+ goto done;
+
+#ifdef MAP_TYPE
+ if(f->bits&SF_MMAP)
+ { /* if mmap is not great, stop mmaping if moving around too much */
+#if _mmap_worthy < 2
+ if((f->next - f->data) < ((f->endb - f->data)/4) )
+ { SFSETBUF(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND);
+ hardseek = 1; /* this forces a hard seek below */
+ }
+ else
+#endif
+ { /* for mmap, f->here can be virtual except for hardseek */
+ newpos(f,p);
+ if(!hardseek)
+ goto done;
+ }
+ }
+#endif
+
+ if(f->endb > f->next)
+ { /* reduce wastage in future buffer fillings */
+ f->iosz = (f->next - f->data) + (f->endb - f->next)/2;
+ f->iosz = ((f->iosz + f->blksz-1)/f->blksz)*f->blksz;
+ }
+ if(f->iosz >= f->size)
+ f->iosz = 0;
+
+ /* buffer is now considered empty */
+ f->next = f->endr = f->endb = f->data;
+
+ /* small backseeks often come in bunches, so seek back as far as possible */
+ if(p < f->lpos && f->size > f->blksz && (p + f->blksz) > s)
+ { if((r = s - f->size) < 0)
+ r = 0;
+ }
+ /* try to align buffer to block boundary to enhance I/O speed */
+ else if(f->blksz > 0 && f->size >= 2*f->blksz)
+ r = p - (p%f->blksz);
+ else
+ { r = p;
+
+ /* seeking around and wasting data, be conservative */
+ if(f->iosz > 0 && (p > f->lpos || p < f->lpos-f->size) )
+ f->bits |= SF_JUSTSEEK;
+ }
+
+ if((hardseek || r != f->here) && (f->here = SFSK(f,r,SEEK_SET,f->disc)) != r)
+ { if(r < p) /* now try to just get to p */
+ f->here = SFSK(f,p,SEEK_SET,f->disc);
+ if(f->here != p)
+ p = -1;
+ goto done;
+ }
+
+ if(r < p) /* read to cover p */
+ { (void)SFRD(f, f->data, f->size, f->disc);
+ if(p <= f->here && p >= (f->here - (f->endb - f->data)) )
+ f->next = f->endb - (size_t)(f->here-p);
+ else /* recover from read failure by just seeking to p */
+ { f->next = f->endb = f->data;
+ if((f->here = SFSK(f,p,SEEK_SET,f->disc)) != p)
+ p = -1;
+ }
+ }
+
+done :
+ if(f->here < 0) /* hasn't been the best of time */
+ { f->extent = -1;
+ f->here = 0;
+ }
+
+ f->lpos = p;
+
+ SFOPEN(f,local);
+
+ if(mustsync)
+ sfsync(f);
+ SFMTXRETURN(f, p);
+}
diff --git a/src/lib/libast/sfio/sfset.c b/src/lib/libast/sfio/sfset.c
new file mode 100644
index 0000000..a18662e
--- /dev/null
+++ b/src/lib/libast/sfio/sfset.c
@@ -0,0 +1,99 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Set some control flags or file descript for the stream
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfset(Sfio_t* f, int flags, int set)
+#else
+int sfset(f,flags,set)
+Sfio_t* f;
+int flags;
+int set;
+#endif
+{
+ reg int oflags, tflags, rv;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,0);
+
+ if(flags == 0 && set == 0)
+ SFMTXRETURN(f, (f->flags&SF_FLAGS));
+
+ if((oflags = (f->mode&SF_RDWR)) != (int)f->mode)
+ { /* avoid sfsetbuf() isatty() call if user sets (SF_LINE|SF_WCWIDTH) */
+ if(set && (flags & (SF_LINE|SF_WCWIDTH)) && !(f->flags & (SF_LINE|SF_WCWIDTH)))
+ { tflags = (SF_LINE|SF_WCWIDTH);
+ f->flags |= tflags;
+ }
+ else tflags = 0;
+ rv = _sfmode(f,oflags,0);
+ if(tflags)
+ f->flags &= ~tflags;
+ if(rv < 0)
+ SFMTXRETURN(f, 0);
+ }
+ if(flags == 0)
+ SFMTXRETURN(f, (f->flags&SF_FLAGS));
+
+ SFLOCK(f,0);
+
+ /* preserve at least one rd/wr flag */
+ oflags = f->flags;
+ if(!(f->bits&SF_BOTH) || (flags&SF_RDWR) == SF_RDWR )
+ flags &= ~SF_RDWR;
+
+ /* set the flag */
+ if(set)
+ f->flags |= (flags&SF_SETS);
+ else f->flags &= ~(flags&SF_SETS);
+
+ /* must have at least one of read/write */
+ if(!(f->flags&SF_RDWR))
+ f->flags |= (oflags&SF_RDWR);
+
+ if(f->extent < 0)
+ f->flags &= ~SF_APPENDWR;
+
+ /* turn to appropriate mode as necessary */
+ if((flags &= SF_RDWR) )
+ { if(!set)
+ { if(flags == SF_READ)
+ flags = SF_WRITE;
+ else flags = SF_READ;
+ }
+ if((flags == SF_WRITE && !(f->mode&SF_WRITE)) ||
+ (flags == SF_READ && !(f->mode&(SF_READ|SF_SYNCED))) )
+ (void)_sfmode(f,flags,1);
+ }
+
+ /* if not shared or unseekable, public means nothing */
+ if(!(f->flags&SF_SHARE) || f->extent < 0)
+ f->flags &= ~SF_PUBLIC;
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, (oflags&SF_FLAGS));
+}
diff --git a/src/lib/libast/sfio/sfsetbuf.c b/src/lib/libast/sfio/sfsetbuf.c
new file mode 100644
index 0000000..cb0240b
--- /dev/null
+++ b/src/lib/libast/sfio/sfsetbuf.c
@@ -0,0 +1,426 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide getpagesize
+#else
+#define getpagesize ______getpagesize
+#endif
+
+#include "sfhdr.h"
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide getpagesize
+#else
+#undef getpagesize
+#endif
+
+#if _lib_getpagesize
+_BEGIN_EXTERNS_
+extern int getpagesize _ARG_((void));
+_END_EXTERNS_
+#endif
+
+/* Set a (new) buffer for a stream.
+** If size < 0, it is assigned a suitable value depending on the
+** kind of stream. The actual buffer size allocated is dependent
+** on how much memory is available.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if !_sys_stat
+struct stat
+{ int st_mode;
+ int st_size;
+};
+#undef sysfstatf
+#define sysfstatf(fd,st) (-1)
+#endif /*_sys_stat*/
+
+#if _PACKAGE_ast && !defined(SFSETLINEMODE)
+#define SFSETLINEMODE 1
+#endif
+
+#if SFSETLINEMODE
+
+static int sfsetlinemode()
+{ char* astsfio;
+ char* endw;
+
+ static int modes = -1;
+ static const char sf_line[] = "SF_LINE";
+ static const char sf_maxr[] = "SF_MAXR=";
+ static const char sf_wcwidth[] = "SF_WCWIDTH";
+
+#define ISSEPAR(c) ((c) == ',' || (c) == ' ' || (c) == '\t')
+ if (modes < 0)
+ { modes = 0;
+ if(astsfio = getenv("SFIO_OPTIONS"))
+ { for(; *astsfio != 0; astsfio = endw)
+ { while(ISSEPAR(*astsfio) )
+ ++astsfio;
+ for(endw = astsfio; *endw && !ISSEPAR(*endw); ++endw)
+ ;
+ if((endw-astsfio) > (sizeof(sf_line)-1) &&
+ strncmp(astsfio,sf_line,sizeof(sf_line)-1) == 0)
+ modes |= SF_LINE;
+ else if((endw-astsfio) > (sizeof(sf_maxr)-1) &&
+ strncmp(astsfio,sf_maxr,sizeof(sf_maxr)-1) == 0)
+#if _PACKAGE_ast
+ _Sfmaxr = (ssize_t)strtonll(astsfio+sizeof(sf_maxr)-1,NiL,NiL,0);
+#else
+ _Sfmaxr = (ssize_t)strtol(astsfio+sizeof(sf_maxr)-1,NiL,0);
+#endif
+ else if((endw-astsfio) > (sizeof(sf_wcwidth)-1) &&
+ strncmp(astsfio,sf_wcwidth,sizeof(sf_wcwidth)-1) == 0)
+ modes |= SF_WCWIDTH;
+ }
+ }
+ }
+ return modes;
+}
+
+#endif
+
+#if __STD_C
+Void_t* sfsetbuf(Sfio_t* f, Void_t* buf, size_t size)
+#else
+Void_t* sfsetbuf(f,buf,size)
+Sfio_t* f; /* stream to be buffered */
+Void_t* buf; /* new buffer */
+size_t size; /* buffer size, -1 for default size */
+#endif
+{
+ int sf_malloc, oflags, init, okmmap, local;
+ ssize_t bufsize, blksz;
+ Sfdisc_t* disc;
+ sfstat_t st;
+ uchar* obuf = NIL(uchar*);
+ ssize_t osize = 0;
+ SFMTXDECL(f);
+
+ SFONCE();
+
+ SFMTXENTER(f,NIL(Void_t*));
+
+ GETLOCAL(f,local);
+
+ if(size == 0 && buf)
+ { /* special case to get buffer info */
+ _Sfi = f->val = (f->bits&SF_MMAP) ? (f->endb-f->data) : f->size;
+ SFMTXRETURN(f, (Void_t*)f->data);
+ }
+
+ /* cleanup actions already done, don't allow write buffering any more */
+ if(_Sfexiting && !(f->flags&SF_STRING) && (f->mode&SF_WRITE))
+ { buf = NIL(Void_t*);
+ size = 0;
+ }
+
+ if((init = f->mode&SF_INIT) )
+ { if(!f->pool && _sfsetpool(f) < 0)
+ SFMTXRETURN(f, NIL(Void_t*));
+ }
+ else if((f->mode&SF_RDWR) != SFMODE(f,local) && _sfmode(f,0,local) < 0)
+ SFMTXRETURN(f, NIL(Void_t*));
+
+ if(init)
+ f->mode = (f->mode&SF_RDWR)|SF_LOCK;
+ else
+ { int rv;
+
+ /* make sure there is no hidden read data */
+ if(f->proc && (f->flags&SF_READ) && (f->mode&SF_WRITE) &&
+ _sfmode(f,SF_READ,local) < 0)
+ SFMTXRETURN(f, NIL(Void_t*));
+
+ /* synchronize first */
+ SFLOCK(f,local); rv = SFSYNC(f); SFOPEN(f,local);
+ if(rv < 0)
+ SFMTXRETURN(f, NIL(Void_t*));
+
+ /* turn off the SF_SYNCED bit because buffer is changing */
+ f->mode &= ~SF_SYNCED;
+ }
+
+ SFLOCK(f,local);
+
+ if((Sfio_t*)buf != f)
+ blksz = -1;
+ else /* setting alignment size only */
+ { blksz = (ssize_t)size;
+
+ if(!init) /* stream already initialized */
+ { obuf = f->data;
+ osize = f->size;
+ goto done;
+ }
+ else /* initialize stream as if in the default case */
+ { buf = NIL(Void_t*);
+ size = (size_t)SF_UNBOUND;
+ }
+ }
+
+ bufsize = 0;
+ oflags = f->flags;
+
+ /* see if memory mapping is possible (see sfwrite for SF_BOTH) */
+ okmmap = (buf || (f->flags&SF_STRING) || (f->flags&SF_RDWR) == SF_RDWR) ? 0 : 1;
+
+ /* save old buffer info */
+#ifdef MAP_TYPE
+ if(f->bits&SF_MMAP)
+ { if(f->data)
+ { SFMUNMAP(f,f->data,f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+ } else
+#endif
+ if(f->data == f->tiny)
+ { f->data = NIL(uchar*);
+ f->size = 0;
+ }
+ obuf = f->data;
+ osize = f->size;
+
+ f->flags &= ~SF_MALLOC;
+ f->bits &= ~SF_MMAP;
+
+ /* pure read/string streams must have a valid string */
+ if((f->flags&(SF_RDWR|SF_STRING)) == SF_RDSTR &&
+ (size == (size_t)SF_UNBOUND || !buf))
+ size = 0;
+
+ /* set disc to the first discipline with a seekf */
+ for(disc = f->disc; disc; disc = disc->disc)
+ if(disc->seekf)
+ break;
+
+ if((init || local) && !(f->flags&SF_STRING))
+ { /* ASSERT(f->file >= 0) */
+ st.st_mode = 0;
+
+ /* if has discipline, set size by discipline if possible */
+ if(!_sys_stat || disc)
+ { if((f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,disc)) < 0)
+ goto unseekable;
+ else
+ { Sfoff_t e;
+ if((e = SFSK(f,(Sfoff_t)0,SEEK_END,disc)) >= 0)
+ f->extent = e > f->here ? e : f->here;
+ (void)SFSK(f,f->here,SEEK_SET,disc);
+ goto setbuf;
+ }
+ }
+
+ /* get file descriptor status */
+ if(sysfstatf((int)f->file,&st) < 0)
+ f->here = -1;
+ else
+ {
+#if _sys_stat && _stat_blksize /* preferred io block size */
+ f->blksz = (size_t)st.st_blksize;
+#endif
+ bufsize = 64 * 1024;
+ if(S_ISDIR(st.st_mode) || (Sfoff_t)st.st_size < (Sfoff_t)SF_GRAIN)
+ okmmap = 0;
+ if(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
+ f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,f->disc);
+ else f->here = -1;
+
+#if O_TEXT /* no memory mapping with O_TEXT because read()/write() alter data stream */
+ if(okmmap && f->here >= 0 &&
+ (sysfcntlf((int)f->file,F_GETFL,0) & O_TEXT) )
+ okmmap = 0;
+#endif
+ }
+
+#if SFSETLINEMODE
+ if(init)
+ f->flags |= sfsetlinemode();
+#endif
+
+ if(f->here >= 0)
+ { f->extent = (Sfoff_t)st.st_size;
+
+ /* seekable std-devices are share-public by default */
+ if(f == sfstdin || f == sfstdout || f == sfstderr)
+ f->flags |= SF_SHARE|SF_PUBLIC;
+ }
+ else
+ {
+ unseekable:
+ f->extent = -1;
+ f->here = 0;
+
+ if(init)
+ { if(S_ISCHR(st.st_mode) )
+ { int oerrno = errno;
+
+ bufsize = SF_GRAIN;
+
+ /* set line mode for terminals */
+ if(!(f->flags&(SF_LINE|SF_WCWIDTH)) && isatty(f->file))
+ f->flags |= SF_LINE|SF_WCWIDTH;
+#if _sys_stat
+ else /* special case /dev/null */
+ { reg int dev, ino;
+ static int null_checked, null_dev, null_ino;
+ dev = (int)st.st_dev;
+ ino = (int)st.st_ino;
+ if(!null_checked)
+ { if(sysstatf(DEVNULL,&st) < 0)
+ null_checked = -1;
+ else
+ { null_checked = 1;
+ null_dev = (int)st.st_dev;
+ null_ino = (int)st.st_ino;
+ }
+ }
+ if(null_checked >= 0 && dev == null_dev && ino == null_ino)
+ SFSETNULL(f);
+ }
+#endif
+ errno = oerrno;
+ }
+
+ /* initialize side buffer for r+w unseekable streams */
+ if(!f->proc && (f->bits&SF_BOTH) )
+ (void)_sfpopen(f,-1,-1,1);
+ }
+ }
+
+ /* set page size, this is also the desired default buffer size */
+ if(_Sfpage <= 0)
+ {
+#if _lib_getpagesize
+ if((_Sfpage = (size_t)getpagesize()) <= 0)
+#endif
+ _Sfpage = SF_PAGE;
+ }
+ }
+
+#ifdef MAP_TYPE
+ if(okmmap && size && (f->mode&SF_READ) && f->extent >= 0 )
+ { /* see if we can try memory mapping */
+ if(!disc)
+ for(disc = f->disc; disc; disc = disc->disc)
+ if(disc->readf)
+ break;
+ if(!disc)
+ { f->bits |= SF_MMAP;
+ if(size == (size_t)SF_UNBOUND)
+ { if(bufsize > _Sfpage)
+ size = bufsize * SF_NMAP;
+ else size = _Sfpage * SF_NMAP;
+ if(size > 256*1024)
+ size = 256*1024;
+ }
+ }
+ }
+#endif
+
+ /* get buffer space */
+setbuf:
+ if(size == (size_t)SF_UNBOUND)
+ { /* define a default size suitable for block transfer */
+ if(init && osize > 0)
+ size = osize;
+ else if(f == sfstderr && (f->mode&SF_WRITE))
+ size = 0;
+ else if(f->flags&SF_STRING )
+ size = SF_GRAIN;
+ else if((f->flags&SF_READ) && !(f->bits&SF_BOTH) &&
+ f->extent > 0 && f->extent < (Sfoff_t)_Sfpage )
+ size = (((size_t)f->extent + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN;
+ else if((ssize_t)(size = _Sfpage) < bufsize)
+ size = bufsize;
+
+ buf = NIL(Void_t*);
+ }
+
+ sf_malloc = 0;
+ if(size > 0 && !buf && !(f->bits&SF_MMAP))
+ { /* try to allocate a buffer */
+ if(obuf && size == (size_t)osize && init)
+ { buf = (Void_t*)obuf;
+ obuf = NIL(uchar*);
+ sf_malloc = (oflags&SF_MALLOC);
+ }
+ if(!buf)
+ { /* do allocation */
+ while(!buf && size > 0)
+ { if((buf = (Void_t*)malloc(size)) )
+ break;
+ else size /= 2;
+ }
+ if(size > 0)
+ sf_malloc = SF_MALLOC;
+ }
+ }
+
+ if(size == 0 && !(f->flags&SF_STRING) && !(f->bits&SF_MMAP) && (f->mode&SF_READ))
+ { /* use the internal buffer */
+ size = sizeof(f->tiny);
+ buf = (Void_t*)f->tiny;
+ }
+
+ /* set up new buffer */
+ f->size = size;
+ f->next = f->data = f->endr = f->endw = (uchar*)buf;
+ f->endb = (f->mode&SF_READ) ? f->data : f->data+size;
+ if(f->flags&SF_STRING)
+ { /* these fields are used to test actual size - see sfseek() */
+ f->extent = (!sf_malloc &&
+ ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ) ? size : 0;
+ f->here = 0;
+
+ /* read+string stream should have all data available */
+ if((f->mode&SF_READ) && !sf_malloc)
+ f->endb = f->data+size;
+ }
+
+ f->flags = (f->flags & ~SF_MALLOC)|sf_malloc;
+
+ if(obuf && obuf != f->data && osize > 0 && (oflags&SF_MALLOC))
+ { free((Void_t*)obuf);
+ obuf = NIL(uchar*);
+ }
+
+done:
+ _Sfi = f->val = obuf ? osize : 0;
+
+ /* blksz is used for aligning disk block boundary while reading data to
+ ** optimize data transfer from disk (eg, via direct I/O). blksz can be
+ ** at most f->size/2 so that data movement in buffer can be optimized.
+ ** blksz should also be a power-of-2 for optimal disk seeks.
+ */
+ if(blksz <= 0 || (blksz & (blksz-1)) != 0 )
+ blksz = SF_GRAIN;
+ while(blksz > f->size/2)
+ blksz /= 2;
+ f->blksz = blksz;
+
+ SFOPEN(f,local);
+
+ SFMTXRETURN(f, (Void_t*)obuf);
+}
diff --git a/src/lib/libast/sfio/sfsetfd.c b/src/lib/libast/sfio/sfsetfd.c
new file mode 100644
index 0000000..9ca3732
--- /dev/null
+++ b/src/lib/libast/sfio/sfsetfd.c
@@ -0,0 +1,136 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Change the file descriptor
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+static int _sfdup(int fd, int newfd)
+#else
+static int _sfdup(fd,newfd)
+int fd;
+int newfd;
+#endif
+{
+ reg int dupfd;
+
+#ifdef F_DUPFD /* the simple case */
+ while((dupfd = sysfcntlf(fd,F_DUPFD,newfd)) < 0 && errno == EINTR)
+ errno = 0;
+ return dupfd;
+
+#else /* do it the hard way */
+ if((dupfd = sysdupf(fd)) < 0 || dupfd >= newfd)
+ return dupfd;
+
+ /* dup() succeeded but didn't get the right number, recurse */
+ newfd = _sfdup(fd,newfd);
+
+ /* close the one that didn't match */
+ CLOSE(dupfd);
+
+ return newfd;
+#endif
+}
+
+#if __STD_C
+int sfsetfd(Sfio_t* f, int newfd)
+#else
+int sfsetfd(f,newfd)
+Sfio_t *f;
+int newfd;
+#endif
+{
+ reg int oldfd;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, -1);
+
+ if(f->flags&SF_STRING)
+ SFMTXRETURN(f, -1);
+
+ if((f->mode&SF_INIT) && f->file < 0)
+ { /* restoring file descriptor after a previous freeze */
+ if(newfd < 0)
+ SFMTXRETURN(f, -1);
+ }
+ else
+ { /* change file descriptor */
+ if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ oldfd = f->file;
+ if(oldfd >= 0)
+ { if(newfd >= 0)
+ { if((newfd = _sfdup(oldfd,newfd)) < 0)
+ { SFOPEN(f,0);
+ SFMTXRETURN(f, -1);
+ }
+ CLOSE(oldfd);
+ }
+ else
+ { /* sync stream if necessary */
+ if(((f->mode&SF_WRITE) && f->next > f->data) ||
+ (f->mode&SF_READ) || f->disc == _Sfudisc)
+ { if(SFSYNC(f) < 0)
+ { SFOPEN(f,0);
+ SFMTXRETURN(f, -1);
+ }
+ }
+
+ if(((f->mode&SF_WRITE) && f->next > f->data) ||
+ ((f->mode&SF_READ) && f->extent < 0 &&
+ f->next < f->endb) )
+ { SFOPEN(f,0);
+ SFMTXRETURN(f, -1);
+ }
+
+#ifdef MAP_TYPE
+ if((f->bits&SF_MMAP) && f->data)
+ { SFMUNMAP(f,f->data,f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+#endif
+
+ /* make stream appears uninitialized */
+ f->endb = f->endr = f->endw = f->data;
+ f->extent = f->here = 0;
+ f->mode = (f->mode&SF_RDWR)|SF_INIT;
+ f->bits &= ~SF_NULL; /* off /dev/null handling */
+ }
+ }
+
+ SFOPEN(f,0);
+ }
+
+ /* notify changes */
+ if(_Sfnotify)
+ (*_Sfnotify)(f, SF_SETFD, (void*)((long)newfd));
+
+ f->file = newfd;
+
+ SFMTXRETURN(f,newfd);
+}
diff --git a/src/lib/libast/sfio/sfsize.c b/src/lib/libast/sfio/sfsize.c
new file mode 100644
index 0000000..7b6d4aa
--- /dev/null
+++ b/src/lib/libast/sfio/sfsize.c
@@ -0,0 +1,109 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Get the size of a stream.
+**
+** Written by Kiem-Phong Vo.
+*/
+#if __STD_C
+Sfoff_t sfsize(Sfio_t* f)
+#else
+Sfoff_t sfsize(f)
+Sfio_t* f;
+#endif
+{
+ Sfdisc_t* disc;
+ reg int mode;
+ Sfoff_t s;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (Sfoff_t)(-1));
+
+ if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0)
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+
+ if(f->flags&SF_STRING)
+ { SFSTRSIZE(f);
+ SFMTXRETURN(f, f->extent);
+ }
+
+ SFLOCK(f,0);
+
+ s = f->here;
+
+ if(f->extent >= 0)
+ { if(f->flags&(SF_SHARE|SF_APPENDWR))
+ { for(disc = f->disc; disc; disc = disc->disc)
+ if(disc->seekf)
+ break;
+ if(!_sys_stat || disc)
+ { Sfoff_t e;
+ if((e = SFSK(f,0,SEEK_END,disc)) >= 0)
+ f->extent = e;
+ if(SFSK(f,f->here,SEEK_SET,disc) != f->here)
+ f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,disc);
+ }
+#if _sys_stat
+ else
+ { sfstat_t st;
+ if(sysfstatf(f->file,&st) < 0)
+ f->extent = -1;
+ else if((f->extent = st.st_size) < f->here)
+ f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,disc);
+ }
+#endif
+ }
+
+ if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC))
+ f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,f->disc);
+ }
+
+ if(f->here != s && (f->mode&SF_READ) )
+ { /* buffered data is known to be invalid */
+#ifdef MAP_TYPE
+ if((f->bits&SF_MMAP) && f->data)
+ { SFMUNMAP(f,f->data,f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+#endif
+ f->next = f->endb = f->endr = f->endw = f->data;
+ }
+
+ if(f->here < 0)
+ f->extent = -1;
+ else if(f->extent < f->here)
+ f->extent = f->here;
+
+ if((s = f->extent) >= 0)
+ { if(f->flags&SF_APPENDWR)
+ s += (f->next - f->data);
+ else if(f->mode&SF_WRITE)
+ { s = f->here + (f->next - f->data);
+ if(s < f->extent)
+ s = f->extent;
+ }
+ }
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, s);
+}
diff --git a/src/lib/libast/sfio/sfsk.c b/src/lib/libast/sfio/sfsk.c
new file mode 100644
index 0000000..4b82a4d
--- /dev/null
+++ b/src/lib/libast/sfio/sfsk.c
@@ -0,0 +1,106 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Seek function that knows discipline
+**
+** Written by Kiem-Phong Vo.
+*/
+#if __STD_C
+Sfoff_t sfsk(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc)
+#else
+Sfoff_t sfsk(f,addr,type,disc)
+Sfio_t* f;
+Sfoff_t addr;
+int type;
+Sfdisc_t* disc;
+#endif
+{
+ Sfoff_t p;
+ reg Sfdisc_t* dc;
+ reg ssize_t s;
+ reg int local, mode;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (Sfoff_t)(-1));
+
+ GETLOCAL(f,local);
+ if(!local && !(f->bits&SF_DCDOWN))
+ { if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0)
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+ if(SFSYNC(f) < 0)
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+#ifdef MAP_TYPE
+ if(f->mode == SF_READ && (f->bits&SF_MMAP) && f->data)
+ { SFMUNMAP(f, f->data, f->endb-f->data);
+ f->data = NIL(uchar*);
+ }
+#endif
+ f->next = f->endb = f->endr = f->endw = f->data;
+ }
+
+ if((type &= (SEEK_SET|SEEK_CUR|SEEK_END)) > SEEK_END)
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+
+ for(;;)
+ { dc = disc;
+ if(f->flags&SF_STRING)
+ { SFSTRSIZE(f);
+ if(type == SEEK_SET)
+ s = (ssize_t)addr;
+ else if(type == SEEK_CUR)
+ s = (ssize_t)(addr + f->here);
+ else s = (ssize_t)(addr + f->extent);
+ }
+ else
+ { SFDISC(f,dc,seekf);
+ if(dc && dc->seekf)
+ { SFDCSK(f,addr,type,dc,p);
+ }
+ else
+ { p = syslseekf(f->file,(sfoff_t)addr,type);
+ }
+ if(p >= 0)
+ SFMTXRETURN(f,p);
+ s = -1;
+ }
+
+ if(local)
+ SETLOCAL(f);
+ switch(_sfexcept(f,SF_SEEK,s,dc))
+ {
+ case SF_EDISC:
+ case SF_ECONT:
+ if(f->flags&SF_STRING)
+ SFMTXRETURN(f, (Sfoff_t)s);
+ goto do_continue;
+ default:
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+ }
+
+ do_continue:
+ for(dc = f->disc; dc; dc = dc->disc)
+ if(dc == disc)
+ break;
+ disc = dc;
+ }
+}
diff --git a/src/lib/libast/sfio/sfstack.c b/src/lib/libast/sfio/sfstack.c
new file mode 100644
index 0000000..bc2ab13
--- /dev/null
+++ b/src/lib/libast/sfio/sfstack.c
@@ -0,0 +1,115 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+
+/* Push/pop streams
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#define STKMTXLOCK(f1,f2) \
+ { if(f1) SFMTXLOCK(f1); \
+ if(f2) SFMTXLOCK(f2); \
+ }
+#define STKMTXRETURN(f1,f2,rv) \
+ { if(f1) SFMTXUNLOCK(f1); \
+ if(f2) SFMTXUNLOCK(f2); \
+ return(rv); \
+ }
+
+#if __STD_C
+Sfio_t* sfstack(Sfio_t* f1, Sfio_t* f2)
+#else
+Sfio_t* sfstack(f1,f2)
+Sfio_t* f1; /* base of stack */
+Sfio_t* f2; /* top of stack */
+#endif
+{
+ reg int n;
+ reg Sfio_t* rf;
+ reg Sfrsrv_t* rsrv;
+ reg Void_t* mtx;
+
+ STKMTXLOCK(f1,f2);
+
+ if(f1 && (f1->mode&SF_RDWR) != f1->mode && _sfmode(f1,0,0) < 0)
+ STKMTXRETURN(f1,f2, NIL(Sfio_t*));
+ if(f2 && (f2->mode&SF_RDWR) != f2->mode && _sfmode(f2,0,0) < 0)
+ STKMTXRETURN(f1,f2, NIL(Sfio_t*));
+ if(!f1)
+ STKMTXRETURN(f1,f2, f2);
+
+ /* give access to other internal functions */
+ _Sfstack = sfstack;
+
+ if(f2 == SF_POPSTACK)
+ { if(!(f2 = f1->push))
+ STKMTXRETURN(f1,f2, NIL(Sfio_t*));
+ f2->mode &= ~SF_PUSH;
+ }
+ else
+ { if(f2->push)
+ STKMTXRETURN(f1,f2, NIL(Sfio_t*));
+ if(f1->pool && f1->pool != &_Sfpool && f1->pool != f2->pool &&
+ f1 == f1->pool->sf[0])
+ { /* get something else to pool front since f1 will be locked */
+ for(n = 1; n < f1->pool->n_sf; ++n)
+ { if(SFFROZEN(f1->pool->sf[n]) )
+ continue;
+ (*_Sfpmove)(f1->pool->sf[n],0);
+ break;
+ }
+ }
+ }
+
+ if(f2->pool && f2->pool != &_Sfpool && f2 != f2->pool->sf[0])
+ (*_Sfpmove)(f2,0);
+
+ /* swap streams */
+ sfswap(f1,f2);
+
+ /* but the reserved buffer and mutex must remain the same */
+ rsrv = f1->rsrv; f1->rsrv = f2->rsrv; f2->rsrv = rsrv;
+ mtx = f1->mutex; f1->mutex = f2->mutex; f2->mutex = mtx;
+
+ SFLOCK(f1,0);
+ SFLOCK(f2,0);
+
+ if(f2->push != f2)
+ { /* freeze the pushed stream */
+ f2->mode |= SF_PUSH;
+ f1->push = f2;
+ rf = f1;
+ }
+ else
+ { /* unfreeze the just exposed stream */
+ f1->mode &= ~SF_PUSH;
+ f2->push = NIL(Sfio_t*);
+ rf = f2;
+ }
+
+ SFOPEN(f1,0);
+ SFOPEN(f2,0);
+
+ STKMTXRETURN(f1,f2, rf);
+}
diff --git a/src/lib/libast/sfio/sfstrtod.c b/src/lib/libast/sfio/sfstrtod.c
new file mode 100644
index 0000000..375d09f
--- /dev/null
+++ b/src/lib/libast/sfio/sfstrtod.c
@@ -0,0 +1,157 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Convert a Sfdouble_t value represented in an ASCII format into
+** the internal Sfdouble_t representation.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#define BATCH (2*sizeof(int)) /* accumulate this many digits at a time */
+#define IPART 0 /* doing integer part */
+#define FPART 1 /* doing fractional part */
+#define EPART 2 /* doing exponent part */
+
+#if __STD_C
+static Sfdouble_t sfpow10(reg int n)
+#else
+static Sfdouble_t sfpow10(n)
+reg int n;
+#endif
+{
+ Sfdouble_t dval;
+
+ switch(n)
+ { case -3: return .001;
+ case -2: return .01;
+ case -1: return .1;
+ case 0: return 1.;
+ case 1: return 10.;
+ case 2: return 100.;
+ case 3: return 1000.;
+ }
+
+ if(n < 0)
+ { dval = .0001;
+ for(n += 4; n < 0; n += 1)
+ dval /= 10.;
+ }
+ else
+ { dval = 10000.;
+ for(n -= 4; n > 0; n -= 1)
+ dval *= 10.;
+ }
+
+ return dval;
+}
+
+#if __STD_C
+Sfdouble_t _sfstrtod(reg const char* s, char** retp)
+#else
+Sfdouble_t _sfstrtod(s,retp)
+reg char* s; /* string to convert */
+char** retp; /* to return the remainder of string */
+#endif
+{
+ reg int n, c, m;
+ reg int mode, fexp, sign, expsign;
+ Sfdouble_t dval;
+#if _lib_locale
+ int decpoint = 0;
+ int thousand = 0;
+ SFSETLOCALE(&decpoint,&thousand);
+#else
+#define decpoint '.'
+#endif
+
+ /* skip initial blanks */
+ while(isspace(*s))
+ ++s;
+
+ /* get the sign */
+ if((sign = (*s == '-')) || *s == '+')
+ s += 1;
+
+ mode = IPART;
+ fexp = expsign = 0;
+ dval = 0.;
+ while(*s)
+ { /* accumulate a handful of the digits */
+ for(m = BATCH, n = 0; m > 0; --m, ++s)
+ { /* get and process a char */
+ c = *s;
+ if(isdigit(c))
+ n = 10*n + (c - '0');
+ else break;
+ }
+
+ /* number of digits accumulated */
+ m = BATCH-m;
+
+ if(mode == IPART)
+ { /* doing the integer part */
+ if(dval == 0.)
+ dval = (Sfdouble_t)n;
+ else dval = dval*sfpow10(m) + (Sfdouble_t)n;
+ }
+ else if(mode == FPART)
+ { /* doing the fractional part */
+ fexp -= m;
+ if(n > 0)
+ dval += n*sfpow10(fexp);
+ }
+ else if(n)
+ { /* doing the exponent part */
+ if(expsign)
+ n = -n;
+ dval *= sfpow10(n);
+ }
+
+ if(!c)
+ break;
+
+ if(m < BATCH)
+ { /* detected a non-digit */
+ if(c == decpoint)
+ { /* start the fractional part or no match */
+ if(mode != IPART)
+ break;
+ mode = FPART;
+ s += 1;
+ }
+ else if(c == 'e' || c == 'E')
+ { if(mode == EPART)
+ break;
+ mode = EPART;
+ c = *++s;
+ if((expsign = (c == '-')) || c == '+')
+ s += 1;
+ }
+ else break;
+ }
+ }
+
+ if(retp)
+ *retp = (char*)s;
+ return sign ? -dval : dval;
+}
diff --git a/src/lib/libast/sfio/sfstrtof.h b/src/lib/libast/sfio/sfstrtof.h
new file mode 100644
index 0000000..37b28ec
--- /dev/null
+++ b/src/lib/libast/sfio/sfstrtof.h
@@ -0,0 +1,568 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * AT&T Research
+ * Glenn Fowler & Phong Vo
+ *
+ * common header and implementation for
+ *
+ * strtof strtod strtold _sfdscan
+ * strntof strntod strntold
+ *
+ * define these macros to instantiate an implementation:
+ *
+ * S2F_function the function name
+ * S2F_static <0:export =0:extern >0:static
+ * S2F_type 0:float 1:double 2:long.double
+ * S2F_qualifier 1 for optional [fFlL] qualifier suffix
+ * S2F_size 1 for interface with size_t second arg
+ * S2F_scan 1 for alternate interface with these arguments:
+ * void* handle
+ * int (*getchar)(void* handle, int flag)
+ * exactly one extra (*getchar)() is done, i.e.,
+ * the caller must do the pushback
+ * flag==0 get next char
+ * flag==1 no number seen
+ * return 0 on error or EOF
+ */
+
+#include "sfhdr.h"
+#include "FEATURE/float"
+
+/*
+ * the default is _sfdscan for standalone sfio compatibility
+ */
+
+#if !defined(S2F_function)
+#define S2F_function _sfdscan
+#define S2F_static 1
+#define S2F_type 2
+#define S2F_scan 1
+#ifndef elementsof
+#define elementsof(a) (sizeof(a)/sizeof(a[0]))
+#endif
+#endif
+
+#if S2F_type == 2 && _ast_fltmax_double
+#undef S2F_type
+#define S2F_type 1
+#endif
+
+#if S2F_type == 0
+#define S2F_number float
+#define S2F_ldexp ldexp
+#define S2F_pow10 _Sffpow10
+#define S2F_inf _Sffinf
+#define S2F_nan _Sffnan
+#define S2F_min (FLT_MIN)
+#define S2F_max (FLT_MAX)
+#define S2F_exp_10_min (FLT_MIN_10_EXP)
+#define S2F_exp_10_max (FLT_MAX_10_EXP)
+#define S2F_exp_2_min (FLT_MIN_EXP)
+#define S2F_exp_2_max (FLT_MAX_EXP)
+#endif
+#if S2F_type == 1
+#define S2F_number double
+#define S2F_ldexp ldexp
+#define S2F_pow10 _Sfdpow10
+#define S2F_inf _Sfdinf
+#define S2F_nan _Sfdnan
+#define S2F_min (DBL_MIN)
+#define S2F_max (DBL_MAX)
+#define S2F_exp_10_min (DBL_MIN_10_EXP)
+#define S2F_exp_10_max (DBL_MAX_10_EXP)
+#define S2F_exp_2_min (DBL_MIN_EXP)
+#define S2F_exp_2_max (DBL_MAX_EXP)
+#endif
+#if S2F_type == 2
+#define S2F_number long double
+#define S2F_ldexp ldexpl
+#define S2F_pow10 _Sflpow10
+#define S2F_inf _Sflinf
+#define S2F_nan _Sflnan
+#define S2F_min (LDBL_MIN)
+#define S2F_max (LDBL_MAX)
+#define S2F_exp_10_min (LDBL_MIN_10_EXP)
+#define S2F_exp_10_max (LDBL_MAX_10_EXP)
+#define S2F_exp_2_min (LDBL_MIN_EXP)
+#define S2F_exp_2_max (LDBL_MAX_EXP)
+#endif
+
+#if -S2F_exp_10_min < S2F_exp_10_max
+#define S2F_exp_10_abs (-S2F_exp_10_min)
+#else
+#define S2F_exp_10_abs S2F_exp_10_max
+#endif
+
+#define S2F_batch _ast_flt_unsigned_max_t
+
+#undef ERR /* who co-opted this namespace? */
+
+#if S2F_scan
+
+typedef int (*S2F_get_f)_ARG_((void*, int));
+
+#define ERR(e)
+#define GET(p) (*get)(p,0)
+#define NON(p) (*get)(p,1)
+#define PUT(p)
+#define REV(p,t,b)
+#define SET(p,t,b)
+
+#else
+
+#define ERR(e) (errno=(e))
+#define NON(p)
+
+#if S2F_size
+#define GET(p) (((p)<(z))?(*p++):(back=0))
+#define PUT(p) (end?(*end=(char*)p-back):(char*)0)
+#define REV(p,t,b) (p=t,back=b)
+#define SET(p,t,b) (t=p,b=back)
+#else
+#define GET(p) (*p++)
+#define PUT(p) (end?(*end=(char*)p-1):(char*)0)
+#define REV(p,t,b) (p=t)
+#define SET(p,t,b) (t=p)
+#endif
+
+#endif
+
+typedef struct S2F_part_s
+{
+ S2F_batch batch;
+ int digits;
+} S2F_part_t;
+
+#if !defined(ERANGE)
+#define ERANGE EINVAL
+#endif
+
+#if S2F_static > 0
+static
+#else
+#if S2F_static < 0 || !defined(S2F_static)
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+extern
+#undef extern
+#endif
+#endif
+S2F_number
+#if S2F_scan
+#if __STD_C
+S2F_function(void* s, S2F_get_f get)
+#else
+S2F_function(s, get) void* s; S2F_get_f get;
+#endif
+#else
+#if S2F_size
+#if __STD_C
+S2F_function(const char* str, size_t size, char** end)
+#else
+S2F_function(str, size, end) char* str; size_t size; char** end;
+#endif
+#else
+#if __STD_C
+S2F_function(const char* str, char** end)
+#else
+S2F_function(str, end) char* str; char** end;
+#endif
+#endif
+#endif
+{
+#if !S2F_scan
+ register unsigned char* s = (unsigned char*)str;
+#if S2F_size
+ register unsigned char* z = s + size;
+ int back = 1;
+ int b;
+#endif
+ unsigned char* t;
+#endif
+ register S2F_batch n;
+ register int c;
+ register int digits;
+ register int m;
+ register unsigned char* cv;
+ int negative;
+ int enegative;
+ int fraction;
+ int decimal = 0;
+ int thousand = 0;
+ int part = 0;
+ int back_part;
+ S2F_batch back_n;
+ S2F_number v;
+ S2F_number p;
+ S2F_part_t parts[16];
+
+ /*
+ * radix char and thousands separator are locale specific
+ */
+
+ SFSETLOCALE(&decimal, &thousand);
+ SFCVINIT();
+
+ /*
+ * skip initial blanks
+ */
+
+ do c = GET(s); while (isspace(c));
+ SET(s, t, b);
+
+ /*
+ * get the sign
+ */
+
+ if ((negative = (c == '-')) || c == '+')
+ c = GET(s);
+
+ /*
+ * drop leading 0's
+ */
+
+ digits = 0;
+ fraction = -1;
+ if (c == '0')
+ {
+ c = GET(s);
+ if (c == 'x' || c == 'X')
+ {
+ /*
+ * hex floating point -- easy
+ */
+
+ cv = _Sfcv36;
+ v = 0;
+ for (;;)
+ {
+ c = GET(s);
+ if ((part = cv[c]) < 16)
+ {
+ digits++;
+ v *= 16;
+ v += part;
+ }
+ else if (c == decimal)
+ {
+ decimal = -1;
+ fraction = digits;
+ }
+ else
+ break;
+ }
+ m = 0;
+ if (c == 'p' || c == 'P')
+ {
+ c = GET(s);
+ if ((enegative = c == '-') || c == '+')
+ c = GET(s);
+ while (c >= '0' && c <= '9')
+ {
+ m = (m << 3) + (m << 1) + (c - '0');
+ c = GET(s);
+ }
+ if (enegative)
+ m = -m;
+ }
+
+#if S2F_qualifier
+
+ /*
+ * consume the optional suffix
+ */
+
+ switch (c)
+ {
+ case 'f':
+ case 'F':
+ case 'l':
+ case 'L':
+ c = GET(s);
+ break;
+ }
+#endif
+ PUT(s);
+ if (v == 0)
+ return negative ? -v : v;
+ if (fraction >= 0)
+ m -= 4 * (digits - fraction);
+ if (m < S2F_exp_2_min)
+ {
+ if ((m -= S2F_exp_2_min) < S2F_exp_2_min)
+ {
+ ERR(ERANGE);
+ return 0;
+ }
+ v = S2F_ldexp(v, S2F_exp_2_min);
+ }
+ else if (m > S2F_exp_2_max)
+ {
+ ERR(ERANGE);
+ return negative ? -S2F_inf : S2F_inf;
+ }
+ v = S2F_ldexp(v, m);
+ goto check;
+ }
+ while (c == '0')
+ c = GET(s);
+ }
+ else if (c == decimal)
+ {
+ decimal = -1;
+ fraction = 0;
+ for (;;)
+ {
+ c = GET(s);
+ if (c != '0')
+ break;
+ digits++;
+ }
+ }
+ else if (c == 'i' || c == 'I')
+ {
+ if ((c = GET(s)) != 'n' && c != 'N' ||
+ (c = GET(s)) != 'f' && c != 'F')
+ {
+ REV(s, t, b);
+ PUT(s);
+ return 0;
+ }
+ c = GET(s);
+ SET(s, t, b);
+ if (((c) == 'i' || c == 'I') &&
+ ((c = GET(s)) == 'n' || c == 'N') &&
+ ((c = GET(s)) == 'i' || c == 'I') &&
+ ((c = GET(s)) == 't' || c == 'T') &&
+ ((c = GET(s)) == 'y' || c == 'Y'))
+ {
+ c = GET(s);
+ SET(s, t, b);
+ }
+ REV(s, t, b);
+ PUT(s);
+ return negative ? -S2F_inf : S2F_inf;
+ }
+ else if (c == 'n' || c == 'N')
+ {
+ if ((c = GET(s)) != 'a' && c != 'A' ||
+ (c = GET(s)) != 'n' && c != 'N')
+ {
+ REV(s, t, b);
+ PUT(s);
+ return 0;
+ }
+ do c = GET(s); while (c && !isspace(c));
+ PUT(s);
+ return negative ? -S2F_nan : S2F_nan;
+ }
+ else if (c < '1' || c > '9')
+ {
+ REV(s, t, b);
+ PUT(s);
+ NON(s);
+ return 0;
+ }
+
+ /*
+ * consume the integral and fractional parts
+ */
+
+ n = 0;
+ m = 0;
+ for (;;)
+ {
+ if (c >= '0' && c <= '9')
+ {
+ digits++;
+ n = (n << 3) + (n << 1) + (c - '0');
+ if (n >= ((~((S2F_batch)0)) / 10) && part < elementsof(parts))
+ {
+ parts[part].batch = n;
+ n = 0;
+ parts[part].digits = digits;
+ part++;
+ }
+ }
+ else if (m && (digits - m) != 3)
+ break;
+ else if (c == decimal)
+ {
+ decimal = -1;
+ thousand = -1;
+ m = 0;
+ fraction = digits;
+ }
+ else if (c != thousand)
+ break;
+ else if (!(m = digits))
+ {
+ SET(s, t, b);
+ break;
+ }
+ else
+ {
+ SET(s, t, b);
+ back_n = n;
+ back_part = part;
+ }
+ c = GET(s);
+ }
+ if (m && (digits - m) != 3)
+ {
+ REV(s, t, b);
+ n = back_n;
+ part = back_part;
+ }
+
+ /*
+ * don't forget the last part
+ */
+
+ if (n && part < elementsof(parts))
+ {
+ parts[part].batch = n;
+ parts[part].digits = digits;
+ part++;
+ }
+
+ /*
+ * consume the exponent
+ */
+
+ if (fraction >= 0)
+ digits = fraction;
+ if (c == 'e' || c == 'E')
+ {
+ c = GET(s);
+ if ((enegative = (c == '-')) || c == '+')
+ c = GET(s);
+ n = 0;
+ while (c >= '0' && c <= '9')
+ {
+ n = (n << 3) + (n << 1) + (c - '0');
+ c = GET(s);
+ }
+ if (enegative)
+ digits -= n;
+ else
+ digits += n;
+ }
+
+#if S2F_qualifier
+
+ /*
+ * consume the optional suffix
+ */
+
+ switch (c)
+ {
+ case 'f':
+ case 'F':
+ case 'l':
+ case 'L':
+ c = GET(s);
+ break;
+ }
+#endif
+ PUT(s);
+
+ /*
+ * adjust for at most one multiply per part
+ * and at most one divide overall
+ */
+
+ v = 0;
+ if (!part)
+ return negative ? -v : v;
+ else if ((m = parts[part-1].digits - digits) > 0)
+ digits += m;
+ else
+ m = 0;
+
+ /*
+ * combine the parts
+ */
+
+ while (part--)
+ {
+ p = parts[part].batch;
+ c = digits - parts[part].digits;
+ if (c > S2F_exp_10_max)
+ {
+ ERR(ERANGE);
+ return negative ? -S2F_inf : S2F_inf;
+ }
+ if (c > 0)
+ {
+#if _ast_mpy_overflow_fpe
+ if ((S2F_max / p) < S2F_pow10[c])
+ {
+ ERR(ERANGE);
+ return negative ? -S2F_inf : S2F_inf;
+ }
+#endif
+ p *= S2F_pow10[c];
+ }
+ v += p;
+ }
+ if (m)
+ {
+ while (m > S2F_exp_10_max)
+ {
+ m -= S2F_exp_10_max;
+ v /= S2F_pow10[S2F_exp_10_max];
+ }
+#if _ast_div_underflow_fpe
+ if ((S2F_min * p) > S2F_pow10[c])
+ {
+ ERR(ERANGE);
+ return negative ? -S2F_inf : S2F_inf;
+ }
+#endif
+ v /= S2F_pow10[m];
+ }
+
+ /*
+ * check the range
+ */
+
+ check:
+ if (v < S2F_min)
+ {
+ ERR(ERANGE);
+ v = 0;
+ }
+ else if (v > S2F_max)
+ {
+ ERR(ERANGE);
+ v = S2F_inf;
+ }
+
+ /*
+ * done
+ */
+
+ return negative ? -v : v;
+}
diff --git a/src/lib/libast/sfio/sfswap.c b/src/lib/libast/sfio/sfswap.c
new file mode 100644
index 0000000..4ffc614
--- /dev/null
+++ b/src/lib/libast/sfio/sfswap.c
@@ -0,0 +1,119 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Swap two streams. If the second argument is NULL,
+** a new stream will be created. Always return the second argument
+** or the new stream. Note that this function will always work
+** unless streams are locked by SF_PUSH.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+Sfio_t* sfswap(reg Sfio_t* f1, reg Sfio_t* f2)
+#else
+Sfio_t* sfswap(f1,f2)
+reg Sfio_t* f1;
+reg Sfio_t* f2;
+#endif
+{
+ Sfio_t tmp;
+ int f1pool, f2pool, f1mode, f2mode, f1flags, f2flags;
+
+ if(!f1 || (f1->mode&SF_AVAIL) || (SFFROZEN(f1) && (f1->mode&SF_PUSH)) )
+ return NIL(Sfio_t*);
+ if(f2 && SFFROZEN(f2) && (f2->mode&SF_PUSH) )
+ return NIL(Sfio_t*);
+ if(f1 == f2)
+ return f2;
+
+ f1mode = f1->mode;
+ SFLOCK(f1,0);
+ f1->mode |= SF_PUSH; /* make sure there is no recursion on f1 */
+
+ if(f2)
+ { f2mode = f2->mode;
+ SFLOCK(f2,0);
+ f2->mode |= SF_PUSH; /* make sure there is no recursion on f2 */
+ }
+ else
+ { f2 = f1->file == 0 ? sfstdin :
+ f1->file == 1 ? sfstdout :
+ f1->file == 2 ? sfstderr : NIL(Sfio_t*);
+ if((!f2 || !(f2->mode&SF_AVAIL)) )
+ { if(!(f2 = (Sfio_t*)malloc(sizeof(Sfio_t))) )
+ { f1->mode = f1mode;
+ SFOPEN(f1,0);
+ return NIL(Sfio_t*);
+ }
+
+ SFCLEAR(f2,NIL(Vtmutex_t*));
+ }
+ f2->mode = SF_AVAIL|SF_LOCK;
+ f2mode = SF_AVAIL;
+ }
+
+ if(!f1->pool)
+ f1pool = -1;
+ else for(f1pool = f1->pool->n_sf-1; f1pool >= 0; --f1pool)
+ if(f1->pool->sf[f1pool] == f1)
+ break;
+ if(!f2->pool)
+ f2pool = -1;
+ else for(f2pool = f2->pool->n_sf-1; f2pool >= 0; --f2pool)
+ if(f2->pool->sf[f2pool] == f2)
+ break;
+
+ f1flags = f1->flags;
+ f2flags = f2->flags;
+
+ /* swap image and pool entries */
+ memcpy((Void_t*)(&tmp),(Void_t*)f1,sizeof(Sfio_t));
+ memcpy((Void_t*)f1,(Void_t*)f2,sizeof(Sfio_t));
+ memcpy((Void_t*)f2,(Void_t*)(&tmp),sizeof(Sfio_t));
+ if(f2pool >= 0)
+ f1->pool->sf[f2pool] = f1;
+ if(f1pool >= 0)
+ f2->pool->sf[f1pool] = f2;
+
+ if(f2flags&SF_STATIC)
+ f2->flags |= SF_STATIC;
+ else f2->flags &= ~SF_STATIC;
+
+ if(f1flags&SF_STATIC)
+ f1->flags |= SF_STATIC;
+ else f1->flags &= ~SF_STATIC;
+
+ if(f2mode&SF_AVAIL) /* swapping to a closed stream */
+ { if(!(f1->flags&SF_STATIC) )
+ free(f1);
+ }
+ else
+ { f1->mode = f2mode;
+ SFOPEN(f1,0);
+ }
+
+ f2->mode = f1mode;
+ SFOPEN(f2,0);
+ return f2;
+}
diff --git a/src/lib/libast/sfio/sfsync.c b/src/lib/libast/sfio/sfsync.c
new file mode 100644
index 0000000..4a9d16f
--- /dev/null
+++ b/src/lib/libast/sfio/sfsync.c
@@ -0,0 +1,172 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Synchronize data in buffers with the file system.
+** If f is nil, all streams are sync-ed
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+static int _sfall(void)
+#else
+static int _sfall()
+#endif
+{
+ reg Sfpool_t *p, *next;
+ reg Sfio_t* f;
+ reg int n, rv;
+ reg int nsync, count, loop;
+#define MAXLOOP 3
+
+ for(loop = 0; loop < MAXLOOP; ++loop)
+ { rv = nsync = count = 0;
+ for(p = &_Sfpool; p; p = next)
+ { /* find the next legitimate pool */
+ for(next = p->next; next; next = next->next)
+ if(next->n_sf > 0)
+ break;
+
+ /* walk the streams for _Sfpool only */
+ for(n = 0; n < ((p == &_Sfpool) ? p->n_sf : 1); ++n)
+ { count += 1;
+ f = p->sf[n];
+
+ if(f->flags&SF_STRING )
+ goto did_sync;
+ if(SFFROZEN(f))
+ continue;
+ if((f->mode&SF_READ) && (f->mode&SF_SYNCED) )
+ goto did_sync;
+ if((f->mode&SF_READ) && !(f->bits&SF_MMAP) &&
+ f->next == f->endb)
+ goto did_sync;
+ if((f->mode&SF_WRITE) && !(f->bits&SF_HOLE) &&
+ f->next == f->data)
+ goto did_sync;
+
+ if(sfsync(f) < 0)
+ rv = -1;
+
+ did_sync:
+ nsync += 1;
+ }
+ }
+
+ if(nsync == count)
+ break;
+ }
+ return rv;
+}
+
+#if __STD_C
+int sfsync(reg Sfio_t* f)
+#else
+int sfsync(f)
+reg Sfio_t* f; /* stream to be synchronized */
+#endif
+{
+ int local, rv, mode, lock;
+ Sfio_t* origf;
+ SFMTXDECL(f);
+
+ if(!(origf = f) )
+ return _sfall();
+
+ SFMTXENTER(origf,-1);
+
+ GETLOCAL(origf,local);
+
+ if(origf->disc == _Sfudisc) /* throw away ungetc */
+ (void)sfclose((*_Sfstack)(origf,NIL(Sfio_t*)));
+
+ rv = 0;
+
+ lock = origf->mode&SF_LOCK;
+ if(origf->mode == (SF_SYNCED|SF_READ) ) /* already synced */
+ goto done;
+
+ if((origf->mode&SF_RDWR) != SFMODE(origf,local) && _sfmode(origf,0,local) < 0)
+ { rv = -1;
+ goto done;
+ }
+
+ for(; f; f = f->push)
+ {
+ if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
+ (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)1),f->disc);
+
+ SFLOCK(f,local);
+
+ /* pretend that this stream is not on a stack */
+ mode = f->mode&SF_PUSH;
+ f->mode &= ~SF_PUSH;
+
+ /* these streams do not need synchronization */
+ if((f->flags&SF_STRING) || (f->mode&SF_SYNCED))
+ goto next;
+
+ if((f->mode&SF_WRITE) && (f->next > f->data || (f->bits&SF_HOLE)) )
+ { /* sync the buffer, make sure pool don't move */
+ reg int pool = f->mode&SF_POOL;
+ f->mode &= ~SF_POOL;
+ if(f->next > f->data && (SFWRALL(f), SFFLSBUF(f,-1)) < 0)
+ rv = -1;
+ if(!SFISNULL(f) && (f->bits&SF_HOLE) )
+ { /* realize a previously created hole of 0's */
+ if(SFSK(f,(Sfoff_t)(-1),SEEK_CUR,f->disc) >= 0)
+ (void)SFWR(f,"",1,f->disc);
+ f->bits &= ~SF_HOLE;
+ }
+ f->mode |= pool;
+ }
+
+ if((f->mode&SF_READ) && f->extent >= 0 &&
+ ((f->bits&SF_MMAP) || f->next < f->endb) )
+ { /* make sure the file pointer is at the right place */
+ f->here -= (f->endb-f->next);
+ f->endr = f->endw = f->data;
+ f->mode = SF_READ|SF_SYNCED|lock;
+ (void)SFSK(f,f->here,SEEK_SET,f->disc);
+
+ if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) &&
+ !(f->bits&SF_MMAP) )
+ { f->endb = f->next = f->data;
+ f->mode &= ~SF_SYNCED;
+ }
+ }
+
+ next:
+ f->mode |= mode;
+ SFOPEN(f,local);
+
+ if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf)
+ (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)0),f->disc);
+ }
+
+done:
+ if(!local && f && (f->mode&SF_POOL) && f->pool && f != f->pool->sf[0])
+ SFSYNC(f->pool->sf[0]);
+
+ SFMTXRETURN(origf, rv);
+}
diff --git a/src/lib/libast/sfio/sftable.c b/src/lib/libast/sfio/sftable.c
new file mode 100644
index 0000000..c165bae
--- /dev/null
+++ b/src/lib/libast/sfio/sftable.c
@@ -0,0 +1,543 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+#include "FEATURE/float"
+
+/* Dealing with $ argument addressing stuffs.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+static char* sffmtint(const char* str, int* v)
+#else
+static char* sffmtint(str, v)
+char* str;
+int* v;
+#endif
+{
+ for(*v = 0; isdigit(*str); ++str)
+ *v = *v * 10 + (*str - '0');
+ *v -= 1;
+ return (char*)str;
+}
+
+#if __STD_C
+static Fmtpos_t* sffmtpos(Sfio_t* f,const char* form,va_list args,Sffmt_t* ft,int type)
+#else
+static Fmtpos_t* sffmtpos(f,form,args,ft,type)
+Sfio_t* f;
+char* form;
+va_list args;
+Sffmt_t* ft;
+int type; /* >0: scanf, =0: printf, -1: internal */
+#endif
+{
+ int base, fmt, flags, dot, width, precis;
+ ssize_t n_str, size;
+ char *t_str, *sp;
+ int v, n, skip, dollar, decimal, thousand;
+ Sffmt_t savft;
+ Fmtpos_t* fp; /* position array of arguments */
+ int argp, argn, maxp, need[FP_INDEX];
+#if _has_multibyte
+ SFMBDCL(fmbs)
+#endif
+
+ if(type < 0)
+ fp = NIL(Fmtpos_t*);
+ else if(!(fp = sffmtpos(f,form,args,ft,-1)) )
+ return NIL(Fmtpos_t*);
+
+ dollar = decimal = thousand = 0; argn = maxp = -1;
+ SFMBCLR(&fmbs);
+ while((n = *form) )
+ { if(n != '%') /* collect the non-pattern chars */
+ { sp = (char*)form;
+ for(;;)
+ { form += SFMBLEN(form, &fmbs);
+ if(*form == 0 || *form == '%')
+ break;
+ }
+ continue;
+ }
+ else form += 1;
+ if(*form == 0)
+ break;
+ else if(*form == '%')
+ { form += 1;
+ continue;
+ }
+
+ if(*form == '*' && type > 0) /* skip in scanning */
+ { skip = 1;
+ form += 1;
+ argp = -1;
+ }
+ else /* get the position of this argument */
+ { skip = 0;
+ sp = sffmtint(form,&argp);
+ if(*sp == '$')
+ { dollar = 1;
+ form = sp+1;
+ }
+ else argp = -1;
+ }
+
+ flags = dot = 0;
+ t_str = NIL(char*); n_str = 0;
+ size = width = precis = base = -1;
+ for(n = 0; n < FP_INDEX; ++n)
+ need[n] = -1;
+
+ loop_flags: /* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */
+ switch((fmt = *form++) )
+ {
+ case LEFTP : /* get the type enclosed in balanced parens */
+ t_str = (char*)form;
+ for(v = 1;;)
+ { switch(*form++)
+ {
+ case 0 : /* not balancable, retract */
+ form = t_str;
+ t_str = NIL(char*);
+ n_str = 0;
+ goto loop_flags;
+ case LEFTP : /* increasing nested level */
+ v += 1;
+ continue;
+ case RIGHTP : /* decreasing nested level */
+ if((v -= 1) != 0)
+ continue;
+ n_str = form-t_str;
+ if(*t_str == '*')
+ { t_str = sffmtint(t_str+1,&n);
+ if(*t_str == '$')
+ dollar = 1;
+ else n = -1;
+ if((n = FP_SET(n,argn)) > maxp)
+ maxp = n;
+ if(fp && fp[n].ft.fmt == 0)
+ { fp[n].ft.fmt = LEFTP;
+ fp[n].ft.form = (char*)form;
+ }
+ need[FP_STR] = n;
+ }
+ goto loop_flags;
+ }
+ }
+
+ case '-' :
+ flags |= SFFMT_LEFT;
+ flags &= ~SFFMT_ZERO;
+ goto loop_flags;
+ case '0' :
+ if(!(flags&SFFMT_LEFT) )
+ flags |= SFFMT_ZERO;
+ goto loop_flags;
+ case ' ' :
+ if(!(flags&SFFMT_SIGN) )
+ flags |= SFFMT_BLANK;
+ goto loop_flags;
+ case '+' :
+ flags |= SFFMT_SIGN;
+ flags &= ~SFFMT_BLANK;
+ goto loop_flags;
+ case '#' :
+ flags |= SFFMT_ALTER;
+ goto loop_flags;
+ case QUOTE:
+ SFSETLOCALE(&decimal,&thousand);
+ if(thousand > 0)
+ flags |= SFFMT_THOUSAND;
+ goto loop_flags;
+
+ case '.' :
+ if((dot += 1) == 2)
+ base = 0; /* for %s,%c */
+ if(isdigit(*form))
+ { fmt = *form++;
+ goto dot_size;
+ }
+ else if(*form != '*')
+ goto loop_flags;
+ else form += 1; /* drop thru below */
+
+ case '*' :
+ form = sffmtint(form,&n);
+ if(*form == '$' )
+ { dollar = 1;
+ form += 1;
+ }
+ else n = -1;
+ if((n = FP_SET(n,argn)) > maxp)
+ maxp = n;
+ if(fp && fp[n].ft.fmt == 0)
+ { fp[n].ft.fmt = '.';
+ fp[n].ft.size = dot;
+ fp[n].ft.form = (char*)form;
+ }
+ if(dot <= 2)
+ need[dot] = n;
+ goto loop_flags;
+
+ case '1' : case '2' : case '3' :
+ case '4' : case '5' : case '6' :
+ case '7' : case '8' : case '9' :
+ dot_size :
+ for(v = fmt - '0', fmt = *form; isdigit(fmt); fmt = *++form)
+ v = v*10 + (fmt - '0');
+ if(dot == 0)
+ width = v;
+ else if(dot == 1)
+ precis = v;
+ else if(dot == 2)
+ base = v;
+ goto loop_flags;
+
+ case 'I' : /* object length */
+ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
+ if(isdigit(*form) )
+ { for(size = 0, n = *form; isdigit(n); n = *++form)
+ size = size*10 + (n - '0');
+ }
+ else if(*form == '*')
+ { form = sffmtint(form+1,&n);
+ if(*form == '$' )
+ { dollar = 1;
+ form += 1;
+ }
+ else n = -1;
+ if((n = FP_SET(n,argn)) > maxp)
+ maxp = n;
+ if(fp && fp[n].ft.fmt == 0)
+ { fp[n].ft.fmt = 'I';
+ fp[n].ft.size = sizeof(int);
+ fp[n].ft.form = (char*)form;
+ }
+ need[FP_SIZE] = n;
+ }
+ goto loop_flags;
+
+ case 'l' :
+ size = -1; flags &= ~SFFMT_TYPES;
+ if(*form == 'l')
+ { form += 1;
+ flags |= SFFMT_LLONG;
+ }
+ else flags |= SFFMT_LONG;
+ goto loop_flags;
+ case 'h' :
+ size = -1; flags &= ~SFFMT_TYPES;
+ if(*form == 'h')
+ { form += 1;
+ flags |= SFFMT_SSHORT;
+ }
+ else flags |= SFFMT_SHORT;
+ goto loop_flags;
+ case 'L' :
+ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE;
+ goto loop_flags;
+ }
+
+ /* set object size for scalars */
+ if(flags & SFFMT_TYPES)
+ { if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n')
+ { if(flags&SFFMT_LONG)
+ size = sizeof(long);
+ else if(flags&SFFMT_SHORT)
+ size = sizeof(short);
+ else if(flags&SFFMT_SSHORT)
+ size = sizeof(char);
+ else if(flags&SFFMT_TFLAG)
+ size = sizeof(ptrdiff_t);
+ else if(flags&SFFMT_ZFLAG)
+ size = sizeof(size_t);
+ else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) )
+ size = sizeof(Sflong_t);
+ else if(flags&SFFMT_IFLAG)
+ { if(size <= 0 ||
+ size == sizeof(Sflong_t)*CHAR_BIT )
+ size = sizeof(Sflong_t);
+ }
+ else if(size < 0)
+ size = sizeof(int);
+ }
+ else if(_Sftype[fmt]&SFFMT_FLOAT)
+ { if(flags&(SFFMT_LONG|SFFMT_LLONG))
+ size = sizeof(double);
+ else if(flags&SFFMT_LDOUBLE)
+ size = sizeof(Sfdouble_t);
+ else if(flags&SFFMT_IFLAG)
+ { if(size <= 0)
+ size = sizeof(Sfdouble_t);
+ }
+ else if(size < 0)
+ size = sizeof(float);
+ }
+ else if(_Sftype[fmt]&SFFMT_CHAR)
+ {
+#if _has_multibyte
+ if((flags&SFFMT_LONG) || fmt == 'C')
+ { size = sizeof(wchar_t) > sizeof(int) ?
+ sizeof(wchar_t) : sizeof(int);
+ } else
+#endif
+ if(size < 0)
+ size = sizeof(int);
+ }
+ }
+
+ if(skip)
+ continue;
+
+ if((argp = FP_SET(argp,argn)) > maxp)
+ maxp = argp;
+
+ if(dollar && fmt == '!')
+ return NIL(Fmtpos_t*);
+
+ if(fp && fp[argp].ft.fmt == 0)
+ { fp[argp].ft.form = (char*)form;
+ fp[argp].ft.fmt = fp[argp].fmt = fmt;
+ fp[argp].ft.size = size;
+ fp[argp].ft.flags = flags;
+ fp[argp].ft.width = width;
+ fp[argp].ft.precis = precis;
+ fp[argp].ft.base = base;
+ fp[argp].ft.t_str = t_str;
+ fp[argp].ft.n_str = n_str;
+ for(n = 0; n < FP_INDEX; ++n)
+ fp[argp].need[n] = need[n];
+ }
+ }
+
+ if(!fp) /* constructing position array only */
+ { if(!dollar || !(fp = (Fmtpos_t*)malloc((maxp+1)*sizeof(Fmtpos_t))) )
+ return NIL(Fmtpos_t*);
+ for(n = 0; n <= maxp; ++n)
+ fp[n].ft.fmt = 0;
+ return fp;
+ }
+
+ /* get value for positions */
+ if(ft)
+ memcpy(&savft, ft, sizeof(*ft));
+ for(n = 0; n <= maxp; ++n)
+ { if(fp[n].ft.fmt == 0) /* gap: pretend it's a 'd' pattern */
+ { fp[n].ft.fmt = 'd';
+ fp[n].ft.width = 0;
+ fp[n].ft.precis = 0;
+ fp[n].ft.base = 0;
+ fp[n].ft.size = 0;
+ fp[n].ft.t_str = 0;
+ fp[n].ft.n_str = 0;
+ fp[n].ft.flags = 0;
+ for(v = 0; v < FP_INDEX; ++v)
+ fp[n].need[v] = -1;
+ }
+
+ if(ft && ft->extf)
+ { fp[n].ft.version = ft->version;
+ fp[n].ft.extf = ft->extf;
+ fp[n].ft.eventf = ft->eventf;
+ if((v = fp[n].need[FP_WIDTH]) >= 0 && v < n)
+ fp[n].ft.width = fp[v].argv.i;
+ if((v = fp[n].need[FP_PRECIS]) >= 0 && v < n)
+ fp[n].ft.precis = fp[v].argv.i;
+ if((v = fp[n].need[FP_BASE]) >= 0 && v < n)
+ fp[n].ft.base = fp[v].argv.i;
+ if((v = fp[n].need[FP_STR]) >= 0 && v < n)
+ fp[n].ft.t_str = fp[v].argv.s;
+ if((v = fp[n].need[FP_SIZE]) >= 0 && v < n)
+ fp[n].ft.size = fp[v].argv.i;
+
+ memcpy(ft,&fp[n].ft,sizeof(Sffmt_t));
+ va_copy(ft->args,args);
+ ft->flags |= SFFMT_ARGPOS;
+ v = (*ft->extf)(f, (Void_t*)(&fp[n].argv), ft);
+ va_copy(args,ft->args);
+ memcpy(&fp[n].ft,ft,sizeof(Sffmt_t));
+ if(v < 0)
+ { memcpy(ft,&savft,sizeof(Sffmt_t));
+ ft = NIL(Sffmt_t*);
+ }
+
+ if(!(fp[n].ft.flags&SFFMT_VALUE) )
+ goto arg_list;
+ else if(_Sftype[fp[n].ft.fmt]&(SFFMT_INT|SFFMT_UINT) )
+ { if(fp[n].ft.size == sizeof(short))
+ { if(_Sftype[fp[n].ft.fmt]&SFFMT_INT)
+ fp[n].argv.i = fp[n].argv.h;
+ else fp[n].argv.i = fp[n].argv.uh;
+ }
+ else if(fp[n].ft.size == sizeof(char))
+ { if(_Sftype[fp[n].ft.fmt]&SFFMT_INT)
+ fp[n].argv.i = fp[n].argv.c;
+ else fp[n].argv.i = fp[n].argv.uc;
+ }
+ }
+ else if(_Sftype[fp[n].ft.fmt]&SFFMT_FLOAT )
+ { if(fp[n].ft.size == sizeof(float) )
+ fp[n].argv.d = fp[n].argv.f;
+ }
+ }
+ else
+ { arg_list:
+ if(fp[n].ft.fmt == LEFTP)
+ { fp[n].argv.s = va_arg(args, char*);
+ fp[n].ft.size = strlen(fp[n].argv.s);
+ }
+ else if(fp[n].ft.fmt == '.' || fp[n].ft.fmt == 'I')
+ fp[n].argv.i = va_arg(args, int);
+ else if(fp[n].ft.fmt == '!')
+ { if(ft)
+ memcpy(ft,&savft,sizeof(Sffmt_t));
+ fp[n].argv.ft = ft = va_arg(args, Sffmt_t*);
+ if(ft->form)
+ ft = NIL(Sffmt_t*);
+ if(ft)
+ memcpy(&savft,ft,sizeof(Sffmt_t));
+ }
+ else if(type > 0) /* from sfvscanf */
+ fp[n].argv.vp = va_arg(args, Void_t*);
+ else switch(_Sftype[fp[n].ft.fmt])
+ { case SFFMT_INT:
+ case SFFMT_UINT:
+#if !_ast_intmax_long
+ if(size == sizeof(Sflong_t) )
+ fp[n].argv.ll = va_arg(args, Sflong_t);
+ else
+#endif
+ if(size == sizeof(long) )
+ fp[n].argv.l = va_arg(args, long);
+ else fp[n].argv.i = va_arg(args, int);
+ break;
+ case SFFMT_FLOAT:
+#if !_ast_fltmax_double
+ if(size == sizeof(Sfdouble_t) )
+ fp[n].argv.ld = va_arg(args,Sfdouble_t);
+ else
+#endif
+ fp[n].argv.d = va_arg(args,double);
+ break;
+ case SFFMT_POINTER:
+ fp[n].argv.vp = va_arg(args,Void_t*);
+ break;
+ case SFFMT_CHAR:
+ if(fp[n].ft.base >= 0)
+ fp[n].argv.s = va_arg(args,char*);
+#if _has_multibyte
+ else if((fp[n].ft.flags & SFFMT_LONG) ||
+ fp[n].ft.fmt == 'C' )
+ { if(sizeof(wchar_t) <= sizeof(int) )
+ fp[n].argv.wc = (wchar_t)va_arg(args,int);
+ else fp[n].argv.wc = va_arg(args,wchar_t);
+ }
+#endif
+ /* observe promotion rule */
+ else fp[n].argv.i = va_arg(args,int);
+ break;
+ default: /* unknown pattern */
+ break;
+ }
+ }
+ }
+
+ if(ft)
+ memcpy(ft,&savft,sizeof(Sffmt_t));
+ return fp;
+}
+
+static const unsigned char flt_nan[] = { _ast_flt_nan_init };
+static const unsigned char flt_inf[] = { _ast_flt_inf_init };
+static const unsigned char dbl_nan[] = { _ast_dbl_nan_init };
+static const unsigned char dbl_inf[] = { _ast_dbl_inf_init };
+#ifdef _ast_ldbl_nan_init
+static const unsigned char ldbl_nan[] = { _ast_ldbl_nan_init };
+static const unsigned char ldbl_inf[] = { _ast_ldbl_inf_init };
+#endif
+
+/* function to initialize conversion tables */
+static int sfcvinit()
+{ reg int d, l;
+
+ for(d = 0; d <= SF_MAXCHAR; ++d)
+ { _Sfcv36[d] = SF_RADIX;
+ _Sfcv64[d] = SF_RADIX;
+ }
+
+ /* [0-9] */
+ for(d = 0; d < 10; ++d)
+ { _Sfcv36[(uchar)_Sfdigits[d]] = d;
+ _Sfcv64[(uchar)_Sfdigits[d]] = d;
+ }
+
+ /* [a-z] */
+ for(; d < 36; ++d)
+ { _Sfcv36[(uchar)_Sfdigits[d]] = d;
+ _Sfcv64[(uchar)_Sfdigits[d]] = d;
+ }
+
+ /* [A-Z] */
+ for(l = 10; d < 62; ++l, ++d)
+ { _Sfcv36[(uchar)_Sfdigits[d]] = l;
+ _Sfcv64[(uchar)_Sfdigits[d]] = d;
+ }
+
+ /* remaining digits */
+ for(; d < SF_RADIX; ++d)
+ { _Sfcv36[(uchar)_Sfdigits[d]] = d;
+ _Sfcv64[(uchar)_Sfdigits[d]] = d;
+ }
+
+ _Sftype['d'] = _Sftype['i'] = SFFMT_INT;
+ _Sftype['u'] = _Sftype['o'] = _Sftype['x'] = _Sftype['X'] = SFFMT_UINT;
+ _Sftype['e'] = _Sftype['E'] = _Sftype['a'] = _Sftype['A'] =
+ _Sftype['g'] = _Sftype['G'] = _Sftype['f'] = SFFMT_FLOAT;
+ _Sftype['s'] = _Sftype['n'] = _Sftype['p'] = _Sftype['!'] = SFFMT_POINTER;
+ _Sftype['c'] = SFFMT_CHAR;
+ _Sftype['['] = SFFMT_CLASS;
+#if _has_multibyte
+ _Sftype['S'] = SFFMT_POINTER;
+ _Sftype['C'] = SFFMT_CHAR;
+#endif
+
+ /* IEEE floating point computed constants */
+
+ memcpy((char*)&_Sffnan, (char*)flt_nan, sizeof(_Sffnan));
+ memcpy((char*)&_Sffinf, (char*)flt_inf, sizeof(_Sffinf));
+ memcpy((char*)&_Sfdnan, (char*)dbl_nan, sizeof(_Sfdnan));
+ memcpy((char*)&_Sfdinf, (char*)dbl_inf, sizeof(_Sfdinf));
+#ifdef _ast_ldbl_nan_init
+ memcpy((char*)&_Sflnan, (char*)ldbl_nan, sizeof(_Sflnan));
+ memcpy((char*)&_Sflinf, (char*)ldbl_inf, sizeof(_Sflinf));
+#else
+ memcpy((char*)&_Sflnan, (char*)dbl_nan, sizeof(_Sfdnan));
+ memcpy((char*)&_Sflinf, (char*)dbl_inf, sizeof(_Sfdinf));
+#endif
+
+ return 1;
+}
+
+/* table for floating point and integer conversions */
+#include "FEATURE/sfinit"
diff --git a/src/lib/libast/sfio/sftell.c b/src/lib/libast/sfio/sftell.c
new file mode 100644
index 0000000..49c183c
--- /dev/null
+++ b/src/lib/libast/sfio/sftell.c
@@ -0,0 +1,59 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Tell the current location in a given stream
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+Sfoff_t sftell(Sfio_t* f)
+#else
+Sfoff_t sftell(f)
+Sfio_t *f;
+#endif
+{
+ reg int mode;
+ Sfoff_t p;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (Sfoff_t)(-1));
+
+ /* set the stream to the right mode */
+ if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0)
+ SFMTXRETURN(f, (Sfoff_t)(-1));
+
+ /* throw away ungetc data */
+ if(f->disc == _Sfudisc)
+ (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*)));
+
+ if(f->flags&SF_STRING)
+ SFMTXRETURN(f, (Sfoff_t)(f->next-f->data));
+
+ /* let sfseek() handle the hard case */
+ if(f->extent >= 0 && (f->flags&(SF_SHARE|SF_APPENDWR)) )
+ p = sfseek(f,(Sfoff_t)0,SEEK_CUR);
+ else p = f->here + ((f->mode&SF_WRITE) ? f->next-f->data : f->next-f->endb);
+
+ SFMTXRETURN(f,p);
+}
diff --git a/src/lib/libast/sfio/sftmp.c b/src/lib/libast/sfio/sftmp.c
new file mode 100644
index 0000000..4f804d6
--- /dev/null
+++ b/src/lib/libast/sfio/sftmp.c
@@ -0,0 +1,402 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Create a temporary stream for read/write.
+** The stream is originally created as a memory-resident stream.
+** When this memory is exceeded, a real temp file will be created.
+** The temp file creation sequence is somewhat convoluted so that
+** pool/stack/discipline will work correctly.
+**
+** Written by David Korn and Kiem-Phong Vo.
+*/
+
+#if _tmp_rmfail
+
+/* File not removable while there is an open file descriptor.
+** To ensure that temp files are properly removed, we need:
+** 1. A discipline to remove a file when the corresponding stream is closed.
+** Care must be taken to close the file descriptor before removing the
+** file because systems such as NT do not allow file removal while
+** there is an open file handle.
+** 2. An atexit() function is set up to close temp files when process exits.
+** 3. On systems with O_TEMPORARY (e.g., NT), this is used to further ensure
+** that temp files will be removed after the last handle is closed.
+*/
+
+typedef struct _file_s File_t;
+struct _file_s
+{ File_t* next; /* link list */
+ Sfio_t* f; /* associated stream */
+ char name[1]; /* temp file name */
+};
+
+static File_t* File; /* list pf temp files */
+
+#if __STD_C
+static int _tmprmfile(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc)
+#else
+static int _tmprmfile(f, type, val, disc)
+Sfio_t* f;
+int type;
+Void_t* val;
+Sfdisc_t* disc;
+#endif
+{
+ reg File_t *ff, *last;
+
+ NOTUSED(val);
+
+ if(type == SF_DPOP) /* don't allow this to pop */
+ return -1;
+
+ if(type == SF_CLOSING)
+ {
+ (void)vtmtxlock(_Sfmutex);
+ for(last = NIL(File_t*), ff = File; ff; last = ff, ff = ff->next)
+ if(ff->f == f)
+ break;
+ if(ff)
+ { if(!last)
+ File = ff->next;
+ else last->next = ff->next;
+
+ if(_Sfnotify)
+ (*_Sfnotify)(f,SF_CLOSING,f->file);
+ CLOSE(f->file);
+ f->file = -1;
+ while(sysremovef(ff->name) < 0 && errno == EINTR)
+ errno = 0;
+
+ free((Void_t*)ff);
+ }
+ (void)vtmtxunlock(_Sfmutex);
+ }
+
+ return 0;
+}
+
+#if __STD_C
+static void _rmfiles(void)
+#else
+static void _rmfiles()
+#endif
+{ reg File_t *ff, *next;
+
+ (void)vtmtxlock(_Sfmutex);
+ for(ff = File; ff; ff = next)
+ { next = ff->next;
+ _tmprmfile(ff->f, SF_CLOSING, NIL(Void_t*), ff->f->disc);
+ }
+ (void)vtmtxunlock(_Sfmutex);
+}
+
+static Sfdisc_t Rmdisc =
+ { NIL(Sfread_f), NIL(Sfwrite_f), NIL(Sfseek_f), _tmprmfile, NIL(Sfdisc_t*) };
+
+#endif /*_tmp_rmfail*/
+
+#if __STD_C
+static int _rmtmp(Sfio_t* f, char* file)
+#else
+static int _rmtmp(f, file)
+Sfio_t* f;
+char* file;
+#endif
+{
+#if _tmp_rmfail /* remove only when stream is closed */
+ reg File_t* ff;
+
+ if(!File)
+ atexit(_rmfiles);
+
+ if(!(ff = (File_t*)malloc(sizeof(File_t)+strlen(file))) )
+ return -1;
+ (void)vtmtxlock(_Sfmutex);
+ ff->f = f;
+ strcpy(ff->name,file);
+ ff->next = File;
+ File = ff;
+ (void)vtmtxunlock(_Sfmutex);
+
+#else /* can remove now */
+ while(sysremovef(file) < 0 && errno == EINTR)
+ errno = 0;
+#endif
+
+ return 0;
+}
+
+#if !_PACKAGE_ast
+#define TMPDFLT "/tmp"
+static char **Tmppath, **Tmpcur;
+
+#if __STD_C
+char** _sfgetpath(char* path)
+#else
+char** _sfgetpath(path)
+char* path;
+#endif
+{ reg char *p, **dirs;
+ reg int n;
+
+ if(!(path = getenv(path)) )
+ return NIL(char**);
+
+ for(p = path, n = 0;;) /* count number of directories */
+ { while(*p == ':')
+ ++p;
+ if(*p == 0)
+ break;
+ n += 1;
+ while(*p && *p != ':') /* skip dir name */
+ ++p;
+ }
+ if(n == 0 || !(dirs = (char**)malloc((n+1)*sizeof(char*))) )
+ return NIL(char**);
+ if(!(p = (char*)malloc(strlen(path)+1)) )
+ { free(dirs);
+ return NIL(char**);
+ }
+ strcpy(p,path);
+ for(n = 0;; ++n)
+ { while(*p == ':')
+ ++p;
+ if(*p == 0)
+ break;
+ dirs[n] = p;
+ while(*p && *p != ':')
+ ++p;
+ if(*p == ':')
+ *p++ = 0;
+ }
+ dirs[n] = NIL(char*);
+
+ return dirs;
+}
+
+#endif /*!_PACKAGE_ast*/
+
+#if __STD_C
+static int _tmpfd(Sfio_t* f)
+#else
+static int _tmpfd(f)
+Sfio_t* f;
+#endif
+{
+ reg char* file;
+ int fd;
+
+#if _PACKAGE_ast
+ if(!(file = pathtemp(NiL,PATH_MAX,NiL,"sf",&fd)))
+ return -1;
+ _rmtmp(f, file);
+ free(file);
+#else
+ int t;
+
+ /* set up path of dirs to create temp files */
+ if(!Tmppath && !(Tmppath = _sfgetpath("TMPPATH")) )
+ { if(!(Tmppath = (char**)malloc(2*sizeof(char*))) )
+ return -1;
+ if(!(file = getenv("TMPDIR")) )
+ file = TMPDFLT;
+ if(!(Tmppath[0] = (char*)malloc(strlen(file)+1)) )
+ { free(Tmppath);
+ Tmppath = NIL(char**);
+ return -1;
+ }
+ strcpy(Tmppath[0],file);
+ Tmppath[1] = NIL(char*);
+ }
+
+ /* set current directory to create this temp file */
+ if(Tmpcur)
+ Tmpcur += 1;
+ if(!Tmpcur || !Tmpcur[0])
+ Tmpcur = Tmppath;
+
+ fd = -1;
+ for(t = 0; t < 10; ++t)
+ { /* compute a random name */
+ static ulong Key, A;
+ if(A == 0 || t > 0) /* get a quasi-random coefficient */
+ { reg int r;
+ A = (ulong)time(NIL(time_t*)) ^ (((ulong)(&t)) >> 3);
+ if(Key == 0)
+ Key = (A >> 16) | ((A&0xffff)<<16);
+ A ^= Key;
+ if((r = (A-1) & 03) != 0) /* Knuth vol.2, page.16, Thm.A */
+ A += 4-r;
+ }
+
+ Key = A*Key + 987654321;
+ file = sfprints("%s/sf%3.3.32lu.%3.3.32lu",
+ Tmpcur[0], (Key>>15)&0x7fff, Key&0x7fff);
+ if(!file)
+ return -1;
+#if _has_oflags
+ if((fd = sysopenf(file,O_RDWR|O_CREAT|O_EXCL|O_TEMPORARY,SF_CREATMODE)) >= 0)
+ break;
+#else
+ if((fd = sysopenf(file,O_RDONLY)) >= 0)
+ { /* file already exists */
+ CLOSE(fd);
+ fd = -1;
+ }
+ else if((fd = syscreatf(file,SF_CREATMODE)) >= 0)
+ { /* reopen for read and write */
+ CLOSE(fd);
+ if((fd = sysopenf(file,O_RDWR)) >= 0)
+ break;
+
+ /* don't know what happened but must remove file */
+ while(sysremovef(file) < 0 && errno == EINTR)
+ errno = 0;
+ }
+#endif /* _has_oflags */
+ }
+ if(fd >= 0)
+ _rmtmp(f, file);
+#endif /* _PACKAGE_ast */
+ return fd;
+}
+
+#if __STD_C
+static int _tmpexcept(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc)
+#else
+static int _tmpexcept(f,type,val,disc)
+Sfio_t* f;
+int type;
+Void_t* val;
+Sfdisc_t* disc;
+#endif
+{
+ reg int fd, m;
+ reg Sfio_t* sf;
+ Sfio_t newf, savf;
+ void (*notifyf)_ARG_((Sfio_t*, int, void*));
+
+ NOTUSED(val);
+
+ /* the discipline needs to change only under the following exceptions */
+ if(type != SF_WRITE && type != SF_SEEK &&
+ type != SF_DPUSH && type != SF_DPOP && type != SF_DBUFFER)
+ return 0;
+
+ /* notify function */
+ notifyf = _Sfnotify;
+
+ /* try to create the temp file */
+ SFCLEAR(&newf,NIL(Vtmutex_t*));
+ newf.flags = SF_STATIC;
+ newf.mode = SF_AVAIL;
+
+ if((fd = _tmpfd(f)) < 0 )
+ return -1;
+
+ /* make sure that the notify function won't be called here since
+ we are only interested in creating the file, not the stream */
+ _Sfnotify = 0;
+ sf = sfnew(&newf,NIL(Void_t*),(size_t)SF_UNBOUND,fd,SF_READ|SF_WRITE);
+ _Sfnotify = notifyf;
+ if(!sf)
+ return -1;
+
+ if(newf.mutex) /* don't need a mutex for this stream */
+ { (void)vtmtxclrlock(newf.mutex);
+ (void)vtmtxclose(newf.mutex);
+ newf.mutex = NIL(Vtmutex_t*);
+ }
+
+ /* make sure that new stream has the same mode */
+ if((m = f->flags&(SF_READ|SF_WRITE)) != (SF_READ|SF_WRITE))
+ sfset(sf, ((~m)&(SF_READ|SF_WRITE)), 0);
+ sfset(sf, (f->mode&(SF_READ|SF_WRITE)), 1);
+
+ /* now remake the old stream into the new image */
+ memcpy((Void_t*)(&savf), (Void_t*)f, sizeof(Sfio_t));
+ memcpy((Void_t*)f, (Void_t*)sf, sizeof(Sfio_t));
+ f->push = savf.push;
+ f->pool = savf.pool;
+ f->rsrv = savf.rsrv;
+ f->proc = savf.proc;
+ f->mutex = savf.mutex;
+ f->stdio = savf.stdio;
+
+ if(savf.data)
+ { SFSTRSIZE(&savf);
+ if(!(savf.flags&SF_MALLOC) )
+ (void)sfsetbuf(f,(Void_t*)savf.data,savf.size);
+ if(savf.extent > 0)
+ (void)sfwrite(f,(Void_t*)savf.data,(size_t)savf.extent);
+ (void)sfseek(f,(Sfoff_t)(savf.next - savf.data),SEEK_SET);
+ if((savf.flags&SF_MALLOC) )
+ free((Void_t*)savf.data);
+ }
+
+ /* announce change of status */
+ if(notifyf)
+ (*notifyf)(f, SF_NEW, (void*)((long)f->file));
+
+ f->disc = disc->disc;
+
+ /* erase all traces of newf */
+ newf.data = newf.endb = newf.endr = newf.endw = NIL(uchar*);
+ newf.file = -1;
+ sfclose(&newf);
+
+ return 1;
+}
+
+#if __STD_C
+Sfio_t* sftmp(size_t s)
+#else
+Sfio_t* sftmp(s)
+size_t s;
+#endif
+{
+ Sfio_t* f;
+ static Sfdisc_t Tmpdisc =
+ { NIL(Sfread_f), NIL(Sfwrite_f), NIL(Sfseek_f), _tmpexcept,
+#if _tmp_rmfail
+ &Rmdisc
+#else
+ NIL(Sfdisc_t*)
+#endif
+ };
+
+ /* start with a memory resident stream */
+ if(!(f = sfnew(NIL(Sfio_t*),NIL(char*),s,-1,SF_STRING|SF_READ|SF_WRITE)) )
+ return NIL(Sfio_t*);
+
+ if(s != (size_t)SF_UNBOUND) /* set up a discipline for out-of-bound, etc. */
+ f->disc = &Tmpdisc;
+
+ /* make the file now */
+ if(s == 0 && _tmpexcept(f,SF_DPOP,NIL(Void_t*),f->disc) < 0)
+ { sfclose(f);
+ return NIL(Sfio_t*);
+ }
+
+ return f;
+}
diff --git a/src/lib/libast/sfio/sfungetc.c b/src/lib/libast/sfio/sfungetc.c
new file mode 100644
index 0000000..08ccc6d
--- /dev/null
+++ b/src/lib/libast/sfio/sfungetc.c
@@ -0,0 +1,108 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Push back one byte to a given SF_READ stream
+**
+** Written by Kiem-Phong Vo.
+*/
+#if __STD_C
+static int _uexcept(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc)
+#else
+static int _uexcept(f,type,val,disc)
+Sfio_t *f;
+int type;
+Void_t* val;
+Sfdisc_t *disc;
+#endif
+{
+ NOTUSED(val);
+
+ /* hmm! This should never happen */
+ if(disc != _Sfudisc)
+ return -1;
+
+ /* close the unget stream */
+ if(type != SF_CLOSING)
+ (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*)));
+
+ return 1;
+}
+
+#if __STD_C
+int sfungetc(Sfio_t* f, int c)
+#else
+int sfungetc(f,c)
+Sfio_t* f; /* push back one byte to this stream */
+int c; /* the value to be pushed back */
+#endif
+{
+ reg Sfio_t* uf;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, -1);
+
+ if(c < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0))
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ /* fast handling of the typical unget */
+ if(f->next > f->data && f->next[-1] == (uchar)c)
+ { f->next -= 1;
+ goto done;
+ }
+
+ /* make a string stream for unget characters */
+ if(f->disc != _Sfudisc)
+ { if(!(uf = sfnew(NIL(Sfio_t*),NIL(char*),(size_t)SF_UNBOUND,
+ -1,SF_STRING|SF_READ)))
+ { c = -1;
+ goto done;
+ }
+ _Sfudisc->exceptf = _uexcept;
+ sfdisc(uf,_Sfudisc);
+ SFOPEN(f,0); (void)sfstack(f,uf); SFLOCK(f,0);
+ }
+
+ /* space for data */
+ if(f->next == f->data)
+ { reg uchar* data;
+ if(f->size < 0)
+ f->size = 0;
+ if(!(data = (uchar*)malloc(f->size+16)))
+ { c = -1;
+ goto done;
+ }
+ f->flags |= SF_MALLOC;
+ if(f->data)
+ memcpy((char*)(data+16),(char*)f->data,f->size);
+ f->size += 16;
+ f->data = data;
+ f->next = data+16;
+ f->endb = data+f->size;
+ }
+
+ *--f->next = (uchar)c;
+done:
+ SFOPEN(f,0);
+ SFMTXRETURN(f, c);
+}
diff --git a/src/lib/libast/sfio/sfvprintf.c b/src/lib/libast/sfio/sfvprintf.c
new file mode 100644
index 0000000..3d1a1bd
--- /dev/null
+++ b/src/lib/libast/sfio/sfvprintf.c
@@ -0,0 +1,1445 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* The engine for formatting data.
+** 1. Argument positioning is done in sftable.c so any changes
+** made here should be reflected in sftable.c as well.
+** 2. For internationalization, Sfio only supports I/O of multibyte strings.
+** However, this code does provide minimal support so that Stdio functions
+** such as fwprintf/swprintf can be emulated (see stdvwprintf()).
+**
+** Written by Kiem-Phong Vo.
+*/
+#define HIGHBITI (~((~((uint)0)) >> 1))
+#define HIGHBITL (~((~((Sfulong_t)0)) >> 1))
+
+#define SFFMT_PREFIX (SFFMT_MINUS|SFFMT_SIGN|SFFMT_BLANK)
+
+#define FPRECIS 6 /* default precision for floats */
+
+#if _PACKAGE_ast
+#include <ccode.h>
+#else
+/* characters when using ebcdic or ascii */
+#if _chr_ebcdic
+#define CC_vt 013 /* vertical tab */
+#define CC_esc 047 /* escape */
+#define CC_bel 057 /* bell */
+#else
+#define CC_vt 013 /* vertical tab */
+#define CC_esc 033 /* escape */
+#define CC_bel 007 /* bell */
+#endif /* _chr_ebcdic */
+#endif /* _PACKAGE_ast */
+
+#if __STD_C
+static int chr2str(char* buf, int v)
+#else
+static int chr2str(buf, v)
+char* buf;
+int v;
+#endif
+{
+ if(isprint(v) && v != '\\')
+ { *buf++ = v;
+ return 1;
+ }
+ else
+ { *buf++ = '\\';
+ switch(v)
+ { case CC_bel: *buf++ = 'a'; return 2;
+ case CC_vt: *buf++ = 'v'; return 2;
+ case CC_esc: *buf++ = 'E'; return 2;
+ case '\b': *buf++ = 'b'; return 2;
+ case '\f': *buf++ = 'f'; return 2;
+ case '\n': *buf++ = 'n'; return 2;
+ case '\r': *buf++ = 'r'; return 2;
+ case '\t': *buf++ = 't'; return 2;
+ case '\\': *buf++ = '\\'; return 2;
+ default: *buf++ = '0' + ((v >> 6) & 03);
+ *buf++ = '0' + ((v >> 3) & 07);
+ *buf++ = '0' + ((v >> 0) & 07);
+ return 4;
+ }
+ }
+}
+
+/* On some platform(s), large functions are not compilable.
+** In such a case, the below macro should be defined non-zero so that
+** some in-lined macros will be made smaller, trading time for space.
+*/
+#if !defined(_sffmt_small) && defined(_UTS)
+#define _sffmt_small 1
+#endif
+
+#if __STD_C
+int sfvprintf(Sfio_t* f, const char* form, va_list args)
+#else
+int sfvprintf(f,form,args)
+Sfio_t* f; /* file to print to */
+char* form; /* format to use */
+va_list args; /* arg list if !argf */
+#endif
+{
+ int n, v, w, k, n_s, base, fmt, flags;
+ Sflong_t lv;
+ char *sp, *ssp, *endsp, *ep, *endep;
+ int dot, width, precis, sign, decpt;
+#if _PACKAGE_ast
+ int scale;
+#endif
+ ssize_t size;
+ Sfdouble_t dval;
+ Void_t* valp;
+ char *tls[2], **ls; /* for %..[separ]s */
+ char* t_str; /* stuff between () */
+ ssize_t n_str; /* its length */
+
+ Argv_t argv; /* for extf to return value */
+ Sffmt_t *ft; /* format environment */
+ Fmt_t *fm, *fmstk; /* stack contexts */
+
+ char* oform; /* original format string */
+ va_list oargs; /* original arg list */
+ Fmtpos_t* fp; /* arg position list */
+ int argp, argn; /* arg position and number */
+
+#define SLACK 1024
+ char buf[SF_MAXDIGITS+SLACK], tmp[SF_MAXDIGITS+1], data[SF_GRAIN];
+ int decimal = 0, thousand = 0;
+
+#if _has_multibyte
+ wchar_t* wsp;
+ SFMBDCL(fmbs) /* state of format string */
+ SFMBDCL(mbs) /* state of some string */
+#ifdef mbwidth
+ char* osp;
+ int n_w, wc;
+#endif
+#endif
+
+ /* local io system */
+ int o, n_output;
+#define SMputc(f,c) { if((o = SFFLSBUF(f,c)) >= 0 ) n_output += 1; \
+ else { SFBUF(f); goto done; } \
+ }
+#define SMnputc(f,c,n) { if((o = SFNPUTC(f,c,n)) > 0 ) n_output += 1; \
+ if(o != n) { SFBUF(f); goto done; } \
+ }
+#define SMwrite(f,s,n) { if((o = SFWRITE(f,(Void_t*)s,n)) > 0 ) n_output += o; \
+ if(o != n) { SFBUF(f); goto done; } \
+ }
+#if _sffmt_small /* these macros are made smaller at some performance cost */
+#define SFBUF(f)
+#define SFINIT(f) (n_output = 0)
+#define SFEND(f)
+#define SFputc(f,c) SMputc(f,c)
+#define SFnputc(f,c,n) SMnputc(f,c,n)
+#define SFwrite(f,s,n) SMwrite(f,s,n)
+#else
+ uchar *d, *endd;
+#define SFBUF(f) (d = f->next, endd = f->endb)
+#define SFINIT(f) (SFBUF(f), n_output = 0)
+#define SFEND(f) ((n_output += d - f->next), (f->next = d))
+#define SFputc(f,c) { if(d < endd) { *d++ = (uchar)c; } \
+ else { SFEND(f); SMputc(f,c); SFBUF(f); } \
+ }
+#define SFnputc(f,c,n) { if(d+n <= endd) { while(n--) *d++ = (uchar)(c); } \
+ else { SFEND(f); SMnputc(f,c,n); SFBUF(f); } \
+ }
+#define SFwrite(f,s,n) { if(d+n <= endd) { while(n--) *d++ = (uchar)(*s++); } \
+ else { SFEND(f); SMwrite(f,s,n); SFBUF(f); } \
+ }
+#endif /* _sffmt_small */
+
+ SFMTXDECL(f);
+
+ SFCVINIT(); /* initialize conversion tables */
+
+ SFMTXENTER(f,-1);
+
+ if(!form)
+ SFMTXRETURN(f, -1);
+
+ /* make sure stream is in write mode and buffer is not NULL */
+ if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0)
+ SFMTXRETURN(f, -1);
+
+ SFLOCK(f,0);
+
+ if(!f->data && !(f->flags&SF_STRING))
+ { f->data = f->next = (uchar*)data;
+ f->endb = f->data+sizeof(data);
+ }
+ SFINIT(f);
+
+ tls[1] = NIL(char*);
+
+ fmstk = NIL(Fmt_t*);
+ ft = NIL(Sffmt_t*);
+
+ oform = (char*)form;
+ va_copy(oargs,args);
+ argn = -1;
+ fp = NIL(Fmtpos_t*);
+
+loop_fmt :
+ SFMBCLR(&fmbs); /* clear multibyte states to parse the format string */
+ while((n = *form) )
+ { if(n != '%') /* collect the non-pattern chars */
+ { sp = (char*)form;
+ do
+ { if((n = SFMBLEN(form, &fmbs)) <= 0)
+ { n = 1;
+ SFMBCLR(&fmbs);
+ }
+ } while(*(form += n) && *form != '%');
+
+ n = form-sp;
+ SFwrite(f,sp,n);
+ continue;
+ }
+ else form += 1;
+
+ flags = 0;
+#if _PACKAGE_ast
+ scale = 0;
+#endif
+ size = width = precis = base = n_s = argp = -1;
+ ssp = _Sfdigits;
+ endep = ep = NIL(char*);
+ endsp = sp = buf+(sizeof(buf)-1);
+ t_str = NIL(char*);
+ n_str = dot = 0;
+
+ loop_flags: /* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */
+ switch((fmt = *form++) )
+ {
+ case '\0':
+ SFputc(f,'%');
+ goto pop_fmt;
+ case '%' :
+ SFputc(f,'%');
+ continue;
+
+ case LEFTP : /* get the type enclosed in balanced parens */
+ t_str = (char*)form;
+ for(v = 1;;)
+ { switch(*form++)
+ {
+ case 0 : /* not balancable, retract */
+ form = t_str;
+ t_str = NIL(char*);
+ n_str = 0;
+ goto loop_flags;
+ case LEFTP : /* increasing nested level */
+ v += 1;
+ continue;
+ case RIGHTP : /* decreasing nested level */
+ if((v -= 1) != 0)
+ continue;
+ if(*t_str != '*' )
+ n_str = (form-1)-t_str;
+ else
+ { t_str = (*_Sffmtintf)(t_str+1,&n);
+ if(*t_str == '$')
+ { if(!fp &&
+ !(fp = (*_Sffmtposf)(f,oform,oargs,ft,0)) )
+ goto pop_fmt;
+ n = FP_SET(n,argn);
+ }
+ else n = FP_SET(-1,argn);
+
+ if(fp)
+ { t_str = fp[n].argv.s;
+ n_str = fp[n].ft.size;
+ }
+ else if(ft && ft->extf )
+ { FMTSET(ft, form,args,
+ LEFTP, 0, 0, 0,0,0,
+ NIL(char*),0);
+ n = (*ft->extf)
+ (f,(Void_t*)&argv,ft);
+ if(n < 0)
+ goto pop_fmt;
+ if(!(ft->flags&SFFMT_VALUE) )
+ goto t_arg;
+ if((t_str = argv.s) &&
+ (n_str = (int)ft->size) < 0)
+ n_str = strlen(t_str);
+ }
+ else
+ { t_arg:
+ if((t_str = va_arg(args,char*)) )
+ n_str = strlen(t_str);
+ }
+ }
+ goto loop_flags;
+ }
+ }
+
+ case '-' :
+ if(dot == 1)
+ { dot = 0;
+ precis = -1;
+ flags |= SFFMT_CHOP;
+ }
+ else
+ flags = (flags & ~(SFFMT_CENTER|SFFMT_ZERO)) | SFFMT_LEFT;
+ goto loop_flags;
+ case '0' :
+ if(!(flags&(SFFMT_LEFT|SFFMT_CENTER)) )
+ flags |= SFFMT_ZERO;
+ goto loop_flags;
+ case ' ' :
+ if(!(flags&SFFMT_SIGN) )
+ flags |= SFFMT_BLANK;
+ goto loop_flags;
+ case '+' :
+ flags = (flags & ~SFFMT_BLANK) | SFFMT_SIGN;
+ goto loop_flags;
+ case '=' :
+ flags = (flags & ~(SFFMT_LEFT|SFFMT_ZERO)) | SFFMT_CENTER;
+ goto loop_flags;
+ case '#' :
+ flags |= SFFMT_ALTER;
+ goto loop_flags;
+ case QUOTE:
+ SFSETLOCALE(&decimal,&thousand);
+ if(thousand > 0)
+ flags |= SFFMT_THOUSAND;
+ goto loop_flags;
+ case ',':
+ SFSETLOCALE(&decimal,&thousand);
+ if(thousand < 0)
+ thousand = fmt;
+ flags |= SFFMT_THOUSAND;
+ goto loop_flags;
+
+ case '.':
+ dot += 1;
+ if(dot == 1)
+ { /* so base can be defined without setting precis */
+ if(*form != '.' && !(flags & SFFMT_CHOP))
+ precis = 0;
+ }
+ else if(dot == 2)
+ { base = 0; /* for %s,%c */
+ v = form[0] == 'l' ? form[1] : form[0];
+ if(v == 'c' || v == 'C' || v == 's' || v == 'S')
+ goto loop_flags;
+ if(*form && !isalnum(*form))
+ { v = form[1] == 'l' ? form[2] : form[1];
+ if(v == 'c' || v == 'C' || v == 's' || v == 'S')
+ { if(*form == '*')
+ goto do_star;
+ else
+ { base = *form++;
+ goto loop_flags;
+ }
+ }
+ }
+ }
+
+ if(isdigit(*form) )
+ { fmt = *form++;
+ goto dot_size;
+ }
+ else if(*form != '*')
+ goto loop_flags;
+ do_star:
+ form += 1; /* fall thru for '*' */
+ case '*' :
+ form = (*_Sffmtintf)(form,&n);
+ if(*form == '$')
+ { form += 1;
+ if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,ft,0)) )
+ goto pop_fmt;
+ n = FP_SET(n,argn);
+ }
+ else n = FP_SET(-1,argn);
+
+ if(fp)
+ v = fp[n].argv.i;
+ else if(ft && ft->extf)
+ { FMTSET(ft, form,args, '.',dot, 0, 0,0,0, NIL(char*), 0);
+ if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0)
+ goto pop_fmt;
+ fmt = ft->fmt;
+ flags = (flags&~SFFMT_TYPES) | (ft->flags&SFFMT_TYPES);
+ if(ft->flags&SFFMT_VALUE)
+ v = argv.i;
+ else v = (dot <= 2) ? va_arg(args,int) : 0;
+ }
+ else v = dot <= 2 ? va_arg(args,int) : 0;
+ goto dot_set;
+
+ case '1' : case '2' : case '3' :
+ case '4' : case '5' : case '6' :
+ case '7' : case '8' : case '9' :
+ dot_size :
+ for(v = fmt - '0'; isdigit(*form); ++form)
+ v = v*10 + (*form - '0');
+ if(*form == '$')
+ { form += 1;
+ if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,ft,0)) )
+ goto pop_fmt;
+ argp = v-1;
+ goto loop_flags;
+ }
+ dot_set :
+ if(dot == 0)
+ { if((width = v) < 0)
+ { width = -width;
+ flags = (flags & ~(SFFMT_CENTER|SFFMT_ZERO)) | SFFMT_LEFT;
+ }
+ }
+ else if(dot == 1)
+ precis = v;
+ else if(dot == 2)
+ base = v;
+ goto loop_flags;
+
+ case 'I' : /* object length */
+ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
+ if(isdigit(*form) )
+ { for(size = 0, n = *form; isdigit(n); n = *++form)
+ size = size*10 + (n - '0');
+ }
+ else if(*form == '*')
+ { form = (*_Sffmtintf)(form+1,&n);
+ if(*form == '$')
+ { form += 1;
+ if(!fp &&
+ !(fp = (*_Sffmtposf)(f,oform,oargs,ft,0)))
+ goto pop_fmt;
+ n = FP_SET(n,argn);
+ }
+ else n = FP_SET(-1,argn);
+
+ if(fp) /* use position list */
+ size = fp[n].argv.i;
+ else if(ft && ft->extf)
+ { FMTSET(ft, form,args, 'I',sizeof(int), 0, 0,0,0,
+ NIL(char*), 0);
+ if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0)
+ goto pop_fmt;
+ if(ft->flags&SFFMT_VALUE)
+ size = argv.i;
+ else size = va_arg(args,int);
+ }
+ else size = va_arg(args,int);
+ }
+ goto loop_flags;
+
+ case 'l' :
+ size = -1; flags &= ~SFFMT_TYPES;
+ if(*form == 'l')
+ { form += 1;
+ flags |= SFFMT_LLONG;
+ }
+ else flags |= SFFMT_LONG;
+ goto loop_flags;
+ case 'h' :
+ size = -1; flags &= ~SFFMT_TYPES;
+ if(*form == 'h')
+ { form += 1;
+ flags |= SFFMT_SSHORT;
+ }
+ else flags |= SFFMT_SHORT;
+ goto loop_flags;
+ case 'L' :
+ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE;
+ goto loop_flags;
+
+ case 'j' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_JFLAG;
+ goto loop_flags;
+ case 'z' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_ZFLAG;
+ goto loop_flags;
+ case 't' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_TFLAG;
+ goto loop_flags;
+ default:
+ break;
+ }
+
+ /* set object size for scalars */
+ if(flags & SFFMT_TYPES)
+ { if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n')
+ { if(flags&SFFMT_LONG)
+ size = sizeof(long);
+ else if(flags&SFFMT_SHORT)
+ size = sizeof(short);
+ else if(flags&SFFMT_SSHORT)
+ size = sizeof(char);
+ else if(flags&SFFMT_TFLAG)
+ size = sizeof(ptrdiff_t);
+ else if(flags&SFFMT_ZFLAG)
+ size = sizeof(size_t);
+ else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) )
+ size = sizeof(Sflong_t);
+ else if(flags&SFFMT_IFLAG)
+ { if(size <= 0 ||
+ size == sizeof(Sflong_t)*CHAR_BIT )
+ size = sizeof(Sflong_t);
+ }
+ else if(size < 0)
+ size = sizeof(int);
+ }
+ else if(_Sftype[fmt]&SFFMT_FLOAT)
+ { if(flags&SFFMT_LDOUBLE)
+ size = sizeof(Sfdouble_t);
+ else if(flags&(SFFMT_LONG|SFFMT_LLONG))
+ size = sizeof(double);
+ else if(flags&SFFMT_IFLAG)
+ { if(size <= 0)
+ size = sizeof(Sfdouble_t);
+ }
+ else if(size < 0)
+ size = sizeof(float);
+ }
+ else if(_Sftype[fmt]&SFFMT_CHAR)
+ {
+#if _has_multibyte
+ if((flags&SFFMT_LONG) || fmt == 'C')
+ { size = sizeof(wchar_t) > sizeof(int) ?
+ sizeof(wchar_t) : sizeof(int);
+ } else
+#endif
+ if(size < 0)
+ size = sizeof(int);
+ }
+ }
+
+ argp = FP_SET(argp,argn);
+ if(fp)
+ { if(ft && ft->extf && fp[argp].ft.fmt != fp[argp].fmt)
+ fmt = fp[argp].ft.fmt;
+ argv = fp[argp].argv;
+ size = fp[argp].ft.size;
+ }
+ else if(ft && ft->extf ) /* extended processing */
+ { FMTSET(ft, form,args, fmt, size,flags, width,precis,base,
+ t_str,n_str);
+ SFEND(f); SFOPEN(f,0);
+ v = (*ft->extf)(f, (Void_t*)(&argv), ft);
+ SFLOCK(f,0); SFBUF(f);
+
+ if(v < 0) /* no further processing */
+ goto pop_fmt;
+ else if(v > 0) /* extf output v bytes */
+ { n_output += v;
+ continue;
+ }
+ else /* extf did not output */
+ { FMTGET(ft, form,args, fmt, size,flags, width,precis,base);
+
+ if(!(ft->flags&SFFMT_VALUE))
+ goto arg_list;
+ else if(_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT) )
+ { if(size == sizeof(short))
+ { if(_Sftype[fmt]&SFFMT_INT)
+ argv.i = argv.h;
+ else argv.i = argv.uh;
+ }
+ else if(size == sizeof(char))
+ { if(_Sftype[fmt]&SFFMT_INT)
+ argv.i = argv.c;
+ else argv.i = argv.uc;
+ }
+ }
+ else if(_Sftype[fmt]&SFFMT_FLOAT )
+ { if(size == sizeof(float) )
+ argv.d = argv.f;
+ }
+ else if(_Sftype[fmt]&SFFMT_CHAR)
+ { if(base < 0)
+ argv.i = (int)argv.c;
+ }
+ }
+ }
+ else
+ { arg_list:
+ switch(_Sftype[fmt])
+ { case SFFMT_INT:
+ case SFFMT_UINT:
+#if !_ast_intmax_long
+ if(size == sizeof(Sflong_t))
+ argv.ll = va_arg(args, Sflong_t);
+ else
+#endif
+ if(size == sizeof(long) )
+ argv.l = va_arg(args, long);
+ else argv.i = va_arg(args, int);
+ break;
+ case SFFMT_FLOAT:
+#if !_ast_fltmax_double
+ if(size == sizeof(Sfdouble_t))
+ argv.ld = va_arg(args,Sfdouble_t);
+ else
+#endif
+ argv.d = va_arg(args,double);
+ break;
+ case SFFMT_POINTER:
+ argv.vp = va_arg(args,Void_t*);
+ break;
+ case SFFMT_CHAR:
+ if(base >= 0)
+ argv.s = va_arg(args,char*);
+#if _has_multibyte
+ else if((flags & SFFMT_LONG) || fmt == 'C')
+ { if(sizeof(wchar_t) <= sizeof(uint) )
+ argv.wc = (wchar_t)va_arg(args,uint);
+ else argv.wc = va_arg(args,wchar_t);
+ }
+#endif
+ else argv.i = va_arg(args,int);
+ break;
+ default: /* unknown pattern */
+ break;
+ }
+ }
+
+ switch(fmt) /* PRINTF DIRECTIVES */
+ {
+ default : /* unknown directive */
+ form -= 1;
+ argn -= 1;
+ continue;
+
+ case '!' : /* stacking a new environment */
+ if(!fp)
+ fp = (*_Sffmtposf)(f,oform,oargs,ft,0);
+ else goto pop_fmt;
+
+ if(!argv.ft)
+ goto pop_fmt;
+ if(!argv.ft->form && ft ) /* change extension functions */
+ { if(ft->eventf &&
+ (*ft->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0)
+ continue;
+ fmstk->ft = ft = argv.ft;
+ }
+ else /* stack a new environment */
+ { if(!(fm = (Fmt_t*)malloc(sizeof(Fmt_t))) )
+ goto done;
+
+ ft = fm->ft = argv.ft;
+ SFMBSET(ft->mbs, &fmbs);
+ if(ft->form)
+ { fm->form = (char*)form; SFMBCPY(&fm->mbs,&fmbs);
+ va_copy(fm->args,args);
+
+ fm->oform = oform;
+ va_copy(fm->oargs,oargs);
+ fm->argn = argn;
+ fm->fp = fp;
+
+ form = ft->form; SFMBCLR(ft->mbs);
+ va_copy(args,ft->args);
+ argn = -1;
+ fp = NIL(Fmtpos_t*);
+ oform = (char*)form;
+ va_copy(oargs,args);
+ }
+ else fm->form = NIL(char*);
+
+ fm->eventf = ft->eventf;
+ fm->next = fmstk;
+ fmstk = fm;
+ }
+ continue;
+
+ case 'S':
+ flags = (flags & ~(SFFMT_TYPES|SFFMT_LDOUBLE)) | SFFMT_LONG;
+ case 's':
+#if _has_multibyte && defined(mbwidth)
+ wc = (flags & SFFMT_LDOUBLE) && mbwide();
+#endif
+ if(base >= 0) /* list of strings */
+ { if(!(ls = argv.sp) || !ls[0])
+ continue;
+ }
+ else
+ { if(!(sp = argv.s))
+ { sp = "(null)";
+ flags &= ~SFFMT_LONG;
+ }
+#if _PACKAGE_ast
+ str_cvt:
+ if(scale)
+ { size = base = -1;
+ flags &= ~SFFMT_LONG;
+ }
+#endif
+ ls = tls; tls[0] = sp;
+ }
+ for(sp = *ls;;)
+ { /* v: number of bytes w: print width of those v bytes */
+#if _has_multibyte
+ if(flags & SFFMT_LONG)
+ { v = 0;
+#ifdef mbwidth
+ w = 0;
+#endif
+ SFMBCLR(&mbs);
+ for(n = 0, wsp = (wchar_t*)sp;; ++wsp, ++n)
+ { if((size >= 0 && n >= size) ||
+ (size < 0 && *wsp == 0) )
+ break;
+ if((n_s = wcrtomb(buf, *wsp, &mbs)) <= 0)
+ break;
+#ifdef mbwidth
+ if(wc)
+ { n_w = mbwidth(*wsp);
+ if(precis >= 0 && (w+n_w) > precis )
+ break;
+ w += n_w;
+ }
+ else
+#endif
+ if(precis >= 0 && (v+n_s) > precis )
+ break;
+ v += n_s;
+ }
+#ifdef mbwidth
+ if(!wc)
+ w = v;
+#endif
+ }
+#ifdef mbwidth
+ else if (wc)
+ { w = 0;
+ SFMBCLR(&mbs);
+ ssp = sp;
+ for(;;)
+ { if((size >= 0 && w >= size) ||
+ (size < 0 && *ssp == 0) )
+ break;
+ osp = ssp;
+ n = mbchar(osp);
+ n_w = mbwidth(n);
+ if(precis >= 0 && (w+n_w) > precis )
+ break;
+ w += n_w;
+ ssp = osp;
+ }
+ v = ssp - sp;
+ }
+#endif
+ else
+#endif
+ { if((v = size) < 0)
+ for(v = 0; v != precis && sp[v]; ++v);
+ if(precis >= 0 && v > precis)
+ v = precis;
+ w = v;
+ }
+
+ if((n = width - w) > 0 && !(flags&SFFMT_LEFT) )
+ { if(flags&SFFMT_CENTER)
+ { n -= (k = n/2);
+ SFnputc(f, ' ', k);
+ }
+ else
+ { SFnputc(f, ' ', n);
+ n = 0;
+ }
+ }
+ if(n < 0 && (flags & SFFMT_CHOP) && width > 0 && precis < 0)
+ {
+#if _has_multibyte
+ if(flags & SFFMT_LONG)
+ { SFMBCLR(&mbs);
+ wsp = (wchar_t*)sp;
+ while(n < 0)
+ {
+#ifdef mbwidth
+ n += mbwidth(*wsp);
+#else
+ n++;
+#endif
+ wsp++;
+ w--;
+ }
+ sp = (char*)wsp;
+ }
+ else if (wc)
+ { SFMBCLR(&mbs);
+ osp = sp;
+ while(n < 0)
+ { ssp = sp;
+ if ((k = mbchar(sp)) <= 0)
+ { sp = ssp;
+ break;
+ }
+#ifdef mbwidth
+ n += mbwidth(k);
+#else
+ n++;
+#endif
+ }
+ v -= (sp - osp);
+ }
+#endif
+ else
+ { sp += -n;
+ v += n;
+ }
+ n = 0;
+ }
+#if _has_multibyte
+ if(flags & SFFMT_LONG)
+ { SFMBCLR(&mbs);
+ for(wsp = (wchar_t*)sp; w > 0; ++wsp, --w)
+ { if((n_s = wcrtomb(buf, *wsp, &mbs)) <= 0)
+ break;
+ sp = buf; SFwrite(f, sp, n_s);
+ }
+ }
+ else
+#endif
+ { SFwrite(f,sp,v); }
+ if(n > 0)
+ { SFnputc(f,' ',n); }
+ if(!(sp = *++ls))
+ break;
+ else if(base > 0)
+ { SFputc(f,base); }
+ }
+ continue;
+
+ case 'C':
+ flags = (flags & ~(SFFMT_TYPES|SFFMT_LDOUBLE)) | SFFMT_LONG;
+ case 'c':
+#if _has_multibyte && defined(mbwidth)
+ wc = (flags & SFFMT_LDOUBLE) && mbwide();
+#endif
+ if(precis <= 0) /* # of times to repeat a character */
+ precis = 1;
+#if _has_multibyte
+ if(flags & SFFMT_LONG)
+ { if(base >= 0)
+ { if(!(wsp = (wchar_t*)argv.s) )
+ continue;
+ for(size = 0; wsp[size]; ++size)
+ ;
+ }
+ else
+ { wsp = &argv.wc;
+ size = 1;
+ }
+ }
+ else
+#endif
+ { if(base >= 0)
+ { if(!(sp = argv.s) )
+ continue;
+ size = strlen(sp);
+ }
+ else
+ { argv.c = (char)(argv.i);
+ sp = &argv.c;
+ size = 1;
+ }
+ }
+
+ while(size > 0)
+ {
+#if _has_multibyte
+ if(flags&SFFMT_LONG)
+ { SFMBCLR(&mbs);
+ if((n_s = wcrtomb(buf, *wsp++, &mbs)) <= 0)
+ break;
+#ifdef mbwidth
+ if(wc)
+ n_s = mbwidth(*(wsp - 1));
+#endif
+ n = width - precis*n_s; /* padding amount */
+ }
+ else
+#endif
+ if(flags&SFFMT_ALTER)
+ { n_s = chr2str(buf, *sp++);
+ n = width - precis*n_s;
+ }
+ else
+ { fmt = *sp++;
+ n = width - precis;
+ }
+
+ if(n > 0 && !(flags&SFFMT_LEFT) )
+ { if(flags&SFFMT_CENTER)
+ { n -= (k = n/2);
+ SFnputc(f, ' ', k);
+ }
+ else
+ { SFnputc(f, ' ', n);
+ n = 0;
+ }
+ }
+
+ v = precis; /* need this because SFnputc may clear it */
+#if _has_multibyte
+ if(flags&SFFMT_LONG)
+ { for(; v > 0; --v)
+ { ssp = buf; k = n_s; SFwrite(f,ssp,k); }
+ }
+ else
+#endif
+ if(flags&SFFMT_ALTER)
+ { for(; v > 0; --v)
+ { ssp = buf; k = n_s; SFwrite(f,ssp,k); }
+ }
+ else
+ { SFnputc(f, fmt, v);
+ }
+
+ if(n > 0)
+ { SFnputc(f,' ',n); };
+
+ if((size -= 1) > 0 && base > 0)
+ { SFputc(f,base); }
+ }
+ continue;
+
+ case 'n': /* return current output length */
+ SFEND(f);
+#if !_ast_intmax_long
+ if(size == sizeof(Sflong_t) )
+ *((Sflong_t*)argv.vp) = (Sflong_t)n_output;
+ else
+#endif
+ if(size == sizeof(long))
+ *((long*)argv.vp) = (long)n_output;
+ else if(size == sizeof(short) )
+ *((short*)argv.vp) = (short)n_output;
+ else if(size == sizeof(uchar) )
+ *((uchar*)argv.vp) = (uchar)n_output;
+ else *((int*)argv.vp) = (int)n_output;
+
+ continue;
+
+ case 'p': /* pointer value */
+ fmt = 'x';
+ base = 16; n_s = 15; n = 4;
+ flags = (flags&~(SFFMT_SIGN|SFFMT_BLANK|SFFMT_ZERO))|SFFMT_ALTER;
+#if _more_void_int
+ lv = (Sflong_t)((Sfulong_t)argv.vp);
+ goto long_cvt;
+#else
+ v = (int)((uint)argv.vp);
+ goto int_cvt;
+#endif
+ case 'o':
+ base = 8; n_s = 7; n = 3;
+ flags &= ~(SFFMT_SIGN|SFFMT_BLANK);
+ goto int_arg;
+ case 'X':
+ ssp = "0123456789ABCDEF";
+ case 'x':
+ base = 16; n_s = 15; n = 4;
+ flags &= ~(SFFMT_SIGN|SFFMT_BLANK);
+ goto int_arg;
+ case 'i':
+#if _PACKAGE_ast
+ if((flags&SFFMT_ALTER) && base < 0)
+ { flags &= ~SFFMT_ALTER;
+ scale = 1024;
+ }
+#endif
+ fmt = 'd';
+ goto d_format;
+ case 'u':
+ flags &= ~(SFFMT_SIGN|SFFMT_BLANK);
+ case 'd':
+ d_format:
+#if _PACKAGE_ast
+ if((flags&SFFMT_ALTER) && base < 0)
+ { flags &= ~SFFMT_ALTER;
+ scale = 1000;
+ }
+#endif
+ if(base < 2 || base > SF_RADIX)
+ base = 10;
+ if((base&(n_s = base-1)) == 0)
+ { if(base < 8)
+ n = base < 4 ? 1 : 2;
+ else if(base < 32)
+ n = base < 16 ? 3 : 4;
+ else n = base < 64 ? 5 : 6;
+ }
+ else n_s = base == 10 ? -1 : 0;
+
+ int_arg:
+#if !_ast_intmax_long || _more_long_int || _more_void_int
+ if(size == sizeof(Sflong_t))
+ { lv = argv.ll;
+ goto long_cvt;
+ }
+ else if(sizeof(long) < sizeof(Sflong_t) && size == sizeof(long))
+ { if(fmt == 'd')
+ lv = (Sflong_t)argv.l;
+ else lv = (Sflong_t)argv.ul;
+ long_cvt:
+#if _PACKAGE_ast
+ if(scale)
+ { sp = fmtscale(lv, scale);
+#if _has_multibyte && defined(mbwidth)
+ wc = 0;
+#endif
+ goto str_cvt;
+ }
+#endif
+ if(lv == 0 && precis == 0)
+ break;
+ if(lv < 0 && fmt == 'd' )
+ { flags |= SFFMT_MINUS;
+ if(lv == HIGHBITL) /* avoid overflow */
+ { lv = (Sflong_t)(HIGHBITL/base);
+ *--sp = _Sfdigits[HIGHBITL -
+ ((Sfulong_t)lv)*base];
+ }
+ else lv = -lv;
+ }
+ if(n_s < 0) /* base 10 */
+ { Sflong_t nv;
+ sfucvt(lv,sp,nv,ssp,Sflong_t,Sfulong_t);
+ }
+ else if(n_s > 0) /* base power-of-2 */
+ { do
+ { *--sp = ssp[lv&n_s];
+ } while((lv = ((Sfulong_t)lv) >> n) );
+ }
+ else /* general base */
+ { do
+ { *--sp = ssp[((Sfulong_t)lv)%base];
+ } while((lv = ((Sfulong_t)lv)/base) );
+ }
+ } else
+#endif
+ if(sizeof(short) < sizeof(int) && size == sizeof(short) )
+ { if(fmt == 'd')
+ v = (int)((short)argv.i);
+ else v = (int)((ushort)argv.i);
+ goto int_cvt;
+ }
+ else if(size == sizeof(char))
+ { if(fmt != 'd')
+ v = (int)((uchar)argv.i);
+ else
+ {
+#if _key_signed
+ v = (int)((signed char)argv.i);
+#else
+ if(argv.i < 0)
+ v = -((int)((char)(-argv.i)));
+ else v = ((int)((char)( argv.i)));
+#endif
+ }
+ goto int_cvt;
+ }
+ else
+ { v = argv.i;
+ int_cvt:
+#if _PACKAGE_ast
+ if(scale)
+ { sp = fmtscale(v, scale);
+#if _has_multibyte && defined(mbwidth)
+ wc = 0;
+#endif
+ goto str_cvt;
+ }
+#endif
+ if(v == 0 && precis == 0)
+ break;
+ if(v < 0 && fmt == 'd' )
+ { flags |= SFFMT_MINUS;
+ if(v == HIGHBITI) /* avoid overflow */
+ { v = (int)(HIGHBITI/base);
+ *--sp = _Sfdigits[HIGHBITI -
+ ((uint)v)*base];
+ }
+ else v = -v;
+ }
+ if(n_s < 0) /* base 10 */
+ { sfucvt(v,sp,n,ssp,int,uint);
+ }
+ else if(n_s > 0) /* base power-of-2 */
+ { do
+ { *--sp = ssp[v&n_s];
+ } while((v = ((uint)v) >> n) );
+ }
+ else /* n_s == 0, general base */
+ { do
+ { *--sp = ssp[((uint)v)%base];
+ } while((v = ((uint)v)/base) );
+ }
+ }
+
+ if(n_s < 0 && (flags&SFFMT_THOUSAND) && (n = endsp-sp) > 3)
+ { if((n %= 3) == 0)
+ n = 3;
+ for(ep = buf+SLACK, endep = ep + n; ; )
+ { while(ep < endep)
+ *ep++ = *sp++;
+ if(sp == endsp)
+ break;
+ if(sp <= endsp-3)
+ *ep++ = thousand;
+ endep = ep+3;
+ }
+ sp = buf+SLACK;
+ endsp = ep;
+ }
+
+ /* zero padding for precision if have room in buffer */
+ if(precis > 0 && (precis -= (endsp-sp)) < (sp-buf)-64)
+ while(precis-- > 0)
+ *--sp = '0';
+
+ if(flags&SFFMT_ALTER) /* prefix */
+ { if(fmt == 'o')
+ { if(*sp != '0')
+ *--sp = '0';
+ }
+ else
+ { if(width > 0 && (flags&SFFMT_ZERO))
+ { /* do 0 padding first */
+ if(fmt == 'x' || fmt == 'X')
+ n = 0;
+ else if(dot < 2)
+ n = width;
+ else n = base < 10 ? 2 : 3;
+ n += (flags&(SFFMT_MINUS|SFFMT_SIGN)) ?
+ 1 : 0;
+ n = width - (n + (endsp-sp));
+ while(n-- > 0)
+ *--sp = '0';
+ }
+ if(fmt == 'x' || fmt == 'X')
+ { *--sp = (char)fmt;
+ *--sp = '0';
+ }
+ else if(dot >= 2)
+ { /* base#value notation */
+ *--sp = '#';
+ if(base < 10)
+ *--sp = (char)('0'+base);
+ else
+ { *--sp = _Sfdec[(base <<= 1)+1];
+ *--sp = _Sfdec[base];
+ }
+ }
+ }
+ }
+
+ break;
+
+ case 'g': case 'G': /* these ultimately become %e or %f */
+ case 'a': case 'A':
+ case 'e': case 'E':
+ case 'f': case 'F':
+#if !_ast_fltmax_double
+ if(size == sizeof(Sfdouble_t) )
+ { v = SFFMT_LDOUBLE;
+ valp = &argv.ld;
+ dval = argv.ld;
+ }
+ else
+#endif
+ { v = 0;
+ valp = &argv.d;
+ dval = argv.d;
+ }
+
+ if(fmt == 'e' || fmt == 'E' && (v |= SFFMT_UPPER))
+ { v |= SFFMT_EFORMAT;
+ n = (precis = precis < 0 ? FPRECIS : precis)+1;
+ ep = _sfcvt(valp,tmp+1,sizeof(tmp)-1, min(n,SF_FDIGITS),
+ &decpt, &sign, &n_s, v);
+ goto e_format;
+ }
+ else if(fmt == 'f' || fmt == 'F' && (v |= SFFMT_UPPER))
+ { precis = precis < 0 ? FPRECIS : precis;
+ ep = _sfcvt(valp,tmp+1,sizeof(tmp)-1, min(precis,SF_FDIGITS),
+ &decpt, &sign, &n_s, v);
+ goto f_format;
+ }
+ else if(fmt == 'a' || fmt == 'A' && (v |= SFFMT_UPPER))
+ { v |= SFFMT_AFORMAT;
+ if(precis < 0)
+ { if(v & SFFMT_LDOUBLE)
+ precis = 2*(sizeof(Sfdouble_t) - 2);
+ else precis = 2*(sizeof(double) - 2);
+ }
+ n = precis + 1;
+ ep = _sfcvt(valp,tmp+1,sizeof(tmp)-1, min(n,SF_FDIGITS),
+ &decpt, &sign, &n_s, v);
+
+ sp = endsp = buf+1; /* reserve space for sign */
+ *endsp++ = '0';
+ *endsp++ = fmt == 'a' ? 'x' : 'X';
+ if (!isxdigit(*ep))
+ goto infinite;
+ if (base < 0)
+ base = 0;
+ goto a_format;
+ }
+ else /* 'g' or 'G' format */
+ { precis = precis < 0 ? FPRECIS : precis == 0 ? 1 : precis;
+ if(fmt == 'G')
+ v |= SFFMT_UPPER;
+ v |= SFFMT_EFORMAT;
+ ep = _sfcvt(valp,tmp+1,sizeof(tmp)-1, min(precis,SF_FDIGITS),
+ &decpt, &sign, &n_s, v);
+ if(dval == 0.)
+ decpt = 1;
+ else if(*ep == 'I')
+ goto infinite;
+
+ if(!(flags&SFFMT_ALTER))
+ { /* zap trailing 0s */
+ if((n = n_s) > precis)
+ n = precis;
+ while((n -= 1) >= 1 && ep[n] == '0')
+ ;
+ n += 1;
+ }
+ else n = precis;
+
+ if(decpt < -3 || decpt > precis)
+ { precis = n-1;
+ goto e_format;
+ }
+ else
+ { precis = n - decpt;
+ goto f_format;
+ }
+ }
+
+ e_format: /* build the x.yyyy string */
+ if(isalpha(*ep))
+ goto infinite;
+ sp = endsp = buf+1; /* reserve space for sign */
+ if (base <= 0)
+ base = 2;
+ a_format:
+ *endsp++ = *ep ? *ep++ : '0';
+
+ SFSETLOCALE(&decimal,&thousand);
+ if(precis > 0 || (flags&SFFMT_ALTER))
+ *endsp++ = decimal;
+ ssp = endsp;
+ endep = ep+precis;
+ while((*endsp++ = *ep++) && ep <= endep)
+ ;
+ precis -= (endsp -= 1) - ssp;
+
+ /* build the exponent */
+ ep = endep = buf+(sizeof(buf)-1);
+ if(dval != 0.)
+ { if((n = decpt - 1) < 0)
+ n = -n;
+ while(n > 9)
+ { v = n; n /= 10;
+ *--ep = (char)('0' + (v - n*10));
+ }
+ }
+ else n = 0;
+ *--ep = (char)('0' + n);
+ while((endep-ep) < base && ep > (buf+2)) /* at least base digits in exponent */
+ *--ep = '0';
+
+ /* the e/Exponent separator and sign */
+ *--ep = (decpt > 0 || dval == 0.) ? '+' : '-';
+ *--ep = fmt == 'a' ? 'p' : fmt == 'A' ? 'P' :
+ isupper(fmt) ? 'E' : 'e';
+
+ goto end_aefg;
+
+ f_format: /* data before the decimal point */
+ if(isalpha(*ep))
+ {
+ infinite:
+ flags &= ~SFFMT_ZERO;
+ endsp = (sp = ep)+sfslen();
+ ep = endep;
+ precis = 0;
+ goto end_aefg;
+ }
+
+ SFSETLOCALE(&decimal,&thousand);
+ endsp = sp = buf+1; /* save a space for sign */
+ endep = ep+decpt;
+ if(decpt > 3 && (flags&SFFMT_THOUSAND) )
+ { if((n = decpt%3) == 0)
+ n = 3;
+ while(ep < endep && (*endsp++ = *ep++) )
+ { if(--n == 0 && (ep <= endep-3) )
+ { *endsp++ = thousand;
+ n = 3;
+ }
+ }
+ }
+ else
+ { while(ep < endep && (*endsp++ = *ep++))
+ ;
+ }
+ if(endsp == sp)
+ *endsp++ = '0';
+
+ if(precis > 0 || (flags&SFFMT_ALTER))
+ *endsp++ = decimal;
+
+ if((n = -decpt) > 0)
+ { /* output zeros for negative exponent */
+ ssp = endsp + min(n,precis);
+ precis -= n;
+ while(endsp < ssp)
+ *endsp++ = '0';
+ }
+
+ ssp = endsp;
+ endep = ep+precis;
+ while((*endsp++ = *ep++) && ep <= endep)
+ ;
+ precis -= (endsp -= 1) - ssp;
+ ep = endep;
+ end_aefg:
+ flags |= SFFMT_FLOAT;
+ if(sign)
+ flags |= SFFMT_MINUS;
+ break;
+ }
+
+ if(flags == 0 && width <= 0)
+ goto do_output;
+
+ if(flags&SFFMT_PREFIX)
+ fmt = (flags&SFFMT_MINUS) ? '-' : (flags&SFFMT_SIGN) ? '+' : ' ';
+
+ n = (endsp-sp) + (endep-ep) + (precis <= 0 ? 0 : precis) +
+ ((flags&SFFMT_PREFIX) ? 1 : 0);
+ if((v = width-n) <= 0)
+ v = 0;
+ else if(!(flags&SFFMT_ZERO)) /* right padding */
+ { if(flags&SFFMT_LEFT)
+ v = -v;
+ else if(flags&SFFMT_PREFIX) /* blank padding, output prefix now */
+ { *--sp = fmt;
+ flags &= ~SFFMT_PREFIX;
+ }
+ }
+
+ if(flags&SFFMT_PREFIX) /* put out the prefix */
+ { SFputc(f,fmt);
+ if(fmt != ' ')
+ flags |= SFFMT_ZERO;
+ }
+
+ if((n = v) > 0) /* left padding */
+ { v = (flags&SFFMT_ZERO) ? '0' : ' ';
+ SFnputc(f,v,n);
+ }
+
+ if((n = precis) > 0 && !(flags&SFFMT_FLOAT))
+ { /* padding for integer precision */
+ SFnputc(f,'0',n);
+ precis = 0;
+ }
+
+ do_output:
+ if((n = endsp-sp) > 0)
+ SFwrite(f,sp,n);
+
+ if(flags&(SFFMT_FLOAT|SFFMT_LEFT))
+ { /* SFFMT_FLOAT: right padding for float precision */
+ if((n = precis) > 0)
+ SFnputc(f,'0',n);
+
+ /* SFFMT_FLOAT: the exponent of %eE */
+ if((n = endep - (sp = ep)) > 0)
+ SFwrite(f,sp,n);
+
+ /* SFFMT_LEFT: right padding */
+ if((n = -v) > 0)
+ { SFnputc(f,' ',n); }
+ }
+ }
+
+pop_fmt:
+ if(fp)
+ { free(fp);
+ fp = NIL(Fmtpos_t*);
+ }
+ while((fm = fmstk) ) /* pop the format stack and continue */
+ { if(fm->eventf)
+ { if(!form || !form[0])
+ (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),ft);
+ else if((*fm->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0)
+ goto loop_fmt;
+ }
+
+ fmstk = fm->next;
+ if((form = fm->form) )
+ { SFMBCPY(&fmbs,&fm->mbs);
+ va_copy(args, fm->args);
+ oform = fm->oform;
+ va_copy(oargs,fm->oargs);
+ argn = fm->argn;
+ fp = fm->fp;
+ }
+ ft = fm->ft;
+ free(fm);
+ if(form && form[0])
+ goto loop_fmt;
+ }
+
+done:
+ if(fp)
+ free(fp);
+ while((fm = fmstk) )
+ { if(fm->eventf)
+ (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),fm->ft);
+ fmstk = fm->next;
+ free(fm);
+ }
+
+ SFEND(f);
+
+ n = f->next - f->data;
+ if((sp = (char*)f->data) == data)
+ f->endw = f->endr = f->endb = f->data = NIL(uchar*);
+ f->next = f->data;
+
+ if((((flags = f->flags)&SF_SHARE) && !(flags&SF_PUBLIC) ) ||
+ (n > 0 && (sp == data || (flags&SF_LINE) ) ) )
+ (void)SFWRITE(f,(Void_t*)sp,n);
+ else f->next += n;
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f, n_output);
+}
diff --git a/src/lib/libast/sfio/sfvscanf.c b/src/lib/libast/sfio/sfvscanf.c
new file mode 100644
index 0000000..c0a1a0b
--- /dev/null
+++ b/src/lib/libast/sfio/sfvscanf.c
@@ -0,0 +1,1100 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* The main engine for reading formatted data
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#define MAXWIDTH (int)(((uint)~0)>>1) /* max amount to scan */
+
+/*
+ * pull in a private strtold()
+ */
+
+#include "sfstrtof.h"
+
+/* refresh stream buffer - taking care of unseekable/share streams too */
+#if __STD_C
+static void _sfbuf(Sfio_t* f, int* peek)
+#else
+static void _sfbuf(f, peek)
+Sfio_t* f;
+int* peek;
+#endif
+{
+ if(f->next >= f->endb)
+ { if(*peek) /* try peeking for a share stream if possible */
+ { f->mode |= SF_RV;
+ if(SFFILBUF(f,-1) > 0)
+ { f->mode |= SF_PEEK;
+ return;
+ }
+ *peek = 0; /* can't peek, back to normal reads */
+ }
+ (void)SFFILBUF(f,-1);
+ }
+}
+
+/* buffer used during scanning of a double value or a multi-byte
+ character. the fields mirror certain local variables in sfvscanf. */
+typedef struct _scan_s
+{ int error; /* get set by _sfdscan if no value specified */
+ int inp; /* last input character read */
+ int width; /* field width */
+ Sfio_t *f; /* stream being scanned */
+ uchar *d, *endd, *data; /* local buffering system */
+ int peek; /* != 0 if unseekable/share stream */
+ int n_input;/* number of input bytes processed */
+} Scan_t;
+
+/* ds != 0 for scanning double values */
+#define SCinit(sc,ds) ((sc)->inp = (sc)->error = -1, (sc)->f = f, \
+ ((sc)->width = (ds) ? width : -1), \
+ (sc)->d = d, (sc)->endd = endd, (sc)->data = data, \
+ (sc)->peek = peek, (sc)->n_input = n_input)
+#define SCend(sc,ds) (inp = (sc)->inp, f = (sc)->f, \
+ (width = (ds) ? (sc)->width : width), \
+ d = (sc)->d, endd = (sc)->endd, data = (sc)->data, \
+ peek = (sc)->peek, n_input = (sc)->n_input)
+
+#if __STD_C
+static int _scgetc(void* arg, int flag)
+#else
+static int _scgetc(arg, flag)
+void* arg;
+int flag;
+#endif
+{
+ Scan_t *sc = (Scan_t*)arg;
+
+ if (flag)
+ { sc->error = flag;
+ return 0;
+ }
+
+ /* if width >= 0, do not allow to exceed width number of bytes */
+ if(sc->width == 0)
+ { sc->inp = -1;
+ return 0;
+ }
+
+ if(sc->d >= sc->endd) /* refresh local buffer */
+ { sc->n_input += sc->d - sc->data;
+ if(sc->peek)
+ SFREAD(sc->f, sc->data, sc->d - sc->data);
+ else sc->f->next = sc->d;
+
+ _sfbuf(sc->f, &sc->peek);
+ sc->data = sc->d = sc->f->next;
+ sc->endd = sc->f->endb;
+
+ if(sc->d >= sc->endd)
+ { sc->inp = -1;
+ return 0;
+ }
+ }
+
+ if((sc->width -= 1) >= 0) /* from _sfdscan */
+ return (sc->inp = (int)(*sc->d++));
+ else return ((int)(*sc->d++));
+}
+
+/* structure to match characters in a character class */
+typedef struct _accept_s
+{ char ok[SF_MAXCHAR+1];
+ int yes;
+ char *form, *endf;
+#if _has_multibyte
+ wchar_t wc;
+#endif
+} Accept_t;
+
+#if __STD_C
+static char* _sfsetclass(const char* form, Accept_t* ac, int flags)
+#else
+static char* _sfsetclass(form, ac, flags)
+char* form; /* format string */
+Accept_t* ac; /* values of accepted characters */
+int flags; /* SFFMT_LONG for wchar_t */
+#endif
+{
+ int c, endc, n;
+#if _has_multibyte
+ SFMBDCL(mbs)
+#endif
+
+ if(*form == '^') /* complementing this set */
+ { ac->yes = 0;
+ form += 1;
+ }
+ else ac->yes = 1;
+
+ for(c = 0; c <= SF_MAXCHAR; ++c)
+ ac->ok[c] = !ac->yes;
+
+ if(*form == ']' || *form == '-') /* special first char */
+ { ac->ok[*form] = ac->yes;
+ form += 1;
+ }
+ ac->form = (char*)form;
+
+ if(flags&SFFMT_LONG)
+ SFMBCLR(&mbs);
+ for(n = 1; *form != ']'; form += n)
+ { if((c = *((uchar*)form)) == 0)
+ return NIL(char*);
+
+ if(*(form+1) == '-')
+ { endc = *((uchar*)(form+2));
+#if _has_multibyte
+ if(c >= 128 || endc >= 128 ) /* range must be ascii */
+ goto one_char;
+#endif
+ for(; c <= endc; ++c)
+ ac->ok[c] = ac->yes;
+ n = 3;
+ }
+ else
+ { one_char:
+#if _has_multibyte /* true multi-byte chars must be checked differently */
+ if((flags&SFFMT_LONG) && (n = (int)SFMBLEN(form,&mbs)) <= 0)
+ return NIL(char*);
+ if(n == 1)
+#endif
+ ac->ok[c] = ac->yes;
+ }
+ }
+
+ ac->endf = (char*)form;
+ return (char*)(form+1);
+}
+
+#if _has_multibyte
+#if __STD_C
+static int _sfwaccept(wchar_t wc, Accept_t* ac)
+#else
+static int _sfwaccept(wc, ac)
+wchar_t wc;
+Accept_t* ac;
+#endif
+{
+ int endc, c, n;
+ wchar_t fwc;
+ char *form = ac->form;
+ SFMBDCL(mbs)
+
+ SFMBCLR(&mbs);
+ for(n = 1; *form != ']'; form += n)
+ { if((c = *((uchar*)form)) == 0)
+ return 0;
+
+ if(*(form+1) == '-')
+ { endc = *((uchar*)(form+2));
+ if(c >= 128 || endc >= 128 ) /* range must be ascii */
+ goto one_char;
+ n = 3;
+ }
+ else
+ { one_char:
+ if((n = mbrtowc(&fwc, form, ac->endf-form, &mbs)) > 1 &&
+ wc == fwc )
+ return ac->yes;
+ }
+ }
+
+ return !ac->yes;
+}
+
+#if _has_multibyte == 1
+#define SFgetwc(sc,wc,fmt,ac,mbs) _sfgetwc(sc,wc,fmt,ac,(Void_t*)(mbs))
+#else
+#define SFgetwc(sc,wc,fmt,ac,mbs) _sfgetwc(sc,wc,fmt,ac,NIL(Void_t*))
+#endif
+
+#if __STD_C
+static int _sfgetwc(Scan_t* sc, wchar_t* wc, int fmt, Accept_t* ac, Void_t *mbs)
+#else
+static int _sfgetwc(sc, wc, fmt, ac, mbs)
+Scan_t* sc; /* the scanning handle */
+wchar_t* wc; /* to return a scanned wchar_t */
+int fmt; /* %s, %c, %[ */
+Accept_t* ac; /* accept handle for %[ */
+Void_t* mbs; /* multibyte parsing state */
+#endif
+{
+ int n, v;
+ char b[16]; /* assuming that SFMBMAX <= 16! */
+
+ /* shift left data so that there will be more room to back up on error.
+ this won't help streams with small buffers - c'est la vie! */
+ if(sc->d > sc->f->data && (n = sc->endd - sc->d) > 0 && n < SFMBMAX)
+ { memcpy(sc->f->data, sc->d, n);
+ if(sc->f->endr == sc->f->endb)
+ sc->f->endr = sc->f->data+n;
+ if(sc->f->endw == sc->f->endb)
+ sc->f->endw = sc->f->data+n;
+ sc->f->endb = sc->f->data+n;
+ sc->d = sc->data = sc->f->data;
+ sc->endd = sc->f->endb;
+ if(!mbs) sc->f->endb = sc->endd; /* stop cc's "unused mbs" warning */
+ }
+
+ for(n = 0; n < SFMBMAX; )
+ { if((v = _scgetc((Void_t*)sc, 0)) <= 0)
+ goto no_match;
+ else b[n++] = v;
+
+ if(mbrtowc(wc, b, n, (mbstate_t*)mbs) == (size_t)(-1))
+ goto no_match; /* malformed multi-byte char */
+ else
+ { /* multi-byte char converted successfully */
+ if(fmt == 'c')
+ return 1;
+ else if(fmt == 's')
+ { if(n > 1 || (n == 1 && !isspace(b[0]) ) )
+ return 1;
+ else goto no_match;
+ }
+ else if(fmt == '[')
+ { if((n == 1 && ac->ok[b[0]]) ||
+ (n > 1 && _sfwaccept(*wc,ac)) )
+ return 1;
+ else goto no_match;
+ }
+ else /* if(fmt == '1') match a single wchar_t */
+ { if(*wc == ac->wc)
+ return 1;
+ else goto no_match;
+ }
+ }
+ }
+
+no_match: /* this unget is lossy on a stream with small buffer */
+ if((sc->d -= n) < sc->data)
+ sc->d = sc->data;
+ return 0;
+}
+#endif /*_has_multibyte*/
+
+
+#if __STD_C
+int sfvscanf(Sfio_t* f, reg const char* form, va_list args)
+#else
+int sfvscanf(f,form,args)
+Sfio_t* f; /* file to be scanned */
+reg char* form; /* scanning format */
+va_list args;
+#endif
+{
+ reg int inp, shift, base, width;
+ ssize_t size;
+ int fmt, flags, dot, n_assign, v, n, n_input;
+ char *sp;
+
+ Accept_t acc;
+
+ Argv_t argv;
+ Sffmt_t *ft;
+ Fmt_t *fm, *fmstk;
+
+ Fmtpos_t* fp;
+ char *oform;
+ va_list oargs;
+ int argp, argn;
+
+ int decimal = 0, thousand = 0;
+
+#if _has_multibyte
+ wchar_t wc;
+ SFMBDCL(fmbs)
+ SFMBDCL(mbs)
+#endif
+
+ Void_t* value; /* location to assign scanned value */
+ char* t_str;
+ ssize_t n_str;
+
+ /* local buffering system */
+ Scan_t scd;
+ uchar *d, *endd, *data;
+ int peek;
+#define SFbuf(f) (_sfbuf(f,&peek), (data = d = f->next), (endd = f->endb) )
+#define SFlen(f) (d - data)
+#define SFinit(f) ((peek = f->extent < 0 && (f->flags&SF_SHARE)), SFbuf(f) )
+#define SFend(f) ((n_input += SFlen(f)), \
+ (peek ? SFREAD(f,(Void_t*)data,SFlen(f)) : ((f->next = d),0)) )
+#define SFgetc(f,c) ((c) = (d < endd || (SFend(f), SFbuf(f), d < endd)) ? \
+ (int)(*d++) : -1 )
+#define SFungetc(f,c) (d -= 1)
+
+ SFMTXDECL(f);
+
+ SFCVINIT(); /* initialize conversion tables */
+
+ SFMTXENTER(f,-1);
+
+ if(!form || f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, -1);
+ SFLOCK(f,0);
+
+ SFinit(f); /* initialize local buffering system */
+
+ n_assign = n_input = 0; inp = -1;
+
+ fmstk = NIL(Fmt_t*);
+ ft = NIL(Sffmt_t*);
+
+ fp = NIL(Fmtpos_t*);
+ argn = -1;
+ oform = (char*)form;
+ va_copy(oargs,args);
+
+ SFSETLOCALE(&decimal, &thousand);
+
+loop_fmt:
+ SFMBCLR(&fmbs);
+ while((fmt = *form++))
+ { if(fmt != '%')
+ { if(isspace(fmt))
+ { if(fmt != '\n' || !(f->flags&SF_LINE))
+ fmt = -1;
+ for(;;)
+ { if(SFgetc(f,inp) < 0 || inp == fmt)
+ goto loop_fmt;
+ else if(!isspace(inp))
+ { SFungetc(f,inp);
+ goto loop_fmt;
+ }
+ }
+ }
+ else
+ { match_1:
+#if _has_multibyte
+ if((n = (int)mbrtowc(&wc,form-1,SFMBMAX,&fmbs)) <= 0)
+ goto pop_fmt;
+ if(n > 1)
+ { acc.wc = wc;
+ SCinit(&scd,0); SFMBCLR(&mbs);
+ v = SFgetwc(&scd, &wc, '1', &acc, &mbs);
+ SCend(&scd,0);
+ if(v == 0)
+ goto pop_fmt;
+ form += n-1;
+ }
+ else
+#endif
+ if(SFgetc(f,inp) != fmt)
+ { if(inp < 0)
+ goto done;
+ SFungetc(f,inp);
+ goto pop_fmt;
+ }
+ }
+ continue;
+ }
+
+ if(*form == '%')
+ { form += 1;
+ do SFgetc(f,inp); while(isspace(inp)); /* skip starting blanks */
+ SFungetc(f,inp);
+ goto match_1;
+ }
+
+ if(*form == '\0')
+ goto pop_fmt;
+
+ if(*form == '*')
+ { flags = SFFMT_SKIP;
+ form += 1;
+ }
+ else flags = 0;
+
+ /* matching some pattern */
+ base = 10; size = -1;
+ width = dot = 0;
+ t_str = NIL(char*); n_str = 0;
+ value = NIL(Void_t*);
+ argp = -1;
+
+ loop_flags: /* LOOP FOR FLAGS, WIDTH, BASE, TYPE */
+ switch((fmt = *form++) )
+ {
+ case LEFTP : /* get the type which is enclosed in balanced () */
+ t_str = (char*)form;
+ for(v = 1;;)
+ { switch(*form++)
+ {
+ case 0 : /* not balanceable, retract */
+ form = t_str;
+ t_str = NIL(char*);
+ n_str = 0;
+ goto loop_flags;
+ case LEFTP : /* increasing nested level */
+ v += 1;
+ continue;
+ case RIGHTP : /* decreasing nested level */
+ if((v -= 1) != 0)
+ continue;
+ if(*t_str != '*' )
+ n_str = (form-1) - t_str;
+ else
+ { t_str = (*_Sffmtintf)(t_str+1,&n);
+ if(*t_str == '$')
+ { if(!fp &&
+ !(fp = (*_Sffmtposf)(f,oform,oargs,ft,1)) )
+ goto pop_fmt;
+ n = FP_SET(n,argn);
+ }
+ else n = FP_SET(-1,argn);
+
+ if(fp)
+ { t_str = fp[n].argv.s;
+ n_str = fp[n].ft.size;
+ }
+ else if(ft && ft->extf )
+ { FMTSET(ft, form,args,
+ LEFTP, 0, 0, 0,0,0,
+ NIL(char*),0);
+ n = (*ft->extf)
+ (f,(Void_t*)&argv,ft);
+ if(n < 0)
+ goto pop_fmt;
+ if(!(ft->flags&SFFMT_VALUE) )
+ goto t_arg;
+ if((t_str = argv.s) &&
+ (n_str = (int)ft->size) < 0)
+ n_str = strlen(t_str);
+ }
+ else
+ { t_arg:
+ if((t_str = va_arg(args,char*)) )
+ n_str = strlen(t_str);
+ }
+ }
+ goto loop_flags;
+ }
+ }
+
+ case '#' : /* alternative format */
+ flags |= SFFMT_ALTER;
+ goto loop_flags;
+
+ case '.' : /* width & base */
+ dot += 1;
+ if(isdigit(*form))
+ { fmt = *form++;
+ goto dot_size;
+ }
+ else if(*form == '*')
+ { form = (*_Sffmtintf)(form+1,&n);
+ if(*form == '$')
+ { form += 1;
+ if(!fp &&
+ !(fp = (*_Sffmtposf)(f,oform,oargs,ft,1)) )
+ goto pop_fmt;
+ n = FP_SET(n,argn);
+ }
+ else n = FP_SET(-1,argn);
+
+ if(fp)
+ v = fp[n].argv.i;
+ else if(ft && ft->extf )
+ { FMTSET(ft, form,args, '.',dot, 0, 0,0,0,
+ NIL(char*), 0);
+ if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0)
+ goto pop_fmt;
+ if(ft->flags&SFFMT_VALUE)
+ v = argv.i;
+ else v = (dot <= 2) ? va_arg(args,int) : 0;
+ }
+ else v = (dot <= 2) ? va_arg(args,int) : 0;
+ if(v < 0)
+ v = 0;
+ goto dot_set;
+ }
+ else goto loop_flags;
+
+ case '0' : case '1' : case '2' : case '3' : case '4' :
+ case '5' : case '6' : case '7' : case '8' : case '9' :
+ dot_size :
+ for(v = fmt-'0'; isdigit(*form); ++form)
+ v = v*10 + (*form - '0');
+
+ if(*form == '$')
+ { form += 1;
+ if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,ft,1)) )
+ goto pop_fmt;
+ argp = v-1;
+ goto loop_flags;
+ }
+
+ dot_set :
+ if(dot == 0 || dot == 1)
+ width = v;
+ else if(dot == 2)
+ base = v;
+ goto loop_flags;
+
+ case 'I' : /* object size */
+ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
+ if(isdigit(*form))
+ { for(size = 0, n = *form; isdigit(n); n = *++form)
+ size = size*10 + (n - '0');
+ }
+ else if(*form == '*')
+ { form = (*_Sffmtintf)(form+1,&n);
+ if(*form == '$')
+ { form += 1;
+ if(!fp &&
+ !(fp = (*_Sffmtposf)(f,oform,oargs,ft,1)))
+ goto pop_fmt;
+ n = FP_SET(n,argn);
+ }
+ else n = FP_SET(-1,argn);
+
+ if(fp) /* use position list */
+ size = fp[n].argv.i;
+ else if(ft && ft->extf )
+ { FMTSET(ft, form,args, 'I',sizeof(int), 0, 0,0,0,
+ NIL(char*), 0);
+ if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0)
+ goto pop_fmt;
+ if(ft->flags&SFFMT_VALUE)
+ size = argv.i;
+ else size = va_arg(args,int);
+ }
+ else size = va_arg(args,int);
+ }
+ goto loop_flags;
+
+ case 'l' :
+ size = -1; flags &= ~SFFMT_TYPES;
+ if(*form == 'l')
+ { form += 1;
+ flags |= SFFMT_LLONG;
+ }
+ else flags |= SFFMT_LONG;
+ goto loop_flags;
+ case 'h' :
+ size = -1; flags &= ~SFFMT_TYPES;
+ if(*form == 'h')
+ { form += 1;
+ flags |= SFFMT_SSHORT;
+ }
+ else flags |= SFFMT_SHORT;
+ goto loop_flags;
+ case 'L' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_LDOUBLE;
+ goto loop_flags;
+ case 'j' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_JFLAG;
+ goto loop_flags;
+ case 'z' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_ZFLAG;
+ goto loop_flags;
+ case 't' :
+ size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_TFLAG;
+ goto loop_flags;
+ case QUOTE :
+ if(thousand > 0)
+ flags |= SFFMT_THOUSAND;
+ goto loop_flags;
+ }
+
+ /* set object size for scalars */
+ if(flags & SFFMT_TYPES)
+ { if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n')
+ { if(flags&SFFMT_LONG)
+ size = sizeof(long);
+ else if(flags&SFFMT_SHORT)
+ size = sizeof(short);
+ else if(flags&SFFMT_SSHORT)
+ size = sizeof(char);
+ else if(flags&SFFMT_TFLAG)
+ size = sizeof(ptrdiff_t);
+ else if(flags&SFFMT_ZFLAG)
+ size = sizeof(size_t);
+ else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) )
+ size = sizeof(Sflong_t);
+ else if(flags&SFFMT_IFLAG)
+ { if(size <= 0 ||
+ size == sizeof(Sflong_t)*CHAR_BIT )
+ size = sizeof(Sflong_t);
+ }
+ else if(size < 0)
+ size = sizeof(int);
+ }
+ else if(_Sftype[fmt]&SFFMT_FLOAT)
+ { if(flags&(SFFMT_LONG|SFFMT_LLONG))
+ size = sizeof(double);
+ else if(flags&SFFMT_LDOUBLE)
+ size = sizeof(Sfdouble_t);
+ else if(flags&SFFMT_IFLAG)
+ { if(size <= 0)
+ size = sizeof(Sfdouble_t);
+ }
+ else if(size < 0)
+ size = sizeof(float);
+ }
+ else if(_Sftype[fmt]&SFFMT_CHAR)
+ {
+#if _has_multibyte
+ if((flags&SFFMT_LONG) || fmt == 'C')
+ { size = sizeof(wchar_t) > sizeof(int) ?
+ sizeof(wchar_t) : sizeof(int);
+ } else
+#endif
+ if(size < 0)
+ size = sizeof(int);
+ }
+ }
+
+ argp = FP_SET(argp,argn);
+ if(fp)
+ { if(!(fp[argp].ft.flags&SFFMT_SKIP) )
+ { n_assign += 1;
+ value = fp[argp].argv.vp;
+ size = fp[argp].ft.size;
+ if(ft && ft->extf && fp[argp].ft.fmt != fp[argp].fmt)
+ fmt = fp[argp].ft.fmt;
+ }
+ else flags |= SFFMT_SKIP;
+ }
+ else if(ft && ft->extf)
+ { FMTSET(ft, form,args, fmt, size,flags, width,0,base, t_str,n_str);
+ SFend(f); SFOPEN(f,0);
+ v = (*ft->extf)(f, (Void_t*)&argv, ft);
+ SFLOCK(f,0); SFbuf(f);
+
+ if(v < 0)
+ goto pop_fmt;
+ else if(v > 0) /* extf comsumed v input bytes */
+ { n_input += v;
+ if(!(ft->flags&SFFMT_SKIP) )
+ n_assign += 1;
+ continue;
+ }
+ else /* if(v == 0): extf did not use input stream */
+ { FMTGET(ft, form,args, fmt, size, flags, width,n,base);
+
+ if((ft->flags&SFFMT_VALUE) && !(ft->flags&SFFMT_SKIP) )
+ value = argv.vp;
+ }
+ }
+
+ if(_Sftype[fmt] == 0) /* unknown pattern */
+ goto pop_fmt;
+
+ if(fmt == '!')
+ { if(!fp)
+ fp = (*_Sffmtposf)(f,oform,oargs,ft,1);
+ else goto pop_fmt;
+
+ if(!(argv.ft = va_arg(args,Sffmt_t*)) )
+ continue;
+ if(!argv.ft->form && ft ) /* change extension functions */
+ { if(ft->eventf &&
+ (*ft->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0)
+ continue;
+ fmstk->ft = ft = argv.ft;
+ }
+ else /* stack a new environment */
+ { if(!(fm = (Fmt_t*)malloc(sizeof(Fmt_t))) )
+ goto done;
+
+ ft = fm->ft = argv.ft;
+ SFMBSET(ft->mbs, &fmbs);
+ if(ft->form)
+ { fm->form = (char*)form; SFMBCPY(&fm->mbs,&fmbs);
+ va_copy(fm->args,args);
+
+ fm->oform = oform;
+ va_copy(fm->oargs,oargs);
+ fm->argn = argn;
+ fm->fp = fp;
+
+ form = ft->form; SFMBCLR(ft->mbs);
+ va_copy(args,ft->args);
+ argn = -1;
+ fp = NIL(Fmtpos_t*);
+ oform = (char*)form;
+ va_copy(oargs,args);
+ }
+ else fm->form = NIL(char*);
+
+ fm->eventf = ft->eventf;
+ fm->next = fmstk;
+ fmstk = fm;
+ }
+ continue;
+ }
+
+ /* get the address to assign value */
+ if(!value && !(flags&SFFMT_SKIP) )
+ value = va_arg(args,Void_t*);
+
+ if(fmt == 'n') /* return length of consumed input */
+ {
+#if !_ast_intmax_long
+ if(size == sizeof(Sflong_t) )
+ *((Sflong_t*)value) = (Sflong_t)(n_input+SFlen(f));
+ else
+#endif
+ if(size == sizeof(long) )
+ *((long*)value) = (long)(n_input+SFlen(f));
+ else if(size == sizeof(short) )
+ *((short*)value) = (short)(n_input+SFlen(f));
+ else if(size == sizeof(uchar))
+ *((uchar*)value) = (uchar)(n_input+SFlen(f));
+ else *((int*)value) = (int)(n_input+SFlen(f));
+ continue;
+ }
+
+ /* if get here, start scanning input */
+ if(width == 0)
+ width = fmt == 'c' ? 1 : MAXWIDTH;
+
+ /* define the first input character */
+ if(fmt == 'c' || fmt == '[' || fmt == 'C' )
+ SFgetc(f,inp);
+ else
+ { do { SFgetc(f,inp); }
+ while(isspace(inp)); /* skip starting blanks */
+ }
+ if(inp < 0)
+ goto done;
+
+ if(_Sftype[fmt] == SFFMT_FLOAT)
+ { SFungetc(f,inp); SCinit(&scd,1);
+ argv.ld = _sfdscan((Void_t*)(&scd), _scgetc);
+ SCend(&scd,1);
+
+ if(scd.error >= 0)
+ { if(inp >= 0)
+ SFungetc(f, inp);
+ goto pop_fmt;
+ }
+
+ if(value)
+ {
+#if !_ast_fltmax_double
+ if(size == sizeof(Sfdouble_t))
+ *((Sfdouble_t*)value) = argv.ld;
+ else
+#endif
+ if(size == sizeof(double))
+ *((double*)value) = (double)argv.ld;
+ else *((float*)value) = (float)argv.ld;
+
+ n_assign += 1;
+ }
+ }
+ else if(_Sftype[fmt] == SFFMT_UINT || fmt == 'p')
+ { if(inp == '-')
+ { SFungetc(f,inp);
+ goto pop_fmt;
+ }
+ else goto int_cvt;
+ }
+ else if(_Sftype[fmt] == SFFMT_INT)
+ { int_cvt:
+ if(inp == '-' || inp == '+')
+ { if(inp == '-')
+ flags |= SFFMT_MINUS;
+ while(--width > 0 && SFgetc(f,inp) >= 0)
+ if(!isspace(inp))
+ break;
+ }
+ if(inp < 0)
+ goto done;
+
+ if(fmt == 'o')
+ base = 8;
+ else if(fmt == 'x' || fmt == 'X' || fmt == 'p')
+ base = 16;
+ else if(fmt == 'i' && inp == '0') /* self-described data */
+ { base = 8;
+ if(width > 1) /* peek to see if it's a base-16 */
+ { if(SFgetc(f,inp) >= 0)
+ { if(inp == 'x' || inp == 'X')
+ base = 16;
+ SFungetc(f,inp);
+ }
+ inp = '0';
+ }
+ }
+
+ /* now convert */
+ argv.lu = 0;
+ if(base == 16)
+ { sp = (char*)_Sfcv36;
+ shift = 4;
+ if(sp[inp] >= 16)
+ { SFungetc(f,inp);
+ goto pop_fmt;
+ }
+ if(inp == '0' && --width > 0)
+ { /* skip leading 0x or 0X */
+ if(SFgetc(f,inp) >= 0 &&
+ (inp == 'x' || inp == 'X') && --width > 0)
+ SFgetc(f,inp);
+ }
+ if(inp >= 0 && sp[inp] < 16)
+ goto base_shift;
+ }
+ else if(base == 10)
+ { for(n = v = 0;; )
+ { /* fast base 10 conversion */
+#define TEN(x) (((x) << 3) + ((x) << 1) )
+ if (inp >= '0' && inp <= '9')
+ { argv.lu = TEN(argv.lu) + (inp-'0');
+ n += 1;
+ }
+ else if(inp == thousand)
+ { if((v && n != 3) || (!v && n > 3) )
+ break;
+ v = 1; n = 0;
+ }
+ else break;
+ if((width -= 1) <= 0 || SFgetc(f,inp) < 0)
+ break;
+ }
+ if (!n && !v)
+ { SFungetc(f,inp);
+ goto pop_fmt;
+ }
+
+ if(fmt == 'i' && inp == '#' && !(flags&SFFMT_ALTER) )
+ { base = (int)argv.lu;
+ if(base < 2 || base > SF_RADIX)
+ goto pop_fmt;
+ argv.lu = 0;
+ sp = (char*)(base <= 36 ? _Sfcv36 : _Sfcv64);
+ if(--width > 0 &&
+ SFgetc(f,inp) >= 0 && sp[inp] < base)
+ goto base_conv;
+ }
+ }
+ else
+ { /* other bases */
+ sp = (char*)(base <= 36 ? _Sfcv36 : _Sfcv64);
+ if(base < 2 || base > SF_RADIX || sp[inp] >= base)
+ { SFungetc(f,inp);
+ goto pop_fmt;
+ }
+
+ base_conv: /* check for power of 2 conversions */
+ if((base & ~(base-1)) == base)
+ { if(base < 8)
+ shift = base < 4 ? 1 : 2;
+ else if(base < 32)
+ shift = base < 16 ? 3 : 4;
+ else shift = base < 64 ? 5 : 6;
+
+ base_shift: do
+ { argv.lu = (argv.lu << shift) + sp[inp];
+ } while(--width > 0 &&
+ SFgetc(f,inp) >= 0 && sp[inp] < base);
+ }
+ else
+ { do
+ { argv.lu = (argv.lu * base) + sp[inp];
+ } while(--width > 0 &&
+ SFgetc(f,inp) >= 0 && sp[inp] < base);
+ }
+ }
+
+ if(flags&SFFMT_MINUS)
+ argv.ll = -argv.ll;
+
+ if(value)
+ { n_assign += 1;
+
+ if(fmt == 'p')
+#if _more_void_int
+ *((Void_t**)value) = (Void_t*)((ulong)argv.lu);
+#else
+ *((Void_t**)value) = (Void_t*)((uint)argv.lu);
+#endif
+#if !_ast_intmax_long
+ else if(size == sizeof(Sflong_t))
+ *((Sflong_t*)value) = argv.ll;
+#endif
+ else if(size == sizeof(long))
+ { if(fmt == 'd' || fmt == 'i')
+ *((long*)value) = (long)argv.ll;
+ else *((ulong*)value) = (ulong)argv.lu;
+ }
+ else if(size == sizeof(short))
+ { if(fmt == 'd' || fmt == 'i')
+ *((short*)value) = (short)argv.ll;
+ else *((ushort*)value) = (ushort)argv.lu;
+ }
+ else if(size == sizeof(char) )
+ { if(fmt == 'd' || fmt == 'i')
+ *((char*)value) = (char)argv.ll;
+ else *((uchar*)value) = (uchar)argv.lu;
+ }
+ else
+ { if(fmt == 'd' || fmt == 'i')
+ *((int*)value) = (int)argv.ll;
+ else *((uint*)value) = (uint)argv.lu;
+ }
+ }
+ }
+ else if(fmt == 'C' || fmt == 'S')
+ { fmt = fmt == 'C' ? 'c' : 's';
+ flags = (flags & ~SFFMT_TYPES) | SFFMT_LONG;
+ goto do_string;
+ }
+ else if(fmt == 's' || fmt == 'c' || fmt == '[' )
+ { do_string:
+ if(value)
+ { if(size < 0)
+ size = MAXWIDTH;
+ if(fmt != 'c')
+ size -= 1;
+#if _has_multibyte
+ if(flags&SFFMT_LONG)
+ argv.ws = (wchar_t*)value;
+ else
+#endif
+ argv.s = (char*)value;
+ }
+ else size = 0;
+
+ if(fmt == '[' && !(form = _sfsetclass(form,&acc,flags)) )
+ { SFungetc(f,inp);
+ goto pop_fmt;
+ }
+
+ n = 0; /* count number of scanned characters */
+#if _has_multibyte
+ if(flags&SFFMT_LONG)
+ { SFungetc(f,inp); SCinit(&scd,0); SFMBCLR(&mbs);
+ for(; width > 0; --width)
+ { if(SFgetwc(&scd,&wc,fmt,&acc,&mbs) == 0)
+ break;
+ if((n += 1) <= size)
+ *argv.ws++ = wc;
+ }
+ SCend(&scd,0);
+ }
+ else
+#endif
+
+ if(fmt == 's')
+ { do
+ { if(isspace(inp))
+ break;
+ if((n += 1) <= size)
+ *argv.s++ = inp;
+ } while(--width > 0 && SFgetc(f,inp) >= 0);
+ }
+ else if(fmt == 'c')
+ { do
+ { if((n += 1) <= size)
+ *argv.s++ = inp;
+ } while(--width > 0 && SFgetc(f,inp) >= 0);
+ }
+ else /* if(fmt == '[') */
+ { do
+ { if(!acc.ok[inp])
+ { if(n > 0 || (flags&SFFMT_ALTER) )
+ break;
+ else
+ { SFungetc(f,inp);
+ goto pop_fmt;
+ }
+ }
+ if((n += 1) <= size)
+ *argv.s++ = inp;
+ } while(--width > 0 && SFgetc(f,inp) >= 0);
+ }
+
+ if(value && (n > 0 || fmt == '[') )
+ { n_assign += 1;
+ if(fmt != 'c' && size >= 0)
+ {
+#if _has_multibyte
+ if(flags&SFFMT_LONG)
+ *argv.ws = 0;
+ else
+#endif
+ *argv.s = 0;
+ }
+ }
+ }
+
+ if(width > 0 && inp >= 0)
+ SFungetc(f,inp);
+ }
+
+pop_fmt:
+ if(fp)
+ { free(fp);
+ fp = NIL(Fmtpos_t*);
+ }
+ while((fm = fmstk) ) /* pop the format stack and continue */
+ { if(fm->eventf)
+ { if(!form || !form[0])
+ (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),ft);
+ else if((*fm->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0)
+ goto loop_fmt;
+ }
+
+ fmstk = fm->next;
+ if((form = fm->form) )
+ { SFMBCPY(&fmbs,&fm->mbs);
+ va_copy(args, fm->args);
+ oform = fm->oform;
+ va_copy(oargs,fm->oargs);
+ argn = fm->argn;
+ fp = fm->fp;
+ }
+ ft = fm->ft;
+ free(fm);
+ if(form && form[0])
+ goto loop_fmt;
+ }
+
+done:
+ if(fp)
+ free(fp);
+ while((fm = fmstk) )
+ { if(fm->eventf)
+ (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),fm->ft);
+ fmstk = fm->next;
+ free(fm);
+ }
+
+ SFend(f);
+
+ SFOPEN(f,0);
+
+ if(n_assign == 0 && inp < 0)
+ n_assign = -1;
+
+ SFMTXRETURN(f,n_assign);
+}
diff --git a/src/lib/libast/sfio/sfwalk.c b/src/lib/libast/sfio/sfwalk.c
new file mode 100644
index 0000000..7019863
--- /dev/null
+++ b/src/lib/libast/sfio/sfwalk.c
@@ -0,0 +1,67 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Walk streams and run operations on them
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+int sfwalk(Sfwalk_f walkf, Void_t* data, int type)
+#else
+int sfwalk(walkf, data, type)
+Sfwalk_f walkf; /* return <0: stop, >=0: continue */
+Void_t* data;
+int type; /* walk streams with all given flags */
+#endif
+{
+ Sfpool_t *p;
+ Sfio_t *f;
+ int n, rv;
+
+ /* truly initializing std-streams before walking */
+ if(sfstdin->mode & SF_INIT)
+ _sfmode(sfstdin, (sfstdin->mode & SF_RDWR), 0);
+ if(sfstdout->mode & SF_INIT)
+ _sfmode(sfstdout, (sfstdout->mode & SF_RDWR), 0);
+ if(sfstderr->mode & SF_INIT)
+ _sfmode(sfstderr, (sfstderr->mode & SF_RDWR), 0);
+
+ for(rv = 0, p = &_Sfpool; p; p = p->next)
+ { for(n = 0; n < p->n_sf; )
+ { f = p->sf[n];
+
+ if(type != 0 && (f->_flags&type) != type )
+ continue; /* not in the interested set */
+
+ if((rv = (*walkf)(f, data)) < 0)
+ return rv;
+
+ if(p->sf[n] == f) /* move forward to next stream */
+ n += 1;
+ /* else - a sfclose() was done on current stream */
+ }
+ }
+
+ return rv;
+}
diff --git a/src/lib/libast/sfio/sfwr.c b/src/lib/libast/sfio/sfwr.c
new file mode 100644
index 0000000..9f1c0f9
--- /dev/null
+++ b/src/lib/libast/sfio/sfwr.c
@@ -0,0 +1,252 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write data with discipline.
+** In the case of a string stream, this is used mainly to extend
+** the buffer. However, this is done here so that exception handling
+** is done uniformly across all stream types.
+**
+** Written by Kiem-Phong Vo.
+*/
+
+/* hole preserving writes */
+#if __STD_C
+static ssize_t sfoutput(Sfio_t* f, char* buf, size_t n)
+#else
+static ssize_t sfoutput(f,buf,n)
+Sfio_t* f;
+char* buf;
+size_t n;
+#endif
+{ reg char *sp, *wbuf, *endbuf;
+ reg ssize_t s, w, wr;
+
+ s = w = 0;
+ wbuf = buf;
+ endbuf = buf+n;
+ while(n > 0)
+ { if((ssize_t)n < _Sfpage) /* no hole possible */
+ { buf += n;
+ s = n = 0;
+ }
+ else while((ssize_t)n >= _Sfpage)
+ { /* see if a hole of 0's starts here */
+ sp = buf+1;
+ if(buf[0] == 0 && buf[_Sfpage-1] == 0)
+ { /* check byte at a time until int-aligned */
+ while(((ulong)sp)%sizeof(int))
+ { if(*sp != 0)
+ goto chk_hole;
+ sp += 1;
+ }
+
+ /* check using int to speed up */
+ while(sp < endbuf)
+ { if(*((int*)sp) != 0)
+ goto chk_hole;
+ sp += sizeof(int);
+ }
+
+ /* check the remaining bytes */
+ if(sp > endbuf)
+ { sp -= sizeof(int);
+ while(sp < endbuf)
+ { if(*sp != 0)
+ goto chk_hole;
+ sp += 1;
+ }
+ }
+ }
+
+ chk_hole:
+ if((s = sp-buf) >= _Sfpage) /* found a hole */
+ break;
+
+ /* skip a dirty page */
+ n -= _Sfpage;
+ buf += _Sfpage;
+ }
+
+ /* write out current dirty pages */
+ if(buf > wbuf)
+ { if((ssize_t)n < _Sfpage)
+ { buf = endbuf;
+ n = s = 0;
+ }
+ if((wr = syswritef(f->file,wbuf,buf-wbuf)) > 0)
+ { w += wr;
+ f->bits &= ~SF_HOLE;
+ }
+ if(wr != (buf-wbuf))
+ break;
+ wbuf = buf;
+ }
+
+ /* seek to a rounded boundary within the hole */
+ if(s >= _Sfpage)
+ { s = (s/_Sfpage)*_Sfpage;
+ if(SFSK(f,(Sfoff_t)s,SEEK_CUR,NIL(Sfdisc_t*)) < 0)
+ break;
+ w += s;
+ n -= s;
+ wbuf = (buf += s);
+ f->bits |= SF_HOLE;
+
+ if(n > 0)
+ { /* next page must be dirty */
+ s = (ssize_t)n <= _Sfpage ? 1 : _Sfpage;
+ buf += s;
+ n -= s;
+ }
+ }
+ }
+
+ return w > 0 ? w : -1;
+}
+
+#if __STD_C
+ssize_t sfwr(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
+#else
+ssize_t sfwr(f,buf,n,disc)
+Sfio_t* f;
+Void_t* buf;
+size_t n;
+Sfdisc_t* disc;
+#endif
+{
+ reg ssize_t w;
+ reg Sfdisc_t* dc;
+ reg int local, oerrno;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f,(ssize_t)(-1));
+
+ GETLOCAL(f,local);
+ if(!local && !(f->bits&SF_DCDOWN)) /* an external user's call */
+ { if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0 )
+ SFMTXRETURN(f, (ssize_t)(-1));
+ if(f->next > f->data && SFSYNC(f) < 0 )
+ SFMTXRETURN(f, (ssize_t)(-1));
+ }
+
+ for(;;)
+ { /* stream locked by sfsetfd() */
+ if(!(f->flags&SF_STRING) && f->file < 0)
+ SFMTXRETURN(f,(ssize_t)0);
+
+ /* clear current error states */
+ f->flags &= ~(SF_EOF|SF_ERROR);
+
+ dc = disc;
+ if(f->flags&SF_STRING) /* just asking to extend buffer */
+ w = n + (f->next - f->data);
+ else
+ { /* warn that a write is about to happen */
+ SFDISC(f,dc,writef);
+ if(dc && dc->exceptf && (f->flags&SF_IOCHECK) )
+ { reg int rv;
+ if(local)
+ SETLOCAL(f);
+ if((rv = _sfexcept(f,SF_WRITE,n,dc)) > 0)
+ n = rv;
+ else if(rv < 0)
+ { f->flags |= SF_ERROR;
+ SFMTXRETURN(f, rv);
+ }
+ }
+
+ if(f->extent >= 0)
+ { /* make sure we are at the right place to write */
+ if(f->flags&SF_APPENDWR)
+ { if(f->here != f->extent || (f->flags&SF_SHARE))
+ { f->here = SFSK(f,(Sfoff_t)0,SEEK_END,dc);
+ f->extent = f->here;
+ }
+ }
+ else if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC))
+ f->here = SFSK(f,f->here,SEEK_SET,dc);
+ }
+
+ oerrno = errno;
+ errno = 0;
+
+ if(dc && dc->writef)
+ { SFDCWR(f,buf,n,dc,w);
+ }
+ else if(SFISNULL(f))
+ w = n;
+ else if(f->flags&SF_WHOLE)
+ goto do_write;
+ else if((ssize_t)n >= _Sfpage &&
+ !(f->flags&(SF_SHARE|SF_APPENDWR)) &&
+ f->here == f->extent && (f->here%_Sfpage) == 0)
+ { if((w = sfoutput(f,(char*)buf,n)) <= 0)
+ goto do_write;
+ }
+ else
+ {
+ do_write:
+ if((w = syswritef(f->file,buf,n)) > 0)
+ f->bits &= ~SF_HOLE;
+ }
+
+ if(errno == 0)
+ errno = oerrno;
+
+ if(w > 0)
+ { if(!(f->bits&SF_DCDOWN) )
+ { if((f->flags&(SF_APPENDWR|SF_PUBLIC)) && f->extent >= 0 )
+ f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,dc);
+ else f->here += w;
+ if(f->extent >= 0 && f->here > f->extent)
+ f->extent = f->here;
+ }
+
+ SFMTXRETURN(f, (ssize_t)w);
+ }
+ }
+
+ if(local)
+ SETLOCAL(f);
+ switch(_sfexcept(f,SF_WRITE,w,dc))
+ {
+ case SF_ECONT :
+ goto do_continue;
+ case SF_EDONE :
+ w = local ? 0 : w;
+ SFMTXRETURN(f, (ssize_t)w);
+ case SF_EDISC :
+ if(!local && !(f->flags&SF_STRING))
+ goto do_continue;
+ /* else fall thru */
+ case SF_ESTACK :
+ SFMTXRETURN(f, (ssize_t)(-1));
+ }
+
+ do_continue:
+ for(dc = f->disc; dc; dc = dc->disc)
+ if(dc == disc)
+ break;
+ disc = dc;
+ }
+}
diff --git a/src/lib/libast/sfio/sfwrite.c b/src/lib/libast/sfio/sfwrite.c
new file mode 100644
index 0000000..170c863
--- /dev/null
+++ b/src/lib/libast/sfio/sfwrite.c
@@ -0,0 +1,171 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "sfhdr.h"
+
+/* Write data out to the file system
+**
+** Written by Kiem-Phong Vo.
+*/
+
+#if __STD_C
+ssize_t sfwrite(Sfio_t* f, const Void_t* buf, size_t n)
+#else
+ssize_t sfwrite(f,buf,n)
+Sfio_t* f; /* write to this stream. */
+Void_t* buf; /* buffer to be written. */
+size_t n; /* number of bytes. */
+#endif
+{
+ reg uchar *s, *begs, *next;
+ reg ssize_t w;
+ reg int local;
+ SFMTXDECL(f);
+
+ SFMTXENTER(f, (ssize_t)(-1));
+
+ GETLOCAL(f,local);
+
+ if(!buf)
+ SFMTXRETURN(f, (ssize_t)(n == 0 ? 0 : -1) );
+
+ /* release peek lock */
+ if(f->mode&SF_PEEK)
+ { if(!(f->mode&SF_WRITE) && (f->flags&SF_RDWR) != SF_RDWR)
+ SFMTXRETURN(f, (ssize_t)(-1));
+
+ if((uchar*)buf != f->next &&
+ (!f->rsrv || f->rsrv->data != (uchar*)buf) )
+ SFMTXRETURN(f, (ssize_t)(-1));
+
+ f->mode &= ~SF_PEEK;
+
+ if(f->mode&SF_PKRD)
+ { /* read past peeked data */
+ char buf[16];
+ reg ssize_t r;
+
+ for(w = n; w > 0; )
+ { if((r = w) > sizeof(buf))
+ r = sizeof(buf);
+ if((r = sysreadf(f->file,buf,r)) <= 0)
+ { n -= w;
+ break;
+ }
+ else w -= r;
+ }
+
+ f->mode &= ~SF_PKRD;
+ f->endb = f->data + n;
+ f->here += n;
+ }
+
+ if((f->mode&SF_READ) && f->proc)
+ f->next += n;
+ }
+
+ s = begs = (uchar*)buf;
+ for(;; f->mode &= ~SF_LOCK)
+ { /* check stream mode */
+ if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0 )
+ { w = s > begs ? s-begs : -1;
+ SFMTXRETURN(f,w);
+ }
+
+ SFLOCK(f,local);
+
+ w = f->endb - f->next;
+
+ if(s == f->next) /* after sfreserve */
+ { if(w > (ssize_t)n)
+ w = (ssize_t)n;
+ f->next = (s += w);
+ n -= w;
+ break;
+ }
+
+ /* attempt to create space in buffer */
+ if(w == 0 || ((f->flags&SF_WHOLE) && w < (ssize_t)n) )
+ { if(f->flags&SF_STRING) /* extend buffer */
+ { (void)SFWR(f, s, n-w, f->disc);
+ if((w = f->endb - f->next) < (ssize_t)n)
+ { if(!(f->flags&SF_STRING)) /* maybe sftmp */
+ { if(f->next > f->data)
+ goto fls_buf;
+ }
+ else if(w == 0)
+ break;
+ }
+ }
+ else if(f->next > f->data)
+ { fls_buf:
+ (void)SFFLSBUF(f, -1);
+ if((w = f->endb - f->next) < (ssize_t)n &&
+ (f->flags&SF_WHOLE) && f->next > f->data )
+ break;
+ }
+ }
+
+ if(!(f->flags&SF_STRING) && f->next == f->data &&
+ (((f->flags&SF_WHOLE) && w <= n) || SFDIRECT(f,n)) )
+ { /* bypass buffering */
+ if((w = SFWR(f,s,n,f->disc)) <= 0 )
+ break;
+ }
+ else
+ { if(w > (ssize_t)n)
+ w = (ssize_t)n;
+ if(w <= 0) /* no forward progress possible */
+ break;
+ memmove(f->next, s, w);
+ f->next += w;
+ }
+
+ s += w;
+ if((n -= w) <= 0)
+ break;
+ }
+
+ /* always flush buffer for share streams */
+ if(f->extent < 0 && (f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) )
+ (void)SFFLSBUF(f,-1);
+
+ /* check to see if buffer should be flushed */
+ else if(n == 0 && (f->flags&SF_LINE) && !(f->flags&SF_STRING))
+ { if((ssize_t)(n = f->next-f->data) > (w = s-begs))
+ n = w;
+ if(n > 0 && n < HIFORLINE)
+ { for(next = f->next-1; n > 0; --n, --next)
+ { if(*next == '\n')
+ { n = HIFORLINE;
+ break;
+ }
+ }
+ }
+ if(n >= HIFORLINE)
+ (void)SFFLSBUF(f,-1);
+ }
+
+ SFOPEN(f,local);
+
+ w = s-begs;
+ SFMTXRETURN(f,w);
+}
diff --git a/src/lib/libast/sfio/vthread.h b/src/lib/libast/sfio/vthread.h
new file mode 100644
index 0000000..4030958
--- /dev/null
+++ b/src/lib/libast/sfio/vthread.h
@@ -0,0 +1,219 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _VTHREAD_H
+#define _VTHREAD_H 1
+
+#define VTHREAD_VERSION 20001201L
+
+/* Header for the Vthread library.
+** Note that the macro vt_threaded may be defined
+** outside of vthread.h to suppress threading.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com
+*/
+
+#include <ast_common.h>
+#include <errno.h>
+
+/* ast doesn't do threads yet */
+#if _PACKAGE_ast && !defined(vt_threaded)
+#define vt_threaded 0
+#endif
+
+#if !defined(vt_threaded) || (defined(vt_threaded) && vt_threaded == 1)
+#define _may_use_threads 1
+#else
+#define _may_use_threads 0
+#endif
+#undef vt_threaded
+
+#if _may_use_threads && !defined(vt_threaded) && _hdr_pthread
+#define vt_threaded 1
+#include <pthread.h>
+typedef pthread_mutex_t _vtmtx_t;
+typedef pthread_once_t _vtonce_t;
+typedef pthread_t _vtself_t;
+typedef pthread_t _vtid_t;
+typedef pthread_attr_t _vtattr_t;
+
+#if !defined(PTHREAD_ONCE_INIT) && defined(pthread_once_init)
+#define PTHREAD_ONCE_INIT pthread_once_init
+#endif
+
+#endif
+
+#if _may_use_threads && !defined(vt_threaded) && _WIN32
+#define vt_threaded 1
+#include <windows.h>
+typedef CRITICAL_SECTION _vtmtx_t;
+typedef int _vtonce_t;
+typedef HANDLE _vtself_t;
+typedef DWORD _vtid_t;
+typedef SECURITY_ATTRIBUTES _vtattr_t;
+#endif
+
+#ifndef vt_threaded
+#define vt_threaded 0
+#endif
+
+/* common attributes for various structures */
+#define VT_RUNNING 000000001 /* thread is running */
+#define VT_SUSPENDED 000000002 /* thread is suspended */
+#define VT_WAITED 000000004 /* thread has been waited */
+#define VT_FREE 000010000 /* object can be freed */
+#define VT_INIT 000020000 /* object was initialized */
+#define VT_BITS 000030007 /* bits that we care about */
+
+/* directives for vtset() */
+#define VT_STACK 1 /* set stack size */
+
+typedef struct _vtmutex_s Vtmutex_t;
+typedef struct _vtonce_s Vtonce_t;
+typedef struct _vthread_s Vthread_t;
+
+#ifndef EINVAL
+#define EINVAL 22
+#endif
+#ifndef EBUSY
+#define EBUSY 16
+#endif
+#ifndef EDEADLK
+#define EDEADLK 45
+#endif
+#ifndef EPERM
+#define EPERM 1
+#endif
+
+_BEGIN_EXTERNS_
+
+extern Vthread_t* vtopen _ARG_((Vthread_t*, int));
+extern int vtclose _ARG_((Vthread_t*));
+extern int vtset _ARG_((Vthread_t*, int, Void_t*));
+extern int vtrun _ARG_((Vthread_t*, void*(*)(void*), void*));
+extern int vtkill _ARG_((Vthread_t*));
+extern int vtwait _ARG_((Vthread_t*));
+
+extern int vtonce _ARG_((Vtonce_t*, void(*)() ));
+
+extern Vtmutex_t* vtmtxopen _ARG_((Vtmutex_t*, int));
+extern int vtmtxclose _ARG_((Vtmutex_t*));
+extern int vtmtxlock _ARG_((Vtmutex_t*));
+extern int vtmtxtrylock _ARG_((Vtmutex_t*));
+extern int vtmtxunlock _ARG_((Vtmutex_t*));
+extern int vtmtxclrlock _ARG_((Vtmutex_t*));
+
+extern Void_t* vtstatus _ARG_((Vthread_t*));
+extern int vterror _ARG_((Vthread_t*));
+extern int vtmtxerror _ARG_((Vtmutex_t*));
+extern int vtonceerror _ARG_((Vtonce_t*));
+
+_END_EXTERNS_
+
+#if vt_threaded
+
+/* mutex structure */
+struct _vtmutex_s
+{ _vtmtx_t lock;
+ int count;
+ _vtid_t owner;
+ int state;
+ int error;
+};
+
+/* structure for states of thread */
+struct _vthread_s
+{ _vtself_t self; /* self-handle */
+ _vtid_t id; /* thread id */
+ _vtattr_t attrs; /* attributes */
+ size_t stack; /* stack size */
+ int state; /* execution state */
+ int error; /* error status */
+ Void_t* exit; /* exit value */
+};
+
+/* structure for exactly once execution */
+struct _vtonce_s
+{ int done;
+ _vtonce_t once;
+ int error;
+};
+
+#if _WIN32
+#define VTONCE_INITDATA {0, 0}
+#else
+#define VTONCE_INITDATA {0, PTHREAD_ONCE_INIT }
+#endif
+
+#define vtstatus(vt) ((vt)->exit)
+#define vterror(vt) ((vt)->error)
+#define vtmtxerror(mtx) ((mtx)->error)
+#define vtonceerror(once) ((once)->error)
+
+#endif /*vt_threaded*/
+
+/* fake structures and functions */
+#if !vt_threaded
+struct _vtmutex_s
+{ int error;
+};
+struct _vtattr_s
+{ int error;
+};
+struct _vthread_s
+{ int error;
+};
+struct _vtonce_s
+{ int error;
+};
+
+typedef int _vtmtx_t;
+typedef int _vtonce_t;
+typedef int _vtself_t;
+typedef int _vtid_t;
+typedef int _vtattr_t;
+
+#define VTONCE_INITDATA {0}
+
+#define vtopen(vt,flgs) ((Vthread_t*)0)
+#define vtclose(vt) (-1)
+#define vtkill(vt) (-1)
+#define vtwait(vt) (-1)
+#define vtrun(vt,fn,arg) (-1)
+
+#define vtset(vt,t,v) (-1)
+#define vtonce(on,fu) (-1)
+
+#define vtmtxopen(mtx,flgs) ((Vtmutex_t*)0)
+#define vtmtxclose(mtx) (-1)
+#define vtmtxlock(mtx) (-1)
+#define vtmtxtrylock(mtx) (-1)
+#define vtmtxunlock(mtx) (-1)
+#define vtmtxclrlock(mtx) (-1)
+
+#define vtstatus(vt) ((Void_t*)0)
+#define vterror(vt) (0)
+#define vtmtxerror(mtx) (0)
+#define vtonceerror(once) (0)
+
+#endif /*!vt_threaded*/
+
+#endif /*_VTHREAD_H*/
diff --git a/src/lib/libast/std/bytesex.h b/src/lib/libast/std/bytesex.h
new file mode 100644
index 0000000..d8a0783
--- /dev/null
+++ b/src/lib/libast/std/bytesex.h
@@ -0,0 +1,43 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * linux/gnu compatibility
+ */
+
+#ifndef _BYTESEX_H
+#define _BYTESEX_H
+
+#include <ast_common.h>
+
+#undef __BYTE_ORDER
+
+#if ( _ast_intswap & 3 ) == 3
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#else
+#if ( _ast_intswap & 3 ) == 1
+#define __BYTE_ORDER __PDP_ENDIAN
+#else
+#define __BYTE_ORDER __BIG_ENDIAN
+#endif
+#endif
+
+#endif
diff --git a/src/lib/libast/std/dirent.h b/src/lib/libast/std/dirent.h
new file mode 100644
index 0000000..de52967
--- /dev/null
+++ b/src/lib/libast/std/dirent.h
@@ -0,0 +1,22 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include <ast_dirent.h>
diff --git a/src/lib/libast/std/endian.h b/src/lib/libast/std/endian.h
new file mode 100644
index 0000000..c54e213
--- /dev/null
+++ b/src/lib/libast/std/endian.h
@@ -0,0 +1,54 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * linux/gnu compatibility
+ */
+
+#ifndef _ENDIAN_H
+#define _ENDIAN_H
+
+#include <bytesex.h>
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __PDP_ENDIAN 3412
+
+#if defined (__USE_BSD) && !defined(__STRICT_ANSI__)
+
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN __LITTLE_ENDIAN
+#endif
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN __BIG_ENDIAN
+#endif
+
+#ifndef PDP_ENDIAN
+#define PDP_ENDIAN __PDP_ENDIAN
+#endif
+
+#undef BYTE_ORDER
+#define BYTE_ORDER __BYTE_ORDER
+
+#endif
+
+#endif
diff --git a/src/lib/libast/std/iconv.h b/src/lib/libast/std/iconv.h
new file mode 100644
index 0000000..fb82d62
--- /dev/null
+++ b/src/lib/libast/std/iconv.h
@@ -0,0 +1,22 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include <ast_iconv.h>
diff --git a/src/lib/libast/std/nl_types.h b/src/lib/libast/std/nl_types.h
new file mode 100644
index 0000000..99299a7
--- /dev/null
+++ b/src/lib/libast/std/nl_types.h
@@ -0,0 +1,22 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include <ast_nl_types.h>
diff --git a/src/lib/libast/std/stdio.h b/src/lib/libast/std/stdio.h
new file mode 100644
index 0000000..c3c09fe
--- /dev/null
+++ b/src/lib/libast/std/stdio.h
@@ -0,0 +1,22 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include <ast_stdio.h>
diff --git a/src/lib/libast/std/wchar.h b/src/lib/libast/std/wchar.h
new file mode 100644
index 0000000..9737c2d
--- /dev/null
+++ b/src/lib/libast/std/wchar.h
@@ -0,0 +1,22 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include <ast_wchar.h>
diff --git a/src/lib/libast/std/wctype.h b/src/lib/libast/std/wctype.h
new file mode 100644
index 0000000..1a3a94f
--- /dev/null
+++ b/src/lib/libast/std/wctype.h
@@ -0,0 +1,22 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include <ast_wctype.h>
diff --git a/src/lib/libast/stdio/_doprnt.c b/src/lib/libast/stdio/_doprnt.c
new file mode 100644
index 0000000..afa160d
--- /dev/null
+++ b/src/lib/libast/stdio/_doprnt.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+_doprnt(const char* fmt, va_list args, Sfio_t* f)
+{
+ STDIO_INT(f, "_doprnt", int, (const char*, va_list, Sfio_t*), (fmt, args, f))
+
+ return sfvprintf(f, fmt, args);
+}
diff --git a/src/lib/libast/stdio/_doscan.c b/src/lib/libast/stdio/_doscan.c
new file mode 100644
index 0000000..d112a40
--- /dev/null
+++ b/src/lib/libast/stdio/_doscan.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+_doscan(Sfio_t* f, const char* fmt, va_list args)
+{
+ STDIO_INT(f, "_doscan", int, (Sfio_t*, const char*, va_list), (f, fmt, args))
+
+ return sfvscanf(f, fmt, args);
+}
diff --git a/src/lib/libast/stdio/_filbuf.c b/src/lib/libast/stdio/_filbuf.c
new file mode 100644
index 0000000..f74e6d7
--- /dev/null
+++ b/src/lib/libast/stdio/_filbuf.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+_filbuf(Sfio_t* f)
+{
+ STDIO_INT(f, "_filbuf", int, (Sfio_t*), (f))
+
+ return _sffilbuf(f, 0);
+}
diff --git a/src/lib/libast/stdio/_flsbuf.c b/src/lib/libast/stdio/_flsbuf.c
new file mode 100644
index 0000000..51cbcda
--- /dev/null
+++ b/src/lib/libast/stdio/_flsbuf.c
@@ -0,0 +1,44 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+#if !STDIO_TRANSFER
+
+NoN(_flsbuf)
+
+#else
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int
+_flsbuf(int c, Sfio_t* f)
+{
+ STDIO_INT(f, "_flsbuf", int, (int, Sfio_t*), (c, f))
+
+ return _sfflsbuf(f, c);
+}
+
+#endif
diff --git a/src/lib/libast/stdio/_stdfun.c b/src/lib/libast/stdio/_stdfun.c
new file mode 100644
index 0000000..5858903
--- /dev/null
+++ b/src/lib/libast/stdio/_stdfun.c
@@ -0,0 +1,80 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if !_UWIN
+
+void _STUB_stdfun(){}
+
+#else
+
+#include <ast_windows.h>
+#include <uwin.h>
+#include <dlfcn.h>
+#include "FEATURE/uwin"
+
+#if _lib___iob_func
+#define IOB ((char*)__iob_func())
+#elif _lib___p__iob
+#define IOB ((char*)__p__iob())
+#elif _dat__iob
+#define IOB ((char*)_iob)
+#else
+#define IOB ((char*)_p__iob())
+#endif
+
+#define IOBMAX (512*32)
+
+#include "stdhdr.h"
+
+int
+_stdfun(Sfio_t* f, Funvec_t* vp)
+{
+ static char* iob;
+ static int init;
+ static void* bp;
+ static void* np;
+
+ if (!iob && !(iob = IOB))
+ return 0;
+ if (f && ((char*)f < iob || (char*)f > iob+IOBMAX))
+ return 0;
+ if (!vp->vec[1])
+ {
+ if (!init)
+ {
+ init = 1;
+ bp = dlopen("/usr/bin/stdio.dll", 0);
+ }
+ if (bp && (vp->vec[1] = (Fun_f)dlsym(bp, vp->name)))
+ return 1;
+ if (!np && !(np = dlopen("/sys/msvcrt.dll", 0)))
+ return -1;
+ if (!(vp->vec[1] = (Fun_f)dlsym(np, vp->name)))
+ return -1;
+ }
+ return 1;
+}
+
+#endif
diff --git a/src/lib/libast/stdio/_stdopen.c b/src/lib/libast/stdio/_stdopen.c
new file mode 100644
index 0000000..dc99778
--- /dev/null
+++ b/src/lib/libast/stdio/_stdopen.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/* OBSOLETE 20010101 -- use fdopen */
+
+#include "stdhdr.h"
+
+extern Sfio_t*
+_stdopen(int fd, const char* mode)
+{
+ return fdopen(fd, mode);
+}
diff --git a/src/lib/libast/stdio/_stdprintf.c b/src/lib/libast/stdio/_stdprintf.c
new file mode 100644
index 0000000..db57a8d
--- /dev/null
+++ b/src/lib/libast/stdio/_stdprintf.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/* OBSOLETE 20010101 -- use printf */
+
+#include "stdhdr.h"
+
+extern int
+_stdprintf(const char* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = sfvprintf(sfstdout, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/_stdscanf.c b/src/lib/libast/stdio/_stdscanf.c
new file mode 100644
index 0000000..386a0cb
--- /dev/null
+++ b/src/lib/libast/stdio/_stdscanf.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/* OBSOLETE 20010101 -- use scanf */
+
+#include "stdhdr.h"
+
+extern int
+_stdscanf(const char* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = sfvscanf(sfstdin, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/_stdsprnt.c b/src/lib/libast/stdio/_stdsprnt.c
new file mode 100644
index 0000000..71c8f74
--- /dev/null
+++ b/src/lib/libast/stdio/_stdsprnt.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/* OBSOLETE 20010101 -- use sprintf */
+
+#include "stdhdr.h"
+
+extern int
+_stdsprintf(char* s, const char* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = s ? sfvsprintf(s, SF_BUFSIZE, fmt, args) : -1;
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/_stdvbuf.c b/src/lib/libast/stdio/_stdvbuf.c
new file mode 100644
index 0000000..c9a2861
--- /dev/null
+++ b/src/lib/libast/stdio/_stdvbuf.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/* OBSOLETE 20010101 -- use setvbuf */
+
+#include "stdhdr.h"
+
+extern int
+_stdsetvbuf(Sfio_t* f, char* buf, int type, size_t size)
+{
+ return setvbuf(f, buf, type, size);
+}
diff --git a/src/lib/libast/stdio/_stdvsnprnt.c b/src/lib/libast/stdio/_stdvsnprnt.c
new file mode 100644
index 0000000..78fdf2d
--- /dev/null
+++ b/src/lib/libast/stdio/_stdvsnprnt.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/* OBSOLETE 20010101 -- use vsnprintf */
+
+#include "stdhdr.h"
+
+extern int
+_stdvsnprintf(char* s, int n, const char* fmt, va_list args)
+{
+ return vsnprintf(s, n, fmt, args);
+}
diff --git a/src/lib/libast/stdio/_stdvsprnt.c b/src/lib/libast/stdio/_stdvsprnt.c
new file mode 100644
index 0000000..a3b78e6
--- /dev/null
+++ b/src/lib/libast/stdio/_stdvsprnt.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/* OBSOLETE 20010101 -- use vsprintf */
+
+#include "stdhdr.h"
+
+extern int
+_stdvsprintf(char* s, const char* fmt, va_list args)
+{
+ return vsprintf(s, fmt, args);
+}
diff --git a/src/lib/libast/stdio/_stdvsscn.c b/src/lib/libast/stdio/_stdvsscn.c
new file mode 100644
index 0000000..0b1fd68
--- /dev/null
+++ b/src/lib/libast/stdio/_stdvsscn.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/* OBSOLETE 20010101 -- use vsscanf */
+
+#include "stdhdr.h"
+
+extern int
+_stdvsscanf(char* s, const char* fmt, va_list args)
+{
+ return vsscanf(s, fmt, args);
+}
diff --git a/src/lib/libast/stdio/asprintf.c b/src/lib/libast/stdio/asprintf.c
new file mode 100644
index 0000000..60f59cc
--- /dev/null
+++ b/src/lib/libast/stdio/asprintf.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+asprintf(char** s, const char* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = vasprintf(s, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/clearerr.c b/src/lib/libast/stdio/clearerr.c
new file mode 100644
index 0000000..5d2e07c
--- /dev/null
+++ b/src/lib/libast/stdio/clearerr.c
@@ -0,0 +1,33 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+clearerr(Sfio_t* f)
+{
+ STDIO_INT(f, "clearerr", int, (Sfio_t*), (f))
+
+ sfclrerr(f);
+ return sfclrlock(f);
+}
diff --git a/src/lib/libast/stdio/fclose.c b/src/lib/libast/stdio/fclose.c
new file mode 100644
index 0000000..17063cb
--- /dev/null
+++ b/src/lib/libast/stdio/fclose.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+fclose(Sfio_t* f)
+{
+ STDIO_INT(f, "fclose", int, (Sfio_t*), (f))
+
+ return sfclose(f);
+}
diff --git a/src/lib/libast/stdio/fcloseall.c b/src/lib/libast/stdio/fcloseall.c
new file mode 100644
index 0000000..94c8553
--- /dev/null
+++ b/src/lib/libast/stdio/fcloseall.c
@@ -0,0 +1,57 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+#define MAXLOOP 3
+
+int
+fcloseall(void)
+{
+ Sfpool_t* p;
+ Sfpool_t* next;
+ int n;
+ int nclose;
+ int count;
+ int loop;
+
+ STDIO_INT(0, "fcloseall", int, (void), ())
+
+ for(loop = 0; loop < MAXLOOP; ++loop)
+ { nclose = count = 0;
+ for(p = &_Sfpool; p; p = next)
+ { /* find the next legitimate pool */
+ for(next = p->next; next; next = next->next)
+ if(next->n_sf > 0)
+ break;
+ for(n = 0; n < ((p == &_Sfpool) ? p->n_sf : 1); ++n)
+ { count += 1;
+ if(sfclose(p->sf[n]) >= 0)
+ nclose += 1;
+ }
+ }
+ if(nclose == count)
+ break;
+ }
+ return 0; /* always return 0 per GNU */
+}
diff --git a/src/lib/libast/stdio/fdopen.c b/src/lib/libast/stdio/fdopen.c
new file mode 100644
index 0000000..c707c83
--- /dev/null
+++ b/src/lib/libast/stdio/fdopen.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+Sfio_t*
+fdopen(int fd, const char* mode)
+{
+ int flags;
+
+ if (fd < 0 || !(flags = _sftype(mode, NiL, NiL)))
+ return 0;
+ return sfnew(NiL, NiL, (size_t)SF_UNBOUND, fd, flags);
+}
diff --git a/src/lib/libast/stdio/feof.c b/src/lib/libast/stdio/feof.c
new file mode 100644
index 0000000..2b77397
--- /dev/null
+++ b/src/lib/libast/stdio/feof.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+#if !_UWIN
+
+NoN(feof)
+
+#else
+
+#undef feof
+
+int
+feof(Sfio_t* f)
+{
+ STDIO_INT(f, "feof", int, (Sfio_t*), (f))
+
+ return sfeof(f);
+}
+
+#endif
diff --git a/src/lib/libast/stdio/ferror.c b/src/lib/libast/stdio/ferror.c
new file mode 100644
index 0000000..d374df1
--- /dev/null
+++ b/src/lib/libast/stdio/ferror.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+#if !_UWIN
+
+NoN(ferror)
+
+#else
+
+#undef ferror
+
+int
+ferror(Sfio_t* f)
+{
+ STDIO_INT(f, "ferror", int, (Sfio_t*), (f))
+
+ return sferror(f);
+}
+
+#endif
diff --git a/src/lib/libast/stdio/fflush.c b/src/lib/libast/stdio/fflush.c
new file mode 100644
index 0000000..de6574b
--- /dev/null
+++ b/src/lib/libast/stdio/fflush.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _USE_GNU
+#define _USE_GNU
+#endif
+
+#include "stdhdr.h"
+
+int
+fflush(Sfio_t* f)
+{
+ if (!f)
+ return fcloseall();
+
+ STDIO_INT(f, "fflush", int, (Sfio_t*), (f))
+
+ if (f->extent > 0)
+ sfseek(f, (Sfoff_t)0, SEEK_CUR|SF_PUBLIC);
+ return (sfsync(f) < 0 || sfpurge(f) < 0) ? -1 : 0;
+}
diff --git a/src/lib/libast/stdio/fgetc.c b/src/lib/libast/stdio/fgetc.c
new file mode 100644
index 0000000..09d280f
--- /dev/null
+++ b/src/lib/libast/stdio/fgetc.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+fgetc(Sfio_t* f)
+{
+ STDIO_INT(f, "fgetc", int, (Sfio_t*), (f))
+
+ return sfgetc(f);
+}
diff --git a/src/lib/libast/stdio/fgetpos.c b/src/lib/libast/stdio/fgetpos.c
new file mode 100644
index 0000000..16da6fa
--- /dev/null
+++ b/src/lib/libast/stdio/fgetpos.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _NO_LARGEFILE64_SOURCE
+#define _NO_LARGEFILE64_SOURCE 1
+#endif
+
+#include "stdhdr.h"
+
+int
+fgetpos(Sfio_t* f, fpos_t* pos)
+{
+ STDIO_INT(f, "fgetpos", int, (Sfio_t*, fpos_t*), (f, pos))
+
+ return (pos->_sf_offset = sfseek(f, (Sfoff_t)0, SEEK_CUR)) >= 0 ? 0 : -1;
+}
+
+#ifdef _typ_int64_t
+
+int
+fgetpos64(Sfio_t* f, fpos64_t* pos)
+{
+ STDIO_INT(f, "fgetpos64", int, (Sfio_t*, fpos64_t*), (f, pos))
+
+ return (pos->_sf_offset = sfseek(f, (Sfoff_t)0, SEEK_CUR)) >= 0 ? 0 : -1;
+}
+
+#endif
diff --git a/src/lib/libast/stdio/fgets.c b/src/lib/libast/stdio/fgets.c
new file mode 100644
index 0000000..727974a
--- /dev/null
+++ b/src/lib/libast/stdio/fgets.c
@@ -0,0 +1,110 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+extern char*
+_stdgets(Sfio_t* f, char* us, int n, int isgets)
+{
+ int p;
+ unsigned char* is;
+ unsigned char* ps;
+
+ if(n <= 0 || !us || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0))
+ return NIL(char*);
+
+ SFLOCK(f,0);
+
+ n -= 1;
+ is = (uchar*)us;
+
+ while(n)
+ { /* peek the read buffer for data */
+ if((p = f->endb - (ps = f->next)) <= 0 )
+ { f->getr = '\n';
+ f->mode |= SF_RC;
+ if(SFRPEEK(f,ps,p) <= 0)
+ break;
+ }
+
+ if(p > n)
+ p = n;
+
+#if _lib_memccpy
+ if((ps = (uchar*)memccpy((char*)is,(char*)ps,'\n',p)) != NIL(uchar*))
+ p = ps-is;
+ is += p;
+ ps = f->next+p;
+#else
+ if(!(f->flags&(SF_BOTH|SF_MALLOC)))
+ { while(p-- && (*is++ = *ps++) != '\n')
+ ;
+ p = ps-f->next;
+ }
+ else
+ { reg int c = ps[p-1];
+ if(c != '\n')
+ ps[p-1] = '\n';
+ while((*is++ = *ps++) != '\n')
+ ;
+ if(c != '\n')
+ { f->next[p-1] = c;
+ if((ps-f->next) >= p)
+ is[-1] = c;
+ }
+ }
+#endif
+
+ /* gobble up read data and continue */
+ f->next = ps;
+ if(is[-1] == '\n')
+ break;
+ else if(n > 0)
+ n -= p;
+ }
+
+ if((_Sfi = is - ((uchar*)us)) <= 0)
+ us = NIL(char*);
+ else if(isgets && is[-1] == '\n')
+ { is[-1] = '\0';
+ _Sfi -= 1;
+ }
+ else *is = '\0';
+
+ SFOPEN(f,0);
+ return us;
+}
+
+char*
+fgets(char* s, int n, Sfio_t* f)
+{
+ STDIO_PTR(f, "fgets", char*, (char*, int, Sfio_t*), (s, n, f))
+
+ return _stdgets(f, s, n, 0);
+}
+
+char*
+gets(char* s)
+{
+ return _stdgets(sfstdin, s, BUFSIZ, 1);
+}
diff --git a/src/lib/libast/stdio/fgetwc.c b/src/lib/libast/stdio/fgetwc.c
new file mode 100644
index 0000000..64f7d83
--- /dev/null
+++ b/src/lib/libast/stdio/fgetwc.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+wint_t
+fgetwc(Sfio_t* f)
+{
+ wchar_t c;
+
+ STDIO_INT(f, "fgetwc", wint_t, (Sfio_t*), (f))
+
+ FWIDE(f, WEOF);
+ return (sfread(f, &c, sizeof(c)) == sizeof(c)) ? c : WEOF;
+}
diff --git a/src/lib/libast/stdio/fgetws.c b/src/lib/libast/stdio/fgetws.c
new file mode 100644
index 0000000..d1adbed
--- /dev/null
+++ b/src/lib/libast/stdio/fgetws.c
@@ -0,0 +1,52 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+wchar_t*
+fgetws(wchar_t* s, int n, Sfio_t* f)
+{
+ register wchar_t* p = s;
+ register wchar_t* e = s + n - 1;
+ register wint_t c;
+
+ STDIO_PTR(f, "fgets", wchar_t*, (wchar_t*, int, Sfio_t*), (s, n, f))
+
+ FWIDE(f, 0);
+ while (p < e && (c = fgetwc(f)) != WEOF && (*p++ = c) != '\n');
+ *p = 0;
+ return s;
+}
+
+wchar_t*
+getws(wchar_t* s)
+{
+ register wchar_t* p = s;
+ register wchar_t* e = s + BUFSIZ - 1;
+ register wint_t c;
+
+ FWIDE(sfstdin, 0);
+ while (p < e && (c = fgetwc(sfstdin)) != WEOF && (*p++ = c) != '\n');
+ *p = 0;
+ return s;
+}
diff --git a/src/lib/libast/stdio/fileno.c b/src/lib/libast/stdio/fileno.c
new file mode 100644
index 0000000..5ca6de8
--- /dev/null
+++ b/src/lib/libast/stdio/fileno.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+#if !_UWIN
+
+NoN(fileno)
+
+#else
+
+#undef fileno
+
+int
+fileno(Sfio_t* f)
+{
+ STDIO_INT(f, "fileno", int, (Sfio_t*), (f))
+
+ return sffileno(f);
+}
+
+#endif
diff --git a/src/lib/libast/stdio/flockfile.c b/src/lib/libast/stdio/flockfile.c
new file mode 100644
index 0000000..43141ec
--- /dev/null
+++ b/src/lib/libast/stdio/flockfile.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+void
+flockfile(Sfio_t* f)
+{
+ STDIO_VOID(f, "flockfile", void, (Sfio_t*), (f))
+
+ (void)sfmutex(f, SFMTX_LOCK);
+}
diff --git a/src/lib/libast/stdio/fmemopen.c b/src/lib/libast/stdio/fmemopen.c
new file mode 100644
index 0000000..dfb6317
--- /dev/null
+++ b/src/lib/libast/stdio/fmemopen.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+Sfio_t*
+fmemopen(void* buf, size_t size, const char* mode)
+{
+ STDIO_PTR(0, "fmemopen", Sfio_t*, (void*, size_t, const char*), (buf, size, mode))
+
+ return sfnew(NiL, buf, size, -1, SF_STRING|_sftype(mode, NiL, NiL));
+}
diff --git a/src/lib/libast/stdio/fopen.c b/src/lib/libast/stdio/fopen.c
new file mode 100644
index 0000000..4b99fef
--- /dev/null
+++ b/src/lib/libast/stdio/fopen.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+Sfio_t*
+fopen(const char* path, const char* mode)
+{
+ return sfopen(NiL, path, mode);
+}
diff --git a/src/lib/libast/stdio/fprintf.c b/src/lib/libast/stdio/fprintf.c
new file mode 100644
index 0000000..0939cc7
--- /dev/null
+++ b/src/lib/libast/stdio/fprintf.c
@@ -0,0 +1,39 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+fprintf(Sfio_t* f, const char* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+
+ STDIO_INT(f, "vfprintf", int, (Sfio_t*, const char*, va_list), (f, fmt, args))
+
+ v = sfvprintf(f, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/fpurge.c b/src/lib/libast/stdio/fpurge.c
new file mode 100644
index 0000000..eeaea0d
--- /dev/null
+++ b/src/lib/libast/stdio/fpurge.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+fpurge(Sfio_t* f)
+{
+ STDIO_INT(f, "fpurge", int, (Sfio_t*), (f))
+
+ return sfpurge(f);
+}
diff --git a/src/lib/libast/stdio/fputc.c b/src/lib/libast/stdio/fputc.c
new file mode 100644
index 0000000..72cf874
--- /dev/null
+++ b/src/lib/libast/stdio/fputc.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+#if !_UWIN
+
+NoN(fputc)
+
+#else
+
+#undef fputc
+
+int
+fputc(int c, Sfio_t* f)
+{
+ STDIO_INT(f, "fputc", int, (int, Sfio_t*), (c, f))
+
+ return sfputc(f, c);
+}
+
+#endif
diff --git a/src/lib/libast/stdio/fputs.c b/src/lib/libast/stdio/fputs.c
new file mode 100644
index 0000000..0fdc459
--- /dev/null
+++ b/src/lib/libast/stdio/fputs.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+fputs(const char* s, Sfio_t* f)
+{
+ STDIO_INT(f, "fputs", int, (const char*, Sfio_t*), (s, f))
+
+ return sfputr(f, s, -1);
+}
diff --git a/src/lib/libast/stdio/fputwc.c b/src/lib/libast/stdio/fputwc.c
new file mode 100644
index 0000000..1029a3b
--- /dev/null
+++ b/src/lib/libast/stdio/fputwc.c
@@ -0,0 +1,33 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+wint_t
+fputwc(wchar_t c, Sfio_t* f)
+{
+ STDIO_INT(f, "fputc", wint_t, (wchar_t, Sfio_t*), (c, f))
+
+ FWIDE(f, WEOF);
+ return (sfwrite(f, &c, sizeof(c)) == sizeof(c)) ? c : WEOF;
+}
diff --git a/src/lib/libast/stdio/fputws.c b/src/lib/libast/stdio/fputws.c
new file mode 100644
index 0000000..3e1034e
--- /dev/null
+++ b/src/lib/libast/stdio/fputws.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+fputws(const wchar_t* s, Sfio_t* f)
+{
+ size_t n;
+
+ STDIO_INT(f, "fputws", int, (const wchar_t*, Sfio_t*), (s, f))
+
+ FWIDE(f, WEOF);
+ n = wcslen(s) * sizeof(wchar_t);
+ return (sfwrite(f, s, n) == n) ? 0 : -1;
+}
diff --git a/src/lib/libast/stdio/fread.c b/src/lib/libast/stdio/fread.c
new file mode 100644
index 0000000..c96a1e7
--- /dev/null
+++ b/src/lib/libast/stdio/fread.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+size_t
+fread(void* p, size_t s, size_t n, Sfio_t* f)
+{
+ ssize_t v;
+
+ STDIO_INT(f, "fread", ssize_t, (void*, size_t, size_t, Sfio_t*), (p, s, n, f))
+
+ return ((v = sfread(f, p, s * n)) <= 0) ? 0 : (v / s);
+}
diff --git a/src/lib/libast/stdio/freopen.c b/src/lib/libast/stdio/freopen.c
new file mode 100644
index 0000000..e8de05b
--- /dev/null
+++ b/src/lib/libast/stdio/freopen.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+Sfio_t*
+freopen(const char* path, const char* mode, Sfio_t* f)
+{
+ STDIO_PTR(f, "freopen", Sfio_t*, (const char*, const char*, Sfio_t*), (path, mode, f))
+
+ return sfopen(f, path, mode);
+}
diff --git a/src/lib/libast/stdio/fscanf.c b/src/lib/libast/stdio/fscanf.c
new file mode 100644
index 0000000..2beb400
--- /dev/null
+++ b/src/lib/libast/stdio/fscanf.c
@@ -0,0 +1,39 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+fscanf(Sfio_t* f, const char* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+
+ STDIO_INT(f, "vfscanf", int, (Sfio_t*, const char*, va_list), (f, fmt, args))
+
+ v = sfvscanf(f, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/fseek.c b/src/lib/libast/stdio/fseek.c
new file mode 100644
index 0000000..1198a31
--- /dev/null
+++ b/src/lib/libast/stdio/fseek.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _NO_LARGEFILE64_SOURCE
+#define _NO_LARGEFILE64_SOURCE 1
+#endif
+
+#include "stdhdr.h"
+
+int
+fseek(Sfio_t* f, long off, int op)
+{
+ STDIO_INT(f, "fseek", int, (Sfio_t*, long, int), (f, off, op))
+
+ return sfseek(f, (Sfoff_t)off, op|SF_SHARE) >= 0 ? 0 : -1;
+}
+
+#ifdef _typ_int64_t
+
+int
+fseek64(Sfio_t* f, int64_t off, int op)
+{
+ STDIO_INT(f, "fseek64", int, (Sfio_t*, int64_t, int), (f, off, op))
+
+ return sfseek(f, (Sfoff_t)off, op|SF_SHARE) >= 0 ? 0 : -1;
+}
+
+#endif
diff --git a/src/lib/libast/stdio/fseeko.c b/src/lib/libast/stdio/fseeko.c
new file mode 100644
index 0000000..0cf3186
--- /dev/null
+++ b/src/lib/libast/stdio/fseeko.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _NO_LARGEFILE64_SOURCE
+#define _NO_LARGEFILE64_SOURCE 1
+#endif
+
+#include "stdhdr.h"
+
+int
+fseeko(Sfio_t* f, off_t off, int op)
+{
+ STDIO_INT(f, "fseeko", int, (Sfio_t*, off_t, int), (f, off, op))
+
+ return sfseek(f, (Sfoff_t)off, op|SF_SHARE) >= 0 ? 0 : -1;
+}
+
+#ifdef _typ_int64_t
+
+int
+fseeko64(Sfio_t* f, int64_t off, int op)
+{
+ STDIO_INT(f, "fseeko64", int, (Sfio_t*, int64_t, int), (f, off, op))
+
+ return sfseek(f, (Sfoff_t)off, op|SF_SHARE) >= 0 ? 0 : -1;
+}
+
+#endif
diff --git a/src/lib/libast/stdio/fsetpos.c b/src/lib/libast/stdio/fsetpos.c
new file mode 100644
index 0000000..cc9abbc
--- /dev/null
+++ b/src/lib/libast/stdio/fsetpos.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _NO_LARGEFILE64_SOURCE
+#define _NO_LARGEFILE64_SOURCE 1
+#endif
+
+#include "stdhdr.h"
+
+int
+fsetpos(Sfio_t* f, const fpos_t* pos)
+{
+ STDIO_INT(f, "fsetpos", int, (Sfio_t*, const fpos_t*), (f, pos))
+
+ return sfseek(f, (Sfoff_t)pos->_sf_offset, SF_PUBLIC) == (Sfoff_t)pos->_sf_offset ? 0 : -1;
+}
+
+#ifdef _typ_int64_t
+
+int
+fsetpos64(Sfio_t* f, const fpos64_t* pos)
+{
+ STDIO_INT(f, "fsetpos64", int, (Sfio_t*, const fpos64_t*), (f, pos))
+
+ return sfseek(f, (Sfoff_t)pos->_sf_offset, SF_PUBLIC) == (Sfoff_t)pos->_sf_offset ? 0 : -1;
+}
+
+#endif
diff --git a/src/lib/libast/stdio/ftell.c b/src/lib/libast/stdio/ftell.c
new file mode 100644
index 0000000..0437e48
--- /dev/null
+++ b/src/lib/libast/stdio/ftell.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _NO_LARGEFILE64_SOURCE
+#define _NO_LARGEFILE64_SOURCE 1
+#endif
+
+#include "stdhdr.h"
+
+long
+ftell(Sfio_t* f)
+{
+ STDIO_INT(f, "ftell", long, (Sfio_t*), (f))
+
+ return (long)sfseek(f, (Sfoff_t)0, SEEK_CUR);
+}
+
+#if _typ_int64_t
+
+int64_t
+ftell64(Sfio_t* f)
+{
+ STDIO_INT(f, "ftell64", int64_t, (Sfio_t*), (f))
+
+ return (int64_t)sfseek(f, (Sfoff_t)0, SEEK_CUR);
+}
+
+#endif
diff --git a/src/lib/libast/stdio/ftello.c b/src/lib/libast/stdio/ftello.c
new file mode 100644
index 0000000..f430fec
--- /dev/null
+++ b/src/lib/libast/stdio/ftello.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _NO_LARGEFILE64_SOURCE
+#define _NO_LARGEFILE64_SOURCE 1
+#endif
+
+#include "stdhdr.h"
+
+off_t
+ftello(Sfio_t* f)
+{
+ STDIO_INT(f, "ftello", off_t, (Sfio_t*), (f))
+
+ return sfseek(f, (Sfoff_t)0, SEEK_CUR);
+}
+
+#ifdef _typ_int64_t
+
+int64_t
+ftello64(Sfio_t* f)
+{
+ STDIO_INT(f, "ftello64", int64_t, (Sfio_t*), (f))
+
+ return sfseek(f, (Sfoff_t)0, SEEK_CUR) >= 0 ? 0 : -1;
+}
+
+#endif
diff --git a/src/lib/libast/stdio/ftrylockfile.c b/src/lib/libast/stdio/ftrylockfile.c
new file mode 100644
index 0000000..28501e8
--- /dev/null
+++ b/src/lib/libast/stdio/ftrylockfile.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+ftrylockfile(Sfio_t* f)
+{
+ STDIO_INT(f, "ftrylockfile", int, (Sfio_t*), (f))
+
+ return sfmutex(f, SFMTX_TRYLOCK);
+}
diff --git a/src/lib/libast/stdio/funlockfile.c b/src/lib/libast/stdio/funlockfile.c
new file mode 100644
index 0000000..33195d5
--- /dev/null
+++ b/src/lib/libast/stdio/funlockfile.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+void
+funlockfile(Sfio_t* f)
+{
+ STDIO_VOID(f, "funlockfile", void, (Sfio_t*), (f))
+
+ (void)sfmutex(f, SFMTX_UNLOCK);
+}
diff --git a/src/lib/libast/stdio/fwide.c b/src/lib/libast/stdio/fwide.c
new file mode 100644
index 0000000..efcb453
--- /dev/null
+++ b/src/lib/libast/stdio/fwide.c
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+fwide(Sfio_t* f, int mode)
+{
+ STDIO_INT(f, "fwide", int, (Sfio_t*, int), (f, mode))
+
+ if (mode > 0)
+ {
+ f->bits &= ~SF_MB;
+ f->bits |= SF_WC;
+ }
+ else if (mode < 0)
+ {
+ f->bits &= ~SF_WC;
+ f->bits |= SF_MB;
+ }
+ if (f->bits & SF_MB)
+ return -1;
+ if (f->bits & SF_WC)
+ return 1;
+ if ((f->flags & SF_SYNCED) || f->next > f->data)
+ {
+ f->bits |= SF_MB;
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/lib/libast/stdio/fwprintf.c b/src/lib/libast/stdio/fwprintf.c
new file mode 100644
index 0000000..b4726e3
--- /dev/null
+++ b/src/lib/libast/stdio/fwprintf.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+fwprintf(Sfio_t* f, const wchar_t* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = vfwprintf(f, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/fwrite.c b/src/lib/libast/stdio/fwrite.c
new file mode 100644
index 0000000..12bfe89
--- /dev/null
+++ b/src/lib/libast/stdio/fwrite.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+size_t
+fwrite(const void* p, size_t s, size_t n, Sfio_t* f)
+{
+ ssize_t v;
+
+ STDIO_INT(f, "fwrite", ssize_t, (const void*, size_t, size_t, Sfio_t*), (p, s, n, f))
+
+ return ((v = sfwrite(f, p, s * n)) <= 0) ? 0 : (v / s);
+}
diff --git a/src/lib/libast/stdio/fwscanf.c b/src/lib/libast/stdio/fwscanf.c
new file mode 100644
index 0000000..f64f203
--- /dev/null
+++ b/src/lib/libast/stdio/fwscanf.c
@@ -0,0 +1,39 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+fwscanf(Sfio_t* f, const wchar_t* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+
+ STDIO_INT(f, "vfwscanf", int, (Sfio_t*, const wchar_t*, va_list), (f, fmt, args))
+
+ v = vfwscanf(f, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/getc.c b/src/lib/libast/stdio/getc.c
new file mode 100644
index 0000000..b04507f
--- /dev/null
+++ b/src/lib/libast/stdio/getc.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+#if !_UWIN
+
+NoN(getc)
+
+#else
+
+#undef getc
+
+int
+getc(Sfio_t* f)
+{
+ STDIO_INT(f, "getc", int, (Sfio_t*), (f))
+
+ return sfgetc(f);
+}
+
+#endif
diff --git a/src/lib/libast/stdio/getchar.c b/src/lib/libast/stdio/getchar.c
new file mode 100644
index 0000000..80781eb
--- /dev/null
+++ b/src/lib/libast/stdio/getchar.c
@@ -0,0 +1,40 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+#if !_UWIN
+
+NoN(getchar)
+
+#else
+
+#undef getchar
+
+int
+getchar(void)
+{
+ return sfgetc(sfstdin);
+}
+
+#endif
diff --git a/src/lib/libast/stdio/getdelim.c b/src/lib/libast/stdio/getdelim.c
new file mode 100644
index 0000000..331125a
--- /dev/null
+++ b/src/lib/libast/stdio/getdelim.c
@@ -0,0 +1,96 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+ssize_t
+getdelim(char** sp, size_t* np, int delim, Sfio_t* f)
+{
+ ssize_t m;
+ ssize_t n;
+ ssize_t k;
+ ssize_t p;
+ uchar* s;
+ uchar* ps;
+ SFMTXDECL(f);
+
+ STDIO_INT(f, "getdelim", ssize_t, (char**, size_t*, int, Sfio_t*), (sp, np, delim, f))
+
+ SFMTXENTER(f, -1);
+
+ if(delim < 0 || delim > 255 || !sp || !np) /* bad parameters */
+ SFMTXRETURN(f, -1);
+
+ if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)
+ SFMTXRETURN(f, -1);
+
+ SFLOCK(f,0);
+
+ if(!(s = (uchar*)(*sp)) || (n = *np) < 0)
+ { s = NIL(uchar*); n = 0; }
+ for(m = 0;; )
+ { /* read new data */
+ if((p = f->endb - (ps = f->next)) <= 0 )
+ { f->getr = delim;
+ f->mode |= SF_RC;
+ if(SFRPEEK(f,ps,p) <= 0)
+ { m = -1;
+ break;
+ }
+ }
+
+ for(k = 0; k < p; ++k) /* find the delimiter */
+ { if(ps[k] == delim)
+ { k += 1; /* include delim in copying */
+ break;
+ }
+ }
+
+ if((m+k+1) >= n ) /* make sure there is space */
+ { n = ((m+k+15)/8)*8;
+ if(!(s = (uchar*)realloc(s, n)) )
+ { *sp = 0; *np = 0;
+ m = -1;
+ break;
+ }
+ *sp = (char*)s; *np = n;
+ }
+
+ memcpy(s+m, ps, k); m += k;
+ f->next = ps+k; /* skip copied data in buffer */
+
+ if(s[m-1] == delim)
+ { s[m] = 0; /* 0-terminated */
+ break;
+ }
+ }
+
+ SFOPEN(f,0);
+ SFMTXRETURN(f,m);
+}
+
+ssize_t
+__getdelim(char** sp, size_t* np, int delim, Sfio_t* f)
+{
+ return getdelim(sp, np, delim, f);
+}
diff --git a/src/lib/libast/stdio/getline.c b/src/lib/libast/stdio/getline.c
new file mode 100644
index 0000000..914a5c1
--- /dev/null
+++ b/src/lib/libast/stdio/getline.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _USE_GNU
+#define _USE_GNU
+#endif
+
+#include "stdhdr.h"
+
+ssize_t
+getline(char** sp, size_t* np, Sfio_t* f)
+{
+ STDIO_INT(f, "getline", ssize_t, (char**, size_t*, Sfio_t*), (sp, np, f))
+
+ return getdelim(sp, np, '\n', f);
+}
diff --git a/src/lib/libast/stdio/getw.c b/src/lib/libast/stdio/getw.c
new file mode 100644
index 0000000..b0063be
--- /dev/null
+++ b/src/lib/libast/stdio/getw.c
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+getw(Sfio_t* f)
+{
+ int v;
+
+ STDIO_INT(f, "getw", int, (Sfio_t*), (f))
+
+ return sfread(f, &v, sizeof(v)) == sizeof(v) ? v : -1;
+}
diff --git a/src/lib/libast/stdio/getwc.c b/src/lib/libast/stdio/getwc.c
new file mode 100644
index 0000000..7e4a39f
--- /dev/null
+++ b/src/lib/libast/stdio/getwc.c
@@ -0,0 +1,31 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+#include "ast_wchar.h"
+
+wint_t
+getwc(Sfio_t* f)
+{
+ return fgetwc(f);
+}
diff --git a/src/lib/libast/stdio/getwchar.c b/src/lib/libast/stdio/getwchar.c
new file mode 100644
index 0000000..4564c2a
--- /dev/null
+++ b/src/lib/libast/stdio/getwchar.c
@@ -0,0 +1,31 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+#include "ast_wchar.h"
+
+wint_t
+getwchar(void)
+{
+ return fgetwc(sfstdin);
+}
diff --git a/src/lib/libast/stdio/pclose.c b/src/lib/libast/stdio/pclose.c
new file mode 100644
index 0000000..b06b25a
--- /dev/null
+++ b/src/lib/libast/stdio/pclose.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+pclose(Sfio_t* f)
+{
+ STDIO_INT(f, "pclose", int, (Sfio_t*), (f))
+
+ return sfclose(f);
+}
diff --git a/src/lib/libast/stdio/popen.c b/src/lib/libast/stdio/popen.c
new file mode 100644
index 0000000..61968aa
--- /dev/null
+++ b/src/lib/libast/stdio/popen.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+Sfio_t*
+popen(const char* cmd, const char* mode)
+{
+ return sfpopen((Sfio_t*)(-1), cmd, mode);
+}
diff --git a/src/lib/libast/stdio/printf.c b/src/lib/libast/stdio/printf.c
new file mode 100644
index 0000000..ca999f4
--- /dev/null
+++ b/src/lib/libast/stdio/printf.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+printf(const char* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = sfvprintf(sfstdout, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/putc.c b/src/lib/libast/stdio/putc.c
new file mode 100644
index 0000000..34d1b14
--- /dev/null
+++ b/src/lib/libast/stdio/putc.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+#if !_UWIN
+
+NoN(putc)
+
+#else
+
+#undef putc
+
+int
+putc(int c, Sfio_t* f)
+{
+ STDIO_INT(f, "putc", int, (int, Sfio_t*), (c, f))
+
+ return sfputc(f, c);
+}
+
+#endif
diff --git a/src/lib/libast/stdio/putchar.c b/src/lib/libast/stdio/putchar.c
new file mode 100644
index 0000000..5fb8217
--- /dev/null
+++ b/src/lib/libast/stdio/putchar.c
@@ -0,0 +1,40 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+#if !_UWIN
+
+NoN(putchar)
+
+#else
+
+#undef putchar
+
+int
+putchar(int c)
+{
+ return sfputc(sfstdout, c);
+}
+
+#endif
diff --git a/src/lib/libast/stdio/puts.c b/src/lib/libast/stdio/puts.c
new file mode 100644
index 0000000..3ef397b
--- /dev/null
+++ b/src/lib/libast/stdio/puts.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+puts(const char* s)
+{
+ return sfputr(sfstdout, s, '\n');
+}
diff --git a/src/lib/libast/stdio/putw.c b/src/lib/libast/stdio/putw.c
new file mode 100644
index 0000000..626439d
--- /dev/null
+++ b/src/lib/libast/stdio/putw.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+putw(int v, Sfio_t* f)
+{
+ STDIO_INT(f, "putw", int, (int, Sfio_t*), (v, f))
+
+ return sfwrite(f, &v, sizeof(v)) == sizeof(v) ? 0 : -1;
+}
diff --git a/src/lib/libast/stdio/putwc.c b/src/lib/libast/stdio/putwc.c
new file mode 100644
index 0000000..8a4e86e
--- /dev/null
+++ b/src/lib/libast/stdio/putwc.c
@@ -0,0 +1,31 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+#include "ast_wchar.h"
+
+wint_t
+putwc(wchar_t c, Sfio_t* f)
+{
+ return fputwc(c, f);
+}
diff --git a/src/lib/libast/stdio/putwchar.c b/src/lib/libast/stdio/putwchar.c
new file mode 100644
index 0000000..70c967f
--- /dev/null
+++ b/src/lib/libast/stdio/putwchar.c
@@ -0,0 +1,31 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+#include "ast_wchar.h"
+
+wint_t
+putwchar(wchar_t c)
+{
+ return fputwc(c, sfstdout);
+}
diff --git a/src/lib/libast/stdio/rewind.c b/src/lib/libast/stdio/rewind.c
new file mode 100644
index 0000000..d82985c
--- /dev/null
+++ b/src/lib/libast/stdio/rewind.c
@@ -0,0 +1,33 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+void
+rewind(Sfio_t* f)
+{
+ STDIO_VOID(f, "rewind", void, (Sfio_t*), (f))
+
+ sfseek(f, (Sfoff_t)0, SEEK_SET|SF_PUBLIC);
+ sfclrlock(f);
+}
diff --git a/src/lib/libast/stdio/scanf.c b/src/lib/libast/stdio/scanf.c
new file mode 100644
index 0000000..5b2976e
--- /dev/null
+++ b/src/lib/libast/stdio/scanf.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+scanf(const char* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = sfvscanf(sfstdin, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/setbuf.c b/src/lib/libast/stdio/setbuf.c
new file mode 100644
index 0000000..83d6132
--- /dev/null
+++ b/src/lib/libast/stdio/setbuf.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+void
+setbuf(Sfio_t* f, char* b)
+{
+ STDIO_VOID(f, "setbuf", void, (Sfio_t*, char*), (f, b))
+
+ sfsetbuf(f, b, b ? BUFSIZ : 0);
+}
diff --git a/src/lib/libast/stdio/setbuffer.c b/src/lib/libast/stdio/setbuffer.c
new file mode 100644
index 0000000..6211c72
--- /dev/null
+++ b/src/lib/libast/stdio/setbuffer.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+setbuffer(Sfio_t* f, char* b, int n)
+{
+ STDIO_INT(f, "setbuffer", int, (Sfio_t*, char*, int), (f, b, n))
+
+ return sfsetbuf(f, b, n) ? 0 : -1;
+}
diff --git a/src/lib/libast/stdio/setlinebuf.c b/src/lib/libast/stdio/setlinebuf.c
new file mode 100644
index 0000000..b18b151
--- /dev/null
+++ b/src/lib/libast/stdio/setlinebuf.c
@@ -0,0 +1,33 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+setlinebuf(Sfio_t* f)
+{
+ STDIO_INT(f, "setlinebuf", int, (Sfio_t*), (f))
+
+ sfset(f, SF_LINE, 1);
+ return 0;
+}
diff --git a/src/lib/libast/stdio/setvbuf.c b/src/lib/libast/stdio/setvbuf.c
new file mode 100644
index 0000000..c8a38f8
--- /dev/null
+++ b/src/lib/libast/stdio/setvbuf.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+setvbuf(Sfio_t* f, char* buf, int type, size_t size)
+{
+ STDIO_INT(f, "setvbuf", int, (Sfio_t*, char*, int, size_t), (f, buf, type, size))
+
+ if (type == _IOLBF)
+ sfset(f, SF_LINE, 1);
+ else if (f->flags & SF_STRING)
+ return -1;
+ else if (type == _IONBF)
+ {
+ sfsync(f);
+ sfsetbuf(f, NiL, 0);
+ }
+ else if (type == _IOFBF)
+ {
+ if (size == 0)
+ size = SF_BUFSIZE;
+ sfsync(f);
+ sfsetbuf(f, (Void_t*)buf, size);
+ }
+ return 0;
+}
diff --git a/src/lib/libast/stdio/snprintf.c b/src/lib/libast/stdio/snprintf.c
new file mode 100644
index 0000000..f30c243
--- /dev/null
+++ b/src/lib/libast/stdio/snprintf.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+snprintf(char* s, int n, const char* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = sfvsprintf(s, n, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/sprintf.c b/src/lib/libast/stdio/sprintf.c
new file mode 100644
index 0000000..3a8139a
--- /dev/null
+++ b/src/lib/libast/stdio/sprintf.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+sprintf(char* s, const char* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = s ? sfvsprintf(s, INT_MAX, fmt, args) : -1;
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/sscanf.c b/src/lib/libast/stdio/sscanf.c
new file mode 100644
index 0000000..c04d2d3
--- /dev/null
+++ b/src/lib/libast/stdio/sscanf.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+sscanf(const char* s, const char* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = sfvsscanf(s, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/stdhdr.h b/src/lib/libast/stdio/stdhdr.h
new file mode 100644
index 0000000..1b2a930
--- /dev/null
+++ b/src/lib/libast/stdio/stdhdr.h
@@ -0,0 +1,115 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#ifndef _STDHDR_H
+#define _STDHDR_H 1
+
+#ifndef _NO_LARGEFILE64_SOURCE
+#define _NO_LARGEFILE64_SOURCE 1
+#endif
+#undef _LARGEFILE64_SOURCE
+
+#define _ast_fseeko ______fseeko
+#define _ast_ftello ______ftello
+#include "sfhdr.h"
+#undef _ast_fseeko
+#undef _ast_ftello
+
+#include "stdio.h"
+
+#define SF_MB 010000
+#define SF_WC 020000
+
+#if _UWIN
+
+#define STDIO_TRANSFER 1
+
+typedef int (*Fun_f)();
+
+typedef struct Funvec_s
+{
+ const char* name;
+ Fun_f vec[2];
+} Funvec_t;
+
+extern int _stdfun(Sfio_t*, Funvec_t*);
+
+#define STDIO_INT(p,n,t,f,a) \
+ { \
+ typedef t (*_s_f)f; \
+ int _i; \
+ static Funvec_t _v = { n }; \
+ if ((_i = _stdfun(p, &_v)) < 0) \
+ return -1; \
+ else if (_i > 0) \
+ return ((_s_f)_v.vec[_i])a; \
+ }
+
+#define STDIO_PTR(p,n,t,f,a) \
+ { \
+ typedef t (*_s_f)f; \
+ int _i; \
+ static Funvec_t _v = { n }; \
+ if ((_i = _stdfun(p, &_v)) < 0) \
+ return 0; \
+ else if (_i > 0) \
+ return ((_s_f)_v.vec[_i])a; \
+ }
+
+#define STDIO_VOID(p,n,t,f,a) \
+ { \
+ typedef t (*_s_f)f; \
+ int _i; \
+ static Funvec_t _v = { n }; \
+ if ((_i = _stdfun(p, &_v)) < 0) \
+ return; \
+ else if (_i > 0) \
+ { \
+ ((_s_f)_v.vec[_i])a; \
+ return; \
+ } \
+ }
+
+#else
+
+#define STDIO_INT(p,n,t,f,a)
+#define STDIO_PTR(p,n,t,f,a)
+#define STDIO_VOID(p,n,t,f,a)
+
+#endif
+
+#define FWIDE(f,r) \
+ do \
+ { \
+ if (fwide(f, 0) < 0) \
+ return r; \
+ f->bits |= SF_WC; \
+ } while (0)
+
+#ifdef __EXPORT__
+#define extern __EXPORT__
+#endif
+
+extern int sfdcwide(Sfio_t*);
+
+#endif
diff --git a/src/lib/libast/stdio/stdio_c99.c b/src/lib/libast/stdio/stdio_c99.c
new file mode 100644
index 0000000..f8d0f8d
--- /dev/null
+++ b/src/lib/libast/stdio/stdio_c99.c
@@ -0,0 +1,118 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * C99 stdio extensions
+ */
+
+#include "stdhdr.h"
+
+void
+clearerr_unlocked(Sfio_t* sp)
+{
+ clearerr(sp);
+}
+
+int
+feof_unlocked(Sfio_t* sp)
+{
+ return feof(sp);
+}
+
+int
+ferror_unlocked(Sfio_t* sp)
+{
+ return ferror(sp);
+}
+
+int
+fflush_unlocked(Sfio_t* sp)
+{
+ return fflush(sp);
+}
+
+int
+fgetc_unlocked(Sfio_t* sp)
+{
+ return fgetc(sp);
+}
+
+char*
+fgets_unlocked(char* buf, int size, Sfio_t* sp)
+{
+ return fgets(buf, size, sp);
+}
+
+int
+fileno_unlocked(Sfio_t* sp)
+{
+ return fileno(sp);
+}
+
+int
+fputc_unlocked(int c, Sfio_t* sp)
+{
+ return fputc(c, sp);
+}
+
+int
+fputs_unlocked(char* buf, Sfio_t* sp)
+{
+ return fputs(buf, sp);
+}
+
+size_t
+fread_unlocked(void* buf, size_t size, size_t n, Sfio_t* sp)
+{
+ return fread(buf, size, n, sp);
+}
+
+size_t
+fwrite_unlocked(void* buf, size_t size, size_t n, Sfio_t* sp)
+{
+ return fwrite(buf, size, n, sp);
+}
+
+int
+getc_unlocked(Sfio_t* sp)
+{
+ return getc(sp);
+}
+
+int
+getchar_unlocked(void)
+{
+ return getchar();
+}
+
+int
+putc_unlocked(int c, Sfio_t* sp)
+{
+ return putc(c, sp);
+}
+
+int
+putchar_unlocked(int c)
+{
+ return putchar(c);
+}
diff --git a/src/lib/libast/stdio/swprintf.c b/src/lib/libast/stdio/swprintf.c
new file mode 100644
index 0000000..6bb0942
--- /dev/null
+++ b/src/lib/libast/stdio/swprintf.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+swprintf(wchar_t* s, size_t size, const wchar_t* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = vswprintf(s, size, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/swscanf.c b/src/lib/libast/stdio/swscanf.c
new file mode 100644
index 0000000..00f27a4
--- /dev/null
+++ b/src/lib/libast/stdio/swscanf.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+swscanf(const wchar_t* s, const wchar_t* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = vswscanf(s, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/tmpfile.c b/src/lib/libast/stdio/tmpfile.c
new file mode 100644
index 0000000..c913dc8
--- /dev/null
+++ b/src/lib/libast/stdio/tmpfile.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+Sfio_t*
+tmpfile(void)
+{
+ return sftmp(0);
+}
diff --git a/src/lib/libast/stdio/ungetc.c b/src/lib/libast/stdio/ungetc.c
new file mode 100644
index 0000000..e448beb
--- /dev/null
+++ b/src/lib/libast/stdio/ungetc.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+ungetc(int c, Sfio_t* f)
+{
+ STDIO_INT(f, "ungetc", int, (int, Sfio_t*), (c, f))
+
+ return sfungetc(f, c);
+}
diff --git a/src/lib/libast/stdio/ungetwc.c b/src/lib/libast/stdio/ungetwc.c
new file mode 100644
index 0000000..4877f0c
--- /dev/null
+++ b/src/lib/libast/stdio/ungetwc.c
@@ -0,0 +1,39 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+wint_t
+ungetwc(wint_t c, Sfio_t* f)
+{
+ register unsigned char* s = (unsigned char*)&c;
+ register unsigned char* e = s + sizeof(c);
+
+ STDIO_INT(f, "ungetwc", wint_t, (wint_t, Sfio_t*), (c, f))
+
+ FWIDE(f, WEOF);
+ while (s < e)
+ if (sfungetc(f, *s++) == EOF)
+ return WEOF;
+ return c;
+}
diff --git a/src/lib/libast/stdio/vasprintf.c b/src/lib/libast/stdio/vasprintf.c
new file mode 100644
index 0000000..f03397f
--- /dev/null
+++ b/src/lib/libast/stdio/vasprintf.c
@@ -0,0 +1,45 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vasprintf(char** s, const char* fmt, va_list args)
+{
+ Sfio_t* f;
+ int v;
+
+ if (f = sfstropen())
+ {
+ v = sfvprintf(f, fmt, args);
+ if (!(*s = strdup(sfstruse(f))))
+ v = -1;
+ sfstrclose(f);
+ }
+ else
+ {
+ *s = 0;
+ v = -1;
+ }
+ return v;
+}
diff --git a/src/lib/libast/stdio/vfprintf.c b/src/lib/libast/stdio/vfprintf.c
new file mode 100644
index 0000000..04a2e2f
--- /dev/null
+++ b/src/lib/libast/stdio/vfprintf.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vfprintf(Sfio_t* f, const char* fmt, va_list args)
+{
+ STDIO_INT(f, "vfprintf", int, (Sfio_t*, const char*, va_list), (f, fmt, args))
+
+ return sfvprintf(f, fmt, args);
+}
diff --git a/src/lib/libast/stdio/vfscanf.c b/src/lib/libast/stdio/vfscanf.c
new file mode 100644
index 0000000..f9bcc01
--- /dev/null
+++ b/src/lib/libast/stdio/vfscanf.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vfscanf(Sfio_t* f, const char* fmt, va_list args)
+{
+ STDIO_INT(f, "vfscanf", int, (Sfio_t*, const char*, va_list), (f, fmt, args))
+
+ return sfvscanf(f, fmt, args);
+}
diff --git a/src/lib/libast/stdio/vfwprintf.c b/src/lib/libast/stdio/vfwprintf.c
new file mode 100644
index 0000000..b396792
--- /dev/null
+++ b/src/lib/libast/stdio/vfwprintf.c
@@ -0,0 +1,68 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vfwprintf(Sfio_t* f, const wchar_t* fmt, va_list args)
+{
+ char* m;
+ char* x;
+ wchar_t*w;
+ size_t n;
+ int v;
+ Sfio_t* t;
+
+ STDIO_INT(f, "vfwprintf", int, (Sfio_t*, const wchar_t*, va_list), (f, fmt, args))
+
+ FWIDE(f, WEOF);
+ n = wcstombs(NiL, fmt, 0);
+ if (m = malloc(n + 1))
+ {
+ if (t = sfstropen())
+ {
+ wcstombs(m, fmt, n + 1);
+ sfvprintf(t, m, args);
+ free(m);
+ if (!(x = sfstruse(t)))
+ v = -1;
+ else
+ {
+ n = mbstowcs(NiL, x, 0);
+ if (w = (wchar_t*)sfreserve(f, n * sizeof(wchar_t) + 1, 0))
+ v = mbstowcs(w, x, n + 1);
+ else
+ v = -1;
+ }
+ sfstrclose(t);
+ }
+ else
+ {
+ free(m);
+ v = -1;
+ }
+ }
+ else
+ v = -1;
+ return v;
+}
diff --git a/src/lib/libast/stdio/vfwscanf.c b/src/lib/libast/stdio/vfwscanf.c
new file mode 100644
index 0000000..ca23f9a
--- /dev/null
+++ b/src/lib/libast/stdio/vfwscanf.c
@@ -0,0 +1,129 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+typedef struct
+{
+ Sfdisc_t sfdisc; /* sfio discipline */
+ Sfio_t* f; /* original wide stream */
+ char fmt[1]; /* mb fmt */
+} Wide_t;
+
+/*
+ * wide exception handler
+ * free on close
+ */
+
+static int
+wideexcept(Sfio_t* f, int op, void* val, Sfdisc_t* dp)
+{
+ if (sffileno(f) >= 0)
+ return -1;
+ switch (op)
+ {
+ case SF_ATEXIT:
+ sfdisc(f, SF_POPDISC);
+ break;
+ case SF_CLOSING:
+ case SF_DPOP:
+ case SF_FINAL:
+ if (op != SF_CLOSING)
+ free(dp);
+ break;
+ }
+ return 0;
+}
+
+/*
+ * sfio wide discipline read
+ * 1 wchar_t at a time
+ * go pure multibyte for best performance
+ */
+
+static ssize_t
+wideread(Sfio_t* f, Void_t* buf, size_t size, Sfdisc_t* dp)
+{
+ register Wide_t* w = (Wide_t*)dp;
+ wchar_t wuf[2];
+
+#if 0
+ if (sfread(w->f, wuf, sizeof(wuf[0])) != sizeof(wuf[0]))
+ return -1;
+ wuf[1] = 0;
+ return wcstombs(buf, wuf, size);
+#else
+ ssize_t r;
+
+ r = sfread(w->f, wuf, sizeof(wuf[0]));
+ if (r != sizeof(wuf[0]))
+ return -1;
+ wuf[1] = 0;
+ r = wcstombs(buf, wuf, size);
+ return r;
+#endif
+}
+
+int
+vfwscanf(Sfio_t* f, const wchar_t* fmt, va_list args)
+{
+ size_t n;
+ int v;
+ Sfio_t* t;
+ Wide_t* w;
+ char buf[1024];
+
+ STDIO_INT(f, "vfwscanf", int, (Sfio_t*, const wchar_t*, va_list), (f, fmt, args))
+
+ FWIDE(f, WEOF);
+ n = wcstombs(NiL, fmt, 0);
+ if (w = newof(0, Wide_t, 1, n))
+ {
+ if (t = sfnew(NiL, buf, sizeof(buf), OPEN_MAX+1, SF_READ))
+ {
+ w->sfdisc.exceptf = wideexcept;
+ w->sfdisc.readf = wideread;
+ w->f = f;
+ if (sfdisc(t, &w->sfdisc) == &w->sfdisc)
+ {
+ wcstombs(w->fmt, fmt, n + 1);
+ v = sfvscanf(t, w->fmt, args);
+ }
+ else
+ {
+ free(w);
+ v = -1;
+ }
+ sfsetfd(t, -1);
+ sfclose(t);
+ }
+ else
+ {
+ free(w);
+ v = -1;
+ }
+ }
+ else
+ v = -1;
+ return v;
+}
diff --git a/src/lib/libast/stdio/vprintf.c b/src/lib/libast/stdio/vprintf.c
new file mode 100644
index 0000000..e8764f3
--- /dev/null
+++ b/src/lib/libast/stdio/vprintf.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vprintf(const char* fmt, va_list args)
+{
+ return sfvprintf(sfstdout, fmt, args);
+}
diff --git a/src/lib/libast/stdio/vscanf.c b/src/lib/libast/stdio/vscanf.c
new file mode 100644
index 0000000..33371d9
--- /dev/null
+++ b/src/lib/libast/stdio/vscanf.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vscanf(const char* fmt, va_list args)
+{
+ return sfvscanf(sfstdin, fmt, args);
+}
diff --git a/src/lib/libast/stdio/vsnprintf.c b/src/lib/libast/stdio/vsnprintf.c
new file mode 100644
index 0000000..5cde8fa
--- /dev/null
+++ b/src/lib/libast/stdio/vsnprintf.c
@@ -0,0 +1,52 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vsnprintf(char* s, int n, const char* form, va_list args)
+{
+ Sfio_t* f;
+ ssize_t rv;
+
+ /* make a temp stream */
+ if(!(f = sfnew(NIL(Sfio_t*),NIL(char*),(size_t)SF_UNBOUND,
+ -1,SF_WRITE|SF_STRING)) )
+ return -1;
+
+ if((rv = sfvprintf(f,form,args)) >= 0 )
+ { if(s && n > 0)
+ { if((rv+1) >= n)
+ n--;
+ else
+ n = rv;
+ memcpy(s, f->data, n);
+ s[n] = 0;
+ }
+ _Sfi = rv;
+ }
+
+ sfclose(f);
+
+ return rv;
+}
diff --git a/src/lib/libast/stdio/vsprintf.c b/src/lib/libast/stdio/vsprintf.c
new file mode 100644
index 0000000..8e44614
--- /dev/null
+++ b/src/lib/libast/stdio/vsprintf.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vsprintf(char* s, const char* fmt, va_list args)
+{
+ return vsnprintf(s, 4 * SF_BUFSIZE, fmt, args);
+}
diff --git a/src/lib/libast/stdio/vsscanf.c b/src/lib/libast/stdio/vsscanf.c
new file mode 100644
index 0000000..b7f14d6
--- /dev/null
+++ b/src/lib/libast/stdio/vsscanf.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vsscanf(const char* s, const char* fmt, va_list args)
+{
+ return sfvsscanf(s, fmt, args);
+}
diff --git a/src/lib/libast/stdio/vswprintf.c b/src/lib/libast/stdio/vswprintf.c
new file mode 100644
index 0000000..ac09afb
--- /dev/null
+++ b/src/lib/libast/stdio/vswprintf.c
@@ -0,0 +1,55 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vswprintf(wchar_t* s, size_t n, const wchar_t* fmt, va_list args)
+{
+ Sfio_t f;
+ int v;
+
+ if (!s)
+ return -1;
+
+ /*
+ * make a fake stream
+ */
+
+ SFCLEAR(&f, NiL);
+ f.flags = SF_STRING|SF_WRITE;
+ f.bits = SF_PRIVATE;
+ f.mode = SF_WRITE;
+ f.size = n - 1;
+ f.data = f.next = f.endr = (uchar*)s;
+ f.endb = f.endw = f.data + f.size;
+
+ /*
+ * call and adjust
+ */
+
+ v = vfwprintf(&f, fmt, args);
+ *f.next = 0;
+ _Sfi = f.next - f.data;
+ return v;
+}
diff --git a/src/lib/libast/stdio/vswscanf.c b/src/lib/libast/stdio/vswscanf.c
new file mode 100644
index 0000000..3f6d96c
--- /dev/null
+++ b/src/lib/libast/stdio/vswscanf.c
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vswscanf(const wchar_t* s, const wchar_t* fmt, va_list args)
+{
+ Sfio_t f;
+
+ if (!s)
+ return -1;
+
+ /*
+ * make a fake stream
+ */
+
+ SFCLEAR(&f, NiL);
+ f.flags = SF_STRING|SF_READ;
+ f.bits = SF_PRIVATE;
+ f.mode = SF_READ;
+ f.size = wcslen(s) * sizeof(wchar_t);
+ f.data = f.next = f.endw = (uchar*)s;
+ f.endb = f.endr = f.data + f.size;
+
+ /*
+ * sfio does the rest
+ */
+
+ return vfwscanf(&f, fmt, args);
+}
diff --git a/src/lib/libast/stdio/vwprintf.c b/src/lib/libast/stdio/vwprintf.c
new file mode 100644
index 0000000..60e9dea
--- /dev/null
+++ b/src/lib/libast/stdio/vwprintf.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vwprintf(const wchar_t* fmt, va_list args)
+{
+ return vfwprintf(sfstdout, fmt, args);
+}
diff --git a/src/lib/libast/stdio/vwscanf.c b/src/lib/libast/stdio/vwscanf.c
new file mode 100644
index 0000000..dd5007f
--- /dev/null
+++ b/src/lib/libast/stdio/vwscanf.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+vwscanf(const wchar_t* fmt, va_list args)
+{
+ return vfwscanf(sfstdin, fmt, args);
+}
diff --git a/src/lib/libast/stdio/wprintf.c b/src/lib/libast/stdio/wprintf.c
new file mode 100644
index 0000000..bf8949a
--- /dev/null
+++ b/src/lib/libast/stdio/wprintf.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+wprintf(const wchar_t* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = vfwprintf(sfstdout, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/stdio/wscanf.c b/src/lib/libast/stdio/wscanf.c
new file mode 100644
index 0000000..7c783b8
--- /dev/null
+++ b/src/lib/libast/stdio/wscanf.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include "stdhdr.h"
+
+int
+wscanf(const wchar_t* fmt, ...)
+{
+ va_list args;
+ int v;
+
+ va_start(args, fmt);
+ v = vfwscanf(sfstdin, fmt, args);
+ va_end(args);
+ return v;
+}
diff --git a/src/lib/libast/string/base64.c b/src/lib/libast/string/base64.c
new file mode 100644
index 0000000..fc07986
--- /dev/null
+++ b/src/lib/libast/string/base64.c
@@ -0,0 +1,312 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * mime base64 encode/decode
+ *
+ * Glenn Fowler
+ * David Korn
+ * AT&T Research
+ */
+
+#include <ast.h>
+
+#define PAD '='
+
+#define B64_UC 3
+#define B64_EC 4
+#define B64_CHUNK 15
+#define B64_PAD 64
+#define B64_SPC 65
+#define B64_IGN 66
+
+static unsigned char map[UCHAR_MAX+1];
+
+static const char alp[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/*
+ * mime base64 encode
+ */
+
+ssize_t
+base64encode(const void* fb, size_t fz, void** fn, void* tb, size_t tz, void** tn)
+{
+ register unsigned char* fp;
+ register unsigned char* tp;
+ register unsigned char* fe;
+ register unsigned char* te;
+ register unsigned char* tc;
+ register unsigned char* m;
+ register unsigned long b;
+ size_t n;
+ unsigned char tmp[B64_EC * B64_CHUNK];
+
+ m = (unsigned char*)alp;
+ fp = fe = (unsigned char*)fb;
+ if (fz >= 3)
+ {
+ n = fz % 3;
+ fe += fz - n;
+ fz = n;
+ }
+ if (tp = (unsigned char*)tb)
+ {
+ te = tp + tz - B64_EC + 1;
+ n = 0;
+ }
+ else
+ {
+ if (fn)
+ *fn = fp;
+ if (tn)
+ *tn = 0;
+ tp = tmp;
+ te = tp + sizeof(tmp) - B64_EC + 1;
+ n = 1;
+ }
+ for (;;)
+ {
+ tc = tp + B64_EC * B64_CHUNK;
+ do
+ {
+ if (fp >= fe)
+ goto done;
+ if (tp >= te)
+ {
+ if (fn)
+ *fn = fp;
+ if (tn)
+ *tn = tp;
+ n = tp - (unsigned char*)tb + 1;
+ tp = tmp;
+ te = tp + sizeof(tmp) - B64_EC + 1;
+ }
+ b = *fp++ << 16;
+ b |= *fp++ << 8;
+ b |= *fp++;
+ *tp++ = m[b >> 18];
+ *tp++ = m[(b >> 12) & 077];
+ *tp++ = m[(b >> 6) & 077];
+ *tp++ = m[b & 077];
+ } while (tp < tc);
+ if (n)
+ {
+ n += tp - tmp + (fp < fe);
+ tp = tmp;
+ }
+ else
+ *tp++ = '\n';
+ }
+ done:
+ if (fz)
+ {
+ if (tp >= te)
+ {
+ if (fn)
+ *fn = fp;
+ if (tn)
+ *tn = tp;
+ n = tp - (unsigned char*)tb + 1;
+ tp = tmp;
+ te = tp + sizeof(tmp) - B64_EC + 1;
+ }
+ b = *fp++ << 16;
+ if (fz == 2)
+ b |= *fp++ << 8;
+ *tp++ = m[b >> 18];
+ *tp++ = m[(b >> 12) & 077];
+ *tp++ = (fz == 2) ? m[(b >> 6) & 077] : PAD;
+ *tp++ = PAD;
+ }
+ if (n)
+ n += (tp - tmp) - 1;
+ else
+ {
+ if (tp > (unsigned char*)tb && *(tp - 1) == '\n')
+ tp--;
+ if (tp < te)
+ *tp = 0;
+ n = tp - (unsigned char*)tb;
+ if (tn)
+ *tn = tp;
+ if (fn)
+ *fn = fp;
+ }
+ return n;
+}
+
+/*
+ * mime base64 decode
+ */
+
+ssize_t
+base64decode(const void* fb, size_t fz, void** fn, void* tb, size_t tz, void** tn)
+{
+ register unsigned char* fp;
+ register unsigned char* tp;
+ register unsigned char* fe;
+ register unsigned char* te;
+ register unsigned char* tx;
+ register unsigned char* m;
+ register int c;
+ register int state;
+ register unsigned long v;
+ unsigned char* fc;
+ ssize_t n;
+
+ if (!(m = map)[0])
+ {
+ memset(m, B64_IGN, sizeof(map));
+ for (tp = (unsigned char*)alp; c = *tp; tp++)
+ m[c] = tp - (unsigned char*)alp;
+ m[PAD] = B64_PAD;
+ m[' '] = m['\t'] = m['\n'] = B64_SPC;
+ }
+ fp = (unsigned char*)fb;
+ fe = fp + fz;
+ if (tp = (unsigned char*)tb)
+ {
+ te = tp + tz;
+ if (tz > 2)
+ tz = 2;
+ tx = te - tz;
+ n = 0;
+ }
+ else
+ {
+ te = tx = tp;
+ n = 1;
+ }
+ for (;;)
+ {
+ fc = fp;
+ state = 0;
+ v = 0;
+ while (fp < fe)
+ {
+ if ((c = m[*fp++]) < 64)
+ {
+ v = (v << 6) | c;
+ if (++state == 4)
+ {
+ if (tp >= tx)
+ {
+ if (n)
+ n += 3;
+ else
+ {
+ n = tp - (unsigned char*)tb + 4;
+ if (tp < te)
+ {
+ *tp++ = (v >> 16);
+ if (tp < te)
+ {
+ *tp++ = (v >> 8);
+ if (tp < te)
+ *tp++ = (v);
+ }
+ }
+ if (tn)
+ *tn = tp;
+ if (fn)
+ *fn = fc;
+ }
+ }
+ else
+ {
+ *tp++ = (v >> 16);
+ *tp++ = (v >> 8);
+ *tp++ = (v);
+ }
+ fc = fp;
+ state = 0;
+ v = 0;
+ }
+ }
+ else if (c == B64_PAD)
+ break;
+ }
+ switch (state)
+ {
+ case 0:
+ goto done;
+ case 2:
+ if (tp < te)
+ *tp++ = v >> 4;
+ else if (n)
+ n++;
+ else
+ {
+ n = tp - (unsigned char*)tb + 2;
+ if (tn)
+ *tn = tp;
+ if (fn)
+ *fn = fc;
+ }
+ break;
+ case 3:
+ if (tp < te)
+ {
+ *tp++ = v >> 10;
+ if (tp < te)
+ *tp++ = v >> 2;
+ else
+ {
+ n = tp - (unsigned char*)tb + 2;
+ if (tn)
+ *tn = tp;
+ if (fn)
+ *fn = fc;
+ }
+ }
+ else if (n)
+ n += 2;
+ else
+ {
+ n = tp - (unsigned char*)tb + 3;
+ if (tn)
+ *tn = tp;
+ if (fn)
+ *fn = fc;
+ }
+ break;
+ }
+ while (fp < fe && ((c = m[*fp++]) == B64_PAD || c == B64_SPC));
+ if (fp >= fe || c >= 64)
+ break;
+ fp--;
+ }
+ done:
+ if (n)
+ n--;
+ else
+ {
+ if (tp < te)
+ *tp = 0;
+ n = tp - (unsigned char*)tb;
+ if (fn)
+ *fn = fp;
+ if (tn)
+ *tn = tp;
+ }
+ return n;
+}
diff --git a/src/lib/libast/string/ccmap.c b/src/lib/libast/string/ccmap.c
new file mode 100644
index 0000000..a42ccb6
--- /dev/null
+++ b/src/lib/libast/string/ccmap.c
@@ -0,0 +1,746 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * dynamic single byte character code maps
+ */
+
+#include <ast.h>
+#include <ccode.h>
+
+#if !GENERATE
+
+/*
+ * catenated CC_ASCII to CC_* character code map table
+ * order determined by CC_* index definitions
+ * old definition values/indices must not change!
+ * each table is followed by its inverse
+ */
+
+static const unsigned char tab[] =
+{
+
+ /* ascii => ascii */
+
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+
+ /* ascii => ascii */
+
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+
+ /* ascii => ebcdic */
+
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f,
+ 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26,
+ 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d,
+ 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
+ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+ 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d,
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0x5f, 0x07,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
+ 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08,
+ 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
+ 0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d,
+ 0x8e, 0x8f, 0x90, 0x6a, 0x9b, 0x9c, 0x9d, 0x9e,
+ 0x9f, 0xa0, 0xaa, 0xab, 0xac, 0x4a, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xa1, 0xbe, 0xbf,
+ 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb,
+ 0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed,
+ 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+
+ /* ebcdic => ascii */
+
+ 0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f,
+ 0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x9d, 0x85, 0x08, 0x87,
+ 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0a, 0x17, 0x1b,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a,
+ 0x20, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xd5, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
+ 0x26, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x7e,
+ 0x2d, 0x2f, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xcb, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
+ 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1,
+ 0xc2, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
+ 0xc3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
+ 0xca, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+ 0x71, 0x72, 0x5e, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+ 0xd1, 0xe5, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0xd2, 0xd3, 0xd4, 0x5b, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x5d, 0xe6, 0xe7,
+ 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed,
+ 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
+ 0x5c, 0x9f, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+
+ /* ascii => ebcdic-i */
+
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f,
+ 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26,
+ 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d,
+ 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
+ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+ 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x5f, 0x6d,
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
+ 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08,
+ 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
+ 0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d,
+ 0x8e, 0x8f, 0x90, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
+ 0x9f, 0xa0, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb,
+ 0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed,
+ 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+
+ /* ebcdic-i => ascii */
+
+ 0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f,
+ 0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x9d, 0x85, 0x08, 0x87,
+ 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0a, 0x17, 0x1b,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a,
+ 0x20, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0x4a, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
+ 0x26, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e,
+ 0x2d, 0x2f, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0x6a, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
+ 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1,
+ 0xc2, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
+ 0xc3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
+ 0xca, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+ 0x71, 0x72, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
+ 0xd1, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0xd2, 0xd3, 0xd4, 0x5b, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x5d, 0xe6, 0xe7,
+ 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed,
+ 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
+ 0x5c, 0x9f, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+
+ /* ascii => ebcdic-o */
+
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f,
+ 0x16, 0x05, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26,
+ 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d,
+ 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
+ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+ 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x5f, 0x6d,
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
+ 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08,
+ 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xff,
+ 0x41, 0xaa, 0x4a, 0xb1, 0x9f, 0xb2, 0x6a, 0xb5,
+ 0xbb, 0xb4, 0x9a, 0x8a, 0xb0, 0xca, 0xaf, 0xbc,
+ 0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3,
+ 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab,
+ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68,
+ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,
+ 0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf,
+ 0x80, 0xfd, 0xfe, 0xfb, 0xfc, 0xba, 0xae, 0x59,
+ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48,
+ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,
+ 0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1,
+ 0x70, 0xdd, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf,
+
+ /* ebcdic-o => ascii */
+
+ 0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f,
+ 0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x9d, 0x0a, 0x08, 0x87,
+ 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1b,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a,
+ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5,
+ 0xe7, 0xf1, 0xa2, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
+ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef,
+ 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e,
+ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5,
+ 0xc7, 0xd1, 0xa6, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
+ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
+ 0xcc, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
+ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1,
+ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+ 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4,
+ 0xb5, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0x5b, 0xde, 0xae,
+ 0xac, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc,
+ 0xbd, 0xbe, 0xdd, 0xa8, 0xaf, 0x5d, 0xb4, 0xd7,
+ 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5,
+ 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xf9, 0xfa, 0xff,
+ 0x5c, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xb3, 0xdb, 0xdc, 0xd9, 0xda, 0x9f,
+
+ /* ascii => ebcdic-s */
+
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f,
+ 0x16, 0x05, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26,
+ 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d,
+ 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
+ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+ 0xe7, 0xe8, 0xe9, 0xbb, 0xbc, 0xbd, 0x6a, 0x6d,
+ 0x4a, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xfb, 0x4f, 0xfd, 0xff, 0x07,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
+ 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08,
+ 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0x5f,
+ 0x41, 0xaa, 0xb0, 0xb1, 0x9f, 0xb2, 0xd0, 0xb5,
+ 0x79, 0xb4, 0x9a, 0x8a, 0xba, 0xca, 0xaf, 0xa1,
+ 0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3,
+ 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab,
+ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68,
+ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,
+ 0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf,
+ 0x80, 0xe0, 0xfe, 0xdd, 0xfc, 0xad, 0xae, 0x59,
+ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48,
+ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,
+ 0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1,
+ 0x70, 0xc0, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf,
+
+ /* ebcdic-s => ascii */
+
+ 0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f,
+ 0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x9d, 0x0a, 0x08, 0x87,
+ 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1b,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a,
+ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5,
+ 0xe7, 0xf1, 0x60, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
+ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef,
+ 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x9f,
+ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5,
+ 0xc7, 0xd1, 0x5e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
+ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
+ 0xcc, 0xa8, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
+ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1,
+ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+ 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4,
+ 0xb5, 0xaf, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0xdd, 0xde, 0xae,
+ 0xa2, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc,
+ 0xbd, 0xbe, 0xac, 0x5b, 0x5c, 0x5d, 0xb4, 0xd7,
+ 0xf9, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5,
+ 0xa6, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xdb, 0xfa, 0xff,
+ 0xd9, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e,
+
+ /* ascii => ebcdic-h */
+
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f,
+ 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26,
+ 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d,
+ 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
+ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+ 0xe7, 0xe8, 0xe9, 0xba, 0xe0, 0xbb, 0xb0, 0x6d,
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
+ 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08,
+ 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xff,
+ 0x41, 0xaa, 0x4a, 0xb1, 0x9f, 0xb2, 0x6a, 0xb5,
+ 0xbd, 0xb4, 0x9a, 0x8a, 0x5f, 0xca, 0xaf, 0xbc,
+ 0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3,
+ 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab,
+ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68,
+ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,
+ 0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf,
+ 0x80, 0xfd, 0xfe, 0xfb, 0xfc, 0xad, 0xae, 0x59,
+ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48,
+ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,
+ 0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1,
+ 0x70, 0xdd, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xdf,
+
+ /* ebcdic-h => ascii */
+
+ 0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f,
+ 0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x9d, 0x85, 0x08, 0x87,
+ 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x0a, 0x17, 0x1b,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a,
+ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5,
+ 0xe7, 0xf1, 0xa2, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
+ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef,
+ 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0xac,
+ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5,
+ 0xc7, 0xd1, 0xa6, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
+ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
+ 0xcc, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
+ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1,
+ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+ 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4,
+ 0xb5, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0xdd, 0xde, 0xae,
+ 0x5e, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc,
+ 0xbd, 0xbe, 0x5b, 0x5d, 0xaf, 0xa8, 0xb4, 0xd7,
+ 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5,
+ 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xf9, 0xfa, 0xff,
+ 0x5c, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xb3, 0xdb, 0xdc, 0xd9, 0xda, 0x9f,
+
+ /* ascii => ebcdic-m */
+
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f,
+ 0x16, 0x05, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26,
+ 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d,
+ 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
+ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+ 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x5f, 0x6d,
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x06, 0x17,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
+ 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08,
+ 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xdf,
+ 0x41, 0xaa, 0x4a, 0xb1, 0x9f, 0xb2, 0x6a, 0xb5,
+ 0xbb, 0xb4, 0x9a, 0x8a, 0xb0, 0xca, 0xaf, 0xbc,
+ 0x90, 0x8f, 0xea, 0xfa, 0xbe, 0xa0, 0xb6, 0xb3,
+ 0x9d, 0xda, 0x9b, 0x8b, 0xb7, 0xb8, 0xb9, 0xab,
+ 0x64, 0x65, 0x62, 0x66, 0x63, 0x67, 0x9e, 0x68,
+ 0x74, 0x71, 0x72, 0x73, 0x78, 0x75, 0x76, 0x77,
+ 0xac, 0x69, 0xed, 0xee, 0xeb, 0xef, 0xec, 0xbf,
+ 0x80, 0xfd, 0xfe, 0xfb, 0xfc, 0xba, 0xae, 0x59,
+ 0x44, 0x45, 0x42, 0x46, 0x43, 0x47, 0x9c, 0x48,
+ 0x54, 0x51, 0x52, 0x53, 0x58, 0x55, 0x56, 0x57,
+ 0x8c, 0x49, 0xcd, 0xce, 0xcb, 0xcf, 0xcc, 0xe1,
+ 0x70, 0xdd, 0xde, 0xdb, 0xdc, 0x8d, 0x8e, 0xff,
+
+ /* ebcdic-m => ascii */
+
+ 0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f,
+ 0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x9d, 0x0a, 0x08, 0x87,
+ 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1b,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,
+ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
+ 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a,
+ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5,
+ 0xe7, 0xf1, 0xa2, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
+ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef,
+ 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e,
+ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5,
+ 0xc7, 0xd1, 0xa6, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
+ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
+ 0xcc, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
+ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1,
+ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+ 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4,
+ 0xb5, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0x5b, 0xde, 0xae,
+ 0xac, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc,
+ 0xbd, 0xbe, 0xdd, 0xa8, 0xaf, 0x5d, 0xb4, 0xd7,
+ 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5,
+ 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xf9, 0xfa, 0x9f,
+ 0x5c, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xb3, 0xdb, 0xdc, 0xd9, 0xda, 0xff,
+
+ /* ascii => ebcdic-u */
+
+ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f,
+ 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x9f,
+ 0x10, 0x11, 0x12, 0x13, 0xb6, 0xb5, 0x32, 0x26,
+ 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d,
+ 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
+ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+ 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x5f, 0x6d,
+ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07,
+ 0x68, 0xdc, 0x51, 0x42, 0x43, 0x44, 0x47, 0x48,
+ 0x52, 0x53, 0x54, 0x57, 0x56, 0x58, 0x63, 0x67,
+ 0x71, 0x9c, 0x9e, 0xcb, 0xcc, 0xcd, 0xdb, 0xdd,
+ 0xdf, 0xec, 0xfc, 0xb0, 0xb1, 0xb2, 0x3e, 0xb4,
+ 0x45, 0x55, 0xce, 0xde, 0x49, 0x69, 0x9a, 0x9b,
+ 0xab, 0x0f, 0xba, 0xb8, 0xb7, 0xaa, 0x8a, 0x8b,
+ 0x3c, 0x3d, 0x62, 0x6a, 0x64, 0x65, 0x66, 0x20,
+ 0x21, 0x22, 0x70, 0x23, 0x72, 0x73, 0x74, 0xbe,
+ 0x76, 0x77, 0x78, 0x80, 0x24, 0x15, 0x8c, 0x8d,
+ 0x8e, 0x41, 0x06, 0x17, 0x28, 0x29, 0x9d, 0x2a,
+ 0x2b, 0x2c, 0x09, 0x0a, 0xac, 0x4a, 0xae, 0xaf,
+ 0x1b, 0x30, 0x31, 0xfa, 0x1a, 0x33, 0x34, 0x35,
+ 0x36, 0x59, 0x08, 0x38, 0xbc, 0x39, 0xa0, 0xbf,
+ 0xca, 0x3a, 0xfe, 0x3b, 0x04, 0xcf, 0xda, 0x14,
+ 0xe1, 0x8f, 0x46, 0x75, 0xfd, 0xeb, 0xee, 0xed,
+ 0x90, 0xef, 0xb3, 0xfb, 0xb9, 0xea, 0xbb, 0xff,
+
+ /* ebcdic-u => ascii */
+
+ 0x00, 0x01, 0x02, 0x03, 0xec, 0x09, 0xca, 0x7f,
+ 0xe2, 0xd2, 0xd3, 0x0b, 0x0c, 0x0d, 0x0e, 0xa9,
+ 0x10, 0x11, 0x12, 0x13, 0xef, 0xc5, 0x08, 0xcb,
+ 0x18, 0x19, 0xdc, 0xd8, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0xb7, 0xb8, 0xb9, 0xbb, 0xc4, 0x0a, 0x17, 0x1b,
+ 0xcc, 0xcd, 0xcf, 0xd0, 0xd1, 0x05, 0x06, 0x07,
+ 0xd9, 0xda, 0x16, 0xdd, 0xde, 0xdf, 0xe0, 0x04,
+ 0xe3, 0xe5, 0xe9, 0xeb, 0xb0, 0xb1, 0x9e, 0x1a,
+ 0x20, 0xc9, 0x83, 0x84, 0x85, 0xa0, 0xf2, 0x86,
+ 0x87, 0xa4, 0xd5, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
+ 0x26, 0x82, 0x88, 0x89, 0x8a, 0xa1, 0x8c, 0x8b,
+ 0x8d, 0xe1, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e,
+ 0x2d, 0x2f, 0xb2, 0x8e, 0xb4, 0xb5, 0xb6, 0x8f,
+ 0x80, 0xa5, 0xb3, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
+ 0xba, 0x90, 0xbc, 0xbd, 0xbe, 0xf3, 0xc0, 0xc1,
+ 0xc2, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
+ 0xc3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0xae, 0xaf, 0xc6, 0xc7, 0xc8, 0xf1,
+ 0xf8, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+ 0x71, 0x72, 0xa6, 0xa7, 0x91, 0xce, 0x92, 0x0f,
+ 0xe6, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0xad, 0xa8, 0xd4, 0x5b, 0xd6, 0xd7,
+ 0x9b, 0x9c, 0x9d, 0xfa, 0x9f, 0x15, 0x14, 0xac,
+ 0xab, 0xfc, 0xaa, 0xfe, 0xe4, 0x5d, 0xbf, 0xe7,
+ 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0xe8, 0x93, 0x94, 0x95, 0xa2, 0xed,
+ 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+ 0x51, 0x52, 0xee, 0x96, 0x81, 0x97, 0xa3, 0x98,
+ 0x5c, 0xf0, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0xfd, 0xf5, 0x99, 0xf7, 0xf6, 0xf9,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0xdb, 0xfb, 0x9a, 0xf4, 0xea, 0xff,
+
+};
+
+#define MAP 256
+#define MAPS (sizeof(tab)/MAP)
+
+struct Map_s; typedef struct Map_s Map_t;
+
+struct Map_s
+{
+ Map_t* next;
+ int op;
+ unsigned char map[MAP];
+};
+
+static Map_t* maps;
+
+/*
+ * generate and return ccode map from i to o
+ */
+
+unsigned char*
+_ccmap(int i, int o)
+{
+ register unsigned char* a;
+ register unsigned char* m;
+ register unsigned char* z;
+ register Map_t* map;
+ register int n;
+ int op;
+
+ if (!i && !o)
+ return (unsigned char*)tab;
+ if (CCCONVERT(i))
+ {
+ o = CCOUT(i);
+ i = CCIN(i);
+ }
+ else if (CCCONVERT(o))
+ {
+ i = CCIN(o);
+ o = CCOUT(o);
+ }
+ else
+ {
+ if (i == 0)
+ i = CC_NATIVE;
+ if (o == 0)
+ o = CC_NATIVE;
+ }
+ if (i == o || i < 1 || i > MAPS || o < 1 || o > MAPS)
+ return 0;
+ if (i == CC_ASCII)
+ return (unsigned char*)tab + MAP * (2 * (o - 1));
+ if (o == CC_ASCII)
+ return (unsigned char*)tab + MAP * (2 * (i - 1) + 1);
+ op = CCOP(i, o);
+ for (map = maps; map; map = map->next)
+ if (map->op == op)
+ return map->map;
+ if (!(map = newof(0, Map_t, 1, 0)))
+ return 0;
+ map->op = op;
+ a = (unsigned char*)tab + MAP * (2 * (o - 1));
+ z = (unsigned char*)tab + MAP * (2 * (i - 1) + 1);
+ m = map->map;
+ for (n = 0; n < MAP; n++)
+ m[n] = n;
+ for (n = MAP - 1; n >= 0; n--)
+ m[n] = a[z[n]];
+ map->next = maps;
+ maps = map;
+ return m;
+}
+
+void*
+_ccmapcpy(register unsigned char* m, void* b, const void* a, size_t n)
+{
+ register unsigned char* ub;
+ register unsigned char* ue;
+ register unsigned char* ua;
+
+ if (m)
+ {
+ ub = (unsigned char*)b;
+ ue = ub + n;
+ ua = (unsigned char*)a;
+ while (ub < ue)
+ *ub++ = m[*ua++];
+ }
+ else
+ memcpy(b, a, n);
+ return b;
+}
+
+void*
+_ccmapstr(register unsigned char* m, void* b, size_t n)
+{
+ register unsigned char* s;
+ register unsigned char* e;
+
+ if (m)
+ for (e = (s = (unsigned char*)b) + n; s < e; s++)
+ *s = m[*s];
+ return b;
+}
+
+#else
+
+static void
+dump(int from, int to)
+{
+ register const unsigned char* m;
+ register int c;
+ register int i;
+
+ m = ccmap(from, to);
+ sfprintf(sfstdout, "\n /* %s => %s */\n\n", ccmapname(from), ccmapname(to));
+ for (c = i = 0; c <= UCHAR_MAX; c++)
+ {
+ sfprintf(sfstdout, " 0x%02x,", m ? m[c] : c);
+ if (!(++i & 0x7))
+ {
+ i = 0;
+ sfprintf(sfstdout, "\n");
+ }
+ }
+}
+
+main(int argc, char** argv)
+{
+ register int i;
+
+ for (i = 1; i <= CC_MAPS; i++)
+ {
+ dump(CC_ASCII, i);
+ dump(i, CC_ASCII);
+ }
+ return 0;
+}
+
+#endif
diff --git a/src/lib/libast/string/ccmapid.c b/src/lib/libast/string/ccmapid.c
new file mode 100644
index 0000000..f18d46e
--- /dev/null
+++ b/src/lib/libast/string/ccmapid.c
@@ -0,0 +1,173 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * 8 bit character code map name/id lookup support
+ */
+
+#include <ast.h>
+#include <ccode.h>
+#include <ctype.h>
+
+static const Ccmap_t maps[] =
+{
+ {
+ "ascii",
+ "a|ascii|?(iso)?(-)646|?(iso)?(-)8859|latin",
+ "8 bit ascii",
+ "ISO-8859-%s",
+ "1",
+ CC_ASCII,
+ },
+
+ {
+ "ebcdic",
+ "e|ebcdic?(-)?([1e])",
+ "X/Open ebcdic",
+ "EBCDIC",
+ 0,
+ CC_EBCDIC_E,
+ },
+
+ {
+ "ebcdic-o",
+ "o|ebcdic?(-)[3o]|?(cp|ibm)1047|open?(-)edition",
+ "mvs OpenEdition ebcdic",
+ "EBCDIC-O",
+ 0,
+ CC_EBCDIC_O,
+ },
+
+ {
+ "ebcdic-h",
+ "h|ebcdic?(-)h|?(cp|ibm)?(00)37|[oa]s?(/-)400",
+ "ibm OS/400 AS/400 ebcdic",
+ "EBCDIC-H",
+ 0,
+ CC_EBCDIC_H,
+ },
+
+ {
+ "ebcdic-s",
+ "s|ebcdic?(-)s|siemens|posix-bc",
+ "siemens posix-bc ebcdic",
+ "EBCDIC-S",
+ 0,
+ CC_EBCDIC_S,
+ },
+
+ {
+ "ebcdic-i",
+ "i|ebcdic?(-)[2i]|ibm",
+ "X/Open ibm ebcdic (not idempotent)",
+ "EBCDIC-I",
+ 0,
+ CC_EBCDIC_I,
+ },
+
+ {
+ "ebcdic-m",
+ "m|ebcdic?(-)m|mvs",
+ "mvs ebcdic",
+ "EBCDIC-M",
+ 0,
+ CC_EBCDIC_M,
+ },
+
+ {
+ "ebcdic-u",
+ "u|ebcdic?(-)(u|mf)|microfocus",
+ "microfocus cobol ebcdic",
+ "EBCDIC-U",
+ 0,
+ CC_EBCDIC_U,
+ },
+
+ {
+ "native",
+ "n|native|local",
+ "native code set",
+ 0,
+ 0,
+ CC_NATIVE,
+ },
+
+ { 0 },
+};
+
+/*
+ * ccode map list iterator
+ */
+
+Ccmap_t*
+ccmaplist(Ccmap_t* mp)
+{
+ return !mp ? (Ccmap_t*)maps : (++mp)->name ? mp : (Ccmap_t*)0;
+}
+
+/*
+ * return ccode map id given name
+ */
+
+int
+ccmapid(const char* name)
+{
+ register const Ccmap_t* mp;
+ register int c;
+ const Ccmap_t* bp;
+ int n;
+ int sub[2];
+
+ bp = 0;
+ n = 0;
+ for (mp = maps; mp->name; mp++)
+ if (strgrpmatch(name, mp->match, sub, elementsof(sub) / 2, STR_MAXIMAL|STR_LEFT|STR_ICASE))
+ {
+ if (!(c = name[sub[1]]))
+ return mp->ccode;
+ if (sub[1] > n && !isalpha(c))
+ {
+ n = sub[1];
+ bp = mp;
+ }
+ }
+ return bp ? bp->ccode : -1;
+}
+
+/*
+ * return ccode map name given id
+ */
+
+char*
+ccmapname(register int id)
+{
+ register const Ccmap_t* mp;
+
+ for (mp = maps; mp->name; mp++)
+ if (id == mp->ccode)
+ return (char*)mp->name;
+ return 0;
+}
diff --git a/src/lib/libast/string/ccnative.c b/src/lib/libast/string/ccnative.c
new file mode 100644
index 0000000..500f165
--- /dev/null
+++ b/src/lib/libast/string/ccnative.c
@@ -0,0 +1,56 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * copy table with element size n
+ * indexed by CC_ASCII to table
+ * indexed by CC_NATIVE
+ */
+
+#include <ast.h>
+#include <ccode.h>
+
+void*
+ccnative(void* b, const void* a, size_t n)
+{
+#if CC_ASCII == CC_NATIVE
+ return memcpy(b, a, n * (UCHAR_MAX + 1));
+#else
+ register int c;
+ register const unsigned char* m;
+ register unsigned char* cb = (unsigned char*)b;
+ register unsigned char* ca = (unsigned char*)a;
+
+ m = CCMAP(CC_ASCII, CC_NATIVE);
+ if (n == sizeof(char))
+ for (c = 0; c <= UCHAR_MAX; c++)
+ cb[c] = ca[m[c]];
+ else
+ for (c = 0; c <= UCHAR_MAX; c++)
+ memcpy(cb + n * c, ca + n * m[c], n);
+ return b;
+#endif
+}
diff --git a/src/lib/libast/string/chresc.c b/src/lib/libast/string/chresc.c
new file mode 100644
index 0000000..9dd3704
--- /dev/null
+++ b/src/lib/libast/string/chresc.c
@@ -0,0 +1,235 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return the next character in the string s
+ * \ character constants are expanded
+ * *p is updated to point to the next character in s
+ * *m is 1 if return value is wide
+ */
+
+#include <ast.h>
+#include <ctype.h>
+
+#include <ccode.h>
+#if !_PACKAGE_astsa
+#include <regex.h>
+#endif
+
+int
+chrexp(register const char* s, char** p, int* m, register int flags)
+{
+ register const char* q;
+ register int c;
+ const char* e;
+ const char* b;
+ char* r;
+ int n;
+ int w;
+
+ w = 0;
+ for (;;)
+ {
+ b = s;
+ switch (c = mbchar(s))
+ {
+ case 0:
+ s--;
+ break;
+ case '\\':
+ switch (c = *s++)
+ {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ if (!(flags & FMT_EXP_CHAR))
+ goto noexpand;
+ c -= '0';
+ q = s + 2;
+ while (s < q)
+ switch (*s)
+ {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ c = (c << 3) + *s++ - '0';
+ break;
+ default:
+ q = s;
+ break;
+ }
+ break;
+ case 'a':
+ if (!(flags & FMT_EXP_CHAR))
+ goto noexpand;
+ c = CC_bel;
+ break;
+ case 'b':
+ if (!(flags & FMT_EXP_CHAR))
+ goto noexpand;
+ c = '\b';
+ break;
+ case 'c': /*DEPRECATED*/
+ case 'C':
+ if (!(flags & FMT_EXP_CHAR))
+ goto noexpand;
+ if (c = *s)
+ {
+ s++;
+ if (c == '\\')
+ {
+ c = chrexp(s - 1, &r, 0, flags);
+ s = (const char*)r;
+ }
+ if (islower(c))
+ c = toupper(c);
+ c = ccmapc(c, CC_NATIVE, CC_ASCII);
+ c ^= 0x40;
+ c = ccmapc(c, CC_ASCII, CC_NATIVE);
+ }
+ break;
+ case 'e': /*DEPRECATED*/
+ case 'E':
+ if (!(flags & FMT_EXP_CHAR))
+ goto noexpand;
+ c = CC_esc;
+ break;
+ case 'f':
+ if (!(flags & FMT_EXP_CHAR))
+ goto noexpand;
+ c = '\f';
+ break;
+ case 'M':
+ if (!(flags & FMT_EXP_CHAR))
+ goto noexpand;
+ if (*s == '-')
+ {
+ s++;
+ c = CC_esc;
+ }
+ break;
+ case 'n':
+ if (flags & FMT_EXP_NONL)
+ continue;
+ if (!(flags & FMT_EXP_LINE))
+ goto noexpand;
+ c = '\n';
+ break;
+ case 'r':
+ if (flags & FMT_EXP_NOCR)
+ continue;
+ if (!(flags & FMT_EXP_LINE))
+ goto noexpand;
+ c = '\r';
+ break;
+ case 't':
+ if (!(flags & FMT_EXP_CHAR))
+ goto noexpand;
+ c = '\t';
+ break;
+ case 'v':
+ if (!(flags & FMT_EXP_CHAR))
+ goto noexpand;
+ c = CC_vt;
+ break;
+ case 'u':
+ case 'U':
+ case 'x':
+ if (q = c == 'u' ? (s + 4) : c == 'U' ? (s + 8) : (char*)0)
+ {
+ if (!(flags & FMT_EXP_WIDE))
+ goto noexpand;
+ w = 1;
+ }
+ b = e = s;
+ n = 0;
+ c = 0;
+ while (!e || !q || s < q)
+ {
+ switch (*s)
+ {
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ c = (c << 4) + *s++ - 'a' + 10;
+ n++;
+ continue;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ c = (c << 4) + *s++ - 'A' + 10;
+ n++;
+ continue;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ c = (c << 4) + *s++ - '0';
+ n++;
+ continue;
+ case '{':
+ case '[':
+ if (s != e)
+ break;
+ e = 0;
+ s++;
+ continue;
+ case '}':
+ case ']':
+ if (!e)
+ s++;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ if (n <= 2 && !(flags & FMT_EXP_CHAR) || n > 2 && (w = 1) && !(flags & FMT_EXP_WIDE))
+ {
+ c = '\\';
+ s = b;
+ }
+ break;
+ case 0:
+ s--;
+ break;
+ }
+ break;
+ default:
+ if ((s - b) > 1)
+ w = 1;
+ break;
+ }
+ break;
+ }
+ normal:
+ if (p)
+ *p = (char*)s;
+ if (m)
+ *m = w;
+ return c;
+ noexpand:
+ c = '\\';
+ s--;
+ goto normal;
+}
+
+int
+chresc(register const char* s, char** p)
+{
+ return chrexp(s, p, NiL, FMT_EXP_CHAR|FMT_EXP_LINE|FMT_EXP_WIDE);
+}
diff --git a/src/lib/libast/string/chrtoi.c b/src/lib/libast/string/chrtoi.c
new file mode 100644
index 0000000..2d8a3e1
--- /dev/null
+++ b/src/lib/libast/string/chrtoi.c
@@ -0,0 +1,55 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * convert a 0 terminated character constant string to an int
+ */
+
+#include <ast.h>
+
+int
+chrtoi(register const char* s)
+{
+ register int c;
+ register int n;
+ register int x;
+ char* p;
+
+ c = 0;
+ for (n = 0; n < sizeof(int) * CHAR_BIT; n += CHAR_BIT)
+ {
+ switch (x = *((unsigned char*)s++))
+ {
+ case '\\':
+ x = chresc(s - 1, &p);
+ s = (const char*)p;
+ break;
+ case 0:
+ return(c);
+ }
+ c = (c << CHAR_BIT) | x;
+ }
+ return(c);
+}
diff --git a/src/lib/libast/string/fmtbase.c b/src/lib/libast/string/fmtbase.c
new file mode 100644
index 0000000..a7262eb
--- /dev/null
+++ b/src/lib/libast/string/fmtbase.c
@@ -0,0 +1,70 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * return base b representation for n
+ * if p!=0 then base prefix is included
+ * otherwise if n==0 or b==0 then output is signed base 10
+ */
+
+#include <ast.h>
+
+char*
+fmtbase(intmax_t n, int b, int p)
+{
+ char* buf;
+ int z;
+
+ if (!p)
+ {
+ if (!n)
+ return "0";
+ if (!b)
+ return fmtint(n, 0);
+ if (b == 10)
+ return fmtint(n, 1);
+ }
+ buf = fmtbuf(z = 72);
+ sfsprintf(buf, z, p ? "%#..*I*u" : "%..*I*u", b, sizeof(n), n);
+ return buf;
+}
+
+#if __OBSOLETE__ < 20140101
+
+#undef fmtbasell
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char*
+fmtbasell(intmax_t n, int b, int p)
+{
+ return fmtbase(n, b, p);
+}
+
+#undef extern
+
+#endif
diff --git a/src/lib/libast/string/fmtbuf.c b/src/lib/libast/string/fmtbuf.c
new file mode 100644
index 0000000..bc96af6
--- /dev/null
+++ b/src/lib/libast/string/fmtbuf.c
@@ -0,0 +1,69 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+/*
+ * return small format buffer chunk of size n
+ * spin lock for thread access
+ * format buffers are short lived
+ * only one concurrent buffer with size > sizeof(buf)
+ */
+
+static char buf[16 * 1024];
+static char* nxt = buf;
+static int lck = -1;
+
+static char* big;
+static size_t bigsiz;
+
+char*
+fmtbuf(size_t n)
+{
+ register char* cur;
+
+ while (++lck)
+ lck--;
+ if (n > (&buf[elementsof(buf)] - nxt))
+ {
+ if (n > elementsof(buf))
+ {
+ if (n > bigsiz)
+ {
+ bigsiz = roundof(n, 8 * 1024);
+ if (!(big = newof(big, char, bigsiz, 0)))
+ {
+ lck--;
+ return 0;
+ }
+ }
+ lck--;
+ return big;
+ }
+ nxt = buf;
+ }
+ cur = nxt;
+ nxt += n;
+ lck--;
+ return cur;
+}
diff --git a/src/lib/libast/string/fmtclock.c b/src/lib/libast/string/fmtclock.c
new file mode 100644
index 0000000..6e54cfa
--- /dev/null
+++ b/src/lib/libast/string/fmtclock.c
@@ -0,0 +1,63 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * return pointer to formatted clock() tics t
+ * return value length is at most 6
+ */
+
+#include <ast.h>
+#include <tm.h>
+
+char*
+fmtclock(register Sfulong_t t)
+{
+ register int u;
+ char* buf;
+ int z;
+
+ static unsigned int clk_tck;
+
+ if (!clk_tck)
+ {
+#ifdef CLOCKS_PER_SEC
+ clk_tck = CLOCKS_PER_SEC;
+#else
+ if (!(clk_tck = (unsigned int)strtoul(astconf("CLK_TCK", NiL, NiL), NiL, 10)))
+ clk_tck = 60;
+#endif
+ }
+ if (t == 0)
+ return "0";
+ if (t == ((Sfulong_t)~0))
+ return "%";
+ t = (t * 1000000) / clk_tck;
+ if (t < 1000)
+ u = 'u';
+ else if ((t /= 1000) < 1000)
+ u = 'm';
+ else
+ return fmtelapsed(t / 10, 100);
+ buf = fmtbuf(z = 7);
+ sfsprintf(buf, z, "%I*u%cs", sizeof(t), t, u);
+ return buf;
+}
diff --git a/src/lib/libast/string/fmtdev.c b/src/lib/libast/string/fmtdev.c
new file mode 100644
index 0000000..9f20f5f
--- /dev/null
+++ b/src/lib/libast/string/fmtdev.c
@@ -0,0 +1,60 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * st_dev formatter
+ */
+
+#include <ast.h>
+#include <ctype.h>
+#include <ls.h>
+
+char*
+fmtdev(struct stat* st)
+{
+ char* buf;
+ unsigned long mm;
+ unsigned int ma;
+ unsigned int mi;
+ int z;
+
+ mm = (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) ? idevice(st) : st->st_dev;
+ ma = major(mm);
+ mi = minor(mm);
+ buf = fmtbuf(z = 17);
+ if (ma == '#' && isalnum(mi))
+ {
+ /*
+ * Plan? Nein!
+ */
+
+ buf[0] = ma;
+ buf[1] = mi;
+ buf[2] = 0;
+ }
+ else
+ sfsprintf(buf, z, "%03d,%03d", ma, mi);
+ return buf;
+}
diff --git a/src/lib/libast/string/fmtelapsed.c b/src/lib/libast/string/fmtelapsed.c
new file mode 100644
index 0000000..a1c5779
--- /dev/null
+++ b/src/lib/libast/string/fmtelapsed.c
@@ -0,0 +1,61 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * return pointer to formatted elapsed time for u 1/n secs
+ * compatible with strelapsed()
+ * return value length is at most 7
+ */
+
+#include <ast.h>
+
+char*
+fmtelapsed(register unsigned long u, register int n)
+{
+ register unsigned long t;
+ char* buf;
+ int z;
+
+ if (u == 0L)
+ return "0";
+ if (u == ~0L)
+ return "%";
+ buf = fmtbuf(z = 8);
+ t = u / n;
+ if (t < 60)
+ sfsprintf(buf, z, "%lu.%02lus", t, (u * 100 / n) % 100);
+ else if (t < 60*60)
+ sfsprintf(buf, z, "%lum%02lus", t / 60, t - (t / 60) * 60);
+ else if (t < 24*60*60)
+ sfsprintf(buf, z, "%luh%02lum", t / (60*60), (t - (t / (60*60)) * (60*60)) / 60);
+ else if (t < 7*24*60*60)
+ sfsprintf(buf, z, "%lud%02luh", t / (24*60*60), (t - (t / (24*60*60)) * (24*60*60)) / (60*60));
+ else if (t < 31*24*60*60)
+ sfsprintf(buf, z, "%luw%02lud", t / (7*24*60*60), (t - (t / (7*24*60*60)) * (7*24*60*60)) / (24*60*60));
+ else if (t < 365*24*60*60)
+ sfsprintf(buf, z, "%luM%02lud", (t * 12) / (365*24*60*60), ((t * 12) - ((t * 12) / (365*24*60*60)) * (365*24*60*60)) / (12*24*60*60));
+ else if (t < (365UL*4UL+1UL)*24UL*60UL*60UL)
+ sfsprintf(buf, z, "%luY%02luM", t / (365*24*60*60), ((t - (t / (365*24*60*60)) * (365*24*60*60)) * 5) / (152 * 24 * 60 * 60));
+ else
+ sfsprintf(buf, z, "%luY%02luM", (t * 4) / ((365UL*4UL+1UL)*24UL*60UL*60UL), (((t * 4) - ((t * 4) / ((365UL*4UL+1UL)*24UL*60UL*60UL)) * ((365UL*4UL+1UL)*24UL*60UL*60UL)) * 5) / ((4 * 152 + 1) * 24 * 60 * 60));
+ return buf;
+}
diff --git a/src/lib/libast/string/fmterror.c b/src/lib/libast/string/fmterror.c
new file mode 100644
index 0000000..eeeb5bc
--- /dev/null
+++ b/src/lib/libast/string/fmterror.c
@@ -0,0 +1,37 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return error message string given errno
+ */
+
+#include <ast.h>
+
+char*
+fmterror(int err)
+{
+ return strerror(err);
+}
diff --git a/src/lib/libast/string/fmtesc.c b/src/lib/libast/string/fmtesc.c
new file mode 100644
index 0000000..753b195
--- /dev/null
+++ b/src/lib/libast/string/fmtesc.c
@@ -0,0 +1,248 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return string with expanded escape chars
+ */
+
+#include <ast.h>
+#include <ccode.h>
+#include <ctype.h>
+#if _hdr_wchar && _hdr_wctype
+#include <wchar.h>
+#include <wctype.h>
+#endif
+
+/*
+ * quote string as of length n with qb...qe
+ * (flags&FMT_ALWAYS) always quotes, otherwise quote output only if necessary
+ * qe and the usual suspects are \... escaped
+ * (flags&FMT_WIDE) doesn't escape 8 bit chars
+ * (flags&FMT_ESCAPED) doesn't \... escape the usual suspects
+ * (flags&FMT_SHELL) escape $`"#;~&|()<>[]*?
+ */
+
+char*
+fmtquote(const char* as, const char* qb, const char* qe, size_t n, int flags)
+{
+ register unsigned char* s = (unsigned char*)as;
+ register unsigned char* e = s + n;
+ register char* b;
+ register int c;
+ register int m;
+ register int escaped;
+ register int spaced;
+ register int doublequote;
+ register int singlequote;
+ int shell;
+ char* f;
+ char* buf;
+
+ c = 4 * (n + 1);
+ if (qb)
+ c += strlen((char*)qb);
+ if (qe)
+ c += strlen((char*)qe);
+ b = buf = fmtbuf(c);
+ shell = 0;
+ doublequote = 0;
+ singlequote = 0;
+ if (qb)
+ {
+ if (qb[0] == '$' && qb[1] == '\'' && qb[2] == 0)
+ shell = 1;
+ else if ((flags & FMT_SHELL) && qb[1] == 0)
+ {
+ if (qb[0] == '"')
+ doublequote = 1;
+ else if (qb[0] == '\'')
+ singlequote = 1;
+ }
+ while (*b = *qb++)
+ b++;
+ }
+ else if (flags & FMT_SHELL)
+ doublequote = 1;
+ f = b;
+ escaped = spaced = !!(flags & FMT_ALWAYS);
+ while (s < e)
+ {
+ if ((m = mbsize(s)) > 1 && (s + m) <= e)
+ {
+#if _hdr_wchar && _hdr_wctype
+ c = mbchar(s);
+ if (!spaced && !escaped && (iswspace(c) || iswcntrl(c)))
+ spaced = 1;
+ s -= m;
+#endif
+ while (m--)
+ *b++ = *s++;
+ }
+ else
+ {
+ c = *s++;
+ if (!(flags & FMT_ESCAPED) && (iscntrl(c) || !isprint(c) || c == '\\'))
+ {
+ escaped = 1;
+ *b++ = '\\';
+ switch (c)
+ {
+ case CC_bel:
+ c = 'a';
+ break;
+ case '\b':
+ c = 'b';
+ break;
+ case '\f':
+ c = 'f';
+ break;
+ case '\n':
+ c = 'n';
+ break;
+ case '\r':
+ c = 'r';
+ break;
+ case '\t':
+ c = 't';
+ break;
+ case CC_vt:
+ c = 'v';
+ break;
+ case CC_esc:
+ c = 'E';
+ break;
+ case '\\':
+ break;
+ default:
+ if (!(flags & FMT_WIDE) || !(c & 0200))
+ {
+ *b++ = '0' + ((c >> 6) & 07);
+ *b++ = '0' + ((c >> 3) & 07);
+ c = '0' + (c & 07);
+ }
+ else
+ b--;
+ break;
+ }
+ }
+ else if (c == '\\')
+ {
+ escaped = 1;
+ *b++ = c;
+ if (*s)
+ c = *s++;
+ }
+ else if (qe && strchr(qe, c))
+ {
+ if (singlequote && c == '\'')
+ {
+ spaced = 1;
+ *b++ = '\'';
+ *b++ = '\\';
+ *b++ = '\'';
+ c = '\'';
+ }
+ else
+ {
+ escaped = 1;
+ *b++ = '\\';
+ }
+ }
+ else if (c == '$' || c == '`')
+ {
+ if (c == '$' && (flags & FMT_PARAM) && (*s == '{' || *s == '('))
+ {
+ if (singlequote || shell)
+ {
+ escaped = 1;
+ *b++ = '\'';
+ *b++ = c;
+ *b++ = *s++;
+ if (shell)
+ {
+ spaced = 1;
+ *b++ = '$';
+ }
+ c = '\'';
+ }
+ else
+ {
+ escaped = 1;
+ *b++ = c;
+ c = *s++;
+ }
+ }
+ else if (doublequote)
+ *b++ = '\\';
+ else if (singlequote || (flags & FMT_SHELL))
+ spaced = 1;
+ }
+ else if (!spaced && !escaped && (isspace(c) || ((flags & FMT_SHELL) || shell) && (strchr("\";~&|()<>[]*?", c) || c == '#' && (b == f || isspace(*(b - 1))))))
+ spaced = 1;
+ *b++ = c;
+ }
+ }
+ if (qb)
+ {
+ if (!escaped)
+ buf += shell + !spaced;
+ if (qe && (escaped || spaced))
+ while (*b = *qe++)
+ b++;
+ }
+ *b = 0;
+ return buf;
+}
+
+/*
+ * escape the usual suspects and quote chars in qs
+ * in length n string as
+ */
+
+char*
+fmtnesq(const char* as, const char* qs, size_t n)
+{
+ return fmtquote(as, NiL, qs, n, 0);
+}
+
+/*
+ * escape the usual suspects and quote chars in qs
+ */
+
+char*
+fmtesq(const char* as, const char* qs)
+{
+ return fmtquote(as, NiL, qs, strlen((char*)as), 0);
+}
+
+/*
+ * escape the usual suspects
+ */
+
+char*
+fmtesc(const char* as)
+{
+ return fmtquote(as, NiL, NiL, strlen((char*)as), 0);
+}
diff --git a/src/lib/libast/string/fmtfmt.c b/src/lib/libast/string/fmtfmt.c
new file mode 100644
index 0000000..639355b
--- /dev/null
+++ b/src/lib/libast/string/fmtfmt.c
@@ -0,0 +1,205 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return printf(3) format signature given format string
+ * the format signature contains one char per format optionally preceded
+ * by the number of `*' args
+ * c char
+ * d double
+ * D long double
+ * f float
+ * h short
+ * i int
+ * j long long
+ * l long
+ * p void*
+ * s string
+ * t ptrdiff_t
+ * z size_t
+ * ? unknown
+ */
+
+#include <ast.h>
+#include <ctype.h>
+
+char*
+fmtfmt(const char* as)
+{
+ register char* s = (char*)as;
+ char* buf;
+ int i;
+ int c;
+ int a;
+ int q;
+ int x;
+ int t;
+ int m;
+ int n;
+ int z;
+ char formats[256];
+ unsigned int extra[elementsof(formats)];
+
+ z = 1;
+ i = m = 0;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ break;
+ case '%':
+ if (*s == '%')
+ continue;
+ n = 0;
+ a = 0;
+ q = 0;
+ t = '?';
+ x = 0;
+ for (;;)
+ {
+ switch (c = *s++)
+ {
+ case 0:
+ s--;
+ break;
+ case '(':
+ q++;
+ continue;
+ case ')':
+ if (--q <= 0)
+ n = 0;
+ continue;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ case '8': case '9':
+ n = n * 10 + (c - '0');
+ continue;
+ case '$':
+ a = n;
+ n = 0;
+ continue;
+ case '*':
+ x++;
+ n = 0;
+ continue;
+ case 'h':
+ if (!q)
+ t = t == 'h' ? 'c' : 'h';
+ continue;
+ case 'l':
+ if (!q)
+ t = t == 'l' ? 'j' : 'l';
+ continue;
+ case 'j':
+ case 't':
+ case 'z':
+ if (!q)
+ t = c;
+ continue;
+ case 'c':
+ case 'p':
+ case 's':
+ if (!q)
+ {
+ t = c;
+ break;
+ }
+ continue;
+ case 'e':
+ case 'g':
+ if (!q)
+ {
+ switch (t)
+ {
+ case 'j':
+ t = 'D';
+ break;
+ default:
+ t = 'd';
+ break;
+ }
+ break;
+ }
+ continue;
+ case 'f':
+ if (!q)
+ {
+ switch (t)
+ {
+ case 'j':
+ t = 'D';
+ break;
+ case 'l':
+ t = 'd';
+ break;
+ default:
+ t = c;
+ break;
+ }
+ break;
+ }
+ continue;
+ default:
+ if (!q && isalpha(c))
+ {
+ if (t == '?')
+ t = 'i';
+ break;
+ }
+ n = 0;
+ continue;
+ }
+ break;
+ }
+ if (a)
+ i = a;
+ else
+ i++;
+ if (i < elementsof(formats))
+ {
+ formats[i] = t;
+ if (extra[i] = x)
+ do z++; while (x /= 10);
+ if (m < i)
+ m = i;
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ s = buf = fmtbuf(m + z);
+ for (i = 1; i <= m; i++)
+ {
+ if (extra[i])
+ s += sfsprintf(s, 10, "%d", extra[m]);
+ *s++ = formats[i];
+ }
+ *s = 0;
+ return buf;
+}
diff --git a/src/lib/libast/string/fmtfs.c b/src/lib/libast/string/fmtfs.c
new file mode 100644
index 0000000..1d89b11
--- /dev/null
+++ b/src/lib/libast/string/fmtfs.c
@@ -0,0 +1,100 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * return fs type string given stat
+ */
+
+#include <ast.h>
+#include <ls.h>
+#include <mnt.h>
+
+#include "FEATURE/fs"
+
+#if _str_st_fstype
+
+char*
+fmtfs(struct stat* st)
+{
+ return st->st_fstype;
+}
+
+#else
+
+#include <cdt.h>
+
+typedef struct Id_s
+{
+ Dtlink_t link;
+ dev_t id;
+ char name[1];
+} Id_t;
+
+char*
+fmtfs(struct stat* st)
+{
+ register Id_t* ip;
+ register void* mp;
+ register Mnt_t* mnt;
+ register char* s;
+ struct stat rt;
+ char* buf;
+
+ static Dt_t* dict;
+ static Dtdisc_t disc;
+
+ if (!dict)
+ {
+ disc.key = offsetof(Id_t, id);
+ disc.size = sizeof(dev_t);
+ dict = dtopen(&disc, Dtset);
+ }
+ else if (ip = (Id_t*)dtmatch(dict, &st->st_dev))
+ return ip->name;
+ s = FS_default;
+ if (mp = mntopen(NiL, "r"))
+ {
+ while ((mnt = mntread(mp)) && (stat(mnt->dir, &rt) || rt.st_dev != st->st_dev));
+ if (mnt && mnt->type)
+ s = mnt->type;
+ }
+ if (!dict || !(ip = newof(0, Id_t, 1, strlen(s))))
+ {
+ if (!mp)
+ return s;
+ buf = fmtbuf(strlen(s) + 1);
+ strcpy(buf, s);
+ mntclose(mp);
+ return buf;
+ }
+ strcpy(ip->name, s);
+ if (mp)
+ mntclose(mp);
+ dtinsert(dict, ip);
+ return ip->name;
+}
+
+#endif
diff --git a/src/lib/libast/string/fmtgid.c b/src/lib/libast/string/fmtgid.c
new file mode 100644
index 0000000..25ef158
--- /dev/null
+++ b/src/lib/libast/string/fmtgid.c
@@ -0,0 +1,101 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * cached gid number -> name
+ */
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide getgrgid
+#else
+#define getgrgid ______getgrgid
+#endif
+
+#include <ast.h>
+#include <cdt.h>
+#include <grp.h>
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide getgrgid
+#else
+#undef getgrgid
+#endif
+
+extern struct group* getgrgid(gid_t);
+
+typedef struct Id_s
+{
+ Dtlink_t link;
+ int id;
+ char name[1];
+} Id_t;
+
+/*
+ * return gid name given gid number
+ */
+
+char*
+fmtgid(int gid)
+{
+ register Id_t* ip;
+ register char* name;
+ register struct group* gr;
+ int z;
+
+ static Dt_t* dict;
+ static Dtdisc_t disc;
+
+ if (!dict)
+ {
+ disc.key = offsetof(Id_t, id);
+ disc.size = sizeof(int);
+ dict = dtopen(&disc, Dtset);
+ }
+ else if (ip = (Id_t*)dtmatch(dict, &gid))
+ return ip->name;
+ if (gr = getgrgid(gid))
+ {
+ name = gr->gr_name;
+#if _WINIX
+ if (streq(name, "Administrators"))
+ name = "sys";
+#endif
+ }
+ else if (gid == 0)
+ name = "sys";
+ else
+ {
+ name = fmtbuf(z = sizeof(gid) * 3 + 1);
+ sfsprintf(name, z, "%I*d", sizeof(gid), gid);
+ }
+ if (dict && (ip = newof(0, Id_t, 1, strlen(name))))
+ {
+ ip->id = gid;
+ strcpy(ip->name, name);
+ dtinsert(dict, ip);
+ return ip->name;
+ }
+ return name;
+}
diff --git a/src/lib/libast/string/fmtident.c b/src/lib/libast/string/fmtident.c
new file mode 100644
index 0000000..0ffab5c
--- /dev/null
+++ b/src/lib/libast/string/fmtident.c
@@ -0,0 +1,77 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <ctype.h>
+
+#define IDENT 01
+#define USAGE 02
+
+/*
+ * format what(1) and/or ident(1) string a
+ */
+
+char*
+fmtident(const char* a)
+{
+ register char* s = (char*)a;
+ register char* t;
+ char* buf;
+ int i;
+
+ i = 0;
+ for (;;)
+ {
+ while (isspace(*s))
+ s++;
+ if (s[0] == '[')
+ {
+ while (*++s && *s != '\n');
+ i |= USAGE;
+ }
+ else if (s[0] == '@' && s[1] == '(' && s[2] == '#' && s[3] == ')')
+ s += 4;
+ else if (s[0] == '$' && s[1] == 'I' && s[2] == 'd' && s[3] == ':' && isspace(s[4]))
+ {
+ s += 5;
+ i |= IDENT;
+ }
+ else
+ break;
+ }
+ if (i)
+ {
+ i &= IDENT;
+ for (t = s; isprint(*t) && *t != '\n'; t++)
+ if (i && t[0] == ' ' && t[1] == '$')
+ break;
+ while (t > s && isspace(t[-1]))
+ t--;
+ i = t - s;
+ buf = fmtbuf(i + 1);
+ memcpy(buf, s, i);
+ s = buf;
+ s[i] = 0;
+ }
+ return s;
+}
diff --git a/src/lib/libast/string/fmtint.c b/src/lib/libast/string/fmtint.c
new file mode 100644
index 0000000..932fe1e
--- /dev/null
+++ b/src/lib/libast/string/fmtint.c
@@ -0,0 +1,122 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * format decimal integer
+ * David Korn
+ * AT&T Research
+ */
+
+#include <ast.h>
+
+static const char table[]=
+{
+ "000001002003004005006007008009010011012013014015016017018019"
+ "020021022023024025026027028029030031032033034035036037038039"
+ "040041042043044045046047048049050051052053054055056057058059"
+ "060061062063064065066067068069070071072073074075076077078079"
+ "080081082083084085086087088089090091092093094095096097098099"
+ "100101102103104105106107108109110111112113114115116117118119"
+ "120121122123124125126127128129130131132133134135136137138139"
+ "140141142143144145146147148149150151152153154155156157158159"
+ "160161162163164165166167168169170171172173174175176177178179"
+ "180181182183184185186187188189190191192193194195196197198199"
+ "200201202203204205206207208209210211212213214215216217218219"
+ "220221222223224225226227228229230231232233234235236237238239"
+ "240241242243244245246247248249250251252253254255256257258259"
+ "260261262263264265266267268269270271272273274275276277278279"
+ "280281282283284285286287288289290291292293294295296297298299"
+ "300301302303304305306307308309310311312313314315316317318319"
+ "320321322323324325326327328329330331332333334335336337338339"
+ "340341342343344345346347348349350351352353354355356357358359"
+ "360361362363364365366367368369370371372373374375376377378379"
+ "380381382383384385386387388389390391392393394395396397398399"
+ "400401402403404405406407408409410411412413414415416417418419"
+ "420421422423424425426427428429430431432433434435436437438439"
+ "440441442443444445446447448449450451452453454455456457458459"
+ "460461462463464465466467468469470471472473474475476477478479"
+ "480481482483484485486487488489490491492493494495496497498499"
+ "500501502503504505506507508509510511512513514515516517518519"
+ "520521522523524525526527528529530531532533534535536537538539"
+ "540541542543544545546547548549550551552553554555556557558559"
+ "560561562563564565566567568569570571572573574575576577578579"
+ "580581582583584585586587588589590591592593594595596597598599"
+ "600601602603604605606607608609610611612613614615616617618619"
+ "620621622623624625626627628629630631632633634635636637638639"
+ "640641642643644645646647648649650651652653654655656657658659"
+ "660661662663664665666667668669670671672673674675676677678679"
+ "680681682683684685686687688689690691692693694695696697698699"
+ "700701702703704705706707708709710711712713714715716717718719"
+ "720721722723724725726727728729730731732733734735736737738739"
+ "740741742743744745746747748749750751752753754755756757758759"
+ "760761762763764765766767768769770771772773774775776777778779"
+ "780781782783784785786787788789790791792793794795796797798799"
+ "800801802803804805806807808809810811812813814815816817818819"
+ "820821822823824825826827828829830831832833834835836837838839"
+ "840841842843844845846847848849850851852853854855856857858859"
+ "860861862863864865866867868869870871872873874875876877878879"
+ "880881882883884885886887888889890891892893894895896897898899"
+ "900901902903904905906907908909910911912913914915916917918919"
+ "920921922923924925926927928929930931932933934935936937938939"
+ "940941942943944945946947948949950951952953954955956957958959"
+ "960961962963964965966967968969970971972973974975976977978979"
+ "980981982983984985986987988989990991992993994995996997998999"
+};
+
+char*
+fmtint(intmax_t ll, int unsign)
+{
+ char *buff;
+ uintmax_t n,m;
+ int j=0,k=3*sizeof(ll);
+ if(unsign || ll>=0)
+ n = ll;
+ else
+ {
+ n = -ll;
+ j = 1;
+ }
+ if(n<10)
+ {
+ buff = fmtbuf(k=3);
+ buff[--k] = 0;
+ buff[--k] = '0' + n;
+ goto skip;
+ }
+ buff = fmtbuf(k);
+ buff[--k] = 0;
+ do
+ {
+ k -= 3;
+ if((m=n) >= 1000)
+ m = n%1000;
+ memcpy(buff+k,table+3*m,3);
+ n /= 1000;
+ }
+ while(n>0);
+ while(buff[k]=='0')
+ k++;
+skip:
+ if(j)
+ buff[--k] = '-';
+ return(&buff[k]);
+}
diff --git a/src/lib/libast/string/fmtip4.c b/src/lib/libast/string/fmtip4.c
new file mode 100644
index 0000000..3920c7f
--- /dev/null
+++ b/src/lib/libast/string/fmtip4.c
@@ -0,0 +1,43 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+/*
+ * format 4 byte local byte order ip address
+ * and optional prefix bits (if 0 <= bits <= 32)
+ */
+
+char*
+fmtip4(register uint32_t addr, int bits)
+{
+ char* buf;
+ int z;
+ int i;
+
+ buf = fmtbuf(z = 20);
+ i = sfsprintf(buf, z, "%d.%d.%d.%d", (addr>>24)&0xff, (addr>>16)&0xff, (addr>>8)&0xff, (addr)&0xff);
+ if (bits >= 0 && bits <= 32)
+ sfsprintf(buf + i, z - i, "/%d", bits);
+ return buf;
+}
diff --git a/src/lib/libast/string/fmtip6.c b/src/lib/libast/string/fmtip6.c
new file mode 100644
index 0000000..50bac43
--- /dev/null
+++ b/src/lib/libast/string/fmtip6.c
@@ -0,0 +1,175 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#if _PACKAGE_ast
+#include <ast.h>
+#endif
+
+#include <ip6.h>
+
+#if !_PACKAGE_ast
+
+/*
+ * return a pointer to n bytes from a circular re-use buffer
+ */
+
+static char*
+fmtbuf(int n)
+{
+ char* b;
+
+ static char buf[1024];
+ static char* p = buf;
+
+ if ((&buf[sizeof(buf)] - p) < n)
+ p = buf;
+ b = p;
+ p += n;
+ return b;
+}
+
+#endif
+
+/*
+ * copy p to s, then convert 0<=n<=999 to text
+ * next char in s returned
+ * caller ensures that s can take strlen(p)+3 bytes
+ */
+
+static char*
+dec(char* s, char* p, int n)
+{
+ while (*s = *p++)
+ s++;
+ if (n >= 100)
+ *s++ = '0' + ((n / 100) % 10);
+ if (n >= 10)
+ *s++ = '0' + ((n / 10) % 10);
+ *s++ = '0' + (n % 10);
+ return s;
+}
+
+/*
+ * return pointer to normalized ipv6 address addr
+ * with optional prefix bits if 0 <= bits <= 128
+ * return value in short-term circular buffer
+ */
+
+char*
+fmtip6(const unsigned char* addr, int bits)
+{
+ register const unsigned char* a = addr;
+ register int n = IP6ADDR;
+ register int i;
+ register int z;
+ register int k;
+ register int m;
+ unsigned char r[IP6ADDR];
+ char* b;
+ char* s;
+
+ static const char dig[] = "0123456789ABCDEF";
+
+ s = b = fmtbuf(44);
+ r[m = z = 0] = 0;
+ if (a[0] == 0x20 && a[1] == 0x02 && (a[2] || a[3] || a[4] || a[5]))
+ {
+ z = 6;
+ s = dec(s, "2002:", a[2]);
+ s = dec(s, ".", a[3]);
+ s = dec(s, ".", a[4]);
+ s = dec(s, ".", a[5]);
+ }
+ for (i = z; i < n; i += 2)
+ {
+ for (k = i; i < n - 1 && !a[i] && !a[i + 1]; i += 2);
+ if ((r[k] = i - k) > r[m] || r[k] == r[m] && i >= (n - 1))
+ m = k;
+ }
+ if (!m)
+ switch (r[m])
+ {
+ case 0:
+ m = -1;
+ break;
+ case 14:
+ if (!a[14] && a[15] <= 15)
+ break;
+ /*FALLTHROUGH*/
+ case 12:
+ s = dec(s, "::", a[12]);
+ s = dec(s, ".", a[13]);
+ s = dec(s, ".", a[14]);
+ s = dec(s, ".", a[15]);
+ n = 0;
+ break;
+ case 10:
+ if (a[10] == 0xFF && a[11] == 0xFF)
+ {
+ s = dec(s, "::FFFF:", a[12]);
+ s = dec(s, ".", a[13]);
+ s = dec(s, ".", a[14]);
+ s = dec(s, ".", a[15]);
+ n = 0;
+ }
+ break;
+ }
+ for (i = z; i < n; i++)
+ {
+ if (i == m)
+ {
+ *s++ = ':';
+ *s++ = ':';
+ if ((i += r[m]) >= n)
+ {
+ z = 1;
+ break;
+ }
+ z = 0;
+ }
+ else if (i && !(i & 1))
+ {
+ if (z)
+ z = 0;
+ else
+ *s++ = '0';
+ *s++ = ':';
+ }
+ if ((k = (a[i] >> 4) & 0xf) || z)
+ {
+ z = 1;
+ *s++ = dig[k];
+ }
+ if ((k = a[i] & 0xf) || z)
+ {
+ z = 1;
+ *s++ = dig[k];
+ }
+ }
+ if (!z && *(s - 1) == ':')
+ *s++ = '0';
+ if (bits >= 0 && bits <= 128)
+ s = dec(s, "/", bits);
+ *s = 0;
+ return b;
+}
diff --git a/src/lib/libast/string/fmtls.c b/src/lib/libast/string/fmtls.c
new file mode 100644
index 0000000..7b791dd
--- /dev/null
+++ b/src/lib/libast/string/fmtls.c
@@ -0,0 +1,120 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * ls formatter
+ */
+
+#include <ast.h>
+#include <ls.h>
+#include <tm.h>
+
+#ifndef LS_W_MAX
+#define LS_W_MAX 128
+#endif
+
+/*
+ * ls formatter
+ *
+ * buf results placed here
+ * name file name
+ * st file stat buffer
+ * info optional info
+ * link link text if != 0
+ * flags LS_* flags
+ *
+ * return end of formatted buf
+ */
+
+char*
+fmtls(char* buf, const char* name, register struct stat* st, const char* info, const char* link, register int flags)
+{
+ register char* s;
+ time_t tm;
+ Sfoff_t n;
+
+ s = buf;
+ if (flags & LS_INUMBER)
+ s += sfsprintf(s, LS_W_MAX, "%*I*u ", LS_W_INUMBER - 1, sizeof(st->st_ino), st->st_ino);
+ if (flags & LS_BLOCKS)
+ {
+ n = iblocks(st);
+ s += sfsprintf(s, LS_W_MAX, "%*I*u ", LS_W_BLOCKS - 1, sizeof(n), n);
+ }
+ if (flags & LS_LONG)
+ {
+ s += sfsprintf(s, LS_W_MAX, "%s%3u", fmtmode(st->st_mode, flags & LS_EXTERNAL), (unsigned int)st->st_nlink);
+ if (!(flags & LS_NOUSER))
+ {
+ if (flags & LS_NUMBER)
+ s += sfsprintf(s, LS_W_MAX, " %-*I*d", LS_W_NAME - 1, sizeof(st->st_uid), st->st_uid);
+ else
+ s += sfsprintf(s, LS_W_MAX, " %-*s", LS_W_NAME - 1, fmtuid(st->st_uid));
+ }
+ if (!(flags & LS_NOGROUP))
+ {
+ if (flags & LS_NUMBER)
+ s += sfsprintf(s, LS_W_MAX, " %-*I*d", LS_W_NAME - 1, sizeof(st->st_gid), st->st_gid);
+ else
+ s += sfsprintf(s, LS_W_MAX, " %-*s", LS_W_NAME - 1, fmtgid(st->st_gid));
+ }
+ if (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode))
+ s += sfsprintf(s, LS_W_MAX, "%8s ", fmtdev(st));
+ else
+ s += sfsprintf(s, LS_W_MAX, "%8I*u ", sizeof(st->st_size), st->st_size);
+ tm = (flags & LS_ATIME) ? st->st_atime : (flags & LS_CTIME) ? st->st_ctime : st->st_mtime;
+ s = tmfmt(s, LS_W_LONG / 2, "%?%QL", &tm);
+ *s++ = ' ';
+ }
+ if (info)
+ {
+ while (*s = *info++)
+ s++;
+ *s++ = ' ';
+ }
+ while (*s = *name++)
+ s++;
+ if (flags & LS_MARK)
+ {
+ if (S_ISDIR(st->st_mode))
+ *s++ = '/';
+#ifdef S_ISLNK
+ else if (S_ISLNK(st->st_mode))
+ *s++ = '@';
+#endif
+ else if (st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
+ *s++ = '*';
+ }
+ if (link)
+ {
+ s += sfsprintf(s, LS_W_MAX, " %s %s",
+#ifdef S_ISLNK
+ S_ISLNK(st->st_mode) ? "->" :
+#endif
+ "==", link);
+ }
+ *s = 0;
+ return s;
+}
diff --git a/src/lib/libast/string/fmtmatch.c b/src/lib/libast/string/fmtmatch.c
new file mode 100644
index 0000000..2daf2f7
--- /dev/null
+++ b/src/lib/libast/string/fmtmatch.c
@@ -0,0 +1,286 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return strmatch() expression given REG_AUGMENTED RE
+ * 0 returned for invalid RE
+ */
+
+#include <ast.h>
+
+char*
+fmtmatch(const char* as)
+{
+ register char* s = (char*)as;
+ register int c;
+ register char* t;
+ register char** p;
+ register char* b;
+ char* x;
+ char* y;
+ char* z;
+ int a;
+ int e;
+ int n;
+ char* buf;
+ char* stack[32];
+
+ c = 3 * (strlen(s) + 1);
+ buf = fmtbuf(c);
+ t = b = buf + 3;
+ p = stack;
+ if (a = *s == '^')
+ s++;
+ e = 0;
+ for (;;)
+ {
+ switch (c = *s++)
+ {
+ case 0:
+ break;
+ case '\\':
+ if (!(c = *s++))
+ return 0;
+ switch (*s)
+ {
+ case '*':
+ case '+':
+ case '?':
+ *t++ = *s++;
+ *t++ = '(';
+ *t++ = '\\';
+ *t++ = c;
+ c = ')';
+ break;
+ case '|':
+ case '&':
+ if (c == '(')
+ {
+ *t++ = c;
+ c = *s++;
+ goto logical;
+ }
+ break;
+ case '{':
+ case '}':
+ break;
+ default:
+ *t++ = '\\';
+ break;
+ }
+ *t++ = c;
+ continue;
+ case '[':
+ x = t;
+ *t++ = c;
+ if ((c = *s++) == '^')
+ {
+ *t++ = '!';
+ c = *s++;
+ }
+ else if (c == '!')
+ {
+ *t++ = '\\';
+ *t++ = c;
+ c = *s++;
+ }
+ for (;;)
+ {
+ if (!(*t++ = c))
+ return 0;
+ if (c == '\\')
+ *t++ = c;
+ if ((c = *s++) == ']')
+ {
+ *t++ = c;
+ break;
+ }
+ }
+ switch (*s)
+ {
+ case '*':
+ case '+':
+ case '?':
+ for (y = t + 2, t--; t >= x; t--)
+ *(t + 2) = *t;
+ *++t = *s++;
+ *++t = '(';
+ t = y;
+ *t++ = ')';
+ break;
+ }
+ continue;
+ case '(':
+ if (p >= &stack[elementsof(stack)])
+ return 0;
+ *p++ = t;
+ if (*s == '?')
+ {
+ s++;
+ if (*s == 'K' && *(s + 1) == ')')
+ {
+ s += 2;
+ p--;
+ while (*t = *s)
+ t++, s++;
+ continue;
+ }
+ *t++ = '~';
+ }
+ else
+ *t++ = '@';
+ *t++ = '(';
+ continue;
+ case ')':
+ if (p == stack)
+ return 0;
+ p--;
+ *t++ = c;
+ switch (*s)
+ {
+ case 0:
+ break;
+ case '*':
+ case '+':
+ case '?':
+ case '!':
+ **p = *s++;
+ if (*s == '?')
+ {
+ s++;
+ x = *p + 1;
+ for (y = ++t; y > x; y--)
+ *y = *(y - 1);
+ *x = '-';
+ }
+ continue;
+ case '{':
+ for (z = s; *z != '}'; z++)
+ if (!*z)
+ return 0;
+ n = z - s;
+ if (*++z == '?')
+ n++;
+ x = *p + n;
+ for (y = t += n; y > x; y--)
+ *y = *(y - n);
+ for (x = *p; s < z; *x++ = *s++);
+ if (*s == '?')
+ {
+ s++;
+ *x++ = '-';
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ case '.':
+ switch (*s)
+ {
+ case 0:
+ *t++ = '?';
+ break;
+ case '*':
+ s++;
+ *t++ = '*';
+ e = !*s;
+ continue;
+ case '+':
+ s++;
+ *t++ = '?';
+ *t++ = '*';
+ continue;
+ case '?':
+ s++;
+ *t++ = '?';
+ *t++ = '(';
+ *t++ = '?';
+ *t++ = ')';
+ continue;
+ default:
+ *t++ = '?';
+ continue;
+ }
+ break;
+ case '*':
+ case '+':
+ case '?':
+ case '{':
+ n = *(t - 1);
+ if (t == b || n == '(' || n == '|')
+ return 0;
+ *(t - 1) = c;
+ if (c == '{')
+ {
+ for (z = s; *z != '}'; z++)
+ if (!*z)
+ return 0;
+ for (; s <= z; *t++ = *s++);
+ }
+ if (*s == '?')
+ {
+ s++;
+ *t++ = '-';
+ }
+ *t++ = '(';
+ *t++ = n;
+ *t++ = ')';
+ continue;
+ case '|':
+ case '&':
+ if (t == b || *(t - 1) == '(')
+ return 0;
+ logical:
+ if (!*s || *s == ')')
+ return 0;
+ if (p == stack && b == buf + 3)
+ {
+ *--b = '(';
+ *--b = '@';
+ }
+ *t++ = c;
+ continue;
+ case '$':
+ if (e = !*s)
+ break;
+ /*FALLTHROUGH*/
+ default:
+ *t++ = c;
+ continue;
+ }
+ break;
+ }
+ if (p != stack)
+ return 0;
+ if (b != buf + 3)
+ *t++ = ')';
+ if (!a && (*b != '*' || *(b + 1) == '(' || (*(b + 1) == '-' || *(b + 1) == '~') && *(b + 2) == '('))
+ *--b = '*';
+ if (!e)
+ *t++ = '*';
+ *t = 0;
+ return b;
+}
diff --git a/src/lib/libast/string/fmtmode.c b/src/lib/libast/string/fmtmode.c
new file mode 100644
index 0000000..2f9dc4f
--- /dev/null
+++ b/src/lib/libast/string/fmtmode.c
@@ -0,0 +1,47 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * return ls -l style file mode string given file mode bits
+ * if external!=0 then mode is modex canonical
+ */
+
+#include "modelib.h"
+
+char*
+fmtmode(register int mode, int external)
+{
+ register char* s;
+ register struct modeop* p;
+ char* buf;
+
+ if (!external)
+ mode = modex(mode);
+ s = buf = fmtbuf(MODELEN + 1);
+ for (p = modetab; p < &modetab[MODELEN]; p++)
+ *s++ = p->name[((mode & p->mask1) >> p->shift1) | ((mode & p->mask2) >> p->shift2)];
+ *s = 0;
+ return buf;
+}
diff --git a/src/lib/libast/string/fmtnum.c b/src/lib/libast/string/fmtnum.c
new file mode 100644
index 0000000..49fb9c3
--- /dev/null
+++ b/src/lib/libast/string/fmtnum.c
@@ -0,0 +1,92 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return scaled number n
+ * string width is 5 chars or less
+ * if m>1 then n divided by m before scaling
+ */
+
+#include <ast.h>
+
+char*
+fmtnum(register unsigned long n, int m)
+{
+ register int i;
+ register unsigned long r;
+ char* buf;
+ int z;
+
+ char suf[2];
+
+ if (m > 1)
+ {
+ r = n;
+ n /= m;
+ r -= n;
+ }
+ else
+ r = 0;
+ suf[1] = 0;
+ if (n < 1024)
+ suf[0] = 0;
+ else if (n < 1024 * 1024)
+ {
+ suf[0] = 'k';
+ r = ((n % 1024) * 100) / 1024;
+ n /= 1024;
+ }
+ else if (n < 1024 * 1024 * 1024)
+ {
+ suf[0] = 'm';
+ r = ((n % (1024 * 1024)) * 100) / (1024 * 1024);
+ n /= 1024 * 1024;
+ }
+ else
+ {
+ suf[0] = 'g';
+ r = ((n % (1024 * 1024 * 1024)) * 100) / (1024 * 1024 * 1024);
+ n /= 1024 * 1024 * 1024;
+ }
+ if (r)
+ {
+ if (n >= 100)
+ r = 0;
+ else if (n >= 10)
+ {
+ i = 1;
+ if (r >= 10)
+ r /= 10;
+ }
+ else
+ i = 2;
+ }
+ buf = fmtbuf(z = 8);
+ if (r)
+ sfsprintf(buf, z, "%lu.%0*lu%s", n, i, r, suf);
+ else
+ sfsprintf(buf, z, "%lu%s", n, suf);
+ return buf;
+}
diff --git a/src/lib/libast/string/fmtperm.c b/src/lib/libast/string/fmtperm.c
new file mode 100644
index 0000000..c10d379
--- /dev/null
+++ b/src/lib/libast/string/fmtperm.c
@@ -0,0 +1,91 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * return strperm() expression for perm
+ */
+
+#include <ast.h>
+#include <ls.h>
+
+char*
+fmtperm(register int perm)
+{
+ register char* s;
+ char* buf;
+
+ s = buf = fmtbuf(32);
+
+ /*
+ * u
+ */
+
+ *s++ = 'u';
+ *s++ = '=';
+ if (perm & S_ISVTX)
+ *s++ = 't';
+ if (perm & S_ISUID)
+ *s++ = 's';
+ if (perm & S_IRUSR)
+ *s++ = 'r';
+ if (perm & S_IWUSR)
+ *s++ = 'w';
+ if (perm & S_IXUSR)
+ *s++ = 'x';
+ if ((perm & (S_ISGID|S_IXGRP)) == S_ISGID)
+ *s++ = 'l';
+
+ /*
+ * g
+ */
+
+ *s++ = ',';
+ *s++ = 'g';
+ *s++ = '=';
+ if ((perm & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP))
+ *s++ = 's';
+ if (perm & S_IRGRP)
+ *s++ = 'r';
+ if (perm & S_IWGRP)
+ *s++ = 'w';
+ if (perm & S_IXGRP)
+ *s++ = 'x';
+
+ /*
+ * o
+ */
+
+ *s++ = ',';
+ *s++ = 'o';
+ *s++ = '=';
+ if (perm & S_IROTH)
+ *s++ = 'r';
+ if (perm & S_IWOTH)
+ *s++ = 'w';
+ if (perm & S_IXOTH)
+ *s++ = 'x';
+ *s = 0;
+ return buf;
+}
diff --git a/src/lib/libast/string/fmtre.c b/src/lib/libast/string/fmtre.c
new file mode 100644
index 0000000..a4a887b
--- /dev/null
+++ b/src/lib/libast/string/fmtre.c
@@ -0,0 +1,226 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return RE expression given strmatch() pattern
+ * 0 returned for invalid RE
+ */
+
+#include <ast.h>
+
+typedef struct Stack_s
+{
+ char* beg;
+ short len;
+ short min;
+} Stack_t;
+
+char*
+fmtre(const char* as)
+{
+ register char* s = (char*)as;
+ register int c;
+ register char* t;
+ register Stack_t* p;
+ char* x;
+ int n;
+ int end;
+ char* buf;
+ Stack_t stack[32];
+
+ end = 1;
+ c = 2 * strlen(s) + 1;
+ t = buf = fmtbuf(c);
+ p = stack;
+ if (*s != '*' || *(s + 1) == '(' || *(s + 1) == '-' && *(s + 2) == '(')
+ *t++ = '^';
+ else
+ s++;
+ for (;;)
+ {
+ switch (c = *s++)
+ {
+ case 0:
+ break;
+ case '\\':
+ if (!(c = *s++) || c == '{' || c == '}')
+ return 0;
+ *t++ = '\\';
+ if ((*t++ = c) == '(' && *s == '|')
+ {
+ *t++ = *s++;
+ goto logical;
+ }
+ continue;
+ case '[':
+ *t++ = c;
+ n = 0;
+ if ((c = *s++) == '!')
+ {
+ *t++ = '^';
+ c = *s++;
+ }
+ else if (c == '^')
+ {
+ if ((c = *s++) == ']')
+ {
+ *(t - 1) = '\\';
+ *t++ = '^';
+ continue;
+ }
+ n = '^';
+ }
+ for (;;)
+ {
+ if (!(*t++ = c))
+ return 0;
+ if ((c = *s++) == ']')
+ {
+ if (n)
+ *t++ = n;
+ *t++ = c;
+ break;
+ }
+ }
+ continue;
+ case '{':
+ for (x = s; *x && *x != '}'; x++);
+ if (*x++ && (*x == '(' || *x == '-' && *(x + 1) == '('))
+ {
+ if (p >= &stack[elementsof(stack)])
+ return 0;
+ p->beg = s - 1;
+ s = x;
+ p->len = s - p->beg;
+ if (p->min = *s == '-')
+ s++;
+ p++;
+ *t++ = *s++;
+ }
+ else
+ *t++ = c;
+ continue;
+ case '*':
+ if (!*s)
+ {
+ end = 0;
+ break;
+ }
+ /*FALLTHROUGH*/
+ case '?':
+ case '+':
+ case '@':
+ case '!':
+ case '~':
+ if (*s == '(' || c != '~' && *s == '-' && *(s + 1) == '(')
+ {
+ if (p >= &stack[elementsof(stack)])
+ return 0;
+ p->beg = s - 1;
+ if (c == '~')
+ {
+ if (*(s + 1) == 'E' && *(s + 2) == ')')
+ {
+ for (s += 3; *t = *s; t++, s++);
+ continue;
+ }
+ p->len = 0;
+ p->min = 0;
+ *t++ = *s++;
+ *t++ = '?';
+ }
+ else
+ {
+ p->len = c != '@';
+ if (p->min = *s == '-')
+ s++;
+ *t++ = *s++;
+ }
+ p++;
+ }
+ else
+ {
+ switch (c)
+ {
+ case '*':
+ *t++ = '.';
+ break;
+ case '?':
+ c = '.';
+ break;
+ case '+':
+ case '!':
+ *t++ = '\\';
+ break;
+ }
+ *t++ = c;
+ }
+ continue;
+ case '(':
+ if (p >= &stack[elementsof(stack)])
+ return 0;
+ p->beg = s - 1;
+ p->len = 0;
+ p->min = 0;
+ p++;
+ *t++ = c;
+ continue;
+ case ')':
+ if (p == stack)
+ return 0;
+ *t++ = c;
+ p--;
+ for (c = 0; c < p->len; c++)
+ *t++ = p->beg[c];
+ if (p->min)
+ *t++ = '?';
+ continue;
+ case '^':
+ case '.':
+ case '$':
+ *t++ = '\\';
+ *t++ = c;
+ continue;
+ case '|':
+ if (t == buf || *(t - 1) == '(')
+ return 0;
+ logical:
+ if (!*s || *s == ')')
+ return 0;
+ /*FALLTHROUGH*/
+ default:
+ *t++ = c;
+ continue;
+ }
+ break;
+ }
+ if (p != stack)
+ return 0;
+ if (end)
+ *t++ = '$';
+ *t = 0;
+ return buf;
+}
diff --git a/src/lib/libast/string/fmtscale.c b/src/lib/libast/string/fmtscale.c
new file mode 100644
index 0000000..5a35577
--- /dev/null
+++ b/src/lib/libast/string/fmtscale.c
@@ -0,0 +1,94 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return number n scaled to metric multiples of k { 1000 1024 }
+ * return string length is at most 5 chars + terminating nul
+ */
+
+#include <ast.h>
+#include <lclib.h>
+
+char*
+fmtscale(register Sfulong_t n, int k)
+{
+ register Sfulong_t m;
+ int r;
+ int z;
+ const char* u;
+ char suf[3];
+ char* s;
+ char* buf;
+ Lc_numeric_t* p = (Lc_numeric_t*)LCINFO(AST_LC_NUMERIC)->data;
+
+ static const char scale[] = "bkMGTPE";
+
+ u = scale;
+ if (n < 1000)
+ r = 0;
+ else
+ {
+ m = 0;
+ while (n >= k && *(u + 1))
+ {
+ m = n;
+ n /= k;
+ u++;
+ }
+ if ((r = (10 * (m % k) + (k / 2)) / k) > 9)
+ {
+ r = 0;
+ n++;
+ }
+ if (k == 1024 && n >= 1000)
+ {
+ n = 1;
+ r = 0;
+ u++;
+ }
+ }
+ buf = fmtbuf(z = 8);
+ s = suf;
+ if (u > scale)
+ {
+ if (k == 1024)
+ {
+ *s++ = *u == 'k' ? 'K' : *u;
+ *s++ = 'i';
+ }
+ else
+ *s++ = *u;
+ }
+ *s = 0;
+ if (n > 0 && n < 10)
+ sfsprintf(buf, z, "%I*u%c%d%s", sizeof(n), n, p->decimal >= 0 ? p->decimal : '.', r, suf);
+ else
+ {
+ if (r >= 5)
+ n++;
+ sfsprintf(buf, z, "%I*u%s", sizeof(n), n, suf);
+ }
+ return buf;
+}
diff --git a/src/lib/libast/string/fmtsignal.c b/src/lib/libast/string/fmtsignal.c
new file mode 100644
index 0000000..a802a1d
--- /dev/null
+++ b/src/lib/libast/string/fmtsignal.c
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * if sig>=0 then return signal text for signal sig
+ * otherwise return signal name for signal -sig
+ */
+
+#include <ast.h>
+#include <sig.h>
+
+char*
+fmtsignal(register int sig)
+{
+ char* buf;
+ int z;
+
+ if (sig >= 0)
+ {
+ if (sig <= sig_info.sigmax)
+ buf = sig_info.text[sig];
+ else
+ {
+ buf = fmtbuf(z = 20);
+ sfsprintf(buf, z, "Signal %d", sig);
+ }
+ }
+ else
+ {
+ sig = -sig;
+ if (sig <= sig_info.sigmax)
+ buf = sig_info.name[sig];
+ else
+ {
+ buf = fmtbuf(z = 20);
+ sfsprintf(buf, z, "%d", sig);
+ }
+ }
+ return buf;
+}
diff --git a/src/lib/libast/string/fmttime.c b/src/lib/libast/string/fmttime.c
new file mode 100644
index 0000000..f2cfbce
--- /dev/null
+++ b/src/lib/libast/string/fmttime.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return tmfmt() formatted time
+ */
+
+#include "tm.h"
+
+char*
+fmttime(const char* format, time_t clock)
+{
+ char* buf;
+ int z;
+
+ buf = fmtbuf(z = 80);
+ tmfmt(buf, z, format, &clock);
+ return buf;
+}
diff --git a/src/lib/libast/string/fmttmx.c b/src/lib/libast/string/fmttmx.c
new file mode 100644
index 0000000..1a427ac
--- /dev/null
+++ b/src/lib/libast/string/fmttmx.c
@@ -0,0 +1,45 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <tmx.h>
+#include <tv.h>
+
+/*
+ * Time_t fmttime()
+ */
+
+char*
+fmttmx(const char* fmt, Time_t t)
+{
+ char* b;
+ char* e;
+ int z;
+
+ z = 0;
+ do
+ {
+ b = fmtbuf(z += 80);
+ e = tmxfmt(b, z, fmt, t);
+ } while (e == b + z);
+ return b;
+}
diff --git a/src/lib/libast/string/fmttv.c b/src/lib/libast/string/fmttv.c
new file mode 100644
index 0000000..f4cdf1b
--- /dev/null
+++ b/src/lib/libast/string/fmttv.c
@@ -0,0 +1,44 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <tv.h>
+#include <tm.h>
+
+/*
+ * Tv_t fmttime()
+ */
+
+char*
+fmttv(const char* fmt, Tv_t* tv)
+{
+ char* s;
+ char* t;
+ int n;
+
+ s = fmttime(fmt, (time_t)tv->tv_sec);
+ if (!tv->tv_nsec || tv->tv_nsec == TV_NSEC_IGNORE)
+ return s;
+ t = fmtbuf(n = strlen(s) + 11);
+ sfsprintf(t, n, "%s.%09lu", s, (unsigned long)tv->tv_nsec);
+ return t;
+}
diff --git a/src/lib/libast/string/fmtuid.c b/src/lib/libast/string/fmtuid.c
new file mode 100644
index 0000000..44a1d44
--- /dev/null
+++ b/src/lib/libast/string/fmtuid.c
@@ -0,0 +1,101 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * uid number -> name
+ */
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide getpwuid
+#else
+#define getpwuid ______getpwuid
+#endif
+
+#include <ast.h>
+#include <cdt.h>
+#include <pwd.h>
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide getpwuid
+#else
+#undef getpwuid
+#endif
+
+extern struct passwd* getpwuid(uid_t);
+
+typedef struct Id_s
+{
+ Dtlink_t link;
+ int id;
+ char name[1];
+} Id_t;
+
+/*
+ * return uid name given uid number
+ */
+
+char*
+fmtuid(int uid)
+{
+ register Id_t* ip;
+ register char* name;
+ register struct passwd* pw;
+ int z;
+
+ static Dt_t* dict;
+ static Dtdisc_t disc;
+
+ if (!dict)
+ {
+ disc.key = offsetof(Id_t, id);
+ disc.size = sizeof(int);
+ dict = dtopen(&disc, Dtset);
+ }
+ else if (ip = (Id_t*)dtmatch(dict, &uid))
+ return ip->name;
+ if (pw = getpwuid(uid))
+ {
+ name = pw->pw_name;
+#if _WINIX
+ if (streq(name, "Administrator"))
+ name = "root";
+#endif
+ }
+ else if (uid == 0)
+ name = "root";
+ else
+ {
+ name = fmtbuf(z = sizeof(uid) * 3 + 1);
+ sfsprintf(name, z, "%I*d", sizeof(uid), uid);
+ }
+ if (dict && (ip = newof(0, Id_t, 1, strlen(name))))
+ {
+ ip->id = uid;
+ strcpy(ip->name, name);
+ dtinsert(dict, ip);
+ return ip->name;
+ }
+ return name;
+}
diff --git a/src/lib/libast/string/fmtversion.c b/src/lib/libast/string/fmtversion.c
new file mode 100644
index 0000000..10f2fc9
--- /dev/null
+++ b/src/lib/libast/string/fmtversion.c
@@ -0,0 +1,53 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * return formatted <magicid.h> version string
+ */
+
+#include <ast.h>
+
+char*
+fmtversion(register unsigned long v)
+{
+ register char* cur;
+ register char* end;
+ char* buf;
+ int n;
+
+ buf = cur = fmtbuf(n = 18);
+ end = cur + n;
+ if (v >= 19700101L && v <= 29991231L)
+ sfsprintf(cur, end - cur, "%04lu-%02lu-%02lu", (v / 10000) % 10000, (v / 100) % 100, v % 100);
+ else
+ {
+ if (n = (v >> 24) & 0xff)
+ cur += sfsprintf(cur, end - cur, "%d.", n);
+ if (n = (v >> 16) & 0xff)
+ cur += sfsprintf(cur, end - cur, "%d.", n);
+ sfsprintf(cur, end - cur, "%ld.%ld", (v >> 8) & 0xff, v & 0xff);
+ }
+ return buf;
+}
diff --git a/src/lib/libast/string/memdup.c b/src/lib/libast/string/memdup.c
new file mode 100644
index 0000000..9282405
--- /dev/null
+++ b/src/lib/libast/string/memdup.c
@@ -0,0 +1,44 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+#if _lib_memdup
+
+NoN(memdup)
+
+#else
+
+/*
+ * return a copy of s of n chars using malloc
+ */
+
+void*
+memdup(register const void* s, register size_t n)
+{
+ register void* t;
+
+ return((t = (void*)newof(0, char, n, 0)) ? memcpy(t, s, n) : 0);
+}
+
+#endif
diff --git a/src/lib/libast/string/modedata.c b/src/lib/libast/string/modedata.c
new file mode 100644
index 0000000..dc10d62
--- /dev/null
+++ b/src/lib/libast/string/modedata.c
@@ -0,0 +1,69 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * fmtmode() and strperm() readonly data
+ * for external format modes
+ */
+
+#include "modelib.h"
+
+struct modeop modetab[MODELEN] =
+{
+ 0170000, 12, 0000000, 0, "-pc?d?b?-Cl?sDw?",
+ 0000400, 8, 0000000, 0, "-r",
+ 0000200, 7, 0000000, 0, "-w",
+ 0004000, 10, 0000100, 6, "-xSs",
+ 0000040, 5, 0000000, 0, "-r",
+ 0000020, 4, 0000000, 0, "-w",
+#ifdef S_ICCTYP
+ 0003000, 8, 0000010, 3, "-x-xSs-x",
+#else
+ 0002000, 9, 0000010, 3, "-xls",
+#endif
+ 0000004, 2, 0000000, 0, "-r",
+ 0000002, 1, 0000000, 0, "-w",
+#ifdef S_ICCTYP
+ 0003000, 8, 0000001, 0, "-xyY-xeE",
+#else
+ 0001000, 8, 0000001, 0, "-xTt",
+#endif
+};
+
+int permmap[PERMLEN] =
+{
+ S_ISUID, X_ISUID,
+ S_ISGID, X_ISGID,
+ S_ISVTX, X_ISVTX,
+ S_IRUSR, X_IRUSR,
+ S_IWUSR, X_IWUSR,
+ S_IXUSR, X_IXUSR,
+ S_IRGRP, X_IRGRP,
+ S_IWGRP, X_IWGRP,
+ S_IXGRP, X_IXGRP,
+ S_IROTH, X_IROTH,
+ S_IWOTH, X_IWOTH,
+ S_IXOTH, X_IXOTH
+};
diff --git a/src/lib/libast/string/modei.c b/src/lib/libast/string/modei.c
new file mode 100644
index 0000000..163d633
--- /dev/null
+++ b/src/lib/libast/string/modei.c
@@ -0,0 +1,55 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * mode_t representation support
+ */
+
+#include "modelib.h"
+
+/*
+ * convert external mode to internal
+ *
+ * NOTE: X_IFMT ignored
+ */
+
+#undef modei
+
+int
+modei(register int x)
+{
+#if _S_IDPERM
+ return(x & X_IPERM);
+#else
+ register int i;
+ register int c;
+
+ i = 0;
+ for (c = 0; c < PERMLEN; c += 2)
+ if (x & permmap[c + 1])
+ i |= permmap[c];
+ return(i);
+#endif
+}
diff --git a/src/lib/libast/string/modelib.h b/src/lib/libast/string/modelib.h
new file mode 100644
index 0000000..e654240
--- /dev/null
+++ b/src/lib/libast/string/modelib.h
@@ -0,0 +1,55 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * mode_t common definitions
+ */
+
+#ifndef _MODELIB_H
+#define _MODELIB_H
+
+#include <ast.h>
+#include <ls.h>
+#include <modex.h>
+
+#define MODELEN 10
+#define PERMLEN 24
+
+#define modetab _mode_table_ /* data hiding */
+#define permmap _mode_permmap_ /* data hiding */
+
+struct modeop /* ops for each char in mode string */
+{
+ int mask1; /* first mask */
+ int shift1; /* first shift count */
+ int mask2; /* second mask */
+ int shift2; /* second shift count */
+ char* name; /* mode char using mask/shift as index */
+};
+
+extern struct modeop modetab[];
+extern int permmap[];
+
+#endif
diff --git a/src/lib/libast/string/modex.c b/src/lib/libast/string/modex.c
new file mode 100644
index 0000000..a5e501a
--- /dev/null
+++ b/src/lib/libast/string/modex.c
@@ -0,0 +1,75 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * mode_t representation support
+ */
+
+#include "modelib.h"
+
+/*
+ * convert internal mode to external
+ */
+
+#undef modex
+
+int
+modex(register int i)
+{
+#if _S_IDPERM && _S_IDTYPE
+ return(i);
+#else
+ register int x;
+ register int c;
+
+ x = 0;
+#if _S_IDPERM
+ x |= (i & 07777);
+#else
+ for (c = 0; c < PERMLEN; c++)
+ if (i & permmap[c++])
+ x |= permmap[c];
+#endif
+#if _S_IDTYPE
+ x |= (i & X_IFMT);
+#else
+ if (S_ISREG(i)) x |= X_IFREG;
+ else if (S_ISDIR(i)) x |= X_IFDIR;
+#ifdef S_ISLNK
+ else if (S_ISLNK(i)) x |= X_IFLNK;
+#endif
+ else if (S_ISBLK(i)) x |= X_IFBLK;
+ else if (S_ISCHR(i)) x |= X_IFCHR;
+#ifdef S_ISCTG
+ else if (S_ISCTG(i)) x |= X_IFCTG;
+#endif
+ else if (S_ISFIFO(i)) x |= X_IFIFO;
+#ifdef S_ISSOCK
+ else if (S_ISSOCK(i)) x |= X_IFSOCK;
+#endif
+#endif
+ return(x);
+#endif
+}
diff --git a/src/lib/libast/string/stracmp.c b/src/lib/libast/string/stracmp.c
new file mode 100644
index 0000000..05b5401
--- /dev/null
+++ b/src/lib/libast/string/stracmp.c
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * ccmapchr(ccmap(CC_NATIVE,CC_ASCII),c) and strcmp
+ */
+
+#include <ast.h>
+#include <ccode.h>
+
+#if _lib_stracmp
+
+NoN(stracmp)
+
+#else
+
+#include <ctype.h>
+
+int
+stracmp(const char* aa, const char* ab)
+{
+ register unsigned char* a;
+ register unsigned char* b;
+ register unsigned char* m;
+ register int c;
+ register int d;
+
+ if (!(m = ccmap(CC_NATIVE, CC_ASCII)))
+ return strcmp(aa, ab);
+ a = (unsigned char*)aa;
+ b = (unsigned char*)ab;
+ for (;;)
+ {
+ c = m[*a++];
+ if (d = c - m[*b++])
+ return d;
+ if (!c)
+ return 0;
+ }
+}
+
+#endif
diff --git a/src/lib/libast/string/strcopy.c b/src/lib/libast/string/strcopy.c
new file mode 100644
index 0000000..de169e7
--- /dev/null
+++ b/src/lib/libast/string/strcopy.c
@@ -0,0 +1,36 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+/*
+ * copy t into s, return a pointer to the end of s ('\0')
+ */
+
+char*
+strcopy(register char* s, register const char* t)
+{
+ if (!t) return(s);
+ while (*s++ = *t++);
+ return(--s);
+}
diff --git a/src/lib/libast/string/strdup.c b/src/lib/libast/string/strdup.c
new file mode 100644
index 0000000..7237fb7
--- /dev/null
+++ b/src/lib/libast/string/strdup.c
@@ -0,0 +1,60 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#undef VMDEBUG
+#define VMDEBUG 0
+
+#if defined(_MSVCRT_H)
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide strdup
+#else
+#define strdup ______strdup
+#endif
+#endif
+
+#include <ast.h>
+
+#if defined(_MSVCRT_H)
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide strdup
+#else
+#undef strdup
+#endif
+#endif
+
+/*
+ * return a copy of s using malloc
+ */
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char*
+strdup(register const char* s)
+{
+ register char* t;
+ register int n;
+
+ return (s && (t = newof(0, char, n = strlen(s) + 1, 0))) ? (char*)memcpy(t, s, n) : (char*)0;
+}
diff --git a/src/lib/libast/string/strelapsed.c b/src/lib/libast/string/strelapsed.c
new file mode 100644
index 0000000..fa7d919
--- /dev/null
+++ b/src/lib/libast/string/strelapsed.c
@@ -0,0 +1,154 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * parse elapsed time in 1/n secs from s
+ * compatible with fmtelapsed()
+ * also handles ps [day-][hour:]min:sec
+ * also handles coshell % for 'infinity'
+ * if e!=0 then it is set to first unrecognized char
+ */
+
+#include <ast.h>
+#include <ctype.h>
+
+unsigned long
+strelapsed(register const char* s, char** e, int n)
+{
+ register int c;
+ register unsigned long v;
+ unsigned long t = 0;
+ int f = 0;
+ int p = 0;
+ int z = 1;
+ int m;
+ const char* last;
+
+ for (;;)
+ {
+ while (isspace(*s) || *s == '_')
+ s++;
+ if (!*(last = s))
+ break;
+ if (z)
+ {
+ z = 0;
+ if (*s == '0' && (!(c = *(s + 1)) || isspace(c) || c == '_'))
+ {
+ last = s + 1;
+ break;
+ }
+ }
+ v = 0;
+ while ((c = *s++) >= '0' && c <= '9')
+ v = v * 10 + c - '0';
+ v *= n;
+ if (c == '.')
+ for (m = n; (c = *s++) >= '0' && c <= '9';)
+ f += (m /= 10) * (c - '0');
+ if (c == '%')
+ {
+ t = ~t;
+ last = s;
+ break;
+ }
+ if (s == last + 1)
+ break;
+ if (!p)
+ while (isspace(c) || c == '_')
+ c = *s++;
+ switch (c)
+ {
+ case 'S':
+ if (*s == 'E' || *s == 'e')
+ {
+ v += f;
+ f = 0;
+ }
+ else
+ v *= 20 * 12 * 4 * 7 * 24 * 60 * 60;
+ break;
+ case 'y':
+ case 'Y':
+ v *= 12 * 4 * 7 * 24 * 60 * 60;
+ break;
+ case 'M':
+ if (*s == 'I' || *s == 'i')
+ v *= 60;
+ else
+ v *= 4 * 7 * 24 * 60 * 60;
+ break;
+ case 'w':
+ v *= 7 * 24 * 60 * 60;
+ break;
+ case '-':
+ p = 1;
+ /*FALLTHROUGH*/
+ case 'd':
+ v *= 24 * 60 * 60;
+ break;
+ case 'h':
+ v *= 60 * 60;
+ break;
+ case ':':
+ p = 1;
+ v *= strchr(s, ':') ? (60 * 60) : 60;
+ break;
+ case 'm':
+ if (*s == 'o')
+ v *= 4 * 7 * 24 * 60 * 60;
+ else
+ v *= 60;
+ break;
+ case 's':
+ if (*s == 'c')
+ {
+ v *= 20 * 12 * 4 * 7 * 24 * 60 * 60;
+ break;
+ }
+ v += f;
+ f = 0;
+ break;
+ case 0:
+ s--;
+ v += f;
+ break;
+ default:
+ if (p)
+ {
+ last = s - 1;
+ t += v + f;
+ }
+ goto done;
+ }
+ t += v;
+ while (isalpha(*s))
+ s++;
+ }
+ done:
+ if (e)
+ *e = (char*)last;
+ return t;
+}
diff --git a/src/lib/libast/string/strerror.c b/src/lib/libast/string/strerror.c
new file mode 100644
index 0000000..1664126
--- /dev/null
+++ b/src/lib/libast/string/strerror.c
@@ -0,0 +1,148 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return error message string given errno
+ */
+
+#include "lclib.h"
+
+#include "FEATURE/errno"
+
+#undef strerror
+
+#if !defined(sys_errlist) && !_def_errno_sys_errlist
+#if _dat_sys_errlist
+extern char* sys_errlist[];
+#else
+#undef _dat_sys_nerr
+char* sys_errlist[] = { 0 };
+#endif
+#endif
+
+#if !defined(sys_nerr) && !_def_errno_sys_nerr
+#if _dat_sys_nerr
+extern int sys_nerr;
+#else
+#undef _dat_sys_nerr
+int sys_nerr = 0;
+#endif
+#endif
+
+#if _lib_strerror
+extern char* strerror(int);
+#endif
+
+#if _PACKAGE_astsa
+
+#define fmtbuf(n) ((n),tmp)
+
+static char tmp[32];
+
+#endif
+
+char*
+_ast_strerror(int err)
+{
+ char* msg;
+ int z;
+
+#if _lib_strerror
+ z = errno;
+ msg = strerror(err);
+ errno = z;
+#else
+ if (err > 0 && err <= sys_nerr)
+ msg = (char*)sys_errlist[err];
+ else
+ msg = 0;
+#endif
+ if (msg)
+ {
+#if !_PACKAGE_astsa
+ if (ERROR_translating())
+ {
+#if _lib_strerror
+ static int sys;
+
+ if (!sys)
+ {
+ char* s;
+ char* t;
+ char* p;
+
+#if _lib_strerror
+ /*
+ * stash the pending strerror() msg
+ */
+
+ msg = strcpy(fmtbuf(strlen(msg) + 1), msg);
+#endif
+
+ /*
+ * make sure that strerror() translates
+ */
+
+ if (!(s = strerror(1)))
+ sys = -1;
+ else
+ {
+ t = fmtbuf(z = strlen(s) + 1);
+ strcpy(t, s);
+ ast.locale.set |= AST_LC_internal;
+ p = setlocale(LC_MESSAGES, NiL);
+ setlocale(LC_MESSAGES, "C");
+ sys = (s = strerror(1)) && strcmp(s, t) ? 1 : -1;
+ setlocale(LC_MESSAGES, p);
+ ast.locale.set &= ~AST_LC_internal;
+ }
+ }
+ if (sys > 0)
+ return msg;
+#endif
+ return ERROR_translate(NiL, NiL, "errlist", msg);
+ }
+#endif
+ return msg;
+ }
+ msg = fmtbuf(z = 32);
+ sfsprintf(msg, z, ERROR_translate(NiL, NiL, "errlist", "Error %d"), err);
+ return msg;
+}
+
+#if !_lib_strerror
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern char*
+strerror(int err)
+{
+ return _ast_strerror(err);
+}
+
+#endif
diff --git a/src/lib/libast/string/stresc.c b/src/lib/libast/string/stresc.c
new file mode 100644
index 0000000..59ec6c9
--- /dev/null
+++ b/src/lib/libast/string/stresc.c
@@ -0,0 +1,67 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * convert \X character constants in s in place
+ * the length of the converted s is returned (may have embedded \0's)
+ * wide chars absent locale guidance default to UTF-8
+ * strexp() FMT_EXP_* flags passed to chrexp() for selective conversion
+ */
+
+#include <ast.h>
+
+int
+strexp(register char* s, int flags)
+{
+ register char* t;
+ register unsigned int c;
+ char* b;
+ char* e;
+ int w;
+
+ b = t = s;
+ while (c = *s++)
+ {
+ if (c == '\\')
+ {
+ c = chrexp(s - 1, &e, &w, flags);
+ s = e;
+ if (w)
+ {
+ t += mbwide() ? mbconv(t, c) : wc2utf8(t, c);
+ continue;
+ }
+ }
+ *t++ = c;
+ }
+ *t = 0;
+ return t - b;
+}
+
+int
+stresc(register char* s)
+{
+ return strexp(s, FMT_EXP_CHAR|FMT_EXP_LINE|FMT_EXP_WIDE);
+}
diff --git a/src/lib/libast/string/streval.c b/src/lib/libast/string/streval.c
new file mode 100644
index 0000000..d246184
--- /dev/null
+++ b/src/lib/libast/string/streval.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * obsolete streval() interface to strexpr()
+ */
+
+#include <ast.h>
+
+typedef long (*Old_convert_t)(const char*, char**);
+
+typedef long (*Convert_t)(const char*, char**, void*);
+
+typedef struct
+{
+ Old_convert_t convert;
+} Handle_t;
+
+static long
+userconv(const char* s, char** end, void* handle)
+{
+ return((*((Handle_t*)handle)->convert)(s, end));
+}
+
+long
+streval(const char* s, char** end, Old_convert_t convert)
+{
+ Handle_t handle;
+
+ return((handle.convert = convert) ? strexpr(s, end, userconv, &handle) : strexpr(s, end, (Convert_t)0, NiL));
+}
diff --git a/src/lib/libast/string/strexpr.c b/src/lib/libast/string/strexpr.c
new file mode 100644
index 0000000..23be2f5
--- /dev/null
+++ b/src/lib/libast/string/strexpr.c
@@ -0,0 +1,294 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * G. S. Fowler
+ * D. G. Korn
+ * AT&T Bell Laboratories
+ *
+ * long integer arithmetic expression evaluator
+ * long constants may be represented as:
+ *
+ * 0ooo octal
+ * 0[xX]hhh hexadecimal
+ * ddd decimal
+ * n#ccc base n, 2 <= b <= 36
+ *
+ * NOTE: all operands are evaluated as both the parse
+ * and evaluation are done on the fly
+ */
+
+#include <ast.h>
+#include <ctype.h>
+
+#define getchr(ex) (*(ex)->nextchr++)
+#define peekchr(ex) (*(ex)->nextchr)
+#define ungetchr(ex) ((ex)->nextchr--)
+
+#define error(ex,msg) return(seterror(ex,msg))
+
+typedef struct /* expression handle */
+{
+ char* nextchr; /* next expression char */
+ char* errchr; /* next char after error */
+ char* errmsg; /* error message text */
+ long (*convert)(const char*, char**, void*);
+ void* handle; /* user convert handle */
+} Expr_t;
+
+/*
+ * set error message string
+ */
+
+static long
+seterror(register Expr_t* ex, char* msg)
+{
+ if (!ex->errmsg) ex->errmsg = msg;
+ ex->errchr = ex->nextchr;
+ ex->nextchr = "";
+ return(0);
+}
+
+/*
+ * evaluate a subexpression with precedence
+ */
+
+static long
+expr(register Expr_t* ex, register int precedence)
+{
+ register int c;
+ register long n;
+ register long x;
+ char* pos;
+ int operand = 1;
+
+ while (c = getchr(ex), isspace(c));
+ switch (c)
+ {
+ case 0:
+ ungetchr(ex);
+ if (!precedence) return(0);
+ error(ex, "more tokens expected");
+ case '-':
+ n = -expr(ex, 13);
+ break;
+ case '+':
+ n = expr(ex, 13);
+ break;
+ case '!':
+ n = !expr(ex, 13);
+ break;
+ case '~':
+ n = ~expr(ex, 13);
+ break;
+ default:
+ ungetchr(ex);
+ n = 0;
+ operand = 0;
+ break;
+ }
+ for (;;)
+ {
+ switch (c = getchr(ex))
+ {
+ case 0:
+ goto done;
+ case ')':
+ if (!precedence) error(ex, "too many )'s");
+ goto done;
+ case '(':
+ n = expr(ex, 1);
+ if (getchr(ex) != ')')
+ {
+ ungetchr(ex);
+ error(ex, "closing ) expected");
+ }
+ gotoperand:
+ if (operand) error(ex, "operator expected");
+ operand = 1;
+ continue;
+ case '?':
+ if (precedence > 1) goto done;
+ if (peekchr(ex) == ':')
+ {
+ getchr(ex);
+ x = expr(ex, 2);
+ if (!n) n = x;
+ }
+ else
+ {
+ x = expr(ex, 2);
+ if (getchr(ex) != ':')
+ {
+ ungetchr(ex);
+ error(ex, ": expected for ? operator");
+ }
+ if (n)
+ {
+ n = x;
+ expr(ex, 2);
+ }
+ else n = expr(ex, 2);
+ }
+ break;
+ case ':':
+ goto done;
+ case '|':
+ if (peekchr(ex) == '|')
+ {
+ if (precedence > 2) goto done;
+ getchr(ex);
+ x = expr(ex, 3);
+ n = n || x;
+ }
+ else
+ {
+ if (precedence > 4) goto done;
+ x = expr(ex, 5);
+ n |= x;
+ }
+ break;
+ case '^':
+ if (precedence > 5) goto done;
+ x = expr(ex, 6);
+ n ^= x;
+ break;
+ case '&':
+ if (peekchr(ex) == '&')
+ {
+ if (precedence > 3) goto done;
+ getchr(ex);
+ x = expr(ex, 4);
+ n = n && x;
+ }
+ else
+ {
+ if (precedence > 6) goto done;
+ x = expr(ex, 7);
+ n &= x;
+ }
+ break;
+ case '=':
+ case '!':
+ if (peekchr(ex) != '=') error(ex, "operator syntax error");
+ if (precedence > 7) goto done;
+ getchr(ex);
+ x = expr(ex, 8);
+ if (c == '=') n = n == x;
+ else n = n != x;
+ break;
+ case '<':
+ case '>':
+ if (peekchr(ex) == c)
+ {
+ if (precedence > 9) goto done;
+ getchr(ex);
+ x = expr(ex, 10);
+ if (c == '<') n <<= x;
+ else n >>= x;
+ }
+ else
+ {
+ if (precedence > 8) goto done;
+ if (peekchr(ex) == '=')
+ {
+ getchr(ex);
+ x = expr(ex, 9);
+ if (c == '<') n = n <= x;
+ else n = n >= x;
+ }
+ else
+ {
+ x = expr(ex, 9);
+ if (c == '<') n = n < x;
+ else n = n > x;
+ }
+ }
+ break;
+ case '+':
+ case '-':
+ if (precedence > 10) goto done;
+ x = expr(ex, 11);
+ if (c == '+') n += x;
+ else n -= x;
+ break;
+ case '*':
+ case '/':
+ case '%':
+ if (precedence > 11) goto done;
+ x = expr(ex, 12);
+ if (c == '*') n *= x;
+ else if (x == 0) error(ex, "divide by zero");
+ else if (c == '/') n /= x;
+ else n %= x;
+ break;
+ default:
+ if (isspace(c)) continue;
+ pos = --ex->nextchr;
+ if (isdigit(c)) n = strton(ex->nextchr, &ex->nextchr, NiL, 0);
+ else if (ex->convert) n = (*ex->convert)(ex->nextchr, &ex->nextchr, ex->handle);
+ if (ex->nextchr == pos) error(ex, "syntax error");
+ goto gotoperand;
+ }
+ if (ex->errmsg) return(0);
+ if (!operand) error(ex, "operand expected");
+ }
+ done:
+ ungetchr(ex);
+ if (!operand) error(ex, "operand expected");
+ return(n);
+}
+
+/*
+ * evaluate an integer arithmetic expression in s
+ *
+ * (long)(*convert)(const char* string, char** end, void* handle)
+ * is a user supplied conversion routine that is called when unknown
+ * chars are encountered; string points to the part to be
+ * converted and end is adjusted to point to the next non-converted
+ * character; if string is 0 then end points to an error message string
+ *
+ * NOTE: (*convert)() may call strexpr(ex, )
+ */
+
+long
+strexpr(const char* s, char** end, long(*convert)(const char*, char**, void*), void* handle)
+{
+ long n;
+ Expr_t ex;
+
+ ex.nextchr = (char*)s;
+ ex.errmsg = 0;
+ ex.convert = convert;
+ ex.handle = handle;
+ n = expr(&ex, 0);
+ if (peekchr(&ex) == ':')
+ seterror(&ex, "invalid use of :");
+ if (ex.errmsg)
+ {
+ if (convert) (*convert)(NiL, &ex.errmsg, handle);
+ ex.nextchr = ex.errchr;
+ n = 0;
+ }
+ if (end) *end = ex.nextchr;
+ return(n);
+}
diff --git a/src/lib/libast/string/strgid.c b/src/lib/libast/string/strgid.c
new file mode 100644
index 0000000..55ebe23
--- /dev/null
+++ b/src/lib/libast/string/strgid.c
@@ -0,0 +1,121 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * gid name -> number
+ */
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide getgrgid getgrnam getpwnam
+#else
+#define getgrgid ______getgrgid
+#define getgrnam ______getgrnam
+#define getpwnam ______getpwnam
+#endif
+
+#include <ast.h>
+#include <cdt.h>
+#include <pwd.h>
+#include <grp.h>
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide getgrgid getgrnam getpwnam
+#else
+#undef getgrgid
+#undef getgrnam
+#undef getpwnam
+#endif
+
+extern struct group* getgrgid(gid_t);
+extern struct group* getgrnam(const char*);
+extern struct passwd* getpwnam(const char*);
+
+typedef struct Id_s
+{
+ Dtlink_t link;
+ int id;
+ char name[1];
+} Id_t;
+
+/*
+ * return gid number given gid/uid name
+ * gid attempted first, then uid->pw_gid
+ * -1 on first error for a given name
+ * -2 on subsequent errors for a given name
+ */
+
+int
+strgid(const char* name)
+{
+ register Id_t* ip;
+ register struct group* gr;
+ register struct passwd* pw;
+ int id;
+ char* e;
+
+ static Dt_t* dict;
+ static Dtdisc_t disc;
+
+ if (!dict)
+ {
+ disc.key = offsetof(Id_t, name);
+ dict = dtopen(&disc, Dtset);
+ }
+ else if (ip = (Id_t*)dtmatch(dict, name))
+ return ip->id;
+ if (gr = getgrnam(name))
+ id = gr->gr_gid;
+ else if (pw = getpwnam(name))
+ id = pw->pw_gid;
+ else
+ {
+ id = strtol(name, &e, 0);
+#if _WINIX
+ if (!*e)
+ {
+ if (!getgrgid(id))
+ id = -1;
+ }
+ else if (!streq(name, "sys"))
+ id = -1;
+ else if (gr = getgrnam("Administrators"))
+ id = gr->gr_gid;
+ else if (pw = getpwnam("Administrator"))
+ id = pw->pw_gid;
+ else
+ id = -1;
+#else
+ if (*e || !getgrgid(id))
+ id = -1;
+#endif
+ }
+ if (dict && (ip = newof(0, Id_t, 1, strlen(name))))
+ {
+ strcpy(ip->name, name);
+ ip->id = id >= 0 ? id : -2;
+ dtinsert(dict, ip);
+ }
+ return id;
+}
diff --git a/src/lib/libast/string/strlcat.c b/src/lib/libast/string/strlcat.c
new file mode 100644
index 0000000..f5f17af
--- /dev/null
+++ b/src/lib/libast/string/strlcat.c
@@ -0,0 +1,83 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * strlcat implementation
+ */
+
+#define strlcat ______strlcat
+
+#include <ast.h>
+
+#undef strlcat
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#if _lib_strlcat
+
+NoN(strlcat)
+
+#else
+
+/*
+ * append t onto s limiting total size of s to n
+ * s 0 terminated if n>0
+ * min(n,strlen(s))+strlen(t) returned
+ */
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern size_t
+strlcat(register char* s, register const char* t, register size_t n)
+{
+ register size_t m;
+ const char* o = t;
+
+ if (m = n)
+ {
+ while (n && *s)
+ {
+ n--;
+ s++;
+ }
+ m -= n;
+ if (n)
+ do
+ {
+ if (!--n)
+ {
+ *s = 0;
+ break;
+ }
+ } while (*s++ = *t++);
+ else
+ *s = 0;
+ }
+ if (!n)
+ while (*t++);
+ return (t - o) + m - 1;
+}
+
+#endif
diff --git a/src/lib/libast/string/strlcpy.c b/src/lib/libast/string/strlcpy.c
new file mode 100644
index 0000000..8410802
--- /dev/null
+++ b/src/lib/libast/string/strlcpy.c
@@ -0,0 +1,71 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * strlcpy implementation
+ */
+
+#define strlcpy ______strlcpy
+
+#include <ast.h>
+
+#undef strlcpy
+
+#undef _def_map_ast
+#include <ast_map.h>
+
+#if _lib_strlcpy
+
+NoN(strlcpy)
+
+#else
+
+/*
+ * copy at most n chars from t into s
+ * result 0 terminated if n>0
+ * strlen(t) returned
+ */
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern size_t
+strlcpy(register char* s, register const char* t, register size_t n)
+{
+ const char* o = t;
+
+ if (n)
+ do
+ {
+ if (!--n)
+ {
+ *s = 0;
+ break;
+ }
+ } while (*s++ = *t++);
+ if (!n)
+ while (*t++);
+ return t - o - 1;
+}
+
+#endif
diff --git a/src/lib/libast/string/strlook.c b/src/lib/libast/string/strlook.c
new file mode 100644
index 0000000..1868697
--- /dev/null
+++ b/src/lib/libast/string/strlook.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include <ast.h>
+
+/*
+ * return pointer to name in tab with element size siz
+ * where the first member of each element is a char*
+ *
+ * the last name in tab must be 0
+ *
+ * 0 returned if name not found
+ */
+
+void*
+strlook(const void* tab, size_t siz, register const char* name)
+{
+ register char* t = (char*)tab;
+ register char* s;
+ register int c = *name;
+
+ for (; s = *((char**)t); t += siz)
+ if (*s == c && !strcmp(s, name))
+ return (void*)t;
+ return 0;
+}
diff --git a/src/lib/libast/string/strmatch.c b/src/lib/libast/string/strmatch.c
new file mode 100644
index 0000000..4114ee4
--- /dev/null
+++ b/src/lib/libast/string/strmatch.c
@@ -0,0 +1,171 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * D. G. Korn
+ * G. S. Fowler
+ * AT&T Research
+ *
+ * match shell file patterns
+ * this interface is a wrapper on regex
+ *
+ * sh pattern egrep RE description
+ * ---------- -------- -----------
+ * * .* 0 or more chars
+ * ? . any single char
+ * [.] [.] char class
+ * [!.] [^.] negated char class
+ * [[:.:]] [[:.:]] ctype class
+ * [[=.=]] [[=.=]] equivalence class
+ * [[...]] [[...]] collation element
+ * *(.) (.)* 0 or more of
+ * +(.) (.)+ 1 or more of
+ * ?(.) (.)? 0 or 1 of
+ * (.) (.) 1 of
+ * @(.) (.) 1 of
+ * a|b a|b a or b
+ * \# () subgroup back reference [1-9]
+ * a&b a and b
+ * !(.) none of
+ *
+ * \ used to escape metacharacters
+ *
+ * *, ?, (, |, &, ), [, \ must be \'d outside of [...]
+ * only ] must be \'d inside [...]
+ *
+ */
+
+#include <ast.h>
+#include <regex.h>
+
+static struct State_s
+{
+ regmatch_t* match;
+ int nmatch;
+} matchstate;
+
+/*
+ * subgroup match
+ * 0 returned if no match
+ * otherwise number of subgroups matched returned
+ * match group begin offsets are even elements of sub
+ * match group end offsets are odd elements of sub
+ * the matched string is from s+sub[0] up to but not
+ * including s+sub[1]
+ */
+
+int
+strgrpmatch(const char* b, const char* p, int* sub, int n, register int flags)
+{
+ register regex_t* re;
+ register int* end;
+ register int i;
+ register regflags_t reflags;
+
+ /*
+ * 0 and empty patterns are special
+ */
+
+ if (!p || !b)
+ {
+ if (!p && !b)
+ regcache(NiL, 0, NiL);
+ return 0;
+ }
+ if (!*p)
+ {
+ if (sub && n > 0)
+ sub[0] = sub[1] = 0;
+ return *b == 0;
+ }
+
+ /*
+ * convert flags
+ */
+
+ if (flags & REG_ADVANCE)
+ reflags = flags & ~REG_ADVANCE;
+ else
+ {
+ reflags = REG_SHELL|REG_AUGMENTED;
+ if (!(flags & STR_MAXIMAL))
+ reflags |= REG_MINIMAL;
+ if (flags & STR_GROUP)
+ reflags |= REG_SHELL_GROUP;
+ if (flags & STR_LEFT)
+ reflags |= REG_LEFT;
+ if (flags & STR_RIGHT)
+ reflags |= REG_RIGHT;
+ if (flags & STR_ICASE)
+ reflags |= REG_ICASE;
+ }
+ if (!sub || n <= 0)
+ reflags |= REG_NOSUB;
+ if (!(re = regcache(p, reflags, NiL)))
+ return 0;
+ if (n > matchstate.nmatch)
+ {
+ if (!(matchstate.match = newof(matchstate.match, regmatch_t, n, 0)))
+ return 0;
+ matchstate.nmatch = n;
+ }
+ if (regexec(re, b, n, matchstate.match, reflags & ~(REG_MINIMAL|REG_SHELL_GROUP|REG_LEFT|REG_RIGHT|REG_ICASE)))
+ return 0;
+ if (!sub || n <= 0)
+ return 1;
+ i = re->re_nsub;
+ end = sub + n * 2;
+ for (n = 0; sub < end && n <= i; n++)
+ {
+ *sub++ = matchstate.match[n].rm_so;
+ *sub++ = matchstate.match[n].rm_eo;
+ }
+ return i + 1;
+}
+
+/*
+ * compare the string s with the shell pattern p
+ * returns 1 for match 0 otherwise
+ */
+
+int
+strmatch(const char* s, const char* p)
+{
+ return strgrpmatch(s, p, NiL, 0, STR_MAXIMAL|STR_LEFT|STR_RIGHT);
+}
+
+/*
+ * leading substring match
+ * first char after end of substring returned
+ * 0 returned if no match
+ *
+ * OBSOLETE: use strgrpmatch()
+ */
+
+char*
+strsubmatch(const char* s, const char* p, int flags)
+{
+ int match[2];
+
+ return strgrpmatch(s, p, match, 1, (flags ? STR_MAXIMAL : 0)|STR_LEFT) ? (char*)s + match[1] : (char*)0;
+}
diff --git a/src/lib/libast/string/strmode.c b/src/lib/libast/string/strmode.c
new file mode 100644
index 0000000..8ec8749
--- /dev/null
+++ b/src/lib/libast/string/strmode.c
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * G. S. Fowler
+ * AT&T Bell Laboratories
+ *
+ * return modex canonical representation of file mode bits
+ * given ls -l style file mode string
+ */
+
+#include "modelib.h"
+
+int
+strmode(register const char* s)
+{
+ register int c;
+ register char* t;
+ register struct modeop* p;
+ int mode;
+
+ mode = 0;
+ for (p = modetab; (c = *s++) && p < &modetab[MODELEN]; p++)
+ for (t = p->name; *t; t++)
+ if (*t == c)
+ {
+ c = t - p->name;
+ mode |= (p->mask1 & (c << p->shift1)) | (p->mask2 & (c << p->shift2));
+ break;
+ }
+ return(mode);
+}
diff --git a/src/lib/libast/string/strnacmp.c b/src/lib/libast/string/strnacmp.c
new file mode 100644
index 0000000..4a6c9c6
--- /dev/null
+++ b/src/lib/libast/string/strnacmp.c
@@ -0,0 +1,66 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * ccmapc(c, CC_NATIVE, CC_ASCII) and strncmp
+ */
+
+#include <ast.h>
+#include <ccode.h>
+
+#if _lib_strnacmp
+
+NoN(strnacmp)
+
+#else
+
+#include <ctype.h>
+
+int
+strnacmp(const char* a, const char* b, size_t n)
+{
+#if CC_NATIVE == CC_ASCII
+ return strncmp(a, b, n);
+#else
+ register unsigned char* ua = (unsigned char*)a;
+ register unsigned char* ub = (unsigned char*)b;
+ register unsigned char* ue;
+ register unsigned char* m;
+ register int c;
+ register int d;
+
+ m = ccmap(CC_NATIVE, CC_ASCII);
+ ue = ua + n;
+ while (ua < ue)
+ {
+ c = m[*ua++];
+ if (d = c - m[*ub++])
+ return d;
+ if (!c)
+ return 0;
+ }
+ return 0;
+#endif
+}
+
+#endif
diff --git a/src/lib/libast/string/strncopy.c b/src/lib/libast/string/strncopy.c
new file mode 100644
index 0000000..65752ac
--- /dev/null
+++ b/src/lib/libast/string/strncopy.c
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+/*
+ * copy up to n bytes of string f into t
+ * trailing 0 always added to t, even if n==0
+ * pointer to the copied 0 returned
+ */
+
+char*
+strncopy(register char* t, register const char* f, size_t n)
+{
+ register char* e = t + n - 1;
+
+ do
+ {
+ if (t >= e)
+ {
+ *t = 0;
+ return t;
+ }
+ } while (*t++ = *f++);
+ return t - 1;
+}
diff --git a/src/lib/libast/string/strnpcmp.c b/src/lib/libast/string/strnpcmp.c
new file mode 100644
index 0000000..e8a4172
--- /dev/null
+++ b/src/lib/libast/string/strnpcmp.c
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+/*
+ * path prefix strncmp(3) -- longest first!
+ */
+
+int
+strnpcmp(register const char* a, register const char* b, size_t n)
+{
+ register const char* e;
+
+ e = a + n;
+ for (;;)
+ {
+ if (a >= e)
+ return 0;
+ if (*a != *b)
+ break;
+ if (!*a++)
+ return 0;
+ b++;
+ }
+ if (*a == 0 && *b == '/')
+ return 1;
+ if (*a == '/' && *b == 0)
+ return -1;
+ return (a < b) ? -1 : 1;
+}
diff --git a/src/lib/libast/string/strntod.c b/src/lib/libast/string/strntod.c
new file mode 100644
index 0000000..e04969b
--- /dev/null
+++ b/src/lib/libast/string/strntod.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strntod() implementation
+ */
+
+#include <ast.h>
+
+#define S2F_function strntod
+#define S2F_type 1
+#define S2F_size 1
+
+#include "sfstrtof.h"
diff --git a/src/lib/libast/string/strntol.c b/src/lib/libast/string/strntol.c
new file mode 100644
index 0000000..e71de8e
--- /dev/null
+++ b/src/lib/libast/string/strntol.c
@@ -0,0 +1,31 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strntol() implementation
+ */
+
+#define S2I_function strntol
+#define S2I_number long
+#define S2I_unumber unsigned long
+#define S2I_size 1
+
+#include "strtoi.h"
diff --git a/src/lib/libast/string/strntold.c b/src/lib/libast/string/strntold.c
new file mode 100644
index 0000000..1b791e2
--- /dev/null
+++ b/src/lib/libast/string/strntold.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strntold() implementation
+ */
+
+#include <ast.h>
+
+#define S2F_function strntold
+#define S2F_type 2
+#define S2F_size 1
+
+#include "sfstrtof.h"
diff --git a/src/lib/libast/string/strntoll.c b/src/lib/libast/string/strntoll.c
new file mode 100644
index 0000000..7eb4772
--- /dev/null
+++ b/src/lib/libast/string/strntoll.c
@@ -0,0 +1,31 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strntoll() implementation
+ */
+
+#define S2I_function strntoll
+#define S2I_number intmax_t
+#define S2I_unumber uintmax_t
+#define S2I_size 1
+
+#include "strtoi.h"
diff --git a/src/lib/libast/string/strnton.c b/src/lib/libast/string/strnton.c
new file mode 100644
index 0000000..5d6e1bf
--- /dev/null
+++ b/src/lib/libast/string/strnton.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strnton() implementation
+ */
+
+#define S2I_function strnton
+#define S2I_number long
+#define S2I_unumber unsigned long
+#define S2I_multiplier 1
+#define S2I_size 1
+
+#include "strtoi.h"
diff --git a/src/lib/libast/string/strntonll.c b/src/lib/libast/string/strntonll.c
new file mode 100644
index 0000000..d55b335
--- /dev/null
+++ b/src/lib/libast/string/strntonll.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strntonll() implementation
+ */
+
+#define S2I_function strntonll
+#define S2I_number intmax_t
+#define S2I_unumber uintmax_t
+#define S2I_multiplier 1
+#define S2I_size 1
+
+#include "strtoi.h"
diff --git a/src/lib/libast/string/strntoul.c b/src/lib/libast/string/strntoul.c
new file mode 100644
index 0000000..f688985
--- /dev/null
+++ b/src/lib/libast/string/strntoul.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strntoul() implementation
+ */
+
+#define S2I_function strntoul
+#define S2I_number long
+#define S2I_unumber unsigned long
+#define S2I_size 1
+#define S2I_unsigned 1
+
+#include "strtoi.h"
diff --git a/src/lib/libast/string/strntoull.c b/src/lib/libast/string/strntoull.c
new file mode 100644
index 0000000..9eae4f1
--- /dev/null
+++ b/src/lib/libast/string/strntoull.c
@@ -0,0 +1,32 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strntoull() implementation
+ */
+
+#define S2I_function strntoull
+#define S2I_number intmax_t
+#define S2I_unumber uintmax_t
+#define S2I_size 1
+#define S2I_unsigned 1
+
+#include "strtoi.h"
diff --git a/src/lib/libast/string/strnvcmp.c b/src/lib/libast/string/strnvcmp.c
new file mode 100644
index 0000000..41d2414
--- /dev/null
+++ b/src/lib/libast/string/strnvcmp.c
@@ -0,0 +1,86 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <ctype.h>
+
+/*
+ * version strncmp(3)
+ */
+
+int
+strnvcmp(register const char* a, register const char* b, size_t n)
+{
+ register const char* ae;
+ register const char* be;
+ register unsigned long na;
+ register unsigned long nb;
+
+ ae = a + n;
+ be = b + n;
+ for (;;)
+ {
+ if (a >= ae)
+ {
+ if (b >= be)
+ return 0;
+ return 1;
+ }
+ else if (b >= be)
+ return -1;
+ if (isdigit(*a) && isdigit(*b))
+ {
+ na = nb = 0;
+ while (a < ae && isdigit(*a))
+ na = na * 10 + *a++ - '0';
+ while (b < be && isdigit(*b))
+ nb = nb * 10 + *b++ - '0';
+ if (na < nb)
+ return -1;
+ if (na > nb)
+ return 1;
+ }
+ else if (*a != *b)
+ break;
+ else if (!*a)
+ return 0;
+ else
+ {
+ a++;
+ b++;
+ }
+ }
+ if (*a == 0)
+ return -1;
+ if (*b == 0)
+ return 1;
+ if (*a == '.')
+ return -1;
+ if (*b == '.')
+ return 1;
+ if (*a == '-')
+ return -1;
+ if (*b == '-')
+ return 1;
+ return *a < *b ? -1 : 1;
+}
diff --git a/src/lib/libast/string/stropt.c b/src/lib/libast/string/stropt.c
new file mode 100644
index 0000000..91bd351
--- /dev/null
+++ b/src/lib/libast/string/stropt.c
@@ -0,0 +1,188 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include <ast.h>
+#include <ctype.h>
+
+/*
+ * parse option expression in s using options in tab with element size siz
+ * first element in tab must be a char*
+ * options match
+ *
+ * [no]name[[:]=['"]value["']][, ]...
+ *
+ * f is called for each option
+ *
+ * (*f)(void* a, char* p, int n, char* v)
+ *
+ * a from stropt
+ * p matching tab entry, or name if no table
+ * n 0 if option had ``no'' prefix, -1 if :=, 1 otherwise
+ * v option value pointer
+ *
+ * for unmatched options p is 0 and v is the offending option
+ *
+ * names in s may be shorter than tab names
+ * longer names must have a prefix that matches a tab name
+ * the first match is returned
+ * \ escapes value using chresc()
+ */
+
+int
+stropt(const char* as, const void* tab, int siz, int(*f)(void*, const void*, int, const char*), void* a)
+{
+ register int c;
+ register char* s;
+ register char* v;
+ register char* t;
+ char** p;
+ char* u;
+ char* x;
+ char* e;
+ int n;
+ int ql;
+ int qr;
+ int qc;
+
+ if (!as) n = 0;
+ else if (!(x = s = strdup(as))) n = -1;
+ else
+ {
+ for (;;)
+ {
+ while (isspace(*s) || *s == ',') s++;
+ if (*s == 'n' && *(s + 1) == 'o')
+ {
+ s += 2;
+ n = 0;
+ }
+ else n = 1;
+ if (!*s)
+ {
+ n = 0;
+ break;
+ }
+ if (tab)
+ {
+ for (p = (char**)tab; t = *p; p = (char**)((char*)p + siz))
+ {
+ for (v = s; *t && *t++ == *v; v++);
+ if (!*t || isspace(*v) || *v == ',' || *v == '=')
+ break;
+ if (*v == ':' && *(v + 1) == '=')
+ {
+ v++;
+ n = -1;
+ break;
+ }
+ }
+ if (!t)
+ {
+ u = v = s;
+ p = 0;
+ }
+ }
+ else
+ {
+ p = (char**)(v = s);
+ t = 0;
+ }
+ while (*v && !isspace(*v) && *v != '=' && *v != ',')
+ if (*v++ == ':' && *v == '=')
+ {
+ if (!t)
+ *(v - 1) = 0;
+ n = -n;
+ break;
+ }
+ if (*v == '=')
+ {
+ if (!t)
+ *v = 0;
+ t = s = ++v;
+ ql = qr = 0;
+ while (c = *s++)
+ {
+ if (c == '\\')
+ {
+ *t++ = chresc(s - 1, &e);
+ s = e;
+ }
+ else if (c == qr)
+ {
+ if (qr != ql)
+ *t++ = c;
+ if (--qc <= 0)
+ qr = ql = 0;
+ }
+ else if (c == ql)
+ {
+ *t++ = c;
+ qc++;
+ }
+ else if (qr)
+ *t++ = c;
+ else if (c == ',' || isspace(c))
+ break;
+ else if (c == '"' || c == '\'')
+ {
+ ql = qr = c;
+ qc = 1;
+ }
+ else
+ {
+ *t++ = c;
+ if (c == '{')
+ {
+ ql = c;
+ qr = '}';
+ qc = 1;
+ }
+ else if (c == '(')
+ {
+ ql = c;
+ qr = ')';
+ qc = 1;
+ }
+ }
+ }
+ *t = 0;
+ }
+ else
+ {
+ s = v;
+ c = *s;
+ *s++ = 0;
+ }
+ n = p ? (*f)(a, p, n, v) : (*f)(a, p, v - u, u);
+ if (n || !c)
+ break;
+ }
+ free(x);
+ }
+ return n;
+}
diff --git a/src/lib/libast/string/strpcmp.c b/src/lib/libast/string/strpcmp.c
new file mode 100644
index 0000000..2c83d71
--- /dev/null
+++ b/src/lib/libast/string/strpcmp.c
@@ -0,0 +1,44 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+
+/*
+ * path prefix strcmp(3) -- longest first!
+ */
+
+int
+strpcmp(register const char* a, register const char* b)
+{
+ while (*a == *b)
+ {
+ if (!*a++)
+ return 0;
+ b++;
+ }
+ if (*a == 0 && *b == '/')
+ return 1;
+ if (*a == '/' && *b == 0)
+ return -1;
+ return (a < b) ? -1 : 1;
+}
diff --git a/src/lib/libast/string/strperm.c b/src/lib/libast/string/strperm.c
new file mode 100644
index 0000000..455d232
--- /dev/null
+++ b/src/lib/libast/string/strperm.c
@@ -0,0 +1,267 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * apply file permission expression expr to perm
+ *
+ * each expression term must match
+ *
+ * [ugoa]*[-&+|^=]?[rwxst0-7]*
+ *
+ * terms may be combined using ,
+ *
+ * if non-null, e points to the first unrecognized char in expr
+ */
+
+#include <ast.h>
+#include <ls.h>
+#include <modex.h>
+
+int
+strperm(const char* aexpr, char** e, register int perm)
+{
+ register char* expr = (char*)aexpr;
+ register int c;
+ register int typ;
+ register int who;
+ int num;
+ int op;
+ int mask;
+ int masked;
+
+ if (perm == -1)
+ {
+ perm = 0;
+ masked = 1;
+ mask = ~0;
+ }
+ else
+ masked = 0;
+ for (;;)
+ {
+ op = num = who = typ = 0;
+ for (;;)
+ {
+ switch (c = *expr++)
+ {
+ case 'u':
+ who |= S_ISVTX|S_ISUID|S_IRWXU;
+ continue;
+ case 'g':
+ who |= S_ISVTX|S_ISGID|S_IRWXG;
+ continue;
+ case 'o':
+ who |= S_ISVTX|S_IRWXO;
+ continue;
+ case 'a':
+ who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
+ continue;
+ default:
+ if (c >= '0' && c <= '7')
+ {
+ if (!who)
+ who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
+ c = '=';
+ }
+ expr--;
+ /*FALLTHROUGH*/
+ case '=':
+ if (who)
+ perm &= ~who;
+ else
+ perm = 0;
+ /*FALLTHROUGH*/
+ case '+':
+ case '|':
+ case '-':
+ case '&':
+ case '^':
+ op = c;
+ for (;;)
+ {
+ switch (c = *expr++)
+ {
+ case 'r':
+ typ |= S_IRUSR|S_IRGRP|S_IROTH;
+ continue;
+ case 'w':
+ typ |= S_IWUSR|S_IWGRP|S_IWOTH;
+ continue;
+ case 'X':
+ if (!S_ISDIR(perm) && !(perm & (S_IXUSR|S_IXGRP|S_IXOTH)))
+ continue;
+ /*FALLTHROUGH*/
+ case 'x':
+ typ |= S_IXUSR|S_IXGRP|S_IXOTH;
+ continue;
+ case 's':
+ typ |= S_ISUID|S_ISGID;
+ continue;
+ case 't':
+ typ |= S_ISVTX;
+ continue;
+ case 'l':
+ if (perm & S_IXGRP)
+ {
+ if (e)
+ *e = expr - 1;
+ return perm & S_IPERM;
+ }
+ typ |= S_ISGID;
+ continue;
+ case '=':
+ case '+':
+ case '|':
+ case '-':
+ case '&':
+ case '^':
+ case ',':
+ case 0:
+ if (who)
+ typ &= who;
+ else
+ switch (op)
+ {
+ case '=':
+ case '+':
+ case '|':
+ case '-':
+ case '&':
+ if (!masked)
+ {
+ masked = 1;
+ umask(mask = umask(0));
+ mask = ~mask;
+ }
+ typ &= mask;
+ break;
+ }
+ switch (op)
+ {
+ default:
+ if (who)
+ perm &= ~who;
+ else
+ perm = 0;
+ /*FALLTHROUGH*/
+ case '+':
+ case '|':
+ perm |= typ;
+ typ = 0;
+ break;
+ case '-':
+ perm &= ~typ;
+ typ = 0;
+ break;
+ case '&':
+ perm &= typ;
+ typ = 0;
+ break;
+ case '^':
+ if (typ &= perm)
+ {
+ /*
+ * propagate least restrictive to most restrictive
+ */
+
+ if (typ & S_IXOTH)
+ perm |= who & (S_IXUSR|S_IXGRP);
+ if (typ & S_IWOTH)
+ perm |= who & (S_IWUSR|S_IWGRP);
+ if (typ & S_IROTH)
+ perm |= who & (S_IRUSR|S_IRGRP);
+ if (typ & S_IXGRP)
+ perm |= who & S_IXUSR;
+ if (typ & S_IWGRP)
+ perm |= who & S_IWUSR;
+ if (typ & S_IRGRP)
+ perm |= who & S_IRUSR;
+
+ /*
+ * if any execute then read => execute
+ */
+
+ if ((typ |= perm) & (S_IXUSR|S_IXGRP|S_IXOTH))
+ {
+ if (typ & S_IRUSR)
+ perm |= who & S_IXUSR;
+ if (typ & S_IRGRP)
+ perm |= who & S_IXGRP;
+ if (typ & S_IROTH)
+ perm |= who & S_IXOTH;
+ }
+ typ = 0;
+ }
+ break;
+ }
+ switch (c)
+ {
+ case '=':
+ case '+':
+ case '|':
+ case '-':
+ case '&':
+ case '^':
+ op = c;
+ typ = 0;
+ continue;
+ }
+ if (c)
+ break;
+ /*FALLTHROUGH*/
+ default:
+ if (c < '0' || c > '7')
+ {
+ if (e)
+ *e = expr - 1;
+ if (typ)
+ {
+ if (who)
+ {
+ typ &= who;
+ perm &= ~who;
+ }
+ perm |= typ;
+ }
+ return perm & S_IPERM;
+ }
+ num = (num << 3) | (c - '0');
+ if (!who && (op == '+' || op == '-'))
+ who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
+ if (*expr < '0' || *expr > '7')
+ {
+ typ |= modei(num);
+ num = 0;
+ }
+ continue;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ }
+ }
+}
diff --git a/src/lib/libast/string/strpsearch.c b/src/lib/libast/string/strpsearch.c
new file mode 100644
index 0000000..69637d5
--- /dev/null
+++ b/src/lib/libast/string/strpsearch.c
@@ -0,0 +1,125 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include <ast.h>
+#include <ccode.h>
+#include <ctype.h>
+
+#if CC_NATIVE == CC_ASCII
+#define MAP(m,c) (c)
+#else
+#define MAP(m,c) m[c]
+#endif
+
+/*
+ * return a pointer to the isalpha() identifier matching
+ * name in the CC_ASCII sorted tab of num elements of
+ * size siz where the first member of each
+ * element is a char*
+ *
+ * [xxx] brackets optional identifier characters
+ * * starts optional identifier characters
+ *
+ * 0 returned if name not found
+ * otherwise if next!=0 then it points to the next
+ * unmatched char in name
+ */
+
+void*
+strpsearch(const void* tab, size_t num, size_t siz, const char* name, char** next)
+{
+ register char* lo = (char*)tab;
+ register char* hi = lo + (num - 1) * siz;
+ register char* mid;
+#if CC_NATIVE != CC_ASCII
+ register unsigned char* m;
+#endif
+ register unsigned char* s;
+ register unsigned char* t;
+ register int c;
+ register int v;
+ int sequential = 0;
+
+#if CC_NATIVE != CC_ASCII
+ m = ccmap(CC_NATIVE, CC_ASCII);
+#endif
+ c = MAP(m, *((unsigned char*)name));
+ while (lo <= hi)
+ {
+ mid = lo + (sequential ? 0 : (((hi - lo) / siz) / 2) * siz);
+ if (!(v = c - MAP(m, *(s = *((unsigned char**)mid)))) || *s == '[' && !(v = c - MAP(m, *++s)) && (v = 1))
+ {
+ t = (unsigned char*)name;
+ for (;;)
+ {
+ if (!v && (*s == '[' || *s == '*'))
+ {
+ v = 1;
+ s++;
+ }
+ else if (v && *s == ']')
+ {
+ v = 0;
+ s++;
+ }
+ else if (!isalpha(*t))
+ {
+ if (v || !*s)
+ {
+ if (next)
+ *next = (char*)t;
+ return (void*)mid;
+ }
+ if (!sequential)
+ {
+ while ((mid -= siz) >= lo && (s = *((unsigned char**)mid)) && ((c == MAP(m, *s)) || *s == '[' && c == MAP(m, *(s + 1))));
+ sequential = 1;
+ }
+ v = 1;
+ break;
+ }
+ else if (*t != *s)
+ {
+ v = MAP(m, *t) - MAP(m, *s);
+ break;
+ }
+ else
+ {
+ t++;
+ s++;
+ }
+ }
+ }
+ else if (sequential)
+ break;
+ if (v > 0)
+ lo = mid + siz;
+ else
+ hi = mid - siz;
+ }
+ return 0;
+}
diff --git a/src/lib/libast/string/strsearch.c b/src/lib/libast/string/strsearch.c
new file mode 100644
index 0000000..56d78fc
--- /dev/null
+++ b/src/lib/libast/string/strsearch.c
@@ -0,0 +1,57 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include <ast.h>
+
+/*
+ * return a pointer to the element matching
+ * name in the (*comparf*)() sorted tab of num elements of
+ * size siz where the first member of each
+ * element is a char*
+ *
+ * 0 returned if name not found
+ */
+
+void*
+strsearch(const void* tab, size_t num, size_t siz, Strcmp_f comparf, const char* name, void* context)
+{
+ register char* lo = (char*)tab;
+ register char* hi = lo + (num - 1) * siz;
+ register char* mid;
+ register int v;
+
+ while (lo <= hi)
+ {
+ mid = lo + (((hi - lo) / siz) / 2) * siz;
+ if (!(v = context ? (*(Strcmp_context_f)comparf)(name, *((char**)mid), context) : (*comparf)(name, *((char**)mid))))
+ return (void*)mid;
+ else if (v > 0)
+ lo = mid + siz;
+ else hi = mid - siz;
+ }
+ return 0;
+}
diff --git a/src/lib/libast/string/strsort.c b/src/lib/libast/string/strsort.c
new file mode 100644
index 0000000..e7ab49a
--- /dev/null
+++ b/src/lib/libast/string/strsort.c
@@ -0,0 +1,57 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * strsort - sort an array pointers using fn
+ *
+ * fn follows strcmp(3) conventions
+ *
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * derived from Bourne Shell
+ */
+
+#include <ast.h>
+
+void
+strsort(char** argv, int n, int(*fn)(const char*, const char*))
+{
+ register int i;
+ register int j;
+ register int m;
+ register char** ap;
+ char* s;
+ int k;
+
+ for (j = 1; j <= n; j *= 2);
+ for (m = 2 * j - 1; m /= 2;)
+ for (j = 0, k = n - m; j < k; j++)
+ for (i = j; i >= 0; i -= m)
+ {
+ ap = &argv[i];
+ if ((*fn)(ap[m], ap[0]) >= 0) break;
+ s = ap[m];
+ ap[m] = ap[0];
+ ap[0] = s;
+ }
+}
diff --git a/src/lib/libast/string/strtape.c b/src/lib/libast/string/strtape.c
new file mode 100644
index 0000000..e31f227
--- /dev/null
+++ b/src/lib/libast/string/strtape.c
@@ -0,0 +1,148 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * local device pathname for portable tape unit specification is returned
+ * if e is non-null then it is set to the next unused char in s
+ *
+ * <unit><density>[<no-rewind>]
+ * {0-7}[l,m,h,u,c][n]
+ */
+
+#include <ast.h>
+
+char*
+strtape(register const char* s, register char** e)
+{
+ int mtunit = '0';
+ int mtdensity = 0;
+ char mtrewind[2];
+ char mtbehavior[2];
+
+ static char tapefile[sizeof("/dev/Xrmt/123456789")];
+
+ mtrewind[0] = mtrewind[1] = mtbehavior[0] = mtbehavior[1] = 0;
+ for (;;)
+ {
+ switch (*s)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ mtunit = *s++;
+ continue;
+ case 'b':
+ case 'v':
+ mtbehavior[0] = *s++;
+ continue;
+ case 'l':
+ case 'm':
+ case 'h':
+ case 'u':
+ case 'c':
+ mtdensity = *s++;
+ continue;
+ case 'n':
+ mtrewind[0] = *s++;
+ continue;
+ }
+ break;
+ }
+ if (e) *e = (char*)s;
+ if (!access("/dev/rmt/.", F_OK))
+ {
+ /*
+ * system V
+ */
+
+ if (!mtdensity) mtdensity = 'm';
+ sfsprintf(tapefile, sizeof(tapefile), "/dev/rmt/ctape%c%s", mtunit, mtrewind);
+ if (!access(tapefile, F_OK)) return(tapefile);
+ for (;;)
+ {
+ sfsprintf(tapefile, sizeof(tapefile), "/dev/rmt/%c%c%s%s", mtunit, mtdensity, mtbehavior, mtrewind);
+ if (!access(tapefile, F_OK)) return(tapefile);
+ if (!mtbehavior[0]) break;
+ mtbehavior[0] = 0;
+ }
+ }
+ else if (!access("/dev/nst0", F_OK))
+ {
+ /*
+ * linux
+ */
+
+ sfsprintf(tapefile, sizeof(tapefile), "/dev/%sst%c", mtrewind, mtunit);
+ }
+ else if (!access("/dev/nrmt0", F_OK))
+ {
+ /*
+ * 9th edition
+ */
+
+ switch (mtdensity)
+ {
+ case 'l':
+ mtunit = '0';
+ break;
+ case 'm':
+ mtunit = '1';
+ break;
+ case 'h':
+ mtunit = '2';
+ break;
+ }
+ sfsprintf(tapefile, sizeof(tapefile), "/dev/%srmt%c", mtrewind, mtunit);
+ }
+ else
+ {
+ /*
+ * BSD
+ */
+
+ mtunit -= '0';
+ switch (mtdensity)
+ {
+ case 'l':
+ break;
+ case 'h':
+ mtunit |= 020;
+ break;
+ default:
+ mtunit |= 010;
+ break;
+ }
+ switch (mtrewind[0])
+ {
+ case 'n':
+ mtunit |= 040;
+ break;
+ }
+ sfsprintf(tapefile, sizeof(tapefile), "/dev/rmt%d", mtunit);
+ }
+ return(tapefile);
+}
diff --git a/src/lib/libast/string/strtoi.h b/src/lib/libast/string/strtoi.h
new file mode 100644
index 0000000..b1155a5
--- /dev/null
+++ b/src/lib/libast/string/strtoi.h
@@ -0,0 +1,640 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * AT&T Research
+ * Glenn Fowler
+ * Phong Vo
+ *
+ * common header and implementation for
+ *
+ * strtol strtoul strton
+ * strtoll strtoull strtonll
+ * strntol strntoul strnton
+ * strntoll strntoull strntonll
+ *
+ * define these macros to instantiate an implementation:
+ *
+ * S2I_function the function name
+ * S2I_number the signed number type
+ * S2I_unumber the unsigned number type
+ * S2I_unsigned 1 for unsigned, 0 for signed
+ * S2I_qualifier 1 for optional qualifier suffix, 0 otherwise
+ * S2I_multiplier 1 for optional multiplier suffix, 0 otherwise
+ * S2I_size the second argument is the input string size
+ *
+ * convert string to number
+ * errno=ERANGE on overflow (LONG_MAX) or underflow (LONG_MIN)
+ * if non-null e will point to first unrecognized char in s
+ * if basep!=0 it points to the default base on input and
+ * will point to the explicit base on return
+ * a default base of 0 will determine the base from the input
+ * a default base of 1 will determine the base from the input using bb#*
+ * a base prefix in the string overrides *b
+ * *b will not be set if the string has no base prefix
+ * if m>1 and no multipler was specified then the result is multiplied by m
+ * if m<0 then multipliers are not consumed
+ * if a base arg or prefix is specified then multiplier is not consumed
+ *
+ * integer numbers are of the form:
+ *
+ * [sign][base][number[qualifier]][multiplier]
+ *
+ * base: nnn# base nnn
+ * 0[xX] hex
+ * 0 octal
+ * [1-9] decimal
+ *
+ * number: [0-9a-zA-Z]*
+ *
+ * qualifier: [lL]
+ * [uU]
+ * [uU][lL]
+ * [lL][uU]
+ * [lL][lL][uU]
+ * [uU][lL][lL]
+ *
+ * multiplier: . pseudo-float if m>1
+ * [bB] block (512)
+ * [cC] char (1)
+ * [gG] giga (1000*1000*1000)
+ * [gG]i gibi (1024*1024*1024)
+ * [kK] kilo (1000)
+ * [kK]i kibi (1024)
+ * [mM] mega (1000*1000)
+ * [mM]i mibi (1024*1024)
+ */
+
+#include <ast.h>
+#include <ctype.h>
+
+#include "sfhdr.h"
+
+#if !__STD_C && !defined(const)
+#define const
+#endif
+
+#ifndef ERANGE
+#define ERANGE EINVAL
+#endif
+
+#define QL 01
+#define QU 02
+
+#define S2I_umax (~((S2I_unumber)0))
+
+#if S2I_unsigned
+#define S2I_type S2I_unumber
+#define S2I_min 0
+#define S2I_max S2I_umax
+#else
+#define S2I_type S2I_number
+#define S2I_min (-S2I_max-1)
+#define S2I_max (S2I_umax>>1)
+#endif
+
+#if S2I_size
+#define S2I_valid(s) ((s)<(z))
+#else
+#define S2I_valid(s) 1
+#endif
+
+#define ADDOVER(n,c,s) ((S2I_umax-(n))<((S2I_unumber)((c)+(s))))
+#define MPYOVER(n,c) (((S2I_unumber)(n))>(S2I_umax/(c)))
+
+static const S2I_unumber mm[] =
+{
+ 0,
+ S2I_umax / 1,
+ S2I_umax / 2,
+ S2I_umax / 3,
+ S2I_umax / 4,
+ S2I_umax / 5,
+ S2I_umax / 6,
+ S2I_umax / 7,
+ S2I_umax / 8,
+ S2I_umax / 9,
+ S2I_umax / 10,
+ S2I_umax / 11,
+ S2I_umax / 12,
+ S2I_umax / 13,
+ S2I_umax / 14,
+ S2I_umax / 15,
+ S2I_umax / 16,
+ S2I_umax / 17,
+ S2I_umax / 18,
+ S2I_umax / 19,
+ S2I_umax / 20,
+ S2I_umax / 21,
+ S2I_umax / 22,
+ S2I_umax / 23,
+ S2I_umax / 24,
+ S2I_umax / 25,
+ S2I_umax / 26,
+ S2I_umax / 27,
+ S2I_umax / 28,
+ S2I_umax / 29,
+ S2I_umax / 30,
+ S2I_umax / 31,
+ S2I_umax / 32,
+ S2I_umax / 33,
+ S2I_umax / 34,
+ S2I_umax / 35,
+ S2I_umax / 36,
+ S2I_umax / 37,
+ S2I_umax / 38,
+ S2I_umax / 39,
+ S2I_umax / 40,
+ S2I_umax / 41,
+ S2I_umax / 42,
+ S2I_umax / 43,
+ S2I_umax / 44,
+ S2I_umax / 45,
+ S2I_umax / 46,
+ S2I_umax / 47,
+ S2I_umax / 48,
+ S2I_umax / 49,
+ S2I_umax / 50,
+ S2I_umax / 51,
+ S2I_umax / 52,
+ S2I_umax / 53,
+ S2I_umax / 54,
+ S2I_umax / 55,
+ S2I_umax / 56,
+ S2I_umax / 57,
+ S2I_umax / 58,
+ S2I_umax / 59,
+ S2I_umax / 60,
+ S2I_umax / 61,
+ S2I_umax / 62,
+ S2I_umax / 63,
+ S2I_umax / 64,
+};
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+extern S2I_type
+#undef extern
+#if S2I_size
+#if S2I_multiplier
+#if __STD_C
+S2I_function(const char* a, size_t size, char** e, char* basep, int m)
+#else
+S2I_function(a, size, e, basep, m) const char* a; size_t size; char** e; char* basep; int m;
+#endif
+#else
+#if __STD_C
+S2I_function(const char* a, size_t size, char** e, int base)
+#else
+S2I_function(a, size, e, base) const char* a; size_t size; char** e; int base;
+#endif
+#endif
+#else
+#if S2I_multiplier
+#if __STD_C
+S2I_function(const char* a, char** e, char* basep, int m)
+#else
+S2I_function(a, e, basep, m) const char* a; char** e; char* basep; int m;
+#endif
+#else
+#if __STD_C
+S2I_function(const char* a, char** e, int base)
+#else
+S2I_function(a, e, base) const char* a; char** e; int base;
+#endif
+#endif
+#endif
+{
+ register unsigned char* s = (unsigned char*)a;
+#if S2I_size
+ register unsigned char* z = s + size;
+#endif
+ register S2I_unumber n;
+ register S2I_unumber x;
+ register int c;
+ register int shift;
+ register unsigned char* p;
+ register unsigned char* cv;
+ unsigned char* b;
+ unsigned char* k;
+ S2I_unumber v;
+#if S2I_multiplier
+ register int base;
+#endif
+ int negative;
+ int overflow = 0;
+ int decimal = 0;
+ int thousand = 0;
+#if !S2I_unsigned
+ int qualifier = 0;
+#endif
+
+#if S2I_multiplier
+ base = basep ? *((unsigned char*)basep) : 0;
+#else
+ if (base > 36 && base <= SF_RADIX)
+ {
+ static int conformance = -1;
+
+ if (conformance < 0)
+ conformance = !strcmp(astconf("CONFORMANCE", NiL, NiL), "standard");
+ if (conformance)
+ base = 1;
+ }
+#endif
+ if (base && (base < 2 || base > SF_RADIX))
+ {
+ errno = EINVAL;
+ return 0;
+ }
+ while (S2I_valid(s) && isspace(*s))
+ s++;
+ if ((negative = S2I_valid(s) && (*s == '-')) || S2I_valid(s) && *s == '+')
+ k = ++s;
+ else
+ k = 0;
+ p = s;
+ if (!base)
+ {
+ if (S2I_valid(p) && (c = *p++) >= '0' && c <= '9')
+ {
+ n = c - '0';
+ if (S2I_valid(p) && (c = *p) >= '0' && c <= '9')
+ {
+ n = (n << 3) + (n << 1) + c - '0';
+ p++;
+ }
+ if (S2I_valid(p) && *p == '#')
+ {
+ if (n >= 2 && n <= 64)
+ {
+ k = s = p + 1;
+ base = n;
+ }
+ }
+ else if (base)
+ base = 0;
+ else if (S2I_valid(s) && *s == '0' && S2I_valid(s + 1))
+ {
+ if ((c = *(s + 1)) == 'x' || c == 'X')
+ {
+ k = s += 2;
+ base = 16;
+ }
+ else if (c >= '0' && c <= '7')
+ {
+ s++;
+ base = 8;
+ }
+ }
+ }
+ if (!base)
+ base = 10;
+ else if (base < 2 || base > SF_RADIX)
+ {
+ errno = EINVAL;
+ return 0;
+ }
+#if S2I_multiplier
+ else
+ {
+ if (basep)
+ *basep = base;
+ m = -1;
+ }
+#endif
+ }
+#if S2I_multiplier
+ else
+ m = -1;
+#endif
+
+ /*
+ * this part transcribed from sfvscanf()
+ */
+
+ SFSETLOCALE(&decimal, &thousand);
+ x = mm[base];
+ n = 0;
+ if (base == 10)
+ {
+ b = s;
+ p = 0;
+ for (;;)
+ {
+ if (S2I_valid(s) && (c = *s++) >= '0' && c <= '9')
+ {
+ if (n > x)
+ overflow = 1;
+ else
+ {
+ n = (n << 3) + (n << 1);
+ c -= '0';
+ if (ADDOVER(n, c, negative))
+ overflow = 1;
+ n += c;
+ }
+ }
+ else if (p && (s - p) != (3 + S2I_valid(s)))
+ {
+ s = p;
+ n = v;
+ c = 0;
+ break;
+ }
+ else if (!S2I_valid(s) || c != thousand)
+ break;
+ else if (!p && (s - b) > 4)
+ {
+ if (e)
+ *e = (char*)s - 1;
+ if (overflow)
+ {
+ errno = ERANGE;
+#if S2I_unsigned
+ n = S2I_max;
+#else
+ n = negative ? S2I_min : S2I_max;
+#endif
+ }
+ return n;
+ }
+ else
+ {
+ p = s;
+ v = n;
+ }
+ }
+ }
+ else
+ {
+ SFCVINIT();
+ cv = base <= 36 ? _Sfcv36 : _Sfcv64;
+ if ((base & ~(base - 1)) == base)
+ {
+#if !S2I_unsigned
+ qualifier |= QU;
+#endif
+ if (base < 8)
+ shift = base < 4 ? 1 : 2;
+ else if (base < 32)
+ shift = base < 16 ? 3 : 4;
+ else
+ shift = base < 64 ? 5 : 6;
+ while (S2I_valid(s) && (c = cv[*s++]) < base)
+ {
+ if (n > x)
+ overflow = 1;
+ else
+ {
+ n <<= shift;
+ if (ADDOVER(n, c, negative))
+ overflow = 1;
+ n += c;
+ }
+ }
+ }
+ else
+ while (S2I_valid(s) && (c = cv[*s++]) < base)
+ {
+ if (n > x)
+ overflow = 1;
+ else
+ {
+ n *= base;
+ if (ADDOVER(n, c, negative))
+ overflow = 1;
+ n += c;
+ }
+ }
+ c = *(s - 1);
+ }
+
+#if S2I_qualifier
+
+ /*
+ * optional qualifier suffix
+ */
+
+ if (S2I_valid(s) && s > (unsigned char*)(a + 1))
+ {
+ base = 0;
+ for (;;)
+ {
+ if (!(base & QL) && (c == 'l' || c == 'L'))
+ {
+ base |= QL;
+ if (!S2I_valid(s))
+ break;
+ c = *s++;
+ if (c == 'l' || c == 'L')
+ {
+ if (!S2I_valid(s))
+ break;
+ c = *s++;
+ }
+ }
+ else if (!(base & QU) && (c == 'u' || c == 'U'))
+ {
+ base |= QU;
+#if !S2I_unsigned
+ qualifier |= QU;
+#endif
+ if (!S2I_valid(s))
+ break;
+ c = *s++;
+ }
+ else
+ break;
+ }
+ }
+#endif
+ if (S2I_valid(s))
+ {
+#if S2I_multiplier
+ /*
+ * optional multiplier suffix
+ */
+
+ if (m < 0 || s == (unsigned char*)(a + 1))
+ s--;
+ else
+ {
+ x = m != 1;
+ switch (c)
+ {
+ case 'b':
+ case 'B':
+ shift = 9;
+ x = 0;
+ break;
+ case 'k':
+ case 'K':
+ shift = 10;
+ break;
+ case 'm':
+ case 'M':
+ shift = 20;
+ break;
+ case 'g':
+ case 'G':
+ shift = 30;
+ break;
+ case 't':
+ case 'T':
+ shift = 40;
+ break;
+ case 'p':
+ case 'P':
+ shift = 50;
+ break;
+ case 'e':
+ case 'E':
+ shift = 60;
+ break;
+ default:
+ if (m <= 1)
+ v = 0;
+ else if (c == decimal && S2I_valid(s))
+ {
+ if (MPYOVER(n, m))
+ overflow = 1;
+ n *= m;
+ v = 0;
+ while (S2I_valid(s) && (c = *s++) >= '0' && c <= '9')
+ v += (m /= 10) * (c - '0');
+ if (ADDOVER(n, v, negative))
+ overflow = 1;
+ n += v;
+ v = 0;
+ }
+ else
+ v = m;
+ s--;
+ shift = 0;
+ break;
+ }
+ if (shift)
+ {
+ if (S2I_valid(s))
+ switch (*s)
+ {
+ case 'i':
+ case 'I':
+ s++;
+ x = 0;
+ break;
+ }
+ if (S2I_valid(s))
+ switch (*s)
+ {
+ case 'b':
+ case 'B':
+ s++;
+ break;
+ }
+ if (x)
+ {
+ v = 1;
+ for (shift /= 10; shift; shift--)
+ {
+ if (v >= (S2I_max/1000))
+ {
+ v = 0;
+ overflow = 1;
+ }
+ v *= 1000;
+ }
+ }
+ else
+#if S2I_unsigned
+ if (shift >= (sizeof(S2I_type) * CHAR_BIT))
+#else
+ if (shift >= (sizeof(S2I_type) * CHAR_BIT - 1))
+#endif
+ {
+ v = 0;
+ overflow = 1;
+ }
+ else
+ v = ((S2I_unumber)1) << shift;
+ }
+ if (v)
+ {
+ if (MPYOVER(n, v))
+ overflow = 1;
+ n *= v;
+ }
+ }
+#else
+ s--;
+#endif
+ }
+ if (s == k)
+ {
+ s--;
+#if S2I_multiplier
+ if (basep)
+ *basep = 10;
+#endif
+ }
+#if !S2I_unsigned
+ else if (!(qualifier & QU))
+ {
+ if (negative)
+ {
+ if (!n)
+ {
+ b = k;
+ do
+ {
+ if (b >= s)
+ {
+ negative = 0;
+ break;
+ }
+ } while (*b++ == '0');
+ }
+ if (negative && (n - 1) > S2I_max)
+ overflow = 1;
+ }
+ else if (n > S2I_max)
+ overflow = 1;
+ }
+#endif
+ if (e)
+ *e = (char*)s;
+ if (overflow)
+ {
+#if !S2I_unsigned
+ if (negative)
+ {
+ if (x << 1)
+ errno = ERANGE;
+ return (S2I_type)S2I_min;
+ }
+#endif
+ errno = ERANGE;
+ return (S2I_type)S2I_max;
+ }
+ return negative ? -n : n;
+}
diff --git a/src/lib/libast/string/strtoip4.c b/src/lib/libast/string/strtoip4.c
new file mode 100644
index 0000000..6d4aed2
--- /dev/null
+++ b/src/lib/libast/string/strtoip4.c
@@ -0,0 +1,150 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <ctype.h>
+
+/*
+ * convert string to 4 byte local byte order ip address
+ * with optional prefix bits
+ * pointer to first unused char placed in *e, even on error
+ * return 0:ok <0:error
+ *
+ * valid addresses match the egrep RE:
+ *
+ * [0-9]{1,3}(\.[0-9]{1,3})*|0[xX][0-9a-fA-Z]+
+ *
+ * valid bits/masks match the egrep RE:
+ *
+ * (/([0-9]+|[0-9]{1,3}(\.[0-9]{1,3})*))?
+ *
+ * if pbits!=0 and no bits/mask specified then trailing 0's in addr
+ * are used to compute the mask
+ */
+
+int
+strtoip4(register const char* s, char** e, uint32_t* paddr, unsigned char* pbits)
+{
+ register int c;
+ register unsigned int n;
+ register uint32_t addr;
+ register int part;
+ register unsigned char bits;
+ uint32_t z;
+ int old;
+ int r;
+ const char* b;
+
+ r = -1;
+ while (isspace(*s))
+ s++;
+ b = s;
+ addr = 0;
+ bits = 0;
+ part = 0;
+ do
+ {
+ n = 0;
+ while ((c = *s++) >= '0' && c <= '9')
+ n = n * 10 + (c - '0');
+ if ((c == 'x' || c == 'X') && !part)
+ {
+ addr = n;
+ for (;;)
+ {
+ if ((c = *s++) >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c -= 'a' - 10;
+ else if (c >= 'A' && c <= 'F')
+ c -= 'F' - 10;
+ else
+ break;
+ addr = addr * 16 + c;
+ }
+ part = 4;
+ break;
+ }
+ if (n > 0xff)
+ goto done;
+ addr = (addr << 8) | n;
+ part++;
+ } while (c == '.');
+ if ((s - b) == 1 && c != '/' || part > 4)
+ goto done;
+ if (old = part < 4)
+ while (part++ < 4)
+ addr <<= 8;
+ if (pbits)
+ {
+ if (c == '/')
+ {
+ part = 0;
+ z = 0;
+ for (;;)
+ {
+ n = 0;
+ while ((c = *s++) >= '0' && c <= '9')
+ n = n * 10 + (c - '0');
+ z = (z << 8) | n;
+ part++;
+ if (c != '.')
+ break;
+ old = 1;
+ }
+ if (part > 4)
+ goto done;
+ if (z <= 32 && (!old || part < 2))
+ bits = z;
+ else if (z)
+ {
+ if (part == 4 && (z & 0x8000001) == 1)
+ z = ~z;
+ while (!(z & 1))
+ z >>= 1;
+ while (z & 1)
+ {
+ z >>= 1;
+ bits++;
+ }
+ }
+ }
+ else if ((z = (addr >> 24)) < 128)
+ bits = 8;
+ else if (z < 192)
+ bits = 16;
+ else
+ bits = 24;
+ if (*pbits = bits)
+ addr &= ~((((uint32_t)1)<<(32-bits))-1);
+ else
+ addr = 0;
+ }
+ if (paddr)
+ *paddr = addr;
+ r = 0;
+ done:
+ if (e)
+ *e = (char*)(s - 1);
+ return r;
+}
diff --git a/src/lib/libast/string/strtoip6.c b/src/lib/libast/string/strtoip6.c
new file mode 100644
index 0000000..ff1c652
--- /dev/null
+++ b/src/lib/libast/string/strtoip6.c
@@ -0,0 +1,204 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#if _PACKAGE_ast
+#include <ast.h>
+#else
+#include <stdint.h>
+#endif
+
+#include <ctype.h>
+#include <ip6.h>
+
+/*
+ * convert string to ipv6 network byte order ip address
+ * with optional prefix bits
+ * pointer to first unused char placed in *e, even on error
+ * return 0:ok <0:error
+ */
+
+#define COL 16
+#define DOT 17
+#define END 18
+#define PFX 19
+
+int
+strtoip6(register const char* s, char** e, unsigned char* addr, unsigned char* bits)
+{
+ register unsigned char* b = addr;
+ register unsigned char* x = b + IP6ADDR;
+ register unsigned char* z;
+ register int c;
+ register uint32_t a;
+
+ static unsigned char lex[256];
+
+ if (!lex[0])
+ {
+ for (c = 0; c < sizeof(lex); ++c)
+ lex[c] = END;
+ lex['0'] = 0;
+ lex['1'] = 1;
+ lex['2'] = 2;
+ lex['3'] = 3;
+ lex['4'] = 4;
+ lex['5'] = 5;
+ lex['6'] = 6;
+ lex['7'] = 7;
+ lex['8'] = 8;
+ lex['9'] = 9;
+ lex['A'] = lex['a'] = 10;
+ lex['B'] = lex['b'] = 11;
+ lex['C'] = lex['c'] = 12;
+ lex['D'] = lex['d'] = 13;
+ lex['E'] = lex['e'] = 14;
+ lex['F'] = lex['f'] = 15;
+ lex[':'] = COL;
+ lex['.'] = DOT;
+ lex['/'] = PFX;
+ }
+ while (isspace(*s))
+ s++;
+ z = 0;
+ a = 0;
+ if (*s)
+ for (;;)
+ {
+ switch (c = lex[*((unsigned char*)s++)])
+ {
+ case END:
+ case PFX:
+ if ((x - b) < 2)
+ break;
+ *b++ = a>>8;
+ *b++ = a;
+ break;
+ case COL:
+ if ((x - b) < 2)
+ break;
+ *b++ = a>>8;
+ *b++ = a;
+ a = 0;
+ if (*s == ':')
+ {
+ if (z)
+ {
+ s--;
+ break;
+ }
+ z = b;
+ if ((c = lex[*((unsigned char*)++s)]) >= 16)
+ {
+ s++;
+ break;
+ }
+ }
+ continue;
+ case DOT:
+ if (b >= x)
+ {
+ s--;
+ break;
+ }
+ *b++ = ((a >> 8) & 0xf) * 100 + ((a >> 4) & 0xf) * 10 + (a & 0xf);
+ a = 0;
+ for (;;)
+ {
+ switch (c = lex[*((unsigned char*)s++)])
+ {
+ case COL:
+ case END:
+ case PFX:
+ if (b < x)
+ *b++ = a;
+ a = 0;
+ break;
+ case DOT:
+ if (b >= x)
+ break;
+ *b++ = a;
+ a = 0;
+ continue;
+ default:
+ a = (a * 10) + c;
+ continue;
+ }
+ break;
+ }
+ if (c == COL)
+ {
+ if (*s == ':')
+ {
+ if (z)
+ {
+ s--;
+ break;
+ }
+ z = b;
+ if ((c = lex[*((unsigned char*)++s)]) >= 16)
+ {
+ s++;
+ break;
+ }
+ }
+ if ((b - addr) == 6 && addr[0] == 0x20 && addr[1] == 0x02)
+ continue;
+ }
+ break;
+ default:
+ a = (a << 4) | c;
+ continue;
+ }
+ break;
+ }
+ if (b == addr)
+ c = END + 1;
+ else
+ {
+ if (z)
+ {
+ while (b > z)
+ *--x = *--b;
+ while (x > z)
+ *--x = 0;
+ }
+ else
+ while (b < x)
+ *b++ = 0;
+ if (bits)
+ {
+ if (c == PFX)
+ {
+ a = 0;
+ while ((c = lex[*((unsigned char*)s++)]) < 10)
+ a = a * 10 + c;
+ }
+ else
+ a = 0xff;
+ *bits = a;
+ }
+ }
+ if (e)
+ *e = (char*)(s - 1);
+ return c == END ? 0 : -1;
+}
diff --git a/src/lib/libast/string/strton.c b/src/lib/libast/string/strton.c
new file mode 100644
index 0000000..05fbd86
--- /dev/null
+++ b/src/lib/libast/string/strton.c
@@ -0,0 +1,31 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strton() implementation
+ */
+
+#define S2I_function strton
+#define S2I_number long
+#define S2I_unumber unsigned long
+#define S2I_multiplier 1
+
+#include "strtoi.h"
diff --git a/src/lib/libast/string/strtonll.c b/src/lib/libast/string/strtonll.c
new file mode 100644
index 0000000..22084dc
--- /dev/null
+++ b/src/lib/libast/string/strtonll.c
@@ -0,0 +1,31 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+/*
+ * strtonll() implementation
+ */
+
+#define S2I_function strtonll
+#define S2I_number intmax_t
+#define S2I_unumber uintmax_t
+#define S2I_multiplier 1
+
+#include "strtoi.h"
diff --git a/src/lib/libast/string/struid.c b/src/lib/libast/string/struid.c
new file mode 100644
index 0000000..9a26e8f
--- /dev/null
+++ b/src/lib/libast/string/struid.c
@@ -0,0 +1,109 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * uid name -> number
+ */
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide getpwnam getpwuid
+#else
+#define getpwnam ______getpwnam
+#define getpwuid ______getpwuid
+#endif
+
+#include <ast.h>
+#include <cdt.h>
+#include <pwd.h>
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide getpwnam getpwuid
+#else
+#undef getpwnam
+#undef getpwuid
+#endif
+
+extern struct passwd* getpwnam(const char*);
+extern struct passwd* getpwuid(uid_t);
+
+typedef struct Id_s
+{
+ Dtlink_t link;
+ int id;
+ char name[1];
+} Id_t;
+
+/*
+ * return uid number given uid name
+ * -1 on first error for a given name
+ * -2 on subsequent errors for a given name
+ */
+
+int
+struid(const char* name)
+{
+ register Id_t* ip;
+ register struct passwd* pw;
+ int id;
+ char* e;
+
+ static Dt_t* dict;
+ static Dtdisc_t disc;
+
+ if (!dict)
+ {
+ disc.key = offsetof(Id_t, name);
+ dict = dtopen(&disc, Dtset);
+ }
+ else if (ip = (Id_t*)dtmatch(dict, name))
+ return ip->id;
+ if (pw = getpwnam(name))
+ id = pw->pw_uid;
+ else
+ {
+ id = strtol(name, &e, 0);
+#if _WINIX
+ if (!*e)
+ {
+ if (!getpwuid(id))
+ id = -1;
+ }
+ else if (streq(name, "root") && (pw = getpwnam("Administrator")))
+ id = pw->pw_uid;
+ else
+ id = -1;
+#else
+ if (*e || !getpwuid(id))
+ id = -1;
+#endif
+ }
+ if (dict && (ip = newof(0, Id_t, 1, strlen(name))))
+ {
+ strcpy(ip->name, name);
+ ip->id = id >= 0 ? id : -2;
+ dtinsert(dict, ip);
+ }
+ return id;
+}
diff --git a/src/lib/libast/string/struniq.c b/src/lib/libast/string/struniq.c
new file mode 100644
index 0000000..498fd4e
--- /dev/null
+++ b/src/lib/libast/string/struniq.c
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * struniq - uniq a sorted argv
+ * 0 sentinel is neither expected nor restored
+ *
+ * Glenn Fowler
+ * David Korn
+ * AT&T Research
+ */
+
+#include <ast.h>
+
+int
+struniq(char** argv, int n)
+{
+ register char** ao;
+ register char** an;
+ register char** ae;
+
+ ao = an = argv;
+ ae = ao + n;
+ while (++an < ae)
+ {
+ while (streq(*ao, *an))
+ if (++an >= ae)
+ return ao - argv + 1;
+ *++ao = *an;
+ }
+ return ao - argv + 1;
+}
diff --git a/src/lib/libast/string/strvcmp.c b/src/lib/libast/string/strvcmp.c
new file mode 100644
index 0000000..036460d
--- /dev/null
+++ b/src/lib/libast/string/strvcmp.c
@@ -0,0 +1,74 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <ctype.h>
+
+/*
+ * version strcmp(3)
+ */
+
+int
+strvcmp(register const char* a, register const char* b)
+{
+ register unsigned long na;
+ register unsigned long nb;
+
+ for (;;)
+ {
+ if (isdigit(*a) && isdigit(*b))
+ {
+ na = nb = 0;
+ while (isdigit(*a))
+ na = na * 10 + *a++ - '0';
+ while (isdigit(*b))
+ nb = nb * 10 + *b++ - '0';
+ if (na < nb)
+ return -1;
+ if (na > nb)
+ return 1;
+ }
+ else if (*a != *b)
+ break;
+ else if (!*a)
+ return 0;
+ else
+ {
+ a++;
+ b++;
+ }
+ }
+ if (*a == 0)
+ return -1;
+ if (*b == 0)
+ return 1;
+ if (*a == '.')
+ return -1;
+ if (*b == '.')
+ return 1;
+ if (*a == '-')
+ return -1;
+ if (*b == '-')
+ return 1;
+ return *a < *b ? -1 : 1;
+}
diff --git a/src/lib/libast/string/swapget.c b/src/lib/libast/string/swapget.c
new file mode 100644
index 0000000..b032bfc
--- /dev/null
+++ b/src/lib/libast/string/swapget.c
@@ -0,0 +1,57 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * internal representation conversion support
+ */
+
+#include <ast.h>
+#include <swap.h>
+
+/*
+ * get int_n from b according to op
+ */
+
+intmax_t
+swapget(int op, const void* b, int n)
+{
+ register unsigned char* p;
+ register unsigned char* d;
+ intmax_t v;
+ unsigned char tmp[sizeof(intmax_t)];
+
+ if (n > sizeof(intmax_t))
+ n = sizeof(intmax_t);
+ if (op) swapmem(op, b, d = tmp, n);
+ else d = (unsigned char*)b;
+ p = d + n;
+ v = 0;
+ while (d < p)
+ {
+ v <<= CHAR_BIT;
+ v |= *d++;
+ }
+ return v;
+}
diff --git a/src/lib/libast/string/swapmem.c b/src/lib/libast/string/swapmem.c
new file mode 100644
index 0000000..7a96bf0
--- /dev/null
+++ b/src/lib/libast/string/swapmem.c
@@ -0,0 +1,109 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * internal representation conversion support
+ */
+
+#include <ast.h>
+#include <swap.h>
+
+/*
+ * swap n bytes according to op
+ * from==to is ok
+ */
+
+void*
+swapmem(int op, const void* from, void* to, register size_t n)
+{
+ register char* f = (char*)from;
+ register char* t = (char*)to;
+ register int c;
+
+ switch (op & (n - 1))
+ {
+ case 0:
+ if (t != f)
+ memcpy(t, f, n);
+ break;
+ case 1:
+ for (n >>= 1; n--; f += 2, t += 2)
+ {
+ c = f[0]; t[0] = f[1]; t[1] = c;
+ }
+ break;
+ case 2:
+ for (n >>= 2; n--; f += 4, t += 4)
+ {
+ c = f[0]; t[0] = f[2]; t[2] = c;
+ c = f[1]; t[1] = f[3]; t[3] = c;
+ }
+ break;
+ case 3:
+ for (n >>= 2; n--; f += 4, t += 4)
+ {
+ c = f[0]; t[0] = f[3]; t[3] = c;
+ c = f[1]; t[1] = f[2]; t[2] = c;
+ }
+ break;
+ case 4:
+ for (n >>= 3; n--; f += 8, t += 8)
+ {
+ c = f[0]; t[0] = f[4]; t[4] = c;
+ c = f[1]; t[1] = f[5]; t[5] = c;
+ c = f[2]; t[2] = f[6]; t[6] = c;
+ c = f[3]; t[3] = f[7]; t[7] = c;
+ }
+ break;
+ case 5:
+ for (n >>= 3; n--; f += 8, t += 8)
+ {
+ c = f[0]; t[0] = f[5]; t[5] = c;
+ c = f[1]; t[1] = f[4]; t[4] = c;
+ c = f[2]; t[2] = f[7]; t[7] = c;
+ c = f[3]; t[3] = f[6]; t[6] = c;
+ }
+ break;
+ case 6:
+ for (n >>= 3; n--; f += 8, t += 8)
+ {
+ c = f[0]; t[0] = f[6]; t[6] = c;
+ c = f[1]; t[1] = f[7]; t[7] = c;
+ c = f[2]; t[2] = f[4]; t[4] = c;
+ c = f[3]; t[3] = f[5]; t[5] = c;
+ }
+ break;
+ case 7:
+ for (n >>= 3; n--; f += 8, t += 8)
+ {
+ c = f[0]; t[0] = f[7]; t[7] = c;
+ c = f[1]; t[1] = f[6]; t[6] = c;
+ c = f[2]; t[2] = f[5]; t[5] = c;
+ c = f[3]; t[3] = f[4]; t[4] = c;
+ }
+ break;
+ }
+ return to;
+}
diff --git a/src/lib/libast/string/swapop.c b/src/lib/libast/string/swapop.c
new file mode 100644
index 0000000..aefe687
--- /dev/null
+++ b/src/lib/libast/string/swapop.c
@@ -0,0 +1,59 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * internal representation conversion support
+ */
+
+#include <ast.h>
+#include <swap.h>
+
+/*
+ * return the swap operation for external to internal conversion
+ * if size<0 then (-size) used and (-size==4)&&(op==3) => op=7
+ * this is a workaround for 4 byte magic predicting 8 byte swap
+ */
+
+int
+swapop(const void* internal, const void* external, int size)
+{
+ register int op;
+ register int z;
+ char tmp[sizeof(intmax_t)];
+
+ if ((z = size) < 0)
+ z = -z;
+ if (z <= 1)
+ return 0;
+ if (z <= sizeof(intmax_t))
+ for (op = 0; op < z; op++)
+ if (!memcmp(internal, swapmem(op, external, tmp, z), z))
+ {
+ if (size < 0 && z == 4 && op == 3)
+ op = 7;
+ return op;
+ }
+ return -1;
+}
diff --git a/src/lib/libast/string/swapput.c b/src/lib/libast/string/swapput.c
new file mode 100644
index 0000000..66373ae
--- /dev/null
+++ b/src/lib/libast/string/swapput.c
@@ -0,0 +1,50 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * internal representation conversion support
+ */
+
+#include <ast.h>
+#include <swap.h>
+
+/*
+ * put v of n chars into b according to op
+ */
+
+void*
+swapput(int op, void* b, int n, intmax_t v)
+{
+ register char* p = (char*)b + n;
+
+ while (p > (char*)b)
+ {
+ *--p = v;
+ v >>= CHAR_BIT;
+ }
+ if (op)
+ swapmem(op, p, p, n);
+ return b;
+}
diff --git a/src/lib/libast/string/tok.c b/src/lib/libast/string/tok.c
new file mode 100644
index 0000000..c781fb7
--- /dev/null
+++ b/src/lib/libast/string/tok.c
@@ -0,0 +1,190 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * token stream routines
+ */
+
+#include <ast.h>
+#include <tok.h>
+
+#define FLG_RESTORE 01 /* restore string on close */
+#define FLG_NEWLINE 02 /* return newline token next */
+
+typedef struct Tok_s /* token stream state */
+{
+ union
+ {
+ char* end; /* end ('\0') of last token */
+ struct Tok_s* nxt; /* next in free list */
+ } ptr;
+ char chr; /* replace *end with this */
+ char flg; /* FLG_* */
+} Tok_t;
+
+static Tok_t* freelist;
+
+/*
+ * open a new token stream on s
+ * if f==0 then string is not restored
+ */
+
+char*
+tokopen(register char* s, int f)
+{
+ register Tok_t* p;
+
+ if (p = freelist)
+ freelist = freelist->ptr.nxt;
+ else if (!(p = newof(0, Tok_t, 1, 0)))
+ return 0;
+ p->chr = *(p->ptr.end = s);
+ p->flg = f ? FLG_RESTORE : 0;
+ return (char*)p;
+}
+
+/*
+ * close a token stream
+ * restore the string to its original state
+ */
+
+void
+tokclose(char* u)
+{
+ register Tok_t* p = (Tok_t*)u;
+
+ if (p->flg == FLG_RESTORE && *p->ptr.end != p->chr)
+ *p->ptr.end = p->chr;
+ p->ptr.nxt = freelist;
+ freelist = p;
+}
+
+/*
+ * return next space separated token
+ * "\n" is returned as a token
+ * 0 returned when no tokens remain
+ * "..." and '...' quotes are honored with \ escapes
+ */
+
+char*
+tokread(char* u)
+{
+ register Tok_t* p = (Tok_t*)u;
+ register char* s;
+ register char* r;
+ register int q;
+ register int c;
+
+ /*
+ * restore string on each call
+ */
+
+ if (!p->chr)
+ return 0;
+ s = p->ptr.end;
+ switch (p->flg)
+ {
+ case FLG_NEWLINE:
+ p->flg = 0;
+ return "\n";
+ case FLG_RESTORE:
+ if (*s != p->chr)
+ *s = p->chr;
+ break;
+ default:
+ if (!*s)
+ s++;
+ break;
+ }
+
+ /*
+ * skip leading space
+ */
+
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (!*s)
+ {
+ p->ptr.end = s;
+ p->chr = 0;
+ return 0;
+ }
+
+ /*
+ * find the end of this token
+ */
+
+ r = s;
+ q = 0;
+ for (;;)
+ switch (c = *r++)
+ {
+ case '\n':
+ if (!q)
+ {
+ if (s == (r - 1))
+ {
+ if (!p->flg)
+ {
+ p->ptr.end = r;
+ return "\n";
+ }
+ r++;
+ }
+ else if (!p->flg)
+ p->flg = FLG_NEWLINE;
+ }
+ /*FALLTHROUGH*/
+ case ' ':
+ case '\t':
+ if (q)
+ break;
+ /*FALLTHROUGH*/
+ case 0:
+ if (s == --r)
+ {
+ p->ptr.end = r;
+ p->chr = 0;
+ }
+ else
+ {
+ p->chr = *(p->ptr.end = r);
+ if (*r)
+ *r = 0;
+ }
+ return s;
+ case '\\':
+ if (*r)
+ r++;
+ break;
+ case '"':
+ case '\'':
+ if (c == q)
+ q = 0;
+ else if (!q)
+ q = c;
+ break;
+ }
+}
diff --git a/src/lib/libast/string/tokline.c b/src/lib/libast/string/tokline.c
new file mode 100644
index 0000000..b572651
--- /dev/null
+++ b/src/lib/libast/string/tokline.c
@@ -0,0 +1,193 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return an Sfio_t* to a file or string that
+ *
+ * splices \\n to single lines
+ * checks for "..." and '...' spanning newlines
+ * drops #...\n comments
+ *
+ * if <arg> is a file and first line matches
+ * #!!! <level> <message> !!!
+ * then error(<lev>,"%s: %s",<arg>,<msg>) called
+ *
+ * NOTE: seek disabled and string disciplines cannot be composed
+ * quoted \n translated to \r
+ */
+
+#include <ast.h>
+#include <error.h>
+#include <tok.h>
+
+typedef struct
+{
+ Sfdisc_t disc;
+ Sfio_t* sp;
+ int quote;
+ int* line;
+} Splice_t;
+
+/*
+ * the splicer
+ */
+
+static int
+spliceline(Sfio_t* s, int op, void* val, Sfdisc_t* ad)
+{
+ Splice_t* d = (Splice_t*)ad;
+ register char* b;
+ register int c;
+ register int n;
+ register int q;
+ register int j;
+ register char* e;
+ char* buf;
+
+ NoP(val);
+ switch (op)
+ {
+ case SF_CLOSING:
+ sfclose(d->sp);
+ return 0;
+ case SF_DPOP:
+ free(d);
+ return 0;
+ case SF_READ:
+ do
+ {
+ if (!(buf = sfgetr(d->sp, '\n', 0)) && !(buf = sfgetr(d->sp, '\n', -1)))
+ return 0;
+ n = sfvalue(d->sp);
+ q = d->quote;
+ j = 0;
+ (*d->line)++;
+ if (n > 1 && buf[n - 2] == '\\')
+ {
+ j = 1;
+ n -= 2;
+ if (q == '#')
+ {
+ n = 0;
+ continue;
+ }
+ }
+ else if (q == '#')
+ {
+ q = 0;
+ n = 0;
+ continue;
+ }
+ if (n > 0)
+ {
+ e = (b = buf) + n;
+ while (b < e)
+ {
+ if ((c = *b++) == '\\')
+ b++;
+ else if (c == q)
+ q = 0;
+ else if (!q)
+ {
+ if (c == '\'' || c == '"')
+ q = c;
+ else if (c == '#' && (b == (buf + 1) || (c = *(b - 2)) == ' ' || c == '\t'))
+ {
+ if (buf[n - 1] != '\n')
+ {
+ q = '#';
+ n = b - buf - 2;
+ }
+ else if (n = b - buf - 1)
+ buf[n - 1] = '\n';
+ break;
+ }
+ }
+ }
+ if (n > 0)
+ {
+ if (!j && buf[n - 1] != '\n' && (s->_flags & SF_STRING))
+ buf[n++] = '\n';
+ if (q && buf[n - 1] == '\n')
+ buf[n - 1] = '\r';
+ }
+ }
+ } while (n <= 0);
+ sfsetbuf(s, buf, n);
+ d->quote = q;
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * open a stream to parse lines
+ *
+ * flags: 0 arg: open Sfio_t*
+ * flags: SF_READ arg: file name
+ * flags: SF_STRING arg: null terminated char*
+ *
+ * if line!=0 then it points to a line count that starts at 0
+ * and is incremented for each input line
+ */
+
+Sfio_t*
+tokline(const char* arg, int flags, int* line)
+{
+ Sfio_t* f;
+ Sfio_t* s;
+ Splice_t* d;
+ char* p;
+ char* e;
+
+ static int hidden;
+
+ if (!(d = newof(0, Splice_t, 1, 0)))
+ return 0;
+ if (!(s = sfopen(NiL, NiL, "s")))
+ {
+ free(d);
+ return 0;
+ }
+ if (!(flags & (SF_STRING|SF_READ)))
+ f = (Sfio_t*)arg;
+ else if (!(f = sfopen(NiL, arg, (flags & SF_STRING) ? "s" : "r")))
+ {
+ free(d);
+ sfclose(s);
+ return 0;
+ }
+ else if ((p = sfreserve(f, 0, 0)) && sfvalue(f) > 11 && strmatch(p, "#!!! +([-0-9]) *([!\n]) !!!\n*") && (e = strchr(p, '\n')))
+ {
+ flags = strtol(p + 5, &p, 10);
+ error(flags, "%s:%-.*s", arg, e - p - 4, p);
+ }
+ d->disc.exceptf = spliceline;
+ d->sp = f;
+ *(d->line = line ? line : &hidden) = 0;
+ sfdisc(s, (Sfdisc_t*)d);
+ return s;
+}
diff --git a/src/lib/libast/string/tokscan.c b/src/lib/libast/string/tokscan.c
new file mode 100644
index 0000000..34f6dfc
--- /dev/null
+++ b/src/lib/libast/string/tokscan.c
@@ -0,0 +1,360 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * scan s for tokens in fmt
+ * s modified in place and not restored
+ * if nxt!=0 then it will point to the first unread char in s
+ * the number of scanned tokens is returned
+ * -1 returned if s was not empty and fmt failed to match
+ *
+ * ' ' in fmt matches 0 or more {space,tab}
+ * '\n' in fmt eats remainder of current line
+ * "..." and '...' quotes interpreted
+ * newline is equivalent to end of buf except when quoted
+ * \\ quotes following char
+ *
+ * message support for %s and %v data
+ *
+ * (5:12345) fixed length strings, ) may be \t
+ * (null) NiL
+ *
+ * "..." and '...' may span \n, and \\n is the line splice
+ * quoted '\r' translated to '\n'
+ * otherwise tokenizing is unconditionally terminated by '\n'
+ *
+ * a null arg pointer skips that arg
+ *
+ * %c char
+ * %[hl]d [short|int|long] base 10
+ * %f double
+ * %g double
+ * %[hl]n [short|int|long] C-style base
+ * %[hl]o [short|int|long] base 8
+ * %s string
+ * %[hl]u same as %[hl]n
+ * %v argv, elements
+ * %[hl]x [short|int|long] base 16
+ *
+ * unmatched char args are set to "", int args to 0
+ */
+
+#include <ast.h>
+#include <tok.h>
+
+static char empty[1];
+
+/*
+ * get one string token into p
+ */
+
+static char*
+lextok(register char* s, register int c, char** p, int* n)
+{
+ register char* t;
+ register int q;
+ char* b;
+ char* u;
+
+ if (*s == '(' && (!c || c == ' ' || c == '\n'))
+ {
+ q = strtol(s + 1, &b, 10);
+ if (*b == ':')
+ {
+ if (*(t = ++b + q) == ')' || *t == '\t')
+ {
+ s = t;
+ *s++ = 0;
+ goto end;
+ }
+ }
+ else if (strneq(b, "null)", 5))
+ {
+ s = b + 5;
+ b = 0;
+ goto end;
+ }
+ }
+ b = s;
+ q = 0;
+ t = 0;
+ for (;;)
+ {
+ if (!*s || !q && *s == '\n')
+ {
+ if (!q)
+ {
+ if (!c || c == ' ' || c == '\n') (*n)++;
+ else
+ {
+ s = b;
+ b = empty;
+ break;
+ }
+ }
+ if (t) *t = 0;
+ break;
+ }
+ else if (*s == '\\')
+ {
+ u = s;
+ if (!*++s || *s == '\n' && (!*++s || *s == '\n')) continue;
+ if (p)
+ {
+ if (b == u) b = s;
+ else if (!t) t = u;
+ }
+ }
+ else if (q)
+ {
+ if (*s == q)
+ {
+ q = 0;
+ if (!t) t = s;
+ s++;
+ continue;
+ }
+ else if (*s == '\r') *s = '\n';
+ }
+ else if (*s == '"' || *s == '\'')
+ {
+ q = *s++;
+ if (p)
+ {
+ if (b == (s - 1)) b = s;
+ else if (!t) t = s - 1;
+ }
+ continue;
+ }
+ else if (*s == c || c == ' ' && *s == '\t')
+ {
+ *s++ = 0;
+ if (t) *t = 0;
+ end:
+ if (c == ' ') while (*s == ' ' || *s == '\t') s++;
+ (*n)++;
+ break;
+ }
+ if (t) *t++ = *s;
+ s++;
+ }
+ if (p) *p = b;
+ return(s);
+}
+
+/*
+ * scan entry
+ */
+
+int
+tokscan(register char* s, char** nxt, const char* fmt, ...)
+{
+ register int c;
+ register char* f;
+ int num = 0;
+ char* skip = 0;
+ int q;
+ int onum;
+ long val;
+ double dval;
+ va_list ap;
+ char* p_char;
+ double* p_double;
+ int* p_int;
+ long* p_long;
+ short* p_short;
+ char** p_string;
+ char* prv_f = 0;
+ va_list prv_ap;
+
+ va_start(ap, fmt);
+ if (!*s || *s == '\n')
+ {
+ skip = s;
+ s = empty;
+ }
+ f = (char*)fmt;
+ for (;;) switch (c = *f++)
+ {
+ case 0:
+ if (f = prv_f)
+ {
+ prv_f = 0;
+ /* prv_ap value is guarded by prv_f */
+ va_copy(ap, prv_ap);
+ continue;
+ }
+ goto done;
+ case ' ':
+ while (*s == ' ' || *s == '\t') s++;
+ break;
+ case '%':
+ onum = num;
+ switch (c = *f++)
+ {
+ case 'h':
+ case 'l':
+ q = c;
+ c = *f++;
+ break;
+ default:
+ q = 0;
+ break;
+ }
+ switch (c)
+ {
+ case 0:
+ case '%':
+ f--;
+ continue;
+ case ':':
+ prv_f = f;
+ f = va_arg(ap, char*);
+ va_copy(prv_ap, ap);
+ va_copy(ap, va_listval(va_arg(ap, va_listarg)));
+ continue;
+ case 'c':
+ p_char = va_arg(ap, char*);
+ if (!(c = *s) || c == '\n')
+ {
+ if (p_char) *p_char = 0;
+ }
+ else
+ {
+ if (p_char) *p_char = c;
+ s++;
+ num++;
+ }
+ break;
+ case 'd':
+ case 'n':
+ case 'o':
+ case 'u':
+ case 'x':
+ switch (c)
+ {
+ case 'd':
+ c = 10;
+ break;
+ case 'n':
+ case 'u':
+ c = 0;
+ break;
+ case 'o':
+ c = 8;
+ break;
+ case 'x':
+ c = 16;
+ break;
+ }
+ if (!*s || *s == '\n')
+ {
+ val = 0;
+ p_char = s;
+ }
+ else val = strtol(s, &p_char, c);
+ switch (q)
+ {
+ case 'h':
+ if (p_short = va_arg(ap, short*)) *p_short = (short)val;
+ break;
+ case 'l':
+ if (p_long = va_arg(ap, long*)) *p_long = val;
+ break;
+ default:
+ if (p_int = va_arg(ap, int*)) *p_int = (int)val;
+ break;
+ }
+ if (s != p_char)
+ {
+ s = p_char;
+ num++;
+ }
+ break;
+ case 'f':
+ case 'g':
+ if (!*s || *s == '\n')
+ {
+ dval = 0;
+ p_char = s;
+ }
+ else dval = strtod(s, &p_char);
+ if (p_double = va_arg(ap, double*)) *p_double = dval;
+ if (s != p_char)
+ {
+ s = p_char;
+ num++;
+ }
+ break;
+ case 's':
+ p_string = va_arg(ap, char**);
+ if (q = *f) f++;
+ if (!*s || *s == '\n')
+ {
+ if (p_string) *p_string = s;
+ }
+ else s = lextok(s, q, p_string, &num);
+ break;
+ case 'v':
+ p_string = va_arg(ap, char**);
+ c = va_arg(ap, int);
+ if (q = *f) f++;
+ if ((!*s || *s == '\n') && p_string)
+ {
+ *p_string = 0;
+ p_string = 0;
+ }
+ while (*s && *s != '\n' && --c > 0)
+ {
+ s = lextok(s, q, p_string, &num);
+ if (p_string) p_string++;
+ }
+ if (p_string) *p_string = 0;
+ break;
+ }
+ if (skip) num = onum;
+ else if (num == onum)
+ {
+ if (!num) num = -1;
+ skip = s;
+ s = empty;
+ }
+ break;
+ case '\n':
+ goto done;
+ default:
+ if ((*s++ != c) && !skip)
+ {
+ skip = s - 1;
+ s = empty;
+ }
+ break;
+ }
+ done:
+ va_end(ap);
+ if (*s == '\n') *s++ = 0;
+ if (nxt) *nxt = skip ? skip : s;
+ return(num);
+}
diff --git a/src/lib/libast/string/wc2utf8.c b/src/lib/libast/string/wc2utf8.c
new file mode 100644
index 0000000..3b70391
--- /dev/null
+++ b/src/lib/libast/string/wc2utf8.c
@@ -0,0 +1,74 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * convert wide character to utf8 in s
+ * s must have room for at least 6 bytes
+ * number of chars in placed in s returned
+ * thanks Tom Duff
+ */
+
+#include <ast.h>
+
+typedef struct Utf8_s
+{
+ uint32_t range;
+ unsigned short prefix;
+ unsigned short shift;
+} Utf8_t;
+
+static const Utf8_t ops[] =
+{
+ { 0x00000080, 0x00, 0 },
+ { 0x00000800, 0xc0, 6 },
+ { 0x00010000, 0xe0, 12 },
+ { 0x00200000, 0xf0, 18 },
+ { 0x04000000, 0xf8, 24 },
+ { 0x80000000, 0xfc, 30 }
+};
+
+int
+wc2utf8(register char* s, register uint32_t w)
+{
+ register int i;
+ char* b;
+
+ for (i = 0; i < elementsof(ops); i++)
+ if (w < ops[i].range)
+ {
+ b = s;
+ *s++ = ops[i].prefix | (w >> ops[i].shift);
+ switch (ops[i].shift)
+ {
+ case 30: *s++ = 0x80 | ((w >> 24) & 0x3f);
+ case 24: *s++ = 0x80 | ((w >> 18) & 0x3f);
+ case 18: *s++ = 0x80 | ((w >> 12) & 0x3f);
+ case 12: *s++ = 0x80 | ((w >> 6) & 0x3f);
+ case 6: *s++ = 0x80 | (w & 0x3f);
+ }
+ return s - b;
+ }
+ return 0;
+}
diff --git a/src/lib/libast/tm/tmdata.c b/src/lib/libast/tm/tmdata.c
new file mode 100644
index 0000000..1cdaf24
--- /dev/null
+++ b/src/lib/libast/tm/tmdata.c
@@ -0,0 +1,288 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time conversion support readonly data
+ */
+
+#include <ast.h>
+#include <tm.h>
+
+/*
+ * default format strings -- must agree with TM_* indices
+ */
+
+static char* format[] =
+{
+ "Jan", "Feb", "Mar", "Apr",
+ "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec",
+
+ "January", "February", "March", "April",
+ "May", "June", "July", "August",
+ "September", "October", "November", "December",
+
+ "Sun", "Mon", "Tue", "Wed",
+ "Thu", "Fri", "Sat",
+
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday",
+
+ "%H:%M:%S", "%m/%d/%y", "%a %b %e %T %Z %Y",
+
+ "AM", "PM",
+
+ "GMT", "UTC", "UCT", "CUT",
+
+ "DST", "", "", "",
+
+ "s", "es", "", "",
+
+ "second", "minute", "hour", "day",
+ "week", "month", "year",
+
+ "midnight", "morning", "noon", "evening",
+
+ "yesterday", "today", "tomorrow",
+
+ "last", "ago", "past",
+ "this", "now", "current",
+ "in", "next", "hence",
+ "exactly", "", "",
+
+ "at", "on", "", "",
+
+ "st", "nd", "rd", "th", "th",
+ "th", "th", "th", "th", "th",
+
+ "", "", "", "", "",
+ "", "", "", "", "",
+
+ "%a %b %e %T %Y",
+ "%a %b %e %T %Z %Y",
+ "%a %b %e %T %z %Z %Y",
+ "%b %e %H:%M",
+ "%b %e %Y",
+ "%I:%M:%S %p",
+
+ "", "", "", "", "",
+
+ "first", "", "third", "fourth", "fifth",
+ "sixth", "seventh", "eighth", "ninth", "tenth",
+
+ "final", "ending", "nth",
+
+ "work", "working", "workday",
+};
+
+/*
+ * format[] lex type classes
+ */
+
+static unsigned char lex[] =
+{
+ TM_MONTH_ABBREV,TM_MONTH_ABBREV,TM_MONTH_ABBREV,TM_MONTH_ABBREV,
+ TM_MONTH_ABBREV,TM_MONTH_ABBREV,TM_MONTH_ABBREV,TM_MONTH_ABBREV,
+ TM_MONTH_ABBREV,TM_MONTH_ABBREV,TM_MONTH_ABBREV,TM_MONTH_ABBREV,
+
+ TM_MONTH, TM_MONTH, TM_MONTH, TM_MONTH,
+ TM_MONTH, TM_MONTH, TM_MONTH, TM_MONTH,
+ TM_MONTH, TM_MONTH, TM_MONTH, TM_MONTH,
+
+ TM_DAY_ABBREV, TM_DAY_ABBREV, TM_DAY_ABBREV, TM_DAY_ABBREV,
+ TM_DAY_ABBREV, TM_DAY_ABBREV, TM_DAY_ABBREV,
+
+ TM_DAY, TM_DAY, TM_DAY, TM_DAY,
+ TM_DAY, TM_DAY, TM_DAY,
+
+ 0, 0, 0,
+
+ TM_MERIDIAN, TM_MERIDIAN,
+
+ TM_UT, TM_UT, TM_UT, TM_UT,
+ TM_DT, TM_DT, TM_DT, TM_DT,
+
+ TM_SUFFIXES, TM_SUFFIXES, TM_SUFFIXES, TM_SUFFIXES,
+
+ TM_PARTS, TM_PARTS, TM_PARTS, TM_PARTS,
+ TM_PARTS, TM_PARTS, TM_PARTS,
+
+ TM_HOURS, TM_HOURS, TM_HOURS, TM_HOURS,
+
+ TM_DAYS, TM_DAYS, TM_DAYS,
+
+ TM_LAST, TM_LAST, TM_LAST,
+ TM_THIS, TM_THIS, TM_THIS,
+ TM_NEXT, TM_NEXT, TM_NEXT,
+ TM_EXACT, TM_EXACT, TM_EXACT,
+
+ TM_NOISE, TM_NOISE, TM_NOISE, TM_NOISE,
+
+ TM_ORDINAL, TM_ORDINAL, TM_ORDINAL, TM_ORDINAL, TM_ORDINAL,
+ TM_ORDINAL, TM_ORDINAL, TM_ORDINAL, TM_ORDINAL, TM_ORDINAL,
+
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+
+ 0, 0, 0,
+ 0, 0, 0,
+
+ 0, 0, 0, 0, 0,
+
+ TM_ORDINALS, TM_ORDINALS, TM_ORDINALS, TM_ORDINALS, TM_ORDINALS,
+ TM_ORDINALS, TM_ORDINALS, TM_ORDINALS, TM_ORDINALS, TM_ORDINALS,
+
+ TM_FINAL, TM_FINAL, TM_FINAL,
+
+ TM_WORK, TM_WORK, TM_WORK,
+};
+
+/*
+ * output format digits
+ */
+
+static char digit[] = "0123456789";
+
+/*
+ * number of days in month i
+ */
+
+static short days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+/*
+ * sum of days in months before month i
+ */
+
+static short sum[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+
+/*
+ * leap second time_t and accumulated adjustments
+ * (reverse order -- biased for recent dates)
+ *
+ * tl.time is the seconds since the epoch for the leap event
+ *
+ * adding: the first additional second
+ * subtracting: the first dissappearing second
+ */
+
+static Tm_leap_t leap[] =
+{
+ 1230768023, 24, /* 2008-12-31+23:59:60-0000 */
+ 1136073622, 23, /* 2005-12-31+23:59:60-0000 */
+ 915148821, 22, /* 1998-12-31+23:59:60-0000 */
+ 867715220, 21, /* 1997-06-30+23:59:60-0000 */
+ 820454419, 20, /* 1995-12-31+23:59:60-0000 */
+ 773020818, 19, /* 1994-06-30+23:59:60-0000 */
+ 741484817, 18, /* 1993-06-30+23:59:60-0000 */
+ 709948816, 17, /* 1992-06-30+23:59:60-0000 */
+ 662688015, 16, /* 1990-12-31+23:59:60-0000 */
+ 631152014, 15, /* 1989-12-31+23:59:60-0000 */
+ 567993613, 14, /* 1987-12-31+23:59:60-0000 */
+ 489024012, 13, /* 1985-06-30+23:59:60-0000 */
+ 425865611, 12, /* 1983-06-30+23:59:60-0000 */
+ 394329610, 11, /* 1982-06-30+23:59:60-0000 */
+ 362793609, 10, /* 1981-06-30+23:59:60-0000 */
+ 315532808, 9, /* 1979-12-31+23:59:60-0000 */
+ 283996807, 8, /* 1978-12-31+23:59:60-0000 */
+ 252460806, 7, /* 1977-12-31+23:59:60-0000 */
+ 220924805, 6, /* 1976-12-31+23:59:60-0000 */
+ 189302404, 5, /* 1975-12-31+23:59:60-0000 */
+ 157766403, 4, /* 1974-12-31+23:59:60-0000 */
+ 126230402, 3, /* 1973-12-31+23:59:60-0000 */
+ 94694401, 2, /* 1972-12-31+23:59:60-0000 */
+ 78796800, 1, /* 1972-06-30+23:59:60-0000 */
+ 0, 0, /* can reference (tl+1) */
+ 0, 0
+};
+
+/*
+ * time zones
+ *
+ * the UTC entries must be first
+ *
+ * zones with the same type are contiguous with all but the
+ * first entry for the type having a null type
+ *
+ * tz.standard is the sentinel
+ */
+
+static Tm_zone_t zone[] =
+{
+ 0, "GMT", 0, ( 0 * 60), 0, /* UTC */
+ 0, "UCT", 0, ( 0 * 60), 0, /* UTC */
+ 0, "UTC", 0, ( 0 * 60), 0, /* UTC */
+ 0, "CUT", 0, ( 0 * 60), 0, /* UTC */
+ 0, "Z", 0, ( 0 * 60), 0, /* UTC */
+ "USA", "HST", 0, (10 * 60), 0, /* Hawaii */
+ 0, "YST", "YDT", ( 9 * 60), TM_DST, /* Yukon */
+ 0, "PST", "PDT", ( 8 * 60), TM_DST, /* Pacific */
+ 0, "PST", "PPET", ( 8 * 60), TM_DST, /* Pacific pres elect */
+ 0, "MST", "MDT", ( 7 * 60), TM_DST, /* Mountain */
+ 0, "CST", "CDT", ( 6 * 60), TM_DST, /* Central */
+ 0, "EST", "EDT", ( 5 * 60), TM_DST, /* Eastern */
+ "CAN", "AST", "ADT", ( 4 * 60), TM_DST, /* Atlantic */
+ 0, "NST", 0, ( 3 * 60 + 30), 0, /* Newfoundland */
+ "GBR", "", "BST", ( 0 * 60), TM_DST, /* British Summer */
+ "EUR", "WET", "WEST", ( 0 * 60), TM_DST, /* Western Eurpoean */
+ 0, "CET", "CEST", -( 1 * 60), TM_DST, /* Central European */
+ 0, "MET", "MEST", -( 1 * 60), TM_DST, /* Middle European */
+ 0, "EET", "EEST", -( 2 * 60), TM_DST, /* Eastern Eurpoean */
+ "ISR", "IST", "IDT", -( 3 * 60), TM_DST, /* Israel */
+ "IND", "IST", 0, -( 5 * 60 + 30 ), 0, /* India */
+ "CHN", "HKT", 0, -( 8 * 60), 0, /* Hong Kong */
+ "KOR", "KST", "KDT", -( 8 * 60), TM_DST, /* Korea */
+ "SNG", "SST", 0, -( 8 * 60), 0, /* Singapore */
+ "JPN", "JST", 0, -( 9 * 60), 0, /* Japan */
+ "AUS", "AWST", 0, -( 8 * 60), 0, /* Australia Western */
+ 0, "WST", 0, -( 8 * 60), 0, /* Australia Western */
+ 0, "ACST", 0, -( 9 * 60 + 30),TM_DST, /* Australia Central */
+ 0, "CST", 0, -( 9 * 60 + 30),TM_DST, /* Australia Central */
+ 0, "AEST", 0, -(10 * 60), TM_DST, /* Australia Eastern */
+ 0, "EST", 0, -(10 * 60), TM_DST, /* Australia Eastern */
+ "NZL", "NZST", "NZDT", -(12 * 60), TM_DST, /* New Zealand */
+ 0, 0, 0, 0, 0
+};
+
+/*
+ * 2007-03-19 move tm_data from _tm_data_ to (*_tm_datap_)
+ * to allow future Tm_data_t growth
+ * by 2009 _tm_data_ can be static
+ */
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+
+extern Tm_data_t _tm_data_;
+
+#undef extern
+
+Tm_data_t _tm_data_ = { format, lex, digit, days, sum, leap, zone };
+
+__EXTERN__(Tm_data_t, _tm_data_);
+
+__EXTERN__(Tm_data_t*, _tm_datap_);
+
+Tm_data_t* _tm_datap_ = &_tm_data_;
diff --git a/src/lib/libast/tm/tmdate.c b/src/lib/libast/tm/tmdate.c
new file mode 100644
index 0000000..e7ffb79
--- /dev/null
+++ b/src/lib/libast/tm/tmdate.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time conversion support
+ */
+
+#include <tmx.h>
+
+/*
+ * parse date expression in s and return time_t value
+ * see tmxdate() for details
+ */
+
+time_t
+tmdate(const char* s, char** e, time_t* clock)
+{
+ return tmxsec(tmxdate(s, e, tmxclock(clock)));
+}
diff --git a/src/lib/libast/tm/tmequiv.c b/src/lib/libast/tm/tmequiv.c
new file mode 100644
index 0000000..4ab07c9
--- /dev/null
+++ b/src/lib/libast/tm/tmequiv.c
@@ -0,0 +1,57 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time_t conversion support
+ */
+
+#include <tm.h>
+
+/*
+ * use one of the 14 equivalent calendar years to determine
+ * daylight savings time for future years beyond the range
+ * of the local system (via tmxtm())
+ */
+
+static const short equiv[] =
+{
+ 2006, 2012,
+ 2001, 2024,
+ 2002, 2008,
+ 2003, 2020,
+ 2009, 2004,
+ 2010, 2016,
+ 2005, 2000,
+};
+
+/*
+ * return the circa 2000 equivalent calendar year for tm
+ */
+
+int
+tmequiv(Tm_t* tm)
+{
+ return tm->tm_year < (2038 - 1900) ? (tm->tm_year + 1900) : equiv[tm->tm_wday + tmisleapyear(tm->tm_year)];
+}
diff --git a/src/lib/libast/tm/tmfix.c b/src/lib/libast/tm/tmfix.c
new file mode 100644
index 0000000..5425a8b
--- /dev/null
+++ b/src/lib/libast/tm/tmfix.c
@@ -0,0 +1,173 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time conversion support
+ */
+
+#include <ast.h>
+#include <tmx.h>
+
+#define DAYS(p) (tm_data.days[(p)->tm_mon]+((p)->tm_mon==1&&LEAP(p)))
+#define LEAP(p) (tmisleapyear((p)->tm_year))
+
+/*
+ * correct out of bounds fields in tm
+ *
+ * tm_isdst is not changed -- call tmxtm() to get that
+ *
+ * tm is the return value
+ */
+
+Tm_t*
+tmfix(register Tm_t* tm)
+{
+ register int n;
+ register int w;
+ Tm_t* p;
+ time_t t;
+
+ /*
+ * check for special case that adjusts tm_wday at the end
+ * this happens during
+ * nl_langinfo() => strftime() => tmfmt()
+ */
+
+ if (w = !tm->tm_sec && !tm->tm_min && !tm->tm_mday && !tm->tm_year && !tm->tm_yday && !tm->tm_isdst)
+ {
+ tm->tm_year = 99;
+ tm->tm_mday = 2;
+ }
+
+ /*
+ * adjust from shortest to longest units
+ */
+
+ if ((n = tm->tm_nsec) < 0)
+ {
+ tm->tm_sec -= (TMX_RESOLUTION - n) / TMX_RESOLUTION;
+ tm->tm_nsec = TMX_RESOLUTION - (-n) % TMX_RESOLUTION;
+ }
+ else if (n >= TMX_RESOLUTION)
+ {
+ tm->tm_sec += n / TMX_RESOLUTION;
+ tm->tm_nsec %= TMX_RESOLUTION;
+ }
+ if ((n = tm->tm_sec) < 0)
+ {
+ tm->tm_min -= (60 - n) / 60;
+ tm->tm_sec = 60 - (-n) % 60;
+ }
+ else if (n > (59 + TM_MAXLEAP))
+ {
+ tm->tm_min += n / 60;
+ tm->tm_sec %= 60;
+ }
+ if ((n = tm->tm_min) < 0)
+ {
+ tm->tm_hour -= (60 - n) / 60;
+ n = tm->tm_min = 60 - (-n) % 60;
+ }
+ if (n > 59)
+ {
+ tm->tm_hour += n / 60;
+ tm->tm_min %= 60;
+ }
+ if ((n = tm->tm_hour) < 0)
+ {
+ tm->tm_mday -= (23 - n) / 24;
+ tm->tm_hour = 24 - (-n) % 24;
+ }
+ else if (n >= 24)
+ {
+ tm->tm_mday += n / 24;
+ tm->tm_hour %= 24;
+ }
+ if (tm->tm_mon >= 12)
+ {
+ tm->tm_year += tm->tm_mon / 12;
+ tm->tm_mon %= 12;
+ }
+ else if (tm->tm_mon < 0)
+ {
+ tm->tm_year--;
+ if ((tm->tm_mon += 12) < 0)
+ {
+ tm->tm_year += tm->tm_mon / 12;
+ tm->tm_mon = (-tm->tm_mon) % 12;
+ }
+ }
+ while (tm->tm_mday < -365)
+ {
+ tm->tm_year--;
+ tm->tm_mday += 365 + LEAP(tm);
+ }
+ while (tm->tm_mday > 365)
+ {
+ tm->tm_mday -= 365 + LEAP(tm);
+ tm->tm_year++;
+ }
+ while (tm->tm_mday < 1)
+ {
+ if (--tm->tm_mon < 0)
+ {
+ tm->tm_mon = 11;
+ tm->tm_year--;
+ }
+ tm->tm_mday += DAYS(tm);
+ }
+ while (tm->tm_mday > (n = DAYS(tm)))
+ {
+ tm->tm_mday -= n;
+ if (++tm->tm_mon > 11)
+ {
+ tm->tm_mon = 0;
+ tm->tm_year++;
+ }
+ }
+ if (w)
+ {
+ w = tm->tm_wday;
+ t = tmtime(tm, TM_LOCALZONE);
+ p = tmmake(&t);
+ if (w = (w - p->tm_wday))
+ {
+ if (w < 0)
+ w += 7;
+ tm->tm_wday += w;
+ if ((tm->tm_mday += w) > DAYS(tm))
+ tm->tm_mday -= 7;
+ }
+ }
+ tm->tm_yday = tm_data.sum[tm->tm_mon] + (tm->tm_mon > 1 && LEAP(tm)) + tm->tm_mday - 1;
+ n = tm->tm_year + 1900 - 1;
+ tm->tm_wday = (n + n / 4 - n / 100 + n / 400 + tm->tm_yday + 1) % 7;
+
+ /*
+ * tm_isdst is adjusted by tmtime()
+ */
+
+ return tm;
+}
diff --git a/src/lib/libast/tm/tmfmt.c b/src/lib/libast/tm/tmfmt.c
new file mode 100644
index 0000000..dda0ed0
--- /dev/null
+++ b/src/lib/libast/tm/tmfmt.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time conversion support
+ */
+
+#include <tmx.h>
+
+/*
+ * format date given clock into buf of length len
+ * see tmxfmt() for details
+ */
+
+char*
+tmfmt(char* buf, size_t len, const char* format, time_t* clock)
+{
+ return tmxfmt(buf, len, format, tmxclock(clock));
+}
diff --git a/src/lib/libast/tm/tmform.c b/src/lib/libast/tm/tmform.c
new file mode 100644
index 0000000..4b608c8
--- /dev/null
+++ b/src/lib/libast/tm/tmform.c
@@ -0,0 +1,44 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * OBSOLETE: use tmfmt() instead
+ *
+ * time conversion support
+ */
+
+#include <ast.h>
+#include <tm.h>
+
+/*
+ * format date given clock
+ * end of buf is returned
+ */
+
+char*
+tmform(char* buf, const char* format, time_t* clock)
+{
+ return tmfmt(buf, 256, format, clock);
+}
diff --git a/src/lib/libast/tm/tmgoff.c b/src/lib/libast/tm/tmgoff.c
new file mode 100644
index 0000000..c8c8d57
--- /dev/null
+++ b/src/lib/libast/tm/tmgoff.c
@@ -0,0 +1,77 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * time conversion support
+ */
+
+#include <ast.h>
+#include <tm.h>
+#include <ctype.h>
+
+/*
+ * return minutes offset from absolute timezone expression
+ *
+ * [[-+]hh[:mm[:ss]]]
+ * [-+]hhmm
+ *
+ * if e is non-null then it points to the first unrecognized char in s
+ * d returned if no offset in s
+ */
+
+int
+tmgoff(register const char* s, char** e, int d)
+{
+ register int n = d;
+ int east;
+ const char* t = s;
+
+ if ((east = *s == '+') || *s == '-')
+ {
+ s++;
+ if (isdigit(*s) && isdigit(*(s + 1)))
+ {
+ n = ((*s - '0') * 10 + (*(s + 1) - '0')) * 60;
+ s += 2;
+ if (*s == ':')
+ s++;
+ if (isdigit(*s) && isdigit(*(s + 1)))
+ {
+ n += ((*s - '0') * 10 + (*(s + 1) - '0'));
+ s += 2;
+ if (*s == ':')
+ s++;
+ if (isdigit(*s) && isdigit(*(s + 1)))
+ s += 2;
+ }
+ if (east)
+ n = -n;
+ t = s;
+ }
+ }
+ if (e)
+ *e = (char*)t;
+ return n;
+}
diff --git a/src/lib/libast/tm/tminit.c b/src/lib/libast/tm/tminit.c
new file mode 100644
index 0000000..1918861
--- /dev/null
+++ b/src/lib/libast/tm/tminit.c
@@ -0,0 +1,460 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time conversion support
+ */
+
+#include <tm.h>
+#include <ctype.h>
+#include <namval.h>
+
+#include "FEATURE/tmlib"
+
+#ifndef tzname
+# if defined(__DYNAMIC__)
+# undef _dat_tzname
+# define tzname __DYNAMIC__(tzname)
+# else
+# if !_dat_tzname
+# if _dat__tzname
+# undef _dat_tzname
+# define _dat_tzname 1
+# define tzname _tzname
+# endif
+# endif
+# endif
+# if _dat_tzname && !defined(tzname)
+ extern char* tzname[];
+# endif
+#endif
+
+#define TM_type (-1)
+
+static const Namval_t options[] =
+{
+ "adjust", TM_ADJUST,
+ "format", TM_DEFAULT,
+ "leap", TM_LEAP,
+ "subsecond", TM_SUBSECOND,
+ "type", TM_type,
+ "utc", TM_UTC,
+ 0, 0
+};
+
+/*
+ * 2007-03-19 move tm_info from _tm_info_ to (*_tm_infop_)
+ * to allow future Tm_info_t growth
+ * by 2009 _tm_info_ can be static
+ */
+
+#if _BLD_ast && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+
+extern Tm_info_t _tm_info_;
+
+#undef extern
+
+Tm_info_t _tm_info_ = { 0 };
+
+__EXTERN__(Tm_info_t, _tm_info_);
+
+__EXTERN__(Tm_info_t*, _tm_infop_);
+
+Tm_info_t* _tm_infop_ = &_tm_info_;
+
+#if _tzset_environ
+
+static char TZ[256];
+static char* TE[2];
+
+struct tm*
+_tm_localtime(const time_t* t)
+{
+ struct tm* r;
+ char* e;
+ char** v = environ;
+
+ if (TZ[0])
+ {
+ if (!environ || !*environ)
+ environ = TE;
+ else
+ e = environ[0];
+ environ[0] = TZ;
+ }
+ r = localtime(t);
+ if (TZ[0])
+ {
+ if (environ != v)
+ environ = v;
+ else
+ environ[0] = e;
+ }
+ return r;
+}
+
+#endif
+
+/*
+ * return minutes west of GMT for local time clock
+ *
+ * isdst will point to non-zero if DST is in effect
+ * this routine also kicks in the local initialization
+ */
+
+static int
+tzwest(time_t* clock, int* isdst)
+{
+ register struct tm* tp;
+ register int n;
+ register int m;
+ int h;
+ time_t epoch;
+
+ /*
+ * convert to GMT assuming local time
+ */
+
+ if (!(tp = gmtime(clock)))
+ {
+ /*
+ * some systems return 0 for negative time_t
+ */
+
+ epoch = 0;
+ clock = &epoch;
+ tp = gmtime(clock);
+ }
+ n = tp->tm_yday;
+ h = tp->tm_hour;
+ m = tp->tm_min;
+
+ /*
+ * tmlocaltime() handles DST and GMT offset
+ */
+
+ tp = tmlocaltime(clock);
+ if (n = tp->tm_yday - n)
+ {
+ if (n > 1)
+ n = -1;
+ else if (n < -1)
+ n = 1;
+ }
+ *isdst = tp->tm_isdst;
+ return (h - tp->tm_hour - n * 24) * 60 + m - tp->tm_min;
+}
+
+/*
+ * stropt() option handler
+ */
+
+static int
+tmopt(void* a, const void* p, int n, const char* v)
+{
+ Tm_zone_t* zp;
+
+ NoP(a);
+ if (p)
+ switch (((Namval_t*)p)->value)
+ {
+ case TM_DEFAULT:
+ tm_info.deformat = (n && (n = strlen(v)) > 0 && (n < 2 || v[n-2] != '%' || v[n-1] != '?')) ? strdup(v) : tm_info.format[TM_DEFAULT];
+ break;
+ case TM_type:
+ tm_info.local->type = (n && *v) ? ((zp = tmtype(v, NiL)) ? zp->type : strdup(v)) : 0;
+ break;
+ default:
+ if (n)
+ tm_info.flags |= ((Namval_t*)p)->value;
+ else
+ tm_info.flags &= ~((Namval_t*)p)->value;
+ break;
+ }
+ return 0;
+}
+
+/*
+ * initialize the local timezone
+ */
+
+static void
+tmlocal(void)
+{
+ register Tm_zone_t* zp;
+ register int n;
+ register char* s;
+ register char* e;
+ int i;
+ int m;
+ int isdst;
+ char* t;
+ struct tm* tp;
+ time_t now;
+ char buf[16];
+
+ static Tm_zone_t local;
+
+#if _tzset_environ
+ {
+ char** v = environ;
+
+ if (s = getenv("TZ"))
+ {
+ sfsprintf(TZ, sizeof(TZ), "TZ=%s", s);
+ if (!environ || !*environ)
+ environ = TE;
+ else
+ e = environ[0];
+ environ[0] = TZ;
+ }
+ else
+ {
+ TZ[0] = 0;
+ e = 0;
+ }
+#endif
+#if _lib_tzset
+ tzset();
+#endif
+#if _tzset_environ
+ if (environ != v)
+ environ = v;
+ else if (e)
+ environ[0] = e;
+ }
+#endif
+#if _dat_tzname
+ local.standard = strdup(tzname[0]);
+ local.daylight = strdup(tzname[1]);
+#endif
+ tmlocale();
+
+ /*
+ * tm_info.local
+ */
+
+ tm_info.zone = tm_info.local = &local;
+ time(&now);
+ n = tzwest(&now, &isdst);
+
+ /*
+ * compute local DST offset by roaming
+ * through the last 12 months until tzwest() changes
+ */
+
+ for (i = 0; i < 12; i++)
+ {
+ now -= 31 * 24 * 60 * 60;
+ if ((m = tzwest(&now, &isdst)) != n)
+ {
+ if (!isdst)
+ {
+ isdst = n;
+ n = m;
+ m = isdst;
+ }
+ m -= n;
+ break;
+ }
+ }
+ local.west = n;
+ local.dst = m;
+
+ /*
+ * now get the time zone names
+ */
+
+#if _dat_tzname
+ if (tzname[0])
+ {
+ /*
+ * POSIX
+ */
+
+ if (!local.standard)
+ local.standard = strdup(tzname[0]);
+ if (!local.daylight)
+ local.daylight = strdup(tzname[1]);
+ }
+ else
+#endif
+ if ((s = getenv("TZNAME")) && *s && (s = strdup(s)))
+ {
+ /*
+ * BSD
+ */
+
+ local.standard = s;
+ if (s = strchr(s, ','))
+ *s++ = 0;
+ else
+ s = "";
+ local.daylight = s;
+ }
+ else if ((s = getenv("TZ")) && *s && *s != ':' && (s = strdup(s)))
+ {
+ /*
+ * POSIX style but skipped by tmlocaltime()
+ */
+
+ local.standard = s;
+ if (*++s && *++s && *++s)
+ {
+ *s++ = 0;
+ tmgoff(s, &t, 0);
+ for (s = t; isalpha(*t); t++);
+ *t = 0;
+ }
+ else
+ s = "";
+ local.daylight = s;
+ }
+ else
+ {
+ /*
+ * tm_data.zone table lookup
+ */
+
+ t = 0;
+ for (zp = tm_data.zone; zp->standard; zp++)
+ {
+ if (zp->type)
+ t = zp->type;
+ if (zp->west == n && zp->dst == m)
+ {
+ local.type = t;
+ local.standard = zp->standard;
+ if (!(s = zp->daylight))
+ {
+ e = (s = buf) + sizeof(buf);
+ s = tmpoff(s, e - s, zp->standard, 0, 0);
+ if (s < e - 1)
+ {
+ *s++ = ' ';
+ tmpoff(s, e - s, tm_info.format[TM_DT], m, TM_DST);
+ }
+ s = strdup(buf);
+ }
+ local.daylight = s;
+ break;
+ }
+ }
+ if (!zp->standard)
+ {
+ /*
+ * not in the table
+ */
+
+ e = (s = buf) + sizeof(buf);
+ s = tmpoff(s, e - s, tm_info.format[TM_UT], n, 0);
+ local.standard = strdup(buf);
+ if (s < e - 1)
+ {
+ *s++ = ' ';
+ tmpoff(s, e - s, tm_info.format[TM_UT], m, TM_DST);
+ local.daylight = strdup(buf);
+ }
+ }
+ }
+
+ /*
+ * set the options
+ */
+
+ stropt(getenv("TM_OPTIONS"), options, sizeof(*options), tmopt, NiL);
+
+ /*
+ * the time zone type is probably related to the locale
+ */
+
+ if (!local.type)
+ {
+ s = local.standard;
+ t = 0;
+ for (zp = tm_data.zone; zp->standard; zp++)
+ {
+ if (zp->type)
+ t = zp->type;
+ if (tmword(s, NiL, zp->standard, NiL, 0))
+ {
+ local.type = t;
+ break;
+ }
+ }
+ }
+
+ /*
+ * tm_info.flags
+ */
+
+ if (!(tm_info.flags & TM_ADJUST))
+ {
+ now = (time_t)78811200; /* Jun 30 1972 23:59:60 */
+ tp = tmlocaltime(&now);
+ if (tp->tm_sec != 60)
+ tm_info.flags |= TM_ADJUST;
+ }
+ if (!(tm_info.flags & TM_UTC))
+ {
+ s = local.standard;
+ zp = tm_data.zone;
+ if (local.daylight)
+ zp++;
+ for (; !zp->type && zp->standard; zp++)
+ if (tmword(s, NiL, zp->standard, NiL, 0))
+ {
+ tm_info.flags |= TM_UTC;
+ break;
+ }
+ }
+}
+
+/*
+ * initialize tm data
+ */
+
+void
+tminit(register Tm_zone_t* zp)
+{
+ static uint32_t serial = ~(uint32_t)0;
+
+ if (serial != ast.env_serial)
+ {
+ serial = ast.env_serial;
+ if (tm_info.local)
+ {
+ memset(tm_info.local, 0, sizeof(*tm_info.local));
+ tm_info.local = 0;
+ }
+ }
+ if (!tm_info.local)
+ tmlocal();
+ if (!zp)
+ zp = tm_info.local;
+ tm_info.zone = zp;
+}
diff --git a/src/lib/libast/tm/tmleap.c b/src/lib/libast/tm/tmleap.c
new file mode 100644
index 0000000..87c2f04
--- /dev/null
+++ b/src/lib/libast/tm/tmleap.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time conversion support
+ */
+
+#include <tmx.h>
+
+/*
+ * return clock with leap seconds adjusted
+ * see tmxleap() for details
+ */
+
+time_t
+tmleap(register time_t* clock)
+{
+ return tmxsec(tmxleap(tmxclock(clock)));
+}
diff --git a/src/lib/libast/tm/tmlex.c b/src/lib/libast/tm/tmlex.c
new file mode 100644
index 0000000..4bcd864
--- /dev/null
+++ b/src/lib/libast/tm/tmlex.c
@@ -0,0 +1,67 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * time conversion support
+ */
+
+#include <ast.h>
+#include <tm.h>
+#include <ctype.h>
+
+/*
+ * return the tab table index that matches s ignoring case and .'s
+ * tm_data.format checked if tminfo.format!=tm_data.format
+ *
+ * ntab and nsuf are the number of elements in tab and suf,
+ * -1 for 0 sentinel
+ *
+ * all isalpha() chars in str must match
+ * suf is a table of nsuf valid str suffixes
+ * if e is non-null then it will point to first unmatched char in str
+ * which will always be non-isalpha()
+ */
+
+int
+tmlex(register const char* s, char** e, char** tab, int ntab, char** suf, int nsuf)
+{
+ register char** p;
+ register char* x;
+ register int n;
+
+ for (p = tab, n = ntab; n-- && (x = *p); p++)
+ if (*x && *x != '%' && tmword(s, e, x, suf, nsuf))
+ return p - tab;
+ if (tm_info.format != tm_data.format && tab >= tm_info.format && tab < tm_info.format + TM_NFORM)
+ {
+ tab = tm_data.format + (tab - tm_info.format);
+ if (suf && tab >= tm_info.format && tab < tm_info.format + TM_NFORM)
+ suf = tm_data.format + (suf - tm_info.format);
+ for (p = tab, n = ntab; n-- && (x = *p); p++)
+ if (*x && *x != '%' && tmword(s, e, x, suf, nsuf))
+ return p - tab;
+ }
+ return -1;
+}
diff --git a/src/lib/libast/tm/tmlocale.c b/src/lib/libast/tm/tmlocale.c
new file mode 100644
index 0000000..98dafdb
--- /dev/null
+++ b/src/lib/libast/tm/tmlocale.c
@@ -0,0 +1,644 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time conversion translation support
+ */
+
+#include <ast.h>
+#include <cdt.h>
+#include <iconv.h>
+#include <mc.h>
+#include <tm.h>
+#include <ast_nl_types.h>
+
+#include "lclib.h"
+
+static struct
+{
+ char* format;
+ Lc_info_t* locale;
+ char null[1];
+} state;
+
+/*
+ * this is unix dadgummit
+ */
+
+static int
+standardized(Lc_info_t* li, register char** b)
+{
+ if ((li->lc->language->flags & (LC_debug|LC_default)) || streq(li->lc->language->code, "en"))
+ {
+ b[TM_TIME] = "%H:%M:%S";
+ b[TM_DATE] = "%m/%d/%y";
+ b[TM_DEFAULT] = "%a %b %e %T %Z %Y";
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * fix up LC_TIME data after loading
+ */
+
+static void
+fixup(Lc_info_t* li, register char** b)
+{
+ register char** v;
+ register char** e;
+ register int n;
+
+ static int must[] =
+ {
+ TM_TIME,
+ TM_DATE,
+ TM_DEFAULT,
+ TM_MERIDIAN,
+ TM_UT,
+ TM_DT,
+ TM_SUFFIXES,
+ TM_PARTS,
+ TM_HOURS,
+ TM_DAYS,
+ TM_LAST,
+ TM_THIS,
+ TM_NEXT,
+ TM_EXACT,
+ TM_NOISE,
+ TM_ORDINAL,
+ TM_CTIME,
+ TM_DATE_1,
+ TM_INTERNATIONAL,
+ TM_RECENT,
+ TM_DISTANT,
+ TM_MERIDIAN_TIME,
+ TM_ORDINALS,
+ TM_FINAL,
+ TM_WORK,
+ };
+
+ standardized(li, b);
+ for (v = b, e = b + TM_NFORM; v < e; v++)
+ if (!*v)
+ *v = state.null;
+ for (n = 0; n < elementsof(must); n++)
+ if (!*b[must[n]])
+ b[must[n]] = tm_data.format[must[n]];
+ if (li->lc->flags & LC_default)
+ for (n = 0; n < TM_NFORM; n++)
+ if (!*b[n])
+ b[n] = tm_data.format[n];
+ if (strchr(b[TM_UT], '%'))
+ {
+ tm_info.deformat = b[TM_UT];
+ for (n = TM_UT; n < TM_DT; n++)
+ b[n] = state.null;
+ }
+ else
+ tm_info.deformat = b[TM_DEFAULT];
+ tm_info.format = b;
+ if (!(tm_info.deformat = state.format))
+ tm_info.deformat = tm_info.format[TM_DEFAULT];
+ li->data = (void*)b;
+}
+
+#if _WINIX
+
+#include <ast_windows.h>
+
+typedef struct Map_s
+{
+ LCID native;
+ int local;
+} Map_t;
+
+static const Map_t map[] =
+{
+ LOCALE_S1159, (TM_MERIDIAN+0),
+ LOCALE_S2359, (TM_MERIDIAN+1),
+ LOCALE_SABBREVDAYNAME1, (TM_DAY_ABBREV+1),
+ LOCALE_SABBREVDAYNAME2, (TM_DAY_ABBREV+2),
+ LOCALE_SABBREVDAYNAME3, (TM_DAY_ABBREV+3),
+ LOCALE_SABBREVDAYNAME4, (TM_DAY_ABBREV+4),
+ LOCALE_SABBREVDAYNAME5, (TM_DAY_ABBREV+5),
+ LOCALE_SABBREVDAYNAME6, (TM_DAY_ABBREV+6),
+ LOCALE_SABBREVDAYNAME7, (TM_DAY_ABBREV+0),
+ LOCALE_SABBREVMONTHNAME1, (TM_MONTH_ABBREV+0),
+ LOCALE_SABBREVMONTHNAME2, (TM_MONTH_ABBREV+1),
+ LOCALE_SABBREVMONTHNAME3, (TM_MONTH_ABBREV+2),
+ LOCALE_SABBREVMONTHNAME4, (TM_MONTH_ABBREV+3),
+ LOCALE_SABBREVMONTHNAME5, (TM_MONTH_ABBREV+4),
+ LOCALE_SABBREVMONTHNAME6, (TM_MONTH_ABBREV+5),
+ LOCALE_SABBREVMONTHNAME7, (TM_MONTH_ABBREV+6),
+ LOCALE_SABBREVMONTHNAME8, (TM_MONTH_ABBREV+7),
+ LOCALE_SABBREVMONTHNAME9, (TM_MONTH_ABBREV+8),
+ LOCALE_SABBREVMONTHNAME10, (TM_MONTH_ABBREV+9),
+ LOCALE_SABBREVMONTHNAME11, (TM_MONTH_ABBREV+10),
+ LOCALE_SABBREVMONTHNAME12, (TM_MONTH_ABBREV+11),
+ LOCALE_SDAYNAME1, (TM_DAY+1),
+ LOCALE_SDAYNAME2, (TM_DAY+2),
+ LOCALE_SDAYNAME3, (TM_DAY+3),
+ LOCALE_SDAYNAME4, (TM_DAY+4),
+ LOCALE_SDAYNAME5, (TM_DAY+5),
+ LOCALE_SDAYNAME6, (TM_DAY+6),
+ LOCALE_SDAYNAME7, (TM_DAY+0),
+ LOCALE_SMONTHNAME1, (TM_MONTH+0),
+ LOCALE_SMONTHNAME2, (TM_MONTH+1),
+ LOCALE_SMONTHNAME3, (TM_MONTH+2),
+ LOCALE_SMONTHNAME4, (TM_MONTH+3),
+ LOCALE_SMONTHNAME5, (TM_MONTH+4),
+ LOCALE_SMONTHNAME6, (TM_MONTH+5),
+ LOCALE_SMONTHNAME7, (TM_MONTH+6),
+ LOCALE_SMONTHNAME8, (TM_MONTH+7),
+ LOCALE_SMONTHNAME9, (TM_MONTH+8),
+ LOCALE_SMONTHNAME10, (TM_MONTH+9),
+ LOCALE_SMONTHNAME11, (TM_MONTH+10),
+ LOCALE_SMONTHNAME12, (TM_MONTH+11),
+};
+
+#undef extern
+
+/*
+ * convert ms word date spec w to posix strftime format f
+ * next char after f returned
+ * the caller already made sure f is big enough
+ */
+
+static char*
+word2posix(register char* f, register char* w, int alternate)
+{
+ register char* r;
+ register int c;
+ register int p;
+ register int n;
+
+ while (*w)
+ {
+ p = 0;
+ r = w;
+ while (*++w == *r);
+ if ((n = w - r) > 3 && alternate)
+ n--;
+ switch (*r)
+ {
+ case 'a':
+ case 'A':
+ if (!strncasecmp(w, "am/pm", 5))
+ w += 5;
+ else if (!strncasecmp(w, "a/p", 3))
+ w += 3;
+ c = 'p';
+ break;
+ case 'd':
+ switch (n)
+ {
+ case 1:
+ p = '-';
+ /*FALLTHROUGH*/
+ case 2:
+ c = 'd';
+ break;
+ case 3:
+ c = 'a';
+ break;
+ default:
+ c = 'A';
+ break;
+ }
+ break;
+ case 'h':
+ switch (n)
+ {
+ case 1:
+ p = '-';
+ /*FALLTHROUGH*/
+ default:
+ c = 'I';
+ break;
+ }
+ break;
+ case 'H':
+ switch (n)
+ {
+ case 1:
+ p = '-';
+ /*FALLTHROUGH*/
+ default:
+ c = 'H';
+ break;
+ }
+ break;
+ case 'M':
+ switch (n)
+ {
+ case 1:
+ p = '-';
+ /*FALLTHROUGH*/
+ case 2:
+ c = 'm';
+ break;
+ case 3:
+ c = 'b';
+ break;
+ default:
+ c = 'B';
+ break;
+ }
+ break;
+ case 'm':
+ switch (n)
+ {
+ case 1:
+ p = '-';
+ /*FALLTHROUGH*/
+ default:
+ c = 'M';
+ break;
+ }
+ break;
+ case 's':
+ switch (n)
+ {
+ case 1:
+ p = '-';
+ /*FALLTHROUGH*/
+ default:
+ c = 'S';
+ break;
+ }
+ break;
+ case 'y':
+ switch (n)
+ {
+ case 1:
+ p = '-';
+ /*FALLTHROUGH*/
+ case 2:
+ c = 'y';
+ break;
+ default:
+ c = 'Y';
+ break;
+ }
+ break;
+ case '\'':
+ if (n & 1)
+ for (w = r + 1; *w; *f++ = *w++)
+ if (*w == '\'')
+ {
+ w++;
+ break;
+ }
+ continue;
+ case '%':
+ while (r < w)
+ {
+ *f++ = *r++;
+ *f++ = *r++;
+ }
+ continue;
+ default:
+ while (r < w)
+ *f++ = *r++;
+ continue;
+ }
+ *f++ = '%';
+ if (p)
+ *f++ = '-';
+ *f++ = c;
+ }
+ *f++ = 0;
+ return f;
+}
+
+/*
+ * load the native LC_TIME data for the current locale
+ */
+
+static void
+native_lc_time(Lc_info_t* li)
+{
+ register char* s;
+ register char* t;
+ register char** b;
+ register int n;
+ register int m;
+ register int i;
+ LCID lcid;
+ int nt;
+ int ns;
+ int nl;
+ int clock_24;
+ int leading_0;
+ char buf[256];
+
+ lcid = li->lc->index;
+ nt = 2 * GetLocaleInfo(lcid, LOCALE_STIME, 0, 0) + 7; /* HH:MM:SS */
+ ns = 3 * GetLocaleInfo(lcid, LOCALE_SSHORTDATE, 0, 0);
+ nl = 3 * GetLocaleInfo(lcid, LOCALE_SLONGDATE, 0, 0);
+ n = nt + ns + nl;
+ for (i = 0; i < elementsof(map); i++)
+ n += GetLocaleInfo(lcid, map[i].native, 0, 0);
+ if (!(b = newof(0, char*, TM_NFORM, n)))
+ return;
+ s = (char*)(b + TM_NFORM);
+ for (i = 0; i < elementsof(map); i++)
+ {
+ if (!(m = GetLocaleInfo(lcid, map[i].native, s, n)))
+ goto bad;
+ b[map[i].local] = s;
+ s += m;
+ }
+ if (!standardized(li, b))
+ {
+ /*
+ * synthesize TM_TIME format from the ms word template
+ */
+
+ if (!GetLocaleInfo(lcid, LOCALE_ITIME, buf, sizeof(buf)))
+ goto bad;
+ clock_24 = atoi(buf);
+ if (!GetLocaleInfo(lcid, LOCALE_ITLZERO, buf, sizeof(buf)))
+ goto bad;
+ leading_0 = atoi(buf);
+ if (!GetLocaleInfo(lcid, LOCALE_STIME, buf, sizeof(buf)))
+ goto bad;
+ b[TM_TIME] = s;
+ *s++ = '%';
+ if (!leading_0)
+ *s++ = '-';
+ *s++ = clock_24 ? 'H' : 'I';
+ for (t = buf; *s = *t++; s++);
+ *s++ = '%';
+ if (!leading_0)
+ *s++ = '-';
+ *s++ = 'M';
+ for (t = buf; *s = *t++; s++);
+ *s++ = '%';
+ if (!leading_0)
+ *s++ = '-';
+ *s++ = 'S';
+ *s++ = 0;
+
+ /*
+ * synthesize TM_DATE format
+ */
+
+ if (!GetLocaleInfo(lcid, LOCALE_SSHORTDATE, buf, sizeof(buf)))
+ goto bad;
+ b[TM_DATE] = s;
+ s = word2posix(s, buf, 1);
+
+ /*
+ * synthesize TM_DEFAULT format
+ */
+
+ if (!GetLocaleInfo(lcid, LOCALE_SLONGDATE, buf, sizeof(buf)))
+ goto bad;
+ b[TM_DEFAULT] = s;
+ s = word2posix(s, buf, 1);
+ strcpy(s - 1, " %X");
+ }
+
+ /*
+ * done
+ */
+
+ fixup(li, b);
+ return;
+ bad:
+ free(b);
+}
+
+#else
+
+#if _lib_nl_langinfo && _hdr_langinfo
+
+#if _hdr_nl_types
+#include <nl_types.h>
+#endif
+
+#include <langinfo.h>
+
+typedef struct Map_s
+{
+ int native;
+ int local;
+} Map_t;
+
+static const Map_t map[] =
+{
+ AM_STR, (TM_MERIDIAN+0),
+ PM_STR, (TM_MERIDIAN+1),
+ ABDAY_1, (TM_DAY_ABBREV+0),
+ ABDAY_2, (TM_DAY_ABBREV+1),
+ ABDAY_3, (TM_DAY_ABBREV+2),
+ ABDAY_4, (TM_DAY_ABBREV+3),
+ ABDAY_5, (TM_DAY_ABBREV+4),
+ ABDAY_6, (TM_DAY_ABBREV+5),
+ ABDAY_7, (TM_DAY_ABBREV+6),
+ ABMON_1, (TM_MONTH_ABBREV+0),
+ ABMON_2, (TM_MONTH_ABBREV+1),
+ ABMON_3, (TM_MONTH_ABBREV+2),
+ ABMON_4, (TM_MONTH_ABBREV+3),
+ ABMON_5, (TM_MONTH_ABBREV+4),
+ ABMON_6, (TM_MONTH_ABBREV+5),
+ ABMON_7, (TM_MONTH_ABBREV+6),
+ ABMON_8, (TM_MONTH_ABBREV+7),
+ ABMON_9, (TM_MONTH_ABBREV+8),
+ ABMON_10, (TM_MONTH_ABBREV+9),
+ ABMON_11, (TM_MONTH_ABBREV+10),
+ ABMON_12, (TM_MONTH_ABBREV+11),
+ DAY_1, (TM_DAY+0),
+ DAY_2, (TM_DAY+1),
+ DAY_3, (TM_DAY+2),
+ DAY_4, (TM_DAY+3),
+ DAY_5, (TM_DAY+4),
+ DAY_6, (TM_DAY+5),
+ DAY_7, (TM_DAY+6),
+ MON_1, (TM_MONTH+0),
+ MON_2, (TM_MONTH+1),
+ MON_3, (TM_MONTH+2),
+ MON_4, (TM_MONTH+3),
+ MON_5, (TM_MONTH+4),
+ MON_6, (TM_MONTH+5),
+ MON_7, (TM_MONTH+6),
+ MON_8, (TM_MONTH+7),
+ MON_9, (TM_MONTH+8),
+ MON_10, (TM_MONTH+9),
+ MON_11, (TM_MONTH+10),
+ MON_12, (TM_MONTH+11),
+#ifdef _DATE_FMT
+ _DATE_FMT, TM_DEFAULT,
+#else
+ D_T_FMT, TM_DEFAULT,
+#endif
+ D_FMT, TM_DATE,
+ T_FMT, TM_TIME,
+#ifdef ERA
+ ERA, TM_ERA,
+ ERA_D_T_FMT, TM_ERA_DEFAULT,
+ ERA_D_FMT, TM_ERA_DATE,
+ ERA_T_FMT, TM_ERA_TIME,
+#endif
+#ifdef ALT_DIGITS
+ ALT_DIGITS, TM_DIGITS,
+#endif
+};
+
+static void
+native_lc_time(Lc_info_t* li)
+{
+ register char* s;
+ register char* t;
+ register char** b;
+ register int n;
+ register int i;
+
+ n = 0;
+ for (i = 0; i < elementsof(map); i++)
+ {
+ if (!(t = nl_langinfo(map[i].native)))
+ t = tm_data.format[map[i].local];
+ n += strlen(t) + 1;
+ }
+ if (!(b = newof(0, char*, TM_NFORM, n)))
+ return;
+ s = (char*)(b + TM_NFORM);
+ for (i = 0; i < elementsof(map); i++)
+ {
+ b[map[i].local] = s;
+ if (!(t = nl_langinfo(map[i].native)))
+ t = tm_data.format[map[i].local];
+ while (*s++ = *t++);
+ }
+ fixup(li, b);
+}
+
+#else
+
+#define native_lc_time(li) ((li->data=(void*)(tm_info.format=tm_data.format)),(tm_info.deformat=tm_info.format[TM_DEFAULT]))
+
+#endif
+
+#endif
+
+/*
+ * load the LC_TIME data for the current locale
+ */
+
+static void
+load(Lc_info_t* li)
+{
+ register char* s;
+ register char** b;
+ register char** v;
+ register char** e;
+ unsigned char* u;
+ ssize_t n;
+ iconv_t cvt;
+ Sfio_t* sp;
+ Sfio_t* tp;
+ char path[PATH_MAX];
+
+ if (b = (char**)li->data)
+ {
+ tm_info.format = b;
+ if (!(tm_info.deformat = state.format))
+ tm_info.deformat = tm_info.format[TM_DEFAULT];
+ return;
+ }
+ tm_info.format = tm_data.format;
+ if (!(tm_info.deformat = state.format))
+ tm_info.deformat = tm_info.format[TM_DEFAULT];
+ if (mcfind(NiL, NiL, LC_TIME, 0, path, sizeof(path)) && (sp = sfopen(NiL, path, "r")))
+ {
+ n = sfsize(sp);
+ tp = 0;
+ if (u = (unsigned char*)sfreserve(sp, 3, 1))
+ {
+ if (u[0] == 0xef && u[1] == 0xbb && u[2] == 0xbf && (cvt = iconv_open("", "utf")) != (iconv_t)(-1))
+ {
+ if (tp = sfstropen())
+ {
+ sfread(sp, u, 3);
+ n = iconv_move(cvt, sp, tp, SF_UNBOUND, NiL);
+ }
+ iconv_close(cvt);
+ }
+ if (!tp)
+ sfread(sp, u, 0);
+ }
+ if (b = newof(0, char*, TM_NFORM, n + 2))
+ {
+ v = b;
+ e = b + TM_NFORM;
+ s = (char*)e;
+ if (tp && memcpy(s, sfstrbase(tp), n) || !tp && sfread(sp, s, n) == n)
+ {
+ s[n] = '\n';
+ while (v < e)
+ {
+ *v++ = s;
+ if (!(s = strchr(s, '\n')))
+ break;
+ *s++ = 0;
+ }
+ fixup(li, b);
+ }
+ else
+ free(b);
+ }
+ if (tp)
+ sfclose(tp);
+ sfclose(sp);
+ }
+ else
+ native_lc_time(li);
+}
+
+/*
+ * check that tm_info.format matches the current locale
+ */
+
+char**
+tmlocale(void)
+{
+ Lc_info_t* li;
+
+ if (!tm_info.format)
+ {
+ tm_info.format = tm_data.format;
+ if (!tm_info.deformat)
+ tm_info.deformat = tm_info.format[TM_DEFAULT];
+ else if (tm_info.deformat != tm_info.format[TM_DEFAULT])
+ state.format = tm_info.deformat;
+ }
+ li = LCINFO(AST_LC_TIME);
+ if (!li->data)
+ load(li);
+ return tm_info.format;
+}
diff --git a/src/lib/libast/tm/tmmake.c b/src/lib/libast/tm/tmmake.c
new file mode 100644
index 0000000..04e0bed
--- /dev/null
+++ b/src/lib/libast/tm/tmmake.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time conversion support
+ */
+
+#include <tmx.h>
+
+/*
+ * return Tm_t for clock
+ * see tmxmake() for details
+ */
+
+Tm_t*
+tmmake(time_t* clock)
+{
+ return tmxmake(tmxclock(clock));
+}
diff --git a/src/lib/libast/tm/tmpoff.c b/src/lib/libast/tm/tmpoff.c
new file mode 100644
index 0000000..0a25704
--- /dev/null
+++ b/src/lib/libast/tm/tmpoff.c
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * time conversion support
+ */
+
+#include <ast.h>
+#include <tm.h>
+
+/*
+ * n is minutes west of UTC
+ *
+ * append p and SHHMM part of n to s
+ * where S is + or -
+ *
+ * n ignored if n==d
+ * end of s is returned
+ */
+
+char*
+tmpoff(register char* s, size_t z, register const char* p, register int n, int d)
+{
+ register char* e = s + z;
+
+ while (s < e && (*s = *p++))
+ s++;
+ if (n != d && s < e)
+ {
+ if (n < 0)
+ {
+ n = -n;
+ *s++ = '+';
+ }
+ else
+ *s++ = '-';
+ s += sfsprintf(s, e - s, "%02d%s%02d", n / 60, d == -24*60 ? ":" : "", n % 60);
+ }
+ return s;
+}
diff --git a/src/lib/libast/tm/tmscan.c b/src/lib/libast/tm/tmscan.c
new file mode 100644
index 0000000..c2cda80
--- /dev/null
+++ b/src/lib/libast/tm/tmscan.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time conversion support
+ */
+
+#include <tmx.h>
+
+/*
+ * scan date expression in s using format
+ * see tmxscan() for details
+ */
+
+time_t
+tmscan(const char* s, char** e, const char* format, char** f, time_t* clock, long flags)
+{
+ return tmxsec(tmxscan(s, e, format, f, tmxclock(clock), flags));
+}
diff --git a/src/lib/libast/tm/tmsleep.c b/src/lib/libast/tm/tmsleep.c
new file mode 100644
index 0000000..3e4f84e
--- /dev/null
+++ b/src/lib/libast/tm/tmsleep.c
@@ -0,0 +1,42 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * nanosecond resolution sleep
+ */
+
+#include <ast.h>
+#include <tm.h>
+#include <tv.h>
+
+int
+tmsleep(time_t sec, time_t nsec)
+{
+ Tv_t tv;
+
+ tv.tv_sec = sec;
+ tv.tv_nsec = nsec;
+ return tvsleep(&tv, NiL);
+}
diff --git a/src/lib/libast/tm/tmtime.c b/src/lib/libast/tm/tmtime.c
new file mode 100644
index 0000000..086dd5a
--- /dev/null
+++ b/src/lib/libast/tm/tmtime.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time conversion support
+ */
+
+#include <tmx.h>
+
+/*
+ * convert Tm_t to time_t
+ * see tmxtime() for details
+ */
+
+time_t
+tmtime(register Tm_t* tm, int west)
+{
+ return tmxsec(tmxtime(tm, west));
+}
diff --git a/src/lib/libast/tm/tmtype.c b/src/lib/libast/tm/tmtype.c
new file mode 100644
index 0000000..ec45f52
--- /dev/null
+++ b/src/lib/libast/tm/tmtype.c
@@ -0,0 +1,57 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * time conversion support
+ */
+
+#include <ast.h>
+#include <tm.h>
+
+/*
+ * return the tm_data.zone[] time zone entry for type s
+ *
+ * if e is non-null then it will point to the first
+ * unmatched char in s
+ *
+ * 0 returned for no match
+ */
+
+Tm_zone_t*
+tmtype(register const char* s, char** e)
+{
+ register Tm_zone_t* zp;
+ register char* t;
+
+ tmset(tm_info.zone);
+ zp = tm_info.local;
+ do
+ {
+ if ((t = zp->type) && tmword(s, e, t, NiL, 0)) return(zp);
+ if (zp == tm_info.local) zp = tm_data.zone;
+ else zp++;
+ } while (zp->standard);
+ return(0);
+}
diff --git a/src/lib/libast/tm/tmweek.c b/src/lib/libast/tm/tmweek.c
new file mode 100644
index 0000000..78ca98c
--- /dev/null
+++ b/src/lib/libast/tm/tmweek.c
@@ -0,0 +1,87 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * Time_t conversion support
+ */
+
+#include <tmx.h>
+
+static unsigned char offset[7][3] =
+{
+ { 7, 6, 6 },
+ { 1, 7, 7 },
+ { 2, 1, 8 },
+ { 3, 2, 9 },
+ { 4, 3, 10},
+ { 5, 4, 4 },
+ { 6, 5, 5 },
+};
+
+/*
+ * type is week type
+ * 0 sunday first day of week
+ * 1 monday first day of week
+ * 2 monday first day of iso week
+ * if week<0 then return week for tm
+ * if day<0 then set tm to first day of week
+ * otherwise set tm to day in week
+ * and return tm->tm_yday
+ */
+
+int
+tmweek(Tm_t* tm, int type, int week, int day)
+{
+ int d;
+
+ if (week < 0)
+ {
+ if ((day = tm->tm_wday - tm->tm_yday % 7) < 0)
+ day += 7;
+ week = (tm->tm_yday + offset[day][type]) / 7;
+ if (type == 2)
+ {
+ if (!week)
+ week = (day > 0 && day < 6 || tmisleapyear(tm->tm_year - 1)) ? 53 : 52;
+ else if (week == 53 && (tm->tm_wday + (31 - tm->tm_mday)) < 4)
+ week = 1;
+ }
+ return week;
+ }
+ if (day < 0)
+ day = type != 0;
+ tm->tm_mon = 0;
+ tm->tm_mday = 1;
+ tmfix(tm);
+ d = tm->tm_wday;
+ tm->tm_mday = week * 7 - offset[d][type] + ((day || type != 2) ? day : 7);
+ tmfix(tm);
+ if (d = tm->tm_wday - day)
+ {
+ tm->tm_mday -= d;
+ tmfix(tm);
+ }
+ return tm->tm_yday;
+}
diff --git a/src/lib/libast/tm/tmword.c b/src/lib/libast/tm/tmword.c
new file mode 100644
index 0000000..33ce66d
--- /dev/null
+++ b/src/lib/libast/tm/tmword.c
@@ -0,0 +1,89 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * time conversion support
+ */
+
+#include <ast.h>
+#include <tm.h>
+#include <ctype.h>
+
+/*
+ * match s against t ignoring case and .'s
+ *
+ * suf is an n element table of suffixes that may trail s
+ * if all isalpha() chars in s match then 1 is returned
+ * and if e is non-null it will point to the first unmatched
+ * char in s, otherwise 0 is returned
+ */
+
+int
+tmword(register const char* s, char** e, register const char* t, char** suf, int n)
+{
+ register int c;
+ const char* b;
+
+ if (*s && *t)
+ {
+ b = s;
+ while (c = *s++)
+ {
+ if (c != '.')
+ {
+ if (!isalpha(c) || c != *t && (islower(c) ? toupper(c) : tolower(c)) != *t)
+ break;
+ t++;
+ }
+ }
+ s--;
+ if (!isalpha(c))
+ {
+ if (c == '_')
+ s++;
+ if (e)
+ *e = (char*)s;
+ return s > b;
+ }
+ if (!*t && s > (b + 1))
+ {
+ b = s;
+ while (n-- && (t = *suf++))
+ {
+ s = b;
+ while (isalpha(c = *s++) && (c == *t || (islower(c) ? toupper(c) : tolower(c)) == *t)) t++;
+ if (!*t && !isalpha(c))
+ {
+ if (c != '_')
+ s--;
+ if (e)
+ *e = (char*)s;
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
diff --git a/src/lib/libast/tm/tmxdate.c b/src/lib/libast/tm/tmxdate.c
new file mode 100644
index 0000000..8048f7f
--- /dev/null
+++ b/src/lib/libast/tm/tmxdate.c
@@ -0,0 +1,1745 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * Time_t conversion support
+ *
+ * relative times inspired by Steve Bellovin's netnews getdate(3)
+ */
+
+#include <tmx.h>
+#include <ctype.h>
+#include <debug.h>
+
+#define dig1(s,n) ((n)=((*(s)++)-'0'))
+#define dig2(s,n) ((n)=((*(s)++)-'0')*10,(n)+=(*(s)++)-'0')
+#define dig3(s,n) ((n)=((*(s)++)-'0')*100,(n)+=((*(s)++)-'0')*10,(n)+=(*(s)++)-'0')
+#define dig4(s,n) ((n)=((*(s)++)-'0')*1000,(n)+=((*(s)++)-'0')*100,(n)+=((*(s)++)-'0')*10,(n)+=(*(s)++)-'0')
+
+#undef BREAK
+
+#define BREAK (1<<0)
+#define CCYYMMDDHHMMSS (1<<1)
+#define CRON (1<<2)
+#define DAY (1<<3)
+#define EXACT (1<<4)
+#define FINAL (1<<5)
+#define HOLD (1<<6)
+#define HOUR (1<<7)
+#define LAST (1<<8)
+#define MDAY (1<<9)
+#define MINUTE (1<<10)
+#define MONTH (1<<11)
+#define NEXT (1<<12)
+#define NSEC (1<<13)
+#define ORDINAL (1<<14)
+#define SECOND (1<<15)
+#define THIS (1L<<16)
+#define WDAY (1L<<17)
+#define WORK (1L<<18)
+#define YEAR (1L<<19)
+#define ZONE (1L<<20)
+
+#define FFMT "%s%s%s%s%s%s%s|"
+#define FLAGS(f) (f&EXACT)?"|EXACT":"",(f&LAST)?"|LAST":"",(f&THIS)?"|THIS":"",(f&NEXT)?"|NEXT":"",(f&ORDINAL)?"|ORDINAL":"",(f&FINAL)?"|FINAL":"",(f&WORK)?"|WORK":""
+/*
+ * parse cron range into set
+ * return: -1:error 0:* 1:some
+ */
+
+static int
+range(register char* s, char** e, char* set, int lo, int hi)
+{
+ int n;
+ int m;
+ int i;
+ char* t;
+
+ while (isspace(*s) || *s == '_')
+ s++;
+ if (*s == '*')
+ {
+ *e = s + 1;
+ return 0;
+ }
+ memset(set, 0, hi + 1);
+ for (;;)
+ {
+ n = strtol(s, &t, 10);
+ if (s == t || n < lo || n > hi)
+ return -1;
+ i = 1;
+ if (*(s = t) == '-')
+ {
+ m = strtol(++s, &t, 10);
+ if (s == t || m < n || m > hi)
+ return -1;
+ if (*(s = t) == '/')
+ {
+ i = strtol(++s, &t, 10);
+ if (s == t || i < 1)
+ return -1;
+ s = t;
+ }
+ }
+ else
+ m = n;
+ for (; n <= m; n += i)
+ set[n] = 1;
+ if (*s != ',')
+ break;
+ s++;
+ }
+ *e = s;
+ return 1;
+}
+
+/*
+ * normalize <p,q> to power of 10 u in tm
+ */
+
+static void
+powerize(Tm_t* tm, unsigned long p, unsigned long q, unsigned long u)
+{
+ Time_t t = p;
+
+ while (q > u)
+ {
+ q /= 10;
+ t /= 10;
+ }
+ while (q < u)
+ {
+ q *= 10;
+ t *= 10;
+ }
+ tm->tm_nsec += (int)(t % TMX_RESOLUTION);
+ tm->tm_sec += (int)(t / TMX_RESOLUTION);
+}
+
+#define K1(c1) (c1)
+#define K2(c1,c2) (((c1)<<8)|(c2))
+#define K3(c1,c2,c3) (((c1)<<16)|((c2)<<8)|(c3))
+#define K4(c1,c2,c3,c4) (((c1)<<24)|((c2)<<16)|((c3)<<8)|(c4))
+
+#define P_INIT(n) w = n; p = q = 0; u = (char*)s + 1
+
+/*
+ * parse date expression in s and return Time_t value
+ *
+ * if non-null, e points to the first invalid sequence in s
+ * now provides default values
+ */
+
+Time_t
+tmxdate(register const char* s, char** e, Time_t now)
+{
+ register Tm_t* tm;
+ register long n;
+ register int w;
+ unsigned long set;
+ unsigned long state;
+ unsigned long flags;
+ Time_t fix;
+ char* t;
+ char* u;
+ const char* o;
+ const char* x;
+ char* last;
+ char* type;
+ int day;
+ int dir;
+ int dst;
+ int zone;
+ int c;
+ int f;
+ int i;
+ int j;
+ int k;
+ int l;
+ long m;
+ unsigned long p;
+ unsigned long q;
+ Tm_zone_t* zp;
+ Tm_t ts;
+ char skip[UCHAR_MAX + 1];
+
+ /*
+ * check DATEMSK first
+ */
+
+ debug((error(-1, "AHA tmxdate 2009-03-06")));
+ fix = tmxscan(s, &last, NiL, &t, now, 0);
+ if (t && !*last)
+ {
+ if (e)
+ *e = last;
+ return fix;
+ }
+ o = s;
+
+ reset:
+
+ /*
+ * use now for defaults
+ */
+
+ tm = tmxtm(&ts, now, NiL);
+ tm_info.date = tm->tm_zone;
+ day = -1;
+ dir = 0;
+ dst = TM_DST;
+ set = state = 0;
+ type = 0;
+ zone = TM_LOCALZONE;
+ skip[0] = 0;
+ for (n = 1; n <= UCHAR_MAX; n++)
+ skip[n] = isspace(n) || strchr("_,;@=|!^()[]{}", n);
+
+ /*
+ * get <weekday year month day hour minutes seconds ?[ds]t [ap]m>
+ */
+
+ again:
+ for (;;)
+ {
+ state &= (state & HOLD) ? ~(HOLD) : ~(EXACT|LAST|NEXT|THIS);
+ if ((set|state) & (YEAR|MONTH|DAY))
+ skip['/'] = 1;
+ message((-1, "AHA#%d state=" FFMT " set=" FFMT, __LINE__, FLAGS(state), FLAGS(set)));
+ for (;;)
+ {
+ if (*s == '.' || *s == '-' || *s == '+')
+ {
+ if (((set|state) & (YEAR|MONTH|HOUR|MINUTE|ZONE)) == (YEAR|MONTH|HOUR|MINUTE) && (i = tmgoff(s, &t, TM_LOCALZONE)) != TM_LOCALZONE)
+ {
+ zone = i;
+ state |= ZONE;
+ if (!*(s = t))
+ break;
+ }
+ else if (*s == '+')
+ break;
+ }
+ else if (!skip[*s])
+ break;
+ s++;
+ }
+ if (!*(last = (char*)s))
+ break;
+ if (*s == '#')
+ {
+ if (isdigit(*++s))
+ {
+ now = strtoull(s, &t, 0);
+ sns:
+ if (*(s = t) == '.')
+ {
+ fix = 0;
+ m = 1000000000;
+ while (isdigit(*++s))
+ fix += (*s - '0') * (m /= 10);
+ now = tmxsns(now, fix);
+ }
+ else if (now <= 0x7fffffff)
+ now = tmxsns(now, 0);
+ goto reset;
+ }
+ else if (*s++ == '#')
+ {
+ now = tmxtime(tm, zone);
+ goto reset;
+ }
+ break;
+ }
+ if ((*s == 'P' || *s == 'p') && (!isalpha(*(s + 1)) || (*(s + 1) == 'T' || *(s + 1) == 't') && !isalpha(*(s + 2))))
+ {
+ Tm_t otm;
+
+ /*
+ * iso duration
+ */
+
+ otm = *tm;
+ t = (char*)s;
+ m = 0;
+ P_INIT('Y');
+ do
+ {
+ c = *++s;
+ duration_next:
+ switch (c)
+ {
+ case 0:
+ m++;
+ if ((char*)s > u)
+ {
+ s--;
+ c = '_';
+ goto duration_next;
+ }
+ break;
+ case 'T':
+ case 't':
+ m++;
+ if ((char*)s > u)
+ {
+ s++;
+ c = 'D';
+ goto duration_next;
+ }
+ continue;
+ case 'Y':
+ case 'y':
+ m = 0;
+ if (q > 1)
+ tm->tm_sec += (365L*24L*60L*60L) * p / q;
+ else
+ tm->tm_year += p;
+ P_INIT('M');
+ continue;
+ case 'm':
+ if (!m)
+ m = 1;
+ /*FALLTHROUGH*/
+ case 'M':
+ switch (*(s + 1))
+ {
+ case 'I':
+ case 'i':
+ s++;
+ m = 1;
+ w = 'S';
+ break;
+ case 'O':
+ case 'o':
+ s++;
+ m = 0;
+ w = 'H';
+ break;
+ case 'S':
+ case 's':
+ s++;
+ m = 2;
+ w = 's';
+ break;
+ }
+ switch (m)
+ {
+ case 0:
+ m = 1;
+ if (q > 1)
+ tm->tm_sec += (3042L*24L*60L*60L) * p / q / 100L;
+ else
+ tm->tm_mon += p;
+ break;
+ case 1:
+ m = 2;
+ if (q > 1)
+ tm->tm_sec += (60L) * p / q;
+ else
+ tm->tm_min += p;
+ break;
+ default:
+ if (q > 1)
+ powerize(tm, p, q, 1000UL);
+ else
+ tm->tm_nsec += p * 1000000L;
+ break;
+ }
+ P_INIT(w);
+ continue;
+ case 'W':
+ case 'w':
+ m = 0;
+ if (q > 1)
+ tm->tm_sec += (7L*24L*60L*60L) * p / q;
+ else
+ tm->tm_mday += 7 * p;
+ P_INIT('D');
+ continue;
+ case 'D':
+ case 'd':
+ m = 0;
+ if (q > 1)
+ tm->tm_sec += (24L*60L*60L) * p / q;
+ else
+ tm->tm_mday += p;
+ P_INIT('H');
+ continue;
+ case 'H':
+ case 'h':
+ m = 1;
+ if (q > 1)
+ tm->tm_sec += (60L*60L) * p / q;
+ else
+ tm->tm_hour += p;
+ P_INIT('m');
+ continue;
+ case 'S':
+ case 's':
+ m = 2;
+ /*FALLTHROUGH*/
+ case ' ':
+ case '_':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ if (q > 1)
+ powerize(tm, p, q, 1000000000UL);
+ else
+ tm->tm_sec += p;
+ P_INIT('U');
+ continue;
+ case 'U':
+ case 'u':
+ switch (*(s + 1))
+ {
+ case 'S':
+ case 's':
+ s++;
+ break;
+ }
+ m = 0;
+ if (q > 1)
+ powerize(tm, p, q, 1000000UL);
+ else
+ tm->tm_nsec += p * 1000L;
+ P_INIT('N');
+ continue;
+ case 'N':
+ case 'n':
+ switch (*(s + 1))
+ {
+ case 'S':
+ case 's':
+ s++;
+ break;
+ }
+ m = 0;
+ if (q > 1)
+ powerize(tm, p, q, 1000000000UL);
+ else
+ tm->tm_nsec += p;
+ P_INIT('Y');
+ continue;
+ case '.':
+ if (q)
+ goto exact;
+ q = 1;
+ continue;
+ case '-':
+ c = 'M';
+ u = (char*)s++;
+ while (*++u && *u != ':')
+ if (*u == '-')
+ {
+ c = 'Y';
+ break;
+ }
+ goto duration_next;
+ case ':':
+ c = 'm';
+ u = (char*)s++;
+ while (*++u)
+ if (*u == ':')
+ {
+ c = 'H';
+ break;
+ }
+ goto duration_next;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ q *= 10;
+ p = p * 10 + (c - '0');
+ continue;
+ default:
+ exact:
+ *tm = otm;
+ s = (const char*)t + 1;
+ if (*t == 'p')
+ {
+ state |= HOLD|EXACT;
+ set &= ~(EXACT|LAST|NEXT|THIS);
+ set |= state & (EXACT|LAST|NEXT|THIS);
+ }
+ goto again;
+ }
+ break;
+ } while (c);
+ continue;
+ }
+ f = -1;
+ if (*s == '+')
+ {
+ while (isspace(*++s) || *s == '_');
+ n = strtol(s, &t, 0);
+ if (w = t - s)
+ {
+ for (s = t; skip[*s]; s++);
+ state |= (f = n) ? NEXT : THIS;
+ set &= ~(EXACT|LAST|NEXT|THIS);
+ set |= state & (EXACT|LAST|NEXT|THIS);
+ }
+ else
+ s = last;
+ }
+ if (!(state & CRON))
+ {
+ /*
+ * check for cron date
+ *
+ * min hour day-of-month month day-of-week
+ *
+ * if it's cron then determine the next time
+ * that satisfies the specification
+ *
+ * NOTE: the only spacing is ' '||'_'||';'
+ */
+
+ i = 0;
+ n = *(t = (char*)s);
+ for (;;)
+ {
+ if (n == '*')
+ n = *++s;
+ else if (!isdigit(n))
+ break;
+ else
+ while ((n = *++s) == ',' || n == '-' || n == '/' || isdigit(n));
+ if (n != ' ' && n != '_' && n != ';')
+ {
+ if (!n)
+ i++;
+ break;
+ }
+ i++;
+ while ((n = *++s) == ' ' || n == '_');
+ }
+ if (i == 5)
+ {
+ Time_t tt;
+ char hit[60];
+ char mon[13];
+ char day[7];
+
+ state |= CRON;
+ flags = 0;
+ tm->tm_sec = 0;
+ tm->tm_min++;
+ tmfix(tm);
+
+ /*
+ * minute
+ */
+
+ if ((k = range(t, &t, hit, 0, 59)) < 0)
+ break;
+ if (k && !hit[i = tm->tm_min])
+ {
+ hit[i] = 1;
+ do if (++i > 59)
+ {
+ i = 0;
+ if (++tm->tm_hour > 59)
+ {
+ tm->tm_min = i;
+ tmfix(tm);
+ }
+ } while (!hit[i]);
+ tm->tm_min = i;
+ }
+
+ /*
+ * hour
+ */
+
+ if ((k = range(t, &t, hit, 0, 23)) < 0)
+ break;
+ if (k && !hit[i = tm->tm_hour])
+ {
+ hit[i] = 1;
+ do if (++i > 23)
+ {
+ i = 0;
+ if (++tm->tm_mday > 28)
+ {
+ tm->tm_hour = i;
+ tmfix(tm);
+ }
+ } while (!hit[i]);
+ tm->tm_hour = i;
+ }
+
+ /*
+ * day of month
+ */
+
+ if ((k = range(t, &t, hit, 1, 31)) < 0)
+ break;
+ if (k)
+ flags |= DAY|MDAY;
+
+ /*
+ * month
+ */
+
+ if ((k = range(t, &t, mon, 1, 12)) < 0)
+ break;
+ if (k)
+ flags |= MONTH;
+ else
+ for (i = 1; i <= 12; i++)
+ mon[i] = 1;
+
+ /*
+ * day of week
+ */
+
+ if ((k = range(t, &t, day, 0, 6)) < 0)
+ break;
+ if (k)
+ flags |= WDAY;
+ s = t;
+ if (flags & (MONTH|MDAY|WDAY))
+ {
+ fix = tmxtime(tm, zone);
+ tm = tmxtm(tm, fix, tm->tm_zone);
+ i = tm->tm_mon + 1;
+ j = tm->tm_mday;
+ k = tm->tm_wday;
+ for (;;)
+ {
+ if (!mon[i])
+ {
+ if (++i > 12)
+ {
+ i = 1;
+ tm->tm_year++;
+ }
+ tm->tm_mon = i - 1;
+ tm->tm_mday = 1;
+ tt = tmxtime(tm, zone);
+ if (tt < fix)
+ goto done;
+ tm = tmxtm(tm, tt, tm->tm_zone);
+ i = tm->tm_mon + 1;
+ j = tm->tm_mday;
+ k = tm->tm_wday;
+ continue;
+ }
+ if (flags & (MDAY|WDAY))
+ {
+ if ((flags & (MDAY|WDAY)) == (MDAY|WDAY))
+ {
+ if (hit[j] && day[k])
+ break;
+ }
+ else if ((flags & MDAY) && hit[j])
+ break;
+ else if ((flags & WDAY) && day[k])
+ break;
+ if (++j > 28)
+ {
+ tm->tm_mon = i - 1;
+ tm->tm_mday = j;
+ tm = tmxtm(tm, tmxtime(tm, zone), tm->tm_zone);
+ i = tm->tm_mon + 1;
+ j = tm->tm_mday;
+ k = tm->tm_wday;
+ }
+ else if ((flags & WDAY) && ++k > 6)
+ k = 0;
+ }
+ else if (flags & MONTH)
+ break;
+ }
+ tm->tm_mon = i - 1;
+ tm->tm_mday = j;
+ tm->tm_wday = k;
+ }
+ continue;
+ }
+ s = t;
+ }
+ n = -1;
+ if (isdigit(*s))
+ {
+ n = strtol(s, &t, 10);
+ if ((w = t - s) && *t == '.' && isdigit(*(t + 1)) && isdigit(*(t + 2)) && isdigit(*(t + 3)))
+ {
+ now = n;
+ goto sns;
+ }
+ if ((*t == 'T' || *t == 't') && ((set|state) & (YEAR|MONTH|DAY)) == (YEAR|MONTH) && isdigit(*(t + 1)))
+ t++;
+ u = t + (*t == '-');
+ message((-1, "AHA#%d n=%d w=%d u='%c' f=%d t=\"%s\"", __LINE__, n, w, *u, f, t));
+ if ((w == 2 || w == 4) && (*u == 'W' || *u == 'w') && isdigit(*(u + 1)))
+ {
+ if (w == 4)
+ {
+ if ((n -= 1900) < TM_WINDOW)
+ break;
+ }
+ else if (n < TM_WINDOW)
+ n += 100;
+ m = n;
+ n = strtol(++u, &t, 10);
+ if ((i = (t - u)) < 2 || i > 3)
+ break;
+ if (i == 3)
+ {
+ k = n % 10;
+ n /= 10;
+ }
+ else if (*t != '-')
+ k = 1;
+ else if (*++t && dig1(t, k) < 1 || k > 7)
+ break;
+ if (n < 0 || n > 53)
+ break;
+ if (k == 7)
+ k = 0;
+ tm->tm_year = m;
+ tmweek(tm, 2, n, k);
+ set |= YEAR|MONTH|DAY;
+ s = t;
+ continue;
+ }
+ else if (w == 6 || w == 8 && (n / 1000000) > 12)
+ {
+ t = (char*)s;
+ flags = 0;
+ if (w == 8 || w == 6 && *u != 'T' && *u != 't')
+ {
+ dig4(t, m);
+ if ((m -= 1900) < TM_WINDOW)
+ break;
+ }
+ else
+ {
+ dig2(t, m);
+ if (m < TM_WINDOW)
+ m += 100;
+ }
+ flags |= YEAR;
+ if (dig2(t, l) <= 0 || l > 12)
+ break;
+ flags |= MONTH;
+ if (*t != 'T' && *t != 't' || !isdigit(*++t))
+ {
+ if (w == 6)
+ goto save_yymm;
+ if (dig2(t, k) < 1 || k > 31)
+ break;
+ flags |= DAY;
+ goto save_yymmdd;
+ }
+ n = strtol(s = t, &t, 0);
+ if ((t - s) < 2)
+ break;
+ if (dig2(s, j) > 24)
+ break;
+ if ((t - s) < 2)
+ {
+ if ((t - s) == 1 || *t++ != '-')
+ break;
+ n = strtol(s = t, &t, 0);
+ if ((t - s) < 2)
+ break;
+ }
+ if (dig2(s, i) > 59)
+ break;
+ flags |= HOUR|MINUTE;
+ if ((t - s) == 2)
+ {
+ if (dig2(s, n) > (59 + TM_MAXLEAP))
+ break;
+ flags |= SECOND;
+ }
+ else if (t - s)
+ break;
+ else
+ n = 0;
+ p = 0;
+ if (*t == '.')
+ {
+ q = 1000000000;
+ while (isdigit(*++t))
+ p += (*t - '0') * (q /= 10);
+ set |= NSEC;
+ }
+ if (n > (59 + TM_MAXLEAP))
+ break;
+ goto save;
+ }
+ else if (f == -1 && isalpha(*t) && tmlex(t, &t, tm_info.format + TM_ORDINAL, TM_ORDINALS - TM_ORDINAL, NiL, 0) >= 0)
+ {
+ message((-1, "AHA#%d n=%d", __LINE__, n));
+ ordinal:
+ if (n)
+ n--;
+ message((-1, "AHA#%d n=%d", __LINE__, n));
+ state |= ((f = n) ? NEXT : THIS)|ORDINAL;
+ set &= ~(EXACT|LAST|NEXT|THIS);
+ set |= state & (EXACT|LAST|NEXT|THIS);
+ for (s = t; skip[*s]; s++);
+ if (isdigit(*s))
+ {
+ if (n = strtol(s, &t, 10))
+ n--;
+ s = t;
+ if (*s == '_')
+ s++;
+ }
+ else
+ n = -1;
+ dir = f;
+ message((-1, "AHA#%d f=%d n=%d state=" FFMT, __LINE__, f, n, FLAGS(state)));
+ }
+ else
+ {
+ for (u = t; isspace(*u); u++);
+ message((-1, "AHA#%d n=%d u=\"%s\"", __LINE__, n, u));
+ if ((j = tmlex(u, NiL, tm_info.format, TM_NFORM, tm_info.format + TM_SUFFIXES, TM_PARTS - TM_SUFFIXES)) >= 0 && tm_data.lex[j] == TM_PARTS)
+ s = u;
+ else
+ {
+ message((-1, "AHA#%d t=\"%s\"", __LINE__, t));
+ if (!(state & (LAST|NEXT|THIS)) && ((i = t - s) == 4 && (*t == '.' && isdigit(*(t + 1)) && isdigit(*(t + 2)) && *(t + 3) != '.' || (!*t || isspace(*t) || *t == '_' || isalnum(*t)) && n >= 0 && (n % 100) < 60 && ((m = (n / 100)) < 20 || m < 24 && !((set|state) & (YEAR|MONTH|HOUR|MINUTE)))) || i > 4 && i <= 12))
+ {
+ /*
+ * various { date(1) touch(1) } formats
+ *
+ * [[cc]yy[mm]]ddhhmm[.ss[.nn...]]
+ * [cc]yyjjj
+ * hhmm[.ss[.nn...]]
+ */
+
+ message((-1, "AHA#%d t=\"%s\"", __LINE__, t));
+ flags = 0;
+ if (state & CCYYMMDDHHMMSS)
+ break;
+ state |= CCYYMMDDHHMMSS;
+ p = 0;
+ if ((i == 7 || i == 5) && (!*t || *t == 'Z' || *t == 'z'))
+ {
+ if (i == 7)
+ {
+ dig4(s, m);
+ if ((m -= 1900) < TM_WINDOW)
+ break;
+ }
+ else if (dig2(s, m) < TM_WINDOW)
+ m += 100;
+ dig3(s, k);
+ l = 1;
+ j = 0;
+ i = 0;
+ n = 0;
+ flags |= MONTH;
+ }
+ else if (i & 1)
+ break;
+ else
+ {
+ u = t;
+ if (i == 12)
+ {
+ x = s;
+ dig2(x, m);
+ if (m <= 12)
+ {
+ u -= 4;
+ i -= 4;
+ x = s + 8;
+ dig4(x, m);
+ }
+ else
+ dig4(s, m);
+ if (m < 1969 || m >= 3000)
+ break;
+ m -= 1900;
+ }
+ else if (i == 10)
+ {
+ x = s;
+ if (!dig2(x, m) || m > 12 || !dig2(x, m) || m > 31 || dig2(x, m) > 24 || dig2(x, m) > 60 || dig2(x, m) <= 60 && !(tm_info.flags & TM_DATESTYLE))
+ dig2(s, m);
+ else
+ {
+ u -= 2;
+ i -= 2;
+ x = s + 8;
+ dig2(x, m);
+ }
+ if (m < TM_WINDOW)
+ m += 100;
+ }
+ else
+ m = tm->tm_year;
+ if ((u - s) < 8)
+ l = tm->tm_mon + 1;
+ else if (dig2(s, l) <= 0 || l > 12)
+ break;
+ else
+ flags |= MONTH;
+ if ((u - s) < 6)
+ k = tm->tm_mday;
+ else if (dig2(s, k) < 1 || k > 31)
+ break;
+ else
+ flags |= DAY;
+ if ((u - s) < 4)
+ break;
+ if (dig2(s, j) > 24)
+ break;
+ if (dig2(s, i) > 59)
+ break;
+ flags |= HOUR|MINUTE;
+ if ((u - s) == 2)
+ {
+ dig2(s, n);
+ flags |= SECOND;
+ }
+ else if (u - s)
+ break;
+ else if (*t != '.')
+ n = 0;
+ else
+ {
+ n = strtol(t + 1, &t, 10);
+ flags |= SECOND;
+ if (*t == '.')
+ {
+ q = 1000000000;
+ while (isdigit(*++t))
+ p += (*t - '0') * (q /= 10);
+ set |= NSEC;
+ }
+ }
+ if (n > (59 + TM_MAXLEAP))
+ break;
+ }
+ save:
+ tm->tm_hour = j;
+ tm->tm_min = i;
+ tm->tm_sec = n;
+ tm->tm_nsec = p;
+ save_yymmdd:
+ tm->tm_mday = k;
+ save_yymm:
+ tm->tm_mon = l - 1;
+ tm->tm_year = m;
+ s = t;
+ set |= flags;
+ continue;
+ }
+ for (s = t; skip[*s]; s++);
+ message((-1, "AHA#%d s=\"%s\"", __LINE__, s));
+ if (*s == ':' || *s == '.' && ((set|state) & (YEAR|MONTH|DAY|HOUR)) == (YEAR|MONTH|DAY))
+ {
+ c = *s;
+ if ((state & HOUR) || n > 24)
+ break;
+ while (isspace(*++s) || *s == '_');
+ if (!isdigit(*s))
+ break;
+ i = n;
+ n = strtol(s, &t, 10);
+ for (s = t; isspace(*s) || *s == '_'; s++);
+ if (n > 59)
+ break;
+ j = n;
+ m = 0;
+ if (*s == c)
+ {
+ while (isspace(*++s) || *s == '_');
+ if (!isdigit(*s))
+ break;
+ n = strtol(s, &t, 10);
+ s = t;
+ if (n > (59 + TM_MAXLEAP))
+ break;
+ set |= SECOND;
+ while (isspace(*s))
+ s++;
+ if (*s == '.')
+ {
+ q = 1000000000;
+ while (isdigit(*++s))
+ m += (*s - '0') * (q /= 10);
+ set |= NSEC;
+ }
+ }
+ else
+ n = 0;
+ set |= HOUR|MINUTE;
+ skip[':'] = 1;
+ k = tm->tm_hour;
+ tm->tm_hour = i;
+ l = tm->tm_min;
+ tm->tm_min = j;
+ tm->tm_sec = n;
+ tm->tm_nsec = m;
+ while (isspace(*s))
+ s++;
+ switch (tmlex(s, &t, tm_info.format, TM_NFORM, tm_info.format + TM_MERIDIAN, 2))
+ {
+ case TM_MERIDIAN:
+ s = t;
+ if (i == 12)
+ tm->tm_hour = i = 0;
+ break;
+ case TM_MERIDIAN+1:
+ if (i < 12)
+ tm->tm_hour = i += 12;
+ break;
+ }
+ if (f >= 0 || (state & (LAST|NEXT)))
+ {
+ message((-1, "AHA#%d f=%d i=%d j=%d k=%d l=%d", __LINE__, f, i, j, k, l));
+ state &= ~HOLD;
+ if (f < 0)
+ {
+ if (state & LAST)
+ f = -1;
+ else if (state & NEXT)
+ f = 1;
+ else
+ f = 0;
+ }
+ if (f > 0)
+ {
+ if (i > k || i == k && j > l)
+ f--;
+ }
+ else if (i < k || i == k && j < l)
+ f++;
+ if (f > 0)
+ {
+ tm->tm_hour += f * 24;
+ while (tm->tm_hour >= 24)
+ {
+ tm->tm_hour -= 24;
+ tm->tm_mday++;
+ }
+ }
+ else if (f < 0)
+ {
+ tm->tm_hour += f * 24;
+ while (tm->tm_hour < 24)
+ {
+ tm->tm_hour += 24;
+ tm->tm_mday--;
+ }
+ }
+ }
+ continue;
+ }
+ }
+ }
+ }
+ for (;;)
+ {
+ message((-1, "AHA#%d s=\"%s\"", __LINE__, s));
+ if (*s == '-' || *s == '+')
+ {
+ if (((set|state) & (MONTH|DAY|HOUR|MINUTE)) == (MONTH|DAY|HOUR|MINUTE) || *s == '+' && (!isdigit(s[1]) || !isdigit(s[2]) || s[3] != ':' && (s[3] != '.' || ((set|state) & (YEAR|MONTH)) != (YEAR|MONTH))))
+ break;
+ s++;
+ }
+ else if (skip[*s])
+ s++;
+ else
+ break;
+ }
+ if (isalpha(*s))
+ {
+ if (n > 0)
+ {
+ x = s;
+ q = *s++;
+ message((-1, "AHA#%d n=%d q='%c'", __LINE__, n, q));
+ if (isalpha(*s))
+ {
+ q <<= 8;
+ q |= *s++;
+ if (isalpha(*s))
+ {
+ if (tmlex(s, &t, tm_info.format + TM_SUFFIXES, TM_PARTS - TM_SUFFIXES, NiL, 0) >= 0)
+ s = t;
+ if (isalpha(*s))
+ {
+ q <<= 8;
+ q |= *s++;
+ if (isalpha(*s))
+ {
+ q <<= 8;
+ q |= *s++;
+ if (isalpha(*s))
+ q = 0;
+ }
+ }
+ }
+ }
+ switch (q)
+ {
+ case K1('y'):
+ case K1('Y'):
+ case K2('y','r'):
+ case K2('Y','R'):
+ tm->tm_year += n;
+ set |= YEAR;
+ continue;
+ case K1('M'):
+ case K2('m','o'):
+ case K2('M','O'):
+ tm->tm_mon += n;
+ set |= MONTH;
+ continue;
+ case K1('w'):
+ case K1('W'):
+ case K2('w','k'):
+ case K2('W','K'):
+ tm->tm_mday += n * 7;
+ set |= DAY;
+ continue;
+ case K1('d'):
+ case K1('D'):
+ case K2('d','a'):
+ case K2('d','y'):
+ case K2('D','A'):
+ case K2('D','Y'):
+ tm->tm_mday += n;
+ set |= DAY;
+ continue;
+ case K1('h'):
+ case K1('H'):
+ case K2('h','r'):
+ case K2('H','R'):
+ tm->tm_hour += n;
+ set |= HOUR;
+ continue;
+ case K1('m'):
+ case K2('m','n'):
+ case K2('M','N'):
+ tm->tm_min += n;
+ set |= MINUTE;
+ continue;
+ case K1('s'):
+ case K2('s','c'):
+ case K1('S'):
+ case K2('S','C'):
+ tm->tm_sec += n;
+ set |= SECOND;
+ continue;
+ case K2('m','s'):
+ case K3('m','s','c'):
+ case K4('m','s','e','c'):
+ case K2('M','S'):
+ case K3('M','S','C'):
+ case K4('M','S','E','C'):
+ tm->tm_nsec += n * 1000000L;
+ continue;
+ case K1('u'):
+ case K2('u','s'):
+ case K3('u','s','c'):
+ case K4('u','s','e','c'):
+ case K1('U'):
+ case K2('U','S'):
+ case K3('U','S','C'):
+ case K4('U','S','E','C'):
+ tm->tm_nsec += n * 1000L;
+ continue;
+ case K2('n','s'):
+ case K3('n','s','c'):
+ case K4('n','s','e','c'):
+ case K2('N','S'):
+ case K3('N','S','C'):
+ case K4('N','S','E','C'):
+ tm->tm_nsec += n;
+ continue;
+ }
+ s = x;
+ }
+ if ((j = tmlex(s, &t, tm_info.format, TM_NFORM, tm_info.format + TM_SUFFIXES, TM_PARTS - TM_SUFFIXES)) >= 0)
+ {
+ if (tm_data.lex[j] == TM_PARTS || n < 1000)
+ {
+ s = t;
+ switch (tm_data.lex[j])
+ {
+ case TM_EXACT:
+ state |= HOLD|EXACT;
+ set &= ~(EXACT|LAST|NEXT|THIS);
+ set |= state & (EXACT|LAST|NEXT|THIS);
+ continue;
+ case TM_LAST:
+ state |= HOLD|LAST;
+ set &= ~(EXACT|LAST|NEXT|THIS);
+ set |= state & (EXACT|LAST|NEXT|THIS);
+ continue;
+ case TM_THIS:
+ state |= HOLD|THIS;
+ set &= ~(EXACT|LAST|NEXT|THIS);
+ set |= state & (EXACT|LAST|NEXT|THIS);
+ n = 0;
+ continue;
+ case TM_NEXT:
+ /*
+ * disambiguate english "last ... in"
+ */
+
+ if (!((state|set) & LAST))
+ {
+ state |= HOLD|NEXT;
+ set &= ~(EXACT|LAST|NEXT|THIS);
+ set |= state & (EXACT|LAST|NEXT|THIS);
+ continue;
+ }
+ /*FALLTHROUGH*/
+ case TM_FINAL:
+ state |= HOLD|THIS|FINAL;
+ set &= ~(EXACT|LAST|NEXT|THIS);
+ set |= state & (EXACT|LAST|NEXT|THIS|FINAL);
+ continue;
+ case TM_WORK:
+ message((-1, "AHA#%d WORK", __LINE__));
+ state |= WORK;
+ set |= DAY;
+ if (state & LAST)
+ {
+ state &= ~LAST;
+ set &= ~LAST;
+ state |= FINAL;
+ set |= FINAL;
+ }
+ goto clear_hour;
+ case TM_ORDINAL:
+ j += TM_ORDINALS - TM_ORDINAL;
+ message((-1, "AHA#%d j=%d", __LINE__, j));
+ /*FALLTHROUGH*/
+ case TM_ORDINALS:
+ n = j - TM_ORDINALS + 1;
+ message((-1, "AHA#%d n=%d", __LINE__, n));
+ goto ordinal;
+ case TM_MERIDIAN:
+ if (f >= 0)
+ f++;
+ else if (state & LAST)
+ f = -1;
+ else if (state & THIS)
+ f = 1;
+ else if (state & NEXT)
+ f = 2;
+ else
+ f = 0;
+ if (n > 0)
+ {
+ if (n > 24)
+ goto done;
+ tm->tm_hour = n;
+ }
+ for (k = tm->tm_hour; k < 0; k += 24);
+ k %= 24;
+ if (j == TM_MERIDIAN)
+ {
+ if (k == 12)
+ tm->tm_hour -= 12;
+ }
+ else if (k < 12)
+ tm->tm_hour += 12;
+ if (n > 0)
+ goto clear_min;
+ continue;
+ case TM_DAY_ABBREV:
+ j += TM_DAY - TM_DAY_ABBREV;
+ /*FALLTHROUGH*/
+ case TM_DAY:
+ case TM_PARTS:
+ case TM_HOURS:
+ state |= set & (EXACT|LAST|NEXT|THIS);
+ if (!(state & (LAST|NEXT|THIS)))
+ for (;;)
+ {
+ while (skip[*s])
+ s++;
+ if ((k = tmlex(s, &t, tm_info.format + TM_LAST, TM_NOISE - TM_LAST, NiL, 0)) >= 0)
+ {
+ s = t;
+ if (k <= 2)
+ state |= LAST;
+ else if (k <= 5)
+ state |= THIS;
+ else if (k <= 8)
+ state |= NEXT;
+ else
+ state |= EXACT;
+ }
+ else
+ {
+ state |= (n > 0) ? NEXT : THIS;
+ break;
+ }
+ set &= ~(EXACT|LAST|NEXT|THIS);
+ set |= state & (EXACT|LAST|NEXT|THIS);
+ }
+ /*FALLTHROUGH*/
+ case TM_DAYS:
+ message((-1, "AHA#%d n=%d j=%d f=%d state=" FFMT, __LINE__, n, j, f, FLAGS(state)));
+ if (n == -1)
+ {
+ /*
+ * disambiguate english "second"
+ */
+
+ if (j == TM_PARTS && f == -1)
+ {
+ state &= ~(LAST|NEXT|THIS|ORDINAL); /*AHA*/
+ n = 2;
+ goto ordinal;
+ }
+ n = 1;
+ }
+
+ /*
+ * disambiguate "last" vs. { "previous" "final" }
+ */
+
+ while (isspace(*s))
+ s++;
+ message((-1, "AHA#%d disambiguate LAST s='%s'", __LINE__, s));
+ if ((k = tmlex(s, &t, tm_info.format + TM_NEXT, TM_EXACT - TM_NEXT, NiL, 0)) >= 0 || (k = tmlex(s, &t, tm_info.format + TM_PARTS + 3, 1, NiL, 0)) >= 0)
+ {
+ s = t;
+ if (state & LAST)
+ {
+ state &= ~LAST;
+ set &= ~LAST;
+ state |= FINAL;
+ set |= FINAL;
+ message((-1, "AHA#%d LAST => FINAL", __LINE__));
+ }
+ else
+ state &= ~(THIS|NEXT);
+ }
+ message((-1, "AHA#%d disambiguate LAST k=%d", __LINE__, k));
+ if (state & LAST)
+ n = -n;
+ else if (!(state & NEXT))
+ n--;
+ m = (f > 0) ? f * n : n;
+ message((-1, "AHA#%d f=%d n=%d i=%d j=%d k=%d l=%d m=%d state=" FFMT, __LINE__, f, n, i, j, k, l, m, FLAGS(state)));
+ switch (j)
+ {
+ case TM_DAYS+0:
+ tm->tm_mday--;
+ set |= DAY;
+ goto clear_hour;
+ case TM_DAYS+1:
+ set |= DAY;
+ goto clear_hour;
+ case TM_DAYS+2:
+ tm->tm_mday++;
+ set |= DAY;
+ goto clear_hour;
+ case TM_PARTS+0:
+ set |= SECOND;
+ if ((m < 0 ? -m : m) > (365L*24L*60L*60L))
+ {
+ now = tmxtime(tm, zone) + tmxsns(m, 0);
+ goto reset;
+ }
+ tm->tm_sec += m;
+ goto clear_nsec;
+ case TM_PARTS+1:
+ tm->tm_min += m;
+ set |= MINUTE;
+ goto clear_sec;
+ case TM_PARTS+2:
+ tm->tm_hour += m;
+ set |= MINUTE;
+ goto clear_min;
+ case TM_PARTS+3:
+ message((-1, "AHA#%d DAY m=%d n=%d%s", __LINE__, m, n, (state & LAST) ? " LAST" : ""));
+ if ((state & (LAST|NEXT|THIS)) == LAST)
+ tm->tm_mday = tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year));
+ else if (state & ORDINAL)
+ tm->tm_mday = m + 1;
+ else
+ tm->tm_mday += m;
+ if (!(set & (FINAL|WORK)))
+ set |= HOUR;
+ goto clear_hour;
+ case TM_PARTS+4:
+ tm = tmxtm(tm, tmxtime(tm, zone), tm->tm_zone);
+ tm->tm_mday += 7 * m - tm->tm_wday + 1;
+ set |= DAY;
+ goto clear_hour;
+ case TM_PARTS+5:
+ tm->tm_mon += m;
+ set |= MONTH;
+ goto clear_mday;
+ case TM_PARTS+6:
+ tm->tm_year += m;
+ goto clear_mon;
+ case TM_HOURS+0:
+ tm->tm_mday += m;
+ set |= DAY;
+ goto clear_hour;
+ case TM_HOURS+1:
+ tm->tm_mday += m;
+ tm->tm_hour = 6;
+ set |= HOUR;
+ goto clear_min;
+ case TM_HOURS+2:
+ tm->tm_mday += m;
+ tm->tm_hour = 12;
+ set |= HOUR;
+ goto clear_min;
+ case TM_HOURS+3:
+ tm->tm_mday += m;
+ tm->tm_hour = 18;
+ set |= HOUR;
+ goto clear_min;
+ }
+ if (m >= 0 && (state & ORDINAL))
+ tm->tm_mday = 1;
+ tm = tmxtm(tm, tmxtime(tm, zone), tm->tm_zone);
+ day = j -= TM_DAY;
+ if (!dir)
+ dir = m;
+ message((-1, "AHA#%d j=%d m=%d", __LINE__, j, m));
+ j -= tm->tm_wday;
+ message((-1, "AHA#%d mday=%d wday=%d day=%d dir=%d f=%d i=%d j=%d l=%d m=%d", __LINE__, tm->tm_mday, tm->tm_wday, day, dir, f, i, j, l, m));
+ if (state & (LAST|NEXT|THIS))
+ {
+ if (state & ORDINAL)
+ {
+ while (isspace(*s))
+ s++;
+ if (isdigit(*s) || tmlex(s, &t, tm_info.format, TM_DAY_ABBREV, NiL, 0) >= 0)
+ {
+ state &= ~(LAST|NEXT|THIS);
+ goto clear_hour;
+ }
+ }
+ if (j < 0)
+ j += 7;
+ }
+ else if (j > 0)
+ j -= 7;
+ message((-1, "AHA#%d day=%d mday=%d f=%d m=%d j=%d state=" FFMT, __LINE__, day, tm->tm_mday, f, m, j, FLAGS(state)));
+ set |= DAY;
+ if (set & (FINAL|WORK))
+ goto clear_hour;
+ else if (state & (LAST|NEXT|THIS))
+ {
+ if (f >= 0)
+ day = -1;
+ else if (m > 0 && (state & (NEXT|YEAR|MONTH)) == NEXT && j >= 0)
+ m--;
+ tm->tm_mday += j + m * 7;
+ set &= ~(LAST|NEXT|THIS|ORDINAL); /*AHA*/
+ state &= ~(LAST|NEXT|THIS|ORDINAL); /*AHA*/
+ if (!(state & EXACT))
+ goto clear_hour;
+ }
+ continue;
+ case TM_MONTH_ABBREV:
+ j += TM_MONTH - TM_MONTH_ABBREV;
+ /*FALLTHROUGH*/
+ case TM_MONTH:
+ if (state & MONTH)
+ goto done;
+ state |= MONTH;
+ i = tm->tm_mon;
+ tm->tm_mon = j - TM_MONTH;
+ if (n < 0)
+ {
+ while (skip[*s])
+ s++;
+ if (isdigit(*s))
+ {
+ n = strtol(s, &t, 10);
+ if (n <= 31 && *t != ':')
+ s = t;
+ else
+ n = -1;
+ }
+ }
+ if (n >= 0)
+ {
+ if (n > 31)
+ goto done;
+ state |= DAY|MDAY;
+ tm->tm_mday = n;
+ if (f > 0)
+ tm->tm_year += f;
+ }
+ if (state & (LAST|NEXT|THIS))
+ {
+ n = i;
+ goto rel_month;
+ }
+ continue;
+ case TM_UT:
+ if (state & ZONE)
+ goto done;
+ state |= ZONE;
+ zone = tmgoff(s, &t, 0);
+ s = t;
+ continue;
+ case TM_DT:
+ if (!dst)
+ goto done;
+ if (!(state & ZONE))
+ {
+ dst = tm->tm_zone->dst;
+ zone = tm->tm_zone->west;
+ }
+ zone += tmgoff(s, &t, dst);
+ s = t;
+ dst = 0;
+ state |= ZONE;
+ continue;
+ case TM_NOISE:
+ continue;
+ }
+ }
+ }
+ if (n < 1000)
+ {
+ if (!(state & ZONE) && (zp = tmzone(s, &t, type, &dst)))
+ {
+ s = t;
+ zone = zp->west + dst;
+ tm_info.date = zp;
+ state |= ZONE;
+ if (n < 0)
+ continue;
+ }
+ else if (!type && (zp = tmtype(s, &t)))
+ {
+ s = t;
+ type = zp->type;
+ if (n < 0)
+ continue;
+ }
+ state |= BREAK;
+ }
+ }
+ else if (*s == '/')
+ {
+ if (!(state & (YEAR|MONTH)) && n >= 1969 && n < 3000 && (i = strtol(s + 1, &t, 10)) > 0 && i <= 12)
+ {
+ state |= YEAR;
+ tm->tm_year = n - 1900;
+ s = t;
+ i--;
+ }
+ else
+ {
+ if ((state & MONTH) || n <= 0 || n > 31)
+ break;
+ if (isalpha(*++s))
+ {
+ if ((i = tmlex(s, &t, tm_info.format, TM_DAY_ABBREV, NiL, 0)) < 0)
+ break;
+ if (i >= TM_MONTH)
+ i -= TM_MONTH;
+ s = t;
+ }
+ else
+ {
+ i = n - 1;
+ n = strtol(s, &t, 10);
+ s = t;
+ if (n <= 0 || n > 31)
+ break;
+ if (*s == '/' && !isdigit(*(s + 1)))
+ break;
+ }
+ state |= DAY;
+ tm->tm_mday = n;
+ }
+ state |= MONTH;
+ n = tm->tm_mon;
+ tm->tm_mon = i;
+ if (*s == '/')
+ {
+ n = strtol(++s, &t, 10);
+ w = t - s;
+ s = t;
+ if (*s == '/' || *s == ':' || *s == '-' || *s == '_')
+ s++;
+ }
+ else
+ {
+ if (state & (LAST|NEXT|THIS))
+ {
+ rel_month:
+ if (state & LAST)
+ tm->tm_year -= (tm->tm_mon < n) ? 0 : 1;
+ else
+ tm->tm_year += ((state & NEXT) ? 1 : 0) + ((tm->tm_mon < n) ? 1 : 0);
+ if (state & MDAY)
+ goto clear_hour;
+ set &= ~(LAST|NEXT|THIS); /*AHA*/
+ state &= ~(LAST|NEXT|THIS); /*AHA*/
+ goto clear_mday;
+ }
+ continue;
+ }
+ }
+ if (n < 0 || w > 4)
+ break;
+ if (w == 4)
+ {
+ if ((state & YEAR) || n < 1969 || n >= 3000)
+ break;
+ state |= YEAR;
+ tm->tm_year = n - 1900;
+ }
+ else if (w == 3)
+ {
+ if (state & (MONTH|MDAY|WDAY))
+ break;
+ state |= MONTH|DAY|MDAY;
+ tm->tm_mon = 0;
+ tm->tm_mday = n;
+ }
+ else if (w == 2 && !(state & YEAR))
+ {
+ state |= YEAR;
+ if (n < TM_WINDOW)
+ n += 100;
+ tm->tm_year = n;
+ }
+ else if (!(state & MONTH) && n >= 1 && n <= 12)
+ {
+ state |= MONTH;
+ tm->tm_mon = n - 1;
+ }
+ else if (!(state & (MDAY|WDAY)) && n >= 1 && n <= 31)
+ {
+ state |= DAY|MDAY|WDAY;
+ tm->tm_mday = n;
+ }
+ else
+ break;
+ if (state & BREAK)
+ {
+ last = t;
+ break;
+ }
+ continue;
+ clear_mon:
+ if ((set|state) & (EXACT|MONTH))
+ continue;
+ tm->tm_mon = 0;
+ clear_mday:
+ set |= MONTH;
+ if ((set|state) & (EXACT|DAY|HOUR))
+ continue;
+ tm->tm_mday = 1;
+ clear_hour:
+ message((-1, "AHA#%d DAY", __LINE__));
+ set |= DAY;
+ if ((set|state) & (EXACT|HOUR))
+ continue;
+ tm->tm_hour = 0;
+ clear_min:
+ set |= HOUR;
+ if ((set|state) & (EXACT|MINUTE))
+ continue;
+ tm->tm_min = 0;
+ clear_sec:
+ set |= MINUTE;
+ if ((set|state) & (EXACT|SECOND))
+ continue;
+ tm->tm_sec = 0;
+ clear_nsec:
+ set |= SECOND;
+ if ((set|state) & (EXACT|NSEC))
+ continue;
+ tm->tm_nsec = 0;
+ }
+ done:
+ if (day >= 0 && !(state & (MDAY|WDAY)))
+ {
+ message((-1, "AHA#%d day=%d dir=%d state=" FFMT, __LINE__, day, dir, FLAGS(state)));
+ tmfix(tm);
+ m = dir;
+ if (state & MONTH)
+ tm->tm_mday = 1;
+ else if (m < 0)
+ m++;
+ tm = tmxtm(tm, tmxtime(tm, zone), tm->tm_zone);
+ j = day - tm->tm_wday;
+ if (j < 0)
+ j += 7;
+ tm->tm_mday += j + m * 7;
+ if (state & FINAL)
+ for (n = tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year)); (tm->tm_mday + 7) <= n; tm->tm_mday += 7);
+ }
+ else if (day < 0 && (state & FINAL) && (set & DAY))
+ {
+ tmfix(tm);
+ tm->tm_mday = tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year));
+ }
+ if (state & WORK)
+ {
+ tm->tm_mday = (set & FINAL) ? (tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year))) : 1;
+ tmfix(tm);
+ message((-1, "AHA#%d WORK mday=%d wday=%d", __LINE__, tm->tm_mday, tm->tm_wday));
+ if (tm->tm_wday == 0 && (j = 1) || tm->tm_wday == 6 && (j = 2))
+ {
+ if ((tm->tm_mday + j) > (tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year))))
+ j -= 3;
+ tm->tm_mday += j;
+ }
+ }
+ now = tmxtime(tm, zone);
+ if (tm->tm_year <= 70 && tmxsec(now) > 31536000)
+ {
+ now = 0;
+ last = (char*)o;
+ }
+ if (e)
+ *e = last;
+ return now;
+}
diff --git a/src/lib/libast/tm/tmxduration.c b/src/lib/libast/tm/tmxduration.c
new file mode 100644
index 0000000..eb456a9
--- /dev/null
+++ b/src/lib/libast/tm/tmxduration.c
@@ -0,0 +1,80 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <tmx.h>
+#include <ctype.h>
+
+/*
+ * parse duration expression in s and return Time_t value
+ * if non-null, e points to the first unused char in s
+ * returns 0 with *e==s on error
+ */
+
+Time_t
+tmxduration(const char* s, char** e)
+{
+ Time_t ns;
+ Time_t ts;
+ Time_t now;
+ char* last;
+ char* t;
+ char* x;
+ Sfio_t* f;
+ int i;
+
+ now = TMX_NOW;
+ while (isspace(*s))
+ s++;
+ if (*s == 'P' || *s == 'p')
+ ns = tmxdate(s, &last, now) - now;
+ else
+ {
+ ns = strtod(s, &last) * TMX_RESOLUTION;
+ if (*last && (f = sfstropen()))
+ {
+ sfprintf(f, "exact %s", s);
+ t = sfstruse(f);
+ ts = tmxdate(t, &x, now);
+ if ((i = x - t - 6) > (last - s))
+ {
+ last = (char*)s + i;
+ ns = ts - now;
+ }
+ else
+ {
+ sfprintf(f, "p%s", s);
+ t = sfstruse(f);
+ ts = tmxdate(t, &x, now);
+ if ((i = x - t - 1) > (last - s))
+ {
+ last = (char*)s + i;
+ ns = ts - now;
+ }
+ }
+ sfstrclose(f);
+ }
+ }
+ if (e)
+ *e = last;
+ return ns;
+}
diff --git a/src/lib/libast/tm/tmxfmt.c b/src/lib/libast/tm/tmxfmt.c
new file mode 100644
index 0000000..2010c08
--- /dev/null
+++ b/src/lib/libast/tm/tmxfmt.c
@@ -0,0 +1,703 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * Time_t conversion support
+ */
+
+#include <tmx.h>
+#include <ctype.h>
+
+#define warped(t,n) ((t)<((n)-tmxsns(6L*30L*24L*60L*60L,0))||(t)>((n)+tmxsns(24L*60L*60L,0)))
+
+/*
+ * format n with padding p into s
+ * return end of s
+ *
+ * p: <0 blank padding
+ * 0 no padding
+ * >0 0 padding
+ */
+
+static char*
+number(register char* s, register char* e, register long n, register int p, int w, int pad)
+{
+ char* b;
+
+ if (w)
+ {
+ if (p > 0 && (pad == 0 || pad == '0'))
+ while (w > p)
+ {
+ p++;
+ n *= 10;
+ }
+ else if (w > p)
+ p = w;
+ }
+ switch (pad)
+ {
+ case '-':
+ p = 0;
+ break;
+ case '_':
+ if (p > 0)
+ p = -p;
+ break;
+ case '0':
+ if (p < 0)
+ p = -p;
+ break;
+ }
+ b = s;
+ if (p > 0)
+ s += sfsprintf(s, e - s, "%0*lu", p, n);
+ else if (p < 0)
+ s += sfsprintf(s, e - s, "%*lu", -p, n);
+ else
+ s += sfsprintf(s, e - s, "%lu", n);
+ if (w && (s - b) > w)
+ *(s = b + w) = 0;
+ return s;
+}
+
+typedef struct Stack_s
+{
+ char* format;
+ int delimiter;
+} Stack_t;
+
+/*
+ * format t into buf of length len
+ * end of buf is returned
+ */
+
+char*
+tmxfmt(char* buf, size_t len, const char* format, Time_t t)
+{
+ register char* cp;
+ register char* ep;
+ register char* p;
+ register int n;
+ int c;
+ int i;
+ int flags;
+ int alt;
+ int pad;
+ int delimiter;
+ int width;
+ int prec;
+ int parts;
+ char* arg;
+ char* f;
+ const char* oformat;
+ Tm_t* tm;
+ Tm_zone_t* zp;
+ Time_t now;
+ Stack_t* sp;
+ Stack_t stack[8];
+ Tm_t ts;
+ char argbuf[256];
+ char fmt[32];
+
+ tmlocale();
+ tm = tmxtm(&ts, t, NiL);
+ if (!format || !*format)
+ format = tm_info.deformat;
+ oformat = format;
+ flags = tm_info.flags;
+ sp = &stack[0];
+ cp = buf;
+ ep = buf + len;
+ delimiter = 0;
+ for (;;)
+ {
+ if ((c = *format++) == delimiter)
+ {
+ delimiter = 0;
+ if (sp <= &stack[0])
+ break;
+ sp--;
+ format = sp->format;
+ delimiter = sp->delimiter;
+ continue;
+ }
+ if (c != '%')
+ {
+ if (cp < ep)
+ *cp++ = c;
+ continue;
+ }
+ alt = 0;
+ arg = 0;
+ pad = 0;
+ width = 0;
+ prec = 0;
+ parts = 0;
+ for (;;)
+ {
+ switch (c = *format++)
+ {
+ case '_':
+ case '-':
+ pad = c;
+ continue;
+ case 'E':
+ case 'O':
+ if (!isalpha(*format))
+ break;
+ alt = c;
+ continue;
+ case '0':
+ if (!parts)
+ {
+ pad = c;
+ continue;
+ }
+ /*FALLTHROUGH*/
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ switch (parts)
+ {
+ case 0:
+ parts++;
+ /*FALLTHROUGH*/
+ case 1:
+ width = width * 10 + (c - '0');
+ break;
+ case 2:
+ prec = prec * 10 + (c - '0');
+ break;
+ }
+ continue;
+ case '.':
+ if (!parts++)
+ parts++;
+ continue;
+ case '(':
+ i = 1;
+ arg = argbuf;
+ for (;;)
+ {
+ if (!(c = *format++))
+ {
+ format--;
+ break;
+ }
+ else if (c == '(')
+ i++;
+ else if (c == ')' && !--i)
+ break;
+ else if (arg < &argbuf[sizeof(argbuf) - 1])
+ *arg++ = c;
+ }
+ *arg = 0;
+ arg = argbuf;
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+ switch (c)
+ {
+ case 0:
+ format--;
+ continue;
+ case '%':
+ if (cp < ep)
+ *cp++ = '%';
+ continue;
+ case '?':
+ if (tm_info.deformat != tm_info.format[TM_DEFAULT])
+ format = tm_info.deformat;
+ else if (!*format)
+ format = tm_info.format[TM_DEFAULT];
+ continue;
+ case 'a': /* abbreviated day of week name */
+ n = TM_DAY_ABBREV + tm->tm_wday;
+ goto index;
+ case 'A': /* day of week name */
+ n = TM_DAY + tm->tm_wday;
+ goto index;
+ case 'b': /* abbreviated month name */
+ case 'h':
+ n = TM_MONTH_ABBREV + tm->tm_mon;
+ goto index;
+ case 'B': /* month name */
+ n = TM_MONTH + tm->tm_mon;
+ goto index;
+ case 'c': /* `ctime(3)' date sans newline */
+ p = tm_info.format[TM_CTIME];
+ goto push;
+ case 'C': /* 2 digit century */
+ cp = number(cp, ep, (long)(1900 + tm->tm_year) / 100, 2, width, pad);
+ continue;
+ case 'd': /* day of month */
+ cp = number(cp, ep, (long)tm->tm_mday, 2, width, pad);
+ continue;
+ case 'D': /* date */
+ p = tm_info.format[TM_DATE];
+ goto push;
+ case 'e': /* blank padded day of month */
+ cp = number(cp, ep, (long)tm->tm_mday, -2, width, pad);
+ continue;
+ case 'f': /* (AST) OBSOLETE use %Qf */
+ p = "%Qf";
+ goto push;
+ case 'F': /* ISO 8601:2000 standard date format */
+ p = "%Y-%m-%d";
+ goto push;
+ case 'g': /* %V 2 digit year */
+ case 'G': /* %V 4 digit year */
+ n = tm->tm_year + 1900;
+ if (tm->tm_yday < 7)
+ {
+ if (tmweek(tm, 2, -1, -1) >= 52)
+ n--;
+ }
+ else if (tm->tm_yday > 358)
+ {
+ if (tmweek(tm, 2, -1, -1) <= 1)
+ n++;
+ }
+ if (c == 'g')
+ {
+ n %= 100;
+ c = 2;
+ }
+ else
+ c = 4;
+ cp = number(cp, ep, (long)n, c, width, pad);
+ continue;
+ case 'H': /* hour (0 - 23) */
+ cp = number(cp, ep, (long)tm->tm_hour, 2, width, pad);
+ continue;
+ case 'i': /* (AST) OBSOLETE use %QI */
+ p = "%QI";
+ goto push;
+ case 'I': /* hour (0 - 12) */
+ if ((n = tm->tm_hour) > 12) n -= 12;
+ else if (n == 0) n = 12;
+ cp = number(cp, ep, (long)n, 2, width, pad);
+ continue;
+ case 'j': /* Julian date (1 offset) */
+ cp = number(cp, ep, (long)(tm->tm_yday + 1), 3, width, pad);
+ continue;
+ case 'J': /* Julian date (0 offset) */
+ cp = number(cp, ep, (long)tm->tm_yday, 3, width, pad);
+ continue;
+ case 'k': /* (AST) OBSOLETE use %QD */
+ p = "%QD";
+ goto push;
+ case 'K': /* (AST) largest to smallest */
+ switch (alt)
+ {
+ case 'E':
+ p = (pad == '_') ? "%Y-%m-%d %H:%M:%S.%N %z" : "%Y-%m-%d+%H:%M:%S.%N%z";
+ break;
+ case 'O':
+ p = (pad == '_') ? "%Y-%m-%d %H:%M:%S.%N" : "%Y-%m-%d+%H:%M:%S.%N";
+ break;
+ default:
+ p = (pad == '_') ? "%Y-%m-%d %H:%M:%S" : "%Y-%m-%d+%H:%M:%S";
+ break;
+ }
+ goto push;
+ case 'l': /* (AST) OBSOLETE use %QL */
+ p = "%QL";
+ goto push;
+ case 'L': /* (AST) OBSOLETE use %Ql */
+ p = "%Ql";
+ goto push;
+ case 'm': /* month number */
+ cp = number(cp, ep, (long)(tm->tm_mon + 1), 2, width, pad);
+ continue;
+ case 'M': /* minutes */
+ cp = number(cp, ep, (long)tm->tm_min, 2, width, pad);
+ continue;
+ case 'n':
+ if (cp < ep)
+ *cp++ = '\n';
+ continue;
+ case 'N': /* (AST|GNU) nanosecond part */
+ cp = number(cp, ep, (long)tm->tm_nsec, 9, width, pad);
+ continue;
+#if 0
+ case 'o': /* (UNUSED) */
+ continue;
+#endif
+ case 'p': /* meridian */
+ n = TM_MERIDIAN + (tm->tm_hour >= 12);
+ goto index;
+ case 'P': /* (AST|GNU) lower case meridian */
+ p = tm_info.format[TM_MERIDIAN + (tm->tm_hour >= 12)];
+ while (cp < ep && (n = *p++))
+ *cp++ = isupper(n) ? tolower(n) : n;
+ continue;
+ case 'q': /* (AST) OBSOLETE use %Qz */
+ p = "%Qz";
+ goto push;
+ case 'Q': /* (AST) %Q<alpha> or %Q<delim>recent<delim>distant<delim> */
+ if (c = *format)
+ {
+ format++;
+ if (isalpha(c))
+ {
+ switch (c)
+ {
+ case 'd': /* `ls -l' distant date */
+ p = tm_info.format[TM_DISTANT];
+ goto push;
+ case 'D': /* `date(1)' date */
+ p = tm_info.format[TM_DATE_1];
+ goto push;
+ case 'f': /* TM_DEFAULT override */
+ p = tm_info.deformat;
+ goto push;
+ case 'I': /* international `date(1)' date */
+ p = tm_info.format[TM_INTERNATIONAL];
+ goto push;
+ case 'l': /* TM_DEFAULT */
+ p = tm_info.format[TM_DEFAULT];
+ goto push;
+ case 'L': /* `ls -l' date */
+ if (t)
+ {
+ now = tmxgettime();
+ if (warped(t, now))
+ {
+ p = tm_info.format[TM_DISTANT];
+ goto push;
+ }
+ }
+ p = tm_info.format[TM_RECENT];
+ goto push;
+ case 'o': /* set options ( %([+-]flag...)o ) */
+ if (arg)
+ {
+ c = '+';
+ i = 0;
+ for (;;)
+ {
+ switch (*arg++)
+ {
+ case 0:
+ n = 0;
+ break;
+ case '=':
+ i = !i;
+ continue;
+ case '+':
+ case '-':
+ case '!':
+ c = *(arg - 1);
+ continue;
+ case 'l':
+ n = TM_LEAP;
+ break;
+ case 'n':
+ case 's':
+ n = TM_SUBSECOND;
+ break;
+ case 'u':
+ n = TM_UTC;
+ break;
+ default:
+ continue;
+ }
+ if (!n)
+ break;
+
+ /*
+ * right, the global state stinks
+ * but we respect its locale-like status
+ */
+
+ if (c == '+')
+ {
+ if (!(flags & n))
+ {
+ flags |= n;
+ tm_info.flags |= n;
+ tm = tmxtm(tm, t, (flags & TM_UTC) ? &tm_data.zone[2] : tm->tm_zone);
+ if (!i)
+ tm_info.flags &= ~n;
+ }
+ }
+ else if (flags & n)
+ {
+ flags &= ~n;
+ tm_info.flags &= ~n;
+ tm = tmxtm(tm, t, (flags & TM_UTC) ? &tm_data.zone[2] : tm->tm_zone);
+ if (!i)
+ tm_info.flags |= n;
+ }
+ }
+ }
+ break;
+ case 'r': /* `ls -l' recent date */
+ p = tm_info.format[TM_RECENT];
+ goto push;
+ case 'z': /* time zone nation code */
+ if (!(flags & TM_UTC))
+ {
+ if ((zp = tm->tm_zone) != tm_info.local)
+ for (; zp >= tm_data.zone; zp--)
+ if (p = zp->type)
+ goto string;
+ else if (p = zp->type)
+ goto string;
+ }
+ break;
+ default:
+ format--;
+ break;
+ }
+ }
+ else
+ {
+ if (t)
+ {
+ now = tmxgettime();
+ p = warped(t, now) ? (char*)0 : (char*)format;
+ }
+ else
+ p = (char*)format;
+ i = 0;
+ while (n = *format)
+ {
+ format++;
+ if (n == c)
+ {
+ if (!p)
+ p = (char*)format;
+ if (++i == 2)
+ goto push_delimiter;
+ }
+ }
+ }
+ }
+ continue;
+ case 'r':
+ p = tm_info.format[TM_MERIDIAN_TIME];
+ goto push;
+ case 'R':
+ p = "%H:%M";
+ goto push;
+ case 's': /* (DEFACTO) seconds[.nanoseconds] since the epoch */
+ case '#':
+ now = t;
+ f = fmt;
+ *f++ = '%';
+ if (pad == '0')
+ *f++ = pad;
+ if (width)
+ f += sfsprintf(f, &fmt[sizeof(fmt)] - f, "%d", width);
+ f += sfsprintf(f, &fmt[sizeof(fmt)] - f, "I%du", sizeof(Tmxsec_t));
+ cp += sfsprintf(cp, ep - cp, fmt, tmxsec(now));
+ if (parts > 1)
+ {
+ n = sfsprintf(cp, ep - cp, ".%09I*u", sizeof(Tmxnsec_t), tmxnsec(now));
+ if (prec && n >= prec)
+ n = prec + 1;
+ cp += n;
+ }
+ continue;
+ case 'S': /* seconds */
+ cp = number(cp, ep, (long)tm->tm_sec, 2, width, pad);
+ if ((flags & TM_SUBSECOND) && (format - 2) != oformat)
+ {
+ p = ".%N";
+ goto push;
+ }
+ continue;
+ case 't':
+ if (cp < ep)
+ *cp++ = '\t';
+ continue;
+ case 'T':
+ p = tm_info.format[TM_TIME];
+ goto push;
+ case 'u': /* weekday number [1(Monday)-7] */
+ if (!(i = tm->tm_wday))
+ i = 7;
+ cp = number(cp, ep, (long)i, 0, width, pad);
+ continue;
+ case 'U': /* week number, Sunday as first day */
+ cp = number(cp, ep, (long)tmweek(tm, 0, -1, -1), 2, width, pad);
+ continue;
+#if 0
+ case 'v': /* (UNUSED) */
+ continue;
+#endif
+ case 'V': /* ISO week number */
+ cp = number(cp, ep, (long)tmweek(tm, 2, -1, -1), 2, width, pad);
+ continue;
+ case 'W': /* week number, Monday as first day */
+ cp = number(cp, ep, (long)tmweek(tm, 1, -1, -1), 2, width, pad);
+ continue;
+ case 'w': /* weekday number [0(Sunday)-6] */
+ cp = number(cp, ep, (long)tm->tm_wday, 0, width, pad);
+ continue;
+ case 'x':
+ p = tm_info.format[TM_DATE];
+ goto push;
+ case 'X':
+ p = tm_info.format[TM_TIME];
+ goto push;
+ case 'y': /* year in the form yy */
+ cp = number(cp, ep, (long)(tm->tm_year % 100), 2, width, pad);
+ continue;
+ case 'Y': /* year in the form ccyy */
+ cp = number(cp, ep, (long)(1900 + tm->tm_year), 4, width, pad);
+ continue;
+ case 'z': /* time zone west offset */
+ if (arg)
+ {
+ if ((zp = tmzone(arg, &f, 0, 0)) && !*f && tm->tm_zone != zp)
+ tm = tmxtm(tm, tmxtime(tm, tm->tm_zone->west + (tm->tm_isdst ? tm->tm_zone->dst : 0)), zp);
+ continue;
+ }
+ if ((ep - cp) >= 16)
+ cp = tmpoff(cp, ep - cp, "", (flags & TM_UTC) ? 0 : tm->tm_zone->west + (tm->tm_isdst ? tm->tm_zone->dst : 0), pad == '_' ? -24 * 60 : 24 * 60);
+ continue;
+ case 'Z': /* time zone */
+ if (arg)
+ {
+ if ((zp = tmzone(arg, &f, 0, 0)) && !*f && tm->tm_zone != zp)
+ tm = tmxtm(tm, tmxtime(tm, tm->tm_zone->west + (tm->tm_isdst ? tm->tm_zone->dst : 0)), zp);
+ continue;
+ }
+ p = (flags & TM_UTC) ? tm_info.format[TM_UT] : tm->tm_isdst && tm->tm_zone->daylight ? tm->tm_zone->daylight : tm->tm_zone->standard;
+ goto string;
+ case '=': /* (AST) OBSOLETE use %([+-]flag...)Qo (old %=[=][+-]flag) */
+ for (arg = argbuf; *format == '=' || *format == '-' || *format == '+' || *format == '!'; format++)
+ if (arg < &argbuf[sizeof(argbuf) - 2])
+ *arg++ = *format;
+ if (*arg++ = *format)
+ format++;
+ *arg = 0;
+ arg = argbuf;
+ goto options;
+ default:
+ if (cp < ep)
+ *cp++ = '%';
+ if (cp < ep)
+ *cp++ = c;
+ continue;
+ }
+ index:
+ p = tm_info.format[n];
+ string:
+ while (cp < ep && (*cp = *p++))
+ cp++;
+ continue;
+ options:
+ c = '+';
+ i = 0;
+ for (;;)
+ {
+ switch (*arg++)
+ {
+ case 0:
+ n = 0;
+ break;
+ case '=':
+ i = !i;
+ continue;
+ case '+':
+ case '-':
+ case '!':
+ c = *(arg - 1);
+ continue;
+ case 'l':
+ n = TM_LEAP;
+ break;
+ case 'n':
+ case 's':
+ n = TM_SUBSECOND;
+ break;
+ case 'u':
+ n = TM_UTC;
+ break;
+ default:
+ continue;
+ }
+ if (!n)
+ break;
+
+ /*
+ * right, the global state stinks
+ * but we respect its locale-like status
+ */
+
+ if (c == '+')
+ {
+ if (!(flags & n))
+ {
+ flags |= n;
+ tm_info.flags |= n;
+ tm = tmxtm(tm, t, (flags & TM_UTC) ? &tm_data.zone[2] : tm->tm_zone);
+ if (!i)
+ tm_info.flags &= ~n;
+ }
+ }
+ else if (flags & n)
+ {
+ flags &= ~n;
+ tm_info.flags &= ~n;
+ tm = tmxtm(tm, t, (flags & TM_UTC) ? &tm_data.zone[2] : tm->tm_zone);
+ if (!i)
+ tm_info.flags |= n;
+ }
+ }
+ continue;
+ push:
+ c = 0;
+ push_delimiter:
+ if (sp < &stack[elementsof(stack)])
+ {
+ sp->format = (char*)format;
+ format = p;
+ sp->delimiter = delimiter;
+ delimiter = c;
+ sp++;
+ }
+ continue;
+ }
+ tm_info.flags = flags;
+ if (cp >= ep)
+ cp = ep - 1;
+ *cp = 0;
+ return cp;
+}
diff --git a/src/lib/libast/tm/tmxgettime.c b/src/lib/libast/tm/tmxgettime.c
new file mode 100644
index 0000000..7ce13f3
--- /dev/null
+++ b/src/lib/libast/tm/tmxgettime.c
@@ -0,0 +1,44 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * Time_t conversion support
+ */
+
+#include <tmx.h>
+#include <tv.h>
+
+/*
+ * return current Time_t
+ */
+
+Time_t
+tmxgettime(void)
+{
+ Tv_t tv;
+
+ tvgettime(&tv);
+ return tmxsns(tv.tv_sec, tv.tv_nsec);
+}
diff --git a/src/lib/libast/tm/tmxleap.c b/src/lib/libast/tm/tmxleap.c
new file mode 100644
index 0000000..ce07c5a
--- /dev/null
+++ b/src/lib/libast/tm/tmxleap.c
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * Time_t conversion support
+ */
+
+#include <tmx.h>
+
+/*
+ * return t with leap seconds adjusted
+ * for direct localtime() access
+ */
+
+Time_t
+tmxleap(Time_t t)
+{
+ register Tm_leap_t* lp;
+ uint32_t sec;
+
+ tmset(tm_info.zone);
+ if (tm_info.flags & TM_ADJUST)
+ {
+ sec = tmxsec(t);
+ for (lp = &tm_data.leap[0]; sec < (lp->time - lp->total); lp++);
+ t = tmxsns(sec + lp->total, tmxnsec(t));
+ }
+ return t;
+}
diff --git a/src/lib/libast/tm/tmxmake.c b/src/lib/libast/tm/tmxmake.c
new file mode 100644
index 0000000..a985633
--- /dev/null
+++ b/src/lib/libast/tm/tmxmake.c
@@ -0,0 +1,140 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * Time_t conversion support
+ */
+
+#include <tmx.h>
+
+#include "FEATURE/tmlib"
+
+/*
+ * return Tm_t for t
+ * time zone and leap seconds accounted for in return value
+ */
+
+Tm_t*
+tmxtm(register Tm_t* tm, Time_t t, Tm_zone_t* zone)
+{
+ register struct tm* tp;
+ register Tm_leap_t* lp;
+ Time_t x;
+ time_t now;
+ int leapsec;
+ int y;
+ uint32_t n;
+ int32_t o;
+#if TMX_FLOAT
+ Time_t z;
+ uint32_t i;
+#endif
+
+ tmset(tm_info.zone);
+ leapsec = 0;
+ if ((tm_info.flags & (TM_ADJUST|TM_LEAP)) == (TM_ADJUST|TM_LEAP) && (n = tmxsec(t)))
+ {
+ for (lp = &tm_data.leap[0]; n < lp->time; lp++);
+ if (lp->total)
+ {
+ if (n == lp->time && (leapsec = (lp->total - (lp+1)->total)) < 0)
+ leapsec = 0;
+ t = tmxsns(n - lp->total, tmxnsec(t));
+ }
+ }
+ x = tmxsec(t);
+ if (!(tm->tm_zone = zone))
+ {
+ if (tm_info.flags & TM_UTC)
+ tm->tm_zone = &tm_data.zone[2];
+ else
+ tm->tm_zone = tm_info.zone;
+ }
+ if ((o = 60 * tm->tm_zone->west) && x > o)
+ {
+ x -= o;
+ o = 0;
+ }
+#if TMX_FLOAT
+ i = x / (24 * 60 * 60);
+ z = i;
+ n = x - z * (24 * 60 * 60);
+ tm->tm_sec = n % 60 + leapsec;
+ n /= 60;
+ tm->tm_min = n % 60;
+ n /= 60;
+ tm->tm_hour = n % 24;
+#define x i
+#else
+ tm->tm_sec = x % 60 + leapsec;
+ x /= 60;
+ tm->tm_min = x % 60;
+ x /= 60;
+ tm->tm_hour = x % 24;
+ x /= 24;
+#endif
+ tm->tm_wday = (x + 4) % 7;
+ tm->tm_year = (400 * (x + 25202)) / 146097 + 1;
+ n = tm->tm_year - 1;
+ x -= n * 365 + n / 4 - n / 100 + (n + (1900 - 1600)) / 400 - (1970 - 1901) * 365 - (1970 - 1901) / 4;
+ tm->tm_mon = 0;
+ tm->tm_mday = x + 1;
+ tm->tm_nsec = tmxnsec(t);
+ tmfix(tm);
+ n += 1900;
+ tm->tm_isdst = 0;
+ if (tm->tm_zone->daylight)
+ {
+ if ((y = tmequiv(tm) - 1900) == tm->tm_year)
+ now = tmxsec(t);
+ else
+ {
+ Tm_t te;
+
+ te = *tm;
+ te.tm_year = y;
+ now = tmxsec(tmxtime(&te, tm->tm_zone->west));
+ }
+ if ((tp = tmlocaltime(&now)) && ((tm->tm_isdst = tp->tm_isdst) || o))
+ {
+ tm->tm_min -= o / 60 + (tm->tm_isdst ? tm->tm_zone->dst : 0);
+ tmfix(tm);
+ }
+ }
+ return tm;
+}
+
+/*
+ * return Tm_t for t
+ * time zone and leap seconds accounted for in return value
+ */
+
+Tm_t*
+tmxmake(Time_t t)
+{
+ static Tm_t ts;
+
+ return tmxtm(&ts, t, NiL);
+}
diff --git a/src/lib/libast/tm/tmxscan.c b/src/lib/libast/tm/tmxscan.c
new file mode 100644
index 0000000..98d4749
--- /dev/null
+++ b/src/lib/libast/tm/tmxscan.c
@@ -0,0 +1,533 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * Time_t conversion support
+ *
+ * scan date expression in s using format
+ * if non-null, e points to the first invalid sequence in s
+ * if non-null, f points to the first unused format char
+ * t provides default values
+ */
+
+#include <tmx.h>
+#include <ctype.h>
+
+typedef struct
+{
+ int32_t nsec;
+ int year;
+ int mon;
+ int week;
+ int weektype;
+ int yday;
+ int mday;
+ int wday;
+ int hour;
+ int min;
+ int sec;
+ int meridian;
+ int zone;
+} Set_t;
+
+#define CLEAR(s) (s.year=s.mon=s.week=s.weektype=s.yday=s.mday=s.wday=s.hour=s.min=s.sec=s.meridian=(-1),s.nsec=1000000000L,s.zone=TM_LOCALZONE)
+
+#define INDEX(m,x) (((n)>=((x)-(m)))?((n)-=((x)-(m))):(n))
+
+#define NUMBER(d,m,x) do \
+ { \
+ n = 0; \
+ u = (char*)s; \
+ while (s < (const char*)(u + d) && *s >= '0' && *s <= '9') \
+ n = n * 10 + *s++ - '0'; \
+ if (u == (char*)s || n < m || n > x) \
+ goto next; \
+ } while (0)
+
+/*
+ * generate a Time_t from tm + set
+ */
+
+static Time_t
+gen(register Tm_t* tm, register Set_t* set)
+{
+ register int n;
+ int z;
+ Time_t t;
+
+ if (set->year >= 0)
+ tm->tm_year = set->year;
+ if (set->mon >= 0)
+ {
+ if (set->year < 0 && set->mon < tm->tm_mon)
+ tm->tm_year++;
+ tm->tm_mon = set->mon;
+ if (set->yday < 0 && set->mday < 0)
+ tm->tm_mday = set->mday = 1;
+ }
+ if (set->week >= 0)
+ {
+ if (set->mon < 0)
+ {
+ tmweek(tm, set->weektype, set->week, set->wday);
+ set->wday = -1;
+ }
+ }
+ else if (set->yday >= 0)
+ {
+ if (set->mon < 0)
+ {
+ tm->tm_mon = 0;
+ tm->tm_mday = set->yday + 1;
+ }
+ }
+ else if (set->mday >= 0)
+ tm->tm_mday = set->mday;
+ if (set->hour >= 0)
+ {
+ if (set->hour < tm->tm_hour && set->yday < 0 && set->mday < 0 && set->wday < 0)
+ tm->tm_mday++;
+ tm->tm_hour = set->hour;
+ tm->tm_min = (set->min >= 0) ? set->min : 0;
+ tm->tm_sec = (set->sec >= 0) ? set->sec : 0;
+ }
+ else if (set->min >= 0)
+ {
+ tm->tm_min = set->min;
+ tm->tm_sec = (set->sec >= 0) ? set->sec : 0;
+ }
+ else if (set->sec >= 0)
+ tm->tm_sec = set->sec;
+ if (set->nsec < 1000000000L)
+ tm->tm_nsec = set->nsec;
+ if (set->meridian > 0)
+ {
+ if (tm->tm_hour < 12)
+ tm->tm_hour += 12;
+ }
+ else if (set->meridian == 0)
+ {
+ if (tm->tm_hour >= 12)
+ tm->tm_hour -= 12;
+ }
+ t = tmxtime(tm, set->zone);
+ if (set->yday >= 0)
+ {
+ z = 1;
+ tm = tmxtm(tm, t, tm->tm_zone);
+ tm->tm_mday += set->yday - tm->tm_yday;
+ }
+ else if (set->wday >= 0)
+ {
+ z = 1;
+ tm = tmxtm(tm, t, tm->tm_zone);
+ if ((n = set->wday - tm->tm_wday) < 0)
+ n += 7;
+ tm->tm_mday += n;
+ }
+ else
+ z = 0;
+ if (set->nsec < 1000000000L)
+ {
+ if (!z)
+ {
+ z = 1;
+ tm = tmxtm(tm, t, tm->tm_zone);
+ }
+ tm->tm_nsec = set->nsec;
+ }
+ return z ? tmxtime(tm, set->zone) : t;
+}
+
+/*
+ * the format scan workhorse
+ */
+
+static Time_t
+scan(register const char* s, char** e, const char* format, char** f, Time_t t, long flags)
+{
+ register int d;
+ register int n;
+ register char* p;
+ register Tm_t* tm;
+ const char* b;
+ char* u;
+ char* stack[4];
+ int m;
+ int hi;
+ int lo;
+ int pedantic;
+ Time_t x;
+ Set_t set;
+ Tm_zone_t* zp;
+ Tm_t ts;
+
+ char** sp = &stack[0];
+
+ while (isspace(*s))
+ s++;
+ b = s;
+ again:
+ CLEAR(set);
+ tm = tmxtm(&ts, t, NiL);
+ pedantic = (flags & TM_PEDANTIC) != 0;
+ for (;;)
+ {
+ if (!(d = *format++))
+ {
+ if (sp <= &stack[0])
+ {
+ format--;
+ break;
+ }
+ format = (const char*)*--sp;
+ }
+ else if (!*s)
+ {
+ format--;
+ break;
+ }
+ else if (d == '%' && (d = *format) && format++ && d != '%')
+ {
+ more:
+ switch (d)
+ {
+ case 'a':
+ lo = TM_DAY_ABBREV;
+ hi = pedantic ? TM_DAY : TM_TIME;
+ goto get_wday;
+ case 'A':
+ lo = pedantic ? TM_DAY : TM_DAY_ABBREV;
+ hi = TM_TIME;
+ get_wday:
+ if ((n = tmlex(s, &u, tm_info.format + lo, hi - lo, NiL, 0)) < 0)
+ goto next;
+ s = u;
+ INDEX(TM_DAY_ABBREV, TM_DAY);
+ set.wday = n;
+ continue;
+ case 'b':
+ case 'h':
+ lo = TM_MONTH_ABBREV;
+ hi = pedantic ? TM_MONTH : TM_DAY_ABBREV;
+ goto get_mon;
+ case 'B':
+ lo = pedantic ? TM_MONTH : TM_MONTH_ABBREV;
+ hi = TM_DAY_ABBREV;
+ get_mon:
+ if ((n = tmlex(s, &u, tm_info.format + lo, hi - lo, NiL, 0)) < 0)
+ goto next;
+ s = u;
+ INDEX(TM_MONTH_ABBREV, TM_MONTH);
+ set.mon = n;
+ continue;
+ case 'c':
+ p = "%a %b %e %T %Y";
+ break;
+ case 'C':
+ NUMBER(2, 19, 99);
+ set.year = (n - 19) * 100 + tm->tm_year % 100;
+ continue;
+ case 'd':
+ if (pedantic && !isdigit(*s))
+ goto next;
+ /*FALLTHROUGH*/
+ case 'e':
+ NUMBER(2, 1, 31);
+ set.mday = n;
+ continue;
+ case 'D':
+ p = "%m/%d/%y";
+ break;
+ case 'E':
+ case 'O':
+ if (*format)
+ {
+ d = *format++;
+ goto more;
+ }
+ continue;
+ case 'F':
+ p = "%Y-%m-%d";
+ break;
+ case 'H':
+ case 'k':
+ NUMBER(2, 0, 23);
+ set.hour = n;
+ continue;
+ case 'I':
+ case 'l':
+ NUMBER(2, 1, 12);
+ set.hour = n;
+ continue;
+ case 'j':
+ NUMBER(3, 1, 366);
+ set.yday = n - 1;
+ continue;
+ case 'm':
+ NUMBER(2, 1, 12);
+ set.mon = n - 1;
+ continue;
+ case 'M':
+ NUMBER(2, 0, 59);
+ set.min = n;
+ continue;
+ case 'n':
+ if (pedantic)
+ while (*s == '\n')
+ s++;
+ else
+ while (isspace(*s))
+ s++;
+ continue;
+ case 'N':
+ NUMBER(9, 0, 999999999L);
+ set.nsec = n;
+ continue;
+ case 'p':
+ if ((n = tmlex(s, &u, tm_info.format + TM_MERIDIAN, TM_UT - TM_MERIDIAN, NiL, 0)) < 0)
+ goto next;
+ set.meridian = n;
+ s = u;
+ continue;
+ case 'r':
+ p = "%I:%M:%S %p";
+ break;
+ case 'R':
+ p = "%H:%M:%S";
+ break;
+ case 's':
+ x = strtoul(s, &u, 0);
+ if (s == u)
+ goto next;
+ tm = tmxtm(tm, tmxsns(x, 0), tm->tm_zone);
+ s = u;
+ CLEAR(set);
+ continue;
+ case 'S':
+ NUMBER(2, 0, 61);
+ set.sec = n;
+ continue;
+ case 'u':
+ NUMBER(2, 1, 7);
+ set.wday = n % 7;
+ continue;
+ case 'U':
+ NUMBER(2, 0, 52);
+ set.week = n;
+ set.weektype = 0;
+ continue;
+ case 'V':
+ NUMBER(2, 1, 53);
+ set.week = n;
+ set.weektype = 2;
+ continue;
+ case 'w':
+ NUMBER(2, 0, 6);
+ set.wday = n;
+ continue;
+ case 'W':
+ NUMBER(2, 0, 52);
+ set.week = n;
+ set.weektype = 1;
+ continue;
+ case 'x':
+ p = tm_info.format[TM_DATE];
+ break;
+ case 'X':
+ p = tm_info.format[TM_TIME];
+ break;
+ case 'y':
+ NUMBER(2, 0, 99);
+ if (n < TM_WINDOW)
+ n += 100;
+ set.year = n;
+ continue;
+ case 'Y':
+ NUMBER(4, 1969, 2100);
+ set.year = n - 1900;
+ continue;
+ case 'Z':
+ case 'q':
+ if (zp = tmtype(s, &u))
+ {
+ s = u;
+ u = zp->type;
+ }
+ else
+ u = 0;
+ if (d == 'q')
+ continue;
+ case 'z':
+ if ((zp = tmzone(s, &u, u, &m)))
+ {
+ s = u;
+ set.zone = zp->west + m;
+ tm_info.date = zp;
+ }
+ continue;
+ case '|':
+ s = b;
+ goto again;
+ case '&':
+ x = gen(tm, &set);
+ x = tmxdate(s, e, t);
+ if (s == (const char*)*e)
+ goto next;
+ t = x;
+ s = (const char*)*e;
+ if (!*format || *format == '%' && *(format + 1) == '|')
+ goto done;
+ goto again;
+ default:
+ goto next;
+ }
+ if (sp >= &stack[elementsof(stack)])
+ goto next;
+ *sp++ = (char*)format;
+ format = (const char*)p;
+ }
+ else if (isspace(d))
+ while (isspace(*s))
+ s++;
+ else if (*s != d)
+ break;
+ else
+ s++;
+ }
+ next:
+ if (sp > &stack[0])
+ format = (const char*)stack[0];
+ if (*format)
+ {
+ p = (char*)format;
+ if (!*s && *p == '%' && *(p + 1) == '|')
+ format += strlen(format);
+ else
+ while (*p)
+ if (*p++ == '%' && *p && *p++ == '|' && *p)
+ {
+ format = (const char*)p;
+ s = b;
+ goto again;
+ }
+ }
+ t = gen(tm, &set);
+ done:
+ if (e)
+ {
+ while (isspace(*s))
+ s++;
+ *e = (char*)s;
+ }
+ if (f)
+ {
+ while (isspace(*format))
+ format++;
+ *f = (char*)format;
+ }
+ return t;
+}
+
+/*
+ * format==0 DATEMSK
+ * *format==0 DATEMSK and tmxdate()
+ * *format!=0 format
+ */
+
+Time_t
+tmxscan(const char* s, char** e, const char* format, char** f, Time_t t, long flags)
+{
+ register char* v;
+ register char** p;
+ char* q;
+ char* r;
+ Time_t x;
+
+ static int initialized;
+ static char** datemask;
+
+ tmlocale();
+ if (!format || !*format)
+ {
+ if (!initialized)
+ {
+ register Sfio_t* sp;
+ register int n;
+ off_t m;
+
+ initialized = 1;
+ if ((v = getenv("DATEMSK")) && *v && (sp = sfopen(NiL, v, "r")))
+ {
+ for (n = 1; sfgetr(sp, '\n', 0); n++);
+ m = sfseek(sp, 0L, SEEK_CUR);
+ if (p = newof(0, char*, n, m))
+ {
+ sfseek(sp, 0L, SEEK_SET);
+ v = (char*)(p + n);
+ if (sfread(sp, v, m) != m)
+ {
+ free(p);
+ p = 0;
+ }
+ else
+ {
+ datemask = p;
+ v[m] = 0;
+ while (*v)
+ {
+ *p++ = v;
+ if (!(v = strchr(v, '\n')))
+ break;
+ *v++ = 0;
+ }
+ *p = 0;
+ }
+ }
+ }
+ }
+ if (p = datemask)
+ while (v = *p++)
+ {
+ x = scan(s, &q, v, &r, t, flags);
+ if (!*q && !*r)
+ {
+ if (e)
+ *e = q;
+ if (f)
+ *f = r;
+ return x;
+ }
+ }
+ if (f)
+ *f = (char*)format;
+ if (format)
+ return tmxdate(s, e, t);
+ if (e)
+ *e = (char*)s;
+ return 0;
+ }
+ return scan(s, e, format, f, t, flags);
+}
diff --git a/src/lib/libast/tm/tmxsettime.c b/src/lib/libast/tm/tmxsettime.c
new file mode 100644
index 0000000..90bee75
--- /dev/null
+++ b/src/lib/libast/tm/tmxsettime.c
@@ -0,0 +1,45 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * Time_t conversion support
+ */
+
+#include <tmx.h>
+#include <tv.h>
+
+/*
+ * return current current time to t
+ */
+
+int
+tmxsettime(Time_t t)
+{
+ Tv_t tv;
+
+ tv.tv_sec = tmxsec(t);
+ tv.tv_nsec = tmxnsec(t);
+ return tvsettime(&tv);
+}
diff --git a/src/lib/libast/tm/tmxsleep.c b/src/lib/libast/tm/tmxsleep.c
new file mode 100644
index 0000000..9de8f9a
--- /dev/null
+++ b/src/lib/libast/tm/tmxsleep.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * Time_t sleep
+ */
+
+#include <tmx.h>
+#include <tv.h>
+
+int
+tmxsleep(Time_t t)
+{
+ Tv_t tv;
+
+ tv.tv_sec = tmxsec(t);
+ tv.tv_nsec = tmxnsec(t);
+ return tvsleep(&tv, NiL);
+}
diff --git a/src/lib/libast/tm/tmxtime.c b/src/lib/libast/tm/tmxtime.c
new file mode 100644
index 0000000..6951f8a
--- /dev/null
+++ b/src/lib/libast/tm/tmxtime.c
@@ -0,0 +1,137 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * Time_t conversion support
+ */
+
+#include <tmx.h>
+
+#include "FEATURE/tmlib"
+
+/*
+ * convert Tm_t to Time_t
+ *
+ * if west==TM_LOCALZONE then the local timezone is used
+ * otherwise west is the number of minutes west
+ * of GMT with DST taken into account
+ *
+ * this routine works with a copy of Tm_t to avoid clashes
+ * with other tm*() that may return static Tm_t*
+ */
+
+Time_t
+tmxtime(register Tm_t* tm, int west)
+{
+ register Time_t t;
+ register Tm_leap_t* lp;
+ register int32_t y;
+ int n;
+ int sec;
+ time_t now;
+ struct tm* tl;
+ Tm_t* to;
+ Tm_t ts;
+
+ ts = *tm;
+ to = tm;
+ tm = &ts;
+ tmset(tm_info.zone);
+ tmfix(tm);
+ y = tm->tm_year;
+ if (y < 69 || y > (TMX_MAXYEAR - 1900))
+ return TMX_NOTIME;
+ y--;
+ t = y * 365 + y / 4 - y / 100 + (y + (1900 - 1600)) / 400 - (1970 - 1901) * 365 - (1970 - 1901) / 4;
+ if ((n = tm->tm_mon) > 11)
+ n = 11;
+ y += 1901;
+ if (n > 1 && tmisleapyear(y))
+ t++;
+ t += tm_data.sum[n] + tm->tm_mday - 1;
+ t *= 24;
+ t += tm->tm_hour;
+ t *= 60;
+ t += tm->tm_min;
+ t *= 60;
+ t += sec = tm->tm_sec;
+ if (west != TM_UTCZONE && !(tm_info.flags & TM_UTC))
+ {
+ /*
+ * time zone adjustments
+ */
+
+ if (west == TM_LOCALZONE)
+ {
+ t += tm_info.zone->west * 60;
+ if (!tm_info.zone->daylight)
+ tm->tm_isdst = 0;
+ else
+ {
+ y = tm->tm_year;
+ tm->tm_year = tmequiv(tm) - 1900;
+ now = tmxsec(tmxtime(tm, tm_info.zone->west));
+ tm->tm_year = y;
+ if (!(tl = tmlocaltime(&now)))
+ return TMX_NOTIME;
+ if (tm->tm_isdst = tl->tm_isdst)
+ t += tm_info.zone->dst * 60;
+ }
+ }
+ else
+ {
+ t += west * 60;
+ if (!tm_info.zone->daylight)
+ tm->tm_isdst = 0;
+ else if (tm->tm_isdst < 0)
+ {
+ y = tm->tm_year;
+ tm->tm_year = tmequiv(tm) - 1900;
+ tm->tm_isdst = 0;
+ now = tmxsec(tmxtime(tm, tm_info.zone->west));
+ tm->tm_year = y;
+ if (!(tl = tmlocaltime(&now)))
+ return TMX_NOTIME;
+ tm->tm_isdst = tl->tm_isdst;
+ }
+ }
+ }
+ else if (tm->tm_isdst)
+ tm->tm_isdst = 0;
+ *to = *tm;
+ if (tm_info.flags & TM_LEAP)
+ {
+ /*
+ * leap second adjustments
+ */
+
+ for (lp = &tm_data.leap[0]; t < lp->time - (lp+1)->total; lp++);
+ t += lp->total;
+ n = lp->total - (lp+1)->total;
+ if (t <= (lp->time + n) && (n > 0 && sec > 59 || n < 0 && sec > (59 + n) && sec <= 59))
+ t -= n;
+ }
+ return tmxsns(t, tm->tm_nsec);
+}
diff --git a/src/lib/libast/tm/tmxtouch.c b/src/lib/libast/tm/tmxtouch.c
new file mode 100644
index 0000000..e711a62
--- /dev/null
+++ b/src/lib/libast/tm/tmxtouch.c
@@ -0,0 +1,81 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * Time_t conversion support
+ */
+
+#include <tmx.h>
+#include <tv.h>
+
+/*
+ * touch path <atime,mtime,ctime>
+ * (flags&PATH_TOUCH_VERBATIM) treats times verbatim, otherwise:
+ * Time_t==0 current time
+ * Time_t==TMX_NOTIME retains path value
+ */
+
+int
+tmxtouch(const char* path, Time_t at, Time_t mt, Time_t ct, int flags)
+{
+ Tv_t av;
+ Tv_t mv;
+ Tv_t cv;
+ Tv_t* ap;
+ Tv_t* mp;
+ Tv_t* cp;
+
+ if (at == TMX_NOTIME && !(flags & PATH_TOUCH_VERBATIM))
+ ap = TV_TOUCH_RETAIN;
+ else if (!at && !(flags & PATH_TOUCH_VERBATIM))
+ ap = 0;
+ else
+ {
+ av.tv_sec = tmxsec(at);
+ av.tv_nsec = tmxnsec(at);
+ ap = &av;
+ }
+ if (mt == TMX_NOTIME && !(flags & PATH_TOUCH_VERBATIM))
+ mp = TV_TOUCH_RETAIN;
+ else if (!mt && !(flags & PATH_TOUCH_VERBATIM))
+ mp = 0;
+ else
+ {
+ mv.tv_sec = tmxsec(mt);
+ mv.tv_nsec = tmxnsec(mt);
+ mp = &mv;
+ }
+ if (ct == TMX_NOTIME && !(flags & PATH_TOUCH_VERBATIM))
+ cp = TV_TOUCH_RETAIN;
+ else if (!ct && !(flags & PATH_TOUCH_VERBATIM))
+ cp = 0;
+ else
+ {
+ cv.tv_sec = tmxsec(ct);
+ cv.tv_nsec = tmxnsec(ct);
+ cp = &cv;
+ }
+ return tvtouch(path, ap, mp, cp, flags & 1);
+}
diff --git a/src/lib/libast/tm/tmzone.c b/src/lib/libast/tm/tmzone.c
new file mode 100644
index 0000000..230a5f3
--- /dev/null
+++ b/src/lib/libast/tm/tmzone.c
@@ -0,0 +1,95 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * time conversion support
+ */
+
+#include <ast.h>
+#include <tm.h>
+
+/*
+ * return timezone pointer given name and type
+ *
+ * if type==0 then all time zone types match
+ * otherwise type must be one of tm_info.zone[].type
+ *
+ * if end is non-null then it will point to the next
+ * unmatched char in name
+ *
+ * if dst!=0 then it will point to 0 for standard zones
+ * and the offset for daylight zones
+ *
+ * 0 returned for no match
+ */
+
+Tm_zone_t*
+tmzone(register const char* name, char** end, const char* type, int* dst)
+{
+ register Tm_zone_t* zp;
+ register char* prev;
+ char* e;
+
+ static Tm_zone_t fixed;
+ static char off[16];
+
+ tmset(tm_info.zone);
+ if ((*name == '+' || *name == '-') && (fixed.west = tmgoff(name, &e, TM_LOCALZONE)) != TM_LOCALZONE && !*e)
+ {
+ strlcpy(fixed.standard = fixed.daylight = off, name, sizeof(off));
+ if (end)
+ *end = e;
+ if (dst)
+ *dst = 0;
+ return &fixed;
+ }
+ zp = tm_info.local;
+ prev = 0;
+ do
+ {
+ if (zp->type)
+ prev = zp->type;
+ if (!type || type == prev || !prev)
+ {
+ if (tmword(name, end, zp->standard, NiL, 0))
+ {
+ if (dst)
+ *dst = 0;
+ return zp;
+ }
+ if (zp->dst && zp->daylight && tmword(name, end, zp->daylight, NiL, 0))
+ {
+ if (dst)
+ *dst = zp->dst;
+ return zp;
+ }
+ }
+ if (zp == tm_info.local)
+ zp = tm_data.zone;
+ else
+ zp++;
+ } while (zp->standard);
+ return 0;
+}
diff --git a/src/lib/libast/tm/tvcmp.c b/src/lib/libast/tm/tvcmp.c
new file mode 100644
index 0000000..2716d3d
--- /dev/null
+++ b/src/lib/libast/tm/tvcmp.c
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <tv.h>
+
+/*
+ * compare a with b
+ * strcmp semantics
+ */
+
+int
+tvcmp(register const Tv_t* a, register const Tv_t* b)
+{
+ if (a->tv_sec < b->tv_sec)
+ return -1;
+ if (a->tv_sec > b->tv_sec)
+ return 1;
+ if (a->tv_nsec != TV_NSEC_IGNORE && b->tv_nsec != TV_NSEC_IGNORE)
+ {
+ if (a->tv_nsec < b->tv_nsec)
+ return -1;
+ if (a->tv_nsec > b->tv_nsec)
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/lib/libast/tm/tvgettime.c b/src/lib/libast/tm/tvgettime.c
new file mode 100644
index 0000000..12866e3
--- /dev/null
+++ b/src/lib/libast/tm/tvgettime.c
@@ -0,0 +1,70 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <tv.h>
+#include <tm.h>
+
+#include "FEATURE/tvlib"
+
+int
+tvgettime(Tv_t* tv)
+{
+
+#if _lib_clock_gettime && defined(CLOCK_REALTIME)
+
+ struct timespec s;
+
+ clock_gettime(CLOCK_REALTIME, &s);
+ tv->tv_sec = s.tv_sec;
+ tv->tv_nsec = s.tv_nsec;
+
+#else
+
+#if defined(tmgettimeofday)
+
+ struct timeval v;
+
+ tmgettimeofday(&v);
+ tv->tv_sec = v.tv_sec;
+ tv->tv_nsec = v.tv_usec * 1000;
+
+#else
+
+ static time_t s;
+ static uint32_t n;
+
+ if ((tv->tv_sec = time(NiL)) != s)
+ {
+ s = tv->tv_sec;
+ n = 0;
+ }
+ else
+ n += 1000;
+ tv->tv_nsec = n;
+
+#endif
+
+#endif
+
+ return 0;
+}
diff --git a/src/lib/libast/tm/tvsettime.c b/src/lib/libast/tm/tvsettime.c
new file mode 100644
index 0000000..4e3842b
--- /dev/null
+++ b/src/lib/libast/tm/tvsettime.c
@@ -0,0 +1,72 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <tv.h>
+#include <tm.h>
+#include <errno.h>
+
+#include "FEATURE/tvlib"
+
+int
+tvsettime(const Tv_t* tv)
+{
+
+#if _lib_clock_settime && defined(CLOCK_REALTIME)
+
+ struct timespec s;
+
+ s.tv_sec = tv->tv_sec;
+ s.tv_nsec = tv->tv_nsec;
+ return clock_settime(CLOCK_REALTIME, &s);
+
+#else
+
+#if defined(tmsettimeofday)
+
+ struct timeval v;
+
+ v.tv_sec = tv->tv_sec;
+ v.tv_usec = tv->tv_nsec / 1000;
+ return tmsettimeofday(&v);
+
+#else
+
+#if _lib_stime
+
+ static time_t s;
+
+ s = tv->tv_sec + (tv->tv_nsec != 0);
+ return stime(s);
+
+#else
+
+ errno = EPERM;
+ return -1;
+
+#endif
+
+#endif
+
+#endif
+
+}
diff --git a/src/lib/libast/tm/tvsleep.c b/src/lib/libast/tm/tvsleep.c
new file mode 100644
index 0000000..78da802
--- /dev/null
+++ b/src/lib/libast/tm/tvsleep.c
@@ -0,0 +1,144 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <tv.h>
+#include <tm.h>
+
+#include "FEATURE/tvlib"
+
+#if !_lib_nanosleep
+# if _lib_select
+# if _sys_select
+# include <sys/select.h>
+# else
+# include <sys/socket.h>
+# endif
+# else
+# if !_lib_usleep
+# if _lib_poll_notimer
+# undef _lib_poll
+# endif
+# if _lib_poll
+# include <poll.h>
+# endif
+# endif
+# endif
+#endif
+
+/*
+ * sleep for tv
+ * non-zero exit if sleep did not complete
+ * with remaining time in rv
+ */
+
+int
+tvsleep(register const Tv_t* tv, register Tv_t* rv)
+{
+
+#if _lib_nanosleep
+
+ struct timespec stv;
+ struct timespec srv;
+ int r;
+
+ stv.tv_sec = tv->tv_sec;
+ stv.tv_nsec = tv->tv_nsec;
+ if ((r = nanosleep(&stv, &srv)) && rv)
+ {
+ rv->tv_sec = srv.tv_sec;
+ rv->tv_nsec = srv.tv_nsec;
+ }
+ return r;
+
+#else
+
+#if _lib_select
+
+ struct timeval stv;
+
+ stv.tv_sec = tv->tv_sec;
+ stv.tv_usec = tv->tv_nsec / 1000;
+ if (select(0, NiL, NiL, NiL, &stv) < 0)
+ {
+ if (rv)
+ *rv = *tv;
+ return -1;
+ }
+ if (rv)
+ {
+ rv->tv_sec = stv.tv_sec;
+ rv->tv_nsec = stv.tv_usec * 1000;
+ }
+ return 0;
+
+#else
+
+ unsigned int s = tv->tv_sec;
+ uint32_t n = tv->tv_nsec;
+
+#if _lib_usleep
+
+
+ unsigned long t;
+
+ if (t = (n + 999L) / 1000L)
+ {
+ usleep(t);
+ s -= t / 1000000L;
+ n = 0;
+ }
+
+#else
+
+#if _lib_poll
+
+ struct pollfd pfd;
+ int t;
+
+ if ((t = (n + 999999L) / 1000000L) > 0)
+ {
+ poll(&pfd, 0, t);
+ s -= t / 1000L;
+ n = 0;
+ }
+
+#endif
+
+#endif
+
+ if ((s += (n + 999999999L) / 1000000000L) && (s = sleep(s)))
+ {
+ if (rv)
+ {
+ rv->tv_sec = s;
+ rv->tv_nsec = 0;
+ }
+ return -1;
+ }
+ return 0;
+
+#endif
+
+#endif
+
+}
diff --git a/src/lib/libast/tm/tvtouch.c b/src/lib/libast/tm/tvtouch.c
new file mode 100644
index 0000000..bd5fb5c
--- /dev/null
+++ b/src/lib/libast/tm/tvtouch.c
@@ -0,0 +1,295 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * Tv_t conversion support
+ */
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide utime
+#else
+#define utime ______utime
+#endif
+
+#ifndef _ATFILE_SOURCE
+#define _ATFILE_SOURCE 1
+#endif
+
+#include <ast.h>
+#include <ls.h>
+#include <tv.h>
+#include <times.h>
+#include <error.h>
+
+#include "FEATURE/tvlib"
+
+#if _hdr_utime && _lib_utime
+#include <utime.h>
+#endif
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide utime
+#else
+#undef utime
+#endif
+
+#if _lib_utime
+#if _hdr_utime
+extern int utime(const char*, const struct utimbuf*);
+#else
+extern int utime(const char*, const time_t*);
+#endif
+#endif
+
+#define NS(n) (((uint32_t)(n))<1000000000L?(n):0)
+
+/*
+ * touch path <atime,mtime,ctime>
+ * Tv_t==0 uses current time
+ * Tv_t==TV_TOUCH_RETAIN retains path value if it exists, current time otherwise
+ * otherwise it is exact time
+ * file created if it doesn't exist and (flags&TV_TOUCH_CREATE)
+ * symlink not followed if (flags&TV_TOUCH_PHYSICAL)
+ * cv most likely ignored on most implementations
+ *
+ * NOTE: when *at() calls are integrated TV_TOUCH_* should be advertized!
+ */
+
+#define TV_TOUCH_CREATE 1
+#define TV_TOUCH_PHYSICAL 2
+
+#if !defined(UTIME_NOW) || !defined(UTIME_OMIT) || defined(__stub_utimensat)
+#undef _lib_utimensat
+#endif
+
+int
+tvtouch(const char* path, register const Tv_t* av, register const Tv_t* mv, const Tv_t* cv, int flags)
+{
+ int fd;
+ int mode;
+ int oerrno;
+ struct stat st;
+ Tv_t now;
+#if _lib_utimets || _lib_utimensat
+ struct timespec ts[2];
+#endif
+#if _lib_utimes
+ struct timeval am[2];
+#else
+#if _hdr_utime
+ struct utimbuf am;
+#else
+ time_t am[2];
+#endif
+#endif
+
+ oerrno = errno;
+#if _lib_utimensat
+ if (!av)
+ {
+ ts[0].tv_sec = 0;
+ ts[0].tv_nsec = UTIME_NOW;
+ }
+ else if (av == TV_TOUCH_RETAIN)
+ {
+ ts[0].tv_sec = 0;
+ ts[0].tv_nsec = UTIME_OMIT;
+ }
+ else
+ {
+ ts[0].tv_sec = av->tv_sec;
+ ts[0].tv_nsec = NS(av->tv_nsec);
+ }
+ if (!mv)
+ {
+ ts[1].tv_sec = 0;
+ ts[1].tv_nsec = UTIME_NOW;
+ }
+ else if (mv == TV_TOUCH_RETAIN)
+ {
+ ts[1].tv_sec = 0;
+ ts[1].tv_nsec = UTIME_OMIT;
+ }
+ else
+ {
+ ts[1].tv_sec = mv->tv_sec;
+ ts[1].tv_nsec = NS(mv->tv_nsec);
+ }
+ if (!cv && av == TV_TOUCH_RETAIN && mv == TV_TOUCH_RETAIN && !stat(path, &st) && !chmod(path, st.st_mode & S_IPERM))
+ return 0;
+ if (!utimensat(AT_FDCWD, path, ts[0].tv_nsec == UTIME_NOW && ts[1].tv_nsec == UTIME_NOW ? (struct timespec*)0 : ts, (flags & TV_TOUCH_PHYSICAL) ? AT_SYMLINK_NOFOLLOW : 0))
+ return 0;
+ if (errno != ENOSYS)
+ {
+ if (errno != ENOENT || !(flags & TV_TOUCH_CREATE))
+ return -1;
+ umask(mode = umask(0));
+ mode = (~mode) & (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+ if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0)
+ return -1;
+ close(fd);
+ errno = oerrno;
+ if ((ts[0].tv_nsec != UTIME_NOW || ts[1].tv_nsec != UTIME_NOW) && utimensat(AT_FDCWD, path, ts, (flags & TV_TOUCH_PHYSICAL) ? AT_SYMLINK_NOFOLLOW : 0))
+ return -1;
+ return 0;
+ }
+#endif
+ if ((av == TV_TOUCH_RETAIN || mv == TV_TOUCH_RETAIN) && stat(path, &st))
+ {
+ errno = oerrno;
+ if (av == TV_TOUCH_RETAIN)
+ av = 0;
+ if (mv == TV_TOUCH_RETAIN)
+ mv = 0;
+ }
+ if (!av || !mv)
+ {
+ tvgettime(&now);
+ if (!av)
+ av = (const Tv_t*)&now;
+ if (!mv)
+ mv = (const Tv_t*)&now;
+ }
+#if _lib_utimets
+ if (av == TV_TOUCH_RETAIN)
+ {
+ ts[0].tv_sec = st.st_atime;
+ ts[0].tv_nsec = ST_ATIME_NSEC_GET(&st);
+ }
+ else
+ {
+ ts[0].tv_sec = av->tv_sec;
+ ts[0].tv_nsec = NS(av->tv_nsec);
+ }
+ if (mv == TV_TOUCH_RETAIN)
+ {
+ ts[1].tv_sec = st.st_mtime;
+ ts[1].tv_nsec = ST_MTIME_NSEC_GET(&st);
+ }
+ else
+ {
+ ts[1].tv_sec = mv->tv_sec;
+ ts[1].tv_nsec = NS(mv->tv_nsec);
+ }
+ if (!utimets(path, ts))
+ return 0;
+ if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utimets(path, NiL))
+ {
+ errno = oerrno;
+ return 0;
+ }
+#else
+#if _lib_utimes
+ if (av == TV_TOUCH_RETAIN)
+ {
+ am[0].tv_sec = st.st_atime;
+ am[0].tv_usec = ST_ATIME_NSEC_GET(&st) / 1000;
+ }
+ else
+ {
+ am[0].tv_sec = av->tv_sec;
+ am[0].tv_usec = NS(av->tv_nsec) / 1000;
+ }
+ if (mv == TV_TOUCH_RETAIN)
+ {
+ am[1].tv_sec = st.st_mtime;
+ am[1].tv_usec = ST_MTIME_NSEC_GET(&st) / 1000;
+ }
+ else
+ {
+ am[1].tv_sec = mv->tv_sec;
+ am[1].tv_usec = NS(mv->tv_nsec) / 1000;
+ }
+ if (!utimes(path, am))
+ return 0;
+ if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utimes(path, NiL))
+ {
+ errno = oerrno;
+ return 0;
+ }
+#else
+#if _lib_utime
+ am.actime = (av == TV_TOUCH_RETAIN) ? st.st_atime : av->tv_sec;
+ am.modtime = (mv == TV_TOUCH_RETAIN) ? st.st_mtime : mv->tv_sec;
+ if (!utime(path, &am))
+ return 0;
+#if _lib_utime_now
+ if (errno != ENOENT && av == (const Tv_t*)&now && mv == (const Tv_t*)&now && !utime(path, NiL))
+ {
+ errno = oerrno;
+ return 0;
+ }
+#endif
+#endif
+#endif
+ if (!access(path, F_OK))
+ {
+ if (av != (const Tv_t*)&now || mv != (const Tv_t*)&now)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if ((fd = open(path, O_RDWR)) >= 0)
+ {
+ char c;
+
+ if (read(fd, &c, 1) == 1)
+ {
+ if (c = (lseek(fd, 0L, 0) == 0L && write(fd, &c, 1) == 1))
+ errno = oerrno;
+ close(fd);
+ if (c)
+ return 0;
+ }
+ close(fd);
+ }
+ }
+#endif
+ if (errno != ENOENT || !(flags & TV_TOUCH_CREATE))
+ return -1;
+ umask(mode = umask(0));
+ mode = (~mode) & (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+ if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0)
+ return -1;
+ close(fd);
+ errno = oerrno;
+ if (av == (const Tv_t*)&now && mv == (const Tv_t*)&now)
+ return 0;
+#if _lib_utimets
+ return utimets(path, am);
+#else
+#if _lib_utimes
+ return utimes(path, am);
+#else
+#if _lib_utime
+ return utime(path, &am);
+#else
+ errno = EINVAL;
+ return -1;
+#endif
+#endif
+#endif
+
+}
diff --git a/src/lib/libast/uwin/a64l.c b/src/lib/libast/uwin/a64l.c
new file mode 100644
index 0000000..20416c6
--- /dev/null
+++ b/src/lib/libast/uwin/a64l.c
@@ -0,0 +1,76 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_a64l
+
+void _STUB_a64l(){}
+
+#else
+
+#define a64l ______a64l
+#define l64a ______l64a
+
+#include <stdlib.h>
+#include <string.h>
+
+#undef a64l
+#undef l64a
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+static char letter[65] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+extern long a64l(const char *str)
+{
+ register unsigned long ul = 0;
+ register int n = 6;
+ register int c;
+ register char *cp;
+ for(n=0; n <6; n++)
+ {
+ if((c= *str++)==0)
+ break;
+ if(!(cp=strchr(letter,c)))
+ break;
+ ul |= (cp-letter)<< (6*n);
+ }
+ return((long)ul);
+}
+
+extern char *l64a(long l)
+{
+ static char buff[7];
+ unsigned ul = ((unsigned long)l & 0xffffffff);
+ register char *cp = buff;
+ while(ul>0)
+ {
+ *cp++ = letter[ul&077];
+ ul >>= 6;
+ }
+ *cp = 0;
+ return(buff);
+}
+
+#endif
diff --git a/src/lib/libast/uwin/acosh.c b/src/lib/libast/uwin/acosh.c
new file mode 100644
index 0000000..9248e91
--- /dev/null
+++ b/src/lib/libast/uwin/acosh.c
@@ -0,0 +1,108 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_acosh
+
+void _STUB_acosh(){}
+
+#else
+
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)acosh.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/* ACOSH(X)
+ * RETURN THE INVERSE HYPERBOLIC COSINE OF X
+ * DOUBLE PRECISION (VAX D FORMAT 56 BITS, IEEE DOUBLE 53 BITS)
+ * CODED IN C BY K.C. NG, 2/16/85;
+ * REVISED BY K.C. NG on 3/6/85, 3/24/85, 4/16/85, 8/17/85.
+ *
+ * Required system supported functions :
+ * sqrt(x)
+ *
+ * Required kernel function:
+ * log1p(x) ...return log(1+x)
+ *
+ * Method :
+ * Based on
+ * acosh(x) = log [ x + sqrt(x*x-1) ]
+ * we have
+ * acosh(x) := log1p(x)+ln2, if (x > 1.0E20); else
+ * acosh(x) := log1p( sqrt(x-1) * (sqrt(x-1) + sqrt(x+1)) ) .
+ * These formulae avoid the over/underflow complication.
+ *
+ * Special cases:
+ * acosh(x) is NaN with signal if x<1.
+ * acosh(NaN) is NaN without signal.
+ *
+ * Accuracy:
+ * acosh(x) returns the exact inverse hyperbolic cosine of x nearly
+ * rounded. In a test run with 512,000 random arguments on a VAX, the
+ * maximum observed error was 3.30 ulps (units of the last place) at
+ * x=1.0070493753568216 .
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following constants.
+ * The decimal values may be used, provided that the compiler will convert
+ * from decimal to binary accurately enough to produce the hexadecimal values
+ * shown.
+ */
+
+#include "mathimpl.h"
+
+vc(ln2hi, 6.9314718055829871446E-1 ,7217,4031,0000,f7d0, 0, .B17217F7D00000)
+vc(ln2lo, 1.6465949582897081279E-12 ,bcd5,2ce7,d9cc,e4f1, -39, .E7BCD5E4F1D9CC)
+
+ic(ln2hi, 6.9314718036912381649E-1, -1, 1.62E42FEE00000)
+ic(ln2lo, 1.9082149292705877000E-10,-33, 1.A39EF35793C76)
+
+#ifdef vccast
+#define ln2hi vccast(ln2hi)
+#define ln2lo vccast(ln2lo)
+#endif
+
+extern double acosh(x)
+double x;
+{
+ double t,big=1.E20; /* big+1==big */
+
+#if !defined(vax)&&!defined(tahoe)
+ if(x!=x) return(x); /* x is NaN */
+#endif /* !defined(vax)&&!defined(tahoe) */
+
+ /* return log1p(x) + log(2) if x is large */
+ if(x>big) {t=log1p(x)+ln2lo; return(t+ln2hi);}
+
+ t=sqrt(x-1.0);
+ return(log1p(t*(t+sqrt(x+1.0))));
+}
+
+#endif
diff --git a/src/lib/libast/uwin/asinh.c b/src/lib/libast/uwin/asinh.c
new file mode 100644
index 0000000..6c8f54c
--- /dev/null
+++ b/src/lib/libast/uwin/asinh.c
@@ -0,0 +1,107 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_asinh
+
+void _STUB_asinh(){}
+
+#else
+
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)asinh.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/* ASINH(X)
+ * RETURN THE INVERSE HYPERBOLIC SINE OF X
+ * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
+ * CODED IN C BY K.C. NG, 2/16/85;
+ * REVISED BY K.C. NG on 3/7/85, 3/24/85, 4/16/85.
+ *
+ * Required system supported functions :
+ * copysign(x,y)
+ * sqrt(x)
+ *
+ * Required kernel function:
+ * log1p(x) ...return log(1+x)
+ *
+ * Method :
+ * Based on
+ * asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
+ * we have
+ * asinh(x) := x if 1+x*x=1,
+ * := sign(x)*(log1p(x)+ln2)) if sqrt(1+x*x)=x, else
+ * := sign(x)*log1p(|x| + |x|/(1/|x| + sqrt(1+(1/|x|)^2)) )
+ *
+ * Accuracy:
+ * asinh(x) returns the exact inverse hyperbolic sine of x nearly rounded.
+ * In a test run with 52,000 random arguments on a VAX, the maximum
+ * observed error was 1.58 ulps (units in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following constants.
+ * The decimal values may be used, provided that the compiler will convert
+ * from decimal to binary accurately enough to produce the hexadecimal values
+ * shown.
+ */
+#include "mathimpl.h"
+
+vc(ln2hi, 6.9314718055829871446E-1 ,7217,4031,0000,f7d0, 0, .B17217F7D00000)
+vc(ln2lo, 1.6465949582897081279E-12 ,bcd5,2ce7,d9cc,e4f1, -39, .E7BCD5E4F1D9CC)
+
+ic(ln2hi, 6.9314718036912381649E-1, -1, 1.62E42FEE00000)
+ic(ln2lo, 1.9082149292705877000E-10, -33, 1.A39EF35793C76)
+
+#ifdef vccast
+#define ln2hi vccast(ln2hi)
+#define ln2lo vccast(ln2lo)
+#endif
+
+extern double asinh(x)
+double x;
+{
+ double t,s;
+ const static double small=1.0E-10, /* fl(1+small*small) == 1 */
+ big =1.0E20, /* fl(1+big) == big */
+ one =1.0 ;
+
+#if !defined(vax)&&!defined(tahoe)
+ if(x!=x) return(x); /* x is NaN */
+#endif /* !defined(vax)&&!defined(tahoe) */
+ if((t=copysign(x,one))>small)
+ if(t<big) {
+ s=one/t; return(copysign(log1p(t+t/(s+sqrt(one+s*s))),x)); }
+ else /* if |x| > big */
+ {s=log1p(t)+ln2lo; return(copysign(s+ln2hi,x));}
+ else /* if |x| < small */
+ return(x);
+}
+
+#endif
diff --git a/src/lib/libast/uwin/atanh.c b/src/lib/libast/uwin/atanh.c
new file mode 100644
index 0000000..b5e9a78
--- /dev/null
+++ b/src/lib/libast/uwin/atanh.c
@@ -0,0 +1,89 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_atanh
+
+void _STUB_atanh(){}
+
+#else
+
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)atanh.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/* ATANH(X)
+ * RETURN THE HYPERBOLIC ARC TANGENT OF X
+ * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
+ * CODED IN C BY K.C. NG, 1/8/85;
+ * REVISED BY K.C. NG on 2/7/85, 3/7/85, 8/18/85.
+ *
+ * Required kernel function:
+ * log1p(x) ...return log(1+x)
+ *
+ * Method :
+ * Return
+ * 1 2x x
+ * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
+ * 2 1 - x 1 - x
+ *
+ * Special cases:
+ * atanh(x) is NaN if |x| > 1 with signal;
+ * atanh(NaN) is that NaN with no signal;
+ * atanh(+-1) is +-INF with signal.
+ *
+ * Accuracy:
+ * atanh(x) returns the exact hyperbolic arc tangent of x nearly rounded.
+ * In a test run with 512,000 random arguments on a VAX, the maximum
+ * observed error was 1.87 ulps (units in the last place) at
+ * x= -3.8962076028810414000e-03.
+ */
+#include "mathimpl.h"
+
+#if defined(vax)||defined(tahoe)
+#include <errno.h>
+#endif /* defined(vax)||defined(tahoe) */
+
+extern double atanh(x)
+double x;
+{
+ double z;
+ z = copysign(0.5,x);
+ x = copysign(x,1.0);
+#if defined(vax)||defined(tahoe)
+ if (x == 1.0) {
+ return(copysign(1.0,z)*infnan(ERANGE)); /* sign(x)*INF */
+ }
+#endif /* defined(vax)||defined(tahoe) */
+ x = x/(1.0-x);
+ return( z*log1p(x+x) );
+}
+
+#endif
diff --git a/src/lib/libast/uwin/cbrt.c b/src/lib/libast/uwin/cbrt.c
new file mode 100644
index 0000000..f28d337
--- /dev/null
+++ b/src/lib/libast/uwin/cbrt.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_cbrt
+
+void _STUB_cbrt(){}
+
+#else
+
+#include "mathimpl.h"
+
+extern double cbrt(double x)
+{
+ return(exp(log(x)/3.0));
+}
+
+
+#endif
diff --git a/src/lib/libast/uwin/crypt.c b/src/lib/libast/uwin/crypt.c
new file mode 100644
index 0000000..5d9569e
--- /dev/null
+++ b/src/lib/libast/uwin/crypt.c
@@ -0,0 +1,959 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_crypt
+
+void _STUB_crypt(){}
+
+#else
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tom Truscott.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)crypt.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#define crypt ______crypt
+#define encrypt ______encrypt
+#define setkey ______setkey
+
+/* #include <unistd.h> */
+#include <stdio.h>
+#include <limits.h>
+#include <pwd.h>
+
+#undef crypt
+#undef encrypt
+#undef setkey
+
+#ifndef _PASSWORD_EFMT1
+#define _PASSWORD_EFMT1 '-'
+#endif
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+/*
+ * UNIX password, and DES, encryption.
+ * By Tom Truscott, trt@rti.rti.org,
+ * from algorithms by Robert W. Baldwin and James Gillogly.
+ *
+ * References:
+ * "Mathematical Cryptology for Computer Scientists and Mathematicians,"
+ * by Wayne Patterson, 1987, ISBN 0-8476-7438-X.
+ *
+ * "Password Security: A Case History," R. Morris and Ken Thompson,
+ * Communications of the ACM, vol. 22, pp. 594-597, Nov. 1979.
+ *
+ * "DES will be Totally Insecure within Ten Years," M.E. Hellman,
+ * IEEE Spectrum, vol. 16, pp. 32-39, July 1979.
+ */
+
+/* ===== Configuration ==================== */
+
+/*
+ * define "MUST_ALIGN" if your compiler cannot load/store
+ * long integers at arbitrary (e.g. odd) memory locations.
+ * (Either that or never pass unaligned addresses to des_cipher!)
+ */
+#if !defined(vax)
+#define MUST_ALIGN
+#endif
+
+#ifdef CHAR_BITS
+#if CHAR_BITS != 8
+ #error C_block structure assumes 8 bit characters
+#endif
+#endif
+
+/*
+ * define "LONG_IS_32_BITS" only if sizeof(long)==4.
+ * This avoids use of bit fields (your compiler may be sloppy with them).
+ */
+#if !defined(cray)
+#define LONG_IS_32_BITS
+#endif
+
+/*
+ * define "B64" to be the declaration for a 64 bit integer.
+ * XXX this feature is currently unused, see "endian" comment below.
+ */
+#if defined(cray)
+#define B64 long
+#endif
+#if defined(convex)
+#define B64 long long
+#endif
+
+/*
+ * define "LARGEDATA" to get faster permutations, by using about 72 kilobytes
+ * of lookup tables. This speeds up des_setkey() and des_cipher(), but has
+ * little effect on crypt().
+ */
+#if defined(notdef)
+#define LARGEDATA
+#endif
+
+/* ==================================== */
+
+/*
+ * Cipher-block representation (Bob Baldwin):
+ *
+ * DES operates on groups of 64 bits, numbered 1..64 (sigh). One
+ * representation is to store one bit per byte in an array of bytes. Bit N of
+ * the NBS spec is stored as the LSB of the Nth byte (index N-1) in the array.
+ * Another representation stores the 64 bits in 8 bytes, with bits 1..8 in the
+ * first byte, 9..16 in the second, and so on. The DES spec apparently has
+ * bit 1 in the MSB of the first byte, but that is particularly noxious so we
+ * bit-reverse each byte so that bit 1 is the LSB of the first byte, bit 8 is
+ * the MSB of the first byte. Specifically, the 64-bit input data and key are
+ * converted to LSB format, and the output 64-bit block is converted back into
+ * MSB format.
+ *
+ * DES operates internally on groups of 32 bits which are expanded to 48 bits
+ * by permutation E and shrunk back to 32 bits by the S boxes. To speed up
+ * the computation, the expansion is applied only once, the expanded
+ * representation is maintained during the encryption, and a compression
+ * permutation is applied only at the end. To speed up the S-box lookups,
+ * the 48 bits are maintained as eight 6 bit groups, one per byte, which
+ * directly feed the eight S-boxes. Within each byte, the 6 bits are the
+ * most significant ones. The low two bits of each byte are zero. (Thus,
+ * bit 1 of the 48 bit E expansion is stored as the "4"-valued bit of the
+ * first byte in the eight byte representation, bit 2 of the 48 bit value is
+ * the "8"-valued bit, and so on.) In fact, a combined "SPE"-box lookup is
+ * used, in which the output is the 64 bit result of an S-box lookup which
+ * has been permuted by P and expanded by E, and is ready for use in the next
+ * iteration. Two 32-bit wide tables, SPE[0] and SPE[1], are used for this
+ * lookup. Since each byte in the 48 bit path is a multiple of four, indexed
+ * lookup of SPE[0] and SPE[1] is simple and fast. The key schedule and
+ * "salt" are also converted to this 8*(6+2) format. The SPE table size is
+ * 8*64*8 = 4K bytes.
+ *
+ * To speed up bit-parallel operations (such as XOR), the 8 byte
+ * representation is "union"ed with 32 bit values "i0" and "i1", and, on
+ * machines which support it, a 64 bit value "b64". This data structure,
+ * "C_block", has two problems. First, alignment restrictions must be
+ * honored. Second, the byte-order (e.g. little-endian or big-endian) of
+ * the architecture becomes visible.
+ *
+ * The byte-order problem is unfortunate, since on the one hand it is good
+ * to have a machine-independent C_block representation (bits 1..8 in the
+ * first byte, etc.), and on the other hand it is good for the LSB of the
+ * first byte to be the LSB of i0. We cannot have both these things, so we
+ * currently use the "little-endian" representation and avoid any multi-byte
+ * operations that depend on byte order. This largely precludes use of the
+ * 64-bit datatype since the relative order of i0 and i1 are unknown. It
+ * also inhibits grouping the SPE table to look up 12 bits at a time. (The
+ * 12 bits can be stored in a 16-bit field with 3 low-order zeroes and 1
+ * high-order zero, providing fast indexing into a 64-bit wide SPE.) On the
+ * other hand, 64-bit datatypes are currently rare, and a 12-bit SPE lookup
+ * requires a 128 kilobyte table, so perhaps this is not a big loss.
+ *
+ * Permutation representation (Jim Gillogly):
+ *
+ * A transformation is defined by its effect on each of the 8 bytes of the
+ * 64-bit input. For each byte we give a 64-bit output that has the bits in
+ * the input distributed appropriately. The transformation is then the OR
+ * of the 8 sets of 64-bits. This uses 8*256*8 = 16K bytes of storage for
+ * each transformation. Unless LARGEDATA is defined, however, a more compact
+ * table is used which looks up 16 4-bit "chunks" rather than 8 8-bit chunks.
+ * The smaller table uses 16*16*8 = 2K bytes for each transformation. This
+ * is slower but tolerable, particularly for password encryption in which
+ * the SPE transformation is iterated many times. The small tables total 9K
+ * bytes, the large tables total 72K bytes.
+ *
+ * The transformations used are:
+ * IE3264: MSB->LSB conversion, initial permutation, and expansion.
+ * This is done by collecting the 32 even-numbered bits and applying
+ * a 32->64 bit transformation, and then collecting the 32 odd-numbered
+ * bits and applying the same transformation. Since there are only
+ * 32 input bits, the IE3264 transformation table is half the size of
+ * the usual table.
+ * CF6464: Compression, final permutation, and LSB->MSB conversion.
+ * This is done by two trivial 48->32 bit compressions to obtain
+ * a 64-bit block (the bit numbering is given in the "CIFP" table)
+ * followed by a 64->64 bit "cleanup" transformation. (It would
+ * be possible to group the bits in the 64-bit block so that 2
+ * identical 32->32 bit transformations could be used instead,
+ * saving a factor of 4 in space and possibly 2 in time, but
+ * byte-ordering and other complications rear their ugly head.
+ * Similar opportunities/problems arise in the key schedule
+ * transforms.)
+ * PC1ROT: MSB->LSB, PC1 permutation, rotate, and PC2 permutation.
+ * This admittedly baroque 64->64 bit transformation is used to
+ * produce the first code (in 8*(6+2) format) of the key schedule.
+ * PC2ROT[0]: Inverse PC2 permutation, rotate, and PC2 permutation.
+ * It would be possible to define 15 more transformations, each
+ * with a different rotation, to generate the entire key schedule.
+ * To save space, however, we instead permute each code into the
+ * next by using a transformation that "undoes" the PC2 permutation,
+ * rotates the code, and then applies PC2. Unfortunately, PC2
+ * transforms 56 bits into 48 bits, dropping 8 bits, so PC2 is not
+ * invertible. We get around that problem by using a modified PC2
+ * which retains the 8 otherwise-lost bits in the unused low-order
+ * bits of each byte. The low-order bits are cleared when the
+ * codes are stored into the key schedule.
+ * PC2ROT[1]: Same as PC2ROT[0], but with two rotations.
+ * This is faster than applying PC2ROT[0] twice,
+ *
+ * The Bell Labs "salt" (Bob Baldwin):
+ *
+ * The salting is a simple permutation applied to the 48-bit result of E.
+ * Specifically, if bit i (1 <= i <= 24) of the salt is set then bits i and
+ * i+24 of the result are swapped. The salt is thus a 24 bit number, with
+ * 16777216 possible values. (The original salt was 12 bits and could not
+ * swap bits 13..24 with 36..48.)
+ *
+ * It is possible, but ugly, to warp the SPE table to account for the salt
+ * permutation. Fortunately, the conditional bit swapping requires only
+ * about four machine instructions and can be done on-the-fly with about an
+ * 8% performance penalty.
+ */
+
+typedef union {
+ unsigned char b[8];
+ struct {
+#if defined(LONG_IS_32_BITS)
+ /* long is often faster than a 32-bit bit field */
+ long i0;
+ long i1;
+#else
+ long i0: 32;
+ long i1: 32;
+#endif
+ } b32;
+#if defined(B64)
+ B64 b64;
+#endif
+} C_block;
+
+/*
+ * Convert twenty-four-bit long in host-order
+ * to six bits (and 2 low-order zeroes) per char little-endian format.
+ */
+#define TO_SIX_BIT(rslt, src) { \
+ C_block cvt; \
+ cvt.b[0] = (unsigned char) src; src >>= 6; \
+ cvt.b[1] = (unsigned char) src; src >>= 6; \
+ cvt.b[2] = (unsigned char) src; src >>= 6; \
+ cvt.b[3] = (unsigned char) src; \
+ rslt = (cvt.b32.i0 & 0x3f3f3f3fL) << 2; \
+ }
+
+/*
+ * These macros may someday permit efficient use of 64-bit integers.
+ */
+#define ZERO(d,d0,d1) d0 = 0, d1 = 0
+#define LOAD(d,d0,d1,bl) d0 = (bl).b32.i0, d1 = (bl).b32.i1
+#define LOADREG(d,d0,d1,s,s0,s1) d0 = s0, d1 = s1
+#define OR(d,d0,d1,bl) d0 |= (bl).b32.i0, d1 |= (bl).b32.i1
+#define STORE(s,s0,s1,bl) (bl).b32.i0 = s0, (bl).b32.i1 = s1
+#define DCL_BLOCK(d,d0,d1) long d0, d1
+/* proto(1) workarounds -- barf */
+#define DCL_BLOCK_D DCL_BLOCK(D,D0,D1)
+#define DCL_BLOCK_K DCL_BLOCK(K,K0,K1)
+
+#if defined(LARGEDATA)
+ /* Waste memory like crazy. Also, do permutations in line */
+#define LGCHUNKBITS 3
+#define CHUNKBITS (1<<LGCHUNKBITS)
+#define PERM6464(d,d0,d1,cpp,p) \
+ LOAD(d,d0,d1,(p)[(0<<CHUNKBITS)+(cpp)[0]]); \
+ OR (d,d0,d1,(p)[(1<<CHUNKBITS)+(cpp)[1]]); \
+ OR (d,d0,d1,(p)[(2<<CHUNKBITS)+(cpp)[2]]); \
+ OR (d,d0,d1,(p)[(3<<CHUNKBITS)+(cpp)[3]]); \
+ OR (d,d0,d1,(p)[(4<<CHUNKBITS)+(cpp)[4]]); \
+ OR (d,d0,d1,(p)[(5<<CHUNKBITS)+(cpp)[5]]); \
+ OR (d,d0,d1,(p)[(6<<CHUNKBITS)+(cpp)[6]]); \
+ OR (d,d0,d1,(p)[(7<<CHUNKBITS)+(cpp)[7]]);
+#define PERM3264(d,d0,d1,cpp,p) \
+ LOAD(d,d0,d1,(p)[(0<<CHUNKBITS)+(cpp)[0]]); \
+ OR (d,d0,d1,(p)[(1<<CHUNKBITS)+(cpp)[1]]); \
+ OR (d,d0,d1,(p)[(2<<CHUNKBITS)+(cpp)[2]]); \
+ OR (d,d0,d1,(p)[(3<<CHUNKBITS)+(cpp)[3]]);
+#else
+ /* "small data" */
+#define LGCHUNKBITS 2
+#define CHUNKBITS (1<<LGCHUNKBITS)
+#define PERM6464(d,d0,d1,cpp,p) \
+ { C_block tblk; permute(cpp,&tblk,p,8); LOAD (d,d0,d1,tblk); }
+#define PERM3264(d,d0,d1,cpp,p) \
+ { C_block tblk; permute(cpp,&tblk,p,4); LOAD (d,d0,d1,tblk); }
+
+static void permute(unsigned char *cp, C_block *out, register C_block *p, int chars_in) {
+ register DCL_BLOCK_D;
+ register C_block *tp;
+ register int t;
+
+ ZERO(D,D0,D1);
+ do {
+ t = *cp++;
+ tp = &p[t&0xf]; OR(D,D0,D1,*tp); p += (1<<CHUNKBITS);
+ tp = &p[t>>4]; OR(D,D0,D1,*tp); p += (1<<CHUNKBITS);
+ } while (--chars_in > 0);
+ STORE(D,D0,D1,*out);
+}
+#endif /* LARGEDATA */
+
+
+/* ===== (mostly) Standard DES Tables ==================== */
+
+static unsigned char IP[] = { /* initial permutation */
+ 58, 50, 42, 34, 26, 18, 10, 2,
+ 60, 52, 44, 36, 28, 20, 12, 4,
+ 62, 54, 46, 38, 30, 22, 14, 6,
+ 64, 56, 48, 40, 32, 24, 16, 8,
+ 57, 49, 41, 33, 25, 17, 9, 1,
+ 59, 51, 43, 35, 27, 19, 11, 3,
+ 61, 53, 45, 37, 29, 21, 13, 5,
+ 63, 55, 47, 39, 31, 23, 15, 7,
+};
+
+/* The final permutation is the inverse of IP - no table is necessary */
+
+static unsigned char ExpandTr[] = { /* expansion operation */
+ 32, 1, 2, 3, 4, 5,
+ 4, 5, 6, 7, 8, 9,
+ 8, 9, 10, 11, 12, 13,
+ 12, 13, 14, 15, 16, 17,
+ 16, 17, 18, 19, 20, 21,
+ 20, 21, 22, 23, 24, 25,
+ 24, 25, 26, 27, 28, 29,
+ 28, 29, 30, 31, 32, 1,
+};
+
+static unsigned char PC1[] = { /* permuted choice table 1 */
+ 57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36,
+
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4,
+};
+
+static unsigned char Rotates[] = { /* PC1 rotation schedule */
+ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,
+};
+
+/* note: each "row" of PC2 is left-padded with bits that make it invertible */
+static unsigned char PC2[] = { /* permuted choice table 2 */
+ 9, 18, 14, 17, 11, 24, 1, 5,
+ 22, 25, 3, 28, 15, 6, 21, 10,
+ 35, 38, 23, 19, 12, 4, 26, 8,
+ 43, 54, 16, 7, 27, 20, 13, 2,
+
+ 0, 0, 41, 52, 31, 37, 47, 55,
+ 0, 0, 30, 40, 51, 45, 33, 48,
+ 0, 0, 44, 49, 39, 56, 34, 53,
+ 0, 0, 46, 42, 50, 36, 29, 32,
+};
+
+static unsigned char S[8][64] = { /* 48->32 bit substitution tables */
+ /* S[1] */
+ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
+ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
+ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
+ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
+ /* S[2] */
+ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
+ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
+ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
+ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
+ /* S[3] */
+ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
+ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
+ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
+ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
+ /* S[4] */
+ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
+ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
+ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
+ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
+ /* S[5] */
+ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
+ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
+ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
+ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
+ /* S[6] */
+ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
+ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
+ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
+ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
+ /* S[7] */
+ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
+ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
+ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
+ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
+ /* S[8] */
+ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
+ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
+ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
+ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,
+};
+
+static unsigned char P32Tr[] = { /* 32-bit permutation function */
+ 16, 7, 20, 21,
+ 29, 12, 28, 17,
+ 1, 15, 23, 26,
+ 5, 18, 31, 10,
+ 2, 8, 24, 14,
+ 32, 27, 3, 9,
+ 19, 13, 30, 6,
+ 22, 11, 4, 25,
+};
+
+static unsigned char CIFP[] = { /* compressed/interleaved permutation */
+ 1, 2, 3, 4, 17, 18, 19, 20,
+ 5, 6, 7, 8, 21, 22, 23, 24,
+ 9, 10, 11, 12, 25, 26, 27, 28,
+ 13, 14, 15, 16, 29, 30, 31, 32,
+
+ 33, 34, 35, 36, 49, 50, 51, 52,
+ 37, 38, 39, 40, 53, 54, 55, 56,
+ 41, 42, 43, 44, 57, 58, 59, 60,
+ 45, 46, 47, 48, 61, 62, 63, 64,
+};
+
+static unsigned char itoa64[] = /* 0..63 => ascii-64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+
+/* ===== Tables that are initialized at run time ==================== */
+
+
+static unsigned char a64toi[128]; /* ascii-64 => 0..63 */
+
+/* Initial key schedule permutation */
+static C_block PC1ROT[64/CHUNKBITS][1<<CHUNKBITS];
+
+/* Subsequent key schedule rotation permutations */
+static C_block PC2ROT[2][64/CHUNKBITS][1<<CHUNKBITS];
+
+/* Initial permutation/expansion table */
+static C_block IE3264[32/CHUNKBITS][1<<CHUNKBITS];
+
+/* Table that combines the S, P, and E operations. */
+static long SPE[2][8][64];
+
+/* compressed/interleaved => final permutation table */
+static C_block CF6464[64/CHUNKBITS][1<<CHUNKBITS];
+
+
+/* ==================================== */
+
+static C_block constdatablock; /* encryption constant */
+static char cryptresult[1+4+4+11+1]; /* encrypted result */
+
+/*
+ * Initialize "perm" to represent transformation "p", which rearranges
+ * (perhaps with expansion and/or contraction) one packed array of bits
+ * (of size "chars_in" characters) into another array (of size "chars_out"
+ * characters).
+ *
+ * "perm" must be all-zeroes on entry to this routine.
+ */
+static void init_perm(C_block perm[64/CHUNKBITS][1<<CHUNKBITS],
+ unsigned char p[64], int chars_in, int chars_out) {
+ register int i, j, k, l;
+
+ for (k = 0; k < chars_out*8; k++) { /* each output bit position */
+ l = p[k] - 1; /* where this bit comes from */
+ if (l < 0)
+ continue; /* output bit is always 0 */
+ i = l>>LGCHUNKBITS; /* which chunk this bit comes from */
+ l = 1<<(l&(CHUNKBITS-1)); /* mask for this bit */
+ for (j = 0; j < (1<<CHUNKBITS); j++) { /* each chunk value */
+ if ((j & l) != 0)
+ perm[i][j].b[k>>3] |= 1<<(k&07);
+ }
+ }
+}
+
+/*
+ * Initialize various tables. This need only be done once. It could even be
+ * done at compile time, if the compiler were capable of that sort of thing.
+ */
+static void init_des(void) {
+ register int i, j;
+ register long k;
+ register int tableno;
+ static unsigned char perm[64], tmp32[32]; /* "static" for speed */
+
+ /*
+ * table that converts chars "./0-9A-Za-z"to integers 0-63.
+ */
+ for (i = 0; i < 64; i++)
+ a64toi[itoa64[i]] = i;
+
+ /*
+ * PC1ROT - bit reverse, then PC1, then Rotate, then PC2.
+ */
+ for (i = 0; i < 64; i++)
+ perm[i] = 0;
+ for (i = 0; i < 64; i++) {
+ if ((k = PC2[i]) == 0)
+ continue;
+ k += Rotates[0]-1;
+ if ((k%28) < Rotates[0]) k -= 28;
+ k = PC1[k];
+ if (k > 0) {
+ k--;
+ k = (k|07) - (k&07);
+ k++;
+ }
+ perm[i] = (unsigned char) k;
+ }
+#ifdef DEBUG
+ prtab("pc1tab", perm, 8);
+#endif
+ init_perm(PC1ROT, perm, 8, 8);
+
+ /*
+ * PC2ROT - PC2 inverse, then Rotate (once or twice), then PC2.
+ */
+ for (j = 0; j < 2; j++) {
+ unsigned char pc2inv[64];
+ for (i = 0; i < 64; i++)
+ perm[i] = pc2inv[i] = 0;
+ for (i = 0; i < 64; i++) {
+ if ((k = PC2[i]) == 0)
+ continue;
+ pc2inv[k-1] = i+1;
+ }
+ for (i = 0; i < 64; i++) {
+ if ((k = PC2[i]) == 0)
+ continue;
+ k += j;
+ if ((k%28) <= j) k -= 28;
+ perm[i] = pc2inv[k];
+ }
+#ifdef DEBUG
+ prtab("pc2tab", perm, 8);
+#endif
+ init_perm(PC2ROT[j], perm, 8, 8);
+ }
+
+ /*
+ * Bit reverse, then initial permutation, then expansion.
+ */
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 8; j++) {
+ k = (j < 2)? 0: IP[ExpandTr[i*6+j-2]-1];
+ if (k > 32)
+ k -= 32;
+ else if (k > 0)
+ k--;
+ if (k > 0) {
+ k--;
+ k = (k|07) - (k&07);
+ k++;
+ }
+ perm[i*8+j] = (unsigned char) k;
+ }
+ }
+#ifdef DEBUG
+ prtab("ietab", perm, 8);
+#endif
+ init_perm(IE3264, perm, 4, 8);
+
+ /*
+ * Compression, then final permutation, then bit reverse.
+ */
+ for (i = 0; i < 64; i++) {
+ k = IP[CIFP[i]-1];
+ if (k > 0) {
+ k--;
+ k = (k|07) - (k&07);
+ k++;
+ }
+ perm[k-1] = i+1;
+ }
+#ifdef DEBUG
+ prtab("cftab", perm, 8);
+#endif
+ init_perm(CF6464, perm, 8, 8);
+
+ /*
+ * SPE table
+ */
+ for (i = 0; i < 48; i++)
+ perm[i] = P32Tr[ExpandTr[i]-1];
+ for (tableno = 0; tableno < 8; tableno++) {
+ for (j = 0; j < 64; j++) {
+ k = (((j >> 0) &01) << 5)|
+ (((j >> 1) &01) << 3)|
+ (((j >> 2) &01) << 2)|
+ (((j >> 3) &01) << 1)|
+ (((j >> 4) &01) << 0)|
+ (((j >> 5) &01) << 4);
+ k = S[tableno][k];
+ k = (((k >> 3)&01) << 0)|
+ (((k >> 2)&01) << 1)|
+ (((k >> 1)&01) << 2)|
+ (((k >> 0)&01) << 3);
+ for (i = 0; i < 32; i++)
+ tmp32[i] = 0;
+ for (i = 0; i < 4; i++)
+ tmp32[4 * tableno + i] = (k >> i) & 01;
+ k = 0;
+ for (i = 24; --i >= 0; )
+ k = (k<<1) | tmp32[perm[i]-1];
+ TO_SIX_BIT(SPE[0][tableno][j], k);
+ k = 0;
+ for (i = 24; --i >= 0; )
+ k = (k<<1) | tmp32[perm[i+24]-1];
+ TO_SIX_BIT(SPE[1][tableno][j], k);
+ }
+ }
+}
+
+/*
+ * The Key Schedule, filled in by des_setkey() or setkey().
+ */
+#define KS_SIZE 16
+static C_block KS[KS_SIZE];
+
+/*
+ * Set up the key schedule from the key.
+ */
+static int des_setkey(register const char *key) {
+ register DCL_BLOCK_K;
+ register C_block *ptabp;
+ register int i;
+ static int des_ready = 0;
+
+ if (!des_ready) {
+ init_des();
+ des_ready = 1;
+ }
+
+ PERM6464(K,K0,K1,(unsigned char *)key,(C_block *)PC1ROT);
+ key = (char *)&KS[0];
+ STORE(K&~0x03030303L, K0&~0x03030303L, K1, *(C_block *)key);
+ for (i = 1; i < 16; i++) {
+ key += sizeof(C_block);
+ STORE(K,K0,K1,*(C_block *)key);
+ ptabp = (C_block *)PC2ROT[Rotates[i]-1];
+ PERM6464(K,K0,K1,(unsigned char *)key,ptabp);
+ STORE(K&~0x03030303L, K0&~0x03030303L, K1, *(C_block *)key);
+ }
+ return (0);
+}
+
+/*
+ * Encrypt (or decrypt if num_iter < 0) the 8 chars at "in" with abs(num_iter)
+ * iterations of DES, using the the given 24-bit salt and the pre-computed key
+ * schedule, and store the resulting 8 chars at "out" (in == out is permitted).
+ *
+ * NOTE: the performance of this routine is critically dependent on your
+ * compiler and machine architecture.
+ */
+static int des_cipher(const char *in, char *out, long salt, int num_iter) {
+ /* variables that we want in registers, most important first */
+#if defined(pdp11)
+ register int j;
+#endif
+ register long L0, L1, R0, R1, k;
+ register C_block *kp;
+ register int ks_inc, loop_count;
+ C_block B;
+
+ L0 = salt;
+ TO_SIX_BIT(salt, L0); /* convert to 4*(6+2) format */
+
+#if defined(vax) || defined(pdp11)
+ salt = ~salt; /* "x &~ y" is faster than "x & y". */
+#define SALT (~salt)
+#else
+#define SALT salt
+#endif
+
+#if defined(MUST_ALIGN)
+ B.b[0] = in[0]; B.b[1] = in[1]; B.b[2] = in[2]; B.b[3] = in[3];
+ B.b[4] = in[4]; B.b[5] = in[5]; B.b[6] = in[6]; B.b[7] = in[7];
+ LOAD(L,L0,L1,B);
+#else
+ LOAD(L,L0,L1,*(C_block *)in);
+#endif
+ LOADREG(R,R0,R1,L,L0,L1);
+ L0 &= 0x55555555L;
+ L1 &= 0x55555555L;
+ L0 = (L0 << 1) | L1; /* L0 is the even-numbered input bits */
+ R0 &= 0xaaaaaaaaL;
+ R1 = (R1 >> 1) & 0x55555555L;
+ L1 = R0 | R1; /* L1 is the odd-numbered input bits */
+ STORE(L,L0,L1,B);
+ PERM3264(L,L0,L1,B.b, (C_block *)IE3264); /* even bits */
+ PERM3264(R,R0,R1,B.b+4,(C_block *)IE3264); /* odd bits */
+
+ if (num_iter >= 0)
+ { /* encryption */
+ kp = &KS[0];
+ ks_inc = sizeof(*kp);
+ }
+ else
+ { /* decryption */
+ num_iter = -num_iter;
+ kp = &KS[KS_SIZE-1];
+ ks_inc = -((int) sizeof(*kp));
+ }
+
+ while (--num_iter >= 0) {
+ loop_count = 8;
+ do {
+
+#define SPTAB(t, i) (*(long *)((unsigned char *)t + i*(sizeof(long)/4)))
+#if defined(gould)
+ /* use this if B.b[i] is evaluated just once ... */
+#define DOXOR(x,y,i) x^=SPTAB(SPE[0][i],B.b[i]); y^=SPTAB(SPE[1][i],B.b[i]);
+#else
+#if defined(pdp11)
+ /* use this if your "long" int indexing is slow */
+#define DOXOR(x,y,i) j=B.b[i]; x^=SPTAB(SPE[0][i],j); y^=SPTAB(SPE[1][i],j);
+#else
+ /* use this if "k" is allocated to a register ... */
+#define DOXOR(x,y,i) k=B.b[i]; x^=SPTAB(SPE[0][i],k); y^=SPTAB(SPE[1][i],k);
+#endif
+#endif
+
+#define CRUNCH(p0, p1, q0, q1) \
+ k = (q0 ^ q1) & SALT; \
+ B.b32.i0 = k ^ q0 ^ kp->b32.i0; \
+ B.b32.i1 = k ^ q1 ^ kp->b32.i1; \
+ kp = (C_block *)((char *)kp+ks_inc); \
+ \
+ DOXOR(p0, p1, 0); \
+ DOXOR(p0, p1, 1); \
+ DOXOR(p0, p1, 2); \
+ DOXOR(p0, p1, 3); \
+ DOXOR(p0, p1, 4); \
+ DOXOR(p0, p1, 5); \
+ DOXOR(p0, p1, 6); \
+ DOXOR(p0, p1, 7);
+
+ CRUNCH(L0, L1, R0, R1);
+ CRUNCH(R0, R1, L0, L1);
+ } while (--loop_count != 0);
+ kp = (C_block *)((char *)kp-(ks_inc*KS_SIZE));
+
+
+ /* swap L and R */
+ L0 ^= R0; L1 ^= R1;
+ R0 ^= L0; R1 ^= L1;
+ L0 ^= R0; L1 ^= R1;
+ }
+
+ /* store the encrypted (or decrypted) result */
+ L0 = ((L0 >> 3) & 0x0f0f0f0fL) | ((L1 << 1) & 0xf0f0f0f0L);
+ L1 = ((R0 >> 3) & 0x0f0f0f0fL) | ((R1 << 1) & 0xf0f0f0f0L);
+ STORE(L,L0,L1,B);
+ PERM6464(L,L0,L1,B.b, (C_block *)CF6464);
+#if defined(MUST_ALIGN)
+ STORE(L,L0,L1,B);
+ out[0] = B.b[0]; out[1] = B.b[1]; out[2] = B.b[2]; out[3] = B.b[3];
+ out[4] = B.b[4]; out[5] = B.b[5]; out[6] = B.b[6]; out[7] = B.b[7];
+#else
+ STORE(L,L0,L1,*(C_block *)out);
+#endif
+ return (0);
+}
+
+/*
+ * "setkey" routine (for backwards compatibility)
+ */
+extern int setkey(register const char *key) {
+ register int i, j, k;
+ C_block keyblock;
+
+ for (i = 0; i < 8; i++) {
+ k = 0;
+ for (j = 0; j < 8; j++) {
+ k <<= 1;
+ k |= (unsigned char)*key++;
+ }
+ keyblock.b[i] = k;
+ }
+ return (des_setkey((char *)keyblock.b));
+}
+
+/*
+ * "encrypt" routine (for backwards compatibility)
+ */
+extern int encrypt(register char *block, int flag) {
+ register int i, j, k;
+ C_block cblock;
+
+ for (i = 0; i < 8; i++) {
+ k = 0;
+ for (j = 0; j < 8; j++) {
+ k <<= 1;
+ k |= (unsigned char)*block++;
+ }
+ cblock.b[i] = k;
+ }
+ if (des_cipher((char *)&cblock, (char *)&cblock, 0L, (flag ? -1: 1)))
+ return (1);
+ for (i = 7; i >= 0; i--) {
+ k = cblock.b[i];
+ for (j = 7; j >= 0; j--) {
+ *--block = k&01;
+ k >>= 1;
+ }
+ }
+ return (0);
+}
+
+/*
+ * Return a pointer to static data consisting of the "setting"
+ * followed by an encryption produced by the "key" and "setting".
+ */
+extern char * crypt(register const char *key, register const char *setting) {
+ register char *encp;
+ register long i;
+ register int t;
+ long salt;
+ int num_iter, salt_size;
+ C_block keyblock, rsltblock;
+
+#ifdef HL_NOENCRYPTION
+ char buff[1024];
+ strncpy(buff, key, 1024);
+ buff[1023] = 0;
+ return buff;
+#endif
+
+ for (i = 0; i < 8; i++) {
+ if ((t = 2*(unsigned char)(*key)) != 0)
+ key++;
+ keyblock.b[i] = t;
+ }
+ if (des_setkey((char *)keyblock.b)) /* also initializes "a64toi" */
+ return (NULL);
+
+ encp = &cryptresult[0];
+ switch (*setting) {
+ case _PASSWORD_EFMT1:
+ /*
+ * Involve the rest of the password 8 characters at a time.
+ */
+ while (*key) {
+ if (des_cipher((char *)&keyblock,
+ (char *)&keyblock, 0L, 1))
+ return (NULL);
+ for (i = 0; i < 8; i++) {
+ if ((t = 2*(unsigned char)(*key)) != 0)
+ key++;
+ keyblock.b[i] ^= t;
+ }
+ if (des_setkey((char *)keyblock.b))
+ return (NULL);
+ }
+
+ *encp++ = *setting++;
+
+ /* get iteration count */
+ num_iter = 0;
+ for (i = 4; --i >= 0; ) {
+ if ((t = (unsigned char)setting[i]) == '\0')
+ t = '.';
+ encp[i] = t;
+ num_iter = (num_iter<<6) | a64toi[t];
+ }
+ setting += 4;
+ encp += 4;
+ salt_size = 4;
+ break;
+ default:
+ num_iter = 25;
+ salt_size = 2;
+ }
+
+ salt = 0;
+ for (i = salt_size; --i >= 0; ) {
+ if ((t = (unsigned char)setting[i]) == '\0')
+ t = '.';
+ encp[i] = t;
+ salt = (salt<<6) | a64toi[t];
+ }
+ encp += salt_size;
+ if (des_cipher((char *)&constdatablock, (char *)&rsltblock,
+ salt, num_iter))
+ return (NULL);
+
+ /*
+ * Encode the 64 cipher bits as 11 ascii characters.
+ */
+ i = ((long)((rsltblock.b[0]<<8) | rsltblock.b[1])<<8) | rsltblock.b[2];
+ encp[3] = itoa64[i&0x3f]; i >>= 6;
+ encp[2] = itoa64[i&0x3f]; i >>= 6;
+ encp[1] = itoa64[i&0x3f]; i >>= 6;
+ encp[0] = itoa64[i]; encp += 4;
+ i = ((long)((rsltblock.b[3]<<8) | rsltblock.b[4])<<8) | rsltblock.b[5];
+ encp[3] = itoa64[i&0x3f]; i >>= 6;
+ encp[2] = itoa64[i&0x3f]; i >>= 6;
+ encp[1] = itoa64[i&0x3f]; i >>= 6;
+ encp[0] = itoa64[i]; encp += 4;
+ i = ((long)((rsltblock.b[6])<<8) | rsltblock.b[7])<<2;
+ encp[2] = itoa64[i&0x3f]; i >>= 6;
+ encp[1] = itoa64[i&0x3f]; i >>= 6;
+ encp[0] = itoa64[i];
+
+ encp[3] = 0;
+
+ return (cryptresult);
+}
+
+#ifdef DEBUG
+STATIC
+prtab(s, t, num_rows)
+ char *s;
+ unsigned char *t;
+ int num_rows;
+{
+ register int i, j;
+
+ (void)printf("%s:\n", s);
+ for (i = 0; i < num_rows; i++) {
+ for (j = 0; j < 8; j++) {
+ (void)printf("%3d", t[i*8+j]);
+ }
+ (void)printf("\n");
+ }
+ (void)printf("\n");
+}
+#endif
+
+#endif
diff --git a/src/lib/libast/uwin/erf.c b/src/lib/libast/uwin/erf.c
new file mode 100644
index 0000000..4a61f78
--- /dev/null
+++ b/src/lib/libast/uwin/erf.c
@@ -0,0 +1,403 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_erf
+
+void _STUB_erf(){}
+
+#else
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)erf.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/* Modified Nov 30, 1992 P. McILROY:
+ * Replaced expansions for x >= 1.25 (error 1.7ulp vs ~6ulp)
+ * Replaced even+odd with direct calculation for x < .84375,
+ * to avoid destructive cancellation.
+ *
+ * Performance of erfc(x):
+ * In 300000 trials in the range [.83, .84375] the
+ * maximum observed error was 3.6ulp.
+ *
+ * In [.84735,1.25] the maximum observed error was <2.5ulp in
+ * 100000 runs in the range [1.2, 1.25].
+ *
+ * In [1.25,26] (Not including subnormal results)
+ * the error is < 1.7ulp.
+ */
+
+/* double erf(double x)
+ * double erfc(double x)
+ * x
+ * 2 |\
+ * erf(x) = --------- | exp(-t*t)dt
+ * sqrt(pi) \|
+ * 0
+ *
+ * erfc(x) = 1-erf(x)
+ *
+ * Method:
+ * 1. Reduce x to |x| by erf(-x) = -erf(x)
+ * 2. For x in [0, 0.84375]
+ * erf(x) = x + x*P(x^2)
+ * erfc(x) = 1 - erf(x) if x<=0.25
+ * = 0.5 + ((0.5-x)-x*P) if x in [0.25,0.84375]
+ * where
+ * 2 2 4 20
+ * P = P(x ) = (p0 + p1 * x + p2 * x + ... + p10 * x )
+ * is an approximation to (erf(x)-x)/x with precision
+ *
+ * -56.45
+ * | P - (erf(x)-x)/x | <= 2
+ *
+ *
+ * Remark. The formula is derived by noting
+ * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
+ * and that
+ * 2/sqrt(pi) = 1.128379167095512573896158903121545171688
+ * is close to one. The interval is chosen because the fixed
+ * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
+ * near 0.6174), and by some experiment, 0.84375 is chosen to
+ * guarantee the error is less than one ulp for erf.
+ *
+ * 3. For x in [0.84375,1.25], let s = x - 1, and
+ * c = 0.84506291151 rounded to single (24 bits)
+ * erf(x) = c + P1(s)/Q1(s)
+ * erfc(x) = (1-c) - P1(s)/Q1(s)
+ * |P1/Q1 - (erf(x)-c)| <= 2**-59.06
+ * Remark: here we use the taylor series expansion at x=1.
+ * erf(1+s) = erf(1) + s*Poly(s)
+ * = 0.845.. + P1(s)/Q1(s)
+ * That is, we use rational approximation to approximate
+ * erf(1+s) - (c = (single)0.84506291151)
+ * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
+ * where
+ * P1(s) = degree 6 poly in s
+ * Q1(s) = degree 6 poly in s
+ *
+ * 4. For x in [1.25, 2]; [2, 4]
+ * erf(x) = 1.0 - tiny
+ * erfc(x) = (1/x)exp(-x*x-(.5*log(pi) -.5z + R(z)/S(z))
+ *
+ * Where z = 1/(x*x), R is degree 9, and S is degree 3;
+ *
+ * 5. For x in [4,28]
+ * erf(x) = 1.0 - tiny
+ * erfc(x) = (1/x)exp(-x*x-(.5*log(pi)+eps + zP(z))
+ *
+ * Where P is degree 14 polynomial in 1/(x*x).
+ *
+ * Notes:
+ * Here 4 and 5 make use of the asymptotic series
+ * exp(-x*x)
+ * erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) );
+ * x*sqrt(pi)
+ *
+ * where for z = 1/(x*x)
+ * P(z) ~ z/2*(-1 + z*3/2*(1 + z*5/2*(-1 + z*7/2*(1 +...))))
+ *
+ * Thus we use rational approximation to approximate
+ * erfc*x*exp(x*x) ~ 1/sqrt(pi);
+ *
+ * The error bound for the target function, G(z) for
+ * the interval
+ * [4, 28]:
+ * |eps + 1/(z)P(z) - G(z)| < 2**(-56.61)
+ * for [2, 4]:
+ * |R(z)/S(z) - G(z)| < 2**(-58.24)
+ * for [1.25, 2]:
+ * |R(z)/S(z) - G(z)| < 2**(-58.12)
+ *
+ * 6. For inf > x >= 28
+ * erf(x) = 1 - tiny (raise inexact)
+ * erfc(x) = tiny*tiny (raise underflow)
+ *
+ * 7. Special cases:
+ * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1,
+ * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
+ * erfc/erf(NaN) is NaN
+ */
+
+#if defined(vax) || defined(tahoe)
+#define _IEEE 0
+#define TRUNC(x) (double) (float) (x)
+#else
+#define _IEEE 1
+#define TRUNC(x) *(((int *) &x) + 1) &= 0xf8000000
+#define infnan(x) 0.0
+#endif
+
+#ifdef _IEEE_LIBM
+/*
+ * redefining "___function" to "function" in _IEEE_LIBM mode
+ */
+#include "ieee_libm.h"
+#endif
+#include "mathimpl.h"
+
+static double
+tiny = 1e-300,
+half = 0.5,
+one = 1.0,
+two = 2.0,
+c = 8.45062911510467529297e-01, /* (float)0.84506291151 */
+/*
+ * Coefficients for approximation to erf in [0,0.84375]
+ */
+p0t8 = 1.02703333676410051049867154944018394163280,
+p0 = 1.283791670955125638123339436800229927041e-0001,
+p1 = -3.761263890318340796574473028946097022260e-0001,
+p2 = 1.128379167093567004871858633779992337238e-0001,
+p3 = -2.686617064084433642889526516177508374437e-0002,
+p4 = 5.223977576966219409445780927846432273191e-0003,
+p5 = -8.548323822001639515038738961618255438422e-0004,
+p6 = 1.205520092530505090384383082516403772317e-0004,
+p7 = -1.492214100762529635365672665955239554276e-0005,
+p8 = 1.640186161764254363152286358441771740838e-0006,
+p9 = -1.571599331700515057841960987689515895479e-0007,
+p10= 1.073087585213621540635426191486561494058e-0008;
+/*
+ * Coefficients for approximation to erf in [0.84375,1.25]
+ */
+static double
+pa0 = -2.362118560752659485957248365514511540287e-0003,
+pa1 = 4.148561186837483359654781492060070469522e-0001,
+pa2 = -3.722078760357013107593507594535478633044e-0001,
+pa3 = 3.183466199011617316853636418691420262160e-0001,
+pa4 = -1.108946942823966771253985510891237782544e-0001,
+pa5 = 3.547830432561823343969797140537411825179e-0002,
+pa6 = -2.166375594868790886906539848893221184820e-0003,
+qa1 = 1.064208804008442270765369280952419863524e-0001,
+qa2 = 5.403979177021710663441167681878575087235e-0001,
+qa3 = 7.182865441419627066207655332170665812023e-0002,
+qa4 = 1.261712198087616469108438860983447773726e-0001,
+qa5 = 1.363708391202905087876983523620537833157e-0002,
+qa6 = 1.198449984679910764099772682882189711364e-0002;
+/*
+ * log(sqrt(pi)) for large x expansions.
+ * The tail (lsqrtPI_lo) is included in the rational
+ * approximations.
+*/
+static double
+ lsqrtPI_hi = .5723649429247000819387380943226;
+/*
+ * lsqrtPI_lo = .000000000000000005132975581353913;
+ *
+ * Coefficients for approximation to erfc in [2, 4]
+*/
+static double
+rb0 = -1.5306508387410807582e-010, /* includes lsqrtPI_lo */
+rb1 = 2.15592846101742183841910806188e-008,
+rb2 = 6.24998557732436510470108714799e-001,
+rb3 = 8.24849222231141787631258921465e+000,
+rb4 = 2.63974967372233173534823436057e+001,
+rb5 = 9.86383092541570505318304640241e+000,
+rb6 = -7.28024154841991322228977878694e+000,
+rb7 = 5.96303287280680116566600190708e+000,
+rb8 = -4.40070358507372993983608466806e+000,
+rb9 = 2.39923700182518073731330332521e+000,
+rb10 = -6.89257464785841156285073338950e-001,
+sb1 = 1.56641558965626774835300238919e+001,
+sb2 = 7.20522741000949622502957936376e+001,
+sb3 = 9.60121069770492994166488642804e+001;
+/*
+ * Coefficients for approximation to erfc in [1.25, 2]
+*/
+static double
+rc0 = -2.47925334685189288817e-007, /* includes lsqrtPI_lo */
+rc1 = 1.28735722546372485255126993930e-005,
+rc2 = 6.24664954087883916855616917019e-001,
+rc3 = 4.69798884785807402408863708843e+000,
+rc4 = 7.61618295853929705430118701770e+000,
+rc5 = 9.15640208659364240872946538730e-001,
+rc6 = -3.59753040425048631334448145935e-001,
+rc7 = 1.42862267989304403403849619281e-001,
+rc8 = -4.74392758811439801958087514322e-002,
+rc9 = 1.09964787987580810135757047874e-002,
+rc10 = -1.28856240494889325194638463046e-003,
+sc1 = 9.97395106984001955652274773456e+000,
+sc2 = 2.80952153365721279953959310660e+001,
+sc3 = 2.19826478142545234106819407316e+001;
+/*
+ * Coefficients for approximation to erfc in [4,28]
+ */
+static double
+rd0 = -2.1491361969012978677e-016, /* includes lsqrtPI_lo */
+rd1 = -4.99999999999640086151350330820e-001,
+rd2 = 6.24999999772906433825880867516e-001,
+rd3 = -1.54166659428052432723177389562e+000,
+rd4 = 5.51561147405411844601985649206e+000,
+rd5 = -2.55046307982949826964613748714e+001,
+rd6 = 1.43631424382843846387913799845e+002,
+rd7 = -9.45789244999420134263345971704e+002,
+rd8 = 6.94834146607051206956384703517e+003,
+rd9 = -5.27176414235983393155038356781e+004,
+rd10 = 3.68530281128672766499221324921e+005,
+rd11 = -2.06466642800404317677021026611e+006,
+rd12 = 7.78293889471135381609201431274e+006,
+rd13 = -1.42821001129434127360582351685e+007;
+
+extern double erf(x)
+ double x;
+{
+ double R,S,P,Q,ax,s,y,z,r,fabs(),exp();
+ if(!finite(x)) { /* erf(nan)=nan */
+ if (isnan(x))
+ return(x);
+ return (x > 0 ? one : -one); /* erf(+/-inf)= +/-1 */
+ }
+ if ((ax = x) < 0)
+ ax = - ax;
+ if (ax < .84375) {
+ if (ax < 3.7e-09) {
+ if (ax < 1.0e-308)
+ return 0.125*(8.0*x+p0t8*x); /*avoid underflow */
+ return x + p0*x;
+ }
+ y = x*x;
+ r = y*(p1+y*(p2+y*(p3+y*(p4+y*(p5+
+ y*(p6+y*(p7+y*(p8+y*(p9+y*p10)))))))));
+ return x + x*(p0+r);
+ }
+ if (ax < 1.25) { /* 0.84375 <= |x| < 1.25 */
+ s = fabs(x)-one;
+ P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+ Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+ if (x>=0)
+ return (c + P/Q);
+ else
+ return (-c - P/Q);
+ }
+ if (ax >= 6.0) { /* inf>|x|>=6 */
+ if (x >= 0.0)
+ return (one-tiny);
+ else
+ return (tiny-one);
+ }
+ /* 1.25 <= |x| < 6 */
+ z = -ax*ax;
+ s = -one/z;
+ if (ax < 2.0) {
+ R = rc0+s*(rc1+s*(rc2+s*(rc3+s*(rc4+s*(rc5+
+ s*(rc6+s*(rc7+s*(rc8+s*(rc9+s*rc10)))))))));
+ S = one+s*(sc1+s*(sc2+s*sc3));
+ } else {
+ R = rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+
+ s*(rb6+s*(rb7+s*(rb8+s*(rb9+s*rb10)))))))));
+ S = one+s*(sb1+s*(sb2+s*sb3));
+ }
+ y = (R/S -.5*s) - lsqrtPI_hi;
+ z += y;
+ z = exp(z)/ax;
+ if (x >= 0)
+ return (one-z);
+ else
+ return (z-one);
+}
+
+extern double erfc(x)
+ double x;
+{
+ double R,S,P,Q,s,ax,y,z,r,fabs(),__exp__D();
+ if (!finite(x)) {
+ if (isnan(x)) /* erfc(NaN) = NaN */
+ return(x);
+ else if (x > 0) /* erfc(+-inf)=0,2 */
+ return 0.0;
+ else
+ return 2.0;
+ }
+ if ((ax = x) < 0)
+ ax = -ax;
+ if (ax < .84375) { /* |x|<0.84375 */
+ if (ax < 1.38777878078144568e-17) /* |x|<2**-56 */
+ return one-x;
+ y = x*x;
+ r = y*(p1+y*(p2+y*(p3+y*(p4+y*(p5+
+ y*(p6+y*(p7+y*(p8+y*(p9+y*p10)))))))));
+ if (ax < .0625) { /* |x|<2**-4 */
+ return (one-(x+x*(p0+r)));
+ } else {
+ r = x*(p0+r);
+ r += (x-half);
+ return (half - r);
+ }
+ }
+ if (ax < 1.25) { /* 0.84375 <= |x| < 1.25 */
+ s = ax-one;
+ P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+ Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+ if (x>=0) {
+ z = one-c; return z - P/Q;
+ } else {
+ z = c+P/Q; return one+z;
+ }
+ }
+ if (ax >= 28) /* Out of range */
+ if (x>0)
+ return (tiny*tiny);
+ else
+ return (two-tiny);
+ z = ax;
+ TRUNC(z);
+ y = z - ax; y *= (ax+z);
+ z *= -z; /* Here z + y = -x^2 */
+ s = one/(-z-y); /* 1/(x*x) */
+ if (ax >= 4) { /* 6 <= ax */
+ R = s*(rd1+s*(rd2+s*(rd3+s*(rd4+s*(rd5+
+ s*(rd6+s*(rd7+s*(rd8+s*(rd9+s*(rd10
+ +s*(rd11+s*(rd12+s*rd13))))))))))));
+ y += rd0;
+ } else if (ax >= 2) {
+ R = rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+
+ s*(rb6+s*(rb7+s*(rb8+s*(rb9+s*rb10)))))))));
+ S = one+s*(sb1+s*(sb2+s*sb3));
+ y += R/S;
+ R = -.5*s;
+ } else {
+ R = rc0+s*(rc1+s*(rc2+s*(rc3+s*(rc4+s*(rc5+
+ s*(rc6+s*(rc7+s*(rc8+s*(rc9+s*rc10)))))))));
+ S = one+s*(sc1+s*(sc2+s*sc3));
+ y += R/S;
+ R = -.5*s;
+ }
+ /* return exp(-x^2 - lsqrtPI_hi + R + y)/x; */
+ s = ((R + y) - lsqrtPI_hi) + z;
+ y = (((z-s) - lsqrtPI_hi) + R) + y;
+ r = __exp__D(s, y)/x;
+ if (x>0)
+ return r;
+ else
+ return two-r;
+}
+
+#endif
diff --git a/src/lib/libast/uwin/err.c b/src/lib/libast/uwin/err.c
new file mode 100644
index 0000000..123a64e
--- /dev/null
+++ b/src/lib/libast/uwin/err.c
@@ -0,0 +1,124 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "FEATURE/uwin"
+
+#if !_UWIN
+
+void _STUB_err(){}
+
+#else
+
+#pragma prototyped
+
+/*
+ * bsd 4.4 compatibility
+ *
+ * NOTE: errorv(ERROR_NOID) => the first arg is the printf format
+ */
+
+#include <ast.h>
+#include <error.h>
+
+#include <windows.h>
+
+#ifdef __EXPORT__
+#define extern __EXPORT__
+#endif
+
+static void
+errmsg(int level, int code, const char* fmt, va_list ap)
+{
+ if (!error_info.id)
+ {
+ struct _astdll* dp = _ast_getdll();
+ char* s;
+ char* t;
+
+ if (s = dp->_ast__argv[0])
+ {
+ if (t = strrchr(s, '/'))
+ s = t + 1;
+ error_info.id = s;
+ }
+ }
+ errorv(fmt, level|ERROR_NOID, ap);
+ if ((level & ERROR_LEVEL) >= ERROR_ERROR)
+ exit(code);
+}
+
+extern void verr(int code, const char* fmt, va_list ap)
+{
+ errmsg(ERROR_ERROR|ERROR_SYSTEM, code, fmt, ap);
+}
+
+extern void err(int code, const char* fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ errmsg(ERROR_ERROR|ERROR_SYSTEM, code, fmt, ap);
+ va_end(ap);
+}
+
+extern void verrx(int code, const char* fmt, va_list ap)
+{
+ errmsg(ERROR_ERROR, code, fmt, ap);
+}
+
+extern void errx(int code, const char* fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ errmsg(ERROR_ERROR, code, fmt, ap);
+ va_end(ap);
+}
+
+extern void vwarn(const char* fmt, va_list ap)
+{
+ errmsg(ERROR_WARNING|ERROR_SYSTEM, 0, fmt, ap);
+}
+
+extern void warn(const char* fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ errmsg(ERROR_WARNING|ERROR_SYSTEM, 0, fmt, ap);
+ va_end(ap);
+}
+
+extern void vwarnx(const char* fmt, va_list ap)
+{
+ errmsg(ERROR_WARNING, 0, fmt, ap);
+}
+
+extern void warnx(const char* fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ errmsg(ERROR_WARNING, 0, fmt, ap);
+ va_end(ap);
+}
+
+#endif
diff --git a/src/lib/libast/uwin/exp.c b/src/lib/libast/uwin/exp.c
new file mode 100644
index 0000000..d1e15bd
--- /dev/null
+++ b/src/lib/libast/uwin/exp.c
@@ -0,0 +1,213 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN
+
+void _STUB_exp(){}
+
+#else
+
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)exp.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/* EXP(X)
+ * RETURN THE EXPONENTIAL OF X
+ * DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS)
+ * CODED IN C BY K.C. NG, 1/19/85;
+ * REVISED BY K.C. NG on 2/6/85, 2/15/85, 3/7/85, 3/24/85, 4/16/85, 6/14/86.
+ *
+ * Required system supported functions:
+ * scalb(x,n)
+ * copysign(x,y)
+ * finite(x)
+ *
+ * Method:
+ * 1. Argument Reduction: given the input x, find r and integer k such
+ * that
+ * x = k*ln2 + r, |r| <= 0.5*ln2 .
+ * r will be represented as r := z+c for better accuracy.
+ *
+ * 2. Compute exp(r) by
+ *
+ * exp(r) = 1 + r + r*R1/(2-R1),
+ * where
+ * R1 = x - x^2*(p1+x^2*(p2+x^2*(p3+x^2*(p4+p5*x^2)))).
+ *
+ * 3. exp(x) = 2^k * exp(r) .
+ *
+ * Special cases:
+ * exp(INF) is INF, exp(NaN) is NaN;
+ * exp(-INF)= 0;
+ * for finite argument, only exp(0)=1 is exact.
+ *
+ * Accuracy:
+ * exp(x) returns the exponential of x nearly rounded. In a test run
+ * with 1,156,000 random arguments on a VAX, the maximum observed
+ * error was 0.869 ulps (units in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following constants.
+ * The decimal values may be used, provided that the compiler will convert
+ * from decimal to binary accurately enough to produce the hexadecimal values
+ * shown.
+ */
+
+#include "mathimpl.h"
+
+vc(ln2hi, 6.9314718055829871446E-1 ,7217,4031,0000,f7d0, 0, .B17217F7D00000)
+vc(ln2lo, 1.6465949582897081279E-12 ,bcd5,2ce7,d9cc,e4f1, -39, .E7BCD5E4F1D9CC)
+vc(lnhuge, 9.4961163736712506989E1 ,ec1d,43bd,9010,a73e, 7, .BDEC1DA73E9010)
+vc(lntiny,-9.5654310917272452386E1 ,4f01,c3bf,33af,d72e, 7,-.BF4F01D72E33AF)
+vc(invln2, 1.4426950408889634148E0 ,aa3b,40b8,17f1,295c, 1, .B8AA3B295C17F1)
+vc(p1, 1.6666666666666602251E-1 ,aaaa,3f2a,a9f1,aaaa, -2, .AAAAAAAAAAA9F1)
+vc(p2, -2.7777777777015591216E-3 ,0b60,bc36,ec94,b5f5, -8,-.B60B60B5F5EC94)
+vc(p3, 6.6137563214379341918E-5 ,b355,398a,f15f,792e, -13, .8AB355792EF15F)
+vc(p4, -1.6533902205465250480E-6 ,ea0e,b6dd,5f84,2e93, -19,-.DDEA0E2E935F84)
+vc(p5, 4.1381367970572387085E-8 ,bb4b,3431,2683,95f5, -24, .B1BB4B95F52683)
+
+#ifdef vccast
+#define ln2hi vccast(ln2hi)
+#define ln2lo vccast(ln2lo)
+#define lnhuge vccast(lnhuge)
+#define lntiny vccast(lntiny)
+#define invln2 vccast(invln2)
+#define p1 vccast(p1)
+#define p2 vccast(p2)
+#define p3 vccast(p3)
+#define p4 vccast(p4)
+#define p5 vccast(p5)
+#endif
+
+ic(p1, 1.6666666666666601904E-1, -3, 1.555555555553E)
+ic(p2, -2.7777777777015593384E-3, -9, -1.6C16C16BEBD93)
+ic(p3, 6.6137563214379343612E-5, -14, 1.1566AAF25DE2C)
+ic(p4, -1.6533902205465251539E-6, -20, -1.BBD41C5D26BF1)
+ic(p5, 4.1381367970572384604E-8, -25, 1.6376972BEA4D0)
+ic(ln2hi, 6.9314718036912381649E-1, -1, 1.62E42FEE00000)
+ic(ln2lo, 1.9082149292705877000E-10,-33, 1.A39EF35793C76)
+ic(lnhuge, 7.1602103751842355450E2, 9, 1.6602B15B7ECF2)
+ic(lntiny,-7.5137154372698068983E2, 9, -1.77AF8EBEAE354)
+ic(invln2, 1.4426950408889633870E0, 0, 1.71547652B82FE)
+
+#if !_lib_exp
+
+extern double exp(x)
+double x;
+{
+ double z,hi,lo,c;
+ int k;
+
+#if !defined(vax)&&!defined(tahoe)
+ if(x!=x) return(x); /* x is NaN */
+#endif /* !defined(vax)&&!defined(tahoe) */
+ if( x <= lnhuge ) {
+ if( x >= lntiny ) {
+
+ /* argument reduction : x --> x - k*ln2 */
+
+ k=invln2*x+copysign(0.5,x); /* k=NINT(x/ln2) */
+
+ /* express x-k*ln2 as hi-lo and let x=hi-lo rounded */
+
+ hi=x-k*ln2hi;
+ x=hi-(lo=k*ln2lo);
+
+ /* return 2^k*[1+x+x*c/(2+c)] */
+ z=x*x;
+ c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5))));
+ return scalb(1.0+(hi-(lo-(x*c)/(2.0-c))),k);
+
+ }
+ /* end of x > lntiny */
+
+ else
+ /* exp(-big#) underflows to zero */
+ if(finite(x)) return(scalb(1.0,-5000));
+
+ /* exp(-INF) is zero */
+ else return(0.0);
+ }
+ /* end of x < lnhuge */
+
+ else
+ /* exp(INF) is INF, exp(+big#) overflows to INF */
+ return( finite(x) ? scalb(1.0,5000) : x);
+}
+
+#endif
+
+/* returns exp(r = x + c) for |c| < |x| with no overlap. */
+
+double __exp__D(x, c)
+double x, c;
+{
+ double z,hi,lo;
+ int k;
+
+#if !defined(vax)&&!defined(tahoe)
+ if (x!=x) return(x); /* x is NaN */
+#endif /* !defined(vax)&&!defined(tahoe) */
+ if ( x <= lnhuge ) {
+ if ( x >= lntiny ) {
+
+ /* argument reduction : x --> x - k*ln2 */
+ z = invln2*x;
+ k = (int)z + copysign(.5, x);
+
+ /* express (x+c)-k*ln2 as hi-lo and let x=hi-lo rounded */
+
+ hi=(x-k*ln2hi); /* Exact. */
+ x= hi - (lo = k*ln2lo-c);
+ /* return 2^k*[1+x+x*c/(2+c)] */
+ z=x*x;
+ c= x - z*(p1+z*(p2+z*(p3+z*(p4+z*p5))));
+ c = (x*c)/(2.0-c);
+
+ return scalb(1.+(hi-(lo - c)), k);
+ }
+ /* end of x > lntiny */
+
+ else
+ /* exp(-big#) underflows to zero */
+ if(finite(x)) return(scalb(1.0,-5000));
+
+ /* exp(-INF) is zero */
+ else return(0.0);
+ }
+ /* end of x < lnhuge */
+
+ else
+ /* exp(INF) is INF, exp(+big#) overflows to INF */
+ return( finite(x) ? scalb(1.0,5000) : x);
+}
+
+#endif
diff --git a/src/lib/libast/uwin/exp__E.c b/src/lib/libast/uwin/exp__E.c
new file mode 100644
index 0000000..5c131a8
--- /dev/null
+++ b/src/lib/libast/uwin/exp__E.c
@@ -0,0 +1,142 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN
+
+void _STUB_exp__E(){}
+
+#else
+
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)exp__E.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/* exp__E(x,c)
+ * ASSUMPTION: c << x SO THAT fl(x+c)=x.
+ * (c is the correction term for x)
+ * exp__E RETURNS
+ *
+ * / exp(x+c) - 1 - x , 1E-19 < |x| < .3465736
+ * exp__E(x,c) = |
+ * \ 0 , |x| < 1E-19.
+ *
+ * DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS)
+ * KERNEL FUNCTION OF EXP, EXPM1, POW FUNCTIONS
+ * CODED IN C BY K.C. NG, 1/31/85;
+ * REVISED BY K.C. NG on 3/16/85, 4/16/85.
+ *
+ * Required system supported function:
+ * copysign(x,y)
+ *
+ * Method:
+ * 1. Rational approximation. Let r=x+c.
+ * Based on
+ * 2 * sinh(r/2)
+ * exp(r) - 1 = ---------------------- ,
+ * cosh(r/2) - sinh(r/2)
+ * exp__E(r) is computed using
+ * x*x (x/2)*W - ( Q - ( 2*P + x*P ) )
+ * --- + (c + x*[---------------------------------- + c ])
+ * 2 1 - W
+ * where P := p1*x^2 + p2*x^4,
+ * Q := q1*x^2 + q2*x^4 (for 56 bits precision, add q3*x^6)
+ * W := x/2-(Q-x*P),
+ *
+ * (See the listing below for the values of p1,p2,q1,q2,q3. The poly-
+ * nomials P and Q may be regarded as the approximations to sinh
+ * and cosh :
+ * sinh(r/2) = r/2 + r * P , cosh(r/2) = 1 + Q . )
+ *
+ * The coefficients were obtained by a special Remez algorithm.
+ *
+ * Approximation error:
+ *
+ * | exp(x) - 1 | 2**(-57), (IEEE double)
+ * | ------------ - (exp__E(x,0)+x)/x | <=
+ * | x | 2**(-69). (VAX D)
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following constants.
+ * The decimal values may be used, provided that the compiler will convert
+ * from decimal to binary accurately enough to produce the hexadecimal values
+ * shown.
+ */
+
+#include "mathimpl.h"
+
+vc(p1, 1.5150724356786683059E-2 ,3abe,3d78,066a,67e1, -6, .F83ABE67E1066A)
+vc(p2, 6.3112487873718332688E-5 ,5b42,3984,0173,48cd, -13, .845B4248CD0173)
+vc(q1, 1.1363478204690669916E-1 ,b95a,3ee8,ec45,44a2, -3, .E8B95A44A2EC45)
+vc(q2, 1.2624568129896839182E-3 ,7905,3ba5,f5e7,72e4, -9, .A5790572E4F5E7)
+vc(q3, 1.5021856115869022674E-6 ,9eb4,36c9,c395,604a, -19, .C99EB4604AC395)
+
+ic(p1, 1.3887401997267371720E-2, -7, 1.C70FF8B3CC2CF)
+ic(p2, 3.3044019718331897649E-5, -15, 1.15317DF4526C4)
+ic(q1, 1.1110813732786649355E-1, -4, 1.C719538248597)
+ic(q2, 9.9176615021572857300E-4, -10, 1.03FC4CB8C98E8)
+
+#ifdef vccast
+#define p1 vccast(p1)
+#define p2 vccast(p2)
+#define q1 vccast(q1)
+#define q2 vccast(q2)
+#define q3 vccast(q3)
+#endif
+
+double __exp__E(x,c)
+double x,c;
+{
+ const static double zero=0.0, one=1.0, half=1.0/2.0, small=1.0E-19;
+ double z,p,q,xp,xh,w;
+ if(copysign(x,one)>small) {
+ z = x*x ;
+ p = z*( p1 +z* p2 );
+#if defined(vax)||defined(tahoe)
+ q = z*( q1 +z*( q2 +z* q3 ));
+#else /* defined(vax)||defined(tahoe) */
+ q = z*( q1 +z* q2 );
+#endif /* defined(vax)||defined(tahoe) */
+ xp= x*p ;
+ xh= x*half ;
+ w = xh-(q-xp) ;
+ p = p+p;
+ c += x*((xh*w-(q-(p+xp)))/(one-w)+c);
+ return(z*half+c);
+ }
+ /* end of |x| > small */
+
+ else {
+ if(x!=zero) one+small; /* raise the inexact flag */
+ return(copysign(zero,x));
+ }
+}
+
+#endif
diff --git a/src/lib/libast/uwin/expm1.c b/src/lib/libast/uwin/expm1.c
new file mode 100644
index 0000000..1e7f694
--- /dev/null
+++ b/src/lib/libast/uwin/expm1.c
@@ -0,0 +1,173 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_expm1
+
+void _STUB_expm1(){}
+
+#else
+
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)expm1.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/* EXPM1(X)
+ * RETURN THE EXPONENTIAL OF X MINUS ONE
+ * DOUBLE PRECISION (IEEE 53 BITS, VAX D FORMAT 56 BITS)
+ * CODED IN C BY K.C. NG, 1/19/85;
+ * REVISED BY K.C. NG on 2/6/85, 3/7/85, 3/21/85, 4/16/85.
+ *
+ * Required system supported functions:
+ * scalb(x,n)
+ * copysign(x,y)
+ * finite(x)
+ *
+ * Kernel function:
+ * exp__E(x,c)
+ *
+ * Method:
+ * 1. Argument Reduction: given the input x, find r and integer k such
+ * that
+ * x = k*ln2 + r, |r| <= 0.5*ln2 .
+ * r will be represented as r := z+c for better accuracy.
+ *
+ * 2. Compute EXPM1(r)=exp(r)-1 by
+ *
+ * EXPM1(r=z+c) := z + exp__E(z,c)
+ *
+ * 3. EXPM1(x) = 2^k * ( EXPM1(r) + 1-2^-k ).
+ *
+ * Remarks:
+ * 1. When k=1 and z < -0.25, we use the following formula for
+ * better accuracy:
+ * EXPM1(x) = 2 * ( (z+0.5) + exp__E(z,c) )
+ * 2. To avoid rounding error in 1-2^-k where k is large, we use
+ * EXPM1(x) = 2^k * { [z+(exp__E(z,c)-2^-k )] + 1 }
+ * when k>56.
+ *
+ * Special cases:
+ * EXPM1(INF) is INF, EXPM1(NaN) is NaN;
+ * EXPM1(-INF)= -1;
+ * for finite argument, only EXPM1(0)=0 is exact.
+ *
+ * Accuracy:
+ * EXPM1(x) returns the exact (exp(x)-1) nearly rounded. In a test run with
+ * 1,166,000 random arguments on a VAX, the maximum observed error was
+ * .872 ulps (units of the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following constants.
+ * The decimal values may be used, provided that the compiler will convert
+ * from decimal to binary accurately enough to produce the hexadecimal values
+ * shown.
+ */
+
+#include "mathimpl.h"
+
+vc(ln2hi, 6.9314718055829871446E-1 ,7217,4031,0000,f7d0, 0, .B17217F7D00000)
+vc(ln2lo, 1.6465949582897081279E-12 ,bcd5,2ce7,d9cc,e4f1, -39, .E7BCD5E4F1D9CC)
+vc(lnhuge, 9.4961163736712506989E1 ,ec1d,43bd,9010,a73e, 7, .BDEC1DA73E9010)
+vc(invln2, 1.4426950408889634148E0 ,aa3b,40b8,17f1,295c, 1, .B8AA3B295C17F1)
+
+ic(ln2hi, 6.9314718036912381649E-1, -1, 1.62E42FEE00000)
+ic(ln2lo, 1.9082149292705877000E-10, -33, 1.A39EF35793C76)
+ic(lnhuge, 7.1602103751842355450E2, 9, 1.6602B15B7ECF2)
+ic(invln2, 1.4426950408889633870E0, 0, 1.71547652B82FE)
+
+#ifdef vccast
+#define ln2hi vccast(ln2hi)
+#define ln2lo vccast(ln2lo)
+#define lnhuge vccast(lnhuge)
+#define invln2 vccast(invln2)
+#endif
+
+extern double expm1(x)
+double x;
+{
+ const static double one=1.0, half=1.0/2.0;
+ double z,hi,lo,c;
+ int k;
+#if defined(vax)||defined(tahoe)
+ static prec=56;
+#else /* defined(vax)||defined(tahoe) */
+ static prec=53;
+#endif /* defined(vax)||defined(tahoe) */
+
+#if !defined(vax)&&!defined(tahoe)
+ if(x!=x) return(x); /* x is NaN */
+#endif /* !defined(vax)&&!defined(tahoe) */
+
+ if( x <= lnhuge ) {
+ if( x >= -40.0 ) {
+
+ /* argument reduction : x - k*ln2 */
+ k= (int)(invln2*x)+copysign(0.5,x); /* k=NINT(x/ln2) */
+ hi=x-k*ln2hi ;
+ z=hi-(lo=k*ln2lo);
+ c=(hi-z)-lo;
+
+ if(k==0) return(z+__exp__E(z,c));
+ if(k==1)
+ if(z< -0.25)
+ {x=z+half;x +=__exp__E(z,c); return(x+x);}
+ else
+ {z+=__exp__E(z,c); x=half+z; return(x+x);}
+ /* end of k=1 */
+
+ else {
+ if(k<=prec)
+ { x=one-scalb(one,-k); z += __exp__E(z,c);}
+ else if(k<100)
+ { x = __exp__E(z,c)-scalb(one,-k); x+=z; z=one;}
+ else
+ { x = __exp__E(z,c)+z; z=one;}
+
+ return (scalb(x+z,k));
+ }
+ }
+ /* end of x > lnunfl */
+
+ else
+ /* expm1(-big#) rounded to -1 (inexact) */
+ if(finite(x))
+ { ln2hi+ln2lo; return(-one);}
+
+ /* expm1(-INF) is -1 */
+ else return(-one);
+ }
+ /* end of x < lnhuge */
+
+ else
+ /* expm1(INF) is INF, expm1(+big#) overflows to INF */
+ return( finite(x) ? scalb(one,5000) : x);
+}
+
+#endif
diff --git a/src/lib/libast/uwin/gamma.c b/src/lib/libast/uwin/gamma.c
new file mode 100644
index 0000000..0cb1d1f
--- /dev/null
+++ b/src/lib/libast/uwin/gamma.c
@@ -0,0 +1,343 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_gamma
+
+void _STUB_gamma(){}
+
+#else
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)gamma.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/*
+ * This code by P. McIlroy, Oct 1992;
+ *
+ * The financial support of UUNET Communications Services is greatfully
+ * acknowledged.
+ */
+
+#define gamma ______gamma
+
+#include <math.h>
+#include <errno.h>
+#include "mathimpl.h"
+
+#undef gamma
+
+/* METHOD:
+ * x < 0: Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x))
+ * At negative integers, return +Inf, and set errno.
+ *
+ * x < 6.5:
+ * Use argument reduction G(x+1) = xG(x) to reach the
+ * range [1.066124,2.066124]. Use a rational
+ * approximation centered at the minimum (x0+1) to
+ * ensure monotonicity.
+ *
+ * x >= 6.5: Use the asymptotic approximation (Stirling's formula)
+ * adjusted for equal-ripples:
+ *
+ * log(G(x)) ~= (x-.5)*(log(x)-1) + .5(log(2*pi)-1) + 1/x*P(1/(x*x))
+ *
+ * Keep extra precision in multiplying (x-.5)(log(x)-1), to
+ * avoid premature round-off.
+ *
+ * Special values:
+ * non-positive integer: Set overflow trap; return +Inf;
+ * x > 171.63: Set overflow trap; return +Inf;
+ * NaN: Set invalid trap; return NaN
+ *
+ * Accuracy: Gamma(x) is accurate to within
+ * x > 0: error provably < 0.9ulp.
+ * Maximum observed in 1,000,000 trials was .87ulp.
+ * x < 0:
+ * Maximum observed error < 4ulp in 1,000,000 trials.
+ */
+
+static double neg_gam __P((double));
+static double small_gam __P((double));
+static double smaller_gam __P((double));
+static struct Double large_gam __P((double));
+static struct Double ratfun_gam __P((double, double));
+
+/*
+ * Rational approximation, A0 + x*x*P(x)/Q(x), on the interval
+ * [1.066.., 2.066..] accurate to 4.25e-19.
+ */
+#define LEFT -.3955078125 /* left boundary for rat. approx */
+#define x0 .461632144968362356785 /* xmin - 1 */
+
+#define a0_hi 0.88560319441088874992
+#define a0_lo -.00000000000000004996427036469019695
+#define P0 6.21389571821820863029017800727e-01
+#define P1 2.65757198651533466104979197553e-01
+#define P2 5.53859446429917461063308081748e-03
+#define P3 1.38456698304096573887145282811e-03
+#define P4 2.40659950032711365819348969808e-03
+#define Q0 1.45019531250000000000000000000e+00
+#define Q1 1.06258521948016171343454061571e+00
+#define Q2 -2.07474561943859936441469926649e-01
+#define Q3 -1.46734131782005422506287573015e-01
+#define Q4 3.07878176156175520361557573779e-02
+#define Q5 5.12449347980666221336054633184e-03
+#define Q6 -1.76012741431666995019222898833e-03
+#define Q7 9.35021023573788935372153030556e-05
+#define Q8 6.13275507472443958924745652239e-06
+/*
+ * Constants for large x approximation (x in [6, Inf])
+ * (Accurate to 2.8*10^-19 absolute)
+ */
+#define lns2pi_hi 0.418945312500000
+#define lns2pi_lo -.000006779295327258219670263595
+#define Pa0 8.33333333333333148296162562474e-02
+#define Pa1 -2.77777777774548123579378966497e-03
+#define Pa2 7.93650778754435631476282786423e-04
+#define Pa3 -5.95235082566672847950717262222e-04
+#define Pa4 8.41428560346653702135821806252e-04
+#define Pa5 -1.89773526463879200348872089421e-03
+#define Pa6 5.69394463439411649408050664078e-03
+#define Pa7 -1.44705562421428915453880392761e-02
+
+static const double zero = 0., one = 1.0, tiny = 1e-300;
+static int endian;
+/*
+ * TRUNC sets trailing bits in a floating-point number to zero.
+ * is a temporary variable.
+ */
+#if defined(vax) || defined(tahoe)
+#define _IEEE 0
+#define TRUNC(x) x = (double) (float) (x)
+#else
+#define _IEEE 1
+#define TRUNC(x) *(((int *) &x) + endian) &= 0xf8000000
+#define infnan(x) 0.0
+#endif
+
+extern double gamma(x)
+ double x;
+{
+ struct Double u;
+ endian = (*(int *) &one) ? 1 : 0;
+
+ if (x >= 6) {
+ if(x > 171.63)
+ return(one/zero);
+ u = large_gam(x);
+ return(__exp__D(u.a, u.b));
+ } else if (x >= 1.0 + LEFT + x0)
+ return (small_gam(x));
+ else if (x > 1.e-17)
+ return (smaller_gam(x));
+ else if (x > -1.e-17) {
+ if (x == 0.0)
+ if (!_IEEE) return (infnan(ERANGE));
+ else return (one/x);
+ one+1e-20; /* Raise inexact flag. */
+ return (one/x);
+ } else if (!finite(x)) {
+ if (_IEEE) /* x = NaN, -Inf */
+ return (x*x);
+ else
+ return (infnan(EDOM));
+ } else
+ return (neg_gam(x));
+}
+/*
+ * Accurate to max(ulp(1/128) absolute, 2^-66 relative) error.
+ */
+static struct Double
+large_gam(x)
+ double x;
+{
+ double z, p;
+ struct Double t, u, v;
+
+ z = one/(x*x);
+ p = Pa0+z*(Pa1+z*(Pa2+z*(Pa3+z*(Pa4+z*(Pa5+z*(Pa6+z*Pa7))))));
+ p = p/x;
+
+ u = __log__D(x);
+ u.a -= one;
+ v.a = (x -= .5);
+ TRUNC(v.a);
+ v.b = x - v.a;
+ t.a = v.a*u.a; /* t = (x-.5)*(log(x)-1) */
+ t.b = v.b*u.a + x*u.b;
+ /* return t.a + t.b + lns2pi_hi + lns2pi_lo + p */
+ t.b += lns2pi_lo; t.b += p;
+ u.a = lns2pi_hi + t.b; u.a += t.a;
+ u.b = t.a - u.a;
+ u.b += lns2pi_hi; u.b += t.b;
+ return (u);
+}
+/*
+ * Good to < 1 ulp. (provably .90 ulp; .87 ulp on 1,000,000 runs.)
+ * It also has correct monotonicity.
+ */
+static double
+small_gam(x)
+ double x;
+{
+ double y, ym1, t;
+ struct Double yy, r;
+ y = x - one;
+ ym1 = y - one;
+ if (y <= 1.0 + (LEFT + x0)) {
+ yy = ratfun_gam(y - x0, 0);
+ return (yy.a + yy.b);
+ }
+ r.a = y;
+ TRUNC(r.a);
+ yy.a = r.a - one;
+ y = ym1;
+ yy.b = r.b = y - yy.a;
+ /* Argument reduction: G(x+1) = x*G(x) */
+ for (ym1 = y-one; ym1 > LEFT + x0; y = ym1--, yy.a--) {
+ t = r.a*yy.a;
+ r.b = r.a*yy.b + y*r.b;
+ r.a = t;
+ TRUNC(r.a);
+ r.b += (t - r.a);
+ }
+ /* Return r*gamma(y). */
+ yy = ratfun_gam(y - x0, 0);
+ y = r.b*(yy.a + yy.b) + r.a*yy.b;
+ y += yy.a*r.a;
+ return (y);
+}
+/*
+ * Good on (0, 1+x0+LEFT]. Accurate to 1ulp.
+ */
+static double
+smaller_gam(x)
+ double x;
+{
+ double t, d;
+ struct Double r, xx;
+ if (x < x0 + LEFT) {
+ t = x, TRUNC(t);
+ d = (t+x)*(x-t);
+ t *= t;
+ xx.a = (t + x), TRUNC(xx.a);
+ xx.b = x - xx.a; xx.b += t; xx.b += d;
+ t = (one-x0); t += x;
+ d = (one-x0); d -= t; d += x;
+ x = xx.a + xx.b;
+ } else {
+ xx.a = x, TRUNC(xx.a);
+ xx.b = x - xx.a;
+ t = x - x0;
+ d = (-x0 -t); d += x;
+ }
+ r = ratfun_gam(t, d);
+ d = r.a/x, TRUNC(d);
+ r.a -= d*xx.a; r.a -= d*xx.b; r.a += r.b;
+ return (d + r.a/x);
+}
+/*
+ * returns (z+c)^2 * P(z)/Q(z) + a0
+ */
+static struct Double
+ratfun_gam(z, c)
+ double z, c;
+{
+ double p, q;
+ struct Double r, t;
+
+ q = Q0 +z*(Q1+z*(Q2+z*(Q3+z*(Q4+z*(Q5+z*(Q6+z*(Q7+z*Q8)))))));
+ p = P0 + z*(P1 + z*(P2 + z*(P3 + z*P4)));
+
+ /* return r.a + r.b = a0 + (z+c)^2*p/q, with r.a truncated to 26 bits. */
+ p = p/q;
+ t.a = z, TRUNC(t.a); /* t ~= z + c */
+ t.b = (z - t.a) + c;
+ t.b *= (t.a + z);
+ q = (t.a *= t.a); /* t = (z+c)^2 */
+ TRUNC(t.a);
+ t.b += (q - t.a);
+ r.a = p, TRUNC(r.a); /* r = P/Q */
+ r.b = p - r.a;
+ t.b = t.b*p + t.a*r.b + a0_lo;
+ t.a *= r.a; /* t = (z+c)^2*(P/Q) */
+ r.a = t.a + a0_hi, TRUNC(r.a);
+ r.b = ((a0_hi-r.a) + t.a) + t.b;
+ return (r); /* r = a0 + t */
+}
+
+static double
+neg_gam(x)
+ double x;
+{
+ int sgn = 1;
+ struct Double lg, lsine;
+ double y, z;
+
+ y = floor(x + .5);
+ if (y == x) /* Negative integer. */
+ if(!_IEEE)
+ return (infnan(ERANGE));
+ else
+ return (one/zero);
+ z = fabs(x - y);
+ y = .5*ceil(x);
+ if (y == ceil(y))
+ sgn = -1;
+ if (z < .25)
+ z = sin(M_PI*z);
+ else
+ z = cos(M_PI*(0.5-z));
+ /* Special case: G(1-x) = Inf; G(x) may be nonzero. */
+ if (x < -170) {
+ if (x < -190)
+ return ((double)sgn*tiny*tiny);
+ y = one - x; /* exact: 128 < |x| < 255 */
+ lg = large_gam(y);
+ lsine = __log__D(M_PI/z); /* = TRUNC(log(u)) + small */
+ lg.a -= lsine.a; /* exact (opposite signs) */
+ lg.b -= lsine.b;
+ y = -(lg.a + lg.b);
+ z = (y + lg.a) + lg.b;
+ y = __exp__D(y, z);
+ if (sgn < 0) y = -y;
+ return (y);
+ }
+ y = one-x;
+ if (one-y == x)
+ y = gamma(y);
+ else /* 1-x is inexact */
+ y = -x*gamma(-x);
+ if (sgn < 0) y = -y;
+ return (M_PI / (y*z));
+}
+
+#endif
diff --git a/src/lib/libast/uwin/getpass.c b/src/lib/libast/uwin/getpass.c
new file mode 100644
index 0000000..bb65996
--- /dev/null
+++ b/src/lib/libast/uwin/getpass.c
@@ -0,0 +1,79 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_getpass
+
+void _STUB_getpass(){}
+
+#else
+
+#pragma prototyped
+
+#define getpass ______getpass
+
+#include <ast.h>
+#include <termios.h>
+#include <signal.h>
+
+#undef getpass
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+static int interrupt;
+static void handler(int sig)
+{
+ interrupt++;
+}
+
+extern char* getpass(const char *prompt)
+{
+ struct termios told,tnew;
+ Sfio_t *iop;
+ static char *cp, passwd[32];
+ void (*savesig)(int);
+ if(!(iop = sfopen((Sfio_t*)0, "/dev/tty", "r")))
+ return(0);
+ if(tcgetattr(sffileno(iop),&told) < 0)
+ return(0);
+ interrupt = 0;
+ tnew = told;
+ tnew.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL);
+ if(tcsetattr(sffileno(iop),TCSANOW,&tnew) < 0)
+ return(0);
+ savesig = signal(SIGINT, handler);
+ sfputr(sfstderr,prompt,-1);
+ if(cp = sfgetr(iop,'\n',1))
+ strncpy(passwd,cp,sizeof(passwd)-1);
+ tcsetattr(sffileno(iop),TCSANOW,&told);
+ sfputc(sfstderr,'\n');
+ sfclose(iop);
+ signal(SIGINT, savesig);
+ if(interrupt)
+ kill(getpid(),SIGINT);
+ return(cp?passwd:0);
+}
+
+
+#endif
diff --git a/src/lib/libast/uwin/lgamma.c b/src/lib/libast/uwin/lgamma.c
new file mode 100644
index 0000000..d37357d
--- /dev/null
+++ b/src/lib/libast/uwin/lgamma.c
@@ -0,0 +1,316 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_lgamma
+
+void _STUB_lgamma(){}
+
+#else
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)lgamma.c 8.2 (Berkeley) 11/30/93";
+#endif /* not lint */
+
+/*
+ * Coded by Peter McIlroy, Nov 1992;
+ *
+ * The financial support of UUNET Communications Services is greatfully
+ * acknowledged.
+ */
+
+#define gamma ______gamma
+#define lgamma ______lgamma
+
+#include <math.h>
+#include <errno.h>
+#include "mathimpl.h"
+
+#undef gamma
+#undef lgamma
+
+/* Log gamma function.
+ * Error: x > 0 error < 1.3ulp.
+ * x > 4, error < 1ulp.
+ * x > 9, error < .6ulp.
+ * x < 0, all bets are off. (When G(x) ~ 1, log(G(x)) ~ 0)
+ * Method:
+ * x > 6:
+ * Use the asymptotic expansion (Stirling's Formula)
+ * 0 < x < 6:
+ * Use gamma(x+1) = x*gamma(x) for argument reduction.
+ * Use rational approximation in
+ * the range 1.2, 2.5
+ * Two approximations are used, one centered at the
+ * minimum to ensure monotonicity; one centered at 2
+ * to maintain small relative error.
+ * x < 0:
+ * Use the reflection formula,
+ * G(1-x)G(x) = PI/sin(PI*x)
+ * Special values:
+ * non-positive integer returns +Inf.
+ * NaN returns NaN
+*/
+static int endian;
+#if defined(vax) || defined(tahoe)
+#define _IEEE 0
+/* double and float have same size exponent field */
+#define TRUNC(x) x = (double) (float) (x)
+#else
+#define _IEEE 1
+#define TRUNC(x) *(((int *) &x) + endian) &= 0xf8000000
+#define infnan(x) 0.0
+#endif
+
+static double small_lgam(double);
+static double large_lgam(double);
+static double neg_lgam(double);
+static double zero = 0.0, one = 1.0;
+int signgam;
+
+#define UNDERFL (1e-1020 * 1e-1020)
+
+#define LEFT (1.0 - (x0 + .25))
+#define RIGHT (x0 - .218)
+/*
+ * Constants for approximation in [1.244,1.712]
+*/
+#define x0 0.461632144968362356785
+#define x0_lo -.000000000000000015522348162858676890521
+#define a0_hi -0.12148629128932952880859
+#define a0_lo .0000000007534799204229502
+#define r0 -2.771227512955130520e-002
+#define r1 -2.980729795228150847e-001
+#define r2 -3.257411333183093394e-001
+#define r3 -1.126814387531706041e-001
+#define r4 -1.129130057170225562e-002
+#define r5 -2.259650588213369095e-005
+#define s0 1.714457160001714442e+000
+#define s1 2.786469504618194648e+000
+#define s2 1.564546365519179805e+000
+#define s3 3.485846389981109850e-001
+#define s4 2.467759345363656348e-002
+/*
+ * Constants for approximation in [1.71, 2.5]
+*/
+#define a1_hi 4.227843350984671344505727574870e-01
+#define a1_lo 4.670126436531227189e-18
+#define p0 3.224670334241133695662995251041e-01
+#define p1 3.569659696950364669021382724168e-01
+#define p2 1.342918716072560025853732668111e-01
+#define p3 1.950702176409779831089963408886e-02
+#define p4 8.546740251667538090796227834289e-04
+#define q0 1.000000000000000444089209850062e+00
+#define q1 1.315850076960161985084596381057e+00
+#define q2 6.274644311862156431658377186977e-01
+#define q3 1.304706631926259297049597307705e-01
+#define q4 1.102815279606722369265536798366e-02
+#define q5 2.512690594856678929537585620579e-04
+#define q6 -1.003597548112371003358107325598e-06
+/*
+ * Stirling's Formula, adjusted for equal-ripple. x in [6,Inf].
+*/
+#define lns2pi .418938533204672741780329736405
+#define pb0 8.33333333333333148296162562474e-02
+#define pb1 -2.77777777774548123579378966497e-03
+#define pb2 7.93650778754435631476282786423e-04
+#define pb3 -5.95235082566672847950717262222e-04
+#define pb4 8.41428560346653702135821806252e-04
+#define pb5 -1.89773526463879200348872089421e-03
+#define pb6 5.69394463439411649408050664078e-03
+#define pb7 -1.44705562421428915453880392761e-02
+
+extern __pure double lgamma(double x)
+{
+ double r;
+
+ signgam = 1;
+ endian = ((*(int *) &one)) ? 1 : 0;
+
+ if (!finite(x))
+ if (_IEEE)
+ return (x+x);
+ else return (infnan(EDOM));
+
+ if (x > 6 + RIGHT) {
+ r = large_lgam(x);
+ return (r);
+ } else if (x > 1e-16)
+ return (small_lgam(x));
+ else if (x > -1e-16) {
+ if (x < 0)
+ signgam = -1, x = -x;
+ return (-log(x));
+ } else
+ return (neg_lgam(x));
+}
+
+static double
+large_lgam(double x)
+{
+ double z, p, x1;
+ struct Double t, u, v;
+ u = __log__D(x);
+ u.a -= 1.0;
+ if (x > 1e15) {
+ v.a = x - 0.5;
+ TRUNC(v.a);
+ v.b = (x - v.a) - 0.5;
+ t.a = u.a*v.a;
+ t.b = x*u.b + v.b*u.a;
+ if (_IEEE == 0 && !finite(t.a))
+ return(infnan(ERANGE));
+ return(t.a + t.b);
+ }
+ x1 = 1./x;
+ z = x1*x1;
+ p = pb0+z*(pb1+z*(pb2+z*(pb3+z*(pb4+z*(pb5+z*(pb6+z*pb7))))));
+ /* error in approximation = 2.8e-19 */
+
+ p = p*x1; /* error < 2.3e-18 absolute */
+ /* 0 < p < 1/64 (at x = 5.5) */
+ v.a = x = x - 0.5;
+ TRUNC(v.a); /* truncate v.a to 26 bits. */
+ v.b = x - v.a;
+ t.a = v.a*u.a; /* t = (x-.5)*(log(x)-1) */
+ t.b = v.b*u.a + x*u.b;
+ t.b += p; t.b += lns2pi; /* return t + lns2pi + p */
+ return (t.a + t.b);
+}
+
+static double
+small_lgam(double x)
+{
+ int x_int;
+ double y, z, t, r = 0, p, q, hi, lo;
+ struct Double rr;
+ x_int = (int)(x + .5);
+ y = x - x_int;
+ if (x_int <= 2 && y > RIGHT) {
+ t = y - x0;
+ y--; x_int++;
+ goto CONTINUE;
+ } else if (y < -LEFT) {
+ t = y +(1.0-x0);
+CONTINUE:
+ z = t - x0_lo;
+ p = r0+z*(r1+z*(r2+z*(r3+z*(r4+z*r5))));
+ q = s0+z*(s1+z*(s2+z*(s3+z*s4)));
+ r = t*(z*(p/q) - x0_lo);
+ t = .5*t*t;
+ z = 1.0;
+ switch (x_int) {
+ case 6: z = (y + 5);
+ case 5: z *= (y + 4);
+ case 4: z *= (y + 3);
+ case 3: z *= (y + 2);
+ rr = __log__D(z);
+ rr.b += a0_lo; rr.a += a0_hi;
+ return(((r+rr.b)+t+rr.a));
+ case 2: return(((r+a0_lo)+t)+a0_hi);
+ case 0: r -= log1p(x);
+ default: rr = __log__D(x);
+ rr.a -= a0_hi; rr.b -= a0_lo;
+ return(((r - rr.b) + t) - rr.a);
+ }
+ } else {
+ p = p0+y*(p1+y*(p2+y*(p3+y*p4)));
+ q = q0+y*(q1+y*(q2+y*(q3+y*(q4+y*(q5+y*q6)))));
+ p = p*(y/q);
+ t = (double)(float) y;
+ z = y-t;
+ hi = (double)(float) (p+a1_hi);
+ lo = a1_hi - hi; lo += p; lo += a1_lo;
+ r = lo*y + z*hi; /* q + r = y*(a0+p/q) */
+ q = hi*t;
+ z = 1.0;
+ switch (x_int) {
+ case 6: z = (y + 5);
+ case 5: z *= (y + 4);
+ case 4: z *= (y + 3);
+ case 3: z *= (y + 2);
+ rr = __log__D(z);
+ r += rr.b; r += q;
+ return(rr.a + r);
+ case 2: return (q+ r);
+ case 0: rr = __log__D(x);
+ r -= rr.b; r -= log1p(x);
+ r += q; r-= rr.a;
+ return(r);
+ default: rr = __log__D(x);
+ r -= rr.b;
+ q -= rr.a;
+ return (r+q);
+ }
+ }
+}
+
+static double
+neg_lgam(double x)
+{
+ int xi;
+ double y, z, one = 1.0, zero = 0.0;
+ extern double gamma();
+
+ /* avoid destructive cancellation as much as possible */
+ if (x > -170) {
+ xi = (int)x;
+ if (xi == x)
+ if (_IEEE)
+ return(one/zero);
+ else
+ return(infnan(ERANGE));
+ y = gamma(x);
+ if (y < 0)
+ y = -y, signgam = -1;
+ return (log(y));
+ }
+ z = floor(x + .5);
+ if (z == x) { /* convention: G(-(integer)) -> +Inf */
+ if (_IEEE)
+ return (one/zero);
+ else
+ return (infnan(ERANGE));
+ }
+ y = .5*ceil(x);
+ if (y == ceil(y))
+ signgam = -1;
+ x = -x;
+ z = fabs(x + z); /* 0 < z <= .5 */
+ if (z < .25)
+ z = sin(M_PI*z);
+ else
+ z = cos(M_PI*(0.5-z));
+ z = log(M_PI/(z*x));
+ y = large_lgam(x);
+ return (z - y);
+}
+
+#endif
diff --git a/src/lib/libast/uwin/log.c b/src/lib/libast/uwin/log.c
new file mode 100644
index 0000000..e9365a3
--- /dev/null
+++ b/src/lib/libast/uwin/log.c
@@ -0,0 +1,496 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN
+
+void _STUB_log(){}
+
+#else
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)log.c 8.2 (Berkeley) 11/30/93";
+#endif /* not lint */
+
+#include <math.h>
+#include <errno.h>
+
+#include "mathimpl.h"
+
+/* Table-driven natural logarithm.
+ *
+ * This code was derived, with minor modifications, from:
+ * Peter Tang, "Table-Driven Implementation of the
+ * Logarithm in IEEE Floating-Point arithmetic." ACM Trans.
+ * Math Software, vol 16. no 4, pp 378-400, Dec 1990).
+ *
+ * Calculates log(2^m*F*(1+f/F)), |f/j| <= 1/256,
+ * where F = j/128 for j an integer in [0, 128].
+ *
+ * log(2^m) = log2_hi*m + log2_tail*m
+ * since m is an integer, the dominant term is exact.
+ * m has at most 10 digits (for subnormal numbers),
+ * and log2_hi has 11 trailing zero bits.
+ *
+ * log(F) = logF_hi[j] + logF_lo[j] is in tabular form in log_table.h
+ * logF_hi[] + 512 is exact.
+ *
+ * log(1+f/F) = 2*f/(2*F + f) + 1/12 * (2*f/(2*F + f))**3 + ...
+ * the leading term is calculated to extra precision in two
+ * parts, the larger of which adds exactly to the dominant
+ * m and F terms.
+ * There are two cases:
+ * 1. when m, j are non-zero (m | j), use absolute
+ * precision for the leading term.
+ * 2. when m = j = 0, |1-x| < 1/256, and log(x) ~= (x-1).
+ * In this case, use a relative precision of 24 bits.
+ * (This is done differently in the original paper)
+ *
+ * Special cases:
+ * 0 return signalling -Inf
+ * neg return signalling NaN
+ * +Inf return +Inf
+*/
+
+#if defined(vax) || defined(tahoe)
+#define _IEEE 0
+#define TRUNC(x) x = (double) (float) (x)
+#else
+#define _IEEE 1
+#define endian (((*(int *) &one)) ? 1 : 0)
+#define TRUNC(x) *(((int *) &x) + endian) &= 0xf8000000
+#define infnan(x) 0.0
+#endif
+
+#define N 128
+
+/* Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128.
+ * Used for generation of extend precision logarithms.
+ * The constant 35184372088832 is 2^45, so the divide is exact.
+ * It ensures correct reading of logF_head, even for inaccurate
+ * decimal-to-binary conversion routines. (Everybody gets the
+ * right answer for integers less than 2^53.)
+ * Values for log(F) were generated using error < 10^-57 absolute
+ * with the bc -l package.
+*/
+static double A1 = .08333333333333178827;
+static double A2 = .01250000000377174923;
+static double A3 = .002232139987919447809;
+static double A4 = .0004348877777076145742;
+
+static double logF_head[N+1] = {
+ 0.,
+ .007782140442060381246,
+ .015504186535963526694,
+ .023167059281547608406,
+ .030771658666765233647,
+ .038318864302141264488,
+ .045809536031242714670,
+ .053244514518837604555,
+ .060624621816486978786,
+ .067950661908525944454,
+ .075223421237524235039,
+ .082443669210988446138,
+ .089612158689760690322,
+ .096729626458454731618,
+ .103796793681567578460,
+ .110814366340264314203,
+ .117783035656430001836,
+ .124703478501032805070,
+ .131576357788617315236,
+ .138402322859292326029,
+ .145182009844575077295,
+ .151916042025732167530,
+ .158605030176659056451,
+ .165249572895390883786,
+ .171850256926518341060,
+ .178407657472689606947,
+ .184922338493834104156,
+ .191394852999565046047,
+ .197825743329758552135,
+ .204215541428766300668,
+ .210564769107350002741,
+ .216873938300523150246,
+ .223143551314024080056,
+ .229374101064877322642,
+ .235566071312860003672,
+ .241719936886966024758,
+ .247836163904594286577,
+ .253915209980732470285,
+ .259957524436686071567,
+ .265963548496984003577,
+ .271933715484010463114,
+ .277868451003087102435,
+ .283768173130738432519,
+ .289633292582948342896,
+ .295464212893421063199,
+ .301261330578199704177,
+ .307025035294827830512,
+ .312755710004239517729,
+ .318453731118097493890,
+ .324119468654316733591,
+ .329753286372579168528,
+ .335355541920762334484,
+ .340926586970454081892,
+ .346466767346100823488,
+ .351976423156884266063,
+ .357455888922231679316,
+ .362905493689140712376,
+ .368325561158599157352,
+ .373716409793814818840,
+ .379078352934811846353,
+ .384411698910298582632,
+ .389716751140440464951,
+ .394993808240542421117,
+ .400243164127459749579,
+ .405465108107819105498,
+ .410659924985338875558,
+ .415827895143593195825,
+ .420969294644237379543,
+ .426084395310681429691,
+ .431173464818130014464,
+ .436236766774527495726,
+ .441274560805140936281,
+ .446287102628048160113,
+ .451274644139630254358,
+ .456237433481874177232,
+ .461175715122408291790,
+ .466089729924533457960,
+ .470979715219073113985,
+ .475845904869856894947,
+ .480688529345570714212,
+ .485507815781602403149,
+ .490303988045525329653,
+ .495077266798034543171,
+ .499827869556611403822,
+ .504556010751912253908,
+ .509261901790523552335,
+ .513945751101346104405,
+ .518607764208354637958,
+ .523248143765158602036,
+ .527867089620485785417,
+ .532464798869114019908,
+ .537041465897345915436,
+ .541597282432121573947,
+ .546132437597407260909,
+ .550647117952394182793,
+ .555141507540611200965,
+ .559615787935399566777,
+ .564070138285387656651,
+ .568504735352689749561,
+ .572919753562018740922,
+ .577315365035246941260,
+ .581691739635061821900,
+ .586049045003164792433,
+ .590387446602107957005,
+ .594707107746216934174,
+ .599008189645246602594,
+ .603290851438941899687,
+ .607555250224322662688,
+ .611801541106615331955,
+ .616029877215623855590,
+ .620240409751204424537,
+ .624433288012369303032,
+ .628608659422752680256,
+ .632766669570628437213,
+ .636907462236194987781,
+ .641031179420679109171,
+ .645137961373620782978,
+ .649227946625615004450,
+ .653301272011958644725,
+ .657358072709030238911,
+ .661398482245203922502,
+ .665422632544505177065,
+ .669430653942981734871,
+ .673422675212350441142,
+ .677398823590920073911,
+ .681359224807238206267,
+ .685304003098281100392,
+ .689233281238557538017,
+ .693147180560117703862
+};
+
+static double logF_tail[N+1] = {
+ 0.,
+ -.00000000000000543229938420049,
+ .00000000000000172745674997061,
+ -.00000000000001323017818229233,
+ -.00000000000001154527628289872,
+ -.00000000000000466529469958300,
+ .00000000000005148849572685810,
+ -.00000000000002532168943117445,
+ -.00000000000005213620639136504,
+ -.00000000000001819506003016881,
+ .00000000000006329065958724544,
+ .00000000000008614512936087814,
+ -.00000000000007355770219435028,
+ .00000000000009638067658552277,
+ .00000000000007598636597194141,
+ .00000000000002579999128306990,
+ -.00000000000004654729747598444,
+ -.00000000000007556920687451336,
+ .00000000000010195735223708472,
+ -.00000000000017319034406422306,
+ -.00000000000007718001336828098,
+ .00000000000010980754099855238,
+ -.00000000000002047235780046195,
+ -.00000000000008372091099235912,
+ .00000000000014088127937111135,
+ .00000000000012869017157588257,
+ .00000000000017788850778198106,
+ .00000000000006440856150696891,
+ .00000000000016132822667240822,
+ -.00000000000007540916511956188,
+ -.00000000000000036507188831790,
+ .00000000000009120937249914984,
+ .00000000000018567570959796010,
+ -.00000000000003149265065191483,
+ -.00000000000009309459495196889,
+ .00000000000017914338601329117,
+ -.00000000000001302979717330866,
+ .00000000000023097385217586939,
+ .00000000000023999540484211737,
+ .00000000000015393776174455408,
+ -.00000000000036870428315837678,
+ .00000000000036920375082080089,
+ -.00000000000009383417223663699,
+ .00000000000009433398189512690,
+ .00000000000041481318704258568,
+ -.00000000000003792316480209314,
+ .00000000000008403156304792424,
+ -.00000000000034262934348285429,
+ .00000000000043712191957429145,
+ -.00000000000010475750058776541,
+ -.00000000000011118671389559323,
+ .00000000000037549577257259853,
+ .00000000000013912841212197565,
+ .00000000000010775743037572640,
+ .00000000000029391859187648000,
+ -.00000000000042790509060060774,
+ .00000000000022774076114039555,
+ .00000000000010849569622967912,
+ -.00000000000023073801945705758,
+ .00000000000015761203773969435,
+ .00000000000003345710269544082,
+ -.00000000000041525158063436123,
+ .00000000000032655698896907146,
+ -.00000000000044704265010452446,
+ .00000000000034527647952039772,
+ -.00000000000007048962392109746,
+ .00000000000011776978751369214,
+ -.00000000000010774341461609578,
+ .00000000000021863343293215910,
+ .00000000000024132639491333131,
+ .00000000000039057462209830700,
+ -.00000000000026570679203560751,
+ .00000000000037135141919592021,
+ -.00000000000017166921336082431,
+ -.00000000000028658285157914353,
+ -.00000000000023812542263446809,
+ .00000000000006576659768580062,
+ -.00000000000028210143846181267,
+ .00000000000010701931762114254,
+ .00000000000018119346366441110,
+ .00000000000009840465278232627,
+ -.00000000000033149150282752542,
+ -.00000000000018302857356041668,
+ -.00000000000016207400156744949,
+ .00000000000048303314949553201,
+ -.00000000000071560553172382115,
+ .00000000000088821239518571855,
+ -.00000000000030900580513238244,
+ -.00000000000061076551972851496,
+ .00000000000035659969663347830,
+ .00000000000035782396591276383,
+ -.00000000000046226087001544578,
+ .00000000000062279762917225156,
+ .00000000000072838947272065741,
+ .00000000000026809646615211673,
+ -.00000000000010960825046059278,
+ .00000000000002311949383800537,
+ -.00000000000058469058005299247,
+ -.00000000000002103748251144494,
+ -.00000000000023323182945587408,
+ -.00000000000042333694288141916,
+ -.00000000000043933937969737844,
+ .00000000000041341647073835565,
+ .00000000000006841763641591466,
+ .00000000000047585534004430641,
+ .00000000000083679678674757695,
+ -.00000000000085763734646658640,
+ .00000000000021913281229340092,
+ -.00000000000062242842536431148,
+ -.00000000000010983594325438430,
+ .00000000000065310431377633651,
+ -.00000000000047580199021710769,
+ -.00000000000037854251265457040,
+ .00000000000040939233218678664,
+ .00000000000087424383914858291,
+ .00000000000025218188456842882,
+ -.00000000000003608131360422557,
+ -.00000000000050518555924280902,
+ .00000000000078699403323355317,
+ -.00000000000067020876961949060,
+ .00000000000016108575753932458,
+ .00000000000058527188436251509,
+ -.00000000000035246757297904791,
+ -.00000000000018372084495629058,
+ .00000000000088606689813494916,
+ .00000000000066486268071468700,
+ .00000000000063831615170646519,
+ .00000000000025144230728376072,
+ -.00000000000017239444525614834
+};
+
+#if !_lib_log
+
+extern double
+#ifdef _ANSI_SOURCE
+log(double x)
+#else
+log(x) double x;
+#endif
+{
+ int m, j;
+ double F, f, g, q, u, u2, v, zero = 0.0, one = 1.0;
+ volatile double u1;
+
+ /* Catch special cases */
+ if (x <= 0)
+ if (_IEEE && x == zero) /* log(0) = -Inf */
+ return (-one/zero);
+ else if (_IEEE) /* log(neg) = NaN */
+ return (zero/zero);
+ else if (x == zero) /* NOT REACHED IF _IEEE */
+ return (infnan(-ERANGE));
+ else
+ return (infnan(EDOM));
+ else if (!finite(x))
+ if (_IEEE) /* x = NaN, Inf */
+ return (x+x);
+ else
+ return (infnan(ERANGE));
+
+ /* Argument reduction: 1 <= g < 2; x/2^m = g; */
+ /* y = F*(1 + f/F) for |f| <= 2^-8 */
+
+ m = logb(x);
+ g = ldexp(x, -m);
+ if (_IEEE && m == -1022) {
+ j = logb(g), m += j;
+ g = ldexp(g, -j);
+ }
+ j = N*(g-1) + .5;
+ F = (1.0/N) * j + 1; /* F*128 is an integer in [128, 512] */
+ f = g - F;
+
+ /* Approximate expansion for log(1+f/F) ~= u + q */
+ g = 1/(2*F+f);
+ u = 2*f*g;
+ v = u*u;
+ q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
+
+ /* case 1: u1 = u rounded to 2^-43 absolute. Since u < 2^-8,
+ * u1 has at most 35 bits, and F*u1 is exact, as F has < 8 bits.
+ * It also adds exactly to |m*log2_hi + log_F_head[j] | < 750
+ */
+ if (m | j)
+ u1 = u + 513, u1 -= 513;
+
+ /* case 2: |1-x| < 1/256. The m- and j- dependent terms are zero;
+ * u1 = u to 24 bits.
+ */
+ else
+ u1 = u, TRUNC(u1);
+ u2 = (2.0*(f - F*u1) - u1*f) * g;
+ /* u1 + u2 = 2f/(2F+f) to extra precision. */
+
+ /* log(x) = log(2^m*F*(1+f/F)) = */
+ /* (m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q); */
+ /* (exact) + (tiny) */
+
+ u1 += m*logF_head[N] + logF_head[j]; /* exact */
+ u2 = (u2 + logF_tail[j]) + q; /* tiny */
+ u2 += logF_tail[N]*m;
+ return (u1 + u2);
+}
+
+#endif
+
+/*
+ * Extra precision variant, returning struct {double a, b;};
+ * log(x) = a+b to 63 bits, with a is rounded to 26 bits.
+ */
+struct Double
+#ifdef _ANSI_SOURCE
+__log__D(double x)
+#else
+__log__D(x) double x;
+#endif
+{
+ int m, j;
+ double F, f, g, q, u, v, u2, one = 1.0;
+ volatile double u1;
+ struct Double r;
+
+ /* Argument reduction: 1 <= g < 2; x/2^m = g; */
+ /* y = F*(1 + f/F) for |f| <= 2^-8 */
+
+ m = (int)logb(x);
+ g = ldexp(x, -m);
+ if (_IEEE && m == -1022) {
+ j = (int)logb(g), m += j;
+ g = ldexp(g, -j);
+ }
+ j = (int)(N*(g-1) + .5);
+ F = (1.0/N) * j + 1;
+ f = g - F;
+
+ g = 1/(2*F+f);
+ u = 2*f*g;
+ v = u*u;
+ q = u*v*(A1 + v*(A2 + v*(A3 + v*A4)));
+ if (m | j)
+ u1 = u + 513, u1 -= 513;
+ else
+ u1 = u, TRUNC(u1);
+ u2 = (2.0*(f - F*u1) - u1*f) * g;
+
+ u1 += m*logF_head[N] + logF_head[j];
+
+ u2 += logF_tail[j]; u2 += q;
+ u2 += logF_tail[N]*m;
+ r.a = u1 + u2; /* Only difference is here */
+ TRUNC(r.a);
+ r.b = (u1 - r.a) + u2;
+ return (r);
+}
+
+#endif
diff --git a/src/lib/libast/uwin/log1p.c b/src/lib/libast/uwin/log1p.c
new file mode 100644
index 0000000..1fad21f
--- /dev/null
+++ b/src/lib/libast/uwin/log1p.c
@@ -0,0 +1,176 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_log1p
+
+void _STUB_log1p(){}
+
+#else
+
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)log1p.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/* LOG1P(x)
+ * RETURN THE LOGARITHM OF 1+x
+ * DOUBLE PRECISION (VAX D FORMAT 56 bits, IEEE DOUBLE 53 BITS)
+ * CODED IN C BY K.C. NG, 1/19/85;
+ * REVISED BY K.C. NG on 2/6/85, 3/7/85, 3/24/85, 4/16/85.
+ *
+ * Required system supported functions:
+ * scalb(x,n)
+ * copysign(x,y)
+ * logb(x)
+ * finite(x)
+ *
+ * Required kernel function:
+ * log__L(z)
+ *
+ * Method :
+ * 1. Argument Reduction: find k and f such that
+ * 1+x = 2^k * (1+f),
+ * where sqrt(2)/2 < 1+f < sqrt(2) .
+ *
+ * 2. Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
+ * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ * log(1+f) is computed by
+ *
+ * log(1+f) = 2s + s*log__L(s*s)
+ * where
+ * log__L(z) = z*(L1 + z*(L2 + z*(... (L6 + z*L7)...)))
+ *
+ * See log__L() for the values of the coefficients.
+ *
+ * 3. Finally, log(1+x) = k*ln2 + log(1+f).
+ *
+ * Remarks 1. In step 3 n*ln2 will be stored in two floating point numbers
+ * n*ln2hi + n*ln2lo, where ln2hi is chosen such that the last
+ * 20 bits (for VAX D format), or the last 21 bits ( for IEEE
+ * double) is 0. This ensures n*ln2hi is exactly representable.
+ * 2. In step 1, f may not be representable. A correction term c
+ * for f is computed. It follows that the correction term for
+ * f - t (the leading term of log(1+f) in step 2) is c-c*x. We
+ * add this correction term to n*ln2lo to attenuate the error.
+ *
+ *
+ * Special cases:
+ * log1p(x) is NaN with signal if x < -1; log1p(NaN) is NaN with no signal;
+ * log1p(INF) is +INF; log1p(-1) is -INF with signal;
+ * only log1p(0)=0 is exact for finite argument.
+ *
+ * Accuracy:
+ * log1p(x) returns the exact log(1+x) nearly rounded. In a test run
+ * with 1,536,000 random arguments on a VAX, the maximum observed
+ * error was .846 ulps (units in the last place).
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following constants.
+ * The decimal values may be used, provided that the compiler will convert
+ * from decimal to binary accurately enough to produce the hexadecimal values
+ * shown.
+ */
+
+#include <errno.h>
+#include "mathimpl.h"
+
+vc(ln2hi, 6.9314718055829871446E-1 ,7217,4031,0000,f7d0, 0, .B17217F7D00000)
+vc(ln2lo, 1.6465949582897081279E-12 ,bcd5,2ce7,d9cc,e4f1, -39, .E7BCD5E4F1D9CC)
+vc(sqrt2, 1.4142135623730950622E0 ,04f3,40b5,de65,33f9, 1, .B504F333F9DE65)
+
+ic(ln2hi, 6.9314718036912381649E-1, -1, 1.62E42FEE00000)
+ic(ln2lo, 1.9082149292705877000E-10, -33, 1.A39EF35793C76)
+ic(sqrt2, 1.4142135623730951455E0, 0, 1.6A09E667F3BCD)
+
+#ifdef vccast
+#define ln2hi vccast(ln2hi)
+#define ln2lo vccast(ln2lo)
+#define sqrt2 vccast(sqrt2)
+#endif
+
+extern double log1p(x)
+double x;
+{
+ const static double zero=0.0, negone= -1.0, one=1.0,
+ half=1.0/2.0, small=1.0E-20; /* 1+small == 1 */
+ double z,s,t,c;
+ int k;
+
+#if !defined(vax)&&!defined(tahoe)
+ if(x!=x) return(x); /* x is NaN */
+#endif /* !defined(vax)&&!defined(tahoe) */
+
+ if(finite(x)) {
+ if( x > negone ) {
+
+ /* argument reduction */
+ if(copysign(x,one)<small) return(x);
+ k=(int)logb(one+x); z=scalb(x,-k); t=scalb(one,-k);
+ if(z+t >= sqrt2 )
+ { k += 1 ; z *= half; t *= half; }
+ t += negone; x = z + t;
+ c = (t-x)+z ; /* correction term for x */
+
+ /* compute log(1+x) */
+ s = x/(2+x); t = x*x*half;
+ c += (k*ln2lo-c*x);
+ z = c+s*(t+__log__L(s*s));
+ x += (z - t) ;
+
+ return(k*ln2hi+x);
+ }
+ /* end of if (x > negone) */
+
+ else {
+#if defined(vax)||defined(tahoe)
+ if ( x == negone )
+ return (infnan(-ERANGE)); /* -INF */
+ else
+ return (infnan(EDOM)); /* NaN */
+#else /* defined(vax)||defined(tahoe) */
+ /* x = -1, return -INF with signal */
+ if ( x == negone ) return( negone/zero );
+
+ /* negative argument for log, return NaN with signal */
+ else return ( zero / zero );
+#endif /* defined(vax)||defined(tahoe) */
+ }
+ }
+ /* end of if (finite(x)) */
+
+ /* log(-INF) is NaN */
+ else if(x<0)
+ return(zero/zero);
+
+ /* log(+INF) is INF */
+ else return(x);
+}
+
+#endif
diff --git a/src/lib/libast/uwin/log__L.c b/src/lib/libast/uwin/log__L.c
new file mode 100644
index 0000000..3276e69
--- /dev/null
+++ b/src/lib/libast/uwin/log__L.c
@@ -0,0 +1,116 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN
+
+void _STUB_log__L(){}
+
+#else
+
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)log__L.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/* log__L(Z)
+ * LOG(1+X) - 2S X
+ * RETURN --------------- WHERE Z = S*S, S = ------- , 0 <= Z <= .0294...
+ * S 2 + X
+ *
+ * DOUBLE PRECISION (VAX D FORMAT 56 bits or IEEE DOUBLE 53 BITS)
+ * KERNEL FUNCTION FOR LOG; TO BE USED IN LOG1P, LOG, AND POW FUNCTIONS
+ * CODED IN C BY K.C. NG, 1/19/85;
+ * REVISED BY K.C. Ng, 2/3/85, 4/16/85.
+ *
+ * Method :
+ * 1. Polynomial approximation: let s = x/(2+x).
+ * Based on log(1+x) = log(1+s) - log(1-s)
+ * = 2s + 2/3 s**3 + 2/5 s**5 + .....,
+ *
+ * (log(1+x) - 2s)/s is computed by
+ *
+ * z*(L1 + z*(L2 + z*(... (L7 + z*L8)...)))
+ *
+ * where z=s*s. (See the listing below for Lk's values.) The
+ * coefficients are obtained by a special Remez algorithm.
+ *
+ * Accuracy:
+ * Assuming no rounding error, the maximum magnitude of the approximation
+ * error (absolute) is 2**(-58.49) for IEEE double, and 2**(-63.63)
+ * for VAX D format.
+ *
+ * Constants:
+ * The hexadecimal values are the intended ones for the following constants.
+ * The decimal values may be used, provided that the compiler will convert
+ * from decimal to binary accurately enough to produce the hexadecimal values
+ * shown.
+ */
+
+#include "mathimpl.h"
+
+vc(L1, 6.6666666666666703212E-1 ,aaaa,402a,aac5,aaaa, 0, .AAAAAAAAAAAAC5)
+vc(L2, 3.9999999999970461961E-1 ,cccc,3fcc,2684,cccc, -1, .CCCCCCCCCC2684)
+vc(L3, 2.8571428579395698188E-1 ,4924,3f92,5782,92f8, -1, .92492492F85782)
+vc(L4, 2.2222221233634724402E-1 ,8e38,3f63,af2c,39b7, -2, .E38E3839B7AF2C)
+vc(L5, 1.8181879517064680057E-1 ,2eb4,3f3a,655e,cc39, -2, .BA2EB4CC39655E)
+vc(L6, 1.5382888777946145467E-1 ,8551,3f1d,781d,e8c5, -2, .9D8551E8C5781D)
+vc(L7, 1.3338356561139403517E-1 ,95b3,3f08,cd92,907f, -2, .8895B3907FCD92)
+vc(L8, 1.2500000000000000000E-1 ,0000,3f00,0000,0000, -2, .80000000000000)
+
+ic(L1, 6.6666666666667340202E-1, -1, 1.5555555555592)
+ic(L2, 3.9999999999416702146E-1, -2, 1.999999997FF24)
+ic(L3, 2.8571428742008753154E-1, -2, 1.24924941E07B4)
+ic(L4, 2.2222198607186277597E-1, -3, 1.C71C52150BEA6)
+ic(L5, 1.8183562745289935658E-1, -3, 1.74663CC94342F)
+ic(L6, 1.5314087275331442206E-1, -3, 1.39A1EC014045B)
+ic(L7, 1.4795612545334174692E-1, -3, 1.2F039F0085122)
+
+#ifdef vccast
+#define L1 vccast(L1)
+#define L2 vccast(L2)
+#define L3 vccast(L3)
+#define L4 vccast(L4)
+#define L5 vccast(L5)
+#define L6 vccast(L6)
+#define L7 vccast(L7)
+#define L8 vccast(L8)
+#endif
+
+double __log__L(z)
+double z;
+{
+#if defined(vax)||defined(tahoe)
+ return(z*(L1+z*(L2+z*(L3+z*(L4+z*(L5+z*(L6+z*(L7+z*L8))))))));
+#else /* defined(vax)||defined(tahoe) */
+ return(z*(L1+z*(L2+z*(L3+z*(L4+z*(L5+z*(L6+z*L7)))))));
+#endif /* defined(vax)||defined(tahoe) */
+}
+
+#endif
diff --git a/src/lib/libast/uwin/mathimpl.h b/src/lib/libast/uwin/mathimpl.h
new file mode 100644
index 0000000..12857f0
--- /dev/null
+++ b/src/lib/libast/uwin/mathimpl.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)mathimpl.h 8.1 (Berkeley) 6/4/93
+ */
+
+#include <sys/cdefs.h>
+#include <math.h>
+
+#if defined(vax)||defined(tahoe)
+
+/* Deal with different ways to concatenate in cpp */
+# ifdef __STDC__
+# define cat3(a,b,c) a ## b ## c
+# else
+# define cat3(a,b,c) a/**/b/**/c
+# endif
+
+/* Deal with vax/tahoe byte order issues */
+# ifdef vax
+# define cat3t(a,b,c) cat3(a,b,c)
+# else
+# define cat3t(a,b,c) cat3(a,c,b)
+# endif
+
+# define vccast(name) (*(const double *)(cat3(name,,x)))
+
+ /*
+ * Define a constant to high precision on a Vax or Tahoe.
+ *
+ * Args are the name to define, the decimal floating point value,
+ * four 16-bit chunks of the float value in hex
+ * (because the vax and tahoe differ in float format!), the power
+ * of 2 of the hex-float exponent, and the hex-float mantissa.
+ * Most of these arguments are not used at compile time; they are
+ * used in a post-check to make sure the constants were compiled
+ * correctly.
+ *
+ * People who want to use the constant will have to do their own
+ * #define foo vccast(foo)
+ * since CPP cannot do this for them from inside another macro (sigh).
+ * We define "vccast" if this needs doing.
+ */
+# define vc(name, value, x1,x2,x3,x4, bexp, xval) \
+ const static long cat3(name,,x)[] = {cat3t(0x,x1,x2), cat3t(0x,x3,x4)};
+
+# define ic(name, value, bexp, xval) ;
+
+#else /* vax or tahoe */
+
+ /* Hooray, we have an IEEE machine */
+# undef vccast
+# define vc(name, value, x1,x2,x3,x4, bexp, xval) ;
+
+# define ic(name, value, bexp, xval) \
+ const static double name = value;
+
+#endif /* defined(vax)||defined(tahoe) */
+
+
+/*
+ * Functions internal to the math package, yet not static.
+ */
+extern double __exp__E();
+extern double __log__L();
+
+struct Double {double a, b;};
+double __exp__D __P((double, double));
+struct Double __log__D __P((double));
+
+/*
+ * All externs exported after this point
+ */
+#if defined(_BLD_ast) && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern double copysign(double, double);
diff --git a/src/lib/libast/uwin/mini.sym b/src/lib/libast/uwin/mini.sym
new file mode 100644
index 0000000..3a75e54
--- /dev/null
+++ b/src/lib/libast/uwin/mini.sym
@@ -0,0 +1,84 @@
+_ast_init
+_sfdlen
+_sffilbuf
+_sfflsbuf
+_sfgetl
+_sfgetl2
+_sfgetu
+_sfgetu2
+_sfllen
+_sfputd
+_sfputl
+_sfputu
+_stdgets
+_stdscanf
+_stdsprintf
+_stkseek
+printf
+remove
+sfclose
+sfclrerr
+sfclrlock
+sfdisc
+sfdlen
+sfdostext
+sfeof
+sferror
+sffcvt
+sffileno
+sfgetc
+sfgetd
+sfgetl
+sfgetr
+sfgetu
+sfkeyprintf
+sfllen
+sfmove
+sfnew
+sfnotify
+sfnputc
+sfopen
+sfpkrd
+sfpoll
+sfpool
+sfpopen
+sfprintf
+sfprints
+sfpurge
+sfputc
+sfputd
+sfputl
+sfputr
+sfputu
+sfrd
+sfread
+sfreserve
+sfscanf
+sfseek
+sfset
+sfsetbuf
+sfsetfd
+sfsize
+sfsk
+sfslen
+sfslowio
+sfsprintf
+sfsscanf
+sfstack
+sfstacked
+sfswap
+sfsync
+sftell
+sftmp
+sfulen
+sfungetc
+sfvalue
+sfvprintf
+sfvscanf
+sfwr
+sfwrite
+sigflag
+sprintf
+system
+mktemp
+strdup
diff --git a/src/lib/libast/uwin/rand48.c b/src/lib/libast/uwin/rand48.c
new file mode 100644
index 0000000..184a3b7
--- /dev/null
+++ b/src/lib/libast/uwin/rand48.c
@@ -0,0 +1,177 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_srand48
+
+void _STUB_srand48(){}
+
+#else
+
+#define drand48 ______drand48
+#define erand48 ______erand48
+#define jrand48 ______jrand48
+#define lcong48 ______lcong48
+#define lrand48 ______lrand48
+#define mrand48 ______mrand48
+#define nrand48 ______nrand48
+#define seed48 ______seed48
+#define srand48 ______srand48
+
+#include <stdlib.h>
+
+#undef drand48
+#undef erand48
+#undef jrand48
+#undef lcong48
+#undef lrand48
+#undef mrand48
+#undef nrand48
+#undef seed48
+#undef srand48
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#define A 0x5DEECE66D
+#define A0 0X5
+#define A1 0xDEEC
+#define A2 0xE66D
+#define C 0xB
+#define XINIT 0x330E
+#define SCALE 3.55271e-15
+
+static unsigned short oldval[3];
+static unsigned short X[3] = { 0, 0, XINIT};
+static unsigned short a[3] = { A0, A1, A2};
+static unsigned short c = C;
+
+static void multadd(unsigned short x[3], unsigned short a[3], unsigned short c)
+{
+ register unsigned long r = c;
+ unsigned short x2 = x[2];
+ unsigned short x1 = x[1];
+ r += a[2]*x2;
+ x[2] = (unsigned short)r;
+ r >>= 16;
+ r += a[1]*x2;
+ r += a[2]*x1;
+ x[1] = (unsigned short)r;
+ r >>= 16;
+ r += a[2]*x[0];
+ r += a[1]*x1;
+ r += a[0]*x2;
+ x[0] = (unsigned short)r;
+}
+
+extern double drand48(void)
+{
+ double d;
+ unsigned long u;
+ multadd(X,a,c);
+ u = (X[0]<<16) + X[1];
+ d = (u*65536.) + X[2];
+ return(d*SCALE);
+}
+
+extern double erand48(unsigned short xsubi[3])
+{
+ double d;
+ unsigned long u;
+ multadd(xsubi,a,c);
+ u = (xsubi[0]<<16) + xsubi[1];
+ d = (u*65536.) + xsubi[2];
+ return(d*SCALE);
+}
+
+extern long jrand48(unsigned short xsubi[3])
+{
+ long u;
+ multadd(xsubi,a,c);
+ u = (xsubi[0]<<16) | xsubi[1];
+ return((long)u);
+}
+
+extern void lcong48(unsigned short param[7])
+{
+ X[0] = param[0];
+ X[1] = param[1];
+ X[2] = param[2];
+ a[0] = param[3];
+ a[1] = param[4];
+ a[2] = param[5];
+ c = param[6];
+}
+
+extern long lrand48(void)
+{
+ long l;
+ multadd(X,a,c);
+ l = (X[0]<<15)|(X[1]>>1);
+ return(l);
+}
+
+extern long mrand48(void)
+{
+ unsigned long u;
+ multadd(X,a,c);
+ u = (X[0]<<16) | X[1];
+ return((long)u);
+}
+
+extern long nrand48(unsigned short xsubi[3])
+{
+ long l;
+ multadd(xsubi,a,c);
+ l = (xsubi[0]<<15)|(xsubi[1]>>1);
+ return(l);
+}
+
+extern unsigned short *seed48(unsigned short seed[3])
+{
+ unsigned short *sp = (unsigned short*)&X;
+ a[0] = A0;
+ a[1] = A1;
+ a[2] = A2;
+ c = C;
+ oldval[0] = X[2];
+ oldval[1] = X[1];
+ oldval[2] = X[0];
+ X[0] = seed[2];
+ X[1] = seed[1];
+ X[2] = seed[0];
+ return(oldval);
+}
+
+extern void srand48(long seedval)
+{
+ a[0] = A0;
+ a[1] = A1;
+ a[2] = A2;
+ c = C;
+ X[0] = (unsigned short)(((unsigned long)seedval) >> 16);
+ X[1] = (unsigned short)seedval;
+ X[2] = XINIT;
+}
+
+#endif
diff --git a/src/lib/libast/uwin/random.c b/src/lib/libast/uwin/random.c
new file mode 100644
index 0000000..6b46d63
--- /dev/null
+++ b/src/lib/libast/uwin/random.c
@@ -0,0 +1,381 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_random
+
+void _STUB_random(){}
+
+#else
+
+/*
+ * Copyright (c) 1983
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This is derived from the Berkeley source:
+ * @(#)random.c 5.5 (Berkeley) 7/6/88
+ * It was reworked for the GNU C Library by Roland McGrath.
+ */
+
+#define initstate ______initstate
+#define random ______random
+#define setstate ______setstate
+#define srandom ______srandom
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#undef initstate
+#undef random
+#undef setstate
+#undef srandom
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern long int random();
+
+#define PTR char*
+
+/* An improved random number generation package. In addition to the standard
+ rand()/srand() like interface, this package also has a special state info
+ interface. The initstate() routine is called with a seed, an array of
+ bytes, and a count of how many bytes are being passed in; this array is
+ then initialized to contain information for random number generation with
+ that much state information. Good sizes for the amount of state
+ information are 32, 64, 128, and 256 bytes. The state can be switched by
+ calling the setstate() function with the same array as was initiallized
+ with initstate(). By default, the package runs with 128 bytes of state
+ information and generates far better random numbers than a linear
+ congruential generator. If the amount of state information is less than
+ 32 bytes, a simple linear congruential R.N.G. is used. Internally, the
+ state information is treated as an array of longs; the zeroeth element of
+ the array is the type of R.N.G. being used (small integer); the remainder
+ of the array is the state information for the R.N.G. Thus, 32 bytes of
+ state information will give 7 longs worth of state information, which will
+ allow a degree seven polynomial. (Note: The zeroeth word of state
+ information also has some other information stored in it; see setstate
+ for details). The random number generation technique is a linear feedback
+ shift register approach, employing trinomials (since there are fewer terms
+ to sum up that way). In this approach, the least significant bit of all
+ the numbers in the state table will act as a linear feedback shift register,
+ and will have period 2^deg - 1 (where deg is the degree of the polynomial
+ being used, assuming that the polynomial is irreducible and primitive).
+ The higher order bits will have longer periods, since their values are
+ also influenced by pseudo-random carries out of the lower bits. The
+ total period of the generator is approximately deg*(2**deg - 1); thus
+ doubling the amount of state information has a vast influence on the
+ period of the generator. Note: The deg*(2**deg - 1) is an approximation
+ only good for large deg, when the period of the shift register is the
+ dominant factor. With deg equal to seven, the period is actually much
+ longer than the 7*(2**7 - 1) predicted by this formula. */
+
+
+
+/* For each of the currently supported random number generators, we have a
+ break value on the amount of state information (you need at least thi
+ bytes of state info to support this random number generator), a degree for
+ the polynomial (actually a trinomial) that the R.N.G. is based on, and
+ separation between the two lower order coefficients of the trinomial. */
+
+/* Linear congruential. */
+#define TYPE_0 0
+#define BREAK_0 8
+#define DEG_0 0
+#define SEP_0 0
+
+/* x**7 + x**3 + 1. */
+#define TYPE_1 1
+#define BREAK_1 32
+#define DEG_1 7
+#define SEP_1 3
+
+/* x**15 + x + 1. */
+#define TYPE_2 2
+#define BREAK_2 64
+#define DEG_2 15
+#define SEP_2 1
+
+/* x**31 + x**3 + 1. */
+#define TYPE_3 3
+#define BREAK_3 128
+#define DEG_3 31
+#define SEP_3 3
+
+/* x**63 + x + 1. */
+#define TYPE_4 4
+#define BREAK_4 256
+#define DEG_4 63
+#define SEP_4 1
+
+
+/* Array versions of the above information to make code run faster.
+ Relies on fact that TYPE_i == i. */
+
+#define MAX_TYPES 5 /* Max number of types above. */
+
+static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static int seps[MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
+
+
+
+/* Initially, everything is set up as if from:
+ initstate(1, randtbl, 128);
+ Note that this initialization takes advantage of the fact that srandom
+ advances the front and rear pointers 10*rand_deg times, and hence the
+ rear pointer which starts at 0 will also end up at zero; thus the zeroeth
+ element of the state information, which contains info about the current
+ position of the rear pointer is just
+ (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */
+
+static long int randtbl[DEG_3 + 1] =
+ {
+ TYPE_3,
+ -851904987, -43806228, -2029755270, 1390239686, -1912102820,
+ -485608943, 1969813258, -1590463333, -1944053249, 455935928, 508023712,
+ -1714531963, 1800685987, -2015299881, 654595283, -1149023258,
+ -1470005550, -1143256056, -1325577603, -1568001885, 1275120390,
+ -607508183, -205999574, -1696891592, 1492211999, -1528267240,
+ -952028296, -189082757, 362343714, 1424981831, 2039449641,
+ };
+
+/* FPTR and RPTR are two pointers into the state info, a front and a rear
+ pointer. These two pointers are always rand_sep places aparts, as they
+ cycle through the state information. (Yes, this does mean we could get
+ away with just one pointer, but the code for random is more efficient
+ this way). The pointers are left positioned as they would be from the call:
+ initstate(1, randtbl, 128);
+ (The position of the rear pointer, rptr, is really 0 (as explained above
+ in the initialization of randtbl) because the state table pointer is set
+ to point to randtbl[1] (as explained below).) */
+
+static long int *fptr = &randtbl[SEP_3 + 1];
+static long int *rptr = &randtbl[1];
+
+
+
+/* The following things are the pointer to the state information table,
+ the type of the current generator, the degree of the current polynomial
+ being used, and the separation between the two pointers.
+ Note that for efficiency of random, we remember the first location of
+ the state information, not the zeroeth. Hence it is valid to access
+ state[-1], which is used to store the type of the R.N.G.
+ Also, we remember the last location, since this is more efficient than
+ indexing every time to find the address of the last element to see if
+ the front and rear pointers have wrapped. */
+
+static long int *state = &randtbl[1];
+
+static int rand_type = TYPE_3;
+static int rand_deg = DEG_3;
+static int rand_sep = SEP_3;
+
+static long int *end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])];
+
+/* Initialize the random number generator based on the given seed. If the
+ type is the trivial no-state-information type, just remember the seed.
+ Otherwise, initializes state[] based on the given "seed" via a linear
+ congruential generator. Then, the pointers are set to known locations
+ that are exactly rand_sep places apart. Lastly, it cycles the state
+ information a given number of times to get rid of any initial dependencies
+ introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
+ for default usage relies on values produced by this routine. */
+extern void srandom(unsigned int x)
+{
+ state[0] = x;
+ if (rand_type != TYPE_0)
+ {
+ register long int i;
+ for (i = 1; i < rand_deg; ++i)
+ state[i] = (1103515145 * state[i - 1]) + 12345;
+ fptr = &state[rand_sep];
+ rptr = &state[0];
+ for (i = 0; i < 10 * rand_deg; ++i)
+ (void) random();
+ }
+}
+
+/* Initialize the state information in the given array of N bytes for
+ future random number generation. Based on the number of bytes we
+ are given, and the break values for the different R.N.G.'s, we choose
+ the best (largest) one we can and set things up for it. srandom is
+ then called to initialize the state information. Note that on return
+ from srandom, we set state[-1] to be the type multiplexed with the current
+ value of the rear pointer; this is so successive calls to initstate won't
+ lose this information and will be able to restart with setstate.
+ Note: The first thing we do is save the current state, if any, just like
+ setstate so that it doesn't matter when initstate is called.
+ Returns a pointer to the old state. */
+extern char* initstate(unsigned int seed, char* arg_state, size_t n)
+{
+ PTR ostate = (PTR) &state[-1];
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
+ if (n < BREAK_1)
+ {
+ if (n < BREAK_0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ rand_type = TYPE_0;
+ rand_deg = DEG_0;
+ rand_sep = SEP_0;
+ }
+ else if (n < BREAK_2)
+ {
+ rand_type = TYPE_1;
+ rand_deg = DEG_1;
+ rand_sep = SEP_1;
+ }
+ else if (n < BREAK_3)
+ {
+ rand_type = TYPE_2;
+ rand_deg = DEG_2;
+ rand_sep = SEP_2;
+ }
+ else if (n < BREAK_4)
+ {
+ rand_type = TYPE_3;
+ rand_deg = DEG_3;
+ rand_sep = SEP_3;
+ }
+ else
+ {
+ rand_type = TYPE_4;
+ rand_deg = DEG_4;
+ rand_sep = SEP_4;
+ }
+
+ state = &((long int *) arg_state)[1]; /* First location. */
+ /* Must set END_PTR before srandom. */
+ end_ptr = &state[rand_deg];
+ srandom(seed);
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
+
+ return ostate;
+}
+
+/* Restore the state from the given state array.
+ Note: It is important that we also remember the locations of the pointers
+ in the current state information, and restore the locations of the pointers
+ from the old state information. This is done by multiplexing the pointer
+ location into the zeroeth word of the state information. Note that due
+ to the order in which things are done, it is OK to call setstate with the
+ same state as the current state
+ Returns a pointer to the old state information. */
+extern char *setstate(const char *arg_state)
+{
+ register long int *new_state = (long int *) arg_state;
+ register int type = new_state[0] % MAX_TYPES;
+ register int rear = new_state[0] / MAX_TYPES;
+ PTR ostate = (PTR) &state[-1];
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
+
+ switch (type)
+ {
+ case TYPE_0:
+ case TYPE_1:
+ case TYPE_2:
+ case TYPE_3:
+ case TYPE_4:
+ rand_type = type;
+ rand_deg = degrees[type];
+ rand_sep = seps[type];
+ break;
+ default:
+ /* State info munged. */
+ errno = EINVAL;
+ return NULL;
+ }
+
+ state = &new_state[1];
+ if (rand_type != TYPE_0)
+ {
+ rptr = &state[rear];
+ fptr = &state[(rear + rand_sep) % rand_deg];
+ }
+ /* Set end_ptr too. */
+ end_ptr = &state[rand_deg];
+
+ return ostate;
+}
+
+/* If we are using the trivial TYPE_0 R.N.G., just do the old linear
+ congruential bit. Otherwise, we do our fancy trinomial stuff, which is the
+ same in all ther other cases due to all the global variables that have been
+ set up. The basic operation is to add the number at the rear pointer into
+ the one at the front pointer. Then both pointers are advanced to the next
+ location cyclically in the table. The value returned is the sum generated,
+ reduced to 31 bits by throwing away the "least random" low bit.
+ Note: The code takes advantage of the fact that both the front and
+ rear pointers can't wrap on the same call by not testing the rear
+ pointer if the front one has wrapped. Returns a 31-bit random number. */
+
+extern long int random()
+{
+ if (rand_type == TYPE_0)
+ {
+ state[0] = ((state[0] * 1103515245) + 12345) & LONG_MAX;
+ return state[0];
+ }
+ else
+ {
+ long int i;
+ *fptr += *rptr;
+ /* Chucking least random bit. */
+ i = (*fptr >> 1) & LONG_MAX;
+ ++fptr;
+ if (fptr >= end_ptr)
+ {
+ fptr = state;
+ ++rptr;
+ }
+ else
+ {
+ ++rptr;
+ if (rptr >= end_ptr)
+ rptr = state;
+ }
+ return i;
+ }
+}
+
+#endif
diff --git a/src/lib/libast/uwin/rcmd.c b/src/lib/libast/uwin/rcmd.c
new file mode 100644
index 0000000..af29684
--- /dev/null
+++ b/src/lib/libast/uwin/rcmd.c
@@ -0,0 +1,571 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_rcmd
+
+void _STUB_rcmd(){}
+
+#else
+
+/*
+ * Copyright (c) 1983
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rcmd.c 5.17 (Berkeley) 6/27/88";
+#endif /* LIBC_SCCS and not lint */
+
+#include "rlib.h"
+#include <pwd.h>
+#include <sys/file.h>
+#include <sys/signal.h>
+#if 1
+#define _PATH_HEQUIV "/etc/hosts.equiv"
+#endif
+#include <sys/stat.h>
+
+#if NLS
+#include "nl_types.h"
+#endif
+
+#ifdef YP
+#include <rpcsvc/ypclnt.h>
+extern void setnetgrent(const char *);
+extern void endnetgrent(void);
+extern int getnetgrent(char **, char **, char **);
+static char *nisdomain = NULL;
+static int _checknetgrouphost(const char *, const char *, int);
+static int _checknetgroupuser(const char *, const char *);
+#endif
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+extern int rresvport(int *alport)
+{
+ struct sockaddr_in sin;
+ int s;
+
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = INADDR_ANY;
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0)
+ return (-1);
+ for (;;) {
+ sin.sin_port = htons((u_short)*alport);
+ if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
+ return (s);
+ if (errno != EADDRINUSE) {
+ (void) close(s);
+ return (-1);
+ }
+ (*alport)--;
+ if (*alport == IPPORT_RESERVED/2) {
+ (void) close(s);
+ errno = EAGAIN; /* close */
+ return (-1);
+ }
+ }
+}
+
+extern int rcmd(char **ahost, unsigned short rport, const char *locuser, const char *remuser, const char *cmd, int *fd2p)
+{
+ int s, timo = 1;
+#ifdef F_SETOWN
+ pid_t pid;
+#endif
+#ifdef _POSIX_SOURCE
+ sigset_t set, oset;
+#else
+ long oldmask;
+#endif
+ struct sockaddr_in sin, from;
+ char c;
+ int lport = IPPORT_RESERVED - 1;
+ struct hostent *hp;
+
+#if NLS
+ libc_nls_init();
+#endif
+
+#ifdef F_SETOWN
+ pid = getpid();
+#endif
+ hp = gethostbyname(*ahost);
+ if (hp == 0) {
+#if NLS
+ fprintf(stderr, "%s: %s\n", *ahost,
+ catgets(_libc_cat, HerrorListSet,
+ 2, "unknown host"));
+#else
+ fprintf(stderr, "%s: unknown host\n", *ahost);
+#endif
+ return (-1);
+ }
+ *ahost = hp->h_name;
+#ifdef SIGURG
+#ifdef _POSIX_SOURCE
+ sigemptyset (&set);
+ sigaddset (&set, SIGURG);
+ sigprocmask (SIG_BLOCK, &set, &oset);
+#else
+ oldmask = sigblock(sigmask(SIGURG));
+#endif
+#endif
+ for (;;) {
+ s = rresvport(&lport);
+ if (s < 0) {
+ if (errno == EAGAIN)
+#if NLS
+ fprintf(stderr, "socket: %s\n",
+ catgets(_libc_cat, NetMiscSet,
+ NetMiscAllPortsInUse,
+ "All ports in use"));
+#else
+ fprintf(stderr, "socket: All ports in use\n");
+#endif
+ else
+#if NLS
+ perror(catgets(_libc_cat, NetMiscSet,
+ NetMiscRcmdSocket,
+ "rcmd: socket"));
+#else
+perror("rcmd: socket");
+#endif
+#ifdef SIGURG
+#ifdef _POSIX_SOURCE
+sigprocmask (SIG_SETMASK, &oset,
+(sigset_t *)NULL);
+#else
+sigsetmask(oldmask);
+#endif
+#endif
+return (-1);
+ }
+#ifdef F_SETOWN
+ fcntl(s, F_SETOWN, pid);
+#endif
+ sin.sin_family = hp->h_addrtype;
+ bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length);
+ sin.sin_port = rport;
+ if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
+ break;
+ (void) close(s);
+ if (errno == EADDRINUSE) {
+ lport--;
+ continue;
+ }
+ if (errno == ECONNREFUSED && timo <= 16) {
+ sleep(timo);
+ timo *= 2;
+ continue;
+ }
+ if (hp->h_addr_list[1] != NULL) {
+ int oerrno = errno;
+
+ fprintf(stderr,
+#if NLS
+ "%s %s: ", catgets(_libc_cat, NetMiscSet,
+ NetMiscAllPortsInUse,
+ "connect to address"),
+ inet_ntoa(sin.sin_addr));
+
+#else
+
+ "connect to address %s: ", inet_ntoa(sin.sin_addr));
+#endif
+ errno = oerrno;
+ perror(0);
+ hp->h_addr_list++;
+ bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
+ hp->h_length);
+
+#if NLS
+ fprintf(stderr, catgets(_libc_cat, NetMiscSet,
+ NetMiscTrying,
+ "Trying %s...\n"),
+#else
+ fprintf(stderr, "Trying %s...\n",
+#endif
+ inet_ntoa(sin.sin_addr));
+ continue;
+ }
+ perror(hp->h_name);
+#ifdef SIGURG
+#ifdef _POSIX_SOURCE
+ sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+#else
+ sigsetmask(oldmask);
+#endif
+#endif
+ return (-1);
+ }
+ lport--;
+ if (fd2p == 0) {
+ write(s, "", 1);
+ lport = 0;
+ } else {
+ char num[8];
+ int s2 = rresvport(&lport), s3;
+ int len = sizeof (from);
+
+ if (s2 < 0)
+ goto bad;
+ listen(s2, 1);
+ (void) snprintf(num, sizeof(num), "%d", lport);
+ if (write(s, num, strlen(num)+1) != strlen(num)+1) {
+#if NLS
+ perror(catgets(_libc_cat, NetMiscSet,
+ NetMiscSettingUpStderr,
+ "write: setting up stderr"));
+#else
+ perror("write: setting up stderr");
+#endif
+ (void) close(s2);
+ goto bad;
+ }
+ s3 = accept(s2, (struct sockaddr *)&from, &len);
+ (void) close(s2);
+ if (s3 < 0) {
+#if NLS
+ perror(catgets(_libc_cat, NetMiscSet,
+ NetMiscAccept,
+ "accept"));
+#else
+ perror("accept");
+#endif
+ lport = 0;
+ goto bad;
+ }
+ *fd2p = s3;
+ from.sin_port = ntohs((u_short)from.sin_port);
+ if (from.sin_family != AF_INET ||
+ from.sin_port >= IPPORT_RESERVED) {
+ fprintf(stderr,
+#if NLS
+ "%s\n",
+ catgets(_libc_cat, NetMiscSet,
+ NetMiscProtocolFailure,
+ "socket: protocol failure in circuit setup."));
+#else
+ "socket: protocol failure in circuit setup.\n");
+#endif
+ goto bad2;
+ }
+ }
+ (void) write(s, locuser, strlen(locuser)+1);
+ (void) write(s, remuser, strlen(remuser)+1);
+ (void) write(s, cmd, strlen(cmd)+1);
+ if (read(s, &c, 1) != 1) {
+ perror(*ahost);
+ goto bad2;
+ }
+ if (c != 0) {
+ while (read(s, &c, 1) == 1) {
+ (void) write(2, &c, 1);
+ if (c == '\n')
+ break;
+ }
+ goto bad2;
+ }
+#ifdef SIGURG
+#ifdef _POSIX_SOURCE
+ sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+#else
+ sigsetmask(oldmask);
+#endif
+#endif
+ return (s);
+bad2:
+ if (lport)
+ (void) close(*fd2p);
+bad:
+ (void) close(s);
+#ifdef SIGURG
+#ifdef _POSIX_SOURCE
+ sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+#else
+ sigsetmask(oldmask);
+#endif
+#endif
+ return (-1);
+}
+
+extern int ruserok(const char *rhost, int superuser, const char *ruser, const char *luser)
+{
+ FILE *hostf;
+ char fhost[MAXHOSTNAMELEN];
+ int first = 1;
+ register const char *sp;
+ register char *p;
+ int baselen = -1;
+ uid_t saveuid;
+
+ saveuid = geteuid();
+ sp = rhost;
+ p = fhost;
+ while (*sp) {
+ if (*sp == '.') {
+ if (baselen == -1)
+ baselen = sp - rhost;
+ *p++ = *sp++;
+ } else {
+ *p++ = isupper(*sp) ? tolower(*sp++) : *sp++;
+ }
+ }
+ *p = '\0';
+ hostf = superuser ? (FILE *)0 : fopen(_PATH_HEQUIV, "r");
+again:
+ if (hostf) {
+ if (!_validuser(hostf, fhost, luser, ruser, baselen)) {
+ (void) fclose(hostf);
+ seteuid(saveuid);
+ return(0);
+ }
+ (void) fclose(hostf);
+ }
+ if (first == 1) {
+ struct stat sbuf;
+ struct passwd *pwd;
+ char pbuf[MAXPATHLEN];
+
+ first = 0;
+ if ((pwd = getpwnam(luser)) == NULL)
+ return(-1);
+ (void)strcpy(pbuf, pwd->pw_dir);
+ (void)strcat(pbuf, "/.rhosts");
+ (void)seteuid(pwd->pw_uid);
+ if ((hostf = fopen(pbuf, "r")) == NULL) {
+ seteuid(saveuid);
+ return(-1);
+ }
+ (void)fstat(fileno(hostf), &sbuf);
+ if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) {
+ fclose(hostf);
+ seteuid(saveuid);
+ return(-1);
+ }
+ goto again;
+ }
+ seteuid(saveuid);
+ return (-1);
+}
+
+int
+_validuser(FILE *hostf, const char *rhost, const char *luser,
+const char *ruser, int baselen)
+{
+ char *user;
+ char ahost[MAXHOSTNAMELEN];
+ register char *p;
+ int hostvalid = 0;
+ int uservalid = 0;
+
+ while (fgets(ahost, sizeof (ahost), hostf)) {
+ /* We need to get rid of all comments. */
+ p = strchr (ahost, '#');
+ if (p) *p = '\0';
+ p = ahost;
+ while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
+ *p = isupper(*p) ? tolower(*p) : *p;
+ p++;
+ }
+ if (*p == ' ' || *p == '\t') {
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ user = p;
+ while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
+ p++;
+ } else
+ user = p;
+ *p = '\0';
+ /* Adding new authentication -Nilendu */
+
+ /* enable all host for + entry */
+ if ('+' == ahost[0] && '\0' == ahost[1] )
+ hostvalid = 1;
+
+ /* enable all user for + entry */
+ if ('+' == user[0] && '\0' == user[1] )
+ uservalid = 1;
+
+ /* disable all host for - entry */
+ if ('-' == ahost[0] && '\0' == ahost[1] )
+ hostvalid = 0;
+
+ /* disable all user for - entry */
+ if ('-' == user[0] && '\0' == user[1] )
+ uservalid = 0;
+
+
+#ifdef YP
+ /* disable host from -hostname entry */
+ if ('-' == ahost[0] && '@' != ahost[1]
+ && _checkhost(rhost, &ahost[1], baselen))
+ return -1;
+ /* disable host from -@netgroup entry for host */
+ if ('-' == ahost[0] && '@' == ahost[1] && '\0' != ahost[2]
+ && _checknetgrouphost(rhost, &ahost[2], baselen))
+ return -1;
+ /* disable user from -user entry */
+ if ('\0' != *user && user[0] == '-' && user[1] != '@'
+ && !strcmp(&user[1], ruser))
+ return -1;
+ /* disable user from -@netgroup entry for user */
+ if ('\0' != *user && user[0] == '-' && user[1] == '@'
+ && user[2] != '\0' && _checknetgroupuser(ruser, &user[2]))
+ return -1;
+ /* enable host from +@netgroup entry for host */
+ if ('+' == ahost[0] && '@' == ahost[1] && '\0' != ahost[2])
+ hostvalid = _checknetgrouphost(rhost, &ahost[2], baselen);
+ else
+ hostvalid = _checkhost(rhost, ahost, baselen);
+ /* enable user from +@netgroup entry for user */
+ if ('\0' != *user && user[0] == '+'
+ && user[1] == '@' && user[2] != '\0')
+ uservalid = _checknetgroupuser(ruser, &user[2]);
+ else
+ uservalid = !strcmp(ruser, *user ? user : luser);
+
+ if (hostvalid && uservalid)
+ return 0;
+#else
+ hostvalid = hostvalid ? 1 : _checkhost(rhost, ahost, baselen);
+ uservalid = uservalid ? 1 : !stricmp(ruser,*user ? user : luser);
+ if (hostvalid && uservalid)
+ return 0;
+
+#endif /* YP */
+ hostvalid = uservalid = 0;
+ }
+ return (-1);
+}
+
+int
+_checkhost(const char *rhost, const char *lhost, int len)
+{
+ static char ldomain[MAXHOSTNAMELEN + 1];
+ static char *domainp = NULL;
+ static int nodomain = 0;
+ register char *cp;
+
+ if (len == -1)
+ return(!strcmp(rhost, lhost));
+ if (strncmp(rhost, lhost, len))
+ return(0);
+ if (!strcmp(rhost, lhost))
+ return(1);
+ if (*(lhost + len) != '\0')
+ return(0);
+ if (nodomain)
+ return(0);
+ if (!domainp) {
+ if (gethostname(ldomain, sizeof(ldomain)) == -1) {
+ nodomain = 1;
+ return(0);
+ }
+ ldomain[MAXHOSTNAMELEN] = (char) 0;
+ if ((domainp = index(ldomain, '.')) == (char *)NULL) {
+ nodomain = 1;
+ return(0);
+ }
+ for (cp = ++domainp; *cp; ++cp)
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+ }
+ return(!strcmp(domainp, rhost + len +1));
+}
+
+#ifdef YP
+static int
+_checknetgrouphost(const char *rhost, const char *netgr, int baselen)
+{
+ char *host, *user, *domain;
+ int status;
+
+ if (NULL == nisdomain)
+ yp_get_default_domain(&nisdomain);
+
+ setnetgrent(netgr);
+ while (1)
+ {
+ while (1 == (status = getnetgrent(&host, &user, &domain))
+ && NULL == host
+ && NULL != domain
+ && 0 != strcmp(domain, nisdomain))
+ ; /* find valid host entry */
+
+ if (0 == status || NULL == host)
+ {
+ endnetgrent();
+ return 0;
+ }
+
+ if(1 == _checkhost(rhost, host, baselen))
+ {
+ endnetgrent();
+ return 1;
+ }
+ }
+}
+
+static int
+_checknetgroupuser(const char *ruser, const char *netgr)
+{
+ char *host, *user, *domain;
+ int status;
+
+ if (NULL == nisdomain)
+ yp_get_default_domain(&nisdomain);
+
+ setnetgrent(netgr);
+ while (1)
+ {
+ while (1 == (status = getnetgrent(&host, &user, &domain))
+ && NULL == user
+ && NULL != domain
+ && 0 != strcmp(domain, nisdomain))
+ ; /* find valid user entry */
+
+ if (0 == status || NULL == user)
+ {
+ endnetgrent();
+ return 0;
+ }
+
+ if(0 == strcmp(ruser, user))
+ {
+ endnetgrent();
+ return 1;
+ }
+ }
+}
+#endif /* YP */
+
+#endif
diff --git a/src/lib/libast/uwin/rint.c b/src/lib/libast/uwin/rint.c
new file mode 100644
index 0000000..9c88011
--- /dev/null
+++ b/src/lib/libast/uwin/rint.c
@@ -0,0 +1,41 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include "FEATURE/uwin"
+
+#if !_UWIN || _lib_ceil && _lib_floor && _lib_rint
+
+void _STUB_rint(){}
+
+#else
+
+#include <math.h>
+
+extern double rint(x)
+double x;
+{
+ double d = floor((x+=.5));
+ if(d==x && d/2.!=floor(d/2))
+ d = d-1;
+ return(d);
+}
+
+#endif
diff --git a/src/lib/libast/uwin/rlib.h b/src/lib/libast/uwin/rlib.h
new file mode 100644
index 0000000..bb9738b
--- /dev/null
+++ b/src/lib/libast/uwin/rlib.h
@@ -0,0 +1,80 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include <ast_std.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#if 0
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <net/if.h>
+#include <linux/sockios.h>
+#endif
+
+#ifndef sigmask
+#define sigmask(n) ((unsigned long)1 << ((n) - 1))
+#endif
+
+extern void _sethtent(int f);
+extern void _endhtent(void);
+extern struct hostent *_gethtent(void);
+extern struct hostent *_gethtbyname(const char *name);
+extern struct hostent *_gethtbyaddr(const char *addr, int len,
+ int type);
+extern int _validuser(FILE *hostf, const char *rhost,
+ const char *luser, const char *ruser, int baselen);
+extern int _checkhost(const char *rhost, const char *lhost, int len);
+
+#if 0
+extern void putlong(u_long l, u_char *msgp);
+extern void putshort(u_short l, u_char *msgp);
+extern u_int32_t _getlong(register const u_char *msgp);
+extern u_int16_t _getshort(register const u_char *msgp);
+extern void p_query(char *msg);
+extern void fp_query(char *msg, FILE *file);
+extern char *p_cdname(char *cp, char *msg, FILE *file);
+extern char *p_rr(char *cp, char *msg, FILE *file);
+extern char *p_type(int type);
+extern char * p_class(int class);
+extern char *p_time(u_long value);
+#endif
+
+extern char * hostalias(const char *name);
+extern void sethostfile(char *name);
+extern void _res_close (void);
+extern void ruserpass(const char *host, char **aname, char **apass);
+extern char* index(const char*, int);
+extern int strcasecmp(const char*, const char*);
+extern void bcopy(const void*, void*, size_t);
diff --git a/src/lib/libast/uwin/support.c b/src/lib/libast/uwin/support.c
new file mode 100644
index 0000000..769444e
--- /dev/null
+++ b/src/lib/libast/uwin/support.c
@@ -0,0 +1,605 @@
+#include "FEATURE/uwin"
+
+#if !_UWIN || (_lib__copysign||_lib_copysign) && _lib_logb && (_lib__finite||_lib_finite) && (_lib_drem||_lib_remainder) && _lib_sqrt && _lib_ilogb && (_lib__scalb||_lib_scalb)
+
+void _STUB_support(){}
+
+#else
+
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)support.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/*
+ * Some IEEE standard 754 recommended functions and remainder and sqrt for
+ * supporting the C elementary functions.
+ ******************************************************************************
+ * WARNING:
+ * These codes are developed (in double) to support the C elementary
+ * functions temporarily. They are not universal, and some of them are very
+ * slow (in particular, drem and sqrt is extremely inefficient). Each
+ * computer system should have its implementation of these functions using
+ * its own assembler.
+ ******************************************************************************
+ *
+ * IEEE 754 required operations:
+ * drem(x,p)
+ * returns x REM y = x - [x/y]*y , where [x/y] is the integer
+ * nearest x/y; in half way case, choose the even one.
+ * sqrt(x)
+ * returns the square root of x correctly rounded according to
+ * the rounding mod.
+ *
+ * IEEE 754 recommended functions:
+ * (a) copysign(x,y)
+ * returns x with the sign of y.
+ * (b) scalb(x,N)
+ * returns x * (2**N), for integer values N.
+ * (c) logb(x)
+ * returns the unbiased exponent of x, a signed integer in
+ * double precision, except that logb(0) is -INF, logb(INF)
+ * is +INF, and logb(NAN) is that NAN.
+ * (d) finite(x)
+ * returns the value TRUE if -INF < x < +INF and returns
+ * FALSE otherwise.
+ *
+ *
+ * CODED IN C BY K.C. NG, 11/25/84;
+ * REVISED BY K.C. NG on 1/22/85, 2/13/85, 3/24/85.
+ */
+
+#include "mathimpl.h"
+
+#if defined(vax)||defined(tahoe) /* VAX D format */
+#include <errno.h>
+ static const unsigned short msign=0x7fff , mexp =0x7f80 ;
+ static const short prep1=57, gap=7, bias=129 ;
+ static const double novf=1.7E38, nunf=3.0E-39, zero=0.0 ;
+#else /* defined(vax)||defined(tahoe) */
+ static const unsigned short msign=0x7fff, mexp =0x7ff0 ;
+ static const short prep1=54, gap=4, bias=1023 ;
+ static const double novf=1.7E308, nunf=3.0E-308,zero=0.0;
+#endif /* defined(vax)||defined(tahoe) */
+
+#if !_lib__scalb || !_lib_scalb
+
+extern double _scalb(x,N)
+double x; double N;
+{
+ int k;
+
+#ifdef national
+ unsigned short *px=(unsigned short *) &x + 3;
+#else /* national */
+ unsigned short *px=(unsigned short *) &x;
+#endif /* national */
+
+ if( x == zero ) return(x);
+
+#if defined(vax)||defined(tahoe)
+ if( (k= *px & mexp ) != ~msign ) {
+ if (N < -260)
+ return(nunf*nunf);
+ else if (N > 260) {
+ return(copysign(infnan(ERANGE),x));
+ }
+#else /* defined(vax)||defined(tahoe) */
+ if( (k= *px & mexp ) != mexp ) {
+ if( N<-2100) return(nunf*nunf); else if(N>2100) return(novf+novf);
+ if( k == 0 ) {
+ x *= scalb(1.0,prep1); N -= prep1; return(scalb(x,N));}
+#endif /* defined(vax)||defined(tahoe) */
+
+ if((k = (k>>gap)+ N) > 0 )
+ if( k < (mexp>>gap) ) *px = (*px&~mexp) | (k<<gap);
+ else x=novf+novf; /* overflow */
+ else
+ if( k > -prep1 )
+ /* gradual underflow */
+ {*px=(*px&~mexp)|(short)(1<<gap); x *= scalb(1.0,k-1);}
+ else
+ return(nunf*nunf);
+ }
+ return(x);
+}
+
+#endif
+
+#if !_lib_scalb
+
+extern double scalb(x,N)
+double x; double N;
+{
+ return _scalb(x, N);
+}
+
+#endif
+
+#if !_lib__copysign
+
+extern double _copysign(x,y)
+double x,y;
+{
+#ifdef national
+ unsigned short *px=(unsigned short *) &x+3,
+ *py=(unsigned short *) &y+3;
+#else /* national */
+ unsigned short *px=(unsigned short *) &x,
+ *py=(unsigned short *) &y;
+#endif /* national */
+
+#if defined(vax)||defined(tahoe)
+ if ( (*px & mexp) == 0 ) return(x);
+#endif /* defined(vax)||defined(tahoe) */
+
+ *px = ( *px & msign ) | ( *py & ~msign );
+ return(x);
+}
+
+#endif
+
+#if !_lib_copysign
+
+extern double copysign(x,y)
+double x,y;
+{
+ return _copysign(x,y);
+}
+
+#endif
+
+#if !_lib_logb
+
+extern double logb(x)
+double x;
+{
+
+#ifdef national
+ short *px=(short *) &x+3, k;
+#else /* national */
+ short *px=(short *) &x, k;
+#endif /* national */
+
+#if defined(vax)||defined(tahoe)
+ return (int)(((*px&mexp)>>gap)-bias);
+#else /* defined(vax)||defined(tahoe) */
+ if( (k= *px & mexp ) != mexp )
+ if ( k != 0 )
+ return ( (k>>gap) - bias );
+ else if( x != zero)
+ return ( -1022.0 );
+ else
+ return(-(1.0/zero));
+ else if(x != x)
+ return(x);
+ else
+ {*px &= msign; return(x);}
+#endif /* defined(vax)||defined(tahoe) */
+}
+
+#endif
+
+#if !_lib__finite
+
+extern int _finite(x)
+double x;
+{
+#if defined(vax)||defined(tahoe)
+ return(1);
+#else /* defined(vax)||defined(tahoe) */
+#ifdef national
+ return( (*((short *) &x+3 ) & mexp ) != mexp );
+#else /* national */
+ return( (*((short *) &x ) & mexp ) != mexp );
+#endif /* national */
+#endif /* defined(vax)||defined(tahoe) */
+}
+
+#endif
+
+#if !_lib_finite
+
+extern int finite(x)
+double x;
+{
+ return _finite(x);
+}
+
+#endif
+
+#if !_lib_drem
+
+extern double drem(x,p)
+double x,p;
+{
+#if _lib_remainder
+ return remainder(x,p);
+#else
+ short sign;
+ double hp,dp,tmp;
+ unsigned short k;
+#ifdef national
+ unsigned short
+ *px=(unsigned short *) &x +3,
+ *pp=(unsigned short *) &p +3,
+ *pd=(unsigned short *) &dp +3,
+ *pt=(unsigned short *) &tmp+3;
+#else /* national */
+ unsigned short
+ *px=(unsigned short *) &x ,
+ *pp=(unsigned short *) &p ,
+ *pd=(unsigned short *) &dp ,
+ *pt=(unsigned short *) &tmp;
+#endif /* national */
+
+ *pp &= msign ;
+
+#if defined(vax)||defined(tahoe)
+ if( ( *px & mexp ) == ~msign ) /* is x a reserved operand? */
+#else /* defined(vax)||defined(tahoe) */
+ if( ( *px & mexp ) == mexp )
+#endif /* defined(vax)||defined(tahoe) */
+ return (x-p)-(x-p); /* create nan if x is inf */
+ if (p == zero) {
+#if defined(vax)||defined(tahoe)
+ return(infnan(EDOM));
+#else /* defined(vax)||defined(tahoe) */
+ return zero/zero;
+#endif /* defined(vax)||defined(tahoe) */
+ }
+
+#if defined(vax)||defined(tahoe)
+ if( ( *pp & mexp ) == ~msign ) /* is p a reserved operand? */
+#else /* defined(vax)||defined(tahoe) */
+ if( ( *pp & mexp ) == mexp )
+#endif /* defined(vax)||defined(tahoe) */
+ { if (p != p) return p; else return x;}
+
+ else if ( ((*pp & mexp)>>gap) <= 1 )
+ /* subnormal p, or almost subnormal p */
+ { double b; b=scalb(1.0,(int)prep1);
+ p *= b; x = drem(x,p); x *= b; return(drem(x,p)/b);}
+ else if ( p >= novf/2)
+ { p /= 2 ; x /= 2; return(drem(x,p)*2);}
+ else
+ {
+ dp=p+p; hp=p/2;
+ sign= *px & ~msign ;
+ *px &= msign ;
+ while ( x > dp )
+ {
+ k=(*px & mexp) - (*pd & mexp) ;
+ tmp = dp ;
+ *pt += k ;
+
+#if defined(vax)||defined(tahoe)
+ if( x < tmp ) *pt -= 128 ;
+#else /* defined(vax)||defined(tahoe) */
+ if( x < tmp ) *pt -= 16 ;
+#endif /* defined(vax)||defined(tahoe) */
+
+ x -= tmp ;
+ }
+ if ( x > hp )
+ { x -= p ; if ( x >= hp ) x -= p ; }
+
+#if defined(vax)||defined(tahoe)
+ if (x)
+#endif /* defined(vax)||defined(tahoe) */
+ *px ^= sign;
+ return( x);
+
+ }
+#endif
+}
+
+#endif
+
+#if !_lib_remainder
+
+extern double remainder(x,p)
+double x,p;
+{
+ return drem(x,p);
+}
+
+#endif
+
+#if !_lib_sqrt
+
+extern double sqrt(x)
+double x;
+{
+ double q,s,b,r;
+ double t;
+ double const zero=0.0;
+ int m,n,i;
+#if defined(vax)||defined(tahoe)
+ int k=54;
+#else /* defined(vax)||defined(tahoe) */
+ int k=51;
+#endif /* defined(vax)||defined(tahoe) */
+
+ /* sqrt(NaN) is NaN, sqrt(+-0) = +-0 */
+ if(x!=x||x==zero) return(x);
+
+ /* sqrt(negative) is invalid */
+ if(x<zero) {
+#if defined(vax)||defined(tahoe)
+ return (infnan(EDOM)); /* NaN */
+#else /* defined(vax)||defined(tahoe) */
+ return(zero/zero);
+#endif /* defined(vax)||defined(tahoe) */
+ }
+
+ /* sqrt(INF) is INF */
+ if(!finite(x)) return(x);
+
+ /* scale x to [1,4) */
+ n=logb(x);
+ x=scalb(x,-n);
+ if((m=logb(x))!=0) x=scalb(x,-m); /* subnormal number */
+ m += n;
+ n = m/2;
+ if((n+n)!=m) {x *= 2; m -=1; n=m/2;}
+
+ /* generate sqrt(x) bit by bit (accumulating in q) */
+ q=1.0; s=4.0; x -= 1.0; r=1;
+ for(i=1;i<=k;i++) {
+ t=s+1; x *= 4; r /= 2;
+ if(t<=x) {
+ s=t+t+2, x -= t; q += r;}
+ else
+ s *= 2;
+ }
+
+ /* generate the last bit and determine the final rounding */
+ r/=2; x *= 4;
+ if(x==zero) goto end; 100+r; /* trigger inexact flag */
+ if(s<x) {
+ q+=r; x -=s; s += 2; s *= 2; x *= 4;
+ t = (x-s)-5;
+ b=1.0+3*r/4; if(b==1.0) goto end; /* b==1 : Round-to-zero */
+ b=1.0+r/4; if(b>1.0) t=1; /* b>1 : Round-to-(+INF) */
+ if(t>=0) q+=r; } /* else: Round-to-nearest */
+ else {
+ s *= 2; x *= 4;
+ t = (x-s)-1;
+ b=1.0+3*r/4; if(b==1.0) goto end;
+ b=1.0+r/4; if(b>1.0) t=1;
+ if(t>=0) q+=r; }
+
+end: return(scalb(q,n));
+}
+
+#endif
+
+#if 0
+/* DREM(X,Y)
+ * RETURN X REM Y =X-N*Y, N=[X/Y] ROUNDED (ROUNDED TO EVEN IN THE HALF WAY CASE)
+ * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
+ * INTENDED FOR ASSEMBLY LANGUAGE
+ * CODED IN C BY K.C. NG, 3/23/85, 4/8/85.
+ *
+ * Warning: this code should not get compiled in unless ALL of
+ * the following machine-dependent routines are supplied.
+ *
+ * Required machine dependent functions (not on a VAX):
+ * swapINX(i): save inexact flag and reset it to "i"
+ * swapENI(e): save inexact enable and reset it to "e"
+ */
+
+extern double drem(x,y)
+double x,y;
+{
+
+#ifdef national /* order of words in floating point number */
+ static const n0=3,n1=2,n2=1,n3=0;
+#else /* VAX, SUN, ZILOG, TAHOE */
+ static const n0=0,n1=1,n2=2,n3=3;
+#endif
+
+ static const unsigned short mexp =0x7ff0, m25 =0x0190, m57 =0x0390;
+ static const double zero=0.0;
+ double hy,y1,t,t1;
+ short k;
+ long n;
+ int i,e;
+ unsigned short xexp,yexp, *px =(unsigned short *) &x ,
+ nx,nf, *py =(unsigned short *) &y ,
+ sign, *pt =(unsigned short *) &t ,
+ *pt1 =(unsigned short *) &t1 ;
+
+ xexp = px[n0] & mexp ; /* exponent of x */
+ yexp = py[n0] & mexp ; /* exponent of y */
+ sign = px[n0] &0x8000; /* sign of x */
+
+/* return NaN if x is NaN, or y is NaN, or x is INF, or y is zero */
+ if(x!=x) return(x); if(y!=y) return(y); /* x or y is NaN */
+ if( xexp == mexp ) return(zero/zero); /* x is INF */
+ if(y==zero) return(y/y);
+
+/* save the inexact flag and inexact enable in i and e respectively
+ * and reset them to zero
+ */
+ i=swapINX(0); e=swapENI(0);
+
+/* subnormal number */
+ nx=0;
+ if(yexp==0) {t=1.0,pt[n0]+=m57; y*=t; nx=m57;}
+
+/* if y is tiny (biased exponent <= 57), scale up y to y*2**57 */
+ if( yexp <= m57 ) {py[n0]+=m57; nx+=m57; yexp+=m57;}
+
+ nf=nx;
+ py[n0] &= 0x7fff;
+ px[n0] &= 0x7fff;
+
+/* mask off the least significant 27 bits of y */
+ t=y; pt[n3]=0; pt[n2]&=0xf800; y1=t;
+
+/* LOOP: argument reduction on x whenever x > y */
+loop:
+ while ( x > y )
+ {
+ t=y;
+ t1=y1;
+ xexp=px[n0]&mexp; /* exponent of x */
+ k=xexp-yexp-m25;
+ if(k>0) /* if x/y >= 2**26, scale up y so that x/y < 2**26 */
+ {pt[n0]+=k;pt1[n0]+=k;}
+ n=x/t; x=(x-n*t1)-n*(t-t1);
+ }
+ /* end while (x > y) */
+
+ if(nx!=0) {t=1.0; pt[n0]+=nx; x*=t; nx=0; goto loop;}
+
+/* final adjustment */
+
+ hy=y/2.0;
+ if(x>hy||((x==hy)&&n%2==1)) x-=y;
+ px[n0] ^= sign;
+ if(nf!=0) { t=1.0; pt[n0]-=nf; x*=t;}
+
+/* restore inexact flag and inexact enable */
+ swapINX(i); swapENI(e);
+
+ return(x);
+}
+#endif
+
+#if 0
+/* SQRT
+ * RETURN CORRECTLY ROUNDED (ACCORDING TO THE ROUNDING MODE) SQRT
+ * FOR IEEE DOUBLE PRECISION ONLY, INTENDED FOR ASSEMBLY LANGUAGE
+ * CODED IN C BY K.C. NG, 3/22/85.
+ *
+ * Warning: this code should not get compiled in unless ALL of
+ * the following machine-dependent routines are supplied.
+ *
+ * Required machine dependent functions:
+ * swapINX(i) ...return the status of INEXACT flag and reset it to "i"
+ * swapRM(r) ...return the current Rounding Mode and reset it to "r"
+ * swapENI(e) ...return the status of inexact enable and reset it to "e"
+ * addc(t) ...perform t=t+1 regarding t as a 64 bit unsigned integer
+ * subc(t) ...perform t=t-1 regarding t as a 64 bit unsigned integer
+ */
+
+static const unsigned long table[] = {
+0, 1204, 3062, 5746, 9193, 13348, 18162, 23592, 29598, 36145, 43202, 50740,
+58733, 67158, 75992, 85215, 83599, 71378, 60428, 50647, 41945, 34246, 27478,
+21581, 16499, 12183, 8588, 5674, 3403, 1742, 661, 130, };
+
+extern double newsqrt(x)
+double x;
+{
+ double y,z,t,addc(),subc()
+ double const b54=134217728.*134217728.; /* b54=2**54 */
+ long mx,scalx;
+ long const mexp=0x7ff00000;
+ int i,j,r,e,swapINX(),swapRM(),swapENI();
+ unsigned long *py=(unsigned long *) &y ,
+ *pt=(unsigned long *) &t ,
+ *px=(unsigned long *) &x ;
+#ifdef national /* ordering of word in a floating point number */
+ const int n0=1, n1=0;
+#else
+ const int n0=0, n1=1;
+#endif
+/* Rounding Mode: RN ...round-to-nearest
+ * RZ ...round-towards 0
+ * RP ...round-towards +INF
+ * RM ...round-towards -INF
+ */
+ const int RN=0,RZ=1,RP=2,RM=3;
+ /* machine dependent: work on a Zilog Z8070
+ * and a National 32081 & 16081
+ */
+
+/* exceptions */
+ if(x!=x||x==0.0) return(x); /* sqrt(NaN) is NaN, sqrt(+-0) = +-0 */
+ if(x<0) return((x-x)/(x-x)); /* sqrt(negative) is invalid */
+ if((mx=px[n0]&mexp)==mexp) return(x); /* sqrt(+INF) is +INF */
+
+/* save, reset, initialize */
+ e=swapENI(0); /* ...save and reset the inexact enable */
+ i=swapINX(0); /* ...save INEXACT flag */
+ r=swapRM(RN); /* ...save and reset the Rounding Mode to RN */
+ scalx=0;
+
+/* subnormal number, scale up x to x*2**54 */
+ if(mx==0) {x *= b54 ; scalx-=0x01b00000;}
+
+/* scale x to avoid intermediate over/underflow:
+ * if (x > 2**512) x=x/2**512; if (x < 2**-512) x=x*2**512 */
+ if(mx>0x5ff00000) {px[n0] -= 0x20000000; scalx+= 0x10000000;}
+ if(mx<0x1ff00000) {px[n0] += 0x20000000; scalx-= 0x10000000;}
+
+/* magic initial approximation to almost 8 sig. bits */
+ py[n0]=(px[n0]>>1)+0x1ff80000;
+ py[n0]=py[n0]-table[(py[n0]>>15)&31];
+
+/* Heron's rule once with correction to improve y to almost 18 sig. bits */
+ t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0;
+
+/* triple to almost 56 sig. bits; now y approx. sqrt(x) to within 1 ulp */
+ t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y;
+ t=z/(t+x) ; pt[n0]+=0x00100000; y+=t;
+
+/* twiddle last bit to force y correctly rounded */
+ swapRM(RZ); /* ...set Rounding Mode to round-toward-zero */
+ swapINX(0); /* ...clear INEXACT flag */
+ swapENI(e); /* ...restore inexact enable status */
+ t=x/y; /* ...chopped quotient, possibly inexact */
+ j=swapINX(i); /* ...read and restore inexact flag */
+ if(j==0) { if(t==y) goto end; else t=subc(t); } /* ...t=t-ulp */
+ b54+0.1; /* ..trigger inexact flag, sqrt(x) is inexact */
+ if(r==RN) t=addc(t); /* ...t=t+ulp */
+ else if(r==RP) { t=addc(t);y=addc(y);}/* ...t=t+ulp;y=y+ulp; */
+ y=y+t; /* ...chopped sum */
+ py[n0]=py[n0]-0x00100000; /* ...correctly rounded sqrt(x) */
+end: py[n0]=py[n0]+scalx; /* ...scale back y */
+ swapRM(r); /* ...restore Rounding Mode */
+ return(y);
+}
+#endif
+
+#if !_lib_ilogb
+
+extern int ilogb(double x)
+{
+ return((int)logb(x));
+}
+
+#endif
+
+#endif
diff --git a/src/lib/libast/vec/vecargs.c b/src/lib/libast/vec/vecargs.c
new file mode 100644
index 0000000..421ade0
--- /dev/null
+++ b/src/lib/libast/vec/vecargs.c
@@ -0,0 +1,76 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * string vector argv insertion
+ */
+
+#include <ast.h>
+#include <vecargs.h>
+#include <ctype.h>
+
+/*
+ * insert the string vector vec between
+ * (*argvp)[0] and (*argvp)[1], sliding (*argvp)[1] ... over
+ * null and blank args are deleted
+ *
+ * vecfree always called
+ *
+ * -1 returned if insertion failed
+ */
+
+int
+vecargs(register char** vec, int* argcp, char*** argvp)
+{
+ register char** argv;
+ register char** oargv;
+ char** ovec;
+ char* s;
+ int num;
+
+ if (!vec) return(-1);
+ if ((num = (char**)(*(vec - 1)) - vec) > 0)
+ {
+ if (!(argv = newof(0, char*, num + *argcp + 1, 0)))
+ {
+ vecfree(vec, 0);
+ return(-1);
+ }
+ oargv = *argvp;
+ *argvp = argv;
+ *argv++ = *oargv++;
+ ovec = vec;
+ while (s = *argv = *vec++)
+ {
+ while (isspace(*s)) s++;
+ if (*s) argv++;
+ }
+ vecfree(ovec, 1);
+ while (*argv = *oargv++) argv++;
+ *argcp = argv - *argvp;
+ }
+ else vecfree(vec, 0);
+ return(0);
+}
diff --git a/src/lib/libast/vec/vecfile.c b/src/lib/libast/vec/vecfile.c
new file mode 100644
index 0000000..6c6991b
--- /dev/null
+++ b/src/lib/libast/vec/vecfile.c
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * string vector load support
+ */
+
+#include <ast.h>
+#include <ls.h>
+#include <vecargs.h>
+
+/*
+ * load a string vector from lines in file
+ */
+
+char**
+vecfile(const char* file)
+{
+ register int n;
+ register char* buf;
+ register char** vec;
+ int fd;
+ struct stat st;
+
+ vec = 0;
+ if ((fd = open(file, O_RDONLY)) >= 0)
+ {
+ if (!fstat(fd, &st) && S_ISREG(st.st_mode) && (n = st.st_size) > 0 && (buf = newof(0, char, n + 1, 0)))
+ {
+ if (read(fd, buf, n) == n)
+ {
+ buf[n] = 0;
+ vec = vecload(buf);
+ }
+ if (!vec) free(buf);
+ }
+ close(fd);
+ }
+ return(vec);
+}
diff --git a/src/lib/libast/vec/vecfree.c b/src/lib/libast/vec/vecfree.c
new file mode 100644
index 0000000..12b3bc2
--- /dev/null
+++ b/src/lib/libast/vec/vecfree.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * file to string vector support
+ */
+
+#include <ast.h>
+#include <vecargs.h>
+
+/*
+ * free a string vector generated by vecload()
+ *
+ * retain!=0 frees the string pointers but retains the string data
+ * in this case the data is permanently allocated
+ */
+
+void
+vecfree(register char** vec, int retain)
+{
+ if (vec)
+ {
+ if (*(vec -= 2) && !retain) free(*vec);
+ free(vec);
+ }
+}
diff --git a/src/lib/libast/vec/vecload.c b/src/lib/libast/vec/vecload.c
new file mode 100644
index 0000000..5f83470
--- /dev/null
+++ b/src/lib/libast/vec/vecload.c
@@ -0,0 +1,96 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * string vector load support
+ */
+
+#include <ast.h>
+#include <vecargs.h>
+
+/*
+ * load a string vector from lines in buf
+ * buf may be modified on return
+ *
+ * each line in buf is treated as a new vector element
+ * lines with # as first char are comments
+ * \ as the last char joins consecutive lines
+ *
+ * the vector ends with a 0 sentinel
+ *
+ * the string array pointer is returned
+ */
+
+char**
+vecload(char* buf)
+{
+ register char* s;
+ register int n;
+ register char** p;
+ char** vec;
+
+ vec = 0;
+ n = (*buf == '#') ? -1 : 0;
+ for (s = buf;; s++)
+ {
+ if (*s == '\n')
+ {
+ if (s > buf && *(s - 1) == '\\') *(s - 1) = *s = ' ';
+ else
+ {
+ *s = 0;
+ if (*(s + 1) != '#')
+ {
+ n++;
+ if (!*(s + 1)) break;
+ }
+ }
+ }
+ else if (!*s)
+ {
+ n++;
+ break;
+ }
+ }
+ if (n < 0) n = 0;
+ if (p = newof(0, char*, n + 3, 0))
+ {
+ *p++ = s = buf;
+ vec = ++p;
+ if (n > 0) for (;;)
+ {
+ if (*s != '#')
+ {
+ *p++ = s;
+ if (--n <= 0) break;
+ }
+ while (*s) s++;
+ s++;
+ }
+ *p = 0;
+ *(vec - 1) = (char*)p;
+ }
+ return(vec);
+}
diff --git a/src/lib/libast/vec/vecstring.c b/src/lib/libast/vec/vecstring.c
new file mode 100644
index 0000000..6aeac9d
--- /dev/null
+++ b/src/lib/libast/vec/vecstring.c
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * string vector load support
+ */
+
+#include <ast.h>
+#include <vecargs.h>
+
+/*
+ * load a string vector from lines in str
+ */
+
+char**
+vecstring(const char* str)
+{
+ register char* buf;
+ register char** vec;
+
+ if (!str || !*str || !(buf = strdup(str))) vec = 0;
+ else if (!(vec = vecload(buf))) free(buf);
+ return(vec);
+}
diff --git a/src/lib/libast/vmalloc/malloc.c b/src/lib/libast/vmalloc/malloc.c
new file mode 100644
index 0000000..e69523a
--- /dev/null
+++ b/src/lib/libast/vmalloc/malloc.c
@@ -0,0 +1,1438 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_malloc(){}
+
+#else
+
+#if _UWIN
+
+#define calloc ______calloc
+#define _ast_free ______free
+#define malloc ______malloc
+#define mallinfo ______mallinfo
+#define mallopt ______mallopt
+#define mstats ______mstats
+#define realloc ______realloc
+
+#define _STDLIB_H_ 1
+
+extern int atexit(void(*)(void));
+extern char* getenv(const char*);
+
+#endif
+
+#include "vmhdr.h"
+#include <errno.h>
+
+#if _UWIN
+
+#include <malloc.h>
+
+#define _map_malloc 1
+#define _mal_alloca 1
+
+#undef calloc
+#define calloc _ast_calloc
+#undef _ast_free
+#define free _ast_free
+#undef malloc
+#define malloc _ast_malloc
+#undef mallinfo
+typedef struct ______mallinfo Mallinfo_t;
+#undef mallopt
+#undef mstats
+typedef struct ______mstats Mstats_t;
+#undef realloc
+#define realloc _ast_realloc
+
+#endif
+
+#if __STD_C
+#define F0(f,t0) f(t0)
+#define F1(f,t1,a1) f(t1 a1)
+#define F2(f,t1,a1,t2,a2) f(t1 a1, t2 a2)
+#else
+#define F0(f,t0) f()
+#define F1(f,t1,a1) f(a1) t1 a1;
+#define F2(f,t1,a1,t2,a2) f(a1, a2) t1 a1; t2 a2;
+#endif
+
+/*
+ * define _AST_std_malloc=1 to force the standard malloc
+ * if _map_malloc is also defined then _ast_malloc etc.
+ * will simply call malloc etc.
+ */
+
+#if !defined(_AST_std_malloc) && __CYGWIN__
+#define _AST_std_malloc 1
+#endif
+
+/* malloc compatibility functions
+**
+** These are aware of debugging/profiling and are driven by the
+** VMALLOC_OPTIONS environment variable which is a comma or space
+** separated list of [no]name[=value] options:
+**
+** abort if Vmregion==Vmdebug then VM_DBABORT is set,
+** otherwise _BLD_DEBUG enabled assertions abort()
+** on failure
+** break try sbrk() block allocator first
+** check if Vmregion==Vmbest then the region is checked every op
+** free disable addfreelist()
+** keep disable free -- if code works with this enabled then it
+** probably accesses free'd data
+** method=m sets Vmregion=m if not defined, m (Vm prefix optional)
+** may be one of { best debug last profile }
+** period=n sets Vmregion=Vmdebug if not defined, if
+** Vmregion==Vmdebug the region is checked every n ops
+** profile=f sets Vmregion=Vmprofile if not set, if
+** Vmregion==Vmprofile then profile info printed to file f
+** start=n sets Vmregion=Vmdebug if not defined, if
+** Vmregion==Vmdebug region checking starts after n ops
+** trace=f enables tracing to file f
+** warn=f sets Vmregion=Vmdebug if not defined, if
+** Vmregion==Vmdebug then warnings printed to file f
+** watch=a sets Vmregion=Vmdebug if not defined, if
+** Vmregion==Vmdebug then address a is watched
+**
+** Output files are created if they don't exist. &n and /dev/fd/n name
+** the file descriptor n which must be open for writing. The pattern %p
+** in a file name is replaced by the process ID.
+**
+** VMALLOC_OPTIONS combines the features of these previously used env vars:
+** { VMCHECK VMDEBUG VMETHOD VMPROFILE VMTRACE }
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+
+#if _sys_stat
+#include <sys/stat.h>
+#endif
+#include <fcntl.h>
+
+#ifdef S_IRUSR
+#define CREAT_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
+#else
+#define CREAT_MODE 0644
+#endif
+
+static Vmulong_t _Vmdbstart = 0;
+static Vmulong_t _Vmdbcheck = 0;
+static Vmulong_t _Vmdbtime = 0;
+static int _Vmpffd = -1;
+
+#if ( !_std_malloc || !_BLD_ast ) && !_AST_std_malloc
+
+#if !_map_malloc
+#undef calloc
+#undef cfree
+#undef free
+#undef mallinfo
+#undef malloc
+#undef mallopt
+#undef memalign
+#undef mstats
+#undef realloc
+#undef valloc
+
+#if _malloc_hook
+
+#include <malloc.h>
+
+#undef calloc
+#undef cfree
+#undef free
+#undef malloc
+#undef memalign
+#undef realloc
+
+#define calloc _ast_calloc
+#define cfree _ast_cfree
+#define free _ast_free
+#define malloc _ast_malloc
+#define memalign _ast_memalign
+#define realloc _ast_realloc
+
+#endif
+
+#endif
+
+#if _WINIX
+
+#include <ast_windows.h>
+
+#if _UWIN
+
+#define VMRECORD(p) _vmrecord(p)
+#define VMBLOCK { int _vmblock = _sigblock();
+#define VMUNBLOCK _sigunblock(_vmblock); }
+
+extern int _sigblock(void);
+extern void _sigunblock(int);
+extern unsigned long _record[2048];
+
+__inline Void_t* _vmrecord(Void_t* p)
+{
+ register unsigned long v = ((unsigned long)p)>>16;
+
+ _record[v>>5] |= 1<<((v&0x1f));
+ return p;
+}
+
+#else
+
+#define getenv(s) lcl_getenv(s)
+
+static char*
+lcl_getenv(const char* s)
+{
+ int n;
+ static char buf[512];
+
+ if (!(n = GetEnvironmentVariable(s, buf, sizeof(buf))) || n > sizeof(buf))
+ return 0;
+ return buf;
+}
+
+#endif /* _UWIN */
+
+#endif /* _WINIX */
+
+#ifndef VMRECORD
+#define VMRECORD(p) (p)
+#define VMBLOCK
+#define VMUNBLOCK
+#endif
+
+#if defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+
+static int _Vmflinit = 0;
+#define VMFLINIT() \
+ { if(!_Vmflinit) vmflinit(); \
+ if(_Vmdbcheck) \
+ { if(_Vmdbtime < _Vmdbstart) _Vmdbtime += 1; \
+ else if((_Vmdbtime += 1) < _Vmdbstart) _Vmdbtime = _Vmdbstart; \
+ if(_Vmdbtime >= _Vmdbstart && (_Vmdbtime % _Vmdbcheck) == 0 && \
+ Vmregion->meth.meth == VM_MTDEBUG) \
+ vmdbcheck(Vmregion); \
+ } \
+ }
+
+#if __STD_C
+static int vmflinit(void)
+#else
+static int vmflinit()
+#endif
+{
+ char* file;
+ int line;
+ Void_t* func;
+
+ /* this must be done now to avoid any inadvertent recursion (more below) */
+ _Vmflinit = 1;
+ VMFLF(Vmregion,file,line,func);
+
+ /* if getenv() calls malloc(), the options may not affect the eventual region */
+ VMOPTIONS();
+
+ /* reset file and line number to correct values for the call */
+ Vmregion->file = file;
+ Vmregion->line = line;
+ Vmregion->func = func;
+
+ return 0;
+}
+
+/* use multiple regions to reduce blocking by concurrent threads */
+#if _mem_mmap_anon || _mem_mmap_zero
+static Vmalloc_t *Region[64]; /* list of concurrent regions */
+static unsigned int Regmax = 64; /* max number of regions */
+#else
+static Vmalloc_t* Region[1]; /* list of concurrent regions */
+static unsigned int Regmax = 0;
+#endif
+static unsigned int Regnum = 0; /* current #concurrent regions */
+
+/* statistics */
+static unsigned int Regopen = 0; /* #allocation calls opened */
+static unsigned int Reglock = 0; /* #allocation calls locked */
+static unsigned int Regprobe = 0; /* #probes to find a region */
+
+int setregmax(int regmax)
+{
+ int oldmax = Regmax;
+
+ if(regmax >= Regnum && regmax <= sizeof(Region)/sizeof(Region[0]))
+ Regmax = regmax;
+
+ return oldmax;
+}
+
+/* return statistics */
+int _mallocstat(Vmstat_t* st)
+{
+ Vmstat_t vmst;
+ int k;
+
+ if(vmstat(Vmregion, st) < 0) /* add up all stats */
+ return -1;
+ for(k = 0; k < Regnum; ++k)
+ { if(!Region[k])
+ continue;
+ if(vmstat(Region[k], &vmst) < 0 )
+ return -1;
+ st->n_busy += vmst.n_busy;
+ st->n_free += vmst.n_free;
+ st->s_busy += vmst.s_busy;
+ st->s_free += vmst.s_free;
+ st->m_busy += vmst.m_busy;
+ st->m_free += vmst.m_free;
+ st->n_seg += vmst.n_seg;
+ st->extent += vmst.extent;
+ }
+
+ st->n_region = Regnum+1;
+ st->n_open = Regopen;
+ st->n_lock = Reglock;
+ st->n_probe = Regprobe;
+
+ return 0;
+}
+
+/* find the region that a block was allocated from */
+static Vmalloc_t* regionof(Void_t* addr)
+{
+ int k;
+
+#if USE_NATIVE
+#define CAUTIOUS 1
+#else
+#define CAUTIOUS 0
+#endif
+ if(CAUTIOUS || Vmregion->meth.meth != VM_MTBEST )
+ { /* addr will not be dereferenced here */
+ if(vmaddr(Vmregion,addr) == 0 )
+ return Vmregion;
+ for(k = 0; k < Regnum; ++k)
+ if(Region[k] && vmaddr(Region[k], addr) == 0 )
+ return Region[k];
+ return NIL(Vmalloc_t*);
+ }
+ else
+ { /* fast, but susceptible to bad data */
+ Vmdata_t *vd = SEG(BLOCK(addr))->vmdt;
+ if(Vmregion->data == vd )
+ return Vmregion;
+ for(k = 0; k < Regnum; ++k)
+ if(Region[k] && Region[k]->data == vd)
+ return Region[k];
+ return NIL(Vmalloc_t*);
+ }
+}
+
+/* manage a cache of free objects */
+typedef struct _regfree_s
+{ struct _regfree_s* next;
+} Regfree_t;
+static Regfree_t *Regfree;
+
+static void addfreelist(Regfree_t* data)
+{
+ unsigned int k;
+ Regfree_t *head;
+
+ for(k = 0;; ASOLOOP(k) )
+ { data->next = head = Regfree;
+ if(asocasptr(&Regfree, head, data) == (Void_t*)head )
+ return;
+ }
+}
+
+static void clrfreelist()
+{
+ Regfree_t *list, *next;
+ Vmalloc_t *vm;
+
+ if(!(list = Regfree) )
+ return; /* nothing to do */
+
+ if(asocasptr(&Regfree, list, NIL(Regfree_t*)) != list )
+ return; /* somebody else is doing it */
+
+ for(; list; list = next)
+ { next = list->next;
+ if(vm = regionof((Void_t*)list))
+ { if(asocasint(&vm->data->lock, 0, 1) == 0) /* can free this now */
+ { (void)(*vm->meth.freef)(vm, (Void_t*)list, 1);
+ vm->data->lock = 0;
+ }
+ else addfreelist(list); /* ah well, back in the queue */
+ }
+ }
+}
+
+/* get a suitable region to allocate from */
+typedef struct _regdisc_s
+{ Vmdisc_t disc;
+ char slop[64]; /* to absorb any extra data in Vmdcsystem */
+} Regdisc_t;
+
+static int regexcept(Vmalloc_t* vm, int type, Void_t* data, Vmdisc_t* disc)
+{
+ if(type == VM_OPEN)
+ { if(data) /* make vmopen allocate all memory using discipline */
+ *(Void_t**)data = data; /* just make it non-NULL */
+ return 0;
+ }
+ return 0;
+}
+
+static Vmalloc_t* getregion(int* local)
+{
+ Vmalloc_t *vm;
+ int p, pos;
+
+ static unsigned int Rand = 0xdeadbeef; /* a cheap prng */
+#define RAND() (Rand = Rand*16777617 + 3)
+
+ clrfreelist();
+
+ if(Regmax <= 0 )
+ { /* uni-process/thread */
+ *local = 1;
+ Vmregion->data->lock = 1;
+ return Vmregion;
+ }
+ else if(asocasint(&Vmregion->data->lock, 0, 1) == 0 )
+ { /* Vmregion is open, so use it */
+ *local = 1;
+ asoincint(&Regopen);
+ return Vmregion;
+ }
+
+ asoincint(&Regprobe); /* probe Region[] to find an open region */
+ if(Regnum == 0)
+ pos = 0;
+ else for(pos = p = RAND()%Regnum;; )
+ { if(Region[p] && asocasint(&Region[p]->data->lock, 0, 1) == 0 )
+ { *local = 1;
+ asoincint(&Regopen);
+ return Region[p];
+ }
+ if((p = (p+1)%Regnum) == pos )
+ break;
+ }
+
+ /* grab the next open slot for a new region */
+ while((p = Regnum) < Regmax)
+ if(asocasint(&Regnum, p, p+1) == p )
+ break;
+ if(p < Regmax) /* this slot is now ours */
+ { static Regdisc_t Regdisc;
+ if(!Regdisc.disc.exceptf) /* one time initialization */
+ { GETPAGESIZE(_Vmpagesize);
+ memcpy(&Regdisc, Vmdcsystem, Vmdcsystem->size);
+ Regdisc.disc.round = ROUND(_Vmpagesize, 64*1024);
+ Regdisc.disc.exceptf = regexcept;
+ }
+
+ /**/ASSERT(Region[p] == NIL(Vmalloc_t*));
+ if((vm = vmopen(&Regdisc.disc, Vmbest, VM_SHARE)) != NIL(Vmalloc_t*) )
+ { vm->data->lock = 1; /* lock new region now */
+ *local = 1;
+ asoincint(&Regopen);
+ return (Region[p] = vm);
+ }
+ else Region[p] = Vmregion; /* better than nothing */
+ }
+
+ /* must return something */
+ vm = Region[pos] ? Region[pos] : Vmregion;
+ if(asocasint(&vm->data->lock, 0, 1) == 0)
+ { *local = 1;
+ asoincint(&Regopen);
+ }
+ else
+ { *local = 0;
+ asoincint(&Reglock);
+ }
+ return vm;
+}
+
+#if __STD_C
+extern Void_t* calloc(reg size_t n_obj, reg size_t s_obj)
+#else
+extern Void_t* calloc(n_obj, s_obj)
+reg size_t n_obj;
+reg size_t s_obj;
+#endif
+{
+ Void_t *addr;
+ Vmalloc_t *vm;
+ int local = 0;
+ VMFLINIT();
+
+ vm = getregion(&local);
+ addr = (*vm->meth.resizef)(vm, NIL(Void_t*), n_obj*s_obj, VM_RSZERO, local);
+ if(local)
+ { /**/ASSERT(vm->data->lock == 1);
+ vm->data->lock = 0;
+ }
+ return VMRECORD(addr);
+}
+
+#if __STD_C
+extern Void_t* malloc(reg size_t size)
+#else
+extern Void_t* malloc(size)
+reg size_t size;
+#endif
+{
+ Void_t *addr;
+ Vmalloc_t *vm;
+ int local = 0;
+ VMFLINIT();
+
+ vm = getregion(&local);
+ addr = (*vm->meth.allocf)(vm, size, local);
+ if(local)
+ { /**/ASSERT(vm->data->lock == 1);
+ vm->data->lock = 0;
+ }
+ return VMRECORD(addr);
+}
+
+#if __STD_C
+extern Void_t* realloc(reg Void_t* data, reg size_t size)
+#else
+extern Void_t* realloc(data,size)
+reg Void_t* data; /* block to be reallocated */
+reg size_t size; /* new size */
+#endif
+{
+ ssize_t copy;
+ Void_t *addr;
+ Vmalloc_t *vm;
+ VMFLINIT();
+
+ if(!data)
+ return malloc(size);
+ else if((vm = regionof(data)) )
+ { if(vm == Vmregion && vm != Vmheap) /* no multiple region usage here */
+ { addr = (*vm->meth.resizef)(vm, data, size, VM_RSCOPY|VM_RSMOVE, 0);
+ return VMRECORD(addr);
+ }
+ if(asocasint(&vm->data->lock, 0, 1) == 0 ) /* region is open */
+ { addr = (*vm->meth.resizef)(vm, data, size, VM_RSCOPY|VM_RSMOVE, 1);
+ vm->data->lock = 0;
+ return VMRECORD(addr);
+ }
+ else if(Regmax > 0 && Vmregion == Vmheap && (addr = malloc(size)) )
+ { if((copy = SIZE(BLOCK(data))&~BITS) > size )
+ copy = size;
+ memcpy(addr, data, copy);
+ addfreelist((Regfree_t*)data);
+ return VMRECORD(addr);
+ }
+ else /* this may block but it is the best that we can do now */
+ { addr = (*vm->meth.resizef)(vm, data, size, VM_RSCOPY|VM_RSMOVE, 0);
+ return VMRECORD(addr);
+ }
+ }
+ else /* not our data */
+ {
+#if USE_NATIVE
+#undef realloc /* let the native realloc() take care of it */
+#if __STD_C
+ extern Void_t* realloc(Void_t*, size_t);
+#else
+ extern Void_t* realloc();
+#endif
+ return realloc(data, size);
+#else
+ return NIL(Void_t*);
+#endif
+ }
+}
+
+#if __STD_C
+extern void free(reg Void_t* data)
+#else
+extern void free(data)
+reg Void_t* data;
+#endif
+{
+ Vmalloc_t *vm;
+ VMFLINIT();
+
+ if(!data || (_Vmassert & VM_keep))
+ return;
+ else if((vm = regionof(data)) )
+ {
+ if(vm == Vmregion && Vmregion != Vmheap || (_Vmassert & VM_free))
+ (void)(*vm->meth.freef)(vm, data, 0);
+ else addfreelist((Regfree_t*)data);
+ return;
+ }
+ else /* not our data */
+ {
+#if USE_NATIVE
+#undef free /* let the native free() take care of it */
+#if __STD_C
+ extern void free(Void_t*);
+#else
+ extern void free();
+#endif
+ free(data);
+#endif
+ return;
+ }
+}
+
+#if __STD_C
+extern void cfree(reg Void_t* data)
+#else
+extern void cfree(data)
+reg Void_t* data;
+#endif
+{
+ free(data);
+}
+
+#if __STD_C
+extern Void_t* memalign(reg size_t align, reg size_t size)
+#else
+extern Void_t* memalign(align, size)
+reg size_t align;
+reg size_t size;
+#endif
+{
+ Void_t *addr;
+ Vmalloc_t *vm;
+ int local = 0;
+ VMFLINIT();
+
+ vm = getregion(&local);
+ VMBLOCK
+ addr = (*vm->meth.alignf)(vm, size, align, local);
+ if(local)
+ { /**/ASSERT(vm->data->lock == 1);
+ vm->data->lock = 0;
+ }
+ VMUNBLOCK
+ return VMRECORD(addr);
+}
+
+#if __STD_C
+extern int posix_memalign(reg Void_t **memptr, reg size_t align, reg size_t size)
+#else
+extern int posix_memalign(memptr, align, size)
+reg Void_t** memptr;
+reg size_t align;
+reg size_t size;
+#endif
+{
+ Void_t *mem;
+
+ if(align == 0 || (align%sizeof(Void_t*)) != 0 || ((align-1)&align) != 0 )
+ return EINVAL;
+
+ if(!(mem = memalign(align, size)) )
+ return ENOMEM;
+
+ *memptr = mem;
+ return 0;
+}
+
+#if __STD_C
+extern Void_t* valloc(reg size_t size)
+#else
+extern Void_t* valloc(size)
+reg size_t size;
+#endif
+{
+ VMFLINIT();
+
+ GETPAGESIZE(_Vmpagesize);
+ return VMRECORD(memalign(_Vmpagesize, size));
+}
+
+#if __STD_C
+extern Void_t* pvalloc(reg size_t size)
+#else
+extern Void_t* pvalloc(size)
+reg size_t size;
+#endif
+{
+ VMFLINIT();
+
+ GETPAGESIZE(_Vmpagesize);
+ return VMRECORD(memalign(_Vmpagesize, ROUND(size,_Vmpagesize)) );
+}
+
+#if !_PACKAGE_ast
+#if __STD_C
+char* strdup(const char* s)
+#else
+char* strdup(s)
+char* s;
+#endif
+{
+ char *ns;
+ size_t n;
+
+ if(!s)
+ return NIL(char*);
+ else
+ { n = strlen(s);
+ if((ns = malloc(n+1)) )
+ memcpy(ns,s,n+1);
+ return ns;
+ }
+}
+#endif /* _PACKAGE_ast */
+
+#if !_lib_alloca || _mal_alloca
+#ifndef _stk_down
+#define _stk_down 0
+#endif
+typedef struct _alloca_s Alloca_t;
+union _alloca_u
+{ struct
+ { char* addr;
+ Alloca_t* next;
+ } head;
+ char array[ALIGN];
+};
+struct _alloca_s
+{ union _alloca_u head;
+ Vmuchar_t data[1];
+};
+
+#if __STD_C
+extern Void_t* alloca(size_t size)
+#else
+extern Void_t* alloca(size)
+size_t size;
+#endif
+{ char array[ALIGN];
+ char* file;
+ int line;
+ Void_t* func;
+ Alloca_t* f;
+ Vmalloc_t *vm;
+ static Alloca_t* Frame;
+
+ VMFLINIT();
+
+ VMFLF(Vmregion,file,line,func); /* save info before freeing frames */
+
+ while(Frame) /* free unused frames */
+ { if(( _stk_down && &array[0] > Frame->head.head.addr) ||
+ (!_stk_down && &array[0] < Frame->head.head.addr) )
+ { f = Frame; Frame = f->head.head.next;
+ if((vm = regionof(f)) )
+ (void)(*vm->meth.freef)(vm, f, 0);
+ /* else: something bad happened. just keep going */
+ }
+ else break;
+ }
+
+ Vmregion->file = file; /* restore file/line info before allocation */
+ Vmregion->line = line;
+ Vmregion->func = func;
+
+ f = (Alloca_t*)(*Vmregion->meth.allocf)(Vmregion, size+sizeof(Alloca_t)-1, 0);
+
+ /* if f is NULL, this mimics a stack overflow with a memory error! */
+ f->head.head.addr = &array[0];
+ f->head.head.next = Frame;
+ Frame = f;
+
+ return (Void_t*)f->data;
+}
+#endif /*!_lib_alloca || _mal_alloca*/
+
+#if _map_malloc
+
+/* not sure of all the implications -- 0 is conservative for now */
+#define USE_NATIVE 0 /* native free/realloc on non-vmalloc ptrs */
+
+#else
+
+#if _malloc_hook
+
+static void vm_free_hook(void* ptr, const void* caller)
+{
+ free(ptr);
+}
+
+static void* vm_malloc_hook(size_t size, const void* caller)
+{
+ void* r;
+
+ r = malloc(size);
+ return r;
+}
+
+static void* vm_memalign_hook(size_t align, size_t size, const void* caller)
+{
+ void* r;
+
+ r = memalign(align, size);
+ return r;
+}
+
+static void* vm_realloc_hook(void* ptr, size_t size, const void* caller)
+{
+ void* r;
+
+ r = realloc(ptr, size);
+ return r;
+}
+
+static void vm_initialize_hook(void)
+{
+ __free_hook = vm_free_hook;
+ __malloc_hook = vm_malloc_hook;
+ __memalign_hook = vm_memalign_hook;
+ __realloc_hook = vm_realloc_hook;
+}
+
+void (*__malloc_initialize_hook)(void) = vm_initialize_hook;
+
+#if 0 /* 2012-02-29 this may be needed to cover shared libs */
+
+void __attribute__ ((constructor)) vm_initialize_initialize_hook(void)
+{
+ vm_initialize_hook();
+ __malloc_initialize_hook = vm_initialize_hook;
+}
+
+#endif
+
+#else
+
+/* intercept _* __* __libc_* variants */
+
+#if __lib__malloc
+extern Void_t* F2(_calloc, size_t,n, size_t,m) { return calloc(n, m); }
+extern Void_t F1(_cfree, Void_t*,p) { free(p); }
+extern Void_t F1(_free, Void_t*,p) { free(p); }
+extern Void_t* F1(_malloc, size_t,n) { return malloc(n); }
+#if _lib_memalign
+extern Void_t* F2(_memalign, size_t,a, size_t,n) { return memalign(a, n); }
+#endif
+#if _lib_pvalloc
+extern Void_t* F1(_pvalloc, size_t,n) { return pvalloc(n); }
+#endif
+extern Void_t* F2(_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
+#if _lib_valloc
+extern Void_t* F1(_valloc, size_t,n) { return valloc(n); }
+#endif
+#endif
+
+#if _lib___malloc
+extern Void_t* F2(__calloc, size_t,n, size_t,m) { return calloc(n, m); }
+extern Void_t F1(__cfree, Void_t*,p) { free(p); }
+extern Void_t F1(__free, Void_t*,p) { free(p); }
+extern Void_t* F1(__malloc, size_t,n) { return malloc(n); }
+#if _lib_memalign
+extern Void_t* F2(__memalign, size_t,a, size_t,n) { return memalign(a, n); }
+#endif
+#if _lib_pvalloc
+extern Void_t* F1(__pvalloc, size_t,n) { return pvalloc(n); }
+#endif
+extern Void_t* F2(__realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
+#if _lib_valloc
+extern Void_t* F1(__valloc, size_t,n) { return valloc(n); }
+#endif
+#endif
+
+#if _lib___libc_malloc
+extern Void_t* F2(__libc_calloc, size_t,n, size_t,m) { return calloc(n, m); }
+extern Void_t F1(__libc_cfree, Void_t*,p) { free(p); }
+extern Void_t F1(__libc_free, Void_t*,p) { free(p); }
+extern Void_t* F1(__libc_malloc, size_t,n) { return malloc(n); }
+#if _lib_memalign
+extern Void_t* F2(__libc_memalign, size_t,a, size_t,n) { return memalign(a, n); }
+#endif
+#if _lib_pvalloc
+extern Void_t* F1(__libc_pvalloc, size_t,n) { return pvalloc(n); }
+#endif
+extern Void_t* F2(__libc_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
+#if _lib_valloc
+extern Void_t* F1(__libc_valloc, size_t,n) { return valloc(n); }
+#endif
+#endif
+
+#endif /* _malloc_hook */
+
+#endif /* _map_malloc */
+
+#undef extern
+
+#if _hdr_malloc /* need the mallint interface for statistics, etc. */
+
+#undef calloc
+#define calloc ______calloc
+#undef cfree
+#define cfree ______cfree
+#undef free
+#define free ______free
+#undef malloc
+#define malloc ______malloc
+#undef pvalloc
+#define pvalloc ______pvalloc
+#undef realloc
+#define realloc ______realloc
+#undef valloc
+#define valloc ______valloc
+
+#if !_UWIN
+
+#include <malloc.h>
+
+typedef struct mallinfo Mallinfo_t;
+typedef struct mstats Mstats_t;
+
+#endif
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#if _lib_mallopt
+#if __STD_C
+extern int mallopt(int cmd, int value)
+#else
+extern int mallopt(cmd, value)
+int cmd;
+int value;
+#endif
+{
+ VMFLINIT();
+ return 0;
+}
+#endif /*_lib_mallopt*/
+
+#if _lib_mallinfo && _mem_arena_mallinfo
+#if __STD_C
+extern Mallinfo_t mallinfo(void)
+#else
+extern Mallinfo_t mallinfo()
+#endif
+{
+ Vmstat_t sb;
+ Mallinfo_t mi;
+
+ VMFLINIT();
+ memset(&mi,0,sizeof(mi));
+ if(vmstat(Vmregion,&sb) >= 0)
+ { mi.arena = sb.extent;
+ mi.ordblks = sb.n_busy+sb.n_free;
+ mi.uordblks = sb.s_busy;
+ mi.fordblks = sb.s_free;
+ }
+ return mi;
+}
+#endif /* _lib_mallinfo */
+
+#if _lib_mstats && _mem_bytes_total_mstats
+#if __STD_C
+extern Mstats_t mstats(void)
+#else
+extern Mstats_t mstats()
+#endif
+{
+ Vmstat_t sb;
+ Mstats_t ms;
+
+ VMFLINIT();
+ memset(&ms,0,sizeof(ms));
+ if(vmstat(Vmregion,&sb) >= 0)
+ { ms.bytes_total = sb.extent;
+ ms.chunks_used = sb.n_busy;
+ ms.bytes_used = sb.s_busy;
+ ms.chunks_free = sb.n_free;
+ ms.bytes_free = sb.s_free;
+ }
+ return ms;
+}
+#endif /*_lib_mstats*/
+
+#undef extern
+
+#endif/*_hdr_malloc*/
+
+#else
+
+/*
+ * even though there is no malloc override, still provide
+ * _ast_* counterparts for object compatibility
+ */
+
+#define setregmax(n)
+
+#undef calloc
+extern Void_t* calloc _ARG_((size_t, size_t));
+
+#undef cfree
+extern void cfree _ARG_((Void_t*));
+
+#undef free
+extern void free _ARG_((Void_t*));
+
+#undef malloc
+extern Void_t* malloc _ARG_((size_t));
+
+#if _lib_memalign
+#undef memalign
+extern Void_t* memalign _ARG_((size_t, size_t));
+#endif
+
+#if _lib_pvalloc
+#undef pvalloc
+extern Void_t* pvalloc _ARG_((size_t));
+#endif
+
+#undef realloc
+extern Void_t* realloc _ARG_((Void_t*, size_t));
+
+#if _lib_valloc
+#undef valloc
+extern Void_t* valloc _ARG_((size_t));
+#endif
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#if !_malloc_hook
+
+extern Void_t F1(_ast_free, Void_t*,p) { free(p); }
+extern Void_t* F1(_ast_malloc, size_t,n) { return malloc(n); }
+#if _lib_memalign
+extern Void_t* F2(_ast_memalign, size_t,a, size_t,n) { return memalign(a, n); }
+#endif
+extern Void_t* F2(_ast_realloc, Void_t*,p, size_t,n) { return realloc(p, n); }
+
+#endif
+
+extern Void_t* F2(_ast_calloc, size_t,n, size_t,m) { return calloc(n, m); }
+extern Void_t F1(_ast_cfree, Void_t*,p) { free(p); }
+#if _lib_pvalloc
+extern Void_t* F1(_ast_pvalloc, size_t,n) { return pvalloc(n); }
+#endif
+#if _lib_valloc
+extern Void_t* F1(_ast_valloc, size_t,n) { return valloc(n); }
+#endif
+
+#undef extern
+
+#if _hdr_malloc
+
+#undef mallinfo
+#undef mallopt
+#undef mstats
+
+#define calloc ______calloc
+#define cfree ______cfree
+#define free ______free
+#define malloc ______malloc
+#define pvalloc ______pvalloc
+#define realloc ______realloc
+#define valloc ______valloc
+
+#if !_UWIN
+
+#if !_malloc_hook
+
+#include <malloc.h>
+
+#endif
+
+typedef struct mallinfo Mallinfo_t;
+typedef struct mstats Mstats_t;
+
+#endif
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#if _lib_mallopt
+extern int F2(_ast_mallopt, int,cmd, int,value) { return mallopt(cmd, value); }
+#endif
+
+#if _lib_mallinfo && _mem_arena_mallinfo
+extern Mallinfo_t F0(_ast_mallinfo, void) { return mallinfo(); }
+#endif
+
+#if _lib_mstats && _mem_bytes_total_mstats
+extern Mstats_t F0(_ast_mstats, void) { return mstats(); }
+#endif
+
+#undef extern
+
+#endif /*_hdr_malloc*/
+
+#endif /*!_std_malloc*/
+
+#if __STD_C
+static Vmulong_t atou(char** sp)
+#else
+static Vmulong_t atou(sp)
+char** sp;
+#endif
+{
+ char* s = *sp;
+ Vmulong_t v = 0;
+
+ if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X') )
+ { for(s += 2; *s; ++s)
+ { if(*s >= '0' && *s <= '9')
+ v = (v << 4) + (*s - '0');
+ else if(*s >= 'a' && *s <= 'f')
+ v = (v << 4) + (*s - 'a') + 10;
+ else if(*s >= 'A' && *s <= 'F')
+ v = (v << 4) + (*s - 'A') + 10;
+ else break;
+ }
+ }
+ else
+ { for(; *s; ++s)
+ { if(*s >= '0' && *s <= '9')
+ v = v*10 + (*s - '0');
+ else break;
+ }
+ }
+
+ *sp = s;
+ return v;
+}
+
+#if __STD_C
+static char* insertpid(char* begs, char* ends)
+#else
+static char* insertpid(begs,ends)
+char* begs;
+char* ends;
+#endif
+{ int pid;
+ char* s;
+
+ if((pid = getpid()) < 0)
+ return NIL(char*);
+
+ s = ends;
+ do
+ { if(s == begs)
+ return NIL(char*);
+ *--s = '0' + pid%10;
+ } while((pid /= 10) > 0);
+ while(s < ends)
+ *begs++ = *s++;
+
+ return begs;
+}
+
+#if __STD_C
+static int createfile(char* file)
+#else
+static int createfile(file)
+char* file;
+#endif
+{
+ char buf[1024];
+ char *next, *endb;
+ int fd;
+
+ next = buf;
+ endb = buf + sizeof(buf);
+ while(*file)
+ { if(*file == '%')
+ { switch(file[1])
+ {
+ case 'p' :
+ if(!(next = insertpid(next,endb)) )
+ return -1;
+ file += 2;
+ break;
+ default :
+ goto copy;
+ }
+ }
+ else
+ { copy:
+ *next++ = *file++;
+ }
+
+ if(next >= endb)
+ return -1;
+ }
+
+ *next = '\0';
+ file = buf;
+ if (*file == '&' && *(file += 1) || strncmp(file, "/dev/fd/", 8) == 0 && *(file += 8))
+ fd = dup((int)atou(&file));
+ else if (*file)
+#if _PACKAGE_ast
+ fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, CREAT_MODE);
+#else
+ fd = creat(file, CREAT_MODE);
+#endif
+ else
+ return -1;
+#if _PACKAGE_ast
+#ifdef FD_CLOEXEC
+ if (fd >= 0)
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+#endif
+ return fd;
+}
+
+#if __STD_C
+static void pfprint(void)
+#else
+static void pfprint()
+#endif
+{
+ if(Vmregion->meth.meth == VM_MTPROFILE)
+ vmprofile(Vmregion,_Vmpffd);
+}
+
+/*
+ * initialize runtime options from the VMALLOC_OPTIONS env var
+ */
+
+#define COPY(t,e,f) while ((*t = *f++) && t < e) t++
+
+#if __STD_C
+void _vmoptions(void)
+#else
+void _vmoptions()
+#endif
+{
+ Vmalloc_t* vm = 0;
+ char* trace = 0;
+ char* s;
+ char* t;
+ char* v;
+ Vmulong_t n;
+ int fd;
+ char buf[1024];
+
+ _Vmoptions = 1;
+ t = buf;
+ v = &buf[sizeof(buf)-1];
+ if (s = getenv("VMALLOC_OPTIONS"))
+ COPY(t, v, s);
+ if (t > buf)
+ {
+ *t = 0;
+ s = buf;
+ for (;;)
+ {
+ while (*s == ',' || *s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
+ s++;
+ if (!*(t = s))
+ break;
+ v = 0;
+ while (*s)
+ if (*s == ',' || *s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
+ {
+ *s++ = 0;
+ break;
+ }
+ else if (!v && *s == '=')
+ {
+ *s++ = 0;
+ if (!*(v = s))
+ v = 0;
+ }
+ else
+ s++;
+ if (t[0] == 'n' && t[1] == 'o')
+ continue;
+ switch (t[0])
+ {
+ case 'a': /* abort */
+ if (!vm)
+ vm = vmopen(Vmdcsystem, Vmdebug, 0);
+ if (vm && vm->meth.meth == VM_MTDEBUG)
+ vmset(vm, VM_DBABORT, 1);
+ else
+ _Vmassert |= VM_abort;
+ break;
+ case 'b': /* break */
+ _Vmassert |= VM_break;
+ break;
+ case 'c': /* check */
+ _Vmassert |= VM_check;
+ break;
+ case 'f': /* free */
+ _Vmassert |= VM_free;
+ break;
+ case 'k': /* keep */
+ _Vmassert |= VM_keep;
+ break;
+ case 'm':
+ if (v && !vm)
+ {
+ if ((v[0] == 'V' || v[0] == 'v') && (v[1] == 'M' || v[1] == 'm'))
+ v += 2;
+ if (strcmp(v, "debug") == 0)
+ vm = vmopen(Vmdcsystem, Vmdebug, 0);
+ else if (strcmp(v, "profile") == 0)
+ vm = vmopen(Vmdcsystem, Vmprofile, 0);
+ else if (strcmp(v, "last") == 0)
+ vm = vmopen(Vmdcsystem, Vmlast, 0);
+ else if (strcmp(v, "best") == 0)
+ vm = Vmheap;
+ }
+ break;
+ case 'p':
+ if (v)
+ switch (t[1])
+ {
+ case 'e': /* period=<count> */
+ if (!vm)
+ vm = vmopen(Vmdcsystem, Vmdebug, 0);
+ if (vm && vm->meth.meth == VM_MTDEBUG)
+ _Vmdbcheck = atou(&v);
+ break;
+ case 'r': /* profile=<path> */
+ if (!vm)
+ vm = vmopen(Vmdcsystem, Vmprofile, 0);
+ if (v && vm && vm->meth.meth == VM_MTPROFILE)
+ _Vmpffd = createfile(v);
+ break;
+ }
+ break;
+ case 's': /* start=<count> */
+ if (!vm)
+ vm = vmopen(Vmdcsystem, Vmdebug, 0);
+ if (v && vm && vm->meth.meth == VM_MTDEBUG)
+ _Vmdbstart = atou(&v);
+ break;
+ case 't': /* trace=<path> */
+ trace = v;
+ break;
+ case 'w':
+ if (t[1] == 'a')
+ switch (t[2])
+ {
+ case 'r': /* warn=<path> */
+ if (!vm)
+ vm = vmopen(Vmdcsystem, Vmdebug, 0);
+ if (v && vm && vm->meth.meth == VM_MTDEBUG && (fd = createfile(v)) >= 0)
+ vmdebug(fd);
+ break;
+ case 't': /* watch=<addr> */
+ if (!vm)
+ vm = vmopen(Vmdcsystem, Vmdebug, 0);
+ if (v && vm && vm->meth.meth == VM_MTDEBUG && (n = atou(&v)) >= 0)
+ vmdbwatch((Void_t*)n);
+ break;
+ }
+ break;
+ }
+ }
+ }
+
+ /* slip in the new region now so that malloc() will work fine */
+
+ if (vm)
+ {
+ if (vm->meth.meth == VM_MTDEBUG)
+ _Vmdbcheck = 1;
+ Vmregion = vm;
+ }
+
+ /* enable tracing -- this currently disables multiple regions */
+
+ if (trace)
+ {
+ setregmax(0);
+ if ((fd = createfile(trace)) >= 0)
+ {
+ vmset(Vmregion, VM_TRACE, 1);
+ vmtrace(fd);
+ }
+ }
+ else if (Vmregion != Vmheap || asometh(0, 0)->type == ASO_SIGNAL)
+ setregmax(0);
+
+ /* make sure that profile data is output upon exiting */
+
+ if (vm && vm->meth.meth == VM_MTPROFILE)
+ {
+ if (_Vmpffd < 0)
+ _Vmpffd = 2;
+ /* this may wind up calling malloc(), but region is ok now */
+ atexit(pfprint);
+ }
+ else if (_Vmpffd >= 0)
+ {
+ close(_Vmpffd);
+ _Vmpffd = -1;
+ }
+}
+
+/*
+ * ast semi-private workaround for system functions
+ * that misbehave by passing bogus addresses to free()
+ *
+ * not prototyped in any header to keep it ast semi-private
+ *
+ * to keep malloc() data by disabling free()
+ * extern _vmkeep(int);
+ * int r = _vmkeep(1);
+ * and to restore to the previous state
+ * (void)_vmkeep(r);
+ */
+
+int
+#if __STD_C
+_vmkeep(int v)
+#else
+_vmkeep(v)
+int v;
+#endif
+{
+ int r;
+
+ r = !!(_Vmassert & VM_keep);
+ if (v)
+ _Vmassert |= VM_keep;
+ else
+ _Vmassert &= ~VM_keep;
+ return r;
+}
+
+#endif /*_UWIN*/
diff --git a/src/lib/libast/vmalloc/vmbest.c b/src/lib/libast/vmalloc/vmbest.c
new file mode 100644
index 0000000..553d83a
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmbest.c
@@ -0,0 +1,1390 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmbest(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Best-fit allocation method. This is based on a best-fit strategy
+** using a splay tree for storage of lists of free blocks of the same
+** size. Recent free blocks may be cached for fast reuse.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+
+#ifdef DEBUG
+static int N_free; /* # of free calls */
+static int N_alloc; /* # of alloc calls */
+static int N_resize; /* # of resize calls */
+static int N_wild; /* # allocated from the wild block */
+static int N_last; /* # allocated from last free block */
+static int N_reclaim; /* # of bestreclaim calls */
+#endif /*DEBUG*/
+
+#define COMPACT 8 /* factor to decide when to compact */
+
+/* Check to see if a block is in the free tree */
+#if __STD_C
+static int vmintree(Block_t* node, Block_t* b)
+#else
+static int vmintree(node,b)
+Block_t* node;
+Block_t* b;
+#endif
+{ Block_t* t;
+
+ for(t = node; t; t = LINK(t))
+ if(t == b)
+ return 1;
+ if(LEFT(node) && vmintree(LEFT(node),b))
+ return 1;
+ if(RIGHT(node) && vmintree(RIGHT(node),b))
+ return 1;
+ return 0;
+}
+
+#if __STD_C
+static int vmonlist(Block_t* list, Block_t* b)
+#else
+static int vmonlist(list,b)
+Block_t* list;
+Block_t* b;
+#endif
+{
+ for(; list; list = LINK(list))
+ if(list == b)
+ return 1;
+ return 0;
+}
+
+/* Check to see if a block is known to be free */
+#if __STD_C
+static int vmisfree(Vmdata_t* vd, Block_t* b)
+#else
+static int vmisfree(vd,b)
+Vmdata_t* vd;
+Block_t* b;
+#endif
+{
+ if(SIZE(b) & (BUSY|JUNK|PFREE))
+ return 0;
+
+ if(b == vd->wild)
+ return 1;
+
+ if(SIZE(b) < MAXTINY)
+ return vmonlist(TINY(vd)[INDEX(SIZE(b))], b);
+
+ if(vd->root)
+ return vmintree(vd->root, b);
+
+ return 0;
+}
+
+/* Check to see if a block is known to be junked */
+#if __STD_C
+static int vmisjunk(Vmdata_t* vd, Block_t* b)
+#else
+static int vmisjunk(vd,b)
+Vmdata_t* vd;
+Block_t* b;
+#endif
+{
+ Block_t* t;
+
+ if((SIZE(b)&BUSY) == 0 || (SIZE(b)&JUNK) == 0)
+ return 0;
+
+ if(b == vd->free) /* recently freed */
+ return 1;
+
+ /* check the list that b is supposed to be in */
+ for(t = CACHE(vd)[C_INDEX(SIZE(b))]; t; t = LINK(t))
+ if(t == b)
+ return 1;
+
+ /* on occasions, b may be put onto the catch-all list */
+ if(C_INDEX(SIZE(b)) < S_CACHE)
+ for(t = CACHE(vd)[S_CACHE]; t; t = LINK(t))
+ if(t == b)
+ return 1;
+
+ return 0;
+}
+
+/* check to see if the free tree is in good shape */
+#if __STD_C
+static int vmchktree(Block_t* node)
+#else
+static int vmchktree(node)
+Block_t* node;
+#endif
+{ Block_t* t;
+
+ if(SIZE(node) & BITS)
+ { /**/ASSERT(0); return -1; }
+
+ for(t = LINK(node); t; t = LINK(t))
+ if(SIZE(t) != SIZE(node))
+ { /**/ASSERT(0); return -1; }
+
+ if((t = LEFT(node)) )
+ { if(SIZE(t) >= SIZE(node) )
+ { /**/ASSERT(0); return -1; }
+ else return vmchktree(t);
+ }
+ if((t = RIGHT(node)) )
+ { if(SIZE(t) <= SIZE(node) )
+ { /**/ASSERT(0); return -1; }
+ else return vmchktree(t);
+ }
+
+ return 0;
+}
+
+#if __STD_C
+int _vmbestcheck(Vmdata_t* vd, Block_t* freeb)
+#else
+int _vmbestcheck(vd, freeb)
+Vmdata_t* vd;
+Block_t* freeb; /* known to be free but not on any free list */
+#endif
+{
+ reg Seg_t *seg;
+ reg Block_t *b, *endb, *nextb;
+ int rv = 0;
+
+ if(!CHECK())
+ return 0;
+
+ /* make sure the free tree is still in shape */
+ if(vd->root && vmchktree(vd->root) < 0 )
+ { rv = -1; /**/ASSERT(0); }
+
+ for(seg = vd->seg; seg && rv == 0; seg = seg->next)
+ { b = SEGBLOCK(seg);
+ endb = (Block_t*)(seg->baddr - sizeof(Head_t));
+ for(; b < endb && rv == 0; b = nextb)
+ { nextb = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) );
+
+ if(!ISBUSY(SIZE(b)) ) /* a completely free block */
+ { /* there should be no marked bits of any type */
+ if(SIZE(b) & (BUSY|JUNK|PFREE) )
+ { rv = -1; /**/ASSERT(0); }
+
+ /* next block must be busy and marked PFREE */
+ if(!ISBUSY(SIZE(nextb)) || !ISPFREE(SIZE(nextb)) )
+ { rv = -1; /**/ASSERT(0); }
+
+ /* must have a self-reference pointer */
+ if(SELF(b) != b)
+ { rv = -1; /**/ASSERT(0); }
+
+ /* segment pointer should be well-defined */
+ if(!TINIEST(b) && SEG(b) != seg)
+ { rv = -1; /**/ASSERT(0); }
+
+ /* must be on a free list */
+ if(b != freeb && !vmisfree(vd, b) )
+ { rv = -1; /**/ASSERT(0); }
+ }
+ else
+ { /* segment pointer should be well-defined */
+ if(SEG(b) != seg)
+ { rv = -1; /**/ASSERT(0); }
+
+ /* next block should not be marked PFREE */
+ if(ISPFREE(SIZE(nextb)) )
+ { rv = -1; /**/ASSERT(0); }
+
+ /* if PFREE, last block should be free */
+ if(ISPFREE(SIZE(b)) && LAST(b) != freeb &&
+ !vmisfree(vd, LAST(b)) )
+ { rv = -1; /**/ASSERT(0); }
+
+ /* if free but unreclaimed, should be junk */
+ if(ISJUNK(SIZE(b)) && !vmisjunk(vd, b))
+ { rv = -1; /**/ASSERT(0); }
+ }
+ }
+ }
+
+ return rv;
+}
+
+/* Tree rotation functions */
+#define RROTATE(x,y) (LEFT(x) = RIGHT(y), RIGHT(y) = (x), (x) = (y))
+#define LROTATE(x,y) (RIGHT(x) = LEFT(y), LEFT(y) = (x), (x) = (y))
+#define RLINK(s,x) ((s) = LEFT(s) = (x))
+#define LLINK(s,x) ((s) = RIGHT(s) = (x))
+
+/* Find and delete a suitable element in the free tree. */
+#if __STD_C
+static Block_t* bestsearch(Vmdata_t* vd, reg size_t size, Block_t* wanted)
+#else
+static Block_t* bestsearch(vd, size, wanted)
+Vmdata_t* vd;
+reg size_t size;
+Block_t* wanted;
+#endif
+{
+ reg size_t s;
+ reg Block_t *t, *root, *l, *r;
+ Block_t link;
+
+ /* extracting a tiniest block from its list */
+ if((root = wanted) && size == TINYSIZE)
+ { reg Seg_t* seg;
+
+ l = TLEFT(root);
+ if((r = LINK(root)) )
+ TLEFT(r) = l;
+ if(l)
+ LINK(l) = r;
+ else TINY(vd)[0] = r;
+
+ seg = vd->seg;
+ if(!seg->next)
+ SEG(root) = seg;
+ else for(;; seg = seg->next)
+ { if((Vmuchar_t*)root > (Vmuchar_t*)seg->addr &&
+ (Vmuchar_t*)root < seg->baddr)
+ { SEG(root) = seg;
+ break;
+ }
+ }
+
+ return root;
+ }
+
+ /**/ASSERT(!vd->root || vmchktree(vd->root) == 0);
+
+ /* find the right one to delete */
+ l = r = &link;
+ if((root = vd->root) ) do
+ { /**/ ASSERT(!ISBITS(size) && !ISBITS(SIZE(root)));
+ if(size == (s = SIZE(root)) )
+ break;
+ if(size < s)
+ { if((t = LEFT(root)) )
+ { if(size <= (s = SIZE(t)) )
+ { RROTATE(root,t);
+ if(size == s)
+ break;
+ t = LEFT(root);
+ }
+ else
+ { LLINK(l,t);
+ t = RIGHT(t);
+ }
+ }
+ RLINK(r,root);
+ }
+ else
+ { if((t = RIGHT(root)) )
+ { if(size >= (s = SIZE(t)) )
+ { LROTATE(root,t);
+ if(size == s)
+ break;
+ t = RIGHT(root);
+ }
+ else
+ { RLINK(r,t);
+ t = LEFT(t);
+ }
+ }
+ LLINK(l,root);
+ }
+ /**/ ASSERT(root != t);
+ } while((root = t) );
+
+ if(root) /* found it, now isolate it */
+ { RIGHT(l) = LEFT(root);
+ LEFT(r) = RIGHT(root);
+ }
+ else /* nothing exactly fit */
+ { LEFT(r) = NIL(Block_t*);
+ RIGHT(l) = NIL(Block_t*);
+
+ /* grab the least one from the right tree */
+ if((root = LEFT(&link)) )
+ { while((t = LEFT(root)) )
+ RROTATE(root,t);
+ LEFT(&link) = RIGHT(root);
+ }
+ }
+
+ if(root && (r = LINK(root)) )
+ { /* head of a link list, use next one for root */
+ LEFT(r) = RIGHT(&link);
+ RIGHT(r) = LEFT(&link);
+ }
+ else if(!(r = LEFT(&link)) )
+ r = RIGHT(&link);
+ else /* graft left tree to right tree */
+ { while((t = LEFT(r)) )
+ RROTATE(r,t);
+ LEFT(r) = RIGHT(&link);
+ }
+ vd->root = r; /**/ASSERT(!r || !ISBITS(SIZE(r)));
+
+ /**/ASSERT(!vd->root || vmchktree(vd->root) == 0);
+ /**/ASSERT(!wanted || wanted == root);
+
+ return root;
+}
+
+/* Reclaim all delayed free blocks into the free tree */
+#if __STD_C
+static int bestreclaim(reg Vmdata_t* vd, Block_t* wanted, int c)
+#else
+static int bestreclaim(vd, wanted, c)
+reg Vmdata_t* vd;
+Block_t* wanted;
+int c;
+#endif
+{
+ reg size_t size, s;
+ reg Block_t *fp, *np, *t, *list;
+ reg int n, saw_wanted;
+
+ /**/COUNT(N_reclaim);
+ /**/ASSERT(_vmbestcheck(vd, NIL(Block_t*)) == 0);
+
+ if((fp = vd->free) )
+ { LINK(fp) = CACHE(vd)[S_CACHE]; CACHE(vd)[S_CACHE] = fp;
+ vd->free = NIL(Block_t*);
+ }
+
+ saw_wanted = wanted ? 0 : 1;
+ for(n = S_CACHE; n >= c; --n)
+ { list = CACHE(vd)[n]; CACHE(vd)[n] = NIL(Block_t*);
+ while((fp = list) )
+ { /* Note that below here we allow ISJUNK blocks to be
+ ** forward-merged even though they are not removed from
+ ** the list immediately. In this way, the list is
+ ** scanned only once. It works because the LINK and SIZE
+ ** fields are not destroyed during the merging. This can
+ ** be seen by observing that a tiniest block has a 2-word
+ ** header and a 2-word body. Merging a tiniest block
+ ** (1seg) and the next block (2seg) looks like this:
+ ** 1seg size link left 2seg size link left ....
+ ** 1seg size link left rite xxxx xxxx .... self
+ ** After the merge, the 2seg word is replaced by the RIGHT
+ ** pointer of the new block and somewhere beyond the
+ ** two xxxx fields, the SELF pointer will replace some
+ ** other word. The important part is that the two xxxx
+ ** fields are kept intact.
+ */
+ list = LINK(list); /**/ASSERT(!vmonlist(list,fp));
+
+ size = SIZE(fp);
+ if(!ISJUNK(size)) /* already done */
+ continue;
+
+ if(ISPFREE(size)) /* backward merge */
+ { fp = LAST(fp);
+ s = SIZE(fp); /**/ASSERT(!(s&BITS));
+ REMOVE(vd,fp,INDEX(s),t,bestsearch);
+ size = (size&~BITS) + s + sizeof(Head_t);
+ }
+ else size &= ~BITS;
+
+ for(;;) /* forward merge */
+ { np = (Block_t*)((Vmuchar_t*)fp+size+sizeof(Head_t));
+ s = SIZE(np); /**/ASSERT(s > 0);
+ if(!ISBUSY(s))
+ { /**/ASSERT((s&BITS) == 0);
+ if(np == vd->wild)
+ vd->wild = NIL(Block_t*);
+ else REMOVE(vd,np,INDEX(s),t,bestsearch);
+ }
+ else if(ISJUNK(s))
+ { /* reclaim any touched junk list */
+ if((int)C_INDEX(s) < c)
+ c = C_INDEX(s);
+ SIZE(np) = 0;
+ CLRBITS(s);
+ }
+ else break;
+ size += s + sizeof(Head_t);
+ }
+ SIZE(fp) = size;
+
+ /* tell next block that this one is free */
+ np = NEXT(fp); /**/ASSERT(ISBUSY(SIZE(np)));
+ /**/ASSERT(!ISJUNK(SIZE(np)));
+ SETPFREE(SIZE(np));
+ SELF(fp) = fp;
+
+ if(fp == wanted) /* to be consumed soon */
+ { /**/ASSERT(!saw_wanted); /* should be seen just once */
+ saw_wanted = 1;
+ continue;
+ }
+
+ /* wilderness preservation */
+ if(np->body.data >= vd->seg->baddr)
+ { vd->wild = fp;
+ continue;
+ }
+
+ /* tiny block goes to tiny list */
+ if(size < MAXTINY)
+ { s = INDEX(size);
+ np = LINK(fp) = TINY(vd)[s];
+ if(s == 0) /* TINIEST block */
+ { if(np)
+ TLEFT(np) = fp;
+ TLEFT(fp) = NIL(Block_t*);
+ }
+ else
+ { if(np)
+ LEFT(np) = fp;
+ LEFT(fp) = NIL(Block_t*);
+ SETLINK(fp);
+ }
+ TINY(vd)[s] = fp;
+ continue;
+ }
+
+ LEFT(fp) = RIGHT(fp) = LINK(fp) = NIL(Block_t*);
+ if(!(np = vd->root) ) /* inserting into an empty tree */
+ { vd->root = fp;
+ continue;
+ }
+
+ size = SIZE(fp);
+ while(1) /* leaf insertion */
+ { /**/ASSERT(np != fp);
+ if((s = SIZE(np)) > size)
+ { if((t = LEFT(np)) )
+ { /**/ ASSERT(np != t);
+ np = t;
+ }
+ else
+ { LEFT(np) = fp;
+ break;
+ }
+ }
+ else if(s < size)
+ { if((t = RIGHT(np)) )
+ { /**/ ASSERT(np != t);
+ np = t;
+ }
+ else
+ { RIGHT(np) = fp;
+ break;
+ }
+ }
+ else /* s == size */
+ { if((t = LINK(np)) )
+ { LINK(fp) = t;
+ LEFT(t) = fp;
+ }
+ LINK(np) = fp;
+ LEFT(fp) = np;
+ SETLINK(fp);
+ break;
+ }
+ }
+ }
+ }
+
+ /**/ASSERT(!wanted || saw_wanted == 1);
+ /**/ASSERT(_vmbestcheck(vd, wanted) == 0);
+ return saw_wanted;
+}
+
+#if __STD_C
+static int bestcompact(Vmalloc_t* vm, int local)
+#else
+static int bestcompact(vm, local)
+Vmalloc_t* vm;
+int local;
+#endif
+{
+ reg Seg_t *seg, *next;
+ reg Block_t *bp, *tp;
+ reg size_t size, segsize, round;
+ reg Vmdata_t* vd = vm->data;
+
+ SETLOCK(vm, local);
+
+ bestreclaim(vd,NIL(Block_t*),0);
+
+ for(seg = vd->seg; seg; seg = next)
+ { next = seg->next;
+
+ bp = BLOCK(seg->baddr);
+ if(!ISPFREE(SIZE(bp)) )
+ continue;
+
+ bp = LAST(bp); /**/ASSERT(vmisfree(vd,bp));
+ size = SIZE(bp);
+ if(bp == vd->wild)
+ { /* During large block allocations, _Vmextend might
+ ** have been enlarged the rounding factor. Reducing
+ ** it a bit help avoiding getting large raw memory.
+ */
+ if((round = vm->disc->round) == 0)
+ round = _Vmpagesize;
+ if(size > COMPACT*vd->incr && vd->incr > round)
+ vd->incr /= 2;
+
+ /* for the bottom segment, we don't necessarily want
+ ** to return raw memory too early. vd->pool has an
+ ** approximation of the average size of recently freed
+ ** blocks. If this is large, the application is managing
+ ** large blocks so we throttle back memory chopping
+ ** to avoid thrashing the underlying memory system.
+ */
+ if(size <= COMPACT*vd->incr || size <= COMPACT*vd->pool)
+ continue;
+
+ vd->wild = NIL(Block_t*);
+ vd->pool = 0;
+ }
+ else REMOVE(vd,bp,INDEX(size),tp,bestsearch);
+ tp = NEXT(bp); /* avoid strict-aliasing pun */
+ CLRPFREE(SIZE(tp));
+
+ if(size < (segsize = seg->size))
+ size += sizeof(Head_t);
+
+ if((size = (*_Vmtruncate)(vm,seg,size,0)) > 0)
+ { if(size >= segsize) /* entire segment deleted */
+ continue;
+ /**/ASSERT(SEG(BLOCK(seg->baddr)) == seg);
+
+ if((size = (seg->baddr - ((Vmuchar_t*)bp) - sizeof(Head_t))) > 0)
+ SIZE(bp) = size - sizeof(Head_t);
+ else bp = NIL(Block_t*);
+ }
+
+ if(bp)
+ { /**/ ASSERT(SIZE(bp) >= BODYSIZE);
+ /**/ ASSERT(SEGWILD(bp));
+ /**/ ASSERT(!vd->root || !vmintree(vd->root,bp));
+ SIZE(bp) |= BUSY|JUNK;
+ LINK(bp) = CACHE(vd)[C_INDEX(SIZE(bp))];
+ CACHE(vd)[C_INDEX(SIZE(bp))] = bp;
+ }
+ }
+
+ if(!local && _Vmtrace && (vd->mode&VM_TRACE) && VMETHOD(vd) == VM_MTBEST)
+ (*_Vmtrace)(vm, (Vmuchar_t*)0, (Vmuchar_t*)0, 0, 0);
+
+ CLRLOCK(vm, local); /**/ASSERT(_vmbestcheck(vd, NIL(Block_t*)) == 0);
+
+ return 0;
+}
+
+#if __STD_C
+static Void_t* bestalloc(Vmalloc_t* vm, size_t size , int local)
+#else
+static Void_t* bestalloc(vm, size, local)
+Vmalloc_t* vm; /* region allocating from */
+size_t size; /* desired block size */
+int local; /* internal call */
+#endif
+{
+ reg Vmdata_t* vd = vm->data;
+ reg size_t s;
+ reg int n;
+ reg Block_t *tp, *np, *ap;
+ size_t orgsize = size;
+
+ /**/COUNT(N_alloc);
+ /**/ASSERT(local ? (vd->lock == 1) : 1 );
+
+ SETLOCK(vm,local);
+
+ /**/ ASSERT(_vmbestcheck(vd, NIL(Block_t*)) == 0);
+ /**/ ASSERT(HEADSIZE == sizeof(Head_t));
+ /**/ ASSERT(BODYSIZE == sizeof(Body_t));
+ /**/ ASSERT((ALIGN%(BITS+1)) == 0 );
+ /**/ ASSERT((sizeof(Head_t)%ALIGN) == 0 );
+ /**/ ASSERT((sizeof(Body_t)%ALIGN) == 0 );
+ /**/ ASSERT((BODYSIZE%ALIGN) == 0 );
+ /**/ ASSERT(sizeof(Block_t) == (sizeof(Body_t)+sizeof(Head_t)) );
+
+ /* for ANSI requirement that malloc(0) returns non-NULL pointer */
+ size = size <= BODYSIZE ? BODYSIZE : ROUND(size,ALIGN);
+
+ if((tp = vd->free) ) /* reuse last free piece if appropriate */
+ { /**/ASSERT(ISBUSY(SIZE(tp)) );
+ /**/ASSERT(ISJUNK(SIZE(tp)) );
+ /**/COUNT(N_last);
+
+ vd->free = NIL(Block_t*);
+ if((s = SIZE(tp)) >= size && s < (size << 1) )
+ { if(s >= size + (sizeof(Head_t)+BODYSIZE) )
+ { SIZE(tp) = size;
+ np = NEXT(tp);
+ SEG(np) = SEG(tp);
+ SIZE(np) = ((s&~BITS) - (size+sizeof(Head_t)))|JUNK|BUSY;
+ vd->free = np;
+ SIZE(tp) |= s&BITS;
+ }
+ CLRJUNK(SIZE(tp));
+ goto done;
+ }
+
+ LINK(tp) = CACHE(vd)[S_CACHE];
+ CACHE(vd)[S_CACHE] = tp;
+ }
+
+ for(n = S_CACHE; n >= 0; --n) /* best-fit except for coalescing */
+ { bestreclaim(vd,NIL(Block_t*),n);
+ if(vd->root && (tp = bestsearch(vd,size,NIL(Block_t*))) )
+ goto got_block;
+ }
+
+ /**/ASSERT(!vd->free);
+ if((tp = vd->wild) && SIZE(tp) >= size)
+ { /**/COUNT(N_wild);
+ vd->wild = NIL(Block_t*);
+ goto got_block;
+ }
+
+ /* need to extend the arena */
+ KPVCOMPACT(vm,bestcompact);
+ if((tp = (*_Vmextend)(vm,size,bestsearch)) )
+ { got_block:
+ /**/ ASSERT(!ISBITS(SIZE(tp)));
+ /**/ ASSERT(SIZE(tp) >= size);
+ /**/ ASSERT((SIZE(tp)%ALIGN) == 0);
+ /**/ ASSERT(!vd->free);
+
+ /* tell next block that we are no longer a free block */
+ np = NEXT(tp);
+ CLRPFREE(SIZE(np)); /**/ ASSERT(ISBUSY(SIZE(np)));
+
+ if((s = SIZE(tp)-size) >= (sizeof(Head_t)+BODYSIZE) )
+ { SIZE(tp) = size;
+
+ np = NEXT(tp);
+ SEG(np) = SEG(tp);
+ SIZE(np) = (s - sizeof(Head_t)) | BUSY|JUNK;
+
+ if(VMWILD(vd,np))
+ { SIZE(np) &= ~BITS;
+ SELF(np) = np;
+ ap = NEXT(np); /**/ASSERT(ISBUSY(SIZE(ap)));
+ SETPFREE(SIZE(ap));
+ vd->wild = np;
+ }
+ else vd->free = np;
+ }
+
+ SETBUSY(SIZE(tp));
+ }
+
+done:
+ if(tp && !local && (vd->mode&VM_TRACE) && _Vmtrace && VMETHOD(vd) == VM_MTBEST)
+ (*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)DATA(tp),orgsize,0);
+
+ CLRLOCK(vm,local); /**/ASSERT(_vmbestcheck(vd, NIL(Block_t*)) == 0);
+
+ return tp ? DATA(tp) : NIL(Void_t*);
+}
+
+#if __STD_C
+static long bestaddr(Vmalloc_t* vm, Void_t* addr, int local )
+#else
+static long bestaddr(vm, addr, local)
+Vmalloc_t* vm; /* region allocating from */
+Void_t* addr; /* address to check */
+int local;
+#endif
+{
+ reg Seg_t* seg;
+ reg Block_t *b, *endb;
+ reg long offset;
+ reg Vmdata_t* vd = vm->data;
+
+ /**/ASSERT(local ? (vd->lock == 1) : 1 );
+ SETLOCK(vm, local);
+
+ offset = -1L; b = endb = NIL(Block_t*);
+ for(seg = vd->seg; seg; seg = seg->next)
+ { b = SEGBLOCK(seg);
+ endb = (Block_t*)(seg->baddr - sizeof(Head_t));
+ if((Vmuchar_t*)addr > (Vmuchar_t*)b &&
+ (Vmuchar_t*)addr < (Vmuchar_t*)endb)
+ break;
+ }
+
+ if(local ) /* from bestfree or bestresize */
+ { b = BLOCK(addr);
+ if(seg && SEG(b) == seg && ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) )
+ offset = 0;
+ }
+ else if(seg)
+ { while(b < endb)
+ { reg Vmuchar_t* data = (Vmuchar_t*)DATA(b);
+ reg size_t size = SIZE(b)&~BITS;
+
+ if((Vmuchar_t*)addr >= data && (Vmuchar_t*)addr < data+size)
+ { if(ISJUNK(SIZE(b)) || !ISBUSY(SIZE(b)))
+ offset = -1L;
+ else offset = (Vmuchar_t*)addr - data;
+ goto done;
+ }
+
+ b = (Block_t*)((Vmuchar_t*)DATA(b) + size);
+ }
+ }
+
+done:
+ CLRLOCK(vm,local);
+ return offset;
+}
+
+#if __STD_C
+static int bestfree(Vmalloc_t* vm, Void_t* data, int local )
+#else
+static int bestfree(vm, data, local )
+Vmalloc_t* vm;
+Void_t* data;
+int local;
+#endif
+{
+ reg Vmdata_t* vd = vm->data;
+ reg Block_t *bp;
+ reg size_t s;
+
+#ifdef DEBUG
+ if(((char*)data - (char*)0) <= 1)
+ { _Vmassert |= VM_check;
+ _vmbestcheck(vd, NIL(Block_t*));
+ if (!data)
+ _Vmassert &= ~VM_check;
+ return 0;
+ }
+#else
+ if(!data) /* ANSI-ism */
+ return 0;
+#endif
+
+ /**/COUNT(N_free);
+ /**/ASSERT(local ? (vd->lock == 1) : 1 );
+
+ SETLOCK(vm, local);
+
+ /**/ASSERT(KPVADDR(vm, data, bestaddr) == 0);
+ /**/ASSERT(_vmbestcheck(vd, NIL(Block_t*)) == 0);
+ bp = BLOCK(data); s = SIZE(bp);
+
+ /* Keep an approximate average free block size.
+ ** This is used in bestcompact() to decide when to release
+ ** raw memory back to the underlying memory system.
+ */
+ vd->pool = (vd->pool + (s&~BITS))/2;
+
+ if(ISBUSY(s) && !ISJUNK(s))
+ { SETJUNK(SIZE(bp));
+ if(s < MAXCACHE)
+ { /**/ASSERT(!vmonlist(CACHE(vd)[INDEX(s)], bp) );
+ LINK(bp) = CACHE(vd)[INDEX(s)];
+ CACHE(vd)[INDEX(s)] = bp;
+ }
+ else if(!vd->free)
+ vd->free = bp;
+ else
+ { /**/ASSERT(!vmonlist(CACHE(vd)[S_CACHE], bp) );
+ LINK(bp) = CACHE(vd)[S_CACHE];
+ CACHE(vd)[S_CACHE] = bp;
+ }
+
+ /* coalesce on freeing large blocks to avoid fragmentation */
+ if(SIZE(bp) >= 2*vd->incr)
+ { bestreclaim(vd,NIL(Block_t*),0);
+ if(vd->wild && SIZE(vd->wild) >= COMPACT*vd->incr)
+ KPVCOMPACT(vm,bestcompact);
+ }
+ }
+
+ if(!local && _Vmtrace && (vd->mode&VM_TRACE) && VMETHOD(vd) == VM_MTBEST )
+ (*_Vmtrace)(vm,(Vmuchar_t*)data,NIL(Vmuchar_t*), (s&~BITS), 0);
+
+ CLRLOCK(vm, local); /**/ASSERT(_vmbestcheck(vd, NIL(Block_t*)) == 0);
+
+ return 0;
+}
+
+#if __STD_C
+static Void_t* bestresize(Vmalloc_t* vm, Void_t* data, reg size_t size, int type, int local)
+#else
+static Void_t* bestresize(vm, data, size, type, local)
+Vmalloc_t* vm; /* region allocating from */
+Void_t* data; /* old block of data */
+reg size_t size; /* new size */
+int type; /* !=0 to move, <0 for not copy */
+int local;
+#endif
+{
+ reg Block_t *rp, *np, *t;
+ size_t s, bs;
+ size_t oldz = 0, orgsize = size;
+ Void_t *oldd = 0, *orgdata = data;
+ Vmdata_t *vd = vm->data;
+
+ /**/COUNT(N_resize);
+ /**/ASSERT(local ? (vd->lock == 1) : 1);
+
+ if(!data) /* resizing a NULL block is the same as allocating */
+ { data = bestalloc(vm, size, local);
+ if(data && (type&VM_RSZERO) )
+ memset((Void_t*)data, 0, size);
+ return data;
+ }
+ if(size == 0) /* resizing to zero size is the same as freeing */
+ { (void)bestfree(vm, data, local);
+ return NIL(Void_t*);
+ }
+
+ SETLOCK(vm, local);
+
+ /**/ASSERT(KPVADDR(vm, data, bestaddr) == 0);
+ /**/ASSERT(_vmbestcheck(vd, NIL(Block_t*)) == 0);
+ size = size <= BODYSIZE ? BODYSIZE : ROUND(size,ALIGN);
+ rp = BLOCK(data); /**/ASSERT(ISBUSY(SIZE(rp)) && !ISJUNK(SIZE(rp)));
+ oldz = SIZE(rp); CLRBITS(oldz);
+ if(oldz < size)
+ { np = (Block_t*)((Vmuchar_t*)rp + oldz + sizeof(Head_t));
+ do /* forward merge as much as possible */
+ { s = SIZE(np); /**/ASSERT(!ISPFREE(s));
+ if(np == vd->free)
+ { vd->free = NIL(Block_t*);
+ CLRBITS(s);
+ }
+ else if(ISJUNK(s) )
+ { if(!bestreclaim(vd,np,C_INDEX(s)) )
+ /**/ASSERT(0); /* oops: did not see np! */
+ s = SIZE(np); /**/ASSERT(s%ALIGN == 0);
+ }
+ else if(!ISBUSY(s) )
+ { if(np == vd->wild)
+ vd->wild = NIL(Block_t*);
+ else REMOVE(vd,np,INDEX(s),t,bestsearch);
+ }
+ else break;
+
+ SIZE(rp) += (s += sizeof(Head_t)); /**/ASSERT((s%ALIGN) == 0);
+ np = (Block_t*)((Vmuchar_t*)np + s);
+ CLRPFREE(SIZE(np));
+ } while(SIZE(rp) < size);
+
+ if(SIZE(rp) < size && size > vd->incr && SEGWILD(rp) )
+ { reg Seg_t* seg;
+
+ s = (size - SIZE(rp)) + sizeof(Head_t); s = ROUND(s,vd->incr);
+ seg = SEG(rp);
+ if((*vm->disc->memoryf)(vm,seg->addr,seg->extent,seg->extent+s,
+ vm->disc) == seg->addr )
+ { SIZE(rp) += s;
+ seg->extent += s;
+ seg->size += s;
+ seg->baddr += s;
+ s = (SIZE(rp)&~BITS) + sizeof(Head_t);
+ np = (Block_t*)((Vmuchar_t*)rp + s);
+ SEG(np) = seg;
+ SIZE(np) = BUSY;
+ }
+ }
+ }
+
+ if((s = SIZE(rp)) >= (size + (BODYSIZE+sizeof(Head_t))) )
+ { SIZE(rp) = size;
+ np = NEXT(rp);
+ SEG(np) = SEG(rp);
+ SIZE(np) = (((s&~BITS)-size) - sizeof(Head_t))|BUSY|JUNK;
+ CPYBITS(SIZE(rp),s);
+ rp = np;
+ goto do_free;
+ }
+ else if((bs = s&~BITS) < size)
+ { if(!(type&(VM_RSMOVE|VM_RSCOPY)) )
+ data = NIL(Void_t*); /* old data is not moveable */
+ else
+ { oldd = data;
+ if((data = KPVALLOC(vm,size,bestalloc)) )
+ { if(type&VM_RSCOPY)
+ memcpy(data, oldd, bs);
+
+ do_free: /* reclaim these right away */
+ SETJUNK(SIZE(rp));
+ LINK(rp) = CACHE(vd)[S_CACHE];
+ CACHE(vd)[S_CACHE] = rp;
+ bestreclaim(vd, NIL(Block_t*), S_CACHE);
+ }
+ }
+ }
+
+ if(data && (type&VM_RSZERO) && (size = SIZE(BLOCK(data))&~BITS) > oldz )
+ memset((Void_t*)((Vmuchar_t*)data + oldz), 0, size-oldz);
+
+ if(!local && _Vmtrace && data && (vd->mode&VM_TRACE) && VMETHOD(vd) == VM_MTBEST)
+ (*_Vmtrace)(vm, (Vmuchar_t*)orgdata, (Vmuchar_t*)data, orgsize, 0);
+
+ CLRLOCK(vm, local); /**/ASSERT(_vmbestcheck(vd, NIL(Block_t*)) == 0);
+
+ return data;
+}
+
+#if __STD_C
+static long bestsize(Vmalloc_t* vm, Void_t* addr, int local )
+#else
+static long bestsize(vm, addr, local)
+Vmalloc_t* vm; /* region allocating from */
+Void_t* addr; /* address to check */
+int local;
+#endif
+{
+ Seg_t *seg;
+ Block_t *b, *endb;
+ long size;
+ Vmdata_t *vd = vm->data;
+
+ SETLOCK(vm, local);
+
+ size = -1L;
+ for(seg = vd->seg; seg; seg = seg->next)
+ { b = SEGBLOCK(seg);
+ endb = (Block_t*)(seg->baddr - sizeof(Head_t));
+ if((Vmuchar_t*)addr <= (Vmuchar_t*)b ||
+ (Vmuchar_t*)addr >= (Vmuchar_t*)endb)
+ continue;
+ while(b < endb)
+ { if(addr == DATA(b))
+ { if(!ISBUSY(SIZE(b)) || ISJUNK(SIZE(b)) )
+ size = -1L;
+ else size = (long)SIZE(b)&~BITS;
+ goto done;
+ }
+ else if((Vmuchar_t*)addr <= (Vmuchar_t*)b)
+ break;
+
+ b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) );
+ }
+ }
+
+done:
+ CLRLOCK(vm, local);
+ return size;
+}
+
+#if __STD_C
+static Void_t* bestalign(Vmalloc_t* vm, size_t size, size_t align, int local)
+#else
+static Void_t* bestalign(vm, size, align, local)
+Vmalloc_t* vm;
+size_t size;
+size_t align;
+int local;
+#endif
+{
+ Vmuchar_t *data;
+ Block_t *tp, *np;
+ Seg_t *seg;
+ size_t s, extra;
+ size_t orgsize = size, orgalign = align;
+ Vmdata_t *vd = vm->data;
+
+ if(size <= 0 || align <= 0)
+ return NIL(Void_t*);
+
+ SETLOCK(vm, local);
+
+ /**/ASSERT(_vmbestcheck(vd, NIL(Block_t*)) == 0);
+ size = size <= BODYSIZE ? BODYSIZE : ROUND(size,ALIGN);
+ align = MULTIPLE(align,ALIGN);
+
+ /* hack so that dbalign() can store header data */
+ if(VMETHOD(vd) != VM_MTDEBUG)
+ extra = 0;
+ else
+ { extra = DB_HEAD;
+ while(align < extra || (align - extra) < sizeof(Block_t))
+ align *= 2;
+ }
+
+ /* reclaim all free blocks now to avoid fragmentation */
+ bestreclaim(vd,NIL(Block_t*),0);
+
+ s = size + 2*(align+sizeof(Head_t)+extra);
+ if(!(data = (Vmuchar_t*)KPVALLOC(vm,s,bestalloc)) )
+ goto done;
+
+ tp = BLOCK(data);
+ seg = SEG(tp);
+
+ /* get an aligned address that we can live with */
+ if((s = (size_t)((VLONG(data)+extra)%align)) != 0)
+ data += align-s; /**/ASSERT(((VLONG(data)+extra)%align) == 0);
+
+ if((np = BLOCK(data)) != tp ) /* need to free left part */
+ { if(((Vmuchar_t*)np - (Vmuchar_t*)tp) < (ssize_t)(sizeof(Block_t)+extra) )
+ { data += align;
+ np = BLOCK(data);
+ } /**/ASSERT(((VLONG(data)+extra)%align) == 0);
+
+ s = (Vmuchar_t*)np - (Vmuchar_t*)tp;
+ SIZE(np) = ((SIZE(tp)&~BITS) - s)|BUSY;
+ SEG(np) = seg;
+
+ SIZE(tp) = (s - sizeof(Head_t)) | (SIZE(tp)&BITS) | JUNK;
+ /**/ ASSERT(SIZE(tp) >= sizeof(Body_t) );
+ LINK(tp) = CACHE(vd)[C_INDEX(SIZE(tp))];
+ CACHE(vd)[C_INDEX(SIZE(tp))] = tp;
+ }
+
+ /* free left-over if too big */
+ if((s = SIZE(np) - size) >= sizeof(Block_t))
+ { SIZE(np) = size;
+
+ tp = NEXT(np);
+ SIZE(tp) = ((s & ~BITS) - sizeof(Head_t)) | BUSY | JUNK;
+ SEG(tp) = seg;
+ LINK(tp) = CACHE(vd)[C_INDEX(SIZE(tp))];
+ CACHE(vd)[C_INDEX(SIZE(tp))] = tp;
+
+ SIZE(np) |= s&BITS;
+ }
+
+ bestreclaim(vd,NIL(Block_t*),0); /* coalesce all free blocks */
+
+ if(!local && _Vmtrace && (vd->mode&VM_TRACE) )
+ (*_Vmtrace)(vm,NIL(Vmuchar_t*),data,orgsize,orgalign);
+
+done:
+ CLRLOCK(vm, local); /**/ASSERT(_vmbestcheck(vd, NIL(Block_t*)) == 0);
+
+ return (Void_t*)data;
+}
+
+/* The below implements the discipline Vmdcsbrk and the heap region Vmheap.
+** There are 5 alternative ways to get raw memory:
+** win32, sbrk, mmap_anon, mmap_zero and reusing the native malloc
+** The selection of method done here is to enable our malloc implementation
+** to work with concurrent threads. The sbrk/brk interface is unfortunately
+** not atomic. Thus, we prefer mmap_anon or mmap_zero if they are available.
+*/
+#if _mem_win32
+#undef _mem_mmap_anon
+#undef _mem_mmap_zero
+#undef _mem_sbrk
+#endif
+#if _mem_mmap_anon
+#undef _mem_mmap_zero
+#if !_PACKAGE_ast
+#undef _mem_sbrk
+#endif
+#endif
+#if _mem_mmap_zero
+#if !_PACKAGE_ast
+#undef _mem_sbrk
+#endif
+#endif
+
+#if _SUNOS /* sunos guarantees that brk-addresses are valid */
+#define chkaddr(a,n) (0)
+
+#else /* make sure that allocated memory are addressable */
+#include <signal.h>
+typedef void (*Sig_f)(int);
+static int Gotsegv = 0;
+
+static void sigsegv(int sig)
+{
+ if(sig == SIGSEGV)
+ Gotsegv = 1;
+}
+static int chkaddr(Vmuchar_t* addr, size_t nsize)
+{
+ Sig_f segv;
+ int rv;
+
+ Gotsegv = 0; /* catch segment fault */
+ segv = signal(SIGSEGV, sigsegv);
+
+ rv = *(addr+nsize-1);
+ rv = Gotsegv ? -1 : rv;
+
+ signal(SIGSEGV, segv); /* restore signal catcher */
+ Gotsegv = 0;
+
+ return rv;
+}
+#endif /*_SUNOS*/
+
+#if _mem_win32 /* getting memory on a window system */
+#if _PACKAGE_ast
+#include <ast_windows.h>
+#else
+#include <windows.h>
+#endif
+
+static Void_t* win32mem(Void_t* caddr, size_t csize, size_t nsize)
+{ /**/ ASSERT(csize > 0 || nsize > 0)
+ if(csize == 0)
+ { caddr = (Void_t*)VirtualAlloc(0,nsize,MEM_COMMIT,PAGE_READWRITE);
+ return caddr;
+ }
+ else if(nsize == 0)
+ { (void)VirtualFree((LPVOID)caddr,0,MEM_RELEASE);
+ return caddr;
+ }
+ else return NIL(Void_t*);
+}
+#endif /* _mem_win32 */
+
+#if _mem_sbrk /* getting space via brk/sbrk - not concurrent-ready */
+static Void_t* sbrkmem(Void_t* caddr, size_t csize, size_t nsize)
+{
+ Vmuchar_t *addr = (Vmuchar_t*)sbrk(0);
+
+ if(!addr || addr == (Vmuchar_t*)(-1) )
+ return NIL(Void_t*);
+
+ if(csize > 0 && addr != (Vmuchar_t*)caddr+csize)
+ return NIL(Void_t*);
+ else if(csize == 0)
+ caddr = addr;
+
+ /**/ASSERT(addr == (Vmuchar_t*)caddr+csize);
+ if(nsize < csize)
+ addr -= csize-nsize;
+ else if((addr += nsize-csize) < (Vmuchar_t*)caddr )
+ return NIL(Void_t*);
+
+ if(brk(addr) != 0 )
+ return NIL(Void_t*);
+ else if(nsize > csize && chkaddr(caddr, nsize) < 0 )
+ { (void)brk((Vmuchar_t*)caddr+csize);
+ return NIL(Void_t*);
+ }
+ else return caddr;
+}
+#endif /* _mem_sbrk */
+
+#if _mem_mmap_anon || _mem_mmap_zero /* get space using mmap */
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#ifndef MAP_ANON
+#ifdef MAP_ANONYMOUS
+#define MAP_ANON MAP_ANONYMOUS
+#else
+#define MAP_ANON 0
+#endif
+#endif /*MAP_ANON*/
+
+#ifndef OPEN_MAX
+#define OPEN_MAX 64
+#endif
+#define FD_PRIVATE (3*OPEN_MAX/4) /* private file descriptor */
+#define FD_INIT (-1) /* uninitialized file desc */
+#define FD_NONE (-2) /* no mapping with file desc */
+
+typedef struct _mmdisc_s
+{ Vmdisc_t disc;
+ int fd;
+ off_t offset;
+} Mmdisc_t;
+
+static Void_t* mmapmem(Void_t* caddr, size_t csize, size_t nsize, Mmdisc_t* mmdc)
+{
+#if _mem_mmap_zero
+ if(mmdc) /* /dev/zero mapping */
+ { if(mmdc->fd == FD_INIT ) /* open /dev/zero for mapping */
+ { int fd;
+ if((fd = open("/dev/zero", O_RDONLY)) < 0 )
+ { mmdc->fd = FD_NONE;
+ return NIL(Void_t*);
+ }
+ if(fd >= FD_PRIVATE || (mmdc->fd = dup2(fd, FD_PRIVATE)) < 0 )
+ mmdc->fd = fd;
+ else close(fd);
+#ifdef FD_CLOEXEC
+ fcntl(mmdc->fd, F_SETFD, FD_CLOEXEC);
+#endif
+ }
+
+ if(mmdc->fd == FD_NONE)
+ return NIL(Void_t*);
+ }
+#endif /* _mem_mmap_zero */
+
+ /**/ASSERT(csize > 0 || nsize > 0);
+ if(csize == 0)
+ { nsize = ROUND(nsize, _Vmpagesize);
+ caddr = NIL(Void_t*);
+#if _mem_mmap_zero
+ if(mmdc && mmdc->fd >= 0 )
+ caddr = mmap(0, nsize, PROT_READ|PROT_WRITE, MAP_PRIVATE, mmdc->fd, mmdc->offset);
+#endif
+#if _mem_mmap_anon
+ if(!mmdc )
+ caddr = mmap(0, nsize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
+#endif
+ if(!caddr || caddr == (Void_t*)(-1))
+ return NIL(Void_t*);
+ else if(chkaddr((Vmuchar_t*)caddr, nsize) < 0 )
+ { (void)munmap(caddr, nsize);
+ return NIL(Void_t*);
+ }
+ else
+ { if(mmdc)
+ mmdc->offset += nsize;
+ return caddr;
+ }
+ }
+ else if(nsize == 0)
+ { Vmuchar_t *addr = (Vmuchar_t*)sbrk(0);
+ if(addr < (Vmuchar_t*)caddr ) /* in sbrk space */
+ return NIL(Void_t*);
+ else
+ { (void)munmap(caddr, csize);
+ return caddr;
+ }
+ }
+ else return NIL(Void_t*);
+}
+#endif /* _mem_map_anon || _mem_mmap_zero */
+
+#if _std_malloc /* using native malloc as a last resource */
+static Void_t* mallocmem(Void_t* caddr, size_t csize, size_t nsize)
+{
+ /**/ASSERT(csize > 0 || nsize > 0);
+ if(csize == 0)
+ return (Void_t*)malloc(nsize);
+ else if(nsize == 0)
+ { free(caddr);
+ return caddr;
+ }
+ else return NIL(Void_t*);
+}
+#endif
+
+/* A discipline to get raw memory using VirtualAlloc/mmap/sbrk */
+static Void_t* getmemory(Vmalloc_t* vm, Void_t* caddr, size_t csize, size_t nsize, Vmdisc_t* disc)
+{
+ Vmuchar_t *addr;
+
+ if((csize > 0 && !caddr) || (csize == 0 && nsize == 0) )
+ return NIL(Void_t*);
+
+#if _mem_win32
+ if((addr = win32mem(caddr, csize, nsize)) )
+ return (Void_t*)addr;
+#endif
+#if _mem_sbrk
+ if((_Vmassert & VM_break) && (addr = sbrkmem(caddr, csize, nsize)) )
+ return (Void_t*)addr;
+#endif
+#if _mem_mmap_anon
+ if((addr = mmapmem(caddr, csize, nsize, (Mmdisc_t*)0)) )
+ return (Void_t*)addr;
+#endif
+#if _mem_mmap_zero
+ if((addr = mmapmem(caddr, csize, nsize, (Mmdisc_t*)disc)) )
+ return (Void_t*)addr;
+#endif
+#if _mem_sbrk
+ if(!(_Vmassert & VM_break) && (addr = sbrkmem(caddr, csize, nsize)) )
+ return (Void_t*)addr;
+#endif
+#if _std_malloc
+ if((addr = mallocmem(caddr, csize, nsize)) )
+ return (Void_t*)addr;
+#endif
+ return NIL(Void_t*);
+}
+
+#if _mem_mmap_zero || _mem_mmap_anon
+static Mmdisc_t _Vmdcsystem = { { getmemory, NIL(Vmexcept_f), 64*1024, sizeof(Mmdisc_t) }, FD_INIT, 0 };
+#else
+static Vmdisc_t _Vmdcsystem = { getmemory, NIL(Vmexcept_f), 0, sizeof(Vmdisc_t) };
+#endif
+
+static Vmethod_t _Vmbest =
+{
+ bestalloc,
+ bestresize,
+ bestfree,
+ bestaddr,
+ bestsize,
+ bestcompact,
+ bestalign,
+ VM_MTBEST
+};
+
+/* The heap region */
+static Vmdata_t _Vmdata =
+{
+ 0, /* lock */
+ VM_MTBEST|VM_SHARE, /* mode */
+ 0, /* incr */
+ 0, /* pool */
+ NIL(Seg_t*), /* seg */
+ NIL(Block_t*), /* free */
+ NIL(Block_t*), /* wild */
+ NIL(Block_t*) /* root */
+ /* tiny[] */
+ /* cache[] */
+};
+Vmalloc_t _Vmheap =
+{
+ { bestalloc,
+ bestresize,
+ bestfree,
+ bestaddr,
+ bestsize,
+ bestcompact,
+ bestalign,
+ VM_MTBEST
+ },
+ NIL(char*), /* file */
+ 0, /* line */
+ 0, /* func */
+ (Vmdisc_t*)(&_Vmdcsystem), /* disc */
+ &_Vmdata, /* data */
+ NIL(Vmalloc_t*) /* next */
+};
+
+__DEFINE__(Vmalloc_t*, Vmheap, &_Vmheap);
+__DEFINE__(Vmalloc_t*, Vmregion, &_Vmheap);
+__DEFINE__(Vmethod_t*, Vmbest, &_Vmbest);
+__DEFINE__(Vmdisc_t*, Vmdcsystem, (Vmdisc_t*)(&_Vmdcsystem) );
+__DEFINE__(Vmdisc_t*, Vmdcsbrk, (Vmdisc_t*)(&_Vmdcsystem) );
+
+#ifdef NoF
+NoF(vmbest)
+#endif
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmclear.c b/src/lib/libast/vmalloc/vmclear.c
new file mode 100644
index 0000000..c4b8107
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmclear.c
@@ -0,0 +1,85 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmclear(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Clear out all allocated space.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+#if __STD_C
+int vmclear(Vmalloc_t* vm)
+#else
+int vmclear(vm)
+Vmalloc_t* vm;
+#endif
+{
+ Seg_t *seg, *next;
+ Block_t *tp;
+ size_t size, s;
+ Vmdata_t *vd = vm->data;
+
+ SETLOCK(vm, 0);
+
+ vd->free = vd->wild = NIL(Block_t*);
+ vd->pool = 0;
+
+ if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE) )
+ { vd->root = NIL(Block_t*);
+ for(s = 0; s < S_TINY; ++s)
+ TINY(vd)[s] = NIL(Block_t*);
+ for(s = 0; s <= S_CACHE; ++s)
+ CACHE(vd)[s] = NIL(Block_t*);
+ }
+
+ for(seg = vd->seg; seg; seg = next)
+ { next = seg->next;
+
+ tp = SEGBLOCK(seg);
+ size = seg->baddr - ((Vmuchar_t*)tp) - 2*sizeof(Head_t);
+
+ SEG(tp) = seg;
+ SIZE(tp) = size;
+ if((vd->mode&(VM_MTLAST|VM_MTPOOL)) )
+ seg->free = tp;
+ else
+ { SIZE(tp) |= BUSY|JUNK;
+ LINK(tp) = CACHE(vd)[C_INDEX(SIZE(tp))];
+ CACHE(vd)[C_INDEX(SIZE(tp))] = tp;
+ }
+
+ tp = BLOCK(seg->baddr);
+ SEG(tp) = seg;
+ SIZE(tp) = BUSY;
+ }
+
+ CLRLOCK(vm, 0);
+
+ return 0;
+}
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmclose.c b/src/lib/libast/vmalloc/vmclose.c
new file mode 100644
index 0000000..65a3a7e
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmclose.c
@@ -0,0 +1,91 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmclose(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Close down a region.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+#if __STD_C
+int vmclose(Vmalloc_t* vm)
+#else
+int vmclose(vm)
+Vmalloc_t* vm;
+#endif
+{
+ Seg_t *seg, *vmseg, *next;
+ Vmalloc_t *v, *last, vmp;
+ Vmdata_t* vd = vm->data;
+ Vmdisc_t* disc = vm->disc;
+ int mode, rv = 0;
+
+ if(vm == Vmheap) /* the heap is never freed */
+ return -1;
+
+ if(vm->disc->exceptf && /* announcing closing event */
+ (rv = (*vm->disc->exceptf)(vm,VM_CLOSE,(Void_t*)1,vm->disc)) < 0 )
+ return -1;
+
+ mode = vd->mode; /* remember this in case it gets destroyed below */
+
+ if((mode&VM_MTPROFILE) && _Vmpfclose)
+ (*_Vmpfclose)(vm);
+
+ /* remove from linked list of regions */
+ _vmlock(NIL(Vmalloc_t*), 1);
+ for(last = Vmheap, v = last->next; v; last = v, v = v->next)
+ { if(v == vm)
+ { last->next = v->next;
+ break;
+ }
+ }
+ _vmlock(NIL(Vmalloc_t*), 0);
+
+ if(rv == 0) /* deallocate memory obtained from the system */
+ { /* lock-free because alzheimer can cause deadlocks :) */
+ vmseg = NIL(Seg_t*);
+ for(seg = vd->seg; seg; seg = next)
+ { next = seg->next;
+ if(seg->extent == seg->size) /* root segment */
+ vmseg = seg; /* don't free this yet */
+ else (*disc->memoryf)(vm,seg->addr,seg->extent,0,disc);
+ }
+ if(vmseg) /* now safe to free root segment */
+ (*disc->memoryf)(vm,vmseg->addr,vmseg->extent,0,disc);
+ }
+
+ if(disc->exceptf) /* finalizing closing */
+ (void)(*disc->exceptf)(vm, VM_ENDCLOSE, (Void_t*)0, disc);
+
+ if(!(mode & VM_MEMORYF) )
+ vmfree(Vmheap,vm);
+
+ return 0;
+}
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmdcheap.c b/src/lib/libast/vmalloc/vmdcheap.c
new file mode 100644
index 0000000..88edc72
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmdcheap.c
@@ -0,0 +1,63 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmdcheap(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* A discipline to get memory from the heap.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+#if __STD_C
+static Void_t* heapmem(Vmalloc_t* vm, Void_t* caddr,
+ size_t csize, size_t nsize,
+ Vmdisc_t* disc)
+#else
+static Void_t* heapmem(vm, caddr, csize, nsize, disc)
+Vmalloc_t* vm; /* region doing allocation from */
+Void_t* caddr; /* current low address */
+size_t csize; /* current size */
+size_t nsize; /* new size */
+Vmdisc_t* disc; /* discipline structure */
+#endif
+{
+ if(csize == 0 && nsize == 0)
+ return NIL(Void_t*);
+ else if(csize == 0)
+ return vmalloc(Vmheap,nsize);
+ else if(nsize == 0)
+ return vmfree(Vmheap,caddr) >= 0 ? caddr : NIL(Void_t*);
+ else return vmresize(Vmheap,caddr,nsize,0);
+}
+
+static Vmdisc_t _Vmdcheap = { heapmem, NIL(Vmexcept_f), 0 };
+__DEFINE__(Vmdisc_t*,Vmdcheap,&_Vmdcheap);
+
+#ifdef NoF
+NoF(vmdcheap)
+#endif
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmdebug.c b/src/lib/libast/vmalloc/vmdebug.c
new file mode 100644
index 0000000..160c189
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmdebug.c
@@ -0,0 +1,745 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmdebug(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Method to help with debugging. This does rigorous checks on
+** addresses and arena integrity.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+
+/* structure to keep track of file names */
+typedef struct _dbfile_s Dbfile_t;
+struct _dbfile_s
+{ Dbfile_t* next;
+ char file[1];
+};
+static Dbfile_t* Dbfile;
+
+/* global watch list */
+#define S_WATCH 32
+static int Dbnwatch;
+static Void_t* Dbwatch[S_WATCH];
+
+/* types of warnings reported by dbwarn() */
+#define DB_CHECK 0
+#define DB_ALLOC 1
+#define DB_FREE 2
+#define DB_RESIZE 3
+#define DB_WATCH 4
+#define DB_RESIZED 5
+
+static int Dbinit = 0;
+#define DBINIT() (Dbinit ? 0 : (dbinit(), Dbinit=1) )
+static void dbinit()
+{ int fd;
+ if((fd = vmtrace(-1)) >= 0)
+ vmtrace(fd);
+}
+
+static int Dbfd = 2; /* default warning file descriptor */
+#if __STD_C
+int vmdebug(int fd)
+#else
+int vmdebug(fd)
+int fd;
+#endif
+{
+ int old = Dbfd;
+ Dbfd = fd;
+ return old;
+}
+
+
+/* just an entry point to make it easy to set break point */
+#if __STD_C
+static void vmdbwarn(Vmalloc_t* vm, char* mesg, int n)
+#else
+static void vmdbwarn(vm, mesg, n)
+Vmalloc_t* vm;
+char* mesg;
+int n;
+#endif
+{
+ reg Vmdata_t* vd = vm->data;
+
+ write(Dbfd,mesg,n);
+ if(vd->mode&VM_DBABORT)
+ abort();
+}
+
+/* issue a warning of some type */
+#if __STD_C
+static void dbwarn(Vmalloc_t* vm, Void_t* data, int where,
+ char* file, int line, Void_t* func, int type)
+#else
+static void dbwarn(vm, data, where, file, line, func, type)
+Vmalloc_t* vm; /* region holding the block */
+Void_t* data; /* data block */
+int where; /* byte that was corrupted */
+char* file; /* file where call originates */
+int line; /* line number of call */
+Void_t* func; /* function called from */
+int type; /* operation being done */
+#endif
+{
+ char buf[1024], *bufp, *endbuf, *s;
+#define SLOP 64 /* enough for a message and an int */
+
+ DBINIT();
+
+ bufp = buf;
+ endbuf = buf + sizeof(buf);
+
+ if(type == DB_ALLOC)
+ bufp = (*_Vmstrcpy)(bufp, "alloc error", ':');
+ else if(type == DB_FREE)
+ bufp = (*_Vmstrcpy)(bufp, "free error", ':');
+ else if(type == DB_RESIZE)
+ bufp = (*_Vmstrcpy)(bufp, "resize error", ':');
+ else if(type == DB_CHECK)
+ bufp = (*_Vmstrcpy)(bufp, "corrupted data", ':');
+ else if(type == DB_WATCH)
+ bufp = (*_Vmstrcpy)(bufp, "alert", ':');
+
+ /* region info */
+ bufp = (*_Vmstrcpy)(bufp, "region", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(vm), 0), ':');
+
+ if(data)
+ { bufp = (*_Vmstrcpy)(bufp,"block",'=');
+ bufp = (*_Vmstrcpy)(bufp,(*_Vmitoa)(VLONG(data),0),':');
+ }
+
+ if(!data)
+ { if(where == DB_ALLOC)
+ bufp = (*_Vmstrcpy)(bufp, "can't get memory", ':');
+ else bufp = (*_Vmstrcpy)(bufp, "region is locked", ':');
+ }
+ else if(type == DB_FREE || type == DB_RESIZE)
+ { if(where == 0)
+ bufp = (*_Vmstrcpy)(bufp, "unallocated block", ':');
+ else bufp = (*_Vmstrcpy)(bufp, "already freed", ':');
+ }
+ else if(type == DB_WATCH)
+ { bufp = (*_Vmstrcpy)(bufp, "size", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(DBSIZE(data),-1), ':');
+ if(where == DB_ALLOC)
+ bufp = (*_Vmstrcpy)(bufp,"just allocated", ':');
+ else if(where == DB_FREE)
+ bufp = (*_Vmstrcpy)(bufp,"being freed", ':');
+ else if(where == DB_RESIZE)
+ bufp = (*_Vmstrcpy)(bufp,"being resized", ':');
+ else if(where == DB_RESIZED)
+ bufp = (*_Vmstrcpy)(bufp,"just resized", ':');
+ }
+ else if(type == DB_CHECK)
+ { bufp = (*_Vmstrcpy)(bufp, "bad byte at", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(where),-1), ':');
+ if((s = DBFILE(data)) && (bufp + strlen(s) + SLOP) < endbuf)
+ { bufp = (*_Vmstrcpy)(bufp,"allocated at", '=');
+ bufp = (*_Vmstrcpy)(bufp, s, ',');
+ bufp = (*_Vmstrcpy)(bufp,(*_Vmitoa)(VLONG(DBLINE(data)),-1),':');
+ }
+ }
+
+ /* location where offending call originates from */
+ if(file && file[0] && line > 0 && (bufp + strlen(file) + SLOP) < endbuf)
+ { bufp = (*_Vmstrcpy)(bufp, "detected at", '=');
+ bufp = (*_Vmstrcpy)(bufp, file, ',');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(line),-1), ',');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(func),-1), ':');
+ }
+
+ *bufp++ = '\n';
+ *bufp = '\0';
+
+ vmdbwarn(vm,buf,(bufp-buf));
+}
+
+/* check for watched address and issue warnings */
+#if __STD_C
+static void dbwatch(Vmalloc_t* vm, Void_t* data,
+ char* file, int line, Void_t* func, int type)
+#else
+static void dbwatch(vm, data, file, line, func, type)
+Vmalloc_t* vm;
+Void_t* data;
+char* file;
+int line;
+Void_t* func;
+int type;
+#endif
+{
+ reg int n;
+
+ for(n = Dbnwatch; n >= 0; --n)
+ { if(Dbwatch[n] == data)
+ { dbwarn(vm,data,type,file,line,func,DB_WATCH);
+ return;
+ }
+ }
+}
+
+/* record information about the block */
+#if __STD_C
+static void dbsetinfo(Vmuchar_t* data, size_t size, char* file, int line)
+#else
+static void dbsetinfo(data, size, file, line)
+Vmuchar_t* data; /* real address not the one from Vmbest */
+size_t size; /* the actual requested size */
+char* file; /* file where the request came from */
+int line; /* and line number */
+#endif
+{
+ reg Vmuchar_t *begp, *endp;
+ reg Dbfile_t *last, *db;
+
+ DBINIT();
+
+ /* find the file structure */
+ if(!file || !file[0])
+ db = NIL(Dbfile_t*);
+ else
+ { for(last = NIL(Dbfile_t*), db = Dbfile; db; last = db, db = db->next)
+ if(strcmp(db->file,file) == 0)
+ break;
+ if(!db)
+ { db = (Dbfile_t*)vmalloc(Vmheap,sizeof(Dbfile_t)+strlen(file));
+ if(db)
+ { (*_Vmstrcpy)(db->file,file,0);
+ db->next = Dbfile;
+ Dbfile = db;
+ }
+ }
+ else if(last) /* move-to-front heuristic */
+ { last->next = db->next;
+ db->next = Dbfile;
+ Dbfile = db;
+ }
+ }
+
+ DBSETFL(data,(db ? db->file : NIL(char*)),line);
+ DBSIZE(data) = size;
+ DBSEG(data) = SEG(DBBLOCK(data));
+
+ DBHEAD(data,begp,endp);
+ while(begp < endp)
+ *begp++ = DB_MAGIC;
+ DBTAIL(data,begp,endp);
+ while(begp < endp)
+ *begp++ = DB_MAGIC;
+}
+
+/* Check to see if an address is in some data block of a region.
+** This returns -(offset+1) if block is already freed, +(offset+1)
+** if block is live, 0 if no match.
+*/
+#if __STD_C
+static long dbaddr(Vmalloc_t* vm, Void_t* addr, int local)
+#else
+static long dbaddr(vm, addr, local)
+Vmalloc_t* vm;
+Void_t* addr;
+int local;
+#endif
+{
+ reg Block_t *b, *endb;
+ reg Seg_t *seg;
+ reg Vmuchar_t *data;
+ reg long offset = -1L;
+ reg Vmdata_t *vd = vm->data;
+
+ SETLOCK(vm, local);
+
+ b = endb = NIL(Block_t*);
+ for(seg = vd->seg; seg; seg = seg->next)
+ { b = SEGBLOCK(seg);
+ endb = (Block_t*)(seg->baddr - sizeof(Head_t));
+ if((Vmuchar_t*)addr > (Vmuchar_t*)b &&
+ (Vmuchar_t*)addr < (Vmuchar_t*)endb)
+ break;
+ }
+ if(!seg)
+ goto done;
+
+ if(local) /* must be vmfree or vmresize checking address */
+ { if(DBSEG(addr) == seg)
+ { b = DBBLOCK(addr);
+ if(ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) )
+ offset = 0;
+ else offset = -2L;
+ }
+ goto done;
+ }
+
+ while(b < endb)
+ { data = (Vmuchar_t*)DATA(b);
+ if((Vmuchar_t*)addr >= data && (Vmuchar_t*)addr < data+SIZE(b))
+ { if(ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) )
+ { data = DB2DEBUG(data);
+ if((Vmuchar_t*)addr >= data &&
+ (Vmuchar_t*)addr < data+DBSIZE(data))
+ offset = (Vmuchar_t*)addr - data;
+ }
+ goto done;
+ }
+
+ b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) );
+ }
+
+done:
+ CLRLOCK(vm, local);
+ return offset;
+}
+
+
+#if __STD_C
+static long dbsize(Vmalloc_t* vm, Void_t* addr, int local)
+#else
+static long dbsize(vm, addr, local)
+Vmalloc_t* vm;
+Void_t* addr;
+int local;
+#endif
+{
+ Block_t *b, *endb;
+ Seg_t *seg;
+ long size;
+ Vmdata_t *vd = vm->data;
+
+ SETLOCK(vm, local);
+
+ size = -1L;
+ for(seg = vd->seg; seg; seg = seg->next)
+ { b = SEGBLOCK(seg);
+ endb = (Block_t*)(seg->baddr - sizeof(Head_t));
+ if((Vmuchar_t*)addr <= (Vmuchar_t*)b ||
+ (Vmuchar_t*)addr >= (Vmuchar_t*)endb)
+ continue;
+ while(b < endb)
+ { if(addr == (Void_t*)DB2DEBUG(DATA(b)))
+ { if(ISBUSY(SIZE(b)) && !ISJUNK(SIZE(b)) )
+ size = (long)DBSIZE(addr);
+ goto done;
+ }
+
+ b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) );
+ }
+ }
+
+done:
+ CLRLOCK(vm, local);
+ return size;
+}
+
+#if __STD_C
+static Void_t* dballoc(Vmalloc_t* vm, size_t size, int local)
+#else
+static Void_t* dballoc(vm, size, local)
+Vmalloc_t* vm;
+size_t size;
+int local;
+#endif
+{
+ size_t s;
+ Vmuchar_t *data;
+ char *file;
+ int line;
+ Void_t *func;
+ Vmdata_t *vd = vm->data;
+ VMFLF(vm,file,line,func);
+
+ SETLOCK(vm, local);
+
+ if(vd->mode&VM_DBCHECK)
+ vmdbcheck(vm);
+
+ s = ROUND(size,ALIGN) + DB_EXTRA;
+ if(s < sizeof(Body_t)) /* no tiny blocks during Vmdebug */
+ s = sizeof(Body_t);
+
+ if(!(data = (Vmuchar_t*)KPVALLOC(vm,s,(*(Vmbest->allocf))) ) )
+ { dbwarn(vm,NIL(Vmuchar_t*),DB_ALLOC,file,line,func,DB_ALLOC);
+ goto done;
+ }
+
+ data = DB2DEBUG(data);
+ dbsetinfo(data,size,file,line);
+
+ if((vd->mode&VM_TRACE) && _Vmtrace)
+ { vm->file = file; vm->line = line; vm->func = func;
+ (*_Vmtrace)(vm,NIL(Vmuchar_t*),data,size,0);
+ }
+
+ if(Dbnwatch > 0 )
+ dbwatch(vm,data,file,line,func,DB_ALLOC);
+
+done:
+ CLRLOCK(vm, local);
+
+ return (Void_t*)data;
+}
+
+
+#if __STD_C
+static int dbfree(Vmalloc_t* vm, Void_t* data, int local )
+#else
+static int dbfree(vm, data, local )
+Vmalloc_t* vm;
+Void_t* data;
+int local;
+#endif
+{
+ char *file;
+ int line;
+ Void_t *func;
+ long offset;
+ int rv, *ip, *endip;
+ Vmdata_t *vd = vm->data;
+ VMFLF(vm,file,line,func);
+
+ if(!data)
+ return 0;
+
+ SETLOCK(vm, local);
+
+ if(vd->mode&VM_DBCHECK)
+ vmdbcheck(vm);
+
+ if((offset = KPVADDR(vm,data,dbaddr)) != 0)
+ { dbwarn(vm,(Vmuchar_t*)data,offset == -1L ? 0 : 1,file,line,func,DB_FREE);
+ rv = -1;
+ }
+ else
+ { if(Dbnwatch > 0)
+ dbwatch(vm,data,file,line,func,DB_FREE);
+
+ if((vd->mode&VM_TRACE) && _Vmtrace)
+ { vm->file = file; vm->line = line; vm->func = func;
+ (*_Vmtrace)(vm,(Vmuchar_t*)data,NIL(Vmuchar_t*),DBSIZE(data),0);
+ }
+
+ /* clear free space */
+ ip = (int*)data;
+ endip = ip + (DBSIZE(data)+sizeof(int)-1)/sizeof(int);
+ while(ip < endip)
+ *ip++ = 0;
+
+ rv = KPVFREE((vm), (Void_t*)DB2BEST(data), (*Vmbest->freef));
+ }
+
+ CLRLOCK(vm, local);
+ return rv;
+}
+
+/* Resizing an existing block */
+#if __STD_C
+static Void_t* dbresize(Vmalloc_t* vm, Void_t* addr, reg size_t size, int type, int local)
+#else
+static Void_t* dbresize(vm, addr, size, type, local)
+Vmalloc_t* vm; /* region allocating from */
+Void_t* addr; /* old block of data */
+reg size_t size; /* new size */
+int type; /* !=0 for movable, >0 for copy */
+int local;
+#endif
+{
+ Vmuchar_t *data;
+ long offset;
+ size_t s, oldsize;
+ char *file, *oldfile;
+ int line, oldline;
+ Void_t *func;
+ Vmdata_t *vd = vm->data;
+ VMFLF(vm,file,line,func);
+
+ if(!addr)
+ { vm->file = file; vm->line = line;
+ data = (Vmuchar_t*)dballoc(vm, size, local);
+ if(data && (type&VM_RSZERO) )
+ memset((Void_t*)data, 0, size);
+ return data;
+ }
+ if(size == 0)
+ { vm->file = file; vm->line = line;
+ (void)dbfree(vm, addr, local);
+ return NIL(Void_t*);
+ }
+
+ SETLOCK(vm, local);
+
+ if(vd->mode&VM_DBCHECK)
+ vmdbcheck(vm);
+
+ if((offset = KPVADDR(vm,addr,dbaddr)) != 0)
+ { dbwarn(vm,(Vmuchar_t*)addr,offset == -1L ? 0 : 1,file,line,func,DB_RESIZE);
+ data = NIL(Vmuchar_t*);
+ }
+ else
+ { if(Dbnwatch > 0)
+ dbwatch(vm,addr,file,line,func,DB_RESIZE);
+
+ /* Vmbest data block */
+ data = DB2BEST(addr);
+ oldsize = DBSIZE(addr);
+ oldfile = DBFILE(addr);
+ oldline = DBLINE(addr);
+
+ /* do the resize */
+ s = ROUND(size,ALIGN) + DB_EXTRA;
+ if(s < sizeof(Body_t))
+ s = sizeof(Body_t);
+ data = (Vmuchar_t*)KPVRESIZE(vm,(Void_t*)data,s,
+ (type&~VM_RSZERO),(*(Vmbest->resizef)) );
+ if(!data) /* failed, reset data for old block */
+ { dbwarn(vm,NIL(Vmuchar_t*),DB_ALLOC,file,line,func,DB_RESIZE);
+ dbsetinfo((Vmuchar_t*)addr,oldsize,oldfile,oldline);
+ }
+ else
+ { data = DB2DEBUG(data);
+ dbsetinfo(data,size,file,line);
+
+ if((vd->mode&VM_TRACE) && _Vmtrace)
+ { vm->file = file; vm->line = line;
+ (*_Vmtrace)(vm,(Vmuchar_t*)addr,data,size,0);
+ }
+ if(Dbnwatch > 0)
+ dbwatch(vm,data,file,line,func,DB_RESIZED);
+ }
+
+ if(data && (type&VM_RSZERO) && size > oldsize)
+ { Vmuchar_t *d = data+oldsize, *ed = data+size;
+ do { *d++ = 0; } while(d < ed);
+ }
+ }
+
+ CLRLOCK(vm, local);
+
+ return (Void_t*)data;
+}
+
+/* compact any residual free space */
+#if __STD_C
+static int dbcompact(Vmalloc_t* vm, int local)
+#else
+static int dbcompact(vm, local)
+Vmalloc_t* vm;
+int local;
+#endif
+{
+ return (*(Vmbest->compactf))(vm, local);
+}
+
+/* check for memory overwrites over all live blocks */
+#if __STD_C
+int vmdbcheck(Vmalloc_t* vm)
+#else
+int vmdbcheck(vm)
+Vmalloc_t* vm;
+#endif
+{
+ reg Block_t *b, *endb;
+ reg Seg_t* seg;
+ int rv;
+ reg Vmdata_t* vd = vm->data;
+
+ /* check the meta-data of this region */
+ if(vd->mode & (VM_MTDEBUG|VM_MTBEST|VM_MTPROFILE))
+ { if(_vmbestcheck(vd, NIL(Block_t*)) < 0)
+ return -1;
+ if(!(vd->mode&VM_MTDEBUG) )
+ return 0;
+ }
+ else return -1;
+
+ rv = 0;
+ for(seg = vd->seg; seg; seg = seg->next)
+ { b = SEGBLOCK(seg);
+ endb = (Block_t*)(seg->baddr - sizeof(Head_t));
+ while(b < endb)
+ { reg Vmuchar_t *data, *begp, *endp;
+
+ if(ISJUNK(SIZE(b)) || !ISBUSY(SIZE(b)))
+ goto next;
+
+ data = DB2DEBUG(DATA(b));
+ if(DBISBAD(data)) /* seen this before */
+ { rv += 1;
+ goto next;
+ }
+
+ DBHEAD(data,begp,endp);
+ for(; begp < endp; ++begp)
+ if(*begp != DB_MAGIC)
+ goto set_bad;
+
+ DBTAIL(data,begp,endp);
+ for(; begp < endp; ++begp)
+ { if(*begp == DB_MAGIC)
+ continue;
+ set_bad:
+ dbwarn(vm,data,begp-data,vm->file,vm->line,0,DB_CHECK);
+ DBSETBAD(data);
+ rv += 1;
+ goto next;
+ }
+
+ next: b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS));
+ }
+ }
+
+ return rv;
+}
+
+/* set/delete an address to watch */
+#if __STD_C
+Void_t* vmdbwatch(Void_t* addr)
+#else
+Void_t* vmdbwatch(addr)
+Void_t* addr; /* address to insert */
+#endif
+{
+ reg int n;
+ reg Void_t* out;
+
+ out = NIL(Void_t*);
+ if(!addr)
+ Dbnwatch = 0;
+ else
+ { for(n = Dbnwatch - 1; n >= 0; --n)
+ if(Dbwatch[n] == addr)
+ break;
+ if(n < 0) /* insert */
+ { if(Dbnwatch == S_WATCH)
+ { /* delete left-most */
+ out = Dbwatch[0];
+ Dbnwatch -= 1;
+ for(n = 0; n < Dbnwatch; ++n)
+ Dbwatch[n] = Dbwatch[n+1];
+ }
+ Dbwatch[Dbnwatch] = addr;
+ Dbnwatch += 1;
+ }
+ }
+ return out;
+}
+
+#if __STD_C
+static Void_t* dbalign(Vmalloc_t* vm, size_t size, size_t align, int local)
+#else
+static Void_t* dbalign(vm, size, align, local)
+Vmalloc_t* vm;
+size_t size;
+size_t align;
+int local;
+#endif
+{
+ Vmuchar_t *data;
+ size_t s;
+ char *file;
+ int line;
+ Void_t *func;
+ Vmdata_t *vd = vm->data;
+ VMFLF(vm,file,line,func);
+
+ if(size <= 0 || align <= 0)
+ return NIL(Void_t*);
+
+ SETLOCK(vm, local);
+
+ if((s = ROUND(size,ALIGN) + DB_EXTRA) < sizeof(Body_t))
+ s = sizeof(Body_t);
+
+ if((data = (Vmuchar_t*)KPVALIGN(vm,s,align,(*(Vmbest->alignf)))) )
+ { data += DB_HEAD;
+ dbsetinfo(data,size,file,line);
+
+ if((vd->mode&VM_TRACE) && _Vmtrace)
+ { vm->file = file; vm->line = line; vm->func = func;
+ (*_Vmtrace)(vm,NIL(Vmuchar_t*),data,size,align);
+ }
+ }
+
+ CLRLOCK(vm, local);
+
+ return (Void_t*)data;
+}
+
+/* print statistics of region vm. If vm is NULL, use Vmregion */
+#if __STD_C
+ssize_t vmdbstat(Vmalloc_t* vm)
+#else
+ssize_t vmdbstat(vm)
+Vmalloc_t* vm;
+#endif
+{ Vmstat_t st;
+ char buf[1024], *bufp;
+
+ vmstat(vm ? vm : Vmregion, &st);
+ bufp = buf;
+ bufp = (*_Vmstrcpy)(bufp, "n_busy", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.n_busy),-1), ',');
+ bufp = (*_Vmstrcpy)(bufp, " s_busy", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.s_busy),-1), '\n');
+ bufp = (*_Vmstrcpy)(bufp, "n_free", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.n_free),-1), ',');
+ bufp = (*_Vmstrcpy)(bufp, " s_free", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.s_free),-1), '\n');
+ bufp = (*_Vmstrcpy)(bufp, "m_busy", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.m_busy),-1), ',');
+ bufp = (*_Vmstrcpy)(bufp, " m_free", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.m_free),-1), '\n');
+ bufp = (*_Vmstrcpy)(bufp, "n_segment", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.n_seg),-1), ',');
+ bufp = (*_Vmstrcpy)(bufp, " extent", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(st.extent),-1), '\n');
+ *bufp = 0;
+ write(Dbfd, buf, strlen(buf));
+ return strlen(buf);
+}
+
+static Vmethod_t _Vmdebug =
+{
+ dballoc,
+ dbresize,
+ dbfree,
+ dbaddr,
+ dbsize,
+ dbcompact,
+ dbalign,
+ VM_MTDEBUG
+};
+
+__DEFINE__(Vmethod_t*,Vmdebug,&_Vmdebug);
+
+#ifdef NoF
+NoF(vmdebug)
+#endif
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmdisc.c b/src/lib/libast/vmalloc/vmdisc.c
new file mode 100644
index 0000000..3f4efbf
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmdisc.c
@@ -0,0 +1,55 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmdisc(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Change the discipline for a region. The old discipline
+** is returned. If the new discipline is NULL then the
+** discipline is not changed.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+#if __STD_C
+Vmdisc_t* vmdisc(Vmalloc_t* vm, Vmdisc_t* disc)
+#else
+Vmdisc_t* vmdisc(vm, disc)
+Vmalloc_t* vm;
+Vmdisc_t* disc;
+#endif
+{
+ Vmdisc_t* old = vm->disc;
+
+ if(disc)
+ { if(old->exceptf &&
+ (*old->exceptf)(vm,VM_DISC,(Void_t*)disc,old) != 0 )
+ return NIL(Vmdisc_t*);
+ vm->disc = disc;
+ }
+ return old;
+}
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmexit.c b/src/lib/libast/vmalloc/vmexit.c
new file mode 100644
index 0000000..c027fd5
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmexit.c
@@ -0,0 +1,100 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmexit(){}
+
+#else
+
+#include "vmhdr.h"
+
+/*
+** Any required functions for process exiting.
+** Written by Kiem-Phong Vo, kpv@research.att.com (05/25/93).
+*/
+#if _PACKAGE_ast || _lib_atexit
+
+void _STUB_vmexit(){}
+
+#else
+
+#if _lib_onexit
+
+#if __STD_C
+int atexit(void (*exitf)(void))
+#else
+int atexit(exitf)
+void (*exitf)();
+#endif
+{
+ return onexit(exitf);
+}
+
+#else /*!_lib_onexit*/
+
+typedef struct _exit_s
+{ struct _exit_s* next;
+ void(* exitf)_ARG_((void));
+} Exit_t;
+static Exit_t* Exit;
+
+#if __STD_C
+atexit(void (*exitf)(void))
+#else
+atexit(exitf)
+void (*exitf)();
+#endif
+{ Exit_t* e;
+
+ if(!(e = (Exit_t*)malloc(sizeof(Exit_t))) )
+ return -1;
+ e->exitf = exitf;
+ e->next = Exit;
+ Exit = e;
+ return 0;
+}
+
+#if __STD_C
+void exit(int type)
+#else
+void exit(type)
+int type;
+#endif
+{
+ Exit_t* e;
+
+ for(e = Exit; e; e = e->next)
+ (*e->exitf)();
+
+#if _exit_cleanup
+ _cleanup();
+#endif
+
+ _exit(type);
+ return type;
+}
+
+#endif /* _lib_onexit || _lib_on_exit */
+
+#endif /*!PACKAGE_ast*/
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmgetmem.c b/src/lib/libast/vmalloc/vmgetmem.c
new file mode 100644
index 0000000..e205fd3
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmgetmem.c
@@ -0,0 +1,51 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#include <vmalloc.h>
+
+/*
+ * vm open/close/resize - a handy default for discipline memory functions
+ *
+ * vmgetmem(0,0,0) open new region
+ * vmgetmem(r,0,0) free region
+ * vmgetmem(r,0,n) allocate n bytes initialized to 0
+ * vmgetmem(r,p,0) free p
+ * vmgetmem(r,p,n) realloc p to n bytes
+ *
+ * Written by Glenn S. Fowler.
+ */
+
+#if __STD_C
+Void_t* vmgetmem(Vmalloc_t* vm, Void_t* data, size_t size)
+#else
+Void_t* vmgetmem(vm, data, size)
+Vmalloc_t* vm;
+Void_t* data;
+size_t size;
+#endif
+{
+ if (!vm)
+ return vmopen(Vmdcheap, Vmbest, 0);
+ if (data || size)
+ return vmresize(vm, data, size, VM_RSMOVE|VM_RSCOPY|VM_RSZERO);
+ vmclose(vm);
+ return 0;
+}
diff --git a/src/lib/libast/vmalloc/vmhdr.h b/src/lib/libast/vmalloc/vmhdr.h
new file mode 100644
index 0000000..25997ac
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmhdr.h
@@ -0,0 +1,530 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#ifndef _VMHDR_H
+#define _VMHDR_H 1
+#ifndef _BLD_vmalloc
+#define _BLD_vmalloc 1
+#endif
+
+/* Common types, and macros for vmalloc functions.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+
+#ifndef __STD_C /* this is normally in vmalloc.h but it's included late here */
+#ifdef __STDC__
+#define __STD_C 1
+#else
+#if __cplusplus || c_plusplus
+#define __STD_C 1
+#else
+#define __STD_C 0
+#endif /*__cplusplus*/
+#endif /*__STDC__*/
+#endif /*__STD_C*/
+
+#if _PACKAGE_ast
+
+#if !_UWIN
+#define getpagesize ______getpagesize
+#define _npt_getpagesize 1
+#define brk ______brk
+#define sbrk ______sbrk
+#define _npt_sbrk 1
+#endif
+
+#include <ast.h>
+
+#if _npt_getpagesize
+#undef getpagesize
+#endif
+#if _npt_sbrk
+#undef brk
+#undef sbrk
+#endif
+
+#else
+
+#include <ast_common.h>
+
+#if !_UWIN
+#define _npt_getpagesize 1
+#define _npt_sbrk 1
+#endif
+
+#undef free
+#undef malloc
+#undef realloc
+
+#endif /*_PACKAGE_ast*/
+
+#include "FEATURE/vmalloc"
+
+#include <aso.h> /* atomic scalor operations */
+#include <setjmp.h> /* use the type jmp_buf for alignment */
+
+/* extra information needed about methods to get memory from the system */
+#if defined(_WIN32)
+#define _mem_win32 1 /* use the VirtualAlloc interface */
+#endif
+#if !_mem_win32 && !_mem_sbrk && !_mem_mmap_anon && !_mem_mmap_zero
+#undef _std_malloc
+#define _std_malloc 1 /* use native malloc/free/realloc */
+#endif
+
+typedef unsigned char Vmuchar_t;
+typedef unsigned long Vmulong_t;
+
+typedef union _head_u Head_t;
+typedef union _body_u Body_t;
+typedef struct _block_s Block_t;
+typedef struct _seg_s Seg_t;
+typedef struct _pfobj_s Pfobj_t;
+
+#define NIL(t) ((t)0)
+#define reg register
+#if __STD_C
+#define NOTUSED(x) (void)(x)
+#else
+#define NOTUSED(x) (&x,1)
+#endif
+
+
+/* convert an address to an integral value */
+#define VLONG(addr) ((Vmulong_t)((Vmuchar_t*)((Vmulong_t)addr) - (Vmuchar_t*)0) )
+
+/* Round x up to a multiple of y. ROUND2 does powers-of-2 and ROUNDX does others */
+#define ROUND2(x,y) (((x) + ((y)-1)) & ~((y)-1))
+#define ROUNDX(x,y) ((((x) + ((y)-1)) / (y)) * (y))
+#define ROUND(x,y) (((y)&((y)-1)) ? ROUNDX((x),(y)) : ROUND2((x),(y)) )
+
+/* compute a value that is a common multiple of x and y */
+#define MULTIPLE(x,y) ((x)%(y) == 0 ? (x) : (y)%(x) == 0 ? (y) : (y)*(x))
+
+#define VM_abort 0x0001 /* abort() on assertion failure */
+#define VM_break 0x0002 /* try sbrk() block allocator first */
+#define VM_check 0x0004 /* enable detailed checks */
+#define VM_free 0x0008 /* disable addfreelist() */
+#define VM_keep 0x0010 /* disable free() */
+
+#if _UWIN
+#include <ast_windows.h>
+#endif
+
+#ifndef DEBUG
+#ifdef _BLD_DEBUG
+#define DEBUG 1
+#endif /*_BLD_DEBUG*/
+#endif /*DEBUG*/
+#if DEBUG
+extern void _vmmessage _ARG_((const char*, long, const char*, long));
+#define MESSAGE(s) _vmmessage(__FILE__,__LINE__,s,0)
+#define ABORT() (_Vmassert & VM_abort)
+#define CHECK() (_Vmassert & VM_check)
+#define ASSERT(p) ((p) ? 0 : (MESSAGE("Assertion failed"), ABORT() ? (abort(),0) : 0))
+#define COUNT(n) ((n) += 1)
+#else
+#define ABORT() (0)
+#define ASSERT(p)
+#define CHECK() (0)
+#define COUNT(n)
+#define MESSAGE(s) (0)
+#endif /*DEBUG*/
+
+#define VMPAGESIZE 8192
+#if _lib_getpagesize
+#define GETPAGESIZE(x) ((x) ? (x) : ((x)=getpagesize()) )
+#else
+#define GETPAGESIZE(x) ((x) = VMPAGESIZE)
+#endif
+
+/* Blocks are allocated such that their sizes are 0%(BITS+1)
+** This frees up enough low order bits to store state information
+*/
+#define BUSY (01) /* block is busy */
+#define PFREE (02) /* preceding block is free */
+#define JUNK (04) /* marked as freed but not yet processed */
+#define BITS (07) /* (BUSY|PFREE|JUNK) */
+#define ALIGNB (8) /* size must be a multiple of BITS+1 */
+
+#define ISBITS(w) ((w) & BITS)
+#define CLRBITS(w) ((w) &= ~BITS)
+#define CPYBITS(w,f) ((w) |= ((f)&BITS) )
+
+#define ISBUSY(w) ((w) & BUSY)
+#define SETBUSY(w) ((w) |= BUSY)
+#define CLRBUSY(w) ((w) &= ~BUSY)
+
+#define ISPFREE(w) ((w) & PFREE)
+#define SETPFREE(w) ((w) |= PFREE)
+#define CLRPFREE(w) ((w) &= ~PFREE)
+
+#define ISJUNK(w) ((w) & JUNK)
+#define SETJUNK(w) ((w) |= JUNK)
+#define CLRJUNK(w) ((w) &= ~JUNK)
+
+#define OFFSET(t,e) ((size_t)(&(((t*)0)->e)) )
+
+#define VMETHOD(vd) ((vd)->mode&VM_METHODS)
+
+/* lock and unlock regions during concurrent accesses */
+#define SETLOCK(vm,l) ((l) ? 0 : _vmlock((vm), 1) )
+#define CLRLOCK(vm,l) ((l) ? 0 : _vmlock((vm), 0) )
+
+/* local calls */
+#define KPVALLOC(vm,sz,func) (func((vm),(sz),1) )
+#define KPVRESIZE(vm,dt,sz,mv,func) (func((vm),(dt),(sz),(mv),1) )
+#define KPVFREE(vm,dt,func) (func((vm),(dt),1) )
+#define KPVADDR(vm,addr,func) (func((vm),(addr),1) )
+#define KPVSIZE(vm,addr,func) (func((vm),(addr),1) )
+#define KPVCOMPACT(vm,func) (func((vm),1) )
+#define KPVALIGN(vm,sz,al,func) (func((vm),(sz),(al),1) )
+
+/* ALIGN is chosen so that a block can store all primitive types.
+** It should also be a multiple of ALIGNB==(BITS+1) so the size field
+** of Block_t will always be 0%(BITS+1) as noted above.
+** Of paramount importance is the ALIGNA macro below. If the local compile
+** environment is strange enough that the below method does not calculate
+** ALIGNA right, then the code below should be commented out and ALIGNA
+** redefined to the appropriate requirement.
+*/
+union _align_u
+{ char c, *cp;
+ int i, *ip;
+ long l, *lp;
+ double d, *dp, ***dppp[8];
+ size_t s, *sp;
+ void(* fn)();
+ union _align_u* align;
+ Head_t* head;
+ Body_t* body;
+ Block_t* block;
+ Vmuchar_t a[ALIGNB];
+ _ast_fltmax_t ld, *ldp;
+ jmp_buf jmp;
+};
+struct _a_s
+{ char c;
+ union _align_u a;
+};
+#define ALIGNA (sizeof(struct _a_s) - sizeof(union _align_u))
+struct _align_s
+{ char data[MULTIPLE(ALIGNA,ALIGNB)];
+};
+#undef ALIGN /* bsd sys/param.h defines this */
+#define ALIGN sizeof(struct _align_s)
+
+/* make sure that the head of a block is a multiple of ALIGN */
+struct _head_s
+{ union
+ { Seg_t* seg; /* the containing segment */
+ Block_t* link; /* possible link list usage */
+ Pfobj_t* pf; /* profile structure pointer */
+ char* file; /* for file name in Vmdebug */
+ } seg;
+ union
+ { size_t size; /* size of data area in bytes */
+ Block_t* link; /* possible link list usage */
+ int line; /* for line number in Vmdebug */
+ } size;
+};
+#define HEADSIZE ROUND(sizeof(struct _head_s),ALIGN)
+union _head_u
+{ Vmuchar_t data[HEADSIZE]; /* to standardize size */
+ struct _head_s head;
+};
+
+/* now make sure that the body of a block is a multiple of ALIGN */
+struct _body_s
+{ Block_t* link; /* next in link list */
+ Block_t* left; /* left child in free tree */
+ Block_t* right; /* right child in free tree */
+ Block_t** self; /* self pointer when free */
+};
+#define BODYSIZE ROUND(sizeof(struct _body_s),ALIGN)
+
+union _body_u
+{ Vmuchar_t data[BODYSIZE]; /* to standardize size */
+ struct _body_s body;
+ Block_t* self[1];
+};
+
+/* After all the songs and dances, we should now have:
+** sizeof(Head_t)%ALIGN == 0
+** sizeof(Body_t)%ALIGN == 0
+** and sizeof(Block_t) = sizeof(Head_t)+sizeof(Body_t)
+*/
+struct _block_s
+{ Head_t head;
+ Body_t body;
+};
+
+/* requirements for smallest block type */
+struct _tiny_s
+{ Block_t* link;
+ Block_t* self;
+};
+#define TINYSIZE ROUND(sizeof(struct _tiny_s),ALIGN)
+#define S_TINY 1 /* # of tiny blocks */
+#define MAXTINY (S_TINY*ALIGN + TINYSIZE)
+#define TLEFT(b) ((b)->head.head.seg.link) /* instead of LEFT */
+#define TINIEST(b) (SIZE(b) == TINYSIZE) /* this type uses TLEFT */
+
+#define DIV(x,y) ((y) == 8 ? ((x)>>3) : (x)/(y) )
+#define INDEX(s) DIV((s)-TINYSIZE,ALIGN)
+
+/* small block types kept in separate caches for quick allocation */
+#define S_CACHE 6 /* # of types of small blocks to be cached */
+#define N_CACHE 32 /* on allocation, create this many at a time */
+#define MAXCACHE (S_CACHE*ALIGN + TINYSIZE)
+#define C_INDEX(s) (s < MAXCACHE ? INDEX(s) : S_CACHE)
+
+#define TINY(vd) ((vd)->tiny)
+#define CACHE(vd) ((vd)->cache)
+
+struct _vmdata_s /* core region data - could be in shared/persistent memory */
+{ unsigned int lock; /* lock status */
+ int mode; /* current mode for region */
+ size_t incr; /* allocate in multiple of this */
+ size_t pool; /* size of an elt in a Vmpool region */
+ Seg_t* seg; /* list of segments */
+ Block_t* free; /* most recent free block */
+ Block_t* wild; /* wilderness block */
+ Block_t* root; /* root of free tree */
+ Block_t* tiny[S_TINY]; /* small blocks */
+ Block_t* cache[S_CACHE+1]; /* delayed free blocks */
+};
+
+#include "vmalloc.h"
+
+#if !_PACKAGE_ast
+/* we don't use these here and they interfere with some local names */
+#undef malloc
+#undef free
+#undef realloc
+#endif
+
+/* segment structure */
+struct _seg_s
+{ Vmdata_t* vmdt; /* the data region holding this */
+ Seg_t* next; /* next segment */
+ Void_t* addr; /* starting segment address */
+ size_t extent; /* extent of segment */
+ Vmuchar_t* baddr; /* bottom of usable memory */
+ size_t size; /* allocable size */
+ Block_t* free; /* recent free blocks */
+ Block_t* last; /* Vmlast last-allocated block */
+};
+
+/* starting block of a segment */
+#define SEGBLOCK(s) ((Block_t*)(((Vmuchar_t*)(s)) + ROUND(sizeof(Seg_t),ALIGN)))
+
+/* short-hands for block data */
+#define SEG(b) ((b)->head.head.seg.seg)
+#define SEGLINK(b) ((b)->head.head.seg.link)
+#define SIZE(b) ((b)->head.head.size.size)
+#define SIZELINK(b) ((b)->head.head.size.link)
+#define LINK(b) ((b)->body.body.link)
+#define LEFT(b) ((b)->body.body.left)
+#define RIGHT(b) ((b)->body.body.right)
+
+#define DATA(b) ((Void_t*)((b)->body.data) )
+#define BLOCK(d) ((Block_t*)((char*)(d) - sizeof(Head_t)) )
+#define SELF(b) (b)->body.self[SIZE(b)/sizeof(Block_t*)-1]
+#define LAST(b) (*((Block_t**)(((char*)(b)) - sizeof(Block_t*)) ) )
+#define NEXT(b) ((Block_t*)((b)->body.data + SIZE(b)) )
+
+/* functions to manipulate link lists of elts of the same size */
+#define SETLINK(b) (RIGHT(b) = (b) )
+#define ISLINK(b) (RIGHT(b) == (b) )
+#define UNLINK(vd,b,i,t) \
+ ((((t) = LINK(b)) ? (LEFT(t) = LEFT(b)) : NIL(Block_t*) ), \
+ (((t) = LEFT(b)) ? (LINK(t) = LINK(b)) : (TINY(vd)[i] = LINK(b)) ) )
+
+/* delete a block from a link list or the free tree.
+** The test in the below macro is worth scratching your head a bit.
+** Even though tiny blocks (size < BODYSIZE) are kept in separate lists,
+** only the TINIEST ones require TLEFT(b) for the back link. Since this
+** destroys the SEG(b) pointer, it must be carefully restored in bestsearch().
+** Other tiny blocks have enough space to use the usual LEFT(b).
+** In this case, I have also carefully arranged so that RIGHT(b) and
+** SELF(b) can be overlapped and the test ISLINK() will go through.
+*/
+#define REMOVE(vd,b,i,t,func) \
+ ((!TINIEST(b) && ISLINK(b)) ? UNLINK((vd),(b),(i),(t)) : \
+ func((vd),SIZE(b),(b)) )
+
+/* see if a block is the wilderness block */
+#define SEGWILD(b) (((b)->body.data+SIZE(b)+sizeof(Head_t)) >= SEG(b)->baddr)
+#define VMWILD(vd,b) (((b)->body.data+SIZE(b)+sizeof(Head_t)) >= vd->seg->baddr)
+
+#define VMFLF(vm,fi,ln,fn) ((fi) = (vm)->file, (vm)->file = NIL(char*), \
+ (ln) = (vm)->line, (vm)->line = 0 , \
+ (fn) = (vm)->func, (vm)->func = NIL(Void_t*) )
+
+/* The lay-out of a Vmprofile block is this:
+** seg_ size ----data---- _pf_ size
+** _________ ____________ _________
+** seg_, size: header required by Vmbest.
+** data: actual data block.
+** _pf_: pointer to the corresponding Pfobj_t struct
+** size: the true size of the block.
+** So each block requires an extra Head_t.
+*/
+#define PF_EXTRA sizeof(Head_t)
+#define PFDATA(d) ((Head_t*)((Vmuchar_t*)(d)+(SIZE(BLOCK(d))&~BITS)-sizeof(Head_t)) )
+#define PFOBJ(d) (PFDATA(d)->head.seg.pf)
+#define PFSIZE(d) (PFDATA(d)->head.size.size)
+
+/* The lay-out of a block allocated by Vmdebug is this:
+** seg_ size file size seg_ magi ----data---- --magi-- magi line
+** --------- --------- --------- ------------ -------- ---------
+** seg_,size: header required by Vmbest management.
+** file: the file where it was created.
+** size: the true byte count of the block
+** seg_: should be the same as the previous seg_.
+** This allows the function vmregion() to work.
+** magi: magic bytes to detect overwrites.
+** data: the actual data block.
+** magi: more magic bytes.
+** line: the line number in the file where it was created.
+** So for each allocated block, we'll need 3 extra Head_t.
+*/
+
+/* convenient macros for accessing the above fields */
+#define DB_HEAD (2*sizeof(Head_t))
+#define DB_TAIL (2*sizeof(Head_t))
+#define DB_EXTRA (DB_HEAD+DB_TAIL)
+#define DBBLOCK(d) ((Block_t*)((Vmuchar_t*)(d) - 3*sizeof(Head_t)) )
+#define DBBSIZE(d) (SIZE(DBBLOCK(d)) & ~BITS)
+#define DBSEG(d) (((Head_t*)((Vmuchar_t*)(d) - sizeof(Head_t)))->head.seg.seg )
+#define DBSIZE(d) (((Head_t*)((Vmuchar_t*)(d) - 2*sizeof(Head_t)))->head.size.size )
+#define DBFILE(d) (((Head_t*)((Vmuchar_t*)(d) - 2*sizeof(Head_t)))->head.seg.file )
+#define DBLN(d) (((Head_t*)((Vmuchar_t*)DBBLOCK(d)+DBBSIZE(d)))->head.size.line )
+#define DBLINE(d) (DBLN(d) < 0 ? -DBLN(d) : DBLN(d))
+
+/* forward/backward translation for addresses between Vmbest and Vmdebug */
+#define DB2BEST(d) ((Vmuchar_t*)(d) - 2*sizeof(Head_t))
+#define DB2DEBUG(b) ((Vmuchar_t*)(b) + 2*sizeof(Head_t))
+
+/* set file and line number, note that DBLN > 0 so that DBISBAD will work */
+#define DBSETFL(d,f,l) (DBFILE(d) = (f), DBLN(d) = (f) ? (l) : 1)
+
+/* set and test the state of known to be corrupted */
+#define DBSETBAD(d) (DBLN(d) > 0 ? (DBLN(d) = -DBLN(d)) : -1)
+#define DBISBAD(d) (DBLN(d) <= 0)
+
+#define DB_MAGIC 0255 /* 10101101 */
+
+/* compute the bounds of the magic areas */
+#define DBHEAD(d,begp,endp) \
+ (((begp) = (Vmuchar_t*)(&DBSEG(d)) + sizeof(Seg_t*)), ((endp) = (d)) )
+#define DBTAIL(d,begp,endp) \
+ (((begp) = (Vmuchar_t*)(d)+DBSIZE(d)), ((endp) = (Vmuchar_t*)(&DBLN(d))) )
+
+
+/* external symbols for use inside vmalloc only */
+typedef Block_t* (*Vmsearch_f)_ARG_((Vmdata_t*, size_t, Block_t*));
+typedef struct _vmextern_s
+{ Block_t* (*vm_extend)_ARG_((Vmalloc_t*, size_t, Vmsearch_f ));
+ ssize_t (*vm_truncate)_ARG_((Vmalloc_t*, Seg_t*, size_t, int));
+ size_t vm_pagesize;
+ char* (*vm_strcpy)_ARG_((char*, const char*, int));
+ char* (*vm_itoa)_ARG_((Vmulong_t, int));
+ void (*vm_trace)_ARG_((Vmalloc_t*,
+ Vmuchar_t*, Vmuchar_t*, size_t, size_t));
+ void (*vm_pfclose)_ARG_((Vmalloc_t*));
+ unsigned int vm_lock;
+ int vm_assert;
+ int vm_options;
+} Vmextern_t;
+
+#define _Vmextend (_Vmextern.vm_extend)
+#define _Vmtruncate (_Vmextern.vm_truncate)
+#define _Vmpagesize (_Vmextern.vm_pagesize)
+#define _Vmstrcpy (_Vmextern.vm_strcpy)
+#define _Vmitoa (_Vmextern.vm_itoa)
+#define _Vmtrace (_Vmextern.vm_trace)
+#define _Vmpfclose (_Vmextern.vm_pfclose)
+#define _Vmlock (_Vmextern.vm_lock)
+#define _Vmassert (_Vmextern.vm_assert)
+#define _Vmoptions (_Vmextern.vm_options)
+
+#define VMOPTIONS() do { if (!_Vmoptions) { _vmoptions(); } } while (0)
+
+extern int _vmbestcheck _ARG_((Vmdata_t*, Block_t*));
+extern int _vmlock _ARG_((Vmalloc_t*, int));
+extern void _vmoptions _ARG_((void));
+
+_BEGIN_EXTERNS_
+
+extern Vmextern_t _Vmextern;
+
+#if _PACKAGE_ast
+
+#if _npt_getpagesize
+extern int getpagesize _ARG_((void));
+#endif
+#if _npt_sbrk
+extern int brk _ARG_(( void* ));
+extern Void_t* sbrk _ARG_(( ssize_t ));
+#endif
+
+#else
+
+#if _hdr_unistd
+#include <unistd.h>
+#else
+extern void abort _ARG_(( void ));
+extern ssize_t write _ARG_(( int, const void*, size_t ));
+extern int getpagesize _ARG_((void));
+extern Void_t* sbrk _ARG_((ssize_t));
+#endif
+
+#if !__STDC__ && !_hdr_stdlib
+extern size_t strlen _ARG_(( const char* ));
+extern char* strcpy _ARG_(( char*, const char* ));
+extern int strcmp _ARG_(( const char*, const char* ));
+extern int atexit _ARG_(( void(*)(void) ));
+extern char* getenv _ARG_(( const char* ));
+extern Void_t* memcpy _ARG_(( Void_t*, const Void_t*, size_t ));
+extern Void_t* memset _ARG_(( Void_t*, int, size_t ));
+#else
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+/* for vmexit.c */
+extern int onexit _ARG_(( void(*)(void) ));
+extern void _exit _ARG_(( int ));
+extern void _cleanup _ARG_(( void ));
+
+#endif /*_PACKAGE_ast*/
+
+/* for vmdcsbrk.c */
+#if !_typ_ssize_t
+typedef int ssize_t;
+#endif
+
+_END_EXTERNS_
+
+#endif /* _VMHDR_H */
diff --git a/src/lib/libast/vmalloc/vmlast.c b/src/lib/libast/vmalloc/vmlast.c
new file mode 100644
index 0000000..31f70b7
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmlast.c
@@ -0,0 +1,431 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmlast(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Allocation with freeing and reallocing of last allocated block only.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+
+#if __STD_C
+static Void_t* lastalloc(Vmalloc_t* vm, size_t size, int local)
+#else
+static Void_t* lastalloc(vm, size, local)
+Vmalloc_t* vm;
+size_t size;
+int local;
+#endif
+{
+ Block_t *tp, *next;
+ Seg_t *seg, *last;
+ size_t s;
+ Vmdata_t *vd = vm->data;
+ size_t orgsize = size;
+
+ SETLOCK(vm, local);
+
+ size = size < ALIGN ? ALIGN : ROUND(size,ALIGN);
+ for(last = NIL(Seg_t*), seg = vd->seg; seg; last = seg, seg = seg->next)
+ { if(!(tp = seg->free) || (SIZE(tp)+sizeof(Head_t)) < size)
+ continue;
+ if(last)
+ { last->next = seg->next;
+ seg->next = vd->seg;
+ vd->seg = seg;
+ }
+ goto got_block;
+ }
+
+ /* there is no usable free space in region, try extending */
+ if((tp = (*_Vmextend)(vm,size,NIL(Vmsearch_f))) )
+ { seg = SEG(tp);
+ goto got_block;
+ }
+ else goto done;
+
+got_block:
+ if((s = SIZE(tp)) >= size)
+ { next = (Block_t*)((Vmuchar_t*)tp+size);
+ SIZE(next) = s - size;
+ SEG(next) = seg;
+ seg->free = next;
+ }
+ else seg->free = NIL(Block_t*);
+
+ vd->free = seg->last = tp;
+
+ if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
+ (*_Vmtrace)(vm, NIL(Vmuchar_t*), (Vmuchar_t*)tp, orgsize, 0);
+
+done:
+ CLRLOCK(vm, local);
+
+ return (Void_t*)tp;
+}
+
+#if __STD_C
+static int lastfree(Vmalloc_t* vm, reg Void_t* data, int local )
+#else
+static int lastfree(vm, data, local)
+Vmalloc_t* vm;
+Void_t* data;
+int local;
+#endif
+{
+ Seg_t *seg;
+ Block_t *fp;
+ size_t s;
+ Vmdata_t *vd = vm->data;
+
+ if(!data)
+ return 0;
+
+ SETLOCK(vm, local);
+
+ if(data != (Void_t*)vd->free)
+ data = NIL(Void_t*); /* signaling an error */
+ else
+ { seg = vd->seg;
+ if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
+ { if(seg->free )
+ s = (Vmuchar_t*)(seg->free) - (Vmuchar_t*)data;
+ else s = (Vmuchar_t*)BLOCK(seg->baddr) - (Vmuchar_t*)data;
+ (*_Vmtrace)(vm, (Vmuchar_t*)data, NIL(Vmuchar_t*), s, 0);
+ }
+
+ vd->free = NIL(Block_t*);
+ fp = (Block_t*)data;
+ SEG(fp) = seg;
+ SIZE(fp) = ((Vmuchar_t*)BLOCK(seg->baddr) - (Vmuchar_t*)data) - sizeof(Head_t);
+ seg->free = fp;
+ seg->last = NIL(Block_t*);
+ }
+
+ CLRLOCK(vm, local);
+
+ return data ? 0 : -1;
+}
+
+#if __STD_C
+static Void_t* lastresize(Vmalloc_t* vm, reg Void_t* data, size_t size, int type, int local)
+#else
+static Void_t* lastresize(vm, data, size, type, local )
+Vmalloc_t* vm;
+reg Void_t* data;
+size_t size;
+int type;
+int local;
+#endif
+{
+ Block_t *tp;
+ Seg_t *seg;
+ ssize_t s, ds;
+ Void_t *addr;
+ size_t oldsize = 0;
+ Void_t *orgdata = data;
+ size_t orgsize = size;
+ Vmdata_t *vd = vm->data;
+
+ if(!data)
+ { data = lastalloc(vm, size, local);
+ if(data && (type&VM_RSZERO) )
+ memset(data, 0, size);
+ return data;
+ }
+ if(size <= 0)
+ { (void)lastfree(vm, data, local);
+ return NIL(Void_t*);
+ }
+
+ SETLOCK(vm, local);
+
+ if(data == (Void_t*)vd->free)
+ seg = vd->seg;
+ else
+ { /* see if it was one of ours */
+ for(seg = vd->seg; seg; seg = seg->next)
+ if(data >= seg->addr && data < (Void_t*)seg->baddr)
+ break;
+ if(!seg || (VLONG(data)%ALIGN) != 0 ||
+ (seg->last && (Vmuchar_t*)data > (Vmuchar_t*)seg->last) )
+ { data = NIL(Void_t*);
+ goto done;
+ }
+ }
+
+ /* set 's' to be the current available space */
+ if(data != seg->last)
+ { if(seg->last && (Vmuchar_t*)data < (Vmuchar_t*)seg->last)
+ oldsize = (Vmuchar_t*)seg->last - (Vmuchar_t*)data;
+ else oldsize = (Vmuchar_t*)BLOCK(seg->baddr) - (Vmuchar_t*)data;
+ s = -1;
+ }
+ else
+ { s = (Vmuchar_t*)BLOCK(seg->baddr) - (Vmuchar_t*)data;
+ if(!(tp = seg->free) )
+ oldsize = s;
+ else
+ { oldsize = (Vmuchar_t*)tp - (Vmuchar_t*)data;
+ seg->free = NIL(Block_t*);
+ }
+ }
+
+ size = size < ALIGN ? ALIGN : ROUND(size,ALIGN);
+ if(s < 0 || (ssize_t)size > s)
+ { if(s >= 0) /* amount to extend */
+ { ds = size-s; ds = ROUND(ds,vd->incr);
+ addr = (*vm->disc->memoryf)(vm, seg->addr, seg->extent,
+ seg->extent+ds, vm->disc);
+ if(addr == seg->addr)
+ { s += ds;
+ seg->size += ds;
+ seg->extent += ds;
+ seg->baddr += ds;
+ SIZE(BLOCK(seg->baddr)) = BUSY;
+ }
+ else goto do_alloc;
+ }
+ else
+ { do_alloc:
+ if(!(type&(VM_RSMOVE|VM_RSCOPY)) )
+ data = NIL(Void_t*);
+ else
+ { tp = vd->free;
+ if(!(addr = KPVALLOC(vm,size,lastalloc)) )
+ { vd->free = tp;
+ data = NIL(Void_t*);
+ }
+ else
+ { if(type&VM_RSCOPY)
+ { ds = oldsize < size ? oldsize : size;
+ memcpy(addr, data, ds);
+ }
+
+ if(s >= 0 && seg != vd->seg)
+ { tp = (Block_t*)data;
+ SEG(tp) = seg;
+ SIZE(tp) = s - sizeof(Head_t);
+ seg->free = tp;
+ }
+
+ /* new block and size */
+ data = addr;
+ seg = vd->seg;
+ s = (Vmuchar_t*)BLOCK(seg->baddr) -
+ (Vmuchar_t*)data;
+ seg->free = NIL(Block_t*);
+ }
+ }
+ }
+ }
+
+ if(data)
+ { if(s >= (ssize_t)(size+sizeof(Head_t)) )
+ { tp = (Block_t*)((Vmuchar_t*)data + size);
+ SEG(tp) = seg;
+ SIZE(tp) = (s - size) - sizeof(Head_t);
+ seg->free = tp;
+ }
+
+ vd->free = seg->last = (Block_t*)data;
+
+ if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
+ (*_Vmtrace)(vm,(Vmuchar_t*)orgdata,(Vmuchar_t*)data,orgsize,0);
+
+ if((type&VM_RSZERO) && size > oldsize)
+ memset((Void_t*)((Vmuchar_t*)data + oldsize), 0, size-oldsize);
+ }
+
+done: CLRLOCK(vm, local);
+
+ return data;
+}
+
+
+#if __STD_C
+static long lastaddr(Vmalloc_t* vm, Void_t* addr, int local)
+#else
+static long lastaddr(vm, addr, local)
+Vmalloc_t* vm;
+Void_t* addr;
+int local;
+#endif
+{
+ long offset;
+ Vmdata_t *vd = vm->data;
+
+ SETLOCK(vm, local);
+
+ if(!vd->free || addr < (Void_t*)vd->free || addr >= (Void_t*)vd->seg->baddr)
+ offset = -1L;
+ else offset = (Vmuchar_t*)addr - (Vmuchar_t*)vd->free;
+
+ CLRLOCK(vm, local);
+
+ return offset;
+}
+
+#if __STD_C
+static long lastsize(Vmalloc_t* vm, Void_t* addr, int local)
+#else
+static long lastsize(vm, addr, local)
+Vmalloc_t* vm;
+Void_t* addr;
+int local;
+#endif
+{
+ long size;
+ Vmdata_t *vd = vm->data;
+
+ SETLOCK(vm, local);
+
+ if(!vd->free || addr != (Void_t*)vd->free )
+ size = -1L;
+ else if(vd->seg->free)
+ size = (Vmuchar_t*)vd->seg->free - (Vmuchar_t*)addr;
+ else size = (Vmuchar_t*)vd->seg->baddr - (Vmuchar_t*)addr - sizeof(Head_t);
+
+ CLRLOCK(vm, local);
+
+ return size;
+}
+
+#if __STD_C
+static int lastcompact(Vmalloc_t* vm, int local)
+#else
+static int lastcompact(vm, local)
+Vmalloc_t* vm;
+int local;
+#endif
+{
+ ssize_t s;
+ Block_t *fp;
+ Seg_t *seg, *next;
+ Vmdata_t *vd = vm->data;
+
+ SETLOCK(vm, local);
+
+ for(seg = vd->seg; seg; seg = next)
+ { next = seg->next;
+
+ if(!(fp = seg->free))
+ continue;
+
+ seg->free = NIL(Block_t*);
+ if(seg->size == (s = SIZE(fp)&~BITS))
+ s = seg->extent;
+ else s += sizeof(Head_t);
+
+ if((*_Vmtruncate)(vm,seg,s,1) == s)
+ seg->free = fp;
+ }
+
+ if((vd->mode&VM_TRACE) && _Vmtrace)
+ (*_Vmtrace)(vm,(Vmuchar_t*)0,(Vmuchar_t*)0,0,0);
+
+ CLRLOCK(vm, local);
+ return 0;
+}
+
+#if __STD_C
+static Void_t* lastalign(Vmalloc_t* vm, size_t size, size_t align, int local)
+#else
+static Void_t* lastalign(vm, size, align, local)
+Vmalloc_t* vm;
+size_t size;
+size_t align;
+int local;
+#endif
+{
+ Vmuchar_t *data;
+ Seg_t *seg;
+ Block_t *next;
+ size_t s, orgsize = size, orgalign = align;
+ Vmdata_t *vd = vm->data;
+
+ if(size <= 0 || align <= 0)
+ return NIL(Void_t*);
+
+ SETLOCK(vm, local);
+
+ size = size <= TINYSIZE ? TINYSIZE : ROUND(size,ALIGN);
+ align = MULTIPLE(align,ALIGN);
+
+ s = size + align;
+ if(!(data = (Vmuchar_t*)KPVALLOC(vm,s,lastalloc)) )
+ goto done;
+
+ /* find the segment containing this block */
+ for(seg = vd->seg; seg; seg = seg->next)
+ if(seg->last == (Block_t*)data)
+ break;
+ /**/ASSERT(seg);
+
+ /* get a suitably aligned address */
+ if((s = (size_t)(VLONG(data)%align)) != 0)
+ data += align-s; /**/ASSERT((VLONG(data)%align) == 0);
+
+ /* free the unused tail */
+ next = (Block_t*)(data+size);
+ if((s = (seg->baddr - (Vmuchar_t*)next)) >= sizeof(Block_t))
+ { SEG(next) = seg;
+ SIZE(next) = s - sizeof(Head_t);
+ seg->free = next;
+ }
+
+ vd->free = seg->last = (Block_t*)data;
+
+ if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
+ (*_Vmtrace)(vm,NIL(Vmuchar_t*),data,orgsize,orgalign);
+
+done:
+ CLRLOCK(vm, local);
+
+ return (Void_t*)data;
+}
+
+/* Public method for free-1 allocation */
+static Vmethod_t _Vmlast =
+{
+ lastalloc,
+ lastresize,
+ lastfree,
+ lastaddr,
+ lastsize,
+ lastcompact,
+ lastalign,
+ VM_MTLAST
+};
+
+__DEFINE__(Vmethod_t*,Vmlast,&_Vmlast);
+
+#ifdef NoF
+NoF(vmlast)
+#endif
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmmopen.c b/src/lib/libast/vmalloc/vmmopen.c
new file mode 100644
index 0000000..4523cae
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmmopen.c
@@ -0,0 +1,518 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmmapopen(){}
+
+#else
+
+#include "vmhdr.h"
+#include <sys/types.h>
+#include <string.h>
+#if _hdr_unistd
+#include <unistd.h>
+#endif
+
+#undef ALIGN /* some sys/param.h define this */
+
+#include <sys/mman.h> /* mmap() headers */
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <sys/shm.h> /* shm headers */
+#include <sys/ipc.h>
+
+#undef ALIGN
+#define ALIGN sizeof(struct _align_s)
+
+/* Create a region to allocate based on mmap() or shmget().
+** Both ways provide for share memory allocation.
+** mmap() also allows for allocating persistent data.
+**
+** Written by Kiem-Phong Vo (kpv@research.att.com)
+*/
+
+#define MM_INIT 001 /* initialization mode */
+
+#define MM_RELEASE 010 /* release share mem */
+#define MM_CLEANUP 020 /* clean up resources */
+
+/* magic word signaling region is being initialized */
+#define MM_LETMEDOIT ((unsigned int)(('N'<<24) | ('B'<<16) | ('&'<<8) | ('I')) )
+
+/* magic word signaling file/segment is ready */
+#define MM_MAGIC ((unsigned int)(('P'<<24) | ('&'<<16) | ('N'<<8) | ('8')) )
+
+/* default mimimum region size */
+#define MM_MINSIZE (64*_Vmpagesize)
+
+/* macros to get the data section and size */
+#define MMHEAD(file) ROUND(sizeof(Mmvm_t)+strlen(file), ALIGN)
+#define MMDATA(mmvm) ((Vmuchar_t*)(mmvm)->base + MMHEAD(mmvm->file))
+#define MMSIZE(mmvm) ((mmvm)->size - MMHEAD(mmvm->file))
+
+#ifdef S_IRUSR
+#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
+#else
+#define FILE_MODE 0644
+#endif
+
+/* to store key/value pairs for application */
+typedef struct _mmuser_s Mmuser_t;
+struct _mmuser_s
+{ Mmuser_t* next; /* link list */
+ int key; /* identifying key */
+ Void_t* val; /* associated value */
+};
+
+typedef struct _mmvm_s
+{ unsigned int magic; /* magic bytes */
+ Void_t* base; /* address to map to */
+ ssize_t size; /* total data size */
+ ssize_t busy; /* amount in use */
+ Mmuser_t* user; /* stored (key,val)'s */
+ int proj; /* project number */
+ char file[1];/* file name */
+} Mmvm_t;
+
+typedef struct _mmdisc_s
+{ Vmdisc_t disc; /* Vmalloc discipline */
+ int flag; /* various modes */
+ Mmvm_t* mmvm; /* shared memory data */
+ ssize_t size; /* desired file size */
+ int shmid; /* ID of the shared mem */
+ int proj; /* shm project ID */
+ char file[1];/* backing store/ftok() */
+} Mmdisc_t;
+
+#if DEBUG
+#include <stdio.h>
+#include <string.h>
+int _vmmdump(Vmalloc_t* vm, int fd)
+{
+ char mesg[1024];
+ Mmdisc_t *mmdc = (Mmdisc_t*)vm->disc;
+
+ fd = fd < 0 ? 2 : fd;
+ sprintf(mesg, "File: %s\n", mmdc->file ); write(fd, mesg, strlen(mesg));
+ sprintf(mesg, "Project: %10d\n", mmdc->proj); write(fd, mesg, strlen(mesg));
+ sprintf(mesg, "Memory: %#010lx\n", mmdc->mmvm); write(fd, mesg, strlen(mesg));
+ sprintf(mesg, "Size: %10d\n", mmdc->size); write(fd, mesg, strlen(mesg));
+ sprintf(mesg, "Shmid: %10d\n", mmdc->shmid); write(fd, mesg, strlen(mesg));
+
+ sprintf(mesg, "File header:\n"); write(fd, mesg, strlen(mesg));
+ sprintf(mesg, "Magic: %10d\n", mmdc->mmvm->magic); write(fd, mesg, strlen(mesg));
+ sprintf(mesg, "Base: %#010lx\n", mmdc->mmvm->base); write(fd, mesg, strlen(mesg));
+ sprintf(mesg, "Size: %10d\n", mmdc->mmvm->size); write(fd, mesg, strlen(mesg));
+ sprintf(mesg, "Busy: %10d\n", mmdc->mmvm->busy); write(fd, mesg, strlen(mesg));
+ return 0;
+}
+#endif /*DEBUG*/
+
+/* fix the mapped address for a region */
+static Mmvm_t* mmfix(Mmvm_t* mmvm, Mmdisc_t* mmdc, int fd)
+{
+ Void_t *base = mmvm->base;
+ ssize_t size = mmvm->size;
+
+ if(base != (Void_t*)mmvm) /* mmvm is not right yet */
+ { /**/ASSERT(!base || (base && (VLONG(base)%_Vmpagesize) == 0) );
+ if(mmdc->proj < 0)
+ { munmap((Void_t*)mmvm, size);
+ mmvm = (Mmvm_t*)mmap(base, size, (PROT_READ|PROT_WRITE),
+ (MAP_FIXED|MAP_SHARED), fd, (off_t)0 );
+ }
+ else
+ { shmdt((Void_t*)mmvm);
+ mmvm = (Mmvm_t*)shmat(mmdc->shmid, base, 0);
+ }
+ if(!mmvm || mmvm == (Mmvm_t*)(-1) )
+ mmvm = NIL(Mmvm_t*);
+ }
+
+ return mmvm;
+}
+
+/* initialize region data */
+static int mminit(Mmdisc_t* mmdc)
+{
+ struct shmid_ds shmds;
+ Void_t *base;
+ int try, k;
+ int fd = -1;
+ key_t key = -1;
+ ssize_t extent, size = 0;
+ Mmvm_t *mmvm = NIL(Mmvm_t*);
+ int rv = -1;
+
+ if(mmdc->mmvm) /* already done this */
+ return 0;
+
+ /* fixed size region so make it reasonably large */
+ if((size = mmdc->size) < MM_MINSIZE )
+ size = MM_MINSIZE;
+ size += MMHEAD(mmdc->file) + ALIGN;
+ size = ROUND(size, _Vmpagesize);
+
+ /* this op can happen simultaneously in different processes */
+ if((fd = open(mmdc->file, O_RDWR|O_CREAT, FILE_MODE)) < 0)
+ return -1;
+
+ /* get/create the initial segment of data */
+ if(mmdc->proj < 0 ) /* proj < 0 means doing mmap() */
+ { /* Note that the location being written to is always zero! */
+ if((extent = (ssize_t)lseek(fd, (off_t)0, SEEK_END)) < 0)
+ goto done;
+ if(extent < size) /* make the file size large enough */
+ if(lseek(fd, (off_t)size, 0) != (off_t)size || write(fd, "", 1) != 1 )
+ goto done;
+
+ /* map the file into memory */
+ mmvm = (Mmvm_t*)mmap(NIL(Void_t*), size, (PROT_READ|PROT_WRITE),
+ MAP_SHARED, fd, (off_t)0 );
+ }
+ else
+ { /* make the key and get/create an id for the share mem segment */
+ if((key = ftok(mmdc->file, mmdc->proj)) < 0 )
+ goto done;
+ if((mmdc->shmid = shmget(key, size, IPC_CREAT|FILE_MODE)) < 0 )
+ goto done;
+
+ /* map the data segment into memory */
+ mmvm = (Mmvm_t*)shmat(mmdc->shmid, NIL(Void_t*), 0);
+ }
+
+ if(!mmvm || mmvm == (Mmvm_t*)(-1) ) /* initial mapping failed */
+ goto done;
+
+ /* all processes compete for the chore to initialize data */
+ if(asocasint(&mmvm->magic, 0, MM_LETMEDOIT) == 0 ) /* lucky winner: us! */
+ { if(!(base = vmmaddress(size)) ) /* get a suitable base for the map */
+ base = (Void_t*)mmvm;
+ mmdc->flag |= MM_INIT;
+ mmvm->base = base;
+ mmvm->size = size;
+ mmvm->busy = 0;
+ mmvm->proj = mmdc->proj;
+ strcpy(mmvm->file, mmdc->file);
+ if(mmdc->proj < 0 ) /* flush to file */
+ msync((Void_t*)mmvm, MMHEAD(mmvm->file), MS_SYNC);
+
+ if(mmvm->base != (Void_t*)mmvm) /* not yet at the right address */
+ if(!(mmvm = mmfix(mmvm, mmdc, fd)) )
+ goto done;
+ rv = 0; /* success, return this value to indicate a new map */
+ }
+ else /* wait for someone else to finish initialization */
+ { /**/ASSERT(!(mmdc->flag&MM_INIT));
+ if(mmvm->magic != MM_LETMEDOIT && mmvm->magic != MM_MAGIC)
+ goto done;
+
+ for(try = 0, k = 0;; ASOLOOP(k) ) /* waiting */
+ { if(asocasint(&mmvm->magic, MM_MAGIC, MM_MAGIC) == MM_MAGIC )
+ break;
+ else if((try += 1) <= 0 ) /* too many tries */
+ goto done;
+ }
+
+ /* mapped the wrong memory */
+ if(mmvm->proj != mmdc->proj || strcmp(mmvm->file, mmdc->file) != 0 )
+ goto done;
+
+ if(mmvm->base != (Void_t*)mmvm) /* not yet at the right address */
+ if(!(mmvm = mmfix(mmvm, mmdc, fd)) )
+ goto done;
+ rv = 1; /* success, return this value to indicate a finished map */
+ }
+
+done: (void)close(fd);
+
+ if(rv >= 0 ) /* successful construction of region */
+ { /**/ASSERT(mmvm && mmvm != (Mmvm_t*)(-1));
+ mmdc->mmvm = mmvm;
+ }
+ else if(mmvm && mmvm != (Mmvm_t*)(-1)) /* error, remove map */
+ { if(mmdc->proj < 0)
+ (void)munmap((Void_t*)mmvm, size);
+ else (void)shmdt((Void_t*)mmvm);
+ }
+
+ return rv;
+}
+
+#if __STD_C /* end a file mapping */
+static int mmend(Mmdisc_t* mmdc)
+#else
+static int mmend(mmdc)
+Mmdisc_t* mmdc;
+#endif
+{
+ Mmvm_t *mmvm;
+ struct shmid_ds shmds;
+
+ if(!(mmvm = mmdc->mmvm) )
+ return 0;
+
+ if(mmdc->proj < 0 )
+ { (void)msync(mmvm->base, mmvm->size, MS_ASYNC);
+ if(mmdc->flag&MM_RELEASE)
+ { if(mmvm->base )
+ (void)munmap(mmvm->base, mmvm->size);
+ }
+ if(mmdc->flag&MM_CLEANUP)
+ (void)unlink(mmdc->file);
+ }
+ else
+ { if(mmdc->flag&MM_RELEASE)
+ { if(mmvm->base )
+ (void)shmdt(mmvm->base);
+ }
+ if(mmdc->flag&MM_CLEANUP)
+ { if(mmdc->shmid >= 0 )
+ (void)shmctl(mmdc->shmid, IPC_RMID, &shmds);
+ }
+ }
+
+ mmdc->mmvm = NIL(Mmvm_t*);
+ return 0;
+}
+
+#if __STD_C
+static Void_t* mmgetmem(Vmalloc_t* vm, Void_t* caddr,
+ size_t csize, size_t nsize, Vmdisc_t* disc)
+#else
+static Void_t* mmgetmem(vm, caddr, csize, nsize, disc)
+Vmalloc_t* vm;
+Void_t* caddr;
+size_t csize;
+size_t nsize;
+Vmdisc_t* disc;
+#endif
+{
+ Mmvm_t *mmvm;
+ Mmdisc_t *mmdc = (Mmdisc_t*)disc;
+
+ if(!(mmvm = mmdc->mmvm) ) /* bad data */
+ return NIL(Void_t*);
+
+ /* this region allows only a single busy block! */
+ if(caddr) /* resizing/freeing an existing block */
+ { if(caddr == MMDATA(mmvm) && nsize <= MMSIZE(mmvm) )
+ { mmvm->busy = nsize;
+ return MMDATA(mmvm);
+ }
+ else return NIL(Void_t*);
+ }
+ else /* requesting a new block */
+ { if(mmvm->busy == 0 )
+ { mmvm->busy = nsize;
+ return MMDATA(mmvm);
+ }
+ else return NIL(Void_t*);
+ }
+}
+
+#if __STD_C
+static int mmexcept(Vmalloc_t* vm, int type, Void_t* data, Vmdisc_t* disc)
+#else
+static int mmexcept(vm, type, data, disc)
+Vmalloc_t* vm;
+int type;
+Void_t* data;
+Vmdisc_t* disc;
+#endif
+{
+ int rv;
+ Void_t *base;
+ Vmdata_t *vd = vm->data;
+ Mmdisc_t *mmdc = (Mmdisc_t*)disc;
+
+ if(type == VM_OPEN)
+ { if(data) /* VM_OPEN event at start of vmopen() */
+ { if((rv = mminit(mmdc)) < 0 ) /* initialization failed */
+ return -1;
+ else if(rv == 0) /* just started a new map */
+ { /**/ASSERT(mmdc->flag&MM_INIT);
+ /**/ASSERT(mmdc->mmvm->magic == MM_LETMEDOIT);
+ return 0;
+ }
+ else /* an existing map was reconstructed */
+ { /**/ASSERT(!(mmdc->flag&MM_INIT));
+ /**/ASSERT(mmdc->mmvm->magic == MM_MAGIC);
+ *((Void_t**)data) = MMDATA(mmdc->mmvm);
+ return 1;
+ }
+ }
+ else return 0;
+ }
+ else if(type == VM_ENDOPEN) /* at end of vmopen() */
+ { if(mmdc->flag&MM_INIT) /* this is the initializing process! */
+ { /**/ASSERT(mmdc->mmvm->magic == MM_LETMEDOIT);
+ asocasint(&mmdc->mmvm->magic, MM_LETMEDOIT, MM_MAGIC);
+
+ if(mmdc->proj < 0) /* sync data to file now */
+ msync((Void_t*)mmdc->mmvm, MMHEAD(mmdc->file), MS_SYNC);
+ } /**/ASSERT(mmdc->mmvm->magic == MM_MAGIC);
+ return 0;
+ }
+ else if(type == VM_CLOSE)
+ return 1; /* tell vmclose not to free memory segments */
+ else if(type == VM_ENDCLOSE) /* this is the final closing event */
+ { (void)mmend(mmdc);
+ (void)vmfree(Vmheap, mmdc);
+ return 0; /* all done */
+ }
+ else return 0;
+}
+
+#if __STD_C
+Vmalloc_t* vmmopen(char* file, int proj, ssize_t size )
+#else
+Vmalloc_t* vmmopen(file, proj, size )
+char* file; /* file for key or data backing */
+int proj; /* project ID, < 0 doing mmap */
+ssize_t size; /* desired size for mem segment */
+#endif
+{
+ Vmalloc_t *vm;
+ Mmdisc_t *mmdc;
+
+ GETPAGESIZE(_Vmpagesize);
+
+ if(!file || !file[0] )
+ return NIL(Vmalloc_t*);
+
+ /* create discipline structure for getting memory from mmap */
+ if(!(mmdc = vmalloc(Vmheap, sizeof(Mmdisc_t)+strlen(file))) )
+ return NIL(Vmalloc_t*);
+ memset(mmdc, 0, sizeof(Mmdisc_t));
+ mmdc->disc.memoryf = mmgetmem;
+ mmdc->disc.exceptf = mmexcept;
+ mmdc->disc.round = _Vmpagesize; /* round request to this size */
+ mmdc->mmvm = NIL(Mmvm_t*);
+ mmdc->size = size;
+ mmdc->shmid = -1;
+ mmdc->flag = 0;
+ mmdc->proj = proj;
+ strcpy(mmdc->file, file);
+
+ /* now open the Vmalloc_t handle to return to application */
+ if(!(vm = vmopen(&mmdc->disc, Vmbest, VM_SHARE)) )
+ { (void)mmend(mmdc);
+ (void)vmfree(Vmheap, mmdc);
+ return NIL(Vmalloc_t*);
+ }
+ else
+ { /**/ASSERT(mmdc->mmvm && mmdc->mmvm->magic == MM_MAGIC);
+ return vm;
+ }
+}
+
+/* to store (key,value) data in the map */
+#if __STD_C
+Void_t* vmmvalue(Vmalloc_t* vm, int key, Void_t* val, int oper)
+#else
+Void_t* vmmvalue(vm, key, val, oper)
+Vmalloc_t* vm; /* a region based on vmmapopen */
+int key; /* key of data to be set */
+Void_t* val; /* data to be set */
+int oper; /* operation type */
+#endif
+{
+ Mmuser_t *u;
+ Vmdata_t *vd = vm->data;
+ Mmdisc_t *mmdc = (Mmdisc_t*)vm->disc;
+ Mmvm_t *mmvm = mmdc->mmvm;
+
+ /* check to see if operation is well-defined */
+ if(oper != VM_MMGET && oper != VM_MMSET && oper != VM_MMADD)
+ return NIL(Void_t*);
+
+ SETLOCK(vm, 0);
+
+ /* find the key */
+ for(u = mmvm->user; u; u = u->next)
+ if(u->key == key)
+ break;
+
+ if(!u && (oper == VM_MMSET || oper == VM_MMADD) )
+ { if((u = KPVALLOC(vm, sizeof(Mmuser_t), vm->meth.allocf)) )
+ { u->val = NIL(Void_t*);
+ u->key = key;
+ u->next = mmvm->user;
+ mmvm->user = u;
+ }
+ }
+
+ if(u) /* update data and set value to return */
+ { if(oper == VM_MMSET)
+ u->val = val;
+ else if(oper == VM_MMADD)
+ u->val = (Void_t*)((long)(u->val) + (long)(val));
+ val = u->val;
+ }
+ else val = NIL(Void_t*);
+
+ CLRLOCK(vm, 0);
+
+ return val;
+}
+
+void vmmrelease(Vmalloc_t* vm, int type)
+{
+ Mmdisc_t *mmdc = (Mmdisc_t*)vm->disc;
+
+ mmdc->flag |= MM_RELEASE;
+ if(type > 0)
+ mmdc->flag |= MM_CLEANUP;
+}
+
+/* suggest an address usable for mapping memory */
+Void_t* vmmaddress(size_t size)
+{
+#if !defined(_map_min) || !defined(_map_max) || !defined(_map_dir)
+ return NIL(Void_t*);
+#else
+ Void_t *avail;
+ static Vmuchar_t *min = (Vmuchar_t*)_map_min;
+ static Vmuchar_t *max = (Vmuchar_t*)_map_max;
+
+ GETPAGESIZE(_Vmpagesize);
+ size = ROUND(size, _Vmpagesize);
+
+ if(_map_dir == 0 || (min+size) > max)
+ avail = NIL(Void_t*);
+ else if(_map_dir > 0)
+ { avail = (Void_t*)min;
+ min += size;
+ }
+ else
+ { max -= size;
+ avail = (Void_t*)max;
+ }
+
+ return avail;
+#endif
+}
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmopen.c b/src/lib/libast/vmalloc/vmopen.c
new file mode 100644
index 0000000..5f6912f
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmopen.c
@@ -0,0 +1,180 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmopen(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Opening a new region of allocation.
+** Note that because of possible exotic memory types,
+** all region data must be stored within the space given
+** by the discipline.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+
+/* this structure lives in the top data segment of the region */
+typedef struct _vminit_s
+{ union
+ { Vmdata_t vd; /* root of usable data space */
+ Vmuchar_t a[ROUND(sizeof(Vmdata_t),ALIGN)];
+ } vd;
+ union
+ { Vmalloc_t vm; /* embedded region if needed */
+ Vmuchar_t a[ROUND(sizeof(Vmalloc_t),ALIGN)];
+ } vm;
+ union
+ { Seg_t seg; /* space for segment */
+ Vmuchar_t a[ROUND(sizeof(Seg_t),ALIGN)];
+ } seg;
+ Block_t block[16]; /* space for a few blocks */
+} Vminit_t;
+
+#if __STD_C
+Vmalloc_t* vmopen(Vmdisc_t* disc, Vmethod_t* meth, int mode)
+#else
+Vmalloc_t* vmopen(disc, meth, mode)
+Vmdisc_t* disc; /* discipline to get segments */
+Vmethod_t* meth; /* method to manage space */
+int mode; /* type of region */
+#endif
+{
+ Vmalloc_t *vm, *vmp, vmproto;
+ Vmdata_t *vd;
+ Vminit_t *init;
+ size_t algn, size, incr;
+ Block_t *bp, *np;
+ Seg_t *seg;
+ Vmuchar_t *addr;
+ int rv;
+
+ if(!meth || !disc || !disc->memoryf )
+ return NIL(Vmalloc_t*);
+
+ GETPAGESIZE(_Vmpagesize);
+
+ vmp = &vmproto; /* avoid memory allocation here! */
+ memset(vmp, 0, sizeof(Vmalloc_t));
+ memcpy(&vmp->meth, meth, sizeof(Vmethod_t));
+ vmp->disc = disc;
+
+ mode &= VM_FLAGS; /* start with user-settable flags */
+ size = 0;
+
+ if(disc->exceptf)
+ { addr = NIL(Vmuchar_t*);
+ if((rv = (*disc->exceptf)(vmp,VM_OPEN,(Void_t*)(&addr),disc)) < 0)
+ return NIL(Vmalloc_t*);
+ else if(rv == 0 )
+ { if(addr) /* vm itself is in memory from disc->memoryf */
+ mode |= VM_MEMORYF;
+ }
+ else if(rv > 0) /* the data section is being restored */
+ { if(!(init = (Vminit_t*)addr) )
+ return NIL(Vmalloc_t*);
+ size = -1; /* to tell that addr was not from disc->memoryf */
+ vd = &init->vd.vd; /**/ASSERT(VLONG(vd)%ALIGN == 0);
+ goto done;
+ }
+ }
+
+ /* make sure vd->incr is properly rounded and get initial memory */
+ incr = disc->round <= 0 ? _Vmpagesize : disc->round;
+ incr = MULTIPLE(incr,ALIGN);
+ size = ROUND(sizeof(Vminit_t),incr); /* get initial memory */
+ if(!(addr = (Vmuchar_t*)(*disc->memoryf)(vmp, NIL(Void_t*), 0, size, disc)) )
+ return NIL(Vmalloc_t*);
+ memset(addr, 0, size);
+
+ /* initialize region data */
+ algn = (size_t)(VLONG(addr)%ALIGN);
+ init = (Vminit_t*)(addr + (algn ? ALIGN-algn : 0)); /**/ASSERT(VLONG(init)%ALIGN == 0);
+ vd = &init->vd.vd; /**/ASSERT(VLONG(vd)%ALIGN == 0);
+ vd->mode = mode | meth->meth;
+ vd->incr = incr;
+ vd->pool = 0;
+ vd->free = vd->wild = NIL(Block_t*);
+
+ if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE))
+ { int k;
+ vd->root = NIL(Block_t*);
+ for(k = S_TINY-1; k >= 0; --k)
+ TINY(vd)[k] = NIL(Block_t*);
+ for(k = S_CACHE; k >= 0; --k)
+ CACHE(vd)[k] = NIL(Block_t*);
+ }
+
+ vd->seg = &init->seg.seg; /**/ ASSERT(VLONG(vd->seg)%ALIGN == 0);
+ seg = vd->seg;
+ seg->next = NIL(Seg_t*);
+ seg->vmdt = vd;
+ seg->addr = (Void_t*)addr;
+ seg->extent = size;
+ seg->baddr = addr + size;
+ seg->size = size; /* Note: this size is unusually large to mark seg as
+ the root segment and can be freed only at closing */
+ seg->free = NIL(Block_t*);
+
+ /* make a data block out of the remainder */
+ bp = SEGBLOCK(seg);
+ SEG(bp) = seg;
+ size = ((seg->baddr - (Vmuchar_t*)bp)/ALIGN) * ALIGN; /**/ ASSERT(size > 0);
+ SIZE(bp) = size - 2*sizeof(Head_t); /**/ASSERT(SIZE(bp) > 0 && (SIZE(bp)%ALIGN) == 0);
+ SELF(bp) = bp;
+ /**/ ASSERT(SIZE(bp)%ALIGN == 0);
+ /**/ ASSERT(VLONG(bp)%ALIGN == 0);
+
+ /* make a fake header for next block in case of noncontiguous segments */
+ np = NEXT(bp);
+ SEG(np) = seg;
+ SIZE(np) = BUSY|PFREE;
+
+ if(vd->mode&(VM_MTLAST|VM_MTPOOL))
+ seg->free = bp;
+ else vd->wild = bp;
+
+done: /* now make the region handle */
+ if(vd->mode&VM_MEMORYF)
+ vm = &init->vm.vm;
+ else if(!(vm = vmalloc(Vmheap, sizeof(Vmalloc_t))) )
+ { if(size > 0)
+ (void)(*disc->memoryf)(vmp, addr, size, 0, disc);
+ return NIL(Vmalloc_t*);
+ }
+ memcpy(vm, vmp, sizeof(Vmalloc_t));
+ vm->data = vd;
+
+ if(disc->exceptf) /* signaling that vmopen succeeded */
+ (void)(*disc->exceptf)(vm, VM_ENDOPEN, NIL(Void_t*), disc);
+
+ /* add to the linked list of regions */
+ _vmlock(NIL(Vmalloc_t*), 1);
+ vm->next = Vmheap->next; Vmheap->next = vm;
+ _vmlock(NIL(Vmalloc_t*), 0);
+
+ return vm;
+}
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmpool.c b/src/lib/libast/vmalloc/vmpool.c
new file mode 100644
index 0000000..2c65a66
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmpool.c
@@ -0,0 +1,316 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmpool(){}
+
+#else
+
+#include "vmhdr.h"
+
+#define POOLFREE 0x55555555L /* block free indicator */
+
+/* Method for pool allocation.
+** All elements in a pool have the same size.
+** The following fields of Vmdata_t are used as:
+** pool: size of a block.
+** free: list of free blocks.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+
+#if __STD_C
+static Void_t* poolalloc(Vmalloc_t* vm, reg size_t size, int local)
+#else
+static Void_t* poolalloc(vm, size, local )
+Vmalloc_t* vm;
+reg size_t size;
+int local;
+#endif
+{
+ reg Block_t *tp, *next;
+ reg size_t s;
+ reg Seg_t *seg;
+ reg Vmdata_t *vd = vm->data;
+
+ if(size <= 0)
+ return NIL(Void_t*);
+
+ if(size != vd->pool)
+ { if(vd->pool <= 0)
+ vd->pool = size;
+ else return NIL(Void_t*);
+ }
+
+ SETLOCK(vm, local);
+
+ if((tp = vd->free) ) /* there is a ready free block */
+ { vd->free = SEGLINK(tp);
+ goto done;
+ }
+
+ size = ROUND(size,ALIGN);
+
+ /* look thru all segments for a suitable free block */
+ for(tp = NIL(Block_t*), seg = vd->seg; seg; seg = seg->next)
+ { if((tp = seg->free) &&
+ (s = (SIZE(tp) & ~BITS) + sizeof(Head_t)) >= size )
+ goto got_blk;
+ }
+
+ if((tp = (*_Vmextend)(vm,ROUND(size,vd->incr),NIL(Vmsearch_f))) )
+ { s = (SIZE(tp) & ~BITS) + sizeof(Head_t);
+ seg = SEG(tp);
+ goto got_blk;
+ }
+ else goto done;
+
+got_blk: /* if get here, (tp, s, seg) must be well-defined */
+ next = (Block_t*)((Vmuchar_t*)tp+size);
+ if((s -= size) <= (size + sizeof(Head_t)) )
+ { for(; s >= size; s -= size)
+ { SIZE(next) = POOLFREE;
+ SEGLINK(next) = vd->free;
+ vd->free = next;
+ next = (Block_t*)((Vmuchar_t*)next + size);
+ }
+ seg->free = NIL(Block_t*);
+ }
+ else
+ { SIZE(next) = s - sizeof(Head_t);
+ SEG(next) = seg;
+ seg->free = next;
+ }
+
+done:
+ if(!local && (vd->mode&VM_TRACE) && _Vmtrace && tp)
+ (*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)tp,vd->pool,0);
+
+ CLRLOCK(vm, local);
+
+ return (Void_t*)tp;
+}
+
+#if __STD_C
+static long pooladdr(Vmalloc_t* vm, reg Void_t* addr, int local)
+#else
+static long pooladdr(vm, addr, local)
+Vmalloc_t* vm;
+reg Void_t* addr;
+int local;
+#endif
+{
+ Block_t *bp, *tp;
+ Vmuchar_t *laddr, *baddr;
+ size_t size;
+ Seg_t *seg;
+ long offset;
+ Vmdata_t* vd = vm->data;
+
+ SETLOCK(vm, local);
+
+ offset = -1L;
+ for(seg = vd->seg; seg; seg = seg->next)
+ { laddr = (Vmuchar_t*)SEGBLOCK(seg);
+ baddr = seg->baddr-sizeof(Head_t);
+ if((Vmuchar_t*)addr < laddr || (Vmuchar_t*)addr >= baddr)
+ continue;
+
+ /* the block that has this address */
+ size = ROUND(vd->pool,ALIGN);
+ tp = (Block_t*)(laddr + (((Vmuchar_t*)addr-laddr)/size)*size );
+
+ /* see if this block has been freed */
+ if(SIZE(tp) == POOLFREE) /* may be a coincidence - make sure */
+ for(bp = vd->free; bp; bp = SEGLINK(bp))
+ if(bp == tp)
+ goto done;
+
+ offset = (Vmuchar_t*)addr - (Vmuchar_t*)tp;
+ goto done;
+ }
+
+done :
+ CLRLOCK(vm, local);
+
+ return offset;
+}
+
+#if __STD_C
+static int poolfree(reg Vmalloc_t* vm, reg Void_t* data, int local )
+#else
+static int poolfree(vm, data, local)
+Vmalloc_t* vm;
+Void_t* data;
+int local;
+#endif
+{
+ Block_t *bp;
+ Vmdata_t *vd = vm->data;
+
+ if(!data)
+ return 0;
+ if(vd->pool <= 0)
+ return -1;
+
+ SETLOCK(vm, local);
+
+ /**/ASSERT(KPVADDR(vm, data, pooladdr) == 0);
+ bp = (Block_t*)data;
+ SIZE(bp) = POOLFREE;
+ SEGLINK(bp) = vd->free;
+ vd->free = bp;
+
+ if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
+ (*_Vmtrace)(vm, (Vmuchar_t*)data, NIL(Vmuchar_t*), vd->pool, 0);
+
+ CLRLOCK(vm, local);
+
+ return 0;
+}
+
+#if __STD_C
+static Void_t* poolresize(Vmalloc_t* vm, Void_t* data, size_t size, int type, int local )
+#else
+static Void_t* poolresize(vm, data, size, type, local )
+Vmalloc_t* vm;
+Void_t* data;
+size_t size;
+int type;
+int local;
+#endif
+{
+ Vmdata_t *vd = vm->data;
+
+ NOTUSED(type);
+
+ if(!data)
+ { data = poolalloc(vm, size, local);
+ if(data && (type&VM_RSZERO) )
+ memset(data, 0, size);
+ return data;
+ }
+ if(size == 0)
+ { (void)poolfree(vm, data, local);
+ return NIL(Void_t*);
+ }
+ if(size != vd->pool)
+ return NIL(Void_t*);
+
+ SETLOCK(vm, local);
+
+ /**/ASSERT(KPVADDR(vm, data, pooladdr) == 0);
+
+ if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
+ (*_Vmtrace)(vm, (Vmuchar_t*)data, (Vmuchar_t*)data, size, 0);
+
+ CLRLOCK(vm, local);
+
+ return data;
+}
+
+#if __STD_C
+static long poolsize(Vmalloc_t* vm, Void_t* addr, int local)
+#else
+static long poolsize(vm, addr, local)
+Vmalloc_t* vm;
+Void_t* addr;
+int local;
+#endif
+{
+ return pooladdr(vm, addr, local) == 0 ? (long)vm->data->pool : -1L;
+}
+
+#if __STD_C
+static int poolcompact(Vmalloc_t* vm, int local)
+#else
+static int poolcompact(vm, local)
+Vmalloc_t* vm;
+int local;
+#endif
+{
+ ssize_t s;
+ Block_t *fp;
+ Seg_t *seg, *next;
+ Vmdata_t *vd = vm->data;
+
+ SETLOCK(vm, local);
+
+ for(seg = vd->seg; seg; seg = next)
+ { next = seg->next;
+
+ if(!(fp = seg->free))
+ continue;
+
+ seg->free = NIL(Block_t*);
+ if(seg->size == (s = SIZE(fp)&~BITS))
+ s = seg->extent;
+ else s += sizeof(Head_t);
+
+ if((*_Vmtruncate)(vm,seg,s,1) == s)
+ seg->free = fp;
+ }
+
+ if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
+ (*_Vmtrace)(vm, (Vmuchar_t*)0, (Vmuchar_t*)0, 0, 0);
+
+ CLRLOCK(vm, local);
+
+ return 0;
+}
+
+#if __STD_C
+static Void_t* poolalign(Vmalloc_t* vm, size_t size, size_t align, int local)
+#else
+static Void_t* poolalign(vm, size, align, local)
+Vmalloc_t* vm;
+size_t size;
+size_t align;
+int local;
+#endif
+{
+ NOTUSED(vm);
+ NOTUSED(size);
+ NOTUSED(align);
+ return NIL(Void_t*);
+}
+
+/* Public interface */
+static Vmethod_t _Vmpool =
+{
+ poolalloc,
+ poolresize,
+ poolfree,
+ pooladdr,
+ poolsize,
+ poolcompact,
+ poolalign,
+ VM_MTPOOL
+};
+
+__DEFINE__(Vmethod_t*,Vmpool,&_Vmpool);
+
+#ifdef NoF
+NoF(vmpool)
+#endif
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmprivate.c b/src/lib/libast/vmalloc/vmprivate.c
new file mode 100644
index 0000000..28f3f70
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmprivate.c
@@ -0,0 +1,292 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmprivate(){}
+
+#else
+
+#include "vmhdr.h"
+
+static char* Version = "\n@(#)$Id: Vmalloc (AT&T Labs - Research) 2011-08-08 $\0\n";
+
+
+/* Private code used in the vmalloc library
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+
+/* Get more memory for a region */
+#if __STD_C
+static Block_t* _vmextend(reg Vmalloc_t* vm, size_t size, Vmsearch_f searchf )
+#else
+static Block_t* _vmextend(vm, size, searchf )
+reg Vmalloc_t* vm; /* region to increase in size */
+size_t size; /* desired amount of space */
+Vmsearch_f searchf; /* tree search function */
+#endif
+{
+ reg size_t s;
+ reg Seg_t* seg;
+ reg Block_t *bp, *tp, *np;
+ reg Vmuchar_t* addr = (Vmuchar_t*)Version; /* shut compiler warning */
+ reg Vmdata_t* vd = vm->data;
+
+ GETPAGESIZE(_Vmpagesize);
+
+ if(vd->incr <= 0) /* this is just _Vmheap on the first call */
+ vd->incr = _Vmpagesize*sizeof(Void_t*);
+
+ /* Get slightly more for administrative data */
+ s = size + sizeof(Seg_t) + sizeof(Block_t) + sizeof(Head_t) + 2*ALIGN;
+ if(s <= size) /* size was too large and we have wrapped around */
+ return NIL(Block_t*);
+ if((size = ROUND(s,vd->incr)) < s)
+ return NIL(Block_t*);
+
+ /* increase the rounding factor to reduce # of future extensions */
+ if(size > 2*vd->incr && vm->disc->round < vd->incr)
+ vd->incr *= 2;
+
+ if(!(seg = vd->seg) ) /* there is no current segment */
+ addr = NIL(Vmuchar_t*);
+ else /* see if we can extend the current segment */
+ { addr = (Vmuchar_t*)(*vm->disc->memoryf)(vm,seg->addr,seg->extent,
+ seg->extent+size,vm->disc);
+ if(addr == (Vmuchar_t*)seg->addr)
+ addr += seg->extent; /* seg successfully extended */
+ else seg = NIL(Seg_t*); /* a new segment was created */
+ }
+
+ if(!addr) /* create a new segment */
+ { if(!(addr = (Vmuchar_t*)(*vm->disc->memoryf)(vm, NIL(Void_t*), 0, size, vm->disc)) )
+ { if(vm->disc->exceptf) /* announce that no more memory is available */
+ {
+ CLRLOCK(vm, 0);
+ (void)(*vm->disc->exceptf)(vm, VM_NOMEM, (Void_t*)size, vm->disc);
+ SETLOCK(vm, 0);
+ }
+ return NIL(Block_t*);
+ }
+ }
+
+ if(seg)
+ { /* extending current segment */
+ bp = BLOCK(seg->baddr);
+
+ if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE) )
+ { /**/ ASSERT((SIZE(bp)&~BITS) == 0);
+ /**/ ASSERT(SEG(bp) == seg);
+
+ if(!ISPFREE(SIZE(bp)) )
+ SIZE(bp) = size - sizeof(Head_t);
+ else
+ { /**/ ASSERT(searchf);
+ bp = LAST(bp);
+ if(bp == vd->wild)
+ vd->wild = NIL(Block_t*);
+ else REMOVE(vd,bp,INDEX(SIZE(bp)),tp,(*searchf));
+ SIZE(bp) += size;
+ }
+ }
+ else
+ { if(seg->free)
+ { bp = seg->free;
+ seg->free = NIL(Block_t*);
+ SIZE(bp) += size;
+ }
+ else
+ { SEG(bp) = seg;
+ SIZE(bp) = size - sizeof(Head_t);
+ }
+ }
+
+ seg->size += size;
+ seg->extent += size;
+ seg->baddr += size;
+ }
+ else
+ { /* creating a new segment */
+ reg Seg_t *sp, *lastsp;
+
+ if((s = (size_t)(VLONG(addr)%ALIGN)) != 0)
+ addr += ALIGN-s;
+
+ seg = (Seg_t*)addr;
+ seg->vmdt = vd;
+ seg->addr = (Void_t*)(addr - (s ? ALIGN-s : 0));
+ seg->extent = size;
+ seg->baddr = addr + size - (s ? 2*ALIGN : 0);
+ seg->free = NIL(Block_t*);
+ bp = SEGBLOCK(seg);
+ SEG(bp) = seg;
+ SIZE(bp) = seg->baddr - (Vmuchar_t*)bp - 2*sizeof(Head_t);
+
+ /* NOTE: for Vmbest, Vmdebug and Vmprofile the region's segment list
+ is reversely ordered by addresses. This is so that we can easily
+ check for the wild block.
+ */
+ lastsp = NIL(Seg_t*);
+ sp = vd->seg;
+ if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE))
+ for(; sp; lastsp = sp, sp = sp->next)
+ if(seg->addr > sp->addr)
+ break;
+ seg->next = sp;
+ if(lastsp)
+ lastsp->next = seg;
+ else vd->seg = seg;
+
+ seg->size = SIZE(bp);
+ }
+
+ /* make a fake header for possible segmented memory */
+ tp = NEXT(bp);
+ SEG(tp) = seg;
+ SIZE(tp) = BUSY;
+
+ /* see if the wild block is still wild */
+ if((tp = vd->wild) && (seg = SEG(tp)) != vd->seg)
+ { np = NEXT(tp);
+ CLRPFREE(SIZE(np));
+ if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE) )
+ { SIZE(tp) |= BUSY|JUNK;
+ LINK(tp) = CACHE(vd)[C_INDEX(SIZE(tp))];
+ CACHE(vd)[C_INDEX(SIZE(tp))] = tp;
+ }
+ else seg->free = tp;
+
+ vd->wild = NIL(Block_t*);
+ }
+
+ return bp;
+}
+
+/* Truncate a segment if possible */
+#if __STD_C
+static ssize_t _vmtruncate(Vmalloc_t* vm, Seg_t* seg, size_t size, int exact)
+#else
+static ssize_t _vmtruncate(vm, seg, size, exact)
+Vmalloc_t* vm; /* containing region */
+Seg_t* seg; /* the one to be truncated */
+size_t size; /* amount of free space */
+int exact;
+#endif
+{
+ reg Void_t* caddr;
+ reg Seg_t* last;
+ reg Vmdata_t* vd = vm->data;
+ reg Vmemory_f memoryf = vm->disc->memoryf;
+
+ caddr = seg->addr;
+
+ if(size < seg->size)
+ { reg ssize_t less;
+
+ if(exact)
+ less = size;
+ else /* keep truncated amount to discipline requirements */
+ { if((less = vm->disc->round) <= 0)
+ less = _Vmpagesize;
+ less = (size/less)*less;
+ less = (less/vd->incr)*vd->incr;
+ if(less > 0 && (ssize_t)size > less && (size-less) < sizeof(Block_t) )
+ less = less <= (ssize_t)vd->incr ? 0 : less - vd->incr;
+ }
+
+ if(less <= 0 ||
+ (*memoryf)(vm,caddr,seg->extent,seg->extent-less,vm->disc) != caddr)
+ return 0;
+
+ seg->extent -= less;
+ seg->size -= less;
+ seg->baddr -= less;
+ SEG(BLOCK(seg->baddr)) = seg;
+ SIZE(BLOCK(seg->baddr)) = BUSY;
+
+ return less;
+ }
+ else
+ { /* unlink segment from region */
+ if(seg == vd->seg)
+ { vd->seg = seg->next;
+ last = NIL(Seg_t*);
+ }
+ else
+ { for(last = vd->seg; last->next != seg; last = last->next)
+ ;
+ last->next = seg->next;
+ }
+
+ /* now delete it */
+ if((*memoryf)(vm,caddr,seg->extent,0,vm->disc) == caddr)
+ return size;
+
+ /* space reduction failed, reinsert segment */
+ if(last)
+ { seg->next = last->next;
+ last->next = seg;
+ }
+ else
+ { seg->next = vd->seg;
+ vd->seg = seg;
+ }
+ return 0;
+ }
+}
+
+int _vmlock(Vmalloc_t* vm, int locking)
+{
+ int k;
+
+ if(!vm) /* some sort of global locking */
+ { if(!locking) /* turn off lock */
+ asolock(&_Vmlock, 1, ASO_UNLOCK);
+ else asolock(&_Vmlock, 1, ASO_SPINLOCK);
+ }
+ else if(vm->data->mode&VM_SHARE)
+ { if(!locking) /* turning off the lock */
+ asolock(&vm->data->lock, 1, ASO_UNLOCK);
+ else asolock(&vm->data->lock, 1, ASO_SPINLOCK);
+ }
+ else
+ { if(!locking)
+ vm->data->lock = 0;
+ else vm->data->lock = 1;
+ }
+ return 0;
+}
+
+
+/* Externally visible names but local to library */
+Vmextern_t _Vmextern =
+{ _vmextend, /* _Vmextend */
+ _vmtruncate, /* _Vmtruncate */
+ 0, /* _Vmpagesize */
+ NIL(char*(*)_ARG_((char*,const char*,int))), /* _Vmstrcpy */
+ NIL(char*(*)_ARG_((Vmulong_t,int))), /* _Vmitoa */
+ NIL(void(*)_ARG_((Vmalloc_t*,
+ Vmuchar_t*,Vmuchar_t*,size_t,size_t))), /* _Vmtrace */
+ NIL(void(*)_ARG_((Vmalloc_t*))) /* _Vmpfclose */
+};
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmprofile.c b/src/lib/libast/vmalloc/vmprofile.c
new file mode 100644
index 0000000..43191ed
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmprofile.c
@@ -0,0 +1,709 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmprofile(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Method to profile space usage.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 03/23/94.
+*/
+
+#define PFHASH(pf) ((pf)->data.data.hash)
+#define PFVM(pf) ((pf)->data.data.vm)
+#define PFFILE(pf) ((pf)->data.data.fm.file)
+#define PFLINE(pf) ((pf)->line)
+#define PFNAME(pf) ((pf)->data.f)
+#define PFNALLOC(pf) ((pf)->data.data.nalloc)
+#define PFALLOC(pf) ((pf)->data.data.alloc)
+#define PFNFREE(pf) ((pf)->data.data.nfree)
+#define PFFREE(pf) ((pf)->data.data.free)
+#define PFREGION(pf) ((pf)->data.data.region)
+#define PFMAX(pf) ((pf)->data.data.fm.max)
+
+typedef struct _pfdata_s Pfdata_t;
+struct _pfdata_s
+{ Vmulong_t hash; /* hash value */
+ union
+ { char* file; /* file name */
+ Vmulong_t max; /* max busy space for region */
+ } fm;
+ Vmalloc_t* vm; /* region alloc from */
+ Pfobj_t* region; /* pointer to region record */
+ Vmulong_t nalloc; /* number of alloc calls */
+ Vmulong_t alloc; /* amount allocated */
+ Vmulong_t nfree; /* number of free calls */
+ Vmulong_t free; /* amount freed */
+};
+struct _pfobj_s
+{ Pfobj_t* next; /* next in linked list */
+ int line; /* line #, 0 for name holder */
+ union
+ {
+ Pfdata_t data;
+ char f[1]; /* actual file name */
+ } data;
+};
+
+static Pfobj_t** Pftable; /* hash table */
+#define PFTABLE 1019 /* table size */
+static Vmalloc_t* Vmpf; /* heap for our own use */
+
+#if __STD_C
+static Pfobj_t* pfsearch(Vmalloc_t* vm, char* file, int line)
+#else
+static Pfobj_t* pfsearch(vm, file, line)
+Vmalloc_t* vm; /* region allocating from */
+char* file; /* the file issuing the allocation request */
+int line; /* line number */
+#endif
+{
+ reg Pfobj_t *pf, *last;
+ reg Vmulong_t h;
+ reg int n;
+ reg char *cp;
+
+ if(!Vmpf && !(Vmpf = vmopen(Vmdcheap,Vmpool,0)) )
+ return NIL(Pfobj_t*);
+
+ /* make hash table; PFTABLE'th slot hold regions' records */
+ if(!Pftable)
+ { if(!(Pftable = (Pfobj_t**)vmalloc(Vmheap,(PFTABLE+1)*sizeof(Pfobj_t*))) )
+ return NIL(Pfobj_t*);
+ for(n = PFTABLE; n >= 0; --n)
+ Pftable[n] = NIL(Pfobj_t*);
+ }
+
+ /* see if it's there with a combined hash value of vm,file,line */
+ h = line + (((Vmulong_t)vm)>>4);
+ for(cp = file; *cp; ++cp)
+ h += (h<<7) + ((*cp)&0377) + 987654321L;
+ n = (int)(h%PFTABLE);
+ for(last = NIL(Pfobj_t*), pf = Pftable[n]; pf; last = pf, pf = pf->next)
+ if(PFLINE(pf) == line && PFVM(pf) == vm && strcmp(PFFILE(pf),file) == 0)
+ break;
+
+ /* insert if not there yet */
+ if(!pf)
+ { reg Pfobj_t* fn;
+ reg Pfobj_t* pfvm;
+ reg Vmulong_t hn;
+
+ /* first get/construct the file name slot */
+ hn = 0;
+ for(cp = file; *cp; ++cp)
+ hn += (hn<<7) + ((*cp)&0377) + 987654321L;
+ n = (int)(hn%PFTABLE);
+ for(fn = Pftable[n]; fn; fn = fn->next)
+ if(PFLINE(fn) < 0 && strcmp(PFNAME(fn),file) == 0)
+ break;
+ if(!fn)
+ { reg size_t s;
+ s = sizeof(Pfobj_t) - sizeof(Pfdata_t) + strlen(file) + 1;
+ if(!(fn = (Pfobj_t*)vmalloc(Vmheap,s)) )
+ return NIL(Pfobj_t*);
+ fn->next = Pftable[n];
+ Pftable[n] = fn;
+ PFLINE(fn) = -1;
+ strcpy(PFNAME(fn),file);
+ }
+
+ /* get region record; note that these are ordered by vm */
+ last = NIL(Pfobj_t*);
+ for(pfvm = Pftable[PFTABLE]; pfvm; last = pfvm, pfvm = pfvm->next)
+ if(vm >= PFVM(pfvm))
+ break;
+ if(!pfvm || PFVM(pfvm) > vm)
+ { if(!(pfvm = (Pfobj_t*)vmalloc(Vmpf,sizeof(Pfobj_t))) )
+ return NIL(Pfobj_t*);
+ if(last)
+ { pfvm->next = last->next;
+ last->next = pfvm;
+ }
+ else
+ { pfvm->next = Pftable[PFTABLE];
+ Pftable[PFTABLE] = pfvm;
+ }
+ PFNALLOC(pfvm) = PFALLOC(pfvm) = 0;
+ PFNFREE(pfvm) = PFFREE(pfvm) = 0;
+ PFMAX(pfvm) = 0;
+ PFVM(pfvm) = vm;
+ PFLINE(pfvm) = 0;
+ }
+
+ if(!(pf = (Pfobj_t*)vmalloc(Vmpf,sizeof(Pfobj_t))) )
+ return NIL(Pfobj_t*);
+ n = (int)(h%PFTABLE);
+ pf->next = Pftable[n];
+ Pftable[n] = pf;
+ PFLINE(pf) = line;
+ PFFILE(pf) = PFNAME(fn);
+ PFREGION(pf) = pfvm;
+ PFVM(pf) = vm;
+ PFNALLOC(pf) = 0;
+ PFALLOC(pf) = 0;
+ PFNFREE(pf) = 0;
+ PFFREE(pf) = 0;
+ PFHASH(pf) = h;
+ }
+ else if(last) /* do a move-to-front */
+ { last->next = pf->next;
+ pf->next = Pftable[n];
+ Pftable[n] = pf;
+ }
+
+ return pf;
+}
+
+#if __STD_C
+static void pfclose(Vmalloc_t* vm)
+#else
+static void pfclose(vm)
+Vmalloc_t* vm;
+#endif
+{
+ reg int n;
+ reg Pfobj_t *pf, *next, *last;
+
+ /* free all records related to region vm */
+ for(n = PFTABLE; n >= 0; --n)
+ { for(last = NIL(Pfobj_t*), pf = Pftable[n]; pf; )
+ { next = pf->next;
+
+ if(PFLINE(pf) >= 0 && PFVM(pf) == vm)
+ { if(last)
+ last->next = next;
+ else Pftable[n] = next;
+ vmfree(Vmpf,pf);
+ }
+ else last = pf;
+
+ pf = next;
+ }
+ }
+}
+
+#if __STD_C
+static void pfsetinfo(Vmalloc_t* vm, Vmuchar_t* data, size_t size, char* file, int line)
+#else
+static void pfsetinfo(vm, data, size, file, line)
+Vmalloc_t* vm;
+Vmuchar_t* data;
+size_t size;
+char* file;
+int line;
+#endif
+{
+ reg Pfobj_t* pf;
+ reg Vmulong_t s;
+
+ /* let vmclose knows that there are records for region vm */
+ _Vmpfclose = pfclose;
+
+ if(!file || line <= 0)
+ { file = "";
+ line = 0;
+ }
+
+ if((pf = pfsearch(vm,file,line)) )
+ { PFALLOC(pf) += size;
+ PFNALLOC(pf) += 1;
+ }
+ PFOBJ(data) = pf;
+ PFSIZE(data) = size;
+
+ if(pf)
+ { /* update region statistics */
+ pf = PFREGION(pf);
+ PFALLOC(pf) += size;
+ PFNALLOC(pf) += 1;
+ if((s = PFALLOC(pf) - PFFREE(pf)) > PFMAX(pf) )
+ PFMAX(pf) = s;
+ }
+}
+
+/* sort by file names and line numbers */
+#if __STD_C
+static Pfobj_t* pfsort(Pfobj_t* pf)
+#else
+static Pfobj_t* pfsort(pf)
+Pfobj_t* pf;
+#endif
+{
+ reg Pfobj_t *one, *two, *next;
+ reg int cmp;
+
+ if(!pf->next)
+ return pf;
+
+ /* partition to two equal size lists */
+ one = two = NIL(Pfobj_t*);
+ while(pf)
+ { next = pf->next;
+ pf->next = one;
+ one = pf;
+
+ if((pf = next) )
+ { next = pf->next;
+ pf->next = two;
+ two = pf;
+ pf = next;
+ }
+ }
+
+ /* sort and merge the lists */
+ one = pfsort(one);
+ two = pfsort(two);
+ for(pf = next = NIL(Pfobj_t*);; )
+ { /* make sure that the "<>" file comes first */
+ if(PFLINE(one) == 0 && PFLINE(two) == 0)
+ cmp = PFVM(one) > PFVM(two) ? 1 : -1;
+ else if(PFLINE(one) == 0)
+ cmp = -1;
+ else if(PFLINE(two) == 0)
+ cmp = 1;
+ else if((cmp = strcmp(PFFILE(one),PFFILE(two))) == 0)
+ { cmp = PFLINE(one) - PFLINE(two);
+ if(cmp == 0)
+ cmp = PFVM(one) > PFVM(two) ? 1 : -1;
+ }
+
+ if(cmp < 0)
+ { if(!pf)
+ pf = one;
+ else next->next = one;
+ next = one;
+ if(!(one = one->next) )
+ { if(two)
+ next->next = two;
+ return pf;
+ }
+ }
+ else
+ { if(!pf)
+ pf = two;
+ else next->next = two;
+ next = two;
+ if(!(two = two->next) )
+ { if(one)
+ next->next = one;
+ return pf;
+ }
+ }
+ }
+}
+
+#if __STD_C
+static char* pfsummary(char* buf, Vmulong_t na, Vmulong_t sa,
+ Vmulong_t nf, Vmulong_t sf, Vmulong_t max, Vmulong_t size)
+#else
+static char* pfsummary(buf, na, sa, nf, sf, max, size)
+char* buf;
+Vmulong_t na;
+Vmulong_t sa;
+Vmulong_t nf;
+Vmulong_t sf;
+Vmulong_t max;
+Vmulong_t size;
+#endif
+{
+ buf = (*_Vmstrcpy)(buf,"n_alloc", '=');
+ buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(na,-1), ':');
+ buf = (*_Vmstrcpy)(buf,"n_free", '=');
+ buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(nf,-1), ':');
+ buf = (*_Vmstrcpy)(buf,"s_alloc", '=');
+ buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(sa,-1), ':');
+ buf = (*_Vmstrcpy)(buf,"s_free", '=');
+ buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(sf,-1), ':');
+ if(max > 0)
+ { buf = (*_Vmstrcpy)(buf,"max_busy", '=');
+ buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(max,-1), ':');
+ buf = (*_Vmstrcpy)(buf,"extent", '=');
+ buf = (*_Vmstrcpy)(buf, (*_Vmitoa)(size,-1), ':');
+ }
+ *buf++ = '\n';
+
+ return buf;
+}
+
+/* print profile data */
+#if __STD_C
+int vmprofile(Vmalloc_t* vm, int fd)
+#else
+int vmprofile(vm, fd)
+Vmalloc_t* vm;
+int fd;
+#endif
+{
+ reg Pfobj_t *pf, *list, *next, *last;
+ reg int n;
+ reg Vmulong_t nalloc, alloc, nfree, free;
+ reg Seg_t *seg;
+ char buf[1024], *bufp, *endbuf;
+#define INITBUF() (bufp = buf, endbuf = buf+sizeof(buf)-128)
+#define CHKBUF() (bufp >= endbuf ? (write(fd,buf,bufp-buf), bufp=buf) : bufp)
+#define FLSBUF() (bufp > buf ? write(fd,buf,bufp-buf) : 0)
+
+ if(fd < 0)
+ return -1;
+
+ /* initialize functions from vmtrace.c that we use below */
+ if((n = vmtrace(-1)) >= 0)
+ vmtrace(n);
+
+ alloc = free = nalloc = nfree = 0;
+ list = NIL(Pfobj_t*);
+ for(n = PFTABLE-1; n >= 0; --n)
+ { for(pf = Pftable[n], last = NIL(Pfobj_t*); pf; )
+ { next = pf->next;
+
+ if(PFLINE(pf) < 0 || (vm && vm != PFVM(pf)) )
+ { last = pf;
+ goto next_pf;
+ }
+
+ /* remove from hash table */
+ if(last)
+ last->next = next;
+ else Pftable[n] = next;
+
+ /* put on output list */
+ pf->next = list;
+ list = pf;
+ nalloc += PFNALLOC(pf);
+ alloc += PFALLOC(pf);
+ nfree += PFNFREE(pf);
+ free += PFFREE(pf);
+
+ next_pf:
+ pf = next;
+ }
+ }
+
+ INITBUF();
+ bufp = (*_Vmstrcpy)(bufp,"ALLOCATION USAGE SUMMARY", ':');
+ bufp = pfsummary(bufp,nalloc,alloc,nfree,free,0,0);
+
+ /* print regions' summary data */
+ for(pf = Pftable[PFTABLE]; pf; pf = pf->next)
+ { if(vm && PFVM(pf) != vm)
+ continue;
+ alloc = 0;
+ for(seg = PFVM(pf)->data->seg; seg; seg = seg->next)
+ alloc += seg->extent;
+ bufp = (*_Vmstrcpy)(bufp,"region", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(PFVM(pf)),0), ':');
+ bufp = pfsummary(bufp,PFNALLOC(pf),PFALLOC(pf),
+ PFNFREE(pf),PFFREE(pf),PFMAX(pf),alloc);
+ }
+
+ /* sort then output detailed profile */
+ list = pfsort(list);
+ for(pf = list; pf; )
+ { /* compute summary for file */
+ alloc = free = nalloc = nfree = 0;
+ for(last = pf; last; last = last->next)
+ { if(strcmp(PFFILE(last),PFFILE(pf)) != 0)
+ break;
+ nalloc += PFNALLOC(pf);
+ alloc += PFALLOC(last);
+ nfree += PFNFREE(last);
+ free += PFFREE(last);
+ }
+ CHKBUF();
+ bufp = (*_Vmstrcpy)(bufp,"file",'=');
+ bufp = (*_Vmstrcpy)(bufp,PFFILE(pf)[0] ? PFFILE(pf) : "<>" ,':');
+ bufp = pfsummary(bufp,nalloc,alloc,nfree,free,0,0);
+
+ while(pf != last) /* detailed data */
+ { CHKBUF();
+ bufp = (*_Vmstrcpy)(bufp,"\tline",'=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(PFLINE(pf),-1), ':');
+ bufp = (*_Vmstrcpy)(bufp, "region", '=');
+ bufp = (*_Vmstrcpy)(bufp, (*_Vmitoa)(VLONG(PFVM(pf)),0), ':');
+ bufp = pfsummary(bufp,PFNALLOC(pf),PFALLOC(pf),
+ PFNFREE(pf),PFFREE(pf),0,0);
+
+ /* reinsert into hash table */
+ next = pf->next;
+ n = (int)(PFHASH(pf)%PFTABLE);
+ pf->next = Pftable[n];
+ Pftable[n] = pf;
+ pf = next;
+ }
+ }
+
+ FLSBUF();
+ return 0;
+}
+
+#if __STD_C
+static Void_t* pfalloc(Vmalloc_t* vm, size_t size, int local)
+#else
+static Void_t* pfalloc(vm, size, local)
+Vmalloc_t* vm;
+size_t size;
+int local;
+#endif
+{
+ reg size_t s;
+ reg Void_t *data;
+ reg char *file;
+ reg int line;
+ reg Void_t *func;
+ reg Vmdata_t *vd = vm->data;
+
+ VMFLF(vm,file,line,func);
+
+ SETLOCK(vm, local);
+
+ s = ROUND(size,ALIGN) + PF_EXTRA;
+ if((data = KPVALLOC(vm,s,(*(Vmbest->allocf))) ) )
+ { pfsetinfo(vm,(Vmuchar_t*)data,size,file,line);
+
+ if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
+ { vm->file = file; vm->line = line; vm->func = func;
+ (*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)data,size,0);
+ }
+ }
+
+ CLRLOCK(vm, local);
+
+ return data;
+}
+
+#if __STD_C
+static int pffree(Vmalloc_t* vm, Void_t* data, int local)
+#else
+static int pffree(vm, data, local)
+Vmalloc_t* vm;
+Void_t* data;
+int local;
+#endif
+{
+ reg Pfobj_t *pf;
+ reg size_t s;
+ reg char *file;
+ reg int line, rv;
+ reg Void_t *func;
+ reg Vmdata_t *vd = vm->data;
+
+ VMFLF(vm,file,line,func);
+
+ if(!data)
+ return 0;
+
+ SETLOCK(vm,local);
+
+ /**/ASSERT(KPVADDR(vm, data, Vmbest->addrf) == 0 );
+ pf = PFOBJ(data);
+ s = PFSIZE(data);
+ if(pf)
+ { PFNFREE(pf) += 1;
+ PFFREE(pf) += s;
+ pf = PFREGION(pf);
+ PFNFREE(pf) += 1;
+ PFFREE(pf) += s;
+ }
+
+ if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
+ { vm->file = file; vm->line = line; vm->func = func;
+ (*_Vmtrace)(vm,(Vmuchar_t*)data,NIL(Vmuchar_t*),s,0);
+ }
+
+ rv = KPVFREE((vm), (Void_t*)data, (*Vmbest->freef));
+
+ CLRLOCK(vm, local);
+
+ return rv;
+}
+
+#if __STD_C
+static Void_t* pfresize(Vmalloc_t* vm, Void_t* data, size_t size, int type, int local)
+#else
+static Void_t* pfresize(vm, data, size, type, local)
+Vmalloc_t* vm;
+Void_t* data;
+size_t size;
+int type;
+int local;
+#endif
+{
+ reg Pfobj_t *pf;
+ reg size_t s, news;
+ reg Void_t *addr;
+ reg char *file;
+ reg int line;
+ reg Void_t *func;
+ reg size_t oldsize;
+ reg Vmdata_t *vd = vm->data;
+
+ if(!data)
+ { addr = pfalloc(vm, size, local);
+ if(addr && (type&VM_RSZERO) )
+ memset(addr, 0, size);
+ return addr;
+ }
+ if(size == 0)
+ { (void)pffree(vm, data, local);
+ return NIL(Void_t*);
+ }
+
+ VMFLF(vm,file,line,func);
+
+ SETLOCK(vm, local);
+
+ /**/ASSERT(KPVADDR(vm,data,Vmbest->addrf) == 0 );
+ pf = PFOBJ(data);
+ s = oldsize = PFSIZE(data);
+
+ news = ROUND(size,ALIGN) + PF_EXTRA;
+ if((addr = KPVRESIZE(vm,data,news,(type&~VM_RSZERO),Vmbest->resizef)) )
+ { if(pf)
+ { PFFREE(pf) += s;
+ PFNFREE(pf) += 1;
+ pf = PFREGION(pf);
+ PFFREE(pf) += s;
+ PFNFREE(pf) += 1;
+ pfsetinfo(vm,(Vmuchar_t*)addr,size,file,line);
+ }
+
+ if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
+ { vm->file = file; vm->line = line; vm->func = func;
+ (*_Vmtrace)(vm,(Vmuchar_t*)data,(Vmuchar_t*)addr,size,0);
+ }
+ }
+ else if(pf) /* reset old info */
+ { PFALLOC(pf) -= s;
+ PFNALLOC(pf) -= 1;
+ pf = PFREGION(pf);
+ PFALLOC(pf) -= s;
+ PFNALLOC(pf) -= 1;
+ file = PFFILE(pf);
+ line = PFLINE(pf);
+ pfsetinfo(vm,(Vmuchar_t*)data,s,file,line);
+ }
+
+ if(addr && (type&VM_RSZERO) && oldsize < size)
+ { reg Vmuchar_t *d = (Vmuchar_t*)addr+oldsize, *ed = (Vmuchar_t*)addr+size;
+ do { *d++ = 0; } while(d < ed);
+ }
+
+ CLRLOCK(vm, local);
+
+ return addr;
+}
+
+#if __STD_C
+static long pfsize(Vmalloc_t* vm, Void_t* addr, int local)
+#else
+static long pfsize(vm, addr, local)
+Vmalloc_t* vm;
+Void_t* addr;
+int local;
+#endif
+{
+ return (*Vmbest->addrf)(vm, addr, local) != 0 ? -1L : (long)PFSIZE(addr);
+}
+
+#if __STD_C
+static long pfaddr(Vmalloc_t* vm, Void_t* addr, int local)
+#else
+static long pfaddr(vm, addr, local)
+Vmalloc_t* vm;
+Void_t* addr;
+int local;
+#endif
+{
+ return (*Vmbest->addrf)(vm, addr, local);
+}
+
+#if __STD_C
+static int pfcompact(Vmalloc_t* vm, int local)
+#else
+static int pfcompact(vm, local)
+Vmalloc_t* vm;
+int local;
+#endif
+{
+ return (*Vmbest->compactf)(vm, local);
+}
+
+#if __STD_C
+static Void_t* pfalign(Vmalloc_t* vm, size_t size, size_t align, int local)
+#else
+static Void_t* pfalign(vm, size, align, local)
+Vmalloc_t* vm;
+size_t size;
+size_t align;
+int local;
+#endif
+{
+ reg size_t s;
+ reg Void_t *data;
+ reg char *file;
+ reg int line, inuse;
+ reg Void_t *func;
+ reg Vmdata_t *vd = vm->data;
+
+ VMFLF(vm,file,line,func);
+
+ SETLOCK(vm, local);
+
+ s = (size <= TINYSIZE ? TINYSIZE : ROUND(size,ALIGN)) + PF_EXTRA;
+ if((data = KPVALIGN(vm,s,align,Vmbest->alignf)) )
+ { pfsetinfo(vm,(Vmuchar_t*)data,size,file,line);
+
+ if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
+ { vm->file = file; vm->line = line; vm->func = func;
+ (*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)data,size,align);
+ }
+ }
+
+ CLRLOCK(vm, local);
+
+ return data;
+}
+
+static Vmethod_t _Vmprofile =
+{
+ pfalloc,
+ pfresize,
+ pffree,
+ pfaddr,
+ pfsize,
+ pfcompact,
+ pfalign,
+ VM_MTPROFILE
+};
+
+__DEFINE__(Vmethod_t*,Vmprofile,&_Vmprofile);
+
+#ifdef NoF
+NoF(vmprofile)
+#endif
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmregion.c b/src/lib/libast/vmalloc/vmregion.c
new file mode 100644
index 0000000..9aa1172
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmregion.c
@@ -0,0 +1,61 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmregion(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Return the containing region of an allocated piece of memory.
+** Beware: this only works with Vmbest, Vmdebug and Vmprofile.
+**
+** 10/31/2009: Add handling of shared/persistent memory regions.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+#if __STD_C
+Vmalloc_t* vmregion(Void_t* addr)
+#else
+Vmalloc_t* vmregion(addr)
+Void_t* addr;
+#endif
+{
+ Vmalloc_t *vm;
+ Vmdata_t *vd;
+
+ if(!addr)
+ return NIL(Vmalloc_t*);
+
+ vd = SEG(BLOCK(addr))->vmdt;
+
+ _vmlock(NIL(Vmalloc_t*), 1);
+ for(vm = Vmheap; vm; vm = vm->next)
+ if(vm->data == vd)
+ break;
+ _vmlock(NIL(Vmalloc_t*), 0);
+
+ return vm;
+}
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmsegment.c b/src/lib/libast/vmalloc/vmsegment.c
new file mode 100644
index 0000000..9cf658d
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmsegment.c
@@ -0,0 +1,58 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmsegment(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Get the segment containing this address
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 02/07/95
+*/
+
+#if __STD_C
+Void_t* vmsegment(Vmalloc_t* vm, Void_t* addr)
+#else
+Void_t* vmsegment(vm, addr)
+Vmalloc_t* vm; /* region */
+Void_t* addr; /* address */
+#endif
+{
+ Seg_t *seg;
+ Vmdata_t *vd = vm->data;
+
+ SETLOCK(vm, 0);
+
+ for(seg = vd->seg; seg; seg = seg->next)
+ if((Vmuchar_t*)addr >= (Vmuchar_t*)seg->addr &&
+ (Vmuchar_t*)addr < (Vmuchar_t*)seg->baddr )
+ break;
+
+ CLRLOCK(vm, 0);
+
+ return seg ? (Void_t*)seg->addr : NIL(Void_t*);
+}
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmset.c b/src/lib/libast/vmalloc/vmset.c
new file mode 100644
index 0000000..c437692
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmset.c
@@ -0,0 +1,62 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmset(){}
+
+#else
+
+#include "vmhdr.h"
+
+
+/* Set the control flags for a region.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+#if __STD_C
+int vmset(reg Vmalloc_t* vm, int flags, int on)
+#else
+int vmset(vm, flags, on)
+reg Vmalloc_t* vm; /* region being worked on */
+int flags; /* flags must be in VM_FLAGS */
+int on; /* !=0 if turning on, else turning off */
+#endif
+{
+ int mode;
+ Vmdata_t *vd = vm->data;
+
+ if(flags == 0 && on == 0)
+ return vd->mode;
+
+ SETLOCK(vm, 0);
+
+ mode = vd->mode;
+ if(on)
+ vd->mode |= (flags&VM_FLAGS);
+ else vd->mode &= ~(flags&VM_FLAGS);
+
+ CLRLOCK(vm, 0);
+
+ return mode;
+}
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmstat.c b/src/lib/libast/vmalloc/vmstat.c
new file mode 100644
index 0000000..4c6f6a4
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmstat.c
@@ -0,0 +1,145 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmstat(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Get statistics from a region.
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+
+#if __STD_C
+int vmstat(Vmalloc_t* vm, Vmstat_t* st)
+#else
+int vmstat(vm, st)
+Vmalloc_t* vm;
+Vmstat_t* st;
+#endif
+{
+ size_t s;
+ Seg_t *seg;
+ Block_t *b, *endb;
+ int local;
+ Vmdata_t *vd;
+ Void_t *d;
+
+ if(!st) /* just checking lock state of region */
+ return (vm ? vm : Vmregion)->data->lock;
+
+ memset(st, 0, sizeof(Vmstat_t));
+
+ if(!vm)
+ { /* getting data for malloc */
+#if ( !_std_malloc || !_BLD_ast ) && !_AST_std_malloc
+ extern int _mallocstat(Vmstat_t*);
+ return _mallocstat(st);
+#else
+ return -1;
+#endif
+ }
+
+ SETLOCK(vm, 0);
+
+ st->n_busy = st->n_free = 0;
+ st->s_busy = st->s_free = st->m_busy = st->m_free = 0;
+ st->n_seg = 0;
+ st->extent = 0;
+
+ vd = vm->data;
+ st->mode = vd->mode;
+ s = 0;
+ if(vd->mode&VM_MTLAST)
+ st->n_busy = 0;
+ else if((vd->mode&VM_MTPOOL) && (s = vd->pool) > 0)
+ { s = ROUND(s,ALIGN);
+ for(b = vd->free; b; b = SEGLINK(b))
+ st->n_free += 1;
+ }
+
+ for(seg = vd->seg; seg; seg = seg->next)
+ { st->n_seg += 1;
+ st->extent += seg->extent;
+
+ b = SEGBLOCK(seg);
+ endb = BLOCK(seg->baddr);
+
+ if(vd->mode&(VM_MTDEBUG|VM_MTBEST|VM_MTPROFILE))
+ { while(b < endb)
+ { s = SIZE(b)&~BITS;
+ if(ISJUNK(SIZE(b)) || !ISBUSY(SIZE(b)))
+ { if(s > st->m_free)
+ st->m_free = s;
+ st->s_free += s;
+ st->n_free += 1;
+ }
+ else /* get the real size */
+ { d = DATA(b);
+ if(vd->mode&VM_MTDEBUG)
+ s = DBSIZE(DB2DEBUG(d));
+ else if(vd->mode&VM_MTPROFILE)
+ s = PFSIZE(d);
+ if(s > st->m_busy)
+ st->m_busy = s;
+ st->s_busy += s;
+ st->n_busy += 1;
+ }
+
+ b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) );
+ }
+ /**/ASSERT(st->extent >= (st->s_busy + st->s_free));
+ }
+ else if(vd->mode&VM_MTLAST)
+ { if((s = seg->free ? (SIZE(seg->free) + sizeof(Head_t)) : 0) > 0)
+ { st->s_free += s;
+ st->n_free += 1;
+ }
+ if((s = ((char*)endb - (char*)b) - s) > 0)
+ { st->s_busy += s;
+ st->n_busy += 1;
+ }
+ }
+ else if((vd->mode&VM_MTPOOL) && s > 0)
+ { if(seg->free)
+ st->n_free += (SIZE(seg->free)+sizeof(Head_t))/s;
+ st->n_busy += ((seg->baddr - (Vmuchar_t*)b) - sizeof(Head_t))/s;
+ }
+ }
+
+ if((vd->mode&VM_MTPOOL) && s > 0)
+ { st->n_busy -= st->n_free;
+ if(st->n_busy > 0)
+ st->s_busy = (st->m_busy = vd->pool)*st->n_busy;
+ if(st->n_free > 0)
+ st->s_free = (st->m_free = vd->pool)*st->n_free;
+ }
+
+ CLRLOCK(vm, 0);
+
+ return 0;
+}
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmstrdup.c b/src/lib/libast/vmalloc/vmstrdup.c
new file mode 100644
index 0000000..2172f6e
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmstrdup.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmstrdup(){}
+
+#else
+
+#include "vmhdr.h"
+
+/*
+ * return a copy of s using vmalloc
+ */
+
+#if __STD_C
+char* vmstrdup(Vmalloc_t* v, register const char* s)
+#else
+char* vmstrdup(v, s)
+Vmalloc_t* v;
+register char* s;
+#endif
+{
+ register char* t;
+ register size_t n;
+
+ return (s && (t = vmalloc(v, n = strlen(s) + 1))) ? (char*)memcpy(t, s, n) : (char*)0;
+}
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmtrace.c b/src/lib/libast/vmalloc/vmtrace.c
new file mode 100644
index 0000000..22edba3
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmtrace.c
@@ -0,0 +1,286 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmtrace(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Turn on tracing for regions
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
+*/
+
+static int Trfile = -1;
+static char Trbuf[128];
+
+#if __STD_C
+static char* trstrcpy(char* to, const char* from, int endc)
+#else
+static char* trstrcpy(to, from, endc)
+char* to;
+const char* from;
+int endc;
+#endif
+{ reg int n;
+
+ n = strlen(from);
+ memcpy(to,from,n);
+ to += n;
+ if((*to = endc) )
+ to += 1;
+ return to;
+}
+
+/* convert a long value to an ascii representation */
+#if __STD_C
+static char* tritoa(Vmulong_t v, int type)
+#else
+static char* tritoa(v, type)
+Vmulong_t v; /* value to convert */
+int type; /* =0 base-16, >0: unsigned base-10, <0: signed base-10 */
+#endif
+{
+ char* s;
+
+ s = &Trbuf[sizeof(Trbuf) - 1];
+ *s-- = '\0';
+
+ if(type == 0) /* base-16 */
+ { reg char* digit = "0123456789abcdef";
+ do
+ { *s-- = digit[v&0xf];
+ v >>= 4;
+ } while(v);
+ }
+ else if(type > 0) /* unsigned base-10 */
+ { do
+ { *s-- = (char)('0' + (v%10));
+ v /= 10;
+ } while(v);
+ }
+ else /* signed base-10 */
+ { int sign = ((long)v < 0);
+ if(sign)
+ v = (Vmulong_t)(-((long)v));
+ do
+ { *s-- = (char)('0' + (v%10));
+ v /= 10;
+ } while(v);
+ if(sign)
+ *s-- = '-';
+ }
+
+ return s+1;
+}
+
+/* generate a trace of some call */
+#if __STD_C
+static void trtrace(Vmalloc_t* vm,
+ Vmuchar_t* oldaddr, Vmuchar_t* newaddr, size_t size, size_t align )
+#else
+static void trtrace(vm, oldaddr, newaddr, size, align)
+Vmalloc_t* vm; /* region call was made from */
+Vmuchar_t* oldaddr; /* old data address */
+Vmuchar_t* newaddr; /* new data address */
+size_t size; /* size of piece */
+size_t align; /* alignment */
+#endif
+{
+ char buf[1024], *bufp, *endbuf;
+ Vmdata_t* vd = vm->data;
+ const char* file = 0;
+ int line = 0;
+ const char* func = 0;
+ int comma;
+ int n;
+ int m;
+
+ int type;
+#define SLOP 64
+
+ if(oldaddr == (Vmuchar_t*)(-1)) /* printing busy blocks */
+ { type = 0;
+ oldaddr = NIL(Vmuchar_t*);
+ }
+ else
+ { type = vd->mode&VM_METHODS;
+ VMFLF(vm,file,line,func);
+ }
+
+ if(Trfile < 0)
+ return;
+
+ bufp = buf; endbuf = buf+sizeof(buf);
+ bufp = trstrcpy(bufp, tritoa(oldaddr ? VLONG(oldaddr) : 0L, 0), ':');
+ bufp = trstrcpy(bufp, tritoa(newaddr ? VLONG(newaddr) : 0L, 0), ':');
+ bufp = trstrcpy(bufp, tritoa((Vmulong_t)size, 1), ':');
+ bufp = trstrcpy(bufp, tritoa((Vmulong_t)align, 1), ':');
+ bufp = trstrcpy(bufp, tritoa(VLONG(vm), 0), ':');
+ if(type&VM_MTBEST)
+ bufp = trstrcpy(bufp, "b", ':');
+ else if(type&VM_MTLAST)
+ bufp = trstrcpy(bufp, "l", ':');
+ else if(type&VM_MTPOOL)
+ bufp = trstrcpy(bufp, "p", ':');
+ else if(type&VM_MTPROFILE)
+ bufp = trstrcpy(bufp, "s", ':');
+ else if(type&VM_MTDEBUG)
+ bufp = trstrcpy(bufp, "d", ':');
+ else bufp = trstrcpy(bufp, "u", ':');
+
+ comma = 0;
+ if(file && file[0] && line > 0)
+ { if((bufp + strlen(file) + SLOP) >= endbuf)
+ { char* f;
+ for(f = bufp + strlen(file); f > file; --f)
+ if(f[-1] == '/' || f[-1] == '\\')
+ break;
+ file = f;
+ }
+
+ bufp = trstrcpy(bufp, "file", '=');
+ n = endbuf - bufp - SLOP - 3;
+ m = strlen(file);
+ if(m > n)
+ { file += (m - n);
+ bufp = trstrcpy(bufp, "..", '.');
+ }
+ bufp = trstrcpy(bufp, file, ',');
+ bufp = trstrcpy(bufp, "line", '=');
+ bufp = trstrcpy(bufp, tritoa((Vmulong_t)line,1), 0);
+ comma = 1;
+ }
+ if(func)
+ { if(comma)
+ *bufp++ = ',';
+ bufp = trstrcpy(bufp, "func", '=');
+#if 1
+ bufp = trstrcpy(bufp, (const char*)func, 0);
+#else
+ bufp = trstrcpy(bufp, tritoa((Vmulong_t)func,0), 0);
+#endif
+ comma = 1;
+ }
+ if(comma)
+ *bufp++ = ':';
+
+ *bufp++ = '\n';
+ *bufp = '\0';
+
+ write(Trfile,buf,(bufp-buf));
+}
+
+#if __STD_C
+void _vmmessage(const char* s1, long n1, const char* s2, long n2)
+#else
+void _vmmessage(s1, n1, s2, n2)
+const char* s1;
+long n1;
+const char* s2;
+long n2;
+#endif
+{
+ char buf[1024], *bufp;
+
+ bufp = buf;
+ bufp = trstrcpy(bufp, "vmalloc", ':');
+ if (s1)
+ {
+ bufp = trstrcpy(bufp, s1, ':');
+ if (n1)
+ bufp = trstrcpy(bufp, tritoa(n1, 1), ':');
+ }
+ if (s2)
+ {
+ bufp = trstrcpy(bufp, s2, ':');
+ if (n2)
+ bufp = trstrcpy(bufp, tritoa(n2, 0), ':');
+ }
+
+ bufp = trstrcpy(bufp, tritoa((long)getpid(), 1), ':');
+
+ *bufp++ = '\n';
+ write(2,buf,(bufp-buf));
+}
+
+#if __STD_C
+int vmtrace(int file)
+#else
+int vmtrace(file)
+int file;
+#endif
+{
+ int fd;
+
+ _Vmstrcpy = trstrcpy;
+ _Vmitoa = tritoa;
+ _Vmtrace = trtrace;
+
+ fd = Trfile;
+ Trfile = file;
+ return fd;
+}
+
+#if __STD_C
+int vmtrbusy(Vmalloc_t* vm)
+#else
+int vmtrbusy(vm)
+Vmalloc_t* vm;
+#endif
+{
+ Seg_t* seg;
+ Vmdata_t* vd = vm->data;
+
+ if(Trfile < 0 || !(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE)))
+ return -1;
+
+ for(seg = vd->seg; seg; seg = seg->next)
+ { Block_t *b, *endb;
+ Vmuchar_t* data;
+ size_t s;
+
+ for(b = SEGBLOCK(seg), endb = BLOCK(seg->baddr); b < endb; )
+ { if(ISJUNK(SIZE(b)) || !ISBUSY(SIZE(b)))
+ continue;
+
+ data = DATA(b);
+ if(vd->mode&VM_MTDEBUG)
+ { data = DB2DEBUG(data);
+ s = DBSIZE(data);
+ }
+ else if(vd->mode&VM_MTPROFILE)
+ s = PFSIZE(data);
+ else s = SIZE(b)&~BITS;
+
+ trtrace(vm, (Vmuchar_t*)(-1), data, s, 0);
+
+ b = (Block_t*)((Vmuchar_t*)DATA(b) + (SIZE(b)&~BITS) );
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/src/lib/libast/vmalloc/vmwalk.c b/src/lib/libast/vmalloc/vmwalk.c
new file mode 100644
index 0000000..d7a8e36
--- /dev/null
+++ b/src/lib/libast/vmalloc/vmwalk.c
@@ -0,0 +1,69 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#if defined(_UWIN) && defined(_BLD_ast)
+
+void _STUB_vmwalk(){}
+
+#else
+
+#include "vmhdr.h"
+
+/* Walks all segments created in region(s)
+**
+** Written by Kiem-Phong Vo, kpv@research.att.com (02/08/96)
+*/
+
+#if __STD_C
+int vmwalk(Vmalloc_t* vm, int(*segf)(Vmalloc_t*, Void_t*, size_t, Vmdisc_t*, Void_t*), Void_t* handle )
+#else
+int vmwalk(vm, segf, handle)
+Vmalloc_t* vm;
+int(* segf)(/* Vmalloc_t*, Void_t*, size_t, Vmdisc_t*, Void_t* */);
+Void_t* handle;
+#endif
+{
+ reg Seg_t *seg;
+ reg int rv = 0;
+
+ if(!vm)
+ { _vmlock(NIL(Vmalloc_t*), 1);
+ for(vm = Vmheap; vm; vm = vm->next)
+ { SETLOCK(vm, 0);
+ for(seg = vm->data->seg; seg; seg = seg->next)
+ if((rv = (*segf)(vm, seg->addr, seg->extent, vm->disc, handle)) < 0 )
+ break;
+ CLRLOCK(vm, 0);
+ }
+ _vmlock(NIL(Vmalloc_t*), 0);
+ }
+ else
+ { SETLOCK(vm, 0);
+ for(seg = vm->data->seg; seg; seg = seg->next)
+ if((rv = (*segf)(vm, seg->addr, seg->extent, vm->disc, handle)) < 0 )
+ break;
+ CLRLOCK(vm, 0);
+ }
+
+ return rv;
+}
+
+#endif
diff --git a/src/lib/libcmd/Makefile b/src/lib/libcmd/Makefile
new file mode 100644
index 0000000..3cecffd
--- /dev/null
+++ b/src/lib/libcmd/Makefile
@@ -0,0 +1,90 @@
+/*
+ * command library -- commands small enough to be builtins
+ */
+
+:PACKAGE: ast
+
+LICENSE = since=1992,author=gsf+dgk
+
+CCFLAGS = $(CC.SUFFIX.DEBUG:+$(CC.DEBUG)) $(CC.OPTIMIZE) $(CC.DLL)
+
+/* 2009-04-15 ld.so experiment -- may become a default for all plugins */
+CC.DLL.ORIGIN = $(CC.LD.ORIGIN:C,/.*,,)
+LDFLAGS = $(CC.DLL.ORIGIN)
+
+CP = $(STDCP|"cp")
+CHMOD = $(STDCHMOD|"chmod")
+
+HOSTTYPE == "$(CC.HOSTTYPE)"
+
+cmd 1.2 :LIBRARY: RELEASE cmdinit.c \
+ cmd.h rev.h wc.h \
+ basename.c cat.c chgrp.c chmod.c chown.c cksum.c cmp.c \
+ comm.c cp.c cut.c dirname.c date.c expr.c fds.c fmt.c fold.c \
+ getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c \
+ mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c \
+ rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c \
+ vmstate.c wc.c revlib.c wclib.c sumlib.o \
+ fts_fix.c lib.c \
+ -lfsg -lmd
+
+sumlib.o : +lsum
+ $(AR) x $(*:O=1) $(<)
+
+$(INCLUDEDIR) :INSTALLPROTO: cmd.h cmdext.h cmdlist.h
+
+"win32*" :NOOPTIMIZE: id.c
+
+src = $(*$(*$(*cmd)):N=*.c:T=F)
+
+cmdext.h : (src) $$(-mam:+$$(src))
+ {
+ cat <<!
+ $("#")pragma prototyped
+ $("/")*
+ $(" ")* -lcmd extern function prototypes
+ $(" ")*/
+
+ $("#")include <shcmd.h>
+
+ !
+ $(SED) \
+ -e '/^b_[a-z_][a-z_0-9]*(/!d' \
+ -e 's/^b_//' \
+ -e 's/(.*//' \
+ -e 's/.*/extern int b_&(int, char**, Shbltin_t*);/' \
+ $($(~:O=1)) |
+ $(SORT) -u
+ } > 1.$(tmp).h
+ if $(CMP) $(CMPFLAGS) 1.$(tmp).h $(<)
+ then $(RM) $(RMFLAGS) 1.$(tmp).h
+ else $(MV) 1.$(tmp).h $(<)
+ fi
+
+cmdlist.h : (src)
+ {
+ cat <<!
+ $("#")pragma prototyped
+ $("/")*
+ $(" ")* -lcmd function list -- define your own CMDLIST()
+ $(" ")*/
+
+ !
+ $(SED) \
+ -e '/^b_[a-z_][a-z_0-9]*(/!d' \
+ -e 's/^b_//' \
+ -e 's/(.*//' \
+ -e 's/.*/CMDLIST(&)/' \
+ $($(~):T=F) |
+ $(SORT) -u
+ } > 1.$(tmp).h
+ if $(CMP) $(CMPFLAGS) 1.$(tmp).h $(<)
+ then $(RM) $(RMFLAGS) 1.$(tmp).h
+ else $(MV) 1.$(tmp).h $(<)
+ fi
+
+if CC.HOSTTYPE == "sun4"
+ pathsetlink == symlink /* ld.so workaround */
+end
+
+ignore dlldefs.h /* prevents bootstrap double build */
diff --git a/src/lib/libcmd/Mamfile b/src/lib/libcmd/Mamfile
new file mode 100644
index 0000000..a523fa4
--- /dev/null
+++ b/src/lib/libcmd/Mamfile
@@ -0,0 +1,866 @@
+info mam static 00000 1994-07-17 make (AT&T Research) 5.7 2012-02-29
+setv INSTALLROOT ../../..
+setv PACKAGE_ast_INCLUDE ${INSTALLROOT}/include/ast
+setv PACKAGE_ast_LIB ${INSTALLROOT}/lib
+setv PACKAGEROOT ../../../../..
+setv AR ${mam_cc_AR} ${mam_cc_AR_ARFLAGS}
+setv ARFLAGS rc
+setv AS as
+setv ASFLAGS
+setv CC cc
+setv mam_cc_FLAGS ${mam_cc_DLL}
+setv CCFLAGS ${mam_cc_DEBUG}
+setv CCLDFLAGS ${-strip-symbols?1?${mam_cc_LD_STRIP}??}
+setv COTEMP $$
+setv CPIO cpio
+setv CPIOFLAGS
+setv CPP "${CC} -E"
+setv F77 f77
+setv HOSTCC ${CC}
+setv IGNORE
+setv LD ld
+setv LDFLAGS ""
+setv LEX lex
+setv LEXFLAGS
+setv LPR lpr
+setv LPRFLAGS
+setv M4FLAGS
+setv NMAKE nmake
+setv NMAKEFLAGS
+setv PR pr
+setv PRFLAGS
+setv SHELL /bin/sh
+setv SILENT
+setv TAR tar
+setv YACC yacc
+setv YACCFLAGS -d
+make ${PACKAGEROOT}/lib/package/ast.lic
+done ${PACKAGEROOT}/lib/package/ast.lic
+make install
+make cmd
+make libcmd.a archive
+make cmd.req
+exec - set -
+exec - echo 'int main(){return 0;}' > 1.${COTEMP}.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -c 1.${COTEMP}.c &&
+exec - x=`${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l'*' 2>&1 | sed -e 's/[][()+@?]/#/g' || :` &&
+exec - {
+exec - case "" in
+exec - *?) echo " " ;;
+exec - esac
+exec - for i in cmd fsg md ast
+exec - do case $i in
+exec - "cmd"|cmd)
+exec - ;;
+exec - *) if test -f ${INSTALLROOT}/lib/lib/$i
+exec - then y=`cat ${INSTALLROOT}/lib/lib/$i`
+exec - case $y in
+exec - *-?*) echo "" $y ;;
+exec - esac
+exec - continue
+exec - elif test ! -f ${INSTALLROOT}/lib/lib$i.a
+exec - then case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -L${INSTALLROOT}/lib ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) continue ;;
+exec - esac
+exec - ;;
+exec - esac
+exec - fi
+exec - ;;
+exec - esac
+exec - echo " -l$i"
+exec - done
+exec - } > cmd.req
+exec - rm -f 1.${COTEMP}.*
+done cmd.req generated
+make cmdinit.o
+make cmdinit.c
+make ${PACKAGE_ast_INCLUDE}/shcmd.h implicit
+make ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+make ${INSTALLROOT}/include/prototyped.h implicit
+done ${INSTALLROOT}/include/prototyped.h dontcare
+done ${PACKAGE_ast_INCLUDE}/prototyped.h dontcare
+done ${PACKAGE_ast_INCLUDE}/shcmd.h
+make cmd.h implicit
+make ${PACKAGE_ast_INCLUDE}/dlldefs.h implicit
+done ${PACKAGE_ast_INCLUDE}/dlldefs.h dontcare ignore
+make cmdext.h implicit
+prev cmdinit.c
+make basename.c
+prev cmd.h implicit
+done basename.c
+make cat.c
+make ${PACKAGE_ast_INCLUDE}/endian.h implicit
+make ${PACKAGE_ast_INCLUDE}/bytesex.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_map.h dontcare
+done ${PACKAGE_ast_INCLUDE}/ast_common.h dontcare
+done ${PACKAGE_ast_INCLUDE}/bytesex.h dontcare
+done ${PACKAGE_ast_INCLUDE}/endian.h dontcare
+prev cmd.h implicit
+done cat.c
+make chgrp.c
+make FEATURE/symlink implicit
+meta FEATURE/symlink features/%>FEATURE/% features/symlink symlink
+make features/symlink
+done features/symlink
+bind -last
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libast} : run features/symlink
+done FEATURE/symlink generated
+make fts_fix.h implicit
+make ${PACKAGE_ast_INCLUDE}/fts.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_mode.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_fs.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+make ${PACKAGE_ast_INCLUDE}/regex.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+make ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wctype.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wctype.h dontcare
+done ${PACKAGE_ast_INCLUDE}/wctype.h dontcare
+make ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_stdio.h implicit
+make ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
+done ${PACKAGE_ast_INCLUDE}/sfio_s.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_stdio.h dontcare
+done ${PACKAGE_ast_INCLUDE}/stdio.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wchar.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/regex.h dontcare
+make ${PACKAGE_ast_INCLUDE}/getopt.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_getopt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_getopt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/getopt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_botch.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_botch.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_limits.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_limits.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_fcntl.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_fcntl.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_getopt.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_sys.h implicit
+prev ${PACKAGE_ast_INCLUDE}/getopt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_sys.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_lib.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_lib.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_std.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/fts.h dontcare
+done fts_fix.h
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+make ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ls.h
+make ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/cdt.h
+prev cmd.h implicit
+done chgrp.c
+make chmod.c
+prev FEATURE/symlink implicit
+prev fts_fix.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done chmod.c
+make chown.c
+prev cmd.h implicit
+done chown.c
+make cksum.c
+make ${PACKAGE_ast_INCLUDE}/error.h implicit
+make ${PACKAGE_ast_INCLUDE}/option.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_api.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_api.h dontcare
+make ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/vmalloc.h dontcare
+make ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/sfio.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/option.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/error.h
+prev fts_fix.h implicit
+make ${PACKAGE_ast_INCLUDE}/modex.h implicit
+make ${PACKAGE_ast_INCLUDE}/modecanon.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/modecanon.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/modex.h
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+make ${PACKAGE_ast_INCLUDE}/sum.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/sum.h
+prev cmd.h implicit
+done cksum.c
+make cmp.c
+make ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_ccode.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_ccode.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ccode.h
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done cmp.c
+make comm.c
+prev cmd.h implicit
+done comm.c
+make cp.c
+make ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+make ${PACKAGE_ast_INCLUDE}/tv.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done ${PACKAGE_ast_INCLUDE}/tv.h dontcare
+make ${PACKAGE_ast_INCLUDE}/tm.h implicit
+make ${PACKAGE_ast_INCLUDE}/times.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_time.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_time.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/times.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/tm.h dontcare
+done ${PACKAGE_ast_INCLUDE}/tmx.h
+make ${PACKAGE_ast_INCLUDE}/stk.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/stk.h
+make ${PACKAGE_ast_INCLUDE}/hashkey.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/hashkey.h
+make ${PACKAGE_ast_INCLUDE}/fs3d.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/fs3d.h
+prev fts_fix.h implicit
+prev ${PACKAGE_ast_INCLUDE}/times.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done cp.c
+make cut.c
+prev cmd.h implicit
+done cut.c
+make dirname.c
+prev cmd.h implicit
+done dirname.c
+make date.c
+prev ${PACKAGE_ast_INCLUDE}/times.h implicit
+prev ${PACKAGE_ast_INCLUDE}/tmx.h implicit
+make ${PACKAGE_ast_INCLUDE}/proc.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/proc.h
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done date.c
+make expr.c
+prev ${PACKAGE_ast_INCLUDE}/regex.h implicit
+prev cmd.h implicit
+done expr.c
+make fds.c
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+make FEATURE/sockets implicit
+meta FEATURE/sockets features/%>FEATURE/% features/sockets sockets
+make features/sockets
+done features/sockets
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libast} : run features/sockets
+done FEATURE/sockets generated
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done fds.c
+make fmt.c
+prev cmd.h implicit
+done fmt.c
+make fold.c
+prev cmd.h implicit
+done fold.c
+make getconf.c
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/proc.h implicit
+prev cmd.h implicit
+done getconf.c
+make head.c
+prev cmd.h implicit
+done head.c
+make id.c
+make fsg.h implicit
+done fsg.h dontcare virtual
+prev ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+make FEATURE/ids implicit
+meta FEATURE/ids features/%>FEATURE/% features/ids ids
+make features/ids
+done features/ids
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libast} : run features/ids
+done FEATURE/ids generated
+prev cmd.h implicit
+done id.c
+make join.c
+prev ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+make ${PACKAGE_ast_INCLUDE}/wchar.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+done ${PACKAGE_ast_INCLUDE}/wchar.h dontcare
+make ${PACKAGE_ast_INCLUDE}/sfdisc.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/sfdisc.h
+prev cmd.h implicit
+done join.c
+make ln.c
+prev cmd.h implicit
+done ln.c
+make logname.c
+prev cmd.h implicit
+done logname.c
+make md5sum.c
+prev cmd.h implicit
+done md5sum.c
+make mkdir.c
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done mkdir.c
+make mkfifo.c
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done mkfifo.c
+make mktemp.c
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done mktemp.c
+make mv.c
+prev cmd.h implicit
+done mv.c
+make paste.c
+prev cmd.h implicit
+done paste.c
+make pathchk.c
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done pathchk.c
+make pids.c
+prev ${PACKAGE_ast_INCLUDE}/sfdisc.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_tty.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_tty.h
+prev cmd.h implicit
+done pids.c
+make rev.c
+make rev.h implicit
+done rev.h
+prev cmd.h implicit
+done rev.c
+make rm.c
+prev ${PACKAGE_ast_INCLUDE}/fs3d.h implicit
+prev fts_fix.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done rm.c
+make rmdir.c
+prev cmd.h implicit
+done rmdir.c
+make stty.c
+prev ${PACKAGE_ast_INCLUDE}/ast_tty.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ccode.h implicit
+prev cmd.h implicit
+done stty.c
+make sum.c
+prev cmd.h implicit
+done sum.c
+make sync.c
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done sync.c
+make tail.c
+prev rev.h implicit
+prev ${PACKAGE_ast_INCLUDE}/tm.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done tail.c
+make tee.c
+make ${PACKAGE_ast_INCLUDE}/sig.h implicit
+done ${PACKAGE_ast_INCLUDE}/sig.h
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev cmd.h implicit
+done tee.c
+make tty.c
+prev cmd.h implicit
+done tty.c
+make uname.c
+make FEATURE/utsname implicit
+meta FEATURE/utsname features/%>FEATURE/% features/utsname utsname
+make features/utsname
+done features/utsname
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libast} : run features/utsname
+done FEATURE/utsname generated
+prev ${PACKAGE_ast_INCLUDE}/proc.h implicit
+prev cmd.h implicit
+done uname.c
+make uniq.c
+prev cmd.h implicit
+done uniq.c
+make vmstate.c
+prev ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+prev cmd.h implicit
+done vmstate.c
+make wc.c
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+make wc.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done wc.h
+prev cmd.h implicit
+done wc.c
+make revlib.c
+prev rev.h implicit
+prev cmd.h implicit
+done revlib.c
+make wclib.c
+make ${PACKAGE_ast_INCLUDE}/lc.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/lc.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+prev ${PACKAGE_ast_INCLUDE}/wchar.h implicit
+prev wc.h implicit
+prev cmd.h implicit
+done wclib.c
+make fts_fix.c
+prev fts_fix.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done fts_fix.c
+make lib.c
+prev cmd.h implicit
+done lib.c
+exec - {
+exec - cat <<!
+exec - #pragma prototyped
+exec - /*
+exec - * -lcmd extern function prototypes
+exec - */
+exec -
+exec - #include <shcmd.h>
+exec -
+exec - !
+exec - sed \
+exec - -e '/^b_[a-z_][a-z_0-9]*(/!d' \
+exec - -e 's/^b_//' \
+exec - -e 's/(.*//' \
+exec - -e 's/.*/extern int b_&(int, char**, Shbltin_t*);/' \
+exec - cmdinit.c basename.c cat.c chgrp.c chmod.c chown.c cksum.c cmp.c comm.c cp.c cut.c dirname.c date.c expr.c fds.c fmt.c fold.c getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c vmstate.c wc.c revlib.c wclib.c fts_fix.c lib.c |
+exec - sort -u
+exec - } > 1.${COTEMP}.h
+exec - if cmp 2>/dev/null -s 1.${COTEMP}.h cmdext.h
+exec - then rm -f 1.${COTEMP}.h
+exec - else mv 1.${COTEMP}.h cmdext.h
+exec - fi
+prev ${PACKAGE_ast_INCLUDE}/shcmd.h implicit
+done cmdext.h dontcare generated
+prev ${PACKAGE_ast_INCLUDE}/shcmd.h implicit
+make ${PACKAGE_ast_INCLUDE}/stak.h implicit
+prev ${PACKAGE_ast_INCLUDE}/stk.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/stak.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done cmd.h
+done cmdinit.c
+meta cmdinit.o %.c>%.o cmdinit.c cmdinit
+prev cmdinit.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -c cmdinit.c
+done cmdinit.o generated
+make basename.o
+prev basename.c
+meta basename.o %.c>%.o basename.c basename
+prev basename.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c basename.c
+done basename.o generated
+make cat.o
+prev cat.c
+meta cat.o %.c>%.o cat.c cat
+prev cat.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -c cat.c
+done cat.o generated
+make chgrp.o
+prev chgrp.c
+meta chgrp.o %.c>%.o chgrp.c chgrp
+prev chgrp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_cmd -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c chgrp.c
+done chgrp.o generated
+make chmod.o
+prev chmod.c
+meta chmod.o %.c>%.o chmod.c chmod
+prev chmod.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c chmod.c
+done chmod.o generated
+make chown.o
+prev chown.c
+meta chown.o %.c>%.o chown.c chown
+prev chown.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -c chown.c
+done chown.o generated
+make cksum.o
+prev cksum.c
+meta cksum.o %.c>%.o cksum.c cksum
+prev cksum.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_DEBUG -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c cksum.c
+done cksum.o generated
+make cmp.o
+prev cmp.c
+meta cmp.o %.c>%.o cmp.c cmp
+prev cmp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c cmp.c
+done cmp.o generated
+make comm.o
+prev comm.c
+meta comm.o %.c>%.o comm.c comm
+prev comm.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c comm.c
+done comm.o generated
+make cp.o
+prev cp.c
+meta cp.o %.c>%.o cp.c cp
+prev cp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_DEBUG -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c cp.c
+done cp.o generated
+make cut.o
+prev cut.c
+meta cut.o %.c>%.o cut.c cut
+prev cut.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c cut.c
+done cut.o generated
+make dirname.o
+prev dirname.c
+meta dirname.o %.c>%.o dirname.c dirname
+prev dirname.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c dirname.c
+done dirname.o generated
+make date.o
+prev date.c
+meta date.o %.c>%.o date.c date
+prev date.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_DEBUG -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c date.c
+done date.o generated
+make expr.o
+prev expr.c
+meta expr.o %.c>%.o expr.c expr
+prev expr.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c expr.c
+done expr.o generated
+make fds.o
+prev fds.c
+meta fds.o %.c>%.o fds.c fds
+prev fds.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c fds.c
+done fds.o generated
+make fmt.o
+prev fmt.c
+meta fmt.o %.c>%.o fmt.c fmt
+prev fmt.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c fmt.c
+done fmt.o generated
+make fold.o
+prev fold.c
+meta fold.o %.c>%.o fold.c fold
+prev fold.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c fold.c
+done fold.o generated
+make getconf.o
+prev getconf.c
+meta getconf.o %.c>%.o getconf.c getconf
+prev getconf.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_DEBUG -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c getconf.c
+done getconf.o generated
+make head.o
+prev head.c
+meta head.o %.c>%.o head.c head
+prev head.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c head.c
+done head.o generated
+make id.o
+prev id.c
+meta id.o %.c>%.o id.c id
+prev id.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c id.c
+done id.o generated
+make join.o
+prev join.c
+meta join.o %.c>%.o join.c join
+prev join.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_DEBUG -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c join.c
+done join.o generated
+make ln.o
+prev ln.c
+meta ln.o %.c>%.o ln.c ln
+prev ln.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -c ln.c
+done ln.o generated
+make logname.o
+prev logname.c
+meta logname.o %.c>%.o logname.c logname
+prev logname.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c logname.c
+done logname.o generated
+make md5sum.o
+prev md5sum.c
+meta md5sum.o %.c>%.o md5sum.c md5sum
+prev md5sum.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -c md5sum.c
+done md5sum.o generated
+make mkdir.o
+prev mkdir.c
+meta mkdir.o %.c>%.o mkdir.c mkdir
+prev mkdir.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c mkdir.c
+done mkdir.o generated
+make mkfifo.o
+prev mkfifo.c
+meta mkfifo.o %.c>%.o mkfifo.c mkfifo
+prev mkfifo.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c mkfifo.c
+done mkfifo.o generated
+make mktemp.o
+prev mktemp.c
+meta mktemp.o %.c>%.o mktemp.c mktemp
+prev mktemp.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c mktemp.c
+done mktemp.o generated
+make mv.o
+prev mv.c
+meta mv.o %.c>%.o mv.c mv
+prev mv.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -c mv.c
+done mv.o generated
+make paste.o
+prev paste.c
+meta paste.o %.c>%.o paste.c paste
+prev paste.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c paste.c
+done paste.o generated
+make pathchk.o
+prev pathchk.c
+meta pathchk.o %.c>%.o pathchk.c pathchk
+prev pathchk.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c pathchk.c
+done pathchk.o generated
+make pids.o
+prev pids.c
+meta pids.o %.c>%.o pids.c pids
+prev pids.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_DEBUG -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c pids.c
+done pids.o generated
+make rev.o
+prev rev.c
+meta rev.o %.c>%.o rev.c rev
+prev rev.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c rev.c
+done rev.o generated
+make rm.o
+prev rm.c
+meta rm.o %.c>%.o rm.c rm
+prev rm.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c rm.c
+done rm.o generated
+make rmdir.o
+prev rmdir.c
+meta rmdir.o %.c>%.o rmdir.c rmdir
+prev rmdir.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c rmdir.c
+done rmdir.o generated
+make stty.o
+prev stty.c
+meta stty.o %.c>%.o stty.c stty
+prev stty.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c stty.c
+done stty.o generated
+make sum.o
+prev sum.c
+meta sum.o %.c>%.o sum.c sum
+prev sum.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -c sum.c
+done sum.o generated
+make sync.o
+prev sync.c
+meta sync.o %.c>%.o sync.c sync
+prev sync.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c sync.c
+done sync.o generated
+make tail.o
+prev tail.c
+meta tail.o %.c>%.o tail.c tail
+prev tail.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_DEBUG -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c tail.c
+done tail.o generated
+make tee.o
+prev tee.c
+meta tee.o %.c>%.o tee.c tee
+prev tee.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c tee.c
+done tee.o generated
+make tty.o
+prev tty.c
+meta tty.o %.c>%.o tty.c tty
+prev tty.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c tty.c
+done tty.o generated
+make uname.o
+prev uname.c
+meta uname.o %.c>%.o uname.c uname
+prev uname.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -DHOSTTYPE=\""${mam_cc_HOSTTYPE}"\" -D_PACKAGE_ast -D_BLD_DEBUG -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c uname.c
+done uname.o generated
+make uniq.o
+prev uniq.c
+meta uniq.o %.c>%.o uniq.c uniq
+prev uniq.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c uniq.c
+done uniq.o generated
+make vmstate.o
+prev vmstate.c
+meta vmstate.o %.c>%.o vmstate.c vmstate
+prev vmstate.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_cmd -D_BLD_DEBUG -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c vmstate.c
+done vmstate.o generated
+make wc.o
+prev wc.c
+meta wc.o %.c>%.o wc.c wc
+prev wc.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -DERROR_CATALOG=\""libcmd"\" -D_PACKAGE_ast -D_BLD_DEBUG -D_BLD_cmd -DUSAGE_LICENSE=\""[-author?Glenn Fowler <gsf@research.att.com>][-author?David Korn <dgk@research.att.com>][-copyright?Copyright (c) 1992-2012 AT&T Intellectual Property][-license?http://www.eclipse.org/org/documents/epl-v10.html][--catalog?libcmd]"\" -c wc.c
+done wc.o generated
+make revlib.o
+prev revlib.c
+meta revlib.o %.c>%.o revlib.c revlib
+prev revlib.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -c revlib.c
+done revlib.o generated
+make wclib.o
+prev wclib.c
+meta wclib.o %.c>%.o wclib.c wclib
+prev wclib.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_DEBUG -D_BLD_cmd -c wclib.c
+done wclib.o generated
+make sumlib.o
+bind -lsum
+exec - ${AR} x ${mam_libsum} sumlib.o
+done sumlib.o generated
+make fts_fix.o
+prev fts_fix.c
+meta fts_fix.o %.c>%.o fts_fix.c fts_fix
+prev fts_fix.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_DEBUG -c fts_fix.c
+done fts_fix.o generated
+make lib.o
+prev lib.c
+meta lib.o %.c>%.o lib.c lib
+prev lib.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_BLD_cmd -D_PACKAGE_ast -D_BLD_DEBUG -c lib.c
+done lib.o generated
+exec - ${AR} rc libcmd.a cmdinit.o basename.o cat.o chgrp.o chmod.o chown.o cksum.o cmp.o comm.o cp.o cut.o dirname.o date.o expr.o fds.o fmt.o fold.o getconf.o head.o id.o join.o ln.o logname.o md5sum.o mkdir.o mkfifo.o mktemp.o mv.o paste.o pathchk.o
+exec - ${AR} rc libcmd.a pids.o rev.o rm.o rmdir.o stty.o sum.o sync.o tail.o tee.o tty.o uname.o uniq.o vmstate.o wc.o revlib.o wclib.o sumlib.o fts_fix.o lib.o
+exec - (ranlib libcmd.a) >/dev/null 2>&1 || true
+done libcmd.a generated
+done cmd virtual
+prev libcmd.a archive
+make ${INSTALLROOT}/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib
+exec - then mkdir -p ${INSTALLROOT}/lib
+exec - fi
+done ${INSTALLROOT}/lib generated
+make ${INSTALLROOT}/lib/libcmd.a archive
+prev ${INSTALLROOT}/lib
+prev libcmd.a archive
+exec - test '' = 'libcmd.a' || ${STDCMP} 2>/dev/null -s libcmd.a ${INSTALLROOT}/lib/libcmd.a || { ${STDMV} ${INSTALLROOT}/lib/libcmd.a ${INSTALLROOT}/lib/libcmd.a.old 2>/dev/null || true; ${STDCP} libcmd.a ${INSTALLROOT}/lib/libcmd.a ;}
+exec - (ranlib ${INSTALLROOT}/lib/libcmd.a) >/dev/null 2>&1 || true
+done ${INSTALLROOT}/lib/libcmd.a generated
+make ${INSTALLROOT}/lib/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib/lib
+exec - then mkdir -p ${INSTALLROOT}/lib/lib
+exec - fi
+done ${INSTALLROOT}/lib/lib generated
+make ${INSTALLROOT}/lib/lib/cmd
+prev ${INSTALLROOT}/lib/lib
+prev cmd.req
+exec - test '' = 'cmd.req' || ${STDCMP} 2>/dev/null -s cmd.req ${INSTALLROOT}/lib/lib/cmd || { ${STDMV} ${INSTALLROOT}/lib/lib/cmd ${INSTALLROOT}/lib/lib/cmd.old 2>/dev/null || true; ${STDCP} cmd.req ${INSTALLROOT}/lib/lib/cmd ;}
+done ${INSTALLROOT}/lib/lib/cmd generated
+make ${PACKAGE_ast_INCLUDE}
+exec - if silent test ! -d ${PACKAGE_ast_INCLUDE}
+exec - then mkdir -p ${PACKAGE_ast_INCLUDE}
+exec - fi
+done ${PACKAGE_ast_INCLUDE} generated
+make ${PACKAGE_ast_INCLUDE}/cmd.h
+prev ${PACKAGE_ast_INCLUDE}
+prev cmd.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1992,author=gsf+dgk' cmd.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${PACKAGE_ast_INCLUDE}/cmd.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${PACKAGE_ast_INCLUDE}/cmd.h
+exec - fi
+done ${PACKAGE_ast_INCLUDE}/cmd.h generated
+make ${PACKAGE_ast_INCLUDE}/cmdext.h
+prev cmdext.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1992,author=gsf+dgk' cmdext.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${PACKAGE_ast_INCLUDE}/cmdext.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${PACKAGE_ast_INCLUDE}/cmdext.h
+exec - fi
+done ${PACKAGE_ast_INCLUDE}/cmdext.h generated
+make ${PACKAGE_ast_INCLUDE}/cmdlist.h
+make cmdlist.h
+exec - {
+exec - cat <<!
+exec - #pragma prototyped
+exec - /*
+exec - * -lcmd function list -- define your own CMDLIST()
+exec - */
+exec -
+exec - !
+exec - sed \
+exec - -e '/^b_[a-z_][a-z_0-9]*(/!d' \
+exec - -e 's/^b_//' \
+exec - -e 's/(.*//' \
+exec - -e 's/.*/CMDLIST(&)/' \
+exec - cmdinit.c basename.c cat.c chgrp.c chmod.c chown.c cksum.c cmp.c comm.c cp.c cut.c dirname.c date.c expr.c fds.c fmt.c fold.c getconf.c head.c id.c join.c ln.c logname.c md5sum.c mkdir.c mkfifo.c mktemp.c mv.c paste.c pathchk.c pids.c rev.c rm.c rmdir.c stty.c sum.c sync.c tail.c tee.c tty.c uname.c uniq.c vmstate.c wc.c revlib.c wclib.c fts_fix.c lib.c |
+exec - sort -u
+exec - } > 1.${COTEMP}.h
+exec - if cmp 2>/dev/null -s 1.${COTEMP}.h cmdlist.h
+exec - then rm -f 1.${COTEMP}.h
+exec - else mv 1.${COTEMP}.h cmdlist.h
+exec - fi
+done cmdlist.h generated
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1992,author=gsf+dgk' cmdlist.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${PACKAGE_ast_INCLUDE}/cmdlist.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${PACKAGE_ast_INCLUDE}/cmdlist.h
+exec - fi
+done ${PACKAGE_ast_INCLUDE}/cmdlist.h generated
+done install virtual
+make test
+done test dontcare virtual
diff --git a/src/lib/libcmd/RELEASE b/src/lib/libcmd/RELEASE
new file mode 100644
index 0000000..436cfbe
--- /dev/null
+++ b/src/lib/libcmd/RELEASE
@@ -0,0 +1,328 @@
+12-02-14 rm.c: --force ignores no file operands specified
+12-01-10 b_* (int, char**, void*) => (int, char**, Shbltin_t*)
+11-08-27 pids.c: add getsid() iffe test
+10-08-16 chmod.c: add -l alias for { -h --symlink }
+11-08-16 chgrp.c: change lchmod() ref to lchown()
+11-05-03 cp.c: do not delete src if mv to dest fails -- doh
+11-03-28 chmod.c,chgrp.c: fix --symlink logic
+11-03-26 rm.c: don't eaccess() check symlinks!
+11-01-27 date: add { -R, --rfc-2822, -T, --rfc-3339=type }
+11-01-03 chgrp.c: --symlink => --physical
+10-12-10 rm.c: fix not-writable logic
+10-12-01 tee.c: add iterrupt logic for slow open(1) -- needs to be generalized
+10-11-30 chgrp.c: add -N,--numeric to bypass name lookup
+10-10-20 cp: add --timestamps (preserv timestamps and permissions)
+10-10-20 ln: fix 'cannot replace existing file' logic
+10-10-10 cp,mv: add --remove-destination
+10-08-11 cp.c,expr.c: use conformance("standard",0) test
+10-08-11 cut.c: use mbnsize() instead of mblen() (for ast C.UTF-8)
+10-07-28 chgrp.c,chmod.c,cksum.c: fts_path for diagnostics, not fts_accpath!
+10-06-14 rm.c: fix -rfu logic
+10-06-12 paste.c: repeat after me: do not modify argv[i]
+10-06-01 sync with ast api 20100601
+10-05-09 tail.c: fix -0f bug that inially listed the entire file
+10-05-06 basename.c: add { -a,--all -s,--suffux=suffix } from BSD
+10-04-12 cat.c: fix -v bug that dumped core and make consistent with cmp --print-chars
+10-04-11 cmp.c: add --print-bytes, --count=n, --differences=n
+10-04-08 vmstate.c: add { method flags } vars for Vmstat_t.mode
+10-04-08 mkdir.c: fix check for { S_ISUID S_ISGID S_ISVTX } after successful mkdir(2)
+10-04-01 stty.c: add --fd=fd option
+10-03-23 tail.c: fix -f large initial offset bug that didn't copy all data
+10-03-07 tail.c: sfsync(sfstdout) after all -f done, fix -f partial line
+10-03-05 mktemp.c: add --regress=seed for testing
+10-03-05 vmstate.c: add
+10-01-26 tail.c: -f sleep(1) only if no progress from last round of checks
+10-01-20 fts_fix.[ch]: use <fts_fix.h> instead of <fts.h> (see fts_fix.c)
+10-01-20 cp.c: free(state) if called from old shell
+09-12-10 join.c: <wctype.h> for iswspace()!
+09-12-04 cmd.h: fix CMD_DYNAMIC logic
+09-12-04 cut.c: handle -d mb
+09-12-03 mkdir.c: add --verbose
+09-11-30 cat.c,date.c,cksum.c: drop setlocale() call already done by optget()
+09-11-30 join.c: handle -t mb
+09-11-28 wclib.c: { -w -L } mb independent of -m
+09-11-28 paste.c: handle -d mb
+09-11-28 uniq.c: handle -s mb
+09-11-28 cksum.c: FTS_SEEDOTDIR by default
+09-09-09 fds.c: add --unit=fd
+09-08-25 tail.c: initialize Tail_t.fifo=0 !!
+09-08-15 tail.c: fix fifo logic
+09-08-11 wc.c: add setlocale(LC_CTYPE,"C") cleanup, add utf8 optimzations
+09-08-10 uniq.c: replace -c 1..9999 sfsprintf() with inline conversion
+09-08-01 join.c: fix empty field null pointer deref
+09-07-23 pathchk.c: add -P,--path and -a,--all
+09-07-02 chgrp.c,chmod.c,cksum.c: fts_flags() default only if not --recursive
+09-06-19 cmd.h,cmdinit.c: add ERROR_CALLBACK for ERROR_NOTIFY main() callback
+09-06-19 mktemp.c: --unsafe now checks and prints path but does create
+09-06-19 tee.c: add ERROR_CALLBACK for tee_cleanup() sfio discipline pop
+09-06-18 rm.c: handle interrupts during interactive query
+09-06-18 cp.c: handle interrupts during interactive query
+09-05-25 tail.c: fix old style option logic to handle --invalid-long-option
+09-05-24 tail.c: -r == +1r
+09-05-01 mktemp.c: handle foo/prefix, add -p dir and -u
+09-03-31 cat.c: handle --no* options
+09-03-15 tail.c: fix --timeout termination logic
+09-03-03 tee.c: clean up sfio disciplines on error
+09-03-03 cat.c: fix -v|-e|-n|-B interaction bugs
+09-02-14 tail.c: fix VSC failures
+09-02-14 join.c: fix VSC failure
+09-02-02 uniq.c: document -number == -fnumber, +number == -snumber
+09-02-02 tail.c: fix usage[] for negative offsets, add sun -b
+09-02-02 mktemp.c: add
+09-02-02 features/utsname: UWIN _UNAME_os_DEFAULT => UWIN
+09-01-31 dirname.c: add experimental { -f -r -x } for pathpath(3)
+09-01-05 cmp.c: fix EOF diagnostic to conform to posix
+09-01-03 mkfifo.c: fix --mode=mode logic
+08-12-07 date.c: add %[_][EO]K for [space pad] [full|long] iso docs
+08-11-10 stty.c: check for -t grouping so -tostop != -t -ostop
+08-10-15 rm.c: handle 'rm -f x x' => exit 0
+08-09-08 stty.c: #ifdef guard TAB[012] -- freebsd: damn the posix, full speed ahead
+08-06-17 shcmd.h: move to libast
+08-04-24 uniq.c: add optget() 'n' option for -1 => -f1
+08-04-24 getconf.c: clarify diffs between "name - value" and "name = value"
+08-04-01 cut.c: add write error check
+08-04-01 paste.c: fix --noserial stream vector access bug
+08-04-01 pids.c: add ls/ps style --format=format
+08-04-01 stty.c: fix off2 unitialized reference
+08-03-28 chgrp.c: add --before=file
+08-03-14 pids.c: add
+08-03-11 chgrp.c: fix -m to use uid:gid as lookup key
+08-02-11 Makefile: add -lmd possibly required by sumlib.o -- hack alert
+08-01-30 expr.c: fix <=0 type that broke substr * 1 * -- wow
+07-12-13 cp.c: fix builtin state reinitialization
+07-11-29 rev.c: honor multibyte locales
+07-11-27 cp.c: open non-existent destination with O_EXCL
+07-11-27 stty.c: add -t,--terminal-group to list tty pgrp
+07-11-27 cksum.c: --silent -s => -S, -s == -x sys5 for gnu compatibility
+07-11-11 tee.c: drop ancient bsd compatibility "-" operand => SIGINT
+07-10-29 cksum.c: add SUM_LEGACY for -r
+07-10-12 cp.c: plug usage string memory leak by using per-builtin state
+07-09-21 cksum.c: add sumprint() default scale arg, --scale, --bsd for solaris
+07-09-10 chmod.c: add --show,-n
+07-07-27 wclib.c: bias <wchar.h> checks for modern unix
+07-07-17 cat.c: fix --squeeze-blank to reduce multiple blank lines to *one*
+07-05-20 cmd.h: handle msvc's balk at if(0)0=0;
+07-05-20 cksum.c: #include <modex.h>
+07-05-11 cmd.h: add _CMD_CONTEXT_OK() to verify >= 20070511 context
+07-05-09 fds.c: handle ipv6 sockets
+07-05-09 cmd.h: <shbltin.h> : cmdquit() => sh_checksig(context)
+07-04-25 mkdir.c: force (S_ISVTX|S_ISUID|S_ISGID) after mkdir(2)
+07-04-24 procrun.c: add -last intercept => sh_run() and whence -q
+07-04-19 uname.c: name operands first checked for CS_NAME, then NAME
+07-03-28 date.c: add --unelapsed=scale, -U: fmtelapsed() => strelapsed()
+07-03-25 wclib.h: iswspace() requires <wctype.h>!
+07-03-11 tty.c: add sysV --line-number, -l
+07-02-26 Makefile: sumlib.o: direct extract from +lsum (vcodex someday)
+07-02-24 Makefile: tweak cmdext.h action for --mam bootstrap
+07-02-09 Makefile: { cmdext.h cmdlist.h } depend on *.c list!
+07-02-09 Makefile: +lsum to bring in static -lsum (no dynamic right now)
+07-02-07 cksum.c: move from src/cmd/std with ftwalk => fts
+07-02-07 getconf.c: handle /bin == /usr/bin in defer logic
+07-01-26 chmod.c: don't FTS_FOLLOW if !FTS_PHYSICAL
+07-01-23 cut.c: Cut_t variable dimension list[] must be last member
+07-01-22 uname.c: fix -h typo that clobbered astconf() state -- ouch
+07-01-02 fmt.c: fix buffer splice off by one bug -- what else
+06-11-23 cmd.h: because of proto cmdinit cannot be a function like macro
+06-11-21 cp.c: fix 06-10-31 const dot[] readonly assignment
+06-11-15 cp.c: fix 06-10-31 ln -s enoent bug
+06-11-11 getconf.c: let astconf() handle "undefined" vs. ""
+06-11-11 getconf.c: fix deferred getconf path search
+06-11-11 fmt.c: handle two char { \t \n } in --usage ouput
+06-10-31 global edit to eliminate most non-const static data0
+06-10-31 use <cmd.h> for all b_*() implementations; drop <cmdlib.h>
+06-10-31 cmd.h: add CMD_ prefix to { BUILTIN DYNAMIC STANDALONE }
+06-10-31 join.c: tone down /tmp usage vi SFSK_DISCARD
+06-10-31 cp.c,rm.c: update to <fts.h> to accomodate non-static data
+06-10-29 date.c: "...%H%..." => "...%H" "%..." to avoid SCCS conflict
+06-10-26 fds.c: handle sctp
+06-10-18 tail.c: fix invalid suffix infinite loop
+06-10-11 chgrp.c,cp.c: add sfstruse() error checks
+06-10-10 tee.c: add --linebuffer, -l
+06-10-06 getconf.c: preserve native getconf(1) known variable behavior
+06-10-04 sync.c: add (thanks to Roland Mainz)
+06-10-04 getconf.c: add -v specification => run native getconf(1)
+06-09-28 stty.c: static setmode() => set() for darwin.i386
+06-09-27 head.c: handle -1c => -c1
+06-09-19 pathchk.c: pathconf() => astconf()
+06-09-11 tail.c: handle compatibility corner cases
+06-09-08 date.c: add output write error diagnostic
+06-09-04 tail.c: fix initial position for -n0, no args => no -f
+06-08-28 uniq.c: add -D,--all-repeated
+06-08-25 wc.c,wclib.c: add -L,--longest-line,WC_LONGEST
+06-08-24 wc.c,wclib.c: implement -m and WC_MBYTE
+06-08-24 rmdir.c: -sp applies to every message, add gnu -e
+06-08-23 rmdir.c: add solaris --suppress, -s
+06-08-23 mkdir.c: don't add 0300 to -p final dir mode
+06-07-17 cut.c: handle last line with no newline
+06-07-17 cut.c: --output-delimiter == --line-delimiter
+06-06-25 chmod.c: mask -c output with S_IPERM
+06-05-09 uname.c: add -o; change -a to match linux
+06-05-03 date.c: add --last -L to list last of multiple time args
+06-02-14 tail.c: fix -f bug that lost fast stream data
+06-02-11 getconf.c: exit 1 if name invalid -- duh
+06-01-28 cp.c,rm.c: fix astquery() 'q' to return and not exit()
+05-08-11 fmt.c: fix -o to handle raw --usage strings
+05-05-17 cat.c,head.c: disable EPIPE error messages
+05-04-14 chgrp.c: -f means all non-syntax error messages
+05-04-11 fds.c: add from old internal open(1)
+05-04-09 cmdext.h,cmdlist.h: generate from source -- about time
+05-03-24 features/symlink: verify { lchmod lchown } implementations
+05-03-07 date.c: add --listzones to list the time zone table
+05-02-14 chmod.c: add --reference=file
+05-01-11 cat.c: restore output stream to binary mode on exit
+04-12-15 cp.c: add --preserve high resolution time support
+04-12-08 date.c: add high resolution time support
+04-12-01 cmp.c: fix %6I*ld => %6I*d -- doh
+ fmt.c: handle "\n\n operands \n\n"
+ head.c: handle -cN -nN, N > 4Gb
+04-11-22 cmp.c: handle >2G chars/lines
+04-11-18 fold.c: add --prepend=text, --append=text
+04-10-31 tail.c: use SF_LOCKR macro
+04-10-28 tail.c: use strtol() for old stype [+-]number[suffix] -- doh
+04-10-22 cp.c: check rename() errno==ENOENT to retain destination
+04-10-11 fmt.c: fix -o,--optget sublist bugs
+ tail.c: use strton() for number conversion
+04-10-08 pathchk.c: add empty path and -p - first component char
+04-10-01 fmt.c: add -o,--optget concatenated usage string format
+ stty.c: context is ERROR_INTERCATIVE
+ rm.c: restore 3d before exit
+04-09-24 pathchk.c: fix docs
+04-09-14 date.c: add %| and %& --parse docs
+04-08-27 cp.c: add FTW_DC check -- duh
+04-08-01 fmt.c: handle last char != '\n'
+04-07-22 date.c,uname.c: access() => eaccess()
+04-07-01 fmt.c: handle large input lines -- ouch
+04-06-11 id.c: fix -r to output something!
+04-05-27 expr.c: fix `:' op subexpression output
+04-04-15 chmod.c: follow symlink for relative mode
+04-04-12 Makefile: add STDCHMOD (for osf.alpha)
+04-03-19 tail.c: handle -f sfreserve() large chunk failure
+04-02-29 cp.c: decouple -f and -i for standard CONFORMANCE
+ cp.c: mv now attempts rename() before remove()+rename()
+ date.c: -f format or +format disables system clock set
+04-02-14 cp.c: add -F --fsync to call fsync(2) for each copied file
+04-01-05 head.c: -s now uses opt_info.number for >2Gb skip
+03-09-18 tail.c: add --log
+03-09-11 rm.c: add --unconditional
+03-08-11 fold.c: add --delimiter=c to break at c
+03-07-28 features/time: change settimeofday() test to 2nd arg of (void*)0
+ expr.c: add {match,substr,index,length,quote}
+03-07-15 fmt.c: fix trailing space bug
+03-06-20 uname.c: fix -p constant string overwrite
+03-06-04 stty.c: add undef to control assignment docs
+03-05-31 uname.c: add -f and sysinfo()/confstr() compatibility via astconf()
+03-05-27 rm.c: fix inappropriate "/.." append path overflow
+ cut.c: snarf from dgk
+03-05-18 rm.c: check st_nlink to verify progress w.r.t. ftwalk/fts
+03-05-15 join.c: fix stealth -v2 bug (thanks ahs)
+03-05-04 wc.c: drop trailing space for `wc -l < file'
+03-03-21 date.c: add %Q/recent/distant/ docs
+03-02-19 date.c: fix %+|!flag docs
+02-11-14 update for cmdinit() 4th arg and ERROR_NOTIFY for interrupt cleanup
+02-10-02 date.c: tmform() => tmfmt()
+02-09-30 date.c,uname.c: change execv() calls to procrun(): exec|exit => bad
+02-09-06 wclib.c: fix 1 char-at-a-time miscount bug
+02-08-19 chgrp.c: convert to use <cdt.h>
+02-07-23 join.c: fix comm snarf typo
+02-04-05 date.c: add %u
+02-01-24 stty.c: ifdef a few more macros for uts (yes, its still running)
+01-12-14 date.c: clarify %z doc
+01-10-31 mkdir.c: mkdir() on existing dir could fail with errno!=EEXIST
+ uname.c: add execve() loop check for unknown options
+01-10-29 tail.c: SF_SHARE on only if not reading through EOF
+01-10-11 getconf.c: fix usage typos
+01-09-11 cp.c,cmd.h: handle . in argv[0]
+ cp.c: add O_BINARY to all open() calls
+01-09-06 tail: input streams must be SF_SHARE -- duh
+01-07-16 stty: fix cntl() macro for CC_NATIVE!=CC_ASCII
+01-05-31 date: fix /bin/date fallback logic
+ stty: fix a few mismatched flags, -a and -g option logic
+ stty: tone down sane to modify current settings rather than from zero
+01-05-01 uname: -i => -h, add sol.sun4 -i, add sgi -R, punt to /usr/bin/uname
+01-04-17 date,rm: add
+01-03-07 cp: fix readonly string mod on "."
+01-01-23 cp: `cp foo' => `cp foo .' only for CONFORMANCE!=standard
+00-12-01 cut: multibyte support
+00-10-31 mkdir: handle races by checking EEXIST
+00-09-20 cp: copy argv to stack before modifying in place
+00-05-18 add setlocale(LC_ALL,"")
+00-04-30 join: drop weird opt_info.argv reference
+00-03-17 expr: add == operator -- duh
+ cp,ln,mv: delay pathcanon() on destination to verify `cp a b/.'
+ getconf: use astgetconf for proper message control
+ ERROR_translate: dictionary update
+00-03-08 tail: handle multiple -f files
+00-03-07 fmt: add
+00-03-07 dirname: handle PATH_LEADING_SLASHES as documented
+ tail: accept + options
+00-02-14 chmod: --ignore-umask to ignore umask(2) in symbolic expressions
+ chmod,chgrp,cp: use FTS_NOSEEDOTDIR for correct path construction
+ cat: fix -n (was ignored, wow)
+00-01-27 getconf: add "-a" and "-v spec" for sol7.* compatibility
+99-09-09 join: fix -j1 vs. -j 1, add --ignorecase
+99-06-22 paste: defualt delim in writable string
+99-06-16 cat: fix --dos-ouput typo
+99-06-11 cp: tighten chown() diagnostics
+99-06-08 expr: nothing for NULL string bug fix
+99-05-21 paste: fix missing newline columnize bug
+99-05-20 mv: do not check for `mv foo foo' since rename() handles it
+99-05-01 cmp,comm,cp/mv/ln,expr,fold,getconf,head: long options
+ join,logname,paste,pathchk,tail,tee: long options
+99-04-10 uname: long options, stdize -a
+ chmod,head,tail,rev: long options
+ cut: long options, pass regression test 02
+99-04-07 cat: long options, fix O_TEXT modes
+99-01-11 tail: fix +n
+ join: another ggs/psm bug
+ join: all 1 and/or 2 to be unseekable
+99-01-01 cp: fix -p
+ chmod: drop -l option because of clash with l (lock) mode
+98-12-25 cat: add -T to sfopen(,,"rt")
+98-11-11 chgrp,chmod: cannot open file stream => not found
+ join: fix another ggs/psm bug; thanks guys
+98-10-20 cp: fix cp -rp to update dir times too
+98-09-22 join: fix ggs null field bug
+98-08-11 join: fix last regression test bug
+98-05-29 join: add jp->common to handle boundary conditions
+98-03-11 cat,cp,rev,tee: fix sfmove() error checks
+98-03-01 join: fix bug that emitted records more than once after eof
+ cp: fix sfmove() error check
+98-02-14 cp: -R physical, -[HLP], -r getconf(PATH_RESOLVE)
+98-01-11 cp: check sfclose() return value
+98-01-07 chown,chgrp,chmod: use fts for -R
+ mkdir: fix -p default mode
+97-12-07 mkdir: fix umask() reset
+97-11-11 chown,chgrp: proper interpretation of -h,-l for lchown()
+ chown,chgrp: only chown() if uid or gid change
+97-10-31 mkdir: do umask right
+97-08-11 cmdinit: clear opt_info.index to allow multiple calls
+ cp,ln,mv: add
+97-07-17 join: fix a few more -a bugs
+97-05-31 expr: optget() only if CONFORMANCE==standard
+97-04-01 join: fix a few bugs that make it work!
+96-12-25 head: sfset(sfstdin,SF_SHARE,1)
+ Makefile: add -last to cmd lib list
+ drop function __IMPORT__
+96-08-11 tail: check for truncated file and rewind for -f
+96-04-08 update <cmd.h>
+96-02-29 uname: -a like std, -l for everything
+ id: add -a (default)
+96-02-14 wc: speed up inner loop newline breakout
+96-01-30 unused var cleanup
+96-01-01 AT&T Research now
+ pathchk: handle getcwd(0,0) error
+ expr: switch to <regex.h>
+95-11-11 add expr.c
+ fix cut exit code and -s optimization
+95-10-11 add extern b_* to cmd.h
+ add void* context 3rd arg to b_main()
+95-05-09 add getconf
+ cat -u avoids mmap
+ add chown|chgrp -m uid|gid map file
+ add chown|chgrp -P for systems with lchown(2)
+ chown|chgrp -P => lstat() too!
+ chmod|chown|chgrp -HLP
+95-04-01 version 1.2
+ add rmdir
+95-02-14 fix mkdir -p symlink bug
+ fix mkdir '/' skip bug that went one too far
diff --git a/src/lib/libcmd/basename.c b/src/lib/libcmd/basename.c
new file mode 100644
index 0000000..9461183
--- /dev/null
+++ b/src/lib/libcmd/basename.c
@@ -0,0 +1,139 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * namebase pathname [suffix]
+ *
+ * print the namebase of a pathname
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: basename (AT&T Research) 2010-05-06 $\n]"
+USAGE_LICENSE
+"[+NAME?basename - strip directory and suffix from filenames]"
+"[+DESCRIPTION?\bbasename\b removes all leading directory components "
+ "from the file name defined by \astring\a. If the file name defined by "
+ "\astring\a has a suffix that ends in \asuffix\a, it is removed as "
+ "well.]"
+"[+?If \astring\a consists solely of \b/\b characters the output will be "
+ "a single \b/\b unless \bPATH_LEADING_SLASHES\b returned by "
+ "\bgetconf\b(1) is \b1\b and \astring\a consists of multiple \b/\b "
+ "characters in which case \b//\b will be output. Otherwise, trailing "
+ "\b/\b characters are removed, and if there are any remaining \b/\b "
+ "characters in \astring\a, all characters up to and including the last "
+ "\b/\b are removed. Finally, if \asuffix\a is specified, and is "
+ "identical the end of \astring\a, these characters are removed. The "
+ "characters not removed from \astring\a will be written on a single line "
+ "to the standard output.]"
+"[a:all?All operands are treated as \astring\a and each modified "
+ "pathname is printed on a separate line on the standard output.]"
+"[s:suffix?All operands are treated as \astring\a and each modified "
+ "pathname, with \asuffix\a removed if it exists, is printed on a "
+ "separate line on the standard output.]:[suffix]"
+"\n"
+"\n string [suffix]\n"
+"string ...\n"
+"\n"
+"[+EXIT STATUS?]"
+ "{"
+ "[+0?Successful Completion.]"
+ "[+>0?An error occurred.]"
+ "}"
+"[+SEE ALSO?\bdirname\b(1), \bgetconf\b(1), \bbasename\b(3)]"
+;
+
+
+#include <cmd.h>
+
+static void namebase(Sfio_t *outfile, register char *pathname, char *suffix)
+{
+ register char *first, *last;
+ register int n=0;
+ for(first=last=pathname; *last; last++);
+ /* back over trailing '/' */
+ if(last>first)
+ while(*--last=='/' && last > first);
+ if(last==first && *last=='/')
+ {
+ /* all '/' or "" */
+ if(*first=='/')
+ if(*++last=='/') /* keep leading // */
+ last++;
+ }
+ else
+ {
+ for(first=last++;first>pathname && *first!='/';first--);
+ if(*first=='/')
+ first++;
+ /* check for trailing suffix */
+ if(suffix && (n=strlen(suffix)) && n<(last-first))
+ {
+ if(memcmp(last-n,suffix,n)==0)
+ last -=n;
+ }
+ }
+ if(last>first)
+ sfwrite(outfile,first,last-first);
+ sfputc(outfile,'\n');
+}
+
+int
+b_basename(int argc, register char** argv, Shbltin_t* context)
+{
+ char* string;
+ char* suffix = 0;
+ int all = 0;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'a':
+ all = 1;
+ continue;
+ case 's':
+ all = 1;
+ suffix = opt_info.arg;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if (error_info.errors || argc < 1 || !all && argc > 2)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if (!all)
+ namebase(sfstdout, argv[0], argv[1]);
+ else
+ while (string = *argv++)
+ namebase(sfstdout, string, suffix);
+ return 0;
+}
diff --git a/src/lib/libcmd/cat.c b/src/lib/libcmd/cat.c
new file mode 100644
index 0000000..dae2a72
--- /dev/null
+++ b/src/lib/libcmd/cat.c
@@ -0,0 +1,557 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * cat
+ */
+
+#include <cmd.h>
+#include <fcntl.h>
+
+static const char usage[] =
+"[-?\n@(#)$Id: cat (AT&T Research) 2012-01-01 $\n]"
+USAGE_LICENSE
+"[+NAME?cat - concatenate files]"
+"[+DESCRIPTION?\bcat\b copies each \afile\a in sequence to the standard"
+" output. If no \afile\a is given, or if the \afile\a is \b-\b,"
+" \bcat\b copies from standard input starting at the current location.]"
+
+"[b:number-nonblank?Number lines as with \b-n\b but omit line numbers from"
+" blank lines.]"
+"[d:dos-input?Input files are opened in \atext\amode which removes carriage"
+" returns in front of new-lines on some systems.]"
+"[e?Equivalent to \b-vE\b.]"
+"[n:number?Causes a line number to be inserted at the beginning of each line.]"
+"[s?Equivalent to \b-S\b for \aatt\a universe and \b-B\b otherwise.]"
+"[t?Equivalent to \b-vT\b.]"
+"[u:unbuffer?The output is not delayed by buffering.]"
+"[v:show-nonprinting|print-chars?Print characters as follows: space and "
+ "printable characters as themselves; control characters as \b^\b "
+ "followed by a letter of the alphabet; and characters with the high bit "
+ "set as the lower 7 bit character prefixed by \bM^\b for 7 bit "
+ "non-printable characters and \bM-\b for all other characters. If the 7 "
+ "bit character encoding is not ASCII then the characters are converted "
+ "to ASCII to determine \ahigh bit set\a, and if set it is cleared and "
+ "converted back to the native encoding. Multibyte characters in the "
+ "current locale are treated as printable characters.]"
+"[A:show-all?Equivalent to \b-vET\b.]"
+"[B:squeeze-blank?Multiple adjacent new-line characters are replace by one"
+" new-line.]"
+"[D:dos-output?Output files are opened in \atext\amode which inserts carriage"
+" returns in front of new-lines on some systems.]"
+"[E:show-ends?Causes a \b$\b to be inserted before each new-line.]"
+"[R:regress?Regression test defaults: \b-v\b buffer size 4.]"
+"[S:silent?\bcat\b is silent about non-existent files.]"
+"[T:show-blank?Causes tabs to be copied as \b^I\b and formfeeds as \b^L\b.]"
+
+"\n"
+"\n[file ...]\n"
+"\n"
+
+"[+SEE ALSO?\bcp\b(1), \bgetconf\b(1), \bpr\b(1)]"
+;
+
+#define RUBOUT 0177
+
+/* control flags */
+#define B_FLAG (1<<0)
+#define E_FLAG (1<<1)
+#define F_FLAG (1<<2)
+#define N_FLAG (1<<3)
+#define S_FLAG (1<<4)
+#define T_FLAG (1<<5)
+#define U_FLAG (1<<6)
+#define V_FLAG (1<<7)
+#define D_FLAG (1<<8)
+#define d_FLAG (1<<9)
+
+/* character types */
+#define T_ERROR 1
+#define T_EOF 2
+#define T_ENDBUF 3
+#define T_NEWLINE 4
+#define T_CONTROL 5
+#define T_EIGHTBIT 6
+#define T_CNTL8BIT 7
+
+#define printof(c) ((c)^0100)
+
+typedef void* (*Reserve_f)(Sfio_t*, ssize_t, int);
+
+#ifndef sfvalue
+#define sfvalue(f) ((f)->_val)
+#endif
+
+static void*
+regress(Sfio_t* sp, ssize_t n, int f)
+{
+ void* r;
+
+ if (!(r = sfreserve(sp, 4, f)))
+ r = sfreserve(sp, n, f);
+ else if (sfvalue(sp) > 4)
+ sfvalue(sp) = 4;
+ return r;
+}
+
+/*
+ * called for any special output processing
+ */
+
+static int
+vcat(register char* states, Sfio_t* ip, Sfio_t* op, Reserve_f reserve, int flags)
+{
+ register unsigned char* cp;
+ register unsigned char* pp;
+ unsigned char* cur;
+ unsigned char* end;
+ unsigned char* buf;
+ unsigned char* nxt;
+ register int n;
+ register int line;
+ register int raw;
+ int last;
+ int c;
+ int m;
+ int any;
+ int header;
+
+ unsigned char meta[3];
+ unsigned char tmp[32];
+
+ meta[0] = 'M';
+ last = -1;
+ *(cp = buf = end = tmp) = 0;
+ any = 0;
+ header = flags & (B_FLAG|N_FLAG);
+ line = 1;
+ states[0] = T_ENDBUF;
+ raw = !mbwide();
+ for (;;)
+ {
+ cur = cp;
+ if (raw)
+ while (!(n = states[*cp++]));
+ else
+ for (;;)
+ {
+ while (!(n = states[*cp++]));
+ if (n < T_CONTROL)
+ break;
+ if ((m = mbsize(pp = cp - 1)) > 1)
+ cp += m - 1;
+ else
+ {
+ if (m <= 0)
+ {
+ if (cur == pp)
+ {
+ if (last > 0)
+ {
+ *end = last;
+ last = -1;
+ c = end - pp + 1;
+ if ((m = mbsize(pp)) == c)
+ {
+ any = 1;
+ if (header)
+ {
+ header = 0;
+ sfprintf(op, "%6d\t", line);
+ }
+ sfwrite(op, cur, m);
+ *(cp = cur = end) = 0;
+ }
+ else
+ {
+ memcpy(tmp, pp, c);
+ if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
+ {
+ states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
+ *(cp = end = tmp + sizeof(tmp) - 1) = 0;
+ last = -1;
+ }
+ else if ((n = sfvalue(ip)) <= 0)
+ {
+ states[0] = n ? T_ERROR : T_EOF;
+ *(cp = end = tmp + sizeof(tmp) - 1) = 0;
+ last = -1;
+ }
+ else
+ {
+ cp = buf = nxt;
+ end = buf + n - 1;
+ last = *end;
+ *end = 0;
+ }
+ mb:
+ if ((n = end - cp + 1) >= (sizeof(tmp) - c))
+ n = sizeof(tmp) - c - 1;
+ memcpy(tmp + c, cp, n);
+ if ((m = mbsize(tmp)) >= c)
+ {
+ any = 1;
+ if (header)
+ {
+ header = 0;
+ sfprintf(op, "%6d\t", line);
+ }
+ sfwrite(op, tmp, m);
+ cur = cp += m - c;
+ }
+ }
+ continue;
+ }
+ }
+ else
+ {
+ cp = pp + 1;
+ n = 0;
+ }
+ }
+ break;
+ }
+ }
+ c = *--cp;
+ if ((m = cp - cur) || n >= T_CONTROL)
+ {
+ flush:
+ any = 1;
+ if (header)
+ {
+ header = 0;
+ sfprintf(op, "%6d\t", line);
+ }
+ if (m)
+ sfwrite(op, cur, m);
+ }
+ special:
+ switch (n)
+ {
+ case T_ERROR:
+ if (cp < end)
+ {
+ n = T_CONTROL;
+ goto flush;
+ }
+ return -1;
+ case T_EOF:
+ if (cp < end)
+ {
+ n = T_CONTROL;
+ goto flush;
+ }
+ return 0;
+ case T_ENDBUF:
+ if (cp < end)
+ {
+ n = T_CONTROL;
+ goto flush;
+ }
+ c = last;
+ if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
+ {
+ *(cp = end = tmp + sizeof(tmp) - 1) = 0;
+ states[0] = (m = sfvalue(ip)) ? T_ERROR : T_EOF;
+ last = -1;
+ }
+ else if ((m = sfvalue(ip)) <= 0)
+ {
+ *(cp = end = tmp + sizeof(tmp) - 1) = 0;
+ states[0] = m ? T_ERROR : T_EOF;
+ last = -1;
+ }
+ else
+ {
+ buf = nxt;
+ end = buf + m - 1;
+ last = *end;
+ *end = 0;
+ cp = buf;
+ }
+ if (c >= 0)
+ {
+ if (!(n = states[c]))
+ {
+ *(cur = tmp) = c;
+ m = 1;
+ goto flush;
+ }
+ if (raw || n < T_CONTROL)
+ {
+ cp--;
+ goto special;
+ }
+ tmp[0] = c;
+ c = 1;
+ goto mb;
+ }
+ break;
+ case T_CONTROL:
+ do
+ {
+ sfputc(op, '^');
+ sfputc(op, printof(c));
+ } while (states[c = *++cp] == T_CONTROL);
+ break;
+ case T_CNTL8BIT:
+ meta[1] = '^';
+ do
+ {
+ n = c & ~0200;
+ meta[2] = printof(n);
+ sfwrite(op, (char*)meta, 3);
+ } while (states[c = *++cp] == T_CNTL8BIT && raw);
+ break;
+ case T_EIGHTBIT:
+ meta[1] = '-';
+ do
+ {
+ meta[2] = c & ~0200;
+ sfwrite(op, (char*)meta, 3);
+ } while (states[c = *++cp] == T_EIGHTBIT && raw);
+ break;
+ case T_NEWLINE:
+ if (header && !(flags & B_FLAG))
+ sfprintf(op, "%6d\t", line);
+ if (flags & E_FLAG)
+ sfputc(op, '$');
+ sfputc(op, '\n');
+ if (!header || !(flags & B_FLAG))
+ line++;
+ header = !(flags & S_FLAG);
+ for (;;)
+ {
+ if ((n = states[*++cp]) == T_ENDBUF)
+ {
+ if (cp < end || last != '\n')
+ break;
+ if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
+ {
+ states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
+ cp = end = tmp;
+ *cp-- = 0;
+ last = -1;
+ }
+ else if ((n = sfvalue(ip)) <= 0)
+ {
+ states[0] = n ? T_ERROR : T_EOF;
+ cp = end = tmp;
+ *cp-- = 0;
+ last = -1;
+ }
+ else
+ {
+ buf = nxt;
+ end = buf + n - 1;
+ last = *end;
+ *end = 0;
+ cp = buf - 1;
+ }
+ }
+ else if (n != T_NEWLINE)
+ break;
+ if (!(flags & S_FLAG) || any || header)
+ {
+ any = 0;
+ header = 0;
+ if ((flags & (B_FLAG|N_FLAG)) == N_FLAG)
+ sfprintf(op, "%6d\t", line);
+ if (flags & E_FLAG)
+ sfputc(op, '$');
+ sfputc(op, '\n');
+ }
+ if (!(flags & B_FLAG))
+ line++;
+ }
+ header = flags & (B_FLAG|N_FLAG);
+ break;
+ }
+ }
+}
+
+int
+b_cat(int argc, char** argv, Shbltin_t* context)
+{
+ register int n;
+ register int flags = 0;
+ register char* cp;
+ register Sfio_t* fp;
+ char* mode;
+ Reserve_f reserve = sfreserve;
+ int att;
+ int dovcat = 0;
+ char states[UCHAR_MAX+1];
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ att = !strcmp(astconf("UNIVERSE", NiL, NiL), "att");
+ mode = "r";
+ for (;;)
+ {
+ n = 0;
+ switch (optget(argv, usage))
+ {
+ case 'A':
+ n = T_FLAG|E_FLAG|V_FLAG;
+ break;
+ case 'B':
+ n = S_FLAG;
+ break;
+ case 'b':
+ n = B_FLAG;
+ break;
+ case 'd':
+ mode = opt_info.num ? "rt" : "r";
+ continue;
+ case 'D':
+ n = d_FLAG;
+ break;
+ case 'E':
+ n = E_FLAG;
+ break;
+ case 'e':
+ n = E_FLAG|V_FLAG;
+ break;
+ case 'n':
+ n = N_FLAG;
+ break;
+ case 'R':
+ reserve = opt_info.num ? regress : sfreserve;
+ continue;
+ case 's':
+ n = att ? F_FLAG : S_FLAG;
+ break;
+ case 'S':
+ n = F_FLAG;
+ break;
+ case 'T':
+ n = T_FLAG;
+ break;
+ case 't':
+ n = T_FLAG|V_FLAG;
+ break;
+ case 'u':
+ n = U_FLAG;
+ break;
+ case 'v':
+ n = V_FLAG;
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ if (!n)
+ break;
+ if (opt_info.num)
+ flags |= n;
+ else
+ flags &= ~n;
+ }
+ argv += opt_info.index;
+ if (error_info.errors)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ memset(states, 0, sizeof(states));
+ if (flags&V_FLAG)
+ {
+ memset(states, T_CONTROL, ' ');
+ states[RUBOUT] = T_CONTROL;
+ memset(states+0200, T_EIGHTBIT, 0200);
+ memset(states+0200, T_CNTL8BIT, ' ');
+ states[RUBOUT|0200] = T_CNTL8BIT;
+ states['\n'] = 0;
+ }
+ if (flags&T_FLAG)
+ states['\t'] = T_CONTROL;
+ states[0] = T_ENDBUF;
+ if (att)
+ {
+ if (flags&V_FLAG)
+ {
+ states['\n'|0200] = T_EIGHTBIT;
+ if (!(flags&T_FLAG))
+ {
+ states['\t'] = states['\f'] = 0;
+ states['\t'|0200] = states['\f'|0200] = T_EIGHTBIT;
+ }
+ }
+ }
+ else if (flags)
+ {
+ if (!(flags&T_FLAG))
+ states['\t'] = 0;
+ }
+ if (flags&(V_FLAG|T_FLAG|N_FLAG|E_FLAG|B_FLAG|S_FLAG))
+ {
+ states['\n'] = T_NEWLINE;
+ dovcat = 1;
+ }
+ if (flags&d_FLAG)
+ sfopen(sfstdout, NiL, "wt");
+ if (cp = *argv)
+ argv++;
+ do
+ {
+ if (!cp || streq(cp, "-"))
+ {
+ fp = sfstdin;
+ if (flags&D_FLAG)
+ sfopen(fp, NiL, mode);
+ }
+ else if (!(fp = sfopen(NiL, cp, mode)))
+ {
+ if (!(flags&F_FLAG))
+ error(ERROR_system(0), "%s: cannot open", cp);
+ error_info.errors = 1;
+ continue;
+ }
+ if (flags&U_FLAG)
+ sfsetbuf(fp, (void*)fp, -1);
+ if (dovcat)
+ n = vcat(states, fp, sfstdout, reserve, flags);
+ else if (sfmove(fp, sfstdout, SF_UNBOUND, -1) >= 0 && sfeof(fp))
+ n = 0;
+ else
+ n = -1;
+ if (fp != sfstdin)
+ sfclose(fp);
+ if (n < 0 && errno != EPIPE && errno != EINTR)
+ {
+ if (cp)
+ error(ERROR_system(0), "%s: read error", cp);
+ else
+ error(ERROR_system(0), "read error");
+ }
+ if (sferror(sfstdout))
+ break;
+ } while (cp = *argv++);
+ if (sfsync(sfstdout))
+ error(ERROR_system(0), "write error");
+ if (flags&d_FLAG)
+ sfopen(sfstdout, NiL, "w");
+ return error_info.errors;
+}
diff --git a/src/lib/libcmd/chgrp.c b/src/lib/libcmd/chgrp.c
new file mode 100644
index 0000000..3c53528
--- /dev/null
+++ b/src/lib/libcmd/chgrp.c
@@ -0,0 +1,501 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * chgrp+chown
+ */
+
+static const char usage_1[] =
+"[-?@(#)$Id: chgrp (AT&T Research) 2011-04-28 $\n]"
+USAGE_LICENSE
+;
+
+static const char usage_grp_1[] =
+"[+NAME?chgrp - change the group ownership of files]"
+"[+DESCRIPTION?\bchgrp\b changes the group ownership of each file"
+" to \agroup\a, which can be either a group name or a numeric"
+" group id. The user ownership of each file may also be changed to"
+" \auser\a by prepending \auser\a\b:\b to the group name.]"
+;
+
+static const char usage_own_1[] =
+"[+NAME?chown - change the ownership of files]"
+"[+DESCRIPTION?\bchown\b changes the ownership of each file"
+" to \auser\a, which can be either a user name or a numeric"
+" user id. The group ownership of each file may also be changed to"
+" \auser\a by appending \b:\b\agroup\a to the user name.]"
+;
+
+static const char usage_2[] =
+"[b:before?Only change files with \bctime\b before (less than) the "
+ "\bmtime\b of \afile\a.]:[file]"
+"[c:changes?Describe only files whose ownership actually changes.]"
+"[f:quiet|silent?Do not report files whose ownership fails to change.]"
+"[h|l:symlink?Change the ownership of symbolic links on systems that "
+ "support \blchown\b(2). Implies \b--physical\b.]"
+"[m:map?The first operand is interpreted as a file that contains a map "
+ "of space separated \afrom_uid:from_gid to_uid:to_gid\a pairs. The "
+ "\auid\a or \agid\a part of each pair may be omitted to mean any \auid\a "
+ "or \agid\a. Ownership of files matching the \afrom\a part of any pair "
+ "is changed to the corresponding \ato\a part of the pair. The matching "
+ "for each file operand is in the order \auid\a:\agid\a, \auid\a:, "
+ ":\agid\a. For a given file, once a \auid\a or \agid\a mapping is "
+ "determined it is not overridden by any subsequent match. Unmatched "
+ "files are silently ignored.]"
+"[n:show?Show actions but don't execute.]"
+"[N:numeric?By default numeric user and group id operands are first "
+ "interpreted as names; if no name exists then they are interpreted as "
+ "explicit numeric ids. \b--numeric\b interprets numeric id operands as "
+ "numeric ids.]"
+"[r:reference?Omit the explicit ownership operand and use the ownership "
+ "of \afile\a instead.]:[file]"
+"[u:unmapped?Print a diagnostic for each file for which either the "
+ "\auid\a or \agid\a or both were not mapped.]"
+"[v:verbose?Describe changed permissions of all files.]"
+"[H:metaphysical?Follow symbolic links for command arguments; otherwise "
+ "don't follow symbolic links when traversing directories.]"
+"[L:logical|follow?Follow symbolic links when traversing directories.]"
+"[P:physical|nofollow?Don't follow symbolic links when traversing "
+ "directories.]"
+"[R:recursive?Recursively change ownership of directories and their "
+ "contents.]"
+"[X:test?Canonicalize output for testing.]"
+
+"\n"
+"\n"
+;
+
+static const char usage_3[] =
+" file ...\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All files changed successfully.]"
+ "[+>0?Unable to change ownership of one or more files.]"
+"}"
+"[+SEE ALSO?\bchmod\b(1), \bchown\b(2), \btw\b(1), \bgetconf\b(1), \bls\b(1)]"
+;
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide lchown
+#else
+#define lchown ______lchown
+#endif
+
+#include <cmd.h>
+#include <cdt.h>
+#include <ls.h>
+#include <ctype.h>
+#include <fts_fix.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+#include "FEATURE/symlink"
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide lchown
+#else
+#undef lchown
+#endif
+
+typedef struct Key_s /* uid/gid key */
+{
+ int uid; /* uid */
+ int gid; /* gid */
+} Key_t;
+
+typedef struct Map_s /* uid/gid map */
+{
+ Dtlink_t link; /* dictionary link */
+ Key_t key; /* key */
+ Key_t to; /* map to these */
+} Map_t;
+
+#define NOID (-1)
+
+#define OPT_CHOWN 0x0001 /* chown */
+#define OPT_FORCE 0x0002 /* ignore errors */
+#define OPT_GID 0x0004 /* have gid */
+#define OPT_LCHOWN 0x0008 /* lchown */
+#define OPT_NUMERIC 0x0010 /* favor numeric ids */
+#define OPT_SHOW 0x0020 /* show but don't do */
+#define OPT_TEST 0x0040 /* canonicalize output */
+#define OPT_UID 0x0080 /* have uid */
+#define OPT_UNMAPPED 0x0100 /* unmapped file diagnostic */
+#define OPT_VERBOSE 0x0200 /* have uid */
+
+extern int lchown(const char*, uid_t, gid_t);
+
+/*
+ * parse uid and gid from s
+ */
+
+static void
+getids(register char* s, char** e, Key_t* key, int options)
+{
+ register char* t;
+ register int n;
+ register int m;
+ char* z;
+ char buf[64];
+
+ key->uid = key->gid = NOID;
+ while (isspace(*s))
+ s++;
+ for (t = s; (n = *t) && n != ':' && n != '.' && !isspace(n); t++);
+ if (n)
+ {
+ options |= OPT_CHOWN;
+ if ((n = t++ - s) >= sizeof(buf))
+ n = sizeof(buf) - 1;
+ *((s = (char*)memcpy(buf, s, n)) + n) = 0;
+ }
+ if (options & OPT_CHOWN)
+ {
+ if (*s)
+ {
+ n = (int)strtol(s, &z, 0);
+ if (*z || !(options & OPT_NUMERIC))
+ {
+ if ((m = struid(s)) != NOID)
+ n = m;
+ else if (*z)
+ error(ERROR_exit(1), "%s: unknown user", s);
+ }
+ key->uid = n;
+ }
+ for (s = t; (n = *t) && !isspace(n); t++);
+ if (n)
+ {
+ if ((n = t++ - s) >= sizeof(buf))
+ n = sizeof(buf) - 1;
+ *((s = (char*)memcpy(buf, s, n)) + n) = 0;
+ }
+ }
+ if (*s)
+ {
+ n = (int)strtol(s, &z, 0);
+ if (*z || !(options & OPT_NUMERIC))
+ {
+ if ((m = strgid(s)) != NOID)
+ n = m;
+ else if (*z)
+ error(ERROR_exit(1), "%s: unknown group", s);
+ }
+ key->gid = n;
+ }
+ if (e)
+ *e = t;
+}
+
+/*
+ * NOTE: we only use the native lchown() on symlinks just in case
+ * the implementation is a feckless stub
+ */
+
+int
+b_chgrp(int argc, char** argv, Shbltin_t* context)
+{
+ register int options = 0;
+ register char* s;
+ register Map_t* m;
+ register FTS* fts;
+ register FTSENT*ent;
+ register int i;
+ Dt_t* map = 0;
+ int logical = 1;
+ int flags;
+ int uid;
+ int gid;
+ char* op;
+ char* usage;
+ char* t;
+ Sfio_t* sp;
+ unsigned long before;
+ Dtdisc_t mapdisc;
+ Key_t keys[3];
+ Key_t key;
+ struct stat st;
+ int (*chownf)(const char*, uid_t, gid_t);
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
+ flags = fts_flags() | FTS_TOP | FTS_NOPOSTORDER | FTS_NOSEEDOTDIR;
+ before = ~0;
+ if (!(sp = sfstropen()))
+ error(ERROR_SYSTEM|3, "out of space");
+ sfputr(sp, usage_1, -1);
+ if (error_info.id[2] == 'g')
+ sfputr(sp, usage_grp_1, -1);
+ else
+ {
+ sfputr(sp, usage_own_1, -1);
+ options |= OPT_CHOWN;
+ }
+ sfputr(sp, usage_2, -1);
+ if (options & OPT_CHOWN)
+ sfputr(sp, ERROR_translate(0, 0, 0, "[owner[:group]]"), -1);
+ else
+ sfputr(sp, ERROR_translate(0, 0, 0, "[[owner:]group]"), -1);
+ sfputr(sp, usage_3, -1);
+ if (!(usage = sfstruse(sp)))
+ error(ERROR_SYSTEM|3, "out of space");
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'b':
+ if (stat(opt_info.arg, &st))
+ error(ERROR_exit(1), "%s: cannot stat", opt_info.arg);
+ before = st.st_mtime;
+ continue;
+ case 'c':
+ case 'v':
+ options |= OPT_VERBOSE;
+ continue;
+ case 'f':
+ options |= OPT_FORCE;
+ continue;
+ case 'h':
+ options |= OPT_LCHOWN;
+ continue;
+ case 'm':
+ memset(&mapdisc, 0, sizeof(mapdisc));
+ mapdisc.key = offsetof(Map_t, key);
+ mapdisc.size = sizeof(Key_t);
+ if (!(map = dtopen(&mapdisc, Dtset)))
+ error(ERROR_exit(1), "out of space [id map]");
+ continue;
+ case 'n':
+ options |= OPT_SHOW;
+ continue;
+ case 'N':
+ options |= OPT_NUMERIC;
+ continue;
+ case 'r':
+ if (stat(opt_info.arg, &st))
+ error(ERROR_exit(1), "%s: cannot stat", opt_info.arg);
+ uid = st.st_uid;
+ gid = st.st_gid;
+ options |= OPT_UID|OPT_GID;
+ continue;
+ case 'u':
+ options |= OPT_UNMAPPED;
+ continue;
+ case 'H':
+ flags |= FTS_META|FTS_PHYSICAL;
+ logical = 0;
+ continue;
+ case 'L':
+ flags &= ~(FTS_META|FTS_PHYSICAL);
+ logical = 0;
+ continue;
+ case 'P':
+ flags &= ~FTS_META;
+ flags |= FTS_PHYSICAL;
+ logical = 0;
+ continue;
+ case 'R':
+ flags &= ~FTS_TOP;
+ logical = 0;
+ continue;
+ case 'X':
+ options |= OPT_TEST;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if (error_info.errors || argc < 2)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ s = *argv;
+ if (options & OPT_LCHOWN)
+ {
+ flags &= ~FTS_META;
+ flags |= FTS_PHYSICAL;
+ logical = 0;
+ }
+ if (logical)
+ flags &= ~(FTS_META|FTS_PHYSICAL);
+ if (map)
+ {
+ if (streq(s, "-"))
+ sp = sfstdin;
+ else if (!(sp = sfopen(NiL, s, "r")))
+ error(ERROR_exit(1), "%s: cannot read", s);
+ while (s = sfgetr(sp, '\n', 1))
+ {
+ getids(s, &t, &key, options);
+ if (!(m = (Map_t*)dtmatch(map, &key)))
+ {
+ if (!(m = (Map_t*)stakalloc(sizeof(Map_t))))
+ error(ERROR_exit(1), "out of space [id dictionary]");
+ m->key = key;
+ m->to.uid = m->to.gid = NOID;
+ dtinsert(map, m);
+ }
+ getids(t, NiL, &m->to, options);
+ }
+ if (sp != sfstdin)
+ sfclose(sp);
+ keys[1].gid = keys[2].uid = NOID;
+ }
+ else if (!(options & (OPT_UID|OPT_GID)))
+ {
+ getids(s, NiL, &key, options);
+ if ((uid = key.uid) != NOID)
+ options |= OPT_UID;
+ if ((gid = key.gid) != NOID)
+ options |= OPT_GID;
+ }
+ switch (options & (OPT_UID|OPT_GID))
+ {
+ case OPT_UID:
+ s = ERROR_translate(0, 0, 0, " owner");
+ break;
+ case OPT_GID:
+ s = ERROR_translate(0, 0, 0, " group");
+ break;
+ case OPT_UID|OPT_GID:
+ s = ERROR_translate(0, 0, 0, " owner and group");
+ break;
+ default:
+ s = "";
+ break;
+ }
+ if (!(fts = fts_open(argv + 1, flags, NiL)))
+ error(ERROR_system(1), "%s: not found", argv[1]);
+ while (!sh_checksig(context) && (ent = fts_read(fts)))
+ switch (ent->fts_info)
+ {
+ case FTS_SL:
+ case FTS_SLNONE:
+ if (options & OPT_LCHOWN)
+ {
+#if _lib_lchown
+ chownf = lchown;
+ op = "lchown";
+ goto commit;
+#else
+ if (!(options & OPT_FORCE))
+ {
+ errno = ENOSYS;
+ error(ERROR_system(0), "%s: cannot change symlink owner/group", ent->fts_path);
+ }
+#endif
+ }
+ break;
+ case FTS_F:
+ case FTS_D:
+ anyway:
+ chownf = chown;
+ op = "chown";
+ commit:
+ if ((unsigned long)ent->fts_statp->st_ctime >= before)
+ break;
+ if (map)
+ {
+ options &= ~(OPT_UID|OPT_GID);
+ uid = gid = NOID;
+ keys[0].uid = keys[1].uid = ent->fts_statp->st_uid;
+ keys[0].gid = keys[2].gid = ent->fts_statp->st_gid;
+ i = 0;
+ do
+ {
+ if (m = (Map_t*)dtmatch(map, &keys[i]))
+ {
+ if (uid == NOID && m->to.uid != NOID)
+ {
+ uid = m->to.uid;
+ options |= OPT_UID;
+ }
+ if (gid == NOID && m->to.gid != NOID)
+ {
+ gid = m->to.gid;
+ options |= OPT_GID;
+ }
+ }
+ } while (++i < elementsof(keys) && (uid == NOID || gid == NOID));
+ }
+ else
+ {
+ if (!(options & OPT_UID))
+ uid = ent->fts_statp->st_uid;
+ if (!(options & OPT_GID))
+ gid = ent->fts_statp->st_gid;
+ }
+ if ((options & OPT_UNMAPPED) && (uid == NOID || gid == NOID))
+ {
+ if (uid == NOID && gid == NOID)
+ error(ERROR_warn(0), "%s: uid and gid not mapped", ent->fts_path);
+ else if (uid == NOID)
+ error(ERROR_warn(0), "%s: uid not mapped", ent->fts_path);
+ else
+ error(ERROR_warn(0), "%s: gid not mapped", ent->fts_path);
+ }
+ if (uid != ent->fts_statp->st_uid && uid != NOID || gid != ent->fts_statp->st_gid && gid != NOID)
+ {
+ if (options & (OPT_SHOW|OPT_VERBOSE))
+ {
+ if (options & OPT_TEST)
+ {
+ ent->fts_statp->st_uid = 0;
+ ent->fts_statp->st_gid = 0;
+ }
+ sfprintf(sfstdout, "%s uid:%05d->%05d gid:%05d->%05d %s\n", op, ent->fts_statp->st_uid, uid, ent->fts_statp->st_gid, gid, ent->fts_path);
+ }
+ if (!(options & OPT_SHOW) && (*chownf)(ent->fts_accpath, uid, gid) && !(options & OPT_FORCE))
+ error(ERROR_system(0), "%s: cannot change%s", ent->fts_path, s);
+ }
+ break;
+ case FTS_DC:
+ if (!(options & OPT_FORCE))
+ error(ERROR_warn(0), "%s: directory causes cycle", ent->fts_path);
+ break;
+ case FTS_DNR:
+ if (!(options & OPT_FORCE))
+ error(ERROR_system(0), "%s: cannot read directory", ent->fts_path);
+ goto anyway;
+ case FTS_DNX:
+ if (!(options & OPT_FORCE))
+ error(ERROR_system(0), "%s: cannot search directory", ent->fts_path);
+ goto anyway;
+ case FTS_NS:
+ if (!(options & OPT_FORCE))
+ error(ERROR_system(0), "%s: not found", ent->fts_path);
+ break;
+ }
+ fts_close(fts);
+ if (map)
+ dtclose(map);
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/chmod.c b/src/lib/libcmd/chmod.c
new file mode 100644
index 0000000..fcb974e
--- /dev/null
+++ b/src/lib/libcmd/chmod.c
@@ -0,0 +1,325 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * chmod
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: chmod (AT&T Research) 2011-03-28 $\n]"
+USAGE_LICENSE
+"[+NAME?chmod - change the access permissions of files]"
+"[+DESCRIPTION?\bchmod\b changes the permission of each file "
+ "according to mode, which can be either a symbolic representation "
+ "of changes to make, or an octal number representing the bit "
+ "pattern for the new permissions.]"
+"[+?Symbolic mode strings consist of one or more comma separated list "
+ "of operations that can be perfomed on the mode. Each operation is of "
+ "the form \auser\a \aop\a \aperm\a where \auser\a is zero or more of "
+ "the following letters:]{"
+ "[+u?User permission bits.]"
+ "[+g?Group permission bits.]"
+ "[+o?Other permission bits.]"
+ "[+a?All permission bits. This is the default if none are specified.]"
+ "}"
+"[+?The \aperm\a portion consists of zero or more of the following letters:]{"
+ "[+r?Read permission.]"
+ "[+s?Setuid when \bu\b is selected for \awho\a and setgid when \bg\b "
+ "is selected for \awho\a.]"
+ "[+w?Write permission.]"
+ "[+x?Execute permission for files, search permission for directories.]"
+ "[+X?Same as \bx\b except that it is ignored for files that do not "
+ "already have at least one \bx\b bit set.]"
+ "[+l?Exclusive lock bit on systems that support it. Group execute "
+ "must be off.]"
+ "[+t?Sticky bit on systems that support it.]"
+ "}"
+"[+?The \aop\a portion consists of one or more of the following characters:]{"
+ "[++?Cause the permission selected to be added to the existing "
+ "permissions. | is equivalent to +.]"
+ "[+-?Cause the permission selected to be removed to the existing "
+ "permissions.]"
+ "[+=?Cause the permission to be set to the given permissions.]"
+ "[+&?Cause the permission selected to be \aand\aed with the existing "
+ "permissions.]"
+ "[+^?Cause the permission selected to be propagated to more "
+ "restrictive groups.]"
+ "}"
+"[+?Symbolic modes with the \auser\a portion omitted are subject to "
+ "\bumask\b(2) settings unless the \b=\b \aop\a or the "
+ "\b--ignore-umask\b option is specified.]"
+"[+?A numeric mode is from one to four octal digits (0-7), "
+ "derived by adding up the bits with values 4, 2, and 1. "
+ "Any omitted digits are assumed to be leading zeros. The "
+ "first digit selects the set user ID (4) and set group ID "
+ "(2) and save text image (1) attributes. The second digit "
+ "selects permissions for the user who owns the file: read "
+ "(4), write (2), and execute (1); the third selects permissions"
+ "for other users in the file's group, with the same values; "
+ "and the fourth for other users not in the file's group, with "
+ "the same values.]"
+
+"[+?For symbolic links, by default, \bchmod\b changes the mode on the file "
+ "referenced by the symbolic link, not on the symbolic link itself. "
+ "The \b-h\b options can be specified to change the mode of the link. "
+ "When traversing directories with \b-R\b, \bchmod\b either follows "
+ "symbolic links or does not follow symbolic links, based on the "
+ "options \b-H\b, \b-L\b, and \b-P\b. The configuration parameter "
+ "\bPATH_RESOLVE\b determines the default behavior if none of these "
+ "options is specified.]"
+
+"[+?When the \b-c\b or \b-v\b options are specified, change notifications "
+ "are written to standard output using the format, "
+ "\b%s: mode changed to %0.4o (%s)\b, with arguments of the "
+ "pathname, the numeric mode, and the resulting permission bits as "
+ "would be displayed by the \bls\b command.]"
+
+"[+?For backwards compatibility, if an invalid option is given that is a valid "
+ "symbolic mode specification, \bchmod\b treats this as a mode "
+ "specification rather than as an option specification.]"
+
+"[H:metaphysical?Follow symbolic links for command arguments; otherwise don't "
+ "follow symbolic links when traversing directories.]"
+"[L:logical|follow?Follow symbolic links when traversing directories.]"
+"[P:physical|nofollow?Don't follow symbolic links when traversing directories.]"
+"[R:recursive?Change the mode for files in subdirectories recursively.]"
+"[c:changes?Describe only files whose permission actually change.]"
+"[f:quiet|silent?Do not report files whose permissioins fail to change.]"
+"[h|l:symlink?Change the mode of symbolic links on systems that "
+ "support \blchmod\b(2). Implies \b--physical\b.]"
+"[i:ignore-umask?Ignore the \bumask\b(2) value in symbolic mode "
+ "expressions. This is probably how you expect \bchmod\b to work.]"
+"[n:show?Show actions but do not change any file modes.]"
+"[F:reference?Omit the \amode\a operand and use the mode of \afile\a "
+ "instead.]:[file]"
+"[v:verbose?Describe changed permissions of all files.]"
+"\n"
+"\nmode file ...\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All files changed successfully.]"
+ "[+>0?Unable to change mode of one or more files.]"
+"}"
+"[+SEE ALSO?\bchgrp\b(1), \bchown\b(1), \blchmod\b(1), \btw\b(1), \bgetconf\b(1), "
+ "\bls\b(1), \bumask\b(2)]"
+;
+
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide lchmod
+#else
+#define lchmod ______lchmod
+#endif
+
+#include <cmd.h>
+#include <ls.h>
+#include <fts_fix.h>
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+#include "FEATURE/symlink"
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide lchmod
+#else
+#undef lchmod
+#endif
+
+extern int lchmod(const char*, mode_t);
+
+/*
+ * NOTE: we only use the native lchmod() on symlinks just in case
+ * the implementation is a feckless stub
+ */
+
+int
+b_chmod(int argc, char** argv, Shbltin_t* context)
+{
+ register int mode;
+ register int force = 0;
+ register int flags;
+ register char* amode = 0;
+ register FTS* fts;
+ register FTSENT*ent;
+ char* last;
+ int (*chmodf)(const char*, mode_t);
+ int logical = 1;
+ int notify = 0;
+ int ignore = 0;
+ int show = 0;
+ int chlink = 0;
+ struct stat st;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
+ flags = fts_flags() | FTS_TOP | FTS_NOPOSTORDER | FTS_NOSEEDOTDIR;
+
+ /*
+ * NOTE: we diverge from the normal optget boilerplate
+ * to allow `chmod -x etc' to fall through
+ */
+
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'c':
+ notify = 1;
+ continue;
+ case 'f':
+ force = 1;
+ continue;
+ case 'h':
+ chlink = 1;
+ continue;
+ case 'i':
+ ignore = 1;
+ continue;
+ case 'n':
+ show = 1;
+ continue;
+ case 'v':
+ notify = 2;
+ continue;
+ case 'F':
+ if (stat(opt_info.arg, &st))
+ error(ERROR_exit(1), "%s: cannot stat", opt_info.arg);
+ mode = st.st_mode;
+ amode = "";
+ continue;
+ case 'H':
+ flags |= FTS_META|FTS_PHYSICAL;
+ logical = 0;
+ continue;
+ case 'L':
+ flags &= ~(FTS_META|FTS_PHYSICAL);
+ logical = 0;
+ continue;
+ case 'P':
+ flags &= ~FTS_META;
+ flags |= FTS_PHYSICAL;
+ logical = 0;
+ continue;
+ case 'R':
+ flags &= ~FTS_TOP;
+ logical = 0;
+ continue;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || !*argv || !amode && !*(argv + 1))
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if (chlink)
+ {
+ flags &= ~FTS_META;
+ flags |= FTS_PHYSICAL;
+ logical = 0;
+ }
+ if (logical)
+ flags &= ~(FTS_META|FTS_PHYSICAL);
+ if (ignore)
+ ignore = umask(0);
+ if (amode)
+ amode = 0;
+ else
+ {
+ amode = *argv++;
+ mode = strperm(amode, &last, 0);
+ if (*last)
+ {
+ if (ignore)
+ umask(ignore);
+ error(ERROR_exit(1), "%s: invalid mode", amode);
+ }
+ }
+ if (!(fts = fts_open(argv, flags, NiL)))
+ {
+ if (ignore)
+ umask(ignore);
+ error(ERROR_system(1), "%s: not found", *argv);
+ }
+ while (!sh_checksig(context) && (ent = fts_read(fts)))
+ switch (ent->fts_info)
+ {
+ case FTS_SL:
+ case FTS_SLNONE:
+ if (chlink)
+ {
+#if _lib_lchmod
+ chmodf = lchmod;
+ goto commit;
+#else
+ if (!force)
+ {
+ errno = ENOSYS;
+ error(ERROR_system(0), "%s: cannot change symlink mode", ent->fts_path);
+ }
+#endif
+ }
+ break;
+ case FTS_F:
+ case FTS_D:
+ anyway:
+ chmodf = chmod;
+#if _lib_lchmod
+ commit:
+#endif
+ if (amode)
+ mode = strperm(amode, &last, ent->fts_statp->st_mode);
+ if (show || (*chmodf)(ent->fts_accpath, mode) >= 0)
+ {
+ if (notify == 2 || notify == 1 && (mode&S_IPERM) != (ent->fts_statp->st_mode&S_IPERM))
+ sfprintf(sfstdout, "%s: mode changed to %0.4o (%s)\n", ent->fts_path, mode, fmtmode(mode, 1)+1);
+ }
+ else if (!force)
+ error(ERROR_system(0), "%s: cannot change mode", ent->fts_path);
+ break;
+ case FTS_DC:
+ if (!force)
+ error(ERROR_warn(0), "%s: directory causes cycle", ent->fts_path);
+ break;
+ case FTS_DNR:
+ if (!force)
+ error(ERROR_system(0), "%s: cannot read directory", ent->fts_path);
+ goto anyway;
+ case FTS_DNX:
+ if (!force)
+ error(ERROR_system(0), "%s: cannot search directory", ent->fts_path);
+ goto anyway;
+ case FTS_NS:
+ if (!force)
+ error(ERROR_system(0), "%s: not found", ent->fts_path);
+ break;
+ }
+ fts_close(fts);
+ if (ignore)
+ umask(ignore);
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/chown.c b/src/lib/libcmd/chown.c
new file mode 100644
index 0000000..3896635
--- /dev/null
+++ b/src/lib/libcmd/chown.c
@@ -0,0 +1,39 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * chown
+ */
+
+static const char id[] = "\n@(#)$Id: chown (AT&T Research) 1997-11-11 $\0\n";
+
+#include <cmd.h>
+
+int
+b_chown(int argc, char** argv, Shbltin_t* context)
+{
+ NoP(id[0]);
+ return b_chgrp(argc, argv, context);
+}
diff --git a/src/lib/libcmd/cksum.c b/src/lib/libcmd/cksum.c
new file mode 100644
index 0000000..ca43e17
--- /dev/null
+++ b/src/lib/libcmd/cksum.c
@@ -0,0 +1,632 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * sum -- list file checksum and size
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: sum (AT&T Research) 2010-07-28 $\n]"
+USAGE_LICENSE
+"[+NAME?cksum,md5sum,sum - print file checksum and block count]"
+"[+DESCRIPTION?\bsum\b lists the checksum, and for most methods the block"
+" count, for each file argument. The standard input is read if there are"
+" no \afile\a arguments. \bgetconf UNIVERSE\b determines the default"
+" \bsum\b method: \batt\b for the \batt\b universe, \bbsd\b otherwise."
+" The default for the other commands is the command name itself. The"
+" \batt\b method is a true sum, all others are order dependent.]"
+"[+?Method names consist of a leading identifier and 0 or more options"
+" separated by -.]"
+"[+?\bgetconf PATH_RESOLVE\b determines how symbolic links are handled. This"
+" can be explicitly overridden by the \b--logical\b, \b--metaphysical\b,"
+" and \b--physical\b options below. \bPATH_RESOLVE\b can be one of:]{"
+" [+logical?Follow all symbolic links.]"
+" [+metaphysical?Follow command argument symbolic links,"
+" otherwise don't follow.]"
+" [+physical?Don't follow symbolic links.]"
+"}"
+
+"[a:all?List the checksum for all files. Use with \b--total\b to list both"
+" individual and total checksums and block counts.]"
+"[b:binary?Read files in binary mode. This is the default.]"
+"[B:scale?Block count scale (bytes per block) override for methods that"
+" include size in the output. The default is method specific.]#[scale]"
+"[c:check?Each \afile\a is interpreted as the output from a previous \bsum\b."
+" If \b--header\b or \b--permissions\b was specified in the previous"
+" \bsum\b then the checksum method is automatically determined,"
+" otherwise \b--method\b must be specified. The listed checksum is"
+" compared with the current value and a warning is issued for each file"
+" that does not match. If \afile\a was generated by \b--permissions\b"
+" then the file mode, user and group are also checked. Empty lines,"
+" lines starting with \b#<space>\b, or the line \b#\b are ignored. Lines"
+" containing no blanks are interpreted as [no]]\aname\a[=\avalue\a]]"
+" options:]{"
+" [+method=name?Checksum method to apply to subsequent lines.]"
+" [+permissions?Subsequent lines were generated with"
+" \b--permissions\b.]"
+"}"
+"[h:header?Print the checksum method as the first output line. Used with"
+" \b--check\b and \b--permissions\b.]"
+"[l:list?Each \afile\a is interpreted as a list of files, one per line,"
+" that is checksummed.]"
+"[p:permissions?If \b--check\b is not specified then list the file"
+" mode, user and group between the checksum and path. User and group"
+" matching the caller are output as \b-\b. If \b--check\b is"
+" specified then the mode, user and group for each path in \afile\a"
+" are updated if necessary to match those in \afile\a. A warning is"
+" printed on the standard error for each changed file.]"
+"[R:recursive?Recursively checksum the contents of directories.]"
+"[S:silent|status?No output for \b--check\b; 0 exit status means all sums"
+" matched, non-0 means at least one sum failed to match. Ignored for"
+" \b--permissions\b.]"
+"[t:total?List only the total checksum and block count of all files."
+" \b--all\b \b--total\b lists each checksum and the total. The"
+" total checksum and block count may be different from the checksum"
+" and block count of the catenation of all files due to partial"
+" blocks that may occur when the files are treated separately.]"
+"[T:text?Read files in text mode (i.e., treat \b\\r\\n\b as \b\\n\b).]"
+"[w!:warn?Warn about invalid \b--check\b lines.]"
+"[x:method|algorithm?Specifies the checksum \amethod\a to"
+" apply. Parenthesized method options are readonly implementation"
+" details.]:[method]{\fmethods\f}"
+"[L:logical|follow?Follow symbolic links when traversing directories. The"
+" default is determined by \bgetconf PATH_RESOLVE\b.]"
+"[H:metaphysical?Follow command argument symbolic links, otherwise don't"
+" follow symbolic links when traversing directories. The default is"
+" determined by \bgetconf PATH_RESOLVE\b.]"
+"[P:physical?Don't follow symbolic links when traversing directories. The"
+" default is determined by \bgetconf PATH_RESOLVE\b.]"
+"[r:bsd?Equivalent to \b--method=bsd --scale=512\b for compatibility with"
+" other \bsum\b(1) implementations.]"
+"[s:sysv?Equivalent to \b--method=sys5\b for compatibility with other"
+" \bsum\b(1) implementations.]"
+
+"\n"
+"\n[ file ... ]\n"
+"\n"
+
+"[+SEE ALSO?\bgetconf\b(1), \btw\b(1), \buuencode\b(1)]"
+;
+
+#include <cmd.h>
+#include <sum.h>
+#include <ls.h>
+#include <modex.h>
+#include <fts_fix.h>
+#include <error.h>
+
+typedef struct State_s /* program state */
+{
+ int all; /* list all items */
+ Sfio_t* check; /* check previous output */
+ int flags; /* sumprint() SUM_* flags */
+ gid_t gid; /* caller gid */
+ int header; /* list method on output */
+ int list; /* list file name too */
+ Sum_t* oldsum; /* previous sum method */
+ int permissions; /* include mode,uer,group */
+ int haveperm; /* permissions in the input */
+ int recursive; /* recursively descend dirs */
+ size_t scale; /* scale override */
+ unsigned long size; /* combined size of all files */
+ int silent; /* silent check, 0 exit if ok */
+ int (*sort)(FTSENT* const*, FTSENT* const*);
+ Sum_t* sum; /* sum method */
+ int text; /* \r\n == \n */
+ int total; /* list totals only */
+ uid_t uid; /* caller uid */
+ int warn; /* invalid check line warnings */
+} State_t;
+
+static void verify(State_t*, char*, char*, Sfio_t*);
+
+/*
+ * open path for read mode
+ */
+
+static Sfio_t*
+openfile(const char* path, const char* mode)
+{
+ Sfio_t* sp;
+
+ if (!path || streq(path, "-") || streq(path, "/dev/stdin") || streq(path, "/dev/fd/0"))
+ {
+ sp = sfstdin;
+ sfopen(sp, NiL, mode);
+ }
+ else if (!(sp = sfopen(NiL, path, mode)))
+ error(ERROR_SYSTEM|2, "%s: cannot read", path);
+ return sp;
+}
+
+/*
+ * close an openfile() stream
+ */
+
+static int
+closefile(Sfio_t* sp)
+{
+ return sp == sfstdin ? 0 : sfclose(sp);
+}
+
+/*
+ * compute and print sum on an open file
+ */
+
+static void
+pr(State_t* state, Sfio_t* op, Sfio_t* ip, char* file, int perm, struct stat* st, Sfio_t* check)
+{
+ register char* p;
+ register char* r;
+ register char* e;
+ register int peek;
+ struct stat ss;
+
+ if (check)
+ {
+ state->oldsum = state->sum;
+ while (p = sfgetr(ip, '\n', 1))
+ verify(state, p, file, check);
+ state->sum = state->oldsum;
+ if (state->warn && !sfeof(ip))
+ error(2, "%s: last line incomplete", file);
+ return;
+ }
+ suminit(state->sum);
+ if (state->text)
+ {
+ peek = 0;
+ while (p = sfreserve(ip, SF_UNBOUND, 0))
+ {
+ e = p + sfvalue(ip);
+ if (peek)
+ {
+ peek = 0;
+ if (*p != '\n')
+ sumblock(state->sum, "\r", 1);
+ }
+ while (r = memchr(p, '\r', e - p))
+ {
+ if (++r >= e)
+ {
+ e--;
+ peek = 1;
+ break;
+ }
+ sumblock(state->sum, p, r - p - (*r == '\n'));
+ p = r;
+ }
+ sumblock(state->sum, p, e - p);
+ }
+ if (peek)
+ sumblock(state->sum, "\r", 1);
+ }
+ else
+ while (p = sfreserve(ip, SF_UNBOUND, 0))
+ sumblock(state->sum, p, sfvalue(ip));
+ if (sfvalue(ip))
+ error(ERROR_SYSTEM|2, "%s: read error", file);
+ sumdone(state->sum);
+ if (!state->total || state->all)
+ {
+ sumprint(state->sum, op, state->flags|SUM_SCALE, state->scale);
+ if (perm >= 0)
+ {
+ if (perm)
+ {
+ if (!st && fstat(sffileno(ip), st = &ss))
+ error(ERROR_SYSTEM|2, "%s: cannot stat", file);
+ else
+ sfprintf(sfstdout, " %04o %s %s",
+ modex(st->st_mode & S_IPERM),
+ (st->st_uid != state->uid && ((st->st_mode & S_ISUID) || (st->st_mode & S_IRUSR) && !(st->st_mode & (S_IRGRP|S_IROTH)) || (st->st_mode & S_IXUSR) && !(st->st_mode & (S_IXGRP|S_IXOTH)))) ? fmtuid(st->st_uid) : "-",
+ (st->st_gid != state->gid && ((st->st_mode & S_ISGID) || (st->st_mode & S_IRGRP) && !(st->st_mode & S_IROTH) || (st->st_mode & S_IXGRP) && !(st->st_mode & S_IXOTH))) ? fmtgid(st->st_gid) : "-");
+ }
+ if (ip != sfstdin)
+ sfprintf(op, " %s", file);
+ sfputc(op, '\n');
+ }
+ }
+}
+
+/*
+ * verify previous sum output
+ */
+
+static void
+verify(State_t* state, register char* s, char* check, Sfio_t* rp)
+{
+ register char* t;
+ char* e;
+ char* file;
+ int attr;
+ int mode;
+ int uid;
+ int gid;
+ Sfio_t* sp;
+ struct stat st;
+
+ if (!*s || *s == '#' && (!*(s + 1) || *(s + 1) == ' ' || *(s + 1) == '\t'))
+ return;
+ if (t = strchr(s, ' '))
+ {
+ if ((t - s) > 10 || !(file = strchr(t + 1, ' ')))
+ file = t;
+ *file++ = 0;
+ attr = 0;
+ if ((mode = strtol(file, &e, 8)) && *e == ' ' && (e - file) == 4)
+ {
+ mode = modei(mode);
+ if (t = strchr(++e, ' '))
+ {
+ if (*e == '-' && (t - e) == 1)
+ uid = -1;
+ else
+ {
+ *t = 0;
+ uid = struid(e);
+ *t = ' ';
+ }
+ if (e = strchr(++t, ' '))
+ {
+ if (*t == '-' && (e - t) == 1)
+ gid = -1;
+ else
+ {
+ *e = 0;
+ gid = struid(t);
+ *e = ' ';
+ }
+ file = e + 1;
+ attr = 1;
+ }
+ }
+ }
+ if (sp = openfile(file, "rb"))
+ {
+ pr(state, rp, sp, file, -1, NiL, NiL);
+ if (!(t = sfstruse(rp)))
+ error(ERROR_SYSTEM|3, "out of space");
+ if (!streq(s, t))
+ {
+ if (state->silent)
+ error_info.errors++;
+ else
+ error(2, "%s: checksum changed", file);
+ }
+ else if (attr)
+ {
+ if (fstat(sffileno(sp), &st))
+ {
+ if (state->silent)
+ error_info.errors++;
+ else
+ error(ERROR_SYSTEM|2, "%s: cannot stat", file);
+ }
+ else
+ {
+ if (uid < 0 || uid == st.st_uid)
+ uid = -1;
+ else if (!state->permissions)
+ {
+ if (state->silent)
+ error_info.errors++;
+ else
+ error(2, "%s: uid should be %s", file, fmtuid(uid));
+ }
+ if (gid < 0 || gid == st.st_gid)
+ gid = -1;
+ else if (!state->permissions)
+ {
+ if (state->silent)
+ error_info.errors++;
+ else
+ error(2, "%s: gid should be %s", file, fmtgid(gid));
+ }
+ if (state->permissions && (uid >= 0 || gid >= 0))
+ {
+ if (chown(file, uid, gid) < 0)
+ {
+ if (uid < 0)
+ error(ERROR_SYSTEM|2, "%s: cannot change group to %s", file, fmtgid(gid));
+ else if (gid < 0)
+ error(ERROR_SYSTEM|2, "%s: cannot change user to %s", file, fmtuid(uid));
+ else
+ error(ERROR_SYSTEM|2, "%s: cannot change user to %s and group to %s", file, fmtuid(uid), fmtgid(gid));
+ }
+ else
+ {
+ if (uid < 0)
+ error(1, "%s: changed group to %s", file, fmtgid(gid));
+ else if (gid < 0)
+ error(1, "%s: changed user to %s", file, fmtuid(uid));
+ else
+ error(1, "%s: changed user to %s and group to %s", file, fmtuid(uid), fmtgid(gid));
+ }
+ }
+ if ((st.st_mode & S_IPERM) ^ mode)
+ {
+ if (state->permissions)
+ {
+ if (chmod(file, mode) < 0)
+ error(ERROR_SYSTEM|2, "%s: cannot change mode to %s", file, fmtmode(mode, 0));
+ else
+ error(ERROR_SYSTEM|1, "%s: changed mode to %s", file, fmtmode(mode, 0));
+ }
+ else if (state->silent)
+ error_info.errors++;
+ else
+ error(2, "%s: mode should be %s", file, fmtmode(mode, 0));
+ }
+ }
+ }
+ closefile(sp);
+ }
+ }
+ else if (strneq(s, "method=", 7))
+ {
+ s += 7;
+ if (state->sum != state->oldsum)
+ sumclose(state->sum);
+ if (!(state->sum = sumopen(s)))
+ error(3, "%s: %s: unknown checksum method", check, s);
+ }
+ else if (streq(s, "permissions"))
+ state->haveperm = 1;
+ else
+ error(1, "%s: %s: unknown option", check, s);
+}
+
+/*
+ * sum the list of files in lp
+ */
+
+static void
+list(State_t* state, register Sfio_t* lp)
+{
+ register char* file;
+ register Sfio_t* sp;
+
+ while (file = sfgetr(lp, '\n', 1))
+ if (sp = openfile(file, state->check ? "rt" : "rb"))
+ {
+ pr(state, sfstdout, sp, file, state->permissions, NiL, state->check);
+ closefile(sp);
+ }
+}
+
+/*
+ * order child entries
+ */
+
+static int
+order(FTSENT* const* f1, FTSENT* const* f2)
+{
+ return strcoll((*f1)->fts_name, (*f2)->fts_name);
+}
+
+/*
+ * optget() info discipline function
+ */
+
+static int
+optinfo(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
+{
+ if (streq(s, "methods"))
+ return sumusage(sp);
+ return 0;
+}
+
+int
+b_cksum(int argc, register char** argv, Shbltin_t* context)
+{
+ register int flags;
+ char* file;
+ char* method;
+ Sfio_t* sp;
+ FTS* fts;
+ FTSENT* ent;
+ int logical;
+ Optdisc_t optdisc;
+ State_t state;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
+ memset(&state, 0, sizeof(state));
+ flags = fts_flags() | FTS_TOP | FTS_NOPOSTORDER;
+ state.flags = SUM_SIZE;
+ state.warn = 1;
+ logical = 1;
+ method = 0;
+ optinit(&optdisc, optinfo);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'a':
+ state.all = 1;
+ continue;
+ case 'b':
+ state.text = 0;
+ continue;
+ case 'B':
+ state.scale = opt_info.num;
+ continue;
+ case 'c':
+ if (!(state.check = sfstropen()))
+ error(3, "out of space [check]");
+ continue;
+ case 'h':
+ state.header = 1;
+ continue;
+ case 'l':
+ state.list = 1;
+ continue;
+ case 'p':
+ state.permissions = 1;
+ continue;
+ case 'r':
+ method = "bsd";
+ state.scale = 512;
+ state.flags |= SUM_LEGACY;
+ continue;
+ case 'R':
+ flags &= ~FTS_TOP;
+ state.recursive = 1;
+ state.sort = order;
+ logical = 0;
+ continue;
+ case 's':
+ method = "sys5";
+ continue;
+ case 'S':
+ state.silent = opt_info.num;
+ continue;
+ case 't':
+ state.total = 1;
+ continue;
+ case 'w':
+ state.warn = opt_info.num;
+ continue;
+ case 'x':
+ method = opt_info.arg;
+ continue;
+ case 'H':
+ flags |= FTS_META|FTS_PHYSICAL;
+ logical = 0;
+ continue;
+ case 'L':
+ flags &= ~(FTS_META|FTS_PHYSICAL);
+ logical = 0;
+ continue;
+ case 'P':
+ flags &= ~FTS_META;
+ flags |= FTS_PHYSICAL;
+ logical = 0;
+ continue;
+ case 'T':
+ state.text = 1;
+ continue;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+
+ /*
+ * check the method
+ */
+
+ if (method && !(state.sum = sumopen(method)))
+ error(3, "%s: unknown checksum method", method);
+ if (!state.sum && !(state.sum = sumopen(error_info.id)) && !(state.sum = sumopen(astconf("UNIVERSE", NiL, NiL))))
+ state.sum = sumopen(NiL);
+
+ /*
+ * do it
+ */
+
+ if (logical)
+ {
+ flags &= ~(FTS_META|FTS_PHYSICAL);
+ flags |= FTS_SEEDOTDIR;
+ }
+ if (state.permissions)
+ {
+ state.uid = geteuid();
+ state.gid = getegid();
+ state.silent = 0;
+ }
+ if (!state.check && (state.header || state.permissions))
+ {
+ sfprintf(sfstdout, "method=%s\n", state.sum->name);
+ if (state.permissions)
+ sfprintf(sfstdout, "permissions\n");
+ }
+ if (state.list)
+ {
+ if (*argv)
+ {
+ while (file = *argv++)
+ if (sp = openfile(file, "rt"))
+ {
+ list(&state, sp);
+ closefile(sp);
+ }
+ }
+ else if (sp = openfile(NiL, "rt"))
+ {
+ list(&state, sp);
+ closefile(sp);
+ }
+ }
+ else if (!*argv && !state.recursive)
+ pr(&state, sfstdout, sfstdin, "/dev/stdin", state.permissions, NiL, state.check);
+ else if (!(fts = fts_open(argv, flags, state.sort)))
+ error(ERROR_system(1), "%s: not found", *argv);
+ else
+ {
+ while (!sh_checksig(context) && (ent = fts_read(fts)))
+ switch (ent->fts_info)
+ {
+ case FTS_SL:
+ if (!(flags & FTS_PHYSICAL) || (flags & FTS_META) && ent->fts_level == 1)
+ fts_set(NiL, ent, FTS_FOLLOW);
+ break;
+ case FTS_F:
+ if (sp = openfile(ent->fts_accpath, "rb"))
+ {
+ pr(&state, sfstdout, sp, ent->fts_path, state.permissions, ent->fts_statp, state.check);
+ closefile(sp);
+ }
+ break;
+ case FTS_DC:
+ error(ERROR_warn(0), "%s: directory causes cycle", ent->fts_path);
+ break;
+ case FTS_DNR:
+ error(ERROR_system(0), "%s: cannot read directory", ent->fts_path);
+ break;
+ case FTS_DNX:
+ error(ERROR_system(0), "%s: cannot search directory", ent->fts_path);
+ break;
+ case FTS_NS:
+ error(ERROR_system(0), "%s: not found", ent->fts_path);
+ break;
+ }
+ fts_close(fts);
+ }
+ if (state.total)
+ {
+ sumprint(state.sum, sfstdout, state.flags|SUM_TOTAL|SUM_SCALE, state.scale);
+ sfputc(sfstdout, '\n');
+ }
+ sumclose(state.sum);
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/cmd.h b/src/lib/libcmd/cmd.h
new file mode 100644
index 0000000..2146e74
--- /dev/null
+++ b/src/lib/libcmd/cmd.h
@@ -0,0 +1,163 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * AT&T Research
+ *
+ * builtin cmd definitions
+ */
+
+#ifndef _CMD_H
+#define _CMD_H
+
+#include <ast.h>
+#include <error.h>
+#include <stak.h>
+#include <shcmd.h>
+
+#define cmdinit _cmd_init
+
+#define ERROR_CALLBACK ERROR_SET
+
+#if _BLD_cmd && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#include <cmdext.h>
+
+#undef extern
+
+#if defined(CMD_BUILTIN) && !defined(CMD_STANDALONE)
+#define CMD_STANDALONE CMD_BUILTIN
+#endif
+
+#ifdef CMD_STANDALONE
+
+#define CMD_CONTEXT(c) ((Shbltin_t*)0)
+
+#if CMD_DYNAMIC
+
+#include <dlldefs.h>
+
+#else
+
+extern int CMD_STANDALONE(int, char**, Shbltin_t*);
+
+#endif
+
+#ifndef CMD_BUILTIN
+
+/*
+ * command initialization
+ */
+
+static int
+cmdinit(int argc, register char** argv, Shbltin_t* context, const char* catalog, int flags)
+{
+ register char* cp;
+ register char* pp;
+
+ if (cp = strrchr(argv[0], '/'))
+ cp++;
+ else
+ cp = argv[0];
+ if (pp = strrchr(cp, '_'))
+ cp = pp + 1;
+ error_info.id = cp;
+ if (!error_info.catalog)
+ error_info.catalog = (char*)catalog;
+ opt_info.index = 0;
+ if (context)
+ error_info.flags |= flags & ~(ERROR_CALLBACK|ERROR_NOTIFY);
+ return 0;
+}
+
+#endif
+
+int
+main(int argc, char** argv)
+{
+#if CMD_DYNAMIC
+ register char* s;
+ register char* t;
+ void* dll;
+ Shbltin_f fun;
+ char buf[64];
+
+ if (s = strrchr(argv[0], '/'))
+ s++;
+ else if (!(s = argv[0]))
+ return 127;
+ if ((t = strrchr(s, '_')) && *++t)
+ s = t;
+ buf[0] = '_';
+ buf[1] = 'b';
+ buf[2] = '_';
+ strncpy(buf + 3, s, sizeof(buf) - 4);
+ buf[sizeof(buf) - 1] = 0;
+ if (t = strchr(buf, '.'))
+ *t = 0;
+ for (;;)
+ {
+ if (dll = dlopen(NiL, RTLD_LAZY))
+ {
+ if (fun = (Shbltin_f)dlsym(dll, buf + 1))
+ break;
+ if (fun = (Shbltin_f)dlsym(dll, buf))
+ break;
+ }
+ if (dll = dllplug(NiL, "cmd", NiL, RTLD_LAZY, NiL, 0))
+ {
+ if (fun = (Shbltin_f)dlsym(dll, buf + 1))
+ break;
+ if (fun = (Shbltin_f)dlsym(dll, buf))
+ break;
+ }
+ return 127;
+ }
+ return (*fun)(argc, argv, NiL);
+#else
+ return CMD_STANDALONE(argc, argv, NiL);
+#endif
+}
+
+#else
+
+#undef cmdinit
+#ifdef _MSC_VER
+#define CMD_CONTEXT(p) ((Shbltin_t*)(p))
+#define cmdinit(a,b,c,d,e) do{if(_cmd_init(a,b,c,d,e))return -1;}while(0)
+#else
+#define CMD_CONTEXT(p) (((p)&&((Shbltin_t*)(p))->version>=20071012&&((Shbltin_t*)(p))->version<20350101)?((Shbltin_t*)(p)):0)
+#define cmdinit(a,b,c,d,e) do{if((c)&&!CMD_CONTEXT(c))c=0;if(_cmd_init(a,b,c,d,e))return -1;}while(0)
+#endif
+
+#if _BLD_cmd && defined(__EXPORT__)
+#define extern extern __EXPORT__
+#endif
+
+extern int _cmd_init(int, char**, Shbltin_t*, const char*, int);
+
+#undef extern
+
+#endif
+
+#endif
diff --git a/src/lib/libcmd/cmdinit.c b/src/lib/libcmd/cmdinit.c
new file mode 100644
index 0000000..a25a51e
--- /dev/null
+++ b/src/lib/libcmd/cmdinit.c
@@ -0,0 +1,75 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * command initialization
+ */
+
+#include <cmd.h>
+#include <shcmd.h>
+
+int
+_cmd_init(int argc, char** argv, Shbltin_t* context, const char* catalog, int flags)
+{
+ register char* cp;
+
+ if (argc <= 0)
+ return -1;
+ if (context)
+ {
+ if (flags & ERROR_CALLBACK)
+ {
+ flags &= ~ERROR_CALLBACK;
+ flags |= ERROR_NOTIFY;
+ }
+ else if (flags & ERROR_NOTIFY)
+ {
+ context->notify = 1;
+ flags &= ~ERROR_NOTIFY;
+ }
+ error_info.flags |= flags;
+ }
+ if (cp = strrchr(argv[0], '/'))
+ cp++;
+ else
+ cp = argv[0];
+ error_info.id = cp;
+ if (!error_info.catalog)
+ error_info.catalog = catalog;
+ opt_info.index = 0;
+ return 0;
+}
+
+#if __OBSOLETE__ < 20080101
+
+#if defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#undef cmdinit
+
+extern void
+cmdinit(char** argv, Shbltin_t* context, const char* catalog, int flags)
+{
+ _cmd_init(0, argv, context, catalog, flags);
+}
+
+#endif
diff --git a/src/lib/libcmd/cmp.c b/src/lib/libcmd/cmp.c
new file mode 100644
index 0000000..7433020
--- /dev/null
+++ b/src/lib/libcmd/cmp.c
@@ -0,0 +1,383 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * Glenn Fowler
+ * AT&T Bell Laboratories
+ *
+ * cmp
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: cmp (AT&T Research) 2010-04-11 $\n]"
+USAGE_LICENSE
+"[+NAME?cmp - compare two files]"
+"[+DESCRIPTION?\bcmp\b compares two files \afile1\a and \afile2\a. "
+ "\bcmp\b writes no output if the files are the same. By default, if the "
+ "files differ, the byte and line number at which the first difference "
+ "occurred are written to standard output. Bytes and lines are numbered "
+ "beginning with 1.]"
+"[+?If \askip1\a or \askip2\a are specified, or the \b-i\b option is "
+ "specified, initial bytes of the corresponding file are skipped before "
+ "beginning the compare. The skip values are in bytes or can have a "
+ "suffix of \bk\b for kilobytes or \bm\b for megabytes.]"
+"[+?If either \afile1\a or \afiles2\a is \b-\b, \bcmp\b uses standard "
+ "input starting at the current location.]"
+"[b:print-bytes?Print differing bytes as 3 digit octal values.]"
+"[c:print-chars?Print differing bytes as follows: non-space printable "
+ "characters as themselves; space and control characters as \b^\b "
+ "followed by a letter of the alphabet; and characters with the high bit "
+ "set as the lower 7 bit character prefixed by \bM^\b for 7 bit space and "
+ "non-printable characters and \bM-\b for all other characters. If the 7 "
+ "bit character encoding is not ASCII then the characters are converted "
+ "to ASCII to determine \ahigh bit set\a, and if set it is cleared and "
+ "converted back to the native encoding. Multibyte characters in the "
+ "current locale are treated as printable characters.]"
+"[d:differences?Print at most \adifferences\a differences using "
+ "\b--verbose\b output format. \b--differences=0\b is equivalent to "
+ "\b--silent\b.]#[differences]"
+"[i:ignore-initial|skip?Skip the the first \askip1\a bytes in \afile1\a "
+ "and the first \askip2\a bytes in \afile2\a. If \askip2\a is omitted "
+ "then \askip1\a is used.]:[skip1[::skip2]]:=0::0]"
+"[l:verbose?Write the decimal byte number and the differing bytes (in "
+ "octal) for each difference.]"
+"[n:count|bytes?Compare at most \acount\a bytes.]#[count]"
+"[s:quiet|silent?Write nothing for differing files; return non-zero exit "
+ "status only.]"
+"\n"
+"\nfile1 file2 [skip1 [skip2]]\n"
+"\n"
+"[+EXIT STATUS?]"
+ "{"
+ "[+0?The files or portions compared are identical.]"
+ "[+1?The files are different.]"
+ "[+>1?An error occurred.]"
+ "}"
+"[+SEE ALSO?\bcomm\b(1), \bdiff\b(1), \bcat\b(1)]"
+;
+
+#include <cmd.h>
+#include <ls.h>
+#include <ctype.h>
+#include <ccode.h>
+
+#define CMP_VERBOSE 0x01
+#define CMP_SILENT 0x02
+#define CMP_CHARS 0x04
+#define CMP_BYTES 0x08
+
+static void
+pretty(Sfio_t *out, int o, int delim, int flags)
+{
+ int c;
+ int m;
+ char* s;
+ char buf[10];
+
+ s = buf;
+ if ((flags & CMP_BYTES) || !(flags & CMP_CHARS))
+ {
+ *s++ = ' ';
+ if ((flags & CMP_CHARS) && delim != -1)
+ *s++ = ' ';
+ *s++ = '0' + ((o >> 6) & 07);
+ *s++ = '0' + ((o >> 3) & 07);
+ *s++ = '0' + (o & 07);
+ }
+ if (flags & CMP_CHARS)
+ {
+ *s++ = ' ';
+ c = ccmapc(o, CC_NATIVE, CC_ASCII);
+ if (c & 0x80)
+ {
+ m = 1;
+ *s++ = 'M';
+ c &= 0x7f;
+ o = ccmapc(c, CC_ASCII, CC_NATIVE);
+ }
+ else
+ m = 0;
+ if (isspace(o) || !isprint(o))
+ {
+ if (!m)
+ *s++ = ' ';
+ *s++ = '^';
+ c ^= 0x40;
+ o = ccmapc(c, CC_ASCII, CC_NATIVE);
+ }
+ else if (m)
+ *s++ = '-';
+ else
+ {
+ *s++ = ' ';
+ *s++ = ' ';
+ }
+ *s++ = o;
+ }
+ *s = 0;
+ sfputr(out, buf, delim);
+}
+
+/*
+ * compare two files
+ */
+
+static int
+cmp(const char* file1, Sfio_t* f1, const char* file2, Sfio_t* f2, int flags, Sfoff_t count, Sfoff_t differences)
+{
+ register int c1;
+ register int c2;
+ register unsigned char* p1 = 0;
+ register unsigned char* p2 = 0;
+ register Sfoff_t lines = 1;
+ register unsigned char* e1 = 0;
+ register unsigned char* e2 = 0;
+ Sfoff_t pos = 0;
+ int n1 = 0;
+ int ret = 0;
+ unsigned char* last;
+
+ for (;;)
+ {
+ if ((c1 = e1 - p1) <= 0)
+ {
+ if (count > 0 && !(count -= n1))
+ return ret;
+ if (!(p1 = (unsigned char*)sfreserve(f1, SF_UNBOUND, 0)) || (c1 = sfvalue(f1)) <= 0)
+ {
+ if ((e2 - p2) > 0 || sfreserve(f2, SF_UNBOUND, 0) && sfvalue(f2) > 0)
+ {
+ ret = 1;
+ if (!(flags & CMP_SILENT))
+ error(ERROR_exit(1), "EOF on %s", file1);
+ }
+ return ret;
+ }
+ if (count > 0 && c1 > count)
+ c1 = (int)count;
+ e1 = p1 + c1;
+ n1 = c1;
+ }
+ if ((c2 = e2 - p2) <= 0)
+ {
+ if (!(p2 = (unsigned char*)sfreserve(f2, SF_UNBOUND, 0)) || (c2 = sfvalue(f2)) <= 0)
+ {
+ if (!(flags & CMP_SILENT))
+ error(ERROR_exit(1), "EOF on %s", file2);
+ return 1;
+ }
+ e2 = p2 + c2;
+ }
+ if (c1 > c2)
+ c1 = c2;
+ pos += c1;
+ if (flags & CMP_SILENT)
+ {
+ if (memcmp(p1, p2, c1))
+ return 1;
+ p1 += c1;
+ p2 += c1;
+ }
+ else
+ {
+ last = p1 + c1;
+ while (p1 < last)
+ {
+ if ((c1 = *p1++) != *p2++)
+ {
+ if (differences >= 0)
+ {
+ if (!differences)
+ return 1;
+ differences--;
+ }
+#if 0
+ if (!flags)
+ sfprintf(sfstdout, "%s %s differ: char %I*d, line %I*u\n", file1, file2, sizeof(pos), pos - (last - p1), sizeof(lines), lines);
+ else
+ {
+ sfprintf(sfstdout, "%6I*d", sizeof(pos), pos - (last - p1));
+ pretty(sfstdout, c1, -1, flags);
+ pretty(sfstdout, *(p2-1), '\n', flags);
+ }
+#else
+ if (flags & CMP_VERBOSE)
+ sfprintf(sfstdout, "%6I*d", sizeof(pos), pos - (last - p1));
+ else
+ sfprintf(sfstdout, "%s %s differ: char %I*d, line %I*u", file1, file2, sizeof(pos), pos - (last - p1), sizeof(lines), lines);
+ if (flags & (CMP_BYTES|CMP_CHARS|CMP_VERBOSE))
+ {
+ sfputc(sfstdout, (flags & CMP_VERBOSE) ? ' ' : ',');
+ pretty(sfstdout, c1, -1, flags);
+ pretty(sfstdout, *(p2-1), '\n', flags);
+ }
+ else
+ sfputc(sfstdout, '\n');
+#endif
+ if (!differences || differences < 0 && !(flags & CMP_VERBOSE))
+ return 1;
+ ret = 1;
+ }
+ if (c1 == '\n')
+ lines++;
+ }
+ }
+ }
+}
+
+int
+b_cmp(int argc, register char** argv, Shbltin_t* context)
+{
+ char* s;
+ char* e;
+ char* file1;
+ char* file2;
+ int n;
+ struct stat s1;
+ struct stat s2;
+
+ Sfio_t* f1 = 0;
+ Sfio_t* f2 = 0;
+ Sfoff_t o1 = 0;
+ Sfoff_t o2 = 0;
+ Sfoff_t count = -1;
+ Sfoff_t differences = -1;
+ int flags = 0;
+
+ NoP(argc);
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'b':
+ flags |= CMP_BYTES;
+ continue;
+ case 'c':
+ flags |= CMP_CHARS;
+ continue;
+ case 'd':
+ flags |= CMP_VERBOSE;
+ differences = opt_info.number;
+ continue;
+ case 'i':
+ o1 = strtoll(opt_info.arg, &e, 0);
+ if (*e == ':')
+ o2 = strtoll(e + 1, &e, 0);
+ else
+ o2 = o1;
+ if (*e)
+ {
+ error(2, "%s: skip1:skip2 expected", opt_info.arg);
+ break;
+ }
+ continue;
+ case 'l':
+ flags |= CMP_VERBOSE;
+ continue;
+ case 'n':
+ count = opt_info.number;
+ continue;
+ case 's':
+ flags |= CMP_SILENT;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || !(file1 = *argv++) || !(file2 = *argv++))
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ n = 2;
+ if (streq(file1, "-"))
+ f1 = sfstdin;
+ else if (!(f1 = sfopen(NiL, file1, "r")))
+ {
+ if (!(flags & CMP_SILENT))
+ error(ERROR_system(0), "%s: cannot open", file1);
+ goto done;
+ }
+ if (streq(file2, "-"))
+ f2 = sfstdin;
+ else if (!(f2 = sfopen(NiL, file2, "r")))
+ {
+ if (!(flags & CMP_SILENT))
+ error(ERROR_system(0), "%s: cannot open", file2);
+ goto done;
+ }
+ if (s = *argv++)
+ {
+ o1 = strtoll(s, &e, 0);
+ if (*e)
+ {
+ error(ERROR_exit(0), "%s: %s: invalid skip", file1, s);
+ goto done;
+ }
+ if (s = *argv++)
+ {
+ o2 = strtoll(s, &e, 0);
+ if (*e)
+ {
+ error(ERROR_exit(0), "%s: %s: invalid skip", file2, s);
+ goto done;
+ }
+ }
+ if (*argv)
+ {
+ error(ERROR_usage(0), "%s", optusage(NiL));
+ goto done;
+ }
+ }
+ if (o1 && sfseek(f1, o1, SEEK_SET) != o1)
+ {
+ if (!(flags & CMP_SILENT))
+ error(ERROR_exit(0), "EOF on %s", file1);
+ n = 1;
+ goto done;
+ }
+ if (o2 && sfseek(f2, o2, SEEK_SET) != o2)
+ {
+ if (!(flags & CMP_SILENT))
+ error(ERROR_exit(0), "EOF on %s", file2);
+ n = 1;
+ goto done;
+ }
+ if (fstat(sffileno(f1), &s1))
+ error(ERROR_system(0), "%s: cannot stat", file1);
+ else if (fstat(sffileno(f2), &s2))
+ error(ERROR_system(0), "%s: cannot stat", file1);
+ else if (s1.st_ino == s2.st_ino && s1.st_dev == s2.st_dev && o1 == o2)
+ n = 0;
+ else
+ n = ((flags & CMP_SILENT) && S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode) && (s1.st_size - o1) != (s2.st_size - o2)) ? 1 : cmp(file1, f1, file2, f2, flags, count, differences);
+ done:
+ if (f1 && f1 != sfstdin)
+ sfclose(f1);
+ if (f2 && f2 != sfstdin)
+ sfclose(f2);
+ return n;
+}
diff --git a/src/lib/libcmd/comm.c b/src/lib/libcmd/comm.c
new file mode 100644
index 0000000..8080001
--- /dev/null
+++ b/src/lib/libcmd/comm.c
@@ -0,0 +1,203 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * comm
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: comm (AT&T Research) 1999-04-28 $\n]"
+USAGE_LICENSE
+"[+NAME?comm - select or reject lines common to two files]"
+"[+DESCRIPTION?\bcomm\b reads two files \afile1\a and \afile2\a "
+ "which should be ordered in the collating sequence of the "
+ "current locale, and produces three text columns as output:]{"
+ "[+1?Lines only in \afile1\a.]"
+ "[+2?Lines only in \afile2\a.]"
+ "[+3?Lines in both files.]"
+ "}"
+"[+?If lines in either file are not ordered according to the collating "
+ "sequence of the current locale, the results are not specified.]"
+"[+?If either \afile1\a or \afile2\a is \b-\b, \bcomm\b "
+ "uses standard input starting at the current location.]"
+
+"[1?Suppress the output column of lines unique to \afile1\a.]"
+"[2?Suppress the output column of lines unique to \afile2\a.]"
+"[3?Suppress the output column of lines duplicate in \afile1\a and \afile2\a.]"
+"\n"
+"\nfile1 file2\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Both files processed successfully.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bcmp\b(1), \bdiff\b(1)]"
+;
+
+
+#include <cmd.h>
+
+#define C_FILE1 1
+#define C_FILE2 2
+#define C_COMMON 4
+#define C_ALL (C_FILE1|C_FILE2|C_COMMON)
+
+static int comm(Sfio_t *in1, Sfio_t *in2, register Sfio_t *out,register int mode)
+{
+ register char *cp1, *cp2;
+ register int n1, n2, n, comp;
+ if(cp1 = sfgetr(in1,'\n',0))
+ n1 = sfvalue(in1);
+ if(cp2 = sfgetr(in2,'\n',0))
+ n2 = sfvalue(in2);
+ while(cp1 && cp2)
+ {
+ n=(n1<n2?n1:n2);
+ if((comp=memcmp(cp1,cp2,n-1))==0 && (comp=n1-n2)==0)
+ {
+ if(mode&C_COMMON)
+ {
+ if(mode!=C_COMMON)
+ {
+ sfputc(out,'\t');
+ if(mode==C_ALL)
+ sfputc(out,'\t');
+ }
+ if(sfwrite(out,cp1,n) < 0)
+ return(-1);
+ }
+ if(cp1 = sfgetr(in1,'\n',0))
+ n1 = sfvalue(in1);
+ if(cp2 = sfgetr(in2,'\n',0))
+ n2 = sfvalue(in2);
+ }
+ else if(comp > 0)
+ {
+ if(mode&C_FILE2)
+ {
+ if(mode&C_FILE1)
+ sfputc(out,'\t');
+ if(sfwrite(out,cp2,n2) < 0)
+ return(-1);
+ }
+ if(cp2 = sfgetr(in2,'\n',0))
+ n2 = sfvalue(in2);
+ }
+ else
+ {
+ if((mode&C_FILE1) && sfwrite(out,cp1,n1) < 0)
+ return(-1);
+ if(cp1 = sfgetr(in1,'\n',0))
+ n1 = sfvalue(in1);
+ }
+ }
+ n = 0;
+ if(cp2)
+ {
+ cp1 = cp2;
+ in1 = in2;
+ n1 = n2;
+ if(mode&C_FILE1)
+ n = 1;
+ mode &= C_FILE2;
+ }
+ else
+ mode &= C_FILE1;
+ if(!mode || !cp1)
+ {
+ if(cp1 && in1==sfstdin)
+ sfseek(in1,(Sfoff_t)0,SEEK_END);
+ return(0);
+ }
+ /* process the remaining stream */
+ while(1)
+ {
+ if(n)
+ sfputc(out,'\t');
+ if(sfwrite(out,cp1,n1) < 0)
+ return(-1);
+ if(!(cp1 = sfgetr(in1,'\n',0)))
+ return(0);
+ n1 = sfvalue(in1);
+ }
+ /* NOT REACHED */
+}
+
+int
+b_comm(int argc, char *argv[], Shbltin_t* context)
+{
+ register int mode = C_FILE1|C_FILE2|C_COMMON;
+ register char *cp;
+ Sfio_t *f1, *f2;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case '1':
+ mode &= ~C_FILE1;
+ continue;
+ case '2':
+ mode &= ~C_FILE2;
+ continue;
+ case '3':
+ mode &= ~C_COMMON;
+ continue;
+ case ':':
+ error(2, "%s",opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s",opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if(error_info.errors || argc!=2)
+ error(ERROR_usage(2),"%s",optusage(NiL));
+ cp = *argv++;
+ if(streq(cp,"-"))
+ f1 = sfstdin;
+ else if(!(f1 = sfopen(NiL, cp,"r")))
+ error(ERROR_system(1),"%s: cannot open",cp);
+ cp = *argv;
+ if(streq(cp,"-"))
+ f2 = sfstdin;
+ else if(!(f2 = sfopen(NiL, cp,"r")))
+ error(ERROR_system(1),"%s: cannot open",cp);
+ if(mode)
+ {
+ if(comm(f1,f2,sfstdout,mode) < 0)
+ error(ERROR_system(1)," write error");
+ }
+ else if(f1==sfstdin || f2==sfstdin)
+ sfseek(sfstdin,(Sfoff_t)0,SEEK_END);
+ if(f1!=sfstdin)
+ sfclose(f1);
+ if(f2!=sfstdin)
+ sfclose(f2);
+ return error_info.errors;
+}
diff --git a/src/lib/libcmd/cp.c b/src/lib/libcmd/cp.c
new file mode 100644
index 0000000..3d1eddb
--- /dev/null
+++ b/src/lib/libcmd/cp.c
@@ -0,0 +1,1009 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * cp/ln/mv -- copy/link/move files
+ */
+
+static const char usage_head[] =
+"[-?@(#)$Id: cp (AT&T Research) 2011-05-03 $\n]"
+USAGE_LICENSE
+;
+
+static const char usage_cp[] =
+"[+NAME?cp - copy files]"
+"[+DESCRIPTION?If the last argument names an existing directory, \bcp\b "
+ "copies each \afile\a into a file with the same name in that directory. "
+ "Otherwise, if only two files are given, \bcp\b copies the first onto "
+ "the second. It is an error if the last argument is not a directory and "
+ "more than two files are given. By default directories are not copied.]"
+
+"[a:archive?Preserve as much as possible of the structure and attributes "
+ "of the original files in the copy. Equivalent to \b--physical\b "
+ "\b--preserve\b \b--recursive\b.]"
+"[A:attributes?Preserve selected file attributes:]:[eipt]"
+ "{"
+ "[+e?Everything permissible.]"
+ "[+i?Owner uid and gid.]"
+ "[+p?Permissions.]"
+ "[+t?Access and modify times.]"
+ "}"
+"[p:preserve?Preserve file owner, group, permissions and timestamps.]"
+"[h:hierarchy|parents?Form the name of each destination file by "
+ "appending to the target directory a slash and the specified source file "
+ "name. The last argument must be an existing directory. Missing "
+ "destination directories are created.]"
+"[H:metaphysical?Follow command argument symbolic links, otherwise don't "
+ "follow.]"
+"[l:link?Make hard links to destination files instead of copies.]"
+"[U:remove-destination?Remove existing destination files before copying.]"
+"[L:logical|dereference?Follow symbolic links and copy the files they "
+ "point to.]"
+"[P|d:physical|nodereference?Don't follow symbolic links; copy symbolic "
+ "rather than the files they point to.]"
+;
+
+static const char usage_ln[] =
+"[+NAME?ln - link files]"
+"[+DESCRIPTION?If the last argument names an existing directory, \bln\b "
+ "links each \afile\a into a file with the same name in that directory. "
+ "Otherwise, if only two files are given, \bln\b links the first onto the "
+ "second. It is an error if the last argument is not a directory and more "
+ "than two files are given. By default directories are not linked.]"
+;
+
+static const char usage_mv[] =
+"[+NAME?mv - rename files]"
+"[+DESCRIPTION?If the last argument names an existing directory, \bmv\b "
+ "renames each \afile\a into a file with the same name in that directory. "
+ "Otherwise, if only two files are given, \bmv\b renames the first onto "
+ "the second. It is an error if the last argument is not a directory and "
+ "more than two files are given. If a source and destination file reside "
+ "on different filesystems then \bmv\b copies the file contents to the "
+ "destination and then deletes the source file.]"
+
+"[U:remove-destination?Remove existing destination files before moving.]"
+;
+
+static const char usage_tail[] =
+"[f:force?Replace existing destination files.]"
+"[i:interactive|prompt?Prompt whether to replace existing destination "
+ "files. An affirmative response (\by\b or \bY\b) replaces the file, a "
+ "quit response (\bq\b or \bQ\b) exits immediately, and all other "
+ "responses skip the file.]"
+"[r|R:recursive?Operate on the contents of directories recursively.]"
+"[s:symlink|symbolic-link?Make symbolic links to destination files.]"
+"[u:update?Replace a destination file only if its modification time is "
+ "older than the corresponding source file modification time.]"
+"[v:verbose?Print the name of each file before operating on it.]"
+"[F:fsync|sync?\bfsync\b(2) each file after it is copied.]"
+"[B:backup?Make backups of files that are about to be replaced. "
+ "\b--suffix\b sets the backup suffix. The backup type is determined in "
+ "this order: this option, the \bVERSION_CONTROL\b environment variable, "
+ "or the default value \bexisting\b. \atype\a may be one of:]:?[type]"
+ "{"
+ "[+numbered|t?Always make numbered backups. The numbered backup "
+ "suffix is \b.\aSNS\a, where \aS\a is the \bbackup-suffix\b and "
+ "\aN\a is the version number, starting at 1, incremented with "
+ "each version.]"
+ "[+existing|nil?Make numbered backups of files that already have "
+ "them, otherwise simple backups.]"
+ "[+simple|never?Always make simple backups.]"
+ "[+none|off?Disable backups.]"
+ "}"
+"[S:suffix?A backup file is made by renaming the file to the same name "
+ "with the backup suffix appended. The backup suffix is determined in "
+ "this order: this option, the \bSIMPLE_BACKUP_SUFFIX\b, environment "
+ "variable, or the default value \b~\b.]:[suffix]"
+"[b?\b--backup\b using the type in the \bVERSION_CONTROL\b environment "
+ "variable.]"
+"[x|X:xdev|local|mount|one-file-system?Do not descend into directories "
+ "in different filesystems than their parents.]"
+
+"\n"
+"\nsource destination\n"
+"file ... directory\n"
+"\n"
+
+"[+SEE ALSO?\bpax\b(1), \bfsync\b(2), \brename\b(2), \bunlink\b(2),"
+" \bremove\b(3)]"
+;
+
+#include <cmd.h>
+#include <ls.h>
+#include <times.h>
+#include <fts_fix.h>
+#include <fs3d.h>
+#include <hashkey.h>
+#include <stk.h>
+#include <tmx.h>
+
+#define PATH_CHUNK 256
+
+#define CP 1
+#define LN 2
+#define MV 3
+
+#define PRESERVE_IDS 0x1 /* preserve uid gid */
+#define PRESERVE_PERM 0x2 /* preserve permissions */
+#define PRESERVE_TIME 0x4 /* preserve times */
+
+#define BAK_replace 0 /* no backup -- just replace */
+#define BAK_existing 1 /* number if already else simple*/
+#define BAK_number 2 /* append .suffix number suffix */
+#define BAK_simple 3 /* append suffix */
+
+typedef struct State_s /* program state */
+{
+ Shbltin_t* context; /* builtin context */
+ int backup; /* BAK_* type */
+ int directory; /* destination is directory */
+ int flags; /* FTS_* flags */
+ int force; /* force approval */
+ int fs3d; /* 3d fs enabled */
+ int hierarchy; /* preserve hierarchy */
+ int interactive; /* prompt for approval */
+ int missmode; /* default missing dir mode */
+ int official; /* move to next view */
+ int op; /* {CP,LN,MV} */
+ int perm; /* permissions to preserve */
+ int postsiz; /* state.path post index */
+ int presiz; /* state.path pre index */
+ int preserve; /* preserve { ids perms times } */
+ int recursive; /* subtrees too */
+ int remove; /* remove destination before op */
+ int suflen; /* strlen(state.suffix) */
+ int sync; /* fsync() each file after copy */
+ int uid; /* caller uid */
+ int update; /* replace only if newer */
+ int verbose; /* list each file before op */
+ int wflags; /* open() for write flags */
+
+ int (*link)(const char*, const char*); /* link */
+ int (*stat)(const char*, struct stat*); /* stat */
+
+#define INITSTATE pathsiz /* (re)init state before this */
+ int pathsiz; /* state.path buffer size */
+
+
+ char* path; /* to pathname buffer */
+ char* opname; /* state.op message string */
+ char* suffix; /* backup suffix */
+
+ Sfio_t* tmp; /* tmp string stream */
+
+ char text[PATH_MAX]; /* link text buffer */
+} State_t;
+
+static const char dot[2] = { '.' };
+
+/*
+ * preserve support
+ */
+
+static void
+preserve(State_t* state, const char* path, struct stat* ns, struct stat* os)
+{
+ int n;
+
+ if ((state->preserve & PRESERVE_TIME) && tmxtouch(path, tmxgetatime(os), tmxgetmtime(os), TMX_NOTIME, 0))
+ error(ERROR_SYSTEM|2, "%s: cannot reset access and modify times", path);
+ if (state->preserve & PRESERVE_IDS)
+ {
+ n = ((ns->st_uid != os->st_uid) << 1) | (ns->st_gid != os->st_gid);
+ if (n && chown(state->path, os->st_uid, os->st_gid))
+ switch (n)
+ {
+ case 01:
+ error(ERROR_SYSTEM|2, "%s: cannot reset group to %s", path, fmtgid(os->st_gid));
+ break;
+ case 02:
+ error(ERROR_SYSTEM|2, "%s: cannot reset owner to %s", path, fmtuid(os->st_uid));
+ break;
+ case 03:
+ error(ERROR_SYSTEM|2, "%s: cannot reset owner to %s and group to %s", path, fmtuid(os->st_uid), fmtgid(os->st_gid));
+ break;
+ }
+ }
+}
+
+/*
+ * visit a single file and state.op to the destination
+ */
+
+static int
+visit(State_t* state, register FTSENT* ent)
+{
+ register char* base;
+ register int n;
+ register int len;
+ int rm;
+ int rfd;
+ int wfd;
+ int m;
+ int v;
+ char* s;
+ char* e;
+ char* protection;
+ Sfio_t* ip;
+ Sfio_t* op;
+ FTS* fts;
+ FTSENT* sub;
+ struct stat st;
+
+ if (ent->fts_info == FTS_DC)
+ {
+ error(2, "%s: directory causes cycle", ent->fts_path);
+ fts_set(NiL, ent, FTS_SKIP);
+ return 0;
+ }
+ if (ent->fts_level == 0)
+ {
+ base = ent->fts_name;
+ len = ent->fts_namelen;
+ if (state->hierarchy)
+ state->presiz = -1;
+ else
+ {
+ state->presiz = ent->fts_pathlen;
+ while (*base == '.' && *(base + 1) == '/')
+ for (base += 2; *base == '/'; base++);
+ if (*base == '.' && !*(base + 1))
+ state->presiz--;
+ else if (*base)
+ state->presiz -= base - ent->fts_name;
+ base = ent->fts_name + len;
+ while (base > ent->fts_name && *(base - 1) == '/')
+ base--;
+ while (base > ent->fts_name && *(base - 1) != '/')
+ base--;
+ len -= base - ent->fts_name;
+ if (state->directory)
+ state->presiz -= len + 1;
+ }
+ }
+ else
+ {
+ base = ent->fts_path + state->presiz + 1;
+ len = ent->fts_pathlen - state->presiz - 1;
+ }
+ len++;
+ if (state->directory)
+ {
+ if ((state->postsiz + len) > state->pathsiz && !(state->path = newof(state->path, char, state->pathsiz = roundof(state->postsiz + len, PATH_CHUNK), 0)))
+ error(ERROR_SYSTEM|3, "out of space");
+ if (state->hierarchy && ent->fts_level == 0 && strchr(base, '/'))
+ {
+ s = state->path + state->postsiz;
+ memcpy(s, base, len);
+ while (e = strchr(s, '/'))
+ {
+ *e = 0;
+ if (access(state->path, F_OK))
+ {
+ st.st_mode = state->missmode;
+ if (s = strrchr(s, '/'))
+ {
+ *s = 0;
+ stat(state->path, &st);
+ *s = '/';
+ }
+ if (mkdir(state->path, st.st_mode & S_IPERM))
+ {
+ error(ERROR_SYSTEM|2, "%s: cannot create directory -- %s ignored", state->path, ent->fts_path);
+ fts_set(NiL, ent, FTS_SKIP);
+ return 0;
+ }
+ }
+ *e++ = '/';
+ s = e;
+ }
+ }
+ }
+ switch (ent->fts_info)
+ {
+ case FTS_DP:
+ if (state->preserve && state->op != LN || ent->fts_level > 0 && (ent->fts_statp->st_mode & S_IRWXU) != S_IRWXU)
+ {
+ if (len && ent->fts_level > 0)
+ memcpy(state->path + state->postsiz, base, len);
+ else
+ state->path[state->postsiz] = 0;
+ if (stat(state->path, &st))
+ error(ERROR_SYSTEM|2, "%s: cannot stat", state->path);
+ else
+ {
+ if ((ent->fts_statp->st_mode & S_IPERM) != (st.st_mode & S_IPERM) && chmod(state->path, ent->fts_statp->st_mode & S_IPERM))
+ error(ERROR_SYSTEM|2, "%s: cannot reset directory mode to %s", state->path, fmtmode(st.st_mode & S_IPERM, 0) + 1);
+ if (state->preserve & (PRESERVE_IDS|PRESERVE_TIME))
+ preserve(state, state->path, &st, ent->fts_statp);
+ }
+ }
+ return 0;
+ case FTS_DNR:
+ case FTS_DNX:
+ case FTS_D:
+ if (!state->recursive)
+ {
+ fts_set(NiL, ent, FTS_SKIP);
+ if (state->op == CP)
+ error(1, "%s: directory -- copying as plain file", ent->fts_path);
+ else if (state->link == link && !state->force)
+ {
+ error(2, "%s: cannot link directory", ent->fts_path);
+ return 0;
+ }
+ }
+ else switch (ent->fts_info)
+ {
+ case FTS_DNR:
+ error(2, "%s: cannot read directory", ent->fts_path);
+ return 0;
+ case FTS_DNX:
+ error(2, "%s: cannot search directory", ent->fts_path);
+ fts_set(NiL, ent, FTS_SKIP);
+
+ /*FALLTHROUGH*/
+ case FTS_D:
+ if (state->directory)
+ memcpy(state->path + state->postsiz, base, len);
+ if (!(*state->stat)(state->path, &st))
+ {
+ if (!S_ISDIR(st.st_mode))
+ {
+ error(2, "%s: not a directory -- %s ignored", state->path, ent->fts_path);
+ return 0;
+ }
+ }
+ else if (mkdir(state->path, (ent->fts_statp->st_mode & S_IPERM)|(ent->fts_info == FTS_D ? S_IRWXU : 0)))
+ {
+ error(ERROR_SYSTEM|2, "%s: cannot create directory -- %s ignored", state->path, ent->fts_path);
+ fts_set(NiL, ent, FTS_SKIP);
+ }
+ if (!state->directory)
+ {
+ state->directory = 1;
+ state->path[state->postsiz++] = '/';
+ state->presiz--;
+ }
+ return 0;
+ }
+ break;
+ case FTS_ERR:
+ case FTS_NS:
+ case FTS_SLNONE:
+ if (state->link != pathsetlink)
+ {
+ error(2, "%s: not found", ent->fts_path);
+ return 0;
+ }
+ break;
+#if 0
+ case FTS_SL:
+ if (state->op == CP)
+ {
+ error(2, "%s: cannot copy non-terminal symbolic link", ent->fts_path);
+ return 0;
+ }
+ break;
+#endif
+ }
+ if (state->directory)
+ memcpy(state->path + state->postsiz, base, len);
+ if ((*state->stat)(state->path, &st))
+ st.st_mode = 0;
+ else if (state->update && !S_ISDIR(st.st_mode) && (unsigned long)ent->fts_statp->st_mtime < (unsigned long)st.st_mtime)
+ {
+ fts_set(NiL, ent, FTS_SKIP);
+ return 0;
+ }
+ else if (!state->fs3d || !iview(&st))
+ {
+ /*
+ * target is in top 3d view
+ */
+
+ if (state->op != LN && st.st_dev == ent->fts_statp->st_dev && st.st_ino == ent->fts_statp->st_ino)
+ {
+ if (state->op == MV)
+ {
+ /*
+ * let rename() handle it
+ */
+
+ if (state->verbose)
+ sfputr(sfstdout, state->path, '\n');
+ goto operate;
+ }
+ if (!state->official)
+ error(2, "%s: identical to %s", state->path, ent->fts_path);
+ return 0;
+ }
+ if (S_ISDIR(st.st_mode))
+ {
+ error(2, "%s: cannot %s existing directory", state->path, state->opname);
+ return 0;
+ }
+ if (state->verbose)
+ sfputr(sfstdout, state->path, '\n');
+ rm = state->remove || ent->fts_info == FTS_SL;
+ if (!rm || !state->force)
+ {
+ if (S_ISLNK(st.st_mode) && (n = -1) || (n = open(state->path, O_RDWR|O_BINARY)) >= 0)
+ {
+ if (n >= 0)
+ close(n);
+ if (state->force)
+ /* ok */;
+ else if (state->interactive)
+ {
+ if (astquery(-1, "%s %s? ", state->opname, state->path) < 0 || sh_checksig(state->context))
+ return 0;
+ }
+ else if (state->op == LN)
+ {
+ error(2, "%s: cannot %s existing file", state->path, state->opname);
+ return 0;
+ }
+ }
+ else if (state->force)
+ rm = 1;
+ else
+ {
+ protection =
+#ifdef ETXTBSY
+ errno == ETXTBSY ? "``running program''" :
+#endif
+ st.st_uid != state->uid ? "``not owner''" :
+ fmtmode(st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO), 0) + 1;
+ if (state->interactive)
+ {
+ if (astquery(-1, "override protection %s for %s? ", protection, state->path) < 0 || sh_checksig(state->context))
+ return 0;
+ rm = 1;
+ }
+ else if (!rm)
+ {
+ error(2, "%s: cannot %s %s protection", state->path, state->opname, protection);
+ return 0;
+ }
+ }
+ }
+ switch (state->backup)
+ {
+ case BAK_existing:
+ case BAK_number:
+ v = 0;
+ if (s = strrchr(state->path, '/'))
+ {
+ e = state->path;
+ *s++ = 0;
+ }
+ else
+ {
+ e = (char*)dot;
+ s = state->path;
+ }
+ n = strlen(s);
+ if (fts = fts_open((char**)e, FTS_NOCHDIR|FTS_ONEPATH|FTS_PHYSICAL|FTS_NOPOSTORDER|FTS_NOSTAT|FTS_NOSEEDOTDIR, NiL))
+ {
+ while (sub = fts_read(fts))
+ {
+ if (strneq(s, sub->fts_name, n) && sub->fts_name[n] == '.' && strneq(sub->fts_name + n + 1, state->suffix, state->suflen) && (m = strtol(sub->fts_name + n + state->suflen + 1, &e, 10)) && streq(e, state->suffix) && m > v)
+ v = m;
+ if (sub->fts_level)
+ fts_set(NiL, sub, FTS_SKIP);
+ }
+ fts_close(fts);
+ }
+ if (s != state->path)
+ *--s = '/';
+ if (v || state->backup == BAK_number)
+ {
+ sfprintf(state->tmp, "%s.%s%d%s", state->path, state->suffix, v + 1, state->suffix);
+ goto backup;
+ }
+ /*FALLTHROUGH*/
+ case BAK_simple:
+ sfprintf(state->tmp, "%s%s", state->path, state->suffix);
+ backup:
+ if (!(s = sfstruse(state->tmp)))
+ error(ERROR_SYSTEM|3, "%s: out of space", state->path);
+ if (rename(state->path, s))
+ {
+ error(ERROR_SYSTEM|2, "%s: cannot backup to %s", state->path, s);
+ return 0;
+ }
+ break;
+ default:
+ if (rm && remove(state->path))
+ {
+ error(ERROR_SYSTEM|2, "%s: cannot remove", state->path);
+ return 0;
+ }
+ break;
+ }
+ }
+ operate:
+ switch (state->op)
+ {
+ case MV:
+ for (;;)
+ {
+ if (!rename(ent->fts_path, state->path))
+ return 0;
+ if (errno == ENOENT)
+ rm = 1;
+ else if (!rm && st.st_mode && !remove(state->path))
+ {
+ rm = 1;
+ continue;
+ }
+ if (errno != EXDEV && (rm || S_ISDIR(ent->fts_statp->st_mode)))
+ {
+ error(ERROR_SYSTEM|2, "%s: cannot rename to %s", ent->fts_path, state->path);
+ return 0;
+ }
+ else
+ break;
+ }
+ /*FALLTHROUGH*/
+ case CP:
+ if (S_ISLNK(ent->fts_statp->st_mode))
+ {
+ if ((n = pathgetlink(ent->fts_path, state->text, sizeof(state->text) - 1)) < 0)
+ {
+ error(ERROR_SYSTEM|2, "%s: cannot read symbolic link text", ent->fts_path);
+ return 0;
+ }
+ state->text[n] = 0;
+ if (pathsetlink(state->text, state->path))
+ {
+ error(ERROR_SYSTEM|2, "%s: cannot copy symbolic link to %s", ent->fts_path, state->path);
+ return 0;
+ }
+ }
+ else if (state->op == CP || S_ISREG(ent->fts_statp->st_mode) || S_ISDIR(ent->fts_statp->st_mode))
+ {
+ if (ent->fts_statp->st_size > 0 && (rfd = open(ent->fts_path, O_RDONLY|O_BINARY)) < 0)
+ {
+ error(ERROR_SYSTEM|2, "%s: cannot read", ent->fts_path);
+ return 0;
+ }
+ else if ((wfd = open(state->path, st.st_mode ? (state->wflags & ~O_EXCL) : state->wflags, ent->fts_statp->st_mode & state->perm)) < 0)
+ {
+ error(ERROR_SYSTEM|2, "%s: cannot write", state->path);
+ if (ent->fts_statp->st_size > 0)
+ close(rfd);
+ return 0;
+ }
+ else if (ent->fts_statp->st_size > 0)
+ {
+ if (!(ip = sfnew(NiL, NiL, SF_UNBOUND, rfd, SF_READ)))
+ {
+ error(ERROR_SYSTEM|2, "%s: %s read stream error", ent->fts_path, state->path);
+ close(rfd);
+ close(wfd);
+ return 0;
+ }
+ if (!(op = sfnew(NiL, NiL, SF_UNBOUND, wfd, SF_WRITE)))
+ {
+ error(ERROR_SYSTEM|2, "%s: %s write stream error", ent->fts_path, state->path);
+ close(wfd);
+ sfclose(ip);
+ return 0;
+ }
+ n = 0;
+ if (sfmove(ip, op, (Sfoff_t)SF_UNBOUND, -1) < 0)
+ n |= 3;
+ if (!sfeof(ip))
+ n |= 1;
+ if (sfsync(op) || state->sync && fsync(wfd) || sfclose(op))
+ n |= 2;
+ if (sfclose(ip))
+ n |= 1;
+ if (n)
+ {
+ error(ERROR_SYSTEM|2, "%s: %s %s error", ent->fts_path, state->path, n == 1 ? ERROR_translate(0, 0, 0, "read") : n == 2 ? ERROR_translate(0, 0, 0, "write") : ERROR_translate(0, 0, 0, "io"));
+ return 0;
+ }
+ }
+ else
+ close(wfd);
+ }
+ else if (S_ISBLK(ent->fts_statp->st_mode) || S_ISCHR(ent->fts_statp->st_mode) || S_ISFIFO(ent->fts_statp->st_mode))
+ {
+ if (mknod(state->path, ent->fts_statp->st_mode, idevice(ent->fts_statp)))
+ {
+ error(ERROR_SYSTEM|2, "%s: cannot copy special file to %s", ent->fts_path, state->path);
+ return 0;
+ }
+ }
+ else
+ {
+ error(2, "%s: cannot copy -- unknown file type 0%o", ent->fts_path, S_ITYPE(ent->fts_statp->st_mode));
+ return 0;
+ }
+ if (state->preserve)
+ {
+ if (ent->fts_info != FTS_SL)
+ {
+ if (stat(state->path, &st))
+ error(ERROR_SYSTEM|2, "%s: cannot stat", state->path);
+ else
+ {
+ if ((state->preserve & PRESERVE_PERM) && (ent->fts_statp->st_mode & state->perm) != (st.st_mode & state->perm) && chmod(state->path, ent->fts_statp->st_mode & state->perm))
+ error(ERROR_SYSTEM|2, "%s: cannot reset mode to %s", state->path, fmtmode(st.st_mode & state->perm, 0) + 1);
+ if (state->preserve & (PRESERVE_IDS|PRESERVE_TIME))
+ preserve(state, state->path, &st, ent->fts_statp);
+ }
+ }
+ if (state->op == MV && remove(ent->fts_path))
+ error(ERROR_SYSTEM|1, "%s: cannot remove", ent->fts_path);
+ }
+ break;
+ case LN:
+ if ((*state->link)(ent->fts_path, state->path))
+ error(ERROR_SYSTEM|2, "%s: cannot link to %s", ent->fts_path, state->path);
+ break;
+ }
+ return 0;
+}
+
+int
+b_cp(int argc, register char** argv, Shbltin_t* context)
+{
+ register char* file;
+ register char* s;
+ char** v;
+ char* backup_type;
+ FTS* fts;
+ FTSENT* ent;
+ const char* usage;
+ int path_resolve;
+ int standard;
+ struct stat st;
+ State_t* state;
+ Shbltin_t* sh;
+ Shbltin_t* cleanup = context;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
+ if (!(sh = CMD_CONTEXT(context)) || !(state = (State_t*)sh->ptr))
+ {
+ if (!(state = newof(0, State_t, 1, 0)))
+ error(ERROR_SYSTEM|3, "out of space");
+ if (sh)
+ sh->ptr = state;
+ }
+ else
+ memset(state, 0, offsetof(State_t, INITSTATE));
+ state->context = context;
+ state->presiz = -1;
+ backup_type = 0;
+ state->flags = FTS_NOCHDIR|FTS_NOSEEDOTDIR;
+ state->uid = geteuid();
+ state->wflags = O_WRONLY|O_CREAT|O_TRUNC|O_BINARY;
+ if (!state->tmp && !(state->tmp = sfstropen()))
+ error(ERROR_SYSTEM|3, "out of space [tmp string]");
+ sfputr(state->tmp, usage_head, -1);
+ standard = !!conformance(0, 0);
+ switch (error_info.id[0])
+ {
+ case 'c':
+ case 'C':
+ sfputr(state->tmp, usage_cp, -1);
+ state->op = CP;
+ state->stat = stat;
+ path_resolve = -1;
+ break;
+ case 'l':
+ case 'L':
+ sfputr(state->tmp, usage_ln, -1);
+ state->op = LN;
+ state->flags |= FTS_PHYSICAL;
+ state->link = link;
+ state->remove = 1;
+ state->stat = lstat;
+ path_resolve = 1;
+ break;
+ case 'm':
+ case 'M':
+ sfputr(state->tmp, usage_mv, -1);
+ state->op = MV;
+ state->flags |= FTS_PHYSICAL;
+ state->preserve = PRESERVE_IDS|PRESERVE_PERM|PRESERVE_TIME;
+ state->stat = lstat;
+ path_resolve = 1;
+ break;
+ default:
+ error(3, "not implemented");
+ break;
+ }
+ sfputr(state->tmp, usage_tail, -1);
+ if (!(usage = sfstruse(state->tmp)))
+ error(ERROR_SYSTEM|3, "%s: out of space", state->path);
+ state->opname = state->op == CP ? ERROR_translate(0, 0, 0, "overwrite") : ERROR_translate(0, 0, 0, "replace");
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'a':
+ state->flags |= FTS_PHYSICAL;
+ state->preserve = PRESERVE_IDS|PRESERVE_PERM|PRESERVE_TIME;
+ state->recursive = 1;
+ path_resolve = 1;
+ continue;
+ case 'A':
+ s = opt_info.arg;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ break;
+ case 'e':
+ state->preserve |= PRESERVE_IDS|PRESERVE_PERM|PRESERVE_TIME;
+ continue;
+ case 'i':
+ state->preserve |= PRESERVE_IDS;
+ continue;
+ case 'p':
+ state->preserve |= PRESERVE_PERM;
+ continue;
+ case 't':
+ state->preserve |= PRESERVE_TIME;
+ continue;
+ default:
+ error(1, "%s=%c: unknown attribute flag", opt_info.option, *(s - 1));
+ continue;
+ }
+ break;
+ }
+ continue;
+ case 'b':
+ state->backup = 1;
+ continue;
+ case 'f':
+ state->force = 1;
+ if (state->op != CP || !standard)
+ state->interactive = 0;
+ continue;
+ case 'h':
+ state->hierarchy = 1;
+ continue;
+ case 'i':
+ state->interactive = 1;
+ if (state->op != CP || !standard)
+ state->force = 0;
+ continue;
+ case 'l':
+ state->op = LN;
+ state->link = link;
+ state->stat = lstat;
+ continue;
+ case 'p':
+ state->preserve = PRESERVE_IDS|PRESERVE_PERM|PRESERVE_TIME;
+ continue;
+ case 'r':
+ state->recursive = 1;
+ if (path_resolve < 0)
+ path_resolve = 0;
+ continue;
+ case 's':
+ state->op = LN;
+ state->link = pathsetlink;
+ state->stat = lstat;
+ continue;
+ case 'u':
+ state->update = 1;
+ continue;
+ case 'v':
+ state->verbose = 1;
+ continue;
+ case 'x':
+ state->flags |= FTS_XDEV;
+ continue;
+ case 'B':
+ backup_type = opt_info.arg;
+ state->backup = 1;
+ continue;
+ case 'F':
+#if _lib_fsync
+ state->sync = 1;
+#else
+ error(1, "%s not implemented on this system", opt_info.name);
+#endif
+ continue;
+ case 'H':
+ state->flags |= FTS_META|FTS_PHYSICAL;
+ path_resolve = 1;
+ continue;
+ case 'L':
+ state->flags &= ~FTS_PHYSICAL;
+ path_resolve = 1;
+ continue;
+ case 'P':
+ state->flags &= ~FTS_META;
+ state->flags |= FTS_PHYSICAL;
+ path_resolve = 1;
+ continue;
+ case 'R':
+ state->recursive = 1;
+ state->flags &= ~FTS_META;
+ state->flags |= FTS_PHYSICAL;
+ path_resolve = 1;
+ continue;
+ case 'S':
+ state->suffix = opt_info.arg;
+ continue;
+ case 'U':
+ state->remove = 1;
+ continue;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ argc -= opt_info.index + 1;
+ argv += opt_info.index;
+ if (*argv && streq(*argv, "-") && !streq(*(argv - 1), "--"))
+ {
+ argc--;
+ argv++;
+ }
+ if (!(v = (char**)stkalloc(stkstd, (argc + 2) * sizeof(char*))))
+ error(ERROR_SYSTEM|3, "out of space");
+ memcpy(v, argv, (argc + 1) * sizeof(char*));
+ argv = v;
+ if (!standard)
+ {
+ state->wflags |= O_EXCL;
+ if (!argc)
+ {
+ argc++;
+ argv[1] = (char*)dot;
+ }
+ }
+ if (state->backup)
+ {
+ if (!(file = backup_type) && !(backup_type = getenv("VERSION_CONTROL")))
+ state->backup = 0;
+ else
+ switch (strkey(backup_type))
+ {
+ case HASHKEY6('e','x','i','s','t','i'):
+ case HASHKEY5('e','x','i','s','t'):
+ case HASHKEY4('e','x','i','s'):
+ case HASHKEY3('e','x','i'):
+ case HASHKEY2('e','x'):
+ case HASHKEY1('e'):
+ case HASHKEY3('n','i','l'):
+ case HASHKEY2('n','i'):
+ state->backup = BAK_existing;
+ break;
+ case HASHKEY5('n','e','v','e','r'):
+ case HASHKEY4('n','e','v','e'):
+ case HASHKEY3('n','e','v'):
+ case HASHKEY2('n','e'):
+ case HASHKEY6('s','i','m','p','l','e'):
+ case HASHKEY5('s','i','m','p','l'):
+ case HASHKEY4('s','i','m','p'):
+ case HASHKEY3('s','i','m'):
+ case HASHKEY2('s','i'):
+ case HASHKEY1('s'):
+ state->backup = BAK_simple;
+ break;
+ case HASHKEY4('n','o','n','e'):
+ case HASHKEY3('n','o','n'):
+ case HASHKEY2('n','o'):
+ case HASHKEY3('o','f','f'):
+ case HASHKEY2('o','f'):
+ case HASHKEY1('o'):
+ state->backup = 0;
+ break;
+ case HASHKEY6('n','u','m','b','e','r'):
+ case HASHKEY5('n','u','m','b','e'):
+ case HASHKEY4('n','u','m','b'):
+ case HASHKEY3('n','u','m'):
+ case HASHKEY2('n','u'):
+ case HASHKEY1('t'):
+ state->backup = BAK_number;
+ break;
+ default:
+ if (file)
+ error(2, "%s: unknown backup type", backup_type);
+ break;
+ }
+ if (!state->suffix && !(state->suffix = getenv("SIMPLE_BACKUP_SUFFIX")))
+ state->suffix = "~";
+ state->suflen = strlen(state->suffix);
+ }
+ if (argc <= 0 || error_info.errors)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ if (!path_resolve)
+ state->flags |= fts_flags();
+ file = argv[argc];
+ argv[argc] = 0;
+ if (s = strrchr(file, '/'))
+ {
+ while (*s == '/')
+ s++;
+ if (!(!*s || *s == '.' && (!*++s || *s == '.' && !*++s)))
+ s = 0;
+ }
+ if (file != (char*)dot)
+ pathcanon(file, 0, 0);
+ if (!(state->directory = !stat(file, &st) && S_ISDIR(st.st_mode)) && argc > 1)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ if (s && !state->directory)
+ error(3, "%s: not a directory", file);
+ if ((state->fs3d = fs3d(FS3D_TEST)) && strmatch(file, "...|*/...|.../*"))
+ state->official = 1;
+ state->postsiz = strlen(file);
+ if (state->pathsiz < roundof(state->postsiz + 2, PATH_CHUNK) && !(state->path = newof(state->path, char, state->pathsiz = roundof(state->postsiz + 2, PATH_CHUNK), 0)))
+ error(ERROR_SYSTEM|3, "out of space");
+ memcpy(state->path, file, state->postsiz + 1);
+ if (state->directory && state->path[state->postsiz - 1] != '/')
+ state->path[state->postsiz++] = '/';
+ if (state->hierarchy)
+ {
+ if (!state->directory)
+ error(3, "%s: last argument must be a directory", file);
+ state->missmode = st.st_mode;
+ }
+ state->perm = state->uid ? S_IPERM : (S_IPERM & ~S_ISVTX);
+ if (!state->recursive)
+ state->flags |= FTS_TOP;
+ if (fts = fts_open(argv, state->flags, NiL))
+ {
+ while (!sh_checksig(context) && (ent = fts_read(fts)) && !visit(state, ent));
+ fts_close(fts);
+ }
+ else if (state->link != pathsetlink)
+ switch (state->op)
+ {
+ case CP:
+ error(ERROR_SYSTEM|2, "%s: cannot copy", argv[0]);
+ break;
+ case LN:
+ error(ERROR_SYSTEM|2, "%s: cannot link", argv[0]);
+ break;
+ case MV:
+ error(ERROR_SYSTEM|2, "%s: cannot move", argv[0]);
+ break;
+ }
+ else if ((*state->link)(*argv, state->path))
+ error(ERROR_SYSTEM|2, "%s: cannot link to %s", *argv, state->path);
+ if (cleanup && !sh)
+ {
+ if (state->path)
+ free(state->path);
+ free(state);
+ }
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/cut.c b/src/lib/libcmd/cut.c
new file mode 100644
index 0000000..985b789
--- /dev/null
+++ b/src/lib/libcmd/cut.c
@@ -0,0 +1,702 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * cut fields or columns from fields from a file
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: cut (AT&T Research) 2010-08-11 $\n]"
+USAGE_LICENSE
+"[+NAME?cut - cut out selected columns or fields of each line of a file]"
+"[+DESCRIPTION?\bcut\b bytes, characters, or character-delimited fields "
+ "from one or more files, contatenating them on standard output.]"
+"[+?The option argument \alist\a is a comma-separated or blank-separated "
+ "list of positive numbers and ranges. Ranges can be of three "
+ "forms. The first is two positive integers separated by a hyphen "
+ "(\alow\a\b-\b\ahigh\a), which represents all fields from \alow\a to "
+ "\ahigh\a. The second is a positive number preceded by a hyphen "
+ "(\b-\b\ahigh\a), which represents all fields from field \b1\b to "
+ "\ahigh\a. The last is a positive number followed by a hyphen "
+ "(\alow\a\b-\b), which represents all fields from \alow\a to the "
+ "last field, inclusive. Elements in the \alist\a can be repeated, "
+ "can overlap, and can appear in any order. The order of the "
+ "output is that of the input.]"
+"[+?One and only one of \b-b\b, \b-c\b, or \b-f\b must be specified.]"
+"[+?If no \afile\a is given, or if the \afile\a is \b-\b, \bcut\b "
+ "cuts from standard input. The start of the file is defined "
+ "as the current offset.]"
+"[b:bytes]:[list?\bcut\b based on a list of byte counts.]"
+"[c:characters]:[list?\bcut\b based on a list of character counts.]"
+"[d:delimiter]:[delim?The field character for the \b-f\b option is set "
+ "to \adelim\a. The default is the \btab\b character.]"
+"[f:fields]:[list?\bcut\b based on fields separated by the delimiter "
+ "character specified with the \b-d\b optiion.]"
+"[n!:split?Split multibyte characters selected by the \b-b\b option.]"
+"[R|r:reclen]#[reclen?If \areclen\a > 0, the input will be read as fixed length "
+ "records of length \areclen\a when used with the \b-b\b or \b-c\b "
+ "option.]"
+"[s:suppress|only-delimited?Suppress lines with no delimiter characters, "
+ "when used with the \b-f\b option. By default, lines with no "
+ "delimiters will be passsed in untouched.]"
+"[D:line-delimeter|output-delimiter]:[ldelim?The line delimiter character for "
+ "the \b-f\b option is set to \aldelim\a. The default is the "
+ "\bnewline\b character.]"
+"[N!:newline?Output new-lines at end of each record when used "
+ "with the \b-b\b or \b-c\b option.]"
+"\n"
+"\n[file ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All files processed successfully.]"
+ "[+>0?One or more files failed to open or could not be read.]"
+"}"
+"[+SEE ALSO?\bpaste\b(1), \bgrep\b(1)]"
+;
+
+#include <cmd.h>
+#include <ctype.h>
+
+typedef struct Delim_s
+{
+ char* str;
+ int len;
+ int chr;
+} Delim_t;
+
+typedef struct Cut_s
+{
+ int mb;
+ int eob;
+ int cflag;
+ int nosplit;
+ int sflag;
+ int nlflag;
+ int reclen;
+ Delim_t wdelim;
+ Delim_t ldelim;
+ unsigned char space[UCHAR_MAX+1];
+ int list[2]; /* NOTE: must be last member */
+} Cut_t;
+
+#define HUGE INT_MAX
+#define BLOCK 8*1024
+#define C_BYTES 1
+#define C_CHARS 2
+#define C_FIELDS 4
+#define C_SUPRESS 8
+#define C_NOSPLIT 16
+#define C_NONEWLINE 32
+
+#define SP_LINE 1
+#define SP_WORD 2
+#define SP_WIDE 3
+
+/*
+ * compare the first of an array of integers
+ */
+
+static int
+mycomp(register const void* a, register const void* b)
+{
+ if (*((int*)a) < *((int*)b))
+ return -1;
+ if (*((int*)a) > *((int*)b))
+ return 1;
+ return 0;
+}
+
+static Cut_t*
+cutinit(int mode, char* str, Delim_t* wdelim, Delim_t* ldelim, size_t reclen)
+{
+ register int* lp;
+ register int c;
+ register int n = 0;
+ register int range = 0;
+ register char* cp = str;
+ Cut_t* cut;
+
+ if (!(cut = (Cut_t*)stakalloc(sizeof(Cut_t) + strlen(cp) * sizeof(int))))
+ error(ERROR_exit(1), "out of space");
+ if (cut->mb = mbwide())
+ {
+ memset(cut->space, 0, sizeof(cut->space) / 2);
+ memset(cut->space + sizeof(cut->space) / 2, SP_WIDE, sizeof(cut->space) / 2);
+ }
+ else
+ memset(cut->space, 0, sizeof(cut->space));
+ cut->wdelim = *wdelim;
+ if (wdelim->len == 1)
+ cut->space[wdelim->chr] = SP_WORD;
+ cut->ldelim = *ldelim;
+ cut->eob = (ldelim->len == 1) ? ldelim->chr : 0;
+ cut->space[cut->eob] = SP_LINE;
+ cut->cflag = (mode&C_CHARS) && cut->mb;
+ cut->nosplit = (mode&(C_BYTES|C_NOSPLIT)) == (C_BYTES|C_NOSPLIT) && cut->mb;
+ cut->sflag = (mode&C_SUPRESS) != 0;
+ cut->nlflag = (mode&C_NONEWLINE) != 0;
+ cut->reclen = reclen;
+ lp = cut->list;
+ for (;;)
+ switch(c = *cp++)
+ {
+ case ' ':
+ case '\t':
+ while(*cp==' ' || *cp=='\t')
+ cp++;
+ /*FALLTHROUGH*/
+ case 0:
+ case ',':
+ if(range)
+ {
+ --range;
+ if((n = (n ? (n-range) : (HUGE-1))) < 0)
+ error(ERROR_exit(1),"invalid range for c/f option");
+ *lp++ = range;
+ *lp++ = n;
+ }
+ else
+ {
+ *lp++ = --n;
+ *lp++ = 1;
+ }
+ if(c==0)
+ {
+ register int *dp;
+ *lp = HUGE;
+ n = 1 + (lp-cut->list)/2;
+ qsort(lp=cut->list,n,2*sizeof(*lp),mycomp);
+ /* eliminate overlapping regions */
+ for(n=0,range= -2,dp=lp; *lp!=HUGE; lp+=2)
+ {
+ if(lp[0] <= range)
+ {
+ if(lp[1]==HUGE)
+ {
+ dp[-1] = HUGE;
+ break;
+ }
+ if((c = lp[0]+lp[1]-range)>0)
+ {
+ range += c;
+ dp[-1] += c;
+ }
+ }
+ else
+ {
+ range = *dp++ = lp[0];
+ if(lp[1]==HUGE)
+ {
+ *dp++ = HUGE;
+ break;
+ }
+ range += (*dp++ = lp[1]);
+ }
+ }
+ *dp = HUGE;
+ lp = cut->list;
+ /* convert ranges into gaps */
+ for(n=0; *lp!=HUGE; lp+=2)
+ {
+ c = *lp;
+ *lp -= n;
+ n = c+lp[1];
+ }
+ return cut;
+ }
+ n = range = 0;
+ break;
+
+ case '-':
+ if(range)
+ error(ERROR_exit(1),"bad list for c/f option");
+ range = n?n:1;
+ n = 0;
+ break;
+
+ default:
+ if(!isdigit(c))
+ error(ERROR_exit(1),"bad list for c/f option");
+ n = 10*n + (c-'0');
+ break;
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * cut each line of file <fdin> and put results to <fdout> using list <list>
+ */
+
+static void
+cutcols(Cut_t* cut, Sfio_t* fdin, Sfio_t* fdout)
+{
+ register int c;
+ register int len;
+ register int ncol = 0;
+ register const int* lp = cut->list;
+ register char* bp;
+ register int skip; /* non-zero for don't copy */
+ int must;
+ char* ep;
+ const char* xx;
+
+ for (;;)
+ {
+ if (len = cut->reclen)
+ bp = sfreserve(fdin, len, -1);
+ else
+ bp = sfgetr(fdin, '\n', 0);
+ if (!bp && !(bp = sfgetr(fdin, 0, SF_LASTR)))
+ break;
+ len = sfvalue(fdin);
+ ep = bp + len;
+ xx = 0;
+ if (!(ncol = skip = *(lp = cut->list)))
+ ncol = *++lp;
+ must = 1;
+ do
+ {
+ if (cut->nosplit)
+ {
+ register const char* s = bp;
+ register int w = len < ncol ? len : ncol;
+ register int z;
+
+ while (w > 0)
+ {
+ if (!(*s & 0x80))
+ z = 1;
+ else if ((z = mbnsize(s, w)) <= 0)
+ {
+ if (s == bp && xx)
+ {
+ w += s - xx;
+ bp = (char*)(s = xx);
+ xx = 0;
+ continue;
+ }
+ xx = s;
+ if (skip)
+ s += w;
+ w = 0;
+ break;
+ }
+ s += z;
+ w -= z;
+ }
+ c = s - bp;
+ ncol = !w && ncol >= len;
+ }
+ else if (cut->cflag)
+ {
+ register const char* s = bp;
+ register int w = len;
+ register int z;
+
+ while (w > 0 && ncol > 0)
+ {
+ ncol--;
+ if (!(*s & 0x80) || (z = mbnsize(s, w)) <= 0)
+ z = 1;
+ s += z;
+ w -= z;
+
+ }
+ c = s - bp;
+ ncol = !w && (ncol || !skip);
+ }
+ else
+ {
+ if ((c = ncol) > len)
+ c = len;
+ else if (c == len && !skip)
+ ncol++;
+ ncol -= c;
+ }
+ if (!skip && c)
+ {
+ if (sfwrite(fdout, (char*)bp, c) < 0)
+ return;
+ must = 0;
+ }
+ bp += c;
+ if (ncol)
+ break;
+ len -= c;
+ ncol = *++lp;
+ skip = !skip;
+ } while (ncol != HUGE);
+ if (!cut->nlflag && (skip || must || cut->reclen))
+ {
+ if (cut->ldelim.len > 1)
+ sfwrite(fdout, cut->ldelim.str, cut->ldelim.len);
+ else
+ sfputc(fdout, cut->ldelim.chr);
+ }
+ }
+}
+
+/*
+ * cut each line of file <fdin> and put results to <fdout> using list <list>
+ * stream <fdin> must be line buffered
+ */
+
+static void
+cutfields(Cut_t* cut, Sfio_t* fdin, Sfio_t* fdout)
+{
+ register unsigned char *sp = cut->space;
+ register unsigned char *cp;
+ register unsigned char *wp;
+ register int c, nfields;
+ register const int *lp = cut->list;
+ register unsigned char *copy;
+ register int nodelim, empty, inword=0;
+ register unsigned char *ep;
+ unsigned char *bp, *first;
+ int lastchar;
+ wchar_t w;
+ Sfio_t *fdtmp = 0;
+ long offset = 0;
+ unsigned char mb[8];
+ /* process each buffer */
+ while ((bp = (unsigned char*)sfreserve(fdin, SF_UNBOUND, -1)) && (c = sfvalue(fdin)) > 0)
+ {
+ cp = bp;
+ ep = cp + --c;
+ if((lastchar = cp[c]) != cut->eob)
+ *ep = cut->eob;
+ /* process each line in the buffer */
+ while (cp <= ep)
+ {
+ first = cp;
+ if (!inword)
+ {
+ nodelim = empty = 1;
+ copy = cp;
+ if (nfields = *(lp = cut->list))
+ copy = 0;
+ else
+ nfields = *++lp;
+ }
+ else if (copy)
+ copy = cp;
+ inword = 0;
+ do
+ {
+ /* skip over non-delimiter characters */
+ if (cut->mb)
+ for (;;)
+ {
+ switch (c = sp[*(unsigned char*)cp++])
+ {
+ case 0:
+ continue;
+ case SP_WIDE:
+ wp = --cp;
+ while ((c = mb2wc(w, cp, ep - cp)) <= 0)
+ {
+ /* mb char possibly spanning buffer boundary -- fun stuff */
+ if ((ep - cp) < mbmax())
+ {
+ int i;
+ int j;
+ int k;
+
+ if (lastchar != cut->eob)
+ {
+ *ep = lastchar;
+ if ((c = mb2wc(w, cp, ep - cp)) > 0)
+ break;
+ }
+ if (copy)
+ {
+ empty = 0;
+ if ((c = cp - copy) > 0 && sfwrite(fdout, (char*)copy, c) < 0)
+ goto failed;
+ }
+ for (i = 0; i <= (ep - cp); i++)
+ mb[i] = cp[i];
+ if (!(bp = (unsigned char*)sfreserve(fdin, SF_UNBOUND, -1)) || (c = sfvalue(fdin)) <= 0)
+ goto failed;
+ cp = bp;
+ ep = cp + --c;
+ if ((lastchar = cp[c]) != cut->eob)
+ *ep = cut->eob;
+ j = i;
+ k = 0;
+ while (j < mbmax())
+ mb[j++] = cp[k++];
+ if ((c = mb2wc(w, (char*)mb, j)) <= 0)
+ {
+ c = i;
+ w = 0;
+ }
+ first = bp = cp += c - i;
+ if (copy)
+ {
+ copy = bp;
+ if (w == cut->ldelim.chr)
+ lastchar = cut->ldelim.chr;
+ else if (w != cut->wdelim.chr)
+ {
+ empty = 0;
+ if (sfwrite(fdout, (char*)mb, c) < 0)
+ goto failed;
+ }
+ }
+ c = 0;
+ }
+ else
+ {
+ w = *cp;
+ c = 1;
+ }
+ break;
+ }
+ cp += c;
+ c = w;
+ if (c == cut->wdelim.chr)
+ {
+ c = SP_WORD;
+ break;
+ }
+ if (c == cut->ldelim.chr)
+ {
+ c = SP_LINE;
+ break;
+ }
+ continue;
+ default:
+ wp = cp - 1;
+ break;
+ }
+ break;
+ }
+ else
+ {
+ while (!(c = sp[*cp++]));
+ wp = cp - 1;
+ }
+ /* check for end-of-line */
+ if (c == SP_LINE)
+ {
+ if (cp <= ep)
+ break;
+ if (lastchar == cut->ldelim.chr)
+ break;
+ /* restore cut->last character */
+ if (lastchar != cut->eob)
+ *ep = lastchar;
+ inword++;
+ if (!sp[lastchar])
+ break;
+ }
+ nodelim = 0;
+ if (--nfields > 0)
+ continue;
+ nfields = *++lp;
+ if (copy)
+ {
+ empty = 0;
+ if ((c = wp - copy) > 0 && sfwrite(fdout, (char*)copy, c) < 0)
+ goto failed;
+ copy = 0;
+ }
+ else
+ /* set to delimiter unless the first field */
+ copy = empty ? cp : wp;
+ } while (!inword);
+ if (!inword)
+ {
+ if (!copy)
+ {
+ if (nodelim)
+ {
+ if (!cut->sflag)
+ {
+ if (offset)
+ {
+ sfseek(fdtmp,(Sfoff_t)0,SEEK_SET);
+ sfmove(fdtmp,fdout,offset,-1);
+ }
+ copy = first;
+ }
+ }
+ else
+ sfputc(fdout,'\n');
+ }
+ if (offset)
+ sfseek(fdtmp,offset=0,SEEK_SET);
+ }
+ if (copy && (c=cp-copy)>0 && (!nodelim || !cut->sflag) && sfwrite(fdout,(char*)copy,c)< 0)
+ goto failed;
+ }
+ /* see whether to save in tmp file */
+ if(inword && nodelim && !cut->sflag && (c=cp-first)>0)
+ {
+ /* copy line to tmpfile in case no fields */
+ if(!fdtmp)
+ fdtmp = sftmp(BLOCK);
+ sfwrite(fdtmp,(char*)first,c);
+ offset +=c;
+ }
+ }
+ failed:
+ if(fdtmp)
+ sfclose(fdtmp);
+}
+
+int
+b_cut(int argc, char** argv, Shbltin_t* context)
+{
+ register char* cp = 0;
+ register Sfio_t* fp;
+ char* s;
+ int n;
+ Cut_t* cut;
+ int mode = 0;
+ Delim_t wdelim;
+ Delim_t ldelim;
+ size_t reclen = 0;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ wdelim.chr = '\t';
+ ldelim.chr = '\n';
+ wdelim.len = ldelim.len = 1;
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 0:
+ break;
+ case 'b':
+ case 'c':
+ if(mode&C_FIELDS)
+ {
+ error(2, "f option already specified");
+ continue;
+ }
+ cp = opt_info.arg;
+ if(opt_info.option[1]=='b')
+ mode |= C_BYTES;
+ else
+ mode |= C_CHARS;
+ continue;
+ case 'D':
+ ldelim.str = opt_info.arg;
+ if (mbwide())
+ {
+ s = opt_info.arg;
+ ldelim.chr = mbchar(s);
+ if ((n = s - opt_info.arg) > 1)
+ {
+ ldelim.len = n;
+ continue;
+ }
+ }
+ ldelim.chr = *(unsigned char*)opt_info.arg;
+ ldelim.len = 1;
+ continue;
+ case 'd':
+ wdelim.str = opt_info.arg;
+ if (mbwide())
+ {
+ s = opt_info.arg;
+ wdelim.chr = mbchar(s);
+ if ((n = s - opt_info.arg) > 1)
+ {
+ wdelim.len = n;
+ continue;
+ }
+ }
+ wdelim.chr = *(unsigned char*)opt_info.arg;
+ wdelim.len = 1;
+ continue;
+ case 'f':
+ if(mode&(C_CHARS|C_BYTES))
+ {
+ error(2, "c option already specified");
+ continue;
+ }
+ cp = opt_info.arg;
+ mode |= C_FIELDS;
+ continue;
+ case 'n':
+ mode |= C_NOSPLIT;
+ continue;
+ case 'N':
+ mode |= C_NONEWLINE;
+ continue;
+ case 'R':
+ case 'r':
+ if(opt_info.num>0)
+ reclen = opt_info.num;
+ continue;
+ case 's':
+ mode |= C_SUPRESS;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors)
+ error(ERROR_usage(2), "%s",optusage(NiL));
+ if(!cp)
+ {
+ error(2, "b, c or f option must be specified");
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ }
+ if(!*cp)
+ error(3, "non-empty b, c or f option must be specified");
+ if((mode & (C_FIELDS|C_SUPRESS)) == C_SUPRESS)
+ error(3, "s option requires f option");
+ cut = cutinit(mode, cp, &wdelim, &ldelim, reclen);
+ if(cp = *argv)
+ argv++;
+ do
+ {
+ if(!cp || streq(cp,"-"))
+ fp = sfstdin;
+ else if(!(fp = sfopen(NiL,cp,"r")))
+ {
+ error(ERROR_system(0),"%s: cannot open",cp);
+ continue;
+ }
+ if(mode&C_FIELDS)
+ cutfields(cut,fp,sfstdout);
+ else
+ cutcols(cut,fp,sfstdout);
+ if(fp!=sfstdin)
+ sfclose(fp);
+ } while(cp = *argv++);
+ if (sfsync(sfstdout))
+ error(ERROR_system(0), "write error");
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/date.c b/src/lib/libcmd/date.c
new file mode 100644
index 0000000..3f9a303
--- /dev/null
+++ b/src/lib/libcmd/date.c
@@ -0,0 +1,515 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * date -- set/display date
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: date (AT&T Research) 2011-01-27 $\n]"
+USAGE_LICENSE
+"[+NAME?date - set/list/convert dates]"
+"[+DESCRIPTION?\bdate\b sets the current date and time (with appropriate"
+" privilege), lists the current date or file dates, or converts"
+" dates.]"
+"[+?Most common \adate\a forms are recognized, including those for"
+" \bcrontab\b(1), \bls\b(1), \btouch\b(1), and the default"
+" output from \bdate\b itself.]"
+"[+?If the \adate\a operand consists of 4, 6, 8, 10 or 12 digits followed"
+" by an optional \b.\b and two digits then it is interpreted as:"
+" \aHHMM.SS\a, \addHHMM.SS\a, \ammddHHMM.SS\a, \ammddHHMMyy.SS\a or"
+" \ayymmddHHMM.SS\a, or \ammddHHMMccyy.SS\a or \accyymmddHHMM.SS\a."
+" Conflicting standards and practice allow a leading or trailing"
+" 2 or 4 digit year for the 10 and 12 digit forms; the X/Open trailing"
+" form is used to disambiguate (\btouch\b(1) uses the leading form.)"
+" Avoid the 10 digit form to avoid confusion. The digit fields are:]{"
+" [+cc?Century - 1, 19-20.]"
+" [+yy?Year in century, 00-99.]"
+" [+mm?Month, 01-12.]"
+" [+dd?Day of month, 01-31.]"
+" [+HH?Hour, 00-23.]"
+" [+MM?Minute, 00-59.]"
+" [+SS?Seconds, 00-60.]"
+"}"
+"[+?If more than one \adate\a operand is specified then:]{"
+" [+1.?Each operand sets the reference date for the next"
+" operand.]"
+" [+2.?The date is listed for each operand.]"
+" [+3.?The system date is not set.]"
+"}"
+
+"[a:access-time|atime?List file argument access times.]"
+"[c:change-time|ctime?List file argument change times.]"
+"[d:date?Use \adate\a as the current date and do not set the system"
+" clock.]:[date]"
+"[e:epoch?Output the date in seconds since the epoch."
+" Equivalent to \b--format=%s\b.]"
+"[E:elapsed?Interpret pairs of arguments as start and stop dates, sum the"
+" differences between all pairs, and list the result as a"
+" \bfmtelapsed\b(3) elapsed time on the standard output. If there are"
+" an odd number of arguments then the last time argument is differenced"
+" with the current time.]"
+"[f:format?Output the date according to the \bstrftime\b(3) \aformat\a."
+" For backwards compatibility, a first argument of the form"
+" \b+\b\aformat\a is equivalent to \b-f\b format."
+" \aformat\a is in \bprintf\b(3) style, where %\afield\a names"
+" a fixed size field, zero padded if necessary,"
+" and \\\ac\a and \\\annn\a sequences are as in C. Invalid"
+" %\afield\a specifications and all other characters are copied"
+" without change. \afield\a may be preceded by \b%-\b to turn off"
+" padding or \b%_\b to pad with space, otherwise numeric fields"
+" are padded with \b0\b and string fields are padded with space."
+" \afield\a may also be preceded by \bE\b for alternate era"
+" representation or \bO\b for alternate digit representation (if"
+" supported by the current locale.) Finally, an integral \awidth\a"
+" preceding \afield\a truncates the field to \awidth\a characters."
+" The fields are:]:[format]{"
+" [+%?% character]"
+" [+a?abbreviated weekday name]"
+" [+A?full weekday name]"
+" [+b?abbreviated month name]"
+" [+B?full month name]"
+" [+c?\bctime\b(3) style date without the trailing newline]"
+" [+C?2-digit century]"
+" [+d?day of month number]"
+" [+D?date as \amm/dd/yy\a]"
+" [+e?blank padded day of month number]"
+" [+f?locale default override date format]"
+" [+F?%ISO 8601:2000 standard date format; equivalent to Y-%m-%d]"
+" [+g?\bls\b(1) \b-l\b recent date with \ahh:mm\a]"
+" [+G?\bls\b(1) \b-l\b distant date with \ayyyy\a]"
+" [+h?abbreviated month name]"
+" [+H?24-hour clock hour]"
+" [+i?international \bdate\b(1) date with time zone type name]"
+" [+I?12-hour clock hour]"
+" [+j?1-offset Julian date]"
+" [+J?0-offset Julian date]"
+" [+k?\bdate\b(1) style date]"
+" [+K?all numeric date; equivalent to \b%Y-%m-%d+%H:%M:%S\b; \b%_[EO]]K\b for space separator, %OK adds \b.%N\b, \b%EK\b adds \b%.N%z\b, \b%_EK\b adds \b.%N %z\b]"
+" [+l?\bls\b(1) \b-l\b date; equivalent to \b%Q/%g/%G/\b]"
+" [+L?locale default date format]"
+" [+m?month number]"
+" [+M?minutes]"
+" [+n?newline character]"
+" [+N?nanoseconds 000000000-999999999]"
+" [+p?meridian (e.g., \bAM\b or \bPM\b)]"
+" [+q?time zone type name (nation code)]"
+" [+Q?\a<del>recent<del>distant<del>\a: \a<del>\a is a unique"
+" delimter character; \arecent\a format for recent"
+" dates, \adistant\a format otherwise]"
+" [+r?12-hour time as \ahh:mm:ss meridian\a]"
+" [+R?24-hour time as \ahh:mm\a]"
+" [+s?number of seconds since the epoch; \a.prec\a preceding"
+" \bs\b appends \aprec\a nanosecond digits, \b9\b if"
+" \aprec\a is omitted]"
+" [+S?seconds 00-60]"
+" [+t?tab character]"
+" [+T?24-hour time as \ahh:mm:ss\a]"
+" [+u?weekday number 1(Monday)-7]"
+" [+U?week number with Sunday as the first day]"
+" [+V?ISO week number (i18n is \afun\a)]"
+" [+w?weekday number 0(Sunday)-6]"
+" [+W?week number with Monday as the first day]"
+" [+x?locale date style that includes month, day and year]"
+" [+X?locale time style that includes hours and minutes]"
+" [+y?2-digit year (you'll be sorry)]"
+" [+Y?4-digit year]"
+" [+z?time zone \aSHHMM\a west of GMT offset where S is"
+" \b+\b or \b-\b, use pad _ for \aSHH:MM\a]"
+" [+Z?time zone name]"
+" [+=[=]][-+]]flag?set (default or +) or clear (-) \aflag\a"
+" for the remainder of \aformat\a, or for the remainder"
+" of the process if \b==\b is specified. \aflag\a may be:]{"
+" [+l?enable leap second adjustments]"
+" [+n?convert \b%S\b as \b%S.%N\b]"
+" [+u?UTC time zone]"
+" }"
+" [+#?equivalent to %s]"
+" [+??alternate?use \aalternate\a format if a default format"
+" override has not been specified, e.g., \bls\b(1) uses"
+" \"%?%l\"; export TM_OPTIONS=\"format='\aoverride\a'\""
+" to override the default]"
+"}"
+"[i:incremental|adjust?Set the system time in incrementatl adjustments to"
+" avoid complete time shift shock. Negative adjustments still maintain"
+" monotonic increasing time. Not available on all systems.]"
+"[L:last?List only the last time for multiple \adate\a operands.]"
+"[l:leap-seconds?Include leap seconds in time calculations. Leap seconds"
+" after the ast library release date are not accounted for.]"
+"[m:modify-time|mtime?List file argument modify times.]"
+"[n!:network?Set network time.]"
+"[p:parse?Add \aformat\a to the list of \bstrptime\b(3) parse conversion"
+" formats. \aformat\a follows the same conventions as the"
+" \b--format\b option, with the addition of these format"
+" fields:]:[format]{"
+" [+|?If the format failed before this point then restart"
+" the parse with the remaining format.]"
+" [+&?Call the \btmdate\b(3) heuristic parser. This is"
+" is the default when \b--parse\b is omitted.]"
+"}"
+"[R:rfc-2822?List date and time in RFC 2822 format "
+ "(%a, %-e %h %Y %H:%M:%S %z).]"
+"[T:rfc-3339?List date and time in RFC 3339 format according to "
+ "\atype\a:]:[type]"
+ "{"
+ "[d:date?(%Y-%m-%d)]"
+ "[s:seconds?(%Y-%m-%d %H:%M:%S%_z)]"
+ "[n:ns|nanoseconds?(%Y-%m-%d %H:%M:%S.%N%_z)]"
+ "}"
+"[s:show?Show the date without setting the system time.]"
+"[u:utc|gmt|zulu|universal?Output dates in \acoordinated universal time\a (UTC).]"
+"[U:unelapsed?Interpret each argument as \bfmtelapsed\b(3) elapsed"
+" time and list the \bstrelapsed\b(3) 1/\ascale\a seconds.]#[scale]"
+"[z:list-zones?List the known time zone table and exit. The table columns"
+" are: country code, standard zone name, savings time zone name,"
+" minutes west of \bUTC\b, and savings time minutes offset. Blank"
+" or empty entries are listed as \b-\b.]"
+
+"\n"
+"\n[ +format | date ... | file ... ]\n"
+"\n"
+
+"[+SEE ALSO?\bcrontab\b(1), \bls\b(1), \btouch\b(1), \bfmtelapsed\b(3),"
+" \bstrftime\b(3), \bstrptime\b(3), \btm\b(3)]"
+;
+
+#include <cmd.h>
+#include <ls.h>
+#include <proc.h>
+#include <tmx.h>
+#include <times.h>
+
+typedef struct Fmt
+{
+ struct Fmt* next;
+ char* format;
+} Fmt_t;
+
+#ifndef ENOSYS
+#define ENOSYS EINVAL
+#endif
+
+/*
+ * set the system clock
+ * the standards wimped out here
+ */
+
+static int
+settime(Shbltin_t* context, const char* cmd, Time_t now, int adjust, int network)
+{
+ char* s;
+ char** argv;
+ char* args[5];
+ char buf[1024];
+
+ if (!adjust && !network)
+ return tmxsettime(now);
+ argv = args;
+ s = "/usr/bin/date";
+ if (!streq(cmd, s) && (!eaccess(s, X_OK) || !eaccess(s+=4, X_OK)))
+ {
+ *argv++ = s;
+ if (streq(astconf("UNIVERSE", NiL, NiL), "att"))
+ {
+ tmxfmt(buf, sizeof(buf), "%m%d%H" "%M%Y.%S", now);
+ if (adjust)
+ *argv++ = "-a";
+ }
+ else
+ {
+ tmxfmt(buf, sizeof(buf), "%Y%m%d%H" "%M.%S", now);
+ if (network)
+ *argv++ = "-n";
+ if (tm_info.flags & TM_UTC)
+ *argv++ = "-u";
+ }
+ *argv++ = buf;
+ *argv = 0;
+ if (!sh_run(context, argv - args, args))
+ return 0;
+ }
+ return -1;
+}
+
+/*
+ * convert s to Time_t with error checking
+ */
+
+static Time_t
+convert(register Fmt_t* f, char* s, Time_t now)
+{
+ char* t;
+ char* u;
+
+ do
+ {
+ now = tmxscan(s, &t, f->format, &u, now, 0);
+ if (!*t && (!f->format || !*u))
+ break;
+ } while (f = f->next);
+ if (!f || *t)
+ error(3, "%s: invalid date specification", f ? t : s);
+ return now;
+}
+
+int
+b_date(int argc, register char** argv, Shbltin_t* context)
+{
+ register int n;
+ register char* s;
+ register Fmt_t* f;
+ char* t;
+ unsigned long u;
+ Time_t now;
+ Time_t ts;
+ Time_t te;
+ Time_t e;
+ char buf[1024];
+ Fmt_t* fmts;
+ Fmt_t fmt;
+ struct stat st;
+
+ char* cmd = argv[0]; /* original command path */
+ char* format = 0; /* tmxfmt() format */
+ char* string = 0; /* date string */
+ int elapsed = 0; /* args are start/stop pairs */
+ int filetime = 0; /* use this st_ time field */
+ int increment = 0; /* incrementally adjust time */
+ int last = 0; /* display the last time arg */
+ Tm_zone_t* listzones = 0; /* known time zone table */
+ int network = 0; /* don't set network time */
+ int show = 0; /* show date and don't set */
+ int unelapsed = 0; /* fmtelapsed() => strelapsed */
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ tm_info.flags = TM_DATESTYLE;
+ fmts = &fmt;
+ fmt.format = "";
+ fmt.next = 0;
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'a':
+ case 'c':
+ case 'm':
+ filetime = opt_info.option[1];
+ continue;
+ case 'd':
+ string = opt_info.arg;
+ show = 1;
+ continue;
+ case 'e':
+ format = "%s";
+ continue;
+ case 'E':
+ elapsed = 1;
+ continue;
+ case 'f':
+ format = opt_info.arg;
+ continue;
+ case 'i':
+ increment = 1;
+ continue;
+ case 'l':
+ tm_info.flags |= TM_LEAP;
+ continue;
+ case 'L':
+ last = 1;
+ continue;
+ case 'n':
+ network = 1;
+ continue;
+ case 'p':
+ if (!(f = newof(0, Fmt_t, 1, 0)))
+ error(ERROR_SYSTEM|3, "out of space [format]");
+ f->next = fmts;
+ f->format = opt_info.arg;
+ fmts = f;
+ continue;
+ case 'R':
+ format = "%a, %-e %h %Y %H:%M:%S %z";
+ continue;
+ case 's':
+ show = 1;
+ continue;
+ case 'T':
+ switch (opt_info.num)
+ {
+ case 'd':
+ format = "%Y-%m-%d";
+ continue;
+ case 'n':
+ format = "%Y-%m-%d %H:%M:%S.%N%_z";
+ continue;
+ case 's':
+ format = "%Y-%m-%d %H:%M:%S%_z";
+ continue;
+ }
+ continue;
+ case 'u':
+ tm_info.flags |= TM_UTC;
+ continue;
+ case 'U':
+ unelapsed = (int)opt_info.num;
+ continue;
+ case 'z':
+ listzones = tm_data.zone;
+ continue;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ now = tmxgettime();
+ if (listzones)
+ {
+ s = "-";
+ while (listzones->standard)
+ {
+ if (listzones->type)
+ s = listzones->type;
+ sfprintf(sfstdout, "%3s %4s %4s %4d %4d\n", s, *listzones->standard ? listzones->standard : "-", listzones->daylight ? listzones->daylight : "-", listzones->west, listzones->dst);
+ listzones++;
+ show = 1;
+ }
+ }
+ else if (elapsed)
+ {
+ e = 0;
+ while (s = *argv++)
+ {
+ if (!(t = *argv++))
+ {
+ argv--;
+ t = "now";
+ }
+ ts = convert(fmts, s, now);
+ te = convert(fmts, t, now);
+ if (te > ts)
+ e += te - ts;
+ else
+ e += ts - te;
+ }
+ sfputr(sfstdout, fmtelapsed((unsigned long)tmxsec(e), 1), '\n');
+ show = 1;
+ }
+ else if (unelapsed)
+ {
+ while (s = *argv++)
+ {
+ u = strelapsed(s, &t, unelapsed);
+ if (*t)
+ error(3, "%s: invalid elapsed time", s);
+ sfprintf(sfstdout, "%lu\n", u);
+ }
+ show = 1;
+ }
+ else if (filetime)
+ {
+ if (!*argv)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ n = argv[1] != 0;
+ while (s = *argv++)
+ {
+ if (stat(s, &st))
+ error(2, "%s: not found", s);
+ else
+ {
+ switch (filetime)
+ {
+ case 'a':
+ now = tmxgetatime(&st);
+ break;
+ case 'c':
+ now = tmxgetctime(&st);
+ break;
+ default:
+ now = tmxgetmtime(&st);
+ break;
+ }
+ tmxfmt(buf, sizeof(buf), format, now);
+ if (n)
+ sfprintf(sfstdout, "%s: %s\n", s, buf);
+ else
+ sfprintf(sfstdout, "%s\n", buf);
+ show = 1;
+ }
+ }
+ }
+ else
+ {
+ if ((s = *argv) && !format && *s == '+')
+ {
+ format = s + 1;
+ argv++;
+ s = *argv;
+ }
+ if (s || (s = string))
+ {
+ if (*argv && string)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ now = convert(fmts, s, now);
+ if (*argv && (s = *++argv))
+ {
+ show = 1;
+ do
+ {
+ if (!last)
+ {
+ tmxfmt(buf, sizeof(buf), format, now);
+ sfprintf(sfstdout, "%s\n", buf);
+ }
+ now = convert(fmts, s, now);
+ } while (s = *++argv);
+ }
+ }
+ else
+ show = 1;
+ if (format || show)
+ {
+ tmxfmt(buf, sizeof(buf), format, now);
+ sfprintf(sfstdout, "%s\n", buf);
+ }
+ else if (settime(context, cmd, now, increment, network))
+ error(ERROR_SYSTEM|3, "cannot set system time");
+ }
+ while (fmts != &fmt)
+ {
+ f = fmts;
+ fmts = fmts->next;
+ free(f);
+ }
+ tm_info.flags = 0;
+ if (show && sfsync(sfstdout))
+ error(ERROR_system(0), "write error");
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/dirname.c b/src/lib/libcmd/dirname.c
new file mode 100644
index 0000000..a0704d5
--- /dev/null
+++ b/src/lib/libcmd/dirname.c
@@ -0,0 +1,139 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * dirname path [suffix]
+ *
+ * print the dirname of a pathname
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: dirname (AT&T Research) 2009-01-31 $\n]"
+USAGE_LICENSE
+"[+NAME?dirname - return directory portion of file name]"
+"[+DESCRIPTION?\bdirname\b treats \astring\a as a file name and returns "
+ "the name of the directory containing the file name by deleting "
+ "the last component from \astring\a.]"
+"[+?If \astring\a consists solely of \b/\b characters the output will "
+ "be a single \b/\b unless \bPATH_LEADING_SLASHES\b returned by "
+ "\bgetconf\b(1) is \b1\b and \astring\a consists of multiple "
+ "\b/\b characters in which case \b//\b will be output. "
+ "Otherwise, trailing \b/\b characters are removed, and if "
+ "there are no remaining \b/\b characters in \astring\a, "
+ "the string \b.\b will be written to standard output. "
+ "Otherwise, all characters following the last \b/\b are removed. "
+ "If the remaining string consists solely of \b/\b characters, "
+ "the output will be as if the original string had consisted solely "
+ "as \b/\b characters as described above. Otherwise, all "
+ "trailing slashes are removed and the output will be this string "
+ "unless this string is empty. If empty the output will be \b.\b.]"
+"[f:file?Print the \b$PATH\b relative regular file path for \astring\a.]"
+"[r:relative?Print the \b$PATH\b relative readable file path for \astring\a.]"
+"[x:executable?Print the \b$PATH\b relative executable file path for \astring\a.]"
+"\n"
+"\nstring\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful Completion.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bbasename\b(1), \bgetconf\b(1), \bdirname\b(3), \bpathname\b(3)]"
+;
+
+#include <cmd.h>
+
+static void l_dirname(register Sfio_t *outfile, register const char *pathname)
+{
+ register const char *last;
+ /* go to end of path */
+ for(last=pathname; *last; last++);
+ /* back over trailing '/' */
+ while(last>pathname && *--last=='/');
+ /* back over non-slash chars */
+ for(;last>pathname && *last!='/';last--);
+ if(last==pathname)
+ {
+ /* all '/' or "" */
+ if(*pathname!='/')
+ last = pathname = ".";
+ }
+ else
+ {
+ /* back over trailing '/' */
+ for(;*last=='/' && last > pathname; last--);
+ }
+ /* preserve // */
+ if(last!=pathname && pathname[0]=='/' && pathname[1]=='/')
+ {
+ while(pathname[2]=='/' && pathname<last)
+ pathname++;
+ if(last!=pathname && pathname[0]=='/' && pathname[1]=='/' && *astconf("PATH_LEADING_SLASHES",NiL,NiL)!='1')
+ pathname++;
+ }
+ sfwrite(outfile,pathname,last+1-pathname);
+ sfputc(outfile,'\n');
+}
+
+int
+b_dirname(int argc, char** argv, Shbltin_t* context)
+{
+ int mode = 0;
+ char buf[PATH_MAX];
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'f':
+ mode |= PATH_REGULAR;
+ continue;
+ case 'r':
+ mode &= ~PATH_REGULAR;
+ mode |= PATH_READ;
+ continue;
+ case 'x':
+ mode |= PATH_EXECUTE;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if(error_info.errors || argc != 1)
+ error(ERROR_usage(2),"%s", optusage(NiL));
+ if(!mode)
+ l_dirname(sfstdout,argv[0]);
+ else if(pathpath(argv[0], "", mode, buf, sizeof(buf)))
+ sfputr(sfstdout, buf, '\n');
+ else
+ error(1|ERROR_WARNING, "%s: relative path not found", argv[0]);
+ return 0;
+}
diff --git a/src/lib/libcmd/expr.c b/src/lib/libcmd/expr.c
new file mode 100644
index 0000000..a19b042
--- /dev/null
+++ b/src/lib/libcmd/expr.c
@@ -0,0 +1,535 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * expr.c
+ * Written by David Korn
+ * Tue Oct 31 08:48:11 EST 1995
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: expr (AT&T Research) 2010-08-11 $\n]"
+USAGE_LICENSE
+"[+NAME?expr - evaluate arguments as an expression]"
+"[+DESCRIPTION?\bexpr\b evaluates an expression given as arguments and writes "
+ "the result to standard output. The character \b0\b will be written "
+ "to indicate a zero value and nothing will be written to indicate an "
+ "empty string.]"
+"[+?Most of the functionality of \bexpr\b is provided in a more natural "
+ "way by the shell, \bsh\b(1), and \bexpr\b is provided primarily "
+ "for backward compatibility.]"
+"[+?Terms of the expression must be separate arguments. A string argument is "
+ "one that can not be identified as an integer. Integer-valued "
+ "arguments may be preceded by a unary plus or minus sign. Because "
+ "many of the operators use characters that have special meaning to "
+ "the shell, they must be quoted when entered from the shell.]"
+
+"[+?Expressions are formed from the operators listed below in order "
+ "of increasing precedence within groups. All of the operators are "
+ "left associative. The symbols \aexpr1\a and \aexpr2\a represent "
+ "expressions formed from strings and integers and the following "
+ "operators:]{"
+ "[+\aexpr1\a \b|\b \aexpr2\a?Returns the evaluation of \aexpr1\a if "
+ "it is neither null nor 0, otherwise returns the evaluation of expr2.]"
+
+ "[+\aexpr1\a \b&\b \aexpr2\a?Returns the evaluation of \aexpr1\a if "
+ "neither expression evaluates to null or 0, otherwise returns 0.]"
+
+ "[+\aexpr1\a \aop\a \aexpr2\a?Returns the result of a decimal integer "
+ "comparison if both arguments are integers; otherwise, returns the "
+ "result of a string comparison using the locale-specific collation "
+ "sequence. The result of each comparison will be 1 if the specified "
+ "relationship is true, or 0 if the relationship is false. \aop\a "
+ "can be one of the following:]{"
+ "[+=?Equal.]"
+ "[+==?Equal.]"
+ "[+>?Greater than.]"
+ "[+>=?Greater than or equal to.]"
+ "[+<?Less than.]"
+ "[+<=?Less than or equal to.]"
+ "[+!=?Not equal to.]"
+ "}"
+
+ "[+\aexpr1\a \aop\a \aexpr2\a?Where \aop\a is \b+\b or \b-\b; "
+ "addition or subtraction of decimal integer-valued arguments.]"
+ "[+\aexpr1\a \aop\a \aexpr2\a?Where \aop\a is \b*\b, \b/\b or \b%\b; "
+ "multiplication, division, or remainder of the decimal "
+ "integer-valued arguments.]"
+ "[+\aexpr1\a \b::\b \aexpr2\a?The matching operator : compares "
+ "\aexpr1\a with \aexpr2\a, which must be a BRE. Normally, "
+ "the matching operator returns the number of bytes matched "
+ "and 0 on failure. However, if the pattern contains at "
+ "least one sub-expression [\\( . . .\\)]], the string "
+ "corresponding to \\1 will be returned.]"
+ "[+( \aexpr1\a )?Grouping symbols. An expression can "
+ "be placed within parenthesis to change precedence.]"
+ "[+match\b \astring\a \aexpr\a?Equivalent to \astring\a \b:\b "
+ "\aexpr\a.]"
+ "[+substr\b \astring\a \apos\a \alength\a?\alength\a character "
+ "substring of \astring\a starting at \apos\a "
+ "(counting from 1).]"
+ "[+index\b \astring\a \achars\a?The position in \astring\a "
+ "(counting from 1) of the leftmost occurrence of any "
+ "character in \achars\a.]"
+ "[+length\b \astring\a?The number of characters in \astring\a.]"
+ "[+quote\b \atoken\a?Treat \atoken\a as a string operand.]"
+ "}"
+"[+?For backwards compatibility, unrecognized options beginning with "
+ "a \b-\b will be treated as operands. Portable applications "
+ "should use \b--\b to indicate end of options.]"
+
+"\n"
+"\n operand ...\n"
+"\n"
+
+"[+EXIT STATUS?]{"
+ "[+0?The expression is neither null nor 0.]"
+ "[+1?The expression is null or 0.]"
+ "[+2?Invalid expressions.]"
+ "[+>2?An error occurred.]"
+ "}"
+"[+SEE ALSO?\bregcomp\b(5), \bgrep\b(1), \bsh\b(1)]"
+;
+
+#include <cmd.h>
+#include <regex.h>
+
+#define T_ADD 0x100
+#define T_MULT 0x200
+#define T_CMP 0x400
+#define T_FUN 0x800
+#define T_OP 7
+#define T_NUM 1
+#define T_STR 2
+
+#define OP_EQ (T_CMP|0)
+#define OP_GT (T_CMP|1)
+#define OP_LT (T_CMP|2)
+#define OP_GE (T_CMP|3)
+#define OP_LE (T_CMP|4)
+#define OP_NE (T_CMP|5)
+#define OP_PLUS (T_ADD|0)
+#define OP_MINUS (T_ADD|1)
+#define OP_MULT (T_MULT|0)
+#define OP_DIV (T_MULT|1)
+#define OP_MOD (T_MULT|2)
+#define OP_INDEX (T_FUN|0)
+#define OP_LENGTH (T_FUN|1)
+#define OP_MATCH (T_FUN|2)
+#define OP_QUOTE (T_FUN|3)
+#define OP_SUBSTR (T_FUN|4)
+
+#define numeric(np) ((np)->type&T_NUM)
+
+static const struct Optable_s
+{
+ const char opname[3];
+ int op;
+}
+optable[] =
+{
+ "|", '|',
+ "&", '&',
+ "=", OP_EQ,
+ "==", OP_EQ,
+ ">", OP_GT,
+ "<", OP_LT,
+ ">=", OP_GE,
+ "<=", OP_LE,
+ "!=", OP_NE,
+ "+", OP_PLUS,
+ "-", OP_MINUS,
+ "*", OP_MULT,
+ "/", OP_DIV,
+ "%", OP_MOD,
+ ":", ':',
+ "(", '(',
+ ")", ')'
+};
+
+typedef struct Node_s
+{
+ int type;
+ long num;
+ char *str;
+} Node_t;
+
+typedef struct State_s
+{
+ int standard;
+ char** arglist;
+ char buf[36];
+} State_t;
+
+static int expr_or(State_t*, Node_t*);
+
+static int getnode(State_t* state, Node_t *np)
+{
+ register char* sp;
+ register char* cp;
+ register int i;
+ register int j;
+ register int k;
+ register int tok;
+ char* ep;
+
+ if (!(cp = *state->arglist++))
+ error(ERROR_exit(2), "argument expected");
+ if (!state->standard)
+ switch (cp[0])
+ {
+ case 'i':
+ if (cp[1] == 'n' && !strcmp(cp, "index"))
+ {
+ if (!(cp = *state->arglist++))
+ error(ERROR_exit(2), "string argument expected");
+ if (!(ep = *state->arglist++))
+ error(ERROR_exit(2), "chars argument expected");
+ np->num = (ep = strpbrk(cp, ep)) ? (ep - cp + 1) : 0;
+ np->type = T_NUM;
+ goto next;
+ }
+ break;
+ case 'l':
+ if (cp[1] == 'e' && !strcmp(cp, "length"))
+ {
+ if (!(cp = *state->arglist++))
+ error(ERROR_exit(2), "string argument expected");
+ np->num = strlen(cp);
+ np->type = T_NUM;
+ goto next;
+ }
+ break;
+ case 'm':
+ if (cp[1] == 'a' && !strcmp(cp, "match"))
+ {
+ if (!(np->str = *state->arglist++))
+ error(ERROR_exit(2), "pattern argument expected");
+ np->type = T_STR;
+ return ':';
+ }
+ break;
+ case 'q':
+ if (cp[1] == 'u' && !strcmp(cp, "quote") && !(cp = *state->arglist++))
+ error(ERROR_exit(2), "string argument expected");
+ break;
+ case 's':
+ if (cp[1] == 'u' && !strcmp(cp, "substr"))
+ {
+ if (!(sp = *state->arglist++))
+ error(ERROR_exit(2), "string argument expected");
+ if (!(cp = *state->arglist++))
+ error(ERROR_exit(2), "position argument expected");
+ i = strtol(cp, &ep, 10);
+ if (*ep || --i < 0)
+ i = -1;
+ if (!(cp = *state->arglist++))
+ error(ERROR_exit(2), "length argument expected");
+ j = strtol(cp, &ep, 10);
+ if (*ep)
+ j = -1;
+ k = strlen(sp);
+ if (i < 0 || i >= k || j < 0)
+ sp = "";
+ else
+ {
+ sp += i;
+ k -= i;
+ if (j < k)
+ sp[j] = 0;
+ }
+ np->type = T_STR;
+ np->str = sp;
+ goto next;
+ }
+ break;
+ }
+ if (*cp=='(' && cp[1]==0)
+ {
+ tok = expr_or(state, np);
+ if (tok != ')')
+ error(ERROR_exit(2),"closing parenthesis missing");
+ }
+ else
+ {
+ np->type = T_STR;
+ np->str = cp;
+ if (*cp)
+ {
+ np->num = strtol(np->str,&ep,10);
+ if (!*ep)
+ np->type |= T_NUM;
+ }
+ }
+ next:
+ if (!(cp = *state->arglist))
+ return 0;
+ state->arglist++;
+ for (i=0; i < sizeof(optable)/sizeof(*optable); i++)
+ if (*cp==optable[i].opname[0] && cp[1]==optable[i].opname[1])
+ return optable[i].op;
+ error(ERROR_exit(2),"%s: unknown operator argument",cp);
+ return 0;
+}
+
+static int expr_cond(State_t* state, Node_t *np)
+{
+ register int tok = getnode(state, np);
+
+ while (tok==':')
+ {
+ regex_t re;
+ regmatch_t match[2];
+ int n;
+ Node_t rp;
+ char *cp;
+ tok = getnode(state, &rp);
+ if (np->type&T_STR)
+ cp = np->str;
+ else
+ sfsprintf(cp=state->buf,sizeof(state->buf),"%d",np->num);
+ np->num = 0;
+ np->type = T_NUM;
+ if (n = regcomp(&re, rp.str, REG_LEFT|REG_LENIENT))
+ regfatal(&re, ERROR_exit(2), n);
+ if (!(n = regexec(&re, cp, elementsof(match), match, 0)))
+ {
+ if (re.re_nsub > 0)
+ {
+ np->type = T_STR;
+ if (match[1].rm_so >= 0)
+ {
+ np->str = cp + match[1].rm_so;
+ np->str[match[1].rm_eo - match[1].rm_so] = 0;
+ np->num = strtol(np->str,&cp,10);
+ if (cp!=np->str && *cp==0)
+ np->type |= T_NUM;
+ }
+ else
+ np->str = "";
+ }
+ else
+ np->num = match[0].rm_eo - match[0].rm_so;
+ }
+ else if (n != REG_NOMATCH)
+ regfatal(&re, ERROR_exit(2), n);
+ else if (re.re_nsub)
+ {
+ np->str = "";
+ np->type = T_STR;
+ }
+ regfree(&re);
+ }
+ return tok;
+}
+
+static int expr_mult(State_t* state, Node_t *np)
+{
+ register int tok = expr_cond(state, np);
+
+ while ((tok&~T_OP)==T_MULT)
+ {
+ Node_t rp;
+ int op = (tok&T_OP);
+ tok = expr_cond(state, &rp);
+ if (!numeric(np) || !numeric(&rp))
+ error(ERROR_exit(2),"non-numeric argument");
+ if (op && rp.num==0)
+ error(ERROR_exit(2),"division by zero");
+ switch(op)
+ {
+ case 0:
+ np->num *= rp.num;
+ break;
+ case 1:
+ np->num /= rp.num;
+ break;
+ case 2:
+ np->num %= rp.num;
+ }
+ np->type = T_NUM;
+ }
+ return tok;
+}
+
+static int expr_add(State_t* state, Node_t *np)
+{
+ register int tok = expr_mult(state, np);
+
+ while ((tok&~T_OP)==T_ADD)
+ {
+ Node_t rp;
+ int op = (tok&T_OP);
+ tok = expr_mult(state, &rp);
+ if (!numeric(np) || !numeric(&rp))
+ error(ERROR_exit(2),"non-numeric argument");
+ if (op)
+ np->num -= rp.num;
+ else
+ np->num += rp.num;
+ np->type = T_NUM;
+ }
+ return tok;
+}
+
+static int expr_cmp(State_t* state, Node_t *np)
+{
+ register int tok = expr_add(state, np);
+
+ while ((tok&~T_OP)==T_CMP)
+ {
+ Node_t rp;
+ register char *left,*right;
+ char buff1[36],buff2[36];
+ int op = (tok&T_OP);
+ tok = expr_add(state, &rp);
+ if (numeric(&rp) && numeric(np))
+ op |= 010;
+ else
+ {
+ if (np->type&T_STR)
+ left = np->str;
+ else
+ sfsprintf(left=buff1,sizeof(buff1),"%d",np->num);
+ if (rp.type&T_STR)
+ right = rp.str;
+ else
+ sfsprintf(right=buff2,sizeof(buff2),"%d",rp.num);
+ }
+ switch(op)
+ {
+ case 0:
+ np->num = streq(left,right);
+ break;
+ case 1:
+ np->num = (strcoll(left,right)>0);
+ break;
+ case 2:
+ np->num = (strcoll(left,right)<0);
+ break;
+ case 3:
+ np->num = (strcoll(left,right)>=0);
+ break;
+ case 4:
+ np->num = (strcoll(left,right)<=0);
+ break;
+ case 5:
+ np->num = !streq(left,right);
+ break;
+ case 010:
+ np->num = (np->num==rp.num);
+ break;
+ case 011:
+ np->num = (np->num>rp.num);
+ break;
+ case 012:
+ np->num = (np->num<rp.num);
+ break;
+ case 013:
+ np->num = (np->num>=rp.num);
+ break;
+ case 014:
+ np->num = (np->num<=rp.num);
+ break;
+ case 015:
+ np->num = (np->num!=rp.num);
+ break;
+ }
+ np->type = T_NUM;
+ }
+ return tok;
+}
+
+static int expr_and(State_t* state, Node_t *np)
+{
+ register int tok = expr_cmp(state, np);
+ while (tok=='&')
+ {
+ Node_t rp;
+ tok = expr_cmp(state, &rp);
+ if ((numeric(&rp) && rp.num==0) || *rp.str==0)
+ {
+ np->num = 0;
+ np->type=T_NUM;
+ }
+ }
+ return tok;
+}
+
+static int expr_or(State_t* state, Node_t *np)
+{
+ register int tok = expr_and(state, np);
+ while (tok=='|')
+ {
+ Node_t rp;
+ tok = expr_and(state, &rp);
+ if ((numeric(np) && np->num==0) || *np->str==0)
+ *np = rp;
+ }
+ return tok;
+}
+
+int
+b_expr(int argc, char** argv, Shbltin_t* context)
+{
+ State_t state;
+ Node_t node;
+ int n;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ state.standard = !!conformance(0, 0);
+#if 0
+ if (state.standard)
+ state.arglist = argv+1;
+ else
+#endif
+ {
+ while (n=optget(argv, usage))
+ {
+ /*
+ * NOTE: this loop ignores all but literal -- and -?
+ * out of kindness for obsolescent usage
+ * (and is ok with the standard) but strict
+ * getopt conformance would give usage for all
+ * unknown - options
+ */
+ if(n=='?')
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ if (opt_info.option[1] != '?')
+ break;
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ }
+ if (error_info.errors)
+ error(ERROR_usage(2),"%s",optusage((char*)0));
+ state.arglist = argv+opt_info.index;
+ }
+ if (expr_or(&state, &node))
+ error(ERROR_exit(2),"syntax error");
+ if (node.type&T_STR)
+ {
+ if (*node.str)
+ sfprintf(sfstdout,"%s\n",node.str);
+ }
+ else
+ sfprintf(sfstdout,"%d\n",node.num);
+ return numeric(&node)?node.num==0:*node.str==0;
+}
diff --git a/src/lib/libcmd/fds.c b/src/lib/libcmd/fds.c
new file mode 100644
index 0000000..4dc934f
--- /dev/null
+++ b/src/lib/libcmd/fds.c
@@ -0,0 +1,360 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+static const char usage[] =
+"[-?\n@(#)$Id: fds (AT&T Research) 2009-09-09 $\n]"
+USAGE_LICENSE
+"[+NAME?fds - list open file descriptor status]"
+"[+DESCRIPTION?\bfds\b lists the status for each open file descriptor. "
+ "When invoked as a shell builtin it accesses the file descriptors of the "
+ "calling shell, otherwise it lists the file descriptors passed across "
+ "\bexec\b(2).]"
+"[l:long?List file descriptor details.]"
+"[u:unit?Write output to \afd\a.]#[fd]"
+"[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2), \bgetsockname\b(2), \bgetsockopts\b(2)]"
+;
+
+#include <cmd.h>
+#include <ls.h>
+
+#include "FEATURE/sockets"
+
+#if defined(S_IFSOCK) && _sys_socket && _hdr_arpa_inet && _hdr_netinet_in && _lib_getsockname && _lib_getsockopt && _lib_inet_ntoa
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#else
+#undef S_IFSOCK
+#endif
+
+#ifndef minor
+#define minor(x) (int)((x)&0xff)
+#endif
+#ifndef major
+#define major(x) (int)(((unsigned int)(x)>>8)&0xff)
+#endif
+
+#undef getconf
+#define getconf(x) strtol(astconf(x,NiL,NiL),NiL,0)
+
+#ifdef S_IFSOCK
+
+typedef struct NV_s
+{
+ const char* name;
+ int value;
+} NV_t;
+
+static const NV_t family[] =
+{
+#ifdef AF_LOCAL
+ "pipe", AF_LOCAL,
+#endif
+#ifdef AF_UNIX
+ "pipe", AF_UNIX,
+#endif
+#ifdef AF_FILE
+ "FILE", AF_FILE,
+#endif
+#ifdef AF_INET
+ "INET", AF_INET,
+#endif
+#ifdef AF_AX25
+ "AX25", AF_AX25,
+#endif
+#ifdef AF_IPX
+ "IPX", AF_IPX,
+#endif
+#ifdef AF_APPLETALK
+ "APPLETALK", AF_APPLETALK,
+#endif
+#ifdef AF_NETROM
+ "NETROM", AF_NETROM,
+#endif
+#ifdef AF_BRIDGE
+ "BRIDGE", AF_BRIDGE,
+#endif
+#ifdef AF_ATMPVC
+ "ATMPVC", AF_ATMPVC,
+#endif
+#ifdef AF_X25
+ "X25", AF_X25,
+#endif
+#ifdef AF_INET6
+ "INET6", AF_INET6,
+#endif
+#ifdef AF_ROSE
+ "ROSE", AF_ROSE,
+#endif
+#ifdef AF_DECnet
+ "DECnet", AF_DECnet,
+#endif
+#ifdef AF_NETBEUI
+ "NETBEUI", AF_NETBEUI,
+#endif
+#ifdef AF_SECURITY
+ "SECURITY", AF_SECURITY,
+#endif
+#ifdef AF_KEY
+ "KEY", AF_KEY,
+#endif
+#ifdef AF_NETLINK
+ "NETLINK", AF_NETLINK,
+#endif
+#ifdef AF_ROUTE
+ "ROUTE", AF_ROUTE,
+#endif
+#ifdef AF_PACKET
+ "PACKET", AF_PACKET,
+#endif
+#ifdef AF_ASH
+ "ASH", AF_ASH,
+#endif
+#ifdef AF_ECONET
+ "ECONET", AF_ECONET,
+#endif
+#ifdef AF_ATMSVC
+ "ATMSVC", AF_ATMSVC,
+#endif
+#ifdef AF_SNA
+ "SNA", AF_SNA,
+#endif
+#ifdef AF_IRDA
+ "IRDA", AF_IRDA,
+#endif
+#ifdef AF_PPPOX
+ "PPPOX", AF_PPPOX,
+#endif
+#ifdef AF_WANPIPE
+ "WANPIPE", AF_WANPIPE,
+#endif
+#ifdef AF_BLUETOOTH
+ "BLUETOOTH", AF_BLUETOOTH,
+#endif
+ 0
+};
+
+#endif
+
+int
+b_fds(int argc, char** argv, Shbltin_t* context)
+{
+ register char* s;
+ register int i;
+ register char* m;
+ register char* x;
+ int flags;
+ int details;
+ int open_max;
+ int unit;
+ Sfio_t* sp;
+ struct stat st;
+#ifdef S_IFSOCK
+ struct sockaddr_in addr;
+ char* a;
+ unsigned char* b;
+ unsigned char* e;
+ socklen_t addrlen;
+ socklen_t len;
+ int type;
+ int port;
+ int prot;
+ char num[64];
+ char fam[64];
+#ifdef INET6_ADDRSTRLEN
+ char nam[256];
+#endif
+#endif
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ details = 0;
+ unit = 1;
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'l':
+ details = opt_info.num;
+ continue;
+ case 'u':
+ unit = opt_info.num;
+ continue;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || *argv)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ if ((open_max = getconf("OPEN_MAX")) <= 0)
+ open_max = OPEN_MAX;
+ if (unit == 1)
+ sp = sfstdout;
+ else if (fstat(unit, &st) || !(sp = sfnew(NiL, NiL, SF_UNBOUND, unit, SF_WRITE)))
+ error(ERROR_SYSTEM|3, "%d: cannot write to file descriptor");
+ for (i = 0; i <= open_max; i++)
+ {
+ if (fstat(i, &st))
+ {
+ /* not open */
+ continue;
+ }
+ if (!details)
+ {
+ sfprintf(sp, "%d\n", i);
+ continue;
+ }
+ if ((flags = fcntl(i, F_GETFL, (char*)0)) == -1)
+ m = "--";
+ else
+ switch (flags & (O_RDONLY|O_WRONLY|O_RDWR))
+ {
+ case O_RDONLY:
+ m = "r-";
+ break;
+ case O_WRONLY:
+ m = "-w";
+ break;
+ case O_RDWR:
+ m = "rw";
+ break;
+ default:
+ m = "??";
+ break;
+ }
+ x = (fcntl(i, F_GETFD, (char*)0) > 0) ? "x" : "-";
+ if (isatty(i) && (s = ttyname(i)))
+ {
+ sfprintf(sp, "%02d %s%s %s %s\n", i, m, x, fmtmode(st.st_mode, 0), s);
+ continue;
+ }
+#ifdef S_IFSOCK
+ addrlen = sizeof(addr);
+ memset(&addr, 0, addrlen);
+ if (!getsockname(i, (struct sockaddr*)&addr, (void*)&addrlen))
+ {
+ type = 0;
+ prot = 0;
+#ifdef SO_TYPE
+ len = sizeof(type);
+ if (getsockopt(i, SOL_SOCKET, SO_TYPE, (void*)&type, (void*)&len))
+ type = -1;
+#endif
+#ifdef SO_PROTOTYPE
+ len = sizeof(prot);
+ if (getsockopt(i, SOL_SOCKET, SO_PROTOTYPE, (void*)&prot, (void*)&len))
+ prot = -1;
+#endif
+ if (!st.st_mode)
+ st.st_mode = S_IFSOCK|S_IRUSR|S_IWUSR;
+ s = 0;
+ switch (type)
+ {
+ case SOCK_DGRAM:
+ switch (addr.sin_family)
+ {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ s = "udp";
+ break;
+ }
+ break;
+ case SOCK_STREAM:
+ switch (addr.sin_family)
+ {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+#ifdef IPPROTO_SCTP
+ if (prot == IPPROTO_SCTP)
+ s = "sctp";
+ else
+#endif
+ s = "tcp";
+ break;
+ }
+ break;
+#ifdef SOCK_RAW
+ case SOCK_RAW:
+ s = "raw";
+ break;
+#endif
+#ifdef SOCK_RDM
+ case SOCK_RDM:
+ s = "rdm";
+ break;
+#endif
+#ifdef SOCK_SEQPACKET
+ case SOCK_SEQPACKET:
+ s = "seqpacket";
+ break;
+#endif
+ }
+ if (!s)
+ {
+ for (type = 0; family[type].name && family[type].value != addr.sin_family; type++);
+ if (!(s = (char*)family[type].name))
+ sfsprintf(s = num, sizeof(num), "family.%d", addr.sin_family);
+ }
+ port = 0;
+#ifdef INET6_ADDRSTRLEN
+ if (a = (char*)inet_ntop(addr.sin_family, &addr.sin_addr, nam, sizeof(nam)))
+ port = ntohs(addr.sin_port);
+ else
+#endif
+ if (addr.sin_family == AF_INET)
+ {
+ a = inet_ntoa(addr.sin_addr);
+ port = ntohs(addr.sin_port);
+ }
+ else
+ {
+ a = fam;
+ e = (b = (unsigned char*)&addr) + addrlen;
+ while (b < e && a < &fam[sizeof(fam)-1])
+ a += sfsprintf(a, &fam[sizeof(fam)] - a - 1, ".%d", *b++);
+ a = a == fam ? "0" : fam + 1;
+ }
+ if (port)
+ sfprintf(sp, "%02d %s%s %s /dev/%s/%s/%d\n", i, m, x, fmtmode(st.st_mode, 0), s, a, port);
+ else
+ sfprintf(sp, "%02d %s%s %s /dev/%s/%s\n", i, m, x, fmtmode(st.st_mode, 0), s, a);
+ continue;
+ }
+#endif
+ sfprintf(sp, "%02d %s%s %s /dev/inode/%u/%u\n", i, m, x, fmtmode(st.st_mode, 0), st.st_dev, st.st_ino);
+ }
+ if (sp != sfstdout)
+ {
+ sfsetfd(sp, -1);
+ sfclose(sp);
+ }
+ return 0;
+}
diff --git a/src/lib/libcmd/features/ids b/src/lib/libcmd/features/ids
new file mode 100644
index 0000000..c8f7faa
--- /dev/null
+++ b/src/lib/libcmd/features/ids
@@ -0,0 +1,9 @@
+lib endgrent,getgrent,setgrent
+lib fsid,getfsgid,isfsg sys/types.h sys/fss.h fsg.h -lfsg
+lib getsid unistd.h
+mac fsid sys/types.h sys/fss.h fsg.h
+cat{
+ #if !_lib_fsid && _mac_fsid
+ #define _lib_fsid 1
+ #endif
+}end
diff --git a/src/lib/libcmd/features/sockets b/src/lib/libcmd/features/sockets
new file mode 100644
index 0000000..2660abb
--- /dev/null
+++ b/src/lib/libcmd/features/sockets
@@ -0,0 +1,3 @@
+sys socket
+hdr arpa.inet,netinet.in
+lib getsockname,getsockopt,inet_ntoa
diff --git a/src/lib/libcmd/features/symlink b/src/lib/libcmd/features/symlink
new file mode 100644
index 0000000..789db0b
--- /dev/null
+++ b/src/lib/libcmd/features/symlink
@@ -0,0 +1,23 @@
+lib lchmod note{ lchmod implemented }end execute{
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <errno.h>
+ int
+ main()
+ {
+ lchmod("No-FiLe", 0);
+ return errno != ENOENT;
+ }
+}end
+
+lib lchown note{ lchown implemented }end execute{
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <errno.h>
+ int
+ main()
+ {
+ lchown("No-FiLe", 0, 0);
+ return errno != ENOENT;
+ }
+}end
diff --git a/src/lib/libcmd/features/utsname b/src/lib/libcmd/features/utsname
new file mode 100644
index 0000000..7254867
--- /dev/null
+++ b/src/lib/libcmd/features/utsname
@@ -0,0 +1,15 @@
+lib getdomainname,gethostid,gethostname,sethostname,syscall,systeminfo,uname
+lib syssgi
+mem utsname.base_rel,utsname.idnumber,utsname.m_type,utsname.nodeext sys/utsname.h
+sys syscall,systeminfo,syssgi
+
+tst cross{
+ u=`/bin/uname -o 2>/dev/null`
+ case $u in
+ UWIN-*) u=UWIN ;;
+ esac
+ case $u in
+ '') ;;
+ *) echo "#define _UNAME_os_DEFAULT \"$u\" /* default os name */" ;;
+ esac
+}end
diff --git a/src/lib/libcmd/fmt.c b/src/lib/libcmd/fmt.c
new file mode 100644
index 0000000..e320767
--- /dev/null
+++ b/src/lib/libcmd/fmt.c
@@ -0,0 +1,635 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+static const char usage[] =
+"[-?\n@(#)$Id: fmt (AT&T Research) 2007-01-02 $\n]"
+USAGE_LICENSE
+"[+NAME?fmt - simple text formatter]"
+"[+DESCRIPTION?\bfmt\b reads the input files and left justifies space "
+ "separated words into lines \awidth\a characters or less in length and "
+ "writes the lines to the standard output. The standard input is read if "
+ "\b-\b or no files are specified. Blank lines and interword spacing are "
+ "preserved in the output. Indentation is preserved, and lines with "
+ "identical indentation are joined and justified.]"
+"[+?\bfmt\b is meant to format mail messages prior to sending, but may "
+ "also be useful for other simple tasks. For example, in \bvi\b(1) the "
+ "command \b:!}fmt\b will justify the lines in the current paragraph.]"
+"[c:crown-margin?Preserve the indentation of the first two lines within "
+ "a paragraph, and align the left margin of each subsequent line with "
+ "that of the second line.]"
+"[o:optget?Format concatenated \boptget\b(3) usage strings.]"
+"[s:split-only?Split lines only; do not join short lines to form longer "
+ "ones.]"
+"[u:uniform-spacing?One space between words, two after sentences.]"
+"[w:width?Set the output line width to \acolumns\a.]#[columns:=72]"
+ "\n\n"
+"[ file ... ]"
+ "\n\n"
+"[+SEE ALSO?\bmailx\b(1), \bnroff\b(1), \btroff\b(1), \bvi\b(1), "
+ "\boptget\b(3)]"
+;
+
+#include <cmd.h>
+#include <ctype.h>
+
+typedef struct Fmt_s
+{
+ long flags;
+ char* outp;
+ char* outbuf;
+ char* endbuf;
+ Sfio_t* in;
+ Sfio_t* out;
+ int indent;
+ int nextdent;
+ int nwords;
+ int prefix;
+ int quote;
+ int retain;
+ int section;
+} Fmt_t;
+
+#define INDENT 4
+#define TABSZ 8
+
+#define isoption(fp,c) ((fp)->flags&(1L<<((c)-'a')))
+#define setoption(fp,c) ((fp)->flags|=(1L<<((c)-'a')))
+#define clroption(fp,c) ((fp)->flags&=~(1L<<((c)-'a')))
+
+static void
+outline(Fmt_t* fp)
+{
+ register char* cp = fp->outbuf;
+ int n = 0;
+ int c;
+ int d;
+
+ if (!fp->outp)
+ return;
+ while (fp->outp[-1] == ' ')
+ fp->outp--;
+ *fp->outp = 0;
+ while (*cp++ == ' ')
+ n++;
+ if (n >= TABSZ)
+ {
+ n /= TABSZ;
+ cp = &fp->outbuf[TABSZ*n];
+ while (n--)
+ *--cp = '\t';
+ }
+ else
+ cp = fp->outbuf;
+ fp->nwords = 0;
+ if (!isoption(fp, 'o'))
+ sfputr(fp->out, cp, '\n');
+ else if (*cp)
+ {
+ n = fp->indent;
+ if (*cp != '[')
+ {
+ if (*cp == ' ')
+ cp++;
+ n += INDENT;
+ }
+ while (n--)
+ sfputc(fp->out, ' ');
+ if (fp->quote)
+ {
+ if ((d = (fp->outp - cp)) <= 0)
+ c = 0;
+ else if ((c = fp->outp[-1]) == 'n' && d > 1 && fp->outp[-2] == '\\')
+ c = '}';
+ sfprintf(fp->out, "\"%s%s\"\n", cp, c == ']' || c == '{' || c == '}' ? "" : " ");
+ }
+ else
+ sfputr(fp->out, cp, '\n');
+ if (fp->nextdent)
+ {
+ fp->indent += fp->nextdent;
+ fp->endbuf -= fp->nextdent;
+ fp->nextdent = 0;
+ }
+ }
+ fp->outp = 0;
+}
+
+static void
+split(Fmt_t* fp, char* buf, int splice)
+{
+ register char* cp;
+ register char* ep;
+ register char* qp;
+ register int c = 1;
+ register int q = 0;
+ register int n;
+ int prefix;
+
+ for (ep = buf; *ep == ' '; ep++);
+ prefix = ep - buf;
+
+ /*
+ * preserve blank lines
+ */
+
+ if ((*ep == 0 || *buf == '.') && !isoption(fp, 'o'))
+ {
+ if (*ep)
+ prefix = strlen(buf);
+ outline(fp);
+ strcpy(fp->outbuf, buf);
+ fp->outp = fp->outbuf+prefix;
+ outline(fp);
+ return;
+ }
+ if (fp->prefix < prefix && !isoption(fp, 'c'))
+ outline(fp);
+ if (!fp->outp || prefix < fp->prefix)
+ fp->prefix = prefix;
+ while (c)
+ {
+ cp = ep;
+ while (*ep == ' ')
+ ep++;
+ if (cp != ep && isoption(fp, 'u'))
+ cp = ep-1;
+ while (c = *ep)
+ {
+ if (c == ' ')
+ break;
+ ep++;
+
+ /*
+ * skip over \space
+ */
+
+ if (c == '\\' && *ep)
+ ep++;
+ }
+ n = (ep-cp);
+ if (n && isoption(fp, 'o'))
+ {
+ for (qp = cp; qp < ep; qp++)
+ if (*qp == '\\')
+ qp++;
+ else if (*qp == '"')
+ q = !q;
+ if (*(ep-1) == '"')
+ goto skip;
+ }
+ if (fp->nwords > 0 && &fp->outp[n] >= fp->endbuf && !fp->retain && !q)
+ outline(fp);
+ skip:
+ if (fp->nwords == 0)
+ {
+ if (fp->prefix)
+ memset(fp->outbuf, ' ', fp->prefix);
+ fp->outp = &fp->outbuf[fp->prefix];
+ while (*cp == ' ')
+ cp++;
+ n = (ep-cp);
+ }
+ memcpy(fp->outp, cp, n);
+ fp->outp += n;
+ fp->nwords++;
+ }
+ if (isoption(fp, 's') || *buf == 0)
+ outline(fp);
+ else if (fp->outp)
+ {
+ /*
+ * two spaces at ends of sentences
+ */
+
+ if (!isoption(fp, 'o') && strchr(".:!?", fp->outp[-1]))
+ *fp->outp++ = ' ';
+ if (!splice && !fp->retain && (!fp->quote || (fp->outp - fp->outbuf) < 2 || fp->outp[-2] != '\\' || fp->outp[-1] != 'n' && fp->outp[-1] != 't' && fp->outp[-1] != ' '))
+ *fp->outp++ = ' ';
+ }
+}
+
+static int
+dofmt(Fmt_t* fp)
+{
+ register int c;
+ int b;
+ int x;
+ int splice;
+ char* cp;
+ char* dp;
+ char* ep;
+ char* lp;
+ char* tp;
+ char buf[8192];
+
+ cp = 0;
+ while (cp || (cp = sfgetr(fp->in, '\n', 0)) && !(splice = 0) && (lp = cp + sfvalue(fp->in) - 1) || (cp = sfgetr(fp->in, '\n', SF_LASTR)) && (splice = 1) && (lp = cp + sfvalue(fp->in)))
+ {
+ if (isoption(fp, 'o'))
+ {
+ if (!isoption(fp, 'i'))
+ {
+ setoption(fp, 'i');
+ b = 0;
+ while (cp < lp)
+ {
+ if (*cp == ' ')
+ b += 1;
+ else if (*cp == '\t')
+ b += INDENT;
+ else
+ break;
+ cp++;
+ }
+ fp->indent = roundof(b, INDENT);
+ }
+ else
+ while (cp < lp && (*cp == ' ' || *cp == '\t'))
+ cp++;
+ if (!isoption(fp, 'q') && cp < lp)
+ {
+ setoption(fp, 'q');
+ if (*cp == '"')
+ {
+ ep = lp;
+ while (--ep > cp)
+ if (*ep == '"')
+ {
+ fp->quote = 1;
+ break;
+ }
+ else if (*ep != ' ' && *ep != '\t')
+ break;
+ }
+ }
+ }
+ again:
+ dp = buf;
+ ep = 0;
+ for (b = 1;; b = 0)
+ {
+ if (cp >= lp)
+ {
+ cp = 0;
+ break;
+ }
+ c = *cp++;
+ if (isoption(fp, 'o'))
+ {
+ if (c == '\\')
+ {
+ x = 0;
+ c = ' ';
+ cp--;
+ while (cp < lp)
+ {
+ if (*cp == '\\')
+ {
+ cp++;
+ if ((lp - cp) < 1)
+ {
+ c = '\\';
+ break;
+ }
+ if (*cp == 'n')
+ {
+ cp++;
+ c = '\n';
+ if ((lp - cp) > 2)
+ {
+ if (*cp == ']' || *cp == '@' && *(cp + 1) == '(')
+ {
+ *dp++ = '\\';
+ *dp++ = 'n';
+ c = *cp++;
+ break;
+ }
+ if (*cp == '\\' && *(cp + 1) == 'n')
+ {
+ cp += 2;
+ *dp++ = '\n';
+ break;
+ }
+ }
+ }
+ else if (*cp == 't' || *cp == ' ')
+ {
+ cp++;
+ x = 1;
+ c = ' ';
+ }
+ else
+ {
+ if (x && dp != buf && *(dp - 1) != ' ')
+ *dp++ = ' ';
+ *dp++ = '\\';
+ c = *cp++;
+ break;
+ }
+ }
+ else if (*cp == ' ' || *cp == '\t')
+ {
+ cp++;
+ c = ' ';
+ x = 1;
+ }
+ else
+ {
+ if (x && c != '\n' && dp != buf && *(dp - 1) != ' ')
+ *dp++ = ' ';
+ break;
+ }
+ }
+ if (c == '\n')
+ {
+ c = 0;
+ goto flush;
+ }
+ if (c == ' ' && (dp == buf || *(dp - 1) == ' '))
+ continue;
+ }
+ else if (c == '"')
+ {
+ if (b || cp >= lp)
+ {
+ if (fp->quote)
+ continue;
+ fp->section = 0;
+ }
+ }
+ else if (c == '\a')
+ {
+ *dp++ = '\\';
+ c = 'a';
+ }
+ else if (c == '\b')
+ {
+ *dp++ = '\\';
+ c = 'b';
+ }
+ else if (c == '\f')
+ {
+ *dp++ = '\\';
+ c = 'f';
+ }
+ else if (c == '\v')
+ {
+ *dp++ = '\\';
+ c = 'v';
+ }
+ else if (c == ']' && (cp >= lp || *cp != ':' && *cp != '#' && *cp != '!'))
+ {
+ if (cp < lp && *cp == ']')
+ {
+ cp++;
+ *dp++ = c;
+ }
+ else
+ {
+ fp->section = 1;
+ fp->retain = 0;
+ flush:
+ *dp++ = c;
+ *dp = 0;
+ split(fp, buf, 0);
+ outline(fp);
+ goto again;
+ }
+ }
+ else if (fp->section)
+ {
+ if (c == '[')
+ {
+ if (b)
+ fp->retain = 1;
+ else
+ {
+ cp--;
+ c = 0;
+ goto flush;
+ }
+ fp->section = 0;
+ }
+ else if (c == '{')
+ {
+ x = 1;
+ for (tp = cp; tp < lp; tp++)
+ {
+ if (*tp == '[' || *tp == '\n')
+ break;
+ if (*tp == ' ' || *tp == '\t' || *tp == '"')
+ continue;
+ if (*tp == '\\' && (lp - tp) > 1)
+ {
+ if (*++tp == 'n')
+ break;
+ if (*tp == 't' || *tp == '\n')
+ continue;
+ }
+ x = 0;
+ break;
+ }
+ if (x)
+ {
+ if (fp->endbuf > (fp->outbuf + fp->indent + 2*INDENT))
+ fp->nextdent = 2*INDENT;
+ goto flush;
+ }
+ else
+ fp->section = 0;
+ }
+ else if (c == '}')
+ {
+ if (fp->indent && (b || *(cp - 2) != 'f'))
+ {
+ if (b)
+ {
+ fp->indent -= 2*INDENT;
+ fp->endbuf += 2*INDENT;
+ }
+ else
+ {
+ cp--;
+ c = 0;
+ }
+ goto flush;
+ }
+ else
+ fp->section = 0;
+ }
+ else if (c == ' ' || c == '\t')
+ continue;
+ else
+ fp->section = 0;
+ }
+ else if (c == '?' && (cp >= lp || *cp != '?'))
+ {
+ if (fp->retain)
+ {
+ cp--;
+ while (cp < lp && *cp != ' ' && *cp != '\t' && *cp != ']' && dp < &buf[sizeof(buf)-3])
+ *dp++ = *cp++;
+ if (cp < lp && (*cp == ' ' || *cp == '\t'))
+ *dp++ = *cp++;
+ *dp = 0;
+ split(fp, buf, 0);
+ dp = buf;
+ ep = 0;
+ fp->retain = 0;
+ if (fp->outp >= fp->endbuf)
+ outline(fp);
+ continue;
+ }
+ }
+ else if (c == ' ' || c == '\t')
+ for (c = ' '; *cp == ' ' || *cp == '\t'; cp++);
+ }
+ else if (c == '\b')
+ {
+ if (dp > buf)
+ {
+ dp--;
+ if (ep)
+ ep--;
+ }
+ continue;
+ }
+ else if (c == '\t')
+ {
+ /*
+ * expand tabs
+ */
+
+ if (!ep)
+ ep = dp;
+ c = isoption(fp, 'o') ? 1 : TABSZ - (dp - buf) % TABSZ;
+ if (dp >= &buf[sizeof(buf) - c - 3])
+ {
+ cp--;
+ break;
+ }
+ while (c-- > 0)
+ *dp++ = ' ';
+ continue;
+ }
+ else if (!isprint(c))
+ continue;
+ if (dp >= &buf[sizeof(buf) - 3])
+ {
+ tp = dp;
+ while (--tp > buf)
+ if (isspace(*tp))
+ {
+ cp -= dp - tp;
+ dp = tp;
+ break;
+ }
+ ep = 0;
+ break;
+ }
+ if (c != ' ')
+ ep = 0;
+ else if (!ep)
+ ep = dp;
+ *dp++ = c;
+ }
+ if (ep)
+ *ep = 0;
+ else
+ *dp = 0;
+ split(fp, buf, splice);
+ }
+ return 0;
+}
+
+int
+b_fmt(int argc, char** argv, Shbltin_t* context)
+{
+ register int n;
+ char* cp;
+ Fmt_t fmt;
+ char outbuf[8 * 1024];
+
+ fmt.flags = 0;
+ fmt.out = sfstdout;
+ fmt.outbuf = outbuf;
+ fmt.outp = 0;
+ fmt.endbuf = &outbuf[72];
+ fmt.indent = 0;
+ fmt.nextdent = 0;
+ fmt.nwords = 0;
+ fmt.prefix = 0;
+ fmt.quote = 0;
+ fmt.retain = 0;
+ fmt.section = 1;
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (n = optget(argv, usage))
+ {
+ case 'c':
+ case 'o':
+ case 's':
+ case 'u':
+ setoption(&fmt, n);
+ continue;
+ case 'w':
+ if (opt_info.num < TABSZ || opt_info.num>= sizeof(outbuf))
+ error(2, "width out of range");
+ fmt.endbuf = &outbuf[opt_info.num];
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if (isoption(&fmt, 'o'))
+ setoption(&fmt, 'c');
+ if (isoption(&fmt, 's'))
+ clroption(&fmt, 'u');
+ if (cp = *argv)
+ argv++;
+ do {
+ if (!cp || streq(cp, "-"))
+ fmt.in = sfstdin;
+ else if (!(fmt.in = sfopen(NiL, cp, "r")))
+ {
+ error(ERROR_system(0), "%s: cannot open", cp);
+ error_info.errors = 1;
+ continue;
+ }
+ dofmt(&fmt);
+ if (fmt.in != sfstdin)
+ sfclose(fmt.in);
+ } while (cp = *argv++);
+ outline(&fmt);
+ if (sfsync(sfstdout))
+ error(ERROR_system(0), "write error");
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/fold.c b/src/lib/libcmd/fold.c
new file mode 100644
index 0000000..7e94ffd
--- /dev/null
+++ b/src/lib/libcmd/fold.c
@@ -0,0 +1,240 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * fold
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: fold (AT&T Research) 2004-11-18 $\n]"
+USAGE_LICENSE
+"[+NAME?fold - fold lines]"
+"[+DESCRIPTION?\bfold\b is a filter that folds lines from its input, "
+ "breaking the lines to have a maximum of \awidth\a column "
+ "positions (or bytes if the \b-b\b option is specified). Lines "
+ "are broken by the insertion of a newline character such that "
+ "each output line is the maximum width possible that does not "
+ "exceed the specified number of column positions, (or bytes). A line "
+ "will not be broken in the middle of a character.] "
+"[+?Unless the \b-b\b option is specified, the following will be treated "
+ "specially:]{"
+ "[+carriage-return?The current count of line width will be set "
+ "to zero. \bfold\b will not insert a newline immediately "
+ "before or after a carriage-return.]"
+ "[+backspace?If positive, the current count of line width will be "
+ "decremented by one. \bfold\b will not insert a newline "
+ "immediately before or after a backspace.]"
+ "[+tab?Each tab character encountered will advance the column "
+ "position to the next tab stop. Tab stops are at each "
+ "column position \an\a, where \an\a modulo 8 equals 1.]"
+ "}"
+"[+?If no \afile\a is given, or if the \afile\a is \b-\b, \bfold\b "
+ "reads from standard input. The start of the file is defined "
+ "as the current offset.]"
+
+"[b:bytes?Count bytes rather than columns so that each carriage-return, "
+ "backspace, and tab counts as 1.]"
+"[c:continue?Emit \atext\a at line splits.]:[text:='\\n']"
+"[d:delimiter?Break at \adelim\a boundaries.]:[delim]"
+"[s:spaces?Break at word boundaries. If the line contains any blanks, "
+ "(spaces or tabs), within the first \awidth\a column positions or "
+ "bytes, the line is broken after the last blank meeting the "
+ "\awidth\a constraint.]"
+"[w:width]#[width:=80?Use a maximum line length of \awidth\a columns "
+ "instead of the default.]"
+"\n"
+"\n[file ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All files processed successfully.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bpaste\b(1)]"
+;
+
+
+#include <cmd.h>
+
+#define WIDTH 80
+#define TABSIZE 8
+
+#define T_EOF 1
+#define T_NL 2
+#define T_BS 3
+#define T_TAB 4
+#define T_SP 5
+#define T_RET 6
+
+static void fold(Sfio_t *in, Sfio_t *out, register int width, const char *cont, size_t contsize, char *cols)
+{
+ register char *cp, *first;
+ register int n, col=0, x=0;
+ register char *last_space=0;
+ cols[0] = 0;
+ for (;;)
+ {
+ if (!(cp = sfgetr(in,'\n',0)))
+ {
+ if (!(cp = sfgetr(in,'\n',-1)) || (n = sfvalue(in)) <= 0)
+ break;
+ x = cp[--n];
+ cp[n] = '\n';
+ }
+ /* special case -b since no column adjustment is needed */
+ if(cols['\b']==0 && (n=sfvalue(in))<=width)
+ {
+ sfwrite(out,cp,n);
+ continue;
+ }
+ first = cp;
+ col = 0;
+ last_space = 0;
+ for(;;)
+ {
+ while((n=cols[*(unsigned char*)cp++])==0);
+ while((cp-first) > (width-col))
+ {
+ if(last_space)
+ col = last_space - first;
+ else
+ col = width-col;
+ sfwrite(out,first,col);
+ first += col;
+ col = 0;
+ last_space = 0;
+ if(cp>first+1 || (n!=T_NL && n!=T_BS))
+ sfwrite(out, cont, contsize);
+ }
+ switch(n)
+ {
+ case T_NL:
+ if(x)
+ *(cp-1) = x;
+ break;
+ case T_RET:
+ col = 0;
+ continue;
+ case T_BS:
+ if((cp+(--col)-first)>0)
+ col--;
+ continue;
+ case T_TAB:
+ n = (TABSIZE-1) - (cp+col-1-first)&(TABSIZE-1);
+ col +=n;
+ if((cp-first) > (width-col))
+ {
+ sfwrite(out,first,(--cp)-first);
+ sfwrite(out, cont, contsize);
+ first = cp;
+ col = TABSIZE-1;
+ last_space = 0;
+ continue;
+ }
+ if(cols[' '])
+ last_space = cp;
+ continue;
+ case T_SP:
+ last_space = cp;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ sfwrite(out,first,cp-first);
+ }
+}
+
+int
+b_fold(int argc, char** argv, Shbltin_t* context)
+{
+ register int n, width=WIDTH;
+ register Sfio_t *fp;
+ register char *cp;
+ char *cont="\n";
+ size_t contsize = 1;
+ char cols[1<<CHAR_BIT];
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ memset(cols, 0, sizeof(cols));
+ cols['\t'] = T_TAB;
+ cols['\b'] = T_BS;
+ cols['\n'] = T_NL;
+ cols['\r'] = T_RET;
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'b':
+ cols['\r'] = cols['\b'] = 0;
+ cols['\t'] = cols[' '];
+ continue;
+ case 'c':
+ contsize = stresc(cont = strdup(opt_info.arg));
+ continue;
+ case 'd':
+ if (n = *opt_info.arg)
+ cols[n] = T_SP;
+ continue;
+ case 's':
+ cols[' '] = T_SP;
+ if(cols['\t']==0)
+ cols['\t'] = T_SP;
+ continue;
+ case 'w':
+ if ((width = opt_info.num) <= 0)
+ error(2, "%d: width must be positive", opt_info.num);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if(error_info.errors)
+ error(ERROR_usage(2),"%s", optusage(NiL));
+ if(cp = *argv)
+ argv++;
+ do
+ {
+ if(!cp || streq(cp,"-"))
+ fp = sfstdin;
+ else if(!(fp = sfopen(NiL,cp,"r")))
+ {
+ error(ERROR_system(0),"%s: cannot open",cp);
+ error_info.errors = 1;
+ continue;
+ }
+ fold(fp,sfstdout,width,cont,contsize,cols);
+ if(fp!=sfstdin)
+ sfclose(fp);
+ }
+ while(cp= *argv++);
+ return(error_info.errors);
+}
diff --git a/src/lib/libcmd/fts_fix.c b/src/lib/libcmd/fts_fix.c
new file mode 100644
index 0000000..61b61ba
--- /dev/null
+++ b/src/lib/libcmd/fts_fix.c
@@ -0,0 +1,57 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * -lcmd specific workaround to handle
+ * fts_namelen
+ * fts_pathlen
+ * fts_level
+ * changing from [unsigned] short bit to [s]size_t
+ *
+ * ksh (or any other main application) that pulls in -lcmd
+ * at runtime may result in old -last running with new -lcmd
+ * which is not a good situation (tm)
+ *
+ * probably safe to drop after 20150101
+ */
+
+#include <ast.h>
+#include <fts_fix.h>
+
+#undef fts_read
+
+FTSENT*
+_fts_read(FTS* fts)
+{
+ FTSENT* oe;
+
+ static FTSENT* ne;
+
+ if ((oe = _ast_fts_read(fts)) && ast.version < 20100102L && (ne || (ne = newof(0, FTSENT, 1, 0))))
+ {
+ *ne = *oe;
+ oe = ne;
+ ne->fts_namelen = ne->_fts_namelen;
+ ne->fts_pathlen = ne->_fts_pathlen;
+ ne->fts_level = ne->_fts_level;
+ }
+ return oe;
+}
diff --git a/src/lib/libcmd/fts_fix.h b/src/lib/libcmd/fts_fix.h
new file mode 100644
index 0000000..96f4448
--- /dev/null
+++ b/src/lib/libcmd/fts_fix.h
@@ -0,0 +1,49 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * -lcmd specific workaround to handle
+ * fts_namelen
+ * fts_pathlen
+ * fts_level
+ * changing from [unsigned] short bit to [s]size_t
+ *
+ * ksh (or any other main application) that pulls in -lcmd
+ * at runtime may result in old -last running with new -lcmd
+ * which is not a good situation (tm)
+ */
+
+#ifndef _FTS_FIX_H
+#define _FTS_FIX_H 1
+
+#include <fts.h>
+
+#ifdef fts_read
+#undef fts_read
+#else
+#define _ast_fts_read fts_read
+#endif
+
+#define fts_read _fts_read
+
+extern FTSENT* fts_read(FTS*);
+
+#endif
diff --git a/src/lib/libcmd/getconf.c b/src/lib/libcmd/getconf.c
new file mode 100644
index 0000000..e151f62
--- /dev/null
+++ b/src/lib/libcmd/getconf.c
@@ -0,0 +1,396 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * getconf - get configuration values
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: getconf (AT&T Research) 2008-04-24 $\n]"
+USAGE_LICENSE
+"[+NAME?getconf - get configuration values]"
+"[+DESCRIPTION?\bgetconf\b displays the system configuration value for"
+" \aname\a. If \aname\a is a filesystem specific variable then"
+" the value is determined relative to \apath\a or the current"
+" directory if \apath\a is omitted. If \avalue\a is specified then"
+" \bgetconf\b attempts to change the process local value to \avalue\a."
+" \b-\b may be used in place of \apath\a when it is not relevant."
+" If \apath\a is \b=\b then the the \avalue\a is cached and used"
+" for subsequent tests in the calling and all child processes."
+" Only \bwritable\b variables may be set; \breadonly\b variables"
+" cannot be changed.]"
+"[+?The current value for \aname\a is written to the standard output. If"
+" \aname\a is valid but undefined then \bundefined\b is written to"
+" the standard output. If \aname\a is invalid or an error occurs in"
+" determining its value, then a diagnostic written to the standard error"
+" and \bgetconf\b exits with a non-zero exit status.]"
+"[+?More than one variable may be set or queried by providing the \aname\a"
+" \apath\a \avalue\a 3-tuple for each variable, specifying \b-\b for"
+" \avalue\a when querying.]"
+"[+?If no operands are specified then all known variables are written in"
+" \aname\a=\avalue\a form to the standard output, one per line."
+" Only one of \b--call\b, \b--name\b or \b--standard\b may be specified.]"
+"[+?This implementation uses the \bastgetconf\b(3) string interface to the native"
+" \bsysconf\b(2), \bconfstr\b(2), \bpathconf\b(2), and \bsysinfo\b(2)"
+" system calls. If \bgetconf\b on \b$PATH\b is not the default native"
+" \bgetconf\b, named by \b$(getconf GETCONF)\b, then \bastgetconf\b(3)"
+" checks only \bast\b specific extensions and the native system calls;"
+" invalid options and/or names not supported by \bastgetconf\b(3) cause"
+" the \bgetconf\b on \b$PATH\b to be executed.]"
+
+"[a:all?Call the native \bgetconf\b(1) with option \b-a\b.]"
+"[b:base?List base variable name sans call and standard prefixes.]"
+"[c:call?Display variables with call prefix that matches \aRE\a. The call"
+" prefixes are:]:[RE]{"
+" [+CS?\bconfstr\b(2)]"
+" [+PC?\bpathconf\b(2)]"
+" [+SC?\bsysconf\b(2)]"
+" [+SI?\bsysinfo\b(2)]"
+" [+XX?Constant value.]"
+"}"
+"[d:defined?Only display defined values when no operands are specified.]"
+"[l:lowercase?List variable names in lower case.]"
+"[n:name?Display variables with name that match \aRE\a.]:[RE]"
+"[p:portable?Display the named \bwritable\b variables and values in a form that"
+" can be directly executed by \bsh\b(1) to set the values. If \aname\a"
+" is omitted then all \bwritable\b variables are listed.]"
+"[q:quote?\"...\" quote values.]"
+"[r:readonly?Display the named \breadonly\b variables in \aname\a=\avalue\a form."
+" If \aname\a is omitted then all \breadonly\b variables are listed.]"
+"[s:standard?Display variables with standard prefix that matches \aRE\a."
+" Use the \b--table\b option to view all standard prefixes, including"
+" local additions. The standard prefixes available on all systems"
+" are:]:[RE]{"
+" [+AES]"
+" [+AST]"
+" [+C]"
+" [+GNU]"
+" [+POSIX]"
+" [+SVID]"
+" [+XBS5]"
+" [+XOPEN]"
+" [+XPG]"
+"}"
+"[t:table?Display the internal table that contains the name, standard,"
+" standard section, and system call symbol prefix for each variable.]"
+"[w:writable?Display the named \bwritable\b variables in \aname\a=\avalue\a"
+" form. If \aname\a is omitted then all \bwritable\b variables are"
+" listed.]"
+"[v:specification?Call the native \bgetconf\b(1) with option"
+" \b-v\b \aname\a.]:[name]"
+
+"\n"
+"\n[ name [ path [ value ] ] ... ]\n"
+"\n"
+
+"[+ENVIRONMENT]{"
+" [+_AST_FEATURES?Process local writable values that are different from"
+" the default are stored in the \b_AST_FEATURES\b environment"
+" variable. The \b_AST_FEATURES\b value is a space-separated"
+" list of \aname\a \apath\a \avalue\a 3-tuples, where"
+" \aname\a is the system configuration name, \apath\a is the"
+" corresponding path, \b-\b if no path is applicable, and"
+" \avalue\a is the system configuration value.]"
+"}"
+"[+SEE ALSO?\bpathchk\b(1), \bconfstr\b(2), \bpathconf\b(2),"
+" \bsysconf\b(2), \bastgetconf\b(3)]"
+;
+
+#include <cmd.h>
+#include <proc.h>
+#include <ls.h>
+
+typedef struct Path_s
+{
+ const char* path;
+ int len;
+} Path_t;
+
+int
+b_getconf(int argc, char** argv, Shbltin_t* context)
+{
+ register char* name;
+ register char* path;
+ register char* value;
+ register const char* s;
+ register const char* t;
+ char* pattern;
+ char* native;
+ char* cmd;
+ Path_t* e;
+ Path_t* p;
+ int flags;
+ int n;
+ int i;
+ int m;
+ int q;
+ char** oargv;
+ char buf[PATH_MAX];
+ Path_t std[64];
+ struct stat st0;
+ struct stat st1;
+
+ static const char empty[] = "-";
+ static const Path_t equiv[] = { { "/bin", 4 }, { "/usr/bin", 8 } };
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ oargv = argv;
+ if (*(native = astconf("GETCONF", NiL, NiL)) != '/')
+ native = 0;
+ flags = 0;
+ name = 0;
+ pattern = 0;
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'a':
+ if (native)
+ goto defer;
+ continue;
+ case 'b':
+ flags |= ASTCONF_base;
+ continue;
+ case 'c':
+ flags |= ASTCONF_matchcall;
+ pattern = opt_info.arg;
+ continue;
+ case 'd':
+ flags |= ASTCONF_defined;
+ continue;
+ case 'l':
+ flags |= ASTCONF_lower;
+ continue;
+ case 'n':
+ flags |= ASTCONF_matchname;
+ pattern = opt_info.arg;
+ continue;
+ case 'p':
+ flags |= ASTCONF_parse;
+ continue;
+ case 'q':
+ flags |= ASTCONF_quote;
+ continue;
+ case 'r':
+ flags |= ASTCONF_read;
+ continue;
+ case 's':
+ flags |= ASTCONF_matchstandard;
+ pattern = opt_info.arg;
+ continue;
+ case 't':
+ flags |= ASTCONF_table;
+ continue;
+ case 'v':
+ if (native)
+ goto defer;
+ continue;
+ case 'w':
+ flags |= ASTCONF_write;
+ continue;
+ case ':':
+ if (native)
+ goto defer;
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (!(name = *argv))
+ path = 0;
+ else if (streq(name, empty))
+ {
+ name = 0;
+ if (path = *++argv)
+ {
+ argv++;
+ if (streq(path, empty))
+ path = 0;
+ }
+ }
+ if (error_info.errors || !name && *argv)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if (!name)
+ astconflist(sfstdout, path, flags, pattern);
+ else
+ {
+ flags = native ? (ASTCONF_system|ASTCONF_error) : 0;
+ do
+ {
+ if (!(path = *++argv))
+ value = 0;
+ else
+ {
+ if (streq(path, empty))
+ {
+ path = 0;
+ flags = 0;
+ }
+ if ((value = *++argv) && (streq(value, empty)))
+ {
+ value = 0;
+ flags = 0;
+ }
+ }
+ s = astgetconf(name, path, value, flags, errorf);
+ if (error_info.errors)
+ break;
+ if (!s)
+ goto defer;
+ if (!value)
+ {
+ if (flags & ASTCONF_write)
+ {
+ sfputr(sfstdout, name, ' ');
+ sfputr(sfstdout, path ? path : empty, ' ');
+ }
+ sfputr(sfstdout, s, '\n');
+ }
+ } while (*argv && (name = *++argv));
+ }
+ return error_info.errors != 0;
+
+ defer:
+
+ /*
+ * defer to argv[0] if absolute and it exists
+ */
+
+ if ((cmd = oargv[0]) && *cmd == '/' && !access(cmd, X_OK))
+ goto found;
+
+ /*
+ * defer to the first getconf on $PATH that is also on the standard PATH
+ */
+
+ e = std;
+ s = astconf("PATH", NiL, NiL);
+ q = !stat(equiv[0].path, &st0) && !stat(equiv[1].path, &st1) && st0.st_ino == st1.st_ino && st0.st_dev == st1.st_dev;
+ m = 0;
+ do
+ {
+ for (t = s; *s && *s != ':'; s++);
+ if ((n = s - t) && *t == '/')
+ {
+ if (q)
+ for (i = 0; i < 2; i++)
+ if (n == equiv[i].len && !strncmp(t, equiv[i].path, n))
+ {
+ if (m & (i+1))
+ t = 0;
+ else
+ {
+ m |= (i+1);
+ if (!(m & (!i+1)))
+ {
+ m |= (!i+1);
+ e->path = t;
+ e->len = n;
+ e++;
+ if (e >= &std[elementsof(std)])
+ break;
+ t = equiv[!i].path;
+ n = equiv[!i].len;
+ }
+ }
+ }
+ if (t)
+ {
+ e->path = t;
+ e->len = n;
+ e++;
+ }
+ }
+ while (*s == ':')
+ s++;
+ } while (*s && e < &std[elementsof(std)]);
+ if (e < &std[elementsof(std)])
+ {
+ e->len = strlen(e->path = "/usr/sbin");
+ if (++e < &std[elementsof(std)])
+ {
+ e->len = strlen(e->path = "/sbin");
+ e++;
+ }
+ }
+ if (s = getenv("PATH"))
+ do
+ {
+ for (t = s; *s && *s != ':'; s++);
+ if ((n = s - t) && *t == '/')
+ {
+ for (p = std; p < e; p++)
+ if (p->len == n && !strncmp(t, p->path, n))
+ {
+ sfsprintf(buf, sizeof(buf), "%-*.*s/%s", n, n, t, error_info.id);
+ if (!access(buf, X_OK))
+ {
+ cmd = buf;
+ goto found;
+ }
+ }
+ }
+ while (*s == ':')
+ s++;
+ } while (*s);
+
+ /*
+ * defer to the first getconf on the standard PATH
+ */
+
+ for (p = std; p < e; p++)
+ {
+ sfsprintf(buf, sizeof(buf), "%-*.*s/%s", p->len, p->len, p->path, error_info.id);
+ if (!access(buf, X_OK))
+ {
+ cmd = buf;
+ goto found;
+ }
+ }
+
+ /*
+ * out of deferrals
+ */
+
+ if (name)
+ error(4, "%s: unknown name -- no native getconf(1) to defer to", name);
+ else
+ error(4, "no native getconf(1) to defer to");
+ return 2;
+
+ found:
+
+ /*
+ * don't blame us for crappy diagnostics
+ */
+
+ oargv[0] = cmd;
+ if ((n = sh_run(context, argc, oargv)) >= EXIT_NOEXEC)
+ error(ERROR_SYSTEM|2, "%s: exec error [%d]", cmd, n);
+ return n;
+}
diff --git a/src/lib/libcmd/head.c b/src/lib/libcmd/head.c
new file mode 100644
index 0000000..6f42b5a
--- /dev/null
+++ b/src/lib/libcmd/head.c
@@ -0,0 +1,150 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * output the beginning portion of one or more files
+ */
+
+static const char usage[] =
+"[-n?\n@(#)$Id: head (AT&T Research) 2012-01-01 $\n]"
+USAGE_LICENSE
+"[+NAME?head - output beginning portion of one or more files ]"
+"[+DESCRIPTION?\bhead\b copies one or more input files to standard "
+ "output stopping at a designated point for each file or to the end of "
+ "the file whichever comes first. Copying ends at the point indicated by "
+ "the options. By default a header of the form \b==> \b\afilename\a\b "
+ "<==\b is output before all but the first file but this can be changed "
+ "with the \b-q\b and \b-v\b options.]"
+"[+?If no \afile\a is given, or if the \afile\a is \b-\b, \bhead\b "
+ "copies from standard input starting at the current location.]"
+"[+?The option argument for \b-c\b, and \b-s\b can optionally be "
+ "followed by one of the following characters to specify a different unit "
+ "other than a single byte:]"
+ "{"
+ "[+b?512 bytes.]"
+ "[+k?1-killobyte.]"
+ "[+m?1-megabyte.]"
+ "}"
+"[+?For backwards compatibility, \b-\b\anumber\a is equivalent to \b-n\b "
+ "\anumber\a.]"
+"[n:lines?Copy \alines\a lines from each file.]#[lines:=10]"
+"[c:bytes?Copy \achars\a bytes from each file.]#[chars]"
+"[q:quiet|silent?Never ouput filename headers.]"
+"[s:skip?Skip \askip\a characters or lines from each file before "
+ "copying.]#[skip]"
+"[v:verbose?Always ouput filename headers.]"
+ "\n\n"
+"[ file ... ]"
+ "\n\n"
+"[+EXIT STATUS?]"
+ "{"
+ "[+0?All files copied successfully.]"
+ "[+>0?One or more files did not copy.]"
+ "}"
+"[+SEE ALSO?\bcat\b(1), \btail\b(1)]"
+;
+
+#include <cmd.h>
+
+int
+b_head(int argc, register char** argv, Shbltin_t* context)
+{
+ static const char header_fmt[] = "\n==> %s <==\n";
+
+ register Sfio_t* fp;
+ register char* cp;
+ register off_t keep = 10;
+ register off_t skip = 0;
+ register int delim = '\n';
+ int header = 1;
+ char* format = (char*)header_fmt+1;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'c':
+ delim = -1;
+ /*FALLTHROUGH*/
+ case 'n':
+ if (opt_info.offset && argv[opt_info.index][opt_info.offset] == 'c')
+ {
+ delim = -1;
+ opt_info.offset++;
+ }
+ if ((keep = opt_info.number) <=0)
+ error(2, "%s: %I*d: positive numeric option argument expected", opt_info.name, sizeof(keep), keep);
+ continue;
+ case 'q':
+ header = argc;
+ continue;
+ case 'v':
+ header = 0;
+ continue;
+ case 's':
+ skip = opt_info.number;
+ continue;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if (error_info.errors)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if (cp = *argv)
+ argv++;
+ do
+ {
+ if (!cp || streq(cp, "-"))
+ {
+ cp = "/dev/stdin";
+ fp = sfstdin;
+ sfset(fp, SF_SHARE, 1);
+ }
+ else if (!(fp = sfopen(NiL, cp, "r")))
+ {
+ error(ERROR_system(0), "%s: cannot open", cp);
+ continue;
+ }
+ if (argc > header)
+ sfprintf(sfstdout, format, cp);
+ format = (char*)header_fmt;
+ if (skip > 0)
+ sfmove(fp, NiL, skip, delim);
+ if (sfmove(fp, sfstdout, keep, delim) < 0 && errno != EPIPE && errno != EINTR)
+ error(ERROR_system(0), "%s: read error", cp);
+ if (fp != sfstdin)
+ sfclose(fp);
+ } while (cp = *argv++);
+ if (sfsync(sfstdout))
+ error(ERROR_system(0), "write error");
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/id.c b/src/lib/libcmd/id.c
new file mode 100644
index 0000000..aa0a65b
--- /dev/null
+++ b/src/lib/libcmd/id.c
@@ -0,0 +1,472 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * id
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: id (AT&T Research) 2004-06-11 $\n]"
+USAGE_LICENSE
+"[+NAME?id - return user identity]"
+"[+DESCRIPTION?If no \auser\a operand is specified \bid\b writes user and "
+ "group IDs and the corresponding user and group names of the "
+ "invoking process to standard output. If the effective and "
+ "real IDs do not match, both are written. Any supplementary "
+ "groups the current process belongs to will also be written.]"
+"[+?If a \auser\a operand is specified and the process has permission, "
+ "the user and group IDs and any supplementary group IDs of the "
+ "selected user will be written to standard output.]"
+"[+?If any options are specified, then only a portion of the information "
+ "is written.]"
+"[n:name?Write the name instead of the numeric ID.]"
+"[r:real?Writes real ID instead of the effective ID.]"
+"[[a?This option is ignored.]"
+"[g:group?Writes only the group ID.]"
+"[u:user?Writes only the user ID.]"
+"[G:groups?Writes only the supplementary group IDs.]"
+"[s:fair-share?Writes fair share scheduler IDs and groups on systems that "
+ "support fair share scheduling.]"
+"\n"
+"\n[user]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful completion.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2)]"
+;
+
+#include <cmd.h>
+
+#include "FEATURE/ids"
+
+#include <grp.h>
+#include <pwd.h>
+
+#if _lib_fsid
+#if _lib_getfsgid && ( _sys_fss || _hdr_fsg )
+#define fss_grp fs_grp
+#define fss_id fs_id
+#define fss_mem fs_mem
+#define fss_passwd fs_passwd
+#define fss_shares fs_shares
+#if _sys_fss
+#include <sys/fss.h>
+#endif
+#if _hdr_fsg
+#include <fsg.h>
+#endif
+#if !_lib_isfsg && !defined(isfsg)
+#define isfsg(p) (!(p)->fs_id&&!(p)->fs_shares&&(!(p)->fs_passwd||!*(p)->fs_passwd))
+#endif
+#else
+#undef _lib_fsid
+#endif
+#endif
+
+#define power2(n) (!((n)&((n)-1)))
+
+#define GG_FLAG (1<<0)
+#define G_FLAG (1<<1)
+#define N_FLAG (1<<2)
+#define R_FLAG (1<<3)
+#define U_FLAG (1<<4)
+#define S_FLAG (1<<5)
+#define O_FLAG (1<<6)
+#define X_FLAG (1<<7)
+
+#if _lib_fsid
+static void
+getfsids(Sfio_t* sp, const char* name, int flags, register int lastchar)
+{
+ register struct fsg* fs;
+ register char* s;
+ register char** p;
+ char** x;
+
+ if (lastchar)
+ {
+ if (flags & O_FLAG) flags = 1;
+ else flags = 0;
+ }
+ else if (flags & N_FLAG) flags = 1;
+ else flags = -1;
+ setfsgent();
+ while (fs = getfsgnam(name))
+ if (!isfsg(fs))
+ {
+ if (p = fs->fs_mem)
+ {
+ if (flags > 0) x = 0;
+ else
+ {
+ register char** q;
+ register char* t;
+ register int n;
+
+ n = 0;
+ q = p;
+ while (s = *q++)
+ n += strlen(s) + 1;
+ if (!(x = newof(0, char*, q - p, n)))
+ break;
+ s = (char*)(x + (q - p));
+ q = x;
+ while (t = *p++)
+ {
+ *q++ = s;
+ while (*s++ = *t++);
+ }
+ *q = 0;
+ p = x;
+ }
+ while (s = *p++)
+ {
+ if (lastchar == '=')
+ {
+ lastchar = ',';
+ sfputr(sp, " fsid=", -1);
+ }
+ else if (!lastchar) lastchar = ' ';
+ else sfputc(sp, lastchar);
+ if (flags > 0) sfprintf(sp, "%s", s);
+ else
+ {
+ setfsgent();
+ while (fs = getfsgnam(s))
+ if (isfsg(fs))
+ {
+ if (flags < 0) sfprintf(sp, "%u", fs->fs_id);
+ else sfprintf(sp, "%u(%s)", fs->fs_id, s);
+ break;
+ }
+ }
+ }
+ if (x) free(x);
+ }
+ break;
+ }
+ endfsgent();
+ if (lastchar == ' ') sfputc(sp, '\n');
+}
+#endif
+
+static void
+putid(Sfio_t* sp, int flags, const char* label, const char* name, long number)
+{
+ sfprintf(sp, "%s=", label);
+ if (flags & O_FLAG)
+ {
+ if (name) sfputr(sp, name, -1);
+ else sfprintf(sp, "%lu", number);
+ }
+ else
+ {
+ sfprintf(sp, "%u", number);
+ if (name) sfprintf(sp, "(%s)", name);
+ }
+}
+
+static int
+getids(Sfio_t* sp, const char* name, register int flags)
+{
+ register struct passwd* pw;
+ register struct group* grp;
+ register int i;
+ register int j;
+ register int k;
+#if _lib_fsid
+ register struct fsg* fs;
+ const char* fs_name;
+ int fs_id;
+#endif
+ char** p;
+ char* s;
+ int lastchar;
+ int ngroups = 0;
+ const char* gname;
+ uid_t user;
+ uid_t euid;
+ gid_t group;
+ gid_t egid;
+
+ static gid_t* groups;
+
+ if (flags & GG_FLAG)
+ {
+ static int maxgroups;
+
+ /*
+ * get supplemental groups if required
+ */
+
+ if (!maxgroups)
+ {
+ /*
+ * first time
+ */
+
+ if ((maxgroups = getgroups(0, groups)) <= 0)
+ maxgroups = NGROUPS_MAX;
+ if (!(groups = newof(0, gid_t, maxgroups + 1, 0)))
+ error(ERROR_exit(1), "out of space [group array]");
+ }
+ ngroups = getgroups(maxgroups, groups);
+ for (i = j = 0; i < ngroups; i++)
+ {
+ for (k = 0; k < j && groups[k] != groups[i]; k++);
+ if (k >= j) groups[j++] = groups[i];
+ }
+ ngroups = j;
+ }
+ if (name)
+ {
+ flags |= X_FLAG;
+ if (!(flags & N_FLAG) || (flags & (G_FLAG|GG_FLAG)))
+ {
+ if (!(pw = getpwnam(name)))
+ {
+ user = strtol(name, &s, 0);
+ if (*s || !(pw = getpwuid(user)))
+ error(ERROR_exit(1), "%s: name not found", name);
+ name = pw->pw_name;
+ }
+ user = pw->pw_uid;
+ group = pw->pw_gid;
+ }
+#if _lib_fsid
+ if (!(flags & N_FLAG) || (flags & S_FLAG))
+ {
+ setfsgent();
+ do
+ {
+ if (!(fs = getfsgnam(name)))
+ error(ERROR_exit(1), "%u: fss name not found", name);
+ } while (isfsg(fs));
+ fs_id = fs->fs_id;
+ }
+#endif
+ }
+ else
+ {
+ if (flags & G_FLAG)
+ group = (flags & R_FLAG) ? getgid() : getegid();
+ if (flags & (GG_FLAG|N_FLAG|U_FLAG))
+ user = (flags & R_FLAG) ? getuid() : geteuid();
+#if _lib_fsid
+ if (flags & S_FLAG)
+ fs_id = fsid(0);
+#endif
+ if (flags & N_FLAG)
+ name = (pw = getpwuid(user)) ? pw->pw_name : (char*)0;
+ }
+ if (ngroups == 1 && groups[0] == group)
+ ngroups = 0;
+ if ((flags & N_FLAG) && (flags & G_FLAG))
+ gname = (grp = getgrgid(group)) ? grp->gr_name : (char*)0;
+#if _lib_fsid
+ if ((flags & N_FLAG) && (flags & S_FLAG))
+ {
+ setfsgent();
+ fs_name = (fs = getfsgid(fs_id)) ? fs->fs_grp : (char*)0;
+ }
+#endif
+ if ((flags & (U_FLAG|G_FLAG|S_FLAG)) == (U_FLAG|G_FLAG|S_FLAG))
+ {
+ putid(sp, flags, "uid", name, user);
+ putid(sp, flags, " gid", gname, group);
+ if ((flags & X_FLAG) && name)
+ {
+#if _lib_getgrent
+#if _lib_setgrent
+ setgrent();
+#endif
+ lastchar = '=';
+ while (grp = getgrent())
+ if (p = grp->gr_mem)
+ while (s = *p++)
+ if (streq(s, name))
+ {
+ if (lastchar == '=')
+ sfputr(sp, " groups", -1);
+ sfputc(sp, lastchar);
+ lastchar = ',';
+ if (flags & O_FLAG)
+ sfprintf(sp, "%s", grp->gr_name);
+ else sfprintf(sp, "%u(%s)", grp->gr_gid, grp->gr_name);
+ }
+#if _lib_endgrent
+ endgrent();
+#endif
+#endif
+#if _lib_fsid
+ getfsids(sp, name, flags, '=');
+#endif
+ }
+ else
+ {
+ if ((euid = geteuid()) != user)
+ putid(sp, flags, " euid", (pw = getpwuid(euid)) ? pw->pw_name : (char*)0, euid);
+ if ((egid = getegid()) != group)
+ putid(sp, flags, " egid", (grp = getgrgid(egid)) ? grp->gr_name : (char*)0, egid);
+ if (ngroups > 0)
+ {
+ sfputr(sp, " groups", -1);
+ lastchar = '=';
+ for (i = 0; i < ngroups; i++)
+ {
+ group = groups[i];
+ sfputc(sp, lastchar);
+ if (grp = getgrgid(group))
+ {
+ if (flags & O_FLAG) sfprintf(sp, "%s", grp->gr_name);
+ else sfprintf(sp, "%u(%s)", group, grp->gr_name);
+ }
+ else sfprintf(sp, "%u", group);
+ lastchar = ',';
+ }
+ }
+#if _lib_fsid
+ putid(sp, flags, " fsid", fs_name, fs_id);
+#endif
+ }
+ sfputc(sp,'\n');
+ return(0);
+ }
+ if (flags & U_FLAG)
+ {
+ if ((flags & N_FLAG) && name) sfputr(sp, name, '\n');
+ else sfprintf(sp, "%u\n", user);
+ }
+ else if (flags & G_FLAG)
+ {
+ if ((flags & N_FLAG) && gname) sfputr(sp, gname, '\n');
+ else sfprintf(sp, "%u\n", group);
+ }
+ else if (flags & GG_FLAG)
+ {
+ if ((flags & X_FLAG) && name)
+ {
+#if _lib_getgrent
+#if _lib_setgrent
+ setgrent();
+#endif
+ i = 0;
+ while (grp = getgrent())
+ if (p = grp->gr_mem)
+ while (s = *p++)
+ if (streq(s, name))
+ {
+ if (i++) sfputc(sp, ' ');
+ if (flags & N_FLAG) sfprintf(sp, "%s", grp->gr_name);
+ else sfprintf(sp, "%u", grp->gr_gid);
+ }
+#if _lib_endgrent
+ endgrent();
+#endif
+ if (i) sfputc(sp, '\n');
+#endif
+ }
+ else if (ngroups > 0)
+ {
+ for (i = 0;;)
+ {
+ group = groups[i];
+ if ((flags & N_FLAG) && (grp = getgrgid(group)))
+ sfprintf(sp, "%s", grp->gr_name);
+ else sfprintf(sp, "%u", group);
+ if (++i >= ngroups) break;
+ sfputc(sp, ' ');
+ }
+ sfputc(sp, '\n');
+ }
+ }
+#if _lib_fsid
+ else if (flags & S_FLAG)
+ {
+ if ((flags & X_FLAG) && name) getfsids(sp, name, flags, 0);
+ else if ((flags & N_FLAG) && fs_name) sfputr(sp, fs_name, '\n');
+ else sfprintf(sp, "%u\n", fs_id);
+ }
+#endif
+ return(0);
+}
+
+int
+b_id(int argc, char** argv, Shbltin_t* context)
+{
+ register int flags = 0;
+ register int n;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'a':
+ continue;
+ case 'G':
+ flags |= GG_FLAG;
+ continue;
+ case 'g':
+ flags |= G_FLAG;
+ continue;
+ case 'n':
+ flags |= N_FLAG;
+ continue;
+ case 'r':
+ flags |= R_FLAG;
+ continue;
+ case 's':
+ flags |= S_FLAG;
+ continue;
+ case 'u':
+ flags |= U_FLAG;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ n = (flags & (GG_FLAG|G_FLAG|S_FLAG|U_FLAG));
+ if (!power2(n))
+ error(2, "incompatible options selected");
+ if (error_info.errors || argc > 1)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if (!(flags & ~(N_FLAG|R_FLAG)))
+ {
+ if (flags & N_FLAG) flags |= O_FLAG;
+ flags |= (U_FLAG|G_FLAG|N_FLAG|R_FLAG|S_FLAG|GG_FLAG);
+ }
+ error_info.errors = getids(sfstdout, *argv, flags);
+ return(error_info.errors);
+}
diff --git a/src/lib/libcmd/join.c b/src/lib/libcmd/join.c
new file mode 100644
index 0000000..675577c
--- /dev/null
+++ b/src/lib/libcmd/join.c
@@ -0,0 +1,984 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * join
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: join (AT&T Research) 2009-12-10 $\n]"
+USAGE_LICENSE
+"[+NAME?join - relational database operator]"
+"[+DESCRIPTION?\bjoin\b performs an \aequality join\a on the files \afile1\a "
+ "and \afile2\a and writes the resulting joined files to standard "
+ "output. By default, a field is delimited by one or more spaces "
+ "and tabs with leading spaces and/or tabs ignored. The \b-t\b option "
+ "can be used to change the field delimiter.]"
+"[+?The \ajoin field\a is a field in each file on which files are compared. "
+ "By default \bjoin\b writes one line in the output for each pair "
+ "of lines in \afiles1\a and \afiles2\a that have identical join "
+ "fields. The default output line consists of the join field, "
+ "then the remaining fields from \afile1\a, then the remaining "
+ "fields from \afile2\a, but this can be changed with the \b-o\b "
+ "option. The \b-a\b option can be used to add unmatched lines "
+ "to the output. The \b-v\b option can be used to output only "
+ "unmatched lines.]"
+"[+?The files \afile1\a and \afile2\a must be ordered in the collating "
+ "sequence of \bsort -b\b on the fields on which they are to be "
+ "joined otherwise the results are unspecified.]"
+"[+?If either \afile1\a or \afile2\a is \b-\b, \bjoin\b "
+ "uses standard input starting at the current location.]"
+
+"[e:empty]:[string?Replace empty output fields in the list selected with"
+" \b-o\b with \astring\a.]"
+"[o:output]:[list?Construct the output line to comprise the fields specified "
+ "in a blank or comma separated list \alist\a. Each element in "
+ "\alist\a consists of a file number (either 1 or 2), a period, "
+ "and a field number or \b0\b representing the join field. "
+ "As an obsolete feature multiple occurrences of \b-o\b can "
+ "be specified.]"
+"[t:separator|tabs]:[delim?Use \adelim\a as the field separator for both input"
+" and output.]"
+"[1:j1]#[field?Join on field \afield\a of \afile1\a. Fields start at 1.]"
+"[2:j2]#[field?Join on field \afield\a of \afile2\a. Fields start at 1.]"
+"[j:join]#[field?Equivalent to \b-1\b \afield\a \b-2\b \afield\a.]"
+"[a:unpairable]#[fileno?Write a line for each unpairable line in file"
+" \afileno\a, where \afileno\a is either 1 or 2, in addition to the"
+" normal output. If \b-a\b options appear for both 1 and 2, then "
+ "all unpairable lines will be output.]"
+"[v:suppress]#[fileno?Write a line for each unpairable line in file"
+" \afileno\a, where \afileno\a is either 1 or 2, instead of the normal "
+ "output. If \b-v\b options appear for both 1 and 2, then "
+ "all unpairable lines will be output.] ]"
+"[i:ignorecase?Ignore case in field comparisons.]"
+"[B!:mmap?Enable memory mapped reads instead of buffered.]"
+
+"[+?The following obsolete option forms are also recognized: \b-j\b \afield\a"
+" is equivalent to \b-1\b \afield\a \b-2\b \afield\a, \b-j1\b \afield\a"
+" is equivalent to \b-1\b \afield\a, and \b-j2\b \afield\a is"
+" equivalent to \b-2\b \afield\a.]"
+
+"\n"
+"\nfile1 file2\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Both files processed successfully.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bcut\b(1), \bcomm\b(1), \bpaste\b(1), \bsort\b(1), \buniq\b(1)]"
+;
+
+#include <cmd.h>
+#include <sfdisc.h>
+
+#if _hdr_wchar && _hdr_wctype && _lib_iswctype
+
+#include <wchar.h>
+#include <wctype.h>
+
+#else
+
+#include <ctype.h>
+
+#ifndef iswspace
+#define iswspace(x) isspace(x)
+#endif
+
+#endif
+
+#define C_FILE1 001
+#define C_FILE2 002
+#define C_COMMON 004
+#define C_ALL (C_FILE1|C_FILE2|C_COMMON)
+
+#define NFIELD 10
+#define JOINFIELD 2
+
+#define S_DELIM 1
+#define S_SPACE 2
+#define S_NL 3
+#define S_WIDE 4
+
+typedef struct Field_s
+{
+ char* beg;
+ char* end;
+} Field_t;
+
+typedef struct File_s
+{
+ Sfio_t* iop;
+ char* name;
+ char* recptr;
+ int reclen;
+ int field;
+ int fieldlen;
+ int nfields;
+ int maxfields;
+ int spaces;
+ int hit;
+ int discard;
+ Field_t* fields;
+} File_t;
+
+typedef struct Join_s
+{
+ unsigned char state[1<<CHAR_BIT];
+ Sfio_t* outfile;
+ int* outlist;
+ int outmode;
+ int ooutmode;
+ char* nullfield;
+ char* delimstr;
+ int delim;
+ int delimlen;
+ int buffered;
+ int ignorecase;
+ int mb;
+ char* same;
+ int samesize;
+ Shbltin_t* context;
+ File_t file[2];
+} Join_t;
+
+static void
+done(register Join_t* jp)
+{
+ if (jp->file[0].iop && jp->file[0].iop != sfstdin)
+ sfclose(jp->file[0].iop);
+ if (jp->file[1].iop && jp->file[1].iop != sfstdin)
+ sfclose(jp->file[1].iop);
+ if (jp->outlist)
+ free(jp->outlist);
+ if (jp->file[0].fields)
+ free(jp->file[0].fields);
+ if (jp->file[1].fields)
+ free(jp->file[1].fields);
+ if (jp->same)
+ free(jp->same);
+ free(jp);
+}
+
+static Join_t*
+init(void)
+{
+ register Join_t* jp;
+ register int i;
+
+ setlocale(LC_ALL, "");
+ if (jp = newof(0, Join_t, 1, 0))
+ {
+ if (jp->mb = mbwide())
+ for (i = 0x80; i <= 0xff; i++)
+ jp->state[i] = S_WIDE;
+ jp->state[' '] = jp->state['\t'] = S_SPACE;
+ jp->state['\n'] = S_NL;
+ jp->delim = -1;
+ jp->nullfield = 0;
+ if (!(jp->file[0].fields = newof(0, Field_t, NFIELD + 1, 0)) ||
+ !(jp->file[1].fields = newof(0, Field_t, NFIELD + 1, 0)))
+ {
+ done(jp);
+ return 0;
+ }
+ jp->file[0].maxfields = NFIELD;
+ jp->file[1].maxfields = NFIELD;
+ jp->outmode = C_COMMON;
+ }
+ return jp;
+}
+
+static int
+getolist(Join_t* jp, const char* first, char** arglist)
+{
+ register const char* cp = first;
+ char** argv = arglist;
+ register int c;
+ int* outptr;
+ int* outmax;
+ int nfield = NFIELD;
+ char* str;
+
+ outptr = jp->outlist = newof(0, int, NFIELD + 1, 0);
+ outmax = outptr + NFIELD;
+ while (c = *cp++)
+ {
+ if (c==' ' || c=='\t' || c==',')
+ continue;
+ str = (char*)--cp;
+ if (*cp=='0' && ((c=cp[1])==0 || c==' ' || c=='\t' || c==','))
+ {
+ str++;
+ c = JOINFIELD;
+ goto skip;
+ }
+ if (cp[1]!='.' || (*cp!='1' && *cp!='2') || (c=strtol(cp+2,&str,10)) <=0)
+ {
+ error(2,"%s: invalid field list",first);
+ break;
+ }
+ c--;
+ c <<=2;
+ if (*cp=='2')
+ c |=1;
+ skip:
+ if (outptr >= outmax)
+ {
+ jp->outlist = newof(jp->outlist, int, 2 * nfield + 1, 0);
+ outptr = jp->outlist + nfield;
+ nfield *= 2;
+ outmax = jp->outlist + nfield;
+ }
+ *outptr++ = c;
+ cp = str;
+ }
+ /* need to accept obsolescent command syntax */
+ while (cp = *argv)
+ {
+ if (cp[1]!='.' || (*cp!='1' && *cp!='2'))
+ {
+ if (*cp=='0' && cp[1]==0)
+ {
+ c = JOINFIELD;
+ goto skip2;
+ }
+ break;
+ }
+ str = (char*)cp;
+ c = strtol(cp+2, &str,10);
+ if (*str || --c<0)
+ break;
+ argv++;
+ c <<= 2;
+ if (*cp=='2')
+ c |=1;
+ skip2:
+ if (outptr >= outmax)
+ {
+ jp->outlist = newof(jp->outlist, int, 2 * nfield + 1, 0);
+ outptr = jp->outlist + nfield;
+ nfield *= 2;
+ outmax = jp->outlist + nfield;
+ }
+ *outptr++ = c;
+ }
+ *outptr = -1;
+ return argv-arglist;
+}
+
+/*
+ * read in a record from file <index> and split into fields
+ */
+static unsigned char*
+getrec(Join_t* jp, int index, int discard)
+{
+ register unsigned char* sp = jp->state;
+ register File_t* fp = &jp->file[index];
+ register Field_t* field = fp->fields;
+ register Field_t* fieldmax = field + fp->maxfields;
+ register char* cp;
+ register int n;
+ char* tp;
+
+ if (sh_checksig(jp->context))
+ return 0;
+ if (discard && fp->discard)
+ sfraise(fp->iop, SFSK_DISCARD, NiL);
+ fp->spaces = 0;
+ fp->hit = 0;
+ if (!(cp = sfgetr(fp->iop, '\n', 0)))
+ {
+ jp->outmode &= ~(1<<index);
+ return 0;
+ }
+ fp->recptr = cp;
+ fp->reclen = sfvalue(fp->iop);
+ if (jp->delim == '\n') /* handle new-line delimiter specially */
+ {
+ field->beg = cp;
+ cp += fp->reclen;
+ field->end = cp - 1;
+ field++;
+ }
+ else
+ do /* separate into fields */
+ {
+ if (field >= fieldmax)
+ {
+ n = 2 * fp->maxfields;
+ fp->fields = newof(fp->fields, Field_t, n + 1, 0);
+ field = fp->fields + fp->maxfields;
+ fp->maxfields = n;
+ fieldmax = fp->fields + n;
+ }
+ field->beg = cp;
+ if (jp->delim == -1)
+ {
+ switch (sp[*(unsigned char*)cp])
+ {
+ case S_SPACE:
+ cp++;
+ break;
+ case S_WIDE:
+ tp = cp;
+ if (iswspace(mbchar(tp)))
+ {
+ cp = tp;
+ break;
+ }
+ /*FALLTHROUGH*/
+ default:
+ goto next;
+ }
+ fp->spaces = 1;
+ if (jp->mb)
+ for (;;)
+ {
+ switch (sp[*(unsigned char*)cp++])
+ {
+ case S_SPACE:
+ continue;
+ case S_WIDE:
+ tp = cp - 1;
+ if (iswspace(mbchar(tp)))
+ {
+ cp = tp;
+ continue;
+ }
+ break;
+ }
+ break;
+ }
+ else
+ while (sp[*(unsigned char*)cp++]==S_SPACE);
+ cp--;
+ }
+ next:
+ if (jp->mb)
+ {
+ for (;;)
+ {
+ tp = cp;
+ switch (n = sp[*(unsigned char*)cp++])
+ {
+ case 0:
+ continue;
+ case S_WIDE:
+ cp--;
+ n = mbchar(cp);
+ if (n == jp->delim)
+ {
+ n = S_DELIM;
+ break;
+ }
+ if (jp->delim == -1 && iswspace(n))
+ {
+ n = S_SPACE;
+ break;
+ }
+ continue;
+ }
+ break;
+ }
+ field->end = tp;
+ }
+ else
+ {
+ while (!(n = sp[*(unsigned char*)cp++]));
+ field->end = cp - 1;
+ }
+ field++;
+ } while (n != S_NL);
+ fp->nfields = field - fp->fields;
+ if ((n = fp->field) < fp->nfields)
+ {
+ cp = fp->fields[n].beg;
+ /* eliminate leading spaces */
+ if (fp->spaces)
+ {
+ if (jp->mb)
+ for (;;)
+ {
+ switch (sp[*(unsigned char*)cp++])
+ {
+ case S_SPACE:
+ continue;
+ case S_WIDE:
+ tp = cp - 1;
+ if (iswspace(mbchar(tp)))
+ {
+ cp = tp;
+ continue;
+ }
+ break;
+ }
+ break;
+ }
+ else
+ while (sp[*(unsigned char*)cp++]==S_SPACE);
+ cp--;
+ }
+ fp->fieldlen = fp->fields[n].end - cp;
+ return (unsigned char*)cp;
+ }
+ fp->fieldlen = 0;
+ return (unsigned char*)"";
+}
+
+#if DEBUG_TRACE
+static unsigned char* u1;
+#define getrec(p,n,d) (u1 = getrec(p, n, d), sfprintf(sfstdout, "[G%d#%d@%I*d:%-.8s]", __LINE__, n, sizeof(Sfoff_t), sftell(p->file[n].iop), u1), u1)
+#endif
+
+/*
+ * print field <n> from file <index>
+ */
+static int
+outfield(Join_t* jp, int index, register int n, int last)
+{
+ register File_t* fp = &jp->file[index];
+ register char* cp;
+ register char* cpmax;
+ register int size;
+ register Sfio_t* iop = jp->outfile;
+ char* tp;
+
+ if (n < fp->nfields)
+ {
+ cp = fp->fields[n].beg;
+ cpmax = fp->fields[n].end + 1;
+ }
+ else
+ cp = 0;
+ if ((n = jp->delim) == -1)
+ {
+ if (cp && fp->spaces)
+ {
+ register unsigned char* sp = jp->state;
+
+ /*eliminate leading spaces */
+ if (jp->mb)
+ for (;;)
+ {
+ switch (sp[*(unsigned char*)cp++])
+ {
+ case S_SPACE:
+ continue;
+ case S_WIDE:
+ tp = cp - 1;
+ if (iswspace(mbchar(tp)))
+ {
+ cp = tp;
+ continue;
+ }
+ break;
+ }
+ break;
+ }
+ else
+ while (sp[*(unsigned char*)cp++]==S_SPACE);
+ cp--;
+ }
+ n = ' ';
+ }
+ else if (jp->delimstr)
+ n = -1;
+ if (last)
+ n = '\n';
+ if (cp)
+ size = cpmax - cp;
+ else
+ size = 0;
+ if (n == -1)
+ {
+ if (size<=1)
+ {
+ if (jp->nullfield && sfputr(iop, jp->nullfield, -1) < 0)
+ return -1;
+ }
+ else if (sfwrite(iop, cp, size) < 0)
+ return -1;
+ if (sfwrite(iop, jp->delimstr, jp->delimlen) < 0)
+ return -1;
+ }
+ else if (size <= 1)
+ {
+ if (!jp->nullfield)
+ sfputc(iop, n);
+ else if (sfputr(iop, jp->nullfield, n) < 0)
+ return -1;
+ }
+ else
+ {
+ last = cp[size-1];
+ cp[size-1] = n;
+ if (sfwrite(iop, cp, size) < 0)
+ return -1;
+ cp[size-1] = last;
+ }
+ return 0;
+}
+
+#if DEBUG_TRACE
+static int i1,i2,i3;
+#define outfield(p,i,n,f) (sfprintf(sfstdout, "[F%d#%d:%d,%d]", __LINE__, i1=i, i2=n, i3=f), outfield(p, i1, i2, i3))
+#endif
+
+static int
+outrec(register Join_t* jp, int mode)
+{
+ register File_t* fp;
+ register int i;
+ register int j;
+ register int k;
+ register int n;
+ int* out;
+
+ if (mode < 0 && jp->file[0].hit++)
+ return 0;
+ if (mode > 0 && jp->file[1].hit++)
+ return 0;
+ if (out = jp->outlist)
+ {
+ while ((n = *out++) >= 0)
+ {
+ if (n == JOINFIELD)
+ {
+ i = mode >= 0;
+ j = jp->file[i].field;
+ }
+ else
+ {
+ i = n & 1;
+ j = (mode<0 && i || mode>0 && !i) ?
+ jp->file[i].nfields :
+ n >> 2;
+ }
+ if (outfield(jp, i, j, *out < 0) < 0)
+ return -1;
+ }
+ return 0;
+ }
+ k = jp->file[0].nfields;
+ if (mode >= 0)
+ k += jp->file[1].nfields - 1;
+ for (i=0; i<2; i++)
+ {
+ fp = &jp->file[i];
+ if (mode>0 && i==0)
+ {
+ k -= (fp->nfields - 1);
+ continue;
+ }
+ n = fp->field;
+ if (mode||i==0)
+ {
+ /* output join field first */
+ if (outfield(jp,i,n,!--k) < 0)
+ return -1;
+ if (!k)
+ return 0;
+ for (j=0; j<n; j++)
+ {
+ if (outfield(jp,i,j,!--k) < 0)
+ return -1;
+ if (!k)
+ return 0;
+ }
+ j = n + 1;
+ }
+ else
+ j = 0;
+ for (;j<fp->nfields; j++)
+ {
+ if (j!=n && outfield(jp,i,j,!--k) < 0)
+ return -1;
+ if (!k)
+ return 0;
+ }
+ }
+ return 0;
+}
+
+#if DEBUG_TRACE
+#define outrec(p,n) (sfprintf(sfstdout, "[R#%d,%d,%lld,%lld:%-.*s{%d}:%-.*s{%d}]", __LINE__, i1=n, lo, hi, jp->file[0].fieldlen, cp1, jp->file[0].hit, jp->file[1].fieldlen, cp2, jp->file[1].hit), outrec(p, i1))
+#endif
+
+static int
+join(Join_t* jp)
+{
+ register unsigned char* cp1;
+ register unsigned char* cp2;
+ register int n1;
+ register int n2;
+ register int n;
+ register int cmp;
+ register int same;
+ int o2;
+ Sfoff_t lo = -1;
+ Sfoff_t hi = -1;
+
+ if ((cp1 = getrec(jp, 0, 0)) && (cp2 = getrec(jp, 1, 0)) || (cp2 = 0))
+ {
+ n1 = jp->file[0].fieldlen;
+ n2 = jp->file[1].fieldlen;
+ same = 0;
+ for (;;)
+ {
+ n = n1 < n2 ? n1 : n2;
+#if DEBUG_TRACE
+ if (!n && !(cmp = n1 < n2 ? -1 : (n1 > n2)) || n && !(cmp = (int)*cp1 - (int)*cp2) && !(cmp = jp->ignorecase ? strncasecmp((char*)cp1, (char*)cp2, n) : memcmp(cp1, cp2, n)))
+ cmp = n1 - n2;
+sfprintf(sfstdout, "[C#%d:%d(%c-%c),%d,%lld,%lld%s]", __LINE__, cmp, *cp1, *cp2, same, lo, hi, (jp->outmode & C_COMMON) ? ",COMMON" : "");
+ if (!cmp)
+#else
+ if (!n && !(cmp = n1 < n2 ? -1 : (n1 > n2)) || n && !(cmp = (int)*cp1 - (int)*cp2) && !(cmp = jp->ignorecase ? strncasecmp((char*)cp1, (char*)cp2, n) : memcmp(cp1, cp2, n)) && !(cmp = n1 - n2))
+#endif
+ {
+ if (!(jp->outmode & C_COMMON))
+ {
+ if (cp1 = getrec(jp, 0, 1))
+ {
+ n1 = jp->file[0].fieldlen;
+ same = 1;
+ continue;
+ }
+ if ((jp->ooutmode & (C_FILE1|C_FILE2)) != C_FILE2)
+ break;
+ if (sfseek(jp->file[0].iop, (Sfoff_t)-jp->file[0].reclen, SEEK_CUR) < 0 || !(cp1 = getrec(jp, 0, 0)))
+ {
+ error(ERROR_SYSTEM|2, "%s: seek error", jp->file[0].name);
+ return -1;
+ }
+ }
+ else if (outrec(jp, 0) < 0)
+ return -1;
+ else if (lo < 0 && (jp->outmode & C_COMMON))
+ {
+ if ((lo = sfseek(jp->file[1].iop, (Sfoff_t)0, SEEK_CUR)) < 0)
+ {
+ error(ERROR_SYSTEM|2, "%s: seek error", jp->file[1].name);
+ return -1;
+ }
+ lo -= jp->file[1].reclen;
+ }
+ if (cp2 = getrec(jp, 1, lo < 0))
+ {
+ n2 = jp->file[1].fieldlen;
+ continue;
+ }
+#if DEBUG_TRACE
+sfprintf(sfstdout, "[2#%d:0,%lld,%lld]", __LINE__, lo, hi);
+#endif
+ }
+ else if (cmp > 0)
+ {
+ if (same)
+ {
+ same = 0;
+ next:
+ if (n2 > jp->samesize)
+ {
+ jp->samesize = roundof(n2, 16);
+ if (!(jp->same = newof(jp->same, char, jp->samesize, 0)))
+ {
+ error(ERROR_SYSTEM|2, "out of space");
+ return -1;
+ }
+ }
+ memcpy(jp->same, cp2, o2 = n2);
+ if (!(cp2 = getrec(jp, 1, 0)))
+ break;
+ n2 = jp->file[1].fieldlen;
+ if (n2 == o2 && *cp2 == *jp->same && !memcmp(cp2, jp->same, n2))
+ goto next;
+ continue;
+ }
+ if (hi >= 0)
+ {
+ if (sfseek(jp->file[1].iop, hi, SEEK_SET) != hi)
+ {
+ error(ERROR_SYSTEM|2, "%s: seek error", jp->file[1].name);
+ return -1;
+ }
+ hi = -1;
+ }
+ else if ((jp->outmode & C_FILE2) && outrec(jp, 1) < 0)
+ return -1;
+ lo = -1;
+ if (cp2 = getrec(jp, 1, 1))
+ {
+ n2 = jp->file[1].fieldlen;
+ continue;
+ }
+#if DEBUG_TRACE
+sfprintf(sfstdout, "[2#%d:0,%lld,%lld]", __LINE__, lo, hi);
+#endif
+ }
+ else if (same)
+ {
+ same = 0;
+ if (!(cp1 = getrec(jp, 0, 0)))
+ break;
+ n1 = jp->file[0].fieldlen;
+ continue;
+ }
+ if (lo >= 0)
+ {
+ if ((hi = sfseek(jp->file[1].iop, (Sfoff_t)0, SEEK_CUR)) < 0 ||
+ (hi -= jp->file[1].reclen) < 0 ||
+ sfseek(jp->file[1].iop, lo, SEEK_SET) != lo ||
+ !(cp2 = getrec(jp, 1, 0)))
+ {
+ error(ERROR_SYSTEM|2, "%s: seek error", jp->file[1].name);
+ return -1;
+ }
+ n2 = jp->file[1].fieldlen;
+ lo = -1;
+ if (jp->file[1].discard)
+ sfseek(jp->file[1].iop, (Sfoff_t)-1, SEEK_SET);
+ }
+ else if (!cp2)
+ break;
+ else if ((jp->outmode & C_FILE1) && outrec(jp, -1) < 0)
+ return -1;
+ if (!(cp1 = getrec(jp, 0, 1)))
+ break;
+ n1 = jp->file[0].fieldlen;
+ }
+ }
+#if DEBUG_TRACE
+sfprintf(sfstdout, "[X#%d:?,%p,%p,%d,%d,%d%s]", __LINE__, cp1, cp2, cmp, lo, hi, (jp->outmode & C_COMMON) ? ",COMMON" : "");
+#endif
+ if (cp2)
+ {
+ if (hi >= 0 &&
+ sfseek(jp->file[1].iop, (Sfoff_t)0, SEEK_CUR) < hi &&
+ sfseek(jp->file[1].iop, hi, SEEK_SET) != hi)
+ {
+ error(ERROR_SYSTEM|2, "%s: seek error", jp->file[1].name);
+ return -1;
+ }
+#if DEBUG_TRACE
+sfprintf(sfstdout, "[O#%d:%02o:%02o]", __LINE__, jp->ooutmode, jp->outmode);
+#endif
+ cp1 = (!cp1 && cmp && hi < 0 && !jp->file[1].hit && ((jp->ooutmode ^ C_ALL) <= 1 || jp->outmode == 2)) ? cp2 : getrec(jp, 1, 0);
+ cmp = 1;
+ n = 1;
+ }
+ else
+ {
+ cmp = -1;
+ n = 0;
+ }
+#if DEBUG_TRACE
+sfprintf(sfstdout, "[X#%d:%d,%p,%p,%d,%02o,%02o%s]", __LINE__, n, cp1, cp2, cmp, jp->ooutmode, jp->outmode, (jp->outmode & C_COMMON) ? ",COMMON" : "");
+#endif
+ if (!cp1 || !(jp->outmode & (1<<n)))
+ {
+ if (cp1 && jp->file[n].iop == sfstdin)
+ sfseek(sfstdin, (Sfoff_t)0, SEEK_END);
+ return 0;
+ }
+ if (outrec(jp, cmp) < 0)
+ return -1;
+ do
+ {
+ if (!getrec(jp, n, 1))
+ return 0;
+ } while (outrec(jp, cmp) >= 0);
+ return -1;
+}
+
+int
+b_join(int argc, char** argv, Shbltin_t* context)
+{
+ register int n;
+ register char* cp;
+ register Join_t* jp;
+ char* e;
+
+#if !DEBUG_TRACE
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
+#endif
+ if (!(jp = init()))
+ error(ERROR_system(1),"out of space");
+ jp->context = context;
+ for (;;)
+ {
+ switch (n = optget(argv, usage))
+ {
+ case 'j':
+ /*
+ * check for obsolete "-j1 field" and "-j2 field"
+ */
+
+ if (opt_info.offset == 0)
+ {
+ cp = argv[opt_info.index - 1];
+ for (n = strlen(cp) - 1; n > 0 && cp[n] != 'j'; n--);
+ n = cp[n] == 'j';
+ }
+ else
+ n = 0;
+ if (n)
+ {
+ if (opt_info.num!=1 && opt_info.num!=2)
+ error(2,"-jfileno field: fileno must be 1 or 2");
+ n = '0' + opt_info.num;
+ if (!(cp = argv[opt_info.index]))
+ {
+ argc = 0;
+ break;
+ }
+ opt_info.num = strtol(cp, &e, 10);
+ if (*e)
+ {
+ argc = 0;
+ break;
+ }
+ opt_info.index++;
+ }
+ else
+ {
+ jp->file[0].field = (int)(opt_info.num-1);
+ n = '2';
+ }
+ /*FALLTHROUGH*/
+ case '1':
+ case '2':
+ if (opt_info.num <=0)
+ error(2,"field number must positive");
+ jp->file[n-'1'].field = (int)(opt_info.num-1);
+ continue;
+ case 'v':
+ jp->outmode &= ~C_COMMON;
+ /*FALLTHROUGH*/
+ case 'a':
+ if (opt_info.num!=1 && opt_info.num!=2)
+ error(2,"%s: file number must be 1 or 2", opt_info.name);
+ jp->outmode |= 1<<(opt_info.num-1);
+ continue;
+ case 'e':
+ jp->nullfield = opt_info.arg;
+ continue;
+ case 'o':
+ /* need to accept obsolescent command syntax */
+ n = getolist(jp, opt_info.arg, argv+opt_info.index);
+ opt_info.index += n;
+ continue;
+ case 't':
+ jp->state[' '] = jp->state['\t'] = 0;
+ if (jp->mb)
+ {
+ cp = opt_info.arg;
+ jp->delim = mbchar(cp);
+ if ((n = cp - opt_info.arg) > 1)
+ {
+ jp->delimlen = n;
+ jp->delimstr = opt_info.arg;
+ continue;
+ }
+ }
+ n = *(unsigned char*)opt_info.arg;
+ jp->state[n] = S_DELIM;
+ jp->delim = n;
+ continue;
+ case 'i':
+ jp->ignorecase = !opt_info.num;
+ continue;
+ case 'B':
+ jp->buffered = !opt_info.num;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ done(jp);
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ argc -= opt_info.index;
+ if (error_info.errors || argc!=2)
+ {
+ done(jp);
+ error(ERROR_usage(2),"%s", optusage(NiL));
+ }
+ jp->ooutmode = jp->outmode;
+ jp->file[0].name = cp = *argv++;
+ if (streq(cp,"-"))
+ {
+ if (sfseek(sfstdin,(Sfoff_t)0,SEEK_CUR) < 0)
+ {
+ if (sfdcseekable(sfstdin))
+ error(ERROR_warn(0),"%s: seek may fail",cp);
+ else
+ jp->file[0].discard = 1;
+ }
+ jp->file[0].iop = sfstdin;
+ }
+ else if (!(jp->file[0].iop = sfopen(NiL, cp, "r")))
+ {
+ done(jp);
+ error(ERROR_system(1),"%s: cannot open",cp);
+ }
+ jp->file[1].name = cp = *argv;
+ if (streq(cp,"-"))
+ {
+ if (sfseek(sfstdin,(Sfoff_t)0,SEEK_CUR) < 0)
+ {
+ if (sfdcseekable(sfstdin))
+ error(ERROR_warn(0),"%s: seek may fail",cp);
+ else
+ jp->file[1].discard = 1;
+ }
+ jp->file[1].iop = sfstdin;
+ }
+ else if (!(jp->file[1].iop = sfopen(NiL, cp, "r")))
+ {
+ done(jp);
+ error(ERROR_system(1),"%s: cannot open",cp);
+ }
+ if (jp->buffered)
+ {
+ sfsetbuf(jp->file[0].iop, jp->file[0].iop, SF_UNBOUND);
+ sfsetbuf(jp->file[1].iop, jp->file[1].iop, SF_UNBOUND);
+ }
+ jp->outfile = sfstdout;
+ if (!jp->outlist)
+ jp->nullfield = 0;
+ if (join(jp) < 0)
+ {
+ done(jp);
+ error(ERROR_system(1),"write error");
+ }
+ else if (jp->file[0].iop==sfstdin || jp->file[1].iop==sfstdin)
+ sfseek(sfstdin,(Sfoff_t)0,SEEK_END);
+ done(jp);
+ return error_info.errors;
+}
diff --git a/src/lib/libcmd/lib.c b/src/lib/libcmd/lib.c
new file mode 100644
index 0000000..2f0bb41
--- /dev/null
+++ b/src/lib/libcmd/lib.c
@@ -0,0 +1,25 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <cmd.h>
+
+SHLIB(cmd)
diff --git a/src/lib/libcmd/ln.c b/src/lib/libcmd/ln.c
new file mode 100644
index 0000000..709b450
--- /dev/null
+++ b/src/lib/libcmd/ln.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * cp/ln/mv -- copy/link/move files
+ */
+
+#include <cmd.h>
+
+int
+b_ln(int argc, register char** argv, Shbltin_t* context)
+{
+ return b_cp(argc, argv, context);
+}
diff --git a/src/lib/libcmd/logname.c b/src/lib/libcmd/logname.c
new file mode 100644
index 0000000..5dce0e2
--- /dev/null
+++ b/src/lib/libcmd/logname.c
@@ -0,0 +1,78 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Research
+ *
+ * logname
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: logname (AT&T Research) 1999-04-30 $\n]"
+USAGE_LICENSE
+"[+NAME?logname - return the user's login name]"
+"[+DESCRIPTION?\blogname\b writes the users's login name to standard "
+ "output. The login name is the string that is returned by the "
+ "\bgetlogin\b(2) function. If \bgetlogin\b(2) does not return "
+ "successfully, the corresponding to the real user id of the calling "
+ "process is used instead.]"
+
+"\n"
+"\n\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?Successful Completion.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bgetlogin\b(2)]"
+;
+
+
+#include <cmd.h>
+
+int
+b_logname(int argc, char** argv, Shbltin_t* context)
+{
+ register char* logname;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ if (error_info.errors)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if (!(logname = getlogin()))
+ logname = fmtuid(getuid());
+ sfputr(sfstdout, logname, '\n');
+ return 0;
+}
+
diff --git a/src/lib/libcmd/md5sum.c b/src/lib/libcmd/md5sum.c
new file mode 100644
index 0000000..bd0b25f
--- /dev/null
+++ b/src/lib/libcmd/md5sum.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * md5sum -- implemented by cksum
+ */
+
+#include <cmd.h>
+
+int
+b_md5sum(int argc, register char** argv, Shbltin_t* context)
+{
+ return b_cksum(argc, argv, context);
+}
diff --git a/src/lib/libcmd/mkdir.c b/src/lib/libcmd/mkdir.c
new file mode 100644
index 0000000..bdd6ecf
--- /dev/null
+++ b/src/lib/libcmd/mkdir.c
@@ -0,0 +1,189 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * mkdir
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: mkdir (AT&T Research) 2010-04-08 $\n]"
+USAGE_LICENSE
+"[+NAME?mkdir - make directories]"
+"[+DESCRIPTION?\bmkdir\b creates one or more directories. By "
+ "default, the mode of created directories is \ba=rwx\b minus the "
+ "bits set in the \bumask\b(1).]"
+"[m:mode]:[mode?Set the mode of created directories to \amode\a. "
+ "\amode\a is symbolic or octal mode as in \bchmod\b(1). Relative "
+ "modes assume an initial mode of \ba=rwx\b.]"
+"[p:parents?Create any missing intermediate pathname components. For "
+ "each dir operand that does not name an existing directory, effects "
+ "equivalent to those caused by the following command shall occur: "
+ "\vmkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode]] "
+ "dir\v where the \b-m\b mode option represents that option supplied to "
+ "the original invocation of \bmkdir\b, if any. Each dir operand that "
+ "names an existing directory shall be ignored without error.]"
+"[v:verbose?Print a message on the standard error for each created "
+ "directory.]"
+"\n"
+"\ndirectory ...\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All directories created successfully, or the \b-p\b option "
+ "was specified and all the specified directories now exist.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bchmod\b(1), \brmdir\b(1), \bumask\b(1)]"
+;
+
+#include <cmd.h>
+#include <ls.h>
+
+#define DIRMODE (S_IRWXU|S_IRWXG|S_IRWXO)
+
+int
+b_mkdir(int argc, char** argv, Shbltin_t* context)
+{
+ register char* path;
+ register int n;
+ register mode_t mode = DIRMODE;
+ register mode_t mask = 0;
+ register int mflag = 0;
+ register int pflag = 0;
+ register int vflag = 0;
+ int made;
+ char* part;
+ mode_t dmode;
+ struct stat st;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'm':
+ mflag = 1;
+ mode = strperm(opt_info.arg, &part, mode);
+ if (*part)
+ error(ERROR_exit(0), "%s: invalid mode", opt_info.arg);
+ continue;
+ case 'p':
+ pflag = 1;
+ continue;
+ case 'v':
+ vflag = 1;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || !*argv)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ mask = umask(0);
+ if (mflag || pflag)
+ {
+ dmode = DIRMODE & ~mask;
+ if (!mflag)
+ mode = dmode;
+ dmode |= S_IWUSR | S_IXUSR;
+ }
+ else
+ {
+ mode &= ~mask;
+ umask(mask);
+ mask = 0;
+ }
+ while (path = *argv++)
+ {
+ if (!mkdir(path, mode))
+ {
+ if (vflag)
+ error(0, "%s: directory created", path);
+ made = 1;
+ }
+ else if (!pflag || !(errno == ENOENT || errno == EEXIST || errno == ENOTDIR))
+ {
+ error(ERROR_system(0), "%s:", path);
+ continue;
+ }
+ else if (errno == EEXIST)
+ continue;
+ else
+ {
+ /*
+ * -p option, preserve intermediates
+ * first eliminate trailing /'s
+ */
+
+ made = 0;
+ n = strlen(path);
+ while (n > 0 && path[--n] == '/');
+ path[n + 1] = 0;
+ for (part = path, n = *part; n;)
+ {
+ /* skip over slashes */
+ while (*part == '/')
+ part++;
+ /* skip to next component */
+ while ((n = *part) && n != '/')
+ part++;
+ *part = 0;
+ if (mkdir(path, n ? dmode : mode) < 0 && errno != EEXIST && access(path, F_OK) < 0)
+ {
+ error(ERROR_system(0), "%s: cannot create intermediate directory", path);
+ *part = n;
+ break;
+ }
+ if (vflag)
+ error(0, "%s: directory created", path);
+ if (!(*part = n))
+ {
+ made = 1;
+ break;
+ }
+ }
+ }
+ if (made && (mode & (S_ISVTX|S_ISUID|S_ISGID)))
+ {
+ if (stat(path, &st))
+ {
+ error(ERROR_system(0), "%s: cannot stat", path);
+ break;
+ }
+ if ((st.st_mode & (S_ISVTX|S_ISUID|S_ISGID)) != (mode & (S_ISVTX|S_ISUID|S_ISGID)) && chmod(path, mode))
+ {
+ error(ERROR_system(0), "%s: cannot change mode from %s to %s", path, fmtperm(st.st_mode & (S_ISVTX|S_ISUID|S_ISGID)), fmtperm(mode));
+ break;
+ }
+ }
+ }
+ if (mask)
+ umask(mask);
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/mkfifo.c b/src/lib/libcmd/mkfifo.c
new file mode 100644
index 0000000..25861a1
--- /dev/null
+++ b/src/lib/libcmd/mkfifo.c
@@ -0,0 +1,96 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * mkfifo
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: mkfifo (AT&T Research) 2009-01-02 $\n]"
+USAGE_LICENSE
+"[+NAME?mkfifo - make FIFOs (named pipes)]"
+"[+DESCRIPTION?\bmkfifo\b creates one or more FIFO's. By "
+ "default, the mode of created FIFO is \ba=rw\b minus the "
+ "bits set in the \bumask\b(1).]"
+"[m:mode]:[mode?Set the mode of created FIFO to \amode\a. "
+ "\amode\a is symbolic or octal mode as in \bchmod\b(1). Relative "
+ "modes assume an initial mode of \ba=rw\b.]"
+"\n"
+"\nfile ...\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All FIFO's created successfully.]"
+ "[+>0?One or more FIFO's could not be created.]"
+"}"
+"[+SEE ALSO?\bchmod\b(1), \bumask\b(1)]"
+;
+
+#include <cmd.h>
+#include <ls.h>
+
+int
+b_mkfifo(int argc, char** argv, Shbltin_t* context)
+{
+ register char* arg;
+ register mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
+ register mode_t mask = 0;
+ register int mflag = 0;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'm':
+ mflag = 1;
+ mode = strperm(arg = opt_info.arg, &opt_info.arg, mode);
+ if (*opt_info.arg)
+ error(ERROR_exit(0), "%s: invalid mode", arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || !*argv)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ mask = umask(0);
+ if (!mflag)
+ {
+ mode &= ~mask;
+ umask(mask);
+ mask = 0;
+ }
+ while (arg = *argv++)
+ if (mkfifo(arg, mode) < 0)
+ error(ERROR_system(0), "%s:", arg);
+ if (mask)
+ umask(mask);
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/mktemp.c b/src/lib/libcmd/mktemp.c
new file mode 100644
index 0000000..d95f864
--- /dev/null
+++ b/src/lib/libcmd/mktemp.c
@@ -0,0 +1,169 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+static const char usage[] =
+"[-?\n@(#)$Id: mktemp (AT&T Research) 2010-03-05 $\n]"
+USAGE_LICENSE
+"[+NAME?mktemp - make temporary file or directory]"
+"[+DESCRIPTION?\bmktemp\b creates a temporary file with optional base "
+ "name prefix \aprefix\a. If \aprefix\a is omitted then \btmp_\b is used "
+ "and \b--tmp\b is implied. If \aprefix\a contains a directory prefix "
+ "then that directory overrides any of the directories described below. A "
+ "temporary file will have mode \brw-------\b and a temporary directory "
+ "will have mode \brwx------\b, subject to \bumask\b(1). Generated paths "
+ "have these attributes:]"
+ "{"
+ "[+*?Lower case to avoid clashes on case ignorant filesystems.]"
+ "[+*?Pseudo-random part to deter denial of service attacks.]"
+ "[+*?Default pseudo-random part (no specific \bX...\b template) "
+ "formatted to accomodate 8.3 filesystems.]"
+ "}"
+"[+?A consecutive trailing sequence of \bX\b's in \aprefix\a is replaced "
+ "by the pseudo-random part. If there are no \bX\b's then the "
+ "pseudo-random part is appended to the prefix.]"
+"[d:directory?Create a directory instead of a regular file.]"
+"[m:mode]:[mode?Set the mode of the created temporary to \amode\a. "
+ "\amode\a is symbolic or octal mode as in \bchmod\b(1). Relative modes "
+ "assume an initial mode of \bu=rwx\b.]"
+"[p:default?Use \adirectory\a if the \bTMPDIR\b environment variable is "
+ "not defined. Implies \b--tmp\b.]:[directory]"
+"[q:quiet?Suppress file and directory error diagnostics.]"
+"[R:regress?The pseudo random generator is seeded with \aseed\a instead "
+ "of process/system specific transient data. Use for testing "
+ "only. A seed of \b0\b is silently changed to \b1\b.]#[seed]"
+"[t:tmp|temporary-directory?Create a path rooted in a temporary "
+ "directory.]"
+"[u:unsafe|dry-run?Check for file/directory existence but do not create. "
+ "Use this for testing only.]"
+"\n"
+"\n[ prefix ]\n"
+"\n"
+"[+SEE ALSO?\bmkdir\b(1), \bpathtemp\b(3), \bmktemp\b(3)]"
+;
+
+#include <cmd.h>
+#include <ls.h>
+
+int
+b_mktemp(int argc, char** argv, Shbltin_t* context)
+{
+ mode_t mode = 0;
+ mode_t mask;
+ int fd;
+ int i;
+ int quiet = 0;
+ int unsafe = 0;
+ int* fdp = &fd;
+ char* dir = "";
+ char* pfx;
+ char* t;
+ char path[PATH_MAX];
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'd':
+ fdp = 0;
+ continue;
+ case 'm':
+ mode = strperm(pfx = opt_info.arg, &opt_info.arg, S_IRWXU);
+ if (*opt_info.arg)
+ error(ERROR_exit(0), "%s: invalid mode", pfx);
+ continue;
+ case 'p':
+ if ((t = getenv("TMPDIR")) && *t)
+ dir = 0;
+ else
+ dir = opt_info.arg;
+ continue;
+ case 'q':
+ quiet = 1;
+ continue;
+ case 't':
+ dir = 0;
+ continue;
+ case 'u':
+ unsafe = 1;
+ fdp = 0;
+ continue;
+ case 'R':
+ if (!pathtemp(NiL, 0, opt_info.arg, "/seed", NiL))
+ error(2, "%s: regression test initializtion failed", opt_info.arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || (pfx = *argv++) && *argv)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ mask = umask(0);
+ if (!mode)
+ mode = (fdp ? (S_IRUSR|S_IWUSR) : S_IRWXU) & ~mask;
+ umask(~mode & (S_IRWXU|S_IRWXG|S_IRWXO));
+ if (!pfx)
+ {
+ pfx = "tmp_";
+ if (dir && !*dir)
+ dir = 0;
+ }
+ if (t = strrchr(pfx, '/'))
+ {
+ i = ++t - pfx;
+ dir = fmtbuf(i);
+ memcpy(dir, pfx, i);
+ dir[i] = 0;
+ pfx = t;
+ }
+ for (;;)
+ {
+ if (!pathtemp(path, sizeof(path), dir, pfx, fdp))
+ {
+ if (quiet)
+ error_info.errors++;
+ else
+ error(ERROR_SYSTEM|2, "cannot create temporary path");
+ break;
+ }
+ if (fdp || unsafe || !mkdir(path, mode))
+ {
+ if (fdp)
+ close(*fdp);
+ sfputr(sfstdout, path, '\n');
+ break;
+ }
+ if (sh_checksig(context))
+ {
+ error_info.errors++;
+ break;
+ }
+ }
+ umask(mask);
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/mv.c b/src/lib/libcmd/mv.c
new file mode 100644
index 0000000..f282bdc
--- /dev/null
+++ b/src/lib/libcmd/mv.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * cp/ln/mv -- copy/link/move files
+ */
+
+#include <cmd.h>
+
+int
+b_mv(int argc, register char** argv, Shbltin_t* context)
+{
+ return b_cp(argc, argv, context);
+}
diff --git a/src/lib/libcmd/paste.c b/src/lib/libcmd/paste.c
new file mode 100644
index 0000000..cb22e8e
--- /dev/null
+++ b/src/lib/libcmd/paste.c
@@ -0,0 +1,288 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * paste [-s] [-d delim] [file] ...
+ *
+ * paste lines from files together
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: paste (AT&T Research) 2010-06-12 $\n]"
+USAGE_LICENSE
+"[+NAME?paste - merge lines of files]"
+"[+DESCRIPTION?\bpaste\b concatenates the corresponding lines of a "
+ "given input file and writes the resulting lines to standard "
+ "output. By default \bpaste\b replaces the newline character of "
+ "every line other than the last input file with the TAB character.]"
+"[+?Unless the \b-s\b option is specified, if an end-of-file is encountered "
+ "on one or more input files, but not all input files, \bpaste\b "
+ "behaves as if empty lines were read from the file(s) on which "
+ "end-of-file was detected.]"
+"[+?Unless the \b-s\b option is specified, \bpaste\b is limited by "
+ "the underlying operating system on how many \afile\a operands "
+ "can be specified.]"
+"[+?If no \afile\a operands are given or if the \afile\a is \b-\b, \bpaste\b "
+ "reads from standard input. The start of the file is defined as the "
+ "current offset.]"
+
+"[s:serial?Paste the lines of one file at a time rather than one line "
+ "from each file. In this case if the \b-d\b option is "
+ "specified the delimiter will be reset to the first in the "
+ "list at the beginning of each file.]"
+"[d:delimiters]:[list?\alist\a specifies a list of delimiters. These "
+ "delimiters are used circularly instead of TAB to replace "
+ "the newline character of the input lines. Unless the \b-s\b "
+ "option is specified, the delimiter will be reset to the first "
+ "element of \alist\a each time a line is processed from each file. "
+ "The delimiter characters corresponding to \alist\a will be found "
+ "by treating \alist\a as an ANSI-C string, except that the \b\\0\b "
+ "sequence will insert the empty string instead of the null character.]"
+"\n"
+"\n[file ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All files processed successfully.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bcut\b(1), \bcat\b(1), \bjoin\b(1)]"
+;
+
+#include <cmd.h>
+
+typedef struct Delim_s
+{
+ const char* chr;
+ size_t len;
+} Delim_t;
+
+/*
+ * paste the lines of the <nstreams> defined in <streams> and put results
+ * to <out>
+ */
+
+static int paste(int nstream,Sfio_t* streams[],Sfio_t *out, register const char *delim, int dsiz, int dlen, Delim_t* mp)
+{
+ register const char *cp;
+ register int d, n, i, z, more=1;
+ register Sfio_t *fp;
+ do
+ {
+ d = (dlen>0?0:-1);
+ for(n=more-1,more=0; n < nstream;)
+ {
+ if(fp=streams[n])
+ {
+ if(cp = sfgetr(fp,'\n',0))
+ {
+ if(n==0)
+ more = 1;
+ else if(!more) /* first stream with output */
+ {
+ if(dsiz == 1)
+ sfnputc(out, *delim, n);
+ else if(dlen>0)
+ {
+ for(d=n; d>dlen; d-=dlen)
+ sfwrite(out,delim,dsiz);
+ if(d)
+ {
+ if(mp)
+ for (i = z = 0; i < d; i++)
+ z += mp[i].len;
+ else
+ z = d;
+ sfwrite(out,delim,z);
+ }
+ }
+ more = n+1;
+ }
+ if(sfwrite(out,cp,sfvalue(fp)-((n+1)<nstream)) < 0)
+ return(-1);
+ }
+ else
+ streams[n] = 0;
+ }
+ if(++n<nstream && more && d>=0)
+ {
+ register int c;
+ if(d >= dlen)
+ d = 0;
+ if(mp)
+ sfwrite(out,mp[d].chr,mp[d].len);
+ else if(c=delim[d])
+ sfputc(out,c);
+ d++;
+ }
+ else if(n==nstream && !streams[n-1] && more)
+ sfputc(out,'\n');
+ }
+ } while(more);
+ return(0);
+}
+
+/*
+ * Handles paste -s, for file <in> to file <out> using delimiters <delim>
+ */
+static int spaste(Sfio_t *in,register Sfio_t* out,register const char *delim,int dsiz,int dlen,Delim_t* mp)
+{
+ register const char *cp;
+ register int d=0;
+ if((cp = sfgetr(in,'\n',0)) && sfwrite(out,cp,sfvalue(in)-1) < 0)
+ return(-1);
+ while(cp=sfgetr(in, '\n',0))
+ {
+ if(dlen)
+ {
+ register int c;
+ if(d >= dlen)
+ d = 0;
+ if(mp)
+ sfwrite(out,mp[d].chr,mp[d].len);
+ else if(c=delim[d])
+ sfputc(out,c);
+ d++;
+ }
+ if(sfwrite(out,cp,sfvalue(in)-1) < 0)
+ return(-1);
+ }
+ sfputc(out,'\n');
+ return(0);
+}
+
+int
+b_paste(int argc, char** argv, Shbltin_t* context)
+{
+ register int n, sflag=0;
+ register Sfio_t *fp, **streams;
+ register char *cp, *delim;
+ char *ep;
+ Delim_t *mp;
+ int dlen, dsiz;
+ char defdelim[2];
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ delim = 0;
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'd':
+ delim = opt_info.arg;
+ continue;
+ case 's':
+ sflag++;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ error(ERROR_usage(2),"%s", optusage(NiL));
+ if(!delim || !*delim)
+ {
+ delim = defdelim;
+ delim[0] = '\t';
+ delim[1] = 0;
+ }
+ if (!(delim = strdup(delim)))
+ error(ERROR_system(1), "out of space");
+ dlen = dsiz = stresc(delim);
+ mp = 0;
+ if (mbwide())
+ {
+ cp = delim;
+ ep = delim + dlen;
+ dlen = 0;
+ while (cp < ep)
+ {
+ mbchar(cp);
+ dlen++;
+ }
+ if(dlen < dsiz)
+ {
+ if (!(mp = newof(0, Delim_t, dlen, 0)))
+ {
+ free(delim);
+ error(ERROR_system(1), "out of space");
+ }
+ cp = delim;
+ dlen = 0;
+ while (cp < ep)
+ {
+ mp[dlen].chr = cp;
+ mbchar(cp);
+ mp[dlen].len = cp - mp[dlen].chr;
+ dlen++;
+ }
+ }
+ }
+ if(cp = *argv)
+ {
+ n = argc - opt_info.index;
+ argv++;
+ }
+ else
+ n = 1;
+ if(!sflag)
+ {
+ if (!(streams = (Sfio_t**)stakalloc(n*sizeof(Sfio_t*))))
+ error(ERROR_exit(1), "out of space");
+ n = 0;
+ }
+ do
+ {
+ if(!cp || streq(cp,"-"))
+ fp = sfstdin;
+ else if(!(fp = sfopen(NiL,cp,"r")))
+ error(ERROR_system(0),"%s: cannot open",cp);
+ if(fp && sflag)
+ {
+ if(spaste(fp,sfstdout,delim,dsiz,dlen,mp) < 0)
+ error(ERROR_system(0),"write failed");
+ if(fp!=sfstdin)
+ sfclose(fp);
+ }
+ else if(!sflag)
+ streams[n++] = fp;
+ } while(cp= *argv++);
+ if(!sflag)
+ {
+ if(error_info.errors==0 && paste(n,streams,sfstdout,delim,dsiz,dlen,mp) < 0)
+ error(ERROR_system(0),"write failed");
+ while(--n>=0)
+ if((fp=streams[n]) && fp!=sfstdin)
+ sfclose(fp);
+ }
+ if (mp)
+ free(mp);
+ free(delim);
+ return(error_info.errors);
+}
diff --git a/src/lib/libcmd/pathchk.c b/src/lib/libcmd/pathchk.c
new file mode 100644
index 0000000..0cba4bd
--- /dev/null
+++ b/src/lib/libcmd/pathchk.c
@@ -0,0 +1,265 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * pathchk
+ *
+ * Written by David Korn
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: pathchk (AT&T Research) 2009-07-24 $\n]"
+USAGE_LICENSE
+"[+NAME?pathchk - check pathnames for portability]"
+"[+DESCRIPTION?\bpathchk\b checks each \apathname\a to see if it is "
+ "valid and/or portable. A \apathname\a is valid if it can be used to "
+ "access or create a file without causing syntax errors. A file is "
+ "portable if no truncation will result on any conforming POSIX.1 "
+ "implementation.]"
+"[+?By default \bpathchk\b checks each component of each \apathname\a "
+ "based on the underlying file system. A diagnostic is written to "
+ "standard error for each pathname that:]"
+ "{"
+ "[+-?Is longer than \b$(getconf PATH_MAX)\b bytes.]"
+ "[+-?Contains any component longer than \b$(getconf NAME_MAX)\b "
+ "bytes.]"
+ "[+-?Contains any directory component in a directory that is not "
+ "searchable.]"
+ "[+-?Contains any character in any component that is not valid "
+ "in its containing directory.]"
+ "[+-?Is empty.]"
+ "}"
+"[p:components?Instead of performing length checks on the underlying "
+ "file system, write a diagnostic for each pathname operand that:]"
+ "{"
+ "[+-?Is longer than \b$(getconf _POSIX_PATH_MAX)\b bytes.]"
+ "[+-?Contains any component longer than \b$(getconf "
+ "_POSIX_NAME_MAX)\b bytes.]"
+ "[+-?Contains any character in any component that is not in the "
+ "portable filename character set.]"
+ "}"
+"[P:path?Write a diagnostic for each pathname operand that:]"
+ "{"
+ "[+-?Contains any component with \b-\b as the first character.]"
+ "[+-?Is empty.]"
+ "}"
+"[a:all|portability?Equivalent to \b--components\b \b--path\b.]"
+"\n"
+"\npathname ...\n"
+"\n"
+"[+EXIT STATUS?]"
+ "{"
+ "[+0?All \apathname\a operands passed all of the checks.]"
+ "[+>0?An error occurred.]"
+ "}"
+"[+SEE ALSO?\bgetconf\b(1), \bcreat\b(2), \bpathchk\b(2)]"
+;
+
+
+#include <cmd.h>
+#include <ls.h>
+
+#define COMPONENTS 0x1
+#define PATH 0x2
+
+#define isport(c) (((c)>='a' && (c)<='z') || ((c)>='A' && (c)<='Z') || ((c)>='0' && (c)<='9') || (strchr("._-",(c))!=0) )
+
+/*
+ * call pathconf and handle unlimited sizes
+ */
+static long mypathconf(const char *path, int op)
+{
+ register long r;
+
+ static const char* const ops[] = { "NAME_MAX", "PATH_MAX" };
+
+ errno = 0;
+ if ((r = strtol(astconf(ops[op], path, NiL), NiL, 0)) < 0 && !errno)
+ return LONG_MAX;
+ return r;
+}
+
+/*
+ * returns 1 if <path> passes test
+ */
+static int pathchk(char* path, int mode)
+{
+ register char *cp=path, *cpold;
+ register int c;
+ register long r,name_max,path_max;
+ char buf[2];
+
+ if(!*path)
+ {
+ if (mode & PATH)
+ error(2,"path is empty");
+ return -1;
+ }
+ if(mode & COMPONENTS)
+ {
+ name_max = _POSIX_NAME_MAX;
+ path_max = _POSIX_PATH_MAX;
+ }
+ else
+ {
+ char tmp[2];
+ name_max = path_max = 0;
+ tmp[0] = (*cp=='/'? '/': '.');
+ tmp[1] = 0;
+ if((r=mypathconf(tmp, 0)) > _POSIX_NAME_MAX)
+ name_max = r;
+ if((r=mypathconf(tmp, 1)) > _POSIX_PATH_MAX)
+ path_max = r;
+ if(*cp!='/')
+ {
+ if(name_max==0||path_max==0)
+ {
+ if(!(cpold = getcwd((char*)0, 0)) && errno == EINVAL && (cpold = newof(0, char, PATH_MAX, 0)) && !getcwd(cpold, PATH_MAX))
+ {
+ free(cpold);
+ cpold = 0;
+ }
+ if(cpold)
+ {
+ cp = cpold + strlen(cpold);
+ while(name_max==0 || path_max==0)
+ {
+ if(cp>cpold)
+ while(--cp>cpold && *cp=='/');
+ *++cp = 0;
+ if(name_max==0 && (r=mypathconf(cpold, 0)) > _POSIX_NAME_MAX)
+ name_max = r;
+ if(path_max==0 && (r=mypathconf(cpold, 1)) > _POSIX_PATH_MAX)
+ path_max=r;
+ if(--cp==cpold)
+ {
+ free(cpold);
+ break;
+ }
+ while(*cp!='/')
+ cp--;
+ }
+ cp=path;
+ }
+ }
+ while(*cp=='/')
+ cp++;
+ }
+ if(name_max==0)
+ name_max=_POSIX_NAME_MAX;
+ if(path_max==0)
+ path_max=_POSIX_PATH_MAX;
+ while(*(cpold=cp))
+ {
+ while((c= *cp++) && c!='/');
+ if((cp-cpold) > name_max)
+ goto err;
+ errno=0;
+ cp[-1] = 0;
+ r = mypathconf(path, 0);
+ if((cp[-1]=c)==0)
+ cp--;
+ else while(*cp=='/')
+ cp++;
+ if(r>=0)
+ name_max=(r<_POSIX_NAME_MAX?_POSIX_NAME_MAX:r);
+ else if(errno==EINVAL)
+ continue;
+#ifdef ENAMETOOLONG
+ else if(errno==ENAMETOOLONG)
+ {
+ error(2,"%s: pathname too long",path);
+ return -1;
+ }
+#endif /*ENAMETOOLONG*/
+ else
+ break;
+ }
+ }
+ while(*(cpold=cp))
+ {
+ if((mode & PATH) && *cp == '-')
+ {
+ error(2,"%s: path component begins with '-'",path,fmtquote(buf, NiL, "'", 1, 0));
+ return -1;
+ }
+ while((c= *cp++) && c!='/')
+ if((mode & COMPONENTS) && !isport(c))
+ {
+ buf[0] = c;
+ buf[1] = 0;
+ error(2,"%s: '%s' not in portable character set",path,fmtquote(buf, NiL, "'", 1, 0));
+ return -1;
+ }
+ if((cp-cpold) > name_max)
+ goto err;
+ if(c==0)
+ break;
+ while(*cp=='/')
+ cp++;
+ }
+ if((cp-path) >= path_max)
+ {
+ error(2, "%s: pathname too long", path);
+ return -1;
+ }
+ return 0;
+ err:
+ error(2, "%s: component name %.*s too long", path, cp-cpold-1, cpold);
+ return -1;
+}
+
+int
+b_pathchk(int argc, char** argv, Shbltin_t* context)
+{
+ register int mode = 0;
+ register char* s;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'a':
+ mode |= COMPONENTS|PATH;
+ continue;
+ case 'p':
+ mode |= COMPONENTS;
+ continue;
+ case 'P':
+ mode |= PATH;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (!*argv || error_info.errors)
+ error(ERROR_usage(2),"%s", optusage(NiL));
+ while (s = *argv++)
+ pathchk(s, mode);
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/pids.c b/src/lib/libcmd/pids.c
new file mode 100644
index 0000000..638f3d3
--- /dev/null
+++ b/src/lib/libcmd/pids.c
@@ -0,0 +1,124 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#define FORMAT "PID=%(pid)d PPID=%(ppid)d PGID=%(pgid)d TID=%(tid)d SID=%(sid)d"
+
+static const char usage[] =
+"[-?\n@(#)$Id: pids (AT&T Research) 2011-08-27 $\n]"
+USAGE_LICENSE
+"[+NAME?pids - list calling shell process ids]"
+"[+DESCRIPTION?When invoked as a shell builtin, \bpids\b lists one or "
+ "more of the calling process ids determined by \bgetpid\b(2), "
+ "\bgetppid\b(2), \bgetpgrp\b(2), \btcgetpgrp\b(2) and \bgetsid\b(2). "
+ "Unknown or invalid ids have the value \b-1\b.]"
+"[f:format?List the ids specified by \aformat\a. \aformat\a follows "
+ "\bprintf\b(3) conventions, except that \bsfio\b(3) inline ids are used "
+ "instead of arguments: "
+ "%[-+]][\awidth\a[.\aprecis\a[.\abase\a]]]]]](\aid\a)\achar\a. The "
+ "supported \aid\as are:]:[format:=" FORMAT "]"
+ "{"
+ "[+pid?The process id.]"
+ "[+pgid?The process group id.]"
+ "[+ppid?The parent process id.]"
+ "[+tid|tty?The controlling terminal id.]"
+ "[+sid?The session id.]"
+ "}"
+"[+SEE ALSO?\bgetpid\b(2), \bgetppid\b(2), \bgetpgrp\b(2), "
+ "\btcgetpgrp\b(2), \bgetsid\b(2)]"
+;
+
+#include <cmd.h>
+#include <ast_tty.h>
+#include <sfdisc.h>
+
+/*
+ * sfkeyprintf() lookup
+ * handle==0 for heading
+ */
+
+static int
+key(void* handle, Sffmt_t* fp, const char* arg, char** ps, Sflong_t* pn)
+{
+ register char* s;
+ int fd;
+ long tid;
+
+ if (!(s = fp->t_str) || streq(s, "pid"))
+ *pn = getpid();
+ else if (streq(s, "pgid"))
+ *pn = getpgrp();
+ else if (streq(s, "ppid"))
+ *pn = getppid();
+ else if (streq(s, "tid") || streq(s, "tty"))
+ {
+ for (fd = 0; fd < 3; fd++)
+ if ((tid = tcgetpgrp(fd)) >= 0)
+ break;
+ *pn = tid;
+ }
+ else if (streq(s, "sid"))
+#if _lib_getsid
+ *pn = getsid(0);
+#else
+ *pn = -1;
+#endif
+ else if (streq(s, "format"))
+ *ps = (char*)handle;
+ else
+ {
+ error(2, "%s: unknown format identifier", s);
+ return 0;
+ }
+ return 1;
+}
+
+int
+b_pids(int argc, char** argv, Shbltin_t* context)
+{
+ char* format = 0;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'f':
+ format = opt_info.arg;
+ continue;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || *argv)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ if (!format)
+ format = FORMAT;
+ sfkeyprintf(sfstdout, format, format, key, NiL);
+ sfprintf(sfstdout, "\n");
+ return 0;
+}
diff --git a/src/lib/libcmd/rev.c b/src/lib/libcmd/rev.c
new file mode 100644
index 0000000..9841120
--- /dev/null
+++ b/src/lib/libcmd/rev.c
@@ -0,0 +1,168 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * rev [-l] [file ...]
+ *
+ * reverse the characters or lines of one or more files
+ *
+ * David Korn
+ * AT&T Laboratories
+ * dgk@research.att.com
+ *
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: rev (AT&T Research) 2007-11-29 $\n]"
+USAGE_LICENSE
+"[+NAME?rev - reverse the characters or lines of one or more files]"
+"[+DESCRIPTION?\brev\b copies one or more files to standard output "
+ "reversing the order of characters on every line of the file "
+ "or reversing the order of lines of the file if \b-l\b is specified.]"
+"[+?If no \afile\a is given, or if the \afile\a is \b-\b, \brev\b "
+ "copies from standard input starting at the current offset.]"
+"[l:line?Reverse the lines of the file.]"
+
+"\n"
+"\n[file ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All files copied successfully.]"
+ "[+>0?One or more files did not copy.]"
+"}"
+"[+SEE ALSO?\bcat\b(1), \btail\b(1)]"
+;
+
+#include <cmd.h>
+#include <rev.h>
+
+/*
+ * reverse the characters within a line
+ */
+static int rev_char(Sfio_t *in, Sfio_t *out)
+{
+ register int c;
+ register char *ep, *bp, *cp;
+ register wchar_t *wp, *xp;
+ register size_t n;
+ register size_t w;
+ if (mbwide())
+ {
+ wp = 0;
+ w = 0;
+ while(cp = bp = sfgetr(in,'\n',0))
+ {
+ ep = bp + (n=sfvalue(in)) - 1;
+ if (n > w)
+ {
+ w = roundof(n + 1, 1024);
+ if (!(wp = newof(wp, wchar_t, w, 0)))
+ {
+ error(ERROR_SYSTEM|2, "out of space");
+ return 0;
+ }
+ }
+ xp = wp;
+ while (cp < ep)
+ *xp++ = mbchar(cp);
+ cp = bp;
+ while (xp > wp)
+ cp += mbconv(cp, *--xp);
+ *cp++ = '\n';
+ if (sfwrite(out, bp, cp - bp) < 0)
+ {
+ if (wp)
+ free(wp);
+ return -1;
+ }
+ }
+ if (wp)
+ free(wp);
+ }
+ else
+ while(cp = bp = sfgetr(in,'\n',0))
+ {
+ ep = bp + (n=sfvalue(in)) -1;
+ while(ep > bp)
+ {
+ c = *--ep;
+ *ep = *bp;
+ *bp++ = c;
+ }
+ if(sfwrite(out,cp,n)<0)
+ return(-1);
+ }
+ return(0);
+}
+
+int
+b_rev(int argc, register char** argv, Shbltin_t* context)
+{
+ register Sfio_t *fp;
+ register char *cp;
+ register int n, line=0;
+ NOT_USED(argc);
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'l':
+ line=1;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if(error_info.errors)
+ error(ERROR_usage(2),"%s",optusage((char*)0));
+ n=0;
+ if(cp = *argv)
+ argv++;
+ do
+ {
+ if(!cp || streq(cp,"-"))
+ fp = sfstdin;
+ else if(!(fp = sfopen((Sfio_t*)0,cp,"r")))
+ {
+ error(ERROR_system(0),"%s: cannot open",cp);
+ n=1;
+ continue;
+ }
+ if(line)
+ line = rev_line(fp,sfstdout,sftell(fp));
+ else
+ line = rev_char(fp,sfstdout);
+ if(fp!=sfstdin)
+ sfclose(fp);
+ if(line < 0)
+ error(ERROR_system(1),"write failed");
+ }
+ while(cp= *argv++);
+ return(n);
+}
diff --git a/src/lib/libcmd/rev.h b/src/lib/libcmd/rev.h
new file mode 100644
index 0000000..c71e689
--- /dev/null
+++ b/src/lib/libcmd/rev.h
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * rev common definitions
+ */
+
+#ifndef _REVLIB_H
+#define _REVLIB_H
+
+#define rev_line _cmd_revline
+
+extern int rev_line(Sfio_t*, Sfio_t*, off_t);
+
+#endif
diff --git a/src/lib/libcmd/revlib.c b/src/lib/libcmd/revlib.c
new file mode 100644
index 0000000..afddbe9
--- /dev/null
+++ b/src/lib/libcmd/revlib.c
@@ -0,0 +1,112 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * common support for tail and rev
+ */
+
+#include <cmd.h>
+#include <rev.h>
+
+#define BUFSIZE SF_BUFSIZE
+#define rounddown(n,size) (((n)-1)&~((size)-1))
+
+/*
+ * copy the lines starting at offset <start> from in <in> to <out>
+ * in reverse order
+ */
+int rev_line(Sfio_t *in, Sfio_t *out, off_t start)
+{
+ register char *cp, *cpold;
+ register int n, nleft=0;
+ char buff[BUFSIZE];
+ off_t offset;
+ if(sfseek(in,(off_t)0,SEEK_CUR) < 0)
+ {
+ Sfio_t *tmp = sftmp(4*SF_BUFSIZE);
+ if(!tmp)
+ return(-1);
+ if(start>0 && sfmove(in, (Sfio_t*)0, start, -1) != start)
+ return(-1);
+ if(sfmove(in, tmp, SF_UNBOUND, -1) < 0 || !sfeof(in) || sferror(tmp))
+ return(-1);
+ in = tmp;
+ start=0;
+ }
+ if((offset = sfseek(in,(off_t)0,SEEK_END)) <= start)
+ return(0);
+ offset = rounddown(offset,BUFSIZE);
+ while(1)
+ {
+ n = BUFSIZE;
+ if(offset < start)
+ {
+ n -= (start-offset);
+ offset = start;
+ }
+ sfseek(in, offset, SEEK_SET);
+ if((n=sfread(in, buff, n)) <=0)
+ break;
+ cp = buff+n;
+ n = *buff;
+ *buff = '\n';
+ while(1)
+ {
+ cpold = cp;
+ if(nleft==0)
+ cp--;
+ if(cp==buff)
+ {
+ nleft= 1;
+ break;
+ }
+ while(*--cp != '\n');
+ if(cp==buff && n!='\n')
+ {
+ *cp = n;
+ nleft += cpold-cp;
+ break;
+ }
+ else
+ cp++;
+ if(sfwrite(out,cp,cpold-cp) < 0)
+ return(-1);
+ if(nleft)
+ {
+ if(nleft==1)
+ sfputc(out,'\n');
+ else if(sfmove(in,out,nleft,-1) != nleft)
+ return(-1);
+ nleft = 0;
+ }
+ }
+ if(offset <= start)
+ break;
+ offset -= BUFSIZE;
+ }
+ if(nleft)
+ {
+ sfseek(in, start, SEEK_SET);
+ if(sfmove(in,out,nleft,-1) != nleft)
+ return(-1);
+ }
+ return(0);
+}
diff --git a/src/lib/libcmd/rm.c b/src/lib/libcmd/rm.c
new file mode 100644
index 0000000..f9abab8
--- /dev/null
+++ b/src/lib/libcmd/rm.c
@@ -0,0 +1,417 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * rm [-fir] [file ...]
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: rm (AT&T Research) 2012-02-14 $\n]"
+USAGE_LICENSE
+"[+NAME?rm - remove files]"
+"[+DESCRIPTION?\brm\b removes the named \afile\a arguments. By default it"
+" does not remove directories. If a file is unwritable, the"
+" standard input is a terminal, and the \b--force\b option is not"
+" given, \brm\b prompts the user for whether to remove the file."
+" An affirmative response (\by\b or \bY\b) removes the file, a quit"
+" response (\bq\b or \bQ\b) causes \brm\b to exit immediately, and"
+" all other responses skip the current file.]"
+
+"[c|F:clear|clobber?Clear the contents of each file before removing by"
+" writing a 0 filled buffer the same size as the file, executing"
+" \bfsync\b(2) and closing before attempting to remove. Implemented"
+" only on systems that support \bfsync\b(2).]"
+"[d:directory?\bremove\b(3) (or \bunlink\b(2)) directories rather than"
+" \brmdir\b(2), and don't require that they be empty before removal."
+" The caller requires sufficient privilege, not to mention a strong"
+" constitution, to use this option. Even though the directory must"
+" not be empty, \brm\b still attempts to empty it before removal.]"
+"[f:force?Ignore nonexistent files, ignore no file operands specified,"
+" and never prompt the user.]"
+"[i:interactive|prompt?Prompt whether to remove each file."
+" An affirmative response (\by\b or \bY\b) removes the file, a quit"
+" response (\bq\b or \bQ\b) causes \brm\b to exit immediately, and"
+" all other responses skip the current file.]"
+"[r|R:recursive?Remove the contents of directories recursively.]"
+"[u:unconditional?If \b--recursive\b and \b--force\b are also enabled then"
+" the owner read, write and execute modes are enabled (if not already"
+" enabled) for each directory before attempting to remove directory"
+" contents.]"
+"[v:verbose?Print the name of each file before removing it.]"
+
+"\n"
+"\nfile ...\n"
+"\n"
+
+"[+SEE ALSO?\bmv\b(1), \brmdir\b(2), \bunlink\b(2), \bremove\b(3)]"
+;
+
+#include <cmd.h>
+#include <ls.h>
+#include <fts_fix.h>
+#include <fs3d.h>
+
+#define RM_ENTRY 1
+
+#define beenhere(f) (((f)->fts_number>>1)==(f)->fts_statp->st_nlink)
+#define isempty(f) (!((f)->fts_number&RM_ENTRY))
+#define nonempty(f) ((f)->fts_parent->fts_number|=RM_ENTRY)
+#define pathchunk(n) roundof(n,1024)
+#define retry(f) ((f)->fts_number=((f)->fts_statp->st_nlink<<1))
+
+typedef struct State_s /* program state */
+{
+ Shbltin_t* context; /* builtin context */
+ int clobber; /* clear out file data first */
+ int directory; /* remove(dir) not rmdir(dir) */
+ int force; /* force actions */
+ int fs3d; /* 3d enabled */
+ int interactive; /* prompt for approval */
+ int recursive; /* remove subtrees too */
+ int terminal; /* attached to terminal */
+ int uid; /* caller uid */
+ int unconditional; /* enable dir rwx on preorder */
+ int verbose; /* display each file */
+#if _lib_fsync
+ char buf[SF_BUFSIZE];/* clobber buffer */
+#endif
+} State_t;
+
+/*
+ * remove a single file
+ */
+
+static int
+rm(State_t* state, register FTSENT* ent)
+{
+ register char* path;
+ register int n;
+ int v;
+ struct stat st;
+
+ if (ent->fts_info == FTS_NS || ent->fts_info == FTS_ERR || ent->fts_info == FTS_SLNONE)
+ {
+ if (!state->force)
+ error(2, "%s: not found", ent->fts_path);
+ }
+ else if (state->fs3d && iview(ent->fts_statp))
+ fts_set(NiL, ent, FTS_SKIP);
+ else switch (ent->fts_info)
+ {
+ case FTS_DNR:
+ case FTS_DNX:
+ if (state->unconditional)
+ {
+ if (!beenhere(ent))
+ break;
+ if (!chmod(ent->fts_name, (ent->fts_statp->st_mode & S_IPERM)|S_IRWXU))
+ {
+ fts_set(NiL, ent, FTS_AGAIN);
+ break;
+ }
+ error_info.errors++;
+ }
+ else if (!state->force)
+ error(2, "%s: cannot %s directory", ent->fts_path, (ent->fts_info & FTS_NR) ? "read" : "search");
+ else
+ error_info.errors++;
+ fts_set(NiL, ent, FTS_SKIP);
+ nonempty(ent);
+ break;
+ case FTS_D:
+ case FTS_DC:
+ path = ent->fts_name;
+ if (path[0] == '.' && (!path[1] || path[1] == '.' && !path[2]) && (ent->fts_level > 0 || path[1]))
+ {
+ fts_set(NiL, ent, FTS_SKIP);
+ if (!state->force)
+ error(2, "%s: cannot remove", ent->fts_path);
+ else
+ error_info.errors++;
+ break;
+ }
+ if (!state->recursive)
+ {
+ fts_set(NiL, ent, FTS_SKIP);
+ error(2, "%s: directory", ent->fts_path);
+ break;
+ }
+ if (!beenhere(ent))
+ {
+ if (state->unconditional && (ent->fts_statp->st_mode & S_IRWXU) != S_IRWXU)
+ chmod(path, (ent->fts_statp->st_mode & S_IPERM)|S_IRWXU);
+ if (ent->fts_level > 0)
+ {
+ char* s;
+
+ if (ent->fts_accpath == ent->fts_name || !(s = strrchr(ent->fts_accpath, '/')))
+ v = !stat(".", &st);
+ else
+ {
+ path = ent->fts_accpath;
+ *s = 0;
+ v = !stat(path, &st);
+ *s = '/';
+ }
+ if (v)
+ v = st.st_nlink <= 2 || st.st_ino == ent->fts_parent->fts_statp->st_ino && st.st_dev == ent->fts_parent->fts_statp->st_dev || strchr(astconf("PATH_ATTRIBUTES", path, NiL), 'l');
+ }
+ else
+ v = 1;
+ if (v)
+ {
+ if (state->interactive)
+ {
+ if ((v = astquery(-1, "remove directory %s? ", ent->fts_path)) < 0 || sh_checksig(state->context))
+ return -1;
+ if (v > 0)
+ {
+ fts_set(NiL, ent, FTS_SKIP);
+ nonempty(ent);
+ }
+ }
+ if (ent->fts_info == FTS_D)
+ break;
+ }
+ else
+ {
+ ent->fts_info = FTS_DC;
+ error(1, "%s: hard link to directory", ent->fts_path);
+ }
+ }
+ else if (ent->fts_info == FTS_D)
+ break;
+ /*FALLTHROUGH*/
+ case FTS_DP:
+ if (isempty(ent) || state->directory)
+ {
+ path = ent->fts_name;
+ if (path[0] != '.' || path[1])
+ {
+ path = ent->fts_accpath;
+ if (state->verbose)
+ sfputr(sfstdout, ent->fts_path, '\n');
+ if ((ent->fts_info == FTS_DC || state->directory) ? remove(path) : rmdir(path))
+ switch (errno)
+ {
+ case ENOENT:
+ break;
+ case EEXIST:
+#if defined(ENOTEMPTY) && (ENOTEMPTY) != (EEXIST)
+ case ENOTEMPTY:
+#endif
+ if (ent->fts_info == FTS_DP && !beenhere(ent))
+ {
+ retry(ent);
+ fts_set(NiL, ent, FTS_AGAIN);
+ break;
+ }
+ /*FALLTHROUGH*/
+ default:
+ nonempty(ent);
+ if (!state->force)
+ error(ERROR_SYSTEM|2, "%s: directory not removed", ent->fts_path);
+ else
+ error_info.errors++;
+ break;
+ }
+ }
+ else if (!state->force)
+ error(2, "%s: cannot remove", ent->fts_path);
+ else
+ error_info.errors++;
+ }
+ else
+ {
+ nonempty(ent);
+ if (!state->force)
+ error(2, "%s: directory not removed", ent->fts_path);
+ else
+ error_info.errors++;
+ }
+ break;
+ default:
+ path = ent->fts_accpath;
+ if (state->verbose)
+ sfputr(sfstdout, ent->fts_path, '\n');
+ if (state->interactive)
+ {
+ if ((v = astquery(-1, "remove %s? ", ent->fts_path)) < 0 || sh_checksig(state->context))
+ return -1;
+ if (v > 0)
+ {
+ nonempty(ent);
+ break;
+ }
+ }
+ else if (!(ent->fts_info & FTS_SL) && !state->force && state->terminal && eaccess(path, W_OK))
+ {
+ if ((v = astquery(-1, "override protection %s for %s? ",
+#ifdef ETXTBSY
+ errno == ETXTBSY ? "``running program''" :
+#endif
+ ent->fts_statp->st_uid != state->uid ? "``not owner''" :
+ fmtmode(ent->fts_statp->st_mode & S_IPERM, 0) + 1, ent->fts_path)) < 0 ||
+ sh_checksig(state->context))
+ return -1;
+ if (v > 0)
+ {
+ nonempty(ent);
+ break;
+ }
+ }
+#if _lib_fsync
+ if (state->clobber && S_ISREG(ent->fts_statp->st_mode) && ent->fts_statp->st_size > 0)
+ {
+ if ((n = open(path, O_WRONLY)) < 0)
+ error(ERROR_SYSTEM|2, "%s: cannot clear data", ent->fts_path);
+ else
+ {
+ off_t c = ent->fts_statp->st_size;
+
+ for (;;)
+ {
+ if (write(n, state->buf, sizeof(state->buf)) != sizeof(state->buf))
+ {
+ error(ERROR_SYSTEM|2, "%s: data clear error", ent->fts_path);
+ break;
+ }
+ if (c <= sizeof(state->buf))
+ break;
+ c -= sizeof(state->buf);
+ }
+ fsync(n);
+ close(n);
+ }
+ }
+#endif
+ if (remove(path))
+ {
+ nonempty(ent);
+ switch (errno)
+ {
+ case ENOENT:
+ break;
+ default:
+ if (!state->force || state->interactive)
+ error(ERROR_SYSTEM|2, "%s: not removed", ent->fts_path);
+ else
+ error_info.errors++;
+ break;
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+int
+b_rm(int argc, register char** argv, Shbltin_t* context)
+{
+ State_t state;
+ FTS* fts;
+ FTSENT* ent;
+ int set3d;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
+ memset(&state, 0, sizeof(state));
+ state.context = context;
+ state.fs3d = fs3d(FS3D_TEST);
+ state.terminal = isatty(0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'd':
+ state.directory = 1;
+ continue;
+ case 'f':
+ state.force = 1;
+ state.interactive = 0;
+ continue;
+ case 'i':
+ state.interactive = 1;
+ state.force = 0;
+ continue;
+ case 'r':
+ case 'R':
+ state.recursive = 1;
+ continue;
+ case 'F':
+#if _lib_fsync
+ state.clobber = 1;
+#else
+ error(1, "%s not implemented on this system", opt_info.name);
+#endif
+ continue;
+ case 'u':
+ state.unconditional = 1;
+ continue;
+ case 'v':
+ state.verbose = 1;
+ continue;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (*argv && streq(*argv, "-") && !streq(*(argv - 1), "--"))
+ argv++;
+ if (error_info.errors || !*argv && !state.force)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ if (!*argv)
+ return 0;
+
+ /*
+ * do it
+ */
+
+ if (state.interactive)
+ state.verbose = 0;
+ state.uid = geteuid();
+ state.unconditional = state.unconditional && state.recursive && state.force;
+ if (state.recursive && state.fs3d)
+ {
+ set3d = state.fs3d;
+ state.fs3d = 0;
+ fs3d(0);
+ }
+ else
+ set3d = 0;
+ if (fts = fts_open(argv, FTS_PHYSICAL, NiL))
+ {
+ while (!sh_checksig(context) && (ent = fts_read(fts)) && !rm(&state, ent));
+ fts_close(fts);
+ }
+ else if (!state.force)
+ error(ERROR_SYSTEM|2, "%s: cannot remove", argv[0]);
+ if (set3d)
+ fs3d(set3d);
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/rmdir.c b/src/lib/libcmd/rmdir.c
new file mode 100644
index 0000000..f03b99b
--- /dev/null
+++ b/src/lib/libcmd/rmdir.c
@@ -0,0 +1,126 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * rmdir
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: rmdir (AT&T Research) 2006-08-24 $\n]"
+USAGE_LICENSE
+"[+NAME?rmdir - remove empty directories]"
+"[+DESCRIPTION?\brmdir\b deletes each given directory. The directory "
+ "must be empty; containing no entries other than \b.\b or \b..\b. "
+ "If a directory and a subdirectory of that directory are specified "
+ "as operands, the subdirectory must be specified before the parent "
+ "so that the parent directory will be empty when \brmdir\b attempts "
+ "to remove it.]"
+"[e:ignore-fail-on-non-empty?Ignore each non-empty directory failure.]"
+"[p:parents?Remove each explicit \adirectory\a argument directory that "
+ "becomes empty after its child directories are removed.]"
+"[s:suppress?Suppress the message printed on the standard error when "
+ "\b-p\b is in effect.]"
+"\n"
+"\ndirectory ...\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All directories deleted successfully.]"
+ "[+>0?One or more directories could not be deleted.]"
+"}"
+"[+SEE ALSO?\bmkdir\b(1), \brm\b(1), \brmdir\b(2), \bunlink\b(2)]"
+;
+
+#include <cmd.h>
+
+int
+b_rmdir(int argc, char** argv, Shbltin_t* context)
+{
+ register char* dir;
+ register char* end;
+ register int n;
+ int eflag = 0;
+ int pflag = 0;
+ int sflag = 0;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'e':
+ eflag = 1;
+ continue;
+ case 'p':
+ pflag = 1;
+ continue;
+ case 's':
+ sflag = 1;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || !*argv)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if (!pflag)
+ sflag = 0;
+ while (dir = *argv++)
+ {
+ end = dir;
+ if (pflag) end += strlen(dir);
+ n = 0;
+ for (;;)
+ {
+ if (rmdir(dir) < 0)
+ {
+ if (!eflag || errno != EEXIST
+#ifdef ENOTEMPTY
+ && errno != ENOTEMPTY
+#endif
+ )
+ {
+ if (sflag)
+ error_info.errors++;
+ else
+ error(ERROR_system(0), "%s: cannot remove", dir);
+ }
+ break;
+ }
+ if (n) *end = '/';
+ else n = 1;
+ do if (end <= dir) goto next; while (*--end != '/');
+ do if (end <= dir) goto next; while (*(end - 1) == '/' && end--);
+ *end = 0;
+ }
+ next: ;
+ }
+ return(error_info.errors != 0);
+}
+
diff --git a/src/lib/libcmd/stty.c b/src/lib/libcmd/stty.c
new file mode 100644
index 0000000..9afcd58
--- /dev/null
+++ b/src/lib/libcmd/stty.c
@@ -0,0 +1,971 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * stty.c
+ * Written by David Korn
+ * Tue Apr 4 10:46:00 EDT 1995
+ */
+
+static const char usage[] =
+"[-?@(#)$Id: stty (AT&T Research) 2010-04-01 $\n]"
+USAGE_LICENSE
+"[+NAME?stty - set or get terminal modes]"
+"[+DESCRIPTION?\bstty\b sets certain terminal I/O modes for the device "
+ "that is the current standard input; without arguments, it writes the "
+ "settings of certain modes to standard output.]"
+"[a:all?Writes to standard output all of the mode settings.]"
+"[f|F:fd|file?Use \afd\a as the terminal fd.]#[fd:=0]"
+"[g:save?Writes the current settings to standard output in a form that "
+ "can be used as an argument to another \bstty\b command. The \brows\b "
+ "and \bcolumns\b values are not included.]"
+"[t:terminal-group?Print the terminal group id of the device, -1 if "
+ "unknown.]"
+"\n"
+"\n[mode ...]\n"
+"\n"
+"[+EXTENDED DESCRIPTION?Modes are specified either as a single name or "
+ "as a name followed by a value. As indicated below, many of the mode "
+ "names can be preceded by a \b-\b to negate its meaning. Modes are "
+ "listed by group corresponding to field in the \btermios\b structure "
+ "defined in \b<termios.h>\b. Modes in the last group are implemented "
+ "using options in the previous groups. Note that many combinations of "
+ "modes make no sense, but no sanity checking is performed. The modes are "
+ "selected from the following:]"
+ "{\fabc\f}"
+"[+EXIT STATUS?]"
+ "{"
+ "[+0?All modes reported or set successfully.]"
+ "[+>0?Standard input not a terminaol or one or more modes "
+ "failed.]"
+ "}"
+"[+SEE ALSO?\btegetattr\b(2), \btcsetattr\b(2), \bioctl\b(2)]"
+;
+
+#include <cmd.h>
+#include <ccode.h>
+#include <ctype.h>
+#include <ast_tty.h>
+#if _sys_ioctl
+#include <sys/ioctl.h>
+#endif
+
+#define C(x) ERROR_catalog(x)
+
+#ifndef _POSIX_VDISABLE
+# define _POSIX_VDISABLE 0
+#endif
+
+#ifndef NCCS
+# ifdef NCC
+# define NCCS NCC
+# else
+# define NCCS elementsof(((struct termio*)0)->c_cc)
+# endif
+#endif
+
+/* command options */
+#define A_FLAG 1
+#define G_FLAG 2
+#define T_FLAG 4
+
+/* termios fields */
+#define C_FLAG 1
+#define C_LINE 2
+#define C_SPEED 3
+#define I_FLAG 4
+#define O_FLAG 5
+#define L_FLAG 6
+#define T_CHAR 7
+#define W_SIZE 8
+
+#define BIT 1
+#define BITS 2
+#define NUM 3
+#define CHAR 4
+#define SPEED 5
+#define SIZE 6
+#define MIXED 7
+#define SANE 8
+#define COOKED 9
+#define CASE 10
+#define TABS 11
+#define WIND 12
+
+#undef SS /* who co-opted this namespace? */
+
+#define IG 0x0001 /* ignore display */
+#define NL 0x0002 /* entry ends line of display */
+#define SS 0x0004 /* set in sane mode */
+#define US 0x0010 /* unset in sane mode */
+
+typedef struct tty_s
+{
+ const char name[8];
+ unsigned char type;
+ unsigned char field;
+ short flags;
+ unsigned long mask;
+ unsigned long val;
+ const char description[76];
+} Tty_t;
+
+static const Tty_t Ttable[] =
+{
+#ifdef CBAUD
+{ "ispeed", NUM, C_SPEED,0, CBAUD, 0, C("\an\a is the input baud rate") },
+{ "ospeed", NUM, C_SPEED,0, CBAUD, 0, C("\an\a is the output baud rate") },
+{ "speed", NUM, C_SPEED,IG, CBAUD },
+#endif
+{ "0", SPEED, C_FLAG, 0, B0 },
+{ "50", SPEED, C_FLAG, 0, B50 },
+{ "75", SPEED, C_FLAG, 0, B75 },
+{ "110", SPEED, C_FLAG, 0, B110 },
+{ "134", SPEED, C_FLAG, 0, B134 },
+{ "150", SPEED, C_FLAG, 0, B150 },
+{ "200", SPEED, C_FLAG, 0, B200 },
+{ "300", SPEED, C_FLAG, 0, B300 },
+{ "600", SPEED, C_FLAG, 0, B600 },
+{ "1200", SPEED, C_FLAG, 0, B1200 },
+{ "1800", SPEED, C_FLAG, 0, B1800 },
+{ "2400", SPEED, C_FLAG, 0, B2400 },
+{ "4800", SPEED, C_FLAG, 0, B4800 },
+{ "9600", SPEED, C_FLAG, 0, B9600 },
+{ "19200", SPEED, C_FLAG, 0, B19200 },
+{ "38400", SPEED, C_FLAG, 0, B38400 },
+
+#ifdef TIOCSWINSZ
+{ "rows", WIND, W_SIZE, IG, 0, 24, C("\an\a is the number of lines for display") },
+{ "cols", WIND, W_SIZE, IG, 1, 80, C("\an\a is the number of columns for display") },
+{ "columns", WIND, W_SIZE, IG, 1, 80, C("Same as \bcols\b") },
+#endif
+{ "intr", CHAR, T_CHAR, SS, VINTR, 'C', C("Send an interrupt signal") },
+{ "quit", CHAR, T_CHAR, SS, VQUIT, '|', C("Send a quit signal") },
+{ "erase", CHAR, T_CHAR, SS, VERASE, 'H', C("Erase the last character entered") },
+{ "kill", CHAR, T_CHAR, NL|SS, VKILL, 'U', C("Erase the current line") },
+{ "eof", CHAR, T_CHAR, SS, VEOF, 'D', C("Send an end of file") },
+#ifdef VEOL2
+{ "eol2", CHAR, T_CHAR, US, VEOL2, _POSIX_VDISABLE, C("Alternate character to end the line") },
+#endif /* VEOL2 */
+#ifdef VSWTCH
+{ "swtch", CHAR, T_CHAR, US, VSWTCH, _POSIX_VDISABLE, C("Switch to a different shell layer") },
+#endif /* VSWTCH */
+{ "eol", CHAR, T_CHAR, NL|US, VEOL, _POSIX_VDISABLE, C("End the line") },
+#ifdef VSTART
+{ "start", CHAR, T_CHAR, SS, VSTART, 'Q', C("Restart the output after stopping it") },
+#endif /* VSTART */
+#ifdef VSTOP
+{ "stop", CHAR, T_CHAR, SS, VSTOP, 'S', C("Stop the output") },
+#endif /* VSTOP */
+#ifdef VDSUSP
+{ "dsusp", CHAR, T_CHAR, SS, VDSUSP, 'Y', C("Send a terminal stop signal after flushing the input") },
+#endif /* VDSUSP */
+#ifdef VSUSP
+{ "susp", CHAR, T_CHAR, NL|SS, VSUSP, 'Z', C("Send a terminal stop signal") },
+#endif /* VSUSP */
+#ifdef VREPRINT
+{ "rprnt", CHAR, T_CHAR, SS, VREPRINT, 'R', C("Redraw the current line") },
+#endif /* VREPRINT */
+#ifdef VDISCARD
+{ "flush", CHAR, T_CHAR, SS, VDISCARD, 'O', C("Discard output") },
+#endif /* VDISCARD */
+#ifdef VWERASE
+{ "werase", CHAR, T_CHAR, SS, VWERASE, 'W', C("Erase the last word entered") },
+#endif /* VWERASE */
+#ifdef VLNEXT
+{ "lnext", CHAR, T_CHAR, NL|SS, VLNEXT, 'V', C("Enter the next input character literally") },
+#endif /* VLNEXT */
+
+#if _mem_c_line_termios
+{ "line", NUM, C_LINE, 0, 0, 0, C("Line discipline number") },
+#endif
+{ "min", NUM, T_CHAR, 0, VMIN, 0, C("Mininmum number of characters to read in raw mode") },
+{ "time", NUM, T_CHAR, 0, VTIME, 0, C("Number of .1 second intervals with raw mode") },
+
+{ "parenb", BIT, C_FLAG, 0, PARENB, PARENB, C("Enable (disable) parity generation and detection") },
+{ "parodd", BIT, C_FLAG, 0, PARODD, PARODD, C("Use odd (even) parity") },
+#ifdef PAREXT
+{ "parext", BIT, C_FLAG, 0, PAREXT, PAREXT },
+#endif /* PAREXT */
+#ifdef CREAD
+{ "cread", BIT, C_FLAG, SS, CREAD, CREAD, C("Enable (disable) input") },
+#endif /* CREAD */
+{ "cs5", SIZE, C_FLAG, 0, CSIZE, CS5 , C("Char size 5") },
+{ "cs6", SIZE, C_FLAG, 0, CSIZE, CS6 , C("Char size 6") },
+{ "cs7", SIZE, C_FLAG, 0, CSIZE, CS7 , C("Char size 7") },
+{ "cs8", SIZE, C_FLAG, 0, CSIZE, CS8 , C("Char size 8") },
+{ "hupcl", BIT, C_FLAG, 0, HUPCL, HUPCL, C("Hangup (do not hangup) connection on last close") },
+{ "hup", BIT, C_FLAG, IG, HUPCL, HUPCL, C("Same as \bhupcl\b") },
+{ "cstopb", BIT, C_FLAG, 0, CSTOPB, CSTOPB, C("Use two (one) stop bits") },
+#ifdef CRTSCTS
+{ "crtscts", BIT, C_FLAG, 0, CRTSCTS, CRTSCTS, C("Enable (disable) RTS/CTS handshaking") },
+#endif /* CRTSCTS */
+{ "clocal", BIT, C_FLAG, NL, CLOCAL, CLOCAL, C("Disable (enable) modem control signals") },
+
+{ "ignbrk", BIT, I_FLAG, US, IGNBRK, IGNBRK, C("Ignore (do not ignore) break characters") },
+{ "brkint", BIT, I_FLAG, SS, BRKINT, BRKINT, C("Generate (do not generate) INTR signal on break") },
+{ "ignpar", BIT, I_FLAG, 0, IGNPAR, IGNPAR, C("Ignore (do not ignore) characters with parity errors") },
+{ "parmrk", BIT, I_FLAG, 0, PARMRK, PARMRK, C("Mark (do not mark) parity errors") },
+{ "inpck", BIT, I_FLAG, 0, INPCK, INPCK, C("Enable (disable) input parity checking") },
+{ "istrip", BIT, I_FLAG, 0, ISTRIP, ISTRIP, C("Clear (do not clear) high bit of input characters") },
+{ "inlcr", BIT, I_FLAG, US, INLCR, INLCR, C("Translate (do not translate) carriage return to newline") },
+{ "igncr", BIT, I_FLAG, US, IGNCR, IGNCR, C("Ignore (do not ignore) carriage return") },
+#ifdef IUCLC
+{ "iuclc", BIT, I_FLAG, US, IUCLC, IUCLC, C("Map (do not map) upper-case to lower case") },
+#endif /* IUCLC */
+{ "ixon", BIT, I_FLAG, 0, IXON, IXON, C("Enable (disable) XON/XOFF flow control. \bstop\b character stops output") },
+#ifdef IXANY
+{ "ixany", BIT, I_FLAG, US, IXANY, IXANY, C("Any character (only start character) can restart output.") },
+{ "decctlq", BIT, I_FLAG, IG, IXANY, 0, C("Same as \b-ixany\b") },
+#endif /* IXANY */
+{ "ixoff", BIT, I_FLAG, US, IXOFF, IXOFF, C("Disable (enable) XON/XOFF flow control") },
+#ifdef IMAXBEL
+{ "imaxbel", BIT, I_FLAG, SS, IMAXBEL, IMAXBEL, C("Beep (do not beep) if a character arrives with full input buffer") },
+#endif /* IMAXBEL */
+{ "icrnl", BIT, I_FLAG, NL|SS, ICRNL, ICRNL, C("Translate (do not translate) carriage return to newline") },
+
+{ "isig", BIT, L_FLAG, SS, ISIG, ISIG, C("Enable (disable) \bintr\b, \bquit\b, and \bsusp\b special characters") },
+{ "icanon", BIT, L_FLAG, SS, ICANON, ICANON, C("Enable (disable) \berase\b, \bkill\b, \bwerase\b, and \brprnt\b special characters") },
+{ "icannon", BIT, L_FLAG, SS, ICANON, ICANON },
+#ifdef IEXTEN
+{ "iexten", BIT, L_FLAG, SS, IEXTEN, IEXTEN, C("Enable (disable) non-POSIX special characters") },
+#endif /* IEXTEN */
+{ "echo", BIT, L_FLAG, SS, ECHO|ECHONL, ECHO|ECHONL, C("Echo (do not echo) input characters") },
+{ "echoe", BIT, L_FLAG, SS, ECHOE, ECHOE, C("Echo (do not echo) erase characters as backspace-space-backspace") },
+{ "echok", BIT, L_FLAG, SS, ECHOK, ECHOK, C("Echo (do not echo) a newline after a kill character") },
+#ifdef ECHOKE
+{ "echoke", BIT, L_FLAG, SS, ECHOKE, ECHOKE, C("Echo (do not echo) a newline after a kill character") },
+#endif
+{ "lfkc", BIT, L_FLAG, IG, ECHOK, ECHOK, C("Same as \bechok\b (\b-echok\b); obsolete") },
+{ "echonl", BIT, L_FLAG, SS, ECHONL, ECHONL,"Echo (do not echo) newline even if not echoing other character" },
+#ifdef ECHOCTL
+{ "echoctl", BIT, L_FLAG, SS, ECHOCTL, ECHOCTL, C("Echo (do not echo) control characters as \b^\b\ac\a") },
+#else
+#define ECHOCTL 0
+#endif /* ECHOCTL */
+#ifdef ECHOPRT
+{ "echoprt", BIT, L_FLAG, US, ECHOPRT, ECHOPRT, C("Echo (do not echo) erased characters backward, between '\\' and '/'") },
+#else
+#define ECHOPRT 0
+#endif /* ECHOPRT */
+#ifdef XCASE
+{ "xcase", BIT, L_FLAG, US, XCASE, XCASE, C("Enable (disable) \bicanon\b uppercase as lowercase with '\\' prefix") },
+#endif /* XCASE */
+#ifdef DEFECHO
+{ "defecho", BIT, L_FLAG, 0, DEFECHO, DEFECHO },
+#endif /* DEFECHO */
+#ifdef FLUSHO
+{ "flusho", BIT, L_FLAG, 0, FLUSHO, FLUSHO, C("Discard (do not discard) written data. Cleared by subsequent input") },
+#endif /* FLUSHO */
+#ifdef PENDIN
+{ "pendin", BIT, L_FLAG, 0, PENDIN, PENDIN, C("Redisplay pending input at next read and then automatically clear \bpendin\b") },
+#endif /* PENDIN */
+{ "noflsh", BIT, L_FLAG, US, NOFLSH, NOFLSH, C("Disable (enable) flushing after \bintr\b and \bquit\b special characters") },
+#ifdef TOSTOP
+{ "tostop", BIT, L_FLAG, NL|US, TOSTOP, TOSTOP, C("Stop (do not stop) background jobs that try to write to the terminal") },
+#endif /* TOSTOP */
+#ifdef OLCUC
+{ "olcuc", BIT, O_FLAG, US, OLCUC, OLCUC, C("Translate (do not translate) lowercase characters to uppercase") },
+#endif /* OLCUC */
+#ifdef ONLCR
+{ "onlcr", BIT, O_FLAG, SS, ONLCR, ONLCR, C("Translate (do not translate) newline to carriage return-newline") },
+#endif /* ONLCR */
+#ifdef ONLRET
+{ "onlret", BIT, O_FLAG, US, ONLRET, ONLRET, C("Newline performs (does not perform) a carriage return") },
+#endif /* ONLRET */
+#ifdef OCRNL
+{ "ocrnl", BIT, O_FLAG, US, OCRNL, OCRNL, C("Translate (do not translate) carriage return to newline") },
+#endif /* OCRNL */
+#ifdef ONOCR
+{ "onocr", BIT, O_FLAG, US, ONOCR, ONOCR, C("Do not (do) print carriage returns in the first column") },
+#endif /* ONOCR */
+#ifdef OFILL
+{ "ofill", BIT, O_FLAG, US, OFILL, OFILL, C("Use fill characters (use timing) for delays") },
+#endif /* OFILL */
+#ifdef OFDEL
+{ "ofdel", BIT, O_FLAG, US, OFDEL, OFDEL, C("Use DEL (NUL) as fill characters for delays") },
+#endif /* OFDEL */
+{ "opost", BIT, O_FLAG, SS, OPOST, OPOST, C(" Postprocess (do not postprocess) output") },
+#ifdef CRDLY
+{ "cr0", BITS, O_FLAG, IG|SS, CRDLY, CR0 },
+{ "cr1", BITS, O_FLAG, US, CRDLY, CR1 },
+{ "cr2", BITS, O_FLAG, US, CRDLY, CR2 },
+{ "cr3", BITS, O_FLAG, US, CRDLY, CR3 },
+#endif
+#ifdef NLDLY
+{ "nl0", BITS, O_FLAG, IG|US, NLDLY, NL0 },
+{ "nl1", BITS, O_FLAG, US, NLDLY, NL1 },
+#endif
+#ifdef TABDLY
+{ "tabs", TABS, O_FLAG, IG, TABDLY, TAB3, C("Preserve (expand to spaces) tabs") },
+#ifdef TAB0
+{ "tab0", BITS, O_FLAG, IG|SS, TABDLY, TAB0 },
+#endif
+#ifdef TAB1
+{ "tab1", BITS, O_FLAG, US, TABDLY, TAB1 },
+#endif
+#ifdef TAB2
+{ "tab2", BITS, O_FLAG, US, TABDLY, TAB2 },
+#endif
+{ "tab3", BITS, O_FLAG, US, TABDLY, TAB3 },
+#endif
+#ifdef BSDLY
+{ "bs0", BITS, O_FLAG, IG|SS, BSDLY, BS0 },
+{ "bs1", BITS, O_FLAG, US, BSDLY, BS1 },
+#endif
+#ifdef VTDLY
+{ "vt0", BITS, O_FLAG, IG|SS, VTDLY, VT0 },
+{ "vt1", BITS, O_FLAG, US, VTDLY, VT1 },
+#endif
+#ifdef FFDLY
+{ "ff0", BITS, O_FLAG, IG|SS, FFDLY, FF0 },
+{ "ff1", BITS, O_FLAG, US, FFDLY, FF1 },
+#endif
+{ "", MIXED, O_FLAG, NL|IG },
+
+{ "evenp", MIXED, C_FLAG, IG, PARENB, 0, C("Same as \bparenb -parodd cs7\b") },
+{ "oddp", MIXED, C_FLAG, IG, PARODD, 0, C("Same as \bparenb parodd cs7\b") },
+{ "parity", MIXED, C_FLAG, IG, 0, 0, C("Same as parenb \b-parodd cs7\b") },
+{ "ek", MIXED, C_FLAG, IG, 0, 0, C("Reset the \berase\b and \bkill\b special characters to their default values") },
+{ "sane", SANE, C_FLAG, IG, 0, 0, C("Reset all modes to some reasonable values") },
+{ "cooked", COOKED, C_FLAG, IG, 0, 0, C("Disable raw input and output") },
+{ "raw", COOKED, C_FLAG, IG, 0, 0, C("Enable raw input and output") },
+{ "lcase", CASE, C_FLAG, IG, 0 , 0, C("Set \bxcase\b, \biuclc\b, and \bolcuc\b") },
+{ "LCASE", CASE, C_FLAG, IG, 0 , 0, C("Same as \blcase\b") }
+};
+
+#if CC_NATIVE == CC_ASCII
+#define cntl(x) (((x)=='?')?0177:((x)&037))
+#else
+#define cntl(x) (((x)=='?')?ccmapc(0177,CC_ASCII,CC_NATIVE):ccmapc(ccmapc(x,CC_NATIVE,CC_ASCII)&037,CC_ASCII,CC_NATIVE))
+#endif
+
+static void sane(register struct termios *sp)
+{
+ register const Tty_t* tp;
+
+ for (tp = Ttable; tp < &Ttable[elementsof(Ttable)]; tp++)
+ if (tp->flags & (SS|US))
+ switch (tp->type)
+ {
+ case BIT:
+ case BITS:
+ switch (tp->field)
+ {
+ case C_FLAG:
+ if (tp->flags & SS)
+ sp->c_cflag |= tp->mask;
+ else
+ sp->c_cflag &= ~tp->mask;
+ break;
+ case I_FLAG:
+ if (tp->flags & SS)
+ sp->c_iflag |= tp->mask;
+ else
+ sp->c_iflag &= ~tp->mask;
+ break;
+ case O_FLAG:
+ if (tp->flags & SS)
+ sp->c_oflag |= tp->mask;
+ else
+ sp->c_oflag &= ~tp->mask;
+ break;
+ case L_FLAG:
+ if (tp->flags & SS)
+ sp->c_lflag |= tp->mask;
+ else
+ sp->c_lflag &= ~tp->mask;
+ break;
+ }
+ break;
+ case CHAR:
+ sp->c_cc[tp->mask] = cntl(tp->val);
+ break;
+ }
+}
+
+static int gin(char *arg,struct termios *sp)
+{
+ register int i;
+ if(*arg++ != ':')
+ return(0);
+ sp->c_iflag = strtol(arg,&arg,16);
+ if(*arg++ != ':')
+ return(0);
+ sp->c_oflag = strtol(arg,&arg,16);
+ if(*arg++ != ':')
+ return(0);
+ sp->c_cflag = strtol(arg,&arg,16);
+ if(*arg++ != ':')
+ return(0);
+ sp->c_lflag = strtol(arg,&arg,16);
+ if(*arg++ != ':')
+ return(0);
+ for(i=0;i< NCCS; i++)
+ {
+ sp->c_cc[i] = strtol(arg,&arg,16);
+ if(*arg++ != ':')
+ return(0);
+ }
+#if _mem_c_line_termios
+ sp->c_line =
+#endif
+ strtol(arg,&arg,16);
+ if(*arg++ != ':')
+ return(0);
+ i = strtol(arg,&arg,16);
+ if(*arg++ != ':')
+ return(0);
+ cfsetispeed(sp, i);
+ i = strtol(arg,&arg,16);
+ if(*arg++ != ':')
+ return(0);
+ cfsetospeed(sp, i);
+ if(*arg)
+ return(0);
+ return(1);
+}
+
+static void gout(struct termios *sp)
+{
+ register int i;
+ sfprintf(sfstdout,":%x",sp->c_iflag);
+ sfprintf(sfstdout,":%x",sp->c_oflag);
+ sfprintf(sfstdout,":%x",sp->c_cflag);
+ sfprintf(sfstdout,":%x",sp->c_lflag);
+ for(i=0;i< NCCS; i++)
+ sfprintf(sfstdout,":%x",sp->c_cc[i]);
+#if _mem_c_line_termios
+ sfprintf(sfstdout,":%x", sp->c_line);
+#else
+ sfprintf(sfstdout,":%x", 0);
+#endif
+ sfprintf(sfstdout,":%x",cfgetispeed(sp));
+ sfprintf(sfstdout,":%x",cfgetospeed(sp));
+ sfprintf(sfstdout,":\n");
+}
+
+static void output(struct termios *sp, int flags)
+{
+ const Tty_t *tp;
+ struct termios tty;
+ register int delim = ' ';
+ register int i,off,off2;
+ char schar[2];
+ unsigned int ispeed = cfgetispeed(sp);
+ unsigned int ospeed = cfgetospeed(sp);
+ if(flags&G_FLAG)
+ {
+ gout(sp);
+ return;
+ }
+ tty = *sp;
+ sane(&tty);
+ for(i=0; i < elementsof(Ttable); i++)
+ {
+ tp= &Ttable[i];
+ if(tp->flags&IG)
+ {
+ if(tp->flags&NL)
+ sfputc(sfstdout,'\n');
+ continue;
+ }
+ switch(tp->type)
+ {
+ case BIT:
+ case BITS:
+ off = off2 = 1;
+ switch(tp->field)
+ {
+ case C_FLAG:
+ if(sp->c_cflag&tp->mask)
+ off = 0;
+ if(tty.c_cflag&tp->mask)
+ off2 = 0;
+ break;
+ case I_FLAG:
+ if(sp->c_iflag&tp->mask)
+ off = 0;
+ if(tty.c_iflag&tp->mask)
+ off2 = 0;
+ break;
+ case O_FLAG:
+ if((sp->c_oflag&tp->mask)==tp->val)
+ off = 0;
+ if(tty.c_oflag&tp->mask)
+ off2 = 0;
+ break;
+ case L_FLAG:
+ if(sp->c_lflag&tp->mask)
+ off = 0;
+ if(tty.c_lflag&tp->mask)
+ off2 = 0;
+ }
+ if(tp->flags&NL)
+ delim = '\n';
+ if(!flags && off==off2)
+ continue;
+ if(!off)
+ sfprintf(sfstdout,"%s%c",tp->name,delim);
+ else if(tp->type==BIT)
+ sfprintf(sfstdout,"-%s%c",tp->name,delim);
+ delim = ' ';
+ break;
+
+ case CHAR:
+ off = sp->c_cc[tp->mask];
+ if(tp->flags&NL)
+ delim = '\n';
+ if(!flags && off==(unsigned char)tty.c_cc[tp->mask])
+ continue;
+ if(off==_POSIX_VDISABLE)
+ sfprintf(sfstdout,"%s = <undef>;%c",tp->name,delim);
+ else if(isprint(off&0xff))
+ sfprintf(sfstdout,"%s = %c;%c",tp->name,off,delim);
+ else
+#if CC_NATIVE == CC_ASCII
+ sfprintf(sfstdout,"%s = ^%c;%c",tp->name,off==0177?'?':(off^0100),delim);
+#else
+ {
+ off = ccmapc(off, CC_NATIVE, CC_ASCII);
+ sfprintf(sfstdout,"%s = ^%c;%c",tp->name,off==0177?'?':ccmapc(off^0100,CC_ASCII,CC_NATIVE),delim);
+ }
+#endif
+ delim = ' ';
+ break;
+ case SIZE:
+ if((sp->c_cflag&CSIZE)!=tp->mask)
+ continue;
+ if(flags || (sp->c_cflag&CSIZE) != (tty.c_cflag&CSIZE))
+ sfprintf(sfstdout,"%s ",tp->name);
+ break;
+ case SPEED:
+ if(tp->mask==ispeed)
+ {
+ if(ispeed!=ospeed)
+ schar[0]='i';
+ else
+ schar[0]=0;
+ }
+ else if(tp->mask==ospeed)
+ schar[0]='o';
+ else
+ continue;
+ schar[1] = 0;
+#ifdef TIOCSWINSZ
+ {
+ struct winsize win;
+ off = ioctl(0,TIOCGWINSZ,&win);
+ if(off>=0)
+ sfprintf(sfstdout,"%sspeed %s baud; rows %d; columns %d;\n",schar,tp->name,win.ws_row,win.ws_col);
+ }
+ if(off<0)
+#endif
+ sfprintf(sfstdout,"%sspeed %s baud;\n",schar,tp->name);
+ }
+ }
+ if(delim=='\n')
+ sfputc(sfstdout,'\n');
+}
+
+static const Tty_t *lookup(const char *name)
+{
+ register int i;
+ for(i=0; i < elementsof(Ttable); i++)
+ {
+ if(strcmp(Ttable[i].name,name)==0)
+ return(&Ttable[i]);
+ }
+ return(0);
+
+}
+
+static const Tty_t *getspeed(unsigned long val)
+{
+ register int i;
+ for(i=0; i < elementsof(Ttable); i++)
+ {
+ if(Ttable[i].type==SPEED && Ttable[i].mask==val)
+ return(&Ttable[i]);
+ }
+ return(0);
+}
+
+static int gettchar(register const char *cp)
+{
+ if(*cp==0)
+ return(-1);
+ if(cp[1]==0)
+ return((unsigned)cp[0]);
+ if(*cp=='^' && cp[1] && cp[2]==0)
+ {
+ switch(cp[1])
+ {
+ case '-':
+ return(-1);
+ default:
+ return(cntl(cp[1]));
+ }
+ }
+ if(streq(cp,"undef") || streq(cp,"<undef>"))
+ return(-1);
+ return(*((unsigned char*)cp));
+}
+
+static void set(char *argv[], struct termios *sp)
+{
+ const Tty_t *tp;
+ register int c,off;
+ char *cp;
+ char *ep;
+ while(cp = *argv++)
+ {
+ off = 0;
+ if(*cp=='-')
+ {
+ cp++;
+ off=1;
+ }
+ if(!(tp=lookup(cp)) || (off && (tp->type!=BIT) && (tp->type!=TABS)))
+ error(ERROR_exit(1),"%s: unknown mode",cp);
+ switch(tp->type)
+ {
+ case CHAR:
+ if(off)
+ error(ERROR_exit(1),"%s: unknown mode",cp);
+ if(!*argv)
+ error(ERROR_exit(1),"missing argument to %s",cp);
+ c = gettchar(*argv++);
+ if(c>=0)
+ sp->c_cc[tp->mask] = c;
+ else
+ sp->c_cc[tp->mask] = _POSIX_VDISABLE;
+ break;
+ case BIT: case BITS:
+ switch(tp->field)
+ {
+ case C_FLAG:
+ if(off)
+ sp->c_cflag &= ~tp->mask;
+ else
+ sp->c_cflag |= tp->mask;
+ break;
+ case I_FLAG:
+ if(off)
+ sp->c_iflag &= ~tp->mask;
+ else
+ sp->c_iflag |= tp->mask;
+ break;
+ case O_FLAG:
+ sp->c_oflag &= ~tp->mask;
+ sp->c_oflag |= tp->val;
+ break;
+ case L_FLAG:
+ if(off)
+ sp->c_lflag &= ~tp->mask;
+ else
+ sp->c_lflag |= tp->mask;
+ break;
+ }
+ break;
+ case TABS:
+ sp->c_oflag &= ~tp->mask;
+ if(off)
+ sp->c_oflag |= tp->val;
+ break;
+#ifdef TIOCSWINSZ
+ case WIND:
+ {
+ struct winsize win;
+ int n;
+ if(ioctl(0,TIOCGWINSZ,&win)<0)
+ error(ERROR_system(1),"cannot set %s",tp->name);
+ if(!(cp= *argv))
+ {
+ sfprintf(sfstdout,"%d\n",tp->mask?win.ws_col:win.ws_row);
+ break;
+ }
+ argv++;
+ n=strtol(cp,&cp,10);
+ if(*cp)
+ error(ERROR_system(1),"%d: invalid number of %s",argv[-1],tp->name);
+ if(tp->mask)
+ win.ws_col = n;
+ else
+ win.ws_row = n;
+ if(ioctl(0,TIOCSWINSZ,&win)<0)
+ error(ERROR_system(1),"cannot set %s",tp->name);
+ break;
+ }
+#endif
+ case NUM:
+ cp = *argv;
+ if (!cp)
+ {
+ if (tp->field == C_SPEED)
+ {
+ if (tp = getspeed(*tp->name == 'i' ? cfgetispeed(sp) : cfgetospeed(sp)))
+ sfprintf(sfstdout, "%s\n", tp->name);
+ break;
+ }
+ error(ERROR_exit(1), "%s: missing numeric argument", tp->name);
+ }
+ argv++;
+ c = (int)strtol(cp, &ep, 10);
+ if (*ep)
+ error(ERROR_exit(1), "%s: %s: numeric argument expected", tp->name, cp);
+ switch (tp->field)
+ {
+#if _mem_c_line_termios
+ case C_LINE:
+ sp->c_line = c;
+ break;
+#endif
+ case C_SPEED:
+ if(getspeed(c))
+ {
+ if (*tp->name != 'o')
+ cfsetispeed(sp, c);
+ if (*tp->name != 'i')
+ cfsetospeed(sp, c);
+ }
+ else
+ error(ERROR_exit(1), "%s: %s: invalid speed", tp->name, cp);
+ break;
+ case T_CHAR:
+ sp->c_cc[tp->mask] = c;
+ break;
+ }
+ break;
+ case SPEED:
+ cfsetospeed(sp, tp->mask);
+ cfsetispeed(sp, tp->mask);
+ break;
+ case SIZE:
+ sp->c_cflag &= ~CSIZE;
+ sp->c_cflag |= tp->mask;
+ break;
+ case SANE:
+ sane(sp);
+ break;
+#if defined(OLCUC) && defined(IUCLC)
+ case CASE:
+ if(off)
+ {
+ sp->c_iflag |= IUCLC;
+ sp->c_oflag |= OLCUC;
+ }
+ else
+ {
+ sp->c_iflag &= ~IUCLC;
+ sp->c_oflag &= ~OLCUC;
+ }
+ break;
+#endif /* OLCUC && IUCLC */
+ }
+ }
+}
+
+
+static void listchars(Sfio_t *sp,int type)
+{
+ int i,c;
+ c = (type==CHAR?'c':'n');
+ for(i=0; i < elementsof(Ttable); i++)
+ {
+ if(Ttable[i].type==type && *Ttable[i].description)
+ sfprintf(sp,"[+%s \a%c\a?%s.]",Ttable[i].name,c,Ttable[i].description);
+ }
+}
+
+static void listgroup(Sfio_t *sp,int type, const char *description)
+{
+ int i;
+ sfprintf(sp,"[+");
+ for(i=0; i < elementsof(Ttable); i++)
+ {
+ if(Ttable[i].type==type)
+ sfprintf(sp,"%s ",Ttable[i].name);
+ }
+ sfprintf(sp,"?%s.]",description);
+}
+
+static void listmask(Sfio_t *sp,unsigned int mask,const char *description)
+{
+ int i;
+ sfprintf(sp,"[+");
+ for(i=0; i < elementsof(Ttable); i++)
+ {
+ if(Ttable[i].mask==mask && Ttable[i].type==BITS)
+ sfprintf(sp,"%s ",Ttable[i].name);
+ }
+ sfprintf(sp,"?%s.]",description);
+}
+
+static void listfields(Sfio_t *sp,int field)
+{
+ int i;
+ for(i=0; i < elementsof(Ttable); i++)
+ {
+ if(Ttable[i].field==field && Ttable[i].type==BIT && *Ttable[i].description)
+ sfprintf(sp,"[+%s (-%s)?%s.]",Ttable[i].name,Ttable[i].name,Ttable[i].description);
+ }
+}
+
+static void listmode(Sfio_t *sp,const char *name)
+{
+ sfprintf(sp,"[+%s?%s.]",name,lookup(name)->description);
+}
+
+static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
+{
+ NoP(op);
+ NoP(s);
+ NoP(dp);
+ sfprintf(sp,"[+Control Modes.]{");
+ listfields(sp,C_FLAG);
+ listgroup(sp,SPEED,"Attempt to set input and output baud rate to number given. A value of \b0\b causes immediate hangup");
+ listchars(sp,NUM);
+ listgroup(sp,SIZE,"Number of bits in a character");
+ sfprintf(sp,"}[+Input Modes.]{");
+ listfields(sp,I_FLAG);
+ sfprintf(sp,"}[+Output Modes.]{");
+ listfields(sp,O_FLAG);
+#ifdef CRDLY
+ listmask(sp,CRDLY,"Carriage return delay style");
+#endif
+#ifdef NLDLY
+ listmask(sp,NLDLY,"Newline delay style");
+#endif
+#ifdef TABDLY
+ listmask(sp,TABDLY,"Horizontal tab delay style");
+#endif
+#ifdef BSDLY
+ listmask(sp,BSDLY,"Backspace delay style");
+#endif
+#ifdef FFDLY
+ listmask(sp,FFDLY,"Form feed delay style");
+#endif
+#ifdef VTDLY
+ listmask(sp,VTDLY,"Vertical tab delay style");
+#endif
+ sfprintf(sp,"}[+Local Modes.]{");
+ listfields(sp,L_FLAG);
+ sfprintf(sp,"}[+Control Assignments.?If \ac\a is \bundef\b or an empty "
+ "string then the control assignment is disabled.]{");
+ listchars(sp,WIND);
+ listchars(sp,CHAR);
+ sfprintf(sp,"}[+Combination Modes.]{");
+ listmode(sp,"ek");
+ listmode(sp,"evenp");
+ listmode(sp,"lcase");
+ listmode(sp,"oddp");
+ listmode(sp,"parity");
+ listmode(sp,"sane");
+ listmode(sp,"tabs");
+ listmode(sp,"LCASE");
+ sfputc(sp,'}');
+ return(1);
+}
+
+#ifndef _lib_tcgetpgrp
+# ifdef TIOCGPGRP
+ static int _i_;
+# define tcgetpgrp(a) (ioctl(a, TIOCGPGRP, &_i_)>=0?_i_:-1)
+# else
+# define tcgetpgrp(a) (-1)
+# endif /* TIOCGPGRP */
+#endif /* _lib_tcgetpgrp */
+
+int
+b_stty(int argc, char** argv, Shbltin_t* context)
+{
+ struct termios tty;
+ register int n;
+ register int flags = 0;
+ int fd = 0;
+ const Tty_t* tp;
+ Optdisc_t disc;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_INTERACTIVE);
+ memset(&disc, 0, sizeof(disc));
+ disc.version = OPT_VERSION;
+ disc.infof = infof;
+ opt_info.disc = &disc;
+ for (;;)
+ {
+ switch (n = optget(argv, usage))
+ {
+ case 'f':
+ fd = (int)opt_info.num;
+ continue;
+ case 'a':
+ case 'g':
+ case 't':
+ if (!opt_info.offset || !argv[opt_info.index][opt_info.offset])
+ {
+ switch (n)
+ {
+ case 'a':
+ flags |= A_FLAG;
+ break;
+ case 'g':
+ flags |= G_FLAG;
+ break;
+ case 't':
+ flags |= T_FLAG;
+ break;
+ }
+ continue;
+ }
+ /*FALLTHROUGH*/
+ case ':':
+ if (!opt_info.offset)
+ error(2, "%s", opt_info.arg);
+ else if (!(tp = lookup(argv[opt_info.index]+1)) || (tp->type != BIT && tp->type != TABS))
+ error(ERROR_exit(1), "%s: unknown mode", argv[opt_info.index]);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || (flags && *argv) || (flags&(flags-1)))
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if (tcgetattr(fd, &tty) < 0)
+ error(ERROR_system(1), "not a tty");
+ if (flags & T_FLAG)
+ sfprintf(sfstdout, "%d\n", tcgetpgrp(0));
+ else if (*argv)
+ {
+ if (!argv[1] && **argv == ':')
+ gin(*argv, &tty);
+ else
+ set(argv, &tty);
+ if (tcsetattr(0, TCSANOW, &tty) < 0)
+ error(ERROR_system(1), "cannot set tty");
+ }
+ else
+ output(&tty, flags);
+ return error_info.errors;
+}
diff --git a/src/lib/libcmd/sum.c b/src/lib/libcmd/sum.c
new file mode 100644
index 0000000..64c6c9e
--- /dev/null
+++ b/src/lib/libcmd/sum.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * sum -- implemented by cksum
+ */
+
+#include <cmd.h>
+
+int
+b_sum(int argc, register char** argv, Shbltin_t* context)
+{
+ return b_cksum(argc, argv, context);
+}
diff --git a/src/lib/libcmd/sync.c b/src/lib/libcmd/sync.c
new file mode 100644
index 0000000..0531725
--- /dev/null
+++ b/src/lib/libcmd/sync.c
@@ -0,0 +1,79 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: sync (AT&T Research) 2006-10-04 $\n]"
+USAGE_LICENSE
+"[+NAME?sync - schedule file system updates]"
+"[+DESCRIPTION?\bsync\b calls \bsync\b(2), which causes all information "
+ "in memory that updates file systems to be scheduled for writing out to "
+ "all file systems. The writing, although scheduled, is not necessarily "
+ "complete upon return from \bsync\b.]"
+"[+?Since \bsync\b(2) has no failure indication, \bsync\b only fails for "
+ "option/operand syntax errors, or when \bsync\b(2) does not return, in "
+ "which case \bsync\b also does not return.]"
+"[+?At minimum \bsync\b should be called before halting the system. Most "
+ "systems provide graceful shutdown procedures that include \bsync\b -- "
+ "use them if possible.]"
+"[+EXIT STATUS?]"
+ "{"
+ "[+0?\bsync\b(2) returned.]"
+ "[+>0?Option/operand syntax error.]"
+ "}"
+"[+SEE ALSO?\bsync\b(2), \bshutdown\b(8)]"
+;
+
+#include <cmd.h>
+#include <ls.h>
+
+int
+b_sync(int argc, char** argv, Shbltin_t* context)
+{
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || *argv)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+#if _lib_sync
+ sync();
+#else
+ error(ERROR_usage(2), "failed -- the native system does not provide a sync(2) call");
+#endif
+ return 0;
+}
diff --git a/src/lib/libcmd/tail.c b/src/lib/libcmd/tail.c
new file mode 100644
index 0000000..18aa270
--- /dev/null
+++ b/src/lib/libcmd/tail.c
@@ -0,0 +1,773 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * print the tail of one or more files
+ *
+ * David Korn
+ * Glenn Fowler
+ */
+
+static const char usage[] =
+"+[-?\n@(#)$Id: tail (AT&T Research) 2010-05-09 $\n]"
+USAGE_LICENSE
+"[+NAME?tail - output trailing portion of one or more files ]"
+"[+DESCRIPTION?\btail\b copies one or more input files to standard output "
+ "starting at a designated point for each file. Copying starts "
+ "at the point indicated by the options and is unlimited in size.]"
+"[+?By default a header of the form \b==> \b\afilename\a\b <==\b "
+ "is output before all but the first file but this can be changed "
+ "with the \b-q\b and \b-v\b options.]"
+"[+?If no \afile\a is given, or if the \afile\a is \b-\b, \btail\b "
+ "copies from standard input. The start of the file is defined "
+ "as the current offset.]"
+"[+?The option argument for \b-c\b can optionally be "
+ "followed by one of the following characters to specify a different "
+ "unit other than a single byte:]{"
+ "[+b?512 bytes.]"
+ "[+k?1 KiB.]"
+ "[+m?1 MiB.]"
+ "[+g?1 GiB.]"
+ "}"
+"[+?For backwards compatibility, \b-\b\anumber\a is equivalent to "
+ "\b-n\b \anumber\a and \b+\b\anumber\a is equivalent to "
+ "\b-n -\b\anumber\a. \anumber\a may also have these option "
+ "suffixes: \bb c f g k l m r\b.]"
+
+"[n:lines]:[lines:=10?Copy \alines\a lines from each file. A negative value "
+ "for \alines\a indicates an offset from the end of the file.]"
+"[b:blocks?Copy units of 512 bytes.]"
+"[c:bytes]:?[chars?Copy \achars\a bytes from each file. A negative value "
+ "for \achars\a indicates an offset from the end of the file.]"
+"[f:forever|follow?Loop forever trying to read more characters as the "
+ "end of each file to copy new data. Ignored if reading from a pipe "
+ "or fifo.]"
+"[h!:headers?Output filename headers.]"
+"[l:lines?Copy units of lines. This is the default.]"
+"[L:log?When a \b--forever\b file times out via \b--timeout\b, verify that "
+ "the curent file has not been renamed and replaced by another file "
+ "of the same name (a common log file practice) before giving up on "
+ "the file.]"
+"[q:quiet?Don't output filename headers. For GNU compatibility.]"
+"[r:reverse?Output lines in reverse order.]"
+"[s:silent?Don't warn about timeout expiration and log file changes.]"
+"[t:timeout?Stop checking after \atimeout\a elapses with no additional "
+ "\b--forever\b output. A separate elapsed time is maintained for "
+ "each file operand. There is no timeout by default. The default "
+ "\atimeout\a unit is seconds. \atimeout\a may be a catenation of 1 "
+ "or more integers, each followed by a 1 character suffix. The suffix "
+ "may be omitted from the last integer, in which case it is "
+ "interpreted as seconds. The supported suffixes are:]:[timeout]{"
+ "[+s?seconds]"
+ "[+m?minutes]"
+ "[+h?hours]"
+ "[+d?days]"
+ "[+w?weeks]"
+ "[+M?months]"
+ "[+y?years]"
+ "[+S?scores]"
+ "}"
+"[v:verbose?Always ouput filename headers.]"
+
+"\n"
+"\n[file ...]\n"
+"\n"
+
+"[+EXIT STATUS?]{"
+ "[+0?All files copied successfully.]"
+ "[+>0?One or more files did not copy.]"
+"}"
+"[+SEE ALSO?\bcat\b(1), \bhead\b(1), \brev\b(1)]"
+;
+
+#include <cmd.h>
+#include <ctype.h>
+#include <ls.h>
+#include <tm.h>
+#include <rev.h>
+
+#define COUNT (1<<0)
+#define ERROR (1<<1)
+#define FOLLOW (1<<2)
+#define HEADERS (1<<3)
+#define LINES (1<<4)
+#define LOG (1<<5)
+#define NEGATIVE (1<<6)
+#define POSITIVE (1<<7)
+#define REVERSE (1<<8)
+#define SILENT (1<<9)
+#define TIMEOUT (1<<10)
+#define VERBOSE (1<<11)
+
+#define NOW (unsigned long)time(NiL)
+
+#define DEFAULT 10
+
+#ifdef S_ISSOCK
+#define FIFO(m) (S_ISFIFO(m)||S_ISSOCK(m))
+#else
+#define FIFO(m) S_ISFIFO(m)
+#endif
+
+struct Tail_s; typedef struct Tail_s Tail_t;
+
+struct Tail_s
+{
+ Tail_t* next;
+ char* name;
+ Sfio_t* sp;
+ Sfoff_t cur;
+ Sfoff_t end;
+ unsigned long expire;
+ long dev;
+ long ino;
+ int fifo;
+};
+
+static const char header_fmt[] = "\n==> %s <==\n";
+
+/*
+ * if file is seekable, position file to tail location and return offset
+ * otherwise, return -1
+ */
+
+static Sfoff_t
+tailpos(register Sfio_t* fp, register Sfoff_t number, int delim)
+{
+ register size_t n;
+ register Sfoff_t offset;
+ register Sfoff_t first;
+ register Sfoff_t last;
+ register char* s;
+ register char* t;
+ struct stat st;
+
+ last = sfsize(fp);
+ if ((first = sfseek(fp, (Sfoff_t)0, SEEK_CUR)) < 0)
+ return last || fstat(sffileno(fp), &st) || st.st_size || FIFO(st.st_mode) ? -1 : 0;
+ if (delim < 0)
+ {
+ if ((offset = last - number) < first)
+ return first;
+ return offset;
+ }
+ for (;;)
+ {
+ if ((offset = last - SF_BUFSIZE) < first)
+ offset = first;
+ sfseek(fp, offset, SEEK_SET);
+ n = last - offset;
+ if (!(s = sfreserve(fp, n, SF_LOCKR)))
+ return -1;
+ t = s + n;
+ while (t > s)
+ if (*--t == delim && number-- <= 0)
+ {
+ sfread(fp, s, 0);
+ return offset + (t - s) + 1;
+ }
+ sfread(fp, s, 0);
+ if (offset == first)
+ break;
+ last = offset;
+ }
+ return first;
+}
+
+/*
+ * this code handles tail from a pipe without any size limits
+ */
+
+static void
+pipetail(Sfio_t* infile, Sfio_t* outfile, Sfoff_t number, int delim)
+{
+ register Sfio_t* out;
+ register Sfoff_t n;
+ register Sfoff_t nleft = number;
+ register size_t a = 2 * SF_BUFSIZE;
+ register int fno = 0;
+ Sfoff_t offset[2];
+ Sfio_t* tmp[2];
+
+ if (delim < 0 && a > number)
+ a = number;
+ out = tmp[0] = sftmp(a);
+ tmp[1] = sftmp(a);
+ offset[0] = offset[1] = 0;
+ while ((n = sfmove(infile, out, number, delim)) > 0)
+ {
+ offset[fno] = sftell(out);
+ if ((nleft -= n) <= 0)
+ {
+ out = tmp[fno= !fno];
+ sfseek(out, (Sfoff_t)0, SEEK_SET);
+ nleft = number;
+ }
+ }
+ if (nleft == number)
+ {
+ offset[fno] = 0;
+ fno= !fno;
+ }
+ sfseek(tmp[0], (Sfoff_t)0, SEEK_SET);
+
+ /*
+ * see whether both files are needed
+ */
+
+ if (offset[fno])
+ {
+ sfseek(tmp[1], (Sfoff_t)0, SEEK_SET);
+ if ((n = number - nleft) > 0)
+ sfmove(tmp[!fno], NiL, n, delim);
+ if ((n = offset[!fno] - sftell(tmp[!fno])) > 0)
+ sfmove(tmp[!fno], outfile, n, -1);
+ }
+ else
+ fno = !fno;
+ sfmove(tmp[fno], outfile, offset[fno], -1);
+ sfclose(tmp[0]);
+ sfclose(tmp[1]);
+}
+
+/*
+ * (re)initialize a tail stream
+ */
+
+static int
+init(Tail_t* tp, Sfoff_t number, int delim, int flags, const char** format)
+{
+ Sfoff_t offset;
+ Sfio_t* op;
+ struct stat st;
+
+ tp->fifo = 0;
+ if (tp->sp)
+ {
+ offset = 0;
+ if (tp->sp == sfstdin)
+ tp->sp = 0;
+ }
+ else
+ offset = 1;
+ if (!tp->name || streq(tp->name, "-"))
+ {
+ tp->name = "/dev/stdin";
+ tp->sp = sfstdin;
+ }
+ else if (!(tp->sp = sfopen(tp->sp, tp->name, "r")))
+ {
+ error(ERROR_system(0), "%s: cannot open", tp->name);
+ return -1;
+ }
+ sfset(tp->sp, SF_SHARE, 0);
+ if (offset)
+ {
+ if (number < 0 || !number && (flags & POSITIVE))
+ {
+ sfset(tp->sp, SF_SHARE, !(flags & FOLLOW));
+ if (number < -1)
+ {
+ sfmove(tp->sp, NiL, -number - 1, delim);
+ offset = sfseek(tp->sp, (Sfoff_t)0, SEEK_CUR);
+ }
+ else
+ offset = 0;
+ }
+ else if ((offset = tailpos(tp->sp, number, delim)) >= 0)
+ sfseek(tp->sp, offset, SEEK_SET);
+ else if (fstat(sffileno(tp->sp), &st))
+ {
+ error(ERROR_system(0), "%s: cannot stat", tp->name);
+ goto bad;
+ }
+ else if (!FIFO(st.st_mode))
+ {
+ error(ERROR_SYSTEM|2, "%s: cannot position file to tail", tp->name);
+ goto bad;
+ }
+ else
+ {
+ tp->fifo = 1;
+ if (flags & (HEADERS|VERBOSE))
+ {
+ sfprintf(sfstdout, *format, tp->name);
+ *format = header_fmt;
+ }
+ op = (flags & REVERSE) ? sftmp(4*SF_BUFSIZE) : sfstdout;
+ pipetail(tp->sp ? tp->sp : sfstdin, op, number, delim);
+ if (flags & REVERSE)
+ {
+ sfseek(op, (Sfoff_t)0, SEEK_SET);
+ rev_line(op, sfstdout, (Sfoff_t)0);
+ sfclose(op);
+ }
+ }
+ }
+ tp->cur = tp->end = offset;
+ if (flags & LOG)
+ {
+ if (fstat(sffileno(tp->sp), &st))
+ {
+ error(ERROR_system(0), "%s: cannot stat", tp->name);
+ goto bad;
+ }
+ tp->dev = st.st_dev;
+ tp->ino = st.st_ino;
+ }
+ return 0;
+ bad:
+ if (tp->sp != sfstdin)
+ sfclose(tp->sp);
+ tp->sp = 0;
+ return -1;
+}
+
+/*
+ * convert number with validity diagnostics
+ */
+
+static intmax_t
+num(register const char* s, char** e, int* f, int o)
+{
+ intmax_t number;
+ char* t;
+ int c;
+
+ *f &= ~(ERROR|NEGATIVE|POSITIVE);
+ if ((c = *s) == '-')
+ {
+ *f |= NEGATIVE;
+ s++;
+ }
+ else if (c == '+')
+ {
+ *f |= POSITIVE;
+ s++;
+ }
+ while (*s == '0' && isdigit(*(s + 1)))
+ s++;
+ errno = 0;
+ number = strtonll(s, &t, NiL, 0);
+ if (t == s)
+ number = DEFAULT;
+ if (o && *t)
+ {
+ number = 0;
+ *f |= ERROR;
+ error(2, "-%c: %s: invalid numeric argument -- unknown suffix", o, s);
+ }
+ else if (errno)
+ {
+ *f |= ERROR;
+ if (o)
+ error(2, "-%c: %s: invalid numeric argument -- out of range", o, s);
+ else
+ error(2, "%s: invalid numeric argument -- out of range", s);
+ }
+ else
+ {
+ *f |= COUNT;
+ if (t > s && isalpha(*(t - 1)))
+ *f &= ~LINES;
+ if (c == '-')
+ number = -number;
+ }
+ if (e)
+ *e = t;
+ return number;
+}
+
+int
+b_tail(int argc, char** argv, Shbltin_t* context)
+{
+ register Sfio_t* ip;
+ register int n;
+ register int i;
+ int delim;
+ int flags = HEADERS|LINES;
+ int blocks = 0;
+ char* s;
+ char* t;
+ char* r;
+ char* file;
+ Sfoff_t offset;
+ Sfoff_t number = DEFAULT;
+ unsigned long timeout = 0;
+ struct stat st;
+ const char* format = header_fmt+1;
+ ssize_t z;
+ ssize_t w;
+ Sfio_t* op;
+ register Tail_t* fp;
+ register Tail_t* pp;
+ register Tail_t* hp;
+ Tail_t* files;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (n = optget(argv, usage))
+ {
+ case 0:
+ if (!(flags & FOLLOW) && argv[opt_info.index] && (argv[opt_info.index][0] == '-' || argv[opt_info.index][0] == '+') && !argv[opt_info.index][1])
+ {
+ number = argv[opt_info.index][0] == '-' ? 10 : -10;
+ flags |= LINES;
+ opt_info.index++;
+ continue;
+ }
+ break;
+ case 'b':
+ blocks = 512;
+ flags &= ~LINES;
+ if (opt_info.option[0] == '+')
+ number = -number;
+ continue;
+ case 'c':
+ flags &= ~LINES;
+ if (opt_info.arg == argv[opt_info.index - 1])
+ {
+ strtol(opt_info.arg, &s, 10);
+ if (*s)
+ {
+ opt_info.index--;
+ t = "";
+ goto suffix;
+ }
+ }
+ else if (opt_info.arg && isalpha(*opt_info.arg))
+ {
+ t = opt_info.arg;
+ goto suffix;
+ }
+ /*FALLTHROUGH*/
+ case 'n':
+ flags |= COUNT;
+ if (s = opt_info.arg)
+ number = num(s, &s, &flags, n);
+ else
+ {
+ number = DEFAULT;
+ flags &= ~(ERROR|NEGATIVE|POSITIVE);
+ s = "";
+ }
+ if (n != 'n' && s && isalpha(*s))
+ {
+ t = s;
+ goto suffix;
+ }
+ if (flags & ERROR)
+ continue;
+ if (flags & (NEGATIVE|POSITIVE))
+ number = -number;
+ if (opt_info.option[0]=='+')
+ number = -number;
+ continue;
+ case 'f':
+ flags |= FOLLOW;
+ continue;
+ case 'h':
+ if (opt_info.num)
+ flags |= HEADERS;
+ else
+ flags &= ~HEADERS;
+ continue;
+ case 'l':
+ flags |= LINES;
+ if (opt_info.option[0] == '+')
+ number = -number;
+ continue;
+ case 'L':
+ flags |= LOG;
+ continue;
+ case 'q':
+ flags &= ~HEADERS;
+ continue;
+ case 'r':
+ flags |= REVERSE;
+ continue;
+ case 's':
+ flags |= SILENT;
+ continue;
+ case 't':
+ flags |= TIMEOUT;
+ timeout = strelapsed(opt_info.arg, &s, 1);
+ if (*s)
+ error(ERROR_exit(1), "%s: invalid elapsed time [%s]", opt_info.arg, s);
+ continue;
+ case 'v':
+ flags |= VERBOSE;
+ continue;
+ case ':':
+ /* handle old style arguments */
+ if (!(r = argv[opt_info.index]) || !opt_info.offset)
+ {
+ error(2, "%s", opt_info.arg);
+ break;
+ }
+ s = r + opt_info.offset - 1;
+ if (i = *(s - 1) == '-' || *(s - 1) == '+')
+ s--;
+ if ((number = num(s, &t, &flags, 0)) && i)
+ number = -number;
+ goto compatibility;
+ suffix:
+ r = 0;
+ if (opt_info.option[0] == '+')
+ number = -number;
+ compatibility:
+ for (;;)
+ {
+ switch (*t++)
+ {
+ case 0:
+ if (r)
+ opt_info.offset = t - r - 1;
+ break;
+ case 'c':
+ flags &= ~LINES;
+ continue;
+ case 'f':
+ flags |= FOLLOW;
+ continue;
+ case 'l':
+ flags |= LINES;
+ continue;
+ case 'r':
+ flags |= REVERSE;
+ continue;
+ default:
+ error(2, "%s: invalid suffix", t - 1);
+ if (r)
+ opt_info.offset = strlen(r);
+ break;
+ }
+ break;
+ }
+ continue;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (!*argv)
+ {
+ flags &= ~HEADERS;
+ if (fstat(0, &st))
+ error(ERROR_system(0), "/dev/stdin: cannot stat");
+ else if (FIFO(st.st_mode))
+ flags &= ~FOLLOW;
+ }
+ else if (!*(argv + 1))
+ flags &= ~HEADERS;
+ delim = (flags & LINES) ? '\n' : -1;
+ if (blocks)
+ number *= blocks;
+ if (flags & REVERSE)
+ {
+ if (delim < 0)
+ error(2, "--reverse requires line mode");
+ if (!(flags & COUNT))
+ number = -1;
+ flags &= ~FOLLOW;
+ }
+ if ((flags & (FOLLOW|TIMEOUT)) == TIMEOUT)
+ {
+ flags &= ~TIMEOUT;
+ timeout = 0;
+ error(ERROR_warn(0), "--timeout ignored for --noforever");
+ }
+ if ((flags & (LOG|TIMEOUT)) == LOG)
+ {
+ flags &= ~LOG;
+ error(ERROR_warn(0), "--log ignored for --notimeout");
+ }
+ if (error_info.errors)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if (flags & FOLLOW)
+ {
+ if (!(fp = (Tail_t*)stakalloc(argc * sizeof(Tail_t))))
+ error(ERROR_system(1), "out of space");
+ files = 0;
+ s = *argv;
+ do
+ {
+ fp->name = s;
+ fp->sp = 0;
+ if (!init(fp, number, delim, flags, &format))
+ {
+ fp->expire = timeout ? (NOW + timeout + 1) : 0;
+ if (files)
+ pp->next = fp;
+ else
+ files = fp;
+ pp = fp;
+ fp++;
+ }
+ } while (s && (s = *++argv));
+ if (!files)
+ return error_info.errors != 0;
+ pp->next = 0;
+ hp = 0;
+ n = 1;
+ while (fp = files)
+ {
+ if (n)
+ n = 0;
+ else
+ sleep(1);
+ pp = 0;
+ while (fp)
+ {
+ if (fstat(sffileno(fp->sp), &st))
+ error(ERROR_system(0), "%s: cannot stat", fp->name);
+ else if (fp->fifo || fp->end < st.st_size)
+ {
+ n = 1;
+ if (timeout)
+ fp->expire = NOW + timeout;
+ z = fp->fifo ? SF_UNBOUND : st.st_size - fp->cur;
+ i = 0;
+ if ((s = sfreserve(fp->sp, z, SF_LOCKR)) || (z = sfvalue(fp->sp)) && (s = sfreserve(fp->sp, z, SF_LOCKR)) && (i = 1))
+ {
+ z = sfvalue(fp->sp);
+ for (r = s + z; r > s && *(r - 1) != '\n'; r--);
+ if ((w = r - s) || i && (w = z))
+ {
+ if ((flags & (HEADERS|VERBOSE)) && hp != fp)
+ {
+ hp = fp;
+ sfprintf(sfstdout, format, fp->name);
+ format = header_fmt;
+ }
+ fp->cur += w;
+ sfwrite(sfstdout, s, w);
+ }
+ else
+ w = 0;
+ sfread(fp->sp, s, w);
+ fp->end += w;
+ }
+ goto next;
+ }
+ else if (!timeout || fp->expire > NOW)
+ goto next;
+ else
+ {
+ if (flags & LOG)
+ {
+ i = 3;
+ while (--i && stat(fp->name, &st))
+ sleep(1);
+ if (i && (fp->dev != st.st_dev || fp->ino != st.st_ino) && !init(fp, 0, 0, flags, &format))
+ {
+ if (!(flags & SILENT))
+ error(ERROR_warn(0), "%s: log file change", fp->name);
+ fp->expire = NOW + timeout;
+ goto next;
+ }
+ }
+ if (!(flags & SILENT))
+ error(ERROR_warn(0), "%s: %s timeout", fp->name, fmtelapsed(timeout, 1));
+ }
+ if (fp->sp && fp->sp != sfstdin)
+ sfclose(fp->sp);
+ if (pp)
+ pp = pp->next = fp->next;
+ else
+ files = files->next;
+ fp = fp->next;
+ continue;
+ next:
+ pp = fp;
+ fp = fp->next;
+ }
+ if (sfsync(sfstdout))
+ error(ERROR_system(1), "write error");
+ }
+ }
+ else
+ {
+ if (file = *argv)
+ argv++;
+ do
+ {
+ if (!file || streq(file, "-"))
+ {
+ file = "/dev/stdin";
+ ip = sfstdin;
+ }
+ else if (!(ip = sfopen(NiL, file, "r")))
+ {
+ error(ERROR_system(0), "%s: cannot open", file);
+ continue;
+ }
+ if (flags & (HEADERS|VERBOSE))
+ {
+ sfprintf(sfstdout, format, file);
+ format = header_fmt;
+ }
+ if (number < 0 || !number && (flags & POSITIVE))
+ {
+ sfset(ip, SF_SHARE, 1);
+ if (number < -1)
+ sfmove(ip, NiL, -number - 1, delim);
+ if (flags & REVERSE)
+ rev_line(ip, sfstdout, sfseek(ip, (Sfoff_t)0, SEEK_CUR));
+ else
+ sfmove(ip, sfstdout, SF_UNBOUND, -1);
+ }
+ else
+ {
+ sfset(ip, SF_SHARE, 0);
+ if ((offset = tailpos(ip, number, delim)) >= 0)
+ {
+ if (flags & REVERSE)
+ rev_line(ip, sfstdout, offset);
+ else
+ {
+ sfseek(ip, offset, SEEK_SET);
+ sfmove(ip, sfstdout, SF_UNBOUND, -1);
+ }
+ }
+ else
+ {
+ op = (flags & REVERSE) ? sftmp(4*SF_BUFSIZE) : sfstdout;
+ pipetail(ip, op, number, delim);
+ if (flags & REVERSE)
+ {
+ sfseek(op, (Sfoff_t)0, SEEK_SET);
+ rev_line(op, sfstdout, (Sfoff_t)0);
+ sfclose(op);
+ }
+ flags = 0;
+ }
+ }
+ if (ip != sfstdin)
+ sfclose(ip);
+ } while (file = *argv++);
+ }
+ return error_info.errors != 0;
+}
diff --git a/src/lib/libcmd/tee.c b/src/lib/libcmd/tee.c
new file mode 100644
index 0000000..ce1c873
--- /dev/null
+++ b/src/lib/libcmd/tee.c
@@ -0,0 +1,204 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * tee
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: tee (AT&T Research) 2012-01-01 $\n]"
+USAGE_LICENSE
+"[+NAME?tee - duplicate standard input]"
+"[+DESCRIPTION?\btee\b copies standard input to standard output "
+ "and to zero or more files. The options determine whether "
+ "the specified files are overwritten or appended to. The "
+ "\btee\b utility does not buffer output. If writes to any "
+ "\afile\a fail, writes to other files continue although \btee\b "
+ "will exit with a non-zero exit status.]"
+"[+?The number of \afile\a operands that can be specified is limited "
+ "by the underlying operating system.]"
+"[a:append?Append the standard input to the given files rather "
+ "than overwriting them.]"
+"[i:ignore-interrupts?Ignore SIGINT signal.]"
+"[l:linebuffer?Set the standard output to be line buffered.]"
+"\n"
+"\n[file ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All files copies successfully.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bcat\b(1), \bsignal\b(3)]"
+;
+
+#include <cmd.h>
+#include <ls.h>
+#include <sig.h>
+
+typedef struct Tee_s
+{
+ Sfdisc_t disc;
+ int line;
+ int fd[1];
+} Tee_t;
+
+/*
+ * This discipline writes to each file in the list given in handle
+ */
+
+static ssize_t
+tee_write(Sfio_t* fp, const void* buf, size_t n, Sfdisc_t* handle)
+{
+ register const char* bp;
+ register const char* ep;
+ register int* hp = ((Tee_t*)handle)->fd;
+ register int fd = sffileno(fp);
+ register ssize_t r;
+
+ do
+ {
+ bp = (const char*)buf;
+ ep = bp + n;
+ while (bp < ep)
+ {
+ if ((r = write(fd, bp, ep - bp)) <= 0)
+ return -1;
+ bp += r;
+ }
+ } while ((fd = *hp++) >= 0);
+ return n;
+}
+
+static void
+tee_cleanup(register Tee_t* tp)
+{
+ register int* hp;
+ register int n;
+
+ if (tp)
+ {
+ sfdisc(sfstdout, NiL);
+ if (tp->line >= 0)
+ sfset(sfstdout, SF_LINE, tp->line);
+ for (hp = tp->fd; (n = *hp) >= 0; hp++)
+ close(n);
+ }
+}
+
+int
+b_tee(int argc, register char** argv, Shbltin_t* context)
+{
+ register Tee_t* tp = 0;
+ register int oflag = O_WRONLY|O_TRUNC|O_CREAT|O_BINARY;
+ register int* hp;
+ register char* cp;
+ int line;
+
+ if (argc <= 0)
+ {
+ if (context && (tp = (Tee_t*)sh_context(context)->data))
+ {
+ sh_context(context)->data = 0;
+ tee_cleanup(tp);
+ }
+ return 0;
+ }
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_CALLBACK);
+ line = -1;
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'a':
+ oflag &= ~O_TRUNC;
+ oflag |= O_APPEND;
+ continue;
+ case 'i':
+ signal(SIGINT, SIG_IGN);
+ continue;
+ case 'l':
+ line = sfset(sfstdout, 0, 0) & SF_LINE;
+ if ((line == 0) == (opt_info.num == 0))
+ line = -1;
+ else
+ sfset(sfstdout, SF_LINE, !!opt_info.num);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ if (error_info.errors)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ argv += opt_info.index;
+ argc -= opt_info.index;
+#if _ANCIENT_BSD_COMPATIBILITY
+ if (*argv && streq(*argv, "-"))
+ {
+ signal(SIGINT, SIG_IGN);
+ argv++;
+ argc--;
+ }
+#endif
+ if (argc > 0)
+ {
+ if (tp = (Tee_t*)stakalloc(sizeof(Tee_t) + argc * sizeof(int)))
+ {
+ memset(&tp->disc, 0, sizeof(tp->disc));
+ tp->disc.writef = tee_write;
+ if (context)
+ sh_context(context)->data = (void*)tp;
+ tp->line = line;
+ hp = tp->fd;
+ while (cp = *argv++)
+ {
+ while ((*hp = open(cp, oflag, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0 && errno == EINTR)
+ errno = 0;
+ if (*hp < 0)
+ error(ERROR_system(0), "%s: cannot create", cp);
+ else
+ hp++;
+ }
+ if (hp == tp->fd)
+ tp = 0;
+ else
+ {
+ *hp = -1;
+ sfdisc(sfstdout, &tp->disc);
+ }
+ }
+ else
+ error(ERROR_exit(0), "out of space");
+ }
+ if ((sfmove(sfstdin, sfstdout, SF_UNBOUND, -1) < 0 || !sfeof(sfstdin)) && errno != EPIPE && errno != EINTR)
+ error(ERROR_system(0), "read error");
+ if (sfsync(sfstdout))
+ error(ERROR_system(0), "write error");
+ tee_cleanup(tp);
+ return error_info.errors;
+}
diff --git a/src/lib/libcmd/tty.c b/src/lib/libcmd/tty.c
new file mode 100644
index 0000000..f5e6aca
--- /dev/null
+++ b/src/lib/libcmd/tty.c
@@ -0,0 +1,105 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * tty
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: tty (AT&T Research) 2008-03-13 $\n]"
+USAGE_LICENSE
+"[+NAME?tty - write the name of the terminal to standard output]"
+"[+DESCRIPTION?\btty\b writes the name of the terminal that is connected "
+ "to standard input onto standard output. If the standard input is not "
+ "a terminal, \"\bnot a tty\b\" will be written to standard output.]"
+"[l:line-number?Write the synchronous line number of the terminal on a "
+ "separate line following the terminal name line. If the standard "
+ "input is not a synchronous terminal then "
+ "\"\bnot on an active synchronous line\b\" is written.]"
+"[s:silent|quiet?Disable the terminal name line. Use \b[[ -t 0 ]]]]\b instead.]"
+"[+EXIT STATUS?]{"
+ "[+0?Standard input is a tty.]"
+ "[+1?Standard input is not a tty.]"
+ "[+2?Invalid arguments.]"
+ "[+3?A an error occurred.]"
+"}"
+;
+
+
+#include <cmd.h>
+
+#if _mac_STWLINE
+#include <sys/stermio.h>
+#endif
+
+int
+b_tty(int argc, char** argv, Shbltin_t* context)
+{
+ register int sflag = 0;
+ register int lflag = 0;
+ register char* tty;
+#if _mac_STWLINE
+ int n;
+#endif
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'l':
+ lflag++;
+ continue;
+ case 's':
+ sflag++;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ if(error_info.errors)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if(!(tty=ttyname(0)))
+ {
+ tty = ERROR_translate(0, 0, 0, "not a tty");
+ error_info.errors++;
+ }
+ if(!sflag)
+ sfputr(sfstdout,tty,'\n');
+ if(lflag)
+ {
+#if _mac_STWLINE
+ if ((n = ioctl(0, STWLINE, 0)) >= 0)
+ error(ERROR_OUTPUT, 1, "synchronous line %d", n);
+ else
+#endif
+ error(ERROR_OUTPUT, 1, "not on an active synchronous line");
+ }
+ return(error_info.errors);
+}
diff --git a/src/lib/libcmd/uname.c b/src/lib/libcmd/uname.c
new file mode 100644
index 0000000..cece94a
--- /dev/null
+++ b/src/lib/libcmd/uname.c
@@ -0,0 +1,514 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * uname
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: uname (AT&T Research) 2007-04-19 $\n]"
+USAGE_LICENSE
+"[+NAME?uname - identify the current system ]"
+"[+DESCRIPTION?By default \buname\b writes the operating system name to"
+" standard output. When options are specified, one or more"
+" system characteristics are written to standard output, space"
+" separated, on a single line. When more than one option is specified"
+" the output is in the order specfied by the \b-A\b option below."
+" Unsupported option values are listed as \a[option]]\a. If any unknown"
+" options are specified then the local \b/usr/bin/uname\b is called.]"
+"[+?If any \aname\a operands are specified then the \bsysinfo\b(2) values"
+" for each \aname\a are listed, separated by space, on one line."
+" \bgetconf\b(1), a pre-existing \astandard\a interface, provides"
+" access to the same information; vendors should spend more time"
+" using standards than inventing them.]"
+"[+?Selected information is printed in the same order as the options below.]"
+"[a:all?Equivalent to \b-snrvmpio\b.]"
+"[s:system|sysname|kernel-name?The detailed kernel name. This is the default.]"
+"[n:nodename?The hostname or nodename.]"
+"[r:release|kernel-release?The kernel release level.]"
+"[v:version|kernel-version?The kernel version level.]"
+"[m:machine?The name of the hardware type the system is running on.]"
+"[p:processor?The name of the processor instruction set architecture.]"
+"[i:implementation|platform|hardware-platform?The hardware implementation;"
+" this is \b--host-id\b on some systems.]"
+"[o:operating-system?The generic operating system name.]"
+"[h:host-id|id?The host id in hex.]"
+"[d:domain?The domain name returned by \agetdomainname\a(2).]"
+"[R:extended-release?The extended release name.]"
+"[A:everything?Equivalent to \b-snrvmpiohdR\b.]"
+"[f:list?List all \bsysinfo\b(2) names and values, one per line.]"
+"[S:sethost?Set the hostname or nodename to \aname\a. No output is"
+" written to standard output.]:[name]"
+"\n"
+"\n[ name ... ]\n"
+"\n"
+"[+SEE ALSO?\bhostname\b(1), \bgetconf\b(1), \buname\b(2),"
+" \bsysconf\b(2), \bsysinfo\b(2)]"
+;
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:hide getdomainname gethostid gethostname sethostname
+#else
+#define getdomainname ______getdomainname
+#define gethostid ______gethostid
+#define gethostname ______gethostname
+#define sethostname ______sethostname
+#endif
+
+#include <cmd.h>
+#include <ctype.h>
+#include <proc.h>
+
+#include "FEATURE/utsname"
+
+#define MAXHOSTNAME 64
+
+#if _lib_uname && _sys_utsname
+
+#include <sys/utsname.h>
+
+#endif
+
+#if defined(__STDPP__directive) && defined(__STDPP__hide)
+__STDPP__directive pragma pp:nohide getdomainname gethostid gethostname sethostname
+#else
+#undef getdomainname
+#undef gethostid
+#undef gethostname
+#undef sethostname
+#endif
+
+#if _lib_getdomainname
+extern int getdomainname(char*, size_t);
+#endif
+#if _lib_gethostid
+extern long gethostid(void);
+#endif
+#if _lib_gethostname
+extern int gethostname(char*, size_t);
+#endif
+#if _lib_sethostname
+extern int sethostname(const char*, size_t);
+#endif
+
+#ifndef HOSTTYPE
+#define HOSTTYPE "unknown"
+#endif
+
+static const char hosttype[] = HOSTTYPE;
+
+#if !_lib_uname || !_sys_utsname
+
+#if defined(__STDPP__)
+#define SYSNAME #(getprd machine)
+#define RELEASE #(getprd release)
+#define VERSION #(getprd version)
+#define MACHINE #(getprd architecture)
+#else
+#define SYSNAME ""
+#define RELEASE ""
+#define VERSION ""
+#define MACHINE ""
+#endif
+
+struct utsname
+{
+ char* sysname;
+ char nodename[MAXHOSTNAME];
+ char* release;
+ char* version;
+ char* machine;
+};
+
+int
+uname(register struct utsname* ut)
+{
+#ifdef HOSTTYPE
+ char* sys = 0;
+ char* arch = 0;
+
+ if (*hosttype)
+ {
+ static char buf[sizeof(hosttype)];
+
+ strcpy(buf, hosttype);
+ sys = buf;
+ if (arch = strchr(sys, '.'))
+ {
+ *arch++ = 0;
+ if (!*arch)
+ arch = 0;
+ }
+ if (!*sys)
+ sys = 0;
+ }
+#endif
+#ifdef _lib_gethostname
+ if (gethostname(ut->nodename, sizeof(ut->nodename) - 1))
+ return -1;
+#else
+ strncpy(ut->nodename, "local", sizeof(ut->nodename) - 1);
+#endif
+#ifdef HOSTTYPE
+ if (!(ut->sysname = sys))
+#endif
+ if (!*(ut->sysname = SYSNAME))
+ ut->sysname = ut->nodename;
+#ifdef HOSTTYPE
+ if (!(ut->machine = arch))
+#endif
+ ut->machine = MACHINE;
+ ut->release = RELEASE;
+ ut->version = VERSION;
+ return 0;
+}
+
+#endif
+
+#define OPT_system (1<<0)
+#define OPT_nodename (1<<1)
+#define OPT_release (1<<2)
+#define OPT_version (1<<3)
+#define OPT_machine (1<<4)
+#define OPT_processor (1<<5)
+
+#define OPT_STANDARD 6
+
+#define OPT_implementation (1<<6)
+#define OPT_operating_system (1<<7)
+
+#define OPT_ALL 8
+
+#define OPT_hostid (1<<8)
+#define OPT_vendor (1<<9)
+#define OPT_domain (1<<10)
+#define OPT_machine_type (1<<11)
+#define OPT_base (1<<12)
+#define OPT_extended_release (1<<13)
+#define OPT_extra (1<<14)
+
+#define OPT_TOTAL 15
+
+#define OPT_all (1L<<29)
+#define OPT_total (1L<<30)
+#define OPT_standard ((1<<OPT_STANDARD)-1)
+
+#ifndef MACHINE
+#if defined(__STDPP__)
+#define MACHINE #(getprd architecture)
+#else
+#define MACHINE ""
+#endif
+#endif
+
+#ifndef HOSTTYPE
+#define HOSTTYPE "unknown"
+#endif
+
+#define extra(m) do \
+ { \
+ if ((char*)&ut.m[sizeof(ut.m)] > last) \
+ last = (char*)&ut.m[sizeof(ut.m)]; \
+ } while(0)
+
+#define output(f,v,u) do \
+ { \
+ if ((flags&(f))&&(*(v)||(flags&(OPT_all|OPT_total))==OPT_all&&((f)&OPT_standard)||!(flags&(OPT_all|OPT_total)))) \
+ { \
+ if (sep) \
+ sfputc(sfstdout, ' '); \
+ else \
+ sep = 1; \
+ if (*(v)) \
+ sfputr(sfstdout, v, -1); \
+ else \
+ sfprintf(sfstdout, "[%s]", u); \
+ } \
+ } while (0)
+
+int
+b_uname(int argc, char** argv, Shbltin_t* context)
+{
+ register long flags = 0;
+ register int sep = 0;
+ register int n;
+ register char* s;
+ char* t;
+ char* e;
+ char* sethost = 0;
+ int list = 0;
+ struct utsname ut;
+ char buf[257];
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'a':
+ flags |= OPT_all|((1L<<OPT_ALL)-1);
+ continue;
+ case 'b':
+ flags |= OPT_base;
+ continue;
+ case 'c':
+ flags |= OPT_vendor;
+ continue;
+ case 'd':
+ flags |= OPT_domain;
+ continue;
+ case 'f':
+ list = 1;
+ continue;
+ case 'h':
+ flags |= OPT_hostid;
+ continue;
+ case 'i':
+ flags |= OPT_implementation;
+ continue;
+ case 'm':
+ flags |= OPT_machine;
+ continue;
+ case 'n':
+ flags |= OPT_nodename;
+ continue;
+ case 'o':
+ flags |= OPT_operating_system;
+ continue;
+ case 'p':
+ flags |= OPT_processor;
+ continue;
+ case 'r':
+ flags |= OPT_release;
+ continue;
+ case 's':
+ flags |= OPT_system;
+ continue;
+ case 't':
+ flags |= OPT_machine_type;
+ continue;
+ case 'v':
+ flags |= OPT_version;
+ continue;
+ case 'x':
+ flags |= OPT_extra;
+ continue;
+ case 'A':
+ flags |= OPT_total|((1L<<OPT_TOTAL)-1);
+ continue;
+ case 'R':
+ flags |= OPT_extended_release;
+ continue;
+ case 'S':
+ sethost = opt_info.arg;
+ continue;
+ case ':':
+ s = "/usr/bin/uname";
+ if (!streq(argv[0], s) && (!eaccess(s, X_OK) || !eaccess(s+=4, X_OK)))
+ {
+ argv[0] = s;
+ return sh_run(context, argc, argv);
+ }
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || *argv && (flags || sethost) || sethost && flags)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if (sethost)
+ {
+#if _lib_sethostname
+ if (sethostname(sethost, strlen(sethost) + 1))
+#else
+#ifdef ENOSYS
+ errno = ENOSYS;
+#else
+ errno = EPERM;
+#endif
+#endif
+ error(ERROR_system(1), "%s: cannot set host name", sethost);
+ }
+ else if (list)
+ astconflist(sfstdout, NiL, ASTCONF_base|ASTCONF_defined|ASTCONF_lower|ASTCONF_quote|ASTCONF_matchcall, "CS|SI");
+ else if (*argv)
+ {
+ e = &buf[sizeof(buf)-1];
+ while (s = *argv++)
+ {
+ t = buf;
+ *t++ = 'C';
+ *t++ = 'S';
+ *t++ = '_';
+ while (t < e && (n = *s++))
+ *t++ = islower(n) ? toupper(n) : n;
+ *t = 0;
+ sfprintf(sfstdout, "%s%c", *(t = astconf(buf, NiL, NiL)) ? t : *(t = astconf(buf+3, NiL, NiL)) ? t : "unknown", *argv ? ' ' : '\n');
+ }
+ }
+ else
+ {
+ s = buf;
+ if (!flags)
+ flags = OPT_system;
+ memzero(&ut, sizeof(ut));
+ if (uname(&ut) < 0)
+ error(ERROR_usage(2), "information unavailable");
+ output(OPT_system, ut.sysname, "sysname");
+ if (flags & OPT_nodename)
+ {
+#if !_mem_nodeext_utsname && _lib_gethostname
+ if (sizeof(ut.nodename) > 9 || gethostname(s, sizeof(buf)))
+#endif
+ s = ut.nodename;
+ output(OPT_nodename, s, "nodename");
+ }
+ output(OPT_release, ut.release, "release");
+ output(OPT_version, ut.version, "version");
+ output(OPT_machine, ut.machine, "machine");
+ if (flags & OPT_processor)
+ {
+ if (!*(s = astconf("ARCHITECTURE", NiL, NiL)))
+ s = ut.machine;
+ output(OPT_processor, s, "processor");
+ }
+ if (flags & OPT_implementation)
+ {
+ if (!*(s = astconf("PLATFORM", NiL, NiL)) && !*(s = astconf("HW_NAME", NiL, NiL)))
+ {
+ if (t = strchr(hosttype, '.'))
+ t++;
+ else
+ t = (char*)hosttype;
+ strncpy(s = buf, t, sizeof(buf) - 1);
+ }
+ output(OPT_implementation, s, "implementation");
+ }
+ if (flags & OPT_operating_system)
+ {
+ s = astconf("OPERATING_SYSTEM", NiL, NiL);
+ if (!*s)
+#ifdef _UNAME_os_DEFAULT
+ s = _UNAME_os_DEFAULT;
+#else
+ s = ut.sysname;
+#endif
+ output(OPT_operating_system, s, "operating-system");
+ }
+ if (flags & OPT_extended_release)
+ {
+ s = astconf("RELEASE", NiL, NiL);
+ output(OPT_extended_release, s, "extended-release");
+ }
+#if _mem_idnumber_utsname
+ output(OPT_hostid, ut.idnumber, "hostid");
+#else
+ if (flags & OPT_hostid)
+ {
+ if (!*(s = astconf("HW_SERIAL", NiL, NiL)))
+#if _lib_gethostid
+ sfsprintf(s = buf, sizeof(buf), "%08x", gethostid());
+#else
+ /*NOP*/;
+#endif
+ output(OPT_hostid, s, "hostid");
+ }
+#endif
+ if (flags & OPT_vendor)
+ {
+ s = astconf("HW_PROVIDER", NiL, NiL);
+ output(OPT_vendor, s, "vendor");
+ }
+ if (flags & OPT_domain)
+ {
+ if (!*(s = astconf("SRPC_DOMAIN", NiL, NiL)))
+#if _lib_getdomainname
+ getdomainname(s, sizeof(buf));
+#else
+ /*NOP*/;
+#endif
+ output(OPT_domain, s, "domain");
+ }
+#if _mem_m_type_utsname
+ s = ut.m_type;
+#else
+ s = astconf("MACHINE", NiL, NiL);
+#endif
+ output(OPT_machine_type, s, "m_type");
+#if _mem_base_rel_utsname
+ s = ut.base_rel;
+#else
+ s = astconf("BASE", NiL, NiL);
+#endif
+ output(OPT_base, s, "base_rel");
+ if (flags & OPT_extra)
+ {
+ char* last = (char*)&ut;
+
+ extra(sysname);
+ extra(nodename);
+ extra(release);
+ extra(version);
+ extra(machine);
+#if _mem_idnumber_utsname
+ extra(idnumber);
+#endif
+#if _mem_m_type_utsname
+ extra(m_type);
+#endif
+#if _mem_base_rel_utsname
+ extra(base_rel);
+#endif
+ if (last < ((char*)(&ut + 1)))
+ {
+ s = t = last;
+ while (s < (char*)(&ut + 1))
+ {
+ if (!(n = *s++))
+ {
+ if ((s - t) > 1)
+ {
+ if (sep)
+ sfputc(sfstdout, ' ');
+ else
+ sep = 1;
+ sfputr(sfstdout, t, -1);
+ }
+ t = s;
+ }
+ else if (!isprint(n))
+ break;
+ }
+ }
+ }
+ if (sep)
+ sfputc(sfstdout, '\n');
+ }
+ return error_info.errors;
+}
diff --git a/src/lib/libcmd/uniq.c b/src/lib/libcmd/uniq.c
new file mode 100644
index 0000000..1336acd
--- /dev/null
+++ b/src/lib/libcmd/uniq.c
@@ -0,0 +1,342 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * uniq
+ *
+ * Written by David Korn
+ */
+
+static const char usage[] =
+"[-n?\n@(#)$Id: uniq (AT&T Research) 2009-11-28 $\n]"
+USAGE_LICENSE
+"[+NAME?uniq - Report or filter out repeated lines in a file]"
+"[+DESCRIPTION?\buniq\b reads the input, compares adjacent lines, and "
+ "writes one copy of each input line on the output. The second "
+ "and succeeding copies of the repeated adjacent lines are not "
+ "written.]"
+"[+?If the output file, \aoutfile\a, is not specified, \buniq\b writes "
+ "to standard output. If no \ainfile\a is given, or if the \ainfile\a "
+ "is \b-\b, \buniq\b reads from standard input with the start of "
+ "the file defined as the current offset.]"
+"[c:count?Output the number of times each line occurred along with "
+ "the line.]"
+"[d:repeated|duplicates?Output the first of each duplicate line.]"
+"[D:all-repeated?Output all duplicate lines as a group with an empty "
+ "line delimiter specified by \adelimit\a:]:?[delimit:=none]"
+ "{"
+ "[n:none?Do not delimit duplicate groups.]"
+ "[p:prepend?Prepend an empty line before each group.]"
+ "[s:separate?Separate each group with an empty line.]"
+ "}"
+"[f:skip-fields]#[fields?\afields\a is the number of fields to skip over "
+ "before checking for uniqueness. A field is the minimal string matching "
+ "the BRE \b[[:blank:]]]]*[^[:blank:]]]]*\b. -\anumber\a is equivalent to "
+ "\b--skip-fields\b=\anumber\a.]"
+"[i:ignore-case?Ignore case in comparisons.]"
+"[s:skip-chars]#[chars?\achars\a is the number of characters to skip over "
+ "before checking for uniqueness. If specified along with \b-f\b, "
+ "the first \achars\a after the first \afields\a are ignored. If "
+ "the \achars\a specifies more characters than are on the line, "
+ "an empty string will be used for comparison. +\anumber\a is "
+ "equivalent to \b--skip-chars\b=\anumber\a.]"
+"[u:unique?Output unique lines.]"
+"[w:check-chars]#[chars?\achars\a is the number of characters to compare "
+ "after skipping any specified fields and characters.]"
+"\n"
+"\n[infile [outfile]]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?The input file was successfully processed.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bsort\b(1), \bgrep\b(1)]"
+;
+
+#include <cmd.h>
+
+#define C_FLAG 1
+#define D_FLAG 2
+#define U_FLAG 4
+
+#define CWIDTH 4
+#define MAXCNT 9999
+
+typedef int (*Compare_f)(const char*, const char*, size_t);
+
+static int uniq(Sfio_t *fdin, Sfio_t *fdout, int fields, int chars, int width, int mode, int* all, Compare_f compare)
+{
+ register int n, f, outsize=0, mb = mbwide();
+ register char *cp, *ep, *mp, *bufp, *outp;
+ char *orecp, *sbufp=0, *outbuff;
+ int reclen,oreclen= -1,count=0,cwidth=0,sep,next;
+ if(mode&C_FLAG)
+ cwidth = CWIDTH+1;
+ while(1)
+ {
+ if(bufp = sfgetr(fdin,'\n',0))
+ n = sfvalue(fdin);
+ else if(bufp = sfgetr(fdin,'\n',SF_LASTR))
+ {
+ n = sfvalue(fdin);
+ bufp = memcpy(fmtbuf(n + 1), bufp, n);
+ bufp[n++] = '\n';
+ }
+ else
+ n = 0;
+ if (n)
+ {
+ cp = bufp;
+ ep = cp + n;
+ if (f = fields)
+ while (f-->0 && cp<ep) /* skip over fields */
+ {
+ while (cp<ep && *cp==' ' || *cp=='\t')
+ cp++;
+ while (cp<ep && *cp!=' ' && *cp!='\t')
+ cp++;
+ }
+ if (chars)
+ {
+ if (mb)
+ for (f = chars; f; f--)
+ mbchar(cp);
+ else
+ cp += chars;
+ }
+ if ((reclen = n - (cp - bufp)) <= 0)
+ {
+ reclen = 1;
+ cp = bufp + n - 1;
+ }
+ else if (width >= 0 && width < reclen)
+ {
+ if (mb)
+ {
+ reclen = 0;
+ mp = cp;
+ while (reclen < width && mp < ep)
+ {
+ reclen++;
+ mbchar(mp);
+ }
+ reclen = mp - cp;
+ }
+ else
+ reclen = width;
+ }
+ }
+ else
+ reclen = -2;
+ if(reclen==oreclen && (!reclen || !(*compare)(cp,orecp,reclen)))
+ {
+ count++;
+ if (!all)
+ continue;
+ next = count;
+ }
+ else
+ {
+ next = 0;
+ if(outsize>0)
+ {
+ if(((mode&D_FLAG)&&count==0) || ((mode&U_FLAG)&&count))
+ {
+ if(outp!=sbufp)
+ sfwrite(fdout,outp,0);
+ }
+ else
+ {
+ if(cwidth)
+ {
+ if(count<9)
+ {
+ f = 0;
+ while(f < CWIDTH-1)
+ outp[f++] = ' ';
+ outp[f++] = '0' + count + 1;
+ outp[f] = ' ';
+ }
+ else if(count<MAXCNT)
+ {
+ count++;
+ f = CWIDTH;
+ outp[f--] = ' ';
+ do
+ {
+ outp[f--] = '0' + (count % 10);
+ } while (count /= 10);
+ while (f >= 0)
+ outp[f--] = ' ';
+ }
+ else
+ {
+ outsize -= (CWIDTH+1);
+ if(outp!=sbufp)
+ {
+ if(!(sbufp=fmtbuf(outsize)))
+ return(1);
+ memcpy(sbufp,outp+CWIDTH+1,outsize);
+ sfwrite(fdout,outp,0);
+ outp = sbufp;
+ }
+ else
+ outp += CWIDTH+1;
+ sfprintf(fdout,"%4d ",count+1);
+ }
+ }
+ if(sfwrite(fdout,outp,outsize) != outsize)
+ return(1);
+ }
+ }
+ }
+ if(n==0)
+ break;
+ if(count = next)
+ {
+ if(sfwrite(fdout,outp,outsize) != outsize)
+ return(1);
+ if(*all >= 0)
+ *all = 1;
+ sep = 0;
+ }
+ else
+ sep = all && *all > 0;
+ /* save current record */
+ if (!(outbuff = sfreserve(fdout, 0, 0)) || (outsize = sfvalue(fdout)) < 0)
+ return(1);
+ outp = outbuff;
+ if(outsize < n+cwidth+sep)
+ {
+ /* no room in outp, clear lock and use side buffer */
+ sfwrite(fdout,outp,0);
+ if(!(sbufp = outp=fmtbuf(outsize=n+cwidth+sep)))
+ return(1);
+ }
+ else
+ outsize = n+cwidth+sep;
+ memcpy(outp+cwidth+sep,bufp,n);
+ if(sep)
+ outp[cwidth] = '\n';
+ oreclen = reclen;
+ orecp = outp+cwidth+sep + (cp-bufp);
+ }
+ return(0);
+}
+
+int
+b_uniq(int argc, char** argv, Shbltin_t* context)
+{
+ register int mode=0;
+ register char *cp;
+ int fields=0, chars=0, width=-1;
+ Sfio_t *fpin, *fpout;
+ int* all = 0;
+ int sep;
+ Compare_f compare = (Compare_f)memcmp;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'c':
+ mode |= C_FLAG;
+ continue;
+ case 'd':
+ mode |= D_FLAG;
+ continue;
+ case 'D':
+ mode |= D_FLAG;
+ switch ((int)opt_info.num)
+ {
+ case 'p':
+ sep = 1;
+ break;
+ case 's':
+ sep = 0;
+ break;
+ default:
+ sep = -1;
+ break;
+ }
+ all = &sep;
+ continue;
+ case 'i':
+ compare = (Compare_f)strncasecmp;
+ continue;
+ case 'u':
+ mode |= U_FLAG;
+ continue;
+ case 'f':
+ if(*opt_info.option=='-')
+ fields = opt_info.num;
+ else
+ chars = opt_info.num;
+ continue;
+ case 's':
+ chars = opt_info.num;
+ continue;
+ case 'w':
+ width = opt_info.num;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if(all && (mode&C_FLAG))
+ error(2, "-c and -D are mutually exclusive");
+ if(error_info.errors)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if((cp = *argv) && (argv++,!streq(cp,"-")))
+ {
+ if(!(fpin = sfopen(NiL,cp,"r")))
+ error(ERROR_system(1),"%s: cannot open",cp);
+ }
+ else
+ fpin = sfstdin;
+ if(cp = *argv)
+ {
+ argv++;
+ if(!(fpout = sfopen(NiL,cp,"w")))
+ error(ERROR_system(1),"%s: cannot create",cp);
+ }
+ else
+ fpout = sfstdout;
+ if(*argv)
+ {
+ error(2, "too many arguments");
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ }
+ error_info.errors = uniq(fpin,fpout,fields,chars,width,mode,all,compare);
+ if(fpin!=sfstdin)
+ sfclose(fpin);
+ if(fpout!=sfstdout)
+ sfclose(fpout);
+ return(error_info.errors);
+}
+
diff --git a/src/lib/libcmd/vmstate.c b/src/lib/libcmd/vmstate.c
new file mode 100644
index 0000000..6367819
--- /dev/null
+++ b/src/lib/libcmd/vmstate.c
@@ -0,0 +1,197 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#define FORMAT "region=%(region)p method=%(method)s flags=%(flags)s size=%(size)d segments=%(segments)d busy=(%(busy_size)d,%(busy_blocks)d,%(busy_max)d) free=(%(free_size)d,%(free_blocks)d,%(free_max)d)"
+
+static const char usage[] =
+"[-?\n@(#)$Id: vmstate (AT&T Research) 2010-04-08 $\n]"
+USAGE_LICENSE
+"[+NAME?vmstate - list the calling process vmalloc region state]"
+"[+DESCRIPTION?When invoked as a shell builtin, \bvmstate\b lists the "
+ "calling process \bvmalloc\b(3) state for all regions.]"
+"[f:format?List the ids specified by \aformat\a. \aformat\a follows "
+ "\bprintf\b(3) conventions, except that \bsfio\b(3) inline ids are used "
+ "instead of arguments: "
+ "%[-+]][\awidth\a[.\aprecis\a[.\abase\a]]]]]](\aid\a)\achar\a. The "
+ "supported \aid\as are:]:[format:=" FORMAT "]"
+ "{"
+ "[+method?The vmalloc method name.]"
+ "[+flags?The vmalloc method flags.]"
+ "[+size?The total region size.]"
+ "[+segments?The number of segments in the region.]"
+ "[+busy_size?The total busy block size.]"
+ "[+busy_blocks?The number of busy blocks.]"
+ "[+busy_max?The maximum busy block size.]"
+ "[+free_size?The total free block size.]"
+ "[+free_blocks?The number of free blocks.]"
+ "[+free_max?The maximum free block size.]"
+ "}"
+"[+SEE ALSO?\bvmalloc\b(3)]"
+;
+
+#include <cmd.h>
+#include <vmalloc.h>
+
+typedef struct State_s
+{
+ char* format;
+ Vmalloc_t* vm;
+ Vmstat_t vs;
+ unsigned int regions;
+ Vmalloc_t* region[256];
+} State_t;
+
+/*
+ * sfkeyprintf() lookup
+ * handle==0 for heading
+ */
+
+static int
+key(void* handle, Sffmt_t* fp, const char* arg, char** ps, Sflong_t* pn)
+{
+ register State_t* state = (State_t*)handle;
+ register char* s;
+
+ if (!(s = fp->t_str) || streq(s, "size"))
+ *pn = state->vs.extent;
+ else if (streq(s, "region"))
+ *pn = integralof(state->vm);
+ else if (streq(s, "segments"))
+ *pn = state->vs.n_seg;
+ else if (streq(s, "busy_size"))
+ *pn = state->vs.s_busy;
+ else if (streq(s, "busy_blocks"))
+ *pn = state->vs.n_busy;
+ else if (streq(s, "busy_max"))
+ *pn = state->vs.m_busy;
+ else if (streq(s, "flags"))
+ {
+ *ps = s = fmtbuf(32);
+#ifdef VM_TRUST
+ if (state->vs.mode & VM_TRUST)
+ s = strcopy(s, "TRUST|");
+#endif
+ if (state->vs.mode & VM_TRACE)
+ s = strcopy(s, "TRACE|");
+ if (state->vs.mode & VM_DBCHECK)
+ s = strcopy(s, "DBCHECK|");
+ if (state->vs.mode & VM_DBABORT)
+ s = strcopy(s, "DBABORT|");
+ if (s > *ps)
+ *(s - 1) = 0;
+ else
+ strcpy(s, "0");
+ }
+ else if (streq(s, "free_size"))
+ *pn = state->vs.s_free;
+ else if (streq(s, "free_blocks"))
+ *pn = state->vs.n_free;
+ else if (streq(s, "free_max"))
+ *pn = state->vs.m_free;
+ else if (streq(s, "format"))
+ *ps = (char*)state->format;
+ else if (streq(s, "method"))
+ {
+ if (state->vs.mode & VM_MTBEST)
+ *ps = "best";
+ else if (state->vs.mode & VM_MTPOOL)
+ *ps = "pool";
+ else if (state->vs.mode & VM_MTLAST)
+ *ps = "last";
+ else if (state->vs.mode & VM_MTDEBUG)
+ *ps = "debug";
+ else if (state->vs.mode & VM_MTPROFILE)
+ *ps = "profile";
+ else
+ *ps = "UNKNOWN";
+ }
+ else
+ {
+ error(2, "%s: unknown format identifier", s);
+ return 0;
+ }
+ return 1;
+}
+
+static int
+visit(Vmalloc_t* vm, void* addr, size_t size, Vmdisc_t* disc, void* handle)
+{
+ State_t* state = (State_t*)handle;
+
+ if (vm != state->vm)
+ {
+ state->vm = vm;
+ if (state->regions < elementsof(state->region))
+ state->region[state->regions++] = vm;
+ }
+ return 0;
+}
+
+int
+b_vmstate(int argc, char** argv, Shbltin_t* context)
+{
+ register int i;
+ State_t state;
+
+ memset(&state, 0, sizeof(state));
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'f':
+ state.format = opt_info.arg;
+ continue;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || *argv)
+ error(ERROR_USAGE|4, "%s", optusage(NiL));
+ if (!state.format)
+ state.format = FORMAT;
+
+ /*
+ * the walk must do no allocations because it locks the regions
+ */
+
+ vmwalk(NiL, visit, &state);
+
+ /*
+ * now we can compute and list the state of each region
+ */
+
+ for (i = 0; i < state.regions; i++)
+ {
+ state.vm = state.region[i];
+ vmstat(state.vm, &state.vs);
+ sfkeyprintf(sfstdout, &state, state.format, key, NiL);
+ sfprintf(sfstdout, "\n");
+ }
+ return 0;
+}
diff --git a/src/lib/libcmd/wc.c b/src/lib/libcmd/wc.c
new file mode 100644
index 0000000..42956a0
--- /dev/null
+++ b/src/lib/libcmd/wc.c
@@ -0,0 +1,188 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * count the number of bytes, words, and lines in a file
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: wc (AT&T Research) 2009-11-28 $\n]"
+USAGE_LICENSE
+"[+NAME?wc - print the number of bytes, words, and lines in files]"
+"[+DESCRIPTION?\bwc\b reads one or more input files and, by default, "
+ "for each file writes a line containing the number of newlines, "
+ "\aword\as, and bytes contained in each file followed by the "
+ "file name to standard output in that order. A \aword\a is "
+ "defined to be a non-zero length string delimited by \bisspace\b(3) "
+ "characters.]"
+"[+?If more than one file is specified, \bwc\b writes a total count "
+ "for all of the named files with \btotal\b written instead "
+ "of the file name.]"
+"[+?By default, \bwc\b writes all three counts. Options can specified "
+ "so that only certain counts are written. The options \b-c\b "
+ "and \b-m\b are mutually exclusive.]"
+"[+?If no \afile\a is given, or if the \afile\a is \b-\b, \bwc\b "
+ "reads from standard input and no filename is written to standard "
+ "output. The start of the file is defined as the current offset.]"
+"[l:lines?List the line counts.]"
+"[w:words?List the word counts.]"
+"[c:bytes|chars:chars?List the byte counts.]"
+"[m|C:multibyte-chars?List the character counts.]"
+"[q:quiet?Suppress invalid multibyte character warnings.]"
+"[L:longest-line|max-line-length?List the longest line length; the newline,"
+ "if any, is not counted in the length.]"
+"[N!:utf8?For \bUTF-8\b locales \b--noutf8\b disables \bUTF-8\b "
+ "optimzations and relies on the native \bmbtowc\b(3).]"
+"\n"
+"\n[file ...]\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All files processed successfully.]"
+ "[+>0?One or more files failed to open or could not be read.]"
+"}"
+"[+SEE ALSO?\bcat\b(1), \bisspace\b(3)]"
+;
+
+
+#include <cmd.h>
+#include <wc.h>
+#include <ls.h>
+
+#define ERRORMAX 125
+
+static void printout(register Wc_t *wp, register char *name,register int mode)
+{
+ if (mode&WC_LINES)
+ sfprintf(sfstdout," %7I*d",sizeof(wp->lines),wp->lines);
+ if (mode&WC_WORDS)
+ sfprintf(sfstdout," %7I*d",sizeof(wp->words),wp->words);
+ if (mode&WC_CHARS)
+ sfprintf(sfstdout," %7I*d",sizeof(wp->chars),wp->chars);
+ if (mode&WC_LONGEST)
+ sfprintf(sfstdout," %7I*d",sizeof(wp->chars),wp->longest);
+ if (name)
+ sfprintf(sfstdout," %s",name);
+ sfputc(sfstdout,'\n');
+}
+
+int
+b_wc(int argc,register char **argv, Shbltin_t* context)
+{
+ register char *cp;
+ register int mode=0, n;
+ register Wc_t *wp;
+ Sfio_t *fp;
+ Sfoff_t tlines=0, twords=0, tchars=0;
+ struct stat statb;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 'c':
+ mode |= WC_CHARS;
+ continue;
+ case 'l':
+ mode |= WC_LINES;
+ continue;
+ case 'L':
+ mode |= WC_LONGEST;
+ continue;
+ case 'N':
+ if (!opt_info.num)
+ mode |= WC_NOUTF8;
+ continue;
+ case 'm':
+ case 'C':
+ mode |= WC_MBYTE;
+ continue;
+ case 'q':
+ mode |= WC_QUIET;
+ continue;
+ case 'w':
+ mode |= WC_WORDS;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ if (mode&WC_MBYTE)
+ {
+ if (mode&WC_CHARS)
+ error(2, "-c and -C are mutually exclusive");
+ if (!mbwide())
+ mode &= ~WC_MBYTE;
+ mode |= WC_CHARS;
+ }
+ if (!(mode&(WC_WORDS|WC_CHARS|WC_LINES|WC_MBYTE|WC_LONGEST)))
+ mode |= (WC_WORDS|WC_CHARS|WC_LINES);
+ if (!(wp = wc_init(mode)))
+ error(3,"internal error");
+ if (cp = *argv)
+ argv++;
+ n = 0;
+ do
+ {
+ if (!cp || streq(cp,"-"))
+ fp = sfstdin;
+ else if (!(fp = sfopen(NiL,cp,"r")))
+ {
+ error(ERROR_system(0),"%s: cannot open",cp);
+ continue;
+ }
+ if (cp)
+ n++;
+ if (!(mode&(WC_WORDS|WC_LINES|WC_MBYTE|WC_LONGEST)) && fstat(sffileno(fp),&statb)>=0
+ && S_ISREG(statb.st_mode))
+ {
+ wp->chars = statb.st_size - lseek(sffileno(fp),0L,1);
+ lseek(sffileno(fp),0L,2);
+ }
+ else
+ wc_count(wp, fp, cp);
+ if (fp!=sfstdin)
+ sfclose(fp);
+ tchars += wp->chars;
+ twords += wp->words;
+ tlines += wp->lines;
+ printout(wp,cp,mode);
+ } while (cp= *argv++);
+ if (n > 1)
+ {
+ wp->lines = tlines;
+ wp->chars = tchars;
+ wp->words = twords;
+ printout(wp,"total",mode);
+ }
+ return error_info.errors<ERRORMAX?error_info.errors:ERRORMAX;
+}
diff --git a/src/lib/libcmd/wc.h b/src/lib/libcmd/wc.h
new file mode 100644
index 0000000..972767f
--- /dev/null
+++ b/src/lib/libcmd/wc.h
@@ -0,0 +1,59 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * header for wc library interface
+ */
+
+#ifndef _WC_H
+#define _WC_H
+
+#include <ast.h>
+
+#define WC_LINES 0x01
+#define WC_WORDS 0x02
+#define WC_CHARS 0x04
+#define WC_MBYTE 0x08
+#define WC_LONGEST 0x10
+#define WC_QUIET 0x20
+#define WC_NOUTF8 0x40
+
+typedef struct
+{
+ char type[1<<CHAR_BIT];
+ Sfoff_t words;
+ Sfoff_t lines;
+ Sfoff_t chars;
+ Sfoff_t longest;
+ int mode;
+ int mb;
+} Wc_t;
+
+#define wc_count _cmd_wccount
+#define wc_init _cmd_wcinit
+
+extern Wc_t* wc_init(int);
+extern int wc_count(Wc_t*, Sfio_t*, const char*);
+
+#endif /* _WC_H */
diff --git a/src/lib/libcmd/wclib.c b/src/lib/libcmd/wclib.c
new file mode 100644
index 0000000..0d52fda
--- /dev/null
+++ b/src/lib/libcmd/wclib.c
@@ -0,0 +1,505 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Bell Laboratories
+ *
+ * library interface for word count
+ */
+
+#include <cmd.h>
+#include <wc.h>
+#include <ctype.h>
+
+#if _hdr_wchar && _hdr_wctype && _lib_iswctype
+
+#include <wchar.h>
+#include <wctype.h>
+#include <lc.h>
+
+#else
+
+#ifndef iswspace
+#define iswspace(x) isspace(x)
+#endif
+
+#endif
+
+#define WC_SP 0x08
+#define WC_NL 0x10
+#define WC_MB 0x20
+#define WC_ERR 0x40
+
+#define eol(c) ((c)&WC_NL)
+#define mbc(c) ((c)&WC_MB)
+#define spc(c) ((c)&WC_SP)
+#define mb2wc(w,p,n) (*ast.mb_towc)(&w,(char*)p,n)
+
+Wc_t* wc_init(int mode)
+{
+ register int n;
+ register int w;
+ Wc_t* wp;
+
+ if (!(wp = (Wc_t*)stakalloc(sizeof(Wc_t))))
+ return 0;
+ if (!mbwide())
+ wp->mb = 0;
+#if _hdr_wchar && _hdr_wctype && _lib_iswctype
+ else if (!(mode & WC_NOUTF8) && (lcinfo(LC_CTYPE)->lc->flags & LC_utf8))
+ wp->mb = 1;
+#endif
+ else
+ wp->mb = -1;
+ w = mode & WC_WORDS;
+ for (n = (1<<CHAR_BIT); --n >= 0;)
+ wp->type[n] = (w && isspace(n)) ? WC_SP : 0;
+ wp->type['\n'] = WC_SP|WC_NL;
+ if ((mode & (WC_MBYTE|WC_WORDS)) && wp->mb > 0)
+ {
+ for (n = 0; n < 64; n++)
+ {
+ wp->type[0x80+n] |= WC_MB;
+ if (n<32)
+ wp->type[0xc0+n] |= WC_MB+1;
+ else if (n<48)
+ wp->type[0xc0+n] |= WC_MB+2;
+ else if (n<56)
+ wp->type[0xc0+n] |= WC_MB+3;
+ else if (n<60)
+ wp->type[0xc0+n] |= WC_MB+4;
+ else if (n<62)
+ wp->type[0xc0+n] |= WC_MB+5;
+ }
+ wp->type[0xc0] = WC_MB|WC_ERR;
+ wp->type[0xc1] = WC_MB|WC_ERR;
+ wp->type[0xfe] = WC_MB|WC_ERR;
+ wp->type[0xff] = WC_MB|WC_ERR;
+ }
+ wp->mode = mode;
+ return wp;
+}
+
+static int invalid(const char *file, int nlines)
+{
+ error_info.file = (char*)file;
+ error_info.line = nlines;
+ error(ERROR_SYSTEM|1, "invalid multibyte character");
+ error_info.file = 0;
+ error_info.line = 0;
+ return nlines;
+}
+
+/*
+ * handle utf space characters
+ */
+
+static int chkstate(int state, register unsigned int c)
+{
+ switch(state)
+ {
+ case 1:
+ state = (c==0x9a?4:0);
+ break;
+ case 2:
+ state = ((c==0x80||c==0x81)?6+(c&1):0);
+ break;
+ case 3:
+ state = (c==0x80?5:0);
+ break;
+ case 4:
+ state = (c==0x80?10:0);
+ break;
+ case 5:
+ state = (c==0x80?10:0);
+ break;
+ case 6:
+ state = 0;
+ if(c==0xa0 || c==0xa1)
+ return(10);
+ else if((c&0xf0)== 0x80)
+ {
+ if((c&=0xf)==7)
+ return(iswspace(0x2007)?10:0);
+ if(c<=0xb)
+ return(10);
+ }
+ else if(c==0xaf && iswspace(0x202f))
+ return(10);
+ break;
+ case 7:
+ state = (c==0x9f?10:0);
+ break;
+ case 8:
+ return (iswspace(c)?10:0);
+ }
+ return state;
+}
+
+/*
+ * compute the line, word, and character count for file <fd>
+ */
+
+int wc_count(Wc_t *wp, Sfio_t *fd, const char* file)
+{
+ register char* type = wp->type;
+ register unsigned char* cp;
+ register Sfoff_t nbytes;
+ register Sfoff_t nchars;
+ register Sfoff_t nwords;
+ register Sfoff_t nlines;
+ register Sfoff_t eline = -1;
+ register Sfoff_t longest = 0;
+ register ssize_t c;
+ register unsigned char* endbuff;
+ register int lasttype = WC_SP;
+ unsigned int lastchar;
+ ssize_t n;
+ ssize_t o;
+ unsigned char* buff;
+ wchar_t x;
+ unsigned char side[32];
+
+ sfset(fd,SF_WRITE,1);
+ nlines = nwords = nchars = nbytes = 0;
+ wp->longest = 0;
+ if (wp->mb < 0 && (wp->mode & (WC_MBYTE|WC_WORDS)))
+ {
+ cp = buff = endbuff = 0;
+ for (;;)
+ {
+ if (cp >= endbuff || (n = mb2wc(x, cp, endbuff-cp)) < 0)
+ {
+ if ((o = endbuff-cp) < sizeof(side))
+ {
+ if (buff)
+ {
+ if (o)
+ memcpy(side, cp, o);
+ mbinit();
+ }
+ else
+ o = 0;
+ cp = side + o;
+ if (!(buff = (unsigned char*)sfreserve(fd, SF_UNBOUND, 0)) || (n = sfvalue(fd)) <= 0)
+ {
+ if ((nchars - longest) > wp->longest)
+ wp->longest = nchars - longest;
+ break;
+ }
+ nbytes += n;
+ if ((c = sizeof(side) - o) > n)
+ c = n;
+ if (c)
+ memcpy(cp, buff, c);
+ endbuff = buff + n;
+ cp = side;
+ x = mbchar(cp);
+ if ((cp-side) < o)
+ {
+ cp = buff;
+ nchars += (cp-side) - 1;
+ }
+ else
+ cp = buff + (cp-side) - o;
+ }
+ else
+ {
+ cp++;
+ x = -1;
+ }
+ if (x == -1 && eline != nlines && !(wp->mode & WC_QUIET))
+ eline = invalid(file, nlines);
+ }
+ else
+ cp += n ? n : 1;
+ if (x == '\n')
+ {
+ if ((nchars - longest) > wp->longest)
+ wp->longest = nchars - longest;
+ longest = nchars + 1;
+ nlines++;
+ lasttype = 1;
+ }
+ else if (iswspace(x))
+ lasttype = 1;
+ else if (lasttype)
+ {
+ lasttype = 0;
+ nwords++;
+ }
+ nchars++;
+ }
+ if (!(wp->mode & WC_MBYTE))
+ nchars = nbytes;
+ }
+ else if (!wp->mb && !(wp->mode & WC_LONGEST) || wp->mb > 0 && !(wp->mode & (WC_MBYTE|WC_WORDS|WC_LONGEST)))
+ {
+ if (!(wp->mode & (WC_MBYTE|WC_WORDS|WC_LONGEST)))
+ {
+ while ((cp = (unsigned char*)sfreserve(fd, SF_UNBOUND, 0)) && (c = sfvalue(fd)) > 0)
+ {
+ nchars += c;
+ endbuff = cp + c;
+ if (*--endbuff == '\n')
+ nlines++;
+ else
+ *endbuff = '\n';
+ for (;;)
+ if (*cp++ == '\n')
+ {
+ if (cp > endbuff)
+ break;
+ nlines++;
+ }
+ }
+ }
+ else
+ {
+ while ((cp = buff = (unsigned char*)sfreserve(fd, SF_UNBOUND, 0)) && (c = sfvalue(fd)) > 0)
+ {
+ nchars += c;
+ /* check to see whether first character terminates word */
+ if (c==1)
+ {
+ if (eol(lasttype))
+ nlines++;
+ if ((c = type[*cp]) && !lasttype)
+ nwords++;
+ lasttype = c;
+ continue;
+ }
+ if (!lasttype && type[*cp])
+ nwords++;
+ lastchar = cp[--c];
+ *(endbuff = cp+c) = '\n';
+ c = lasttype;
+ /* process each buffer */
+ for (;;)
+ {
+ /* process spaces and new-lines */
+ do
+ {
+ if (eol(c))
+ for (;;)
+ {
+ /* check for end of buffer */
+ if (cp > endbuff)
+ goto beob;
+ nlines++;
+ if (*cp != '\n')
+ break;
+ cp++;
+ }
+ } while (c = type[*cp++]);
+ /* skip over word characters */
+ while (!(c = type[*cp++]));
+ nwords++;
+ }
+ beob:
+ if ((cp -= 2) >= buff)
+ c = type[*cp];
+ else
+ c = lasttype;
+ lasttype = type[lastchar];
+ /* see if was in word */
+ if (!c && !lasttype)
+ nwords--;
+ }
+ if (eol(lasttype))
+ nlines++;
+ else if (!lasttype)
+ nwords++;
+ }
+ }
+ else
+ {
+ int lineoff=0;
+ int skip=0;
+ int adjust=0;
+ int state=0;
+ int oldc;
+ int xspace;
+ int wasspace = 1;
+ unsigned char* start;
+
+ lastchar = 0;
+ start = (endbuff = side) + 1;
+ xspace = iswspace(0xa0) || iswspace(0x85);
+ while ((cp = buff = (unsigned char*)sfreserve(fd, SF_UNBOUND, 0)) && (c = sfvalue(fd)) > 0)
+ {
+ nbytes += c;
+ nchars += c;
+ start = cp-lineoff;
+ /* check to see whether first character terminates word */
+ if(c==1)
+ {
+ if(eol(lasttype))
+ nlines++;
+ if((c = type[*cp]) && !lasttype)
+ nwords++;
+ lasttype = c;
+ endbuff = start;
+ continue;
+ }
+ lastchar = cp[--c];
+ endbuff = cp+c;
+ cp[c] = '\n';
+ if(mbc(lasttype))
+ {
+ c = lasttype;
+ goto mbyte;
+ }
+ if(!lasttype && spc(type[*cp]))
+ nwords++;
+ c = lasttype;
+ /* process each buffer */
+ for (;;)
+ {
+ /* process spaces and new-lines */
+ spaces:
+ do
+ {
+ if (eol(c))
+ {
+ /* check for end of buffer */
+ if (cp > endbuff)
+ goto eob;
+ if(wp->mode&WC_LONGEST)
+ {
+ if((cp-start)-adjust > longest)
+ longest = (cp-start)-adjust-1;
+ start = cp;
+ }
+ nlines++;
+ nchars -= adjust;
+ adjust = 0;
+ }
+ } while (spc(c = type[*cp++]));
+ wasspace=1;
+ if(mbc(c))
+ {
+ mbyte:
+ do
+ {
+ if(c&WC_ERR)
+ goto err;
+ if(skip && (c&7))
+ break;
+ if(!skip)
+ {
+ if(!(c&7))
+ {
+ skip=1;
+ break;
+ }
+ skip = (c&7);
+ adjust += skip;
+ state = 0;
+ if(skip==2 && (cp[-1]&0xc)==0 && (state=(cp[-1]&0x3)))
+ oldc = *cp;
+ else if(xspace && cp[-1]==0xc2)
+ {
+ state = 8;
+ oldc = *cp;
+ }
+ }
+ else
+ {
+ skip--;
+ if(state && (state=chkstate(state,oldc)))
+ {
+ if(state==10)
+ {
+ if(!wasspace)
+ nwords++;
+ wasspace = 1;
+ state=0;
+ goto spaces;
+ }
+ oldc = *cp;
+ }
+ }
+ } while (mbc(c = type[*cp++]));
+ wasspace = 0;
+ if(skip)
+ {
+ if(eol(c) && (cp > endbuff))
+ goto eob;
+ err:
+ skip = 0;
+ state = 0;
+ if(eline!=nlines && !(wp->mode & WC_QUIET))
+ eline = invalid(file, nlines);
+ while(mbc(c) && ((c|WC_ERR) || (c&7)==0))
+ c=type[*cp++];
+ if(eol(c) && (cp > endbuff))
+ {
+ c = WC_MB|WC_ERR;
+ goto eob;
+ }
+ if(mbc(c))
+ goto mbyte;
+ else if(c&WC_SP)
+ goto spaces;
+ }
+ if(spc(c))
+ {
+ nwords++;
+ continue;
+ }
+ }
+ /* skip over word characters */
+ while(!(c = type[*cp++]));
+ if(mbc(c))
+ goto mbyte;
+ nwords++;
+ }
+ eob:
+ lineoff = cp-start;
+ if((cp -= 2) >= buff)
+ c = type[*cp];
+ else
+ c = lasttype;
+ lasttype = type[lastchar];
+ /* see if was in word */
+ if(!c && !lasttype)
+ nwords--;
+ }
+ if ((wp->mode&WC_LONGEST) && ((endbuff + 1 - start) - adjust - (lastchar == '\n')) > longest)
+ longest = (endbuff + 1 - start) - adjust - (lastchar == '\n');
+ wp->longest = longest;
+ if (eol(lasttype))
+ nlines++;
+ else if (!lasttype)
+ nwords++;
+ if (wp->mode & WC_MBYTE)
+ nchars -= adjust;
+ else
+ nchars = nbytes;
+ }
+ wp->chars = nchars;
+ wp->words = nwords;
+ wp->lines = nlines;
+ return 0;
+}
+
diff --git a/src/lib/libcoshell/Makefile b/src/lib/libcoshell/Makefile
new file mode 100644
index 0000000..8fe9beb
--- /dev/null
+++ b/src/lib/libcoshell/Makefile
@@ -0,0 +1,20 @@
+/*
+ * coshell library
+ */
+
+:PACKAGE: ast
+
+CCFLAGS = $(CC.OPTIMIZE) $(CC.PIC) /* pic allows archive to be pulled into other dlls */
+
+LICENSE = since=1990,author=gsf
+
+coshell 1.0 :LIBRARY: RELEASE coshell.3 coshell.h colib.h \
+ coopen.c coclose.c coinit.c coexec.c costash.c \
+ cowait.c cokill.c cosync.c coquote.c codata.c \
+ coexport.c procrun.c system.c
+
+ignore :: ignore.sh
+
+silent :: silent.sh
+
+$(INCLUDEDIR) :INSTALLPROTO: coshell.h
diff --git a/src/lib/libcoshell/Mamfile b/src/lib/libcoshell/Mamfile
new file mode 100644
index 0000000..6f67e24
--- /dev/null
+++ b/src/lib/libcoshell/Mamfile
@@ -0,0 +1,464 @@
+info mam static 00000 1994-07-17 make (AT&T Research) 5.7 2012-02-29
+setv INSTALLROOT ../../..
+setv PACKAGE_ast_INCLUDE ${INSTALLROOT}/include/ast
+setv PACKAGE_ast_LIB ${INSTALLROOT}/lib
+setv PACKAGEROOT ../../../../..
+setv AR ${mam_cc_AR} ${mam_cc_AR_ARFLAGS}
+setv ARFLAGS rc
+setv AS as
+setv ASFLAGS
+setv CC cc
+setv mam_cc_FLAGS ${mam_cc_PIC}
+setv CCFLAGS ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${mam_cc_OPTIMIZE}?}
+setv CCLDFLAGS ${-strip-symbols?1?${mam_cc_LD_STRIP}??}
+setv COTEMP $$
+setv CPIO cpio
+setv CPIOFLAGS
+setv CPP "${CC} -E"
+setv F77 f77
+setv HOSTCC ${CC}
+setv IGNORE
+setv LD ld
+setv LDFLAGS
+setv LEX lex
+setv LEXFLAGS
+setv LPR lpr
+setv LPRFLAGS
+setv M4FLAGS
+setv NMAKE nmake
+setv NMAKEFLAGS
+setv PR pr
+setv PRFLAGS
+setv SHELL /bin/sh
+setv SILENT
+setv TAR tar
+setv YACC yacc
+setv YACCFLAGS -d
+make ${PACKAGEROOT}/lib/package/ast.lic
+done ${PACKAGEROOT}/lib/package/ast.lic
+make install
+make coshell
+make libcoshell.a archive
+make coshell.req
+exec - set -
+exec - echo 'int main(){return 0;}' > 1.${COTEMP}.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -c 1.${COTEMP}.c &&
+exec - x=`${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l'*' 2>&1 | sed -e 's/[][()+@?]/#/g' || :` &&
+exec - {
+exec - case "" in
+exec - *?) echo " " ;;
+exec - esac
+exec - for i in coshell ast
+exec - do case $i in
+exec - "coshell"|coshell)
+exec - ;;
+exec - *) if test -f ${INSTALLROOT}/lib/lib/$i
+exec - then y=`cat ${INSTALLROOT}/lib/lib/$i`
+exec - case $y in
+exec - *-?*) echo "" $y ;;
+exec - esac
+exec - continue
+exec - elif test ! -f ${INSTALLROOT}/lib/lib$i.a
+exec - then case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -L${INSTALLROOT}/lib ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) continue ;;
+exec - esac
+exec - ;;
+exec - esac
+exec - fi
+exec - ;;
+exec - esac
+exec - echo " -l$i"
+exec - done
+exec - } > coshell.req
+exec - rm -f 1.${COTEMP}.*
+done coshell.req generated
+make coopen.o
+make coopen.c
+make ${PACKAGE_ast_INCLUDE}/tok.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_api.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_api.h dontcare
+make ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_map.h dontcare
+make ${PACKAGE_ast_INCLUDE}/endian.h implicit
+make ${PACKAGE_ast_INCLUDE}/bytesex.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+done ${PACKAGE_ast_INCLUDE}/bytesex.h dontcare
+done ${PACKAGE_ast_INCLUDE}/endian.h dontcare
+done ${PACKAGE_ast_INCLUDE}/ast_common.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+make ${PACKAGE_ast_INCLUDE}/regex.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+make ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wctype.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wctype.h dontcare
+done ${PACKAGE_ast_INCLUDE}/wctype.h dontcare
+make ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_stdio.h implicit
+make ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
+done ${PACKAGE_ast_INCLUDE}/sfio_s.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_stdio.h dontcare
+done ${PACKAGE_ast_INCLUDE}/stdio.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wchar.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+make ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+make ${INSTALLROOT}/include/prototyped.h implicit
+done ${INSTALLROOT}/include/prototyped.h dontcare
+done ${PACKAGE_ast_INCLUDE}/prototyped.h dontcare
+done ${PACKAGE_ast_INCLUDE}/regex.h dontcare
+make ${PACKAGE_ast_INCLUDE}/getopt.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_getopt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_getopt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/getopt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_botch.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_botch.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_limits.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_limits.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_fcntl.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_fs.h dontcare
+done ${PACKAGE_ast_INCLUDE}/ast_fcntl.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_getopt.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_sys.h implicit
+prev ${PACKAGE_ast_INCLUDE}/getopt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_sys.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_lib.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_lib.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_std.h dontcare
+done ${PACKAGE_ast_INCLUDE}/vmalloc.h dontcare
+make ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/sfio.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/tok.h
+make ${PACKAGE_ast_INCLUDE}/sfdisc.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/sfdisc.h
+make ${PACKAGE_ast_INCLUDE}/proc.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/proc.h
+make ${PACKAGE_ast_INCLUDE}/namval.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/namval.h
+make colib.h implicit
+make ${PACKAGE_ast_INCLUDE}/wait.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wait.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wait.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/wait.h dontcare
+make ${PACKAGE_ast_INCLUDE}/sig.h implicit
+done ${PACKAGE_ast_INCLUDE}/sig.h dontcare
+make ${PACKAGE_ast_INCLUDE}/error.h implicit
+make ${PACKAGE_ast_INCLUDE}/option.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/option.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/error.h dontcare
+make coshell.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done coshell.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+make ${PACKAGE_ast_INCLUDE}/dt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+make ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/cdt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/dt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done colib.h
+done coopen.c
+meta coopen.o %.c>%.o coopen.c coopen
+prev coopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c coopen.c
+done coopen.o generated
+make coclose.o
+make coclose.c
+prev colib.h implicit
+done coclose.c
+meta coclose.o %.c>%.o coclose.c coclose
+prev coclose.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c coclose.c
+done coclose.o generated
+make coinit.o
+make coinit.c
+make ${PACKAGE_ast_INCLUDE}/ls.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_mode.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ls.h
+make ${PACKAGE_ast_INCLUDE}/fs3d.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/fs3d.h
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev colib.h implicit
+done coinit.c
+meta coinit.o %.c>%.o coinit.c coinit
+prev coinit.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c coinit.c
+done coinit.o generated
+make coexec.o
+make coexec.c
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev ${PACKAGE_ast_INCLUDE}/proc.h implicit
+prev colib.h implicit
+done coexec.c
+meta coexec.o %.c>%.o coexec.c coexec
+prev coexec.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c coexec.c
+done coexec.o generated
+make costash.o
+make costash.c
+prev colib.h implicit
+done costash.c
+meta costash.o %.c>%.o costash.c costash
+prev costash.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c costash.c
+done costash.o generated
+make cowait.o
+make cowait.c
+prev colib.h implicit
+done cowait.c
+meta cowait.o %.c>%.o cowait.c cowait
+prev cowait.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c cowait.c
+done cowait.o generated
+make cokill.o
+make cokill.c
+prev colib.h implicit
+done cokill.c
+meta cokill.o %.c>%.o cokill.c cokill
+prev cokill.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c cokill.c
+done cokill.o generated
+make cosync.o
+make cosync.c
+make FEATURE/nfsd implicit
+meta FEATURE/nfsd >FEATURE/% nfsd
+bind -last
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libast} : def nfsd
+done FEATURE/nfsd generated
+prev ${PACKAGE_ast_INCLUDE}/ls.h implicit
+prev colib.h implicit
+done cosync.c
+meta cosync.o %.c>%.o cosync.c cosync
+prev cosync.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c cosync.c
+done cosync.o generated
+make coquote.o
+make coquote.c
+prev colib.h implicit
+done coquote.c
+meta coquote.o %.c>%.o coquote.c coquote
+prev coquote.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c coquote.c
+done coquote.o generated
+make codata.o
+make codata.c
+prev colib.h implicit
+done codata.c
+meta codata.o %.c>%.o codata.c codata
+prev codata.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c codata.c
+done codata.o generated
+make coexport.o
+make coexport.c
+prev colib.h implicit
+done coexport.c
+meta coexport.o %.c>%.o coexport.c coexport
+prev coexport.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c coexport.c
+done coexport.o generated
+make procrun.o
+make procrun.c
+prev ${PACKAGE_ast_INCLUDE}/proc.h implicit
+prev colib.h implicit
+done procrun.c
+meta procrun.o %.c>%.o procrun.c procrun
+prev procrun.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c procrun.c
+done procrun.o generated
+make system.o
+make system.c
+prev colib.h implicit
+done system.c
+meta system.o %.c>%.o system.c system
+prev system.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_coshell -c system.c
+done system.o generated
+exec - ${AR} rc libcoshell.a coopen.o coclose.o coinit.o coexec.o costash.o cowait.o cokill.o cosync.o coquote.o codata.o coexport.o procrun.o system.o
+exec - (ranlib libcoshell.a) >/dev/null 2>&1 || true
+done libcoshell.a generated
+done coshell virtual
+prev libcoshell.a archive
+make ignore
+make ignore.sh
+done ignore.sh
+meta ignore %.sh>% ignore.sh ignore
+prev ignore.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : ignore contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n ignore.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 0 in
+exec - 0) cp ignore.sh ignore
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < ignore.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - ignore.sh <<'!'
+exec -
+exec - !
+exec - } > ignore
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - ignore.sh > ignore <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec -
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w ignore -a -x ignore || chmod u+w,+x ignore
+done ignore generated
+make silent
+make silent.sh
+done silent.sh
+meta silent %.sh>% silent.sh silent
+prev silent.sh
+exec - case static,port:$OPTIND:$RANDOM in
+exec - ?*:*:*|*::*|*:*:$RANDOM)
+exec - ;;
+exec - *) if ENV= LC_ALL=C x= $SHELL -nc '[[ a || b ]] && : ${list[level]} !(pattern)' 2>/dev/null
+exec - then if grep -q '### .*archaic.* ###'
+exec - then : silent contains archaic constructs :
+exec - else ENV= LC_ALL=C $SHELL -n silent.sh
+exec - fi
+exec - fi
+exec - ;;
+exec - esac
+exec - case '${mam_cc_SHELLMAGIC}' in
+exec - "") case 0 in
+exec - 0) cp silent.sh silent
+exec - ;;
+exec - *) {
+exec - i=`(read x; echo $x) < silent.sh`
+exec - case $i in
+exec - '#!'*|*'||'*|':'*|'":"'*|"':'"*) echo "$i" ;;
+exec - esac
+exec - cat - silent.sh <<'!'
+exec -
+exec - !
+exec - } > silent
+exec - ;;
+exec - esac
+exec - ;;
+exec - *) cat - silent.sh > silent <<'!'
+exec - ${mam_cc_SHELLMAGIC}
+exec -
+exec - !
+exec - ;;
+exec - esac
+exec - silent test -w silent -a -x silent || chmod u+w,+x silent
+done silent generated
+make ${INSTALLROOT}/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib
+exec - then mkdir -p ${INSTALLROOT}/lib
+exec - fi
+done ${INSTALLROOT}/lib generated
+make ${INSTALLROOT}/lib/libcoshell.a archive
+prev ${INSTALLROOT}/lib
+prev libcoshell.a archive
+exec - test '' = 'libcoshell.a' || ${STDCMP} 2>/dev/null -s libcoshell.a ${INSTALLROOT}/lib/libcoshell.a || { ${STDMV} ${INSTALLROOT}/lib/libcoshell.a ${INSTALLROOT}/lib/libcoshell.a.old 2>/dev/null || true; ${STDCP} libcoshell.a ${INSTALLROOT}/lib/libcoshell.a ;}
+exec - (ranlib ${INSTALLROOT}/lib/libcoshell.a) >/dev/null 2>&1 || true
+done ${INSTALLROOT}/lib/libcoshell.a generated
+make ${INSTALLROOT}/man/man3
+exec - if silent test ! -d ${INSTALLROOT}/man/man3
+exec - then mkdir -p ${INSTALLROOT}/man/man3
+exec - fi
+done ${INSTALLROOT}/man/man3 generated
+make ${INSTALLROOT}/man/man3/coshell.3
+prev ${INSTALLROOT}/man/man3
+make coshell.3
+done coshell.3
+exec - test '' = 'coshell.3' || ${STDCMP} 2>/dev/null -s coshell.3 ${INSTALLROOT}/man/man3/coshell.3 || { ${STDMV} ${INSTALLROOT}/man/man3/coshell.3 ${INSTALLROOT}/man/man3/coshell.3.old 2>/dev/null || true; ${STDCP} coshell.3 ${INSTALLROOT}/man/man3/coshell.3 ;}
+done ${INSTALLROOT}/man/man3/coshell.3 generated
+make ${INSTALLROOT}/lib/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib/lib
+exec - then mkdir -p ${INSTALLROOT}/lib/lib
+exec - fi
+done ${INSTALLROOT}/lib/lib generated
+make ${INSTALLROOT}/lib/lib/coshell
+prev ${INSTALLROOT}/lib/lib
+prev coshell.req
+exec - test '' = 'coshell.req' || ${STDCMP} 2>/dev/null -s coshell.req ${INSTALLROOT}/lib/lib/coshell || { ${STDMV} ${INSTALLROOT}/lib/lib/coshell ${INSTALLROOT}/lib/lib/coshell.old 2>/dev/null || true; ${STDCP} coshell.req ${INSTALLROOT}/lib/lib/coshell ;}
+done ${INSTALLROOT}/lib/lib/coshell generated
+make ${INSTALLROOT}/bin
+exec - if silent test ! -d ${INSTALLROOT}/bin
+exec - then mkdir -p ${INSTALLROOT}/bin
+exec - fi
+done ${INSTALLROOT}/bin generated
+make ${INSTALLROOT}/bin/ignore
+prev ${INSTALLROOT}/bin
+prev ignore
+exec - test '' = 'ignore' || ${STDCMP} 2>/dev/null -s ignore ${INSTALLROOT}/bin/ignore || { ${STDMV} ${INSTALLROOT}/bin/ignore ${INSTALLROOT}/bin/ignore.old 2>/dev/null || true; ${STDCP} ignore ${INSTALLROOT}/bin/ignore ;}
+done ${INSTALLROOT}/bin/ignore generated
+make ${INSTALLROOT}/bin/silent
+prev silent
+exec - test '' = 'silent' || ${STDCMP} 2>/dev/null -s silent ${INSTALLROOT}/bin/silent || { ${STDMV} ${INSTALLROOT}/bin/silent ${INSTALLROOT}/bin/silent.old 2>/dev/null || true; ${STDCP} silent ${INSTALLROOT}/bin/silent ;}
+done ${INSTALLROOT}/bin/silent generated
+make ${PACKAGE_ast_INCLUDE}
+exec - if silent test ! -d ${PACKAGE_ast_INCLUDE}
+exec - then mkdir -p ${PACKAGE_ast_INCLUDE}
+exec - fi
+done ${PACKAGE_ast_INCLUDE} generated
+make ${PACKAGE_ast_INCLUDE}/coshell.h
+prev ${PACKAGE_ast_INCLUDE}
+prev coshell.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1990,author=gsf' coshell.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${PACKAGE_ast_INCLUDE}/coshell.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${PACKAGE_ast_INCLUDE}/coshell.h
+exec - fi
+done ${PACKAGE_ast_INCLUDE}/coshell.h generated
+done install virtual
+make test
+done test dontcare virtual
diff --git a/src/lib/libcoshell/RELEASE b/src/lib/libcoshell/RELEASE
new file mode 100644
index 0000000..9d09db2
--- /dev/null
+++ b/src/lib/libcoshell/RELEASE
@@ -0,0 +1,49 @@
+12-02-22 coinit.c: handle non-identifier export var names
+11-12-13 cowait.c: handle sfpoll() error return on interrupt
+11-11-21 cowait.c: poll before blocking read to weed out killed jobs (no 'x' message)
+11-08-30 codata.c,coopen.c: drop macro "..." catenation for old cc
+10-08-11 coinit.c: force _BLD_DLL for environ intercept
+10-06-01 sync with ast api 20100601
+10-05-19 cokill.c: do cowait(co,co,0) to drain pending messages
+10-05-15 coshell.h,coopen.c: add CO_ORPHAN for PROC_ORPHAN
+10-05-11 coopen.c: add PROC_ORPHAN for CO_SHELL
+10-05-10 coopen.c: no atexit() for CO_SHELL
+10-04-15 first ksh93u local job pool tests work (service daemon tbd)
+10-04-14 cowait.c: add 3rd cowait() arg timeout; 0 Coshell_t* operates on all open coshells
+10-04-10 coshell.h: add CO_SHELL for shell using coshell!
+09-12-09 coexport.c: add runtime CO_ENV_EXPORT hook that avoids changing environ
+08-10-28 coopen.c: close write side of parent msgfd -- doh
+08-04-28 coexec.c: check for fd 1,2 equivalence before CO_SERIALIZE 2>&1
+07-10-29 coshell.h,coexec.c: fix procrun()/system() intercept logic
+07-08-15 add CO_SEPARATE,CO_MODE_SEPARATE for separate shell+wait per action
+07-04-09 Makefile: $(CC.PIC) to allow archive to be pulled into other dlls
+06-08-22 coshell.h: procrun => coprocrun, system => cosystem
+06-08-09 coshell.h: export CO_ENV_MSGFD for COSHELL=coshell
+06-08-02 coexec.c: Cojob_t.flags&CO_SERVICE for service requests
+06-08-02 cokill.c: cokill() signal==0 => kill CO_SERVICE jobs
+06-07-27 coexec.c: drop server cowait() that bypassed caller
+06-06-21 coexec.c: add non-block cowait() to drain responses
+06-06-11 fix service intercept cleanup
+06-05-24 add service=name:init lightweight service intercepts
+05-04-19 cowait.c: beef up invalid message tests and diagnostics
+05-04-11 drop fixed CO_MSGFD for $_coshell_msgfd
+05-04-07 coexec.c: fix !_lib_fork&&_map_spawnve close-on-exec redirection
+04-09-22 cowait.c: remove CO_SERIALIZE temporaries after listing -- duh
+04-09-01 co*: add CO_SERIALIZE
+04-07-22 system.c: access() => eaccess()
+04-02-11 coinit.c: fix CO_CROSS PATH initialization
+02-10-30 coclose.c: fix reference-after-free bug in coclose()
+02-01-31 codata.c,coopen.c: fix CO_MSGFD parameterization
+02-01-24 coopen.c: fix small memory leak
+01-10-26 coopen.c: hung sfclose(fp) -> close(sffileno(fp)) -- wow
+01-09-11 coinit.c: fix coident[] for ancient bsh that die on `test == 1'
+ coinit.c: and fix coident[] to weed out buggy ksh88i trap on exit
+01-05-31 co*: add CO_CROSS, expose CO_DEVFD
+01-04-23 coquote: add state.type to avoid getenv() overwrite on some systems
+01-01-01 cokill: killjob => cokilljob, killshell => cokillshell
+00-12-18 coinit: CO_OSH ? "${!-$$}" : "${!:-$$}"
+00-10-25 codata: $ZSH_VERSION is not ksh
+00-02-14 procrun,system: system(3) returns wait() status (not shell status)
+99-11-19 co*: add CO_OSH for bsdi lack of times(1)
+ coexec: CO_IGNORE for all but real ksh
+98-06-22 coinit: quote cd path arg
diff --git a/src/lib/libcoshell/coclose.c b/src/lib/libcoshell/coclose.c
new file mode 100644
index 0000000..9ca00b5
--- /dev/null
+++ b/src/lib/libcoshell/coclose.c
@@ -0,0 +1,113 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * close a coshell
+ */
+
+#include "colib.h"
+
+/*
+ * called when coshell is hung
+ */
+
+static void
+hung(int sig)
+{
+ NoP(sig);
+ kill(state.current->pid, SIGKILL);
+}
+
+/*
+ * shut down one coshell
+ */
+
+static int
+shut(register Coshell_t* co)
+{
+ register Coshell_t* cs;
+ int n;
+ int status;
+ Coshell_t* ps;
+ Coservice_t* sv;
+ Sig_handler_t handler;
+
+ sfclose(co->msgfp);
+ close(co->cmdfd);
+ if (co->pid)
+ {
+ if (co->running > 0)
+ killpg(co->pid, SIGTERM);
+ state.current = co;
+ handler = signal(SIGALRM, hung);
+ n = alarm(3);
+ if (waitpid(co->pid, &status, 0) != co->pid)
+ status = -1;
+ alarm(n);
+ signal(SIGALRM, handler);
+ killpg(co->pid, SIGTERM);
+ }
+ else
+ status = 0;
+ if (co->flags & CO_DEBUG)
+ errormsg(state.lib, 2, "coshell %d jobs %d user %s sys %s", co->index, co->total, fmtelapsed(co->user, CO_QUANT), fmtelapsed(co->sys, CO_QUANT));
+ for (sv = co->service; sv; sv = sv->next)
+ {
+ if (sv->fd > 0)
+ close(sv->fd);
+ if (sv->pid)
+ waitpid(sv->pid, &status, 0);
+ }
+ cs = state.coshells;
+ ps = 0;
+ while (cs)
+ {
+ if (cs == co)
+ {
+ cs = cs->next;
+ if (ps)
+ ps->next = cs;
+ else
+ state.coshells = cs;
+ vmclose(co->vm);
+ break;
+ }
+ ps = cs;
+ cs = cs->next;
+ }
+ return status;
+}
+
+/*
+ * close coshell co
+ */
+
+int
+coclose(register Coshell_t* co)
+{
+ if (co)
+ return shut(co);
+ while (state.coshells)
+ shut(state.coshells);
+ return 0;
+}
diff --git a/src/lib/libcoshell/codata.c b/src/lib/libcoshell/codata.c
new file mode 100644
index 0000000..fa6559f
--- /dev/null
+++ b/src/lib/libcoshell/codata.c
@@ -0,0 +1,169 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * coshell readonly data
+ */
+
+#include "colib.h"
+
+char coident[] = "\
+# @(#)$Id: libcoshell (AT&T Research) 2012-02-22 $\n\
+%s=%d\n\
+{ { (eval 'function fun { trap \":\" 0; return 1; }; trap \"exit 0\" 0; fun; exit 1') && PATH= print -u$%s ksh; } || { times && echo bsh >&$%s; } || { echo osh >&$%s; }; } >/dev/null 2>&1\n\
+";
+
+char cobinit[] = "\
+if (eval 'f() echo') >/dev/null 2>&1\n\
+then eval 'ignore() {\n\
+ case $- in\n\
+ *x*) set -\n\
+ _coshell_silent=\n\
+ ;;\n\
+ *) _coshell_silent=1\n\
+ ;;\n\
+ esac\n\
+ _coshell_state=exp\n\
+ _coshell_stop=\"<< -- StoP -- >>\"\n\
+ _coshell_quote='\\\\\\''\n\
+ set \"$@\" \"$_coshell_stop\"\n\
+ while :\n\
+ do case $1 in\n\
+ $_coshell_stop)\n\
+ shift\n\
+ break\n\
+ ;;\n\
+ *=*) ;;\n\
+ *) _coshell_state=arg ;;\n\
+ esac\n\
+ case $_coshell_state in\n\
+ exp) _coshell_arg=`echo $1 | sed \"s/\\\\([^=]*\\\\)=\\\\(.*\\\\)/\\\\1=$_coshell_quote\\\\2$_coshell_quote/\"`\n\
+ set \"\" \"$@\" \"$_coshell_arg\"\n\
+ shift\n\
+ ;;\n\
+ arg) set \"\" \"$@\" \"$_coshell_quote$1$_coshell_quote\"\n\
+ shift\n\
+ ;;\n\
+ esac\n\
+ shift\n\
+ done\n\
+ case $_coshell_silent in\n\
+ \"\") set \"set -x;\" \"$@\" ;;\n\
+ esac\n\
+ eval \"$@\"\n\
+ return 0\n\
+ }'\n\
+ eval 'silent() {\n\
+ case $- in\n\
+ *x*) set -\n\
+ _coshell_silent=\n\
+ ;;\n\
+ *) _coshell_silent=1\n\
+ ;;\n\
+ esac\n\
+ _coshell_state=exp\n\
+ _coshell_stop=\"<< -- StoP -- >>\"\n\
+ _coshell_quote='\\\\\\''\n\
+ set \"$@\" \"$_coshell_stop\"\n\
+ while :\n\
+ do case $1 in\n\
+ $_coshell_stop)\n\
+ shift\n\
+ break\n\
+ ;;\n\
+ *=*) ;;\n\
+ *) _coshell_state=arg ;;\n\
+ esac\n\
+ case $_coshell_state in\n\
+ exp) _coshell_arg=`echo $1 | sed \"s/\\\\([^=]*\\\\)=\\\\(.*\\\\)/\\\\1=$_coshell_quote\\\\2$_coshell_quote/\"`\n\
+ set \"\" \"$@\" \"$_coshell_arg\"\n\
+ shift\n\
+ ;;\n\
+ arg) set \"\" \"$@\" \"$_coshell_quote$1$_coshell_quote\"\n\
+ shift\n\
+ ;;\n\
+ esac\n\
+ shift\n\
+ done\n\
+ eval \"$@\"\n\
+ _coshell_state=$?\n\
+ case $_coshell_silent in\n\
+ \"\") set -x ;;\n\
+ esac\n\
+ return $_coshell_state\n\
+ }'\n\
+else :\n\
+fi\n\
+";
+
+char cokinit[] = "\
+set +o bgnice -o monitor\n\
+(wait $$; exit 0) 2>/dev/null || alias wait=:\n\
+alias ignore='ignore '\n\
+function ignore\n\
+{\n\
+ integer argc=0\n\
+ typeset argv state=exp\n\
+ while :\n\
+ do case $# in\n\
+ 0) break ;;\n\
+ esac\n\
+ case $1 in\n\
+ *=*) ;;\n\
+ *) state=arg ;;\n\
+ esac\n\
+ case $state in\n\
+ exp) argv[argc]=${1%%=*}=\"'${1#*=}'\" ;;\n\
+ arg) argv[argc]=\"'\"$1\"'\" ;;\n\
+ esac\n\
+ ((argc=argc+1))\n\
+ shift\n\
+ done\n\
+ eval \"${argv[@]}\"\n\
+ return 0\n\
+}\n\
+alias silent='set +x X$- \"$@\";_coshell_flags_=$1;shift;silent '\n\
+function silent\n\
+{\n\
+ case $_coshell_flags_ in\n\
+ *x*) trap ' _coshell_status_=$?\n\
+ if ((_coshell_status_==0))\n\
+ then set -x\n\
+ else set -x;(set +x;exit $_coshell_status_)\n\
+ fi' 0\n\
+ ;;\n\
+ esac\n\
+ \"$@\"\n\
+}\n\
+typeset -xf ignore silent\n\
+";
+
+char* co_export[] = /* default export var list */
+{
+ CO_ENV_EXPORT, /* first */
+ CO_ENV_ATTRIBUTES,
+ CO_ENV_PROC,
+ "FPATH",
+ "VPATH",
+ 0 /* last */
+};
diff --git a/src/lib/libcoshell/coexec.c b/src/lib/libcoshell/coexec.c
new file mode 100644
index 0000000..637c650
--- /dev/null
+++ b/src/lib/libcoshell/coexec.c
@@ -0,0 +1,449 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * send an action to the coshell for execution
+ */
+
+#include "colib.h"
+
+#include <proc.h>
+#include <ls.h>
+
+static Cojob_t*
+service(register Coshell_t* co, Coservice_t* cs, Cojob_t* cj, int flags, Sfio_t* sp)
+{
+ Proc_t* proc;
+ size_t n;
+ int i;
+ int j;
+ int fds[2];
+ long ops[4];
+ char* s;
+ char** a;
+
+ if (flags & CO_DEBUG)
+ {
+ for (a = cs->argv; *a; a++)
+ sfprintf(sp, " %s", *a);
+ if (!(s = costash(sp)))
+ goto nospace;
+ errormsg(state.lib, ERROR_LIBRARY|2, "service %s:%s", cs->path, s);
+ }
+ if (pipe(fds) < 0)
+ {
+ errormsg(state.lib, ERROR_LIBRARY|ERROR_SYSTEM|2, "%s: cannot allocate service pipe", cs->name);
+ return 0;
+ }
+ if (co->flags & CO_SHELL)
+ for (i = 0; i < elementsof(fds); i++)
+ if (fds[i] < 10 && (j = fcntl(fds[i], F_DUPFD, 10)) >= 0)
+ {
+ close(fds[i]);
+ fds[i] = j;
+ }
+ cs->fd = fds[1];
+ ops[0] = PROC_FD_DUP(fds[0], 0, PROC_FD_PARENT);
+ ops[1] = PROC_FD_CLOSE(fds[1], PROC_FD_CHILD);
+ ops[2] = PROC_FD_DUP(co->gsmfd, 1, 0);
+ ops[3] = 0;
+ if (!(proc = procopen(cs->path, cs->argv, NiL, ops, PROC_DAEMON|PROC_IGNORE)))
+ {
+ errormsg(state.lib, ERROR_LIBRARY|ERROR_SYSTEM|2, "%s: cannot connect to %s service", cs->path, cs->name);
+ close(fds[0]);
+ close(fds[1]);
+ return 0;
+ }
+ fcntl(cs->fd, F_SETFD, FD_CLOEXEC);
+ cs->pid = proc->pid;
+ procfree(proc);
+ sfprintf(sp, "id=%d info\n", cj->id);
+ n = sfstrtell(sp);
+ if (!(s = costash(sp)))
+ goto bad;
+ if (write(cs->fd, s, n) != n || sfpoll(&co->msgfp, 1, 5 * 1000) <= 0)
+ goto bad;
+ cj->pid = 0;
+ cj->status = 0;
+ cj->local = 0;
+ cj->service = cs;
+ co->svc_outstanding++;
+ co->svc_running++;
+ if (!cowait(co, cj, -1))
+ goto bad;
+ return cj;
+ bad:
+ errormsg(state.lib, ERROR_LIBRARY|ERROR_SYSTEM|2, "%s: service not responding", cs->name);
+ nospace:
+ cj->pid = CO_PID_FREE;
+ cs->pid = 0;
+ close(cs->fd);
+ cs->fd = -1;
+ return 0;
+}
+
+static Cojob_t*
+request(register Coshell_t* co, Cojob_t* cj, Coservice_t* cs, const char* action, int flags)
+{
+ ssize_t n;
+ ssize_t i;
+ Sfio_t* sp;
+
+ if (!(sp = sfstropen()))
+ {
+ errormsg(state.lib, ERROR_LIBRARY|2, "out of space");
+ return 0;
+ }
+ if (!cs->fd && !service(co, cs, cj, flags, sp))
+ goto bad;
+ if (!cs->pid)
+ goto bad;
+ if (flags & CO_DEBUG)
+ errormsg(state.lib, ERROR_LIBRARY|2, "job %d commands:\n\n%s %s\n", cj->id, cs->name, action);
+ if (!(flags & CO_SILENT))
+ sfprintf(sfstderr, "+ %s %s\n", cs->name, action);
+ sfprintf(sp, "id=%d %s\n", cj->id, action);
+ n = sfstrtell(sp);
+ action = sfstrbase(sp);
+ while ((i = write(cs->fd, action, n)) > 0 && (n -= i) > 0)
+ action += i;
+ sfstrclose(sp);
+ if (n)
+ goto bad;
+ sfclose(sp);
+ cj->pid = 0;
+ cj->status = 0;
+ cj->local = 0;
+ cj->service = cs;
+ co->svc_outstanding++;
+ co->svc_running++;
+ co->total++;
+ return cj;
+ bad:
+ cj->pid = CO_PID_FREE;
+ sfclose(sp);
+ return 0;
+}
+
+Cojob_t*
+coexec(register Coshell_t* co, const char* action, int flags, const char* out, const char* err, const char* att)
+{
+ register Cojob_t* cj;
+ register Sfio_t* sp;
+ register Coservice_t* cs;
+ int n;
+ int i;
+ int og;
+ int cg;
+ char* s;
+ char* t;
+ char* env;
+ char* red;
+ char* sh[4];
+ struct stat sto;
+ struct stat ste;
+
+ /*
+ * get a free job slot
+ */
+
+ for (cj = co->jobs; cj; cj = cj->next)
+ if (cj->pid == CO_PID_FREE)
+ break;
+ if (cj)
+ cj->service = 0;
+ else if (!(cj = vmnewof(co->vm, 0, Cojob_t, 1, 0)))
+ return 0;
+ else
+ {
+ cj->coshell = co;
+ cj->pid = CO_PID_FREE;
+ cj->id = ++co->slots;
+ cj->next = co->jobs;
+ co->jobs = cj;
+ }
+
+ /*
+ * set the flags
+ */
+
+ flags &= ~co->mask;
+ flags |= co->flags;
+ cj->flags = flags;
+
+ /*
+ * check service intercepts
+ */
+
+ for (cs = co->service; cs; cs = cs->next)
+ {
+ for (s = cs->name, t = (char*)action; *s && *s == *t; s++, t++);
+ if (!*s && *t == ' ')
+ return request(co, cj, cs, t + 1, flags);
+ }
+ cj->flags &= ~CO_SERVICE;
+ red = (cj->flags & CO_APPEND) ? ">>" : ">";
+
+ /*
+ * package the action
+ */
+
+ if (!(env = coinitialize(co, co->flags)))
+ return 0;
+ if (!(sp = sfstropen()))
+ return 0;
+ n = strlen(action);
+ if (co->flags & CO_SERVER)
+ {
+ /*
+ * leave it to server
+ */
+
+ sfprintf(sp, "#%05d\ne %d %d %s %s %s",
+ 0,
+ cj->id,
+ cj->flags,
+ state.pwd,
+ out,
+ err);
+ if (att)
+ sfprintf(sp, " (%d:%s)", strlen(att), att);
+ else
+ sfprintf(sp, " %s", att);
+ sfprintf(sp, " (%d:%s) (%d:%s)\n", strlen(env), env, n, action);
+ }
+ else if (co->flags & CO_INIT)
+ {
+ if (flags & CO_DEBUG)
+ sfprintf(sp, "set -x\n");
+ sfprintf(sp, "%s%s\necho x %d $? >&$%s\n",
+ env,
+ action,
+ cj->id,
+ CO_ENV_MSGFD);
+ }
+ else if (flags & CO_KSH)
+ {
+#if !_lib_fork && defined(_map_spawnve)
+ Sfio_t* tp;
+
+ tp = sp;
+ if (!(sp = sfstropen()))
+ sp = tp;
+#endif
+ sfprintf(sp, "{\ntrap 'set %s$?; trap \"\" 0; IFS=\"\n\"; print -u$%s x %d $1 $(times); exit $1' 0 HUP INT QUIT TERM%s\n%s%s%s",
+ (flags & CO_SILENT) ? "" : "+x ",
+ CO_ENV_MSGFD,
+ cj->id,
+ (flags & CO_IGNORE) ? "" : " ERR",
+ env,
+ n > CO_MAXEVAL ? "" : "eval '",
+ (flags & CO_SILENT) ? "" : "set -x\n");
+ if (n > CO_MAXEVAL)
+ sfputr(sp, action, -1);
+ else
+ {
+ coquote(sp, action, 0);
+ sfprintf(sp, "\n'");
+ }
+ sfprintf(sp, "\n} </dev/null");
+ if (out)
+ {
+ if (*out == '/')
+ sfprintf(sp, " %s%s", red, out);
+ else
+ sfprintf(sp, " %s%s/%s", red, state.pwd, out);
+ }
+ else if ((flags & CO_SERIALIZE) && (cj->out = pathtemp(NiL, 64, NiL, "coo", NiL)))
+ sfprintf(sp, " >%s", cj->out);
+ if (err)
+ {
+ if (out && streq(out, err))
+ sfprintf(sp, " 2>&1");
+ else if (*err == '/')
+ sfprintf(sp, " 2%s%s", red, err);
+ else
+ sfprintf(sp, " 2%s%s/%s", red, state.pwd, err);
+ }
+ else if (flags & CO_SERIALIZE)
+ {
+ if (!out && !fstat(1, &sto) && !fstat(2, &ste) && sto.st_dev == ste.st_dev && sto.st_ino == ste.st_ino)
+ sfprintf(sp, " 2>&1");
+ else if (cj->err = pathtemp(NiL, 64, NiL, "coe", NiL))
+ sfprintf(sp, " 2>%s", cj->err);
+ }
+#if !_lib_fork && defined(_map_spawnve)
+ if (sp != tp)
+ {
+ sfprintf(tp, "%s -c '", state.sh);
+ if (!(s = costash(sp)))
+ return 0;
+ coquote(tp, s, 0);
+ sfprintf(tp, "'");
+ sfstrclose(sp);
+ sp = tp;
+ }
+#endif
+ sfprintf(sp, " &\nprint -u$%s j %d $!\n",
+ CO_ENV_MSGFD,
+ cj->id);
+ }
+ else
+ {
+#if !_lib_fork && defined(_map_spawnve)
+ Sfio_t* tp;
+
+ tp = sp;
+ if (!(sp = sfstropen())) sp = tp;
+#endif
+ flags |= CO_IGNORE;
+ if (co->mode & CO_MODE_SEPARATE)
+ {
+ flags &= ~CO_SERIALIZE;
+ og = '{';
+ cg = '}';
+ }
+ else
+ {
+ og = '(';
+ cg = ')';
+ }
+ sfprintf(sp, "%c\n%s%sset -%s%s\n",
+ og,
+ env,
+ n > CO_MAXEVAL ? "" : "eval '",
+ (flags & CO_IGNORE) ? "" : "e",
+ (flags & CO_SILENT) ? "" : "x");
+ if (n > CO_MAXEVAL)
+ sfprintf(sp, "%s", action);
+ else
+ {
+ coquote(sp, action, 0);
+ sfprintf(sp, "\n'");
+ }
+ sfprintf(sp, "\n%c </dev/null", cg);
+ if (out)
+ {
+ if (*out == '/')
+ sfprintf(sp, " %s%s", red, out);
+ else
+ sfprintf(sp, " %s%s/%s", red, state.pwd, out);
+ }
+ else if ((flags & CO_SERIALIZE) && (cj->out = pathtemp(NiL, 64, NiL, "coo", NiL)))
+ sfprintf(sp, " >%s", cj->out);
+ if (err)
+ {
+ if (out && streq(out, err))
+ sfprintf(sp, " 2>&1");
+ else if (*err == '/')
+ sfprintf(sp, " 2%s%s", red, err);
+ else
+ sfprintf(sp, " 2%s%s/%s", red, state.pwd, err);
+ }
+ else if (flags & CO_SERIALIZE)
+ {
+ if (out)
+ sfprintf(sp, " 2>&1");
+ else if (cj->err = pathtemp(NiL, 64, NiL, "coe", NiL))
+ sfprintf(sp, " 2>%s", cj->err);
+ }
+ if (!(co->mode & CO_MODE_SEPARATE))
+ {
+ if (flags & CO_OSH)
+ sfprintf(sp, " && echo x %d 0 >&$%s || echo x %d $? >&$%s",
+ cj->id,
+ CO_ENV_MSGFD,
+ cj->id,
+ CO_ENV_MSGFD);
+ else
+ sfprintf(sp, " && echo x %d 0 `times` >&$%s || echo x %d $? `times` >&$%s",
+ cj->id,
+ CO_ENV_MSGFD,
+ cj->id,
+ CO_ENV_MSGFD);
+ }
+#if !_lib_fork && defined(_map_spawnve)
+ if (sp != tp)
+ {
+ sfprintf(tp, "%s -c '", state.sh);
+ if (!(s = costash(sp)))
+ return 0;
+ coquote(tp, s, 0);
+ sfprintf(tp, "'");
+ sfstrclose(sp);
+ sp = tp;
+ }
+#endif
+ if (!(co->mode & CO_MODE_SEPARATE))
+ sfprintf(sp, " &\necho j %d $! >&$%s\n",
+ cj->id,
+ CO_ENV_MSGFD);
+ }
+ n = sfstrtell(sp);
+ if (!costash(sp))
+ return 0;
+ if (flags & CO_SERVER)
+ sfprintf(sp, "#%05d\n", n - 7);
+ s = sfstrseek(sp, 0, SEEK_SET);
+ if (flags & CO_DEBUG)
+ errormsg(state.lib, ERROR_LIBRARY|2, "job %d commands:\n\n%s\n", cj->id, s);
+ if (co->mode & CO_MODE_SEPARATE)
+ {
+ sh[0] = state.sh;
+ sh[1] = "-c";
+ sh[2] = s;
+ sh[3] = 0;
+ cj->status = procrun(state.sh, sh, 0);
+ sfstrclose(sp);
+ cj->pid = CO_PID_ZOMBIE;
+ cj->local = 0;
+ co->outstanding++;
+ co->total++;
+ }
+ else
+ {
+ /*
+ * send it off
+ */
+
+ while ((i = write(co->cmdfd, s, n)) > 0 && (n -= i) > 0)
+ s += i;
+ sfstrclose(sp);
+ if (n)
+ return 0;
+
+ /*
+ * it's a job
+ */
+
+ cj->pid = 0;
+ cj->status = 0;
+ cj->local = 0;
+ co->outstanding++;
+ co->running++;
+ co->total++;
+ if (co->mode & CO_MODE_ACK)
+ cj = cowait(co, cj, -1);
+ }
+ return cj;
+}
diff --git a/src/lib/libcoshell/coexport.c b/src/lib/libcoshell/coexport.c
new file mode 100644
index 0000000..4ba62a6
--- /dev/null
+++ b/src/lib/libcoshell/coexport.c
@@ -0,0 +1,80 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * at&t Research
+ *
+ * coshell export var set/unset
+ */
+
+#include "colib.h"
+
+/*
+ * set or unset coshell export variable
+ */
+
+int
+coexport(Coshell_t* co, const char* name, const char* value)
+{
+ Coexport_t* ex;
+ char* v;
+
+ if (!co->export)
+ {
+ if (!(co->exdisc = vmnewof(co->vm, 0, Dtdisc_t, 1, 0)))
+ return -1;
+ co->exdisc->link = offsetof(Coexport_t, link);
+ co->exdisc->key = offsetof(Coexport_t, name);
+ co->exdisc->size = 0;
+ if (!(co->export = dtnew(co->vm, co->exdisc, Dtset)))
+ {
+ vmfree(co->vm, co->exdisc);
+ return -1;
+ }
+ }
+ if (!(ex = (Coexport_t*)dtmatch(co->export, name)))
+ {
+ if (!value)
+ return 0;
+ if (!(ex = vmnewof(co->vm, 0, Coexport_t, 1, strlen(name))))
+ return -1;
+ strcpy(ex->name, name);
+ dtinsert(co->export, ex);
+ }
+ if (ex->value)
+ {
+ vmfree(co->vm, ex->value);
+ ex->value = 0;
+ }
+ if (value)
+ {
+ if (!(v = vmstrdup(co->vm, value)))
+ return -1;
+ ex->value = v;
+ }
+ else
+ {
+ dtdelete(co->export, ex);
+ vmfree(co->vm, ex);
+ }
+ co->init.sync = 1;
+ return 0;
+}
diff --git a/src/lib/libcoshell/coinit.c b/src/lib/libcoshell/coinit.c
new file mode 100644
index 0000000..d36fbde
--- /dev/null
+++ b/src/lib/libcoshell/coinit.c
@@ -0,0 +1,431 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2012 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return job initialization commands
+ */
+
+#if _WIN32
+#undef _BLD_DLL
+#define _BLD_DLL 1
+#endif
+
+#include "colib.h"
+
+#include <ctype.h>
+#include <fs3d.h>
+#include <ls.h>
+
+static void
+exid(Sfio_t* sp, const char* pre, const char* name, const char* pos)
+{
+ int c;
+
+ sfputr(sp, pre, -1);
+ if ((c = *name++) && c != '=')
+ {
+ if (isdigit(c))
+ sfputc(sp, '_');
+ do
+ {
+ if (!isalnum(c))
+ c = '_';
+ sfputc(sp, c);
+ } while ((c = *name++) && c != '=');
+ }
+ else
+ sfputc(sp, '_');
+ sfputr(sp, pos, -1);
+}
+
+/*
+ * add n to the export list
+ * old!=0 formats in old style
+ * coex!=0 for CO_ENV_EXPORT
+ * if n prefixed by % then coquote conversion enabled
+ */
+
+static void
+putexport(Coshell_t* co, Sfio_t* sp, char* n, int old, int coex, int flags)
+{
+ int cvt;
+ char* v;
+ Coexport_t* ex;
+
+ if (cvt = *n == '%')
+ n++;
+
+ /*
+ * currently limited to valid identifer env var names
+ */
+
+ if (!co->export || !dtmatch(co->export, n))
+ {
+ if (old)
+ cvt = 0;
+ if ((v = getenv(n)) && *v || coex && ((flags & CO_EXPORT) || co->export && dtsize(co->export) > 0))
+ {
+ if (!old)
+ sfprintf(sp, "\\\n");
+ exid(sp, " ", n, "='");
+ if (coex && (flags & CO_EXPORT))
+ v = "(*)";
+ if (v)
+ coquote(sp, v, cvt);
+ if (coex && !(flags & CO_EXPORT))
+ {
+ v = v ? ":" : "";
+ for (ex = (Coexport_t*)dtfirst(co->export); ex; ex = (Coexport_t*)dtnext(co->export, ex))
+ {
+ sfprintf(sp, "%s%s", v, ex->name);
+ exid(sp, v, ex->name, "");
+ v = ":";
+ }
+ }
+ sfputc(sp, '\'');
+ if (old)
+ exid(sp, "\nexport ", n, "\n");
+ }
+ }
+}
+
+/*
+ * return job initialization commands
+ */
+
+char*
+coinitialize(Coshell_t* co, int flags)
+{
+ register char* s;
+ int n;
+ int m;
+ int old;
+ int sync;
+ char* t;
+ long p;
+ Coexport_t* ex;
+ Sfio_t* sp;
+ Sfio_t* tp;
+ struct stat st;
+
+ sync = co->init.sync;
+ co->init.sync = 0;
+
+ /*
+ * pwd
+ */
+
+ if (stat(".", &st))
+ return 0;
+ if (!state.pwd || st.st_ino != co->init.pwd_ino || st.st_dev != co->init.pwd_dev)
+ {
+ co->init.pwd_dev = st.st_dev;
+ co->init.pwd_ino = st.st_ino;
+ if (state.pwd)
+ free(state.pwd);
+ if (!(state.pwd = getcwd(NiL, 0)))
+ {
+ if (errno != EINVAL || !(state.pwd = newof(0, char, PATH_MAX, 0)))
+ return 0;
+ if (!getcwd(state.pwd, PATH_MAX))
+ {
+ free(state.pwd);
+ state.pwd = 0;
+ return 0;
+ }
+ }
+ if (!(flags & CO_INIT))
+ sync = 1;
+ }
+
+ /*
+ * umask
+ */
+
+ umask(n = umask(co->init.mask));
+ if (co->init.mask != n)
+ {
+ co->init.mask = n;
+ if (!(flags & CO_INIT))
+ sync = 1;
+ }
+ if (!co->init.script || sync)
+ {
+ /*
+ * co_export[] vars
+ */
+
+ if (!(sp = sfstropen()))
+ return 0;
+ tp = 0;
+ old = !(flags & (CO_KSH|CO_SERVER));
+ if (!old)
+ sfprintf(sp, "export");
+ if (sync)
+ {
+ if (flags & CO_EXPORT)
+ s = "(*)";
+ else
+ {
+ for (n = 0; s = co_export[n]; n++)
+ putexport(co, sp, s, old, !n, flags);
+ s = getenv(co_export[0]);
+ }
+ if (s)
+ {
+ if (*s == '(')
+ {
+ register char** ep = environ;
+ register char* e;
+ char* v;
+ char* es;
+ char* xs;
+
+ if (v = strchr(s, ':'))
+ *v = 0;
+ while (e = *ep++)
+ if ((t = strsubmatch(e, s, 1)) && (*t == '=' || !*t && (t = strchr(e, '='))))
+ {
+ m = (int)(t - e);
+ if (!strneq(e, "PATH=", 5) && !strneq(e, "_=", 2))
+ {
+ for (n = 0; xs = co_export[n]; n++)
+ {
+ es = e;
+ while (*xs && *es == *xs)
+ {
+ es++;
+ xs++;
+ }
+ if (*es == '=' && !*xs)
+ break;
+ }
+ if (!xs)
+ {
+ if (!old)
+ sfprintf(sp, "\\\n");
+ exid(sp, " ", e, "='");
+ coquote(sp, e + m + 1, 0);
+ sfputc(sp, '\'');
+ if (old)
+ exid(sp, "\nexport ", e, "\n");
+ }
+ }
+ }
+ if (v)
+ {
+ *v++ = ':';
+ s = v;
+ }
+ }
+ if (*s)
+ for (;;)
+ {
+ if (t = strchr(s, ':'))
+ *t = 0;
+ putexport(co, sp, s, old, 0, 0);
+ if (!(s = t))
+ break;
+ *s++ = ':';
+ }
+ }
+ if (co->export)
+ for (ex = (Coexport_t*)dtfirst(co->export); ex; ex = (Coexport_t*)dtnext(co->export, ex))
+ {
+ if (!old)
+ sfprintf(sp, "\\\n");
+ exid(sp, " ", ex->name, "='");
+ coquote(sp, ex->value, 0);
+ sfputc(sp, '\'');
+ if (old)
+ exid(sp, "\nexport ", ex->name, "\n");
+ }
+ }
+
+ /*
+ * PATH
+ */
+
+ if (!old)
+ sfprintf(sp, "\\\n");
+ sfprintf(sp, " PATH='");
+ n = PATH_MAX;
+ if (!(t = sfstrrsrv(sp, n)))
+ {
+ bad:
+ sfstrclose(sp);
+ if (tp)
+ sfstrclose(tp);
+ return 0;
+ }
+ t += n / 2;
+ if (!(flags & CO_CROSS) && !pathpath("ignore", NiL, PATH_ABSOLUTE|PATH_REGULAR|PATH_EXECUTE, t, n / 2) && pathpath("bin/ignore", "", PATH_ABSOLUTE|PATH_REGULAR|PATH_EXECUTE, t, n / 2))
+ {
+ *strrchr(t, '/') = 0;
+ sfputc(sp, ':');
+ coquote(sp, t, !old);
+ sfputc(sp, ':');
+ s = pathbin();
+ }
+ else
+ {
+ s = pathbin();
+ if (!(flags & CO_CROSS))
+ {
+ if (!sync && (*s == ':' || *s == '.' && *(s + 1) == ':'))
+ {
+ sfstrseek(sp, 0, SEEK_SET);
+ goto done;
+ }
+ sfputc(sp, ':');
+ }
+ }
+ for (;;)
+ {
+ if (*s == ':')
+ s++;
+ else if (*s == '.' && *(s + 1) == ':')
+ s += 2;
+ else
+ break;
+ }
+ if (!(flags & CO_CROSS))
+ tp = 0;
+ else if (!(tp = sfstropen()))
+ goto bad;
+ else
+ {
+ while (n = *s++)
+ {
+ if (n == ':')
+ {
+ while (*s == ':')
+ s++;
+ if (!*s)
+ break;
+ if (*s == '.')
+ {
+ if (!*(s + 1))
+ break;
+ if (*(s + 1) == ':')
+ {
+ s++;
+ continue;
+ }
+ }
+ }
+ sfputc(tp, n);
+ }
+ if (!(s = costash(tp)))
+ goto bad;
+ }
+ coquote(sp, s, !old);
+ if (tp)
+ sfstrclose(tp);
+ sfputc(sp, '\'');
+ if (old)
+ sfprintf(sp, "\nexport PATH");
+ sfputc(sp, '\n');
+ if (sync)
+ {
+ /*
+ * VPATH
+ */
+
+ p = (int)sfstrtell(sp);
+ sfprintf(sp, "vpath ");
+ n = PATH_MAX;
+ if (fs3d(FS3D_TEST))
+ for (;;)
+ {
+ if (!(t = sfstrrsrv(sp, n)))
+ goto bad;
+ if ((m = mount(NiL, t, FS3D_GET|FS3D_ALL|FS3D_SIZE(n), NiL)) > 0)
+ m = n;
+ else
+ {
+ if (!m)
+ sfstrseek(sp, strlen(t), SEEK_CUR);
+ break;
+ }
+ }
+ else
+ {
+ m = 0;
+ sfprintf(sp, "- /#option/2d");
+ }
+ if (m)
+ sfstrseek(sp, p, SEEK_SET);
+ else
+ sfprintf(sp, " 2>/dev/null || :\n");
+ sfprintf(sp, "umask 0%o\ncd '%s'\n", co->init.mask, state.pwd);
+ }
+ done:
+ if (!(flags & CO_SERVER))
+ {
+ sfprintf(sp, "%s%s=%05d${!%s-$$}\n", old ? "" : "export ", CO_ENV_TEMP, getpid(), (flags & CO_OSH) ? "" : ":");
+ if (old)
+ sfprintf(sp, "export %s\n", CO_ENV_TEMP);
+ }
+ sfputc(sp, 0);
+ n = (int)sfstrtell(sp);
+ if (co->vm)
+ {
+ if (co->init.script)
+ vmfree(co->vm, co->init.script);
+ if (!(co->init.script = vmnewof(co->vm, 0, char, n, 1)))
+ goto bad;
+ }
+ else
+ {
+ if (co->init.script)
+ free(co->init.script);
+ if (!(co->init.script = newof(0, char, n, 1)))
+ goto bad;
+ }
+ memcpy(co->init.script, sfstrbase(sp), n);
+ sfstrclose(sp);
+ }
+ else if (!co->init.script)
+ {
+ if (co->init.script = co->vm ? vmnewof(co->vm, 0, char, 1, 0) : newof(0, char, 1, 0))
+ *co->init.script = 0;
+ }
+ return co->init.script;
+}
+
+/*
+ * return generic job initialization commands
+ */
+
+char*
+coinit(int flags)
+{
+ if (!state.generic)
+ {
+ if (!(state.generic = newof(0, Coshell_t, 1, 0)))
+ return 0;
+ state.generic->init.sync = 1;
+ }
+ return coinitialize(state.generic, flags);
+}
diff --git a/src/lib/libcoshell/cokill.c b/src/lib/libcoshell/cokill.c
new file mode 100644
index 0000000..b0c4fd4
--- /dev/null
+++ b/src/lib/libcoshell/cokill.c
@@ -0,0 +1,134 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * if co==0 then kill all coshell jobs with sig
+ * elif cj==0 then kill co jobs with sig
+ * else kill cj with sig
+ *
+ * if sig==0 then cause all CO_SERVICE jobs to fail
+ */
+
+#include "colib.h"
+
+/*
+ * kill job cj in shell co with signal sig
+ */
+
+static int
+cokilljob(register Coshell_t* co, register Cojob_t* cj, int sig)
+{
+ int n;
+
+ if (co->flags & CO_DEBUG)
+ errormsg(state.lib, 2, "coshell %d kill co=%d cj=%d sig=%d", co->index, co->pid, cj->pid, sig);
+ if (cj->pid < 0)
+ return 0;
+ if (cj->pid == 0)
+ {
+ if (cj->service)
+ co->svc_running--;
+ else
+ co->running--;
+ cj->pid = CO_PID_ZOMBIE;
+ cj->status = EXIT_TERM(sig);
+ return 0;
+ }
+ if (sig == SIGKILL)
+ {
+ co->running--;
+ cj->pid = CO_PID_ZOMBIE;
+ cj->status = EXIT_TERM(sig);
+ }
+ n = kill(cj->pid, sig);
+ killpg(cj->pid, sig);
+ return n;
+}
+
+/*
+ * kill cj (or all jobs if cj==0) in shell co with sig
+ */
+
+static int
+cokillshell(register Coshell_t* co, register Cojob_t* cj, int sig)
+{
+ int n;
+
+ if (sig && (co->flags & CO_SERVER))
+ {
+ char buf[CO_BUFSIZ];
+
+ n = sfsprintf(buf, sizeof(buf), "#%05d\nk %d %d\n", 0, cj ? cj->id : 0, sig);
+ sfsprintf(buf, 7, "#%05d\n", n - 7);
+ return write(co->cmdfd, buf, n) == n ? 0 : -1;
+ }
+ if (cj)
+ return cokilljob(co, cj, sig);
+ n = 0;
+ for (cj = co->jobs; cj; cj = cj->next)
+ if (cj->pid > 0)
+ n |= cokilljob(co, cj, sig);
+ return n;
+}
+
+int
+cokill(register Coshell_t* co, register Cojob_t* cj, int sig)
+{
+ int any;
+ int n;
+
+ if (cj)
+ {
+ if (!co)
+ co = cj->coshell;
+ else if (co != cj->coshell)
+ return -1;
+ any = 0;
+ }
+ else if (co)
+ any = 0;
+ else if (!(co = state.coshells))
+ return -1;
+ else
+ any = 1;
+ if (co->flags & CO_DEBUG)
+ errormsg(state.lib, 2, "coshell %d kill co=%d cj=%d sig=%d", co->index, co ? co->pid : 0, cj ? cj->pid : 0, sig);
+ switch (sig)
+ {
+ case SIGINT:
+ sig = SIGTERM;
+ break;
+#if defined(SIGSTOP) && defined(SIGTSTP)
+ case SIGTSTP:
+ sig = SIGSTOP;
+ break;
+#endif
+ }
+ n = 0;
+ do
+ {
+ cowait(co, (Cojob_t*)co, 0);
+ n |= cokillshell(co, cj, sig);
+ } while (any && (co = co->next));
+ return n;
+}
diff --git a/src/lib/libcoshell/colib.h b/src/lib/libcoshell/colib.h
new file mode 100644
index 0000000..e4512b5
--- /dev/null
+++ b/src/lib/libcoshell/colib.h
@@ -0,0 +1,137 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * coshell library private definitions
+ */
+
+#ifndef _COLIB_H
+#define _COLIB_H
+
+#include <ast.h>
+#include <dt.h>
+#include <vmalloc.h>
+
+#define _CO_JOB_PRIVATE_ /* Cojob_t private additions */ \
+ Cojob_t* next; /* next in list */ \
+ Coservice_t* service; /* service */ \
+ int pid; /* pid */ \
+ char* out; /* serialized stdout file */ \
+ char* err; /* serialized stderr file */ \
+ /* end of private additions */
+
+#define _CO_SHELL_PRIVATE_ /* Coshell_t private additions */ \
+ Vmalloc_t* vm; /* Coshell_t vm */ \
+ Coshell_t* next; /* next in list */ \
+ Cojob_t* jobs; /* job list */ \
+ Coservice_t* service; /* service */ \
+ Dt_t* export; /* coexport() dictionary */ \
+ Dtdisc_t* exdisc; /* coexport() discipline */ \
+ struct Coinit_s /* initialization script state */ \
+ { \
+ char* script; /* initialization script */ \
+ dev_t pwd_dev; /* previous pwd dev */ \
+ ino_t pwd_ino; /* previous pwd inode number */ \
+ int mask; /* previous umask */ \
+ int sync; /* sync script */ \
+ } init; \
+ int cmdfd; /* command pipe fd */ \
+ int gsmfd; /* msgfp child write side */ \
+ int mask; /* CO_* flags to clear */ \
+ int mode; /* connection modes */ \
+ int svc_outstanding;/* outstanding service intercepts */ \
+ int svc_running; /* running service intercepts */ \
+ int pid; /* pid */ \
+ int index; /* coshell index */ \
+ int slots; /* number of job slots */ \
+ /* end of private additions */
+
+typedef struct Coexport_s
+{
+ Dtlink_t link;
+ char* value;
+ char name[1];
+} Coexport_t;
+
+struct Coservice_s;
+typedef struct Coservice_s Coservice_t;
+
+struct Coservice_s /* service info */
+{
+ Coservice_t* next; /* next in list */
+ char* name; /* instance name */
+ char* path; /* coexec() command path */
+ char* db; /* state/db path */
+ int fd; /* command pipe */
+ int pid; /* pid */
+ char* argv[16]; /* coexec() command argv[] */
+};
+
+#include <coshell.h>
+#include <error.h>
+#include <sig.h>
+#include <wait.h>
+
+#define state _coshell_info_ /* hide external symbol */
+
+#define CO_MODE_ACK (1<<0) /* wait for coexec() ack */
+#define CO_MODE_INDIRECT (1<<1) /* indirect CO_SERVER */
+#define CO_MODE_SEPARATE (1<<2) /* 1 shell+wait per action */
+
+#define CO_INIT (CO_USER>>1) /* initial command */
+
+#define CO_PID_FREE (-3) /* free job slot */
+#define CO_PID_WARPED (-2) /* exit before start message */
+#define CO_PID_ZOMBIE (-1) /* ready for wait */
+
+#define CO_BUFSIZ (PATH_MAX/2) /* temporary buffer size */
+#define CO_MAXEVAL (PATH_MAX*8) /* max eval'd action size */
+
+typedef struct Costate_s /* global coshell state */
+{
+ const char* lib; /* library id */
+ Coshell_t* coshells; /* list of all coshells */
+ Coshell_t* current; /* current coshell */
+ Coshell_t* generic; /* generic coshell for coinit() */
+ char* pwd; /* pwd */
+ char* sh; /* sh from first coopen() */
+ char* type; /* CO_ENV_TYPE value */
+ int init; /* 0 if first coopen() */
+ int index; /* last coshell index */
+} Costate_t;
+
+extern char coident[]; /* coshell ident script */
+extern char cobinit[]; /* bsh initialition script */
+extern char cokinit[]; /* ksh initialition script */
+extern char* co_export[]; /* default export var list */
+
+extern Costate_t state; /* global coshell info */
+
+#ifndef errno
+extern int errno;
+#endif
+
+extern char* costash(Sfio_t*);
+extern char* coinitialize(Coshell_t*, int);
+
+#endif
diff --git a/src/lib/libcoshell/coopen.c b/src/lib/libcoshell/coopen.c
new file mode 100644
index 0000000..07dcb87
--- /dev/null
+++ b/src/lib/libcoshell/coopen.c
@@ -0,0 +1,411 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * open a new coshell
+ */
+
+#include "colib.h"
+
+#include <namval.h>
+#include <proc.h>
+#include <sfdisc.h>
+#include <tok.h>
+
+static const Namval_t options[] =
+{
+ "cross", CO_CROSS,
+ "debug", CO_DEBUG,
+ "devfd", CO_DEVFD,
+ "ignore", CO_IGNORE,
+ "orphan", CO_ORPHAN,
+ "silent", CO_SILENT,
+ "separate", CO_SEPARATE,
+ "service", CO_SERVICE,
+ 0, 0
+};
+
+Costate_t state = { "libcoshell:coshell" };
+
+/*
+ * called when ident sequence hung
+ */
+
+static void
+hung(int sig)
+{
+ NoP(sig);
+ close(sffileno(state.current->msgfp));
+}
+
+/*
+ * close all open coshells
+ */
+
+static void
+clean(void)
+{
+ coclose(NiL);
+}
+
+#ifdef SIGCONT
+
+/*
+ * pass job control signals to the coshell and self
+ */
+
+static void
+stop(int sig)
+{
+ cokill(NiL, NiL, sig);
+ signal(sig, SIG_DFL);
+ sigunblock(sig);
+ kill(getpid(), sig);
+ cokill(NiL, NiL, SIGCONT);
+ signal(sig, stop);
+}
+
+#endif
+
+/*
+ * called by stropt() to set options
+ */
+
+static int
+setopt(void* handle, register const void* p, int n, const char* v)
+{
+ Coshell_t* co = (Coshell_t*)handle;
+ Coservice_t* cs;
+ char* s;
+ char** a;
+
+ NoP(v);
+ if (p)
+ {
+ if (n)
+ {
+ co->flags |= ((Namval_t*)p)->value;
+ if (((Namval_t*)p)->value == CO_SERVICE && v && (cs = vmnewof(co->vm, 0, Coservice_t, 1, 2 * strlen(v))))
+ {
+ a = cs->argv;
+ *a++ = s = cs->path = cs->name = (char*)(cs + 1);
+ while (*s = *v++)
+ if (*s++ == ':')
+ {
+ *(s - 1) = 0;
+ if (*v == '-')
+ {
+ v++;
+ if (*v == '-')
+ v++;
+ }
+ if (strneq(v, "command=", 8))
+ cs->path = s + 8;
+ else if (strneq(v, "state=", 6))
+ cs->db = s + 6;
+ else if (strneq(v, "db=", 3))
+ cs->db = s + 3;
+ else if (a < &cs->argv[elementsof(cs->argv)-2] && *v && *v != ':')
+ {
+ *a++ = s;
+ *s++ = '-';
+ *s++ = '-';
+ }
+ }
+ if (cs->db)
+ *a++ = cs->db;
+ *a = 0;
+ cs->next = co->service;
+ co->service = cs;
+ }
+ }
+ else
+ co->mask |= ((Namval_t*)p)->value;
+ }
+ return 0;
+}
+
+Coshell_t*
+coopen(const char* path, int flags, const char* attributes)
+{
+ register Coshell_t* co;
+ register char* s;
+ register int i;
+ char* t;
+ int n;
+ Proc_t* proc;
+ Cojob_t* cj;
+ Vmalloc_t* vm;
+ Sfio_t* sp;
+ Sig_handler_t handler;
+ int pio[4];
+ long ops[5];
+ char devfd[16];
+ char evbuf[sizeof(CO_ENV_MSGFD) + 8];
+ char* av[8];
+ char* ev[2];
+
+ static char* sh[] = { 0, 0, "ksh", "sh", "/bin/sh" };
+
+ if (!state.type && (!(s = getenv(CO_ENV_TYPE)) || !(state.type = strdup(s))))
+ state.type = "";
+ if ((flags & CO_ANY) && (co = state.coshells))
+ return co;
+ if (!(vm = vmopen(Vmdcheap, Vmbest, 0)) || !(co = vmnewof(vm, 0, Coshell_t, 1, 0)))
+ {
+ if (vm)
+ vmclose(vm);
+ errormsg(state.lib, ERROR_LIBRARY|2, "out of space");
+ return 0;
+ }
+ co->vm = vm;
+ co->index = ++state.index;
+ stropt(getenv(CO_ENV_OPTIONS), options, sizeof(*options), setopt, co);
+ if (attributes)
+ stropt(attributes, options, sizeof(*options), setopt, co);
+ co->flags |= ((flags | CO_DEVFD) & ~co->mask);
+ if (co->flags & CO_SEPARATE)
+ {
+ co->flags &= ~CO_SEPARATE;
+ co->mode |= CO_MODE_SEPARATE;
+ }
+ co->flags |= CO_INIT;
+ if (co->mode & CO_MODE_SEPARATE)
+ {
+ flags = 0;
+ proc = 0;
+ }
+ else
+ {
+ for (i = 0; i < elementsof(pio); i++)
+ pio[i] = -1;
+ if (pipe(&pio[0]) < 0 || pipe(&pio[2]) < 0)
+ {
+ errormsg(state.lib, ERROR_LIBRARY|ERROR_SYSTEM|2, "cannot allocate pipes");
+ goto bad;
+ }
+ if (flags & CO_SHELL)
+ for (i = 0; i < elementsof(pio); i++)
+ if (pio[i] < 10 && (n = fcntl(pio[i], F_DUPFD, 10)) >= 0)
+ {
+ close(pio[i]);
+ pio[i] = n;
+ }
+ co->cmdfd = pio[1];
+ co->gsmfd = pio[3];
+ if (!(co->msgfp = sfnew(NiL, NiL, 256, pio[2], SF_READ)))
+ {
+ errormsg(state.lib, ERROR_LIBRARY|ERROR_SYSTEM|2, "cannot allocate message stream");
+ goto bad;
+ }
+ sfdcslow(co->msgfp);
+ ops[0] = PROC_FD_DUP(pio[0], 0, PROC_FD_PARENT);
+ ops[1] = PROC_FD_CLOSE(pio[1], PROC_FD_CHILD);
+ ops[2] = PROC_FD_CLOSE(pio[2], PROC_FD_CHILD);
+ ops[3] = PROC_FD_CLOSE(pio[3], PROC_FD_PARENT);
+ ops[4] = 0;
+ sfsprintf(devfd, sizeof(devfd), "/dev/fd/%d", pio[0]);
+ flags = !access(devfd, F_OK);
+ }
+ sh[0] = (char*)path;
+ sh[1] = getenv(CO_ENV_SHELL);
+ for (i = 0; i < elementsof(sh); i++)
+ if ((s = sh[i]) && *s && (s = strdup(s)))
+ {
+ if ((n = tokscan(s, NiL, " %v ", av, elementsof(av) - 1)) > 0)
+ {
+ if (t = strrchr(s = av[0], '/'))
+ av[0] = t + 1;
+ if (flags || (co->flags & CO_DEVFD) && strmatch(s, "*ksh*"))
+ av[n++] = devfd;
+ av[n] = 0;
+ sfsprintf(evbuf, sizeof(evbuf), "%s=%d", CO_ENV_MSGFD, co->gsmfd);
+ ev[0] = evbuf;
+ ev[1] = 0;
+ if ((co->mode & CO_MODE_SEPARATE) || (proc = procopen(s, av, ev, ops, (co->flags & (CO_SHELL|CO_ORPHAN)) ? (PROC_ORPHAN|PROC_DAEMON|PROC_IGNORE) : (PROC_DAEMON|PROC_IGNORE))))
+ {
+ if (!state.sh)
+ state.sh = strdup(s);
+ free(s);
+ if (proc)
+ {
+ co->pid = proc->pid;
+ procfree(proc);
+ }
+ break;
+ }
+ }
+ free(s);
+ }
+ if (i >= elementsof(sh))
+ {
+ errormsg(state.lib, ERROR_LIBRARY|ERROR_SYSTEM|2, "cannot execute");
+ goto bad;
+ }
+ if (!(co->mode & CO_MODE_SEPARATE))
+ {
+ /*
+ * send the shell identification sequence
+ */
+
+ if (!(sp = sfstropen()))
+ {
+ errormsg(state.lib, ERROR_LIBRARY|2, "out of buffer space");
+ goto bad;
+ }
+ sfprintf(sp, "#%05d\n%s='", 0, CO_ENV_ATTRIBUTES);
+ if (t = getenv(CO_ENV_ATTRIBUTES))
+ {
+ coquote(sp, t, 0);
+ if (attributes)
+ sfprintf(sp, ",");
+ }
+ if (attributes)
+ coquote(sp, attributes, 0);
+ sfprintf(sp, "'\n");
+ sfprintf(sp, coident, CO_ENV_MSGFD, pio[3], CO_ENV_MSGFD, CO_ENV_MSGFD, CO_ENV_MSGFD);
+ i = sfstrtell(sp);
+ sfstrseek(sp, 0, SEEK_SET);
+ sfprintf(sp, "#%05d\n", i - 7);
+ i = write(co->cmdfd, sfstrbase(sp), i) != i;
+ sfstrclose(sp);
+ if (i)
+ {
+ errormsg(state.lib, ERROR_LIBRARY|ERROR_SYSTEM|2, "cannot write initialization message");
+ goto nope;
+ }
+ state.current = co;
+ handler = signal(SIGALRM, hung);
+ i = alarm(30);
+ if (!(s = sfgetr(co->msgfp, '\n', 1)))
+ {
+ if (errno == EINTR)
+ errormsg(state.lib, ERROR_LIBRARY|ERROR_SYSTEM|2, "identification message read timeout");
+ goto nope;
+ }
+ alarm(i);
+ signal(SIGALRM, handler);
+ if (co->flags & CO_DEBUG)
+ errormsg(state.lib, 2, "coshell %d shell path %s identification \"%s\"", co->index, state.sh, s);
+ switch (*s)
+ {
+ case 'o':
+ co->flags |= CO_OSH;
+ /*FALLTHROUGH*/
+ case 'b':
+ s = cobinit;
+ break;
+ case 'k':
+ co->flags |= CO_KSH;
+ s = cokinit;
+ break;
+ case 'i': /* NOTE: 'i' is obsolete */
+ case 's':
+ co->flags |= CO_SERVER;
+ co->pid = 0;
+ for (;;)
+ {
+ if (t = strchr(s, ','))
+ *t = 0;
+ if (streq(s, CO_OPT_ACK))
+ co->mode |= CO_MODE_ACK;
+ else if (streq(s, CO_OPT_INDIRECT))
+ co->mode |= CO_MODE_INDIRECT;
+ if (!(s = t))
+ break;
+ s++;
+ }
+ if (!(co->mode & CO_MODE_INDIRECT))
+ wait(NiL);
+ break;
+ default:
+ goto nope;
+ }
+ if (s)
+ {
+ if (!(cj = coexec(co, s, 0, NiL, NiL, NiL)) || cowait(co, cj, -1) != cj)
+ {
+ errormsg(state.lib, ERROR_LIBRARY|ERROR_SYSTEM|2, "initialization message exec error");
+ goto nope;
+ }
+ co->total = 0;
+ co->user = 0;
+ co->sys = 0;
+ }
+ }
+ co->flags &= ~CO_INIT;
+ fcntl(pio[1], F_SETFD, FD_CLOEXEC);
+ fcntl(pio[2], F_SETFD, FD_CLOEXEC);
+ co->next = state.coshells;
+ state.coshells = co;
+ if (!(co->flags & CO_SHELL))
+ {
+#ifdef SIGCONT
+#ifdef SIGTSTP
+ signal(SIGTSTP, stop);
+#endif
+#ifdef SIGTTIN
+ signal(SIGTTIN, stop);
+#endif
+#ifdef SIGTTOU
+ signal(SIGTTOU, stop);
+#endif
+#endif
+ if (!state.init)
+ {
+ state.init = 1;
+ atexit(clean);
+ }
+ }
+ return co;
+ bad:
+ n = errno;
+ if (co->msgfp)
+ {
+ sfclose(co->msgfp);
+ pio[2] = -1;
+ }
+ for (i = 0; i < elementsof(pio); i++)
+ if (pio[i] >= 0)
+ close(pio[i]);
+ coclose(co);
+ errno = n;
+ return 0;
+ nope:
+ i = errno;
+ if (!(s = sh[1]) || (s = (t = strrchr(s, '/')) ? (t + 1) : s) && !strmatch(s, "?(k)sh") && !streq(s, CO_ID))
+ error(2, "export %s={ksh,sh,%s}", CO_ENV_SHELL, CO_ID);
+ coclose(co);
+ errno = i;
+ return 0;
+}
+
+/*
+ * set coshell attributes
+ */
+
+int
+coattr(Coshell_t* co, const char* attributes)
+{
+ return 0;
+}
diff --git a/src/lib/libcoshell/coquote.c b/src/lib/libcoshell/coquote.c
new file mode 100644
index 0000000..1c1edf2
--- /dev/null
+++ b/src/lib/libcoshell/coquote.c
@@ -0,0 +1,60 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * single quote s into sp
+ * if type!=0 then /<getenv(<CO_ENV_TYPE>)/ translated to /$<CO_ENV_TYPE>/
+ */
+
+#include "colib.h"
+
+void
+coquote(register Sfio_t* sp, register const char* s, int type)
+{
+ register int c;
+
+ if (type && (!state.type || !*state.type))
+ type = 0;
+ while (c = *s++)
+ {
+ sfputc(sp, c);
+ if (c == '\'')
+ {
+ sfputc(sp, '\\');
+ sfputc(sp, '\'');
+ sfputc(sp, '\'');
+ }
+ else if (type && c == '/' && *s == *state.type)
+ {
+ register const char* x = s;
+ register char* t = state.type;
+
+ while (*t && *t++ == *x) x++;
+ if (!*t && *x == '/')
+ {
+ s = x;
+ sfprintf(sp, "'$%s'", CO_ENV_TYPE);
+ }
+ }
+ }
+}
diff --git a/src/lib/libcoshell/coshell.3 b/src/lib/libcoshell/coshell.3
new file mode 100644
index 0000000..b0a1201
--- /dev/null
+++ b/src/lib/libcoshell/coshell.3
@@ -0,0 +1,396 @@
+.fp 5 CW
+.de L \" literal font
+.ft 5
+.if !\\$1 \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \f1
+..
+.de LR
+.}S 5 1 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+.de RL
+.}S 1 5 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH COSHELL 3
+.SH NAME \" @(#)coshell.3 (gsf@research.att.com) 10/11/90
+coshell \- shell coprocess support
+.SH SYNOPSIS
+.L "#include <coshell.h>"
+.br
+.L "\-lcoshell \-last"
+.SH DESCRIPTION
+The
+.I coshell
+routines support the shell as a coprocess.
+This coprocess may be either
+.IR ksh (1)
+or
+.IR sh (1)
+executing on the local host, or it may be
+.IR coshell (1)
+with access to shells on hosts throughout the local network.
+.PP
+The coshell inherits the environment of the calling process.
+Signals sent to the calling process are passed to the coshell.
+.PP
+More than one coshell may be open in the current process.
+If the
+.L Coshell_t*
+argument to the
+.LR cowait() ,
+.LR cokill() ,
+.LR copending() ,
+.LR cozombie() ,
+or
+.L coclose()
+calls below is
+.L 0
+then the call is applied to all open coshell.
+.PP
+.L "Coshell_t* coopen(const char* shell, int flags, const char* attributes)"
+.PP
+Returns a pointer to a new coshell.
+.L NULL
+is returned on error.
+If
+.L shell
+is
+.L NULL
+then the coshell executable is determined by doing the usual path search,
+in order, on the value of the environment variable
+.B COSHELL
+and the commands
+.BR ksh
+and
+.BR sh .
+.L flags
+is the inclusive-or of the following:
+.TP
+.L CO_ANY
+Return a pointer to a previously opened coshell if possible, otherwise
+open a new coshell.
+.TP
+.L CO_DEBUG
+Enable library debug tracing.
+.TP
+.L CO_IGNORE
+Ignore any command errors.
+By default any command error that is not tested by a condtional causes
+the job to terminate.
+.TP
+.L CO_LOCAL
+Commands are to be executed on the local host only.
+.TP
+.L CO_SHELL
+The caller is
+.BR sh (1):
+internal file descriptors are moved to 10 or above;
+SIGSTOP and SIGCONT handlers are not installed.
+.TP
+.L CO_SILENT
+Don't trace commands.
+By default commands are traced using the shell
+.B \-x
+option.
+.TP
+.L CO_NONBLOCK
+Normally
+.L coexec()
+blocks when the job queue is full and waits until a job completes.
+.L CO_NONBLOCK
+causes
+.L coexec()
+to return
+.L NULL
+when the job queue is full.
+.PP
+.L attributes
+is a string that is interpreted by the coshell.
+If
+.L attributes
+is
+.L NULL
+then the value of the environment variable
+.B COATTRIBUTES
+is used if defined.
+.B ksh
+and
+.B sh
+ignore this string.
+The return value points to a structure with the following readonly elements:
+.TP
+.L "int flags"
+The default flags.
+.TP
+.L "int outstanding"
+The number of jobs that have not been waited for.
+.TP
+.L "int running"
+The number of jobs still running.
+.TP
+.L "int total"
+The total number of jobs sent to the coshell.
+.TP
+.L "unsigned long user"
+The total user time of all completed jobs in
+.L 1/CO_QUANT
+second increments.
+.TP
+.L "unsigned long sys"
+The total system time of all completed jobs in
+.L 1/CO_QUANT
+second increments.
+.PP
+.L "int coclose(Coshell_t* sh)"
+.PP
+Close an open coshell pointed to by
+.LR sh .
+The coshell exit status is returned.
+.PP
+.L "Cojob_t* coexec(Coshell_t* sh, const char* cmd, int flags, const char* out, const char* err, const char* att)"
+.PP
+Sends the shell command line
+.L cmd
+to the open coshell pointed to by
+.L sh
+for execution.
+.L flags
+are the same as in the
+.L coopen()
+call, and are used to augment the default settings from
+.LR coopen() .
+.L out
+is the standard output file name and defaults to
+.B stdout
+if
+.LR NULL .
+.L err
+is the standard error file name and defaults to
+.B stderr
+if
+.LR NULL .
+.LR att ,
+if
+.RL non- NULL ,
+contains job attributes that are appended to the attributes from
+.L coopen()
+before being sent to the coshell.
+The return value points to a structure with the following elements:
+.TP
+.L "int id"
+A number that uniquely identifies the job within the coshell.
+.TP
+.L "int status"
+The job exit status, valid only for job pointers returned by
+.LR cowait() .
+.TP
+.L "int flags"
+The flags enabled for this job.
+.TP
+.L "void* local"
+A user reserved pointer, initially set to
+.L NULL
+on return from
+.LR coexec() .
+This is the only job field that may be modified by the user.
+The user defined value is preserved until after the
+.L cowait()
+call that returns the job pointer.
+.TP
+.L "unsigned long user"
+The user time of this job in
+.L 1/CO_QUANT
+second increments, valid only for job pointers returned by
+.LR cowait() .
+.TP
+.L "unsigned long sys"
+The system time of this job in
+.L 1/CO_QUANT
+second increments, valid only for job pointers returned by
+.LR cowait() .
+.PP
+.L "Cojob_t* cowait(Coshell_t* sh, Cojob_t* job, int timeout)"
+.PP
+Returns the job pointer in the coshell pointed to by
+.L sh
+for the job pointed to by
+.LR job .
+If
+.L job
+is
+.L NULL
+then a pointer to any completed job is returned.
+.L cowait()
+blocks until the specified job(s) complete.
+.L NULL
+is returned on error or if all jobs have completed and
+.L errno
+is set to EINVAL for coshell communication errors,
+ECHILD if
+.L job
+is
+.L NULL
+and there are no children, and ESRCH if
+.L job
+is not
+.L NULL
+and not an active job.
+.L "cozombie(sh)"
+is the number of jobs that may be waited for without blocking.
+The return value
+.LR status ,
+.L user
+and
+.L sys
+job fields are set to their final values.
+The return value is valid until the next
+.LR coexec() ,
+.L cowait()
+or
+.L coclose()
+call.
+.L timeout
+is the maximum time in milliseconds that wait will block.
+If the wait times out then 0 is returned.
+A negative
+.L timeout
+waits until a job completes or a signal is received.
+.TP
+.L "int cojobs(Coshell_t* sh)"
+Returns the number of outstanding jobs that are children of the caller.
+(Remote jobs or jobs executed by a separate daemon are not counted here.)
+.TP
+.L "int copending(Coshell_t* sh)"
+Returns the number of pending jobs; this is the number of
+.L cowait()
+calls required to reap all running jobs.
+.TP
+.L "int cozombie(Coshell_t* sh)"
+Returns the number of jobs that have completed but have not been
+.L cowait()'d
+for.
+.TP
+.L "int cokill(Coshell_t* sh, Cojob_t* job, int sig)"
+The signal
+.L sig
+is sent to the job pointed to by
+.L job
+running in the coshell pointed to by
+.LR sh .
+If
+.L job
+is
+.L NULL
+then the signal is sent to all jobs in the coshell.
+If both
+.L sh
+and
+.L job
+are
+.L NULL
+then the signal is sent to all jobs in all coshells.
+.L \-1
+is returned on error,
+.L 0
+otherwise.
+.TP
+.L "int cosync(Coshell_t* sh, const char* path, int fd, int mode)"
+Sync all outstanding file operations for either the file
+.L path
+or the file descriptor
+.L fd
+after its shell action has completed in
+.LR sh .
+If
+.L path
+is
+.L NULL
+then
+.L fd
+is used.
+If
+.L fd<0
+and
+.L mode>=0
+then
+.L path
+is opened using
+.L mode.
+This is an unfortunate workaround for NFS and remote coshells, and is a
+no-op for all real file systems.
+It should be called after
+.L cowait()
+to ensure that all file system cache info has been flushed.
+.IR sync (2)
+or
+.IR fsync (2)
+must still be called to schedule file data to be written to disk.
+.TP
+.L "char* coinit(Coshell_t* sh)"
+Returns the shell initialization commands for the next job.
+These commands represent process state changes that may have occurred
+since the last call to
+.L coinit(),
+e.g., current working directory or umask.
+If
+.L sh
+is local (a child of the calling process)
+.L coinit()
+may return the empty string;
+if
+.L sh
+is remote then considerably more information may be returned.
+This routine is used by remote coshell implementations and is
+not normally called from user code.
+.TP
+.L "void coquote(Sfio_T* sp, const char* string, int type)"
+Applies shell single quoting to
+.L string
+and copies the result into the sfio stream
+.L sp.
+If
+.L type!=0
+then any occurence of \f5/\fP\fIhosttype\fP\f5/\fP is translated to
+\f5/$HOSTTYPE/\fP, where
+.I hosttype
+is the current value of the
+.L HOSTTYPE
+environment variable.
+This routine is used by remote coshell implementations and is
+not normally called from user code.
+.SH CAVEATS
+.L cosync()
+is a hack workaround, but we do have to work in the real world.
+.PP
+A bug in
+.IR bsh (1)
+and
+.IR ksh (1)
+implementations up to and including ksh88e causes some interrupted
+jobs to return 0 exit status.
+This should be fixed in later shell releases.
+.PP
+.L "trap 0"
+is reserved by
+.L coexec()
+at the outermost scope.
+To use
+.L "trap 0"
+use
+.L "(...)"
+to force a subshell.
+.SH "SEE ALSO"
+coshell(1), ksh(1), nmake(1), sh(1), cs(3), libast(3)
diff --git a/src/lib/libcoshell/coshell.h b/src/lib/libcoshell/coshell.h
new file mode 100644
index 0000000..9063f14
--- /dev/null
+++ b/src/lib/libcoshell/coshell.h
@@ -0,0 +1,143 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * coshell library interface
+ */
+
+#ifndef _COSHELL_H
+#define _COSHELL_H
+
+#include <ast.h>
+
+#if !_BLD_coshell
+
+#undef procrun
+#define procrun(a,b,c) coprocrun(a,b,c)
+#undef system
+#define system(a) cosystem(a)
+
+#endif
+
+struct Coshell_s; typedef struct Coshell_s Coshell_t;
+struct Cojob_s; typedef struct Cojob_s Cojob_t;
+
+/*
+ * DEPRECATED names for compatibility
+ */
+
+#define COSHELL Coshell_t
+#define COJOB Cojob_t
+
+#define CO_ID "coshell" /* library/command id */
+
+#define CO_ENV_ATTRIBUTES "COATTRIBUTES"/* coshell attributes env var */
+#define CO_ENV_EXPORT "COEXPORT" /* coshell env var export list */
+#define CO_ENV_HOST "HOSTNAME" /* coshell host name env var */
+#define CO_ENV_MSGFD "_COSHELL_msgfd"/* msg fd */
+#define CO_ENV_OPTIONS "COSHELL_OPTIONS"/* options environment var */
+#define CO_ENV_PROC "NPROC" /* concurrency environment var */
+#define CO_ENV_SHELL "COSHELL" /* coshell path environment var */
+#define CO_ENV_TEMP "COTEMP" /* 10 char temp file base */
+#define CO_ENV_TYPE "HOSTTYPE" /* coshell host type env var */
+
+#define CO_OPT_ACK "ack" /* wait for server coexec() ack */
+#define CO_OPT_INDIRECT "indirect" /* indirect server connection */
+#define CO_OPT_SERVER "server" /* server connection */
+
+#define CO_QUANT 100 /* time quanta per sec */
+
+#define CO_ANY 0x000001 /* return any open coshell */
+#define CO_DEBUG 0x000002 /* library debug trace */
+#define CO_EXPORT 0x000004 /* export everything */
+#define CO_IGNORE 0x000008 /* ignore command errors */
+#define CO_LOCAL 0x000010 /* local affinity */
+#define CO_NONBLOCK 0x000020 /* don't block coexec if Q full */
+#define CO_SHELL 0x000040 /* shell using coshell! */
+#define CO_SILENT 0x000080 /* don't trace commands */
+
+#define CO_KSH 0x000100 /* coshell is ksh (readonly) */
+#define CO_SERVER 0x000200 /* coshell is server (readonly) */
+#define CO_OSH 0x000400 /* coshell is OLD (readonly) */
+
+#define CO_CROSS 0x000800 /* don't prepend local dirs */
+#define CO_DEVFD 0x001000 /* coshell handles /dev/fd/# */
+
+#define CO_SERIALIZE 0x002000 /* serialize stdout and stderr */
+#define CO_SERVICE 0x004000 /* service callouts */
+
+#define CO_APPEND 0x008000 /* append coexec() out/err */
+#define CO_SEPARATE 0x010000 /* 1 shell+wait per coexec() */
+#define CO_ORPHAN 0x020000 /* PROC_ORPHAN */
+
+#define CO_USER 0x100000 /* first user flag */
+
+struct Cojob_s /* coshell job info */
+{
+ Coshell_t* coshell; /* running in this coshell */
+ int id; /* job id */
+ int status; /* exit status */
+ int flags; /* CO_* flags */
+ void* local; /* local info */
+ unsigned long user; /* user time in 1/CO_QUANT secs */
+ unsigned long sys; /* sys time in 1/CO_QUANT secs */
+#ifdef _CO_JOB_PRIVATE_
+ _CO_JOB_PRIVATE_ /* library private additions */
+#endif
+};
+
+struct Coshell_s /* coshell connection info */
+{
+ void* data; /* user data, initially 0 */
+ int flags; /* flags */
+ int outstanding; /* number of outstanding jobs */
+ int running; /* number of running jobs */
+ int total; /* number of coexec() jobs */
+ unsigned long user; /* user time in 1/CO_QUANT secs */
+ unsigned long sys; /* sys time in 1/CO_QUANT secs */
+ Sfio_t* msgfp; /* message stream for sfpoll() */
+#ifdef _CO_SHELL_PRIVATE_
+ _CO_SHELL_PRIVATE_ /* library private additions */
+#endif
+};
+
+extern int coclose(Coshell_t*);
+extern Cojob_t* coexec(Coshell_t*, const char*, int, const char*, const char*, const char*);
+extern char* coinit(int);
+extern int coexport(Coshell_t*, const char*, const char*);
+extern int cokill(Coshell_t*, Cojob_t*, int);
+extern Coshell_t* coopen(const char*, int, const char*);
+extern void coquote(Sfio_t*, const char*, int);
+extern int cosync(Coshell_t*, const char*, int, int);
+extern Cojob_t* cowait(Coshell_t*, Cojob_t*, int);
+
+extern int cojobs(Coshell_t*);
+extern int copending(Coshell_t*);
+extern int cozombie(Coshell_t*);
+
+extern int coattr(Coshell_t*, const char*);
+
+extern int coprocrun(const char*, char**, int);
+extern int cosystem(const char*);
+
+#endif
diff --git a/src/lib/libcoshell/costash.c b/src/lib/libcoshell/costash.c
new file mode 100644
index 0000000..c378909
--- /dev/null
+++ b/src/lib/libcoshell/costash.c
@@ -0,0 +1,40 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include <colib.h>
+
+/*
+ * 0 terminate string stream, reset, and return value
+ */
+
+char*
+costash(Sfio_t* sp)
+{
+ char* s;
+
+ if (!(s = sfstruse(sp)))
+ errormsg(state.lib, ERROR_LIBRARY|2, "out of space");
+ return s;
+}
diff --git a/src/lib/libcoshell/cosync.c b/src/lib/libcoshell/cosync.c
new file mode 100644
index 0000000..4439efa
--- /dev/null
+++ b/src/lib/libcoshell/cosync.c
@@ -0,0 +1,127 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * sync all outstanding file operations for file opened on fd
+ * if file==0 then fd used
+ * if fd<0 then file used
+ * if mode<0 then fd not created
+ *
+ * NOTE: this is an unfortunate NFS workaround that should be done by fsync()
+ */
+
+#include "colib.h"
+
+#include <ls.h>
+
+#include "FEATURE/nfsd"
+
+int
+cosync(Coshell_t* co, const char* file, int fd, int mode)
+{
+#if defined(_cmd_nfsd)
+ if (!co || (co->flags & CO_SERVER))
+ {
+ char tmp[PATH_MAX];
+
+ if (file && *file)
+ {
+ register const char* s;
+ register char* t;
+ register char* b;
+ int td;
+
+ /*
+ * writing to a dir apparently flushes the
+ * attribute cache for all entries in the dir
+ */
+
+ s = file;
+ b = t = tmp;
+ while (t < &tmp[sizeof(tmp) - 1])
+ {
+ if (!(*t = *s++)) break;
+ if (*t++ == '/') b = t;
+ }
+ s = "..nfs..botch..";
+ t = b;
+ while (t < &tmp[sizeof(tmp) - 1] && (*t++ = *s++));
+ *t = 0;
+ if ((td = open(tmp, O_WRONLY|O_CREAT|O_TRUNC, 0)) >= 0) close(td);
+ unlink(tmp);
+ if (fd >= 0 && mode >= 0)
+ {
+ if ((td = open(file, mode)) < 0) return(-1);
+ close(fd);
+ dup2(td, fd);
+ close(td);
+ }
+ }
+#if defined(F_SETLK)
+ else
+ {
+ int clean = 0;
+ struct flock lock;
+
+ if (fd < 0)
+ {
+ if (!file || mode < 0 || (fd = open(file, O_RDONLY)) < 0) return(-1);
+ clean = 1;
+ }
+
+ /*
+ * this sets the VNOCACHE flag across NFS
+ */
+
+ lock.l_type = F_RDLCK;
+ lock.l_whence = 0;
+ lock.l_start = 0;
+ lock.l_len = 1;
+ if (!fcntl(fd, F_SETLK, &lock))
+ {
+ lock.l_type = F_UNLCK;
+ fcntl(fd, F_SETLK, &lock);
+ }
+ if (clean) close(fd);
+
+ /*
+ * 4.1 has a bug that lets VNOCACHE linger after unlock
+ * VNOCACHE inhibits mapping which kills exec
+ * the double rename flushes the incore vnode (and VNOCACHE)
+ *
+ * this kind of stuff doesn't happen with *real* file systems
+ */
+
+ if (file && *file)
+ {
+ strcpy(tmp, file);
+ fd = strlen(tmp) - 1;
+ tmp[fd] = (tmp[fd] == '*') ? '?' : '*';
+ if (!rename(file, tmp)) rename(tmp, file);
+ }
+ }
+#endif
+ }
+#endif
+ return(0);
+}
diff --git a/src/lib/libcoshell/cowait.c b/src/lib/libcoshell/cowait.c
new file mode 100644
index 0000000..ccc98d3
--- /dev/null
+++ b/src/lib/libcoshell/cowait.c
@@ -0,0 +1,411 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * wait for and return status of job or the next coshell job that completes
+ * job==co for non-blocking wait
+ */
+
+#include "colib.h"
+
+#include <ctype.h>
+
+/*
+ * cat and remove fd {1,2} serialized output
+ */
+
+static void
+cat(Cojob_t* job, char** path, Sfio_t* op)
+{
+ Sfio_t* sp;
+
+ if (sp = sfopen(NiL, *path, "r"))
+ {
+ sfmove(sp, op, SF_UNBOUND, -1);
+ sfclose(sp);
+ }
+ else
+ errormsg(state.lib, ERROR_LIBRARY|2, "%s: cannot open job %d serialized output", *path, job->id);
+ remove(*path);
+ free(*path);
+ *path = 0;
+}
+
+/*
+ * the number of running+zombie jobs
+ * these would count against --jobs or NPROC
+ */
+
+int
+cojobs(Coshell_t* co)
+{
+ int any;
+ int n;
+
+ if (co)
+ any = 0;
+ else if (!(co = state.coshells))
+ return -1;
+ else
+ any = 1;
+ n = 0;
+ do
+ {
+ n += co->outstanding;
+ } while (any && (co = co->next));
+ return n;
+}
+
+/*
+ * the number of pending cowait()'s
+ */
+
+int
+copending(Coshell_t* co)
+{
+ int any;
+ int n;
+
+ if (co)
+ any = 0;
+ else if (!(co = state.coshells))
+ return -1;
+ else
+ any = 1;
+ n = 0;
+ do
+ {
+ n += co->outstanding + co->svc_outstanding;
+ } while (any && (co = co->next));
+ return n;
+}
+
+/*
+ * the number of completed jobs not cowait()'d for
+ * cowait() always reaps the zombies first
+ */
+
+int
+cozombie(Coshell_t* co)
+{
+ int any;
+ int n;
+
+ if (co)
+ any = 0;
+ else if (!(co = state.coshells))
+ return -1;
+ else
+ any = 1;
+ n = 0;
+ do
+ {
+ n += (co->outstanding + co->svc_outstanding) - (co->running + co->svc_running);
+ } while (any && (co = co->next));
+ return n;
+}
+
+Cojob_t*
+cowait(register Coshell_t* co, Cojob_t* job, int timeout)
+{
+ register char* s;
+ register Cojob_t* cj;
+ register Coservice_t* cs;
+ register ssize_t n;
+ char* b;
+ char* e;
+ unsigned long user;
+ unsigned long sys;
+ int active;
+ int any;
+ int id;
+ int loop;
+ int to;
+ int type;
+ char buf[128];
+
+ static unsigned long serial = 0;
+
+ serial++;
+ if (co || job && (co = job->coshell))
+ any = 0;
+ else if (!(co = state.coshells))
+ goto echild;
+ else
+ any = 1;
+
+ /*
+ * first drain the zombies
+ */
+
+ active = 0;
+ to = timeout >= 0 ? timeout : 60 * 1000;
+ zombies:
+ do
+ {
+#if 0
+ errormsg(state.lib, 2, "coshell %d zombie wait %lu timeout=%d outstanding=<%d,%d> running=<%d,%d>", co->index, serial, timeout, co->outstanding, co->svc_outstanding, co->running, co->svc_running);
+#endif
+ if ((co->outstanding + co->svc_outstanding) > (co->running + co->svc_running))
+ for (cj = co->jobs; cj; cj = cj->next)
+ if (cj->pid == CO_PID_ZOMBIE && (!job || cj == job))
+ {
+ cj->pid = CO_PID_FREE;
+ if (cj->service)
+ co->svc_outstanding--;
+ else
+ co->outstanding--;
+#if 0
+ errormsg(state.lib, 2, "coshell %d zombie wait %lu timeout=%d outstanding=<%d,%d> running=<%d,%d> reap job %d", co->index, serial, timeout, co->outstanding, co->svc_outstanding, co->running, co->svc_running, cj->id);
+#endif
+ return cj;
+ }
+ else if (cj->service && !cj->service->pid)
+ {
+ cj->pid = CO_PID_ZOMBIE;
+ cj->status = 2;
+ cj->service = 0;
+ co->svc_running--;
+ }
+ if (co->running > 0)
+ active = 1;
+ else if (co->svc_running > 0)
+ {
+ n = 0;
+ for (cs = co->service; cs; cs = cs->next)
+ if (cs->pid && kill(cs->pid, 0))
+ {
+ cs->pid = 0;
+ close(cs->fd);
+ cs->fd = -1;
+ n = 1;
+ }
+ if (n)
+ goto zombies;
+ active = 1;
+ }
+ } while (any && (co = co->next));
+
+ /*
+ * reap the active jobs
+ */
+
+ if (!active)
+ goto echild;
+ if (any)
+ co = state.coshells;
+ do
+ {
+ loop = 0;
+ for (;;)
+ {
+ if (co->flags & CO_DEBUG)
+ {
+ loop++;
+ errormsg(state.lib, 2, "coshell %d wait %lu.%d timeout=%d outstanding=<%d,%d> running=<%d,%d>", co->index, serial, loop, timeout, co->outstanding, co->svc_outstanding, co->running, co->svc_running);
+ for (cj = co->jobs; cj; cj = cj->next)
+ if (cj->pid != CO_PID_FREE)
+ errormsg(state.lib, 2, "\tjob %d pid=%d status=%d", cj->id, cj->pid, cj->status);
+ }
+ if (co->running <= 0)
+ break;
+ while ((n = sfpoll(&co->msgfp, 1, to)) < 1)
+ {
+ if (n < 0)
+ {
+ if (errno == EINTR)
+ return 0;
+ break;
+ }
+ if (timeout >= 0)
+ break;
+
+ /*
+ * check for a killed job with no status
+ */
+
+ for (cj = co->jobs; cj; cj = cj->next)
+ if (cj->pid > 0)
+ {
+ n = sfsprintf(buf, sizeof(buf), "kill -0 %d 2>/dev/null || echo k %d `wait %d 2>/dev/null; echo $?` >&$%s\n", cj->pid, cj->id, cj->pid, CO_ENV_MSGFD);
+ write(co->cmdfd, buf, n);
+ break;
+ }
+ }
+
+ /*
+ * get one coshell message
+ */
+
+ if (!(s = b = sfgetr(co->msgfp, '\n', 1)))
+ break;
+#if 0
+ errormsg(state.lib, 2, "coshell %d active wait %lu timeout=%d outstanding=<%d,%d> running=<%d,%d>", co->index, serial, timeout, co->outstanding, co->svc_outstanding, co->running, co->svc_running);
+#endif
+
+ /*
+ * read and parse a coshell message packet of the form
+ *
+ * <type> <id> <args> <newline>
+ * %c %d %s %c
+ */
+
+ while (isspace(*s))
+ s++;
+ if (!(type = *s) || type != 'a' && type != 'j' && type != 'k' && type != 'x')
+ goto invalid;
+ while (*++s && !isspace(*s));
+ id = strtol(s, &e, 10);
+ if (*e && !isspace(*e))
+ goto invalid;
+ for (s = e; isspace(*s); s++);
+
+ /*
+ * locate id in the job list
+ */
+
+ for (cj = co->jobs; cj; cj = cj->next)
+ if (id == cj->id)
+ break;
+ if ((co->flags | (cj ? cj->flags : 0)) & CO_DEBUG)
+ errormsg(state.lib, 2, "coshell %d message \"%c %d %s\"", co->index, type, id, s);
+ if (!cj)
+ {
+ if (type == 'k')
+ continue;
+ errormsg(state.lib, 2, "coshell %d job id %d not found [%s]", co->index, id, b);
+ errno = ESRCH;
+ return 0;
+ }
+
+ /*
+ * now interpret the message
+ */
+
+ switch (type)
+ {
+
+ case 'a':
+ /*
+ * coexec() ack
+ */
+
+ if (cj == job)
+ return cj;
+ break;
+
+ case 'j':
+ /*
+ * <s> is the job pid
+ */
+
+ n = cj->pid;
+ cj->pid = strtol(s, NiL, 10);
+ if (n == CO_PID_WARPED)
+ goto nuke;
+ break;
+
+ case 'k':
+ /*
+ * <s> is a synthesized killed status
+ */
+
+ if (cj->pid < 0)
+ continue;
+ /*FALLTHROUGH*/
+
+ case 'x':
+ /*
+ * <s> is the job exit code and user,sys times
+ */
+
+ cj->status = strtol(s, &e, 10);
+ user = sys = 0;
+ for (;;)
+ {
+ if (e <= s)
+ break;
+ for (s = e; isalpha(*s) || isspace(*s); s++);
+ user += strelapsed(s, &e, CO_QUANT);
+ if (e <= s)
+ break;
+ for (s = e; isalpha(*s) || isspace(*s); s++);
+ sys += strelapsed(s, &e, CO_QUANT);
+ }
+ cj->user += user;
+ cj->sys += sys;
+ co->user += user;
+ co->sys += sys;
+ if (cj->out)
+ cat(cj, &cj->out, sfstdout);
+ if (cj->err)
+ cat(cj, &cj->err, sfstderr);
+ if (cj->pid > 0 || cj->service || (co->flags & (CO_INIT|CO_SERVER)))
+ {
+ nuke:
+ if (cj->pid > 0 && type != 'k')
+ {
+ /*
+ * nuke the zombies
+ */
+
+ n = sfsprintf(buf, sizeof(buf), "wait %d\n", cj->pid);
+ write(co->cmdfd, buf, n);
+ }
+ if (cj->service)
+ co->svc_running--;
+ else
+ co->running--;
+ if (!job || cj == job)
+ {
+ cj->pid = CO_PID_FREE;
+ if (cj->service)
+ co->svc_outstanding--;
+ else
+ co->outstanding--;
+#if 0
+ errormsg(state.lib, 2, "coshell %d active wait %lu timeout=%d outstanding=<%d,%d> running=<%d,%d> reap job %d", co->index, serial, timeout, co->outstanding, co->svc_outstanding, co->running, co->svc_running, cj->id);
+#endif
+ return cj;
+ }
+ cj->pid = CO_PID_ZOMBIE;
+ }
+ else
+ cj->pid = CO_PID_WARPED;
+ break;
+
+ }
+ }
+ } while (any && (co = co->next));
+ return 0;
+ echild:
+#if 0
+ errormsg(state.lib, 2, "coshell wait ECHILD");
+#endif
+ errno = ECHILD;
+ return 0;
+ invalid:
+ errormsg(state.lib, 2, "coshell %d invalid message \"%-.*s>>>%s<<<\"", co->index, s - b, b, s);
+ errno = EINVAL;
+ return 0;
+}
diff --git a/src/lib/libcoshell/ignore.sh b/src/lib/libcoshell/ignore.sh
new file mode 100644
index 0000000..f70002e
--- /dev/null
+++ b/src/lib/libcoshell/ignore.sh
@@ -0,0 +1,45 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1990-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+:
+#
+# Glenn Fowler
+# AT&T Bell Laboratories
+#
+# Bourne coshell support
+#
+# @(#)ignore (AT&T Bell Laboratories) 08/11/92
+#
+while :
+do case $# in
+ 0) exit 0 ;;
+ esac
+ case $1 in
+ *=*) case $RANDOM in
+ $RANDOM)`echo $1 | sed "s/\\([^=]*\\)=\\(.*\\)/eval \\1='\\2'; export \\1/"` ;;
+ *) export "$1" ;;
+ esac
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+done
+"$@"
+exit 0
diff --git a/src/lib/libcoshell/procrun.c b/src/lib/libcoshell/procrun.c
new file mode 100644
index 0000000..cdd5357
--- /dev/null
+++ b/src/lib/libcoshell/procrun.c
@@ -0,0 +1,56 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * coshell procrun(3)
+ */
+
+#include "colib.h"
+
+#include <proc.h>
+
+int
+coprocrun(const char* path, char** argv, int flags)
+{
+ register char* s;
+ register char** a;
+ register Sfio_t* tmp;
+ int n;
+
+ if (!(a = argv))
+ return procclose(procopen(path, a, NiL, NiL, PROC_FOREGROUND|PROC_GID|PROC_UID|flags));
+ if (!(tmp = sfstropen()))
+ return -1;
+ sfputr(tmp, path ? path : "sh", -1);
+ while (s = *++a)
+ {
+ sfputr(tmp, " '", -1);
+ coquote(tmp, s, 0);
+ sfputc(tmp, '\'');
+ }
+ if (!(s = costash(tmp)))
+ return -1;
+ n = cosystem(s);
+ sfstrclose(tmp);
+ return n;
+}
diff --git a/src/lib/libcoshell/silent.sh b/src/lib/libcoshell/silent.sh
new file mode 100644
index 0000000..1f3f4b7
--- /dev/null
+++ b/src/lib/libcoshell/silent.sh
@@ -0,0 +1,44 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1990-2011 AT&T Intellectual Property #
+# and is licensed under the #
+# Eclipse Public License, Version 1.0 #
+# by AT&T Intellectual Property #
+# #
+# A copy of the License is available at #
+# http://www.eclipse.org/org/documents/epl-v10.html #
+# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+:
+#
+# Glenn Fowler
+# AT&T Bell Laboratories
+#
+# Bourne coshell support
+#
+# @(#)silent (AT&T Bell Laboratories) 08/11/92
+#
+while :
+do case $# in
+ 0) exit 0 ;;
+ esac
+ case $1 in
+ *=*) case $RANDOM in
+ $RANDOM)`echo $1 | sed "s/\\([^=]*\\)=\\(.*\\)/eval \\1='\\2'; export \\1/"` ;;
+ *) export "$1" ;;
+ esac
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+done
+"$@"
diff --git a/src/lib/libcoshell/system.c b/src/lib/libcoshell/system.c
new file mode 100644
index 0000000..9179ef8
--- /dev/null
+++ b/src/lib/libcoshell/system.c
@@ -0,0 +1,57 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1990-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * coshell system(3)
+ */
+
+#include "colib.h"
+
+int
+cosystem(const char* cmd)
+{
+ Coshell_t* co;
+ Cojob_t* cj;
+ int status;
+
+ if (!cmd)
+ return !eaccess(pathshell(), X_OK);
+ if (!(co = coopen(NiL, CO_ANY, NiL)))
+ return -1;
+ if (cj = coexec(co, cmd, CO_SILENT, NiL, NiL, NiL))
+ cj = cowait(co, cj, -1);
+ if (!cj)
+ return -1;
+
+ /*
+ * synthesize wait() status from shell status
+ * lack of synthesis is the standard's proprietary sellout
+ */
+
+ status = cj->status;
+ if (EXITED_TERM(status))
+ status &= ((1<<(EXIT_BITS-1))-1);
+ else
+ status = (status & ((1<<EXIT_BITS)-1)) << EXIT_BITS;
+ return status;
+}
diff --git a/src/lib/libdll/Makefile b/src/lib/libdll/Makefile
new file mode 100644
index 0000000..1fdde57
--- /dev/null
+++ b/src/lib/libdll/Makefile
@@ -0,0 +1,17 @@
+:PACKAGE: ast
+
+LICENSE = since=1997,author=gsf
+
+CCFLAGS = $(CC.OPTIMIZE) $(CC.DLL)
+
+dll 1.0 :LIBRARY: dlfcn.c dllopen.c dllfind.c dllplug.c dll_lib.c \
+ dllnext.c dlllook.c dllscan.c dllcheck.c dllerror.c \
+ -ldl -ldld
+
+win32.i386-64 :NOOPTIMIZE: dllscan.c
+
+$(INCLUDEDIR) :INSTALLPROTO: dlldefs.h
+
+dlldefs.h :COPY: FEATURE/dll
+
+:: RELEASE
diff --git a/src/lib/libdll/Mamfile b/src/lib/libdll/Mamfile
new file mode 100644
index 0000000..198ac1e
--- /dev/null
+++ b/src/lib/libdll/Mamfile
@@ -0,0 +1,319 @@
+info mam static 00000 1994-07-17 make (AT&T Research) 5.7 2012-02-29
+setv INSTALLROOT ../../..
+setv PACKAGE_ast_INCLUDE ${INSTALLROOT}/include/ast
+setv PACKAGE_ast_LIB ${INSTALLROOT}/lib
+setv PACKAGEROOT ../../../../..
+setv AR ${mam_cc_AR} ${mam_cc_AR_ARFLAGS}
+setv ARFLAGS rc
+setv AS as
+setv ASFLAGS
+setv CC cc
+setv mam_cc_FLAGS ${mam_cc_DLL}
+setv CCFLAGS ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${mam_cc_OPTIMIZE}?}
+setv CCLDFLAGS ${-strip-symbols?1?${mam_cc_LD_STRIP}??}
+setv COTEMP $$
+setv CPIO cpio
+setv CPIOFLAGS
+setv CPP "${CC} -E"
+setv F77 f77
+setv HOSTCC ${CC}
+setv IGNORE
+setv LD ld
+setv LDFLAGS
+setv LEX lex
+setv LEXFLAGS
+setv LPR lpr
+setv LPRFLAGS
+setv M4FLAGS
+setv NMAKE nmake
+setv NMAKEFLAGS
+setv PR pr
+setv PRFLAGS
+setv SHELL /bin/sh
+setv SILENT
+setv TAR tar
+setv YACC yacc
+setv YACCFLAGS -d
+make ${PACKAGEROOT}/lib/package/ast.lic
+done ${PACKAGEROOT}/lib/package/ast.lic
+make install
+make dll
+make libdll.a archive
+make dll.req
+exec - set -
+exec - echo 'int main(){return 0;}' > 1.${COTEMP}.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -c 1.${COTEMP}.c &&
+exec - x=`${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l'*' 2>&1 | sed -e 's/[][()+@?]/#/g' || :` &&
+exec - {
+exec - case "" in
+exec - *?) echo " " ;;
+exec - esac
+exec - for i in dll dl dld ast
+exec - do case $i in
+exec - "dll"|dll)
+exec - ;;
+exec - *) if test -f ${INSTALLROOT}/lib/lib/$i
+exec - then y=`cat ${INSTALLROOT}/lib/lib/$i`
+exec - case $y in
+exec - *-?*) echo "" $y ;;
+exec - esac
+exec - continue
+exec - elif test ! -f ${INSTALLROOT}/lib/lib$i.a
+exec - then case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -L${INSTALLROOT}/lib ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) continue ;;
+exec - esac
+exec - ;;
+exec - esac
+exec - fi
+exec - ;;
+exec - esac
+exec - echo " -l$i"
+exec - done
+exec - } > dll.req
+exec - rm -f 1.${COTEMP}.*
+done dll.req generated
+make dlfcn.o
+make dlfcn.c
+make dll.h implicit
+done dll.h dontcare virtual
+make xcoff.h implicit
+done xcoff.h dontcare virtual
+make dl.h implicit
+done dl.h dontcare virtual
+make ${PACKAGE_ast_INCLUDE}/error.h implicit
+make ${PACKAGE_ast_INCLUDE}/option.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_api.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_api.h dontcare
+make ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_map.h dontcare
+make ${PACKAGE_ast_INCLUDE}/endian.h implicit
+make ${PACKAGE_ast_INCLUDE}/bytesex.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+done ${PACKAGE_ast_INCLUDE}/bytesex.h dontcare
+done ${PACKAGE_ast_INCLUDE}/endian.h dontcare
+done ${PACKAGE_ast_INCLUDE}/ast_common.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+make ${PACKAGE_ast_INCLUDE}/regex.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+make ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wctype.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wctype.h dontcare
+done ${PACKAGE_ast_INCLUDE}/wctype.h dontcare
+make ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_stdio.h implicit
+make ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
+done ${PACKAGE_ast_INCLUDE}/sfio_s.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_stdio.h dontcare
+done ${PACKAGE_ast_INCLUDE}/stdio.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wchar.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+make ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+make ${INSTALLROOT}/include/prototyped.h implicit
+done ${INSTALLROOT}/include/prototyped.h dontcare
+done ${PACKAGE_ast_INCLUDE}/prototyped.h dontcare
+done ${PACKAGE_ast_INCLUDE}/regex.h dontcare
+make ${PACKAGE_ast_INCLUDE}/getopt.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_getopt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_getopt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/getopt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_botch.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_botch.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_limits.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_limits.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_fcntl.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_fs.h dontcare
+done ${PACKAGE_ast_INCLUDE}/ast_fcntl.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_getopt.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_sys.h implicit
+prev ${PACKAGE_ast_INCLUDE}/getopt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_sys.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_lib.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_lib.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_std.h dontcare
+done ${PACKAGE_ast_INCLUDE}/vmalloc.h dontcare
+make ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/sfio.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/option.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/error.h
+make dlldefs.h implicit
+make FEATURE/dll
+meta FEATURE/dll features/%>FEATURE/% features/dll dll
+make features/dll
+done features/dll
+bind -ldl dontcare
+bind -last
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdl} ${mam_libast} : run features/dll
+done FEATURE/dll generated
+exec - cmp 2>/dev/null -s FEATURE/dll dlldefs.h || { rm -f dlldefs.h; silent test -d . || mkdir .; cp FEATURE/dll dlldefs.h; }
+done dlldefs.h generated
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done dlfcn.c
+meta dlfcn.o %.c>%.o dlfcn.c dlfcn
+prev dlfcn.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_BLD_dll -D_PACKAGE_ast -c dlfcn.c
+done dlfcn.o generated
+make dllopen.o
+make dllopen.c
+make dlllib.h implicit
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev dlldefs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done dlllib.h
+done dllopen.c
+meta dllopen.o %.c>%.o dllopen.c dllopen
+prev dllopen.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_dll -c dllopen.c
+done dllopen.o generated
+make dllfind.o
+make dllfind.c
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev dlldefs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done dllfind.c
+meta dllfind.o %.c>%.o dllfind.c dllfind
+prev dllfind.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_dll -c dllfind.c
+done dllfind.o generated
+make dllplug.o
+make dllplug.c
+prev dlllib.h implicit
+done dllplug.c
+meta dllplug.o %.c>%.o dllplug.c dllplug
+prev dllplug.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_dll -c dllplug.c
+done dllplug.o generated
+make dll_lib.o
+make dll_lib.c
+prev dlllib.h implicit
+done dll_lib.c
+meta dll_lib.o %.c>%.o dll_lib.c dll_lib
+prev dll_lib.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_dll -c dll_lib.c
+done dll_lib.o generated
+make dllnext.o
+make dllnext.c
+make rld_interface.h implicit
+done rld_interface.h dontcare virtual
+prev dlldefs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done dllnext.c
+meta dllnext.o %.c>%.o dllnext.c dllnext
+prev dllnext.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_BLD_dll -D_PACKAGE_ast -c dllnext.c
+done dllnext.o generated
+make dlllook.o
+make dlllook.c
+prev dlldefs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done dlllook.c
+meta dlllook.o %.c>%.o dlllook.c dlllook
+prev dlllook.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_BLD_dll -D_PACKAGE_ast -c dlllook.c
+done dlllook.o generated
+make dllscan.o
+make dllscan.c
+prev dlldefs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+make ${PACKAGE_ast_INCLUDE}/fts.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_mode.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/fts.h
+prev ${PACKAGE_ast_INCLUDE}/error.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+make ${PACKAGE_ast_INCLUDE}/cdt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/cdt.h
+prev ${PACKAGE_ast_INCLUDE}/ast.h implicit
+done dllscan.c
+meta dllscan.o %.c>%.o dllscan.c dllscan
+prev dllscan.c
+exec - ${CC} ${mam_cc_FLAGS} ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${CCFLAGS.FORCE}?} -I. -I${PACKAGE_ast_INCLUDE} -D_BLD_dll -D_PACKAGE_ast -c dllscan.c
+done dllscan.o generated
+make dllcheck.o
+make dllcheck.c
+prev dlllib.h implicit
+done dllcheck.c
+meta dllcheck.o %.c>%.o dllcheck.c dllcheck
+prev dllcheck.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_dll -c dllcheck.c
+done dllcheck.o generated
+make dllerror.o
+make dllerror.c
+prev dlllib.h implicit
+done dllerror.c
+meta dllerror.o %.c>%.o dllerror.c dllerror
+prev dllerror.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -D_BLD_dll -c dllerror.c
+done dllerror.o generated
+exec - ${AR} rc libdll.a dlfcn.o dllopen.o dllfind.o dllplug.o dll_lib.o dllnext.o dlllook.o dllscan.o dllcheck.o dllerror.o
+exec - (ranlib libdll.a) >/dev/null 2>&1 || true
+done libdll.a generated
+done dll virtual
+prev libdll.a archive
+make ${INSTALLROOT}/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib
+exec - then mkdir -p ${INSTALLROOT}/lib
+exec - fi
+done ${INSTALLROOT}/lib generated
+make ${INSTALLROOT}/lib/libdll.a archive
+prev ${INSTALLROOT}/lib
+prev libdll.a archive
+exec - test '' = 'libdll.a' || ${STDCMP} 2>/dev/null -s libdll.a ${INSTALLROOT}/lib/libdll.a || { ${STDMV} ${INSTALLROOT}/lib/libdll.a ${INSTALLROOT}/lib/libdll.a.old 2>/dev/null || true; ${STDCP} libdll.a ${INSTALLROOT}/lib/libdll.a ;}
+exec - (ranlib ${INSTALLROOT}/lib/libdll.a) >/dev/null 2>&1 || true
+done ${INSTALLROOT}/lib/libdll.a generated
+make ${INSTALLROOT}/lib/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib/lib
+exec - then mkdir -p ${INSTALLROOT}/lib/lib
+exec - fi
+done ${INSTALLROOT}/lib/lib generated
+make ${INSTALLROOT}/lib/lib/dll
+prev ${INSTALLROOT}/lib/lib
+prev dll.req
+exec - test '' = 'dll.req' || ${STDCMP} 2>/dev/null -s dll.req ${INSTALLROOT}/lib/lib/dll || { ${STDMV} ${INSTALLROOT}/lib/lib/dll ${INSTALLROOT}/lib/lib/dll.old 2>/dev/null || true; ${STDCP} dll.req ${INSTALLROOT}/lib/lib/dll ;}
+done ${INSTALLROOT}/lib/lib/dll generated
+make ${PACKAGE_ast_INCLUDE}
+exec - if silent test ! -d ${PACKAGE_ast_INCLUDE}
+exec - then mkdir -p ${PACKAGE_ast_INCLUDE}
+exec - fi
+done ${PACKAGE_ast_INCLUDE} generated
+make ${PACKAGE_ast_INCLUDE}/dlldefs.h
+prev ${PACKAGE_ast_INCLUDE}
+prev dlldefs.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1997,author=gsf' dlldefs.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${PACKAGE_ast_INCLUDE}/dlldefs.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${PACKAGE_ast_INCLUDE}/dlldefs.h
+exec - fi
+done ${PACKAGE_ast_INCLUDE}/dlldefs.h generated
+done install virtual
+make test
+done test dontcare virtual
diff --git a/src/lib/libdll/RELEASE b/src/lib/libdll/RELEASE
new file mode 100644
index 0000000..516c866
--- /dev/null
+++ b/src/lib/libdll/RELEASE
@@ -0,0 +1,52 @@
+11-10-11 dll_lib.c: add { dllnames() dll_lib() }
+10-10-20 dllscan.c: version arg "-" => 0
+10-10-19 dllplug.c: fix bug that wiped out dlopen() error message
+10-10-19 dllplug.c: un-localize lookup names (happens with cut and paste)
+10-10-19 dllscan.c: still no code for implicit libs missed by dlopen()
+10-08-02 dllplug.c: fix local path dllcheck() call
+10-05-28 dllplug.c: add dllplugin() with dllcheck() version check
+10-05-28 dllcheck.c: add dllcheck() to do plugin_version() checks
+10-05-28 dllerror.c: add dllerror(int retain) for dll*() and dl*() messages
+09-11-17 dllscan.c: handle name[-.]version in dlsopen()
+09-04-15 dllopen.c: add, use dllopen() internally to wrap dlopen()
+08-05-12 dllscan.c: LIBSUFFIX==.dylib => default plugin version match 0.0
+06-10-11 dllscan.c: check sfstruse() return values -- doh
+06-01-25 dllplug.c: add errorf() library message for dlopen() error
+05-02-14 dllscan.c: "" || "-" => NiL
+04-10-01 dllfind.c: drop ksh "builtin" workaround
+ dllscan.c: directory prefix in name limits search to dir and siblings
+04-07-22 dllscan.c: access() => eaccess()
+04-01-30 dllfind.c: dllplug(error_info.id) then dllplug(0)
+04-01-28 dllscan.c: update for new plugin scheme: lib/foo/bar.xxx
+ dllplug.c: add dllplug() for plugin dllfind()
+03-03-12 dllfind.c: dlopen() with RTLD_GLOBAL|RTLD_PARENT defaults
+03-02-11 dllscan.c: change LIBPATH to <dir>[:<env>[:<pat>]][,...]
+03-01-08 dllscan.c: hack version logic again -- is consistency rocket science?
+03-01-07 dlfcn.c: fix darwin.ppc dlopen/dlsym/dlclose
+02-11-18 dllfind.c: add path,size args (with backwards compatibility checks)
+02-11-15 dllfind.c: check for ./path if '.' in path but no '/'
+02-08-30 dllfind.c: fix a bug that returned uninitialized value on not found
+02-08-28 dllscan.c: handle and display bin as a sibling dir
+02-07-31 dllscan.c: add dllsopen,dllsread,dllsclose
+ dllfind.c: use dllsopen,dllsread,dllsclose
+02-07-26 dllfind.c: add dllinfo()
+02-06-27 dllnext.c: define _GNU_SOURCE to enable RTLD_NEXT
+02-03-17 dllfind.c: fix dll prefix search (for cygwin)
+02-01-11 features/dll: include <dlfcn.h> only if _hdr_dlfcn&&_lib_dlopen
+01-10-31 dlfcn.c: change hp.pa dlopen() prototype (<dlfcn.h> but no -ldl!)
+01-09-25 dllfind: add LIBSUFFIX
+01-07-17 dllfind: do at least one dlopen() to prime dlerror()
+01-05-29 dlopen: fix dlopen(0,0) for HP
+01-04-20 dllfind: use getconf HOSTTYPE LIBPATH LIBSUFFIX
+01-02-14 features/dll: fix unbalanced ' quote and ancient hostinfo reference
+00-01-26 dlllook: add -- dlsym() with `_' weak prefix fallback
+99-04-01 features/dll: drop <stdio.h> -- iffe protos printf
+99-03-19 static=1 for all but win32.*
+98-06-01 dllfind: fix version search
+98-03-11 features/dll: probe for _DLL_RLD_SYM
+98-03-01 dllnext: fix to work!
+98-01-23 -ldl test moved to lib0ast
+98-01-11 update for astconf("LIBPATH")
+ add dllnext(flags) to uncover next layer
+ dllfind() and dllnext() in separate files (for 3d)
+97-10-11 move from libast so libast can link static
diff --git a/src/lib/libdll/dlfcn.c b/src/lib/libdll/dlfcn.c
new file mode 100644
index 0000000..810be1b
--- /dev/null
+++ b/src/lib/libdll/dlfcn.c
@@ -0,0 +1,536 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1997-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * provide dlopen/dlsym/dlerror interface
+ *
+ * David Korn
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+static const char id[] = "\n@(#)$Id: dll library (AT&T Research) 2010-10-20 $\0\n";
+
+#include <ast.h>
+#include <dlldefs.h>
+#include <error.h>
+
+#define T(x) ERROR_dictionary(x)
+
+#if _BLD_dll && defined(__EXPORT__)
+#define extern __EXPORT__
+#endif
+
+#if _hdr_dlfcn && _lib_dlopen
+
+ /*
+ * standard
+ */
+
+# include <dlfcn.h>
+
+#else
+#if _hdr_dl
+
+ /*
+ * HP-UX
+ */
+
+# include <dl.h>
+# ifndef BIND_FIRST
+# define BIND_FIRST 0x4
+# endif
+# ifndef BIND_NOSTART
+# define BIND_NOSTART 0x10
+# endif
+
+ static shl_t all;
+ static int err;
+
+ extern void* dlopen(const char* path, int mode)
+ {
+ void* dll;
+
+ if (!path)
+ return (void*)&all;
+ if (mode)
+ mode = (BIND_IMMEDIATE|BIND_FIRST|BIND_NOSTART);
+ if (!(dll = (void*)shl_load(path, mode, 0L)))
+ err = errno;
+ return dll;
+ }
+
+ extern int dlclose(void* dll)
+ {
+ return 0;
+ }
+
+ extern void* dlsym(void* dll, const char* name)
+ {
+ shl_t handle;
+ long addr;
+
+ handle = dll == (void*)&all ? (shl_t)0 : (shl_t)dll;
+ if (shl_findsym(&handle, name, TYPE_UNDEFINED, &addr))
+ {
+ err = errno;
+ return 0;
+ }
+ return (void*)addr;
+ }
+
+ extern char* dlerror(void)
+ {
+ char* msg;
+
+ if (!err)
+ return 0;
+ msg = fmterror(err);
+ err = 0;
+ return msg;
+ }
+
+#else
+#if _sys_ldr && _lib_loadbind
+
+ /*
+ * rs6000
+ */
+
+# include <sys/ldr.h>
+# include <xcoff.h>
+
+ /* xcoff module header */
+ struct hdr
+ {
+ struct filehdr f;
+ struct aouthdr a;
+ struct scnhdr s[1];
+ };
+
+ static struct ld_info* ld_info;
+ static unsigned int ld_info_size = 1024;
+ static void* last_module;
+ static int err;
+
+ extern void* dlopen(const char* path, int mode)
+ {
+ void* dll;
+
+ if (!(dll = (void*)load((char*)path, mode, getenv("LIBPATH"))))
+ err = errno;
+ return dll;
+ }
+
+ extern int dlclose(void* dll)
+ {
+ return 0;
+ }
+
+ static int getquery(void)
+ {
+ if (!ld_info)
+ ld_info = malloc(ld_info_size);
+ for (;;)
+ {
+ if (!ld_info)
+ return 1;
+ if (!loadquery(L_GETINFO, ld_info, ld_info_size))
+ return 0;
+ if (errno != ENOMEM)
+ return 1;
+ ld_info = realloc(ld_info, ld_info_size *= 2);
+ }
+ }
+
+ /* find the loaded module whose data area contains the
+ * address passed in. Remember that procedure pointers
+ * are implemented as pointers to descriptors in the
+ * data area of the module defining the procedure
+ */
+ static struct ld_info* getinfo(void* module)
+ {
+ struct ld_info* info = ld_info;
+ register int n = 1;
+
+ if (!ld_info || module != last_module)
+ {
+ last_module = module;
+ if (getquery())
+ return 0;
+ info = ld_info;
+ }
+ while (n)
+ {
+ if ((char*)(info->ldinfo_dataorg) <= (char*)module &&
+ (char*)module <= ((char*)(info->ldinfo_dataorg)
+ + (unsigned)(info->ldinfo_datasize)))
+ return info;
+ if (n=info->ldinfo_next)
+ info = (void*)((char*)info + n);
+ }
+ return 0;
+ }
+
+ static char* getloc(struct hdr* hdr, char* data, char* name)
+ {
+ struct ldhdr* ldhdr;
+ struct ldsym* ldsym;
+ ulong datareloc;
+ ulong textreloc;
+ int i;
+
+ /* data is relocated by the difference between
+ * its virtual origin and where it was
+ * actually placed
+ */
+ /*N.B. o_sndata etc. are one based */
+ datareloc = (ulong)data - hdr->s[hdr->a.o_sndata-1].s_vaddr;
+ /*hdr is address of header, not text, so add text s_scnptr */
+ textreloc = (ulong)hdr + hdr->s[hdr->a.o_sntext-1].s_scnptr
+ - hdr->s[hdr->a.o_sntext-1].s_vaddr;
+ ldhdr = (void*)((char*)hdr+ hdr->s[hdr->a.o_snloader-1].s_scnptr);
+ ldsym = (void*) (ldhdr+1);
+ /* search the exports symbols */
+ for(i=0; i < ldhdr->l_nsyms;ldsym++,i++)
+ {
+ char *symname,symbuf[9];
+ char *loc;
+ /* the symbol name representation is a nuisance since
+ * 8 character names appear in l_name but may
+ * not be null terminated. This code works around
+ * that by brute force
+ */
+ if (ldsym->l_zeroes)
+ {
+ symname = symbuf;
+ memcpy(symbuf,ldsym->l_name,8);
+ symbuf[8] = 0;
+ }
+ else
+ symname = (void*)(ldsym->l_offset + (ulong)ldhdr + ldhdr->l_stoff);
+ if (strcmp(symname,name))
+ continue;
+ loc = (char*)ldsym->l_value;
+ if ((ldsym->l_scnum==hdr->a.o_sndata) ||
+ (ldsym->l_scnum==hdr->a.o_snbss))
+ loc += datareloc;
+ else if (ldsym->l_scnum==hdr->a.o_sntext)
+ loc += textreloc;
+ return loc;
+ }
+ return 0;
+ }
+
+ extern void* dlsym(void* handle, const char* name)
+ {
+ void* addr;
+ struct ld_info* info;
+
+ if (!(info = getinfo(handle)) || !(addr = getloc(info->ldinfo_textorg,info->ldinfo_dataorg,(char*)name)))
+ {
+ err = errno;
+ return 0;
+ }
+ return addr;
+ }
+
+ extern char* dlerror(void)
+ {
+ char* msg;
+
+ if (!err)
+ return 0;
+ msg = fmterror(err);
+ err = 0;
+ return msg;
+ }
+
+#else
+#if _hdr_dll && _lib_dllload
+
+ /*
+ * MVS
+ */
+
+# include <dll.h>
+
+ static int err;
+
+ extern void* dlopen(const char* path, int mode)
+ {
+ void* dll;
+
+ NoP(mode);
+ if (!(dll = (void*)dllload(path)))
+ err = errno;
+ return dll;
+ }
+
+ extern int dlclose(void* dll)
+ {
+ return 0;
+ }
+
+ extern void* dlsym(void* handle, const char* name)
+ {
+ void* addr;
+
+ if (!(addr = (void*)dllqueryfn(handle, (char*)name)))
+ err = errno;
+ return addr;
+ }
+
+ extern char* dlerror(void)
+ {
+ char* msg;
+
+ if (!err)
+ return 0;
+ msg = fmterror(err);
+ err = 0;
+ return msg;
+ }
+
+#else
+#if _hdr_mach_o_dyld
+
+ /*
+ * mac[h]
+ */
+
+# include <mach-o/dyld.h>
+
+ typedef const struct mach_header* NSImage;
+
+ typedef struct Dll_s
+ {
+ unsigned long magic;
+ NSImage image;
+ NSModule module;
+ char path[1];
+ } Dll_t;
+
+ #define DL_MAGIC 0x04190c04
+ #define DL_NEXT ((Dll_t*)RTLD_NEXT)
+
+ static const char* dlmessage = "no error";
+
+ static const char e_cover[] = T("cannot access covered library");
+ static const char e_handle[] = T("invalid handle");
+ static const char e_space[] = T("out of space");
+ static const char e_static[] = T("image statically linked");
+ static const char e_undefined[] = T("undefined symbol");
+
+ static Dll_t global = { DL_MAGIC };
+
+ static void undefined(const char* name)
+ {
+ }
+
+ static NSModule multiple(NSSymbol sym, NSModule om, NSModule nm)
+ {
+ return om;
+ }
+
+ static void linkedit(NSLinkEditErrors c, int n, const char* f, const char* m)
+ {
+ dlmessage = m;
+ }
+
+ static NSLinkEditErrorHandlers handlers =
+ {
+ undefined, multiple, linkedit
+ };
+
+ extern void* dlopen(const char* path, int mode)
+ {
+ Dll_t* dll;
+ int i;
+ NSObjectFileImage image;
+
+ static int init = 0;
+
+ if (!_dyld_present())
+ {
+ dlmessage = e_static;
+ return 0;
+ }
+ if (!init)
+ {
+ init = 1;
+ NSInstallLinkEditErrorHandlers(&handlers);
+ }
+ if (!path)
+ dll = &global;
+ else if (!(dll = newof(0, Dll_t, 1, strlen(path))))
+ {
+ dlmessage = e_space;
+ return 0;
+ }
+ else
+ {
+ switch (NSCreateObjectFileImageFromFile(path, &image))
+ {
+ case NSObjectFileImageSuccess:
+ dll->module = NSLinkModule(image, path, (mode & RTLD_LAZY) ? 0 : NSLINKMODULE_OPTION_BINDNOW);
+ NSDestroyObjectFileImage(image);
+ if (!dll->module)
+ {
+ free(dll);
+ return 0;
+ }
+ break;
+ case NSObjectFileImageInappropriateFile:
+ dll->image = NSAddImage(path, 0);
+ if (!dll->image)
+ {
+ free(dll);
+ return 0;
+ }
+ break;
+ default:
+ free(dll);
+ return 0;
+ }
+ strcpy(dll->path, path);
+ dll->magic = DL_MAGIC;
+ }
+ return (void*)dll;
+ }
+
+ extern int dlclose(void* handle)
+ {
+ Dll_t* dll = (Dll_t*)handle;
+
+ if (!dll || dll == DL_NEXT || dll->magic != DL_MAGIC)
+ {
+ dlmessage = e_handle;
+ return -1;
+ }
+ if (dll->module)
+ NSUnLinkModule(dll->module, 0);
+ free(dll);
+ return 0;
+ }
+
+ static NSSymbol
+ lookup(Dll_t* dll, const char* name)
+ {
+ unsigned long pun;
+ void* address;
+
+ if (dll == DL_NEXT)
+ {
+ if (!_dyld_func_lookup(name, &pun))
+ return 0;
+ address = (NSSymbol)pun;
+ }
+ else if (dll->module)
+ address = NSLookupSymbolInModule(dll->module, name);
+ else if (dll->image)
+ {
+ if (!NSIsSymbolNameDefinedInImage(dll->image, name))
+ return 0;
+ address = NSLookupSymbolInImage(dll->image, name, 0);
+ }
+ else
+ {
+ if (!NSIsSymbolNameDefined(name))
+ return 0;
+ address = NSLookupAndBindSymbol(name);
+ }
+ if (address)
+ address = NSAddressOfSymbol(address);
+ return address;
+ }
+
+ extern void* dlsym(void* handle, const char* name)
+ {
+ Dll_t* dll = (Dll_t*)handle;
+ NSSymbol address;
+ char buf[1024];
+
+ if (!dll || dll != DL_NEXT && (dll->magic != DL_MAGIC || !dll->image && !dll->module))
+ {
+ dlmessage = e_handle;
+ return 0;
+ }
+ if (!(address = lookup(dll, name)) && name[0] != '_' && strlen(name) < (sizeof(buf) - 1))
+ {
+ buf[0] = '_';
+ strcpy(buf + 1, name);
+ address = lookup(dll, buf);
+ }
+ if (!address)
+ {
+ dlmessage = dll == DL_NEXT ? e_cover : e_undefined;
+ return 0;
+ }
+ return (void*)address;
+ }
+
+ extern char* dlerror(void)
+ {
+ char* msg;
+
+ msg = (char*)dlmessage;
+ dlmessage = 0;
+ return msg;
+ }
+
+#else
+ /*
+ * punt
+ */
+
+ static int err;
+
+ extern void* dlopen(const char* path, int mode)
+ {
+ err = 1;
+ return 0;
+ }
+
+ extern int dlclose(void* dll)
+ {
+ err = 1;
+ return 0;
+ }
+
+ extern void* dlsym(void* handle, const char* name)
+ {
+ err = 1;
+ return 0;
+ }
+
+ extern char* dlerror(void)
+ {
+ if (!err)
+ return 0;
+ err = 0;
+ return "dynamic linking not supported";
+ }
+
+#endif
+#endif
+#endif
+#endif
+#endif
diff --git a/src/lib/libdll/dll_lib.c b/src/lib/libdll/dll_lib.c
new file mode 100644
index 0000000..29e4cd8
--- /dev/null
+++ b/src/lib/libdll/dll_lib.c
@@ -0,0 +1,183 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1997-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include "dlllib.h"
+
+typedef void* (*Dll_lib_f)(const char*, void*, const char*);
+
+typedef struct Dll_lib_s
+{
+ struct Dll_lib_s* next;
+ Dll_lib_f libf;
+ char* path;
+ char base[1];
+} Dll_lib_t;
+
+/*
+ * split <name,base,type,opts> from name into names
+ */
+
+Dllnames_t*
+dllnames(const char* id, const char* name, Dllnames_t* names)
+{
+ char* s;
+ char* t;
+ char* b;
+ char* e;
+ size_t n;
+
+ n = strlen(id);
+ if (strneq(name, id, n) && (streq(name + n, "_s") || streq(name + n, "_t")))
+ return 0;
+ if (!names)
+ {
+ s = fmtbuf(sizeof(Dllnames_t*) + sizeof(names) - 1);
+ if (n = (s - (char*)0) % sizeof(names))
+ s += sizeof(names) - n;
+ names = (Dllnames_t*)s;
+ }
+
+ /*
+ * determine the base name
+ */
+
+ if ((s = strrchr(name, '/')) || (s = strrchr(name, '\\')))
+ s++;
+ else
+ s = (char*)name;
+ if (strneq(s, "lib", 3))
+ s += 3;
+ b = names->base = names->data;
+ e = b + sizeof(names->data) - 1;
+ t = s;
+ while (b < e && *t && *t != '.' && *t != '-' && *t != ':')
+ *b++ = *t++;
+ *b++ = 0;
+
+ /*
+ * determine the optional type
+ */
+
+ if (t = strrchr(s, ':'))
+ {
+ names->name = b;
+ while (b < e && s < t)
+ *b++ = *s++;
+ *b++ = 0;
+ names->type = b;
+ while (b < e && *++t)
+ *b++ = *t;
+ *b++ = 0;
+ }
+ else
+ {
+ names->name = (char*)name;
+ names->type = 0;
+ }
+ *(names->path = b) = 0;
+ names->opts = 0;
+ names->id = (char*)id;
+ return names;
+}
+
+/*
+ * return method pointer for <id,version> in names
+ */
+
+void*
+dll_lib(Dllnames_t* names, unsigned long version, Dllerror_f errorf, void* disc)
+{
+ void* dll;
+ Dll_lib_t* lib;
+ Dll_lib_f libf;
+ int n;
+ char sym[64];
+
+ static Dll_lib_t* loaded;
+
+ if (!names)
+ return 0;
+
+ /*
+ * check if plugin already loaded
+ */
+
+ for (lib = loaded; lib; lib = lib->next)
+ if (streq(names->base, lib->base))
+ {
+ libf = lib->libf;
+ goto init;
+ }
+
+ /*
+ * load
+ */
+
+ if (!(dll = dllplugin(names->id, names->name, NiL, version, NiL, RTLD_LAZY, names->path, names->data + sizeof(names->data) - names->path)) && (streq(names->name, names->base) || !(dll = dllplugin(names->id, names->base, NiL, version, NiL, RTLD_LAZY, names->path, names->data + sizeof(names->data) - names->path))))
+ {
+ if (errorf)
+ (*errorf)(NiL, disc, 2, "%s: library not found", names->name);
+ return 0;
+ }
+
+ /*
+ * init
+ */
+
+ sfsprintf(sym, sizeof(sym), "%s_lib", names->id);
+ if (!(libf = (Dll_lib_f)dlllook(dll, sym)))
+ {
+ if (errorf)
+ (*errorf)(NiL, disc, 2, "%s: %s: initialization function not found in library", names->path, sym);
+ return 0;
+ }
+
+ /*
+ * add to the loaded list
+ */
+
+ if (lib = newof(0, Dll_lib_t, 1, (n = strlen(names->base)) + strlen(names->path) + 1))
+ {
+ lib->libf = libf;
+ strcpy(lib->base, names->base);
+ strcpy(lib->path = lib->base + n + 1, names->path);
+ lib->next = loaded;
+ loaded = lib;
+ }
+ init:
+ return (*libf)(names->path, disc, names->type);
+}
+
+/*
+ * return method pointer for <id,name,version>
+ */
+
+void*
+dllmeth(const char* id, const char* name, unsigned long version)
+{
+ Dllnames_t names;
+
+ return dll_lib(dllnames(id, name, &names), version, 0, 0);
+}
diff --git a/src/lib/libdll/dllcheck.c b/src/lib/libdll/dllcheck.c
new file mode 100644
index 0000000..c18f83e
--- /dev/null
+++ b/src/lib/libdll/dllcheck.c
@@ -0,0 +1,85 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1997-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include "dlllib.h"
+
+/*
+ * return plugin version for dll
+ * 0 if there is none
+ * path!=0 enables library level diagnostics
+ */
+
+extern unsigned long
+dllversion(void* dll, const char* path)
+{
+ Dll_plugin_version_f pvf;
+
+ if (pvf = (Dll_plugin_version_f)dlllook(dll, "plugin_version"))
+ return (*pvf)();
+ if (path)
+ {
+ state.error = 1;
+ sfsprintf(state.errorbuf, sizeof(state.errorbuf), "plugin_version() not found");
+ errorf("dll", NiL, 1, "%s: %s", path, state.errorbuf);
+ }
+ return 0;
+}
+
+/*
+ * check if dll on path has plugin version >= ver
+ * 1 returned on success, 0 on failure
+ * path!=0 enables library level diagnostics
+ * cur!=0 gets actual version
+ */
+
+extern int
+dllcheck(void* dll, const char* path, unsigned long ver, unsigned long* cur)
+{
+ unsigned long v;
+ Dll_plugin_version_f pvf;
+
+ state.error = 0;
+ if (ver || cur)
+ {
+ v = dllversion(dll, path);
+ if (cur)
+ *cur = v;
+ }
+ if (!ver)
+ return 1;
+ if (!v)
+ return 0;
+ if (v < ver)
+ {
+ if (path)
+ {
+ state.error = 1;
+ sfsprintf(state.errorbuf, sizeof(state.errorbuf), "plugin version %lu older than caller %lu", v, ver);
+ errorf("dll", NiL, 1, "%s: %s", path, state.errorbuf);
+ }
+ return 0;
+ }
+ return 1;
+}
diff --git a/src/lib/libdll/dllerror.c b/src/lib/libdll/dllerror.c
new file mode 100644
index 0000000..dd0278d
--- /dev/null
+++ b/src/lib/libdll/dllerror.c
@@ -0,0 +1,52 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1997-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include "dlllib.h"
+
+Dllstate_t state;
+
+/*
+ * return error message from last failed dl*() call
+ * retain==0 resets the last dl*() error
+ */
+
+extern char*
+dllerror(int retain)
+{
+ char* s;
+
+ if (state.error)
+ {
+ state.error = retain;
+ return state.errorbuf;
+ }
+ s = dlerror();
+ if (retain)
+ {
+ state.error = retain;
+ sfsprintf(state.errorbuf, sizeof(state.errorbuf), "%s", s);
+ }
+ return s;
+}
diff --git a/src/lib/libdll/dllfind.c b/src/lib/libdll/dllfind.c
new file mode 100644
index 0000000..6446663
--- /dev/null
+++ b/src/lib/libdll/dllfind.c
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1997-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include <ast.h>
+#include <dlldefs.h>
+#include <error.h>
+
+/*
+ * find and load library name with optional version ver and dlopen() flags
+ * at least one dlopen() is called to initialize dlerror()
+ * if path!=0 then library path up to size chars copied to path with trailing 0
+ * if name contains a directory prefix then library search is limited to the dir and siblings
+ */
+
+extern void*
+dllfind(const char* lib, const char* ver, int flags, char* path, size_t size)
+{
+ char* id;
+ void* dll;
+
+ if ((id = error_info.id) && (dll = dllplug(id, lib, ver, flags, path, size)))
+ return dll;
+ return dllplug(NiL, lib, ver, flags, path, size);
+}
diff --git a/src/lib/libdll/dlllib.h b/src/lib/libdll/dlllib.h
new file mode 100644
index 0000000..c5fb1ab
--- /dev/null
+++ b/src/lib/libdll/dlllib.h
@@ -0,0 +1,34 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1997-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+#include <ast.h>
+#include <dlldefs.h>
+#include <error.h>
+
+#define state _dll_state
+
+typedef struct Dllstate_s
+{
+ int error;
+ char errorbuf[128];
+} Dllstate_t;
+
+extern Dllstate_t state;
diff --git a/src/lib/libdll/dlllook.c b/src/lib/libdll/dlllook.c
new file mode 100644
index 0000000..10928a6
--- /dev/null
+++ b/src/lib/libdll/dlllook.c
@@ -0,0 +1,46 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1997-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include <ast.h>
+#include <dlldefs.h>
+
+/*
+ * dlsym() with `_' weak fallback
+ */
+
+void*
+dlllook(void* dll, const char* name)
+{
+ register void* addr;
+ char buf[256];
+
+ if (!(addr = dlsym(dll, name)) && strlen(name) < (sizeof(buf) - 2))
+ {
+ buf[0] = '_';
+ strcpy(buf + 1, name);
+ addr = dlsym(dll, buf);
+ }
+ return addr;
+}
diff --git a/src/lib/libdll/dllnext.c b/src/lib/libdll/dllnext.c
new file mode 100644
index 0000000..9e81c4a
--- /dev/null
+++ b/src/lib/libdll/dllnext.c
@@ -0,0 +1,223 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1997-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+#ifndef __EXTENSIONS__
+#define __EXTENSIONS__ 1
+#endif
+
+#include <ast.h>
+#include <dlldefs.h>
+
+#if _hdr_rld_interface
+#include <rld_interface.h>
+#endif
+
+/*
+ * return a handle for the next layer down,
+ * i.e., the next layer that has symbols covered
+ * by the main prog and dll's loaded so far
+ *
+ * intentionally light on external lib calls
+ * so this routine can be used early in process
+ * startup
+ */
+
+#ifdef _DLL_RLD_SYM
+
+#define DEBUG 1
+
+#if DEBUG
+
+typedef ssize_t (*Write_f)(int, const void*, size_t);
+
+#endif
+
+#undef dllnext
+
+void*
+_dll_next(int flags, _DLL_RLD_SYM_TYPE* here)
+{
+ register char* vp;
+ register void* lp;
+ register int found = 0;
+ char* s;
+ char* b;
+ char* e;
+ char dummy[256];
+#if DEBUG
+ Write_f wr = 0;
+ Write_f xr;
+ char buf[1024];
+#endif
+
+#if DEBUG
+ if (getenv("DLL_DEBUG") && (vp = (char*)_rld_new_interface(_RLD_FIRST_PATHNAME)))
+ {
+ do
+ {
+ if (strcmp(vp, "MAIN") && (lp = dllopen(vp, flags)))
+ {
+ if (xr = (Write_f)dlsym(lp, "write"))
+ wr = xr;
+ }
+ } while (vp = (char*)_rld_new_interface(_RLD_NEXT_PATHNAME));
+ }
+#endif
+ if (vp = (char*)_rld_new_interface(_RLD_FIRST_PATHNAME))
+ {
+ do
+ {
+ if (lp = dllopen(strcmp(vp, "MAIN") ? vp : (char*)0, flags))
+ {
+ if (found)
+ {
+ b = e = 0;
+ s = vp;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ break;
+ case '/':
+ b = s;
+ e = 0;
+ continue;
+ case '.':
+ if (!e)
+ e = s - 1;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ if (b && e)
+ {
+ s = dummy;
+ *s++ = '_';
+ *s++ = '_';
+ while (b < e)
+ *s++ = *b++;
+ b = "_dummy";
+ while (*s++ = *b++);
+ if (dlsym(lp, dummy))
+ {
+ dlclose(lp);
+ lp = 0;
+ }
+ }
+ if (lp)
+ {
+#if DEBUG
+ if (wr)
+ (*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: next %s\n", vp));
+#endif
+ return lp;
+ }
+#if DEBUG
+ else if (wr)
+ (*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: skip %s\n", vp));
+#endif
+ }
+ else if ((_DLL_RLD_SYM_TYPE*)dlsym(lp, _DLL_RLD_SYM_STR) == here)
+ {
+#if DEBUG
+ if (wr)
+ (*wr)(2, buf, sfsprintf(buf, sizeof(buf), "dll: this %s\n", vp));
+#endif
+ found = 1;
+ }
+ }
+ } while (vp = (char*)_rld_new_interface(_RLD_NEXT_PATHNAME));
+ }
+ return dllnext(flags);
+}
+
+#endif
+
+#ifndef RTLD_NEXT
+#if _dll_DYNAMIC
+
+#include <link.h>
+
+extern struct link_dynamic _DYNAMIC;
+
+#endif
+#endif
+
+void*
+dllnext(int flags)
+{
+ register void* dll;
+#ifndef RTLD_NEXT
+#if _dll_DYNAMIC
+ register struct link_map* map;
+ register char* s;
+ register char* b;
+#endif
+ register char* ver;
+ char* path;
+
+ static char next[] = { _DLL_NEXT_PATH };
+#endif
+
+#ifdef RTLD_NEXT
+ dll = RTLD_NEXT;
+#else
+ path = next;
+#if _dll_DYNAMIC
+ for (map = _DYNAMIC.ld_un.ld_1->ld_loaded; map; map = map->lm_next)
+ {
+ b = 0;
+ s = map->lm_name;
+ while (*s)
+ if (*s++ == '/')
+ b = s;
+ if (b && b[0] == 'l' && b[1] == 'i' && b[2] == 'b' && b[3] == 'c' && b[4] == '.')
+ {
+ path = map->lm_name;
+ break;
+ }
+ }
+#endif
+ ver = path + strlen(path);
+ while (!(dll = dllopen(path, flags)))
+ {
+ do
+ {
+ if (ver <= path)
+ return 0;
+ } while (*--ver != '.');
+ if (*(ver + 1) <= '0' || *(ver + 1) >= '9')
+ return 0;
+ *ver = 0;
+ }
+#endif
+ return dll;
+}
diff --git a/src/lib/libdll/dllopen.c b/src/lib/libdll/dllopen.c
new file mode 100644
index 0000000..0fac2d0
--- /dev/null
+++ b/src/lib/libdll/dllopen.c
@@ -0,0 +1,93 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1997-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * at&t research
+ */
+
+#include "dlllib.h"
+
+#if 0
+
+/*
+ * dlopen() wrapper that properly initializes LIBPATH
+ * with the path of the dll to be opened
+ *
+ * 2009-04-15 -- if ld.so re-checked the env this would work ...
+ */
+
+void*
+dllopen(const char* name, int mode)
+{
+ void* dll;
+ Dllinfo_t* info;
+ char* olibpath;
+ char* path;
+ char* oenv;
+ char* nenv[2];
+ char* dir;
+ char* base;
+ int len;
+
+ if (!environ)
+ {
+ nenv[0] = nenv[1] = 0;
+ environ = nenv;
+ }
+ info = dllinfo();
+ oenv = environ[0];
+ olibpath = getenv(info->env);
+ if (base = strrchr(name, '/'))
+ {
+ dir = (char*)name;
+ len = ++base - dir;
+ }
+ else
+ {
+ dir = "./";
+ len = 2;
+ base = (char*)name;
+ }
+ path = sfprints("%-.*s%s%c%s=%-.*s%s%s", len, dir, base, 0, info->env, len, dir, olibpath ? ":" : "", olibpath ? olibpath : "");
+ environ[0] = path + strlen(path) + 1;
+ state.error = 0;
+ dll = dlopen(path, mode);
+ if (environ == nenv)
+ environ = 0;
+ else
+ environ[0] = oenv;
+ return dll;
+}
+
+#else
+
+/*
+ * dlopen() wrapper -- waiting for prestidigitaions
+ */
+
+void*
+dllopen(const char* name, int mode)
+{
+ state.error = 0;
+ return dlopen(name, mode);
+}
+
+#endif
diff --git a/src/lib/libdll/dllplug.c b/src/lib/libdll/dllplug.c
new file mode 100644
index 0000000..3854762
--- /dev/null
+++ b/src/lib/libdll/dllplug.c
@@ -0,0 +1,126 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1997-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include "dlllib.h"
+
+/*
+ * find and load lib plugin/module library name with optional version ver and dlopen() flags
+ * at least one dlopen() is called to initialize dlerror()
+ * if path!=0 then library path up to size chars copied to path with trailing 0
+ * if name contains a directory prefix then library search is limited to the dir and siblings
+ */
+
+extern void*
+dllplugin(const char* lib, const char* name, const char* ver, unsigned long rel, unsigned long* cur, int flags, char* path, size_t size)
+{
+ void* dll;
+ int err;
+ int hit;
+ Dllscan_t* dls;
+ Dllent_t* dle;
+
+ err = hit = 0;
+ for (;;)
+ {
+ if (dls = dllsopen(lib, name, ver))
+ {
+ while (dle = dllsread(dls))
+ {
+ hit = 1;
+#if 0
+ again:
+#endif
+ if (dll = dllopen(dle->path, flags|RTLD_GLOBAL|RTLD_PARENT))
+ {
+ if (!dllcheck(dll, dle->path, rel, cur))
+ {
+ err = state.error;
+ dlclose(dll);
+ dll = 0;
+ continue;
+ }
+ if (path && size)
+ strlcpy(path, dle->path, size);
+ break;
+ }
+ else
+ {
+#if 0
+ /*
+ * dlopen() should load implicit libraries
+ * this code does that
+ * but it doesn't help on galadriel
+ */
+
+ char* s;
+ char* e;
+
+ if ((s = dllerror(1)) && (e = strchr(s, ':')))
+ {
+ *e = 0;
+ error(1, "AHA %s implicit", s);
+ dll = dllplugin(lib, s, 0, 0, 0, flags, path, size);
+ *e = ':';
+ if (dll)
+ {
+ error(1, "AHA implicit %s => %s", s, path);
+ goto again;
+ }
+ }
+#endif
+ errorf("dll", NiL, 1, "%s: dlopen failed: %s", dle->path, dllerror(1));
+ err = state.error;
+ }
+ }
+ dllsclose(dls);
+ }
+ if (hit)
+ {
+ if (!dll)
+ state.error = err;
+ return dll;
+ }
+ if (!lib)
+ break;
+ lib = 0;
+ }
+ if (dll = dllopen(name, flags))
+ {
+ if (!dllcheck(dll, name, rel, cur))
+ {
+ dlclose(dll);
+ dll = 0;
+ }
+ else if (path && size)
+ strlcpy(path, name, size);
+ }
+ return dll;
+}
+
+extern void*
+dllplug(const char* lib, const char* name, const char* ver, int flags, char* path, size_t size)
+{
+ return dllplugin(lib, name, ver, 0, NiL, flags, path, size);
+}
diff --git a/src/lib/libdll/dllscan.c b/src/lib/libdll/dllscan.c
new file mode 100644
index 0000000..1c8f5a5
--- /dev/null
+++ b/src/lib/libdll/dllscan.c
@@ -0,0 +1,525 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1997-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#define _DLLINFO_PRIVATE_ \
+ char* sib[3]; \
+ char sibbuf[64]; \
+ char envbuf[64];
+
+#define _DLLSCAN_PRIVATE_ \
+ Dllent_t entry; \
+ Uniq_t* uniq; \
+ int flags; \
+ Vmalloc_t* vm; \
+ Dt_t* dict; \
+ Dtdisc_t disc; \
+ FTS* fts; \
+ FTSENT* ent; \
+ Sfio_t* tmp; \
+ char** sb; \
+ char** sp; \
+ char* pb; \
+ char* pp; \
+ char* pe; \
+ int off; \
+ int prelen; \
+ int suflen; \
+ char** lib; \
+ char nam[64]; \
+ char pat[64]; \
+ char buf[64];
+
+#define DLL_MATCH_DONE 0x8000
+#define DLL_MATCH_NAME 0x4000
+#define DLL_MATCH_VERSION 0x2000
+
+#include <ast.h>
+#include <cdt.h>
+#include <ctype.h>
+#include <error.h>
+#include <fts.h>
+#include <vmalloc.h>
+
+typedef struct Uniq_s
+{
+ Dtlink_t link;
+ char name[1];
+} Uniq_t;
+
+#include <dlldefs.h>
+
+static char bin[] = "bin";
+static char lib[] = "lib";
+
+/*
+ * we need a sibling dir in PATH to search for dlls
+ * the confstr LIBPATH provides the local info
+ *
+ * <sibling-dir>[:<env-var>[:<host-pattern>]][,...]
+ *
+ * if <host-pattern> is present then it must match confstr HOSTTYPE
+ */
+
+Dllinfo_t*
+dllinfo(void)
+{
+ register char* s;
+ register char* h;
+ char* d;
+ char* v;
+ char* p;
+ int dn;
+ int vn;
+ int pn;
+ char pat[256];
+
+ static Dllinfo_t info;
+
+ if (!info.sibling)
+ {
+ info.sibling = info.sib;
+ if (*(s = astconf("LIBPATH", NiL, NiL)))
+ {
+ while (*s == ':' || *s == ',')
+ s++;
+ if (*s)
+ {
+ h = 0;
+ for (;;)
+ {
+ for (d = s; *s && *s != ':' && *s != ','; s++);
+ if (!(dn = s - d))
+ d = 0;
+ if (*s == ':')
+ {
+ for (v = ++s; *s && *s != ':' && *s != ','; s++);
+ if (!(vn = s - v))
+ v = 0;
+ if (*s == ':')
+ {
+ for (p = ++s; *s && *s != ':' && *s != ','; s++);
+ if (!(pn = s - p))
+ p = 0;
+ }
+ else
+ p = 0;
+ }
+ else
+ {
+ v = 0;
+ p = 0;
+ }
+ while (*s && *s++ != ',');
+ if (!*s || !p || !h && !*(h = astconf("HOSTTYPE", NiL, NiL)))
+ break;
+ if (pn >= sizeof(pat))
+ pn = sizeof(pat) - 1;
+ memcpy(pat, p, pn);
+ pat[pn] = 0;
+ if (strmatch(h, pat))
+ break;
+ }
+ if (d && dn < sizeof(info.sibbuf))
+ {
+ memcpy(info.sibbuf, d, dn);
+ info.sibling[0] = info.sibbuf;
+ }
+ if (v && vn < sizeof(info.envbuf))
+ {
+ memcpy(info.envbuf, v, vn);
+ info.env = info.envbuf;
+ }
+ }
+ }
+ if (!info.sibling[0] || streq(info.sibling[0], bin))
+ info.sibling[0] = bin;
+ if (!streq(info.sibling[0], lib))
+ info.sibling[1] = lib;
+ if (!info.env)
+ info.env = "LD_LIBRARY_PATH";
+ info.prefix = astconf("LIBPREFIX", NiL, NiL);
+ info.suffix = astconf("LIBSUFFIX", NiL, NiL);
+ if (streq(info.suffix, ".dll"))
+ info.flags |= DLL_INFO_PREVER;
+ else
+ info.flags |= DLL_INFO_DOTVER;
+ }
+ return &info;
+}
+
+/*
+ * fts version sort order
+ * higher versions appear first
+ */
+
+static int
+vercmp(FTSENT* const* ap, FTSENT* const* bp)
+{
+ register unsigned char* a = (unsigned char*)(*ap)->fts_name;
+ register unsigned char* b = (unsigned char*)(*bp)->fts_name;
+ register int n;
+ register int m;
+ char* e;
+
+ for (;;)
+ {
+ if (isdigit(*a) && isdigit(*b))
+ {
+ m = strtol((char*)a, &e, 10);
+ a = (unsigned char*)e;
+ n = strtol((char*)b, &e, 10);
+ b = (unsigned char*)e;
+ if (n -= m)
+ return n;
+ }
+ if (n = *a - *b)
+ return n;
+ if (!*a++)
+ return *b ? 0 : -1;
+ if (!*b++)
+ return 1;
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * open a scan stream
+ */
+
+Dllscan_t*
+dllsopen(const char* lib, const char* name, const char* version)
+{
+ register char* s;
+ register char* t;
+ Dllscan_t* scan;
+ Dllinfo_t* info;
+ Vmalloc_t* vm;
+ int i;
+ int j;
+ int k;
+ char buf[32];
+
+ if (!(vm = vmopen(Vmdcheap, Vmlast, 0)))
+ return 0;
+ if (lib && *lib && (*lib != '-' || *(lib + 1)))
+ {
+ /*
+ * grab the local part of the library id
+ */
+
+ if (s = strrchr(lib, ':'))
+ lib = (const char*)(s + 1);
+ i = 2 * sizeof(char**) + strlen(lib) + 5;
+ }
+ else
+ {
+ lib = 0;
+ i = 0;
+ }
+ if (version && (!*version || *version == '-' && !*(version + 1)))
+ version = 0;
+ if (!(scan = vmnewof(vm, 0, Dllscan_t, 1, i)) || !(scan->tmp = sfstropen()))
+ {
+ vmclose(vm);
+ return 0;
+ }
+ scan->vm = vm;
+ info = dllinfo();
+ scan->flags = info->flags;
+ if (lib)
+ {
+ scan->lib = (char**)(scan + 1);
+ s = *scan->lib = (char*)(scan->lib + 2);
+ sfsprintf(s, i, "lib/%s", lib);
+ if (!version && streq(info->suffix, ".dylib"))
+ version = "0.0";
+ }
+ if (!name || !*name || *name == '-' && !*(name + 1))
+ {
+ name = (const char*)"?*";
+ scan->flags |= DLL_MATCH_NAME;
+ }
+ else if (t = strrchr(name, '/'))
+ {
+ if (!(scan->pb = vmnewof(vm, 0, char, t - (char*)name, 2)))
+ goto bad;
+ memcpy(scan->pb, name, t - (char*)name);
+ name = (const char*)(t + 1);
+ }
+ if (name)
+ {
+ i = strlen(name);
+ j = strlen(info->prefix);
+ if (!j || i > j && strneq(name, info->prefix, j))
+ {
+ k = strlen(info->suffix);
+ if (i > k && streq(name + i - k, info->suffix))
+ {
+ i -= j + k;
+ if (!(t = vmnewof(vm, 0, char, i, 1)))
+ goto bad;
+ memcpy(t, name + j, i);
+ t[i] = 0;
+ name = (const char*)t;
+ }
+ }
+ if (!version)
+ for (t = (char*)name; *t; t++)
+ if ((*t == '-' || *t == '.' || *t == '?') && isdigit(*(t + 1)))
+ {
+ if (*t != '-')
+ scan->flags |= DLL_MATCH_VERSION;
+ version = t + 1;
+ if (!(s = vmnewof(vm, 0, char, t - (char*)name, 1)))
+ goto bad;
+ memcpy(s, name, t - (char*)name);
+ name = (const char*)s;
+ break;
+ }
+ }
+ if (!version)
+ {
+ scan->flags |= DLL_MATCH_VERSION;
+ sfsprintf(scan->nam, sizeof(scan->nam), "%s%s%s", info->prefix, name, info->suffix);
+ }
+ else if (scan->flags & DLL_INFO_PREVER)
+ {
+ sfprintf(scan->tmp, "%s%s", info->prefix, name);
+ for (s = (char*)version; *s; s++)
+ if (isdigit(*s))
+ sfputc(scan->tmp, *s);
+ sfprintf(scan->tmp, "%s", info->suffix);
+ if (!(s = sfstruse(scan->tmp)))
+ goto bad;
+ sfsprintf(scan->nam, sizeof(scan->nam), "%s", s);
+ }
+ else
+ sfsprintf(scan->nam, sizeof(scan->nam), "%s%s%s.%s", info->prefix, name, info->suffix, version);
+ if (scan->flags & (DLL_MATCH_NAME|DLL_MATCH_VERSION))
+ {
+ if (scan->flags & DLL_INFO_PREVER)
+ {
+ if (!version)
+ version = "*([0-9_])";
+ else
+ {
+ t = buf;
+ for (s = (char*)version; *s; s++)
+ if (isdigit(*s) && t < &buf[sizeof(buf)-1])
+ *t++ = *s;
+ *t = 0;
+ version = (const char*)buf;
+ }
+ sfsprintf(scan->pat, sizeof(scan->pat), "%s%s%s%s", info->prefix, name, version, info->suffix);
+ }
+ else if (version)
+ sfsprintf(scan->pat, sizeof(scan->pat), "%s%s@(%s([-.])%s%s|%s.%s)", info->prefix, name, strchr(version, '.') ? "@" : "?", version, info->suffix, info->suffix, version);
+ else
+ {
+ version = "*([0-9.])";
+ sfsprintf(scan->pat, sizeof(scan->pat), "%s%s@(?([-.])%s%s|%s%s)", info->prefix, name, version, info->suffix, info->suffix, version);
+ }
+ }
+ scan->sp = scan->sb = (scan->lib ? scan->lib : info->sibling);
+ scan->prelen = strlen(info->prefix);
+ scan->suflen = strlen(info->suffix);
+ return scan;
+ bad:
+ dllsclose(scan);
+ return 0;
+}
+
+/*
+ * close a scan stream
+ */
+
+int
+dllsclose(Dllscan_t* scan)
+{
+ if (!scan)
+ return -1;
+ if (scan->fts)
+ fts_close(scan->fts);
+ if (scan->dict)
+ dtclose(scan->dict);
+ if (scan->tmp)
+ sfclose(scan->tmp);
+ if (scan->vm)
+ vmclose(scan->vm);
+ return 0;
+}
+
+/*
+ * return the next scan stream entry
+ */
+
+Dllent_t*
+dllsread(register Dllscan_t* scan)
+{
+ register char* p;
+ register char* b;
+ register char* t;
+ register Uniq_t* u;
+ register int n;
+ register int m;
+
+ if (scan->flags & DLL_MATCH_DONE)
+ return 0;
+ again:
+ do
+ {
+ while (!scan->ent || !(scan->ent = scan->ent->fts_link))
+ {
+ if (scan->fts)
+ {
+ fts_close(scan->fts);
+ scan->fts = 0;
+ }
+ if (!scan->pb)
+ scan->pb = pathbin();
+ else if (!*scan->sp)
+ {
+ scan->sp = scan->sb;
+ if (!*scan->pe++)
+ return 0;
+ scan->pb = scan->pe;
+ }
+ for (p = scan->pp = scan->pb; *p && *p != ':'; p++)
+ if (*p == '/')
+ scan->pp = p;
+ scan->pe = p;
+ if (*scan->sp == bin)
+ scan->off = sfprintf(scan->tmp, "%-.*s", scan->pe - scan->pb, scan->pb);
+ else
+ scan->off = sfprintf(scan->tmp, "%-.*s/%s", scan->pp - scan->pb, scan->pb, *scan->sp);
+ scan->sp++;
+ if (!(scan->flags & DLL_MATCH_NAME))
+ {
+ sfprintf(scan->tmp, "/%s", scan->nam);
+ if (!(p = sfstruse(scan->tmp)))
+ return 0;
+ if (!eaccess(p, R_OK))
+ {
+ b = scan->nam;
+ goto found;
+ }
+ if (errno != ENOENT)
+ continue;
+ }
+ if (scan->flags & (DLL_MATCH_NAME|DLL_MATCH_VERSION))
+ {
+ sfstrseek(scan->tmp, scan->off, SEEK_SET);
+ if (!(t = sfstruse(scan->tmp)))
+ return 0;
+ if ((scan->fts = fts_open((char**)t, FTS_LOGICAL|FTS_NOPOSTORDER|FTS_ONEPATH, vercmp)) && (scan->ent = fts_read(scan->fts)) && (scan->ent = fts_children(scan->fts, FTS_NOSTAT)))
+ break;
+ }
+ }
+ } while (!strmatch(scan->ent->fts_name, scan->pat));
+ b = scan->ent->fts_name;
+ sfstrseek(scan->tmp, scan->off, SEEK_SET);
+ sfprintf(scan->tmp, "/%s", b);
+ if (!(p = sfstruse(scan->tmp)))
+ return 0;
+ found:
+ b = scan->buf + sfsprintf(scan->buf, sizeof(scan->buf), "%s", b + scan->prelen);
+ if (!(scan->flags & DLL_INFO_PREVER))
+ while (b > scan->buf)
+ {
+ if (!isdigit(*(b - 1)) && *(b - 1) != '.')
+ break;
+ b--;
+ }
+ b -= scan->suflen;
+ if (b > (scan->buf + 2) && (*(b - 1) == 'g' || *(b - 1) == 'O') && *(b - 2) == '-')
+ b -= 2;
+ n = m = 0;
+ for (t = b; t > scan->buf; t--)
+ if (isdigit(*(t - 1)))
+ n = 1;
+ else if (*(t - 1) != m)
+ {
+ if (*(t - 1) == '.' || *(t - 1) == '-' || *(t - 1) == '_')
+ {
+ n = 1;
+ if (m)
+ {
+ m = -1;
+ t--;
+ break;
+ }
+ m = *(t - 1);
+ }
+ else
+ break;
+ }
+ if (n)
+ {
+ if (isdigit(t[0]) && isdigit(t[1]) && !isdigit(t[2]))
+ n = (t[0] - '0') * 10 + (t[1] - '0');
+ else if (isdigit(t[1]) && isdigit(t[2]) && !isdigit(t[3]))
+ n = (t[1] - '0') * 10 + (t[2] - '0');
+ else
+ n = 0;
+ if (n && !(n & (n - 1)))
+ {
+ if (!isdigit(t[0]))
+ t++;
+ m = *(t += 2);
+ }
+ if (m || (scan->flags & DLL_INFO_PREVER))
+ b = t;
+ }
+ *b = 0;
+ if (!*(b = scan->buf))
+ goto again;
+ if (scan->uniq)
+ {
+ if (!scan->dict)
+ {
+ scan->disc.key = offsetof(Uniq_t, name);
+ scan->disc.size = 0;
+ scan->disc.link = offsetof(Uniq_t, link);
+ if (!(scan->dict = dtopen(&scan->disc, Dtset)))
+ return 0;
+ dtinsert(scan->dict, scan->uniq);
+ }
+ if (dtmatch(scan->dict, b))
+ goto again;
+ if (!(u = vmnewof(scan->vm, 0, Uniq_t, 1, strlen(b))))
+ return 0;
+ strcpy(u->name, b);
+ dtinsert(scan->dict, u);
+ }
+ else if (!(scan->flags & DLL_MATCH_NAME))
+ scan->flags |= DLL_MATCH_DONE;
+ else if (!(scan->uniq = vmnewof(scan->vm, 0, Uniq_t, 1, strlen(b))))
+ return 0;
+ else
+ strcpy(scan->uniq->name, b);
+ scan->entry.name = b;
+ scan->entry.path = p;
+ return &scan->entry;
+}
diff --git a/src/lib/libdll/features/dll b/src/lib/libdll/features/dll
new file mode 100644
index 0000000..691012f
--- /dev/null
+++ b/src/lib/libdll/features/dll
@@ -0,0 +1,263 @@
+set prototyped
+hdr dl,dlfcn,dll,rld_interface,mach-o/dyld
+sys ldr
+lib dlopen -ldl
+lib dllload,loadbind,shl_load -ldl
+tst dll_DYNAMIC link{
+ #include <sys/types.h>
+ #include <link.h>
+ extern struct link_dynamic _DYNAMIC;
+ int
+ main()
+ {
+ return _DYNAMIC.ld_version;
+ }
+}end
+tst run{
+ lib=
+ for d in /shlib /usr/shlib /lib /usr/lib
+ do if test -d $d
+ then for s in "*.*" "*[!a]*"
+ do for b in libc
+ do for i in $d/$b.$s
+ do if test -f $i
+ then lib=$i
+ fi
+ done
+ case $lib in
+ ?*) break 3 ;;
+ esac
+ done
+ done
+ fi
+ done
+ case $lib in
+ *.[0-9]*.[0-9]*)
+ i=`echo $lib | sed 's,\([^0-9]*[0-9]*\).*,\1,'`
+ if test -f $i
+ then lib=$i
+ fi
+ ;;
+ esac
+ # some run time linkers barf with /lib/xxx if
+ # /usr/lib/xxx is there
+ case $lib in
+ /usr*) ;;
+ *) if test -f /usr$lib
+ then lib=/usr$lib
+ fi
+ ;;
+ esac
+ case $lib in
+ "") lib=/lib/libc.so.1 ;;
+ esac
+ case $lib in
+ /usr/lib/*)
+ case `package` in
+ sgi.mips3)
+ abi=/lib32
+ ;;
+ sgi.mips4)
+ abi=/lib64
+ ;;
+ *) abi=
+ ;;
+ esac
+ case $abi in
+ ?*) if test -d $abi
+ then lib=`echo $lib | sed 's,/usr/lib/,,'`
+ lib=$abi/$lib
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ echo "#define _DLL_NEXT_PATH \"$lib\""
+}end
+tst - output{
+ #if defined(__MVS__) && !defined(__SUSV3)
+ #define __SUSV3 1
+ #endif
+ #if _hdr_dlfcn && _lib_dlopen
+ #include <dlfcn.h>
+ #endif
+ #if _hdr_rld_interface
+ #include <rld_interface.h>
+ #endif
+ int
+ main()
+ {
+ int i;
+ #if _hdr_rld_interface
+ void* dll;
+ static char* local[] = { "__elf_header", "_call_add_gp_range", "_etext" };
+ #endif
+ printf("\n");
+ printf("#if defined(__MVS__) && !defined(__SUSV3)\n");
+ printf("#define __SUSV3 1\n");
+ printf("#endif\n");
+ #if _hdr_dlfcn && _lib_dlopen
+ printf("#include <dlfcn.h>\n");
+ #endif
+ #ifndef RTLD_LAZY
+ i = 0;
+ printf("\n");
+ printf("#define RTLD_LAZY 1\n");
+ #else
+ i = 1;
+ #endif
+ #ifndef RTLD_NOW
+ if (i)
+ {
+ i = 0;
+ printf("\n");
+ }
+ printf("#define RTLD_NOW 2\n");
+ #endif
+ #ifndef RTLD_GLOBAL
+ if (i)
+ {
+ i = 0;
+ printf("\n");
+ }
+ printf("#define RTLD_GLOBAL 0\n");
+ #endif
+ #ifndef RTLD_LOCAL
+ if (i)
+ {
+ i = 0;
+ printf("\n");
+ }
+ printf("#define RTLD_LOCAL 0\n");
+ #endif
+ #ifndef RTLD_PARENT
+ if (i)
+ {
+ i = 0;
+ printf("\n");
+ }
+ printf("#define RTLD_PARENT 0\n");
+ #endif
+ #if defined(_hdr_mach_o_dyld) && !defined(RTLD_NEXT)
+ if (i)
+ {
+ i = 0;
+ printf("\n");
+ }
+ printf("#define RTLD_NEXT ((void*)16)\n");
+ #endif
+ #if _hdr_rld_interface
+ if (!(dll = dlopen(0, RTLD_LAZY)))
+ i = -1;
+ else
+ {
+ for (i = 0; i < sizeof(local) / sizeof(local[0]); i++)
+ if (dlsym(dll, local[i]))
+ break;
+ if (i >= sizeof(local) / sizeof(local[0]))
+ i = -1;
+ }
+ if (i >= 0)
+ {
+ printf("\n");
+ printf("#define _DLL_RLD_SYM %s\n", local[i]);
+ printf("#define _DLL_RLD_SYM_STR \"%s\"\n", local[i]);
+ printf("#define _DLL_RLD_SYM_TYPE void*\n");
+ }
+ #endif
+ printf("\n");
+ printf("#define DLL_INFO_PREVER 0x0001 /* pre-suffix style version */\n");
+ printf("#define DLL_INFO_DOTVER 0x0002 /* post-suffix style version */\n");
+ printf("\n");
+ printf("typedef unsigned long (*Dll_plugin_version_f)(void);\n");
+ printf("typedef int (*Dllerror_f)(void*, void*, int, ...);\n");
+ printf("\n");
+ printf("typedef struct Dllinfo_s\n");
+ printf("{\n");
+ printf(" char** sibling; /* sibling dirs on $PATH */\n");
+ printf(" char* prefix; /* library name prefix */\n");
+ printf(" char* suffix; /* library name suffix */\n");
+ printf(" char* env; /* library path env var */\n");
+ printf(" int flags; /* DLL_INFO_* flags */\n");
+ printf("#ifdef _DLLINFO_PRIVATE_\n");
+ printf(" _DLLINFO_PRIVATE_\n");
+ printf("#endif\n");
+ printf("} Dllinfo_t;\n");
+ printf("\n");
+ printf("typedef struct Dllnames_s\n");
+ printf("{\n");
+ printf(" char* id;\n");
+ printf(" char* name;\n");
+ printf(" char* base;\n");
+ printf(" char* type;\n");
+ printf(" char* opts;\n");
+ printf(" char* path;\n");
+ printf(" char data[1024];\n");
+ printf("} Dllnames_t;\n");
+ printf("\n");
+ printf("typedef struct Dllent_s\n");
+ printf("{\n");
+ printf(" char* path;\n");
+ printf(" char* name;\n");
+ printf("#ifdef _DLLENT_PRIVATE_\n");
+ printf(" _DLLENT_PRIVATE_\n");
+ printf("#endif\n");
+ printf("} Dllent_t;\n");
+ printf("\n");
+ printf("typedef struct Dllscan_s\n");
+ printf("{\n");
+ printf(" void* pad;\n");
+ printf("#ifdef _DLLSCAN_PRIVATE_\n");
+ printf(" _DLLSCAN_PRIVATE_\n");
+ printf("#endif\n");
+ printf("} Dllscan_t;\n");
+ #if !_hdr_dlfcn || !_lib_dlopen
+ printf("\n");
+ printf("extern void* dlopen(const char*, int);\n");
+ printf("extern void* dlsym(void*, const char*);\n");
+ printf("extern int dlclose(void*);\n");
+ printf("extern char* dlerror(void);\n");
+ #endif
+ printf("\n");
+ printf("#if _BLD_dll && defined(__EXPORT__)\n");
+ printf("#define extern __EXPORT__\n");
+ printf("#endif\n");
+ printf("\n");
+ printf("extern Dllinfo_t* dllinfo(void);\n");
+ printf("extern void* dllplugin(const char*, const char*, const char*, unsigned long, unsigned long*, int, char*, size_t);\n");
+ printf("extern void* dllplug(const char*, const char*, const char*, int, char*, size_t);\n");
+ printf("extern void* dllfind(const char*, const char*, int, char*, size_t);\n");
+ printf("extern Dllnames_t* dllnames(const char*, const char*, Dllnames_t*);\n");
+ printf("extern void* dll_lib(Dllnames_t*, unsigned long, Dllerror_f, void*);\n");
+ printf("extern void* dllmeth(const char*, const char*, unsigned long);\n");
+ printf("extern void* dllopen(const char*, int);\n");
+ printf("extern void* dllnext(int);\n");
+ printf("extern void* dlllook(void*, const char*);\n");
+ printf("extern int dllcheck(void*, const char*, unsigned long, unsigned long*);\n");
+ printf("extern unsigned long dllversion(void*, const char*);\n");
+ printf("extern char* dllerror(int);\n");
+ #if _hdr_rld_interface
+ if (i >= 0)
+ {
+ printf("\n");
+ printf("extern void* _dll_next(int, _DLL_RLD_SYM_TYPE*);\n");
+ printf("#define dllnext(f) _dll_next(f, &_DLL_RLD_SYM)\n");
+ }
+ #endif
+ printf("\n");
+ printf("extern Dllscan_t* dllsopen(const char*, const char*, const char*);\n");
+ printf("extern Dllent_t* dllsread(Dllscan_t*);\n");
+ printf("extern int dllsclose(Dllscan_t*);\n");
+ printf("\n");
+ printf("#undef extern\n");
+ #if _hdr_rld_interface
+ if (i >= 0)
+ {
+ printf("\n");
+ printf("extern _DLL_RLD_SYM_TYPE _DLL_RLD_SYM;\n");
+ }
+ #endif
+ printf("\n");
+ return 0;
+ }
+}end
diff --git a/src/lib/libsum/Makefile b/src/lib/libsum/Makefile
new file mode 100644
index 0000000..31de0de
--- /dev/null
+++ b/src/lib/libsum/Makefile
@@ -0,0 +1,11 @@
+:PACKAGE: ast
+
+LICENSE = since=1996,author=gsf
+
+CCFLAGS = $(CC.OPTIMIZE) $(CC.PIC)
+
+sum 1.0 :LIBRARY: sum.h sumlib.c -lmd
+
+$(INCLUDEDIR) :INSTALLPROTO: sum.h
+
+:: RELEASE
diff --git a/src/lib/libsum/Mamfile b/src/lib/libsum/Mamfile
new file mode 100644
index 0000000..c52e277
--- /dev/null
+++ b/src/lib/libsum/Mamfile
@@ -0,0 +1,245 @@
+info mam static 00000 1994-07-17 make (AT&T Research) 5.7 2012-02-29
+setv INSTALLROOT ../../..
+setv PACKAGE_ast_INCLUDE ${INSTALLROOT}/include/ast
+setv PACKAGE_ast_LIB ${INSTALLROOT}/lib
+setv PACKAGEROOT ../../../../..
+setv AR ${mam_cc_AR} ${mam_cc_AR_ARFLAGS}
+setv ARFLAGS rc
+setv AS as
+setv ASFLAGS
+setv CC cc
+setv mam_cc_FLAGS ${mam_cc_PIC}
+setv CCFLAGS ${-debug-symbols?1?${mam_cc_DEBUG} -D_BLD_DEBUG?${mam_cc_OPTIMIZE}?}
+setv CCLDFLAGS ${-strip-symbols?1?${mam_cc_LD_STRIP}??}
+setv COTEMP $$
+setv CPIO cpio
+setv CPIOFLAGS
+setv CPP "${CC} -E"
+setv F77 f77
+setv HOSTCC ${CC}
+setv IGNORE
+setv LD ld
+setv LDFLAGS
+setv LEX lex
+setv LEXFLAGS
+setv LPR lpr
+setv LPRFLAGS
+setv M4FLAGS
+setv NMAKE nmake
+setv NMAKEFLAGS
+setv PR pr
+setv PRFLAGS
+setv SHELL /bin/sh
+setv SILENT
+setv TAR tar
+setv YACC yacc
+setv YACCFLAGS -d
+make ${PACKAGEROOT}/lib/package/ast.lic
+done ${PACKAGEROOT}/lib/package/ast.lic
+make install
+make sum
+make libsum.a archive
+make sum.req
+exec - set -
+exec - echo 'int main(){return 0;}' > 1.${COTEMP}.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -c 1.${COTEMP}.c &&
+exec - x=`${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l'*' 2>&1 | sed -e 's/[][()+@?]/#/g' || :` &&
+exec - {
+exec - case "" in
+exec - *?) echo " " ;;
+exec - esac
+exec - for i in sum md ast
+exec - do case $i in
+exec - "sum"|sum)
+exec - ;;
+exec - *) if test -f ${INSTALLROOT}/lib/lib/$i
+exec - then y=`cat ${INSTALLROOT}/lib/lib/$i`
+exec - case $y in
+exec - *-?*) echo "" $y ;;
+exec - esac
+exec - continue
+exec - elif test ! -f ${INSTALLROOT}/lib/lib$i.a
+exec - then case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -L${INSTALLROOT}/lib ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) case `{ ${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} -o 1.${COTEMP}.x 1.${COTEMP}.o -l$i 2>&1 || echo '' $x ;} | sed -e 's/[][()+@?]/#/g' || :` in
+exec - *$x*) continue ;;
+exec - esac
+exec - ;;
+exec - esac
+exec - fi
+exec - ;;
+exec - esac
+exec - echo " -l$i"
+exec - done
+exec - } > sum.req
+exec - rm -f 1.${COTEMP}.*
+done sum.req generated
+make sumlib.o
+make sumlib.c
+make sum-sha2.c implicit
+make ${PACKAGE_ast_INCLUDE}/endian.h implicit
+make ${PACKAGE_ast_INCLUDE}/bytesex.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_map.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_common.h dontcare
+done ${PACKAGE_ast_INCLUDE}/bytesex.h dontcare
+done ${PACKAGE_ast_INCLUDE}/endian.h dontcare
+done sum-sha2.c dontcare
+make sum-sha1.c implicit
+done sum-sha1.c dontcare
+make sum-md5.c implicit
+done sum-md5.c dontcare
+make sum-lmd.c implicit
+make sha2.h implicit
+done sha2.h dontcare virtual
+make sha1.h implicit
+done sha1.h dontcare virtual
+make md5.h implicit
+done md5.h dontcare virtual
+make md4.h implicit
+done md4.h dontcare virtual
+done sum-lmd.c dontcare
+make sum-prng.c implicit
+make ${PACKAGE_ast_INCLUDE}/fnv.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+make ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+make ${INSTALLROOT}/include/prototyped.h implicit
+done ${INSTALLROOT}/include/prototyped.h dontcare
+done ${PACKAGE_ast_INCLUDE}/prototyped.h dontcare
+done ${PACKAGE_ast_INCLUDE}/fnv.h
+done sum-prng.c
+make sum-crc.c implicit
+done sum-crc.c
+make sum-bsd.c implicit
+done sum-bsd.c
+make sum-ast4.c implicit
+done sum-ast4.c
+make sum-att.c implicit
+done sum-att.c
+make FEATURE/sum implicit
+meta FEATURE/sum features/%>FEATURE/% features/sum sum
+make features/sum
+done features/sum
+bind -last
+exec - iffe -v -c '${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS} ' ref ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libast} : run features/sum
+done FEATURE/sum generated
+make ${PACKAGE_ast_INCLUDE}/hashpart.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/hashpart.h
+make ${PACKAGE_ast_INCLUDE}/swap.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/swap.h
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+make sum.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_api.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_api.h dontcare
+make ${PACKAGE_ast_INCLUDE}/vmalloc.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+make ${PACKAGE_ast_INCLUDE}/regex.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wchar.h implicit
+make ${PACKAGE_ast_INCLUDE}/wctype.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_wctype.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wctype.h dontcare
+done ${PACKAGE_ast_INCLUDE}/wctype.h dontcare
+make ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_stdio.h implicit
+make ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
+done ${PACKAGE_ast_INCLUDE}/sfio_s.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_stdio.h dontcare
+done ${PACKAGE_ast_INCLUDE}/stdio.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/stdio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_wchar.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/regex.h dontcare
+make ${PACKAGE_ast_INCLUDE}/getopt.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_getopt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_getopt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/getopt.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_map.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_botch.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_botch.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_limits.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_limits.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_fcntl.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_fs.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_fs.h dontcare
+done ${PACKAGE_ast_INCLUDE}/ast_fcntl.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_getopt.h implicit
+make ${PACKAGE_ast_INCLUDE}/ast_sys.h implicit
+prev ${PACKAGE_ast_INCLUDE}/getopt.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+prev ${PACKAGE_ast_INCLUDE}/endian.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_sys.h dontcare
+make ${PACKAGE_ast_INCLUDE}/ast_lib.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_lib.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast_std.h dontcare
+done ${PACKAGE_ast_INCLUDE}/vmalloc.h dontcare
+make ${PACKAGE_ast_INCLUDE}/sfio.h implicit
+prev ${PACKAGE_ast_INCLUDE}/sfio_s.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_common.h implicit
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+done ${PACKAGE_ast_INCLUDE}/sfio.h dontcare
+prev ${PACKAGE_ast_INCLUDE}/ast_std.h implicit
+prev ${PACKAGE_ast_INCLUDE}/prototyped.h implicit
+done ${PACKAGE_ast_INCLUDE}/ast.h dontcare
+done sum.h
+done sumlib.c
+meta sumlib.o %.c>%.o sumlib.c sumlib
+prev sumlib.c
+exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -I${PACKAGE_ast_INCLUDE} -D_PACKAGE_ast -c sumlib.c
+done sumlib.o generated
+exec - ${AR} rc libsum.a sumlib.o
+exec - (ranlib libsum.a) >/dev/null 2>&1 || true
+done libsum.a generated
+done sum virtual
+prev libsum.a archive
+make ${INSTALLROOT}/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib
+exec - then mkdir -p ${INSTALLROOT}/lib
+exec - fi
+done ${INSTALLROOT}/lib generated
+make ${INSTALLROOT}/lib/libsum.a archive
+prev ${INSTALLROOT}/lib
+prev libsum.a archive
+exec - test '' = 'libsum.a' || ${STDCMP} 2>/dev/null -s libsum.a ${INSTALLROOT}/lib/libsum.a || { ${STDMV} ${INSTALLROOT}/lib/libsum.a ${INSTALLROOT}/lib/libsum.a.old 2>/dev/null || true; ${STDCP} libsum.a ${INSTALLROOT}/lib/libsum.a ;}
+exec - (ranlib ${INSTALLROOT}/lib/libsum.a) >/dev/null 2>&1 || true
+done ${INSTALLROOT}/lib/libsum.a generated
+make ${INSTALLROOT}/lib/lib
+exec - if silent test ! -d ${INSTALLROOT}/lib/lib
+exec - then mkdir -p ${INSTALLROOT}/lib/lib
+exec - fi
+done ${INSTALLROOT}/lib/lib generated
+make ${INSTALLROOT}/lib/lib/sum
+prev ${INSTALLROOT}/lib/lib
+prev sum.req
+exec - test '' = 'sum.req' || ${STDCMP} 2>/dev/null -s sum.req ${INSTALLROOT}/lib/lib/sum || { ${STDMV} ${INSTALLROOT}/lib/lib/sum ${INSTALLROOT}/lib/lib/sum.old 2>/dev/null || true; ${STDCP} sum.req ${INSTALLROOT}/lib/lib/sum ;}
+done ${INSTALLROOT}/lib/lib/sum generated
+make ${PACKAGE_ast_INCLUDE}
+exec - if silent test ! -d ${PACKAGE_ast_INCLUDE}
+exec - then mkdir -p ${PACKAGE_ast_INCLUDE}
+exec - fi
+done ${PACKAGE_ast_INCLUDE} generated
+make ${PACKAGE_ast_INCLUDE}/sum.h
+prev ${PACKAGE_ast_INCLUDE}
+prev sum.h
+exec - proto -p -s -l ${PACKAGEROOT}/lib/package/ast.lic '-o since=1996,author=gsf' sum.h > 1.${COTEMP}.x
+exec - if cmp 2>/dev/null -s ${PACKAGE_ast_INCLUDE}/sum.h 1.${COTEMP}.x
+exec - then rm -f 1.${COTEMP}.x
+exec - else mv 1.${COTEMP}.x ${PACKAGE_ast_INCLUDE}/sum.h
+exec - fi
+done ${PACKAGE_ast_INCLUDE}/sum.h generated
+done install virtual
+make test
+done test dontcare virtual
diff --git a/src/lib/libsum/RELEASE b/src/lib/libsum/RELEASE
new file mode 100644
index 0000000..e8d899a
--- /dev/null
+++ b/src/lib/libsum/RELEASE
@@ -0,0 +1,16 @@
+12-02-29 sum-sha2.c: bitcount[] order reversed to allow a single noalias buffer copy
+09-09-28 sumlib.c: use simple (faster) method name match function
+08-06-05 sum-lmd.c: align context to largest int
+08-05-01 sumlib.c: add some -lmd verification checks
+08-02-11 sum-lmd.c,features/sum: add wrapper for solaris -lmd
+07-10-29 sum.h,sumlib.c: add SUM_LEGACY for legacy output format
+07-09-21 sum-sha1.c: reinstate Steve Reid's public domain implementation
+07-07-26 sumlib.c: drop GPL sum-sha1.c
+05-02-14 sumlib.c: split into sum-*.c
+05-02-14 sum-sha2.c: add SHA { 256 384 512 }
+04-02-29 Makefile: compile with $(CC.PIC) for codexlib/sum $(CC.DLL)
+03-12-16 add { crc prng } generic methods and maps[] to these methods
+03-12-16 sum.h,sumlib.c: add sumdata()
+03-09-29 sumlib.c: fix FNV to use ^ instead of +
+03-04-28 sumlib.c: drop md5 `zeroize' for performance
+ sumlib.c: add FIPS 180-1 SHA-1
diff --git a/src/lib/libsum/features/sum b/src/lib/libsum/features/sum
new file mode 100644
index 0000000..ce15b49
--- /dev/null
+++ b/src/lib/libsum/features/sum
@@ -0,0 +1,4 @@
+lib MD4Init md4.h -lmd
+lib MD5Init md5.h -lmd
+lib SHA1Init sha1.h -lmd
+lib SHA2Init sha2.h -lmd
diff --git a/src/lib/libsum/sum-ast4.c b/src/lib/libsum/sum-ast4.c
new file mode 100644
index 0000000..763b18a
--- /dev/null
+++ b/src/lib/libsum/sum-ast4.c
@@ -0,0 +1,120 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1996-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * ast4
+ */
+
+#define ast4_description \
+ "The \bast\b 128 bit PRNG hash generated by catenating 4 separate 32 \
+ bit PNRG hashes. The block count is not printed."
+#define ast4_options 0
+#define ast4_match "ast4|32x4|tw"
+#define ast4_done long_done
+#define ast4_scale 0
+
+typedef struct Ast4_sum_s
+{
+ uint32_t sum0;
+ uint32_t sum1;
+ uint32_t sum2;
+ uint32_t sum3;
+} Ast4_sum_t;
+
+typedef struct Ast4_s
+{
+ _SUM_PUBLIC_
+ _SUM_PRIVATE_
+ Ast4_sum_t cur;
+ Ast4_sum_t tot;
+ unsigned char buf[sizeof(Ast4_sum_t)];
+} Ast4_t;
+
+static int
+ast4_init(Sum_t* p)
+{
+ register Ast4_t* a = (Ast4_t*)p;
+
+ a->tot.sum0 ^= a->cur.sum0;
+ a->cur.sum0 = 0;
+ a->tot.sum1 ^= a->cur.sum1;
+ a->cur.sum1 = 0;
+ a->tot.sum2 ^= a->cur.sum2;
+ a->cur.sum2 = 0;
+ a->tot.sum3 ^= a->cur.sum3;
+ a->cur.sum3 = 0;
+ return 0;
+}
+
+static Sum_t*
+ast4_open(const Method_t* method, const char* name)
+{
+ Ast4_t* p;
+
+ if (p = newof(0, Ast4_t, 1, 0))
+ {
+ p->method = (Method_t*)method;
+ p->name = name;
+ }
+ return (Sum_t*)p;
+}
+
+static int
+ast4_block(Sum_t* p, const void* s, size_t n)
+{
+ register Ast4_sum_t* a = &((Ast4_t*)p)->cur;
+ register unsigned char* b = (unsigned char*)s;
+ register unsigned char* e = b + n;
+ register int c;
+
+ while (b < e)
+ {
+ c = *b++;
+ a->sum0 = a->sum0 * 0x63c63cd9 + 0x9c39c33d + c;
+ a->sum1 = a->sum1 * 0x00000011 + 0x00017cfb + c;
+ a->sum2 = a->sum2 * 0x12345679 + 0x3ade68b1 + c;
+ a->sum3 = a->sum3 * 0xf1eac01d + 0xcafe10af + c;
+ }
+ return 0;
+}
+
+static int
+ast4_print(Sum_t* p, Sfio_t* sp, int flags, size_t scale)
+{
+ register Ast4_sum_t* a;
+
+ a = (flags & SUM_TOTAL) ? &((Ast4_t*)p)->tot : &((Ast4_t*)p)->cur;
+ sfprintf(sp, "%06..64u%06..64u%06..64u%06..64u", a->sum0, a->sum1, a->sum2, a->sum3);
+ return 0;
+}
+
+static int
+ast4_data(Sum_t* p, Sumdata_t* data)
+{
+ data->size = sizeof(((Ast4_t*)p)->cur);
+ data->num = 0;
+#if _ast_intswap
+ swapmem(_ast_intswap, data->buf = ((Ast4_t*)p)->buf, &((Ast4_t*)p)->cur, sizeof(((Ast4_t*)p)->cur));
+#else
+ data->buf = &((Ast4_t*)p)->cur;
+#endif
+ return 0;
+}
diff --git a/src/lib/libsum/sum-att.c b/src/lib/libsum/sum-att.c
new file mode 100644
index 0000000..eb4b44c
--- /dev/null
+++ b/src/lib/libsum/sum-att.c
@@ -0,0 +1,60 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1996-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * att
+ */
+
+#define att_description \
+ "The system 5 release 4 checksum. This is the default for \bsum\b \
+ when \bgetconf UNIVERSE\b is \batt\b. This is the only true sum; \
+ all of the other methods are order dependent."
+#define att_options 0
+#define att_match "att|sys5|s5|default"
+#define att_open long_open
+#define att_init long_init
+#define att_print long_print
+#define att_data long_data
+#define att_scale 512
+
+static int
+att_block(register Sum_t* p, const void* s, size_t n)
+{
+ register uint32_t c = ((Integral_t*)p)->sum;
+ register unsigned char* b = (unsigned char*)s;
+ register unsigned char* e = b + n;
+
+ while (b < e)
+ c += *b++;
+ ((Integral_t*)p)->sum = c;
+ return 0;
+}
+
+static int
+att_done(Sum_t* p)
+{
+ register uint32_t c = ((Integral_t*)p)->sum;
+
+ c = (c & 0xffff) + ((c >> 16) & 0xffff);
+ c = (c & 0xffff) + (c >> 16);
+ ((Integral_t*)p)->sum = c & 0xffff;
+ return short_done(p);
+}
diff --git a/src/lib/libsum/sum-bsd.c b/src/lib/libsum/sum-bsd.c
new file mode 100644
index 0000000..e54c00e
--- /dev/null
+++ b/src/lib/libsum/sum-bsd.c
@@ -0,0 +1,48 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1996-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * bsd
+ */
+
+#define bsd_description \
+ "The BSD checksum."
+#define bsd_options 0
+#define bsd_match "bsd|ucb"
+#define bsd_open long_open
+#define bsd_init long_init
+#define bsd_done short_done
+#define bsd_print long_print
+#define bsd_data long_data
+#define bsd_scale 1024
+
+static int
+bsd_block(register Sum_t* p, const void* s, size_t n)
+{
+ register uint32_t c = ((Integral_t*)p)->sum;
+ register unsigned char* b = (unsigned char*)s;
+ register unsigned char* e = b + n;
+
+ while (b < e)
+ c = ((c >> 1) + *b++ + ((c & 01) ? 0x8000 : 0)) & 0xffff;
+ ((Integral_t*)p)->sum = c;
+ return 0;
+}
diff --git a/src/lib/libsum/sum-crc.c b/src/lib/libsum/sum-crc.c
new file mode 100644
index 0000000..371cd99
--- /dev/null
+++ b/src/lib/libsum/sum-crc.c
@@ -0,0 +1,191 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1996-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * crc
+ */
+
+#define crc_description \
+ "32 bit CRC (cyclic redundancy check)."
+#define crc_options "\
+[+polynomial?The 32 bit crc polynomial bitmask with implicit bit 32.]:[mask:=0xedb88320]\
+[+done?XOR the final crc value with \anumber\a. 0xffffffff is used if \anumber\a is omitted.]:?[number:=0]\
+[+init?The initial crc value. 0xffffffff is used if \anumber\a is omitted.]:?[number:=0]\
+[+rotate?XOR each input character with the high order crc byte (instead of the low order).]\
+[+size?Include the total number of bytes in the crc. \anumber\a, if specified, is first XOR'd into the size.]:?[number:=0]\
+"
+#define crc_match "crc"
+#define crc_open crc_open
+#define crc_print long_print
+#define crc_data long_data
+#define crc_scale 0
+
+typedef uint32_t Crcnum_t;
+
+typedef struct Crc_s
+{
+ _SUM_PUBLIC_
+ _SUM_PRIVATE_
+ _INTEGRAL_PRIVATE_
+ Crcnum_t init;
+ Crcnum_t done;
+ Crcnum_t xorsize;
+ Crcnum_t tab[256];
+ unsigned int addsize;
+ unsigned int rotate;
+} Crc_t;
+
+#define CRC(p,s,c) (s = (s >> 8) ^ (p)->tab[(s ^ (c)) & 0xff])
+#define CRCROTATE(p,s,c) (s = (s << 8) ^ (p)->tab[((s >> 24) ^ (c)) & 0xff])
+
+static Sum_t*
+crc_open(const Method_t* method, const char* name)
+{
+ register Crc_t* sum;
+ register const char* s;
+ register const char* t;
+ register const char* v;
+ register int i;
+ register int j;
+ Crcnum_t polynomial;
+ Crcnum_t x;
+
+ if (sum = newof(0, Crc_t, 1, 0))
+ {
+ sum->method = (Method_t*)method;
+ sum->name = name;
+ }
+ polynomial = 0xedb88320;
+ s = name;
+ while (*(t = s))
+ {
+ for (t = s, v = 0; *s && *s != '-'; s++)
+ if (*s == '=' && !v)
+ v = s;
+ i = (v ? v : s) - t;
+ if (isdigit(*t) || v && i >= 4 && strneq(t, "poly", 4) && (t = v + 1))
+ polynomial = strtoul(t, NiL, 0);
+ else if (strneq(t, "done", i))
+ sum->done = v ? strtoul(v + 1, NiL, 0) : ~sum->done;
+ else if (strneq(t, "init", i))
+ sum->init = v ? strtoul(v + 1, NiL, 0) : ~sum->init;
+ else if (strneq(t, "rotate", i))
+ sum->rotate = 1;
+ else if (strneq(t, "size", i))
+ {
+ sum->addsize = 1;
+ if (v)
+ sum->xorsize = strtoul(v + 1, NiL, 0);
+ }
+ if (*s == '-')
+ s++;
+ }
+ if (sum->rotate)
+ {
+ Crcnum_t t;
+ Crcnum_t p[8];
+
+ p[0] = polynomial;
+ for (i = 1; i < 8; i++)
+ p[i] = (p[i-1] << 1) ^ ((p[i-1] & 0x80000000) ? polynomial : 0);
+ for (i = 0; i < elementsof(sum->tab); i++)
+ {
+ t = 0;
+ x = i;
+ for (j = 0; j < 8; j++)
+ {
+ if (x & 1)
+ t ^= p[j];
+ x >>= 1;
+ }
+ sum->tab[i] = t;
+ }
+ }
+ else
+ {
+ for (i = 0; i < elementsof(sum->tab); i++)
+ {
+ x = i;
+ for (j = 0; j < 8; j++)
+ x = (x>>1) ^ ((x & 1) ? polynomial : 0);
+ sum->tab[i] = x;
+ }
+ }
+ return (Sum_t*)sum;
+}
+
+static int
+crc_init(Sum_t* p)
+{
+ Crc_t* sum = (Crc_t*)p;
+
+ sum->sum = sum->init;
+ return 0;
+}
+
+static int
+crc_block(Sum_t* p, const void* s, size_t n)
+{
+ Crc_t* sum = (Crc_t*)p;
+ register Crcnum_t c = sum->sum;
+ register unsigned char* b = (unsigned char*)s;
+ register unsigned char* e = b + n;
+
+ if (sum->rotate)
+ while (b < e)
+ CRCROTATE(sum, c, *b++);
+ else
+ while (b < e)
+ CRC(sum, c, *b++);
+ sum->sum = c;
+ return 0;
+}
+
+static int
+crc_done(Sum_t* p)
+{
+ register Crc_t* sum = (Crc_t*)p;
+ register Crcnum_t c;
+ register uintmax_t n;
+ int i;
+ int j;
+
+ c = sum->sum;
+ if (sum->addsize)
+ {
+ n = sum->size ^ sum->xorsize;
+ if (sum->rotate)
+ while (n)
+ {
+ CRCROTATE(sum, c, n);
+ n >>= 8;
+ }
+ else
+ for (i = 0, j = 32; i < 4; i++)
+ {
+ j -= 8;
+ CRC(sum, c, n >> j);
+ }
+ }
+ sum->sum = c ^ sum->done;
+ sum->total_sum ^= (sum->sum &= 0xffffffff);
+ return 0;
+}
diff --git a/src/lib/libsum/sum-lmd.c b/src/lib/libsum/sum-lmd.c
new file mode 100644
index 0000000..b733a9f
--- /dev/null
+++ b/src/lib/libsum/sum-lmd.c
@@ -0,0 +1,330 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1996-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * sum(3) wrapper for solaris -lmd message digest library
+ */
+
+typedef void (*Lmd_init_f)(void*);
+typedef void (*Lmd_update_f)(void*, const void*, size_t);
+typedef void (*Lmd_final_f)(unsigned char*, void*);
+
+#define _SUM_LMD_ \
+ _SUM_PUBLIC_ \
+ _SUM_PRIVATE_ \
+ Lmd_init_f initf; \
+ Lmd_update_f updatef; \
+ Lmd_final_f finalf; \
+ unsigned int datasize; \
+ unsigned char total[64]; \
+ unsigned char data[64];
+
+typedef struct Lmd_s
+{
+ _SUM_LMD_
+ struct
+ {
+ uintmax_t context;
+ } context;
+} Lmd_t;
+
+static int
+lmd_init(Sum_t* p)
+{
+ Lmd_t* lmd = (Lmd_t*)p;
+
+ (*lmd->initf)(&lmd->context);
+ return 0;
+}
+
+static int
+lmd_block(Sum_t* p, const void* s, size_t n)
+{
+ Lmd_t* lmd = (Lmd_t*)p;
+
+ (*lmd->updatef)(&lmd->context, s, n);
+ return 0;
+}
+
+static int
+lmd_done(Sum_t* p)
+{
+ register Lmd_t* lmd = (Lmd_t*)p;
+ register int i;
+
+ (*lmd->finalf)(lmd->data, &lmd->context);
+ for (i = 0; i < lmd->datasize; i++)
+ lmd->total[i] ^= lmd->data[i];
+ return 0;
+}
+
+static int
+lmd_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
+{
+ register Lmd_t* lmd = (Lmd_t*)p;
+ register unsigned char* d;
+ register int i;
+
+ d = (flags & SUM_TOTAL) ? lmd->total : lmd->data;
+ for (i = 0; i < lmd->datasize; i++)
+ sfprintf(sp, "%02x", d[i]);
+ return 0;
+}
+
+static int
+lmd_data(Sum_t* p, Sumdata_t* data)
+{
+ Lmd_t* lmd = (Lmd_t*)p;
+
+ data->size = lmd->datasize;
+ data->num = 0;
+ data->buf = lmd->data;
+ return 0;
+}
+
+#if _lib_MD4Init && _hdr_md4
+
+#include <md4.h>
+
+#define md4_description "RFC1320 MD4 message digest. Cryptographically weak. The block count is not printed."
+#define md4_options "[+(version)?md4 (solaris -lmd) 2005-07-26]"
+#define md4_match "md4|MD4"
+#define md4_scale 0
+#define md4_init lmd_init
+#define md4_block lmd_block
+#define md4_done lmd_done
+#define md4_print lmd_print
+#define md4_data lmd_data
+
+typedef struct Md4_s
+{
+ _SUM_LMD_
+ MD4_CTX context;
+} Md4_t;
+
+static Sum_t*
+md4_open(const Method_t* method, const char* name)
+{
+ Md4_t* lmd;
+
+ if (lmd = newof(0, Md4_t, 1, 0))
+ {
+ lmd->method = (Method_t*)method;
+ lmd->name = name;
+ lmd->datasize = 16;
+ lmd->initf = (Lmd_init_f)MD4Init;
+ lmd->updatef = (Lmd_update_f)MD4Update;
+ lmd->finalf = (Lmd_final_f)MD4Final;
+ md4_init((Sum_t*)lmd);
+ }
+ return (Sum_t*)lmd;
+}
+
+#endif
+
+#if _lib_MD5Init && _hdr_md5
+
+#include <md5.h>
+
+#define md5_description "RFC1321 MD5 message digest. Cryptographically weak. The block count is not printed."
+#define md5_options "[+(version)?md5 (solaris -lmd) 2005-07-26]"
+#define md5_match "md5|MD5"
+#define md5_scale 0
+#define md5_init lmd_init
+#define md5_block lmd_block
+#define md5_done lmd_done
+#define md5_print lmd_print
+#define md5_data lmd_data
+
+typedef struct Md5_s
+{
+ _SUM_LMD_
+ MD5_CTX context;
+} Md5_t;
+
+static Sum_t*
+md5_open(const Method_t* method, const char* name)
+{
+ Md5_t* lmd;
+
+ if (lmd = newof(0, Md5_t, 1, 0))
+ {
+ lmd->method = (Method_t*)method;
+ lmd->name = name;
+ lmd->datasize = 16;
+ lmd->initf = (Lmd_init_f)MD5Init;
+ lmd->updatef = (Lmd_update_f)MD5Update;
+ lmd->finalf = (Lmd_final_f)MD5Final;
+ md5_init((Sum_t*)lmd);
+ }
+ return (Sum_t*)lmd;
+}
+
+#endif
+
+#if _lib_SHA1Init && _hdr_sha1
+
+#include <sha1.h>
+
+#define sha1_description "RFC3174 / FIPS 180-1 SHA-1 secure hash algorithm 1. Cryptographically weak. The block count is not printed."
+#define sha1_options "[+(version)?sha1 (solaris -lmd) 2005-07-26]"
+#define sha1_match "sha1|SHA1|sha-1|SHA-1"
+#define sha1_scale 0
+#define sha1_init lmd_init
+#define sha1_block lmd_block
+#define sha1_done lmd_done
+#define sha1_print lmd_print
+#define sha1_data lmd_data
+
+typedef struct Sha1_s
+{
+ _SUM_LMD_
+ SHA1_CTX context;
+ unsigned char pad[1024]; /* XXX: who's bug is it? */
+} Sha1_t;
+
+static Sum_t*
+sha1_open(const Method_t* method, const char* name)
+{
+ Sha1_t* lmd;
+
+ if (lmd = newof(0, Sha1_t, 1, 0))
+ {
+ lmd->method = (Method_t*)method;
+ lmd->name = name;
+ lmd->datasize = 20;
+ lmd->initf = (Lmd_init_f)SHA1Init;
+ lmd->updatef = (Lmd_update_f)SHA1Update;
+ lmd->finalf = (Lmd_final_f)SHA1Final;
+ sha1_init((Sum_t*)lmd);
+ }
+ return (Sum_t*)lmd;
+}
+
+#endif
+
+#if _lib_SHA2Init && _hdr_sha2
+
+#include <sha2.h>
+
+#define sha256_description "FIPS 180-2 SHA256 secure hash algorithm. The block count is not printed."
+#define sha256_options "[+(version)?sha256 (solaris -lmd) 2005-07-26]"
+#define sha256_match "sha256|sha-256|SHA256|SHA-256"
+#define sha256_scale 0
+#define sha256_init lmd_init
+#define sha256_block lmd_block
+#define sha256_done lmd_done
+#define sha256_print lmd_print
+#define sha256_data lmd_data
+
+typedef struct Sha256_s
+{
+ _SUM_LMD_
+ SHA256_CTX context;
+} Sha256_t;
+
+static Sum_t*
+sha256_open(const Method_t* method, const char* name)
+{
+ Sha256_t* lmd;
+
+ if (lmd = newof(0, Sha256_t, 1, 0))
+ {
+ lmd->method = (Method_t*)method;
+ lmd->name = name;
+ lmd->datasize = 32;
+ lmd->initf = (Lmd_init_f)SHA256Init;
+ lmd->updatef = (Lmd_update_f)SHA256Update;
+ lmd->finalf = (Lmd_final_f)SHA256Final;
+ sha256_init((Sum_t*)lmd);
+ }
+ return (Sum_t*)lmd;
+}
+
+#define sha384_description "FIPS 180-2 SHA384 secure hash algorithm. The block count is not printed."
+#define sha384_options "[+(version)?sha384 (solaris -lmd) 2005-07-26]"
+#define sha384_match "sha384|sha-384|SHA384|SHA-384"
+#define sha384_scale 0
+#define sha384_init lmd_init
+#define sha384_block lmd_block
+#define sha384_done lmd_done
+#define sha384_print lmd_print
+#define sha384_data lmd_data
+
+typedef struct Sha384_s
+{
+ _SUM_LMD_
+ SHA384_CTX context;
+} Sha384_t;
+
+static Sum_t*
+sha384_open(const Method_t* method, const char* name)
+{
+ Sha384_t* lmd;
+
+ if (lmd = newof(0, Sha384_t, 1, 0))
+ {
+ lmd->method = (Method_t*)method;
+ lmd->name = name;
+ lmd->datasize = 48;
+ lmd->initf = (Lmd_init_f)SHA384Init;
+ lmd->updatef = (Lmd_update_f)SHA384Update;
+ lmd->finalf = (Lmd_final_f)SHA384Final;
+ sha384_init((Sum_t*)lmd);
+ }
+ return (Sum_t*)lmd;
+}
+
+#define sha512_description "FIPS 180-2 SHA512 secure hash algorithm. The block count is not printed."
+#define sha512_options "[+(version)?sha512 (solaris -lmd) 2005-07-26]"
+#define sha512_match "sha512|sha-512|SHA512|SHA-512"
+#define sha512_scale 0
+#define sha512_init lmd_init
+#define sha512_block lmd_block
+#define sha512_done lmd_done
+#define sha512_print lmd_print
+#define sha512_data lmd_data
+
+typedef struct Sha512_s
+{
+ _SUM_LMD_
+ SHA512_CTX context;
+} Sha512_t;
+
+static Sum_t*
+sha512_open(const Method_t* method, const char* name)
+{
+ Sha512_t* lmd;
+
+ if (lmd = newof(0, Sha512_t, 1, 0))
+ {
+ lmd->method = (Method_t*)method;
+ lmd->name = name;
+ lmd->datasize = 64;
+ lmd->initf = (Lmd_init_f)SHA512Init;
+ lmd->updatef = (Lmd_update_f)SHA512Update;
+ lmd->finalf = (Lmd_final_f)SHA512Final;
+ sha512_init((Sum_t*)lmd);
+ }
+ return (Sum_t*)lmd;
+}
+
+#endif
diff --git a/src/lib/libsum/sum-md5.c b/src/lib/libsum/sum-md5.c
new file mode 100644
index 0000000..8f3b7f6
--- /dev/null
+++ b/src/lib/libsum/sum-md5.c
@@ -0,0 +1,355 @@
+#pragma prototyped
+
+/*
+ * md5
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ Method" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD5 Message-Digest Method" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+#define md5_description \
+ "The RSA Data Security, Inc. MD5 Message-Digest Method, 1991-2, \
+ used with permission. The block count is not printed."
+#define md5_options "[+(version)?md5 (RSA Data Security, Inc. MD5 Message-Digest, 1991-2) 1996-02-29]"
+#define md5_match "md5|MD5"
+#define md5_scale 0
+
+typedef uint32_t UINT4;
+
+typedef struct Md5_s
+{
+ _SUM_PUBLIC_
+ _SUM_PRIVATE_
+ UINT4 state[4]; /* state (ABCD) */
+ UINT4 count[2]; /* # bits handled mod 2^64 (lsb)*/
+ unsigned char buffer[64]; /* input buffer */
+ unsigned char digest[16]; /* final digest */
+ unsigned char digest_sum[16]; /* sum of all digests */
+} Md5_t;
+
+static const unsigned char md5_pad[] =
+{
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/*
+ * encode input into output
+ * len must be a multiple of 4
+ */
+
+static void
+md5_encode(register unsigned char* output, register UINT4* input, unsigned int len)
+{
+ register unsigned int i;
+ register unsigned int j;
+
+ for (i = j = 0; j < len; i++, j += 4)
+ {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+ }
+}
+
+/*
+ * decode input into output
+ * len must be a multiple of 4
+ */
+
+static void
+md5_decode(register UINT4* output, register unsigned char* input, unsigned int len)
+{
+ unsigned int i;
+ unsigned int j;
+
+ for (i = j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) |
+ (((UINT4)input[j+1]) << 8) |
+ (((UINT4)input[j+2]) << 16) |
+ (((UINT4)input[j+3]) << 24);
+}
+
+static int
+md5_init(Sum_t* p)
+{
+ register Md5_t* context = (Md5_t*)p;
+
+ context->count[0] = context->count[1] = 0;
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+ return 0;
+}
+
+static Sum_t*
+md5_open(const Method_t* method, const char* name)
+{
+ Md5_t* p;
+
+ if (p = newof(0, Md5_t, 1, 0))
+ {
+ p->method = (Method_t*)method;
+ p->name = name;
+ md5_init((Sum_t*)p);
+ }
+ return (Sum_t*)p;
+}
+
+/*
+ * basic MD5 step -- transforms buf based on in
+ */
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+/* F, G, H and I are basic MD5 functions */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+static void
+md5_transform(UINT4 state[4], unsigned char block[64])
+{
+ UINT4 a = state[0];
+ UINT4 b = state[1];
+ UINT4 c = state[2];
+ UINT4 d = state[3];
+ UINT4 x[16];
+
+ md5_decode(x, block, 64);
+
+ /* round 1 */
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* round 2 */
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* round 3 */
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x04881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* round 4 */
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+}
+
+static int
+md5_block(Sum_t* p, const void* s, size_t inputLen)
+{
+ register Md5_t* context = (Md5_t*)p;
+ unsigned char* input = (unsigned char*)s;
+ unsigned int i;
+ unsigned int index;
+ unsigned int partLen;
+
+ /* compute number of bytes mod 64 */
+ index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+
+ /* update number of bits */
+ if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((UINT4)inputLen >> 29);
+ partLen = 64 - index;
+
+ /* transform as many times as possible */
+ if (inputLen >= partLen)
+ {
+ memcpy(&context->buffer[index], input, partLen);
+ md5_transform(context->state, context->buffer);
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ md5_transform(context->state, &input[i]);
+ index = 0;
+ }
+ else
+ i = 0;
+
+ /* buffer remaining input */
+ memcpy(&context->buffer[index], &input[i], inputLen - i);
+
+ return 0;
+}
+
+static int
+md5_done(Sum_t* p)
+{
+ register Md5_t* context = (Md5_t*)p;
+ unsigned char bits[8];
+ unsigned int index;
+ unsigned int padLen;
+
+ /* save number of bits */
+ md5_encode(bits, context->count, sizeof(bits));
+
+ /* pad out to 56 mod 64 */
+ index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ md5_block(p, md5_pad, padLen);
+
+ /* append length (before padding) */
+ md5_block(p, bits, sizeof(bits));
+
+ /* store state in digest */
+ md5_encode(context->digest, context->state, sizeof(context->digest));
+
+ /* accumulate the digests */
+ for (index = 0; index < elementsof(context->digest); index++)
+ context->digest_sum[index] ^= context->digest[index];
+
+ return 0;
+}
+
+static int
+md5_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
+{
+ register Md5_t* x = (Md5_t*)p;
+ register unsigned char* d;
+ register int n;
+
+ d = (flags & SUM_TOTAL) ? x->digest_sum : x->digest;
+ for (n = 0; n < elementsof(x->digest); n++)
+ sfprintf(sp, "%02x", d[n]);
+ return 0;
+}
+
+static int
+md5_data(Sum_t* p, Sumdata_t* data)
+{
+ register Md5_t* x = (Md5_t*)p;
+
+ data->size = elementsof(x->digest);
+ data->num = 0;
+ data->buf = x->digest;
+ return 0;
+}
diff --git a/src/lib/libsum/sum-prng.c b/src/lib/libsum/sum-prng.c
new file mode 100644
index 0000000..8a85e47
--- /dev/null
+++ b/src/lib/libsum/sum-prng.c
@@ -0,0 +1,113 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1996-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * prng
+ */
+
+#include <fnv.h>
+
+#define prng_description \
+ "32 bit PRNG (pseudo random number generator) hash."
+#define prng_options "\
+[+mpy?The 32 bit PRNG multiplier.]:[number:=0x01000193]\
+[+add?The 32 bit PRNG addend.]:[number:=0]\
+[+init?The PRNG initial value. 0xffffffff is used if \anumber\a is omitted.]:?[number:=0x811c9dc5]\
+"
+#define prng_match "prng"
+#define prng_done long_done
+#define prng_print long_print
+#define prng_data long_data
+#define prng_scale 0
+
+typedef uint32_t Prngnum_t;
+
+typedef struct Prng_s
+{
+ _SUM_PUBLIC_
+ _SUM_PRIVATE_
+ _INTEGRAL_PRIVATE_
+ Prngnum_t init;
+ Prngnum_t mpy;
+ Prngnum_t add;
+} Prng_t;
+
+static Sum_t*
+prng_open(const Method_t* method, const char* name)
+{
+ register Prng_t* sum;
+ register const char* s;
+ register const char* t;
+ register const char* v;
+ register int i;
+
+ if (sum = newof(0, Prng_t, 1, 0))
+ {
+ sum->method = (Method_t*)method;
+ sum->name = name;
+ }
+ s = name;
+ while (*(t = s))
+ {
+ for (t = s, v = 0; *s && *s != '-'; s++)
+ if (*s == '=' && !v)
+ v = s;
+ i = (v ? v : s) - t;
+ if (isdigit(*t) || v && strneq(t, "mpy", i) && (t = v + 1))
+ sum->mpy = strtoul(t, NiL, 0);
+ else if (strneq(t, "add", i))
+ sum->add = v ? strtoul(v + 1, NiL, 0) : ~sum->add;
+ else if (strneq(t, "init", i))
+ sum->init = v ? strtoul(v + 1, NiL, 0) : ~sum->init;
+ if (*s == '-')
+ s++;
+ }
+ if (!sum->mpy)
+ {
+ sum->mpy = FNV_MULT;
+ if (!sum->init)
+ sum->init = FNV_INIT;
+ }
+ return (Sum_t*)sum;
+}
+
+static int
+prng_init(Sum_t* p)
+{
+ Prng_t* sum = (Prng_t*)p;
+
+ sum->sum = sum->init;
+ return 0;
+}
+
+static int
+prng_block(Sum_t* p, const void* s, size_t n)
+{
+ Prng_t* sum = (Prng_t*)p;
+ register Prngnum_t c = sum->sum;
+ register unsigned char* b = (unsigned char*)s;
+ register unsigned char* e = b + n;
+
+ while (b < e)
+ c = c * sum->mpy + sum->add + *b++;
+ sum->sum = c;
+ return 0;
+}
diff --git a/src/lib/libsum/sum-sha1.c b/src/lib/libsum/sum-sha1.c
new file mode 100644
index 0000000..76723fd
--- /dev/null
+++ b/src/lib/libsum/sum-sha1.c
@@ -0,0 +1,323 @@
+#pragma prototyped
+
+/*
+ * SHA-1 in C
+ * By Steve Reid <steve@edmweb.com>
+ * 100% Public Domain
+ *
+ * Test Vectors (from FIPS PUB 180-1)
+ * "abc"
+ * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+ * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+ * A million repetitions of "a"
+ * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+ */
+
+#define sha1_description "FIPS 180-1 SHA-1 secure hash algorithm 1."
+#define sha1_options "[+(version)?sha1 (FIPS 180-1) 1996-09-26]\
+ [+(author)?Steve Reid <steve@edmweb.com>]"
+#define sha1_match "sha1|SHA1|sha-1|SHA-1"
+#define sha1_scale 0
+
+#define sha1_padding md5_pad
+
+typedef struct Sha1_s
+{
+ _SUM_PUBLIC_
+ _SUM_PRIVATE_
+ uint32_t count[2];
+ uint32_t state[5];
+ uint8_t buffer[64];
+ uint8_t digest[20];
+ uint8_t digest_sum[20];
+} Sha1_t;
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/*
+ * blk0() and blk() perform the initial expand.
+ * I got the idea of expanding during the round function from SSLeay
+ */
+#if _ast_intswap
+# define blk0(i) \
+ (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \
+ | (rol(block->l[i], 8) & 0x00FF00FF))
+#else
+# define blk0(i) block->l[i]
+#endif
+#define blk(i) \
+ (block->l[i & 15] = rol(block->l[(i + 13) & 15] \
+ ^ block->l[(i + 8) & 15] \
+ ^ block->l[(i + 2) & 15] \
+ ^ block->l[i & 15], 1))
+
+/*
+ * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
+ */
+#define R0(v,w,x,y,z,i) \
+ z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
+ w = rol(w, 30);
+#define R1(v,w,x,y,z,i) \
+ z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
+ w = rol(w, 30);
+#define R2(v,w,x,y,z,i) \
+ z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
+ w = rol(w, 30);
+#define R3(v,w,x,y,z,i) \
+ z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
+ w = rol(w, 30);
+#define R4(v,w,x,y,z,i) \
+ z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
+ w = rol(w, 30);
+
+typedef union {
+ unsigned char c[64];
+ unsigned int l[16];
+} CHAR64LONG16;
+
+#ifdef __sparc_v9__
+static void do_R01(uint32_t *a, uint32_t *b, uint32_t *c,
+ uint32_t *d, uint32_t *e, CHAR64LONG16 *);
+static void do_R2(uint32_t *a, uint32_t *b, uint32_t *c,
+ uint32_t *d, uint32_t *e, CHAR64LONG16 *);
+static void do_R3(uint32_t *a, uint32_t *b, uint32_t *c,
+ uint32_t *d, uint32_t *e, CHAR64LONG16 *);
+static void do_R4(uint32_t *a, uint32_t *b, uint32_t *c,
+ uint32_t *d, uint32_t *e, CHAR64LONG16 *);
+
+#define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i)
+#define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i)
+#define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i)
+#define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i)
+#define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i)
+
+static void
+do_R01(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d,
+ uint32_t *e, CHAR64LONG16 *block)
+{
+ nR0(a,b,c,d,e, 0); nR0(e,a,b,c,d, 1); nR0(d,e,a,b,c, 2);
+ nR0(c,d,e,a,b, 3); nR0(b,c,d,e,a, 4); nR0(a,b,c,d,e, 5);
+ nR0(e,a,b,c,d, 6); nR0(d,e,a,b,c, 7); nR0(c,d,e,a,b, 8);
+ nR0(b,c,d,e,a, 9); nR0(a,b,c,d,e,10); nR0(e,a,b,c,d,11);
+ nR0(d,e,a,b,c,12); nR0(c,d,e,a,b,13); nR0(b,c,d,e,a,14);
+ nR0(a,b,c,d,e,15); nR1(e,a,b,c,d,16); nR1(d,e,a,b,c,17);
+ nR1(c,d,e,a,b,18); nR1(b,c,d,e,a,19);
+}
+
+static void
+do_R2(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d,
+ uint32_t *e, CHAR64LONG16 *block)
+{
+ nR2(a,b,c,d,e,20); nR2(e,a,b,c,d,21); nR2(d,e,a,b,c,22);
+ nR2(c,d,e,a,b,23); nR2(b,c,d,e,a,24); nR2(a,b,c,d,e,25);
+ nR2(e,a,b,c,d,26); nR2(d,e,a,b,c,27); nR2(c,d,e,a,b,28);
+ nR2(b,c,d,e,a,29); nR2(a,b,c,d,e,30); nR2(e,a,b,c,d,31);
+ nR2(d,e,a,b,c,32); nR2(c,d,e,a,b,33); nR2(b,c,d,e,a,34);
+ nR2(a,b,c,d,e,35); nR2(e,a,b,c,d,36); nR2(d,e,a,b,c,37);
+ nR2(c,d,e,a,b,38); nR2(b,c,d,e,a,39);
+}
+
+static void
+do_R3(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d,
+ uint32_t *e, CHAR64LONG16 *block)
+{
+ nR3(a,b,c,d,e,40); nR3(e,a,b,c,d,41); nR3(d,e,a,b,c,42);
+ nR3(c,d,e,a,b,43); nR3(b,c,d,e,a,44); nR3(a,b,c,d,e,45);
+ nR3(e,a,b,c,d,46); nR3(d,e,a,b,c,47); nR3(c,d,e,a,b,48);
+ nR3(b,c,d,e,a,49); nR3(a,b,c,d,e,50); nR3(e,a,b,c,d,51);
+ nR3(d,e,a,b,c,52); nR3(c,d,e,a,b,53); nR3(b,c,d,e,a,54);
+ nR3(a,b,c,d,e,55); nR3(e,a,b,c,d,56); nR3(d,e,a,b,c,57);
+ nR3(c,d,e,a,b,58); nR3(b,c,d,e,a,59);
+}
+
+static void
+do_R4(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d,
+ uint32_t *e, CHAR64LONG16 *block)
+{
+ nR4(a,b,c,d,e,60); nR4(e,a,b,c,d,61); nR4(d,e,a,b,c,62);
+ nR4(c,d,e,a,b,63); nR4(b,c,d,e,a,64); nR4(a,b,c,d,e,65);
+ nR4(e,a,b,c,d,66); nR4(d,e,a,b,c,67); nR4(c,d,e,a,b,68);
+ nR4(b,c,d,e,a,69); nR4(a,b,c,d,e,70); nR4(e,a,b,c,d,71);
+ nR4(d,e,a,b,c,72); nR4(c,d,e,a,b,73); nR4(b,c,d,e,a,74);
+ nR4(a,b,c,d,e,75); nR4(e,a,b,c,d,76); nR4(d,e,a,b,c,77);
+ nR4(c,d,e,a,b,78); nR4(b,c,d,e,a,79);
+}
+#endif
+
+/*
+ * Hash a single 512-bit block. This is the core of the algorithm.
+ */
+static void
+sha1_transform(uint32_t state[5], const unsigned char buffer[64]) {
+ uint32_t a, b, c, d, e;
+ CHAR64LONG16 *block;
+ CHAR64LONG16 workspace;
+
+ block = &workspace;
+ (void)memcpy(block, buffer, 64);
+
+ /* Copy sha->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+#ifdef __sparc_v9__
+ do_R01(&a, &b, &c, &d, &e, block);
+ do_R2(&a, &b, &c, &d, &e, block);
+ do_R3(&a, &b, &c, &d, &e, block);
+ do_R4(&a, &b, &c, &d, &e, block);
+#else
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+#endif
+
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+static int
+sha1_block(register Sum_t* p, const void* s, size_t len)
+{
+ Sha1_t* sha = (Sha1_t*)p;
+ uint8_t* data = (uint8_t*)s;
+ unsigned int i, j;
+
+ if (len) {
+ j = sha->count[0];
+ if ((sha->count[0] += len << 3) < j)
+ sha->count[1] += (len >> 29) + 1;
+ j = (j >> 3) & 63;
+ if ((j + len) > 63) {
+ (void)memcpy(&sha->buffer[j], data, (i = 64 - j));
+ sha1_transform(sha->state, sha->buffer);
+ for ( ; i + 63 < len; i += 64)
+ sha1_transform(sha->state, &data[i]);
+ j = 0;
+ } else {
+ i = 0;
+ }
+
+ (void)memcpy(&sha->buffer[j], &data[i], len - i);
+ }
+ return 0;
+}
+
+static int
+sha1_init(Sum_t* p)
+{
+ register Sha1_t* sha = (Sha1_t*)p;
+
+ sha->count[0] = sha->count[1] = 0;
+ sha->state[0] = 0x67452301;
+ sha->state[1] = 0xEFCDAB89;
+ sha->state[2] = 0x98BADCFE;
+ sha->state[3] = 0x10325476;
+ sha->state[4] = 0xC3D2E1F0;
+
+ return 0;
+}
+
+static Sum_t*
+sha1_open(const Method_t* method, const char* name)
+{
+ Sha1_t* sha;
+
+ if (sha = newof(0, Sha1_t, 1, 0))
+ {
+ sha->method = (Method_t*)method;
+ sha->name = name;
+ sha1_init((Sum_t*)sha);
+ }
+ return (Sum_t*)sha;
+}
+
+/*
+ * Add padding and return the message digest.
+ */
+
+static const unsigned char final_200 = 128;
+static const unsigned char final_0 = 0;
+
+static int
+sha1_done(Sum_t* p)
+{
+ Sha1_t* sha = (Sha1_t*)p;
+ unsigned int i;
+ unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ /* Endian independent */
+ finalcount[i] = (unsigned char)
+ ((sha->count[(i >= 4 ? 0 : 1)]
+ >> ((3 - (i & 3)) * 8)) & 255);
+ }
+
+ sha1_block(p, &final_200, 1);
+ while ((sha->count[0] & 504) != 448)
+ sha1_block(p, &final_0, 1);
+ /* The next Update should cause a sha1_transform() */
+ sha1_block(p, finalcount, 8);
+
+ for (i = 0; i < elementsof(sha->digest); i++)
+ {
+ sha->digest[i] = (unsigned char)((sha->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
+ sha->digest_sum[i] ^= sha->digest[i];
+ }
+ memset(sha->count, 0, sizeof(sha->count));
+ memset(sha->state, 0, sizeof(sha->state));
+ memset(sha->buffer, 0, sizeof(sha->buffer));
+ return 0;
+}
+
+static int
+sha1_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
+{
+ register Sha1_t* sha = (Sha1_t*)p;
+ register unsigned char* d;
+ register int n;
+
+ d = (flags & SUM_TOTAL) ? sha->digest_sum : sha->digest;
+ for (n = 0; n < elementsof(sha->digest); n++)
+ sfprintf(sp, "%02x", d[n]);
+ return 0;
+}
+
+static int
+sha1_data(Sum_t* p, Sumdata_t* data)
+{
+ register Sha1_t* sha = (Sha1_t*)p;
+
+ data->size = elementsof(sha->digest);
+ data->num = 0;
+ data->buf = sha->digest;
+ return 0;
+}
diff --git a/src/lib/libsum/sum-sha2.c b/src/lib/libsum/sum-sha2.c
new file mode 100644
index 0000000..9dd52e7
--- /dev/null
+++ b/src/lib/libsum/sum-sha2.c
@@ -0,0 +1,1229 @@
+#pragma prototyped
+
+#if _typ_int64_t
+
+/*
+ * Aaron D. Gifford's SHA {256,384,512} code transcribed into a -lsum method
+ * with bitcount[] order reversed to allow a single noalias buffer copy
+ */
+
+/*
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * ASSERT NOTE:
+ * Some sanity checking code is included using assert(). On my FreeBSD
+ * system, this additional code can be removed by compiling with NDEBUG
+ * defined. Check your own systems manpage on assert() to see how to
+ * compile WITHOUT the sanity checking code on your system.
+ *
+ * UNROLLED TRANSFORM LOOP NOTE:
+ * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
+ * loop version for the hash transform rounds (defined using macros
+ * later in this file). Either define on the command line, for example:
+ *
+ * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
+ *
+ * or define below:
+ *
+ * #define SHA2_UNROLL_TRANSFORM
+ *
+ */
+
+/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+
+#if _PACKAGE_ast
+
+#ifndef __USE_BSD
+#define __undef__USE_BSD
+#define __USE_BSD
+#endif
+#include <endian.h>
+#ifdef __undef__USE_BSD
+#undef __undef__USE_BSD
+#undef __USE_BSD
+#endif
+
+typedef uint8_t sha2_byte; /* Exactly 1 byte */
+typedef uint32_t sha2_word32; /* Exactly 4 bytes */
+typedef uint64_t sha2_word64; /* Exactly 8 bytes */
+
+#define assert(x)
+
+#undef R
+#undef S32
+#undef S64
+
+#else /* _PACKAGE_ast */
+
+/*
+ * BYTE_ORDER NOTE:
+ *
+ * Please make sure that your system defines BYTE_ORDER. If your
+ * architecture is little-endian, make sure it also defines
+ * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
+ * equivilent.
+ *
+ * If your system does not define the above, then you can do so by
+ * hand like this:
+ *
+ * #define LITTLE_ENDIAN 1234
+ * #define BIG_ENDIAN 4321
+ *
+ * And for little-endian machines, add:
+ *
+ * #define BYTE_ORDER LITTLE_ENDIAN
+ *
+ * Or for big-endian machines:
+ *
+ * #define BYTE_ORDER BIG_ENDIAN
+ *
+ * The FreeBSD machine this was written on defines BYTE_ORDER
+ * appropriately by including <sys/types.h> (which in turn includes
+ * <machine/endian.h> where the appropriate definitions are actually
+ * made).
+ */
+
+#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
+#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
+#endif
+
+/*
+ * Define the following sha2_* types to types of the correct length on
+ * the native archtecture. Most BSD systems and Linux define u_intXX_t
+ * types. Machines with very recent ANSI C headers, can use the
+ * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H
+ * during compile or in the sha.h header file.
+ *
+ * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t
+ * will need to define these three typedefs below (and the appropriate
+ * ones in sha.h too) by hand according to their system architecture.
+ *
+ * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t
+ * types and pointing out recent ANSI C support for uintXX_t in inttypes.h.
+ */
+
+#ifdef SHA2_USE_INTTYPES_H
+
+typedef uint8_t sha2_byte; /* Exactly 1 byte */
+typedef uint32_t sha2_word32; /* Exactly 4 bytes */
+typedef uint64_t sha2_word64; /* Exactly 8 bytes */
+
+#else /* SHA2_USE_INTTYPES_H */
+
+typedef u_int8_t sha2_byte; /* Exactly 1 byte */
+typedef u_int32_t sha2_word32; /* Exactly 4 bytes */
+typedef u_int64_t sha2_word64; /* Exactly 8 bytes */
+
+#endif /* SHA2_USE_INTTYPES_H */
+
+#endif /* _PACKAGE_ast */
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+
+#define SHA256_BLOCK_LENGTH 64
+#define SHA256_DIGEST_LENGTH 32
+#define SHA384_BLOCK_LENGTH 128
+#define SHA384_DIGEST_LENGTH 48
+#define SHA512_BLOCK_LENGTH 128
+#define SHA512_DIGEST_LENGTH 64
+
+#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
+#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16)
+#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
+
+/*** ENDIAN REVERSAL MACROS *******************************************/
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define REVERSE32(w,x) { \
+ sha2_word32 tmp = (w); \
+ tmp = (tmp >> 16) | (tmp << 16); \
+ (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+}
+#if _ast_LL
+#define REVERSE64(w,x) { \
+ sha2_word64 tmp = (w); \
+ tmp = (tmp >> 32) | (tmp << 32); \
+ tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
+ ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
+ (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
+ ((tmp & 0x0000ffff0000ffffULL) << 16); \
+}
+#else
+#define REVERSE64(w,x) { \
+ sha2_word64 tmp = (w); \
+ tmp = (tmp >> 32) | (tmp << 32); \
+ tmp = ((tmp & ((sha2_word64)0xff00ff00ff00ff00)) >> 8) | \
+ ((tmp & ((sha2_word64)0x00ff00ff00ff00ff)) << 8); \
+ (x) = ((tmp & ((sha2_word64)0xffff0000ffff0000)) >> 16) | \
+ ((tmp & ((sha2_word64)0x0000ffff0000ffff)) << 16); \
+}
+#endif
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * Macro for incrementally adding the unsigned 64-bit integer n to the
+ * unsigned 128-bit integer (represented using a two-element array of
+ * 64-bit words):
+ */
+
+#define ADDINC128(w,n) { \
+ (w)[1] += (sha2_word64)(n); \
+ if ((w)[1] < (n)) { \
+ (w)[0]++; \
+ } \
+}
+
+/*
+ * Macros for copying blocks of memory and for zeroing out ranges
+ * of memory. Using these macros makes it easy to switch from
+ * using memset()/memcpy() and using bzero()/bcopy().
+ *
+ * Please define either SHA2_USE_MEMSET_MEMCPY or define
+ * SHA2_USE_BZERO_BCOPY depending on which function set you
+ * choose to use:
+ */
+
+#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY)
+/* Default to memset()/memcpy() if no option is specified */
+#define SHA2_USE_MEMSET_MEMCPY 1
+#endif
+#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY)
+/* Abort with an error if BOTH options are defined */
+#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both!
+#endif
+
+#ifdef SHA2_USE_MEMSET_MEMCPY
+#define MEMSET_BZERO(p,l) memset((p), 0, (l))
+#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l))
+#endif
+#ifdef SHA2_USE_BZERO_BCOPY
+#define MEMSET_BZERO(p,l) bzero((p), (l))
+#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l))
+#endif
+
+
+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
+/*
+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
+ *
+ * NOTE: The naming of R and S appears backwards here (R is a SHIFT and
+ * S is a ROTATION) because the SHA-256/384/512 description document
+ * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
+ * same "backwards" definition.
+ */
+
+/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+#define R(b,x) ((x) >> (b))
+/* 32-bit Rotate-right (used in SHA-256): */
+#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b))))
+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
+#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b))))
+
+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* Four of six logical functions used in SHA-256: */
+#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x)))
+#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x)))
+#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x)))
+#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x)))
+
+/* Four of six logical functions used in SHA-384 and SHA-512: */
+#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
+#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
+#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x)))
+#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x)))
+
+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
+/* Hash constant words K for SHA-256: */
+static const sha2_word32 K256[64] = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+ 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+ 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+ 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+ 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+ 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+ 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+ 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+ 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+ 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+ 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+ 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+ 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+ 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+ 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Initial hash value H for SHA-256: */
+static const sha2_word32 sha256_initial_hash_value[8] = {
+ 0x6a09e667UL,
+ 0xbb67ae85UL,
+ 0x3c6ef372UL,
+ 0xa54ff53aUL,
+ 0x510e527fUL,
+ 0x9b05688cUL,
+ 0x1f83d9abUL,
+ 0x5be0cd19UL
+};
+
+/* Hash constant words K for SHA-384 and SHA-512: */
+static const sha2_word64 K512[80] = {
+#if _ast_LL
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+#else
+ ((sha2_word64)0x428a2f98d728ae22), ((sha2_word64)0x7137449123ef65cd),
+ ((sha2_word64)0xb5c0fbcfec4d3b2f), ((sha2_word64)0xe9b5dba58189dbbc),
+ ((sha2_word64)0x3956c25bf348b538), ((sha2_word64)0x59f111f1b605d019),
+ ((sha2_word64)0x923f82a4af194f9b), ((sha2_word64)0xab1c5ed5da6d8118),
+ ((sha2_word64)0xd807aa98a3030242), ((sha2_word64)0x12835b0145706fbe),
+ ((sha2_word64)0x243185be4ee4b28c), ((sha2_word64)0x550c7dc3d5ffb4e2),
+ ((sha2_word64)0x72be5d74f27b896f), ((sha2_word64)0x80deb1fe3b1696b1),
+ ((sha2_word64)0x9bdc06a725c71235), ((sha2_word64)0xc19bf174cf692694),
+ ((sha2_word64)0xe49b69c19ef14ad2), ((sha2_word64)0xefbe4786384f25e3),
+ ((sha2_word64)0x0fc19dc68b8cd5b5), ((sha2_word64)0x240ca1cc77ac9c65),
+ ((sha2_word64)0x2de92c6f592b0275), ((sha2_word64)0x4a7484aa6ea6e483),
+ ((sha2_word64)0x5cb0a9dcbd41fbd4), ((sha2_word64)0x76f988da831153b5),
+ ((sha2_word64)0x983e5152ee66dfab), ((sha2_word64)0xa831c66d2db43210),
+ ((sha2_word64)0xb00327c898fb213f), ((sha2_word64)0xbf597fc7beef0ee4),
+ ((sha2_word64)0xc6e00bf33da88fc2), ((sha2_word64)0xd5a79147930aa725),
+ ((sha2_word64)0x06ca6351e003826f), ((sha2_word64)0x142929670a0e6e70),
+ ((sha2_word64)0x27b70a8546d22ffc), ((sha2_word64)0x2e1b21385c26c926),
+ ((sha2_word64)0x4d2c6dfc5ac42aed), ((sha2_word64)0x53380d139d95b3df),
+ ((sha2_word64)0x650a73548baf63de), ((sha2_word64)0x766a0abb3c77b2a8),
+ ((sha2_word64)0x81c2c92e47edaee6), ((sha2_word64)0x92722c851482353b),
+ ((sha2_word64)0xa2bfe8a14cf10364), ((sha2_word64)0xa81a664bbc423001),
+ ((sha2_word64)0xc24b8b70d0f89791), ((sha2_word64)0xc76c51a30654be30),
+ ((sha2_word64)0xd192e819d6ef5218), ((sha2_word64)0xd69906245565a910),
+ ((sha2_word64)0xf40e35855771202a), ((sha2_word64)0x106aa07032bbd1b8),
+ ((sha2_word64)0x19a4c116b8d2d0c8), ((sha2_word64)0x1e376c085141ab53),
+ ((sha2_word64)0x2748774cdf8eeb99), ((sha2_word64)0x34b0bcb5e19b48a8),
+ ((sha2_word64)0x391c0cb3c5c95a63), ((sha2_word64)0x4ed8aa4ae3418acb),
+ ((sha2_word64)0x5b9cca4f7763e373), ((sha2_word64)0x682e6ff3d6b2b8a3),
+ ((sha2_word64)0x748f82ee5defb2fc), ((sha2_word64)0x78a5636f43172f60),
+ ((sha2_word64)0x84c87814a1f0ab72), ((sha2_word64)0x8cc702081a6439ec),
+ ((sha2_word64)0x90befffa23631e28), ((sha2_word64)0xa4506cebde82bde9),
+ ((sha2_word64)0xbef9a3f7b2c67915), ((sha2_word64)0xc67178f2e372532b),
+ ((sha2_word64)0xca273eceea26619c), ((sha2_word64)0xd186b8c721c0c207),
+ ((sha2_word64)0xeada7dd6cde0eb1e), ((sha2_word64)0xf57d4f7fee6ed178),
+ ((sha2_word64)0x06f067aa72176fba), ((sha2_word64)0x0a637dc5a2c898a6),
+ ((sha2_word64)0x113f9804bef90dae), ((sha2_word64)0x1b710b35131c471b),
+ ((sha2_word64)0x28db77f523047d84), ((sha2_word64)0x32caab7b40c72493),
+ ((sha2_word64)0x3c9ebe0a15c9bebc), ((sha2_word64)0x431d67c49c100d4c),
+ ((sha2_word64)0x4cc5d4becb3e42b6), ((sha2_word64)0x597f299cfc657e2a),
+ ((sha2_word64)0x5fcb6fab3ad6faec), ((sha2_word64)0x6c44198c4a475817)
+#endif
+};
+
+/* Initial hash value H for SHA-384 */
+static const sha2_word64 sha384_initial_hash_value[8] = {
+#if _ast_LL
+ 0xcbbb9d5dc1059ed8ULL,
+ 0x629a292a367cd507ULL,
+ 0x9159015a3070dd17ULL,
+ 0x152fecd8f70e5939ULL,
+ 0x67332667ffc00b31ULL,
+ 0x8eb44a8768581511ULL,
+ 0xdb0c2e0d64f98fa7ULL,
+ 0x47b5481dbefa4fa4ULL
+#else
+ ((sha2_word64)0xcbbb9d5dc1059ed8),
+ ((sha2_word64)0x629a292a367cd507),
+ ((sha2_word64)0x9159015a3070dd17),
+ ((sha2_word64)0x152fecd8f70e5939),
+ ((sha2_word64)0x67332667ffc00b31),
+ ((sha2_word64)0x8eb44a8768581511),
+ ((sha2_word64)0xdb0c2e0d64f98fa7),
+ ((sha2_word64)0x47b5481dbefa4fa4)
+#endif
+};
+
+/* Initial hash value H for SHA-512 */
+static const sha2_word64 sha512_initial_hash_value[8] = {
+#if _ast_LL
+ 0x6a09e667f3bcc908ULL,
+ 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL,
+ 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL,
+ 0x5be0cd19137e2179ULL
+#else
+ ((sha2_word64)0x6a09e667f3bcc908),
+ ((sha2_word64)0xbb67ae8584caa73b),
+ ((sha2_word64)0x3c6ef372fe94f82b),
+ ((sha2_word64)0xa54ff53a5f1d36f1),
+ ((sha2_word64)0x510e527fade682d1),
+ ((sha2_word64)0x9b05688c2b3e6c1f),
+ ((sha2_word64)0x1f83d9abfb41bd6b),
+ ((sha2_word64)0x5be0cd19137e2179)
+#endif
+};
+
+/*** SHA-256: *********************************************************/
+
+#define sha256_description "FIPS SHA-256 secure hash algorithm."
+#define sha256_options "\
+[+(version)?sha-256 (FIPS) 2000-01-01]\
+[+(author)?Aaron D. Gifford]\
+"
+#define sha256_match "sha256|sha-256|SHA256|SHA-256"
+#define sha256_scale 0
+
+#define sha256_padding md5_pad
+
+#define SHA256_CTX Sha256_t
+
+typedef struct Sha256_s
+{
+ _SUM_PUBLIC_
+ _SUM_PRIVATE_
+ sha2_byte digest[SHA256_DIGEST_LENGTH];
+ sha2_byte digest_sum[SHA256_DIGEST_LENGTH];
+ sha2_word32 state[8];
+ sha2_word64 bitcount;
+ sha2_byte buffer[SHA256_BLOCK_LENGTH];
+} Sha256_t;
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-256 round macros: */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
+ REVERSE32(*data++, W256[j]); \
+ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+ K256[j] + W256[j]; \
+ (d) += T1; \
+ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+ j++
+
+
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
+ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+ K256[j] + (W256[j] = *data++); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+ j++
+
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND256(a,b,c,d,e,f,g,h) \
+ s0 = W256[(j+1)&0x0f]; \
+ s0 = sigma0_256(s0); \
+ s1 = W256[(j+14)&0x0f]; \
+ s1 = sigma1_256(s1); \
+ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
+ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+ j++
+
+static void SHA256_Transform(SHA256_CTX* sha, const sha2_word32* data) {
+ sha2_word32 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word32 T1, *W256;
+ int j;
+
+ W256 = (sha2_word32*)sha->buffer;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = sha->state[0];
+ b = sha->state[1];
+ c = sha->state[2];
+ d = sha->state[3];
+ e = sha->state[4];
+ f = sha->state[5];
+ g = sha->state[6];
+ h = sha->state[7];
+
+ j = 0;
+ do {
+ /* Rounds 0 to 15 (unrolled): */
+ ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
+ ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
+ ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
+ ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
+ ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
+ ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
+ ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
+ ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
+ } while (j < 16);
+
+ /* Now for the remaining rounds to 64: */
+ do {
+ ROUND256(a,b,c,d,e,f,g,h);
+ ROUND256(h,a,b,c,d,e,f,g);
+ ROUND256(g,h,a,b,c,d,e,f);
+ ROUND256(f,g,h,a,b,c,d,e);
+ ROUND256(e,f,g,h,a,b,c,d);
+ ROUND256(d,e,f,g,h,a,b,c);
+ ROUND256(c,d,e,f,g,h,a,b);
+ ROUND256(b,c,d,e,f,g,h,a);
+ } while (j < 64);
+
+ /* Compute the current intermediate hash value */
+ sha->state[0] += a;
+ sha->state[1] += b;
+ sha->state[2] += c;
+ sha->state[3] += d;
+ sha->state[4] += e;
+ sha->state[5] += f;
+ sha->state[6] += g;
+ sha->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+static void SHA256_Transform(SHA256_CTX* sha, const sha2_word32* data) {
+ sha2_word32 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word32 T1, T2, *W256;
+ int j;
+
+ W256 = (sha2_word32*)sha->buffer;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = sha->state[0];
+ b = sha->state[1];
+ c = sha->state[2];
+ d = sha->state[3];
+ e = sha->state[4];
+ f = sha->state[5];
+ g = sha->state[6];
+ h = sha->state[7];
+
+ j = 0;
+ do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Copy data while converting to host byte order */
+ REVERSE32(*data++,W256[j]);
+ /* Apply the SHA-256 compression function to update a..h */
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+ /* Apply the SHA-256 compression function to update a..h with copy */
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+ T2 = Sigma0_256(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 16);
+
+ do {
+ /* Part of the message block expansion: */
+ s0 = W256[(j+1)&0x0f];
+ s0 = sigma0_256(s0);
+ s1 = W256[(j+14)&0x0f];
+ s1 = sigma1_256(s1);
+
+ /* Apply the SHA-256 compression function to update a..h */
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
+ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
+ T2 = Sigma0_256(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 64);
+
+ /* Compute the current intermediate hash value */
+ sha->state[0] += a;
+ sha->state[1] += b;
+ sha->state[2] += c;
+ sha->state[3] += d;
+ sha->state[4] += e;
+ sha->state[5] += f;
+ sha->state[6] += g;
+ sha->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+static int
+sha256_block(register Sum_t* p, const void* s, size_t len)
+{
+ Sha256_t* sha = (Sha256_t*)p;
+ sha2_byte* data = (sha2_byte*)s;
+ unsigned int freespace, usedspace;
+
+ if (!len)
+ return 0;
+ usedspace = (sha->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+ if (usedspace > 0) {
+ /* Calculate how much free space is available in the buffer */
+ freespace = SHA256_BLOCK_LENGTH - usedspace;
+
+ if (len >= freespace) {
+ /* Fill the buffer completely and process it */
+ MEMCPY_BCOPY(&sha->buffer[usedspace], data, freespace);
+ sha->bitcount += freespace << 3;
+ len -= freespace;
+ data += freespace;
+ SHA256_Transform(sha, (sha2_word32*)sha->buffer);
+ } else {
+ /* The buffer is not yet full */
+ MEMCPY_BCOPY(&sha->buffer[usedspace], data, len);
+ sha->bitcount += len << 3;
+ /* Clean up: */
+ usedspace = freespace = 0;
+ return 0;
+ }
+ }
+ while (len >= SHA256_BLOCK_LENGTH) {
+ /* Process as many complete blocks as we can */
+ SHA256_Transform(sha, (sha2_word32*)data);
+ sha->bitcount += SHA256_BLOCK_LENGTH << 3;
+ len -= SHA256_BLOCK_LENGTH;
+ data += SHA256_BLOCK_LENGTH;
+ }
+ if (len > 0) {
+ /* There's left-overs, so save 'em */
+ MEMCPY_BCOPY(sha->buffer, data, len);
+ sha->bitcount += len << 3;
+ }
+ /* Clean up: */
+ usedspace = freespace = 0;
+
+ return 0;
+}
+
+static int
+sha256_init(Sum_t* p)
+{
+ register Sha256_t* sha = (Sha256_t*)p;
+
+ MEMCPY_BCOPY(sha->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH);
+ MEMSET_BZERO(sha->buffer, SHA256_BLOCK_LENGTH);
+ sha->bitcount = 0;
+
+ return 0;
+}
+
+static Sum_t*
+sha256_open(const Method_t* method, const char* name)
+{
+ Sha256_t* sha;
+
+ if (sha = newof(0, Sha256_t, 1, 0))
+ {
+ sha->method = (Method_t*)method;
+ sha->name = name;
+ sha256_init((Sum_t*)sha);
+ }
+ return (Sum_t*)sha;
+}
+
+static int
+sha256_done(Sum_t* p)
+{
+ Sha256_t* sha = (Sha256_t*)p;
+ unsigned int usedspace;
+ register int i;
+
+ /* Sanity check: */
+ assert(sha != (SHA256_CTX*)0);
+
+ usedspace = (sha->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert FROM host byte order */
+ REVERSE64(sha->bitcount,sha->bitcount);
+#endif
+ if (usedspace > 0) {
+ /* Begin padding with a 1 bit: */
+ sha->buffer[usedspace++] = 0x80;
+
+ if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
+ /* Set-up for the last transform: */
+ MEMSET_BZERO(&sha->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
+ } else {
+ if (usedspace < SHA256_BLOCK_LENGTH) {
+ MEMSET_BZERO(&sha->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
+ }
+ /* Do second-to-last transform: */
+ SHA256_Transform(sha, (sha2_word32*)sha->buffer);
+
+ /* And set-up for the last transform: */
+ MEMSET_BZERO(sha->buffer, SHA256_SHORT_BLOCK_LENGTH);
+ }
+ } else {
+ /* Set-up for the last transform: */
+ MEMSET_BZERO(sha->buffer, SHA256_SHORT_BLOCK_LENGTH);
+
+ /* Begin padding with a 1 bit: */
+ *sha->buffer = 0x80;
+ }
+ /* Store the length of input data (in bits): */
+ MEMCPY_BCOPY(&sha->buffer[SHA256_SHORT_BLOCK_LENGTH], &sha->bitcount, 8);
+
+ /* Final transform: */
+ SHA256_Transform(sha, (sha2_word32*)sha->buffer);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ {
+ /* Convert TO host byte order */
+ int j;
+ sha2_word32* d = (sha2_word32*)sha->digest;
+ for (j = 0; j < 8; j++) {
+ REVERSE32(sha->state[j],sha->state[j]);
+ *d++ = sha->state[j];
+ }
+ }
+#else
+ MEMCPY_BCOPY(sha->digest, sha->state, SHA256_DIGEST_LENGTH);
+#endif
+
+ /* accumulate the digests */
+ for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
+ sha->digest_sum[i] ^= sha->digest[i];
+
+ /* Clean up state data: */
+ MEMSET_BZERO(&sha->state, sizeof(*sha) - offsetof(Sha256_t, state));
+ usedspace = 0;
+
+ return 0;
+}
+
+static int
+sha256_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
+{
+ register Sha256_t* sha = (Sha256_t*)p;
+ register sha2_byte* d;
+ register sha2_byte* e;
+
+ d = (flags & SUM_TOTAL) ? sha->digest_sum : sha->digest;
+ e = d + SHA256_DIGEST_LENGTH;
+ while (d < e)
+ sfprintf(sp, "%02x", *d++);
+ return 0;
+}
+
+static int
+sha256_data(Sum_t* p, Sumdata_t* data)
+{
+ register Sha256_t* sha = (Sha256_t*)p;
+
+ data->size = SHA256_DIGEST_LENGTH;
+ data->num = 0;
+ data->buf = sha->digest;
+ return 0;
+}
+
+/*** SHA-512: *********************************************************/
+
+#define sha512_description "FIPS SHA-512 secure hash algorithm."
+#define sha512_options "\
+[+(version)?sha-512 (FIPS) 2000-01-01]\
+[+(author)?Aaron D. Gifford]\
+"
+#define sha512_match "sha512|sha-512|SHA512|SHA-512"
+#define sha512_scale 0
+
+#define sha512_padding md5_pad
+
+#define SHA512_CTX Sha512_t
+
+typedef struct Sha512_s
+{
+ _SUM_PUBLIC_
+ _SUM_PRIVATE_
+ sha2_byte digest[SHA512_DIGEST_LENGTH];
+ sha2_byte digest_sum[SHA512_DIGEST_LENGTH];
+ sha2_word64 state[8];
+ sha2_word64 bitcount[2];
+ sha2_byte buffer[SHA512_BLOCK_LENGTH];
+} Sha512_t;
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-512 round macros: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
+ REVERSE64(*data++, W512[j]); \
+ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+ K512[j] + W512[j]; \
+ (d) += T1, \
+ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
+ j++
+
+
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
+ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+ K512[j] + (W512[j] = *data++); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+ j++
+
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND512(a,b,c,d,e,f,g,h) \
+ s0 = W512[(j+1)&0x0f]; \
+ s0 = sigma0_512(s0); \
+ s1 = W512[(j+14)&0x0f]; \
+ s1 = sigma1_512(s1); \
+ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
+ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+ j++
+
+static void SHA512_Transform(SHA512_CTX* sha, const sha2_word64* data) {
+ sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word64 T1, *W512 = (sha2_word64*)sha->buffer;
+ int j;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = sha->state[0];
+ b = sha->state[1];
+ c = sha->state[2];
+ d = sha->state[3];
+ e = sha->state[4];
+ f = sha->state[5];
+ g = sha->state[6];
+ h = sha->state[7];
+
+ j = 0;
+ do {
+ ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
+ ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
+ ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
+ ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
+ ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
+ ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
+ ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
+ ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
+ } while (j < 16);
+
+ /* Now for the remaining rounds up to 79: */
+ do {
+ ROUND512(a,b,c,d,e,f,g,h);
+ ROUND512(h,a,b,c,d,e,f,g);
+ ROUND512(g,h,a,b,c,d,e,f);
+ ROUND512(f,g,h,a,b,c,d,e);
+ ROUND512(e,f,g,h,a,b,c,d);
+ ROUND512(d,e,f,g,h,a,b,c);
+ ROUND512(c,d,e,f,g,h,a,b);
+ ROUND512(b,c,d,e,f,g,h,a);
+ } while (j < 80);
+
+ /* Compute the current intermediate hash value */
+ sha->state[0] += a;
+ sha->state[1] += b;
+ sha->state[2] += c;
+ sha->state[3] += d;
+ sha->state[4] += e;
+ sha->state[5] += f;
+ sha->state[6] += g;
+ sha->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+static void SHA512_Transform(SHA512_CTX* sha, const sha2_word64* data) {
+ sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word64 T1, T2, *W512 = (sha2_word64*)sha->buffer;
+ int j;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = sha->state[0];
+ b = sha->state[1];
+ c = sha->state[2];
+ d = sha->state[3];
+ e = sha->state[4];
+ f = sha->state[5];
+ g = sha->state[6];
+ h = sha->state[7];
+
+ j = 0;
+ do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert TO host byte order */
+ REVERSE64(*data++, W512[j]);
+ /* Apply the SHA-512 compression function to update a..h */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+ /* Apply the SHA-512 compression function to update a..h with copy */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+ T2 = Sigma0_512(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 16);
+
+ do {
+ /* Part of the message block expansion: */
+ s0 = W512[(j+1)&0x0f];
+ s0 = sigma0_512(s0);
+ s1 = W512[(j+14)&0x0f];
+ s1 = sigma1_512(s1);
+
+ /* Apply the SHA-512 compression function to update a..h */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
+ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
+ T2 = Sigma0_512(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 80);
+
+ /* Compute the current intermediate hash value */
+ sha->state[0] += a;
+ sha->state[1] += b;
+ sha->state[2] += c;
+ sha->state[3] += d;
+ sha->state[4] += e;
+ sha->state[5] += f;
+ sha->state[6] += g;
+ sha->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+static int
+sha512_block(register Sum_t* p, const void* s, size_t len)
+{
+ Sha512_t* sha = (Sha512_t*)p;
+ sha2_byte* data = (sha2_byte*)s;
+ unsigned int freespace, usedspace;
+
+ if (!len)
+ return 0;
+ usedspace = (sha->bitcount[1] >> 3) % SHA512_BLOCK_LENGTH;
+ if (usedspace > 0) {
+ /* Calculate how much free space is available in the buffer */
+ freespace = SHA512_BLOCK_LENGTH - usedspace;
+
+ if (len >= freespace) {
+ /* Fill the buffer completely and process it */
+ MEMCPY_BCOPY(&sha->buffer[usedspace], data, freespace);
+ ADDINC128(sha->bitcount, freespace << 3);
+ len -= freespace;
+ data += freespace;
+ SHA512_Transform(sha, (sha2_word64*)sha->buffer);
+ } else {
+ /* The buffer is not yet full */
+ MEMCPY_BCOPY(&sha->buffer[usedspace], data, len);
+ ADDINC128(sha->bitcount, len << 3);
+ /* Clean up: */
+ usedspace = freespace = 0;
+ return 0;
+ }
+ }
+ while (len >= SHA512_BLOCK_LENGTH) {
+ /* Process as many complete blocks as we can */
+ SHA512_Transform(sha, (sha2_word64*)data);
+ ADDINC128(sha->bitcount, SHA512_BLOCK_LENGTH << 3);
+ len -= SHA512_BLOCK_LENGTH;
+ data += SHA512_BLOCK_LENGTH;
+ }
+ if (len > 0) {
+ /* There's left-overs, so save 'em */
+ MEMCPY_BCOPY(sha->buffer, data, len);
+ ADDINC128(sha->bitcount, len << 3);
+ }
+ /* Clean up: */
+ usedspace = freespace = 0;
+
+ return 0;
+}
+
+static int
+sha512_init(Sum_t* p)
+{
+ register Sha512_t* sha = (Sha512_t*)p;
+
+ MEMCPY_BCOPY(sha->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH);
+ MEMSET_BZERO(sha->buffer, SHA512_BLOCK_LENGTH);
+ sha->bitcount[0] = sha->bitcount[1] = 0;
+
+ return 0;
+}
+
+static Sum_t*
+sha512_open(const Method_t* method, const char* name)
+{
+ Sha512_t* sha;
+
+ if (sha = newof(0, Sha512_t, 1, 0))
+ {
+ sha->method = (Method_t*)method;
+ sha->name = name;
+ sha512_init((Sum_t*)sha);
+ }
+ return (Sum_t*)sha;
+}
+
+static int
+sha512_done(Sum_t* p)
+{
+ Sha512_t* sha = (Sha512_t*)p;
+ unsigned int usedspace;
+ register int i;
+
+ usedspace = (sha->bitcount[1] >> 3) % SHA512_BLOCK_LENGTH;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert FROM host byte order */
+ REVERSE64(sha->bitcount[0],sha->bitcount[0]);
+ REVERSE64(sha->bitcount[1],sha->bitcount[1]);
+#endif
+ if (usedspace > 0) {
+ /* Begin padding with a 1 bit: */
+ sha->buffer[usedspace++] = 0x80;
+
+ if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
+ /* Set-up for the last transform: */
+ MEMSET_BZERO(&sha->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
+ } else {
+ if (usedspace < SHA512_BLOCK_LENGTH) {
+ MEMSET_BZERO(&sha->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
+ }
+ /* Do second-to-last transform: */
+ SHA512_Transform(sha, (sha2_word64*)sha->buffer);
+
+ /* And set-up for the last transform: */
+ MEMSET_BZERO(sha->buffer, SHA512_BLOCK_LENGTH - 2);
+ }
+ } else {
+ /* Prepare for final transform: */
+ MEMSET_BZERO(sha->buffer, SHA512_SHORT_BLOCK_LENGTH);
+
+ /* Begin padding with a 1 bit: */
+ *sha->buffer = 0x80;
+ }
+ /* Store the length of input data (in bits): */
+ MEMCPY_BCOPY(&sha->buffer[SHA512_SHORT_BLOCK_LENGTH], &sha->bitcount[0], 16);
+
+ /* Final transform: */
+ SHA512_Transform(sha, (sha2_word64*)sha->buffer);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ {
+ /* Convert TO host byte order */
+ sha2_word64* d = (sha2_word64*)sha->digest;
+ int j;
+ for (j = 0; j < 8; j++) {
+ REVERSE64(sha->state[j],sha->state[j]);
+ *d++ = sha->state[j];
+ }
+ }
+#else
+ MEMCPY_BCOPY(sha->digest, sha->state, SHA512_DIGEST_LENGTH);
+#endif
+
+ /* accumulate the digests */
+ for (i = 0; i < SHA512_DIGEST_LENGTH; i++)
+ sha->digest_sum[i] ^= sha->digest[i];
+
+ /* Clean up state data: */
+ MEMSET_BZERO(&sha->state, sizeof(*sha) - offsetof(Sha512_t, state));
+ usedspace = 0;
+
+ return 0;
+}
+
+static int
+sha512_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
+{
+ register Sha512_t* sha = (Sha512_t*)p;
+ register sha2_byte* d;
+ register sha2_byte* e;
+
+ d = (flags & SUM_TOTAL) ? sha->digest_sum : sha->digest;
+ e = d + SHA512_DIGEST_LENGTH;
+ while (d < e)
+ sfprintf(sp, "%02x", *d++);
+ return 0;
+}
+
+static int
+sha512_data(Sum_t* p, Sumdata_t* data)
+{
+ register Sha512_t* sha = (Sha512_t*)p;
+
+ data->size = SHA512_DIGEST_LENGTH;
+ data->num = 0;
+ data->buf = sha->digest;
+ return 0;
+}
+
+/*** SHA-384: *********************************************************/
+
+#define sha384_description "FIPS SHA-384 secure hash algorithm."
+#define sha384_options "\
+[+(version)?sha-384 (FIPS) 2000-01-01]\
+[+(author)?Aaron D. Gifford]\
+"
+#define sha384_match "sha384|sha-384|SHA384|SHA-384"
+#define sha384_scale 0
+#define sha384_block sha512_block
+#define sha384_done sha512_done
+
+#define sha384_padding md5_pad
+
+#define Sha384_t Sha512_t
+#define SHA384_CTX Sha384_t
+#define SHA384_DIGEST_LENGTH 48
+
+static int
+sha384_init(Sum_t* p)
+{
+ register Sha384_t* sha = (Sha384_t*)p;
+
+ MEMCPY_BCOPY(sha->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH);
+ MEMSET_BZERO(sha->buffer, SHA384_BLOCK_LENGTH);
+ sha->bitcount[0] = sha->bitcount[1] = 0;
+
+ return 0;
+}
+
+static Sum_t*
+sha384_open(const Method_t* method, const char* name)
+{
+ Sha384_t* sha;
+
+ if (sha = newof(0, Sha384_t, 1, 0))
+ {
+ sha->method = (Method_t*)method;
+ sha->name = name;
+ sha384_init((Sum_t*)sha);
+ }
+ return (Sum_t*)sha;
+}
+
+static int
+sha384_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
+{
+ register Sha384_t* sha = (Sha384_t*)p;
+ register sha2_byte* d;
+ register sha2_byte* e;
+
+ d = (flags & SUM_TOTAL) ? sha->digest_sum : sha->digest;
+ e = d + SHA384_DIGEST_LENGTH;
+ while (d < e)
+ sfprintf(sp, "%02x", *d++);
+ return 0;
+}
+
+static int
+sha384_data(Sum_t* p, Sumdata_t* data)
+{
+ register Sha384_t* sha = (Sha384_t*)p;
+
+ data->size = SHA384_DIGEST_LENGTH;
+ data->num = 0;
+ data->buf = sha->digest;
+ return 0;
+}
+
+#endif /* _typ_int64_t */
diff --git a/src/lib/libsum/sum.h b/src/lib/libsum/sum.h
new file mode 100644
index 0000000..af8ba60
--- /dev/null
+++ b/src/lib/libsum/sum.h
@@ -0,0 +1,65 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1996-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * checksum library interface
+ */
+
+#ifndef _SUM_H
+#define _SUM_H
+
+#include <ast.h>
+
+#define SUM_SIZE (1<<0) /* print size too */
+#define SUM_SCALE (1<<1) /* traditional size scale */
+#define SUM_TOTAL (1<<2) /* print totals since sumopen */
+#define SUM_LEGACY (1<<3) /* legacy field widths */
+
+#define _SUM_PUBLIC_ const char* name;
+
+typedef struct Sumdata_s
+{
+ uint32_t size;
+ uint32_t num;
+ void* buf;
+} Sumdata_t;
+
+typedef struct Sum_s
+{
+ _SUM_PUBLIC_
+#ifdef _SUM_PRIVATE_
+ _SUM_PRIVATE_
+#endif
+} Sum_t;
+
+extern Sum_t* sumopen(const char*);
+extern int suminit(Sum_t*);
+extern int sumblock(Sum_t*, const void*, size_t);
+extern int sumdone(Sum_t*);
+extern int sumdata(Sum_t*, Sumdata_t*);
+extern int sumprint(Sum_t*, Sfio_t*, int, size_t);
+extern int sumusage(Sfio_t*);
+extern int sumclose(Sum_t*);
+
+#endif
diff --git a/src/lib/libsum/sumlib.c b/src/lib/libsum/sumlib.c
new file mode 100644
index 0000000..49c4c19
--- /dev/null
+++ b/src/lib/libsum/sumlib.c
@@ -0,0 +1,376 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1996-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * man this is sum library
+ */
+
+static const char id[] = "\n@(#)$Id: sumlib (AT&T Research) 2009-09-28 $\0\n";
+
+#define _SUM_PRIVATE_ \
+ struct Method_s* method; \
+ uintmax_t total_count; \
+ uintmax_t total_size; \
+ uintmax_t size;
+
+#include <sum.h>
+#include <ctype.h>
+#include <swap.h>
+#include <hashpart.h>
+
+#define SCALE(n,m) (((n)+(m)-1)/(m))
+
+typedef struct Method_s
+{
+ const char* match;
+ const char* description;
+ const char* options;
+ Sum_t* (*open)(const struct Method_s*, const char*);
+ int (*init)(Sum_t*);
+ int (*block)(Sum_t*, const void*, size_t);
+ int (*data)(Sum_t*, Sumdata_t*);
+ int (*print)(Sum_t*, Sfio_t*, int, size_t);
+ int (*done)(Sum_t*);
+ int scale;
+} Method_t;
+
+typedef struct Map_s
+{
+ const char* match;
+ const char* description;
+ const char* map;
+} Map_t;
+
+/*
+ * 16 and 32 bit common code
+ */
+
+#define _INTEGRAL_PRIVATE_ \
+ uint32_t sum; \
+ uint32_t total_sum;
+
+typedef struct Integral_s
+{
+ _SUM_PUBLIC_
+ _SUM_PRIVATE_
+ _INTEGRAL_PRIVATE_
+} Integral_t;
+
+static Sum_t*
+long_open(const Method_t* method, const char* name)
+{
+ Integral_t* p;
+
+ if (p = newof(0, Integral_t, 1, 0))
+ {
+ p->method = (Method_t*)method;
+ p->name = name;
+ }
+ return (Sum_t*)p;
+}
+
+static int
+long_init(Sum_t* p)
+{
+ ((Integral_t*)p)->sum = 0;
+ return 0;
+}
+
+static int
+long_done(Sum_t* p)
+{
+ register Integral_t* x = (Integral_t*)p;
+
+ x->total_sum ^= (x->sum &= 0xffffffff);
+ return 0;
+}
+
+static int
+short_done(Sum_t* p)
+{
+ register Integral_t* x = (Integral_t*)p;
+
+ x->total_sum ^= (x->sum &= 0xffff);
+ return 0;
+}
+
+static int
+long_print(Sum_t* p, Sfio_t* sp, register int flags, size_t scale)
+{
+ register Integral_t* x = (Integral_t*)p;
+ register uint32_t c;
+ register uintmax_t z;
+ register size_t n;
+
+ c = (flags & SUM_TOTAL) ? x->total_sum : x->sum;
+ sfprintf(sp, "%.*I*u", (flags & SUM_LEGACY) ? 5 : 1, sizeof(c), c);
+ if (flags & SUM_SIZE)
+ {
+ z = (flags & SUM_TOTAL) ? x->total_size : x->size;
+ if ((flags & SUM_SCALE) && ((n = scale) || (n = x->method->scale)))
+ z = SCALE(z, n);
+ sfprintf(sp, " %*I*u", (flags & SUM_LEGACY) ? 6 : 0, sizeof(z), z);
+ }
+ if (flags & SUM_TOTAL)
+ sfprintf(sp, " %*I*u", (flags & SUM_LEGACY) ? 6 : 0, sizeof(x->total_count), x->total_count);
+ return 0;
+}
+
+static int
+long_data(Sum_t* p, Sumdata_t* data)
+{
+ register Integral_t* x = (Integral_t*)p;
+
+ data->size = sizeof(data->num);
+ data->num = x->sum;
+ data->buf = 0;
+ return 0;
+}
+
+#include "FEATURE/sum"
+
+#include "sum-att.c"
+#include "sum-ast4.c"
+#include "sum-bsd.c"
+#include "sum-crc.c"
+#include "sum-prng.c"
+
+#if _LIB_md && _lib_MD5Init && _hdr_md5 && _lib_SHA2Init && _hdr_sha2
+
+#include "sum-lmd.c"
+
+#else
+
+#include "sum-md5.c"
+#include "sum-sha1.c"
+#include "sum-sha2.c"
+
+#endif
+
+/*
+ * now the library interface
+ */
+
+#undef METHOD /* solaris <sys/localedef.h>! */
+#define METHOD(x) x##_match,x##_description,x##_options,x##_open,x##_init,x##_block,x##_data,x##_print,x##_done,x##_scale
+
+static const Method_t methods[] =
+{
+ METHOD(att),
+ METHOD(ast4),
+ METHOD(bsd),
+ METHOD(crc),
+ METHOD(prng),
+#ifdef md4_description
+ METHOD(md4),
+#endif
+#ifdef md5_description
+ METHOD(md5),
+#endif
+#ifdef sha1_description
+ METHOD(sha1),
+#endif
+#ifdef sha256_description
+ METHOD(sha256),
+#endif
+#ifdef sha384_description
+ METHOD(sha384),
+#endif
+#ifdef sha512_description
+ METHOD(sha512),
+#endif
+};
+
+static const Map_t maps[] =
+{
+ {
+ "posix|cksum|std|standard",
+ "The posix 1003.2-1992 32 bit crc checksum. This is the"
+ " default \bcksum\b(1) method.",
+ "crc-0x04c11db7-rotate-done-size"
+ },
+ {
+ "zip",
+ "The \bzip\b(1) crc.",
+ "crc-0xedb88320-init-done"
+ },
+ {
+ "fddi",
+ "The FDDI crc.",
+ "crc-0xedb88320-size=0xcc55cc55"
+ },
+ {
+ "fnv|fnv1",
+ "The Fowler-Noll-Vo 32 bit PRNG hash with non-zero"
+ " initializer (FNV-1).",
+ "prng-0x01000193-init=0x811c9dc5"
+ },
+ {
+ "ast|strsum",
+ "The \bast\b \bstrsum\b(3) PRNG hash.",
+ "prng-0x63c63cd9-add=0x9c39c33d"
+ },
+};
+
+/*
+ * simple alternation prefix match
+ */
+
+static int
+match(register const char* s, register const char* p)
+{
+ register const char* b = s;
+
+ for (;;)
+ {
+ do
+ {
+ if (*p == '|' || *p == 0)
+ return 1;
+ } while (*s++ == *p++);
+ for (;;)
+ {
+ switch (*p++)
+ {
+ case 0:
+ return 0;
+ case '|':
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ s = b;
+ }
+ return 0;
+}
+
+/*
+ * open sum method name
+ */
+
+Sum_t*
+sumopen(register const char* name)
+{
+ register int n;
+
+ if (!name || !name[0] || name[0] == '-' && !name[1])
+ name = "default";
+ for (n = 0; n < elementsof(maps); n++)
+ if (match(name, maps[n].match))
+ {
+ name = maps[n].map;
+ break;
+ }
+ for (n = 0; n < elementsof(methods); n++)
+ if (match(name, methods[n].match))
+ return (*methods[n].open)(&methods[n], name);
+ return 0;
+}
+
+/*
+ * initialize for a new run of blocks
+ */
+
+int
+suminit(Sum_t* p)
+{
+ p->size = 0;
+ return (*p->method->init)(p);
+}
+
+/*
+ * compute the running sum on buf
+ */
+
+int
+sumblock(Sum_t* p, const void* buf, size_t siz)
+{
+ p->size += siz;
+ return (*p->method->block)(p, buf, siz);
+}
+
+/*
+ * done with this run of blocks
+ */
+
+int
+sumdone(Sum_t* p)
+{
+ p->total_count++;
+ p->total_size += p->size;
+ return (*p->method->done)(p);
+}
+
+/*
+ * print the sum [size] on sp
+ */
+
+int
+sumprint(Sum_t* p, Sfio_t* sp, int flags, size_t scale)
+{
+ return (*p->method->print)(p, sp, flags, scale);
+}
+
+/*
+ * return the current sum (internal) data
+ */
+
+int
+sumdata(Sum_t* p, Sumdata_t* d)
+{
+ return (*p->method->data)(p, d);
+}
+
+/*
+ * close an open sum handle
+ */
+
+int
+sumclose(Sum_t* p)
+{
+ free(p);
+ return 0;
+}
+
+/*
+ * print the checksum method optget(3) usage on sp and return the length
+ */
+
+int
+sumusage(Sfio_t* sp)
+{
+ register int i;
+ register int n;
+
+ for (i = n = 0; i < elementsof(methods); i++)
+ {
+ n += sfprintf(sp, "[+%s?%s]", methods[i].match, methods[i].description);
+ if (methods[i].options)
+ n += sfprintf(sp, "{\n%s\n}", methods[i].options);
+ }
+ for (i = 0; i < elementsof(maps); i++)
+ n += sfprintf(sp, "[+%s?%s Shorthand for \b%s\b.]", maps[i].match, maps[i].description, maps[i].map);
+ return n;
+}